Merge remote-tracking branch 'origin/develop-3.10' into develop-3.10-next
author黄涛 <huangtao@rock-chips.com>
Mon, 4 Aug 2014 08:52:07 +0000 (16:52 +0800)
committer黄涛 <huangtao@rock-chips.com>
Mon, 4 Aug 2014 08:52:07 +0000 (16:52 +0800)
Conflicts:
drivers/staging/android/ion/ion.c
include/linux/rockchip/sysmmu.h

381 files changed:
Documentation/devicetree/bindings/sound/rockchip-audio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/rockchip-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/rockchip-spdif.txt [new file with mode: 0644]
arch/arm/boot/dts/lcd-box.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk3036-clocks.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk3036-fpga.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3036-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/rk3036-rk88.dts [new file with mode: 0755]
arch/arm/boot/dts/rk3036-sdk.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3036.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk3126-fpga.dts [new file with mode: 0755]
arch/arm/boot/dts/rk3126-sdk.dts [new file with mode: 0755]
arch/arm/boot/dts/rk3128-box.dts [new file with mode: 0755]
arch/arm/boot/dts/rk3128-sdk.dts [new file with mode: 0755]
arch/arm/boot/dts/rk312x-clocks.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk312x-pinctrl.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk312x-sdk.dtsi [new file with mode: 0755]
arch/arm/boot/dts/rk312x.dtsi [new file with mode: 0755]
arch/arm/configs/rk3036_defconfig [new file with mode: 0644]
arch/arm/configs/rockchip_defconfig
arch/arm/include/debug/rockchip.S
arch/arm/kernel/pie.lds.S
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/cpu_axi.h
arch/arm/mach-rockchip/platsmp.c
arch/arm/mach-rockchip/rk3036.c [new file with mode: 0755]
arch/arm/mach-rockchip/rk312x.c [new file with mode: 0755]
arch/arm/mach-rockchip/vcodec_service.c
block/partitions/Kconfig
block/partitions/Makefile
block/partitions/check.c
block/partitions/mtdpart.c [deleted file]
block/partitions/mtdpart.h [deleted file]
block/partitions/rk.c [new file with mode: 0755]
block/partitions/rk.h [new file with mode: 0755]
drivers/clk/rockchip/clk-pll.c [changed mode: 0644->0755]
drivers/clk/rockchip/clk-pll.h [changed mode: 0644->0755]
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Makefile
drivers/gpu/arm/Kbuild
drivers/gpu/arm/mali400/Kbuild [new file with mode: 0644]
drivers/gpu/arm/mali400/include/ump/ump.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_debug.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_osu.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_platform.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h [new file with mode: 0755]
drivers/gpu/arm/mali400/include/ump/ump_uk_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/Kbuild [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/Kconfig [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/__malidrv_build_info.c [new file with mode: 0644]
drivers/gpu/arm/mali400/mali/common/mali_broadcast.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_broadcast.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_dlbu.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_dlbu.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_dma.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_dma.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_gp.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_gp.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_gp_job.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_gp_job.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_group.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_group.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_hw_core.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_hw_core.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_common.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_core.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_core.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_descriptor_mapping.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_descriptor_mapping.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_utilization.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_utilization.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_kernel_vsync.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_l2_cache.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_l2_cache.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_mem_validation.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_mem_validation.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_mmu.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_mmu.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_mmu_page_directory.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_mmu_page_directory.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_osk.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_osk_bitops.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_osk_list.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_osk_mali.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_osk_profiling.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_osk_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pm.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pm.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pm_domain.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pm_domain.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pmu.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pmu.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pp.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pp.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pp_job.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pp_job.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_scheduler.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_scheduler.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_scheduler_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_session.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_session.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_soft_job.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_soft_job.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_spinlock_reentrant.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_spinlock_reentrant.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_timeline.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_timeline.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_timeline_fence_wait.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_timeline_fence_wait.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_ukk.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_user_settings_db.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/common/mali_user_settings_db.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_counters.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_ioctl.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_profiling_events.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_profiling_gator_api.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_uk_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/license/gpl/mali_kernel_license.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_device_pause_resume.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_linux_trace.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_block_alloc.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_block_alloc.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_dma_buf.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_dma_buf.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_external.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_memory_ump.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_atomics.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_irq.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_locks.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_locks.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_low_level_mem.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_mali.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_math.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_memory.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_misc.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_notification.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_pm.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_profiling.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_specific.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_time.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_timers.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_wait_queue.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_osk_wq.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_pmu_power_up_down.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_profiling_events.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_profiling_gator_api.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_profiling_internal.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_profiling_internal.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_sync.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_sync.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_uk_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_core.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_gp.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_mem.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_pp.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_profiling.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_soft_job.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_timeline.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_vsync.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/linux/mali_ukk_wrappers.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/platform/arm/arm.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/platform/rk30/mali_platform.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/platform/rk30/mali_platform.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/platform/rk30/rk3066.c [new file with mode: 0644]
drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/regs/mali_200_regs.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/regs/mali_gp_regs.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/timestamp-arm11-cc/mali_timestamp.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/timestamp-arm11-cc/mali_timestamp.h [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/timestamp-default/mali_timestamp.c [new file with mode: 0755]
drivers/gpu/arm/mali400/mali/timestamp-default/mali_timestamp.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/Kbuild [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/Kconfig [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/Makefile.common [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/arch [new symlink]
drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_api.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_common.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_common.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_descriptor_mapping.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_descriptor_mapping.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_memory_backend.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_ref_drv.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_kernel_types.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_osk.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/common/ump_ukk.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/license/gpl/ump_kernel_license.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_ioctl.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_kernel_linux.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_kernel_linux.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_dedicated.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_dedicated.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_os.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_os.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_memory_backend.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_osk_atomics.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_osk_low_level_mem.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_osk_misc.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_ukk_ref_wrappers.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_ukk_ref_wrappers.h [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_ukk_wrappers.c [new file with mode: 0755]
drivers/gpu/arm/mali400/ump/linux/ump_ukk_wrappers.h [new file with mode: 0755]
drivers/iio/adc/rockchip_adc.c
drivers/input/Kconfig [changed mode: 0644->0755]
drivers/input/Makefile [changed mode: 0644->0755]
drivers/input/keyboard/Kconfig
drivers/input/keyboard/rk_keys.c
drivers/input/remotectl/Kconfig
drivers/input/remotectl/Makefile
drivers/input/remotectl/rkxx_remotectl.c [deleted file]
drivers/input/remotectl/rockchip_pwm_remotectl.c [new file with mode: 0755]
drivers/input/remotectl/rockchip_pwm_remotectl.h [new file with mode: 0755]
drivers/input/touchscreen/vtl_ts/LX20JS06_A1_CT363_V03_5198_121015.dat [new file with mode: 0755]
drivers/input/touchscreen/vtl_ts/chip.c
drivers/iommu/rockchip-iommu.c
drivers/iommu/rockchip-iovmm.c
drivers/mmc/host/Kconfig
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc-rockchip.c
drivers/mmc/host/rk_sdmmc.c
drivers/net/ethernet/rockchip/vmac/rk29_vmac.c
drivers/net/ethernet/rockchip/vmac/rk29_vmac.h
drivers/net/ethernet/rockchip/vmac/rk29_vmac_phy.c
drivers/net/wireless/Makefile [changed mode: 0644->0755]
drivers/net/wireless/rockchip_wlan/esp8089/Kconfig
drivers/net/wireless/rockchip_wlan/esp8089/Makefile [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/eagle_fw1.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/eagle_fw2.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_android.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_android.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_cfg80211.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_conf.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_config.mk [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_ctrl.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_ctrl.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_debug.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_debug.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_ext.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_ext.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_init_data.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_io.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_mac80211.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_main.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_os.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_path.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_pm.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_pub.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_sif.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_sip.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_sip.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_utils.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_utils.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_version.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_wl.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/esp_wmac.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/init_data.conf [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/rk2.env [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/sdio_sif_esp.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/sdio_stub.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/sip2_common.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/slc_host_register.h [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/spi_sif_esp.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/testmode.c [new file with mode: 0755]
drivers/net/wireless/rockchip_wlan/esp8089/testmode.h [new file with mode: 0755]
drivers/pinctrl/pinctrl-rockchip.c
drivers/power/rk818_battery.c
drivers/rtc/rtc-HYM8563.c
drivers/staging/android/ion/ion.c
drivers/usb/dwc_otg_310/Makefile
drivers/usb/dwc_otg_310/dwc_otg_driver.c
drivers/usb/dwc_otg_310/usbdev_bc.c
drivers/usb/dwc_otg_310/usbdev_grf_regs.h [changed mode: 0644->0755]
drivers/usb/dwc_otg_310/usbdev_rk.h
drivers/usb/dwc_otg_310/usbdev_rk3036.c [new file with mode: 0755]
drivers/usb/dwc_otg_310/usbdev_rk3126.c [new file with mode: 0755]
drivers/video/Kconfig
drivers/video/rockchip/Makefile
drivers/video/rockchip/display-sys.c
drivers/video/rockchip/hdmi/chips/Kconfig
drivers/video/rockchip/hdmi/chips/Makefile
drivers/video/rockchip/hdmi/chips/rk3036/Kconfig [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/Makefile [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdcp.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_cec.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_cec.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c [changed mode: 0644->0755]
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.c
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi_hw.h
drivers/video/rockchip/hdmi/rk_hdmi.h
drivers/video/rockchip/hdmi/rk_hdmi_edid.c
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c
drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
drivers/video/rockchip/hdmi/rk_hdmi_task.c
drivers/video/rockchip/lcdc/Kconfig
drivers/video/rockchip/lcdc/Makefile
drivers/video/rockchip/lcdc/rk3036_lcdc.c [new file with mode: 0755]
drivers/video/rockchip/lcdc/rk3036_lcdc.h [new file with mode: 0644]
drivers/video/rockchip/lcdc/rk312x_lcdc.c [new file with mode: 0755]
drivers/video/rockchip/lcdc/rk312x_lcdc.h [new file with mode: 0755]
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rkfb_sysfs.c
drivers/video/rockchip/transmitter/Kconfig
drivers/video/rockchip/transmitter/Makefile
drivers/video/rockchip/transmitter/rk31xx_lvds.c [new file with mode: 0755]
drivers/video/rockchip/transmitter/rk31xx_lvds.h [new file with mode: 0755]
drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
drivers/video/rockchip/tve/Kconfig
drivers/video/rockchip/tve/Makefile
drivers/video/rockchip/tve/rk3036/Kconfig [new file with mode: 0644]
drivers/video/rockchip/tve/rk3036/Makefile [new file with mode: 0644]
drivers/video/rockchip/tve/rk3036/rk3036_tve.c [new file with mode: 0644]
drivers/video/rockchip/tve/rk3036/rk3036_tve.h [new file with mode: 0644]
drivers/video/rockchip/tve/rk610/Kconfig [new file with mode: 0644]
drivers/video/rockchip/tve/rk610/Makefile [new file with mode: 0644]
drivers/video/rockchip/tve/rk610/rk610_tv.c [new file with mode: 0644]
drivers/video/rockchip/tve/rk610/rk610_tv.h [new file with mode: 0644]
drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c [new file with mode: 0644]
drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c [new file with mode: 0644]
drivers/video/rockchip/tve/rk610_tv.c [deleted file]
drivers/video/rockchip/tve/rk610_tv.h [deleted file]
drivers/video/rockchip/tve/rk610_tv_cvbs.c [deleted file]
drivers/video/rockchip/tve/rk610_tv_ypbpr.c [deleted file]
include/dt-bindings/clock/rockchip,rk3036.h [new file with mode: 0644]
include/dt-bindings/clock/rockchip,rk312x.h [new file with mode: 0755]
include/dt-bindings/clock/rockchip.h
include/dt-bindings/pinctrl/rockchip-rk3036.h [new file with mode: 0644]
include/dt-bindings/pinctrl/rockchip-rk312x.h [new file with mode: 0755]
include/dt-bindings/pinctrl/rockchip.h
include/linux/mmc/rk_mmc.h
include/linux/rk_fb.h
include/linux/rk_screen.h
include/linux/rockchip/common.h
include/linux/rockchip/cpu.h
include/linux/rockchip/cru.h
include/linux/rockchip/grf.h
include/linux/rockchip/iomap.h
include/linux/rockchip/sysmmu.h
net/rfkill/rfkill-wlan.c
pie/Makefile
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile [changed mode: 0755->0644]
sound/soc/codecs/hdmi_spdif.c
sound/soc/codecs/rk3036_codec.c [new file with mode: 0644]
sound/soc/codecs/rk3036_codec.h [new file with mode: 0644]
sound/soc/rockchip/Kconfig [changed mode: 0755->0644]
sound/soc/rockchip/Makefile [changed mode: 0755->0644]
sound/soc/rockchip/rk30_i2s.c
sound/soc/rockchip/rk_rk3036.c [new file with mode: 0644]
sound/soc/rockchip/rk_spdif.c [changed mode: 0755->0644]

diff --git a/Documentation/devicetree/bindings/sound/rockchip-audio.txt b/Documentation/devicetree/bindings/sound/rockchip-audio.txt
new file mode 100644 (file)
index 0000000..a4d728a
--- /dev/null
@@ -0,0 +1,36 @@
+* Rockchip Audio controller
+
+Required SoC Specific Properties:
+
+- compatible : "rk3036-audio"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: must include clock specifiers corresponding to entries in the
+  clock-names property.
+- clocks-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "rockchip-i2s" and "rk3036-codec".
+- interrupts: interrupt number to the cpu.
+- dmas: list of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+- pinctrl-names: must contain a "default" entry.
+- pinctrl-0: pin control group to be used for this controller.
+- pinctrl-1: pin control group to be used for gpio.
+
+Example:
+
+rockchip-audio {
+       compatible = "rk3036-audio";
+       dais {
+               dai0 {
+                       audio-codec = <&codec>;
+                       i2s-controller = <&i2s>;
+                       format = "i2s";
+                       //continuous-clock;
+                       //bitclock-inversion;
+                       //frame-inversion;
+                       //bitclock-master;
+                       //frame-master;
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
new file mode 100644 (file)
index 0000000..6915841
--- /dev/null
@@ -0,0 +1,35 @@
+* Rockchip I2S controller
+
+Required SoC Specific Properties:
+
+- compatible : "rockchip-i2s"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- i2s-id: i2s controller id,
+- clocks: must include clock specifiers corresponding to entries in the
+  clock-names property.
+- clocks-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "i2s_clk" and "i2s_hclk".
+- interrupts: interrupt number to the cpu.
+- dmas: list of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+- pinctrl-names: must contain a "default" entry.
+- pinctrl-0: pin control group to be used for this controller.
+- pinctrl-1: pin control group to be used for gpio.
+
+Example:
+
+i2s0: i2s@10220000 {
+       compatible = "rockchip-i2s";
+       reg = <0x10220000 0x1000>;
+       i2s-id = <0>;
+       clocks = <&clk_i2s_2ch>, <&clk_i2s_2ch_out>, <&clk_gates7 2>;
+       clock-names = "i2s_clk", "i2s_mclk", "i2s_hclk";
+       interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+       dmas = <&pdma 0>, <&pdma 1>;
+       dma-names = "tx", "rx";
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&i2s0_mclk &i2s0_sclk &i2s0_lrckrx &i2s0_lrcktx &i2s0_sdi &i2s0_sdo>;
+       pinctrl-1 = <&i2s0_gpio>;
+};
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt
new file mode 100644 (file)
index 0000000..cef4f5e
--- /dev/null
@@ -0,0 +1,32 @@
+* Rockchip SPDIF controller
+
+Required SoC Specific Properties:
+
+- compatible : "rockchip-spdif"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: must include clock specifiers corresponding to entries in the
+  clock-names property.
+- clocks-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "spdif_mclk" and "spdif_hclk".
+- interrupts: interrupt number to the cpu.
+- dmas: list of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+- pinctrl-names: must contain a "default" entry.
+- pinctrl-0: pin control group to be used for this controller.
+- pinctrl-1: pin control group to be used for gpio.
+
+Example:
+
+spdif: spdif@10204000 {
+       compatible = "rockchip-spdif";
+       reg = <0x10204000 0x1000>;
+       clocks = <&clk_spdif>, <&clk_gates10 8>;
+       clock-names = "spdif_mclk", "spdif_hclk";
+       interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+       dmas = <&pdma 13>;
+       dma-names = "tx";
+       pinctrl-names = "default";
+       pinctrl-0 = <&spdif_tx>;
+};
diff --git a/arch/arm/boot/dts/lcd-box.dtsi b/arch/arm/boot/dts/lcd-box.dtsi
new file mode 100755 (executable)
index 0000000..8d7710b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * RockChip. LCD_BOX
+ *
+ */
+
+/ {
+               disp_power_ctr: power_ctr {
+                     /*                        rockchip,debug = <0>;
+                        lcd_en:lcd_en {
+                                rockchip,power_type = <GPIO>;
+                                gpios = <&gpio0 GPIO_B0 GPIO_ACTIVE_HIGH>;
+                                rockchip,delay = <10>;
+                        };
+
+                        bl_en:bl_en {
+                                rockchip,power_type = <GPIO>;
+                                gpios = <&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
+                                rockchip,delay = <10>;
+                        };
+
+                        bl_ctr:bl_ctr {
+                                rockchip,power_type = <GPIO>;
+                                gpios = <&gpio3 GPIO_D6 GPIO_ACTIVE_HIGH>;
+                                rockchip,delay = <10>;
+                        };
+
+                        lcd_rst:lcd_rst {
+                                rockchip,power_type = <REGULATOR>;
+                                rockchip,delay = <5>;
+                        };*/
+
+                };
+
+               disp_timings: display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               screen-type = <SCREEN_RGB>;
+                               out-face    = <OUT_P888>;
+                               clock-frequency = <74250000>;
+                               hactive = <1280>;
+                               vactive = <720>;
+                               hback-porch = <220>;
+                               hfront-porch = <110>;
+                               vback-porch = <20>;
+                               vfront-porch = <5>;
+                               hsync-len = <40>;
+                               vsync-len = <5>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                               swap-rb = <0>;
+                               swap-rg = <0>;
+                               swap-gb = <0>;
+                       };
+                       timing1: timing1 {
+                               screen-type = <SCREEN_RGB>;
+                               out-face    = <OUT_P888>;
+                               clock-frequency = <148500000>;
+                               hactive = <1920>;
+                               vactive = <1080>;
+                               hback-porch = <148>;
+                               hfront-porch = <88>;
+                               vback-porch = <36>;
+                               vfront-porch = <4>;
+                               hsync-len = <44>;
+                               vsync-len = <5>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                               swap-rb = <0>;
+                               swap-rg = <0>;
+                               swap-gb = <0>;
+                       };
+                       timing2: timing2 {
+                               screen-type = <SCREEN_RGB>;
+                               out-face    = <OUT_P888>;
+                               clock-frequency = <297000000>;
+                               hactive = <3840>;
+                               vactive = <2160>;
+                               hback-porch = <296>;
+                               hfront-porch = <176>;
+                               vback-porch = <72>;
+                               vfront-porch = <8>;
+                               hsync-len = <88>;
+                               vsync-len = <10>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               de-active = <0>;
+                               pixelclk-active = <0>;
+                               swap-rb = <0>;
+                               swap-rg = <0>;
+                               swap-gb = <0>;
+                       };
+               };
+};
diff --git a/arch/arm/boot/dts/rk3036-clocks.dtsi b/arch/arm/boot/dts/rk3036-clocks.dtsi
new file mode 100755 (executable)
index 0000000..81691f1
--- /dev/null
@@ -0,0 +1,1521 @@
+/*
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <dt-bindings/clock/rockchip,rk3036.h>
+
+/{
+
+       clocks {
+               compatible = "rockchip,rk-clocks";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x0  0x20000000  0x1f0>;
+
+               fixed_rate_cons {
+                       compatible = "rockchip,rk-fixed-rate-cons";
+
+                       xin24m: xin24m {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "xin24m";
+                               clock-frequency = <24000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       xin12m: xin12m {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clocks = <&xin24m>;
+                               clock-output-names = "xin12m";
+                               clock-frequency = <12000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       rmii_clkin: rmii_clkin {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "rmii_clkin";
+                               clock-frequency = <50000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       usb_480m: usb_480m {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "usb_480m";
+                               clock-frequency = <480000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       i2s_clkin: i2s_clkin {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "i2s_clkin";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       jtag_tck: jtag_tck {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "jtag_tck";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       dummy: dummy {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "dummy";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       dummy_cpll: dummy_cpll {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "dummy_cpll";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+               };
+
+               fixed_factor_cons {
+                       compatible = "rockchip,rk-fixed-factor-cons";
+/*
+                       otgphy0_12m: otgphy0_12m {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&clk_gates1 5>;
+                               clock-output-names = "otgphy0_12m";
+                               clock-div = <1>;
+                               clock-mult = <20>;
+                               #clock-cells = <0>;
+                       };
+*/
+                       hclk_vcodec: hclk_vcodec {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&aclk_vcodec_pre>;
+                               clock-output-names = "hclk_vcodec";
+                               clock-div = <4>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+                       io_mac_mdclkout: io_mac_mdclkout {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&aclk_peri_pre>;
+                               clock-output-names = "io_mac_mdclkout";
+                               clock-div = <2>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+               };
+
+               clock_regs {
+                       compatible = "rockchip,rk-clock-regs";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x0000 0x01f0>;
+                       ranges;
+
+                       /* PLL control regs */
+                       pll_cons {
+                               compatible = "rockchip,rk-pll-cons";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges ;
+
+                               clk_apll: pll-clk@0000 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0000 0x10>;
+                                       mode-reg = <0x0040 0>;
+                                       status-reg = <0x0004 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_apll";
+                                       rockchip,pll-type = <CLK_PLL_3036_APLL>;
+                                       #clock-cells = <0>;
+                               };
+
+                               clk_dpll: pll-clk@0010 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0010 0x10>;
+                                       mode-reg = <0x0040 4>;
+                                       status-reg = <0x0014 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_dpll";
+                                       rockchip,pll-type = <CLK_PLL_3036PLUS_AUTO>;
+                                       #clock-cells = <0>;
+                               };
+
+                               clk_gpll: pll-clk@0030 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0030 0x10>;
+                                       mode-reg = <0x0040 12>;
+                                       status-reg = <0x0034 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_gpll";
+                                       rockchip,pll-type = <CLK_PLL_3036PLUS_AUTO>;
+                                       #clock-cells = <0>;
+                                       #clock-init-cells = <1>;
+                               };
+
+                       };
+
+                       /* Select control regs */
+                       clk_sel_cons {
+                               compatible = "rockchip,rk-sel-cons";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges;
+
+                               clk_sel_con0: sel-con@0044 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0044 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_core_div: clk_core_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_core>;
+                                               clock-output-names = "clk_core";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_CORE>;
+                                               rockchip,flags = <(CLK_GET_RATE_NOCACHE |
+                                                                       CLK_SET_RATE_NO_REPARENT)>;
+                                       };
+
+                                       /* reg[6:5]: reserved */
+
+                                       clk_core: clk_core_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <7 1>;
+                                               clocks = <&clk_apll>, <&clk_gates0 6>;
+                                               clock-output-names = "clk_core";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       aclk_cpu_pre_div: aclk_cpu_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&aclk_cpu_pre>;
+                                               clock-output-names = "aclk_cpu_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       aclk_cpu_pre: aclk_cpu_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>,<&clk_gpll>;
+                                               clock-output-names = "aclk_cpu_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con1: sel-con@0048 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0048 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       pclk_dbg_div:  pclk_dbg_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 4>;
+                                               clocks = <&clk_core>;
+                                               clock-output-names = "pclk_dbg";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_CORE_CHILD>;
+                                       };
+
+                                       aclk_core_pre: aclk_core_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <4 3>;
+                                               clocks = <&clk_core>;
+                                               clock-output-names = "aclk_core_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_CORE_CHILD>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       hclk_cpu_pre: hclk_cpu_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&aclk_cpu_pre>;
+                                               clock-output-names = "hclk_cpu_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       pclk_cpu_pre: pclk_cpu_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <12 3>;
+                                               clocks = <&aclk_cpu_pre>;
+                                               clock-output-names = "pclk_cpu_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15]: reserved */
+                               };
+
+                               clk_sel_con2: sel-con@004c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x004c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       /* reg[3:0]: reserved */
+
+                                       clk_timer0: clk_timer0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <4 1>;
+                                               clocks = <&xin24m>, <&aclk_peri_pre>;
+                                               clock-output-names = "clk_timer0";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_timer1: clk_timer1_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <5 1>;
+                                               clocks = <&xin24m>, <&aclk_peri_pre>;
+                                               clock-output-names = "clk_timer1";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_timer2: clk_timer2_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <6 1>;
+                                               clocks = <&xin24m>, <&aclk_peri_pre>;
+                                               clock-output-names = "clk_timer2";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_timer3: clk_timer3_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <7 1>;
+                                               clocks = <&xin24m>, <&aclk_peri_pre>;
+                                               clock-output-names = "clk_timer3";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15:8]: reserved */
+                               };
+
+                               clk_sel_con3: sel-con@0050 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0050 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_i2s_pll_div: clk_i2s_pll_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_i2s_pll>;
+                                               clock-output-names = "clk_i2s_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_i2s: clk_i2s_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_i2s_pll_div>, <&i2s_frac>, <&i2s_clkin>, <&xin12m>;
+                                               clock-output-names = "clk_i2s";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       clk_i2s_out: i2s_outclk_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <12 1>;
+                                               clocks = <&xin12m>, <&clk_i2s>;
+                                               clock-output-names = "i2s_clkout";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       clk_i2s_pll: i2s_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "clk_i2s_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con5: sel-con@0058 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0058 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       spdif_div: spdif_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_spdif_pll>;
+                                               clock-output-names = "clk_spdif_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_spdif: spdif_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&spdif_div>, <&spdif_frac>, <&xin12m>;
+                                               clock-output-names = "clk_spdif";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       clk_spdif_pll: spdif_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <10 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "clk_spdif_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15:12]: reserved */
+                               };
+
+                               clk_sel_con7: sel-con@0060 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0060 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       i2s_frac: i2s_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_i2s_pll>;
+                                               clock-output-names = "i2s_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con9: sel-con@0068 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0068 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       spdif_frac: spdif_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&spdif_div>;
+                                               clock-output-names = "spdif_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con10: sel-con@006c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x006c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       aclk_peri_pre_div: aclk_peri_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&aclk_peri_pre>;
+                                               clock-output-names = "aclk_peri_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7:5]: reserved */
+
+                                       hclk_peri_pre: hclk_peri_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&aclk_peri_pre>;
+                                               clock-output-names = "hclk_peri_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_USER_DEFINE>;
+                                               rockchip,div-relations =
+                                                               <0x0 1
+                                                                0x1 2
+                                                                0x2 4>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       pclk_peri_pre: pclk_peri_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <12 2>;
+                                               clocks = <&aclk_peri_pre>;
+                                               clock-output-names = "pclk_peri_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_USER_DEFINE>;
+                                               rockchip,div-relations =
+                                                               <0x0 1
+                                                                0x1 2
+                                                                0x2 4
+                                                                0x3 8>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       aclk_peri_pre: aclk_peri_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "aclk_peri_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+                               };
+
+                               clk_sel_con11: sel-con@0070 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0070 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_sdmmc0_div: clk_sdmmc0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 6>;
+                                               clocks = <&clk_sdmmc0>;
+                                               clock-output-names = "clk_sdmmc0";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_sdio_div: clk_sdio_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 7>;
+                                               clocks = <&clk_sdio>;
+                                               clock-output-names = "clk_sdio";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       /* reg[15]: reserved */
+
+                               };
+
+                               clk_sel_con12: sel-con@0074 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0074 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_emmc_div: clk_emmc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_emmc>;
+                                               clock-output-names = "clk_emmc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_sdmmc0: clk_sdmmc0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>, <&xin24m>;
+                                               clock-output-names = "clk_sdmmc0";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       clk_sdio: clk_sdio_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <10 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>, <&xin24m>;
+                                               clock-output-names = "clk_sdio";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       clk_emmc: clk_emmc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <12 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>, <&xin24m>;
+                                               clock-output-names = "clk_emmc";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[15:14]: reserved */
+                               };
+
+                               clk_sel_con13: sel-con@0078 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0078 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_uart0_div: clk_uart0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_uart_pll>;
+                                               clock-output-names = "clk_uart0_div";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_uart0: clk_uart0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_uart0_div>, <&uart0_frac>, <&xin24m>;
+                                               clock-output-names = "clk_uart0";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       clk_uart_pll: clk_uart_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <10 2>;
+                                               clocks = <&clk_apll>,<&clk_dpll>, <&clk_gpll>, <&usb_480m>;
+                                               clock-output-names = "clk_uart_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15:12]: reserved */
+
+                               };
+
+                               clk_sel_con14: sel-con@007c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x007c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_uart1_div: clk_uart1_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_uart_pll>;
+                                               clock-output-names = "clk_uart1_div";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_uart1: clk_uart1_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_uart1_div>, <&uart1_frac>, <&xin24m>;
+                                               clock-output-names = "clk_uart1";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+                               };
+
+                               clk_sel_con15: sel-con@0080 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0080 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_uart2_div: clk_uart2_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_uart_pll>;
+                                               clock-output-names = "clk_uart2_div";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_uart2: clk_uart2_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_uart2_div>, <&uart2_frac>, <&xin24m>;
+                                               clock-output-names = "clk_uart2";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+                               };
+
+                               clk_sel_con16: sel-con@0084 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0084 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_sfc: clk_sfc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>, <&xin24m>;
+                                               clock-output-names = "clk_sfc";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       clk_sfc_div: clk_sfc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <2 5>;
+                                               clocks = <&clk_sfc>;
+                                               clock-output-names = "clk_sfc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_nandc: clk_nandc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "clk_nandc";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       clk_nandc_div: clk_nandc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <10 5>;
+                                               clocks = <&clk_nandc>;
+                                               clock-output-names = "clk_nandc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };
+
+                                       /* reg[31:15]: reserved */
+                               };
+
+                               clk_sel_con17: sel-con@0088 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0088 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       uart0_frac: uart0_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_uart0_div>;
+                                               clock-output-names = "uart0_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con18: sel-con@008c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x008c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       uart1_frac: uart1_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_uart1_div>;
+                                               clock-output-names = "uart1_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con19: sel-con@0090 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0090 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       uart2_frac: uart2_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_uart2_div>;
+                                               clock-output-names = "uart2_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+
+                               };
+
+                               clk_sel_con20: sel-con@0094 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0094 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_hevc_core: clk_hevc_core_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "clk_hevc_core";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_hevc_core_div: clk_hevc_core_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <2 5>;
+                                               clocks = <&clk_hevc_core>;
+                                               clock-output-names = "clk_hevc_core";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[31:7]: reserved */
+
+                               };
+
+                               clk_sel_con21: sel-con@0098 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0098 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_mac_pll: clk_mac_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "clk_mac_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[2]: reserved */
+
+                                       clk_mac_ref: clk_mac_ref_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <3 1>;
+                                               clocks = <&clk_mac_pll_div>, <&rmii_clkin>;
+                                               clock-output-names = "clk_mac_ref";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MAC_REF>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_mac_ref_div: clk_mac_ref_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <4 5>;
+                                               clocks = <&clk_mac_ref>;
+                                               clock-output-names = "clk_mac";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_mac_pll_div: clk_mac_pll_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <9 5>;
+                                               clocks = <&clk_mac_pll>;
+                                               clock-output-names = "clk_mac_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15:14]: reserved */
+                               };
+
+                               clk_sel_con25: sel-con@00a8 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00a8 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_spi0_div: clk_spi0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_spi0>;
+                                               clock-output-names = "clk_spi0";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_spi0: clk_spi0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>,<&clk_gpll>;
+                                               clock-output-names = "clk_spi0";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+
+                               };
+
+                               clk_sel_con26: sel-con@00ac {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00ac 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       ddr_div: ddr_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_ddr>;
+                                               clock-output-names = "clk_ddr";
+                                               rockchip,div-type = <CLK_DIVIDER_USER_DEFINE>;
+                                               rockchip,div-relations =
+                                                               <0x0 1
+                                                                0x1 2
+                                                                0x3 4>;
+                                               #clock-cells = <0>;
+                                               rockchip,flags = <(CLK_GET_RATE_NOCACHE |
+                                                                       CLK_SET_RATE_NO_REPARENT)>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_DDR>;
+                                       };
+
+                                       /* reg[7:1]: reserved */
+
+                                       clk_ddr: ddr_clk_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 1>;
+                                               clocks = <&clk_dpll>, <&dummy>;
+                                               clock-output-names = "clk_ddr";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[15:9]: reserved */
+                               };
+
+                               clk_sel_con28: sel-con@00b4 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00b4 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       dclk_lcdc1: dclk_lcdc1_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "dclk_lcdc1";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[7:2]: reserved */
+
+                                       dclk_lcdc1_div: dclk_lcdc1_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 8>;
+                                               clocks = <&dclk_lcdc1>;
+                                               clock-output-names = "dclk_lcdc1";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+                               };
+
+                               clk_sel_con30: sel-con@00bc {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00bc 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_testout_div: clk_testout_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&dummy>;
+                                               clock-output-names = "clk_testout";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[7:5]: reserved */
+
+                                       hclk_vio_pre_div: hclk_vio_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&hclk_vio_pre>;
+                                               clock-output-names = "hclk_vio_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       hclk_vio_pre: hclk_vio_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "hclk_vio_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con31: sel-con@00c0 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00c0 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_hdmi: clk_hdmi_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 1>;
+                                               clocks = <&dclk_lcdc1_div>, <&dummy>;
+                                               clock-output-names = "clk_hdmi";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7:1]: reserved */
+
+                                       aclk_vio_pre_div: aclk_vio_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&aclk_vio_pre>;
+                                               clock-output-names = "aclk_vio_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       aclk_vio_pre: aclk_vio_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "aclk_vio_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con32: sel-con@00c4 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00c4 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       /* reg[7:0]: reserved */
+
+                                       aclk_vcodec_pre_div: aclk_vcodec_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&aclk_vcodec_pre>;
+                                               clock-output-names = "aclk_vcodec_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       aclk_vcodec_pre: aclk_vcodec_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_apll>, <&clk_dpll>, <&clk_gpll>;
+                                               clock-output-names = "aclk_vcodec_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+                               };
+
+                               clk_sel_con34: sel-con@00cc {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00cc 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_gpu_div: clk_gpu_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_gpu>;
+                                               clock-output-names = "clk_gpu";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT_IN_ORDER>;
+                                       };
+
+                                       /* reg[7:5]: reserved */
+
+                                       clk_gpu: clk_gpu_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&dummy>, <&dummy>, <&clk_gpll>;
+                                               clock-output-names = "clk_gpu";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+
+                               };
+
+                       };
+
+
+                       /* Gate control regs */
+                       clk_gate_cons {
+                               compatible = "rockchip,rk-gate-cons";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges ;
+
+                               clk_gates0: gate-clk@00d0{
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00d0 0x4>;
+                                       clocks =
+                                               <&clk_core>,            <&clk_gpll>,
+                                               <&clk_dpll>,    <&aclk_cpu_pre>,
+
+                                               <&aclk_cpu_pre>,        <&aclk_cpu_pre>,
+                                               <&clk_gpll>,            <&clk_core>,
+
+                                               <&clk_gpll>,    <&clk_i2s_pll>,
+                                               <&i2s_frac>,    <&hclk_vio_pre>,
+
+                                               <&dummy>,               <&clk_i2s_out>,
+                                               <&clk_i2s>,             <&dummy>;
+
+                                       clock-output-names =
+                                               "pclk_dbg",                     "reserved",      /* do not use bit1 = "cpu_gpll" */
+                                               "reserved",             "aclk_cpu_pre",
+
+                                               "hclk_cpu_pre",         "pclk_cpu_pre",
+                                               "reserved",             "aclk_core_pre",
+
+                                               "reserved",             "clk_i2s_pll",
+                                               "i2s_frac",             "hclk_vio_pre",
+
+                                               "clk_cryto",            "clk_i2s_out",
+                                               "clk_i2s",              "clk_testout";
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates1: gate-clk@00d4{
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00d4 0x4>;
+                                       clocks =
+                                               <&clk_timer0>,          <&clk_timer1>,
+                                               <&dummy>,               <&jtag_tck>,
+
+                                               <&aclk_vio_pre>,                <&xin12m>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&clk_uart0_div>,               <&uart0_frac>,
+                                               <&clk_uart1_div>,               <&uart1_frac>,
+
+                                               <&clk_uart2_div>,               <&uart2_frac>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "clk_timer0",           "clk_timer1",
+                                               "reserved",             "clk_jatg",
+
+                                               "aclk_vio_pre",         "clk_otgphy0",
+                                               "clk_otgphy1",                  "reserved",
+
+                                               "clk_uart0_div",        "uart0_frac",
+                                               "clk_uart1_div",        "uart1_frac",
+
+                                               "clk_uart2_div",        "uart2_frac",
+                                               "reserved",     "reserved";
+
+                                        rockchip,suspend-clkgating-setting=<0x0 0x0>;
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates2: gate-clk@00d8 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00d8 0x4>;
+                                       clocks =
+                                               <&aclk_peri_pre>,               <&aclk_peri_pre>,
+                                               <&aclk_peri_pre>,               <&aclk_peri_pre>,
+
+                                               <&clk_timer2>,          <&clk_timer3>,
+                                               <&clk_mac_ref>,         <&dummy>,
+
+                                               <&dummy>,               <&clk_spi0>,
+                                               <&clk_spdif_pll>,               <&clk_sdmmc0>,
+
+                                               <&spdif_frac>,          <&clk_sdio>,
+                                               <&clk_emmc>,            <&dummy>;
+
+                                       clock-output-names =
+                                               "aclk_peri",            "aclk_peri_pre",
+                                               "hclk_peri_pre",                "pclk_peri_pre",
+
+                                               "clk_timer2",           "clk_timer3",
+                                               "clk_mac",              "reserved",
+
+                                               "reserved",             "clk_spi0",
+                                               "clk_spdif_pll",                "clk_sdmmc0",
+
+                                               "spdif_frac",           "clk_sdio",
+                                               "clk_emmc",             "reserved";
+                                           rockchip,suspend-clkgating-setting=<0x0 0x0>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates3: gate-clk@00dc {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00dc 0x4>;
+                                       clocks =
+                                               <&dummy>,               <&dummy>,
+                                               <&dclk_lcdc1>,          <&dummy>,
+
+                                               <&dummy>,                       <&hclk_peri_pre>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&pclk_cpu_pre>,                <&dummy>,
+                                               <&dummy>,               <&aclk_vcodec_pre>,
+
+                                               <&aclk_vcodec_pre>,             <&clk_gpu>,
+                                               <&hclk_peri_pre>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "reserved",             "reserved",
+                                               "dclk_lcdc1",           "reserved",
+
+                                               "reserved",             "g_hclk_mac",
+                                               "reserved",             "reserved",
+
+                                               "g_pclk_hdmi",          "reserved",
+                                               "reserved",             "aclk_vcodec_pre",
+
+                                               "hclk_vcodec",          "clk_gpu",
+                                               "g_hclk_sfc",           "reserved";
+                                       rockchip,suspend-clkgating-setting=<0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates4: gate-clk@00e0{
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00e0 0x4>;
+                                       clocks =
+                                               <&hclk_peri_pre>,               <&pclk_peri_pre>,
+                                               <&aclk_peri_pre>,               <&aclk_peri_pre>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&aclk_cpu_pre>,                <&dummy>,
+
+                                               <&aclk_cpu_pre>,                <&dummy>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "g_hp_axi_matrix",              "g_pp_axi_matrix",
+                                               "g_aclk_cpu_peri",              "g_ap_axi_matrix",
+
+                                               "reserved",             "g_hclk_mac",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "reserved",
+                                               "g_aclk_strc_sys",              "reserved",
+
+                                               /* Not use these ddr gates */
+                                               "g_aclk_intmem",                "reserved",
+                                               "reserved",             "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates5: gate-clk@00e4 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00e4 0x4>;
+                                       clocks =
+                                               <&dummy>,               <&aclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&pclk_cpu_pre>,                <&dummy>,
+                                               <&hclk_cpu_pre>,                <&pclk_cpu_pre>,
+
+                                               <&dummy>,               <&hclk_peri_pre>,
+                                               <&hclk_peri_pre>,               <&hclk_peri_pre>,
+
+                                               <&dummy>,               <&hclk_peri_pre>,
+                                               <&pclk_cpu_pre>,                <&dummy>;
+
+                                       clock-output-names =
+                                               "reserved",             "g_aclk_dmac2",
+                                               "g_pclk_efuse", "reserved",
+
+                                               "g_pclk_grf",           "reserved",
+                                               "g_hclk_rom",           "g_pclk_ddrupctl",
+
+                                               "reserved",             "g_hclk_nandc",
+                                               "g_hclk_sdmmc0",                "g_hclk_sdio",
+
+                                               "reserved",             "g_hclk_otg0",
+                                               "g_pclk_acodec",                "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates6: gate-clk@00e8 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00e8 0x4>;
+                                       clocks =
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,                       <&dummy>,
+
+                                               <&hclk_vio_pre>,                <&aclk_vio_pre>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved",
+
+                                               "g_hclk_vio_bus",               "g_aclk_vio",
+                                               "reserved",             "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates7: gate-clk@00ec {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00ec 0x4>;
+                                       clocks =
+                                               <&hclk_peri_pre>,               <&dummy>,
+                                               <&hclk_peri_pre>,               <&hclk_peri_pre>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&pclk_peri_pre>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&pclk_peri_pre>,               <&dummy>,
+                                               <&dummy>,               <&pclk_peri_pre>;
+
+                                       clock-output-names =
+                                               "g_hclk_emmc",          "reserved",
+                                               "g_hclk_i2s",           "g_hclk_otg1",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "g_pclk_timer0",
+
+                                               "reserved",             "reserved",
+                                               "g_pclk_pwm",           "reserved",
+
+                                               "g_pclk_spi",           "reserved",
+                                               "reserved",             "g_pclk_wdt";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates8: gate-clk@00f0 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00f0 0x4>;
+                                       clocks =
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&dummy>,               <&pclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "g_pclk_uart0",         "g_pclk_uart1",
+                                               "g_pclk_uart2",         "reserved",
+
+                                               "g_pclk_i2c0",          "g_pclk_i2c1",
+                                               "g_pclk_i2c2",          "reserved",
+
+                                               "reserved",             "g_pclk_gpio0",
+                                               "g_pclk_gpio1",         "g_pclk_gpio2",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved";
+
+                                        rockchip,suspend-clkgating-setting=<0x0000 0x0000>;
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates9: gate-clk@00f4 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00f4 0x4>;
+                                       clocks =
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&hclk_vio_pre>,
+                                               <&aclk_vio_pre>,                <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&hclk_peri_pre>,
+                                               <&hclk_peri_pre>,               <&aclk_peri_pre>;
+
+                                       clock-output-names =
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "g_hclk_lcdc",
+                                               "g_aclk_lcdc",          "reserved",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "g_hclk_usb_peri",
+                                               "g_hclk_pe_arbi",               "g_aclk_peri_niu";
+
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates10: gate-clk@00f8 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00f8 0x4>;
+                                       clocks =
+                                               <&xin24m>,              <&xin24m>,
+                                               <&xin24m>,              <&dummy>,
+
+                                               <&clk_nandc>,           <&clk_sfc>,
+                                               <&clk_hevc_core>,               <&dummy>,
+
+                                               <&clk_dpll>,            <&dummy>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "g_clk_pvtm_core",              "g_clk_pvtm_gpu",
+                                               "g_pvtm_video",         "reserved",
+
+                                               "clk_nandc",            "clk_sfc",
+                                               "clk_hevc_core",                "reserved",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "reserved",
+                                               "reserved",             "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0 0x0>; /* pwm logic vol */
+
+                                       #clock-cells = <1>;
+                               };
+
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/rk3036-fpga.dts b/arch/arm/boot/dts/rk3036-fpga.dts
new file mode 100644 (file)
index 0000000..c8ae65a
--- /dev/null
@@ -0,0 +1,23 @@
+/dts-v1/;
+#include <dt-bindings/rkfb/rk_fb.h>
+#include "rk3036.dtsi"
+#include "lcd-box.dtsi"
+
+/ {
+       compatible = "rockchip,rk3036";
+
+       memory {
+               device_type = "memory";
+               reg = <0x60000000 0x10000000>;
+       };
+
+       chosen {
+               bootargs = "androidboot.console=ttyFIQ0 initrd=0x62000000,0x00800000";
+       };
+
+       fiq-debugger {
+               status = "okay";
+       };
+
+
+};
diff --git a/arch/arm/boot/dts/rk3036-pinctrl.dtsi b/arch/arm/boot/dts/rk3036-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..6297a05
--- /dev/null
@@ -0,0 +1,582 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/pinctrl/rockchip-rk3036.h>
+
+/ {
+       pinctrl: pinctrl@20008000 {
+               compatible = "rockchip,rk3036-pinctrl";
+               reg = <0x20008000 0xA8>,
+                     <0x200080A8 0x30>,
+                     <0x20008118 0x18>,
+                     <0x20008100 0x04>;
+               reg-names = "base", "mux", "pull", "drv";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gpio0: gpio0@2007c000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x2007c000 0x100>;
+                       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 9>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio1@20080000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20080000 0x100>;
+                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 10>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio2@20084000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20084000 0x100>;
+                       interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 11>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio15: gpio15@20086000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20086000 0x100>;
+                       interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;//127 = 160-32-1
+                       clocks = <&clk_gates8 12>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               pcfg_pull_up: pcfg_pull_up {
+                       bias-pull-up;
+               };
+
+               pcfg_pull_down: pcfg_pull_down {
+                       bias-pull-down;
+               };
+
+               pcfg_pull_none: pcfg_pull_none {
+                       bias-disable;
+               };
+
+               gpio0_uart0 {
+                       uart0_xfer: uart0-xfer {
+                               rockchip,pins = <UART0_SIN>,
+                                               <UART0_SOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       uart0_cts: uart0-cts {
+                               rockchip,pins = <UART0_CTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       uart0_rts: uart0-rts {
+                               rockchip,pins = <UART0_RTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       uart0_rts_gpio: uart0-rts-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(UART0_RTSN)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+               };
+
+               gpio1_uart1 {
+                       uart1_xfer: uart1-xfer {
+                               rockchip,pins = <UART1_SIN>,
+                                               <UART1_SOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+               };
+
+               gpio1_uart2 {
+                       uart2_xfer: uart2-xfer {
+                               rockchip,pins = <UART2_SIN>,
+                                               <UART2_SOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+                       /* no rts / cts for uart2 */
+               };
+
+
+               gpio0_i2c0 {
+                       i2c0_sda:i2c0-sda {
+                               rockchip,pins = <I2C0_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       i2c0_scl:i2c0-scl {
+                               rockchip,pins = <I2C0_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       i2c0_gpio: i2c0-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C0_SDA)>, <FUNC_TO_GPIO(I2C0_SCL)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+               };
+
+               gpio0_i2c1 {
+                       i2c1_sda:i2c1-sda {
+                               rockchip,pins = <I2C1_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       i2c1_scl:i2c1-scl {
+                               rockchip,pins = <I2C1_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       i2c1_gpio: i2c1-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C1_SDA)>, <FUNC_TO_GPIO(I2C1_SCL)>;
+                                rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+               };
+
+               gpio2_i2c2 {
+                       i2c2_sda:i2c2-sda {
+                               rockchip,pins = <I2C2_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       i2c2_scl:i2c2-scl {
+                               rockchip,pins = <I2C2_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       i2c2_gpio: i2c2-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C2_SDA)>, <FUNC_TO_GPIO(I2C2_SCL)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+               };
+
+               gpio1_spi0 {
+                       spi0_txd:spi0-txd {
+                               rockchip,pins = <SPI0_TXD>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       spi0_rxd:spi0-rxd {
+                               rockchip,pins = <SPI0_RXD>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       spi0_clk:spi0-clk {
+                               rockchip,pins = <SPI0_CLK>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       spi0_cs0:spi0-cs0 {
+                               rockchip,pins = <SPI0_CS0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       spi0_cs1:spi0-cs1 {
+                               rockchip,pins = <SPI0_CS1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+               };
+
+               gpio1_hdmi {
+                       hdmi_cec:hdmi-cec {
+                               rockchip,pins = <HDMI_CEC>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       hdmi_sda:hdmi-sda {
+                               rockchip,pins = <HDMI_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       hdmi_scl:hdmi-scl {
+                               rockchip,pins = <HDMI_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       hdmi_hpd:hdmi-hpd {
+                               rockchip,pins = <HDMI_HPD>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+
+                       };
+
+                       hdmi_gpio: hdmi-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(HDMI_CEC)>, <FUNC_TO_GPIO(HDMI_SDA)>, <FUNC_TO_GPIO(HDMI_SCL)>, <FUNC_TO_GPIO(HDMI_HPD)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+               };
+
+               gpio1_i2s0 {
+                       i2s0_mclk:i2s0-mclk {
+                               rockchip,pins = <I2S0_MCLK>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+                       i2s0_sclk:i2s0-sclk {
+                               rockchip,pins = <I2S0_SCLK>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+                       i2s0_lrckrx:i2s0-lrckrx {
+                               rockchip,pins = <I2S0_LRCKRX>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+                       i2s0_lrcktx:i2s0-lrcktx {
+                               rockchip,pins = <I2S0_LRCKTX>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+                       i2s0_sdo:i2s0-sdo {
+                               rockchip,pins = <I2S0_SDO>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+                       i2s0_sdi:i2s0-sdi {
+                               rockchip,pins = <I2S0_SDI>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+                       i2s0_gpio: i2s0-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2S0_MCLK)>,
+                                               <FUNC_TO_GPIO(I2S0_SCLK)>,
+                                               <FUNC_TO_GPIO(I2S0_LRCKRX)>,
+                                               <FUNC_TO_GPIO(I2S0_LRCKTX)>,
+                                               <FUNC_TO_GPIO(I2S0_SDO)>,
+                                               <FUNC_TO_GPIO(I2S0_SDI)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+               };
+
+               gpio0_spdif {
+                       spdif_tx: spdif-tx {
+                               rockchip,pins = <SPDIF_TX>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+               };
+
+               gpio1_emmc0 {
+                       emmc0_clk: emmc0-clk {
+                               rockchip,pins = <EMMC_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       emmc0_cmd: emmc0-cmd {
+                               rockchip,pins = <EMMC_CMD>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+
+                       emmc0_bus1: emmc0-bus-width1 {
+                               rockchip,pins = <EMMC_D0>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+                       emmc0_bus4: emmc0-bus-width4 {
+                               rockchip,pins = <EMMC_D0>,
+                                               <EMMC_D1>,
+                                               <EMMC_D2 >,
+                                               <EMMC_D3>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+               };
+
+               gpio1_sdmmc0 {
+                       sdmmc0_clk: sdmmc0-clk {
+                               rockchip,pins = <MMC0_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       sdmmc0_cmd: sdmmc0-cmd {
+                               rockchip,pins = <MMC0_CMD>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+                       };
+
+                       sdmmc0_dectn: sdmmc0-dectn{
+                               rockchip,pins = <MMC0_DETN>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+
+                       sdmmc0_bus1: sdmmc0-bus-width1 {
+                               rockchip,pins = <MMC0_D0>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+                       sdmmc0_bus4: sdmmc0-bus-width4 {
+                               rockchip,pins = <MMC0_D0>,
+                                               <MMC0_D1>,
+                                               <MMC0_D2>,
+                                               <MMC0_D3>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+                       sdmmc0_gpio: sdmmc0_gpio{
+                               rockchip,pins =
+                                       <GPIO1_B7>,  //CMD
+                                       <GPIO1_C0>,  //CLK
+                                       <GPIO1_C1>,  //DET
+                                       <GPIO1_C2>,  //D0
+                                       <GPIO1_C3>,  //D1
+                                       <GPIO1_C4>,  //D2
+                                       <GPIO1_C5>;  //D3
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+               };
+
+               gpio1_nandc {
+                       nandc_ale:nandc-ale {
+                               rockchip,pins = <NAND_ALE>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_cle:nandc-cle {
+                               rockchip,pins = <NAND_CLE>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_wrn:nandc-wrn {
+                               rockchip,pins = <NAND_WRN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_rdn:nandc-rdn {
+                               rockchip,pins = <NAND_RDN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_rdy:nandc-rdy {
+                               rockchip,pins = <NAND_RDY>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_cs0:nandc-cs0 {
+                               rockchip,pins = <NAND_CS0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+
+                       nandc_data: nandc-data {
+                               rockchip,pins = <NAND_D0>,
+                                               <NAND_D1>,
+                                               <NAND_D2>,
+                                               <NAND_D3>,
+                                               <NAND_D4>,
+                                               <NAND_D5>,
+                                               <NAND_D6>,
+                                               <NAND_D7>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+                       };
+
+               };
+
+               gpio0_sdio0 {
+                       sdio0_clk: sdio0_clk {
+                               rockchip,pins = <MMC1_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       sdio0_cmd: sdio0_cmd {
+                               rockchip,pins = <MMC1_CMD>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+                       sdio0_bus1: sdio0-bus-width1 {
+                               rockchip,pins = <MMC1_D0>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+                       sdio0_bus4: sdio0-bus-width4 {
+                               rockchip,pins = <MMC1_D0>,
+                                               <MMC1_D1>,
+                                               <MMC1_D2>,
+                                               <MMC1_D3>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+
+                       sdio0_gpio: sdio0-all-gpio{
+                               rockchip,pins =
+                                       <GPIO0_B1>,   //CLK
+                                       <GPIO0_B0>,   //CMD
+                                       <GPIO0_B3>,   //DO
+                                       <GPIO0_B4>,   //D1
+                                       <GPIO0_B5>,   //D2
+                                       <GPIO0_B6>;   //D3
+                               rockchip,pull = <VALUE_PULL_UP>;
+
+
+                       };
+               };
+
+               gpio0_pwm{
+                       pwm0_pin:pwm0 {
+                               rockchip,pins = <PWM0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       pwm1_pin:pwm1 {
+                               rockchip,pins = <PWM1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       pwm2_pin:pwm2 {
+                               rockchip,pins = <PWM2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       pwm3_pin:pwm3 {
+                               rockchip,pins = <PWM3(IR)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+               };
+
+               gpio2_gmac {
+                       mac_clk: mac-clk {
+                               rockchip,pins = <MAC_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       mac_txpins: mac-txpins {
+                               rockchip,pins = <MAC_TXD0>, <MAC_TXD1>,  <MAC_TXEN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       mac_rxpins: mac-rxpins {
+                               rockchip,pins = <MAC_RXD0>, <MAC_RXD1>,<MAC_RXER>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       mac_crs: mac-crs {
+                               rockchip,pins = <MAC_CRS>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+
+                       mac_mdpins: mac-mdpins {
+                               rockchip,pins = <MAC_MDIO>, <MAC_MDC>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+
+
+                       };
+               };
+
+
+               //to add
+
+
+       };
+
+};
diff --git a/arch/arm/boot/dts/rk3036-rk88.dts b/arch/arm/boot/dts/rk3036-rk88.dts
new file mode 100755 (executable)
index 0000000..744a1a9
--- /dev/null
@@ -0,0 +1,147 @@
+/dts-v1/;
+
+#include "rk3036.dtsi"
+
+/ {
+
+       fiq-debugger {
+               status = "okay";
+       };
+
+       pwm_regulator {
+               compatible = "rockchip_pwm_regulator";
+               pwms = <&pwm2 0 25000>;
+               rockchip,pwm_id= <2>;
+               rockchip,pwm_voltage_map= <950000 975000 1000000 1025000 1050000 1075000 1100000 1125000 1150000 1175000 1200000 1225000 1250000 1275000 1300000 1325000 1350000 1375000 1400000 1425000 1450000>;
+               rockchip,pwm_voltage= <1250000>;
+               rockchip,pwm_min_voltage= <950000>;
+               rockchip,pwm_max_voltage= <1450000>;
+               rockchip,pwm_suspend_voltage= <1250000>;
+               rockchip,pwm_coefficient= <500>;
+               status = "disabled";
+               regulators {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pwm_reg0: regulator@0 {
+                               regulator-compatible = "pwm_dcdc1";
+                               regulator-name= "vdd_arm";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+
+    wireless-wlan {
+        compatible = "wlan-platdata";
+
+        wifi_chip_type = "";
+        sdio_vref = <1800>; //1800mv or 3300mv
+
+        //power_ctrl_by_pmu;
+        //power_pmu_regulator = "act_ldo3";
+        //power_pmu_enable_level = <1>; //1->HIGH, 0->LOW
+
+        //vref_ctrl_enable;
+        //vref_ctrl_gpio = <&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
+        //vref_pmu_regulator = "act_ldo3";
+        //vref_pmu_enable_level = <1>; //1->HIGH, 0->LOW
+
+        //WIFI,poweren_gpio = <&gpio4 GPIO_D4 GPIO_ACTIVE_HIGH>;
+        //WIFI,host_wake_irq = <&gpio4 GPIO_D6 GPIO_ACTIVE_HIGH>;
+        //WIFI,reset_gpio = <&gpio0 GPIO_A2 GPIO_ACTIVE_LOW>;
+
+        status = "okay";
+    };
+
+    wireless-bluetooth {
+        compatible = "bluetooth-platdata";
+
+        //wifi-bt-power-toggle;
+
+        //uart_rts_gpios = <&gpio4 GPIO_C3 GPIO_ACTIVE_LOW>;
+        //pinctrl-names = "default","rts_gpio";
+        //pinctrl-0 = <&uart0_rts>;
+        //pinctrl-1 = <&uart0_rts_gpio>;
+
+        //BT,power_gpio = <&gpio4 GPIO_D3 GPIO_ACTIVE_HIGH>;
+        //BT,reset_gpio = <&gpio4 GPIO_D5 GPIO_ACTIVE_HIGH>;
+        //BT,wake_gpio = <&gpio4 GPIO_D2 GPIO_ACTIVE_HIGH>;
+        //BT,wake_host_irq = <&gpio4 GPIO_D7 GPIO_ACTIVE_LOW>;
+
+        status = "okay";
+
+    };
+};
+
+&nandc {
+       status = "disabled"; // used nand set "disabled" ,used emmc set "okay"
+};  
+
+&emmc {
+       clock-frequency = <100000000>;
+       clock-freq-min-max = <400000 100000000>;
+
+        supports-highspeed;
+       supports-emmc;
+        bootpart-no-access;
+
+       supports-DDR_MODE;
+       //caps2-mmc-hs200;
+
+        ignore-pm-notify;
+       keep-power-in-suspend;
+       
+       //poll-hw-reset 
+       status = "okay";
+};
+    
+&sdmmc {
+               clock-frequency = <50000000>;
+               clock-freq-min-max = <400000 50000000>;
+               supports-highspeed;
+               supports-sd;
+               broken-cd;
+               card-detect-delay = <200>;
+
+               ignore-pm-notify;
+               keep-power-in-suspend;
+       
+               //vmmc-supply = <&rk808_ldo5_reg>;
+               status = "okay";
+};
+               
+&sdio {
+               clock-frequency = <50000000>;
+               clock-freq-min-max = <200000 50000000>;
+               supports-highspeed;
+               supports-sdio;
+               ignore-pm-notify;
+               keep-power-in-suspend;
+               //cap-sdio-irq;
+               status = "okay";
+};
+
+&uart0 {
+        status = "okay";
+        dma-names = "!tx", "!rx";
+        //pinctrl-0 = <&uart0_xfer &uart0_cts>;
+};
+
+&rk_screen {
+        display-timings = <&disp_timings>;
+};
+
+&lcdc {
+       status = "okay";
+};
+
+&tve {
+       status = "disabled";
+};
+
+&hdmi {
+       status = "okay";
+       //rockchips,hdmi_audio_source = <0>;
+};
diff --git a/arch/arm/boot/dts/rk3036-sdk.dts b/arch/arm/boot/dts/rk3036-sdk.dts
new file mode 100644 (file)
index 0000000..a77e61d
--- /dev/null
@@ -0,0 +1,232 @@
+/dts-v1/;
+#include <dt-bindings/rkfb/rk_fb.h>
+#include "rk3036.dtsi"
+#include "rk3036-pinctrl.dtsi"
+#include "lcd-box.dtsi"
+/ {
+
+       fiq-debugger {
+               status = "okay";
+       };
+
+       pwm_regulator {
+               compatible = "rockchip_pwm_regulator";
+               pwms = <&pwm2 0 25000>;
+               rockchip,pwm_id= <2>;
+               rockchip,pwm_voltage_map= <950000 975000 1000000 1025000 1050000 1075000 1100000 1125000 1150000 1175000 1200000 1225000 1250000 1275000 1300000 1325000 1350000 1375000 1400000 1425000 1450000>;
+               rockchip,pwm_voltage= <1250000>;
+               rockchip,pwm_min_voltage= <950000>;
+               rockchip,pwm_max_voltage= <1450000>;
+               rockchip,pwm_suspend_voltage= <1250000>;
+               rockchip,pwm_coefficient= <500>;
+               status = "disabled";
+               regulators {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pwm_reg0: regulator@0 {
+                               regulator-compatible = "pwm_dcdc1";
+                               regulator-name= "vdd_arm";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+
+       wireless-wlan {
+               compatible = "wlan-platdata";
+
+               wifi_chip_type = "";
+               sdio_vref = <0>; //1800mv or 3300mv
+
+               //power_ctrl_by_pmu;
+               //power_pmu_regulator = "act_ldo3";
+               //power_pmu_enable_level = <1>; //1->HIGH, 0->LOW
+
+               //vref_ctrl_enable;
+               //vref_ctrl_gpio = <&gpio0 GPIO_A2 GPIO_ACTIVE_HIGH>;
+               //vref_pmu_regulator = "act_ldo3";
+               //vref_pmu_enable_level = <1>; //1->HIGH, 0->LOW
+
+               WIFI,poweren_gpio = <&gpio2 GPIO_D6 GPIO_ACTIVE_HIGH>;
+               WIFI,host_wake_irq = <&gpio2 GPIO_C4 GPIO_ACTIVE_HIGH>;
+               //WIFI,reset_gpio = <&gpio0 GPIO_A2 GPIO_ACTIVE_LOW>;
+
+               status = "okay";
+    };
+
+    wireless-bluetooth {
+        compatible = "bluetooth-platdata";
+
+        //wifi-bt-power-toggle;
+
+       uart_rts_gpios = <&gpio0 GPIO_C2 GPIO_ACTIVE_LOW>;
+        pinctrl-names = "default","rts_gpio";
+        pinctrl-0 = <&uart0_rts>;
+        pinctrl-1 = <&uart0_rts_gpio>;
+
+        //BT,power_gpio = <&gpio4 GPIO_D3 GPIO_ACTIVE_HIGH>;
+        BT,reset_gpio = <&gpio2 GPIO_D5 GPIO_ACTIVE_HIGH>;
+        BT,wake_gpio = <&gpio2 GPIO_C5 GPIO_ACTIVE_HIGH>;
+        BT,wake_host_irq = <&gpio0 GPIO_A0 GPIO_ACTIVE_LOW>;
+
+        status = "okay";
+    };
+
+       usb_control {
+               compatible = "rockchip,rk3036-usb-control";
+               host_drv_gpio = <&gpio2 GPIO_C7 GPIO_ACTIVE_LOW>;
+               otg_drv_gpio = <&gpio0 GPIO_D2 GPIO_ACTIVE_LOW>;
+
+               rockchip,remote_wakeup;
+               rockchip,usb_irq_wakeup;
+       };
+
+       key {
+               compatible = "rockchip,key";
+       };
+
+       codec_hdmi_i2s: codec-hdmi-i2s {
+               compatible = "hdmi-i2s";
+       };
+
+       rockchip-hdmi-i2s {
+               compatible = "rockchip-hdmi-i2s";
+               dais {
+                       dai0 {
+                               audio-codec = <&codec_hdmi_i2s>;
+                               i2s-controller = <&i2s>;
+                               format = "i2s";
+                               //continuous-clock;
+                               //bitclock-inversion;
+                               //frame-inversion;
+                               //bitclock-master;
+                               //frame-master;
+                       };
+               };
+       };
+
+       codec_hdmi_spdif: codec-hdmi-spdif {
+               compatible = "hdmi-spdif";
+       };
+
+       rockchip-hdmi-spdif {
+               compatible = "rockchip-hdmi-spdif";
+               dais {
+                       dai0 {
+                               audio-codec = <&codec_hdmi_spdif>;
+                               i2s-controller = <&spdif>;
+                       };
+               };
+       };
+
+       rockchip-audio {
+               compatible = "rk3036-audio";
+               dais {
+                       dai0 {
+                               audio-codec = <&codec>;
+                               i2s-controller = <&i2s>;
+                               format = "i2s";
+                               //continuous-clock;
+                               //bitclock-inversion;
+                               //frame-inversion;
+                               //bitclock-master;
+                               //frame-master;
+                       };
+               };
+       };
+};
+
+&uart0{
+       status = "okay";
+       dma-names = "!tx", "!rx";
+       pinctrl-0 = <&uart0_xfer &uart0_cts>;
+};
+
+&nandc {
+       status = "okay"; // used nand set "okay" ,used emmc set "disabled"
+};
+
+&nandc0reg {
+       status = "disabled"; // used nand set "disabled" ,used emmc set "okay"
+};
+
+&emmc {
+       clock-frequency = <100000000>;
+       clock-freq-min-max = <400000 100000000>;
+
+        supports-highspeed;
+       supports-emmc;
+        bootpart-no-access;
+
+       supports-DDR_MODE;
+       //caps2-mmc-hs200;
+
+        ignore-pm-notify;
+       keep-power-in-suspend;
+
+       //poll-hw-reset
+       status = "disabled";
+};
+
+&sdmmc {
+               clock-frequency = <50000000>;
+               clock-freq-min-max = <400000 50000000>;
+               supports-highspeed;
+               supports-sd;
+               broken-cd;
+               card-detect-delay = <200>;
+
+               ignore-pm-notify;
+               keep-power-in-suspend;
+
+               //vmmc-supply = <&rk808_ldo5_reg>;
+               status = "disabled";
+};
+
+&sdio {
+               clock-frequency = <50000000>;
+               clock-freq-min-max = <200000 50000000>;
+               supports-highspeed;
+               supports-sdio;
+               ignore-pm-notify;
+               keep-power-in-suspend;
+               //cap-sdio-irq;
+               status = "okay";
+};
+
+
+&i2c1 {
+       status = "okay";
+        rtc@51 {
+                compatible = "rtc,hym8563";
+                reg = <0x51>;
+                //irq_gpio = <&gpio0 GPIO_A4 IRQ_TYPE_EDGE_FALLING>;
+        };
+};
+
+
+&rk_screen {
+        display-timings = <&disp_timings>;
+};
+
+&lcdc {
+       status = "okay";
+};
+
+&tve {
+       status = "disabled";
+};
+
+&hdmi {
+       status = "okay";
+       //rockchips,hdmi_audio_source = <0>;
+};
+
+&vmac {
+//     pmu_regulator = "act_ldo5";
+//     pmu_enable_level = <1>; //1->HIGH, 0->LOW
+//      power-gpio = <&gpio0 GPIO_A6 GPIO_ACTIVE_HIGH>;
+        reset-gpio = <&gpio2 GPIO_C6 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
new file mode 100755 (executable)
index 0000000..d845b1a
--- /dev/null
@@ -0,0 +1,707 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+#include "rk3036-clocks.dtsi"
+#include "rk3036-pinctrl.dtsi"
+
+/ {
+       compatible = "rockchip,rk3036";
+       rockchip,sram = <&sram>;
+       interrupt-parent = <&gic>;
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               spi0 = &spi0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0xf00>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0xf01>;
+               };
+       };
+
+       gic: interrupt-controller@10139000 {
+               compatible = "arm,cortex-a15-gic";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               reg = <0x10139000 0x1000>,
+                     <0x1013a000 0x1000>;
+       };
+
+       arm-pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       cpu_axi_bus: cpu_axi_bus {
+               compatible = "rockchip,cpu_axi_bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               qos {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       core {
+                               reg = <0x1012a000 0x20>;
+                               rockchip,priority = <3 2>;
+                       };
+                       peri {
+                               reg = <0x1012c000 0x20>;
+                       };
+                       gpu {
+                               reg = <0x1012d000 0x20>;
+                       };
+                       vpu {
+                               reg = <0x1012e000 0x20>;
+                       };
+                       hevc {
+                               reg = <0x1012e080 0x20>;
+                       };
+                       vio {
+                               reg = <0x1012f000 0x20>;
+                               rockchip,priority = <3 3>;
+                       };
+               };
+
+               msch {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       msch@10128000 {
+                               reg = <0x10128000 0x40>;
+                               rockchip,read-latency = <0x80>;
+                       };
+               };
+       };
+
+       sram: sram@10080000 {
+               compatible = "mmio-sram";
+               reg = <0x10080000 0x2000>;
+               map-exec;
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clock-frequency = <24000000>;
+       };
+
+       timer@20044000 {
+               compatible = "rockchip,timer";
+               reg = <0x20044000 0x20>;
+               interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,broadcast = <1>;
+       };
+
+       watchdog: wdt@2004c000 {
+               compatible = "rockchip,watch dog";
+               reg = <0x2004c000 0x100>;
+               clocks = <&clk_gates7 15>;
+               clock-names = "pclk_wdt";
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,irq = <1>;
+               rockchip,timeout = <60>;
+               rockchip,atboot = <1>;
+               rockchip,debug = <0>;
+               status = "disabled";
+       };
+
+       amba {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "arm,amba-bus";
+               interrupt-parent = <&gic>;
+               ranges;
+
+               pdma: pdma@20078000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x20078000 0x4000>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+               };
+       };
+
+       reset: reset@20000110{
+               compatible = "rockchip,reset";
+               reg = <0x20000110 0x24>;
+               rockchip,reset-flag = <ROCKCHIP_RESET_HIWORD_MASK>;
+               #reset-cells = <1>;
+       };
+
+       nandc: nandc@10500000 {
+               compatible = "rockchip,rk-nandc";
+               reg = <0x10500000 0x4000>;
+               interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+               //pinctrl-names = "default";
+               //pinctrl-0 = <&nandc_ale &nandc_cle &nandc_wrn &nandc_rdn &nandc_rdy &nandc_cs0 &nandc_data>;
+               nandc_id = <0>;
+               clocks = <&clk_nandc>, <&clk_gates5 9>, <&clk_gates10 4>;
+               clock-names = "clk_nandc", "g_clk_nandc", "hclk_nandc";
+       };
+
+       nandc0reg: nandc0@10500000 {
+               compatible = "rockchip,rk-nandc";
+               reg = <0x10500000 0x4000>;
+       };
+
+       spi0: spi@20074000 {
+               compatible = "rockchip,rockchip-spi";
+               reg = <0x20074000 0x1000>;
+               interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&spi0_txd &spi0_rxd &spi0_clk &spi0_cs0 &spi0_cs1>;
+               rockchip,spi-src-clk = <0>;
+               num-cs = <2>;
+               clocks =<&clk_spi0>, <&clk_gates2 9>;
+               clock-names = "spi","pclk_spi0";
+               dmas = <&pdma 8>, <&pdma 9>;
+               #dma-cells = <2>;
+               dma-names = "tx", "rx";
+               status = "disabled";
+       };
+
+       uart0: serial@20060000 {
+               compatible = "rockchip,serial";
+               reg = <0x20060000 0x100>;
+               interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               clocks = <&clk_uart0>, <&clk_gates8 0>;
+               clock-names = "sclk_uart", "pclk_uart";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               dmas = <&pdma 2>, <&pdma 3>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+               status = "disabled";
+       };
+
+       uart1: serial@20064000 {
+               compatible = "rockchip,serial";
+               reg = <0x20064000 0x100>;
+               interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               clocks = <&clk_uart1>, <&clk_gates8 1>;
+               clock-names = "sclk_uart", "pclk_uart";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               dmas = <&pdma 4>, <&pdma 5>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart1_xfer>;
+               status = "disabled";
+       };
+
+       uart2: serial@20068000 {
+               compatible = "rockchip,serial";
+               reg = <0x20068000 0x100>;
+               interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               clocks = <&clk_uart2>, <&clk_gates8 2>;
+               clock-names = "sclk_uart", "pclk_uart";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               dmas = <&pdma 6>, <&pdma 7>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart2_xfer>;
+               status = "disabled";
+       };
+
+       fiq-debugger {
+               compatible = "rockchip,fiq-debugger";
+               rockchip,serial-id = <2>;
+               rockchip,signal-irq = <106>;
+               rockchip,wake-irq = <0>;
+               status = "disabled";
+       };
+
+       clocks-init{
+               compatible = "rockchip,clocks-init";
+               rockchip,clocks-init-parent =
+                       <&clk_core &clk_apll>, <&aclk_cpu_pre &clk_gpll>,
+                       <&aclk_peri_pre &clk_gpll>, <&clk_uart_pll &clk_gpll>,
+                       <&clk_i2s_pll &clk_gpll>, <&clk_spdif_pll &clk_gpll>,
+                       <&aclk_vcodec_pre &clk_gpll>, <&clk_hevc_core &clk_gpll>,
+                       <&aclk_vio_pre &clk_gpll>, <&clk_mac_pll &clk_apll>;
+               rockchip,clocks-init-rate =
+                       <&clk_core 1000000000>, <&clk_gpll 594000000>,
+                       <&aclk_cpu_pre 150000000>, <&hclk_cpu_pre 75000000>,
+                       <&pclk_cpu_pre 75000000>,        <&aclk_peri_pre 150000000>,
+                       <&hclk_peri_pre 75000000>, <&pclk_peri_pre 75000000>,
+                       <&clk_gpu 300000000>,    <&aclk_vio_pre 300000000>,
+                       <&hclk_vio_pre 150000000>, <&aclk_vcodec_pre 300000000>,
+                       <&clk_hevc_core 200000000>, <&clk_mac_pll_div 50000000>,
+                       <&clk_mac_ref_div 25000000>;
+       /*      rockchip,clocks-uboot-has-init =
+                       <&aclk_vio1>;*/
+       };
+
+       clocks-enable {
+               compatible = "rockchip,clocks-enable";
+               clocks =
+                               /*PD_CORE*/
+                               <&clk_gates0 0>, <&clk_gates0 7>,
+
+                               /*PD_CPU*/
+                               <&clk_gates0 3>, <&clk_gates0 4>,
+                               <&clk_gates0 5>,
+
+                               /*TIMER*/
+                               <&clk_gates1 0>, <&clk_gates1 1>,
+                               <&clk_gates2 4>, <&clk_gates2 5>,
+
+                               /*PD_PERI*/
+                               <&clk_gates2 0>, <&hclk_peri_pre>,
+                               <&pclk_peri_pre>, <&clk_gates2 1>,
+
+                               /*aclk_cpu_pre*/
+                               <&clk_gates4 12>,/*aclk_intmem*/
+                               <&clk_gates4 10>,/*aclk_strc_sys*/
+
+                               /*hclk_cpu_pre*/
+                               <&clk_gates5 6>,/*hclk_rom*/
+
+                               /*pclk_cpu_pre*/
+                               <&clk_gates5 4>,/*pclk_grf*/
+                               <&clk_gates5 7>,/*pclk_ddrupctl*/
+                               <&clk_gates5 14>,/*pclk_acodec*/
+                               <&clk_gates3 8>,/*pclk_hdmi*/
+
+                               /*aclk_peri_pre*/
+                               <&clk_gates4 3>,/*aclk_peri_axi_matrix*/
+                               <&clk_gates5 1>,/*aclk_dmac2*/
+                               <&clk_gates9 15>,/*aclk_peri_niu*/
+                               <&clk_gates4 2>,/*aclk_cpu_peri*/
+
+                               /*hclk_peri_pre*/
+                               <&clk_gates4 0>,/*hclk_peri_matrix*/
+                               <&clk_gates9 13>,/*hclk_usb_peri*/
+                               <&clk_gates9 14>,/*hclk_peri_arbi*/
+
+                               /*pclk_peri_pre*/
+                               <&clk_gates4 1>,/*pclk_peri_axi_matrix*/
+
+                               /*hclk_vio_pre*/
+                               <&clk_gates6 12>,/*hclk_vio_bus*/
+                               <&clk_gates9 5>,/*hclk_lcdc*/
+
+                               /*aclk_vio_pre*/
+                               <&clk_gates6 13>,/*aclk_vio*/
+                               <&clk_gates9 6>,/*aclk_lcdc*/
+
+                               /*UART*/
+                               <&clk_gates1 12>,
+                               <&clk_gates1 13>,
+                               <&clk_gates8 2>,/*pclk_uart2*/
+
+                               <&clk_gpu>,
+
+                               /*jtag*/
+                               <&clk_gates1 3>;/*clk_jtag*/
+       };
+
+       i2c0: i2c@20072000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x20072000 0x1000>;
+               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c0_sda &i2c0_scl>;
+               pinctrl-1 = <&i2c0_gpio>;
+               gpios = <&gpio0 GPIO_A1 GPIO_ACTIVE_LOW>, <&gpio0 GPIO_A0 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 4>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@20056000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x20056000 0x1000>;
+               interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c1_sda &i2c1_scl>;
+               pinctrl-1 = <&i2c1_gpio>;
+               gpios = <&gpio0 GPIO_A3 GPIO_ACTIVE_LOW>, <&gpio0 GPIO_A2 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 5>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@2005a000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x2005a000 0x1000>;
+               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c2_sda &i2c2_scl>;
+               pinctrl-1 = <&i2c2_gpio>;
+               gpios = <&gpio2 GPIO_C4 GPIO_ACTIVE_LOW>, <&gpio2 GPIO_C5 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 6>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2s: i2s@10220000 {
+               compatible = "rockchip-i2s";
+               reg = <0x10220000 0x1000>;
+               i2s-id = <0>;
+               clocks = <&clk_i2s>, <&clk_i2s_out>, <&clk_gates7 2>;
+               clock-names = "i2s_clk","i2s_mclk", "i2s_hclk";
+               interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+               dmas = <&pdma 0>, <&pdma 1>;
+               //#dma-cells = <2>;
+               dma-names = "tx", "rx";
+               //pinctrl-names = "default", "sleep";
+               //pinctrl-0 = <&i2s_mclk &i2s_sclk &i2s_lrckrx &i2s_lrcktx &i2s_sdi &i2s_sdo0 &i2s_sdo1 &i2s_sdo2 &i2s_sdo3>;
+               //pinctrl-1 = <&i2s_gpio>;
+       };
+
+       codec: codec@20030000 {
+               compatible = "rk3036-codec";
+               reg = <0x20030000 0x1000>;
+               spk_ctl_io = <&gpio1 GPIO_A0 0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s0_gpio>;
+
+               boot_depop = <1>;
+               pa_enable_time = <1000>;
+               clocks = <&clk_gates5 14>;
+               clock-names = "g_pclk_acodec";
+       };
+
+       spdif: spdif@10204000 {
+               compatible = "rockchip-spdif";
+               reg = <0x10204000 0x1000>;
+               clocks = <&clk_spdif>;
+               clock-names = "spdif_mclk";
+               interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+               dmas = <&pdma 13>;
+               //#dma-cells = <1>;
+               dma-names = "tx";
+               pinctrl-names = "default";
+               pinctrl-0 = <&spdif_tx>;
+       };
+
+       pwm0: pwm@20050000 {
+               compatible = "rockchip,rk-pwm";
+               reg = <0x20050000 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm0_pin>;
+               clocks = <&clk_gates7 10>;
+               clock-names = "pclk_pwm";
+               status = "disabled";
+       };
+
+       pwm1: pwm@20050010 {
+               compatible = "rockchip,rk-pwm";
+               reg = <0x20050010 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm1_pin>;
+               clocks = <&clk_gates7 10>;
+               clock-names = "pclk_pwm";
+               status = "disabled";
+       };
+
+       pwm2: pwm@20050020 {
+               compatible = "rockchip,rk-pwm";
+               reg = <0x20050020 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm2_pin>;
+               clocks = <&clk_gates7 10>;
+               clock-names = "pclk_pwm";
+               status = "disabled";
+       };
+
+       pwm3: pwm@20050030 {
+               compatible = "rockchip,rk-pwm";
+               reg = <0x20050030 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm3_pin>;
+               clocks = <&clk_gates7 10>;
+               clock-names = "pclk_pwm";
+               status = "disabled";
+       };
+
+       remotectl: pwm@20050030 {
+               compatible = "rockchip,remotectl-pwm";
+               reg = <0x20050030 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm3_pin>;
+               clocks = <&clk_gates7 10>;
+               clock-names = "pclk_pwm";
+               interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+               status = "okay";
+       };
+
+       emmc: rksdmmc@1021c000 {
+               compatible = "rockchip,rk_mmc", "rockchip,rk3036-sdmmc";
+               reg = <0x1021c000 0x4000>;
+               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               //pinctrl-names = "default",,"suspend";
+               //pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_wp &sd0_pwr &sd0_bus1 &sd0_bus4>;
+               clocks = <&clk_emmc>, <&clk_gates7 0>;
+               clock-names = "clk_mmc", "hclk_mmc";
+               dmas = <&pdma 12>;
+               dma-names = "dw_mci";
+               num-slots = <1>;
+               fifo-depth = <0x100>;
+               bus-width = <8>;
+       };
+
+
+       sdmmc: rksdmmc@10214000 {
+               compatible = "rockchip,rk_mmc", "rockchip,rk3036-sdmmc";
+               reg = <0x10214000 0x4000>;
+               interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "idle";
+               pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>;
+               pinctrl-1 = <&sdmmc0_gpio>;
+               cd-gpios = <&gpio1 GPIO_C1 GPIO_ACTIVE_HIGH>;/*CD GPIO*/
+               clocks = <&clk_sdmmc0>, <&clk_gates5 10>;
+               clock-names = "clk_mmc", "hclk_mmc";
+               dmas = <&pdma 10>;
+               dma-names = "dw_mci";
+               num-slots = <1>;
+               fifo-depth = <0x100>;
+               bus-width = <4>;
+       };
+
+       sdio: rksdmmc@10218000 {
+               compatible = "rockchip,rk_mmc", "rockchip,rk3036-sdmmc";
+               reg = <0x10218000 0x4000>;
+               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default","idle";
+               pinctrl-0 = <&sdio0_clk &sdio0_cmd  &sdio0_bus4>;
+               pinctrl-1 = <&sdio0_gpio>;
+               clocks = <&clk_sdio>, <&clk_gates5 11>;
+               clock-names = "clk_mmc", "hclk_mmc";
+               dmas = <&pdma 11>;
+               dma-names = "dw_mci";
+               num-slots = <1>;
+               fifo-depth = <0x100>;
+               bus-width = <4>;
+       };
+       gpu {
+               compatible = "arm,mali400";
+               reg = <0x10091000 0x200>,
+                         <0x10090000 0x100>,
+                         <0x10093000 0x100>,
+                         <0x10098000 0x1100>,
+                         <0x10094000 0x100>;
+               reg-names = "Mali_L2",
+                                       "Mali_GP",
+                                       "Mali_GP_MMU",
+                                       "Mali_PP0",
+                                       "Mali_PP0_MMU";
+
+           interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+           interrupt-names = "Mali_GP_IRQ",
+                                                 "Mali_GP_MMU_IRQ",
+                                                 "Mali_PP0_IRQ",
+                                                 "Mali_PP0_MMU_IRQ";
+         };
+       dwc_control_usb: dwc-control-usb@20008000 {
+               compatible = "rockchip,rk3036-dwc-control-usb";
+               reg = <0x20008000 0x4>;
+               interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "otg_bvalid";
+               clocks = <&clk_gates9 13>;
+               clock-names = "hclk_usb_peri";
+               rockchip,remote_wakeup;
+               rockchip,usb_irq_wakeup;
+               resets = <&reset RK3036_RST_USBPOR>;
+               reset-names = "usbphy_por";
+               usb_bc{
+                       compatible = "rockchip,ctrl";
+                       rk_usb,bvalid   = <0x14c 8 1>;
+                       rk_usb,iddig    = <0x14c 11 1>;
+                       rk_usb,line     = <0x14c 9 2>;
+                       rk_usb,softctrl = <0x17c 0 1>;
+                       rk_usb,opmode   = <0x17c 2 2>;
+                       rk_usb,xcvrsel  = <0x17c 4 2>;
+                       rk_usb,termsel  = <0x17c 6 1>;
+               };
+       };
+       usb0: usb@10180000 {
+               compatible = "rockchip,rk3036_usb20_otg";
+               reg = <0x10180000 0x40000>;
+               interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates1 5>, <&clk_gates5 13>;
+               clock-names = "clk_usbphy0", "hclk_usb0";
+               resets = <&reset RK3036_RST_USBOTG0>, <&reset RK3036_RST_UTMI0>,
+                               <&reset RK3036_RST_OTGC0>;
+               reset-names = "otg_ahb", "otg_phy", "otg_controller";
+               /*0 - Normal, 1 - Force Host, 2 - Force Device*/
+               rockchip,usb-mode = <0>;
+       };
+
+       usb1: usb@101c0000 {
+               compatible = "rockchip,rk3036_usb20_host";
+               reg = <0x101c0000 0x40000>;
+               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates1 6>, <&clk_gates7 3>;
+               clock-names = "clk_usbphy1", "hclk_usb1";
+               resets = <&reset RK3036_RST_USBOTG1>, <&reset RK3036_RST_UTMI1>,
+                               <&reset RK3036_RST_OTGC1>;
+               reset-names = "host_ahb", "host_phy", "host_controller";
+       };
+
+       fb: fb{
+               compatible = "rockchip,rk-fb";
+               rockchip,disp-mode = <NO_DUAL>;
+       };
+
+       rk_screen: rk_screen{
+               compatible = "rockchip,screen";
+       };
+
+       lcdc: lcdc@10118000 {
+               compatible = "rockchip,rk3036-lcdc";
+               reg = <0x10118000 0x200>;
+               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+               clocks = <&clk_gates9 6>, <&dclk_lcdc1>, <&clk_gates9 5>;
+               clock-names = "aclk_lcdc", "dclk_lcdc", "hclk_lcdc";
+               rockchip,iommu-enabled = <1>;
+       };
+
+       hdmi: hdmi@20034000 {
+               compatible = "rockchip,rk3036-hdmi";
+               reg = <0x20034000 0x4000>;
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,hdmi_lcdc_source = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&hdmi_cec &hdmi_sda &hdmi_scl &hdmi_hpd>;
+               pinctrl-1 = <&hdmi_gpio>;
+               clocks = <&clk_gates3 8>;
+               clock-names = "pclk_hdmi";
+               status = "disabled";
+       };
+
+       tve: tve{
+               compatible = "rockchip,rk3036-tve";
+               reg = <0x10118200 0x100>;
+               status = "disabled";
+       };
+
+       ion {
+               compatible = "rockchip,ion";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ion_cma: rockchip,ion-heap@1 { /* CMA HEAP */
+                       compatible = "rockchip,ion-reserve";
+                       rockchip,ion_heap = <1>;
+                       reg = <0x00000000 0x00000000>; /* 0MB */
+               };
+               rockchip,ion-heap@3 { /* VMALLOC HEAP */
+                       rockchip,ion_heap = <3>;
+               };
+       };
+
+        vpu: vpu_service@10108000 {
+               compatible = "vpu_service";
+               reg = <0x10108000 0x800>;
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "irq_dec";
+               clocks = <&aclk_vcodec_pre>, <&clk_gates3 12>;
+               clock-names = "aclk_vcodec", "hclk_vcodec";
+               name = "vpu_service";
+               status = "okay";
+       };
+
+       hevc: hevc_service@1010c000 {
+               compatible = "rockchip,hevc_service";
+               reg = <0x1010c000 0x400>;
+               interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "irq_dec";
+               clocks = <&aclk_vcodec_pre>, <&clk_gates3 12>, <&clk_hevc_core>;
+               clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core";
+               name = "hevc_service";
+               status = "okay";
+        };
+
+       vop_mmu {
+               dbgname = "vop";
+               compatible = "iommu,vop_mmu";
+               reg = <0x10118300 0x100>;
+               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vop_mmu";
+       };
+
+       hevc_mmu {
+               dbgname = "hevc";
+               compatible = "iommu,hevc_mmu";
+               reg = <0x1010c440 0x100>,
+                     <0x1010c480 0x100>;
+               interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "hevc_mmu";
+       };
+
+       vpu_mmu {
+               dbgname = "vpu";
+               compatible = "iommu,vpu_mmu";
+               reg = <0x10108800 0x100>;
+               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vpu_mmu";
+       };
+
+       vmac: eth@10200000 {
+               compatible = "rockchip,vmac";
+               reg = <0x10200000 0x4000>;
+               interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "macirq";
+               clocks = <&clk_mac_pll>, <&clk_mac_ref>,
+                       <&clk_mac_pll_div>, <&clk_mac_ref_div>,
+                       <&clk_gates2 6>, <&clk_gates3 5>;
+                clock-names = "clk_mac_pll", "clk_mac_ref",
+                          "clk_mac_pll_div", "clk_mac_ref_div",
+                          "clk_tx_rx_gate", "hclk_mac";
+                pinctrl-names = "default";
+                pinctrl-0 = <&mac_clk &mac_txpins &mac_rxpins &mac_crs &mac_mdpins>;
+        };
+};
diff --git a/arch/arm/boot/dts/rk3126-fpga.dts b/arch/arm/boot/dts/rk3126-fpga.dts
new file mode 100755 (executable)
index 0000000..b889ffd
--- /dev/null
@@ -0,0 +1,38 @@
+/dts-v1/;
+#include "rk312x.dtsi"
+#include "rk312x-pinctrl.dtsi"
+#include "lcd-td043mgeal.dtsi"
+
+/ {
+       compatible = "rockchip,rk3126";
+
+       memory {
+               device_type = "memory";
+               reg = <0x60000000 0x10000000>;
+       };
+
+       chosen {
+               bootargs = "androidboot.console=ttyFIQ0 initrd=0x62000000,0x00800000";
+       };
+
+       fiq-debugger {
+               status = "okay";
+       };
+
+};
+
+&fb {
+       rockchip,disp-mode = <ONE_DUAL>;
+};
+
+&rk_screen {
+       display-timings = <&disp_timings>;
+};
+
+&lvds {
+       status = "okay";
+};
+
+&lcdc {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3126-sdk.dts b/arch/arm/boot/dts/rk3126-sdk.dts
new file mode 100755 (executable)
index 0000000..5b89f30
--- /dev/null
@@ -0,0 +1,25 @@
+#include "rk312x-sdk.dtsi"
+
+/ {
+        compatible = "rockchip,rk3126";
+        backlight {
+                compatible = "pwm-backlight";
+                pwms = <&pwm0 0 25000>;
+                brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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 = <128>;
+                enable-gpios = <&gpio3 GPIO_C1 GPIO_ACTIVE_HIGH>;
+        };
+};
+
+&lcdc {
+       status = "okay";
+
+       power_ctr: power_ctr {
+               rockchip,debug = <0>;
+               lcd_en: lcd_en {
+                       rockchip,power_type = <GPIO>;
+                       gpios = <&gpio1 GPIO_B3 GPIO_ACTIVE_HIGH>;
+                       rockchip,delay = <10>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/rk3128-box.dts b/arch/arm/boot/dts/rk3128-box.dts
new file mode 100755 (executable)
index 0000000..372e2d0
--- /dev/null
@@ -0,0 +1,6 @@
+#include "rk312x-sdk.dtsi"
+
+/ {
+        compatible = "rockchip,rk3128";
+};
+
diff --git a/arch/arm/boot/dts/rk3128-sdk.dts b/arch/arm/boot/dts/rk3128-sdk.dts
new file mode 100755 (executable)
index 0000000..9c3a47a
--- /dev/null
@@ -0,0 +1,25 @@
+#include "rk312x-sdk.dtsi"
+
+/ {
+        compatible = "rockchip,rk3128";
+        backlight {
+                compatible = "pwm-backlight";
+                pwms = <&pwm0 0 25000>;
+                brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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 = <128>;
+                enable-gpios = <&gpio0 GPIO_D3 GPIO_ACTIVE_HIGH>;
+        };
+};
+
+&lcdc {
+       status = "okay";
+
+       power_ctr: power_ctr {
+               rockchip,debug = <0>;
+               lcd_en: lcd_en {
+                       rockchip,power_type = <GPIO>;
+                       gpios = <&gpio0 GPIO_D1 GPIO_ACTIVE_HIGH>;
+                       rockchip,delay = <10>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/rk312x-clocks.dtsi b/arch/arm/boot/dts/rk312x-clocks.dtsi
new file mode 100755 (executable)
index 0000000..e7b9549
--- /dev/null
@@ -0,0 +1,1898 @@
+/*
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <dt-bindings/clock/rockchip,rk312x.h>
+
+/{
+
+       clocks {
+               compatible = "rockchip,rk-clocks";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x0  0x20000000  0x1f0>;
+
+               fixed_rate_cons {
+                       compatible = "rockchip,rk-fixed-rate-cons";
+
+                       xin24m: xin24m {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "xin24m";
+                               clock-frequency = <24000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       xin12m: xin12m {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clocks = <&xin24m>;
+                               clock-output-names = "xin12m";
+                               clock-frequency = <12000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       gmac_clkin: rmii_clkin {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "gmac_clkin";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       usb480m: usb480m {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "usb480m";
+                               clock-frequency = <480000000>;
+                               #clock-cells = <0>;
+                       };
+
+                       i2s_clkin: i2s_clkin {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "i2s_clkin";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       jtag_tck: jtag_tck {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "jtag_tck";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       pclkin_cif: pclkin_cif {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "pclkin_cif";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       clk_tsp_in: clk_tsp_in {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "clk_tsp_in";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+
+                       dummy: dummy {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "dummy";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+                       dummy_cpll: dummy_cpll {
+                               compatible = "rockchip,rk-fixed-clock";
+                               clock-output-names = "dummy_cpll";
+                               clock-frequency = <0>;
+                               #clock-cells = <0>;
+                       };
+
+               };
+
+               fixed_factor_cons {
+                       compatible = "rockchip,rk-fixed-factor-cons";
+
+                       clk_gpll_div2: clk_gpll_div2 {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&clk_gpll>;
+                               clock-output-names = "clk_gpll_div2";
+                               clock-div = <2>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+                       clk_gpll_div3: clk_gpll_div3 {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&clk_gpll>;
+                               clock-output-names = "clk_gpll_div3";
+                               clock-div = <3>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+                       clk_pvtm_func: clk_pvtm_func {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&xin24m>;
+                               clock-output-names = "clk_pvtm_func";
+                               clock-div = <1>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+                       hclk_vepu: hclk_vepu {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&clk_vepu>;
+                               clock-output-names = "hclk_vepu";
+                               clock-div = <4>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+                       hclk_vdpu: hclk_vdpu {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&clk_vdpu>;
+                               clock-output-names = "hclk_vdpu";
+                               clock-div = <4>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+                       pclkin_cif_inv: pclkin_cif_inv {
+                               compatible = "rockchip,rk-fixed-factor-clock";
+                               clocks = <&clk_gates3 3>;
+                               clock-output-names = "pclkin_cif_inv";
+                               clock-div = <1>;
+                               clock-mult = <1>;
+                               #clock-cells = <0>;
+                       };
+
+               };
+
+               pd_cons {
+                       compatible = "rockchip,rk-pd-cons";
+
+                       pd_gpu: pd_gpu {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_gpu";
+                               rockchip,pd-id = <CLK_PD_GPU>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_video: pd_video {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_video";
+                               rockchip,pd-id = <CLK_PD_VIDEO>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_vio: pd_vio {
+                               compatible = "rockchip,rk-pd-clock";
+                               clock-output-names = "pd_vio";
+                               rockchip,pd-id = <CLK_PD_VIO>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_vop0: pd_vop0 {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_vop0";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_vop1: pd_vop1 {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_vop1";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_vip: pd_vip {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_vip";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_iep: pd_iep {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_iep";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_rga: pd_rga {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_rga";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_ebc: pd_ebc {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_ebc";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_mipidsi: pd_mipidsi {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_mipidsi";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+                       pd_hdmi: pd_hdmi {
+                               compatible = "rockchip,rk-pd-clock";
+                               clocks = <&pd_vio>;
+                               clock-output-names = "pd_hdmi";
+                               rockchip,pd-id = <CLK_PD_VIRT>;
+                               #clock-cells = <0>;
+                       };
+
+               };
+
+
+               clock_regs {
+                       compatible = "rockchip,rk-clock-regs";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x0000 0x01f0>;
+                       ranges;
+
+                       /* PLL control regs */
+                       pll_cons {
+                               compatible = "rockchip,rk-pll-cons";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges ;
+
+                               clk_apll: pll-clk@0000 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0000 0x10>;
+                                       mode-reg = <0x0040 0>;
+                                       status-reg = <0x0004 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_apll";
+                                       rockchip,pll-type = <CLK_PLL_3036_APLL>;
+                                       #clock-cells = <0>;
+                               };
+
+                               clk_dpll: pll-clk@0010 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0010 0x10>;
+                                       mode-reg = <0x0040 4>;
+                                       status-reg = <0x0014 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_dpll";
+                                       rockchip,pll-type = <CLK_PLL_3036PLUS_AUTO>;
+                                       #clock-cells = <0>;
+                               };
+
+                               clk_cpll: pll-clk@0020 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0020 0x10>;
+                                       mode-reg = <0x0040 8>;
+                                       status-reg = <0x0024 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_cpll";
+                                       rockchip,pll-type = <CLK_PLL_312XPLUS>;
+                                       #clock-cells = <0>;
+                                       #clock-init-cells = <1>;
+                               };
+
+                               clk_gpll: pll-clk@0030 {
+                                       compatible = "rockchip,rk3188-pll-clk";
+                                       reg = <0x0030 0x10>;
+                                       mode-reg = <0x0040 12>;
+                                       status-reg = <0x0034 10>;
+                                       clocks = <&xin24m>;
+                                       clock-output-names = "clk_gpll";
+                                       rockchip,pll-type = <CLK_PLL_3036PLUS_AUTO>;
+                                       #clock-cells = <0>;
+                                       #clock-init-cells = <1>;
+                               };
+
+                       };
+
+                       /* Select control regs */
+                       clk_sel_cons {
+                               compatible = "rockchip,rk-sel-cons";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges;
+
+                               clk_sel_con0: sel-con@0044 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0044 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_core_div: clk_core_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_core>;
+                                               clock-output-names = "clk_core";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_CORE>;
+                                               rockchip,flags = <(CLK_GET_RATE_NOCACHE |
+                                                                       CLK_SET_RATE_NO_REPARENT)>;
+                                       };
+
+                                       /* reg[6:5]: reserved */
+
+                                       clk_core: clk_core_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <7 1>;
+                                               clocks = <&clk_apll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_core";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       aclk_cpu_div: aclk_cpu_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&aclk_cpu>;
+                                               clock-output-names = "aclk_cpu";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       aclk_cpu: aclk_cpu_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <13 2>;
+                                               clocks = <&clk_apll>, <&clk_gpll>,<&clk_gpll_div2>,<&clk_gpll_div3>;
+                                               clock-output-names = "aclk_cpu";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+                                       
+                                       /* reg[15]: reserved */
+
+                               };
+
+                               clk_sel_con1: sel-con@0048 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0048 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       pclk_dbg_div:  pclk_dbg_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 4>;
+                                               clocks = <&clk_core>;
+                                               clock-output-names = "pclk_dbg";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_CORE_CHILD>;
+                                       };
+
+                                       aclk_core_pre: aclk_core_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <4 3>;
+                                               clocks = <&clk_core>;
+                                               clock-output-names = "aclk_core_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_CORE_CHILD>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       hclk_cpu_pre: hclk_cpu_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&aclk_cpu>;
+                                               clock-output-names = "hclk_cpu_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       pclk_cpu_pre: pclk_cpu_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <12 3>;
+                                               clocks = <&aclk_cpu>;
+                                               clock-output-names = "pclk_cpu_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15]: reserved */
+                               };
+
+                               clk_sel_con2: sel-con@004c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x004c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_pvtm_div: clk_pvtm_div {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_pvtm_func>;
+                                               clock-output-names = "clk_pvtm";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_nandc_div: clk_nandc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&clk_nandc>;
+                                               clock-output-names = "clk_nandc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };
+
+                                       /* reg[13]: reserved */
+       
+                                       clk_nandc: clk_nandc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_nandc";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con3: sel-con@0050 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0050 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_i2s_2ch_pll_div: clk_i2s_2ch_pll_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_i2s_2ch_pll>;
+                                               clock-output-names = "clk_i2s_2ch_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_i2s_2ch: clk_i2s_2ch_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_i2s_2ch_pll_div>, <&i2s_2ch_frac>, <&i2s_clkin>, <&xin12m>;
+                                               clock-output-names = "clk_i2s_2ch";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       clk_i2s_2ch_out: clk_i2s_2ch_out_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <12 1>;
+                                               clocks = <&clk_i2s_2ch>, <&xin12m>;
+                                               clock-output-names = "i2s_clkout";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       clk_i2s_2ch_pll: i2s_2ch_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_i2s_2ch_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con4: sel-con@0054 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0054 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_tsp_div: clk_tsp_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_tsp>;
+                                               clock-output-names = "clk_tsp";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };
+
+                                       /* reg[5]: reserved */
+       
+                                       clk_tsp: clk_tsp_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <6 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_tsp";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_24m_div: clk_24m_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&xin24m>;
+                                               clock-output-names = "clk_24m";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[15:13]: reserved */
+                                       
+                               };
+
+
+                               clk_sel_con5: sel-con@0058 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0058 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_mac_pll_div: clk_mac_pll_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_mac_pll>;
+                                               clock-output-names = "clk_mac_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[5]: reserved */
+
+                                       clk_mac_pll: clk_mac_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <6 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_mac_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[14:8]: reserved */
+
+                                       clk_mac_ref: clk_mac_ref_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <15 1>;
+                                               clocks = <&clk_mac_pll_div>, <&gmac_clkin>;
+                                               clock-output-names = "clk_mac_ref";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MAC_REF>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+                               
+                               
+                               clk_sel_con6: sel-con@005c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x005c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       spdif_div: spdif_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_spdif_pll>;
+                                               clock-output-names = "clk_spdif_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_spdif: spdif_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&spdif_div>, <&spdif_frac>, <&xin12m>;
+                                               clock-output-names = "clk_spdif";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+                                       
+                                       /* reg[13:10]: reserved */
+
+                                       clk_spdif_pll: spdif_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_spdif_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con7: sel-con@0060 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0060 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       i2s_2ch_frac: i2s_2ch_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_i2s_2ch_pll>;
+                                               clock-output-names = "i2s_2ch_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con8: sel-con@0064 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0064 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       i2s_8ch_frac: i2s_8ch_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_i2s_8ch_pll>;
+                                               clock-output-names = "i2s_8ch_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con9: sel-con@0068 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0068 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_i2s_8ch_pll_div: clk_i2s_8ch_pll_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_i2s_8ch_pll>;
+                                               clock-output-names = "clk_i2s_8ch_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_i2s_8ch: clk_i2s_8ch_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_i2s_8ch_pll_div>, <&i2s_8ch_frac>, <&i2s_clkin>, <&xin12m>;
+                                               clock-output-names = "clk_i2s_8ch";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[13:10]: reserved */
+
+                                       clk_i2s_8ch_pll: i2s_8ch_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "clk_i2s_8ch_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con10: sel-con@006c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x006c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       aclk_peri_div: aclk_peri_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&aclk_peri>;
+                                               clock-output-names = "aclk_peri";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[7:5]: reserved */
+
+                                       hclk_peri_pre: hclk_peri_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&aclk_peri>;
+                                               clock-output-names = "hclk_peri_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_USER_DEFINE>;
+                                               rockchip,div-relations =
+                                                               <0x0 1
+                                                                0x1 2
+                                                                0x2 4>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       pclk_peri_pre: pclk_peri_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <12 2>;
+                                               clocks = <&aclk_peri>;
+                                               clock-output-names = "pclk_peri_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_USER_DEFINE>;
+                                               rockchip,div-relations =
+                                                               <0x0 1
+                                                                0x1 2
+                                                                0x2 4
+                                                                0x3 8>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       aclk_peri: aclk_peri_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_gpll>,<&clk_cpll>,<&clk_gpll_div2>,<&clk_gpll_div3>;
+                                               clock-output-names = "aclk_peri";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+                               };
+
+                               clk_sel_con11: sel-con@0070 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0070 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_sdmmc0_div: clk_sdmmc0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 6>;
+                                               clocks = <&clk_sdmmc0>;
+                                               clock-output-names = "clk_sdmmc0";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       clk_sdmmc0: clk_sdmmc0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <6 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>,<&clk_gpll_div2>,<&xin24m>;
+                                               clock-output-names = "clk_sdmmc0";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_sfc_div: clk_sfc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&clk_sfc>;
+                                               clock-output-names = "clk_sfc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       clk_sfc: clk_sfc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>,<&clk_gpll_div2>,<&xin24m>;
+                                               clock-output-names = "clk_sfc";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con12: sel-con@0074 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0074 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_sdio_div: clk_sdio_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 6>;
+                                               clocks = <&clk_sdio>;
+                                               clock-output-names = "clk_sdio";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       clk_sdio: clk_sdio_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <6 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>, <&xin24m>;
+                                               clock-output-names = "clk_sdio";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_emmc_div: clk_emmc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 6>;
+                                               clocks = <&clk_emmc>;
+                                               clock-output-names = "clk_emmc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_EVENDIV>;
+                                       };
+
+                                       clk_emmc: clk_emmc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>, <&xin24m>;
+                                               clock-output-names = "clk_emmc";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con13: sel-con@0078 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0078 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_uart0_pll_div: clk_uart0_pll_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_uart0_pll>;
+                                               clock-output-names = "clk_uart0_pll";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_uart0: clk_uart0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_uart0_pll>, <&uart0_frac>, <&xin24m>;
+                                               clock-output-names = "clk_uart0";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[11:10]: reserved */
+
+                                       clk_uart0_pll: clk_uart0_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <12 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>, <&usb480m>;
+                                               clock-output-names = "clk_uart0_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_uart2_pll: clk_uart2_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>, <&usb480m>;
+                                               clock-output-names = "clk_uart2_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con14: sel-con@007c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x007c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_uart1_div: clk_uart1_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_uart2_pll>;
+                                               clock-output-names = "clk_uart1_div";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_uart1: clk_uart1_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_uart1_div>, <&uart1_frac>, <&xin24m>;
+                                               clock-output-names = "clk_uart1";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+                               };
+
+                               clk_sel_con15: sel-con@0080 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0080 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_uart2_div: clk_uart2_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_uart2_pll>;
+                                               clock-output-names = "clk_uart2_div";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_uart2: clk_uart2_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_uart2_div>, <&uart2_frac>, <&xin24m>;
+                                               clock-output-names = "clk_uart2";
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_RK3288_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+                               };
+
+                               clk_sel_con17: sel-con@0088 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0088 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       uart0_frac: uart0_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_uart0_pll>;
+                                               clock-output-names = "uart0_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con18: sel-con@008c {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x008c 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       uart1_frac: uart1_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_uart1_div>;
+                                               clock-output-names = "uart1_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+                               };
+
+                               clk_sel_con19: sel-con@0090 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0090 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       uart2_frac: uart2_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&clk_uart2_div>;
+                                               clock-output-names = "uart2_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+
+                               };
+
+                               clk_sel_con20: sel-con@0094 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x0094 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       spdif_frac: spdif_frac {
+                                               compatible = "rockchip,rk3188-frac-con";
+                                               clocks = <&spdif_div>;
+                                               clock-output-names = "spdif_frac";
+                                               /* numerator    denominator */
+                                               rockchip,bits = <0 32>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_FRAC>;
+                                               #clock-cells = <0>;
+                                       };
+
+                               };
+
+                               clk_sel_con23: sel-con@00a0 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00a0 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       
+                                       dclk_ebc: dclk_ebc_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_cpll>,<&clk_gpll>, <&clk_gpll_div2>;
+                                               clock-output-names = "dclk_ebc";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[7:2]: reserved */
+
+                                       dclk_ebc_div: dclk_ebc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 8>;
+                                               clocks = <&dclk_ebc>;
+                                               clock-output-names = "dclk_ebc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };      
+                               
+                               };
+
+                               clk_sel_con24: sel-con@00a4 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00a4 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       
+                                       clk_crypto_div: clk_crypto_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&aclk_cpu>;
+                                               clock-output-names = "clk_crypto";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };      
+
+                                       /* reg[7:2]: reserved */
+
+                                       clk_saradc: clk_saradc_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 8>;
+                                               clocks = <&xin24m>;
+                                               clock-output-names = "clk_saradc";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };      
+                               
+                               };
+
+                               clk_sel_con25: sel-con@00a8 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00a8 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_spi0_div: clk_spi0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 7>;
+                                               clocks = <&clk_spi0>;
+                                               clock-output-names = "clk_spi0";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                       };
+
+                                       /* reg[7]: reserved */
+
+                                       clk_spi0: clk_spi0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>,<&clk_gpll_div2>;
+                                               clock-output-names = "clk_spi0";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[15:10]: reserved */
+
+                               };
+
+                               clk_sel_con26: sel-con@00ac {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00ac 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       ddr_div: ddr_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_ddr>;
+                                               clock-output-names = "clk_ddr";
+                                               rockchip,div-type = <CLK_DIVIDER_USER_DEFINE>;
+                                               rockchip,div-relations =
+                                                               <0x0 1
+                                                                0x1 2
+                                                                0x3 4>;
+                                               #clock-cells = <0>;
+                                               rockchip,flags = <(CLK_GET_RATE_NOCACHE |
+                                                                       CLK_SET_RATE_NO_REPARENT)>;
+                                               rockchip,clkops-idx = <CLKOPS_RATE_DDR>;
+                                       };
+
+                                       /* reg[7:2]: reserved */
+
+                                       clk_ddr: ddr_clk_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <8 1>;
+                                               clocks = <&clk_dpll>, <&dummy>;
+                                               clock-output-names = "clk_ddr";
+                                               #clock-cells = <0>;
+                                       };
+
+                                       /* reg[15:9]: reserved */
+                               };
+
+                               clk_sel_con27: sel-con@00b0 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00b0 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       dclk_lcdc0: dclk_lcdc0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>;
+                                               clock-output-names = "dclk_lcdc0";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[7:2]: reserved */
+
+                                       dclk_lcdc0_div: dclk_lcdc0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 8>;
+                                               clocks = <&dclk_lcdc0>;
+                                               clock-output-names = "dclk_lcdc0";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+                               };
+
+                               clk_sel_con28: sel-con@00b4 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00b4 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       sclk_lcdc0: sclk_lcdc0_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>;
+                                               clock-output-names = "sclk_lcdc0";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[7:2]: reserved */
+
+                                       sclk_lcdc0_div: sclk_lcdc0_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 8>;
+                                               clocks = <&sclk_lcdc0>;
+                                               clock-output-names = "sclk_lcdc0";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+                               };
+
+                               clk_sel_con29: sel-con@00b8 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00b8 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_cif_pll: clk_cif_pll_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <0 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&usb480m>;
+                                               clock-output-names = "clk_cif_pll";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_cif_out_div: clk_cif_out_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <2 5>;
+                                               clocks = <&clk_cif_out>;
+                                               clock-output-names = "clk_cif_out";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       clk_cif_out: clk_cif_out_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <7 1>;
+                                               clocks = <&clk_cif_pll>, <&xin24m>;
+                                               clock-output-names = "clk_cif_out";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       pclk_pmu_pre: pclk_pmu_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 6>;
+                                               clocks = <&clk_cpll>;
+                                               clock-output-names = "pclk_pmu_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[15:14]: reserved */
+                               };
+
+                               clk_sel_con30: sel-con@00bc {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00bc 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_testout_div: clk_testout_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&dummy>;
+                                               clock-output-names = "clk_testout";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       /* reg[6:5]: reserved */
+
+                                       clk_cif0_in: clk_cif0_in_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <7 1>;
+                                               clocks = <&pclkin_cif>, <&pclkin_cif_inv>;
+                                               clock-output-names = "clk_cif0_in";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       hclk_vio_pre_div: hclk_vio_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&hclk_vio_pre>;
+                                               clock-output-names = "hclk_vio_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       /* reg[13]: reserved */
+
+                                       hclk_vio_pre: hclk_vio_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <14 2>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&usb480m>;
+                                               clock-output-names = "hclk_vio_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con31: sel-con@00c0 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00c0 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       aclk_vio0_pre_div: aclk_vio0_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&aclk_vio0_pre>;
+                                               clock-output-names = "aclk_vio0_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       aclk_vio0_pre: aclk_vio0_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <5 3>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>, <&usb480m>;
+                                               clock-output-names = "aclk_vio0_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       aclk_vio1_pre_div: aclk_vio1_pre_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&aclk_vio1_pre>;
+                                               clock-output-names = "aclk_vio1_pre";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       aclk_vio1_pre: aclk_vio1_pre_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <13 3>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>, <&usb480m>;
+                                               clock-output-names = "aclk_vio1_pre";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con32: sel-con@00c4 {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00c4 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_vepu_div: clk_vepu_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_vepu>;
+                                               clock-output-names = "clk_vepu";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       clk_vepu: clk_vepu_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <5 3>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>, <&usb480m>;
+                                               clock-output-names = "clk_vepu";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_vdpu_div: clk_vdpu_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&clk_vdpu>;
+                                               clock-output-names = "clk_vdpu";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       clk_vdpu: clk_vdpu_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <13 3>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>, <&usb480m>;
+                                               clock-output-names = "clk_vdpu";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                               clk_sel_con34: sel-con@00cc {
+                                       compatible = "rockchip,rk3188-selcon";
+                                       reg = <0x00cc 0x4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       clk_gpu_div: clk_gpu_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <0 5>;
+                                               clocks = <&clk_gpu>;
+                                               clock-output-names = "clk_gpu";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT_IN_ORDER>;
+                                       };
+
+                                       clk_gpu: clk_gpu_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <5 3>;
+                                               clocks = <&dummy_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>, <&usb480m>;
+                                               clock-output-names = "clk_gpu";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                                       clk_hevc_core_div: clk_hevc_core_div {
+                                               compatible = "rockchip,rk3188-div-con";
+                                               rockchip,bits = <8 5>;
+                                               clocks = <&clk_hevc_core>;
+                                               clock-output-names = "clk_hevc_core";
+                                               rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               #clock-cells = <0>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
+                                               rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
+                                       };
+
+                                       clk_hevc_core: clk_hevc_core_mux {
+                                               compatible = "rockchip,rk3188-mux-con";
+                                               rockchip,bits = <13 3>;
+                                               clocks = <&clk_cpll>, <&clk_gpll>, <&clk_gpll_div2>, <&clk_gpll_div3>, <&usb480m>;
+                                               clock-output-names = "clk_hevc_core";
+                                               #clock-cells = <0>;
+                                               #clock-init-cells = <1>;
+                                       };
+
+                               };
+
+                       };
+
+
+                       /* Gate control regs */
+                       clk_gate_cons {
+                               compatible = "rockchip,rk-gate-cons";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges ;
+
+                               clk_gates0: gate-clk@00d0{
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00d0 0x4>;
+                                       clocks =
+                                               <&clk_core>,            <&dummy>,
+                                               <&dummy>,       <&aclk_cpu>,
+
+                                               <&aclk_cpu>,    <&aclk_cpu>,
+                                               <&dummy>,               <&clk_core>,
+
+                                               <&dummy>,       <&clk_i2s_2ch_pll>,
+                                               <&i2s_2ch_frac>,        <&hclk_vio_pre>,
+
+                                               <&aclk_cpu>,            <&clk_i2s_2ch_out>,
+                                               <&clk_i2s_2ch>,         <&dummy>;
+
+                                       clock-output-names =
+                                               "pclk_dbg",                     "aclk_cpu",      /*clk_cpu_cpll*/
+                                               "clk_ddr",              "aclk_cpu_pre",
+
+                                               "hclk_cpu_pre",         "pclk_cpu_pre",
+                                               "clk_core",             "aclk_core_pre",
+
+                                               "reserved",             "clk_i2s_2ch_pll",
+                                               "i2s_2ch_frac",         "hclk_vio_pre",
+
+                                               "clk_crypto",           "clk_i2s_2ch_out",
+                                               "clk_i2s_2ch",          "clk_testout";
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates1: gate-clk@00d4{
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00d4 0x4>;
+                                       clocks =
+                                               <&clk_cpll>,            <&dummy>,
+                                               <&dummy>,               <&jtag_tck>,
+
+                                               <&aclk_vio1_pre>,               <&xin12m>,
+                                               <&xin12m>,              <&clk_mac_pll>,
+
+                                               <&clk_uart0_pll>,               <&uart0_frac>,
+                                               <&clk_uart1_div>,               <&uart1_frac>,
+
+                                               <&clk_uart2_div>,               <&uart2_frac>,
+                                               <&clk_tsp>,             <&dummy>;
+
+                                       clock-output-names =
+                                               "pclk_pmu_pre",         "reserved",
+                                               "reserved",             "clk_jtag",
+
+                                               "aclk_vio1_pre",                "clk_otgphy0",
+                                               "clk_otgphy1",                  "clk_mac_pll",
+
+                                               "clk_uart0_pll",        "uart0_frac",
+                                               "clk_uart1_div",        "uart1_frac",
+
+                                               "clk_uart2_div",        "uart2_frac",
+                                               "clk_tsp",      "reserved";
+
+                                        rockchip,suspend-clkgating-setting=<0x0 0x0>;
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates2: gate-clk@00d8 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00d8 0x4>;
+                                       clocks =
+                                               <&aclk_peri>,           <&aclk_peri>,
+                                               <&aclk_peri>,           <&aclk_peri>,
+
+                                               <&clk_mac_ref>,         <&clk_mac_ref>,
+                                               <&clk_mac_ref>,         <&clk_mac_ref>,
+
+                                               <&clk_saradc>,          <&clk_spi0>,
+                                               <&clk_spdif_pll>,               <&clk_sdmmc0>,
+
+                                               <&spdif_frac>,          <&clk_sdio>,
+                                               <&clk_emmc>,            <&xin24m>;
+                                       clock-output-names =
+                                               "aclk_peri",            "aclk_peri_pre",
+                                               "hclk_peri_pre",                "pclk_peri_pre",
+
+                                               "clk_mac_ref",          "clk_mac_refout",
+                                               "clk_mac_rx",           "clk_mac_tx",
+
+                                               "clk_saradc",           "clk_spi0",
+                                               "clk_spdif_pll",                "clk_sdmmc0",
+
+                                               "spdif_frac",           "clk_sdio",
+                                               "clk_emmc",             "clk_mipi_24m";
+                                           rockchip,suspend-clkgating-setting=<0x0 0x0>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates3: gate-clk@00dc {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00dc 0x4>;
+                                       clocks =
+                                               <&aclk_vio0_pre>,               <&dclk_lcdc0>,
+                                               <&sclk_lcdc0>,          <&pclkin_cif>,
+
+                                               <&dclk_ebc>,                    <&hclk_cpu_pre>,
+                                               <&hclk_peri_pre>,               <&clk_cif_pll>,
+
+                                               <&pclk_cpu_pre>,                <&clk_vepu>,
+                                               <&clk_hevc_core>,               <&clk_vdpu>,
+
+                                               <&hclk_vdpu>,           <&clk_gpu>,
+                                               <&aclk_peri>,           <&clk_sfc>;
+
+                                       clock-output-names =
+                                               "aclk_vio0_pre",                "dclk_lcdc0",
+                                               "sclk_lcdc0",           "pclkin_cif",
+
+                                               "dclk_ebc",             "g_hclk_crypto",
+                                               "g_hclk_em_peri",               "clk_cif_pll",
+
+                                               "g_pclk_hdmi",          "clk_vepu",
+                                               "clk_hevc_core",                "clk_vdpu",
+
+                                               "hclk_vdpu",            "clk_gpu",
+                                               "g_hclk_gps",           "clk_sfc";
+                                       rockchip,suspend-clkgating-setting=<0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates4: gate-clk@00e0{
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00e0 0x4>;
+                                       clocks =
+                                               <&hclk_peri_pre>,               <&pclk_peri_pre>,
+                                               <&aclk_peri>,           <&aclk_peri>,
+
+                                               <&clk_i2s_8ch_pll>,             <&i2s_8ch_frac>,
+                                               <&clk_i2s_8ch>,         <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&aclk_cpu>,            <&dummy>,
+
+                                               <&aclk_cpu>,            <&dummy>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "g_hp_axi_matrix",              "g_pp_axi_matrix",
+                                               "g_aclk_cpu_peri",              "g_ap_axi_matrix",
+
+                                               "clk_i2s_8ch_pll",              "i2s_8ch_frac",
+                                               "clk_i2s_8ch",          "reserved",
+
+                                               "reserved",             "reserved",
+                                               "g_aclk_strc_sys",              "reserved",
+
+                                               /* Not use these ddr gates */
+                                               "g_aclk_intmem",                "reserved",
+                                               "reserved",             "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates5: gate-clk@00e4 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00e4 0x4>;
+                                       clocks =
+                                               <&pclk_cpu_pre>,                <&aclk_peri>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&pclk_cpu_pre>,                <&dummy>,
+                                               <&hclk_cpu_pre>,                <&pclk_cpu_pre>,
+
+                                               <&dummy>,               <&hclk_peri_pre>,
+                                               <&hclk_peri_pre>,               <&hclk_peri_pre>,
+
+                                               <&dummy>,               <&hclk_peri_pre>,
+                                               <&pclk_cpu_pre>,                <&dummy>;
+
+                                       clock-output-names =
+                                               "g_pclk_mipiphy",               "g_aclk_dmac",
+                                               "g_pclk_efuse", "reserved",
+
+                                               "g_pclk_grf",           "reserved",
+                                               "g_hclk_rom",           "g_pclk_ddrupctl",
+
+                                               "reserved",             "g_hclk_nandc",
+                                               "g_hclk_sdmmc0",                "g_hclk_sdio",
+
+                                               "reserved",             "g_hclk_otg0",
+                                               "g_pclk_acodec",                "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates6: gate-clk@00e8 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00e8 0x4>;
+                                       clocks =
+                                               <&aclk_vio0_pre>,               <&hclk_vio_pre>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&hclk_vio_pre>,                <&aclk_vio0_pre>,
+                                               <&dummy>,               <&dummy>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&hclk_vio_pre>,                        <&aclk_vio0_pre>,
+
+                                               <&hclk_vio_pre>,                <&aclk_vio0_pre>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "g_aclk_lcdc0",         "g_hclk_lcdc0",
+                                               "reserved",             "reserved",
+
+                                               "g_hclk_cif",           "g_aclk_cif",
+                                               "reserved",             "reserved",
+
+                                               "reserved",             "reserved",
+                                               "g_hclk_rga",           "g_aclk_rga",
+
+                                               "g_hclk_vio_bus",               "g_aclk_vio",
+                                               "reserved",             "reserved";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates7: gate-clk@00ec {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00ec 0x4>;
+                                       clocks =
+                                               <&hclk_peri_pre>,               <&hclk_peri_pre>,
+                                               <&hclk_peri_pre>,               <&hclk_peri_pre>,
+
+                                               <&hclk_peri_pre>,               <&dummy>,
+                                               <&dummy>,               <&pclk_peri_pre>,
+
+                                               <&dummy>,               <&dummy>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&pclk_peri_pre>,               <&dummy>,
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>;
+
+                                       clock-output-names =
+                                               "g_hclk_emmc",          "g_hclk_sfc",
+                                               "g_hclk_i2s_2ch",               "g_hclk_host",
+
+                                               "g_hclk_i2s_8ch",               "reserved",
+                                               "reserved",             "g_pclk_timer",
+
+                                               "reserved",             "reserved",
+                                               "g_pclk_pwm",           "reserved",
+
+                                               "g_pclk_spi0",          "reserved",
+                                               "g_pclk_saradc",                "g_pclk_wdt";
+
+                                       rockchip,suspend-clkgating-setting = <0x0000 0x0000>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates8: gate-clk@00f0 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00f0 0x4>;
+                                       clocks =
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&dummy>,
+
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+
+                                               <&dummy>,               <&pclk_peri_pre>,
+                                               <&pclk_peri_pre>,               <&pclk_peri_pre>,
+
+                                               <&pclk_peri_pre>,               <&dummy>,
+                                               <&dummy>,               <&dummy>;
+
+                                       clock-output-names =
+                                               "g_pclk_uart0",         "g_pclk_uart1",
+                                               "g_pclk_uart2",         "reserved",
+
+                                               "g_pclk_i2c0",          "g_pclk_i2c1",
+                                               "g_pclk_i2c2",          "g_pclk_i2c3",
+
+                                               "reserved",             "g_pclk_gpio0",
+                                               "g_pclk_gpio1",         "g_pclk_gpio2",
+
+                                               "g_pclk_gpio3",         "reserved",
+                                               "reserved",             "reserved";
+
+                                        rockchip,suspend-clkgating-setting=<0x0000 0x0000>;
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates9: gate-clk@00f4 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00f4 0x4>;
+                                       clocks =
+                                               <&dummy>,               <&dummy>,
+                                               <&pclk_pmu_pre>,                <&pclk_pmu_pre>,
+
+                                               <&dummy>,               <&hclk_vio_pre>,
+                                               <&hclk_vio_pre>,                <&hclk_vio_pre>,
+
+                                               <&aclk_vio1_pre>,               <&hclk_vio_pre>,
+                                               <&aclk_vio1_pre>,               <&dummy>,
+
+                                               <&pclk_peri_pre>,               <&hclk_peri_pre>,
+                                               <&hclk_peri_pre>,               <&aclk_peri>;
+
+                                       clock-output-names =
+                                               "reserved",             "reserved",
+                                               "g_pclk_pmu",           "g_pclk_pmu_noc",
+
+                                               "reserved",             "g_hclk_vio_h2p",
+                                               "g_pclk_mipi",          "g_hclk_iep",
+
+                                               "g_aclk_iep",           "g_hclk_ebc",
+                                               "g_aclk_vio1_niu",              "reserved",
+
+                                               "g_pclk_sim_card",              "g_hclk_usb_peri",
+                                               "g_hclk_pe_arbi",               "g_aclk_peri_niu";
+
+                                       rockchip,suspend-clkgating-setting=<0x0 0x0>;
+
+                                       #clock-cells = <1>;
+                               };
+
+                               clk_gates10: gate-clk@00f8 {
+                                       compatible = "rockchip,rk3188-gate-clk";
+                                       reg = <0x00f8 0x4>;
+                                       clocks =
+                                               <&xin24m>,              <&xin24m>,
+                                               <&xin24m>,              <&xin24m>,
+
+                                               <&xin24m>,              <&xin24m>,
+                                               <&xin24m>,              <&xin24m>,
+
+                                               <&xin24m>,              <&hclk_peri_pre>,
+                                               <&aclk_peri>,           <&pclk_peri_pre>,
+
+                                               <&hclk_peri_pre>,               <&clk_tsp_in>,
+                                               <&hclk_peri_pre>,               <&clk_nandc>;
+
+                                       clock-output-names =
+                                               "clk_pvtm_core",                "clk_pvtm_gpu",
+                                               "clk_pvtm_func",                "clk_timer0",
+
+                                               "clk_timer1",           "clk_timer2",
+                                               "clk_timer3",           "clk_timer4",
+
+                                               "clk_timer5",           "g_hclk_spdif",
+                                               "g_aclk_gmac",          "g_pclk_gmac",
+
+                                               "g_hclk_tsp",           "g_clkin0_tsp",
+                                               "g_hclk_usbhost",               "clk_nandc";
+
+                                       rockchip,suspend-clkgating-setting = <0x0 0x0>; /* pwm logic vol */
+
+                                       #clock-cells = <1>;
+                               };
+
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/rk312x-pinctrl.dtsi b/arch/arm/boot/dts/rk312x-pinctrl.dtsi
new file mode 100755 (executable)
index 0000000..16c7b42
--- /dev/null
@@ -0,0 +1,866 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/pinctrl/rockchip-rk312x.h>
+
+/ { 
+       pinctrl: pinctrl@20008000 {
+               compatible = "rockchip,rk312x-pinctrl";
+               reg = <0x20008000 0xA8>,
+                     <0x200080A8 0x4C>,
+                     <0x20008118 0x20>,
+                     <0x20008100 0x04>;
+               reg-names = "base", "mux", "pull", "drv";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gpio0: gpio0@2007c000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x2007c000 0x100>;
+                       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 9>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio1@20080000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20080000 0x100>;
+                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 10>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio2@20084000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20084000 0x100>;
+                       interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 11>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio3: gpio3@20088000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20088000 0x100>;
+                       interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 12>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio15: gpio15@2008A000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x20086000 0x100>;
+                       interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;//127 = 160-32-1
+                       clocks = <&clk_gates8 12>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               pcfg_pull_up: pcfg_pull_up {
+                       bias-pull-up;
+               };
+
+               pcfg_pull_down: pcfg_pull_down {
+                       bias-pull-down;
+               };
+
+               pcfg_pull_none: pcfg_pull_none {
+                       bias-disable;
+               };
+
+               gpio0_uart0 {
+                       uart0_xfer: uart0-xfer {
+                               rockchip,pins = <UART0_SIN>,
+                                               <UART0_SOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart0_cts: uart0-cts {
+                               rockchip,pins = <UART0_CTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart0_rts: uart0-rts {
+                               rockchip,pins = <UART0_RTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart0_rts_gpio: uart0-rts-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(UART0_RTSN)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+
+               gpio1_uart1 {
+                       uart1_xfer: uart1-xfer {
+                               rockchip,pins = <UART1_SIN>,
+                                               <UART1_SOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart1_cts: uart1-cts {
+                               rockchip,pins = <UART1_CTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart1_rts: uart1-rts {
+                               rockchip,pins = <UART1_RTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart1_rts_gpio: uart1-rts-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(UART1_RTSN)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+               
+               gpio1_uart2 {
+                       uart2_xfer: uart2-xfer {
+                               rockchip,pins = <UART2_SIN>,
+                                               <UART2_SOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart2_cts: uart2-cts {
+                               rockchip,pins = <UART2_CTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart2_rts: uart2-rts {
+                               rockchip,pins = <UART2_RTSN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       uart2_rts_gpio: uart2-rts-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(UART2_RTSN)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+
+
+               gpio0_i2c0 {
+                       i2c0_sda:i2c0-sda {
+                               rockchip,pins = <I2C0_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c0_scl:i2c0-scl {
+                               rockchip,pins = <I2C0_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c0_gpio: i2c0-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C0_SDA)>, <FUNC_TO_GPIO(I2C0_SCL)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+
+               gpio0_i2c1 {
+                       i2c1_sda:i2c1-sda {
+                               rockchip,pins = <I2C1_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c1_scl:i2c1-scl {
+                               rockchip,pins = <I2C1_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c1_gpio: i2c1-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C1_SDA)>, <FUNC_TO_GPIO(I2C1_SCL)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+
+               gpio1_i2c2 {
+                       i2c2_sda:i2c2-sda {
+                               rockchip,pins = <I2C2_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c2_scl:i2c2-scl {
+                               rockchip,pins = <I2C2_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c2_gpio: i2c2-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C2_SDA)>, <FUNC_TO_GPIO(I2C2_SCL)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+
+
+               gpio0_i2c3 {
+                       i2c3_sda:i2c3-sda {
+                               rockchip,pins = <I2C3_SDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c3_scl:i2c3-scl {
+                               rockchip,pins = <I2C3_SCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                               
+                       };
+
+                       i2c3_gpio: i2c3-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(I2C3_SDA)>, <FUNC_TO_GPIO(I2C3_SCL)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+
+               
+
+               gpio1_spi0 {
+                       spi0_txd_mux0:spi0-txd-mux0 {
+                               rockchip,pins = <SPI0_TXD_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_rxd_mux0:spi0-rxd-mux0 {
+                               rockchip,pins = <SPI0_RXD_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_clk_mux0:spi0-clk-mux0 {
+                               rockchip,pins = <SPI0_CLK_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_cs0_mux0:spi0-cs0-mux0 {
+                               rockchip,pins = <SPI0_CS0_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_cs1_mux0:spi0-cs1-mux0 {
+                               rockchip,pins = <SPI0_CS1_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+
+
+                       spi0_txd_mux1:spi0-txd-mux1 {
+                               rockchip,pins = <SPI0_TXD_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_rxd_mux1:spi0-rxd-mux1 {
+                               rockchip,pins = <SPI0_RXD_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_clk_mux1:spi0-clk-mux1 {
+                               rockchip,pins = <SPI0_CLK_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_cs0_mux1:spi0-cs0-mux1 {
+                               rockchip,pins = <SPI0_CS0_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_cs1_mux1:spi0-cs1-mux1 {
+                               rockchip,pins = <SPI0_CS1_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+
+                       
+                       spi0_txd_mux2:spi0-txd-mux2 {
+                               rockchip,pins = <SPI0_TXD_MUX2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_rxd_mux2:spi0-rxd-mux2 {
+                               rockchip,pins = <SPI0_RXD_MUX2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_clk_mux2:spi0-clk-mux2 {
+                               rockchip,pins = <SPI0_CLK_MUX2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       spi0_cs0_mux2:spi0-cs0-mux2 {
+                               rockchip,pins = <SPI0_CS0_MUX2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+               };
+
+               gpio1_hdmi {
+                       hdmi_cec:hdmi-cec {
+                               rockchip,pins = <HDMI_CEC>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       hdmi_sda:hdmi-sda {
+                               rockchip,pins = <HDMI_DSDA>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       hdmi_scl:hdmi-scl {
+                               rockchip,pins = <HDMI_DSCL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       hdmi_hpd:hdmi-hpd {
+                               rockchip,pins = <HDMI_HPD>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;
+
+                       };
+
+                       hdmi_gpio: hdmi-gpio {
+                               rockchip,pins = <FUNC_TO_GPIO(HDMI_CEC)>, <FUNC_TO_GPIO(HDMI_DSDA)>, <FUNC_TO_GPIO(HDMI_DSCL)>, <FUNC_TO_GPIO(HDMI_HPD)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               //rockchip,drive = <VALUE_DRV_DEFAULT>;                         
+                       };
+               };              
+
+               gpio1_i2s0 {
+                       i2s0_mclk_mux0:i2s0-mclk-mux0 {
+                               rockchip,pins = <I2S0_MCLK_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_sclk_mux0:i2s0-sclk-mux0 {
+                               rockchip,pins = <I2S0_SCLK_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_lrckrx_mux0:i2s0-lrckrx-mux0 {
+                               rockchip,pins = <I2S0_LRCKRX_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_lrcktx_mux0:i2s0-lrcktx-mux0 {
+                               rockchip,pins = <I2S0_LRCKTX_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_sdo_mux0:i2s0-sdo-mux0 {
+                               rockchip,pins = <I2S0_SDO_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_sdi_mux0:i2s0-sdi-mux0 {
+                               rockchip,pins = <I2S0_SDI_MUX0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_gpio_mux0: i2s0-gpio-mux0 {
+                               rockchip,pins = <FUNC_TO_GPIO(I2S0_MCLK_MUX0)>,
+                                               <FUNC_TO_GPIO(I2S0_SCLK_MUX0)>,
+                                               <FUNC_TO_GPIO(I2S0_LRCKRX_MUX0)>,
+                                               <FUNC_TO_GPIO(I2S0_LRCKTX_MUX0)>,
+                                               <FUNC_TO_GPIO(I2S0_SDO_MUX0)>,
+                                               <FUNC_TO_GPIO(I2S0_SDI_MUX0)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+
+                       i2s0_mclk_mux1:i2s0-mclk-mux1 {
+                               rockchip,pins = <I2S0_MCLK_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_sclk_mux1:i2s0-sclk-mux1 {
+                               rockchip,pins = <I2S0_SCLK_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_lrckrx_mux1:i2s0-lrckrx-mux1 {
+                               rockchip,pins = <I2S0_LRCKRX_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_lrcktx_mux1:i2s0-lrcktx-mux1 {
+                               rockchip,pins = <I2S0_LRCKTX_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_sdo_mux1:i2s0-sdo-mux1 {
+                               rockchip,pins = <I2S0_SDO_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_sdi_mux1:i2s0-sdi-mux1 {
+                               rockchip,pins = <I2S0_SDI_MUX1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+                       i2s0_gpio_mux1: i2s0-gpio-mux1 {
+                               rockchip,pins = <FUNC_TO_GPIO(I2S0_MCLK_MUX1)>,
+                                               <FUNC_TO_GPIO(I2S0_SCLK_MUX1)>,
+                                               <FUNC_TO_GPIO(I2S0_LRCKRX_MUX1)>,
+                                               <FUNC_TO_GPIO(I2S0_LRCKTX_MUX1)>,
+                                               <FUNC_TO_GPIO(I2S0_SDO_MUX1)>,
+                                               <FUNC_TO_GPIO(I2S0_SDI_MUX1)>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+
+               };
+
+               gpio0_spdif {
+                       spdif_tx: spdif-tx {
+                               rockchip,pins = <SPDIF_TX>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+                       };
+               };
+               
+               gpio0_emmc0 {
+                       emmc0_clk: emmc0-clk {
+                               rockchip,pins = <EMMC_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+
+                       emmc0_cmd_mux0: emmc0-cmd-mux0 {
+                               rockchip,pins = <EMMC_CMD_MUX0>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+                       emmc0_cmd_mux1: emmc0-cmd-mux1 {
+                               rockchip,pins = <EMMC_CMD_MUX1>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+
+                       emmc0_bus1: emmc0-bus-width1 {
+                               rockchip,pins = <EMMC_D0>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+                       emmc0_bus4: emmc0-bus-width4 {
+                               rockchip,pins = <EMMC_D0>,
+                                               <EMMC_D1>,
+                                               <EMMC_D2 >,
+                                               <EMMC_D3>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+               };
+
+               gpio1_sdmmc0 {
+                       sdmmc0_clk: sdmmc0-clk {
+                               rockchip,pins = <MMC0_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+
+                       sdmmc0_cmd: sdmmc0-cmd {
+                               rockchip,pins = <MMC0_CMD>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+                       };
+
+                       sdmmc0_dectn: sdmmc0-dectn{
+                               rockchip,pins = <MMC0_DETN>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+
+                       sdmmc0_bus1: sdmmc0-bus-width1 {
+                               rockchip,pins = <MMC0_D0>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+                       sdmmc0_bus4: sdmmc0-bus-width4 {
+                               rockchip,pins = <MMC0_D0>,
+                                               <MMC0_D1>,
+                                               <MMC0_D2>,
+                                               <MMC0_D3>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+                       sdmmc0_gpio: sdmmc0_gpio{
+                               rockchip,pins =
+                                       <GPIO1_B7>,  //CMD
+                                       <GPIO1_C0>,  //CLK
+                                       <GPIO1_C1>,  //DET
+                                       <GPIO1_C2>,  //D0
+                                       <GPIO1_C3>,  //D1
+                                       <GPIO1_C4>,  //D2
+                                       <GPIO1_C5>;  //D3
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+               };
+
+               gpio2_nandc {
+                       nandc_ale:nandc-ale {
+                               rockchip,pins = <NAND_ALE>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_cle:nandc-cle {
+                               rockchip,pins = <NAND_CLE>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_wrn:nandc-wrn {
+                               rockchip,pins = <NAND_WRN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_rdn:nandc-rdn {
+                               rockchip,pins = <NAND_RDN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_rdy:nandc-rdy {
+                               rockchip,pins = <NAND_RDY>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+                       nandc_cs0:nandc-cs0 {
+                               rockchip,pins = <NAND_CS0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+
+                       nandc_data: nandc-data {
+                               rockchip,pins = <NAND_D0>,
+                                               <NAND_D1>,
+                                               <NAND_D2>,
+                                               <NAND_D3>,
+                                               <NAND_D4>,
+                                               <NAND_D5>,
+                                               <NAND_D6>,
+                                               <NAND_D7>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;   
+
+                       };
+
+               };
+
+               gpio0_sdio0 {
+                       sdio0_pwren: sdio0_pwren {
+                               rockchip,pins = <MMC1_PWREN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+
+                       sdio0_cmd: sdio0_cmd {
+                               rockchip,pins = <MMC1_CMD>;
+                               rockchip,pull = <VALUE_PULL_UP>;
+                               
+
+                       };
+
+                       sdio0_gpio: sdio0_gpio{
+                               rockchip,pins = <GPIO0_D6>, //pwren
+                                               <GPIO0_A3>; //cmd
+                               rockchip,pull = <VALUE_PULL_UP>;
+                       };
+
+               };
+                
+               gpio0_pwm{
+                       pwm0_pin:pwm0 {
+                               rockchip,pins = <PWM0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+
+                       pwm1_pin:pwm1 {
+                               rockchip,pins = <PWM1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+
+                       pwm2_pin:pwm2 {
+                               rockchip,pins = <PWM2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+
+                       pwm3_pin:pwm3 {
+                               rockchip,pins = <PWM_IRIN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                               
+
+                       };
+               };
+
+               gpio2_gmac {
+                       gmac_rxdv:gmac-rxdv {
+                               rockchip,pins = <GMAC_RXDV>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_txclk:gmac-txclk {
+                               rockchip,pins = <GMAC_TXCLK>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_crs:gmac-crs {
+                               rockchip,pins = <GMAC_CRS>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_rxclk:gmac-rxclk {
+                               rockchip,pins = <GMAC_RXCLK>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_mdio:gmac-mdio {
+                               rockchip,pins = <GMAC_MDIO>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_txen:gmac-txen {
+                               rockchip,pins = <GMAC_TXEN>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_clk:gmac-clk {
+                               rockchip,pins = <GMAC_CLK>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       gmac_rxer:gmac-rxer {
+                               rockchip,pins = <GMAC_RXER>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_rxd1:gmac-rxd1 {
+                               rockchip,pins = <GMAC_RXD1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_rxd0:gmac-rxd0 {
+                               rockchip,pins = <GMAC_RXD0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_txd1:gmac-txd1 {
+                               rockchip,pins = <GMAC_TXD1>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_txd0:gmac-txd0 {
+                               rockchip,pins = <GMAC_TXD0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       gmac_rxd3:gmac-rxd3 {
+                               rockchip,pins = <GMAC_RXD3>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_rxd2:gmac-rxd2 {
+                               rockchip,pins = <GMAC_RXD2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_txd2:gmac-txd2 {
+                               rockchip,pins = <GMAC_TXD2>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_txd3:gmac-txd3 {
+                               rockchip,pins = <GMAC_TXD3>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_col:gmac-col {
+                               rockchip,pins = <GMAC_COL>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+                       
+                       gmac_mdc:gmac-mdc {
+                               rockchip,pins = <GMAC_MDC>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+
+
+               };
+
+               gpio2_lcdc0 {
+                       lcdc0_lcdc:lcdc0-lcdc {
+                               rockchip,pins =
+                                               <LCDC0_DCLK>,
+                                               <LCDC0_DEN>,
+                                               <LCDC0_HSYNC>,
+                                               <LCDC0_VSYNC>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       lcdc0_gpio:lcdc0-gpio {
+                               rockchip,pins =
+                                               <FUNC_TO_GPIO(LCDC0_DCLK)>,
+                                               <FUNC_TO_GPIO(LCDC0_DEN)>,
+                                               <FUNC_TO_GPIO(LCDC0_HSYNC)>,
+                                               <FUNC_TO_GPIO(LCDC0_VSYNC)>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+               };
+
+               gpio2_lcdc0_d {
+                       lcdc0_lcdc_d: lcdc0-lcdc_d {
+                               rockchip,pins =
+                                               <LCDC0_D10>,
+                                               <LCDC0_D11>,
+                                               <LCDC0_D12>,
+                                               <LCDC0_D13>,
+                                               <LCDC0_D14>,
+                                               <LCDC0_D15>,
+                                               <LCDC0_D16>,
+                                               <LCDC0_D17>,
+                                               <LCDC0_D18>,
+                                               <LCDC0_D19>,
+                                               <LCDC0_D20>,
+                                               <LCDC0_D21>,
+                                               <LCDC0_D22>,
+                                               <LCDC0_D23>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+                       lcdc0_lcdc_gpio: lcdc0-lcdc_gpio {
+                               rockchip,pins =
+                                               <FUNC_TO_GPIO(LCDC0_D10)>,
+                                               <FUNC_TO_GPIO(LCDC0_D11)>,
+                                               <FUNC_TO_GPIO(LCDC0_D12)>,
+                                               <FUNC_TO_GPIO(LCDC0_D13)>,
+                                               <FUNC_TO_GPIO(LCDC0_D14)>,
+                                               <FUNC_TO_GPIO(LCDC0_D15)>,
+                                               <FUNC_TO_GPIO(LCDC0_D16)>,
+                                               <FUNC_TO_GPIO(LCDC0_D17)>,
+                                               <FUNC_TO_GPIO(LCDC0_D18)>,
+                                               <FUNC_TO_GPIO(LCDC0_D19)>,
+                                               <FUNC_TO_GPIO(LCDC0_D20)>,
+                                               <FUNC_TO_GPIO(LCDC0_D21)>,
+                                               <FUNC_TO_GPIO(LCDC0_D22)>,
+                                               <FUNC_TO_GPIO(LCDC0_D23)>;
+                               rockchip,pull = <VALUE_PULL_DOWN>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                       };
+
+               };
+
+               //to add 
+
+               
+       };      
+
+};
diff --git a/arch/arm/boot/dts/rk312x-sdk.dtsi b/arch/arm/boot/dts/rk312x-sdk.dtsi
new file mode 100755 (executable)
index 0000000..a35bdbd
--- /dev/null
@@ -0,0 +1,382 @@
+/dts-v1/;
+
+#include "rk312x.dtsi"
+#include "lcd-b101ew05.dtsi"
+
+/ {
+       fiq-debugger {
+               status = "okay";
+       };
+
+       chosen {
+               bootargs = "vmalloc=512M clk_ignore_unused";
+       };
+
+       usb_control {
+               compatible = "rockchip,rk3126-usb-control";
+               host_drv_gpio = <&gpio2 GPIO_B4 GPIO_ACTIVE_LOW>;
+               otg_drv_gpio = <&gpio2 GPIO_B6 GPIO_ACTIVE_LOW>;
+
+               rockchip,remote_wakeup;
+               rockchip,usb_irq_wakeup;
+       };
+};
+
+&nandc {
+       status = "okay"; // used nand set "okay" ,used emmc set "disabled"
+};
+
+&nandc0reg {
+       status = "disabled"; // used nand set "disabled" ,used emmc set "okay"
+};
+
+&emmc {
+       clock-frequency = <100000000>;
+       clock-freq-min-max = <400000 100000000>;
+       supports-highspeed;
+       supports-emmc;
+       bootpart-no-access;
+       supports-DDR_MODE;
+       //caps2-mmc-hs200;
+       ignore-pm-notify;
+       keep-power-in-suspend;
+       //poll-hw-reset
+       status = "disabled";
+};
+
+&sdmmc {
+       clock-frequency = <50000000>;
+       clock-freq-min-max = <400000 50000000>;
+       supports-highspeed;
+       supports-sd;
+       broken-cd;
+       card-detect-delay = <200>;
+       ignore-pm-notify;
+       keep-power-in-suspend;
+       //vmmc-supply = <&rk808_ldo5_reg>;
+       status = "disabled";
+};
+
+&sdio {
+       clock-frequency = <50000000>;
+       clock-freq-min-max = <200000 50000000>;
+       supports-highspeed;
+       supports-sdio;
+       ignore-pm-notify;
+       keep-power-in-suspend;
+       //cap-sdio-irq;
+       status = "disabled";
+};
+
+&adc {
+       status = "okay";
+
+       key {
+               compatible = "rockchip,key";
+               io-channels = <&adc 1>;
+
+               vol-up-key {
+                       linux,code = <115>;
+                       label = "volume up";
+                       rockchip,adc_value = <1>;
+               };
+
+               vol-down-key {
+                       linux,code = <114>;
+                       label = "volume down";
+                       rockchip,adc_value = <170>;
+               };
+
+               power-key {
+                       gpios = <&gpio0 GPIO_A5 GPIO_ACTIVE_LOW>;
+                       linux,code = <116>;
+                       label = "power";
+                       gpio-key,wakeup;
+               };
+
+               menu-key {
+                       linux,code = <59>;
+                       label = "menu";
+                       rockchip,adc_value = <355>;
+               };
+
+               home-key {
+                       linux,code = <102>;
+                       label = "home";
+                       rockchip,adc_value = <746>;
+               };
+
+               back-key {
+                       linux,code = <158>;
+                       label = "back";
+                       rockchip,adc_value = <560>;
+               };
+
+               camera-key {
+                       linux,code = <212>;
+                       label = "camera";
+                       rockchip,adc_value = <450>;
+               };
+       };
+};
+
+
+&i2c0 {
+       status = "okay";
+       rk818: rk818@1c {
+               reg = <0x1c>;
+               status = "okay";
+       };
+};
+&i2c2 {
+       status = "okay";
+       ts@01 {
+               compatible = "ct,vtl_ts";
+               reg = <0x01>;
+               screen_max_x = <1280>;
+               screen_max_y = <800>;
+               irq_gpio_number = <&gpio1 GPIO_B0 IRQ_TYPE_LEVEL_LOW>;
+               rst_gpio_number = <&gpio2 GPIO_C1 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&fb {
+       rockchip,disp-mode = <ONE_DUAL>;
+       rockchip,uboot-logo-on = <0>;
+};
+
+&rk_screen {
+       display-timings = <&disp_timings>;
+};
+
+&hdmi {
+       status = "okay";
+};
+
+/include/ "rk818.dtsi"
+&rk818 {
+       gpios =<&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>,<&gpio1 GPIO_A1 GPIO_ACTIVE_LOW>;
+       rk818,system-power-controller;
+
+       regulators {
+
+               rk818_dcdc1_reg: regulator@0{
+                       regulator-name= "vdd_arm";
+                       regulator-min-microvolt = <700000>;
+                       regulator-max-microvolt = <1500000>;
+                       regulator-initial-mode = <0x2>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-mode = <0x2>;
+                               regulator-state-enabled;
+                               regulator-state-uv = <900000>;
+                       };
+               };
+
+               rk818_dcdc2_reg: regulator@1 {
+                       regulator-name= "vdd_logic";
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1200000>;
+                       regulator-initial-mode = <0x2>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-mode = <0x2>;
+                               regulator-state-enabled;
+                               regulator-state-uv = <900000>;
+                       };
+               };
+
+               rk818_dcdc3_reg: regulator@2 {
+                       regulator-name= "rk818_dcdc3";
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1200000>;
+                       regulator-initial-mode = <0x2>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-mode = <0x2>;
+                               regulator-state-disabled;
+                               regulator-state-uv = <1200000>;
+                       };
+               };
+
+               rk818_dcdc4_reg: regulator@3 {
+                       regulator-name= "vccio";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-initial-mode = <0x2>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-mode = <0x2>;
+                               regulator-state-disabled;
+                               regulator-state-uv = <2800000>;
+                       };
+               };
+
+               rk818_ldo1_reg: regulator@4 {
+                       regulator-name= "rk818_ldo1";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <3300000>;
+                       };
+               };
+
+               rk818_ldo2_reg: regulator@5 {
+                       regulator-name= "rk818_ldo2";
+                       regulator-min-microvolt = <3000000>;
+                       regulator-max-microvolt = <3000000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <3000000>;
+                       };
+               };
+
+               rk818_ldo3_reg: regulator@6 {
+                       regulator-name= "rk818_ldo3";
+                       regulator-min-microvolt = <1100000>;
+                       regulator-max-microvolt = <1100000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <1100000>;
+                       };
+               };
+
+               rk818_ldo4_reg:regulator@7 {
+                       regulator-name= "rk818_ldo4";
+                       regulator-min-microvolt = <2500000>;
+                       regulator-max-microvolt = <2500000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <2500000>;
+                       };
+               };
+
+               rk818_ldo5_reg: regulator@8 {
+                       regulator-name= "rk818_ldo5";
+                       regulator-min-microvolt = <3000000>;
+                       regulator-max-microvolt = <3000000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <3000000>;
+                       };
+               };
+
+               rk818_ldo6_reg: regulator@9 {
+                       regulator-name= "rk818_ldo6";
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1200000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <1200000>;
+                       };
+               };
+
+               rk818_ldo7_reg: regulator@10 {
+                       regulator-name= "rk818_ldo7";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <1800000>;
+                       };
+               };
+
+               rk818_ldo8_reg: regulator@11 {
+                       regulator-name= "rk818_ldo8";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <1800000>;
+                       };
+               };
+               rk818_ldo9_reg: regulator@12 {
+                       regulator-name= "vcc_sd";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <3000000>;
+                       regulator-initial-state = <3>;
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                               regulator-state-uv = <3000000>;
+                       };
+               };
+               rk818_ldo10_reg: regulator@13 {
+                       regulator-name= "rk818_ldo10";
+                       regulator-state-mem {
+                               regulator-state-disabled;
+                       };
+               };
+       };
+       battery {
+                ocv_table = <3350 3677 3693 3719 3752 3770 3775 3778 3785 3796 3812 3839 3881 3907 3933 3958 3978 4033 4087 4123 4174>;
+                design_capacity = <2100>;
+                design_qmax = <2200>;
+                max_overcharge = <100>;
+                max_charge_currentmA = <1500>;
+                max_charge_voltagemV = <4260>;
+                max_bat_voltagemV = <4200>;
+        };
+
+};
+&clk_core_dvfs_table {
+       operating-points = <
+               /* KHz    uV */
+               408000 1250000
+               600000 1250000
+               696000 1250000
+               816000 1250000
+               >;
+       status="disable";
+};
+
+&clk_gpu_dvfs_table {
+       operating-points = <
+               /* KHz    uV */
+               200000 125000
+               300000 125000
+               >;
+       status="okay";
+};
+
+&clk_ddr_dvfs_table {
+       operating-points = <
+               /* KHz    uV */
+               200000 950000
+               300000 950000
+               400000 1000000
+               533000 1050000
+               >;
+
+       freq-table = <
+               /*status                freq(KHz)*/
+               SYS_STATUS_NORMAL       400000
+               SYS_STATUS_SUSPEND      200000
+               SYS_STATUS_VIDEO_1080P  240000
+               SYS_STATUS_VIDEO_4K     400000
+               SYS_STATUS_PERFORMANCE  528000
+               SYS_STATUS_DUALVIEW     400000
+               SYS_STATUS_BOOST        324000
+               SYS_STATUS_ISP          533000
+               >;
+       auto-freq-table = <
+               240000
+               324000
+               396000
+               528000
+               >;
+       auto-freq=<0>;
+       status="disable";
+};
+
+&pwm0 {
+        status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi
new file mode 100755 (executable)
index 0000000..5c6cbc1
--- /dev/null
@@ -0,0 +1,800 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/suspend/rockchip-pm.h>
+#include <dt-bindings/sensor-dev.h>
+#include <dt-bindings/clock/rk_system_status.h>
+#include <dt-bindings/rkfb/rk_fb.h>
+
+#include "skeleton.dtsi"
+#include "rk312x-clocks.dtsi"
+#include "rk312x-pinctrl.dtsi"
+
+/ {
+       compatible = "rockchip,rk312x";
+       rockchip,sram = <&sram>;
+       interrupt-parent = <&gic>;
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               i2c3 = &i2c3;
+               lcdc = &lcdc;
+       //      spi0 = &spi0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0xf00>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0xf01>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0xf02>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0xf03>;
+               };
+       };
+
+       gic: interrupt-controller@10139000 {
+               compatible = "arm,cortex-a15-gic";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               reg = <0x10139000 0x1000>,
+                     <0x1013a000 0x1000>;
+       };
+
+       arm-pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       sram: sram@10080000 {
+               compatible = "mmio-sram";
+               reg = <0x10080000 0x2000>;
+               map-exec;
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clock-frequency = <24000000>;
+       };
+
+       timer@20044000 {
+               compatible = "rockchip,timer";
+               reg = <0x20044000 0x20>;
+               interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,broadcast = <1>;
+       };
+
+       watchdog: wdt@2004c000 {
+               compatible = "rockchip,watch dog";
+               reg = <0x2004c000 0x100>;
+       //      clocks = <&clk_gates7 15>;
+               clock-names = "pclk_wdt";
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,irq = <1>;
+               rockchip,timeout = <60>;
+               rockchip,atboot = <1>;
+               rockchip,debug = <0>;
+               status = "disabled";
+       };
+
+       amba {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "arm,amba-bus";
+               interrupt-parent = <&gic>;
+               ranges;
+
+               pdma: pdma@20078000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x20078000 0x4000>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+               };
+       };
+
+       reset: reset@20000110 {
+               compatible = "rockchip,reset";
+               reg = <0x20000110 0x24>;
+               rockchip,reset-flag = <ROCKCHIP_RESET_HIWORD_MASK>;
+               #reset-cells = <1>;
+       };
+
+       nandc: nandc@10500000 {
+               compatible = "rockchip,rk-nandc";
+               reg = <0x10500000 0x4000>;
+               interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+               //pinctrl-names = "default";
+               //pinctrl-0 = <&nandc_ale &nandc_cle &nandc_wrn &nandc_rdn &nandc_rdy &nandc_cs0 &nandc_data>;
+               nandc_id = <0>;
+               clocks = <&clk_nandc>, <&clk_gates5 9>, <&clk_gates10 15>;
+               clock-names = "clk_nandc", "g_clk_nandc", "hclk_nandc";
+       };
+       
+       nandc0reg: nandc0@10500000 {
+               compatible = "rockchip,rk-nandc";
+               reg = <0x10500000 0x4000>;
+       };
+       uart0: serial@20060000 {
+               compatible = "rockchip,serial";
+               reg = <0x20060000 0x100>;
+               interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               clocks = <&clk_uart0>, <&clk_gates8 0>;
+               clock-names = "sclk_uart", "pclk_uart";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               dmas = <&pdma 2>, <&pdma 3>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+               status = "disabled";
+       };
+
+       uart1: serial@20064000 {
+               compatible = "rockchip,serial";
+               reg = <0x20064000 0x100>;
+               interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               clocks = <&clk_uart1>, <&clk_gates8 1>;
+               clock-names = "sclk_uart", "pclk_uart";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               dmas = <&pdma 4>, <&pdma 5>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart1_xfer &uart1_cts &uart1_rts>;
+               status = "disabled";
+       };
+
+       uart2: serial@20068000 {
+               compatible = "rockchip,serial";
+               reg = <0x20068000 0x100>;
+               interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               clocks = <&clk_uart2>, <&clk_gates8 2>;
+               clock-names = "sclk_uart", "pclk_uart";
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               dmas = <&pdma 6>, <&pdma 7>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart2_xfer>;
+               status = "disabled";
+       };
+
+       fiq-debugger {
+               compatible = "rockchip,fiq-debugger";
+               rockchip,serial-id = <2>;
+               rockchip,signal-irq = <106>;
+               rockchip,wake-irq = <0>;
+               status = "disabled";
+       };
+
+       clocks-init{
+               compatible = "rockchip,clocks-init";
+               rockchip,clocks-init-parent =
+                       <&clk_core &clk_apll>, <&aclk_cpu &clk_gpll_div2>,
+                       <&aclk_peri &clk_gpll_div2>, <&clk_uart0_pll &clk_gpll>,
+                       <&clk_uart2_pll &clk_gpll>, <&clk_i2s_2ch_pll &clk_gpll>,
+                       <&clk_i2s_8ch_pll &clk_gpll>, <&clk_spdif_pll &clk_gpll>,
+                       <&clk_vepu &clk_gpll_div2>, <&clk_vdpu &clk_gpll_div2>,
+                       <&clk_hevc_core &clk_gpll>, <&aclk_vio0_pre &clk_gpll_div2>,
+                       <&aclk_vio1_pre &clk_gpll_div2>, <&hclk_vio_pre &clk_gpll_div2>,
+                       <&sclk_lcdc0 &clk_cpll>, <&clk_gpu &clk_gpll_div2>,
+                       <&clk_cif_pll &clk_gpll_div2>, <&dclk_ebc &clk_gpll_div2>,
+                       <&clk_emmc &clk_gpll_div2>, <&clk_sdio &clk_gpll_div2>,
+                       <&clk_sfc &clk_gpll_div2>, <&clk_sdmmc0 &clk_gpll_div2>,
+                       <&clk_tsp &clk_gpll_div2>, <&clk_nandc &clk_gpll_div2>,
+                       <&clk_mac_pll &clk_cpll>;
+               rockchip,clocks-init-rate =
+                       <&clk_core 816000000>, <&clk_gpll 594000000>,
+                       <&clk_cpll 400000000>, <&aclk_cpu 300000000>,
+                       <&hclk_cpu_pre 150000000>, <&pclk_cpu_pre 75000000>,
+                       <&aclk_peri 300000000>, <&hclk_peri_pre 150000000>,
+                       <&pclk_peri_pre 75000000>, <&clk_gpu 300000000>,
+                       <&aclk_vio0_pre 300000000>, <&hclk_vio_pre 150000000>,
+                       <&aclk_vio1_pre 300000000>, <&clk_vepu 300000000>,
+                       <&clk_vdpu 300000000>, <&clk_hevc_core 200000000>,
+                       <&clk_mac_ref 50000000>;
+       /*      rockchip,clocks-uboot-has-init =
+                       <&aclk_vio1>;*/
+       };
+       gpu {
+               compatible = "arm,mali400";
+               reg = <0x10091000 0x200>,
+                     <0x10090000 0x100>,
+                     <0x10093000 0x100>,
+                     <0x10098000 0x1100>,
+                     <0x10094000 0x100>,
+                     <0x1009A000 0x1100>,
+                     <0x10095000 0x100>;
+               
+               reg-names = "Mali_L2",
+                           "Mali_GP",
+                           "Mali_GP_MMU",
+                           "Mali_PP0",
+                           "Mali_PP0_MMU",
+                           "Mali_PP1",
+                           "Mali_PP1_MMU";
+
+               interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+               
+               interrupt-names = "Mali_GP_IRQ",
+                                 "Mali_GP_MMU_IRQ",
+                                 "Mali_PP0_IRQ",
+                                 "Mali_PP0_MMU_IRQ",
+                                 "Mali_PP1_IRQ",
+                                 "Mali_PP1_MMU_IRQ";
+         };
+
+       clocks-enable {
+               compatible = "rockchip,clocks-enable";
+               clocks =
+                               /*PD_CORE*/
+                               <&clk_gates0 6>,<&clk_gates0 0>,
+                               <&clk_gates0 7>,
+
+                               /*PD_CPU*/
+                               <&clk_gates0 1>, <&clk_gates0 3>,
+                               <&clk_gates0 4>, <&clk_gates0 5>,
+                               <&clk_gates0 12>,
+
+                               /*TIMER*/
+                               <&clk_gates10 3>, <&clk_gates10 4>,
+                               <&clk_gates10 5>, <&clk_gates10 6>,
+                               <&clk_gates10 7>, <&clk_gates10 8>,
+
+                               /*PD_PERI*/
+                               <&clk_gates2 0>, <&hclk_peri_pre>,
+                               <&pclk_peri_pre>, <&clk_gates2 1>,
+
+                               /*aclk_cpu_pre*/
+                               <&clk_gates4 12>,/*aclk_intmem*/
+                               <&clk_gates4 10>,/*aclk_strc_sys*/
+
+                               /*hclk_cpu_pre*/
+                               <&clk_gates5 6>,/*hclk_rom*/
+                               <&clk_gates3 5>,/*hclk_crypto*/
+
+                               /*pclk_cpu_pre*/
+                               <&clk_gates5 4>,/*pclk_grf*/
+                               <&clk_gates5 7>,/*pclk_ddrupctl*/
+                               <&clk_gates5 14>,/*pclk_acodec*/
+                               <&clk_gates3 8>,/*pclk_hdmi*/
+
+                               /*aclk_peri_pre*/
+                               <&clk_gates10 10>,/*aclk_gmac*/
+                               <&clk_gates4 3>,/*aclk_peri_axi_matrix*/
+                               <&clk_gates5 1>,/*aclk_dmac2*/
+                               <&clk_gates9 15>,/*aclk_peri_niu*/
+                               <&clk_gates4 2>,/*aclk_cpu_peri*/
+
+                               /*hclk_peri_pre*/
+                               <&clk_gates4 0>,/*hclk_peri_matrix*/
+                               <&clk_gates9 13>,/*hclk_usb_peri*/
+                               <&clk_gates9 14>,/*hclk_peri_arbi*/
+
+                               /*pclk_peri_pre*/
+                               <&clk_gates4 1>,/*pclk_peri_axi_matrix*/
+
+                               /*hclk_vio_pre*/
+                               <&clk_gates6 12>,/*hclk_vio_niu*/
+                               <&clk_gates6 1>,/*hclk_lcdc*/
+
+                               /*aclk_vio0_pre*/
+                               <&clk_gates6 13>,/*aclk_vio*/
+                               <&clk_gates6 0>,/*aclk_lcdc*/
+
+                               /*aclk_vio1_pre*/
+                               <&clk_gates9 10>,/*aclk_vio1_niu*/
+
+                               /*UART*/
+                               <&clk_gates1 12>,
+                               <&clk_gates1 13>,
+                               <&clk_gates8 2>,/*pclk_uart2*/
+
+                               <&clk_gpu>,
+
+                               /*jtag*/
+                               <&clk_gates1 3>,/*clk_jtag*/
+
+                               /*pmu*/
+                               <&clk_gates1 0>;/*pclk_pmu_pre*/
+       };
+
+       i2c0: i2c@20072000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x20072000 0x1000>;
+               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c0_sda &i2c0_scl>;
+               pinctrl-1 = <&i2c0_gpio>;
+               gpios = <&gpio0 GPIO_A1 GPIO_ACTIVE_LOW>, <&gpio0 GPIO_A0 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 4>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@20056000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x20056000 0x1000>;
+               interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c1_sda &i2c1_scl>;
+               pinctrl-1 = <&i2c1_gpio>;
+               gpios = <&gpio0 GPIO_A3 GPIO_ACTIVE_LOW>, <&gpio0 GPIO_A2 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 5>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@2005a000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x2005a000 0x1000>;
+               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c2_sda &i2c2_scl>;
+               pinctrl-1 = <&i2c2_gpio>;
+               gpios = <&gpio2 GPIO_C4 GPIO_ACTIVE_LOW>, <&gpio2 GPIO_C5 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 6>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2c3: i2c@2005e000 {
+               compatible = "rockchip,rk30-i2c";
+               reg = <0x2005e000 0x1000>;
+               interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+                pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&i2c3_sda &i2c3_scl>;
+               pinctrl-1 = <&i2c3_gpio>;
+               gpios = <&gpio0 GPIO_A7 GPIO_ACTIVE_LOW>, <&gpio0 GPIO_A6 GPIO_ACTIVE_LOW>;
+               clocks = <&clk_gates8 7>;
+               rockchip,check-idle = <1>;
+               status = "disabled";
+       };
+
+       i2s0: i2s@10220000 {
+               compatible = "rockchip-i2s";
+               reg = <0x10220000 0x1000>;
+               i2s-id = <0>;
+               clocks = <&clk_i2s_2ch>, <&clk_i2s_2ch_out>, <&clk_gates7 2>;
+               clock-names = "i2s_clk", "i2s_mclk", "i2s_hclk";
+               interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+               dmas = <&pdma 0>, <&pdma 1>;
+               //#dma-cells = <2>;
+               dma-names = "tx", "rx";
+               //pinctrl-names = "default", "sleep";
+               //pinctrl-0 = <&i2s0_mclk &i2s0_sclk &i2s0_lrckrx &i2s0_lrcktx &i2s0_sdi &i2s0_sdo>;
+               //pinctrl-1 = <&i2s0_gpio>;
+       };
+
+       i2s1: i2s@10200000 {
+               compatible = "rockchip-i2s";
+               reg = <0x10200000 0x1000>;
+               i2s-id = <1>;
+               clocks = <&clk_i2s_8ch>, <&clk_gates7 4>;
+               clock-names = "i2s_clk", "i2s_hclk";
+               interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+               dmas = <&pdma 14>, <&pdma 15>;
+               //#dma-cells = <2>;
+               dma-names = "tx", "rx";
+       };
+
+       spdif: spdif@10204000 {
+               compatible = "rockchip-spdif";
+               reg = <0x10204000 0x1000>;
+               clocks = <&clk_spdif>, <&clk_gates10 8>;
+               clock-names = "spdif_8ch_mclk", "spdif_hclk";
+               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+               dmas = <&pdma 13>;
+               //#dma-cells = <1>;
+               dma-names = "tx";
+               //pinctrl-names = "default";
+               //pinctrl-0 = <&spdif_tx>;
+       };
+
+       dsihost0: mipi@10110000{
+               compatible = "rockchip,rk32-dsi";
+               rockchip,prop = <0>;
+               reg = <0x10110000 0x4000>, <0x20038000 0x4000>;
+               reg-names = "mipi_dsi_host" ,"mipi_dsi_phy";
+               interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates2 15>, <&clk_gates5 0> ;//, <&pd_mipidsi>;
+               clock-names = "clk_mipi_24m", "pclk_mipi_dsi";//, "pd_mipi_dsi";
+               status = "okay";
+       };
+
+       emmc: rksdmmc@1021c000 {
+               compatible = "rockchip,rk_mmc", "rockchip,rk312x-sdmmc";
+               reg = <0x1021c000 0x4000>;
+               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               //pinctrl-names = "default",,"suspend";
+               //pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_wp &sd0_pwr &sd0_bus1 &sd0_bus4>;
+               clocks = <&clk_emmc>, <&clk_gates7 0>;
+               clock-names = "clk_mmc", "hclk_mmc";
+               dmas = <&pdma 12>;
+               dma-names = "dw_mci";
+               num-slots = <1>;
+               fifo-depth = <0x100>;
+               bus-width = <8>;
+        };
+
+
+        sdmmc: rksdmmc@10214000 {
+               compatible = "rockchip,rk_mmc", "rockchip,rk312x-sdmmc";
+               reg = <0x10214000 0x4000>;
+               interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default", "idle";
+               pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>;
+               pinctrl-1 = <&sdmmc0_gpio>;
+               //cd-gpios = <&gpio1 GPIO_C1 GPIO_ACTIVE_HIGH>;/*CD GPIO*/
+               clocks = <&clk_sdmmc0>, <&clk_gates5 10>;
+               clock-names = "clk_mmc", "hclk_mmc";
+               dmas = <&pdma 10>;
+               dma-names = "dw_mci";
+               num-slots = <1>;
+               fifo-depth = <0x100>;
+               bus-width = <4>;
+       };
+
+       sdio: rksdmmc@10218000 {
+               compatible = "rockchip,rk_mmc", "rockchip,rk312x-sdmmc";
+               reg = <0x10218000 0x4000>;
+               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default","idle";
+               pinctrl-0 = <&sdio0_pwren &sdio0_cmd>;
+               pinctrl-1 = <&sdio0_gpio>;
+               clocks = <&clk_sdio>, <&clk_gates5 11>;
+               clock-names = "clk_mmc", "hclk_mmc";
+               dmas = <&pdma 11>;
+               dma-names = "dw_mci";
+               num-slots = <1>;
+               fifo-depth = <0x100>;
+               bus-width = <4>;
+       };
+
+       adc: adc@2006c000 {
+               compatible = "rockchip,saradc";
+               reg = <0x2006c000 0x100>;
+               interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+               #io-channel-cells = <1>;
+               io-channel-ranges;
+               rockchip,adc-vref = <1800>;
+               clock-frequency = <1000000>;
+               //clocks = <&clk_saradc>, <&clk_gates7 1>;
+               //clock-names = "saradc", "pclk_saradc";
+               status = "disabled";
+       };
+
+       pwm0: pwm@20050000 {
+               compatible = "rockchip,rk-pwm";
+               reg = <0x20050000 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm0_pin>;
+               clocks = <&clk_gates7 10>;
+               clock-names = "pclk_pwm";
+               status = "disabled";
+       };
+
+        pwm1: pwm@20050010 {
+                compatible = "rockchip,rk-pwm";
+                reg = <0x20050010 0x10>;
+                #pwm-cells = <2>;
+                pinctrl-names = "default";
+                pinctrl-0 = <&pwm1_pin>;
+                clocks = <&clk_gates7 10>;
+                clock-names = "pclk_pwm";
+                status = "disabled";
+        };
+
+        pwm2: pwm@20050020 {
+                compatible = "rockchip,rk-pwm";
+                reg = <0x20050020 0x10>;
+                #pwm-cells = <2>;
+                pinctrl-names = "default";
+                pinctrl-0 = <&pwm2_pin>;
+                clocks = <&clk_gates7 10>;
+                clock-names = "pclk_pwm";
+                status = "disabled";
+        };
+
+        pwm3: pwm@20050030 {
+                compatible = "rockchip,rk-pwm";
+                reg = <0x20050030 0x10>;
+                #pwm-cells = <2>;
+                pinctrl-names = "default";
+                pinctrl-0 = <&pwm3_pin>;
+                clocks = <&clk_gates7 10>;
+                clock-names = "pclk_pwm";
+                status = "disabled";
+        };
+
+       dwc_control_usb: dwc-control-usb@20008000 {
+               compatible = "rockchip,rk3126-dwc-control-usb";
+               reg = <0x20008000 0x4>;
+               interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "otg_bvalid";
+               clocks = <&clk_gates9 13>;
+               clock-names = "hclk_usb_peri";
+               rockchip,remote_wakeup;
+               rockchip,usb_irq_wakeup;
+               resets = <&reset RK3128_RST_USBPOR>;
+               reset-names = "usbphy_por";
+               usb_bc{
+                       compatible = "inno,phy";
+                       regbase = &dwc_control_usb;
+               };
+       };
+
+       usb0: usb@10180000 {
+               compatible = "rockchip,rk3126_usb20_otg";
+               reg = <0x10180000 0x40000>;
+               interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates1 5>, <&clk_gates5 13>;
+               clock-names = "clk_usbphy0", "hclk_usb0";
+               resets = <&reset RK3128_RST_USBOTG0>, <&reset RK3128_RST_USBOTG0>,
+                               <&reset RK3128_RST_OTGC0>;
+               reset-names = "otg_ahb", "otg_phy", "otg_controller";
+               /*0 - Normal, 1 - Force Host, 2 - Force Device*/
+               rockchip,usb-mode = <0>;
+       };
+
+       usb1: usb@101c0000 {
+               compatible = "rockchip,rk3126_usb20_host";
+               reg = <0x101c0000 0x40000>;
+               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates1 6>, <&clk_gates7 3>;
+               clock-names = "clk_usbphy1", "hclk_usb1";
+               resets = <&reset RK3128_RST_USBOTG1>, <&reset RK3128_RST_UTMI1>,
+                               <&reset RK3128_RST_OTGC1>;
+               reset-names = "host_ahb", "host_phy", "host_controller";
+       };
+
+       fb: fb{
+               compatible = "rockchip,rk-fb";
+               rockchip,disp-mode = <ONE_DUAL>;
+       };
+
+       rk_screen: rk_screen{
+               compatible = "rockchip,screen";
+       };
+
+       lvds: lvds@20038000 {
+               compatible = "rockchip,rk31xx-lvds";
+               reg = <0x20038000 0x4000>;
+               clocks = <&clk_gates5 0>;
+               clock-names = "pclk_lvds";
+               pinctrl-names = "lcdc", "sleep";
+               pinctrl-0 = <&lcdc0_lcdc_d>;
+               pinctrl-1 = <&lcdc0_lcdc_gpio>;
+       };
+
+       lcdc: lcdc@1010e000 {
+               compatible = "rockchip,rk312x-lcdc";
+               rockchip,prop = <PRMRY>;
+               reg = <0x1010e000 0x2000>;
+               interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&lcdc0_lcdc>;
+               pinctrl-1 = <&lcdc0_gpio>;
+               clocks = <&clk_gates6 0>, <&dclk_lcdc0>, <&clk_gates6 1>, <&sclk_lcdc0>;
+               clock-names = "aclk_lcdc", "dclk_lcdc", "hclk_lcdc", "sclk";
+               rockchip,iommu-enabled = <1>;
+               status = "disabled";
+       };
+
+       hdmi: hdmi@20034000 {
+               compatible = "rockchip,rk312x-hdmi";
+               reg = <0x20034000 0x4000>;
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+               rockchip,hdmi_lcdc_source = <0>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&hdmi_cec &hdmi_sda &hdmi_scl &hdmi_hpd>;
+               pinctrl-1 = <&hdmi_gpio>;
+               clocks = <&clk_gates3 8>;
+               clock-names = "pclk_hdmi";
+               status = "disabled";
+       };
+
+       tve: tve{
+               compatible = "rockchip,rk312x-tve";
+               reg = <0x1010e200 0x100>;
+               status = "disabled";
+       };
+
+        vpu: vpu_service@10104000 {
+               compatible = "vpu_service";
+               reg = <0x10104000 0x800>;
+               interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "irq_enc", "irq_dec";
+               clocks = <&clk_vdpu>, <&hclk_vdpu>;
+               clock-names = "aclk_vcodec", "hclk_vcodec";
+               name = "vpu_service";
+               status = "disabled";
+       };
+
+       hevc: hevc_service@10104000 {
+               compatible = "rockchip,hevc_service";
+               reg = <0x10104000 0x400>;
+               interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "irq_dec";
+               clocks = <&clk_vdpu>, <&hclk_vdpu>, <&clk_hevc_core>;
+               clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core";
+               name = "hevc_service";
+               status = "disabled";
+        };
+
+        iep: iep@10108000 {
+               compatible = "rockchip,iep";
+               reg = <0x10108000 0x800>;
+               interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates9 8>, <&clk_gates9 7>;
+               clock-names = "aclk_iep", "hclk_iep";
+               status = "okay";
+       };
+       
+       vop_mmu {
+               dbgname = "vop";
+               compatible = "iommu,vop_mmu";
+               reg = <0x1010e300 0x100>;
+               interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vop_mmu";
+         };
+
+         hevc_mmu {
+               dbgname = "hevc";
+               compatible = "iommu,hevc_mmu";
+               reg = <0x10104440 0x100>,
+                     <0x10104480 0x100>;
+               interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "hevc_mmu";
+         };
+
+         vpu_mmu {
+               dbgname = "vpu";
+               compatible = "iommu,vpu_mmu";
+               reg = <0x10104800 0x100>;
+               interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vpu_mmu";
+         };
+
+         iep_mmu {
+               dbgname = "iep";
+               compatible = "iommu,iep_mmu";
+               reg = <0x10108800 0x100>;
+               interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "iep_mmu";
+         };
+
+         dvfs {
+               temp-limit-enable = <0>;
+               target-temp = <80>;
+
+               vd_arm: vd_arm {
+                       regulator_name = "vdd_arm";
+                       pd_core {
+                               clk_core_dvfs_table: clk_core {
+                                       operating-points = <
+                                               /* KHz    uV */
+                                               312000 1100000
+                                               504000 1100000
+                                               816000 1100000
+                                               1008000 1100000
+                                               >;
+                                       temp-channel = <1>;
+                                       normal-temp-limit = <
+                                       /*delta-temp    delta-freq*/
+                                               3       96000
+                                               6       144000
+                                               9       192000
+                                               15      384000
+                                               >;
+                                       performance-temp-limit = <
+                                               /*temp    freq*/
+                                               110     816000
+                                               >;
+                                       status = "okay";
+                                       regu-mode-table = <
+                                               /*freq     mode*/
+                                               1008000    4
+                                               0          3
+                                       >;
+                                       regu-mode-en = <0>;
+                               };
+                       };
+               };
+
+               vd_logic: vd_logic {
+                       regulator_name = "vdd_logic";
+                       pd_ddr {
+                               clk_ddr_dvfs_table: clk_ddr {
+                                       operating-points = <
+                                               /* KHz    uV */
+                                               200000 1200000
+                                               300000 1200000
+                                               400000 1200000
+                                               >;
+                                       status = "disabled";
+                               };
+                       };
+
+                       pd_gpu {
+                               clk_gpu_dvfs_table: clk_gpu {
+                                       operating-points = <
+                                               /* KHz    uV */
+                                               200000 1200000
+                                               300000 1200000
+                                               400000 1200000
+                                               >;
+                                       status = "okay";
+                                       regu-mode-table = <
+                                               /*freq     mode*/
+                                               200000     4
+                                               0          3
+                                       >;
+                                       regu-mode-en = <0>;
+                               };
+                       };
+               };
+       };
+       ion {
+               compatible = "rockchip,ion";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ion_cma: rockchip,ion-heap@1 { /* CMA HEAP */
+                       compatible = "rockchip,ion-reserve";
+                       rockchip,ion_heap = <1>;
+                       reg = <0x00000000 0x10000000>; /* 256MB */
+               };
+               rockchip,ion-heap@3 { /* VMALLOC HEAP */
+                       rockchip,ion_heap = <3>;
+               };
+       };
+};
diff --git a/arch/arm/configs/rk3036_defconfig b/arch/arm/configs/rk3036_defconfig
new file mode 100644 (file)
index 0000000..a0ecdf1
--- /dev/null
@@ -0,0 +1,557 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_UID16 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_RK_PARTITION=y
+CONFIG_BLOCK_RKNAND=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_753970=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_CMA=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_COREDUMP is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_DEBUG=y
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_NF_NAT_IPV4=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_RK=y
+CONFIG_DEVTMPFS=y
+CONFIG_DMA_CMA=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_UID_STAT=y
+CONFIG_SRAM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_RK_VMAC_ETH=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_RTL8152=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_CDC_EEM=y
+CONFIG_USB_NET_CDC_MBIM=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_DM9620=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_CX82310_ETH=y
+CONFIG_USB_NET_KALMIA=y
+CONFIG_USB_NET_QMI_WWAN=y
+CONFIG_USB_HSO=y
+CONFIG_USB_NET_INT51X1=y
+CONFIG_USB_IPHETH=y
+CONFIG_USB_SIERRA_NET=y
+CONFIG_RKWIFI=y
+CONFIG_AP6210=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_TABLET_USB_WACOM=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GT8XX=y
+CONFIG_TOUCHSCREEN_VTL_CT36X=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_RICOH619_PWRKEY=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_GS_LIS3DH is not set
+# CONFIG_GS_MMA7660 is not set
+# CONFIG_GS_LSM303D is not set
+# CONFIG_COMPASS_DEVICE is not set
+# CONFIG_GYROSCOPE_DEVICE is not set
+# CONFIG_HALL_DEVICE is not set
+CONFIG_ROCKCHIP_REMOTECTL=y
+CONFIG_ROCKCHIP_REMOTECTL_PWM=y
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_ROCKCHIP=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_ROCKCHIP=y
+CONFIG_I2C_ROCKCHIP_COMPAT=y
+CONFIG_SPI=y
+CONFIG_SPI_ROCKCHIP_CORE=y
+CONFIG_SPI_ROCKCHIP=y
+CONFIG_SPI_ROCKCHIP_DMA=y
+CONFIG_SPI_ROCKCHIP_TEST=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_BATTERY_RICOH619=y
+CONFIG_BATTERY_BQ24296=y
+CONFIG_BATTERY_BQ27320=y
+CONFIG_CW2015_BATTERY=y
+CONFIG_SENSORS_ROCKCHIP_TSADC=y
+CONFIG_THERMAL=y
+CONFIG_MFD_RK808=y
+CONFIG_MFD_RICOH619=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_ACT8846_SUPPORT_RESET=y
+CONFIG_ROCKCHIP_PWM_REGULATOR=y
+CONFIG_REGULATOR_SYR82X=y
+CONFIG_REGULATOR_RICOH619=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MALI400=y
+CONFIG_MALI400_DEBUG=y
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_SHARED_INTERRUPTS=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FB_ROCKCHIP=y
+CONFIG_LCDC_RK3188=y
+CONFIG_LCDC_RK3288=y
+CONFIG_LCDC_RK3036=y
+CONFIG_RK_TRSM=y
+CONFIG_RK32_LVDS=y
+CONFIG_DP_ANX6345=y
+CONFIG_RK32_DP=y
+CONFIG_RK_HDMI=y
+CONFIG_RK_TVENCODER=y
+CONFIG_RK3036_TV_ENCODER=y
+CONFIG_ROCKCHIP_RGA2=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_RK_SOC=y
+CONFIG_SND_RK_SOC_HDMI_I2S=y
+CONFIG_SND_RK_SOC_RK3036=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_APPLEIR=y
+CONFIG_HID_AUREAL=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_ICADE=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LENOVO_TPKBD=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_PS3REMOTE=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_STEELSERIES=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THINGM=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_RK=y
+CONFIG_USB_ACM=y
+CONFIG_USB_PRINTER=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_OPTION=y
+CONFIG_USB_TRANCEVIBRATOR=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB20_HOST=y
+CONFIG_USB20_OTG=y
+CONFIG_MMC=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HYM8563=y
+CONFIG_RK808_RTC=y
+CONFIG_RTC_DRV_RC5T619=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_INTF_ALARM_DEV=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_SW_SYNC_USER=y
+CONFIG_ION=y
+CONFIG_ION_ROCKCHIP=y
+CONFIG_ION_CMA_HIGHMEM=y
+CONFIG_ION_ROCKCHIP_SNAPSHOT=y
+CONFIG_ION_SNAPSHOT_BUF_SHIFT=15
+CONFIG_FIQ_DEBUGGER=y
+CONFIG_FIQ_DEBUGGER_NO_SLEEP=y
+CONFIG_FIQ_DEBUGGER_CONSOLE=y
+CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y
+CONFIG_COMMON_CLK_DEBUG=y
+CONFIG_ROCKCHIP_IOMMU=y
+CONFIG_ROCKCHIP_IOVMM=y
+CONFIG_ROCKCHIP_IOMMU_DEBUG=y
+CONFIG_IIO=y
+CONFIG_ROCKCHIP_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RK_HEADSET=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_CIFS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_SCHED_TRACER=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
index fb6d3016ed64a436fc00640462909007e04ac363..09bfd429f1db7351f5ac8594e395f43cd599d99c 100644 (file)
@@ -345,13 +345,10 @@ CONFIG_MEDIA_RC_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_MALI_MIDGARD=m
-CONFIG_MALI_MIDGARD_DVFS=y
-CONFIG_MALI_MIDGARD_RT_PM=y
-CONFIG_MALI_MIDGARD_DEBUG_SYS=y
-CONFIG_MALI_EXPERT=y
-CONFIG_MALI_DEBUG_SHADER_SPLIT_FS=y
-CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="rk"
+CONFIG_MALI400=y
+CONFIG_MALI400_DEBUG=y
+# CONFIG_MALI400_PROFILING is not set
+CONFIG_MALI_SHARED_INTERRUPTS=y
 CONFIG_FB=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
@@ -361,8 +358,10 @@ CONFIG_BACKLIGHT_PWM=y
 CONFIG_FB_ROCKCHIP=y
 CONFIG_LCDC_RK3188=y
 CONFIG_LCDC_RK3288=y
+CONFIG_LCDC_RK312X=y
 CONFIG_RK_TRSM=y
 CONFIG_RK32_LVDS=y
+CONFIG_RK31XX_LVDS=y
 CONFIG_DP_ANX6345=y
 CONFIG_RK32_DP=y
 CONFIG_RK_HDMI=y
@@ -484,7 +483,6 @@ CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_BLOCK_MINORS=32
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
index ebb6e2a8a31e69ce4e40c14b3259ab15af405848..39b907e25da2f3d5e25dd4a638fe594a528f7b67 100644 (file)
                ldr     \rv, = 0x413fc090
                cmp     \tmp, \rv
                ldreq   \rp, = RK3188_UART2_PHYS
-               ldrne   \rp, = RK3288_UART_DBG_PHYS
-               ldr     \rv, = 0xfec00000
+               beq     10f
+               ldr     \rv, = 0x410fc075
+               cmp     \tmp, \rv
+               ldreq   \rp, = RK3036_UART2_PHYS
+               beq     10f
+               ldr     \rp, = RK3288_UART_DBG_PHYS
+10:            ldr     \rv, = 0xfec00000
                mov     \tmp, \rp
                bic     \tmp, \tmp, #0xff000000
                bic     \tmp, \tmp, #0x00f00000
index 921b746acd6344fcb0c6409d772418e0cb8eb258..0652f8e8f7375f40c8f243c339557ecc02b10840 100755 (executable)
@@ -36,6 +36,8 @@ SECTIONS
                PIE_OVERLAY_SECTION(overlay)
                PIE_OVERLAY_SECTION(rk3288)
                PIE_OVERLAY_SECTION(rk3188)
+               PIE_OVERLAY_SECTION(rk3036)
+               PIE_OVERLAY_SECTION(rk312x)
        }
        PIE_OVERLAY_END
 
index 6ac8c76fc4e70c46c1c15cbe4d3c4119303fc3d1..feb29aa42b7bd3747a01bf0b04317eff0a146346 100755 (executable)
@@ -1,5 +1,7 @@
 obj-y += common.o
 obj-y += cpu.o
+obj-y += rk3036.o
+obj-y += rk312x.o
 obj-y += rk3188.o
 obj-y += rk3288.o
 obj-y += ddr_freq.o
index 4c346dec79f26d42f461960aa0399a3431ca89bf..53a94f108285a9f3a865870cad3ccc147a175e9d 100644 (file)
@@ -12,7 +12,8 @@
 #define CPU_AXI_QOS_MODE_LIMITER        2
 #define CPU_AXI_QOS_MODE_REGULATOR      3
 
-#define CPU_AXI_QOS_PRIORITY_LEVEL(h, l)        ((((h) & 3) << 2) | ((l) & 3))
+#define CPU_AXI_QOS_PRIORITY_LEVEL(h, l) \
+       ((((h) & 3) << 8) | (((h) & 3) << 2) | ((l) & 3))
 #define CPU_AXI_SET_QOS_PRIORITY(h, l, base) \
        writel_relaxed(CPU_AXI_QOS_PRIORITY_LEVEL(h, l), base + CPU_AXI_QOS_PRIORITY)
 
index db66d50bcadcbeeb5d36728fef1297d5e81249d4..e567c09ebc978db4bac26e2df867108efecd9303 100644 (file)
@@ -148,13 +148,13 @@ static void __init rockchip_a9_smp_prepare_cpus(unsigned int max_cpus)
 static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 {
        unsigned int i, cpu;
-       unsigned long scuctlr;
+       unsigned long l2ctlr;
 
        if (scu_a9_has_base())
                return rockchip_a9_smp_prepare_cpus(max_cpus);
 
-       asm("mrc p15, 1, %0, c9, c0, 4" : "=r" (scuctlr));
-       ncores = (scuctlr & 3) + 1;
+       asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr));
+       ncores = ((l2ctlr >> 24) & 3) + 1;
        cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 0);
        /* Make sure that all cores except myself are really off */
        for (i = 0; i < ncores; i++) {
diff --git a/arch/arm/mach-rockchip/rk3036.c b/arch/arm/mach-rockchip/rk3036.c
new file mode 100755 (executable)
index 0000000..e4bdd33
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Device Tree support for Rockchip RK3036
+ *
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/cpuidle.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/wakeup_reason.h>
+#include <linux/rockchip/common.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/cru.h>
+#include <linux/rockchip/dvfs.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/pmu.h>
+#include <asm/cpuidle.h>
+#include <asm/cputype.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include "cpu_axi.h"
+#include "loader.h"
+#define CPU 3036
+#include "sram.h"
+#include "pm.h"
+
+#define RK3036_DEVICE(name) \
+       { \
+               .virtual        = (unsigned long) RK_##name##_VIRT, \
+               .pfn            = __phys_to_pfn(RK3036_##name##_PHYS), \
+               .length         = RK3036_##name##_SIZE, \
+               .type           = MT_DEVICE, \
+       }
+
+#define RK3036_IMEM_VIRT (RK_BOOTRAM_VIRT + SZ_32K)
+#define RK3036_TIMER5_VIRT (RK_TIMER_VIRT + 0xa0)
+
+static struct map_desc rk3036_io_desc[] __initdata = {
+       RK3036_DEVICE(CRU),
+       RK3036_DEVICE(GRF),
+       RK3036_DEVICE(ROM),
+       RK3036_DEVICE(EFUSE),
+       RK_DEVICE(RK_DDR_VIRT, RK3036_DDR_PCTL_PHYS, RK3036_DDR_PCTL_SIZE),
+       RK_DEVICE(RK_DDR_VIRT + RK3036_DDR_PCTL_SIZE, RK3036_DDR_PHY_PHYS,
+                 RK3036_DDR_PHY_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(0), RK3036_GPIO0_PHYS, RK3036_GPIO_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(1), RK3036_GPIO1_PHYS, RK3036_GPIO_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(2), RK3036_GPIO2_PHYS, RK3036_GPIO_SIZE),
+       RK_DEVICE(RK_DEBUG_UART_VIRT, RK3036_UART2_PHYS, RK3036_UART_SIZE),
+       RK_DEVICE(RK_GIC_VIRT, RK3036_GIC_DIST_PHYS, RK3036_GIC_DIST_SIZE),
+       RK_DEVICE(RK_GIC_VIRT + RK3036_GIC_DIST_SIZE, RK3036_GIC_CPU_PHYS,
+                 RK3036_GIC_CPU_SIZE),
+       RK_DEVICE(RK3036_IMEM_VIRT, RK3036_IMEM_PHYS, SZ_4K),
+       RK_DEVICE(RK_TIMER_VIRT, RK3036_TIMER_PHYS, RK3036_TIMER_SIZE),
+};
+
+static void __init rk3036_boot_mode_init(void)
+{
+       u32 flag = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG4);
+       u32 mode = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_OS_REG5);
+       u32 rst_st = readl_relaxed(RK_CRU_VIRT + RK3036_CRU_RST_ST);
+
+       if (flag == (SYS_KERNRL_REBOOT_FLAG | BOOT_RECOVER))
+               mode = BOOT_MODE_RECOVERY;
+       if (rst_st & ((1 << 2) | (1 << 3)))
+               mode = BOOT_MODE_WATCHDOG;
+       rockchip_boot_mode_init(flag, mode);
+}
+
+static void usb_uart_init(void)
+{
+#ifdef CONFIG_RK_USB_UART
+       u32 soc_status0 = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_STATUS0);
+#endif
+       writel_relaxed(0x34000000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4);
+#ifdef CONFIG_RK_USB_UART
+       if (!(soc_status0 & (1 << 14)) && (soc_status0 & (1 << 17))) {
+               /* software control usb phy enable */
+               writel_relaxed(0x007f0055, RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+               writel_relaxed(0x34003000, RK_GRF_VIRT + RK3036_GRF_UOC1_CON4);
+       }
+#endif
+
+       writel_relaxed(0x07, RK_DEBUG_UART_VIRT + 0x88);
+       writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04);
+       writel_relaxed(0x83, RK_DEBUG_UART_VIRT + 0x0c);
+       writel_relaxed(0x0d, RK_DEBUG_UART_VIRT + 0x00);
+       writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04);
+       writel_relaxed(0x03, RK_DEBUG_UART_VIRT + 0x0c);
+}
+
+static void __init rk3036_dt_map_io(void)
+{
+       rockchip_soc_id = ROCKCHIP_SOC_RK3036;
+
+       iotable_init(rk3036_io_desc, ARRAY_SIZE(rk3036_io_desc));
+       debug_ll_io_init();
+       usb_uart_init();
+
+       /* enable timer5 for core */
+       writel_relaxed(0, RK3036_TIMER5_VIRT + 0x10);
+       dsb();
+       writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x00);
+       writel_relaxed(0xFFFFFFFF, RK3036_TIMER5_VIRT + 0x04);
+       dsb();
+       writel_relaxed(1, RK3036_TIMER5_VIRT + 0x10);
+       dsb();
+
+       rk3036_boot_mode_init();
+}
+
+extern void secondary_startup(void);
+static int rk3036_sys_set_power_domain(enum pmu_power_domain pd, bool on)
+{
+       if (on) {
+#ifdef CONFIG_SMP
+               if (PD_CPU_1 == pd) {
+                       writel_relaxed(0x20000,
+                                      RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON);
+                       dsb();
+                       udelay(10);
+                       writel_relaxed(virt_to_phys(secondary_startup),
+                                      RK3036_IMEM_VIRT + 8);
+                       writel_relaxed(0xDEADBEAF, RK3036_IMEM_VIRT + 4);
+                       dsb_sev();
+               }
+#endif
+       } else {
+#ifdef CONFIG_SMP
+               if (PD_CPU_1 == pd) {
+                       writel_relaxed(0x20002,
+                                      RK_CRU_VIRT + RK3036_CRU_SOFTRST0_CON);
+                       dsb();
+               }
+#endif
+       }
+
+       return 0;
+}
+
+static bool rk3036_pmu_power_domain_is_on(enum pmu_power_domain pd)
+{
+       return 1;
+}
+
+static int rk3036_pmu_set_idle_request(enum pmu_idle_req req, bool idle)
+{
+       return 0;
+}
+
+static void __init rk3036_dt_init_timer(void)
+{
+       rockchip_pmu_ops.set_power_domain = rk3036_sys_set_power_domain;
+       rockchip_pmu_ops.power_domain_is_on = rk3036_pmu_power_domain_is_on;
+       rockchip_pmu_ops.set_idle_request = rk3036_pmu_set_idle_request;
+       of_clk_init(NULL);
+       clocksource_of_init();
+}
+
+#ifdef CONFIG_PM
+static inline void rk3036_uart_printch(char byte)
+{
+write_uart:
+       writel_relaxed(byte, RK_DEBUG_UART_VIRT);
+       dsb();
+
+       /* loop check LSR[6], Transmitter Empty bit */
+       while (!(readl_relaxed(RK_DEBUG_UART_VIRT + 0x14) & 0x40))
+               barrier();
+
+       if (byte == '\n') {
+               byte = '\r';
+               goto write_uart;
+       }
+}
+
+static void rk3036_ddr_printch(char byte)
+{
+       rk3036_uart_printch(byte);
+
+       rk_last_log_text(&byte, 1);
+
+       if (byte == '\n') {
+               byte = '\r';
+               rk_last_log_text(&byte, 1);
+       }
+}
+
+#define GPIO_INTEN             0x30
+#define GPIO_INT_STATUS                0x40
+#define GIC_DIST_PENDING_SET   0x200
+static void rk3036_pm_dump_irq(void)
+{
+       u32 irq_gpio =
+           (readl_relaxed(RK_GIC_VIRT + GIC_DIST_PENDING_SET + 8) >> 4) & 7;
+       u32 irq[4];
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(irq); i++) {
+               irq[i] = readl_relaxed(RK_GIC_VIRT + GIC_DIST_PENDING_SET +
+                                      (1 + i) * 4);
+               if (irq[i])
+                       log_wakeup_reason(32 * (i + 1) + fls(irq[i]) - 1);
+       }
+       pr_info("wakeup irq: %08x %08x %08x %08x\n",
+               irq[0], irq[1], irq[2], irq[3]);
+       for (i = 0; i <= 2; i++) {
+               if (irq_gpio & (1 << i))
+                       pr_info("wakeup gpio%d: %08x\n", i,
+                               readl_relaxed(RK_GPIO_VIRT(i) +
+                                             GPIO_INT_STATUS));
+       }
+}
+
+#define DUMP_GPIO_INTEN(ID) \
+       do { \
+               u32 en = readl_relaxed(RK_GPIO_VIRT(ID) + GPIO_INTEN); \
+               if (en) { \
+                       pr_info("GPIO%d_INTEN: %08x\n", ID, en); \
+               } \
+       } while (0)
+
+static void rk3036_pm_dump_inten(void)
+{
+       DUMP_GPIO_INTEN(0);
+       DUMP_GPIO_INTEN(1);
+       DUMP_GPIO_INTEN(2);
+}
+
+static void __init rk3036_suspend_init(void)
+{
+       rkpm_set_ops_prepare_finish(rk3036_pm_dump_inten, rk3036_pm_dump_irq);
+       rkpm_set_ops_printch(rk3036_ddr_printch);
+       rockchip_suspend_init();
+}
+#endif
+
+static void __init rk3036_init_late(void)
+{
+#ifdef CONFIG_PM
+       rk3036_suspend_init();
+#endif
+}
+
+static void __init rk3036_reserve(void)
+{
+       /* reserve memory for ION */
+       rockchip_ion_reserve();
+}
+
+static void rk3036_restart(char mode, const char *cmd)
+{
+       u32 boot_flag, boot_mode;
+
+       rockchip_restart_get_boot_mode(cmd, &boot_flag, &boot_mode);
+
+       writel_relaxed(boot_flag, RK_GRF_VIRT + RK3036_GRF_OS_REG4);    // for loader
+       writel_relaxed(boot_mode, RK_GRF_VIRT + RK3036_GRF_OS_REG5);    // for linux
+       dsb();
+
+       /* pll enter slow mode */
+       writel_relaxed(0x30110000, RK_CRU_VIRT + RK3036_CRU_MODE_CON);
+       dsb();
+       writel_relaxed(0xeca8, RK_CRU_VIRT + RK3036_CRU_GLB_SRST_SND_VALUE);
+       dsb();
+}
+
+static const char *const rk3036_dt_compat[] __initconst = {
+       "rockchip,rk3036",
+       NULL,
+};
+
+DT_MACHINE_START(RK3036_DT, "Rockchip RK3036")
+       .dt_compat      = rk3036_dt_compat,
+       .smp            = smp_ops(rockchip_smp_ops),
+       .reserve        = rk3036_reserve,
+       .map_io         = rk3036_dt_map_io,
+       .init_time      = rk3036_dt_init_timer,
+       .init_late      = rk3036_init_late,
+       .reserve        = rk3036_reserve,
+       .restart        = rk3036_restart,
+MACHINE_END
diff --git a/arch/arm/mach-rockchip/rk312x.c b/arch/arm/mach-rockchip/rk312x.c
new file mode 100755 (executable)
index 0000000..3280532
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Device Tree support for Rockchip RK3288
+ *
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/cpuidle.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/rockchip/common.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/cru.h>
+#include <linux/rockchip/dvfs.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/pmu.h>
+#include <asm/cpuidle.h>
+#include <asm/cputype.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include "cpu_axi.h"
+#include "loader.h"
+#define CPU 312x
+#include "sram.h"
+#include "pm.h"
+
+#define RK312X_DEVICE(name) \
+       { \
+               .virtual        = (unsigned long) RK_##name##_VIRT, \
+               .pfn            = __phys_to_pfn(RK312X_##name##_PHYS), \
+               .length         = RK312X_##name##_SIZE, \
+               .type           = MT_DEVICE, \
+       }
+
+static const char * const rk3126_dt_compat[] __initconst = {
+       "rockchip,rk3126",
+       NULL,
+};
+
+static const char * const rk3128_dt_compat[] __initconst = {
+       "rockchip,rk3128",
+       NULL,
+};
+
+#define RK312X_IMEM_VIRT (RK_BOOTRAM_VIRT + SZ_32K)
+#define RK312X_TIMER5_VIRT (RK_TIMER_VIRT + 0xa0)
+
+static struct map_desc rk312x_io_desc[] __initdata = {
+       RK312X_DEVICE(CRU),
+       RK312X_DEVICE(GRF),
+       RK312X_DEVICE(ROM),
+       RK312X_DEVICE(EFUSE),
+       RK312X_DEVICE(TIMER),
+       RK_DEVICE(RK_DEBUG_UART_VIRT, RK312X_UART2_PHYS, RK312X_UART_SIZE),
+       RK_DEVICE(RK_DDR_VIRT, RK312X_DDR_PCTL_PHYS, RK312X_DDR_PCTL_SIZE),
+       RK_DEVICE(RK_DDR_VIRT + RK312X_DDR_PCTL_SIZE, RK312X_DDR_PHY_PHYS, RK312X_DDR_PHY_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(0), RK312X_GPIO0_PHYS, RK312X_GPIO_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(1), RK312X_GPIO1_PHYS, RK312X_GPIO_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(2), RK312X_GPIO2_PHYS, RK312X_GPIO_SIZE),
+       RK_DEVICE(RK_GPIO_VIRT(3), RK312X_GPIO3_PHYS, RK312X_GPIO_SIZE),
+       RK_DEVICE(RK_GIC_VIRT, RK312X_GIC_DIST_PHYS, RK312X_GIC_DIST_SIZE),
+       RK_DEVICE(RK_GIC_VIRT + RK312X_GIC_DIST_SIZE, RK312X_GIC_CPU_PHYS, RK312X_GIC_CPU_SIZE),
+       RK_DEVICE(RK312X_IMEM_VIRT, RK312X_IMEM_PHYS, SZ_4K),
+};
+static void usb_uart_init(void)
+{
+#ifdef CONFIG_RK_USB_UART
+       u32 soc_status0 = readl_relaxed(RK_GRF_VIRT + RK312X_GRF_SOC_STATUS0);
+#endif
+       writel_relaxed(0x34000000, RK_GRF_VIRT + RK312X_GRF_UOC1_CON4);
+#ifdef CONFIG_RK_USB_UART
+       if (!(soc_status0 & (1 << 5)) && (soc_status0 & (1 << 8))) {
+               /* software control usb phy enable */
+               writel_relaxed(0x007f0055, RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+               writel_relaxed(0x34003000, RK_GRF_VIRT + RK312X_GRF_UOC1_CON4);
+       }
+#endif
+
+       writel_relaxed(0x07, RK_DEBUG_UART_VIRT + 0x88);
+       writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04);
+       writel_relaxed(0x83, RK_DEBUG_UART_VIRT + 0x0c);
+       writel_relaxed(0x0d, RK_DEBUG_UART_VIRT + 0x00);
+       writel_relaxed(0x00, RK_DEBUG_UART_VIRT + 0x04);
+       writel_relaxed(0x03, RK_DEBUG_UART_VIRT + 0x0c);
+}
+
+static void __init rk312x_dt_map_io(void)
+{
+       iotable_init(rk312x_io_desc, ARRAY_SIZE(rk312x_io_desc));
+       debug_ll_io_init();
+       usb_uart_init();
+
+       /* enable timer5 for core */
+       writel_relaxed(0, RK312X_TIMER5_VIRT + 0x10);
+       dsb();
+       writel_relaxed(0xFFFFFFFF, RK312X_TIMER5_VIRT + 0x00);
+       writel_relaxed(0xFFFFFFFF, RK312X_TIMER5_VIRT + 0x04);
+       dsb();
+       writel_relaxed(1, RK312X_TIMER5_VIRT + 0x10);
+       dsb();
+}
+
+static void __init rk3126_dt_map_io(void)
+{
+       rockchip_soc_id = ROCKCHIP_SOC_RK3126;
+
+       rk312x_dt_map_io();
+}
+
+static void __init rk3128_dt_map_io(void)
+{
+       rockchip_soc_id = ROCKCHIP_SOC_RK3128;
+
+       rk312x_dt_map_io();
+}
+
+extern void secondary_startup(void);
+static int rk312x_sys_set_power_domain(enum pmu_power_domain pd, bool on)
+{
+       if (on) {
+#ifdef CONFIG_SMP
+               if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
+                       writel_relaxed(0x20000 << (pd - PD_CPU_1),
+                                      RK_CRU_VIRT + RK312X_CRU_SOFTRSTS_CON(0));
+                       dsb();
+                       udelay(10);
+                       writel_relaxed(virt_to_phys(secondary_startup),
+                                      RK312X_IMEM_VIRT + 8);
+                       writel_relaxed(0xDEADBEAF, RK312X_IMEM_VIRT + 4);
+                       dsb_sev();
+               }
+#endif
+       } else {
+#ifdef CONFIG_SMP
+               if (pd >= PD_CPU_1 && pd <= PD_CPU_3) {
+                       writel_relaxed(0x20002 << (pd - PD_CPU_1),
+                                      RK_CRU_VIRT + RK312X_CRU_SOFTRSTS_CON(0));
+                       dsb();
+               }
+#endif
+       }
+
+       return 0;
+}
+
+static bool rk312x_pmu_power_domain_is_on(enum pmu_power_domain pd)
+{
+       return 1;
+}
+
+static int rk312x_pmu_set_idle_request(enum pmu_idle_req req, bool idle)
+{
+       return 0;
+}
+
+static void __init rk312x_dt_init_timer(void)
+{
+       rockchip_pmu_ops.set_power_domain = rk312x_sys_set_power_domain;
+       rockchip_pmu_ops.power_domain_is_on = rk312x_pmu_power_domain_is_on;
+       rockchip_pmu_ops.set_idle_request = rk312x_pmu_set_idle_request;
+       of_clk_init(NULL);
+       clocksource_of_init();
+       of_dvfs_init();
+}
+
+static void __init rk312x_reserve(void)
+{
+}
+
+static void __init rk312x_init_late(void)
+{
+}
+
+static void rk312x_restart(char mode, const char *cmd)
+{
+}
+
+DT_MACHINE_START(RK3126_DT, "Rockchip RK3126")
+       .smp            = smp_ops(rockchip_smp_ops),
+       .map_io         = rk3126_dt_map_io,
+       .init_time      = rk312x_dt_init_timer,
+       .dt_compat      = rk3126_dt_compat,
+       .init_late      = rk312x_init_late,
+       .reserve        = rk312x_reserve,
+       .restart        = rk312x_restart,
+MACHINE_END
+
+DT_MACHINE_START(RK3128_DT, "Rockchip RK3128")
+       .smp            = smp_ops(rockchip_smp_ops),
+       .map_io         = rk3128_dt_map_io,
+       .init_time      = rk312x_dt_init_timer,
+       .dt_compat      = rk3128_dt_compat,
+       .init_late      = rk312x_init_late,
+       .reserve        = rk312x_reserve,
+       .restart        = rk312x_restart,
+MACHINE_END
+
+
+char PIE_DATA(sram_stack)[1024];
+EXPORT_PIE_SYMBOL(DATA(sram_stack));
+
+static int __init rk312x_pie_init(void)
+{
+       int err;
+
+       if (!cpu_is_rk312x())
+               return 0;
+
+       err = rockchip_pie_init();
+       if (err)
+               return err;
+
+       rockchip_pie_chunk = pie_load_sections(rockchip_sram_pool, rk312x);
+       if (IS_ERR(rockchip_pie_chunk)) {
+               err = PTR_ERR(rockchip_pie_chunk);
+               pr_err("%s: failed to load section %d\n", __func__, err);
+               rockchip_pie_chunk = NULL;
+               return err;
+       }
+
+       rockchip_sram_virt = kern_to_pie(rockchip_pie_chunk, &__pie_common_start[0]);
+       rockchip_sram_stack = kern_to_pie(rockchip_pie_chunk, (char *)DATA(sram_stack) + sizeof(DATA(sram_stack)));
+
+       return 0;
+}
+arch_initcall(rk312x_pie_init);
index 1d410e28d9ab5aca7d01681348fc57c84fa744ae..45e13034fd24f7a5a97f0bf0edf46174c9c19d02 100755 (executable)
@@ -37,7 +37,8 @@
 #include <linux/rockchip/cru.h>\r
 \r
 #include <asm/cacheflush.h>\r
-#include <asm/uaccess.h>\r
+#include <linux/uaccess.h>\r
+#include <linux/rockchip/grf.h>\r
 \r
 #if defined(CONFIG_ION_ROCKCHIP)\r
 #include <linux/rockchip_ion.h>\r
 \r
 #include "vcodec_service.h"\r
 \r
-#define HEVC_TEST_ENABLE    0\r
-#define HEVC_SIM_ENABLE     0\r
-#define VCODEC_CLOCK_ENABLE 1\r
+#define HEVC_TEST_ENABLE       0\r
+#define HEVC_SIM_ENABLE                0\r
+#define VCODEC_CLOCK_ENABLE    1\r
 \r
 typedef enum {\r
        VPU_DEC_ID_9190         = 0x6731,\r
        VPU_ID_8270             = 0x8270,\r
        VPU_ID_4831             = 0x4831,\r
-    HEVC_ID         = 0x6867,\r
+       HEVC_ID                 = 0x6867,\r
 } VPU_HW_ID;\r
 \r
 typedef enum {\r
@@ -85,8 +86,8 @@ typedef enum VPU_FREQ {
        VPU_FREQ_266M,\r
        VPU_FREQ_300M,\r
        VPU_FREQ_400M,\r
-    VPU_FREQ_500M,\r
-    VPU_FREQ_600M,\r
+       VPU_FREQ_500M,\r
+       VPU_FREQ_600M,\r
        VPU_FREQ_DEFAULT,\r
        VPU_FREQ_BUT,\r
 } VPU_FREQ;\r
@@ -123,7 +124,7 @@ static struct timeval pp_start,  pp_end;
 #define REG_NUM_ENC_4831                       (164)\r
 #define REG_SIZE_ENC_4831                      (0x400)\r
 \r
-#define REG_NUM_HEVC_DEC            (68)\r
+#define REG_NUM_HEVC_DEC                       (68)\r
 \r
 #define SIZE_REG(reg)                          ((reg)*4)\r
 \r
@@ -136,7 +137,7 @@ static VPU_HW_INFO_E vpu_hw_set[] = {
                .enc_io_size    = REG_NUM_ENC_8270 * 4,\r
                .dec_offset     = REG_SIZE_ENC_8270,\r
                .dec_reg_num    = REG_NUM_9190_DEC_PP,\r
-               .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
+               .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
        },\r
        [1] = {\r
                .hw_id          = VPU_ID_4831,\r
@@ -146,31 +147,42 @@ static VPU_HW_INFO_E vpu_hw_set[] = {
                .enc_io_size    = REG_NUM_ENC_4831 * 4,\r
                .dec_offset     = REG_SIZE_ENC_4831,\r
                .dec_reg_num    = REG_NUM_9190_DEC_PP,\r
-               .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
+               .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
        },\r
-    [2] = {\r
-        .hw_id      = HEVC_ID,\r
-        .hw_addr    = 0,\r
-        .dec_offset = 0x0,\r
-        .dec_reg_num    = REG_NUM_HEVC_DEC,\r
-        .dec_io_size    = REG_NUM_HEVC_DEC * 4,\r
-    },\r
+       [2] = {\r
+               .hw_id          = HEVC_ID,\r
+               .hw_addr        = 0,\r
+               .dec_offset     = 0x0,\r
+               .dec_reg_num    = REG_NUM_HEVC_DEC,\r
+               .dec_io_size    = REG_NUM_HEVC_DEC * 4,\r
+       },\r
+       [3] = {\r
+               .hw_id          = VPU_DEC_ID_9190,\r
+               .hw_addr        = 0,\r
+               .enc_offset     = 0x0,\r
+               .enc_reg_num    = 0,\r
+               .enc_io_size    = 0,\r
+               .dec_offset     = REG_SIZE_ENC_4831,\r
+               .dec_reg_num    = REG_NUM_9190_DEC_PP,\r
+               .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
+       },\r
+       \r
 };\r
 \r
 \r
-#define DEC_INTERRUPT_REGISTER                 1\r
-#define PP_INTERRUPT_REGISTER                  60\r
-#define ENC_INTERRUPT_REGISTER                 1\r
+#define DEC_INTERRUPT_REGISTER                 1\r
+#define PP_INTERRUPT_REGISTER                  60\r
+#define ENC_INTERRUPT_REGISTER                 1\r
 \r
 #define DEC_INTERRUPT_BIT                      0x100\r
 #define DEC_BUFFER_EMPTY_BIT                   0x4000\r
 #define PP_INTERRUPT_BIT                       0x100\r
 #define ENC_INTERRUPT_BIT                      0x1\r
 \r
-#define HEVC_DEC_INT_RAW_BIT        0x200\r
-#define HEVC_DEC_STR_ERROR_BIT      0x4000\r
-#define HEVC_DEC_BUS_ERROR_BIT      0x2000\r
-#define HEVC_DEC_BUFFER_EMPTY_BIT   0x10000\r
+#define HEVC_DEC_INT_RAW_BIT                   0x200\r
+#define HEVC_DEC_STR_ERROR_BIT                 0x4000\r
+#define HEVC_DEC_BUS_ERROR_BIT                 0x2000\r
+#define HEVC_DEC_BUFFER_EMPTY_BIT              0x10000\r
 \r
 #define VPU_REG_EN_ENC                         14\r
 #define VPU_REG_ENC_GATE                       2\r
@@ -188,7 +200,8 @@ static VPU_HW_INFO_E vpu_hw_set[] = {
 \r
 #if defined(CONFIG_VCODEC_MMU)\r
 static u8 addr_tbl_vpu_h264dec[] = {\r
-       12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 41\r
+       12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\r
+       25, 26, 27, 28, 29, 40, 41\r
 };\r
 \r
 static u8 addr_tbl_vpu_vp8dec[] = {\r
@@ -216,7 +229,8 @@ static u8 addr_tbl_vpu_enc[] = {
 };\r
 \r
 static u8 addr_tbl_hevc_dec[] = {\r
-       4, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43\r
+       4, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,\r
+       21, 22, 23, 24, 42, 43\r
 };\r
 #endif\r
 \r
@@ -267,7 +281,7 @@ typedef struct vpu_session {
  */\r
 typedef struct vpu_reg {\r
        VPU_CLIENT_TYPE         type;\r
-       VPU_FREQ                    freq;\r
+       VPU_FREQ                freq;\r
        vpu_session             *session;\r
        struct list_head        session_link;           /* link to vpu service session */\r
        struct list_head        status_link;            /* link to register set list */\r
@@ -292,12 +306,12 @@ enum vcodec_device_id {
 };\r
 \r
 struct vcodec_mem_region {\r
-    struct list_head srv_lnk;\r
-    struct list_head reg_lnk;\r
-    struct list_head session_lnk;\r
-    unsigned long iova;              /* virtual address for iommu */\r
-    unsigned long len;\r
-    struct ion_handle *hdl;\r
+       struct list_head srv_lnk;\r
+       struct list_head reg_lnk;\r
+       struct list_head session_lnk;\r
+       unsigned long iova;     /* virtual address for iommu */\r
+       unsigned long len;\r
+       struct ion_handle *hdl;\r
 };\r
 \r
 typedef struct vpu_service_info {\r
@@ -321,49 +335,53 @@ typedef struct vpu_service_info {
        bool                    bug_dec_addr;\r
        atomic_t                freq_status;\r
 \r
-    struct clk *aclk_vcodec;\r
-    struct clk *hclk_vcodec;\r
-    struct clk *clk_core;\r
-    struct clk *clk_cabac;\r
-    struct clk *pd_video;\r
+       struct clk              *aclk_vcodec;\r
+       struct clk              *hclk_vcodec;\r
+       struct clk              *clk_core;\r
+       struct clk              *clk_cabac;\r
+       struct clk              *pd_video;\r
 \r
-    int irq_dec;\r
-    int irq_enc;\r
+       int                     irq_dec;\r
+       int                     irq_enc;\r
 \r
-    vpu_device enc_dev;\r
-    vpu_device dec_dev;\r
+       vpu_device              enc_dev;\r
+       vpu_device              dec_dev;\r
 \r
-    struct device   *dev;\r
+       struct device           *dev;\r
 \r
-    struct cdev     cdev;\r
-    dev_t           dev_t;\r
-    struct class    *cls;\r
-    struct device   *child_dev;\r
+       struct cdev             cdev;\r
+       dev_t                   dev_t;\r
+       struct class            *cls;\r
+       struct device           *child_dev;\r
 \r
-    struct dentry   *debugfs_dir;\r
-    struct dentry   *debugfs_file_regs;\r
+       struct dentry           *debugfs_dir;\r
+       struct dentry           *debugfs_file_regs;\r
 \r
-    u32 irq_status;\r
+       u32 irq_status;\r
 #if defined(CONFIG_VCODEC_MMU) \r
-       struct ion_client ion_client;\r
-    struct list_head mem_region_list;\r
-    struct device *mmu_dev;\r
+       struct ion_client       *ion_client;\r
+       struct list_head        mem_region_list;\r
+       struct device           *mmu_dev;\r
 #endif\r
 \r
-       enum vcodec_device_id dev_id;\r
+       enum vcodec_device_id   dev_id;\r
 \r
-    struct delayed_work simulate_work;\r
+       u32                     reserved_mode;\r
+\r
+       struct delayed_work     simulate_work;\r
 } vpu_service_info;\r
 \r
 typedef struct vpu_request\r
 {\r
-       unsigned long   *req;\r
-       unsigned long   size;\r
+       unsigned long *req;\r
+       unsigned long size;\r
 } vpu_request;\r
 \r
 /// global variable\r
 //static struct clk *pd_video;\r
 static struct dentry *parent; // debugfs root directory for all device (vpu, hevc).\r
+/* mutex for selecting operation registers of vpu or hevc */\r
+static struct mutex g_mode_mutex;\r
 \r
 #ifdef CONFIG_DEBUG_FS\r
 static int vcodec_debugfs_init(void);\r
@@ -372,91 +390,136 @@ static struct dentry* vcodec_debugfs_create_device_dir(char *dirname, struct den
 static int debug_vcodec_open(struct inode *inode, struct file *file);\r
 \r
 static const struct file_operations debug_vcodec_fops = {\r
-    .open = debug_vcodec_open,\r
-    .read = seq_read,\r
-    .llseek = seq_lseek,\r
-    .release = single_release,\r
+       .open = debug_vcodec_open,\r
+       .read = seq_read,\r
+       .llseek = seq_lseek,\r
+       .release = single_release,\r
 };\r
 #endif\r
 \r
 #define VPU_POWER_OFF_DELAY            4*HZ /* 4s */\r
 #define VPU_TIMEOUT_DELAY              2*HZ /* 2s */\r
+#define VPU_SIMULATE_DELAY             msecs_to_jiffies(15)\r
+\r
+static void vcodec_enter_mode_nolock(enum vcodec_device_id id, u32 *reserved_mode)\r
+{\r
+       if (soc_is_rk3036()) {\r
+               if (reserved_mode)\r
+                       *reserved_mode = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1);\r
+#define BIT_VCODEC_SEL         (1<<3)\r
+               if (id == VCODEC_DEVICE_ID_HEVC) {\r
+                       writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) | (BIT_VCODEC_SEL) | (BIT_VCODEC_SEL << 16), RK_GRF_VIRT + RK3036_GRF_SOC_CON1);\r
+               } else {\r
+                       writel_relaxed((readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) & (~BIT_VCODEC_SEL)) | (BIT_VCODEC_SEL << 16), RK_GRF_VIRT + RK3036_GRF_SOC_CON1);\r
+               }\r
+       }\r
+}\r
+\r
+static void vcodec_exit_mode_nolock(enum vcodec_device_id id, u32 reserved_mode)\r
+{\r
+       writel_relaxed(reserved_mode | (BIT_VCODEC_SEL << 16), RK_GRF_VIRT + RK3036_GRF_SOC_CON1);\r
+}\r
+\r
+static void vcodec_enter_mode(enum vcodec_device_id id)\r
+{\r
+       if (soc_is_rk3036())\r
+               mutex_lock(&g_mode_mutex);\r
+       vcodec_enter_mode_nolock(id, NULL);\r
+}\r
 \r
-#define VPU_SIMULATE_DELAY      msecs_to_jiffies(15)\r
+static void vcodec_exit_mode(void)\r
+{\r
+       if (soc_is_rk3036())\r
+               mutex_unlock(&g_mode_mutex);\r
+}\r
 \r
 static int vpu_get_clk(struct vpu_service_info *pservice)\r
 {\r
 #if VCODEC_CLOCK_ENABLE\r
-    do {\r
-        pservice->aclk_vcodec   = devm_clk_get(pservice->dev, "aclk_vcodec");\r
-        if (IS_ERR(pservice->aclk_vcodec)) {\r
-            dev_err(pservice->dev, "failed on clk_get aclk_vcodec\n");\r
-            break;\r
-        }\r
-    \r
-        pservice->hclk_vcodec   = devm_clk_get(pservice->dev, "hclk_vcodec");\r
-        if (IS_ERR(pservice->hclk_vcodec)) {\r
-            dev_err(pservice->dev, "failed on clk_get hclk_vcodec\n");\r
-            break;\r
-        }\r
-    \r
-        if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
-            pservice->clk_core = devm_clk_get(pservice->dev, "clk_core");\r
-            if (IS_ERR(pservice->clk_core)) {\r
-                dev_err(pservice->dev, "failed on clk_get clk_core\n");\r
-                break;\r
-            }\r
-    \r
-            pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");\r
-            if (IS_ERR(pservice->clk_cabac)) {\r
-                dev_err(pservice->dev, "failed on clk_get clk_cabac\n");\r
-                break;\r
-            }\r
-            \r
-            pservice->pd_video = devm_clk_get(pservice->dev, "pd_hevc");\r
-            if (IS_ERR(pservice->pd_video)) {\r
-                dev_err(pservice->dev, "failed on clk_get pd_hevc\n");\r
-                break;\r
-            }\r
-        } else {\r
-            pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");\r
-            if (IS_ERR(pservice->pd_video)) {\r
-                dev_err(pservice->dev, "failed on clk_get pd_video\n");\r
-                break;\r
-            }\r
-        }\r
-        \r
-        return 0;\r
-    } while (0);\r
-    \r
-    return -1;\r
+       do {\r
+               pservice->aclk_vcodec   = devm_clk_get(pservice->dev, "aclk_vcodec");\r
+               if (IS_ERR(pservice->aclk_vcodec)) {\r
+                       dev_err(pservice->dev, "failed on clk_get aclk_vcodec\n");\r
+                       break;\r
+               }\r
+\r
+               pservice->hclk_vcodec   = devm_clk_get(pservice->dev, "hclk_vcodec");\r
+               if (IS_ERR(pservice->hclk_vcodec)) {\r
+                       dev_err(pservice->dev, "failed on clk_get hclk_vcodec\n");\r
+                       break;\r
+               }\r
+\r
+               if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
+                       pservice->clk_core = devm_clk_get(pservice->dev, "clk_core");\r
+                       if (IS_ERR(pservice->clk_core)) {\r
+                               dev_err(pservice->dev, "failed on clk_get clk_core\n");\r
+                               break;\r
+                       }\r
+\r
+                       if (!soc_is_rk3036()) {\r
+                               pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");\r
+                               if (IS_ERR(pservice->clk_cabac)) {\r
+                                       dev_err(pservice->dev, "failed on clk_get clk_cabac\n");\r
+                                       break;\r
+                               }\r
+                       } else {\r
+                               pservice->clk_cabac = NULL;\r
+                       }\r
+\r
+                       if (!soc_is_rk3036()) {\r
+                               pservice->pd_video = devm_clk_get(pservice->dev, "pd_hevc");\r
+                               if (IS_ERR(pservice->pd_video)) {\r
+                                       dev_err(pservice->dev, "failed on clk_get pd_hevc\n");\r
+                                       break;\r
+                               }\r
+                       } else {\r
+                               pservice->pd_video = NULL;\r
+                       }\r
+               } else {\r
+                       if (!soc_is_rk3036()) {\r
+                               pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");\r
+                               if (IS_ERR(pservice->pd_video)) {\r
+                                       dev_err(pservice->dev, "failed on clk_get pd_video\n");\r
+                                       break;\r
+                               }\r
+                       } else {\r
+                               pservice->pd_video = NULL;\r
+                       }\r
+               }\r
+\r
+               return 0;\r
+       } while (0);\r
+\r
+       return -1;\r
+#else\r
+       return 0;\r
 #endif\r
 }\r
 \r
 static void vpu_put_clk(struct vpu_service_info *pservice)\r
 {\r
 #if VCODEC_CLOCK_ENABLE\r
-    if (pservice->pd_video) {\r
-        devm_clk_put(pservice->dev, pservice->pd_video);\r
-    }\r
-\r
-    if (pservice->aclk_vcodec) {\r
-        devm_clk_put(pservice->dev, pservice->aclk_vcodec);\r
-    }\r
-\r
-    if (pservice->hclk_vcodec) {\r
-        devm_clk_put(pservice->dev, pservice->hclk_vcodec);\r
-    }\r
-\r
-    if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
-        if (pservice->clk_core) {\r
-            devm_clk_put(pservice->dev, pservice->clk_core);\r
-        }\r
-        \r
-        if (pservice->clk_cabac) {\r
-            devm_clk_put(pservice->dev, pservice->clk_cabac);\r
-        }\r
-    }\r
+       if (pservice->pd_video) {\r
+               devm_clk_put(pservice->dev, pservice->pd_video);\r
+       }\r
+\r
+       if (pservice->aclk_vcodec) {\r
+               devm_clk_put(pservice->dev, pservice->aclk_vcodec);\r
+       }\r
+\r
+       if (pservice->hclk_vcodec) {\r
+               devm_clk_put(pservice->dev, pservice->hclk_vcodec);\r
+       }\r
+\r
+       if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
+               if (pservice->clk_core) {\r
+                       devm_clk_put(pservice->dev, pservice->clk_core);\r
+               }\r
+\r
+               if (pservice->clk_cabac) {\r
+                       devm_clk_put(pservice->dev, pservice->clk_cabac);\r
+               }\r
+       }\r
 #endif\r
 }\r
 \r
@@ -538,39 +601,42 @@ static void vpu_service_dump(struct vpu_service_info *pservice)
 \r
 static void vpu_service_power_off(struct vpu_service_info *pservice)\r
 {\r
-    int total_running;\r
-    if (!pservice->enabled) {\r
-        return;\r
-    }\r
-\r
-    pservice->enabled = false;\r
-    total_running = atomic_read(&pservice->total_running);\r
-    if (total_running) {\r
-        pr_alert("alert: power off when %d task running!!\n", total_running);\r
-        mdelay(50);\r
-        pr_alert("alert: delay 50 ms for running task\n");\r
-        vpu_service_dump(pservice);\r
-    }\r
-    \r
+       int total_running;\r
+       if (!pservice->enabled)\r
+               return;\r
+\r
+       pservice->enabled = false;\r
+       total_running = atomic_read(&pservice->total_running);\r
+       if (total_running) {\r
+               pr_alert("alert: power off when %d task running!!\n", total_running);\r
+               mdelay(50);\r
+               pr_alert("alert: delay 50 ms for running task\n");\r
+               vpu_service_dump(pservice);\r
+       }\r
+\r
 #if defined(CONFIG_VCODEC_MMU)\r
-    if (pservice->mmu_dev) {\r
-        iovmm_deactivate(pservice->dev);\r
-    }\r
-#endif \r
+       if (pservice->mmu_dev)\r
+               iovmm_deactivate(pservice->dev);\r
+#endif\r
 \r
-    printk("%s: power off...", dev_name(pservice->dev));\r
-    udelay(10);\r
+       pr_info("%s: power off...", dev_name(pservice->dev));\r
+       udelay(10);\r
 #if VCODEC_CLOCK_ENABLE\r
-    clk_disable_unprepare(pservice->pd_video);\r
-    clk_disable_unprepare(pservice->hclk_vcodec);\r
-    clk_disable_unprepare(pservice->aclk_vcodec);\r
-    if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
-        clk_disable_unprepare(pservice->clk_core);\r
-        clk_disable_unprepare(pservice->clk_cabac);\r
-    }\r
+       if (pservice->pd_video)\r
+               clk_disable_unprepare(pservice->pd_video);\r
+       if (pservice->hclk_vcodec)\r
+               clk_disable_unprepare(pservice->hclk_vcodec);\r
+       if (pservice->aclk_vcodec)\r
+               clk_disable_unprepare(pservice->aclk_vcodec);\r
+       if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
+               if (pservice->clk_core)\r
+                       clk_disable_unprepare(pservice->clk_core);\r
+               if (pservice->clk_cabac)\r
+                       clk_disable_unprepare(pservice->clk_cabac);\r
+       }\r
 #endif\r
-    wake_unlock(&pservice->wake_lock);\r
-    printk("done\n");\r
+       wake_unlock(&pservice->wake_lock);\r
+       pr_info("done\n");\r
 }\r
 \r
 static inline void vpu_queue_power_off_work(struct vpu_service_info *pservice)\r
@@ -580,8 +646,8 @@ static inline void vpu_queue_power_off_work(struct vpu_service_info *pservice)
 \r
 static void vpu_power_off_work(struct work_struct *work_s)\r
 {\r
-    struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
-    struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, power_off_work);\r
+       struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
+       struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, power_off_work);\r
 \r
        if (mutex_trylock(&pservice->lock)) {\r
                vpu_service_power_off(pservice);\r
@@ -594,45 +660,52 @@ static void vpu_power_off_work(struct work_struct *work_s)
 \r
 static void vpu_service_power_on(struct vpu_service_info *pservice)\r
 {\r
-    static ktime_t last;\r
-    ktime_t now = ktime_get();\r
-    if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) {\r
-        cancel_delayed_work_sync(&pservice->power_off_work);\r
-        vpu_queue_power_off_work(pservice);\r
-        last = now;\r
-    }\r
-    if (pservice->enabled)\r
-        return ;\r
-\r
-    pservice->enabled = true;\r
-    printk("%s: power on\n", dev_name(pservice->dev));\r
+       static ktime_t last;\r
+       ktime_t now = ktime_get();\r
+       if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) {\r
+               cancel_delayed_work_sync(&pservice->power_off_work);\r
+               vpu_queue_power_off_work(pservice);\r
+               last = now;\r
+       }\r
+       if (pservice->enabled)\r
+               return ;\r
+\r
+       pservice->enabled = true;\r
+       printk("%s: power on\n", dev_name(pservice->dev));\r
 \r
 #if VCODEC_CLOCK_ENABLE\r
-    clk_prepare_enable(pservice->aclk_vcodec);\r
-    clk_prepare_enable(pservice->hclk_vcodec);\r
-\r
-    if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
-        clk_prepare_enable(pservice->clk_core);\r
-        clk_prepare_enable(pservice->clk_cabac);\r
-    }\r
-    \r
-    clk_prepare_enable(pservice->pd_video);\r
+       if (pservice->aclk_vcodec)\r
+               clk_prepare_enable(pservice->aclk_vcodec);\r
+\r
+       if (pservice->hclk_vcodec)\r
+               clk_prepare_enable(pservice->hclk_vcodec);\r
+\r
+       if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
+               if (pservice->clk_core)\r
+                       clk_prepare_enable(pservice->clk_core);\r
+       if (pservice->clk_cabac)\r
+               clk_prepare_enable(pservice->clk_cabac);\r
+       }\r
+\r
+       if (pservice->pd_video)\r
+               clk_prepare_enable(pservice->pd_video);\r
 #endif\r
 \r
 #if defined(CONFIG_ARCH_RK319X)\r
-    /// select aclk_vepu as vcodec clock source. \r
-    #define BIT_VCODEC_SEL  (1<<7)\r
-    writel_relaxed(readl_relaxed(RK319X_GRF_BASE + GRF_SOC_CON1) | (BIT_VCODEC_SEL) | (BIT_VCODEC_SEL << 16), RK319X_GRF_BASE + GRF_SOC_CON1);\r
+       /// select aclk_vepu as vcodec clock source. \r
+#define BIT_VCODEC_SEL (1<<7)\r
+       writel_relaxed(readl_relaxed(RK319X_GRF_BASE + GRF_SOC_CON1) |\r
+               (BIT_VCODEC_SEL) | (BIT_VCODEC_SEL << 16),\r
+               RK319X_GRF_BASE + GRF_SOC_CON1);\r
+#endif\r
+\r
+       udelay(10);\r
+       wake_lock(&pservice->wake_lock);\r
+\r
+#if defined(CONFIG_VCODEC_MMU)\r
+       if (pservice->mmu_dev)\r
+               iovmm_activate(pservice->dev);\r
 #endif\r
-    \r
-    udelay(10);\r
-    wake_lock(&pservice->wake_lock);\r
-    \r
-#if defined(CONFIG_VCODEC_MMU)    \r
-    if (pservice->mmu_dev) {\r
-        iovmm_activate(pservice->dev);\r
-    }\r
-#endif    \r
 }\r
 \r
 static inline bool reg_check_rmvb_wmv(vpu_reg *reg)\r
@@ -655,9 +728,8 @@ static inline enum VPU_DEC_FMT reg_check_fmt(vpu_reg *reg)
 \r
 static inline int reg_probe_width(vpu_reg *reg)\r
 {\r
-    int width_in_mb = reg->reg[4] >> 23;\r
-    \r
-    return width_in_mb * 16;\r
+       int width_in_mb = reg->reg[4] >> 23;\r
+       return width_in_mb * 16;\r
 }\r
 \r
 #if defined(CONFIG_VCODEC_MMU)\r
@@ -677,12 +749,12 @@ static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int
        for (i = 0; i < size; i++) {\r
                usr_fd = reg->reg[tbl[i]] & 0x3FF;\r
 \r
-               if (tbl[i] == 41 && pservice->hw_info->hw_id != HEVC_ID && (reg->type == VPU_DEC || reg->type == VPU_DEC_PP)) {\r
+               if (tbl[i] == 41 && pservice->hw_info->hw_id != HEVC_ID &&\r
+                   (reg->type == VPU_DEC || reg->type == VPU_DEC_PP))\r
                        /* special for vpu dec num 41 regitster */\r
                        offset = reg->reg[tbl[i]] >> 10 << 4;\r
-               } else {\r
+               else\r
                        offset = reg->reg[tbl[i]] >> 10;\r
-               }\r
 \r
                if (usr_fd != 0) {\r
                        struct ion_handle *hdl;\r
@@ -705,7 +777,9 @@ static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl, int
 \r
                        mem_region->hdl = hdl;\r
 \r
+                       vcodec_enter_mode(pservice->dev_id);\r
                        ret = ion_map_iommu(pservice->dev, pservice->ion_client, mem_region->hdl, &mem_region->iova, &mem_region->len);\r
+                       vcodec_exit_mode();\r
                        if (ret < 0) {\r
                                dev_err(pservice->dev, "ion map iommu failed\n");\r
                                kfree(mem_region);\r
@@ -807,9 +881,8 @@ static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session
        INIT_LIST_HEAD(&reg->status_link);\r
 \r
 #if defined(CONFIG_VCODEC_MMU)  \r
-        if (pservice->mmu_dev) {\r
-            INIT_LIST_HEAD(&reg->mem_region_list);\r
-        }\r
+       if (pservice->mmu_dev)\r
+               INIT_LIST_HEAD(&reg->mem_region_list);\r
 #endif\r
 \r
        if (copy_from_user(&reg->reg[0], (void __user *)src, size)) {\r
@@ -873,7 +946,13 @@ static void reg_deinit(struct vpu_service_info *pservice, vpu_reg *reg)
        // release memory region attach to this registers table.\r
        if (pservice->mmu_dev) {\r
                list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {\r
-                       ion_unmap_iommu(pservice->dev, pservice->ion_client, mem_region->hdl);\r
+                       /* do not unmap iommu manually,\r
+                          unmap will proccess when memory release */\r
+                       /*vcodec_enter_mode(pservice->dev_id);\r
+                       ion_unmap_iommu(pservice->dev,\r
+                                       pservice->ion_client,\r
+                                       mem_region->hdl);\r
+                       vcodec_exit_mode();*/\r
                        ion_free(pservice->ion_client, mem_region->hdl);\r
                        list_del_init(&mem_region->reg_lnk);\r
                        kfree(mem_region);\r
@@ -893,10 +972,11 @@ static void reg_from_wait_to_run(struct vpu_service_info *pservice, vpu_reg *reg
        list_add_tail(&reg->session_link, &reg->session->running);\r
 }\r
 \r
-static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count)\r
+static void reg_copy_from_hw(struct vpu_service_info *pservice, vpu_reg *reg, volatile u32 *src, u32 count)\r
 {\r
        int i;\r
        u32 *dst = (u32 *)&reg->reg[0];\r
+\r
        for (i = 0; i < count; i++)\r
                *dst++ = *src++;\r
 }\r
@@ -910,30 +990,31 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg
        list_del_init(&reg->session_link);\r
        list_add_tail(&reg->session_link, &reg->session->done);\r
 \r
+       vcodec_enter_mode(pservice->dev_id);\r
        switch (reg->type) {\r
        case VPU_ENC : {\r
                pservice->reg_codec = NULL;\r
-               reg_copy_from_hw(reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);\r
+               reg_copy_from_hw(pservice, reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);\r
                irq_reg = ENC_INTERRUPT_REGISTER;\r
                break;\r
        }\r
        case VPU_DEC : {\r
                int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;\r
                pservice->reg_codec = NULL;\r
-               reg_copy_from_hw(reg, pservice->dec_dev.hwregs, reg_len);\r
+               reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs, reg_len);\r
                irq_reg = DEC_INTERRUPT_REGISTER;\r
                break;\r
        }\r
        case VPU_PP : {\r
                pservice->reg_pproc = NULL;\r
-               reg_copy_from_hw(reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);\r
+               reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);\r
                pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
                break;\r
        }\r
        case VPU_DEC_PP : {\r
                pservice->reg_codec = NULL;\r
                pservice->reg_pproc = NULL;\r
-               reg_copy_from_hw(reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);\r
+               reg_copy_from_hw(pservice, reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);\r
                pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
                break;\r
        }\r
@@ -942,6 +1023,7 @@ static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg
                break;\r
        }\r
        }\r
+       vcodec_exit_mode();\r
 \r
        if (irq_reg != -1) {\r
                reg->reg[irq_reg] = pservice->irq_status;\r
@@ -1005,6 +1087,9 @@ static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)
        if (pservice->auto_freq) {\r
                vpu_service_set_freq(pservice, reg);\r
        }\r
+\r
+       vcodec_enter_mode(pservice->dev_id);\r
+\r
        switch (reg->type) {\r
        case VPU_ENC : {\r
                int enc_count = pservice->hw_info->enc_reg_num;\r
@@ -1107,6 +1192,8 @@ static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)
        }\r
        }\r
 \r
+       vcodec_exit_mode();\r
+\r
 #if HEVC_SIM_ENABLE\r
        if (pservice->hw_info->hw_id == HEVC_ID) {\r
                simulate_start(pservice);\r
@@ -1296,9 +1383,9 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long
        case VPU_IOC_PROBE_IOMMU_STATUS: {\r
                int iommu_enable = 0;\r
 \r
-#if defined(CONFIG_VCODEC_MMU)                \r
-                iommu_enable = pservice->mmu_dev ? 1 : 0; \r
-#endif                \r
+#if defined(CONFIG_VCODEC_MMU)\r
+               iommu_enable = pservice->mmu_dev ? 1 : 0; \r
+#endif\r
 \r
                if (copy_to_user((void __user *)arg, &iommu_enable, sizeof(int))) {\r
                        pr_err("error: VPU_IOC_PROBE_IOMMU_STATUS copy_to_user failed\n");\r
@@ -1314,7 +1401,7 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long
 \r
        return 0;\r
 }\r
-\r
+#if 1\r
 static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)\r
 {\r
        int ret = -EINVAL, i = 0;\r
@@ -1328,7 +1415,6 @@ static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
                return 0;\r
        }\r
 #endif\r
-\r
        enc_id = (enc_id >> 16) & 0xFFFF;\r
        pr_info("checking hw id %x\n", enc_id);\r
        p->hw_info = NULL;\r
@@ -1342,6 +1428,7 @@ static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
        iounmap((void *)tmp);\r
        return ret;\r
 }\r
+#endif\r
 \r
 static int vpu_service_open(struct inode *inode, struct file *filp)\r
 {\r
@@ -1412,28 +1499,28 @@ static void get_hw_info(struct vpu_service_info *pservice);
 #if HEVC_SIM_ENABLE\r
 static void simulate_work(struct work_struct *work_s)\r
 {\r
-    struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
-    struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, simulate_work);\r
-    vpu_device *dev = &pservice->dec_dev;\r
-\r
-    if (!list_empty(&pservice->running)) {\r
-        atomic_add(1, &dev->irq_count_codec);\r
-        vdpu_isr(0, (void*)pservice);\r
-    } else {\r
-        //simulate_start(pservice);\r
-        pr_err("empty running queue\n");\r
-    }\r
+       struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
+       struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, simulate_work);\r
+       vpu_device *dev = &pservice->dec_dev;\r
+\r
+       if (!list_empty(&pservice->running)) {\r
+               atomic_add(1, &dev->irq_count_codec);\r
+               vdpu_isr(0, (void*)pservice);\r
+       } else {\r
+               //simulate_start(pservice);\r
+               pr_err("empty running queue\n");\r
+       }\r
 }\r
 \r
 static void simulate_init(struct vpu_service_info *pservice)\r
 {\r
-    INIT_DELAYED_WORK(&pservice->simulate_work, simulate_work);\r
+       INIT_DELAYED_WORK(&pservice->simulate_work, simulate_work);\r
 }\r
 \r
 static void simulate_start(struct vpu_service_info *pservice)\r
 {\r
-    cancel_delayed_work_sync(&pservice->power_off_work);\r
-    queue_delayed_work(system_nrt_wq, &pservice->simulate_work, VPU_SIMULATE_DELAY);\r
+       cancel_delayed_work_sync(&pservice->power_off_work);\r
+       queue_delayed_work(system_nrt_wq, &pservice->simulate_work, VPU_SIMULATE_DELAY);\r
 }\r
 #endif\r
 \r
@@ -1445,488 +1532,497 @@ extern struct ion_client *rockchip_ion_client_create(const char * name);
 #endif\r
 static int vcodec_probe(struct platform_device *pdev)\r
 {\r
-    int ret = 0;\r
-    struct resource *res = NULL;\r
-    struct device *dev = &pdev->dev;\r
-    void __iomem *regs = NULL;\r
-    struct device_node *np = pdev->dev.of_node;\r
-    struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);\r
-    char *prop = (char*)dev_name(dev);\r
+       int ret = 0;\r
+       struct resource *res = NULL;\r
+       struct device *dev = &pdev->dev;\r
+       void __iomem *regs = NULL;\r
+       struct device_node *np = pdev->dev.of_node;\r
+       struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);\r
+       char *prop = (char*)dev_name(dev);\r
 #if defined(CONFIG_VCODEC_MMU)\r
-    char mmu_dev_dts_name[40];\r
+       char mmu_dev_dts_name[40];\r
 #endif\r
 \r
-    pr_info("probe device %s\n", dev_name(dev));\r
-\r
-    of_property_read_string(np, "name", (const char**)&prop);\r
-    dev_set_name(dev, prop);\r
-\r
-    if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
-        pservice->dev_id = VCODEC_DEVICE_ID_HEVC;\r
-    } else if (strcmp(dev_name(dev), "vpu_service") == 0) {\r
-        pservice->dev_id = VCODEC_DEVICE_ID_VPU;\r
-    } else {\r
-        dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));\r
-        return -1;\r
-    }\r
-\r
-    wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");\r
-    INIT_LIST_HEAD(&pservice->waiting);\r
-    INIT_LIST_HEAD(&pservice->running);\r
-    INIT_LIST_HEAD(&pservice->done);\r
-    INIT_LIST_HEAD(&pservice->session);\r
-    mutex_init(&pservice->lock);\r
-    pservice->reg_codec        = NULL;\r
-    pservice->reg_pproc        = NULL;\r
-    atomic_set(&pservice->total_running, 0);\r
-    pservice->enabled = false;\r
+       pr_info("probe device %s\n", dev_name(dev));\r
+\r
+       of_property_read_string(np, "name", (const char**)&prop);\r
+       dev_set_name(dev, prop);\r
+\r
+       if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
+               pservice->dev_id = VCODEC_DEVICE_ID_HEVC;\r
+       } else if (strcmp(dev_name(dev), "vpu_service") == 0) {\r
+               pservice->dev_id = VCODEC_DEVICE_ID_VPU;\r
+       } else {\r
+               dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));\r
+               return -1;\r
+       }\r
+\r
+       mutex_init(&g_mode_mutex);\r
+       vcodec_enter_mode(pservice->dev_id);\r
+\r
+       wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");\r
+       INIT_LIST_HEAD(&pservice->waiting);\r
+       INIT_LIST_HEAD(&pservice->running);\r
+       INIT_LIST_HEAD(&pservice->done);\r
+       INIT_LIST_HEAD(&pservice->session);\r
+       mutex_init(&pservice->lock);\r
+       pservice->reg_codec     = NULL;\r
+       pservice->reg_pproc     = NULL;\r
+       atomic_set(&pservice->total_running, 0);\r
+       pservice->enabled = false;\r
 #if defined(CONFIG_VCODEC_MMU)    \r
-    pservice->mmu_dev = NULL;\r
-#endif    \r
-    pservice->dev = dev;\r
-\r
-    if (0 > vpu_get_clk(pservice)) {\r
-        goto err;\r
-    }\r
+       pservice->mmu_dev = NULL;\r
+#endif\r
+       pservice->dev = dev;\r
 \r
-    INIT_DELAYED_WORK(&pservice->power_off_work, vpu_power_off_work);\r
+       if (0 > vpu_get_clk(pservice))\r
+               goto err;\r
 \r
-    vpu_service_power_on(pservice);\r
-    \r
-    mdelay(1);\r
+       INIT_DELAYED_WORK(&pservice->power_off_work, vpu_power_off_work);\r
 \r
-    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       vpu_service_power_on(pservice);\r
 \r
-    regs = devm_ioremap_resource(pservice->dev, res);\r
-    if (IS_ERR(regs)) {\r
-        ret = PTR_ERR(regs);\r
-        goto err;\r
-    }\r
+       mdelay(1);\r
 \r
-    ret = vpu_service_check_hw(pservice, res->start);\r
-    if (ret < 0) {\r
-        pr_err("error: hw info check faild\n");\r
-        goto err;\r
-    }\r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
 \r
-    /// define regs address.\r
-    pservice->dec_dev.iobaseaddr = res->start + pservice->hw_info->dec_offset;\r
-    pservice->dec_dev.iosize     = pservice->hw_info->dec_io_size;\r
+       res->flags &= ~IORESOURCE_CACHEABLE;\r
 \r
-    pservice->dec_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->dec_offset);\r
+       regs = devm_ioremap_resource(pservice->dev, res);\r
+       if (IS_ERR(regs)) {\r
+               ret = PTR_ERR(regs);\r
+               goto err;\r
+       }\r
 \r
-    pservice->reg_size   = pservice->dec_dev.iosize;\r
+       {\r
+               u32 offset = res->start;\r
+               if (soc_is_rk3036()) {\r
+                       if (pservice->dev_id == VCODEC_DEVICE_ID_VPU)\r
+                               offset += 0x400;\r
+               }\r
+               ret = vpu_service_check_hw(pservice, offset);\r
+               if (ret < 0) {\r
+                       pr_err("error: hw info check faild\n");\r
+                       goto err;\r
+               }\r
+       }\r
 \r
-    if (pservice->hw_info->hw_id != HEVC_ID) {\r
-        pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;\r
-        pservice->enc_dev.iosize     = pservice->hw_info->enc_io_size;\r
+       /// define regs address.\r
+       pservice->dec_dev.iobaseaddr = res->start + pservice->hw_info->dec_offset;\r
+       pservice->dec_dev.iosize     = pservice->hw_info->dec_io_size;\r
 \r
-        pservice->reg_size = pservice->reg_size > pservice->enc_dev.iosize ? pservice->reg_size : pservice->enc_dev.iosize;\r
+       pservice->dec_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->dec_offset);\r
 \r
-        pservice->enc_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->enc_offset);\r
+       pservice->reg_size   = pservice->dec_dev.iosize;\r
 \r
-        pservice->irq_enc = platform_get_irq_byname(pdev, "irq_enc");\r
-        if (pservice->irq_enc < 0) {\r
-            dev_err(pservice->dev, "cannot find IRQ encoder\n");\r
-            ret = -ENXIO;\r
-            goto err;\r
-        }\r
+       if (pservice->hw_info->hw_id != HEVC_ID && !soc_is_rk3036()) {\r
+               pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;\r
+               pservice->enc_dev.iosize     = pservice->hw_info->enc_io_size;\r
 \r
-        ret = devm_request_threaded_irq(pservice->dev, pservice->irq_enc, vepu_irq, vepu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
-        if (ret) {\r
-            dev_err(pservice->dev, "error: can't request vepu irq %d\n", pservice->irq_enc);\r
-            goto err;\r
-        }\r
-    }\r
+               pservice->reg_size = pservice->reg_size > pservice->enc_dev.iosize ? pservice->reg_size : pservice->enc_dev.iosize;\r
 \r
-    pservice->irq_dec = platform_get_irq_byname(pdev, "irq_dec");\r
-    if (pservice->irq_dec < 0) {\r
-        dev_err(pservice->dev, "cannot find IRQ decoder\n");\r
-        ret = -ENXIO;\r
-        goto err;\r
-    }\r
+               pservice->enc_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->enc_offset);\r
 \r
-    /* get the IRQ line */\r
-    ret = devm_request_threaded_irq(pservice->dev, pservice->irq_dec, vdpu_irq, vdpu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
-    if (ret) {\r
-        dev_err(pservice->dev, "error: can't request vdpu irq %d\n", pservice->irq_dec);\r
-        goto err;\r
-    }\r
+               pservice->irq_enc = platform_get_irq_byname(pdev, "irq_enc");\r
+               if (pservice->irq_enc < 0) {\r
+                       dev_err(pservice->dev, "cannot find IRQ encoder\n");\r
+                       ret = -ENXIO;\r
+                       goto err;\r
+               }\r
 \r
-    atomic_set(&pservice->dec_dev.irq_count_codec, 0);\r
-    atomic_set(&pservice->dec_dev.irq_count_pp, 0);\r
-    atomic_set(&pservice->enc_dev.irq_count_codec, 0);\r
-    atomic_set(&pservice->enc_dev.irq_count_pp, 0);\r
+               ret = devm_request_threaded_irq(pservice->dev, pservice->irq_enc, vepu_irq, vepu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
+               if (ret) {\r
+                       dev_err(pservice->dev, "error: can't request vepu irq %d\n", pservice->irq_enc);\r
+                       goto err;\r
+               }\r
+       }\r
 \r
-    /// create device\r
-    ret = alloc_chrdev_region(&pservice->dev_t, 0, 1, dev_name(dev));\r
-    if (ret) {\r
-        dev_err(dev, "alloc dev_t failed\n");\r
-        goto err;\r
-    }\r
+       pservice->irq_dec = platform_get_irq_byname(pdev, "irq_dec");\r
+       if (pservice->irq_dec < 0) {\r
+               dev_err(pservice->dev, "cannot find IRQ decoder\n");\r
+               ret = -ENXIO;\r
+               goto err;\r
+       }\r
+\r
+       /* get the IRQ line */\r
+       ret = devm_request_threaded_irq(pservice->dev, pservice->irq_dec, vdpu_irq, vdpu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
+       if (ret) {\r
+               dev_err(pservice->dev, "error: can't request vdpu irq %d\n", pservice->irq_dec);\r
+               goto err;\r
+       }\r
 \r
-    cdev_init(&pservice->cdev, &vpu_service_fops);\r
+       atomic_set(&pservice->dec_dev.irq_count_codec, 0);\r
+       atomic_set(&pservice->dec_dev.irq_count_pp, 0);\r
+       atomic_set(&pservice->enc_dev.irq_count_codec, 0);\r
+       atomic_set(&pservice->enc_dev.irq_count_pp, 0);\r
 \r
-    pservice->cdev.owner = THIS_MODULE;\r
-    pservice->cdev.ops = &vpu_service_fops;\r
+       /// create device\r
+       ret = alloc_chrdev_region(&pservice->dev_t, 0, 1, dev_name(dev));\r
+       if (ret) {\r
+               dev_err(dev, "alloc dev_t failed\n");\r
+               goto err;\r
+       }\r
 \r
-    ret = cdev_add(&pservice->cdev, pservice->dev_t, 1);\r
+       cdev_init(&pservice->cdev, &vpu_service_fops);\r
 \r
-    if (ret) {\r
-        dev_err(dev, "add dev_t failed\n");\r
-        goto err;\r
-    }\r
+       pservice->cdev.owner = THIS_MODULE;\r
+       pservice->cdev.ops = &vpu_service_fops;\r
+\r
+       ret = cdev_add(&pservice->cdev, pservice->dev_t, 1);\r
+\r
+       if (ret) {\r
+               dev_err(dev, "add dev_t failed\n");\r
+               goto err;\r
+       }\r
 \r
-    pservice->cls = class_create(THIS_MODULE, dev_name(dev));\r
+       pservice->cls = class_create(THIS_MODULE, dev_name(dev));\r
 \r
-    if (IS_ERR(pservice->cls)) {\r
-        ret = PTR_ERR(pservice->cls);\r
-        dev_err(dev, "class_create err:%d\n", ret);\r
-        goto err;\r
-    }\r
+       if (IS_ERR(pservice->cls)) {\r
+               ret = PTR_ERR(pservice->cls);\r
+               dev_err(dev, "class_create err:%d\n", ret);\r
+               goto err;\r
+       }\r
 \r
-    pservice->child_dev = device_create(pservice->cls, dev, pservice->dev_t, NULL, dev_name(dev));\r
+       pservice->child_dev = device_create(pservice->cls, dev, pservice->dev_t, NULL, dev_name(dev));\r
 \r
-    platform_set_drvdata(pdev, pservice);\r
+       platform_set_drvdata(pdev, pservice);\r
 \r
-    get_hw_info(pservice);\r
+       get_hw_info(pservice);\r
 \r
 \r
 #ifdef CONFIG_DEBUG_FS\r
-    pservice->debugfs_dir = vcodec_debugfs_create_device_dir((char*)dev_name(dev), parent);\r
-    \r
-    if (pservice->debugfs_dir == NULL) {\r
-        pr_err("create debugfs dir %s failed\n", dev_name(dev));\r
-    }\r
-\r
-    pservice->debugfs_file_regs = debugfs_create_file("regs", 0664,\r
-                    pservice->debugfs_dir, pservice,\r
-                    &debug_vcodec_fops);\r
+       pservice->debugfs_dir = vcodec_debugfs_create_device_dir((char*)dev_name(dev), parent);\r
+       if (pservice->debugfs_dir == NULL)\r
+               pr_err("create debugfs dir %s failed\n", dev_name(dev));\r
+\r
+       pservice->debugfs_file_regs = \r
+               debugfs_create_file("regs", 0664,\r
+                                   pservice->debugfs_dir, pservice,\r
+                                   &debug_vcodec_fops);\r
 #endif\r
 \r
 #if defined(CONFIG_VCODEC_MMU)\r
-    pservice->ion_client = rockchip_ion_client_create("vpu");\r
-    if (IS_ERR(pservice->ion_client)) {\r
-        dev_err(&pdev->dev, "failed to create ion client for vcodec");\r
-        return PTR_ERR(pservice->ion_client);\r
-    } else {\r
-        dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
-    }\r
-    \r
-    if (pservice->hw_info->hw_id == HEVC_ID) {\r
-        sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");\r
-    } else {\r
-        sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");\r
-    }\r
-    \r
-    pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);\r
-    \r
-    if (pservice->mmu_dev) {\r
-        platform_set_sysmmu(pservice->mmu_dev, pservice->dev);\r
-        iovmm_activate(pservice->dev);\r
-    }\r
+       pservice->ion_client = rockchip_ion_client_create("vpu");\r
+       if (IS_ERR(pservice->ion_client)) {\r
+               dev_err(&pdev->dev, "failed to create ion client for vcodec");\r
+               return PTR_ERR(pservice->ion_client);\r
+       } else {\r
+               dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
+       }\r
+\r
+       if (pservice->hw_info->hw_id == HEVC_ID)\r
+               sprintf(mmu_dev_dts_name, "iommu,hevc_mmu");\r
+       else\r
+               sprintf(mmu_dev_dts_name, "iommu,vpu_mmu");\r
+       pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);\r
+\r
+       if (pservice->mmu_dev) {\r
+               platform_set_sysmmu(pservice->mmu_dev, pservice->dev);\r
+               iovmm_activate(pservice->dev);\r
+       }\r
 #endif\r
 \r
-    vpu_service_power_off(pservice);\r
-    pr_info("init success\n");\r
+       vpu_service_power_off(pservice);\r
+       vcodec_exit_mode();\r
+\r
+       pr_info("init success\n");\r
 \r
 #if HEVC_SIM_ENABLE\r
-    if (pservice->hw_info->hw_id == HEVC_ID) {\r
-        simulate_init(pservice);\r
-    }\r
+       if (pservice->hw_info->hw_id == HEVC_ID)\r
+               simulate_init(pservice);\r
 #endif\r
 \r
 #if HEVC_TEST_ENABLE\r
-    hevc_test_case0(pservice);\r
+       hevc_test_case0(pservice);\r
 #endif\r
 \r
-    return 0;\r
+       return 0;\r
 \r
 err:\r
-    pr_info("init failed\n");\r
-    vpu_service_power_off(pservice);\r
-    vpu_put_clk(pservice);\r
-    wake_lock_destroy(&pservice->wake_lock);\r
-\r
-    if (res) {\r
-        devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
-    }\r
-\r
-    if (pservice->irq_enc > 0) {\r
-        free_irq(pservice->irq_enc, (void *)pservice);\r
-    }\r
-\r
-    if (pservice->irq_dec > 0) {\r
-        free_irq(pservice->irq_dec, (void *)pservice);\r
-    }\r
-\r
-    if (pservice->child_dev) {\r
-        device_destroy(pservice->cls, pservice->dev_t);\r
-        cdev_del(&pservice->cdev);\r
-        unregister_chrdev_region(pservice->dev_t, 1);\r
-    }\r
-\r
-    if (pservice->cls) {\r
-        class_destroy(pservice->cls);\r
-    }\r
-\r
-    return ret;\r
+       pr_info("init failed\n");\r
+       vpu_service_power_off(pservice);\r
+       vpu_put_clk(pservice);\r
+       wake_lock_destroy(&pservice->wake_lock);\r
+\r
+       if (res)\r
+               devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
+       if (pservice->irq_enc > 0)\r
+               free_irq(pservice->irq_enc, (void *)pservice);\r
+       if (pservice->irq_dec > 0)\r
+               free_irq(pservice->irq_dec, (void *)pservice);\r
+\r
+       if (pservice->child_dev) {\r
+               device_destroy(pservice->cls, pservice->dev_t);\r
+               cdev_del(&pservice->cdev);\r
+               unregister_chrdev_region(pservice->dev_t, 1);\r
+       }\r
+\r
+       if (pservice->cls)\r
+               class_destroy(pservice->cls);\r
+\r
+       return ret;\r
 }\r
 \r
 static int vcodec_remove(struct platform_device *pdev)\r
 {\r
-    struct vpu_service_info *pservice = platform_get_drvdata(pdev);\r
-    struct resource *res;\r
-\r
-    device_destroy(pservice->cls, pservice->dev_t);\r
-    class_destroy(pservice->cls);\r
-    cdev_del(&pservice->cdev);\r
-    unregister_chrdev_region(pservice->dev_t, 1);\r
-\r
-    free_irq(pservice->irq_enc, (void *)&pservice->enc_dev);\r
-    free_irq(pservice->irq_dec, (void *)&pservice->dec_dev);\r
-    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-    devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
-    vpu_put_clk(pservice);\r
-    wake_lock_destroy(&pservice->wake_lock);\r
-    \r
-#ifdef CONFIG_DEBUG_FS\r
-    if (pservice->debugfs_file_regs) {\r
-        debugfs_remove(pservice->debugfs_file_regs);\r
-    }\r
+       struct vpu_service_info *pservice = platform_get_drvdata(pdev);\r
+       struct resource *res;\r
 \r
-    if (pservice->debugfs_dir) {\r
-        debugfs_remove(pservice->debugfs_dir);\r
-    }\r
+       device_destroy(pservice->cls, pservice->dev_t);\r
+       class_destroy(pservice->cls);\r
+       cdev_del(&pservice->cdev);\r
+       unregister_chrdev_region(pservice->dev_t, 1);\r
+\r
+       free_irq(pservice->irq_enc, (void *)&pservice->enc_dev);\r
+       free_irq(pservice->irq_dec, (void *)&pservice->dec_dev);\r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
+       vpu_put_clk(pservice);\r
+       wake_lock_destroy(&pservice->wake_lock);\r
+\r
+#ifdef CONFIG_DEBUG_FS\r
+       debugfs_remove(pservice->debugfs_file_regs);\r
+       debugfs_remove(pservice->debugfs_dir);\r
 #endif\r
 \r
-    return 0;\r
+       return 0;\r
 }\r
 \r
 #if defined(CONFIG_OF)\r
 static const struct of_device_id vcodec_service_dt_ids[] = {\r
-    {.compatible = "vpu_service",},\r
-    {.compatible = "rockchip,hevc_service",},\r
-    {},\r
+       {.compatible = "vpu_service",},\r
+       {.compatible = "rockchip,hevc_service",},\r
+       {},\r
 };\r
 #endif\r
 \r
 static struct platform_driver vcodec_driver = {\r
-    .probe     = vcodec_probe,\r
-    .remove       = vcodec_remove,\r
-    .driver = {\r
-        .name = "vcodec",\r
-        .owner = THIS_MODULE,\r
+       .probe = vcodec_probe,\r
+       .remove = vcodec_remove,\r
+       .driver = {\r
+               .name = "vcodec",\r
+               .owner = THIS_MODULE,\r
 #if defined(CONFIG_OF)\r
-        .of_match_table = of_match_ptr(vcodec_service_dt_ids),\r
+               .of_match_table = of_match_ptr(vcodec_service_dt_ids),\r
 #endif\r
-    },\r
+       },\r
 };\r
 \r
 static void get_hw_info(struct vpu_service_info *pservice)\r
 {\r
-    VPUHwDecConfig_t *dec = &pservice->dec_config;\r
-    VPUHwEncConfig_t *enc = &pservice->enc_config;\r
-\r
-    if (pservice->dev_id == VCODEC_DEVICE_ID_VPU) {            \r
-        u32 configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG0];\r
-        u32 asicID      = pservice->dec_dev.hwregs[0];\r
-    \r
-        dec->h264Support    = (configReg >> DWL_H264_E) & 0x3U;\r
-        dec->jpegSupport    = (configReg >> DWL_JPEG_E) & 0x01U;\r
-        if (dec->jpegSupport && ((configReg >> DWL_PJPEG_E) & 0x01U))\r
-            dec->jpegSupport = JPEG_PROGRESSIVE;\r
-        dec->mpeg4Support   = (configReg >> DWL_MPEG4_E) & 0x3U;\r
-        dec->vc1Support     = (configReg >> DWL_VC1_E) & 0x3U;\r
-        dec->mpeg2Support   = (configReg >> DWL_MPEG2_E) & 0x01U;\r
-        dec->sorensonSparkSupport = (configReg >> DWL_SORENSONSPARK_E) & 0x01U;\r
-        dec->refBufSupport  = (configReg >> DWL_REF_BUFF_E) & 0x01U;\r
-        dec->vp6Support     = (configReg >> DWL_VP6_E) & 0x01U;\r
-    \r
-        if (!soc_is_rk3190() && !soc_is_rk3288()) {\r
-            dec->maxDecPicWidth = configReg & 0x07FFU;\r
-        } else {\r
-            dec->maxDecPicWidth = 4096;\r
-        }\r
-    \r
-        /* 2nd Config register */\r
-        configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG1];\r
-        if (dec->refBufSupport) {\r
-            if ((configReg >> DWL_REF_BUFF_ILACE_E) & 0x01U)\r
-                dec->refBufSupport |= 2;\r
-            if ((configReg >> DWL_REF_BUFF_DOUBLE_E) & 0x01U)\r
-                dec->refBufSupport |= 4;\r
-        }\r
-        dec->customMpeg4Support = (configReg >> DWL_MPEG4_CUSTOM_E) & 0x01U;\r
-        dec->vp7Support     = (configReg >> DWL_VP7_E) & 0x01U;\r
-        dec->vp8Support     = (configReg >> DWL_VP8_E) & 0x01U;\r
-        dec->avsSupport     = (configReg >> DWL_AVS_E) & 0x01U;\r
-    \r
-        /* JPEG xtensions */\r
-        if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {\r
-            dec->jpegESupport = (configReg >> DWL_JPEG_EXT_E) & 0x01U;\r
-        } else {\r
-            dec->jpegESupport = JPEG_EXT_NOT_SUPPORTED;\r
-        }\r
-    \r
-        if (((asicID >> 16) >= 0x9170U) || ((asicID >> 16) == 0x6731U) ) {\r
-            dec->rvSupport = (configReg >> DWL_RV_E) & 0x03U;\r
-        } else {\r
-            dec->rvSupport = RV_NOT_SUPPORTED;\r
-        }\r
-    \r
-        dec->mvcSupport = (configReg >> DWL_MVC_E) & 0x03U;\r
-    \r
-        if (dec->refBufSupport && (asicID >> 16) == 0x6731U ) {\r
-            dec->refBufSupport |= 8; /* enable HW support for offset */\r
-        }\r
-    \r
-        /// invalidate fuse register value in rk319x vpu and following.\r
-        if (!soc_is_rk3190() && !soc_is_rk3288()) {\r
-            VPUHwFuseStatus_t hwFuseSts;\r
-            /* Decoder fuse configuration */\r
-            u32 fuseReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
-    \r
-            hwFuseSts.h264SupportFuse = (fuseReg >> DWL_H264_FUSE_E) & 0x01U;\r
-            hwFuseSts.mpeg4SupportFuse = (fuseReg >> DWL_MPEG4_FUSE_E) & 0x01U;\r
-            hwFuseSts.mpeg2SupportFuse = (fuseReg >> DWL_MPEG2_FUSE_E) & 0x01U;\r
-            hwFuseSts.sorensonSparkSupportFuse = (fuseReg >> DWL_SORENSONSPARK_FUSE_E) & 0x01U;\r
-            hwFuseSts.jpegSupportFuse = (fuseReg >> DWL_JPEG_FUSE_E) & 0x01U;\r
-            hwFuseSts.vp6SupportFuse = (fuseReg >> DWL_VP6_FUSE_E) & 0x01U;\r
-            hwFuseSts.vc1SupportFuse = (fuseReg >> DWL_VC1_FUSE_E) & 0x01U;\r
-            hwFuseSts.jpegProgSupportFuse = (fuseReg >> DWL_PJPEG_FUSE_E) & 0x01U;\r
-            hwFuseSts.rvSupportFuse = (fuseReg >> DWL_RV_FUSE_E) & 0x01U;\r
-            hwFuseSts.avsSupportFuse = (fuseReg >> DWL_AVS_FUSE_E) & 0x01U;\r
-            hwFuseSts.vp7SupportFuse = (fuseReg >> DWL_VP7_FUSE_E) & 0x01U;\r
-            hwFuseSts.vp8SupportFuse = (fuseReg >> DWL_VP8_FUSE_E) & 0x01U;\r
-            hwFuseSts.customMpeg4SupportFuse = (fuseReg >> DWL_CUSTOM_MPEG4_FUSE_E) & 0x01U;\r
-            hwFuseSts.mvcSupportFuse = (fuseReg >> DWL_MVC_FUSE_E) & 0x01U;\r
-    \r
-            /* check max. decoder output width */\r
-    \r
-            if (fuseReg & 0x8000U)\r
-                hwFuseSts.maxDecPicWidthFuse = 1920;\r
-            else if (fuseReg & 0x4000U)\r
-                hwFuseSts.maxDecPicWidthFuse = 1280;\r
-            else if (fuseReg & 0x2000U)\r
-                hwFuseSts.maxDecPicWidthFuse = 720;\r
-            else if (fuseReg & 0x1000U)\r
-                hwFuseSts.maxDecPicWidthFuse = 352;\r
-            else    /* remove warning */\r
-                hwFuseSts.maxDecPicWidthFuse = 352;\r
-    \r
-            hwFuseSts.refBufSupportFuse = (fuseReg >> DWL_REF_BUFF_FUSE_E) & 0x01U;\r
-    \r
-            /* Pp configuration */\r
-            configReg = pservice->dec_dev.hwregs[VPU_PP_HW_SYNTH_CFG];\r
-    \r
-            if ((configReg >> DWL_PP_E) & 0x01U) {\r
-                dec->ppSupport = 1;\r
-                dec->maxPpOutPicWidth = configReg & 0x07FFU;\r
-                /*pHwCfg->ppConfig = (configReg >> DWL_CFG_E) & 0x0FU; */\r
-                dec->ppConfig = configReg;\r
-            } else {\r
-                dec->ppSupport = 0;\r
-                dec->maxPpOutPicWidth = 0;\r
-                dec->ppConfig = 0;\r
-            }\r
-    \r
-            /* check the HW versio */\r
-            if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U))    {\r
-                /* Pp configuration */\r
-                configReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
-    \r
-                if ((configReg >> DWL_PP_E) & 0x01U) {\r
-                    /* Pp fuse configuration */\r
-                    u32 fuseRegPp = pservice->dec_dev.hwregs[VPU_PP_HW_FUSE_CFG];\r
-    \r
-                    if ((fuseRegPp >> DWL_PP_FUSE_E) & 0x01U) {\r
-                        hwFuseSts.ppSupportFuse = 1;\r
-                        /* check max. pp output width */\r
-                        if      (fuseRegPp & 0x8000U) hwFuseSts.maxPpOutPicWidthFuse = 1920;\r
-                        else if (fuseRegPp & 0x4000U) hwFuseSts.maxPpOutPicWidthFuse = 1280;\r
-                        else if (fuseRegPp & 0x2000U) hwFuseSts.maxPpOutPicWidthFuse = 720;\r
-                        else if (fuseRegPp & 0x1000U) hwFuseSts.maxPpOutPicWidthFuse = 352;\r
-                        else                          hwFuseSts.maxPpOutPicWidthFuse = 352;\r
-                        hwFuseSts.ppConfigFuse = fuseRegPp;\r
-                    } else {\r
-                        hwFuseSts.ppSupportFuse = 0;\r
-                        hwFuseSts.maxPpOutPicWidthFuse = 0;\r
-                        hwFuseSts.ppConfigFuse = 0;\r
-                    }\r
-                } else {\r
-                    hwFuseSts.ppSupportFuse = 0;\r
-                    hwFuseSts.maxPpOutPicWidthFuse = 0;\r
-                    hwFuseSts.ppConfigFuse = 0;\r
-                }\r
-    \r
-                if (dec->maxDecPicWidth > hwFuseSts.maxDecPicWidthFuse)\r
-                    dec->maxDecPicWidth = hwFuseSts.maxDecPicWidthFuse;\r
-                if (dec->maxPpOutPicWidth > hwFuseSts.maxPpOutPicWidthFuse)\r
-                    dec->maxPpOutPicWidth = hwFuseSts.maxPpOutPicWidthFuse;\r
-                if (!hwFuseSts.h264SupportFuse) dec->h264Support = H264_NOT_SUPPORTED;\r
-                if (!hwFuseSts.mpeg4SupportFuse) dec->mpeg4Support = MPEG4_NOT_SUPPORTED;\r
-                if (!hwFuseSts.customMpeg4SupportFuse) dec->customMpeg4Support = MPEG4_CUSTOM_NOT_SUPPORTED;\r
-                if (!hwFuseSts.jpegSupportFuse) dec->jpegSupport = JPEG_NOT_SUPPORTED;\r
-                if ((dec->jpegSupport == JPEG_PROGRESSIVE) && !hwFuseSts.jpegProgSupportFuse)\r
-                    dec->jpegSupport = JPEG_BASELINE;\r
-                if (!hwFuseSts.mpeg2SupportFuse) dec->mpeg2Support = MPEG2_NOT_SUPPORTED;\r
-                if (!hwFuseSts.vc1SupportFuse) dec->vc1Support = VC1_NOT_SUPPORTED;\r
-                if (!hwFuseSts.vp6SupportFuse) dec->vp6Support = VP6_NOT_SUPPORTED;\r
-                if (!hwFuseSts.vp7SupportFuse) dec->vp7Support = VP7_NOT_SUPPORTED;\r
-                if (!hwFuseSts.vp8SupportFuse) dec->vp8Support = VP8_NOT_SUPPORTED;\r
-                if (!hwFuseSts.ppSupportFuse) dec->ppSupport = PP_NOT_SUPPORTED;\r
-    \r
-                /* check the pp config vs fuse status */\r
-                if ((dec->ppConfig & 0xFC000000) && ((hwFuseSts.ppConfigFuse & 0xF0000000) >> 5)) {\r
-                    u32 deInterlace = ((dec->ppConfig & PP_DEINTERLACING) >> 25);\r
-                    u32 alphaBlend  = ((dec->ppConfig & PP_ALPHA_BLENDING) >> 24);\r
-                    u32 deInterlaceFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_DEINTERLACING) >> 25);\r
-                    u32 alphaBlendFuse  = (((hwFuseSts.ppConfigFuse >> 5) & PP_ALPHA_BLENDING) >> 24);\r
-    \r
-                    if (deInterlace && !deInterlaceFuse) dec->ppConfig &= 0xFD000000;\r
-                    if (alphaBlend && !alphaBlendFuse) dec->ppConfig &= 0xFE000000;\r
-                }\r
-                if (!hwFuseSts.sorensonSparkSupportFuse) dec->sorensonSparkSupport = SORENSON_SPARK_NOT_SUPPORTED;\r
-                if (!hwFuseSts.refBufSupportFuse)   dec->refBufSupport = REF_BUF_NOT_SUPPORTED;\r
-                if (!hwFuseSts.rvSupportFuse)       dec->rvSupport = RV_NOT_SUPPORTED;\r
-                if (!hwFuseSts.avsSupportFuse)      dec->avsSupport = AVS_NOT_SUPPORTED;\r
-                if (!hwFuseSts.mvcSupportFuse)      dec->mvcSupport = MVC_NOT_SUPPORTED;\r
-            }\r
-        }\r
-    \r
-        configReg = pservice->enc_dev.hwregs[63];\r
-        enc->maxEncodedWidth = configReg & ((1 << 11) - 1);\r
-        enc->h264Enabled = (configReg >> 27) & 1;\r
-        enc->mpeg4Enabled = (configReg >> 26) & 1;\r
-        enc->jpegEnabled = (configReg >> 25) & 1;\r
-        enc->vsEnabled = (configReg >> 24) & 1;\r
-        enc->rgbEnabled = (configReg >> 28) & 1;\r
-        //enc->busType = (configReg >> 20) & 15;\r
-        //enc->synthesisLanguage = (configReg >> 16) & 15;\r
-        //enc->busWidth = (configReg >> 12) & 15;\r
-        enc->reg_size = pservice->reg_size;\r
-        enc->reserv[0] = enc->reserv[1] = 0;\r
-    \r
-        pservice->auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926() || soc_is_rk3288();\r
-        if (pservice->auto_freq) {\r
-            pr_info("vpu_service set to auto frequency mode\n");\r
-            atomic_set(&pservice->freq_status, VPU_FREQ_BUT);\r
-        }\r
-        pservice->bug_dec_addr = cpu_is_rk30xx();\r
-        //printk("cpu 3066b bug %d\n", service.bug_dec_addr);\r
-    } else {\r
-        // disable frequency switch in hevc.\r
-        pservice->auto_freq = false;\r
-    }\r
+       VPUHwDecConfig_t *dec = &pservice->dec_config;\r
+       VPUHwEncConfig_t *enc = &pservice->enc_config;\r
+\r
+       if (pservice->dev_id == VCODEC_DEVICE_ID_VPU) {\r
+               u32 configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG0];\r
+               u32 asicID      = pservice->dec_dev.hwregs[0];\r
+       \r
+               dec->h264Support    = (configReg >> DWL_H264_E) & 0x3U;\r
+               dec->jpegSupport    = (configReg >> DWL_JPEG_E) & 0x01U;\r
+               if (dec->jpegSupport && ((configReg >> DWL_PJPEG_E) & 0x01U))\r
+                       dec->jpegSupport = JPEG_PROGRESSIVE;\r
+               dec->mpeg4Support   = (configReg >> DWL_MPEG4_E) & 0x3U;\r
+               dec->vc1Support     = (configReg >> DWL_VC1_E) & 0x3U;\r
+               dec->mpeg2Support   = (configReg >> DWL_MPEG2_E) & 0x01U;\r
+               dec->sorensonSparkSupport = (configReg >> DWL_SORENSONSPARK_E) & 0x01U;\r
+               dec->refBufSupport  = (configReg >> DWL_REF_BUFF_E) & 0x01U;\r
+               dec->vp6Support     = (configReg >> DWL_VP6_E) & 0x01U;\r
+\r
+               if (soc_is_rk3190() || soc_is_rk3288())\r
+                       dec->maxDecPicWidth = 4096;\r
+               else if (soc_is_rk3036())\r
+                       dec->maxDecPicWidth = 1920;\r
+               else\r
+                       dec->maxDecPicWidth = configReg & 0x07FFU;\r
+       \r
+               /* 2nd Config register */\r
+               configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG1];\r
+               if (dec->refBufSupport) {\r
+                       if ((configReg >> DWL_REF_BUFF_ILACE_E) & 0x01U)\r
+                               dec->refBufSupport |= 2;\r
+                       if ((configReg >> DWL_REF_BUFF_DOUBLE_E) & 0x01U)\r
+                               dec->refBufSupport |= 4;\r
+               }\r
+               dec->customMpeg4Support = (configReg >> DWL_MPEG4_CUSTOM_E) & 0x01U;\r
+               dec->vp7Support     = (configReg >> DWL_VP7_E) & 0x01U;\r
+               dec->vp8Support     = (configReg >> DWL_VP8_E) & 0x01U;\r
+               dec->avsSupport     = (configReg >> DWL_AVS_E) & 0x01U;\r
+\r
+               /* JPEG xtensions */\r
+               if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U))\r
+                       dec->jpegESupport = (configReg >> DWL_JPEG_EXT_E) & 0x01U;\r
+               else\r
+                       dec->jpegESupport = JPEG_EXT_NOT_SUPPORTED;\r
+\r
+               if (((asicID >> 16) >= 0x9170U) || ((asicID >> 16) == 0x6731U) )\r
+                       dec->rvSupport = (configReg >> DWL_RV_E) & 0x03U;\r
+               else\r
+                       dec->rvSupport = RV_NOT_SUPPORTED;\r
+               dec->mvcSupport = (configReg >> DWL_MVC_E) & 0x03U;\r
+\r
+               if (dec->refBufSupport && (asicID >> 16) == 0x6731U )\r
+                       dec->refBufSupport |= 8; /* enable HW support for offset */\r
+       \r
+               /// invalidate fuse register value in rk319x vpu and following.\r
+               if (!soc_is_rk3190() && !soc_is_rk3288() && !soc_is_rk3036()) {\r
+                       VPUHwFuseStatus_t hwFuseSts;\r
+                       /* Decoder fuse configuration */\r
+                       u32 fuseReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
+\r
+                       hwFuseSts.h264SupportFuse = (fuseReg >> DWL_H264_FUSE_E) & 0x01U;\r
+                       hwFuseSts.mpeg4SupportFuse = (fuseReg >> DWL_MPEG4_FUSE_E) & 0x01U;\r
+                       hwFuseSts.mpeg2SupportFuse = (fuseReg >> DWL_MPEG2_FUSE_E) & 0x01U;\r
+                       hwFuseSts.sorensonSparkSupportFuse = (fuseReg >> DWL_SORENSONSPARK_FUSE_E) & 0x01U;\r
+                       hwFuseSts.jpegSupportFuse = (fuseReg >> DWL_JPEG_FUSE_E) & 0x01U;\r
+                       hwFuseSts.vp6SupportFuse = (fuseReg >> DWL_VP6_FUSE_E) & 0x01U;\r
+                       hwFuseSts.vc1SupportFuse = (fuseReg >> DWL_VC1_FUSE_E) & 0x01U;\r
+                       hwFuseSts.jpegProgSupportFuse = (fuseReg >> DWL_PJPEG_FUSE_E) & 0x01U;\r
+                       hwFuseSts.rvSupportFuse = (fuseReg >> DWL_RV_FUSE_E) & 0x01U;\r
+                       hwFuseSts.avsSupportFuse = (fuseReg >> DWL_AVS_FUSE_E) & 0x01U;\r
+                       hwFuseSts.vp7SupportFuse = (fuseReg >> DWL_VP7_FUSE_E) & 0x01U;\r
+                       hwFuseSts.vp8SupportFuse = (fuseReg >> DWL_VP8_FUSE_E) & 0x01U;\r
+                       hwFuseSts.customMpeg4SupportFuse = (fuseReg >> DWL_CUSTOM_MPEG4_FUSE_E) & 0x01U;\r
+                       hwFuseSts.mvcSupportFuse = (fuseReg >> DWL_MVC_FUSE_E) & 0x01U;\r
+\r
+                       /* check max. decoder output width */\r
+\r
+                       if (fuseReg & 0x8000U)\r
+                               hwFuseSts.maxDecPicWidthFuse = 1920;\r
+                       else if (fuseReg & 0x4000U)\r
+                               hwFuseSts.maxDecPicWidthFuse = 1280;\r
+                       else if (fuseReg & 0x2000U)\r
+                               hwFuseSts.maxDecPicWidthFuse = 720;\r
+                       else if (fuseReg & 0x1000U)\r
+                               hwFuseSts.maxDecPicWidthFuse = 352;\r
+                       else    /* remove warning */\r
+                               hwFuseSts.maxDecPicWidthFuse = 352;\r
+\r
+                       hwFuseSts.refBufSupportFuse = (fuseReg >> DWL_REF_BUFF_FUSE_E) & 0x01U;\r
+\r
+                       /* Pp configuration */\r
+                       configReg = pservice->dec_dev.hwregs[VPU_PP_HW_SYNTH_CFG];\r
+\r
+                       if ((configReg >> DWL_PP_E) & 0x01U) {\r
+                               dec->ppSupport = 1;\r
+                               dec->maxPpOutPicWidth = configReg & 0x07FFU;\r
+                               /*pHwCfg->ppConfig = (configReg >> DWL_CFG_E) & 0x0FU; */\r
+                               dec->ppConfig = configReg;\r
+                       } else {\r
+                               dec->ppSupport = 0;\r
+                               dec->maxPpOutPicWidth = 0;\r
+                               dec->ppConfig = 0;\r
+                       }\r
+\r
+                       /* check the HW versio */\r
+                       if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {\r
+                               /* Pp configuration */\r
+                               configReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
+                               if ((configReg >> DWL_PP_E) & 0x01U) {\r
+                                       /* Pp fuse configuration */\r
+                                       u32 fuseRegPp = pservice->dec_dev.hwregs[VPU_PP_HW_FUSE_CFG];\r
+\r
+                                       if ((fuseRegPp >> DWL_PP_FUSE_E) & 0x01U) {\r
+                                               hwFuseSts.ppSupportFuse = 1;\r
+                                               /* check max. pp output width */\r
+                                               if (fuseRegPp & 0x8000U)\r
+                                                       hwFuseSts.maxPpOutPicWidthFuse = 1920;\r
+                                               else if (fuseRegPp & 0x4000U)\r
+                                                       hwFuseSts.maxPpOutPicWidthFuse = 1280;\r
+                                               else if (fuseRegPp & 0x2000U)\r
+                                                       hwFuseSts.maxPpOutPicWidthFuse = 720;\r
+                                               else if (fuseRegPp & 0x1000U)\r
+                                                       hwFuseSts.maxPpOutPicWidthFuse = 352;\r
+                                               else\r
+                                                       hwFuseSts.maxPpOutPicWidthFuse = 352;\r
+                                               hwFuseSts.ppConfigFuse = fuseRegPp;\r
+                                       } else {\r
+                                               hwFuseSts.ppSupportFuse = 0;\r
+                                               hwFuseSts.maxPpOutPicWidthFuse = 0;\r
+                                               hwFuseSts.ppConfigFuse = 0;\r
+                                       }\r
+                               } else {\r
+                                       hwFuseSts.ppSupportFuse = 0;\r
+                                       hwFuseSts.maxPpOutPicWidthFuse = 0;\r
+                                       hwFuseSts.ppConfigFuse = 0;\r
+                               }\r
+\r
+                               if (dec->maxDecPicWidth > hwFuseSts.maxDecPicWidthFuse)\r
+                                       dec->maxDecPicWidth = hwFuseSts.maxDecPicWidthFuse;\r
+                               if (dec->maxPpOutPicWidth > hwFuseSts.maxPpOutPicWidthFuse)\r
+                                       dec->maxPpOutPicWidth = hwFuseSts.maxPpOutPicWidthFuse;\r
+                               if (!hwFuseSts.h264SupportFuse) dec->h264Support = H264_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.mpeg4SupportFuse) dec->mpeg4Support = MPEG4_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.customMpeg4SupportFuse) dec->customMpeg4Support = MPEG4_CUSTOM_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.jpegSupportFuse) dec->jpegSupport = JPEG_NOT_SUPPORTED;\r
+                               if ((dec->jpegSupport == JPEG_PROGRESSIVE) && !hwFuseSts.jpegProgSupportFuse)\r
+                                       dec->jpegSupport = JPEG_BASELINE;\r
+                               if (!hwFuseSts.mpeg2SupportFuse) dec->mpeg2Support = MPEG2_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.vc1SupportFuse) dec->vc1Support = VC1_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.vp6SupportFuse) dec->vp6Support = VP6_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.vp7SupportFuse) dec->vp7Support = VP7_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.vp8SupportFuse) dec->vp8Support = VP8_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.ppSupportFuse) dec->ppSupport = PP_NOT_SUPPORTED;\r
+\r
+                               /* check the pp config vs fuse status */\r
+                               if ((dec->ppConfig & 0xFC000000) && ((hwFuseSts.ppConfigFuse & 0xF0000000) >> 5)) {\r
+                                       u32 deInterlace = ((dec->ppConfig & PP_DEINTERLACING) >> 25);\r
+                                       u32 alphaBlend  = ((dec->ppConfig & PP_ALPHA_BLENDING) >> 24);\r
+                                       u32 deInterlaceFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_DEINTERLACING) >> 25);\r
+                                       u32 alphaBlendFuse  = (((hwFuseSts.ppConfigFuse >> 5) & PP_ALPHA_BLENDING) >> 24);\r
+\r
+                                       if (deInterlace && !deInterlaceFuse) dec->ppConfig &= 0xFD000000;\r
+                                       if (alphaBlend && !alphaBlendFuse) dec->ppConfig &= 0xFE000000;\r
+                               }\r
+                               if (!hwFuseSts.sorensonSparkSupportFuse) dec->sorensonSparkSupport = SORENSON_SPARK_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.refBufSupportFuse)   dec->refBufSupport = REF_BUF_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.rvSupportFuse)       dec->rvSupport = RV_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.avsSupportFuse)      dec->avsSupport = AVS_NOT_SUPPORTED;\r
+                               if (!hwFuseSts.mvcSupportFuse)      dec->mvcSupport = MVC_NOT_SUPPORTED;\r
+                       }\r
+               }\r
+\r
+               if (!soc_is_rk3036()) {\r
+                       configReg = pservice->enc_dev.hwregs[63];\r
+                       enc->maxEncodedWidth = configReg & ((1 << 11) - 1);\r
+                       enc->h264Enabled = (configReg >> 27) & 1;\r
+                       enc->mpeg4Enabled = (configReg >> 26) & 1;\r
+                       enc->jpegEnabled = (configReg >> 25) & 1;\r
+                       enc->vsEnabled = (configReg >> 24) & 1;\r
+                       enc->rgbEnabled = (configReg >> 28) & 1;\r
+                       /*enc->busType = (configReg >> 20) & 15;\r
+                       enc->synthesisLanguage = (configReg >> 16) & 15;\r
+                       enc->busWidth = (configReg >> 12) & 15;*/\r
+                       enc->reg_size = pservice->reg_size;\r
+                       enc->reserv[0] = enc->reserv[1] = 0;\r
+               }\r
+\r
+               pservice->auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926() || soc_is_rk3288();\r
+               if (pservice->auto_freq) {\r
+                       pr_info("vpu_service set to auto frequency mode\n");\r
+                       atomic_set(&pservice->freq_status, VPU_FREQ_BUT);\r
+               }\r
+\r
+               pservice->bug_dec_addr = cpu_is_rk30xx();\r
+       } else {\r
+               if (soc_is_rk3036())\r
+                       dec->maxDecPicWidth = 1920;\r
+               else\r
+                       dec->maxDecPicWidth = 4096;\r
+               /* disable frequency switch in hevc.*/\r
+               pservice->auto_freq = false;\r
+       }\r
 }\r
 \r
 static irqreturn_t vdpu_irq(int irq, void *dev_id)\r
 {\r
-    struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
-    vpu_device *dev = &pservice->dec_dev;\r
-    u32 raw_status;\r
-    u32 irq_status = raw_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
+       struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
+       vpu_device *dev = &pservice->dec_dev;\r
+       u32 raw_status;\r
+       u32 irq_status;\r
+\r
+       vcodec_enter_mode_nolock(pservice->dev_id, &pservice->reserved_mode);\r
+\r
+       irq_status = raw_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
 \r
        pr_debug("dec_irq\n");\r
 \r
@@ -1940,37 +2036,34 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id)
                }\r
 \r
                /* clear dec IRQ */\r
-        if (pservice->hw_info->hw_id != HEVC_ID) {\r
-            writel(irq_status & (~DEC_INTERRUPT_BIT|DEC_BUFFER_EMPTY_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER);\r
-        } else {\r
-            /*writel(irq_status \r
-              & (~(DEC_INTERRUPT_BIT|HEVC_DEC_INT_RAW_BIT|HEVC_DEC_STR_ERROR_BIT|HEVC_DEC_BUS_ERROR_BIT|HEVC_DEC_BUFFER_EMPTY_BIT)), \r
-                   dev->hwregs + DEC_INTERRUPT_REGISTER);*/\r
-\r
-            writel(0, dev->hwregs + DEC_INTERRUPT_REGISTER);\r
-        }\r
+               if (pservice->hw_info->hw_id != HEVC_ID)\r
+                       writel(irq_status & (~DEC_INTERRUPT_BIT|DEC_BUFFER_EMPTY_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER);\r
+               else\r
+                       writel(0, dev->hwregs + DEC_INTERRUPT_REGISTER);\r
                atomic_add(1, &dev->irq_count_codec);\r
        }\r
 \r
-    if (pservice->hw_info->hw_id != HEVC_ID) {\r
-        irq_status  = readl(dev->hwregs + PP_INTERRUPT_REGISTER);\r
-        if (irq_status & PP_INTERRUPT_BIT) {\r
-            pr_debug("vdpu_isr pp  %x\n", irq_status);\r
-            /* clear pp IRQ */\r
-            writel(irq_status & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER);\r
-            atomic_add(1, &dev->irq_count_pp);\r
-        }\r
-    }\r
+       if (pservice->hw_info->hw_id != HEVC_ID) {\r
+               irq_status = readl(dev->hwregs + PP_INTERRUPT_REGISTER);\r
+               if (irq_status & PP_INTERRUPT_BIT) {\r
+                       pr_debug("vdpu_isr pp  %x\n", irq_status);\r
+                       /* clear pp IRQ */\r
+                       writel(irq_status & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER);\r
+                       atomic_add(1, &dev->irq_count_pp);\r
+               }\r
+       }\r
+\r
+       pservice->irq_status = raw_status;\r
 \r
-    pservice->irq_status = raw_status;\r
+       vcodec_exit_mode_nolock(pservice->dev_id, pservice->reserved_mode);\r
 \r
        return IRQ_WAKE_THREAD;\r
 }\r
 \r
 static irqreturn_t vdpu_isr(int irq, void *dev_id)\r
 {\r
-    struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
-    vpu_device *dev = &pservice->dec_dev;\r
+       struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
+       vpu_device *dev = &pservice->dec_dev;\r
 \r
        mutex_lock(&pservice->lock);\r
        if (atomic_read(&dev->irq_count_codec)) {\r
@@ -2011,10 +2104,12 @@ static irqreturn_t vdpu_isr(int irq, void *dev_id)
 \r
 static irqreturn_t vepu_irq(int irq, void *dev_id)\r
 {\r
-       //struct vpu_device *dev = (struct vpu_device *) dev_id;\r
-    struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
-    vpu_device *dev = &pservice->enc_dev;\r
-       u32 irq_status = readl(dev->hwregs + ENC_INTERRUPT_REGISTER);\r
+       struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
+       vpu_device *dev = &pservice->enc_dev;\r
+       u32 irq_status;\r
+\r
+       vcodec_enter_mode_nolock(pservice->dev_id,  &pservice->reserved_mode);\r
+       irq_status= readl(dev->hwregs + ENC_INTERRUPT_REGISTER);\r
 \r
        pr_debug("vepu_irq irq status %x\n", irq_status);\r
 \r
@@ -2024,23 +2119,23 @@ static irqreturn_t vepu_irq(int irq, void *dev_id)
                (enc_end.tv_sec  - enc_start.tv_sec)  * 1000 +\r
                (enc_end.tv_usec - enc_start.tv_usec) / 1000);\r
 #endif\r
-    \r
        if (likely(irq_status & ENC_INTERRUPT_BIT)) {\r
                /* clear enc IRQ */\r
                writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER);\r
                atomic_add(1, &dev->irq_count_codec);\r
        }\r
-    \r
-    pservice->irq_status = irq_status;\r
+\r
+       pservice->irq_status = irq_status;\r
+\r
+       vcodec_exit_mode_nolock(pservice->dev_id, pservice->reserved_mode);\r
 \r
        return IRQ_WAKE_THREAD;\r
 }\r
 \r
 static irqreturn_t vepu_isr(int irq, void *dev_id)\r
 {\r
-       //struct vpu_device *dev = (struct vpu_device *) dev_id;\r
-    struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
-    vpu_device *dev = &pservice->enc_dev;\r
+       struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
+       vpu_device *dev = &pservice->enc_dev;\r
 \r
        mutex_lock(&pservice->lock);\r
        if (atomic_read(&dev->irq_count_codec)) {\r
@@ -2058,24 +2153,24 @@ static irqreturn_t vepu_isr(int irq, void *dev_id)
 \r
 static int __init vcodec_service_init(void)\r
 {\r
-    int ret;\r
+       int ret;\r
 \r
-    if ((ret = platform_driver_register(&vcodec_driver)) != 0) {\r
-        pr_err("Platform device register failed (%d).\n", ret);\r
-        return ret;\r
-    }\r
+       if ((ret = platform_driver_register(&vcodec_driver)) != 0) {\r
+               pr_err("Platform device register failed (%d).\n", ret);\r
+               return ret;\r
+       }\r
 \r
 #ifdef CONFIG_DEBUG_FS\r
-    vcodec_debugfs_init();\r
+       vcodec_debugfs_init();\r
 #endif\r
 \r
-    return ret;\r
+       return ret;\r
 }\r
 \r
 static void __exit vcodec_service_exit(void)\r
 {\r
 #ifdef CONFIG_DEBUG_FS\r
-    vcodec_debugfs_exit();\r
+       vcodec_debugfs_exit();\r
 #endif\r
 \r
        platform_driver_unregister(&vcodec_driver);\r
@@ -2089,49 +2184,48 @@ module_exit(vcodec_service_exit);
 \r
 static int vcodec_debugfs_init()\r
 {\r
-    parent = debugfs_create_dir("vcodec", NULL);\r
-    if (!parent)\r
-        return -1;\r
+       parent = debugfs_create_dir("vcodec", NULL);\r
+       if (!parent)\r
+               return -1;\r
 \r
-    return 0;\r
+       return 0;\r
 }\r
 \r
 static void vcodec_debugfs_exit()\r
 {\r
-    debugfs_remove(parent);\r
+       debugfs_remove(parent);\r
 }\r
 \r
 static struct dentry* vcodec_debugfs_create_device_dir(char *dirname, struct dentry *parent)\r
 {\r
-    return debugfs_create_dir(dirname, parent);\r
+       return debugfs_create_dir(dirname, parent);\r
 }\r
 \r
 static int debug_vcodec_show(struct seq_file *s, void *unused)\r
 {\r
        struct vpu_service_info *pservice = s->private;\r
-    unsigned int i, n;\r
+       unsigned int i, n;\r
        vpu_reg *reg, *reg_tmp;\r
        vpu_session *session, *session_tmp;\r
 \r
        mutex_lock(&pservice->lock);\r
        vpu_service_power_on(pservice);\r
-    if (pservice->hw_info->hw_id != HEVC_ID) {\r
-        seq_printf(s, "\nENC Registers:\n");\r
-        n = pservice->enc_dev.iosize >> 2;\r
-        for (i = 0; i < n; i++) {\r
-            seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->enc_dev.hwregs + i));\r
-        }\r
-    }\r
+       if (pservice->hw_info->hw_id != HEVC_ID) {\r
+               seq_printf(s, "\nENC Registers:\n");\r
+               n = pservice->enc_dev.iosize >> 2;\r
+               for (i = 0; i < n; i++) {\r
+                       seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->enc_dev.hwregs + i));\r
+               }\r
+       }\r
        seq_printf(s, "\nDEC Registers:\n");\r
        n = pservice->dec_dev.iosize >> 2;\r
-       for (i = 0; i < n; i++) {\r
+       for (i = 0; i < n; i++)\r
                seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
-       }\r
 \r
        seq_printf(s, "\nvpu service status:\n");\r
        list_for_each_entry_safe(session, session_tmp, &pservice->session, list_session) {\r
                seq_printf(s, "session pid %d type %d:\n", session->pid, session->type);\r
-               //seq_printf(s, "waiting reg set %d\n");\r
+               /*seq_printf(s, "waiting reg set %d\n");*/\r
                list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {\r
                        seq_printf(s, "waiting register set\n");\r
                }\r
@@ -2144,7 +2238,7 @@ static int debug_vcodec_show(struct seq_file *s, void *unused)
        }\r
        mutex_unlock(&pservice->lock);\r
 \r
-    return 0;\r
+       return 0;\r
 }\r
 \r
 static int debug_vcodec_open(struct inode *inode, struct file *file)\r
@@ -2175,18 +2269,17 @@ static struct ion_client *ion_client = NULL;
 u8* get_align_ptr(u8* tbl, int len, u32 *phy)\r
 {\r
        int size = (len+15) & (~15);\r
-    struct ion_handle *handle;\r
+       struct ion_handle *handle;\r
        u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
 \r
-    if (ion_client == NULL) {\r
-        ion_client = rockchip_ion_client_create("vcodec");\r
-    }\r
+       if (ion_client == NULL)\r
+               ion_client = rockchip_ion_client_create("vcodec");\r
 \r
-    handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
+       handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
 \r
-    ptr = ion_map_kernel(ion_client, handle);\r
+       ptr = ion_map_kernel(ion_client, handle);\r
 \r
-    ion_phys(ion_client, handle, phy, &size);\r
+       ion_phys(ion_client, handle, phy, &size);\r
 \r
        memcpy(ptr, tbl, len);\r
 \r
@@ -2196,18 +2289,17 @@ u8* get_align_ptr(u8* tbl, int len, u32 *phy)
 u8* get_align_ptr_no_copy(int len, u32 *phy)\r
 {\r
        int size = (len+15) & (~15);\r
-    struct ion_handle *handle;\r
-       u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
+       struct ion_handle *handle;\r
+       u8 *ptr;\r
 \r
-    if (ion_client == NULL) {\r
-        ion_client = rockchip_ion_client_create("vcodec");\r
-    }\r
+       if (ion_client == NULL)\r
+               ion_client = rockchip_ion_client_create("vcodec");\r
 \r
-    handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
+       handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
 \r
-    ptr = ion_map_kernel(ion_client, handle);\r
+       ptr = ion_map_kernel(ion_client, handle);\r
 \r
-    ion_phys(ion_client, handle, phy, &size);\r
+       ion_phys(ion_client, handle, phy, &size);\r
 \r
        return ptr;\r
 }\r
@@ -2215,17 +2307,17 @@ u8* get_align_ptr_no_copy(int len, u32 *phy)
 #define TEST_CNT    2\r
 static int hevc_test_case0(vpu_service_info *pservice)\r
 {\r
-    vpu_session session;\r
-    vpu_reg *reg; \r
-    unsigned long size = 272;//sizeof(register_00); // registers array length\r
-    int testidx = 0;\r
-    int ret = 0;\r
-\r
-    u8 *pps_tbl[TEST_CNT];\r
-    u8 *register_tbl[TEST_CNT];\r
-    u8 *rps_tbl[TEST_CNT];\r
-    u8 *scaling_list_tbl[TEST_CNT];\r
-    u8 *stream_tbl[TEST_CNT];\r
+       vpu_session session;\r
+       vpu_reg *reg; \r
+       unsigned long size = 272;//sizeof(register_00); // registers array length\r
+       int testidx = 0;\r
+       int ret = 0;\r
+\r
+       u8 *pps_tbl[TEST_CNT];\r
+       u8 *register_tbl[TEST_CNT];\r
+       u8 *rps_tbl[TEST_CNT];\r
+       u8 *scaling_list_tbl[TEST_CNT];\r
+       u8 *stream_tbl[TEST_CNT];\r
 \r
        int stream_size[2];\r
        int pps_size[2];\r
@@ -2233,13 +2325,13 @@ static int hevc_test_case0(vpu_service_info *pservice)
        int scl_size[2];\r
        int cabac_size[2];\r
        \r
-    u32 phy_pps;\r
-    u32 phy_rps;\r
-    u32 phy_scl;\r
-    u32 phy_str;\r
-    u32 phy_yuv;\r
-    u32 phy_ref;\r
-    u32 phy_cabac;\r
+       u32 phy_pps;\r
+       u32 phy_rps;\r
+       u32 phy_scl;\r
+       u32 phy_str;\r
+       u32 phy_yuv;\r
+       u32 phy_ref;\r
+       u32 phy_cabac;\r
 \r
        volatile u8 *stream_buf;\r
        volatile u8 *pps_buf;\r
@@ -2249,27 +2341,27 @@ static int hevc_test_case0(vpu_service_info *pservice)
        volatile u8 *cabac_buf;\r
        volatile u8 *ref_buf;\r
 \r
-    u8 *pps;\r
-    u8 *yuv[2];\r
-    int i;\r
-    \r
-    pps_tbl[0] = pps_00;\r
-    pps_tbl[1] = pps_01;\r
+       u8 *pps;\r
+       u8 *yuv[2];\r
+       int i;\r
+\r
+       pps_tbl[0] = pps_00;\r
+       pps_tbl[1] = pps_01;\r
 \r
-    register_tbl[0] = register_00;\r
-    register_tbl[1] = register_01;\r
-    \r
-    rps_tbl[0] = rps_00;\r
-    rps_tbl[1] = rps_01;\r
-    \r
-    scaling_list_tbl[0] = scaling_list_00;\r
-    scaling_list_tbl[1] = scaling_list_01;\r
+       register_tbl[0] = register_00;\r
+       register_tbl[1] = register_01;\r
 \r
-    stream_tbl[0] = stream_00;\r
-    stream_tbl[1] = stream_01;\r
+       rps_tbl[0] = rps_00;\r
+       rps_tbl[1] = rps_01;\r
 \r
-    stream_size[0] = sizeof(stream_00);\r
-    stream_size[1] = sizeof(stream_01);\r
+       scaling_list_tbl[0] = scaling_list_00;\r
+       scaling_list_tbl[1] = scaling_list_01;\r
+\r
+       stream_tbl[0] = stream_00;\r
+       stream_tbl[1] = stream_01;\r
+\r
+       stream_size[0] = sizeof(stream_00);\r
+       stream_size[1] = sizeof(stream_01);\r
 \r
        pps_size[0] = sizeof(pps_00);\r
        pps_size[1] = sizeof(pps_01);\r
@@ -2283,10 +2375,10 @@ static int hevc_test_case0(vpu_service_info *pservice)
        cabac_size[0] = sizeof(Cabac_table);\r
        cabac_size[1] = sizeof(Cabac_table);\r
 \r
-    // create session\r
-    session.pid = current->pid;\r
-    session.type = VPU_DEC;\r
-    INIT_LIST_HEAD(&session.waiting);\r
+       /* create session */\r
+       session.pid = current->pid;\r
+       session.type = VPU_DEC;\r
+       INIT_LIST_HEAD(&session.waiting);\r
        INIT_LIST_HEAD(&session.running);\r
        INIT_LIST_HEAD(&session.done);\r
        INIT_LIST_HEAD(&session.list_session);\r
@@ -2294,33 +2386,31 @@ static int hevc_test_case0(vpu_service_info *pservice)
        atomic_set(&session.task_running, 0);\r
        list_add_tail(&session.list_session, &pservice->session);\r
 \r
-    yuv[0] = get_align_ptr_no_copy(256*256*2, &phy_yuv);\r
-    yuv[1] = get_align_ptr_no_copy(256*256*2, &phy_ref);\r
+       yuv[0] = get_align_ptr_no_copy(256*256*2, &phy_yuv);\r
+       yuv[1] = get_align_ptr_no_copy(256*256*2, &phy_ref);\r
 \r
        while (testidx < TEST_CNT) {\r
-       \r
-        // create registers\r
-        reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
-        if (NULL == reg) {\r
-            pr_err("error: kmalloc fail in reg_init\n");\r
-            return -1;\r
-        }\r
-\r
-\r
-        if (size > pservice->reg_size) {\r
-            printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
-            size = pservice->reg_size;\r
-        }\r
-        reg->session = &session;\r
-        reg->type = session.type;\r
-        reg->size = size;\r
-        reg->freq = VPU_FREQ_DEFAULT;\r
-        reg->reg = (unsigned long *)&reg[1];\r
-        INIT_LIST_HEAD(&reg->session_link);\r
-        INIT_LIST_HEAD(&reg->status_link);\r
-\r
-        // TODO: stuff registers\r
-        memcpy(&reg->reg[0], register_tbl[testidx], /*sizeof(register_00)*/ 176);\r
+               /* create registers */\r
+               reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
+               if (NULL == reg) {\r
+                       pr_err("error: kmalloc fail in reg_init\n");\r
+                       return -1;\r
+               }\r
+\r
+               if (size > pservice->reg_size) {\r
+                       printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
+                       size = pservice->reg_size;\r
+               }\r
+               reg->session = &session;\r
+               reg->type = session.type;\r
+               reg->size = size;\r
+               reg->freq = VPU_FREQ_DEFAULT;\r
+               reg->reg = (unsigned long *)&reg[1];\r
+               INIT_LIST_HEAD(&reg->session_link);\r
+               INIT_LIST_HEAD(&reg->status_link);\r
+\r
+               /* TODO: stuff registers */\r
+               memcpy(&reg->reg[0], register_tbl[testidx], /*sizeof(register_00)*/ 176);\r
 \r
                stream_buf = get_align_ptr(stream_tbl[testidx], stream_size[testidx], &phy_str);\r
                pps_buf = get_align_ptr(pps_tbl[0], pps_size[0], &phy_pps);\r
@@ -2330,108 +2420,103 @@ static int hevc_test_case0(vpu_service_info *pservice)
 \r
                pps = pps_buf;\r
 \r
-        // TODO: replace reigster address\r
-\r
-        for (i=0; i<64; i++) {\r
-            u32 scaling_offset;\r
-            u32 tmp;\r
-\r
-            scaling_offset = (u32)pps[i*80+74];\r
-            scaling_offset += (u32)pps[i*80+75] << 8;\r
-            scaling_offset += (u32)pps[i*80+76] << 16;\r
-            scaling_offset += (u32)pps[i*80+77] << 24;\r
-\r
-            tmp = phy_scl + scaling_offset;\r
-\r
-            pps[i*80+74] = tmp & 0xff;\r
-            pps[i*80+75] = (tmp >> 8) & 0xff;\r
-            pps[i*80+76] = (tmp >> 16) & 0xff;\r
-            pps[i*80+77] = (tmp >> 24) & 0xff;\r
-        }\r
-\r
-        printk("%s %d, phy stream %08x, phy pps %08x, phy rps %08x\n", __func__, __LINE__, phy_str, phy_pps, phy_rps);\r
-\r
-        reg->reg[1] = 0x21;\r
-        reg->reg[4] = phy_str;\r
-        reg->reg[5] = ((stream_size[testidx]+15)&(~15))+64;\r
-        reg->reg[6] = phy_cabac;\r
-        reg->reg[7] = testidx?phy_ref:phy_yuv;\r
-        reg->reg[42] = phy_pps;\r
-        reg->reg[43] = phy_rps;\r
-        for (i = 10; i <= 24; i++) {\r
-            reg->reg[i] = phy_yuv;\r
-        }\r
-\r
-        mutex_lock(&pservice->lock);\r
-        list_add_tail(&reg->status_link, &pservice->waiting);\r
-        list_add_tail(&reg->session_link, &session.waiting);\r
-        mutex_unlock(&pservice->lock);\r
-\r
-        printk("%s %d %p\n", __func__, __LINE__, pservice);\r
-\r
-        // stuff hardware\r
-        try_set_reg(pservice);\r
-\r
-        // wait for result\r
-        ret = wait_event_timeout(session.wait, !list_empty(&session.done), VPU_TIMEOUT_DELAY);\r
-        if (!list_empty(&session.done)) {\r
-            if (ret < 0) {\r
-                pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session.pid, ret);\r
-            }\r
-            ret = 0;\r
-        } else {\r
-            if (unlikely(ret < 0)) {\r
-                pr_err("error: pid %d wait task ret %d\n", session.pid, ret);\r
-            } else if (0 == ret) {\r
-                pr_err("error: pid %d wait %d task done timeout\n", session.pid, atomic_read(&session.task_running));\r
-                ret = -ETIMEDOUT;\r
-            }\r
-        }\r
-        if (ret < 0) {\r
-            int task_running = atomic_read(&session.task_running);\r
-            int n;\r
-            mutex_lock(&pservice->lock);\r
-            vpu_service_dump(pservice);\r
-            if (task_running) {\r
-                atomic_set(&session.task_running, 0);\r
-                atomic_sub(task_running, &pservice->total_running);\r
-                printk("%d task is running but not return, reset hardware...", task_running);\r
-                vpu_reset(pservice);\r
-                printk("done\n");\r
-            }\r
-            vpu_service_session_clear(pservice, &session);\r
-            mutex_unlock(&pservice->lock);\r
-\r
-            printk("\nDEC Registers:\n");\r
-               n = pservice->dec_dev.iosize >> 2;\r
-               for (i=0; i<n; i++) {\r
-                       printk("\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
-               }\r
-\r
-            pr_err("test index %d failed\n", testidx);\r
-            break;\r
-        } else {\r
-            pr_info("test index %d success\n", testidx);\r
-\r
-            vpu_reg *reg = list_entry(session.done.next, vpu_reg, session_link);\r
-\r
-            for (i=0; i<68; i++) {\r
-                if (i % 4 == 0) {\r
-                    printk("%02d: ", i);\r
-                }\r
-                printk("%08x ", reg->reg[i]);\r
-                if ((i+1) % 4 == 0) {\r
-                    printk("\n");\r
-                }\r
-            }\r
-\r
-            testidx++;\r
-        }\r
-\r
-        reg_deinit(pservice, reg);\r
-    }\r
-\r
-    return 0;\r
+               /* TODO: replace reigster address */\r
+               for (i=0; i<64; i++) {\r
+                       u32 scaling_offset;\r
+                       u32 tmp;\r
+\r
+                       scaling_offset = (u32)pps[i*80+74];\r
+                       scaling_offset += (u32)pps[i*80+75] << 8;\r
+                       scaling_offset += (u32)pps[i*80+76] << 16;\r
+                       scaling_offset += (u32)pps[i*80+77] << 24;\r
+\r
+                       tmp = phy_scl + scaling_offset;\r
+\r
+                       pps[i*80+74] = tmp & 0xff;\r
+                       pps[i*80+75] = (tmp >> 8) & 0xff;\r
+                       pps[i*80+76] = (tmp >> 16) & 0xff;\r
+                       pps[i*80+77] = (tmp >> 24) & 0xff;\r
+               }\r
+\r
+               printk("%s %d, phy stream %08x, phy pps %08x, phy rps %08x\n",\r
+                       __func__, __LINE__, phy_str, phy_pps, phy_rps);\r
+\r
+               reg->reg[1] = 0x21;\r
+               reg->reg[4] = phy_str;\r
+               reg->reg[5] = ((stream_size[testidx]+15)&(~15))+64;\r
+               reg->reg[6] = phy_cabac;\r
+               reg->reg[7] = testidx?phy_ref:phy_yuv;\r
+               reg->reg[42] = phy_pps;\r
+               reg->reg[43] = phy_rps;\r
+               for (i = 10; i <= 24; i++)\r
+                       reg->reg[i] = phy_yuv;\r
+\r
+               mutex_lock(&pservice->lock);\r
+               list_add_tail(&reg->status_link, &pservice->waiting);\r
+               list_add_tail(&reg->session_link, &session.waiting);\r
+               mutex_unlock(&pservice->lock);\r
+\r
+               printk("%s %d %p\n", __func__, __LINE__, pservice);\r
+\r
+               /* stuff hardware */\r
+               try_set_reg(pservice);\r
+\r
+               /* wait for result */\r
+               ret = wait_event_timeout(session.wait, !list_empty(&session.done), VPU_TIMEOUT_DELAY);\r
+               if (!list_empty(&session.done)) {\r
+                       if (ret < 0)\r
+                               pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session.pid, ret);\r
+                       ret = 0;\r
+               } else {\r
+                       if (unlikely(ret < 0)) {\r
+                               pr_err("error: pid %d wait task ret %d\n", session.pid, ret);\r
+                       } else if (0 == ret) {\r
+                               pr_err("error: pid %d wait %d task done timeout\n", session.pid, atomic_read(&session.task_running));\r
+                               ret = -ETIMEDOUT;\r
+                       }\r
+               }\r
+               if (ret < 0) {\r
+                       int task_running = atomic_read(&session.task_running);\r
+                       int n;\r
+                       mutex_lock(&pservice->lock);\r
+                       vpu_service_dump(pservice);\r
+                       if (task_running) {\r
+                               atomic_set(&session.task_running, 0);\r
+                               atomic_sub(task_running, &pservice->total_running);\r
+                               printk("%d task is running but not return, reset hardware...", task_running);\r
+                               vpu_reset(pservice);\r
+                               printk("done\n");\r
+                       }\r
+                       vpu_service_session_clear(pservice, &session);\r
+                       mutex_unlock(&pservice->lock);\r
+\r
+                       printk("\nDEC Registers:\n");\r
+                       n = pservice->dec_dev.iosize >> 2;\r
+                       for (i=0; i<n; i++)\r
+                               printk("\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
+\r
+                       pr_err("test index %d failed\n", testidx);\r
+                       break;\r
+               } else {\r
+                       pr_info("test index %d success\n", testidx);\r
+\r
+                       vpu_reg *reg = list_entry(session.done.next, vpu_reg, session_link);\r
+\r
+                       for (i=0; i<68; i++) {\r
+                               if (i % 4 == 0)\r
+                                       printk("%02d: ", i);\r
+                               printk("%08x ", reg->reg[i]);\r
+                               if ((i+1) % 4 == 0)\r
+                                       printk("\n");\r
+                       }\r
+\r
+                       testidx++;\r
+               }\r
+\r
+               reg_deinit(pservice, reg);\r
+       }\r
+\r
+       return 0;\r
 }\r
 \r
 #endif\r
index 75a54e1adbb5b58ea0fa8dfaad2e1ae0cffc30f0..1a9c61ee4d80c88ecbf5a2f6ad9b53ab411286f0 100644 (file)
@@ -249,3 +249,14 @@ config SYSV68_PARTITION
          partition table format used by Motorola Delta machines (using
          sysv68).
          Otherwise, say N.
+
+
+config RK_PARTITION
+       bool "Rockchip partition table support" if PARTITION_ADVANCED
+       default y if ARCH_ROCKCHIP
+       ---help---
+         Like most systems, Rockchip use its own hard disk partition table
+         format,incompatible with all others. Say Y here if you would like
+         to be able to read the hard diskpartition table format used by Rockchip
+         Soc inside machines with eMMC as main storage disk. Otherwise, as well
+         as you don't know what all this about, say N.
index 1e5d63d1f01c5e9bd538529b67de9561a54890fd..d6842b632b61868acbeb0e6233d8f41ecbfd6f0a 100644 (file)
@@ -18,6 +18,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
 obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
-
-#added for emmc in Rockchip project.
-obj-$(CONFIG_MMC_DW_ROCKCHIP) += mtdpart.o
+obj-$(CONFIG_RK_PARTITION) += rk.o
index 4997581ae64f0c737b427bcff01c4c9137a72f81..a7c678fff0b762d0102d411b34785c89f94b7eb7 100755 (executable)
@@ -19,8 +19,6 @@
 #include <linux/genhd.h>
 
 #include "check.h"
-#include "mtdpart.h"
-
 #include "acorn.h"
 #include "amiga.h"
 #include "atari.h"
@@ -35,6 +33,7 @@
 #include "efi.h"
 #include "karma.h"
 #include "sysv68.h"
+#include "rk.h"
 
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
 
@@ -105,9 +104,8 @@ static int (*check_part[])(struct parsed_partitions *) = {
 #ifdef CONFIG_SYSV68_PARTITION
        sysv68_partition,
 #endif
-
-#if CONFIG_MMC_DW_ROCKCHIP
-    mtdpart_partition,
+#ifdef CONFIG_RK_PARTITION
+       rkpart_partition,
 #endif
 
        NULL
@@ -163,10 +161,12 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
                sprintf(state->name, "p");
 
        i = res = err = 0;
-       
-       //if the disk is eMMC,then skip directly the check_part to mtdpart_partition; added by xbw, at 2014-03-24       
-       if((179 == MAJOR(bdev->bd_dev)&& (1 == hd->emmc_disk)))
-               i=sizeof(check_part)/sizeof(struct parsed_partitions *)-2;
+
+       /* Rockchip partition table ONLY used by eMMC disk */
+       #ifdef CONFIG_RK_PARTITION
+       if ((179 == MAJOR(bdev->bd_dev) && (1 == hd->emmc_disk)))
+               i = sizeof(check_part) / sizeof(struct parsed_partitions *) - 2;
+       #endif
 
        while (!res && check_part[i]) {
                memset(state->parts, 0, state->limit * sizeof(state->parts[0]));
diff --git a/block/partitions/mtdpart.c b/block/partitions/mtdpart.c
deleted file mode 100755 (executable)
index 6f3e004..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
-
-#include "check.h"
-#include "mtdpart.h"
-
-/* error message prefix */
-#define ERRP "mtd: "
-
-/* debug macro */
-#if 0
-#define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
-#else
-#define dbg(x)
-#endif
-
-#define SECTOR_1G      0x200000        // 0x200000 * 512 = 1G
-#define FROM_OFFSET    0x2000          // 4MB
-
-/* special size referring to all the remaining space in a partition */
-#define SIZE_REMAINING UINT_MAX
-#define OFFSET_CONTINUOUS UINT_MAX
-
-struct mtd_partition{
-       char *name;
-       sector_t from;
-       sector_t size;
-};
-struct cmdline_mtd_partition {
-       struct cmdline_mtd_partition *next;
-       char *mtd_id;
-       int num_parts;
-       struct mtd_partition *parts;
-};
-
-/* mtdpart_setup() parses into here */
-static struct cmdline_mtd_partition *partitions;
-
-/* the command line passed to mtdpart_setupd() */
-static char *cmdline;
-static int cmdline_parsed = 0;
-
-/*
- * Parse one partition definition for an MTD. Since there can be many
- * comma separated partition definitions, this function calls itself
- * recursively until no more partition definitions are found. Nice side
- * effect: the memory to keep the mtd_partition structs and the names
- * is allocated upon the last definition being found. At that point the
- * syntax has been verified ok.
- */
-static struct mtd_partition * newpart(char *s,
-                                      char **retptr,
-                                      int *num_parts,
-                                      int this_part,
-                                      unsigned char **extra_mem_ptr,
-                                      int extra_mem_size)
-{
-       struct mtd_partition *parts;
-       sector_t size;
-       sector_t from = OFFSET_CONTINUOUS;
-       char *name;
-       int name_len;
-       unsigned char *extra_mem;
-       char delim;
-
-       /* fetch the partition size */
-       if (*s == '-')
-       {       /* assign all remaining space to this partition */
-               size = SIZE_REMAINING;
-               s++;
-       }
-       else
-       {
-               size = memparse(s, &s);
-               if (size < (PAGE_SIZE)>>9)
-               {
-                       printk(KERN_ERR ERRP "partition size too small (%llx)\n", size);
-                       return NULL;
-               }
-       }
-
-       /* fetch partition name */
-       delim = 0;
-        /* check for from */
-        if (*s == '@')
-       {
-                s++;
-                from = memparse(s, &s);
-        }
-        /* now look for name */
-       if (*s == '(')
-       {
-               delim = ')';
-       }
-
-       if (delim)
-       {
-               char *p;
-
-               name = ++s;
-               p = strchr(name, delim);
-               if (!p)
-               {
-                       printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
-                       return NULL;
-               }
-               name_len = p - name;
-               s = p + 1;
-       }
-       else
-       {
-               name = NULL;
-               name_len = 13; /* Partition_000 */
-       }
-
-       /* record name length for memory allocation later */
-       extra_mem_size += name_len + 1;
-
-       /* test if more partitions are following */
-       if (*s == ',')
-       {
-               if (size == SIZE_REMAINING)
-               {
-                       printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
-                       return NULL;
-               }
-               /* more partitions follow, parse them */
-               parts = newpart(s + 1, &s, num_parts, this_part + 1,
-                               &extra_mem, extra_mem_size);
-               if (!parts)
-                       return NULL;
-       }
-       else
-       {       /* this is the last partition: allocate space for all */
-               int alloc_size;
-
-               *num_parts = this_part + 1;
-               alloc_size = *num_parts * sizeof(struct mtd_partition) +
-                            extra_mem_size;
-               parts = kzalloc(alloc_size, GFP_KERNEL);
-               if (!parts)
-               {
-                       printk(KERN_ERR ERRP "out of memory\n");
-                       return NULL;
-               }
-               extra_mem = (unsigned char *)(parts + *num_parts);
-       }
-       /* enter this partition (from will be calculated later if it is zero at this point) */
-       parts[this_part].size = size;
-       parts[this_part].from = from;
-       if (name)
-       {
-               strlcpy(extra_mem, name, name_len + 1);
-       }
-       else
-       {
-               sprintf(extra_mem, "Partition_%03d", this_part);
-       }
-       parts[this_part].name = extra_mem;
-       extra_mem += name_len + 1;
-
-       dbg(("partition %d: name <%s>, from %llx, size %llx\n",
-            this_part,
-            parts[this_part].name,
-            parts[this_part].from,
-            parts[this_part].size));
-
-       /* return (updated) pointer to extra_mem memory */
-       if (extra_mem_ptr)
-         *extra_mem_ptr = extra_mem;
-
-       /* return (updated) pointer command line string */
-       *retptr = s;
-
-       /* return partition table */
-       return parts;
-}
-
-/*
- * Parse the command line.
- */
-static int mtdpart_setup_real(char *s)
-{
-       cmdline_parsed = 1;
-
-       for( ; s != NULL; )
-       {
-               struct cmdline_mtd_partition *this_mtd;
-               struct mtd_partition *parts;
-               int mtd_id_len;
-               int num_parts;
-               char *p, *mtd_id;
-
-               mtd_id = s;
-               /* fetch <mtd-id> */
-               if (!(p = strchr(s, ':')))
-               {
-                       dbg(( "no mtd-id\n"));
-                       return 0;
-               }
-               mtd_id_len = p - mtd_id;
-
-               dbg(("parsing <%s>\n", p+1));
-
-               /*
-                * parse one mtd. have it reserve memory for the
-                * struct cmdline_mtd_partition and the mtd-id string.
-                */
-               parts = newpart(p + 1,          /* cmdline */
-                               &s,             /* out: updated cmdline ptr */
-                               &num_parts,     /* out: number of parts */
-                               0,              /* first partition */
-                               (unsigned char**)&this_mtd, /* out: extra mem */
-                               mtd_id_len + 1 + sizeof(*this_mtd) +
-                               sizeof(void*)-1 /*alignment*/);
-               if(!parts)
-               {
-                       /*
-                        * An error occurred. We're either:
-                        * a) out of memory, or
-                        * b) in the middle of the partition spec
-                        * Either way, this mtd is hosed and we're
-                        * unlikely to succeed in parsing any more
-                        */
-                        return 0;
-                }
-
-               /* align this_mtd */
-               this_mtd = (struct cmdline_mtd_partition *)
-                       ALIGN((unsigned long)this_mtd, sizeof(void*));
-               /* enter results */
-               this_mtd->parts = parts;
-               this_mtd->num_parts = num_parts;
-               this_mtd->mtd_id = (char*)(this_mtd + 1);
-               strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1);
-
-               /* link into chain */
-               this_mtd->next = partitions;
-               partitions = this_mtd;
-
-               dbg(("mtdid=<%s> num_parts=<%d>\n",
-                    this_mtd->mtd_id, this_mtd->num_parts));
-
-               /* EOS - we're done */
-               if (*s == 0)
-                       break;
-#if 0
-               /* does another spec follow? */
-               if (*s != ';')
-               {
-                       printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s);
-                       return 0;
-               }
-#endif
-               s++;
-       }
-       return 1;
-}
-
-/*
- * Main function to be called from the MTD mapping driver/device to
- * obtain the partitioning information. At this point the command line
- * arguments will actually be parsed and turned to struct mtd_partition
- * information. It returns partitions for the requested mtd device, or
- * the first one in the chain if a NULL mtd_id is passed in.
- */
-static int parse_cmdline_partitions(sector_t n,
-                                   struct mtd_partition **pparts,
-                                   unsigned long origin)
-{
-       unsigned long from;
-       int i;
-       struct cmdline_mtd_partition *part;
-       const char *mtd_id = "rk29xxnand";
-
-       /* parse command line */
-       if (!cmdline_parsed)
-               mtdpart_setup_real(cmdline);
-
-       for(part = partitions; part; part = part->next)
-       {
-               if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id)))
-               {
-                       for(i = 0, from = 0; i < part->num_parts; i++)
-                       {
-                               if (part->parts[i].from == OFFSET_CONTINUOUS)
-                                 part->parts[i].from = from;
-                               else
-                                 from = part->parts[i].from;
-                               if (part->parts[i].size == SIZE_REMAINING)
-                                 part->parts[i].size = n - from - FROM_OFFSET;
-                               if (from + part->parts[i].size > n)
-                               {
-                                       printk(KERN_WARNING ERRP
-                                              "%s: partitioning exceeds flash size, truncating\n",
-                                              part->mtd_id);
-                                       part->parts[i].size = n - from;
-                                       part->num_parts = i;
-                               }
-                               from += part->parts[i].size;
-                       }
-                       *pparts = kmemdup(part->parts,
-                                       sizeof(*part->parts) * part->num_parts,
-                                       GFP_KERNEL);
-                       if (!*pparts)
-                               return -ENOMEM;
-                       return part->num_parts;
-               }
-       }
-       return 0;
-}
-
-static void rk_emmc_fix(void)
-{
-       const char mode_emmc[] = " androidboot.mode=emmc";
-       const char charger_emmc[] = " androidboot.charger.emmc=1";
-       char *new_command_line;
-       size_t saved_command_line_len = strlen(saved_command_line);
-
-       if (strstr(saved_command_line, "androidboot.mode=charger")) {
-               new_command_line = kzalloc(saved_command_line_len + strlen(charger_emmc) + 1, GFP_KERNEL);
-               sprintf(new_command_line, "%s%s", saved_command_line, charger_emmc);
-       } else {
-               new_command_line = kzalloc(saved_command_line_len + strlen(mode_emmc) + 1, GFP_KERNEL);
-               sprintf(new_command_line, "%s%s", saved_command_line, mode_emmc);
-       }
-       saved_command_line = new_command_line;
-}
-
-int mtdpart_partition(struct parsed_partitions *state)
-{
-       int num_parts = 0, i;
-       sector_t n = get_capacity(state->bdev->bd_disk);
-       struct mtd_partition *parts = NULL;
-
-       if(n < SECTOR_1G)
-               return 0;
-       
-        //only used to eMMC-disk
-        if(1 != state->bdev->bd_disk->emmc_disk)
-               return 0;
-
-       cmdline = strstr(saved_command_line, "mtdparts=") + 9;
-       
-       num_parts = parse_cmdline_partitions(n, &parts, 0);
-       if(num_parts < 0)
-               return num_parts;
-
-       for(i = 0; i < num_parts; i++){
-               put_partition(state, i+1, parts[i].from + FROM_OFFSET, parts[i].size);
-               strcpy(state->parts[i+1].info.volname, parts[i].name);
-               printk(KERN_INFO "%10s: 0x%09llx -- 0x%09llx (%llu MB)\n", 
-                               parts[i].name,
-                               parts[i].from * 512,
-                               (parts[i].from + parts[i].size) * 512,
-                               parts[i].size / 2048);
-       }
-
-       rk_emmc_fix();
-
-       return 1;
-}
-
-
diff --git a/block/partitions/mtdpart.h b/block/partitions/mtdpart.h
deleted file mode 100755 (executable)
index e5cde6a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- *  fs/partitions/mtdpart.h
- */
-
-int mtdpart_partition(struct parsed_partitions *state);
diff --git a/block/partitions/rk.c b/block/partitions/rk.c
new file mode 100755 (executable)
index 0000000..93cb0d6
--- /dev/null
@@ -0,0 +1,333 @@
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include "check.h"
+#include "rk.h"
+
+/* rkpart_setup() parses into here */
+static struct cmdline_rk_partition *partitions;
+/* the command line passed to mtdpart_setupd() */
+static char *cmdline;
+static int cmdline_parsed;
+
+/*
+ * Parse one partition definition for an rkpart. Since there can be many
+ * comma separated partition definitions, this function calls itself
+ * recursively until no more partition definitions are found. Nice side
+ * effect: the memory to keep the rk_partition structs and the names
+ * is allocated upon the last definition being found. At that point the
+ * syntax has been verified ok.
+ */
+static struct rk_partition *newpart(char *s,
+                                        char **retptr,
+                                        int *num_parts,
+                                        int this_part,
+                                        unsigned char **extra_mem_ptr,
+                                        int extra_mem_size)
+{
+       struct rk_partition *parts;
+       sector_t size;
+       sector_t from = OFFSET_CONTINUOUS;
+       char *name;
+       int name_len;
+       unsigned char *extra_mem;
+       char delim;
+
+       /* fetch the partition size */
+       if (*s == '-')
+       {       /* assign all remaining space to this partition */
+               size = SIZE_REMAINING;
+               s++;
+       }
+       else
+       {
+               size = memparse(s, &s);
+               /* No sense support partition less than 8B */
+               if (size < ((PAGE_SIZE) >> 9))
+               {
+                       printk(KERN_ERR ERRP "partition size too small (%llx)\n", size);
+                       return NULL;
+               }
+       }
+
+       /* fetch partition name */
+       delim = 0;
+        /* check for from */
+        if (*s == '@')
+       {
+                s++;
+                from = memparse(s, &s);
+        }
+        /* now look for name */
+       if (*s == '(')
+       {
+               delim = ')';
+       }
+
+       if (delim)
+       {
+               char *p;
+
+               name = ++s;
+               p = strchr(name, delim);
+               if (!p)
+               {
+                       printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
+                       return NULL;
+               }
+               name_len = p - name;
+               s = p + 1;
+       }
+       else
+       {
+               name = NULL;
+               name_len = 13; /* Partition_000 */
+       }
+
+       /* record name length for memory allocation later */
+       extra_mem_size += name_len + 1;
+
+       /* test if more partitions are following */
+       if (*s == ',')
+       {
+               if (size == SIZE_REMAINING)
+               {
+                       printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
+                       return NULL;
+               }
+               /* more partitions follow, parse them */
+               parts = newpart(s + 1, &s, num_parts, this_part + 1,
+                               &extra_mem, extra_mem_size);
+               if (!parts)
+                       return NULL;
+       }
+       else
+       {       /* this is the last partition: allocate space for all */
+               int alloc_size;
+
+               *num_parts = this_part + 1;
+               alloc_size = *num_parts * sizeof(struct rk_partition) +
+                            extra_mem_size;
+               parts = kzalloc(alloc_size, GFP_KERNEL);
+               if (!parts)
+               {
+                       printk(KERN_ERR ERRP "out of memory\n");
+                       return NULL;
+               }
+               extra_mem = (unsigned char *)(parts + *num_parts);
+       }
+       /* enter this partition (from will be calculated later if it is zero at this point) */
+       parts[this_part].size = size;
+       parts[this_part].from = from;
+       if (name)
+       {
+               strlcpy(extra_mem, name, name_len + 1);
+       }
+       else
+       {
+               sprintf(extra_mem, "Partition_%03d", this_part);
+       }
+       parts[this_part].name = extra_mem;
+       extra_mem += name_len + 1;
+
+       dbg(("partition %d: name <%s>, from %llx, size %llx\n",
+            this_part,
+            parts[this_part].name,
+            parts[this_part].from,
+            parts[this_part].size));
+
+       /* return (updated) pointer to extra_mem memory */
+       if (extra_mem_ptr)
+         *extra_mem_ptr = extra_mem;
+
+       /* return (updated) pointer command line string */
+       *retptr = s;
+
+       /* return partition table */
+       return parts;
+}
+
+/*
+ * Parse the command line.
+ */
+static int rkpart_setup_real(char *s)
+{
+       cmdline_parsed = 1;
+
+       for( ; s != NULL; )
+       {
+               struct cmdline_rk_partition *this_rk;
+               struct rk_partition *parts;
+               int rk_id_len;
+               int num_parts;
+               char *p, *rk_id;
+
+               rk_id = s;
+               /* fetch <rk-id> */
+               if (!(p = strchr(s, ':')))
+               {
+                       dbg(( "no rk-id\n"));
+                       return 0;
+               }
+               rk_id_len = p - rk_id;
+
+               dbg(("parsing <%s>\n", p + 1));
+
+               /*
+                * parse one mtd. have it reserve memory for the
+                * struct cmdline_mtd_partition and the mtd-id string.
+                */
+               parts = newpart(p + 1,          /* cmdline */
+                               &s,             /* out: updated cmdline ptr */
+                               &num_parts,     /* out: number of parts */
+                               0,              /* first partition */
+                               (unsigned char**)&this_rk, /* out: extra mem */
+                               rk_id_len + 1 + sizeof(*this_rk) +
+                               sizeof(void*)-1 /*alignment*/);
+               if(!parts)
+               {
+                       /*
+                        * An error occurred. We're either:
+                        * a) out of memory, or
+                        * b) in the middle of the partition spec
+                        * Either way, this mtd is hosed and we're
+                        * unlikely to succeed in parsing any more
+                        */
+                        return 0;
+                }
+
+               /* align this_rk */
+               this_rk = (struct cmdline_rk_partition *)
+                       ALIGN((unsigned long)this_rk, sizeof(void*));
+               /* enter results */
+               this_rk->parts = parts;
+               this_rk->num_parts = num_parts;
+               this_rk->rk_id = (char*)(this_rk + 1);
+               strlcpy(this_rk->rk_id, rk_id, rk_id_len + 1);
+
+               /* link into chain */
+               this_rk->next = partitions;
+               partitions = this_rk;
+
+               dbg(("rkid=<%s> num_parts=<%d>\n",
+                    this_rk->mtd_id, this_rk->num_parts));
+
+               /* EOS - we're done */
+               if (*s == 0)
+                       break;
+               s++;
+       }
+       return 1;
+}
+
+/*
+ * Main function to be called from the MTD mapping driver/device to
+ * obtain the partitioning information. At this point the command line
+ * arguments will actually be parsed and turned to struct mtd_partition
+ * information. It returns partitions for the requested mtd device, or
+ * the first one in the chain if a NULL mtd_id is passed in.
+ */
+static int parse_cmdline_partitions(sector_t n,
+                                   struct rk_partition **pparts,
+                                   unsigned long origin)
+{
+       unsigned long from;
+       int i;
+       struct cmdline_rk_partition *part;
+       /* Fixme: parameter should be coherence with part table id */
+       const char *rk_id = "rk29xxnand";
+
+       /* parse command line */
+       if (!cmdline_parsed)
+               rkpart_setup_real(cmdline);
+
+       for(part = partitions; part; part = part->next)
+       {
+               if ((!rk_id) || (!strcmp(part->rk_id, rk_id)))
+               {
+                       for(i = 0, from = 0; i < part->num_parts; i++)
+                       {
+                               if (part->parts[i].from == OFFSET_CONTINUOUS)
+                                 part->parts[i].from = from;
+                               else
+                                 from = part->parts[i].from;
+                               if (part->parts[i].size == SIZE_REMAINING)
+                                 part->parts[i].size = n - from - FROM_OFFSET;
+                               if (from + part->parts[i].size > n)
+                               {
+                                       printk(KERN_WARNING ERRP
+                                              "%s: partitioning exceeds flash size, truncating\n",
+                                              part->rk_id);
+                                       part->parts[i].size = n - from;
+                                       part->num_parts = i;
+                               }
+                               from += part->parts[i].size;
+                       }
+                       *pparts = kmemdup(part->parts,
+                                       sizeof(*part->parts) * part->num_parts,
+                                       GFP_KERNEL);
+                       if (!*pparts)
+                               return -ENOMEM;
+                       return part->num_parts;
+               }
+       }
+       return 0;
+}
+
+static void rkpart_bootmode_fixup(void)
+{
+       const char mode[] = " androidboot.mode=emmc";
+       const char charger[] = " androidboot.charger.emmc=1";
+       char *new_command_line;
+       size_t saved_command_line_len = strlen(saved_command_line);
+
+       if (strstr(saved_command_line, "androidboot.mode=charger")) {
+               new_command_line = kzalloc(saved_command_line_len + strlen(charger) + 1, GFP_KERNEL);
+               sprintf(new_command_line, "%s%s", saved_command_line, charger);
+       } else {
+               new_command_line = kzalloc(saved_command_line_len + strlen(mode) + 1, GFP_KERNEL);
+               sprintf(new_command_line, "%s%s", saved_command_line, mode);
+       }
+       saved_command_line = new_command_line;
+}
+
+int rkpart_partition(struct parsed_partitions *state)
+{
+       int num_parts = 0, i;
+       sector_t n = get_capacity(state->bdev->bd_disk);
+       struct rk_partition *parts = NULL;
+
+       if (n < SECTOR_1G)
+               return 0;
+
+        /* ONLY be used by eMMC-disk */
+        if (1 != state->bdev->bd_disk->emmc_disk)
+                return 0;
+
+        /* Fixme: parameter should be coherence with part table */
+       cmdline = strstr(saved_command_line, "mtdparts=") + 9;
+       cmdline_parsed = 0;
+
+       num_parts = parse_cmdline_partitions(n, &parts, 0);
+       if (num_parts < 0)
+               return num_parts;
+
+       for (i = 0; i < num_parts; i++) {
+               put_partition(  state,
+                               i+1,
+                                parts[i].from + FROM_OFFSET,
+                                parts[i].size);
+               strcpy(state->parts[i+1].info.volname, parts[i].name);
+                printk(KERN_INFO "%10s: 0x%09llx -- 0x%09llx (%llu MB)\n", 
+                               parts[i].name,
+                               parts[i].from * 512,
+                               (parts[i].from + parts[i].size) * 512,
+                               parts[i].size / 2048);
+       }
+
+       rkpart_bootmode_fixup();
+
+       return 1;
+}
+
+
diff --git a/block/partitions/rk.h b/block/partitions/rk.h
new file mode 100755 (executable)
index 0000000..25085e7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  block/partitions/rk.h
+ */
+
+/* error message prefix */
+#define ERRP "rkpart: "
+
+/* debug macro */
+#define RKPART_DEBUG 0
+#if RKPART_DEBUG
+#define dbg(x)  do {    \
+printk("DEBUG-CMDLINE-PART: ");        \
+printk x;       \
+} while (0)
+#else
+#define dbg(x)
+#endif
+
+/* At least 1GB disk support*/
+#define SECTOR_1G      0x200000
+
+/* Default partition table offet got from loader: 4MB*/
+#define FROM_OFFSET    0x2000
+
+/* special size referring to all the remaining space in a partition */
+#define SIZE_REMAINING UINT_MAX
+#define OFFSET_CONTINUOUS UINT_MAX
+
+struct rk_partition {
+       char *name;
+       sector_t from;
+       sector_t size;
+};
+struct cmdline_rk_partition {
+       struct cmdline_rk_partition *next;
+       char *rk_id;
+       int num_parts;
+       struct rk_partition *parts;
+};
+int rkpart_partition(struct parsed_partitions *state);
old mode 100644 (file)
new mode 100755 (executable)
index e4a0b48..c092f83
@@ -177,6 +177,64 @@ static const struct apll_clk_set rk3288_apll_table[] = {
        _RK3288_APLL_SET_CLKS(0,        1,      32,     16,     2,      2,      4,      4,      4),
 };
 
+static const struct apll_clk_set rk3036_apll_table[] = {
+       _RK3036_APLL_SET_CLKS(1608, 1, 67, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1584, 1, 66, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1560, 1, 65, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1536, 1, 64, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1512, 1, 63, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1488, 1, 62, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1464, 1, 61, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1440, 1, 60, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1416, 1, 59, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1392, 1, 58, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1368, 1, 57, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1344, 1, 56, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1320, 1, 55, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1296, 1, 54, 1, 1, 1, 0, 81, 81, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1272, 1, 53, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1248, 1, 52, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1200, 1, 50, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1104, 1, 46, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1100, 12, 550, 1, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1008, 1, 84, 2, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(1000, 6, 500, 2, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(984, 1, 82, 2, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(960, 1, 80, 2, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(936, 1, 78, 2, 1, 1, 0, 81, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(912, 1, 76, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(900, 4, 300, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(888, 1, 74, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(864, 1, 72, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(840, 1, 70, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(816, 1, 68, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(800, 6, 400, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(700, 6, 350, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(696, 1, 58, 2, 1, 1, 0, 41, 41, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(600, 1, 75, 3, 1, 1, 0, 41, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(504, 1, 63, 3, 1, 1, 0, 41, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(500, 6, 250, 2, 1, 1, 0, 41, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(408, 1, 68, 2, 2, 1, 0, 41, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(312, 1, 52, 2, 2, 1, 0, 41, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(216, 1, 72, 4, 2, 1, 0, 41, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(96, 1, 64, 4, 4, 1, 0, 21, 21, 41, 21, 21),
+       _RK3036_APLL_SET_CLKS(0, 1, 0, 1, 1, 1, 0, 21, 21, 41, 21, 21),
+};
+
+static const struct pll_clk_set rk3036plus_pll_com_table[] = {
+       _RK3036_PLL_SET_CLKS(1188000, 2, 99, 1, 1, 1, 0),
+       _RK3036_PLL_SET_CLKS(594000, 2, 99, 2, 1, 1, 0),
+       /*_RK3036_PLL_SET_CLKS(297000, 2, 99, 4, 1, 1, 0),*/
+};
+
+static const struct pll_clk_set rk312xplus_pll_com_table[] = {
+       /*_RK3036_PLL_SET_CLKS(1064000, 3, 133, 1, 1, 1, 0),*/
+       /*_RK3036_PLL_SET_CLKS(798000, 2, 133, 2, 1, 1, 0),*/
+       _RK3036_PLL_SET_CLKS(594000, 2, 99, 2, 1, 1, 0),
+       _RK3036_PLL_SET_CLKS(500000, 6, 250, 2, 1, 1, 0),
+       _RK3036_PLL_SET_CLKS(400000, 6, 400, 2, 2, 1, 0),
+};
+
 static void pll_wait_lock(struct clk_hw *hw)
 {
        struct clk_pll *pll = to_clk_pll(hw);
@@ -204,6 +262,33 @@ static void pll_wait_lock(struct clk_hw *hw)
        }
 }
 
+static void rk3036_pll_wait_lock(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       int delay = 24000000;
+
+
+       while (delay > 0) {
+               if (cru_readl(pll->status_offset) & (1 << pll->status_shift))
+                       break;
+               delay--;
+       }
+
+       if (delay == 0) {
+               clk_err("pll %s: can't lock! status_shift=%u\n"
+                               "pll_con0=%08x\npll_con1=%08x\n"
+                               "pll_con2=%08x\n",
+                               __clk_get_name(hw->clk),
+                               pll->status_shift,
+                               cru_readl(pll->reg + RK3188_PLL_CON(0)),
+                               cru_readl(pll->reg + RK3188_PLL_CON(1)),
+                               cru_readl(pll->reg + RK3188_PLL_CON(2)));
+               while (1);
+
+       }
+}
+
+
 /* get rate that is most close to target */
 static const struct apll_clk_set *apll_get_best_set(unsigned long rate,
                const struct apll_clk_set *table)
@@ -1347,7 +1432,344 @@ static const struct clk_ops clk_pll_ops_3288_apll = {
        .set_rate = clk_pll_set_rate_3288_apll,
 };
 
+/* CLK_PLL_3036_APLL type ops */
+#define FRAC_MODE      0
+static unsigned long rk3036_pll_clk_recalc(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       unsigned long rate;
+       unsigned int dsmp = 0;
+       u64 rate64 = 0, frac_rate64 = 0;
+
+       dsmp = RK3036_PLL_GET_DSMPD(cru_readl(pll->reg + RK3188_PLL_CON(1)));
+
+       if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift)) {
+               u32 pll_con0 = cru_readl(pll->reg + RK3188_PLL_CON(0));
+               u32 pll_con1 = cru_readl(pll->reg + RK3188_PLL_CON(1));
+               u32 pll_con2 = cru_readl(pll->reg + RK3188_PLL_CON(2));
+               /*integer mode*/
+               rate64 = (u64)parent_rate * RK3036_PLL_GET_FBDIV(pll_con0);
+               do_div(rate64, RK3036_PLL_GET_REFDIV(pll_con1));
+
+               if (FRAC_MODE == dsmp) {
+                       /*fractional mode*/
+                       frac_rate64 = (u64)parent_rate
+                       * RK3036_PLL_GET_FRAC(pll_con2);
+                       do_div(frac_rate64, RK3036_PLL_GET_REFDIV(pll_con1));
+                       rate64 += frac_rate64 >> 24;
+                       clk_debug("%s frac_rate=%llu(%08x/2^24) by pass mode\n",
+                                       __func__, frac_rate64 >> 24,
+                                       RK3036_PLL_GET_FRAC(pll_con2));
+               }
+               do_div(rate64, RK3036_PLL_GET_POSTDIV1(pll_con0));
+               do_div(rate64, RK3036_PLL_GET_POSTDIV2(pll_con1));
+
+               rate = rate64;
+               } else {
+               rate = parent_rate;
+               clk_debug("pll_clk_recalc rate=%lu by pass mode\n", rate);
+       }
+       return rate;
+}
+
+static unsigned long clk_pll_recalc_rate_3036_apll(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       return rk3036_pll_clk_recalc(hw, parent_rate);
+}
+
+static long clk_pll_round_rate_3036_apll(struct clk_hw *hw, unsigned long rate,
+               unsigned long *prate)
+{
+       struct clk *parent = __clk_get_parent(hw->clk);
+
+       if (parent && (rate == __clk_get_rate(parent))) {
+               clk_debug("pll %s round rate=%lu equal to parent rate\n",
+                               __clk_get_name(hw->clk), rate);
+               return rate;
+       }
+
+       return (apll_get_best_set(rate, rk3036_apll_table)->rate);
+}
+
+static  int rk3036_pll_clk_set_rate(struct pll_clk_set *clk_set,
+       struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
 
+       /*enter slowmode*/
+       cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
+       pll->mode_offset);
+
+       cru_writel(clk_set->pllcon0,  pll->reg + RK3188_PLL_CON(0));
+       cru_writel(clk_set->pllcon1,  pll->reg + RK3188_PLL_CON(1));
+       cru_writel(clk_set->pllcon2,  pll->reg + RK3188_PLL_CON(2));
+
+       clk_debug("pllcon0%08x\n", cru_readl(pll->reg + RK3188_PLL_CON(0)));
+       clk_debug("pllcon1%08x\n", cru_readl(pll->reg + RK3188_PLL_CON(1)));
+       clk_debug("pllcon2%08x\n", cru_readl(pll->reg + RK3188_PLL_CON(2)));
+       /*wating lock state*/
+       udelay(clk_set->rst_dly);
+       rk3036_pll_wait_lock(hw);
+
+       /*return form slow*/
+       cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift),
+       pll->mode_offset);
+
+       return 0;
+}
+
+#define MIN_FOUTVCO_FREQ       (400 * 1000 * 1000)
+#define MAX_FOUTVCO_FREQ       (1600 * 1000 * 1000)
+static int rk3036_pll_clk_set_postdiv(unsigned long fout_hz,
+u32 *postdiv1, u32 *postdiv2, u32 *foutvco)
+{
+       if (fout_hz < MIN_FOUTVCO_FREQ) {
+               for (*postdiv1 = 1; *postdiv1 <= 7; (*postdiv1)++)
+                       for (*postdiv2 = 1; *postdiv2 <= 7; (*postdiv2)++) {
+                               if (fout_hz * (*postdiv1) * (*postdiv2)
+                                       >= MIN_FOUTVCO_FREQ && fout_hz
+                                       * (*postdiv1) * (*postdiv2)
+                                       <= MAX_FOUTVCO_FREQ) {
+                                       *foutvco = fout_hz * (*postdiv1)
+                                               * (*postdiv2);
+                                       return 0;
+                               }
+                       }
+               clk_debug("CANNOT FINE postdiv1/2 to make fout in range from 400M to 1600M, fout = %lu\n",
+                               fout_hz);
+       } else {
+               *postdiv1 = 1;
+               *postdiv2 = 1;
+       }
+       return 0;
+}
+
+static int rk3036_pll_clk_get_set(unsigned long fin_hz, unsigned long fout_hz,
+               u32 *refdiv, u32 *fbdiv, u32 *postdiv1,
+               u32 *postdiv2, u32 *frac)
+{
+       /* FIXME set postdiv1/2 always 1*/
+       u32 gcd, foutvco = fout_hz;
+       u64 fin_64, frac_64;
+       u32 f_frac;
+
+       if (!fin_hz || !fout_hz || fout_hz == fin_hz)
+               return -1;
+
+       rk3036_pll_clk_set_postdiv(fout_hz, postdiv1, postdiv2, &foutvco);
+       if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz) {
+               fin_hz /= MHZ;
+               foutvco /= MHZ;
+               gcd = clk_gcd(fin_hz, foutvco);
+               *refdiv = fin_hz / gcd;
+               *fbdiv = foutvco / gcd;
+
+               *frac = 0;
+
+               clk_debug("fin=%lu,fout=%lu,gcd=%u,refdiv=%u,fbdiv=%u,postdiv1=%u,postdiv2=%u,frac=%u\n",
+                       fin_hz, fout_hz, gcd, *refdiv, *fbdiv, *postdiv1, *postdiv2, *frac);
+       } else {
+               clk_debug("******frac div running, fin_hz=%lu, fout_hz=%lu,fin_INT_mhz=%lu, fout_INT_mhz=%lu\n",
+                       fin_hz, fout_hz, fin_hz / MHZ * MHZ, fout_hz / MHZ * MHZ);
+               clk_debug("******frac get postdiv1=%u, postdiv2=%u,foutvco=%u\n",
+                       *postdiv1, *postdiv2, foutvco);
+               gcd = clk_gcd(fin_hz / MHZ, foutvco / MHZ);
+               *refdiv = fin_hz / MHZ / gcd;
+               *fbdiv = foutvco / MHZ / gcd;
+               clk_debug("******frac get refdiv=%u, fbdiv=%u\n", *refdiv, *fbdiv);
+
+               *frac = 0;
+
+               f_frac = (foutvco % MHZ);
+               fin_64 = fin_hz;
+               do_div(fin_64, (u64)*refdiv);
+               frac_64 = (u64)f_frac << 24;
+               do_div(frac_64, fin_64);
+               *frac = (u32) frac_64;
+               clk_debug("frac=%x\n", *frac);
+       }
+       return 0;
+}
+static int rk3036_pll_set_con(struct clk_hw *hw, u32 refdiv, u32 fbdiv, u32 postdiv1, u32 postdiv2, u32 frac)
+{
+       struct pll_clk_set temp_clk_set;
+       temp_clk_set.pllcon0 = RK3036_PLL_SET_FBDIV(fbdiv) | RK3036_PLL_SET_POSTDIV1(postdiv1);
+       temp_clk_set.pllcon1 = RK3036_PLL_SET_REFDIV(refdiv) | RK3036_PLL_SET_POSTDIV2(postdiv2);
+       if (frac != 0)
+               temp_clk_set.pllcon1 |= RK3036_PLL_SET_DSMPD(0);
+       else
+               temp_clk_set.pllcon1 |= RK3036_PLL_SET_DSMPD(1);
+
+       temp_clk_set.pllcon2 = RK3036_PLL_SET_FRAC(frac);
+       temp_clk_set.rst_dly = 0;
+       clk_debug("setting....\n");
+       return rk3036_pll_clk_set_rate(&temp_clk_set, hw);
+}
+
+static int clk_pll_set_rate_3036_apll(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags;
+       u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
+       struct apll_clk_set *ps = (struct apll_clk_set *)(rk3036_apll_table);
+
+       while (ps->rate) {
+               if (ps->rate == rate) {
+                       break;
+               }
+               ps++;
+       }
+
+       clk_debug("%s %lu\n", __func__,  rate);
+       clk_debug("pllcon0 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(0)));
+       clk_debug("pllcon1 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(1)));
+       clk_debug("pllcon2 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(2)));
+       clk_debug("clksel0 %08x\n", cru_readl(RK3036_CRU_CLKSELS_CON(0)));
+       clk_debug("clksel1 %08x\n", cru_readl(RK3036_CRU_CLKSELS_CON(1)));
+       if (ps->rate == rate) {
+               clk_debug("apll get a rate\n");
+
+               /*enter slowmode*/
+               local_irq_save(flags);
+               cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
+               loops_per_jiffy = LPJ_24M;
+
+               cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
+               cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
+               cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
+               cru_writel(ps->clksel0, RK3036_CRU_CLKSELS_CON(0));
+               cru_writel(ps->clksel1, RK3036_CRU_CLKSELS_CON(1));
+
+               clk_debug("pllcon0 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(0)));
+               clk_debug("pllcon1 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(1)));
+               clk_debug("pllcon2 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(2)));
+               clk_debug("clksel0 %08x\n", cru_readl(RK3036_CRU_CLKSELS_CON(0)));
+               clk_debug("clksel1 %08x\n", cru_readl(RK3036_CRU_CLKSELS_CON(1)));
+
+               /*wating lock state*/
+               udelay(ps->rst_dly);
+               rk3036_pll_wait_lock(hw);
+
+               /*return form slow*/
+               cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
+               loops_per_jiffy = ps->lpj;
+               local_irq_restore(flags);
+       } else {
+               /*FIXME*/
+               rk3036_pll_clk_get_set(parent_rate, rate, &refdiv, &fbdiv, &postdiv1, &postdiv2, &frac);
+               rk3036_pll_set_con(hw, refdiv, fbdiv, postdiv1, postdiv2, frac);
+       }
+       clk_debug("setting OK\n");
+
+       return 0;       
+}
+static const struct clk_ops clk_pll_ops_3036_apll = {
+       .recalc_rate = clk_pll_recalc_rate_3036_apll,
+       .round_rate = clk_pll_round_rate_3036_apll,
+       .set_rate = clk_pll_set_rate_3036_apll,
+};
+
+
+/* CLK_PLL_3036_plus_autotype ops */
+
+static long clk_pll_round_rate_3036plus_auto(struct clk_hw *hw, unsigned long rate,
+               unsigned long *prate)
+{
+       struct clk *parent = __clk_get_parent(hw->clk);
+
+       if (parent && (rate == __clk_get_rate(parent))) {
+               clk_debug("pll %s round rate=%lu equal to parent rate\n",
+                               __clk_get_name(hw->clk), rate);
+               return rate;
+       }
+
+       return (pll_com_get_best_set(rate, rk3036plus_pll_com_table)->rate);
+}
+
+static int clk_pll_set_rate_3036plus_auto(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct pll_clk_set *clk_set = (struct pll_clk_set *)(rk3036plus_pll_com_table);
+
+       clk_debug("******%s\n", __func__);
+       while (clk_set->rate) {
+               clk_debug("******%s clk_set->rate=%lu\n", __func__, clk_set->rate);
+               if (clk_set->rate == rate) {
+                       break;
+               }
+               clk_set++;
+       }
+       if (clk_set->rate == rate) {
+               rk3036_pll_clk_set_rate(clk_set, hw);
+       } else {
+               clk_debug("gpll is no corresponding rate=%lu\n", rate);
+               return -1;
+       }
+       clk_debug("******%s end\n", __func__);
+
+       return 0;       
+}
+
+static const struct clk_ops clk_pll_ops_3036plus_auto = {
+       .recalc_rate = clk_pll_recalc_rate_3036_apll,
+       .round_rate = clk_pll_round_rate_3036plus_auto,
+       .set_rate = clk_pll_set_rate_3036plus_auto,
+};
+
+static long clk_cpll_round_rate_312xplus(struct clk_hw *hw, unsigned long rate,
+               unsigned long *prate)
+{
+       unsigned long best;
+
+       for (best = rate; best > 0; best--) {
+               if (!pll_clk_get_best_set(*prate, best, NULL, NULL, NULL))
+                       return best;
+       }
+
+       return 0;
+}
+
+static int clk_cpll_set_rate_312xplus(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct pll_clk_set *clk_set = (struct pll_clk_set *)(rk312xplus_pll_com_table);
+       u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
+
+       while (clk_set->rate) {
+               if (clk_set->rate == rate) {
+                       break;
+               }
+               clk_set++;
+       }
+
+       if (clk_set->rate == rate) {
+               clk_debug("cpll get a rate\n");
+               rk3036_pll_clk_set_rate(clk_set, hw);
+
+       } else {
+               clk_debug("cpll get auto calc a rate\n");
+               if (rk3036_pll_clk_get_set(parent_rate, rate, &refdiv, &fbdiv, &postdiv1, &postdiv2, &frac) != 0) {
+                       pr_err("cpll auto set rate error\n");
+                       return -ENOENT;
+               }
+               clk_debug("%s get rate=%lu, refdiv=%u, fbdiv=%u, postdiv1=%u, postdiv2=%u",
+                               __func__, rate, refdiv, fbdiv, postdiv1, postdiv2);
+               rk3036_pll_set_con(hw, refdiv, fbdiv, postdiv1, postdiv2, frac);
+
+       }
+
+       clk_debug("setting OK\n");
+       return 0;
+}
+
+static const struct clk_ops clk_pll_ops_312xplus = {
+       .recalc_rate = clk_pll_recalc_rate_3036_apll,
+       .round_rate = clk_cpll_round_rate_312xplus,
+       .set_rate = clk_cpll_set_rate_312xplus,
+};
 
 const struct clk_ops *rk_get_pll_ops(u32 pll_flags)
 {
@@ -1370,6 +1792,15 @@ const struct clk_ops *rk_get_pll_ops(u32 pll_flags)
                case CLK_PLL_3188PLUS_AUTO:
                        return &clk_pll_ops_3188plus_auto;
 
+               case CLK_PLL_3036_APLL:
+                       return &clk_pll_ops_3036_apll;
+
+               case CLK_PLL_3036PLUS_AUTO:
+                       return &clk_pll_ops_3036plus_auto;
+
+               case CLK_PLL_312XPLUS:
+                       return &clk_pll_ops_312xplus;
+
                default:
                        clk_err("%s: unknown pll_flags!\n", __func__);
                        return NULL;
old mode 100644 (file)
new mode 100755 (executable)
index 2479cb4..df41b57
        .clksel1 = RK3288_CLK_L2RAM_DIV(l2_div) | RK3288_ATCLK_DIV(atclk_div) | RK3288_PCLK_DBG_DIV(pclk_dbg_div),\
        .lpj = (CLK_LOOPS_JIFFY_REF*_mhz) / CLK_LOOPS_RATE_REF,\
 }
+/***************************RK3036 PLL**************************************/
+#define LPJ_24M        (CLK_LOOPS_JIFFY_REF * 24) / CLK_LOOPS_RATE_REF
+/*PLL_CON 0,1,2*/
+#define RK3036_PLL_PWR_ON                      (0)
+#define RK3036_PLL_PWR_DN                      (1)
+#define RK3036_PLL_BYPASS                      (1 << 15)
+#define RK3036_PLL_NO_BYPASS                   (0 << 15)
+/*con0*/
+#define RK3036_PLL_BYPASS_SHIFT                (15)
+
+#define RK3036_PLL_POSTDIV1_MASK               (0x7)
+#define RK3036_PLL_POSTDIV1_SHIFT              (12)
+#define RK3036_PLL_FBDIV_MASK                  (0xfff)
+#define RK3036_PLL_FBDIV_SHIFT                 (0)
+
+/*con1*/
+#define RK3036_PLL_RSTMODE_SHIFT               (15)
+#define RK3036_PLL_RST_SHIFT                   (14)
+#define RK3036_PLL_PWR_DN_SHIFT                (13)
+#define RK3036_PLL_DSMPD_SHIFT                 (12)
+#define RK3036_PLL_LOCK_SHIFT                  (10)
+
+#define RK3036_PLL_POSTDIV2_MASK               (0x7)
+#define RK3036_PLL_POSTDIV2_SHIFT              (6)
+#define RK3036_PLL_REFDIV_MASK                 (0x3f)
+#define RK3036_PLL_REFDIV_SHIFT                (0)
+
+/*con2*/
+#define RK3036_PLL_FOUT4PHASE_PWR_DN_SHIFT     (27)
+#define RK3036_PLL_FOUTVCO_PWR_DN_SHIFT        (26)
+#define RK3036_PLL_FOUTPOSTDIV_PWR_DN_SHIFT    (25)
+#define RK3036_PLL_DAC_PWR_DN_SHIFT            (24)
+
+#define RK3036_PLL_FRAC_MASK                   (0xffffff)
+#define RK3036_PLL_FRAC_SHIFT                  (0)
+
+#define CRU_GET_REG_BIT_VAL(reg, bits_shift)           (((reg) >> (bits_shift)) & (0x1))
+#define CRU_GET_REG_BITS_VAL(reg, bits_shift, msk)     (((reg) >> (bits_shift)) & (msk))
+#define CRU_SET_BIT(val, bits_shift)                   (((val) & (0x1)) << (bits_shift))
+#define CRU_W_MSK(bits_shift, msk)                     ((msk) << ((bits_shift) + 16))
+
+#define CRU_W_MSK_SETBITS(val, bits_shift, msk)        (CRU_W_MSK(bits_shift, msk)     \
+                                                       | CRU_SET_BITS(val, bits_shift, msk))
+#define CRU_W_MSK_SETBIT(val, bits_shift)              (CRU_W_MSK(bits_shift, 0x1)     \
+                                                       | CRU_SET_BIT(val, bits_shift))
+
+#define RK3036_PLL_SET_REFDIV(val)                             CRU_W_MSK_SETBITS(val, RK3036_PLL_REFDIV_SHIFT, RK3036_PLL_REFDIV_MASK)
+#define RK3036_PLL_SET_FBDIV(val)                              CRU_W_MSK_SETBITS(val, RK3036_PLL_FBDIV_SHIFT, RK3036_PLL_FBDIV_MASK)
+#define RK3036_PLL_SET_POSTDIV1(val)                           CRU_W_MSK_SETBITS(val, RK3036_PLL_POSTDIV1_SHIFT, RK3036_PLL_POSTDIV1_MASK)
+#define RK3036_PLL_SET_POSTDIV2(val)                           CRU_W_MSK_SETBITS(val, RK3036_PLL_POSTDIV2_SHIFT, RK3036_PLL_POSTDIV2_MASK)
+#define RK3036_PLL_SET_FRAC(val)                               CRU_SET_BITS(val, RK3036_PLL_FRAC_SHIFT, RK3036_PLL_FRAC_MASK)
+
+#define RK3036_PLL_GET_REFDIV(reg)                             CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_REFDIV_SHIFT, RK3036_PLL_REFDIV_MASK)
+#define RK3036_PLL_GET_FBDIV(reg)                              CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_FBDIV_SHIFT, RK3036_PLL_FBDIV_MASK)
+#define RK3036_PLL_GET_POSTDIV1(reg)                           CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_POSTDIV1_SHIFT, RK3036_PLL_POSTDIV1_MASK)
+#define RK3036_PLL_GET_POSTDIV2(reg)                           CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_POSTDIV2_SHIFT, RK3036_PLL_POSTDIV2_MASK)
+#define RK3036_PLL_GET_FRAC(reg)                               CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_FRAC_SHIFT, RK3036_PLL_FRAC_MASK)
+
+/*#define APLL_SET_BYPASS(val)                         CRU_SET_BIT(val, PLL_BYPASS_SHIFT)*/
+#define RK3036_PLL_SET_DSMPD(val)                              CRU_W_MSK_SETBIT(val, RK3036_PLL_DSMPD_SHIFT)
+#define RK3036_PLL_GET_DSMPD(reg)                              CRU_GET_REG_BIT_VAL(reg, RK3036_PLL_DSMPD_SHIFT)
 
+/*******************CLKSEL0 BITS***************************/
+#define RK3036_CLK_SET_DIV_CON_SUB1(val, bits_shift, msk)      CRU_W_MSK_SETBITS((val - 1), bits_shift, msk)
+
+#define RK3036_CPU_CLK_PLL_SEL_SHIFT           (14)
+#define RK3036_CPU_CLK_PLL_SEL_MASK    (0x3)
+#define RK3036_CORE_CLK_PLL_SEL_SHIFT          (7)
+#define RK3036_SEL_APLL                        (0)
+#define RK3036_SEL_GPLL                        (1)
+#define RK3036_CPU_SEL_PLL(plls)               CRU_W_MSK_SETBITS(plls, RK3036_CPU_CLK_PLL_SEL_SHIFT, RK3036_CPU_CLK_PLL_SEL_MASK)
+#define RK3036_CORE_SEL_PLL(plls)              CRU_W_MSK_SETBIT(plls, RK3036_CORE_CLK_PLL_SEL_SHIFT)
+
+#define RK3036_ACLK_CPU_DIV_MASK               (0x1f)
+#define RK3036_ACLK_CPU_DIV_SHIFT              (8)
+#define RK3036_A9_CORE_DIV_MASK                (0x1f)
+#define RK3036_A9_CORE_DIV_SHIFT               (0)
+
+#define RATIO_11               (1)
+#define RATIO_21               (2)
+#define RATIO_41               (4)
+#define RATIO_81               (8)
+
+#define RK3036_ACLK_CPU_DIV(val)               RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_ACLK_CPU_DIV_SHIFT, RK3036_ACLK_CPU_DIV_MASK)
+#define RK3036_CLK_CORE_DIV(val)               RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_A9_CORE_DIV_SHIFT, RK3036_A9_CORE_DIV_MASK)
+/*******************CLKSEL1 BITS***************************/
+#define RK3036_PCLK_CPU_DIV_MASK               (0x7)
+#define RK3036_PCLK_CPU_DIV_SHIFT              (12)
+#define RK3036_HCLK_CPU_DIV_MASK               (0x3)
+#define RK3036_HCLK_CPU_DIV_SHIFT              (8)
+#define RK3036_ACLK_CORE_DIV_MASK              (0x7)
+#define RK3036_ACLK_CORE_DIV_SHIFT             (4)
+#define RK3036_CORE_PERIPH_DIV_MASK            (0xf)
+#define RK3036_CORE_PERIPH_DIV_SHIFT           (0)
+
+#define RK3036_PCLK_CPU_DIV(val)               RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_PCLK_CPU_DIV_SHIFT, RK3036_PCLK_CPU_DIV_MASK)
+#define RK3036_HCLK_CPU_DIV(val)               RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_HCLK_CPU_DIV_SHIFT, RK3036_HCLK_CPU_DIV_MASK)
+#define RK3036_ACLK_CORE_DIV(val)              RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_ACLK_CORE_DIV_SHIFT, RK3036_ACLK_CORE_DIV_MASK)
+#define RK3036_CLK_CORE_PERI_DIV(val)          RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_CORE_PERIPH_DIV_SHIFT, RK3036_CORE_PERIPH_DIV_MASK)
+
+/*******************clksel10***************************/
+#define RK3036_PERI_PLL_SEL_SHIFT      14
+#define RK3036_PERI_PLL_SEL_MASK       (0x3)
+#define RK3036_PERI_PCLK_DIV_MASK      (0x3)
+#define RK3036_PERI_PCLK_DIV_SHIFT     (12)
+#define RK3036_PERI_HCLK_DIV_MASK      (0x3)
+#define RK3036_PERI_HCLK_DIV_SHIFT     (8)
+#define RK3036_PERI_ACLK_DIV_MASK      (0x1f)
+#define RK3036_PERI_ACLK_DIV_SHIFT     (0)
+
+#define RK3036_SEL_3PLL_APLL           (0)
+#define RK3036_SEL_3PLL_DPLL           (1)
+#define RK3036_SEL_3PLL_GPLL           (2)
+
+
+#define RK3036_PERI_CLK_SEL_PLL(plls)  CRU_W_MSK_SETBITS(plls, RK3036_PERI_PLL_SEL_SHIFT, RK3036_PERI_PLL_SEL_MASK)
+#define RK3036_PERI_SET_ACLK_DIV(val)          RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_PERI_ACLK_DIV_SHIFT, RK3036_PERI_ACLK_DIV_MASK)
+
+/*******************gate BITS***************************/
+#define RK3036_CLK_GATE_CLKID_CONS(i)  RK3036_CRU_CLKGATES_CON((i) / 16)
+
+#define RK3036_CLK_GATE(i)             (1 << ((i)%16))
+#define RK3036_CLK_UN_GATE(i)          (0)
+
+#define RK3036_CLK_GATE_W_MSK(i)       (1 << (((i) % 16) + 16))
+#define RK3036_CLK_GATE_CLKID(i)       (16 * (i))
+
+#define _RK3036_APLL_SET_CLKS(_mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac, \
+               _periph_div, _aclk_core_div, _axi_div, _apb_div, _ahb_div) \
+{ \
+       .rate   = (_mhz) * MHZ, \
+       .pllcon0 = RK3036_PLL_SET_POSTDIV1(_postdiv1) | RK3036_PLL_SET_FBDIV(_fbdiv),   \
+       .pllcon1 = RK3036_PLL_SET_DSMPD(_dsmpd) | RK3036_PLL_SET_POSTDIV2(_postdiv2) | RK3036_PLL_SET_REFDIV(_refdiv),  \
+       .pllcon2 = RK3036_PLL_SET_FRAC(_frac),  \
+       .clksel1 = RK3036_ACLK_CORE_DIV(RATIO_##_aclk_core_div) | RK3036_CLK_CORE_PERI_DIV(RATIO_##_periph_div),        \
+       .lpj    = (CLK_LOOPS_JIFFY_REF * _mhz) / CLK_LOOPS_RATE_REF,    \
+       .rst_dly = 0,\
+}
+
+#define _RK3036_PLL_SET_CLKS(_mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac) \
+{ \
+       .rate   = (_mhz) * KHZ, \
+       .pllcon0 = RK3036_PLL_SET_POSTDIV1(_postdiv1) | RK3036_PLL_SET_FBDIV(_fbdiv),   \
+       .pllcon1 = RK3036_PLL_SET_DSMPD(_dsmpd) | RK3036_PLL_SET_POSTDIV2(_postdiv2) | RK3036_PLL_SET_REFDIV(_refdiv),  \
+       .pllcon2 = RK3036_PLL_SET_FRAC(_frac),  \
+}
 
 struct pll_clk_set {
        unsigned long   rate;
index 8327444b76cb58abaa0d22e9f6c3bf192f66fda0..19e77bb35e83fc0fe698d2b1fca7614311a22bd3 100644 (file)
@@ -104,6 +104,14 @@ config ARM_OMAP2PLUS_CPUFREQ
        default ARCH_OMAP2PLUS
        select CPU_FREQ_TABLE
 
+config ARM_ROCKCHIP_CPUFREQ
+       bool "CPUfreq driver for Rockchip CPUs"
+       depends on ARCH_ROCKCHIP
+       default y
+       help
+         This enables the CPUfreq driver for Rockchips CPUs.
+         If in doubt, say Y.
+
 config ARM_S3C2416_CPUFREQ
        bool "S3C2416 CPU Frequency scaling support"
        depends on CPU_S3C2416
index d1c5526cc548179601777f670550aa4e79835fdc..f8f6ea53427a698d3312f55559ff20aca43c6aa9 100644 (file)
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)   += omap-cpufreq.o
 obj-$(CONFIG_PXA25x)                   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA27x)                   += pxa2xx-cpufreq.o
 obj-$(CONFIG_PXA3xx)                   += pxa3xx-cpufreq.o
+obj-$(CONFIG_ARM_ROCKCHIP_CPUFREQ)     += rockchip-cpufreq.o
 obj-$(CONFIG_ARM_S3C2416_CPUFREQ)      += s3c2416-cpufreq.o
 obj-$(CONFIG_ARM_S3C64XX_CPUFREQ)      += s3c64xx-cpufreq.o
 obj-$(CONFIG_ARM_S5PV210_CPUFREQ)      += s5pv210-cpufreq.o
@@ -94,4 +95,3 @@ obj-$(CONFIG_SH_CPU_FREQ)             += sh-cpufreq.o
 obj-$(CONFIG_SPARC_US2E_CPUFREQ)       += sparc-us2e-cpufreq.o
 obj-$(CONFIG_SPARC_US3_CPUFREQ)                += sparc-us3-cpufreq.o
 obj-$(CONFIG_UNICORE32)                        += unicore2-cpufreq.o
-obj-$(CONFIG_ARCH_ROCKCHIP)            += rockchip-cpufreq.o
index 19c7e9a2659d23b7688ef78ca644b380a6cc3827..9de45d245a86fb1fb22a5914d49eb89c46edd5c6 100755 (executable)
@@ -15,3 +15,4 @@
 
 
 obj-$(CONFIG_MALI_MIDGARD) += midgard/
+obj-$(CONFIG_MALI400)      += mali400/
diff --git a/drivers/gpu/arm/mali400/Kbuild b/drivers/gpu/arm/mali400/Kbuild
new file mode 100644 (file)
index 0000000..9e361d3
--- /dev/null
@@ -0,0 +1 @@
+obj-y += mali/ ump/
diff --git a/drivers/gpu/arm/mali400/include/ump/ump.h b/drivers/gpu/arm/mali400/include/ump/ump.h
new file mode 100755 (executable)
index 0000000..ce593c7
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump.h
+ *
+ * This file contains the user space part of the UMP API.
+ */
+
+#ifndef _UNIFIED_MEMORY_PROVIDER_H_
+#define _UNIFIED_MEMORY_PROVIDER_H_
+
+
+/** @defgroup ump_user_space_api UMP User Space API
+ * @{ */
+
+
+#include "ump_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * External representation of a UMP handle in user space.
+ */
+typedef void *ump_handle;
+
+/**
+ * Typedef for a secure ID, a system wide identificator for UMP memory buffers.
+ */
+typedef unsigned int ump_secure_id;
+
+/**
+ * Value to indicate an invalid UMP memory handle.
+ */
+#define UMP_INVALID_MEMORY_HANDLE ((ump_handle)0)
+
+/**
+ * Value to indicate an invalid secure Id.
+ */
+#define UMP_INVALID_SECURE_ID     ((ump_secure_id)-1)
+
+/**
+ * UMP error codes for user space.
+ */
+typedef enum
+{
+       UMP_OK = 0, /**< indicates success */
+       UMP_ERROR,  /**< indicates failure */
+} ump_result;
+
+
+/**
+ * Opens and initializes the UMP library.
+ *
+ * This function must be called at least once before calling any other UMP API functions.
+ * Each open is reference counted and must be matched with a call to @ref ump_close "ump_close".
+ *
+ * @see ump_close
+ *
+ * @return UMP_OK indicates success, UMP_ERROR indicates failure.
+ */
+UMP_API_EXPORT ump_result ump_open(void);
+
+
+/**
+ * Terminate the UMP library.
+ *
+ * This must be called once for every successful @ref ump_open "ump_open". The UMP library is
+ * terminated when, and only when, the last open reference to the UMP interface is closed.
+ *
+ * @see ump_open
+ */
+UMP_API_EXPORT void ump_close(void);
+
+
+/**
+ * Retrieves the secure ID for the specified UMP memory.
+ *
+ * This identificator is unique across the entire system, and uniquely identifies
+ * the specified UMP memory. This identificator can later be used through the
+ * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" or
+ * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id"
+ * functions in order to access this UMP memory, for instance from another process.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_secure_id_get "ump_dd_secure_id_get"
+ *
+ * @see ump_handle_create_from_secure_id
+ * @see ump_dd_handle_create_from_secure_id
+ * @see ump_dd_secure_id_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return Returns the secure ID for the specified UMP memory.
+ */
+UMP_API_EXPORT ump_secure_id ump_secure_id_get(ump_handle mem);
+
+
+/**
+ * Retrieves a handle to allocated UMP memory.
+ *
+ * The usage of UMP memory is reference counted, so this will increment the reference
+ * count by one for the specified UMP memory.
+ * Use @ref ump_reference_release "ump_reference_release" when there is no longer any
+ * use for the retrieved handle.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id"
+ *
+ * @see ump_reference_release
+ * @see ump_dd_handle_create_from_secure_id
+ *
+ * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function.
+ *
+ * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned.
+ */
+UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id);
+
+
+/**
+ * Retrieves the actual size of the specified UMP memory.
+ *
+ * The size is reported in bytes, and is typically page aligned.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_size_get "ump_dd_size_get"
+ *
+ * @see ump_dd_size_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return Returns the allocated size of the specified UMP memory, in bytes.
+ */
+UMP_API_EXPORT unsigned long ump_size_get(ump_handle mem);
+
+
+/**
+ * Read from specified UMP memory.
+ *
+ * Another way of reading from (and writing to) UMP memory is to use the
+ * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve
+ * a CPU mapped pointer to the memory.
+ *
+ * @see ump_mapped_pointer_get
+ *
+ * @param dst Destination buffer.
+ * @param src Handle to UMP memory to read from.
+ * @param offset Where to start reading, given in bytes.
+ * @param length How much to read, given in bytes.
+ */
+UMP_API_EXPORT void ump_read(void *dst, ump_handle src, unsigned long offset, unsigned long length);
+
+
+/**
+ * Write to specified UMP memory.
+ *
+ * Another way of writing to (and reading from) UMP memory is to use the
+ * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve
+ * a CPU mapped pointer to the memory.
+ *
+ * @see ump_mapped_pointer_get
+ *
+ * @param dst Handle to UMP memory to write to.
+ * @param offset Where to start writing, given in bytes.
+ * @param src Buffer to read from.
+ * @param length How much to write, given in bytes.
+ */
+UMP_API_EXPORT void ump_write(ump_handle dst, unsigned long offset, const void *src, unsigned long length);
+
+
+/**
+ * Retrieves a memory mapped pointer to the specified UMP memory.
+ *
+ * This function retrieves a memory mapped pointer to the specified UMP memory,
+ * that can be used by the CPU. Every successful call to
+ * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" is reference counted,
+ * and must therefore be followed by a call to
+ * @ref ump_mapped_pointer_release "ump_mapped_pointer_release " when the
+ * memory mapping is no longer needed.
+ *
+ * @note Systems without a MMU for the CPU only return the physical address, because no mapping is required.
+ *
+ * @see ump_mapped_pointer_release
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return NULL indicates failure, otherwise a CPU mapped pointer is returned.
+ */
+UMP_API_EXPORT void *ump_mapped_pointer_get(ump_handle mem);
+
+
+/**
+ * Releases a previously mapped pointer to the specified UMP memory.
+ *
+ * The CPU mapping of the specified UMP memory memory is reference counted,
+ * so every call to @ref ump_mapped_pointer_get "ump_mapped_pointer_get" must
+ * be matched with a call to this function when the mapping is no longer needed.
+ *
+ * The CPU mapping is not removed before all references to the mapping is released.
+ *
+ * @note Systems without a MMU must still implement this function, even though no unmapping should be needed.
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_API_EXPORT void ump_mapped_pointer_release(ump_handle mem);
+
+
+/**
+ * Adds an extra reference to the specified UMP memory.
+ *
+ * This function adds an extra reference to the specified UMP memory. This function should
+ * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_handle
+ * variable. The function @ref ump_reference_release "ump_reference_release" must then be used
+ * to release each copy of the UMP memory handle.
+ *
+ * @note You are not required to call @ref ump_reference_add "ump_reference_add"
+ * for UMP handles returned from
+ * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id",
+ * because these handles are already reference counted by this function.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_reference_add "ump_dd_reference_add"
+ *
+ * @see ump_dd_reference_add
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_API_EXPORT void ump_reference_add(ump_handle mem);
+
+
+/**
+ * Releases a reference from the specified UMP memory.
+ *
+ * This function should be called once for every reference to the UMP memory handle.
+ * When the last reference is released, all resources associated with this UMP memory
+ * handle are freed.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_reference_release "ump_dd_reference_release"
+ *
+ * @see ump_dd_reference_release
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_API_EXPORT void ump_reference_release(ump_handle mem);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/** @} */ /* end group ump_user_space_api */
+
+
+#endif /*_UNIFIED_MEMORY_PROVIDER_H_ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_debug.h b/drivers/gpu/arm/mali400/include/ump/ump_debug.h
new file mode 100755 (executable)
index 0000000..c9d129c
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2005-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_debug.h
+ *
+ * The file include several useful macros for debugging and printing.
+ * - UMP_PRINTF(...)           Do not use this function: Will be included in Release builds.
+ * - UMP_DEBUG_TRACE()         Prints current location in code.
+ * - UMP_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=UMP_DEBUG_LEVEL.
+ * - UMP_DEBUG_TPRINT(nr, X )  Prints the source trace and second argument if nr<=UMP_DEBUG_LEVEL.
+ * - UMP_DEBUG_ERROR( (X) )    Prints an errortext, a source trace, and the given error message.
+ * - UMP_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit.
+ * - UMP_DEBUG_ASSERT_RANGE(x, min, max) Triggers if variable x is not between or equal to max and min.
+ * - UMP_DEBUG_ASSERT_LEQ(x, max) Triggers if variable x is not less than equal to max.
+ * - UMP_DEBUG_ASSERT_POINTER(pointer)  Triggers if the pointer is a zero pointer.
+ * - UMP_DEBUG_CODE( X )       The code inside the macro is only copiled in Debug builds.
+ *
+ * The (X) means that you must add an extra parantese around the argumentlist.
+ *
+ * The  printf function: UMP_PRINTF(...) is routed to _ump_sys_printf
+ *
+ * Suggested range for the DEBUG-LEVEL is [1:6] where
+ * [1:2] Is messages with highest priority, indicate possible errors.
+ * [3:4] Is messages with medium priority, output important variables.
+ * [5:6] Is messages with low priority, used during extensive debugging.
+ *
+ */
+#ifndef _UMP_DEBUG_H_
+#define _UMP_DEBUG_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* START: Configuration */
+#ifndef UMP_PRINTF
+#define UMP_PRINTF printf
+#endif /* UMP_PRINTF */
+
+#ifndef UMP_PRINT_FLUSH
+#define UMP_PRINT_FLUSH do {} while (0)
+#endif /* UMP_PRINT_FLUSH */
+
+#ifndef UMP_DEBUG_LEVEL
+#define UMP_DEBUG_LEVEL 1
+#endif /* UMP_DEBUG_LEVEL */
+
+#ifndef UMP_DEBUG_ERROR_START_MSG
+#define UMP_DEBUG_ERROR_START_MSG do {\
+               UMP_PRINTF("*********************************************************************\n");\
+               UMP_PRINT_FLUSH; } while (0)
+#endif /* UMP_DEBUG_ERROR_START_MSG */
+
+#ifndef UMP_DEBUG_ERROR_STOP_MSG
+#define UMP_DEBUG_ERROR_STOP_MSG  do { UMP_PRINTF("\n"); UMP_PRINT_FLUSH; } while (0)
+#endif /* UMP_DEBUG_ERROR_STOP_MSG */
+
+#ifndef UMP_ASSERT_QUIT_CMD
+#define UMP_ASSERT_QUIT_CMD    abort()
+#endif /* UMP_ASSERT_QUIT_CMD */
+/* STOP: Configuration */
+
+/**
+ *  The macro UMP_FUNCTION evaluates to the name of the function enclosing
+ *  this macro's usage, or "<unknown>" if not supported.
+ */
+#if (defined(__SYMBIAN32__) && defined(__ARMCC__)) || defined(_MSC_VER)
+#   define UMP_FUNCTION __FUNCTION__
+#elif __STDC__  && __STDC_VERSION__ >= 199901L
+#   define UMP_FUNCTION __FUNCTION__
+#elif defined(__GNUC__) && __GNUC__ >= 2
+#   define UMP_FUNCTION __FUNCTION__
+#elif defined(__func__)
+#   define UMP_FUNCTION __func__
+#else
+#   define UMP_FUNCTION "<unknown>"
+#endif
+
+/**
+ *  Explicitly ignore a parameter passed into a function, to suppress compiler warnings.
+ *  Should only be used with parameter names.
+ */
+#define UMP_IGNORE(x) (void)x
+
+/**
+ * @def     UMP_DEBUG_TRACE()
+ * @brief   Prints current location in code.
+ *          Can be turned off by defining UMP_DEBUG_SKIP_TRACE
+ */
+
+#ifndef UMP_DEBUG_SKIP_TRACE
+#ifndef UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME
+#define UMP_DEBUG_TRACE()  do { UMP_PRINTF( "In file: "__FILE__ \
+               "  function: %s()   line:%4d\n" , UMP_FUNCTION, __LINE__);  UMP_PRINT_FLUSH; } while (0)
+#else
+#define UMP_DEBUG_TRACE()  do { UMP_PRINTF( "In file: "__FILE__ "  line:%4d\n" , __LINE__);  UMP_PRINT_FLUSH; } while (0)
+#endif /* UMP_DEBUG_SKIP_PRINT_FUNCTION_NAME */
+#else
+#define UMP_DEBUG_TRACE()
+#endif /* UMP_DEBUG_SKIP_TRACE */
+
+/**
+ * @def     UMP_DEBUG_PRINT(nr, (X) )
+ * @brief   Prints the second argument if nr<=UMP_DEBUG_LEVEL.
+ *          Can be turned off by defining UMP_DEBUG_SKIP_PRINT
+ * @param   nr   If nr <= UMP_DEBUG_LEVEL, we print the text.
+ * @param   X  A parantese with the contents to be sent to UMP_PRINTF
+ */
+#ifndef UMP_DEBUG_SKIP_PRINT
+#define UMP_DEBUG_PRINT(nr, X )  do { if ( nr<=UMP_DEBUG_LEVEL ) { UMP_PRINTF X ; UMP_PRINT_FLUSH; } } while (0)
+#else
+#define UMP_DEBUG_PRINT(nr, X )
+#endif /* UMP_DEBUG_SKIP_PRINT */
+
+/**
+ * @def     UMP_DEBUG_TPRINT(nr, (X) )
+ * @brief   Prints the second argument if nr<=UMP_DEBUG_LEVEL.
+ *          Can be turned off by defining UMP_DEBUG_SKIP_TPRINT.
+ *          Can be shortened by defining UMP_DEBUG_TPRINT_SKIP_FUNCTION.
+ * @param   nr   If nr <= UMP_DEBUG_LEVEL, we print the text.
+ * @param   X  A parantese with the contents to be sent to UMP_PRINTF
+ */
+
+/* helper to handle if the function name should be included or not */
+#ifndef UMP_DEBUG_TPRINT_SKIP_FUNCTION
+#define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__" %s()%4d " , UMP_FUNCTION, __LINE__); UMP_PRINT_FLUSH; }  while (0)
+#else
+#define UMP_DEBUG_TPRINT_INTERN do {UMP_PRINTF( ""__FILE__ "%4d " , __LINE__); UMP_PRINT_FLUSH; }  while (0)
+#endif /* UMP_DEBUG_TPRINT_SKIP_FUNCTION */
+
+#ifndef UMP_DEBUG_SKIP_TPRINT
+#define UMP_DEBUG_TPRINT(nr, X ) \
+       do{\
+               if ( nr<=UMP_DEBUG_LEVEL )\
+               {\
+                       UMP_DEBUG_TPRINT_INTERN;\
+                       UMP_PRINTF X ;\
+                       UMP_PRINT_FLUSH;\
+               }\
+       } while (0)
+#else
+#define UMP_DEBUG_TPRINT(nr, X )
+#endif /* UMP_DEBUG_SKIP_TPRINT */
+
+/**
+ * @def     UMP_DEBUG_ERROR( (X) )
+ * @brief   Prints an errortext, a source Trace, and the given error message.
+ *          Prints filename, function, linenr, and the given error message.
+ *          The error message must be inside a second parantese.
+ *          The error message is written on a separate line, and a NL char is added.
+ *          Can be turned of by defining UMP_DEBUG_SKIP_ERROR;
+ *          You do not need to type the words ERROR in the message, since it will
+ *          be added anyway.
+ *
+ * @note    You should not end the text with a newline, since it is added by the macro.
+ * @note    You should not write "ERROR" in the text, since it is added by the macro.
+ * @param    X  A parantese with the contents to be sent to UMP_PRINTF
+ */
+
+#ifndef UMP_DEBUG_SKIP_ERROR
+#define UMP_DEBUG_ERROR( X )  \
+       do{ \
+               UMP_DEBUG_ERROR_START_MSG;\
+               UMP_PRINTF("ERROR: ");\
+               UMP_PRINT_FLUSH;\
+               UMP_DEBUG_TRACE(); \
+               UMP_PRINTF X ; \
+               UMP_PRINT_FLUSH;\
+               UMP_DEBUG_ERROR_STOP_MSG;\
+       } while (0)
+#else
+#define UMP_DEBUG_ERROR( X ) do{ ; } while ( 0 )
+#endif /* UMP_DEBUG_SKIP_ERROR */
+
+/**
+ * @def     UMP_DEBUG_ASSERT(expr, (X) )
+ * @brief   If the asserted expr is false, the program will exit.
+ *          Prints filename, function, linenr, and the given error message.
+ *          The error message must be inside a second parantese.
+ *          The error message is written on a separate line, and a NL char is added.
+ *          Can be turned of by defining UMP_DEBUG_SKIP_ERROR;
+ *          You do not need to type the words ASSERT in the message, since it will
+ *          be added anyway.
+ *
+ * @param    X  A parantese with the contents to be sent to UMP_PRINTF
+ *          Prints filename, function, linenr, and the error message
+ *          on a separte line. A newline char is added at the end.
+ *          Can be turned of by defining UMP_DEBUG_SKIP_ASSERT
+ * @param   expr  Will exit program if \a expr is false;
+ * @param   (X)  Text that will be written if the assertion toggles.
+ */
+
+#ifndef UMP_DEBUG_SKIP_ASSERT
+#define UMP_DEBUG_ASSERT(expr, X ) \
+       do{\
+               if ( !(expr) ) \
+               { \
+                       UMP_DEBUG_ERROR_START_MSG;\
+                       UMP_PRINTF("ASSERT EXIT: ");\
+                       UMP_PRINT_FLUSH;\
+                       UMP_DEBUG_TRACE(); \
+                       UMP_PRINTF X ; \
+                       UMP_PRINT_FLUSH;\
+                       UMP_DEBUG_ERROR_STOP_MSG;\
+                       UMP_ASSERT_QUIT_CMD;\
+               }\
+       } while (0)
+#else
+#define UMP_DEBUG_ASSERT(expr, X)
+#endif /* UMP_DEBUG_SKIP_ASSERT */
+
+
+/**
+ * @def     UMP_DEBUG_ASSERT_POINTER(pointer)
+ * @brief   If the asserted pointer is NULL, the program terminates and TRACE info is printed
+ *          The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
+ */
+#define UMP_DEBUG_ASSERT_POINTER(pointer) UMP_DEBUG_ASSERT(pointer, ("Null pointer " #pointer) )
+
+/**
+ * @def     UMP_DEBUG_ASSERT_HANDLE(handle)
+ * @brief   If the asserted handle is not a valid handle, the program terminates and TRACE info is printed
+ *          The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
+ */
+#define UMP_DEBUG_ASSERT_HANDLE(handle) UMP_DEBUG_ASSERT(UMP_NO_HANDLE != (handle), ("Invalid handle" #handle) )
+
+/**
+ * @def     UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align)
+ * @brief   If the asserted pointer is  not aligned to align, the program terminates with trace info printed.
+ *          The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
+ */
+#ifndef UMP_DEBUG_SKIP_ASSERT
+#define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align) do {                                                    \
+               UMP_DEBUG_ASSERT(0 == (align & (align - 1)), ("align %d is not a power-of-two", align));           \
+               UMP_DEBUG_ASSERT(0 == (((u32)(ptr)) & (align - 1)), ("ptr %p not aligned to %d bytes", (void*)ptr, align)); \
+       } while (0)
+#else
+#define UMP_DEBUG_ASSERT_ALIGNMENT(ptr, align)
+#endif /* UMP_DEBUG_SKIP_ASSERT */
+
+/**
+ * @def     UMP_DEBUG_ASSERT_RANGE(x,min,max)
+ * @brief   If variable x is not between or equal to max and min, the assertion triggers.
+ *          The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
+ */
+#define UMP_DEBUG_ASSERT_RANGE(x, min, max) \
+       UMP_DEBUG_ASSERT( (x) >= (min) && (x) <= (max), \
+                         (#x " out of range (%2.2f)", (double)x ) \
+                       )
+
+/**
+ * @def     UMP_DEBUG_ASSERT_LEQ(x,max)
+ * @brief   If variable x is less than or equal to max, the assertion triggers.
+ *          The checking is disabled if "UMP_DEBUG_SKIP_ASSERT" is defined.
+ */
+#define UMP_DEBUG_ASSERT_LEQ(x, max) \
+       UMP_DEBUG_ASSERT( (x) <= (max), \
+                         (#x " out of range (%2.2f)", (double)x ) \
+                       )
+
+/**
+ * @def     UMP_DEBUG_CODE( X )
+ * @brief   Run the code X on debug builds.
+ *          The code will not be used if UMP_DEBUG_SKIP_CODE is defined .
+ *
+ */
+#ifdef UMP_DEBUG_SKIP_CODE
+#define UMP_DEBUG_CODE( X )
+#else
+#define UMP_DEBUG_CODE( X ) X
+#endif /* UMP_DEBUG_SKIP_CODE */
+
+#endif /* _UMP_DEBUG_H_ */
+
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h b/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface.h
new file mode 100755 (executable)
index 0000000..ad2e0fc
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_interface.h
+ *
+ * This file contains the kernel space part of the UMP API.
+ */
+
+#ifndef __UMP_KERNEL_INTERFACE_H__
+#define __UMP_KERNEL_INTERFACE_H__
+
+
+/** @defgroup ump_kernel_space_api UMP Kernel Space API
+ * @{ */
+
+
+#include "ump_kernel_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * External representation of a UMP handle in kernel space.
+ */
+typedef void *ump_dd_handle;
+
+/**
+ * Typedef for a secure ID, a system wide identificator for UMP memory buffers.
+ */
+typedef unsigned int ump_secure_id;
+
+
+/**
+ * Value to indicate an invalid UMP memory handle.
+ */
+#define UMP_DD_HANDLE_INVALID ((ump_dd_handle)0)
+
+
+/**
+ * Value to indicate an invalid secure Id.
+ */
+#define UMP_INVALID_SECURE_ID ((ump_secure_id)-1)
+
+
+/**
+ * UMP error codes for kernel space.
+ */
+typedef enum
+{
+       UMP_DD_SUCCESS, /**< indicates success */
+       UMP_DD_INVALID, /**< indicates failure */
+} ump_dd_status_code;
+
+
+/**
+ * Struct used to describe a physical block used by UMP memory
+ */
+typedef struct ump_dd_physical_block
+{
+       unsigned long addr; /**< The physical address of the block */
+       unsigned long size; /**< The length of the block, typically page aligned */
+} ump_dd_physical_block;
+
+
+/**
+ * Retrieves the secure ID for the specified UMP memory.
+ *
+ * This identificator is unique across the entire system, and uniquely identifies
+ * the specified UMP memory. This identificator can later be used through the
+ * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id" or
+ * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id"
+ * functions in order to access this UMP memory, for instance from another process.
+ *
+ * @note There is a user space equivalent function called @ref ump_secure_id_get "ump_secure_id_get"
+ *
+ * @see ump_dd_handle_create_from_secure_id
+ * @see ump_handle_create_from_secure_id
+ * @see ump_secure_id_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return Returns the secure ID for the specified UMP memory.
+ */
+UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle mem);
+
+
+/**
+ * Retrieves a handle to allocated UMP memory.
+ *
+ * The usage of UMP memory is reference counted, so this will increment the reference
+ * count by one for the specified UMP memory.
+ * Use @ref ump_dd_reference_release "ump_dd_reference_release" when there is no longer any
+ * use for the retrieved handle.
+ *
+ * @note There is a user space equivalent function called @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id"
+ *
+ * @see ump_dd_reference_release
+ * @see ump_handle_create_from_secure_id
+ *
+ * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function.
+ *
+ * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned.
+ */
+UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id);
+
+
+/**
+ * Retrieves the number of physical blocks used by the specified UMP memory.
+ *
+ * This function retrieves the number of @ref ump_dd_physical_block "ump_dd_physical_block" structs needed
+ * to describe the physical memory layout of the given UMP memory. This can later be used when calling
+ * the functions @ref ump_dd_phys_blocks_get "ump_dd_phys_blocks_get" and
+ * @ref ump_dd_phys_block_get "ump_dd_phys_block_get".
+ *
+ * @see ump_dd_phys_blocks_get
+ * @see ump_dd_phys_block_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return The number of ump_dd_physical_block structs required to describe the physical memory layout of the specified UMP memory.
+ */
+UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle mem);
+
+
+/**
+ * Retrieves all physical memory block information for specified UMP memory.
+ *
+ * This function can be used by other device drivers in order to create MMU tables.
+ *
+ * @note This function will fail if the num_blocks parameter is either to large or to small.
+ *
+ * @see ump_dd_phys_block_get
+ *
+ * @param mem Handle to UMP memory.
+ * @param blocks An array of @ref ump_dd_physical_block "ump_dd_physical_block" structs that will receive the physical description.
+ * @param num_blocks The number of blocks to return in the blocks array. Use the function
+ *                   @ref ump_dd_phys_block_count_get "ump_dd_phys_block_count_get" first to determine the number of blocks required.
+ *
+ * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure.
+ */
+UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle mem, ump_dd_physical_block *blocks, unsigned long num_blocks);
+
+
+/**
+ * Retrieves the physical memory block information for specified block for the specified UMP memory.
+ *
+ * This function can be used by other device drivers in order to create MMU tables.
+ *
+ * @note This function will return UMP_DD_INVALID if the specified index is out of range.
+ *
+ * @see ump_dd_phys_blocks_get
+ *
+ * @param mem Handle to UMP memory.
+ * @param index Which physical info block to retrieve.
+ * @param block Pointer to a @ref ump_dd_physical_block "ump_dd_physical_block" struct which will receive the requested information.
+ *
+ * @return UMP_DD_SUCCESS indicates success, UMP_DD_INVALID indicates failure.
+ */
+UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle mem, unsigned long index, ump_dd_physical_block *block);
+
+
+/**
+ * Retrieves the actual size of the specified UMP memory.
+ *
+ * The size is reported in bytes, and is typically page aligned.
+ *
+ * @note There is a user space equivalent function called @ref ump_size_get "ump_size_get"
+ *
+ * @see ump_size_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return Returns the allocated size of the specified UMP memory, in bytes.
+ */
+UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle mem);
+
+
+/**
+ * Adds an extra reference to the specified UMP memory.
+ *
+ * This function adds an extra reference to the specified UMP memory. This function should
+ * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_dd_handle
+ * variable. The function @ref ump_dd_reference_release "ump_dd_reference_release" must then be used
+ * to release each copy of the UMP memory handle.
+ *
+ * @note You are not required to call @ref ump_dd_reference_add "ump_dd_reference_add"
+ * for UMP handles returned from
+ * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id",
+ * because these handles are already reference counted by this function.
+ *
+ * @note There is a user space equivalent function called @ref ump_reference_add "ump_reference_add"
+ *
+ * @see ump_reference_add
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle mem);
+
+
+/**
+ * Releases a reference from the specified UMP memory.
+ *
+ * This function should be called once for every reference to the UMP memory handle.
+ * When the last reference is released, all resources associated with this UMP memory
+ * handle are freed.
+ *
+ * @note There is a user space equivalent function called @ref ump_reference_release "ump_reference_release"
+ *
+ * @see ump_reference_release
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle mem);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/** @} */ /* end group ump_kernel_space_api */
+
+
+#endif  /* __UMP_KERNEL_INTERFACE_H__ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h b/drivers/gpu/arm/mali400/include/ump/ump_kernel_interface_ref_drv.h
new file mode 100755 (executable)
index 0000000..ca3f9ac
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_interface.h
+ */
+
+#ifndef __UMP_KERNEL_INTERFACE_REF_DRV_H__
+#define __UMP_KERNEL_INTERFACE_REF_DRV_H__
+
+#include "ump_kernel_interface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Turn specified physical memory into UMP memory. */
+UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block *blocks, unsigned long num_blocks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __UMP_KERNEL_INTERFACE_REF_DRV_H__ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h b/drivers/gpu/arm/mali400/include/ump/ump_kernel_platform.h
new file mode 100755 (executable)
index 0000000..ed9ed33
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_platform.h
+ *
+ * This file should define UMP_KERNEL_API_EXPORT,
+ * which dictates how the UMP kernel API should be exported/imported.
+ * Modify this file, if needed, to match your platform setup.
+ */
+
+#ifndef __UMP_KERNEL_PLATFORM_H__
+#define __UMP_KERNEL_PLATFORM_H__
+
+/** @addtogroup ump_kernel_space_api
+ * @{ */
+
+/**
+ * A define which controls how UMP kernel space API functions are imported and exported.
+ * This define should be set by the implementor of the UMP API.
+ */
+
+#if defined(_WIN32)
+
+#if defined(UMP_BUILDING_UMP_LIBRARY)
+#define UMP_KERNEL_API_EXPORT __declspec(dllexport)
+#else
+#define UMP_KERNEL_API_EXPORT __declspec(dllimport)
+#endif
+
+#else
+
+#define UMP_KERNEL_API_EXPORT
+
+#endif
+
+
+/** @} */ /* end group ump_kernel_space_api */
+
+
+#endif /* __UMP_KERNEL_PLATFORM_H__ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_osu.h b/drivers/gpu/arm/mali400/include/ump/ump_osu.h
new file mode 100755 (executable)
index 0000000..f656313
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_osu.h
+ * Defines the OS abstraction layer for the base driver
+ */
+
+#ifndef __UMP_OSU_H__
+#define __UMP_OSU_H__
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef unsigned int u32;
+#ifdef _MSC_VER
+typedef unsigned __int64        u64;
+typedef signed   __int64        s64;
+#else
+typedef unsigned long long      u64;
+typedef signed long long        s64;
+#endif
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+typedef unsigned long ump_bool;
+
+#ifndef UMP_TRUE
+#define UMP_TRUE ((ump_bool)1)
+#endif
+
+#ifndef UMP_FALSE
+#define UMP_FALSE ((ump_bool)0)
+#endif
+
+#define UMP_STATIC          static
+
+/**
+ * @addtogroup ump_user_space_api Unified Device Driver (UDD) APIs used by UMP
+ *
+ * @{
+ */
+
+/**
+ * @defgroup ump_osuapi UDD OS Abstraction for User-side (OSU) APIs for UMP
+ *
+ * @{
+ */
+
+/* The following is necessary to prevent the _ump_osk_errcode_t doxygen from
+ * becoming unreadable: */
+/** @cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */
+
+/**
+ * @brief OSU/OSK Error codes.
+ *
+ * Each OS may use its own set of error codes, and may require that the
+ * User/Kernel interface take certain error code. This means that the common
+ * error codes need to be sufficiently rich to pass the correct error code
+ * through from the OSK/OSU to U/K layer, across all OSs.
+ *
+ * The result is that some error codes will appear redundant on some OSs.
+ * Under all OSs, the OSK/OSU layer must translate native OS error codes to
+ * _ump_osk/u_errcode_t codes. Similarly, the U/K layer must translate from
+ * _ump_osk/u_errcode_t codes to native OS error codes.
+ *
+ */
+typedef enum
+{
+       _UMP_OSK_ERR_OK = 0,              /**< Success. */
+       _UMP_OSK_ERR_FAULT = -1,          /**< General non-success */
+       _UMP_OSK_ERR_INVALID_FUNC = -2,   /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */
+       _UMP_OSK_ERR_INVALID_ARGS = -3,   /**< Invalid arguments passed through User/Kernel interface */
+       _UMP_OSK_ERR_NOMEM = -4,          /**< Insufficient memory */
+       _UMP_OSK_ERR_TIMEOUT = -5,        /**< Timeout occured */
+       _UMP_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */
+       _UMP_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */
+       _UMP_OSK_ERR_BUSY = -8,           /**< Device/operation is busy. Try again later */
+       _UMP_OSK_ERR_UNSUPPORTED = -9,  /**< Optional part of the interface used, and is unsupported */
+} _ump_osk_errcode_t;
+
+/** @endcond */ /* end cond OSU_COPY_OF__UMP_OSU_ERRCODE_T */
+
+/**
+ * @brief OSU Error codes.
+ *
+ * OSU error codes - enum values intentionally same as OSK
+ */
+typedef enum
+{
+       _UMP_OSU_ERR_OK = 0,           /**< Success. */
+       _UMP_OSU_ERR_FAULT = -1,       /**< General non-success */
+       _UMP_OSU_ERR_TIMEOUT = -2,     /**< Timeout occured */
+} _ump_osu_errcode_t;
+
+/** @brief Translate OSU error code to base driver error code.
+ *
+ * The _UMP_OSU_TRANSLATE_ERROR macro translates an OSU error code to the
+ * error codes in use by the base driver.
+ */
+#define _UMP_OSU_TRANSLATE_ERROR(_ump_osu_errcode) ( ( _UMP_OSU_ERR_OK == (_ump_osu_errcode) ) ? UMP_ERR_NO_ERROR : UMP_ERR_FUNCTION_FAILED)
+
+/** @defgroup _ump_osu_lock OSU Mutual Exclusion Locks
+  * @{ */
+
+/** @brief OSU Mutual Exclusion Lock flags type.
+ *
+ * This is made to look like and function identically to the OSK locks (refer
+ * to \ref _ump_osk_lock). However, please note the following \b important
+ * differences:
+ * - the OSU default lock is a Sleeping, non-interruptible mutex.
+ * - the OSU adds the ANYUNLOCK type of lock which allows a thread which doesn't
+ * own the lock to release the lock.
+ * - the order parameter when creating a lock is currently unused
+ *
+ * @note Pay careful attention to the difference in default locks for OSU and
+ * OSK locks; OSU locks are always non-interruptible, but OSK locks are by
+ * default, interruptible. This has implications for systems that do not
+ * distinguish between user and kernel mode.
+ */
+typedef enum
+{
+       _UMP_OSU_LOCKFLAG_DEFAULT = 0, /**< Default lock type. */
+       /** @enum _ump_osu_lock_flags_t
+        *
+        * Flags from 0x0--0x8000 are RESERVED for Kernel-mode
+        */
+       _UMP_OSU_LOCKFLAG_ANYUNLOCK = 0x10000, /**< Mutex that guarantees that any thread can unlock it when locked. Otherwise, this will not be possible. */
+       /** @enum _ump_osu_lock_flags_t
+        *
+        * Flags from 0x10000 are RESERVED for User-mode
+        */
+       _UMP_OSU_LOCKFLAG_STATIC = 0x20000, /* Flag in OSU reserved range to identify lock as a statically initialized lock */
+
+} _ump_osu_lock_flags_t;
+
+typedef enum
+{
+       _UMP_OSU_LOCKMODE_UNDEF = -1,  /**< Undefined lock mode. For internal use only */
+       _UMP_OSU_LOCKMODE_RW    = 0x0, /**< Default. Lock is used to protect data that is read from and written to */
+       /** @enum _ump_osu_lock_mode_t
+        *
+        * Lock modes 0x1--0x3F are RESERVED for Kernel-mode */
+} _ump_osu_lock_mode_t;
+
+/** @brief Private type for Mutual Exclusion lock objects. */
+typedef struct _ump_osu_lock_t_struct _ump_osu_lock_t;
+
+/** @brief The number of static locks supported in _ump_osu_lock_static(). */
+#define UMP_OSU_STATIC_LOCK_COUNT (sizeof(_ump_osu_static_locks) / sizeof(_ump_osu_lock_t))
+
+/** @} */ /* end group _ump_osu_lock */
+
+/** @defgroup _ump_osu_memory OSU Memory Allocation
+ * @{ */
+
+/** @brief Allocate zero-initialized memory.
+ *
+ * Returns a buffer capable of containing at least \a n elements of \a size
+ * bytes each. The buffer is initialized to zero.
+ *
+ * The buffer is suitably aligned for storage and subsequent access of every
+ * type that the compiler supports. Therefore, the pointer to the start of the
+ * buffer may be cast into any pointer type, and be subsequently accessed from
+ * such a pointer, without loss of information.
+ *
+ * When the buffer is no longer in use, it must be freed with _ump_osu_free().
+ * Failure to do so will cause a memory leak.
+ *
+ * @note Most toolchains supply memory allocation functions that meet the
+ * compiler's alignment requirements.
+ *
+ * @param n Number of elements to allocate
+ * @param size Size of each element
+ * @return On success, the zero-initialized buffer allocated. NULL on failure
+ */
+void *_ump_osu_calloc(u32 n, u32 size);
+
+/** @brief Allocate memory.
+ *
+ * Returns a buffer capable of containing at least \a size bytes. The
+ * contents of the buffer are undefined.
+ *
+ * The buffer is suitably aligned for storage and subsequent access of every
+ * type that the compiler supports. Therefore, the pointer to the start of the
+ * buffer may be cast into any pointer type, and be subsequently accessed from
+ * such a pointer, without loss of information.
+ *
+ * When the buffer is no longer in use, it must be freed with _ump_osu_free().
+ * Failure to do so will cause a memory leak.
+ *
+ * @note Most toolchains supply memory allocation functions that meet the
+ * compiler's alignment requirements.
+ *
+ * Remember to free memory using _ump_osu_free().
+ * @param size Number of bytes to allocate
+ * @return On success, the buffer allocated. NULL on failure.
+ */
+void *_ump_osu_malloc(u32 size);
+
+/** @brief Free memory.
+ *
+ * Reclaims the buffer pointed to by the parameter \a ptr for the system.
+ * All memory returned from _ump_osu_malloc(), _ump_osu_calloc() and
+ * _ump_osu_realloc() must be freed before the application exits. Otherwise,
+ * a memory leak will occur.
+ *
+ * Memory must be freed once. It is an error to free the same non-NULL pointer
+ * more than once.
+ *
+ * It is legal to free the NULL pointer.
+ *
+ * @param ptr Pointer to buffer to free
+ */
+void _ump_osu_free(void *ptr);
+
+/** @brief Copies memory.
+ *
+ * Copies the \a len bytes from the buffer pointed by the parameter \a src
+ * directly to the buffer pointed by \a dst.
+ *
+ * It is an error for \a src to overlap \a dst anywhere in \a len bytes.
+ *
+ * @param dst Pointer to the destination array where the content is to be
+ * copied.
+ * @param src Pointer to the source of data to be copied.
+ * @param len Number of bytes to copy.
+ * @return \a dst is always passed through unmodified.
+ */
+void *_ump_osu_memcpy(void *dst, const void *src, u32   len);
+
+/** @brief Fills memory.
+ *
+ * Sets the first \a size bytes of the block of memory pointed to by \a ptr to
+ * the specified value
+ * @param ptr Pointer to the block of memory to fill.
+ * @param chr Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB)
+ * are used.
+ * @param size Number of bytes to be set to the value.
+ * @return \a ptr is always passed through unmodified
+ */
+void *_ump_osu_memset(void *ptr, u32 chr, u32 size);
+
+/** @} */ /* end group _ump_osu_memory */
+
+
+/** @addtogroup _ump_osu_lock
+ * @{ */
+
+/** @brief Initialize a Mutual Exclusion Lock.
+ *
+ * Locks are created in the signalled (unlocked) state.
+ *
+ * The parameter \a initial must be zero.
+ *
+ * At present, the parameter \a order must be zero. It remains for future
+ * expansion for mutex order checking.
+ *
+ * @param flags flags combined with bitwise OR ('|'), or zero. There are
+ * restrictions on which flags can be combined, see \ref _ump_osu_lock_flags_t.
+ * @param initial For future expansion into semaphores. SBZ.
+ * @param order The locking order of the mutex. SBZ.
+ * @return On success, a pointer to a \ref _ump_osu_lock_t object. NULL on failure.
+ */
+_ump_osu_lock_t *_ump_osu_lock_init(_ump_osu_lock_flags_t flags, u32 initial, u32 order);
+
+/** @brief Obtain a statically initialized Mutual Exclusion Lock.
+ *
+ * Retrieves a reference to a statically initialized lock. Up to
+ * _UMP_OSU_STATIC_LOCK_COUNT statically initialized locks are
+ * available. Only _ump_osu_lock_wait(), _ump_osu_lock_trywait(),
+ * _ump_osu_lock_signal() can be used with statically initialized locks.
+ * _UMP_OSU_LOCKMODE_RW mode should be used when waiting and signalling
+ * statically initialized locks.
+ *
+ * For the same \a nr a pointer to the same statically initialized lock is
+ * returned. That is, given the following code:
+ * @code
+ *  extern u32 n;
+ *
+ *  _ump_osu_lock_t *locka = _ump_osu_lock_static(n);
+ *  _ump_osu_lock_t *lockb = _ump_osu_lock_static(n);
+ * @endcode
+ * Then (locka == lockb), for all 0 <= n < UMP_OSU_STATIC_LOCK_COUNT.
+ *
+ * @param nr index of a statically initialized lock [0..UMP_OSU_STATIC_LOCK_COUNT-1]
+ * @return On success, a pointer to a _ump_osu_lock_t object. NULL on failure.
+ */
+_ump_osu_lock_t *_ump_osu_lock_static(u32 nr);
+
+/** @brief Initialize a Mutual Exclusion Lock safely across multiple threads.
+ *
+ * The _ump_osu_lock_auto_init() function guarantees that the given lock will
+ * be initialized once and precisely once, even in a situation involving
+ * multiple threads.
+ *
+ * This is necessary because the first call to certain Public API functions must
+ * initialize the API. However, there can be a race involved to call the first
+ * library function in multi-threaded applications. To resolve this race, a
+ * mutex can be used. This mutex must be initialized, but initialized only once
+ * by any thread that might compete for its initialization. This function
+ * guarantees the initialization to happen correctly, even when there is an
+ * initialization race between multiple threads.
+ *
+ * Otherwise, the operation is identical to the _ump_osu_lock_init() function.
+ * For more details, refer to _ump_osu_lock_init().
+ *
+ * @param pplock pointer to storage for a _ump_osu_lock_t pointer. This
+ * _ump_osu_lock_t pointer may point to a _ump_osu_lock_t that has been
+ * initialized already
+ * @param flags flags combined with bitwise OR ('|'), or zero. There are
+ * restrictions on which flags can be combined. Refer to
+ * \ref _ump_osu_lock_flags_t for more information.
+ * The absence of any flags (the value 0) results in a sleeping-mutex,
+ * which is non-interruptible.
+ * @param initial For future expansion into semaphores. SBZ.
+ * @param order The locking order of the mutex. SBZ.
+ * @return On success, _UMP_OSU_ERR_OK is returned and a pointer to an
+ * initialized \ref _ump_osu_lock_t object is written into \a *pplock.
+ * _UMP_OSU_ERR_FAULT is returned on failure.
+ */
+_ump_osu_errcode_t _ump_osu_lock_auto_init(_ump_osu_lock_t **pplock, _ump_osu_lock_flags_t flags, u32 initial, u32 order);
+
+/** @brief Wait for a lock to be signalled (obtained).
+ *
+ * After a thread has successfully waited on the lock, the lock is obtained by
+ * the thread, and is marked as unsignalled. The thread releases the lock by
+ * signalling it.
+ *
+ * To prevent deadlock, locks must always be obtained in the same order.
+ *
+ * @param lock the lock to wait upon (obtain).
+ * @param mode the mode in which the lock should be obtained. Currently this
+ * must be _UMP_OSU_LOCKMODE_RW.
+ * @return On success, _UMP_OSU_ERR_OK, _UMP_OSU_ERR_FAULT on error.
+ */
+_ump_osu_errcode_t _ump_osu_lock_wait(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode);
+
+/** @brief Wait for a lock to be signalled (obtained) with timeout
+ *
+ * After a thread has successfully waited on the lock, the lock is obtained by
+ * the thread, and is marked as unsignalled. The thread releases the lock by
+ * signalling it.
+ *
+ * To prevent deadlock, locks must always be obtained in the same order.
+ *
+ * This version can return early if it cannot obtain the lock within the given timeout.
+ *
+ * @param lock the lock to wait upon (obtain).
+ * @param mode the mode in which the lock should be obtained. Currently this
+ * must be _UMP_OSU_LOCKMODE_RW.
+ * @param timeout Relative time in microseconds for the timeout
+ * @return _UMP_OSU_ERR_OK if the lock was obtained, _UMP_OSU_ERR_TIMEOUT if the timeout expired or  _UMP_OSU_ERR_FAULT on error.
+ */
+_ump_osu_errcode_t _ump_osu_lock_timed_wait(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode, u64 timeout);
+
+/** @brief Test for a lock to be signalled and obtains the lock when so.
+ *
+ * Obtains the lock only when it is in signalled state. The lock is then
+ * marked as unsignalled. The lock is released again by signalling
+ * it by _ump_osu_lock_signal().
+ *
+ * If the lock could not be obtained immediately (that is, another thread
+ * currently holds the lock), then this function \b does \b not wait for the
+ * lock to be in a signalled state. Instead, an error code is immediately
+ * returned to indicate that the thread could not obtain the lock.
+ *
+ * To prevent deadlock, locks must always be obtained in the same order.
+ *
+ * @param lock the lock to wait upon (obtain).
+ * @param mode the mode in which the lock should be obtained. Currently this
+ * must be _UMP_OSU_LOCKMODE_RW.
+ * @return When the lock was obtained, _UMP_OSU_ERR_OK. If the lock could not
+ * be obtained, _UMP_OSU_ERR_FAULT.
+ */
+_ump_osu_errcode_t _ump_osu_lock_trywait(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode);
+
+/** @brief Signal (release) a lock.
+ *
+ * Locks may only be signalled by the thread that originally waited upon the
+ * lock, unless the lock was created using the _UMP_OSU_LOCKFLAG_ANYUNLOCK flag.
+ *
+ * @param lock the lock to signal (release).
+ * @param mode the mode in which the lock should be obtained. This must match
+ * the mode in which the lock was waited upon.
+ */
+void _ump_osu_lock_signal(_ump_osu_lock_t *lock, _ump_osu_lock_mode_t mode);
+
+/** @brief Terminate a lock.
+ *
+ * This terminates a lock and frees all associated resources.
+ *
+ * It is a programming error to terminate the lock when it is held (unsignalled)
+ * by a thread.
+ *
+ * @param lock the lock to terminate.
+ */
+void _ump_osu_lock_term(_ump_osu_lock_t *lock);
+/** @} */ /* end group _ump_osu_lock */
+
+/** @} */ /* end group osuapi */
+
+/** @} */ /* end group uddapi */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_OSU_H__ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_platform.h b/drivers/gpu/arm/mali400/include/ump/ump_platform.h
new file mode 100755 (executable)
index 0000000..6560fb7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_platform.h
+ *
+ * This file should define UMP_API_EXPORT,
+ * which dictates how the UMP user space API should be exported/imported.
+ * Modify this file, if needed, to match your platform setup.
+ */
+
+#ifndef __UMP_PLATFORM_H__
+#define __UMP_PLATFORM_H__
+
+/** @addtogroup ump_user_space_api
+ * @{ */
+
+/**
+ * A define which controls how UMP user space API functions are imported and exported.
+ * This define should be set by the implementor of the UMP API.
+ */
+#if defined(_WIN32)
+
+#define UMP_API_EXPORT
+
+#elif defined(__SYMBIAN32__)
+
+#define UMP_API_EXPORT IMPORT_C
+
+#else
+
+#if defined(__GNUC__)
+#if __GNUC__ >= 4
+#   define MALI_VISIBLE  __attribute__ ((visibility ("default")))       /**< Function should be visible from outside the dll */
+#else
+#   define MALI_VISIBLE
+#endif
+
+#elif defined(__ARMCC_VERSION)
+/* ARMCC specific */
+#   define MALI_VISIBLE  __declspec(dllexport)
+
+#else
+#   define MALI_VISIBLE
+
+#endif
+
+#define UMP_API_EXPORT MALI_VISIBLE
+
+#endif
+
+/** @} */ /* end group ump_user_space_api */
+
+
+#endif /* __UMP_PLATFORM_H__ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h b/drivers/gpu/arm/mali400/include/ump/ump_ref_drv.h
new file mode 100755 (executable)
index 0000000..c1c0965
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ref_drv.h
+ *
+ * Reference driver extensions to the UMP user space API for allocating UMP memory
+ */
+
+#ifndef _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_
+#define _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_
+
+#include "ump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+       /* This enum must match with the IOCTL enum in ump_ioctl.h */
+       UMP_REF_DRV_CONSTRAINT_NONE = 0,
+       UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1,
+       UMP_REF_DRV_CONSTRAINT_USE_CACHE = 4,
+       UMP_REF_DRV_CONSTRAINT_PRE_RESERVE = 8,
+} ump_alloc_constraints;
+
+/** Allocate an UMP handle containing a memory buffer.
+ * Input: Size: The minimum size for the allocation.
+ * Usage: If this is UMP_REF_DRV_CONSTRAINT_USE_CACHE, the allocation is mapped as cached by the cpu.
+ *        If it is UMP_REF_DRV_CONSTRAINT_NONE it is mapped as noncached.
+ *        The flag UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR is not supported.*/
+UMP_API_EXPORT ump_handle ump_ref_drv_allocate(unsigned long size, ump_alloc_constraints usage);
+
+UMP_API_EXPORT int ump_phy_addr_get(ump_handle memh);
+
+typedef enum
+{
+       UMP_MSYNC_CLEAN = 0 ,
+       UMP_MSYNC_CLEAN_AND_INVALIDATE = 1,
+       UMP_MSYNC_INVALIDATE = 2,
+       UMP_MSYNC_READOUT_CACHE_ENABLED = 128,
+} ump_cpu_msync_op;
+
+typedef enum
+{
+       UMP_READ = 1,
+       UMP_READ_WRITE = 3,
+} ump_lock_usage;
+
+/** Flushing cache for an ump_handle.
+ * The function will always CLEAN_AND_INVALIDATE as long as the \a op is not UMP_MSYNC_READOUT_CACHE_ENABLED.
+ * If so it will only report back if the given ump_handle is cacheable.
+ * At the momement the implementation does not use \a address or \a size.
+ * Return value is 1 if cache is enabled, and 0 if it is disabled for the given allocation.*/
+UMP_API_EXPORT int ump_cpu_msync_now(ump_handle mem, ump_cpu_msync_op op, void *address, int size);
+
+
+typedef enum
+{
+       UMP_USED_BY_CPU = 0,
+       UMP_USED_BY_MALI = 1,
+       UMP_USED_BY_UNKNOWN_DEVICE = 100,
+} ump_hw_usage;
+
+typedef enum
+{
+       UMP_CACHE_OP_START = 0,
+       UMP_CACHE_OP_FINISH  = 1,
+} ump_cache_op_control;
+
+/** Cache operation control. Tell when cache maintenance operations start and end.
+This will allow the kernel to merge cache operations togheter, thus making them faster */
+UMP_API_EXPORT int ump_cache_operations_control(ump_cache_op_control op);
+
+/** Memory synchronization - cache flushing if previous user was different hardware */
+UMP_API_EXPORT int ump_switch_hw_usage(ump_handle mem, ump_hw_usage new_user);
+
+/** Memory synchronization - cache flushing if previous user was different hardware */
+UMP_API_EXPORT int ump_switch_hw_usage_secure_id(ump_secure_id ump_id, ump_hw_usage new_user);
+
+/** Locking buffer. Blocking call if the buffer is already locked. */
+UMP_API_EXPORT int ump_lock(ump_handle mem, ump_lock_usage lock_usage);
+
+/** Locking buffer. Blocking call if the buffer is already locked. */
+UMP_API_EXPORT int ump_lock_secure_id(ump_secure_id ump_id, ump_lock_usage lock_usage);
+
+/** Unlocking buffer. Let other users lock the buffer for their usage */
+UMP_API_EXPORT int ump_unlock(ump_handle mem);
+
+/** Unlocking buffer. Let other users lock the buffer for their usage */
+UMP_API_EXPORT int ump_unlock_secure_id(ump_secure_id ump_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ */
diff --git a/drivers/gpu/arm/mali400/include/ump/ump_uk_types.h b/drivers/gpu/arm/mali400/include/ump/ump_uk_types.h
new file mode 100755 (executable)
index 0000000..8db8d55
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_uk_types.h
+ * Defines the types and constants used in the user-kernel interface
+ */
+
+#ifndef __UMP_UK_TYPES_H__
+#define __UMP_UK_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Helpers for API version handling */
+#define MAKE_VERSION_ID(x) (((x) << 16UL) | (x))
+#define IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF))
+#define GET_VERSION(x) (((x) >> 16UL) & 0xFFFF)
+#define IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y))))
+
+/**
+ * API version define.
+ * Indicates the version of the kernel API
+ * The version is a 16bit integer incremented on each API change.
+ * The 16bit integer is stored twice in a 32bit integer
+ * So for version 1 the value would be 0x00010001
+ */
+#define UMP_IOCTL_API_VERSION MAKE_VERSION_ID(2)
+
+typedef enum
+{
+       _UMP_IOC_QUERY_API_VERSION = 1,
+       _UMP_IOC_ALLOCATE,
+       _UMP_IOC_RELEASE,
+       _UMP_IOC_SIZE_GET,
+       _UMP_IOC_MAP_MEM,    /* not used in Linux */
+       _UMP_IOC_UNMAP_MEM,  /* not used in Linux */
+       _UMP_IOC_MSYNC,
+       _UMP_IOC_CACHE_OPERATIONS_CONTROL,
+       _UMP_IOC_SWITCH_HW_USAGE,
+       _UMP_IOC_LOCK,
+       _UMP_IOC_UNLOCK,
+}_ump_uk_functions;
+
+typedef enum
+{
+       UMP_REF_DRV_UK_CONSTRAINT_NONE = 0,
+       UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR = 1,
+       UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE = 4,
+       UMP_REF_DRV_UK_CONSTRAINT_PRE_RESERVE = 8,
+       UMP_REF_DRV_UK_CONSTRAINT_MEM_SWITCH = 16,
+} ump_uk_alloc_constraints;
+
+typedef enum
+{
+       _UMP_UK_MSYNC_CLEAN = 0,
+       _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1,
+       _UMP_UK_MSYNC_INVALIDATE = 2,
+       _UMP_UK_MSYNC_FLUSH_L1   = 3,
+       _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128,
+} ump_uk_msync_op;
+
+typedef enum
+{
+       _UMP_UK_CACHE_OP_START = 0,
+       _UMP_UK_CACHE_OP_FINISH  = 1,
+} ump_uk_cache_op_control;
+
+typedef enum
+{
+       _UMP_UK_READ = 1,
+       _UMP_UK_READ_WRITE = 3,
+} ump_uk_lock_usage;
+
+typedef enum
+{
+       _UMP_UK_USED_BY_CPU = 0,
+       _UMP_UK_USED_BY_MALI = 1,
+       _UMP_UK_USED_BY_UNKNOWN_DEVICE = 100,
+} ump_uk_user;
+
+/**
+ * Get API version ([in,out] u32 api_version, [out] u32 compatible)
+ */
+typedef struct _ump_uk_api_version_s
+{
+       void *ctx;      /**< [in,out] user-kernel context (trashed on output) */
+       u32 version;    /**< Set to the user space version on entry, stores the device driver version on exit */
+       u32 compatible; /**< Non-null if the device is compatible with the client */
+} _ump_uk_api_version_s;
+
+/**
+ * ALLOCATE ([out] u32 secure_id, [in,out] u32 size,  [in] contraints)
+ */
+typedef struct _ump_uk_allocate_s
+{
+       void *ctx;                              /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;                          /**< Return value from DD to Userdriver */
+       u32 size;                               /**< Input and output. Requested size; input. Returned size; output */
+       ump_uk_alloc_constraints constraints;   /**< Only input to Devicedriver */
+} _ump_uk_allocate_s;
+
+/**
+ * SIZE_GET ([in] u32 secure_id, [out]size )
+ */
+typedef struct _ump_uk_size_get_s
+{
+       void *ctx;                              /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;                          /**< Input to DD */
+       u32 size;                               /**< Returned size; output */
+} _ump_uk_size_get_s;
+
+/**
+ * Release ([in] u32 secure_id)
+ */
+typedef struct _ump_uk_release_s
+{
+       void *ctx;                              /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;                          /**< Input to DD */
+} _ump_uk_release_s;
+
+typedef struct _ump_uk_map_mem_s
+{
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       void *mapping;                  /**< [out] Returns user-space virtual address for the mapping */
+       void *phys_addr;                /**< [in] physical address */
+       unsigned long size;             /**< [in] size */
+       u32 secure_id;                  /**< [in] secure_id to assign to mapping */
+       void *_ukk_private;             /**< Only used inside linux port between kernel frontend and common part to store vma */
+       u32 cookie;
+       u32 is_cached;            /**< [in,out] caching of CPU mappings */
+} _ump_uk_map_mem_s;
+
+typedef struct _ump_uk_unmap_mem_s
+{
+       void *ctx;            /**< [in,out] user-kernel context (trashed on output) */
+       void *mapping;
+       u32 size;
+       void *_ukk_private;
+       u32 cookie;
+} _ump_uk_unmap_mem_s;
+
+typedef struct _ump_uk_msync_s
+{
+       void *ctx;            /**< [in,out] user-kernel context (trashed on output) */
+       void *mapping;        /**< [in] mapping addr */
+       void *address;        /**< [in] flush start addr */
+       u32 size;             /**< [in] size to flush */
+       ump_uk_msync_op op;   /**< [in] flush operation */
+       u32 cookie;           /**< [in] cookie stored with reference to the kernel mapping internals */
+       u32 secure_id;        /**< [in] secure_id that identifies the ump buffer */
+       u32 is_cached;        /**< [out] caching of CPU mappings */
+} _ump_uk_msync_s;
+
+typedef struct _ump_uk_cache_operations_control_s
+{
+       void *ctx;                   /**< [in,out] user-kernel context (trashed on output) */
+       ump_uk_cache_op_control op;  /**< [in] cache operations start/stop */
+} _ump_uk_cache_operations_control_s;
+
+
+typedef struct _ump_uk_switch_hw_usage_s
+{
+       void *ctx;            /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;        /**< [in] secure_id that identifies the ump buffer */
+       ump_uk_user new_user;         /**< [in] cookie stored with reference to the kernel mapping internals */
+
+} _ump_uk_switch_hw_usage_s;
+
+typedef struct _ump_uk_lock_s
+{
+       void *ctx;            /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;        /**< [in] secure_id that identifies the ump buffer */
+       ump_uk_lock_usage lock_usage;
+} _ump_uk_lock_s;
+
+typedef struct _ump_uk_unlock_s
+{
+       void *ctx;            /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;        /**< [in] secure_id that identifies the ump buffer */
+} _ump_uk_unlock_s;
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_UK_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/Kbuild b/drivers/gpu/arm/mali400/mali/Kbuild
new file mode 100755 (executable)
index 0000000..44b0161
--- /dev/null
@@ -0,0 +1,229 @@
+#
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2007-2011 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
+#
+
+# This file is called by the Linux build system.
+
+# set up defaults if not defined by the user
+USING_UMP ?= 1
+USING_OS_MEMORY ?= 1
+USING_MALI_PMU ?= 0
+TIMESTAMP ?= default
+OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16
+USING_GPU_UTILIZATION ?= 1
+PROFILING_SKIP_PP_JOBS ?= 0
+PROFILING_SKIP_PP_AND_GP_JOBS ?= 0
+TARGET_PLATFORM ?= rk30
+MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0
+MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0
+MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0
+MALI_UPPER_HALF_SCHEDULING ?= 1
+MALI_ENABLE_CPU_CYCLES ?= 0
+
+MALI_PLATFORM ?=rk30
+
+# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases:
+# The ARM proprietary product will only include the license/proprietary directory
+# The GPL product will only include the license/gpl directory
+ifeq ($(wildcard $(src)/linux/license/gpl/*),)
+    ccflags-y += -I$(src)/linux/license/proprietary
+    ifeq ($(CONFIG_MALI400_PROFILING),y)
+        $(error Profiling is incompatible with non-GPL license)
+    endif
+    ifeq ($(CONFIG_PM_RUNTIME),y)
+        $(error Runtime PM is incompatible with non-GPL license)
+    endif
+    ifeq ($(CONFIG_DMA_SHARED_BUFFER),y)
+        $(error DMA-BUF is incompatible with non-GPL license)
+    endif
+    $(error Linux Device integration is incompatible with non-GPL license)
+else
+    ccflags-y += -I$(src)/linux/license/gpl
+endif
+
+ccflags-y += -I$(srctree)/drivers/staging/android
+
+ifneq ($(MALI_PLATFORM),)
+EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1
+#MALI_PLATFORM_FILES = $(wildcard platform/$(MALI_PLATFORM)/*.c)
+mali-y += \
+       platform/$(MALI_PLATFORM)/mali_platform.o \
+       platform/$(MALI_PLATFORM)/rk3066.o
+endif
+
+
+mali-y += \
+       linux/mali_osk_atomics.o \
+       linux/mali_osk_irq.o \
+       linux/mali_osk_wq.o \
+       linux/mali_osk_locks.o \
+       linux/mali_osk_wait_queue.o \
+       linux/mali_osk_low_level_mem.o \
+       linux/mali_osk_math.o \
+       linux/mali_osk_memory.o \
+       linux/mali_osk_misc.o \
+       linux/mali_osk_mali.o \
+       linux/mali_osk_notification.o \
+       linux/mali_osk_time.o \
+       linux/mali_osk_timers.o
+
+mali-y += linux/mali_memory.o linux/mali_memory_os_alloc.o
+mali-y += linux/mali_memory_external.o
+mali-y += linux/mali_memory_block_alloc.o
+
+mali-y += \
+       linux/mali_ukk_mem.o \
+       linux/mali_ukk_gp.o \
+       linux/mali_ukk_pp.o \
+       linux/mali_ukk_core.o \
+       linux/mali_ukk_soft_job.o \
+       linux/mali_ukk_timeline.o
+
+# Source files which always are included in a build
+mali-y += \
+       common/mali_kernel_core.o \
+       linux/mali_kernel_linux.o \
+       common/mali_kernel_descriptor_mapping.o \
+       common/mali_session.o \
+       linux/mali_device_pause_resume.o \
+       common/mali_kernel_vsync.o \
+       linux/mali_ukk_vsync.o \
+       linux/mali_kernel_sysfs.o \
+       common/mali_mmu.o \
+       common/mali_mmu_page_directory.o \
+       common/mali_mem_validation.o \
+       common/mali_hw_core.o \
+       common/mali_gp.o \
+       common/mali_pp.o \
+       common/mali_pp_job.o \
+       common/mali_gp_job.o \
+       common/mali_soft_job.o \
+       common/mali_scheduler.o \
+       common/mali_gp_scheduler.o \
+       common/mali_pp_scheduler.o \
+       common/mali_group.o \
+       common/mali_dlbu.o \
+       common/mali_broadcast.o \
+       common/mali_pm.o \
+       common/mali_pmu.o \
+       common/mali_user_settings_db.o \
+       common/mali_kernel_utilization.o \
+       common/mali_l2_cache.o \
+       common/mali_dma.o \
+       common/mali_timeline.o \
+       common/mali_timeline_fence_wait.o \
+       common/mali_timeline_sync_fence.o \
+       common/mali_spinlock_reentrant.o \
+       common/mali_pm_domain.o \
+       linux/mali_osk_pm.o \
+       linux/mali_pmu_power_up_down.o \
+       __malidrv_build_info.o
+
+ifneq ($(MALI_PLATFORM_FILES),)
+       mali-y += $(MALI_PLATFORM_FILES:.c=.o)
+endif
+
+mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o
+mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o
+
+mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o
+ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP)
+
+mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_dma_buf.o
+mali-$(CONFIG_SYNC) += linux/mali_sync.o
+
+mali-$(CONFIG_MALI400_UMP) += linux/mali_memory_ump.o
+
+mali-$(CONFIG_MALI400_POWER_PERFORMANCE_POLICY) += common/mali_power_performance_policy.o
+
+# Tell the Linux build system from which .o file to create the kernel module
+obj-$(CONFIG_MALI400) := mali.o
+
+ccflags-y += $(EXTRA_DEFINES)
+
+# Set up our defines, which will be passed to gcc
+ccflags-y += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS)
+ccflags-y += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS)
+
+ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP)
+ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED)
+ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS)
+ccflags-y += -DMALI_STATE_TRACKING=1
+ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
+ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION)
+ccflags-y += -DMALI_ENABLE_CPU_CYCLES=$(MALI_ENABLE_CPU_CYCLES)
+
+ifeq ($(MALI_UPPER_HALF_SCHEDULING),1)
+       ccflags-y += -DMALI_UPPER_HALF_SCHEDULING
+endif
+
+ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../include/ump
+ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG
+
+# Use our defines when compiling
+ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform
+
+# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available
+MALI_RELEASE_NAME=$(shell cat $(src)/.version 2> /dev/null)
+
+SVN_INFO = (cd $(src); svn info 2>/dev/null)
+
+ifneq ($(shell $(SVN_INFO) 2>/dev/null),)
+# SVN detected
+SVN_REV := $(shell $(SVN_INFO) | grep '^Revision: '| sed -e 's/^Revision: //' 2>/dev/null)
+DRIVER_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV)
+CHANGE_DATE := $(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-)
+CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-)
+REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-)
+
+else # SVN
+GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null)
+ifneq ($(GIT_REV),)
+# Git detected
+DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV)
+CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci")
+CHANGED_REVISION := $(GIT_REV)
+REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null)
+
+else # Git
+# No Git or SVN detected
+DRIVER_REV := $(MALI_RELEASE_NAME)
+CHANGE_DATE := $(MALI_RELEASE_NAME)
+CHANGED_REVISION := $(MALI_RELEASE_NAME)
+endif
+endif
+
+ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\"
+
+VERSION_STRINGS :=
+VERSION_STRINGS += API_VERSION=$(shell cd $(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 )
+VERSION_STRINGS += REPO_URL=$(REPO_URL)
+VERSION_STRINGS += REVISION=$(DRIVER_REV)
+VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION)
+VERSION_STRINGS += CHANGE_DATE=$(CHANGE_DATE)
+VERSION_STRINGS += BUILD_DATE=$(shell date)
+ifdef CONFIG_MALI400_DEBUG
+VERSION_STRINGS += BUILD=debug
+else
+VERSION_STRINGS += BUILD=release
+endif
+VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM)
+VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM)
+VERSION_STRINGS += KDIR=$(KDIR)
+VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
+VERSION_STRINGS += USING_UMP=$(CONFIG_MALI400_UMP)
+VERSION_STRINGS += USING_PROFILING=$(CONFIG_MALI400_PROFILING)
+VERSION_STRINGS += USING_INTERNAL_PROFILING=$(CONFIG_MALI400_INTERNAL_PROFILING)
+VERSION_STRINGS += USING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION)
+VERSION_STRINGS += USING_POWER_PERFORMANCE_POLICY=$(CONFIG_POWER_PERFORMANCE_POLICY)
+VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING)
+
+# Create file with Mali driver configuration
+$(src)/__malidrv_build_info.c:
+       @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(src)/__malidrv_build_info.c
diff --git a/drivers/gpu/arm/mali400/mali/Kconfig b/drivers/gpu/arm/mali400/mali/Kconfig
new file mode 100755 (executable)
index 0000000..477e6b6
--- /dev/null
@@ -0,0 +1,81 @@
+config MALI400
+       tristate "Mali-300/400/450 support"
+       depends on ARM
+       select DMA_SHARED_BUFFER
+       ---help---
+         This enables support for the ARM Mali-300, Mali-400, and Mali-450
+         GPUs.
+
+         To compile this driver as a module, choose M here: the module will be
+         called mali.
+
+config MALI450
+       bool "Enable Mali-450 support"
+       depends on MALI400
+       ---help---
+         This enables support for Mali-450 specific features.
+
+config MALI400_DEBUG
+       bool "Enable debug in Mali driver"
+       depends on MALI400
+       ---help---
+         This enabled extra debug checks and messages in the Mali driver.
+
+config MALI400_PROFILING
+       bool "Enable Mali profiling"
+       depends on MALI400
+       select TRACEPOINTS
+       default y
+       ---help---
+         This enables gator profiling of Mali GPU events.
+
+config MALI400_INTERNAL_PROFILING
+       bool "Enable internal Mali profiling API"
+       depends on MALI400_PROFILING
+       default n
+       ---help---
+         This enables the internal legacy Mali profiling API.
+
+config MALI400_UMP
+       bool "Enable UMP support"
+       depends on MALI400
+       ---help---
+         This enables support for the UMP memory sharing API in the Mali driver.
+
+config MALI400_POWER_PERFORMANCE_POLICY
+       bool "Enable Mali power performance policy"
+       depends on ARM
+       default n
+       ---help---
+         This enables support for dynamic performance scaling of Mali with the goal of lowering power consumption.
+
+config MALI_DMA_BUF_MAP_ON_ATTACH
+       bool "Map dma-buf attachments on attach"
+       depends on MALI400 && DMA_SHARED_BUFFER
+       default y
+       ---help---
+         This makes the Mali driver map dma-buf attachments after doing
+         attach. If this is not set the dma-buf attachments will be mapped for
+         every time the GPU need to access the buffer.
+
+         Mapping for each access can cause lower performance.
+
+config MALI_SHARED_INTERRUPTS
+       bool "Support for shared interrupts"
+       depends on MALI400
+       default n
+       ---help---
+         Adds functionality required to properly support shared interrupts.  Without this support,
+         the device driver will fail during insmod if it detects shared interrupts.  This also
+         works when the GPU is not using shared interrupts, but might have a slight performance
+         impact.
+
+config MALI_PMU_PARALLEL_POWER_UP
+       bool "Power up Mali PMU domains in parallel"
+       depends on MALI400
+       default n
+       ---help---
+         This makes the Mali driver power up all PMU power domains in parallel, instead of
+         powering up domains one by one, with a slight delay in between. Powering on all power
+         domains at the same time may cause peak currents higher than what some systems can handle.
+         These systems must not enable this option.
diff --git a/drivers/gpu/arm/mali400/mali/__malidrv_build_info.c b/drivers/gpu/arm/mali400/mali/__malidrv_build_info.c
new file mode 100644 (file)
index 0000000..769a384
--- /dev/null
@@ -0,0 +1 @@
+const char *__malidrv_build_info(void) { return "malidrv:  API_VERSION=401 REPO_URL=heads/develop-3.10-next REVISION=r4p0-00rel0-lsk-android-14.05-18365-g3172295 CHANGED_REVISION=lsk-android-14.05-18365-g3172295 CHANGE_DATE=2014-06-26 20:38:04 +0800 BUILD_DATE=2014年 06月 30日 星期一 12:43:13 CST BUILD=debug TARGET_PLATFORM=rk30 MALI_PLATFORM= KDIR= OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=16 USING_UMP=y USING_PROFILING= USING_INTERNAL_PROFILING= USING_GPU_UTILIZATION=1 USING_POWER_PERFORMANCE_POLICY= MALI_UPPER_HALF_SCHEDULING=1";}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_broadcast.c b/drivers/gpu/arm/mali400/mali/common/mali_broadcast.c
new file mode 100755 (executable)
index 0000000..c8f4887
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_broadcast.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+static const int bcast_unit_reg_size = 0x1000;
+static const int bcast_unit_addr_broadcast_mask = 0x0;
+static const int bcast_unit_addr_irq_override_mask = 0x4;
+
+struct mali_bcast_unit {
+       struct mali_hw_core hw_core;
+       u32 current_mask;
+};
+
+struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t *resource)
+{
+       struct mali_bcast_unit *bcast_unit = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(resource);
+       MALI_DEBUG_PRINT(2, ("Mali Broadcast unit: Creating Mali Broadcast unit: %s\n", resource->description));
+
+       bcast_unit = _mali_osk_malloc(sizeof(struct mali_bcast_unit));
+       if (NULL == bcast_unit) {
+               MALI_PRINT_ERROR(("Mali Broadcast unit: Failed to allocate memory for Broadcast unit\n"));
+               return NULL;
+       }
+
+       if (_MALI_OSK_ERR_OK == mali_hw_core_create(&bcast_unit->hw_core, resource, bcast_unit_reg_size)) {
+               bcast_unit->current_mask = 0;
+               mali_bcast_reset(bcast_unit);
+
+               return bcast_unit;
+       } else {
+               MALI_PRINT_ERROR(("Mali Broadcast unit: Failed map broadcast unit\n"));
+       }
+
+       _mali_osk_free(bcast_unit);
+
+       return NULL;
+}
+
+void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit)
+{
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+
+       mali_hw_core_delete(&bcast_unit->hw_core);
+       _mali_osk_free(bcast_unit);
+}
+
+void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group)
+{
+       u32 bcast_id;
+       u32 broadcast_mask;
+
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group));
+
+       broadcast_mask = bcast_unit->current_mask;
+
+       broadcast_mask |= (bcast_id); /* add PP core to broadcast */
+       broadcast_mask |= (bcast_id << 16); /* add MMU to broadcast */
+
+       /* store mask so we can restore on reset */
+       bcast_unit->current_mask = broadcast_mask;
+}
+
+void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group)
+{
+       u32 bcast_id;
+       u32 broadcast_mask;
+
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group));
+
+       broadcast_mask = bcast_unit->current_mask;
+
+       broadcast_mask &= ~((bcast_id << 16) | bcast_id);
+
+       /* store mask so we can restore on reset */
+       bcast_unit->current_mask = broadcast_mask;
+}
+
+void mali_bcast_reset(struct mali_bcast_unit *bcast_unit)
+{
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+
+       /* set broadcast mask */
+       mali_hw_core_register_write(&bcast_unit->hw_core,
+                                   bcast_unit_addr_broadcast_mask,
+                                   bcast_unit->current_mask);
+
+       /* set IRQ override mask */
+       mali_hw_core_register_write(&bcast_unit->hw_core,
+                                   bcast_unit_addr_irq_override_mask,
+                                   bcast_unit->current_mask & 0xFF);
+}
+
+void mali_bcast_disable(struct mali_bcast_unit *bcast_unit)
+{
+       MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+
+       /* set broadcast mask */
+       mali_hw_core_register_write(&bcast_unit->hw_core,
+                                   bcast_unit_addr_broadcast_mask,
+                                   0x0);
+
+       /* set IRQ override mask */
+       mali_hw_core_register_write(&bcast_unit->hw_core,
+                                   bcast_unit_addr_irq_override_mask,
+                                   0x0);
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_broadcast.h b/drivers/gpu/arm/mali400/mali/common/mali_broadcast.h
new file mode 100755 (executable)
index 0000000..472d9bc
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/*
+ *  Interface for the broadcast unit on Mali-450.
+ *
+ * - Represents up to 8 × (MMU + PP) pairs.
+ * - Supports dynamically changing which (MMU + PP) pairs receive the broadcast by
+ *   setting a mask.
+ */
+
+#include "mali_hw_core.h"
+#include "mali_group.h"
+
+struct mali_bcast_unit;
+
+struct mali_bcast_unit *mali_bcast_unit_create(const _mali_osk_resource_t *resource);
+void mali_bcast_unit_delete(struct mali_bcast_unit *bcast_unit);
+
+/* Add a group to the list of (MMU + PP) pairs broadcasts go out to. */
+void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group);
+
+/* Remove a group to the list of (MMU + PP) pairs broadcasts go out to. */
+void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group);
+
+/* Re-set cached mask. This needs to be called after having been suspended. */
+void mali_bcast_reset(struct mali_bcast_unit *bcast_unit);
+
+/**
+ * Disable broadcast unit
+ *
+ * mali_bcast_enable must be called to re-enable the unit. Cores may not be
+ * added or removed when the unit is disabled.
+ */
+void mali_bcast_disable(struct mali_bcast_unit *bcast_unit);
+
+/**
+ * Re-enable broadcast unit
+ *
+ * This resets the masks to include the cores present when mali_bcast_disable was called.
+ */
+MALI_STATIC_INLINE void mali_bcast_enable(struct mali_bcast_unit *bcast_unit)
+{
+       mali_bcast_reset(bcast_unit);
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_dlbu.c b/drivers/gpu/arm/mali400/mali/common/mali_dlbu.c
new file mode 100755 (executable)
index 0000000..94cc5a7
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_dlbu.h"
+#include "mali_memory.h"
+#include "mali_pp.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "mali_hw_core.h"
+
+/**
+ * Size of DLBU registers in bytes
+ */
+#define MALI_DLBU_SIZE 0x400
+
+u32 mali_dlbu_phys_addr = 0;
+static mali_io_address mali_dlbu_cpu_addr = 0;
+
+/**
+ * DLBU register numbers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_dlbu_register {
+       MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address;
+                                                            31:12 Physical address to the page used for the DLBU
+                                                            0 DLBU enable - set this bit to 1 enables the AXI bus
+                                                            between PPs and L2s, setting to 0 disables the router and
+                                                            no further transactions are sent to DLBU */
+       MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR     = 0x0004, /**< Master tile list virtual base address;
+                                                            31:12 Virtual address to the page used for the DLBU */
+       MALI_DLBU_REGISTER_TLLIST_VBASEADDR        = 0x0008, /**< Tile list virtual base address;
+                                                            31:12 Virtual address to the tile list. This address is used when
+                                                            calculating the call address sent to PP.*/
+       MALI_DLBU_REGISTER_FB_DIM                  = 0x000C, /**< Framebuffer dimension;
+                                                            23:16 Number of tiles in Y direction-1
+                                                            7:0 Number of tiles in X direction-1 */
+       MALI_DLBU_REGISTER_TLLIST_CONF             = 0x0010, /**< Tile list configuration;
+                                                            29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024
+                                                            21:16 2^n number of tiles to be binned to one tile list in Y direction
+                                                            5:0 2^n number of tiles to be binned to one tile list in X direction */
+       MALI_DLBU_REGISTER_START_TILE_POS          = 0x0014, /**< Start tile positions;
+                                                            31:24 start position in Y direction for group 1
+                                                            23:16 start position in X direction for group 1
+                                                            15:8 start position in Y direction for group 0
+                                                            7:0 start position in X direction for group 0 */
+       MALI_DLBU_REGISTER_PP_ENABLE_MASK          = 0x0018, /**< PP enable mask;
+                                                            7 enable PP7 for load balancing
+                                                            6 enable PP6 for load balancing
+                                                            5 enable PP5 for load balancing
+                                                            4 enable PP4 for load balancing
+                                                            3 enable PP3 for load balancing
+                                                            2 enable PP2 for load balancing
+                                                            1 enable PP1 for load balancing
+                                                            0 enable PP0 for load balancing */
+} mali_dlbu_register;
+
+typedef enum {
+       PP0ENABLE = 0,
+       PP1ENABLE,
+       PP2ENABLE,
+       PP3ENABLE,
+       PP4ENABLE,
+       PP5ENABLE,
+       PP6ENABLE,
+       PP7ENABLE
+} mali_dlbu_pp_enable;
+
+struct mali_dlbu_core {
+       struct mali_hw_core     hw_core;           /**< Common for all HW cores */
+       u32                     pp_cores_mask;     /**< This is a mask for the PP cores whose operation will be controlled by LBU
+                                                     see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */
+};
+
+_mali_osk_errcode_t mali_dlbu_initialize(void)
+{
+
+       MALI_DEBUG_PRINT(2, ("Mali DLBU: Initializing\n"));
+
+       if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr)) {
+               MALI_SUCCESS;
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_dlbu_terminate(void)
+{
+       MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n"));
+
+       mali_mmu_release_table_page(mali_dlbu_phys_addr, mali_dlbu_cpu_addr);
+}
+
+struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
+{
+       struct mali_dlbu_core *core = NULL;
+
+       MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description));
+
+       core = _mali_osk_malloc(sizeof(struct mali_dlbu_core));
+       if (NULL != core) {
+               if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE)) {
+                       core->pp_cores_mask = 0;
+                       if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core)) {
+                               return core;
+                       }
+                       MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description));
+                       mali_hw_core_delete(&core->hw_core);
+               }
+
+               _mali_osk_free(core);
+       } else {
+               MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n"));
+       }
+
+       return NULL;
+}
+
+void mali_dlbu_delete(struct mali_dlbu_core *dlbu)
+{
+       MALI_DEBUG_ASSERT_POINTER(dlbu);
+
+       mali_dlbu_reset(dlbu);
+       mali_hw_core_delete(&dlbu->hw_core);
+       _mali_osk_free(dlbu);
+}
+
+_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu)
+{
+       u32 dlbu_registers[7];
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+       MALI_DEBUG_ASSERT_POINTER(dlbu);
+
+       MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description));
+
+       dlbu_registers[0] = mali_dlbu_phys_addr | 1; /* bit 0 enables the whole core */
+       dlbu_registers[1] = MALI_DLBU_VIRT_ADDR;
+       dlbu_registers[2] = 0;
+       dlbu_registers[3] = 0;
+       dlbu_registers[4] = 0;
+       dlbu_registers[5] = 0;
+       dlbu_registers[6] = dlbu->pp_cores_mask;
+
+       /* write reset values to core registers */
+       mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, dlbu_registers, 7);
+
+       err = _MALI_OSK_ERR_OK;
+
+       return err;
+}
+
+void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu)
+{
+       MALI_DEBUG_ASSERT_POINTER(dlbu);
+
+       mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
+}
+
+void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
+{
+       struct mali_pp_core *pp_core;
+       u32 bcast_id;
+
+       MALI_DEBUG_ASSERT_POINTER( dlbu );
+       MALI_DEBUG_ASSERT_POINTER( group );
+
+       pp_core = mali_group_get_pp_core(group);
+       bcast_id = mali_pp_core_get_bcast_id(pp_core);
+
+       dlbu->pp_cores_mask |= bcast_id;
+       MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n", bcast_id , dlbu->pp_cores_mask));
+}
+
+/* Remove a group from the DLBU */
+void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
+{
+       struct mali_pp_core *pp_core;
+       u32 bcast_id;
+
+       MALI_DEBUG_ASSERT_POINTER( dlbu );
+       MALI_DEBUG_ASSERT_POINTER( group );
+
+       pp_core = mali_group_get_pp_core(group);
+       bcast_id = mali_pp_core_get_bcast_id(pp_core);
+
+       dlbu->pp_cores_mask &= ~bcast_id;
+       MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", bcast_id, dlbu->pp_cores_mask));
+}
+
+/* Configure the DLBU for \a job. This needs to be done before the job is started on the groups in the DLBU. */
+void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job)
+{
+       u32 *registers;
+       MALI_DEBUG_ASSERT(job);
+       registers = mali_pp_job_get_dlbu_registers(job);
+       MALI_DEBUG_PRINT(4, ("Mali DLBU: Starting job\n"));
+
+       /* Writing 4 registers:
+        * DLBU registers except the first two (written once at DLBU initialisation / reset) and the PP_ENABLE_MASK register */
+       mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4);
+
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_dlbu.h b/drivers/gpu/arm/mali400/mali/common/mali_dlbu.h
new file mode 100755 (executable)
index 0000000..597a908
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_DLBU_H__
+#define __MALI_DLBU_H__
+
+#define MALI_DLBU_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */
+
+#include "mali_osk.h"
+
+struct mali_pp_job;
+struct mali_group;
+
+extern u32 mali_dlbu_phys_addr;
+
+struct mali_dlbu_core;
+
+_mali_osk_errcode_t mali_dlbu_initialize(void);
+void mali_dlbu_terminate(void);
+
+struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource);
+void mali_dlbu_delete(struct mali_dlbu_core *dlbu);
+
+_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu);
+
+void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group);
+void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group);
+
+/** @brief Called to update HW after DLBU state changed
+ *
+ * This function must be called after \a mali_dlbu_add_group or \a
+ * mali_dlbu_remove_group to write the updated mask to hardware, unless the
+ * same is accomplished by calling \a mali_dlbu_reset.
+ */
+void mali_dlbu_update_mask(struct mali_dlbu_core *dlbu);
+
+void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job);
+
+#endif /* __MALI_DLBU_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_dma.c b/drivers/gpu/arm/mali400/mali/common/mali_dma.c
new file mode 100755 (executable)
index 0000000..2fb8750
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_hw_core.h"
+#include "mali_dma.h"
+
+/**
+ * Size of the Mali-450 DMA unit registers in bytes.
+ */
+#define MALI450_DMA_REG_SIZE 0x08
+
+/**
+ * Value that appears in MEMSIZE if an error occurs when reading the command list.
+ */
+#define MALI450_DMA_BUS_ERR_VAL 0xffffffff
+
+/**
+ * Mali DMA registers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register.
+ */
+typedef enum mali_dma_register {
+
+       MALI450_DMA_REG_SOURCE_ADDRESS = 0x0000,
+       MALI450_DMA_REG_SOURCE_SIZE = 0x0004,
+} mali_dma_register;
+
+struct mali_dma_core {
+       struct mali_hw_core  hw_core;      /**< Common for all HW cores */
+       _mali_osk_spinlock_t *lock;            /**< Lock protecting access to DMA core */
+       mali_dma_pool pool;                /**< Memory pool for command buffers */
+};
+
+static struct mali_dma_core *mali_global_dma_core = NULL;
+
+struct mali_dma_core *mali_dma_create(_mali_osk_resource_t *resource)
+{
+       struct mali_dma_core* dma;
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT(NULL == mali_global_dma_core);
+
+       dma = _mali_osk_malloc(sizeof(struct mali_dma_core));
+       if (dma == NULL) goto alloc_failed;
+
+       dma->lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_DMA_COMMAND);
+       if (NULL == dma->lock) goto lock_init_failed;
+
+       dma->pool = mali_dma_pool_create(MALI_DMA_CMD_BUF_SIZE, 4, 0);
+       if (NULL == dma->pool) goto dma_pool_failed;
+
+       err = mali_hw_core_create(&dma->hw_core, resource, MALI450_DMA_REG_SIZE);
+       if (_MALI_OSK_ERR_OK != err) goto hw_core_failed;
+
+       mali_global_dma_core = dma;
+       MALI_DEBUG_PRINT(2, ("Mali DMA: Created Mali APB DMA unit\n"));
+       return dma;
+
+       /* Error handling */
+
+hw_core_failed:
+       mali_dma_pool_destroy(dma->pool);
+dma_pool_failed:
+       _mali_osk_spinlock_term(dma->lock);
+lock_init_failed:
+       _mali_osk_free(dma);
+alloc_failed:
+       MALI_DEBUG_PRINT(2, ("Mali DMA: Failed to create APB DMA unit\n"));
+       return NULL;
+}
+
+void mali_dma_delete(struct mali_dma_core *dma)
+{
+       MALI_DEBUG_ASSERT_POINTER(dma);
+
+       MALI_DEBUG_PRINT(2, ("Mali DMA: Deleted Mali APB DMA unit\n"));
+
+       mali_hw_core_delete(&dma->hw_core);
+       _mali_osk_spinlock_term(dma->lock);
+       mali_dma_pool_destroy(dma->pool);
+       _mali_osk_free(dma);
+}
+
+static void mali_dma_bus_error(struct mali_dma_core *dma)
+{
+       u32 addr = mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS);
+
+       MALI_PRINT_ERROR(("Mali DMA: Bus error when reading command list from 0x%lx\n", addr));
+
+       /* Clear the bus error */
+       mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE, 0);
+}
+
+static mali_bool mali_dma_is_busy(struct mali_dma_core *dma)
+{
+       u32 val;
+       mali_bool dma_busy_flag = MALI_FALSE;
+
+       MALI_DEBUG_ASSERT_POINTER(dma);
+
+       val = mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE);
+
+       if (MALI450_DMA_BUS_ERR_VAL == val) {
+               /* Bus error reading command list */
+               mali_dma_bus_error(dma);
+               return MALI_FALSE;
+       }
+       if (val > 0) {
+               dma_busy_flag = MALI_TRUE;
+       }
+
+       return dma_busy_flag;
+}
+
+static void mali_dma_start_transfer(struct mali_dma_core* dma, mali_dma_cmd_buf *buf)
+{
+       u32 memsize = buf->size * 4;
+       u32 addr = buf->phys_addr;
+
+       MALI_DEBUG_ASSERT_POINTER(dma);
+       MALI_DEBUG_ASSERT(memsize < (1 << 16));
+       MALI_DEBUG_ASSERT(0 == (memsize & 0x3)); /* 4 byte aligned */
+
+       MALI_DEBUG_ASSERT(!mali_dma_is_busy(dma));
+
+       /* Writes the physical source memory address of chunk containing command headers and data */
+       mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS, addr);
+
+       /* Writes the length of transfer */
+       mali_hw_core_register_write(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE, memsize);
+}
+
+_mali_osk_errcode_t mali_dma_get_cmd_buf(mali_dma_cmd_buf *buf)
+{
+       MALI_DEBUG_ASSERT_POINTER(buf);
+
+       buf->virt_addr = (u32*)mali_dma_pool_alloc(mali_global_dma_core->pool, &buf->phys_addr);
+       if (NULL == buf->virt_addr) {
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       /* size contains the number of words in the buffer and is incremented
+        * as commands are added to the buffer. */
+       buf->size = 0;
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_dma_put_cmd_buf(mali_dma_cmd_buf *buf)
+{
+       MALI_DEBUG_ASSERT_POINTER(buf);
+
+       if (NULL == buf->virt_addr) return;
+
+       mali_dma_pool_free(mali_global_dma_core->pool, buf->virt_addr, buf->phys_addr);
+
+       buf->virt_addr = NULL;
+}
+
+_mali_osk_errcode_t mali_dma_start(struct mali_dma_core* dma, mali_dma_cmd_buf *buf)
+{
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+
+       _mali_osk_spinlock_lock(dma->lock);
+
+       if (mali_dma_is_busy(dma)) {
+               err = _MALI_OSK_ERR_BUSY;
+               goto out;
+       }
+
+       mali_dma_start_transfer(dma, buf);
+
+out:
+       _mali_osk_spinlock_unlock(dma->lock);
+       return err;
+}
+
+void mali_dma_debug(struct mali_dma_core *dma)
+{
+       MALI_DEBUG_ASSERT_POINTER(dma);
+       MALI_DEBUG_PRINT(1, ("DMA unit registers:\n\t%08x, %08x\n",
+                            mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_ADDRESS),
+                            mali_hw_core_register_read(&dma->hw_core, MALI450_DMA_REG_SOURCE_SIZE)
+                           ));
+
+}
+
+struct mali_dma_core *mali_dma_get_global_dma_core(void)
+{
+       /* Returns the global dma core object */
+       return mali_global_dma_core;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_dma.h b/drivers/gpu/arm/mali400/mali/common/mali_dma.h
new file mode 100755 (executable)
index 0000000..e62b7b9
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_DMA_H__
+#define __MALI_DMA_H__
+
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_hw_core.h"
+
+#define MALI_DMA_CMD_BUF_SIZE 1024
+
+typedef struct mali_dma_cmd_buf {
+       u32 *virt_addr;           /**< CPU address of command buffer */
+       u32 phys_addr;            /**< Physical address of command buffer */
+       u32 size;                 /**< Number of prepared words in command buffer */
+} mali_dma_cmd_buf;
+
+/** @brief Create a new DMA unit
+ *
+ * This is called from entry point of the driver in order to create and
+ * intialize the DMA resource
+ *
+ * @param resource it will be a pointer to a DMA resource
+ * @return DMA object on success, NULL on failure
+ */
+struct mali_dma_core *mali_dma_create(_mali_osk_resource_t *resource);
+
+/** @brief Delete DMA unit
+ *
+ * This is called on entry point of driver if the driver initialization fails
+ * after initialization of the DMA unit. It is also called on the exit of the
+ * driver to delete the DMA resource
+ *
+ * @param dma Pointer to DMA unit object
+ */
+void mali_dma_delete(struct mali_dma_core *dma);
+
+/** @brief Retrieves the MALI DMA core object (if there is)
+ *
+ * @return The Mali DMA object otherwise NULL
+ */
+struct mali_dma_core *mali_dma_get_global_dma_core(void);
+
+/**
+ * @brief Run a command buffer on the DMA unit
+ *
+ * @param dma Pointer to the DMA unit to use
+ * @param buf Pointer to the command buffer to use
+ * @return _MALI_OSK_ERR_OK if the buffer was started successfully,
+ *         _MALI_OSK_ERR_BUSY if the DMA unit is busy.
+ */
+_mali_osk_errcode_t mali_dma_start(struct mali_dma_core* dma, mali_dma_cmd_buf *buf);
+
+/**
+ * @brief Create a DMA command
+ *
+ * @param core Mali core
+ * @param reg offset to register of core
+ * @param n number of registers to write
+ */
+MALI_STATIC_INLINE u32 mali_dma_command_write(struct mali_hw_core *core, u32 reg, u32 n)
+{
+       u32 core_offset = core->phys_offset;
+
+       MALI_DEBUG_ASSERT(reg < 0x2000);
+       MALI_DEBUG_ASSERT(n < 0x800);
+       MALI_DEBUG_ASSERT(core_offset < 0x30000);
+       MALI_DEBUG_ASSERT(0 == ((core_offset + reg) & ~0x7FFFF));
+
+       return (n << 20) | (core_offset + reg);
+}
+
+/**
+ * @brief Add a array write to DMA command buffer
+ *
+ * @param buf DMA command buffer to fill in
+ * @param core Core to do DMA to
+ * @param reg Register on core to start writing to
+ * @param data Pointer to data to write
+ * @param count Number of 4 byte words to write
+ */
+MALI_STATIC_INLINE void mali_dma_write_array(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
+        u32 reg, u32 *data, u32 count)
+{
+       MALI_DEBUG_ASSERT((buf->size + 1 + count ) < MALI_DMA_CMD_BUF_SIZE / 4);
+
+       buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, count);
+
+       _mali_osk_memcpy(buf->virt_addr + buf->size, data, count * sizeof(*buf->virt_addr));
+
+       buf->size += count;
+}
+
+/**
+ * @brief Add a conditional array write to DMA command buffer
+ *
+ * @param buf DMA command buffer to fill in
+ * @param core Core to do DMA to
+ * @param reg Register on core to start writing to
+ * @param data Pointer to data to write
+ * @param count Number of 4 byte words to write
+ * @param ref Pointer to referance data that can be skipped if equal
+ */
+MALI_STATIC_INLINE void mali_dma_write_array_conditional(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
+        u32 reg, u32 *data, u32 count, const u32 *ref)
+{
+       /* Do conditional array writes are not yet implemented, fallback to a
+        * normal array write. */
+       mali_dma_write_array(buf, core, reg, data, count);
+}
+
+/**
+ * @brief Add a conditional register write to the DMA command buffer
+ *
+ * If the data matches the reference the command will be skipped.
+ *
+ * @param buf DMA command buffer to fill in
+ * @param core Core to do DMA to
+ * @param reg Register on core to start writing to
+ * @param data Pointer to data to write
+ * @param ref Pointer to referance data that can be skipped if equal
+ */
+MALI_STATIC_INLINE void mali_dma_write_conditional(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
+        u32 reg, u32 data, const u32 ref)
+{
+       /* Skip write if reference value is equal to data. */
+       if (data == ref) return;
+
+       buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, 1);
+
+       buf->virt_addr[buf->size++] = data;
+
+       MALI_DEBUG_ASSERT(buf->size < MALI_DMA_CMD_BUF_SIZE / 4);
+}
+
+/**
+ * @brief Add a register write to the DMA command buffer
+ *
+ * @param buf DMA command buffer to fill in
+ * @param core Core to do DMA to
+ * @param reg Register on core to start writing to
+ * @param data Pointer to data to write
+ */
+MALI_STATIC_INLINE void mali_dma_write(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
+                                       u32 reg, u32 data)
+{
+       buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, 1);
+
+       buf->virt_addr[buf->size++] = data;
+
+       MALI_DEBUG_ASSERT(buf->size < MALI_DMA_CMD_BUF_SIZE / 4);
+}
+
+/**
+ * @brief Prepare DMA command buffer for use
+ *
+ * This function allocates the DMA buffer itself.
+ *
+ * @param buf The mali_dma_cmd_buf to prepare
+ * @return _MALI_OSK_ERR_OK if the \a buf is ready to use
+ */
+_mali_osk_errcode_t mali_dma_get_cmd_buf(mali_dma_cmd_buf *buf);
+
+/**
+ * @brief Check if a DMA command buffer is ready for use
+ *
+ * @param buf The mali_dma_cmd_buf to check
+ * @return MALI_TRUE if buffer is usable, MALI_FALSE otherwise
+ */
+MALI_STATIC_INLINE mali_bool mali_dma_cmd_buf_is_valid(mali_dma_cmd_buf *buf)
+{
+       return NULL != buf->virt_addr;
+}
+
+/**
+ * @brief Return a DMA command buffer
+ *
+ * @param buf Pointer to DMA command buffer to return
+ */
+void mali_dma_put_cmd_buf(mali_dma_cmd_buf *buf);
+
+#endif /* __MALI_DMA_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp.c b/drivers/gpu/arm/mali400/mali/common/mali_gp.c
new file mode 100755 (executable)
index 0000000..0572fde
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_gp.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "regs/mali_gp_regs.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#if defined(CONFIG_MALI400_PROFILING)
+#include "mali_osk_profiling.h"
+#endif
+
+static struct mali_gp_core *mali_global_gp_core = NULL;
+
+/* Interrupt handlers */
+static void mali_gp_irq_probe_trigger(void *data);
+static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data);
+
+struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group)
+{
+       struct mali_gp_core* core = NULL;
+
+       MALI_DEBUG_ASSERT(NULL == mali_global_gp_core);
+       MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description));
+
+       core = _mali_osk_malloc(sizeof(struct mali_gp_core));
+       if (NULL != core) {
+               if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE)) {
+                       _mali_osk_errcode_t ret;
+
+                       ret = mali_gp_reset(core);
+
+                       if (_MALI_OSK_ERR_OK == ret) {
+                               ret = mali_group_add_gp_core(group, core);
+                               if (_MALI_OSK_ERR_OK == ret) {
+                                       /* Setup IRQ handlers (which will do IRQ probing if needed) */
+                                       core->irq = _mali_osk_irq_init(resource->irq,
+                                                                      mali_group_upper_half_gp,
+                                                                      group,
+                                                                      mali_gp_irq_probe_trigger,
+                                                                      mali_gp_irq_probe_ack,
+                                                                      core,
+                                                                      resource->description);
+                                       if (NULL != core->irq) {
+                                               MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core));
+                                               mali_global_gp_core = core;
+
+                                               return core;
+                                       } else {
+                                               MALI_PRINT_ERROR(("Mali GP: Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
+                                       }
+                                       mali_group_remove_gp_core(group);
+                               } else {
+                                       MALI_PRINT_ERROR(("Mali GP: Failed to add core %s to group\n", core->hw_core.description));
+                               }
+                       }
+                       mali_hw_core_delete(&core->hw_core);
+               }
+
+               _mali_osk_free(core);
+       } else {
+               MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n"));
+       }
+
+       return NULL;
+}
+
+void mali_gp_delete(struct mali_gp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       _mali_osk_irq_term(core->irq);
+       mali_hw_core_delete(&core->hw_core);
+       mali_global_gp_core = NULL;
+       _mali_osk_free(core);
+}
+
+void mali_gp_stop_bus(struct mali_gp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
+}
+
+_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core)
+{
+       int i;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       /* Send the stop bus command. */
+       mali_gp_stop_bus(core);
+
+       /* Wait for bus to be stopped */
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
+               if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) {
+                       break;
+               }
+       }
+
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description));
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_gp_hard_reset(struct mali_gp_core *core)
+{
+       const u32 reset_wait_target_register = MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW;
+       const u32 reset_invalid_value = 0xC0FFE000;
+       const u32 reset_check_value = 0xC01A0000;
+       const u32 reset_default_value = 0;
+       int i;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+       MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description));
+
+       mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value);
+
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET);
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
+               mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value);
+               if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register)) {
+                       break;
+               }
+       }
+
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n"));
+       }
+
+       mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */
+       /* Re-enable interrupts */
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+
+}
+
+void mali_gp_reset_async(struct mali_gp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description));
+
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
+
+}
+
+_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core)
+{
+       int i;
+       u32 rawstat = 0;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
+               rawstat = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT);
+               if (rawstat & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) {
+                       break;
+               }
+       }
+
+       if (i == MALI_REG_POLL_COUNT_FAST) {
+               MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, rawstat: 0x%08x\n",
+                                 core->hw_core.description, rawstat));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Re-enable interrupts */
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core)
+{
+       mali_gp_reset_async(core);
+       return mali_gp_reset_wait(core);
+}
+
+void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job)
+{
+       u32 startcmd = 0;
+       u32 *frame_registers = mali_gp_job_get_frame_registers(job);
+       u32 counter_src0 = mali_gp_job_get_perf_counter_src0(job);
+       u32 counter_src1 = mali_gp_job_get_perf_counter_src1(job);
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       if (mali_gp_job_has_vs_job(job)) {
+               startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS;
+       }
+
+       if (mali_gp_job_has_plbu_job(job)) {
+               startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU;
+       }
+
+       MALI_DEBUG_ASSERT(0 != startcmd);
+
+       mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME);
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, counter_src0);
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+       }
+       if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, counter_src1);
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+       }
+
+       MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd));
+
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC);
+
+       /* Barrier to make sure the previous register write is finished */
+       _mali_osk_write_mem_barrier();
+
+       /* This is the command that starts the core. */
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd);
+
+       /* Barrier to make sure the previous register write is finished */
+       _mali_osk_write_mem_barrier();
+}
+
+void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr)
+{
+       u32 irq_readout;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT);
+
+       if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) {
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG));
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr);
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr);
+
+               MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n"));
+
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC);
+               _mali_osk_write_mem_barrier();
+       }
+       /*
+        * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response.
+        * A timeout or a page fault on Mali-200 PP core can cause this behaviour.
+        */
+}
+
+u32 mali_gp_core_get_version(struct mali_gp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION);
+}
+
+struct mali_gp_core *mali_gp_get_global_gp_core(void)
+{
+       return mali_global_gp_core;
+}
+
+/* ------------- interrupt handling below ------------------ */
+static void mali_gp_irq_probe_trigger(void *data)
+{
+       struct mali_gp_core *core = (struct mali_gp_core *)data;
+
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG);
+       _mali_osk_mem_barrier();
+}
+
+static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data)
+{
+       struct mali_gp_core *core = (struct mali_gp_core *)data;
+       u32 irq_readout;
+
+       irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+       if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout) {
+               mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG);
+               _mali_osk_mem_barrier();
+               return _MALI_OSK_ERR_OK;
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+/* ------ local helper functions below --------- */
+#if MALI_STATE_TRACKING
+u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size)
+{
+       int n = 0;
+
+       n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description);
+
+       return n;
+}
+#endif
+
+void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend)
+{
+       u32 val0 = 0;
+       u32 val1 = 0;
+       u32 counter_src0 = mali_gp_job_get_perf_counter_src0(job);
+       u32 counter_src1 = mali_gp_job_get_perf_counter_src1(job);
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
+               val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+               mali_gp_job_set_perf_counter_value0(job, val0);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               _mali_osk_profiling_report_hw_counter(COUNTER_VP_0_C0, val0);
+#endif
+
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
+               val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+               mali_gp_job_set_perf_counter_value1(job, val1);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               _mali_osk_profiling_report_hw_counter(COUNTER_VP_0_C1, val1);
+#endif
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp.h b/drivers/gpu/arm/mali400/mali/common/mali_gp.h
new file mode 100755 (executable)
index 0000000..b9a2762
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_GP_H__
+#define __MALI_GP_H__
+
+#include "mali_osk.h"
+#include "mali_gp_job.h"
+#include "mali_hw_core.h"
+#include "regs/mali_gp_regs.h"
+
+struct mali_group;
+
+/**
+ * Definition of the GP core struct
+ * Used to track a GP core in the system.
+ */
+struct mali_gp_core {
+       struct mali_hw_core  hw_core;           /**< Common for all HW cores */
+       _mali_osk_irq_t     *irq;               /**< IRQ handler */
+};
+
+_mali_osk_errcode_t mali_gp_initialize(void);
+void mali_gp_terminate(void);
+
+struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group);
+void mali_gp_delete(struct mali_gp_core *core);
+
+void mali_gp_stop_bus(struct mali_gp_core *core);
+_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core);
+void mali_gp_reset_async(struct mali_gp_core *core);
+_mali_osk_errcode_t mali_gp_reset_wait(struct mali_gp_core *core);
+void mali_gp_hard_reset(struct mali_gp_core *core);
+_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core);
+
+void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job);
+void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr);
+
+u32 mali_gp_core_get_version(struct mali_gp_core *core);
+
+struct mali_gp_core *mali_gp_get_global_gp_core(void);
+
+u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size);
+
+void mali_gp_update_performance_counters(struct mali_gp_core *core, struct mali_gp_job *job, mali_bool suspend);
+
+/*** Accessor functions ***/
+MALI_STATIC_INLINE const char *mali_gp_get_hw_core_desc(struct mali_gp_core *core)
+{
+       return core->hw_core.description;
+}
+
+/*** Register reading/writing functions ***/
+MALI_STATIC_INLINE u32 mali_gp_get_int_stat(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+}
+
+MALI_STATIC_INLINE void mali_gp_mask_all_interrupts(struct mali_gp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE);
+}
+
+MALI_STATIC_INLINE u32 mali_gp_read_rawstat(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_read_core_status(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS);
+}
+
+MALI_STATIC_INLINE void mali_gp_enable_interrupts(struct mali_gp_core *core, u32 irq_exceptions)
+{
+       /* Enable all interrupts, except those specified in irq_exceptions */
+       mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK,
+                                   MALIGP2_REG_VAL_IRQ_MASK_USED & ~irq_exceptions);
+}
+
+MALI_STATIC_INLINE u32 mali_gp_read_plbu_alloc_start_addr(struct mali_gp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR);
+}
+
+#endif /* __MALI_GP_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp_job.c b/drivers/gpu/arm/mali400/mali/common/mali_gp_job.c
new file mode 100755 (executable)
index 0000000..1e74d30
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_gp_job.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+
+static u32 gp_counter_src0 = MALI_HW_CORE_NO_COUNTER;      /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+static u32 gp_counter_src1 = MALI_HW_CORE_NO_COUNTER;          /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+
+struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id, struct mali_timeline_tracker *pp_tracker)
+{
+       struct mali_gp_job *job;
+       u32 perf_counter_flag;
+
+       job = _mali_osk_malloc(sizeof(struct mali_gp_job));
+       if (NULL != job) {
+               job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s));
+               if (NULL == job->finished_notification) {
+                       _mali_osk_free(job);
+                       return NULL;
+               }
+
+               job->oom_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s));
+               if (NULL == job->oom_notification) {
+                       _mali_osk_notification_delete(job->finished_notification);
+                       _mali_osk_free(job);
+                       return NULL;
+               }
+
+               if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s))) {
+                       _mali_osk_notification_delete(job->finished_notification);
+                       _mali_osk_notification_delete(job->oom_notification);
+                       _mali_osk_free(job);
+                       return NULL;
+               }
+
+               perf_counter_flag = mali_gp_job_get_perf_counter_flag(job);
+
+               /* case when no counters came from user space
+                * so pass the debugfs / DS-5 provided global ones to the job object */
+               if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) ||
+                     (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) {
+                       mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0());
+                       mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1());
+               }
+
+               _mali_osk_list_init(&job->list);
+               job->session = session;
+               job->id = id;
+               job->heap_current_addr = job->uargs.frame_registers[4];
+               job->perf_counter_value0 = 0;
+               job->perf_counter_value1 = 0;
+               job->pid = _mali_osk_get_pid();
+               job->tid = _mali_osk_get_tid();
+
+               job->pp_tracker = pp_tracker;
+               if (NULL != job->pp_tracker) {
+                       /* Take a reference on PP job's tracker that will be released when the GP
+                          job is done. */
+                       mali_timeline_system_tracker_get(session->timeline_system, pp_tracker);
+               }
+
+               mali_timeline_tracker_init(&job->tracker, MALI_TIMELINE_TRACKER_GP, NULL, job);
+               mali_timeline_fence_copy_uk_fence(&(job->tracker.fence), &(job->uargs.fence));
+
+               return job;
+       }
+
+       return NULL;
+}
+
+void mali_gp_job_delete(struct mali_gp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT(NULL == job->pp_tracker);
+
+       /* de-allocate the pre-allocated oom notifications */
+       if (NULL != job->oom_notification) {
+               _mali_osk_notification_delete(job->oom_notification);
+               job->oom_notification = NULL;
+       }
+       if (NULL != job->finished_notification) {
+               _mali_osk_notification_delete(job->finished_notification);
+               job->finished_notification = NULL;
+       }
+
+       _mali_osk_free(job);
+}
+
+u32 mali_gp_job_get_gp_counter_src0(void)
+{
+       return gp_counter_src0;
+}
+
+void mali_gp_job_set_gp_counter_src0(u32 counter)
+{
+       gp_counter_src0 = counter;
+}
+
+u32 mali_gp_job_get_gp_counter_src1(void)
+{
+       return gp_counter_src1;
+}
+
+void mali_gp_job_set_gp_counter_src1(u32 counter)
+{
+       gp_counter_src1 = counter;
+}
+
+mali_scheduler_mask mali_gp_job_signal_pp_tracker(struct mali_gp_job *job, mali_bool success)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       if (NULL != job->pp_tracker) {
+               schedule_mask |= mali_timeline_system_tracker_put(job->session->timeline_system, job->pp_tracker, MALI_FALSE == success);
+               job->pp_tracker = NULL;
+       }
+
+       return schedule_mask;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp_job.h b/drivers/gpu/arm/mali400/mali/common/mali_gp_job.h
new file mode 100755 (executable)
index 0000000..b30bcfd
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_GP_JOB_H__
+#define __MALI_GP_JOB_H__
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+#include "mali_session.h"
+#include "mali_timeline.h"
+#include "mali_scheduler_types.h"
+
+/**
+ * The structure represents a GP job, including all sub-jobs
+ * (This struct unfortunately needs to be public because of how the _mali_osk_list_*
+ * mechanism works)
+ */
+struct mali_gp_job {
+       _mali_osk_list_t list;                             /**< Used to link jobs together in the scheduler queue */
+       struct mali_session_data *session;                 /**< Session which submitted this job */
+       _mali_uk_gp_start_job_s uargs;                     /**< Arguments from user space */
+       u32 id;                                            /**< Identifier for this job in kernel space (sequential numbering) */
+       u32 cache_order;                                   /**< Cache order used for L2 cache flushing (sequential numbering) */
+       u32 heap_current_addr;                             /**< Holds the current HEAP address when the job has completed */
+       u32 perf_counter_value0;                           /**< Value of performance counter 0 (to be returned to user space) */
+       u32 perf_counter_value1;                           /**< Value of performance counter 1 (to be returned to user space) */
+       u32 pid;                                           /**< Process ID of submitting process */
+       u32 tid;                                           /**< Thread ID of submitting thread */
+       _mali_osk_notification_t *finished_notification;   /**< Notification sent back to userspace on job complete */
+       _mali_osk_notification_t *oom_notification;        /**< Notification sent back to userspace on OOM */
+       struct mali_timeline_tracker tracker;              /**< Timeline tracker for this job */
+       struct mali_timeline_tracker *pp_tracker;          /**< Pointer to Timeline tracker for PP job that depends on this job. */
+};
+
+struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id, struct mali_timeline_tracker *pp_tracker);
+void mali_gp_job_delete(struct mali_gp_job *job);
+
+u32 mali_gp_job_get_gp_counter_src0(void);
+void mali_gp_job_set_gp_counter_src0(u32 counter);
+u32 mali_gp_job_get_gp_counter_src1(void);
+void mali_gp_job_set_gp_counter_src1(u32 counter);
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job)
+{
+       return (NULL == job) ? 0 : job->id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_cache_order(struct mali_gp_job *job)
+{
+       return (NULL == job) ? 0 : job->cache_order;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job)
+{
+       return job->uargs.user_job_ptr;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job)
+{
+       return job->uargs.frame_builder_id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job)
+{
+       return job->uargs.flush_id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_pid(struct mali_gp_job *job)
+{
+       return job->pid;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_tid(struct mali_gp_job *job)
+{
+       return job->tid;
+}
+
+MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job)
+{
+       return job->uargs.frame_registers;
+}
+
+MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job)
+{
+       return job->session;
+}
+
+MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job)
+{
+       return (job->uargs.frame_registers[0] != job->uargs.frame_registers[1]) ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job)
+{
+       return (job->uargs.frame_registers[2] != job->uargs.frame_registers[3]) ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job)
+{
+       return job->heap_current_addr;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *job, u32 heap_addr)
+{
+       job->heap_current_addr = heap_addr;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job)
+{
+       return job->uargs.perf_counter_flag;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job)
+{
+       return job->uargs.perf_counter_src0;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job)
+{
+       return job->uargs.perf_counter_src1;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job)
+{
+       return job->perf_counter_value0;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *job)
+{
+       return job->perf_counter_value1;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src0(struct mali_gp_job *job, u32 src)
+{
+       job->uargs.perf_counter_src0 = src;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_src1(struct mali_gp_job *job, u32 src)
+{
+       job->uargs.perf_counter_src1 = src;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value)
+{
+       job->perf_counter_value0 = value;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value1(struct mali_gp_job *job, u32 value)
+{
+       job->perf_counter_value1 = value;
+}
+
+/**
+ * Returns MALI_TRUE if first job is after the second job, ordered by job ID.
+ *
+ * @param first First job.
+ * @param second Second job.
+ * @return MALI_TRUE if first job should be ordered after the second job, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_gp_job_is_after(struct mali_gp_job *first, struct mali_gp_job *second)
+{
+       /* A span is used to handle job ID wrapping. */
+       return (mali_gp_job_get_id(first) - mali_gp_job_get_id(second)) < MALI_SCHEDULER_JOB_ID_SPAN;
+}
+
+/**
+ * Release reference on tracker for PP job that depends on this GP job.
+ *
+ * @note If GP job has a reference on tracker, this function MUST be called before the GP job is
+ * deleted.
+ *
+ * @param job GP job that is done.
+ * @param success MALI_TRUE if job completed successfully, MALI_FALSE if not.
+ * @return A scheduling bitmask indicating whether scheduling needs to be done.
+ */
+mali_scheduler_mask mali_gp_job_signal_pp_tracker(struct mali_gp_job *job, mali_bool success);
+
+#endif /* __MALI_GP_JOB_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.c b/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.c
new file mode 100755 (executable)
index 0000000..a2c50bb
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_gp_scheduler.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_scheduler.h"
+#include "mali_gp.h"
+#include "mali_gp_job.h"
+#include "mali_group.h"
+#include "mali_timeline.h"
+#include "mali_osk_profiling.h"
+#include "mali_kernel_utilization.h"
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+#include <linux/sched.h>
+#include <trace/events/gpu.h>
+#endif
+
+enum mali_gp_slot_state {
+       MALI_GP_SLOT_STATE_IDLE,
+       MALI_GP_SLOT_STATE_WORKING,
+       MALI_GP_SLOT_STATE_DISABLED,
+};
+
+/* A render slot is an entity which jobs can be scheduled onto */
+struct mali_gp_slot {
+       struct mali_group *group;
+       /*
+        * We keep track of the state here as well as in the group object
+        * so we don't need to take the group lock so often (and also avoid clutter with the working lock)
+        */
+       enum mali_gp_slot_state state;
+       u32 returned_cookie;
+};
+
+static u32 gp_version = 0;
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(job_queue);      /* List of unscheduled jobs. */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(job_queue_high); /* List of unscheduled high priority jobs. */
+static struct mali_gp_slot slot;
+
+/* Variables to allow safe pausing of the scheduler */
+static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL;
+static u32 pause_count = 0;
+
+static mali_bool mali_gp_scheduler_is_suspended(void *data);
+static void mali_gp_scheduler_job_queued(void);
+static void mali_gp_scheduler_job_completed(void);
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+static _mali_osk_spinlock_irq_t *gp_scheduler_lock = NULL;
+#else
+static _mali_osk_spinlock_t *gp_scheduler_lock = NULL;
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+
+_mali_osk_errcode_t mali_gp_scheduler_initialize(void)
+{
+       u32 num_groups;
+       u32 i;
+       _mali_osk_errcode_t ret = _MALI_OSK_ERR_OK;
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       gp_scheduler_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+#else
+       gp_scheduler_lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+       if (NULL == gp_scheduler_lock) {
+               ret = _MALI_OSK_ERR_NOMEM;
+               goto cleanup;
+       }
+
+       gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init();
+       if (NULL == gp_scheduler_working_wait_queue) {
+               ret = _MALI_OSK_ERR_NOMEM;
+               goto cleanup;
+       }
+
+       /* Find all the available GP cores */
+       num_groups = mali_group_get_glob_num_groups();
+       for (i = 0; i < num_groups; i++) {
+               struct mali_group *group = mali_group_get_glob_group(i);
+               MALI_DEBUG_ASSERT(NULL != group);
+               if (NULL != group) {
+                       struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+                       if (NULL != gp_core) {
+                               if (0 == gp_version) {
+                                       /* Retrieve GP version */
+                                       gp_version = mali_gp_core_get_version(gp_core);
+                               }
+                               slot.group = group;
+                               slot.state = MALI_GP_SLOT_STATE_IDLE;
+                               break; /* There is only one GP, no point in looking for more */
+                       }
+               } else {
+                       ret = _MALI_OSK_ERR_ITEM_NOT_FOUND;
+                       goto cleanup;
+               }
+       }
+
+       return _MALI_OSK_ERR_OK;
+
+cleanup:
+       if (NULL != gp_scheduler_working_wait_queue) {
+               _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue);
+               gp_scheduler_working_wait_queue = NULL;
+       }
+
+       if (NULL != gp_scheduler_lock) {
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+               _mali_osk_spinlock_irq_term(gp_scheduler_lock);
+#else
+               _mali_osk_spinlock_term(gp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+               gp_scheduler_lock = NULL;
+       }
+
+       return ret;
+}
+
+void mali_gp_scheduler_terminate(void)
+{
+       MALI_DEBUG_ASSERT(   MALI_GP_SLOT_STATE_IDLE     == slot.state
+                            || MALI_GP_SLOT_STATE_DISABLED == slot.state);
+       MALI_DEBUG_ASSERT_POINTER(slot.group);
+       mali_group_delete(slot.group);
+
+       _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue);
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       _mali_osk_spinlock_irq_term(gp_scheduler_lock);
+#else
+       _mali_osk_spinlock_term(gp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+}
+
+MALI_STATIC_INLINE void mali_gp_scheduler_lock(void)
+{
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       _mali_osk_spinlock_irq_lock(gp_scheduler_lock);
+#else
+       _mali_osk_spinlock_lock(gp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+       MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n"));
+}
+
+MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void)
+{
+       MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n"));
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       _mali_osk_spinlock_irq_unlock(gp_scheduler_lock);
+#else
+       _mali_osk_spinlock_unlock(gp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+}
+
+#if defined(DEBUG)
+#define MALI_ASSERT_GP_SCHEDULER_LOCKED() MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock)
+#else
+#define MALI_ASSERT_GP_SCHEDULER_LOCKED() do {} while (0)
+#endif /* defined(DEBUG) */
+
+/* Group and scheduler must be locked when entering this function.  Both will be unlocked before
+ * exiting. */
+static void mali_gp_scheduler_schedule_internal_and_unlock(void)
+{
+       struct mali_gp_job *job = NULL;
+
+       MALI_DEBUG_ASSERT_LOCK_HELD(slot.group->lock);
+       MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock);
+
+       if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state ||
+           (_mali_osk_list_empty(&job_queue) && _mali_osk_list_empty(&job_queue_high))) {
+               mali_gp_scheduler_unlock();
+               mali_group_unlock(slot.group);
+               MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
+                                    pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0));
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+               trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(), 0, 0, 0);
+#endif
+               return; /* Nothing to do, so early out */
+       }
+
+       /* Get next job in queue */
+       if (!_mali_osk_list_empty(&job_queue_high)) {
+               job = _MALI_OSK_LIST_ENTRY(job_queue_high.next, struct mali_gp_job, list);
+       } else {
+               MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&job_queue));
+               job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list);
+       }
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       /* Remove the job from queue */
+       _mali_osk_list_del(&job->list);
+
+       /* Mark slot as busy */
+       slot.state = MALI_GP_SLOT_STATE_WORKING;
+
+       mali_gp_scheduler_unlock();
+
+       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job));
+
+       mali_group_start_gp_job(slot.group, job);
+       mali_group_unlock(slot.group);
+}
+
+void mali_gp_scheduler_schedule(void)
+{
+       mali_group_lock(slot.group);
+       mali_gp_scheduler_lock();
+
+       mali_gp_scheduler_schedule_internal_and_unlock();
+}
+
+static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success)
+{
+       _mali_uk_gp_job_finished_s *jobres = job->finished_notification->result_buffer;
+       _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */
+       jobres->user_job_ptr = mali_gp_job_get_user_id(job);
+       if (MALI_TRUE == success) {
+               jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS;
+       } else {
+               jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR;
+       }
+
+       jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job);
+       jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job);
+       jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job);
+
+       mali_session_send_notification(mali_gp_job_get_session(job), job->finished_notification);
+       job->finished_notification = NULL;
+
+       mali_gp_job_delete(job);
+       mali_gp_scheduler_job_completed();
+}
+
+/* Group must be locked when entering this function.  Will be unlocked before exiting. */
+void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+       MALI_DEBUG_ASSERT(slot.group == group);
+
+       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure"));
+
+       /* Release tracker. */
+       schedule_mask |= mali_timeline_tracker_release(&job->tracker);
+
+       /* Signal PP job. */
+       schedule_mask |= mali_gp_job_signal_pp_tracker(job, success);
+
+       mali_gp_scheduler_lock();
+
+       /* Mark slot as idle again */
+       slot.state = MALI_GP_SLOT_STATE_IDLE;
+
+       /* If paused, then this was the last job, so wake up sleeping workers */
+       if (pause_count > 0) {
+               _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue);
+       }
+
+       /* Schedule any queued GP jobs on this group. */
+       mali_gp_scheduler_schedule_internal_and_unlock();
+
+       /* GP is now scheduled, removing it from the mask. */
+       schedule_mask &= ~MALI_SCHEDULER_MASK_GP;
+
+       if (MALI_SCHEDULER_MASK_EMPTY != schedule_mask) {
+               /* Releasing the tracker activated other jobs that need scheduling. */
+               mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE);
+       }
+
+       /* Sends the job end message to user space and free the job object */
+       mali_gp_scheduler_return_job_to_user(job, success);
+}
+
+void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job)
+{
+       _mali_uk_gp_job_suspended_s * jobres;
+       _mali_osk_notification_t * notification;
+
+       mali_gp_scheduler_lock();
+
+       notification = job->oom_notification;
+       job->oom_notification = NULL;
+       slot.returned_cookie = mali_gp_job_get_id(job);
+
+       jobres = (_mali_uk_gp_job_suspended_s *)notification->result_buffer;
+       jobres->user_job_ptr = mali_gp_job_get_user_id(job);
+       jobres->cookie = mali_gp_job_get_id(job);
+
+       mali_gp_scheduler_unlock();
+
+       mali_session_send_notification(mali_gp_job_get_session(job), notification);
+
+       /*
+       * If this function failed, then we could return the job to user space right away,
+       * but there is a job timer anyway that will do that eventually.
+       * This is not exactly a common case anyway.
+       */
+}
+
+void mali_gp_scheduler_suspend(void)
+{
+       mali_gp_scheduler_lock();
+       pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */
+       mali_gp_scheduler_unlock();
+
+       _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended, NULL);
+}
+
+void mali_gp_scheduler_resume(void)
+{
+       mali_gp_scheduler_lock();
+       pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
+       mali_gp_scheduler_unlock();
+       if (0 == pause_count) {
+               mali_gp_scheduler_schedule();
+       }
+}
+
+mali_timeline_point mali_gp_scheduler_submit_job(struct mali_session_data *session, struct mali_gp_job *job)
+{
+       mali_timeline_point point;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       mali_gp_scheduler_job_queued();
+
+       /* Add job to Timeline system. */
+       point = mali_timeline_system_add_tracker(session->timeline_system, &job->tracker, MALI_TIMELINE_GP);
+
+       return point;
+}
+
+_mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *uargs)
+{
+       struct mali_session_data *session;
+       struct mali_gp_job *job;
+       mali_timeline_point point;
+       u32 __user *timeline_point_ptr = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(uargs);
+       MALI_DEBUG_ASSERT_POINTER(ctx);
+
+       session = (struct mali_session_data*)ctx;
+
+       job = mali_gp_job_create(session, uargs, mali_scheduler_get_new_id(), NULL);
+       if (NULL == job) {
+               MALI_PRINT_ERROR(("Failed to create GP job.\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       timeline_point_ptr = (u32 __user *) job->uargs.timeline_point_ptr;
+
+       point = mali_gp_scheduler_submit_job(session, job);
+
+       if (0 != _mali_osk_put_user(((u32) point), timeline_point_ptr)) {
+               /* Let user space know that something failed after the job was started. */
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args)
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+       args->number_of_cores = 1;
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args)
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+       args->version = gp_version;
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args)
+{
+       struct mali_session_data *session;
+       struct mali_gp_job *resumed_job;
+       _mali_osk_notification_t *new_notification = 0;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+
+       if (NULL == args->ctx) {
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+
+       session = (struct mali_session_data*)args->ctx;
+       if (NULL == session) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) {
+               new_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s));
+
+               if (NULL == new_notification) {
+                       MALI_PRINT_ERROR(("Mali GP scheduler: Failed to allocate notification object. Will abort GP job.\n"));
+                       mali_group_lock(slot.group);
+                       mali_group_abort_gp_job(slot.group, args->cookie);
+                       mali_group_unlock(slot.group);
+                       return _MALI_OSK_ERR_FAULT;
+               }
+       }
+
+       mali_group_lock(slot.group);
+
+       if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) {
+               MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1]));
+
+               resumed_job = mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]);
+               if (NULL != resumed_job) {
+                       resumed_job->oom_notification = new_notification;
+                       mali_group_unlock(slot.group);
+                       return _MALI_OSK_ERR_OK;
+               } else {
+                       mali_group_unlock(slot.group);
+                       _mali_osk_notification_delete(new_notification);
+                       return _MALI_OSK_ERR_FAULT;
+               }
+       }
+
+       MALI_DEBUG_PRINT(2, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie));
+       mali_group_abort_gp_job(slot.group, args->cookie);
+       mali_group_unlock(slot.group);
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_gp_scheduler_abort_session(struct mali_session_data *session)
+{
+       struct mali_gp_job *job, *tmp;
+       _MALI_OSK_LIST_HEAD_STATIC_INIT(removed_jobs);
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_ASSERT(session->is_aborting);
+
+       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08X.\n", session));
+
+       mali_gp_scheduler_lock();
+
+       /* Find all jobs from the aborting session. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) {
+               if (job->session == session) {
+                       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Removing job %u (0x%08X) from queue.\n", mali_gp_job_get_id(job), job));
+                       _mali_osk_list_move(&job->list, &removed_jobs);
+               }
+       }
+
+       /* Find all high priority jobs from the aborting session. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue_high, struct mali_gp_job, list) {
+               if (job->session == session) {
+                       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Removing job %u (0x%08X) from queue.\n", mali_gp_job_get_id(job), job));
+                       _mali_osk_list_move(&job->list, &removed_jobs);
+               }
+       }
+
+       mali_gp_scheduler_unlock();
+
+       /* Release and delete all found jobs from the aborting session. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &removed_jobs, struct mali_gp_job, list) {
+               mali_timeline_tracker_release(&job->tracker);
+               mali_gp_job_signal_pp_tracker(job, MALI_FALSE);
+               mali_gp_job_delete(job);
+               mali_gp_scheduler_job_completed();
+       }
+
+       /* Abort any running jobs from the session. */
+       mali_group_abort_session(slot.group, session);
+}
+
+static mali_bool mali_gp_scheduler_is_suspended(void *data)
+{
+       mali_bool ret;
+
+       /* This callback does not use the data pointer. */
+       MALI_IGNORE(data);
+
+       mali_gp_scheduler_lock();
+       ret = pause_count > 0 && (slot.state == MALI_GP_SLOT_STATE_IDLE || slot.state == MALI_GP_SLOT_STATE_DISABLED);
+       mali_gp_scheduler_unlock();
+
+       return ret;
+}
+
+
+#if MALI_STATE_TRACKING
+u32 mali_gp_scheduler_dump_state(char *buf, u32 size)
+{
+       int n = 0;
+
+       n += _mali_osk_snprintf(buf + n, size - n, "GP\n");
+       n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty");
+       n += _mali_osk_snprintf(buf + n, size - n, "\tHigh priority queue is %s\n", _mali_osk_list_empty(&job_queue_high) ? "empty" : "not empty");
+
+       n += mali_group_dump_state(slot.group, buf + n, size - n);
+       n += _mali_osk_snprintf(buf + n, size - n, "\n");
+
+       return n;
+}
+#endif
+
+void mali_gp_scheduler_reset_all_groups(void)
+{
+       if (NULL != slot.group) {
+               mali_group_lock(slot.group);
+               mali_group_reset(slot.group);
+               mali_group_unlock(slot.group);
+       }
+}
+
+void mali_gp_scheduler_zap_all_active(struct mali_session_data *session)
+{
+       if (NULL != slot.group) {
+               mali_group_zap_session(slot.group, session);
+       }
+}
+
+void mali_gp_scheduler_enable_group(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT(slot.group == group);
+       MALI_DEBUG_PRINT(2, ("Mali GP scheduler: enabling gp group %p\n", group));
+
+       mali_group_lock(group);
+
+       if (MALI_GROUP_STATE_DISABLED != group->state) {
+               mali_group_unlock(group);
+               MALI_DEBUG_PRINT(2, ("Mali GP scheduler: gp group %p already enabled\n", group));
+               return;
+       }
+
+       mali_gp_scheduler_lock();
+
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state);
+       MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_DISABLED == slot.state);
+       slot.state = MALI_GP_SLOT_STATE_IDLE;
+       group->state = MALI_GROUP_STATE_IDLE;
+
+       mali_group_power_on_group(group);
+       mali_group_reset(group);
+
+       /* Pick up any jobs that might have been queued while the GP group was disabled. */
+       mali_gp_scheduler_schedule_internal_and_unlock();
+}
+
+void mali_gp_scheduler_disable_group(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT(slot.group == group);
+       MALI_DEBUG_PRINT(2, ("Mali GP scheduler: disabling gp group %p\n", group));
+
+       mali_gp_scheduler_suspend();
+       mali_group_lock(group);
+       mali_gp_scheduler_lock();
+
+       MALI_DEBUG_ASSERT(   MALI_GROUP_STATE_IDLE     == group->state
+                            || MALI_GROUP_STATE_DISABLED == group->state);
+
+       if (MALI_GROUP_STATE_DISABLED == group->state) {
+               MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_DISABLED == slot.state);
+               MALI_DEBUG_PRINT(2, ("Mali GP scheduler: gp group %p already disabled\n", group));
+       } else {
+               MALI_DEBUG_ASSERT(MALI_GP_SLOT_STATE_IDLE == slot.state);
+               slot.state = MALI_GP_SLOT_STATE_DISABLED;
+               group->state = MALI_GROUP_STATE_DISABLED;
+
+               mali_group_power_off_group(group, MALI_TRUE);
+       }
+
+       mali_gp_scheduler_unlock();
+       mali_group_unlock(group);
+       mali_gp_scheduler_resume();
+}
+
+static mali_scheduler_mask mali_gp_scheduler_queue_job(struct mali_gp_job *job)
+{
+       _mali_osk_list_t *queue = NULL;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+       struct mali_gp_job *iter, *tmp;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->session);
+
+       MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE, job->pid, job->tid, job->uargs.frame_builder_id, job->uargs.flush_id, 0);
+
+       job->cache_order = mali_scheduler_get_new_cache_order();
+
+       /* Determine which queue the job should be added to. */
+       if (job->session->use_high_priority_job_queue) {
+               queue = &job_queue_high;
+       } else {
+               queue = &job_queue;
+       }
+
+       /* Find position in queue where job should be added. */
+       _MALI_OSK_LIST_FOREACHENTRY_REVERSE(iter, tmp, queue, struct mali_gp_job, list) {
+               if (mali_gp_job_is_after(job, iter)) {
+                       break;
+               }
+       }
+
+       /* Add job to queue. */
+       _mali_osk_list_add(&job->list, &iter->list);
+
+       /* Set schedule bitmask if the GP core is idle. */
+       if (MALI_GP_SLOT_STATE_IDLE == slot.state) {
+               schedule_mask |= MALI_SCHEDULER_MASK_GP;
+       }
+
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+       trace_gpu_job_enqueue(mali_gp_job_get_tid(job), mali_gp_job_get_id(job), "GP");
+#endif
+
+       MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job));
+
+       return schedule_mask;
+}
+
+mali_scheduler_mask mali_gp_scheduler_activate_job(struct mali_gp_job *job)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->session);
+
+       MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Timeline activation for job %u (0x%08X).\n", mali_gp_job_get_id(job), job));
+
+       mali_gp_scheduler_lock();
+
+       if (unlikely(job->session->is_aborting)) {
+               /* Before checking if the session is aborting, the scheduler must be locked. */
+               MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock);
+
+               MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) activated while session is aborting.\n", mali_gp_job_get_id(job), job));
+
+               /* This job should not be on any list. */
+               MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list));
+
+               mali_gp_scheduler_unlock();
+
+               /* Release tracker and delete job. */
+               mali_timeline_tracker_release(&job->tracker);
+               mali_gp_job_signal_pp_tracker(job, MALI_FALSE);
+               mali_gp_job_delete(job);
+               mali_gp_scheduler_job_completed();
+
+               /* Since we are aborting we ignore the scheduler mask. */
+               return MALI_SCHEDULER_MASK_EMPTY;
+       }
+
+       /* GP job is ready to run, queue it. */
+       schedule_mask = mali_gp_scheduler_queue_job(job);
+
+       mali_gp_scheduler_unlock();
+
+       return schedule_mask;
+}
+
+static void mali_gp_scheduler_job_queued(void)
+{
+       /* We hold a PM reference for every job we hold queued (and running) */
+       _mali_osk_pm_dev_ref_add();
+
+       if (mali_utilization_enabled()) {
+               /*
+                * We cheat a little bit by counting the PP as busy from the time a GP job is queued.
+                * This will be fine because we only loose the tiny idle gap between jobs, but
+                * we will instead get less utilization work to do (less locks taken)
+                */
+               mali_utilization_gp_start();
+       }
+}
+
+static void mali_gp_scheduler_job_completed(void)
+{
+       /* Release the PM reference we got in the mali_gp_scheduler_job_queued() function */
+       _mali_osk_pm_dev_ref_dec();
+
+       if (mali_utilization_enabled()) {
+               mali_utilization_gp_end();
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h b/drivers/gpu/arm/mali400/mali/common/mali_gp_scheduler.h
new file mode 100755 (executable)
index 0000000..9a98f0a
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_GP_SCHEDULER_H__
+#define __MALI_GP_SCHEDULER_H__
+
+#include "mali_osk.h"
+#include "mali_gp_job.h"
+#include "mali_group.h"
+
+_mali_osk_errcode_t mali_gp_scheduler_initialize(void);
+void mali_gp_scheduler_terminate(void);
+
+void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success);
+void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job);
+u32 mali_gp_scheduler_dump_state(char *buf, u32 size);
+
+void mali_gp_scheduler_suspend(void);
+void mali_gp_scheduler_resume(void);
+
+/**
+ * @brief Abort all running and queued GP jobs from session.
+ *
+* This functions aborts all GP jobs from the specified session. Queued jobs are removed from the
+* queue and jobs currently running on a core will be aborted.
+ *
+ * @param session Session that is aborting.
+ */
+void mali_gp_scheduler_abort_session(struct mali_session_data *session);
+
+/**
+ * @brief Reset all groups
+ *
+ * This function resets all groups known by the GP scheuduler. This must be
+ * called after the Mali HW has been powered on in order to reset the HW.
+ */
+void mali_gp_scheduler_reset_all_groups(void);
+
+/**
+ * @brief Zap TLB on all groups with \a session active
+ *
+ * The scheculer will zap the session on all groups it owns.
+ */
+void mali_gp_scheduler_zap_all_active(struct mali_session_data *session);
+
+/**
+ * @brief Re-enable a group that has been disabled with mali_gp_scheduler_disable_group
+ *
+ * If a Mali PMU is present, the group will be powered back on and added back
+ * into the GP scheduler.
+ *
+ * @param group Pointer to the group to enable
+ */
+void mali_gp_scheduler_enable_group(struct mali_group *group);
+
+/**
+ * @brief Disable a group
+ *
+ * The group will be taken out of the GP scheduler and powered off, if a Mali
+ * PMU is present.
+ *
+ * @param group Pointer to the group to disable
+ */
+void mali_gp_scheduler_disable_group(struct mali_group *group);
+
+/**
+ * @brief Used by the Timeline system to queue a GP job.
+ *
+ * @note @ref mali_scheduler_schedule_from_mask() should be called if this function returns non-zero.
+ *
+ * @param job The GP job that is being activated.
+ *
+ * @return A scheduling bitmask that can be used to decide if scheduling is necessary after this
+ * call.
+ */
+mali_scheduler_mask mali_gp_scheduler_activate_job(struct mali_gp_job *job);
+
+/**
+ * @brief Schedule queued jobs on idle cores.
+ */
+void mali_gp_scheduler_schedule(void);
+
+/**
+ * @brief Submit a GP job to the GP scheduler.
+ *
+ * This will add the GP job to the Timeline system.
+ *
+ * @param session Session this job belongs to.
+ * @param job GP job that will be submitted
+ * @return Point on GP timeline for job.
+ */
+mali_timeline_point mali_gp_scheduler_submit_job(struct mali_session_data *session, struct mali_gp_job *job);
+
+#endif /* __MALI_GP_SCHEDULER_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_group.c b/drivers/gpu/arm/mali400/mali/common/mali_group.c
new file mode 100755 (executable)
index 0000000..050b551
--- /dev/null
@@ -0,0 +1,1859 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "mali_l2_cache.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_mmu.h"
+#include "mali_dlbu.h"
+#include "mali_broadcast.h"
+#include "mali_scheduler.h"
+#include "mali_osk_profiling.h"
+#include "mali_pm_domain.h"
+#include "mali_pm.h"
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+#include <linux/sched.h>
+#include <trace/events/gpu.h>
+#endif
+
+
+static void mali_group_bottom_half_mmu(void *data);
+static void mali_group_bottom_half_gp(void *data);
+static void mali_group_bottom_half_pp(void *data);
+
+static void mali_group_timeout(void *data);
+static void mali_group_reset_pp(struct mali_group *group);
+static void mali_group_reset_mmu(struct mali_group *group);
+
+#if defined(CONFIG_MALI400_PROFILING)
+static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num);
+#endif /* #if defined(CONFIG_MALI400_PROFILING) */
+
+/*
+ * The group object is the most important object in the device driver,
+ * and acts as the center of many HW operations.
+ * The reason for this is that operations on the MMU will affect all
+ * cores connected to this MMU (a group is defined by the MMU and the
+ * cores which are connected to this).
+ * The group lock is thus the most important lock, followed by the
+ * GP and PP scheduler locks. They must be taken in the following
+ * order:
+ * GP/PP lock first, then group lock(s).
+ */
+
+static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS] = { NULL, };
+static u32 mali_global_num_groups = 0;
+
+/* timer related */
+int mali_max_job_runtime = MALI_MAX_JOB_RUNTIME_DEFAULT;
+extern u32 mali_group_error;
+/* local helper functions */
+static void mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session);
+static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session);
+static void mali_group_recovery_reset(struct mali_group *group);
+static void mali_group_mmu_page_fault_and_unlock(struct mali_group *group);
+
+static void mali_group_post_process_job_pp(struct mali_group *group);
+static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend);
+
+void mali_group_lock(struct mali_group *group)
+{
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_lock(group->lock);
+#else
+       _mali_osk_spinlock_lock(group->lock);
+#endif
+       MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group));
+}
+
+void mali_group_unlock(struct mali_group *group)
+{
+       MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group));
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_unlock(group->lock);
+#else
+       _mali_osk_spinlock_unlock(group->lock);
+#endif
+}
+
+#ifdef DEBUG
+void mali_group_assert_locked(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+}
+#endif
+
+
+struct mali_group *mali_group_create(struct mali_l2_cache_core *core, struct mali_dlbu_core *dlbu, struct mali_bcast_unit *bcast)
+{
+       struct mali_group *group = NULL;
+
+       if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS) {
+               MALI_PRINT_ERROR(("Mali group: Too many group objects created\n"));
+               return NULL;
+       }
+
+       group = _mali_osk_calloc(1, sizeof(struct mali_group));
+       if (NULL != group) {
+               group->timeout_timer = _mali_osk_timer_init();
+
+               if (NULL != group->timeout_timer) {
+                       _mali_osk_lock_order_t order;
+                       _mali_osk_timer_setcallback(group->timeout_timer, mali_group_timeout, (void *)group);
+
+                       if (NULL != dlbu) {
+                               order = _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL;
+                       } else {
+                               order = _MALI_OSK_LOCK_ORDER_GROUP;
+                       }
+
+#ifdef MALI_UPPER_HALF_SCHEDULING
+                       group->lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, order);
+#else
+                       group->lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, order);
+#endif
+
+                       if (NULL != group->lock) {
+                               group->l2_cache_core[0] = core;
+                               group->session = NULL;
+                               group->power_is_on = MALI_TRUE;
+                               group->state = MALI_GROUP_STATE_IDLE;
+                               _mali_osk_list_init(&group->group_list);
+                               _mali_osk_list_init(&group->pp_scheduler_list);
+                               group->parent_group = NULL;
+                               group->l2_cache_core_ref_count[0] = 0;
+                               group->l2_cache_core_ref_count[1] = 0;
+                               group->bcast_core = bcast;
+                               group->dlbu_core = dlbu;
+
+                               mali_global_groups[mali_global_num_groups] = group;
+                               mali_global_num_groups++;
+
+                               return group;
+                       }
+                       _mali_osk_timer_term(group->timeout_timer);
+               }
+               _mali_osk_free(group);
+       }
+
+       return NULL;
+}
+
+_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core)
+{
+       /* This group object now owns the MMU core object */
+       group->mmu= mmu_core;
+       group->bottom_half_work_mmu = _mali_osk_wq_create_work(mali_group_bottom_half_mmu, group);
+       if (NULL == group->bottom_half_work_mmu) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_group_remove_mmu_core(struct mali_group *group)
+{
+       /* This group object no longer owns the MMU core object */
+       group->mmu = NULL;
+       if (NULL != group->bottom_half_work_mmu) {
+               _mali_osk_wq_delete_work(group->bottom_half_work_mmu);
+       }
+}
+
+_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core)
+{
+       /* This group object now owns the GP core object */
+       group->gp_core = gp_core;
+       group->bottom_half_work_gp = _mali_osk_wq_create_work(mali_group_bottom_half_gp, group);
+       if (NULL == group->bottom_half_work_gp) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_group_remove_gp_core(struct mali_group *group)
+{
+       /* This group object no longer owns the GP core object */
+       group->gp_core = NULL;
+       if (NULL != group->bottom_half_work_gp) {
+               _mali_osk_wq_delete_work(group->bottom_half_work_gp);
+       }
+}
+
+_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core)
+{
+       /* This group object now owns the PP core object */
+       group->pp_core = pp_core;
+       group->bottom_half_work_pp = _mali_osk_wq_create_work(mali_group_bottom_half_pp, group);
+       if (NULL == group->bottom_half_work_pp) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_group_remove_pp_core(struct mali_group *group)
+{
+       /* This group object no longer owns the PP core object */
+       group->pp_core = NULL;
+       if (NULL != group->bottom_half_work_pp) {
+               _mali_osk_wq_delete_work(group->bottom_half_work_pp);
+       }
+}
+
+void mali_group_set_pm_domain(struct mali_group *group, struct mali_pm_domain *domain)
+{
+       group->pm_domain = domain;
+}
+
+void mali_group_delete(struct mali_group *group)
+{
+       u32 i;
+
+       MALI_DEBUG_PRINT(4, ("Deleting group %p\n", group));
+
+       MALI_DEBUG_ASSERT(NULL == group->parent_group);
+
+       /* Delete the resources that this group owns */
+       if (NULL != group->gp_core) {
+               mali_gp_delete(group->gp_core);
+       }
+
+       if (NULL != group->pp_core) {
+               mali_pp_delete(group->pp_core);
+       }
+
+       if (NULL != group->mmu) {
+               mali_mmu_delete(group->mmu);
+       }
+
+       if (mali_group_is_virtual(group)) {
+               /* Remove all groups from virtual group */
+               struct mali_group *child;
+               struct mali_group *temp;
+
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                       child->parent_group = NULL;
+                       mali_group_delete(child);
+               }
+
+               mali_dlbu_delete(group->dlbu_core);
+
+               if (NULL != group->bcast_core) {
+                       mali_bcast_unit_delete(group->bcast_core);
+               }
+       }
+
+       for (i = 0; i < mali_global_num_groups; i++) {
+               if (mali_global_groups[i] == group) {
+                       mali_global_groups[i] = NULL;
+                       mali_global_num_groups--;
+
+                       if (i != mali_global_num_groups) {
+                               /* We removed a group from the middle of the array -- move the last
+                                * group to the current position to close the gap */
+                               mali_global_groups[i] = mali_global_groups[mali_global_num_groups];
+                               mali_global_groups[mali_global_num_groups] = NULL;
+                       }
+
+                       break;
+               }
+       }
+
+       if (NULL != group->timeout_timer) {
+               _mali_osk_timer_del(group->timeout_timer);
+               _mali_osk_timer_term(group->timeout_timer);
+       }
+
+       if (NULL != group->bottom_half_work_mmu) {
+               _mali_osk_wq_delete_work(group->bottom_half_work_mmu);
+       }
+
+       if (NULL != group->bottom_half_work_gp) {
+               _mali_osk_wq_delete_work(group->bottom_half_work_gp);
+       }
+
+       if (NULL != group->bottom_half_work_pp) {
+               _mali_osk_wq_delete_work(group->bottom_half_work_pp);
+       }
+
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_term(group->lock);
+#else
+       _mali_osk_spinlock_term(group->lock);
+#endif
+       _mali_osk_free(group);
+}
+
+MALI_DEBUG_CODE(static void mali_group_print_virtual(struct mali_group *vgroup)
+{
+       u32 i;
+       struct mali_group *group;
+       struct mali_group *temp;
+
+       MALI_DEBUG_PRINT(4, ("Virtual group %p\n", vgroup));
+       MALI_DEBUG_PRINT(4, ("l2_cache_core[0] = %p, ref = %d\n", vgroup->l2_cache_core[0], vgroup->l2_cache_core_ref_count[0]));
+       MALI_DEBUG_PRINT(4, ("l2_cache_core[1] = %p, ref = %d\n", vgroup->l2_cache_core[1], vgroup->l2_cache_core_ref_count[1]));
+
+       i = 0;
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &vgroup->group_list, struct mali_group, group_list) {
+               MALI_DEBUG_PRINT(4, ("[%d] %p, l2_cache_core[0] = %p\n", i, group, group->l2_cache_core[0]));
+               i++;
+       }
+})
+
+/**
+ * @brief Add child group to virtual group parent
+ *
+ * Before calling this function, child must have it's state set to JOINING_VIRTUAL
+ * to ensure it's not touched during the transition period. When this function returns,
+ * child's state will be IN_VIRTUAL.
+ */
+void mali_group_add_group(struct mali_group *parent, struct mali_group *child, mali_bool update_hw)
+{
+       mali_bool found;
+       u32 i;
+       struct mali_session_data *child_session;
+
+       MALI_DEBUG_PRINT(3, ("Adding group %p to virtual group %p\n", child, parent));
+
+       MALI_ASSERT_GROUP_LOCKED(parent);
+
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
+       MALI_DEBUG_ASSERT(!mali_group_is_virtual(child));
+       MALI_DEBUG_ASSERT(NULL == child->parent_group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_JOINING_VIRTUAL == child->state);
+
+       _mali_osk_list_addtail(&child->group_list, &parent->group_list);
+
+       child->state = MALI_GROUP_STATE_IN_VIRTUAL;
+       child->parent_group = parent;
+
+       MALI_DEBUG_ASSERT_POINTER(child->l2_cache_core[0]);
+
+       MALI_DEBUG_PRINT(4, ("parent->l2_cache_core: [0] = %p, [1] = %p\n", parent->l2_cache_core[0], parent->l2_cache_core[1]));
+       MALI_DEBUG_PRINT(4, ("child->l2_cache_core: [0] = %p, [1] = %p\n", child->l2_cache_core[0], child->l2_cache_core[1]));
+
+       /* Keep track of the L2 cache cores of child groups */
+       found = MALI_FALSE;
+       for (i = 0; i < 2; i++) {
+               if (parent->l2_cache_core[i] == child->l2_cache_core[0]) {
+                       MALI_DEBUG_ASSERT(parent->l2_cache_core_ref_count[i] > 0);
+                       parent->l2_cache_core_ref_count[i]++;
+                       found = MALI_TRUE;
+               }
+       }
+
+       if (!found) {
+               /* First time we see this L2 cache, add it to our list */
+               i = (NULL == parent->l2_cache_core[0]) ? 0 : 1;
+
+               MALI_DEBUG_PRINT(4, ("First time we see l2_cache %p. Adding to [%d] = %p\n", child->l2_cache_core[0], i, parent->l2_cache_core[i]));
+
+               MALI_DEBUG_ASSERT(NULL == parent->l2_cache_core[i]);
+
+               parent->l2_cache_core[i] = child->l2_cache_core[0];
+               parent->l2_cache_core_ref_count[i]++;
+       }
+
+       /* Update Broadcast Unit and DLBU */
+       mali_bcast_add_group(parent->bcast_core, child);
+       mali_dlbu_add_group(parent->dlbu_core, child);
+
+       child_session = child->session;
+       child->session = NULL;
+
+       /* Above this comment, only software state is updated and the HW is not
+        * touched. Now, check if Mali is powered and skip the rest if it isn't
+        * powered.
+        */
+
+       if (!update_hw) {
+               MALI_DEBUG_CODE(mali_group_print_virtual(parent));
+               return;
+       }
+
+       /* Update MMU */
+       if (parent->session == child_session) {
+               mali_mmu_zap_tlb(child->mmu);
+       } else {
+               if (NULL == parent->session) {
+                       mali_mmu_activate_empty_page_directory(child->mmu);
+               } else {
+                       mali_mmu_activate_page_directory(child->mmu, mali_session_get_page_directory(parent->session));
+               }
+       }
+
+       /* Update HW only if power is on */
+       mali_bcast_reset(parent->bcast_core);
+       mali_dlbu_update_mask(parent->dlbu_core);
+
+       /* Start job on child when parent is active */
+       if (NULL != parent->pp_running_job) {
+               struct mali_pp_job *job = parent->pp_running_job;
+               MALI_DEBUG_PRINT(3, ("Group %x joining running job %d on virtual group %x\n",
+                                    child, mali_pp_job_get_id(job), parent));
+               MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING == parent->state);
+               mali_pp_job_start(child->pp_core, job, mali_pp_core_get_id(child->pp_core), MALI_TRUE);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
+                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                             MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                             mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
+                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
+                                             mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
+       }
+
+       MALI_DEBUG_CODE(mali_group_print_virtual(parent);)
+}
+
+/**
+ * @brief Remove child group from virtual group parent
+ *
+ * After the child is removed, it's state will be LEAVING_VIRTUAL and must be set
+ * to IDLE before it can be used.
+ */
+void mali_group_remove_group(struct mali_group *parent, struct mali_group *child)
+{
+       u32 i;
+
+       MALI_ASSERT_GROUP_LOCKED(parent);
+
+       MALI_DEBUG_PRINT(3, ("Removing group %p from virtual group %p\n", child, parent));
+
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
+       MALI_DEBUG_ASSERT(!mali_group_is_virtual(child));
+       MALI_DEBUG_ASSERT(parent == child->parent_group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IN_VIRTUAL == child->state);
+       /* Removing groups while running is not yet supported. */
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == parent->state);
+
+       mali_group_lock(child);
+
+       /* Update Broadcast Unit and DLBU */
+       mali_bcast_remove_group(parent->bcast_core, child);
+       mali_dlbu_remove_group(parent->dlbu_core, child);
+
+       /* Update HW only if power is on */
+       if (mali_pm_is_power_on()) {
+               mali_bcast_reset(parent->bcast_core);
+               mali_dlbu_update_mask(parent->dlbu_core);
+       }
+
+       _mali_osk_list_delinit(&child->group_list);
+
+       child->session = parent->session;
+       child->parent_group = NULL;
+       child->state = MALI_GROUP_STATE_LEAVING_VIRTUAL;
+
+       /* Keep track of the L2 cache cores of child groups */
+       i = (child->l2_cache_core[0] == parent->l2_cache_core[0]) ? 0 : 1;
+
+       MALI_DEBUG_ASSERT(child->l2_cache_core[0] == parent->l2_cache_core[i]);
+
+       parent->l2_cache_core_ref_count[i]--;
+
+       if (parent->l2_cache_core_ref_count[i] == 0) {
+               parent->l2_cache_core[i] = NULL;
+       }
+
+       MALI_DEBUG_CODE(mali_group_print_virtual(parent));
+
+       mali_group_unlock(child);
+}
+
+struct mali_group *mali_group_acquire_group(struct mali_group *parent)
+{
+       struct mali_group *child;
+
+       MALI_ASSERT_GROUP_LOCKED(parent);
+
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
+       MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&parent->group_list));
+
+       child = _MALI_OSK_LIST_ENTRY(parent->group_list.prev, struct mali_group, group_list);
+
+       mali_group_remove_group(parent, child);
+
+       return child;
+}
+
+void mali_group_reset(struct mali_group *group)
+{
+       /*
+        * This function should not be used to abort jobs,
+        * currently only called during insmod and PM resume
+        */
+       MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+       MALI_DEBUG_ASSERT(NULL == group->gp_running_job);
+       MALI_DEBUG_ASSERT(NULL == group->pp_running_job);
+
+       group->session = NULL;
+
+       if (NULL != group->dlbu_core) {
+               mali_dlbu_reset(group->dlbu_core);
+       }
+
+       if (NULL != group->bcast_core) {
+               mali_bcast_reset(group->bcast_core);
+       }
+
+       if (NULL != group->mmu) {
+               mali_group_reset_mmu(group);
+       }
+
+       if (NULL != group->gp_core) {
+               mali_gp_reset(group->gp_core);
+       }
+
+       if (NULL != group->pp_core) {
+               mali_group_reset_pp(group);
+       }
+}
+
+struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group)
+{
+       return group->gp_core;
+}
+
+struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group)
+{
+       return group->pp_core;
+}
+
+void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job)
+{
+       struct mali_session_data *session;
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
+
+       session = mali_gp_job_get_session(job);
+
+       if (NULL != group->l2_cache_core[0]) {
+               mali_l2_cache_invalidate_conditional(group->l2_cache_core[0], mali_gp_job_get_cache_order(job));
+       }
+
+       mali_group_activate_page_directory(group, session);
+
+       mali_gp_job_start(group->gp_core, job);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
+                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) |
+                                     MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                     mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0);
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
+                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
+                                     mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0);
+#if defined(CONFIG_MALI400_PROFILING)
+       if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
+           (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
+               mali_group_report_l2_cache_counters_per_core(group, 0);
+#endif /* #if defined(CONFIG_MALI400_PROFILING) */
+
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+       trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(),
+                              mali_gp_job_get_pid(job), 0, mali_gp_job_get_id(job));
+#endif
+
+       group->gp_running_job = job;
+       group->state = MALI_GROUP_STATE_WORKING;
+
+       /* Setup the timeout timer value and save the job id for the job running on the gp core */
+       _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
+}
+
+void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job)
+{
+       struct mali_session_data *session;
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
+
+       session = mali_pp_job_get_session(job);
+
+       if (NULL != group->l2_cache_core[0]) {
+               mali_l2_cache_invalidate_conditional(group->l2_cache_core[0], mali_pp_job_get_cache_order(job));
+       }
+
+       if (NULL != group->l2_cache_core[1]) {
+               mali_l2_cache_invalidate_conditional(group->l2_cache_core[1], mali_pp_job_get_cache_order(job));
+       }
+
+       mali_group_activate_page_directory(group, session);
+
+       if (mali_group_is_virtual(group)) {
+               struct mali_group *child;
+               struct mali_group *temp;
+               u32 core_num = 0;
+
+               MALI_DEBUG_ASSERT( mali_pp_job_is_virtual(job));
+
+               /* Configure DLBU for the job */
+               mali_dlbu_config_job(group->dlbu_core, job);
+
+               /* Write stack address for each child group */
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                       mali_pp_write_addr_stack(child->pp_core, job);
+                       core_num++;
+               }
+
+               /* Try to use DMA unit to start job, fallback to writing directly to the core */
+               MALI_DEBUG_ASSERT(mali_dma_cmd_buf_is_valid(&job->dma_cmd_buf));
+               if (_MALI_OSK_ERR_OK != mali_dma_start(mali_dma_get_global_dma_core(), &job->dma_cmd_buf)) {
+                       mali_pp_job_start(group->pp_core, job, sub_job, MALI_FALSE);
+               }
+       } else {
+               mali_pp_job_start(group->pp_core, job, sub_job, MALI_FALSE);
+       }
+
+       /* if the group is virtual, loop through physical groups which belong to this group
+        * and call profiling events for its cores as virtual */
+       if (MALI_TRUE == mali_group_is_virtual(group)) {
+               struct mali_group *child;
+               struct mali_group *temp;
+
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                                     MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                                     mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
+
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
+                                                     mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
+               }
+#if defined(CONFIG_MALI400_PROFILING)
+               if (0 != group->l2_cache_core_ref_count[0]) {
+                       if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
+                           (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) {
+                               mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
+                       }
+               }
+               if (0 != group->l2_cache_core_ref_count[1]) {
+                       if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) &&
+                           (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1]))) {
+                               mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1]));
+                       }
+               }
+#endif /* #if defined(CONFIG_MALI400_PROFILING) */
+       } else { /* group is physical - call profiling events for physical cores */
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
+                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
+                                             MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+                                             mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
+                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL,
+                                             mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
+#if defined(CONFIG_MALI400_PROFILING)
+               if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
+                   (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) {
+                       mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
+               }
+#endif /* #if defined(CONFIG_MALI400_PROFILING) */
+       }
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+       trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), mali_pp_job_get_tid(job), 0, mali_pp_job_get_id(job));
+#endif
+       group->pp_running_job = job;
+       group->pp_running_sub_job = sub_job;
+       group->state = MALI_GROUP_STATE_WORKING;
+
+       /* Setup the timeout timer value and save the job id for the job running on the pp core */
+       _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
+}
+
+struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       if (group->state != MALI_GROUP_STATE_OOM ||
+           mali_gp_job_get_id(group->gp_running_job) != job_id) {
+               return NULL; /* Illegal request or job has already been aborted */
+       }
+
+       if (NULL != group->l2_cache_core[0]) {
+               mali_l2_cache_invalidate(group->l2_cache_core[0]);
+       }
+
+       mali_mmu_zap_tlb_without_stall(group->mmu);
+
+       mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0);
+
+       group->state = MALI_GROUP_STATE_WORKING;
+
+       return group->gp_running_job;
+}
+
+static void mali_group_reset_mmu(struct mali_group *group)
+{
+       struct mali_group *child;
+       struct mali_group *temp;
+       _mali_osk_errcode_t err;
+
+       if (!mali_group_is_virtual(group)) {
+               /* This is a physical group or an idle virtual group -- simply wait for
+                * the reset to complete. */
+               err = mali_mmu_reset(group->mmu);
+               MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err);
+       } else { /* virtual group */
+               err = mali_mmu_reset(group->mmu);
+               if (_MALI_OSK_ERR_OK == err) {
+                       return;
+               }
+
+               /* Loop through all members of this virtual group and wait
+                * until they are done resetting.
+                */
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                       err = mali_mmu_reset(child->mmu);
+                       MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err);
+               }
+       }
+}
+
+static void mali_group_reset_pp(struct mali_group *group)
+{
+       struct mali_group *child;
+       struct mali_group *temp;
+
+       mali_pp_reset_async(group->pp_core);
+
+       if (!mali_group_is_virtual(group) || NULL == group->pp_running_job) {
+               /* This is a physical group or an idle virtual group -- simply wait for
+                * the reset to complete. */
+               mali_pp_reset_wait(group->pp_core);
+       } else { /* virtual group */
+               /* Loop through all members of this virtual group and wait until they
+                * are done resetting.
+                */
+               _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                       mali_pp_reset_wait(child->pp_core);
+               }
+       }
+}
+
+/* Group must be locked when entering this function.  Will be unlocked before exiting. */
+static void mali_group_complete_pp_and_unlock(struct mali_group *group, mali_bool success, mali_bool in_upper_half)
+{
+       struct mali_pp_job *pp_job_to_return;
+       u32 pp_sub_job_to_return;
+
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_POINTER(group->pp_core);
+       MALI_DEBUG_ASSERT_POINTER(group->pp_running_job);
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       mali_group_post_process_job_pp(group);
+
+       if (success) {
+               /* Only do soft reset for successful jobs, a full recovery
+                * reset will be done for failed jobs. */
+               mali_pp_reset_async(group->pp_core);
+       }
+
+       pp_job_to_return = group->pp_running_job;
+       pp_sub_job_to_return = group->pp_running_sub_job;
+       group->state = MALI_GROUP_STATE_IDLE;
+       group->pp_running_job = NULL;
+
+       if (!success) {
+               MALI_DEBUG_PRINT(2, ("Mali group: Executing recovery reset due to job failure\n"));
+               mali_group_recovery_reset(group);
+       } else if (_MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core)) {
+               MALI_PRINT_ERROR(("Mali group: Executing recovery reset due to reset failure\n"));
+               mali_group_recovery_reset(group);
+       }
+
+       /* Return job to user, schedule and unlock group. */
+       mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, success, in_upper_half);
+}
+
+/* Group must be locked when entering this function.  Will be unlocked before exiting. */
+static void mali_group_complete_gp_and_unlock(struct mali_group *group, mali_bool success)
+{
+       struct mali_gp_job *gp_job_to_return;
+
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_POINTER(group->gp_core);
+       MALI_DEBUG_ASSERT_POINTER(group->gp_running_job);
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       mali_group_post_process_job_gp(group, MALI_FALSE);
+
+       if (success) {
+               /* Only do soft reset for successful jobs, a full recovery
+                * reset will be done for failed jobs. */
+               mali_gp_reset_async(group->gp_core);
+       }
+
+       gp_job_to_return = group->gp_running_job;
+       group->state = MALI_GROUP_STATE_IDLE;
+       group->gp_running_job = NULL;
+
+       if (!success) {
+               MALI_DEBUG_PRINT(2, ("Mali group: Executing recovery reset due to job failure\n"));
+               mali_group_recovery_reset(group);
+       } else if (_MALI_OSK_ERR_OK != mali_gp_reset_wait(group->gp_core)) {
+               MALI_PRINT_ERROR(("Mali group: Executing recovery reset due to reset failure\n"));
+               mali_group_recovery_reset(group);
+       }
+
+       /* Return job to user, schedule and unlock group. */
+       mali_gp_scheduler_job_done(group, gp_job_to_return, success);
+}
+
+void mali_group_abort_gp_job(struct mali_group *group, u32 job_id)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       if (MALI_GROUP_STATE_IDLE == group->state ||
+           mali_gp_job_get_id(group->gp_running_job) != job_id) {
+               return; /* No need to cancel or job has already been aborted or completed */
+       }
+
+       /* Function will unlock the group, so we need to lock it again */
+       mali_group_complete_gp_and_unlock(group, MALI_FALSE);
+       mali_group_lock(group);
+}
+
+static void mali_group_abort_pp_job(struct mali_group *group, u32 job_id)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       if (MALI_GROUP_STATE_IDLE == group->state ||
+           mali_pp_job_get_id(group->pp_running_job) != job_id) {
+               return; /* No need to cancel or job has already been aborted or completed */
+       }
+
+       mali_group_complete_pp_and_unlock(group, MALI_FALSE, MALI_FALSE);
+       mali_group_lock(group);
+}
+
+void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session)
+{
+       struct mali_gp_job *gp_job;
+       struct mali_pp_job *pp_job;
+       u32 gp_job_id = 0;
+       u32 pp_job_id = 0;
+       mali_bool abort_pp = MALI_FALSE;
+       mali_bool abort_gp = MALI_FALSE;
+
+       mali_group_lock(group);
+
+       if (mali_group_is_in_virtual(group)) {
+               /* Group is member of a virtual group, don't touch it! */
+               mali_group_unlock(group);
+               return;
+       }
+
+       gp_job = group->gp_running_job;
+       pp_job = group->pp_running_job;
+
+       if ((NULL != gp_job) && (mali_gp_job_get_session(gp_job) == session)) {
+               MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session));
+
+               gp_job_id = mali_gp_job_get_id(gp_job);
+               abort_gp = MALI_TRUE;
+       }
+
+       if ((NULL != pp_job) && (mali_pp_job_get_session(pp_job) == session)) {
+               MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session));
+
+               pp_job_id = mali_pp_job_get_id(pp_job);
+               abort_pp = MALI_TRUE;
+       }
+
+       if (abort_gp) {
+               mali_group_abort_gp_job(group, gp_job_id);
+       }
+       if (abort_pp) {
+               mali_group_abort_pp_job(group, pp_job_id);
+       }
+
+       mali_group_remove_session_if_unused(group, session);
+
+       mali_group_unlock(group);
+}
+
+struct mali_group *mali_group_get_glob_group(u32 index)
+{
+       if(mali_global_num_groups > index) {
+               return mali_global_groups[index];
+       }
+
+       return NULL;
+}
+
+u32 mali_group_get_glob_num_groups(void)
+{
+       return mali_global_num_groups;
+}
+
+static void mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group));
+
+       if (group->session != session) {
+               /* Different session than last time, so we need to do some work */
+               MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X\n", session, group->session, group));
+               mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session));
+               group->session = session;
+       } else {
+               /* Same session as last time, so no work required */
+               MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X\n", session->page_directory, group));
+               mali_mmu_zap_tlb_without_stall(group->mmu);
+       }
+}
+
+static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       if (MALI_GROUP_STATE_IDLE == group->state) {
+               if (group->session == session) {
+                       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING != group->state);
+                       MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on);
+                       MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group));
+                       mali_mmu_activate_empty_page_directory(group->mmu);
+                       group->session = NULL;
+               }
+       }
+}
+
+mali_bool mali_group_power_is_on(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+       return group->power_is_on;
+}
+
+void mali_group_power_on_group(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+       MALI_DEBUG_ASSERT(   MALI_GROUP_STATE_IDLE       == group->state
+                            || MALI_GROUP_STATE_IN_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_JOINING_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_DISABLED   == group->state);
+
+       MALI_DEBUG_PRINT(3, ("Group %p powered on\n", group));
+
+       group->power_is_on = MALI_TRUE;
+}
+
+void mali_group_power_off_group(struct mali_group *group, mali_bool do_power_change)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+       MALI_DEBUG_ASSERT(   MALI_GROUP_STATE_IDLE       == group->state
+                            || MALI_GROUP_STATE_IN_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_JOINING_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_DISABLED   == group->state);
+
+       MALI_DEBUG_PRINT(3, ("Group %p powered off\n", group));
+
+       /* It is necessary to set group->session = NULL so that the powered off MMU is not written
+        * to on map/unmap.  It is also necessary to set group->power_is_on = MALI_FALSE so that
+        * pending bottom_halves does not access powered off cores. */
+
+       group->session = NULL;
+
+       if (do_power_change) {
+               group->power_is_on = MALI_FALSE;
+       }
+}
+
+void mali_group_power_on(void)
+{
+       int i;
+       for (i = 0; i < mali_global_num_groups; i++) {
+               struct mali_group *group = mali_global_groups[i];
+
+               mali_group_lock(group);
+               if (MALI_GROUP_STATE_DISABLED == group->state) {
+                       MALI_DEBUG_ASSERT(MALI_FALSE == group->power_is_on);
+               } else {
+                       mali_group_power_on_group(group);
+               }
+               mali_group_unlock(group);
+       }
+       MALI_DEBUG_PRINT(4, ("Mali Group: power on\n"));
+}
+
+void mali_group_power_off(mali_bool do_power_change)
+{
+       int i;
+
+       for (i = 0; i < mali_global_num_groups; i++) {
+               struct mali_group *group = mali_global_groups[i];
+
+               mali_group_lock(group);
+               if (MALI_GROUP_STATE_DISABLED == group->state) {
+                       MALI_DEBUG_ASSERT(MALI_FALSE == group->power_is_on);
+               } else {
+                       mali_group_power_off_group(group, do_power_change);
+               }
+               mali_group_unlock(group);
+       }
+       MALI_DEBUG_PRINT(4, ("Mali Group: power off\n"));
+}
+
+static void mali_group_recovery_reset(struct mali_group *group)
+{
+       _mali_osk_errcode_t err;
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       /* Stop cores, bus stop */
+       if (NULL != group->pp_core) {
+               mali_pp_stop_bus(group->pp_core);
+       } else {
+               mali_gp_stop_bus(group->gp_core);
+       }
+
+       /* Flush MMU and clear page fault (if any) */
+       mali_mmu_activate_fault_flush_page_directory(group->mmu);
+       mali_mmu_page_fault_done(group->mmu);
+
+       /* Wait for cores to stop bus, then do a hard reset on them */
+       if (NULL != group->pp_core) {
+               if (mali_group_is_virtual(group)) {
+                       struct mali_group *child, *temp;
+
+                       /* Disable the broadcast unit while we do reset directly on the member cores. */
+                       mali_bcast_disable(group->bcast_core);
+
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                               mali_pp_stop_bus_wait(child->pp_core);
+                               mali_pp_hard_reset(child->pp_core);
+                       }
+
+                       mali_bcast_enable(group->bcast_core);
+               } else {
+                       mali_pp_stop_bus_wait(group->pp_core);
+                       mali_pp_hard_reset(group->pp_core);
+               }
+       } else {
+               mali_gp_stop_bus_wait(group->gp_core);
+               mali_gp_hard_reset(group->gp_core);
+       }
+
+       /* Reset MMU */
+       err = mali_mmu_reset(group->mmu);
+       MALI_DEBUG_ASSERT(_MALI_OSK_ERR_OK == err);
+       MALI_IGNORE(err);
+
+       group->session = NULL;
+}
+
+#if MALI_STATE_TRACKING
+u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size)
+{
+       int n = 0;
+
+       n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group);
+       n += _mali_osk_snprintf(buf + n, size - n, "\tstate: %d\n", group->state);
+       if (group->gp_core) {
+               n += mali_gp_dump_state(group->gp_core, buf + n, size - n);
+               n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job);
+       }
+       if (group->pp_core) {
+               n += mali_pp_dump_state(group->pp_core, buf + n, size - n);
+               n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n",
+                                       group->pp_running_job, group->pp_running_sub_job);
+       }
+
+       return n;
+}
+#endif
+
+/* Group must be locked when entering this function.  Will be unlocked before exiting. */
+static void mali_group_mmu_page_fault_and_unlock(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       if (NULL != group->pp_core) {
+               struct mali_pp_job *pp_job_to_return;
+               u32 pp_sub_job_to_return;
+
+               MALI_DEBUG_ASSERT_POINTER(group->pp_running_job);
+
+               mali_group_post_process_job_pp(group);
+
+               pp_job_to_return = group->pp_running_job;
+               pp_sub_job_to_return = group->pp_running_sub_job;
+               group->state = MALI_GROUP_STATE_IDLE;
+               group->pp_running_job = NULL;
+
+               mali_group_recovery_reset(group); /* This will also clear the page fault itself */
+
+               /* Will unlock group. */
+               mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, MALI_FALSE, MALI_FALSE);
+       } else {
+               struct mali_gp_job *gp_job_to_return;
+
+               MALI_DEBUG_ASSERT_POINTER(group->gp_running_job);
+
+               mali_group_post_process_job_gp(group, MALI_FALSE);
+
+               gp_job_to_return = group->gp_running_job;
+               group->state = MALI_GROUP_STATE_IDLE;
+               group->gp_running_job = NULL;
+
+               mali_group_recovery_reset(group); /* This will also clear the page fault itself */
+
+               /* Will unlock group. */
+               mali_gp_scheduler_job_done(group, gp_job_to_return, MALI_FALSE);
+       }
+}
+
+_mali_osk_errcode_t mali_group_upper_half_mmu(void * data)
+{
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_mmu_core *mmu = group->mmu;
+       u32 int_stat;
+
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) {
+               goto out;
+       }
+#endif
+
+       /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
+       int_stat = mali_mmu_get_int_status(mmu);
+       if (0 != int_stat) {
+               struct mali_group *parent = group->parent_group;
+
+               /* page fault or bus error, we thread them both in the same way */
+               mali_mmu_mask_all_interrupts(mmu);
+               if (NULL == parent) {
+                       _mali_osk_wq_schedule_work(group->bottom_half_work_mmu);
+               } else {
+                       _mali_osk_wq_schedule_work(parent->bottom_half_work_mmu);
+               }
+               err = _MALI_OSK_ERR_OK;
+               goto out;
+       }
+
+out:
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       mali_pm_domain_unlock_state(group->pm_domain);
+#endif
+
+       return err;
+}
+
+static void mali_group_bottom_half_mmu(void * data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_mmu_core *mmu = group->mmu;
+       u32 rawstat;
+       MALI_DEBUG_CODE(u32 status);
+
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+       mali_group_lock(group);
+
+       MALI_DEBUG_ASSERT(NULL == group->parent_group);
+
+       if ( MALI_FALSE == mali_group_power_is_on(group) ) {
+               MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mmu->hw_core.description));
+               mali_group_unlock(group);
+               return;
+       }
+
+       rawstat = mali_mmu_get_rawstat(mmu);
+       MALI_DEBUG_CODE(status = mali_mmu_get_status(mmu));
+
+       MALI_DEBUG_PRINT(4, ("Mali MMU: Bottom half, interrupt 0x%08X, status 0x%08X\n", rawstat, status));
+
+       if (rawstat & (MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR)) {
+               /* An actual page fault has occurred. */
+#ifdef DEBUG
+               u32 fault_address = mali_mmu_get_page_fault_addr(mmu);
+               MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n",
+                                   (void*)fault_address,
+                                   (status >> 6) & 0x1F,
+                                   (status & 32) ? "write" : "read",
+                                   mmu->hw_core.description));
+#endif
+
+               mali_group_mmu_page_fault_and_unlock(group);
+               return;
+       }
+
+       mali_group_unlock(group);
+}
+
+_mali_osk_errcode_t mali_group_upper_half_gp(void *data)
+{
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_gp_core *core = group->gp_core;
+       u32 irq_readout;
+
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) {
+               goto out;
+       }
+#endif
+
+       irq_readout = mali_gp_get_int_stat(core);
+
+       if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout) {
+               /* Mask out all IRQs from this core until IRQ is handled */
+               mali_gp_mask_all_interrupts(core);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
+
+               /* We do need to handle this in a bottom half */
+               _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
+
+               err = _MALI_OSK_ERR_OK;
+               goto out;
+       }
+
+out:
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       mali_pm_domain_unlock_state(group->pm_domain);
+#endif
+
+       return err;
+}
+
+static void mali_group_bottom_half_gp(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       u32 irq_readout;
+       u32 irq_errors;
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0);
+
+       mali_group_lock(group);
+
+       if ( MALI_FALSE == mali_group_power_is_on(group) ) {
+               MALI_PRINT_ERROR(("Mali group: Interrupt bottom half of %s when core is OFF.", mali_gp_get_hw_core_desc(group->gp_core)));
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       irq_readout = mali_gp_read_rawstat(group->gp_core);
+
+       MALI_DEBUG_PRINT(4, ("Mali group: GP bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core)));
+
+       if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST)) {
+               u32 core_status = mali_gp_read_core_status(group->gp_core);
+               if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) {
+                       MALI_DEBUG_PRINT(4, ("Mali group: GP job completed, calling group handler\n"));
+                       group->core_timed_out = MALI_FALSE;
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                                     0, _mali_osk_get_tid(), 0, 0, 0);
+
+                       mali_group_complete_gp_and_unlock(group, MALI_TRUE);
+                       return;
+               }
+       }
+
+       /*
+        * Now lets look at the possible error cases (IRQ indicating error or timeout)
+        * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error.
+        */
+       irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM);
+       if (0 != irq_errors) {
+               MALI_PRINT_ERROR(("Mali group: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core)));
+               group->core_timed_out = MALI_FALSE;
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+
+               mali_group_complete_gp_and_unlock(group, MALI_FALSE);
+               mali_group_error++;
+               return;
+       } else if (group->core_timed_out) { /* SW timeout */
+               group->core_timed_out = MALI_FALSE;
+               if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->gp_running_job) {
+                       MALI_PRINT(("Mali group: Job %d timed out\n", mali_gp_job_get_id(group->gp_running_job)));
+
+                       mali_group_complete_gp_and_unlock(group, MALI_FALSE);
+                       mali_group_error++;
+                       return;
+               }
+       } else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) {
+               /* GP wants more memory in order to continue. */
+               MALI_DEBUG_PRINT(3, ("Mali group: PLBU needs more heap memory\n"));
+
+               group->state = MALI_GROUP_STATE_OOM;
+               mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */
+               mali_gp_scheduler_oom(group, group->gp_running_job);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       /*
+        * The only way to get here is if we only got one of two needed END_CMD_LST
+        * interrupts. Enable all but not the complete interrupt that has been
+        * received and continue to run.
+        */
+       mali_gp_enable_interrupts(group->gp_core, irq_readout & (MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST));
+       mali_group_unlock(group);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
+}
+
+static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend)
+{
+       /* Stop the timeout timer. */
+       _mali_osk_timer_del_async(group->timeout_timer);
+
+       if (NULL == group->gp_running_job) {
+               /* Nothing to do */
+               return;
+       }
+
+       mali_gp_update_performance_counters(group->gp_core, group->gp_running_job, suspend);
+
+#if defined(CONFIG_MALI400_PROFILING)
+       if (suspend) {
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
+                                             mali_gp_job_get_perf_counter_value0(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_value1(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8),
+                                             0, 0);
+       } else {
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
+                                             mali_gp_job_get_perf_counter_value0(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_value1(group->gp_running_job),
+                                             mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8),
+                                             0, 0);
+
+               if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
+                   (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
+                       mali_group_report_l2_cache_counters_per_core(group, 0);
+       }
+#endif
+
+       mali_gp_job_set_current_heap_addr(group->gp_running_job,
+                                         mali_gp_read_plbu_alloc_start_addr(group->gp_core));
+}
+
+_mali_osk_errcode_t mali_group_upper_half_pp(void *data)
+{
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_pp_core *core = group->pp_core;
+       u32 irq_readout;
+
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       if (MALI_FALSE == mali_pm_domain_lock_state(group->pm_domain)) {
+               goto out;
+       }
+#endif
+
+       /*
+        * For Mali-450 there is one particular case we need to watch out for:
+        *
+        * Criteria 1) this function call can be due to a shared interrupt,
+        * and not necessary because this core signaled an interrupt.
+        * Criteria 2) this core is a part of a virtual group, and thus it should
+        * not do any post processing.
+        * Criteria 3) this core has actually indicated that is has completed by
+        * having set raw_stat/int_stat registers to != 0
+        *
+        * If all this criteria is meet, then we could incorrectly start post
+        * processing on the wrong group object (this should only happen on the
+        * parent group)
+        */
+#if !defined(MALI_UPPER_HALF_SCHEDULING)
+       if (mali_group_is_in_virtual(group)) {
+               /*
+                * This check is done without the group lock held, which could lead to
+                * a potential race. This is however ok, since we will safely re-check
+                * this with the group lock held at a later stage. This is just an
+                * early out which will strongly benefit shared IRQ systems.
+                */
+               err = _MALI_OSK_ERR_OK;
+               goto out;
+       }
+#endif
+
+       irq_readout = mali_pp_get_int_stat(core);
+       if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) {
+               /* Mask out all IRQs from this core until IRQ is handled */
+               mali_pp_mask_all_interrupts(core);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               /* Currently no support for this interrupt event for the virtual PP core */
+               if (!mali_group_is_virtual(group)) {
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) |
+                                                     MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT,
+                                                     irq_readout, 0, 0, 0, 0);
+               }
+#endif
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+               /* Check if job is complete without errors */
+               if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout) {
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                     0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+
+                       MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler from upper half\n"));
+
+                       mali_group_lock(group);
+
+                       /* Check if job is complete without errors, again, after taking the group lock */
+                       irq_readout = mali_pp_read_rawstat(core);
+                       if (MALI200_REG_VAL_IRQ_END_OF_FRAME != irq_readout) {
+                               mali_pp_enable_interrupts(core);
+                               mali_group_unlock(group);
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                             0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+                               err = _MALI_OSK_ERR_OK;
+                               goto out;
+                       }
+
+                       if (mali_group_is_virtual(group)) {
+                               u32 status_readout = mali_pp_read_status(group->pp_core);
+                               if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE) {
+                                       MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n"));
+                                       mali_pp_enable_interrupts(core);
+                                       mali_group_unlock(group);
+                                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                                     0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+                                       err = _MALI_OSK_ERR_OK;
+                                       goto out;
+                               }
+                       }
+
+                       if (mali_group_is_in_virtual(group)) {
+                               /* We're member of a virtual group, so interrupt should be handled by the virtual group */
+                               mali_pp_enable_interrupts(core);
+                               mali_group_unlock(group);
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                             0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+                               err =  _MALI_OSK_ERR_FAULT;
+                               goto out;
+                       }
+
+                       group->core_timed_out = MALI_FALSE;
+
+                       mali_group_complete_pp_and_unlock(group, MALI_TRUE, MALI_TRUE);
+
+                       /* No need to enable interrupts again, since the core will be reset while completing the job */
+
+                       MALI_DEBUG_PRINT(6, ("Mali PP: Upper half job done\n"));
+
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+                                                     0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+
+                       err = _MALI_OSK_ERR_OK;
+                       goto out;
+               }
+#endif
+
+               /* We do need to handle this in a bottom half */
+               _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
+               err = _MALI_OSK_ERR_OK;
+               goto out;
+       }
+
+out:
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       mali_pm_domain_unlock_state(group->pm_domain);
+#endif
+
+       return err;
+}
+
+static void mali_group_bottom_half_pp(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+       struct mali_pp_core *core = group->pp_core;
+       u32 irq_readout;
+       u32 irq_errors;
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
+                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                     0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+
+       mali_group_lock(group);
+
+       if (mali_group_is_in_virtual(group)) {
+               /* We're member of a virtual group, so interrupt should be handled by the virtual group */
+               mali_pp_enable_interrupts(core);
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       if ( MALI_FALSE == mali_group_power_is_on(group) ) {
+               MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mali_pp_get_hw_core_desc(core)));
+               mali_group_unlock(group);
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               return;
+       }
+
+       irq_readout = mali_pp_read_rawstat(group->pp_core);
+
+       MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
+
+       /* Check if job is complete without errors */
+       if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout) {
+               if (mali_group_is_virtual(group)) {
+                       u32 status_readout = mali_pp_read_status(group->pp_core);
+
+                       if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE && !group->core_timed_out) {
+                               MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n"));
+                               mali_pp_enable_interrupts(core);
+                               mali_group_unlock(group);
+
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                                             0, _mali_osk_get_tid(), 0, 0, 0);
+                               return;
+                       }
+               }
+
+               if (!group->core_timed_out) {
+                       MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n"));
+                       group->core_timed_out = MALI_FALSE;
+
+                       mali_group_complete_pp_and_unlock(group, MALI_TRUE, MALI_FALSE);
+
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                                     0, _mali_osk_get_tid(), 0, 0, 0);
+                       return;
+               }
+       }
+
+       /*
+        * Now lets look at the possible error cases (IRQ indicating error or timeout)
+        * END_OF_FRAME and HANG interrupts are not considered error.
+        */
+       irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG);
+       if (0 != irq_errors) {
+               MALI_PRINT_ERROR(("Mali PP: Unexpected interrupt 0x%08X from core %s, aborting job\n",
+                                 irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
+               group->core_timed_out = MALI_FALSE;
+
+               mali_group_complete_pp_and_unlock(group, MALI_FALSE, MALI_FALSE);
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               mali_group_error++;
+               return;
+       } else if (group->core_timed_out) { /* SW timeout */
+               group->core_timed_out = MALI_FALSE;
+               if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->pp_running_job) {
+                       MALI_PRINT(("Mali PP: Job %d timed out on core %s\n",
+                                   mali_pp_job_get_id(group->pp_running_job), mali_pp_get_hw_core_desc(core)));
+
+                       mali_group_complete_pp_and_unlock(group, MALI_FALSE, MALI_FALSE);
+               } else {
+                       mali_group_unlock(group);
+               }
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                             0, _mali_osk_get_tid(), 0, 0, 0);
+               mali_group_error++;
+               return;
+       }
+
+       /*
+        * We should never get here, re-enable interrupts and continue
+        */
+       if (0 == irq_readout) {
+               MALI_DEBUG_PRINT(3, ("Mali group: No interrupt found on core %s\n",
+                                    mali_pp_get_hw_core_desc(group->pp_core)));
+       } else {
+               MALI_PRINT_ERROR(("Mali group: Unhandled PP interrupt 0x%08X on %s\n", irq_readout,
+                                 mali_pp_get_hw_core_desc(group->pp_core)));
+       }
+       mali_pp_enable_interrupts(core);
+       mali_group_unlock(group);
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+                                     MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                     MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+                                     0, _mali_osk_get_tid(), 0, 0, 0);
+}
+
+static void mali_group_post_process_job_pp(struct mali_group *group)
+{
+       MALI_ASSERT_GROUP_LOCKED(group);
+
+       /* Stop the timeout timer. */
+       _mali_osk_timer_del_async(group->timeout_timer);
+
+       if (NULL != group->pp_running_job) {
+               if (MALI_TRUE == mali_group_is_virtual(group)) {
+                       struct mali_group *child;
+                       struct mali_group *temp;
+
+                       /* update performance counters from each physical pp core within this virtual group */
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                               mali_pp_update_performance_counters(group->pp_core, child->pp_core, group->pp_running_job, mali_pp_core_get_id(child->pp_core));
+                       }
+
+#if defined(CONFIG_MALI400_PROFILING)
+                       /* send profiling data per physical core */
+                       _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list) {
+                               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
+                                                             MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
+                                                             MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
+                                                             mali_pp_job_get_perf_counter_value0(group->pp_running_job, mali_pp_core_get_id(child->pp_core)),
+                                                             mali_pp_job_get_perf_counter_value1(group->pp_running_job, mali_pp_core_get_id(child->pp_core)),
+                                                             mali_pp_job_get_perf_counter_src0(group->pp_running_job, group->pp_running_sub_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job, group->pp_running_sub_job) << 8),
+                                                             0, 0);
+                       }
+                       if (0 != group->l2_cache_core_ref_count[0]) {
+                               if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
+                                   (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) {
+                                       mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
+                               }
+                       }
+                       if (0 != group->l2_cache_core_ref_count[1]) {
+                               if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) &&
+                                   (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1]))) {
+                                       mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1]));
+                               }
+                       }
+
+#endif
+               } else {
+                       /* update performance counters for a physical group's pp core */
+                       mali_pp_update_performance_counters(group->pp_core, group->pp_core, group->pp_running_job, group->pp_running_sub_job);
+
+#if defined(CONFIG_MALI400_PROFILING)
+                       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
+                                                     MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
+                                                     MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL,
+                                                     mali_pp_job_get_perf_counter_value0(group->pp_running_job, group->pp_running_sub_job),
+                                                     mali_pp_job_get_perf_counter_value1(group->pp_running_job, group->pp_running_sub_job),
+                                                     mali_pp_job_get_perf_counter_src0(group->pp_running_job, group->pp_running_sub_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job, group->pp_running_sub_job) << 8),
+                                                     0, 0);
+
+                       if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
+                           (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0]))) {
+                               mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
+                       }
+#endif
+               }
+       }
+}
+
+static void mali_group_timeout(void *data)
+{
+       struct mali_group *group = (struct mali_group *)data;
+
+       group->core_timed_out = MALI_TRUE;
+
+       if (NULL != group->gp_core) {
+               MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_gp_get_hw_core_desc(group->gp_core)));
+               _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
+       } else {
+               MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_pp_get_hw_core_desc(group->pp_core)));
+               _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
+       }
+}
+
+void mali_group_zap_session(struct mali_group *group, struct mali_session_data *session)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       /* Early out - safe even if mutex is not held */
+       if (group->session != session) return;
+
+       mali_group_lock(group);
+
+       mali_group_remove_session_if_unused(group, session);
+
+       if (group->session == session) {
+               /* The Zap also does the stall and disable_stall */
+               mali_bool zap_success = mali_mmu_zap_tlb(group->mmu);
+               if (MALI_TRUE != zap_success) {
+                       MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n"));
+
+                       mali_group_mmu_page_fault_and_unlock(group);
+                       return;
+               }
+       }
+
+       mali_group_unlock(group);
+}
+
+#if defined(CONFIG_MALI400_PROFILING)
+static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num)
+{
+       u32 source0 = 0;
+       u32 value0 = 0;
+       u32 source1 = 0;
+       u32 value1 = 0;
+       u32 profiling_channel = 0;
+
+       switch(core_num) {
+       case 0:
+               profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
+                                   MALI_PROFILING_EVENT_CHANNEL_GPU |
+                                   MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS;
+               break;
+       case 1:
+               profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
+                                   MALI_PROFILING_EVENT_CHANNEL_GPU |
+                                   MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS;
+               break;
+       case 2:
+               profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
+                                   MALI_PROFILING_EVENT_CHANNEL_GPU |
+                                   MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS;
+               break;
+       default:
+               profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
+                                   MALI_PROFILING_EVENT_CHANNEL_GPU |
+                                   MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS;
+               break;
+       }
+
+       if (0 == core_num) {
+               mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1);
+       }
+       if (1 == core_num) {
+               if (1 == mali_l2_cache_get_id(group->l2_cache_core[0])) {
+                       mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1);
+               } else if (1 == mali_l2_cache_get_id(group->l2_cache_core[1])) {
+                       mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1);
+               }
+       }
+       if (2 == core_num) {
+               if (2 == mali_l2_cache_get_id(group->l2_cache_core[0])) {
+                       mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1);
+               } else if (2 == mali_l2_cache_get_id(group->l2_cache_core[1])) {
+                       mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1);
+               }
+       }
+
+       _mali_osk_profiling_add_event(profiling_channel, source1 << 8 | source0, value0, value1, 0, 0);
+}
+#endif /* #if defined(CONFIG_MALI400_PROFILING) */
+
+mali_bool mali_group_is_enabled(struct mali_group *group)
+{
+       mali_bool enabled = MALI_TRUE;
+
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       mali_group_lock(group);
+       if (MALI_GROUP_STATE_DISABLED == group->state) {
+               enabled = MALI_FALSE;
+       }
+       mali_group_unlock(group);
+
+       return enabled;
+}
+
+void mali_group_enable(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT(   NULL != mali_group_get_pp_core(group)
+                            || NULL != mali_group_get_gp_core(group));
+
+       if (NULL != mali_group_get_pp_core(group)) {
+               mali_pp_scheduler_enable_group(group);
+       } else {
+               mali_gp_scheduler_enable_group(group);
+       }
+}
+
+void mali_group_disable(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+       MALI_DEBUG_ASSERT(   NULL != mali_group_get_pp_core(group)
+                            || NULL != mali_group_get_gp_core(group));
+
+       if (NULL != mali_group_get_pp_core(group)) {
+               mali_pp_scheduler_disable_group(group);
+       } else {
+               mali_gp_scheduler_disable_group(group);
+       }
+}
+
+static struct mali_pm_domain* mali_group_get_l2_domain(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT(NULL == group->l2_cache_core[1]);
+
+       /* l2_cache_core[0] stores the related l2 domain */
+       return group->l2_cache_core[0]->pm_domain;
+}
+
+void mali_group_get_pm_domain_ref(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       /* Get group used l2 domain ref */
+       mali_pm_domain_ref_get(mali_group_get_l2_domain(group));
+       /* Get group used core domain ref */
+       mali_pm_domain_ref_get(group->pm_domain);
+}
+
+void mali_group_put_pm_domain_ref(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       /* Put group used core domain ref */
+       mali_pm_domain_ref_put(group->pm_domain);
+       /* Put group used l2 domain ref */
+       mali_pm_domain_ref_put(mali_group_get_l2_domain(group));
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_group.h b/drivers/gpu/arm/mali400/mali/common/mali_group.h
new file mode 100755 (executable)
index 0000000..ba86796
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_GROUP_H__
+#define __MALI_GROUP_H__
+
+#include "linux/jiffies.h"
+#include "mali_osk.h"
+#include "mali_l2_cache.h"
+#include "mali_mmu.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_session.h"
+
+/**
+ * @brief Default max runtime [ms] for a core job - used by timeout timers
+ */
+#define MALI_MAX_JOB_RUNTIME_DEFAULT 4000
+
+/** @brief A mali group object represents a MMU and a PP and/or a GP core.
+ *
+ */
+#define MALI_MAX_NUMBER_OF_GROUPS 10
+
+enum mali_group_core_state {
+       MALI_GROUP_STATE_IDLE,
+       MALI_GROUP_STATE_WORKING,
+       MALI_GROUP_STATE_OOM,
+       MALI_GROUP_STATE_IN_VIRTUAL,
+       MALI_GROUP_STATE_JOINING_VIRTUAL,
+       MALI_GROUP_STATE_LEAVING_VIRTUAL,
+       MALI_GROUP_STATE_DISABLED,
+};
+
+/* Forward declaration from mali_pm_domain.h */
+struct mali_pm_domain;
+
+/**
+ * The structure represents a render group
+ * A render group is defined by all the cores that share the same Mali MMU
+ */
+
+struct mali_group {
+       struct mali_mmu_core        *mmu;
+       struct mali_session_data    *session;
+
+       mali_bool                   power_is_on;
+       enum mali_group_core_state  state;
+
+       struct mali_gp_core         *gp_core;
+       struct mali_gp_job          *gp_running_job;
+
+       struct mali_pp_core         *pp_core;
+       struct mali_pp_job          *pp_running_job;
+       u32                         pp_running_sub_job;
+
+       struct mali_l2_cache_core   *l2_cache_core[2];
+       u32                         l2_cache_core_ref_count[2];
+
+       struct mali_dlbu_core       *dlbu_core;
+       struct mali_bcast_unit      *bcast_core;
+
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_t        *lock;
+#else
+       _mali_osk_spinlock_t            *lock;
+#endif
+
+       _mali_osk_list_t            pp_scheduler_list;
+
+       /* List used for virtual groups. For a virtual group, the list represents the
+        * head element. */
+       _mali_osk_list_t            group_list;
+
+       struct mali_group           *pm_domain_list;
+       struct mali_pm_domain       *pm_domain;
+
+       /* Parent virtual group (if any) */
+       struct mali_group           *parent_group;
+
+       _mali_osk_wq_work_t         *bottom_half_work_mmu;
+       _mali_osk_wq_work_t         *bottom_half_work_gp;
+       _mali_osk_wq_work_t         *bottom_half_work_pp;
+
+       _mali_osk_timer_t           *timeout_timer;
+       mali_bool                   core_timed_out;
+};
+
+/** @brief Create a new Mali group object
+ *
+ * @param cluster Pointer to the cluster to which the group is connected.
+ * @param mmu Pointer to the MMU that defines this group
+ * @return A pointer to a new group object
+ */
+struct mali_group *mali_group_create(struct mali_l2_cache_core *core,
+                                     struct mali_dlbu_core *dlbu,
+                                     struct mali_bcast_unit *bcast);
+
+_mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core);
+void mali_group_remove_mmu_core(struct mali_group *group);
+
+_mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core);
+void mali_group_remove_gp_core(struct mali_group *group);
+
+_mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core);
+void mali_group_remove_pp_core(struct mali_group *group);
+
+void mali_group_set_pm_domain(struct mali_group *group, struct mali_pm_domain *domain);
+
+void mali_group_delete(struct mali_group *group);
+
+/** @brief Virtual groups */
+void mali_group_add_group(struct mali_group *parent, struct mali_group *child, mali_bool update_hw);
+void mali_group_remove_group(struct mali_group *parent, struct mali_group *child);
+struct mali_group *mali_group_acquire_group(struct mali_group *parent);
+
+MALI_STATIC_INLINE mali_bool mali_group_is_virtual(struct mali_group *group)
+{
+#if defined(CONFIG_MALI450)
+       return (NULL != group->dlbu_core);
+#else
+       return MALI_FALSE;
+#endif
+}
+
+/** @brief Check if a group is considered as part of a virtual group
+ *
+ * @note A group is considered to be "part of" a virtual group also during the transition
+ *       in to / out of the virtual group.
+ */
+MALI_STATIC_INLINE mali_bool mali_group_is_in_virtual(struct mali_group *group)
+{
+#if defined(CONFIG_MALI450)
+       return (MALI_GROUP_STATE_IN_VIRTUAL == group->state ||
+               MALI_GROUP_STATE_JOINING_VIRTUAL == group->state ||
+               MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state);
+#else
+       return MALI_FALSE;
+#endif
+}
+
+/** @brief Reset group
+ *
+ * This function will reset the entire group, including all the cores present in the group.
+ *
+ * @param group Pointer to the group to reset
+ */
+void mali_group_reset(struct mali_group *group);
+
+/** @brief Zap MMU TLB on all groups
+ *
+ * Zap TLB on group if \a session is active.
+ */
+void mali_group_zap_session(struct mali_group* group, struct mali_session_data *session);
+
+/** @brief Get pointer to GP core object
+ */
+struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group);
+
+/** @brief Get pointer to PP core object
+ */
+struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group);
+
+/** @brief Lock group object
+ *
+ * Most group functions will lock the group object themselves. The expection is
+ * the group_bottom_half which requires the group to be locked on entry.
+ *
+ * @param group Pointer to group to lock
+ */
+void mali_group_lock(struct mali_group *group);
+
+/** @brief Unlock group object
+ *
+ * @param group Pointer to group to unlock
+ */
+void mali_group_unlock(struct mali_group *group);
+#ifdef DEBUG
+void mali_group_assert_locked(struct mali_group *group);
+#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group)
+#else
+#define MALI_ASSERT_GROUP_LOCKED(group)
+#endif
+
+/** @brief Start GP job
+ */
+void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job);
+/** @brief Start fragment of PP job
+ */
+void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job);
+
+/** @brief Resume GP job that suspended waiting for more heap memory
+ */
+struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr);
+/** @brief Abort GP job
+ *
+ * Used to abort suspended OOM jobs when user space failed to allocte more memory.
+ */
+void mali_group_abort_gp_job(struct mali_group *group, u32 job_id);
+/** @brief Abort all GP jobs from \a session
+ *
+ * Used on session close when terminating all running and queued jobs from \a session.
+ */
+void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session);
+
+mali_bool mali_group_power_is_on(struct mali_group *group);
+void mali_group_power_on_group(struct mali_group *group);
+void mali_group_power_off_group(struct mali_group *group, mali_bool power_status);
+void mali_group_power_on(void);
+
+/** @brief Prepare group for power off
+ *
+ * Update the group's state and prepare for the group to be powered off.
+ *
+ * If do_power_change is MALI_FALSE group session will be set to NULL so that
+ * no more activity will happen to this group, but the power state flag will be
+ * left unchanged.
+ *
+ * @do_power_change MALI_TRUE if power status is to be updated
+ */
+void mali_group_power_off(mali_bool do_power_change);
+
+struct mali_group *mali_group_get_glob_group(u32 index);
+u32 mali_group_get_glob_num_groups(void);
+
+u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size);
+
+/* MMU-related functions */
+_mali_osk_errcode_t mali_group_upper_half_mmu(void * data);
+
+/* GP-related functions */
+_mali_osk_errcode_t mali_group_upper_half_gp(void *data);
+
+/* PP-related functions */
+_mali_osk_errcode_t mali_group_upper_half_pp(void *data);
+
+/** @brief Check if group is enabled
+ *
+ * @param group group to check
+ * @return MALI_TRUE if enabled, MALI_FALSE if not
+ */
+mali_bool mali_group_is_enabled(struct mali_group *group);
+
+/** @brief Enable group
+ *
+ * An enabled job is put on the idle scheduler list and can be used to handle jobs.  Does nothing if
+ * group is already enabled.
+ *
+ * @param group group to enable
+ */
+void mali_group_enable(struct mali_group *group);
+
+/** @brief Disable group
+ *
+ * A disabled group will no longer be used by the scheduler.  If part of a virtual group, the group
+ * will be removed before being disabled.  Cores part of a disabled group is safe to power down.
+ *
+ * @param group group to disable
+ */
+void mali_group_disable(struct mali_group *group);
+
+MALI_STATIC_INLINE mali_bool mali_group_virtual_disable_if_empty(struct mali_group *group)
+{
+       mali_bool empty = MALI_FALSE;
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(group));
+
+       if (_mali_osk_list_empty(&group->group_list)) {
+               group->state = MALI_GROUP_STATE_DISABLED;
+               group->session = NULL;
+
+               empty = MALI_TRUE;
+       }
+
+       return empty;
+}
+
+MALI_STATIC_INLINE mali_bool mali_group_virtual_enable_if_empty(struct mali_group *group)
+{
+       mali_bool empty = MALI_FALSE;
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT(mali_group_is_virtual(group));
+
+       if (_mali_osk_list_empty(&group->group_list)) {
+               MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state);
+
+               group->state = MALI_GROUP_STATE_IDLE;
+
+               empty = MALI_TRUE;
+       }
+
+       return empty;
+}
+
+/* Get group used l2 domain and core domain ref */
+void mali_group_get_pm_domain_ref(struct mali_group *group);
+/* Put group used l2 domain and core domain ref */
+void mali_group_put_pm_domain_ref(struct mali_group *group);
+
+#endif /* __MALI_GROUP_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_hw_core.c b/drivers/gpu/arm/mali400/mali/common/mali_hw_core.c
new file mode 100755 (executable)
index 0000000..fcde143
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_hw_core.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_osk_mali.h"
+
+_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size)
+{
+       core->phys_addr = resource->base;
+       core->phys_offset = resource->base - _mali_osk_resource_base_address();
+       core->description = resource->description;
+       core->size = reg_size;
+
+       MALI_DEBUG_ASSERT(core->phys_offset < core->phys_addr);
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description)) {
+               core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description);
+               if (NULL != core->mapped_registers) {
+                       return _MALI_OSK_ERR_OK;
+               } else {
+                       MALI_PRINT_ERROR(("Failed to map memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr));
+               }
+               _mali_osk_mem_unreqregion(core->phys_addr, core->size);
+       } else {
+               MALI_PRINT_ERROR(("Failed to request memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr));
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_hw_core_delete(struct mali_hw_core *core)
+{
+       _mali_osk_mem_unmapioregion(core->phys_addr, core->size, core->mapped_registers);
+       core->mapped_registers = NULL;
+       _mali_osk_mem_unreqregion(core->phys_addr, core->size);
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_hw_core.h b/drivers/gpu/arm/mali400/mali/common/mali_hw_core.h
new file mode 100755 (executable)
index 0000000..66e9b42
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_HW_CORE_H__
+#define __MALI_HW_CORE_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+/**
+ * The common parts for all Mali HW cores (GP, PP, MMU, L2 and PMU)
+ * This struct is embedded inside all core specific structs.
+ */
+struct mali_hw_core {
+       u32 phys_addr;                    /**< Physical address of the registers */
+       u32 phys_offset;                  /**< Offset from start of Mali to registers */
+       u32 size;                         /**< Size of registers */
+       mali_io_address mapped_registers; /**< Virtual mapping of the registers */
+       const char* description;          /**< Name of unit (as specified in device configuration) */
+};
+
+#define MALI_REG_POLL_COUNT_FAST 1000
+#define MALI_REG_POLL_COUNT_SLOW 1000000
+
+_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size);
+void mali_hw_core_delete(struct mali_hw_core *core);
+
+MALI_STATIC_INLINE u32 mali_hw_core_register_read(struct mali_hw_core *core, u32 relative_address)
+{
+       u32 read_val;
+       read_val = _mali_osk_mem_ioread32(core->mapped_registers, relative_address);
+       MALI_DEBUG_PRINT(6, ("register_read for core %s, relative addr=0x%04X, val=0x%08X\n",
+                            core->description, relative_address, read_val));
+       return read_val;
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core *core, u32 relative_address, u32 new_val)
+{
+       MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n",
+                            core->description, relative_address, new_val));
+       _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val);
+}
+
+/* Conditionally write a register.
+ * The register will only be written if the new value is different from the old_value.
+ * If the new value is different, the old value will also be updated */
+MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 new_val, const u32 old_val)
+{
+       MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n",
+                            core->description, relative_address, new_val));
+       if(old_val != new_val) {
+               _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val);
+       }
+}
+
+
+MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val)
+{
+       MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n",
+                            core->description, relative_address, new_val));
+       _mali_osk_mem_iowrite32(core->mapped_registers, relative_address, new_val);
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs)
+{
+       u32 i;
+       MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n",
+                            core->description,relative_address, nr_of_regs));
+
+       /* Do not use burst writes against the registers */
+       for (i = 0; i< nr_of_regs; i++) {
+               mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]);
+       }
+}
+
+/* Conditionally write a set of registers.
+ * The register will only be written if the new value is different from the old_value.
+ * If the new value is different, the old value will also be updated */
+MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs, const u32* old_array)
+{
+       u32 i;
+       MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n",
+                            core->description,relative_address, nr_of_regs));
+
+       /* Do not use burst writes against the registers */
+       for (i = 0; i< nr_of_regs; i++) {
+               if(old_array[i] != write_array[i]) {
+                       mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]);
+               }
+       }
+}
+
+#endif /* __MALI_HW_CORE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_common.h b/drivers/gpu/arm/mali400/mali/common/mali_kernel_common.h
new file mode 100755 (executable)
index 0000000..6ffa67c
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_KERNEL_COMMON_H__
+#define __MALI_KERNEL_COMMON_H__
+
+#include "mali_osk.h"
+
+/* Make sure debug is defined when it should be */
+#ifndef DEBUG
+#if defined(_DEBUG)
+#define DEBUG
+#endif
+#endif
+
+/* The file include several useful macros for error checking, debugging and printing.
+ * - MALI_PRINTF(...)           Do not use this function: Will be included in Release builds.
+ * - MALI_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=MALI_DEBUG_LEVEL.
+ * - MALI_DEBUG_ERROR( (X) )    Prints an errortext, a source trace, and the given error message.
+ * - MALI_DEBUG_ASSERT(exp,(X)) If the asserted expr is false, the program will exit.
+ * - MALI_DEBUG_ASSERT_POINTER(pointer)  Triggers if the pointer is a zero pointer.
+ * - MALI_DEBUG_CODE( X )       The code inside the macro is only compiled in Debug builds.
+ *
+ * The (X) means that you must add an extra parenthesis around the argumentlist.
+ *
+ * The  printf function: MALI_PRINTF(...) is routed to _mali_osk_debugmsg
+ *
+ * Suggested range for the DEBUG-LEVEL is [1:6] where
+ * [1:2] Is messages with highest priority, indicate possible errors.
+ * [3:4] Is messages with medium priority, output important variables.
+ * [5:6] Is messages with low priority, used during extensive debugging.
+ */
+
+/**
+*  Fundamental error macro. Reports an error code. This is abstracted to allow us to
+*  easily switch to a different error reporting method if we want, and also to allow
+*  us to search for error returns easily.
+*
+*  Note no closing semicolon - this is supplied in typical usage:
+*
+*  MALI_ERROR(MALI_ERROR_OUT_OF_MEMORY);
+*/
+#define MALI_ERROR(error_code) return (error_code)
+
+/**
+ *  Basic error macro, to indicate success.
+ *  Note no closing semicolon - this is supplied in typical usage:
+ *
+ *  MALI_SUCCESS;
+ */
+#define MALI_SUCCESS MALI_ERROR(_MALI_OSK_ERR_OK)
+
+/**
+ *     Basic error macro. This checks whether the given condition is true, and if not returns
+ *     from this function with the supplied error code. This is a macro so that we can override it
+ *     for stress testing.
+ *
+ *     Note that this uses the do-while-0 wrapping to ensure that we don't get problems with dangling
+ *     else clauses. Note also no closing semicolon - this is supplied in typical usage:
+ *
+ *     MALI_CHECK((p!=NULL), ERROR_NO_OBJECT);
+ */
+#define MALI_CHECK(condition, error_code) do { if(!(condition)) MALI_ERROR(error_code); } while(0)
+
+/**
+ *     Error propagation macro. If the expression given is anything other than _MALI_OSK_NO_ERROR,
+ *     then the value is returned from the enclosing function as an error code. This effectively
+ *     acts as a guard clause, and propagates error values up the call stack. This uses a
+ *     temporary value to ensure that the error expression is not evaluated twice.
+ *  If the counter for forcing a failure has been set using _mali_force_error, this error will be
+ *  returned without evaluating the expression in MALI_CHECK_NO_ERROR
+ */
+#define MALI_CHECK_NO_ERROR(expression) \
+    do { _mali_osk_errcode_t _check_no_error_result=(expression); \
+         if(_check_no_error_result != _MALI_OSK_ERR_OK) \
+         MALI_ERROR(_check_no_error_result); \
+    } while(0)
+
+/**
+ *  Pointer check macro. Checks non-null pointer.
+ */
+#define MALI_CHECK_NON_NULL(pointer, error_code) MALI_CHECK( ((pointer)!=NULL), (error_code) )
+
+/**
+ *     Error macro with goto. This checks whether the given condition is true, and if not jumps
+ *     to the specified label using a goto. The label must therefore be local to the function in
+ *     which this macro appears. This is most usually used to execute some clean-up code before
+ *     exiting with a call to ERROR.
+ *
+ *     Like the other macros, this is a macro to allow us to override the condition if we wish,
+ *     e.g. to force an error during stress testing.
+ */
+#define MALI_CHECK_GOTO(condition, label) do { if(!(condition)) goto label; } while(0)
+
+/**
+ *  Explicitly ignore a parameter passed into a function, to suppress compiler warnings.
+ *  Should only be used with parameter names.
+ */
+#define MALI_IGNORE(x) x=x
+
+#define MALI_PRINTF(args) _mali_osk_dbgmsg args;
+
+#define MALI_PRINT_ERROR(args) do{ \
+       MALI_PRINTF(("Mali: ERR: %s\n" ,__FILE__)); \
+       MALI_PRINTF(("           %s()%4d\n           ", __FUNCTION__, __LINE__)) ; \
+       MALI_PRINTF(args); \
+       MALI_PRINTF(("\n")); \
+       } while(0)
+
+#define MALI_PRINT(args) do{ \
+       MALI_PRINTF(("Mali: ")); \
+       MALI_PRINTF(args); \
+       } while (0)
+
+#ifdef DEBUG
+#ifndef mali_debug_level
+extern int mali_debug_level;
+#endif
+
+#define MALI_DEBUG_CODE(code) code
+#define MALI_DEBUG_PRINT(level, args)  do { \
+       if((level) <=  mali_debug_level)\
+        {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); } \
+       } while (0)
+
+#define MALI_DEBUG_PRINT_ERROR(args) MALI_PRINT_ERROR(args)
+
+#define MALI_DEBUG_PRINT_IF(level,condition,args)  \
+       if((condition)&&((level) <=  mali_debug_level))\
+        {MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); }
+
+#define MALI_DEBUG_PRINT_ELSE(level, args)\
+       else if((level) <=  mali_debug_level)\
+    { MALI_PRINTF(("Mali<" #level ">: ")); MALI_PRINTF(args); }
+
+/**
+ * @note these variants of DEBUG ASSERTS will cause a debugger breakpoint
+ * to be entered (see _mali_osk_break() ). An alternative would be to call
+ * _mali_osk_abort(), on OSs that support it.
+ */
+#define MALI_DEBUG_PRINT_ASSERT(condition, args) do  {if( !(condition)) { MALI_PRINT_ERROR(args); _mali_osk_break(); } } while(0)
+#define MALI_DEBUG_ASSERT_POINTER(pointer) do  {if( (pointer)== NULL) {MALI_PRINT_ERROR(("NULL pointer " #pointer)); _mali_osk_break();} } while(0)
+#define MALI_DEBUG_ASSERT(condition) do  {if( !(condition)) {MALI_PRINT_ERROR(("ASSERT failed: " #condition )); _mali_osk_break();} } while(0)
+
+#else /* DEBUG */
+
+#define MALI_DEBUG_CODE(code)
+#define MALI_DEBUG_PRINT(string,args) do {} while(0)
+#define MALI_DEBUG_PRINT_ERROR(args) do {} while(0)
+#define MALI_DEBUG_PRINT_IF(level,condition,args) do {} while(0)
+#define MALI_DEBUG_PRINT_ELSE(level,condition,args) do {} while(0)
+#define MALI_DEBUG_PRINT_ASSERT(condition,args) do {} while(0)
+#define MALI_DEBUG_ASSERT_POINTER(pointer) do {} while(0)
+#define MALI_DEBUG_ASSERT(condition) do {} while(0)
+
+#endif /* DEBUG */
+
+/**
+ * variables from user space cannot be dereferenced from kernel space; tagging them
+ * with __user allows the GCC compiler to generate a warning. Other compilers may
+ * not support this so we define it here as an empty macro if the compiler doesn't
+ * define it.
+ */
+#ifndef __user
+#define __user
+#endif
+
+#endif /* __MALI_KERNEL_COMMON_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_core.c b/drivers/gpu/arm/mali400/mali/common/mali_kernel_core.c
new file mode 100755 (executable)
index 0000000..f774fc6
--- /dev/null
@@ -0,0 +1,1405 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_ukk.h"
+#include "mali_kernel_core.h"
+#include "mali_memory.h"
+#include "mali_mem_validation.h"
+#include "mali_mmu.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_dlbu.h"
+#include "mali_broadcast.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_pp_job.h"
+#include "mali_group.h"
+#include "mali_pm.h"
+#include "mali_pmu.h"
+#include "mali_scheduler.h"
+#include "mali_kernel_utilization.h"
+#include "mali_l2_cache.h"
+#include "mali_dma.h"
+#include "mali_timeline.h"
+#include "mali_soft_job.h"
+#include "mali_pm_domain.h"
+#if defined(CONFIG_MALI400_PROFILING)
+#include "mali_osk_profiling.h"
+#endif
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+#include "mali_profiling_internal.h"
+#endif
+//extern unsigned long totalram_pages;
+#include <linux/mm.h>
+
+
+/* Mali GPU memory. Real values come from module parameter or from device specific data */
+unsigned int mali_dedicated_mem_start = 0;
+unsigned int mali_dedicated_mem_size = 0;
+unsigned long mali_shared_mem_size = 0;
+
+/* Frame buffer memory to be accessible by Mali GPU */
+int mali_fb_start = 0;
+int mali_fb_size = 0;
+
+/* Mali max job runtime */
+extern int mali_max_job_runtime;
+
+/** Start profiling from module load? */
+int mali_boot_profiling = 0;
+
+/** Limits for the number of PP cores behind each L2 cache. */
+int mali_max_pp_cores_group_1 = 0xFF;
+int mali_max_pp_cores_group_2 = 0xFF;
+
+int mali_inited_pp_cores_group_1 = 0;
+int mali_inited_pp_cores_group_2 = 0;
+
+static _mali_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN;
+static u32 global_gpu_base_address = 0;
+static u32 global_gpu_major_version = 0;
+static u32 global_gpu_minor_version = 0;
+
+mali_bool mali_gpu_class_is_mali450 = MALI_FALSE;
+
+static _mali_osk_errcode_t mali_set_global_gpu_base_address(void)
+{
+       global_gpu_base_address = _mali_osk_resource_base_address();
+       if (0 == global_gpu_base_address) {
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static u32 mali_get_bcast_id(_mali_osk_resource_t *resource_pp)
+{
+       switch (resource_pp->base - global_gpu_base_address) {
+       case 0x08000:
+       case 0x20000: /* fall-through for aliased mapping */
+               return 0x01;
+       case 0x0A000:
+       case 0x22000: /* fall-through for aliased mapping */
+               return 0x02;
+       case 0x0C000:
+       case 0x24000: /* fall-through for aliased mapping */
+               return 0x04;
+       case 0x0E000:
+       case 0x26000: /* fall-through for aliased mapping */
+               return 0x08;
+       case 0x28000:
+               return 0x10;
+       case 0x2A000:
+               return 0x20;
+       case 0x2C000:
+               return 0x40;
+       case 0x2E000:
+               return 0x80;
+       default:
+               return 0;
+       }
+}
+
+static _mali_osk_errcode_t mali_parse_product_info(void)
+{
+       /*
+        * Mali-200 has the PP core first, while Mali-300, Mali-400 and Mali-450 have the GP core first.
+        * Look at the version register for the first PP core in order to determine the GPU HW revision.
+        */
+
+       u32 first_pp_offset;
+       _mali_osk_resource_t first_pp_resource;
+
+       /* Find out where the first PP core is located */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL)) {
+               /* Mali-300/400/450 */
+               first_pp_offset = 0x8000;
+       } else {
+               /* Mali-200 */
+               first_pp_offset = 0x0000;
+       }
+
+       /* Find the first PP core resource (again) */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + first_pp_offset, &first_pp_resource)) {
+               /* Create a dummy PP object for this core so that we can read the version register */
+               struct mali_group *group = mali_group_create(NULL, NULL, NULL);
+               if (NULL != group) {
+                       struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE, mali_get_bcast_id(&first_pp_resource));
+                       if (NULL != pp_core) {
+                               u32 pp_version = mali_pp_core_get_version(pp_core);
+                               mali_group_delete(group);
+
+                               global_gpu_major_version = (pp_version >> 8) & 0xFF;
+                               global_gpu_minor_version = pp_version & 0xFF;
+
+                               switch (pp_version >> 16) {
+                               case MALI200_PP_PRODUCT_ID:
+                                       global_product_id = _MALI_PRODUCT_ID_MALI200;
+                                       MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+                                       MALI_PRINT_ERROR(("Mali-200 is not supported by this driver.\n"));
+                                       _mali_osk_abort();
+                                       break;
+                               case MALI300_PP_PRODUCT_ID:
+                                       global_product_id = _MALI_PRODUCT_ID_MALI300;
+                                       MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+                                       break;
+                               case MALI400_PP_PRODUCT_ID:
+                                       global_product_id = _MALI_PRODUCT_ID_MALI400;
+                                       MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+                                       break;
+                               case MALI450_PP_PRODUCT_ID:
+                                       global_product_id = _MALI_PRODUCT_ID_MALI450;
+                                       MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+                                       break;
+                               default:
+                                       MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version));
+                                       return _MALI_OSK_ERR_FAULT;
+                               }
+
+                               return _MALI_OSK_ERR_OK;
+                       } else {
+                               MALI_PRINT_ERROR(("Failed to create initial PP object\n"));
+                       }
+               } else {
+                       MALI_PRINT_ERROR(("Failed to create initial group object\n"));
+               }
+       } else {
+               MALI_PRINT_ERROR(("First PP core not specified in config file\n"));
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+
+static void mali_resource_count(u32 *pp_count, u32 *l2_count)
+{
+       *pp_count = 0;
+       *l2_count = 0;
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL)) {
+               ++(*pp_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL)) {
+               ++(*pp_count);
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL)) {
+               ++(*l2_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL)) {
+               ++(*l2_count);
+       }
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL)) {
+               ++(*l2_count);
+       }
+}
+
+static void mali_delete_groups(void)
+{
+       struct mali_group *group;
+
+       group = mali_group_get_glob_group(0);
+       while (NULL != group) {
+               mali_group_delete(group);
+               group = mali_group_get_glob_group(0);
+       }
+
+       MALI_DEBUG_ASSERT(0 == mali_group_get_glob_num_groups());
+}
+
+static void mali_delete_l2_cache_cores(void)
+{
+       struct mali_l2_cache_core *l2;
+
+       l2 = mali_l2_cache_core_get_glob_l2_core(0);
+       while (NULL != l2) {
+               mali_l2_cache_delete(l2);
+               l2 = mali_l2_cache_core_get_glob_l2_core(0);
+       }
+
+       MALI_DEBUG_ASSERT(0 == mali_l2_cache_core_get_glob_num_l2_cores());
+}
+
+static struct mali_l2_cache_core *mali_create_l2_cache_core(_mali_osk_resource_t *resource)
+{
+       struct mali_l2_cache_core *l2_cache = NULL;
+
+       if (NULL != resource) {
+
+               MALI_DEBUG_PRINT(3, ("Found L2 cache %s\n", resource->description));
+
+               l2_cache = mali_l2_cache_create(resource);
+               if (NULL == l2_cache) {
+                       MALI_PRINT_ERROR(("Failed to create L2 cache object\n"));
+                       return NULL;
+               }
+       }
+       MALI_DEBUG_PRINT(3, ("Created L2 cache core object\n"));
+
+       return l2_cache;
+}
+
+static _mali_osk_errcode_t mali_parse_config_l2_cache(void)
+{
+       struct mali_l2_cache_core *l2_cache = NULL;
+
+       if (mali_is_mali400()) {
+               _mali_osk_resource_t l2_resource;
+               if (_MALI_OSK_ERR_OK != _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_resource)) {
+                       MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n"));
+                       return _MALI_OSK_ERR_FAULT;
+               }
+
+               l2_cache = mali_create_l2_cache_core(&l2_resource);
+               if (NULL == l2_cache) {
+                       return _MALI_OSK_ERR_FAULT;
+               }
+               mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L20_DOMAIN_INDEX), l2_cache);
+       } else if (mali_is_mali450()) {
+               /*
+                * L2 for GP    at 0x10000
+                * L2 for PP0-3 at 0x01000
+                * L2 for PP4-7 at 0x11000 (optional)
+                */
+
+               _mali_osk_resource_t l2_gp_resource;
+               _mali_osk_resource_t l2_pp_grp0_resource;
+               _mali_osk_resource_t l2_pp_grp1_resource;
+
+               /* Make cluster for GP's L2 */
+               if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, &l2_gp_resource)) {
+                       MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for GP\n"));
+                       l2_cache = mali_create_l2_cache_core(&l2_gp_resource);
+                       if (NULL == l2_cache) {
+                               return _MALI_OSK_ERR_FAULT;
+                       }
+                       mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L20_DOMAIN_INDEX), l2_cache);
+               } else {
+                       MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n"));
+                       return _MALI_OSK_ERR_FAULT;
+               }
+
+               /* Find corresponding l2 domain */
+               if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, &l2_pp_grp0_resource)) {
+                       MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 0\n"));
+                       l2_cache = mali_create_l2_cache_core(&l2_pp_grp0_resource);
+                       if (NULL == l2_cache) {
+                               return _MALI_OSK_ERR_FAULT;
+                       }
+                       mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L21_DOMAIN_INDEX), l2_cache);
+               } else {
+                       MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n"));
+                       return _MALI_OSK_ERR_FAULT;
+               }
+
+               /* Second PP core group is optional, don't fail if we don't find it */
+               if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, &l2_pp_grp1_resource)) {
+                       MALI_DEBUG_PRINT(3, ("Creating Mali-450 L2 cache core for PP group 1\n"));
+                       l2_cache = mali_create_l2_cache_core(&l2_pp_grp1_resource);
+                       if (NULL == l2_cache) {
+                               return _MALI_OSK_ERR_FAULT;
+                       }
+                       mali_pm_domain_add_l2(mali_pmu_get_domain_mask(MALI_L22_DOMAIN_INDEX), l2_cache);
+               }
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static struct mali_group *mali_create_group(struct mali_l2_cache_core *cache,
+        _mali_osk_resource_t *resource_mmu,
+        _mali_osk_resource_t *resource_gp,
+        _mali_osk_resource_t *resource_pp)
+{
+       struct mali_mmu_core *mmu;
+       struct mali_group *group;
+
+       MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
+
+       /* Create the group object */
+       group = mali_group_create(cache, NULL, NULL);
+       if (NULL == group) {
+               MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description));
+               return NULL;
+       }
+
+       /* Create the MMU object inside group */
+       mmu = mali_mmu_create(resource_mmu, group, MALI_FALSE);
+       if (NULL == mmu) {
+               MALI_PRINT_ERROR(("Failed to create MMU object\n"));
+               mali_group_delete(group);
+               return NULL;
+       }
+
+       if (NULL != resource_gp) {
+               /* Create the GP core object inside this group */
+               struct mali_gp_core *gp_core = mali_gp_create(resource_gp, group);
+               if (NULL == gp_core) {
+                       /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
+                       MALI_PRINT_ERROR(("Failed to create GP object\n"));
+                       mali_group_delete(group);
+                       return NULL;
+               }
+       }
+
+       if (NULL != resource_pp) {
+               struct mali_pp_core *pp_core;
+
+               /* Create the PP core object inside this group */
+               pp_core = mali_pp_create(resource_pp, group, MALI_FALSE, mali_get_bcast_id(resource_pp));
+               if (NULL == pp_core) {
+                       /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
+                       MALI_PRINT_ERROR(("Failed to create PP object\n"));
+                       mali_group_delete(group);
+                       return NULL;
+               }
+       }
+
+       /* Reset group */
+       mali_group_lock(group);
+       mali_group_reset(group);
+       mali_group_unlock(group);
+
+       return group;
+}
+
+static _mali_osk_errcode_t mali_create_virtual_group(_mali_osk_resource_t *resource_mmu_pp_bcast,
+        _mali_osk_resource_t *resource_pp_bcast,
+        _mali_osk_resource_t *resource_dlbu,
+        _mali_osk_resource_t *resource_bcast)
+{
+       struct mali_mmu_core *mmu_pp_bcast_core;
+       struct mali_pp_core *pp_bcast_core;
+       struct mali_dlbu_core *dlbu_core;
+       struct mali_bcast_unit *bcast_core;
+       struct mali_group *group;
+
+       MALI_DEBUG_PRINT(2, ("Starting new virtual group for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
+
+       /* Create the DLBU core object */
+       dlbu_core = mali_dlbu_create(resource_dlbu);
+       if (NULL == dlbu_core) {
+               MALI_PRINT_ERROR(("Failed to create DLBU object \n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the Broadcast unit core */
+       bcast_core = mali_bcast_unit_create(resource_bcast);
+       if (NULL == bcast_core) {
+               MALI_PRINT_ERROR(("Failed to create Broadcast unit object!\n"));
+               mali_dlbu_delete(dlbu_core);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the group object */
+       group = mali_group_create(NULL, dlbu_core, bcast_core);
+       if (NULL == group) {
+               MALI_PRINT_ERROR(("Failed to create group object for MMU PP broadcast core %s\n", resource_mmu_pp_bcast->description));
+               mali_bcast_unit_delete(bcast_core);
+               mali_dlbu_delete(dlbu_core);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the MMU object inside group */
+       mmu_pp_bcast_core = mali_mmu_create(resource_mmu_pp_bcast, group, MALI_TRUE);
+       if (NULL == mmu_pp_bcast_core) {
+               MALI_PRINT_ERROR(("Failed to create MMU PP broadcast object\n"));
+               mali_group_delete(group);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create the PP core object inside this group */
+       pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE, 0);
+       if (NULL == pp_bcast_core) {
+               /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
+               MALI_PRINT_ERROR(("Failed to create PP object\n"));
+               mali_group_delete(group);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_parse_config_groups(void)
+{
+       struct mali_group *group;
+       int cluster_id_gp = 0;
+       int cluster_id_pp_grp0 = 0;
+       int cluster_id_pp_grp1 = 0;
+       int i;
+
+       _mali_osk_resource_t resource_gp;
+       _mali_osk_resource_t resource_gp_mmu;
+       _mali_osk_resource_t resource_pp[8];
+       _mali_osk_resource_t resource_pp_mmu[8];
+       _mali_osk_resource_t resource_pp_mmu_bcast;
+       _mali_osk_resource_t resource_pp_bcast;
+       _mali_osk_resource_t resource_dlbu;
+       _mali_osk_resource_t resource_bcast;
+       _mali_osk_errcode_t resource_gp_found;
+       _mali_osk_errcode_t resource_gp_mmu_found;
+       _mali_osk_errcode_t resource_pp_found[8];
+       _mali_osk_errcode_t resource_pp_mmu_found[8];
+       _mali_osk_errcode_t resource_pp_mmu_bcast_found;
+       _mali_osk_errcode_t resource_pp_bcast_found;
+       _mali_osk_errcode_t resource_dlbu_found;
+       _mali_osk_errcode_t resource_bcast_found;
+
+       if (!(mali_is_mali400() || mali_is_mali450())) {
+               /* No known HW core */
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       if (MALI_MAX_JOB_RUNTIME_DEFAULT == mali_max_job_runtime) {
+               /* Group settings are not overridden by module parameters, so use device settings */
+               struct _mali_osk_device_data data = { 0, };
+
+               if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
+                       /* Use device specific settings (if defined) */
+                       if (0 != data.max_job_runtime) {
+                               mali_max_job_runtime = data.max_job_runtime;
+                       }
+               }
+       }
+
+       if (mali_is_mali450()) {
+               /* Mali-450 have separate L2s for GP, and PP core group(s) */
+               cluster_id_pp_grp0 = 1;
+               cluster_id_pp_grp1 = 2;
+       }
+
+       resource_gp_found = _mali_osk_resource_find(global_gpu_base_address + 0x00000, &resource_gp);
+       resource_gp_mmu_found = _mali_osk_resource_find(global_gpu_base_address + 0x03000, &resource_gp_mmu);
+       resource_pp_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x08000, &(resource_pp[0]));
+       resource_pp_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x0A000, &(resource_pp[1]));
+       resource_pp_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x0C000, &(resource_pp[2]));
+       resource_pp_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x0E000, &(resource_pp[3]));
+       resource_pp_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x28000, &(resource_pp[4]));
+       resource_pp_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x2A000, &(resource_pp[5]));
+       resource_pp_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x2C000, &(resource_pp[6]));
+       resource_pp_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x2E000, &(resource_pp[7]));
+       resource_pp_mmu_found[0] = _mali_osk_resource_find(global_gpu_base_address + 0x04000, &(resource_pp_mmu[0]));
+       resource_pp_mmu_found[1] = _mali_osk_resource_find(global_gpu_base_address + 0x05000, &(resource_pp_mmu[1]));
+       resource_pp_mmu_found[2] = _mali_osk_resource_find(global_gpu_base_address + 0x06000, &(resource_pp_mmu[2]));
+       resource_pp_mmu_found[3] = _mali_osk_resource_find(global_gpu_base_address + 0x07000, &(resource_pp_mmu[3]));
+       resource_pp_mmu_found[4] = _mali_osk_resource_find(global_gpu_base_address + 0x1C000, &(resource_pp_mmu[4]));
+       resource_pp_mmu_found[5] = _mali_osk_resource_find(global_gpu_base_address + 0x1D000, &(resource_pp_mmu[5]));
+       resource_pp_mmu_found[6] = _mali_osk_resource_find(global_gpu_base_address + 0x1E000, &(resource_pp_mmu[6]));
+       resource_pp_mmu_found[7] = _mali_osk_resource_find(global_gpu_base_address + 0x1F000, &(resource_pp_mmu[7]));
+
+
+       if (mali_is_mali450()) {
+               resource_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x13000, &resource_bcast);
+               resource_dlbu_found = _mali_osk_resource_find(global_gpu_base_address + 0x14000, &resource_dlbu);
+               resource_pp_mmu_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x15000, &resource_pp_mmu_bcast);
+               resource_pp_bcast_found = _mali_osk_resource_find(global_gpu_base_address + 0x16000, &resource_pp_bcast);
+
+               if (_MALI_OSK_ERR_OK != resource_bcast_found ||
+                   _MALI_OSK_ERR_OK != resource_dlbu_found ||
+                   _MALI_OSK_ERR_OK != resource_pp_mmu_bcast_found ||
+                   _MALI_OSK_ERR_OK != resource_pp_bcast_found) {
+                       /* Missing mandatory core(s) for Mali-450 */
+                       MALI_DEBUG_PRINT(2, ("Missing mandatory resources, Mali-450 needs DLBU, Broadcast unit, virtual PP core and virtual MMU\n"));
+                       return _MALI_OSK_ERR_FAULT;
+               }
+       }
+
+       if (_MALI_OSK_ERR_OK != resource_gp_found ||
+           _MALI_OSK_ERR_OK != resource_gp_mmu_found ||
+           _MALI_OSK_ERR_OK != resource_pp_found[0] ||
+           _MALI_OSK_ERR_OK != resource_pp_mmu_found[0]) {
+               /* Missing mandatory core(s) */
+               MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU\n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       MALI_DEBUG_ASSERT(1 <= mali_l2_cache_core_get_glob_num_l2_cores());
+       group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_gp), &resource_gp_mmu, &resource_gp, NULL);
+       if (NULL == group) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Add GP in group, for PMU ref count */
+       mali_pm_domain_add_group(mali_pmu_get_domain_mask(MALI_GP_DOMAIN_INDEX), group);
+
+       /* Create group for first (and mandatory) PP core */
+       MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */
+       group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[0], NULL, &resource_pp[0]);
+       if (NULL == group) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Find corresponding pp domain */
+       mali_pm_domain_add_group(mali_pmu_get_domain_mask(MALI_PP0_DOMAIN_INDEX), group);
+
+       mali_inited_pp_cores_group_1++;
+
+       /* Create groups for rest of the cores in the first PP core group */
+       for (i = 1; i < 4; i++) { /* First half of the PP cores belong to first core group */
+               if (mali_inited_pp_cores_group_1 < mali_max_pp_cores_group_1) {
+                       if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) {
+                               group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp0), &resource_pp_mmu[i], NULL, &resource_pp[i]);
+                               if (NULL == group) {
+                                       return _MALI_OSK_ERR_FAULT;
+                               }
+
+                               mali_pm_domain_add_group(mali_pmu_get_domain_mask(i + MALI_PP0_DOMAIN_INDEX), group);
+
+                               mali_inited_pp_cores_group_1++;
+                       }
+               }
+       }
+
+       /* Create groups for cores in the second PP core group */
+       for (i = 4; i < 8; i++) { /* Second half of the PP cores belong to second core group */
+               if (mali_inited_pp_cores_group_2 < mali_max_pp_cores_group_2) {
+                       if (_MALI_OSK_ERR_OK == resource_pp_found[i] && _MALI_OSK_ERR_OK == resource_pp_mmu_found[i]) {
+                               MALI_DEBUG_ASSERT(mali_l2_cache_core_get_glob_num_l2_cores() >= 2); /* Only Mali-450 have a second core group */
+                               group = mali_create_group(mali_l2_cache_core_get_glob_l2_core(cluster_id_pp_grp1), &resource_pp_mmu[i], NULL, &resource_pp[i]);
+                               if (NULL == group) {
+                                       return _MALI_OSK_ERR_FAULT;
+                               }
+                               mali_pm_domain_add_group(mali_pmu_get_domain_mask(i + MALI_PP0_DOMAIN_INDEX), group);
+                               mali_inited_pp_cores_group_2++;
+                       }
+               }
+       }
+
+       if(mali_is_mali450()) {
+               _mali_osk_errcode_t err = mali_create_virtual_group(&resource_pp_mmu_bcast, &resource_pp_bcast, &resource_dlbu, &resource_bcast);
+               if (_MALI_OSK_ERR_OK != err) {
+                       return err;
+               }
+       }
+
+       mali_max_pp_cores_group_1 = mali_inited_pp_cores_group_1;
+       mali_max_pp_cores_group_2 = mali_inited_pp_cores_group_2;
+       MALI_DEBUG_PRINT(2, ("%d+%d PP cores initialized\n", mali_inited_pp_cores_group_1, mali_inited_pp_cores_group_2));
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_check_shared_interrupts(void)
+{
+#if !defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       if (MALI_TRUE == _mali_osk_shared_interrupts()) {
+               MALI_PRINT_ERROR(("Shared interrupts detected, but driver support is not enabled\n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+#endif /* !defined(CONFIG_MALI_SHARED_INTERRUPTS) */
+
+       /* It is OK to compile support for shared interrupts even if Mali is not using it. */
+       return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_create_pm_domains(void)
+{
+       int i;
+
+       for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
+               if (0x0 == mali_pmu_get_domain_mask(i)) continue;
+
+               if (NULL == mali_pm_domain_create(mali_pmu_get_domain_mask(i))) {
+                       return _MALI_OSK_ERR_NOMEM;
+               }
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static void mali_use_default_pm_domain_config(void)
+{
+       u32 pp_count_gr1 = 0;
+       u32 pp_count_gr2 = 0;
+       u32 l2_count = 0;
+
+       MALI_DEBUG_ASSERT(0 != global_gpu_base_address);
+
+       /* GP core */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x00000, NULL)) {
+               mali_pmu_set_domain_mask(MALI_GP_DOMAIN_INDEX, 0x01);
+       }
+
+       /* PP0 - PP3 core */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x08000, NULL)) {
+               ++pp_count_gr1;
+
+               if (mali_is_mali400()) {
+                       mali_pmu_set_domain_mask(MALI_PP0_DOMAIN_INDEX, 0x01<<2);
+               } else if (mali_is_mali450()) {
+                       mali_pmu_set_domain_mask(MALI_PP0_DOMAIN_INDEX, 0x01<<1);
+               }
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0A000, NULL)) {
+               ++pp_count_gr1;
+
+               if (mali_is_mali400()) {
+                       mali_pmu_set_domain_mask(MALI_PP1_DOMAIN_INDEX, 0x01<<3);
+               } else if (mali_is_mali450()) {
+                       mali_pmu_set_domain_mask(MALI_PP1_DOMAIN_INDEX, 0x01<<2);
+               }
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0C000, NULL)) {
+               ++pp_count_gr1;
+
+               if (mali_is_mali400()) {
+                       mali_pmu_set_domain_mask(MALI_PP2_DOMAIN_INDEX, 0x01<<4);
+               } else if (mali_is_mali450()) {
+                       mali_pmu_set_domain_mask(MALI_PP2_DOMAIN_INDEX, 0x01<<2);
+               }
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x0E000, NULL)) {
+               ++pp_count_gr1;
+
+               if (mali_is_mali400()) {
+                       mali_pmu_set_domain_mask(MALI_PP3_DOMAIN_INDEX, 0x01<<5);
+               } else if (mali_is_mali450()) {
+                       mali_pmu_set_domain_mask(MALI_PP3_DOMAIN_INDEX, 0x01<<2);
+               }
+       }
+
+       /* PP4 - PP7 */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x28000, NULL)) {
+               ++pp_count_gr2;
+
+               mali_pmu_set_domain_mask(MALI_PP4_DOMAIN_INDEX, 0x01<<3);
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2A000, NULL)) {
+               ++pp_count_gr2;
+
+               mali_pmu_set_domain_mask(MALI_PP5_DOMAIN_INDEX, 0x01<<3);
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2C000, NULL)) {
+               ++pp_count_gr2;
+
+               mali_pmu_set_domain_mask(MALI_PP6_DOMAIN_INDEX, 0x01<<3);
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x2E000, NULL)) {
+               ++pp_count_gr2;
+
+               mali_pmu_set_domain_mask(MALI_PP7_DOMAIN_INDEX, 0x01<<3);
+       }
+
+       /* L2gp/L2PP0/L2PP4 */
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x10000, NULL)) {
+               ++l2_count;
+
+               if (mali_is_mali400()) {
+                       mali_pmu_set_domain_mask(MALI_L20_DOMAIN_INDEX, 0x01<<1);
+               } else if (mali_is_mali450()) {
+                       mali_pmu_set_domain_mask(MALI_L20_DOMAIN_INDEX, 0x01<<0);
+               }
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x1000, NULL)) {
+               ++l2_count;
+
+               mali_pmu_set_domain_mask(MALI_L21_DOMAIN_INDEX, 0x01<<1);
+       }
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x11000, NULL)) {
+               ++l2_count;
+
+               mali_pmu_set_domain_mask(MALI_L22_DOMAIN_INDEX, 0x01<<3);
+       }
+
+       MALI_DEBUG_PRINT(2, ("Using default PMU domain config: (%d) gr1_pp_cores, (%d) gr2_pp_cores, (%d) l2_count. \n", pp_count_gr1, pp_count_gr2, l2_count));
+}
+
+static void mali_set_pmu_global_domain_config(void)
+{
+       struct _mali_osk_device_data data = { 0, };
+       int i = 0;
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
+               /* Check whether has customized pmu domain configure */
+               for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
+                       if (0 != data.pmu_domain_config[i]) break;
+               }
+
+               if (MALI_MAX_NUMBER_OF_DOMAINS == i) {
+                       mali_use_default_pm_domain_config();
+               } else {
+                       /* Copy the customer config to global config */
+                       mali_pmu_copy_domain_mask(data.pmu_domain_config, sizeof(data.pmu_domain_config));
+               }
+       }
+}
+
+static _mali_osk_errcode_t mali_parse_config_pmu(void)
+{
+       _mali_osk_resource_t resource_pmu;
+
+       MALI_DEBUG_ASSERT(0 != global_gpu_base_address);
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu)) {
+               struct mali_pmu_core *pmu;
+
+               mali_set_pmu_global_domain_config();
+
+               pmu = mali_pmu_create(&resource_pmu);
+               if (NULL == pmu) {
+                       MALI_PRINT_ERROR(("Failed to create PMU\n"));
+                       return _MALI_OSK_ERR_FAULT;
+               }
+       }
+
+       /* It's ok if the PMU doesn't exist */
+       return _MALI_OSK_ERR_OK;
+}
+/*extern u32 ddr_get_cap(void);*/
+static _mali_osk_errcode_t mali_parse_config_dma(void)
+{
+       _mali_osk_resource_t resource_dma;
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x12000, &resource_dma)) {
+               if (NULL == mali_dma_create(&resource_dma)) {
+                       return _MALI_OSK_ERR_FAULT;
+               }
+               return _MALI_OSK_ERR_OK;
+       } else {
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+}
+
+static _mali_osk_errcode_t mali_parse_config_memory(void)
+{
+       _mali_osk_errcode_t ret;
+
+       if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) {
+               /* Memory settings are not overridden by module parameters, so use device settings */
+               struct _mali_osk_device_data data = { 0, };
+
+               if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
+                       /* Use device specific settings (if defined) */
+                       mali_dedicated_mem_start = data.dedicated_mem_start;
+                       mali_dedicated_mem_size = data.dedicated_mem_size;
+/*
+                       mali_shared_mem_size = data.shared_mem_size;
+*/
+                       mali_shared_mem_size = totalram_pages * 4 * 1024;
+                       /*ddr_get_cap();*/
+               }
+
+               if (0 == mali_dedicated_mem_start && 0 == mali_dedicated_mem_size && 0 == mali_shared_mem_size) {
+                       /* No GPU memory specified */
+                       return _MALI_OSK_ERR_INVALID_ARGS;
+               }
+
+               MALI_DEBUG_PRINT(2, ("Using device defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
+                                    mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
+       } else {
+               MALI_DEBUG_PRINT(2, ("Using module defined memory settings (dedicated: 0x%08X@0x%08X, shared: 0x%08X)\n",
+                                    mali_dedicated_mem_size, mali_dedicated_mem_start, mali_shared_mem_size));
+       }
+
+       if (0 < mali_dedicated_mem_size && 0 != mali_dedicated_mem_start) {
+               /* Dedicated memory */
+               ret = mali_memory_core_resource_dedicated_memory(mali_dedicated_mem_start, mali_dedicated_mem_size);
+               if (_MALI_OSK_ERR_OK != ret) {
+                       MALI_PRINT_ERROR(("Failed to register dedicated memory\n"));
+                       mali_memory_terminate();
+                       return ret;
+               }
+       }
+
+       if (0 < mali_shared_mem_size) {
+               /* Shared OS memory */
+               ret = mali_memory_core_resource_os_memory(mali_shared_mem_size);
+               if (_MALI_OSK_ERR_OK != ret) {
+                       MALI_PRINT_ERROR(("Failed to register shared OS memory\n"));
+                       mali_memory_terminate();
+                       return ret;
+               }
+       }
+
+       if (0 == mali_fb_start && 0 == mali_fb_size) {
+               /* Frame buffer settings are not overridden by module parameters, so use device settings */
+               struct _mali_osk_device_data data = { 0, };
+
+               if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
+                       /* Use device specific settings (if defined) */
+                       mali_fb_start = data.fb_start;
+                       mali_fb_size = data.fb_size;
+               }
+
+               MALI_DEBUG_PRINT(2, ("Using device defined frame buffer settings (0x%08X@0x%08X)\n",
+                                    mali_fb_size, mali_fb_start));
+       } else {
+               MALI_DEBUG_PRINT(2, ("Using module defined frame buffer settings (0x%08X@0x%08X)\n",
+                                    mali_fb_size, mali_fb_start));
+       }
+
+       if (0 != mali_fb_size) {
+               /* Register frame buffer */
+               ret = mali_mem_validation_add_range(mali_fb_start, mali_fb_size);
+               if (_MALI_OSK_ERR_OK != ret) {
+                       MALI_PRINT_ERROR(("Failed to register frame buffer memory region\n"));
+                       mali_memory_terminate();
+                       return ret;
+               }
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static void mali_detect_gpu_class(void)
+{
+       u32 number_of_pp_cores = 0;
+       u32 number_of_l2_caches = 0;
+
+       mali_resource_count(&number_of_pp_cores, &number_of_l2_caches);
+       if (number_of_l2_caches > 1) {
+               mali_gpu_class_is_mali450 = MALI_TRUE;
+       }
+}
+
+_mali_osk_errcode_t mali_initialize_subsystems(void)
+{
+       _mali_osk_errcode_t err;
+       struct mali_pmu_core *pmu;
+
+       mali_pp_job_initialize();
+
+       err = mali_session_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto session_init_failed;
+
+#if defined(CONFIG_MALI400_PROFILING)
+       err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
+       if (_MALI_OSK_ERR_OK != err) {
+               /* No biggie if we weren't able to initialize the profiling */
+               MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
+       }
+#endif
+
+       err = mali_memory_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto memory_init_failed;
+
+       /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */
+       err = mali_parse_config_memory();
+       if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed;
+
+       err = mali_set_global_gpu_base_address();
+       if (_MALI_OSK_ERR_OK != err) goto set_global_gpu_base_address_failed;
+
+       /* Detect gpu class according to l2 cache number */
+       mali_detect_gpu_class();
+
+       err = mali_check_shared_interrupts();
+       if (_MALI_OSK_ERR_OK != err) goto check_shared_interrupts_failed;
+
+       err = mali_pp_scheduler_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed;
+
+       /* Initialize the power management module */
+       err = mali_pm_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto pm_init_failed;
+
+       /* Initialize the MALI PMU */
+       err = mali_parse_config_pmu();
+       if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed;
+
+       /* Make sure the power stays on for the rest of this function */
+       err = _mali_osk_pm_dev_ref_add();
+       if (_MALI_OSK_ERR_OK != err) goto pm_always_on_failed;
+
+       /*
+        * If run-time PM is used, then the mali_pm module has now already been
+        * notified that the power now is on (through the resume callback functions).
+        * However, if run-time PM is not used, then there will probably not be any
+        * calls to the resume callback functions, so we need to explicitly tell it
+        * that the power is on.
+        */
+       mali_pm_set_power_is_on();
+
+       /* Reset PMU HW and ensure all Mali power domains are on */
+       pmu = mali_pmu_get_global_pmu_core();
+       if (NULL != pmu) {
+               err = mali_pmu_reset(pmu);
+               if (_MALI_OSK_ERR_OK != err) goto pmu_reset_failed;
+       }
+
+       /* Detect which Mali GPU we are dealing with */
+       err = mali_parse_product_info();
+       if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed;
+
+       /* The global_product_id is now populated with the correct Mali GPU */
+
+       /* Create PM domains only if PMU exists */
+       if (NULL != pmu) {
+               err = mali_create_pm_domains();
+               if (_MALI_OSK_ERR_OK != err) goto pm_domain_failed;
+       }
+
+       /* Initialize MMU module */
+       err = mali_mmu_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed;
+
+       if (mali_is_mali450()) {
+               err = mali_dlbu_initialize();
+               if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed;
+
+               err = mali_parse_config_dma();
+               if (_MALI_OSK_ERR_OK != err) goto dma_parsing_failed;
+       }
+
+       /* Start configuring the actual Mali hardware. */
+       err = mali_parse_config_l2_cache();
+       if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
+       err = mali_parse_config_groups();
+       if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
+
+       /* Initialize the schedulers */
+       err = mali_scheduler_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed;
+       err = mali_gp_scheduler_initialize();
+       if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed;
+
+       /* PP scheduler population can't fail */
+       mali_pp_scheduler_populate();
+
+       /* Initialize the GPU utilization tracking */
+       err = mali_utilization_init();
+       if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed;
+
+       /* Allowing the system to be turned off */
+       _mali_osk_pm_dev_ref_dec();
+
+       MALI_SUCCESS; /* all ok */
+
+       /* Error handling */
+
+utilization_init_failed:
+       mali_pp_scheduler_depopulate();
+       mali_gp_scheduler_terminate();
+gp_scheduler_init_failed:
+       mali_scheduler_terminate();
+scheduler_init_failed:
+config_parsing_failed:
+       mali_delete_groups(); /* Delete any groups not (yet) owned by a scheduler */
+       mali_delete_l2_cache_cores(); /* Delete L2 cache cores even if config parsing failed. */
+       {
+               struct mali_dma_core *dma = mali_dma_get_global_dma_core();
+               if (NULL != dma) mali_dma_delete(dma);
+       }
+dma_parsing_failed:
+       mali_dlbu_terminate();
+dlbu_init_failed:
+       mali_mmu_terminate();
+mmu_init_failed:
+       mali_pm_domain_terminate();
+pm_domain_failed:
+       /* Nothing to roll back */
+product_info_parsing_failed:
+       /* Nothing to roll back */
+pmu_reset_failed:
+       /* Allowing the system to be turned off */
+       _mali_osk_pm_dev_ref_dec();
+pm_always_on_failed:
+       pmu = mali_pmu_get_global_pmu_core();
+       if (NULL != pmu) {
+               mali_pmu_delete(pmu);
+       }
+parse_pmu_config_failed:
+       mali_pm_terminate();
+pm_init_failed:
+       mali_pp_scheduler_terminate();
+pp_scheduler_init_failed:
+check_shared_interrupts_failed:
+       global_gpu_base_address = 0;
+set_global_gpu_base_address_failed:
+       /* undoing mali_parse_config_memory() is done by mali_memory_terminate() */
+parse_memory_config_failed:
+       mali_memory_terminate();
+memory_init_failed:
+#if defined(CONFIG_MALI400_PROFILING)
+       _mali_osk_profiling_term();
+#endif
+       mali_session_terminate();
+session_init_failed:
+       mali_pp_job_terminate();
+       return err;
+}
+
+void mali_terminate_subsystems(void)
+{
+       struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+       struct mali_dma_core *dma = mali_dma_get_global_dma_core();
+
+       MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n"));
+
+       /* shut down subsystems in reverse order from startup */
+
+       /* We need the GPU to be powered up for the terminate sequence */
+       _mali_osk_pm_dev_ref_add();
+
+       mali_utilization_term();
+       mali_pp_scheduler_depopulate();
+       mali_gp_scheduler_terminate();
+       mali_scheduler_terminate();
+       mali_delete_l2_cache_cores();
+       if (mali_is_mali450()) {
+               mali_dlbu_terminate();
+       }
+       mali_mmu_terminate();
+       if (NULL != pmu) {
+               mali_pmu_delete(pmu);
+       }
+       if (NULL != dma) {
+               mali_dma_delete(dma);
+       }
+       mali_pm_terminate();
+       mali_memory_terminate();
+#if defined(CONFIG_MALI400_PROFILING)
+       _mali_osk_profiling_term();
+#endif
+
+       /* Allowing the system to be turned off */
+       _mali_osk_pm_dev_ref_dec();
+
+       mali_pp_scheduler_terminate();
+       mali_session_terminate();
+
+       mali_pp_job_terminate();
+}
+
+_mali_product_id_t mali_kernel_core_get_product_id(void)
+{
+       return global_product_id;
+}
+
+u32 mali_kernel_core_get_gpu_major_version(void)
+{
+       return global_gpu_major_version;
+}
+
+u32 mali_kernel_core_get_gpu_minor_version(void)
+{
+       return global_gpu_minor_version;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args )
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       /* check compatability */
+       if ( args->version == _MALI_UK_API_VERSION ) {
+               args->compatible = 1;
+       } else {
+               args->compatible = 0;
+       }
+
+       args->version = _MALI_UK_API_VERSION; /* report our version */
+
+       /* success regardless of being compatible or not */
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args )
+{
+       _mali_osk_errcode_t err;
+       _mali_osk_notification_t * notification;
+       _mali_osk_notification_queue_t *queue;
+
+       /* check input */
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
+
+       /* if the queue does not exist we're currently shutting down */
+       if (NULL == queue) {
+               MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
+               args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
+               MALI_SUCCESS;
+       }
+
+       /* receive a notification, might sleep */
+       err = _mali_osk_notification_queue_receive(queue, &notification);
+       if (_MALI_OSK_ERR_OK != err) {
+               MALI_ERROR(err); /* errcode returned, pass on to caller */
+       }
+
+       /* copy the buffer to the user */
+       args->type = (_mali_uk_notification_type)notification->notification_type;
+       _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size);
+
+       /* finished with the notification */
+       _mali_osk_notification_delete( notification );
+
+       MALI_SUCCESS; /* all ok */
+}
+
+_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args )
+{
+       _mali_osk_notification_t * notification;
+       _mali_osk_notification_queue_t *queue;
+
+       /* check input */
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
+
+       /* if the queue does not exist we're currently shutting down */
+       if (NULL == queue) {
+               MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
+               MALI_SUCCESS;
+       }
+
+       notification = _mali_osk_notification_create(args->type, 0);
+       if (NULL == notification) {
+               MALI_PRINT_ERROR( ("Failed to create notification object\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       _mali_osk_notification_queue_send(queue, notification);
+
+       MALI_SUCCESS; /* all ok */
+}
+
+_mali_osk_errcode_t _mali_ukk_request_high_priority( _mali_uk_request_high_priority_s *args )
+{
+       struct mali_session_data *session;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session = (struct mali_session_data *) args->ctx;
+
+       if (!session->use_high_priority_job_queue) {
+               session->use_high_priority_job_queue = MALI_TRUE;
+               MALI_DEBUG_PRINT(2, ("Session 0x%08X with pid %d was granted higher priority.\n", session, _mali_osk_get_pid()));
+       }
+
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_open(void **context)
+{
+       u32 i;
+       struct mali_session_data *session;
+
+       /* allocated struct to track this session */
+       session = (struct mali_session_data *)_mali_osk_calloc(1, sizeof(struct mali_session_data));
+       MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_NOMEM);
+
+       MALI_DEBUG_PRINT(3, ("Session starting\n"));
+
+       /* create a response queue for this session */
+       session->ioctl_queue = _mali_osk_notification_queue_init();
+       if (NULL == session->ioctl_queue) {
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       session->page_directory = mali_mmu_pagedir_alloc();
+       if (NULL == session->page_directory) {
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session->page_directory, MALI_DLBU_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE)) {
+               MALI_PRINT_ERROR(("Failed to map DLBU page into session\n"));
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       if (0 != mali_dlbu_phys_addr) {
+               mali_mmu_pagedir_update(session->page_directory, MALI_DLBU_VIRT_ADDR, mali_dlbu_phys_addr,
+                                       _MALI_OSK_MALI_PAGE_SIZE, MALI_MMU_FLAGS_DEFAULT);
+       }
+
+       if (_MALI_OSK_ERR_OK != mali_memory_session_begin(session)) {
+               mali_mmu_pagedir_free(session->page_directory);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       /* Create soft system. */
+       session->soft_job_system = mali_soft_job_system_create(session);
+       if (NULL == session->soft_job_system) {
+               mali_memory_session_end(session);
+               mali_mmu_pagedir_free(session->page_directory);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       /* Create timeline system. */
+       session->timeline_system = mali_timeline_system_create(session);
+       if (NULL == session->timeline_system) {
+               mali_soft_job_system_destroy(session->soft_job_system);
+               mali_memory_session_end(session);
+               mali_mmu_pagedir_free(session->page_directory);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&session->number_of_window_jobs, 0)) {
+               MALI_DEBUG_PRINT_ERROR(("Initialization of atomic number_of_window_jobs failed.\n"));
+               mali_timeline_system_destroy(session->timeline_system);
+               mali_soft_job_system_destroy(session->soft_job_system);
+               mali_memory_session_end(session);
+               mali_mmu_pagedir_free(session->page_directory);
+               _mali_osk_notification_queue_term(session->ioctl_queue);
+               _mali_osk_free(session);
+               return _MALI_OSK_ERR_FAULT;
+       }
+#endif
+
+       session->use_high_priority_job_queue = MALI_FALSE;
+
+       /* Initialize list of PP jobs on this session. */
+       _MALI_OSK_INIT_LIST_HEAD(&session->pp_job_list);
+
+       /* Initialize the pp_job_fb_lookup_list array used to quickly lookup jobs from a given frame builder */
+       for (i = 0; i < MALI_PP_JOB_FB_LOOKUP_LIST_SIZE; ++i) {
+               _MALI_OSK_INIT_LIST_HEAD(&session->pp_job_fb_lookup_list[i]);
+       }
+
+       *context = (void*)session;
+
+       /* Add session to the list of all sessions. */
+       mali_session_add(session);
+
+       MALI_DEBUG_PRINT(2, ("Session started\n"));
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_close(void **context)
+{
+       struct mali_session_data *session;
+       MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
+       session = (struct mali_session_data *)*context;
+
+       MALI_DEBUG_PRINT(3, ("Session ending\n"));
+
+       MALI_DEBUG_ASSERT_POINTER(session->soft_job_system);
+       MALI_DEBUG_ASSERT_POINTER(session->timeline_system);
+
+       /* Remove session from list of all sessions. */
+       mali_session_remove(session);
+
+       /* This flag is used to prevent queueing of jobs due to activation. */
+       session->is_aborting = MALI_TRUE;
+
+       /* Stop the soft job timer. */
+       mali_timeline_system_stop_timer(session->timeline_system);
+
+       /* Abort queued and running GP and PP jobs. */
+       mali_gp_scheduler_abort_session(session);
+       mali_pp_scheduler_abort_session(session);
+
+       /* Abort the soft job system. */
+       mali_soft_job_system_abort(session->soft_job_system);
+
+       /* Force execution of all pending bottom half processing for GP and PP. */
+       _mali_osk_wq_flush();
+
+       /* The session PP list should now be empty. */
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&session->pp_job_list));
+
+       /* At this point the GP and PP scheduler no longer has any jobs queued or running from this
+        * session, and all soft jobs in the soft job system has been destroyed. */
+
+       /* Any trackers left in the timeline system are directly or indirectly waiting on external
+        * sync fences.  Cancel all sync fence waiters to trigger activation of all remaining
+        * trackers.  This call will sleep until all timelines are empty. */
+       mali_timeline_system_abort(session->timeline_system);
+
+       /* Flush pending work.
+        * Needed to make sure all bottom half processing related to this
+        * session has been completed, before we free internal data structures.
+        */
+       _mali_osk_wq_flush();
+
+       /* Destroy timeline system. */
+       mali_timeline_system_destroy(session->timeline_system);
+       session->timeline_system = NULL;
+
+       /* Destroy soft system. */
+       mali_soft_job_system_destroy(session->soft_job_system);
+       session->soft_job_system = NULL;
+
+       MALI_DEBUG_CODE( {
+               /* Check that the pp_job_fb_lookup_list array is empty. */
+               u32 i;
+               for (i = 0; i < MALI_PP_JOB_FB_LOOKUP_LIST_SIZE; ++i)
+               {
+                       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&session->pp_job_fb_lookup_list[i]));
+               }
+       });
+
+       /* Free remaining memory allocated to this session */
+       mali_memory_session_end(session);
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       _mali_osk_atomic_term(&session->number_of_window_jobs);
+#endif
+
+       /* Free session data structures */
+       mali_mmu_pagedir_free(session->page_directory);
+       _mali_osk_notification_queue_term(session->ioctl_queue);
+       _mali_osk_free(session);
+
+       *context = NULL;
+
+       MALI_DEBUG_PRINT(2, ("Session has ended\n"));
+
+       MALI_SUCCESS;
+}
+
+#if MALI_STATE_TRACKING
+u32 _mali_kernel_core_dump_state(char* buf, u32 size)
+{
+       int n = 0; /* Number of bytes written to buf */
+
+       n += mali_gp_scheduler_dump_state(buf + n, size - n);
+       n += mali_pp_scheduler_dump_state(buf + n, size - n);
+
+       return n;
+}
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_core.h b/drivers/gpu/arm/mali400/mali/common/mali_kernel_core.h
new file mode 100755 (executable)
index 0000000..f0c0b0f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_KERNEL_CORE_H__
+#define __MALI_KERNEL_CORE_H__
+
+#include "mali_osk.h"
+
+typedef enum {
+       _MALI_PRODUCT_ID_UNKNOWN,
+       _MALI_PRODUCT_ID_MALI200,
+       _MALI_PRODUCT_ID_MALI300,
+       _MALI_PRODUCT_ID_MALI400,
+       _MALI_PRODUCT_ID_MALI450,
+} _mali_product_id_t;
+
+extern mali_bool mali_gpu_class_is_mali450;
+
+_mali_osk_errcode_t mali_initialize_subsystems(void);
+
+void mali_terminate_subsystems(void);
+
+_mali_product_id_t mali_kernel_core_get_product_id(void);
+
+u32 mali_kernel_core_get_gpu_major_version(void);
+
+u32 mali_kernel_core_get_gpu_minor_version(void);
+
+u32 _mali_kernel_core_dump_state(char* buf, u32 size);
+
+MALI_STATIC_INLINE mali_bool mali_is_mali450(void)
+{
+#if defined(CONFIG_MALI450)
+       return mali_gpu_class_is_mali450;
+#else
+       return MALI_FALSE;
+#endif
+}
+
+MALI_STATIC_INLINE mali_bool mali_is_mali400(void)
+{
+#if !defined(CONFIG_MALI450)
+       return MALI_TRUE;
+#else
+       return !mali_gpu_class_is_mali450;
+#endif
+}
+
+#endif /* __MALI_KERNEL_CORE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_descriptor_mapping.c b/drivers/gpu/arm/mali400/mali/common/mali_kernel_descriptor_mapping.c
new file mode 100755 (executable)
index 0000000..a3f7026
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_osk.h"
+#include "mali_osk_bitops.h"
+
+#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1))
+
+/**
+ * Allocate a descriptor table capable of holding 'count' mappings
+ * @param count Number of mappings in the table
+ * @return Pointer to a new table, NULL on error
+ */
+static mali_descriptor_table * descriptor_table_alloc(int count);
+
+/**
+ * Free a descriptor table
+ * @param table The table to free
+ */
+static void descriptor_table_free(mali_descriptor_table * table);
+
+mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries)
+{
+       mali_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(mali_descriptor_mapping));
+
+       init_entries = MALI_PAD_INT(init_entries);
+       max_entries = MALI_PAD_INT(max_entries);
+
+       if (NULL != map) {
+               map->table = descriptor_table_alloc(init_entries);
+               if (NULL != map->table) {
+                       map->lock = _mali_osk_mutex_rw_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP);
+                       if (NULL != map->lock) {
+                               _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
+                               map->max_nr_mappings_allowed = max_entries;
+                               map->current_nr_mappings = init_entries;
+                               return map;
+                       }
+                       descriptor_table_free(map->table);
+               }
+               _mali_osk_free(map);
+       }
+       return NULL;
+}
+
+void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map)
+{
+       descriptor_table_free(map->table);
+       _mali_osk_mutex_rw_term(map->lock);
+       _mali_osk_free(map);
+}
+
+_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *odescriptor)
+{
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+       int new_descriptor;
+
+       MALI_DEBUG_ASSERT_POINTER(map);
+       MALI_DEBUG_ASSERT_POINTER(odescriptor);
+
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
+       new_descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings);
+       if (new_descriptor == map->current_nr_mappings) {
+               /* no free descriptor, try to expand the table */
+               mali_descriptor_table * new_table, * old_table;
+               if (map->current_nr_mappings >= map->max_nr_mappings_allowed) goto unlock_and_exit;
+
+               map->current_nr_mappings += BITS_PER_LONG;
+               new_table = descriptor_table_alloc(map->current_nr_mappings);
+               if (NULL == new_table) goto unlock_and_exit;
+
+               old_table = map->table;
+               _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG);
+               _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*));
+               map->table = new_table;
+               descriptor_table_free(old_table);
+       }
+
+       /* we have found a valid descriptor, set the value and usage bit */
+       _mali_osk_set_nonatomic_bit(new_descriptor, map->table->usage);
+       map->table->mappings[new_descriptor] = target;
+       *odescriptor = new_descriptor;
+       err = _MALI_OSK_ERR_OK;
+
+unlock_and_exit:
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+       MALI_ERROR(err);
+}
+
+void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*))
+{
+       int i;
+
+       MALI_DEBUG_ASSERT_POINTER(map);
+       MALI_DEBUG_ASSERT_POINTER(callback);
+
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
+       /* id 0 is skipped as it's an reserved ID not mapping to anything */
+       for (i = 1; i < map->current_nr_mappings; ++i) {
+               if (_mali_osk_test_bit(i, map->table->usage)) {
+                       callback(i, map->table->mappings[i]);
+               }
+       }
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+}
+
+_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target)
+{
+       _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT;
+       MALI_DEBUG_ASSERT_POINTER(map);
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
+       if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) {
+               *target = map->table->mappings[descriptor];
+               result = _MALI_OSK_ERR_OK;
+       } else *target = NULL;
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+       MALI_ERROR(result);
+}
+
+_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target)
+{
+       _mali_osk_errcode_t result = _MALI_OSK_ERR_FAULT;
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
+       if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) {
+               map->table->mappings[descriptor] = target;
+               result = _MALI_OSK_ERR_OK;
+       }
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+       MALI_ERROR(result);
+}
+
+void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor)
+{
+       void *old_value = NULL;
+
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
+       if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) {
+               old_value = map->table->mappings[descriptor];
+               map->table->mappings[descriptor] = NULL;
+               _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
+       }
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+
+       return old_value;
+}
+
+static mali_descriptor_table * descriptor_table_alloc(int count)
+{
+       mali_descriptor_table * table;
+
+       table = _mali_osk_calloc(1, sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count));
+
+       if (NULL != table) {
+               table->usage = (u32*)((u8*)table + sizeof(mali_descriptor_table));
+               table->mappings = (void**)((u8*)table + sizeof(mali_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG));
+       }
+
+       return table;
+}
+
+static void descriptor_table_free(mali_descriptor_table * table)
+{
+       _mali_osk_free(table);
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_descriptor_mapping.h b/drivers/gpu/arm/mali400/mali/common/mali_kernel_descriptor_mapping.h
new file mode 100755 (executable)
index 0000000..59115bd
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_kernel_descriptor_mapping.h
+ */
+
+#ifndef __MALI_KERNEL_DESCRIPTOR_MAPPING_H__
+#define __MALI_KERNEL_DESCRIPTOR_MAPPING_H__
+
+#include "mali_osk.h"
+
+/**
+ * The actual descriptor mapping table, never directly accessed by clients
+ */
+typedef struct mali_descriptor_table {
+       u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */
+       void** mappings; /**< Array of the pointers the descriptors map to */
+} mali_descriptor_table;
+
+/**
+ * The descriptor mapping object
+ * Provides a separate namespace where we can map an integer to a pointer
+ */
+typedef struct mali_descriptor_mapping {
+       _mali_osk_mutex_rw_t *lock; /**< Lock protecting access to the mapping object */
+       int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */
+       int current_nr_mappings; /**< Current number of possible mappings */
+       mali_descriptor_table * table; /**< Pointer to the current mapping table */
+} mali_descriptor_mapping;
+
+/**
+ * Create a descriptor mapping object
+ * Create a descriptor mapping capable of holding init_entries growable to max_entries
+ * @param init_entries Number of entries to preallocate memory for
+ * @param max_entries Number of entries to max support
+ * @return Pointer to a descriptor mapping object, NULL on failure
+ */
+mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int max_entries);
+
+/**
+ * Destroy a descriptor mapping object
+ * @param map The map to free
+ */
+void mali_descriptor_mapping_destroy(mali_descriptor_mapping * map);
+
+/**
+ * Allocate a new mapping entry (descriptor ID)
+ * Allocates a new entry in the map.
+ * @param map The map to allocate a new entry in
+ * @param target The value to map to
+ * @return The descriptor allocated, a negative value on error
+ */
+_mali_osk_errcode_t mali_descriptor_mapping_allocate_mapping(mali_descriptor_mapping * map, void * target, int *descriptor);
+
+/**
+ * Get the value mapped to by a descriptor ID
+ * @param map The map to lookup the descriptor id in
+ * @param descriptor The descriptor ID to lookup
+ * @param target Pointer to a pointer which will receive the stored value
+ * @return 0 on successful lookup, negative on error
+ */
+_mali_osk_errcode_t mali_descriptor_mapping_get(mali_descriptor_mapping * map, int descriptor, void** target);
+
+/**
+ * Set the value mapped to by a descriptor ID
+ * @param map The map to lookup the descriptor id in
+ * @param descriptor The descriptor ID to lookup
+ * @param target Pointer to replace the current value with
+ * @return 0 on successful lookup, negative on error
+ */
+_mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, int descriptor, void * target);
+
+/**
+ * Call the specified callback function for each descriptor in map.
+ * Entire function is mutex protected.
+ * @param map The map to do callbacks for
+ * @param callback A callback function which will be calle for each entry in map
+ */
+void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (*callback)(int, void*));
+
+/**
+ * Free the descriptor ID
+ * For the descriptor to be reused it has to be freed
+ * @param map The map to free the descriptor from
+ * @param descriptor The descriptor ID to free
+ *
+ * @return old value of descriptor mapping
+ */
+void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor);
+
+#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_utilization.c b/drivers/gpu/arm/mali400/mali/common/mali_kernel_utilization.c
new file mode 100755 (executable)
index 0000000..2775fde
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_utilization.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_scheduler.h"
+
+/* Thresholds for GP bound detection. */
+#define MALI_GP_BOUND_GP_UTILIZATION_THRESHOLD 240
+#define MALI_GP_BOUND_PP_UTILIZATION_THRESHOLD 250
+
+/* Define how often to calculate and report GPU utilization, in milliseconds */
+static _mali_osk_spinlock_irq_t *time_data_lock;
+
+static u32 num_running_gp_cores;
+static u32 num_running_pp_cores;
+
+static u64 work_start_time_gpu = 0;
+static u64 work_start_time_gp = 0;
+static u64 work_start_time_pp = 0;
+static u64 accumulated_work_time_gpu = 0;
+static u64 accumulated_work_time_gp = 0;
+static u64 accumulated_work_time_pp = 0;
+
+static u64 period_start_time = 0;
+static _mali_osk_timer_t *utilization_timer = NULL;
+static mali_bool timer_running = MALI_FALSE;
+
+static u32 last_utilization_gpu = 0 ;
+static u32 last_utilization_gp = 0 ;
+static u32 last_utilization_pp = 0 ;
+
+extern u32 mali_utilization_timeout;
+void (*mali_utilization_callback)(struct mali_gpu_utilization_data *data) = NULL;
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+extern void mali_power_performance_policy_callback(struct mali_gpu_utilization_data *data);
+#define NUMBER_OF_NANOSECONDS_PER_SECOND  1000000000ULL
+
+static u32 calculate_window_render_fps(u64 time_period)
+{
+       u32 max_window_number;
+       u64 tmp;
+       u64 max = time_period;
+       u32 leading_zeroes;
+       u32 shift_val;
+       u32 time_period_shift;
+       u32 max_window_number_shift;
+       u32 ret_val;
+
+       max_window_number = mali_session_max_window_num();
+       /* To avoid float division, extend the dividend to ns unit */
+       tmp = (u64)max_window_number * NUMBER_OF_NANOSECONDS_PER_SECOND;
+       if (tmp > time_period) {
+               max = tmp;
+       }
+
+       /*
+        * We may have 64-bit values, a dividend or a divisor or both
+        * To avoid dependencies to a 64-bit divider, we shift down the two values
+        * equally first.
+        */
+       leading_zeroes = _mali_osk_clz((u32)(max >> 32));
+       shift_val = 32 - leading_zeroes;
+
+       time_period_shift = (u32)(time_period >> shift_val);
+       max_window_number_shift = (u32)(tmp >> shift_val);
+
+       ret_val = max_window_number_shift / time_period_shift;
+
+       return ret_val;
+}
+#endif  /* defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY) */
+
+static void calculate_gpu_utilization(void* arg)
+{
+       u64 time_now;
+       u64 time_period;
+       u32 leading_zeroes;
+       u32 shift_val;
+       u32 work_normalized_gpu;
+       u32 work_normalized_gp;
+       u32 work_normalized_pp;
+       u32 period_normalized;
+       u32 utilization_gpu;
+       u32 utilization_gp;
+       u32 utilization_pp;
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       u32 window_render_fps;
+#endif
+
+       _mali_osk_spinlock_irq_lock(time_data_lock);
+
+       if (accumulated_work_time_gpu == 0 && work_start_time_gpu == 0) {
+               /*
+                * No work done for this period
+                * - No need to reschedule timer
+                * - Report zero usage
+                */
+               timer_running = MALI_FALSE;
+
+               last_utilization_gpu = 0;
+               last_utilization_gp = 0;
+               last_utilization_pp = 0;
+
+               _mali_osk_spinlock_irq_unlock(time_data_lock);
+
+               if (NULL != mali_utilization_callback) {
+                       struct mali_gpu_utilization_data data = { 0, };
+                       mali_utilization_callback(&data);
+               }
+
+               mali_scheduler_hint_disable(MALI_SCHEDULER_HINT_GP_BOUND);
+
+               return;
+       }
+
+       time_now = _mali_osk_time_get_ns();
+
+       time_period = time_now - period_start_time;
+
+       /* If we are currently busy, update working period up to now */
+       if (work_start_time_gpu != 0) {
+               accumulated_work_time_gpu += (time_now - work_start_time_gpu);
+               work_start_time_gpu = time_now;
+
+               /* GP and/or PP will also be busy if the GPU is busy at this point */
+
+               if (work_start_time_gp != 0) {
+                       accumulated_work_time_gp += (time_now - work_start_time_gp);
+                       work_start_time_gp = time_now;
+               }
+
+               if (work_start_time_pp != 0) {
+                       accumulated_work_time_pp += (time_now - work_start_time_pp);
+                       work_start_time_pp = time_now;
+               }
+       }
+
+       /*
+        * We have two 64-bit values, a dividend and a divisor.
+        * To avoid dependencies to a 64-bit divider, we shift down the two values
+        * equally first.
+        * We shift the dividend up and possibly the divisor down, making the result X in 256.
+        */
+
+       /* Shift the 64-bit values down so they fit inside a 32-bit integer */
+       leading_zeroes = _mali_osk_clz((u32)(time_period >> 32));
+       shift_val = 32 - leading_zeroes;
+       work_normalized_gpu = (u32)(accumulated_work_time_gpu >> shift_val);
+       work_normalized_gp = (u32)(accumulated_work_time_gp >> shift_val);
+       work_normalized_pp = (u32)(accumulated_work_time_pp >> shift_val);
+       period_normalized = (u32)(time_period >> shift_val);
+
+       /*
+        * Now, we should report the usage in parts of 256
+        * this means we must shift up the dividend or down the divisor by 8
+        * (we could do a combination, but we just use one for simplicity,
+        * but the end result should be good enough anyway)
+        */
+       if (period_normalized > 0x00FFFFFF) {
+               /* The divisor is so big that it is safe to shift it down */
+               period_normalized >>= 8;
+       } else {
+               /*
+                * The divisor is so small that we can shift up the dividend, without loosing any data.
+                * (dividend is always smaller than the divisor)
+                */
+               work_normalized_gpu <<= 8;
+               work_normalized_gp <<= 8;
+               work_normalized_pp <<= 8;
+       }
+
+       utilization_gpu = work_normalized_gpu / period_normalized;
+       utilization_gp = work_normalized_gp / period_normalized;
+       utilization_pp = work_normalized_pp / period_normalized;
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       window_render_fps = calculate_window_render_fps(time_period);
+#endif
+
+       last_utilization_gpu = utilization_gpu;
+       last_utilization_gp = utilization_gp;
+       last_utilization_pp = utilization_pp;
+
+       if ((MALI_GP_BOUND_GP_UTILIZATION_THRESHOLD < last_utilization_gp) &&
+           (MALI_GP_BOUND_PP_UTILIZATION_THRESHOLD > last_utilization_pp)) {
+               mali_scheduler_hint_enable(MALI_SCHEDULER_HINT_GP_BOUND);
+       } else {
+               mali_scheduler_hint_disable(MALI_SCHEDULER_HINT_GP_BOUND);
+       }
+
+       /* starting a new period */
+       accumulated_work_time_gpu = 0;
+       accumulated_work_time_gp = 0;
+       accumulated_work_time_pp = 0;
+       period_start_time = time_now;
+
+       _mali_osk_spinlock_irq_unlock(time_data_lock);
+
+       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout));
+
+       if (NULL != mali_utilization_callback) {
+               struct mali_gpu_utilization_data data = {
+                       utilization_gpu, utilization_gp, utilization_pp,
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+                       window_render_fps, window_render_fps
+#endif
+               };
+               mali_utilization_callback(&data);
+       }
+}
+
+_mali_osk_errcode_t mali_utilization_init(void)
+{
+#if USING_GPU_UTILIZATION
+       struct _mali_osk_device_data data;
+       if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
+               /* Use device specific settings (if defined) */
+               if (0 != data.utilization_interval) {
+                       mali_utilization_timeout = data.utilization_interval;
+               }
+               if (NULL != data.utilization_callback) {
+                       mali_utilization_callback = data.utilization_callback;
+                       MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: Platform has it's own policy \n"));
+                       MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: Utilization handler installed with interval %u\n", mali_utilization_timeout));
+               }
+       }
+#endif
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       if (mali_utilization_callback == NULL) {
+               MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: MALI Power Performance Policy Algorithm \n"));
+               mali_utilization_callback = mali_power_performance_policy_callback;
+       }
+#endif
+
+       if (NULL == mali_utilization_callback) {
+               MALI_DEBUG_PRINT(2, ("Mali GPU Utilization: No utilization handler installed\n"));
+       }
+
+       time_data_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_UTILIZATION);
+
+       if (NULL == time_data_lock) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       num_running_gp_cores = 0;
+       num_running_pp_cores = 0;
+
+       utilization_timer = _mali_osk_timer_init();
+       if (NULL == utilization_timer) {
+               _mali_osk_spinlock_irq_term(time_data_lock);
+               return _MALI_OSK_ERR_FAULT;
+       }
+       _mali_osk_timer_setcallback(utilization_timer, calculate_gpu_utilization, NULL);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_utilization_suspend(void)
+{
+       _mali_osk_spinlock_irq_lock(time_data_lock);
+
+       if (timer_running == MALI_TRUE) {
+               timer_running = MALI_FALSE;
+               _mali_osk_spinlock_irq_unlock(time_data_lock);
+               _mali_osk_timer_del(utilization_timer);
+               return;
+       }
+
+       _mali_osk_spinlock_irq_unlock(time_data_lock);
+}
+
+void mali_utilization_term(void)
+{
+       if (NULL != utilization_timer) {
+               _mali_osk_timer_del(utilization_timer);
+               timer_running = MALI_FALSE;
+               _mali_osk_timer_term(utilization_timer);
+               utilization_timer = NULL;
+       }
+
+       _mali_osk_spinlock_irq_term(time_data_lock);
+}
+
+void mali_utilization_gp_start(void)
+{
+       _mali_osk_spinlock_irq_lock(time_data_lock);
+
+       ++num_running_gp_cores;
+       if (1 == num_running_gp_cores) {
+               u64 time_now = _mali_osk_time_get_ns();
+
+               /* First GP core started, consider GP busy from now and onwards */
+               work_start_time_gp = time_now;
+
+               if (0 == num_running_pp_cores) {
+                       /*
+                        * There are no PP cores running, so this is also the point
+                        * at which we consider the GPU to be busy as well.
+                        */
+                       work_start_time_gpu = time_now;
+               }
+
+               /* Start a new period (and timer) if needed */
+               if (timer_running != MALI_TRUE) {
+                       timer_running = MALI_TRUE;
+                       period_start_time = time_now;
+
+                       /* Clear session->number_of_window_jobs */
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+                       mali_session_max_window_num();
+#endif
+                       _mali_osk_spinlock_irq_unlock(time_data_lock);
+
+                       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout));
+               } else {
+                       _mali_osk_spinlock_irq_unlock(time_data_lock);
+               }
+       } else {
+               /* Nothing to do */
+               _mali_osk_spinlock_irq_unlock(time_data_lock);
+       }
+}
+
+void mali_utilization_pp_start(void)
+{
+       _mali_osk_spinlock_irq_lock(time_data_lock);
+
+       ++num_running_pp_cores;
+       if (1 == num_running_pp_cores) {
+               u64 time_now = _mali_osk_time_get_ns();
+
+               /* First PP core started, consider PP busy from now and onwards */
+               work_start_time_pp = time_now;
+
+               if (0 == num_running_gp_cores) {
+                       /*
+                        * There are no GP cores running, so this is also the point
+                        * at which we consider the GPU to be busy as well.
+                        */
+                       work_start_time_gpu = time_now;
+               }
+
+               /* Start a new period (and timer) if needed */
+               if (timer_running != MALI_TRUE) {
+                       timer_running = MALI_TRUE;
+                       period_start_time = time_now;
+
+                       /* Clear session->number_of_window_jobs */
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+                       mali_session_max_window_num();
+#endif
+                       _mali_osk_spinlock_irq_unlock(time_data_lock);
+
+                       _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(mali_utilization_timeout));
+               } else {
+                       _mali_osk_spinlock_irq_unlock(time_data_lock);
+               }
+       } else {
+               /* Nothing to do */
+               _mali_osk_spinlock_irq_unlock(time_data_lock);
+       }
+}
+
+void mali_utilization_gp_end(void)
+{
+       _mali_osk_spinlock_irq_lock(time_data_lock);
+
+       --num_running_gp_cores;
+       if (0 == num_running_gp_cores) {
+               u64 time_now = _mali_osk_time_get_ns();
+
+               /* Last GP core ended, consider GP idle from now and onwards */
+               accumulated_work_time_gp += (time_now - work_start_time_gp);
+               work_start_time_gp = 0;
+
+               if (0 == num_running_pp_cores) {
+                       /*
+                        * There are no PP cores running, so this is also the point
+                        * at which we consider the GPU to be idle as well.
+                        */
+                       accumulated_work_time_gpu += (time_now - work_start_time_gpu);
+                       work_start_time_gpu = 0;
+               }
+       }
+
+       _mali_osk_spinlock_irq_unlock(time_data_lock);
+}
+
+void mali_utilization_pp_end(void)
+{
+       _mali_osk_spinlock_irq_lock(time_data_lock);
+
+       --num_running_pp_cores;
+       if (0 == num_running_pp_cores) {
+               u64 time_now = _mali_osk_time_get_ns();
+
+               /* Last PP core ended, consider PP idle from now and onwards */
+               accumulated_work_time_pp += (time_now - work_start_time_pp);
+               work_start_time_pp = 0;
+
+               if (0 == num_running_gp_cores) {
+                       /*
+                        * There are no GP cores running, so this is also the point
+                        * at which we consider the GPU to be idle as well.
+                        */
+                       accumulated_work_time_gpu += (time_now - work_start_time_gpu);
+                       work_start_time_gpu = 0;
+               }
+       }
+
+       _mali_osk_spinlock_irq_unlock(time_data_lock);
+}
+
+u32 _mali_ukk_utilization_gp_pp(void)
+{
+       return last_utilization_gpu;
+}
+
+u32 _mali_ukk_utilization_gp(void)
+{
+       return last_utilization_gp;
+}
+
+u32 _mali_ukk_utilization_pp(void)
+{
+       return last_utilization_pp;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_utilization.h b/drivers/gpu/arm/mali400/mali/common/mali_kernel_utilization.h
new file mode 100755 (executable)
index 0000000..a249b3a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_KERNEL_UTILIZATION_H__
+#define __MALI_KERNEL_UTILIZATION_H__
+
+#include <linux/mali/mali_utgard.h>
+#include "mali_osk.h"
+
+extern void (*mali_utilization_callback)(struct mali_gpu_utilization_data *data);
+
+/**
+ * Initialize/start the Mali GPU utilization metrics reporting.
+ *
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t mali_utilization_init(void);
+
+/**
+ * Terminate the Mali GPU utilization metrics reporting
+ */
+void mali_utilization_term(void);
+
+/**
+ * Check if Mali utilization is enabled
+ */
+MALI_STATIC_INLINE mali_bool mali_utilization_enabled(void)
+{
+       return (NULL != mali_utilization_callback);
+}
+
+/**
+ * Should be called when a job is about to execute a GP job
+ */
+void mali_utilization_gp_start(void);
+
+/**
+ * Should be called when a job has completed executing a GP job
+ */
+void mali_utilization_gp_end(void);
+
+/**
+ * Should be called when a job is about to execute a PP job
+ */
+void mali_utilization_pp_start(void);
+
+/**
+ * Should be called when a job has completed executing a PP job
+ */
+void mali_utilization_pp_end(void);
+
+/**
+ * Should be called to stop the utilization timer during system suspend
+ */
+void mali_utilization_suspend(void);
+
+
+#endif /* __MALI_KERNEL_UTILIZATION_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_kernel_vsync.c b/drivers/gpu/arm/mali400/mali/common/mali_kernel_vsync.c
new file mode 100755 (executable)
index 0000000..e7dc3dd
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_ukk.h"
+
+#if defined(CONFIG_MALI400_PROFILING)
+#include "mali_osk_profiling.h"
+#endif
+
+_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args)
+{
+       _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event;
+       MALI_IGNORE(event); /* event is not used for release code, and that is OK */
+
+#if defined(CONFIG_MALI400_PROFILING)
+       /*
+        * Manually generate user space events in kernel space.
+        * This saves user space from calling kernel space twice in this case.
+        * We just need to remember to add pid and tid manually.
+        */
+       if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT) {
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+                                             _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
+       }
+
+       if (event==_MALI_UK_VSYNC_EVENT_END_WAIT) {
+
+               _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME |
+                                             MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+                                             MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+                                             _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
+       }
+#endif
+
+       MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));
+       MALI_SUCCESS;
+}
+
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_l2_cache.c b/drivers/gpu/arm/mali400/mali/common/mali_l2_cache.c
new file mode 100755 (executable)
index 0000000..f7f91f8
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_l2_cache.h"
+#include "mali_hw_core.h"
+#include "mali_scheduler.h"
+#include "mali_pm_domain.h"
+
+/**
+ * Size of the Mali L2 cache registers in bytes
+ */
+#define MALI400_L2_CACHE_REGISTERS_SIZE 0x30
+
+/**
+ * Mali L2 cache register numbers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_l2_cache_register {
+       MALI400_L2_CACHE_REGISTER_SIZE         = 0x0004,
+       MALI400_L2_CACHE_REGISTER_STATUS       = 0x0008,
+       /*unused                               = 0x000C */
+       MALI400_L2_CACHE_REGISTER_COMMAND      = 0x0010, /**< Misc cache commands, e.g. clear */
+       MALI400_L2_CACHE_REGISTER_CLEAR_PAGE   = 0x0014,
+       MALI400_L2_CACHE_REGISTER_MAX_READS    = 0x0018, /**< Limit of outstanding read requests */
+       MALI400_L2_CACHE_REGISTER_ENABLE       = 0x001C, /**< Enable misc cache features */
+       MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020,
+       MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024,
+       MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028,
+       MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C,
+} mali_l2_cache_register;
+
+/**
+ * Mali L2 cache commands
+ * These are the commands that can be sent to the Mali L2 cache unit
+ */
+typedef enum mali_l2_cache_command {
+       MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */
+       /* Read HW TRM carefully before adding/using other commands than the clear above */
+} mali_l2_cache_command;
+
+/**
+ * Mali L2 cache commands
+ * These are the commands that can be sent to the Mali L2 cache unit
+ */
+typedef enum mali_l2_cache_enable {
+       MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */
+       MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */
+       MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */
+} mali_l2_cache_enable;
+
+/**
+ * Mali L2 cache status bits
+ */
+typedef enum mali_l2_cache_status {
+       MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */
+       MALI400_L2_CACHE_STATUS_DATA_BUSY    = 0x02, /**< L2 cache is busy handling data requests */
+} mali_l2_cache_status;
+
+#define MALI400_L2_MAX_READS_DEFAULT 0x1C
+
+static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES] = { NULL, };
+static u32 mali_global_num_l2_cache_cores = 0;
+
+int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT;
+
+
+/* Local helper functions */
+static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val);
+
+
+static void mali_l2_cache_counter_lock(struct mali_l2_cache_core *cache)
+{
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_lock(cache->counter_lock);
+#else
+       _mali_osk_spinlock_lock(cache->counter_lock);
+#endif
+}
+
+static void mali_l2_cache_counter_unlock(struct mali_l2_cache_core *cache)
+{
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_unlock(cache->counter_lock);
+#else
+       _mali_osk_spinlock_unlock(cache->counter_lock);
+#endif
+}
+
+static void mali_l2_cache_command_lock(struct mali_l2_cache_core *cache)
+{
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_lock(cache->command_lock);
+#else
+       _mali_osk_spinlock_lock(cache->command_lock);
+#endif
+}
+
+static void mali_l2_cache_command_unlock(struct mali_l2_cache_core *cache)
+{
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_unlock(cache->command_lock);
+#else
+       _mali_osk_spinlock_unlock(cache->command_lock);
+#endif
+}
+
+struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource)
+{
+       struct mali_l2_cache_core *cache = NULL;
+
+       MALI_DEBUG_PRINT(4, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description));
+
+       if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES) {
+               MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n"));
+               return NULL;
+       }
+
+       cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core));
+       if (NULL != cache) {
+               cache->core_id =  mali_global_num_l2_cache_cores;
+               cache->counter_src0 = MALI_HW_CORE_NO_COUNTER;
+               cache->counter_src1 = MALI_HW_CORE_NO_COUNTER;
+               cache->pm_domain = NULL;
+               cache->mali_l2_status = MALI_L2_NORMAL;
+               if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE)) {
+                       MALI_DEBUG_CODE(u32 cache_size = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_SIZE));
+                       MALI_DEBUG_PRINT(2, ("Mali L2 cache: Created %s: % 3uK, %u-way, % 2ubyte cache line, % 3ubit external bus\n",
+                                            resource->description,
+                                            1 << (((cache_size >> 16) & 0xff) - 10),
+                                            1 << ((cache_size >> 8) & 0xff),
+                                            1 << (cache_size & 0xff),
+                                            1 << ((cache_size >> 24) & 0xff)));
+
+#ifdef MALI_UPPER_HALF_SCHEDULING
+                       cache->command_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
+#else
+                       cache->command_lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
+#endif
+                       if (NULL != cache->command_lock) {
+#ifdef MALI_UPPER_HALF_SCHEDULING
+                               cache->counter_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
+#else
+                               cache->counter_lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
+#endif
+                               if (NULL != cache->counter_lock) {
+                                       mali_l2_cache_reset(cache);
+
+                                       cache->last_invalidated_id = 0;
+
+                                       mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache;
+                                       mali_global_num_l2_cache_cores++;
+
+                                       return cache;
+                               } else {
+                                       MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description));
+                               }
+#ifdef MALI_UPPER_HALF_SCHEDULING
+                               _mali_osk_spinlock_irq_term(cache->command_lock);
+#else
+                               _mali_osk_spinlock_term(cache->command_lock);
+#endif
+                       } else {
+                               MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description));
+                       }
+
+                       mali_hw_core_delete(&cache->hw_core);
+               }
+
+               _mali_osk_free(cache);
+       } else {
+               MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n"));
+       }
+
+       return NULL;
+}
+
+void mali_l2_cache_delete(struct mali_l2_cache_core *cache)
+{
+       u32 i;
+
+       /* reset to defaults */
+       mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT);
+       mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT);
+
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_term(cache->counter_lock);
+       _mali_osk_spinlock_irq_term(cache->command_lock);
+#else
+       _mali_osk_spinlock_term(cache->command_lock);
+       _mali_osk_spinlock_term(cache->counter_lock);
+#endif
+
+       mali_hw_core_delete(&cache->hw_core);
+
+       for (i = 0; i < mali_global_num_l2_cache_cores; i++) {
+               if (mali_global_l2_cache_cores[i] == cache) {
+                       mali_global_l2_cache_cores[i] = NULL;
+                       mali_global_num_l2_cache_cores--;
+
+                       if (i != mali_global_num_l2_cache_cores) {
+                               /* We removed a l2 cache from the middle of the array -- move the last
+                                * l2 cache to the current position to close the gap */
+                               mali_global_l2_cache_cores[i] = mali_global_l2_cache_cores[mali_global_num_l2_cache_cores];
+                               mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = NULL;
+                       }
+
+                       break;
+               }
+       }
+
+       _mali_osk_free(cache);
+}
+
+u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache)
+{
+       return cache->core_id;
+}
+
+static void mali_l2_cache_core_set_counter_internal(struct mali_l2_cache_core *cache, u32 source_id, u32 counter)
+{
+       u32 value = 0; /* disabled src */
+       u32 reg_offset = 0;
+       mali_bool core_is_on;
+
+       MALI_DEBUG_ASSERT_POINTER(cache);
+
+       core_is_on = mali_l2_cache_lock_power_state(cache);
+
+       mali_l2_cache_counter_lock(cache);
+
+       switch (source_id) {
+       case 0:
+               cache->counter_src0 = counter;
+               reg_offset = MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0;
+               break;
+
+       case 1:
+               cache->counter_src1 = counter;
+               reg_offset = MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1;
+               break;
+
+       default:
+               MALI_DEBUG_ASSERT(0);
+               break;
+       }
+
+       if (MALI_L2_PAUSE == cache->mali_l2_status) {
+               mali_l2_cache_counter_unlock(cache);
+               mali_l2_cache_unlock_power_state(cache);
+               return;
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER != counter) {
+               value = counter;
+       }
+
+       if (MALI_TRUE == core_is_on) {
+               mali_hw_core_register_write(&cache->hw_core, reg_offset, value);
+       }
+
+       mali_l2_cache_counter_unlock(cache);
+       mali_l2_cache_unlock_power_state(cache);
+}
+
+void mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter)
+{
+       mali_l2_cache_core_set_counter_internal(cache, 0, counter);
+}
+
+void mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter)
+{
+       mali_l2_cache_core_set_counter_internal(cache, 1, counter);
+}
+
+u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache)
+{
+       return cache->counter_src0;
+}
+
+u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache)
+{
+       return cache->counter_src1;
+}
+
+void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1)
+{
+       MALI_DEBUG_ASSERT(NULL != src0);
+       MALI_DEBUG_ASSERT(NULL != value0);
+       MALI_DEBUG_ASSERT(NULL != src1);
+       MALI_DEBUG_ASSERT(NULL != value1);
+
+       /* Caller must hold the PM lock and know that we are powered on */
+
+       mali_l2_cache_counter_lock(cache);
+
+       if (MALI_L2_PAUSE == cache->mali_l2_status) {
+               mali_l2_cache_counter_unlock(cache);
+
+               return;
+       }
+
+       *src0 = cache->counter_src0;
+       *src1 = cache->counter_src1;
+
+       if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) {
+               *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0);
+       }
+
+       if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) {
+               *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1);
+       }
+
+       mali_l2_cache_counter_unlock(cache);
+}
+
+static void mali_l2_cache_reset_counters_all(void)
+{
+       int i;
+       u32 value;
+       struct mali_l2_cache_core *cache;
+       u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores();
+
+       for (i = 0; i < num_cores; i++) {
+               cache = mali_l2_cache_core_get_glob_l2_core(i);
+               if (MALI_TRUE == mali_l2_cache_lock_power_state(cache)) {
+                       mali_l2_cache_counter_lock(cache);
+
+                       if (MALI_L2_PAUSE == cache->mali_l2_status) {
+                               mali_l2_cache_counter_unlock(cache);
+                               mali_l2_cache_unlock_power_state(cache);
+                               return;
+                       }
+
+                       /* Reset performance counters */
+                       if (MALI_HW_CORE_NO_COUNTER == cache->counter_src0) {
+                               value = 0;
+                       } else {
+                               value = cache->counter_src0;
+                       }
+                       mali_hw_core_register_write(&cache->hw_core,
+                                                   MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value);
+
+                       if (MALI_HW_CORE_NO_COUNTER == cache->counter_src1) {
+                               value = 0;
+                       } else {
+                               value = cache->counter_src1;
+                       }
+                       mali_hw_core_register_write(&cache->hw_core,
+                                                   MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value);
+
+                       mali_l2_cache_counter_unlock(cache);
+               }
+
+               mali_l2_cache_unlock_power_state(cache);
+       }
+}
+
+
+struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index)
+{
+       if (mali_global_num_l2_cache_cores > index) {
+               return mali_global_l2_cache_cores[index];
+       }
+
+       return NULL;
+}
+
+u32 mali_l2_cache_core_get_glob_num_l2_cores(void)
+{
+       return mali_global_num_l2_cache_cores;
+}
+
+void mali_l2_cache_reset(struct mali_l2_cache_core *cache)
+{
+       /* Invalidate cache (just to keep it in a known state at startup) */
+       mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
+
+       mali_l2_cache_counter_lock(cache);
+
+       if (MALI_L2_PAUSE == cache->mali_l2_status) {
+               mali_l2_cache_counter_unlock(cache);
+
+               return;
+       }
+
+       /* Enable cache */
+       mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE);
+       mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads);
+
+       /* Restart any performance counters (if enabled) */
+       if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER) {
+               mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0);
+       }
+
+       if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER) {
+               mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1);
+       }
+
+       mali_l2_cache_counter_unlock(cache);
+}
+
+void mali_l2_cache_reset_all(void)
+{
+       int i;
+       u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores();
+
+       for (i = 0; i < num_cores; i++) {
+               mali_l2_cache_reset(mali_l2_cache_core_get_glob_l2_core(i));
+       }
+}
+
+void mali_l2_cache_invalidate(struct mali_l2_cache_core *cache)
+{
+       MALI_DEBUG_ASSERT_POINTER(cache);
+
+       if (NULL != cache) {
+               cache->last_invalidated_id = mali_scheduler_get_new_cache_order();
+               mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
+       }
+}
+
+mali_bool mali_l2_cache_invalidate_conditional(struct mali_l2_cache_core *cache, u32 id)
+{
+       MALI_DEBUG_ASSERT_POINTER(cache);
+
+       if (NULL != cache) {
+               /* If the last cache invalidation was done by a job with a higher id we
+                * don't have to flush. Since user space will store jobs w/ their
+                * corresponding memory in sequence (first job #0, then job #1, ...),
+                * we don't have to flush for job n-1 if job n has already invalidated
+                * the cache since we know for sure that job n-1's memory was already
+                * written when job n was started. */
+               if (((s32)id) <= ((s32)cache->last_invalidated_id)) {
+                       return MALI_FALSE;
+               } else {
+                       cache->last_invalidated_id = mali_scheduler_get_new_cache_order();
+               }
+
+               mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
+       }
+       return MALI_TRUE;
+}
+
+void mali_l2_cache_invalidate_all(void)
+{
+       u32 i;
+       for (i = 0; i < mali_global_num_l2_cache_cores; i++) {
+               /*additional check*/
+               if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i])) {
+                       _mali_osk_errcode_t ret;
+                       mali_global_l2_cache_cores[i]->last_invalidated_id = mali_scheduler_get_new_cache_order();
+                       ret = mali_l2_cache_send_command(mali_global_l2_cache_cores[i], MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
+                       if (_MALI_OSK_ERR_OK != ret) {
+                               MALI_PRINT_ERROR(("Failed to invalidate cache\n"));
+                       }
+               }
+               mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]);
+       }
+}
+
+void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages)
+{
+       u32 i;
+       for (i = 0; i < mali_global_num_l2_cache_cores; i++) {
+               /*additional check*/
+               if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_l2_cache_cores[i])) {
+                       u32 j;
+                       for (j = 0; j < num_pages; j++) {
+                               _mali_osk_errcode_t ret;
+                               ret = mali_l2_cache_send_command(mali_global_l2_cache_cores[i], MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[j]);
+                               if (_MALI_OSK_ERR_OK != ret) {
+                                       MALI_PRINT_ERROR(("Failed to invalidate page cache\n"));
+                               }
+                       }
+               }
+               mali_l2_cache_unlock_power_state(mali_global_l2_cache_cores[i]);
+       }
+}
+
+mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache)
+{
+       return mali_pm_domain_lock_state(cache->pm_domain);
+}
+
+void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache)
+{
+       return mali_pm_domain_unlock_state(cache->pm_domain);
+}
+
+/* -------- local helper functions below -------- */
+
+
+static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val)
+{
+       int i = 0;
+       const int loop_count = 100000;
+
+       /*
+        * Grab lock in order to send commands to the L2 cache in a serialized fashion.
+        * The L2 cache will ignore commands if it is busy.
+        */
+       mali_l2_cache_command_lock(cache);
+
+       if (MALI_L2_PAUSE == cache->mali_l2_status) {
+               mali_l2_cache_command_unlock(cache);
+               MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for L2 come back\n"));
+
+               MALI_ERROR( _MALI_OSK_ERR_BUSY );
+       }
+
+       /* First, wait for L2 cache command handler to go idle */
+
+       for (i = 0; i < loop_count; i++) {
+               if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY)) {
+                       break;
+               }
+       }
+
+       if (i == loop_count) {
+               mali_l2_cache_command_unlock(cache);
+               MALI_DEBUG_PRINT(1, ( "Mali L2 cache: aborting wait for command interface to go idle\n"));
+               MALI_ERROR( _MALI_OSK_ERR_FAULT );
+       }
+
+       /* then issue the command */
+       mali_hw_core_register_write(&cache->hw_core, reg, val);
+
+       mali_l2_cache_command_unlock(cache);
+
+       MALI_SUCCESS;
+}
+
+void mali_l2_cache_pause_all(mali_bool pause)
+{
+       int i;
+       struct mali_l2_cache_core * cache;
+       u32 num_cores = mali_l2_cache_core_get_glob_num_l2_cores();
+       mali_l2_power_status status = MALI_L2_NORMAL;
+
+       if (pause) {
+               status = MALI_L2_PAUSE;
+       }
+
+       for (i = 0; i < num_cores; i++) {
+               cache = mali_l2_cache_core_get_glob_l2_core(i);
+               if (NULL != cache) {
+                       cache->mali_l2_status = status;
+
+                       /* Take and release the counter and command locks to
+                        * ensure there are no active threads that didn't get
+                        * the status flag update.
+                        *
+                        * The locks will also ensure the necessary memory
+                        * barriers are done on SMP systems.
+                        */
+                       mali_l2_cache_counter_lock(cache);
+                       mali_l2_cache_counter_unlock(cache);
+
+                       mali_l2_cache_command_lock(cache);
+                       mali_l2_cache_command_unlock(cache);
+               }
+       }
+
+       /* Resume from pause: do the cache invalidation here to prevent any
+        * loss of cache operation during the pause period to make sure the SW
+        * status is consistent with L2 cache status.
+        */
+       if(!pause) {
+               mali_l2_cache_invalidate_all();
+               mali_l2_cache_reset_counters_all();
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_l2_cache.h b/drivers/gpu/arm/mali400/mali/common/mali_l2_cache.h
new file mode 100755 (executable)
index 0000000..5d979ad
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_KERNEL_L2_CACHE_H__
+#define __MALI_KERNEL_L2_CACHE_H__
+
+#include "mali_osk.h"
+#include "mali_hw_core.h"
+
+#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES  3
+/* Maximum 1 GP and 4 PP for an L2 cache core (Mali-400 Quad-core) */
+#define MALI_MAX_NUMBER_OF_GROUPS_PER_L2_CACHE 5
+
+struct mali_group;
+struct mali_pm_domain;
+
+/* Flags describing state of the L2 */
+typedef enum mali_l2_power_status {
+       MALI_L2_NORMAL, /**< L2 is in normal state and operational */
+       MALI_L2_PAUSE,  /**< L2 may not be accessed and may be powered off */
+} mali_l2_power_status;
+
+/**
+ * Definition of the L2 cache core struct
+ * Used to track a L2 cache unit in the system.
+ * Contains information about the mapping of the registers
+ */
+struct mali_l2_cache_core {
+       struct mali_hw_core  hw_core;      /**< Common for all HW cores */
+       u32                  core_id;      /**< Unique core ID */
+#ifdef MALI_UPPER_HALF_SCHEDULING
+       _mali_osk_spinlock_irq_t    *command_lock; /**< Serialize all L2 cache commands */
+       _mali_osk_spinlock_irq_t    *counter_lock; /**< Synchronize L2 cache counter access */
+#else
+       _mali_osk_spinlock_t        *command_lock;
+       _mali_osk_spinlock_t        *counter_lock;
+#endif
+       u32                  counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+       u32                  counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+       u32                  last_invalidated_id;
+       struct mali_pm_domain *pm_domain;
+       mali_l2_power_status   mali_l2_status; /**< Indicate whether the L2 is paused or not */
+};
+
+_mali_osk_errcode_t mali_l2_cache_initialize(void);
+void mali_l2_cache_terminate(void);
+/**
+ * L2 pause is just a status that the L2 can't be accessed temporarily.
+*/
+void mali_l2_cache_pause_all(mali_bool pause);
+struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t * resource);
+void mali_l2_cache_delete(struct mali_l2_cache_core *cache);
+
+MALI_STATIC_INLINE void mali_l2_cache_set_pm_domain(struct mali_l2_cache_core *cache, struct mali_pm_domain *domain)
+{
+       cache->pm_domain = domain;
+}
+
+u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache);
+
+void mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter);
+void mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter);
+u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache);
+u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache);
+void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1);
+struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index);
+u32 mali_l2_cache_core_get_glob_num_l2_cores(void);
+
+void mali_l2_cache_reset(struct mali_l2_cache_core *cache);
+void mali_l2_cache_reset_all(void);
+
+struct mali_group *mali_l2_cache_get_group(struct mali_l2_cache_core *cache, u32 index);
+
+void mali_l2_cache_invalidate(struct mali_l2_cache_core *cache);
+mali_bool mali_l2_cache_invalidate_conditional(struct mali_l2_cache_core *cache, u32 id);
+void mali_l2_cache_invalidate_all(void);
+void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages);
+
+mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache);
+void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache);
+
+#endif /* __MALI_KERNEL_L2_CACHE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_mem_validation.c b/drivers/gpu/arm/mali400/mali/common/mali_mem_validation.c
new file mode 100755 (executable)
index 0000000..ae229c7
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_mem_validation.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+//#include "mali_platform.h"
+#include <linux/fb.h>
+
+#define MALI_INVALID_MEM_ADDR 0xFFFFFFFF
+
+typedef struct {
+       u32 phys_base;        /**< Mali physical base of the memory, page aligned */
+       u32 size;             /**< size in bytes of the memory, multiple of page size */
+} _mali_mem_validation_t;
+
+static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR };
+
+_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size_para)
+{
+       /* Check that no other MEM_VALIDATION resources exist */
+       if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base) {
+               MALI_PRINT_ERROR(("Failed to add frame buffer memory; another range is already specified\n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Check restrictions on page alignment */
+       if ((0 != (start & (~_MALI_OSK_CPU_PAGE_MASK))) ||
+           (0 != (size_para & (~_MALI_OSK_CPU_PAGE_MASK)))) {
+               MALI_PRINT_ERROR(("Failed to add frame buffer memory; incorrect alignment\n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       mali_mem_validator.phys_base = start;
+       mali_mem_validator.size = size_para;
+       MALI_DEBUG_PRINT(2, ("Memory Validator installed for Mali physical address base=0x%08X, size=0x%08X\n",
+                            mali_mem_validator.phys_base, mali_mem_validator.size));
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size)
+{
+#if 0
+       if (phys_addr < (phys_addr + size)) { /* Don't allow overflow (or zero size) */
+               if ((0 == ( phys_addr & (~_MALI_OSK_CPU_PAGE_MASK))) &&
+                   (0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)))) {
+                       if ((phys_addr          >= mali_mem_validator.phys_base) &&
+                           ((phys_addr + (size - 1)) >= mali_mem_validator.phys_base) &&
+                           (phys_addr          <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) &&
+                           ((phys_addr + (size - 1)) <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) ) {
+                               MALI_DEBUG_PRINT(3, ("Accepted range 0x%08X + size 0x%08X (= 0x%08X)\n", phys_addr, size, (phys_addr + size - 1)));
+                               return _MALI_OSK_ERR_OK;
+                       }
+               }
+       }
+
+       MALI_PRINT_ERROR(("MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_addr, size));
+
+       return _MALI_OSK_ERR_FAULT;
+#endif
+       MALI_PRINT(("abort mali mem validation check needed by little Q \r\n"));
+       return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_mem_validation.h b/drivers/gpu/arm/mali400/mali/common/mali_mem_validation.h
new file mode 100755 (executable)
index 0000000..4a247ae
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MEM_VALIDATION_H__
+#define __MALI_MEM_VALIDATION_H__
+
+#include "mali_osk.h"
+
+_mali_osk_errcode_t mali_mem_validation_add_range(u32 start, u32 size);
+_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size);
+
+#endif /* __MALI_MEM_VALIDATION_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_mmu.c b/drivers/gpu/arm/mali400/mali/common/mali_mmu.c
new file mode 100755 (executable)
index 0000000..92b0888
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_ukk.h"
+
+#include "mali_mmu.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "mali_mmu_page_directory.h"
+
+/**
+ * Size of the MMU registers in bytes
+ */
+#define MALI_MMU_REGISTERS_SIZE 0x24
+
+/**
+ * MMU commands
+ * These are the commands that can be sent
+ * to the MMU unit.
+ */
+typedef enum mali_mmu_command {
+       MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
+       MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
+       MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**<  Enable stall on page fault */
+       MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
+       MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
+       MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
+       MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */
+} mali_mmu_command;
+
+static void mali_mmu_probe_trigger(void *data);
+static _mali_osk_errcode_t mali_mmu_probe_ack(void *data);
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu);
+
+/* page fault queue flush helper pages
+ * note that the mapping pointers are currently unused outside of the initialization functions */
+static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
+static mali_io_address mali_page_fault_flush_page_directory_mapping = NULL;
+static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
+static mali_io_address mali_page_fault_flush_page_table_mapping = NULL;
+static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
+static mali_io_address mali_page_fault_flush_data_page_mapping = NULL;
+
+/* an empty page directory (no address valid) which is active on any MMU not currently marked as in use */
+static u32 mali_empty_page_directory_phys   = MALI_INVALID_PAGE;
+static mali_io_address mali_empty_page_directory_virt = NULL;
+
+
+_mali_osk_errcode_t mali_mmu_initialize(void)
+{
+       /* allocate the helper pages */
+       mali_empty_page_directory_phys = mali_allocate_empty_page(&mali_empty_page_directory_virt);
+       if(0 == mali_empty_page_directory_phys) {
+               MALI_DEBUG_PRINT_ERROR(("Mali MMU: Could not allocate empty page directory.\n"));
+               mali_empty_page_directory_phys = MALI_INVALID_PAGE;
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory,
+               &mali_page_fault_flush_page_directory_mapping,
+               &mali_page_fault_flush_page_table,
+               &mali_page_fault_flush_page_table_mapping,
+               &mali_page_fault_flush_data_page,
+               &mali_page_fault_flush_data_page_mapping)) {
+               MALI_DEBUG_PRINT_ERROR(("Mali MMU: Could not allocate fault flush pages\n"));
+               mali_free_empty_page(mali_empty_page_directory_phys, mali_empty_page_directory_virt);
+               mali_empty_page_directory_phys = MALI_INVALID_PAGE;
+               mali_empty_page_directory_virt = NULL;
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_mmu_terminate(void)
+{
+       MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n"));
+
+       /* Free global helper pages */
+       mali_free_empty_page(mali_empty_page_directory_phys, mali_empty_page_directory_virt);
+       mali_empty_page_directory_phys = MALI_INVALID_PAGE;
+       mali_empty_page_directory_virt = NULL;
+
+       /* Free the page fault flush pages */
+       mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory, &mali_page_fault_flush_page_directory_mapping,
+                                      &mali_page_fault_flush_page_table, &mali_page_fault_flush_page_table_mapping,
+                                      &mali_page_fault_flush_data_page, &mali_page_fault_flush_data_page_mapping);
+}
+
+struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual)
+{
+       struct mali_mmu_core* mmu = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(resource);
+
+       MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description));
+
+       mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
+       if (NULL != mmu) {
+               if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE)) {
+                       if (_MALI_OSK_ERR_OK == mali_group_add_mmu_core(group, mmu)) {
+                               if (is_virtual) {
+                                       /* Skip reset and IRQ setup for virtual MMU */
+                                       return mmu;
+                               }
+
+                               if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu)) {
+                                       /* Setup IRQ handlers (which will do IRQ probing if needed) */
+                                       mmu->irq = _mali_osk_irq_init(resource->irq,
+                                                                     mali_group_upper_half_mmu,
+                                                                     group,
+                                                                     mali_mmu_probe_trigger,
+                                                                     mali_mmu_probe_ack,
+                                                                     mmu,
+                                                                     resource->description);
+                                       if (NULL != mmu->irq) {
+                                               return mmu;
+                                       } else {
+                                               MALI_PRINT_ERROR(("Mali MMU: Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
+                                       }
+                               }
+                               mali_group_remove_mmu_core(group);
+                       } else {
+                               MALI_PRINT_ERROR(("Mali MMU: Failed to add core %s to group\n", mmu->hw_core.description));
+                       }
+                       mali_hw_core_delete(&mmu->hw_core);
+               }
+
+               _mali_osk_free(mmu);
+       } else {
+               MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n"));
+       }
+
+       return NULL;
+}
+
+void mali_mmu_delete(struct mali_mmu_core *mmu)
+{
+       if (NULL != mmu->irq) {
+               _mali_osk_irq_term(mmu->irq);
+       }
+
+       mali_hw_core_delete(&mmu->hw_core);
+       _mali_osk_free(mmu);
+}
+
+static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
+{
+       int i;
+
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
+               if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) {
+                       break;
+               }
+       }
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+       }
+}
+
+/**
+ * Issues the enable stall command to the MMU and waits for HW to complete the request
+ * @param mmu The MMU to enable paging for
+ * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out)
+ */
+static mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
+{
+       int i;
+       u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+
+       if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) ) {
+               MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enabled.\n"));
+               return MALI_TRUE;
+       }
+
+       if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) {
+               MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n"));
+               return MALI_FALSE;
+       }
+
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
+               mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+               if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
+                       break;
+               }
+               if ((mmu_status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) && (0 == (mmu_status & MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE))) {
+                       break;
+               }
+               if (0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED ))) {
+                       break;
+               }
+       }
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_DEBUG_PRINT(2, ("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+               return MALI_FALSE;
+       }
+
+       if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) {
+               MALI_DEBUG_PRINT(2, ("Aborting MMU stall request since it has a pagefault.\n"));
+               return MALI_FALSE;
+       }
+
+       return MALI_TRUE;
+}
+
+/**
+ * Issues the disable stall command to the MMU and waits for HW to complete the request
+ * @param mmu The MMU to enable paging for
+ */
+static void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
+{
+       int i;
+       u32 mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+
+       if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) {
+               MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n"));
+               return;
+       }
+       if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) {
+               MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n"));
+               return;
+       }
+
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
+               u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+               if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) ) {
+                       break;
+               }
+               if ( status &  MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) {
+                       break;
+               }
+               if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED )) {
+                       break;
+               }
+       }
+       if (MALI_REG_POLL_COUNT_FAST == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+}
+
+void mali_mmu_page_fault_done(struct mali_mmu_core *mmu)
+{
+       MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description));
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
+}
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu)
+{
+       int i;
+
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
+       MALI_DEBUG_ASSERT(0xCAFEB000 == mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR));
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET);
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; ++i) {
+               if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0) {
+                       break;
+               }
+       }
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
+{
+       _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+       mali_bool stall_success;
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+       stall_success = mali_mmu_enable_stall(mmu);
+       if (!stall_success) {
+               err = _MALI_OSK_ERR_BUSY;
+       }
+
+       MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
+
+       if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu)) {
+               mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+               /* no session is active, so just activate the empty page directory */
+               mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory_phys);
+               mali_mmu_enable_paging(mmu);
+               err = _MALI_OSK_ERR_OK;
+       }
+       mali_mmu_disable_stall(mmu);
+
+       return err;
+}
+
+mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
+{
+       mali_bool stall_success = mali_mmu_enable_stall(mmu);
+
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+
+       if (MALI_FALSE == stall_success) {
+               /* False means that it is in Pagefault state. Not possible to disable_stall then */
+               return MALI_FALSE;
+       }
+
+       mali_mmu_disable_stall(mmu);
+       return MALI_TRUE;
+}
+
+void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu)
+{
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+}
+
+
+void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address)
+{
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address));
+}
+
+static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory)
+{
+       /* The MMU must be in stalled or page fault mode, for this writing to work */
+       MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)
+                                 & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+
+}
+
+void mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
+{
+       mali_bool stall_success;
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+       MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));
+
+       stall_success = mali_mmu_enable_stall(mmu);
+       MALI_DEBUG_ASSERT(stall_success);
+       MALI_IGNORE(stall_success);
+       mali_mmu_activate_address_space(mmu, pagedir->page_directory);
+       mali_mmu_disable_stall(mmu);
+}
+
+void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu)
+{
+       mali_bool stall_success;
+
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+       MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
+
+       stall_success = mali_mmu_enable_stall(mmu);
+
+       /* This function can only be called when the core is idle, so it could not fail. */
+       MALI_DEBUG_ASSERT(stall_success);
+       MALI_IGNORE(stall_success);
+
+       mali_mmu_activate_address_space(mmu, mali_empty_page_directory_phys);
+       mali_mmu_disable_stall(mmu);
+}
+
+void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu)
+{
+       mali_bool stall_success;
+       MALI_DEBUG_ASSERT_POINTER(mmu);
+
+       MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description));
+       stall_success = mali_mmu_enable_stall(mmu);
+       /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */
+       mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory);
+       if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu);
+}
+
+/* Is called when we want the mmu to give an interrupt */
+static void mali_mmu_probe_trigger(void *data)
+{
+       struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+}
+
+/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
+static _mali_osk_errcode_t mali_mmu_probe_ack(void *data)
+{
+       struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+       u32 int_stat;
+
+       int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
+
+       MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
+       if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) {
+               MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
+               mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
+       } else {
+               MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
+       }
+
+       if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) {
+               MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
+               mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+       } else {
+               MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
+       }
+
+       if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
+            (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) {
+               return _MALI_OSK_ERR_OK;
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+#if 0
+void mali_mmu_print_state(struct mali_mmu_core *mmu)
+{
+       MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+}
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_mmu.h b/drivers/gpu/arm/mali400/mali/common/mali_mmu.h
new file mode 100755 (executable)
index 0000000..d11748c
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MMU_H__
+#define __MALI_MMU_H__
+
+#include "mali_osk.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_hw_core.h"
+
+/* Forward declaration from mali_group.h */
+struct mali_group;
+
+/**
+ * MMU register numbers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_mmu_register {
+       MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */
+       MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */
+       MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */
+       MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */
+       MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */
+       MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */
+       MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */
+       MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */
+       MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */
+} mali_mmu_register;
+
+/**
+ * MMU interrupt register bits
+ * Each cause of the interrupt is reported
+ * through the (raw) interrupt status registers.
+ * Multiple interrupts can be pending, so multiple bits
+ * can be set at once.
+ */
+typedef enum mali_mmu_interrupt {
+       MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */
+       MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */
+} mali_mmu_interrupt;
+
+typedef enum mali_mmu_status_bits {
+       MALI_MMU_STATUS_BIT_PAGING_ENABLED      = 1 << 0,
+       MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE   = 1 << 1,
+       MALI_MMU_STATUS_BIT_STALL_ACTIVE        = 1 << 2,
+       MALI_MMU_STATUS_BIT_IDLE                = 1 << 3,
+       MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY = 1 << 4,
+       MALI_MMU_STATUS_BIT_PAGE_FAULT_IS_WRITE = 1 << 5,
+       MALI_MMU_STATUS_BIT_STALL_NOT_ACTIVE    = 1 << 31,
+} mali_mmu_status_bits;
+
+/**
+ * Definition of the MMU struct
+ * Used to track a MMU unit in the system.
+ * Contains information about the mapping of the registers
+ */
+struct mali_mmu_core {
+       struct mali_hw_core hw_core; /**< Common for all HW cores */
+       _mali_osk_irq_t *irq;        /**< IRQ handler */
+};
+
+_mali_osk_errcode_t mali_mmu_initialize(void);
+
+void mali_mmu_terminate(void);
+
+struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual);
+void mali_mmu_delete(struct mali_mmu_core *mmu);
+
+_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu);
+mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu);
+void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu);
+void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address);
+
+void mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir);
+void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu);
+void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu);
+
+void mali_mmu_page_fault_done(struct mali_mmu_core *mmu);
+
+/*** Register reading/writing functions ***/
+MALI_STATIC_INLINE u32 mali_mmu_get_int_status(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
+}
+
+MALI_STATIC_INLINE u32 mali_mmu_get_rawstat(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT);
+}
+
+MALI_STATIC_INLINE void mali_mmu_mask_all_interrupts(struct mali_mmu_core *mmu)
+{
+       mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0);
+}
+
+MALI_STATIC_INLINE u32 mali_mmu_get_status(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+}
+
+MALI_STATIC_INLINE u32 mali_mmu_get_page_fault_addr(struct mali_mmu_core *mmu)
+{
+       return mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
+}
+
+#endif /* __MALI_MMU_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_mmu_page_directory.c b/drivers/gpu/arm/mali400/mali/common/mali_mmu_page_directory.c
new file mode 100755 (executable)
index 0000000..1439d7b
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_memory.h"
+#include "mali_l2_cache.h"
+
+static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data);
+
+u32 mali_allocate_empty_page(mali_io_address *virt_addr)
+{
+       _mali_osk_errcode_t err;
+       mali_io_address mapping;
+       u32 address;
+
+       if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&address, &mapping)) {
+               /* Allocation failed */
+               MALI_DEBUG_PRINT(2, ("Mali MMU: Failed to get table page for empty pgdir\n"));
+               return 0;
+       }
+
+       MALI_DEBUG_ASSERT_POINTER( mapping );
+
+       err = fill_page(mapping, 0);
+       if (_MALI_OSK_ERR_OK != err) {
+               mali_mmu_release_table_page(address, mapping);
+               MALI_DEBUG_PRINT(2, ("Mali MMU: Failed to zero page\n"));
+               return 0;
+       }
+
+       *virt_addr = mapping;
+       return address;
+}
+
+void mali_free_empty_page(u32 address, mali_io_address virt_addr)
+{
+       if (MALI_INVALID_PAGE != address) {
+               mali_mmu_release_table_page(address, virt_addr);
+       }
+}
+
+_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, mali_io_address *page_directory_mapping,
+        u32 *page_table, mali_io_address *page_table_mapping,
+        u32 *data_page, mali_io_address *data_page_mapping)
+{
+       _mali_osk_errcode_t err;
+
+       err = mali_mmu_get_table_page(data_page, data_page_mapping);
+       if (_MALI_OSK_ERR_OK == err) {
+               err = mali_mmu_get_table_page(page_table, page_table_mapping);
+               if (_MALI_OSK_ERR_OK == err) {
+                       err = mali_mmu_get_table_page(page_directory, page_directory_mapping);
+                       if (_MALI_OSK_ERR_OK == err) {
+                               fill_page(*data_page_mapping, 0);
+                               fill_page(*page_table_mapping, *data_page | MALI_MMU_FLAGS_DEFAULT);
+                               fill_page(*page_directory_mapping, *page_table | MALI_MMU_FLAGS_PRESENT);
+                               MALI_SUCCESS;
+                       }
+                       mali_mmu_release_table_page(*page_table, *page_table_mapping);
+                       *page_table = MALI_INVALID_PAGE;
+               }
+               mali_mmu_release_table_page(*data_page, *data_page_mapping);
+               *data_page = MALI_INVALID_PAGE;
+       }
+       return err;
+}
+
+void mali_destroy_fault_flush_pages(u32 *page_directory, mali_io_address *page_directory_mapping,
+                                    u32 *page_table, mali_io_address *page_table_mapping,
+                                    u32 *data_page, mali_io_address *data_page_mapping)
+{
+       if (MALI_INVALID_PAGE != *page_directory) {
+               mali_mmu_release_table_page(*page_directory, *page_directory_mapping);
+               *page_directory = MALI_INVALID_PAGE;
+               *page_directory_mapping = NULL;
+       }
+
+       if (MALI_INVALID_PAGE != *page_table) {
+               mali_mmu_release_table_page(*page_table, *page_table_mapping);
+               *page_table = MALI_INVALID_PAGE;
+               *page_table_mapping = NULL;
+       }
+
+       if (MALI_INVALID_PAGE != *data_page) {
+               mali_mmu_release_table_page(*data_page, *data_page_mapping);
+               *data_page = MALI_INVALID_PAGE;
+               *data_page_mapping = NULL;
+       }
+}
+
+static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data)
+{
+       int i;
+       MALI_DEBUG_ASSERT_POINTER( mapping );
+
+       for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++) {
+               _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data);
+       }
+       _mali_osk_mem_barrier();
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size)
+{
+       const int first_pde = MALI_MMU_PDE_ENTRY(mali_address);
+       const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1);
+       _mali_osk_errcode_t err;
+       mali_io_address pde_mapping;
+       u32 pde_phys;
+       int i;
+
+       if (last_pde < first_pde) {
+               MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+       }
+
+       for(i = first_pde; i <= last_pde; i++) {
+               if(0 == (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & MALI_MMU_FLAGS_PRESENT)) {
+                       /* Page table not present */
+                       MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]);
+                       MALI_DEBUG_ASSERT(NULL == pagedir->page_entries_mapped[i]);
+
+                       err = mali_mmu_get_table_page(&pde_phys, &pde_mapping);
+                       if(_MALI_OSK_ERR_OK != err) {
+                               MALI_PRINT_ERROR(("Failed to allocate page table page.\n"));
+                               return err;
+                       }
+                       pagedir->page_entries_mapped[i] = pde_mapping;
+
+                       /* Update PDE, mark as present */
+                       _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32),
+                                                       pde_phys | MALI_MMU_FLAGS_PRESENT);
+
+                       MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]);
+                       pagedir->page_entries_usage_count[i] = 1;
+               } else {
+                       pagedir->page_entries_usage_count[i]++;
+               }
+       }
+       _mali_osk_write_mem_barrier();
+
+       MALI_SUCCESS;
+}
+
+MALI_STATIC_INLINE void mali_mmu_zero_pte(mali_io_address page_table, u32 mali_address, u32 size)
+{
+       int i;
+       const int first_pte = MALI_MMU_PTE_ENTRY(mali_address);
+       const int last_pte = MALI_MMU_PTE_ENTRY(mali_address + size - 1);
+
+       for (i = first_pte; i <= last_pte; i++) {
+               _mali_osk_mem_iowrite32_relaxed(page_table, i * sizeof(u32), 0);
+       }
+}
+
+_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size)
+{
+       const int first_pde = MALI_MMU_PDE_ENTRY(mali_address);
+       const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1);
+       u32 left = size;
+       int i;
+       mali_bool pd_changed = MALI_FALSE;
+       u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */
+       u32 num_pages_inv = 0;
+       mali_bool invalidate_all = MALI_FALSE; /* safety mechanism in case page_entries_usage_count is unreliable */
+
+       /* For all page directory entries in range. */
+       for (i = first_pde; i <= last_pde; i++) {
+               u32 size_in_pde, offset;
+
+               MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]);
+               MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]);
+
+               /* Offset into page table, 0 if mali_address is 4MiB aligned */
+               offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1));
+               if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset) {
+                       size_in_pde = left;
+               } else {
+                       size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset;
+               }
+
+               pagedir->page_entries_usage_count[i]--;
+
+               /* If entire page table is unused, free it */
+               if (0 == pagedir->page_entries_usage_count[i]) {
+                       u32 page_phys;
+                       void *page_virt;
+                       MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n"));
+                       /* last reference removed, no need to zero out each PTE  */
+
+                       page_phys = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)));
+                       page_virt = pagedir->page_entries_mapped[i];
+                       pagedir->page_entries_mapped[i] = NULL;
+                       _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0);
+
+                       mali_mmu_release_table_page(page_phys, page_virt);
+                       pd_changed = MALI_TRUE;
+               } else {
+                       MALI_DEBUG_ASSERT(num_pages_inv < 2);
+                       if (num_pages_inv < 2) {
+                               pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i);
+                               num_pages_inv++;
+                       } else {
+                               invalidate_all = MALI_TRUE;
+                       }
+
+                       /* If part of the page table is still in use, zero the relevant PTEs */
+                       mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde);
+               }
+
+               left -= size_in_pde;
+               mali_address += size_in_pde;
+       }
+       _mali_osk_write_mem_barrier();
+
+       /* L2 pages invalidation */
+       if (MALI_TRUE == pd_changed) {
+               MALI_DEBUG_ASSERT(num_pages_inv < 3);
+               if (num_pages_inv < 3) {
+                       pages_to_invalidate[num_pages_inv] = pagedir->page_directory;
+                       num_pages_inv++;
+               } else {
+                       invalidate_all = MALI_TRUE;
+               }
+       }
+
+       if (invalidate_all) {
+               mali_l2_cache_invalidate_all();
+       } else {
+               mali_l2_cache_invalidate_all_pages(pages_to_invalidate, num_pages_inv);
+       }
+
+       MALI_SUCCESS;
+}
+
+struct mali_page_directory *mali_mmu_pagedir_alloc(void)
+{
+       struct mali_page_directory *pagedir;
+
+       pagedir = _mali_osk_calloc(1, sizeof(struct mali_page_directory));
+       if(NULL == pagedir) {
+               return NULL;
+       }
+
+       if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&pagedir->page_directory, &pagedir->page_directory_mapped)) {
+               _mali_osk_free(pagedir);
+               return NULL;
+       }
+
+       /* Zero page directory */
+       fill_page(pagedir->page_directory_mapped, 0);
+
+       return pagedir;
+}
+
+void mali_mmu_pagedir_free(struct mali_page_directory *pagedir)
+{
+       const int num_page_table_entries = sizeof(pagedir->page_entries_mapped) / sizeof(pagedir->page_entries_mapped[0]);
+       int i;
+
+       /* Free referenced page tables and zero PDEs. */
+       for (i = 0; i < num_page_table_entries; i++) {
+               if (pagedir->page_directory_mapped && (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT)) {
+                       u32 phys = _mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK;
+                       _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i * sizeof(u32), 0);
+                       mali_mmu_release_table_page(phys, pagedir->page_entries_mapped[i]);
+               }
+       }
+       _mali_osk_write_mem_barrier();
+
+       /* Free the page directory page. */
+       mali_mmu_release_table_page(pagedir->page_directory, pagedir->page_directory_mapped);
+
+       _mali_osk_free(pagedir);
+}
+
+
+void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, u32 permission_bits)
+{
+       u32 end_address = mali_address + size;
+
+       /* Map physical pages into MMU page tables */
+       for ( ; mali_address < end_address; mali_address += MALI_MMU_PAGE_SIZE, phys_address += MALI_MMU_PAGE_SIZE) {
+               MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]);
+               _mali_osk_mem_iowrite32_relaxed(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)],
+                                               MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32),
+                                               phys_address | permission_bits);
+       }
+}
+
+u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index)
+{
+       return (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, index*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+}
+
+/* For instrumented */
+struct dump_info {
+       u32 buffer_left;
+       u32 register_writes_size;
+       u32 page_table_dump_size;
+       u32 *buffer;
+};
+
+static _mali_osk_errcode_t writereg(u32 where, u32 what, const char *comment, struct dump_info *info)
+{
+       if (NULL != info) {
+               info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */
+
+               if (NULL != info->buffer) {
+                       /* check that we have enough space */
+                       if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+                       *info->buffer = where;
+                       info->buffer++;
+
+                       *info->buffer = what;
+                       info->buffer++;
+
+                       info->buffer_left -= sizeof(u32)*2;
+               }
+       }
+
+       MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_mmu_dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info)
+{
+       if (NULL != info) {
+               /* 4096 for the page and 4 bytes for the address */
+               const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4;
+               const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE;
+               const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4;
+
+               info->page_table_dump_size += dump_size_in_bytes;
+
+               if (NULL != info->buffer) {
+                       if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+                       *info->buffer = phys_addr;
+                       info->buffer++;
+
+                       _mali_osk_memcpy(info->buffer, page, page_size_in_bytes);
+                       info->buffer += page_size_in_elements;
+
+                       info->buffer_left -= dump_size_in_bytes;
+               }
+       }
+
+       MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_page_table(struct mali_page_directory *pagedir, struct dump_info * info)
+{
+       MALI_DEBUG_ASSERT_POINTER(pagedir);
+       MALI_DEBUG_ASSERT_POINTER(info);
+
+       if (NULL != pagedir->page_directory_mapped) {
+               int i;
+
+               MALI_CHECK_NO_ERROR(
+                   mali_mmu_dump_page(pagedir->page_directory_mapped, pagedir->page_directory, info)
+               );
+
+               for (i = 0; i < 1024; i++) {
+                       if (NULL != pagedir->page_entries_mapped[i]) {
+                               MALI_CHECK_NO_ERROR(
+                                   mali_mmu_dump_page(pagedir->page_entries_mapped[i],
+                                                      _mali_osk_mem_ioread32(pagedir->page_directory_mapped,
+                                                              i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info)
+                               );
+                       }
+               }
+       }
+
+       MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_registers(struct mali_page_directory *pagedir, struct dump_info * info)
+{
+       MALI_CHECK_NO_ERROR(writereg(0x00000000, pagedir->page_directory,
+                                    "set the page directory address", info));
+       MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info));
+       MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info));
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args )
+{
+       struct dump_info info = { 0, 0, 0, NULL };
+       struct mali_session_data * session_data;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session_data = (struct mali_session_data *)(args->ctx);
+
+       MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info));
+       MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info));
+       args->size = info.register_writes_size + info.page_table_dump_size;
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args )
+{
+       struct dump_info info = { 0, 0, 0, NULL };
+       struct mali_session_data * session_data;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+       MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session_data = (struct mali_session_data *)(args->ctx);
+
+       info.buffer_left = args->size;
+       info.buffer = args->buffer;
+
+       args->register_writes = info.buffer;
+       MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info));
+
+       args->page_table_dump = info.buffer;
+       MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info));
+
+       args->register_writes_size = info.register_writes_size;
+       args->page_table_dump_size = info.page_table_dump_size;
+
+       MALI_SUCCESS;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_mmu_page_directory.h b/drivers/gpu/arm/mali400/mali/common/mali_mmu_page_directory.h
new file mode 100755 (executable)
index 0000000..0db8a76
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MMU_PAGE_DIRECTORY_H__
+#define __MALI_MMU_PAGE_DIRECTORY_H__
+
+#include "mali_osk.h"
+
+/**
+ * Size of an MMU page in bytes
+ */
+#define MALI_MMU_PAGE_SIZE 0x1000
+
+/*
+ * Size of the address space referenced by a page table page
+ */
+#define MALI_MMU_VIRTUAL_PAGE_SIZE 0x400000 /* 4 MiB */
+
+/**
+ * Page directory index from address
+ * Calculates the page directory index from the given address
+ */
+#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF)
+
+/**
+ * Page table index from address
+ * Calculates the page table index from the given address
+ */
+#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF)
+
+/**
+ * Extract the memory address from an PDE/PTE entry
+ */
+#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00)
+
+#define MALI_INVALID_PAGE ((u32)(~0))
+
+/**
+ *
+ */
+typedef enum mali_mmu_entry_flags {
+       MALI_MMU_FLAGS_PRESENT = 0x01,
+       MALI_MMU_FLAGS_READ_PERMISSION = 0x02,
+       MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04,
+       MALI_MMU_FLAGS_OVERRIDE_CACHE  = 0x8,
+       MALI_MMU_FLAGS_WRITE_CACHEABLE  = 0x10,
+       MALI_MMU_FLAGS_WRITE_ALLOCATE  = 0x20,
+       MALI_MMU_FLAGS_WRITE_BUFFERABLE  = 0x40,
+       MALI_MMU_FLAGS_READ_CACHEABLE  = 0x80,
+       MALI_MMU_FLAGS_READ_ALLOCATE  = 0x100,
+       MALI_MMU_FLAGS_MASK = 0x1FF,
+} mali_mmu_entry_flags;
+
+
+#define MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE ( \
+MALI_MMU_FLAGS_PRESENT | \
+       MALI_MMU_FLAGS_READ_PERMISSION |  \
+       MALI_MMU_FLAGS_WRITE_PERMISSION | \
+       MALI_MMU_FLAGS_OVERRIDE_CACHE | \
+       MALI_MMU_FLAGS_WRITE_CACHEABLE | \
+       MALI_MMU_FLAGS_WRITE_BUFFERABLE | \
+       MALI_MMU_FLAGS_READ_CACHEABLE | \
+       MALI_MMU_FLAGS_READ_ALLOCATE )
+
+#define MALI_MMU_FLAGS_DEFAULT ( \
+       MALI_MMU_FLAGS_PRESENT | \
+       MALI_MMU_FLAGS_READ_PERMISSION |  \
+       MALI_MMU_FLAGS_WRITE_PERMISSION )
+
+
+struct mali_page_directory {
+       u32 page_directory; /**< Physical address of the memory session's page directory */
+       mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */
+
+       mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */
+       u32   page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */
+};
+
+/* Map Mali virtual address space (i.e. ensure page tables exist for the virtual range)  */
+_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size);
+_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size);
+
+/* Back virtual address space with actual pages. Assumes input is contiguous and 4k aligned. */
+void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size, u32 cache_settings);
+
+u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index);
+
+u32 mali_allocate_empty_page(mali_io_address *virtual);
+void mali_free_empty_page(u32 address, mali_io_address virtual);
+_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, mali_io_address *page_directory_mapping,
+        u32 *page_table, mali_io_address *page_table_mapping,
+        u32 *data_page, mali_io_address *data_page_mapping);
+void mali_destroy_fault_flush_pages(u32 *page_directory, mali_io_address *page_directory_mapping,
+                                    u32 *page_table, mali_io_address *page_table_mapping,
+                                    u32 *data_page, mali_io_address *data_page_mapping);
+
+struct mali_page_directory *mali_mmu_pagedir_alloc(void);
+void mali_mmu_pagedir_free(struct mali_page_directory *pagedir);
+
+#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_osk.h b/drivers/gpu/arm/mali400/mali/common/mali_osk.h
new file mode 100755 (executable)
index 0000000..ce40309
--- /dev/null
@@ -0,0 +1,1335 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk.h
+ * Defines the OS abstraction layer for the kernel device driver (OSK)
+ */
+
+#ifndef __MALI_OSK_H__
+#define __MALI_OSK_H__
+
+#include "mali_osk_types.h"
+#include "mali_osk_specific.h"           /* include any per-os specifics */
+#include "mali_osk_locks.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup uddapi Unified Device Driver (UDD) APIs
+ *
+ * @{
+ */
+
+/**
+ * @addtogroup oskapi UDD OS Abstraction for Kernel-side (OSK) APIs
+ *
+ * @{
+ */
+
+/** @addtogroup _mali_osk_lock OSK Mutual Exclusion Locks
+ * @{ */
+
+#ifdef DEBUG
+/** @brief Macro for asserting that the current thread holds a given lock
+ */
+#define MALI_DEBUG_ASSERT_LOCK_HELD(l) MALI_DEBUG_ASSERT(_mali_osk_lock_get_owner((_mali_osk_lock_debug_t *)l) == _mali_osk_get_tid());
+
+/** @brief returns a lock's owner (thread id) if debugging is enabled
+ */
+#else
+#define MALI_DEBUG_ASSERT_LOCK_HELD(l) do {} while(0)
+#endif
+
+/** @} */ /* end group _mali_osk_lock */
+
+/** @addtogroup _mali_osk_miscellaneous
+ * @{ */
+
+/** @brief Find the containing structure of another structure
+ *
+ * This is the reverse of the operation 'offsetof'. This means that the
+ * following condition is satisfied:
+ *
+ *   ptr == _MALI_OSK_CONTAINER_OF( &ptr->member, type, member )
+ *
+ * When ptr is of type 'type'.
+ *
+ * Its purpose it to recover a larger structure that has wrapped a smaller one.
+ *
+ * @note no type or memory checking occurs to ensure that a wrapper structure
+ * does in fact exist, and that it is being recovered with respect to the
+ * correct member.
+ *
+ * @param ptr the pointer to the member that is contained within the larger
+ * structure
+ * @param type the type of the structure that contains the member
+ * @param member the name of the member in the structure that ptr points to.
+ * @return a pointer to a \a type object which contains \a member, as pointed
+ * to by \a ptr.
+ */
+#define _MALI_OSK_CONTAINER_OF(ptr, type, member) \
+             ((type *)( ((char *)ptr) - offsetof(type,member) ))
+
+/** @addtogroup _mali_osk_wq
+ * @{ */
+
+/** @brief Initialize work queues (for deferred work)
+ *
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_wq_init(void);
+
+/** @brief Terminate work queues (for deferred work)
+ */
+void _mali_osk_wq_term(void);
+
+/** @brief Create work in the work queue
+ *
+ * Creates a work object which can be scheduled in the work queue. When
+ * scheduled, \a handler will be called with \a data as the argument.
+ *
+ * Refer to \ref _mali_osk_wq_schedule_work() for details on how work
+ * is scheduled in the queue.
+ *
+ * The returned pointer must be freed with \ref _mali_osk_wq_delete_work()
+ * when no longer needed.
+ */
+_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data );
+
+/** @brief A high priority version of \a _mali_osk_wq_create_work()
+ *
+ * Creates a work object which can be scheduled in the high priority work queue.
+ *
+ * This is unfortunately needed to get low latency scheduling of the Mali cores.  Normally we would
+ * schedule the next job in hw_irq or tasklet, but often we can't since we need to synchronously map
+ * and unmap shared memory when a job is connected to external fences (timelines). And this requires
+ * taking a mutex.
+ *
+ * We do signal a lot of other (low priority) work also as part of the job being finished, and if we
+ * don't set this Mali scheduling thread as high priority, we see that the CPU scheduler often runs
+ * random things instead of starting the next GPU job when the GPU is idle.  So setting the gpu
+ * scheduler to high priority does give a visually more responsive system.
+ *
+ * Start the high priority work with: \a _mali_osk_wq_schedule_work_high_pri()
+ */
+_mali_osk_wq_work_t *_mali_osk_wq_create_work_high_pri( _mali_osk_wq_work_handler_t handler, void *data );
+
+/** @brief Delete a work object
+ *
+ * This will flush the work queue to ensure that the work handler will not
+ * be called after deletion.
+ */
+void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work );
+
+/** @brief Delete a work object
+ *
+ * This will NOT flush the work queue, so only call this if you are sure that the work handler will
+ * not be called after deletion.
+ */
+void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work );
+
+/** @brief Cause a queued, deferred call of the work handler
+ *
+ * _mali_osk_wq_schedule_work provides a mechanism for enqueuing deferred calls
+ * to the work handler. After calling \ref _mali_osk_wq_schedule_work(), the
+ * work handler will be scheduled to run at some point in the future.
+ *
+ * Typically this is called by the IRQ upper-half to defer further processing of
+ * IRQ-related work to the IRQ bottom-half handler. This is necessary for work
+ * that cannot be done in an IRQ context by the IRQ upper-half handler. Timer
+ * callbacks also use this mechanism, because they are treated as though they
+ * operate in an IRQ context. Refer to \ref _mali_osk_timer_t for more
+ * information.
+ *
+ * Code that operates in a kernel-process context (with no IRQ context
+ * restrictions) may also enqueue deferred calls to the IRQ bottom-half. The
+ * advantage over direct calling is that deferred calling allows the caller and
+ * IRQ bottom half to hold the same mutex, with a guarantee that they will not
+ * deadlock just by using this mechanism.
+ *
+ * _mali_osk_wq_schedule_work() places deferred call requests on a queue, to
+ * allow for more than one thread to make a deferred call. Therfore, if it is
+ * called 'K' times, then the IRQ bottom-half will be scheduled 'K' times too.
+ * 'K' is a number that is implementation-specific.
+ *
+ * _mali_osk_wq_schedule_work() is guaranteed to not block on:
+ * - enqueuing a deferred call request.
+ * - the completion of the work handler.
+ *
+ * This is to prevent deadlock. For example, if _mali_osk_wq_schedule_work()
+ * blocked, then it would cause a deadlock when the following two conditions
+ * hold:
+ * - The work handler callback (of type _mali_osk_wq_work_handler_t) locks
+ * a mutex
+ * - And, at the same time, the caller of _mali_osk_wq_schedule_work() also
+ * holds the same mutex
+ *
+ * @note care must be taken to not overflow the queue that
+ * _mali_osk_wq_schedule_work() operates on. Code must be structured to
+ * ensure that the number of requests made to the queue is bounded. Otherwise,
+ * work will be lost.
+ *
+ * The queue that _mali_osk_wq_schedule_work implements is a FIFO of N-writer,
+ * 1-reader type. The writers are the callers of _mali_osk_wq_schedule_work
+ * (all OSK-registered IRQ upper-half handlers in the system, watchdog timers,
+ * callers from a Kernel-process context). The reader is a single thread that
+ * handles all OSK-registered work.
+ *
+ * @param work a pointer to the _mali_osk_wq_work_t object corresponding to the
+ * work to begin processing.
+ */
+void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work );
+
+/** @brief Cause a queued, deferred call of the high priority work handler
+ *
+ * Function is the same as \a _mali_osk_wq_schedule_work() with the only
+ * difference that it runs in a high (real time) priority on the system.
+ *
+ * Should only be used as a substitue for doing the same work in interrupts.
+ *
+ * This is allowed to sleep, but the work should be small since it will block
+ * all other applications.
+*/
+void _mali_osk_wq_schedule_work_high_pri( _mali_osk_wq_work_t *work );
+
+/** @brief Flush the work queue
+ *
+ * This will flush the OSK work queue, ensuring all work in the queue has
+ * completed before returning.
+ *
+ * Since this blocks on the completion of work in the work-queue, the
+ * caller of this function \b must \b not hold any mutexes that are taken by
+ * any registered work handler. To do so may cause a deadlock.
+ *
+ */
+void _mali_osk_wq_flush(void);
+
+/** @brief Create work in the delayed work queue
+ *
+ * Creates a work object which can be scheduled in the work queue. When
+ * scheduled, a timer will be start and the \a handler will be called with
+ * \a data as the argument when timer out
+ *
+ * Refer to \ref _mali_osk_wq_delayed_schedule_work() for details on how work
+ * is scheduled in the queue.
+ *
+ * The returned pointer must be freed with \ref _mali_osk_wq_delayed_delete_work_nonflush()
+ * when no longer needed.
+ */
+_mali_osk_wq_delayed_work_t *_mali_osk_wq_delayed_create_work(_mali_osk_wq_work_handler_t handler, void *data);
+
+/** @brief Delete a work object
+ *
+ * This will NOT flush the work queue, so only call this if you are sure that the work handler will
+ * not be called after deletion.
+ */
+void _mali_osk_wq_delayed_delete_work_nonflush(_mali_osk_wq_delayed_work_t *work);
+
+/** @brief Cancel a delayed work without waiting for it to finish
+ *
+ * Note that the \a work callback function may still be running on return from
+ * _mali_osk_wq_delayed_cancel_work_async().
+ *
+ * @param work The delayed work to be cancelled
+ */
+void _mali_osk_wq_delayed_cancel_work_async(_mali_osk_wq_delayed_work_t *work);
+
+/** @brief Cancel a delayed work and wait for it to finish
+ *
+ * When this function returns, the \a work was either cancelled or it finished running.
+ *
+ * @param work The delayed work to be cancelled
+ */
+void _mali_osk_wq_delayed_cancel_work_sync(_mali_osk_wq_delayed_work_t *work);
+
+/** @brief Put \a work task in global workqueue after delay
+ *
+ * After waiting for a given time this puts a job in the kernel-global
+ * workqueue.
+ *
+ * If \a work was already on a queue, this function will return without doing anything
+ *
+ * @param work job to be done
+ * @param delay number of jiffies to wait or 0 for immediate execution
+ */
+void _mali_osk_wq_delayed_schedule_work(_mali_osk_wq_delayed_work_t *work, u32 delay);
+
+/** @} */ /* end group _mali_osk_wq */
+
+
+/** @addtogroup _mali_osk_irq
+ * @{ */
+
+/** @brief Initialize IRQ handling for a resource
+ *
+ * Registers an interrupt handler \a uhandler for the given IRQ number \a irqnum.
+ * \a data will be passed as argument to the handler when an interrupt occurs.
+ *
+ * If \a irqnum is -1, _mali_osk_irq_init will probe for the IRQ number using
+ * the supplied \a trigger_func and \a ack_func. These functions will also
+ * receive \a data as their argument.
+ *
+ * @param irqnum The IRQ number that the resource uses, as seen by the CPU.
+ * The value -1 has a special meaning which indicates the use of probing, and
+ * trigger_func and ack_func must be non-NULL.
+ * @param uhandler The interrupt handler, corresponding to a ISR handler for
+ * the resource
+ * @param int_data resource specific data, which will be passed to uhandler
+ * @param trigger_func Optional: a function to trigger the resource's irq, to
+ * probe for the interrupt. Use NULL if irqnum != -1.
+ * @param ack_func Optional: a function to acknowledge the resource's irq, to
+ * probe for the interrupt. Use NULL if irqnum != -1.
+ * @param probe_data resource-specific data, which will be passed to
+ * (if present) trigger_func and ack_func
+ * @param description textual description of the IRQ resource.
+ * @return on success, a pointer to a _mali_osk_irq_t object, which represents
+ * the IRQ handling on this resource. NULL on failure.
+ */
+_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description );
+
+/** @brief Terminate IRQ handling on a resource.
+ *
+ * This will disable the interrupt from the device, and then waits for any
+ * currently executing IRQ handlers to complete.
+ *
+ * @note If work is deferred to an IRQ bottom-half handler through
+ * \ref _mali_osk_wq_schedule_work(), be sure to flush any remaining work
+ * with \ref _mali_osk_wq_flush() or (implicitly) with \ref _mali_osk_wq_delete_work()
+ *
+ * @param irq a pointer to the _mali_osk_irq_t object corresponding to the
+ * resource whose IRQ handling is to be terminated.
+ */
+void _mali_osk_irq_term( _mali_osk_irq_t *irq );
+
+/** @} */ /* end group _mali_osk_irq */
+
+
+/** @addtogroup _mali_osk_atomic
+ * @{ */
+
+/** @brief Decrement an atomic counter
+ *
+ * @note It is an error to decrement the counter beyond -(1<<23)
+ *
+ * @param atom pointer to an atomic counter */
+void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom );
+
+/** @brief Decrement an atomic counter, return new value
+ *
+ * @param atom pointer to an atomic counter
+ * @return The new value, after decrement */
+u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom );
+
+/** @brief Increment an atomic counter
+ *
+ * @note It is an error to increment the counter beyond (1<<23)-1
+ *
+ * @param atom pointer to an atomic counter */
+void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom );
+
+/** @brief Increment an atomic counter, return new value
+ *
+ * @param atom pointer to an atomic counter */
+u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom );
+
+/** @brief Initialize an atomic counter
+ *
+ * @note the parameter required is a u32, and so signed integers should be
+ * cast to u32.
+ *
+ * @param atom pointer to an atomic counter
+ * @param val the value to initialize the atomic counter.
+ * @return _MALI_OSK_ERR_OK on success, otherwise, a suitable
+ * _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val );
+
+/** @brief Read a value from an atomic counter
+ *
+ * This can only be safely used to determine the value of the counter when it
+ * is guaranteed that other threads will not be modifying the counter. This
+ * makes its usefulness limited.
+ *
+ * @param atom pointer to an atomic counter
+ */
+u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom );
+
+/** @brief Terminate an atomic counter
+ *
+ * @param atom pointer to an atomic counter
+ */
+void _mali_osk_atomic_term( _mali_osk_atomic_t *atom );
+
+/** @brief Assign a new val to atomic counter, and return the old atomic counter
+ *
+ * @param atom pointer to an atomic counter
+ * @param val the new value assign to the atomic counter
+ * @return the old value of the atomic counter
+ */
+u32 _mali_osk_atomic_xchg( _mali_osk_atomic_t *atom, u32 val );
+/** @} */  /* end group _mali_osk_atomic */
+
+
+/** @defgroup _mali_osk_memory OSK Memory Allocation
+ * @{ */
+
+/** @brief Allocate zero-initialized memory.
+ *
+ * Returns a buffer capable of containing at least \a n elements of \a size
+ * bytes each. The buffer is initialized to zero.
+ *
+ * If there is a need for a bigger block of memory (16KB or bigger), then
+ * consider to use _mali_osk_vmalloc() instead, as this function might
+ * map down to a OS function with size limitations.
+ *
+ * The buffer is suitably aligned for storage and subsequent access of every
+ * type that the compiler supports. Therefore, the pointer to the start of the
+ * buffer may be cast into any pointer type, and be subsequently accessed from
+ * such a pointer, without loss of information.
+ *
+ * When the buffer is no longer in use, it must be freed with _mali_osk_free().
+ * Failure to do so will cause a memory leak.
+ *
+ * @note Most toolchains supply memory allocation functions that meet the
+ * compiler's alignment requirements.
+ *
+ * @param n Number of elements to allocate
+ * @param size Size of each element
+ * @return On success, the zero-initialized buffer allocated. NULL on failure
+ */
+void *_mali_osk_calloc( u32 n, u32 size );
+
+/** @brief Allocate memory.
+ *
+ * Returns a buffer capable of containing at least \a size bytes. The
+ * contents of the buffer are undefined.
+ *
+ * If there is a need for a bigger block of memory (16KB or bigger), then
+ * consider to use _mali_osk_vmalloc() instead, as this function might
+ * map down to a OS function with size limitations.
+ *
+ * The buffer is suitably aligned for storage and subsequent access of every
+ * type that the compiler supports. Therefore, the pointer to the start of the
+ * buffer may be cast into any pointer type, and be subsequently accessed from
+ * such a pointer, without loss of information.
+ *
+ * When the buffer is no longer in use, it must be freed with _mali_osk_free().
+ * Failure to do so will cause a memory leak.
+ *
+ * @note Most toolchains supply memory allocation functions that meet the
+ * compiler's alignment requirements.
+ *
+ * Remember to free memory using _mali_osk_free().
+ * @param size Number of bytes to allocate
+ * @return On success, the buffer allocated. NULL on failure.
+ */
+void *_mali_osk_malloc( u32 size );
+
+/** @brief Free memory.
+ *
+ * Reclaims the buffer pointed to by the parameter \a ptr for the system.
+ * All memory returned from _mali_osk_malloc() and _mali_osk_calloc()
+ * must be freed before the application exits. Otherwise,
+ * a memory leak will occur.
+ *
+ * Memory must be freed once. It is an error to free the same non-NULL pointer
+ * more than once.
+ *
+ * It is legal to free the NULL pointer.
+ *
+ * @param ptr Pointer to buffer to free
+ */
+void _mali_osk_free( void *ptr );
+
+/** @brief Allocate memory.
+ *
+ * Returns a buffer capable of containing at least \a size bytes. The
+ * contents of the buffer are undefined.
+ *
+ * This function is potentially slower than _mali_osk_malloc() and _mali_osk_calloc(),
+ * but do support bigger sizes.
+ *
+ * The buffer is suitably aligned for storage and subsequent access of every
+ * type that the compiler supports. Therefore, the pointer to the start of the
+ * buffer may be cast into any pointer type, and be subsequently accessed from
+ * such a pointer, without loss of information.
+ *
+ * When the buffer is no longer in use, it must be freed with _mali_osk_free().
+ * Failure to do so will cause a memory leak.
+ *
+ * @note Most toolchains supply memory allocation functions that meet the
+ * compiler's alignment requirements.
+ *
+ * Remember to free memory using _mali_osk_free().
+ * @param size Number of bytes to allocate
+ * @return On success, the buffer allocated. NULL on failure.
+ */
+void *_mali_osk_valloc( u32 size );
+
+/** @brief Free memory.
+ *
+ * Reclaims the buffer pointed to by the parameter \a ptr for the system.
+ * All memory returned from _mali_osk_valloc() must be freed before the
+ * application exits. Otherwise a memory leak will occur.
+ *
+ * Memory must be freed once. It is an error to free the same non-NULL pointer
+ * more than once.
+ *
+ * It is legal to free the NULL pointer.
+ *
+ * @param ptr Pointer to buffer to free
+ */
+void _mali_osk_vfree( void *ptr );
+
+/** @brief Copies memory.
+ *
+ * Copies the \a len bytes from the buffer pointed by the parameter \a src
+ * directly to the buffer pointed by \a dst.
+ *
+ * It is an error for \a src to overlap \a dst anywhere in \a len bytes.
+ *
+ * @param dst Pointer to the destination array where the content is to be
+ * copied.
+ * @param src Pointer to the source of data to be copied.
+ * @param len Number of bytes to copy.
+ * @return \a dst is always passed through unmodified.
+ */
+void *_mali_osk_memcpy( void *dst, const void *src, u32 len );
+
+/** @brief Fills memory.
+ *
+ * Sets the first \a n bytes of the block of memory pointed to by \a s to
+ * the specified value
+ * @param s Pointer to the block of memory to fill.
+ * @param c Value to be set, passed as u32. Only the 8 Least Significant Bits (LSB)
+ * are used.
+ * @param n Number of bytes to be set to the value.
+ * @return \a s is always passed through unmodified
+ */
+void *_mali_osk_memset( void *s, u32 c, u32 n );
+/** @} */ /* end group _mali_osk_memory */
+
+
+/** @brief Checks the amount of memory allocated
+ *
+ * Checks that not more than \a max_allocated bytes are allocated.
+ *
+ * Some OS bring up an interactive out of memory dialogue when the
+ * system runs out of memory. This can stall non-interactive
+ * apps (e.g. automated test runs). This function can be used to
+ * not trigger the OOM dialogue by keeping allocations
+ * within a certain limit.
+ *
+ * @return MALI_TRUE when \a max_allocated bytes are not in use yet. MALI_FALSE
+ * when at least \a max_allocated bytes are in use.
+ */
+mali_bool _mali_osk_mem_check_allocated( u32 max_allocated );
+
+
+/** @addtogroup _mali_osk_low_level_memory
+ * @{ */
+
+/** @brief Issue a memory barrier
+ *
+ * This defines an arbitrary memory barrier operation, which forces an ordering constraint
+ * on memory read and write operations.
+ */
+void _mali_osk_mem_barrier( void );
+
+/** @brief Issue a write memory barrier
+ *
+ * This defines an write memory barrier operation which forces an ordering constraint
+ * on memory write operations.
+ */
+void _mali_osk_write_mem_barrier( void );
+
+/** @brief Map a physically contiguous region into kernel space
+ *
+ * This is primarily used for mapping in registers from resources, and Mali-MMU
+ * page tables. The mapping is only visable from kernel-space.
+ *
+ * Access has to go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32
+ *
+ * @param phys CPU-physical base address of the memory to map in. This must
+ * be aligned to the system's page size, which is assumed to be 4K.
+ * @param size the number of bytes of physically contiguous address space to
+ * map in
+ * @param description A textual description of the memory being mapped in.
+ * @return On success, a Mali IO address through which the mapped-in
+ * memory/registers can be accessed. NULL on failure.
+ */
+mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description );
+
+/** @brief Unmap a physically contiguous address range from kernel space.
+ *
+ * The address range should be one previously mapped in through
+ * _mali_osk_mem_mapioregion.
+ *
+ * It is a programming error to do (but not limited to) the following:
+ * - attempt an unmap twice
+ * - unmap only part of a range obtained through _mali_osk_mem_mapioregion
+ * - unmap more than the range obtained through  _mali_osk_mem_mapioregion
+ * - unmap an address range that was not successfully mapped using
+ * _mali_osk_mem_mapioregion
+ * - provide a mapping that does not map to phys.
+ *
+ * @param phys CPU-physical base address of the memory that was originally
+ * mapped in. This must be aligned to the system's page size, which is assumed
+ * to be 4K
+ * @param size The number of bytes that were originally mapped in.
+ * @param mapping The Mali IO address through which the mapping is
+ * accessed.
+ */
+void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address mapping );
+
+/** @brief Allocate and Map a physically contiguous region into kernel space
+ *
+ * This is used for allocating physically contiguous regions (such as Mali-MMU
+ * page tables) and mapping them into kernel space. The mapping is only
+ * visible from kernel-space.
+ *
+ * The alignment of the returned memory is guaranteed to be at least
+ * _MALI_OSK_CPU_PAGE_SIZE.
+ *
+ * Access must go through _mali_osk_mem_ioread32 and _mali_osk_mem_iowrite32
+ *
+ * @note This function is primarily to provide support for OSs that are
+ * incapable of separating the tasks 'allocate physically contiguous memory'
+ * and 'map it into kernel space'
+ *
+ * @param[out] phys CPU-physical base address of memory that was allocated.
+ * (*phys) will be guaranteed to be aligned to at least
+ * _MALI_OSK_CPU_PAGE_SIZE on success.
+ *
+ * @param[in] size the number of bytes of physically contiguous memory to
+ * allocate. This must be a multiple of _MALI_OSK_CPU_PAGE_SIZE.
+ *
+ * @return On success, a Mali IO address through which the mapped-in
+ * memory/registers can be accessed. NULL on failure, and (*phys) is unmodified.
+ */
+mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size );
+
+/** @brief Free a physically contiguous address range from kernel space.
+ *
+ * The address range should be one previously mapped in through
+ * _mali_osk_mem_allocioregion.
+ *
+ * It is a programming error to do (but not limited to) the following:
+ * - attempt a free twice on the same ioregion
+ * - free only part of a range obtained through _mali_osk_mem_allocioregion
+ * - free more than the range obtained through  _mali_osk_mem_allocioregion
+ * - free an address range that was not successfully mapped using
+ * _mali_osk_mem_allocioregion
+ * - provide a mapping that does not map to phys.
+ *
+ * @param phys CPU-physical base address of the memory that was originally
+ * mapped in, which was aligned to _MALI_OSK_CPU_PAGE_SIZE.
+ * @param size The number of bytes that were originally mapped in, which was
+ * a multiple of _MALI_OSK_CPU_PAGE_SIZE.
+ * @param mapping The Mali IO address through which the mapping is
+ * accessed.
+ */
+void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address mapping );
+
+/** @brief Request a region of physically contiguous memory
+ *
+ * This is used to ensure exclusive access to a region of physically contigous
+ * memory.
+ *
+ * It is acceptable to implement this as a stub. However, it is then the job
+ * of the System Integrator to ensure that no other device driver will be using
+ * the physical address ranges used by Mali, while the Mali device driver is
+ * loaded.
+ *
+ * @param phys CPU-physical base address of the memory to request. This must
+ * be aligned to the system's page size, which is assumed to be 4K.
+ * @param size the number of bytes of physically contiguous address space to
+ * request.
+ * @param description A textual description of the memory being requested.
+ * @return _MALI_OSK_ERR_OK on success. Otherwise, a suitable
+ * _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description );
+
+/** @brief Un-request a region of physically contiguous memory
+ *
+ * This is used to release a regious of physically contiguous memory previously
+ * requested through _mali_osk_mem_reqregion, so that other device drivers may
+ * use it. This will be called at time of Mali device driver termination.
+ *
+ * It is a programming error to attempt to:
+ * - unrequest a region twice
+ * - unrequest only part of a range obtained through _mali_osk_mem_reqregion
+ * - unrequest more than the range obtained through  _mali_osk_mem_reqregion
+ * - unrequest an address range that was not successfully requested using
+ * _mali_osk_mem_reqregion
+ *
+ * @param phys CPU-physical base address of the memory to un-request. This must
+ * be aligned to the system's page size, which is assumed to be 4K
+ * @param size the number of bytes of physically contiguous address space to
+ * un-request.
+ */
+void _mali_osk_mem_unreqregion( u32 phys, u32 size );
+
+/** @brief Read from a location currently mapped in through
+ * _mali_osk_mem_mapioregion
+ *
+ * This reads a 32-bit word from a 32-bit aligned location. It is a programming
+ * error to provide unaligned locations, or to read from memory that is not
+ * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or
+ * _mali_osk_mem_allocioregion().
+ *
+ * @param mapping Mali IO address to read from
+ * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4
+ * @return the 32-bit word from the specified location.
+ */
+u32 _mali_osk_mem_ioread32( volatile mali_io_address mapping, u32 offset );
+
+/** @brief Write to a location currently mapped in through
+ * _mali_osk_mem_mapioregion without memory barriers
+ *
+ * This write a 32-bit word to a 32-bit aligned location without using memory barrier.
+ * It is a programming error to provide unaligned locations, or to write to memory that is not
+ * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or
+ * _mali_osk_mem_allocioregion().
+ *
+ * @param mapping Mali IO address to write to
+ * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4
+ * @param val the 32-bit word to write.
+ */
+void _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val );
+
+/** @brief Write to a location currently mapped in through
+ * _mali_osk_mem_mapioregion with write memory barrier
+ *
+ * This write a 32-bit word to a 32-bit aligned location. It is a programming
+ * error to provide unaligned locations, or to write to memory that is not
+ * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or
+ * _mali_osk_mem_allocioregion().
+ *
+ * @param mapping Mali IO address to write to
+ * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4
+ * @param val the 32-bit word to write.
+ */
+void _mali_osk_mem_iowrite32( volatile mali_io_address mapping, u32 offset, u32 val );
+
+/** @brief Flush all CPU caches
+ *
+ * This should only be implemented if flushing of the cache is required for
+ * memory mapped in through _mali_osk_mem_mapregion.
+ */
+void _mali_osk_cache_flushall( void );
+
+/** @brief Flush any caches necessary for the CPU and MALI to have the same view of a range of uncached mapped memory
+ *
+ * This should only be implemented if your OS doesn't do a full cache flush (inner & outer)
+ * after allocating uncached mapped memory.
+ *
+ * Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory.
+ * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches.
+ * This is required for MALI to have the correct view of the memory.
+ */
+void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size );
+
+/** @} */ /* end group _mali_osk_low_level_memory */
+
+
+/** @addtogroup _mali_osk_notification
+ *
+ * User space notification framework
+ *
+ * Communication with user space of asynchronous events is performed through a
+ * synchronous call to the \ref u_k_api.
+ *
+ * Since the events are asynchronous, the events have to be queued until a
+ * synchronous U/K API call can be made by user-space. A U/K API call might also
+ * be received before any event has happened. Therefore the notifications the
+ * different subsystems wants to send to user space has to be queued for later
+ * reception, or a U/K API call has to be blocked until an event has occured.
+ *
+ * Typical uses of notifications are after running of jobs on the hardware or
+ * when changes to the system is detected that needs to be relayed to user
+ * space.
+ *
+ * After an event has occured user space has to be notified using some kind of
+ * message. The notification framework supports sending messages to waiting
+ * threads or queueing of messages until a U/K API call is made.
+ *
+ * The notification queue is a FIFO. There are no restrictions on the numbers
+ * of readers or writers in the queue.
+ *
+ * A message contains what user space needs to identifiy how to handle an
+ * event. This includes a type field and a possible type specific payload.
+ *
+ * A notification to user space is represented by a
+ * \ref _mali_osk_notification_t object. A sender gets hold of such an object
+ * using _mali_osk_notification_create(). The buffer given by the
+ * _mali_osk_notification_t::result_buffer field in the object is used to store
+ * any type specific data. The other fields are internal to the queue system
+ * and should not be touched.
+ *
+ * @{ */
+
+/** @brief Create a notification object
+ *
+ * Returns a notification object which can be added to the queue of
+ * notifications pending for user space transfer.
+ *
+ * The implementation will initialize all members of the
+ * \ref _mali_osk_notification_t object. In particular, the
+ * _mali_osk_notification_t::result_buffer member will be initialized to point
+ * to \a size bytes of storage, and that storage will be suitably aligned for
+ * storage of any structure. That is, the created buffer meets the same
+ * requirements as _mali_osk_malloc().
+ *
+ * The notification object must be deleted when not in use. Use
+ * _mali_osk_notification_delete() for deleting it.
+ *
+ * @note You \b must \b not call _mali_osk_free() on a \ref _mali_osk_notification_t,
+ * object, or on a _mali_osk_notification_t::result_buffer. You must only use
+ * _mali_osk_notification_delete() to free the resources assocaited with a
+ * \ref _mali_osk_notification_t object.
+ *
+ * @param type The notification type
+ * @param size The size of the type specific buffer to send
+ * @return Pointer to a notification object with a suitable buffer, or NULL on error.
+ */
+_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size );
+
+/** @brief Delete a notification object
+ *
+ * This must be called to reclaim the resources of a notification object. This
+ * includes:
+ * - The _mali_osk_notification_t::result_buffer
+ * - The \ref _mali_osk_notification_t itself.
+ *
+ * A notification object \b must \b not be used after it has been deleted by
+ * _mali_osk_notification_delete().
+ *
+ * In addition, the notification object may not be deleted while it is in a
+ * queue. That is, if it has been placed on a queue with
+ * _mali_osk_notification_queue_send(), then it must not be deleted until
+ * it has been received by a call to _mali_osk_notification_queue_receive().
+ * Otherwise, the queue may be corrupted.
+ *
+ * @param object the notification object to delete.
+ */
+void _mali_osk_notification_delete( _mali_osk_notification_t *object );
+
+/** @brief Create a notification queue
+ *
+ * Creates a notification queue which can be used to queue messages for user
+ * delivery and get queued messages from
+ *
+ * The queue is a FIFO, and has no restrictions on the numbers of readers or
+ * writers.
+ *
+ * When the queue is no longer in use, it must be terminated with
+ * \ref _mali_osk_notification_queue_term(). Failure to do so will result in a
+ * memory leak.
+ *
+ * @return Pointer to a new notification queue or NULL on error.
+ */
+_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void );
+
+/** @brief Destroy a notification queue
+ *
+ * Destroys a notification queue and frees associated resources from the queue.
+ *
+ * A notification queue \b must \b not be destroyed in the following cases:
+ * - while there are \ref _mali_osk_notification_t objects in the queue.
+ * - while there are writers currently acting upon the queue. That is, while
+ * a thread is currently calling \ref _mali_osk_notification_queue_send() on
+ * the queue, or while a thread may call
+ * \ref _mali_osk_notification_queue_send() on the queue in the future.
+ * - while there are readers currently waiting upon the queue. That is, while
+ * a thread is currently calling \ref _mali_osk_notification_queue_receive() on
+ * the queue, or while a thread may call
+ * \ref _mali_osk_notification_queue_receive() on the queue in the future.
+ *
+ * Therefore, all \ref _mali_osk_notification_t objects must be flushed and
+ * deleted by the code that makes use of the notification queues, since only
+ * they know the structure of the _mali_osk_notification_t::result_buffer
+ * (even if it may only be a flat sturcture).
+ *
+ * @note Since the queue is a FIFO, the code using notification queues may
+ * create its own 'flush' type of notification, to assist in flushing the
+ * queue.
+ *
+ * Once the queue has been destroyed, it must not be used again.
+ *
+ * @param queue The queue to destroy
+ */
+void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue );
+
+/** @brief Schedule notification for delivery
+ *
+ * When a \ref _mali_osk_notification_t object has been created successfully
+ * and set up, it may be added to the queue of objects waiting for user space
+ * transfer.
+ *
+ * The sending will not block if the queue is full.
+ *
+ * A \ref _mali_osk_notification_t object \b must \b not be put on two different
+ * queues at the same time, or enqueued twice onto a single queue before
+ * reception. However, it is acceptable for it to be requeued \em after reception
+ * from a call to _mali_osk_notification_queue_receive(), even onto the same queue.
+ *
+ * Again, requeuing must also not enqueue onto two different queues at the same
+ * time, or enqueue onto the same queue twice before reception.
+ *
+ * @param queue The notification queue to add this notification to
+ * @param object The entry to add
+ */
+void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object );
+
+/** @brief Receive a notification from a queue
+ *
+ * Receives a single notification from the given queue.
+ *
+ * If no notifciations are ready the thread will sleep until one becomes ready.
+ * Therefore, notifications may not be received into an
+ * IRQ or 'atomic' context (that is, a context where sleeping is disallowed).
+ *
+ * @param queue The queue to receive from
+ * @param result Pointer to storage of a pointer of type
+ * \ref _mali_osk_notification_t*. \a result will be written to such that the
+ * expression \a (*result) will evaluate to a pointer to a valid
+ * \ref _mali_osk_notification_t object, or NULL if none were received.
+ * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_RESTARTSYSCALL if the sleep was interrupted.
+ */
+_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result );
+
+/** @brief Dequeues a notification from a queue
+ *
+ * Receives a single notification from the given queue.
+ *
+ * If no notifciations are ready the function call will return an error code.
+ *
+ * @param queue The queue to receive from
+ * @param result Pointer to storage of a pointer of type
+ * \ref _mali_osk_notification_t*. \a result will be written to such that the
+ * expression \a (*result) will evaluate to a pointer to a valid
+ * \ref _mali_osk_notification_t object, or NULL if none were received.
+ * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if queue was empty.
+ */
+_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result );
+
+/** @} */ /* end group _mali_osk_notification */
+
+
+/** @addtogroup _mali_osk_timer
+ *
+ * Timers use the OS's representation of time, which are 'ticks'. This is to
+ * prevent aliasing problems between the internal timer time, and the time
+ * asked for.
+ *
+ * @{ */
+
+/** @brief Initialize a timer
+ *
+ * Allocates resources for a new timer, and initializes them. This does not
+ * start the timer.
+ *
+ * @return a pointer to the allocated timer object, or NULL on failure.
+ */
+_mali_osk_timer_t *_mali_osk_timer_init(void);
+
+/** @brief Start a timer
+ *
+ * It is an error to start a timer without setting the callback via
+ * _mali_osk_timer_setcallback().
+ *
+ * It is an error to use this to start an already started timer.
+ *
+ * The timer will expire in \a ticks_to_expire ticks, at which point, the
+ * callback function will be invoked with the callback-specific data,
+ * as registered by _mali_osk_timer_setcallback().
+ *
+ * @param tim the timer to start
+ * @param ticks_to_expire the amount of time in ticks for the timer to run
+ * before triggering.
+ */
+void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire );
+
+/** @brief Modify a timer
+ *
+ * Set the relative time at which a timer will expire, and start it if it is
+ * stopped. If \a ticks_to_expire 0 the timer fires immediately.
+ *
+ * It is an error to modify a timer without setting the callback via
+ *  _mali_osk_timer_setcallback().
+ *
+ * The timer will expire at \a ticks_to_expire from the time of the call, at
+ * which point, the callback function will be invoked with the
+ * callback-specific data, as set by _mali_osk_timer_setcallback().
+ *
+ * @param tim the timer to modify, and start if necessary
+ * @param ticks_to_expire the \em absolute time in ticks at which this timer
+ * should trigger.
+ *
+ */
+void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire);
+
+/** @brief Stop a timer, and block on its completion.
+ *
+ * Stop the timer. When the function returns, it is guaranteed that the timer's
+ * callback will not be running on any CPU core.
+ *
+ * Since stoping the timer blocks on compeletion of the callback, the callback
+ * may not obtain any mutexes that the caller holds. Otherwise, a deadlock will
+ * occur.
+ *
+ * @note While the callback itself is guaranteed to not be running, work
+ * enqueued on the work-queue by the timer (with
+ * \ref _mali_osk_wq_schedule_work()) may still run. The timer callback and
+ * work handler must take this into account.
+ *
+ * It is legal to stop an already stopped timer.
+ *
+ * @param tim the timer to stop.
+ *
+ */
+void _mali_osk_timer_del( _mali_osk_timer_t *tim );
+
+/** @brief Stop a timer.
+ *
+ * Stop the timer. When the function returns, the timer's callback may still be
+ * running on any CPU core.
+ *
+ * It is legal to stop an already stopped timer.
+ *
+ * @param tim the timer to stop.
+ */
+void _mali_osk_timer_del_async( _mali_osk_timer_t *tim );
+
+/** @brief Check if timer is pending.
+ *
+ * Check if timer is active.
+ *
+ * @param tim the timer to check
+ * @return MALI_TRUE if time is active, MALI_FALSE if it is not active
+ */
+mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim);
+
+/** @brief Set a timer's callback parameters.
+ *
+ * This must be called at least once before a timer is started/modified.
+ *
+ * After a timer has been stopped or expires, the callback remains set. This
+ * means that restarting the timer will call the same function with the same
+ * parameters on expiry.
+ *
+ * @param tim the timer to set callback on.
+ * @param callback Function to call when timer expires
+ * @param data Function-specific data to supply to the function on expiry.
+ */
+void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data );
+
+/** @brief Terminate a timer, and deallocate resources.
+ *
+ * The timer must first be stopped by calling _mali_osk_timer_del().
+ *
+ * It is a programming error for _mali_osk_timer_term() to be called on:
+ * - timer that is currently running
+ * - a timer that is currently executing its callback.
+ *
+ * @param tim the timer to deallocate.
+ */
+void _mali_osk_timer_term( _mali_osk_timer_t *tim );
+/** @} */ /* end group _mali_osk_timer */
+
+
+/** @defgroup _mali_osk_time OSK Time functions
+ *
+ * \ref _mali_osk_time use the OS's representation of time, which are
+ * 'ticks'. This is to prevent aliasing problems between the internal timer
+ * time, and the time asked for.
+ *
+ * OS tick time is measured as a u32. The time stored in a u32 may either be
+ * an absolute time, or a time delta between two events. Whilst it is valid to
+ * use math opeartors to \em change the tick value represented as a u32, it
+ * is often only meaningful to do such operations on time deltas, rather than
+ * on absolute time. However, it is meaningful to add/subtract time deltas to
+ * absolute times.
+ *
+ * Conversion between tick time and milliseconds (ms) may not be loss-less,
+ * and are \em implementation \em depenedant.
+ *
+ * Code use OS time must take this into account, since:
+ * - a small OS time may (or may not) be rounded
+ * - a large time may (or may not) overflow
+ *
+ * @{ */
+
+/** @brief Return whether ticka occurs after tickb
+ *
+ * Some OSs handle tick 'rollover' specially, and so can be more robust against
+ * tick counters rolling-over. This function must therefore be called to
+ * determine if a time (in ticks) really occurs after another time (in ticks).
+ *
+ * @param ticka ticka
+ * @param tickb tickb
+ * @return non-zero if ticka represents a time that occurs after tickb.
+ * Zero otherwise.
+ */
+int    _mali_osk_time_after( u32 ticka, u32 tickb );
+
+/** @brief Convert milliseconds to OS 'ticks'
+ *
+ * @param ms time interval in milliseconds
+ * @return the corresponding time interval in OS ticks.
+ */
+u32    _mali_osk_time_mstoticks( u32 ms );
+
+/** @brief Convert OS 'ticks' to milliseconds
+ *
+ * @param ticks time interval in OS ticks.
+ * @return the corresponding time interval in milliseconds
+ */
+u32    _mali_osk_time_tickstoms( u32 ticks );
+
+
+/** @brief Get the current time in OS 'ticks'.
+ * @return the current time in OS 'ticks'.
+ */
+u32    _mali_osk_time_tickcount( void );
+
+/** @brief Cause a microsecond delay
+ *
+ * The delay will have microsecond resolution, and is necessary for correct
+ * operation of the driver. At worst, the delay will be \b at least \a usecs
+ * microseconds, and so may be (significantly) more.
+ *
+ * This function may be implemented as a busy-wait, which is the most sensible
+ * implementation. On OSs where there are situations in which a thread must not
+ * sleep, this is definitely implemented as a busy-wait.
+ *
+ * @param usecs the number of microseconds to wait for.
+ */
+void _mali_osk_time_ubusydelay( u32 usecs );
+
+/** @brief Return time in nano seconds, since any given reference.
+ *
+ * @return Time in nano seconds
+ */
+u64 _mali_osk_time_get_ns( void );
+
+
+/** @} */ /* end group _mali_osk_time */
+
+/** @defgroup _mali_osk_math OSK Math
+ * @{ */
+
+/** @brief Count Leading Zeros (Little-endian)
+ *
+ * @note This function must be implemented to support the reference
+ * implementation of _mali_osk_find_first_zero_bit, as defined in
+ * mali_osk_bitops.h.
+ *
+ * @param val 32-bit words to count leading zeros on
+ * @return the number of leading zeros.
+ */
+u32 _mali_osk_clz( u32 val );
+
+/** @brief find last (most-significant) bit set
+ *
+ * @param val 32-bit words to count last bit set on
+ * @return last bit set.
+ */
+u32 _mali_osk_fls( u32 val );
+
+/** @} */ /* end group _mali_osk_math */
+
+/** @addtogroup _mali_osk_wait_queue OSK Wait Queue functionality
+ * @{ */
+
+/** @brief Initialize an empty Wait Queue */
+_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void );
+
+/** @brief Sleep if condition is false
+ *
+ * @param queue the queue to use
+ * @param condition function pointer to a boolean function
+ * @param data data parameter for condition function
+ *
+ * Put thread to sleep if the given \a condition function returns false. When
+ * being asked to wake up again, the condition will be re-checked and the
+ * thread only woken up if the condition is now true.
+ */
+void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void *), void *data );
+
+/** @brief Sleep if condition is false
+ *
+ * @param queue the queue to use
+ * @param condition function pointer to a boolean function
+ * @param data data parameter for condition function
+ * @param timeout timeout in ms
+ *
+ * Put thread to sleep if the given \a condition function returns false. When
+ * being asked to wake up again, the condition will be re-checked and the
+ * thread only woken up if the condition is now true.  Will return if time
+ * exceeds timeout.
+ */
+void _mali_osk_wait_queue_wait_event_timeout( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void *), void *data, u32 timeout );
+
+/** @brief Wake up all threads in wait queue if their respective conditions are
+ * true
+ *
+ * @param queue the queue whose threads should be woken up
+ *
+ * Wake up all threads in wait queue \a queue whose condition is now true.
+ */
+void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue );
+
+/** @brief terminate a wait queue
+ *
+ * @param queue the queue to terminate.
+ */
+void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue );
+/** @} */ /* end group _mali_osk_wait_queue */
+
+
+/** @addtogroup _mali_osk_miscellaneous
+ * @{ */
+
+/** @brief Output a device driver debug message.
+ *
+ * The interpretation of \a fmt is the same as the \c format parameter in
+ * _mali_osu_vsnprintf().
+ *
+ * @param fmt a _mali_osu_vsnprintf() style format string
+ * @param ... a variable-number of parameters suitable for \a fmt
+ */
+void _mali_osk_dbgmsg( const char *fmt, ... );
+
+/** @brief Print fmt into buf.
+ *
+ * The interpretation of \a fmt is the same as the \c format parameter in
+ * _mali_osu_vsnprintf().
+ *
+ * @param buf a pointer to the result buffer
+ * @param size the total number of bytes allowed to write to \a buf
+ * @param fmt a _mali_osu_vsnprintf() style format string
+ * @param ... a variable-number of parameters suitable for \a fmt
+ * @return The number of bytes written to \a buf
+ */
+u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... );
+
+/** @brief Abnormal process abort.
+ *
+ * Terminates the caller-process if this function is called.
+ *
+ * This function will be called from Debug assert-macros in mali_kernel_common.h.
+ *
+ * This function will never return - because to continue from a Debug assert
+ * could cause even more problems, and hinder debugging of the initial problem.
+ *
+ * This function is only used in Debug builds, and is not used in Release builds.
+ */
+void _mali_osk_abort(void);
+
+/** @brief Sets breakpoint at point where function is called.
+ *
+ * This function will be called from Debug assert-macros in mali_kernel_common.h,
+ * to assist in debugging. If debugging at this level is not required, then this
+ * function may be implemented as a stub.
+ *
+ * This function is only used in Debug builds, and is not used in Release builds.
+ */
+void _mali_osk_break(void);
+
+/** @brief Return an identificator for calling process.
+ *
+ * @return Identificator for calling process.
+ */
+u32 _mali_osk_get_pid(void);
+
+/** @brief Return an identificator for calling thread.
+ *
+ * @return Identificator for calling thread.
+ */
+u32 _mali_osk_get_tid(void);
+
+/** @brief Enable OS controlled runtime power management
+ */
+void _mali_osk_pm_dev_enable(void);
+
+/** @brief Disable OS controlled runtime power management
+ */
+void _mali_osk_pm_dev_disable(void);
+
+
+/** @brief Take a reference to the power manager system for the Mali device.
+ *
+ * When function returns successfully, Mali is ON.
+ *
+ * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference.
+ */
+_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void);
+
+
+/** @brief Release the reference to the power manger system for the Mali device.
+ *
+ * When reference count reach zero, the cores can be off.
+ *
+ * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add().
+ */
+void _mali_osk_pm_dev_ref_dec(void);
+
+
+/** @brief Take a reference to the power manager system for the Mali device.
+ *
+ * Will leave the cores powered off if they are already powered off.
+ *
+ * @note Call \a _mali_osk_pm_dev_ref_dec() to release this reference.
+ *
+ * @return MALI_TRUE if the Mali GPU is powered on, otherwise MALI_FALSE.
+ */
+mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void);
+
+
+/** @brief Releasing the reference to the power manger system for the Mali device.
+ *
+ * When reference count reach zero, the cores can be off.
+ *
+ * @note This must be used to release references taken with \a _mali_osk_pm_dev_ref_add_no_power_on().
+ */
+void _mali_osk_pm_dev_ref_dec_no_power_on(void);
+
+/** @brief Block untill pending PM operations are done
+ */
+void _mali_osk_pm_dev_barrier(void);
+
+/** @} */ /* end group  _mali_osk_miscellaneous */
+
+/** @} */ /* end group osuapi */
+
+/** @} */ /* end group uddapi */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Check standard inlines */
+#ifndef MALI_STATIC_INLINE
+#error MALI_STATIC_INLINE not defined on your OS
+#endif
+
+#ifndef MALI_NON_STATIC_INLINE
+#error MALI_NON_STATIC_INLINE not defined on your OS
+#endif
+
+#endif /* __MALI_OSK_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_osk_bitops.h b/drivers/gpu/arm/mali400/mali/common/mali_osk_bitops.h
new file mode 100755 (executable)
index 0000000..f1ddc2c
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_bitops.h
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#ifndef __MALI_OSK_BITOPS_H__
+#define __MALI_OSK_BITOPS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MALI_STATIC_INLINE void _mali_internal_clear_bit( u32 bit, u32 *addr )
+{
+       MALI_DEBUG_ASSERT( bit < 32 );
+       MALI_DEBUG_ASSERT( NULL != addr );
+
+       (*addr) &= ~(1 << bit);
+}
+
+MALI_STATIC_INLINE void _mali_internal_set_bit( u32 bit, u32 *addr )
+{
+       MALI_DEBUG_ASSERT( bit < 32 );
+       MALI_DEBUG_ASSERT( NULL != addr );
+
+       (*addr) |= (1 << bit);
+}
+
+MALI_STATIC_INLINE u32 _mali_internal_test_bit( u32 bit, u32 value )
+{
+       MALI_DEBUG_ASSERT( bit < 32 );
+       return value & (1 << bit);
+}
+
+MALI_STATIC_INLINE int _mali_internal_find_first_zero_bit( u32 value )
+{
+       u32 inverted;
+       u32 negated;
+       u32 isolated;
+       u32 leading_zeros;
+
+       /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range  0..31 */
+       inverted = ~value; /* zzz...z1000...0 */
+       /* Using count_trailing_zeros on inverted value -
+        * See ARM System Developers Guide for details of count_trailing_zeros */
+
+       /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */
+       negated = (u32)-inverted ; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */
+       /* negated = xxx...x1000...0 */
+
+       isolated = negated & inverted ; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */
+       /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it
+        * Note that the output is zero if value was all 1s */
+
+       leading_zeros = _mali_osk_clz( isolated );
+
+       return 31 - leading_zeros;
+}
+
+
+/** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations
+ * @{ */
+
+/**
+ * These bit-operations do not work atomically, and so locks must be used if
+ * atomicity is required.
+ *
+ * Reference implementations for Little Endian are provided, and so it should
+ * not normally be necessary to re-implement these. Efficient bit-twiddling
+ * techniques are used where possible, implemented in portable C.
+ *
+ * Note that these reference implementations rely on _mali_osk_clz() being
+ * implemented.
+ */
+
+/** @brief Clear a bit in a sequence of 32-bit words
+ * @param nr bit number to clear, starting from the (Little-endian) least
+ * significant bit
+ * @param addr starting point for counting.
+ */
+MALI_STATIC_INLINE void _mali_osk_clear_nonatomic_bit( u32 nr, u32 *addr )
+{
+       addr += nr >> 5; /* find the correct word */
+       nr = nr & ((1 << 5)-1); /* The bit number within the word */
+
+       _mali_internal_clear_bit( nr, addr );
+}
+
+/** @brief Set a bit in a sequence of 32-bit words
+ * @param nr bit number to set, starting from the (Little-endian) least
+ * significant bit
+ * @param addr starting point for counting.
+ */
+MALI_STATIC_INLINE void _mali_osk_set_nonatomic_bit( u32 nr, u32 *addr )
+{
+       addr += nr >> 5; /* find the correct word */
+       nr = nr & ((1 << 5)-1); /* The bit number within the word */
+
+       _mali_internal_set_bit( nr, addr );
+}
+
+/** @brief Test a bit in a sequence of 32-bit words
+ * @param nr bit number to test, starting from the (Little-endian) least
+ * significant bit
+ * @param addr starting point for counting.
+ * @return zero if bit was clear, non-zero if set. Do not rely on the return
+ * value being related to the actual word under test.
+ */
+MALI_STATIC_INLINE u32 _mali_osk_test_bit( u32 nr, u32 *addr )
+{
+       addr += nr >> 5; /* find the correct word */
+       nr = nr & ((1 << 5)-1); /* The bit number within the word */
+
+       return _mali_internal_test_bit( nr, *addr );
+}
+
+/* Return maxbit if not found */
+/** @brief Find the first zero bit in a sequence of 32-bit words
+ * @param addr starting point for search.
+ * @param maxbit the maximum number of bits to search
+ * @return the number of the first zero bit found, or maxbit if none were found
+ * in the specified range.
+ */
+MALI_STATIC_INLINE u32 _mali_osk_find_first_zero_bit( const u32 *addr, u32 maxbit )
+{
+       u32 total;
+
+       for ( total = 0; total < maxbit; total += 32, ++addr ) {
+               int result;
+               result = _mali_internal_find_first_zero_bit( *addr );
+
+               /* non-negative signifies the bit was found */
+               if ( result >= 0 ) {
+                       total += (u32)result;
+                       break;
+               }
+       }
+
+       /* Now check if we reached maxbit or above */
+       if ( total >= maxbit ) {
+               total = maxbit;
+       }
+
+       return total; /* either the found bit nr, or maxbit if not found */
+}
+/** @} */ /* end group _mali_osk_bitops */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_BITOPS_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_osk_list.h b/drivers/gpu/arm/mali400/mali/common/mali_osk_list.h
new file mode 100755 (executable)
index 0000000..c44013f
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_list.h
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#ifndef __MALI_OSK_LIST_H__
+#define __MALI_OSK_LIST_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MALI_STATIC_INLINE void __mali_osk_list_add(_mali_osk_list_t *new_entry, _mali_osk_list_t *prev, _mali_osk_list_t *next)
+{
+       next->prev = new_entry;
+       new_entry->next = next;
+       new_entry->prev = prev;
+       prev->next = new_entry;
+}
+
+MALI_STATIC_INLINE void __mali_osk_list_del(_mali_osk_list_t *prev, _mali_osk_list_t *next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+/** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists
+ * @{ */
+
+/** Reference implementations of Doubly-linked Circular Lists are provided.
+ * There is often no need to re-implement these.
+ *
+ * @note The implementation may differ subtly from any lists the OS provides.
+ * For this reason, these lists should not be mixed with OS-specific lists
+ * inside the OSK/UKK implementation. */
+
+/** @brief Initialize a list to be a head of an empty list
+ * @param exp the list to initialize. */
+#define _MALI_OSK_INIT_LIST_HEAD(exp) _mali_osk_list_init(exp)
+
+/** @brief Define a list variable, which is uninitialized.
+ * @param exp the name of the variable that the list will be defined as. */
+#define _MALI_OSK_LIST_HEAD(exp) _mali_osk_list_t exp
+
+/** @brief Define a list variable, which is initialized.
+ * @param exp the name of the variable that the list will be defined as. */
+#define _MALI_OSK_LIST_HEAD_STATIC_INIT(exp) _mali_osk_list_t exp = { &exp, &exp }
+
+/** @brief Initialize a list element.
+ *
+ * All list elements must be initialized before use.
+ *
+ * Do not use on any list element that is present in a list without using
+ * _mali_osk_list_del first, otherwise this will break the list.
+ *
+ * @param list the list element to initialize
+ */
+MALI_STATIC_INLINE void _mali_osk_list_init( _mali_osk_list_t *list )
+{
+       list->next = list;
+       list->prev = list;
+}
+
+/** @brief Insert a single list element after an entry in a list
+ *
+ * As an example, if this is inserted to the head of a list, then this becomes
+ * the first element of the list.
+ *
+ * Do not use to move list elements from one list to another, as it will break
+ * the originating list.
+ *
+ *
+ * @param newlist the list element to insert
+ * @param list the list in which to insert. The new element will be the next
+ * entry in this list
+ */
+MALI_STATIC_INLINE void _mali_osk_list_add( _mali_osk_list_t *new_entry, _mali_osk_list_t *list )
+{
+       __mali_osk_list_add(new_entry, list, list->next);
+}
+
+/** @brief Insert a single list element before an entry in a list
+ *
+ * As an example, if this is inserted to the head of a list, then this becomes
+ * the last element of the list.
+ *
+ * Do not use to move list elements from one list to another, as it will break
+ * the originating list.
+ *
+ * @param newlist the list element to insert
+ * @param list the list in which to insert. The new element will be the previous
+ * entry in this list
+ */
+MALI_STATIC_INLINE void _mali_osk_list_addtail( _mali_osk_list_t *new_entry, _mali_osk_list_t *list )
+{
+       __mali_osk_list_add(new_entry, list->prev, list);
+}
+
+/** @brief Remove a single element from a list
+ *
+ * The element will no longer be present in the list. The removed list element
+ * will be uninitialized, and so should not be traversed. It must be
+ * initialized before further use.
+ *
+ * @param list the list element to remove.
+ */
+MALI_STATIC_INLINE void _mali_osk_list_del( _mali_osk_list_t *list )
+{
+       __mali_osk_list_del(list->prev, list->next);
+}
+
+/** @brief Remove a single element from a list, and re-initialize it
+ *
+ * The element will no longer be present in the list. The removed list element
+ * will initialized, and so can be used as normal.
+ *
+ * @param list the list element to remove and initialize.
+ */
+MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list )
+{
+       __mali_osk_list_del(list->prev, list->next);
+       _mali_osk_list_init(list);
+}
+
+/** @brief Determine whether a list is empty.
+ *
+ * An empty list is one that contains a single element that points to itself.
+ *
+ * @param list the list to check.
+ * @return non-zero if the list is empty, and zero otherwise.
+ */
+MALI_STATIC_INLINE mali_bool _mali_osk_list_empty( _mali_osk_list_t *list )
+{
+       return list->next == list;
+}
+
+/** @brief Move a list element from one list to another.
+ *
+ * The list element must be initialized.
+ *
+ * As an example, moving a list item to the head of a new list causes this item
+ * to be the first element in the new list.
+ *
+ * @param move the list element to move
+ * @param list the new list into which the element will be inserted, as the next
+ * element in the list.
+ */
+MALI_STATIC_INLINE void _mali_osk_list_move( _mali_osk_list_t *move_entry, _mali_osk_list_t *list )
+{
+       __mali_osk_list_del(move_entry->prev, move_entry->next);
+       _mali_osk_list_add(move_entry, list);
+}
+
+/** @brief Move an entire list
+ *
+ * The list element must be initialized.
+ *
+ * Allows you to move a list from one list head to another list head
+ *
+ * @param old_list The existing list head
+ * @param new_list The new list head (must be an empty list)
+ */
+MALI_STATIC_INLINE void _mali_osk_list_move_list( _mali_osk_list_t *old_list, _mali_osk_list_t *new_list )
+{
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(new_list));
+       if (!_mali_osk_list_empty(old_list)) {
+               new_list->next = old_list->next;
+               new_list->prev = old_list->prev;
+               new_list->next->prev = new_list;
+               new_list->prev->next = new_list;
+               old_list->next = old_list;
+               old_list->prev = old_list;
+       }
+}
+
+/** @brief Find the containing structure of a list
+ *
+ * When traversing a list, this is used to recover the containing structure,
+ * given that is contains a _mali_osk_list_t member.
+ *
+ * Each list must be of structures of one type, and must link the same members
+ * together, otherwise it will not be possible to correctly recover the
+ * sturctures that the lists link.
+ *
+ * @note no type or memory checking occurs to ensure that a structure does in
+ * fact exist for the list entry, and that it is being recovered with respect
+ * to the correct list member.
+ *
+ * @param ptr the pointer to the _mali_osk_list_t member in this structure
+ * @param type the type of the structure that contains the member
+ * @param member the member of the structure that ptr points to.
+ * @return a pointer to a \a type object which contains the _mali_osk_list_t
+ * \a member, as pointed to by the _mali_osk_list_t \a *ptr.
+ */
+#define _MALI_OSK_LIST_ENTRY(ptr, type, member) \
+       _MALI_OSK_CONTAINER_OF(ptr, type, member)
+
+/** @brief Enumerate a list safely
+ *
+ * With this macro, lists can be enumerated in a 'safe' manner. That is,
+ * entries can be deleted from the list without causing an error during
+ * enumeration. To achieve this, a 'temporary' pointer is required, which must
+ * be provided to the macro.
+ *
+ * Use it like a 'for()', 'while()' or 'do()' construct, and so it must be
+ * followed by a statement or compound-statement which will be executed for
+ * each list entry.
+ *
+ * Upon loop completion, providing that an early out was not taken in the
+ * loop body, then it is guaranteed that ptr->member == list, even if the loop
+ * body never executed.
+ *
+ * @param ptr a pointer to an object of type 'type', which points to the
+ * structure that contains the currently enumerated list entry.
+ * @param tmp a pointer to an object of type 'type', which must not be used
+ * inside the list-execution statement.
+ * @param list a pointer to a _mali_osk_list_t, from which enumeration will
+ * begin
+ * @param type the type of the structure that contains the _mali_osk_list_t
+ * member that is part of the list to be enumerated.
+ * @param member the _mali_osk_list_t member of the structure that is part of
+ * the list to be enumerated.
+ */
+#define _MALI_OSK_LIST_FOREACHENTRY(ptr, tmp, list, type, member)         \
+       for (ptr = _MALI_OSK_LIST_ENTRY((list)->next, type, member),      \
+            tmp = _MALI_OSK_LIST_ENTRY(ptr->member.next, type, member);  \
+            &ptr->member != (list);                                      \
+            ptr = tmp,                                                   \
+            tmp = _MALI_OSK_LIST_ENTRY(tmp->member.next, type, member))
+
+/** @brief Enumerate a list in reverse order safely
+ *
+ * This macro is identical to @ref _MALI_OSK_LIST_FOREACHENTRY, except that
+ * entries are enumerated in reverse order.
+ *
+ * @param ptr a pointer to an object of type 'type', which points to the
+ * structure that contains the currently enumerated list entry.
+ * @param tmp a pointer to an object of type 'type', which must not be used
+ * inside the list-execution statement.
+ * @param list a pointer to a _mali_osk_list_t, from which enumeration will
+ * begin
+ * @param type the type of the structure that contains the _mali_osk_list_t
+ * member that is part of the list to be enumerated.
+ * @param member the _mali_osk_list_t member of the structure that is part of
+ * the list to be enumerated.
+ */
+#define _MALI_OSK_LIST_FOREACHENTRY_REVERSE(ptr, tmp, list, type, member) \
+       for (ptr = _MALI_OSK_LIST_ENTRY((list)->prev, type, member),      \
+            tmp = _MALI_OSK_LIST_ENTRY(ptr->member.prev, type, member);  \
+            &ptr->member != (list);                                      \
+            ptr = tmp,                                                   \
+            tmp = _MALI_OSK_LIST_ENTRY(tmp->member.prev, type, member))
+
+/** @} */ /* end group _mali_osk_list */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_LIST_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_osk_mali.h b/drivers/gpu/arm/mali400/mali/common/mali_osk_mali.h
new file mode 100755 (executable)
index 0000000..b6e3c62
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_mali.h
+ * Defines the OS abstraction layer which is specific for the Mali kernel device driver (OSK)
+ */
+
+#ifndef __MALI_OSK_MALI_H__
+#define __MALI_OSK_MALI_H__
+
+#include <linux/mali/mali_utgard.h>
+#include <mali_osk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup _mali_osk_miscellaneous
+ * @{ */
+
+/** @brief Struct with device specific configuration data
+ */
+struct _mali_osk_device_data {
+       /* Dedicated GPU memory range (physical). */
+       u32 dedicated_mem_start;
+       u32 dedicated_mem_size;
+
+       /* Shared GPU memory */
+       u32 shared_mem_size;
+
+       /* Frame buffer memory to be accessible by Mali GPU (physical) */
+       u32 fb_start;
+       u32 fb_size;
+
+       /* Max runtime [ms] for jobs */
+       int max_job_runtime;
+
+       /* Report GPU utilization in this interval (specified in ms) */
+       u32 utilization_interval;
+
+       /* Function that will receive periodic GPU utilization numbers */
+       void (*utilization_callback)(struct mali_gpu_utilization_data *data);
+
+       /*
+        * Mali PMU switch delay.
+        * Only needed if the power gates are connected to the PMU in a high fanout
+        * network. This value is the number of Mali clock cycles it takes to
+        * enable the power gates and turn on the power mesh.
+        * This value will have no effect if a daisy chain implementation is used.
+        */
+       u32 pmu_switch_delay;
+
+       /* Mali Dynamic power domain configuration in sequence from 0-11
+        *  GP  PP0 PP1  PP2  PP3  PP4  PP5  PP6  PP7, L2$0 L2$1 L2$2
+        */
+       u16 pmu_domain_config[12];
+
+       /* Fuction that platform callback for freq tunning, needed when MALI400_POWER_PERFORMANCE_POLICY enabled */
+       int (*set_freq_callback)(unsigned int mhz);
+};
+
+/** @brief Find Mali GPU HW resource
+ *
+ * @param addr Address of Mali GPU resource to find
+ * @param res Storage for resource information if resource is found.
+ * @return _MALI_OSK_ERR_OK on success, _MALI_OSK_ERR_ITEM_NOT_FOUND if resource is not found
+ */
+_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res);
+
+
+/** @brief Find Mali GPU HW base address
+ *
+ * @return 0 if resources are found, otherwise the Mali GPU component with lowest address.
+ */
+u32 _mali_osk_resource_base_address(void);
+
+/** @brief Retrieve the Mali GPU specific data
+ *
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data);
+
+/** @brief Determines if Mali GPU has been configured with shared interrupts.
+ *
+ * @return MALI_TRUE if shared interrupts, MALI_FALSE if not.
+ */
+mali_bool _mali_osk_shared_interrupts(void);
+
+/** @} */ /* end group _mali_osk_miscellaneous */
+
+/** @addtogroup _mali_osk_low_level_memory
+ * @{ */
+
+/** @brief Copy as much data as possible from src to dest, do not crash if src or dest isn't available.
+ *
+ * @param dest Destination buffer (limited to user space mapped Mali memory)
+ * @param src Source buffer
+ * @param size Number of bytes to copy
+ * @return Number of bytes actually copied
+ */
+u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size);
+
+/** @} */ /* end group _mali_osk_low_level_memory */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_MALI_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_osk_profiling.h b/drivers/gpu/arm/mali400/mali/common/mali_osk_profiling.h
new file mode 100755 (executable)
index 0000000..a5136fd
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_OSK_PROFILING_H__
+#define __MALI_OSK_PROFILING_H__
+
+#if defined(CONFIG_MALI400_PROFILING) && defined (CONFIG_TRACEPOINTS)
+
+#include "mali_linux_trace.h"
+#include "mali_profiling_events.h"
+#include "mali_profiling_gator_api.h"
+
+#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576
+
+#define MALI_PROFILING_NO_HW_COUNTER = ((u32)-1)
+
+/** @defgroup _mali_osk_profiling External profiling connectivity
+ * @{ */
+
+/**
+ * Initialize the profiling module.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start);
+
+/*
+ * Terminate the profiling module.
+ */
+void _mali_osk_profiling_term(void);
+
+/**
+ * Start recording profiling data
+ *
+ * The specified limit will determine how large the capture buffer is.
+ * MALI_PROFILING_MAX_BUFFER_ENTRIES determines the maximum size allowed by the device driver.
+ *
+ * @param limit The desired maximum number of events to record on input, the actual maximum on output.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit);
+
+/**
+ * Add an profiling event
+ *
+ * @param event_id The event identificator.
+ * @param data0 First data parameter, depending on event_id specified.
+ * @param data1 Second data parameter, depending on event_id specified.
+ * @param data2 Third data parameter, depending on event_id specified.
+ * @param data3 Fourth data parameter, depending on event_id specified.
+ * @param data4 Fifth data parameter, depending on event_id specified.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+/* Call Linux tracepoint directly */
+#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4))
+
+/**
+ * Report a hardware counter event.
+ *
+ * @param counter_id The ID of the counter.
+ * @param value The value of the counter.
+ */
+
+/* Call Linux tracepoint directly */
+#define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value)
+
+/**
+ * Report SW counters
+ *
+ * @param counters array of counter values
+ */
+void _mali_osk_profiling_report_sw_counters(u32 *counters);
+
+/**
+ * Stop recording profiling data
+ *
+ * @param count Returns the number of recorded events.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count);
+
+/**
+ * Retrieves the number of events that can be retrieved
+ *
+ * @return The number of recorded events that can be retrieved.
+ */
+u32 _mali_osk_profiling_get_count(void);
+
+/**
+ * Retrieve an event
+ *
+ * @param index Event index (start with 0 and continue until this function fails to retrieve all events)
+ * @param timestamp The timestamp for the retrieved event will be stored here.
+ * @param event_id The event ID for the retrieved event will be stored here.
+ * @param data The 5 data values for the retrieved event will be stored here.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]);
+
+/**
+ * Clear the recorded buffer.
+ *
+ * This is needed in order to start another recording.
+ *
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_osk_profiling_clear(void);
+
+/**
+ * Checks if a recording of profiling data is in progress
+ *
+ * @return MALI_TRUE if recording of profiling data is in progress, MALI_FALSE if not
+ */
+mali_bool _mali_osk_profiling_is_recording(void);
+
+/**
+ * Checks if profiling data is available for retrival
+ *
+ * @return MALI_TRUE if profiling data is avaiable, MALI_FALSE if not
+ */
+mali_bool _mali_osk_profiling_have_recording(void);
+
+/** @} */ /* end group _mali_osk_profiling */
+
+#else /* defined(CONFIG_MALI400_PROFILING)  && defined(CONFIG_TRACEPOINTS) */
+
+/* Dummy add_event, for when profiling is disabled. */
+
+#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4)
+
+#endif /* defined(CONFIG_MALI400_PROFILING)  && defined(CONFIG_TRACEPOINTS) */
+
+#endif /* __MALI_OSK_PROFILING_H__ */
+
+
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_osk_types.h b/drivers/gpu/arm/mali400/mali/common/mali_osk_types.h
new file mode 100755 (executable)
index 0000000..313c49a
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_types.h
+ * Defines types of the OS abstraction layer for the kernel device driver (OSK)
+ */
+
+#ifndef __MALI_OSK_TYPES_H__
+#define __MALI_OSK_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup uddapi Unified Device Driver (UDD) APIs
+ *
+ * @{
+ */
+
+/**
+ * @addtogroup oskapi UDD OS Abstraction for Kernel-side (OSK) APIs
+ *
+ * @{
+ */
+
+/** @defgroup _mali_osk_miscellaneous OSK Miscellaneous functions, constants and types
+ * @{ */
+
+/* Define integer types used by OSK. Note: these currently clash with Linux so we only define them if not defined already */
+#ifndef __KERNEL__
+typedef unsigned char      u8;
+typedef signed char        s8;
+typedef unsigned short     u16;
+typedef signed short       s16;
+typedef unsigned int       u32;
+typedef signed int         s32;
+typedef unsigned long long u64;
+#define BITS_PER_LONG (sizeof(long)*8)
+#else
+/* Ensure Linux types u32, etc. are defined */
+#include <linux/types.h>
+#endif
+
+/** @brief Mali Boolean type which uses MALI_TRUE and MALI_FALSE
+  */
+typedef unsigned long mali_bool;
+
+#ifndef MALI_TRUE
+#define MALI_TRUE ((mali_bool)1)
+#endif
+
+#ifndef MALI_FALSE
+#define MALI_FALSE ((mali_bool)0)
+#endif
+
+#define MALI_HW_CORE_NO_COUNTER     ((u32)-1)
+
+/**
+ * @brief OSK Error codes
+ *
+ * Each OS may use its own set of error codes, and may require that the
+ * User/Kernel interface take certain error code. This means that the common
+ * error codes need to be sufficiently rich to pass the correct error code
+ * thorugh from the OSK to U/K layer, across all OSs.
+ *
+ * The result is that some error codes will appear redundant on some OSs.
+ * Under all OSs, the OSK layer must translate native OS error codes to
+ * _mali_osk_errcode_t codes. Similarly, the U/K layer must translate from
+ * _mali_osk_errcode_t codes to native OS error codes.
+ */
+typedef enum {
+       _MALI_OSK_ERR_OK = 0, /**< Success. */
+       _MALI_OSK_ERR_FAULT = -1, /**< General non-success */
+       _MALI_OSK_ERR_INVALID_FUNC = -2, /**< Invalid function requested through User/Kernel interface (e.g. bad IOCTL number) */
+       _MALI_OSK_ERR_INVALID_ARGS = -3, /**< Invalid arguments passed through User/Kernel interface */
+       _MALI_OSK_ERR_NOMEM = -4, /**< Insufficient memory */
+       _MALI_OSK_ERR_TIMEOUT = -5, /**< Timeout occurred */
+       _MALI_OSK_ERR_RESTARTSYSCALL = -6, /**< Special: On certain OSs, must report when an interruptable mutex is interrupted. Ignore otherwise. */
+       _MALI_OSK_ERR_ITEM_NOT_FOUND = -7, /**< Table Lookup failed */
+       _MALI_OSK_ERR_BUSY = -8, /**< Device/operation is busy. Try again later */
+       _MALI_OSK_ERR_UNSUPPORTED = -9, /**< Optional part of the interface used, and is unsupported */
+} _mali_osk_errcode_t;
+
+/** @} */ /* end group _mali_osk_miscellaneous */
+
+/** @defgroup _mali_osk_wq OSK work queues
+ * @{ */
+
+/** @brief Private type for work objects */
+typedef struct _mali_osk_wq_work_s _mali_osk_wq_work_t;
+typedef struct _mali_osk_wq_delayed_work_s _mali_osk_wq_delayed_work_t;
+
+/** @brief Work queue handler function
+ *
+ * This function type is called when the work is scheduled by the work queue,
+ * e.g. as an IRQ bottom-half handler.
+ *
+ * Refer to \ref _mali_osk_wq_schedule_work() for more information on the
+ * work-queue and work handlers.
+ *
+ * @param arg resource-specific data
+ */
+typedef void (*_mali_osk_wq_work_handler_t)( void * arg );
+
+/* @} */ /* end group _mali_osk_wq */
+
+/** @defgroup _mali_osk_irq OSK IRQ handling
+ * @{ */
+
+/** @brief Private type for IRQ handling objects */
+typedef struct _mali_osk_irq_t_struct _mali_osk_irq_t;
+
+/** @brief Optional function to trigger an irq from a resource
+ *
+ * This function is implemented by the common layer to allow probing of a resource's IRQ.
+ * @param arg resource-specific data */
+typedef void  (*_mali_osk_irq_trigger_t)( void * arg );
+
+/** @brief Optional function to acknowledge an irq from a resource
+ *
+ * This function is implemented by the common layer to allow probing of a resource's IRQ.
+ * @param arg resource-specific data
+ * @return _MALI_OSK_ERR_OK if the IRQ was successful, or a suitable _mali_osk_errcode_t on failure. */
+typedef _mali_osk_errcode_t (*_mali_osk_irq_ack_t)( void * arg );
+
+/** @brief IRQ 'upper-half' handler callback.
+ *
+ * This function is implemented by the common layer to do the initial handling of a
+ * resource's IRQ. This maps on to the concept of an ISR that does the minimum
+ * work necessary before handing off to an IST.
+ *
+ * The communication of the resource-specific data from the ISR to the IST is
+ * handled by the OSK implementation.
+ *
+ * On most systems, the IRQ upper-half handler executes in IRQ context.
+ * Therefore, the system may have restrictions about what can be done in this
+ * context
+ *
+ * If an IRQ upper-half handler requires more work to be done than can be
+ * acheived in an IRQ context, then it may defer the work with
+ * _mali_osk_wq_schedule_work(). Refer to \ref _mali_osk_wq_create_work() for
+ * more information.
+ *
+ * @param arg resource-specific data
+ * @return _MALI_OSK_ERR_OK if the IRQ was correctly handled, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+typedef _mali_osk_errcode_t  (*_mali_osk_irq_uhandler_t)( void * arg );
+
+
+/** @} */ /* end group _mali_osk_irq */
+
+
+/** @defgroup _mali_osk_atomic OSK Atomic counters
+ * @{ */
+
+/** @brief Public type of atomic counters
+ *
+ * This is public for allocation on stack. On systems that support it, this is just a single 32-bit value.
+ * On others, it could be encapsulating an object stored elsewhere.
+ *
+ * Regardless of implementation, the \ref _mali_osk_atomic functions \b must be used
+ * for all accesses to the variable's value, even if atomicity is not required.
+ * Do not access u.val or u.obj directly.
+ */
+typedef struct {
+       union {
+               u32 val;
+               void *obj;
+       } u;
+} _mali_osk_atomic_t;
+/** @} */ /* end group _mali_osk_atomic */
+
+
+/** @defgroup _mali_osk_lock OSK Mutual Exclusion Locks
+ * @{ */
+
+
+/** @brief OSK Mutual Exclusion Lock ordered list
+ *
+ * This lists the various types of locks in the system and is used to check
+ * that locks are taken in the correct order.
+ *
+ * - Holding more than one lock of the same order at the same time is not
+ *   allowed.
+ * - Taking a lock of a lower order than the highest-order lock currently held
+ *   is not allowed.
+ *
+ */
+typedef enum {
+       /*  ||    Locks    ||  */
+       /*  ||   must be   ||  */
+       /* _||_  taken in _||_ */
+       /* \  /    this   \  / */
+       /*  \/    order!   \/  */
+
+       _MALI_OSK_LOCK_ORDER_FIRST = 0,
+
+       _MALI_OSK_LOCK_ORDER_SESSIONS,
+       _MALI_OSK_LOCK_ORDER_MEM_SESSION,
+       _MALI_OSK_LOCK_ORDER_MEM_INFO,
+       _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE,
+       _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP,
+       _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL,
+       _MALI_OSK_LOCK_ORDER_GROUP,
+       _MALI_OSK_LOCK_ORDER_TIMELINE_SYSTEM,
+       _MALI_OSK_LOCK_ORDER_SCHEDULER,
+       _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED,
+       _MALI_OSK_LOCK_ORDER_PM_CORE_STATE,
+       _MALI_OSK_LOCK_ORDER_L2_COMMAND,
+       _MALI_OSK_LOCK_ORDER_DMA_COMMAND,
+       _MALI_OSK_LOCK_ORDER_PROFILING,
+       _MALI_OSK_LOCK_ORDER_L2_COUNTER,
+       _MALI_OSK_LOCK_ORDER_UTILIZATION,
+       _MALI_OSK_LOCK_ORDER_PM_EXECUTE,
+       _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS,
+       _MALI_OSK_LOCK_ORDER_PM_DOMAIN,
+       _MALI_OSK_LOCK_ORDER_PMU,
+
+       _MALI_OSK_LOCK_ORDER_LAST,
+} _mali_osk_lock_order_t;
+
+
+/** @brief OSK Mutual Exclusion Lock flags type
+ *
+ * - Any lock can use the order parameter.
+ */
+typedef enum {
+       _MALI_OSK_LOCKFLAG_UNORDERED        = 0x1, /**< Indicate that the order of this lock should not be checked */
+       _MALI_OSK_LOCKFLAG_ORDERED          = 0x2,
+       /** @enum _mali_osk_lock_flags_t
+        *
+        * Flags from 0x10000--0x80000000 are RESERVED for User-mode */
+
+} _mali_osk_lock_flags_t;
+
+/** @brief Mutual Exclusion Lock Mode Optimization hint
+ *
+ * The lock mode is used to implement the read/write locking of locks when we call
+ * functions _mali_osk_mutex_rw_init/wait/signal/term/. In this case, the RO mode can
+ * be used to allow multiple concurrent readers, but no writers. The RW mode is used for
+ * writers, and so will wait for all readers to release the lock (if any present).
+ * Further readers and writers will wait until the writer releases the lock.
+ *
+ * The mode is purely an optimization hint: for example, it is permissible for
+ * all locks to behave in RW mode, regardless of that supplied.
+ *
+ * It is an error to attempt to use locks in anything other that RW mode when
+ * call functions _mali_osk_mutex_rw_wait/signal().
+ *
+ */
+typedef enum {
+       _MALI_OSK_LOCKMODE_UNDEF = -1,  /**< Undefined lock mode. For internal use only */
+       _MALI_OSK_LOCKMODE_RW    = 0x0, /**< Read-write mode, default. All readers and writers are mutually-exclusive */
+       _MALI_OSK_LOCKMODE_RO,          /**< Read-only mode, to support multiple concurrent readers, but mutual exclusion in the presence of writers. */
+       /** @enum _mali_osk_lock_mode_t
+        *
+        * Lock modes 0x40--0x7F are RESERVED for User-mode */
+} _mali_osk_lock_mode_t;
+
+/** @brief Private types for Mutual Exclusion lock objects */
+typedef struct _mali_osk_lock_debug_s _mali_osk_lock_debug_t;
+typedef struct _mali_osk_spinlock_s _mali_osk_spinlock_t;
+typedef struct _mali_osk_spinlock_irq_s _mali_osk_spinlock_irq_t;
+typedef struct _mali_osk_mutex_s _mali_osk_mutex_t;
+typedef struct _mali_osk_mutex_rw_s _mali_osk_mutex_rw_t;
+
+/** @} */ /* end group _mali_osk_lock */
+
+/** @defgroup _mali_osk_low_level_memory OSK Low-level Memory Operations
+ * @{ */
+
+/**
+ * @brief Private data type for use in IO accesses to/from devices.
+ *
+ * This represents some range that is accessible from the device. Examples
+ * include:
+ * - Device Registers, which could be readable and/or writeable.
+ * - Memory that the device has access to, for storing configuration structures.
+ *
+ * Access to this range must be made through the _mali_osk_mem_ioread32() and
+ * _mali_osk_mem_iowrite32() functions.
+ */
+typedef struct _mali_io_address * mali_io_address;
+
+/** @defgroup _MALI_OSK_CPU_PAGE CPU Physical page size macros.
+ *
+ * The order of the page size is supplied for
+ * ease of use by algorithms that might require it, since it is easier to know
+ * it ahead of time rather than calculating it.
+ *
+ * The Mali Page Mask macro masks off the lower bits of a physical address to
+ * give the start address of the page for that physical address.
+ *
+ * @note The Mali device driver code is designed for systems with 4KB page size.
+ * Changing these macros will not make the entire Mali device driver work with
+ * page sizes other than 4KB.
+ *
+ * @note The CPU Physical Page Size has been assumed to be the same as the Mali
+ * Physical Page Size.
+ *
+ * @{
+ */
+
+/** CPU Page Order, as log to base 2 of the Page size. @see _MALI_OSK_CPU_PAGE_SIZE */
+#define _MALI_OSK_CPU_PAGE_ORDER ((u32)12)
+/** CPU Page Size, in bytes.               */
+#define _MALI_OSK_CPU_PAGE_SIZE (((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER))
+/** CPU Page Mask, which masks off the offset within a page */
+#define _MALI_OSK_CPU_PAGE_MASK (~((((u32)1) << (_MALI_OSK_CPU_PAGE_ORDER)) - ((u32)1)))
+/** @} */ /* end of group _MALI_OSK_CPU_PAGE */
+
+/** @defgroup _MALI_OSK_MALI_PAGE Mali Physical Page size macros
+ *
+ * Mali Physical page size macros. The order of the page size is supplied for
+ * ease of use by algorithms that might require it, since it is easier to know
+ * it ahead of time rather than calculating it.
+ *
+ * The Mali Page Mask macro masks off the lower bits of a physical address to
+ * give the start address of the page for that physical address.
+ *
+ * @note The Mali device driver code is designed for systems with 4KB page size.
+ * Changing these macros will not make the entire Mali device driver work with
+ * page sizes other than 4KB.
+ *
+ * @note The Mali Physical Page Size has been assumed to be the same as the CPU
+ * Physical Page Size.
+ *
+ * @{
+ */
+
+/** Mali Page Order, as log to base 2 of the Page size. @see _MALI_OSK_MALI_PAGE_SIZE */
+#define _MALI_OSK_MALI_PAGE_ORDER ((u32)12)
+/** Mali Page Size, in bytes.               */
+#define _MALI_OSK_MALI_PAGE_SIZE (((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER))
+/** Mali Page Mask, which masks off the offset within a page */
+#define _MALI_OSK_MALI_PAGE_MASK (~((((u32)1) << (_MALI_OSK_MALI_PAGE_ORDER)) - ((u32)1)))
+/** @} */ /* end of group _MALI_OSK_MALI_PAGE*/
+
+/** @brief flags for mapping a user-accessible memory range
+ *
+ * Where a function with prefix '_mali_osk_mem_mapregion' accepts flags as one
+ * of the function parameters, it will use one of these. These allow per-page
+ * control over mappings. Compare with the mali_memory_allocation_flag type,
+ * which acts over an entire range
+ *
+ * These may be OR'd together with bitwise OR (|), but must be cast back into
+ * the type after OR'ing.
+ */
+typedef enum {
+       _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR = 0x1, /**< Physical address is OS Allocated */
+} _mali_osk_mem_mapregion_flags_t;
+/** @} */ /* end group _mali_osk_low_level_memory */
+
+/** @defgroup _mali_osk_notification OSK Notification Queues
+ * @{ */
+
+/** @brief Private type for notification queue objects */
+typedef struct _mali_osk_notification_queue_t_struct _mali_osk_notification_queue_t;
+
+/** @brief Public notification data object type */
+typedef struct _mali_osk_notification_t_struct {
+       u32 notification_type;   /**< The notification type */
+       u32 result_buffer_size; /**< Size of the result buffer to copy to user space */
+       void * result_buffer;   /**< Buffer containing any type specific data */
+} _mali_osk_notification_t;
+
+/** @} */ /* end group _mali_osk_notification */
+
+
+/** @defgroup _mali_osk_timer OSK Timer Callbacks
+ * @{ */
+
+/** @brief Function to call when a timer expires
+ *
+ * When a timer expires, this function is called. Note that on many systems,
+ * a timer callback will be executed in IRQ context. Therefore, restrictions
+ * may apply on what can be done inside the timer callback.
+ *
+ * If a timer requires more work to be done than can be acheived in an IRQ
+ * context, then it may defer the work with a work-queue. For example, it may
+ * use \ref _mali_osk_wq_schedule_work() to make use of a bottom-half handler
+ * to carry out the remaining work.
+ *
+ * Stopping the timer with \ref _mali_osk_timer_del() blocks on compeletion of
+ * the callback. Therefore, the callback may not obtain any mutexes also held
+ * by any callers of _mali_osk_timer_del(). Otherwise, a deadlock may occur.
+ *
+ * @param arg Function-specific data */
+typedef void (*_mali_osk_timer_callback_t)(void * arg);
+
+/** @brief Private type for Timer Callback Objects */
+typedef struct _mali_osk_timer_t_struct _mali_osk_timer_t;
+/** @} */ /* end group _mali_osk_timer */
+
+
+/** @addtogroup _mali_osk_list OSK Doubly-Linked Circular Lists
+ * @{ */
+
+/** @brief Public List objects.
+ *
+ * To use, add a _mali_osk_list_t member to the structure that may become part
+ * of a list. When traversing the _mali_osk_list_t objects, use the
+ * _MALI_OSK_CONTAINER_OF() macro to recover the structure from its
+ *_mali_osk_list_t member
+ *
+ * Each structure may have multiple _mali_osk_list_t members, so that the
+ * structure is part of multiple lists. When traversing lists, ensure that the
+ * correct _mali_osk_list_t member is used, because type-checking will be
+ * lost by the compiler.
+ */
+typedef struct _mali_osk_list_s {
+       struct _mali_osk_list_s *next;
+       struct _mali_osk_list_s *prev;
+} _mali_osk_list_t;
+/** @} */ /* end group _mali_osk_list */
+
+/** @addtogroup _mali_osk_miscellaneous
+ * @{ */
+
+/** @brief resource description struct
+ *
+ * Platform independent representation of a Mali HW resource
+ */
+typedef struct _mali_osk_resource {
+       const char * description;       /**< short description of the resource */
+       u32 base;                       /**< Physical base address of the resource, as seen by Mali resources. */
+       u32 irq;                        /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */
+} _mali_osk_resource_t;
+/** @} */ /* end group _mali_osk_miscellaneous */
+
+/** @defgroup _mali_osk_wait_queue OSK Wait Queue functionality
+ * @{ */
+/** @brief Private type for wait queue objects */
+typedef struct _mali_osk_wait_queue_t_struct _mali_osk_wait_queue_t;
+/** @} */ /* end group _mali_osk_wait_queue */
+
+/** @} */ /* end group osuapi */
+
+/** @} */ /* end group uddapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pm.c b/drivers/gpu/arm/mali400/mali/common/mali_pm.c
new file mode 100755 (executable)
index 0000000..2bd0c38
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_pm.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_scheduler.h"
+#include "mali_kernel_utilization.h"
+#include "mali_group.h"
+#include "mali_pm_domain.h"
+#include "mali_pmu.h"
+
+static mali_bool mali_power_on = MALI_FALSE;
+
+_mali_osk_errcode_t mali_pm_initialize(void)
+{
+       _mali_osk_pm_dev_enable();
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_pm_terminate(void)
+{
+       mali_pm_domain_terminate();
+       _mali_osk_pm_dev_disable();
+}
+
+/* Reset GPU after power up */
+static void mali_pm_reset_gpu(void)
+{
+       /* Reset all L2 caches */
+       mali_l2_cache_reset_all();
+
+       /* Reset all groups */
+       mali_scheduler_reset_all_groups();
+}
+
+void mali_pm_os_suspend(void)
+{
+       MALI_DEBUG_PRINT(3, ("Mali PM: OS suspend\n"));
+       mali_gp_scheduler_suspend();
+       mali_pp_scheduler_suspend();
+       mali_utilization_suspend();
+       mali_group_power_off(MALI_TRUE);
+       mali_power_on = MALI_FALSE;
+}
+
+void mali_pm_os_resume(void)
+{
+       struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+       mali_bool do_reset = MALI_FALSE;
+
+       MALI_DEBUG_PRINT(3, ("Mali PM: OS resume\n"));
+
+       if (MALI_TRUE != mali_power_on) {
+               do_reset = MALI_TRUE;
+       }
+
+       if (NULL != pmu) {
+               mali_pmu_reset(pmu);
+       }
+
+       mali_power_on = MALI_TRUE;
+       _mali_osk_write_mem_barrier();
+
+       if (do_reset) {
+               mali_pm_reset_gpu();
+               mali_group_power_on();
+       }
+
+       mali_gp_scheduler_resume();
+       mali_pp_scheduler_resume();
+}
+
+void mali_pm_runtime_suspend(void)
+{
+       MALI_DEBUG_PRINT(2, ("Mali PM: Runtime suspend\n"));
+       mali_group_power_off(MALI_TRUE);
+       mali_power_on = MALI_FALSE;
+}
+
+void mali_pm_runtime_resume(void)
+{
+       struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+       mali_bool do_reset = MALI_FALSE;
+
+       MALI_DEBUG_PRINT(2, ("Mali PM: Runtime resume\n"));
+
+       if (MALI_TRUE != mali_power_on) {
+               do_reset = MALI_TRUE;
+       }
+
+       if (NULL != pmu) {
+               mali_pmu_reset(pmu);
+       }
+
+       mali_power_on = MALI_TRUE;
+       _mali_osk_write_mem_barrier();
+
+       if (do_reset) {
+               mali_pm_reset_gpu();
+               mali_group_power_on();
+       }
+}
+
+void mali_pm_set_power_is_on(void)
+{
+       mali_power_on = MALI_TRUE;
+}
+
+mali_bool mali_pm_is_power_on(void)
+{
+       return mali_power_on;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pm.h b/drivers/gpu/arm/mali400/mali/common/mali_pm.h
new file mode 100755 (executable)
index 0000000..2c1063a
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PM_H__
+#define __MALI_PM_H__
+
+#include "mali_osk.h"
+
+_mali_osk_errcode_t mali_pm_initialize(void);
+void mali_pm_terminate(void);
+
+/* Callback functions registered for the runtime PMM system */
+void mali_pm_os_suspend(void);
+void mali_pm_os_resume(void);
+void mali_pm_runtime_suspend(void);
+void mali_pm_runtime_resume(void);
+
+void mali_pm_set_power_is_on(void);
+mali_bool mali_pm_is_power_on(void);
+
+#endif /* __MALI_PM_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pm_domain.c b/drivers/gpu/arm/mali400/mali/common/mali_pm_domain.c
new file mode 100755 (executable)
index 0000000..486e893
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_pm_domain.h"
+#include "mali_pmu.h"
+#include "mali_group.h"
+
+static struct mali_pm_domain *mali_pm_domains[MALI_MAX_NUMBER_OF_DOMAINS] = { NULL, };
+
+static void mali_pm_domain_lock(struct mali_pm_domain *domain)
+{
+       _mali_osk_spinlock_irq_lock(domain->lock);
+}
+
+static void mali_pm_domain_unlock(struct mali_pm_domain *domain)
+{
+       _mali_osk_spinlock_irq_unlock(domain->lock);
+}
+
+MALI_STATIC_INLINE void mali_pm_domain_state_set(struct mali_pm_domain *domain, mali_pm_domain_state state)
+{
+       domain->state = state;
+}
+
+struct mali_pm_domain *mali_pm_domain_create(u32 pmu_mask)
+{
+       struct mali_pm_domain* domain = NULL;
+       u32 domain_id = 0;
+
+       domain = mali_pm_domain_get_from_mask(pmu_mask);
+       if (NULL != domain) return domain;
+
+       MALI_DEBUG_PRINT(2, ("Mali PM domain: Creating Mali PM domain (mask=0x%08X)\n", pmu_mask));
+
+       domain = (struct mali_pm_domain *)_mali_osk_malloc(sizeof(struct mali_pm_domain));
+       if (NULL != domain) {
+               domain->lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_PM_DOMAIN);
+               if (NULL == domain->lock) {
+                       _mali_osk_free(domain);
+                       return NULL;
+               }
+
+               domain->state = MALI_PM_DOMAIN_ON;
+               domain->pmu_mask = pmu_mask;
+               domain->use_count = 0;
+               domain->group_list = NULL;
+               domain->group_count = 0;
+               domain->l2 = NULL;
+
+               domain_id = _mali_osk_fls(pmu_mask) - 1;
+               /* Verify the domain_id */
+               MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > domain_id);
+               /* Verify that pmu_mask only one bit is set */
+               MALI_DEBUG_ASSERT((1 << domain_id) == pmu_mask);
+               mali_pm_domains[domain_id] = domain;
+
+               return domain;
+       } else {
+               MALI_DEBUG_PRINT_ERROR(("Unable to create PM domain\n"));
+       }
+
+       return NULL;
+}
+
+void mali_pm_domain_delete(struct mali_pm_domain *domain)
+{
+       if (NULL == domain) {
+               return;
+       }
+       _mali_osk_spinlock_irq_term(domain->lock);
+
+       _mali_osk_free(domain);
+}
+
+void mali_pm_domain_terminate(void)
+{
+       int i;
+
+       /* Delete all domains */
+       for (i = 0; i < MALI_MAX_NUMBER_OF_DOMAINS; i++) {
+               mali_pm_domain_delete(mali_pm_domains[i]);
+       }
+}
+
+void mali_pm_domain_add_group(u32 mask, struct mali_group *group)
+{
+       struct mali_pm_domain *domain = mali_pm_domain_get_from_mask(mask);
+       struct mali_group *next;
+
+       if (NULL == domain) return;
+
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       ++domain->group_count;
+       next = domain->group_list;
+
+       domain->group_list = group;
+
+       group->pm_domain_list = next;
+
+       mali_group_set_pm_domain(group, domain);
+
+       /* Get pm domain ref after mali_group_set_pm_domain */
+       mali_group_get_pm_domain_ref(group);
+}
+
+void mali_pm_domain_add_l2(u32 mask, struct mali_l2_cache_core *l2)
+{
+       struct mali_pm_domain *domain = mali_pm_domain_get_from_mask(mask);
+
+       if (NULL == domain) return;
+
+       MALI_DEBUG_ASSERT(NULL == domain->l2);
+       MALI_DEBUG_ASSERT(NULL != l2);
+
+       domain->l2 = l2;
+
+       mali_l2_cache_set_pm_domain(l2, domain);
+}
+
+struct mali_pm_domain *mali_pm_domain_get_from_mask(u32 mask)
+{
+       u32 id = 0;
+
+       if (0 == mask) return NULL;
+
+       id = _mali_osk_fls(mask)-1;
+
+       MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
+       /* Verify that pmu_mask only one bit is set */
+       MALI_DEBUG_ASSERT((1 << id) == mask);
+
+       return mali_pm_domains[id];
+}
+
+struct mali_pm_domain *mali_pm_domain_get_from_index(u32 id)
+{
+       MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > id);
+
+       return mali_pm_domains[id];
+}
+
+void mali_pm_domain_ref_get(struct mali_pm_domain *domain)
+{
+       if (NULL == domain) return;
+
+       mali_pm_domain_lock(domain);
+       ++domain->use_count;
+
+       if (MALI_PM_DOMAIN_ON != domain->state) {
+               /* Power on */
+               struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+
+               MALI_DEBUG_PRINT(3, ("PM Domain: Powering on 0x%08x\n", domain->pmu_mask));
+
+               if (NULL != pmu) {
+                       _mali_osk_errcode_t err;
+
+                       err = mali_pmu_power_up(pmu, domain->pmu_mask);
+
+                       if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) {
+                               MALI_PRINT_ERROR(("PM Domain: Failed to power up PM domain 0x%08x\n",
+                                                 domain->pmu_mask));
+                       }
+               }
+               mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_ON);
+       } else {
+               MALI_DEBUG_ASSERT(MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(domain));
+       }
+
+       mali_pm_domain_unlock(domain);
+}
+
+void mali_pm_domain_ref_put(struct mali_pm_domain *domain)
+{
+       if (NULL == domain) return;
+
+       mali_pm_domain_lock(domain);
+       --domain->use_count;
+
+       if (0 == domain->use_count && MALI_PM_DOMAIN_OFF != domain->state) {
+               /* Power off */
+               struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+
+               MALI_DEBUG_PRINT(3, ("PM Domain: Powering off 0x%08x\n", domain->pmu_mask));
+
+               mali_pm_domain_state_set(domain, MALI_PM_DOMAIN_OFF);
+
+               if (NULL != pmu) {
+                       _mali_osk_errcode_t err;
+
+                       err = mali_pmu_power_down(pmu, domain->pmu_mask);
+
+                       if (_MALI_OSK_ERR_OK != err && _MALI_OSK_ERR_BUSY != err) {
+                               MALI_PRINT_ERROR(("PM Domain: Failed to power down PM domain 0x%08x\n",
+                                                 domain->pmu_mask));
+                       }
+               }
+       }
+       mali_pm_domain_unlock(domain);
+}
+
+mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain)
+{
+       mali_bool is_powered = MALI_TRUE;
+
+       /* Take a reference without powering on */
+       if (NULL != domain) {
+               mali_pm_domain_lock(domain);
+               ++domain->use_count;
+
+               if (MALI_PM_DOMAIN_ON != domain->state) {
+                       is_powered = MALI_FALSE;
+               }
+               mali_pm_domain_unlock(domain);
+       }
+
+       if(!_mali_osk_pm_dev_ref_add_no_power_on()) {
+               is_powered = MALI_FALSE;
+       }
+
+       return is_powered;
+}
+
+void mali_pm_domain_unlock_state(struct mali_pm_domain *domain)
+{
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+
+       if (NULL != domain) {
+               mali_pm_domain_ref_put(domain);
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pm_domain.h b/drivers/gpu/arm/mali400/mali/common/mali_pm_domain.h
new file mode 100755 (executable)
index 0000000..c5776dd
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PM_DOMAIN_H__
+#define __MALI_PM_DOMAIN_H__
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+#include "mali_l2_cache.h"
+#include "mali_group.h"
+#include "mali_pmu.h"
+
+typedef enum {
+       MALI_PM_DOMAIN_ON,
+       MALI_PM_DOMAIN_OFF,
+} mali_pm_domain_state;
+
+struct mali_pm_domain {
+       mali_pm_domain_state state;
+       _mali_osk_spinlock_irq_t *lock;
+
+       s32 use_count;
+
+       u32 pmu_mask;
+
+       int group_count;
+       struct mali_group *group_list;
+
+       struct mali_l2_cache_core *l2;
+};
+
+struct mali_pm_domain *mali_pm_domain_create(u32 pmu_mask);
+
+void mali_pm_domain_add_group(u32 mask, struct mali_group *group);
+
+void mali_pm_domain_add_l2(u32 mask, struct mali_l2_cache_core *l2);
+void mali_pm_domain_delete(struct mali_pm_domain *domain);
+
+void mali_pm_domain_terminate(void);
+
+/** Get PM domain from domain ID
+ */
+struct mali_pm_domain *mali_pm_domain_get_from_mask(u32 mask);
+struct mali_pm_domain *mali_pm_domain_get_from_index(u32 id);
+
+/* Ref counting */
+void mali_pm_domain_ref_get(struct mali_pm_domain *domain);
+void mali_pm_domain_ref_put(struct mali_pm_domain *domain);
+
+MALI_STATIC_INLINE struct mali_l2_cache_core *mali_pm_domain_l2_get(struct mali_pm_domain *domain)
+{
+       return domain->l2;
+}
+
+MALI_STATIC_INLINE mali_pm_domain_state mali_pm_domain_state_get(struct mali_pm_domain *domain)
+{
+       return domain->state;
+}
+
+mali_bool mali_pm_domain_lock_state(struct mali_pm_domain *domain);
+void mali_pm_domain_unlock_state(struct mali_pm_domain *domain);
+
+#define MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) for ((group) = (domain)->group_list;\
+               NULL != (group); (group) = (group)->pm_domain_list)
+
+#endif /* __MALI_PM_DOMAIN_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pmu.c b/drivers/gpu/arm/mali400/mali/common/mali_pmu.c
new file mode 100755 (executable)
index 0000000..3f99465
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_pmu.c
+ * Mali driver functions for Mali 400 PMU hardware
+ */
+#include "mali_hw_core.h"
+#include "mali_pmu.h"
+#include "mali_pp.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_pm.h"
+#include "mali_osk_mali.h"
+
+u16 mali_pmu_global_domain_config[MALI_MAX_NUMBER_OF_DOMAINS]= {0};
+
+static u32 mali_pmu_detect_mask(void);
+
+/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask
+ */
+struct mali_pmu_core {
+       struct mali_hw_core hw_core;
+       _mali_osk_spinlock_t *lock;
+       u32 registered_cores_mask;
+       u32 active_cores_mask;
+       u32 switch_delay;
+};
+
+static struct mali_pmu_core *mali_global_pmu_core = NULL;
+
+/** @brief Register layout for hardware PMU
+ */
+typedef enum {
+       PMU_REG_ADDR_MGMT_POWER_UP                  = 0x00,     /*< Power up register */
+       PMU_REG_ADDR_MGMT_POWER_DOWN                = 0x04,     /*< Power down register */
+       PMU_REG_ADDR_MGMT_STATUS                    = 0x08,     /*< Core sleep status register */
+       PMU_REG_ADDR_MGMT_INT_MASK                  = 0x0C,     /*< Interrupt mask register */
+       PMU_REG_ADDR_MGMT_INT_RAWSTAT               = 0x10,     /*< Interrupt raw status register */
+       PMU_REG_ADDR_MGMT_INT_CLEAR                 = 0x18,     /*< Interrupt clear register */
+       PMU_REG_ADDR_MGMT_SW_DELAY                  = 0x1C,     /*< Switch delay register */
+       PMU_REGISTER_ADDRESS_SPACE_SIZE             = 0x28,     /*< Size of register space */
+} pmu_reg_addr_mgmt_addr;
+
+#define PMU_REG_VAL_IRQ 1
+
+struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource)
+{
+       struct mali_pmu_core* pmu;
+
+       MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core);
+       MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n"));
+
+       pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core));
+       if (NULL != pmu) {
+               pmu->lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_PMU);
+               if (NULL != pmu->lock) {
+                       pmu->registered_cores_mask = mali_pmu_detect_mask();
+                       pmu->active_cores_mask = pmu->registered_cores_mask;
+
+                       if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE)) {
+                               _mali_osk_errcode_t err;
+                               struct _mali_osk_device_data data = { 0, };
+
+                               err = _mali_osk_device_data_get(&data);
+                               if (_MALI_OSK_ERR_OK == err) {
+                                       pmu->switch_delay = data.pmu_switch_delay;
+                                       mali_global_pmu_core = pmu;
+                                       return pmu;
+                               }
+                               mali_hw_core_delete(&pmu->hw_core);
+                       }
+                       _mali_osk_spinlock_term(pmu->lock);
+               }
+               _mali_osk_free(pmu);
+       }
+
+       return NULL;
+}
+
+void mali_pmu_delete(struct mali_pmu_core *pmu)
+{
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(pmu == mali_global_pmu_core);
+       MALI_DEBUG_PRINT(2, ("Mali PMU: Deleting Mali PMU core\n"));
+
+       _mali_osk_spinlock_term(pmu->lock);
+       mali_hw_core_delete(&pmu->hw_core);
+       _mali_osk_free(pmu);
+       mali_global_pmu_core = NULL;
+}
+
+static void mali_pmu_lock(struct mali_pmu_core *pmu)
+{
+       _mali_osk_spinlock_lock(pmu->lock);
+}
+static void mali_pmu_unlock(struct mali_pmu_core *pmu)
+{
+       _mali_osk_spinlock_unlock(pmu->lock);
+}
+
+static _mali_osk_errcode_t mali_pmu_wait_for_command_finish(struct mali_pmu_core *pmu)
+{
+       u32 rawstat;
+       u32 timeout = MALI_REG_POLL_COUNT_SLOW;
+
+       MALI_DEBUG_ASSERT(pmu);
+
+       /* Wait for the command to complete */
+       do {
+               rawstat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT);
+               --timeout;
+       } while (0 == (rawstat & PMU_REG_VAL_IRQ) && 0 < timeout);
+
+       MALI_DEBUG_ASSERT(0 < timeout);
+       if (0 == timeout) {
+               return _MALI_OSK_ERR_TIMEOUT;
+       }
+
+       mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_CLEAR, PMU_REG_VAL_IRQ);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_pmu_power_up_internal(struct mali_pmu_core *pmu, const u32 mask)
+{
+       u32 stat;
+       _mali_osk_errcode_t err;
+#if !defined(CONFIG_MALI_PMU_PARALLEL_POWER_UP)
+       u32 current_domain;
+#endif
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(0 == (mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT)
+                               & PMU_REG_VAL_IRQ));
+
+       stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+       stat &= pmu->registered_cores_mask;
+       if (0 == mask || 0 == (stat & mask)) return _MALI_OSK_ERR_OK;
+
+#if defined(CONFIG_MALI_PMU_PARALLEL_POWER_UP)
+       mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_UP, mask);
+
+       err = mali_pmu_wait_for_command_finish(pmu);
+       if (_MALI_OSK_ERR_OK != err) {
+               return err;
+       }
+#else
+       for (current_domain = 1; current_domain <= pmu->registered_cores_mask; current_domain <<= 1) {
+               if (current_domain & mask & stat) {
+                       mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_UP, current_domain);
+
+                       err = mali_pmu_wait_for_command_finish(pmu);
+                       if (_MALI_OSK_ERR_OK != err) {
+                               return err;
+                       }
+               }
+       }
+#endif
+
+#if defined(DEBUG)
+       /* Get power status of cores */
+       stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+       stat &= pmu->registered_cores_mask;
+
+       MALI_DEBUG_ASSERT(0 == (stat & mask));
+       MALI_DEBUG_ASSERT(0 == (stat & pmu->active_cores_mask));
+#endif /* defined(DEBUG) */
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_pmu_power_down_internal(struct mali_pmu_core *pmu, const u32 mask)
+{
+       u32 stat;
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(0 == (mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_RAWSTAT)
+                               & PMU_REG_VAL_IRQ));
+
+       stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+       stat &= pmu->registered_cores_mask;
+
+       if (0 == mask || 0 == ((~stat) & mask)) return _MALI_OSK_ERR_OK;
+
+       mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_DOWN, mask);
+
+       /* Do not wait for interrupt on Mali-300/400 if all domains are powered off
+        * by our power down command, because the HW will simply not generate an
+        * interrupt in this case.*/
+       if (mali_is_mali450() || pmu->registered_cores_mask != (mask | stat)) {
+               err = mali_pmu_wait_for_command_finish(pmu);
+               if (_MALI_OSK_ERR_OK != err) {
+                       return err;
+               }
+       } else {
+               mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_CLEAR, PMU_REG_VAL_IRQ);
+       }
+#if defined(DEBUG)
+       /* Get power status of cores */
+       stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+       stat &= pmu->registered_cores_mask;
+
+       MALI_DEBUG_ASSERT(mask == (stat & mask));
+#endif
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu)
+{
+       _mali_osk_errcode_t err;
+       u32 cores_off_mask, cores_on_mask, stat;
+
+       mali_pmu_lock(pmu);
+
+       /* Setup the desired defaults */
+       mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0);
+       mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay);
+
+       /* Get power status of cores */
+       stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+
+       cores_off_mask = pmu->registered_cores_mask & ~(stat | pmu->active_cores_mask);
+       cores_on_mask  = pmu->registered_cores_mask &  (stat & pmu->active_cores_mask);
+
+       if (0 != cores_off_mask) {
+               err = mali_pmu_power_down_internal(pmu, cores_off_mask);
+               if (_MALI_OSK_ERR_OK != err) return err;
+       }
+
+       if (0 != cores_on_mask) {
+               err = mali_pmu_power_up_internal(pmu, cores_on_mask);
+               if (_MALI_OSK_ERR_OK != err) return err;
+       }
+
+#if defined(DEBUG)
+       {
+               stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+               stat &= pmu->registered_cores_mask;
+
+               MALI_DEBUG_ASSERT(stat == (pmu->registered_cores_mask & ~pmu->active_cores_mask));
+       }
+#endif /* defined(DEBUG) */
+
+       mali_pmu_unlock(pmu);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pmu_power_down(struct mali_pmu_core *pmu, u32 mask)
+{
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0 );
+
+       /* Make sure we have a valid power domain mask */
+       if (mask > pmu->registered_cores_mask) {
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+
+       mali_pmu_lock(pmu);
+
+       MALI_DEBUG_PRINT(4, ("Mali PMU: Power down (0x%08X)\n", mask));
+
+       pmu->active_cores_mask &= ~mask;
+
+       _mali_osk_pm_dev_ref_add_no_power_on();
+       if (!mali_pm_is_power_on()) {
+               /* Don't touch hardware if all of Mali is powered off. */
+               _mali_osk_pm_dev_ref_dec_no_power_on();
+               mali_pmu_unlock(pmu);
+
+               MALI_DEBUG_PRINT(4, ("Mali PMU: Skipping power down (0x%08X) since Mali is off\n", mask));
+
+               return _MALI_OSK_ERR_BUSY;
+       }
+
+       err = mali_pmu_power_down_internal(pmu, mask);
+
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+       mali_pmu_unlock(pmu);
+
+       return err;
+}
+
+_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask)
+{
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0 );
+
+       /* Make sure we have a valid power domain mask */
+       if (mask & ~pmu->registered_cores_mask) {
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+
+       mali_pmu_lock(pmu);
+
+       MALI_DEBUG_PRINT(4, ("Mali PMU: Power up (0x%08X)\n", mask));
+
+       pmu->active_cores_mask |= mask;
+
+       _mali_osk_pm_dev_ref_add_no_power_on();
+       if (!mali_pm_is_power_on()) {
+               /* Don't touch hardware if all of Mali is powered off. */
+               _mali_osk_pm_dev_ref_dec_no_power_on();
+               mali_pmu_unlock(pmu);
+
+               MALI_DEBUG_PRINT(4, ("Mali PMU: Skipping power up (0x%08X) since Mali is off\n", mask));
+
+               return _MALI_OSK_ERR_BUSY;
+       }
+
+       err = mali_pmu_power_up_internal(pmu, mask);
+
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+       mali_pmu_unlock(pmu);
+
+       return err;
+}
+
+_mali_osk_errcode_t mali_pmu_power_down_all(struct mali_pmu_core *pmu)
+{
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0);
+
+       mali_pmu_lock(pmu);
+
+       /* Setup the desired defaults in case we were called before mali_pmu_reset() */
+       mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0);
+       mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay);
+
+       err = mali_pmu_power_down_internal(pmu, pmu->registered_cores_mask);
+
+       mali_pmu_unlock(pmu);
+
+       return err;
+}
+
+_mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu)
+{
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       MALI_DEBUG_ASSERT(pmu->registered_cores_mask != 0);
+
+       mali_pmu_lock(pmu);
+
+       /* Setup the desired defaults in case we were called before mali_pmu_reset() */
+       mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0);
+       mali_hw_core_register_write_relaxed(&pmu->hw_core, PMU_REG_ADDR_MGMT_SW_DELAY, pmu->switch_delay);
+
+       err = mali_pmu_power_up_internal(pmu, pmu->active_cores_mask);
+
+       mali_pmu_unlock(pmu);
+       return err;
+}
+
+struct mali_pmu_core *mali_pmu_get_global_pmu_core(void)
+{
+       return mali_global_pmu_core;
+}
+
+static u32 mali_pmu_detect_mask(void)
+{
+       int dynamic_config_pp = 0;
+       int dynamic_config_l2 = 0;
+       int i = 0;
+       u32 mask = 0;
+
+       /* Check if PM domain compatible with actually pp core and l2 cache and collection info about domain */
+       mask = mali_pmu_get_domain_mask(MALI_GP_DOMAIN_INDEX);
+
+       for (i = MALI_PP0_DOMAIN_INDEX; i <= MALI_PP7_DOMAIN_INDEX; i++) {
+               mask |= mali_pmu_get_domain_mask(i);
+
+               if (0x0 != mali_pmu_get_domain_mask(i)) {
+                       dynamic_config_pp++;
+               }
+       }
+
+       for (i = MALI_L20_DOMAIN_INDEX; i <= MALI_L22_DOMAIN_INDEX; i++) {
+               mask |= mali_pmu_get_domain_mask(i);
+
+               if (0x0 != mali_pmu_get_domain_mask(i)) {
+                       dynamic_config_l2++;
+               }
+       }
+
+       MALI_DEBUG_PRINT(2, ("Mali PMU: mask 0x%x, pp_core %d, l2_core %d \n", mask, dynamic_config_pp, dynamic_config_l2));
+
+       return mask;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pmu.h b/drivers/gpu/arm/mali400/mali/common/mali_pmu.h
new file mode 100755 (executable)
index 0000000..cdbd674
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_platform.h
+ * Platform specific Mali driver functions
+ */
+
+#ifndef __MALI_PMU_H__
+#define __MALI_PMU_H__
+
+#include "mali_osk.h"
+
+#define MALI_GP_DOMAIN_INDEX   0
+#define MALI_PP0_DOMAIN_INDEX  1
+#define MALI_PP1_DOMAIN_INDEX  2
+#define MALI_PP2_DOMAIN_INDEX  3
+#define MALI_PP3_DOMAIN_INDEX  4
+#define MALI_PP4_DOMAIN_INDEX  5
+#define MALI_PP5_DOMAIN_INDEX  6
+#define MALI_PP6_DOMAIN_INDEX  7
+#define MALI_PP7_DOMAIN_INDEX  8
+#define MALI_L20_DOMAIN_INDEX  9
+#define MALI_L21_DOMAIN_INDEX  10
+#define MALI_L22_DOMAIN_INDEX  11
+
+#define MALI_MAX_NUMBER_OF_DOMAINS     12
+
+/* Record the domain config from the customer or default config */
+extern u16 mali_pmu_global_domain_config[];
+
+static inline u16 mali_pmu_get_domain_mask(u32 index)
+{
+       MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > index);
+
+       return mali_pmu_global_domain_config[index];
+}
+
+static inline void mali_pmu_set_domain_mask(u32 index, u16 value)
+{
+       MALI_DEBUG_ASSERT(MALI_MAX_NUMBER_OF_DOMAINS > index);
+
+       mali_pmu_global_domain_config[index] = value;
+}
+
+static inline void mali_pmu_copy_domain_mask(void *src, u32 len)
+{
+       _mali_osk_memcpy(mali_pmu_global_domain_config, src, len);
+}
+
+struct mali_pmu_core;
+
+/** @brief Initialisation of MALI PMU
+ *
+ * This is called from entry point of the driver in order to create and intialize the PMU resource
+ *
+ * @param resource it will be a pointer to a PMU resource
+ * @param number_of_pp_cores Number of found PP resources in configuration
+ * @param number_of_l2_caches Number of found L2 cache resources in configuration
+ * @return The created PMU object, or NULL in case of failure.
+ */
+struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource);
+
+/** @brief It deallocates the PMU resource
+ *
+ * This is called on the exit of the driver to terminate the PMU resource
+ *
+ * @param pmu Pointer to PMU core object to delete
+ */
+void mali_pmu_delete(struct mali_pmu_core *pmu);
+
+/** @brief Reset PMU core
+ *
+ * @param pmu Pointer to PMU core object to reset
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu);
+
+/** @brief MALI GPU power down using MALI in-built PMU
+ *
+ * Called to power down the specified cores. The mask will be saved so that \a
+ * mali_pmu_power_up_all will bring the PMU back to the previous state set with
+ * this function or \a mali_pmu_power_up.
+ *
+ * @param pmu Pointer to PMU core object to power down
+ * @param mask Mask specifying which power domains to power down
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmu_power_down(struct mali_pmu_core *pmu, u32 mask);
+
+/** @brief MALI GPU power up using MALI in-built PMU
+ *
+ * Called to power up the specified cores. The mask will be saved so that \a
+ * mali_pmu_power_up_all will bring the PMU back to the previous state set with
+ * this function or \a mali_pmu_power_down.
+ *
+ * @param pmu Pointer to PMU core object to power up
+ * @param mask Mask specifying which power domains to power up
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask);
+
+/** @brief MALI GPU power down using MALI in-built PMU
+ *
+ * called to power down all cores
+ *
+ * @param pmu Pointer to PMU core object to power down
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmu_power_down_all(struct mali_pmu_core *pmu);
+
+/** @brief MALI GPU power up using MALI in-built PMU
+ *
+ * called to power up all cores
+ *
+ * @param pmu Pointer to PMU core object to power up
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmu_power_up_all(struct mali_pmu_core *pmu);
+
+/** @brief Retrieves the Mali PMU core object (if any)
+ *
+ * @return The Mali PMU object, or NULL if no PMU exists.
+ */
+struct mali_pmu_core *mali_pmu_get_global_pmu_core(void);
+
+#endif /* __MALI_PMU_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp.c b/drivers/gpu/arm/mali400/mali/common/mali_pp.c
new file mode 100755 (executable)
index 0000000..8fd9115
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_pp_job.h"
+#include "mali_pp.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "regs/mali_200_regs.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_dma.h"
+#if defined(CONFIG_MALI400_PROFILING)
+#include "mali_osk_profiling.h"
+#endif
+
+/* Number of frame registers on Mali-200 */
+#define MALI_PP_MALI200_NUM_FRAME_REGISTERS ((0x04C/4)+1)
+/* Number of frame registers on Mali-300 and later */
+#define MALI_PP_MALI400_NUM_FRAME_REGISTERS ((0x058/4)+1)
+
+static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES] = { NULL };
+static u32 mali_global_num_pp_cores = 0;
+
+/* Interrupt handlers */
+static void mali_pp_irq_probe_trigger(void *data);
+static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data);
+
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id)
+{
+       struct mali_pp_core* core = NULL;
+
+       MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base));
+
+       if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES) {
+               MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n"));
+               return NULL;
+       }
+
+       core = _mali_osk_malloc(sizeof(struct mali_pp_core));
+       if (NULL != core) {
+               core->core_id = mali_global_num_pp_cores;
+               core->bcast_id = bcast_id;
+
+               if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK)) {
+                       _mali_osk_errcode_t ret;
+
+                       if (!is_virtual) {
+                               ret = mali_pp_reset(core);
+                       } else {
+                               ret = _MALI_OSK_ERR_OK;
+                       }
+
+                       if (_MALI_OSK_ERR_OK == ret) {
+                               ret = mali_group_add_pp_core(group, core);
+                               if (_MALI_OSK_ERR_OK == ret) {
+                                       /* Setup IRQ handlers (which will do IRQ probing if needed) */
+                                       MALI_DEBUG_ASSERT(!is_virtual || -1 != resource->irq);
+
+                                       core->irq = _mali_osk_irq_init(resource->irq,
+                                                                      mali_group_upper_half_pp,
+                                                                      group,
+                                                                      mali_pp_irq_probe_trigger,
+                                                                      mali_pp_irq_probe_ack,
+                                                                      core,
+                                                                      resource->description);
+                                       if (NULL != core->irq) {
+                                               mali_global_pp_cores[mali_global_num_pp_cores] = core;
+                                               mali_global_num_pp_cores++;
+
+                                               return core;
+                                       } else {
+                                               MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
+                                       }
+                                       mali_group_remove_pp_core(group);
+                               } else {
+                                       MALI_PRINT_ERROR(("Mali PP: Failed to add core %s to group\n", core->hw_core.description));
+                               }
+                       }
+                       mali_hw_core_delete(&core->hw_core);
+               }
+
+               _mali_osk_free(core);
+       } else {
+               MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n"));
+       }
+
+       return NULL;
+}
+
+void mali_pp_delete(struct mali_pp_core *core)
+{
+       u32 i;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       _mali_osk_irq_term(core->irq);
+       mali_hw_core_delete(&core->hw_core);
+
+       /* Remove core from global list */
+       for (i = 0; i < mali_global_num_pp_cores; i++) {
+               if (mali_global_pp_cores[i] == core) {
+                       mali_global_pp_cores[i] = NULL;
+                       mali_global_num_pp_cores--;
+
+                       if (i != mali_global_num_pp_cores) {
+                               /* We removed a PP core from the middle of the array -- move the last
+                                * PP core to the current position to close the gap */
+                               mali_global_pp_cores[i] = mali_global_pp_cores[mali_global_num_pp_cores];
+                               mali_global_pp_cores[mali_global_num_pp_cores] = NULL;
+                       }
+
+                       break;
+               }
+       }
+
+       _mali_osk_free(core);
+}
+
+void mali_pp_stop_bus(struct mali_pp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+       /* Will only send the stop bus command, and not wait for it to complete */
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
+}
+
+_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core)
+{
+       int i;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       /* Send the stop bus command. */
+       mali_pp_stop_bus(core);
+
+       /* Wait for bus to be stopped */
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
+               if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED)
+                       break;
+       }
+
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+/* Frame register reset values.
+ * Taken from the Mali400 TRM, 3.6. Pixel processor control register summary */
+static const u32 mali_frame_registers_reset_values[_MALI_PP_MAX_FRAME_REGISTERS] = {
+       0x0, /* Renderer List Address Register */
+       0x0, /* Renderer State Word Base Address Register */
+       0x0, /* Renderer Vertex Base Register */
+       0x2, /* Feature Enable Register */
+       0x0, /* Z Clear Value Register */
+       0x0, /* Stencil Clear Value Register */
+       0x0, /* ABGR Clear Value 0 Register */
+       0x0, /* ABGR Clear Value 1 Register */
+       0x0, /* ABGR Clear Value 2 Register */
+       0x0, /* ABGR Clear Value 3 Register */
+       0x0, /* Bounding Box Left Right Register */
+       0x0, /* Bounding Box Bottom Register */
+       0x0, /* FS Stack Address Register */
+       0x0, /* FS Stack Size and Initial Value Register */
+       0x0, /* Reserved */
+       0x0, /* Reserved */
+       0x0, /* Origin Offset X Register */
+       0x0, /* Origin Offset Y Register */
+       0x75, /* Subpixel Specifier Register */
+       0x0, /* Tiebreak mode Register */
+       0x0, /* Polygon List Format Register */
+       0x0, /* Scaling Register */
+       0x0 /* Tilebuffer configuration Register */
+};
+
+/* WBx register reset values */
+static const u32 mali_wb_registers_reset_values[_MALI_PP_MAX_WB_REGISTERS] = {
+       0x0, /* WBx Source Select Register */
+       0x0, /* WBx Target Address Register */
+       0x0, /* WBx Target Pixel Format Register */
+       0x0, /* WBx Target AA Format Register */
+       0x0, /* WBx Target Layout */
+       0x0, /* WBx Target Scanline Length */
+       0x0, /* WBx Target Flags Register */
+       0x0, /* WBx MRT Enable Register */
+       0x0, /* WBx MRT Offset Register */
+       0x0, /* WBx Global Test Enable Register */
+       0x0, /* WBx Global Test Reference Value Register */
+       0x0  /* WBx Global Test Compare Function Register */
+};
+
+/* Performance Counter 0 Enable Register reset value */
+static const u32 mali_perf_cnt_enable_reset_value = 0;
+
+_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core)
+{
+       /* Bus must be stopped before calling this function */
+       const u32 reset_invalid_value = 0xC0FFE000;
+       const u32 reset_check_value = 0xC01A0000;
+       int i;
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+       MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description));
+
+       /* Set register to a bogus value. The register will be used to detect when reset is complete */
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value);
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
+
+       /* Force core to reset */
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);
+
+       /* Wait for reset to be complete */
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
+               mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value);
+               if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW)) {
+                       break;
+               }
+       }
+
+       if (MALI_REG_POLL_COUNT_FAST == i) {
+               MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n"));
+       }
+
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */
+       /* Re-enable interrupts */
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_pp_reset_async(struct mali_pp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description));
+
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_MASK_ALL);
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);
+}
+
+_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core)
+{
+       int i;
+       u32 rawstat = 0;
+
+       for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++) {
+               if (!(mali_pp_read_status(core) & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)) {
+                       rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT);
+                       if (rawstat == MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) {
+                               break;
+                       }
+               }
+       }
+
+       if (i == MALI_REG_POLL_COUNT_FAST) {
+               MALI_PRINT_ERROR(("Mali PP: Failed to reset core %s, rawstat: 0x%08x\n",
+                                 core->hw_core.description, rawstat));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Re-enable interrupts */
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
+{
+       mali_pp_reset_async(core);
+       return mali_pp_reset_wait(core);
+}
+
+void mali_pp_job_dma_cmd_prepare(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job,
+                                 mali_bool restart_virtual, mali_dma_cmd_buf *buf)
+{
+       u32 relative_address;
+       u32 start_index;
+       u32 nr_of_regs;
+       u32 *frame_registers = mali_pp_job_get_frame_registers(job);
+       u32 *wb0_registers = mali_pp_job_get_wb0_registers(job);
+       u32 *wb1_registers = mali_pp_job_get_wb1_registers(job);
+       u32 *wb2_registers = mali_pp_job_get_wb2_registers(job);
+       u32 counter_src0 = mali_pp_job_get_perf_counter_src0(job, sub_job);
+       u32 counter_src1 = mali_pp_job_get_perf_counter_src1(job, sub_job);
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       /* Write frame registers */
+
+       /*
+        * There are two frame registers which are different for each sub job:
+        * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME)
+        * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK)
+        */
+       mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]);
+
+       /* For virtual jobs, the stack address shouldn't be broadcast but written individually */
+       if (!mali_pp_job_is_virtual(job) || restart_virtual) {
+               mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]);
+       }
+
+       /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */
+       relative_address = MALI200_REG_ADDR_RSW;
+       start_index = MALI200_REG_ADDR_RSW / sizeof(u32);
+       nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32);
+
+       mali_dma_write_array_conditional(buf, &core->hw_core,
+                                        relative_address, &frame_registers[start_index],
+                                        nr_of_regs, &mali_frame_registers_reset_values[start_index]);
+
+       /* MALI200_REG_ADDR_STACK_SIZE */
+       relative_address = MALI200_REG_ADDR_STACK_SIZE;
+       start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32);
+
+       mali_dma_write_conditional(buf, &core->hw_core,
+                                  relative_address, frame_registers[start_index],
+                                  mali_frame_registers_reset_values[start_index]);
+
+       /* Skip 2 reserved registers */
+
+       /* Write remaining registers */
+       relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X;
+       start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
+       nr_of_regs = MALI_PP_MALI400_NUM_FRAME_REGISTERS - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
+
+       mali_dma_write_array_conditional(buf, &core->hw_core,
+                                        relative_address, &frame_registers[start_index],
+                                        nr_of_regs, &mali_frame_registers_reset_values[start_index]);
+
+       /* Write WBx registers */
+       if (wb0_registers[0]) { /* M200_WB0_REG_SOURCE_SELECT register */
+               mali_dma_write_array_conditional(buf, &core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
+       }
+
+       if (wb1_registers[0]) { /* M200_WB1_REG_SOURCE_SELECT register */
+               mali_dma_write_array_conditional(buf, &core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
+       }
+
+       if (wb2_registers[0]) { /* M200_WB2_REG_SOURCE_SELECT register */
+               mali_dma_write_array_conditional(buf, &core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
+               mali_dma_write(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, counter_src0);
+               mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
+       }
+       if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
+               mali_dma_write(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, counter_src1);
+               mali_dma_write_conditional(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
+       }
+
+       /* This is the command that starts the core. */
+       mali_dma_write(buf, &core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
+}
+
+void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual)
+{
+       u32 relative_address;
+       u32 start_index;
+       u32 nr_of_regs;
+       u32 *frame_registers = mali_pp_job_get_frame_registers(job);
+       u32 *wb0_registers = mali_pp_job_get_wb0_registers(job);
+       u32 *wb1_registers = mali_pp_job_get_wb1_registers(job);
+       u32 *wb2_registers = mali_pp_job_get_wb2_registers(job);
+       u32 counter_src0 = mali_pp_job_get_perf_counter_src0(job, sub_job);
+       u32 counter_src1 = mali_pp_job_get_perf_counter_src1(job, sub_job);
+
+       MALI_DEBUG_ASSERT_POINTER(core);
+
+       /* Write frame registers */
+
+       /*
+        * There are two frame registers which are different for each sub job:
+        * 1. The Renderer List Address Register (MALI200_REG_ADDR_FRAME)
+        * 2. The FS Stack Address Register (MALI200_REG_ADDR_STACK)
+        */
+       mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_FRAME / sizeof(u32)]);
+
+       /* For virtual jobs, the stack address shouldn't be broadcast but written individually */
+       if (!mali_pp_job_is_virtual(job) || restart_virtual) {
+               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK / sizeof(u32)]);
+       }
+
+       /* Write registers between MALI200_REG_ADDR_FRAME and MALI200_REG_ADDR_STACK */
+       relative_address = MALI200_REG_ADDR_RSW;
+       start_index = MALI200_REG_ADDR_RSW / sizeof(u32);
+       nr_of_regs = (MALI200_REG_ADDR_STACK - MALI200_REG_ADDR_RSW) / sizeof(u32);
+
+       mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core,
+               relative_address, &frame_registers[start_index],
+               nr_of_regs, &mali_frame_registers_reset_values[start_index]);
+
+       /* MALI200_REG_ADDR_STACK_SIZE */
+       relative_address = MALI200_REG_ADDR_STACK_SIZE;
+       start_index = MALI200_REG_ADDR_STACK_SIZE / sizeof(u32);
+
+       mali_hw_core_register_write_relaxed_conditional(&core->hw_core,
+               relative_address, frame_registers[start_index],
+               mali_frame_registers_reset_values[start_index]);
+
+       /* Skip 2 reserved registers */
+
+       /* Write remaining registers */
+       relative_address = MALI200_REG_ADDR_ORIGIN_OFFSET_X;
+       start_index = MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
+       nr_of_regs = MALI_PP_MALI400_NUM_FRAME_REGISTERS - MALI200_REG_ADDR_ORIGIN_OFFSET_X / sizeof(u32);
+
+       mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core,
+               relative_address, &frame_registers[start_index],
+               nr_of_regs, &mali_frame_registers_reset_values[start_index]);
+
+       /* Write WBx registers */
+       if (wb0_registers[0]) { /* M200_WB0_REG_SOURCE_SELECT register */
+               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
+       }
+
+       if (wb1_registers[0]) { /* M200_WB1_REG_SOURCE_SELECT register */
+               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
+       }
+
+       if (wb2_registers[0]) { /* M200_WB2_REG_SOURCE_SELECT register */
+               mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, _MALI_PP_MAX_WB_REGISTERS, mali_wb_registers_reset_values);
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, counter_src0);
+               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
+       }
+       if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, counter_src1);
+               mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value);
+       }
+
+#ifdef CONFIG_MALI400_HEATMAPS_ENABLED
+       if(job->uargs.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_HEATMAP_ENABLE) {
+               mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERFMON_CONTR, ((job->uargs.tilesx & 0x3FF) << 16) | 1);
+               mali_hw_core_register_write_relaxed(&core->hw_core,  MALI200_REG_ADDR_MGMT_PERFMON_BASE, job->uargs.heatmap_mem & 0xFFFFFFF8);
+       }
+#endif /* CONFIG_MALI400_HEATMAPS_ENABLED */
+
+       MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description));
+
+       /* Adding barrier to make sure all rester writes are finished */
+       _mali_osk_write_mem_barrier();
+
+       /* This is the command that starts the core. */
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
+
+       /* Adding barrier to make sure previous rester writes is finished */
+       _mali_osk_write_mem_barrier();
+}
+
+u32 mali_pp_core_get_version(struct mali_pp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+       return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION);
+}
+
+struct mali_pp_core* mali_pp_get_global_pp_core(u32 index)
+{
+       if (mali_global_num_pp_cores > index) {
+               return mali_global_pp_cores[index];
+       }
+
+       return NULL;
+}
+
+u32 mali_pp_get_glob_num_pp_cores(void)
+{
+       return mali_global_num_pp_cores;
+}
+
+/* ------------- interrupt handling below ------------------ */
+static void mali_pp_irq_probe_trigger(void *data)
+{
+       struct mali_pp_core *core = (struct mali_pp_core *)data;
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG);
+       _mali_osk_mem_barrier();
+}
+
+static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data)
+{
+       struct mali_pp_core *core = (struct mali_pp_core *)data;
+       u32 irq_readout;
+
+       irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+       if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout) {
+               mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG);
+               _mali_osk_mem_barrier();
+               return _MALI_OSK_ERR_OK;
+       }
+
+       return _MALI_OSK_ERR_FAULT;
+}
+
+
+#if 0
+static void mali_pp_print_registers(struct mali_pp_core *core)
+{
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC)));
+       MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE)));
+}
+#endif
+
+#if 0
+void mali_pp_print_state(struct mali_pp_core *core)
+{
+       MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) ));
+}
+#endif
+
+void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob)
+{
+       u32 val0 = 0;
+       u32 val1 = 0;
+       u32 counter_src0 = mali_pp_job_get_perf_counter_src0(job, subjob);
+       u32 counter_src1 = mali_pp_job_get_perf_counter_src1(job, subjob);
+#if defined(CONFIG_MALI400_PROFILING)
+       int counter_index = COUNTER_FP_0_C0 + (2 * child->core_id);
+#endif
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src0) {
+               val0 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+               mali_pp_job_set_perf_counter_value0(job, subjob, val0);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               _mali_osk_profiling_report_hw_counter(counter_index, val0);
+#endif
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER != counter_src1) {
+               val1 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+               mali_pp_job_set_perf_counter_value1(job, subjob, val1);
+
+#if defined(CONFIG_MALI400_PROFILING)
+               _mali_osk_profiling_report_hw_counter(counter_index + 1, val1);
+#endif
+       }
+}
+
+#if MALI_STATE_TRACKING
+u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size)
+{
+       int n = 0;
+
+       n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description);
+
+       return n;
+}
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp.h b/drivers/gpu/arm/mali400/mali/common/mali_pp.h
new file mode 100755 (executable)
index 0000000..839b43e
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PP_H__
+#define __MALI_PP_H__
+
+#include "mali_osk.h"
+#include "mali_pp_job.h"
+#include "mali_hw_core.h"
+#include "mali_dma.h"
+
+struct mali_group;
+
+#define MALI_MAX_NUMBER_OF_PP_CORES        9
+
+/**
+ * Definition of the PP core struct
+ * Used to track a PP core in the system.
+ */
+struct mali_pp_core {
+       struct mali_hw_core  hw_core;           /**< Common for all HW cores */
+       _mali_osk_irq_t     *irq;               /**< IRQ handler */
+       u32                  core_id;           /**< Unique core ID */
+       u32                  bcast_id;          /**< The "flag" value used by the Mali-450 broadcast and DLBU unit */
+};
+
+_mali_osk_errcode_t mali_pp_initialize(void);
+void mali_pp_terminate(void);
+
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id);
+void mali_pp_delete(struct mali_pp_core *core);
+
+void mali_pp_stop_bus(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core);
+void mali_pp_reset_async(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_reset_wait(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core);
+
+void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job, mali_bool restart_virtual);
+
+/**
+ * @brief Add commands to DMA command buffer to start PP job on core.
+ */
+void mali_pp_job_dma_cmd_prepare(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job,
+                                 mali_bool restart_virtual, mali_dma_cmd_buf *buf);
+
+u32 mali_pp_core_get_version(struct mali_pp_core *core);
+
+MALI_STATIC_INLINE u32 mali_pp_core_get_id(struct mali_pp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+       return core->core_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_core_get_bcast_id(struct mali_pp_core *core)
+{
+       MALI_DEBUG_ASSERT_POINTER(core);
+       return core->bcast_id;
+}
+
+struct mali_pp_core* mali_pp_get_global_pp_core(u32 index);
+u32 mali_pp_get_glob_num_pp_cores(void);
+
+/* Debug */
+u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size);
+
+/**
+ * Put instrumented HW counters from the core(s) to the job object (if enabled)
+ *
+ * parent and child is always the same, except for virtual jobs on Mali-450.
+ * In this case, the counters will be enabled on the virtual core (parent),
+ * but values need to be read from the child cores.
+ *
+ * @param parent The core used to see if the counters was enabled
+ * @param child The core to actually read the values from
+ * @job Job object to update with counter values (if enabled)
+ * @subjob Which subjob the counters are applicable for (core ID for virtual jobs)
+ */
+void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob);
+
+MALI_STATIC_INLINE const char *mali_pp_get_hw_core_desc(struct mali_pp_core *core)
+{
+       return core->hw_core.description;
+}
+
+/*** Register reading/writing functions ***/
+MALI_STATIC_INLINE u32 mali_pp_get_int_stat(struct mali_pp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+}
+
+MALI_STATIC_INLINE u32 mali_pp_read_rawstat(struct mali_pp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_read_status(struct mali_pp_core *core)
+{
+       return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS);
+}
+
+MALI_STATIC_INLINE void mali_pp_mask_all_interrupts(struct mali_pp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
+}
+
+MALI_STATIC_INLINE void mali_pp_clear_hang_interrupt(struct mali_pp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG);
+}
+
+MALI_STATIC_INLINE void mali_pp_enable_interrupts(struct mali_pp_core *core)
+{
+       mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+}
+
+MALI_STATIC_INLINE void mali_pp_write_addr_stack(struct mali_pp_core *core, struct mali_pp_job *job)
+{
+       u32 addr = mali_pp_job_get_addr_stack(job, core->core_id);
+       mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, addr);
+}
+
+#endif /* __MALI_PP_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp_job.c b/drivers/gpu/arm/mali400/mali/common/mali_pp_job.c
new file mode 100755 (executable)
index 0000000..ab4068b
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_pp.h"
+#include "mali_pp_job.h"
+#include "mali_dma.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_kernel_common.h"
+#include "mali_uk_types.h"
+#include "mali_pp_scheduler.h"
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+#include "linux/mali_memory_dma_buf.h"
+#endif
+
+static u32 pp_counter_src0 = MALI_HW_CORE_NO_COUNTER;   /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+static u32 pp_counter_src1 = MALI_HW_CORE_NO_COUNTER;   /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+static _mali_osk_atomic_t pp_counter_per_sub_job_count; /**< Number of values in the two arrays which is != MALI_HW_CORE_NO_COUNTER */
+static u32 pp_counter_per_sub_job_src0[_MALI_PP_MAX_SUB_JOBS] = { MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER };
+static u32 pp_counter_per_sub_job_src1[_MALI_PP_MAX_SUB_JOBS] = { MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER, MALI_HW_CORE_NO_COUNTER };
+
+void mali_pp_job_initialize(void)
+{
+       _mali_osk_atomic_init(&pp_counter_per_sub_job_count, 0);
+}
+
+void mali_pp_job_terminate(void)
+{
+       _mali_osk_atomic_term(&pp_counter_per_sub_job_count);
+}
+
+struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id)
+{
+       struct mali_pp_job *job;
+       u32 perf_counter_flag;
+
+       job = _mali_osk_calloc(1, sizeof(struct mali_pp_job));
+       if (NULL != job) {
+               if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s))) {
+                       goto fail;
+               }
+
+               if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS) {
+                       MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
+                       goto fail;
+               }
+
+               if (!mali_pp_job_use_no_notification(job)) {
+                       job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
+                       if (NULL == job->finished_notification) goto fail;
+               }
+
+               perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);
+
+               /* case when no counters came from user space
+                * so pass the debugfs / DS-5 provided global ones to the job object */
+               if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) ||
+                     (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) {
+                       u32 sub_job_count = _mali_osk_atomic_read(&pp_counter_per_sub_job_count);
+
+                       /* These counters apply for all virtual jobs, and where no per sub job counter is specified */
+                       job->uargs.perf_counter_src0 = pp_counter_src0;
+                       job->uargs.perf_counter_src1 = pp_counter_src1;
+
+                       /* We only copy the per sub job array if it is enabled with at least one counter */
+                       if (0 < sub_job_count) {
+                               job->perf_counter_per_sub_job_count = sub_job_count;
+                               _mali_osk_memcpy(job->perf_counter_per_sub_job_src0, pp_counter_per_sub_job_src0, sizeof(pp_counter_per_sub_job_src0));
+                               _mali_osk_memcpy(job->perf_counter_per_sub_job_src1, pp_counter_per_sub_job_src1, sizeof(pp_counter_per_sub_job_src1));
+                       }
+               }
+
+               _mali_osk_list_init(&job->list);
+               job->session = session;
+               _mali_osk_list_init(&job->session_list);
+               job->id = id;
+
+               job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1;
+               job->pid = _mali_osk_get_pid();
+               job->tid = _mali_osk_get_tid();
+
+               job->num_memory_cookies = job->uargs.num_memory_cookies;
+               if (job->num_memory_cookies > 0) {
+                       u32 size;
+
+                       if (job->uargs.num_memory_cookies > session->descriptor_mapping->current_nr_mappings) {
+                               MALI_PRINT_ERROR(("Mali PP job: Too many memory cookies specified in job object\n"));
+                               goto fail;
+                       }
+
+                       size = sizeof(*job->uargs.memory_cookies) * job->num_memory_cookies;
+
+                       job->memory_cookies = _mali_osk_malloc(size);
+                       if (NULL == job->memory_cookies) {
+                               MALI_PRINT_ERROR(("Mali PP job: Failed to allocate %d bytes of memory cookies!\n", size));
+                               goto fail;
+                       }
+
+                       if (0 != _mali_osk_copy_from_user(job->memory_cookies, job->uargs.memory_cookies, size)) {
+                               MALI_PRINT_ERROR(("Mali PP job: Failed to copy %d bytes of memory cookies from user!\n", size));
+                               goto fail;
+                       }
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+                       job->num_dma_bufs = job->num_memory_cookies;
+                       job->dma_bufs = _mali_osk_calloc(job->num_dma_bufs, sizeof(struct mali_dma_buf_attachment *));
+                       if (NULL == job->dma_bufs) {
+                               MALI_PRINT_ERROR(("Mali PP job: Failed to allocate dma_bufs array!\n"));
+                               goto fail;
+                       }
+#endif
+               }
+
+               /* Prepare DMA command buffer to start job, if it is virtual. */
+               if (mali_pp_job_is_virtual(job)) {
+                       struct mali_pp_core *core;
+                       _mali_osk_errcode_t err =  mali_dma_get_cmd_buf(&job->dma_cmd_buf);
+
+                       if (_MALI_OSK_ERR_OK != err) {
+                               MALI_PRINT_ERROR(("Mali PP job: Failed to allocate DMA command buffer\n"));
+                               goto fail;
+                       }
+
+                       core = mali_pp_scheduler_get_virtual_pp();
+                       MALI_DEBUG_ASSERT_POINTER(core);
+
+                       mali_pp_job_dma_cmd_prepare(core, job, 0, MALI_FALSE, &job->dma_cmd_buf);
+               }
+
+               if (_MALI_OSK_ERR_OK != mali_pp_job_check(job)) {
+                       /* Not a valid job. */
+                       goto fail;
+               }
+
+               mali_timeline_tracker_init(&job->tracker, MALI_TIMELINE_TRACKER_PP, NULL, job);
+               mali_timeline_fence_copy_uk_fence(&(job->tracker.fence), &(job->uargs.fence));
+
+               return job;
+       }
+
+fail:
+       if (NULL != job) {
+               mali_pp_job_delete(job);
+       }
+
+       return NULL;
+}
+
+void mali_pp_job_delete(struct mali_pp_job *job)
+{
+       mali_dma_put_cmd_buf(&job->dma_cmd_buf);
+       if (NULL != job->finished_notification) {
+               _mali_osk_notification_delete(job->finished_notification);
+       }
+
+       _mali_osk_free(job->memory_cookies);
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+       /* Unmap buffers attached to job */
+       if (0 < job->num_dma_bufs) {
+               mali_dma_buf_unmap_job(job);
+       }
+
+       _mali_osk_free(job->dma_bufs);
+#endif /* CONFIG_DMA_SHARED_BUFFER */
+
+       _mali_osk_free(job);
+}
+
+u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job, u32 sub_job)
+{
+       /* Virtual jobs always use the global job counter (or if there are per sub job counters at all) */
+       if (mali_pp_job_is_virtual(job) || 0 == job->perf_counter_per_sub_job_count) {
+               return job->uargs.perf_counter_src0;
+       }
+
+       /* Use per sub job counter if enabled... */
+       if (MALI_HW_CORE_NO_COUNTER != job->perf_counter_per_sub_job_src0[sub_job]) {
+               return job->perf_counter_per_sub_job_src0[sub_job];
+       }
+
+       /* ...else default to global job counter */
+       return job->uargs.perf_counter_src0;
+}
+
+u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job, u32 sub_job)
+{
+       /* Virtual jobs always use the global job counter (or if there are per sub job counters at all) */
+       if (mali_pp_job_is_virtual(job) || 0 == job->perf_counter_per_sub_job_count) {
+               /* Virtual jobs always use the global job counter */
+               return job->uargs.perf_counter_src1;
+       }
+
+       /* Use per sub job counter if enabled... */
+       if (MALI_HW_CORE_NO_COUNTER != job->perf_counter_per_sub_job_src1[sub_job]) {
+               return job->perf_counter_per_sub_job_src1[sub_job];
+       }
+
+       /* ...else default to global job counter */
+       return job->uargs.perf_counter_src1;
+}
+
+void mali_pp_job_set_pp_counter_global_src0(u32 counter)
+{
+       pp_counter_src0 = counter;
+}
+
+void mali_pp_job_set_pp_counter_global_src1(u32 counter)
+{
+       pp_counter_src1 = counter;
+}
+
+void mali_pp_job_set_pp_counter_sub_job_src0(u32 sub_job, u32 counter)
+{
+       MALI_DEBUG_ASSERT(sub_job < _MALI_PP_MAX_SUB_JOBS);
+
+       if (MALI_HW_CORE_NO_COUNTER == pp_counter_per_sub_job_src0[sub_job]) {
+               /* increment count since existing counter was disabled */
+               _mali_osk_atomic_inc(&pp_counter_per_sub_job_count);
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER == counter) {
+               /* decrement count since new counter is disabled */
+               _mali_osk_atomic_dec(&pp_counter_per_sub_job_count);
+       }
+
+       /* PS: A change from MALI_HW_CORE_NO_COUNTER to MALI_HW_CORE_NO_COUNTER will inc and dec, result will be 0 change */
+
+       pp_counter_per_sub_job_src0[sub_job] = counter;
+}
+
+void mali_pp_job_set_pp_counter_sub_job_src1(u32 sub_job, u32 counter)
+{
+       MALI_DEBUG_ASSERT(sub_job < _MALI_PP_MAX_SUB_JOBS);
+
+       if (MALI_HW_CORE_NO_COUNTER == pp_counter_per_sub_job_src1[sub_job]) {
+               /* increment count since existing counter was disabled */
+               _mali_osk_atomic_inc(&pp_counter_per_sub_job_count);
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER == counter) {
+               /* decrement count since new counter is disabled */
+               _mali_osk_atomic_dec(&pp_counter_per_sub_job_count);
+       }
+
+       /* PS: A change from MALI_HW_CORE_NO_COUNTER to MALI_HW_CORE_NO_COUNTER will inc and dec, result will be 0 change */
+
+       pp_counter_per_sub_job_src1[sub_job] = counter;
+}
+
+u32 mali_pp_job_get_pp_counter_global_src0(void)
+{
+       return pp_counter_src0;
+}
+
+u32 mali_pp_job_get_pp_counter_global_src1(void)
+{
+       return pp_counter_src1;
+}
+
+u32 mali_pp_job_get_pp_counter_sub_job_src0(u32 sub_job)
+{
+       MALI_DEBUG_ASSERT(sub_job < _MALI_PP_MAX_SUB_JOBS);
+       return pp_counter_per_sub_job_src0[sub_job];
+}
+
+u32 mali_pp_job_get_pp_counter_sub_job_src1(u32 sub_job)
+{
+       MALI_DEBUG_ASSERT(sub_job < _MALI_PP_MAX_SUB_JOBS);
+       return pp_counter_per_sub_job_src1[sub_job];
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp_job.h b/drivers/gpu/arm/mali400/mali/common/mali_pp_job.h
new file mode 100755 (executable)
index 0000000..7a25992
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PP_JOB_H__
+#define __MALI_PP_JOB_H__
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+#include "mali_session.h"
+#include "mali_kernel_common.h"
+#include "regs/mali_200_regs.h"
+#include "mali_kernel_core.h"
+#include "mali_dma.h"
+#include "mali_dlbu.h"
+#include "mali_timeline.h"
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+#include "linux/mali_memory_dma_buf.h"
+#endif
+
+/**
+ * The structure represents a PP job, including all sub-jobs
+ * (This struct unfortunately needs to be public because of how the _mali_osk_list_*
+ * mechanism works)
+ */
+struct mali_pp_job {
+       _mali_osk_list_t list;                             /**< Used to link jobs together in the scheduler queue */
+       struct mali_session_data *session;                 /**< Session which submitted this job */
+       _mali_osk_list_t session_list;                     /**< Used to link jobs together in the session job list */
+       _mali_osk_list_t session_fb_lookup_list;           /**< Used to link jobs together from the same frame builder in the session */
+       _mali_uk_pp_start_job_s uargs;                     /**< Arguments from user space */
+       mali_dma_cmd_buf dma_cmd_buf;                      /**< Command buffer for starting job using Mali-450 DMA unit */
+       u32 id;                                            /**< Identifier for this job in kernel space (sequential numbering) */
+       u32 cache_order;                                   /**< Cache order used for L2 cache flushing (sequential numbering) */
+       u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS];    /**< Value of performance counter 0 (to be returned to user space), one for each sub job */
+       u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS];    /**< Value of performance counter 1 (to be returned to user space), one for each sub job */
+       u32 sub_jobs_num;                                  /**< Number of subjobs; set to 1 for Mali-450 if DLBU is used, otherwise equals number of PP cores */
+       u32 sub_jobs_started;                              /**< Total number of sub-jobs started (always started in ascending order) */
+       u32 sub_jobs_completed;                            /**< Number of completed sub-jobs in this superjob */
+       u32 sub_job_errors;                                /**< Bitfield with errors (errors for each single sub-job is or'ed together) */
+       u32 pid;                                           /**< Process ID of submitting process */
+       u32 tid;                                           /**< Thread ID of submitting thread */
+       _mali_osk_notification_t *finished_notification;   /**< Notification sent back to userspace on job complete */
+       u32 num_memory_cookies;                            /**< Number of memory cookies attached to job */
+       u32 *memory_cookies;                               /**< Memory cookies attached to job */
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+       struct mali_dma_buf_attachment **dma_bufs;         /**< Array of DMA-bufs used by job */
+       u32 num_dma_bufs;                                  /**< Number of DMA-bufs used by job */
+#endif
+       struct mali_timeline_tracker tracker;              /**< Timeline tracker for this job */
+       u32 perf_counter_per_sub_job_count;                /**< Number of values in the two arrays which is != MALI_HW_CORE_NO_COUNTER */
+       u32 perf_counter_per_sub_job_src0[_MALI_PP_MAX_SUB_JOBS]; /**< Per sub job counters src0 */
+       u32 perf_counter_per_sub_job_src1[_MALI_PP_MAX_SUB_JOBS]; /**< Per sub job counters src1 */
+};
+
+void mali_pp_job_initialize(void);
+void mali_pp_job_terminate(void);
+
+struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id);
+void mali_pp_job_delete(struct mali_pp_job *job);
+
+u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job, u32 sub_job);
+u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job, u32 sub_job);
+
+void mali_pp_job_set_pp_counter_global_src0(u32 counter);
+void mali_pp_job_set_pp_counter_global_src1(u32 counter);
+void mali_pp_job_set_pp_counter_sub_job_src0(u32 sub_job, u32 counter);
+void mali_pp_job_set_pp_counter_sub_job_src1(u32 sub_job, u32 counter);
+
+u32 mali_pp_job_get_pp_counter_global_src0(void);
+u32 mali_pp_job_get_pp_counter_global_src1(void);
+u32 mali_pp_job_get_pp_counter_sub_job_src0(u32 sub_job);
+u32 mali_pp_job_get_pp_counter_sub_job_src1(u32 sub_job);
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job)
+{
+       return (NULL == job) ? 0 : job->id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_cache_order(struct mali_pp_job *job)
+{
+       return (NULL == job) ? 0 : job->cache_order;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job)
+{
+       return job->uargs.user_job_ptr;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job)
+{
+       return job->uargs.frame_builder_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job)
+{
+       return job->uargs.flush_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_pid(struct mali_pp_job *job)
+{
+       return job->pid;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_tid(struct mali_pp_job *job)
+{
+       return job->tid;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job)
+{
+       return job->uargs.frame_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_dlbu_registers(struct mali_pp_job *job)
+{
+       return job->uargs.dlbu_registers;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_is_virtual(struct mali_pp_job *job)
+{
+#if defined(CONFIG_MALI450)
+       return 0 == job->uargs.num_cores;
+#else
+       return MALI_FALSE;
+#endif
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job)
+{
+       if (mali_pp_job_is_virtual(job)) {
+               return MALI_DLBU_VIRT_ADDR;
+       } else if (0 == sub_job) {
+               return job->uargs.frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)];
+       } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) {
+               return job->uargs.frame_registers_addr_frame[sub_job - 1];
+       }
+
+       return 0;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job)
+{
+       if (0 == sub_job) {
+               return job->uargs.frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)];
+       } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) {
+               return job->uargs.frame_registers_addr_stack[sub_job - 1];
+       }
+
+       return 0;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job)
+{
+       return job->uargs.wb0_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job)
+{
+       return job->uargs.wb1_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job)
+{
+       return job->uargs.wb2_registers;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job)
+{
+       job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job)
+{
+       job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job)
+{
+       job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_all_writeback_unit_disabled(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       if ( job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] ||
+            job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] ||
+            job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT]
+          ) {
+               /* At least one output unit active */
+               return MALI_FALSE;
+       }
+
+       /* All outputs are disabled - we can abort the job */
+       return MALI_TRUE;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_fb_lookup_id(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       return MALI_PP_JOB_FB_LOOKUP_LIST_MASK & job->uargs.frame_builder_id;
+}
+
+MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job)
+{
+       return job->session;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job)
+{
+       return (job->sub_jobs_started < job->sub_jobs_num) ? MALI_TRUE : MALI_FALSE;
+}
+
+/* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job.
+   Makes sure that no new subjobs are started. */
+MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_failed(struct mali_pp_job *job)
+{
+       u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started;
+       job->sub_jobs_started   += jobs_remaining;
+       job->sub_jobs_completed += jobs_remaining;
+       job->sub_job_errors     += jobs_remaining;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_success(struct mali_pp_job *job)
+{
+       u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started;
+       job->sub_jobs_started   += jobs_remaining;
+       job->sub_jobs_completed += jobs_remaining;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job)
+{
+       return (job->sub_jobs_num == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job)
+{
+       return job->sub_jobs_started;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job)
+{
+       return job->sub_jobs_num;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_needs_dma_buf_mapping(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT(job);
+
+       if (0 != job->num_memory_cookies) {
+               return MALI_TRUE;
+       }
+
+       return MALI_FALSE;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       /* Assert that we are marking the "first unstarted sub job" as started */
+       MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job);
+
+       job->sub_jobs_started++;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success)
+{
+       job->sub_jobs_completed++;
+       if ( MALI_FALSE == success ) {
+               job->sub_job_errors++;
+       }
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job)
+{
+       if ( 0 == job->sub_job_errors ) {
+               return MALI_TRUE;
+       }
+       return MALI_FALSE;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job)
+{
+       return job->uargs.flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job)
+{
+       return job->uargs.perf_counter_flag;
+}
+
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job)
+{
+       return job->perf_counter_value0[sub_job];
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job)
+{
+       return job->perf_counter_value1[sub_job];
+}
+
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value)
+{
+       job->perf_counter_value0[sub_job] = value;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value)
+{
+       job->perf_counter_value1[sub_job] = value;
+}
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job)
+{
+       if (mali_pp_job_is_virtual(job) && job->sub_jobs_num != 1) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+       return _MALI_OSK_ERR_OK;
+}
+
+/**
+ * Returns MALI_TRUE if first job should be started after second job.
+ *
+ * @param first First job.
+ * @param second Second job.
+ * @return MALI_TRUE if first job should be started after second job, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_pp_job_should_start_after(struct mali_pp_job *first, struct mali_pp_job *second)
+{
+       MALI_DEBUG_ASSERT_POINTER(first);
+       MALI_DEBUG_ASSERT_POINTER(second);
+
+       /* First job should be started after second job if second job is in progress. */
+       if (0 < second->sub_jobs_started) {
+               return MALI_TRUE;
+       }
+
+       /* First job should be started after second job if first job has a higher job id.  A span is
+          used to handle job id wrapping. */
+       if ((mali_pp_job_get_id(first) - mali_pp_job_get_id(second)) < MALI_SCHEDULER_JOB_ID_SPAN) {
+               return MALI_TRUE;
+       }
+
+       /* Second job should be started after first job. */
+       return MALI_FALSE;
+}
+
+/**
+ * Returns MALI_TRUE if this job has more than two sub jobs and all sub jobs are unstarted.
+ *
+ * @param job Job to check.
+ * @return MALI_TRUE if job has more than two sub jobs and all sub jobs are unstarted, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_pp_job_is_large_and_unstarted(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual(job));
+
+       return (0 == job->sub_jobs_started && 2 < job->sub_jobs_num);
+}
+
+/**
+ * Get PP job's Timeline tracker.
+ *
+ * @param job PP job.
+ * @return Pointer to Timeline tracker for the job.
+ */
+MALI_STATIC_INLINE struct mali_timeline_tracker *mali_pp_job_get_tracker(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       return &(job->tracker);
+}
+
+#endif /* __MALI_PP_JOB_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.c b/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.c
new file mode 100755 (executable)
index 0000000..6b985d0
--- /dev/null
@@ -0,0 +1,2067 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_pp_scheduler.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_scheduler.h"
+#include "mali_pp.h"
+#include "mali_pp_job.h"
+#include "mali_group.h"
+#include "mali_pm.h"
+#include "mali_timeline.h"
+#include "mali_osk_profiling.h"
+#include "mali_kernel_utilization.h"
+#include "mali_session.h"
+#include "mali_pm_domain.h"
+#include "linux/mali/mali_utgard.h"
+
+#if defined(CONFIG_DMA_SHARED_BUFFER)
+#include "mali_memory_dma_buf.h"
+#endif
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+#include <linux/sched.h>
+#include <trace/events/gpu.h>
+#endif
+
+/* Queue type used for physical and virtual job queues. */
+struct mali_pp_scheduler_job_queue {
+       _MALI_OSK_LIST_HEAD(normal_pri); /* List of jobs with some unscheduled work. */
+       _MALI_OSK_LIST_HEAD(high_pri);   /* List of high priority jobs with some unscheduled work. */
+       u32 depth;                       /* Depth of combined queues. */
+};
+
+/* If dma_buf with map on demand is used, we defer job deletion and job queue if in atomic context,
+ * since both might sleep. */
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+#define MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE 1
+#define MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE 1
+#endif /* !defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) */
+
+static void mali_pp_scheduler_job_queued(void);
+static void mali_pp_scheduler_job_completed(void);
+
+/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */
+#define MALI_MAX_NUMBER_OF_PP_GROUPS 9
+
+static mali_bool mali_pp_scheduler_is_suspended(void *data);
+
+static u32 pp_version = 0;
+
+/* Physical job queue */
+static struct mali_pp_scheduler_job_queue job_queue;
+
+/* Physical groups */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_working);     /* List of physical groups with working jobs on the pp core */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_idle);        /* List of physical groups with idle jobs on the pp core */
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(group_list_disabled);    /* List of disabled physical groups */
+
+/* Virtual job queue (Mali-450 only) */
+static struct mali_pp_scheduler_job_queue virtual_job_queue;
+
+/**
+ * Add job to scheduler queue.
+ *
+ * @param job Job to queue.
+ * @return Schedule mask.
+ */
+static mali_scheduler_mask mali_pp_scheduler_queue_job(struct mali_pp_job *job);
+
+/* Virtual group (Mali-450 only) */
+static struct mali_group *virtual_group = NULL;                 /* Virtual group (if any) */
+static enum {
+       VIRTUAL_GROUP_IDLE,
+       VIRTUAL_GROUP_WORKING,
+       VIRTUAL_GROUP_DISABLED,
+}
+virtual_group_state = VIRTUAL_GROUP_IDLE;            /* Flag which indicates whether the virtual group is working or idle */
+
+/* Number of physical cores */
+static u32 num_cores = 0;
+
+/* Number of physical cores which are enabled */
+static u32 enabled_cores = 0;
+
+/* Enable or disable core scaling */
+static mali_bool core_scaling_enabled = MALI_TRUE;
+
+/* Variables to allow safe pausing of the scheduler */
+static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL;
+static u32 pause_count = 0;
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+static _mali_osk_spinlock_irq_t *pp_scheduler_lock = NULL;
+#else
+static _mali_osk_spinlock_t *pp_scheduler_lock = NULL;
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+
+MALI_STATIC_INLINE void mali_pp_scheduler_lock(void)
+{
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       _mali_osk_spinlock_irq_lock(pp_scheduler_lock);
+#else
+       _mali_osk_spinlock_lock(pp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+       MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken.\n"));
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void)
+{
+       MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock.\n"));
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       _mali_osk_spinlock_irq_unlock(pp_scheduler_lock);
+#else
+       _mali_osk_spinlock_unlock(pp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+}
+
+#if defined(DEBUG)
+#define MALI_ASSERT_PP_SCHEDULER_LOCKED() MALI_DEBUG_ASSERT_LOCK_HELD(pp_scheduler_lock)
+#else
+#define MALI_ASSERT_PP_SCHEDULER_LOCKED() do {} while (0)
+#endif /* defined(DEBUG) */
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+
+static _mali_osk_wq_work_t *pp_scheduler_wq_job_delete = NULL;
+static _mali_osk_spinlock_irq_t *pp_scheduler_job_delete_lock = NULL;
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(pp_scheduler_job_deletion_queue);
+
+static void mali_pp_scheduler_deferred_job_delete(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       _mali_osk_spinlock_irq_lock(pp_scheduler_job_delete_lock);
+
+       /* This job object should not be on any lists. */
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list));
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->session_list));
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->session_fb_lookup_list));
+
+       _mali_osk_list_addtail(&job->list, &pp_scheduler_job_deletion_queue);
+
+       _mali_osk_spinlock_irq_unlock(pp_scheduler_job_delete_lock);
+
+       _mali_osk_wq_schedule_work(pp_scheduler_wq_job_delete);
+}
+
+static void mali_pp_scheduler_do_job_delete(void *arg)
+{
+       _MALI_OSK_LIST_HEAD_STATIC_INIT(list);
+       struct mali_pp_job *job;
+       struct mali_pp_job *tmp;
+
+       MALI_IGNORE(arg);
+
+       _mali_osk_spinlock_irq_lock(pp_scheduler_job_delete_lock);
+
+       /*
+        * Quickly "unhook" the jobs pending to be deleted, so we can release the lock before
+        * we start deleting the job objects (without any locks held
+        */
+       _mali_osk_list_move_list(&pp_scheduler_job_deletion_queue, &list);
+
+       _mali_osk_spinlock_irq_unlock(pp_scheduler_job_delete_lock);
+
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &list, struct mali_pp_job, list) {
+               mali_pp_job_delete(job); /* delete the job object itself */
+       }
+}
+
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) */
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE)
+
+static _mali_osk_wq_work_t *pp_scheduler_wq_job_queue = NULL;
+static _mali_osk_spinlock_irq_t *pp_scheduler_job_queue_lock = NULL;
+static _MALI_OSK_LIST_HEAD_STATIC_INIT(pp_scheduler_job_queue_list);
+
+static void mali_pp_scheduler_deferred_job_queue(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       _mali_osk_spinlock_irq_lock(pp_scheduler_job_queue_lock);
+       _mali_osk_list_addtail(&job->list, &pp_scheduler_job_queue_list);
+       _mali_osk_spinlock_irq_unlock(pp_scheduler_job_queue_lock);
+
+       _mali_osk_wq_schedule_work(pp_scheduler_wq_job_queue);
+}
+
+static void mali_pp_scheduler_do_job_queue(void *arg)
+{
+       _MALI_OSK_LIST_HEAD_STATIC_INIT(list);
+       struct mali_pp_job *job;
+       struct mali_pp_job *tmp;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_IGNORE(arg);
+
+       _mali_osk_spinlock_irq_lock(pp_scheduler_job_queue_lock);
+
+       /*
+        * Quickly "unhook" the jobs pending to be queued, so we can release the lock before
+        * we start queueing the job objects (without any locks held)
+        */
+       _mali_osk_list_move_list(&pp_scheduler_job_queue_list, &list);
+
+       _mali_osk_spinlock_irq_unlock(pp_scheduler_job_queue_lock);
+
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &list, struct mali_pp_job, list) {
+               _mali_osk_list_delinit(&job->list);
+               schedule_mask |= mali_pp_scheduler_queue_job(job);
+       }
+
+       mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE);
+}
+
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE) */
+
+MALI_STATIC_INLINE mali_bool mali_pp_scheduler_has_virtual_group(void)
+{
+#if defined(CONFIG_MALI450)
+       return NULL != virtual_group;
+#else
+       return MALI_FALSE;
+#endif /* defined(CONFIG_MALI450) */
+}
+
+_mali_osk_errcode_t mali_pp_scheduler_initialize(void)
+{
+       _MALI_OSK_INIT_LIST_HEAD(&job_queue.normal_pri);
+       _MALI_OSK_INIT_LIST_HEAD(&job_queue.high_pri);
+       job_queue.depth = 0;
+
+       _MALI_OSK_INIT_LIST_HEAD(&virtual_job_queue.normal_pri);
+       _MALI_OSK_INIT_LIST_HEAD(&virtual_job_queue.high_pri);
+       virtual_job_queue.depth = 0;
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       pp_scheduler_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+#else
+       pp_scheduler_lock = _mali_osk_spinlock_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+       if (NULL == pp_scheduler_lock) goto cleanup;
+
+       pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init();
+       if (NULL == pp_scheduler_working_wait_queue) goto cleanup;
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+       pp_scheduler_wq_job_delete = _mali_osk_wq_create_work(mali_pp_scheduler_do_job_delete, NULL);
+       if (NULL == pp_scheduler_wq_job_delete) goto cleanup;
+
+       pp_scheduler_job_delete_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED);
+       if (NULL == pp_scheduler_job_delete_lock) goto cleanup;
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) */
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE)
+       pp_scheduler_wq_job_queue = _mali_osk_wq_create_work(mali_pp_scheduler_do_job_queue, NULL);
+       if (NULL == pp_scheduler_wq_job_queue) goto cleanup;
+
+       pp_scheduler_job_queue_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER_DEFERRED);
+       if (NULL == pp_scheduler_job_queue_lock) goto cleanup;
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE) */
+
+       return _MALI_OSK_ERR_OK;
+
+cleanup:
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE)
+       if (NULL != pp_scheduler_job_queue_lock) {
+               _mali_osk_spinlock_irq_term(pp_scheduler_job_queue_lock);
+               pp_scheduler_job_queue_lock = NULL;
+       }
+
+       if (NULL != pp_scheduler_wq_job_queue) {
+               _mali_osk_wq_delete_work(pp_scheduler_wq_job_queue);
+               pp_scheduler_wq_job_queue = NULL;
+       }
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE) */
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+       if (NULL != pp_scheduler_job_delete_lock) {
+               _mali_osk_spinlock_irq_term(pp_scheduler_job_delete_lock);
+               pp_scheduler_job_delete_lock = NULL;
+       }
+
+       if (NULL != pp_scheduler_wq_job_delete) {
+               _mali_osk_wq_delete_work(pp_scheduler_wq_job_delete);
+               pp_scheduler_wq_job_delete = NULL;
+       }
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) */
+
+       if (NULL != pp_scheduler_working_wait_queue) {
+               _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue);
+               pp_scheduler_working_wait_queue = NULL;
+       }
+
+       if (NULL != pp_scheduler_lock) {
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+               _mali_osk_spinlock_irq_term(pp_scheduler_lock);
+#else
+               _mali_osk_spinlock_term(pp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+               pp_scheduler_lock = NULL;
+       }
+
+       return _MALI_OSK_ERR_NOMEM;
+}
+
+void mali_pp_scheduler_terminate(void)
+{
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE)
+       _mali_osk_spinlock_irq_term(pp_scheduler_job_queue_lock);
+       _mali_osk_wq_delete_work(pp_scheduler_wq_job_queue);
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE) */
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+       _mali_osk_spinlock_irq_term(pp_scheduler_job_delete_lock);
+       _mali_osk_wq_delete_work(pp_scheduler_wq_job_delete);
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) */
+
+       _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue);
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       _mali_osk_spinlock_irq_term(pp_scheduler_lock);
+#else
+       _mali_osk_spinlock_term(pp_scheduler_lock);
+#endif /* defined(MALI_UPPER_HALF_SCHEDULING) */
+}
+
+void mali_pp_scheduler_populate(void)
+{
+       struct mali_group *group;
+       struct mali_pp_core *pp_core;
+       u32 num_groups;
+       u32 i;
+
+       num_groups = mali_group_get_glob_num_groups();
+
+       /* Do we have a virtual group? */
+       for (i = 0; i < num_groups; i++) {
+               group = mali_group_get_glob_group(i);
+
+               if (mali_group_is_virtual(group)) {
+                       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Found virtual group %p.\n", group));
+
+                       virtual_group = group;
+                       break;
+               }
+       }
+
+       /* Find all the available PP cores */
+       for (i = 0; i < num_groups; i++) {
+               group = mali_group_get_glob_group(i);
+               pp_core = mali_group_get_pp_core(group);
+
+               if (NULL != pp_core && !mali_group_is_virtual(group)) {
+                       if (0 == pp_version) {
+                               /* Retrieve PP version from the first available PP core */
+                               pp_version = mali_pp_core_get_version(pp_core);
+                       }
+
+                       if (mali_pp_scheduler_has_virtual_group()) {
+                               /* Add all physical PP cores to the virtual group */
+                               mali_group_lock(virtual_group);
+                               group->state = MALI_GROUP_STATE_JOINING_VIRTUAL;
+                               mali_group_add_group(virtual_group, group, MALI_TRUE);
+                               mali_group_unlock(virtual_group);
+                       } else {
+                               _mali_osk_list_add(&group->pp_scheduler_list, &group_list_idle);
+                       }
+
+                       num_cores++;
+               }
+       }
+
+       enabled_cores = num_cores;
+}
+
+void mali_pp_scheduler_depopulate(void)
+{
+       struct mali_group *group, *temp;
+
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+       MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state);
+
+       /* Delete all groups owned by scheduler */
+       if (mali_pp_scheduler_has_virtual_group()) {
+               mali_group_delete(virtual_group);
+       }
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) {
+               mali_group_delete(group);
+       }
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_disabled, struct mali_group, pp_scheduler_list) {
+               mali_group_delete(group);
+       }
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_disable_empty_virtual(void)
+{
+       MALI_ASSERT_GROUP_LOCKED(virtual_group);
+
+       if (mali_group_virtual_disable_if_empty(virtual_group)) {
+               MALI_DEBUG_PRINT(4, ("Disabling empty virtual group\n"));
+
+               MALI_DEBUG_ASSERT(VIRTUAL_GROUP_IDLE == virtual_group_state);
+
+               virtual_group_state = VIRTUAL_GROUP_DISABLED;
+       }
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_enable_empty_virtual(void)
+{
+       MALI_ASSERT_GROUP_LOCKED(virtual_group);
+
+       if (mali_group_virtual_enable_if_empty(virtual_group)) {
+               MALI_DEBUG_PRINT(4, ("Re-enabling empty virtual group\n"));
+
+               MALI_DEBUG_ASSERT(VIRTUAL_GROUP_DISABLED == virtual_group_state);
+
+               virtual_group_state = VIRTUAL_GROUP_IDLE;
+       }
+}
+
+static struct mali_pp_job *mali_pp_scheduler_get_job(struct mali_pp_scheduler_job_queue *queue)
+{
+       struct mali_pp_job *job = NULL;
+
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT_POINTER(queue);
+
+       /* Check if we have a normal priority job. */
+       if (!_mali_osk_list_empty(&queue->normal_pri)) {
+               MALI_DEBUG_ASSERT(queue->depth > 0);
+               job = _MALI_OSK_LIST_ENTRY(queue->normal_pri.next, struct mali_pp_job, list);
+       }
+
+       /* Prefer normal priority job if it is in progress. */
+       if (NULL != job && 0 < job->sub_jobs_started) {
+               return job;
+       }
+
+       /* Check if we have a high priority job. */
+       if (!_mali_osk_list_empty(&queue->high_pri)) {
+               MALI_DEBUG_ASSERT(queue->depth > 0);
+               job = _MALI_OSK_LIST_ENTRY(queue->high_pri.next, struct mali_pp_job, list);
+       }
+
+       return job;
+}
+
+/**
+ * Returns a physical job if a physical job is ready to run
+ */
+MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_physical_job(void)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       return mali_pp_scheduler_get_job(&job_queue);
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_physical_job(struct mali_pp_job *job)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT(job_queue.depth > 0);
+
+       /* Remove job from queue */
+       if (!mali_pp_job_has_unstarted_sub_jobs(job)) {
+               /* All sub jobs have been started: remove job from queue */
+               _mali_osk_list_delinit(&job->list);
+               _mali_osk_list_delinit(&job->session_fb_lookup_list);
+       }
+
+       --job_queue.depth;
+}
+
+/**
+ * Returns a virtual job if a virtual job is ready to run
+ */
+MALI_STATIC_INLINE struct mali_pp_job *mali_pp_scheduler_get_virtual_job(void)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT_POINTER(virtual_group);
+       return mali_pp_scheduler_get_job(&virtual_job_queue);
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_dequeue_virtual_job(struct mali_pp_job *job)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT(virtual_job_queue.depth > 0);
+
+       /* Remove job from queue */
+       _mali_osk_list_delinit(&job->list);
+       _mali_osk_list_delinit(&job->session_fb_lookup_list);
+       --virtual_job_queue.depth;
+}
+
+/**
+ * Checks if the criteria is met for removing a physical core from virtual group
+ */
+MALI_STATIC_INLINE mali_bool mali_pp_scheduler_can_move_virtual_to_physical(void)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+       MALI_DEBUG_ASSERT(mali_pp_scheduler_has_virtual_group());
+       MALI_ASSERT_GROUP_LOCKED(virtual_group);
+       /*
+        * The criteria for taking out a physical group from a virtual group are the following:
+        * - There virtual group is idle
+        * - There are currently no physical groups (idle and working)
+        * - There are physical jobs to be scheduled
+        */
+       return (VIRTUAL_GROUP_IDLE == virtual_group_state) &&
+              _mali_osk_list_empty(&group_list_idle) &&
+              _mali_osk_list_empty(&group_list_working) &&
+              (NULL != mali_pp_scheduler_get_physical_job());
+}
+
+MALI_STATIC_INLINE struct mali_group *mali_pp_scheduler_acquire_physical_group(void)
+{
+       MALI_ASSERT_PP_SCHEDULER_LOCKED();
+
+       if (!_mali_osk_list_empty(&group_list_idle)) {
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from idle list.\n"));
+               return _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list);
+       } else if (mali_pp_scheduler_has_virtual_group()) {
+               MALI_ASSERT_GROUP_LOCKED(virtual_group);
+               if (mali_pp_scheduler_can_move_virtual_to_physical()) {
+                       struct mali_group *group;
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquiring physical group from virtual group.\n"));
+                       group = mali_group_acquire_group(virtual_group);
+
+                       if (mali_pp_scheduler_has_virtual_group()) {
+                               mali_pp_scheduler_disable_empty_virtual();
+                       }
+
+                       return group;
+               }
+       }
+
+       return NULL;
+}
+
+static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job, mali_bool deferred)
+{
+       if (MALI_FALSE == mali_pp_job_use_no_notification(job)) {
+               u32 i;
+               u32 num_counters_to_copy;
+               mali_bool success = mali_pp_job_was_success(job);
+
+               _mali_uk_pp_job_finished_s *jobres = job->finished_notification->result_buffer;
+               _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */
+               jobres->user_job_ptr = mali_pp_job_get_user_id(job);
+               if (MALI_TRUE == success) {
+                       jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS;
+               } else {
+                       jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR;
+               }
+
+               if (mali_pp_job_is_virtual(job)) {
+                       num_counters_to_copy = num_cores; /* Number of physical cores available */
+               } else {
+                       num_counters_to_copy = mali_pp_job_get_sub_job_count(job);
+               }
+
+               for (i = 0; i < num_counters_to_copy; i++) {
+                       jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i);
+                       jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i);
+                       jobres->perf_counter_src0 = mali_pp_job_get_pp_counter_global_src0();
+                       jobres->perf_counter_src1 = mali_pp_job_get_pp_counter_global_src1();
+               }
+
+               mali_session_send_notification(mali_pp_job_get_session(job), job->finished_notification);
+               job->finished_notification = NULL;
+       }
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+       if (MALI_TRUE == deferred) {
+               /* The deletion of the job object (releasing sync refs etc) must be done in a different context */
+               mali_pp_scheduler_deferred_job_delete(job);
+       } else {
+               mali_pp_job_delete(job);
+       }
+#else
+       MALI_DEBUG_ASSERT(MALI_FALSE == deferred); /* no use cases need this in this configuration */
+       mali_pp_job_delete(job);
+#endif
+}
+
+static void mali_pp_scheduler_finalize_job(struct mali_pp_job * job)
+{
+       /* This job object should not be on any lists. */
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list));
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->session_list));
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->session_fb_lookup_list));
+
+       /* Send notification back to user space */
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+       mali_pp_scheduler_return_job_to_user(job, MALI_TRUE);
+#else
+       mali_pp_scheduler_return_job_to_user(job, MALI_FALSE);
+#endif
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       if (_MALI_PP_JOB_FLAG_IS_WINDOW_SURFACE & job->uargs.flags) {
+               _mali_osk_atomic_inc(&job->session->number_of_window_jobs);
+       }
+#endif
+
+       mali_pp_scheduler_job_completed();
+}
+
+void mali_pp_scheduler_schedule(void)
+{
+       struct mali_group* physical_groups_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS - 1];
+       struct mali_pp_job* physical_jobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS - 1];
+       u32 physical_sub_jobs_to_start[MALI_MAX_NUMBER_OF_PP_GROUPS - 1];
+       int num_physical_jobs_to_start = 0;
+       int i;
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               /* Lock the virtual group since we might have to grab physical groups. */
+               mali_group_lock(virtual_group);
+       }
+
+       mali_pp_scheduler_lock();
+       if (pause_count > 0) {
+               /* Scheduler is suspended, don't schedule any jobs. */
+               mali_pp_scheduler_unlock();
+               if (mali_pp_scheduler_has_virtual_group()) {
+                       mali_group_unlock(virtual_group);
+               }
+               return;
+       }
+
+       /* Find physical job(s) to schedule first. */
+       while (1) {
+               struct mali_group *group;
+               struct mali_pp_job *job;
+               u32 sub_job;
+
+               job = mali_pp_scheduler_get_physical_job();
+               if (NULL == job) {
+                       break; /* No job, early out. */
+               }
+
+               if (mali_scheduler_hint_is_enabled(MALI_SCHEDULER_HINT_GP_BOUND) &&
+                   mali_pp_job_is_large_and_unstarted(job) && !_mali_osk_list_empty(&group_list_working)) {
+                       /* Since not all groups are idle, don't schedule yet. */
+                       break;
+               }
+
+               MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual(job));
+               MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
+               MALI_DEBUG_ASSERT(1 <= mali_pp_job_get_sub_job_count(job));
+
+               /* Acquire a physical group, either from the idle list or from the virtual group.
+                * In case the group was acquired from the virtual group, it's state will be
+                * LEAVING_VIRTUAL and must be set to IDLE before it can be used. */
+               group = mali_pp_scheduler_acquire_physical_group();
+               if (NULL == group) {
+                       /* Could not get a group to run the job on, early out. */
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: No more physical groups available.\n"));
+                       break;
+               }
+
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Acquired physical group %p.\n", group));
+
+               /* Mark sub job as started. */
+               sub_job = mali_pp_job_get_first_unstarted_sub_job(job);
+               mali_pp_job_mark_sub_job_started(job, sub_job);
+
+               /* Remove job from queue (if this was the last sub job). */
+               mali_pp_scheduler_dequeue_physical_job(job);
+
+               /* Move group to working list. */
+               _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_working);
+
+               /* Keep track of this group, so that we actually can start the job once we are done with the scheduler lock we are now holding. */
+               physical_groups_to_start[num_physical_jobs_to_start] = group;
+               physical_jobs_to_start[num_physical_jobs_to_start] = job;
+               physical_sub_jobs_to_start[num_physical_jobs_to_start] = sub_job;
+               ++num_physical_jobs_to_start;
+
+               MALI_DEBUG_ASSERT(num_physical_jobs_to_start < MALI_MAX_NUMBER_OF_PP_GROUPS);
+       }
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               if (VIRTUAL_GROUP_IDLE == virtual_group_state) {
+                       /* We have a virtual group and it is idle. */
+
+                       struct mali_pp_job *job;
+
+                       /* Find a virtual job we can start. */
+                       job = mali_pp_scheduler_get_virtual_job();
+
+                       if (NULL != job) {
+                               MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job));
+                               MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
+                               MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job));
+
+                               /* Mark the one and only sub job as started. */
+                               mali_pp_job_mark_sub_job_started(job, 0);
+
+                               /* Remove job from queue. */
+                               mali_pp_scheduler_dequeue_virtual_job(job);
+
+                               /* Virtual group is now working. */
+                               virtual_group_state = VIRTUAL_GROUP_WORKING;
+
+                               /* We no longer need the scheduler lock, but we still need the virtual lock
+                                * in order to start the virtual job. */
+                               mali_pp_scheduler_unlock();
+
+                               /* Start job. */
+                               mali_group_start_pp_job(virtual_group, job, 0);
+
+                               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from schedule).\n",
+                                                    mali_pp_job_get_id(job), job, 1,
+                                                    mali_pp_job_get_sub_job_count(job)));
+
+                               mali_group_unlock(virtual_group);
+                       } else {
+                               /* No virtual job to start. */
+                               mali_pp_scheduler_unlock();
+                               mali_group_unlock(virtual_group);
+                       }
+               } else {
+                       /* We have a virtual group, but it is busy or disabled. */
+                       MALI_DEBUG_ASSERT(VIRTUAL_GROUP_IDLE != virtual_group_state);
+
+                       mali_pp_scheduler_unlock();
+                       mali_group_unlock(virtual_group);
+               }
+       } else {
+               /* There is no virtual group. */
+               mali_pp_scheduler_unlock();
+       }
+
+       /* We have now released the scheduler lock, and we are ready to start the physical jobs.
+        * The reason we want to wait until we have released the scheduler lock is that job start
+        * may take quite a bit of time (many registers have to be written). This will allow new
+        * jobs from user space to come in, and post-processing of other PP jobs to happen at the
+        * same time as we start jobs. */
+       for (i = 0; i < num_physical_jobs_to_start; i++) {
+               struct mali_group *group = physical_groups_to_start[i];
+               struct mali_pp_job *job  = physical_jobs_to_start[i];
+               u32 sub_job              = physical_sub_jobs_to_start[i];
+
+               MALI_DEBUG_ASSERT_POINTER(group);
+               MALI_DEBUG_ASSERT_POINTER(job);
+               MALI_DEBUG_ASSERT(!mali_group_is_virtual(group));
+               MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual(job));
+
+               mali_group_lock(group);
+
+               /* Set state to IDLE if group was acquired from the virtual group. */
+               group->state = MALI_GROUP_STATE_IDLE;
+
+               mali_group_start_pp_job(group, job, sub_job);
+
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from schedule).\n",
+                                    mali_pp_job_get_id(job), job, sub_job + 1,
+                                    mali_pp_job_get_sub_job_count(job)));
+
+               mali_group_unlock(group);
+       }
+}
+
+/**
+ * Set group idle.
+ *
+ * If @ref group is the virtual group, nothing is done since the virtual group should be idle
+ * already.
+ *
+ * If @ref group is a physical group we rejoin the virtual group, if it exists.  If not, we move the
+ * physical group to the idle list.
+ *
+ * @note The group and the scheduler must both be locked when entering this function.  Both will be
+ * unlocked before exiting.
+ *
+ * @param group The group to set idle.
+ */
+static void mali_pp_scheduler_set_group_idle_and_unlock(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT_LOCK_HELD(pp_scheduler_lock);
+
+       if (mali_group_is_virtual(group)) {
+               /* The virtual group should have been set to non-working already. */
+               MALI_DEBUG_ASSERT(VIRTUAL_GROUP_IDLE == virtual_group_state);
+
+               mali_pp_scheduler_unlock();
+               mali_group_unlock(group);
+
+               return;
+       } else {
+               if (mali_pp_scheduler_has_virtual_group()) {
+                       /* Rejoin virtual group. */
+
+                       /* We're no longer needed on the scheduler list. */
+                       _mali_osk_list_delinit(&(group->pp_scheduler_list));
+
+                       /* Make sure no interrupts are handled for this group during the transition
+                        * from physical to virtual. */
+                       group->state = MALI_GROUP_STATE_JOINING_VIRTUAL;
+
+                       mali_pp_scheduler_unlock();
+                       mali_group_unlock(group);
+
+                       mali_group_lock(virtual_group);
+
+                       if (mali_pp_scheduler_has_virtual_group()) {
+                               mali_pp_scheduler_enable_empty_virtual();
+                       }
+
+                       /* We need to recheck the group state since it is possible that someone has
+                        * modified the group before we locked the virtual group. */
+                       if (MALI_GROUP_STATE_JOINING_VIRTUAL == group->state) {
+                               mali_group_add_group(virtual_group, group, MALI_TRUE);
+                       }
+
+                       mali_group_unlock(virtual_group);
+               } else {
+                       /* Move physical group back to idle list. */
+                       _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle);
+
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+                       trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), 0, 0, 0);
+#endif
+
+                       mali_pp_scheduler_unlock();
+                       mali_group_unlock(group);
+               }
+       }
+}
+
+/**
+ * Schedule job on locked group.
+ *
+ * @note The group and the scheduler must both be locked when entering this function.  Both will be
+ * unlocked before exiting.
+ *
+ * @param group The group to schedule on.
+ */
+static void mali_pp_scheduler_schedule_on_group_and_unlock(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       MALI_DEBUG_ASSERT_LOCK_HELD(pp_scheduler_lock);
+
+       if (mali_group_is_virtual(group)) {
+               /* Now that the virtual group is idle, check if we should reconfigure. */
+
+               struct mali_pp_job *virtual_job = NULL;
+               struct mali_pp_job *physical_job = NULL;
+               struct mali_group *physical_group = NULL;
+               u32 physical_sub_job = 0;
+
+               MALI_DEBUG_ASSERT(VIRTUAL_GROUP_IDLE == virtual_group_state);
+
+               if (mali_pp_scheduler_can_move_virtual_to_physical()) {
+                       /* There is a runnable physical job and we can acquire a physical group. */
+                       physical_job = mali_pp_scheduler_get_physical_job();
+                       MALI_DEBUG_ASSERT_POINTER(physical_job);
+                       MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(physical_job));
+
+                       /* Mark sub job as started. */
+                       physical_sub_job = mali_pp_job_get_first_unstarted_sub_job(physical_job);
+                       mali_pp_job_mark_sub_job_started(physical_job, physical_sub_job);
+
+                       /* Remove job from queue (if this was the last sub job). */
+                       mali_pp_scheduler_dequeue_physical_job(physical_job);
+
+                       /* Acquire a physical group from the virtual group.  Its state will
+                        * be LEAVING_VIRTUAL and must be set to IDLE before it can be
+                        * used. */
+                       physical_group = mali_group_acquire_group(virtual_group);
+
+                       /* Move physical group to the working list, as we will soon start a job on it. */
+                       _mali_osk_list_move(&(physical_group->pp_scheduler_list), &group_list_working);
+
+                       mali_pp_scheduler_disable_empty_virtual();
+               }
+
+               /* Get next virtual job. */
+               virtual_job = mali_pp_scheduler_get_virtual_job();
+               if (NULL != virtual_job && VIRTUAL_GROUP_IDLE == virtual_group_state) {
+                       /* There is a runnable virtual job. */
+
+                       MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(virtual_job));
+                       MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(virtual_job));
+                       MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(virtual_job));
+
+                       mali_pp_job_mark_sub_job_started(virtual_job, 0);
+
+                       /* Remove job from queue. */
+                       mali_pp_scheduler_dequeue_virtual_job(virtual_job);
+
+                       /* Virtual group is now working. */
+                       virtual_group_state = VIRTUAL_GROUP_WORKING;
+
+                       mali_pp_scheduler_unlock();
+
+                       /* Start job. */
+                       mali_group_start_pp_job(group, virtual_job, 0);
+
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Virtual job %u (0x%08X) part %u/%u started (from job_done).\n",
+                                            mali_pp_job_get_id(virtual_job), virtual_job, 1,
+                                            mali_pp_job_get_sub_job_count(virtual_job)));
+               } else {
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+                       trace_gpu_sched_switch("Mali_Virtual_PP", sched_clock(), 0, 0, 0);
+#endif
+
+                       mali_pp_scheduler_unlock();
+               }
+
+               /* Releasing the virtual group lock that was held when entering the function. */
+               mali_group_unlock(group);
+
+               /* Start a physical job (if we acquired a physical group earlier). */
+               if (NULL != physical_job && NULL != physical_group) {
+                       mali_group_lock(physical_group);
+
+                       /* Change the group state from LEAVING_VIRTUAL to IDLE to complete the transition. */
+                       physical_group->state = MALI_GROUP_STATE_IDLE;
+
+                       /* Start job. */
+                       mali_group_start_pp_job(physical_group, physical_job, physical_sub_job);
+
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done).\n",
+                                            mali_pp_job_get_id(physical_job), physical_job, physical_sub_job + 1,
+                                            mali_pp_job_get_sub_job_count(physical_job)));
+
+                       mali_group_unlock(physical_group);
+               }
+       } else {
+               /* Physical group. */
+               struct mali_pp_job *job = NULL;
+               u32 sub_job = 0;
+
+               job = mali_pp_scheduler_get_physical_job();
+               if (NULL != job) {
+                       /* There is a runnable physical job. */
+                       MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job));
+
+                       /* Mark sub job as started. */
+                       sub_job = mali_pp_job_get_first_unstarted_sub_job(job);
+                       mali_pp_job_mark_sub_job_started(job, sub_job);
+
+                       /* Remove job from queue (if this was the last sub job). */
+                       mali_pp_scheduler_dequeue_physical_job(job);
+
+                       mali_pp_scheduler_unlock();
+
+                       /* Group is already on the working list, so start the new job. */
+                       mali_group_start_pp_job(group, job, sub_job);
+
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Physical job %u (0x%08X) part %u/%u started (from job_done).\n",
+                                            mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job)));
+
+                       mali_group_unlock(group);
+               } else {
+                       mali_pp_scheduler_set_group_idle_and_unlock(group);
+               }
+       }
+}
+
+void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success, mali_bool in_upper_half)
+{
+       mali_bool job_is_done = MALI_FALSE;
+       mali_bool schedule_on_group = MALI_FALSE;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) part %u/%u completed (%s).\n",
+                            mali_pp_job_is_virtual(job) ? "Virtual" : "Physical",
+                            mali_pp_job_get_id(job),
+                            job, sub_job + 1,
+                            mali_pp_job_get_sub_job_count(job),
+                            success ? "success" : "failure"));
+
+       MALI_ASSERT_GROUP_LOCKED(group);
+       mali_pp_scheduler_lock();
+
+       mali_pp_job_mark_sub_job_completed(job, success);
+
+       MALI_DEBUG_ASSERT(mali_pp_job_is_virtual(job) == mali_group_is_virtual(group));
+
+       job_is_done = mali_pp_job_is_complete(job);
+
+       if (job_is_done) {
+               /* Job is removed from these lists when the last sub job is scheduled. */
+               MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list));
+               MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->session_fb_lookup_list));
+
+               /* Remove job from session list. */
+               _mali_osk_list_delinit(&job->session_list);
+
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for %s job %u (0x%08X).\n",
+                                    mali_pp_job_is_virtual(job) ? "virtual" : "physical",
+                                    mali_pp_job_get_id(job), job));
+
+               mali_pp_scheduler_unlock();
+
+               /* Release tracker.  If other trackers are waiting on this tracker, this could
+                * trigger activation.  The returned scheduling mask can be used to determine if we
+                * have to schedule GP, PP or both. */
+               schedule_mask = mali_timeline_tracker_release(&job->tracker);
+
+               mali_pp_scheduler_lock();
+       }
+
+       if (mali_group_is_virtual(group)) {
+               /* Obey the policy. */
+               virtual_group_state = VIRTUAL_GROUP_IDLE;
+       }
+
+       /* If paused, then this was the last job, so wake up sleeping workers and return. */
+       if (pause_count > 0) {
+               /* Wake up sleeping workers. Their wake-up condition is that
+                * num_slots == num_slots_idle, so unless we are done working, no
+                * threads will actually be woken up.
+                */
+               if (!mali_group_is_virtual(group)) {
+                       /* Move physical group to idle list. */
+                       _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle);
+               }
+
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+               trace_gpu_sched_switch(mali_pp_get_hw_core_desc(group->pp_core), sched_clock(), 0, 0, 0);
+#endif
+
+               _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue);
+
+               mali_pp_scheduler_unlock();
+               mali_group_unlock(group);
+
+               if (job_is_done) {
+                       /* Return job to user and delete it. */
+                       mali_pp_scheduler_finalize_job(job);
+               }
+
+               /* A GP job might be queued by tracker release above,
+                * make sure GP scheduler gets a chance to schedule this (if possible)
+                */
+               mali_scheduler_schedule_from_mask(schedule_mask & ~MALI_SCHEDULER_MASK_PP, in_upper_half);
+
+               return;
+       }
+
+       /* Since this group just finished running a job, we can reschedule a new job on it
+        * immediately. */
+
+       /* By default, don't schedule on group. */
+       schedule_on_group = MALI_FALSE;
+
+       if (mali_group_is_virtual(group)) {
+               /* Always schedule immediately on virtual group. */
+               schedule_mask &= ~MALI_SCHEDULER_MASK_PP;
+               schedule_on_group = MALI_TRUE;
+       } else if (0 < job_queue.depth && (!mali_scheduler_mask_is_set(schedule_mask, MALI_SCHEDULER_MASK_PP) || _mali_osk_list_empty(&group_list_idle))) {
+               struct mali_pp_job *next_job = NULL;
+
+               next_job = mali_pp_scheduler_get_physical_job();
+               MALI_DEBUG_ASSERT_POINTER(next_job);
+
+               /* If no new jobs have been queued or if this group is the only idle group, we can
+                * schedule immediately on this group, unless we are GP bound and the next job would
+                * benefit from all its sub jobs being started concurrently. */
+
+               if (mali_scheduler_hint_is_enabled(MALI_SCHEDULER_HINT_GP_BOUND) && mali_pp_job_is_large_and_unstarted(next_job)) {
+                       /* We are GP bound and the job would benefit from all sub jobs being started
+                        * concurrently.  Postpone scheduling until after group has been unlocked. */
+                       schedule_mask |= MALI_SCHEDULER_MASK_PP;
+                       schedule_on_group = MALI_FALSE;
+               } else {
+                       /* Schedule job immediately since we are not GP bound. */
+                       schedule_mask &= ~MALI_SCHEDULER_MASK_PP;
+                       schedule_on_group = MALI_TRUE;
+               }
+       }
+
+       if (schedule_on_group) {
+               /* Schedule a new job on this group. */
+               mali_pp_scheduler_schedule_on_group_and_unlock(group);
+       } else {
+               /* Set group idle.  Will rejoin virtual group, under appropriate conditions. */
+               mali_pp_scheduler_set_group_idle_and_unlock(group);
+       }
+
+       if (!schedule_on_group || MALI_SCHEDULER_MASK_EMPTY != schedule_mask) {
+               if (MALI_SCHEDULER_MASK_PP & schedule_mask) {
+                       /* Schedule PP directly. */
+                       mali_pp_scheduler_schedule();
+                       schedule_mask &= ~MALI_SCHEDULER_MASK_PP;
+               }
+
+               /* Schedule other jobs that were activated. */
+               mali_scheduler_schedule_from_mask(schedule_mask, in_upper_half);
+       }
+
+       if (job_is_done) {
+               /* Return job to user and delete it. */
+               mali_pp_scheduler_finalize_job(job);
+       }
+}
+
+void mali_pp_scheduler_suspend(void)
+{
+       mali_pp_scheduler_lock();
+       pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */
+       mali_pp_scheduler_unlock();
+
+       /* Go to sleep. When woken up again (in mali_pp_scheduler_job_done), the
+        * mali_pp_scheduler_suspended() function will be called. This will return true
+        * if state is idle and pause_count > 0, so if the core is active this
+        * will not do anything.
+        */
+       _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended, NULL);
+}
+
+void mali_pp_scheduler_resume(void)
+{
+       mali_pp_scheduler_lock();
+       pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
+       mali_pp_scheduler_unlock();
+       if (0 == pause_count) {
+               mali_pp_scheduler_schedule();
+       }
+}
+
+mali_timeline_point mali_pp_scheduler_submit_job(struct mali_session_data *session, struct mali_pp_job *job)
+{
+       mali_timeline_point point;
+       u32 fb_lookup_id = 0;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       mali_pp_scheduler_lock();
+
+       fb_lookup_id = mali_pp_job_get_fb_lookup_id(job);
+       MALI_DEBUG_ASSERT(MALI_PP_JOB_FB_LOOKUP_LIST_SIZE > fb_lookup_id);
+
+       /* Adding job to the lookup list used to quickly discard writeback units of queued jobs. */
+       _mali_osk_list_addtail(&job->session_fb_lookup_list, &session->pp_job_fb_lookup_list[fb_lookup_id]);
+
+       mali_pp_scheduler_unlock();
+
+       mali_pp_scheduler_job_queued();
+
+       /* Add job to Timeline system. */
+       point = mali_timeline_system_add_tracker(session->timeline_system, &job->tracker, MALI_TIMELINE_PP);
+
+       return point;
+}
+
+_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs)
+{
+       struct mali_session_data *session;
+       struct mali_pp_job *job;
+       mali_timeline_point point;
+       u32 __user *timeline_point_ptr = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(uargs);
+       MALI_DEBUG_ASSERT_POINTER(ctx);
+
+       session = (struct mali_session_data*)ctx;
+
+       job = mali_pp_job_create(session, uargs, mali_scheduler_get_new_id());
+       if (NULL == job) {
+               MALI_PRINT_ERROR(("Failed to create PP job.\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       timeline_point_ptr = (u32 __user *) job->uargs.timeline_point_ptr;
+
+       point = mali_pp_scheduler_submit_job(session, job);
+       job = NULL;
+
+       if (0 != _mali_osk_put_user(((u32) point), timeline_point_ptr)) {
+               /* Let user space know that something failed after the job was started. */
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_pp_and_gp_start_job(void *ctx, _mali_uk_pp_and_gp_start_job_s *uargs)
+{
+       struct mali_session_data *session;
+       _mali_uk_pp_and_gp_start_job_s kargs;
+       struct mali_pp_job *pp_job;
+       struct mali_gp_job *gp_job;
+       u32 __user *timeline_point_ptr = NULL;
+       mali_timeline_point point;
+
+       MALI_DEBUG_ASSERT_POINTER(ctx);
+       MALI_DEBUG_ASSERT_POINTER(uargs);
+
+       session = (struct mali_session_data *) ctx;
+
+       if (0 != _mali_osk_copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_and_gp_start_job_s))) {
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       pp_job = mali_pp_job_create(session, kargs.pp_args, mali_scheduler_get_new_id());
+       if (NULL == pp_job) {
+               MALI_PRINT_ERROR(("Failed to create PP job.\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       gp_job = mali_gp_job_create(session, kargs.gp_args, mali_scheduler_get_new_id(), mali_pp_job_get_tracker(pp_job));
+       if (NULL == gp_job) {
+               MALI_PRINT_ERROR(("Failed to create GP job.\n"));
+               mali_pp_job_delete(pp_job);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       timeline_point_ptr = (u32 __user *) pp_job->uargs.timeline_point_ptr;
+
+       /* Submit GP job. */
+       mali_gp_scheduler_submit_job(session, gp_job);
+       gp_job = NULL;
+
+       /* Submit PP job. */
+       point = mali_pp_scheduler_submit_job(session, pp_job);
+       pp_job = NULL;
+
+       if (0 != _mali_osk_put_user(((u32) point), timeline_point_ptr)) {
+               /* Let user space know that something failed after the jobs were started. */
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args)
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_DEBUG_ASSERT_POINTER(args->ctx);
+       args->number_of_total_cores = num_cores;
+       args->number_of_enabled_cores = enabled_cores;
+       return _MALI_OSK_ERR_OK;
+}
+
+u32 mali_pp_scheduler_get_num_cores_total(void)
+{
+       return num_cores;
+}
+
+u32 mali_pp_scheduler_get_num_cores_enabled(void)
+{
+       return enabled_cores;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args)
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_DEBUG_ASSERT_POINTER(args->ctx);
+       args->version = pp_version;
+       return _MALI_OSK_ERR_OK;
+}
+
+void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args)
+{
+       struct mali_session_data *session;
+       struct mali_pp_job *job;
+       struct mali_pp_job *tmp;
+       u32 fb_lookup_id;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_DEBUG_ASSERT_POINTER(args->ctx);
+
+       session = (struct mali_session_data*)args->ctx;
+
+       fb_lookup_id = args->fb_id & MALI_PP_JOB_FB_LOOKUP_LIST_MASK;
+
+       mali_pp_scheduler_lock();
+
+       /* Iterate over all jobs for given frame builder_id. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &session->pp_job_fb_lookup_list[fb_lookup_id], struct mali_pp_job, session_fb_lookup_list) {
+               MALI_DEBUG_CODE(u32 disable_mask = 0);
+
+               if (mali_pp_job_get_frame_builder_id(job) == (u32) args->fb_id) {
+                       MALI_DEBUG_CODE(disable_mask |= 0xD<<(4*3));
+                       if (args->wb0_memory == job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_ADDR/sizeof(u32)]) {
+                               MALI_DEBUG_CODE(disable_mask |= 0x1<<(4*1));
+                               mali_pp_job_disable_wb0(job);
+                       }
+                       if (args->wb1_memory == job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_ADDR/sizeof(u32)]) {
+                               MALI_DEBUG_CODE(disable_mask |= 0x2<<(4*2));
+                               mali_pp_job_disable_wb1(job);
+                       }
+                       if (args->wb2_memory == job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_ADDR/sizeof(u32)]) {
+                               MALI_DEBUG_CODE(disable_mask |= 0x3<<(4*3));
+                               mali_pp_job_disable_wb2(job);
+                       }
+                       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Disable WB: 0x%X.\n", disable_mask));
+               } else {
+                       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Disable WB mismatching FB.\n"));
+               }
+       }
+
+       mali_pp_scheduler_unlock();
+}
+
+void mali_pp_scheduler_abort_session(struct mali_session_data *session)
+{
+       u32 i = 0;
+       struct mali_pp_job *job, *tmp_job;
+       struct mali_group *group, *tmp_group;
+       struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS];
+       _MALI_OSK_LIST_HEAD_STATIC_INIT(removed_jobs);
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_ASSERT(session->is_aborting);
+
+       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08X.\n", session));
+
+       mali_pp_scheduler_lock();
+
+       /* Find all jobs from the aborting session. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &session->pp_job_list, struct mali_pp_job, session_list) {
+               /* Remove job from queue. */
+               if (mali_pp_job_is_virtual(job)) {
+                       MALI_DEBUG_ASSERT(1 == mali_pp_job_get_sub_job_count(job));
+                       if (0 == mali_pp_job_get_first_unstarted_sub_job(job)) {
+                               --virtual_job_queue.depth;
+                       }
+               } else {
+                       job_queue.depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job);
+               }
+
+               _mali_osk_list_delinit(&job->list);
+               _mali_osk_list_delinit(&job->session_fb_lookup_list);
+
+               mali_pp_job_mark_unstarted_failed(job);
+
+               if (mali_pp_job_is_complete(job)) {
+                       /* Job is complete, remove from session list. */
+                       _mali_osk_list_delinit(&job->session_list);
+
+                       /* Move job to local list for release and deletion. */
+                       _mali_osk_list_add(&job->list, &removed_jobs);
+
+                       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborted PP job %u (0x%08X).\n", mali_pp_job_get_id(job), job));
+               } else {
+                       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Keeping partially started PP job %u (0x%08X) in session.\n", mali_pp_job_get_id(job), job));
+               }
+       }
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_working, struct mali_group, pp_scheduler_list) {
+               groups[i++] = group;
+       }
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, tmp_group, &group_list_idle, struct mali_group, pp_scheduler_list) {
+               groups[i++] = group;
+       }
+
+       mali_pp_scheduler_unlock();
+
+       /* Release and delete all found jobs from the aborting session. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp_job, &removed_jobs, struct mali_pp_job, list) {
+               mali_timeline_tracker_release(&job->tracker);
+               mali_pp_job_delete(job);
+               mali_pp_scheduler_job_completed();
+       }
+
+       /* Abort any running jobs from the session. */
+       while (i > 0) {
+               mali_group_abort_session(groups[--i], session);
+       }
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               mali_group_abort_session(virtual_group, session);
+       }
+}
+
+static mali_bool mali_pp_scheduler_is_suspended(void *data)
+{
+       mali_bool ret;
+
+       /* This callback does not use the data pointer. */
+       MALI_IGNORE(data);
+
+       mali_pp_scheduler_lock();
+
+       ret = pause_count > 0
+             && _mali_osk_list_empty(&group_list_working)
+             && VIRTUAL_GROUP_WORKING != virtual_group_state;
+
+       mali_pp_scheduler_unlock();
+
+       return ret;
+}
+
+struct mali_pp_core *mali_pp_scheduler_get_virtual_pp(void)
+{
+       if (mali_pp_scheduler_has_virtual_group()) {
+               return mali_group_get_pp_core(virtual_group);
+       } else {
+               return NULL;
+       }
+}
+
+#if MALI_STATE_TRACKING
+u32 mali_pp_scheduler_dump_state(char *buf, u32 size)
+{
+       int n = 0;
+       struct mali_group *group;
+       struct mali_group *temp;
+
+       n += _mali_osk_snprintf(buf + n, size - n, "PP:\n");
+       n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue.normal_pri) ? "empty" : "not empty");
+       n += _mali_osk_snprintf(buf + n, size - n, "\tHigh priority queue is %s\n", _mali_osk_list_empty(&job_queue.high_pri) ? "empty" : "not empty");
+       n += _mali_osk_snprintf(buf + n, size - n, "\n");
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list) {
+               n += mali_group_dump_state(group, buf + n, size - n);
+       }
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) {
+               n += mali_group_dump_state(group, buf + n, size - n);
+       }
+
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_disabled, struct mali_group, pp_scheduler_list) {
+               n += mali_group_dump_state(group, buf + n, size - n);
+       }
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               n += mali_group_dump_state(virtual_group, buf + n, size -n);
+       }
+
+       n += _mali_osk_snprintf(buf + n, size - n, "\n");
+       return n;
+}
+#endif
+
+/* This function is intended for power on reset of all cores.
+ * No locking is done for the list iteration, which can only be safe if the
+ * scheduler is paused and all cores idle. That is always the case on init and
+ * power on. */
+void mali_pp_scheduler_reset_all_groups(void)
+{
+       struct mali_group *group, *temp;
+       struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS];
+       s32 i = 0;
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               mali_group_lock(virtual_group);
+               mali_group_reset(virtual_group);
+               mali_group_unlock(virtual_group);
+       }
+
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+       MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state);
+       mali_pp_scheduler_lock();
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list) {
+               groups[i++] = group;
+       }
+       mali_pp_scheduler_unlock();
+
+       while (i > 0) {
+               group = groups[--i];
+
+               mali_group_lock(group);
+               mali_group_reset(group);
+               mali_group_unlock(group);
+       }
+}
+
+void mali_pp_scheduler_zap_all_active(struct mali_session_data *session)
+{
+       struct mali_group *group, *temp;
+       struct mali_group *groups[MALI_MAX_NUMBER_OF_GROUPS];
+       s32 i = 0;
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               mali_group_zap_session(virtual_group, session);
+       }
+
+       mali_pp_scheduler_lock();
+       _MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_working, struct mali_group, pp_scheduler_list) {
+               groups[i++] = group;
+       }
+       mali_pp_scheduler_unlock();
+
+       while (i > 0) {
+               mali_group_zap_session(groups[--i], session);
+       }
+}
+
+/* A pm reference must be taken with _mali_osk_pm_dev_ref_add_no_power_on
+ * before calling this function to avoid Mali powering down as HW is accessed.
+ */
+static void mali_pp_scheduler_enable_group_internal(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       mali_group_lock(group);
+
+       if (MALI_GROUP_STATE_DISABLED != group->state) {
+               mali_group_unlock(group);
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: PP group %p already enabled.\n", group));
+               return;
+       }
+
+       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Enabling PP group %p.\n", group));
+
+       mali_pp_scheduler_lock();
+
+       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state);
+       ++enabled_cores;
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               mali_bool update_hw;
+
+               /* Add group to virtual group. */
+               _mali_osk_list_delinit(&(group->pp_scheduler_list));
+               group->state = MALI_GROUP_STATE_JOINING_VIRTUAL;
+
+               mali_pp_scheduler_unlock();
+               mali_group_unlock(group);
+
+               mali_group_lock(virtual_group);
+
+               update_hw = mali_pm_is_power_on();
+               /* Get ref of group domain */
+               mali_group_get_pm_domain_ref(group);
+
+               MALI_DEBUG_ASSERT(NULL == group->pm_domain ||
+                                 MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(group->pm_domain));
+
+               if (update_hw) {
+                       mali_group_lock(group);
+                       mali_group_power_on_group(group);
+                       mali_group_reset(group);
+                       mali_group_unlock(group);
+               }
+
+               mali_pp_scheduler_enable_empty_virtual();
+               mali_group_add_group(virtual_group, group, update_hw);
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Done enabling group %p. Added to virtual group.\n", group));
+
+               mali_group_unlock(virtual_group);
+       } else {
+               /* Get ref of group domain */
+               mali_group_get_pm_domain_ref(group);
+
+               MALI_DEBUG_ASSERT(NULL == group->pm_domain ||
+                                 MALI_PM_DOMAIN_ON == mali_pm_domain_state_get(group->pm_domain));
+
+               /* Put group on idle list. */
+               if (mali_pm_is_power_on()) {
+                       mali_group_power_on_group(group);
+                       mali_group_reset(group);
+               }
+
+               _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle);
+               group->state = MALI_GROUP_STATE_IDLE;
+
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Done enabling group %p. Now on idle list.\n", group));
+               mali_pp_scheduler_unlock();
+               mali_group_unlock(group);
+       }
+}
+
+void mali_pp_scheduler_enable_group(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       _mali_osk_pm_dev_ref_add_no_power_on();
+
+       mali_pp_scheduler_enable_group_internal(group);
+
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+
+       /* Pick up any jobs that might have been queued if all PP groups were disabled. */
+       mali_pp_scheduler_schedule();
+}
+
+static void mali_pp_scheduler_disable_group_internal(struct mali_group *group)
+{
+       if (mali_pp_scheduler_has_virtual_group()) {
+               mali_group_lock(virtual_group);
+
+               MALI_DEBUG_ASSERT(VIRTUAL_GROUP_WORKING != virtual_group_state);
+               if (MALI_GROUP_STATE_JOINING_VIRTUAL == group->state) {
+                       /* The group was in the process of being added to the virtual group.  We
+                        * only need to change the state to reverse this. */
+                       group->state = MALI_GROUP_STATE_LEAVING_VIRTUAL;
+               } else if (MALI_GROUP_STATE_IN_VIRTUAL == group->state) {
+                       /* Remove group from virtual group.  The state of the group will be
+                        * LEAVING_VIRTUAL and the group will not be on any scheduler list. */
+                       mali_group_remove_group(virtual_group, group);
+
+                       mali_pp_scheduler_disable_empty_virtual();
+               }
+
+               mali_group_unlock(virtual_group);
+       }
+
+       mali_group_lock(group);
+       mali_pp_scheduler_lock();
+
+       MALI_DEBUG_ASSERT(   MALI_GROUP_STATE_IDLE            == group->state
+                            || MALI_GROUP_STATE_LEAVING_VIRTUAL == group->state
+                            || MALI_GROUP_STATE_DISABLED        == group->state);
+
+       if (MALI_GROUP_STATE_DISABLED == group->state) {
+               MALI_DEBUG_PRINT(4, ("Mali PP scheduler: PP group %p already disabled.\n", group));
+       } else {
+               MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Disabling PP group %p.\n", group));
+
+               --enabled_cores;
+               _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_disabled);
+               group->state = MALI_GROUP_STATE_DISABLED;
+
+               mali_group_power_off_group(group, MALI_TRUE);
+               mali_group_put_pm_domain_ref(group);
+       }
+
+       mali_pp_scheduler_unlock();
+       mali_group_unlock(group);
+}
+
+void mali_pp_scheduler_disable_group(struct mali_group *group)
+{
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       mali_pp_scheduler_suspend();
+
+       _mali_osk_pm_dev_ref_add_no_power_on();
+
+       mali_pp_scheduler_disable_group_internal(group);
+
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+
+       mali_pp_scheduler_resume();
+}
+
+static void mali_pp_scheduler_notify_core_change(u32 num_cores)
+{
+       mali_bool done = MALI_FALSE;
+
+       if (mali_is_mali450()) {
+               return;
+       }
+
+       /*
+        * This function gets a bit complicated because we can't hold the session lock while
+        * allocating notification objects.
+        */
+
+       while (!done) {
+               u32 i;
+               u32 num_sessions_alloc;
+               u32 num_sessions_with_lock;
+               u32 used_notification_objects = 0;
+               _mali_osk_notification_t **notobjs;
+
+               /* Pre allocate the number of notifications objects we need right now (might change after lock has been taken) */
+               num_sessions_alloc = mali_session_get_count();
+               if (0 == num_sessions_alloc) {
+                       /* No sessions to report to */
+                       return;
+               }
+
+               notobjs = (_mali_osk_notification_t **)_mali_osk_malloc(sizeof(_mali_osk_notification_t *) * num_sessions_alloc);
+               if (NULL == notobjs) {
+                       MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change (alloc failure)\n"));
+                       /* there is probably no point in trying again, system must be really low on memory and probably unusable now anyway */
+                       return;
+               }
+
+               for (i = 0; i < num_sessions_alloc; i++) {
+                       notobjs[i] = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_NUM_CORE_CHANGE, sizeof(_mali_uk_pp_num_cores_changed_s));
+                       if (NULL != notobjs[i]) {
+                               _mali_uk_pp_num_cores_changed_s *data = notobjs[i]->result_buffer;
+                               data->number_of_enabled_cores = num_cores;
+                       } else {
+                               MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change (alloc failure %u)\n", i));
+                       }
+               }
+
+               mali_session_lock();
+
+               /* number of sessions will not change while we hold the lock */
+               num_sessions_with_lock = mali_session_get_count();
+
+               if (num_sessions_alloc >= num_sessions_with_lock) {
+                       /* We have allocated enough notification objects for all the sessions atm */
+                       struct mali_session_data *session, *tmp;
+                       MALI_SESSION_FOREACH(session, tmp, link) {
+                               MALI_DEBUG_ASSERT(used_notification_objects < num_sessions_alloc);
+                               if (NULL != notobjs[used_notification_objects]) {
+                                       mali_session_send_notification(session, notobjs[used_notification_objects]);
+                                       notobjs[used_notification_objects] = NULL; /* Don't track this notification object any more */
+                               }
+                               used_notification_objects++;
+                       }
+                       done = MALI_TRUE;
+               }
+
+               mali_session_unlock();
+
+               /* Delete any remaining/unused notification objects */
+               for (; used_notification_objects < num_sessions_alloc; used_notification_objects++) {
+                       if (NULL != notobjs[used_notification_objects]) {
+                               _mali_osk_notification_delete(notobjs[used_notification_objects]);
+                       }
+               }
+
+               _mali_osk_free(notobjs);
+       }
+}
+
+static void mali_pp_scheduler_core_scale_up(unsigned int target_core_nr)
+{
+       MALI_DEBUG_PRINT(2, ("Requesting %d cores: enabling %d cores\n", target_core_nr, target_core_nr - enabled_cores));
+
+       _mali_osk_pm_dev_ref_add_no_power_on();
+       _mali_osk_pm_dev_barrier();
+
+       while (target_core_nr > enabled_cores) {
+               /*
+                * If there are any cores which do not belong to any domain,
+                * then these will always be found at the head of the list and
+                * we'll thus enabled these first.
+                */
+
+               mali_pp_scheduler_lock();
+
+               if (!_mali_osk_list_empty(&group_list_disabled)) {
+                       struct mali_group *group;
+
+                       group = _MALI_OSK_LIST_ENTRY(group_list_disabled.next, struct mali_group, pp_scheduler_list);
+
+                       MALI_DEBUG_ASSERT_POINTER(group);
+                       MALI_DEBUG_ASSERT(MALI_GROUP_STATE_DISABLED == group->state);
+
+                       mali_pp_scheduler_unlock();
+
+                       mali_pp_scheduler_enable_group_internal(group);
+               } else {
+                       mali_pp_scheduler_unlock();
+                       break; /* no more groups on disabled list */
+               }
+       }
+
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+
+       mali_pp_scheduler_schedule();
+}
+
+static void mali_pp_scheduler_core_scale_down(unsigned int target_core_nr)
+{
+       MALI_DEBUG_PRINT(2, ("Requesting %d cores: disabling %d cores\n", target_core_nr, enabled_cores - target_core_nr));
+
+       mali_pp_scheduler_suspend();
+
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+
+       _mali_osk_pm_dev_ref_add_no_power_on();
+
+       if (NULL != mali_pmu_get_global_pmu_core()) {
+               int i;
+
+               for (i = MALI_MAX_NUMBER_OF_DOMAINS - 1; i >= 0; i--) {
+                       if (target_core_nr < enabled_cores) {
+                               struct mali_pm_domain *domain;
+
+                               domain = mali_pm_domain_get_from_index(i);
+
+                               /* Domain is valid and has pp cores */
+                               if ((NULL != domain) && (NULL != domain->group_list)) {
+                                       struct mali_group *group;
+
+                                       MALI_PM_DOMAIN_FOR_EACH_GROUP(group, domain) {
+                                               /* If group is pp core */
+                                               if (NULL != mali_group_get_pp_core(group)) {
+                                                       mali_pp_scheduler_disable_group_internal(group);
+                                                       if (target_core_nr >= enabled_cores) {
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * Didn't find enough cores associated with a power domain,
+        * so we need to disable cores which we can't power off with the PMU.
+        * Start with physical groups used by the scheduler,
+        * then remove physical from virtual if even more groups are needed.
+        */
+
+       while (target_core_nr < enabled_cores) {
+               mali_pp_scheduler_lock();
+               if (!_mali_osk_list_empty(&group_list_idle)) {
+                       struct mali_group *group;
+
+                       group = _MALI_OSK_LIST_ENTRY(group_list_idle.next, struct mali_group, pp_scheduler_list);
+                       MALI_DEBUG_ASSERT_POINTER(group);
+
+                       mali_pp_scheduler_unlock();
+
+                       mali_pp_scheduler_disable_group_internal(group);
+               } else {
+                       mali_pp_scheduler_unlock();
+                       break; /* No more physical groups */
+               }
+       }
+
+       if (mali_pp_scheduler_has_virtual_group()) {
+               while (target_core_nr < enabled_cores) {
+                       mali_group_lock(virtual_group);
+                       if (!_mali_osk_list_empty(&virtual_group->group_list)) {
+                               struct mali_group *group;
+
+                               group = _MALI_OSK_LIST_ENTRY(virtual_group->group_list.next, struct mali_group, group_list);
+                               MALI_DEBUG_ASSERT_POINTER(group);
+
+                               mali_group_unlock(virtual_group);
+
+                               mali_pp_scheduler_disable_group_internal(group);
+                       } else {
+                               mali_group_unlock(virtual_group);
+                               break; /* No more physical groups in virtual group */
+                       }
+               }
+       }
+
+       _mali_osk_pm_dev_ref_dec_no_power_on();
+
+       mali_pp_scheduler_resume();
+}
+
+int mali_pp_scheduler_set_perf_level(unsigned int target_core_nr, mali_bool override)
+{
+       if (target_core_nr == enabled_cores) return 0;
+       if (MALI_FALSE == core_scaling_enabled && MALI_FALSE == override) return -EPERM;
+       if (target_core_nr > num_cores) return -EINVAL;
+       if (0 == target_core_nr) return -EINVAL;
+
+       if (target_core_nr > enabled_cores) {
+               mali_pp_scheduler_core_scale_up(target_core_nr);
+       } else if (target_core_nr < enabled_cores) {
+               mali_pp_scheduler_core_scale_down(target_core_nr);
+       }
+
+       if (target_core_nr != enabled_cores) {
+               MALI_DEBUG_PRINT(2, ("Core scaling failed, target number: %d, actual number: %d\n", target_core_nr, enabled_cores));
+       }
+
+       mali_pp_scheduler_notify_core_change(enabled_cores);
+
+       return 0;
+}
+
+void mali_pp_scheduler_core_scaling_enable(void)
+{
+       /* PS: Core scaling is by default enabled */
+       core_scaling_enabled = MALI_TRUE;
+}
+
+void mali_pp_scheduler_core_scaling_disable(void)
+{
+       core_scaling_enabled = MALI_FALSE;
+}
+
+mali_bool mali_pp_scheduler_core_scaling_is_enabled(void)
+{
+       return core_scaling_enabled;
+}
+
+static void mali_pp_scheduler_job_queued(void)
+{
+       /* We hold a PM reference for every job we hold queued (and running) */
+       _mali_osk_pm_dev_ref_add();
+
+       if (mali_utilization_enabled()) {
+               /*
+                * We cheat a little bit by counting the PP as busy from the time a PP job is queued.
+                * This will be fine because we only loose the tiny idle gap between jobs, but
+                * we will instead get less utilization work to do (less locks taken)
+                */
+               mali_utilization_pp_start();
+       }
+}
+
+static void mali_pp_scheduler_job_completed(void)
+{
+       /* Release the PM reference we got in the mali_pp_scheduler_job_queued() function */
+       _mali_osk_pm_dev_ref_dec();
+
+       if (mali_utilization_enabled()) {
+               mali_utilization_pp_end();
+       }
+}
+
+static void mali_pp_scheduler_abort_job_and_unlock_scheduler(struct mali_pp_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_LOCK_HELD(pp_scheduler_lock);
+
+       /* This job should not be on any lists. */
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list));
+       MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->session_list));
+
+       _mali_osk_list_delinit(&job->session_fb_lookup_list);
+
+       mali_pp_scheduler_unlock();
+
+       /* Release tracker. */
+       mali_timeline_tracker_release(&job->tracker);
+}
+
+static mali_scheduler_mask mali_pp_scheduler_queue_job(struct mali_pp_job *job)
+{
+       _mali_osk_list_t *queue = NULL;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+       struct mali_pp_job *iter, *tmp;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->session);
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE)
+       if (mali_pp_job_needs_dma_buf_mapping(job)) {
+               mali_dma_buf_map_job(job);
+       }
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE) */
+
+       mali_pp_scheduler_lock();
+
+       if (unlikely(job->session->is_aborting)) {
+               /* Before checking if the session is aborting, the scheduler must be locked. */
+               MALI_DEBUG_ASSERT_LOCK_HELD(pp_scheduler_lock);
+
+               MALI_DEBUG_PRINT(2, ("Mali PP scheduler: Job %u (0x%08X) queued while session is aborting.\n", mali_pp_job_get_id(job), job));
+
+               mali_pp_scheduler_abort_job_and_unlock_scheduler(job);
+
+               /* Delete job. */
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
+               mali_pp_scheduler_deferred_job_delete(job);
+#else
+               mali_pp_job_delete(job);
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE) */
+               mali_pp_scheduler_job_completed();
+
+               /* Since we are aborting we ignore the scheduler mask. */
+               return MALI_SCHEDULER_MASK_EMPTY;
+       }
+
+#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
+       trace_gpu_job_enqueue(mali_pp_job_get_tid(job), mali_pp_job_get_id(job), "PP");
+#endif
+
+       _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE, job->pid, job->tid, job->uargs.frame_builder_id, job->uargs.flush_id, 0);
+
+       job->cache_order = mali_scheduler_get_new_cache_order();
+
+       /* Determine which queue the job should be added to. */
+       if (mali_pp_job_is_virtual(job)) {
+               if (job->session->use_high_priority_job_queue) {
+                       queue = &virtual_job_queue.high_pri;
+               } else {
+                       queue = &virtual_job_queue.normal_pri;
+               }
+
+               virtual_job_queue.depth += 1;
+
+               /* Set schedule bitmask if the virtual group is idle. */
+               if (VIRTUAL_GROUP_IDLE == virtual_group_state) {
+                       schedule_mask |= MALI_SCHEDULER_MASK_PP;
+               }
+       } else {
+               if (job->session->use_high_priority_job_queue) {
+                       queue = &job_queue.high_pri;
+               } else {
+                       queue = &job_queue.normal_pri;
+               }
+
+               job_queue.depth += mali_pp_job_get_sub_job_count(job);
+
+               /* Set schedule bitmask if there are physical PP cores available, or if there is an
+                * idle virtual group. */
+               if (!_mali_osk_list_empty(&group_list_idle)
+                   || (mali_pp_scheduler_has_virtual_group()
+                       && (VIRTUAL_GROUP_IDLE == virtual_group_state))) {
+                       schedule_mask |= MALI_SCHEDULER_MASK_PP;
+               }
+       }
+
+       /* Find position in queue where job should be added. */
+       _MALI_OSK_LIST_FOREACHENTRY_REVERSE(iter, tmp, queue, struct mali_pp_job, list) {
+               if (mali_pp_job_should_start_after(job, iter)) {
+                       break;
+               }
+       }
+
+       /* Add job to queue. */
+       _mali_osk_list_add(&job->list, &iter->list);
+
+       /* Add job to session list. */
+       _mali_osk_list_addtail(&job->session_list, &(job->session->pp_job_list));
+
+       MALI_DEBUG_PRINT(3, ("Mali PP scheduler: %s job %u (0x%08X) with %u parts queued.\n",
+                            mali_pp_job_is_virtual(job) ? "Virtual" : "Physical",
+                            mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job)));
+
+       mali_pp_scheduler_unlock();
+
+       return schedule_mask;
+}
+
+mali_scheduler_mask mali_pp_scheduler_activate_job(struct mali_pp_job *job)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->session);
+
+       MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Timeline activation for job %u (0x%08X).\n", mali_pp_job_get_id(job), job));
+
+       if (MALI_TIMELINE_ACTIVATION_ERROR_FATAL_BIT & job->tracker.activation_error) {
+               MALI_DEBUG_PRINT(2, ("Mali PP scheduler: Job %u (0x%08X) activated with error, aborting.\n", mali_pp_job_get_id(job), job));
+
+               mali_pp_scheduler_lock();
+               mali_pp_scheduler_abort_job_and_unlock_scheduler(job);
+
+               mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+               mali_pp_scheduler_finalize_job(job);
+
+               return MALI_SCHEDULER_MASK_EMPTY;
+       }
+
+       /* PP job is ready to run, queue it. */
+
+#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE)
+       if (mali_pp_job_needs_dma_buf_mapping(job)) {
+               mali_pp_scheduler_deferred_job_queue(job);
+
+               return MALI_SCHEDULER_MASK_EMPTY;
+       }
+#endif /* defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_QUEUE) */
+
+       schedule_mask = mali_pp_scheduler_queue_job(job);
+
+       return schedule_mask;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h b/drivers/gpu/arm/mali400/mali/common/mali_pp_scheduler.h
new file mode 100755 (executable)
index 0000000..6167d8c
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PP_SCHEDULER_H__
+#define __MALI_PP_SCHEDULER_H__
+
+#include "mali_osk.h"
+#include "mali_pp_job.h"
+#include "mali_group.h"
+#include "linux/mali/mali_utgard.h"
+
+/** Initalize the HW independent parts of the  PP scheduler
+ */
+_mali_osk_errcode_t mali_pp_scheduler_initialize(void);
+void mali_pp_scheduler_terminate(void);
+
+/** Poplulate the PP scheduler with groups
+ */
+void mali_pp_scheduler_populate(void);
+void mali_pp_scheduler_depopulate(void);
+
+/**
+ * @brief Handle job completion.
+ *
+ * Will attempt to start a new job on the locked group.
+ *
+ * If all sub jobs have completed the job's tracker will be released, any other resources associated
+ * with the job will be freed.  A notification will also be sent to user space.
+ *
+ * Releasing the tracker might activate other jobs, so if appropriate we also schedule them.
+ *
+ * @note Group must be locked when entering this function.  Will be unlocked before exiting.
+ *
+ * @param group The group that completed the job.
+ * @param job The job that is done.
+ * @param sub_job Sub job of job.
+ * @param success MALI_TRUE if job completed successfully, MALI_FALSE if not.
+ * @param in_upper_half MALI_TRUE if called from upper half, MALI_FALSE if not.
+ */
+void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success, mali_bool in_upper_half);
+
+void mali_pp_scheduler_suspend(void);
+void mali_pp_scheduler_resume(void);
+
+/**
+ * @brief Abort all running and queued PP jobs from session.
+ *
+ * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the
+ * queue and jobs currently running on a core will be aborted.
+ *
+ * @param session Session that is aborting.
+ */
+void mali_pp_scheduler_abort_session(struct mali_session_data *session);
+
+/**
+ * @brief Reset all groups
+ *
+ * This function resets all groups known by the PP scheuduler. This must be
+ * called after the Mali HW has been powered on in order to reset the HW.
+ *
+ * This function is intended for power on reset of all cores.
+ * No locking is done, which can only be safe if the scheduler is paused and
+ * all cores idle. That is always the case on init and power on.
+ */
+void mali_pp_scheduler_reset_all_groups(void);
+
+/**
+ * @brief Zap TLB on all groups with \a session active
+ *
+ * The scheculer will zap the session on all groups it owns.
+ */
+void mali_pp_scheduler_zap_all_active(struct mali_session_data *session);
+
+/**
+ * @brief Get the virtual PP core
+ *
+ * The returned PP core may only be used to prepare DMA command buffers for the
+ * PP core. Other actions must go through the PP scheduler, or the virtual
+ * group.
+ *
+ * @return Pointer to the virtual PP core, NULL if this doesn't exist
+ */
+struct mali_pp_core *mali_pp_scheduler_get_virtual_pp(void);
+
+u32 mali_pp_scheduler_dump_state(char *buf, u32 size);
+
+void mali_pp_scheduler_enable_group(struct mali_group *group);
+void mali_pp_scheduler_disable_group(struct mali_group *group);
+
+/**
+ * @brief Used by the Timeline system to queue a PP job.
+ *
+ * @note @ref mali_scheduler_schedule_from_mask() should be called if this function returns non-zero.
+ *
+ * @param job The PP job that is being activated.
+ *
+ * @return A scheduling bitmask that can be used to decide if scheduling is necessary after this
+ * call.
+ */
+mali_scheduler_mask mali_pp_scheduler_activate_job(struct mali_pp_job *job);
+
+/**
+ * @brief Schedule queued jobs on idle cores.
+ */
+void mali_pp_scheduler_schedule(void);
+
+int mali_pp_scheduler_set_perf_level(u32 cores, mali_bool override);
+
+void mali_pp_scheduler_core_scaling_enable(void);
+void mali_pp_scheduler_core_scaling_disable(void);
+mali_bool mali_pp_scheduler_core_scaling_is_enabled(void);
+
+u32 mali_pp_scheduler_get_num_cores_total(void);
+u32 mali_pp_scheduler_get_num_cores_enabled(void);
+
+/**
+ * @brief Returns the number of Pixel Processors in the system irrespective of the context
+ *
+ * @return number of physical Pixel Processor cores in the system
+ */
+u32 mali_pp_scheduler_get_num_cores_total(void);
+
+#endif /* __MALI_PP_SCHEDULER_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_scheduler.c b/drivers/gpu/arm/mali400/mali/common/mali_scheduler.c
new file mode 100755 (executable)
index 0000000..2daa2e4
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_scheduler.h"
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+mali_bool mali_scheduler_hints[MALI_SCHEDULER_HINT_MAX];
+
+static _mali_osk_atomic_t mali_job_id_autonumber;
+static _mali_osk_atomic_t mali_job_cache_order_autonumber;
+
+static _mali_osk_wq_work_t *pp_scheduler_wq_high_pri = NULL;
+static _mali_osk_wq_work_t *gp_scheduler_wq_high_pri = NULL;
+
+static void mali_scheduler_wq_schedule_pp(void *arg)
+{
+       MALI_IGNORE(arg);
+
+       mali_pp_scheduler_schedule();
+}
+
+static void mali_scheduler_wq_schedule_gp(void *arg)
+{
+       MALI_IGNORE(arg);
+
+       mali_gp_scheduler_schedule();
+}
+
+_mali_osk_errcode_t mali_scheduler_initialize(void)
+{
+       if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_id_autonumber, 0)) {
+               MALI_DEBUG_PRINT(1,  ("Initialization of atomic job id counter failed.\n"));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_cache_order_autonumber, 0)) {
+               MALI_DEBUG_PRINT(1,  ("Initialization of atomic job cache order counter failed.\n"));
+               _mali_osk_atomic_term(&mali_job_id_autonumber);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       pp_scheduler_wq_high_pri = _mali_osk_wq_create_work_high_pri(mali_scheduler_wq_schedule_pp, NULL);
+       if (NULL == pp_scheduler_wq_high_pri) {
+               _mali_osk_atomic_term(&mali_job_cache_order_autonumber);
+               _mali_osk_atomic_term(&mali_job_id_autonumber);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       gp_scheduler_wq_high_pri = _mali_osk_wq_create_work_high_pri(mali_scheduler_wq_schedule_gp, NULL);
+       if (NULL == gp_scheduler_wq_high_pri) {
+               _mali_osk_wq_delete_work(pp_scheduler_wq_high_pri);
+               _mali_osk_atomic_term(&mali_job_cache_order_autonumber);
+               _mali_osk_atomic_term(&mali_job_id_autonumber);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_scheduler_terminate(void)
+{
+       _mali_osk_wq_delete_work(gp_scheduler_wq_high_pri);
+       _mali_osk_wq_delete_work(pp_scheduler_wq_high_pri);
+       _mali_osk_atomic_term(&mali_job_cache_order_autonumber);
+       _mali_osk_atomic_term(&mali_job_id_autonumber);
+}
+
+u32 mali_scheduler_get_new_id(void)
+{
+       u32 job_id = _mali_osk_atomic_inc_return(&mali_job_id_autonumber);
+       return job_id;
+}
+
+u32 mali_scheduler_get_new_cache_order(void)
+{
+       u32 job_cache_order = _mali_osk_atomic_inc_return(&mali_job_cache_order_autonumber);
+       return job_cache_order;
+}
+
+void mali_scheduler_schedule_from_mask(mali_scheduler_mask mask, mali_bool deferred_schedule)
+{
+       if (MALI_SCHEDULER_MASK_GP & mask) {
+               /* GP needs scheduling. */
+               if (deferred_schedule) {
+                       /* Schedule GP deferred. */
+                       _mali_osk_wq_schedule_work_high_pri(gp_scheduler_wq_high_pri);
+               } else {
+                       /* Schedule GP now. */
+                       mali_gp_scheduler_schedule();
+               }
+       }
+
+       if (MALI_SCHEDULER_MASK_PP & mask) {
+               /* PP needs scheduling. */
+               if (deferred_schedule) {
+                       /* Schedule PP deferred. */
+                       _mali_osk_wq_schedule_work_high_pri(pp_scheduler_wq_high_pri);
+               } else {
+                       /* Schedule PP now. */
+                       mali_pp_scheduler_schedule();
+               }
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_scheduler.h b/drivers/gpu/arm/mali400/mali/common/mali_scheduler.h
new file mode 100755 (executable)
index 0000000..0725200
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_SCHEDULER_H__
+#define __MALI_SCHEDULER_H__
+
+#include "mali_osk.h"
+#include "mali_scheduler_types.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+
+_mali_osk_errcode_t mali_scheduler_initialize(void);
+void mali_scheduler_terminate(void);
+
+u32 mali_scheduler_get_new_id(void);
+u32 mali_scheduler_get_new_cache_order(void);
+
+/**
+ * @brief Reset all groups
+ *
+ * This function resets all groups known by the both the PP and GP scheuduler.
+ * This must be called after the Mali HW has been powered on in order to reset
+ * the HW.
+ */
+MALI_STATIC_INLINE void mali_scheduler_reset_all_groups(void)
+{
+       mali_gp_scheduler_reset_all_groups();
+       mali_pp_scheduler_reset_all_groups();
+}
+
+/**
+ * @brief Zap TLB on all active groups running \a session
+ *
+ * @param session Pointer to the session to zap
+ */
+MALI_STATIC_INLINE void mali_scheduler_zap_all_active(struct mali_session_data *session)
+{
+       mali_gp_scheduler_zap_all_active(session);
+       mali_pp_scheduler_zap_all_active(session);
+}
+
+/**
+ * Check if bit is set in scheduler mask.
+ *
+ * @param mask Scheduler mask to check.
+ * @param bit Bit to check.
+ * @return MALI_TRUE if bit is set in scheduler mask, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_scheduler_mask_is_set(mali_scheduler_mask mask, mali_scheduler_mask bit)
+{
+       return MALI_SCHEDULER_MASK_EMPTY != (bit & mask);
+}
+
+/**
+ * Schedule GP and PP according to bitmask.
+ *
+ * @param mask A scheduling bitmask.
+ * @param deferred_schedule MALI_TRUE if schedule should be deferred, MALI_FALSE if not.
+ */
+void mali_scheduler_schedule_from_mask(mali_scheduler_mask mask, mali_bool deferred_schedule);
+
+/* Enable or disable scheduler hint. */
+extern mali_bool mali_scheduler_hints[MALI_SCHEDULER_HINT_MAX];
+
+MALI_STATIC_INLINE void mali_scheduler_hint_enable(mali_scheduler_hint hint)
+{
+       MALI_DEBUG_ASSERT(hint < MALI_SCHEDULER_HINT_MAX);
+       mali_scheduler_hints[hint] = MALI_TRUE;
+}
+
+MALI_STATIC_INLINE void mali_scheduler_hint_disable(mali_scheduler_hint hint)
+{
+       MALI_DEBUG_ASSERT(hint < MALI_SCHEDULER_HINT_MAX);
+       mali_scheduler_hints[hint] = MALI_FALSE;
+}
+
+MALI_STATIC_INLINE mali_bool mali_scheduler_hint_is_enabled(mali_scheduler_hint hint)
+{
+       MALI_DEBUG_ASSERT(hint < MALI_SCHEDULER_HINT_MAX);
+       return mali_scheduler_hints[hint];
+}
+
+#endif /* __MALI_SCHEDULER_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_scheduler_types.h b/drivers/gpu/arm/mali400/mali/common/mali_scheduler_types.h
new file mode 100755 (executable)
index 0000000..5cbf598
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_SCHEDULER_TYPES_H__
+#define __MALI_SCHEDULER_TYPES_H__
+
+#include "mali_osk.h"
+
+#define MALI_SCHEDULER_JOB_ID_SPAN 65535
+
+/**
+ * Bitmask used for defered scheduling of subsystems.
+ */
+typedef u32 mali_scheduler_mask;
+
+#define MALI_SCHEDULER_MASK_GP (1<<0)
+#define MALI_SCHEDULER_MASK_PP (1<<1)
+
+#define MALI_SCHEDULER_MASK_EMPTY 0
+#define MALI_SCHEDULER_MASK_ALL (MALI_SCHEDULER_MASK_GP | MALI_SCHEDULER_MASK_PP)
+
+typedef enum {
+       MALI_SCHEDULER_HINT_GP_BOUND = 0
+#define MALI_SCHEDULER_HINT_MAX        1
+} mali_scheduler_hint;
+
+#endif /* __MALI_SCHEDULER_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_session.c b/drivers/gpu/arm/mali400/mali/common/mali_session.c
new file mode 100755 (executable)
index 0000000..852f1e1
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_session.h"
+
+_MALI_OSK_LIST_HEAD(mali_sessions);
+static u32 mali_session_count = 0;
+
+_mali_osk_spinlock_irq_t *mali_sessions_lock;
+
+_mali_osk_errcode_t mali_session_initialize(void)
+{
+       _MALI_OSK_INIT_LIST_HEAD(&mali_sessions);
+
+       mali_sessions_lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SESSIONS);
+
+       if (NULL == mali_sessions_lock) return _MALI_OSK_ERR_NOMEM;
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_session_terminate(void)
+{
+       _mali_osk_spinlock_irq_term(mali_sessions_lock);
+}
+
+void mali_session_add(struct mali_session_data *session)
+{
+       mali_session_lock();
+       _mali_osk_list_add(&session->link, &mali_sessions);
+       mali_session_count++;
+       mali_session_unlock();
+}
+
+void mali_session_remove(struct mali_session_data *session)
+{
+       mali_session_lock();
+       _mali_osk_list_delinit(&session->link);
+       mali_session_count--;
+       mali_session_unlock();
+}
+
+u32 mali_session_get_count(void)
+{
+       return mali_session_count;
+}
+
+/*
+ * Get the max completed window jobs from all active session,
+ * which will be used in window render frame per sec calculate
+ */
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+u32 mali_session_max_window_num(void)
+{
+       struct mali_session_data *session, *tmp;
+       u32 max_window_num = 0;
+       u32 tmp_number = 0;
+
+       mali_session_lock();
+
+       MALI_SESSION_FOREACH(session, tmp, link) {
+               tmp_number = _mali_osk_atomic_xchg(&session->number_of_window_jobs, 0);
+               if (max_window_num < tmp_number) {
+                       max_window_num = tmp_number;
+               }
+       }
+
+       mali_session_unlock();
+
+       return max_window_num;
+}
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_session.h b/drivers/gpu/arm/mali400/mali/common/mali_session.h
new file mode 100755 (executable)
index 0000000..ef8d5f5
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_SESSION_H__
+#define __MALI_SESSION_H__
+
+#include "mali_mmu_page_directory.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+
+struct mali_timeline_system;
+struct mali_soft_system;
+
+/* Number of frame builder job lists per session. */
+#define MALI_PP_JOB_FB_LOOKUP_LIST_SIZE 16
+#define MALI_PP_JOB_FB_LOOKUP_LIST_MASK (MALI_PP_JOB_FB_LOOKUP_LIST_SIZE - 1)
+
+struct mali_session_data {
+       _mali_osk_notification_queue_t * ioctl_queue;
+
+       _mali_osk_mutex_t *memory_lock; /**< Lock protecting the vm manipulation */
+       mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
+       _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */
+
+       struct mali_page_directory *page_directory; /**< MMU page directory for this session */
+
+       _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */
+       _MALI_OSK_LIST_HEAD(pp_job_list); /**< List of all PP jobs on this session */
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       _mali_osk_atomic_t number_of_window_jobs; /**< Record the window jobs completed on this session in a period */
+#endif
+
+       _mali_osk_list_t pp_job_fb_lookup_list[MALI_PP_JOB_FB_LOOKUP_LIST_SIZE]; /**< List of PP job lists per frame builder id.  Used to link jobs from same frame builder. */
+
+       struct mali_soft_job_system *soft_job_system; /**< Soft job system for this session. */
+       struct mali_timeline_system *timeline_system; /**< Timeline system for this session. */
+
+       mali_bool is_aborting; /**< MALI_TRUE if the session is aborting, MALI_FALSE if not. */
+       mali_bool use_high_priority_job_queue; /**< If MALI_TRUE, jobs added from this session will use the high priority job queues. */
+};
+
+_mali_osk_errcode_t mali_session_initialize(void);
+void mali_session_terminate(void);
+
+/* List of all sessions. Actual list head in mali_kernel_core.c */
+extern _mali_osk_list_t mali_sessions;
+/* Lock to protect modification and access to the mali_sessions list */
+extern _mali_osk_spinlock_irq_t *mali_sessions_lock;
+
+MALI_STATIC_INLINE void mali_session_lock(void)
+{
+       _mali_osk_spinlock_irq_lock(mali_sessions_lock);
+}
+
+MALI_STATIC_INLINE void mali_session_unlock(void)
+{
+       _mali_osk_spinlock_irq_unlock(mali_sessions_lock);
+}
+
+void mali_session_add(struct mali_session_data *session);
+void mali_session_remove(struct mali_session_data *session);
+u32 mali_session_get_count(void);
+
+#define MALI_SESSION_FOREACH(session, tmp, link) \
+       _MALI_OSK_LIST_FOREACHENTRY(session, tmp, &mali_sessions, struct mali_session_data, link)
+
+MALI_STATIC_INLINE struct mali_page_directory *mali_session_get_page_directory(struct mali_session_data *session)
+{
+       return session->page_directory;
+}
+
+MALI_STATIC_INLINE void mali_session_send_notification(struct mali_session_data *session, _mali_osk_notification_t *object)
+{
+       _mali_osk_notification_queue_send(session->ioctl_queue, object);
+}
+
+/*
+ * Get the max completed window jobs from all active session,
+ * which will be used in  window render frame per sec calculate
+ */
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+u32 mali_session_max_window_num(void);
+#endif
+
+#endif /* __MALI_SESSION_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_soft_job.c b/drivers/gpu/arm/mali400/mali/common/mali_soft_job.c
new file mode 100755 (executable)
index 0000000..b2bb8e3
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_soft_job.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_timeline.h"
+#include "mali_session.h"
+#include "mali_kernel_common.h"
+#include "mali_uk_types.h"
+#include "mali_scheduler.h"
+
+MALI_STATIC_INLINE void mali_soft_job_system_lock(struct mali_soft_job_system *system)
+{
+       MALI_DEBUG_ASSERT_POINTER(system);
+       _mali_osk_spinlock_irq_lock(system->lock);
+       MALI_DEBUG_PRINT(5, ("Mali Soft Job: soft system %p lock taken\n", system));
+       MALI_DEBUG_ASSERT(0 == system->lock_owner);
+       MALI_DEBUG_CODE(system->lock_owner = _mali_osk_get_tid());
+}
+
+MALI_STATIC_INLINE void mali_soft_job_system_unlock(struct mali_soft_job_system *system)
+{
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_PRINT(5, ("Mali Soft Job: releasing soft system %p lock\n", system));
+       MALI_DEBUG_ASSERT(_mali_osk_get_tid() == system->lock_owner);
+       MALI_DEBUG_CODE(system->lock_owner = 0);
+       _mali_osk_spinlock_irq_unlock(system->lock);
+}
+
+#if defined(DEBUG)
+MALI_STATIC_INLINE void mali_soft_job_system_assert_locked(struct mali_soft_job_system *system)
+{
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT(_mali_osk_get_tid() == system->lock_owner);
+}
+#define MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system) mali_soft_job_system_assert_locked(system)
+#else
+#define MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system)
+#endif /* defined(DEBUG) */
+
+struct mali_soft_job_system *mali_soft_job_system_create(struct mali_session_data *session)
+{
+       u32 i;
+       struct mali_soft_job_system *system;
+       struct mali_soft_job *job;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       system = (struct mali_soft_job_system *) _mali_osk_calloc(1, sizeof(struct mali_soft_job_system));
+       if (NULL == system) {
+               return NULL;
+       }
+
+       system->session = session;
+
+       system->lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+       if (NULL == system->lock) {
+               mali_soft_job_system_destroy(system);
+               return NULL;
+       }
+       system->lock_owner = 0;
+
+       _MALI_OSK_INIT_LIST_HEAD(&(system->jobs_free));
+       _MALI_OSK_INIT_LIST_HEAD(&(system->jobs_used));
+
+       for (i = 0; i < MALI_MAX_NUM_SOFT_JOBS; ++i) {
+               job = &(system->jobs[i]);
+               _mali_osk_list_add(&(job->system_list), &(system->jobs_free));
+               job->system = system;
+               job->state = MALI_SOFT_JOB_STATE_FREE;
+               job->id = i;
+       }
+
+       return system;
+}
+
+void mali_soft_job_system_destroy(struct mali_soft_job_system *system)
+{
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       /* All jobs should be free at this point. */
+       MALI_DEBUG_CODE( {
+               u32 i;
+               struct mali_soft_job *job;
+
+               for (i = 0; i < MALI_MAX_NUM_SOFT_JOBS; ++i)
+               {
+                       job = &(system->jobs[i]);
+                       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_FREE == job->state);
+               }
+       });
+
+       if (NULL != system) {
+               if (NULL != system->lock) {
+                       _mali_osk_spinlock_irq_term(system->lock);
+               }
+               _mali_osk_free(system);
+       }
+}
+
+static struct mali_soft_job *mali_soft_job_system_alloc_job(struct mali_soft_job_system *system)
+{
+       struct mali_soft_job *job;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system);
+
+       if (_mali_osk_list_empty(&(system->jobs_free))) {
+               /* No jobs available. */
+               return NULL;
+       }
+
+       /* Grab first job and move it to the used list. */
+       job = _MALI_OSK_LIST_ENTRY(system->jobs_free.next, struct mali_soft_job, system_list);
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_FREE == job->state);
+
+       _mali_osk_list_move(&(job->system_list), &(system->jobs_used));
+       job->state = MALI_SOFT_JOB_STATE_ALLOCATED;
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_INVALID_ID != job->id);
+       MALI_DEBUG_ASSERT(system == job->system);
+
+       return job;
+}
+
+static void mali_soft_job_system_free_job(struct mali_soft_job_system *system, struct mali_soft_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_soft_job_system_lock(job->system);
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_FREE != job->state);
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_INVALID_ID != job->id);
+       MALI_DEBUG_ASSERT(system == job->system);
+
+       job->state = MALI_SOFT_JOB_STATE_FREE;
+       _mali_osk_list_move(&(job->system_list), &(system->jobs_free));
+
+       mali_soft_job_system_unlock(job->system);
+}
+
+MALI_STATIC_INLINE struct mali_soft_job *mali_soft_job_system_lookup_job(struct mali_soft_job_system *system, u32 job_id)
+{
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system);
+
+       if (job_id < MALI_MAX_NUM_SOFT_JOBS) {
+               return &system->jobs[job_id];
+       }
+
+       return NULL;
+}
+
+void mali_soft_job_destroy(struct mali_soft_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->system);
+
+       MALI_DEBUG_PRINT(4, ("Mali Soft Job: destroying soft job %u (0x%08X)\n", job->id, job));
+
+       if (NULL != job) {
+               if (0 < _mali_osk_atomic_dec_return(&job->refcount)) return;
+
+               _mali_osk_atomic_term(&job->refcount);
+
+               if (NULL != job->activated_notification) {
+                       _mali_osk_notification_delete(job->activated_notification);
+                       job->activated_notification = NULL;
+               }
+
+               mali_soft_job_system_free_job(job->system, job);
+       }
+}
+
+struct mali_soft_job *mali_soft_job_create(struct mali_soft_job_system *system, mali_soft_job_type type, u32 user_job)
+{
+       struct mali_soft_job *job;
+       _mali_osk_notification_t *notification = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_TYPE_USER_SIGNALED >= type);
+
+       if (MALI_SOFT_JOB_TYPE_USER_SIGNALED == type) {
+               notification = _mali_osk_notification_create(_MALI_NOTIFICATION_SOFT_ACTIVATED, sizeof(_mali_uk_soft_job_activated_s));
+               if (unlikely(NULL == notification)) {
+                       MALI_PRINT_ERROR(("Mali Soft Job: failed to allocate notification"));
+                       return NULL;
+               }
+       }
+
+       mali_soft_job_system_lock(system);
+
+       job = mali_soft_job_system_alloc_job(system);
+       if (NULL == job) {
+               mali_soft_job_system_unlock(system);
+               MALI_PRINT_ERROR(("Mali Soft Job: failed to allocate job"));
+               _mali_osk_notification_delete(notification);
+               return NULL;
+       }
+
+       job->type = type;
+       job->user_job = user_job;
+       job->activated = MALI_FALSE;
+
+       if (MALI_SOFT_JOB_TYPE_USER_SIGNALED == type) {
+               job->activated_notification = notification;
+       }
+
+       _mali_osk_atomic_init(&job->refcount, 1);
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_ALLOCATED == job->state);
+       MALI_DEBUG_ASSERT(system == job->system);
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_INVALID_ID != job->id);
+
+       mali_soft_job_system_unlock(system);
+
+       return job;
+}
+
+mali_timeline_point mali_soft_job_start(struct mali_soft_job *job, struct mali_timeline_fence *fence)
+{
+       mali_timeline_point point;
+       struct mali_soft_job_system *system;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(fence);
+
+       MALI_DEBUG_ASSERT_POINTER(job->system);
+       system = job->system;
+
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+       MALI_DEBUG_ASSERT_POINTER(system->session->timeline_system);
+
+       mali_soft_job_system_lock(system);
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_ALLOCATED == job->state);
+       job->state = MALI_SOFT_JOB_STATE_STARTED;
+
+       mali_soft_job_system_unlock(system);
+
+       MALI_DEBUG_PRINT(4, ("Mali Soft Job: starting soft job %u (0x%08X)\n", job->id, job));
+
+       mali_timeline_tracker_init(&job->tracker, MALI_TIMELINE_TRACKER_SOFT, fence, job);
+       point = mali_timeline_system_add_tracker(system->session->timeline_system, &job->tracker, MALI_TIMELINE_SOFT);
+
+       return point;
+}
+
+static mali_bool mali_soft_job_is_activated(void *data)
+{
+       struct mali_soft_job *job;
+
+       job = (struct mali_soft_job *) data;
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       return job->activated;
+}
+
+_mali_osk_errcode_t mali_soft_job_system_signal_job(struct mali_soft_job_system *system, u32 job_id)
+{
+       struct mali_soft_job *job;
+       struct mali_timeline_system *timeline_system;
+       mali_scheduler_mask schedule_mask;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_soft_job_system_lock(system);
+
+       job = mali_soft_job_system_lookup_job(system, job_id);
+
+       if (NULL == job || !(MALI_SOFT_JOB_STATE_STARTED == job->state || MALI_SOFT_JOB_STATE_TIMED_OUT == job->state)) {
+               mali_soft_job_system_unlock(system);
+               MALI_PRINT_ERROR(("Mali Soft Job: invalid soft job id %u", job_id));
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) {
+               job->state = MALI_SOFT_JOB_STATE_SIGNALED;
+               mali_soft_job_system_unlock(system);
+
+               MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);
+               MALI_DEBUG_PRINT(4, ("Mali Soft Job: soft job %u (0x%08X) was timed out\n", job->id, job));
+               mali_soft_job_destroy(job);
+
+               return _MALI_OSK_ERR_TIMEOUT;
+       }
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);
+
+       job->state = MALI_SOFT_JOB_STATE_SIGNALED;
+       mali_soft_job_system_unlock(system);
+
+       /* Since the job now is in signaled state, timeouts from the timeline system will be
+        * ignored, and it is not possible to signal this job again. */
+
+       timeline_system = system->session->timeline_system;
+       MALI_DEBUG_ASSERT_POINTER(timeline_system);
+
+       /* Wait until activated. */
+       _mali_osk_wait_queue_wait_event(timeline_system->wait_queue, mali_soft_job_is_activated, (void *) job);
+
+       MALI_DEBUG_PRINT(4, ("Mali Soft Job: signaling soft job %u (0x%08X)\n", job->id, job));
+
+       schedule_mask = mali_timeline_tracker_release(&job->tracker);
+       mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE);
+
+       mali_soft_job_destroy(job);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+static void mali_soft_job_send_activated_notification(struct mali_soft_job *job)
+{
+       if (NULL != job->activated_notification) {
+               _mali_uk_soft_job_activated_s *res = job->activated_notification->result_buffer;
+               res->user_job = job->user_job;
+               mali_session_send_notification(job->system->session, job->activated_notification);
+       }
+       job->activated_notification = NULL;
+}
+
+void mali_soft_job_system_activate_job(struct mali_soft_job *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->system);
+       MALI_DEBUG_ASSERT_POINTER(job->system->session);
+
+       MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline activation for soft job %u (0x%08X).\n", job->id, job));
+
+       mali_soft_job_system_lock(job->system);
+
+       if (unlikely(job->system->session->is_aborting)) {
+               MALI_DEBUG_PRINT(3, ("Mali Soft Job: Soft job %u (0x%08X) activated while session is aborting.\n", job->id, job));
+
+               mali_soft_job_system_unlock(job->system);
+
+               /* Since we are in shutdown, we can ignore the scheduling bitmask. */
+               mali_timeline_tracker_release(&job->tracker);
+               mali_soft_job_destroy(job);
+               return;
+       }
+
+       /* Send activated notification. */
+       mali_soft_job_send_activated_notification(job);
+
+       /* Wake up sleeping signaler. */
+       job->activated = MALI_TRUE;
+       _mali_osk_wait_queue_wake_up(job->tracker.system->wait_queue);
+
+       mali_soft_job_system_unlock(job->system);
+}
+
+mali_scheduler_mask mali_soft_job_system_timeout_job(struct mali_soft_job *job)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(job);
+       MALI_DEBUG_ASSERT_POINTER(job->system);
+       MALI_DEBUG_ASSERT_POINTER(job->system->session);
+       MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);
+
+       MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline timeout for soft job %u (0x%08X).\n", job->id, job));
+
+       mali_soft_job_system_lock(job->system);
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED  == job->state ||
+                         MALI_SOFT_JOB_STATE_SIGNALED == job->state);
+
+       if (unlikely(job->system->session->is_aborting)) {
+               /* The session is aborting.  This job will be released and destroyed by @ref
+                * mali_soft_job_system_abort(). */
+               mali_soft_job_system_unlock(job->system);
+
+               return MALI_SCHEDULER_MASK_EMPTY;
+       }
+
+       if (MALI_SOFT_JOB_STATE_STARTED != job->state) {
+               MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state);
+
+               /* The job is about to be signaled, ignore timeout. */
+               MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeout on soft job %u (0x%08X) in signaled state.\n", job->id, job));
+               mali_soft_job_system_unlock(job->system);
+               return schedule_mask;
+       }
+
+       MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);
+
+       job->state = MALI_SOFT_JOB_STATE_TIMED_OUT;
+       _mali_osk_atomic_inc(&job->refcount);
+
+       mali_soft_job_system_unlock(job->system);
+
+       schedule_mask = mali_timeline_tracker_release(&job->tracker);
+
+       mali_soft_job_destroy(job);
+
+       return schedule_mask;
+}
+
+void mali_soft_job_system_abort(struct mali_soft_job_system *system)
+{
+       u32 i;
+       struct mali_soft_job *job, *tmp;
+       _MALI_OSK_LIST_HEAD_STATIC_INIT(jobs);
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+       MALI_DEBUG_ASSERT(system->session->is_aborting);
+
+       MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting soft job system for session 0x%08X.\n", system->session));
+
+       mali_soft_job_system_lock(system);
+
+       for (i = 0; i < MALI_MAX_NUM_SOFT_JOBS; ++i) {
+               job = &(system->jobs[i]);
+
+               MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_FREE      == job->state ||
+                                 MALI_SOFT_JOB_STATE_STARTED   == job->state ||
+                                 MALI_SOFT_JOB_STATE_TIMED_OUT == job->state);
+
+               if (MALI_SOFT_JOB_STATE_STARTED == job->state) {
+                       /* If the job has been activated, we have to release the tracker and destroy
+                        * the job.  If not, the tracker will be released and the job destroyed when
+                        * it is activated. */
+                       if (MALI_TRUE == job->activated) {
+                               MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting unsignaled soft job %u (0x%08X).\n", job->id, job));
+
+                               job->state = MALI_SOFT_JOB_STATE_SIGNALED;
+                               _mali_osk_list_move(&job->system_list, &jobs);
+                       }
+               } else if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) {
+                       MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting timed out soft job %u (0x%08X).\n", job->id, job));
+
+                       /* We need to destroy this soft job. */
+                       _mali_osk_list_move(&job->system_list, &jobs);
+               }
+       }
+
+       mali_soft_job_system_unlock(system);
+
+       /* Release and destroy jobs. */
+       _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &jobs, struct mali_soft_job, system_list) {
+               MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED  == job->state ||
+                                 MALI_SOFT_JOB_STATE_TIMED_OUT == job->state);
+
+               if (MALI_SOFT_JOB_STATE_SIGNALED == job->state) {
+                       mali_timeline_tracker_release(&job->tracker);
+               }
+
+               /* Move job back to used list before destroying. */
+               _mali_osk_list_move(&job->system_list, &system->jobs_used);
+
+               mali_soft_job_destroy(job);
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_soft_job.h b/drivers/gpu/arm/mali400/mali/common/mali_soft_job.h
new file mode 100755 (executable)
index 0000000..1a50dc1
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_SOFT_JOB_H__
+#define __MALI_SOFT_JOB_H__
+
+#include "mali_osk.h"
+
+#include "mali_timeline.h"
+
+struct mali_timeline_fence;
+struct mali_session_data;
+struct mali_soft_job;
+struct mali_soft_job_system;
+
+/**
+ * Soft job types.
+ *
+ * Soft jobs of type MALI_SOFT_JOB_TYPE_USER_SIGNALED will only complete after activation if either
+ * they are signaled by user-space (@ref mali_soft_job_system_signaled_job) or if they are timed out
+ * by the Timeline system.
+ */
+typedef enum mali_soft_job_type {
+       MALI_SOFT_JOB_TYPE_USER_SIGNALED,
+} mali_soft_job_type;
+
+/**
+ * Soft job state.
+ *
+ * All soft jobs in a soft job system will initially be in state MALI_SOFT_JOB_STATE_FREE.  On @ref
+ * mali_soft_job_system_start_job a job will first be allocated.  A job in state
+ * MALI_SOFT_JOB_STATE_FREE will be picked and the state changed to MALI_SOFT_JOB_STATE_ALLOCATED.
+ * Once the job is added to the timeline system, the state changes to MALI_SOFT_JOB_STATE_STARTED.
+ *
+ * For soft jobs of type MALI_SOFT_JOB_TYPE_USER_SIGNALED the state is changed to
+ * MALI_SOFT_JOB_STATE_SIGNALED when @ref mali_soft_job_system_signal_job is called and the soft
+ * job's state is MALI_SOFT_JOB_STATE_STARTED or MALI_SOFT_JOB_STATE_TIMED_OUT.
+ *
+ * If a soft job of type MALI_SOFT_JOB_TYPE_USER_SIGNALED is timed out before being signaled, the
+ * state is changed to MALI_SOFT_JOB_STATE_TIMED_OUT.  This can only happen to soft jobs in state
+ * MALI_SOFT_JOB_STATE_STARTED.
+ *
+ * When a soft job's reference count reaches zero, it will be freed and the state returns to
+ * MALI_SOFT_JOB_STATE_FREE.
+ */
+typedef enum mali_soft_job_state {
+       MALI_SOFT_JOB_STATE_FREE,
+       MALI_SOFT_JOB_STATE_ALLOCATED,
+       MALI_SOFT_JOB_STATE_STARTED,
+       MALI_SOFT_JOB_STATE_SIGNALED,
+       MALI_SOFT_JOB_STATE_TIMED_OUT,
+} mali_soft_job_state;
+
+#define MALI_SOFT_JOB_INVALID_ID ((u32) -1)
+
+/* Maximum number of soft jobs per soft system. */
+#define MALI_MAX_NUM_SOFT_JOBS 20
+
+/**
+ * Soft job struct.
+ *
+ * Soft job can be used to represent any kind of CPU work done in kernel-space.
+ */
+typedef struct mali_soft_job {
+       mali_soft_job_type            type;                   /**< Soft job type.  Must be one of MALI_SOFT_JOB_TYPE_*. */
+       u32                           user_job;               /**< Identifier for soft job in user space. */
+       _mali_osk_atomic_t            refcount;               /**< Soft jobs are reference counted to prevent premature deletion. */
+       struct mali_timeline_tracker  tracker;                /**< Timeline tracker for soft job. */
+       mali_bool                     activated;              /**< MALI_TRUE if the job has been activated, MALI_FALSE if not. */
+       _mali_osk_notification_t     *activated_notification; /**< Pre-allocated notification object for ACTIVATED_NOTIFICATION. */
+
+       /* Protected by soft job system lock. */
+       u32                           id;                     /**< Used by user-space to find corresponding soft job in kernel-space. */
+       mali_soft_job_state           state;                  /**< State of soft job, must be one of MALI_SOFT_JOB_STATE_*. */
+       struct mali_soft_job_system  *system;                 /**< The soft job system this job is in. */
+       _mali_osk_list_t              system_list;            /**< List element used by soft job system. */
+} mali_soft_job;
+
+/**
+ * Per-session soft job system.
+ *
+ * The soft job system is used to manage all soft jobs that belongs to a session.
+ */
+typedef struct mali_soft_job_system {
+       struct mali_session_data *session;                    /**< The session this soft job system belongs to. */
+
+       struct mali_soft_job jobs[MALI_MAX_NUM_SOFT_JOBS];    /**< Array of all soft jobs in this system. */
+       _MALI_OSK_LIST_HEAD(jobs_free);                       /**< List of all free soft jobs. */
+       _MALI_OSK_LIST_HEAD(jobs_used);                       /**< List of all allocated soft jobs. */
+
+       _mali_osk_spinlock_irq_t *lock;                       /**< Lock used to protect soft job system and its soft jobs. */
+       u32 lock_owner;                                       /**< Contains tid of thread that locked the system or 0, if not locked. */
+} mali_soft_job_system;
+
+/**
+ * Create a soft job system.
+ *
+ * @param session The session this soft job system will belong to.
+ * @return The new soft job system, or NULL if unsuccessful.
+ */
+struct mali_soft_job_system *mali_soft_job_system_create(struct mali_session_data *session);
+
+/**
+ * Destroy a soft job system.
+ *
+ * @note The soft job must not have any started or activated jobs.  Call @ref
+ * mali_soft_job_system_abort first.
+ *
+ * @param system The soft job system we are destroying.
+ */
+void mali_soft_job_system_destroy(struct mali_soft_job_system *system);
+
+/**
+ * Create a soft job.
+ *
+ * @param system Soft job system to create soft job from.
+ * @param type Type of the soft job.
+ * @param user_job Identifier for soft job in user space.
+ * @return New soft job if successful, NULL if not.
+ */
+struct mali_soft_job *mali_soft_job_create(struct mali_soft_job_system *system, mali_soft_job_type type, u32 user_job);
+
+/**
+ * Destroy soft job.
+ *
+ * @param job Soft job to destroy.
+ */
+void mali_soft_job_destroy(struct mali_soft_job *job);
+
+/**
+ * Start a soft job.
+ *
+ * The soft job will be added to the Timeline system which will then activate it after all
+ * dependencies have been resolved.
+ *
+ * Create soft jobs with @ref mali_soft_job_create before starting them.
+ *
+ * @param job Soft job to start.
+ * @param fence Fence representing dependencies for this soft job.
+ * @return Point on soft job timeline.
+ */
+mali_timeline_point mali_soft_job_start(struct mali_soft_job *job, struct mali_timeline_fence *fence);
+
+/**
+ * Use by user-space to signal that a soft job has completed.
+ *
+ * @note Only valid for soft jobs with type MALI_SOFT_JOB_TYPE_USER_SIGNALED.
+ *
+ * @note The soft job must be in state MALI_SOFT_JOB_STATE_STARTED for the signal to be successful.
+ *
+ * @note If the soft job was signaled successfully, or it received a time out, the soft job will be
+ * destroyed after this call and should no longer be used.
+ *
+ * @note This function will block until the soft job has been activated.
+ *
+ * @param system The soft job system the job was started in.
+ * @param job_id ID of soft job we are signaling.
+ *
+ * @return _MALI_OSK_ERR_ITEM_NOT_FOUND if the soft job ID was invalid, _MALI_OSK_ERR_TIMEOUT if the
+ * soft job was timed out or _MALI_OSK_ERR_OK if we successfully signaled the soft job.
+ */
+_mali_osk_errcode_t mali_soft_job_system_signal_job(struct mali_soft_job_system *system, u32 job_id);
+
+/**
+ * Used by the Timeline system to activate a soft job.
+ *
+ * @param job The soft job that is being activated.
+ */
+void mali_soft_job_system_activate_job(struct mali_soft_job *job);
+
+/**
+ * Used by the Timeline system to timeout a soft job.
+ *
+ * A soft job is timed out if it completes or is signaled later than MALI_TIMELINE_TIMEOUT_HZ after
+ * activation.
+ *
+ * @param job The soft job that is being timed out.
+ * @return A scheduling bitmask.
+ */
+mali_scheduler_mask mali_soft_job_system_timeout_job(struct mali_soft_job *job);
+
+/**
+ * Used to cleanup activated soft jobs in the soft job system on session abort.
+ *
+ * @param system The soft job system that is being aborted.
+ */
+void mali_soft_job_system_abort(struct mali_soft_job_system *system);
+
+#endif /* __MALI_SOFT_JOB_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_spinlock_reentrant.c b/drivers/gpu/arm/mali400/mali/common/mali_spinlock_reentrant.c
new file mode 100755 (executable)
index 0000000..e11feee
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_spinlock_reentrant.h"
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+struct mali_spinlock_reentrant *mali_spinlock_reentrant_init(_mali_osk_lock_order_t lock_order)
+{
+       struct mali_spinlock_reentrant *spinlock;
+
+       spinlock = _mali_osk_calloc(1, sizeof(struct mali_spinlock_reentrant));
+       if (NULL == spinlock) {
+               return NULL;
+       }
+
+       spinlock->lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, lock_order);
+       if (NULL == spinlock->lock) {
+               mali_spinlock_reentrant_term(spinlock);
+               return NULL;
+       }
+
+       return spinlock;
+}
+
+void mali_spinlock_reentrant_term(struct mali_spinlock_reentrant *spinlock)
+{
+       MALI_DEBUG_ASSERT_POINTER(spinlock);
+       MALI_DEBUG_ASSERT(0 == spinlock->counter && 0 == spinlock->owner);
+
+       if (NULL != spinlock->lock) {
+               _mali_osk_spinlock_irq_term(spinlock->lock);
+       }
+
+       _mali_osk_free(spinlock);
+}
+
+void mali_spinlock_reentrant_wait(struct mali_spinlock_reentrant *spinlock, u32 tid)
+{
+       MALI_DEBUG_ASSERT_POINTER(spinlock);
+       MALI_DEBUG_ASSERT_POINTER(spinlock->lock);
+       MALI_DEBUG_ASSERT(0 != tid);
+
+       MALI_DEBUG_PRINT(5, ("%s ^\n", __FUNCTION__));
+
+       if (tid != spinlock->owner) {
+               _mali_osk_spinlock_irq_lock(spinlock->lock);
+               MALI_DEBUG_ASSERT(0 == spinlock->owner && 0 == spinlock->counter);
+               spinlock->owner = tid;
+       }
+
+       MALI_DEBUG_PRINT(5, ("%s v\n", __FUNCTION__));
+
+       ++spinlock->counter;
+}
+
+void mali_spinlock_reentrant_signal(struct mali_spinlock_reentrant *spinlock, u32 tid)
+{
+       MALI_DEBUG_ASSERT_POINTER(spinlock);
+       MALI_DEBUG_ASSERT_POINTER(spinlock->lock);
+       MALI_DEBUG_ASSERT(0 != tid && tid == spinlock->owner);
+
+       --spinlock->counter;
+       if (0 == spinlock->counter) {
+               spinlock->owner = 0;
+               MALI_DEBUG_PRINT(5, ("%s release last\n", __FUNCTION__));
+               _mali_osk_spinlock_irq_unlock(spinlock->lock);
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_spinlock_reentrant.h b/drivers/gpu/arm/mali400/mali/common/mali_spinlock_reentrant.h
new file mode 100755 (executable)
index 0000000..2dc7ab9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_SPINLOCK_REENTRANT_H__
+#define __MALI_SPINLOCK_REENTRANT_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+/**
+ * Reentrant spinlock.
+ */
+struct mali_spinlock_reentrant {
+       _mali_osk_spinlock_irq_t *lock;
+       u32               owner;
+       u32               counter;
+};
+
+/**
+ * Create a new reentrant spinlock.
+ *
+ * @param lock_order Lock order.
+ * @return New reentrant spinlock.
+ */
+struct mali_spinlock_reentrant *mali_spinlock_reentrant_init(_mali_osk_lock_order_t lock_order);
+
+/**
+ * Terminate reentrant spinlock and free any associated resources.
+ *
+ * @param spinlock Reentrant spinlock to terminate.
+ */
+void mali_spinlock_reentrant_term(struct mali_spinlock_reentrant *spinlock);
+
+/**
+ * Wait for reentrant spinlock to be signaled.
+ *
+ * @param spinlock Reentrant spinlock.
+ * @param tid Thread ID.
+ */
+void mali_spinlock_reentrant_wait(struct mali_spinlock_reentrant *spinlock, u32 tid);
+
+/**
+ * Signal reentrant spinlock.
+ *
+ * @param spinlock Reentrant spinlock.
+ * @param tid Thread ID.
+ */
+void mali_spinlock_reentrant_signal(struct mali_spinlock_reentrant *spinlock, u32 tid);
+
+/**
+ * Check if thread is holding reentrant spinlock.
+ *
+ * @param spinlock Reentrant spinlock.
+ * @param tid Thread ID.
+ * @return MALI_TRUE if thread is holding spinlock, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_spinlock_reentrant_is_held(struct mali_spinlock_reentrant *spinlock, u32 tid)
+{
+       MALI_DEBUG_ASSERT_POINTER(spinlock->lock);
+       return (tid == spinlock->owner && 0 < spinlock->counter);
+}
+
+#endif /* __MALI_SPINLOCK_REENTRANT_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_timeline.c b/drivers/gpu/arm/mali400/mali/common/mali_timeline.c
new file mode 100755 (executable)
index 0000000..c7b18b5
--- /dev/null
@@ -0,0 +1,1374 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_timeline.h"
+#include "mali_kernel_common.h"
+#include "mali_osk_mali.h"
+#include "mali_scheduler.h"
+#include "mali_soft_job.h"
+#include "mali_timeline_fence_wait.h"
+#include "mali_timeline_sync_fence.h"
+
+#define MALI_TIMELINE_SYSTEM_LOCKED(system) (mali_spinlock_reentrant_is_held((system)->spinlock, _mali_osk_get_tid()))
+
+static mali_scheduler_mask mali_timeline_system_release_waiter(struct mali_timeline_system *system,
+        struct mali_timeline_waiter *waiter);
+
+#if defined(CONFIG_SYNC)
+/* Callback that is called when a sync fence a tracker is waiting on is signaled. */
+static void mali_timeline_sync_fence_callback(struct sync_fence *sync_fence, struct sync_fence_waiter *sync_fence_waiter)
+{
+       struct mali_timeline_system  *system;
+       struct mali_timeline_waiter  *waiter;
+       struct mali_timeline_tracker *tracker;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+       u32 tid = _mali_osk_get_tid();
+       mali_bool is_aborting = MALI_FALSE;
+       int fence_status = sync_fence->status;
+
+       MALI_DEBUG_ASSERT_POINTER(sync_fence);
+       MALI_DEBUG_ASSERT_POINTER(sync_fence_waiter);
+
+       tracker = _MALI_OSK_CONTAINER_OF(sync_fence_waiter, struct mali_timeline_tracker, sync_fence_waiter);
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       system = tracker->system;
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       is_aborting = system->session->is_aborting;
+       if (!is_aborting && (0 > fence_status)) {
+               MALI_PRINT_ERROR(("Mali Timeline: sync fence fd %d signaled with error %d\n", tracker->fence.sync_fd, fence_status));
+               tracker->activation_error |= MALI_TIMELINE_ACTIVATION_ERROR_SYNC_BIT;
+       }
+
+       waiter = tracker->waiter_sync;
+       MALI_DEBUG_ASSERT_POINTER(waiter);
+
+       tracker->sync_fence = NULL;
+       schedule_mask |= mali_timeline_system_release_waiter(system, waiter);
+
+       /* If aborting, wake up sleepers that are waiting for sync fence callbacks to complete. */
+       if (is_aborting) {
+               _mali_osk_wait_queue_wake_up(system->wait_queue);
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       sync_fence_put(sync_fence);
+
+       if (!is_aborting) {
+               mali_scheduler_schedule_from_mask(schedule_mask, MALI_TRUE);
+       }
+}
+#endif /* defined(CONFIG_SYNC) */
+
+static mali_scheduler_mask mali_timeline_tracker_time_out(struct mali_timeline_tracker *tracker)
+{
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_TRACKER_SOFT == tracker->type);
+
+       return mali_soft_job_system_timeout_job((struct mali_soft_job *) tracker->job);
+}
+
+static void mali_timeline_timer_callback(void *data)
+{
+       struct mali_timeline_system *system;
+       struct mali_timeline_tracker *tracker;
+       struct mali_timeline *timeline;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+       u32 tid = _mali_osk_get_tid();
+
+       timeline = (struct mali_timeline *) data;
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+
+       system = timeline->system;
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       if (!system->timer_enabled) {
+               mali_spinlock_reentrant_signal(system->spinlock, tid);
+               return;
+       }
+
+       tracker = timeline->tracker_tail;
+       timeline->timer_active = MALI_FALSE;
+
+       if (NULL != tracker && MALI_TRUE == tracker->timer_active) {
+               /* This is likely the delayed work that has been schedule out before cancelled. */
+               if (MALI_TIMELINE_TIMEOUT_HZ > (_mali_osk_time_tickcount() - tracker->os_tick_activate)) {
+                       mali_spinlock_reentrant_signal(system->spinlock, tid);
+                       return;
+               }
+
+               schedule_mask = mali_timeline_tracker_time_out(tracker);
+               tracker->timer_active = MALI_FALSE;
+       } else {
+               MALI_PRINT_ERROR(("Mali Timeline: Soft job timer callback without a waiting tracker.\n"));
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE);
+}
+
+void mali_timeline_system_stop_timer(struct mali_timeline_system *system)
+{
+       u32 i;
+       u32 tid = _mali_osk_get_tid();
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+       system->timer_enabled = MALI_FALSE;
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               struct mali_timeline *timeline = system->timelines[i];
+
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               if (NULL != timeline->delayed_work) {
+                       _mali_osk_wq_delayed_cancel_work_sync(timeline->delayed_work);
+                       timeline->timer_active = MALI_FALSE;
+               }
+       }
+}
+
+static void mali_timeline_destroy(struct mali_timeline *timeline)
+{
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       if (NULL != timeline) {
+               /* Assert that the timeline object has been properly cleaned up before destroying it. */
+               MALI_DEBUG_ASSERT(timeline->point_oldest == timeline->point_next);
+               MALI_DEBUG_ASSERT(NULL == timeline->tracker_head);
+               MALI_DEBUG_ASSERT(NULL == timeline->tracker_tail);
+               MALI_DEBUG_ASSERT(NULL == timeline->waiter_head);
+               MALI_DEBUG_ASSERT(NULL == timeline->waiter_tail);
+               MALI_DEBUG_ASSERT(NULL != timeline->system);
+               MALI_DEBUG_ASSERT(MALI_TIMELINE_MAX > timeline->id);
+
+#if defined(CONFIG_SYNC)
+               if (NULL != timeline->sync_tl) {
+                       sync_timeline_destroy(timeline->sync_tl);
+               }
+#endif /* defined(CONFIG_SYNC) */
+
+               if (NULL != timeline->delayed_work) {
+                       _mali_osk_wq_delayed_cancel_work_sync(timeline->delayed_work);
+                       _mali_osk_wq_delayed_delete_work_nonflush(timeline->delayed_work);
+               }
+
+               _mali_osk_free(timeline);
+       }
+}
+
+static struct mali_timeline *mali_timeline_create(struct mali_timeline_system *system, enum mali_timeline_id id)
+{
+       struct mali_timeline *timeline;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT(id < MALI_TIMELINE_MAX);
+
+       timeline = (struct mali_timeline *) _mali_osk_calloc(1, sizeof(struct mali_timeline));
+       if (NULL == timeline) {
+               return NULL;
+       }
+
+       /* Initially the timeline is empty. */
+#if defined(MALI_TIMELINE_DEBUG_START_POINT)
+       /* Start the timeline a bit before wrapping when debugging. */
+       timeline->point_next = UINT_MAX - MALI_TIMELINE_MAX_POINT_SPAN - 128;
+#else
+       timeline->point_next = 1;
+#endif
+       timeline->point_oldest = timeline->point_next;
+
+       /* The tracker and waiter lists will initially be empty. */
+
+       timeline->system = system;
+       timeline->id = id;
+
+       timeline->delayed_work = _mali_osk_wq_delayed_create_work(mali_timeline_timer_callback, timeline);
+       if (NULL == timeline->delayed_work) {
+               mali_timeline_destroy(timeline);
+               return NULL;
+       }
+
+       timeline->timer_active = MALI_FALSE;
+
+#if defined(CONFIG_SYNC)
+       {
+               char timeline_name[32];
+
+               switch (id) {
+               case MALI_TIMELINE_GP:
+                       _mali_osk_snprintf(timeline_name, 32, "mali-%u-gp", _mali_osk_get_pid());
+                       break;
+               case MALI_TIMELINE_PP:
+                       _mali_osk_snprintf(timeline_name, 32, "mali-%u-pp", _mali_osk_get_pid());
+                       break;
+               case MALI_TIMELINE_SOFT:
+                       _mali_osk_snprintf(timeline_name, 32, "mali-%u-soft", _mali_osk_get_pid());
+                       break;
+               default:
+                       MALI_PRINT_ERROR(("Mali Timeline: Invalid timeline id %d\n", id));
+                       mali_timeline_destroy(timeline);
+                       return NULL;
+               }
+
+               timeline->sync_tl = mali_sync_timeline_create(timeline_name);
+               if (NULL == timeline->sync_tl) {
+                       mali_timeline_destroy(timeline);
+                       return NULL;
+               }
+       }
+#endif /* defined(CONFIG_SYNC) */
+
+       return timeline;
+}
+
+static void mali_timeline_insert_tracker(struct mali_timeline *timeline, struct mali_timeline_tracker *tracker)
+{
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       if (mali_timeline_is_full(timeline)) {
+               /* Don't add tracker if timeline is full. */
+               tracker->point = MALI_TIMELINE_NO_POINT;
+               return;
+       }
+
+       tracker->timeline = timeline;
+       tracker->point    = timeline->point_next;
+
+       /* Find next available point. */
+       timeline->point_next++;
+       if (MALI_TIMELINE_NO_POINT == timeline->point_next) {
+               timeline->point_next++;
+       }
+
+       MALI_DEBUG_ASSERT(!mali_timeline_is_empty(timeline));
+
+       /* Add tracker as new head on timeline's tracker list. */
+       if (NULL == timeline->tracker_head) {
+               /* Tracker list is empty. */
+               MALI_DEBUG_ASSERT(NULL == timeline->tracker_tail);
+
+               timeline->tracker_tail = tracker;
+
+               MALI_DEBUG_ASSERT(NULL == tracker->timeline_next);
+               MALI_DEBUG_ASSERT(NULL == tracker->timeline_prev);
+       } else {
+               MALI_DEBUG_ASSERT(NULL == timeline->tracker_head->timeline_next);
+
+               tracker->timeline_prev = timeline->tracker_head;
+               timeline->tracker_head->timeline_next = tracker;
+
+               MALI_DEBUG_ASSERT(NULL == tracker->timeline_next);
+       }
+       timeline->tracker_head = tracker;
+
+       MALI_DEBUG_ASSERT(NULL == timeline->tracker_head->timeline_next);
+       MALI_DEBUG_ASSERT(NULL == timeline->tracker_tail->timeline_prev);
+}
+
+/* Inserting the waiter object into the given timeline */
+static void mali_timeline_insert_waiter(struct mali_timeline *timeline, struct mali_timeline_waiter *waiter_new)
+{
+       struct mali_timeline_waiter *waiter_prev;
+       struct mali_timeline_waiter *waiter_next;
+
+       /* Waiter time must be between timeline head and tail, and there must
+        * be less than MALI_TIMELINE_MAX_POINT_SPAN elements between */
+       MALI_DEBUG_ASSERT(( waiter_new->point - timeline->point_oldest) < MALI_TIMELINE_MAX_POINT_SPAN);
+       MALI_DEBUG_ASSERT((-waiter_new->point + timeline->point_next) < MALI_TIMELINE_MAX_POINT_SPAN);
+
+       /* Finding out where to put this waiter, in the linked waiter list of the given timeline **/
+       waiter_prev = timeline->waiter_head; /* Insert new after  waiter_prev */
+       waiter_next = NULL;                  /* Insert new before waiter_next */
+
+       /* Iterating backwards from head (newest) to tail (oldest) until we
+        * find the correct spot to insert the new waiter */
+       while (waiter_prev && mali_timeline_point_after(waiter_prev->point, waiter_new->point)) {
+               waiter_next = waiter_prev;
+               waiter_prev = waiter_prev->timeline_prev;
+       }
+
+       if (NULL == waiter_prev && NULL == waiter_next) {
+               /* list is empty */
+               timeline->waiter_head = waiter_new;
+               timeline->waiter_tail = waiter_new;
+       } else if (NULL == waiter_next) {
+               /* insert at head */
+               waiter_new->timeline_prev = timeline->waiter_head;
+               timeline->waiter_head->timeline_next = waiter_new;
+               timeline->waiter_head = waiter_new;
+       } else if (NULL == waiter_prev) {
+               /* insert at tail */
+               waiter_new->timeline_next = timeline->waiter_tail;
+               timeline->waiter_tail->timeline_prev = waiter_new;
+               timeline->waiter_tail = waiter_new;
+       } else {
+               /* insert between */
+               waiter_new->timeline_next = waiter_next;
+               waiter_new->timeline_prev = waiter_prev;
+               waiter_next->timeline_prev = waiter_new;
+               waiter_prev->timeline_next = waiter_new;
+       }
+}
+
+static void mali_timeline_update_delayed_work(struct mali_timeline *timeline)
+{
+       struct mali_timeline_system *system;
+       struct mali_timeline_tracker *oldest_tracker;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SOFT == timeline->id);
+
+       system = timeline->system;
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       /* Timer is disabled, early out. */
+       if (!system->timer_enabled) return;
+
+       oldest_tracker = timeline->tracker_tail;
+       if (NULL != oldest_tracker && 0 == oldest_tracker->trigger_ref_count) {
+               if (MALI_FALSE == oldest_tracker->timer_active) {
+                       if (MALI_TRUE == timeline->timer_active) {
+                               _mali_osk_wq_delayed_cancel_work_async(timeline->delayed_work);
+                       }
+                       _mali_osk_wq_delayed_schedule_work(timeline->delayed_work, MALI_TIMELINE_TIMEOUT_HZ);
+                       oldest_tracker->timer_active = MALI_TRUE;
+                       timeline->timer_active = MALI_TRUE;
+               }
+       } else if (MALI_TRUE == timeline->timer_active) {
+               _mali_osk_wq_delayed_cancel_work_async(timeline->delayed_work);
+               timeline->timer_active = MALI_FALSE;
+       }
+}
+
+static mali_scheduler_mask mali_timeline_update_oldest_point(struct mali_timeline *timeline)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+
+       MALI_DEBUG_CODE({
+               struct mali_timeline_system *system = timeline->system;
+               MALI_DEBUG_ASSERT_POINTER(system);
+
+               MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+       });
+
+       if (NULL != timeline->tracker_tail) {
+               /* Set oldest point to oldest tracker's point */
+               timeline->point_oldest = timeline->tracker_tail->point;
+       } else {
+               /* No trackers, mark point list as empty */
+               timeline->point_oldest = timeline->point_next;
+       }
+
+       /* Release all waiters no longer on the timeline's point list.
+        * Releasing a waiter can trigger this function to be called again, so
+        * we do not store any pointers on stack. */
+       while (NULL != timeline->waiter_tail) {
+               u32 waiter_time_relative;
+               u32 time_head_relative;
+               struct mali_timeline_waiter *waiter = timeline->waiter_tail;
+
+               time_head_relative = timeline->point_next - timeline->point_oldest;
+               waiter_time_relative = waiter->point - timeline->point_oldest;
+
+               if (waiter_time_relative < time_head_relative) {
+                       /* This and all following waiters are on the point list, so we are done. */
+                       break;
+               }
+
+               /* Remove waiter from timeline's waiter list. */
+               if (NULL != waiter->timeline_next) {
+                       waiter->timeline_next->timeline_prev = NULL;
+               } else {
+                       /* This was the last waiter */
+                       timeline->waiter_head = NULL;
+               }
+               timeline->waiter_tail = waiter->timeline_next;
+
+               /* Release waiter.  This could activate a tracker, if this was
+                * the last waiter for the tracker. */
+               schedule_mask |= mali_timeline_system_release_waiter(timeline->system, waiter);
+       }
+
+       return schedule_mask;
+}
+
+void mali_timeline_tracker_init(struct mali_timeline_tracker *tracker,
+                                mali_timeline_tracker_type type,
+                                struct mali_timeline_fence *fence,
+                                void *job)
+{
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       MALI_DEBUG_ASSERT_POINTER(job);
+
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_TRACKER_MAX > type);
+
+       /* Zero out all tracker members. */
+       _mali_osk_memset(tracker, 0, sizeof(*tracker));
+
+       tracker->type = type;
+       tracker->job = job;
+       tracker->trigger_ref_count = 1;  /* Prevents any callback from trigging while adding it */
+       tracker->os_tick_create = _mali_osk_time_tickcount();
+       MALI_DEBUG_CODE(tracker->magic = MALI_TIMELINE_TRACKER_MAGIC);
+
+       tracker->activation_error = MALI_TIMELINE_ACTIVATION_ERROR_NONE;
+
+       /* Copy fence. */
+       if (NULL != fence) {
+               _mali_osk_memcpy(&tracker->fence, fence, sizeof(struct mali_timeline_fence));
+       }
+}
+
+mali_scheduler_mask mali_timeline_tracker_release(struct mali_timeline_tracker *tracker)
+{
+       struct mali_timeline *timeline;
+       struct mali_timeline_system *system;
+       struct mali_timeline_tracker *tracker_next, *tracker_prev;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+       u32 tid = _mali_osk_get_tid();
+
+       /* Upon entry a group lock will be held, but not a scheduler lock. */
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_TRACKER_MAGIC == tracker->magic);
+
+       /* Tracker should have been triggered */
+       MALI_DEBUG_ASSERT(0 == tracker->trigger_ref_count);
+
+       /* All waiters should have been released at this point */
+       MALI_DEBUG_ASSERT(NULL == tracker->waiter_head);
+       MALI_DEBUG_ASSERT(NULL == tracker->waiter_tail);
+
+       MALI_DEBUG_PRINT(3, ("Mali Timeline: releasing tracker for job 0x%08X\n", tracker->job));
+
+       timeline = tracker->timeline;
+       if (NULL == timeline) {
+               /* Tracker was not on a timeline, there is nothing to release. */
+               return MALI_SCHEDULER_MASK_EMPTY;
+       }
+
+       system = timeline->system;
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       /* Tracker should still be on timeline */
+       MALI_DEBUG_ASSERT(!mali_timeline_is_empty(timeline));
+       MALI_DEBUG_ASSERT( mali_timeline_is_point_on(timeline, tracker->point));
+
+       /* Tracker is no longer valid. */
+       MALI_DEBUG_CODE(tracker->magic = 0);
+
+       tracker_next = tracker->timeline_next;
+       tracker_prev = tracker->timeline_prev;
+       tracker->timeline_next = NULL;
+       tracker->timeline_prev = NULL;
+
+       /* Removing tracker from timeline's tracker list */
+       if (NULL == tracker_next) {
+               /* This tracker was the head */
+               timeline->tracker_head = tracker_prev;
+       } else {
+               tracker_next->timeline_prev = tracker_prev;
+       }
+
+       if (NULL == tracker_prev) {
+               /* This tracker was the tail */
+               timeline->tracker_tail = tracker_next;
+               MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+               /* Update the timeline's oldest time and release any waiters */
+               schedule_mask |= mali_timeline_update_oldest_point(timeline);
+               MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+       } else {
+               tracker_prev->timeline_next = tracker_next;
+       }
+
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       /* Update delayed work only when it is the soft job timeline */
+       if (MALI_TIMELINE_SOFT == tracker->timeline->id) {
+               mali_timeline_update_delayed_work(tracker->timeline);
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       return schedule_mask;
+}
+
+void mali_timeline_system_release_waiter_list(struct mali_timeline_system *system,
+        struct mali_timeline_waiter *tail,
+        struct mali_timeline_waiter *head)
+{
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(head);
+       MALI_DEBUG_ASSERT_POINTER(tail);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       head->tracker_next = system->waiter_empty_list;
+       system->waiter_empty_list = tail;
+}
+
+static mali_scheduler_mask mali_timeline_tracker_activate(struct mali_timeline_tracker *tracker)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+       struct mali_timeline_system *system;
+       struct mali_timeline *timeline;
+       u32 tid = _mali_osk_get_tid();
+
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_TRACKER_MAGIC == tracker->magic);
+
+       system = tracker->system;
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       tracker->os_tick_activate = _mali_osk_time_tickcount();
+
+       if (NULL != tracker->waiter_head) {
+               mali_timeline_system_release_waiter_list(system, tracker->waiter_tail, tracker->waiter_head);
+               tracker->waiter_head = NULL;
+               tracker->waiter_tail = NULL;
+       }
+
+       switch (tracker->type) {
+       case MALI_TIMELINE_TRACKER_GP:
+               schedule_mask = mali_gp_scheduler_activate_job((struct mali_gp_job *) tracker->job);
+               break;
+       case MALI_TIMELINE_TRACKER_PP:
+               schedule_mask = mali_pp_scheduler_activate_job((struct mali_pp_job *) tracker->job);
+               break;
+       case MALI_TIMELINE_TRACKER_SOFT:
+               timeline = tracker->timeline;
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               mali_soft_job_system_activate_job((struct mali_soft_job *) tracker->job);
+
+               /* Start a soft timer to make sure the soft job be released in a limited time */
+               mali_spinlock_reentrant_wait(system->spinlock, tid);
+               mali_timeline_update_delayed_work(timeline);
+               mali_spinlock_reentrant_signal(system->spinlock, tid);
+               break;
+       case MALI_TIMELINE_TRACKER_WAIT:
+               mali_timeline_fence_wait_activate((struct mali_timeline_fence_wait_tracker *) tracker->job);
+               break;
+       case MALI_TIMELINE_TRACKER_SYNC:
+#if defined(CONFIG_SYNC)
+               mali_timeline_sync_fence_activate((struct mali_timeline_sync_fence_tracker *) tracker->job);
+#else
+               MALI_PRINT_ERROR(("Mali Timeline: sync tracker not supported\n", tracker->type));
+#endif /* defined(CONFIG_SYNC) */
+               break;
+       default:
+               MALI_PRINT_ERROR(("Mali Timeline - Illegal tracker type: %d\n", tracker->type));
+               break;
+       }
+
+       return schedule_mask;
+}
+
+void mali_timeline_system_tracker_get(struct mali_timeline_system *system, struct mali_timeline_tracker *tracker)
+{
+       u32 tid = _mali_osk_get_tid();
+
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       MALI_DEBUG_ASSERT(0 < tracker->trigger_ref_count);
+       tracker->trigger_ref_count++;
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+}
+
+mali_scheduler_mask mali_timeline_system_tracker_put(struct mali_timeline_system *system, struct mali_timeline_tracker *tracker, mali_timeline_activation_error activation_error)
+{
+       u32 tid = _mali_osk_get_tid();
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       MALI_DEBUG_ASSERT(0 < tracker->trigger_ref_count);
+       tracker->trigger_ref_count--;
+
+       tracker->activation_error |= activation_error;
+
+       if (0 == tracker->trigger_ref_count) {
+               schedule_mask |= mali_timeline_tracker_activate(tracker);
+               tracker = NULL;
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       return schedule_mask;
+}
+
+void mali_timeline_fence_copy_uk_fence(struct mali_timeline_fence *fence, _mali_uk_fence_t *uk_fence)
+{
+       u32 i;
+
+       MALI_DEBUG_ASSERT_POINTER(fence);
+       MALI_DEBUG_ASSERT_POINTER(uk_fence);
+
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               fence->points[i] = uk_fence->points[i];
+       }
+
+       fence->sync_fd = uk_fence->sync_fd;
+}
+
+struct mali_timeline_system *mali_timeline_system_create(struct mali_session_data *session)
+{
+       u32 i;
+       struct mali_timeline_system *system;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_PRINT(4, ("Mali Timeline: creating timeline system\n"));
+
+       system = (struct mali_timeline_system *) _mali_osk_calloc(1, sizeof(struct mali_timeline_system));
+       if (NULL == system) {
+               return NULL;
+       }
+
+       system->spinlock = mali_spinlock_reentrant_init(_MALI_OSK_LOCK_ORDER_TIMELINE_SYSTEM);
+       if (NULL == system->spinlock) {
+               mali_timeline_system_destroy(system);
+               return NULL;
+       }
+
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               system->timelines[i] = mali_timeline_create(system, (enum mali_timeline_id)i);
+               if (NULL == system->timelines[i]) {
+                       mali_timeline_system_destroy(system);
+                       return NULL;
+               }
+       }
+
+#if defined(CONFIG_SYNC)
+       system->signaled_sync_tl = mali_sync_timeline_create("mali-always-signaled");
+       if (NULL == system->signaled_sync_tl) {
+               mali_timeline_system_destroy(system);
+               return NULL;
+       }
+#endif /* defined(CONFIG_SYNC) */
+
+       system->waiter_empty_list = NULL;
+       system->session = session;
+       system->timer_enabled = MALI_TRUE;
+
+       system->wait_queue = _mali_osk_wait_queue_init();
+       if (NULL == system->wait_queue) {
+               mali_timeline_system_destroy(system);
+               return NULL;
+       }
+
+       return system;
+}
+
+#if defined(CONFIG_SYNC)
+
+/**
+ * Check if there are any trackers left on timeline.
+ *
+ * Used as a wait queue conditional.
+ *
+ * @param data Timeline.
+ * @return MALI_TRUE if there are no trackers on timeline, MALI_FALSE if not.
+ */
+static mali_bool mali_timeline_has_no_trackers(void *data)
+{
+       struct mali_timeline *timeline = (struct mali_timeline *) data;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+
+       return mali_timeline_is_empty(timeline);
+}
+
+/**
+ * Cancel sync fence waiters waited upon by trackers on all timelines.
+ *
+ * Will return after all timelines have no trackers left.
+ *
+ * @param system Timeline system.
+ */
+static void mali_timeline_cancel_sync_fence_waiters(struct mali_timeline_system *system)
+{
+       u32 i;
+       u32 tid = _mali_osk_get_tid();
+       struct mali_timeline_tracker *tracker, *tracker_next;
+       _MALI_OSK_LIST_HEAD_STATIC_INIT(tracker_list);
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+       MALI_DEBUG_ASSERT(system->session->is_aborting);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       /* Cancel sync fence waiters. */
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               struct mali_timeline *timeline = system->timelines[i];
+
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               tracker_next = timeline->tracker_tail;
+               while (NULL != tracker_next) {
+                       tracker = tracker_next;
+                       tracker_next = tracker->timeline_next;
+
+                       if (NULL == tracker->sync_fence) continue;
+
+                       MALI_DEBUG_PRINT(3, ("Mali Timeline: Cancelling sync fence wait for tracker 0x%08X.\n", tracker));
+
+                       /* Cancel sync fence waiter. */
+                       if (0 == sync_fence_cancel_async(tracker->sync_fence, &tracker->sync_fence_waiter)) {
+                               /* Callback was not called, move tracker to local list. */
+                               _mali_osk_list_add(&tracker->sync_fence_cancel_list, &tracker_list);
+                       }
+               }
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       /* Manually call sync fence callback in order to release waiter and trigger activation of tracker. */
+       _MALI_OSK_LIST_FOREACHENTRY(tracker, tracker_next, &tracker_list, struct mali_timeline_tracker, sync_fence_cancel_list) {
+               mali_timeline_sync_fence_callback(tracker->sync_fence, &tracker->sync_fence_waiter);
+       }
+
+       /* Sleep until all sync fence callbacks are done and all timelines are empty. */
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               struct mali_timeline *timeline = system->timelines[i];
+
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               _mali_osk_wait_queue_wait_event(system->wait_queue, mali_timeline_has_no_trackers, (void *) timeline);
+       }
+}
+
+#endif /* defined(CONFIG_SYNC) */
+
+void mali_timeline_system_abort(struct mali_timeline_system *system)
+{
+       MALI_DEBUG_CODE(u32 tid = _mali_osk_get_tid(););
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+       MALI_DEBUG_ASSERT(system->session->is_aborting);
+
+       MALI_DEBUG_PRINT(3, ("Mali Timeline: Aborting timeline system for session 0x%08X.\n", system->session));
+
+#if defined(CONFIG_SYNC)
+       mali_timeline_cancel_sync_fence_waiters(system);
+#endif /* defined(CONFIG_SYNC) */
+
+       /* Should not be any waiters or trackers left at this point. */
+       MALI_DEBUG_CODE( {
+               u32 i;
+               mali_spinlock_reentrant_wait(system->spinlock, tid);
+               for (i = 0; i < MALI_TIMELINE_MAX; ++i)
+               {
+                       struct mali_timeline *timeline = system->timelines[i];
+                       MALI_DEBUG_ASSERT_POINTER(timeline);
+                       MALI_DEBUG_ASSERT(timeline->point_oldest == timeline->point_next);
+                       MALI_DEBUG_ASSERT(NULL == timeline->tracker_head);
+                       MALI_DEBUG_ASSERT(NULL == timeline->tracker_tail);
+                       MALI_DEBUG_ASSERT(NULL == timeline->waiter_head);
+                       MALI_DEBUG_ASSERT(NULL == timeline->waiter_tail);
+               }
+               mali_spinlock_reentrant_signal(system->spinlock, tid);
+       });
+}
+
+void mali_timeline_system_destroy(struct mali_timeline_system *system)
+{
+       u32 i;
+       struct mali_timeline_waiter *waiter, *next;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+
+       MALI_DEBUG_PRINT(4, ("Mali Timeline: destroying timeline system\n"));
+
+       if (NULL != system) {
+               /* There should be no waiters left on this queue. */
+               if (NULL != system->wait_queue) {
+                       _mali_osk_wait_queue_term(system->wait_queue);
+                       system->wait_queue = NULL;
+               }
+
+               /* Free all waiters in empty list */
+               waiter = system->waiter_empty_list;
+               while (NULL != waiter) {
+                       next = waiter->tracker_next;
+                       _mali_osk_free(waiter);
+                       waiter = next;
+               }
+
+#if defined(CONFIG_SYNC)
+               if (NULL != system->signaled_sync_tl) {
+                       sync_timeline_destroy(system->signaled_sync_tl);
+               }
+#endif /* defined(CONFIG_SYNC) */
+
+               for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+                       if (NULL != system->timelines[i]) {
+                               mali_timeline_destroy(system->timelines[i]);
+                       }
+               }
+               if (NULL != system->spinlock) {
+                       mali_spinlock_reentrant_term(system->spinlock);
+               }
+
+               _mali_osk_free(system);
+       }
+}
+
+/**
+ * Find how many waiters are needed for a given fence.
+ *
+ * @param fence The fence to check.
+ * @return Number of waiters needed for fence.
+ */
+static u32 mali_timeline_fence_num_waiters(struct mali_timeline_fence *fence)
+{
+       u32 i, num_waiters = 0;
+
+       MALI_DEBUG_ASSERT_POINTER(fence);
+
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               if (MALI_TIMELINE_NO_POINT != fence->points[i]) {
+                       ++num_waiters;
+               }
+       }
+
+#if defined(CONFIG_SYNC)
+       if (-1 != fence->sync_fd) ++num_waiters;
+#endif /* defined(CONFIG_SYNC) */
+
+       return num_waiters;
+}
+
+static struct mali_timeline_waiter *mali_timeline_system_get_zeroed_waiter(struct mali_timeline_system *system)
+{
+       struct mali_timeline_waiter *waiter;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       waiter = system->waiter_empty_list;
+       if (NULL != waiter) {
+               /* Remove waiter from empty list and zero it */
+               system->waiter_empty_list = waiter->tracker_next;
+               _mali_osk_memset(waiter, 0, sizeof(*waiter));
+       }
+
+       /* Return NULL if list was empty. */
+       return waiter;
+}
+
+static void mali_timeline_system_allocate_waiters(struct mali_timeline_system *system,
+        struct mali_timeline_waiter **tail,
+        struct mali_timeline_waiter **head,
+        int max_num_waiters)
+{
+       u32 i, tid = _mali_osk_get_tid();
+       mali_bool do_alloc;
+       struct mali_timeline_waiter *waiter;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(tail);
+       MALI_DEBUG_ASSERT_POINTER(head);
+
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       *head = *tail = NULL;
+       do_alloc = MALI_FALSE;
+       i = 0;
+       while (i < max_num_waiters) {
+               if (MALI_FALSE == do_alloc) {
+                       waiter = mali_timeline_system_get_zeroed_waiter(system);
+                       if (NULL == waiter) {
+                               do_alloc = MALI_TRUE;
+                               mali_spinlock_reentrant_signal(system->spinlock, tid);
+                               continue;
+                       }
+               } else {
+                       waiter = _mali_osk_calloc(1, sizeof(struct mali_timeline_waiter));
+                       if (NULL == waiter) break;
+               }
+               ++i;
+               if (NULL == *tail) {
+                       *tail = waiter;
+                       *head = waiter;
+               } else {
+                       (*head)->tracker_next = waiter;
+                       *head = waiter;
+               }
+       }
+       if (MALI_TRUE == do_alloc) {
+               mali_spinlock_reentrant_wait(system->spinlock, tid);
+       }
+}
+
+/**
+ * Create waiters for the given tracker. The tracker is activated when all waiters are release.
+ *
+ * @note Tracker can potentially be activated before this function returns.
+ *
+ * @param system Timeline system.
+ * @param tracker Tracker we will create waiters for.
+ * @param waiter_tail List of pre-allocated waiters.
+ * @param waiter_head List of pre-allocated waiters.
+ */
+static void mali_timeline_system_create_waiters_and_unlock(struct mali_timeline_system *system,
+        struct mali_timeline_tracker *tracker,
+        struct mali_timeline_waiter *waiter_tail,
+        struct mali_timeline_waiter *waiter_head)
+{
+       int i;
+       u32 tid = _mali_osk_get_tid();
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+#if defined(CONFIG_SYNC)
+       struct sync_fence *sync_fence = NULL;
+#endif /* defined(CONFIG_SYNC) */
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       MALI_DEBUG_ASSERT(NULL == tracker->waiter_head);
+       MALI_DEBUG_ASSERT(NULL == tracker->waiter_tail);
+       MALI_DEBUG_ASSERT(NULL != tracker->job);
+
+       /* Creating waiter object for all the timelines the fence is put on. Inserting this waiter
+        * into the timelines sorted list of waiters */
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               mali_timeline_point point;
+               struct mali_timeline *timeline;
+               struct mali_timeline_waiter *waiter;
+
+               /* Get point on current timeline from tracker's fence. */
+               point = tracker->fence.points[i];
+
+               if (likely(MALI_TIMELINE_NO_POINT == point)) {
+                       /* Fence contains no point on this timeline so we don't need a waiter. */
+                       continue;
+               }
+
+               timeline = system->timelines[i];
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               if (unlikely(!mali_timeline_is_point_valid(timeline, point))) {
+                       MALI_PRINT_ERROR(("Mali Timeline: point %d is not valid (oldest=%d, next=%d)\n",
+                                         point, timeline->point_oldest, timeline->point_next));
+                       continue;
+               }
+
+               if (likely(mali_timeline_is_point_released(timeline, point))) {
+                       /* Tracker representing the point has been released so we don't need a
+                        * waiter. */
+                       continue;
+               }
+
+               /* The point is on timeline. */
+               MALI_DEBUG_ASSERT(mali_timeline_is_point_on(timeline, point));
+
+               /* Get a new zeroed waiter object. */
+               if (likely(NULL != waiter_tail)) {
+                       waiter = waiter_tail;
+                       waiter_tail = waiter_tail->tracker_next;
+               } else {
+                       MALI_PRINT_ERROR(("Mali Timeline: failed to allocate memory for waiter\n"));
+                       continue;
+               }
+
+               /* Yanking the trigger ref count of the tracker. */
+               tracker->trigger_ref_count++;
+
+               waiter->point   = point;
+               waiter->tracker = tracker;
+
+               /* Insert waiter on tracker's singly-linked waiter list. */
+               if (NULL == tracker->waiter_head) {
+                       /* list is empty */
+                       MALI_DEBUG_ASSERT(NULL == tracker->waiter_tail);
+                       tracker->waiter_tail = waiter;
+               } else {
+                       tracker->waiter_head->tracker_next = waiter;
+               }
+               tracker->waiter_head = waiter;
+
+               /* Add waiter to timeline. */
+               mali_timeline_insert_waiter(timeline, waiter);
+       }
+#if defined(CONFIG_SYNC)
+       if (-1 != tracker->fence.sync_fd) {
+               int ret;
+               struct mali_timeline_waiter *waiter;
+
+               sync_fence = sync_fence_fdget(tracker->fence.sync_fd);
+               if (unlikely(NULL == sync_fence)) {
+                       MALI_PRINT_ERROR(("Mali Timeline: failed to get sync fence from fd %d\n", tracker->fence.sync_fd));
+                       goto exit;
+               }
+
+               /* Check if we have a zeroed waiter object available. */
+               if (unlikely(NULL == waiter_tail)) {
+                       MALI_PRINT_ERROR(("Mali Timeline: failed to allocate memory for waiter\n"));
+                       goto exit;
+               }
+
+               /* Start asynchronous wait that will release waiter when the fence is signaled. */
+               sync_fence_waiter_init(&tracker->sync_fence_waiter, mali_timeline_sync_fence_callback);
+               ret = sync_fence_wait_async(sync_fence, &tracker->sync_fence_waiter);
+               if (1 == ret) {
+                       /* Fence already signaled, no waiter needed. */
+                       goto exit;
+               } else if (0 != ret) {
+                       MALI_PRINT_ERROR(("Mali Timeline: sync fence fd %d signaled with error %d\n", tracker->fence.sync_fd, ret));
+                       tracker->activation_error |= MALI_TIMELINE_ACTIVATION_ERROR_SYNC_BIT;
+                       goto exit;
+               }
+
+               /* Grab new zeroed waiter object. */
+               waiter = waiter_tail;
+               waiter_tail = waiter_tail->tracker_next;
+
+               /* Increase the trigger ref count of the tracker. */
+               tracker->trigger_ref_count++;
+
+               waiter->point   = MALI_TIMELINE_NO_POINT;
+               waiter->tracker = tracker;
+
+               /* Insert waiter on tracker's singly-linked waiter list. */
+               if (NULL == tracker->waiter_head) {
+                       /* list is empty */
+                       MALI_DEBUG_ASSERT(NULL == tracker->waiter_tail);
+                       tracker->waiter_tail = waiter;
+               } else {
+                       tracker->waiter_head->tracker_next = waiter;
+               }
+               tracker->waiter_head = waiter;
+
+               /* Also store waiter in separate field for easy access by sync callback. */
+               tracker->waiter_sync = waiter;
+
+               /* Store the sync fence in tracker so we can retrieve in abort session, if needed. */
+               tracker->sync_fence = sync_fence;
+
+               sync_fence = NULL;
+       }
+exit:
+#endif /* defined(CONFIG_SYNC) */
+
+       if (NULL != waiter_tail) {
+               mali_timeline_system_release_waiter_list(system, waiter_tail, waiter_head);
+       }
+
+       /* Release the initial trigger ref count. */
+       tracker->trigger_ref_count--;
+
+       /* If there were no waiters added to this tracker we activate immediately. */
+       if (0 == tracker->trigger_ref_count) {
+               schedule_mask |= mali_timeline_tracker_activate(tracker);
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+#if defined(CONFIG_SYNC)
+       if (NULL != sync_fence) {
+               sync_fence_put(sync_fence);
+       }
+#endif /* defined(CONFIG_SYNC) */
+
+       mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE);
+}
+
+mali_timeline_point mali_timeline_system_add_tracker(struct mali_timeline_system *system,
+        struct mali_timeline_tracker *tracker,
+        enum mali_timeline_id timeline_id)
+{
+       int num_waiters = 0;
+       struct mali_timeline_waiter *waiter_tail, *waiter_head;
+       u32 tid = _mali_osk_get_tid();
+       mali_timeline_point point = MALI_TIMELINE_NO_POINT;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(system->session);
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       MALI_DEBUG_ASSERT(MALI_FALSE == system->session->is_aborting);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_TRACKER_MAX > tracker->type);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_TRACKER_MAGIC == tracker->magic);
+
+       MALI_DEBUG_PRINT(4, ("Mali Timeline: adding tracker for job %p, timeline: %d\n", tracker->job, timeline_id));
+
+       MALI_DEBUG_ASSERT(0 < tracker->trigger_ref_count);
+       tracker->system = system;
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       num_waiters = mali_timeline_fence_num_waiters(&tracker->fence);
+
+       /* Allocate waiters. */
+       mali_timeline_system_allocate_waiters(system, &waiter_tail, &waiter_head, num_waiters);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       /* Add tracker to timeline.  This will allocate a point for the tracker on the timeline. If
+        * timeline ID is MALI_TIMELINE_NONE the tracker will NOT be added to a timeline and the
+        * point will be MALI_TIMELINE_NO_POINT.
+        *
+        * NOTE: the tracker can fail to be added if the timeline is full.  If this happens, the
+        * point will be MALI_TIMELINE_NO_POINT. */
+       MALI_DEBUG_ASSERT(timeline_id < MALI_TIMELINE_MAX || timeline_id == MALI_TIMELINE_NONE);
+       if (likely(timeline_id < MALI_TIMELINE_MAX)) {
+               struct mali_timeline *timeline = system->timelines[timeline_id];
+               mali_timeline_insert_tracker(timeline, tracker);
+               MALI_DEBUG_ASSERT(!mali_timeline_is_empty(timeline));
+       }
+
+       point = tracker->point;
+
+       /* Create waiters for tracker based on supplied fence.  Each waiter will increase the
+        * trigger ref count. */
+       mali_timeline_system_create_waiters_and_unlock(system, tracker, waiter_tail, waiter_head);
+       tracker = NULL;
+
+       /* At this point the tracker object might have been freed so we should no longer
+        * access it. */
+
+
+       /* The tracker will always be activated after calling add_tracker, even if NO_POINT is
+        * returned. */
+       return point;
+}
+
+static mali_scheduler_mask mali_timeline_system_release_waiter(struct mali_timeline_system *system,
+        struct mali_timeline_waiter *waiter)
+{
+       struct mali_timeline_tracker *tracker;
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(waiter);
+
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_SYSTEM_LOCKED(system));
+
+       tracker = waiter->tracker;
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       /* At this point the waiter has been removed from the timeline's waiter list, but it is
+        * still on the tracker's waiter list.  All of the tracker's waiters will be released when
+        * the tracker is activated. */
+
+       waiter->point   = MALI_TIMELINE_NO_POINT;
+       waiter->tracker = NULL;
+
+       tracker->trigger_ref_count--;
+       if (0 == tracker->trigger_ref_count) {
+               /* This was the last waiter; activate tracker */
+               schedule_mask |= mali_timeline_tracker_activate(tracker);
+               tracker = NULL;
+       }
+
+       return schedule_mask;
+}
+
+mali_timeline_point mali_timeline_system_get_latest_point(struct mali_timeline_system *system,
+        enum mali_timeline_id timeline_id)
+{
+       mali_timeline_point point;
+       struct mali_timeline *timeline;
+       u32 tid = _mali_osk_get_tid();
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       if (MALI_TIMELINE_MAX <= timeline_id) {
+               return MALI_TIMELINE_NO_POINT;
+       }
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       timeline = system->timelines[timeline_id];
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+
+       point = MALI_TIMELINE_NO_POINT;
+       if (timeline->point_oldest != timeline->point_next) {
+               point = timeline->point_next - 1;
+               if (MALI_TIMELINE_NO_POINT == point) point--;
+       }
+
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+       return point;
+}
+
+#if defined(MALI_TIMELINE_DEBUG_FUNCTIONS)
+
+static mali_bool is_waiting_on_timeline(struct mali_timeline_tracker *tracker, enum mali_timeline_id id)
+{
+       struct mali_timeline *timeline;
+       struct mali_timeline_system *system;
+
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       MALI_DEBUG_ASSERT_POINTER(tracker->timeline);
+       timeline = tracker->timeline;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline->system);
+       system = timeline->system;
+
+       if (MALI_TIMELINE_MAX > id) {
+               return mali_timeline_is_point_on(system->timelines[id], tracker->fence.points[id]);
+       } else {
+               MALI_DEBUG_ASSERT(MALI_TIMELINE_NONE == id);
+               return MALI_FALSE;
+       }
+}
+
+static const char *timeline_id_to_string(enum mali_timeline_id id)
+{
+       switch (id) {
+       case MALI_TIMELINE_GP:
+               return "  GP";
+       case MALI_TIMELINE_PP:
+               return "  PP";
+       case MALI_TIMELINE_SOFT:
+               return "SOFT";
+       default:
+               return "NONE";
+       }
+}
+
+static const char *timeline_tracker_type_to_string(enum mali_timeline_tracker_type type)
+{
+       switch (type) {
+       case MALI_TIMELINE_TRACKER_GP:
+               return "  GP";
+       case MALI_TIMELINE_TRACKER_PP:
+               return "  PP";
+       case MALI_TIMELINE_TRACKER_SOFT:
+               return "SOFT";
+       case MALI_TIMELINE_TRACKER_WAIT:
+               return "WAIT";
+       case MALI_TIMELINE_TRACKER_SYNC:
+               return "SYNC";
+       default:
+               return "INVALID";
+       }
+}
+
+mali_timeline_tracker_state mali_timeline_debug_get_tracker_state(struct mali_timeline_tracker *tracker)
+{
+       struct mali_timeline *timeline = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+       timeline = tracker->timeline;
+
+       if (0 != tracker->trigger_ref_count) {
+               return MALI_TIMELINE_TS_WAITING;
+       }
+
+       if (timeline && (timeline->tracker_tail == tracker || NULL != tracker->timeline_prev)) {
+               return MALI_TIMELINE_TS_ACTIVE;
+       }
+
+       if (timeline && (MALI_TIMELINE_NO_POINT == tracker->point)) {
+               return MALI_TIMELINE_TS_INIT;
+       }
+
+       return MALI_TIMELINE_TS_FINISH;
+}
+
+void mali_timeline_debug_print_tracker(struct mali_timeline_tracker *tracker)
+{
+       const char *tracker_state = "IWAF";
+
+       MALI_DEBUG_ASSERT_POINTER(tracker);
+
+       if (0 != tracker->trigger_ref_count) {
+               MALI_PRINTF(("TL:  %s %u %c - ref_wait:%u [%s%u,%s%u,%s%u,%d]  (0x%08X)\n",
+                            timeline_tracker_type_to_string(tracker->type), tracker->point,
+                            *(tracker_state + mali_timeline_debug_get_tracker_state(tracker)),
+                            tracker->trigger_ref_count,
+                            is_waiting_on_timeline(tracker, MALI_TIMELINE_GP) ? "W" : " ", tracker->fence.points[0],
+                            is_waiting_on_timeline(tracker, MALI_TIMELINE_PP) ? "W" : " ", tracker->fence.points[1],
+                            is_waiting_on_timeline(tracker, MALI_TIMELINE_SOFT) ? "W" : " ", tracker->fence.points[2],
+                            tracker->fence.sync_fd, tracker->job));
+       } else {
+               MALI_PRINTF(("TL:  %s %u %c  (0x%08X)\n",
+                            timeline_tracker_type_to_string(tracker->type), tracker->point,
+                            *(tracker_state + mali_timeline_debug_get_tracker_state(tracker)),
+                            tracker->job));
+       }
+}
+
+void mali_timeline_debug_print_timeline(struct mali_timeline *timeline)
+{
+       struct mali_timeline_tracker *tracker = NULL;
+       int i_max = 30;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+
+       tracker = timeline->tracker_tail;
+       while (NULL != tracker && 0 < --i_max) {
+               mali_timeline_debug_print_tracker(tracker);
+               tracker = tracker->timeline_next;
+       }
+
+       if (0 == i_max) {
+               MALI_PRINTF(("TL: Too many trackers in list to print\n"));
+       }
+}
+
+void mali_timeline_debug_print_system(struct mali_timeline_system *system)
+{
+       int i;
+       int num_printed = 0;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+
+       /* Print all timelines */
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               struct mali_timeline *timeline = system->timelines[i];
+
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               if (NULL == timeline->tracker_head) continue;
+
+               MALI_PRINTF(("TL: Timeline %s:\n",
+                            timeline_id_to_string((enum mali_timeline_id)i)));
+               mali_timeline_debug_print_timeline(timeline);
+               num_printed++;
+       }
+
+       if (0 == num_printed) {
+               MALI_PRINTF(("TL: All timelines empty\n"));
+       }
+}
+
+#endif /* defined(MALI_TIMELINE_DEBUG_FUNCTIONS) */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_timeline.h b/drivers/gpu/arm/mali400/mali/common/mali_timeline.h
new file mode 100755 (executable)
index 0000000..a5f1678
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_TIMELINE_H__
+#define __MALI_TIMELINE_H__
+
+#include "mali_osk.h"
+#include "mali_ukk.h"
+#include "mali_session.h"
+#include "mali_kernel_common.h"
+#include "mali_spinlock_reentrant.h"
+#include "mali_sync.h"
+#include "mali_scheduler_types.h"
+
+/**
+ * Soft job timeout.
+ *
+ * Soft jobs have to be signaled as complete after activation.  Normally this is done by user space,
+ * but in order to guarantee that every soft job is completed, we also have a timer.
+ */
+#define MALI_TIMELINE_TIMEOUT_HZ ((u32) (HZ * 3 / 2)) /* 1500 ms. */
+
+/**
+ * Timeline type.
+ */
+typedef enum mali_timeline_id {
+       MALI_TIMELINE_GP   = MALI_UK_TIMELINE_GP,   /**< GP job timeline. */
+       MALI_TIMELINE_PP   = MALI_UK_TIMELINE_PP,   /**< PP job timeline. */
+       MALI_TIMELINE_SOFT = MALI_UK_TIMELINE_SOFT, /**< Soft job timeline. */
+       MALI_TIMELINE_MAX  = MALI_UK_TIMELINE_MAX
+} mali_timeline_id;
+
+/**
+ * Used by trackers that should not be added to a timeline (@ref mali_timeline_system_add_tracker).
+ */
+#define MALI_TIMELINE_NONE MALI_TIMELINE_MAX
+
+/**
+ * Tracker type.
+ */
+typedef enum mali_timeline_tracker_type {
+       MALI_TIMELINE_TRACKER_GP   = 0, /**< Tracker used by GP jobs. */
+       MALI_TIMELINE_TRACKER_PP   = 1, /**< Tracker used by PP jobs. */
+       MALI_TIMELINE_TRACKER_SOFT = 2, /**< Tracker used by soft jobs. */
+       MALI_TIMELINE_TRACKER_WAIT = 3, /**< Tracker used for fence wait. */
+       MALI_TIMELINE_TRACKER_SYNC = 4, /**< Tracker used for sync fence. */
+       MALI_TIMELINE_TRACKER_MAX  = 5,
+} mali_timeline_tracker_type;
+
+/**
+ * Tracker activation error.
+ */
+typedef u32 mali_timeline_activation_error;
+#define MALI_TIMELINE_ACTIVATION_ERROR_NONE      0
+#define MALI_TIMELINE_ACTIVATION_ERROR_SYNC_BIT  (1<<1)
+#define MALI_TIMELINE_ACTIVATION_ERROR_FATAL_BIT (1<<0)
+
+/**
+ * Type used to represent a point on a timeline.
+ */
+typedef u32 mali_timeline_point;
+
+/**
+ * Used to represent that no point on a timeline.
+ */
+#define MALI_TIMELINE_NO_POINT ((mali_timeline_point) 0)
+
+/**
+ * The maximum span of points on a timeline.  A timeline will be considered full if the difference
+ * between the oldest and newest points is equal or larger to this value.
+ */
+#define MALI_TIMELINE_MAX_POINT_SPAN 65536
+
+/**
+ * Magic value used to assert on validity of trackers.
+ */
+#define MALI_TIMELINE_TRACKER_MAGIC 0xabcdabcd
+
+struct mali_timeline;
+struct mali_timeline_waiter;
+struct mali_timeline_tracker;
+
+/**
+ * Timeline fence.
+ */
+struct mali_timeline_fence {
+       mali_timeline_point points[MALI_TIMELINE_MAX]; /**< For each timeline, a point or MALI_TIMELINE_NO_POINT. */
+       s32                 sync_fd;                   /**< A file descriptor representing a sync fence, or -1. */
+};
+
+/**
+ * Timeline system.
+ *
+ * The Timeline system has a set of timelines associated with a session.
+ */
+struct mali_timeline_system {
+       struct mali_spinlock_reentrant *spinlock;   /**< Spin lock protecting the timeline system */
+       struct mali_timeline           *timelines[MALI_TIMELINE_MAX]; /**< The timelines in this system */
+
+       /* Single-linked list of unused waiter objects.  Uses the tracker_next field in tracker. */
+       struct mali_timeline_waiter    *waiter_empty_list;
+
+       struct mali_session_data       *session;    /**< Session that owns this system. */
+
+       mali_bool                       timer_enabled; /**< Set to MALI_TRUE if soft job timer should be enabled, MALI_FALSE if not. */
+
+       _mali_osk_wait_queue_t         *wait_queue; /**< Wait queue. */
+
+#if defined(CONFIG_SYNC)
+       struct sync_timeline           *signaled_sync_tl; /**< Special sync timeline used to create pre-signaled sync fences */
+#endif /* defined(CONFIG_SYNC) */
+};
+
+/**
+ * Timeline.  Each Timeline system will have MALI_TIMELINE_MAX timelines.
+ */
+struct mali_timeline {
+       mali_timeline_point           point_next;   /**< The next available point. */
+       mali_timeline_point           point_oldest; /**< The oldest point not released. */
+
+       /* Double-linked list of trackers.  Sorted in ascending order by tracker->time_number with
+        * tail pointing to the tracker with the oldest time. */
+       struct mali_timeline_tracker *tracker_head;
+       struct mali_timeline_tracker *tracker_tail;
+
+       /* Double-linked list of waiters.  Sorted in ascending order by waiter->time_number_wait
+        * with tail pointing to the waiter with oldest wait time. */
+       struct mali_timeline_waiter  *waiter_head;
+       struct mali_timeline_waiter  *waiter_tail;
+
+       struct mali_timeline_system  *system;       /**< Timeline system this timeline belongs to. */
+       enum mali_timeline_id         id;           /**< Timeline type. */
+
+#if defined(CONFIG_SYNC)
+       struct sync_timeline         *sync_tl;      /**< Sync timeline that corresponds to this timeline. */
+#endif /* defined(CONFIG_SYNC) */
+
+       /* The following fields are used to time out soft job trackers. */
+       _mali_osk_wq_delayed_work_t  *delayed_work;
+       mali_bool                     timer_active;
+};
+
+/**
+ * Timeline waiter.
+ */
+struct mali_timeline_waiter {
+       mali_timeline_point           point;         /**< Point on timeline we are waiting for to be released. */
+       struct mali_timeline_tracker *tracker;       /**< Tracker that is waiting. */
+
+       struct mali_timeline_waiter  *timeline_next; /**< Next waiter on timeline's waiter list. */
+       struct mali_timeline_waiter  *timeline_prev; /**< Previous waiter on timeline's waiter list. */
+
+       struct mali_timeline_waiter  *tracker_next;  /**< Next waiter on tracker's waiter list. */
+};
+
+/**
+ * Timeline tracker.
+ */
+struct mali_timeline_tracker {
+       MALI_DEBUG_CODE(u32            magic); /**< Should always be MALI_TIMELINE_TRACKER_MAGIC for a valid tracker. */
+
+       mali_timeline_point            point; /**< Point on timeline for this tracker */
+
+       struct mali_timeline_tracker  *timeline_next; /**< Next tracker on timeline's tracker list */
+       struct mali_timeline_tracker  *timeline_prev; /**< Previous tracker on timeline's tracker list */
+
+       u32                            trigger_ref_count; /**< When zero tracker will be activated */
+       mali_timeline_activation_error activation_error;  /**< Activation error. */
+       struct mali_timeline_fence     fence;             /**< Fence used to create this tracker */
+
+       /* Single-linked list of waiters.  Sorted in order of insertions with
+        * tail pointing to first waiter. */
+       struct mali_timeline_waiter   *waiter_head;
+       struct mali_timeline_waiter   *waiter_tail;
+
+#if defined(CONFIG_SYNC)
+       /* These are only used if the tracker is waiting on a sync fence. */
+       struct mali_timeline_waiter   *waiter_sync; /**< A direct pointer to timeline waiter representing sync fence. */
+       struct sync_fence_waiter       sync_fence_waiter; /**< Used to connect sync fence and tracker in sync fence wait callback. */
+       struct sync_fence             *sync_fence;   /**< The sync fence this tracker is waiting on. */
+       _mali_osk_list_t               sync_fence_cancel_list; /**< List node used to cancel sync fence waiters. */
+#endif /* defined(CONFIG_SYNC) */
+
+       struct mali_timeline_system   *system;       /**< Timeline system. */
+       struct mali_timeline          *timeline;     /**< Timeline, or NULL if not on a timeline. */
+       enum mali_timeline_tracker_type type;        /**< Type of tracker. */
+       void                          *job;          /**< Owner of tracker. */
+
+       /* The following fields are used to time out soft job trackers. */
+       u32                           os_tick_create;
+       u32                           os_tick_activate;
+       mali_bool                     timer_active;
+};
+
+/**
+ * What follows is a set of functions to check the state of a timeline and to determine where on a
+ * timeline a given point is.  Most of these checks will translate the timeline so the oldest point
+ * on the timeline is aligned with zero.  Remember that all of these calculation are done on
+ * unsigned integers.
+ *
+ * The following example illustrates the three different states a point can be in.  The timeline has
+ * been translated to put the oldest point at zero:
+ *
+ *
+ *
+ *                               [ point is in forbidden zone ]
+ *                                          64k wide
+ *                                MALI_TIMELINE_MAX_POINT_SPAN
+ *
+ *    [ point is on timeline     )                            ( point is released ]
+ *
+ *    0--------------------------##############################--------------------2^32 - 1
+ *    ^                          ^
+ *    \                          |
+ *     oldest point on timeline  |
+ *                               \
+ *                                next point on timeline
+ */
+
+/**
+ * Compare two timeline points
+ *
+ * Returns true if a is after b, false if a is before or equal to b.
+ *
+ * This funcion ignores MALI_TIMELINE_MAX_POINT_SPAN. Wrapping is supported and
+ * the result will be correct if the points is less then UINT_MAX/2 apart.
+ *
+ * @param a Point on timeline
+ * @param b Point on timeline
+ * @return MALI_TRUE if a is after b
+ */
+MALI_STATIC_INLINE mali_bool mali_timeline_point_after(mali_timeline_point a, mali_timeline_point b)
+{
+       return 0 > ((s32)b) - ((s32)a);
+}
+
+/**
+ * Check if a point is on timeline.  A point is on a timeline if it is greater than, or equal to,
+ * the oldest point, and less than the next point.
+ *
+ * @param timeline Timeline.
+ * @param point Point on timeline.
+ * @return MALI_TRUE if point is on timeline, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_timeline_is_point_on(struct mali_timeline *timeline, mali_timeline_point point)
+{
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
+
+       return (point - timeline->point_oldest) < (timeline->point_next - timeline->point_oldest);
+}
+
+/**
+ * Check if a point has been released.  A point is released if it is older than the oldest point on
+ * the timeline, newer than the next point, and also not in the forbidden zone.
+ *
+ * @param timeline Timeline.
+ * @param point Point on timeline.
+ * @return MALI_TRUE if point has been release, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_timeline_is_point_released(struct mali_timeline *timeline, mali_timeline_point point)
+{
+       mali_timeline_point point_normalized;
+       mali_timeline_point next_normalized;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
+
+       point_normalized = point - timeline->point_oldest;
+       next_normalized = timeline->point_next - timeline->point_oldest;
+
+       return point_normalized > (next_normalized + MALI_TIMELINE_MAX_POINT_SPAN);
+}
+
+/**
+ * Check if a point is valid.  A point is valid if is on the timeline or has been released.
+ *
+ * @param timeline Timeline.
+ * @param point Point on timeline.
+ * @return MALI_TRUE if point is valid, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_timeline_is_point_valid(struct mali_timeline *timeline, mali_timeline_point point)
+{
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       return mali_timeline_is_point_on(timeline, point) || mali_timeline_is_point_released(timeline, point);
+}
+
+/**
+ * Check if timeline is empty (has no points on it).  A timeline is empty if next == oldest.
+ *
+ * @param timeline Timeline.
+ * @return MALI_TRUE if timeline is empty, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_timeline_is_empty(struct mali_timeline *timeline)
+{
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       return timeline->point_next == timeline->point_oldest;
+}
+
+/**
+ * Check if timeline is full.  A valid timeline cannot span more than 64k points (@ref
+ * MALI_TIMELINE_MAX_POINT_SPAN).
+ *
+ * @param timeline Timeline.
+ * @return MALI_TRUE if timeline is full, MALI_FALSE if not.
+ */
+MALI_STATIC_INLINE mali_bool mali_timeline_is_full(struct mali_timeline *timeline)
+{
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       return MALI_TIMELINE_MAX_POINT_SPAN <= (timeline->point_next - timeline->point_oldest);
+}
+
+/**
+ * Create a new timeline system.
+ *
+ * @param session The session this timeline system will belong to.
+ * @return New timeline system.
+ */
+struct mali_timeline_system *mali_timeline_system_create(struct mali_session_data *session);
+
+/**
+ * Abort timeline system.
+ *
+ * This will release all pending waiters in the timeline system causing all trackers to be
+ * activated.
+ *
+ * @param system Timeline system to abort all jobs from.
+ */
+void mali_timeline_system_abort(struct mali_timeline_system *system);
+
+/**
+ * Destroy an empty timeline system.
+ *
+ * @note @ref mali_timeline_system_abort() should be called prior to this function.
+ *
+ * @param system Timeline system to destroy.
+ */
+void mali_timeline_system_destroy(struct mali_timeline_system *system);
+
+/**
+ * Stop the soft job timer.
+ *
+ * @param system Timeline system
+ */
+void mali_timeline_system_stop_timer(struct mali_timeline_system *system);
+
+/**
+ * Add a tracker to a timeline system and optionally also on a timeline.
+ *
+ * Once added to the timeline system, the tracker is guaranteed to be activated.  The tracker can be
+ * activated before this function returns.  Thus, it is also possible that the tracker is released
+ * before this function returns, depending on the tracker type.
+ *
+ * @note Tracker must be initialized (@ref mali_timeline_tracker_init) before being added to the
+ * timeline system.
+ *
+ * @param system Timeline system the tracker will be added to.
+ * @param tracker The tracker to be added.
+ * @param timeline_id Id of the timeline the tracker will be added to, or
+ *                    MALI_TIMELINE_NONE if it should not be added on a timeline.
+ * @return Point on timeline identifying this tracker, or MALI_TIMELINE_NO_POINT if not on timeline.
+ */
+mali_timeline_point mali_timeline_system_add_tracker(struct mali_timeline_system *system,
+        struct mali_timeline_tracker *tracker,
+        enum mali_timeline_id timeline_id);
+
+/**
+ * Get latest point on timeline.
+ *
+ * @param system Timeline system.
+ * @param timeline_id Id of timeline to get latest point from.
+ * @return Latest point on timeline, or MALI_TIMELINE_NO_POINT if the timeline is empty.
+ */
+mali_timeline_point mali_timeline_system_get_latest_point(struct mali_timeline_system *system,
+        enum mali_timeline_id timeline_id);
+
+/**
+ * Initialize tracker.
+ *
+ * Must be called before tracker is added to timeline system (@ref mali_timeline_system_add_tracker).
+ *
+ * @param tracker Tracker to initialize.
+ * @param type Type of tracker.
+ * @param fence Fence used to set up dependencies for tracker.
+ * @param job Pointer to job struct this tracker is associated with.
+ */
+void mali_timeline_tracker_init(struct mali_timeline_tracker *tracker,
+                                mali_timeline_tracker_type type,
+                                struct mali_timeline_fence *fence,
+                                void *job);
+
+/**
+ * Grab trigger ref count on tracker.
+ *
+ * This will prevent tracker from being activated until the trigger ref count reaches zero.
+ *
+ * @note Tracker must have been initialized (@ref mali_timeline_tracker_init).
+ *
+ * @param system Timeline system.
+ * @param tracker Tracker.
+ */
+void mali_timeline_system_tracker_get(struct mali_timeline_system *system, struct mali_timeline_tracker *tracker);
+
+/**
+ * Release trigger ref count on tracker.
+ *
+ * If the trigger ref count reaches zero, the tracker will be activated.
+ *
+ * @param system Timeline system.
+ * @param tracker Tracker.
+ * @param activation_error Error bitmask if activated with error, or MALI_TIMELINE_ACTIVATION_ERROR_NONE if no error.
+ * @return Scheduling bitmask.
+ */
+mali_scheduler_mask mali_timeline_system_tracker_put(struct mali_timeline_system *system, struct mali_timeline_tracker *tracker, mali_timeline_activation_error activation_error);
+
+/**
+ * Release a tracker from the timeline system.
+ *
+ * This is used to signal that the job being tracker is finished, either due to normal circumstances
+ * (job complete/abort) or due to a timeout.
+ *
+ * We may need to schedule some subsystems after a tracker has been released and the returned
+ * bitmask will tell us if it is necessary.  If the return value is non-zero, this value needs to be
+ * sent as an input parameter to @ref mali_scheduler_schedule_from_mask() to do the scheduling.
+ *
+ * @note Tracker must have been activated before being released.
+ * @warning Not calling @ref mali_scheduler_schedule_from_mask() after releasing a tracker can lead
+ * to a deadlock.
+ *
+ * @param tracker Tracker being released.
+ * @return Scheduling bitmask.
+ */
+mali_scheduler_mask mali_timeline_tracker_release(struct mali_timeline_tracker *tracker);
+
+/**
+ * Copy data from a UK fence to a Timeline fence.
+ *
+ * @param fence Timeline fence.
+ * @param uk_fence UK fence.
+ */
+void mali_timeline_fence_copy_uk_fence(struct mali_timeline_fence *fence, _mali_uk_fence_t *uk_fence);
+
+#define MALI_TIMELINE_DEBUG_FUNCTIONS
+#if defined(MALI_TIMELINE_DEBUG_FUNCTIONS)
+
+/**
+ * Tracker state.  Used for debug printing.
+ */
+typedef enum mali_timeline_tracker_state {
+       MALI_TIMELINE_TS_INIT    = 0,
+       MALI_TIMELINE_TS_WAITING = 1,
+       MALI_TIMELINE_TS_ACTIVE  = 2,
+       MALI_TIMELINE_TS_FINISH  = 3,
+} mali_timeline_tracker_state;
+
+/**
+ * Get tracker state.
+ *
+ * @param tracker Tracker to check.
+ * @return State of tracker.
+ */
+mali_timeline_tracker_state mali_timeline_debug_get_tracker_state(struct mali_timeline_tracker *tracker);
+
+/**
+ * Print debug information about tracker.
+ *
+ * @param tracker Tracker to print.
+ */
+void mali_timeline_debug_print_tracker(struct mali_timeline_tracker *tracker);
+
+/**
+ * Print debug information about timeline.
+ *
+ * @param timeline Timeline to print.
+ */
+void mali_timeline_debug_print_timeline(struct mali_timeline *timeline);
+
+/**
+ * Print debug information about timeline system.
+ *
+ * @param system Timeline system to print.
+ */
+void mali_timeline_debug_print_system(struct mali_timeline_system *system);
+
+#endif /* defined(MALI_TIMELINE_DEBUG_FUNCTIONS) */
+
+#endif /* __MALI_TIMELINE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_timeline_fence_wait.c b/drivers/gpu/arm/mali400/mali/common/mali_timeline_fence_wait.c
new file mode 100755 (executable)
index 0000000..ab5cb00
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_timeline_fence_wait.h"
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_spinlock_reentrant.h"
+
+/**
+ * Allocate a fence waiter tracker.
+ *
+ * @return New fence waiter if successful, NULL if not.
+ */
+static struct mali_timeline_fence_wait_tracker *mali_timeline_fence_wait_tracker_alloc(void)
+{
+       return (struct mali_timeline_fence_wait_tracker *) _mali_osk_calloc(1, sizeof(struct mali_timeline_fence_wait_tracker));
+}
+
+/**
+ * Free fence waiter tracker.
+ *
+ * @param wait Fence wait tracker to free.
+ */
+static void mali_timeline_fence_wait_tracker_free(struct mali_timeline_fence_wait_tracker *wait)
+{
+       MALI_DEBUG_ASSERT_POINTER(wait);
+       _mali_osk_atomic_term(&wait->refcount);
+       _mali_osk_free(wait);
+}
+
+/**
+ * Check if fence wait tracker has been activated.  Used as a wait queue condition.
+ *
+ * @param data Fence waiter.
+ * @return MALI_TRUE if tracker has been activated, MALI_FALSE if not.
+ */
+static mali_bool mali_timeline_fence_wait_tracker_is_activated(void *data)
+{
+       struct mali_timeline_fence_wait_tracker *wait;
+
+       wait = (struct mali_timeline_fence_wait_tracker *) data;
+       MALI_DEBUG_ASSERT_POINTER(wait);
+
+       return wait->activated;
+}
+
+/**
+ * Check if fence has been signaled.
+ *
+ * @param system Timeline system.
+ * @param fence Timeline fence.
+ * @return MALI_TRUE if fence is signaled, MALI_FALSE if not.
+ */
+static mali_bool mali_timeline_fence_wait_check_status(struct mali_timeline_system *system, struct mali_timeline_fence *fence)
+{
+       int i;
+       u32 tid = _mali_osk_get_tid();
+       mali_bool ret = MALI_TRUE;
+#if defined(CONFIG_SYNC)
+       struct sync_fence *sync_fence = NULL;
+#endif
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(fence);
+
+       mali_spinlock_reentrant_wait(system->spinlock, tid);
+
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               struct mali_timeline *timeline;
+               mali_timeline_point   point;
+
+               point = fence->points[i];
+
+               if (likely(MALI_TIMELINE_NO_POINT == point)) {
+                       /* Fence contains no point on this timeline. */
+                       continue;
+               }
+
+               timeline = system->timelines[i];
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               if (unlikely(!mali_timeline_is_point_valid(timeline, point))) {
+                       MALI_PRINT_ERROR(("Mali Timeline: point %d is not valid (oldest=%d, next=%d)\n", point, timeline->point_oldest, timeline->point_next));
+               }
+
+               if (!mali_timeline_is_point_released(timeline, point)) {
+                       ret = MALI_FALSE;
+                       goto exit;
+               }
+       }
+
+#if defined(CONFIG_SYNC)
+       if (-1 != fence->sync_fd) {
+               sync_fence = sync_fence_fdget(fence->sync_fd);
+               if (likely(NULL != sync_fence)) {
+                       if (0 == sync_fence->status) {
+                               ret = MALI_FALSE;
+                       }
+               } else {
+                       MALI_PRINT_ERROR(("Mali Timeline: failed to get sync fence from fd %d\n", fence->sync_fd));
+               }
+       }
+#endif /* defined(CONFIG_SYNC) */
+
+exit:
+       mali_spinlock_reentrant_signal(system->spinlock, tid);
+
+#if defined(CONFIG_SYNC)
+       if (NULL != sync_fence) {
+               sync_fence_put(sync_fence);
+       }
+#endif /* defined(CONFIG_SYNC) */
+
+       return ret;
+}
+
+mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout)
+{
+       struct mali_timeline_fence_wait_tracker *wait;
+       mali_timeline_point point;
+       mali_bool ret;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(fence);
+
+       MALI_DEBUG_PRINT(4, ("Mali Timeline: wait on fence\n"));
+
+       if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY == timeout) {
+               return mali_timeline_fence_wait_check_status(system, fence);
+       }
+
+       wait = mali_timeline_fence_wait_tracker_alloc();
+       if (unlikely(NULL == wait)) {
+               MALI_PRINT_ERROR(("Mali Timeline: failed to allocate data for fence wait\n"));
+               return MALI_FALSE;
+       }
+
+       wait->activated = MALI_FALSE;
+       wait->system = system;
+
+       /* Initialize refcount to two references.  The reference first will be released by this
+        * function after the wait is over.  The second reference will be released when the tracker
+        * is activated. */
+       _mali_osk_atomic_init(&wait->refcount, 2);
+
+       /* Add tracker to timeline system, but not to a timeline. */
+       mali_timeline_tracker_init(&wait->tracker, MALI_TIMELINE_TRACKER_WAIT, fence, wait);
+       point = mali_timeline_system_add_tracker(system, &wait->tracker, MALI_TIMELINE_NONE);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point);
+       MALI_IGNORE(point);
+
+       /* Wait for the tracker to be activated or time out. */
+       if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER == timeout) {
+               _mali_osk_wait_queue_wait_event(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait);
+       } else {
+               _mali_osk_wait_queue_wait_event_timeout(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait, timeout);
+       }
+
+       ret = wait->activated;
+
+       if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) {
+               mali_timeline_fence_wait_tracker_free(wait);
+       }
+
+       return ret;
+}
+
+void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *wait)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(wait);
+       MALI_DEBUG_ASSERT_POINTER(wait->system);
+
+       MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for fence wait tracker\n"));
+
+       MALI_DEBUG_ASSERT(MALI_FALSE == wait->activated);
+       wait->activated = MALI_TRUE;
+
+       _mali_osk_wait_queue_wake_up(wait->system->wait_queue);
+
+       /* Nothing can wait on this tracker, so nothing to schedule after release. */
+       schedule_mask = mali_timeline_tracker_release(&wait->tracker);
+       MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);
+       MALI_IGNORE(schedule_mask);
+
+       if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) {
+               mali_timeline_fence_wait_tracker_free(wait);
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_timeline_fence_wait.h b/drivers/gpu/arm/mali400/mali/common/mali_timeline_fence_wait.h
new file mode 100755 (executable)
index 0000000..16d2f2c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_timeline_fence_wait.h
+ *
+ * This file contains functions used to wait until a Timeline fence is signaled.
+ */
+
+#ifndef __MALI_TIMELINE_FENCE_WAIT_H__
+#define __MALI_TIMELINE_FENCE_WAIT_H__
+
+#include "mali_osk.h"
+#include "mali_timeline.h"
+
+/**
+ * If used as the timeout argument in @ref mali_timeline_fence_wait, a timer is not used and the
+ * function only returns when the fence is signaled.
+ */
+#define MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER ((u32) -1)
+
+/**
+ * If used as the timeout argument in @ref mali_timeline_fence_wait, the function will return
+ * immediately with the current state of the fence.
+ */
+#define MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY 0
+
+/**
+ * Fence wait tracker.
+ *
+ * The fence wait tracker is added to the Timeline system with the fence we are waiting on as a
+ * dependency.  We will then perform a blocking wait, possibly with a timeout, until the tracker is
+ * activated, which happens when the fence is signaled.
+ */
+struct mali_timeline_fence_wait_tracker {
+       mali_bool activated;                  /**< MALI_TRUE if the tracker has been activated, MALI_FALSE if not. */
+       _mali_osk_atomic_t refcount;          /**< Reference count. */
+       struct mali_timeline_system *system;  /**< Timeline system. */
+       struct mali_timeline_tracker tracker; /**< Timeline tracker. */
+};
+
+/**
+ * Wait for a fence to be signaled, or timeout is reached.
+ *
+ * @param system Timeline system.
+ * @param fence Fence to wait on.
+ * @param timeout Timeout in ms, or MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER or
+ * MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY.
+ * @return MALI_TRUE if signaled, MALI_FALSE if timed out.
+ */
+mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout);
+
+/**
+ * Used by the Timeline system to activate a fence wait tracker.
+ *
+ * @param fence_wait_tracker Fence waiter tracker.
+ */
+void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *fence_wait_tracker);
+
+#endif /* __MALI_TIMELINE_FENCE_WAIT_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.c b/drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.c
new file mode 100755 (executable)
index 0000000..e63e5ae
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_timeline_sync_fence.h"
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_sync.h"
+
+#if defined(CONFIG_SYNC)
+
+/**
+ * Creates a sync fence tracker and a sync fence.  Adds sync fence tracker to Timeline system and
+ * returns sync fence.  The sync fence will be signaled when the sync fence tracker is activated.
+ *
+ * @param timeline Timeline.
+ * @param point Point on timeline.
+ * @return Sync fence that will be signaled when tracker is activated.
+ */
+static struct sync_fence *mali_timeline_sync_fence_create_and_add_tracker(struct mali_timeline *timeline, mali_timeline_point point)
+{
+       struct mali_timeline_sync_fence_tracker *sync_fence_tracker;
+       struct sync_fence                       *sync_fence;
+       struct mali_timeline_fence               fence;
+
+       MALI_DEBUG_ASSERT_POINTER(timeline);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
+
+       /* Allocate sync fence tracker. */
+       sync_fence_tracker = _mali_osk_calloc(1, sizeof(struct mali_timeline_sync_fence_tracker));
+       if (NULL == sync_fence_tracker) {
+               MALI_PRINT_ERROR(("Mali Timeline: sync_fence_tracker allocation failed\n"));
+               return NULL;
+       }
+
+       /* Create sync flag. */
+       MALI_DEBUG_ASSERT_POINTER(timeline->sync_tl);
+       sync_fence_tracker->flag = mali_sync_flag_create(timeline->sync_tl, point);
+       if (NULL == sync_fence_tracker->flag) {
+               MALI_PRINT_ERROR(("Mali Timeline: sync_flag creation failed\n"));
+               _mali_osk_free(sync_fence_tracker);
+               return NULL;
+       }
+
+       /* Create sync fence from sync flag. */
+       sync_fence = mali_sync_flag_create_fence(sync_fence_tracker->flag);
+       if (NULL == sync_fence) {
+               MALI_PRINT_ERROR(("Mali Timeline: sync_fence creation failed\n"));
+               mali_sync_flag_put(sync_fence_tracker->flag);
+               _mali_osk_free(sync_fence_tracker);
+               return NULL;
+       }
+
+       /* Setup fence for tracker. */
+       _mali_osk_memset(&fence, 0, sizeof(struct mali_timeline_fence));
+       fence.sync_fd = -1;
+       fence.points[timeline->id] = point;
+
+       /* Finally, add the tracker to Timeline system. */
+       mali_timeline_tracker_init(&sync_fence_tracker->tracker, MALI_TIMELINE_TRACKER_SYNC, &fence, sync_fence_tracker);
+       point = mali_timeline_system_add_tracker(timeline->system, &sync_fence_tracker->tracker, MALI_TIMELINE_NONE);
+       MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point);
+
+       return sync_fence;
+}
+
+s32 mali_timeline_sync_fence_create(struct mali_timeline_system *system, struct mali_timeline_fence *fence)
+{
+       u32 i;
+       struct sync_fence *sync_fence_acc = NULL;
+
+       MALI_DEBUG_ASSERT_POINTER(system);
+       MALI_DEBUG_ASSERT_POINTER(fence);
+
+       for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
+               struct mali_timeline *timeline;
+               struct sync_fence *sync_fence;
+
+               if (MALI_TIMELINE_NO_POINT == fence->points[i]) continue;
+
+               timeline = system->timelines[i];
+               MALI_DEBUG_ASSERT_POINTER(timeline);
+
+               sync_fence = mali_timeline_sync_fence_create_and_add_tracker(timeline, fence->points[i]);
+               if (NULL == sync_fence) goto error;
+
+               if (NULL != sync_fence_acc) {
+                       /* Merge sync fences. */
+                       sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence);
+                       if (NULL == sync_fence_acc) goto error;
+               } else {
+                       /* This was the first sync fence created. */
+                       sync_fence_acc = sync_fence;
+               }
+       }
+
+       if (-1 != fence->sync_fd) {
+               struct sync_fence *sync_fence;
+
+               sync_fence = sync_fence_fdget(fence->sync_fd);
+               if (NULL == sync_fence) goto error;
+
+               if (NULL != sync_fence_acc) {
+                       sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence);
+                       if (NULL == sync_fence_acc) goto error;
+               } else {
+                       sync_fence_acc = sync_fence;
+               }
+       }
+
+       if (NULL == sync_fence_acc) {
+               MALI_DEBUG_ASSERT_POINTER(system->signaled_sync_tl);
+
+               /* There was nothing to wait on, so return an already signaled fence. */
+
+               sync_fence_acc = mali_sync_timeline_create_signaled_fence(system->signaled_sync_tl);
+               if (NULL == sync_fence_acc) goto error;
+       }
+
+       /* Return file descriptor for the accumulated sync fence. */
+       return mali_sync_fence_fd_alloc(sync_fence_acc);
+
+error:
+       if (NULL != sync_fence_acc) {
+               sync_fence_put(sync_fence_acc);
+       }
+
+       return -1;
+}
+
+void mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker *sync_fence_tracker)
+{
+       mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
+
+       MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker);
+       MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker->flag);
+
+       MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for sync fence tracker\n"));
+
+       /* Signal flag and release reference. */
+       mali_sync_flag_signal(sync_fence_tracker->flag, 0);
+       mali_sync_flag_put(sync_fence_tracker->flag);
+
+       /* Nothing can wait on this tracker, so nothing to schedule after release. */
+       schedule_mask = mali_timeline_tracker_release(&sync_fence_tracker->tracker);
+       MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);
+
+       _mali_osk_free(sync_fence_tracker);
+}
+
+#endif /* defined(CONFIG_SYNC) */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.h b/drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.h
new file mode 100755 (executable)
index 0000000..3d8e3a1
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_timeline_sync_fence.h
+ *
+ * This file contains code related to creating sync fences from timeline fences.
+ */
+
+#ifndef __MALI_TIMELINE_SYNC_FENCE_H__
+#define __MALI_TIMELINE_SYNC_FENCE_H__
+
+#include "mali_timeline.h"
+
+#if defined(CONFIG_SYNC)
+
+/**
+ * Sync fence tracker.
+ */
+struct mali_timeline_sync_fence_tracker {
+       struct mali_sync_flag        *flag;    /**< Sync flag used to connect tracker and sync fence. */
+       struct mali_timeline_tracker  tracker; /**< Timeline tracker. */
+};
+
+/**
+ * Create a sync fence that will be signaled when @ref fence is signaled.
+ *
+ * @param system Timeline system.
+ * @param fence Fence to create sync fence from.
+ * @return File descriptor for new sync fence, or -1 on error.
+ */
+s32 mali_timeline_sync_fence_create(struct mali_timeline_system *system, struct mali_timeline_fence *fence);
+
+/**
+ * Used by the Timeline system to activate a sync fence tracker.
+ *
+ * @param sync_fence_tracker Sync fence tracker.
+ *
+ */
+void mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker *sync_fence_tracker);
+
+#endif /* defined(CONFIG_SYNC) */
+
+#endif /* __MALI_TIMELINE_SYNC_FENCE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_ukk.h b/drivers/gpu/arm/mali400/mali/common/mali_ukk.h
new file mode 100755 (executable)
index 0000000..5bc8e1b
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_ukk.h
+ * Defines the kernel-side interface of the user-kernel interface
+ */
+
+#ifndef __MALI_UKK_H__
+#define __MALI_UKK_H__
+
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup uddapi Unified Device Driver (UDD) APIs
+ *
+ * @{
+ */
+
+/**
+ * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs
+ *
+ * - The _mali_uk functions are an abstraction of the interface to the device
+ * driver. On certain OSs, this would be implemented via the IOCTL interface.
+ * On other OSs, it could be via extension of some Device Driver Class, or
+ * direct function call for Bare metal/RTOSs.
+ * - It is important to note that:
+ *   -  The Device Driver has implemented the _mali_ukk set of functions
+ *   -  The Base Driver calls the corresponding set of _mali_uku functions.
+ * - What requires porting is solely the calling mechanism from User-side to
+ * Kernel-side, and propagating back the results.
+ * - Each U/K function is associated with a (group, number) pair from
+ * \ref _mali_uk_functions to make it possible for a common function in the
+ * Base Driver and Device Driver to route User/Kernel calls from/to the
+ * correct _mali_uk function. For example, in an IOCTL system, the IOCTL number
+ * would be formed based on the group and number assigned to the _mali_uk
+ * function, as listed in \ref _mali_uk_functions. On the user-side, each
+ * _mali_uku function would just make an IOCTL with the IOCTL-code being an
+ * encoded form of the (group, number) pair. On the kernel-side, the Device
+ * Driver's IOCTL handler decodes the IOCTL-code back into a (group, number)
+ * pair, and uses this to determine which corresponding _mali_ukk should be
+ * called.
+ *   - Refer to \ref _mali_uk_functions for more information about this
+ * (group, number) pairing.
+ * - In a system where there is no distinction between user and kernel-side,
+ * the U/K interface may be implemented as:@code
+ * MALI_STATIC_INLINE _mali_osk_errcode_t _mali_uku_examplefunction( _mali_uk_examplefunction_s *args )
+ * {
+ *     return mali_ukk_examplefunction( args );
+ * }
+ * @endcode
+ * - Therefore, all U/K calls behave \em as \em though they were direct
+ * function calls (but the \b implementation \em need \em not be a direct
+ * function calls)
+ *
+ * @note Naming the _mali_uk functions the same on both User and Kernel sides
+ * on non-RTOS systems causes debugging issues when setting breakpoints. In
+ * this case, it is not clear which function the breakpoint is put on.
+ * Therefore the _mali_uk functions in user space are prefixed with \c _mali_uku
+ * and in kernel space with \c _mali_ukk. The naming for the argument
+ * structures is unaffected.
+ *
+ * - The _mali_uk functions are synchronous.
+ * - Arguments to the _mali_uk functions are passed in a structure. The only
+ * parameter passed to the _mali_uk functions is a pointer to this structure.
+ * This first member of this structure, ctx, is a pointer to a context returned
+ * by _mali_uku_open(). For example:@code
+ * typedef struct
+ * {
+ *     void *ctx;
+ *     u32 number_of_cores;
+ * } _mali_uk_get_gp_number_of_cores_s;
+ * @endcode
+ *
+ * - Each _mali_uk function has its own argument structure named after the
+ *  function. The argument is distinguished by the _s suffix.
+ * - The argument types are defined by the base driver and user-kernel
+ *  interface.
+ * - All _mali_uk functions return a standard \ref _mali_osk_errcode_t.
+ * - Only arguments of type input or input/output need be initialized before
+ * calling a _mali_uk function.
+ * - Arguments of type output and input/output are only valid when the
+ * _mali_uk function returns \ref _MALI_OSK_ERR_OK.
+ * - The \c ctx member is always invalid after it has been used by a
+ * _mali_uk function, except for the context management functions
+ *
+ *
+ * \b Interface \b restrictions
+ *
+ * The requirements of the interface mean that an implementation of the
+ * User-kernel interface may do no 'real' work. For example, the following are
+ * illegal in the User-kernel implementation:
+ * - Calling functions necessary for operation on all systems,  which would
+ * not otherwise get called on RTOS systems.
+ *     - For example, a  U/K interface that calls multiple _mali_ukk functions
+ * during one particular U/K call. This could not be achieved by the same code
+ * which uses direct function calls for the U/K interface.
+ * -  Writing in values to the args members, when otherwise these members would
+ * not hold a useful value for a direct function call U/K interface.
+ *     - For example, U/K interface implementation that take NULL members in
+ * their arguments structure from the user side, but those members are
+ * replaced with non-NULL values in the kernel-side of the U/K interface
+ * implementation. A scratch area for writing data is one such example. In this
+ * case, a direct function call U/K interface would segfault, because no code
+ * would be present to replace the NULL pointer with a meaningful pointer.
+ *     - Note that we discourage the case where the U/K implementation changes
+ * a NULL argument member to non-NULL, and then the Device Driver code (outside
+ * of the U/K layer) re-checks this member for NULL, and corrects it when
+ * necessary. Whilst such code works even on direct function call U/K
+ * intefaces, it reduces the testing coverage of the Device Driver code. This
+ * is because we have no way of testing the NULL == value path on an OS
+ * implementation.
+ *
+ * A number of allowable examples exist where U/K interfaces do 'real' work:
+ * - The 'pointer switching' technique for \ref _mali_ukk_get_system_info
+ *     - In this case, without the pointer switching on direct function call
+ * U/K interface, the Device Driver code still sees the same thing: a pointer
+ * to which it can write memory. This is because such a system has no
+ * distinction between a user and kernel pointer.
+ * - Writing an OS-specific value into the ukk_private member for
+ * _mali_ukk_mem_mmap().
+ *     - In this case, this value is passed around by Device Driver code, but
+ * its actual value is never checked. Device Driver code simply passes it from
+ * the U/K layer to the OSK layer, where it can be acted upon. In this case,
+ * \em some OS implementations of the U/K (_mali_ukk_mem_mmap()) and OSK
+ * (_mali_osk_mem_mapregion_init()) functions will collaborate on the
+ *  meaning of ukk_private member. On other OSs, it may be unused by both
+ * U/K and OSK layers
+ *     - Therefore, on error inside the U/K interface implementation itself,
+ * it will be as though the _mali_ukk function itself had failed, and cleaned
+ * up after itself.
+ *     - Compare this to a direct function call U/K implementation, where all
+ * error cleanup is handled by the _mali_ukk function itself. The direct
+ * function call U/K interface implementation is automatically atomic.
+ *
+ * The last example highlights a consequence of all U/K interface
+ * implementations: they must be atomic with respect to the Device Driver code.
+ * And therefore, should Device Driver code succeed but the U/K implementation
+ * fail afterwards (but before return to user-space), then the U/K
+ * implementation must cause appropriate cleanup actions to preserve the
+ * atomicity of the interface.
+ *
+ * @{
+ */
+
+
+/** @defgroup _mali_uk_context U/K Context management
+ *
+ * These functions allow for initialisation of the user-kernel interface once per process.
+ *
+ * Generally the context will store the OS specific object to communicate with the kernel device driver and further
+ * state information required by the specific implementation. The context is shareable among all threads in the caller process.
+ *
+ * On IOCTL systems, this is likely to be a file descriptor as a result of opening the kernel device driver.
+ *
+ * On a bare-metal/RTOS system with no distinction between kernel and
+ * user-space, the U/K interface simply calls the _mali_ukk variant of the
+ * function by direct function call. In this case, the context returned is the
+ * mali_session_data from _mali_ukk_open().
+ *
+ * The kernel side implementations of the U/K interface expect the first member of the argument structure to
+ * be the context created by _mali_uku_open(). On some OS implementations, the meaning of this context
+ * will be different between user-side and kernel-side. In which case, the kernel-side will need to replace this context
+ * with the kernel-side equivalent, because user-side will not have access to kernel-side data. The context parameter
+ * in the argument structure therefore has to be of type input/output.
+ *
+ * It should be noted that the caller cannot reuse the \c ctx member of U/K
+ * argument structure after a U/K call, because it may be overwritten. Instead,
+ * the context handle must always be stored  elsewhere, and copied into
+ * the appropriate U/K argument structure for each user-side call to
+ * the U/K interface. This is not usually a problem, since U/K argument
+ * structures are usually placed on the stack.
+ *
+ * @{ */
+
+/** @brief Begin a new Mali Device Driver session
+ *
+ * This is used to obtain a per-process context handle for all future U/K calls.
+ *
+ * @param context pointer to storage to return a (void*)context handle.
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_open( void **context );
+
+/** @brief End a Mali Device Driver session
+ *
+ * This should be called when the process no longer requires use of the Mali Device Driver.
+ *
+ * The context handle must not be used after it has been closed.
+ *
+ * @param context pointer to a stored (void*)context handle.
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_close( void **context );
+
+/** @} */ /* end group _mali_uk_context */
+
+
+/** @addtogroup _mali_uk_core U/K Core
+ *
+ * The core functions provide the following functionality:
+ * - verify that the user and kernel API are compatible
+ * - retrieve information about the cores and memory banks in the system
+ * - wait for the result of jobs started on a core
+ *
+ * @{ */
+
+/** @brief Waits for a job notification.
+ *
+ * Sleeps until notified or a timeout occurs. Returns information about the notification.
+ *
+ * @param args see _mali_uk_wait_for_notification_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args );
+
+/** @brief Post a notification to the notification queue of this application.
+ *
+ * @param args see _mali_uk_post_notification_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args );
+
+/** @brief Verifies if the user and kernel side of this API are compatible.
+ *
+ * @param args see _mali_uk_get_api_version_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args );
+
+/** @brief Get the user space settings applicable for calling process.
+ *
+ * @param args see _mali_uk_get_user_settings_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args);
+
+/** @brief Get a user space setting applicable for calling process.
+ *
+ * @param args see _mali_uk_get_user_setting_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args);
+
+/* @brief Grant or deny high priority scheduling for this session.
+ *
+ * @param args see _mali_uk_request_high_priority_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_request_high_priority(_mali_uk_request_high_priority_s *args);
+
+/** @} */ /* end group _mali_uk_core */
+
+
+/** @addtogroup _mali_uk_memory U/K Memory
+ *
+ * The memory functions provide functionality with and without a Mali-MMU present.
+ *
+ * For Mali-MMU based systems, the following functionality is provided:
+ * - Initialize and terminate MALI virtual address space
+ * - Allocate/deallocate physical memory to a MALI virtual address range and map into/unmap from the
+ * current process address space
+ * - Map/unmap external physical memory into the MALI virtual address range
+ *
+ * For Mali-nonMMU based systems:
+ * - Allocate/deallocate MALI memory
+ *
+ * @{ */
+
+/** @brief Map Mali Memory into the current user process
+ *
+ * Maps Mali memory into the current user process in a generic way.
+ *
+ * This function is to be used for Mali-MMU mode. The function is available in both Mali-MMU and Mali-nonMMU modes,
+ * but should not be called by a user process in Mali-nonMMU mode.
+ *
+ * The implementation and operation of _mali_ukk_mem_mmap() is dependant on whether the driver is built for Mali-MMU
+ * or Mali-nonMMU:
+ * - In the nonMMU case, _mali_ukk_mem_mmap() requires a physical address to be specified. For this reason, an OS U/K
+ * implementation should not allow this to be called from user-space. In any case, nonMMU implementations are
+ * inherently insecure, and so the overall impact is minimal. Mali-MMU mode should be used if security is desired.
+ * - In the MMU case, _mali_ukk_mem_mmap() the _mali_uk_mem_mmap_s::phys_addr
+ * member is used for the \em Mali-virtual address desired for the mapping. The
+ * implementation of _mali_ukk_mem_mmap() will allocate both the CPU-virtual
+ * and CPU-physical addresses, and can cope with mapping a contiguous virtual
+ * address range to a sequence of non-contiguous physical pages. In this case,
+ * the CPU-physical addresses are not communicated back to the user-side, as
+ * they are unnecsessary; the \em Mali-virtual address range must be used for
+ * programming Mali structures.
+ *
+ * In the second (MMU) case, _mali_ukk_mem_mmap() handles management of
+ * CPU-virtual and CPU-physical ranges, but the \em caller must manage the
+ * \em Mali-virtual address range from the user-side.
+ *
+ * @note Mali-virtual address ranges are entirely separate between processes.
+ * It is not possible for a process to accidentally corrupt another process'
+ * \em Mali-virtual address space.
+ *
+ * @param args see _mali_uk_mem_mmap_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args );
+
+/** @brief Unmap Mali Memory from the current user process
+ *
+ * Unmaps Mali memory from the current user process in a generic way. This only operates on Mali memory supplied
+ * from _mali_ukk_mem_mmap().
+ *
+ * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args );
+
+/** @brief Determine the buffer size necessary for an MMU page table dump.
+ * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args );
+/** @brief Dump MMU Page tables.
+ * @param args see _mali_uk_dump_mmu_page_table_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args );
+
+/** @brief Write user data to specified Mali memory without causing segfaults.
+ * @param args see _mali_uk_mem_write_safe_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_mem_write_safe( _mali_uk_mem_write_safe_s *args );
+
+/** @brief Map a physically contiguous range of memory into Mali
+ * @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args );
+
+/** @brief Unmap a physically contiguous range of memory from Mali
+ * @param args see _mali_uk_unmap_external_mem_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args );
+
+#if defined(CONFIG_MALI400_UMP)
+/** @brief Map UMP memory into Mali
+ * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args );
+/** @brief Unmap UMP memory from Mali
+ * @param args see _mali_uk_release_ump_mem_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args );
+#endif /* CONFIG_MALI400_UMP */
+
+/** @brief Determine virtual-to-physical mapping of a contiguous memory range
+ * (optional)
+ *
+ * This allows the user-side to do a virtual-to-physical address translation.
+ * In conjunction with _mali_uku_map_external_mem, this can be used to do
+ * direct rendering.
+ *
+ * This function will only succeed on a virtual range that is mapped into the
+ * current process, and that is contigious.
+ *
+ * If va is not page-aligned, then it is rounded down to the next page
+ * boundary. The remainer is added to size, such that ((u32)va)+size before
+ * rounding is equal to ((u32)va)+size after rounding. The rounded modified
+ * va and size will be written out into args on success.
+ *
+ * If the supplied size is zero, or not a multiple of the system's PAGE_SIZE,
+ * then size will be rounded up to the next multiple of PAGE_SIZE before
+ * translation occurs. The rounded up size will be written out into args on
+ * success.
+ *
+ * On most OSs, virtual-to-physical address translation is a priveledged
+ * function. Therefore, the implementer must validate the range supplied, to
+ * ensure they are not providing arbitrary virtual-to-physical address
+ * translations. While it is unlikely such a mechanism could be used to
+ * compromise the security of a system on its own, it is possible it could be
+ * combined with another small security risk to cause a much larger security
+ * risk.
+ *
+ * @note This is an optional part of the interface, and is only used by certain
+ * implementations of libEGL. If the platform layer in your libEGL
+ * implementation does not require Virtual-to-Physical address translation,
+ * then this function need not be implemented. A stub implementation should not
+ * be required either, as it would only be removed by the compiler's dead code
+ * elimination.
+ *
+ * @note if implemented, this function is entirely platform-dependant, and does
+ * not exist in common code.
+ *
+ * @param args see _mali_uk_va_to_mali_pa_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args );
+
+/** @} */ /* end group _mali_uk_memory */
+
+
+/** @addtogroup _mali_uk_pp U/K Fragment Processor
+ *
+ * The Fragment Processor (aka PP (Pixel Processor)) functions provide the following functionality:
+ * - retrieving version of the fragment processors
+ * - determine number of fragment processors
+ * - starting a job on a fragment processor
+ *
+ * @{ */
+
+/** @brief Issue a request to start a new job on a Fragment Processor.
+ *
+ * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can
+ * try to start the job again.
+ *
+ * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job
+ * which the hardware hasn't actually started processing yet. In this case the new job will be started instead and the
+ * existing one returned, otherwise the new job is started and the status field args->status is set to
+ * _MALI_UK_START_JOB_STARTED.
+ *
+ * Job completion can be awaited with _mali_ukk_wait_for_notification().
+ *
+ * @param ctx user-kernel context (mali_session)
+ * @param uargs see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data!
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_pp_start_job( void *ctx, _mali_uk_pp_start_job_s *uargs );
+
+/**
+ * @brief Issue a request to start new jobs on both Vertex Processor and Fragment Processor.
+ *
+ * @note Will call into @ref _mali_ukk_pp_start_job and @ref _mali_ukk_gp_start_job.
+ *
+ * @param ctx user-kernel context (mali_session)
+ * @param uargs see _mali_uk_pp_and_gp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data!
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_pp_and_gp_start_job( void *ctx, _mali_uk_pp_and_gp_start_job_s *uargs );
+
+/** @brief Returns the number of Fragment Processors in the system
+ *
+ * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args );
+
+/** @brief Returns the version that all Fragment Processor cores are compatible with.
+ *
+ * This function may only be called when _mali_ukk_get_pp_number_of_cores() indicated at least one Fragment
+ * Processor core is available.
+ *
+ * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args );
+
+/** @brief Disable Write-back unit(s) on specified job
+ *
+ * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h"
+ */
+void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args);
+
+
+/** @} */ /* end group _mali_uk_pp */
+
+
+/** @addtogroup _mali_uk_gp U/K Vertex Processor
+ *
+ * The Vertex Processor (aka GP (Geometry Processor)) functions provide the following functionality:
+ * - retrieving version of the Vertex Processors
+ * - determine number of Vertex Processors available
+ * - starting a job on a Vertex Processor
+ *
+ * @{ */
+
+/** @brief Issue a request to start a new job on a Vertex Processor.
+ *
+ * If the request fails args->status is set to _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE and you can
+ * try to start the job again.
+ *
+ * An existing job could be returned for requeueing if the new job has a higher priority than a previously started job
+ * which the hardware hasn't actually started processing yet. In this case the new job will be started and the
+ * existing one returned, otherwise the new job is started and the status field args->status is set to
+ * _MALI_UK_START_JOB_STARTED.
+ *
+ * Job completion can be awaited with _mali_ukk_wait_for_notification().
+ *
+ * @param ctx user-kernel context (mali_session)
+ * @param uargs see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data!
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_gp_start_job( void *ctx, _mali_uk_gp_start_job_s *uargs );
+
+/** @brief Returns the number of Vertex Processors in the system.
+ *
+ * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args );
+
+/** @brief Returns the version that all Vertex Processor cores are compatible with.
+ *
+ * This function may only be called when _mali_uk_get_gp_number_of_cores() indicated at least one Vertex
+ * Processor core is available.
+ *
+ * @param args see _mali_uk_get_gp_core_version_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args );
+
+/** @brief Resume or abort suspended Vertex Processor jobs.
+ *
+ * After receiving notification that a Vertex Processor job was suspended from
+ * _mali_ukk_wait_for_notification() you can use this function to resume or abort the job.
+ *
+ * @param args see _mali_uk_gp_suspend_response_s in "mali_utgard_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args );
+
+/** @} */ /* end group _mali_uk_gp */
+
+#if defined(CONFIG_MALI400_PROFILING)
+/** @addtogroup _mali_uk_profiling U/K Timeline profiling module
+ * @{ */
+
+/** @brief Start recording profiling events.
+ *
+ * @param args see _mali_uk_profiling_start_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args);
+
+/** @brief Add event to profiling buffer.
+ *
+ * @param args see _mali_uk_profiling_add_event_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args);
+
+/** @brief Stop recording profiling events.
+ *
+ * @param args see _mali_uk_profiling_stop_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args);
+
+/** @brief Retrieve a recorded profiling event.
+ *
+ * @param args see _mali_uk_profiling_get_event_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args);
+
+/** @brief Clear recorded profiling events.
+ *
+ * @param args see _mali_uk_profiling_clear_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args);
+
+/** @} */ /* end group _mali_uk_profiling */
+#endif
+
+/** @addtogroup _mali_uk_vsync U/K VSYNC reporting module
+ * @{ */
+
+/** @brief Report events related to vsync.
+ *
+ * @note Events should be reported when starting to wait for vsync and when the
+ * waiting is finished. This information can then be used in kernel space to
+ * complement the GPU utilization metric.
+ *
+ * @param args see _mali_uk_vsync_event_report_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args);
+
+/** @} */ /* end group _mali_uk_vsync */
+
+/** @addtogroup _mali_sw_counters_report U/K Software counter reporting
+ * @{ */
+
+/** @brief Report software counters.
+ *
+ * @param args see _mali_uk_sw_counters_report_s in "mali_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args);
+
+/** @} */ /* end group _mali_sw_counters_report */
+
+/** @} */ /* end group u_k_api */
+
+/** @} */ /* end group uddapi */
+
+u32 _mali_ukk_report_memory_usage(void);
+
+u32 _mali_ukk_utilization_gp_pp(void);
+
+u32 _mali_ukk_utilization_gp(void);
+
+u32 _mali_ukk_utilization_pp(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UKK_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_user_settings_db.c b/drivers/gpu/arm/mali400/mali/common/mali_user_settings_db.c
new file mode 100755 (executable)
index 0000000..c28a8d6
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_uk_types.h"
+#include "mali_user_settings_db.h"
+#include "mali_session.h"
+
+static u32 mali_user_settings[_MALI_UK_USER_SETTING_MAX];
+const char *_mali_uk_user_setting_descriptions[] = _MALI_UK_USER_SETTING_DESCRIPTIONS;
+
+static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value)
+{
+       mali_bool done = MALI_FALSE;
+
+       /*
+        * This function gets a bit complicated because we can't hold the session lock while
+        * allocating notification objects.
+        */
+
+       while (!done) {
+               u32 i;
+               u32 num_sessions_alloc;
+               u32 num_sessions_with_lock;
+               u32 used_notification_objects = 0;
+               _mali_osk_notification_t **notobjs;
+
+               /* Pre allocate the number of notifications objects we need right now (might change after lock has been taken) */
+               num_sessions_alloc = mali_session_get_count();
+               if (0 == num_sessions_alloc) {
+                       /* No sessions to report to */
+                       return;
+               }
+
+               notobjs = (_mali_osk_notification_t **)_mali_osk_malloc(sizeof(_mali_osk_notification_t *) * num_sessions_alloc);
+               if (NULL == notobjs) {
+                       MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change (alloc failure)\n"));
+                       return;
+               }
+
+               for (i = 0; i < num_sessions_alloc; i++) {
+                       notobjs[i] = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED,
+                                    sizeof(_mali_uk_settings_changed_s));
+                       if (NULL != notobjs[i]) {
+                               _mali_uk_settings_changed_s *data;
+                               data = notobjs[i]->result_buffer;
+
+                               data->setting = setting;
+                               data->value = value;
+                       } else {
+                               MALI_PRINT_ERROR(("Failed to notify user space session about setting change (alloc failure %u)\n", i));
+                       }
+               }
+
+               mali_session_lock();
+
+               /* number of sessions will not change while we hold the lock */
+               num_sessions_with_lock = mali_session_get_count();
+
+               if (num_sessions_alloc >= num_sessions_with_lock) {
+                       /* We have allocated enough notification objects for all the sessions atm */
+                       struct mali_session_data *session, *tmp;
+                       MALI_SESSION_FOREACH(session, tmp, link) {
+                               MALI_DEBUG_ASSERT(used_notification_objects < num_sessions_alloc);
+                               if (NULL != notobjs[used_notification_objects]) {
+                                       mali_session_send_notification(session, notobjs[used_notification_objects]);
+                                       notobjs[used_notification_objects] = NULL; /* Don't track this notification object any more */
+                               }
+                               used_notification_objects++;
+                       }
+                       done = MALI_TRUE;
+               }
+
+               mali_session_unlock();
+
+               /* Delete any remaining/unused notification objects */
+               for (; used_notification_objects < num_sessions_alloc; used_notification_objects++) {
+                       if (NULL != notobjs[used_notification_objects]) {
+                               _mali_osk_notification_delete(notobjs[used_notification_objects]);
+                       }
+               }
+
+               _mali_osk_free(notobjs);
+       }
+}
+
+void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value)
+{
+       mali_bool notify = MALI_FALSE;
+
+       if (setting >= _MALI_UK_USER_SETTING_MAX) {
+               MALI_DEBUG_PRINT_ERROR(("Invalid user setting %ud\n"));
+               return;
+       }
+
+       if (mali_user_settings[setting] != value) {
+               notify = MALI_TRUE;
+       }
+
+       mali_user_settings[setting] = value;
+
+       if (notify) {
+               mali_user_settings_notify(setting, value);
+       }
+}
+
+u32 mali_get_user_setting(_mali_uk_user_setting_t setting)
+{
+       if (setting >= _MALI_UK_USER_SETTING_MAX) {
+               return 0;
+       }
+
+       return mali_user_settings[setting];
+}
+
+_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args)
+{
+       _mali_uk_user_setting_t setting;
+       MALI_DEBUG_ASSERT_POINTER(args);
+
+       setting = args->setting;
+
+       if (_MALI_UK_USER_SETTING_MAX > setting) {
+               args->value = mali_user_settings[setting];
+               return _MALI_OSK_ERR_OK;
+       } else {
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+}
+
+_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args)
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+
+       _mali_osk_memcpy(args->settings, mali_user_settings, sizeof(mali_user_settings));
+
+       return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali400/mali/common/mali_user_settings_db.h b/drivers/gpu/arm/mali400/mali/common/mali_user_settings_db.h
new file mode 100755 (executable)
index 0000000..547ffee
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_USER_SETTINGS_DB_H__
+#define __MALI_USER_SETTINGS_DB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mali_uk_types.h"
+
+/** @brief Set Mali user setting in DB
+ *
+ * Update the DB with a new value for \a setting. If the value is different from theprevious set value running sessions will be notified of the change.
+ *
+ * @param setting the setting to be changed
+ * @param value the new value to set
+ */
+void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value);
+
+/** @brief Get current Mali user setting value from DB
+ *
+ * @param setting the setting to extract
+ * @return the value of the selected setting
+ */
+u32 mali_get_user_setting(_mali_uk_user_setting_t setting);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* __MALI_KERNEL_USER_SETTING__ */
diff --git a/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard.h b/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard.h
new file mode 100755 (executable)
index 0000000..16dd5e4
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_utgard.h
+ * Defines types and interface exposed by the Mali Utgard device driver
+ */
+
+#ifndef __MALI_UTGARD_H__
+#define __MALI_UTGARD_H__
+
+#include "mali_osk_types.h"
+
+#define MALI_GPU_NAME_UTGARD "mali-utgard"
+
+/* Mali-200 */
+
+#define MALI_GPU_RESOURCES_MALI200(base_addr, gp_irq, pp_irq, mmu_irq) \
+       MALI_GPU_RESOURCE_PP(base_addr + 0x0000, pp_irq) \
+       MALI_GPU_RESOURCE_GP(base_addr + 0x2000, gp_irq) \
+       MALI_GPU_RESOURCE_MMU(base_addr + 0x3000, mmu_irq)
+
+/* Mali-300 */
+
+#define MALI_GPU_RESOURCES_MALI300(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI300_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp_irq, pp_mmu_irq)
+
+/* Mali-400 */
+
+#define MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP1_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP1(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+#define MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+#define MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+#define MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x1000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x0000, gp_irq, base_addr + 0x3000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x8000, pp0_irq, base_addr + 0x4000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0xA000, pp1_irq, base_addr + 0x5000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0xC000, pp2_irq, base_addr + 0x6000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0xE000, pp3_irq, base_addr + 0x7000, pp3_mmu_irq)
+
+#define MALI_GPU_RESOURCES_MALI400_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \
+       MALI_GPU_RESOURCES_MALI400_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000)
+
+/* Mali-450 */
+#define MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) \
+       MALI_GPU_RESOURCE_DMA(base_addr + 0x12000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP2_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP2(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+#define MALI_GPU_RESOURCES_MALI450_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP3_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP3(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+#define MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) \
+       MALI_GPU_RESOURCE_DMA(base_addr + 0x12000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP4_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP4(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+#define MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x28000, pp3_irq, base_addr + 0x1C000, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x2A000, pp4_irq, base_addr + 0x1D000, pp4_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2C000, pp5_irq, base_addr + 0x1E000, pp5_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) \
+       MALI_GPU_RESOURCE_DMA(base_addr + 0x12000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP6_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP6(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+#define MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x10000) \
+       MALI_GPU_RESOURCE_GP_WITH_MMU(base_addr + 0x00000, gp_irq, base_addr + 0x03000, gp_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x01000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(0, base_addr + 0x08000, pp0_irq, base_addr + 0x04000, pp0_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(1, base_addr + 0x0A000, pp1_irq, base_addr + 0x05000, pp1_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(2, base_addr + 0x0C000, pp2_irq, base_addr + 0x06000, pp2_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(3, base_addr + 0x0E000, pp3_irq, base_addr + 0x07000, pp3_mmu_irq) \
+       MALI_GPU_RESOURCE_L2(base_addr + 0x11000) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(4, base_addr + 0x28000, pp4_irq, base_addr + 0x1C000, pp4_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(5, base_addr + 0x2A000, pp5_irq, base_addr + 0x1D000, pp5_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(6, base_addr + 0x2C000, pp6_irq, base_addr + 0x1E000, pp6_mmu_irq) \
+       MALI_GPU_RESOURCE_PP_WITH_MMU(7, base_addr + 0x2E000, pp7_irq, base_addr + 0x1F000, pp7_mmu_irq) \
+       MALI_GPU_RESOURCE_BCAST(base_addr + 0x13000) \
+       MALI_GPU_RESOURCE_DLBU(base_addr + 0x14000) \
+       MALI_GPU_RESOURCE_PP_BCAST(base_addr + 0x16000, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PP_MMU_BCAST(base_addr + 0x15000) \
+       MALI_GPU_RESOURCE_DMA(base_addr + 0x12000)
+
+#define MALI_GPU_RESOURCES_MALI450_MP8_PMU(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCES_MALI450_MP8(base_addr, gp_irq, gp_mmu_irq, pp0_irq, pp0_mmu_irq, pp1_irq, pp1_mmu_irq, pp2_irq, pp2_mmu_irq, pp3_irq, pp3_mmu_irq, pp4_irq, pp4_mmu_irq, pp5_irq, pp5_mmu_irq, pp6_irq, pp6_mmu_irq, pp7_irq, pp7_mmu_irq, pp_bcast_irq) \
+       MALI_GPU_RESOURCE_PMU(base_addr + 0x2000) \
+#define MALI_GPU_RESOURCE_L2(addr) \
+       { \
+               .name = "Mali_L2", \
+               .flags = IORESOURCE_MEM, \
+               .start = addr, \
+               .end   = addr + 0x200, \
+       },
+
+#define MALI_GPU_RESOURCE_GP(gp_addr, gp_irq) \
+       { \
+               .name = "Mali_GP", \
+               .flags = IORESOURCE_MEM, \
+               .start = gp_addr, \
+               .end =   gp_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_GP_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = gp_irq, \
+               .end   = gp_irq, \
+       }, \
+#define MALI_GPU_RESOURCE_GP_WITH_MMU(gp_addr, gp_irq, gp_mmu_addr, gp_mmu_irq) \
+       { \
+               .name = "Mali_GP", \
+               .flags = IORESOURCE_MEM, \
+               .start = gp_addr, \
+               .end =   gp_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_GP_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = gp_irq, \
+               .end   = gp_irq, \
+       }, \
+       { \
+               .name = "Mali_GP_MMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = gp_mmu_addr, \
+               .end =   gp_mmu_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_GP_MMU_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = gp_mmu_irq, \
+               .end =   gp_mmu_irq, \
+       },
+
+#define MALI_GPU_RESOURCE_PP(pp_addr, pp_irq) \
+       { \
+               .name = "Mali_PP", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_addr, \
+               .end =   pp_addr + 0x1100, \
+       }, \
+       { \
+               .name = "Mali_PP_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_irq, \
+               .end =   pp_irq, \
+       }, \
+#define MALI_GPU_RESOURCE_PP_WITH_MMU(id, pp_addr, pp_irq, pp_mmu_addr, pp_mmu_irq) \
+       { \
+               .name = "Mali_PP" #id, \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_addr, \
+               .end =   pp_addr + 0x1100, \
+       }, \
+       { \
+               .name = "Mali_PP" #id "_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_irq, \
+               .end =   pp_irq, \
+       }, \
+       { \
+               .name = "Mali_PP" #id "_MMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_mmu_addr, \
+               .end =   pp_mmu_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_PP" #id "_MMU_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_mmu_irq, \
+               .end =   pp_mmu_irq, \
+       },
+
+#define MALI_GPU_RESOURCE_MMU(mmu_addr, mmu_irq) \
+       { \
+               .name = "Mali_MMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = mmu_addr, \
+               .end =   mmu_addr + 0x100, \
+       }, \
+       { \
+               .name = "Mali_MMU_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = mmu_irq, \
+               .end =   mmu_irq, \
+       },
+
+#define MALI_GPU_RESOURCE_PMU(pmu_addr) \
+       { \
+               .name = "Mali_PMU", \
+               .flags = IORESOURCE_MEM, \
+               .start = pmu_addr, \
+               .end =   pmu_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_DMA(dma_addr) \
+       { \
+               .name = "Mali_DMA", \
+               .flags = IORESOURCE_MEM, \
+               .start = dma_addr, \
+               .end = dma_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_DLBU(dlbu_addr) \
+       { \
+               .name = "Mali_DLBU", \
+               .flags = IORESOURCE_MEM, \
+               .start = dlbu_addr, \
+               .end = dlbu_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_BCAST(bcast_addr) \
+       { \
+               .name = "Mali_Broadcast", \
+               .flags = IORESOURCE_MEM, \
+               .start = bcast_addr, \
+               .end = bcast_addr + 0x100, \
+       },
+
+#define MALI_GPU_RESOURCE_PP_BCAST(pp_addr, pp_irq) \
+       { \
+               .name = "Mali_PP_Broadcast", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_addr, \
+               .end =   pp_addr + 0x1100, \
+       }, \
+       { \
+               .name = "Mali_PP_Broadcast_IRQ", \
+               .flags = IORESOURCE_IRQ, \
+               .start = pp_irq, \
+               .end =   pp_irq, \
+       }, \
+#define MALI_GPU_RESOURCE_PP_MMU_BCAST(pp_mmu_bcast_addr) \
+       { \
+               .name = "Mali_PP_MMU_Broadcast", \
+               .flags = IORESOURCE_MEM, \
+               .start = pp_mmu_bcast_addr, \
+               .end = pp_mmu_bcast_addr + 0x100, \
+       },
+
+struct mali_gpu_utilization_data {
+       unsigned int utilization_gpu; /* Utilization for GP and all PP cores combined, 0 = no utilization, 256 = full utilization */
+       unsigned int utilization_gp;  /* Utilization for GP core only, 0 = no utilization, 256 = full utilization */
+       unsigned int utilization_pp;  /* Utilization for all PP cores combined, 0 = no utilization, 256 = full utilization */
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+       unsigned int number_of_window_jobs;
+       unsigned int number_of_window_jobs_under_pressure;
+#endif
+};
+
+struct mali_gpu_device_data {
+       /* Dedicated GPU memory range (physical). */
+       unsigned long dedicated_mem_start;
+       unsigned long dedicated_mem_size;
+
+       /* Shared GPU memory */
+       unsigned long shared_mem_size;
+
+       /* Frame buffer memory to be accessible by Mali GPU (physical) */
+       unsigned long fb_start;
+       unsigned long fb_size;
+
+       /* Max runtime [ms] for jobs */
+       int max_job_runtime;
+
+       /* Report GPU utilization in this interval (specified in ms) */
+       unsigned long utilization_interval;
+
+       /* Function that will receive periodic GPU utilization numbers */
+       void (*utilization_callback)(struct mali_gpu_utilization_data *data);
+
+       /*
+        * Mali PMU switch delay.
+        * Only needed if the power gates are connected to the PMU in a high fanout
+        * network. This value is the number of Mali clock cycles it takes to
+        * enable the power gates and turn on the power mesh.
+        * This value will have no effect if a daisy chain implementation is used.
+        */
+       u32 pmu_switch_delay;
+
+
+       /* Mali Dynamic power domain configuration in sequence from 0-11
+        *  GP  PP0 PP1  PP2  PP3  PP4  PP5  PP6  PP7, L2$0 L2$1 L2$2
+        */
+       u16 pmu_domain_config[12];
+
+       /* Fuction that platform callback for freq tunning, needed when POWER_PERFORMANCE_POLICY enabled*/
+       int (*set_freq_callback)(unsigned int mhz);
+};
+
+/** @brief MALI GPU power down using MALI in-built PMU
+ *
+ * called to power down all cores
+ */
+int mali_pmu_powerdown(void);
+
+
+/** @brief MALI GPU power up using MALI in-built PMU
+ *
+ * called to power up all cores
+ */
+int mali_pmu_powerup(void);
+
+/**
+ * Pause the scheduling and power state changes of Mali device driver.
+ * mali_dev_resume() must always be called as soon as possible after this function
+ * in order to resume normal operation of the Mali driver.
+ */
+void mali_dev_pause(void);
+
+/**
+ * Resume scheduling and allow power changes in Mali device driver.
+ * This must always be called after mali_dev_pause().
+ */
+void mali_dev_resume(void);
+
+/** @brief Set the desired number of PP cores to use.
+ *
+ * The internal Mali PMU will be used, if present, to physically power off the PP cores.
+ *
+ * @param num_cores The number of desired cores
+ * @return 0 on success, otherwise error. -EINVAL means an invalid number of cores was specified.
+ */
+int mali_perf_set_num_pp_cores(unsigned int num_cores);
+
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_counters.h b/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_counters.h
new file mode 100755 (executable)
index 0000000..7ea190f
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef _MALI_UTGARD_COUNTERS_H_
+#define _MALI_UTGARD_COUNTERS_H_
+
+typedef struct {
+       void *unused;
+} mali_cinstr_counter_info;
+
+typedef enum {
+       MALI_CINSTR_COUNTER_SOURCE_EGL      =     0,
+       MALI_CINSTR_COUNTER_SOURCE_OPENGLES =  1000,
+       MALI_CINSTR_COUNTER_SOURCE_OPENVG   =  2000,
+       MALI_CINSTR_COUNTER_SOURCE_GP       =  3000,
+       MALI_CINSTR_COUNTER_SOURCE_PP       =  4000,
+} cinstr_counter_source;
+
+#define MALI_CINSTR_EGL_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_EGL
+#define MALI_CINSTR_EGL_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_EGL + 999)
+
+#define MALI_CINSTR_GLES_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENGLES
+#define MALI_CINSTR_GLES_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 999)
+
+#define MALI_CINSTR_VG_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENVG
+#define MALI_CINSTR_VG_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENVG + 999)
+
+#define MALI_CINSTR_GP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_GP
+#define MALI_CINSTR_GP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_GP + 999)
+
+#define MALI_CINSTR_PP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_PP
+#define MALI_CINSTR_PP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_PP + 999)
+
+
+typedef enum {
+       /* EGL counters */
+
+       MALI_CINSTR_EGL_BLIT_TIME                                            = MALI_CINSTR_COUNTER_SOURCE_EGL + 0,
+
+       /* Last counter in the EGL set */
+       MALI_CINSTR_EGL_MAX_COUNTER                                           = MALI_CINSTR_COUNTER_SOURCE_EGL + 1,
+
+       /* GLES counters */
+
+       MALI_CINSTR_GLES_DRAW_ELEMENTS_CALLS                                 = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 0,
+       MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_INDICES                           = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 1,
+       MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED                       = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 2,
+       MALI_CINSTR_GLES_DRAW_ARRAYS_CALLS                                   = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 3,
+       MALI_CINSTR_GLES_DRAW_ARRAYS_NUM_TRANSFORMED                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 4,
+       MALI_CINSTR_GLES_DRAW_POINTS                                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 5,
+       MALI_CINSTR_GLES_DRAW_LINES                                          = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 6,
+       MALI_CINSTR_GLES_DRAW_LINE_LOOP                                      = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 7,
+       MALI_CINSTR_GLES_DRAW_LINE_STRIP                                     = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 8,
+       MALI_CINSTR_GLES_DRAW_TRIANGLES                                      = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 9,
+       MALI_CINSTR_GLES_DRAW_TRIANGLE_STRIP                                 = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 10,
+       MALI_CINSTR_GLES_DRAW_TRIANGLE_FAN                                   = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 11,
+       MALI_CINSTR_GLES_NON_VBO_DATA_COPY_TIME                              = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 12,
+       MALI_CINSTR_GLES_UNIFORM_BYTES_COPIED_TO_MALI                        = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 13,
+       MALI_CINSTR_GLES_UPLOAD_TEXTURE_TIME                                 = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 14,
+       MALI_CINSTR_GLES_UPLOAD_VBO_TIME                                     = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 15,
+       MALI_CINSTR_GLES_NUM_FLUSHES                                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 16,
+       MALI_CINSTR_GLES_NUM_VSHADERS_GENERATED                              = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 17,
+       MALI_CINSTR_GLES_NUM_FSHADERS_GENERATED                              = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 18,
+       MALI_CINSTR_GLES_VSHADER_GEN_TIME                                    = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 19,
+       MALI_CINSTR_GLES_FSHADER_GEN_TIME                                    = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 20,
+       MALI_CINSTR_GLES_INPUT_TRIANGLES                                     = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 21,
+       MALI_CINSTR_GLES_VXCACHE_HIT                                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 22,
+       MALI_CINSTR_GLES_VXCACHE_MISS                                        = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 23,
+       MALI_CINSTR_GLES_VXCACHE_COLLISION                                   = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 24,
+       MALI_CINSTR_GLES_CULLED_TRIANGLES                                    = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 25,
+       MALI_CINSTR_GLES_CULLED_LINES                                        = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 26,
+       MALI_CINSTR_GLES_BACKFACE_TRIANGLES                                  = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 27,
+       MALI_CINSTR_GLES_GBCLIP_TRIANGLES                                    = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 28,
+       MALI_CINSTR_GLES_GBCLIP_LINES                                        = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 29,
+       MALI_CINSTR_GLES_TRIANGLES_DRAWN                                     = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 30,
+       MALI_CINSTR_GLES_DRAWCALL_TIME                                       = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 31,
+       MALI_CINSTR_GLES_TRIANGLES_COUNT                                     = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 32,
+       MALI_CINSTR_GLES_INDEPENDENT_TRIANGLES_COUNT                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 33,
+       MALI_CINSTR_GLES_STRIP_TRIANGLES_COUNT                               = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 34,
+       MALI_CINSTR_GLES_FAN_TRIANGLES_COUNT                                 = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 35,
+       MALI_CINSTR_GLES_LINES_COUNT                                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 36,
+       MALI_CINSTR_GLES_INDEPENDENT_LINES_COUNT                             = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 37,
+       MALI_CINSTR_GLES_STRIP_LINES_COUNT                                   = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 38,
+       MALI_CINSTR_GLES_LOOP_LINES_COUNT                                    = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 39,
+       MALI_CINSTR_GLES_POINTS_COUNT                                        = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 40,
+
+       /* Last counter in the GLES set */
+       MALI_CINSTR_GLES_MAX_COUNTER                                         = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 41,
+
+       /* OpenVG counters */
+
+       MALI_CINSTR_VG_MASK_COUNTER                                          = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 0,
+       MALI_CINSTR_VG_CLEAR_COUNTER                                         = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 1,
+       MALI_CINSTR_VG_APPEND_PATH_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 2,
+       MALI_CINSTR_VG_APPEND_PATH_DATA_COUNTER                              = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 3,
+       MALI_CINSTR_VG_MODIFY_PATH_COORDS_COUNTER                            = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 4,
+       MALI_CINSTR_VG_TRANSFORM_PATH_COUNTER                                = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 5,
+       MALI_CINSTR_VG_INTERPOLATE_PATH_COUNTER                              = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 6,
+       MALI_CINSTR_VG_PATH_LENGTH_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 7,
+       MALI_CINSTR_VG_POINT_ALONG_PATH_COUNTER                              = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 8,
+       MALI_CINSTR_VG_PATH_BOUNDS_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 9,
+       MALI_CINSTR_VG_PATH_TRANSFORMED_BOUNDS_COUNTER                       = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 10,
+       MALI_CINSTR_VG_DRAW_PATH_COUNTER                                     = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 11,
+       MALI_CINSTR_VG_CLEAR_IMAGE_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 12,
+       MALI_CINSTR_VG_IMAGE_SUB_DATA_COUNTER                                = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 13,
+       MALI_CINSTR_VG_GET_IMAGE_SUB_DATA_COUNTER                            = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 14,
+       MALI_CINSTR_VG_COPY_IMAGE_COUNTER                                    = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 15,
+       MALI_CINSTR_VG_DRAW_IMAGE_COUNTER                                    = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 16,
+       MALI_CINSTR_VG_SET_PIXELS_COUNTER                                    = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 17,
+       MALI_CINSTR_VG_WRITE_PIXELS_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 18,
+       MALI_CINSTR_VG_GET_PIXELS_COUNTER                                    = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 19,
+       MALI_CINSTR_VG_READ_PIXELS_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 20,
+       MALI_CINSTR_VG_COPY_PIXELS_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 21,
+       MALI_CINSTR_VG_COLOR_MATRIX_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 22,
+       MALI_CINSTR_VG_CONVOLVE_COUNTER                                      = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 23,
+       MALI_CINSTR_VG_SEPARABLE_CONVOLVE_COUNTER                            = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 24,
+       MALI_CINSTR_VG_GAUSSIAN_BLUR_COUNTER                                 = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 25,
+       MALI_CINSTR_VG_LOOKUP_COUNTER                                        = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 26,
+       MALI_CINSTR_VG_LOOKUP_SINGLE_COUNTER                                 = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 27,
+       MALI_CINSTR_VG_CONTEXT_CREATE_COUNTER                                = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 28,
+       MALI_CINSTR_VG_STROKED_CUBICS_COUNTER                                = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 29,
+       MALI_CINSTR_VG_STROKED_QUADS_COUNTER                                 = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 30,
+       MALI_CINSTR_VG_STROKED_ARCS_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 31,
+       MALI_CINSTR_VG_STROKED_LINES_COUNTER                                 = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 32,
+       MALI_CINSTR_VG_FILLED_CUBICS_COUNTER                                 = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 33,
+       MALI_CINSTR_VG_FILLED_QUADS_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 34,
+       MALI_CINSTR_VG_FILLED_ARCS_COUNTER                                   = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 35,
+       MALI_CINSTR_VG_FILLED_LINES_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 36,
+       MALI_CINSTR_VG_DRAW_PATH_CALLS_COUNTER                               = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 37,
+       MALI_CINSTR_VG_TRIANGLES_COUNTER                                     = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 38,
+       MALI_CINSTR_VG_VERTICES_COUNTER                                      = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 39,
+       MALI_CINSTR_VG_INDICES_COUNTER                                       = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 40,
+       MALI_CINSTR_VG_FILLED_PATHS_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 41,
+       MALI_CINSTR_VG_STROKED_PATHS_COUNTER                                 = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 42,
+       MALI_CINSTR_VG_FILL_EXTRACT_COUNTER                                  = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 43,
+       MALI_CINSTR_VG_DRAW_FILLED_PATH_COUNTER                              = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 44,
+       MALI_CINSTR_VG_STROKE_EXTRACT_COUNTER                                = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 45,
+       MALI_CINSTR_VG_DRAW_STROKED_PATH_COUNTER                             = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 46,
+       MALI_CINSTR_VG_DRAW_PAINT_COUNTER                                    = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 47,
+       MALI_CINSTR_VG_DATA_STRUCTURES_COUNTER                               = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 48,
+       MALI_CINSTR_VG_MEM_PATH_COUNTER                                      = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 49,
+       MALI_CINSTR_VG_RSW_COUNTER                                           = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 50,
+
+       /* Last counter in the VG set */
+       MALI_CINSTR_VG_MAX_COUNTER                                           = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 51,
+
+       /* Mali GP counters */
+
+       MALI_CINSTR_GP_DEPRECATED_0                                          = MALI_CINSTR_COUNTER_SOURCE_GP + 0,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_GP                                      = MALI_CINSTR_COUNTER_SOURCE_GP + 1,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER                           = MALI_CINSTR_COUNTER_SOURCE_GP + 2,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_STORER                           = MALI_CINSTR_COUNTER_SOURCE_GP + 3,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_LOADER                           = MALI_CINSTR_COUNTER_SOURCE_GP + 4,
+       MALI_CINSTR_GP_CYCLES_VERTEX_LOADER_WAITING_FOR_VERTEX_SHADER        = MALI_CINSTR_COUNTER_SOURCE_GP + 5,
+       MALI_CINSTR_GP_NUMBER_OF_WORDS_READ                                  = MALI_CINSTR_COUNTER_SOURCE_GP + 6,
+       MALI_CINSTR_GP_NUMBER_OF_WORDS_WRITTEN                               = MALI_CINSTR_COUNTER_SOURCE_GP + 7,
+       MALI_CINSTR_GP_NUMBER_OF_READ_BURSTS                                 = MALI_CINSTR_COUNTER_SOURCE_GP + 8,
+       MALI_CINSTR_GP_NUMBER_OF_WRITE_BURSTS                                = MALI_CINSTR_COUNTER_SOURCE_GP + 9,
+       MALI_CINSTR_GP_NUMBER_OF_VERTICES_PROCESSED                          = MALI_CINSTR_COUNTER_SOURCE_GP + 10,
+       MALI_CINSTR_GP_NUMBER_OF_VERTICES_FETCHED                            = MALI_CINSTR_COUNTER_SOURCE_GP + 11,
+       MALI_CINSTR_GP_NUMBER_OF_PRIMITIVES_FETCHED                          = MALI_CINSTR_COUNTER_SOURCE_GP + 12,
+       MALI_CINSTR_GP_RESERVED_13                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 13,
+       MALI_CINSTR_GP_NUMBER_OF_BACKFACE_CULLINGS_DONE                      = MALI_CINSTR_COUNTER_SOURCE_GP + 14,
+       MALI_CINSTR_GP_NUMBER_OF_COMMANDS_WRITTEN_TO_TILES                   = MALI_CINSTR_COUNTER_SOURCE_GP + 15,
+       MALI_CINSTR_GP_NUMBER_OF_MEMORY_BLOCKS_ALLOCATED                     = MALI_CINSTR_COUNTER_SOURCE_GP + 16,
+       MALI_CINSTR_GP_RESERVED_17                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 17,
+       MALI_CINSTR_GP_RESERVED_18                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 18,
+       MALI_CINSTR_GP_NUMBER_OF_VERTEX_LOADER_CACHE_MISSES                  = MALI_CINSTR_COUNTER_SOURCE_GP + 19,
+       MALI_CINSTR_GP_RESERVED_20                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 20,
+       MALI_CINSTR_GP_RESERVED_21                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 21,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER_COMMAND_PROCESSOR         = MALI_CINSTR_COUNTER_SOURCE_GP + 22,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_COMMAND_PROCESSOR                  = MALI_CINSTR_COUNTER_SOURCE_GP + 23,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_LIST_WRITER                        = MALI_CINSTR_COUNTER_SOURCE_GP + 24,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_THROUGH_THE_PREPARE_LIST_COMMANDS       = MALI_CINSTR_COUNTER_SOURCE_GP + 25,
+       MALI_CINSTR_GP_RESERVED_26                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 26,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_PRIMITIVE_ASSEMBLY                      = MALI_CINSTR_COUNTER_SOURCE_GP + 27,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_VERTEX_FETCHER                     = MALI_CINSTR_COUNTER_SOURCE_GP + 28,
+       MALI_CINSTR_GP_RESERVED_29                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 29,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_BOUNDINGBOX_AND_COMMAND_GENERATOR       = MALI_CINSTR_COUNTER_SOURCE_GP + 30,
+       MALI_CINSTR_GP_RESERVED_31                                           = MALI_CINSTR_COUNTER_SOURCE_GP + 31,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_SCISSOR_TILE_ITERATOR                   = MALI_CINSTR_COUNTER_SOURCE_GP + 32,
+       MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_TILE_ITERATOR                      = MALI_CINSTR_COUNTER_SOURCE_GP + 33,
+       MALI_CINSTR_GP_JOB_COUNT                                             = MALI_CINSTR_COUNTER_SOURCE_GP + 900,
+
+       /* Mali PP counters */
+
+       MALI_CINSTR_PP_ACTIVE_CLOCK_CYCLES_COUNT                             = MALI_CINSTR_COUNTER_SOURCE_PP + 0,
+       MALI_CINSTR_PP_TOTAL_CLOCK_CYCLES_COUNT_REMOVED                      = MALI_CINSTR_COUNTER_SOURCE_PP + 1,
+       MALI_CINSTR_PP_TOTAL_BUS_READS                                       = MALI_CINSTR_COUNTER_SOURCE_PP + 2,
+       MALI_CINSTR_PP_TOTAL_BUS_WRITES                                      = MALI_CINSTR_COUNTER_SOURCE_PP + 3,
+       MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT                         = MALI_CINSTR_COUNTER_SOURCE_PP + 4,
+       MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT                        = MALI_CINSTR_COUNTER_SOURCE_PP + 5,
+       MALI_CINSTR_PP_BUS_READ_TRANSACTIONS_COUNT                           = MALI_CINSTR_COUNTER_SOURCE_PP + 6,
+       MALI_CINSTR_PP_BUS_WRITE_TRANSACTIONS_COUNT                          = MALI_CINSTR_COUNTER_SOURCE_PP + 7,
+       MALI_CINSTR_PP_RESERVED_08                                           = MALI_CINSTR_COUNTER_SOURCE_PP + 8,
+       MALI_CINSTR_PP_TILE_WRITEBACK_WRITES                                 = MALI_CINSTR_COUNTER_SOURCE_PP + 9,
+       MALI_CINSTR_PP_STORE_UNIT_WRITES                                     = MALI_CINSTR_COUNTER_SOURCE_PP + 10,
+       MALI_CINSTR_PP_RESERVED_11                                           = MALI_CINSTR_COUNTER_SOURCE_PP + 11,
+       MALI_CINSTR_PP_PALETTE_CACHE_READS                                   = MALI_CINSTR_COUNTER_SOURCE_PP + 12,
+       MALI_CINSTR_PP_TEXTURE_CACHE_UNCOMPRESSED_READS                      = MALI_CINSTR_COUNTER_SOURCE_PP + 13,
+       MALI_CINSTR_PP_POLYGON_LIST_READS                                    = MALI_CINSTR_COUNTER_SOURCE_PP + 14,
+       MALI_CINSTR_PP_RSW_READS                                             = MALI_CINSTR_COUNTER_SOURCE_PP + 15,
+       MALI_CINSTR_PP_VERTEX_CACHE_READS                                    = MALI_CINSTR_COUNTER_SOURCE_PP + 16,
+       MALI_CINSTR_PP_UNIFORM_REMAPPING_READS                               = MALI_CINSTR_COUNTER_SOURCE_PP + 17,
+       MALI_CINSTR_PP_PROGRAM_CACHE_READS                                   = MALI_CINSTR_COUNTER_SOURCE_PP + 18,
+       MALI_CINSTR_PP_VARYING_READS                                         = MALI_CINSTR_COUNTER_SOURCE_PP + 19,
+       MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS                             = MALI_CINSTR_COUNTER_SOURCE_PP + 20,
+       MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS                   = MALI_CINSTR_COUNTER_SOURCE_PP + 21,
+       MALI_CINSTR_PP_TEXTURE_CACHE_COMPRESSED_READS                        = MALI_CINSTR_COUNTER_SOURCE_PP + 22,
+       MALI_CINSTR_PP_LOAD_UNIT_READS                                       = MALI_CINSTR_COUNTER_SOURCE_PP + 23,
+       MALI_CINSTR_PP_POLYGON_COUNT                                         = MALI_CINSTR_COUNTER_SOURCE_PP + 24,
+       MALI_CINSTR_PP_PIXEL_RECTANGLE_COUNT                                 = MALI_CINSTR_COUNTER_SOURCE_PP + 25,
+       MALI_CINSTR_PP_LINES_COUNT                                           = MALI_CINSTR_COUNTER_SOURCE_PP + 26,
+       MALI_CINSTR_PP_POINTS_COUNT                                          = MALI_CINSTR_COUNTER_SOURCE_PP + 27,
+       MALI_CINSTR_PP_STALL_CYCLES_POLYGON_LIST_READER                      = MALI_CINSTR_COUNTER_SOURCE_PP + 28,
+       MALI_CINSTR_PP_STALL_CYCLES_TRIANGLE_SETUP                           = MALI_CINSTR_COUNTER_SOURCE_PP + 29,
+       MALI_CINSTR_PP_QUAD_RASTERIZED_COUNT                                 = MALI_CINSTR_COUNTER_SOURCE_PP + 30,
+       MALI_CINSTR_PP_FRAGMENT_RASTERIZED_COUNT                             = MALI_CINSTR_COUNTER_SOURCE_PP + 31,
+       MALI_CINSTR_PP_FRAGMENT_REJECTED_FRAGMENT_KILL_COUNT                 = MALI_CINSTR_COUNTER_SOURCE_PP + 32,
+       MALI_CINSTR_PP_FRAGMENT_REJECTED_FWD_FRAGMENT_KILL_COUNT             = MALI_CINSTR_COUNTER_SOURCE_PP + 33,
+       MALI_CINSTR_PP_FRAGMENT_PASSED_ZSTENCIL_COUNT                        = MALI_CINSTR_COUNTER_SOURCE_PP + 34,
+       MALI_CINSTR_PP_PATCHES_REJECTED_EARLY_Z_STENCIL_COUNT                = MALI_CINSTR_COUNTER_SOURCE_PP + 35,
+       MALI_CINSTR_PP_PATCHES_EVALUATED                                     = MALI_CINSTR_COUNTER_SOURCE_PP + 36,
+       MALI_CINSTR_PP_INSTRUCTION_COMPLETED_COUNT                           = MALI_CINSTR_COUNTER_SOURCE_PP + 37,
+       MALI_CINSTR_PP_INSTRUCTION_FAILED_RENDEZVOUS_COUNT                   = MALI_CINSTR_COUNTER_SOURCE_PP + 38,
+       MALI_CINSTR_PP_INSTRUCTION_FAILED_VARYING_MISS_COUNT                 = MALI_CINSTR_COUNTER_SOURCE_PP + 39,
+       MALI_CINSTR_PP_INSTRUCTION_FAILED_TEXTURE_MISS_COUNT                 = MALI_CINSTR_COUNTER_SOURCE_PP + 40,
+       MALI_CINSTR_PP_INSTRUCTION_FAILED_LOAD_MISS_COUNT                    = MALI_CINSTR_COUNTER_SOURCE_PP + 41,
+       MALI_CINSTR_PP_INSTRUCTION_FAILED_TILE_READ_MISS_COUNT               = MALI_CINSTR_COUNTER_SOURCE_PP + 42,
+       MALI_CINSTR_PP_INSTRUCTION_FAILED_STORE_MISS_COUNT                   = MALI_CINSTR_COUNTER_SOURCE_PP + 43,
+       MALI_CINSTR_PP_RENDEZVOUS_BREAKAGE_COUNT                             = MALI_CINSTR_COUNTER_SOURCE_PP + 44,
+       MALI_CINSTR_PP_PIPELINE_BUBBLES_CYCLE_COUNT                          = MALI_CINSTR_COUNTER_SOURCE_PP + 45,
+       MALI_CINSTR_PP_TEXTURE_MAPPER_MULTIPASS_COUNT                        = MALI_CINSTR_COUNTER_SOURCE_PP + 46,
+       MALI_CINSTR_PP_TEXTURE_MAPPER_CYCLE_COUNT                            = MALI_CINSTR_COUNTER_SOURCE_PP + 47,
+       MALI_CINSTR_PP_VERTEX_CACHE_HIT_COUNT                                = MALI_CINSTR_COUNTER_SOURCE_PP + 48,
+       MALI_CINSTR_PP_VERTEX_CACHE_MISS_COUNT                               = MALI_CINSTR_COUNTER_SOURCE_PP + 49,
+       MALI_CINSTR_PP_VARYING_CACHE_HIT_COUNT                               = MALI_CINSTR_COUNTER_SOURCE_PP + 50,
+       MALI_CINSTR_PP_VARYING_CACHE_MISS_COUNT                              = MALI_CINSTR_COUNTER_SOURCE_PP + 51,
+       MALI_CINSTR_PP_VARYING_CACHE_CONFLICT_MISS_COUNT                     = MALI_CINSTR_COUNTER_SOURCE_PP + 52,
+       MALI_CINSTR_PP_TEXTURE_CACHE_HIT_COUNT                               = MALI_CINSTR_COUNTER_SOURCE_PP + 53,
+       MALI_CINSTR_PP_TEXTURE_CACHE_MISS_COUNT                              = MALI_CINSTR_COUNTER_SOURCE_PP + 54,
+       MALI_CINSTR_PP_TEXTURE_CACHE_CONFLICT_MISS_COUNT                     = MALI_CINSTR_COUNTER_SOURCE_PP + 55,
+       MALI_CINSTR_PP_PALETTE_CACHE_HIT_COUNT                               = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 200 only */
+       MALI_CINSTR_PP_PALETTE_CACHE_MISS_COUNT                              = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 200 only */
+       MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_HIT_COUNT                    = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 400 class only */
+       MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_MISS_COUNT                   = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 400 class only */
+       MALI_CINSTR_PP_LOAD_STORE_CACHE_HIT_COUNT                            = MALI_CINSTR_COUNTER_SOURCE_PP + 58,
+       MALI_CINSTR_PP_LOAD_STORE_CACHE_MISS_COUNT                           = MALI_CINSTR_COUNTER_SOURCE_PP + 59,
+       MALI_CINSTR_PP_PROGRAM_CACHE_HIT_COUNT                               = MALI_CINSTR_COUNTER_SOURCE_PP + 60,
+       MALI_CINSTR_PP_PROGRAM_CACHE_MISS_COUNT                              = MALI_CINSTR_COUNTER_SOURCE_PP + 61,
+       MALI_CINSTR_PP_JOB_COUNT                                             = MALI_CINSTR_COUNTER_SOURCE_PP + 900,
+} cinstr_counters_m200_t;
+
+#endif /*_MALI_UTGARD_COUNTERS_H_*/
diff --git a/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_ioctl.h b/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_ioctl.h
new file mode 100755 (executable)
index 0000000..b73e248
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_UTGARD_IOCTL_H__
+#define __MALI_UTGARD_IOCTL_H__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>       /* file system operations */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file mali_kernel_ioctl.h
+ * Interface to the Linux device driver.
+ * This file describes the interface needed to use the Linux device driver.
+ * Its interface is designed to used by the HAL implementation through a thin arch layer.
+ */
+
+/**
+ * ioctl commands
+ */
+
+#define MALI_IOC_BASE           0x82
+#define MALI_IOC_CORE_BASE      (_MALI_UK_CORE_SUBSYSTEM      + MALI_IOC_BASE)
+#define MALI_IOC_MEMORY_BASE    (_MALI_UK_MEMORY_SUBSYSTEM    + MALI_IOC_BASE)
+#define MALI_IOC_PP_BASE        (_MALI_UK_PP_SUBSYSTEM        + MALI_IOC_BASE)
+#define MALI_IOC_GP_BASE        (_MALI_UK_GP_SUBSYSTEM        + MALI_IOC_BASE)
+#define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE)
+#define MALI_IOC_VSYNC_BASE     (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE)
+
+#define MALI_IOC_WAIT_FOR_NOTIFICATION      _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_WAIT_FOR_NOTIFICATION, _mali_uk_wait_for_notification_s *)
+#define MALI_IOC_GET_API_VERSION            _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_API_VERSION, _mali_uk_get_api_version_s *)
+#define MALI_IOC_GET_MALI_VERSION_IN_RK30   _IOWR(MALI_IOC_CORE_BASE,_MALI_UK_GET_MALI_VERSION_IN_RK30,_mali_uk_get_mali_version_in_rk30_s *)
+#define MALI_IOC_POST_NOTIFICATION          _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *)
+#define MALI_IOC_GET_USER_SETTING           _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *)
+#define MALI_IOC_GET_USER_SETTINGS          _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *)
+#define MALI_IOC_REQUEST_HIGH_PRIORITY      _IOW (MALI_IOC_CORE_BASE, _MALI_UK_REQUEST_HIGH_PRIORITY, _mali_uk_request_high_priority_s *)
+#define MALI_IOC_TIMELINE_GET_LATEST_POINT  _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_TIMELINE_GET_LATEST_POINT, _mali_uk_timeline_get_latest_point_s *)
+#define MALI_IOC_TIMELINE_WAIT              _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_TIMELINE_WAIT, _mali_uk_timeline_wait_s *)
+#define MALI_IOC_TIMELINE_CREATE_SYNC_FENCE _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_TIMELINE_CREATE_SYNC_FENCE, _mali_uk_timeline_create_sync_fence_s *)
+#define MALI_IOC_SOFT_JOB_START             _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_SOFT_JOB_START, _mali_uk_soft_job_start_s *)
+#define MALI_IOC_SOFT_JOB_SIGNAL            _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_SOFT_JOB_SIGNAL, _mali_uk_soft_job_signal_s *)
+
+#define MALI_IOC_MEM_MAP_EXT                _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MAP_EXT_MEM, _mali_uk_map_external_mem_s *)
+#define MALI_IOC_MEM_UNMAP_EXT              _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_UNMAP_EXT_MEM, _mali_uk_unmap_external_mem_s *)
+#define MALI_IOC_MEM_ATTACH_DMA_BUF         _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_DMA_BUF, _mali_uk_attach_dma_buf_s *)
+#define MALI_IOC_MEM_RELEASE_DMA_BUF        _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_DMA_BUF, _mali_uk_release_dma_buf_s *)
+#define MALI_IOC_MEM_DMA_BUF_GET_SIZE       _IOR(MALI_IOC_MEMORY_BASE, _MALI_UK_DMA_BUF_GET_SIZE, _mali_uk_dma_buf_get_size_s *)
+#define MALI_IOC_MEM_ATTACH_UMP             _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_ATTACH_UMP_MEM, _mali_uk_attach_ump_mem_s *)
+#define MALI_IOC_MEM_RELEASE_UMP            _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_UMP_MEM, _mali_uk_release_ump_mem_s *)
+#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s *)
+#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE    _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s *)
+#define MALI_IOC_MEM_WRITE_SAFE             _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MEM_WRITE_SAFE, _mali_uk_mem_write_safe_s *)
+
+#define MALI_IOC_PP_START_JOB               _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s *)
+#define MALI_IOC_PP_AND_GP_START_JOB        _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_AND_GP_START_JOB, _mali_uk_pp_and_gp_start_job_s *)
+#define MALI_IOC_PP_NUMBER_OF_CORES_GET            _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_NUMBER_OF_CORES, _mali_uk_get_pp_number_of_cores_s *)
+#define MALI_IOC_PP_CORE_VERSION_GET       _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_CORE_VERSION, _mali_uk_get_pp_core_version_s * )
+#define MALI_IOC_PP_DISABLE_WB              _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_DISABLE_WB, _mali_uk_pp_disable_wb_s * )
+
+#define MALI_IOC_GP2_START_JOB              _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_START_JOB, _mali_uk_gp_start_job_s *)
+#define MALI_IOC_GP2_NUMBER_OF_CORES_GET    _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_NUMBER_OF_CORES, _mali_uk_get_gp_number_of_cores_s *)
+#define MALI_IOC_GP2_CORE_VERSION_GET      _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_CORE_VERSION, _mali_uk_get_gp_core_version_s *)
+#define MALI_IOC_GP2_SUSPEND_RESPONSE      _IOW (MALI_IOC_GP_BASE, _MALI_UK_GP_SUSPEND_RESPONSE,_mali_uk_gp_suspend_response_s *)
+
+#define MALI_IOC_PROFILING_START            _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_START, _mali_uk_profiling_start_s *)
+#define MALI_IOC_PROFILING_ADD_EVENT        _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_ADD_EVENT, _mali_uk_profiling_add_event_s*)
+#define MALI_IOC_PROFILING_STOP             _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *)
+#define MALI_IOC_PROFILING_GET_EVENT        _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *)
+#define MALI_IOC_PROFILING_CLEAR            _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *)
+#define MALI_IOC_PROFILING_GET_CONFIG       _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_CONFIG, _mali_uk_get_user_settings_s *)
+#define MALI_IOC_PROFILING_REPORT_SW_COUNTERS  _IOW (MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_REPORT_SW_COUNTERS, _mali_uk_sw_counters_report_s *)
+
+#define MALI_IOC_VSYNC_EVENT_REPORT         _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *)
+
+/* Deprecated ioctls */
+#define MALI_IOC_MEM_GET_BIG_BLOCK          _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *)
+#define MALI_IOC_MEM_FREE_BIG_BLOCK         _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *)
+#define MALI_IOC_MEM_INIT                   _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, void *)
+#define MALI_IOC_MEM_TERM                   _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_TERM_MEM, void *)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UTGARD_IOCTL_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_profiling_events.h
new file mode 100755 (executable)
index 0000000..0bc62d4
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef _MALI_UTGARD_PROFILING_EVENTS_H_
+#define _MALI_UTGARD_PROFILING_EVENTS_H_
+
+/*
+ * The event ID is a 32 bit value consisting of different fields
+ * reserved, 4 bits, for future use
+ * event type, 4 bits, cinstr_profiling_event_type_t
+ * event channel, 8 bits, the source of the event.
+ * event data, 16 bit field, data depending on event type
+ */
+
+/**
+ * Specifies what kind of event this is
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_TYPE_SINGLE  = 0 << 24,
+       MALI_PROFILING_EVENT_TYPE_START   = 1 << 24,
+       MALI_PROFILING_EVENT_TYPE_STOP    = 2 << 24,
+       MALI_PROFILING_EVENT_TYPE_SUSPEND = 3 << 24,
+       MALI_PROFILING_EVENT_TYPE_RESUME  = 4 << 24,
+} cinstr_profiling_event_type_t;
+
+
+/**
+ * Secifies the channel/source of the event
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_CHANNEL_SOFTWARE =  0 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_GP0      =  1 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP0      =  5 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP1      =  6 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP2      =  7 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP3      =  8 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP4      =  9 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP5      = 10 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP6      = 11 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_PP7      = 12 << 16,
+       MALI_PROFILING_EVENT_CHANNEL_GPU      = 21 << 16,
+} cinstr_profiling_event_channel_t;
+
+
+#define MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(num) (((MALI_PROFILING_EVENT_CHANNEL_GP0 >> 16) + (num)) << 16)
+#define MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(num) (((MALI_PROFILING_EVENT_CHANNEL_PP0 >> 16) + (num)) << 16)
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from software channel
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_NONE                  = 0,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_NEW_FRAME         = 1,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_FLUSH                 = 2,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SWAP_BUFFERS      = 3,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT              = 4,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE            = 5,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE            = 6,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_READBACK              = 7,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_WRITEBACK             = 8,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC        = 10,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC        = 11,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_DISCARD_ATTACHMENTS   = 13,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK          = 53,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK              = 54,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK            = 55,
+       MALI_PROFILING_EVENT_REASON_SINGLE_LOCK_CONTENDED           = 56,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_MALI_FENCE_DUP    = 57,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SET_PP_JOB_FENCE  = 58,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_WAIT_SYNC         = 59,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_CREATE_FENCE_SYNC = 60,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_CREATE_NATIVE_FENCE_SYNC = 61,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_FENCE_FLUSH       = 62,
+       MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_FLUSH_SERVER_WAITS= 63,
+} cinstr_profiling_event_reason_single_sw_t;
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel
+ * to inform whether the core is physical or virtual
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL  = 0,
+       MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL   = 1,
+} cinstr_profiling_event_reason_start_stop_hw_t;
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel
+ */
+typedef enum {
+       /*MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE            = 0,*/
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_MALI            = 1,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_CALLBACK_THREAD = 2,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_WORKER_THREAD   = 3,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF     = 4,
+       MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF      = 5,
+} cinstr_profiling_event_reason_start_stop_sw_t;
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SUSPEND/RESUME is used from software channel
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE                     =  0, /* used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL            =  1, /* NOT used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC                    = 26, /* used in some build configurations */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT           = 27, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC           = 28, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP   = 29, /* used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE          = 30, /* used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL       = 31, /* used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS     = 32, /* used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE  = 33, /* NOT used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_QUEUE_BUFFER         = 34, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_DEQUEUE_BUFFER       = 35, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_UMP_LOCK                 = 36, /* Not currently used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_GLOBAL_LOCK          = 37, /* Not currently used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_SWAP                 = 38, /* Not currently used */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_MALI_EGL_IMAGE_SYNC_WAIT = 39, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GP_JOB_HANDLING          = 40, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PP_JOB_HANDLING          = 41, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_MALI_FENCE_MERGE     = 42, /* USED */
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_MALI_FENCE_DUP       = 43,
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_FLUSH_SERVER_WAITS   = 44,
+       MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SYNC            = 45, /* USED */
+} cinstr_profiling_event_reason_suspend_resume_sw_t;
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from a HW channel (GPx+PPx)
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_REASON_SINGLE_HW_NONE          = 0,
+       MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT     = 1,
+       MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH         = 2,
+} cinstr_profiling_event_reason_single_hw_t;
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_NONE              = 0,
+       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE  = 1,
+       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS      = 2,
+       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS      = 3,
+       MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS      = 4,
+} cinstr_profiling_event_reason_single_gpu_t;
+
+/**
+ * These values are applicable for the 3rd data parameter when
+ * the type MALI_PROFILING_EVENT_TYPE_START is used from the software channel
+ * with the MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF reason.
+ */
+typedef enum {
+       MALI_PROFILING_EVENT_DATA_CORE_GP0             =  1,
+       MALI_PROFILING_EVENT_DATA_CORE_PP0             =  5,
+       MALI_PROFILING_EVENT_DATA_CORE_PP1             =  6,
+       MALI_PROFILING_EVENT_DATA_CORE_PP2             =  7,
+       MALI_PROFILING_EVENT_DATA_CORE_PP3             =  8,
+       MALI_PROFILING_EVENT_DATA_CORE_PP4             =  9,
+       MALI_PROFILING_EVENT_DATA_CORE_PP5             = 10,
+       MALI_PROFILING_EVENT_DATA_CORE_PP6             = 11,
+       MALI_PROFILING_EVENT_DATA_CORE_PP7             = 12,
+} cinstr_profiling_event_data_core_t;
+
+#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(num) (MALI_PROFILING_EVENT_DATA_CORE_GP0 + (num))
+#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(num) (MALI_PROFILING_EVENT_DATA_CORE_PP0 + (num))
+
+
+#endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/
diff --git a/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_profiling_gator_api.h b/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_profiling_gator_api.h
new file mode 100755 (executable)
index 0000000..918a3f3
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_UTGARD_PROFILING_GATOR_API_H__
+#define __MALI_UTGARD_PROFILING_GATOR_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MALI_PROFILING_API_VERSION 4
+
+#define MAX_NUM_L2_CACHE_CORES 3
+#define MAX_NUM_FP_CORES 8
+#define MAX_NUM_VP_CORES 1
+
+/** The list of events supported by the Mali DDK. */
+typedef enum {
+       /* Vertex processor activity */
+       ACTIVITY_VP_0 = 0,
+
+       /* Fragment processor activity */
+       ACTIVITY_FP_0,
+       ACTIVITY_FP_1,
+       ACTIVITY_FP_2,
+       ACTIVITY_FP_3,
+       ACTIVITY_FP_4,
+       ACTIVITY_FP_5,
+       ACTIVITY_FP_6,
+       ACTIVITY_FP_7,
+
+       /* L2 cache counters */
+       COUNTER_L2_0_C0,
+       COUNTER_L2_0_C1,
+       COUNTER_L2_1_C0,
+       COUNTER_L2_1_C1,
+       COUNTER_L2_2_C0,
+       COUNTER_L2_2_C1,
+
+       /* Vertex processor counters */
+       COUNTER_VP_0_C0,
+       COUNTER_VP_0_C1,
+
+       /* Fragment processor counters */
+       COUNTER_FP_0_C0,
+       COUNTER_FP_0_C1,
+       COUNTER_FP_1_C0,
+       COUNTER_FP_1_C1,
+       COUNTER_FP_2_C0,
+       COUNTER_FP_2_C1,
+       COUNTER_FP_3_C0,
+       COUNTER_FP_3_C1,
+       COUNTER_FP_4_C0,
+       COUNTER_FP_4_C1,
+       COUNTER_FP_5_C0,
+       COUNTER_FP_5_C1,
+       COUNTER_FP_6_C0,
+       COUNTER_FP_6_C1,
+       COUNTER_FP_7_C0,
+       COUNTER_FP_7_C1,
+
+       /*
+        * If more hardware counters are added, the _mali_osk_hw_counter_table
+        * below should also be updated.
+        */
+
+       /* EGL software counters */
+       COUNTER_EGL_BLIT_TIME,
+
+       /* GLES software counters */
+       COUNTER_GLES_DRAW_ELEMENTS_CALLS,
+       COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES,
+       COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED,
+       COUNTER_GLES_DRAW_ARRAYS_CALLS,
+       COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED,
+       COUNTER_GLES_DRAW_POINTS,
+       COUNTER_GLES_DRAW_LINES,
+       COUNTER_GLES_DRAW_LINE_LOOP,
+       COUNTER_GLES_DRAW_LINE_STRIP,
+       COUNTER_GLES_DRAW_TRIANGLES,
+       COUNTER_GLES_DRAW_TRIANGLE_STRIP,
+       COUNTER_GLES_DRAW_TRIANGLE_FAN,
+       COUNTER_GLES_NON_VBO_DATA_COPY_TIME,
+       COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI,
+       COUNTER_GLES_UPLOAD_TEXTURE_TIME,
+       COUNTER_GLES_UPLOAD_VBO_TIME,
+       COUNTER_GLES_NUM_FLUSHES,
+       COUNTER_GLES_NUM_VSHADERS_GENERATED,
+       COUNTER_GLES_NUM_FSHADERS_GENERATED,
+       COUNTER_GLES_VSHADER_GEN_TIME,
+       COUNTER_GLES_FSHADER_GEN_TIME,
+       COUNTER_GLES_INPUT_TRIANGLES,
+       COUNTER_GLES_VXCACHE_HIT,
+       COUNTER_GLES_VXCACHE_MISS,
+       COUNTER_GLES_VXCACHE_COLLISION,
+       COUNTER_GLES_CULLED_TRIANGLES,
+       COUNTER_GLES_CULLED_LINES,
+       COUNTER_GLES_BACKFACE_TRIANGLES,
+       COUNTER_GLES_GBCLIP_TRIANGLES,
+       COUNTER_GLES_GBCLIP_LINES,
+       COUNTER_GLES_TRIANGLES_DRAWN,
+       COUNTER_GLES_DRAWCALL_TIME,
+       COUNTER_GLES_TRIANGLES_COUNT,
+       COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT,
+       COUNTER_GLES_STRIP_TRIANGLES_COUNT,
+       COUNTER_GLES_FAN_TRIANGLES_COUNT,
+       COUNTER_GLES_LINES_COUNT,
+       COUNTER_GLES_INDEPENDENT_LINES_COUNT,
+       COUNTER_GLES_STRIP_LINES_COUNT,
+       COUNTER_GLES_LOOP_LINES_COUNT,
+
+       /* Framebuffer capture pseudo-counter */
+       COUNTER_FILMSTRIP,
+
+       NUMBER_OF_EVENTS
+} _mali_osk_counter_id;
+
+#define FIRST_ACTIVITY_EVENT    ACTIVITY_VP_0
+#define LAST_ACTIVITY_EVENT     ACTIVITY_FP_7
+
+#define FIRST_HW_COUNTER        COUNTER_L2_0_C0
+#define LAST_HW_COUNTER         COUNTER_FP_7_C1
+
+#define FIRST_SW_COUNTER        COUNTER_EGL_BLIT_TIME
+#define LAST_SW_COUNTER         COUNTER_GLES_LOOP_LINES_COUNT
+
+#define FIRST_SPECIAL_COUNTER   COUNTER_FILMSTRIP
+#define LAST_SPECIAL_COUNTER    COUNTER_FILMSTRIP
+
+/**
+ * Structure to pass performance counter data of a Mali core
+ */
+typedef struct _mali_profiling_core_counters {
+       u32 source0;
+       u32 value0;
+       u32 source1;
+       u32 value1;
+} _mali_profiling_core_counters;
+
+/**
+ * Structure to pass performance counter data of Mali L2 cache cores
+ */
+typedef struct _mali_profiling_l2_counter_values {
+       struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES];
+} _mali_profiling_l2_counter_values;
+
+/**
+ * Structure to pass data defining Mali instance in use:
+ *
+ * mali_product_id - Mali product id
+ * mali_version_major - Mali version major number
+ * mali_version_minor - Mali version minor number
+ * num_of_l2_cores - number of L2 cache cores
+ * num_of_fp_cores - number of fragment processor cores
+ * num_of_vp_cores - number of vertex processor cores
+ */
+typedef struct _mali_profiling_mali_version {
+       u32 mali_product_id;
+       u32 mali_version_major;
+       u32 mali_version_minor;
+       u32 num_of_l2_cores;
+       u32 num_of_fp_cores;
+       u32 num_of_vp_cores;
+} _mali_profiling_mali_version;
+
+/*
+ * List of possible actions to be controlled by Streamline.
+ * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting.
+ * We cannot use the enums in mali_uk_types.h because they are unknown inside gator.
+ */
+#define FBDUMP_CONTROL_ENABLE (1)
+#define FBDUMP_CONTROL_RATE (2)
+#define SW_COUNTER_ENABLE (3)
+#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
+
+void _mali_profiling_control(u32 action, u32 value);
+
+u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values);
+
+int _mali_profiling_set_event(u32 counter_id, s32 event_id);
+
+u32 _mali_profiling_get_api_version(void);
+
+void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UTGARD_PROFILING_GATOR_API_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_uk_types.h b/drivers/gpu/arm/mali400/mali/include/linux/mali/mali_utgard_uk_types.h
new file mode 100755 (executable)
index 0000000..e374c79
--- /dev/null
@@ -0,0 +1,1144 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_uk_types.h
+ * Defines the types and constants used in the user-kernel interface
+ */
+
+#ifndef __MALI_UTGARD_UK_TYPES_H__
+#define __MALI_UTGARD_UK_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Iteration functions depend on these values being consecutive. */
+#define MALI_UK_TIMELINE_GP   0
+#define MALI_UK_TIMELINE_PP   1
+#define MALI_UK_TIMELINE_SOFT 2
+#define MALI_UK_TIMELINE_MAX  3
+
+typedef struct {
+       u32 points[MALI_UK_TIMELINE_MAX];
+       s32 sync_fd;
+} _mali_uk_fence_t;
+
+/**
+ * @addtogroup uddapi Unified Device Driver (UDD) APIs
+ *
+ * @{
+ */
+
+/**
+ * @addtogroup u_k_api UDD User/Kernel Interface (U/K) APIs
+ *
+ * @{
+ */
+
+/** @defgroup _mali_uk_core U/K Core
+ * @{ */
+
+/** Definition of subsystem numbers, to assist in creating a unique identifier
+ * for each U/K call.
+ *
+ * @see _mali_uk_functions */
+typedef enum {
+       _MALI_UK_CORE_SUBSYSTEM,      /**< Core Group of U/K calls */
+       _MALI_UK_MEMORY_SUBSYSTEM,    /**< Memory Group of U/K calls */
+       _MALI_UK_PP_SUBSYSTEM,        /**< Fragment Processor Group of U/K calls */
+       _MALI_UK_GP_SUBSYSTEM,        /**< Vertex Processor Group of U/K calls */
+       _MALI_UK_PROFILING_SUBSYSTEM, /**< Profiling Group of U/K calls */
+       _MALI_UK_PMM_SUBSYSTEM,       /**< Power Management Module Group of U/K calls */
+       _MALI_UK_VSYNC_SUBSYSTEM,     /**< VSYNC Group of U/K calls */
+} _mali_uk_subsystem_t;
+
+/** Within a function group each function has its unique sequence number
+ * to assist in creating a unique identifier for each U/K call.
+ *
+ * An ordered pair of numbers selected from
+ * ( \ref _mali_uk_subsystem_t,\ref  _mali_uk_functions) will uniquely identify the
+ * U/K call across all groups of functions, and all functions. */
+typedef enum {
+       /** Core functions */
+
+       _MALI_UK_OPEN                    = 0, /**< _mali_ukk_open() */
+       _MALI_UK_CLOSE,                       /**< _mali_ukk_close() */
+       _MALI_UK_WAIT_FOR_NOTIFICATION,       /**< _mali_ukk_wait_for_notification() */
+       _MALI_UK_GET_API_VERSION,             /**< _mali_ukk_get_api_version() */
+       _MALI_UK_POST_NOTIFICATION,           /**< _mali_ukk_post_notification() */
+    _MALI_UK_GET_MALI_VERSION_IN_RK30,
+       _MALI_UK_GET_USER_SETTING,            /**< _mali_ukk_get_user_setting() *//**< [out] */
+       _MALI_UK_GET_USER_SETTINGS,           /**< _mali_ukk_get_user_settings() *//**< [out] */
+       _MALI_UK_REQUEST_HIGH_PRIORITY,       /**< _mali_ukk_request_high_priority() */
+       _MALI_UK_TIMELINE_GET_LATEST_POINT,   /**< _mali_ukk_timeline_get_latest_point() */
+       _MALI_UK_TIMELINE_WAIT,               /**< _mali_ukk_timeline_wait() */
+       _MALI_UK_TIMELINE_CREATE_SYNC_FENCE,  /**< _mali_ukk_timeline_create_sync_fence() */
+       _MALI_UK_SOFT_JOB_START,              /**< _mali_ukk_soft_job_start() */
+       _MALI_UK_SOFT_JOB_SIGNAL,             /**< _mali_ukk_soft_job_signal() */
+
+       /** Memory functions */
+
+       _MALI_UK_INIT_MEM                = 0,    /**< _mali_ukk_init_mem() */
+       _MALI_UK_TERM_MEM,                       /**< _mali_ukk_term_mem() */
+       _MALI_UK_GET_BIG_BLOCK,                  /**< _mali_ukk_get_big_block() */
+       _MALI_UK_FREE_BIG_BLOCK,                 /**< _mali_ukk_free_big_block() */
+       _MALI_UK_MAP_MEM,                        /**< _mali_ukk_mem_mmap() */
+       _MALI_UK_UNMAP_MEM,                      /**< _mali_ukk_mem_munmap() */
+       _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, /**< _mali_ukk_mem_get_mmu_page_table_dump_size() */
+       _MALI_UK_DUMP_MMU_PAGE_TABLE,            /**< _mali_ukk_mem_dump_mmu_page_table() */
+       _MALI_UK_ATTACH_DMA_BUF,                 /**< _mali_ukk_attach_dma_buf() */
+       _MALI_UK_RELEASE_DMA_BUF,                /**< _mali_ukk_release_dma_buf() */
+       _MALI_UK_DMA_BUF_GET_SIZE,               /**< _mali_ukk_dma_buf_get_size() */
+       _MALI_UK_ATTACH_UMP_MEM,                 /**< _mali_ukk_attach_ump_mem() */
+       _MALI_UK_RELEASE_UMP_MEM,                /**< _mali_ukk_release_ump_mem() */
+       _MALI_UK_MAP_EXT_MEM,                    /**< _mali_uku_map_external_mem() */
+       _MALI_UK_UNMAP_EXT_MEM,                  /**< _mali_uku_unmap_external_mem() */
+       _MALI_UK_VA_TO_MALI_PA,                  /**< _mali_uku_va_to_mali_pa() */
+       _MALI_UK_MEM_WRITE_SAFE,                 /**< _mali_uku_mem_write_safe() */
+
+       /** Common functions for each core */
+
+       _MALI_UK_START_JOB           = 0,     /**< Start a Fragment/Vertex Processor Job on a core */
+       _MALI_UK_GET_NUMBER_OF_CORES,         /**< Get the number of Fragment/Vertex Processor cores */
+       _MALI_UK_GET_CORE_VERSION,            /**< Get the Fragment/Vertex Processor version compatible with all cores */
+
+       /** Fragment Processor Functions  */
+
+       _MALI_UK_PP_START_JOB            = _MALI_UK_START_JOB,            /**< _mali_ukk_pp_start_job() */
+       _MALI_UK_GET_PP_NUMBER_OF_CORES  = _MALI_UK_GET_NUMBER_OF_CORES,  /**< _mali_ukk_get_pp_number_of_cores() */
+       _MALI_UK_GET_PP_CORE_VERSION     = _MALI_UK_GET_CORE_VERSION,     /**< _mali_ukk_get_pp_core_version() */
+       _MALI_UK_PP_DISABLE_WB,                                           /**< _mali_ukk_pp_job_disable_wb() */
+       _MALI_UK_PP_AND_GP_START_JOB,                                     /**< _mali_ukk_pp_and_gp_start_job() */
+
+       /** Vertex Processor Functions  */
+
+       _MALI_UK_GP_START_JOB            = _MALI_UK_START_JOB,            /**< _mali_ukk_gp_start_job() */
+       _MALI_UK_GET_GP_NUMBER_OF_CORES  = _MALI_UK_GET_NUMBER_OF_CORES,  /**< _mali_ukk_get_gp_number_of_cores() */
+       _MALI_UK_GET_GP_CORE_VERSION     = _MALI_UK_GET_CORE_VERSION,     /**< _mali_ukk_get_gp_core_version() */
+       _MALI_UK_GP_SUSPEND_RESPONSE,                                     /**< _mali_ukk_gp_suspend_response() */
+
+       /** Profiling functions */
+
+       _MALI_UK_PROFILING_START         = 0, /**< __mali_uku_profiling_start() */
+       _MALI_UK_PROFILING_ADD_EVENT,         /**< __mali_uku_profiling_add_event() */
+       _MALI_UK_PROFILING_STOP,              /**< __mali_uku_profiling_stop() */
+       _MALI_UK_PROFILING_GET_EVENT,         /**< __mali_uku_profiling_get_event() */
+       _MALI_UK_PROFILING_CLEAR,             /**< __mali_uku_profiling_clear() */
+       _MALI_UK_PROFILING_GET_CONFIG,        /**< __mali_uku_profiling_get_config() */
+       _MALI_UK_PROFILING_REPORT_SW_COUNTERS,/**< __mali_uku_profiling_report_sw_counters() */
+
+       /** VSYNC reporting fuctions */
+       _MALI_UK_VSYNC_EVENT_REPORT      = 0, /**< _mali_ukk_vsync_event_report() */
+
+} _mali_uk_functions;
+
+/** @brief Get the size necessary for system info
+ *
+ * @see _mali_ukk_get_system_info_size()
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 size;                       /**< [out] size of buffer necessary to hold system information data, in bytes */
+} _mali_uk_get_system_info_size_s;
+
+
+/** @defgroup _mali_uk_getsysteminfo U/K Get System Info
+ * @{ */
+
+/**
+ * Type definition for the core version number.
+ * Used when returning the version number read from a core
+ *
+ * Its format is that of the 32-bit Version register for a particular core.
+ * Refer to the "Mali200 and MaliGP2 3D Graphics Processor Technical Reference
+ * Manual", ARM DDI 0415C, for more information.
+ */
+typedef u32 _mali_core_version;
+
+/**
+ * Enum values for the different modes the driver can be put in.
+ * Normal is the default mode. The driver then uses a job queue and takes job objects from the clients.
+ * Job completion is reported using the _mali_ukk_wait_for_notification call.
+ * The driver blocks this io command until a job has completed or failed or a timeout occurs.
+ *
+ * The 'raw' mode is reserved for future expansion.
+ */
+typedef enum _mali_driver_mode {
+       _MALI_DRIVER_MODE_RAW = 1,    /**< Reserved for future expansion */
+       _MALI_DRIVER_MODE_NORMAL = 2  /**< Normal mode of operation */
+} _mali_driver_mode;
+
+/** @brief List of possible cores
+ *
+ * add new entries to the end of this enum */
+typedef enum _mali_core_type {
+       _MALI_GP2 = 2,                /**< MaliGP2 Programmable Vertex Processor */
+       _MALI_200 = 5,                /**< Mali200 Programmable Fragment Processor */
+       _MALI_400_GP = 6,             /**< Mali400 Programmable Vertex Processor */
+       _MALI_400_PP = 7,             /**< Mali400 Programmable Fragment Processor */
+       /* insert new core here, do NOT alter the existing values */
+} _mali_core_type;
+
+
+/** @brief Capabilities of Memory Banks
+ *
+ * These may be used to restrict memory banks for certain uses. They may be
+ * used when access is not possible (e.g. Bus does not support access to it)
+ * or when access is possible but not desired (e.g. Access is slow).
+ *
+ * In the case of 'possible but not desired', there is no way of specifying
+ * the flags as an optimization hint, so that the memory could be used as a
+ * last resort.
+ *
+ * @see _mali_mem_info
+ */
+typedef enum _mali_bus_usage {
+
+       _MALI_PP_READABLE   = (1<<0),  /** Readable by the Fragment Processor */
+       _MALI_PP_WRITEABLE  = (1<<1),  /** Writeable by the Fragment Processor */
+       _MALI_GP_READABLE   = (1<<2),  /** Readable by the Vertex Processor */
+       _MALI_GP_WRITEABLE  = (1<<3),  /** Writeable by the Vertex Processor */
+       _MALI_CPU_READABLE  = (1<<4),  /** Readable by the CPU */
+       _MALI_CPU_WRITEABLE = (1<<5),  /** Writeable by the CPU */
+       _MALI_GP_L2_ALLOC   = (1<<6),  /** GP allocate mali L2 cache lines*/
+       _MALI_MMU_READABLE  = _MALI_PP_READABLE | _MALI_GP_READABLE,   /** Readable by the MMU (including all cores behind it) */
+       _MALI_MMU_WRITEABLE = _MALI_PP_WRITEABLE | _MALI_GP_WRITEABLE, /** Writeable by the MMU (including all cores behind it) */
+} _mali_bus_usage;
+
+typedef enum mali_memory_cache_settings {
+       MALI_CACHE_STANDARD                     = 0,
+       MALI_CACHE_GP_READ_ALLOCATE     = 1,
+} mali_memory_cache_settings ;
+
+
+/** @brief Information about the Mali Memory system
+ *
+ * Information is stored in a linked list, which is stored entirely in the
+ * buffer pointed to by the system_info member of the
+ * _mali_uk_get_system_info_s arguments provided to _mali_ukk_get_system_info()
+ *
+ * Each element of the linked list describes a single Mali Memory bank.
+ * Each allocation can only come from one bank, and will not cross multiple
+ * banks.
+ *
+ * On Mali-MMU systems, there is only one bank, which describes the maximum
+ * possible address range that could be allocated (which may be much less than
+ * the available physical memory)
+ *
+ * The flags member describes the capabilities of the memory. It is an error
+ * to attempt to build a job for a particular core (PP or GP) when the memory
+ * regions used do not have the capabilities for supporting that core. This
+ * would result in a job abort from the Device Driver.
+ *
+ * For example, it is correct to build a PP job where read-only data structures
+ * are taken from a memory with _MALI_PP_READABLE set and
+ * _MALI_PP_WRITEABLE clear, and a framebuffer with  _MALI_PP_WRITEABLE set and
+ * _MALI_PP_READABLE clear. However, it would be incorrect to use a framebuffer
+ * where _MALI_PP_WRITEABLE is clear.
+ */
+typedef struct _mali_mem_info {
+       u32 size;                     /**< Size of the memory bank in bytes */
+       _mali_bus_usage flags;        /**< Capabilitiy flags of the memory */
+       u32 maximum_order_supported;  /**< log2 supported size */
+       u32 identifier;               /* mali_memory_cache_settings cache_settings; */
+       struct _mali_mem_info * next; /**< Next List Link */
+} _mali_mem_info;
+
+/** @} */ /* end group _mali_uk_core */
+
+
+/** @defgroup _mali_uk_gp U/K Vertex Processor
+ * @{ */
+
+/** @defgroup _mali_uk_gp_suspend_response_s Vertex Processor Suspend Response
+ * @{ */
+
+/** @brief Arguments for _mali_ukk_gp_suspend_response()
+ *
+ * When _mali_wait_for_notification() receives notification that a
+ * Vertex Processor job was suspended, you need to send a response to indicate
+ * what needs to happen with this job. You can either abort or resume the job.
+ *
+ * - set @c code to indicate response code. This is either @c _MALIGP_JOB_ABORT or
+ * @c _MALIGP_JOB_RESUME_WITH_NEW_HEAP to indicate you will provide a new heap
+ * for the job that will resolve the out of memory condition for the job.
+ * - copy the @c cookie value from the @c _mali_uk_gp_job_suspended_s notification;
+ * this is an identifier for the suspended job
+ * - set @c arguments[0] and @c arguments[1] to zero if you abort the job. If
+ * you resume it, @c argument[0] should specify the Mali start address for the new
+ * heap and @c argument[1] the Mali end address of the heap.
+ * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
+ *
+ */
+typedef enum _maligp_job_suspended_response_code {
+       _MALIGP_JOB_ABORT,                  /**< Abort the Vertex Processor job */
+       _MALIGP_JOB_RESUME_WITH_NEW_HEAP    /**< Resume the Vertex Processor job with a new heap */
+} _maligp_job_suspended_response_code;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 cookie;                     /**< [in] cookie from the _mali_uk_gp_job_suspended_s notification */
+       _maligp_job_suspended_response_code code; /**< [in] abort or resume response code, see \ref _maligp_job_suspended_response_code */
+       u32 arguments[2];               /**< [in] 0 when aborting a job. When resuming a job, the Mali start and end address for a new heap to resume the job with */
+} _mali_uk_gp_suspend_response_s;
+
+/** @} */ /* end group _mali_uk_gp_suspend_response_s */
+
+/** @defgroup _mali_uk_gpstartjob_s Vertex Processor Start Job
+ * @{ */
+
+/** @brief Status indicating the result of starting a Vertex or Fragment processor job */
+typedef enum {
+       _MALI_UK_START_JOB_STARTED,                         /**< Job started */
+       _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE           /**< Job could not be started at this time. Try starting the job again */
+} _mali_uk_start_job_status;
+
+/** @brief Status indicating the result of the execution of a Vertex or Fragment processor job  */
+
+typedef enum {
+       _MALI_UK_JOB_STATUS_END_SUCCESS         = 1<<(16+0),
+       _MALI_UK_JOB_STATUS_END_OOM             = 1<<(16+1),
+       _MALI_UK_JOB_STATUS_END_ABORT           = 1<<(16+2),
+       _MALI_UK_JOB_STATUS_END_TIMEOUT_SW      = 1<<(16+3),
+       _MALI_UK_JOB_STATUS_END_HANG            = 1<<(16+4),
+       _MALI_UK_JOB_STATUS_END_SEG_FAULT       = 1<<(16+5),
+       _MALI_UK_JOB_STATUS_END_ILLEGAL_JOB     = 1<<(16+6),
+       _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR     = 1<<(16+7),
+       _MALI_UK_JOB_STATUS_END_SHUTDOWN        = 1<<(16+8),
+       _MALI_UK_JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9)
+} _mali_uk_job_status;
+
+#define MALIGP2_NUM_REGS_FRAME (6)
+
+/** @brief Arguments for _mali_ukk_gp_start_job()
+ *
+ * To start a Vertex Processor job
+ * - associate the request with a reference to a @c mali_gp_job_info by setting
+ * user_job_ptr to the address of the @c mali_gp_job_info of the job.
+ * - set @c priority to the priority of the @c mali_gp_job_info
+ * - specify a timeout for the job by setting @c watchdog_msecs to the number of
+ * milliseconds the job is allowed to run. Specifying a value of 0 selects the
+ * default timeout in use by the device driver.
+ * - copy the frame registers from the @c mali_gp_job_info into @c frame_registers.
+ * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero
+ * for a non-instrumented build. For an instrumented build you can use up
+ * to two performance counters. Set the corresponding bit in @c perf_counter_flag
+ * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify
+ * the source of what needs to get counted (e.g. number of vertex loader
+ * cache hits). For source id values, see ARM DDI0415A, Table 3-60.
+ * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
+ *
+ * When @c _mali_ukk_gp_start_job() returns @c _MALI_OSK_ERR_OK, status contains the
+ * result of the request (see \ref _mali_uk_start_job_status). If the job could
+ * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be
+ * tried again.
+ *
+ * After the job has started, @c _mali_wait_for_notification() will be notified
+ * that the job finished or got suspended. It may get suspended due to
+ * resource shortage. If it finished (see _mali_ukk_wait_for_notification())
+ * the notification will contain a @c _mali_uk_gp_job_finished_s result. If
+ * it got suspended the notification will contain a @c _mali_uk_gp_job_suspended_s
+ * result.
+ *
+ * The @c _mali_uk_gp_job_finished_s contains the job status (see \ref _mali_uk_job_status),
+ * the number of milliseconds the job took to render, and values of core registers
+ * when the job finished (irq status, performance counters, renderer list
+ * address). A job has finished succesfully when its status is
+ * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering
+ * the job, or software detected the job is taking more than watchdog_msecs to
+ * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG.
+ * If the hardware detected a bus error while accessing memory associated with the
+ * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT.
+ * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to
+ * stop the job but the job didn't start on the hardware yet, e.g. when the
+ * driver shutdown.
+ *
+ * In case the job got suspended, @c _mali_uk_gp_job_suspended_s contains
+ * the @c user_job_ptr identifier used to start the job with, the @c reason
+ * why the job stalled (see \ref _maligp_job_suspended_reason) and a @c cookie
+ * to identify the core on which the job stalled.  This @c cookie will be needed
+ * when responding to this nofication by means of _mali_ukk_gp_suspend_response().
+ * (see _mali_ukk_gp_suspend_response()). The response is either to abort or
+ * resume the job. If the job got suspended due to an out of memory condition
+ * you may be able to resolve this by providing more memory and resuming the job.
+ *
+ */
+typedef struct {
+       void *ctx;                          /**< [in,out] user-kernel context (trashed on output) */
+       u32 user_job_ptr;                   /**< [in] identifier for the job in user space, a @c mali_gp_job_info* */
+       u32 priority;                       /**< [in] job priority. A lower number means higher priority */
+       u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job */
+       u32 perf_counter_flag;              /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */
+       u32 perf_counter_src0;              /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
+       u32 perf_counter_src1;              /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
+       u32 frame_builder_id;               /**< [in] id of the originating frame builder */
+       u32 flush_id;                       /**< [in] flush id within the originating frame builder */
+       _mali_uk_fence_t fence;             /**< [in] fence this job must wait on */
+       u32 *timeline_point_ptr;            /**< [in,out] pointer to location where point on gp timeline for this job will be written */
+} _mali_uk_gp_start_job_s;
+
+#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE (1<<0) /**< Enable performance counter SRC0 for a job */
+#define _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE (1<<1) /**< Enable performance counter SRC1 for a job */
+#define _MALI_PERFORMANCE_COUNTER_FLAG_HEATMAP_ENABLE (1<<2) /**< Enable per tile (aka heatmap) generation with for a job (using the enabled counter sources) */
+
+/** @} */ /* end group _mali_uk_gpstartjob_s */
+
+typedef struct {
+       u32 user_job_ptr;               /**< [out] identifier for the job in user space */
+       _mali_uk_job_status status;     /**< [out] status of finished job */
+       u32 heap_current_addr;          /**< [out] value of the GP PLB PL heap start address register */
+       u32 perf_counter0;              /**< [out] value of performance counter 0 (see ARM DDI0415A) */
+       u32 perf_counter1;              /**< [out] value of performance counter 1 (see ARM DDI0415A) */
+} _mali_uk_gp_job_finished_s;
+
+typedef struct {
+       u32 user_job_ptr;                    /**< [out] identifier for the job in user space */
+       u32 cookie;                          /**< [out] identifier for the core in kernel space on which the job stalled */
+} _mali_uk_gp_job_suspended_s;
+
+/** @} */ /* end group _mali_uk_gp */
+
+
+/** @defgroup _mali_uk_pp U/K Fragment Processor
+ * @{ */
+
+#define _MALI_PP_MAX_SUB_JOBS 8
+
+#define _MALI_PP_MAX_FRAME_REGISTERS ((0x058/4)+1)
+
+#define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1)
+
+#define _MALI_DLBU_MAX_REGISTERS 4
+
+/** Flag for _mali_uk_pp_start_job_s */
+#define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0)
+#define _MALI_PP_JOB_FLAG_IS_WINDOW_SURFACE (1<<1)
+
+/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job
+ * @{ */
+
+/** @brief Arguments for _mali_ukk_pp_start_job()
+ *
+ * To start a Fragment Processor job
+ * - associate the request with a reference to a mali_pp_job by setting
+ * @c user_job_ptr to the address of the @c mali_pp_job of the job.
+ * - set @c priority to the priority of the mali_pp_job
+ * - specify a timeout for the job by setting @c watchdog_msecs to the number of
+ * milliseconds the job is allowed to run. Specifying a value of 0 selects the
+ * default timeout in use by the device driver.
+ * - copy the frame registers from the @c mali_pp_job into @c frame_registers.
+ * For MALI200 you also need to copy the write back 0,1 and 2 registers.
+ * - set the @c perf_counter_flag, @c perf_counter_src0 and @c perf_counter_src1 to zero
+ * for a non-instrumented build. For an instrumented build you can use up
+ * to two performance counters. Set the corresponding bit in @c perf_counter_flag
+ * to enable them. @c perf_counter_src0 and @c perf_counter_src1 specify
+ * the source of what needs to get counted (e.g. number of vertex loader
+ * cache hits). For source id values, see ARM DDI0415A, Table 3-60.
+ * - pass in the user-kernel context in @c ctx that was returned from _mali_ukk_open()
+ *
+ * When _mali_ukk_pp_start_job() returns @c _MALI_OSK_ERR_OK, @c status contains the
+ * result of the request (see \ref _mali_uk_start_job_status). If the job could
+ * not get started (@c _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE) it should be
+ * tried again.
+ *
+ * After the job has started, _mali_wait_for_notification() will be notified
+ * when the job finished. The notification will contain a
+ * @c _mali_uk_pp_job_finished_s result. It contains the @c user_job_ptr
+ * identifier used to start the job with, the job @c status (see \ref _mali_uk_job_status),
+ * the number of milliseconds the job took to render, and values of core registers
+ * when the job finished (irq status, performance counters, renderer list
+ * address). A job has finished succesfully when its status is
+ * @c _MALI_UK_JOB_STATUS_FINISHED. If the hardware detected a timeout while rendering
+ * the job, or software detected the job is taking more than @c watchdog_msecs to
+ * complete, the status will indicate @c _MALI_UK_JOB_STATUS_HANG.
+ * If the hardware detected a bus error while accessing memory associated with the
+ * job, status will indicate @c _MALI_UK_JOB_STATUS_SEG_FAULT.
+ * status will indicate @c _MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to
+ * stop the job but the job didn't start on the hardware yet, e.g. when the
+ * driver shutdown.
+ *
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 user_job_ptr;               /**< [in] identifier for the job in user space */
+       u32 priority;                   /**< [in] job priority. A lower number means higher priority */
+       u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS];         /**< [in] core specific registers associated with first sub job, see ARM DDI0415A */
+       u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_FRAME registers for sub job 1-7 */
+       u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_STACK registers for sub job 1-7 */
+       u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS];
+       u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS];
+       u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS];
+       u32 dlbu_registers[_MALI_DLBU_MAX_REGISTERS]; /**< [in] Dynamic load balancing unit registers */
+       u32 num_cores;                      /**< [in] Number of cores to set up (valid range: 1-4) */
+       u32 perf_counter_flag;              /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */
+       u32 perf_counter_src0;              /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
+       u32 perf_counter_src1;              /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
+       u32 frame_builder_id;               /**< [in] id of the originating frame builder */
+       u32 flush_id;                       /**< [in] flush id within the originating frame builder */
+       u32 flags;                          /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */
+       u32 tilesx;                         /**< [in] number of tiles in the x direction (needed for heatmap generation */
+       u32 tilesy;                         /**< [in] number of tiles in y direction (needed for reading the heatmap memory) */
+       u32 heatmap_mem;                    /**< [in] memory address to store counter values per tile (aka heatmap) */
+       u32 num_memory_cookies;             /**< [in] number of memory cookies attached to job */
+       u32 *memory_cookies;                /**< [in] memory cookies attached to job  */
+       _mali_uk_fence_t fence;             /**< [in] fence this job must wait on */
+       u32 *timeline_point_ptr;            /**< [in,out] pointer to location where point on pp timeline for this job will be written */
+} _mali_uk_pp_start_job_s;
+
+typedef struct {
+       void *ctx;                          /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_gp_start_job_s *gp_args;   /**< [in,out] GP uk arguments (see _mali_uk_gp_start_job_s) */
+       _mali_uk_pp_start_job_s *pp_args;   /**< [in,out] PP uk arguments (see _mali_uk_pp_start_job_s) */
+} _mali_uk_pp_and_gp_start_job_s;
+
+/** @} */ /* end group _mali_uk_ppstartjob_s */
+
+typedef struct {
+       u32 user_job_ptr;                          /**< [out] identifier for the job in user space */
+       _mali_uk_job_status status;                /**< [out] status of finished job */
+       u32 perf_counter0[_MALI_PP_MAX_SUB_JOBS];  /**< [out] value of perfomance counter 0 (see ARM DDI0415A), one for each sub job */
+       u32 perf_counter1[_MALI_PP_MAX_SUB_JOBS];  /**< [out] value of perfomance counter 1 (see ARM DDI0415A), one for each sub job */
+       u32 perf_counter_src0;
+       u32 perf_counter_src1;
+} _mali_uk_pp_job_finished_s;
+
+typedef struct {
+       u32 number_of_enabled_cores;               /**< [out] the new number of enabled cores */
+} _mali_uk_pp_num_cores_changed_s;
+
+
+
+/**
+ * Flags to indicate write-back units
+ */
+typedef enum {
+       _MALI_UK_PP_JOB_WB0 = 1,
+       _MALI_UK_PP_JOB_WB1 = 2,
+       _MALI_UK_PP_JOB_WB2 = 4,
+} _mali_uk_pp_job_wbx_flag;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 fb_id;                      /**< [in] Frame builder ID of job to disable WB units for */
+       u32 wb0_memory;
+       u32 wb1_memory;
+       u32 wb2_memory;
+} _mali_uk_pp_disable_wb_s;
+
+
+/** @} */ /* end group _mali_uk_pp */
+
+/** @defgroup _mali_uk_soft_job U/K Soft Job
+ * @{ */
+
+typedef struct {
+       void *ctx;                          /**< [in,out] user-kernel context (trashed on output) */
+       u32 type;                           /**< [in] type of soft job */
+       u32 user_job;                       /**< [in] identifier for the job in user space */
+       u32 *job_id_ptr;                    /**< [in,out] pointer to location where job id will be written */
+       _mali_uk_fence_t fence;             /**< [in] fence this job must wait on */
+       u32 point;                          /**< [out] point on soft timeline for this job */
+} _mali_uk_soft_job_start_s;
+
+typedef struct {
+       u32 user_job;                       /**< [out] identifier for the job in user space */
+} _mali_uk_soft_job_activated_s;
+
+typedef struct {
+       void *ctx;                          /**< [in,out] user-kernel context (trashed on output) */
+       u32 job_id;                         /**< [in] id for soft job */
+} _mali_uk_soft_job_signal_s;
+
+/** @} */ /* end group _mali_uk_soft_job */
+
+/** @addtogroup _mali_uk_core U/K Core
+ * @{ */
+
+/** @defgroup _mali_uk_waitfornotification_s Wait For Notification
+ * @{ */
+
+/** @brief Notification type encodings
+ *
+ * Each Notification type is an ordered pair of (subsystem,id), and is unique.
+ *
+ * The encoding of subsystem,id into a 32-bit word is:
+ * encoding = (( subsystem << _MALI_NOTIFICATION_SUBSYSTEM_SHIFT ) & _MALI_NOTIFICATION_SUBSYSTEM_MASK)
+ *            | (( id <<  _MALI_NOTIFICATION_ID_SHIFT ) & _MALI_NOTIFICATION_ID_MASK)
+ *
+ * @see _mali_uk_wait_for_notification_s
+ */
+typedef enum {
+       /** core notifications */
+
+       _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS =  (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20,
+       _MALI_NOTIFICATION_APPLICATION_QUIT =           (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40,
+       _MALI_NOTIFICATION_SETTINGS_CHANGED =           (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x80,
+       _MALI_NOTIFICATION_SOFT_ACTIVATED =             (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x100,
+
+       /** Fragment Processor notifications */
+
+       _MALI_NOTIFICATION_PP_FINISHED =                (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10,
+       _MALI_NOTIFICATION_PP_NUM_CORE_CHANGE =         (_MALI_UK_PP_SUBSYSTEM << 16) | 0x20,
+
+       /** Vertex Processor notifications */
+
+       _MALI_NOTIFICATION_GP_FINISHED =                (_MALI_UK_GP_SUBSYSTEM << 16) | 0x10,
+       _MALI_NOTIFICATION_GP_STALLED =                 (_MALI_UK_GP_SUBSYSTEM << 16) | 0x20,
+
+} _mali_uk_notification_type;
+
+/** to assist in splitting up 32-bit notification value in subsystem and id value */
+#define _MALI_NOTIFICATION_SUBSYSTEM_MASK 0xFFFF0000
+#define _MALI_NOTIFICATION_SUBSYSTEM_SHIFT 16
+#define _MALI_NOTIFICATION_ID_MASK 0x0000FFFF
+#define _MALI_NOTIFICATION_ID_SHIFT 0
+
+
+/** @brief Enumeration of possible settings which match mali_setting_t in user space
+ *
+ *
+ */
+typedef enum {
+       _MALI_UK_USER_SETTING_SW_EVENTS_ENABLE = 0,
+       _MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED,
+       _MALI_UK_USER_SETTING_DEPTHBUFFER_CAPTURE_ENABLED,
+       _MALI_UK_USER_SETTING_STENCILBUFFER_CAPTURE_ENABLED,
+       _MALI_UK_USER_SETTING_PER_TILE_COUNTERS_CAPTURE_ENABLED,
+       _MALI_UK_USER_SETTING_BUFFER_CAPTURE_COMPOSITOR,
+       _MALI_UK_USER_SETTING_BUFFER_CAPTURE_WINDOW,
+       _MALI_UK_USER_SETTING_BUFFER_CAPTURE_OTHER,
+       _MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES,
+       _MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR,
+       _MALI_UK_USER_SETTING_SW_COUNTER_ENABLED,
+       _MALI_UK_USER_SETTING_MAX,
+} _mali_uk_user_setting_t;
+
+/* See mali_user_settings_db.c */
+extern const char *_mali_uk_user_setting_descriptions[];
+#define _MALI_UK_USER_SETTING_DESCRIPTIONS \
+{                                           \
+       "sw_events_enable",                 \
+       "colorbuffer_capture_enable",       \
+       "depthbuffer_capture_enable",       \
+       "stencilbuffer_capture_enable",     \
+       "per_tile_counters_enable",         \
+       "buffer_capture_compositor",        \
+       "buffer_capture_window",            \
+       "buffer_capture_other",             \
+       "buffer_capture_n_frames",          \
+       "buffer_capture_resize_factor",     \
+       "sw_counters_enable",               \
+};
+
+/** @brief struct to hold the value to a particular setting as seen in the kernel space
+ */
+typedef struct {
+       _mali_uk_user_setting_t setting;
+       u32 value;
+} _mali_uk_settings_changed_s;
+
+/** @brief Arguments for _mali_ukk_wait_for_notification()
+ *
+ * On successful return from _mali_ukk_wait_for_notification(), the members of
+ * this structure will indicate the reason for notification.
+ *
+ * Specifically, the source of the notification can be identified by the
+ * subsystem and id fields of the mali_uk_notification_type in the code.type
+ * member. The type member is encoded in a way to divide up the types into a
+ * subsystem field, and a per-subsystem ID field. See
+ * _mali_uk_notification_type for more information.
+ *
+ * Interpreting the data union member depends on the notification type:
+ *
+ * - type == _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS
+ *     - The kernel side is shutting down. No further
+ * _mali_uk_wait_for_notification() calls should be made.
+ *     - In this case, the value of the data union member is undefined.
+ *     - This is used to indicate to the user space client that it should close
+ * the connection to the Mali Device Driver.
+ * - type == _MALI_NOTIFICATION_PP_FINISHED
+ *    - The notification data is of type _mali_uk_pp_job_finished_s. It contains the user_job_ptr
+ * identifier used to start the job with, the job status, the number of milliseconds the job took to render,
+ * and values of core registers when the job finished (irq status, performance counters, renderer list
+ * address).
+ *    - A job has finished succesfully when its status member is _MALI_UK_JOB_STATUS_FINISHED.
+ *    - If the hardware detected a timeout while rendering the job, or software detected the job is
+ * taking more than watchdog_msecs (see _mali_ukk_pp_start_job()) to complete, the status member will
+ * indicate _MALI_UK_JOB_STATUS_HANG.
+ *    - If the hardware detected a bus error while accessing memory associated with the job, status will
+ * indicate _MALI_UK_JOB_STATUS_SEG_FAULT.
+ *    - Status will indicate MALI_UK_JOB_STATUS_NOT_STARTED if the driver had to stop the job but the job
+ * didn't start the hardware yet, e.g. when the driver closes.
+ * - type == _MALI_NOTIFICATION_GP_FINISHED
+ *     - The notification data is of type _mali_uk_gp_job_finished_s. The notification is similar to that of
+ * type == _MALI_NOTIFICATION_PP_FINISHED, except that several other GP core register values are returned.
+ * The status values have the same meaning for type == _MALI_NOTIFICATION_PP_FINISHED.
+ * - type == _MALI_NOTIFICATION_GP_STALLED
+ *     - The nofication data is of type _mali_uk_gp_job_suspended_s. It contains the user_job_ptr
+ * identifier used to start the job with, the reason why the job stalled and a cookie to identify the core on
+ * which the job stalled.
+ *     - The reason member of gp_job_suspended is set to _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY
+ * when the polygon list builder unit has run out of memory.
+ */
+typedef struct {
+       void *ctx;                       /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_notification_type type; /**< [out] Type of notification available */
+       union {
+               _mali_uk_gp_job_suspended_s gp_job_suspended;/**< [out] Notification data for _MALI_NOTIFICATION_GP_STALLED notification type */
+               _mali_uk_gp_job_finished_s  gp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_GP_FINISHED notification type */
+               _mali_uk_pp_job_finished_s  pp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_PP_FINISHED notification type */
+               _mali_uk_settings_changed_s setting_changed;/**< [out] Notification data for _MALI_NOTIFICAATION_SETTINGS_CHANGED notification type */
+               _mali_uk_soft_job_activated_s soft_job_activated; /**< [out] Notification data for _MALI_NOTIFICATION_SOFT_ACTIVATED notification type */
+       } data;
+} _mali_uk_wait_for_notification_s;
+
+/** @brief Arguments for _mali_ukk_post_notification()
+ *
+ * Posts the specified notification to the notification queue for this application.
+ * This is used to send a quit message to the callback thread.
+ */
+typedef struct {
+       void *ctx;                       /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_notification_type type; /**< [in] Type of notification to post */
+} _mali_uk_post_notification_s;
+
+/** @} */ /* end group _mali_uk_waitfornotification_s */
+
+/** @defgroup _mali_uk_getapiversion_s Get API Version
+ * @{ */
+
+/** helpers for Device Driver API version handling */
+
+/** @brief Encode a version ID from a 16-bit input
+ *
+ * @note the input is assumed to be 16 bits. It must not exceed 16 bits. */
+#define _MAKE_VERSION_ID(x) (((x) << 16UL) | (x))
+
+/** @brief Check whether a 32-bit value is likely to be Device Driver API
+ * version ID. */
+#define _IS_VERSION_ID(x) (((x) & 0xFFFF) == (((x) >> 16UL) & 0xFFFF))
+
+/** @brief Decode a 16-bit version number from a 32-bit Device Driver API version
+ * ID */
+#define _GET_VERSION(x) (((x) >> 16UL) & 0xFFFF)
+
+/** @brief Determine whether two 32-bit encoded version IDs match */
+#define _IS_API_MATCH(x, y) (IS_VERSION_ID((x)) && IS_VERSION_ID((y)) && (GET_VERSION((x)) == GET_VERSION((y))))
+
+ /**
+  * RK MALI version code
+  */
+#define _MALI_RK_LIBS_VERSION 6
+
+/**
+ * API version define.
+ * Indicates the version of the kernel API
+ * The version is a 16bit integer incremented on each API change.
+ * The 16bit integer is stored twice in a 32bit integer
+ * For example, for version 1 the value would be 0x00010001
+ */
+#define _MALI_API_VERSION 401
+#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION)
+
+/**
+ * The API version is a 16-bit integer stored in both the lower and upper 16-bits
+ * of a 32-bit value. The 16-bit API version value is incremented on each API
+ * change. Version 1 would be 0x00010001. Used in _mali_uk_get_api_version_s.
+ */
+typedef u32 _mali_uk_api_version;
+
+/** @brief Arguments for _mali_uk_get_api_version()
+ *
+ * The user-side interface version must be written into the version member,
+ * encoded using _MAKE_VERSION_ID(). It will be compared to the API version of
+ * the kernel-side interface.
+ *
+ * On successful return, the version member will be the API version of the
+ * kernel-side interface. _MALI_UK_API_VERSION macro defines the current version
+ * of the API.
+ *
+ * The compatible member must be checked to see if the version of the user-side
+ * interface is compatible with the kernel-side interface, since future versions
+ * of the interface may be backwards compatible.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_api_version version;   /**< [in,out] API version of user-side interface. */
+       int compatible;                 /**< [out] @c 1 when @version is compatible, @c 0 otherwise */
+} _mali_uk_get_api_version_s;
+/** @} */ /* end group _mali_uk_getapiversion_s */
+
+typedef struct
+{
+    void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+    _mali_uk_api_version version;                   /**< [in,out] API version of user-side interface. */
+} _mali_uk_get_mali_version_in_rk30_s;
+
+/** @defgroup _mali_uk_get_user_settings_s Get user space settings */
+
+/** @brief struct to keep the matching values of the user space settings within certain context
+ *
+ * Each member of the settings array corresponds to a matching setting in the user space and its value is the value
+ * of that particular setting.
+ *
+ * All settings are given reference to the context pointed to by the ctx pointer.
+ *
+ */
+typedef struct {
+       void *ctx;                       /**< [in,out] user-kernel context (trashed on output) */
+       u32 settings[_MALI_UK_USER_SETTING_MAX]; /**< [out] The values for all settings */
+} _mali_uk_get_user_settings_s;
+
+/** @brief struct to hold the value of a particular setting from the user space within a given context
+ */
+typedef struct {
+       void *ctx;                       /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_user_setting_t setting; /**< [in] setting to get */
+       u32 value;                       /**< [out] value of setting */
+} _mali_uk_get_user_setting_s;
+
+/** @brief Arguments for _mali_ukk_request_high_priority() */
+typedef struct {
+       void *ctx;                       /**< [in,out] user-kernel context (trashed on output) */
+} _mali_uk_request_high_priority_s;
+
+/** @} */ /* end group _mali_uk_core */
+
+
+/** @defgroup _mali_uk_memory U/K Memory
+ * @{ */
+
+/** Flag for _mali_uk_map_external_mem_s, _mali_uk_attach_ump_mem_s and _mali_uk_attach_dma_buf_s */
+#define _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE (1<<0)
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 phys_addr;                  /**< [in] physical address */
+       u32 size;                       /**< [in] size */
+       u32 mali_address;               /**< [in] mali address to map the physical memory to */
+       u32 rights;                     /**< [in] rights necessary for accessing memory */
+       u32 flags;                      /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */
+       u32 cookie;                     /**< [out] identifier for mapped memory object in kernel space  */
+} _mali_uk_map_external_mem_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 cookie;                     /**< [out] identifier for mapped memory object in kernel space  */
+} _mali_uk_unmap_external_mem_s;
+
+/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by memory descriptor */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 mem_fd;                     /**< [in] Memory descriptor */
+       u32 size;                       /**< [in] size */
+       u32 mali_address;               /**< [in] mali address to map the physical memory to */
+       u32 rights;                     /**< [in] rights necessary for accessing memory */
+       u32 flags;                      /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */
+       u32 cookie;                     /**< [out] identifier for mapped memory object in kernel space  */
+} _mali_uk_attach_dma_buf_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 mem_fd;                     /**< [in] Memory descriptor */
+       u32 size;                       /**< [out] size */
+} _mali_uk_dma_buf_get_size_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 cookie;                     /**< [in] identifier for mapped memory object in kernel space  */
+} _mali_uk_release_dma_buf_s;
+
+/** @note This is identical to _mali_uk_map_external_mem_s above, however phys_addr is replaced by secure_id */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 secure_id;                  /**< [in] secure id */
+       u32 size;                       /**< [in] size */
+       u32 mali_address;               /**< [in] mali address to map the physical memory to */
+       u32 rights;                     /**< [in] rights necessary for accessing memory */
+       u32 flags;                      /**< [in] flags, see \ref _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE */
+       u32 cookie;                     /**< [out] identifier for mapped memory object in kernel space  */
+} _mali_uk_attach_ump_mem_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 cookie;                     /**< [in] identifier for mapped memory object in kernel space  */
+} _mali_uk_release_ump_mem_s;
+
+/** @brief Arguments for _mali_ukk_va_to_mali_pa()
+ *
+ * if size is zero or not a multiple of the system's page size, it will be
+ * rounded up to the next multiple of the page size. This will occur before
+ * any other use of the size parameter.
+ *
+ * if va is not PAGE_SIZE aligned, it will be rounded down to the next page
+ * boundary.
+ *
+ * The range (va) to ((u32)va)+(size-1) inclusive will be checked for physical
+ * contiguity.
+ *
+ * The implementor will check that the entire physical range is allowed to be mapped
+ * into user-space.
+ *
+ * Failure will occur if either of the above are not satisfied.
+ *
+ * Otherwise, the physical base address of the range is returned through pa,
+ * va is updated to be page aligned, and size is updated to be a non-zero
+ * multiple of the system's pagesize.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       void *va;                       /**< [in,out] Virtual address of the start of the range */
+       u32 pa;                         /**< [out] Physical base address of the range */
+       u32 size;                       /**< [in,out] Size of the range, in bytes. */
+} _mali_uk_va_to_mali_pa_s;
+
+/**
+ * @brief Arguments for _mali_uk[uk]_mem_write_safe()
+ */
+typedef struct {
+       void *ctx;        /**< [in,out] user-kernel context (trashed on output) */
+       const void *src;  /**< [in]     Pointer to source data */
+       void *dest;       /**< [in]     Destination Mali buffer */
+       u32 size;         /**< [in,out] Number of bytes to write/copy on input, number of bytes actually written/copied on output */
+} _mali_uk_mem_write_safe_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 size;                       /**< [out] size of MMU page table information (registers + page tables) */
+} _mali_uk_query_mmu_page_table_dump_size_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 size;                       /**< [in] size of buffer to receive mmu page table information */
+       void *buffer;                   /**< [in,out] buffer to receive mmu page table information */
+       u32 register_writes_size;       /**< [out] size of MMU register dump */
+       u32 *register_writes;           /**< [out] pointer within buffer where MMU register dump is stored */
+       u32 page_table_dump_size;       /**< [out] size of MMU page table dump */
+       u32 *page_table_dump;           /**< [out] pointer within buffer where MMU page table dump is stored */
+} _mali_uk_dump_mmu_page_table_s;
+
+/** @} */ /* end group _mali_uk_memory */
+
+
+/** @addtogroup _mali_uk_pp U/K Fragment Processor
+ * @{ */
+
+/** @brief Arguments for _mali_ukk_get_pp_number_of_cores()
+ *
+ * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
+ * - Upon successful return from _mali_ukk_get_pp_number_of_cores(), @c number_of_cores
+ * will contain the number of Fragment Processor cores in the system.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 number_of_total_cores;      /**< [out] Total number of Fragment Processor cores in the system */
+       u32 number_of_enabled_cores;    /**< [out] Number of enabled Fragment Processor cores */
+} _mali_uk_get_pp_number_of_cores_s;
+
+/** @brief Arguments for _mali_ukk_get_pp_core_version()
+ *
+ * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
+ * - Upon successful return from _mali_ukk_get_pp_core_version(), @c version contains
+ * the version that all Fragment Processor cores are compatible with.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       _mali_core_version version;     /**< [out] version returned from core, see \ref _mali_core_version  */
+} _mali_uk_get_pp_core_version_s;
+
+/** @} */ /* end group _mali_uk_pp */
+
+
+/** @addtogroup _mali_uk_gp U/K Vertex Processor
+ * @{ */
+
+/** @brief Arguments for _mali_ukk_get_gp_number_of_cores()
+ *
+ * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
+ * - Upon successful return from _mali_ukk_get_gp_number_of_cores(), @c number_of_cores
+ * will contain the number of Vertex Processor cores in the system.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 number_of_cores;            /**< [out] number of Vertex Processor cores in the system */
+} _mali_uk_get_gp_number_of_cores_s;
+
+/** @brief Arguments for _mali_ukk_get_gp_core_version()
+ *
+ * - pass in the user-kernel context @c ctx that was returned from _mali_ukk_open()
+ * - Upon successful return from _mali_ukk_get_gp_core_version(), @c version contains
+ * the version that all Vertex Processor cores are compatible with.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       _mali_core_version version;     /**< [out] version returned from core, see \ref _mali_core_version */
+} _mali_uk_get_gp_core_version_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 limit;                      /**< [in,out] The desired limit for number of events to record on input, actual limit on output */
+} _mali_uk_profiling_start_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 event_id;                   /**< [in] event id to register (see  enum mali_profiling_events for values) */
+       u32 data[5];                    /**< [in] event specific data */
+} _mali_uk_profiling_add_event_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 count;                      /**< [out] The number of events sampled */
+} _mali_uk_profiling_stop_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 index;                      /**< [in] which index to get (starting at zero) */
+       u64 timestamp;                  /**< [out] timestamp of event */
+       u32 event_id;                   /**< [out] event id of event (see  enum mali_profiling_events for values) */
+       u32 data[5];                    /**< [out] event specific data */
+} _mali_uk_profiling_get_event_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+} _mali_uk_profiling_clear_s;
+
+/** @} */ /* end group _mali_uk_gp */
+
+
+/** @addtogroup _mali_uk_memory U/K Memory
+ * @{ */
+
+/** @brief Arguments to _mali_ukk_mem_mmap()
+ *
+ * Use of the phys_addr member depends on whether the driver is compiled for
+ * Mali-MMU or nonMMU:
+ * - in the nonMMU case, this is the physical address of the memory as seen by
+ * the CPU (which may be a constant offset from that used by Mali)
+ * - in the MMU case, this is the Mali Virtual base address of the memory to
+ * allocate, and the particular physical pages used to back the memory are
+ * entirely determined by _mali_ukk_mem_mmap(). The details of the physical pages
+ * are not reported to user-space for security reasons.
+ *
+ * The cookie member must be stored for use later when freeing the memory by
+ * calling _mali_ukk_mem_munmap(). In the Mali-MMU case, the cookie is secure.
+ *
+ * The ukk_private word must be set to zero when calling from user-space. On
+ * Kernel-side, the  OS implementation of the U/K interface can use it to
+ * communicate data to the OS implementation of the OSK layer. In particular,
+ * _mali_ukk_get_big_block() directly calls _mali_ukk_mem_mmap directly, and
+ * will communicate its own ukk_private word through the ukk_private member
+ * here. The common code itself will not inspect or modify the ukk_private
+ * word, and so it may be safely used for whatever purposes necessary to
+ * integrate Mali Memory handling into the OS.
+ *
+ * The uku_private member is currently reserved for use by the user-side
+ * implementation of the U/K interface. Its value must be zero.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       void *mapping;                  /**< [out] Returns user-space virtual address for the mapping */
+       u32 size;                       /**< [in] Size of the requested mapping */
+       u32 phys_addr;                  /**< [in] Physical address - could be offset, depending on caller+callee convention */
+       u32 cookie;                     /**< [out] Returns a cookie for use in munmap calls */
+       void *uku_private;              /**< [in] User-side Private word used by U/K interface */
+       void *ukk_private;              /**< [in] Kernel-side Private word used by U/K interface */
+       mali_memory_cache_settings cache_settings; /**< [in] Option to set special cache flags, tuning L2 efficency */
+} _mali_uk_mem_mmap_s;
+
+/** @brief Arguments to _mali_ukk_mem_munmap()
+ *
+ * The cookie and mapping members must be that returned from the same previous
+ * call to _mali_ukk_mem_mmap(). The size member must correspond to cookie
+ * and mapping - that is, it must be the value originally supplied to a call to
+ * _mali_ukk_mem_mmap that returned the values of mapping and cookie.
+ *
+ * An error will be returned if an attempt is made to unmap only part of the
+ * originally obtained range, or to unmap more than was originally obtained.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       void *mapping;                  /**< [in] The mapping returned from mmap call */
+       u32 size;                       /**< [in] The size passed to mmap call */
+       u32 cookie;                     /**< [in] Cookie from mmap call */
+} _mali_uk_mem_munmap_s;
+/** @} */ /* end group _mali_uk_memory */
+
+/** @defgroup _mali_uk_vsync U/K VSYNC Wait Reporting Module
+ * @{ */
+
+/** @brief VSYNC events
+ *
+ * These events are reported when DDK starts to wait for vsync and when the
+ * vsync has occured and the DDK can continue on the next frame.
+ */
+typedef enum _mali_uk_vsync_event {
+       _MALI_UK_VSYNC_EVENT_BEGIN_WAIT = 0,
+       _MALI_UK_VSYNC_EVENT_END_WAIT
+} _mali_uk_vsync_event;
+
+/** @brief Arguments to _mali_ukk_vsync_event()
+ *
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_vsync_event event;     /**< [in] VSYNCH event type */
+} _mali_uk_vsync_event_report_s;
+
+/** @} */ /* end group _mali_uk_vsync */
+
+/** @defgroup _mali_uk_sw_counters_report U/K Software Counter Reporting
+ * @{ */
+
+/** @brief Software counter values
+ *
+ * Values recorded for each of the software counters during a single renderpass.
+ */
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32* counters;                  /**< [in] The array of counter values */
+       u32  num_counters;              /**< [in] The number of elements in counters array */
+} _mali_uk_sw_counters_report_s;
+
+/** @} */ /* end group _mali_uk_sw_counters_report */
+
+/** @defgroup _mali_uk_timeline U/K Mali Timeline
+ * @{ */
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       u32 timeline;                   /**< [in] timeline id */
+       u32 point;                      /**< [out] latest point on timeline */
+} _mali_uk_timeline_get_latest_point_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_fence_t fence;         /**< [in] fence */
+       u32 timeout;                    /**< [in] timeout (0 for no wait, -1 for blocking) */
+       u32 status;                     /**< [out] status of fence (1 if signaled, 0 if timeout) */
+} _mali_uk_timeline_wait_s;
+
+typedef struct {
+       void *ctx;                      /**< [in,out] user-kernel context (trashed on output) */
+       _mali_uk_fence_t fence;         /**< [in] mali fence to create linux sync fence from */
+       s32 sync_fd;                    /**< [out] file descriptor for new linux sync fence */
+} _mali_uk_timeline_create_sync_fence_s;
+
+/** @} */ /* end group _mali_uk_timeline */
+
+/** @} */ /* end group u_k_api */
+
+/** @} */ /* end group uddapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UTGARD_UK_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/arm/mali400/mali/linux/license/gpl/mali_kernel_license.h
new file mode 100755 (executable)
index 0000000..993d14d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_kernel_license.h
+ * Defines for the macro MODULE_LICENSE.
+ */
+
+#ifndef __MALI_KERNEL_LICENSE_H__
+#define __MALI_KERNEL_LICENSE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define MALI_KERNEL_LINUX_LICENSE     "GPL"
+#define MALI_LICENSE_IS_GPL 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_LICENSE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h b/drivers/gpu/arm/mali400/mali/linux/license/proprietary/mali_kernel_license.h
new file mode 100755 (executable)
index 0000000..d3760d8
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_kernel_license.h
+ * Defines for the macro MODULE_LICENSE.
+ */
+
+#ifndef __MALI_KERNEL_LICENSE_H__
+#define __MALI_KERNEL_LICENSE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MALI_KERNEL_LINUX_LICENSE     "Proprietary"
+#define MALI_LICENSE_IS_GPL 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_LICENSE_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_device_pause_resume.c b/drivers/gpu/arm/mali400/mali/linux/mali_device_pause_resume.c
new file mode 100755 (executable)
index 0000000..68a28f4
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_device_pause_resume.c
+ * Implementation of the Mali pause/resume functionality
+ */
+
+#include <linux/module.h>
+#include <linux/mali/mali_utgard.h>
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+
+void mali_dev_pause(void)
+{
+       mali_gp_scheduler_suspend();
+       mali_pp_scheduler_suspend();
+       mali_group_power_off(MALI_FALSE);
+       mali_l2_cache_pause_all(MALI_TRUE);
+}
+
+EXPORT_SYMBOL(mali_dev_pause);
+
+void mali_dev_resume(void)
+{
+       mali_l2_cache_pause_all(MALI_FALSE);
+       mali_gp_scheduler_resume();
+       mali_pp_scheduler_resume();
+}
+
+EXPORT_SYMBOL(mali_dev_resume);
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c
new file mode 100755 (executable)
index 0000000..4f61c39
--- /dev/null
@@ -0,0 +1,827 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_kernel_linux.c
+ * Implementation of the Linux device driver entrypoints
+ */
+#include <linux/module.h>   /* kernel module definitions */
+#include <linux/fs.h>       /* file system operations */
+#include <linux/cdev.h>     /* character device definitions */
+#include <linux/mm.h>       /* memory manager definitions */
+#include <linux/mali/mali_utgard_ioctl.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include "mali_kernel_license.h"
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_kernel_core.h"
+#include "mali_osk.h"
+#include "mali_kernel_linux.h"
+#include "mali_ukk.h"
+#include "mali_ukk_wrappers.h"
+#include "mali_kernel_sysfs.h"
+#include "mali_pm.h"
+#include "mali_kernel_license.h"
+#include "mali_memory.h"
+#include "mali_memory_dma_buf.h"
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+#include "mali_profiling_internal.h"
+#endif
+#include <linux/of.h>
+
+/* Streamline support for the Mali driver */
+#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_MALI400_PROFILING)
+/* Ask Linux to create the tracepoints */
+#define CREATE_TRACE_POINTS
+#include "mali_linux_trace.h"
+#endif /* CONFIG_TRACEPOINTS */
+
+/* from the __malidrv_build_info.c file that is generated during build */
+extern const char *__malidrv_build_info(void);
+
+/* Module parameter to control log level */
+int mali_debug_level = 2;
+module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
+MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output");
+
+extern int mali_max_job_runtime;
+module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what");
+
+extern int mali_l2_max_reads;
+module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache");
+
+extern unsigned int mali_dedicated_mem_start;
+module_param(mali_dedicated_mem_start, uint, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory.");
+
+extern unsigned int mali_dedicated_mem_size;
+module_param(mali_dedicated_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory.");
+
+extern unsigned long mali_shared_mem_size;
+module_param(mali_shared_mem_size, ulong, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory.");
+
+#if defined(CONFIG_MALI400_PROFILING)
+extern int mali_boot_profiling;
+module_param(mali_boot_profiling, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver initialization");
+#endif
+
+extern int mali_max_pp_cores_group_1;
+module_param(mali_max_pp_cores_group_1, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_max_pp_cores_group_1, "Limit the number of PP cores to use from first PP group.");
+
+extern int mali_max_pp_cores_group_2;
+module_param(mali_max_pp_cores_group_2, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_max_pp_cores_group_2, "Limit the number of PP cores to use from second PP group (Mali-450 only).");
+
+#if defined(CONFIG_MALI400_POWER_PERFORMANCE_POLICY)
+/** the max fps the same as display vsync default 60, can set by module insert parameter */
+extern int mali_max_system_fps;
+module_param(mali_max_system_fps, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_max_system_fps, "Max system fps the same as display VSYNC.");
+
+/** a lower limit on their desired FPS default 58, can set by module insert parameter*/
+extern int mali_desired_fps;
+module_param(mali_desired_fps, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_desired_fps, "A bit lower than max_system_fps which user desired fps");
+#endif
+
+#if MALI_ENABLE_CPU_CYCLES
+#include <linux/cpumask.h>
+#include <linux/timer.h>
+#include <asm/smp.h>
+static struct timer_list mali_init_cpu_clock_timers[8];
+static u32 mali_cpu_clock_last_value[8] = {0,};
+#endif
+
+/* Export symbols from common code: mali_user_settings.c */
+#include "mali_user_settings_db.h"
+EXPORT_SYMBOL(mali_set_user_setting);
+EXPORT_SYMBOL(mali_get_user_setting);
+
+static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
+
+/* This driver only supports one Mali device, and this variable stores this single platform device */
+struct platform_device *mali_platform_device = NULL;
+
+/* This driver only supports one Mali device, and this variable stores the exposed misc device (/dev/mali) */
+static struct miscdevice mali_miscdevice = { 0, };
+
+static int mali_miscdevice_register(struct platform_device *pdev);
+static void mali_miscdevice_unregister(void);
+
+static int mali_open(struct inode *inode, struct file *filp);
+static int mali_release(struct inode *inode, struct file *filp);
+#ifdef HAVE_UNLOCKED_IOCTL
+static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+#else
+static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+#endif
+
+static int mali_probe(struct platform_device *pdev);
+static int mali_remove(struct platform_device *pdev);
+
+static int mali_driver_suspend_scheduler(struct device *dev);
+static int mali_driver_resume_scheduler(struct device *dev);
+
+#ifdef CONFIG_PM_RUNTIME
+static int mali_driver_runtime_suspend(struct device *dev);
+static int mali_driver_runtime_resume(struct device *dev);
+static int mali_driver_runtime_idle(struct device *dev);
+#endif
+
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+extern int mali_platform_device_register(struct platform_device *pdev);
+extern int mali_platform_device_unregister(struct platform_device *pdev);
+#endif
+
+
+/* Linux power management operations provided by the Mali device driver */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+struct pm_ext_ops mali_dev_ext_pm_ops = {
+       .base =
+       {
+               .suspend = mali_driver_suspend_scheduler,
+               .resume = mali_driver_resume_scheduler,
+               .freeze = mali_driver_suspend_scheduler,
+               .thaw =   mali_driver_resume_scheduler,
+       },
+};
+#else
+static const struct dev_pm_ops mali_dev_pm_ops = {
+#ifdef CONFIG_PM_RUNTIME
+       .runtime_suspend = mali_driver_runtime_suspend,
+       .runtime_resume = mali_driver_runtime_resume,
+       .runtime_idle = mali_driver_runtime_idle,
+#endif
+       .suspend = mali_driver_suspend_scheduler,
+       .resume = mali_driver_resume_scheduler,
+       .freeze = mali_driver_suspend_scheduler,
+       .thaw = mali_driver_resume_scheduler,
+       .poweroff = mali_driver_suspend_scheduler,
+};
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id mali_dt_ids[] = {
+       { .compatible = "arm,mali400" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mali_dt_ids);
+#endif
+
+/* The Mali device driver struct */
+static struct platform_driver mali_platform_driver = {
+       .probe  = mali_probe,
+       .remove = mali_remove,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+       .pm = &mali_dev_ext_pm_ops,
+#endif
+       .driver =
+       {
+               .name   = MALI_GPU_NAME_UTGARD,
+               .owner  = THIS_MODULE,
+               .bus = &platform_bus_type,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+               .pm = &mali_dev_pm_ops,
+               .of_match_table = of_match_ptr(mali_dt_ids),
+#endif
+       },
+};
+
+/* Linux misc device operations (/dev/mali) */
+struct file_operations mali_fops = {
+       .owner = THIS_MODULE,
+       .open = mali_open,
+       .release = mali_release,
+#ifdef HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = mali_ioctl,
+#else
+       .ioctl = mali_ioctl,
+#endif
+       .mmap = mali_mmap
+};
+
+
+#if MALI_ENABLE_CPU_CYCLES
+void mali_init_cpu_time_counters(int reset, int enable_divide_by_64)
+{
+       /* The CPU assembly reference used is: ARM Architecture Reference Manual ARMv7-AR C.b */
+       u32 write_value;
+
+       /* See B4.1.116 PMCNTENSET, Performance Monitors Count Enable Set register, VMSA */
+       /* setting p15 c9 c12 1 to 0x8000000f==CPU_CYCLE_ENABLE |EVENT_3_ENABLE|EVENT_2_ENABLE|EVENT_1_ENABLE|EVENT_0_ENABLE */
+       asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(0x8000000f));
+
+
+       /* See B4.1.117 PMCR, Performance Monitors Control Register. Writing to p15, c9, c12, 0 */
+       write_value = 1<<0; /* Bit 0 set. Enable counters */
+       if (reset) {
+               write_value |= 1<<1; /* Reset event counters */
+               write_value |= 1<<2; /* Reset cycle counter  */
+       }
+       if (enable_divide_by_64) {
+               write_value |= 1<<3; /* Enable the Clock divider by 64 */
+       }
+       write_value |= 1<<4; /* Export enable. Not needed */
+       asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(write_value ));
+
+       /* PMOVSR Overflow Flag Status Register - Clear Clock and Event overflows */
+       asm volatile ("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
+
+
+       /* See B4.1.124 PMUSERENR - setting p15 c9 c14 to 1" */
+       /* User mode access to the Performance Monitors enabled. */
+       /* Lets User space read cpu clock cycles */
+       asm volatile( "mcr p15, 0, %0, c9, c14, 0" :: "r"(1) );
+}
+
+/** A timer function that configures the cycle clock counter on current CPU.
+       The function \a mali_init_cpu_time_counters_on_all_cpus sets up this function
+       to trigger on all Cpus during module load. */
+static void mali_init_cpu_clock_timer_func(unsigned long data)
+{
+       int reset_counters, enable_divide_clock_counter_by_64;
+       int current_cpu = raw_smp_processor_id();
+       unsigned int sample0;
+       unsigned int sample1;
+
+       MALI_IGNORE(data);
+
+       reset_counters= 1;
+       enable_divide_clock_counter_by_64 = 0;
+       mali_init_cpu_time_counters(reset_counters, enable_divide_clock_counter_by_64);
+
+       sample0 = mali_get_cpu_cyclecount();
+       sample1 = mali_get_cpu_cyclecount();
+
+       MALI_DEBUG_PRINT(3, ("Init Cpu %d cycle counter- First two samples: %08x %08x \n", current_cpu, sample0, sample1));
+}
+
+/** A timer functions for storing current time on all cpus.
+    Used for checking if the clocks have similar values or if they are drifting. */
+static void mali_print_cpu_clock_timer_func(unsigned long data)
+{
+       int current_cpu = raw_smp_processor_id();
+       unsigned int sample0;
+
+       MALI_IGNORE(data);
+       sample0 = mali_get_cpu_cyclecount();
+       if ( current_cpu<8 ) {
+               mali_cpu_clock_last_value[current_cpu] = sample0;
+       }
+}
+
+/** Init the performance registers on all CPUs to count clock cycles.
+       For init \a print_only should be 0.
+    If \a print_only is 1, it will intead print the current clock value of all CPUs.*/
+void mali_init_cpu_time_counters_on_all_cpus(int print_only)
+{
+       int i = 0;
+       int cpu_number;
+       int jiffies_trigger;
+       int jiffies_wait;
+
+       jiffies_wait = 2;
+       jiffies_trigger = jiffies + jiffies_wait;
+
+       for ( i=0 ; i < 8 ; i++ ) {
+               init_timer(&mali_init_cpu_clock_timers[i]);
+               if (print_only) mali_init_cpu_clock_timers[i].function = mali_print_cpu_clock_timer_func;
+               else            mali_init_cpu_clock_timers[i].function = mali_init_cpu_clock_timer_func;
+               mali_init_cpu_clock_timers[i].expires = jiffies_trigger ;
+       }
+       cpu_number = cpumask_first(cpu_online_mask);
+       for ( i=0 ; i < 8 ; i++ ) {
+               int next_cpu;
+               add_timer_on(&mali_init_cpu_clock_timers[i], cpu_number);
+               next_cpu = cpumask_next(cpu_number, cpu_online_mask);
+               if (next_cpu >= nr_cpu_ids) break;
+               cpu_number = next_cpu;
+       }
+
+       while (jiffies_wait) jiffies_wait= schedule_timeout_uninterruptible(jiffies_wait);
+
+       for ( i=0 ; i < 8 ; i++ ) {
+               del_timer_sync(&mali_init_cpu_clock_timers[i]);
+       }
+
+       if (print_only) {
+               if ( (0==mali_cpu_clock_last_value[2]) &&  (0==mali_cpu_clock_last_value[3]) ) {
+                       /* Diff can be printed if we want to check if the clocks are in sync
+                       int diff = mali_cpu_clock_last_value[0] - mali_cpu_clock_last_value[1];*/
+                       MALI_DEBUG_PRINT(2, ("CPU cycle counters readout all: %08x %08x\n", mali_cpu_clock_last_value[0], mali_cpu_clock_last_value[1]));
+               } else {
+                       MALI_DEBUG_PRINT(2, ("CPU cycle counters readout all: %08x %08x %08x %08x\n", mali_cpu_clock_last_value[0], mali_cpu_clock_last_value[1], mali_cpu_clock_last_value[2], mali_cpu_clock_last_value[3] ));
+               }
+       }
+}
+#endif
+
+
+int mali_module_init(void)
+{
+       int err = 0;
+
+       MALI_DEBUG_PRINT(2, ("Inserting Mali v%d device driver. \n",_MALI_API_VERSION));
+       MALI_DEBUG_PRINT(2, ("Compiled: %s, time: %s.\n", __DATE__, __TIME__));
+       MALI_DEBUG_PRINT(2, ("Driver revision: %s\n", SVN_REV_STRING));
+
+#if MALI_ENABLE_CPU_CYCLES
+       mali_init_cpu_time_counters_on_all_cpus(0);
+       MALI_DEBUG_PRINT(2, ("CPU cycle counter setup complete\n"));
+       /* Printing the current cpu counters */
+       mali_init_cpu_time_counters_on_all_cpus(1);
+#endif
+
+       MALI_PRINT(("mali_module_init() registering driver\n"));
+
+       err = platform_driver_register(&mali_platform_driver);
+
+       if (0 != err) {
+               MALI_PRINT(("mali_module_init() Failed to register driver (%d)\n", err));
+               mali_platform_device = NULL;
+               return err;
+       }
+
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+       err = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
+       if (0 != err) {
+               /* No biggie if we wheren't able to initialize the profiling */
+               MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
+       }
+#endif
+
+       MALI_PRINT(("Mali device driver loaded\n"));
+
+       return 0; /* Success */
+}
+
+void mali_module_exit(void)
+{
+       MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION));
+
+       MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering driver\n"));
+
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+       _mali_internal_profiling_term();
+#endif
+
+       platform_driver_unregister(&mali_platform_driver);
+
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+       MALI_DEBUG_PRINT(2, ("mali_module_exit() unregistering device\n"));
+       mali_platform_device_unregister(mali_platform_device);
+#endif
+
+       MALI_PRINT(("Mali device driver unloaded\n"));
+}
+
+static int mali_probe(struct platform_device *pdev)
+{
+       int err;
+
+       MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name));
+       
+       if (NULL != mali_platform_device) {
+               /* Already connected to a device, return error */
+               MALI_PRINT_ERROR(("mali_probe(): The Mali driver is already connected with a Mali device."));
+               return -EEXIST;
+       }
+       
+       mali_platform_device = pdev;
+
+       pr_info("mali_platform_device->num_resources = %d\n",mali_platform_device->num_resources);
+
+       {
+               int i = 0;
+               for(i=0;i<mali_platform_device->num_resources;i++)
+               {
+                       pr_info("mali_platform_device->resource[%d].start = 0x%08x\n",i,mali_platform_device->resource[i].start);
+               }
+       }
+       
+       
+#if defined(MALI_FAKE_PLATFORM_DEVICE)
+       MALI_DEBUG_PRINT(2, ("mali_module_init() registering device\n"));
+       err = mali_platform_device_register(mali_platform_device);
+       if (0 != err) 
+       {
+               mali_platform_device_unregister(mali_platform_device);
+               return err;
+       }
+#endif
+
+       if (_MALI_OSK_ERR_OK == _mali_osk_wq_init()) {
+               /* Initialize the Mali GPU HW specified by pdev */
+               if (_MALI_OSK_ERR_OK == mali_initialize_subsystems()) {
+                       /* Register a misc device (so we are accessible from user space) */
+                       err = mali_miscdevice_register(pdev);
+                       if (0 == err) {
+                               /* Setup sysfs entries */
+                               err = mali_sysfs_register(mali_dev_name);
+                               if (0 == err) {
+                                       MALI_DEBUG_PRINT(2, ("mali_probe(): Successfully initialized driver for platform device %s\n", pdev->name));
+                                       return 0;
+                               } else {
+                                       MALI_PRINT_ERROR(("mali_probe(): failed to register sysfs entries"));
+                               }
+                               mali_miscdevice_unregister();
+                       } else {
+                               MALI_PRINT_ERROR(("mali_probe(): failed to register Mali misc device."));
+                       }
+                       mali_terminate_subsystems();
+               } else {
+                       MALI_PRINT_ERROR(("mali_probe(): Failed to initialize Mali device driver."));
+               }
+               _mali_osk_wq_term();
+       }
+
+       mali_platform_device = NULL;
+       return -EFAULT;
+}
+
+static int mali_remove(struct platform_device *pdev)
+{
+       MALI_DEBUG_PRINT(2, ("mali_remove() called for platform device %s\n", pdev->name));
+       mali_sysfs_unregister();
+       mali_miscdevice_unregister();
+       mali_terminate_subsystems();
+       _mali_osk_wq_term();
+       mali_platform_device = NULL;
+       return 0;
+}
+
+static int mali_miscdevice_register(struct platform_device *pdev)
+{
+       int err;
+
+       mali_miscdevice.minor = MISC_DYNAMIC_MINOR;
+       mali_miscdevice.name = mali_dev_name;
+       mali_miscdevice.fops = &mali_fops;
+       mali_miscdevice.parent = get_device(&pdev->dev);
+
+       err = misc_register(&mali_miscdevice);
+       if (0 != err) {
+               MALI_PRINT_ERROR(("Failed to register misc device, misc_register() returned %d\n", err));
+       }
+
+       return err;
+}
+
+static void mali_miscdevice_unregister(void)
+{
+       misc_deregister(&mali_miscdevice);
+}
+
+static int mali_driver_suspend_scheduler(struct device *dev)
+{
+       mali_pm_os_suspend();
+       return 0;
+}
+
+static int mali_driver_resume_scheduler(struct device *dev)
+{
+       mali_pm_os_resume();
+       return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int mali_driver_runtime_suspend(struct device *dev)
+{
+       mali_pm_runtime_suspend();
+       return 0;
+}
+
+static int mali_driver_runtime_resume(struct device *dev)
+{
+       mali_pm_runtime_resume();
+       return 0;
+}
+
+static int mali_driver_runtime_idle(struct device *dev)
+{
+       /* Nothing to do */
+       return 0;
+}
+#endif
+
+static int mali_open(struct inode *inode, struct file *filp)
+{
+       struct mali_session_data * session_data;
+       _mali_osk_errcode_t err;
+
+       /* input validation */
+       if (mali_miscdevice.minor != iminor(inode)) {
+               MALI_PRINT_ERROR(("mali_open() Minor does not match\n"));
+               return -ENODEV;
+       }
+
+       /* allocated struct to track this session */
+       err = _mali_ukk_open((void **)&session_data);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       /* initialize file pointer */
+       filp->f_pos = 0;
+
+       /* link in our session data */
+       filp->private_data = (void*)session_data;
+
+       return 0;
+}
+
+static int mali_release(struct inode *inode, struct file *filp)
+{
+       _mali_osk_errcode_t err;
+
+       /* input validation */
+       if (mali_miscdevice.minor != iminor(inode)) {
+               MALI_PRINT_ERROR(("mali_release() Minor does not match\n"));
+               return -ENODEV;
+       }
+
+       err = _mali_ukk_close((void **)&filp->private_data);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       return 0;
+}
+
+int map_errcode( _mali_osk_errcode_t err )
+{
+       switch(err) {
+       case _MALI_OSK_ERR_OK :
+               return 0;
+       case _MALI_OSK_ERR_FAULT:
+               return -EFAULT;
+       case _MALI_OSK_ERR_INVALID_FUNC:
+               return -ENOTTY;
+       case _MALI_OSK_ERR_INVALID_ARGS:
+               return -EINVAL;
+       case _MALI_OSK_ERR_NOMEM:
+               return -ENOMEM;
+       case _MALI_OSK_ERR_TIMEOUT:
+               return -ETIMEDOUT;
+       case _MALI_OSK_ERR_RESTARTSYSCALL:
+               return -ERESTARTSYS;
+       case _MALI_OSK_ERR_ITEM_NOT_FOUND:
+               return -ENOENT;
+       default:
+               return -EFAULT;
+       }
+}
+
+#ifdef HAVE_UNLOCKED_IOCTL
+static long mali_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#else
+static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+       int err;
+       struct mali_session_data *session_data;
+
+#ifndef HAVE_UNLOCKED_IOCTL
+       /* inode not used */
+       (void)inode;
+#endif
+
+       MALI_DEBUG_PRINT(7, ("Ioctl received 0x%08X 0x%08lX\n", cmd, arg));
+
+       session_data = (struct mali_session_data *)filp->private_data;
+       if (NULL == session_data) {
+               MALI_DEBUG_PRINT(7, ("filp->private_data was NULL\n"));
+               return -ENOTTY;
+       }
+
+       if (NULL == (void *)arg) {
+               MALI_DEBUG_PRINT(7, ("arg was NULL\n"));
+               return -ENOTTY;
+       }
+
+       switch(cmd) {
+       case MALI_IOC_WAIT_FOR_NOTIFICATION:
+               err = wait_for_notification_wrapper(session_data, (_mali_uk_wait_for_notification_s __user *)arg);
+               break;
+
+       case MALI_IOC_GET_API_VERSION:
+               err = get_api_version_wrapper(session_data, (_mali_uk_get_api_version_s __user *)arg);
+               break;
+
+       case MALI_IOC_POST_NOTIFICATION:
+               err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg);
+               break;
+
+               case MALI_IOC_GET_MALI_VERSION_IN_RK30:
+                       err = get_mali_version_in_rk30_wrapper(session_data,(_mali_uk_get_mali_version_in_rk30_s __user *)arg);
+                       break;
+       case MALI_IOC_GET_USER_SETTINGS:
+               err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
+               break;
+
+       case MALI_IOC_REQUEST_HIGH_PRIORITY:
+               err = request_high_priority_wrapper(session_data, (_mali_uk_request_high_priority_s __user *)arg);
+               break;
+
+#if defined(CONFIG_MALI400_PROFILING)
+       case MALI_IOC_PROFILING_START:
+               err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg);
+               break;
+
+       case MALI_IOC_PROFILING_ADD_EVENT:
+               err = profiling_add_event_wrapper(session_data, (_mali_uk_profiling_add_event_s __user *)arg);
+               break;
+
+       case MALI_IOC_PROFILING_STOP:
+               err = profiling_stop_wrapper(session_data, (_mali_uk_profiling_stop_s __user *)arg);
+               break;
+
+       case MALI_IOC_PROFILING_GET_EVENT:
+               err = profiling_get_event_wrapper(session_data, (_mali_uk_profiling_get_event_s __user *)arg);
+               break;
+
+       case MALI_IOC_PROFILING_CLEAR:
+               err = profiling_clear_wrapper(session_data, (_mali_uk_profiling_clear_s __user *)arg);
+               break;
+
+       case MALI_IOC_PROFILING_GET_CONFIG:
+               /* Deprecated: still compatible with get_user_settings */
+               err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
+               break;
+
+       case MALI_IOC_PROFILING_REPORT_SW_COUNTERS:
+               err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg);
+               break;
+
+#else
+
+       case MALI_IOC_PROFILING_START:              /* FALL-THROUGH */
+       case MALI_IOC_PROFILING_ADD_EVENT:          /* FALL-THROUGH */
+       case MALI_IOC_PROFILING_STOP:               /* FALL-THROUGH */
+       case MALI_IOC_PROFILING_GET_EVENT:          /* FALL-THROUGH */
+       case MALI_IOC_PROFILING_CLEAR:              /* FALL-THROUGH */
+       case MALI_IOC_PROFILING_GET_CONFIG:         /* FALL-THROUGH */
+       case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */
+               MALI_DEBUG_PRINT(2, ("Profiling not supported\n"));
+               err = -ENOTTY;
+               break;
+
+#endif
+
+       case MALI_IOC_MEM_WRITE_SAFE:
+               err = mem_write_safe_wrapper(session_data, (_mali_uk_mem_write_safe_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_MAP_EXT:
+               err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_UNMAP_EXT:
+               err = mem_unmap_ext_wrapper(session_data, (_mali_uk_unmap_external_mem_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE:
+               err = mem_query_mmu_page_table_dump_size_wrapper(session_data, (_mali_uk_query_mmu_page_table_dump_size_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE:
+               err = mem_dump_mmu_page_table_wrapper(session_data, (_mali_uk_dump_mmu_page_table_s __user *)arg);
+               break;
+
+#if defined(CONFIG_MALI400_UMP)
+
+       case MALI_IOC_MEM_ATTACH_UMP:
+               err = mem_attach_ump_wrapper(session_data, (_mali_uk_attach_ump_mem_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_RELEASE_UMP:
+               err = mem_release_ump_wrapper(session_data, (_mali_uk_release_ump_mem_s __user *)arg);
+               break;
+
+#else
+
+       case MALI_IOC_MEM_ATTACH_UMP:
+       case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */
+               MALI_DEBUG_PRINT(2, ("UMP not supported\n"));
+               err = -ENOTTY;
+               break;
+#endif
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+       case MALI_IOC_MEM_ATTACH_DMA_BUF:
+               err = mali_attach_dma_buf(session_data, (_mali_uk_attach_dma_buf_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_RELEASE_DMA_BUF:
+               err = mali_release_dma_buf(session_data, (_mali_uk_release_dma_buf_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_DMA_BUF_GET_SIZE:
+               err = mali_dma_buf_get_size(session_data, (_mali_uk_dma_buf_get_size_s __user *)arg);
+               break;
+#else
+
+       case MALI_IOC_MEM_ATTACH_DMA_BUF:   /* FALL-THROUGH */
+       case MALI_IOC_MEM_RELEASE_DMA_BUF:  /* FALL-THROUGH */
+       case MALI_IOC_MEM_DMA_BUF_GET_SIZE: /* FALL-THROUGH */
+               MALI_DEBUG_PRINT(2, ("DMA-BUF not supported\n"));
+               err = -ENOTTY;
+               break;
+#endif
+
+       case MALI_IOC_PP_START_JOB:
+               err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg);
+               break;
+
+       case MALI_IOC_PP_AND_GP_START_JOB:
+               err = pp_and_gp_start_job_wrapper(session_data, (_mali_uk_pp_and_gp_start_job_s __user *)arg);
+               break;
+
+       case MALI_IOC_PP_NUMBER_OF_CORES_GET:
+               err = pp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_pp_number_of_cores_s __user *)arg);
+               break;
+
+       case MALI_IOC_PP_CORE_VERSION_GET:
+               err = pp_get_core_version_wrapper(session_data, (_mali_uk_get_pp_core_version_s __user *)arg);
+               break;
+
+       case MALI_IOC_PP_DISABLE_WB:
+               err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg);
+               break;
+
+       case MALI_IOC_GP2_START_JOB:
+               err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
+               break;
+
+       case MALI_IOC_GP2_NUMBER_OF_CORES_GET:
+               err = gp_get_number_of_cores_wrapper(session_data, (_mali_uk_get_gp_number_of_cores_s __user *)arg);
+               break;
+
+       case MALI_IOC_GP2_CORE_VERSION_GET:
+               err = gp_get_core_version_wrapper(session_data, (_mali_uk_get_gp_core_version_s __user *)arg);
+               break;
+
+       case MALI_IOC_GP2_SUSPEND_RESPONSE:
+               err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg);
+               break;
+
+       case MALI_IOC_VSYNC_EVENT_REPORT:
+               err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
+               break;
+
+       case MALI_IOC_TIMELINE_GET_LATEST_POINT:
+               err = timeline_get_latest_point_wrapper(session_data, (_mali_uk_timeline_get_latest_point_s __user *)arg);
+               break;
+       case MALI_IOC_TIMELINE_WAIT:
+               err = timeline_wait_wrapper(session_data, (_mali_uk_timeline_wait_s __user *)arg);
+               break;
+       case MALI_IOC_TIMELINE_CREATE_SYNC_FENCE:
+               err = timeline_create_sync_fence_wrapper(session_data, (_mali_uk_timeline_create_sync_fence_s __user *)arg);
+               break;
+       case MALI_IOC_SOFT_JOB_START:
+               err = soft_job_start_wrapper(session_data, (_mali_uk_soft_job_start_s __user *)arg);
+               break;
+       case MALI_IOC_SOFT_JOB_SIGNAL:
+               err = soft_job_signal_wrapper(session_data, (_mali_uk_soft_job_signal_s __user *)arg);
+               break;
+
+       case MALI_IOC_MEM_INIT: /* Fallthrough */
+       case MALI_IOC_MEM_TERM: /* Fallthrough */
+               MALI_DEBUG_PRINT(2, ("Deprecated ioctls called\n"));
+               err = -ENOTTY;
+               break;
+
+       case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */
+       case MALI_IOC_MEM_FREE_BIG_BLOCK:
+               MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n"));
+               err = -ENOTTY;
+               break;
+
+       default:
+               MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg));
+               err = -ENOTTY;
+       };
+
+       return err;
+}
+
+
+module_init(mali_module_init);
+module_exit(mali_module_exit);
+
+MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
+MODULE_AUTHOR("ARM Ltd.");
+MODULE_VERSION(SVN_REV_STRING);
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.h b/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.h
new file mode 100755 (executable)
index 0000000..149e435
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_KERNEL_LINUX_H__
+#define __MALI_KERNEL_LINUX_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/cdev.h>     /* character device definitions */
+#include "mali_kernel_license.h"
+#include "mali_osk_types.h"
+
+extern struct platform_device *mali_platform_device;
+
+#if MALI_LICENSE_IS_GPL
+/* Defined in mali_osk_irq.h */
+extern struct workqueue_struct * mali_wq_normal;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_LINUX_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.c b/drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.c
new file mode 100755 (executable)
index 0000000..973fb90
--- /dev/null
@@ -0,0 +1,1390 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+
+/**
+ * @file mali_kernel_sysfs.c
+ * Implementation of some sysfs data exports
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include "mali_kernel_license.h"
+#include "mali_kernel_common.h"
+#include "mali_ukk.h"
+
+#if MALI_LICENSE_IS_GPL
+
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_sysfs.h"
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+#include <linux/slab.h>
+#include "mali_osk_profiling.h"
+#endif
+
+#include <linux/mali/mali_utgard.h>
+#include "mali_pm.h"
+#include "mali_pmu.h"
+#include "mali_group.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_l2_cache.h"
+#include "mali_hw_core.h"
+#include "mali_kernel_core.h"
+#include "mali_user_settings_db.h"
+#include "mali_profiling_internal.h"
+#include "mali_gp_job.h"
+#include "mali_pp_job.h"
+#include "mali_pp_scheduler.h"
+
+#define PRIVATE_DATA_COUNTER_MAKE_GP(src) (src)
+#define PRIVATE_DATA_COUNTER_MAKE_PP(src) ((1 << 24) | src)
+#define PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(src, sub_job) ((1 << 24) | (1 << 16) | (sub_job << 8) | src)
+#define PRIVATE_DATA_COUNTER_IS_PP(a) ((((a) >> 24) & 0xFF) ? MALI_TRUE : MALI_FALSE)
+#define PRIVATE_DATA_COUNTER_GET_SRC(a) (a & 0xFF)
+#define PRIVATE_DATA_COUNTER_IS_SUB_JOB(a) ((((a) >> 16) & 0xFF) ? MALI_TRUE : MALI_FALSE)
+#define PRIVATE_DATA_COUNTER_GET_SUB_JOB(a) (((a) >> 8) & 0xFF)
+
+#define POWER_BUFFER_SIZE 3
+
+static struct dentry *mali_debugfs_dir = NULL;
+
+typedef enum {
+       _MALI_DEVICE_SUSPEND,
+       _MALI_DEVICE_RESUME,
+       _MALI_DEVICE_DVFS_PAUSE,
+       _MALI_DEVICE_DVFS_RESUME,
+       _MALI_MAX_EVENTS
+} _mali_device_debug_power_events;
+
+static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
+       [_MALI_DEVICE_SUSPEND] = "suspend",
+       [_MALI_DEVICE_RESUME] = "resume",
+       [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
+       [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
+};
+
+static mali_bool power_always_on_enabled = MALI_FALSE;
+
+static int open_copy_private_data(struct inode *inode, struct file *filp)
+{
+       filp->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t group_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+       struct mali_group *group;
+
+       group = (struct mali_group *)filp->private_data;
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       r = sprintf(buffer, "%u\n", mali_group_is_enabled(group) ? 1 : 0);
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static ssize_t group_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+       unsigned long val;
+       struct mali_group *group;
+
+       group = (struct mali_group *)filp->private_data;
+       MALI_DEBUG_ASSERT_POINTER(group);
+
+       if (count >= sizeof(buffer)) {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count)) {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       r = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != r) {
+               return -EINVAL;
+       }
+
+       switch (val) {
+       case 1:
+               mali_group_enable(group);
+               break;
+       case 0:
+               mali_group_disable(group);
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       *offp += count;
+       return count;
+}
+
+static const struct file_operations group_enabled_fops = {
+       .owner = THIS_MODULE,
+       .open  = open_copy_private_data,
+       .read = group_enabled_read,
+       .write = group_enabled_write,
+};
+
+static ssize_t hw_core_base_addr_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+       struct mali_hw_core *hw_core;
+
+       hw_core = (struct mali_hw_core *)filp->private_data;
+       MALI_DEBUG_ASSERT_POINTER(hw_core);
+
+       r = sprintf(buffer, "0x%08X\n", hw_core->phys_addr);
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static const struct file_operations hw_core_base_addr_fops = {
+       .owner = THIS_MODULE,
+       .open  = open_copy_private_data,
+       .read = hw_core_base_addr_read,
+};
+
+static ssize_t profiling_counter_src_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((u32)filp->private_data);
+       u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((u32)filp->private_data);
+       mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((u32)filp->private_data);
+       u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((u32)filp->private_data);
+       char buf[64];
+       int r;
+       u32 val;
+
+       if (MALI_TRUE == is_pp) {
+               /* PP counter */
+               if (MALI_TRUE == is_sub_job) {
+                       /* Get counter for a particular sub job */
+                       if (0 == src_id) {
+                               val = mali_pp_job_get_pp_counter_sub_job_src0(sub_job);
+                       } else {
+                               val = mali_pp_job_get_pp_counter_sub_job_src1(sub_job);
+                       }
+               } else {
+                       /* Get default counter for all PP sub jobs */
+                       if (0 == src_id) {
+                               val = mali_pp_job_get_pp_counter_global_src0();
+                       } else {
+                               val = mali_pp_job_get_pp_counter_global_src1();
+                       }
+               }
+       } else {
+               /* GP counter */
+               if (0 == src_id) {
+                       val = mali_gp_job_get_gp_counter_src0();
+               } else {
+                       val = mali_gp_job_get_gp_counter_src1();
+               }
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER == val) {
+               r = sprintf(buf, "-1\n");
+       } else {
+               r = sprintf(buf, "%u\n", val);
+       }
+
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t profiling_counter_src_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((u32)filp->private_data);
+       u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((u32)filp->private_data);
+       mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((u32)filp->private_data);
+       u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((u32)filp->private_data);
+       char buf[64];
+       long val;
+       int ret;
+
+       if (cnt >= sizeof(buf)) {
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&buf, ubuf, cnt)) {
+               return -EFAULT;
+       }
+
+       buf[cnt] = 0;
+
+       ret = strict_strtol(buf, 10, &val);
+       if (ret < 0) {
+               return ret;
+       }
+
+       if (val < 0) {
+               /* any negative input will disable counter */
+               val = MALI_HW_CORE_NO_COUNTER;
+       }
+
+       if (MALI_TRUE == is_pp) {
+               /* PP counter */
+               if (MALI_TRUE == is_sub_job) {
+                       /* Set counter for a particular sub job */
+                       if (0 == src_id) {
+                               mali_pp_job_set_pp_counter_sub_job_src0(sub_job, (u32)val);
+                       } else {
+                               mali_pp_job_set_pp_counter_sub_job_src1(sub_job, (u32)val);
+                       }
+               } else {
+                       /* Set default counter for all PP sub jobs */
+                       if (0 == src_id) {
+                               mali_pp_job_set_pp_counter_global_src0((u32)val);
+                       } else {
+                               mali_pp_job_set_pp_counter_global_src1((u32)val);
+                       }
+               }
+       } else {
+               /* GP counter */
+               if (0 == src_id) {
+                       mali_gp_job_set_gp_counter_src0((u32)val);
+               } else {
+                       mali_gp_job_set_gp_counter_src1((u32)val);
+               }
+       }
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static const struct file_operations profiling_counter_src_fops = {
+       .owner = THIS_MODULE,
+       .open  = open_copy_private_data,
+       .read  = profiling_counter_src_read,
+       .write = profiling_counter_src_write,
+};
+
+static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+       char buf[64];
+       int r;
+       u32 val;
+       struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
+
+       if (0 == src_id) {
+               val = mali_l2_cache_core_get_counter_src0(l2_core);
+       } else {
+               val = mali_l2_cache_core_get_counter_src1(l2_core);
+       }
+
+       if (MALI_HW_CORE_NO_COUNTER == val) {
+               r = sprintf(buf, "-1\n");
+       } else {
+               r = sprintf(buf, "%u\n", val);
+       }
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+       struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
+       char buf[64];
+       long val;
+       int ret;
+
+       if (cnt >= sizeof(buf)) {
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&buf, ubuf, cnt)) {
+               return -EFAULT;
+       }
+
+       buf[cnt] = 0;
+
+       ret = strict_strtol(buf, 10, &val);
+       if (ret < 0) {
+               return ret;
+       }
+
+       if (val < 0) {
+               /* any negative input will disable counter */
+               val = MALI_HW_CORE_NO_COUNTER;
+       }
+
+       if (0 == src_id) {
+               mali_l2_cache_core_set_counter_src0(l2_core, (u32)val);
+       } else {
+               mali_l2_cache_core_set_counter_src1(l2_core, (u32)val);
+       }
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+       char buf[64];
+       long val;
+       int ret;
+       u32 l2_id;
+       struct mali_l2_cache_core *l2_cache;
+
+       if (cnt >= sizeof(buf)) {
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&buf, ubuf, cnt)) {
+               return -EFAULT;
+       }
+
+       buf[cnt] = 0;
+
+       ret = strict_strtol(buf, 10, &val);
+       if (ret < 0) {
+               return ret;
+       }
+
+       if (val < 0) {
+               /* any negative input will disable counter */
+               val = MALI_HW_CORE_NO_COUNTER;
+       }
+
+       l2_id = 0;
+       l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+       while (NULL != l2_cache) {
+               if (0 == src_id) {
+                       mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val);
+               } else {
+                       mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val);
+               }
+
+               /* try next L2 */
+               l2_id++;
+               l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+       }
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
+}
+
+static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
+}
+
+static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
+}
+
+static const struct file_operations l2_l2x_counter_src0_fops = {
+       .owner = THIS_MODULE,
+       .open  = open_copy_private_data,
+       .read  = l2_l2x_counter_src0_read,
+       .write = l2_l2x_counter_src0_write,
+};
+
+static const struct file_operations l2_l2x_counter_src1_fops = {
+       .owner = THIS_MODULE,
+       .open  = open_copy_private_data,
+       .read  = l2_l2x_counter_src1_read,
+       .write = l2_l2x_counter_src1_write,
+};
+
+static const struct file_operations l2_all_counter_src0_fops = {
+       .owner = THIS_MODULE,
+       .write = l2_all_counter_src0_write,
+};
+
+static const struct file_operations l2_all_counter_src1_fops = {
+       .owner = THIS_MODULE,
+       .write = l2_all_counter_src1_write,
+};
+
+static ssize_t power_always_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       unsigned long val;
+       int ret;
+       char buf[32];
+
+       cnt = min(cnt, sizeof(buf) - 1);
+       if (copy_from_user(buf, ubuf, cnt)) {
+               return -EFAULT;
+       }
+       buf[cnt] = '\0';
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (0 != ret) {
+               return ret;
+       }
+
+       /* Update setting (not exactly thread safe) */
+       if (1 == val && MALI_FALSE == power_always_on_enabled) {
+               power_always_on_enabled = MALI_TRUE;
+               _mali_osk_pm_dev_ref_add();
+       } else if (0 == val && MALI_TRUE == power_always_on_enabled) {
+               power_always_on_enabled = MALI_FALSE;
+               _mali_osk_pm_dev_ref_dec();
+       }
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static ssize_t power_always_on_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       if (MALI_TRUE == power_always_on_enabled) {
+               return simple_read_from_buffer(ubuf, cnt, ppos, "1\n", 2);
+       } else {
+               return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
+       }
+}
+
+static const struct file_operations power_always_on_fops = {
+       .owner = THIS_MODULE,
+       .read  = power_always_on_read,
+       .write = power_always_on_write,
+};
+
+static ssize_t power_power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+
+       if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND]))) {
+               mali_pm_os_suspend();
+
+       } else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME]))) {
+               mali_pm_os_resume();
+       } else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE]))) {
+               mali_dev_pause();
+       } else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME]))) {
+               mali_dev_resume();
+       }
+       *ppos += cnt;
+       return cnt;
+}
+
+static loff_t power_power_events_seek(struct file *file, loff_t offset, int orig)
+{
+       file->f_pos = offset;
+       return 0;
+}
+
+static const struct file_operations power_power_events_fops = {
+       .owner = THIS_MODULE,
+       .write = power_power_events_write,
+       .llseek = power_power_events_seek,
+};
+
+#if MALI_STATE_TRACKING
+static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
+{
+       u32 len = 0;
+       u32 size;
+       char *buf;
+
+       size = seq_get_buf(seq_file, &buf);
+
+       if(!size) {
+               return -ENOMEM;
+       }
+
+       /* Create the internal state dump. */
+       len  = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING);
+       len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
+
+       len += _mali_kernel_core_dump_state(buf + len, size - len);
+
+       seq_commit(seq_file, len);
+
+       return 0;
+}
+
+static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mali_seq_internal_state_show, NULL);
+}
+
+static const struct file_operations mali_seq_internal_state_fops = {
+       .owner = THIS_MODULE,
+       .open = mali_seq_internal_state_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+#endif /* MALI_STATE_TRACKING */
+
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       int r;
+
+       r = sprintf(buf, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       unsigned long val;
+       int ret;
+
+       if (cnt >= sizeof(buf)) {
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&buf, ubuf, cnt)) {
+               return -EFAULT;
+       }
+
+       buf[cnt] = 0;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret < 0) {
+               return ret;
+       }
+
+       if (val != 0) {
+               u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
+
+               /* check if we are already recording */
+               if (MALI_TRUE == _mali_internal_profiling_is_recording()) {
+                       MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
+                       return -EFAULT;
+               }
+
+               /* check if we need to clear out an old recording first */
+               if (MALI_TRUE == _mali_internal_profiling_have_recording()) {
+                       if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear()) {
+                               MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
+                               return -EFAULT;
+                       }
+               }
+
+               /* start recording profiling data */
+               if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) {
+                       MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
+                       return -EFAULT;
+               }
+
+               MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
+       } else {
+               /* stop recording profiling data */
+               u32 count = 0;
+               if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) {
+                       MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
+                       return -EFAULT;
+               }
+
+               MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
+       }
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static const struct file_operations profiling_record_fops = {
+       .owner = THIS_MODULE,
+       .read  = profiling_record_read,
+       .write = profiling_record_write,
+};
+
+static void *profiling_events_start(struct seq_file *s, loff_t *pos)
+{
+       loff_t *spos;
+
+       /* check if we have data avaiable */
+       if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
+               return NULL;
+       }
+
+       spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
+       if (NULL == spos) {
+               return NULL;
+       }
+
+       *spos = *pos;
+       return spos;
+}
+
+static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       loff_t *spos = v;
+
+       /* check if we have data avaiable */
+       if (MALI_TRUE != _mali_internal_profiling_have_recording()) {
+               return NULL;
+       }
+
+       /* check if the next entry actually is avaiable */
+       if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) {
+               return NULL;
+       }
+
+       *pos = ++*spos;
+       return spos;
+}
+
+static void profiling_events_stop(struct seq_file *s, void *v)
+{
+       kfree(v);
+}
+
+static int profiling_events_show(struct seq_file *seq_file, void *v)
+{
+       loff_t *spos = v;
+       u32 index;
+       u64 timestamp;
+       u32 event_id;
+       u32 data[5];
+
+       index = (u32)*spos;
+
+       /* Retrieve all events */
+       if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data)) {
+               seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
+               return 0;
+       }
+
+       return 0;
+}
+
+static int profiling_events_show_human_readable(struct seq_file *seq_file, void *v)
+{
+#define MALI_EVENT_ID_IS_HW(event_id) (((event_id & 0x00FF0000) >= MALI_PROFILING_EVENT_CHANNEL_GP0) && ((event_id & 0x00FF0000) <= MALI_PROFILING_EVENT_CHANNEL_PP7))
+
+       static u64 start_time = 0;
+       loff_t *spos = v;
+       u32 index;
+       u64 timestamp;
+       u32 event_id;
+       u32 data[5];
+
+       index = (u32)*spos;
+
+       /* Retrieve all events */
+       if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, &timestamp, &event_id, data)) {
+               seq_printf(seq_file, "%llu %u %u %u %u %u %u # ", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
+
+               if (0 == index) {
+                       start_time = timestamp;
+               }
+
+               seq_printf(seq_file, "[%06u] ", index);
+
+               switch(event_id & 0x0F000000) {
+               case MALI_PROFILING_EVENT_TYPE_SINGLE:
+                       seq_printf(seq_file, "SINGLE | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_START:
+                       seq_printf(seq_file, "START | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_STOP:
+                       seq_printf(seq_file, "STOP | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_SUSPEND:
+                       seq_printf(seq_file, "SUSPEND | ");
+                       break;
+               case MALI_PROFILING_EVENT_TYPE_RESUME:
+                       seq_printf(seq_file, "RESUME | ");
+                       break;
+               default:
+                       seq_printf(seq_file, "0x%01X | ", (event_id & 0x0F000000) >> 24);
+                       break;
+               }
+
+               switch(event_id & 0x00FF0000) {
+               case MALI_PROFILING_EVENT_CHANNEL_SOFTWARE:
+                       seq_printf(seq_file, "SW | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_GP0:
+                       seq_printf(seq_file, "GP0 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP0:
+                       seq_printf(seq_file, "PP0 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP1:
+                       seq_printf(seq_file, "PP1 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP2:
+                       seq_printf(seq_file, "PP2 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP3:
+                       seq_printf(seq_file, "PP3 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP4:
+                       seq_printf(seq_file, "PP4 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP5:
+                       seq_printf(seq_file, "PP5 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP6:
+                       seq_printf(seq_file, "PP6 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_PP7:
+                       seq_printf(seq_file, "PP7 | ");
+                       break;
+               case MALI_PROFILING_EVENT_CHANNEL_GPU:
+                       seq_printf(seq_file, "GPU | ");
+                       break;
+               default:
+                       seq_printf(seq_file, "0x%02X | ", (event_id & 0x00FF0000) >> 16);
+                       break;
+               }
+
+               if (MALI_EVENT_ID_IS_HW(event_id)) {
+                       if (((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_START) || ((event_id & 0x0F000000) == MALI_PROFILING_EVENT_TYPE_STOP)) {
+                               switch(event_id & 0x0000FFFF) {
+                               case MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL:
+                                       seq_printf(seq_file, "PHYSICAL | ");
+                                       break;
+                               case MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL:
+                                       seq_printf(seq_file, "VIRTUAL | ");
+                                       break;
+                               default:
+                                       seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
+                                       break;
+                               }
+                       } else {
+                               seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
+                       }
+               } else {
+                       seq_printf(seq_file, "0x%04X | ", event_id & 0x0000FFFF);
+               }
+
+               seq_printf(seq_file, "T0 + 0x%016llX\n", timestamp - start_time);
+
+               return 0;
+       }
+
+       return 0;
+}
+
+static const struct seq_operations profiling_events_seq_ops = {
+       .start = profiling_events_start,
+       .next  = profiling_events_next,
+       .stop  = profiling_events_stop,
+       .show  = profiling_events_show
+};
+
+static int profiling_events_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &profiling_events_seq_ops);
+}
+
+static const struct file_operations profiling_events_fops = {
+       .owner = THIS_MODULE,
+       .open = profiling_events_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+static const struct seq_operations profiling_events_human_readable_seq_ops = {
+       .start = profiling_events_start,
+       .next  = profiling_events_next,
+       .stop  = profiling_events_stop,
+       .show  = profiling_events_show_human_readable
+};
+
+static int profiling_events_human_readable_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &profiling_events_human_readable_seq_ops);
+}
+
+static const struct file_operations profiling_events_human_readable_fops = {
+       .owner = THIS_MODULE,
+       .open = profiling_events_human_readable_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+#endif
+
+static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 mem = _mali_ukk_report_memory_usage();
+
+       r = snprintf(buf, 64, "%u\n", mem);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static const struct file_operations memory_usage_fops = {
+       .owner = THIS_MODULE,
+       .read = memory_used_read,
+};
+
+static ssize_t utilization_gp_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 uval= _mali_ukk_utilization_gp_pp();
+
+       r = snprintf(buf, 64, "%u\n", uval);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t utilization_gp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 uval= _mali_ukk_utilization_gp();
+
+       r = snprintf(buf, 64, "%u\n", uval);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t utilization_pp_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 uval= _mali_ukk_utilization_pp();
+
+       r = snprintf(buf, 64, "%u\n", uval);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+
+static const struct file_operations utilization_gp_pp_fops = {
+       .owner = THIS_MODULE,
+       .read = utilization_gp_pp_read,
+};
+
+static const struct file_operations utilization_gp_fops = {
+       .owner = THIS_MODULE,
+       .read = utilization_gp_read,
+};
+
+static const struct file_operations utilization_pp_fops = {
+       .owner = THIS_MODULE,
+       .read = utilization_pp_read,
+};
+
+static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       unsigned long val;
+       int ret;
+       _mali_uk_user_setting_t setting;
+       char buf[32];
+
+       cnt = min(cnt, sizeof(buf) - 1);
+       if (copy_from_user(buf, ubuf, cnt)) {
+               return -EFAULT;
+       }
+       buf[cnt] = '\0';
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (0 != ret) {
+               return ret;
+       }
+
+       /* Update setting */
+       setting = (_mali_uk_user_setting_t)(filp->private_data);
+       mali_set_user_setting(setting, val);
+
+       *ppos += cnt;
+       return cnt;
+}
+
+static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 value;
+       _mali_uk_user_setting_t setting;
+
+       setting = (_mali_uk_user_setting_t)(filp->private_data);
+       value = mali_get_user_setting(setting);
+
+       r = snprintf(buf, 64, "%u\n", value);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static const struct file_operations user_settings_fops = {
+       .owner = THIS_MODULE,
+       .open = open_copy_private_data,
+       .read = user_settings_read,
+       .write = user_settings_write,
+};
+
+static int mali_sysfs_user_settings_register(void)
+{
+       struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
+
+       if (mali_user_settings_dir != NULL) {
+               int i;
+               for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++) {
+                       debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops);
+               }
+       }
+
+       return 0;
+}
+
+static ssize_t pmu_power_down_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+       struct mali_pmu_core *pmu;
+       _mali_osk_errcode_t err;
+
+       if (count >= sizeof(buffer)) {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count)) {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret) {
+               return -EINVAL;
+       }
+
+       pmu = mali_pmu_get_global_pmu_core();
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+
+       err = mali_pmu_power_down(pmu, val);
+       if (_MALI_OSK_ERR_OK != err) {
+               return -EINVAL;
+       }
+
+       *offp += count;
+       return count;
+}
+
+static ssize_t pmu_power_up_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+       struct mali_pmu_core *pmu;
+       _mali_osk_errcode_t err;
+
+       if (count >= sizeof(buffer)) {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count)) {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret) {
+               return -EINVAL;
+       }
+
+       pmu = mali_pmu_get_global_pmu_core();
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+
+       err = mali_pmu_power_up(pmu, val);
+       if (_MALI_OSK_ERR_OK != err) {
+               return -EINVAL;
+       }
+
+       *offp += count;
+       return count;
+}
+
+static const struct file_operations pmu_power_down_fops = {
+       .owner = THIS_MODULE,
+       .write = pmu_power_down_write,
+};
+
+static const struct file_operations pmu_power_up_fops = {
+       .owner = THIS_MODULE,
+       .write = pmu_power_up_write,
+};
+
+static ssize_t pp_num_cores_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+
+       if (count >= sizeof(buffer)) {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count)) {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret) {
+               return -EINVAL;
+       }
+
+       ret = mali_pp_scheduler_set_perf_level(val, MALI_TRUE); /* override even if core scaling is disabled */
+       if (ret) {
+               return ret;
+       }
+
+       *offp += count;
+       return count;
+}
+
+static ssize_t pp_num_cores_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+
+       r = sprintf(buffer, "%u\n", mali_pp_scheduler_get_num_cores_enabled());
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static const struct file_operations pp_num_cores_enabled_fops = {
+       .owner = THIS_MODULE,
+       .write = pp_num_cores_enabled_write,
+       .read = pp_num_cores_enabled_read,
+       .llseek = default_llseek,
+};
+
+static ssize_t pp_num_cores_total_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r;
+       char buffer[64];
+
+       r = sprintf(buffer, "%u\n", mali_pp_scheduler_get_num_cores_total());
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static const struct file_operations pp_num_cores_total_fops = {
+       .owner = THIS_MODULE,
+       .read = pp_num_cores_total_read,
+};
+
+static ssize_t pp_core_scaling_enabled_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+       int ret;
+       char buffer[32];
+       unsigned long val;
+
+       if (count >= sizeof(buffer)) {
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(&buffer[0], buf, count)) {
+               return -EFAULT;
+       }
+       buffer[count] = '\0';
+
+       ret = strict_strtoul(&buffer[0], 10, &val);
+       if (0 != ret) {
+               return -EINVAL;
+       }
+
+       switch (val) {
+       case 1:
+               mali_pp_scheduler_core_scaling_enable();
+               break;
+       case 0:
+               mali_pp_scheduler_core_scaling_disable();
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       *offp += count;
+       return count;
+}
+
+static ssize_t pp_core_scaling_enabled_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       return simple_read_from_buffer(buf, count, offp, mali_pp_scheduler_core_scaling_is_enabled() ? "1\n" : "0\n", 2);
+}
+static const struct file_operations pp_core_scaling_enabled_fops = {
+       .owner = THIS_MODULE,
+       .write = pp_core_scaling_enabled_write,
+       .read = pp_core_scaling_enabled_read,
+       .llseek = default_llseek,
+};
+
+static ssize_t version_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+       int r = 0;
+       char buffer[64];
+
+       switch (mali_kernel_core_get_product_id()) {
+       case _MALI_PRODUCT_ID_MALI200:
+               r = sprintf(buffer, "Mali-200\n");
+               break;
+       case _MALI_PRODUCT_ID_MALI300:
+               r = sprintf(buffer, "Mali-300\n");
+               break;
+       case _MALI_PRODUCT_ID_MALI400:
+               r = sprintf(buffer, "Mali-400 MP\n");
+               break;
+       case _MALI_PRODUCT_ID_MALI450:
+               r = sprintf(buffer, "Mali-450 MP\n");
+               break;
+       case _MALI_PRODUCT_ID_UNKNOWN:
+               return -EINVAL;
+               break;
+       };
+
+       return simple_read_from_buffer(buf, count, offp, buffer, r);
+}
+
+static const struct file_operations version_fops = {
+       .owner = THIS_MODULE,
+       .read = version_read,
+};
+
+int mali_sysfs_register(const char *mali_dev_name)
+{
+       mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
+       if(ERR_PTR(-ENODEV) == mali_debugfs_dir) {
+               /* Debugfs not supported. */
+               mali_debugfs_dir = NULL;
+       } else {
+               if(NULL != mali_debugfs_dir) {
+                       /* Debugfs directory created successfully; create files now */
+                       struct dentry *mali_pmu_dir;
+                       struct dentry *mali_power_dir;
+                       struct dentry *mali_gp_dir;
+                       struct dentry *mali_pp_dir;
+                       struct dentry *mali_l2_dir;
+                       struct dentry *mali_profiling_dir;
+
+                       debugfs_create_file("version", 0400, mali_debugfs_dir, NULL, &version_fops);
+
+                       mali_pmu_dir = debugfs_create_dir("pmu", mali_debugfs_dir);
+                       if (NULL != mali_pmu_dir) {
+                               debugfs_create_file("power_down", 0200, mali_pmu_dir, NULL, &pmu_power_down_fops);
+                               debugfs_create_file("power_up", 0200, mali_pmu_dir, NULL, &pmu_power_up_fops);
+                       }
+
+                       mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
+                       if (mali_power_dir != NULL) {
+                               debugfs_create_file("always_on", 0600, mali_power_dir, NULL, &power_always_on_fops);
+                               debugfs_create_file("power_events", 0200, mali_power_dir, NULL, &power_power_events_fops);
+                       }
+
+                       mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
+                       if (mali_gp_dir != NULL) {
+                               u32 num_groups;
+                               int i;
+
+                               num_groups = mali_group_get_glob_num_groups();
+                               for (i = 0; i < num_groups; i++) {
+                                       struct mali_group *group = mali_group_get_glob_group(i);
+
+                                       struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+                                       if (NULL != gp_core) {
+                                               struct dentry *mali_gp_gpx_dir;
+                                               mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
+                                               if (NULL != mali_gp_gpx_dir) {
+                                                       debugfs_create_file("base_addr", 0400, mali_gp_gpx_dir, &gp_core->hw_core, &hw_core_base_addr_fops);
+                                                       debugfs_create_file("enabled", 0600, mali_gp_gpx_dir, group, &group_enabled_fops);
+                                               }
+                                               break; /* no need to look for any other GP cores */
+                                       }
+
+                               }
+                       }
+
+                       mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
+                       if (mali_pp_dir != NULL) {
+                               u32 num_groups;
+                               int i;
+
+                               debugfs_create_file("num_cores_total", 0400, mali_pp_dir, NULL, &pp_num_cores_total_fops);
+                               debugfs_create_file("num_cores_enabled", 0600, mali_pp_dir, NULL, &pp_num_cores_enabled_fops);
+                               debugfs_create_file("core_scaling_enabled", 0600, mali_pp_dir, NULL, &pp_core_scaling_enabled_fops);
+
+                               num_groups = mali_group_get_glob_num_groups();
+                               for (i = 0; i < num_groups; i++) {
+                                       struct mali_group *group = mali_group_get_glob_group(i);
+
+                                       struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+                                       if (NULL != pp_core) {
+                                               char buf[16];
+                                               struct dentry *mali_pp_ppx_dir;
+                                               _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
+                                               mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
+                                               if (NULL != mali_pp_ppx_dir) {
+                                                       debugfs_create_file("base_addr", 0400, mali_pp_ppx_dir, &pp_core->hw_core, &hw_core_base_addr_fops);
+                                                       if (!mali_group_is_virtual(group)) {
+                                                               debugfs_create_file("enabled", 0600, mali_pp_ppx_dir, group, &group_enabled_fops);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
+                       if (mali_l2_dir != NULL) {
+                               struct dentry *mali_l2_all_dir;
+                               u32 l2_id;
+                               struct mali_l2_cache_core *l2_cache;
+
+                               mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
+                               if (mali_l2_all_dir != NULL) {
+                                       debugfs_create_file("counter_src0", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
+                                       debugfs_create_file("counter_src1", 0200, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
+                               }
+
+                               l2_id = 0;
+                               l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+                               while (NULL != l2_cache) {
+                                       char buf[16];
+                                       struct dentry *mali_l2_l2x_dir;
+                                       _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
+                                       mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
+                                       if (NULL != mali_l2_l2x_dir) {
+                                               debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
+                                               debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
+                                               debugfs_create_file("base_addr", 0400, mali_l2_l2x_dir, &l2_cache->hw_core, &hw_core_base_addr_fops);
+                                       }
+
+                                       /* try next L2 */
+                                       l2_id++;
+                                       l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+                               }
+                       }
+
+                       debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
+
+                       debugfs_create_file("utilization_gp_pp", 0400, mali_debugfs_dir, NULL, &utilization_gp_pp_fops);
+                       debugfs_create_file("utilization_gp", 0400, mali_debugfs_dir, NULL, &utilization_gp_fops);
+                       debugfs_create_file("utilization_pp", 0400, mali_debugfs_dir, NULL, &utilization_pp_fops);
+
+                       mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
+                       if (mali_profiling_dir != NULL) {
+                               u32 max_sub_jobs;
+                               int i;
+                               struct dentry *mali_profiling_gp_dir;
+                               struct dentry *mali_profiling_pp_dir;
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+                               struct dentry *mali_profiling_proc_dir;
+#endif
+                               /*
+                                * Create directory where we can set GP HW counters.
+                                */
+                               mali_profiling_gp_dir = debugfs_create_dir("gp", mali_profiling_dir);
+                               if (mali_profiling_gp_dir != NULL) {
+                                       debugfs_create_file("counter_src0", 0600, mali_profiling_gp_dir, (void*)PRIVATE_DATA_COUNTER_MAKE_GP(0), &profiling_counter_src_fops);
+                                       debugfs_create_file("counter_src1", 0600, mali_profiling_gp_dir, (void*)PRIVATE_DATA_COUNTER_MAKE_GP(1), &profiling_counter_src_fops);
+                               }
+
+                               /*
+                                * Create directory where we can set PP HW counters.
+                                * Possible override with specific HW counters for a particular sub job
+                                * (Disable core scaling before using the override!)
+                                */
+                               mali_profiling_pp_dir = debugfs_create_dir("pp", mali_profiling_dir);
+                               if (mali_profiling_pp_dir != NULL) {
+                                       debugfs_create_file("counter_src0", 0600, mali_profiling_pp_dir, (void*)PRIVATE_DATA_COUNTER_MAKE_PP(0), &profiling_counter_src_fops);
+                                       debugfs_create_file("counter_src1", 0600, mali_profiling_pp_dir, (void*)PRIVATE_DATA_COUNTER_MAKE_PP(1), &profiling_counter_src_fops);
+                               }
+
+                               max_sub_jobs = mali_pp_scheduler_get_num_cores_total();
+                               for (i = 0; i < max_sub_jobs; i++) {
+                                       char buf[16];
+                                       struct dentry *mali_profiling_pp_x_dir;
+                                       _mali_osk_snprintf(buf, sizeof(buf), "%u", i);
+                                       mali_profiling_pp_x_dir = debugfs_create_dir(buf, mali_profiling_pp_dir);
+                                       if (NULL != mali_profiling_pp_x_dir) {
+                                               debugfs_create_file("counter_src0", 0600, mali_profiling_pp_x_dir, (void*)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(0, i), &profiling_counter_src_fops);
+                                               debugfs_create_file("counter_src1", 0600, mali_profiling_pp_x_dir, (void*)PRIVATE_DATA_COUNTER_MAKE_PP_SUB_JOB(1, i), &profiling_counter_src_fops);
+                                       }
+                               }
+
+#if defined(CONFIG_MALI400_INTERNAL_PROFILING)
+                               mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
+                               if (mali_profiling_proc_dir != NULL) {
+                                       struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
+                                       if (mali_profiling_proc_default_dir != NULL) {
+                                               debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
+                                       }
+                               }
+                               debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
+                               debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
+                               debugfs_create_file("events_human_readable", 0400, mali_profiling_dir, NULL, &profiling_events_human_readable_fops);
+#endif
+                       }
+
+#if MALI_STATE_TRACKING
+                       debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
+#endif
+
+                       if (mali_sysfs_user_settings_register()) {
+                               /* Failed to create the debugfs entries for the user settings DB. */
+                               MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
+                       }
+               }
+       }
+
+       /* Success! */
+       return 0;
+}
+
+int mali_sysfs_unregister(void)
+{
+       if(NULL != mali_debugfs_dir) {
+               debugfs_remove_recursive(mali_debugfs_dir);
+       }
+       return 0;
+}
+
+#else /* MALI_LICENSE_IS_GPL */
+
+/* Dummy implementations for non-GPL */
+
+int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+{
+       return 0;
+}
+
+int mali_sysfs_unregister(void)
+{
+       return 0;
+}
+
+#endif /* MALI_LICENSE_IS_GPL */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.h b/drivers/gpu/arm/mali400/mali/linux/mali_kernel_sysfs.h
new file mode 100755 (executable)
index 0000000..ab35087
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_KERNEL_SYSFS_H__
+#define __MALI_KERNEL_SYSFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/device.h>
+
+#define MALI_PROC_DIR "driver/mali"
+
+int mali_sysfs_register(const char *mali_dev_name);
+int mali_sysfs_unregister(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_LINUX_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_linux_trace.h b/drivers/gpu/arm/mali400/mali/linux/mali_linux_trace.h
new file mode 100755 (executable)
index 0000000..fcd7966
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ)
+#define MALI_LINUX_TRACE_H
+
+#include <linux/types.h>
+
+#include <linux/stringify.h>
+#include <linux/tracepoint.h>
+
+#undef  TRACE_SYSTEM
+#define TRACE_SYSTEM mali
+#define TRACE_SYSTEM_STRING __stringfy(TRACE_SYSTEM)
+
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE mali_linux_trace
+
+/**
+ * Define the tracepoint used to communicate the status of a GPU. Called
+ * when a GPU turns on or turns off.
+ *
+ * @param event_id The type of the event. This parameter is a bitfield
+ *  encoding the type of the event.
+ *
+ * @param d0 First data parameter.
+ * @param d1 Second data parameter.
+ * @param d2 Third data parameter.
+ * @param d3 Fourth data parameter.
+ * @param d4 Fifth data parameter.
+ */
+TRACE_EVENT(mali_timeline_event,
+
+            TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1,
+                     unsigned int d2, unsigned int d3, unsigned int d4),
+
+            TP_ARGS(event_id, d0, d1, d2, d3, d4),
+
+            TP_STRUCT__entry(
+                __field(unsigned int, event_id)
+                __field(unsigned int, d0)
+                __field(unsigned int, d1)
+                __field(unsigned int, d2)
+                __field(unsigned int, d3)
+                __field(unsigned int, d4)
+            ),
+
+            TP_fast_assign(
+                __entry->event_id = event_id;
+                __entry->d0 = d0;
+                __entry->d1 = d1;
+                __entry->d2 = d2;
+                __entry->d3 = d3;
+                __entry->d4 = d4;
+            ),
+
+            TP_printk("event=%d", __entry->event_id)
+           );
+
+/**
+ * Define a tracepoint used to regsiter the value of a hardware counter.
+ * Hardware counters belonging to the vertex or fragment processor are
+ * reported via this tracepoint each frame, whilst L2 cache hardware
+ * counters are reported continuously.
+ *
+ * @param counter_id The counter ID.
+ * @param value The value of the counter.
+ */
+TRACE_EVENT(mali_hw_counter,
+
+            TP_PROTO(unsigned int counter_id, unsigned int value),
+
+            TP_ARGS(counter_id, value),
+
+            TP_STRUCT__entry(
+                __field(unsigned int, counter_id)
+                __field(unsigned int, value)
+            ),
+
+            TP_fast_assign(
+                __entry->counter_id = counter_id;
+            ),
+
+            TP_printk("event %d = %d", __entry->counter_id, __entry->value)
+           );
+
+/**
+ * Define a tracepoint used to send a bundle of software counters.
+ *
+ * @param counters The bundle of counters.
+ */
+TRACE_EVENT(mali_sw_counters,
+
+            TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters),
+
+            TP_ARGS(pid, tid, surface_id, counters),
+
+            TP_STRUCT__entry(
+                __field(pid_t, pid)
+                __field(pid_t, tid)
+                __field(void *, surface_id)
+                __field(unsigned int *, counters)
+            ),
+
+            TP_fast_assign(
+                __entry->pid = pid;
+                __entry->tid = tid;
+                __entry->surface_id = surface_id;
+                __entry->counters = counters;
+            ),
+
+            TP_printk("counters were %s", __entry->counters == NULL? "NULL" : "not NULL")
+           );
+
+#endif /* MALI_LINUX_TRACE_H */
+
+/* This part must exist outside the header guard. */
+#include <trace/define_trace.h>
+
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory.c
new file mode 100755 (executable)
index 0000000..b84c82a
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/fs.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_kernel_linux.h"
+#include "mali_scheduler.h"
+#include "mali_kernel_descriptor_mapping.h"
+
+#include "mali_memory.h"
+#include "mali_memory_dma_buf.h"
+#include "mali_memory_os_alloc.h"
+#include "mali_memory_block_alloc.h"
+
+/* session->memory_lock must be held when calling this function */
+static void mali_mem_release(mali_mem_allocation *descriptor)
+{
+       MALI_DEBUG_ASSERT_POINTER(descriptor);
+       MALI_DEBUG_ASSERT_LOCK_HELD(descriptor->session->memory_lock);
+
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+
+       switch (descriptor->type) {
+       case MALI_MEM_OS:
+               mali_mem_os_release(descriptor);
+               break;
+       case MALI_MEM_DMA_BUF:
+#if defined(CONFIG_DMA_SHARED_BUFFER)
+               mali_mem_dma_buf_release(descriptor);
+#endif
+               break;
+       case MALI_MEM_UMP:
+#if defined(CONFIG_MALI400_UMP)
+               mali_mem_ump_release(descriptor);
+#endif
+               break;
+       case MALI_MEM_EXTERNAL:
+               mali_mem_external_release(descriptor);
+               break;
+       case MALI_MEM_BLOCK:
+               mali_mem_block_release(descriptor);
+               break;
+       }
+}
+
+static void mali_mem_vma_open(struct vm_area_struct * vma)
+{
+       mali_mem_allocation *descriptor = (mali_mem_allocation*)vma->vm_private_data;
+       MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma));
+
+       descriptor->cpu_mapping.ref++;
+
+       return;
+}
+
+static void mali_mem_vma_close(struct vm_area_struct *vma)
+{
+       mali_mem_allocation *descriptor;
+       struct mali_session_data *session;
+       mali_mem_virt_cpu_mapping *mapping;
+
+       MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma));
+
+       descriptor = (mali_mem_allocation*)vma->vm_private_data;
+       BUG_ON(!descriptor);
+
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+
+       mapping = &descriptor->cpu_mapping;
+       BUG_ON(0 == mapping->ref);
+
+       mapping->ref--;
+       if (0 != mapping->ref) {
+               MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", mapping->ref));
+               return;
+       }
+
+       session = descriptor->session;
+
+       mali_descriptor_mapping_free(session->descriptor_mapping, descriptor->id);
+
+       _mali_osk_mutex_wait(session->memory_lock);
+       mali_mem_release(descriptor);
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       mali_mem_descriptor_destroy(descriptor);
+}
+
+static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       void __user * address;
+       mali_mem_allocation *descriptor;
+
+       address = vmf->virtual_address;
+       descriptor = (mali_mem_allocation *)vma->vm_private_data;
+
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+
+       /*
+        * We always fail the call since all memory is pre-faulted when assigned to the process.
+        * Only the Mali cores can use page faults to extend buffers.
+       */
+
+       MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n"));
+       MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void*)address));
+
+       MALI_IGNORE(address);
+       MALI_IGNORE(descriptor);
+
+       return VM_FAULT_SIGBUS;
+}
+
+struct vm_operations_struct mali_kernel_vm_ops = {
+       .open = mali_mem_vma_open,
+       .close = mali_mem_vma_close,
+       .fault = mali_kernel_memory_cpu_page_fault_handler
+};
+
+/** @note munmap handler is done by vma close handler */
+int mali_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct mali_session_data *session;
+       mali_mem_allocation *descriptor;
+       u32 size = vma->vm_end - vma->vm_start;
+       u32 mali_addr = vma->vm_pgoff << PAGE_SHIFT;
+
+       session = (struct mali_session_data *)filp->private_data;
+       if (NULL == session) {
+               MALI_PRINT_ERROR(("mmap called without any session data available\n"));
+               return -EFAULT;
+       }
+
+       MALI_DEBUG_PRINT(4, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X vma->flags 0x%08x\n",
+                            (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT),
+                            (unsigned int)(vma->vm_end - vma->vm_start), vma->vm_flags));
+
+       /* Set some bits which indicate that, the memory is IO memory, meaning
+        * that no paging is to be performed and the memory should not be
+        * included in crash dumps. And that the memory is reserved, meaning
+        * that it's present and can never be paged out (see also previous
+        * entry)
+        */
+       vma->vm_flags |= VM_IO;
+       vma->vm_flags |= VM_DONTCOPY;
+       vma->vm_flags |= VM_PFNMAP;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+       vma->vm_flags |= VM_RESERVED;
+#else
+       vma->vm_flags |= VM_DONTDUMP;
+       vma->vm_flags |= VM_DONTEXPAND;
+#endif
+
+       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+       vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */
+
+       descriptor = mali_mem_block_alloc(mali_addr, size, vma, session);
+       if (NULL == descriptor) {
+               descriptor = mali_mem_os_alloc(mali_addr, size, vma, session);
+               if (NULL == descriptor) {
+                       MALI_DEBUG_PRINT(3, ("MMAP failed\n"));
+                       return -ENOMEM;
+               }
+       }
+
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+
+       vma->vm_private_data = (void*)descriptor;
+
+       /* Put on descriptor map */
+       if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &descriptor->id)) {
+               _mali_osk_mutex_wait(session->memory_lock);
+               mali_mem_os_release(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+
+/* Prepare memory descriptor */
+mali_mem_allocation *mali_mem_descriptor_create(struct mali_session_data *session, mali_mem_type type)
+{
+       mali_mem_allocation *descriptor;
+
+       descriptor = (mali_mem_allocation*)kzalloc(sizeof(mali_mem_allocation), GFP_KERNEL);
+       if (NULL == descriptor) {
+               MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n"));
+               return NULL;
+       }
+
+       MALI_DEBUG_CODE(descriptor->magic = MALI_MEM_ALLOCATION_VALID_MAGIC);
+
+       descriptor->flags = 0;
+       descriptor->type = type;
+       descriptor->session = session;
+
+       return descriptor;
+}
+
+void mali_mem_descriptor_destroy(mali_mem_allocation *descriptor)
+{
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+       MALI_DEBUG_CODE(descriptor->magic = MALI_MEM_ALLOCATION_FREED_MAGIC);
+
+       kfree(descriptor);
+}
+
+_mali_osk_errcode_t mali_mem_mali_map_prepare(mali_mem_allocation *descriptor)
+{
+       u32 size = descriptor->size;
+       struct mali_session_data *session = descriptor->session;
+
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+
+       /* Map dma-buf into this session's page tables */
+
+       if (descriptor->flags & MALI_MEM_FLAG_MALI_GUARD_PAGE) {
+               size += MALI_MMU_PAGE_SIZE;
+       }
+
+       return mali_mmu_pagedir_map(session->page_directory, descriptor->mali_mapping.addr, size);
+}
+
+void mali_mem_mali_map_free(mali_mem_allocation *descriptor)
+{
+       u32 size = descriptor->size;
+       struct mali_session_data *session = descriptor->session;
+
+       MALI_DEBUG_ASSERT(MALI_MEM_ALLOCATION_VALID_MAGIC == descriptor->magic);
+
+       if (descriptor->flags & MALI_MEM_FLAG_MALI_GUARD_PAGE) {
+               size += MALI_MMU_PAGE_SIZE;
+       }
+
+       /* Umap and flush L2 */
+       mali_mmu_pagedir_unmap(session->page_directory, descriptor->mali_mapping.addr, descriptor->size);
+
+       mali_scheduler_zap_all_active(session);
+}
+
+u32 _mali_ukk_report_memory_usage(void)
+{
+       u32 sum = 0;
+
+       sum += mali_mem_block_allocator_stat();
+       sum += mali_mem_os_stat();
+
+       return sum;
+}
+
+/**
+ * Per-session memory descriptor mapping table sizes
+ */
+#define MALI_MEM_DESCRIPTORS_INIT 64
+#define MALI_MEM_DESCRIPTORS_MAX 65536
+
+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data)
+{
+       MALI_DEBUG_PRINT(5, ("Memory session begin\n"));
+
+       /* Create descriptor mapping table */
+       session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX);
+
+       if (NULL == session_data->descriptor_mapping) {
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       session_data->memory_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED,
+                                   _MALI_OSK_LOCK_ORDER_MEM_SESSION);
+
+       if (NULL == session_data->memory_lock) {
+               mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+               _mali_osk_free(session_data);
+               MALI_ERROR(_MALI_OSK_ERR_FAULT);
+       }
+
+       MALI_DEBUG_PRINT(5, ("MMU session begin: success\n"));
+       MALI_SUCCESS;
+}
+
+/** @brief Callback function that releases memory
+ *
+ * session->memory_lock must be held when calling this function.
+ */
+static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target)
+{
+       mali_mem_allocation *descriptor;
+
+       descriptor = (mali_mem_allocation*)map_target;
+
+       MALI_DEBUG_ASSERT_LOCK_HELD(descriptor->session->memory_lock);
+
+       MALI_DEBUG_PRINT(3, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target));
+       MALI_DEBUG_ASSERT(descriptor);
+
+       mali_mem_release(descriptor);
+       mali_mem_descriptor_destroy(descriptor);
+}
+
+void mali_memory_session_end(struct mali_session_data *session)
+{
+       MALI_DEBUG_PRINT(3, ("MMU session end\n"));
+
+       if (NULL == session) {
+               MALI_DEBUG_PRINT(1, ("No session data found during session end\n"));
+               return;
+       }
+
+       /* Lock the session so we can modify the memory list */
+       _mali_osk_mutex_wait(session->memory_lock);
+
+       /* Free all allocations still in the descriptor map, and terminate the map */
+       if (NULL != session->descriptor_mapping) {
+               mali_descriptor_mapping_call_for_each(session->descriptor_mapping, descriptor_table_cleanup_callback);
+               mali_descriptor_mapping_destroy(session->descriptor_mapping);
+               session->descriptor_mapping = NULL;
+       }
+
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       /* Free the lock */
+       _mali_osk_mutex_term(session->memory_lock);
+
+       return;
+}
+
+_mali_osk_errcode_t mali_memory_initialize(void)
+{
+       return mali_mem_os_init();
+}
+
+void mali_memory_terminate(void)
+{
+       mali_mem_os_term();
+       mali_mem_block_allocator_destroy(NULL);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory.h b/drivers/gpu/arm/mali400/mali/linux/mali_memory.h
new file mode 100755 (executable)
index 0000000..95aeba4
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MEMORY_H__
+#define __MALI_MEMORY_H__
+
+#include "mali_osk.h"
+#include "mali_session.h"
+
+#include <linux/list.h>
+#include <linux/mm.h>
+
+#include "mali_memory_types.h"
+#include "mali_memory_os_alloc.h"
+
+_mali_osk_errcode_t mali_memory_initialize(void);
+void mali_memory_terminate(void);
+
+/** @brief Allocate a page table page
+ *
+ * Allocate a page for use as a page directory or page table. The page is
+ * mapped into kernel space.
+ *
+ * @return _MALI_OSK_ERR_OK on success, otherwise an error code
+ * @param table_page GPU pointer to the allocated page
+ * @param mapping CPU pointer to the mapping of the allocated page
+ */
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping)
+{
+       return mali_mem_os_get_table_page(table_page, mapping);
+}
+
+/** @brief Release a page table page
+ *
+ * Release a page table page allocated through \a mali_mmu_get_table_page
+ *
+ * @param pa the GPU address of the page to release
+ */
+MALI_STATIC_INLINE void mali_mmu_release_table_page(u32 phys, void *virt)
+{
+       mali_mem_os_release_table_page(phys, virt);
+}
+
+/** @brief mmap function
+ *
+ * mmap syscalls on the Mali device node will end up here.
+ *
+ * This function allocates Mali memory and maps it on CPU and Mali.
+ */
+int mali_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/** @brief Allocate and initialize a Mali memory descriptor
+ *
+ * @param session Pointer to the session allocating the descriptor
+ * @param type Type of memory the descriptor will represent
+ */
+mali_mem_allocation *mali_mem_descriptor_create(struct mali_session_data *session, mali_mem_type type);
+
+/** @brief Destroy a Mali memory descriptor
+ *
+ * This function will only free the descriptor itself, and not the memory it
+ * represents.
+ *
+ * @param descriptor Pointer to the descriptor to destroy
+ */
+void mali_mem_descriptor_destroy(mali_mem_allocation *descriptor);
+
+/** @brief Start a new memory session
+ *
+ * Called when a process opens the Mali device node.
+ *
+ * @param session Pointer to session to initialize
+ */
+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *session);
+
+/** @brief Close a memory session
+ *
+ * Called when a process closes the Mali device node.
+ *
+ * Memory allocated by the session will be freed
+ *
+ * @param session Pointer to the session to terminate
+ */
+void mali_memory_session_end(struct mali_session_data *session);
+
+/** @brief Prepare Mali page tables for mapping
+ *
+ * This function will prepare the Mali page tables for mapping the memory
+ * described by \a descriptor.
+ *
+ * Page tables will be reference counted and allocated, if not yet present.
+ *
+ * @param descriptor Pointer to the memory descriptor to the mapping
+ */
+_mali_osk_errcode_t mali_mem_mali_map_prepare(mali_mem_allocation *descriptor);
+
+/** @brief Free Mali page tables for mapping
+ *
+ * This function will unmap pages from Mali memory and free the page tables
+ * that are now unused.
+ *
+ * The updated pages in the Mali L2 cache will be invalidated, and the MMU TLBs will be zapped if necessary.
+ *
+ * @param descriptor Pointer to the memory descriptor to unmap
+ */
+void mali_mem_mali_map_free(mali_mem_allocation *descriptor);
+
+/** @brief Parse resource and prepare the OS memory allocator
+ *
+ * @param size Maximum size to allocate for Mali GPU.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size);
+
+/** @brief Parse resource and prepare the dedicated memory allocator
+ *
+ * @param start Physical start address of dedicated Mali GPU memory.
+ * @param size Size of dedicated Mali GPU memory.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size);
+
+
+void mali_mem_ump_release(mali_mem_allocation *descriptor);
+void mali_mem_external_release(mali_mem_allocation *descriptor);
+
+#endif /* __MALI_MEMORY_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_block_alloc.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_block_alloc.c
new file mode 100755 (executable)
index 0000000..e8c890e
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include "mali_kernel_common.h"
+#include "mali_memory.h"
+#include "mali_memory_block_alloc.h"
+#include "mali_osk.h"
+#include <linux/mutex.h>
+#define MALI_BLOCK_SIZE (256UL * 1024UL)  /* 256 kB, remember to keep the ()s */
+
+struct block_info {
+       struct block_info *next;
+};
+
+typedef struct block_info block_info;
+
+
+typedef struct block_allocator {
+       struct mutex mutex;
+       block_info *all_blocks;
+       block_info *first_free;
+       u32 base;
+       u32 cpu_usage_adjust;
+       u32 num_blocks;
+       u32 free_blocks;
+} block_allocator;
+
+static block_allocator *mali_mem_block_gobal_allocator = NULL;
+
+MALI_STATIC_INLINE u32 get_phys(block_allocator *info, block_info *block)
+{
+       return info->base + ((block - info->all_blocks) * MALI_BLOCK_SIZE);
+}
+
+mali_mem_allocator *mali_mem_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size)
+{
+       block_allocator *info;
+       u32 usable_size;
+       u32 num_blocks;
+
+       usable_size = size & ~(MALI_BLOCK_SIZE - 1);
+       MALI_DEBUG_PRINT(3, ("Mali block allocator create for region starting at 0x%08X length 0x%08X\n", base_address, size));
+       MALI_DEBUG_PRINT(4, ("%d usable bytes\n", usable_size));
+       num_blocks = usable_size / MALI_BLOCK_SIZE;
+       MALI_DEBUG_PRINT(4, ("which becomes %d blocks\n", num_blocks));
+
+       if (usable_size == 0) {
+               MALI_DEBUG_PRINT(1, ("Memory block of size %d is unusable\n", size));
+               return NULL;
+       }
+
+       info = _mali_osk_malloc(sizeof(block_allocator));
+       if (NULL != info) {
+               mutex_init(&info->mutex);
+               info->all_blocks = _mali_osk_malloc(sizeof(block_info) * num_blocks);
+               if (NULL != info->all_blocks) {
+                       u32 i;
+                       info->first_free = NULL;
+                       info->num_blocks = num_blocks;
+                       info->free_blocks = num_blocks;
+
+                       info->base = base_address;
+                       info->cpu_usage_adjust = cpu_usage_adjust;
+
+                       for ( i = 0; i < num_blocks; i++) {
+                               info->all_blocks[i].next = info->first_free;
+                               info->first_free = &info->all_blocks[i];
+                       }
+
+                       return (mali_mem_allocator *)info;
+               }
+               _mali_osk_free(info);
+       }
+
+       return NULL;
+}
+
+void mali_mem_block_allocator_destroy(mali_mem_allocator *allocator)
+{
+       block_allocator *info = (block_allocator*)allocator;
+
+       info = mali_mem_block_gobal_allocator;
+       if (NULL == info) return;
+
+       MALI_DEBUG_ASSERT_POINTER(info);
+
+       _mali_osk_free(info->all_blocks);
+       _mali_osk_free(info);
+}
+
+static void mali_mem_block_mali_map(mali_mem_allocation *descriptor, u32 phys, u32 virt, u32 size)
+{
+       struct mali_page_directory *pagedir = descriptor->session->page_directory;
+       u32 prop = descriptor->mali_mapping.properties;
+       u32 offset = 0;
+
+       while (size) {
+               mali_mmu_pagedir_update(pagedir, virt + offset, phys + offset, MALI_MMU_PAGE_SIZE, prop);
+
+               size -= MALI_MMU_PAGE_SIZE;
+               offset += MALI_MMU_PAGE_SIZE;
+       }
+}
+
+static int mali_mem_block_cpu_map(mali_mem_allocation *descriptor, struct vm_area_struct *vma, u32 mali_phys, u32 mapping_offset, u32 size, u32 cpu_usage_adjust)
+{
+       u32 virt = vma->vm_start + mapping_offset;
+       u32 cpu_phys = mali_phys + cpu_usage_adjust;
+       u32 offset = 0;
+       int ret;
+
+       while (size) {
+               ret = vm_insert_pfn(vma, virt + offset, __phys_to_pfn(cpu_phys + offset));
+
+               if (unlikely(ret)) {
+                       MALI_DEBUG_PRINT(1, ("Block allocator: Failed to insert pfn into vma\n"));
+                       return 1;
+               }
+
+               size -= MALI_MMU_PAGE_SIZE;
+               offset += MALI_MMU_PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+mali_mem_allocation *mali_mem_block_alloc(u32 mali_addr, u32 size, struct vm_area_struct *vma, struct mali_session_data *session)
+{
+       _mali_osk_errcode_t err;
+       mali_mem_allocation *descriptor;
+       block_allocator *info;
+       u32 left;
+       block_info *last_allocated = NULL;
+       block_allocator_allocation *ret_allocation;
+       u32 offset = 0;
+
+       size = ALIGN(size, MALI_BLOCK_SIZE);
+
+       info = mali_mem_block_gobal_allocator;
+       if (NULL == info) return NULL;
+
+       left = size;
+       MALI_DEBUG_ASSERT(0 != left);
+
+       descriptor = mali_mem_descriptor_create(session, MALI_MEM_BLOCK);
+       if (NULL == descriptor) {
+               return NULL;
+       }
+
+       descriptor->mali_mapping.addr = mali_addr;
+       descriptor->size = size;
+       descriptor->cpu_mapping.addr = (void __user*)vma->vm_start;
+       descriptor->cpu_mapping.ref = 1;
+
+       if (VM_SHARED == (VM_SHARED & vma->vm_flags)) {
+               descriptor->mali_mapping.properties = MALI_MMU_FLAGS_DEFAULT;
+       } else {
+               /* Cached Mali memory mapping */
+               descriptor->mali_mapping.properties = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE;
+               vma->vm_flags |= VM_SHARED;
+       }
+
+       ret_allocation = &descriptor->block_mem.mem;
+
+       ret_allocation->mapping_length = 0;
+
+       _mali_osk_mutex_wait(session->memory_lock);
+       mutex_lock(&info->mutex);
+
+       if (left > (info->free_blocks * MALI_BLOCK_SIZE)) {
+               MALI_DEBUG_PRINT(2, ("Mali block allocator: not enough free blocks to service allocation (%u)\n", left));
+               mutex_unlock(&info->mutex);
+               _mali_osk_mutex_signal(session->memory_lock);
+               mali_mem_descriptor_destroy(descriptor);
+               return NULL;
+       }
+
+       err = mali_mem_mali_map_prepare(descriptor);
+       if (_MALI_OSK_ERR_OK != err) {
+               mutex_unlock(&info->mutex);
+               _mali_osk_mutex_signal(session->memory_lock);
+               mali_mem_descriptor_destroy(descriptor);
+               return NULL;
+       }
+
+       while ((left > 0) && (info->first_free)) {
+               block_info *block;
+               u32 phys_addr;
+               u32 current_mapping_size;
+
+               block = info->first_free;
+               info->first_free = info->first_free->next;
+               block->next = last_allocated;
+               last_allocated = block;
+
+               phys_addr = get_phys(info, block);
+
+               if (MALI_BLOCK_SIZE < left) {
+                       current_mapping_size = MALI_BLOCK_SIZE;
+               } else {
+                       current_mapping_size = left;
+               }
+
+               mali_mem_block_mali_map(descriptor, phys_addr, mali_addr + offset, current_mapping_size);
+               if (mali_mem_block_cpu_map(descriptor, vma, phys_addr, offset, current_mapping_size, info->cpu_usage_adjust)) {
+                       /* release all memory back to the pool */
+                       while (last_allocated) {
+                               /* This relinks every block we've just allocated back into the free-list */
+                               block = last_allocated->next;
+                               last_allocated->next = info->first_free;
+                               info->first_free = last_allocated;
+                               last_allocated = block;
+                       }
+
+                       mutex_unlock(&info->mutex);
+                       _mali_osk_mutex_signal(session->memory_lock);
+
+                       mali_mem_mali_map_free(descriptor);
+                       mali_mem_descriptor_destroy(descriptor);
+
+                       return NULL;
+               }
+
+               left -= current_mapping_size;
+               offset += current_mapping_size;
+               ret_allocation->mapping_length += current_mapping_size;
+
+               --info->free_blocks;
+       }
+
+       mutex_unlock(&info->mutex);
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       MALI_DEBUG_ASSERT(0 == left);
+
+       /* Record all the information about this allocation */
+       ret_allocation->last_allocated = last_allocated;
+       ret_allocation->info = info;
+
+       return descriptor;
+}
+
+void mali_mem_block_release(mali_mem_allocation *descriptor)
+{
+       block_allocator *info = descriptor->block_mem.mem.info;
+       block_info *block, *next;
+       block_allocator_allocation *allocation = &descriptor->block_mem.mem;
+
+       MALI_DEBUG_ASSERT(MALI_MEM_BLOCK == descriptor->type);
+
+       block = allocation->last_allocated;
+
+       MALI_DEBUG_ASSERT_POINTER(block);
+
+       /* unmap */
+       mali_mem_mali_map_free(descriptor);
+
+       mutex_lock(&info->mutex);
+
+       while (block) {
+               MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks))));
+
+               next = block->next;
+
+               /* relink into free-list */
+               block->next = info->first_free;
+               info->first_free = block;
+
+               /* advance the loop */
+               block = next;
+
+               ++info->free_blocks;
+       }
+
+       mutex_unlock(&info->mutex);
+}
+
+u32 mali_mem_block_allocator_stat(void)
+{
+       block_allocator *info = (block_allocator *)mali_mem_block_gobal_allocator;
+
+       if (NULL == info) return 0;
+
+       MALI_DEBUG_ASSERT_POINTER(info);
+
+       return (info->num_blocks - info->free_blocks) * MALI_BLOCK_SIZE;
+}
+
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size)
+{
+       mali_mem_allocator *allocator;
+
+       /* Do the low level linux operation first */
+
+       /* Request ownership of the memory */
+       if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory")) {
+               MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       /* Create generic block allocator object to handle it */
+       allocator = mali_mem_block_allocator_create(start, 0 /* cpu_usage_adjust */, size);
+
+       if (NULL == allocator) {
+               MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
+               _mali_osk_mem_unreqregion(start, size);
+               MALI_ERROR(_MALI_OSK_ERR_FAULT);
+       }
+
+       mali_mem_block_gobal_allocator = (block_allocator*)allocator;
+
+       return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_block_alloc.h b/drivers/gpu/arm/mali400/mali/linux/mali_memory_block_alloc.h
new file mode 100755 (executable)
index 0000000..c0d412d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_BLOCK_ALLOCATOR_H__
+#define __MALI_BLOCK_ALLOCATOR_H__
+
+#include "mali_session.h"
+#include "mali_memory.h"
+
+#include "mali_memory_types.h"
+
+typedef struct mali_mem_allocator mali_mem_allocator;
+
+mali_mem_allocator *mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size);
+void mali_mem_block_allocator_destroy(mali_mem_allocator *allocator);
+
+mali_mem_allocation *mali_mem_block_alloc(u32 mali_addr, u32 size, struct vm_area_struct *vma, struct mali_session_data *session);
+void mali_mem_block_release(mali_mem_allocation *descriptor);
+
+u32 mali_mem_block_allocator_stat(void);
+
+#endif /* __MALI_BLOCK_ALLOCATOR_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_dma_buf.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_dma_buf.c
new file mode 100755 (executable)
index 0000000..9605312
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include <linux/fs.h>     /* file system operations */
+#include <asm/uaccess.h>       /* user space access */
+#include <linux/dma-buf.h>
+#include <linux/scatterlist.h>
+#include <linux/rbtree.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_kernel_linux.h"
+
+#include "mali_memory.h"
+#include "mali_memory_dma_buf.h"
+
+#include "mali_pp_job.h"
+
+static void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem);
+
+struct mali_dma_buf_attachment {
+       struct dma_buf *buf;
+       struct dma_buf_attachment *attachment;
+       struct sg_table *sgt;
+       struct mali_session_data *session;
+       int map_ref;
+       struct mutex map_lock;
+       mali_bool is_mapped;
+       wait_queue_head_t wait_queue;
+};
+
+static void mali_dma_buf_release(struct mali_dma_buf_attachment *mem)
+{
+       MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release attachment %p\n", mem));
+
+       MALI_DEBUG_ASSERT_POINTER(mem);
+       MALI_DEBUG_ASSERT_POINTER(mem->attachment);
+       MALI_DEBUG_ASSERT_POINTER(mem->buf);
+
+#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+       /* We mapped implicitly on attach, so we need to unmap on release */
+       mali_dma_buf_unmap(mem);
+#endif
+
+       /* Wait for buffer to become unmapped */
+       wait_event(mem->wait_queue, !mem->is_mapped);
+       MALI_DEBUG_ASSERT(!mem->is_mapped);
+
+       dma_buf_detach(mem->buf, mem->attachment);
+       dma_buf_put(mem->buf);
+
+       _mali_osk_free(mem);
+}
+
+void mali_mem_dma_buf_release(mali_mem_allocation *descriptor)
+{
+       struct mali_dma_buf_attachment *mem = descriptor->dma_buf.attachment;
+
+       mali_dma_buf_release(mem);
+}
+
+/*
+ * Map DMA buf attachment \a mem into \a session at virtual address \a virt.
+ */
+static int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 flags)
+{
+       struct mali_page_directory *pagedir;
+       struct scatterlist *sg;
+       int i;
+
+       MALI_DEBUG_ASSERT_POINTER(mem);
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_ASSERT(mem->session == session);
+
+       mutex_lock(&mem->map_lock);
+
+       mem->map_ref++;
+
+       MALI_DEBUG_PRINT(5, ("Mali DMA-buf: map attachment %p, new map_ref = %d\n", mem, mem->map_ref));
+
+       if (1 == mem->map_ref) {
+               /* First reference taken, so we need to map the dma buf */
+               MALI_DEBUG_ASSERT(!mem->is_mapped);
+
+               pagedir = mali_session_get_page_directory(session);
+               MALI_DEBUG_ASSERT_POINTER(pagedir);
+
+               mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL);
+               if (IS_ERR_OR_NULL(mem->sgt)) {
+                       MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf attachment\n"));
+                       return -EFAULT;
+               }
+
+               for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i) {
+                       u32 size = sg_dma_len(sg);
+                       dma_addr_t phys = sg_dma_address(sg);
+
+                       /* sg must be page aligned. */
+                       MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE);
+
+                       mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_MMU_FLAGS_DEFAULT);
+
+                       virt += size;
+               }
+
+               if (flags & MALI_MEM_FLAG_MALI_GUARD_PAGE) {
+                       u32 guard_phys;
+                       MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n"));
+
+                       guard_phys = sg_dma_address(mem->sgt->sgl);
+                       mali_mmu_pagedir_update(pagedir, virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_MMU_FLAGS_DEFAULT);
+               }
+
+               mem->is_mapped = MALI_TRUE;
+               mutex_unlock(&mem->map_lock);
+
+               /* Wake up any thread waiting for buffer to become mapped */
+               wake_up_all(&mem->wait_queue);
+       } else {
+               MALI_DEBUG_ASSERT(mem->is_mapped);
+               mutex_unlock(&mem->map_lock);
+       }
+
+       return 0;
+}
+
+static void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem)
+{
+       MALI_DEBUG_ASSERT_POINTER(mem);
+       MALI_DEBUG_ASSERT_POINTER(mem->attachment);
+       MALI_DEBUG_ASSERT_POINTER(mem->buf);
+
+       mutex_lock(&mem->map_lock);
+
+       mem->map_ref--;
+
+       MALI_DEBUG_PRINT(5, ("Mali DMA-buf: unmap attachment %p, new map_ref = %d\n", mem, mem->map_ref));
+
+       if (0 == mem->map_ref) {
+               dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL);
+
+               mem->is_mapped = MALI_FALSE;
+       }
+
+       mutex_unlock(&mem->map_lock);
+
+       /* Wake up any thread waiting for buffer to become unmapped */
+       wake_up_all(&mem->wait_queue);
+}
+
+#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+int mali_dma_buf_map_job(struct mali_pp_job *job)
+{
+       mali_mem_allocation *descriptor;
+       struct mali_dma_buf_attachment *mem;
+       _mali_osk_errcode_t err;
+       int i;
+       int ret = 0;
+
+       _mali_osk_mutex_wait(job->session->memory_lock);
+
+       for (i = 0; i < job->num_memory_cookies; i++) {
+               int cookie = job->memory_cookies[i];
+
+               if (0 == cookie) {
+                       /* 0 is not a valid cookie */
+                       MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+                       continue;
+               }
+
+               MALI_DEBUG_ASSERT(0 < cookie);
+
+               err = mali_descriptor_mapping_get(job->session->descriptor_mapping,
+                                                 cookie, (void**)&descriptor);
+
+               if (_MALI_OSK_ERR_OK != err) {
+                       MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to get descriptor for cookie %d\n", cookie));
+                       ret = -EFAULT;
+                       MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+                       continue;
+               }
+
+               if (MALI_MEM_DMA_BUF != descriptor->type) {
+                       /* Not a DMA-buf */
+                       MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+                       continue;
+               }
+
+               mem = descriptor->dma_buf.attachment;
+
+               MALI_DEBUG_ASSERT_POINTER(mem);
+               MALI_DEBUG_ASSERT(mem->session == job->session);
+
+               err = mali_dma_buf_map(mem, mem->session, descriptor->mali_mapping.addr, descriptor->flags);
+               if (0 != err) {
+                       MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to map dma-buf for cookie %d at mali address %x\b",
+                                               cookie, descriptor->mali_mapping.addr));
+                       ret = -EFAULT;
+                       MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+                       continue;
+               }
+
+               /* Add mem to list of DMA-bufs mapped for this job */
+               job->dma_bufs[i] = mem;
+       }
+
+       _mali_osk_mutex_signal(job->session->memory_lock);
+
+       return ret;
+}
+
+void mali_dma_buf_unmap_job(struct mali_pp_job *job)
+{
+       int i;
+       for (i = 0; i < job->num_dma_bufs; i++) {
+               if (NULL == job->dma_bufs[i]) continue;
+
+               mali_dma_buf_unmap(job->dma_bufs[i]);
+               job->dma_bufs[i] = NULL;
+       }
+}
+#endif /* !CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH */
+
+int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg)
+{
+       struct dma_buf *buf;
+       struct mali_dma_buf_attachment *mem;
+       _mali_uk_attach_dma_buf_s args;
+       mali_mem_allocation *descriptor;
+       int md;
+       int fd;
+
+       /* Get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if (0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_attach_dma_buf_s))) {
+               return -EFAULT;
+       }
+
+       if (args.mali_address & ~PAGE_MASK) {
+               MALI_DEBUG_PRINT_ERROR(("Requested address (0x%08x) is not page aligned\n", args.mali_address));
+               return -EINVAL;
+       }
+
+       if (args.mali_address >= args.mali_address + args.size) {
+               MALI_DEBUG_PRINT_ERROR(("Requested address and size (0x%08x + 0x%08x) is too big\n", args.mali_address, args.size));
+               return -EINVAL;
+       }
+
+       fd = args.mem_fd;
+
+       buf = dma_buf_get(fd);
+       if (IS_ERR_OR_NULL(buf)) {
+               MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd));
+               return PTR_RET(buf);
+       }
+
+       /* Currently, mapping of the full buffer are supported. */
+       if (args.size != buf->size) {
+               MALI_DEBUG_PRINT_ERROR(("dma-buf size doesn't match mapping size.\n"));
+               dma_buf_put(buf);
+               return -EINVAL;
+       }
+
+       mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment));
+       if (NULL == mem) {
+               MALI_DEBUG_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n"));
+               dma_buf_put(buf);
+               return -ENOMEM;
+       }
+
+       mem->buf = buf;
+       mem->session = session;
+       mem->map_ref = 0;
+       mutex_init(&mem->map_lock);
+       init_waitqueue_head(&mem->wait_queue);
+
+       mem->attachment = dma_buf_attach(mem->buf, &mali_platform_device->dev);
+       if (NULL == mem->attachment) {
+               MALI_DEBUG_PRINT_ERROR(("Failed to attach to dma-buf %d\n", fd));
+               dma_buf_put(mem->buf);
+               _mali_osk_free(mem);
+               return -EFAULT;
+       }
+
+       /* Set up Mali memory descriptor */
+       descriptor = mali_mem_descriptor_create(session, MALI_MEM_DMA_BUF);
+       if (NULL == descriptor) {
+               MALI_DEBUG_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd));
+               mali_dma_buf_release(mem);
+               return -ENOMEM;
+       }
+
+       descriptor->size = args.size;
+       descriptor->mali_mapping.addr = args.mali_address;
+
+       descriptor->dma_buf.attachment = mem;
+
+       descriptor->flags |= MALI_MEM_FLAG_DONT_CPU_MAP;
+       if (args.flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) {
+               descriptor->flags = MALI_MEM_FLAG_MALI_GUARD_PAGE;
+       }
+
+       _mali_osk_mutex_wait(session->memory_lock);
+
+       /* Map dma-buf into this session's page tables */
+       if (_MALI_OSK_ERR_OK != mali_mem_mali_map_prepare(descriptor)) {
+               _mali_osk_mutex_signal(session->memory_lock);
+               MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf on Mali\n"));
+               mali_mem_descriptor_destroy(descriptor);
+               mali_dma_buf_release(mem);
+               return -ENOMEM;
+       }
+
+#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+       /* Map memory into session's Mali virtual address space. */
+
+       if (0 != mali_dma_buf_map(mem, session, descriptor->mali_mapping.addr, descriptor->flags)) {
+               mali_mem_mali_map_free(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+
+               MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd));
+               mali_mem_descriptor_destroy(descriptor);
+               mali_dma_buf_release(mem);
+               return -ENOMEM;
+       }
+
+#endif
+
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       /* Get descriptor mapping for memory. */
+       if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) {
+               _mali_osk_mutex_wait(session->memory_lock);
+               mali_mem_mali_map_free(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+
+               MALI_DEBUG_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd));
+               mali_mem_descriptor_destroy(descriptor);
+               mali_dma_buf_release(mem);
+               return -EFAULT;
+       }
+
+       /* Return stuff to user space */
+       if (0 != put_user(md, &user_arg->cookie)) {
+               _mali_osk_mutex_wait(session->memory_lock);
+               mali_mem_mali_map_free(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+
+               MALI_DEBUG_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd));
+               mali_descriptor_mapping_free(session->descriptor_mapping, md);
+               mali_dma_buf_release(mem);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg)
+{
+       int ret = 0;
+       _mali_uk_release_dma_buf_s args;
+       mali_mem_allocation *descriptor;
+
+       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_release_dma_buf_s)) ) {
+               return -EFAULT;
+       }
+
+       MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release descriptor cookie %d\n", args.cookie));
+
+       _mali_osk_mutex_wait(session->memory_lock);
+
+       descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie);
+
+       if (NULL != descriptor) {
+               MALI_DEBUG_PRINT(3, ("Mali DMA-buf: Releasing dma-buf at mali address %x\n", descriptor->mali_mapping.addr));
+
+               mali_mem_mali_map_free(descriptor);
+
+               mali_dma_buf_release(descriptor->dma_buf.attachment);
+
+               mali_mem_descriptor_destroy(descriptor);
+       } else {
+               MALI_DEBUG_PRINT_ERROR(("Invalid memory descriptor %d used to release dma-buf\n", args.cookie));
+               ret = -EINVAL;
+       }
+
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       /* Return the error that _mali_ukk_map_external_ump_mem produced */
+       return ret;
+}
+
+int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg)
+{
+       _mali_uk_dma_buf_get_size_s args;
+       int fd;
+       struct dma_buf *buf;
+
+       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if ( 0 != copy_from_user(&args, (void __user *)user_arg, sizeof(_mali_uk_dma_buf_get_size_s)) ) {
+               return -EFAULT;
+       }
+
+       /* Do DMA-BUF stuff */
+       fd = args.mem_fd;
+
+       buf = dma_buf_get(fd);
+       if (IS_ERR_OR_NULL(buf)) {
+               MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd));
+               return PTR_RET(buf);
+       }
+
+       if (0 != put_user(buf->size, &user_arg->size)) {
+               dma_buf_put(buf);
+               return -EFAULT;
+       }
+
+       dma_buf_put(buf);
+
+       return 0;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_dma_buf.h b/drivers/gpu/arm/mali400/mali/linux/mali_memory_dma_buf.h
new file mode 100755 (executable)
index 0000000..c34edd8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MEMORY_DMA_BUF_H__
+#define __MALI_MEMORY_DMA_BUF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mali_osk.h"
+#include "mali_memory.h"
+
+struct mali_pp_job;
+
+struct mali_dma_buf_attachment;
+
+int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *arg);
+int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *arg);
+int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *arg);
+
+void mali_mem_dma_buf_release(mali_mem_allocation *descriptor);
+
+#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+int mali_dma_buf_map_job(struct mali_pp_job *job);
+void mali_dma_buf_unmap_job(struct mali_pp_job *job);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_MEMORY_DMA_BUF_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_external.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_external.c
new file mode 100755 (executable)
index 0000000..0f09eed
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_osk.h"
+#include "mali_memory.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_mem_validation.h"
+#include "mali_uk_types.h"
+
+void mali_mem_external_release(mali_mem_allocation *descriptor)
+{
+       MALI_DEBUG_ASSERT(MALI_MEM_EXTERNAL == descriptor->type);
+
+       mali_mem_mali_map_free(descriptor);
+}
+
+_mali_osk_errcode_t _mali_ukk_map_external_mem(_mali_uk_map_external_mem_s *args)
+{
+       struct mali_session_data *session;
+       mali_mem_allocation * descriptor;
+       int md;
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session = (struct mali_session_data *)args->ctx;
+       MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_INVALID_ARGS);
+
+       /* check arguments */
+       /* NULL might be a valid Mali address */
+       if (! args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+       /* size must be a multiple of the system page size */
+       if (args->size % _MALI_OSK_MALI_PAGE_SIZE) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+       MALI_DEBUG_PRINT(3,
+                        ("Requested to map physical memory 0x%x-0x%x into virtual memory 0x%x\n",
+                         (void*)args->phys_addr,
+                         (void*)(args->phys_addr + args->size -1),
+                         (void*)args->mali_address)
+                       );
+
+       /* Validate the mali physical range */
+       if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size)) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       descriptor = mali_mem_descriptor_create(session, MALI_MEM_EXTERNAL);
+       if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+       descriptor->mali_mapping.addr = args->mali_address;
+       descriptor->size = args->size;
+
+       if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) {
+               descriptor->flags = MALI_MEM_FLAG_MALI_GUARD_PAGE;
+       }
+
+       _mali_osk_mutex_wait(session->memory_lock);
+       {
+               u32 virt = descriptor->mali_mapping.addr;
+               u32 phys = args->phys_addr;
+               u32 size = args->size;
+
+               err = mali_mem_mali_map_prepare(descriptor);
+               if (_MALI_OSK_ERR_OK != err) {
+                       _mali_osk_mutex_signal(session->memory_lock);
+                       mali_mem_descriptor_destroy(descriptor);
+                       return _MALI_OSK_ERR_NOMEM;
+               }
+
+               mali_mmu_pagedir_update(session->page_directory, virt, phys, size, MALI_MMU_FLAGS_DEFAULT);
+
+               if (descriptor->flags & MALI_MEM_FLAG_MALI_GUARD_PAGE) {
+                       mali_mmu_pagedir_update(session->page_directory, virt + size, phys, _MALI_OSK_MALI_PAGE_SIZE, MALI_MMU_FLAGS_DEFAULT);
+               }
+       }
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) {
+               _mali_osk_mutex_wait(session->memory_lock);
+               mali_mem_external_release(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+               mali_mem_descriptor_destroy(descriptor);
+               MALI_ERROR(_MALI_OSK_ERR_FAULT);
+       }
+
+       args->cookie = md;
+
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
+{
+       mali_mem_allocation * descriptor;
+       void* old_value;
+       struct mali_session_data *session;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session = (struct mali_session_data *)args->ctx;
+       MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_INVALID_ARGS);
+
+       if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args->cookie, (void**)&descriptor)) {
+               MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to unmap external memory\n", args->cookie));
+               MALI_ERROR(_MALI_OSK_ERR_FAULT);
+       }
+
+       old_value = mali_descriptor_mapping_free(session->descriptor_mapping, args->cookie);
+
+       if (NULL != old_value) {
+               _mali_osk_mutex_wait(session->memory_lock);
+               mali_mem_external_release(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+               mali_mem_descriptor_destroy(descriptor);
+       }
+
+       MALI_SUCCESS;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c
new file mode 100755 (executable)
index 0000000..7188b81
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/fs.h>
+#include <linux/dma-mapping.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#include "mali_osk.h"
+#include "mali_memory.h"
+#include "mali_memory_os_alloc.h"
+#include "mali_kernel_linux.h"
+
+/* Minimum size of allocator page pool */
+#define MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES (MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 256)
+#define MALI_OS_MEMORY_POOL_TRIM_JIFFIES (10 * CONFIG_HZ) /* Default to 10s */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+static int mali_mem_os_shrink(int nr_to_scan, gfp_t gfp_mask);
+#else
+static int mali_mem_os_shrink(struct shrinker *shrinker, int nr_to_scan, gfp_t gfp_mask);
+#endif
+#else
+static int mali_mem_os_shrink(struct shrinker *shrinker, struct shrink_control *sc);
+#endif
+static void mali_mem_os_trim_pool(struct work_struct *work);
+
+static struct mali_mem_os_allocator {
+       spinlock_t pool_lock;
+       struct list_head pool_pages;
+       size_t pool_count;
+
+       atomic_t allocated_pages;
+       size_t allocation_limit;
+
+       struct shrinker shrinker;
+       struct delayed_work timed_shrinker;
+       struct workqueue_struct *wq;
+} mali_mem_os_allocator = {
+       .pool_lock = __SPIN_LOCK_UNLOCKED(pool_lock),
+       .pool_pages = LIST_HEAD_INIT(mali_mem_os_allocator.pool_pages),
+       .pool_count = 0,
+
+       .allocated_pages = ATOMIC_INIT(0),
+       .allocation_limit = 0,
+
+       .shrinker.shrink = mali_mem_os_shrink,
+       .shrinker.seeks = DEFAULT_SEEKS,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+       .timed_shrinker = __DELAYED_WORK_INITIALIZER(mali_mem_os_allocator.timed_shrinker, mali_mem_os_trim_pool, TIMER_DEFERRABLE),
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+       .timed_shrinker = __DEFERRED_WORK_INITIALIZER(mali_mem_os_allocator.timed_shrinker, mali_mem_os_trim_pool),
+#else
+       .timed_shrinker = __DELAYED_WORK_INITIALIZER(mali_mem_os_allocator.timed_shrinker, mali_mem_os_trim_pool),
+#endif
+};
+
+static void mali_mem_os_free(mali_mem_allocation *descriptor)
+{
+       LIST_HEAD(pages);
+
+       MALI_DEBUG_ASSERT(MALI_MEM_OS == descriptor->type);
+
+       atomic_sub(descriptor->os_mem.count, &mali_mem_os_allocator.allocated_pages);
+
+       /* Put pages on pool. */
+       list_cut_position(&pages, &descriptor->os_mem.pages, descriptor->os_mem.pages.prev);
+
+       spin_lock(&mali_mem_os_allocator.pool_lock);
+
+       list_splice(&pages, &mali_mem_os_allocator.pool_pages);
+       mali_mem_os_allocator.pool_count += descriptor->os_mem.count;
+
+       spin_unlock(&mali_mem_os_allocator.pool_lock);
+
+       if (MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES < mali_mem_os_allocator.pool_count) {
+               MALI_DEBUG_PRINT(5, ("OS Mem: Starting pool trim timer %u\n", mali_mem_os_allocator.pool_count));
+               queue_delayed_work(mali_mem_os_allocator.wq, &mali_mem_os_allocator.timed_shrinker, MALI_OS_MEMORY_POOL_TRIM_JIFFIES);
+       }
+}
+
+static int mali_mem_os_alloc_pages(mali_mem_allocation *descriptor, u32 size)
+{
+       struct page *new_page, *tmp;
+       LIST_HEAD(pages);
+       size_t page_count = PAGE_ALIGN(size) / _MALI_OSK_MALI_PAGE_SIZE;
+       size_t remaining = page_count;
+       u32 i;
+
+       MALI_DEBUG_ASSERT_POINTER(descriptor);
+       MALI_DEBUG_ASSERT(MALI_MEM_OS == descriptor->type);
+
+       INIT_LIST_HEAD(&descriptor->os_mem.pages);
+       descriptor->os_mem.count = page_count;
+
+       /* Grab pages from pool. */
+       {
+               size_t pool_pages;
+               spin_lock(&mali_mem_os_allocator.pool_lock);
+               pool_pages = min(remaining, mali_mem_os_allocator.pool_count);
+               for (i = pool_pages; i > 0; i--) {
+                       BUG_ON(list_empty(&mali_mem_os_allocator.pool_pages));
+                       list_move(mali_mem_os_allocator.pool_pages.next, &pages);
+               }
+               mali_mem_os_allocator.pool_count -= pool_pages;
+               remaining -= pool_pages;
+               spin_unlock(&mali_mem_os_allocator.pool_lock);
+       }
+
+       /* Process pages from pool. */
+       i = 0;
+       list_for_each_entry_safe(new_page, tmp, &pages, lru) {
+               BUG_ON(NULL == new_page);
+
+               list_move_tail(&new_page->lru, &descriptor->os_mem.pages);
+       }
+
+       /* Allocate new pages, if needed. */
+       for (i = 0; i < remaining; i++) {
+               dma_addr_t dma_addr;
+
+               new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD);
+
+               if (unlikely(NULL == new_page)) {
+                       /* Calculate the number of pages actually allocated, and free them. */
+                       descriptor->os_mem.count = (page_count - remaining) + i;
+                       atomic_add(descriptor->os_mem.count, &mali_mem_os_allocator.allocated_pages);
+                       mali_mem_os_free(descriptor);
+                       return -ENOMEM;
+               }
+
+               /* Ensure page is flushed from CPU caches. */
+               dma_addr = dma_map_page(&mali_platform_device->dev, new_page,
+                                       0, _MALI_OSK_MALI_PAGE_SIZE, DMA_TO_DEVICE);
+
+               /* Store page phys addr */
+               SetPagePrivate(new_page);
+               set_page_private(new_page, dma_addr);
+
+               list_add_tail(&new_page->lru, &descriptor->os_mem.pages);
+       }
+
+       atomic_add(page_count, &mali_mem_os_allocator.allocated_pages);
+
+       if (MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES > mali_mem_os_allocator.pool_count) {
+               MALI_DEBUG_PRINT(4, ("OS Mem: Stopping pool trim timer, only %u pages on pool\n", mali_mem_os_allocator.pool_count));
+               cancel_delayed_work(&mali_mem_os_allocator.timed_shrinker);
+       }
+
+       return 0;
+}
+
+static int mali_mem_os_mali_map(mali_mem_allocation *descriptor, struct mali_session_data *session)
+{
+       struct mali_page_directory *pagedir = session->page_directory;
+       struct page *page;
+       _mali_osk_errcode_t err;
+       u32 virt = descriptor->mali_mapping.addr;
+       u32 prop = descriptor->mali_mapping.properties;
+
+       MALI_DEBUG_ASSERT(MALI_MEM_OS == descriptor->type);
+
+       err = mali_mem_mali_map_prepare(descriptor);
+       if (_MALI_OSK_ERR_OK != err) {
+               return -ENOMEM;
+       }
+
+       list_for_each_entry(page, &descriptor->os_mem.pages, lru) {
+               u32 phys = page_private(page);
+               mali_mmu_pagedir_update(pagedir, virt, phys, MALI_MMU_PAGE_SIZE, prop);
+               virt += MALI_MMU_PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+static void mali_mem_os_mali_unmap(struct mali_session_data *session, mali_mem_allocation *descriptor)
+{
+       mali_mem_mali_map_free(descriptor);
+}
+
+static int mali_mem_os_cpu_map(mali_mem_allocation *descriptor, struct vm_area_struct *vma)
+{
+       struct page *page;
+       int ret;
+       unsigned long addr = vma->vm_start;
+
+       list_for_each_entry(page, &descriptor->os_mem.pages, lru) {
+               /* We should use vm_insert_page, but it does a dcache
+                * flush which makes it way slower than remap_pfn_range or vm_insert_pfn.
+               ret = vm_insert_page(vma, addr, page);
+               */
+               ret = vm_insert_pfn(vma, addr, page_to_pfn(page));
+
+               if (unlikely(0 != ret)) {
+                       return -EFAULT;
+               }
+               addr += _MALI_OSK_MALI_PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+mali_mem_allocation *mali_mem_os_alloc(u32 mali_addr, u32 size, struct vm_area_struct *vma, struct mali_session_data *session)
+{
+       mali_mem_allocation *descriptor;
+       int err;
+
+       if (atomic_read(&mali_mem_os_allocator.allocated_pages) * _MALI_OSK_MALI_PAGE_SIZE + size > mali_mem_os_allocator.allocation_limit) {
+               MALI_DEBUG_PRINT(2, ("Mali Mem: Unable to allocate %u bytes. Currently allocated: %lu, max limit %lu\n",
+                                    size,
+                                    atomic_read(&mali_mem_os_allocator.allocated_pages) * _MALI_OSK_MALI_PAGE_SIZE,
+                                    mali_mem_os_allocator.allocation_limit));
+               return NULL;
+       }
+
+       descriptor = mali_mem_descriptor_create(session, MALI_MEM_OS);
+       if (NULL == descriptor) return NULL;
+
+       descriptor->mali_mapping.addr = mali_addr;
+       descriptor->size = size;
+       descriptor->cpu_mapping.addr = (void __user*)vma->vm_start;
+       descriptor->cpu_mapping.ref = 1;
+
+       if (VM_SHARED == (VM_SHARED & vma->vm_flags)) {
+               descriptor->mali_mapping.properties = MALI_MMU_FLAGS_DEFAULT;
+       } else {
+               /* Cached Mali memory mapping */
+               descriptor->mali_mapping.properties = MALI_MMU_FLAGS_FORCE_GP_READ_ALLOCATE;
+               vma->vm_flags |= VM_SHARED;
+       }
+
+       err = mali_mem_os_alloc_pages(descriptor, size); /* Allocate pages */
+       if (0 != err) goto alloc_failed;
+
+       /* Take session memory lock */
+       _mali_osk_mutex_wait(session->memory_lock);
+
+       err = mali_mem_os_mali_map(descriptor, session); /* Map on Mali */
+       if (0 != err) goto mali_map_failed;
+
+       _mali_osk_mutex_signal(session->memory_lock);
+
+       err = mali_mem_os_cpu_map(descriptor, vma); /* Map on CPU */
+       if (0 != err) goto cpu_map_failed;
+
+       return descriptor;
+
+cpu_map_failed:
+       mali_mem_os_mali_unmap(session, descriptor);
+mali_map_failed:
+       _mali_osk_mutex_signal(session->memory_lock);
+       mali_mem_os_free(descriptor);
+alloc_failed:
+       mali_mem_descriptor_destroy(descriptor);
+       MALI_DEBUG_PRINT(2, ("OS allocator: Failed to allocate memory (%d)\n", err));
+       return NULL;
+}
+
+void mali_mem_os_release(mali_mem_allocation *descriptor)
+{
+       struct mali_session_data *session = descriptor->session;
+
+       /* Unmap the memory from the mali virtual address space. */
+       mali_mem_os_mali_unmap(session, descriptor);
+
+       /* Free pages */
+       mali_mem_os_free(descriptor);
+}
+
+
+#define MALI_MEM_OS_PAGE_TABLE_PAGE_POOL_SIZE 128
+static struct {
+       struct {
+               u32 phys;
+               mali_io_address mapping;
+       } page[MALI_MEM_OS_PAGE_TABLE_PAGE_POOL_SIZE];
+       u32 count;
+       spinlock_t lock;
+} mali_mem_page_table_page_pool = {
+       .count = 0,
+       .lock = __SPIN_LOCK_UNLOCKED(pool_lock),
+};
+
+_mali_osk_errcode_t mali_mem_os_get_table_page(u32 *phys, mali_io_address *mapping)
+{
+       _mali_osk_errcode_t ret = _MALI_OSK_ERR_NOMEM;
+
+       spin_lock(&mali_mem_page_table_page_pool.lock);
+       if (0 < mali_mem_page_table_page_pool.count) {
+               u32 i = --mali_mem_page_table_page_pool.count;
+               *phys = mali_mem_page_table_page_pool.page[i].phys;
+               *mapping = mali_mem_page_table_page_pool.page[i].mapping;
+
+               ret = _MALI_OSK_ERR_OK;
+       }
+       spin_unlock(&mali_mem_page_table_page_pool.lock);
+
+       if (_MALI_OSK_ERR_OK != ret) {
+               *mapping = dma_alloc_writecombine(&mali_platform_device->dev, _MALI_OSK_MALI_PAGE_SIZE, phys, GFP_KERNEL);
+               if (NULL != *mapping) {
+                       ret = _MALI_OSK_ERR_OK;
+               }
+       }
+
+       return ret;
+}
+
+void mali_mem_os_release_table_page(u32 phys, void *virt)
+{
+       spin_lock(&mali_mem_page_table_page_pool.lock);
+       if (MALI_MEM_OS_PAGE_TABLE_PAGE_POOL_SIZE > mali_mem_page_table_page_pool.count) {
+               u32 i = mali_mem_page_table_page_pool.count;
+               mali_mem_page_table_page_pool.page[i].phys = phys;
+               mali_mem_page_table_page_pool.page[i].mapping = virt;
+
+               ++mali_mem_page_table_page_pool.count;
+
+               spin_unlock(&mali_mem_page_table_page_pool.lock);
+       } else {
+               spin_unlock(&mali_mem_page_table_page_pool.lock);
+
+               dma_free_writecombine(&mali_platform_device->dev, _MALI_OSK_MALI_PAGE_SIZE, virt, phys);
+       }
+}
+
+static void mali_mem_os_free_page(struct page *page)
+{
+       BUG_ON(page_count(page) != 1);
+
+       dma_unmap_page(&mali_platform_device->dev, page_private(page),
+                      _MALI_OSK_MALI_PAGE_SIZE, DMA_TO_DEVICE);
+
+       ClearPagePrivate(page);
+
+       __free_page(page);
+}
+
+/* The maximum number of page table pool pages to free in one go. */
+#define MALI_MEM_OS_CHUNK_TO_FREE 64UL
+
+/* Free a certain number of pages from the page table page pool.
+ * The pool lock must be held when calling the function, and the lock will be
+ * released before returning.
+ */
+static void mali_mem_os_page_table_pool_free(size_t nr_to_free)
+{
+       u32 phys_arr[MALI_MEM_OS_CHUNK_TO_FREE];
+       void *virt_arr[MALI_MEM_OS_CHUNK_TO_FREE];
+       u32 i;
+
+       MALI_DEBUG_ASSERT(nr_to_free <= MALI_MEM_OS_CHUNK_TO_FREE);
+
+       /* Remove nr_to_free pages from the pool and store them locally on stack. */
+       for (i = 0; i < nr_to_free; i++) {
+               u32 pool_index = mali_mem_page_table_page_pool.count - i - 1;
+
+               phys_arr[i] = mali_mem_page_table_page_pool.page[pool_index].phys;
+               virt_arr[i] = mali_mem_page_table_page_pool.page[pool_index].mapping;
+       }
+
+       mali_mem_page_table_page_pool.count -= nr_to_free;
+
+       spin_unlock(&mali_mem_page_table_page_pool.lock);
+
+       /* After releasing the spinlock: free the pages we removed from the pool. */
+       for (i = 0; i < nr_to_free; i++) {
+               dma_free_writecombine(&mali_platform_device->dev, _MALI_OSK_MALI_PAGE_SIZE, virt_arr[i], phys_arr[i]);
+       }
+}
+
+static void mali_mem_os_trim_page_table_page_pool(void)
+{
+       size_t nr_to_free = 0;
+       size_t nr_to_keep;
+
+       /* Keep 2 page table pages for each 1024 pages in the page cache. */
+       nr_to_keep = mali_mem_os_allocator.pool_count / 512;
+       /* And a minimum of eight pages, to accomodate new sessions. */
+       nr_to_keep += 8;
+
+       if (0 == spin_trylock(&mali_mem_page_table_page_pool.lock)) return;
+
+       if (nr_to_keep < mali_mem_page_table_page_pool.count) {
+               nr_to_free = mali_mem_page_table_page_pool.count - nr_to_keep;
+               nr_to_free = min((size_t)MALI_MEM_OS_CHUNK_TO_FREE, nr_to_free);
+       }
+
+       /* Pool lock will be released by the callee. */
+       mali_mem_os_page_table_pool_free(nr_to_free);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+static int mali_mem_os_shrink(int nr_to_scan, gfp_t gfp_mask)
+#else
+static int mali_mem_os_shrink(struct shrinker *shrinker, int nr_to_scan, gfp_t gfp_mask)
+#endif
+#else
+static int mali_mem_os_shrink(struct shrinker *shrinker, struct shrink_control *sc)
+#endif
+{
+       struct page *page, *tmp;
+       unsigned long flags;
+       struct list_head *le, pages;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
+       int nr = nr_to_scan;
+#else
+       int nr = sc->nr_to_scan;
+#endif
+
+       if (0 == nr) {
+               return mali_mem_os_allocator.pool_count + mali_mem_page_table_page_pool.count;
+       }
+
+       if (0 == mali_mem_os_allocator.pool_count) {
+               /* No pages availble */
+               return 0;
+       }
+
+       if (0 == spin_trylock_irqsave(&mali_mem_os_allocator.pool_lock, flags)) {
+               /* Not able to lock. */
+               return -1;
+       }
+
+       /* Release from general page pool */
+       nr = min((size_t)nr, mali_mem_os_allocator.pool_count);
+       mali_mem_os_allocator.pool_count -= nr;
+       list_for_each(le, &mali_mem_os_allocator.pool_pages) {
+               --nr;
+               if (0 == nr) break;
+       }
+       list_cut_position(&pages, &mali_mem_os_allocator.pool_pages, le);
+       spin_unlock_irqrestore(&mali_mem_os_allocator.pool_lock, flags);
+
+       list_for_each_entry_safe(page, tmp, &pages, lru) {
+               mali_mem_os_free_page(page);
+       }
+
+       /* Release some pages from page table page pool */
+       mali_mem_os_trim_page_table_page_pool();
+
+       if (MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES > mali_mem_os_allocator.pool_count) {
+               /* Pools are empty, stop timer */
+               MALI_DEBUG_PRINT(5, ("Stopping timer, only %u pages on pool\n", mali_mem_os_allocator.pool_count));
+               cancel_delayed_work(&mali_mem_os_allocator.timed_shrinker);
+       }
+
+       return mali_mem_os_allocator.pool_count + mali_mem_page_table_page_pool.count;
+}
+
+static void mali_mem_os_trim_pool(struct work_struct *data)
+{
+       struct page *page, *tmp;
+       struct list_head *le;
+       LIST_HEAD(pages);
+       size_t nr_to_free;
+
+       MALI_IGNORE(data);
+
+       MALI_DEBUG_PRINT(3, ("OS Mem: Trimming pool %u\n", mali_mem_os_allocator.pool_count));
+
+       /* Release from general page pool */
+       spin_lock(&mali_mem_os_allocator.pool_lock);
+       if (MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES < mali_mem_os_allocator.pool_count) {
+               size_t count = mali_mem_os_allocator.pool_count - MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES;
+               /* Free half the pages on the pool above the static limit. Or 64 pages, 256KB. */
+               nr_to_free = max(count / 2, (size_t)64);
+
+               mali_mem_os_allocator.pool_count -= nr_to_free;
+               list_for_each(le, &mali_mem_os_allocator.pool_pages) {
+                       --nr_to_free;
+                       if (0 == nr_to_free) break;
+               }
+               list_cut_position(&pages, &mali_mem_os_allocator.pool_pages, le);
+       }
+       spin_unlock(&mali_mem_os_allocator.pool_lock);
+
+       list_for_each_entry_safe(page, tmp, &pages, lru) {
+               mali_mem_os_free_page(page);
+       }
+
+       /* Release some pages from page table page pool */
+       mali_mem_os_trim_page_table_page_pool();
+
+       if (MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_PAGES < mali_mem_os_allocator.pool_count) {
+               MALI_DEBUG_PRINT(4, ("OS Mem: Starting pool trim timer %u\n", mali_mem_os_allocator.pool_count));
+               queue_delayed_work(mali_mem_os_allocator.wq, &mali_mem_os_allocator.timed_shrinker, MALI_OS_MEMORY_POOL_TRIM_JIFFIES);
+       }
+}
+
+_mali_osk_errcode_t mali_mem_os_init(void)
+{
+       mali_mem_os_allocator.wq = alloc_workqueue("mali-mem", WQ_UNBOUND, 1);
+       if (NULL == mali_mem_os_allocator.wq) {
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       register_shrinker(&mali_mem_os_allocator.shrinker);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void mali_mem_os_term(void)
+{
+       struct page *page, *tmp;
+
+       unregister_shrinker(&mali_mem_os_allocator.shrinker);
+       cancel_delayed_work_sync(&mali_mem_os_allocator.timed_shrinker);
+       destroy_workqueue(mali_mem_os_allocator.wq);
+
+       spin_lock(&mali_mem_os_allocator.pool_lock);
+       list_for_each_entry_safe(page, tmp, &mali_mem_os_allocator.pool_pages, lru) {
+               mali_mem_os_free_page(page);
+
+               --mali_mem_os_allocator.pool_count;
+       }
+       BUG_ON(mali_mem_os_allocator.pool_count);
+       spin_unlock(&mali_mem_os_allocator.pool_lock);
+
+       /* Release from page table page pool */
+       do {
+               u32 nr_to_free;
+
+               spin_lock(&mali_mem_page_table_page_pool.lock);
+
+               nr_to_free = min((size_t)MALI_MEM_OS_CHUNK_TO_FREE, mali_mem_page_table_page_pool.count);
+
+               /* Pool lock will be released by the callee. */
+               mali_mem_os_page_table_pool_free(nr_to_free);
+       } while (0 != mali_mem_page_table_page_pool.count);
+}
+
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size)
+{
+       mali_mem_os_allocator.allocation_limit = size;
+
+       MALI_SUCCESS;
+}
+
+u32 mali_mem_os_stat(void)
+{
+       return atomic_read(&mali_mem_os_allocator.allocated_pages) * _MALI_OSK_MALI_PAGE_SIZE;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.h b/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.h
new file mode 100755 (executable)
index 0000000..76f8ecf
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MEMORY_OS_ALLOC_H__
+#define __MALI_MEMORY_OS_ALLOC_H__
+
+#include "mali_osk.h"
+#include "mali_session.h"
+
+#include "mali_memory_types.h"
+
+/* OS memory allocator */
+/** @brief Allocate memory from OS
+ *
+ * This function will create a descriptor, allocate pages and map these on the CPU and Mali.
+ *
+ * @param mali_addr Mali virtual address to use for Mali mapping
+ * @param size Size to allocate
+ * @param vma Pointer to vma for CPU mapping
+ * @param session Pointer to session doing the allocation
+ */
+mali_mem_allocation *mali_mem_os_alloc(u32 mali_addr, u32 size, struct vm_area_struct *vma, struct mali_session_data *session);
+
+/** @brief Release Mali OS memory
+ *
+ * The session memory_lock must be held when calling this function.
+ *
+ * @param descriptor Pointer to the descriptor to release
+ */
+void mali_mem_os_release(mali_mem_allocation *descriptor);
+
+_mali_osk_errcode_t mali_mem_os_get_table_page(u32 *phys, mali_io_address *mapping);
+
+void mali_mem_os_release_table_page(u32 phys, void *virt);
+
+_mali_osk_errcode_t mali_mem_os_init(void);
+void mali_mem_os_term(void);
+u32 mali_mem_os_stat(void);
+
+#endif /* __MALI_MEMORY_OS_ALLOC_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_types.h b/drivers/gpu/arm/mali400/mali/linux/mali_memory_types.h
new file mode 100755 (executable)
index 0000000..97db7e9
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_MEMORY_TYPES_H__
+#define __MALI_MEMORY_TYPES_H__
+
+#if defined(CONFIG_MALI400_UMP)
+#include "ump_kernel_interface.h"
+#endif
+
+typedef u32 mali_address_t;
+
+typedef enum mali_mem_type {
+       MALI_MEM_OS,
+       MALI_MEM_EXTERNAL,
+       MALI_MEM_DMA_BUF,
+       MALI_MEM_UMP,
+       MALI_MEM_BLOCK,
+} mali_mem_type;
+
+typedef struct mali_mem_os_mem {
+       struct list_head pages;
+       u32 count;
+} mali_mem_os_mem;
+
+typedef struct mali_mem_dma_buf {
+#if defined(CONFIG_DMA_SHARED_BUFFER)
+       struct mali_dma_buf_attachment *attachment;
+#endif
+} mali_mem_dma_buf;
+
+typedef struct mali_mem_external {
+       dma_addr_t phys;
+       u32 size;
+} mali_mem_external;
+
+typedef struct mali_mem_ump {
+#if defined(CONFIG_MALI400_UMP)
+       ump_dd_handle handle;
+#endif
+} mali_mem_ump;
+
+typedef struct block_allocator_allocation {
+       /* The list will be released in reverse order */
+       struct block_info *last_allocated;
+       u32 mapping_length;
+       struct block_allocator *info;
+} block_allocator_allocation;
+
+typedef struct mali_mem_block_mem {
+       block_allocator_allocation mem;
+} mali_mem_block_mem;
+
+typedef struct mali_mem_virt_mali_mapping {
+       mali_address_t addr; /* Virtual Mali address */
+       u32 properties;      /* MMU Permissions + cache, must match MMU HW */
+} mali_mem_virt_mali_mapping;
+
+typedef struct mali_mem_virt_cpu_mapping {
+       void __user *addr;
+       u32 ref;
+} mali_mem_virt_cpu_mapping;
+
+#define MALI_MEM_ALLOCATION_VALID_MAGIC 0xdeda110c
+#define MALI_MEM_ALLOCATION_FREED_MAGIC 0x10101010
+
+typedef struct mali_mem_allocation {
+       MALI_DEBUG_CODE(u32 magic);
+       mali_mem_type type;                /**< Type of memory */
+       int id;                            /**< ID in the descriptor map for this allocation */
+
+       u32 size;                          /**< Size of the allocation */
+       u32 flags;                         /**< Flags for this allocation */
+
+       struct mali_session_data *session; /**< Pointer to session that owns the allocation */
+
+       /* Union selected by type. */
+       union {
+               mali_mem_os_mem os_mem;       /**< MALI_MEM_OS */
+               mali_mem_external ext_mem;    /**< MALI_MEM_EXTERNAL */
+               mali_mem_dma_buf dma_buf;     /**< MALI_MEM_DMA_BUF */
+               mali_mem_ump ump_mem;         /**< MALI_MEM_UMP */
+               mali_mem_block_mem block_mem; /**< MALI_MEM_BLOCK */
+       };
+
+       mali_mem_virt_cpu_mapping cpu_mapping; /**< CPU mapping */
+       mali_mem_virt_mali_mapping mali_mapping; /**< Mali mapping */
+} mali_mem_allocation;
+
+#define MALI_MEM_FLAG_MALI_GUARD_PAGE (1 << 0)
+#define MALI_MEM_FLAG_DONT_CPU_MAP    (1 << 1)
+
+#endif /* __MALI_MEMORY_TYPES__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_ump.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_ump.c
new file mode 100755 (executable)
index 0000000..2a95ae7
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_kernel_linux.h"
+
+#include "mali_memory.h"
+
+#include "ump_kernel_interface.h"
+
+static int mali_ump_map(struct mali_session_data *session, mali_mem_allocation *descriptor)
+{
+       ump_dd_handle ump_mem;
+       u32 nr_blocks;
+       u32 i;
+       ump_dd_physical_block *ump_blocks;
+       struct mali_page_directory *pagedir;
+       u32 offset = 0;
+       u32 prop;
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+       MALI_DEBUG_ASSERT_POINTER(descriptor);
+       MALI_DEBUG_ASSERT(MALI_MEM_UMP == descriptor->type);
+
+       ump_mem = descriptor->ump_mem.handle;
+       MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID != ump_mem);
+
+       nr_blocks = ump_dd_phys_block_count_get(ump_mem);
+       if (nr_blocks == 0) {
+               MALI_DEBUG_PRINT(1, ("No block count\n"));
+               return -EINVAL;
+       }
+
+       ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks);
+       if (NULL == ump_blocks) {
+               return -ENOMEM;
+       }
+
+       if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks)) {
+               _mali_osk_free(ump_blocks);
+               return -EFAULT;
+       }
+
+       pagedir = session->page_directory;
+       prop = descriptor->mali_mapping.properties;
+
+       err = mali_mem_mali_map_prepare(descriptor);
+       if (_MALI_OSK_ERR_OK != err) {
+               MALI_DEBUG_PRINT(1, ("Mapping of UMP memory failed\n"));
+
+               _mali_osk_free(ump_blocks);
+               return -ENOMEM;
+       }
+
+       for(i = 0; i < nr_blocks; ++i) {
+               u32 virt = descriptor->mali_mapping.addr + offset;
+
+               MALI_DEBUG_PRINT(7, ("Mapping in 0x%08x size %d\n", ump_blocks[i].addr , ump_blocks[i].size));
+
+               mali_mmu_pagedir_update(pagedir, virt, ump_blocks[i].addr,
+                                       ump_blocks[i].size, prop);
+
+               offset += ump_blocks[i].size;
+       }
+
+       if (descriptor->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) {
+               u32 virt = descriptor->mali_mapping.addr + offset;
+
+               /* Map in an extra virtual guard page at the end of the VMA */
+               MALI_DEBUG_PRINT(6, ("Mapping in extra guard page\n"));
+
+               mali_mmu_pagedir_update(pagedir, virt, ump_blocks[0].addr, _MALI_OSK_MALI_PAGE_SIZE, prop);
+
+               offset += _MALI_OSK_MALI_PAGE_SIZE;
+       }
+
+       _mali_osk_free(ump_blocks);
+
+       return 0;
+}
+
+void mali_ump_unmap(struct mali_session_data *session, mali_mem_allocation *descriptor)
+{
+       ump_dd_handle ump_mem;
+       struct mali_page_directory *pagedir;
+
+       ump_mem = descriptor->ump_mem.handle;
+       pagedir = session->page_directory;
+
+       MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID != ump_mem);
+
+       mali_mem_mali_map_free(descriptor);
+
+       ump_dd_reference_release(ump_mem);
+       return;
+}
+
+_mali_osk_errcode_t _mali_ukk_attach_ump_mem(_mali_uk_attach_ump_mem_s *args)
+{
+       ump_dd_handle ump_mem;
+       struct mali_session_data *session;
+       mali_mem_allocation *descriptor;
+       int md, ret;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session = (struct mali_session_data *)args->ctx;
+       MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_INVALID_ARGS);
+
+       /* check arguments */
+       /* NULL might be a valid Mali address */
+       if (!args->size) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+       /* size must be a multiple of the system page size */
+       if (args->size % _MALI_OSK_MALI_PAGE_SIZE) MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+
+       MALI_DEBUG_PRINT(3,
+                        ("Requested to map ump memory with secure id %d into virtual memory 0x%08X, size 0x%08X\n",
+                         args->secure_id, args->mali_address, args->size));
+
+       ump_mem = ump_dd_handle_create_from_secure_id((int)args->secure_id);
+
+       if (UMP_DD_HANDLE_INVALID == ump_mem) MALI_ERROR(_MALI_OSK_ERR_FAULT);
+
+       descriptor = mali_mem_descriptor_create(session, MALI_MEM_UMP);
+       if (NULL == descriptor) {
+               ump_dd_reference_release(ump_mem);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       descriptor->ump_mem.handle = ump_mem;
+       descriptor->mali_mapping.addr = args->mali_address;
+       descriptor->size = args->size;
+       descriptor->mali_mapping.properties = MALI_MMU_FLAGS_DEFAULT;
+       descriptor->flags |= MALI_MEM_FLAG_DONT_CPU_MAP;
+
+       if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) {
+               descriptor->flags = MALI_MEM_FLAG_MALI_GUARD_PAGE;
+       }
+
+       _mali_osk_mutex_wait(session->memory_lock);
+
+       ret = mali_ump_map(session, descriptor);
+       if (0 != ret) {
+               _mali_osk_mutex_signal(session->memory_lock);
+               ump_dd_reference_release(ump_mem);
+               mali_mem_descriptor_destroy(descriptor);
+               MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+       }
+
+       _mali_osk_mutex_signal(session->memory_lock);
+
+
+       if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md)) {
+               ump_dd_reference_release(ump_mem);
+               mali_mem_descriptor_destroy(descriptor);
+               MALI_ERROR(_MALI_OSK_ERR_FAULT);
+       }
+
+       args->cookie = md;
+
+       MALI_DEBUG_PRINT(5,("Returning from UMP attach\n"));
+
+       MALI_SUCCESS;
+}
+
+void mali_mem_ump_release(mali_mem_allocation *descriptor)
+{
+       struct mali_session_data *session = descriptor->session;
+
+       MALI_DEBUG_ASSERT(MALI_MEM_UMP == descriptor->type);
+
+       mali_ump_unmap(session, descriptor);
+}
+
+_mali_osk_errcode_t _mali_ukk_release_ump_mem(_mali_uk_release_ump_mem_s *args)
+{
+       mali_mem_allocation * descriptor;
+       struct mali_session_data *session;
+
+       MALI_DEBUG_ASSERT_POINTER(args);
+       MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+       session = (struct mali_session_data *)args->ctx;
+       MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_INVALID_ARGS);
+
+       if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args->cookie, (void**)&descriptor)) {
+               MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release ump memory\n", args->cookie));
+               MALI_ERROR(_MALI_OSK_ERR_FAULT);
+       }
+
+       descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args->cookie);
+
+       if (NULL != descriptor) {
+               _mali_osk_mutex_wait(session->memory_lock);
+               mali_mem_ump_release(descriptor);
+               _mali_osk_mutex_signal(session->memory_lock);
+
+               mali_mem_descriptor_destroy(descriptor);
+       }
+
+       MALI_SUCCESS;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_atomics.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_atomics.c
new file mode 100755 (executable)
index 0000000..a623112
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_atomics.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include "mali_osk.h"
+#include <asm/atomic.h>
+#include "mali_kernel_common.h"
+
+void _mali_osk_atomic_dec( _mali_osk_atomic_t *atom )
+{
+       atomic_dec((atomic_t *)&atom->u.val);
+}
+
+u32 _mali_osk_atomic_dec_return( _mali_osk_atomic_t *atom )
+{
+       return atomic_dec_return((atomic_t *)&atom->u.val);
+}
+
+void _mali_osk_atomic_inc( _mali_osk_atomic_t *atom )
+{
+       atomic_inc((atomic_t *)&atom->u.val);
+}
+
+u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom )
+{
+       return atomic_inc_return((atomic_t *)&atom->u.val);
+}
+
+_mali_osk_errcode_t _mali_osk_atomic_init( _mali_osk_atomic_t *atom, u32 val )
+{
+       MALI_CHECK_NON_NULL(atom, _MALI_OSK_ERR_INVALID_ARGS);
+       atomic_set((atomic_t *)&atom->u.val, val);
+       return _MALI_OSK_ERR_OK;
+}
+
+u32 _mali_osk_atomic_read( _mali_osk_atomic_t *atom )
+{
+       return atomic_read((atomic_t *)&atom->u.val);
+}
+
+void _mali_osk_atomic_term( _mali_osk_atomic_t *atom )
+{
+       MALI_IGNORE(atom);
+}
+
+u32 _mali_osk_atomic_xchg( _mali_osk_atomic_t *atom, u32 val )
+{
+       return atomic_xchg((atomic_t*)&atom->u.val, val);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_irq.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_irq.c
new file mode 100755 (executable)
index 0000000..2a30710
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_irq.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <linux/slab.h>        /* For memory allocation */
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+typedef struct _mali_osk_irq_t_struct {
+       u32 irqnum;
+       void *data;
+       _mali_osk_irq_uhandler_t uhandler;
+} mali_osk_irq_object_t;
+
+typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *);
+static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ); /* , struct pt_regs *regs*/
+
+#if defined(DEBUG)
+#if 0
+
+struct test_interrupt_data {
+       _mali_osk_irq_ack_t ack_func;
+       void *probe_data;
+       mali_bool interrupt_received;
+       wait_queue_head_t wq;
+};
+
+static irqreturn_t test_interrupt_upper_half(int port_name, void *dev_id)
+{
+       irqreturn_t ret = IRQ_NONE;
+       struct test_interrupt_data *data = (struct test_interrupt_data *)dev_id;
+
+       if (_MALI_OSK_ERR_OK == data->ack_func(data->probe_data)) {
+               data->interrupt_received = MALI_TRUE;
+               wake_up(&data->wq);
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
+static _mali_osk_errcode_t test_interrupt(u32 irqnum,
+        _mali_osk_irq_trigger_t trigger_func,
+        _mali_osk_irq_ack_t ack_func,
+        void *probe_data,
+        const char *description)
+{
+       unsigned long irq_flags = 0;
+       struct test_interrupt_data data = {
+               .ack_func = ack_func,
+               .probe_data = probe_data,
+               .interrupt_received = MALI_FALSE,
+       };
+
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       irq_flags |= IRQF_SHARED;
+#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
+
+       if (0 != request_irq(irqnum, test_interrupt_upper_half, irq_flags, description, &data)) {
+               MALI_DEBUG_PRINT(2, ("Unable to install test IRQ handler for core '%s'\n", description));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       init_waitqueue_head(&data.wq);
+
+       trigger_func(probe_data);
+       wait_event_timeout(data.wq, data.interrupt_received, 100);
+
+       free_irq(irqnum, &data);
+
+       if (data.interrupt_received) {
+               MALI_DEBUG_PRINT(3, ("%s: Interrupt test OK\n", description));
+               return _MALI_OSK_ERR_OK;
+       } else {
+               MALI_PRINT_ERROR(("%s: Failed interrupt test on %u\n", description, irqnum));
+               return _MALI_OSK_ERR_FAULT;
+       }
+}
+#endif
+
+#endif /* defined(DEBUG) */
+
+_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description )
+{
+       mali_osk_irq_object_t *irq_object;
+       unsigned long irq_flags = 0;
+
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+       irq_flags |= IRQF_SHARED;
+#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
+
+       irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
+       if (NULL == irq_object) {
+               return NULL;
+       }
+
+       if (-1 == irqnum) {
+               /* Probe for IRQ */
+               if ( (NULL != trigger_func) && (NULL != ack_func) ) {
+                       unsigned long probe_count = 3;
+                       _mali_osk_errcode_t err;
+                       int irq;
+
+                       MALI_DEBUG_PRINT(2, ("Probing for irq\n"));
+
+                       do {
+                               unsigned long mask;
+
+                               mask = probe_irq_on();
+                               trigger_func(probe_data);
+
+                               _mali_osk_time_ubusydelay(5);
+
+                               irq = probe_irq_off(mask);
+                               err = ack_func(probe_data);
+                       } while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--);
+
+                       if (irq < 0 || (_MALI_OSK_ERR_OK != err)) irqnum = -1;
+                       else irqnum = irq;
+               } else irqnum = -1; /* no probe functions, fault */
+
+               if (-1 != irqnum) {
+                       /* found an irq */
+                       MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum));
+               } else {
+                       MALI_DEBUG_PRINT(2, ("Probe for irq failed\n"));
+               }
+       }
+
+       irq_object->irqnum = irqnum;
+       irq_object->uhandler = uhandler;
+       irq_object->data = int_data;
+
+       if (-1 == irqnum) {
+               MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
+               kfree(irq_object);
+               return NULL;
+       }
+
+#if defined(DEBUG)
+#if 0
+       /* Verify that the configured interrupt settings are working */
+       if (_MALI_OSK_ERR_OK != test_interrupt(irqnum, trigger_func, ack_func, probe_data, description)) {
+               MALI_DEBUG_PRINT(2, ("Test of IRQ handler for core '%s' failed\n", description));
+               kfree(irq_object);
+               return NULL;
+       }
+#endif
+#endif
+
+       if (0 != request_irq(irqnum, irq_handler_upper_half, irq_flags, description, irq_object)) {
+               MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
+               kfree(irq_object);
+               return NULL;
+       }
+
+       return irq_object;
+}
+
+void _mali_osk_irq_term( _mali_osk_irq_t *irq )
+{
+       mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
+       free_irq(irq_object->irqnum, irq_object);
+       kfree(irq_object);
+}
+
+
+/** This function is called directly in interrupt context from the OS just after
+ * the CPU get the hw-irq from mali, or other devices on the same IRQ-channel.
+ * It is registered one of these function for each mali core. When an interrupt
+ * arrives this function will be called equal times as registered mali cores.
+ * That means that we only check one mali core in one function call, and the
+ * core we check for each turn is given by the \a dev_id variable.
+ * If we detect an pending interrupt on the given core, we mask the interrupt
+ * out by settging the core's IRQ_MASK register to zero.
+ * Then we schedule the mali_core_irq_handler_bottom_half to run as high priority
+ * work queue job.
+ */
+static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , struct pt_regs *regs*/
+{
+       irqreturn_t ret = IRQ_NONE;
+       mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id;
+
+       if (_MALI_OSK_ERR_OK == irq_object->uhandler(irq_object->data)) {
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_locks.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_locks.c
new file mode 100755 (executable)
index 0000000..c4d8a23
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_locks.c
+ * Implemenation of the OS abstraction layer for the kernel device driver
+ */
+
+#include "mali_osk_locks.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+
+#ifdef DEBUG
+#ifdef LOCK_ORDER_CHECKING
+static DEFINE_SPINLOCK(lock_tracking_lock);
+static mali_bool add_lock_to_log_and_check(struct _mali_osk_lock_debug_s *lock, uint32_t tid);
+static void remove_lock_from_log(struct _mali_osk_lock_debug_s *lock, uint32_t tid);
+static const char * const lock_order_to_string(_mali_osk_lock_order_t order);
+#endif /* LOCK_ORDER_CHECKING */
+
+void _mali_osk_locks_debug_init(struct _mali_osk_lock_debug_s *checker, _mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
+{
+       checker->orig_flags = flags;
+       checker->owner = 0;
+
+#ifdef LOCK_ORDER_CHECKING
+       checker->order = order;
+       checker->next = NULL;
+#endif
+}
+
+void _mali_osk_locks_debug_add(struct _mali_osk_lock_debug_s *checker)
+{
+       checker->owner = _mali_osk_get_tid();
+
+#ifdef LOCK_ORDER_CHECKING
+       if (!(checker->orig_flags & _MALI_OSK_LOCKFLAG_UNORDERED)) {
+               if (!add_lock_to_log_and_check(checker, _mali_osk_get_tid())) {
+                       printk(KERN_ERR "%d: ERROR lock %p taken while holding a lock of a higher order.\n",
+                              _mali_osk_get_tid(), checker);
+                       dump_stack();
+               }
+       }
+#endif
+}
+
+void _mali_osk_locks_debug_remove(struct _mali_osk_lock_debug_s *checker)
+{
+
+#ifdef LOCK_ORDER_CHECKING
+       if (!(checker->orig_flags & _MALI_OSK_LOCKFLAG_UNORDERED)) {
+               remove_lock_from_log(checker, _mali_osk_get_tid());
+       }
+#endif
+       checker->owner = 0;
+}
+
+
+#ifdef LOCK_ORDER_CHECKING
+/* Lock order checking
+ * -------------------
+ *
+ * To assure that lock ordering scheme defined by _mali_osk_lock_order_t is strictly adhered to, the
+ * following function will, together with a linked list and some extra members in _mali_osk_lock_debug_s,
+ * make sure that a lock that is taken has a higher order than the current highest-order lock a
+ * thread holds.
+ *
+ * This is done in the following manner:
+ * - A linked list keeps track of locks held by a thread.
+ * - A `next' pointer is added to each lock. This is used to chain the locks together.
+ * - When taking a lock, the `add_lock_to_log_and_check' makes sure that taking
+ *   the given lock is legal. It will follow the linked list  to find the last
+ *   lock taken by this thread. If the last lock's order was lower than the
+ *   lock that is to be taken, it appends the new lock to the list and returns
+ *   true, if not, it return false. This return value is assert()'ed on in
+ *   _mali_osk_lock_wait().
+ */
+
+static struct _mali_osk_lock_debug_s *lock_lookup_list;
+
+static void dump_lock_tracking_list(void)
+{
+       struct _mali_osk_lock_debug_s *l;
+       u32 n = 1;
+
+       /* print list for debugging purposes */
+       l = lock_lookup_list;
+
+       while (NULL != l) {
+               printk(" [lock: %p, tid_owner: %d, order: %d] ->", l, l->owner, l->order);
+               l = l->next;
+               MALI_DEBUG_ASSERT(n++ < 100);
+       }
+       printk(" NULL\n");
+}
+
+static int tracking_list_length(void)
+{
+       struct _mali_osk_lock_debug_s *l;
+       u32 n = 0;
+       l = lock_lookup_list;
+
+       while (NULL != l) {
+               l = l->next;
+               n++;
+               MALI_DEBUG_ASSERT(n < 100);
+       }
+       return n;
+}
+
+static mali_bool add_lock_to_log_and_check(struct _mali_osk_lock_debug_s *lock, uint32_t tid)
+{
+       mali_bool ret = MALI_FALSE;
+       _mali_osk_lock_order_t highest_order_for_tid = _MALI_OSK_LOCK_ORDER_FIRST;
+       struct _mali_osk_lock_debug_s *highest_order_lock = (struct _mali_osk_lock_debug_s *)0xbeefbabe;
+       struct _mali_osk_lock_debug_s *l;
+       unsigned long local_lock_flag;
+       u32 len;
+
+       spin_lock_irqsave(&lock_tracking_lock, local_lock_flag);
+       len = tracking_list_length();
+
+       l  = lock_lookup_list;
+       if (NULL == l) { /* This is the first lock taken by this thread -- record and return true */
+               lock_lookup_list = lock;
+               spin_unlock_irqrestore(&lock_tracking_lock, local_lock_flag);
+               return MALI_TRUE;
+       } else {
+               /* Traverse the locks taken and find the lock of the highest order.
+                * Since several threads may hold locks, each lock's owner must be
+                * checked so that locks not owned by this thread can be ignored. */
+               for(;;) {
+                       MALI_DEBUG_ASSERT_POINTER( l );
+                       if (tid == l->owner && l->order >= highest_order_for_tid) {
+                               highest_order_for_tid = l->order;
+                               highest_order_lock = l;
+                       }
+
+                       if (NULL != l->next) {
+                               l = l->next;
+                       } else {
+                               break;
+                       }
+               }
+
+               l->next = lock;
+               l->next = NULL;
+       }
+
+       /* We have now found the highest order lock currently held by this thread and can see if it is
+        * legal to take the requested lock. */
+       ret = highest_order_for_tid < lock->order;
+
+       if (!ret) {
+               printk(KERN_ERR "Took lock of order %d (%s) while holding lock of order %d (%s)\n",
+                      lock->order, lock_order_to_string(lock->order),
+                      highest_order_for_tid, lock_order_to_string(highest_order_for_tid));
+               dump_lock_tracking_list();
+       }
+
+       if (len+1 != tracking_list_length()) {
+               printk(KERN_ERR "************ lock: %p\n", lock);
+               printk(KERN_ERR "************ before: %d *** after: %d ****\n", len, tracking_list_length());
+               dump_lock_tracking_list();
+               MALI_DEBUG_ASSERT_POINTER(NULL);
+       }
+
+       spin_unlock_irqrestore(&lock_tracking_lock, local_lock_flag);
+       return ret;
+}
+
+static void remove_lock_from_log(struct _mali_osk_lock_debug_s *lock, uint32_t tid)
+{
+       struct _mali_osk_lock_debug_s *curr;
+       struct _mali_osk_lock_debug_s *prev = NULL;
+       unsigned long local_lock_flag;
+       u32 len;
+       u32 n = 0;
+
+       spin_lock_irqsave(&lock_tracking_lock, local_lock_flag);
+       len = tracking_list_length();
+       curr = lock_lookup_list;
+
+       if (NULL == curr) {
+               printk(KERN_ERR "Error: Lock tracking list was empty on call to remove_lock_from_log\n");
+               dump_lock_tracking_list();
+       }
+
+       MALI_DEBUG_ASSERT_POINTER(curr);
+
+
+       while (lock != curr) {
+               prev = curr;
+
+               MALI_DEBUG_ASSERT_POINTER(curr);
+               curr = curr->next;
+               MALI_DEBUG_ASSERT(n++ < 100);
+       }
+
+       if (NULL == prev) {
+               lock_lookup_list = curr->next;
+       } else {
+               MALI_DEBUG_ASSERT_POINTER(curr);
+               MALI_DEBUG_ASSERT_POINTER(prev);
+               prev->next = curr->next;
+       }
+
+       lock->next = NULL;
+
+       if (len-1 != tracking_list_length()) {
+               printk(KERN_ERR "************ lock: %p\n", lock);
+               printk(KERN_ERR "************ before: %d *** after: %d ****\n", len, tracking_list_length());
+               dump_lock_tracking_list();
+               MALI_DEBUG_ASSERT_POINTER(NULL);
+       }
+
+       spin_unlock_irqrestore(&lock_tracking_lock, local_lock_flag);
+}
+
+static const char * const lock_order_to_string(_mali_osk_lock_order_t order)
+{
+       switch (order) {
+       case _MALI_OSK_LOCK_ORDER_SESSIONS:
+               return "_MALI_OSK_LOCK_ORDER_SESSIONS";
+               break;
+       case _MALI_OSK_LOCK_ORDER_MEM_SESSION:
+               return "_MALI_OSK_LOCK_ORDER_MEM_SESSION";
+               break;
+       case _MALI_OSK_LOCK_ORDER_MEM_INFO:
+               return "_MALI_OSK_LOCK_ORDER_MEM_INFO";
+               break;
+       case _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE:
+               return "_MALI_OSK_LOCK_ORDER_MEM_PT_CACHE";
+               break;
+       case _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP:
+               return "_MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP";
+               break;
+       case _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL:
+               return "_MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL";
+               break;
+       case _MALI_OSK_LOCK_ORDER_GROUP:
+               return "_MALI_OSK_LOCK_ORDER_GROUP";
+               break;
+       case _MALI_OSK_LOCK_ORDER_SCHEDULER:
+               return "_MALI_OSK_LOCK_ORDER_SCHEDULER";
+               break;
+       case _MALI_OSK_LOCK_ORDER_PM_CORE_STATE:
+               return "_MALI_OSK_LOCK_ORDER_PM_CORE_STATE";
+               break;
+       case _MALI_OSK_LOCK_ORDER_L2_COMMAND:
+               return "_MALI_OSK_LOCK_ORDER_L2_COMMAND";
+               break;
+       case _MALI_OSK_LOCK_ORDER_PROFILING:
+               return "_MALI_OSK_LOCK_ORDER_PROFILING";
+               break;
+       case _MALI_OSK_LOCK_ORDER_L2_COUNTER:
+               return "_MALI_OSK_LOCK_ORDER_L2_COUNTER";
+               break;
+       case _MALI_OSK_LOCK_ORDER_UTILIZATION:
+               return "_MALI_OSK_LOCK_ORDER_UTILIZATION";
+               break;
+       case _MALI_OSK_LOCK_ORDER_PM_EXECUTE:
+               return "_MALI_OSK_LOCK_ORDER_PM_EXECUTE";
+               break;
+       case _MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS:
+               return "_MALI_OSK_LOCK_ORDER_SESSION_PENDING_JOBS";
+               break;
+       default:
+               return "";
+       }
+}
+#endif /* LOCK_ORDER_CHECKING */
+#endif /* DEBUG */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_locks.h b/drivers/gpu/arm/mali400/mali/linux/mali_osk_locks.h
new file mode 100755 (executable)
index 0000000..ddef3c9
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_locks.h
+ * Defines OS abstraction of lock and mutex
+ */
+#ifndef _MALI_OSK_LOCKS_H
+#define _MALI_OSK_LOCKS_H
+
+#include <linux/spinlock.h>
+#include <linux/rwsem.h>
+#include <linux/mutex.h>
+
+#include <linux/slab.h>
+
+#include "mali_osk_types.h"
+
+#ifdef _cplusplus
+extern "C" {
+#endif
+
+       /* When DEBUG is enabled, this struct will be used to track owner, mode and order checking */
+#ifdef DEBUG
+       struct _mali_osk_lock_debug_s {
+               u32 owner;
+               _mali_osk_lock_flags_t orig_flags;
+               _mali_osk_lock_order_t order;
+               struct _mali_osk_lock_debug_s *next;
+       };
+#endif
+
+       /* Anstraction of spinlock_t */
+       struct _mali_osk_spinlock_s {
+#ifdef DEBUG
+               struct _mali_osk_lock_debug_s checker;
+#endif
+               spinlock_t spinlock;
+       };
+
+       /* Abstration of spinlock_t and lock flag which is used to store register's state before locking */
+       struct _mali_osk_spinlock_irq_s {
+#ifdef DEBUG
+               struct _mali_osk_lock_debug_s checker;
+#endif
+
+               spinlock_t spinlock;
+               unsigned long flags;
+       };
+
+       /* Abstraction of rw_semaphore in OS */
+       struct _mali_osk_mutex_rw_s {
+#ifdef DEBUG
+               struct _mali_osk_lock_debug_s checker;
+               _mali_osk_lock_mode_t mode;
+#endif
+
+               struct rw_semaphore rw_sema;
+       };
+
+       /* Mutex and mutex_interruptible functions share the same osk mutex struct */
+       struct _mali_osk_mutex_s {
+#ifdef DEBUG
+               struct _mali_osk_lock_debug_s checker;
+#endif
+               struct mutex mutex;
+       };
+
+#ifdef DEBUG
+       /** @brief _mali_osk_locks_debug_init/add/remove() functions are declared when DEBUG is enabled and
+        * defined in file mali_osk_locks.c. When LOCK_ORDER_CHECKING is enabled, calling these functions when we
+        * init/lock/unlock a lock/mutex, we could track lock order of a given tid. */
+       void _mali_osk_locks_debug_init(struct _mali_osk_lock_debug_s *checker, _mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order);
+       void _mali_osk_locks_debug_add(struct _mali_osk_lock_debug_s *checker);
+       void _mali_osk_locks_debug_remove(struct _mali_osk_lock_debug_s *checker);
+
+       /** @brief This function can return a given lock's owner when DEBUG     is enabled. */
+       static inline u32 _mali_osk_lock_get_owner(struct _mali_osk_lock_debug_s *lock)
+       {
+               return lock->owner;
+       }
+#else
+#define _mali_osk_locks_debug_init(x, y, z) do {} while (0)
+#define _mali_osk_locks_debug_add(x) do {} while (0)
+#define _mali_osk_locks_debug_remove(x) do {} while (0)
+#endif
+
+       /** @brief Before use _mali_osk_spin_lock, init function should be used to allocate memory and initial spinlock*/
+       static inline _mali_osk_spinlock_t *_mali_osk_spinlock_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
+       {
+               _mali_osk_spinlock_t *lock = NULL;
+
+               lock = kmalloc(sizeof(_mali_osk_spinlock_t), GFP_KERNEL);
+               if (NULL == lock) {
+                       return NULL;
+               }
+               spin_lock_init(&lock->spinlock);
+               _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
+               return lock;
+       }
+
+       /** @brief Lock a spinlock */
+       static inline void  _mali_osk_spinlock_lock(_mali_osk_spinlock_t *lock)
+       {
+               BUG_ON(NULL == lock);
+               spin_lock(&lock->spinlock);
+               _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
+       }
+
+       /** @brief Unlock a spinlock */
+       static inline void _mali_osk_spinlock_unlock(_mali_osk_spinlock_t *lock)
+       {
+               BUG_ON(NULL == lock);
+               _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
+               spin_unlock(&lock->spinlock);
+       }
+
+       /** @brief Free a memory block which the argument lock pointed to and its type must be
+        * _mali_osk_spinlock_t *. */
+       static inline void _mali_osk_spinlock_term(_mali_osk_spinlock_t *lock)
+       {
+               /* Parameter validation  */
+               BUG_ON(NULL == lock);
+
+               /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
+               kfree(lock);
+       }
+
+       /** @brief Before _mali_osk_spinlock_irq_lock/unlock/term() is called, init function should be
+        * called to initial spinlock and flags in struct _mali_osk_spinlock_irq_t. */
+       static inline _mali_osk_spinlock_irq_t *_mali_osk_spinlock_irq_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
+       {
+               _mali_osk_spinlock_irq_t *lock = NULL;
+               lock = kmalloc(sizeof(_mali_osk_spinlock_irq_t), GFP_KERNEL);
+
+               if (NULL == lock) {
+                       return NULL;
+               }
+
+               lock->flags = 0;
+               spin_lock_init(&lock->spinlock);
+               _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
+               return lock;
+       }
+
+       /** @brief Lock spinlock and save the register's state */
+       static inline void _mali_osk_spinlock_irq_lock(_mali_osk_spinlock_irq_t *lock)
+       {
+               unsigned long tmp_flags;
+
+               BUG_ON(NULL == lock);
+               spin_lock_irqsave(&lock->spinlock, tmp_flags);
+               lock->flags = tmp_flags;
+               _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
+       }
+
+       /** @brief Unlock spinlock with saved register's state */
+       static inline void _mali_osk_spinlock_irq_unlock(_mali_osk_spinlock_irq_t *lock)
+       {
+               BUG_ON(NULL == lock);
+               _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
+               spin_unlock_irqrestore(&lock->spinlock, lock->flags);
+       }
+
+       /** @brief Destroy a given memory block which lock pointed to, and the lock type must be
+        * _mali_osk_spinlock_irq_t *. */
+       static inline void _mali_osk_spinlock_irq_term(_mali_osk_spinlock_irq_t *lock)
+       {
+               /* Parameter validation  */
+               BUG_ON(NULL == lock);
+
+               /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
+               kfree(lock);
+       }
+
+       /** @brief Before _mali_osk_mutex_rw_wait/signal/term() is called, we should call
+        * _mali_osk_mutex_rw_init() to kmalloc a memory block and initial part of elements in it. */
+       static inline _mali_osk_mutex_rw_t *_mali_osk_mutex_rw_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
+       {
+               _mali_osk_mutex_rw_t *lock = NULL;
+
+               lock = kmalloc(sizeof(_mali_osk_mutex_rw_t), GFP_KERNEL);
+
+               if (NULL == lock) {
+                       return NULL;
+               }
+
+               init_rwsem(&lock->rw_sema);
+               _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
+               return lock;
+       }
+
+       /** @brief When call _mali_osk_mutex_rw_wait/signal() functions, the second argument mode
+        * should be assigned with value _MALI_OSK_LOCKMODE_RO or _MALI_OSK_LOCKMODE_RW */
+       static inline void _mali_osk_mutex_rw_wait(_mali_osk_mutex_rw_t *lock, _mali_osk_lock_mode_t mode)
+       {
+               BUG_ON(NULL == lock);
+               BUG_ON(!(_MALI_OSK_LOCKMODE_RO == mode || _MALI_OSK_LOCKMODE_RW == mode));
+
+               if (mode == _MALI_OSK_LOCKMODE_RO) {
+                       down_read(&lock->rw_sema);
+               } else {
+                       down_write(&lock->rw_sema);
+               }
+
+#ifdef DEBUG
+               if (mode == _MALI_OSK_LOCKMODE_RW) {
+                       lock->mode = mode;
+               } else { /* mode == _MALI_OSK_LOCKMODE_RO */
+                       lock->mode = mode;
+               }
+               _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
+#endif
+       }
+
+       /** @brief Up lock->rw_sema with up_read/write() accordinf argument mode's value. */
+       static inline void  _mali_osk_mutex_rw_signal(_mali_osk_mutex_rw_t *lock, _mali_osk_lock_mode_t mode)
+       {
+               BUG_ON(NULL == lock);
+               BUG_ON(!(_MALI_OSK_LOCKMODE_RO == mode || _MALI_OSK_LOCKMODE_RW == mode));
+#ifdef DEBUG
+               /* make sure the thread releasing the lock actually was the owner */
+               if (mode == _MALI_OSK_LOCKMODE_RW) {
+                       _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
+                       /* This lock now has no owner */
+                       lock->checker.owner = 0;
+               }
+#endif
+
+               if (mode == _MALI_OSK_LOCKMODE_RO) {
+                       up_read(&lock->rw_sema);
+               } else {
+                       up_write(&lock->rw_sema);
+               }
+       }
+
+       /** @brief Free a given memory block which lock pointed to and its type must be
+        * _mali_sok_mutex_rw_t *. */
+       static inline void _mali_osk_mutex_rw_term(_mali_osk_mutex_rw_t *lock)
+       {
+               /* Parameter validation  */
+               BUG_ON(NULL == lock);
+
+               /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
+               kfree(lock);
+       }
+
+       /** @brief Mutex & mutex_interruptible share the same init and term function, because they have the
+        * same osk mutex struct, and the difference between them is which locking function they use */
+       static inline _mali_osk_mutex_t *_mali_osk_mutex_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
+       {
+               _mali_osk_mutex_t *lock = NULL;
+
+               lock = kmalloc(sizeof(_mali_osk_mutex_t), GFP_KERNEL);
+
+               if (NULL == lock) {
+                       return NULL;
+               }
+               mutex_init(&lock->mutex);
+
+               _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
+               return lock;
+       }
+
+       /** @brief  Lock the lock->mutex with mutex_lock_interruptible function */
+       static inline _mali_osk_errcode_t _mali_osk_mutex_wait_interruptible(_mali_osk_mutex_t *lock)
+       {
+               _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+
+               BUG_ON(NULL == lock);
+
+               if (mutex_lock_interruptible(&lock->mutex)) {
+                       printk(KERN_WARNING "Mali: Can not lock mutex\n");
+                       err = _MALI_OSK_ERR_RESTARTSYSCALL;
+               }
+
+               _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
+               return err;
+       }
+
+       /** @brief Unlock the lock->mutex which is locked with mutex_lock_interruptible() function. */
+       static inline void _mali_osk_mutex_signal_interruptible(_mali_osk_mutex_t *lock)
+       {
+               BUG_ON(NULL == lock);
+               _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
+               mutex_unlock(&lock->mutex);
+       }
+
+       /** @brief Lock the lock->mutex just with mutex_lock() function which could not be interruptted. */
+       static inline void _mali_osk_mutex_wait(_mali_osk_mutex_t *lock)
+       {
+               BUG_ON(NULL == lock);
+               mutex_lock(&lock->mutex);
+               _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
+       }
+
+       /** @brief Unlock the lock->mutex which is locked with mutex_lock() function. */
+       static inline void _mali_osk_mutex_signal(_mali_osk_mutex_t *lock)
+       {
+               BUG_ON(NULL == lock);
+               _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
+               mutex_unlock(&lock->mutex);
+       }
+
+       /** @brief Free a given memory block which lock point. */
+       static inline void _mali_osk_mutex_term(_mali_osk_mutex_t *lock)
+       {
+               /* Parameter validation  */
+               BUG_ON(NULL == lock);
+
+               /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
+               kfree(lock);
+       }
+
+#ifdef _cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_low_level_mem.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_low_level_mem.c
new file mode 100755 (executable)
index 0000000..f600b54
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_low_level_mem.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_ukk.h"
+
+void _mali_osk_mem_barrier( void )
+{
+       mb();
+}
+
+void _mali_osk_write_mem_barrier( void )
+{
+       wmb();
+}
+
+mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description )
+{
+       return (mali_io_address)ioremap_nocache(phys, size);
+}
+
+void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address virt )
+{
+       iounmap((void*)virt);
+}
+
+_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description )
+{
+#if MALI_LICENSE_IS_GPL
+       return _MALI_OSK_ERR_OK; /* GPL driver gets the mem region for the resources registered automatically */
+#else
+       return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK);
+#endif
+}
+
+void inline _mali_osk_mem_unreqregion( u32 phys, u32 size )
+{
+#if !MALI_LICENSE_IS_GPL
+       release_mem_region(phys, size);
+#endif
+}
+
+void inline _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val )
+{
+       __raw_writel(cpu_to_le32(val),((u8*)addr) + offset);
+}
+
+u32 inline _mali_osk_mem_ioread32( volatile mali_io_address addr, u32 offset )
+{
+       return ioread32(((u8*)addr) + offset);
+}
+
+void inline _mali_osk_mem_iowrite32( volatile mali_io_address addr, u32 offset, u32 val )
+{
+       iowrite32(val, ((u8*)addr) + offset);
+}
+
+void _mali_osk_cache_flushall( void )
+{
+       /** @note Cached memory is not currently supported in this implementation */
+}
+
+void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size )
+{
+       _mali_osk_write_mem_barrier();
+}
+
+u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size)
+{
+#define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096
+       u32 retval = 0;
+       void *temp_buf;
+
+       temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL);
+       if (NULL != temp_buf) {
+               u32 bytes_left_to_copy = size;
+               u32 i;
+               for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE) {
+                       u32 size_to_copy;
+                       u32 size_copied;
+                       u32 bytes_left;
+
+                       if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE) {
+                               size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE;
+                       } else {
+                               size_to_copy = bytes_left_to_copy;
+                       }
+
+                       bytes_left = copy_from_user(temp_buf, ((char*)src) + i, size_to_copy);
+                       size_copied = size_to_copy - bytes_left;
+
+                       bytes_left = copy_to_user(((char*)dest) + i, temp_buf, size_copied);
+                       size_copied -= bytes_left;
+
+                       bytes_left_to_copy -= size_copied;
+                       retval += size_copied;
+
+                       if (size_copied != size_to_copy) {
+                               break; /* Early out, we was not able to copy this entire block */
+                       }
+               }
+
+               kfree(temp_buf);
+       }
+
+       return retval;
+}
+
+_mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args)
+{
+       MALI_DEBUG_ASSERT_POINTER(args);
+
+       if (NULL == args->ctx) {
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+
+       /* Return number of bytes actually copied */
+       args->size = _mali_osk_mem_write_safe(args->dest, args->src, args->size);
+       return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_mali.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_mali.c
new file mode 100755 (executable)
index 0000000..e03b744
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_mali.c
+ * Implementation of the OS abstraction layer which is specific for the Mali kernel device driver
+ */
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mali/mali_utgard.h>
+
+#include "mali_osk_mali.h"
+#include "mali_kernel_common.h" /* MALI_xxx macros */
+#include "mali_osk.h"           /* kernel side OS functions */
+#include "mali_kernel_linux.h"
+
+static u32 _mali_osk_resource_irq(_mali_osk_resource_t *res)
+{
+       int i;
+       char name[32];
+       struct resource *resource;
+
+       snprintf(name, sizeof(name), "%s_IRQ", res->description);
+       for (i = 0; i < mali_platform_device->num_resources; i++) {
+               resource = &mali_platform_device->resource[i];
+               if (IORESOURCE_IRQ == resource_type(resource) &&
+                   !strncmp(name, resource->name, sizeof(name)))
+                       return resource->start;
+       }
+
+       return -1;
+}
+
+_mali_osk_errcode_t _mali_osk_resource_find(u32 addr, _mali_osk_resource_t *res)
+{
+       int i;
+
+       if (NULL == mali_platform_device) {
+               /* Not connected to a device */
+               return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       }
+
+       for (i = 0; i < mali_platform_device->num_resources; i++) {
+               if (IORESOURCE_MEM == resource_type(&(mali_platform_device->resource[i])) &&
+                   mali_platform_device->resource[i].start == addr) {
+                       if (NULL != res) {
+                               res->base = addr;
+                               res->description = mali_platform_device->resource[i].name;
+
+                               res->irq = _mali_osk_resource_irq(res);
+#if 0
+                               /* Any (optional) IRQ resource belonging to this resource will follow */
+                               if ((i + 1) < mali_platform_device->num_resources &&
+                                   IORESOURCE_IRQ == resource_type(&(mali_platform_device->resource[i+1]))) {
+                                       res->irq = mali_platform_device->resource[i+1].start;
+                               } else {
+                                       res->irq = -1;
+                               }
+#endif
+                       }
+                       return _MALI_OSK_ERR_OK;
+               }
+       }
+
+       return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+}
+
+u32 _mali_osk_resource_base_address(void)
+{
+       u32 lowest_addr = 0xFFFFFFFF;
+       u32 ret = 0;
+
+       if (NULL != mali_platform_device) {
+               int i;
+               for (i = 0; i < mali_platform_device->num_resources; i++) {
+                       if (mali_platform_device->resource[i].flags & IORESOURCE_MEM &&
+                           mali_platform_device->resource[i].start < lowest_addr) {
+                               lowest_addr = mali_platform_device->resource[i].start;
+                               ret = lowest_addr;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data)
+{
+       MALI_DEBUG_ASSERT_POINTER(data);
+
+       if (NULL != mali_platform_device) {
+               struct mali_gpu_device_data* os_data = NULL;
+
+               os_data = (struct mali_gpu_device_data*)mali_platform_device->dev.platform_data;
+               if (NULL != os_data) {
+                       /* Copy data from OS dependant struct to Mali neutral struct (identical!) */
+                       data->dedicated_mem_start = os_data->dedicated_mem_start;
+                       data->dedicated_mem_size = os_data->dedicated_mem_size;
+                       data->shared_mem_size = os_data->shared_mem_size;
+                       data->fb_start = os_data->fb_start;
+                       data->fb_size = os_data->fb_size;
+                       data->max_job_runtime = os_data->max_job_runtime;
+                       data->utilization_interval = os_data->utilization_interval;
+                       data->utilization_callback = os_data->utilization_callback;
+                       data->pmu_switch_delay = os_data->pmu_switch_delay;
+                       data->set_freq_callback = os_data->set_freq_callback;
+
+                       memcpy(data->pmu_domain_config, os_data->pmu_domain_config, sizeof(os_data->pmu_domain_config));
+                       return _MALI_OSK_ERR_OK;
+               }
+       }
+
+       return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+}
+
+mali_bool _mali_osk_shared_interrupts(void)
+{
+       u32 irqs[128];
+       u32 i, j, irq, num_irqs_found = 0;
+
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources);
+
+       for (i = 0; i < mali_platform_device->num_resources; i++) {
+               if (IORESOURCE_IRQ & mali_platform_device->resource[i].flags) {
+                       irq = mali_platform_device->resource[i].start;
+
+                       for (j = 0; j < num_irqs_found; ++j) {
+                               if (irq == irqs[j]) {
+                                       return MALI_TRUE;
+                               }
+                       }
+
+                       irqs[num_irqs_found++] = irq;
+               }
+       }
+
+       return MALI_FALSE;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_math.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_math.c
new file mode 100755 (executable)
index 0000000..08d4ced
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_math.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include "mali_osk.h"
+#include <linux/bitops.h>
+
+u32 _mali_osk_clz( u32 input )
+{
+       return 32-fls(input);
+}
+
+u32 _mali_osk_fls( u32 input )
+{
+       return fls(input);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_memory.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_memory.c
new file mode 100755 (executable)
index 0000000..9774294
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_memory.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include "mali_osk.h"
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+void inline *_mali_osk_calloc( u32 n, u32 size )
+{
+       return kcalloc(n, size, GFP_KERNEL);
+}
+
+void inline *_mali_osk_malloc( u32 size )
+{
+       return kmalloc(size, GFP_KERNEL);
+}
+
+void inline _mali_osk_free( void *ptr )
+{
+       kfree(ptr);
+}
+
+void inline *_mali_osk_valloc( u32 size )
+{
+       return vmalloc(size);
+}
+
+void inline _mali_osk_vfree( void *ptr )
+{
+       vfree(ptr);
+}
+
+void inline *_mali_osk_memcpy( void *dst, const void *src, u32 len )
+{
+       return memcpy(dst, src, len);
+}
+
+void inline *_mali_osk_memset( void *s, u32 c, u32 n )
+{
+       return memset(s, c, n);
+}
+
+mali_bool _mali_osk_mem_check_allocated( u32 max_allocated )
+{
+       /* No need to prevent an out-of-memory dialogue appearing on Linux,
+        * so we always return MALI_TRUE.
+        */
+       return MALI_TRUE;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_misc.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_misc.c
new file mode 100755 (executable)
index 0000000..81bf5f9
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_misc.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include "mali_osk.h"
+
+void _mali_osk_dbgmsg( const char *fmt, ... )
+{
+       va_list args;
+       va_start(args, fmt);
+       vprintk(fmt, args);
+       va_end(args);
+}
+
+u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... )
+{
+       int res;
+       va_list args;
+       va_start(args, fmt);
+
+       res = vscnprintf(buf, (size_t)size, fmt, args);
+
+       va_end(args);
+       return res;
+}
+
+void _mali_osk_abort(void)
+{
+       /* make a simple fault by dereferencing a NULL pointer */
+       dump_stack();
+       *(int *)0 = 0;
+}
+
+void _mali_osk_break(void)
+{
+       _mali_osk_abort();
+}
+
+u32 _mali_osk_get_pid(void)
+{
+       /* Thread group ID is the process ID on Linux */
+       return (u32)current->tgid;
+}
+
+u32 _mali_osk_get_tid(void)
+{
+       /* pid is actually identifying the thread on Linux */
+       u32 tid = current->pid;
+
+       /* If the pid is 0 the core was idle.  Instead of returning 0 we return a special number
+        * identifying which core we are on. */
+       if (0 == tid) {
+               tid = -(1 + raw_smp_processor_id());
+       }
+
+       return tid;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_notification.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_notification.c
new file mode 100755 (executable)
index 0000000..0afcb76
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_notification.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/**
+ * Declaration of the notification queue object type
+ * Contains a linked list of notification pending delivery to user space.
+ * It also contains a wait queue of exclusive waiters blocked in the ioctl
+ * When a new notification is posted a single thread is resumed.
+ */
+struct _mali_osk_notification_queue_t_struct {
+       spinlock_t mutex; /**< Mutex protecting the list */
+       wait_queue_head_t receive_queue; /**< Threads waiting for new entries to the queue */
+       struct list_head head; /**< List of notifications waiting to be picked up */
+};
+
+typedef struct _mali_osk_notification_wrapper_t_struct {
+       struct list_head list;           /**< Internal linked list variable */
+       _mali_osk_notification_t data;   /**< Notification data */
+} _mali_osk_notification_wrapper_t;
+
+_mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void )
+{
+       _mali_osk_notification_queue_t *        result;
+
+       result = (_mali_osk_notification_queue_t *)kmalloc(sizeof(_mali_osk_notification_queue_t), GFP_KERNEL);
+       if (NULL == result) return NULL;
+
+       spin_lock_init(&result->mutex);
+       init_waitqueue_head(&result->receive_queue);
+       INIT_LIST_HEAD(&result->head);
+
+       return result;
+}
+
+_mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
+{
+       /* OPT Recycling of notification objects */
+       _mali_osk_notification_wrapper_t *notification;
+
+       notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size,
+                      GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT);
+       if (NULL == notification) {
+               MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n"));
+               return NULL;
+       }
+
+       /* Init the list */
+       INIT_LIST_HEAD(&notification->list);
+
+       if (0 != size) {
+               notification->data.result_buffer = ((u8*)notification) + sizeof(_mali_osk_notification_wrapper_t);
+       } else {
+               notification->data.result_buffer = NULL;
+       }
+
+       /* set up the non-allocating fields */
+       notification->data.notification_type = type;
+       notification->data.result_buffer_size = size;
+
+       /* all ok */
+       return &(notification->data);
+}
+
+void _mali_osk_notification_delete( _mali_osk_notification_t *object )
+{
+       _mali_osk_notification_wrapper_t *notification;
+       MALI_DEBUG_ASSERT_POINTER( object );
+
+       notification = container_of( object, _mali_osk_notification_wrapper_t, data );
+
+       /* Free the container */
+       kfree(notification);
+}
+
+void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue )
+{
+       _mali_osk_notification_t *result;
+       MALI_DEBUG_ASSERT_POINTER( queue );
+
+       while (_MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, &result)) {
+               _mali_osk_notification_delete( result );
+       }
+
+       /* not much to do, just free the memory */
+       kfree(queue);
+}
+void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object )
+{
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       unsigned long irq_flags;
+#endif
+
+       _mali_osk_notification_wrapper_t *notification;
+       MALI_DEBUG_ASSERT_POINTER( queue );
+       MALI_DEBUG_ASSERT_POINTER( object );
+
+       notification = container_of( object, _mali_osk_notification_wrapper_t, data );
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       spin_lock_irqsave(&queue->mutex, irq_flags);
+#else
+       spin_lock(&queue->mutex);
+#endif
+
+       list_add_tail(&notification->list, &queue->head);
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       spin_unlock_irqrestore(&queue->mutex, irq_flags);
+#else
+       spin_unlock(&queue->mutex);
+#endif
+
+       /* and wake up one possible exclusive waiter */
+       wake_up(&queue->receive_queue);
+}
+
+_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result )
+{
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       unsigned long irq_flags;
+#endif
+
+       _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND;
+       _mali_osk_notification_wrapper_t *wrapper_object;
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       spin_lock_irqsave(&queue->mutex, irq_flags);
+#else
+       spin_lock(&queue->mutex);
+#endif
+
+       if (!list_empty(&queue->head)) {
+               wrapper_object = list_entry(queue->head.next, _mali_osk_notification_wrapper_t, list);
+               *result = &(wrapper_object->data);
+               list_del_init(&wrapper_object->list);
+               ret = _MALI_OSK_ERR_OK;
+       }
+
+#if defined(MALI_UPPER_HALF_SCHEDULING)
+       spin_unlock_irqrestore(&queue->mutex, irq_flags);
+#else
+       spin_unlock(&queue->mutex);
+#endif
+
+       return ret;
+}
+
+_mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result )
+{
+       /* check input */
+       MALI_DEBUG_ASSERT_POINTER( queue );
+       MALI_DEBUG_ASSERT_POINTER( result );
+
+       /* default result */
+       *result = NULL;
+
+       if (wait_event_interruptible(queue->receive_queue,
+                                    _MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, result))) {
+               return _MALI_OSK_ERR_RESTARTSYSCALL;
+       }
+
+       return _MALI_OSK_ERR_OK; /* all ok */
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_pm.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_pm.c
new file mode 100755 (executable)
index 0000000..b115267
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_pm.c
+ * Implementation of the callback functions from common power management
+ */
+
+#include <linux/sched.h>
+
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif /* CONFIG_PM_RUNTIME */
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_linux.h"
+
+static _mali_osk_atomic_t mali_pm_ref_count;
+
+void _mali_osk_pm_dev_enable(void)
+{
+       _mali_osk_atomic_init(&mali_pm_ref_count, 0);
+}
+
+void _mali_osk_pm_dev_disable(void)
+{
+       _mali_osk_atomic_term(&mali_pm_ref_count);
+}
+
+/* Can NOT run in atomic context */
+_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       int err;
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       err = pm_runtime_get_sync(&(mali_platform_device->dev));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+       pm_runtime_mark_last_busy(&(mali_platform_device->dev));
+#endif
+       if (0 > err) {
+               MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get_sync() returned error code %d\n", err));
+               return _MALI_OSK_ERR_FAULT;
+       }
+       _mali_osk_atomic_inc(&mali_pm_ref_count);
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
+#endif
+       return _MALI_OSK_ERR_OK;
+}
+
+/* Can run in atomic context */
+void _mali_osk_pm_dev_ref_dec(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       _mali_osk_atomic_dec(&mali_pm_ref_count);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+       pm_runtime_mark_last_busy(&(mali_platform_device->dev));
+       pm_runtime_put_autosuspend(&(mali_platform_device->dev));
+#else
+       pm_runtime_put(&(mali_platform_device->dev));
+#endif
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
+#endif
+}
+
+/* Can run in atomic context */
+mali_bool _mali_osk_pm_dev_ref_add_no_power_on(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       u32 ref;
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+       pm_runtime_get_noresume(&(mali_platform_device->dev));
+       ref = _mali_osk_atomic_read(&mali_pm_ref_count);
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
+       return ref > 0 ? MALI_TRUE : MALI_FALSE;
+#else
+       return MALI_TRUE;
+#endif
+}
+
+/* Can run in atomic context */
+void _mali_osk_pm_dev_ref_dec_no_power_on(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+       pm_runtime_put_autosuspend(&(mali_platform_device->dev));
+#else
+       pm_runtime_put(&(mali_platform_device->dev));
+#endif
+       MALI_DEBUG_PRINT(4, ("Mali OSK PM: No-power ref released (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
+#endif
+}
+
+void _mali_osk_pm_dev_barrier(void)
+{
+#ifdef CONFIG_PM_RUNTIME
+       pm_runtime_barrier(&(mali_platform_device->dev));
+#endif
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_profiling.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_profiling.c
new file mode 100755 (executable)
index 0000000..bb89be6
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include <linux/module.h>
+
+#include <mali_profiling_gator_api.h>
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_ukk.h"
+#include "mali_uk_types.h"
+#include "mali_osk_profiling.h"
+#include "mali_linux_trace.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_pp_scheduler.h"
+#include "mali_l2_cache.h"
+#include "mali_user_settings_db.h"
+
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start)
+{
+       if (MALI_TRUE == auto_start) {
+               mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE);
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_profiling_term(void)
+{
+       /* Nothing to do */
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit)
+{
+       /* Nothing to do */
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count)
+{
+       /* Nothing to do */
+       return _MALI_OSK_ERR_OK;
+}
+
+u32 _mali_osk_profiling_get_count(void)
+{
+       return 0;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
+{
+       /* Nothing to do */
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_clear(void)
+{
+       /* Nothing to do */
+       return _MALI_OSK_ERR_OK;
+}
+
+mali_bool _mali_osk_profiling_is_recording(void)
+{
+       return MALI_FALSE;
+}
+
+mali_bool _mali_osk_profiling_have_recording(void)
+{
+       return MALI_FALSE;
+}
+
+void _mali_osk_profiling_report_sw_counters(u32 *counters)
+{
+       trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters);
+}
+
+
+_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args)
+{
+       return _mali_osk_profiling_start(&args->limit);
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args)
+{
+       /* Always add process and thread identificator in the first two data elements for events from user space */
+       _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]);
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args)
+{
+       return _mali_osk_profiling_stop(&args->count);
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args)
+{
+       return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data);
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args)
+{
+       return _mali_osk_profiling_clear();
+}
+
+_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args)
+{
+       _mali_osk_profiling_report_sw_counters(args->counters);
+       return _MALI_OSK_ERR_OK;
+}
+
+/**
+ * Called by gator.ko to set HW counters
+ *
+ * @param counter_id The counter ID.
+ * @param event_id Event ID that the counter should count (HW counter value from TRM).
+ *
+ * @return 1 on success, 0 on failure.
+ */
+int _mali_profiling_set_event(u32 counter_id, s32 event_id)
+{
+       if (COUNTER_VP_0_C0 == counter_id) {
+               mali_gp_job_set_gp_counter_src0(event_id);
+       } else if (COUNTER_VP_0_C1 == counter_id) {
+               mali_gp_job_set_gp_counter_src1(event_id);
+       } else if (COUNTER_FP_0_C0 <= counter_id && COUNTER_FP_7_C1 >= counter_id) {
+               /*
+                * Two compatibility notes for this function:
+                *
+                * 1) Previously the DDK allowed per core counters.
+                *
+                *    This did not make much sense on Mali-450 with the "virtual PP core" concept,
+                *    so this option was removed, and only the same pair of HW counters was allowed on all cores,
+                *    beginning with r3p2 release.
+                *
+                *    Starting with r4p0, it is now possible to set different HW counters for the different sub jobs.
+                *    This should be almost the same, since sub job 0 is designed to run on core 0,
+                *    sub job 1 on core 1, and so on.
+                *
+                *    The scheduling of PP sub jobs is not predictable, and this often led to situations where core 0 ran 2
+                *    sub jobs, while for instance core 1 ran zero. Having the counters set per sub job would thus increase
+                *    the predictability of the returned data (as you would be guaranteed data for all the selected HW counters).
+                *
+                *    PS: Core scaling needs to be disabled in order to use this reliably (goes for both solutions).
+                *
+                *    The framework/#defines with Gator still indicates that the counter is for a particular core,
+                *    but this is internally used as a sub job ID instead (no translation needed).
+                *
+                *  2) Global/default vs per sub job counters
+                *
+                *     Releases before r3p2 had only per PP core counters.
+                *     r3p2 releases had only one set of default/global counters which applied to all PP cores
+                *     Starting with r4p0, we have both a set of default/global counters,
+                *     and individual counters per sub job (equal to per core).
+                *
+                *     To keep compatibility with Gator/DS-5/streamline, the following scheme is used:
+                *
+                *     r3p2 release; only counters set for core 0 is handled,
+                *     this is applied as the default/global set of counters, and will thus affect all cores.
+                *
+                *     r4p0 release; counters set for core 0 is applied as both the global/default set of counters,
+                *     and counters for sub job 0.
+                *     Counters set for core 1-7 is only applied for the corresponding sub job.
+                *
+                *     This should allow the DS-5/Streamline GUI to have a simple mode where it only allows setting the
+                *     values for core 0, and thus this will be applied to all PP sub jobs/cores.
+                *     Advanced mode will also be supported, where individual pairs of HW counters can be selected.
+                *
+                *     The GUI will (until it is updated) still refer to cores instead of sub jobs, but this is probably
+                *     something we can live with!
+                *
+                *     Mali-450 note: Each job is not divided into a deterministic number of sub jobs, as the HW DLBU
+                *     automatically distributes the load between whatever number of cores is available at this particular time.
+                *     A normal PP job on Mali-450 is thus considered a single (virtual) job, and it will thus only be possible
+                *     to use a single pair of HW counters (even if the job ran on multiple PP cores).
+                *     In other words, only the global/default pair of PP HW counters will be used for normal Mali-450 jobs.
+                */
+               u32 sub_job = (counter_id - COUNTER_FP_0_C0) >> 1;
+               u32 counter_src = (counter_id - COUNTER_FP_0_C0) & 1;
+               if (0 == counter_src) {
+                       mali_pp_job_set_pp_counter_sub_job_src0(sub_job, event_id);
+                       if (0 == sub_job) {
+                               mali_pp_job_set_pp_counter_global_src0(event_id);
+                       }
+               } else {
+                       mali_pp_job_set_pp_counter_sub_job_src1(sub_job, event_id);
+                       if (0 == sub_job) {
+                               mali_pp_job_set_pp_counter_global_src1(event_id);
+                       }
+               }
+       } else if (COUNTER_L2_0_C0 <= counter_id && COUNTER_L2_2_C1 >= counter_id) {
+               u32 core_id = (counter_id - COUNTER_L2_0_C0) >> 1;
+               struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id);
+
+               if (NULL != l2_cache_core) {
+                       u32 counter_src = (counter_id - COUNTER_L2_0_C0) & 1;
+                       if (0 == counter_src) {
+                               mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id);
+                       } else {
+                               mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id);
+                       }
+               }
+       } else {
+               return 0; /* Failure, unknown event */
+       }
+
+       return 1; /* success */
+}
+
+/**
+ * Called by gator.ko to retrieve the L2 cache counter values for all L2 cache cores.
+ * The L2 cache counters are unique in that they are polled by gator, rather than being
+ * transmitted via the tracepoint mechanism.
+ *
+ * @param values Pointer to a _mali_profiling_l2_counter_values structure where
+ *               the counter sources and values will be output
+ * @return 0 if all went well; otherwise, return the mask with the bits set for the powered off cores
+ */
+u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values)
+{
+       struct mali_l2_cache_core *l2_cache;
+       u32 l2_cores_num = mali_l2_cache_core_get_glob_num_l2_cores();
+       u32 i;
+       u32 ret = 0;
+
+       MALI_DEBUG_ASSERT(l2_cores_num <= 3);
+
+       for (i = 0; i < l2_cores_num; i++) {
+               l2_cache = mali_l2_cache_core_get_glob_l2_core(i);
+
+               if (NULL == l2_cache) {
+                       continue;
+               }
+
+               if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) {
+                       /* It is now safe to access the L2 cache core in order to retrieve the counters */
+                       mali_l2_cache_core_get_counter_values(l2_cache,
+                                                             &values->cores[i].source0,
+                                                             &values->cores[i].value0,
+                                                             &values->cores[i].source1,
+                                                             &values->cores[i].value1);
+               } else {
+                       /* The core was not available, set the right bit in the mask. */
+                       ret |= (1 << i);
+               }
+               mali_l2_cache_unlock_power_state(l2_cache);
+       }
+
+       return ret;
+}
+
+/**
+ * Called by gator to control the production of profiling information at runtime.
+ */
+void _mali_profiling_control(u32 action, u32 value)
+{
+       switch(action) {
+       case FBDUMP_CONTROL_ENABLE:
+               mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE));
+               break;
+       case FBDUMP_CONTROL_RATE:
+               mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value);
+               break;
+       case SW_COUNTER_ENABLE:
+               mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value);
+               break;
+       case FBDUMP_CONTROL_RESIZE_FACTOR:
+               mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value);
+               break;
+       default:
+               break;  /* Ignore unimplemented actions */
+       }
+}
+
+/**
+ * Called by gator to get mali api version.
+ */
+u32 _mali_profiling_get_api_version(void)
+{
+       return MALI_PROFILING_API_VERSION;
+}
+
+/**
+* Called by gator to get the data about Mali instance in use:
+* product id, version, number of cores
+*/
+void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values)
+{
+       values->mali_product_id = (u32)mali_kernel_core_get_product_id();
+       values->mali_version_major = mali_kernel_core_get_gpu_major_version();
+       values->mali_version_minor = mali_kernel_core_get_gpu_minor_version();
+       values->num_of_l2_cores = mali_l2_cache_core_get_glob_num_l2_cores();
+       values->num_of_fp_cores = mali_pp_scheduler_get_num_cores_total();
+       values->num_of_vp_cores = 1;
+}
+
+EXPORT_SYMBOL(_mali_profiling_set_event);
+EXPORT_SYMBOL(_mali_profiling_get_l2_counters);
+EXPORT_SYMBOL(_mali_profiling_control);
+EXPORT_SYMBOL(_mali_profiling_get_api_version);
+EXPORT_SYMBOL(_mali_profiling_get_mali_version);
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_specific.h b/drivers/gpu/arm/mali400/mali/linux/mali_osk_specific.h
new file mode 100755 (executable)
index 0000000..c0d4f5d
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_specific.h
+ * Defines per-OS Kernel level specifics, such as unusual workarounds for
+ * certain OSs.
+ */
+
+#ifndef __MALI_OSK_SPECIFIC_H__
+#define __MALI_OSK_SPECIFIC_H__
+
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/dmapool.h>
+#include <linux/gfp.h>
+#include <linux/hardirq.h>
+
+#include "mali_osk_types.h"
+#include "mali_kernel_linux.h"
+
+#define MALI_STATIC_INLINE static inline
+#define MALI_NON_STATIC_INLINE inline
+
+typedef struct dma_pool * mali_dma_pool;
+
+
+MALI_STATIC_INLINE mali_dma_pool mali_dma_pool_create(u32 size, u32 alignment, u32 boundary)
+{
+       return dma_pool_create("mali-dma", &mali_platform_device->dev, size, alignment, boundary);
+}
+
+MALI_STATIC_INLINE void mali_dma_pool_destroy(mali_dma_pool pool)
+{
+       dma_pool_destroy(pool);
+}
+
+MALI_STATIC_INLINE mali_io_address mali_dma_pool_alloc(mali_dma_pool pool, u32 *phys_addr)
+{
+       return dma_pool_alloc(pool, GFP_KERNEL, phys_addr);
+}
+
+MALI_STATIC_INLINE void mali_dma_pool_free(mali_dma_pool pool, void* virt_addr, u32 phys_addr)
+{
+       dma_pool_free(pool, virt_addr, phys_addr);
+}
+
+
+#if MALI_ENABLE_CPU_CYCLES
+/* Reads out the clock cycle performance counter of the current cpu.
+   It is useful for cost-free (2 cycle) measuring of the time spent
+   in a code path. Sample before and after, the diff number of cycles.
+   When the CPU is idle it will not increase this clock counter.
+   It means that the counter is accurate if only spin-locks are used,
+   but mutexes may lead to too low values since the cpu might "idle"
+   waiting for the mutex to become available.
+   The clock source is configured on the CPU during mali module load,
+   but will not give useful output after a CPU has been power cycled.
+   It is therefore important to configure the system to not turn of
+   the cpu cores when using this functionallity.*/
+static inline unsigned int mali_get_cpu_cyclecount(void)
+{
+       unsigned int value;
+       /* Reading the CCNT Register - CPU clock counter */
+       asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
+       return value;
+}
+
+void mali_init_cpu_time_counters(int reset, int enable_divide_by_64);
+#endif
+
+
+MALI_STATIC_INLINE u32 _mali_osk_copy_from_user(void *to, void *from, u32 n)
+{
+       return (u32)copy_from_user(to, from, (unsigned long)n);
+}
+
+MALI_STATIC_INLINE mali_bool _mali_osk_in_atomic(void)
+{
+       return in_atomic();
+}
+
+#define _mali_osk_put_user(x, ptr) put_user(x, ptr)
+
+#endif /* __MALI_OSK_SPECIFIC_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_time.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_time.c
new file mode 100755 (executable)
index 0000000..3a0b354
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_time.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include "mali_osk.h"
+#include <linux/jiffies.h>
+#include <linux/time.h>
+#include <asm/delay.h>
+
+int    _mali_osk_time_after( u32 ticka, u32 tickb )
+{
+       return time_after((unsigned long)ticka, (unsigned long)tickb);
+}
+
+u32    _mali_osk_time_mstoticks( u32 ms )
+{
+       return msecs_to_jiffies(ms);
+}
+
+u32    _mali_osk_time_tickstoms( u32 ticks )
+{
+       return jiffies_to_msecs(ticks);
+}
+
+u32    _mali_osk_time_tickcount( void )
+{
+       return jiffies;
+}
+
+void _mali_osk_time_ubusydelay( u32 usecs )
+{
+       udelay(usecs);
+}
+
+u64 _mali_osk_time_get_ns( void )
+{
+       struct timespec tsval;
+       getnstimeofday(&tsval);
+       return (u64)timespec_to_ns(&tsval);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_timers.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_timers.c
new file mode 100755 (executable)
index 0000000..e1f0df7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_timers.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+struct _mali_osk_timer_t_struct {
+       struct timer_list timer;
+};
+
+typedef void (*timer_timeout_function_t)(unsigned long);
+
+_mali_osk_timer_t *_mali_osk_timer_init(void)
+{
+       _mali_osk_timer_t *t = (_mali_osk_timer_t*)kmalloc(sizeof(_mali_osk_timer_t), GFP_KERNEL);
+       if (NULL != t) init_timer(&t->timer);
+       return t;
+}
+
+void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       tim->timer.expires = jiffies + ticks_to_expire;
+       add_timer(&(tim->timer));
+}
+
+void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 ticks_to_expire)
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       mod_timer(&(tim->timer), jiffies + ticks_to_expire);
+}
+
+void _mali_osk_timer_del( _mali_osk_timer_t *tim )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       del_timer_sync(&(tim->timer));
+}
+
+void _mali_osk_timer_del_async( _mali_osk_timer_t *tim )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       del_timer(&(tim->timer));
+}
+
+mali_bool _mali_osk_timer_pending( _mali_osk_timer_t *tim )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       return 1 == timer_pending(&(tim->timer));
+}
+
+void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       tim->timer.data = (unsigned long)data;
+       tim->timer.function = (timer_timeout_function_t)callback;
+}
+
+void _mali_osk_timer_term( _mali_osk_timer_t *tim )
+{
+       MALI_DEBUG_ASSERT_POINTER(tim);
+       kfree(tim);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_wait_queue.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_wait_queue.c
new file mode 100755 (executable)
index 0000000..fe2cc8b
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_wait_queue.c
+ * Implemenation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+struct _mali_osk_wait_queue_t_struct {
+       wait_queue_head_t wait_queue;
+};
+
+_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void )
+{
+       _mali_osk_wait_queue_t* ret = NULL;
+
+       ret = kmalloc(sizeof(_mali_osk_wait_queue_t), GFP_KERNEL);
+
+       if (NULL == ret) {
+               return ret;
+       }
+
+       init_waitqueue_head(&ret->wait_queue);
+       MALI_DEBUG_ASSERT(!waitqueue_active(&ret->wait_queue));
+
+       return ret;
+}
+
+void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void *), void *data )
+{
+       MALI_DEBUG_ASSERT_POINTER( queue );
+       MALI_DEBUG_PRINT(6, ("Adding to wait queue %p\n", queue));
+       wait_event(queue->wait_queue, condition(data));
+}
+
+void _mali_osk_wait_queue_wait_event_timeout( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void *), void *data, u32 timeout )
+{
+       MALI_DEBUG_ASSERT_POINTER( queue );
+       MALI_DEBUG_PRINT(6, ("Adding to wait queue %p\n", queue));
+       wait_event_timeout(queue->wait_queue, condition(data), _mali_osk_time_mstoticks(timeout));
+}
+
+void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue )
+{
+       MALI_DEBUG_ASSERT_POINTER( queue );
+
+       /* if queue is empty, don't attempt to wake up its elements */
+       if (!waitqueue_active(&queue->wait_queue)) return;
+
+       MALI_DEBUG_PRINT(6, ("Waking up elements in wait queue %p ....\n", queue));
+
+       wake_up_all(&queue->wait_queue);
+
+       MALI_DEBUG_PRINT(6, ("... elements in wait queue %p woken up\n", queue));
+}
+
+void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue )
+{
+       /* Parameter validation  */
+       MALI_DEBUG_ASSERT_POINTER( queue );
+
+       /* Linux requires no explicit termination of wait queues */
+       kfree(queue);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_osk_wq.c b/drivers/gpu/arm/mali400/mali/linux/mali_osk_wq.c
new file mode 100755 (executable)
index 0000000..5467dcd
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_osk_wq.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <linux/slab.h>        /* For memory allocation */
+#include <linux/workqueue.h>
+#include <linux/version.h>
+#include <linux/sched.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_license.h"
+#include "mali_kernel_linux.h"
+
+typedef struct _mali_osk_wq_work_s {
+       _mali_osk_wq_work_handler_t handler;
+       void *data;
+       mali_bool high_pri;
+       struct work_struct work_handle;
+} mali_osk_wq_work_object_t;
+
+typedef struct _mali_osk_wq_delayed_work_s {
+       _mali_osk_wq_work_handler_t handler;
+       void *data;
+       struct delayed_work work;
+} mali_osk_wq_delayed_work_object_t;
+
+#if MALI_LICENSE_IS_GPL
+struct workqueue_struct *mali_wq_normal = NULL;
+struct workqueue_struct *mali_wq_high = NULL;
+#endif
+
+static void _mali_osk_wq_work_func(struct work_struct *work);
+
+_mali_osk_errcode_t _mali_osk_wq_init(void)
+{
+#if MALI_LICENSE_IS_GPL
+       MALI_DEBUG_ASSERT(NULL == mali_wq_normal);
+       MALI_DEBUG_ASSERT(NULL == mali_wq_high);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+       mali_wq_normal = alloc_workqueue("mali", WQ_UNBOUND, 0);
+       mali_wq_high = alloc_workqueue("mali_high_pri", WQ_HIGHPRI, 0);
+#else
+       mali_wq_normal = create_workqueue("mali");
+       mali_wq_high = create_workqueue("mali_high_pri");
+#endif
+       if (NULL == mali_wq_normal || NULL == mali_wq_high) {
+               MALI_PRINT_ERROR(("Unable to create Mali workqueues\n"));
+
+               if (mali_wq_normal) destroy_workqueue(mali_wq_normal);
+               if (mali_wq_high)   destroy_workqueue(mali_wq_high);
+
+               mali_wq_normal = NULL;
+               mali_wq_high   = NULL;
+
+               return _MALI_OSK_ERR_FAULT;
+       }
+#endif /* MALI_LICENSE_IS_GPL */
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_wq_flush(void)
+{
+#if MALI_LICENSE_IS_GPL
+       flush_workqueue(mali_wq_high);
+       flush_workqueue(mali_wq_normal);
+#else
+       flush_scheduled_work();
+#endif
+}
+
+void _mali_osk_wq_term(void)
+{
+#if MALI_LICENSE_IS_GPL
+       MALI_DEBUG_ASSERT(NULL != mali_wq_normal);
+       MALI_DEBUG_ASSERT(NULL != mali_wq_high);
+
+       flush_workqueue(mali_wq_normal);
+       destroy_workqueue(mali_wq_normal);
+
+       flush_workqueue(mali_wq_high);
+       destroy_workqueue(mali_wq_high);
+
+       mali_wq_normal = NULL;
+       mali_wq_high   = NULL;
+#else
+       flush_scheduled_work();
+#endif
+}
+
+_mali_osk_wq_work_t *_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler, void *data )
+{
+       mali_osk_wq_work_object_t *work = kmalloc(sizeof(mali_osk_wq_work_object_t), GFP_KERNEL);
+
+       if (NULL == work) return NULL;
+
+       work->handler = handler;
+       work->data = data;
+       work->high_pri = MALI_FALSE;
+
+       INIT_WORK( &work->work_handle, _mali_osk_wq_work_func);
+
+       return work;
+}
+
+_mali_osk_wq_work_t *_mali_osk_wq_create_work_high_pri( _mali_osk_wq_work_handler_t handler, void *data )
+{
+       mali_osk_wq_work_object_t *work = kmalloc(sizeof(mali_osk_wq_work_object_t), GFP_KERNEL);
+
+       if (NULL == work) return NULL;
+
+       work->handler = handler;
+       work->data = data;
+       work->high_pri = MALI_TRUE;
+
+       INIT_WORK( &work->work_handle, _mali_osk_wq_work_func );
+
+       return work;
+}
+
+void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work )
+{
+       mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+       _mali_osk_wq_flush();
+       kfree(work_object);
+}
+
+void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work )
+{
+       mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+       kfree(work_object);
+}
+
+void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work )
+{
+       mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+#if MALI_LICENSE_IS_GPL
+       queue_work(mali_wq_normal, &work_object->work_handle);
+#else
+       schedule_work(&work_object->work_handle);
+#endif
+}
+
+void _mali_osk_wq_schedule_work_high_pri( _mali_osk_wq_work_t *work )
+{
+       mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+#if MALI_LICENSE_IS_GPL
+       queue_work(mali_wq_high, &work_object->work_handle);
+#else
+       schedule_work(&work_object->work_handle);
+#endif
+}
+
+static void _mali_osk_wq_work_func( struct work_struct *work )
+{
+       mali_osk_wq_work_object_t *work_object;
+
+       work_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_wq_work_object_t, work_handle);
+
+       /* We want higher priority than the Dynamic Priority, setting it to the lowest of the RT priorities */
+       if (MALI_TRUE == work_object->high_pri) {
+               set_user_nice(current, -19);
+       }
+
+       work_object->handler(work_object->data);
+}
+
+static void _mali_osk_wq_delayed_work_func( struct work_struct *work )
+{
+       mali_osk_wq_delayed_work_object_t *work_object;
+
+       work_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_wq_delayed_work_object_t, work.work);
+       work_object->handler(work_object->data);
+}
+
+mali_osk_wq_delayed_work_object_t *_mali_osk_wq_delayed_create_work( _mali_osk_wq_work_handler_t handler, void *data)
+{
+       mali_osk_wq_delayed_work_object_t *work = kmalloc(sizeof(mali_osk_wq_delayed_work_object_t), GFP_KERNEL);
+
+       if (NULL == work) return NULL;
+
+       work->handler = handler;
+       work->data = data;
+
+       INIT_DELAYED_WORK(&work->work, _mali_osk_wq_delayed_work_func);
+
+       return work;
+}
+
+void _mali_osk_wq_delayed_delete_work_nonflush( _mali_osk_wq_delayed_work_t *work )
+{
+       mali_osk_wq_delayed_work_object_t *work_object = (mali_osk_wq_delayed_work_object_t *)work;
+       kfree(work_object);
+}
+
+void _mali_osk_wq_delayed_cancel_work_async( _mali_osk_wq_delayed_work_t *work )
+{
+       mali_osk_wq_delayed_work_object_t *work_object = (mali_osk_wq_delayed_work_object_t *)work;
+       cancel_delayed_work(&work_object->work);
+}
+
+void _mali_osk_wq_delayed_cancel_work_sync( _mali_osk_wq_delayed_work_t *work )
+{
+       mali_osk_wq_delayed_work_object_t *work_object = (mali_osk_wq_delayed_work_object_t *)work;
+       cancel_delayed_work_sync(&work_object->work);
+}
+
+void _mali_osk_wq_delayed_schedule_work( _mali_osk_wq_delayed_work_t *work, u32 delay )
+{
+       mali_osk_wq_delayed_work_object_t *work_object = (mali_osk_wq_delayed_work_object_t *)work;
+
+#if MALI_LICENSE_IS_GPL
+       queue_delayed_work(mali_wq_normal, &work_object->work, delay);
+#else
+       schedule_delayed_work(&work_object->work, delay);
+#endif
+
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_pmu_power_up_down.c b/drivers/gpu/arm/mali400/mali/linux/mali_pmu_power_up_down.c
new file mode 100755 (executable)
index 0000000..7ad03de
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_pmu_power_up_down.c
+ */
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_pmu.h"
+#include "mali_pp_scheduler.h"
+#include "linux/mali/mali_utgard.h"
+
+/* Mali PMU power up/down APIs */
+
+int mali_pmu_powerup(void)
+{
+       struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+
+       MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n"));
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       if (NULL == pmu) {
+               return -ENXIO;
+       }
+
+       if (_MALI_OSK_ERR_OK != mali_pmu_power_up_all(pmu)) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(mali_pmu_powerup);
+
+int mali_pmu_powerdown(void)
+{
+       struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+
+       MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n"));
+
+       MALI_DEBUG_ASSERT_POINTER(pmu);
+       if (NULL == pmu) {
+               return -ENXIO;
+       }
+
+       if (_MALI_OSK_ERR_OK != mali_pmu_power_down_all(pmu)) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(mali_pmu_powerdown);
+
+int mali_perf_set_num_pp_cores(unsigned int num_cores)
+{
+       return mali_pp_scheduler_set_perf_level(num_cores, MALI_FALSE);
+}
+
+EXPORT_SYMBOL(mali_perf_set_num_pp_cores);
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_profiling_events.h b/drivers/gpu/arm/mali400/mali/linux/mali_profiling_events.h
new file mode 100755 (executable)
index 0000000..0164e81
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PROFILING_EVENTS_H__
+#define __MALI_PROFILING_EVENTS_H__
+
+/* Simple wrapper in order to find the OS specific location of this file */
+#include <linux/mali/mali_utgard_profiling_events.h>
+
+#endif /* __MALI_PROFILING_EVENTS_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_profiling_gator_api.h b/drivers/gpu/arm/mali400/mali/linux/mali_profiling_gator_api.h
new file mode 100755 (executable)
index 0000000..9736b4a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PROFILING_GATOR_API_H__
+#define __MALI_PROFILING_GATOR_API_H__
+
+/* Simple wrapper in order to find the OS specific location of this file */
+#include <linux/mali/mali_utgard_profiling_gator_api.h>
+
+#endif /* __MALI_PROFILING_GATOR_API_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_profiling_internal.c b/drivers/gpu/arm/mali400/mali/linux/mali_profiling_internal.c
new file mode 100755 (executable)
index 0000000..90dce62
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_ukk.h"
+#include "mali_timestamp.h"
+#include "mali_osk_profiling.h"
+#include "mali_user_settings_db.h"
+#include "mali_profiling_internal.h"
+
+typedef struct mali_profiling_entry {
+       u64 timestamp;
+       u32 event_id;
+       u32 data[5];
+} mali_profiling_entry;
+
+typedef enum mali_profiling_state {
+       MALI_PROFILING_STATE_UNINITIALIZED,
+       MALI_PROFILING_STATE_IDLE,
+       MALI_PROFILING_STATE_RUNNING,
+       MALI_PROFILING_STATE_RETURN,
+} mali_profiling_state;
+
+static _mali_osk_mutex_t *lock = NULL;
+static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
+static mali_profiling_entry* profile_entries = NULL;
+static _mali_osk_atomic_t profile_insert_index;
+static u32 profile_mask = 0;
+
+static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4);
+
+void probe_mali_timeline_event(void *data, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned
+                               int d2, unsigned int d3, unsigned int d4))
+{
+       add_event(event_id, d0, d1, d2, d3, d4);
+}
+
+_mali_osk_errcode_t _mali_internal_profiling_init(mali_bool auto_start)
+{
+       profile_entries = NULL;
+       profile_mask = 0;
+       _mali_osk_atomic_init(&profile_insert_index, 0);
+
+       lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_PROFILING);
+       if (NULL == lock) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       prof_state = MALI_PROFILING_STATE_IDLE;
+
+       if (MALI_TRUE == auto_start) {
+               u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */
+
+               mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE);
+               if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) {
+                       return _MALI_OSK_ERR_FAULT;
+               }
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void _mali_internal_profiling_term(void)
+{
+       u32 count;
+
+       /* Ensure profiling is stopped */
+       _mali_internal_profiling_stop(&count);
+
+       prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
+
+       if (NULL != profile_entries) {
+               _mali_osk_vfree(profile_entries);
+               profile_entries = NULL;
+       }
+
+       if (NULL != lock) {
+               _mali_osk_mutex_term(lock);
+               lock = NULL;
+       }
+}
+
+_mali_osk_errcode_t _mali_internal_profiling_start(u32 * limit)
+{
+       _mali_osk_errcode_t ret;
+       mali_profiling_entry *new_profile_entries;
+
+       _mali_osk_mutex_wait(lock);
+
+       if (MALI_PROFILING_STATE_RUNNING == prof_state) {
+               _mali_osk_mutex_signal(lock);
+               return _MALI_OSK_ERR_BUSY;
+       }
+
+       new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry));
+
+       if (NULL == new_profile_entries) {
+               _mali_osk_vfree(new_profile_entries);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       if (MALI_PROFILING_MAX_BUFFER_ENTRIES < *limit) {
+               *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES;
+       }
+
+       profile_mask = 1;
+       while (profile_mask <= *limit) {
+               profile_mask <<= 1;
+       }
+       profile_mask >>= 1;
+
+       *limit = profile_mask;
+
+       profile_mask--; /* turns the power of two into a mask of one less */
+
+       if (MALI_PROFILING_STATE_IDLE != prof_state) {
+               _mali_osk_mutex_signal(lock);
+               _mali_osk_vfree(new_profile_entries);
+               return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+       }
+
+       profile_entries = new_profile_entries;
+
+       ret = _mali_timestamp_reset();
+
+       if (_MALI_OSK_ERR_OK == ret) {
+               prof_state = MALI_PROFILING_STATE_RUNNING;
+       } else {
+               _mali_osk_vfree(profile_entries);
+               profile_entries = NULL;
+       }
+
+       register_trace_mali_timeline_event(probe_mali_timeline_event, NULL);
+
+       _mali_osk_mutex_signal(lock);
+       return ret;
+}
+
+static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4)
+{
+       u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) & profile_mask;
+
+       profile_entries[cur_index].timestamp = _mali_timestamp_get();
+       profile_entries[cur_index].event_id = event_id;
+       profile_entries[cur_index].data[0] = data0;
+       profile_entries[cur_index].data[1] = data1;
+       profile_entries[cur_index].data[2] = data2;
+       profile_entries[cur_index].data[3] = data3;
+       profile_entries[cur_index].data[4] = data4;
+
+       /* If event is "leave API function", add current memory usage to the event
+        * as data point 4.  This is used in timeline profiling to indicate how
+        * much memory was used when leaving a function. */
+       if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) {
+               profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage();
+       }
+}
+
+_mali_osk_errcode_t _mali_internal_profiling_stop(u32 * count)
+{
+       _mali_osk_mutex_wait(lock);
+
+       if (MALI_PROFILING_STATE_RUNNING != prof_state) {
+               _mali_osk_mutex_signal(lock);
+               return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+       }
+
+       /* go into return state (user to retreive events), no more events will be added after this */
+       prof_state = MALI_PROFILING_STATE_RETURN;
+
+       unregister_trace_mali_timeline_event(probe_mali_timeline_event, NULL);
+
+       _mali_osk_mutex_signal(lock);
+
+       tracepoint_synchronize_unregister();
+
+       *count = _mali_osk_atomic_read(&profile_insert_index);
+       if (*count > profile_mask) *count = profile_mask;
+
+       return _MALI_OSK_ERR_OK;
+}
+
+u32 _mali_internal_profiling_get_count(void)
+{
+       u32 retval = 0;
+
+       _mali_osk_mutex_wait(lock);
+       if (MALI_PROFILING_STATE_RETURN == prof_state) {
+               retval = _mali_osk_atomic_read(&profile_insert_index);
+               if (retval > profile_mask) retval = profile_mask;
+       }
+       _mali_osk_mutex_signal(lock);
+
+       return retval;
+}
+
+_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
+{
+       u32 raw_index = _mali_osk_atomic_read(&profile_insert_index);
+
+       _mali_osk_mutex_wait(lock);
+
+       if (index < profile_mask) {
+               if ((raw_index & ~profile_mask) != 0) {
+                       index += raw_index;
+                       index &= profile_mask;
+               }
+
+               if (prof_state != MALI_PROFILING_STATE_RETURN) {
+                       _mali_osk_mutex_signal(lock);
+                       return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+               }
+
+               if(index >= raw_index) {
+                       _mali_osk_mutex_signal(lock);
+                       return _MALI_OSK_ERR_FAULT;
+               }
+
+               *timestamp = profile_entries[index].timestamp;
+               *event_id = profile_entries[index].event_id;
+               data[0] = profile_entries[index].data[0];
+               data[1] = profile_entries[index].data[1];
+               data[2] = profile_entries[index].data[2];
+               data[3] = profile_entries[index].data[3];
+               data[4] = profile_entries[index].data[4];
+       } else {
+               _mali_osk_mutex_signal(lock);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       _mali_osk_mutex_signal(lock);
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_internal_profiling_clear(void)
+{
+       _mali_osk_mutex_wait(lock);
+
+       if (MALI_PROFILING_STATE_RETURN != prof_state) {
+               _mali_osk_mutex_signal(lock);
+               return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+       }
+
+       prof_state = MALI_PROFILING_STATE_IDLE;
+       profile_mask = 0;
+       _mali_osk_atomic_init(&profile_insert_index, 0);
+
+       if (NULL != profile_entries) {
+               _mali_osk_vfree(profile_entries);
+               profile_entries = NULL;
+       }
+
+       _mali_osk_mutex_signal(lock);
+       return _MALI_OSK_ERR_OK;
+}
+
+mali_bool _mali_internal_profiling_is_recording(void)
+{
+       return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE;
+}
+
+mali_bool _mali_internal_profiling_have_recording(void)
+{
+       return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_profiling_internal.h b/drivers/gpu/arm/mali400/mali/linux/mali_profiling_internal.h
new file mode 100755 (executable)
index 0000000..07ffbb5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_PROFILING_INTERNAL_H__
+#define __MALI_PROFILING_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mali_osk.h"
+
+int _mali_internal_profiling_init(mali_bool auto_start);
+void _mali_internal_profiling_term(void);
+
+mali_bool _mali_internal_profiling_is_recording(void);
+mali_bool _mali_internal_profiling_have_recording(void);
+_mali_osk_errcode_t _mali_internal_profiling_clear(void);
+_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]);
+u32 _mali_internal_profiling_get_count(void);
+int _mali_internal_profiling_stop(u32 * count);
+int _mali_internal_profiling_start(u32 * limit);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PROFILING_INTERNAL_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_sync.c b/drivers/gpu/arm/mali400/mali/linux/mali_sync.c
new file mode 100755 (executable)
index 0000000..9542eb1
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_sync.h"
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_timeline.h"
+
+#include <linux/file.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+
+struct mali_sync_pt {
+       struct sync_pt         sync_pt;
+       struct mali_sync_flag *flag;
+};
+
+/**
+ * The sync flag is used to connect sync fences to the Mali Timeline system.  Sync fences can be
+ * created from a sync flag, and when the flag is signaled, the sync fences will also be signaled.
+ */
+struct mali_sync_flag {
+       struct sync_timeline *sync_tl;  /**< Sync timeline this flag is connected to. */
+       u32                   point;    /**< Point on timeline. */
+       int                   status;   /**< 0 if unsignaled, 1 if signaled without error or negative if signaled with error. */
+       struct kref           refcount; /**< Reference count. */
+};
+
+MALI_STATIC_INLINE struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt)
+{
+       return container_of(pt, struct mali_sync_pt, sync_pt);
+}
+
+static struct sync_pt *timeline_dup(struct sync_pt *pt)
+{
+       struct mali_sync_pt *mpt, *new_mpt;
+       struct sync_pt *new_pt;
+
+       MALI_DEBUG_ASSERT_POINTER(pt);
+       mpt = to_mali_sync_pt(pt);
+
+       new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt));
+       if (NULL == new_pt) return NULL;
+
+       new_mpt = to_mali_sync_pt(new_pt);
+
+       mali_sync_flag_get(mpt->flag);
+       new_mpt->flag = mpt->flag;
+
+       return new_pt;
+}
+
+static int timeline_has_signaled(struct sync_pt *pt)
+{
+       struct mali_sync_pt *mpt;
+
+       MALI_DEBUG_ASSERT_POINTER(pt);
+       mpt = to_mali_sync_pt(pt);
+
+       MALI_DEBUG_ASSERT_POINTER(mpt->flag);
+
+       return mpt->flag->status;
+}
+
+static int timeline_compare(struct sync_pt *pta, struct sync_pt *ptb)
+{
+       struct mali_sync_pt *mpta;
+       struct mali_sync_pt *mptb;
+       u32 a, b;
+
+       MALI_DEBUG_ASSERT_POINTER(pta);
+       MALI_DEBUG_ASSERT_POINTER(ptb);
+       mpta = to_mali_sync_pt(pta);
+       mptb = to_mali_sync_pt(ptb);
+
+       MALI_DEBUG_ASSERT_POINTER(mpta->flag);
+       MALI_DEBUG_ASSERT_POINTER(mptb->flag);
+
+       a = mpta->flag->point;
+       b = mpta->flag->point;
+
+       if (a == b) return 0;
+
+       return ((b - a) < (a - b) ? -1 : 1);
+}
+
+static void timeline_free_pt(struct sync_pt *pt)
+{
+       struct mali_sync_pt *mpt;
+
+       MALI_DEBUG_ASSERT_POINTER(pt);
+       mpt = to_mali_sync_pt(pt);
+
+       mali_sync_flag_put(mpt->flag);
+}
+
+static void timeline_release(struct sync_timeline *sync_timeline)
+{
+       module_put(THIS_MODULE);
+}
+
+static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
+{
+       struct mali_sync_pt *mpt;
+
+       MALI_DEBUG_ASSERT_POINTER(s);
+       MALI_DEBUG_ASSERT_POINTER(sync_pt);
+
+       mpt = to_mali_sync_pt(sync_pt);
+       MALI_DEBUG_ASSERT_POINTER(mpt->flag);
+
+       seq_printf(s, "%u", mpt->flag->point);
+}
+
+static struct sync_timeline_ops mali_timeline_ops = {
+       .driver_name    = "Mali",
+       .dup            = timeline_dup,
+       .has_signaled   = timeline_has_signaled,
+       .compare        = timeline_compare,
+       .free_pt        = timeline_free_pt,
+       .release_obj    = timeline_release,
+       .print_pt       = timeline_print_pt,
+};
+
+struct sync_timeline *mali_sync_timeline_create(const char *name)
+{
+       struct sync_timeline *sync_tl;
+
+       sync_tl = sync_timeline_create(&mali_timeline_ops, sizeof(struct sync_timeline), name);
+       if (NULL == sync_tl) return NULL;
+
+       /* Grab a reference on the module to ensure the callbacks are present
+        * as long some timeline exists. The reference is released when the
+        * timeline is freed.
+        * Since this function is called from a ioctl on an open file we know
+        * we already have a reference, so using __module_get is safe. */
+       __module_get(THIS_MODULE);
+
+       return sync_tl;
+}
+
+mali_bool mali_sync_timeline_is_ours(struct sync_timeline *sync_tl)
+{
+       MALI_DEBUG_ASSERT_POINTER(sync_tl);
+       return (sync_tl->ops == &mali_timeline_ops) ? MALI_TRUE : MALI_FALSE;
+}
+
+s32 mali_sync_fence_fd_alloc(struct sync_fence *sync_fence)
+{
+       s32 fd = -1;
+
+       fd = get_unused_fd();
+       if (fd < 0) {
+               sync_fence_put(sync_fence);
+               return -1;
+       }
+       sync_fence_install(sync_fence, fd);
+
+       return fd;
+}
+
+struct sync_fence *mali_sync_fence_merge(struct sync_fence *sync_fence1, struct sync_fence *sync_fence2)
+{
+       struct sync_fence *sync_fence;
+
+       MALI_DEBUG_ASSERT_POINTER(sync_fence1);
+       MALI_DEBUG_ASSERT_POINTER(sync_fence1);
+
+       sync_fence = sync_fence_merge("mali_merge_fence", sync_fence1, sync_fence2);
+       sync_fence_put(sync_fence1);
+       sync_fence_put(sync_fence2);
+
+       return sync_fence;
+}
+
+struct sync_fence *mali_sync_timeline_create_signaled_fence(struct sync_timeline *sync_tl)
+{
+       struct mali_sync_flag *flag;
+       struct sync_fence *sync_fence;
+
+       MALI_DEBUG_ASSERT_POINTER(sync_tl);
+
+       flag = mali_sync_flag_create(sync_tl, 0);
+       if (NULL == flag) return NULL;
+
+       sync_fence = mali_sync_flag_create_fence(flag);
+
+       mali_sync_flag_signal(flag, 0);
+       mali_sync_flag_put(flag);
+
+       return sync_fence;
+}
+
+struct mali_sync_flag *mali_sync_flag_create(struct sync_timeline *sync_tl, mali_timeline_point point)
+{
+       struct mali_sync_flag *flag;
+
+       if (NULL == sync_tl) return NULL;
+
+       flag = _mali_osk_calloc(1, sizeof(*flag));
+       if (NULL == flag) return NULL;
+
+       flag->sync_tl = sync_tl;
+       flag->point = point;
+
+       flag->status = 0;
+       kref_init(&flag->refcount);
+
+       return flag;
+}
+
+void mali_sync_flag_get(struct mali_sync_flag *flag)
+{
+       MALI_DEBUG_ASSERT_POINTER(flag);
+       kref_get(&flag->refcount);
+}
+
+/**
+ * Free sync flag.
+ *
+ * @param ref kref object embedded in sync flag that should be freed.
+ */
+static void mali_sync_flag_free(struct kref *ref)
+{
+       struct mali_sync_flag *flag;
+
+       MALI_DEBUG_ASSERT_POINTER(ref);
+       flag = container_of(ref, struct mali_sync_flag, refcount);
+
+       _mali_osk_free(flag);
+}
+
+void mali_sync_flag_put(struct mali_sync_flag *flag)
+{
+       MALI_DEBUG_ASSERT_POINTER(flag);
+       kref_put(&flag->refcount, mali_sync_flag_free);
+}
+
+void mali_sync_flag_signal(struct mali_sync_flag *flag, int error)
+{
+       MALI_DEBUG_ASSERT_POINTER(flag);
+
+       MALI_DEBUG_ASSERT(0 == flag->status);
+       flag->status = (0 > error) ? error : 1;
+
+       _mali_osk_write_mem_barrier();
+
+       sync_timeline_signal(flag->sync_tl);
+}
+
+/**
+ * Create a sync point attached to given sync flag.
+ *
+ * @note Sync points must be triggered in *exactly* the same order as they are created.
+ *
+ * @param flag Sync flag.
+ * @return New sync point if successful, NULL if not.
+ */
+static struct sync_pt *mali_sync_flag_create_pt(struct mali_sync_flag *flag)
+{
+       struct sync_pt *pt;
+       struct mali_sync_pt *mpt;
+
+       MALI_DEBUG_ASSERT_POINTER(flag);
+       MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
+
+       pt = sync_pt_create(flag->sync_tl, sizeof(struct mali_sync_pt));
+       if (NULL == pt) return NULL;
+
+       mali_sync_flag_get(flag);
+
+       mpt = to_mali_sync_pt(pt);
+       mpt->flag = flag;
+
+       return pt;
+}
+
+struct sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag)
+{
+       struct sync_pt    *sync_pt;
+       struct sync_fence *sync_fence;
+
+       MALI_DEBUG_ASSERT_POINTER(flag);
+       MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
+
+       sync_pt = mali_sync_flag_create_pt(flag);
+       if (NULL == sync_pt) return NULL;
+
+       sync_fence = sync_fence_create("mali_flag_fence", sync_pt);
+       if (NULL == sync_fence) {
+               sync_pt_free(sync_pt);
+               return NULL;
+       }
+
+       return sync_fence;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_sync.h b/drivers/gpu/arm/mali400/mali/linux/mali_sync.h
new file mode 100755 (executable)
index 0000000..bd87bb6
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_sync.h
+ *
+ * Mali interface for Linux sync objects.
+ */
+
+#ifndef _MALI_SYNC_H_
+#define _MALI_SYNC_H_
+
+#if defined(CONFIG_SYNC)
+
+#include <linux/seq_file.h>
+#include "sync.h"
+
+#include "mali_osk.h"
+
+struct mali_sync_flag;
+
+/**
+ * Create a sync timeline.
+ *
+ * @param name Name of the sync timeline.
+ * @return The new sync timeline if successful, NULL if not.
+ */
+struct sync_timeline *mali_sync_timeline_create(const char *name);
+
+/**
+ * Check if sync timeline belongs to Mali.
+ *
+ * @param sync_tl Sync timeline to check.
+ * @return MALI_TRUE if sync timeline belongs to Mali, MALI_FALSE if not.
+ */
+mali_bool mali_sync_timeline_is_ours(struct sync_timeline *sync_tl);
+
+/**
+ * Creates a file descriptor representing the sync fence.  Will release sync fence if allocation of
+ * file descriptor fails.
+ *
+ * @param sync_fence Sync fence.
+ * @return File descriptor representing sync fence if successful, or -1 if not.
+ */
+s32 mali_sync_fence_fd_alloc(struct sync_fence *sync_fence);
+
+/**
+ * Merges two sync fences.  Both input sync fences will be released.
+ *
+ * @param sync_fence1 First sync fence.
+ * @param sync_fence2 Second sync fence.
+ * @return New sync fence that is the result of the merger if successful, or NULL if not.
+ */
+struct sync_fence *mali_sync_fence_merge(struct sync_fence *sync_fence1, struct sync_fence *sync_fence2);
+
+/**
+ * Create a sync fence that is already signaled.
+ *
+ * @param tl Sync timeline.
+ * @return New signaled sync fence if successful, NULL if not.
+ */
+struct sync_fence *mali_sync_timeline_create_signaled_fence(struct sync_timeline *sync_tl);
+
+/**
+ * Create a sync flag.
+ *
+ * @param sync_tl Sync timeline.
+ * @param point Point on Mali timeline.
+ * @return New sync flag if successful, NULL if not.
+ */
+struct mali_sync_flag *mali_sync_flag_create(struct sync_timeline *sync_tl, u32 point);
+
+/**
+ * Grab sync flag reference.
+ *
+ * @param flag Sync flag.
+ */
+void mali_sync_flag_get(struct mali_sync_flag *flag);
+
+/**
+ * Release sync flag reference.  If this was the last reference, the sync flag will be freed.
+ *
+ * @param flag Sync flag.
+ */
+void mali_sync_flag_put(struct mali_sync_flag *flag);
+
+/**
+ * Signal sync flag.  All sync fences created from this flag will be signaled.
+ *
+ * @param flag Sync flag to signal.
+ * @param error Negative error code, or 0 if no error.
+ */
+void mali_sync_flag_signal(struct mali_sync_flag *flag, int error);
+
+/**
+ * Create a sync fence attached to given sync flag.
+ *
+ * @param flag Sync flag.
+ * @return New sync fence if successful, NULL if not.
+ */
+struct sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag);
+
+#endif /* defined(CONFIG_SYNC) */
+
+#endif /* _MALI_SYNC_H_ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_uk_types.h b/drivers/gpu/arm/mali400/mali/linux/mali_uk_types.h
new file mode 100755 (executable)
index 0000000..fac43ae
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_UK_TYPES_H__
+#define __MALI_UK_TYPES_H__
+
+/* Simple wrapper in order to find the OS specific location of this file */
+#include <linux/mali/mali_utgard_uk_types.h>
+
+#endif /* __MALI_UK_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_core.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_core.c
new file mode 100755 (executable)
index 0000000..1cd7293
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <linux/slab.h>     /* memort allocation functions */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs)
+{
+       _mali_uk_get_api_version_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       if (0 != get_user(kargs.version, &uargs->version)) return -EFAULT;
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_get_api_version(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
+       if (0 != put_user(kargs.compatible, &uargs->compatible)) return -EFAULT;
+
+       return 0;
+}
+#define mali400_in_rk30_version 0x01
+int get_mali_version_in_rk30_wrapper(struct mali_session_data *session_data, _mali_uk_get_mali_version_in_rk30_s __user *uargs)
+{
+       _mali_uk_get_mali_version_in_rk30_s kargs;
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       kargs.ctx = session_data;
+       kargs.version = mali400_in_rk30_version;
+       if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
+       return 0;
+}
+int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs)
+{
+       _mali_uk_wait_for_notification_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_wait_for_notification(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       if(_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS != kargs.type) {
+               kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+               if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_wait_for_notification_s))) return -EFAULT;
+       } else {
+               if (0 != put_user(kargs.type, &uargs->type)) return -EFAULT;
+       }
+
+       return 0;
+}
+
+int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs)
+{
+       _mali_uk_post_notification_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       kargs.ctx = session_data;
+
+       if (0 != get_user(kargs.type, &uargs->type)) {
+               return -EFAULT;
+       }
+
+       err = _mali_ukk_post_notification(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       return 0;
+}
+
+int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs)
+{
+       _mali_uk_get_user_settings_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_get_user_settings(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+       if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_user_settings_s))) return -EFAULT;
+
+       return 0;
+}
+
+int request_high_priority_wrapper(struct mali_session_data *session_data, _mali_uk_request_high_priority_s __user *uargs)
+{
+       _mali_uk_request_high_priority_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_request_high_priority(&kargs);
+
+       kargs.ctx = NULL;
+
+       return map_errcode(err);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_gp.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_gp.c
new file mode 100755 (executable)
index 0000000..d3992d1
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs)
+{
+       _mali_osk_errcode_t err;
+
+       /* If the job was started successfully, 0 is returned.  If there was an error, but the job
+        * was started, we return -ENOENT.  For anything else returned, the job was not started. */
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       err = _mali_ukk_gp_start_job(session_data, uargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       return 0;
+}
+
+int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs)
+{
+       _mali_uk_get_gp_core_version_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       kargs.ctx = session_data;
+       err =  _mali_ukk_get_gp_core_version(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       /* no known transactions to roll-back */
+
+       if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
+
+       return 0;
+}
+
+int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs)
+{
+       _mali_uk_gp_suspend_response_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_suspend_response_s))) return -EFAULT;
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_gp_suspend_response(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       if (0 != put_user(kargs.cookie, &uargs->cookie)) return -EFAULT;
+
+       /* no known transactions to roll-back */
+       return 0;
+}
+
+int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs)
+{
+       _mali_uk_get_gp_number_of_cores_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_get_gp_number_of_cores(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       /* no known transactions to roll-back */
+
+       if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) return -EFAULT;
+
+       return 0;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_mem.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_mem.c
new file mode 100755 (executable)
index 0000000..6baf151
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs)
+{
+       _mali_uk_mem_write_safe_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s))) {
+               return -EFAULT;
+       }
+
+       kargs.ctx = session_data;
+
+       /* Check if we can access the buffers */
+       if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
+           || !access_ok(VERIFY_READ, kargs.src, kargs.size)) {
+               return -EINVAL;
+       }
+
+       /* Check if size wraps */
+       if ((kargs.size + kargs.dest) <= kargs.dest
+           || (kargs.size + kargs.src) <= kargs.src) {
+               return -EINVAL;
+       }
+
+       err = _mali_ukk_mem_write_safe(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       if (0 != put_user(kargs.size, &uargs->size)) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument)
+{
+       _mali_uk_map_external_mem_s uk_args;
+       _mali_osk_errcode_t err_code;
+
+       /* validate input */
+       /* the session_data pointer was validated by caller */
+       MALI_CHECK_NON_NULL( argument, -EINVAL);
+
+       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_map_external_mem_s)) ) {
+               return -EFAULT;
+       }
+
+       uk_args.ctx = session_data;
+       err_code = _mali_ukk_map_external_mem( &uk_args );
+
+       if (0 != put_user(uk_args.cookie, &argument->cookie)) {
+               if (_MALI_OSK_ERR_OK == err_code) {
+                       /* Rollback */
+                       _mali_uk_unmap_external_mem_s uk_args_unmap;
+
+                       uk_args_unmap.ctx = session_data;
+                       uk_args_unmap.cookie = uk_args.cookie;
+                       err_code = _mali_ukk_unmap_external_mem( &uk_args_unmap );
+                       if (_MALI_OSK_ERR_OK != err_code) {
+                               MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_unmap_external_mem, as a result of failing put_user(), failed\n"));
+                       }
+               }
+               return -EFAULT;
+       }
+
+       /* Return the error that _mali_ukk_free_big_block produced */
+       return map_errcode(err_code);
+}
+
+int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument)
+{
+       _mali_uk_unmap_external_mem_s uk_args;
+       _mali_osk_errcode_t err_code;
+
+       /* validate input */
+       /* the session_data pointer was validated by caller */
+       MALI_CHECK_NON_NULL( argument, -EINVAL);
+
+       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_unmap_external_mem_s)) ) {
+               return -EFAULT;
+       }
+
+       uk_args.ctx = session_data;
+       err_code = _mali_ukk_unmap_external_mem( &uk_args );
+
+       /* Return the error that _mali_ukk_free_big_block produced */
+       return map_errcode(err_code);
+}
+
+#if defined(CONFIG_MALI400_UMP)
+int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument)
+{
+       _mali_uk_release_ump_mem_s uk_args;
+       _mali_osk_errcode_t err_code;
+
+       /* validate input */
+       /* the session_data pointer was validated by caller */
+       MALI_CHECK_NON_NULL( argument, -EINVAL);
+
+       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_release_ump_mem_s)) ) {
+               return -EFAULT;
+       }
+
+       uk_args.ctx = session_data;
+       err_code = _mali_ukk_release_ump_mem( &uk_args );
+
+       /* Return the error that _mali_ukk_free_big_block produced */
+       return map_errcode(err_code);
+}
+
+int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument)
+{
+       _mali_uk_attach_ump_mem_s uk_args;
+       _mali_osk_errcode_t err_code;
+
+       /* validate input */
+       /* the session_data pointer was validated by caller */
+       MALI_CHECK_NON_NULL( argument, -EINVAL);
+
+       /* get call arguments from user space. copy_from_user returns how many bytes which where NOT copied */
+       if ( 0 != copy_from_user(&uk_args, (void __user *)argument, sizeof(_mali_uk_attach_ump_mem_s)) ) {
+               return -EFAULT;
+       }
+
+       uk_args.ctx = session_data;
+       err_code = _mali_ukk_attach_ump_mem( &uk_args );
+
+       if (0 != put_user(uk_args.cookie, &argument->cookie)) {
+               if (_MALI_OSK_ERR_OK == err_code) {
+                       /* Rollback */
+                       _mali_uk_release_ump_mem_s uk_args_unmap;
+
+                       uk_args_unmap.ctx = session_data;
+                       uk_args_unmap.cookie = uk_args.cookie;
+                       err_code = _mali_ukk_release_ump_mem( &uk_args_unmap );
+                       if (_MALI_OSK_ERR_OK != err_code) {
+                               MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_attach_mem, as a result of failing put_user(), failed\n"));
+                       }
+               }
+               return -EFAULT;
+       }
+
+       /* Return the error that _mali_ukk_map_external_ump_mem produced */
+       return map_errcode(err_code);
+}
+#endif /* CONFIG_MALI400_UMP */
+
+int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs)
+{
+       _mali_uk_query_mmu_page_table_dump_size_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       kargs.ctx = session_data;
+
+       err = _mali_ukk_query_mmu_page_table_dump_size(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       if (0 != put_user(kargs.size, &uargs->size)) return -EFAULT;
+
+       return 0;
+}
+
+int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs)
+{
+       _mali_uk_dump_mmu_page_table_s kargs;
+       _mali_osk_errcode_t err;
+       void *buffer;
+       int rc = -EFAULT;
+
+       /* validate input */
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       /* the session_data pointer was validated by caller */
+
+       kargs.buffer = NULL;
+
+       /* get location of user buffer */
+       if (0 != get_user(buffer, &uargs->buffer)) goto err_exit;
+       /* get size of mmu page table info buffer from user space */
+       if ( 0 != get_user(kargs.size, &uargs->size) ) goto err_exit;
+       /* verify we can access the whole of the user buffer */
+       if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit;
+
+       /* allocate temporary buffer (kernel side) to store mmu page table info */
+       MALI_CHECK(kargs.size > 0, -ENOMEM);
+       kargs.buffer = _mali_osk_valloc(kargs.size);
+       if (NULL == kargs.buffer) {
+               rc = -ENOMEM;
+               goto err_exit;
+       }
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_dump_mmu_page_table(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               rc = map_errcode(err);
+               goto err_exit;
+       }
+
+       /* copy mmu page table info back to user space and update pointers */
+       if (0 != copy_to_user(uargs->buffer, kargs.buffer, kargs.size) ) goto err_exit;
+       if (0 != put_user((kargs.register_writes - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->register_writes)) goto err_exit;
+       if (0 != put_user((kargs.page_table_dump - (u32 *)kargs.buffer) + (u32 *)uargs->buffer, &uargs->page_table_dump)) goto err_exit;
+       if (0 != put_user(kargs.register_writes_size, &uargs->register_writes_size)) goto err_exit;
+       if (0 != put_user(kargs.page_table_dump_size, &uargs->page_table_dump_size)) goto err_exit;
+       rc = 0;
+
+err_exit:
+       if (kargs.buffer) _mali_osk_vfree(kargs.buffer);
+       return rc;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_pp.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_pp.c
new file mode 100755 (executable)
index 0000000..1519230
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs)
+{
+       _mali_osk_errcode_t err;
+
+       /* If the job was started successfully, 0 is returned.  If there was an error, but the job
+        * was started, we return -ENOENT.  For anything else returned, the job was not started. */
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       err = _mali_ukk_pp_start_job(session_data, uargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       return 0;
+}
+
+int pp_and_gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_and_gp_start_job_s __user *uargs)
+{
+       _mali_osk_errcode_t err;
+
+       /* If the jobs were started successfully, 0 is returned.  If there was an error, but the
+        * jobs were started, we return -ENOENT.  For anything else returned, the jobs were not
+        * started. */
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       err = _mali_ukk_pp_and_gp_start_job(session_data, uargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       return 0;
+}
+
+int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs)
+{
+       _mali_uk_get_pp_number_of_cores_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       kargs.ctx = session_data;
+
+       err = _mali_ukk_get_pp_number_of_cores(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+       if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_pp_number_of_cores_s))) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs)
+{
+       _mali_uk_get_pp_core_version_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_get_pp_core_version(&kargs);
+       if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+       if (0 != put_user(kargs.version, &uargs->version)) return -EFAULT;
+
+       return 0;
+}
+
+int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs)
+{
+       _mali_uk_pp_disable_wb_s kargs;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_disable_wb_s))) return -EFAULT;
+
+       kargs.ctx = session_data;
+       _mali_ukk_pp_job_disable_wb(&kargs);
+
+       return 0;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_profiling.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_profiling.c
new file mode 100755 (executable)
index 0000000..d77ca25
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+#include <linux/slab.h>
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs)
+{
+       _mali_uk_profiling_start_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_start_s))) {
+               return -EFAULT;
+       }
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_profiling_start(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       if (0 != put_user(kargs.limit, &uargs->limit)) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs)
+{
+       _mali_uk_profiling_add_event_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_profiling_add_event_s))) {
+               return -EFAULT;
+       }
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_profiling_add_event(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       return 0;
+}
+
+int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs)
+{
+       _mali_uk_profiling_stop_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_profiling_stop(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       if (0 != put_user(kargs.count, &uargs->count)) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs)
+{
+       _mali_uk_profiling_get_event_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       if (0 != get_user(kargs.index, &uargs->index)) {
+               return -EFAULT;
+       }
+
+       kargs.ctx = session_data;
+
+       err = _mali_ukk_profiling_get_event(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+       if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_profiling_get_event_s))) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs)
+{
+       _mali_uk_profiling_clear_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_profiling_clear(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       return 0;
+}
+
+int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs)
+{
+       _mali_uk_sw_counters_report_s kargs;
+       _mali_osk_errcode_t err;
+       u32 *counter_buffer;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_sw_counters_report_s))) {
+               return -EFAULT;
+       }
+
+       /* make sure that kargs.num_counters is [at least somewhat] sane */
+       if (kargs.num_counters > 10000) {
+               MALI_DEBUG_PRINT(1, ("User space attempted to allocate too many counters.\n"));
+               return -EINVAL;
+       }
+
+       counter_buffer = (u32*)kmalloc(sizeof(u32) * kargs.num_counters, GFP_KERNEL);
+       if (NULL == counter_buffer) {
+               return -ENOMEM;
+       }
+
+       if (0 != copy_from_user(counter_buffer, kargs.counters, sizeof(u32) * kargs.num_counters)) {
+               kfree(counter_buffer);
+               return -EFAULT;
+       }
+
+       kargs.ctx = session_data;
+       kargs.counters = counter_buffer;
+
+       err = _mali_ukk_sw_counters_report(&kargs);
+
+       kfree(counter_buffer);
+
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       return 0;
+}
+
+
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_soft_job.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_soft_job.c
new file mode 100755 (executable)
index 0000000..4dd005d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+#include "mali_soft_job.h"
+#include "mali_timeline.h"
+
+int soft_job_start_wrapper(struct mali_session_data *session, _mali_uk_soft_job_start_s __user *uargs)
+{
+       u32 type, user_job, point;
+       _mali_uk_fence_t uk_fence;
+       struct mali_timeline_fence fence;
+       struct mali_soft_job *job = NULL;
+       u32 __user *job_id_ptr = NULL;
+
+       /* If the job was started successfully, 0 is returned.  If there was an error, but the job
+        * was started, we return -ENOENT.  For anything else returned, the job was not started. */
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+       MALI_CHECK_NON_NULL(session, -EINVAL);
+
+       MALI_DEBUG_ASSERT_POINTER(session->soft_job_system);
+
+       if (0 != get_user(type, &uargs->type))                 return -EFAULT;
+       if (0 != get_user(user_job, &uargs->user_job))         return -EFAULT;
+       if (0 != get_user(job_id_ptr, &uargs->job_id_ptr))     return -EFAULT;
+
+       if (0 != copy_from_user(&uk_fence, &uargs->fence, sizeof(_mali_uk_fence_t))) return -EFAULT;
+       mali_timeline_fence_copy_uk_fence(&fence, &uk_fence);
+
+       if (MALI_SOFT_JOB_TYPE_USER_SIGNALED < type) {
+               MALI_DEBUG_PRINT_ERROR(("Invalid soft job type specified\n"));
+               return -EINVAL;
+       }
+
+       /* Create soft job. */
+       job = mali_soft_job_create(session->soft_job_system, (enum mali_soft_job_type)type, user_job);
+       if (unlikely(NULL == job)) {
+               return map_errcode(_MALI_OSK_ERR_NOMEM);
+       }
+
+       /* Write job id back to user space. */
+       if (0 != put_user(job->id, job_id_ptr)) {
+               MALI_PRINT_ERROR(("Mali Soft Job: failed to put job id"));
+               mali_soft_job_destroy(job);
+               return map_errcode(_MALI_OSK_ERR_NOMEM);
+       }
+
+       /* Start soft job. */
+       point = mali_soft_job_start(job, &fence);
+
+       if (0 != put_user(point, &uargs->point)) {
+               /* Let user space know that something failed after the job was started. */
+               return -ENOENT;
+       }
+
+       return 0;
+}
+
+int soft_job_signal_wrapper(struct mali_session_data *session, _mali_uk_soft_job_signal_s __user *uargs)
+{
+       u32 job_id;
+       _mali_osk_errcode_t err;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       if (0 != get_user(job_id, &uargs->job_id)) return -EFAULT;
+
+       err = mali_soft_job_system_signal_job(session->soft_job_system, job_id);
+
+       return map_errcode(err);
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_timeline.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_timeline.c
new file mode 100755 (executable)
index 0000000..e227002
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+#include "mali_timeline.h"
+#include "mali_timeline_fence_wait.h"
+#include "mali_timeline_sync_fence.h"
+
+int timeline_get_latest_point_wrapper(struct mali_session_data *session, _mali_uk_timeline_get_latest_point_s __user *uargs)
+{
+       u32 val;
+       mali_timeline_id timeline;
+       mali_timeline_point point;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       if (0 != get_user(val, &uargs->timeline)) return -EFAULT;
+
+       if (MALI_UK_TIMELINE_MAX <= val) {
+               return -EINVAL;
+       }
+
+       timeline = (mali_timeline_id)val;
+
+       point = mali_timeline_system_get_latest_point(session->timeline_system, timeline);
+
+       if (0 != put_user(point, &uargs->point)) return -EFAULT;
+
+       return 0;
+}
+
+int timeline_wait_wrapper(struct mali_session_data *session, _mali_uk_timeline_wait_s __user *uargs)
+{
+       u32 timeout, status;
+       mali_bool ret;
+       _mali_uk_fence_t uk_fence;
+       struct mali_timeline_fence fence;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       if (0 != copy_from_user(&uk_fence, &uargs->fence, sizeof(_mali_uk_fence_t))) return -EFAULT;
+       if (0 != get_user(timeout, &uargs->timeout)) return -EFAULT;
+
+       mali_timeline_fence_copy_uk_fence(&fence, &uk_fence);
+
+       ret = mali_timeline_fence_wait(session->timeline_system, &fence, timeout);
+       status = (MALI_TRUE == ret ? 1 : 0);
+
+       if (0 != put_user(status, &uargs->status)) return -EFAULT;
+
+       return 0;
+}
+
+int timeline_create_sync_fence_wrapper(struct mali_session_data *session, _mali_uk_timeline_create_sync_fence_s __user *uargs)
+{
+       s32 sync_fd = -1;
+       _mali_uk_fence_t uk_fence;
+       struct mali_timeline_fence fence;
+
+       MALI_DEBUG_ASSERT_POINTER(session);
+
+       if (0 != copy_from_user(&uk_fence, &uargs->fence, sizeof(_mali_uk_fence_t))) return -EFAULT;
+       mali_timeline_fence_copy_uk_fence(&fence, &uk_fence);
+
+#if defined(CONFIG_SYNC)
+       sync_fd = mali_timeline_sync_fence_create(session->timeline_system, &fence);
+#else
+       sync_fd = -1;
+#endif /* defined(CONFIG_SYNC) */
+
+       if (0 != put_user(sync_fd, &uargs->sync_fd)) return -EFAULT;
+
+       return 0;
+}
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_vsync.c b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_vsync.c
new file mode 100755 (executable)
index 0000000..18fdef6
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2011-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+#include <linux/fs.h>       /* file system operations */
+#include <asm/uaccess.h>    /* user space access */
+
+#include "mali_ukk.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_session.h"
+#include "mali_ukk_wrappers.h"
+
+
+int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs)
+{
+       _mali_uk_vsync_event_report_s kargs;
+       _mali_osk_errcode_t err;
+
+       MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+       if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_vsync_event_report_s))) {
+               return -EFAULT;
+       }
+
+       kargs.ctx = session_data;
+       err = _mali_ukk_vsync_event_report(&kargs);
+       if (_MALI_OSK_ERR_OK != err) {
+               return map_errcode(err);
+       }
+
+       return 0;
+}
+
diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_ukk_wrappers.h b/drivers/gpu/arm/mali400/mali/linux/mali_ukk_wrappers.h
new file mode 100755 (executable)
index 0000000..3739898
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_ukk_wrappers.h
+ * Defines the wrapper functions for each user-kernel function
+ */
+
+#ifndef __MALI_UKK_WRAPPERS_H__
+#define __MALI_UKK_WRAPPERS_H__
+
+#include "mali_uk_types.h"
+#include "mali_osk.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_uk_wait_for_notification_s __user *uargs);
+int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs);
+int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs);
+int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs);
+int request_high_priority_wrapper(struct mali_session_data *session_data, _mali_uk_request_high_priority_s __user *uargs);
+
+int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs);
+int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument);
+int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument);
+int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs);
+int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user * uargs);
+int get_mali_version_in_rk30_wrapper(struct mali_session_data *session_data, _mali_uk_get_mali_version_in_rk30_s __user *uargs)
+;
+int timeline_get_latest_point_wrapper(struct mali_session_data *session, _mali_uk_timeline_get_latest_point_s __user *uargs);
+int timeline_wait_wrapper(struct mali_session_data *session, _mali_uk_timeline_wait_s __user *uargs);
+int timeline_create_sync_fence_wrapper(struct mali_session_data *session, _mali_uk_timeline_create_sync_fence_s __user *uargs);
+int soft_job_start_wrapper(struct mali_session_data *session, _mali_uk_soft_job_start_s __user *uargs);
+int soft_job_signal_wrapper(struct mali_session_data *session, _mali_uk_soft_job_signal_s __user *uargs);
+
+#if defined(CONFIG_MALI400_UMP)
+int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_attach_ump_mem_s __user * argument);
+int mem_release_ump_wrapper(struct mali_session_data *session_data, _mali_uk_release_ump_mem_s __user * argument);
+#endif
+
+int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs);
+int pp_and_gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_and_gp_start_job_s __user *uargs);
+int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs);
+int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_core_version_s __user *uargs);
+int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs);
+int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs);
+int gp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_number_of_cores_s __user *uargs);
+int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs);
+int gp_suspend_response_wrapper(struct mali_session_data *session_data, _mali_uk_gp_suspend_response_s __user *uargs);
+
+int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs);
+int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_add_event_s __user *uargs);
+int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_stop_s __user *uargs);
+int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs);
+int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs);
+int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs);
+
+int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs);
+
+
+int map_errcode( _mali_osk_errcode_t err );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UKK_WRAPPERS_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/platform/arm/arm.c b/drivers/gpu/arm/mali400/mali/platform/arm/arm.c
new file mode 100755 (executable)
index 0000000..314363a
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_platform.c
+ * Platform specific Mali driver functions for:
+ * - Realview Versatile platforms with ARM11 Mpcore and virtex 5.
+ * - Versatile Express platforms with ARM Cortex-A9 and virtex 6.
+ */
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+#include <asm/io.h>
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+#include <linux/dma-mapping.h>
+#include <linux/moduleparam.h>
+
+#include "arm_core_scaling.h"
+#include "mali_pp_scheduler.h"
+
+static void mali_platform_device_release(struct device *device);
+static u32 mali_read_phys(u32 phys_addr);
+#if defined(CONFIG_ARCH_REALVIEW)
+static void mali_write_phys(u32 phys_addr, u32 value);
+#endif
+
+static int mali_core_scaling_enable = 1;
+
+void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
+
+#if defined(CONFIG_ARCH_VEXPRESS)
+
+static struct resource mali_gpu_resources_m450_mp8[] = {
+       MALI_GPU_RESOURCES_MALI450_MP8_PMU(0xFC040000, -1, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 68)
+};
+
+#elif defined(CONFIG_ARCH_REALVIEW)
+
+static struct resource mali_gpu_resources_m300[] = {
+       MALI_GPU_RESOURCES_MALI300_PMU(0xC0000000, -1, -1, -1, -1)
+};
+
+static struct resource mali_gpu_resources_m400_mp1[] = {
+       MALI_GPU_RESOURCES_MALI400_MP1_PMU(0xC0000000, -1, -1, -1, -1)
+};
+
+static struct resource mali_gpu_resources_m400_mp2[] = {
+       MALI_GPU_RESOURCES_MALI400_MP2_PMU(0xC0000000, -1, -1, -1, -1, -1, -1)
+};
+
+#endif
+
+static struct mali_gpu_device_data mali_gpu_data = {
+#if defined(CONFIG_ARCH_VEXPRESS)
+       .shared_mem_size =256 * 1024 * 1024, /* 256MB */
+#elif defined(CONFIG_ARCH_REALVIEW)
+       .dedicated_mem_start = 0x80000000, /* Physical start address (use 0xD0000000 for old indirect setup) */
+       .dedicated_mem_size = 0x10000000, /* 256MB */
+#endif
+       .fb_start = 0xe0000000,
+       .fb_size = 0x01000000,
+       .max_job_runtime = 60000, /* 60 seconds */
+       .utilization_interval = 1000, /* 1000ms */
+       .utilization_callback = mali_gpu_utilization_callback,
+       .pmu_switch_delay = 0xFF, /* do not have to be this high on FPGA, but it is good for testing to have a delay */
+       .pmu_domain_config = {0x1, 0x2, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x1, 0x2, 0x8},
+};
+
+static struct platform_device mali_gpu_device = {
+       .name = MALI_GPU_NAME_UTGARD,
+       .id = 0,
+       .dev.release = mali_platform_device_release,
+       .dev.coherent_dma_mask = DMA_BIT_MASK(32),
+
+       .dev.platform_data = &mali_gpu_data,
+};
+
+int mali_platform_device_register(void)
+{
+       int err = -1;
+       int num_pp_cores = 0;
+#if defined(CONFIG_ARCH_REALVIEW)
+       u32 m400_gp_version;
+#endif
+
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n"));
+
+       /* Detect present Mali GPU and connect the correct resources to the device */
+#if defined(CONFIG_ARCH_VEXPRESS)
+
+       if (mali_read_phys(0xFC020000) == 0x00010100) {
+               MALI_DEBUG_PRINT(4, ("Registering Mali-450 MP8 device\n"));
+               num_pp_cores = 8;
+               mali_gpu_device.num_resources = ARRAY_SIZE(mali_gpu_resources_m450_mp8);
+               mali_gpu_device.resource = mali_gpu_resources_m450_mp8;
+       }
+
+#elif defined(CONFIG_ARCH_REALVIEW)
+
+       m400_gp_version = mali_read_phys(0xC000006C);
+       if ((m400_gp_version & 0xFFFF0000) == 0x0C070000) {
+               MALI_DEBUG_PRINT(4, ("Registering Mali-300 device\n"));
+               num_pp_cores = 1;
+               mali_gpu_device.num_resources = ARRAY_SIZE(mali_gpu_resources_m300);
+               mali_gpu_device.resource = mali_gpu_resources_m300;
+               mali_write_phys(0xC0010020, 0xA); /* Enable direct memory mapping for FPGA */
+       } else if ((m400_gp_version & 0xFFFF0000) == 0x0B070000) {
+               u32 fpga_fw_version = mali_read_phys(0xC0010000);
+               if (fpga_fw_version == 0x130C008F || fpga_fw_version == 0x110C008F) {
+                       /* Mali-400 MP1 r1p0 or r1p1 */
+                       MALI_DEBUG_PRINT(4, ("Registering Mali-400 MP1 device\n"));
+                       num_pp_cores = 1;
+                       mali_gpu_device.num_resources = ARRAY_SIZE(mali_gpu_resources_m400_mp1);
+                       mali_gpu_device.resource = mali_gpu_resources_m400_mp1;
+                       mali_write_phys(0xC0010020, 0xA); /* Enable direct memory mapping for FPGA */
+               } else if (fpga_fw_version == 0x130C000F) {
+                       /* Mali-400 MP2 r1p1 */
+                       MALI_DEBUG_PRINT(4, ("Registering Mali-400 MP2 device\n"));
+                       num_pp_cores = 2;
+                       mali_gpu_device.num_resources = ARRAY_SIZE(mali_gpu_resources_m400_mp2);
+                       mali_gpu_device.resource = mali_gpu_resources_m400_mp2;
+                       mali_write_phys(0xC0010020, 0xA); /* Enable direct memory mapping for FPGA */
+               }
+       }
+
+#endif
+       /* Register the platform device */
+       err = platform_device_register(&mali_gpu_device);
+       if (0 == err) {
+#ifdef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+               pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000);
+               pm_runtime_use_autosuspend(&(mali_gpu_device.dev));
+#endif
+               pm_runtime_enable(&(mali_gpu_device.dev));
+#endif
+               MALI_DEBUG_ASSERT(0 < num_pp_cores);
+               mali_core_scaling_init(num_pp_cores);
+
+               return 0;
+       }
+
+       return err;
+}
+
+void mali_platform_device_unregister(void)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
+
+       mali_core_scaling_term();
+       platform_device_unregister(&mali_gpu_device);
+
+       platform_device_put(&mali_gpu_device);
+
+#if defined(CONFIG_ARCH_REALVIEW)
+       mali_write_phys(0xC0010020, 0x9); /* Restore default (legacy) memory mapping */
+#endif
+}
+
+static void mali_platform_device_release(struct device *device)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
+}
+
+static u32 mali_read_phys(u32 phys_addr)
+{
+       u32 phys_addr_page = phys_addr & 0xFFFFE000;
+       u32 phys_offset    = phys_addr & 0x00001FFF;
+       u32 map_size       = phys_offset + sizeof(u32);
+       u32 ret = 0xDEADBEEF;
+       void *mem_mapped = ioremap_nocache(phys_addr_page, map_size);
+       if (NULL != mem_mapped) {
+               ret = (u32)ioread32(((u8*)mem_mapped) + phys_offset);
+               iounmap(mem_mapped);
+       }
+
+       return ret;
+}
+
+#if defined(CONFIG_ARCH_REALVIEW)
+static void mali_write_phys(u32 phys_addr, u32 value)
+{
+       u32 phys_addr_page = phys_addr & 0xFFFFE000;
+       u32 phys_offset    = phys_addr & 0x00001FFF;
+       u32 map_size       = phys_offset + sizeof(u32);
+       void *mem_mapped = ioremap_nocache(phys_addr_page, map_size);
+       if (NULL != mem_mapped) {
+               iowrite32(value, ((u8*)mem_mapped) + phys_offset);
+               iounmap(mem_mapped);
+       }
+}
+#endif
+
+static int param_set_core_scaling(const char *val, const struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+
+       if (1 == mali_core_scaling_enable) {
+               mali_core_scaling_sync(mali_pp_scheduler_get_num_cores_enabled());
+       }
+       return ret;
+}
+
+static struct kernel_param_ops param_ops_core_scaling = {
+       .set = param_set_core_scaling,
+       .get = param_get_int,
+};
+
+module_param_cb(mali_core_scaling_enable, &param_ops_core_scaling, &mali_core_scaling_enable, 0644);
+MODULE_PARM_DESC(mali_core_scaling_enable, "1 means to enable core scaling policy, 0 means to disable core scaling policy");
+
+void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
+{
+       if (1 == mali_core_scaling_enable) {
+               mali_core_scaling_update(data);
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.c b/drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.c
new file mode 100755 (executable)
index 0000000..e9fcf80
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file arm_core_scaling.c
+ * Example core scaling policy.
+ */
+
+#include "arm_core_scaling.h"
+
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+
+#include <linux/workqueue.h>
+
+static int num_cores_total;
+static int num_cores_enabled;
+
+static struct work_struct wq_work;
+
+static void set_num_cores(struct work_struct *work)
+{
+       int err = mali_perf_set_num_pp_cores(num_cores_enabled);
+       MALI_DEBUG_ASSERT(0 == err);
+       MALI_IGNORE(err);
+}
+
+static void enable_one_core(void)
+{
+       if (num_cores_enabled < num_cores_total) {
+               ++num_cores_enabled;
+               schedule_work(&wq_work);
+               MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
+       }
+
+       MALI_DEBUG_ASSERT(              1 <= num_cores_enabled);
+       MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
+}
+
+static void disable_one_core(void)
+{
+       if (1 < num_cores_enabled) {
+               --num_cores_enabled;
+               schedule_work(&wq_work);
+               MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
+       }
+
+       MALI_DEBUG_ASSERT(              1 <= num_cores_enabled);
+       MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
+}
+
+static void enable_max_num_cores(void)
+{
+       if (num_cores_enabled < num_cores_total) {
+               num_cores_enabled = num_cores_total;
+               schedule_work(&wq_work);
+               MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
+       }
+
+       MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
+}
+
+void mali_core_scaling_init(int num_pp_cores)
+{
+       INIT_WORK(&wq_work, set_num_cores);
+
+       num_cores_total   = num_pp_cores;
+       num_cores_enabled = num_pp_cores;
+
+       /* NOTE: Mali is not fully initialized at this point. */
+}
+
+void mali_core_scaling_sync(int num_cores)
+{
+       num_cores_enabled = num_cores;
+}
+
+void mali_core_scaling_term(void)
+{
+       flush_scheduled_work();
+}
+
+#define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
+
+void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
+{
+       /*
+        * This function implements a very trivial PP core scaling algorithm.
+        *
+        * It is _NOT_ of production quality.
+        * The only intention behind this algorithm is to exercise and test the
+        * core scaling functionality of the driver.
+        * It is _NOT_ tuned for neither power saving nor performance!
+        *
+        * Other metrics than PP utilization need to be considered as well
+        * in order to make a good core scaling algorithm.
+        */
+
+       MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, data->utilization_pp, num_cores_enabled, num_cores_total));
+
+       /* NOTE: this function is normally called directly from the utilization callback which is in
+        * timer context. */
+
+       if (     PERCENT_OF(90, 256) < data->utilization_pp) {
+               enable_max_num_cores();
+       } else if (PERCENT_OF(50, 256) < data->utilization_pp) {
+               enable_one_core();
+       } else if (PERCENT_OF(40, 256) < data->utilization_pp) {
+               /* do nothing */
+       } else if (PERCENT_OF( 0, 256) < data->utilization_pp) {
+               disable_one_core();
+       } else {
+               /* do nothing */
+       }
+}
diff --git a/drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.h b/drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.h
new file mode 100755 (executable)
index 0000000..bab8598
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file arm_core_scaling.h
+ * Example core scaling policy.
+ */
+
+#ifndef __ARM_CORE_SCALING_H__
+#define __ARM_CORE_SCALING_H__
+
+struct mali_gpu_utilization_data;
+
+/**
+ * Initialize core scaling policy.
+ *
+ * @note The core scaling policy will assume that all PP cores are on initially.
+ *
+ * @param num_pp_cores Total number of PP cores.
+ */
+void mali_core_scaling_init(int num_pp_cores);
+
+/**
+ * Terminate core scaling policy.
+ */
+void mali_core_scaling_term(void);
+
+/**
+ * Update core scaling policy with new utilization data.
+ *
+ * @param data Utilization data.
+ */
+void mali_core_scaling_update(struct mali_gpu_utilization_data *data);
+
+void mali_core_scaling_sync(int num_cores);
+
+#endif /* __ARM_CORE_SCALING_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/platform/rk30/mali_platform.c b/drivers/gpu/arm/mali400/mali/platform/rk30/mali_platform.c
new file mode 100755 (executable)
index 0000000..1a6fd09
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_platform.c
+ * Platform specific Mali driver functions for a default platform
+ */
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_platform.h"
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/gfp.h>
+#include <linux/fs.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/dvfs.h>
+
+#define GPUCLK_NAME    "clk_gpu"
+#define GPUCLK_PD_NAME "pd_gpu"
+#define GPU_MHZ        1000000
+
+static struct dvfs_node *mali_clock = 0;
+static struct clk *mali_clock_pd = 0;
+static struct clk *audis_gpu_clk = 0;
+
+#define MALI_DVFS_DEFAULT_STEP 0 // 50Mhz default
+
+u32 mali_dvfs[] = {50, 100, 133, 160, 200, 266, 400};
+int num_clock;
+
+u32 mali_init_clock = 50;
+static int minuend = 0;
+
+static struct cpufreq_frequency_table *freq_table = NULL;
+
+module_param_array(mali_dvfs, int, &num_clock,S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mali_dvfs,"mali clock table");
+
+module_param(mali_init_clock, int,S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mali_init_clock,"mali init clock value");
+
+u32 mali_group_error = 0;
+u32 scale_enable = 1;
+u32 gpu_power_state = 0;
+static u32 utilization_global = 0;
+
+u32 mali_utilization_timeout = 10;
+u32 sampling_enable = 1;
+
+#define mali_freq_workqueue_name        "mali_freq_workqueue"
+#define mali_freq_work_name             "mali_freq_work"
+
+struct mali_freq_data {
+       struct workqueue_struct *wq;
+       struct work_struct work;
+       u32 freq;
+} *mali_freq_data;
+
+typedef struct mali_dvfs_tableTag {
+       u32 clock;
+       u32 vol;
+} mali_dvfs_table;
+
+typedef struct mali_dvfs_statusTag {
+    int currentStep;
+    mali_dvfs_table * pCurrentDvfs;
+
+} mali_dvfs_status;
+
+mali_dvfs_status maliDvfsStatus;
+
+#define GPU_DVFS_UP_THRESHOLD  ((int)((255*50)/100))   
+#define GPU_DVFS_DOWN_THRESHOLD ((int)((255*35)/100))  
+
+_mali_osk_mutex_t *clockSetlock;
+
+struct clk* mali_clk_get(unsigned char *name)
+{
+       struct clk *clk;
+       clk = clk_get(NULL,name);
+       return clk;
+}
+unsigned long mali_clk_get_rate(struct dvfs_node *clk)
+{
+       return dvfs_clk_get_rate(clk);
+}
+
+void mali_clk_set_rate(struct dvfs_node *clk, u32 value)
+{
+       unsigned long rate = (unsigned long)value * GPU_MHZ;
+       dvfs_clk_set_rate(clk, rate);
+       rate = mali_clk_get_rate(clk);
+}
+
+static struct kobject *mali400_utility_object;
+
+static u32 get_mali_dvfs_status(void)
+{
+       return maliDvfsStatus.currentStep;
+}
+static void set_mali_dvfs_step(u32 value)
+{
+       maliDvfsStatus.currentStep = value;
+}
+
+static void scale_enable_set(u32 value)
+{
+       scale_enable = value;
+}
+static u32 mali_dvfs_search(u32 value)
+{
+       u32 i;  
+       u32 clock = value;
+       for (i=0;i<num_clock;i++) {
+               if (clock == mali_dvfs[i]) {
+                       _mali_osk_mutex_wait(clockSetlock);
+                       mali_clk_set_rate(mali_clock,clock);
+                       _mali_osk_mutex_signal(clockSetlock);
+                       set_mali_dvfs_step(i);
+                       scale_enable_set(0);
+                       return 0;
+               }
+               if (i>=7)
+                       MALI_DEBUG_PRINT(2,("USER set clock not in the mali_dvfs table\r\n"));
+       }
+       return 1;
+}
+
+static int mali400_utility_show(struct device *dev,struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", utilization_global);
+}
+static int mali400_clock_set(struct device *dev,struct device_attribute *attr, const char *buf,u32 count)
+{
+       u32 clock;
+       u32 currentStep;
+       u64 timeValue;
+       clock = simple_strtoul(buf, NULL, 10);
+       currentStep = get_mali_dvfs_status();
+       timeValue = _mali_osk_time_get_ns();
+       /*MALI_PRINT(("USER SET CLOCK,%d\r\n",clock));*/
+       if(!clock) {
+               scale_enable_set(1);
+       } else {
+               mali_dvfs_search(clock);
+       }
+       return count;
+}
+static int clock_show(struct device *dev,struct device_attribute *attr, char *buf)
+{
+       u32 i;
+       char *pos = buf;
+       pos += snprintf(pos,PAGE_SIZE,"%d,",num_clock);
+       for(i=0;i<(num_clock-1);i++) {
+               pos += snprintf(pos,PAGE_SIZE,"%d,",mali_dvfs[i]);
+       }
+       pos +=snprintf(pos,PAGE_SIZE,"%d\n",mali_dvfs[i]); 
+       return pos - buf;
+}
+static int sampling_timeout_show(struct device *dev,struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "mali_utilization_timeout = %d\n", mali_utilization_timeout);
+}
+static int sampling_timeout_set(struct device *dev,struct device_attribute *attr,
+                               const char *buf,u32 count)
+{
+       u32 sampling;
+       sampling = simple_strtoul(buf, NULL, 10);
+       
+       if (sampling == 0 ) {
+               sampling_enable = 0;
+               MALI_PRINT(("disable mali clock frequency scalling\r\n"));
+       } else {
+               mali_utilization_timeout = sampling;
+               sampling_enable = 1;
+               MALI_PRINT(("enable mali clock frequency scalling ,mali_utilization_timeout : %dms\r\n",
+                           mali_utilization_timeout));
+       }
+       return count;
+}
+static int error_count_show(struct device *dev,struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", mali_group_error);
+}
+
+static DEVICE_ATTR(utility, 0644, mali400_utility_show, mali400_clock_set);
+static DEVICE_ATTR(param, 0644, clock_show, NULL);
+static DEVICE_ATTR(sampling_timeout, 0644, sampling_timeout_show, sampling_timeout_set);
+static DEVICE_ATTR(error_count, 0644, error_count_show, NULL);
+
+
+static mali_bool mali400_utility_sysfs_init(void)
+{
+       u32 ret ;
+
+       mali400_utility_object = kobject_create_and_add("mali400_utility", NULL);
+       if (mali400_utility_object == NULL) {
+               return -1;
+       }
+       ret = sysfs_create_file(mali400_utility_object, &dev_attr_utility.attr);
+       if (ret) {
+               return -1;
+       }
+       ret = sysfs_create_file(mali400_utility_object, &dev_attr_param.attr);
+       if (ret) {
+               return -1;
+       }
+       ret = sysfs_create_file(mali400_utility_object, &dev_attr_sampling_timeout.attr);
+       if(ret){
+               return -1;      
+       }
+       ret = sysfs_create_file(mali400_utility_object, &dev_attr_error_count.attr);
+       if(ret){
+               return -1;
+       }
+       return 0 ;
+}      
+static unsigned int decideNextStatus(unsigned int utilization)
+{
+    u32 level=0;
+
+    if(utilization > GPU_DVFS_UP_THRESHOLD &&
+            maliDvfsStatus.currentStep == 0 &&
+            maliDvfsStatus.currentStep < (num_clock-minuend))
+           level = 1;
+    else if (utilization > GPU_DVFS_UP_THRESHOLD &&
+            maliDvfsStatus.currentStep == 1 &&
+            maliDvfsStatus.currentStep < (num_clock-minuend))
+           level = 2;
+    else if (utilization > GPU_DVFS_UP_THRESHOLD &&
+            maliDvfsStatus.currentStep == 2 &&
+            maliDvfsStatus.currentStep < (num_clock-minuend))
+           level = 3;
+    else if (utilization > GPU_DVFS_UP_THRESHOLD &&
+            maliDvfsStatus.currentStep == 3 &&
+            maliDvfsStatus.currentStep < (num_clock-minuend))
+           level = 4;
+    else if (utilization > GPU_DVFS_UP_THRESHOLD &&
+            maliDvfsStatus.currentStep == 4 &&
+            maliDvfsStatus.currentStep < (num_clock-minuend))
+           level = 5;
+    else if (utilization > GPU_DVFS_UP_THRESHOLD &&
+            maliDvfsStatus.currentStep == 5 &&
+            maliDvfsStatus.currentStep < (num_clock-minuend))
+           level = 6;
+       /*
+       determined by minuend to up to level 6
+       */
+    else if(utilization < GPU_DVFS_DOWN_THRESHOLD &&
+           maliDvfsStatus.currentStep == 6)
+           level = 5;
+    else if(utilization < GPU_DVFS_DOWN_THRESHOLD &&
+           maliDvfsStatus.currentStep == 5)
+           level = 4;
+    else if(utilization < GPU_DVFS_DOWN_THRESHOLD &&
+           maliDvfsStatus.currentStep == 4)
+           level = 3;
+    else if(utilization < GPU_DVFS_DOWN_THRESHOLD &&
+           maliDvfsStatus.currentStep == 3)
+           level = 2;
+    else if(utilization < GPU_DVFS_DOWN_THRESHOLD &&
+           maliDvfsStatus.currentStep == 2)
+           level = 1;
+    else if(utilization < GPU_DVFS_DOWN_THRESHOLD &&
+           maliDvfsStatus.currentStep == 1)
+           level = 0;
+    else
+           level = maliDvfsStatus.currentStep;
+    return level;
+}
+
+static mali_bool set_mali_dvfs_status(u32 step)
+{
+       u32 validatedStep=step; 
+
+       _mali_osk_mutex_wait(clockSetlock);
+       mali_clk_set_rate(mali_clock, mali_dvfs[validatedStep]);
+       _mali_osk_mutex_signal(clockSetlock);
+       set_mali_dvfs_step(validatedStep);
+       
+       return MALI_TRUE;
+}
+
+static mali_bool change_mali_dvfs_status(u32 step)
+{
+       if(!set_mali_dvfs_status(step)) {
+               MALI_DEBUG_PRINT(2,("error on set_mali_dvfs_status: %d\n",step));
+               return MALI_FALSE;
+       }
+
+       return MALI_TRUE;
+}
+
+static void  mali_freq_scale_work(struct work_struct *work)
+{      
+
+       u32 nextStatus = 0;
+       u32 curStatus = 0;
+
+       curStatus = get_mali_dvfs_status();
+       nextStatus = decideNextStatus(utilization_global);
+       
+       if (curStatus!=nextStatus) {
+               if (!change_mali_dvfs_status(nextStatus)) {
+                       MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n"));
+               }
+       }               
+}
+static mali_bool init_mali_clock(void)
+{
+       mali_bool ret = MALI_TRUE;
+       int i;
+
+       if (mali_clock != 0 || mali_clock_pd != 0)
+               return ret; 
+#if 1
+       mali_clock_pd = clk_get(NULL,GPUCLK_PD_NAME);
+       if (IS_ERR(mali_clock_pd)) {
+               MALI_PRINT( ("MALI Error : failed to get source mali pd\n"));
+               ret = MALI_FALSE;
+               goto err_gpu_clk;
+       }
+       clk_prepare_enable(mali_clock_pd);
+#endif
+       mali_clock = clk_get_dvfs_node(GPUCLK_NAME);
+       if (IS_ERR(mali_clock)) {
+               MALI_PRINT( ("MALI Error : failed to get source mali clock\n"));
+               ret = MALI_FALSE;
+               goto err_gpu_clk;
+       }
+       dvfs_clk_prepare_enable(mali_clock);
+       freq_table = dvfs_get_freq_volt_table(mali_clock);
+       if (!freq_table) {
+               MALI_PRINT(("Stop,dvfs table should be set in dts\n"));
+               return MALI_FALSE;
+       }
+       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+               mali_dvfs[i] = freq_table[i].frequency/1000;
+       }
+       mali_init_clock = mali_dvfs[0];
+       num_clock = i;
+       minuend = 1;
+       MALI_PRINT(("Mali400 inside of rk3126\r\n"));
+
+       mali_clk_set_rate(mali_clock, mali_init_clock);
+       gpu_power_state = 1;
+
+       return MALI_TRUE;
+
+err_gpu_clk:
+       MALI_PRINT(("::clk_put:: %s mali_clock\n", __FUNCTION__));
+       gpu_power_state = 0;
+#if 1
+       clk_disable_unprepare(mali_clock_pd);
+#endif
+       dvfs_clk_disable_unprepare(mali_clock);
+       mali_clock = 0;
+       mali_clock_pd = 0;
+       return ret;
+}
+
+static mali_bool deinit_mali_clock(void)
+{
+       if (mali_clock == 0 && mali_clock_pd == 0)
+               return MALI_TRUE;
+       dvfs_clk_disable_unprepare(mali_clock);
+#if 1
+       clk_disable_unprepare(mali_clock_pd);
+#endif
+       mali_clock = 0;
+       mali_clock_pd = 0;
+       if(gpu_power_state)
+               gpu_power_state = 0;
+
+       return MALI_TRUE;
+}
+
+mali_bool init_mali_dvfs_status(int step)
+{
+       set_mali_dvfs_step(step);
+    return MALI_TRUE;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mali_pm_early_suspend(struct early_suspend *mali_dev)
+{
+       /*do nothing*/
+}
+static void mali_pm_late_resume(struct early_suspend *mali_dev)
+{
+       /*do nothing*/
+}
+static struct early_suspend mali_dev_early_suspend = {
+       .suspend = mali_pm_early_suspend,
+       .resume = mali_pm_late_resume,
+       .level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
+};
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+_mali_osk_errcode_t mali_platform_init(void)
+{
+       if (cpu_is_rk3036()) {
+               audis_gpu_clk = clk_get(NULL,"clk_gpu");        
+
+               if (IS_ERR(audis_gpu_clk)) {
+                        MALI_PRINT( ("MALI Error : failed to get audis mali clk\n"));
+                        return MALI_FALSE;
+                        
+               }
+
+               clk_prepare_enable(audis_gpu_clk);
+
+               MALI_SUCCESS;
+       }
+       MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT);
+       
+       clockSetlock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED,_MALI_OSK_LOCK_ORDER_UTILIZATION);
+
+       if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP))
+               MALI_DEBUG_PRINT(1, ("init_mali_dvfs_status failed\n"));
+       
+       if(mali400_utility_sysfs_init())
+               MALI_PRINT(("mali400_utility_sysfs_init error\r\n"));
+       
+       mali_freq_data = kmalloc(sizeof(struct mali_freq_data), GFP_KERNEL);
+       if(!mali_freq_data) {
+               MALI_PRINT(("kmalloc error\r\n"));
+               MALI_ERROR(-1);
+       }
+       mali_freq_data->wq = create_workqueue(mali_freq_workqueue_name);
+       if(!mali_freq_data->wq)
+               MALI_ERROR(-1);
+       INIT_WORK(&mali_freq_data->work,mali_freq_scale_work);
+       
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       register_early_suspend(&mali_dev_early_suspend);
+#endif
+
+    MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_deinit(void)
+{
+       if (cpu_is_rk3036()) {
+               clk_disable_unprepare(audis_gpu_clk);
+               MALI_SUCCESS;
+       }
+
+       deinit_mali_clock();
+       _mali_osk_mutex_term(clockSetlock);
+
+    MALI_SUCCESS;
+}
+_mali_osk_errcode_t mali_power_domain_control(u32 bpower_off)
+{
+       if (!bpower_off) {
+               if (!gpu_power_state) {
+                       if (cpu_is_rk3036()) {
+                               clk_prepare_enable(audis_gpu_clk);
+                       } else {
+               #if 1
+                               clk_prepare_enable(mali_clock_pd);
+               #endif
+                               dvfs_clk_prepare_enable(mali_clock);
+                       }
+                       gpu_power_state = 1 ;
+               }               
+       } else if (bpower_off == 2) {
+               ;
+       } else if (bpower_off == 1) {
+               if(gpu_power_state) {
+                       if (cpu_is_rk3036()) {
+                               clk_disable_unprepare(audis_gpu_clk);
+                       } else {
+                               dvfs_clk_disable_unprepare(mali_clock);
+               #if 1
+                               clk_disable_unprepare(mali_clock_pd);   
+               #endif
+                       }
+                       gpu_power_state = 0;
+               }
+       }
+       MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode)
+{
+#if 1
+       switch(power_mode) {
+               case MALI_POWER_MODE_ON:
+                       MALI_DEBUG_PRINT(2,("MALI_POWER_MODE_ON\r\n"));
+                       mali_power_domain_control(MALI_POWER_MODE_ON);
+                       break;
+               case MALI_POWER_MODE_LIGHT_SLEEP:
+                       MALI_DEBUG_PRINT(2,("MALI_POWER_MODE_LIGHT_SLEEP\r\n"));
+                       mali_power_domain_control(MALI_POWER_MODE_LIGHT_SLEEP);
+                       break;
+               case MALI_POWER_MODE_DEEP_SLEEP:
+                       MALI_DEBUG_PRINT(2,("MALI_POWER_MODE_DEEP_SLEEP\r\n"));
+                       mali_power_domain_control(MALI_POWER_MODE_DEEP_SLEEP);
+                       break;
+               default:
+                       MALI_DEBUG_PRINT(2,("mali_platform_power_mode_change:power_mode(%d) not support \r\n",power_mode));
+       }
+#endif
+    MALI_SUCCESS;
+}
+
+void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data)
+{
+       if (cpu_is_rk3036())
+               return;
+
+       if(data->utilization_pp > 256)
+               return;
+       utilization_global = data->utilization_pp;
+       /*
+       MALI_PRINT(("utilization_global = %d\r\n",utilization_global));
+       */
+       if(scale_enable && sampling_enable)
+               queue_work(mali_freq_data->wq,&mali_freq_data->work);
+       
+       return ;
+}
diff --git a/drivers/gpu/arm/mali400/mali/platform/rk30/mali_platform.h b/drivers/gpu/arm/mali400/mali/platform/rk30/mali_platform.h
new file mode 100755 (executable)
index 0000000..8707f7c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_platform.h
+ * Platform specific Mali driver functions
+ */
+
+#ifndef __MALI_PLATFORM_H__
+#define __MALI_PLATFORM_H__
+
+#include "mali_osk.h"
+#include <linux/mali/mali_utgard.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief description of power change reasons
+ */
+typedef enum mali_power_mode_tag
+{
+       MALI_POWER_MODE_ON,           /**< Power Mali on */
+       MALI_POWER_MODE_LIGHT_SLEEP,  /**< Mali has been idle for a short time, or runtime PM suspend */
+       MALI_POWER_MODE_DEEP_SLEEP,   /**< Mali has been idle for a long time, or OS suspend */
+} mali_power_mode;
+
+/** @brief Platform specific setup and initialisation of MALI
+ *
+ * This is called from the entrypoint of the driver to initialize the platform
+ *
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_platform_init(void);
+
+/** @brief Platform specific deinitialisation of MALI
+ *
+ * This is called on the exit of the driver to terminate the platform
+ *
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_platform_deinit(void);
+
+/** @brief Platform specific powerdown sequence of MALI
+ *
+ * Notification from the Mali device driver stating the new desired power mode.
+ * MALI_POWER_MODE_ON must be obeyed, while the other modes are optional.
+ * @param power_mode defines the power modes
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode);
+
+
+/** @brief Platform specific handling of GPU utilization data
+ *
+ * When GPU utilization data is enabled, this function will be
+ * periodically called.
+ *
+ * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization.
+ */
+void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data);
+
+/** @brief Setting the power domain of MALI
+ *
+ * This function sets the power domain of MALI if Linux run time power management is enabled
+ *
+ * @param dev Reference to struct platform_device (defined in linux) used by MALI GPU
+ */
+void set_mali_parent_power_domain(void* dev);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/platform/rk30/rk3066.c b/drivers/gpu/arm/mali400/mali/platform/rk30/rk3066.c
new file mode 100644 (file)
index 0000000..732faa9
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/*author by xxm  2012-12-1*/
+
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+
+#include "mali_platform.h"
+
+#include <linux/workqueue.h>
+#include <linux/dma-mapping.h>
+#include <linux/rockchip/cpu.h>
+
+static int num_cores_total;
+static int num_cores_enabled;
+static void mali_platform_device_release(struct device *device);
+static int mali_os_suspend(struct device *device);
+static int mali_os_resume(struct device *device);
+static int mali_os_freeze(struct device *device);
+static int mali_os_thaw(struct device *device);
+#ifdef CONFIG_PM_RUNTIME
+static int mali_runtime_suspend(struct device *device);
+static int mali_runtime_resume(struct device *device);
+static int mali_runtime_idle(struct device *device);
+#endif
+
+/*#include "arm_core_scaling.h"*/
+void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
+
+static struct work_struct wq_work;
+
+static struct dev_pm_ops mali_gpu_device_type_pm_ops = {
+       .suspend = mali_os_suspend,
+       .resume = mali_os_resume,
+       .freeze = mali_os_freeze,
+       .thaw = mali_os_thaw,
+#ifdef CONFIG_PM_RUNTIME
+       .runtime_suspend = mali_runtime_suspend,
+       .runtime_resume = mali_runtime_resume,
+       .runtime_idle = mali_runtime_idle,
+#endif
+};
+
+static struct device_type mali_gpu_device_device_type = {
+       .pm = &mali_gpu_device_type_pm_ops,
+};
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+static struct mali_gpu_device_data mali_gpu_data = {
+       .shared_mem_size = 1024* 1024 * 1024, /* 1GB */
+       .fb_start = 0x40000000,
+       .fb_size = 0xb1000000,
+       .utilization_interval = 0, /* 0ms */
+       .utilization_callback = mali_gpu_utilization_handler,
+};
+static void mali_platform_device_add_config(struct platform_device *pdev)
+{
+       if (cpu_is_rk3036())
+               mali_gpu_device_device_type.pm = NULL;
+       pdev->dev.id = 0;
+       pdev->dev.release = mali_platform_device_release;
+       pdev->dev.type = &mali_gpu_device_device_type;
+       pdev->dev.dma_mask = &dma_dmamask;
+       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+}
+static void set_num_cores(struct work_struct *work)
+{
+       int err = mali_perf_set_num_pp_cores(num_cores_enabled);
+       MALI_DEBUG_ASSERT(0 == err);
+       MALI_IGNORE(err);
+}
+static void enable_one_core(void)
+{
+       if (num_cores_enabled < num_cores_total) {
+               ++num_cores_enabled;
+               schedule_work(&wq_work);
+               MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
+       }
+
+       MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
+       MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
+}
+static void disable_one_core(void)
+{
+       if (1 < num_cores_enabled) {
+               --num_cores_enabled;
+               schedule_work(&wq_work);
+               MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
+       }
+
+       MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
+       MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
+}
+static void enable_max_num_cores(void)
+{
+       if (num_cores_enabled < num_cores_total) {
+               num_cores_enabled = num_cores_total;
+               schedule_work(&wq_work);
+               MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
+       }
+
+       MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
+}
+void mali_core_scaling_init(int num_pp_cores)
+{
+       INIT_WORK(&wq_work, set_num_cores);
+
+       num_cores_total   = num_pp_cores;
+       num_cores_enabled = num_pp_cores;
+
+       /* NOTE: Mali is not fully initialized at this point. */
+}
+void mali_core_scaling_term(void)
+{
+       flush_scheduled_work();
+}
+#define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
+void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
+{
+       /*
+        * This function implements a very trivial PP core scaling algorithm.
+        *
+        * It is _NOT_ of production quality.
+        * The only intention behind this algorithm is to exercise and test the
+        * core scaling functionality of the driver.
+        * It is _NOT_ tuned for neither power saving nor performance!
+        *
+        * Other metrics than PP utilization need to be considered as well
+        * in order to make a good core scaling algorithm.
+        */
+
+       MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", 
+                        data->utilization_gpu, data->utilization_gp,
+                        data->utilization_pp, num_cores_enabled, num_cores_total));
+
+       /* NOTE: this function is normally called directly from the utilization callback which is in
+        * timer context. */
+
+       if (PERCENT_OF(90, 256) < data->utilization_pp) {
+               enable_max_num_cores();
+       } else if (PERCENT_OF(50, 256) < data->utilization_pp) {
+               enable_one_core();
+       } else if (PERCENT_OF(40, 256) < data->utilization_pp) {
+               /* do nothing */
+       } else if (PERCENT_OF( 0, 256) < data->utilization_pp) {
+               disable_one_core();
+       } else {
+               /* do nothing */
+       }
+}
+int mali_platform_device_register(struct platform_device *pdev)
+{
+       int err = 0;
+       int num_pp_cores = 0;
+       MALI_PRINT(("mali_platform_device_register() called\n"));
+       
+       num_pp_cores = 1;
+       
+       mali_platform_device_add_config(pdev);
+
+       err = platform_device_add_data(pdev, &mali_gpu_data, sizeof(mali_gpu_data));
+       
+       if (0 == err) {
+               err = mali_platform_init();
+               if(0 == err) {
+#ifdef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+                       pm_runtime_set_autosuspend_delay(&(pdev->dev), 1000);
+                       pm_runtime_use_autosuspend(&(pdev->dev));
+#endif
+                       pm_runtime_enable(&(pdev->dev));
+#endif
+                       mali_core_scaling_init(num_pp_cores);
+                       return 0;
+               }
+       }
+       return err;
+}
+void mali_platform_device_unregister(struct platform_device *pdev)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
+
+       mali_platform_deinit();
+       mali_core_scaling_term();
+}
+
+static void mali_platform_device_release(struct device *device)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
+}
+static int mali_os_suspend(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(2, ("mali_os_suspend() called\n"));
+       
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->suspend) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->suspend(device);
+       }
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
+
+       return ret;
+}
+
+static int mali_os_resume(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(2, ("mali_os_resume() called\n"));
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->resume) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->resume(device);
+       }
+
+       return ret;
+}
+
+static int mali_os_freeze(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->freeze) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->freeze(device);
+       }
+
+       return ret;
+}
+
+static int mali_os_thaw(struct device *device)
+{
+       int ret = 0;
+
+       MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->thaw) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->thaw(device);
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int mali_runtime_suspend(struct device *device)
+{
+       int ret = 0;
+       MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->runtime_suspend) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->runtime_suspend(device);
+       }
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
+
+       return ret;
+}
+
+static int mali_runtime_resume(struct device *device)
+{
+       int ret = 0;
+       MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
+
+       mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->runtime_resume) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->runtime_resume(device);
+       }
+
+       return ret;
+}
+
+static int mali_runtime_idle(struct device *device)
+{
+       int ret = 0;
+       MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
+
+       if (NULL != device->driver &&
+           NULL != device->driver->pm &&
+           NULL != device->driver->pm->runtime_idle) {
+               /* Need to notify Mali driver about this event */
+               ret = device->driver->pm->runtime_idle(device);
+               if (0 != ret)
+                       return ret;
+       }
+
+       pm_runtime_suspend(device);
+
+       return 0;
+}
+#endif
+void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
+{
+       mali_core_scaling_update(data);
+}
+
diff --git a/drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c b/drivers/gpu/arm/mali400/mali/platform/tcc8900/tcc8900.c
new file mode 100755 (executable)
index 0000000..d7d2d6f
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file mali_platform.c
+ * Platform specific Mali driver functions for the TCC8900 platform
+ */
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+#include <linux/mali/mali_utgard.h>
+#include "mali_kernel_common.h"
+
+static void mali_platform_device_release(struct device *device);
+
+#define MALI_GP_IRQ    25
+#define MALI_PP_IRQ    24
+#define MALI_MMU_IRQ   26
+
+static struct resource mali_gpu_resources[] =
+{
+       MALI_GPU_RESOURCES_MALI200(0xF0000000, MALI_GP_IRQ, MALI_PP_IRQ, MALI_MMU_IRQ)
+};
+
+static struct platform_device mali_gpu_device =
+{
+       .name = MALI_GPU_NAME_UTGARD,
+       .id = 0,
+       .dev.release = mali_platform_device_release,
+};
+
+static struct mali_gpu_device_data mali_gpu_data =
+{
+#if 0
+       /* Dedicated memory setup (not sure if this is actually reserved on the platforms any more) */
+       .dedicated_mem_start = 0x48A00000, /* Physical start address */
+       .dedicated_mem_size = 0x07800000, /* 120MB */
+#endif
+       .shared_mem_size = 96 * 1024 * 1024, /* 96MB */
+       .fb_start = 0x48200000,
+       .fb_size = 0x00800000,
+};
+
+int mali_platform_device_register(void)
+{
+       int err;
+
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n"));
+
+       /* Connect resources to the device */
+       err = platform_device_add_resources(&mali_gpu_device, mali_gpu_resources, sizeof(mali_gpu_resources) / sizeof(mali_gpu_resources[0]));
+       if (0 == err)
+       {
+               err = platform_device_add_data(&mali_gpu_device, &mali_gpu_data, sizeof(mali_gpu_data));
+               if (0 == err)
+               {
+                       /* Register the platform device */
+                       err = platform_device_register(&mali_gpu_device);
+                       if (0 == err)
+                       {
+#ifdef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+                               pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000);
+                               pm_runtime_use_autosuspend(&(mali_gpu_device.dev));
+#endif
+                               pm_runtime_enable(&(mali_gpu_device.dev));
+#endif
+
+                               return 0;
+                       }
+               }
+
+               platform_device_unregister(&mali_gpu_device);
+       }
+
+       return err;
+}
+
+void mali_platform_device_unregister(void)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
+
+       platform_device_unregister(&mali_gpu_device);
+}
+
+static void mali_platform_device_release(struct device *device)
+{
+       MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
+}
diff --git a/drivers/gpu/arm/mali400/mali/regs/mali_200_regs.h b/drivers/gpu/arm/mali400/mali/regs/mali_200_regs.h
new file mode 100755 (executable)
index 0000000..1aa67e7
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef _MALI200_REGS_H_
+#define _MALI200_REGS_H_
+
+/**
+ *  Enum for management register addresses.
+ */
+enum mali200_mgmt_reg {
+       MALI200_REG_ADDR_MGMT_VERSION                              = 0x1000,
+       MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR               = 0x1004,
+       MALI200_REG_ADDR_MGMT_STATUS                               = 0x1008,
+       MALI200_REG_ADDR_MGMT_CTRL_MGMT                            = 0x100c,
+
+       MALI200_REG_ADDR_MGMT_INT_RAWSTAT                          = 0x1020,
+       MALI200_REG_ADDR_MGMT_INT_CLEAR                            = 0x1024,
+       MALI200_REG_ADDR_MGMT_INT_MASK                             = 0x1028,
+       MALI200_REG_ADDR_MGMT_INT_STATUS                           = 0x102c,
+
+       MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW                   = 0x1044,
+
+       MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS                     = 0x1050,
+
+       MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE                    = 0x1080,
+       MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC                       = 0x1084,
+       MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE                     = 0x108c,
+
+       MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE                    = 0x10a0,
+       MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC                       = 0x10a4,
+       MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE                     = 0x10ac,
+
+       MALI200_REG_ADDR_MGMT_PERFMON_CONTR                        = 0x10b0,
+       MALI200_REG_ADDR_MGMT_PERFMON_BASE                         = 0x10b4,
+
+       MALI200_REG_SIZEOF_REGISTER_BANK                           = 0x10f0
+
+};
+
+#define MALI200_REG_VAL_PERF_CNT_ENABLE 1
+
+enum mali200_mgmt_ctrl_mgmt {
+       MALI200_REG_VAL_CTRL_MGMT_STOP_BUS         = (1<<0),
+       MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES     = (1<<3),
+       MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET      = (1<<5),
+       MALI200_REG_VAL_CTRL_MGMT_START_RENDERING  = (1<<6),
+       MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET     = (1<<7), /* Only valid for Mali-300 and later */
+};
+
+enum mali200_mgmt_irq {
+       MALI200_REG_VAL_IRQ_END_OF_FRAME          = (1<<0),
+       MALI200_REG_VAL_IRQ_END_OF_TILE           = (1<<1),
+       MALI200_REG_VAL_IRQ_HANG                  = (1<<2),
+       MALI200_REG_VAL_IRQ_FORCE_HANG            = (1<<3),
+       MALI200_REG_VAL_IRQ_BUS_ERROR             = (1<<4),
+       MALI200_REG_VAL_IRQ_BUS_STOP              = (1<<5),
+       MALI200_REG_VAL_IRQ_CNT_0_LIMIT           = (1<<6),
+       MALI200_REG_VAL_IRQ_CNT_1_LIMIT           = (1<<7),
+       MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR  = (1<<8),
+       MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND = (1<<9),
+       MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW  = (1<<10),
+       MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW   = (1<<11),
+       MALI400PP_REG_VAL_IRQ_RESET_COMPLETED       = (1<<12),
+};
+
+#define MALI200_REG_VAL_IRQ_MASK_ALL  ((enum mali200_mgmt_irq) (\
+    MALI200_REG_VAL_IRQ_END_OF_FRAME                           |\
+    MALI200_REG_VAL_IRQ_END_OF_TILE                            |\
+    MALI200_REG_VAL_IRQ_HANG                                   |\
+    MALI200_REG_VAL_IRQ_FORCE_HANG                             |\
+    MALI200_REG_VAL_IRQ_BUS_ERROR                              |\
+    MALI200_REG_VAL_IRQ_BUS_STOP                               |\
+    MALI200_REG_VAL_IRQ_CNT_0_LIMIT                            |\
+    MALI200_REG_VAL_IRQ_CNT_1_LIMIT                            |\
+    MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR                   |\
+    MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND                  |\
+    MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW                   |\
+    MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW                    |\
+    MALI400PP_REG_VAL_IRQ_RESET_COMPLETED))
+
+#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\
+    MALI200_REG_VAL_IRQ_END_OF_FRAME                           |\
+    MALI200_REG_VAL_IRQ_FORCE_HANG                             |\
+    MALI200_REG_VAL_IRQ_BUS_ERROR                              |\
+    MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR                   |\
+    MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND                  |\
+    MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW                   |\
+    MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW))
+
+#define MALI200_REG_VAL_IRQ_MASK_NONE ((enum mali200_mgmt_irq)(0))
+
+enum mali200_mgmt_status {
+       MALI200_REG_VAL_STATUS_RENDERING_ACTIVE     = (1<<0),
+       MALI200_REG_VAL_STATUS_BUS_STOPPED          = (1<<4),
+};
+
+enum mali200_render_unit {
+       MALI200_REG_ADDR_FRAME = 0x0000,
+       MALI200_REG_ADDR_RSW   = 0x0004,
+       MALI200_REG_ADDR_STACK = 0x0030,
+       MALI200_REG_ADDR_STACK_SIZE = 0x0034,
+       MALI200_REG_ADDR_ORIGIN_OFFSET_X  = 0x0040
+};
+
+enum mali200_wb_unit {
+       MALI200_REG_ADDR_WB0 = 0x0100,
+       MALI200_REG_ADDR_WB1 = 0x0200,
+       MALI200_REG_ADDR_WB2 = 0x0300
+};
+
+enum mali200_wb_unit_regs {
+       MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000,
+       MALI200_REG_ADDR_WB_SOURCE_ADDR   = 0x0004,
+};
+
+/* This should be in the top 16 bit of the version register of Mali PP */
+#define MALI200_PP_PRODUCT_ID 0xC807
+#define MALI300_PP_PRODUCT_ID 0xCE07
+#define MALI400_PP_PRODUCT_ID 0xCD07
+#define MALI450_PP_PRODUCT_ID 0xCF07
+
+
+#endif /* _MALI200_REGS_H_ */
diff --git a/drivers/gpu/arm/mali400/mali/regs/mali_gp_regs.h b/drivers/gpu/arm/mali400/mali/regs/mali_gp_regs.h
new file mode 100755 (executable)
index 0000000..e865e13
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef _MALIGP2_CONROL_REGS_H_
+#define _MALIGP2_CONROL_REGS_H_
+
+/**
+ * These are the different geometry processor control registers.
+ * Their usage is to control and monitor the operation of the
+ * Vertex Shader and the Polygon List Builder in the geometry processor.
+ * Addresses are in 32-bit word relative sizes.
+ * @see [P0081] "Geometry Processor Data Structures" for details
+ */
+
+typedef enum {
+       MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR           = 0x00,
+       MALIGP2_REG_ADDR_MGMT_VSCL_END_ADDR             = 0x04,
+       MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR         = 0x08,
+       MALIGP2_REG_ADDR_MGMT_PLBUCL_END_ADDR           = 0x0c,
+       MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR     = 0x10,
+       MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR       = 0x14,
+       MALIGP2_REG_ADDR_MGMT_CMD                       = 0x20,
+       MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT               = 0x24,
+       MALIGP2_REG_ADDR_MGMT_INT_CLEAR                 = 0x28,
+       MALIGP2_REG_ADDR_MGMT_INT_MASK                  = 0x2C,
+       MALIGP2_REG_ADDR_MGMT_INT_STAT                  = 0x30,
+       MALIGP2_REG_ADDR_MGMT_WRITE_BOUND_LOW           = 0x34,
+       MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE         = 0x3C,
+       MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE         = 0x40,
+       MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC            = 0x44,
+       MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC            = 0x48,
+       MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE          = 0x4C,
+       MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE          = 0x50,
+       MALIGP2_REG_ADDR_MGMT_STATUS                    = 0x68,
+       MALIGP2_REG_ADDR_MGMT_VERSION                   = 0x6C,
+       MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR_READ      = 0x80,
+       MALIGP2_REG_ADDR_MGMT_PLBCL_START_ADDR_READ     = 0x84,
+       MALIGP2_CONTR_AXI_BUS_ERROR_STAT                = 0x94,
+       MALIGP2_REGISTER_ADDRESS_SPACE_SIZE             = 0x98,
+} maligp_reg_addr_mgmt_addr;
+
+#define MALIGP2_REG_VAL_PERF_CNT_ENABLE 1
+
+/**
+ * Commands to geometry processor.
+ *  @see MALIGP2_CTRL_REG_CMD
+ */
+typedef enum {
+       MALIGP2_REG_VAL_CMD_START_VS                    = (1<< 0),
+       MALIGP2_REG_VAL_CMD_START_PLBU                  = (1<< 1),
+       MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC   = (1<< 4),
+       MALIGP2_REG_VAL_CMD_RESET                               = (1<< 5),
+       MALIGP2_REG_VAL_CMD_FORCE_HANG                  = (1<< 6),
+       MALIGP2_REG_VAL_CMD_STOP_BUS                    = (1<< 9),
+       MALI400GP_REG_VAL_CMD_SOFT_RESET                = (1<<10), /* only valid for Mali-300 and later */
+} mgp_contr_reg_val_cmd;
+
+
+/**  @defgroup MALIGP2_IRQ
+ * Interrupt status of geometry processor.
+ *  @see MALIGP2_CTRL_REG_INT_RAWSTAT, MALIGP2_REG_ADDR_MGMT_INT_CLEAR,
+ *       MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_ADDR_MGMT_INT_STAT
+ * @{
+ */
+#define MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      (1 << 0)
+#define MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST    (1 << 1)
+#define MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM     (1 << 2)
+#define MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ          (1 << 3)
+#define MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ        (1 << 4)
+#define MALIGP2_REG_VAL_IRQ_HANG                (1 << 5)
+#define MALIGP2_REG_VAL_IRQ_FORCE_HANG          (1 << 6)
+#define MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT    (1 << 7)
+#define MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT    (1 << 8)
+#define MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     (1 << 9)
+#define MALIGP2_REG_VAL_IRQ_SYNC_ERROR          (1 << 10)
+#define MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR       (1 << 11)
+#define MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED     (1 << 12)
+#define MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD      (1 << 13)
+#define MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD     (1 << 14)
+#define MALI400GP_REG_VAL_IRQ_RESET_COMPLETED     (1 << 19)
+#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW (1 << 20)
+#define MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW  (1 << 21)
+#define MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS  (1 << 22)
+
+/* Mask defining all IRQs in Mali GP */
+#define MALIGP2_REG_VAL_IRQ_MASK_ALL \
+       (\
+               MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      | \
+               MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST    | \
+               MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM     | \
+               MALIGP2_REG_VAL_IRQ_VS_SEM_IRQ          | \
+               MALIGP2_REG_VAL_IRQ_PLBU_SEM_IRQ        | \
+               MALIGP2_REG_VAL_IRQ_HANG                | \
+               MALIGP2_REG_VAL_IRQ_FORCE_HANG          | \
+               MALIGP2_REG_VAL_IRQ_PERF_CNT_0_LIMIT    | \
+               MALIGP2_REG_VAL_IRQ_PERF_CNT_1_LIMIT    | \
+               MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     | \
+               MALIGP2_REG_VAL_IRQ_SYNC_ERROR          | \
+               MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR       | \
+               MALI400GP_REG_VAL_IRQ_AXI_BUS_STOPPED     | \
+               MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD      | \
+               MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD     | \
+               MALI400GP_REG_VAL_IRQ_RESET_COMPLETED     | \
+               MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \
+               MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW  | \
+               MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS)
+
+/* Mask defining the IRQs in Mali GP which we use */
+#define MALIGP2_REG_VAL_IRQ_MASK_USED \
+       (\
+               MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST      | \
+               MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST    | \
+               MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM     | \
+               MALIGP2_REG_VAL_IRQ_FORCE_HANG          | \
+               MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR     | \
+               MALIGP2_REG_VAL_IRQ_SYNC_ERROR          | \
+               MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR       | \
+               MALI400GP_REG_VAL_IRQ_VS_INVALID_CMD      | \
+               MALI400GP_REG_VAL_IRQ_PLB_INVALID_CMD     | \
+               MALI400GP_REG_VAL_IRQ_SEMAPHORE_UNDERFLOW | \
+               MALI400GP_REG_VAL_IRQ_SEMAPHORE_OVERFLOW  | \
+               MALI400GP_REG_VAL_IRQ_PTR_ARRAY_OUT_OF_BOUNDS)
+
+/* Mask defining non IRQs on MaliGP2*/
+#define MALIGP2_REG_VAL_IRQ_MASK_NONE 0
+
+/** }@ defgroup MALIGP2_IRQ*/
+
+/** @defgroup MALIGP2_STATUS
+ * The different Status values to the geometry processor.
+ *  @see MALIGP2_CTRL_REG_STATUS
+ * @{
+ */
+#define MALIGP2_REG_VAL_STATUS_VS_ACTIVE         0x0002
+#define MALIGP2_REG_VAL_STATUS_BUS_STOPPED       0x0004
+#define MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE       0x0008
+#define MALIGP2_REG_VAL_STATUS_BUS_ERROR         0x0040
+#define MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR   0x0100
+/** }@ defgroup MALIGP2_STATUS*/
+
+#define MALIGP2_REG_VAL_STATUS_MASK_ACTIVE (\
+       MALIGP2_REG_VAL_STATUS_VS_ACTIVE|\
+       MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE)
+
+
+#define MALIGP2_REG_VAL_STATUS_MASK_ERROR (\
+       MALIGP2_REG_VAL_STATUS_BUS_ERROR |\
+       MALIGP2_REG_VAL_STATUS_WRITE_BOUND_ERR )
+
+/* This should be in the top 16 bit of the version register of gp.*/
+#define MALI200_GP_PRODUCT_ID 0xA07
+#define MALI300_GP_PRODUCT_ID 0xC07
+#define MALI400_GP_PRODUCT_ID 0xB07
+#define MALI450_GP_PRODUCT_ID 0xD07
+
+/**
+ * The different sources for instrumented on the geometry processor.
+ *  @see MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC
+ */
+
+enum MALIGP2_cont_reg_perf_cnt_src {
+       MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED = 0x0a,
+};
+
+#endif
diff --git a/drivers/gpu/arm/mali400/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/gpu/arm/mali400/mali/timestamp-arm11-cc/mali_timestamp.c
new file mode 100755 (executable)
index 0000000..dc44c4b
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_timestamp.h"
+
+/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */
diff --git a/drivers/gpu/arm/mali400/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/arm/mali400/mali/timestamp-arm11-cc/mali_timestamp.h
new file mode 100755 (executable)
index 0000000..0b53257
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_TIMESTAMP_H__
+#define __MALI_TIMESTAMP_H__
+
+#include "mali_osk.h"
+
+MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void)
+{
+       /*
+        * reset counters and overflow flags
+        */
+
+       u32 mask = (1 << 0) | /* enable all three counters */
+                  (0 << 1) | /* reset both Count Registers to 0x0 */
+                  (1 << 2) | /* reset the Cycle Counter Register to 0x0 */
+                  (0 << 3) | /* 1 = Cycle Counter Register counts every 64th processor clock cycle */
+                  (0 << 4) | /* Count Register 0 interrupt enable */
+                  (0 << 5) | /* Count Register 1 interrupt enable */
+                  (0 << 6) | /* Cycle Counter interrupt enable */
+                  (0 << 8) | /* Count Register 0 overflow flag (clear or write, flag on read) */
+                  (0 << 9) | /* Count Register 1 overflow flag (clear or write, flag on read) */
+                  (1 << 10); /* Cycle Counter Register overflow flag (clear or write, flag on read) */
+
+       __asm__ __volatile__ ("MCR    p15, 0, %0, c15, c12, 0" : : "r" (mask) );
+
+       return _MALI_OSK_ERR_OK;
+}
+
+MALI_STATIC_INLINE u64 _mali_timestamp_get(void)
+{
+       u32 result;
+
+       /* this is for the clock cycles */
+       __asm__ __volatile__ ("MRC    p15, 0, %0, c15, c12, 1" : "=r" (result));
+
+       return (u64)result;
+}
+
+#endif /* __MALI_TIMESTAMP_H__ */
diff --git a/drivers/gpu/arm/mali400/mali/timestamp-default/mali_timestamp.c b/drivers/gpu/arm/mali400/mali/timestamp-default/mali_timestamp.c
new file mode 100755 (executable)
index 0000000..dc44c4b
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_timestamp.h"
+
+/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */
diff --git a/drivers/gpu/arm/mali400/mali/timestamp-default/mali_timestamp.h b/drivers/gpu/arm/mali400/mali/timestamp-default/mali_timestamp.h
new file mode 100755 (executable)
index 0000000..a059ebb
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __MALI_TIMESTAMP_H__
+#define __MALI_TIMESTAMP_H__
+
+#include "mali_osk.h"
+
+MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void)
+{
+       return _MALI_OSK_ERR_OK;
+}
+
+MALI_STATIC_INLINE u64 _mali_timestamp_get(void)
+{
+       return _mali_osk_time_get_ns();
+}
+
+#endif /* __MALI_TIMESTAMP_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/Kbuild b/drivers/gpu/arm/mali400/ump/Kbuild
new file mode 100755 (executable)
index 0000000..4bc2472
--- /dev/null
@@ -0,0 +1,95 @@
+#
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2008-2012 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
+#
+
+# Set default configuration to use, if Makefile didn't provide one.
+# Change this to use a different config.h
+CONFIG ?= pb-virtex5-m400-4
+
+# Validate selected config
+ifneq ($(shell [ -d $(src)/arch-$(CONFIG) ] && [ -f  $(src)/arch-$(CONFIG)/config.h ] && echo "OK"), OK)
+$(warning Current directory is $(src))
+$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists)
+else
+# Link arch to the selected arch-config directory
+$(shell [ -L $(src)/arch ] && rm $(src)/arch)
+$(shell ln -sf arch-$(CONFIG) $(src)/arch)
+$(shell touch $(src)/arch/config.h)
+endif
+
+UDD_FILE_PREFIX = ../mali/
+
+# Get subversion revision number, fall back to 0000 if no svn info is available
+SVN_INFO = (cd $(src); svn info 2>/dev/null)
+
+ifneq ($(shell $(SVN_INFO) 2>/dev/null),)
+# SVN detected
+SVN_REV := $(shell $(SVN_INFO) | grep '^Revision: '| sed -e 's/^Revision: //' 2>/dev/null)
+DRIVER_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV)
+CHANGE_DATE := $(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-)
+CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-)
+REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-)
+
+else # SVN
+GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null)
+ifneq ($(GIT_REV),)
+# Git detected
+DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV)
+CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci")
+CHANGED_REVISION := $(GIT_REV)
+REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null)
+
+else # Git
+# No Git or SVN detected
+DRIVER_REV := $(MALI_RELEASE_NAME)
+CHANGE_DATE := $(MALI_RELEASE_NAME)
+CHANGED_REVISION := $(MALI_RELEASE_NAME)
+endif
+endif
+
+ccflags-y += -DSVN_REV=$(SVN_REV)
+ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\"
+
+ccflags-y += -I$(src) -I$(src)/common -I$(src)/linux -I$(src)/../mali/common -I$(src)/../mali/linux -I$(src)/../include/ump
+ccflags-y += -DMALI_STATE_TRACKING=0
+ccflags-y += -DMALI_ENABLE_CPU_CYCLES=0
+ccflags-$(CONFIG_UMP_DEBUG) += -DDEBUG
+
+# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases:
+# The ARM proprietary product will only include the license/proprietary directory
+# The GPL product will only include the license/gpl directory
+
+ifeq ($(wildcard $(src)/linux/license/gpl/*),)
+ccflags-y += -I$(src)/linux/license/proprietary -I$(src)/../mali/linux/license/proprietary
+else
+ccflags-y += -I$(src)/linux/license/gpl -I$(src)/../mali/linux/license/gpl
+endif
+
+ump-y = common/ump_kernel_common.o \
+       common/ump_kernel_descriptor_mapping.o \
+       common/ump_kernel_api.o \
+       common/ump_kernel_ref_drv.o \
+       linux/ump_kernel_linux.o \
+       linux/ump_kernel_memory_backend_os.o \
+       linux/ump_kernel_memory_backend_dedicated.o \
+       linux/ump_memory_backend.o \
+       linux/ump_ukk_wrappers.o \
+       linux/ump_ukk_ref_wrappers.o \
+       linux/ump_osk_atomics.o \
+       linux/ump_osk_low_level_mem.o \
+       linux/ump_osk_misc.o 
+ifeq ($(CONFIG_UMP),m)
+ump-y += $(UDD_FILE_PREFIX)linux/mali_osk_atomics.o 
+ump-y += $(UDD_FILE_PREFIX)linux/mali_osk_locks.o 
+ump-y += $(UDD_FILE_PREFIX)linux/mali_osk_memory.o 
+ump-y += $(UDD_FILE_PREFIX)linux/mali_osk_math.o 
+ump-y += $(UDD_FILE_PREFIX)linux/mali_osk_misc.o
+endif
+obj-$(CONFIG_UMP) := ump.o
+
diff --git a/drivers/gpu/arm/mali400/ump/Kconfig b/drivers/gpu/arm/mali400/ump/Kconfig
new file mode 100755 (executable)
index 0000000..3ae316c
--- /dev/null
@@ -0,0 +1,16 @@
+config UMP
+       tristate "UMP support"
+       depends on ARM
+       ---help---
+         This enables support for the UMP memory allocation and sharing API.
+
+         To compile this driver as a module, choose M here: the module will be
+         called ump.
+
+config UMP_DEBUG
+       bool "Enable extra debug in UMP"
+       depends on UMP
+       default y
+       ---help---
+         This enabled extra debug checks and messages in UMP.
+
diff --git a/drivers/gpu/arm/mali400/ump/Makefile.common b/drivers/gpu/arm/mali400/ump/Makefile.common
new file mode 100755 (executable)
index 0000000..8e62aa0
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# This confidential and proprietary software may be used only as
+# authorised by a licensing agreement from ARM Limited
+# (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+# ALL RIGHTS RESERVED
+# The entire notice above must be reproduced on all authorised
+# copies and copies may only be made to the extent permitted
+# by a licensing agreement from ARM Limited.
+#
+
+SRC = $(UMP_FILE_PREFIX)common/ump_kernel_common.c \
+       $(UMP_FILE_PREFIX)common/ump_kernel_descriptor_mapping.c \
+       $(UMP_FILE_PREFIX)common/ump_kernel_api.c \
+       $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.c
+
+# Get subversion revision number, fall back to 0000 if no svn info is available
+SVN_REV:=$(shell ((svnversion | grep -qv exported && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //')
+
+EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV)
+EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\"
diff --git a/drivers/gpu/arm/mali400/ump/arch b/drivers/gpu/arm/mali400/ump/arch
new file mode 120000 (symlink)
index 0000000..12e631f
--- /dev/null
@@ -0,0 +1 @@
+arch-pb-virtex5-m400-4
\ No newline at end of file
diff --git a/drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h b/drivers/gpu/arm/mali400/ump/arch-pb-virtex5-m400-4/config.h
new file mode 100755 (executable)
index 0000000..e45e31d
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT          1
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT   0//0xC8000000
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT 512UL * 1024UL * 1024UL
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_api.c b/drivers/gpu/arm/mali400/ump/common/ump_kernel_api.c
new file mode 100755 (executable)
index 0000000..e77c822
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "ump_osk.h"
+#include "ump_uk_types.h"
+#include "ump_kernel_interface.h"
+#include "ump_kernel_common.h"
+
+
+
+/* ---------------- UMP kernel space API functions follows ---------------- */
+
+
+
+UMP_KERNEL_API_EXPORT ump_secure_id ump_dd_secure_id_get(ump_dd_handle memh)
+{
+       ump_dd_mem * mem = (ump_dd_mem *)memh;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       DBG_MSG(5, ("Returning secure ID. ID: %u\n", mem->secure_id));
+
+       return mem->secure_id;
+}
+
+
+
+UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secure_id secure_id)
+{
+       ump_dd_mem * mem;
+
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+
+       DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id));
+       if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id));
+               return UMP_DD_HANDLE_INVALID;
+       }
+
+       ump_dd_reference_add(mem);
+
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+
+       return (ump_dd_handle)mem;
+}
+
+
+
+UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh)
+{
+       ump_dd_mem * mem = (ump_dd_mem*) memh;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       return mem->nr_blocks;
+}
+
+
+
+UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_blocks_get(ump_dd_handle memh, ump_dd_physical_block * blocks, unsigned long num_blocks)
+{
+       ump_dd_mem * mem = (ump_dd_mem *)memh;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       if (blocks == NULL) {
+               DBG_MSG(1, ("NULL parameter in ump_dd_phys_blocks_get()\n"));
+               return UMP_DD_INVALID;
+       }
+
+       if (mem->nr_blocks != num_blocks) {
+               DBG_MSG(1, ("Specified number of blocks do not match actual number of blocks\n"));
+               return UMP_DD_INVALID;
+       }
+
+       DBG_MSG(5, ("Returning physical block information. ID: %u\n", mem->secure_id));
+
+       _mali_osk_memcpy(blocks, mem->block_array, sizeof(ump_dd_physical_block) * mem->nr_blocks);
+
+       return UMP_DD_SUCCESS;
+}
+
+
+
+UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_phys_block_get(ump_dd_handle memh, unsigned long index, ump_dd_physical_block * block)
+{
+       ump_dd_mem * mem = (ump_dd_mem *)memh;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       if (block == NULL) {
+               DBG_MSG(1, ("NULL parameter in ump_dd_phys_block_get()\n"));
+               return UMP_DD_INVALID;
+       }
+
+       if (index >= mem->nr_blocks) {
+               DBG_MSG(5, ("Invalid index specified in ump_dd_phys_block_get()\n"));
+               return UMP_DD_INVALID;
+       }
+
+       DBG_MSG(5, ("Returning physical block information. ID: %u, index: %lu\n", mem->secure_id, index));
+
+       *block = mem->block_array[index];
+
+       return UMP_DD_SUCCESS;
+}
+
+
+
+UMP_KERNEL_API_EXPORT unsigned long ump_dd_size_get(ump_dd_handle memh)
+{
+       ump_dd_mem * mem = (ump_dd_mem*)memh;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       DBG_MSG(5, ("Returning size. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes));
+
+       return mem->size_bytes;
+}
+
+
+
+UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle memh)
+{
+       ump_dd_mem * mem = (ump_dd_mem*)memh;
+       int new_ref;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       new_ref = _ump_osk_atomic_inc_and_read(&mem->ref_count);
+
+       DBG_MSG(5, ("Memory reference incremented. ID: %u, new value: %d\n", mem->secure_id, new_ref));
+}
+
+
+
+UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle memh)
+{
+       int new_ref;
+       ump_dd_mem * mem = (ump_dd_mem*)memh;
+
+       DEBUG_ASSERT_POINTER(mem);
+
+       /* We must hold this mutex while doing the atomic_dec_and_read, to protect
+       that elements in the ump_descriptor_mapping table is always valid.  If they
+       are not, userspace may accidently map in this secure_ids right before its freed
+       giving a mapped backdoor into unallocated memory.*/
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+
+       new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count);
+
+       DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n", mem->secure_id, new_ref));
+
+       if (0 == new_ref) {
+               DBG_MSG(3, ("Final release of memory. ID: %u\n", mem->secure_id));
+
+               ump_descriptor_mapping_free(device.secure_id_map, (int)mem->secure_id);
+
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               mem->release_func(mem->ctx, mem);
+               _mali_osk_free(mem);
+       } else {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+       }
+}
+
+
+
+/* --------------- Handling of user space requests follows --------------- */
+
+
+_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args )
+{
+       ump_session_data * session_data;
+
+       DEBUG_ASSERT_POINTER( args );
+       DEBUG_ASSERT_POINTER( args->ctx );
+
+       session_data = (ump_session_data *)args->ctx;
+
+       /* check compatability */
+       if (args->version == UMP_IOCTL_API_VERSION) {
+               DBG_MSG(3, ("API version set to newest %d (compatible)\n", GET_VERSION(args->version)));
+               args->compatible = 1;
+               session_data->api_version = args->version;
+       } else if (args->version == MAKE_VERSION_ID(1)) {
+               DBG_MSG(2, ("API version set to depricated: %d (compatible)\n", GET_VERSION(args->version)));
+               args->compatible = 1;
+               session_data->api_version = args->version;
+       } else {
+               DBG_MSG(2, ("API version set to %d (incompatible with client version %d)\n", GET_VERSION(UMP_IOCTL_API_VERSION), GET_VERSION(args->version)));
+               args->compatible = 0;
+               args->version = UMP_IOCTL_API_VERSION; /* report our version */
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+
+_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info )
+{
+       ump_session_memory_list_element * session_memory_element;
+       ump_session_memory_list_element * tmp;
+       ump_session_data * session_data;
+       _mali_osk_errcode_t ret = _MALI_OSK_ERR_INVALID_FUNC;
+       int secure_id;
+
+       DEBUG_ASSERT_POINTER( release_info );
+       DEBUG_ASSERT_POINTER( release_info->ctx );
+
+       /* Retreive the session data */
+       session_data = (ump_session_data*)release_info->ctx;
+
+       /* If there are many items in the memory session list we
+        * could be de-referencing this pointer a lot so keep a local copy
+        */
+       secure_id = release_info->secure_id;
+
+       DBG_MSG(4, ("Releasing memory with IOCTL, ID: %u\n", secure_id));
+
+       /* Iterate through the memory list looking for the requested secure ID */
+       _mali_osk_mutex_wait(session_data->lock);
+       _MALI_OSK_LIST_FOREACHENTRY(session_memory_element, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) {
+               if ( session_memory_element->mem->secure_id == secure_id) {
+                       ump_dd_mem *release_mem;
+
+                       release_mem = session_memory_element->mem;
+                       _mali_osk_list_del(&session_memory_element->list);
+                       ump_dd_reference_release(release_mem);
+                       _mali_osk_free(session_memory_element);
+
+                       ret = _MALI_OSK_ERR_OK;
+                       break;
+               }
+       }
+
+       _mali_osk_mutex_signal(session_data->lock);
+       DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id));
+
+       DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret));
+       return ret;
+}
+
+_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction )
+{
+       ump_dd_mem * mem;
+       _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT;
+
+       DEBUG_ASSERT_POINTER( user_interaction );
+
+       /* We lock the mappings so things don't get removed while we are looking for the memory */
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)user_interaction->secure_id, (void**)&mem)) {
+               user_interaction->size = mem->size_bytes;
+               DBG_MSG(4, ("Returning size. ID: %u, size: %lu ", (ump_secure_id)user_interaction->secure_id, (unsigned long)user_interaction->size));
+               ret = _MALI_OSK_ERR_OK;
+       } else {
+               user_interaction->size = 0;
+               DBG_MSG(1, ("Failed to look up mapping in ump_ioctl_size_get(). ID: %u\n", (ump_secure_id)user_interaction->secure_id));
+       }
+
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+       return ret;
+}
+
+
+
+void _ump_ukk_msync( _ump_uk_msync_s *args )
+{
+       ump_dd_mem * mem = NULL;
+       void *virtual = NULL;
+       u32 size = 0;
+       u32 offset = 0;
+
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem);
+
+       if (NULL == mem) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_msync(). ID: %u\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+       /* Ensure the memory doesn't dissapear when we are flushing it. */
+       ump_dd_reference_add(mem);
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+
+       /* Returns the cache settings back to Userspace */
+       args->is_cached=mem->is_cached;
+
+       /* If this flag is the only one set, we should not do the actual flush, only the readout */
+       if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED==args->op ) {
+               DBG_MSG(3, ("_ump_ukk_msync READOUT  ID: %u Enabled: %d\n", (ump_secure_id)args->secure_id, mem->is_cached));
+               goto msync_release_and_return;
+       }
+
+       /* Nothing to do if the memory is not caches */
+       if ( 0==mem->is_cached ) {
+               DBG_MSG(3, ("_ump_ukk_msync IGNORING ID: %u Enabled: %d  OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op));
+               goto msync_release_and_return;
+       }
+       DBG_MSG(3, ("UMP[%02u] _ump_ukk_msync  Flush  OP: %d Address: 0x%08x Mapping: 0x%08x\n",
+                   (ump_secure_id)args->secure_id, args->op, args->address, args->mapping));
+
+       if ( args->address ) {
+               virtual = (void *)((u32)args->address);
+               offset = (u32)((args->address) - (args->mapping));
+       } else {
+               /* Flush entire mapping when no address is specified. */
+               virtual = args->mapping;
+       }
+       if ( args->size ) {
+               size = args->size;
+       } else {
+               /* Flush entire mapping when no size is specified. */
+               size = mem->size_bytes - offset;
+       }
+
+       if ( (offset + size) > mem->size_bytes ) {
+               DBG_MSG(1, ("Trying to flush more than the entire UMP allocation: offset: %u + size: %u > %u\n", offset, size, mem->size_bytes));
+               goto msync_release_and_return;
+       }
+
+       /* The actual cache flush - Implemented for each OS*/
+       _ump_osk_msync( mem, virtual, offset, size, args->op, NULL);
+
+msync_release_and_return:
+       ump_dd_reference_release(mem);
+       return;
+}
+
+void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args)
+{
+       ump_session_data * session_data;
+       ump_uk_cache_op_control op;
+
+       DEBUG_ASSERT_POINTER( args );
+       DEBUG_ASSERT_POINTER( args->ctx );
+
+       op = args->op;
+       session_data = (ump_session_data *)args->ctx;
+
+       _mali_osk_mutex_wait(session_data->lock);
+       if ( op== _UMP_UK_CACHE_OP_START ) {
+               session_data->cache_operations_ongoing++;
+               DBG_MSG(4, ("Cache ops start\n" ));
+               if ( session_data->cache_operations_ongoing != 1 ) {
+                       DBG_MSG(2, ("UMP: Number of simultanious cache control ops: %d\n", session_data->cache_operations_ongoing) );
+               }
+       } else if ( op== _UMP_UK_CACHE_OP_FINISH ) {
+               DBG_MSG(4, ("Cache ops finish\n"));
+               session_data->cache_operations_ongoing--;
+#if 0
+               if ( session_data->has_pending_level1_cache_flush) {
+                       /* This function will set has_pending_level1_cache_flush=0 */
+                       _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data);
+               }
+#endif
+
+               /* to be on the safe side: always flush l1 cache when cache operations are done */
+               _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data);
+               DBG_MSG(4, ("Cache ops finish end\n" ));
+       } else {
+               DBG_MSG(1, ("Illegal call to %s at line %d\n", __FUNCTION__, __LINE__));
+       }
+       _mali_osk_mutex_signal(session_data->lock);
+
+}
+
+void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args )
+{
+       ump_dd_mem * mem = NULL;
+       ump_uk_user old_user;
+       ump_uk_msync_op cache_op = _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE;
+       ump_session_data *session_data;
+
+       DEBUG_ASSERT_POINTER( args );
+       DEBUG_ASSERT_POINTER( args->ctx );
+
+       session_data = (ump_session_data *)args->ctx;
+
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem);
+
+       if (NULL == mem) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_switch_hw_usage(). ID: %u\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+
+       old_user = mem->hw_device;
+       mem->hw_device = args->new_user;
+
+       DBG_MSG(3, ("UMP[%02u] Switch usage  Start  New: %s  Prev: %s.\n", (ump_secure_id)args->secure_id, args->new_user?"MALI":"CPU",old_user?"MALI":"CPU"));
+
+       if ( ! mem->is_cached ) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(3, ("UMP[%02u] Changing owner of uncached memory. Cache flushing not needed.\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+
+       if ( old_user == args->new_user) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(4, ("UMP[%02u] Setting the new_user equal to previous for. Cache flushing not needed.\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+       if (
+           /* Previous AND new is both different from CPU */
+           (old_user != _UMP_UK_USED_BY_CPU) && (args->new_user != _UMP_UK_USED_BY_CPU  )
+       ) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(4, ("UMP[%02u] Previous and new user is not CPU. Cache flushing not needed.\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+
+       if ( (old_user != _UMP_UK_USED_BY_CPU ) && (args->new_user==_UMP_UK_USED_BY_CPU) ) {
+               cache_op =_UMP_UK_MSYNC_INVALIDATE;
+               DBG_MSG(4, ("UMP[%02u] Cache invalidation needed\n", (ump_secure_id)args->secure_id));
+#ifdef UMP_SKIP_INVALIDATION
+#error
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(4, ("UMP[%02u] Performing Cache invalidation SKIPPED\n", (ump_secure_id)args->secure_id));
+               return;
+#endif
+       }
+       /* Ensure the memory doesn't dissapear when we are flushing it. */
+       ump_dd_reference_add(mem);
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+
+       /* Take lock to protect: session->cache_operations_ongoing and session->has_pending_level1_cache_flush */
+       _mali_osk_mutex_wait(session_data->lock);
+       /* Actual cache flush */
+       _ump_osk_msync( mem, NULL, 0, mem->size_bytes, cache_op, session_data);
+       _mali_osk_mutex_signal(session_data->lock);
+
+       ump_dd_reference_release(mem);
+       DBG_MSG(4, ("UMP[%02u] Switch usage  Finish\n", (ump_secure_id)args->secure_id));
+       return;
+}
+
+void _ump_ukk_lock(_ump_uk_lock_s *args )
+{
+       ump_dd_mem * mem = NULL;
+
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem);
+
+       if (NULL == mem) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(1, ("UMP[%02u] Failed to look up mapping in _ump_ukk_lock(). ID: %u\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+       ump_dd_reference_add(mem);
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+
+       DBG_MSG(1, ("UMP[%02u] Lock. New lock flag: %d. Old Lock flag:\n", (u32)args->secure_id, (u32)args->lock_usage, (u32) mem->lock_usage ));
+
+       mem->lock_usage = (ump_lock_usage) args->lock_usage;
+
+       ump_dd_reference_release(mem);
+}
+
+void _ump_ukk_unlock(_ump_uk_unlock_s *args )
+{
+       ump_dd_mem * mem = NULL;
+
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem);
+
+       if (NULL == mem) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_unlock(). ID: %u\n", (ump_secure_id)args->secure_id));
+               return;
+       }
+       ump_dd_reference_add(mem);
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+
+       DBG_MSG(1, ("UMP[%02u] Unlocking. Old Lock flag:\n", (u32)args->secure_id, (u32) mem->lock_usage ));
+
+       mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED;
+
+       ump_dd_reference_release(mem);
+}
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_common.c b/drivers/gpu/arm/mali400/ump/common/ump_kernel_common.c
new file mode 100755 (executable)
index 0000000..d57920c
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_bitops.h"
+#include "mali_osk_list.h"
+#include "ump_osk.h"
+#include "ump_uk_types.h"
+#include "ump_ukk.h"
+#include "ump_kernel_common.h"
+#include "ump_kernel_descriptor_mapping.h"
+#include "ump_kernel_memory_backend.h"
+
+
+
+/**
+ * Define the initial and maximum size of number of secure_ids on the system
+ */
+#define UMP_SECURE_ID_TABLE_ENTRIES_INITIAL (128  )
+#define UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM (4096 )
+
+
+/**
+ * Define the initial and maximum size of the ump_session_data::cookies_map,
+ * which is a \ref ump_descriptor_mapping. This limits how many secure_ids
+ * may be mapped into a particular process using _ump_ukk_map_mem().
+ */
+
+#define UMP_COOKIES_PER_SESSION_INITIAL (UMP_SECURE_ID_TABLE_ENTRIES_INITIAL )
+#define UMP_COOKIES_PER_SESSION_MAXIMUM (UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM)
+
+struct ump_dev device;
+
+_mali_osk_errcode_t ump_kernel_constructor(void)
+{
+       _mali_osk_errcode_t err;
+
+       /* Perform OS Specific initialization */
+       err = _ump_osk_init();
+       if( _MALI_OSK_ERR_OK != err ) {
+               MSG_ERR(("Failed to initiaze the UMP Device Driver"));
+               return err;
+       }
+
+       /* Init the global device */
+       _mali_osk_memset(&device, 0, sizeof(device) );
+
+       /* Create the descriptor map, which will be used for mapping secure ID to ump_dd_mem structs */
+       device.secure_id_map_lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_UNORDERED, 0);
+       if (NULL == device.secure_id_map_lock) {
+               MSG_ERR(("Failed to create OSK lock for secure id lookup table\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       device.secure_id_map = ump_descriptor_mapping_create(UMP_SECURE_ID_TABLE_ENTRIES_INITIAL, UMP_SECURE_ID_TABLE_ENTRIES_MAXIMUM);
+       if (NULL == device.secure_id_map) {
+               _mali_osk_mutex_term(device.secure_id_map_lock);
+               MSG_ERR(("Failed to create secure id lookup table\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       /* Init memory backend */
+       device.backend = ump_memory_backend_create();
+       if (NULL == device.backend) {
+               MSG_ERR(("Failed to create memory backend\n"));
+               _mali_osk_mutex_term(device.secure_id_map_lock);
+               ump_descriptor_mapping_destroy(device.secure_id_map);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void ump_kernel_destructor(void)
+{
+       DEBUG_ASSERT_POINTER(device.secure_id_map);
+       DEBUG_ASSERT_POINTER(device.secure_id_map_lock);
+
+       _mali_osk_mutex_term(device.secure_id_map_lock);
+       device.secure_id_map_lock = NULL;
+
+       ump_descriptor_mapping_destroy(device.secure_id_map);
+       device.secure_id_map = NULL;
+
+       device.backend->shutdown(device.backend);
+       device.backend = NULL;
+
+       ump_memory_backend_destroy();
+
+       _ump_osk_term();
+}
+
+/** Creates a new UMP session
+ */
+_mali_osk_errcode_t _ump_ukk_open( void** context )
+{
+       struct ump_session_data * session_data;
+
+       /* allocated struct to track this session */
+       session_data = (struct ump_session_data *)_mali_osk_malloc(sizeof(struct ump_session_data));
+       if (NULL == session_data) {
+               MSG_ERR(("Failed to allocate ump_session_data in ump_file_open()\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       session_data->lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_UNORDERED, 0);
+       if( NULL == session_data->lock ) {
+               MSG_ERR(("Failed to initialize lock for ump_session_data in ump_file_open()\n"));
+               _mali_osk_free(session_data);
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       session_data->cookies_map = ump_descriptor_mapping_create( UMP_COOKIES_PER_SESSION_INITIAL, UMP_COOKIES_PER_SESSION_MAXIMUM );
+
+       if ( NULL == session_data->cookies_map ) {
+               MSG_ERR(("Failed to create descriptor mapping for _ump_ukk_map_mem cookies\n"));
+
+               _mali_osk_mutex_term(session_data->lock);
+               _mali_osk_free( session_data );
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_list);
+
+       _MALI_OSK_INIT_LIST_HEAD(&session_data->list_head_session_memory_mappings_list);
+
+       /* Since initial version of the UMP interface did not use the API_VERSION ioctl we have to assume
+          that it is this version, and not the "latest" one: UMP_IOCTL_API_VERSION
+          Current and later API versions would do an additional call to this IOCTL and update this variable
+          to the correct one.*/
+       session_data->api_version = MAKE_VERSION_ID(1);
+
+       *context = (void*)session_data;
+
+       session_data->cache_operations_ongoing = 0 ;
+       session_data->has_pending_level1_cache_flush = 0;
+
+       DBG_MSG(2, ("New session opened\n"));
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _ump_ukk_close( void** context )
+{
+       struct ump_session_data * session_data;
+       ump_session_memory_list_element * item;
+       ump_session_memory_list_element * tmp;
+
+       session_data = (struct ump_session_data *)*context;
+       if (NULL == session_data) {
+               MSG_ERR(("Session data is NULL in _ump_ukk_close()\n"));
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+
+       /* Unmap any descriptors mapped in. */
+       if (0 == _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list)) {
+               ump_memory_allocation *descriptor;
+               ump_memory_allocation *temp;
+
+               DBG_MSG(1, ("Memory mappings found on session usage list during session termination\n"));
+
+               /* use the 'safe' list iterator, since freeing removes the active block from the list we're iterating */
+               _MALI_OSK_LIST_FOREACHENTRY(descriptor, temp, &session_data->list_head_session_memory_mappings_list, ump_memory_allocation, list) {
+                       _ump_uk_unmap_mem_s unmap_args;
+                       DBG_MSG(4, ("Freeing block with phys address 0x%x size 0x%x mapped in user space at 0x%x\n",
+                                   descriptor->phys_addr, descriptor->size, descriptor->mapping));
+                       unmap_args.ctx = (void*)session_data;
+                       unmap_args.mapping = descriptor->mapping;
+                       unmap_args.size = descriptor->size;
+                       unmap_args._ukk_private = NULL; /* NOTE: unused */
+                       unmap_args.cookie = descriptor->cookie;
+
+                       /* NOTE: This modifies the list_head_session_memory_mappings_list */
+                       _ump_ukk_unmap_mem( &unmap_args );
+               }
+       }
+
+       /* ASSERT that we really did free everything, because _ump_ukk_unmap_mem()
+        * can fail silently. */
+       DEBUG_ASSERT( _mali_osk_list_empty(&session_data->list_head_session_memory_mappings_list) );
+
+       _MALI_OSK_LIST_FOREACHENTRY(item, tmp, &session_data->list_head_session_memory_list, ump_session_memory_list_element, list) {
+               _mali_osk_list_del(&item->list);
+               DBG_MSG(2, ("Releasing UMP memory %u as part of file close\n", item->mem->secure_id));
+               ump_dd_reference_release(item->mem);
+               _mali_osk_free(item);
+       }
+
+       ump_descriptor_mapping_destroy( session_data->cookies_map );
+
+       _mali_osk_mutex_term(session_data->lock);
+       _mali_osk_free(session_data);
+
+       DBG_MSG(2, ("Session closed\n"));
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args )
+{
+       struct ump_session_data * session_data;
+       ump_memory_allocation * descriptor;  /* Describes current mapping of memory */
+       _mali_osk_errcode_t err;
+       unsigned long offset = 0;
+       unsigned long left;
+       ump_dd_handle handle;  /* The real UMP handle for this memory. Its real datatype is ump_dd_mem*  */
+       ump_dd_mem * mem;      /* The real UMP memory. It is equal to the handle, but with exposed struct */
+       u32 block;
+       int map_id;
+
+       session_data = (ump_session_data *)args->ctx;
+       if( NULL == session_data ) {
+               MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
+               return _MALI_OSK_ERR_INVALID_ARGS;
+       }
+
+       descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation));
+       if (NULL == descriptor) {
+               MSG_ERR(("ump_ukk_map_mem: descriptor allocation failed\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       handle = ump_dd_handle_create_from_secure_id(args->secure_id);
+       if ( UMP_DD_HANDLE_INVALID == handle) {
+               _mali_osk_free(descriptor);
+               DBG_MSG(1, ("Trying to map unknown secure ID %u\n", args->secure_id));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       mem = (ump_dd_mem*)handle;
+       DEBUG_ASSERT(mem);
+       if (mem->size_bytes != args->size) {
+               _mali_osk_free(descriptor);
+               ump_dd_reference_release(handle);
+               DBG_MSG(1, ("Trying to map too much or little. ID: %u, virtual size=%lu, UMP size: %lu\n", args->secure_id, args->size, mem->size_bytes));
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       map_id = ump_descriptor_mapping_allocate_mapping( session_data->cookies_map, (void*) descriptor );
+
+       if (map_id < 0) {
+               _mali_osk_free(descriptor);
+               ump_dd_reference_release(handle);
+               DBG_MSG(1, ("ump_ukk_map_mem: unable to allocate a descriptor_mapping for return cookie\n"));
+
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       descriptor->size = args->size;
+       descriptor->handle = handle;
+       descriptor->phys_addr = args->phys_addr;
+       descriptor->process_mapping_info = args->_ukk_private;
+       descriptor->ump_session = session_data;
+       descriptor->cookie = (u32)map_id;
+
+       if ( mem->is_cached ) {
+               descriptor->is_cached = 1;
+               args->is_cached       = 1;
+               DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id));
+       } else {
+               descriptor->is_cached = 0;
+               args->is_cached       = 0;
+               DBG_MSG(3, ("Mapping UMP secure_id: %d  as Uncached.\n", args->secure_id));
+       }
+
+       _mali_osk_list_init( &descriptor->list );
+
+       err = _ump_osk_mem_mapregion_init( descriptor );
+       if( _MALI_OSK_ERR_OK != err ) {
+               DBG_MSG(1, ("Failed to initialize memory mapping in _ump_ukk_map_mem(). ID: %u\n", args->secure_id));
+               ump_descriptor_mapping_free( session_data->cookies_map, map_id );
+               _mali_osk_free(descriptor);
+               ump_dd_reference_release(mem);
+               return err;
+       }
+
+       DBG_MSG(4, ("Mapping virtual to physical memory: ID: %u, size:%lu, first physical addr: 0x%08lx, number of regions: %lu\n",
+                   mem->secure_id,
+                   mem->size_bytes,
+                   ((NULL != mem->block_array) ? mem->block_array->addr : 0),
+                   mem->nr_blocks));
+
+       left = descriptor->size;
+       /* loop over all blocks and map them in */
+       for (block = 0; block < mem->nr_blocks; block++) {
+               unsigned long size_to_map;
+
+               if (left >  mem->block_array[block].size) {
+                       size_to_map = mem->block_array[block].size;
+               } else {
+                       size_to_map = left;
+               }
+
+               if (_MALI_OSK_ERR_OK != _ump_osk_mem_mapregion_map(descriptor, offset, (u32 *)&(mem->block_array[block].addr), size_to_map ) ) {
+                       DBG_MSG(1, ("WARNING: _ump_ukk_map_mem failed to map memory into userspace\n"));
+                       ump_descriptor_mapping_free( session_data->cookies_map, map_id );
+                       ump_dd_reference_release(mem);
+                       _ump_osk_mem_mapregion_term( descriptor );
+                       _mali_osk_free(descriptor);
+                       return _MALI_OSK_ERR_FAULT;
+               }
+               left -= size_to_map;
+               offset += size_to_map;
+       }
+
+       /* Add to the ump_memory_allocation tracking list */
+       _mali_osk_mutex_wait(session_data->lock);
+       _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list );
+       _mali_osk_mutex_signal(session_data->lock);
+
+       args->mapping = descriptor->mapping;
+       args->cookie = descriptor->cookie;
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args )
+{
+       struct ump_session_data * session_data;
+       ump_memory_allocation * descriptor;
+       ump_dd_handle handle;
+
+       session_data = (ump_session_data *)args->ctx;
+
+       if( NULL == session_data ) {
+               MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
+               return;
+       }
+
+       if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) {
+               MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie ));
+               return;
+       }
+
+       DEBUG_ASSERT_POINTER(descriptor);
+
+       handle = descriptor->handle;
+       if ( UMP_DD_HANDLE_INVALID == handle) {
+               DBG_MSG(1, ("WARNING: Trying to unmap unknown handle: UNKNOWN\n"));
+               return;
+       }
+
+       /* Remove the ump_memory_allocation from the list of tracked mappings */
+       _mali_osk_mutex_wait(session_data->lock);
+       _mali_osk_list_del( &descriptor->list );
+       _mali_osk_mutex_signal(session_data->lock);
+
+       ump_descriptor_mapping_free( session_data->cookies_map, (int)args->cookie );
+
+       ump_dd_reference_release(handle);
+
+       _ump_osk_mem_mapregion_term( descriptor );
+       _mali_osk_free(descriptor);
+}
+
+u32 _ump_ukk_report_memory_usage( void )
+{
+       if(device.backend->stat)
+               return device.backend->stat(device.backend);
+       else
+               return 0;
+}
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_common.h b/drivers/gpu/arm/mali400/ump/common/ump_kernel_common.h
new file mode 100755 (executable)
index 0000000..59aee9e
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __UMP_KERNEL_COMMON_H__
+#define __UMP_KERNEL_COMMON_H__
+
+#include "ump_kernel_types.h"
+#include "ump_kernel_interface.h"
+#include "ump_kernel_descriptor_mapping.h"
+#include "ump_kernel_memory_backend.h"
+
+
+#ifdef DEBUG
+extern int ump_debug_level;
+#define UMP_DEBUG_PRINT(args) _mali_osk_dbgmsg args
+#define UMP_DEBUG_CODE(args) args
+#define DBG_MSG(level,args)  do { /* args should be in brackets */ \
+               ((level) <=  ump_debug_level)?\
+               UMP_DEBUG_PRINT(("UMP<" #level ">: ")), \
+               UMP_DEBUG_PRINT(args):0; \
+               } while (0)
+
+#define DBG_MSG_IF(level,condition,args) /* args should be in brackets */ \
+               if((condition)&&((level) <=  ump_debug_level)) {\
+               UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \
+               UMP_DEBUG_PRINT(args); \
+               }
+
+#define DBG_MSG_ELSE(level,args) /* args should be in brackets */ \
+               else if((level) <=  ump_debug_level) { \
+               UMP_DEBUG_PRINT(("UMP<" #level ">: ")); \
+               UMP_DEBUG_PRINT(args); \
+               }
+
+#define DEBUG_ASSERT_POINTER(pointer) do  {if( (pointer)== NULL) MSG_ERR(("NULL pointer " #pointer)); } while(0)
+#define DEBUG_ASSERT(condition) do  {if(!(condition)) MSG_ERR(("ASSERT failed: " #condition)); } while(0)
+#else /* DEBUG */
+#define UMP_DEBUG_PRINT(args) do {} while(0)
+#define UMP_DEBUG_CODE(args)
+#define DBG_MSG(level,args) do {} while(0)
+#define DBG_MSG_IF(level,condition,args) do {} while(0)
+#define DBG_MSG_ELSE(level,args) do {} while(0)
+#define DEBUG_ASSERT(condition) do {} while(0)
+#define DEBUG_ASSERT_POINTER(pointer) do  {} while(0)
+#endif /* DEBUG */
+
+#define MSG_ERR(args) do{ /* args should be in brackets */ \
+        _mali_osk_dbgmsg("UMP: ERR: %s\n" ,__FILE__); \
+        _mali_osk_dbgmsg( "           %s()%4d\n", __FUNCTION__, __LINE__) ; \
+        _mali_osk_dbgmsg args ; \
+        _mali_osk_dbgmsg("\n"); \
+       } while(0)
+
+#define MSG(args) do{ /* args should be in brackets */ \
+                _mali_osk_dbgmsg("UMP: "); \
+                _mali_osk_dbgmsg args; \
+               } while (0)
+
+
+
+/*
+ * This struct is used to store per session data.
+ * A session is created when someone open() the device, and
+ * closed when someone close() it or the user space application terminates.
+ */
+typedef struct ump_session_data {
+       _mali_osk_list_t list_head_session_memory_list;  /**< List of ump allocations made by the process (elements are ump_session_memory_list_element) */
+       _mali_osk_list_t list_head_session_memory_mappings_list; /**< List of ump_memory_allocations mapped in */
+       int api_version;
+       _mali_osk_mutex_t *lock;
+       ump_descriptor_mapping * cookies_map; /**< Secure mapping of cookies from _ump_ukk_map_mem() */
+       int cache_operations_ongoing;
+       int has_pending_level1_cache_flush;
+} ump_session_data;
+
+
+
+/*
+ * This struct is used to track the UMP memory references a session has.
+ * We need to track this in order to be able to clean up after user space processes
+ * which don't do it themself (e.g. due to a crash or premature termination).
+ */
+typedef struct ump_session_memory_list_element {
+       struct ump_dd_mem * mem;
+       _mali_osk_list_t list;
+} ump_session_memory_list_element;
+
+
+
+/*
+ * Device specific data, created when device driver is loaded, and then kept as the global variable device.
+ */
+typedef struct ump_dev {
+       _mali_osk_mutex_t *secure_id_map_lock;
+       ump_descriptor_mapping * secure_id_map;
+       ump_memory_backend * backend;
+} ump_dev;
+
+
+
+extern int ump_debug_level;
+extern struct ump_dev device;
+
+_mali_osk_errcode_t ump_kernel_constructor(void);
+void ump_kernel_destructor(void);
+int map_errcode( _mali_osk_errcode_t err );
+
+/**
+ * variables from user space cannot be dereferenced from kernel space; tagging them
+ * with __user allows the GCC compiler to generate a warning. Other compilers may
+ * not support this so we define it here as an empty macro if the compiler doesn't
+ * define it.
+ */
+#ifndef __user
+#define __user
+#endif
+
+#endif /* __UMP_KERNEL_COMMON_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_descriptor_mapping.c b/drivers/gpu/arm/mali400/ump/common/ump_kernel_descriptor_mapping.c
new file mode 100755 (executable)
index 0000000..8863ff7
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_bitops.h"
+#include "ump_kernel_common.h"
+#include "ump_kernel_descriptor_mapping.h"
+
+#define MALI_PAD_INT(x) (((x) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1))
+
+/**
+ * Allocate a descriptor table capable of holding 'count' mappings
+ * @param count Number of mappings in the table
+ * @return Pointer to a new table, NULL on error
+ */
+static ump_descriptor_table * descriptor_table_alloc(int count);
+
+/**
+ * Free a descriptor table
+ * @param table The table to free
+ */
+static void descriptor_table_free(ump_descriptor_table * table);
+
+ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries)
+{
+       ump_descriptor_mapping * map = _mali_osk_calloc(1, sizeof(ump_descriptor_mapping) );
+
+       init_entries = MALI_PAD_INT(init_entries);
+       max_entries = MALI_PAD_INT(max_entries);
+
+       if (NULL != map) {
+               map->table = descriptor_table_alloc(init_entries);
+               if (NULL != map->table) {
+                       map->lock = _mali_osk_mutex_rw_init(_MALI_OSK_LOCKFLAG_UNORDERED, 0);
+                       if ( NULL != map->lock ) {
+                               _mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
+                               map->max_nr_mappings_allowed = max_entries;
+                               map->current_nr_mappings = init_entries;
+                               return map;
+                       }
+                       descriptor_table_free(map->table);
+               }
+               _mali_osk_free(map);
+       }
+       return NULL;
+}
+
+void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map)
+{
+       descriptor_table_free(map->table);
+       _mali_osk_mutex_rw_term(map->lock);
+       _mali_osk_free(map);
+}
+
+int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target)
+{
+       int descriptor = -1;/*-EFAULT;*/
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
+       descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings);
+       if (descriptor == map->current_nr_mappings) {
+               int nr_mappings_new;
+               /* no free descriptor, try to expand the table */
+               ump_descriptor_table * new_table;
+               ump_descriptor_table * old_table = map->table;
+               nr_mappings_new= map->current_nr_mappings *2;
+
+               if (map->current_nr_mappings >= map->max_nr_mappings_allowed) {
+                       descriptor = -1;
+                       goto unlock_and_exit;
+               }
+
+               new_table = descriptor_table_alloc(nr_mappings_new);
+               if (NULL == new_table) {
+                       descriptor = -1;
+                       goto unlock_and_exit;
+               }
+
+               _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG);
+               _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*));
+               map->table = new_table;
+               map->current_nr_mappings = nr_mappings_new;
+               descriptor_table_free(old_table);
+       }
+
+       /* we have found a valid descriptor, set the value and usage bit */
+       _mali_osk_set_nonatomic_bit(descriptor, map->table->usage);
+       map->table->mappings[descriptor] = target;
+
+unlock_and_exit:
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+       return descriptor;
+}
+
+int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target)
+{
+       int result = -1;/*-EFAULT;*/
+       DEBUG_ASSERT(map);
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
+       if ((descriptor > 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
+               *target = map->table->mappings[descriptor];
+               result = 0;
+       } else *target = NULL;
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+       return result;
+}
+
+int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target)
+{
+       int result = -1;/*-EFAULT;*/
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RO);
+       if ((descriptor > 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
+               map->table->mappings[descriptor] = target;
+               result = 0;
+       }
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+       return result;
+}
+
+void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor)
+{
+       _mali_osk_mutex_rw_wait(map->lock, _MALI_OSK_LOCKMODE_RW);
+       if ((descriptor > 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage)) {
+               map->table->mappings[descriptor] = NULL;
+               _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
+       }
+       _mali_osk_mutex_rw_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+static ump_descriptor_table * descriptor_table_alloc(int count)
+{
+       ump_descriptor_table * table;
+
+       table = _mali_osk_calloc(1, sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG) + (sizeof(void*) * count) );
+
+       if (NULL != table) {
+               table->usage = (u32*)((u8*)table + sizeof(ump_descriptor_table));
+               table->mappings = (void**)((u8*)table + sizeof(ump_descriptor_table) + ((sizeof(unsigned long) * count)/BITS_PER_LONG));
+       }
+
+       return table;
+}
+
+static void descriptor_table_free(ump_descriptor_table * table)
+{
+       _mali_osk_free(table);
+}
+
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_descriptor_mapping.h b/drivers/gpu/arm/mali400/ump/common/ump_kernel_descriptor_mapping.h
new file mode 100755 (executable)
index 0000000..234c6fc
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_descriptor_mapping.h
+ */
+
+#ifndef __UMP_KERNEL_DESCRIPTOR_MAPPING_H__
+#define __UMP_KERNEL_DESCRIPTOR_MAPPING_H__
+
+#include "mali_osk.h"
+
+/**
+ * The actual descriptor mapping table, never directly accessed by clients
+ */
+typedef struct ump_descriptor_table {
+       u32 * usage; /**< Pointer to bitpattern indicating if a descriptor is valid/used or not */
+       void** mappings; /**< Array of the pointers the descriptors map to */
+} ump_descriptor_table;
+
+/**
+ * The descriptor mapping object
+ * Provides a separate namespace where we can map an integer to a pointer
+ */
+typedef struct ump_descriptor_mapping {
+       _mali_osk_mutex_rw_t *lock; /**< Lock protecting access to the mapping object */
+       int max_nr_mappings_allowed; /**< Max number of mappings to support in this namespace */
+       int current_nr_mappings; /**< Current number of possible mappings */
+       ump_descriptor_table * table; /**< Pointer to the current mapping table */
+} ump_descriptor_mapping;
+
+/**
+ * Create a descriptor mapping object
+ * Create a descriptor mapping capable of holding init_entries growable to max_entries
+ * @param init_entries Number of entries to preallocate memory for
+ * @param max_entries Number of entries to max support
+ * @return Pointer to a descriptor mapping object, NULL on failure
+ */
+ump_descriptor_mapping * ump_descriptor_mapping_create(int init_entries, int max_entries);
+
+/**
+ * Destroy a descriptor mapping object
+ * @param map The map to free
+ */
+void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map);
+
+/**
+ * Allocate a new mapping entry (descriptor ID)
+ * Allocates a new entry in the map.
+ * @param map The map to allocate a new entry in
+ * @param target The value to map to
+ * @return The descriptor allocated, a negative value on error
+ */
+int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target);
+
+/**
+ * Get the value mapped to by a descriptor ID
+ * @param map The map to lookup the descriptor id in
+ * @param descriptor The descriptor ID to lookup
+ * @param target Pointer to a pointer which will receive the stored value
+ * @return 0 on successful lookup, negative on error
+ */
+int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target);
+
+/**
+ * Set the value mapped to by a descriptor ID
+ * @param map The map to lookup the descriptor id in
+ * @param descriptor The descriptor ID to lookup
+ * @param target Pointer to replace the current value with
+ * @return 0 on successful lookup, negative on error
+ */
+int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target);
+
+/**
+ * Free the descriptor ID
+ * For the descriptor to be reused it has to be freed
+ * @param map The map to free the descriptor from
+ * @param descriptor The descriptor ID to free
+ */
+void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor);
+
+#endif /* __UMP_KERNEL_DESCRIPTOR_MAPPING_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_memory_backend.h b/drivers/gpu/arm/mali400/ump/common/ump_kernel_memory_backend.h
new file mode 100755 (executable)
index 0000000..ad35b6f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_memory_mapping.h
+ */
+
+#ifndef __UMP_KERNEL_MEMORY_BACKEND_H__
+#define __UMP_KERNEL_MEMORY_BACKEND_H__
+
+#include "ump_kernel_interface.h"
+#include "ump_kernel_types.h"
+
+
+typedef struct ump_memory_allocation {
+       void                    * phys_addr;
+       void                    * mapping;
+       unsigned long             size;
+       ump_dd_handle             handle;
+       void                    * process_mapping_info;
+       u32                       cookie;               /**< necessary on some U/K interface implementations */
+       struct ump_session_data * ump_session;          /**< Session that this allocation belongs to */
+       _mali_osk_list_t          list;                 /**< List for linking together memory allocations into the session's memory head */
+       u32 is_cached;
+} ump_memory_allocation;
+
+typedef struct ump_memory_backend {
+       int  (*allocate)(void* ctx, ump_dd_mem * descriptor);
+       void (*release)(void* ctx, ump_dd_mem * descriptor);
+       void (*shutdown)(struct ump_memory_backend * backend);
+       u32  (*stat)(struct ump_memory_backend *backend);
+       int  (*pre_allocate_physical_check)(void *ctx, u32 size);
+       u32  (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys);
+       void * ctx;
+} ump_memory_backend;
+
+ump_memory_backend * ump_memory_backend_create ( void );
+void ump_memory_backend_destroy( void );
+
+#endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */
+
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_ref_drv.c b/drivers/gpu/arm/mali400/ump/common/ump_kernel_ref_drv.c
new file mode 100755 (executable)
index 0000000..30e04e8
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "ump_osk.h"
+#include "ump_uk_types.h"
+
+#include "ump_kernel_interface_ref_drv.h"
+#include "ump_kernel_common.h"
+#include "ump_kernel_descriptor_mapping.h"
+
+#define UMP_MINIMUM_SIZE         4096
+#define UMP_MINIMUM_SIZE_MASK    (~(UMP_MINIMUM_SIZE-1))
+#define UMP_SIZE_ALIGN(x)        (((x)+UMP_MINIMUM_SIZE-1)&UMP_MINIMUM_SIZE_MASK)
+#define UMP_ADDR_ALIGN_OFFSET(x) ((x)&(UMP_MINIMUM_SIZE-1))
+static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor);
+
+UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks)
+{
+       ump_dd_mem * mem;
+       unsigned long size_total = 0;
+       int map_id;
+       u32 i;
+
+       /* Go through the input blocks and verify that they are sane */
+       for (i=0; i < num_blocks; i++) {
+               unsigned long addr = blocks[i].addr;
+               unsigned long size = blocks[i].size;
+
+               DBG_MSG(5, ("Adding physical memory to new handle. Address: 0x%08lx, size: %lu\n", addr, size));
+               size_total += blocks[i].size;
+
+               if (0 != UMP_ADDR_ALIGN_OFFSET(addr)) {
+                       MSG_ERR(("Trying to create UMP memory from unaligned physical address. Address: 0x%08lx\n", addr));
+                       return UMP_DD_HANDLE_INVALID;
+               }
+
+               if (0 != UMP_ADDR_ALIGN_OFFSET(size)) {
+                       MSG_ERR(("Trying to create UMP memory with unaligned size. Size: %lu\n", size));
+                       return UMP_DD_HANDLE_INVALID;
+               }
+       }
+
+       /* Allocate the ump_dd_mem struct for this allocation */
+       mem = _mali_osk_malloc(sizeof(*mem));
+       if (NULL == mem) {
+               DBG_MSG(1, ("Could not allocate ump_dd_mem in ump_dd_handle_create_from_phys_blocks()\n"));
+               return UMP_DD_HANDLE_INVALID;
+       }
+
+       /* Find a secure ID for this allocation */
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*) mem);
+
+       if (map_id < 0) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               _mali_osk_free(mem);
+               DBG_MSG(1, ("Failed to allocate secure ID in ump_dd_handle_create_from_phys_blocks()\n"));
+               return UMP_DD_HANDLE_INVALID;
+       }
+
+       /* Now, make a copy of the block information supplied by the user */
+       mem->block_array = _mali_osk_malloc(sizeof(ump_dd_physical_block)* num_blocks);
+       if (NULL == mem->block_array) {
+               ump_descriptor_mapping_free(device.secure_id_map, map_id);
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               _mali_osk_free(mem);
+               DBG_MSG(1, ("Could not allocate a mem handle for function ump_dd_handle_create_from_phys_blocks().\n"));
+               return UMP_DD_HANDLE_INVALID;
+       }
+
+       _mali_osk_memcpy(mem->block_array, blocks, sizeof(ump_dd_physical_block) * num_blocks);
+
+       /* And setup the rest of the ump_dd_mem struct */
+       _mali_osk_atomic_init(&mem->ref_count, 1);
+       mem->secure_id = (ump_secure_id)map_id;
+       mem->size_bytes = size_total;
+       mem->nr_blocks = num_blocks;
+       mem->backend_info = NULL;
+       mem->ctx = NULL;
+       mem->release_func = phys_blocks_release;
+       /* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */
+       mem->is_cached = 0;
+       mem->hw_device = _UMP_UK_USED_BY_CPU;
+       mem->lock_usage = UMP_NOT_LOCKED;
+
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+       DBG_MSG(3, ("UMP memory created. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes));
+
+       return (ump_dd_handle)mem;
+}
+
+static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor)
+{
+       _mali_osk_free(descriptor->block_array);
+       descriptor->block_array = NULL;
+}
+
+_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction )
+{
+       ump_session_data * session_data = NULL;
+       ump_dd_mem *new_allocation = NULL;
+       ump_session_memory_list_element * session_memory_element = NULL;
+       int map_id;
+
+       DEBUG_ASSERT_POINTER( user_interaction );
+       DEBUG_ASSERT_POINTER( user_interaction->ctx );
+
+       session_data = (ump_session_data *) user_interaction->ctx;
+
+       session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element));
+       if (NULL == session_memory_element) {
+               DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+
+       new_allocation = _mali_osk_calloc( 1, sizeof(ump_dd_mem));
+       if (NULL==new_allocation) {
+               _mali_osk_free(session_memory_element);
+               DBG_MSG(1, ("Failed to allocate ump_dd_mem in _ump_ukk_allocate()\n"));
+               return _MALI_OSK_ERR_NOMEM;
+       }
+
+       /* Create a secure ID for this allocation */
+       _mali_osk_mutex_wait(device.secure_id_map_lock);
+       map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*)new_allocation);
+
+       if (map_id < 0) {
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               _mali_osk_free(session_memory_element);
+               _mali_osk_free(new_allocation);
+               DBG_MSG(1, ("Failed to allocate secure ID in ump_ioctl_allocate()\n"));
+               return - _MALI_OSK_ERR_INVALID_FUNC;
+       }
+
+       /* Initialize the part of the new_allocation that we know so for */
+       new_allocation->secure_id = (ump_secure_id)map_id;
+       _mali_osk_atomic_init(&new_allocation->ref_count,1);
+       if ( 0==(UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE & user_interaction->constraints) )
+               new_allocation->is_cached = 0;
+       else new_allocation->is_cached = 1;
+
+       /* special case a size of 0, we should try to emulate what malloc does in this case, which is to return a valid pointer that must be freed, but can't be dereferences */
+       if (0 == user_interaction->size) {
+               user_interaction->size = 1; /* emulate by actually allocating the minimum block size */
+       }
+
+       new_allocation->size_bytes = UMP_SIZE_ALIGN(user_interaction->size); /* Page align the size */
+       new_allocation->lock_usage = UMP_NOT_LOCKED;
+
+       /* Now, ask the active memory backend to do the actual memory allocation */
+       if (!device.backend->allocate( device.backend->ctx, new_allocation ) ) {
+               DBG_MSG(3, ("OOM: No more UMP memory left. Failed to allocate memory in ump_ioctl_allocate(). Size: %lu, requested size: %lu\n", new_allocation->size_bytes, (unsigned long)user_interaction->size));
+               ump_descriptor_mapping_free(device.secure_id_map, map_id);
+               _mali_osk_mutex_signal(device.secure_id_map_lock);
+               _mali_osk_free(new_allocation);
+               _mali_osk_free(session_memory_element);
+               return _MALI_OSK_ERR_INVALID_FUNC;
+       }
+       new_allocation->hw_device = _UMP_UK_USED_BY_CPU;
+       new_allocation->ctx = device.backend->ctx;
+       new_allocation->release_func = device.backend->release;
+
+       _mali_osk_mutex_signal(device.secure_id_map_lock);
+
+       /* Initialize the session_memory_element, and add it to the session object */
+       session_memory_element->mem = new_allocation;
+       _mali_osk_mutex_wait(session_data->lock);
+       _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list));
+       _mali_osk_mutex_signal(session_data->lock);
+
+       user_interaction->secure_id = new_allocation->secure_id;
+       user_interaction->size = new_allocation->size_bytes;
+       DBG_MSG(3, ("UMP memory allocated. ID: %u, size: %lu\n", new_allocation->secure_id, new_allocation->size_bytes));
+
+       return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_kernel_types.h b/drivers/gpu/arm/mali400/ump/common/ump_kernel_types.h
new file mode 100755 (executable)
index 0000000..115c06e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __UMP_KERNEL_TYPES_H__
+#define __UMP_KERNEL_TYPES_H__
+
+#include "ump_kernel_interface.h"
+#include "mali_osk.h"
+
+
+typedef enum {
+       UMP_USED_BY_CPU = 0,
+       UMP_USED_BY_MALI = 1,
+       UMP_USED_BY_UNKNOWN_DEVICE= 100,
+} ump_hw_usage;
+
+typedef enum {
+       UMP_NOT_LOCKED = 0,
+       UMP_READ = 1,
+       UMP_READ_WRITE = 3,
+} ump_lock_usage;
+
+
+/*
+ * This struct is what is "behind" a ump_dd_handle
+ */
+typedef struct ump_dd_mem {
+       ump_secure_id secure_id;
+       _mali_osk_atomic_t ref_count;
+       unsigned long size_bytes;
+       unsigned long nr_blocks;
+       ump_dd_physical_block * block_array;
+       void (*release_func)(void * ctx, struct ump_dd_mem * descriptor);
+       void * ctx;
+       void * backend_info;
+       int is_cached;
+       ump_hw_usage hw_device;
+       ump_lock_usage lock_usage;
+} ump_dd_mem;
+
+
+
+#endif /* __UMP_KERNEL_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_osk.h b/drivers/gpu/arm/mali400/ump/common/ump_osk.h
new file mode 100755 (executable)
index 0000000..a146c5b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_osk.h
+ * Defines the OS abstraction layer for the UMP kernel device driver (OSK)
+ */
+
+#ifndef __UMP_OSK_H__
+#define __UMP_OSK_H__
+
+#include <mali_osk.h>
+#include <ump_kernel_memory_backend.h>
+#include "ump_uk_types.h"
+#include "ump_kernel_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_mali_osk_errcode_t _ump_osk_init( void );
+
+_mali_osk_errcode_t _ump_osk_term( void );
+
+int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom );
+
+int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom );
+
+_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation *descriptor );
+
+_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size );
+
+void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor );
+
+void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/arm/mali400/ump/common/ump_ukk.h b/drivers/gpu/arm/mali400/ump/common/ump_ukk.h
new file mode 100755 (executable)
index 0000000..fbc02be
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ukk.h
+ * Defines the kernel-side interface of the user-kernel interface
+ */
+
+#ifndef __UMP_UKK_H__
+#define __UMP_UKK_H__
+
+#include "mali_osk.h"
+#include "ump_uk_types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+_mali_osk_errcode_t _ump_ukk_open( void** context );
+
+_mali_osk_errcode_t _ump_ukk_close( void** context );
+
+_mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction );
+
+_mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info );
+
+_mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction );
+
+_mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args );
+
+_mali_osk_errcode_t _ump_uku_get_api_version( _ump_uk_api_version_s *args );
+
+void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args );
+
+void _ump_ukk_msync( _ump_uk_msync_s *args );
+
+void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args);
+
+void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args );
+
+void _ump_ukk_lock(_ump_uk_lock_s *args );
+
+void _ump_ukk_unlock(_ump_uk_unlock_s *args );
+
+u32 _ump_ukk_report_memory_usage( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_UKK_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/linux/license/gpl/ump_kernel_license.h b/drivers/gpu/arm/mali400/ump/linux/license/gpl/ump_kernel_license.h
new file mode 100755 (executable)
index 0000000..98953d1
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2012 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_license.h
+ * Defines for the macro MODULE_LICENSE.
+ */
+
+#ifndef __UMP_KERNEL_LICENSE_H__
+#define __UMP_KERNEL_LICENSE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define UMP_KERNEL_LINUX_LICENSE     "GPL"
+#define UMP_LICENSE_IS_GPL 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_KERNEL_LICENSE_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h b/drivers/gpu/arm/mali400/ump/linux/license/proprietary/ump_kernel_license.h
new file mode 100755 (executable)
index 0000000..93ac808
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2010-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_license.h
+ * Defines for the macro MODULE_LICENSE.
+ */
+
+#ifndef __UMP_KERNEL_LICENSE_H__
+#define __UMP_KERNEL_LICENSE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UMP_KERNEL_LINUX_LICENSE     "Proprietary"
+#define UMP_LICENSE_IS_GPL 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_KERNEL_LICENSE_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_ioctl.h b/drivers/gpu/arm/mali400/ump/linux/ump_ioctl.h
new file mode 100755 (executable)
index 0000000..326ff27
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __UMP_IOCTL_H__
+#define __UMP_IOCTL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include <ump_uk_types.h>
+
+#ifndef __user
+#define __user
+#endif
+
+
+/**
+ * @file UMP_ioctl.h
+ * This file describes the interface needed to use the Linux device driver.
+ * The interface is used by the userpace UMP driver.
+ */
+
+#define UMP_IOCTL_NR 0x90
+
+
+#define UMP_IOC_QUERY_API_VERSION _IOR(UMP_IOCTL_NR, _UMP_IOC_QUERY_API_VERSION, _ump_uk_api_version_s)
+#define UMP_IOC_ALLOCATE  _IOWR(UMP_IOCTL_NR,  _UMP_IOC_ALLOCATE,  _ump_uk_allocate_s)
+#define UMP_IOC_RELEASE  _IOR(UMP_IOCTL_NR,  _UMP_IOC_RELEASE,  _ump_uk_release_s)
+#define UMP_IOC_SIZE_GET  _IOWR(UMP_IOCTL_NR,  _UMP_IOC_SIZE_GET, _ump_uk_size_get_s)
+#define UMP_IOC_MSYNC     _IOW(UMP_IOCTL_NR,  _UMP_IOC_MSYNC, _ump_uk_msync_s)
+
+#define UMP_IOC_CACHE_OPERATIONS_CONTROL _IOW(UMP_IOCTL_NR,  _UMP_IOC_CACHE_OPERATIONS_CONTROL, _ump_uk_cache_operations_control_s)
+#define UMP_IOC_SWITCH_HW_USAGE   _IOW(UMP_IOCTL_NR,  _UMP_IOC_SWITCH_HW_USAGE, _ump_uk_switch_hw_usage_s)
+#define UMP_IOC_LOCK          _IOW(UMP_IOCTL_NR,  _UMP_IOC_LOCK, _ump_uk_lock_s)
+#define UMP_IOC_UNLOCK        _IOW(UMP_IOCTL_NR,  _UMP_IOC_UNLOCK, _ump_uk_unlock_s)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_IOCTL_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_kernel_linux.c b/drivers/gpu/arm/mali400/ump/linux/ump_kernel_linux.c
new file mode 100755 (executable)
index 0000000..8d15ecd
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include <linux/module.h>            /* kernel module definitions */
+#include <linux/fs.h>                /* file system operations */
+#include <linux/cdev.h>              /* character device definitions */
+#include <linux/ioport.h>            /* request_mem_region */
+#include <linux/mm.h>                /* memory management functions and types */
+#include <asm/uaccess.h>             /* user space access */
+#include <asm/atomic.h>
+#include <linux/device.h>
+#include <linux/debugfs.h>
+
+#include "arch/config.h"             /* Configuration for current platform. The symlinc for arch is set by Makefile */
+#include "ump_ioctl.h"
+#include "ump_kernel_common.h"
+#include "ump_kernel_interface.h"
+#include "ump_kernel_interface_ref_drv.h"
+#include "ump_kernel_descriptor_mapping.h"
+#include "ump_kernel_memory_backend.h"
+#include "ump_kernel_memory_backend_os.h"
+#include "ump_kernel_memory_backend_dedicated.h"
+#include "ump_kernel_license.h"
+
+#include "ump_osk.h"
+#include "ump_ukk.h"
+#include "ump_uk_types.h"
+#include "ump_ukk_wrappers.h"
+#include "ump_ukk_ref_wrappers.h"
+
+
+/* Module parameter to control log level */
+int ump_debug_level = 2;
+module_param(ump_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
+MODULE_PARM_DESC(ump_debug_level, "Higher number, more dmesg output");
+
+/* By default the module uses any available major, but it's possible to set it at load time to a specific number */
+int ump_major = 0;
+module_param(ump_major, int, S_IRUGO); /* r--r--r-- */
+MODULE_PARM_DESC(ump_major, "Device major number");
+
+/* Name of the UMP device driver */
+static char ump_dev_name[] = "ump"; /* should be const, but the functions we call requires non-cost */
+
+
+#if UMP_LICENSE_IS_GPL
+static struct dentry *ump_debugfs_dir = NULL;
+#endif
+
+/*
+ * The data which we attached to each virtual memory mapping request we get.
+ * Each memory mapping has a reference to the UMP memory it maps.
+ * We release this reference when the last memory mapping is unmapped.
+ */
+typedef struct ump_vma_usage_tracker {
+       int references;
+       ump_dd_handle handle;
+} ump_vma_usage_tracker;
+
+struct ump_device {
+       struct cdev cdev;
+#if UMP_LICENSE_IS_GPL
+       struct class * ump_class;
+#endif
+};
+
+/* The global variable containing the global device data */
+static struct ump_device ump_device;
+
+
+/* Forward declare static functions */
+static int ump_file_open(struct inode *inode, struct file *filp);
+static int ump_file_release(struct inode *inode, struct file *filp);
+#ifdef HAVE_UNLOCKED_IOCTL
+static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+#else
+static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+#endif
+static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma);
+
+
+/* This variable defines the file operations this UMP device driver offer */
+static struct file_operations ump_fops = {
+       .owner   = THIS_MODULE,
+       .open    = ump_file_open,
+       .release = ump_file_release,
+#ifdef HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl   = ump_file_ioctl,
+#else
+       .ioctl   = ump_file_ioctl,
+#endif
+       .mmap    = ump_file_mmap
+};
+
+
+/* This function is called by Linux to initialize this module.
+ * All we do is initialize the UMP device driver.
+ */
+static int ump_initialize_module(void)
+{
+       _mali_osk_errcode_t err;
+
+       DBG_MSG(2, ("Inserting UMP device driver. Compiled: %s, time: %s\n", __DATE__, __TIME__));
+
+       err = ump_kernel_constructor();
+       if (_MALI_OSK_ERR_OK != err) {
+               MSG_ERR(("UMP device driver init failed\n"));
+               return map_errcode(err);
+       }
+
+       MSG(("UMP device driver %s loaded\n", SVN_REV_STRING));
+       return 0;
+}
+
+
+
+/*
+ * This function is called by Linux to unload/terminate/exit/cleanup this module.
+ * All we do is terminate the UMP device driver.
+ */
+static void ump_cleanup_module(void)
+{
+       DBG_MSG(2, ("Unloading UMP device driver\n"));
+       ump_kernel_destructor();
+       DBG_MSG(2, ("Module unloaded\n"));
+}
+
+
+
+static ssize_t ump_memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       size_t r;
+       u32 mem = _ump_ukk_report_memory_usage();
+
+       r = snprintf(buf, 64, "%u\n", mem);
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static const struct file_operations ump_memory_usage_fops = {
+       .owner = THIS_MODULE,
+       .read = ump_memory_used_read,
+};
+
+/*
+ * Initialize the UMP device driver.
+ */
+int ump_kernel_device_initialize(void)
+{
+       int err;
+       dev_t dev = 0;
+#if UMP_LICENSE_IS_GPL
+       ump_debugfs_dir = debugfs_create_dir(ump_dev_name, NULL);
+       if (ERR_PTR(-ENODEV) == ump_debugfs_dir) {
+               ump_debugfs_dir = NULL;
+       } else {
+               debugfs_create_file("memory_usage", 0400, ump_debugfs_dir, NULL, &ump_memory_usage_fops);
+       }
+#endif
+
+       if (0 == ump_major) {
+               /* auto select a major */
+               err = alloc_chrdev_region(&dev, 0, 1, ump_dev_name);
+               ump_major = MAJOR(dev);
+       } else {
+               /* use load time defined major number */
+               dev = MKDEV(ump_major, 0);
+               err = register_chrdev_region(dev, 1, ump_dev_name);
+       }
+
+       if (0 == err) {
+               memset(&ump_device, 0, sizeof(ump_device));
+
+               /* initialize our char dev data */
+               cdev_init(&ump_device.cdev, &ump_fops);
+               ump_device.cdev.owner = THIS_MODULE;
+               ump_device.cdev.ops = &ump_fops;
+
+               /* register char dev with the kernel */
+               err = cdev_add(&ump_device.cdev, dev, 1/*count*/);
+               if (0 == err) {
+
+#if UMP_LICENSE_IS_GPL
+                       ump_device.ump_class = class_create(THIS_MODULE, ump_dev_name);
+                       if (IS_ERR(ump_device.ump_class)) {
+                               err = PTR_ERR(ump_device.ump_class);
+                       } else {
+                               struct device * mdev;
+                               mdev = device_create(ump_device.ump_class, NULL, dev, NULL, ump_dev_name);
+                               if (!IS_ERR(mdev)) {
+                                       return 0;
+                               }
+
+                               err = PTR_ERR(mdev);
+                       }
+                       cdev_del(&ump_device.cdev);
+#else
+                       return 0;
+#endif
+               }
+
+               unregister_chrdev_region(dev, 1);
+       }
+
+       return err;
+}
+
+
+
+/*
+ * Terminate the UMP device driver
+ */
+void ump_kernel_device_terminate(void)
+{
+       dev_t dev = MKDEV(ump_major, 0);
+
+#if UMP_LICENSE_IS_GPL
+       device_destroy(ump_device.ump_class, dev);
+       class_destroy(ump_device.ump_class);
+#endif
+
+       /* unregister char device */
+       cdev_del(&ump_device.cdev);
+
+       /* free major */
+       unregister_chrdev_region(dev, 1);
+
+#if UMP_LICENSE_IS_GPL
+       if(ump_debugfs_dir)
+               debugfs_remove_recursive(ump_debugfs_dir);
+#endif
+}
+
+/*
+ * Open a new session. User space has called open() on us.
+ */
+static int ump_file_open(struct inode *inode, struct file *filp)
+{
+       struct ump_session_data * session_data;
+       _mali_osk_errcode_t err;
+
+       /* input validation */
+       if (0 != MINOR(inode->i_rdev)) {
+               MSG_ERR(("Minor not zero in ump_file_open()\n"));
+               return -ENODEV;
+       }
+
+       /* Call the OS-Independent UMP Open function */
+       err = _ump_ukk_open((void**) &session_data );
+       if( _MALI_OSK_ERR_OK != err ) {
+               MSG_ERR(("Ump failed to open a new session\n"));
+               return map_errcode( err );
+       }
+
+       filp->private_data = (void*)session_data;
+       filp->f_pos = 0;
+
+       return 0; /* success */
+}
+
+
+
+/*
+ * Close a session. User space has called close() or crashed/terminated.
+ */
+static int ump_file_release(struct inode *inode, struct file *filp)
+{
+       _mali_osk_errcode_t err;
+
+       err = _ump_ukk_close((void**) &filp->private_data );
+       if( _MALI_OSK_ERR_OK != err ) {
+               return map_errcode( err );
+       }
+
+       return 0;  /* success */
+}
+
+
+
+/*
+ * Handle IOCTL requests.
+ */
+#ifdef HAVE_UNLOCKED_IOCTL
+static long ump_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#else
+static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+       int err = -ENOTTY;
+       void __user * argument;
+       struct ump_session_data * session_data;
+
+#ifndef HAVE_UNLOCKED_IOCTL
+       (void)inode; /* inode not used */
+#endif
+
+       session_data = (struct ump_session_data *)filp->private_data;
+       if (NULL == session_data) {
+               MSG_ERR(("No session data attached to file object\n"));
+               return -ENOTTY;
+       }
+
+       /* interpret the argument as a user pointer to something */
+       argument = (void __user *)arg;
+
+       switch (cmd) {
+       case UMP_IOC_QUERY_API_VERSION:
+               err = ump_get_api_version_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_ALLOCATE :
+               err = ump_allocate_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_RELEASE:
+               err = ump_release_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_SIZE_GET:
+               err = ump_size_get_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_MSYNC:
+               err = ump_msync_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_CACHE_OPERATIONS_CONTROL:
+               err = ump_cache_operations_control_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_SWITCH_HW_USAGE:
+               err = ump_switch_hw_usage_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_LOCK:
+               err = ump_lock_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       case UMP_IOC_UNLOCK:
+               err = ump_unlock_wrapper((u32 __user *)argument, session_data);
+               break;
+
+       default:
+               DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg));
+               err = -EFAULT;
+               break;
+       }
+
+       return err;
+}
+
+int map_errcode( _mali_osk_errcode_t err )
+{
+       switch(err) {
+       case _MALI_OSK_ERR_OK :
+               return 0;
+       case _MALI_OSK_ERR_FAULT:
+               return -EFAULT;
+       case _MALI_OSK_ERR_INVALID_FUNC:
+               return -ENOTTY;
+       case _MALI_OSK_ERR_INVALID_ARGS:
+               return -EINVAL;
+       case _MALI_OSK_ERR_NOMEM:
+               return -ENOMEM;
+       case _MALI_OSK_ERR_TIMEOUT:
+               return -ETIMEDOUT;
+       case _MALI_OSK_ERR_RESTARTSYSCALL:
+               return -ERESTARTSYS;
+       case _MALI_OSK_ERR_ITEM_NOT_FOUND:
+               return -ENOENT;
+       default:
+               return -EFAULT;
+       }
+}
+
+/*
+ * Handle from OS to map specified virtual memory to specified UMP memory.
+ */
+static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+       _ump_uk_map_mem_s args;
+       _mali_osk_errcode_t err;
+       struct ump_session_data * session_data;
+
+       /* Validate the session data */
+       session_data = (struct ump_session_data *)filp->private_data;
+       if (NULL == session_data) {
+               MSG_ERR(("mmap() called without any session data available\n"));
+               return -EFAULT;
+       }
+
+       /* Re-pack the arguments that mmap() packed for us */
+       args.ctx = session_data;
+       args.phys_addr = 0;
+       args.size = vma->vm_end - vma->vm_start;
+       args._ukk_private = vma;
+       args.secure_id = vma->vm_pgoff;
+       args.is_cached = 0;
+
+       if (!(vma->vm_flags & VM_SHARED)) {
+               args.is_cached = 1;
+               vma->vm_flags = vma->vm_flags | VM_SHARED | VM_MAYSHARE  ;
+               DBG_MSG(3, ("UMP Map function: Forcing the CPU to use cache\n"));
+       }
+       /* By setting this flag, during a process fork; the child process will not have the parent UMP mappings */
+       vma->vm_flags |= VM_DONTCOPY;
+
+       DBG_MSG(4, ("UMP vma->flags: %x\n", vma->vm_flags ));
+
+       /* Call the common mmap handler */
+       err = _ump_ukk_map_mem( &args );
+       if ( _MALI_OSK_ERR_OK != err) {
+               MSG_ERR(("_ump_ukk_map_mem() failed in function ump_file_mmap()"));
+               return map_errcode( err );
+       }
+
+       return 0; /* success */
+}
+
+/* Export UMP kernel space API functions */
+EXPORT_SYMBOL(ump_dd_secure_id_get);
+EXPORT_SYMBOL(ump_dd_handle_create_from_secure_id);
+EXPORT_SYMBOL(ump_dd_phys_block_count_get);
+EXPORT_SYMBOL(ump_dd_phys_block_get);
+EXPORT_SYMBOL(ump_dd_phys_blocks_get);
+EXPORT_SYMBOL(ump_dd_size_get);
+EXPORT_SYMBOL(ump_dd_reference_add);
+EXPORT_SYMBOL(ump_dd_reference_release);
+
+/* Export our own extended kernel space allocator */
+EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks);
+
+/* Setup init and exit functions for this module */
+module_init(ump_initialize_module);
+module_exit(ump_cleanup_module);
+
+/* And some module informatio */
+MODULE_LICENSE(UMP_KERNEL_LINUX_LICENSE);
+MODULE_AUTHOR("ARM Ltd.");
+MODULE_VERSION(SVN_REV_STRING);
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_kernel_linux.h b/drivers/gpu/arm/mali400/ump/linux/ump_kernel_linux.h
new file mode 100755 (executable)
index 0000000..5f302cf
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2007-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#ifndef __UMP_KERNEL_LINUX_H__
+#define __UMP_KERNEL_LINUX_H__
+
+int ump_kernel_device_initialize(void);
+void ump_kernel_device_terminate(void);
+
+
+#endif /* __UMP_KERNEL_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_dedicated.c
new file mode 100755 (executable)
index 0000000..4f41d1b
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/* needed to detect kernel version specific code */
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/semaphore.h>
+#else /* pre 2.6.26 the file was in the arch specific location */
+#include <asm/semaphore.h>
+#endif
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/atomic.h>
+#include <linux/vmalloc.h>
+#include "ump_kernel_common.h"
+#include "ump_kernel_memory_backend.h"
+
+
+
+#define UMP_BLOCK_SIZE (256UL * 1024UL)  /* 256kB, remember to keep the ()s */
+
+
+
+typedef struct block_info {
+       struct block_info * next;
+} block_info;
+
+
+
+typedef struct block_allocator {
+       struct semaphore mutex;
+       block_info * all_blocks;
+       block_info * first_free;
+       u32 base;
+       u32 num_blocks;
+       u32 num_free;
+} block_allocator;
+
+
+static void block_allocator_shutdown(ump_memory_backend * backend);
+static int block_allocator_allocate(void* ctx, ump_dd_mem * mem);
+static void block_allocator_release(void * ctx, ump_dd_mem * handle);
+static inline u32 get_phys(block_allocator * allocator, block_info * block);
+static u32 block_allocator_stat(struct ump_memory_backend *backend);
+
+
+
+/*
+ * Create dedicated memory backend
+ */
+ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size)
+{
+       ump_memory_backend * backend;
+       block_allocator * allocator;
+       u32 usable_size;
+       u32 num_blocks;
+
+       usable_size = (size + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1);
+       num_blocks = usable_size / UMP_BLOCK_SIZE;
+
+       if (0 == usable_size) {
+               DBG_MSG(1, ("Memory block of size %u is unusable\n", size));
+               return NULL;
+       }
+
+       DBG_MSG(5, ("Creating dedicated UMP memory backend. Base address: 0x%08x, size: 0x%08x\n", base_address, size));
+       DBG_MSG(6, ("%u usable bytes which becomes %u blocks\n", usable_size, num_blocks));
+
+       backend = kzalloc(sizeof(ump_memory_backend), GFP_KERNEL);
+       if (NULL != backend) {
+               allocator = kmalloc(sizeof(block_allocator), GFP_KERNEL);
+               if (NULL != allocator) {
+                       allocator->all_blocks = kmalloc(sizeof(block_info) * num_blocks, GFP_KERNEL);
+                       if (NULL != allocator->all_blocks) {
+                               int i;
+
+                               allocator->first_free = NULL;
+                               allocator->num_blocks = num_blocks;
+                               allocator->num_free = num_blocks;
+                               allocator->base = base_address;
+                               sema_init(&allocator->mutex, 1);
+
+                               for (i = 0; i < num_blocks; i++) {
+                                       allocator->all_blocks[i].next = allocator->first_free;
+                                       allocator->first_free = &allocator->all_blocks[i];
+                               }
+
+                               backend->ctx = allocator;
+                               backend->allocate = block_allocator_allocate;
+                               backend->release = block_allocator_release;
+                               backend->shutdown = block_allocator_shutdown;
+                               backend->stat = block_allocator_stat;
+                               backend->pre_allocate_physical_check = NULL;
+                               backend->adjust_to_mali_phys = NULL;
+
+                               return backend;
+                       }
+                       kfree(allocator);
+               }
+               kfree(backend);
+       }
+
+       return NULL;
+}
+
+
+
+/*
+ * Destroy specified dedicated memory backend
+ */
+static void block_allocator_shutdown(ump_memory_backend * backend)
+{
+       block_allocator * allocator;
+
+       BUG_ON(!backend);
+       BUG_ON(!backend->ctx);
+
+       allocator = (block_allocator*)backend->ctx;
+
+       DBG_MSG_IF(1, allocator->num_free != allocator->num_blocks, ("%u blocks still in use during shutdown\n", allocator->num_blocks - allocator->num_free));
+
+       kfree(allocator->all_blocks);
+       kfree(allocator);
+       kfree(backend);
+}
+
+
+
+static int block_allocator_allocate(void* ctx, ump_dd_mem * mem)
+{
+       block_allocator * allocator;
+       u32 left;
+       block_info * last_allocated = NULL;
+       int i = 0;
+
+       BUG_ON(!ctx);
+       BUG_ON(!mem);
+
+       allocator = (block_allocator*)ctx;
+       left = mem->size_bytes;
+
+       BUG_ON(!left);
+       BUG_ON(!&allocator->mutex);
+
+       mem->nr_blocks = ((left + UMP_BLOCK_SIZE - 1) & ~(UMP_BLOCK_SIZE - 1)) / UMP_BLOCK_SIZE;
+       mem->block_array = (ump_dd_physical_block*)vmalloc(sizeof(ump_dd_physical_block) * mem->nr_blocks);
+       if (NULL == mem->block_array) {
+               MSG_ERR(("Failed to allocate block array\n"));
+               return 0;
+       }
+
+       if (down_interruptible(&allocator->mutex)) {
+               MSG_ERR(("Could not get mutex to do block_allocate\n"));
+               return 0;
+       }
+
+       mem->size_bytes = 0;
+
+       while ((left > 0) && (allocator->first_free)) {
+               block_info * block;
+
+               block = allocator->first_free;
+               allocator->first_free = allocator->first_free->next;
+               block->next = last_allocated;
+               last_allocated = block;
+               allocator->num_free--;
+
+               mem->block_array[i].addr = get_phys(allocator, block);
+               mem->block_array[i].size = UMP_BLOCK_SIZE;
+               mem->size_bytes += UMP_BLOCK_SIZE;
+
+               i++;
+
+               if (left < UMP_BLOCK_SIZE) left = 0;
+               else left -= UMP_BLOCK_SIZE;
+       }
+
+       if (left) {
+               block_info * block;
+               /* release all memory back to the pool */
+               while (last_allocated) {
+                       block = last_allocated->next;
+                       last_allocated->next = allocator->first_free;
+                       allocator->first_free = last_allocated;
+                       last_allocated = block;
+                       allocator->num_free++;
+               }
+
+               vfree(mem->block_array);
+               mem->backend_info = NULL;
+               mem->block_array = NULL;
+
+               DBG_MSG(4, ("Could not find a mem-block for the allocation.\n"));
+               up(&allocator->mutex);
+
+               return 0;
+       }
+
+       mem->backend_info = last_allocated;
+
+       up(&allocator->mutex);
+       mem->is_cached=0;
+
+       return 1;
+}
+
+
+
+static void block_allocator_release(void * ctx, ump_dd_mem * handle)
+{
+       block_allocator * allocator;
+       block_info * block, * next;
+
+       BUG_ON(!ctx);
+       BUG_ON(!handle);
+
+       allocator = (block_allocator*)ctx;
+       block = (block_info*)handle->backend_info;
+       BUG_ON(!block);
+
+       if (down_interruptible(&allocator->mutex)) {
+               MSG_ERR(("Allocator release: Failed to get mutex - memory leak\n"));
+               return;
+       }
+
+       while (block) {
+               next = block->next;
+
+               BUG_ON( (block < allocator->all_blocks) || (block > (allocator->all_blocks + allocator->num_blocks)));
+
+               block->next = allocator->first_free;
+               allocator->first_free = block;
+               allocator->num_free++;
+
+               block = next;
+       }
+       DBG_MSG(3, ("%d blocks free after release call\n", allocator->num_free));
+       up(&allocator->mutex);
+
+       vfree(handle->block_array);
+       handle->block_array = NULL;
+}
+
+
+
+/*
+ * Helper function for calculating the physical base adderss of a memory block
+ */
+static inline u32 get_phys(block_allocator * allocator, block_info * block)
+{
+       return allocator->base + ((block - allocator->all_blocks) * UMP_BLOCK_SIZE);
+}
+
+static u32 block_allocator_stat(struct ump_memory_backend *backend)
+{
+       block_allocator *allocator;
+       BUG_ON(!backend);
+       allocator = (block_allocator*)backend->ctx;
+       BUG_ON(!allocator);
+
+       return (allocator->num_blocks - allocator->num_free)* UMP_BLOCK_SIZE;
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_dedicated.h
new file mode 100755 (executable)
index 0000000..dbd5356
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_memory_backend_dedicated.h
+ */
+
+#ifndef __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__
+#define __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__
+
+#include "ump_kernel_memory_backend.h"
+
+ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size);
+
+#endif /* __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ */
+
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_os.c b/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_os.c
new file mode 100755 (executable)
index 0000000..5e6fafd
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/* needed to detect kernel version specific code */
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/semaphore.h>
+#else /* pre 2.6.26 the file was in the arch specific location */
+#include <asm/semaphore.h>
+#endif
+
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/atomic.h>
+#include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
+#include "ump_kernel_common.h"
+#include "ump_kernel_memory_backend.h"
+
+
+
+typedef struct os_allocator {
+       struct semaphore mutex;
+       u32 num_pages_max;       /**< Maximum number of pages to allocate from the OS */
+       u32 num_pages_allocated; /**< Number of pages allocated from the OS */
+} os_allocator;
+
+
+
+static void os_free(void* ctx, ump_dd_mem * descriptor);
+static int os_allocate(void* ctx, ump_dd_mem * descriptor);
+static void os_memory_backend_destroy(ump_memory_backend * backend);
+static u32 os_stat(struct ump_memory_backend *backend);
+
+
+
+/*
+ * Create OS memory backend
+ */
+ump_memory_backend * ump_os_memory_backend_create(const int max_allocation)
+{
+       ump_memory_backend * backend;
+       os_allocator * info;
+
+       info = kmalloc(sizeof(os_allocator), GFP_KERNEL);
+       if (NULL == info) {
+               return NULL;
+       }
+
+       info->num_pages_max = max_allocation >> PAGE_SHIFT;
+       info->num_pages_allocated = 0;
+
+       sema_init(&info->mutex, 1);
+
+       backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL);
+       if (NULL == backend) {
+               kfree(info);
+               return NULL;
+       }
+
+       backend->ctx = info;
+       backend->allocate = os_allocate;
+       backend->release = os_free;
+       backend->shutdown = os_memory_backend_destroy;
+       backend->stat = os_stat;
+       backend->pre_allocate_physical_check = NULL;
+       backend->adjust_to_mali_phys = NULL;
+
+       return backend;
+}
+
+
+
+/*
+ * Destroy specified OS memory backend
+ */
+static void os_memory_backend_destroy(ump_memory_backend * backend)
+{
+       os_allocator * info = (os_allocator*)backend->ctx;
+
+       DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated));
+
+       kfree(info);
+       kfree(backend);
+}
+
+
+
+/*
+ * Allocate UMP memory
+ */
+static int os_allocate(void* ctx, ump_dd_mem * descriptor)
+{
+       u32 left;
+       os_allocator * info;
+       int pages_allocated = 0;
+       int is_cached;
+
+       BUG_ON(!descriptor);
+       BUG_ON(!ctx);
+
+       info = (os_allocator*)ctx;
+       left = descriptor->size_bytes;
+       is_cached = descriptor->is_cached;
+
+       if (down_interruptible(&info->mutex)) {
+               DBG_MSG(1, ("Failed to get mutex in os_free\n"));
+               return 0; /* failure */
+       }
+
+       descriptor->backend_info = NULL;
+       descriptor->nr_blocks = ((left + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+       DBG_MSG(5, ("Allocating page array. Size: %lu\n", descriptor->nr_blocks * sizeof(ump_dd_physical_block)));
+
+       descriptor->block_array = (ump_dd_physical_block *)vmalloc(sizeof(ump_dd_physical_block) * descriptor->nr_blocks);
+       if (NULL == descriptor->block_array) {
+               up(&info->mutex);
+               DBG_MSG(1, ("Block array could not be allocated\n"));
+               return 0; /* failure */
+       }
+
+       while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max)) {
+               struct page * new_page;
+
+               if (is_cached) {
+                       new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN);
+               } else {
+                       new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD);
+               }
+               if (NULL == new_page) {
+                       break;
+               }
+
+               /* Ensure page caches are flushed. */
+               if ( is_cached ) {
+                       descriptor->block_array[pages_allocated].addr = page_to_phys(new_page);
+                       descriptor->block_array[pages_allocated].size = PAGE_SIZE;
+               } else {
+                       descriptor->block_array[pages_allocated].addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL );
+                       descriptor->block_array[pages_allocated].size = PAGE_SIZE;
+               }
+
+               DBG_MSG(5, ("Allocated page 0x%08lx cached: %d\n", descriptor->block_array[pages_allocated].addr, is_cached));
+
+               if (left < PAGE_SIZE) {
+                       left = 0;
+               } else {
+                       left -= PAGE_SIZE;
+               }
+
+               pages_allocated++;
+       }
+
+       DBG_MSG(5, ("Alloce for ID:%2d got %d pages, cached: %d\n", descriptor->secure_id,  pages_allocated));
+
+       if (left) {
+               DBG_MSG(1, ("Failed to allocate needed pages\n"));
+
+               while(pages_allocated) {
+                       pages_allocated--;
+                       if ( !is_cached ) {
+                               dma_unmap_page(NULL, descriptor->block_array[pages_allocated].addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+                       }
+                       __free_page(pfn_to_page(descriptor->block_array[pages_allocated].addr >> PAGE_SHIFT) );
+               }
+
+               up(&info->mutex);
+
+               return 0; /* failure */
+       }
+
+       info->num_pages_allocated += pages_allocated;
+
+       DBG_MSG(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max));
+
+       up(&info->mutex);
+
+       return 1; /* success*/
+}
+
+
+/*
+ * Free specified UMP memory
+ */
+static void os_free(void* ctx, ump_dd_mem * descriptor)
+{
+       os_allocator * info;
+       int i;
+
+       BUG_ON(!ctx);
+       BUG_ON(!descriptor);
+
+       info = (os_allocator*)ctx;
+
+       BUG_ON(descriptor->nr_blocks > info->num_pages_allocated);
+
+       if (down_interruptible(&info->mutex)) {
+               DBG_MSG(1, ("Failed to get mutex in os_free\n"));
+               return;
+       }
+
+       DBG_MSG(5, ("Releasing %lu OS pages\n", descriptor->nr_blocks));
+
+       info->num_pages_allocated -= descriptor->nr_blocks;
+
+       up(&info->mutex);
+
+       for ( i = 0; i < descriptor->nr_blocks; i++) {
+               DBG_MSG(6, ("Freeing physical page. Address: 0x%08lx\n", descriptor->block_array[i].addr));
+               if ( ! descriptor->is_cached) {
+                       dma_unmap_page(NULL, descriptor->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+               }
+               __free_page(pfn_to_page(descriptor->block_array[i].addr>>PAGE_SHIFT) );
+       }
+
+       vfree(descriptor->block_array);
+}
+
+
+static u32 os_stat(struct ump_memory_backend *backend)
+{
+       os_allocator *info;
+       info = (os_allocator*)backend->ctx;
+       return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE;
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_os.h b/drivers/gpu/arm/mali400/ump/linux/ump_kernel_memory_backend_os.h
new file mode 100755 (executable)
index 0000000..82b45c2
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_kernel_memory_backend_os.h
+ */
+
+#ifndef __UMP_KERNEL_MEMORY_BACKEND_OS_H__
+#define __UMP_KERNEL_MEMORY_BACKEND_OS_H__
+
+#include "ump_kernel_memory_backend.h"
+
+ump_memory_backend * ump_os_memory_backend_create(const int max_allocation);
+
+#endif /* __UMP_KERNEL_MEMORY_BACKEND_OS_H__ */
+
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_memory_backend.c b/drivers/gpu/arm/mali400/ump/linux/ump_memory_backend.c
new file mode 100755 (executable)
index 0000000..136b05f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+#include <linux/module.h>            /* kernel module definitions */
+#include <linux/ioport.h>            /* request_mem_region */
+
+#include "arch/config.h"             /* Configuration for current platform. The symlink for arch is set by Makefile */
+
+#include "ump_osk.h"
+#include "ump_kernel_common.h"
+#include "ump_kernel_memory_backend_os.h"
+#include "ump_kernel_memory_backend_dedicated.h"
+extern unsigned long totalram_pages;
+
+/* Configure which dynamic memory allocator to use */
+int ump_backend = ARCH_UMP_BACKEND_DEFAULT;
+module_param(ump_backend, int, S_IRUGO); /* r--r--r-- */
+MODULE_PARM_DESC(ump_backend, "0 = dedicated memory backend (default), 1 = OS memory backend");
+
+/* The base address of the memory block for the dedicated memory backend */
+unsigned int ump_memory_address = ARCH_UMP_MEMORY_ADDRESS_DEFAULT;
+module_param(ump_memory_address, uint, S_IRUGO); /* r--r--r-- */
+MODULE_PARM_DESC(ump_memory_address, "The physical address to map for the dedicated memory backend");
+
+/* The size of the memory block for the dedicated memory backend */
+unsigned int ump_memory_size = ARCH_UMP_MEMORY_SIZE_DEFAULT;
+module_param(ump_memory_size, uint, S_IRUGO); /* r--r--r-- */
+MODULE_PARM_DESC(ump_memory_size, "The size of fixed memory to map in the dedicated memory backend");
+
+ump_memory_backend* ump_memory_backend_create ( void )
+{
+       ump_memory_backend * backend = NULL;
+
+       /* Create the dynamic memory allocator backend */
+       if (0 == ump_backend) {
+               DBG_MSG(2, ("Using dedicated memory backend\n"));
+
+               DBG_MSG(2, ("Requesting dedicated memory: 0x%08x, size: %u\n", ump_memory_address, ump_memory_size));
+               /* Ask the OS if we can use the specified physical memory */
+               if (NULL == request_mem_region(ump_memory_address, ump_memory_size, "UMP Memory")) {
+                       MSG_ERR(("Failed to request memory region (0x%08X - 0x%08X). Is Mali DD already loaded?\n", ump_memory_address, ump_memory_address + ump_memory_size - 1));
+                       return NULL;
+               }
+               backend = ump_block_allocator_create(ump_memory_address, ump_memory_size);
+       } else if (1 == ump_backend) {
+               ump_memory_size = totalram_pages * 4 * 1024 / 2;
+               DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size));
+               backend = ump_os_memory_backend_create(ump_memory_size);
+       }
+
+       return backend;
+}
+
+void ump_memory_backend_destroy( void )
+{
+       if (0 == ump_backend) {
+               DBG_MSG(2, ("Releasing dedicated memory: 0x%08x\n", ump_memory_address));
+               release_mem_region(ump_memory_address, ump_memory_size);
+       }
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_osk_atomics.c b/drivers/gpu/arm/mali400/ump/linux/ump_osk_atomics.c
new file mode 100755 (executable)
index 0000000..0d56ae0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_osk_atomics.c
+ * Implementation of the OS abstraction layer for the UMP kernel device driver
+ */
+
+#include "ump_osk.h"
+#include <asm/atomic.h>
+
+int _ump_osk_atomic_dec_and_read( _mali_osk_atomic_t *atom )
+{
+       return atomic_dec_return((atomic_t *)&atom->u.val);
+}
+
+int _ump_osk_atomic_inc_and_read( _mali_osk_atomic_t *atom )
+{
+       return atomic_inc_return((atomic_t *)&atom->u.val);
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_osk_low_level_mem.c b/drivers/gpu/arm/mali400/ump/linux/ump_osk_low_level_mem.c
new file mode 100755 (executable)
index 0000000..4d5a726
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_osk_memory.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+/* needed to detect kernel version specific code */
+#include <linux/version.h>
+
+#include "ump_osk.h"
+#include "ump_uk_types.h"
+#include "ump_ukk.h"
+#include "ump_kernel_common.h"
+#include <linux/module.h>            /* kernel module definitions */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/memory.h>
+#include <asm/uaccess.h>                       /* to verify pointers from user space */
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+
+typedef struct ump_vma_usage_tracker {
+       atomic_t references;
+       ump_memory_allocation *descriptor;
+} ump_vma_usage_tracker;
+
+static void ump_vma_open(struct vm_area_struct * vma);
+static void ump_vma_close(struct vm_area_struct * vma);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf);
+#else
+static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address);
+#endif
+
+static struct vm_operations_struct ump_vm_ops = {
+       .open = ump_vma_open,
+       .close = ump_vma_close,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+       .fault = ump_cpu_page_fault_handler
+#else
+       .nopfn = ump_cpu_page_fault_handler
+#endif
+};
+
+/*
+ * Page fault for VMA region
+ * This should never happen since we always map in the entire virtual memory range.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+static int ump_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf)
+#else
+static unsigned long ump_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address)
+#endif
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+       void __user * address;
+       address = vmf->virtual_address;
+#endif
+       MSG_ERR(("Page-fault in UMP memory region caused by the CPU\n"));
+       MSG_ERR(("VMA: 0x%08lx, virtual address: 0x%08lx\n", (unsigned long)vma, address));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+       return VM_FAULT_SIGBUS;
+#else
+       return NOPFN_SIGBUS;
+#endif
+}
+
+static void ump_vma_open(struct vm_area_struct * vma)
+{
+       ump_vma_usage_tracker * vma_usage_tracker;
+       int new_val;
+
+       vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data;
+       BUG_ON(NULL == vma_usage_tracker);
+
+       new_val = atomic_inc_return(&vma_usage_tracker->references);
+
+       DBG_MSG(4, ("VMA open, VMA reference count incremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val));
+}
+
+static void ump_vma_close(struct vm_area_struct * vma)
+{
+       ump_vma_usage_tracker * vma_usage_tracker;
+       _ump_uk_unmap_mem_s args;
+       int new_val;
+
+       vma_usage_tracker = (ump_vma_usage_tracker*)vma->vm_private_data;
+       BUG_ON(NULL == vma_usage_tracker);
+
+       new_val = atomic_dec_return(&vma_usage_tracker->references);
+
+       DBG_MSG(4, ("VMA close, VMA reference count decremented. VMA: 0x%08lx, reference count: %d\n", (unsigned long)vma, new_val));
+
+       if (0 == new_val) {
+               ump_memory_allocation * descriptor;
+
+               descriptor = vma_usage_tracker->descriptor;
+
+               args.ctx = descriptor->ump_session;
+               args.cookie = descriptor->cookie;
+               args.mapping = descriptor->mapping;
+               args.size = descriptor->size;
+
+               args._ukk_private = NULL; /** @note unused */
+
+               DBG_MSG(4, ("No more VMA references left, releasing UMP memory\n"));
+               _ump_ukk_unmap_mem( & args );
+
+               /* vma_usage_tracker is free()d by _ump_osk_mem_mapregion_term() */
+       }
+}
+
+_mali_osk_errcode_t _ump_osk_mem_mapregion_init( ump_memory_allocation * descriptor )
+{
+       ump_vma_usage_tracker * vma_usage_tracker;
+       struct vm_area_struct *vma;
+
+       if (NULL == descriptor) return _MALI_OSK_ERR_FAULT;
+
+       vma_usage_tracker = kmalloc(sizeof(ump_vma_usage_tracker), GFP_KERNEL);
+       if (NULL == vma_usage_tracker) {
+               DBG_MSG(1, ("Failed to allocate memory for ump_vma_usage_tracker in _mali_osk_mem_mapregion_init\n"));
+               return -_MALI_OSK_ERR_FAULT;
+       }
+
+       vma = (struct vm_area_struct*)descriptor->process_mapping_info;
+       if (NULL == vma ) {
+               kfree(vma_usage_tracker);
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       vma->vm_private_data = vma_usage_tracker;
+       vma->vm_flags |= VM_IO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+       vma->vm_flags |= VM_RESERVED;
+#else
+       vma->vm_flags |= VM_DONTDUMP;
+       vma->vm_flags |= VM_DONTEXPAND;
+       vma->vm_flags |= VM_PFNMAP;
+#endif
+
+
+       if (0==descriptor->is_cached) {
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+       }
+       DBG_MSG(3, ("Mapping with page_prot: 0x%x\n", vma->vm_page_prot ));
+
+       /* Setup the functions which handle further VMA handling */
+       vma->vm_ops = &ump_vm_ops;
+
+       /* Do the va range allocation - in this case, it was done earlier, so we copy in that information */
+       descriptor->mapping = (void __user*)vma->vm_start;
+
+       atomic_set(&vma_usage_tracker->references, 1); /*this can later be increased if process is forked, see ump_vma_open() */
+       vma_usage_tracker->descriptor = descriptor;
+
+       return _MALI_OSK_ERR_OK;
+}
+
+void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor )
+{
+       struct vm_area_struct* vma;
+       ump_vma_usage_tracker * vma_usage_tracker;
+
+       if (NULL == descriptor) return;
+
+       /* Linux does the right thing as part of munmap to remove the mapping
+        * All that remains is that we remove the vma_usage_tracker setup in init() */
+       vma = (struct vm_area_struct*)descriptor->process_mapping_info;
+
+       vma_usage_tracker = vma->vm_private_data;
+
+       /* We only get called if mem_mapregion_init succeeded */
+       kfree(vma_usage_tracker);
+       return;
+}
+
+_mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descriptor, u32 offset, u32 * phys_addr, unsigned long size )
+{
+       struct vm_area_struct *vma;
+       _mali_osk_errcode_t retval;
+
+       if (NULL == descriptor) return _MALI_OSK_ERR_FAULT;
+
+       vma = (struct vm_area_struct*)descriptor->process_mapping_info;
+
+       if (NULL == vma ) return _MALI_OSK_ERR_FAULT;
+
+       retval = remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, (*phys_addr) >> PAGE_SHIFT, size, vma->vm_page_prot) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;;
+
+       DBG_MSG(4, ("Mapping virtual to physical memory. ID: %u, vma: 0x%08lx, virtual addr:0x%08lx, physical addr: 0x%08lx, size:%lu, prot:0x%x, vm_flags:0x%x RETVAL: 0x%x\n",
+                   ump_dd_secure_id_get(descriptor->handle),
+                   (unsigned long)vma,
+                   (unsigned long)(vma->vm_start + offset),
+                   (unsigned long)*phys_addr,
+                   size,
+                   (unsigned int)vma->vm_page_prot, vma->vm_flags, retval));
+
+       return retval;
+}
+
+static void level1_cache_flush_all(void)
+{
+       DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n"));
+       __cpuc_flush_kern_all();
+}
+
+void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data )
+{
+       int i;
+
+       /* Flush L1 using virtual address, the entire range in one go.
+        * Only flush if user space process has a valid write mapping on given address. */
+       if( (mem) && (virt!=NULL) && (access_ok(VERIFY_WRITE, virt, size)) ) {
+               __cpuc_flush_dcache_area(virt, size);
+               DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. CPU address: %x, size: %x\n", mem->secure_id, virt, size));
+       } else {
+               if (session_data) {
+                       if (op == _UMP_UK_MSYNC_FLUSH_L1  ) {
+                               DBG_MSG(4, ("UMP Pending L1 cache flushes: %d\n", session_data->has_pending_level1_cache_flush));
+                               session_data->has_pending_level1_cache_flush = 0;
+                               level1_cache_flush_all();
+                               return;
+                       } else {
+                               if (session_data->cache_operations_ongoing) {
+                                       session_data->has_pending_level1_cache_flush++;
+                                       DBG_MSG(4, ("UMP[%02u] Defering the L1 flush. Nr pending:%d\n", mem->secure_id, session_data->has_pending_level1_cache_flush) );
+                               } else {
+                                       /* Flushing the L1 cache for each switch_user() if ump_cache_operations_control(START) is not called */
+                                       level1_cache_flush_all();
+                               }
+                       }
+               } else {
+                       DBG_MSG(4, ("Unkown state %s %d\n", __FUNCTION__, __LINE__));
+                       level1_cache_flush_all();
+               }
+       }
+
+       if ( NULL == mem ) return;
+
+       if ( mem->size_bytes==size) {
+               DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache\n",mem->secure_id));
+       } else {
+               DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache. Blocks:%u, TotalSize:%u. FlushSize:%u Offset:0x%x FirstPaddr:0x%08x\n",
+                           mem->secure_id, mem->nr_blocks, mem->size_bytes, size, offset, mem->block_array[0].addr));
+       }
+
+
+       /* Flush L2 using physical addresses, block for block. */
+       for (i=0 ; i < mem->nr_blocks; i++) {
+               u32 start_p, end_p;
+               ump_dd_physical_block *block;
+               block = &mem->block_array[i];
+
+               if(offset >= block->size) {
+                       offset -= block->size;
+                       continue;
+               }
+
+               if(offset) {
+                       start_p = (u32)block->addr + offset;
+                       /* We'll zero the offset later, after using it to calculate end_p. */
+               } else {
+                       start_p = (u32)block->addr;
+               }
+
+               if(size < block->size - offset) {
+                       end_p = start_p + size - 1;
+                       size = 0;
+               } else {
+                       if(offset) {
+                               end_p = start_p + (block->size - offset - 1);
+                               size -= block->size - offset;
+                               offset = 0;
+                       } else {
+                               end_p = start_p + block->size - 1;
+                               size -= block->size;
+                       }
+               }
+
+               switch(op) {
+               case _UMP_UK_MSYNC_CLEAN:
+                       outer_clean_range(start_p, end_p);
+                       break;
+               case _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE:
+                       outer_flush_range(start_p, end_p);
+                       break;
+               case _UMP_UK_MSYNC_INVALIDATE:
+                       outer_inv_range(start_p, end_p);
+                       break;
+               default:
+                       break;
+               }
+
+               if(0 == size) {
+                       /* Nothing left to flush. */
+                       break;
+               }
+       }
+
+       return;
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_osk_misc.c b/drivers/gpu/arm/mali400/ump/linux/ump_osk_misc.c
new file mode 100755 (executable)
index 0000000..6ed25d3
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_osk_misc.c
+ * Implementation of the OS abstraction layer for the UMP kernel device driver
+ */
+
+
+#include "ump_osk.h"
+
+#include <linux/kernel.h>
+#include "ump_kernel_linux.h"
+
+/* is called from ump_kernel_constructor in common code */
+_mali_osk_errcode_t _ump_osk_init( void )
+{
+       if (0 != ump_kernel_device_initialize()) {
+               return _MALI_OSK_ERR_FAULT;
+       }
+
+       return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _ump_osk_term( void )
+{
+       ump_kernel_device_terminate();
+       return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_ukk_ref_wrappers.c b/drivers/gpu/arm/mali400/ump/linux/ump_ukk_ref_wrappers.c
new file mode 100755 (executable)
index 0000000..f2b084e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ukk_wrappers.c
+ * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation
+ */
+
+
+#include <asm/uaccess.h>             /* user space access */
+
+#include "ump_osk.h"
+#include "ump_uk_types.h"
+#include "ump_ukk.h"
+#include "ump_kernel_common.h"
+
+/*
+ * IOCTL operation; Allocate UMP memory
+ */
+int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_allocate_s user_interaction;
+       _mali_osk_errcode_t err;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_allocate()\n"));
+               return -ENOTTY;
+       }
+
+       /* Copy the user space memory to kernel space (so we safely can read it) */
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_allocate()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+
+       err = _ump_ukk_allocate( &user_interaction );
+       if( _MALI_OSK_ERR_OK != err ) {
+               DBG_MSG(1, ("_ump_ukk_allocate() failed in ump_ioctl_allocate()\n"));
+               return map_errcode(err);
+       }
+       user_interaction.ctx = NULL;
+
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               /* If the copy fails then we should release the memory. We can use the IOCTL release to accomplish this */
+               _ump_uk_release_s release_args;
+
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_allocate()\n"));
+
+               release_args.ctx = (void *) session_data;
+               release_args.secure_id = user_interaction.secure_id;
+
+               err = _ump_ukk_release( &release_args );
+               if(_MALI_OSK_ERR_OK != err) {
+                       MSG_ERR(("_ump_ukk_release() also failed when trying to release newly allocated memory in ump_ioctl_allocate()\n"));
+               }
+
+               return -EFAULT;
+       }
+
+       return 0; /* success */
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_ukk_ref_wrappers.h b/drivers/gpu/arm/mali400/ump/linux/ump_ukk_ref_wrappers.h
new file mode 100755 (executable)
index 0000000..ba028f2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ukk_wrappers.h
+ * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls for the reference implementation
+ */
+
+#ifndef __UMP_UKK_REF_WRAPPERS_H__
+#define __UMP_UKK_REF_WRAPPERS_H__
+
+#include <linux/kernel.h>
+#include "ump_kernel_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_UKK_REF_WRAPPERS_H__ */
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_ukk_wrappers.c b/drivers/gpu/arm/mali400/ump/linux/ump_ukk_wrappers.c
new file mode 100755 (executable)
index 0000000..64a62f6
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ukk_wrappers.c
+ * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls
+ */
+
+#include <asm/uaccess.h>             /* user space access */
+
+#include "ump_osk.h"
+#include "ump_uk_types.h"
+#include "ump_ukk.h"
+#include "ump_kernel_common.h"
+
+/*
+ * IOCTL operation; Negotiate version of IOCTL API
+ */
+int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data)
+{
+       _ump_uk_api_version_s version_info;
+       _mali_osk_errcode_t err;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_get_api_version()\n"));
+               return -ENOTTY;
+       }
+
+       /* Copy the user space memory to kernel space (so we safely can read it) */
+       if (0 != copy_from_user(&version_info, argument, sizeof(version_info))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n"));
+               return -EFAULT;
+       }
+
+       version_info.ctx = (void*) session_data;
+       err = _ump_uku_get_api_version( &version_info );
+       if( _MALI_OSK_ERR_OK != err ) {
+               MSG_ERR(("_ump_uku_get_api_version() failed in ump_ioctl_get_api_version()\n"));
+               return map_errcode(err);
+       }
+
+       version_info.ctx = NULL;
+
+       /* Copy ouput data back to user space */
+       if (0 != copy_to_user(argument, &version_info, sizeof(version_info))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_get_api_version()\n"));
+               return -EFAULT;
+       }
+
+       return 0; /* success */
+}
+
+
+/*
+ * IOCTL operation; Release reference to specified UMP memory.
+ */
+int ump_release_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_release_s release_args;
+       _mali_osk_errcode_t err;
+
+       /* Sanity check input parameters */
+       if (NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_release()\n"));
+               return -ENOTTY;
+       }
+
+       /* Copy the user space memory to kernel space (so we safely can read it) */
+       if (0 != copy_from_user(&release_args, argument, sizeof(release_args))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_get_api_version()\n"));
+               return -EFAULT;
+       }
+
+       release_args.ctx = (void*) session_data;
+       err = _ump_ukk_release( &release_args );
+       if( _MALI_OSK_ERR_OK != err ) {
+               MSG_ERR(("_ump_ukk_release() failed in ump_ioctl_release()\n"));
+               return map_errcode(err);
+       }
+
+
+       return 0; /* success */
+}
+
+/*
+ * IOCTL operation; Return size for specified UMP memory.
+ */
+int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_size_get_s user_interaction;
+       _mali_osk_errcode_t err;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+               return -ENOTTY;
+       }
+
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_size_get()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+       err = _ump_ukk_size_get( &user_interaction );
+       if( _MALI_OSK_ERR_OK != err ) {
+               MSG_ERR(("_ump_ukk_size_get() failed in ump_ioctl_size_get()\n"));
+               return map_errcode(err);
+       }
+
+       user_interaction.ctx = NULL;
+
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_size_get()\n"));
+               return -EFAULT;
+       }
+
+       return 0; /* success */
+}
+
+/*
+ * IOCTL operation; Do cache maintenance on specified UMP memory.
+ */
+int ump_msync_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_msync_s user_interaction;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+               return -ENOTTY;
+       }
+
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_msync()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+
+       _ump_ukk_msync( &user_interaction );
+
+       user_interaction.ctx = NULL;
+
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_msync()\n"));
+               return -EFAULT;
+       }
+
+       return 0; /* success */
+}
+int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_cache_operations_control_s user_interaction;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+               return -ENOTTY;
+       }
+
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_cache_operations_control()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+
+       _ump_ukk_cache_operations_control((_ump_uk_cache_operations_control_s*) &user_interaction );
+
+       user_interaction.ctx = NULL;
+
+#if 0  /* No data to copy back */
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_cache_operations_control()\n"));
+               return -EFAULT;
+       }
+#endif
+       return 0; /* success */
+}
+
+int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_switch_hw_usage_s user_interaction;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+               return -ENOTTY;
+       }
+
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+
+       _ump_ukk_switch_hw_usage( &user_interaction );
+
+       user_interaction.ctx = NULL;
+
+#if 0  /* No data to copy back */
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n"));
+               return -EFAULT;
+       }
+#endif
+       return 0; /* success */
+}
+
+int ump_lock_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_lock_s user_interaction;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+               return -ENOTTY;
+       }
+
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+
+       _ump_ukk_lock( &user_interaction );
+
+       user_interaction.ctx = NULL;
+
+#if 0  /* No data to copy back */
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n"));
+               return -EFAULT;
+       }
+#endif
+
+       return 0; /* success */
+}
+
+int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data  * session_data)
+{
+       _ump_uk_unlock_s user_interaction;
+
+       /* Sanity check input parameters */
+       if (NULL == argument || NULL == session_data) {
+               MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+               return -ENOTTY;
+       }
+
+       if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction))) {
+               MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n"));
+               return -EFAULT;
+       }
+
+       user_interaction.ctx = (void *) session_data;
+
+       _ump_ukk_unlock( &user_interaction );
+
+       user_interaction.ctx = NULL;
+
+#if 0  /* No data to copy back */
+       if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction))) {
+               MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n"));
+               return -EFAULT;
+       }
+#endif
+
+       return 0; /* success */
+}
diff --git a/drivers/gpu/arm/mali400/ump/linux/ump_ukk_wrappers.h b/drivers/gpu/arm/mali400/ump/linux/ump_ukk_wrappers.h
new file mode 100755 (executable)
index 0000000..9b8c87d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010, 2012-2013 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ukk_wrappers.h
+ * Defines the wrapper functions which turn Linux IOCTL calls into _ukk_ calls
+ */
+
+#ifndef __UMP_UKK_WRAPPERS_H__
+#define __UMP_UKK_WRAPPERS_H__
+
+#include <linux/kernel.h>
+#include "ump_kernel_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data * session_data);
+int ump_release_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+int ump_msync_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+int ump_lock_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data  * session_data);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* __UMP_UKK_WRAPPERS_H__ */
index c25aa5937f22944dbd2ef9b007edc1406378bf19..256f036da4a95882ec57c2739189f92fcca34e6f 100755 (executable)
@@ -190,6 +190,7 @@ static const struct iio_chan_spec rk_adc_iio_channels[] = {
        ADC_CHANNEL(0, "adc0"),
        ADC_CHANNEL(1, "adc1"),
        ADC_CHANNEL(2, "adc2"),
+       ADC_CHANNEL(3, "adc3"),
 };
 
 static int rk_adc_remove_devices(struct device *dev, void *c)
old mode 100644 (file)
new mode 100755 (executable)
index 12eaec2..dfcb794
@@ -198,6 +198,8 @@ source "drivers/input/touchscreen/Kconfig"
 source "drivers/input/misc/Kconfig"
 
 source "drivers/input/sensors/Kconfig"
+
+source "drivers/input/remotectl/Kconfig"
 endif
 
 menu "Hardware I/O ports"
old mode 100644 (file)
new mode 100755 (executable)
index 1b7621c..20ff7f8
@@ -26,3 +26,4 @@ obj-$(CONFIG_INPUT_MISC)      += misc/
 obj-$(CONFIG_SENSOR_DEVICE) += sensors/
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
 obj-$(CONFIG_INPUT_KEYRESET)   += keyreset.o
+obj-$(CONFIG_ROCKCHIP_REMOTECTL)        += remotectl/
index d554586fc184a81a9338d7ea0bbc475ef60dbd3b..8e45f2ee3fe1c21d8e034b0ec2eed8b307c28cdb 100644 (file)
@@ -14,7 +14,6 @@ if INPUT_KEYBOARD
 
 config KEYS_RK
         tristate "rk keyboard"
-        depends on ROCKCHIP_ADC 
         default y
         help
           rk keyboard drivers(gpio and adc)
index c0f7929908c71ce00cf3ad98bae6da58a79ddbb5..9fc39010406e97bfea7c651858e995c20d273b3f 100755 (executable)
@@ -183,6 +183,8 @@ static int rk_key_adc_iio_read(struct rk_keys_drvdata *data)
         struct iio_channel *channel = data->chan;
         int val, ret;
 
+       if (!channel)
+               return INVALID_ADVALUE;
         ret = iio_read_channel_raw(channel, &val);
         if (ret < 0) {
                 pr_err("read channel() error: %d\n", ret);
@@ -244,8 +246,10 @@ static int rk_keys_parse_dt(struct rk_keys_drvdata *pdata,
        u32 code, adc_value, flags;;
        
        chan = iio_channel_get(&pdev->dev, NULL);
-    if (IS_ERR(chan))
-        goto error_ret;
+       if (IS_ERR(chan)) {
+               dev_info(&pdev->dev, "no io-channels defined\n");
+               chan = NULL;
+       }
     pdata->chan = chan;
        
        for_each_child_of_node(node, child_node) {
@@ -308,10 +312,8 @@ static int  keys_probe(struct platform_device *pdev)
        int wakeup, key_num = 0;
 
        key_num = of_get_child_count(np);
-       if (key_num == 0) {
-               error = -ENODEV;
-               return error;
-       }
+       if (key_num == 0)
+               dev_info(&pdev->dev, "no key defined\n");
 
     ddata = devm_kzalloc(dev, sizeof(struct rk_keys_drvdata) +
            key_num * sizeof(struct rk_keys_button),
@@ -413,9 +415,11 @@ static int  keys_probe(struct platform_device *pdev)
        }
 
         //adc polling work
-       INIT_DELAYED_WORK(&ddata->adc_poll_work, adc_key_poll);
-       schedule_delayed_work(&ddata->adc_poll_work,
-                                       msecs_to_jiffies(ADC_SAMPLE_TIME));
+       if (ddata->chan) {
+               INIT_DELAYED_WORK(&ddata->adc_poll_work, adc_key_poll);
+               schedule_delayed_work(&ddata->adc_poll_work,
+                                     msecs_to_jiffies(ADC_SAMPLE_TIME));
+       }
 
     spdata = ddata;
        sinput_dev = input;
@@ -444,7 +448,8 @@ static int keys_remove(struct platform_device *pdev)
        for (i = 0; i < ddata->nbuttons; i++) {
                del_timer_sync(&ddata->button[i].timer);
        }
-       cancel_delayed_work_sync(&ddata->adc_poll_work);
+       if (ddata->chan)
+               cancel_delayed_work_sync(&ddata->adc_poll_work);
        input_unregister_device(input);
        
        sinput_dev = NULL;
index 8f353cfc9453220527133e3ae74bd8a58a2b68bf..eb8f7bd33c99489ff85793d7213047a9c0ec7d95 100755 (executable)
@@ -2,7 +2,7 @@
 # Touchscreen driver configuration
 #
 menuconfig ROCKCHIP_REMOTECTL
-       bool "rkxx remotectl"
+       bool "rockchip remotectl"
        default n
        help
          Say Y here, will suport rk remotectl.
@@ -11,12 +11,7 @@ menuconfig ROCKCHIP_REMOTECTL
          
 if ROCKCHIP_REMOTECTL  
 
-config RK_REMOTECTL
-       bool "rkxx remoctrl"
+config ROCKCHIP_REMOTECTL_PWM
+    bool "rockchip remoctrl pwm capture"
        default n
-       
-config RK_IR_WAKEUP
-       bool "rkxx remoctrl wakeup"
-       depends on PLAT_RK
-       default n       
 endif
index 0edc158f05c2223d86cbb93f6e589d274a8e9ed5..3b6f4e299ad6e5d14e66ea7165fcd43241b03b8b 100755 (executable)
@@ -4,4 +4,4 @@
 # Each configuration option enables a list of files.
 
 
-obj-$(CONFIG_RK_REMOTECTL)      += rkxx_remotectl.o
+obj-$(CONFIG_ROCKCHIP_REMOTECTL_PWM)      += rockchip_pwm_remotectl.o
diff --git a/drivers/input/remotectl/rkxx_remotectl.c b/drivers/input/remotectl/rkxx_remotectl.c
deleted file mode 100755 (executable)
index 94f6319..0000000
+++ /dev/null
@@ -1,686 +0,0 @@
-\r
-/*\r
- * Driver for keys on GPIO lines capable of generating interrupts.\r
- *\r
- * Copyright 2005 Phil Blundell\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License version 2 as\r
- * published by the Free Software Foundation.\r
- */\r
-\r
-#include <linux/module.h>\r
-#include <linux/init.h>\r
-#include <linux/fs.h>\r
-#include <linux/interrupt.h>\r
-#include <linux/irq.h>\r
-#include <linux/sched.h>\r
-#include <linux/pm.h>\r
-#include <linux/sysctl.h>\r
-#include <linux/proc_fs.h>\r
-#include <linux/delay.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/input.h>\r
-#include <linux/workqueue.h>\r
-#include <linux/adc.h>\r
-#include <asm/gpio.h>\r
-#include <mach/remotectl.h>\r
-#include <mach/iomux.h>\r
-#include <linux/wakelock.h>\r
-#include <linux/suspend.h>\r
-\r
-\r
-#if 1\r
-#define remotectl_dbg(bdata, format, arg...)           \\r
-       dev_printk(KERN_INFO , &bdata->input->dev , format , ## arg)\r
-#else\r
-#define remotectl_dbg(bdata, format, arg...)   \r
-#endif\r
-\r
-extern suspend_state_t get_suspend_state(void);\r
-\r
-struct rkxx_remotectl_suspend_data{\r
-    int suspend_flag;\r
-    int cnt;\r
-    long scanTime[50];\r
-};\r
-\r
-struct rkxx_remote_key_table{\r
-    int scanCode;\r
-       int keyCode;            \r
-};\r
-\r
-struct rkxx_remotectl_button { \r
-    int usercode;\r
-    int nbuttons;\r
-    struct rkxx_remote_key_table *key_table;\r
-};\r
-\r
-struct rkxx_remotectl_drvdata {\r
-    int state;\r
-       int nbuttons;\r
-       int result;\r
-    unsigned long pre_time;\r
-    unsigned long cur_time;\r
-    long int pre_sec;\r
-    long int cur_sec;\r
-    long period;\r
-    int scanData;\r
-    int count;\r
-    int keybdNum;\r
-    int keycode;\r
-    int press;\r
-    int pre_press;\r
-    \r
-    struct input_dev *input;\r
-    struct timer_list timer;\r
-    struct tasklet_struct remote_tasklet;\r
-    struct wake_lock remotectl_wake_lock;\r
-    struct rkxx_remotectl_suspend_data remotectl_suspend_data;\r
-};\r
-\r
-\r
-\r
-//ÌØÊ⹦ÄܼüÖµ¶¨Òå\r
-    //193      //photo\r
-    //194      //video\r
-    //195      //music\r
-    //196      //IE\r
-    //197      //\r
-    //198\r
-    //199\r
-    //200\r
-    \r
-    //183      //rorate_left\r
-    //184      //rorate_right\r
-    //185      //zoom out\r
-    //186      //zoom in\r
-    \r
-static struct rkxx_remote_key_table remote_key_table_meiyu_202[] = {\r
-    {0xB0, KEY_ENTER},//ok = DPAD CENTER\r
-    {0xA2, KEY_BACK}, \r
-    {0xD0, KEY_UP},\r
-    {0x70, KEY_DOWN},\r
-    {0x08, KEY_LEFT},\r
-    {0x88, KEY_RIGHT},  ////////\r
-    {0x42, KEY_HOME},     //home\r
-    {0xA8, KEY_VOLUMEUP},\r
-    {0x38, KEY_VOLUMEDOWN},\r
-    {0xE2, KEY_SEARCH},     //search\r
-    {0xB2, KEY_POWER},     //power off\r
-    {0xC2, KEY_MUTE},       //mute\r
-    {0xC8, KEY_MENU},\r
-\r
-//media ctrl\r
-    {0x78,   0x190},      //play pause\r
-    {0xF8,   0x191},      //pre\r
-    {0x02,   0x192},      //next\r
-\r
-//pic\r
-    {0xB8, 183},          //rorate left\r
-    {0x58, 248},          //rorate right\r
-    {0x68, 185},          //zoom out\r
-    {0x98, 186},          //zoom in\r
-//mouse switch\r
-    {0xf0,388},\r
-//display switch\r
-    {0x82,   0x175},\r
-};\r
-\r
-static struct rkxx_remote_key_table remote_key_table_df[] = {\r
-    {0xf8, KEY_REPLY},\r
-    {0xc0, KEY_BACK}, \r
-    {0xf0, KEY_UP},\r
-    {0xd8, KEY_DOWN},\r
-    {0xd0, KEY_LEFT},\r
-    {0xe8,KEY_RIGHT},  ////////\r
-    {0x90, KEY_VOLUMEDOWN},\r
-    {0x60, KEY_VOLUMEUP},\r
-    {0x80, KEY_HOME},     //home\r
-    {0xe0, 183},          //rorate left\r
-    {0x10, 184},          //rorate right\r
-    {0x20, 185},          //zoom out\r
-    {0xa0, 186},          //zoom in\r
-    {0x70, KEY_MUTE},       //mute\r
-    {0x50, KEY_POWER},     //power off\r
-    {0x40, KEY_SEARCH},     //search\r
-};\r
-\r
-extern suspend_state_t get_suspend_state(void);\r
-\r
-\r
-static struct rkxx_remotectl_button remotectl_button[] = \r
-{\r
-    {  \r
-       .usercode = 0x206, \r
-       .nbuttons =  22, \r
-       .key_table = &remote_key_table_meiyu_202[0],\r
-    },\r
-    {\r
-       .usercode = 0x12ee,\r
-       .nbuttons =  22,\r
-       .key_table = &remote_key_table_meiyu_202[0],\r
-    },\r
-    {  \r
-       .usercode = 0x202, \r
-       .nbuttons =  22, \r
-       .key_table = &remote_key_table_meiyu_202[0],\r
-    },\r
-    {  \r
-       .usercode = 0xdf, \r
-       .nbuttons =  16, \r
-       .key_table = &remote_key_table_df[0],\r
-    },    \r
-    \r
-};\r
-\r
-\r
-static int remotectl_keybdNum_lookup(struct rkxx_remotectl_drvdata *ddata)\r
-{      \r
-    int i;     \r
-\r
-    for (i = 0; i < sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button); i++){               \r
-        if (remotectl_button[i].usercode == (ddata->scanData&0xFFFF)){                 \r
-            ddata->keybdNum = i;\r
-            return 1;\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-\r
-static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)\r
-{      \r
-    int i;     \r
-    unsigned char keyData = ((ddata->scanData >> 8) & 0xff);\r
-\r
-    for (i = 0; i < remotectl_button[ddata->keybdNum].nbuttons; i++){\r
-        if (remotectl_button[ddata->keybdNum].key_table[i].scanCode == keyData){                       \r
-            ddata->keycode = remotectl_button[ddata->keybdNum].key_table[i].keyCode;\r
-            return 1;\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-\r
-static void remotectl_get_pwr_scanData(struct rkxx_remotectl_drvdata *ddata,int *pwr_data,int loop)\r
-{      \r
-    int i;\r
-    int temp_scanCode;\r
-    int temp_pwr_data;\r
-    \r
-    for (i = 0; i < remotectl_button[loop].nbuttons; i++){\r
-        if (remotectl_button[loop].key_table[i].keyCode == KEY_POWER){                 \r
-            temp_scanCode = remotectl_button[loop].key_table[i].scanCode;\r
-            temp_pwr_data = (temp_scanCode<<8)|((~temp_scanCode)&0xFF);\r
-            //printk("pwr data =0x%x\n",temp_pwr_data);\r
-        }\r
-    }\r
-    *pwr_data = temp_pwr_data;\r
-}\r
-\r
-static void remotectl_do_something(unsigned long  data)\r
-{\r
-    struct rkxx_remotectl_drvdata *ddata = (struct rkxx_remotectl_drvdata *)data;\r
-\r
-    switch (ddata->state)\r
-    {\r
-        case RMC_IDLE:\r
-        {\r
-            ;\r
-        }\r
-        break;\r
-        \r
-        case RMC_PRELOAD:\r
-        {\r
-            mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130));\r
-            //printk("RMC_PRELOAD,period=%d\n",ddata->period);\r
-            if ((TIME_PRE_MIN < ddata->period) && (ddata->period < TIME_PRE_MAX)){\r
-                \r
-                ddata->scanData = 0;\r
-                ddata->count = 0;\r
-                ddata->state = RMC_USERCODE;\r
-            }else{\r
-                ddata->state = RMC_PRELOAD;\r
-            }\r
-            ddata->pre_time = ddata->cur_time;\r
-            //mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130));\r
-        }\r
-        break;\r
-        \r
-        case RMC_USERCODE:\r
-        {\r
-            ddata->scanData <<= 1;\r
-            ddata->count ++;\r
-           printk("RMC_USERCODE,period=%d£¬count=%d\n",ddata->period,ddata->count );\r
-            if ((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){\r
-                ddata->scanData |= 0x01;\r
-            }\r
-               \r
-            if (ddata->count == 0x10){//16 bit user code\r
-                printk("u=0x%x\n",((ddata->scanData)&0xFFFF));\r
-                if (remotectl_keybdNum_lookup(ddata)){\r
-                    ddata->state = RMC_GETDATA;\r
-                    ddata->scanData = 0;\r
-                    ddata->count = 0;\r
-                }else{                //user code error\r
-                    ddata->state = RMC_PRELOAD;\r
-                }\r
-            }\r
-        }\r
-        break;\r
-        \r
-        case RMC_GETDATA:\r
-        {\r
-            ddata->count ++;\r
-            ddata->scanData <<= 1;\r
-\r
-          \r
-            if ((TIME_BIT1_MIN < ddata->period) && (ddata->period < TIME_BIT1_MAX)){\r
-                ddata->scanData |= 0x01;\r
-            }           \r
-            if (ddata->count == 0x10){\r
-                //printk("RMC_GETDATA=%x\n",(ddata->scanData&0xFFFF));\r
-\r
-                if ((ddata->scanData&0x0ff) == ((~ddata->scanData >> 8)&0x0ff)){\r
-                    if (remotectl_keycode_lookup(ddata)){\r
-                        ddata->press = 1;\r
-                        /*\r
-                         if (get_suspend_state()==0){\r
-                                input_event(ddata->input, EV_KEY, ddata->keycode, 1);\r
-                                input_sync(ddata->input);\r
-                            }else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){\r
-                                input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);\r
-                                input_sync(ddata->input);\r
-                            }*/\r
-                            //printk("0\n");\r
-                            input_event(ddata->input, EV_KEY, ddata->keycode, 1);\r
-                            input_sync(ddata->input);\r
-                        //input_event(ddata->input, EV_KEY, ddata->keycode, ddata->press);\r
-                               //input_sync(ddata->input);\r
-                        ddata->state = RMC_SEQUENCE;\r
-                    }else{\r
-                        ddata->state = RMC_PRELOAD;\r
-                    }\r
-                }else{\r
-                    ddata->state = RMC_PRELOAD;\r
-                }\r
-            }\r
-        }\r
-        break;\r
-             \r
-        case RMC_SEQUENCE:{\r
-\r
-            //printk( "S=%d\n",ddata->period);\r
-  \r
-            if ((TIME_RPT_MIN < ddata->period) && (ddata->period < TIME_RPT_MAX)){\r
-                        mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110));\r
-                 //printk("1\n");;\r
-            }else if ((TIME_SEQ1_MIN < ddata->period) && (ddata->period < TIME_SEQ1_MAX)){\r
-                                                                 mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110));\r
-                                                                 //printk("2\n");\r
-            }else if ((TIME_SEQ2_MIN < ddata->period) && (ddata->period < TIME_SEQ2_MAX)){\r
-                         mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(110));\r
-                         //printk("3\n");;   \r
-            }else{\r
-                        input_event(ddata->input, EV_KEY, ddata->keycode, 0);\r
-                              input_sync(ddata->input);\r
-                        ddata->state = RMC_PRELOAD;\r
-                        ddata->press = 0;\r
-                        //printk("4\n");\r
-            }\r
-        }\r
-        break;\r
-       \r
-        default:\r
-            break;\r
-    } \r
-       return;\r
-}\r
-\r
-\r
-#ifdef CONFIG_PM\r
-void remotectl_wakeup(unsigned long _data)\r
-{\r
-    struct rkxx_remotectl_drvdata *ddata =  (struct rkxx_remotectl_drvdata*)_data;\r
-    long *time;\r
-    int i;\r
-       int power_scanData;\r
-                \r
-    time = ddata->remotectl_suspend_data.scanTime;\r
-\r
-    if (get_suspend_state()){\r
-        ddata->remotectl_suspend_data.suspend_flag = 0;\r
-        ddata->count = 0;\r
-        ddata->state = RMC_USERCODE;\r
-        ddata->scanData = 0;\r
-        \r
-        for (i=0;i<ddata->remotectl_suspend_data.cnt;i++){\r
-                       if (ddata->count>=32)\r
-                               break;\r
-\r
-           if ((TIME_BIT1_MIN < time[i]) && (time[i] < TIME_BIT1_MAX)){\r
-                ddata->scanData |= 0x01;\r
-                ddata->scanData <<= 1;\r
-                ddata->count ++;;\r
-            }else if ((TIME_BIT0_MIN < time[i]) && (time[i] < TIME_BIT0_MAX)){\r
-                 ddata->scanData <<= 1;\r
-                 ddata->count ++;;\r
-            }/*else{\r
-                  if (ddata->count>16){\r
-                         break;\r
-                  }else{\r
-                       \r
-                       printk(KERN_ERR "ddata->count=0x%x**********************\n",ddata->count);\r
-                       ddata->count = 0;\r
-                       ddata->scanData = 0;\r
-                  }            \r
-            }*/\r
-        }\r
-        //printk(KERN_ERR"data=0x%x\n",ddata->scanData);\r
-        if (ddata->scanData)                                   //(ddata->scanData>16)                  \r
-                               {\r
-                                         ddata->scanData=(ddata->scanData>>1)&0xFFFF;                          \r
-                                         printk(KERN_ERR"data=0x%x\n",ddata->scanData);\r
-                                         \r
-                                         for (i=0;i<sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);i++){\r
-                                               remotectl_get_pwr_scanData(ddata,&power_scanData,i);\r
-                                               if ((ddata->scanData == power_scanData)||((ddata->scanData&0x0fff) == (power_scanData&0x0fff))||((ddata->scanData&0x00ff) == (power_scanData&0x00ff)))                                  //modified by zwm       2013.06.19\r
-                                           {\r
-                                               input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);\r
-                       input_sync(ddata->input);\r
-                       input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);\r
-                       input_sync(ddata->input);\r
-                       break;\r
-                                           }\r
-                                         }\r
-                               }\r
-    }\r
-    memset(ddata->remotectl_suspend_data.scanTime,0,50*sizeof(long));\r
-    ddata->remotectl_suspend_data.cnt= 0; \r
-    ddata->state = RMC_PRELOAD;\r
-    \r
-}\r
-\r
-#endif\r
-\r
-\r
-static void remotectl_timer(unsigned long _data)\r
-{\r
-    struct rkxx_remotectl_drvdata *ddata =  (struct rkxx_remotectl_drvdata*)_data;\r
-    \r
-    //printk("to\n");\r
-    \r
-    if(ddata->press != ddata->pre_press) {\r
-        ddata->pre_press = ddata->press = 0;\r
-        \r
-                               input_event(ddata->input, EV_KEY, ddata->keycode, 0);\r
-        input_sync(ddata->input);\r
-        //printk("5\n");\r
-        //if (get_suspend_state()==0){\r
-            //input_event(ddata->input, EV_KEY, ddata->keycode, 1);\r
-            //input_sync(ddata->input);\r
-            //input_event(ddata->input, EV_KEY, ddata->keycode, 0);\r
-                   //input_sync(ddata->input);\r
-        //}else if ((get_suspend_state())&&(ddata->keycode==KEY_POWER)){\r
-            //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 1);\r
-            //input_sync(ddata->input);\r
-            //input_event(ddata->input, EV_KEY, KEY_WAKEUP, 0);\r
-            //input_sync(ddata->input);\r
-        //}\r
-    }\r
-#ifdef CONFIG_PM\r
-    remotectl_wakeup(_data);\r
-#endif\r
-    ddata->state = RMC_PRELOAD;\r
-}\r
-\r
-\r
-\r
-static irqreturn_t remotectl_isr(int irq, void *dev_id)\r
-{\r
-    struct rkxx_remotectl_drvdata *ddata =  (struct rkxx_remotectl_drvdata*)dev_id;\r
-    struct timeval  ts;\r
-\r
-\r
-    ddata->pre_time = ddata->cur_time;\r
-    ddata->pre_sec = ddata->cur_sec;\r
-    do_gettimeofday(&ts);\r
-    ddata->cur_time = ts.tv_usec;\r
-    ddata->cur_sec = ts.tv_sec;\r
-    \r
-               if (likely(ddata->cur_sec == ddata->pre_sec)){\r
-                       ddata->period =  ddata->cur_time - ddata->pre_time;\r
-         }else{\r
-                               ddata->period =  1000000 - ddata->pre_time + ddata->cur_time;\r
-               }\r
-\r
-    tasklet_hi_schedule(&ddata->remote_tasklet); \r
-    //if ((ddata->state==RMC_PRELOAD)||(ddata->state==RMC_SEQUENCE))\r
-    //mod_timer(&ddata->timer,jiffies + msecs_to_jiffies(130));\r
-#ifdef CONFIG_PM\r
-   if (ddata->state==RMC_PRELOAD)\r
-       wake_lock_timeout(&ddata->remotectl_wake_lock, HZ);\r
-   if ((get_suspend_state())&&(ddata->remotectl_suspend_data.cnt<50))          //zwm\r
-       ddata->remotectl_suspend_data.scanTime[ddata->remotectl_suspend_data.cnt++] = ddata->period;\r
-#endif\r
-\r
-    return IRQ_HANDLED;\r
-}\r
-\r
-\r
-static int __devinit remotectl_probe(struct platform_device *pdev)\r
-{\r
-    struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
-    struct rkxx_remotectl_drvdata *ddata;\r
-    struct input_dev *input;\r
-    int i, j;\r
-    int irq;\r
-    int error = 0;\r
-\r
-    printk("++++++++remotectl_probe\n");\r
-\r
-    if(!pdata) \r
-        return -EINVAL;\r
-\r
-    ddata = kzalloc(sizeof(struct rkxx_remotectl_drvdata),GFP_KERNEL);\r
-    memset(ddata,0,sizeof(struct rkxx_remotectl_drvdata));\r
-\r
-    ddata->state = RMC_PRELOAD;\r
-    input = input_allocate_device();\r
-    \r
-    if (!ddata || !input) {\r
-        error = -ENOMEM;\r
-        goto fail0;\r
-    }\r
-\r
-    platform_set_drvdata(pdev, ddata);\r
-\r
-    input->name = pdev->name;\r
-    input->phys = "gpio-keys/input0";\r
-    input->dev.parent = &pdev->dev;\r
-\r
-    input->id.bustype = BUS_HOST;\r
-    input->id.vendor = 0x0001;\r
-    input->id.product = 0x0001;\r
-    input->id.version = 0x0100;\r
-\r
-       /* Enable auto repeat feature of Linux input subsystem */\r
-       if (pdata->rep)\r
-               __set_bit(EV_REP, input->evbit);\r
-    \r
-       ddata->nbuttons = pdata->nbuttons;\r
-       ddata->input = input;\r
-  wake_lock_init(&ddata->remotectl_wake_lock, WAKE_LOCK_SUSPEND, "rk29_remote");\r
-  if (pdata->set_iomux){\r
-       pdata->set_iomux();\r
-  }\r
-  error = gpio_request(pdata->gpio, "remotectl");\r
-       if (error < 0) {\r
-               printk("gpio-keys: failed to request GPIO %d,"\r
-               " error %d\n", pdata->gpio, error);\r
-               //goto fail1;\r
-       }\r
-       error = gpio_direction_input(pdata->gpio);\r
-       if (error < 0) {\r
-               pr_err("gpio-keys: failed to configure input"\r
-                       " direction for GPIO %d, error %d\n",\r
-               pdata->gpio, error);\r
-               gpio_free(pdata->gpio);\r
-               //goto fail1;\r
-       }\r
-    irq = gpio_to_irq(pdata->gpio);\r
-       if (irq < 0) {\r
-               error = irq;\r
-               pr_err("gpio-keys: Unable to get irq number for GPIO %d, error %d\n",\r
-               pdata->gpio, error);\r
-               gpio_free(pdata->gpio);\r
-               goto fail1;\r
-       }\r
-       \r
-       error = request_irq(irq, remotectl_isr, IRQF_TRIGGER_FALLING , "remotectl", ddata);\r
-       \r
-       if (error) {\r
-               pr_err("gpio-remotectl: Unable to claim irq %d; error %d\n", irq, error);\r
-               gpio_free(pdata->gpio);\r
-               goto fail1;\r
-       }\r
-    setup_timer(&ddata->timer,remotectl_timer, (unsigned long)ddata);\r
-    \r
-    tasklet_init(&ddata->remote_tasklet, remotectl_do_something, (unsigned long)ddata);\r
-    \r
-    for (j=0;j<sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);j++){ \r
-       printk("remotectl probe j=0x%x\n",j);\r
-               for (i = 0; i < remotectl_button[j].nbuttons; i++) {\r
-                       unsigned int type = EV_KEY;\r
-               \r
-                       input_set_capability(input, type, remotectl_button[j].key_table[i].keyCode);\r
-               }\r
-  }\r
-       error = input_register_device(input);\r
-       if (error) {\r
-               pr_err("gpio-keys: Unable to register input device, error: %d\n", error);\r
-               goto fail2;\r
-       }\r
-    \r
-    input_set_capability(input, EV_KEY, KEY_WAKEUP);\r
-\r
-       device_init_wakeup(&pdev->dev, 1);\r
-\r
-       return 0;\r
-\r
-fail2:\r
-    pr_err("gpio-remotectl input_allocate_device fail\n");\r
-       input_free_device(input);\r
-       kfree(ddata);\r
-fail1:\r
-    pr_err("gpio-remotectl gpio irq request fail\n");\r
-    free_irq(gpio_to_irq(pdata->gpio), ddata);\r
-    del_timer_sync(&ddata->timer);\r
-    tasklet_kill(&ddata->remote_tasklet); \r
-    gpio_free(pdata->gpio);\r
-fail0: \r
-    pr_err("gpio-remotectl input_register_device fail\n");\r
-    platform_set_drvdata(pdev, NULL);\r
-\r
-       return error;\r
-}\r
-\r
-static int __devexit remotectl_remove(struct platform_device *pdev)\r
-{\r
-       struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
-       struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);\r
-       struct input_dev *input = ddata->input;\r
-    int irq;\r
-\r
-       device_init_wakeup(&pdev->dev, 0);\r
-    irq = gpio_to_irq(pdata->gpio);\r
-    free_irq(irq, ddata);\r
-    tasklet_kill(&ddata->remote_tasklet); \r
-    gpio_free(pdata->gpio);\r
-\r
-       input_unregister_device(input);\r
-\r
-       return 0;\r
-}\r
-\r
-\r
-#ifdef CONFIG_PM\r
-static int remotectl_suspend(struct device *dev)\r
-{\r
-       struct platform_device *pdev = to_platform_device(dev);\r
-       struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
-    struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);\r
-    \r
-    //ddata->remotectl_suspend_data.suspend_flag = 1;\r
-    ddata->remotectl_suspend_data.cnt = 0;\r
-\r
-       if (device_may_wakeup(&pdev->dev)) {\r
-               if (pdata->wakeup) {\r
-                       int irq = gpio_to_irq(pdata->gpio);\r
-                       enable_irq_wake(irq);\r
-               }\r
-       }\r
-    \r
-       return 0;\r
-}\r
-\r
-static int remotectl_resume(struct device *dev)\r
-{\r
-       struct platform_device *pdev = to_platform_device(dev);\r
-       struct RKxx_remotectl_platform_data *pdata = pdev->dev.platform_data;\r
-\r
-    if (device_may_wakeup(&pdev->dev)) {\r
-        if (pdata->wakeup) {\r
-            int irq = gpio_to_irq(pdata->gpio);\r
-            disable_irq_wake(irq);\r
-        }\r
-    }\r
-\r
-       return 0;\r
-}\r
-\r
-static const struct dev_pm_ops remotectl_pm_ops = {\r
-       .suspend        = remotectl_suspend,\r
-       .resume         = remotectl_resume,\r
-};\r
-#endif\r
-\r
-\r
-\r
-static struct platform_driver remotectl_device_driver = {\r
-       .probe          = remotectl_probe,\r
-       .remove         = __devexit_p(remotectl_remove),\r
-       .driver         = {\r
-               .name   = "rkxx-remotectl",\r
-               .owner  = THIS_MODULE,\r
-#ifdef CONFIG_PM\r
-           .pm = &remotectl_pm_ops,\r
-#endif\r
-       },\r
-\r
-};\r
-\r
-static int  remotectl_init(void)\r
-{\r
-    printk(KERN_INFO "++++++++remotectl_init\n");\r
-    return platform_driver_register(&remotectl_device_driver);\r
-}\r
-\r
-\r
-static void  remotectl_exit(void)\r
-{\r
-       platform_driver_unregister(&remotectl_device_driver);\r
-    printk(KERN_INFO "++++++++remotectl_init\n");\r
-}\r
-\r
-module_init(remotectl_init);\r
-module_exit(remotectl_exit);\r
-\r
-MODULE_LICENSE("GPL");\r
-MODULE_AUTHOR("rockchip");\r
-MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");\r
-MODULE_ALIAS("platform:gpio-keys1");\r
-\r
-\r
diff --git a/drivers/input/remotectl/rockchip_pwm_remotectl.c b/drivers/input/remotectl/rockchip_pwm_remotectl.c
new file mode 100755 (executable)
index 0000000..b1db3dc
--- /dev/null
@@ -0,0 +1,453 @@
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/wakelock.h>
+#include "rockchip_pwm_remotectl.h"
+
+
+
+/*sys/module/rk_pwm_remotectl/parameters,
+modify code_print to change the value*/
+
+static int rk_remote_print_code;
+module_param_named(code_print, rk_remote_print_code, int, 0644);
+#define DBG_CODE(args...) \
+       do { \
+               if (rk_remote_print_code) { \
+                       pr_info(args); \
+               } \
+       } while (0)
+
+static int rk_remote_pwm_dbg_level;
+module_param_named(dbg_level, rk_remote_pwm_dbg_level, int, 0644);
+#define DBG(args...) \
+       do { \
+               if (rk_remote_pwm_dbg_level) { \
+                       pr_info(args); \
+               } \
+       } while (0)
+
+
+struct rkxx_remote_key_table {
+       int scancode;
+       int keycode;
+};
+
+struct rkxx_remotectl_button {
+       int usercode;
+       int nbuttons;
+       struct rkxx_remote_key_table *key_table;
+};
+
+struct rkxx_remotectl_drvdata {
+       void __iomem *base;
+       int state;
+       int nbuttons;
+       int result;
+       int scandata;
+       int count;
+       int keynum;
+       int keycode;
+       int press;
+       int pre_press;
+       int period;
+       int irq;
+       int wakeup;
+       struct input_dev *input;
+       struct timer_list timer;
+       struct tasklet_struct remote_tasklet;
+       struct wake_lock remotectl_wake_lock;
+};
+
+
+static struct rkxx_remote_key_table remote_key_table_meiyu_4040[] = {
+       {0xf2, KEY_REPLY},
+       {0xba, KEY_BACK},
+       {0xf4, KEY_UP},
+       {0xf1, KEY_DOWN},
+       {0xef, KEY_LEFT},
+       {0xee, KEY_RIGHT},
+       {0xbd, KEY_HOME},
+       {0xea, KEY_VOLUMEUP},
+       {0xe3, KEY_VOLUMEDOWN},
+       {0xe2, KEY_SEARCH},
+       {0xb2, KEY_POWER},
+       {0xbc, KEY_MUTE},
+       {0xec, KEY_MENU},
+/*lay pause*/
+       {0xbf, 0x190},
+/*pre*/
+       {0xe0, 0x191},
+/*next*/
+       {0xe1, 0x192},
+/*pic,rorate left*/
+       {0xe9, 183},
+/*rorate right*/
+       {0xe6, 248},
+/*zoom out*/
+       {0xe8, 185},
+/*zoom in*/
+       {0xe7, 186},
+/*mouse switch*/
+       {0xb8, 388},
+/*zoom outdisplay switch*/
+       {0xbe, 0x175},
+};
+
+
+static struct rkxx_remote_key_table remote_key_table_sunchip_ff00[] = {
+       {0xf9, KEY_HOME},
+       {0xbf, KEY_BACK},
+       {0xfb, KEY_MENU},
+       {0xaa, KEY_REPLY},
+       {0xb9, KEY_UP},
+       {0xe9, KEY_DOWN},
+       {0xb8, KEY_LEFT},
+       {0xea, KEY_RIGHT},
+       {0xeb, KEY_VOLUMEDOWN},
+       {0xef, KEY_VOLUMEUP},
+       {0xf7, KEY_MUTE},
+       {0xe7, KEY_POWER},
+       {0xfc, KEY_POWER},
+       {0xa9, KEY_VOLUMEDOWN},
+       {0xa8, KEY_VOLUMEDOWN},
+       {0xe0, KEY_VOLUMEDOWN},
+       {0xa5, KEY_VOLUMEDOWN},
+       {0xab, 183},
+       {0xb7, 388},
+       {0xf8, 184},
+       {0xaf, 185},
+       {0xed, KEY_VOLUMEDOWN},
+       {0xee, 186},
+       {0xb3, KEY_VOLUMEDOWN},
+       {0xf1, KEY_VOLUMEDOWN},
+       {0xf2, KEY_VOLUMEDOWN},
+       {0xf3, KEY_SEARCH},
+       {0xb4, KEY_VOLUMEDOWN},
+       {0xbe, KEY_SEARCH},
+};
+
+
+static struct rkxx_remotectl_button remotectl_button[] = {
+       {
+               .usercode = 0xff00,
+               .nbuttons =  29,
+               .key_table = &remote_key_table_sunchip_ff00[0],
+       },
+       {
+               .usercode = 0x4040,
+               .nbuttons =  22,
+               .key_table = &remote_key_table_meiyu_4040[0],
+       },
+};
+
+
+static int remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata *ddata)
+{
+       int i;
+       int num;
+
+       num =  sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);
+       for (i = 0; i < num; i++) {
+               if (remotectl_button[i].usercode == (ddata->scandata&0xFFFF)) {
+                       ddata->keynum = i;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+
+static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)
+{
+       int i;
+       unsigned char keydata = (unsigned char)((ddata->scandata >> 8) & 0xff);
+
+       for (i = 0; i < remotectl_button[ddata->keynum].nbuttons; i++) {
+               if (remotectl_button[ddata->keynum].key_table[i].scancode ==
+                   keydata) {
+                       ddata->keycode =
+                       remotectl_button[ddata->keynum].key_table[i].keycode;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+
+static void rk_pwm_remotectl_do_something(unsigned long  data)
+{
+       struct rkxx_remotectl_drvdata *ddata;
+
+       ddata = (struct rkxx_remotectl_drvdata *)data;
+       switch (ddata->state) {
+       case RMC_IDLE: {
+               ;
+               break;
+       }
+       case RMC_PRELOAD: {
+               mod_timer(&ddata->timer, jiffies + msecs_to_jiffies(130));
+               if ((RK_PWM_TIME_PRE_MIN < ddata->period) &&
+                   (ddata->period < RK_PWM_TIME_PRE_MAX)) {
+                       ddata->scandata = 0;
+                       ddata->count = 0;
+                       ddata->state = RMC_USERCODE;
+               } else {
+                       ddata->state = RMC_PRELOAD;
+               }
+               break;
+       }
+       case RMC_USERCODE: {
+               if ((RK_PWM_TIME_BIT1_MIN < ddata->period) &&
+                   (ddata->period < RK_PWM_TIME_BIT1_MAX))
+                       ddata->scandata |= (0x01 << ddata->count);
+               ddata->count++;
+               if (ddata->count == 0x10) {
+                       DBG_CODE("USERCODE=0x%x\n", ddata->scandata);
+                       if (remotectl_keybd_num_lookup(ddata)) {
+                               ddata->state = RMC_GETDATA;
+                               ddata->scandata = 0;
+                               ddata->count = 0;
+                       } else {
+                               ddata->state = RMC_PRELOAD;
+                       }
+               }
+       }
+       break;
+       case RMC_GETDATA: {
+               if ((RK_PWM_TIME_BIT1_MIN < ddata->period) &&
+                   (ddata->period < RK_PWM_TIME_BIT1_MAX))
+                       ddata->scandata |= (0x01<<ddata->count);
+               ddata->count++;
+               if (ddata->count < 0x10)
+                       return;
+               DBG_CODE("RMC_GETDATA=%x\n", (ddata->scandata>>8));
+               if ((ddata->scandata&0x0ff) ==
+                   ((~ddata->scandata >> 8) & 0x0ff)) {
+                       if (remotectl_keycode_lookup(ddata)) {
+                               ddata->press = 1;
+                               input_event(ddata->input, EV_KEY,
+                                           ddata->keycode, 1);
+                               input_sync(ddata->input);
+                               ddata->state = RMC_SEQUENCE;
+                       } else {
+                               ddata->state = RMC_PRELOAD;
+                       }
+               } else {
+                       ddata->state = RMC_PRELOAD;
+               }
+       }
+       break;
+       case RMC_SEQUENCE:{
+               DBG("S=%d\n", ddata->period);
+               if ((RK_PWM_TIME_RPT_MIN < ddata->period) &&
+                   (ddata->period < RK_PWM_TIME_RPT_MAX)) {
+                       DBG("S1\n");
+                       mod_timer(&ddata->timer, jiffies
+                                 + msecs_to_jiffies(110));
+               } else if ((RK_PWM_TIME_SEQ1_MIN < ddata->period) &&
+                          (ddata->period < RK_PWM_TIME_SEQ1_MAX)) {
+                       DBG("S2\n");
+                       mod_timer(&ddata->timer, jiffies
+                                 + msecs_to_jiffies(110));
+               } else if ((RK_PWM_TIME_SEQ2_MIN < ddata->period) &&
+                         (ddata->period < RK_PWM_TIME_SEQ2_MAX)) {
+                       DBG("S3\n");
+                       mod_timer(&ddata->timer, jiffies
+                                 + msecs_to_jiffies(110));
+               } else {
+                       DBG("S4\n");
+                       input_event(ddata->input, EV_KEY,
+                                   ddata->keycode, 0);
+                       input_sync(ddata->input);
+                       ddata->state = RMC_PRELOAD;
+                       ddata->press = 0;
+               }
+       }
+       break;
+       default:
+       break;
+       }
+}
+
+static void rk_pwm_remotectl_timer(unsigned long _data)
+{
+       struct rkxx_remotectl_drvdata *ddata;
+
+       ddata =  (struct rkxx_remotectl_drvdata *)_data;
+       if (ddata->press != ddata->pre_press) {
+               ddata->pre_press = 0;
+               ddata->press = 0;
+               input_event(ddata->input, EV_KEY, ddata->keycode, 0);
+               input_sync(ddata->input);
+       }
+       ddata->state = RMC_PRELOAD;
+}
+
+
+static irqreturn_t rockchip_pwm_irq(int irq, void *dev_id)
+{
+       struct rkxx_remotectl_drvdata *ddata;
+       int val;
+
+       ddata = (struct rkxx_remotectl_drvdata *)dev_id;
+       val = readl_relaxed(ddata->base + PWM_REG_INTSTS);
+       if (val&PWM_CH3_INT) {
+               if (val & PWM_CH3_POL) {
+                       val = readl_relaxed(ddata->base + PWM_REG_HPR);
+                       ddata->period = val;
+                       tasklet_hi_schedule(&ddata->remote_tasklet);
+                       DBG("hpr=0x%x\n", val);
+               } else {
+                       val = readl_relaxed(ddata->base + PWM_REG_LPR);
+                       DBG("lpr=0x%x\n", val);
+               }
+               writel_relaxed(PWM_CH3_INT, ddata->base + PWM_REG_INTSTS);
+               if (ddata->state == RMC_PRELOAD)
+                       wake_lock_timeout(&ddata->remotectl_wake_lock, HZ);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+static int rk_pwm_remotectl_hw_init(struct rkxx_remotectl_drvdata *ddata)
+{
+       int val;
+
+       val = readl_relaxed(ddata->base + PWM_REG_CTRL);
+       val = (val & 0xFFFFFFFE) | PWM_DISABLE;
+       writel_relaxed(val, ddata->base + PWM_REG_CTRL);
+       val = readl_relaxed(ddata->base + PWM_REG_CTRL);
+       val = (val & 0xFFFFFFF9) | PWM_MODE_CAPTURE;
+       writel_relaxed(val, ddata->base + PWM_REG_CTRL);
+       val = readl_relaxed(ddata->base + PWM_REG_CTRL);
+       val = (val & 0xFF008DFF) | 0x00646200;
+       writel_relaxed(val, ddata->base + PWM_REG_CTRL);
+       val = readl_relaxed(ddata->base + PWM_REG_INT_EN);
+       val = (val & 0xFFFFFFF7) | PWM_CH3_INT_ENABLE;
+       writel_relaxed(val, ddata->base + PWM_REG_INT_EN);
+       val = readl_relaxed(ddata->base + PWM_REG_CTRL);
+       val = (val & 0xFFFFFFFE) | PWM_ENABLE;
+       writel_relaxed(val, ddata->base + PWM_REG_CTRL);
+       return 0;
+}
+
+
+
+static int rk_pwm_probe(struct platform_device *pdev)
+{
+       struct rkxx_remotectl_drvdata *ddata;
+       struct resource *r;
+       struct input_dev *input;
+       struct clk *clk;
+       int num;
+       int irq;
+       int ret;
+       int i, j;
+
+       DBG(".. rk pwm remotectl v1.1 init\n");
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               dev_err(&pdev->dev, "no memory resources defined\n");
+               return -ENODEV;
+       }
+       ddata = devm_kzalloc(&pdev->dev, sizeof(struct rkxx_remotectl_drvdata),
+                            GFP_KERNEL);
+       if (!ddata) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+       ddata->state = RMC_PRELOAD;
+       ddata->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(ddata->base))
+               return PTR_ERR(ddata->base);
+       clk = devm_clk_get(&pdev->dev, "pclk_pwm");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+       platform_set_drvdata(pdev, ddata);
+       input = input_allocate_device();
+       input->name = pdev->name;
+       input->phys = "gpio-keys/remotectl";
+       input->dev.parent = &pdev->dev;
+       input->id.bustype = BUS_HOST;
+       input->id.vendor = 0x0001;
+       input->id.product = 0x0001;
+       input->id.version = 0x0100;
+       ddata->input = input;
+       ddata->input = input;
+       wake_lock_init(&ddata->remotectl_wake_lock,
+                      WAKE_LOCK_SUSPEND, "rk29_pwm_remote");
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               return ret;
+       irq = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot find IRQ\n");
+               return ret;
+       }
+       ddata->irq = irq;
+       ddata->wakeup = 1;
+       tasklet_init(&ddata->remote_tasklet, rk_pwm_remotectl_do_something,
+                    (unsigned long)ddata);
+       num =  sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);
+       for (j = 0; j < num; j++) {
+               DBG("remotectl probe j = 0x%x\n", j);
+               for (i = 0; i < remotectl_button[j].nbuttons; i++) {
+                       unsigned int type = EV_KEY;
+
+                       input_set_capability(input, type, remotectl_button[j].
+                                            key_table[i].keycode);
+               }
+       }
+       ret = input_register_device(input);
+       if (ret)
+               pr_err("remotectl: register input device err, ret: %d\n", ret);
+       input_set_capability(input, EV_KEY, KEY_WAKEUP);
+       device_init_wakeup(&pdev->dev, 1);
+       ret = devm_request_irq(&pdev->dev, irq, rockchip_pwm_irq,
+                              0, "rk_pwm_irq", ddata);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot claim IRQ %d\n", irq);
+               return ret;
+       }
+       enable_irq_wake(irq);
+       setup_timer(&ddata->timer, rk_pwm_remotectl_timer,
+                   (unsigned long)ddata);
+       mod_timer(&ddata->timer, jiffies + msecs_to_jiffies(1000));
+       rk_pwm_remotectl_hw_init(ddata);
+       return ret;
+}
+
+static int rk_pwm_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+
+static const struct of_device_id rk_pwm_of_match[] = {
+       { .compatible =  "rockchip,remotectl-pwm"},
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, rk_pwm_of_match);
+
+static struct platform_driver rk_pwm_driver = {
+       .driver = {
+               .name = "remotectl-pwm",
+               .of_match_table = rk_pwm_of_match,
+       },
+       .probe = rk_pwm_probe,
+       .remove = rk_pwm_remove,
+};
+
+module_platform_driver(rk_pwm_driver);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/remotectl/rockchip_pwm_remotectl.h b/drivers/input/remotectl/rockchip_pwm_remotectl.h
new file mode 100755 (executable)
index 0000000..6cb64ba
--- /dev/null
@@ -0,0 +1,128 @@
+\r
+#ifndef __RKXX_PWM_REMOTECTL_H__\r
+#define __RKXX_PWM_REMOTECTL_H__\r
+#include <linux/input.h>\r
+\r
+/* PWM0 registers  */\r
+#define PWM_REG_CNTR                    0x00  /* Counter Register */\r
+#define PWM_REG_HPR                              0x04  /* Period Register */\r
+#define PWM_REG_LPR                     0x08  /* Duty Cycle Register */\r
+#define PWM_REG_CTRL                    0x0c  /* Control Register */\r
+#define PWM_REG_INTSTS                  0x10  /* Interrupt Status Refister */\r
+#define PWM_REG_INT_EN                  0x14  /* Interrupt Enable Refister */\r
+\r
+\r
+/*REG_CTRL bits definitions*/\r
+#define PWM_ENABLE                                 (1 << 0)\r
+#define PWM_DISABLE                                (0 << 0)\r
+\r
+/*operation mode*/\r
+#define PWM_MODE_ONESHOT                            (0x00 << 1)\r
+#define PWM_MODE_CONTINUMOUS        (0x01 << 1)\r
+#define PWM_MODE_CAPTURE                       (0x02 << 1)\r
+\r
+/*duty cycle output polarity*/\r
+#define PWM_DUTY_POSTIVE                   (0x01 << 3)\r
+#define PWM_DUTY_NEGATIVE                  (0x00 << 3)\r
+\r
+/*incative state output polarity*/\r
+#define PWM_INACTIVE_POSTIVE               (0x01 << 4)\r
+#define PWM_INACTIVE_NEGATIVE              (0x00 << 4)\r
+\r
+/*clock source select*/\r
+#define PWM_CLK_SCALE                      (1 << 9)\r
+#define PWM_CLK_NON_SCALE                  (0 << 9)\r
+\r
+#define PWM_CH0_INT                     (1 << 0)\r
+#define PWM_CH1_INT                     (1 << 1)\r
+#define PWM_CH2_INT                     (1 << 2)\r
+#define PWM_CH3_INT                     (1 << 3)\r
+\r
+#define PWM_CH0_POL                     (1 << 8)\r
+#define PWM_CH1_POL                     (1 << 9)\r
+#define PWM_CH2_POL                     (1 << 10)\r
+#define PWM_CH3_POL                     (1 << 11)\r
+\r
+#define PWM_CH0_INT_ENABLE              (1 << 0)\r
+#define PWM_CH0_INT_DISABLE             (0 << 0)\r
+\r
+#define PWM_CH1_INT_ENABLE              (1 << 0)\r
+#define PWM_CH1_INT_DISABLE             (0 << 1)\r
+\r
+#define PWM_CH2_INT_ENABLE              (1 << 2)\r
+#define PWM_CH2_INT_DISABLE             (0 << 2)\r
+\r
+#define PWM_CH3_INT_ENABLE              (1 << 3)\r
+#define PWM_CH3_INT_DISABLE             (0 << 3)\r
+\r
+/*prescale factor*/\r
+#define PWMCR_MIN_PRESCALE                 0x00\r
+#define PWMCR_MAX_PRESCALE                 0x07\r
+\r
+#define PWMDCR_MIN_DUTY                        0x0001\r
+#define PWMDCR_MAX_DUTY                            0xFFFF\r
+\r
+#define PWMPCR_MIN_PERIOD                      0x0001\r
+#define PWMPCR_MAX_PERIOD                      0xFFFF\r
+\r
+#define PWMPCR_MIN_PERIOD                      0x0001\r
+#define PWMPCR_MAX_PERIOD                      0xFFFF\r
+\r
+enum pwm_div {\r
+        PWM_DIV1                 = (0x0 << 12),\r
+        PWM_DIV2                 = (0x1 << 12),\r
+        PWM_DIV4                 = (0x2 << 12),\r
+        PWM_DIV8                 = (0x3 << 12),\r
+        PWM_DIV16                = (0x4 << 12),\r
+        PWM_DIV32                = (0x5 << 12),\r
+        PWM_DIV64                = (0x6 << 12),\r
+        PWM_DIV128              = (0x7 << 12),\r
+}; \r
+\r
+\r
+\r
+\r
+/********************************************************************\r
+**                            ºê¶¨Òå                                *\r
+********************************************************************/\r
+#define RK_PWM_TIME_PRE_MIN      19   /*4500*/\r
+#define RK_PWM_TIME_PRE_MAX      30   /*5500*/           /*PreLoad 4.5+0.56 = 5.06ms*/\r
+\r
+#define RK_PWM_TIME_BIT0_MIN     1  /*Bit0  1.125ms*/\r
+#define RK_PWM_TIME_BIT0_MAX     5\r
+\r
+#define RK_PWM_TIME_BIT1_MIN     7  /*Bit1  2.25ms*/\r
+#define RK_PWM_TIME_BIT1_MAX     11\r
+\r
+#define RK_PWM_TIME_RPT_MIN      200   /*101000*/\r
+#define RK_PWM_TIME_RPT_MAX      250   /*103000*/         /*Repeat  105-2.81=102.19ms*/  //110-9-2.25-0.56=98.19ms\r
+\r
+#define RK_PWM_TIME_SEQ1_MIN     8   /*2650*/\r
+#define RK_PWM_TIME_SEQ1_MAX     12   /*3000*/           /*sequence  2.25+0.56=2.81ms*/ //11.25ms\r
+\r
+#define RK_PWM_TIME_SEQ2_MIN     450   /*101000*/\r
+#define RK_PWM_TIME_SEQ2_MAX     500   /*103000*/         /*Repeat  105-2.81=102.19ms*/  //110-9-2.25-0.56=98.19ms\r
+\r
+/********************************************************************\r
+**                          ½á¹¹¶¨Òå                                *\r
+********************************************************************/\r
+typedef enum _RMC_STATE\r
+{\r
+    RMC_IDLE,\r
+    RMC_PRELOAD,\r
+    RMC_USERCODE,\r
+    RMC_GETDATA,\r
+    RMC_SEQUENCE\r
+}eRMC_STATE;\r
+\r
+\r
+struct RKxx_remotectl_platform_data {\r
+       //struct rkxx_remotectl_button *buttons;\r
+       int nbuttons;\r
+       int rep;\r
+       int timer;\r
+       int wakeup;\r
+};\r
+\r
+#endif\r
+\r
diff --git a/drivers/input/touchscreen/vtl_ts/LX20JS06_A1_CT363_V03_5198_121015.dat b/drivers/input/touchscreen/vtl_ts/LX20JS06_A1_CT363_V03_5198_121015.dat
new file mode 100755 (executable)
index 0000000..dd2c3d8
--- /dev/null
@@ -0,0 +1,4096 @@
+  0x02, 0x65, 0x1E, 0x02, 0x00, 0x3F, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x02, 0x78, 0xC9, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x02, 0x27, 0xFF, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x02, 0x65, 0x17, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x02, 0x64, 0xE8, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x02, 0x78, 0xA0, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x02, 0x27, 0xFC, 0x75, 0x86,\r
+  0x09, 0x75, 0x84, 0x9C, 0xD2, 0xA9, 0x22, 0x32,\r
+  0x90, 0x3F, 0xF0, 0x74, 0x56, 0xF0, 0xA3, 0x74,\r
+  0x54, 0xF0, 0xA3, 0x74, 0x4C, 0xF0, 0x22, 0x78,\r
+  0xE4, 0x7C, 0x12, 0x7D, 0x01, 0x7B, 0xFF, 0x7A,\r
+  0x78, 0x79, 0x7D, 0x7E, 0x00, 0x7F, 0x05, 0x12,\r
+  0x59, 0x49, 0x90, 0x12, 0xF2, 0x12, 0x5B, 0x94,\r
+  0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x12, 0xF6, 0x12,\r
+  0x5B, 0x94, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0A,\r
+  0x7C, 0x13, 0x7D, 0x01, 0x7B, 0xFF, 0x7A, 0x78,\r
+  0x79, 0x82, 0x7E, 0x00, 0x7F, 0x0A, 0x12, 0x59,\r
+  0x49, 0x78, 0x14, 0x7C, 0x13, 0x7D, 0x01, 0x7B,\r
+  0xFF, 0x7A, 0x78, 0x79, 0x8C, 0x7E, 0x00, 0x7F,\r
+  0x14, 0x12, 0x59, 0x49, 0xC2, 0x1A, 0xE4, 0x90,\r
+  0xED, 0x9F, 0x0F, 0x6F, 0xED, 0x6D, 0x0F, 0x6F,\r
+  0xED, 0x6C, 0x0F, 0x6F, 0xEC, 0xF6, 0x8B, 0xFC,\r
+  0xF0, 0x30, 0x15, 0x0A, 0x90, 0x88, 0xB0, 0xE0,\r
+  0x90, 0x88, 0xC1, 0xF0, 0x80, 0x05, 0xE4, 0x90,\r
+  0x88, 0xC1, 0xF0, 0xE4, 0x90, 0x12, 0xDF, 0xF0,\r
+  0xC2, 0x0F, 0xC2, 0x11, 0x90, 0x13, 0x09, 0xE0,\r
+  0xFF, 0x90, 0x88, 0xC1, 0xE0, 0xD3, 0x9F, 0x40,\r
+  0x03, 0x02, 0x03, 0xB1, 0x90, 0x88, 0xC0, 0xE0,\r
+  0x9F, 0x40, 0x03, 0x02, 0x03, 0xB1, 0xE4, 0xF0,\r
+  0x75, 0x9E, 0x55, 0x90, 0x12, 0xDB, 0xF0, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFF, 0xC3, 0x95, 0x0D, 0x40,\r
+  0x03, 0x02, 0x03, 0x71, 0x75, 0x9E, 0x55, 0x74,\r
+  0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0xE0, 0x64, 0x01, 0x60, 0x15, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x24, 0xE5, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x88, 0xF5, 0x83, 0xE0, 0x64, 0x02, 0x60, 0x03,\r
+  0x02, 0x03, 0x59, 0x90, 0x12, 0xDB, 0xE0, 0xFF,\r
+  0x90, 0x88, 0xC0, 0xE0, 0x24, 0x04, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x13, 0xF5, 0x83, 0xEF, 0xF0, 0x74,\r
+  0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0x74, 0x04, 0xF0, 0xE4, 0x90, 0x12, 0xDC,\r
+  0xF0, 0x90, 0x88, 0xC1, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDC, 0xE0, 0xFE, 0xC3, 0x9F, 0x40, 0x03, 0x02,\r
+  0x03, 0x51, 0x75, 0x9E, 0x55, 0x90, 0x12, 0xDB,\r
+  0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0xC3, 0x9D,\r
+  0xEA, 0x9C, 0x40, 0x36, 0xEF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90,\r
+  0x12, 0xDC, 0xE0, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xC3, 0x9F, 0xFF, 0xEC,\r
+  0x9E, 0x90, 0x12, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x80, 0x37, 0x90, 0x12, 0xDC, 0xE0, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xC3, 0x9F, 0xFF,\r
+  0xEC, 0x9E, 0x90, 0x12, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0x90, 0x12, 0xDB, 0xE0, 0xFF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0x90, 0x12, 0xDC, 0xE0, 0xFE, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0xC3, 0x9D,\r
+  0xEA, 0x9C, 0x40, 0x33, 0xEF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82,\r
+  0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xC3, 0x9D, 0xFF, 0xEE, 0x9C, 0x90, 0x12,\r
+  0xF0, 0xF0, 0xA3, 0xEF, 0xF0, 0x80, 0x37, 0x90,\r
+  0x12, 0xDC, 0xE0, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x12, 0xDB,\r
+  0xE0, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xC3, 0x9F, 0xFF, 0xEC, 0x9E, 0x90,\r
+  0x12, 0xF0, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xF0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xFB, 0xAA,\r
+  0x06, 0xE4, 0xF9, 0xF8, 0x90, 0x12, 0xF0, 0xE0,\r
+  0xA3, 0xE0, 0xE4, 0xFC, 0xFD, 0x12, 0x5A, 0x34,\r
+  0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07,\r
+  0x90, 0x12, 0xEE, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xFB, 0xAA, 0x06, 0xE4, 0xF9, 0xF8, 0x90, 0x12,\r
+  0xEE, 0xE0, 0xA3, 0xE0, 0xE4, 0xFC, 0xFD, 0x12,\r
+  0x5A, 0x34, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01,\r
+  0xD0, 0x00, 0xEF, 0x2B, 0xFF, 0xEE, 0x3A, 0xFE,\r
+  0xED, 0x39, 0xFD, 0xEC, 0x38, 0xFC, 0x90, 0x88,\r
+  0xC0, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0,\r
+  0x83, 0xC0, 0x82, 0x90, 0x12, 0xDC, 0xE0, 0xD0,\r
+  0x82, 0xD0, 0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B,\r
+  0xC5, 0x12, 0x5B, 0x88, 0x90, 0x88, 0xC0, 0xE0,\r
+  0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0,\r
+  0x82, 0x90, 0x12, 0xDC, 0xE0, 0xD0, 0x82, 0xD0,\r
+  0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xE4, 0x7B, 0x32, 0xFA, 0xF9, 0xF8,\r
+  0xD3, 0x12, 0x5B, 0x51, 0x40, 0x02, 0xD2, 0x1A,\r
+  0x90, 0x12, 0xDC, 0xE0, 0x04, 0xF0, 0x02, 0x01,\r
+  0x49, 0x90, 0x88, 0xC0, 0xE0, 0x04, 0xF0, 0x80,\r
+  0x0F, 0x90, 0x12, 0xDB, 0xE0, 0x24, 0xE5, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x04, 0xF0, 0x02, 0x00,\r
+  0xEF, 0xE4, 0x90, 0x12, 0xDC, 0xF0, 0x90, 0x13,\r
+  0x09, 0xE0, 0xFF, 0x90, 0x12, 0xDC, 0xE0, 0xFE,\r
+  0xC3, 0x9F, 0x50, 0x2D, 0x90, 0x88, 0xC1, 0xE0,\r
+  0xFF, 0xEE, 0xC3, 0x9F, 0x50, 0x0F, 0x74, 0xA0,\r
+  0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83,\r
+  0x74, 0x01, 0xF0, 0x80, 0x0C, 0x74, 0xA0, 0x2E,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xE4,\r
+  0xF0, 0x90, 0x12, 0xDC, 0xE0, 0x04, 0xF0, 0x80,\r
+  0xC5, 0x75, 0x9E, 0x55, 0x90, 0x13, 0x09, 0xE0,\r
+  0xFF, 0x90, 0x88, 0xC1, 0xE0, 0xD3, 0x9F, 0x40,\r
+  0x03, 0x02, 0x1B, 0x20, 0x90, 0x88, 0xC0, 0xE0,\r
+  0x9F, 0x40, 0x03, 0x02, 0x1B, 0x20, 0x30, 0x1A,\r
+  0x03, 0x02, 0x1B, 0x20, 0xE0, 0x94, 0x00, 0x50,\r
+  0x03, 0x02, 0x18, 0x51, 0x90, 0x88, 0xC1, 0xE0,\r
+  0xD3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x18, 0x51,\r
+  0xE0, 0xFF, 0x90, 0x88, 0xC0, 0xE0, 0xD3, 0x9F,\r
+  0x40, 0x03, 0x02, 0x0E, 0x23, 0x90, 0x88, 0xC0,\r
+  0xE0, 0x24, 0xE3, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x88, 0xC1, 0xE0,\r
+  0xFE, 0xEF, 0x6E, 0x70, 0x03, 0x02, 0x06, 0x01,\r
+  0x75, 0x9E, 0x55, 0xE4, 0x90, 0x12, 0xDA, 0xF0,\r
+  0x90, 0x88, 0xC1, 0xE0, 0xFF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFE, 0xC3, 0x9F, 0x50, 0x14, 0x74, 0xE9,\r
+  0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE4, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0,\r
+  0x80, 0xDE, 0xC2, 0x19, 0xE4, 0x90, 0x12, 0xDA,\r
+  0xF0, 0x90, 0x88, 0xC0, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFE, 0xC3, 0x9F, 0x50, 0x4E, 0x74,\r
+  0xE4, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xFF, 0x90, 0x88, 0xC1, 0xE0, 0xFE,\r
+  0xEF, 0xB5, 0x06, 0x04, 0xD2, 0x19, 0x80, 0x35,\r
+  0x74, 0xE9, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xE0, 0x70, 0x1C, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x24, 0xE4, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xE0, 0x24, 0xE9, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x12, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x80,\r
+  0x04, 0xD2, 0x19, 0x80, 0x08, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x04, 0xF0, 0x80, 0xA4, 0x90, 0x12, 0xF6,\r
+  0x12, 0x5B, 0x94, 0x00, 0x00, 0x00, 0x00, 0x30,\r
+  0x19, 0x03, 0x02, 0x05, 0x9E, 0xE4, 0x90, 0x12,\r
+  0xDA, 0xF0, 0x90, 0x88, 0xC0, 0xE0, 0xFF, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xFE, 0xC3, 0x9F, 0x50, 0x77,\r
+  0xE0, 0xFF, 0x24, 0xE4, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0xFA, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xED,\r
+  0xF0, 0x90, 0x12, 0xF6, 0xE0, 0xF8, 0xA3, 0xE0,\r
+  0xF9, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0xEE,\r
+  0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0,\r
+  0x82, 0x90, 0x12, 0xDA, 0xE0, 0x24, 0xE4, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xD0,\r
+  0x82, 0xD0, 0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B,\r
+  0xC5, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xEB, 0x2F, 0xFF, 0xEA,\r
+  0x3E, 0xFE, 0xE9, 0x3D, 0xFD, 0xE8, 0x3C, 0xFC,\r
+  0x90, 0x12, 0xF6, 0x12, 0x5B, 0x88, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x04, 0xB2, 0x90,\r
+  0x12, 0xF2, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0xF8,\r
+  0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0xFB, 0xC3, 0x12, 0x5B, 0x51, 0x50, 0x47, 0x90,\r
+  0x12, 0xF6, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x12, 0xF2,\r
+  0x12, 0x5B, 0x88, 0xE4, 0x90, 0x12, 0xDA, 0xF0,\r
+  0x90, 0x88, 0xC0, 0xE0, 0xFF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFE, 0xC3, 0x9F, 0x50, 0x20, 0x74, 0xFA,\r
+  0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0xFF, 0x74, 0xFF, 0x2E, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x12, 0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x80, 0xD2, 0xC2, 0x18,\r
+  0xE4, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x88, 0xC0,\r
+  0xE0, 0x14, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFE,\r
+  0xC3, 0x9F, 0x50, 0x3E, 0x74, 0xE4, 0x2E, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xFF,\r
+  0x90, 0x88, 0xC1, 0xE0, 0xFE, 0xEF, 0xB5, 0x06,\r
+  0x21, 0x90, 0x12, 0xDA, 0xE0, 0xFF, 0x24, 0xE4,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4,\r
+  0xF0, 0x74, 0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0x04, 0xF0, 0xD2, 0x18,\r
+  0x80, 0x08, 0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0,\r
+  0x80, 0xB3, 0x30, 0x18, 0x03, 0x02, 0x03, 0xF5,\r
+  0x90, 0x12, 0xE4, 0xE0, 0x04, 0xF0, 0x02, 0x03,\r
+  0xF5, 0x90, 0x88, 0xC0, 0xE0, 0x90, 0x12, 0xE0,\r
+  0xF0, 0xE4, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x12,\r
+  0xE0, 0xE0, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFE,\r
+  0xC3, 0x9F, 0x40, 0x03, 0x02, 0x18, 0x51, 0xE0,\r
+  0xFF, 0x24, 0x04, 0xF5, 0x82, 0xE4, 0x34, 0x13,\r
+  0xF5, 0x83, 0xE0, 0x90, 0x12, 0xE2, 0xF0, 0x74,\r
+  0xFF, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0x90, 0x12, 0xE1, 0xF0, 0xC2, 0x0F,\r
+  0xC2, 0x11, 0xEE, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0xB4, 0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83,\r
+  0xC0, 0x83, 0xC0, 0x82, 0x90, 0x12, 0xE1, 0xE0,\r
+  0xD0, 0x82, 0xD0, 0x83, 0x75, 0xF0, 0x04, 0x12,\r
+  0x5B, 0xC5, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x74, 0xFF, 0xFB,\r
+  0xFA, 0xF9, 0xF8, 0xD3, 0x12, 0x5B, 0x51, 0x50,\r
+  0x03, 0x02, 0x0E, 0x1A, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0,\r
+  0x82, 0x90, 0x12, 0xE1, 0xE0, 0xD0, 0x82, 0xD0,\r
+  0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xE4, 0x7B, 0xE0, 0x7A, 0x2E, 0xF9,\r
+  0xF8, 0xC3, 0x12, 0x5B, 0x51, 0x50, 0x57, 0x90,\r
+  0x12, 0xE1, 0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFE, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xEE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0,\r
+  0xA3, 0xED, 0xF0, 0x02, 0x09, 0xEC, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0,\r
+  0x83, 0xC0, 0x82, 0x90, 0x12, 0xE1, 0xE0, 0xD0,\r
+  0x82, 0xD0, 0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B,\r
+  0xC5, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xE4, 0x7B, 0xB8, 0x7A,\r
+  0x0B, 0xF9, 0xF8, 0xC3, 0x12, 0x5B, 0x51, 0x40,\r
+  0x03, 0x02, 0x08, 0x35, 0x90, 0x12, 0xE1, 0xE0,\r
+  0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xA3, 0xE0,\r
+  0x25, 0xE0, 0xFF, 0x05, 0x82, 0xD5, 0x82, 0x02,\r
+  0x15, 0x83, 0x15, 0x82, 0xE0, 0x33, 0xFE, 0x90,\r
+  0x12, 0xE2, 0xE0, 0xFC, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA,\r
+  0x3E, 0xFE, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E,\r
+  0xFE, 0xEF, 0x78, 0x02, 0xCE, 0xC3, 0x13, 0xCE,\r
+  0x13, 0xD8, 0xF9, 0xFF, 0xEC, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90,\r
+  0x12, 0xE1, 0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xA3, 0xE0, 0x25, 0xE0, 0xFF, 0x05, 0x82,\r
+  0xD5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xE0,\r
+  0x33, 0xFE, 0x90, 0x12, 0xE2, 0xE0, 0xFC, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0x2F, 0xFF, 0xEA, 0x3E, 0xFE, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F,\r
+  0xFF, 0xEA, 0x3E, 0xFE, 0xEF, 0x78, 0x02, 0xCE,\r
+  0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0xEC,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0x02, 0x09, 0xEC, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83,\r
+  0xC0, 0x82, 0x90, 0x12, 0xE1, 0xE0, 0xD0, 0x82,\r
+  0xD0, 0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0xE4, 0x7B, 0xDC, 0x7A, 0x05,\r
+  0xF9, 0xF8, 0xC3, 0x12, 0x5B, 0x51, 0x40, 0x03,\r
+  0x02, 0x09, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0xFD,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x90, 0x12, 0xE1, 0xE0, 0xFC, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0x2F, 0xFF, 0xEA, 0x3E, 0xC3, 0x13, 0xFE, 0xEF,\r
+  0x13, 0xFF, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xEC, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF,\r
+  0xEA, 0x3E, 0xC3, 0x13, 0xFE, 0xEF, 0x13, 0xFF,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x02, 0x09, 0xEC, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xA3, 0xE0, 0x25, 0xE0, 0xFF, 0x05, 0x82, 0xD5,\r
+  0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xE0, 0x33,\r
+  0xFE, 0x90, 0x12, 0xE1, 0xE0, 0xFC, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F,\r
+  0xFF, 0xEA, 0x3E, 0xFE, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF,\r
+  0xEA, 0x3E, 0xFE, 0xEF, 0x78, 0x02, 0xCE, 0xC3,\r
+  0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xA3, 0xE0, 0x25, 0xE0, 0xFF,\r
+  0x05, 0x82, 0xD5, 0x82, 0x02, 0x15, 0x83, 0x15,\r
+  0x82, 0xE0, 0x33, 0xFE, 0xEC, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF,\r
+  0xEC, 0x3E, 0xFE, 0x90, 0x12, 0xE2, 0xE0, 0xFD,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFA, 0xA3,\r
+  0xE0, 0x2F, 0xFF, 0xEA, 0x3E, 0xFE, 0xEF, 0x78,\r
+  0x02, 0xCE, 0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9,\r
+  0xFF, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xC3, 0x9D, 0xFF,\r
+  0xEE, 0x9C, 0xFE, 0x12, 0x78, 0xF1, 0x90, 0x13,\r
+  0x28, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xC3,\r
+  0x9D, 0xFF, 0xEE, 0x9C, 0xFE, 0x12, 0x78, 0xF1,\r
+  0x90, 0x13, 0x2A, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x90, 0x13, 0x2A, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x13, 0x29, 0xE0, 0x2F, 0xFF, 0x90, 0x13,\r
+  0x28, 0xE0, 0x3E, 0xFE, 0x90, 0x13, 0x2C, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xD3, 0x94, 0x0C, 0xEE, 0x94,\r
+  0x00, 0x40, 0x4A, 0x90, 0x12, 0xE2, 0xE0, 0xFF,\r
+  0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xD3, 0x94, 0x04, 0x40, 0x0E, 0x74,\r
+  0x81, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0x24, 0xFC, 0xF0, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFF, 0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0xC3, 0x94, 0x01, 0x50,\r
+  0x0C, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0xF1, 0x0A,\r
+  0x74, 0x01, 0xF0, 0x80, 0x66, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFF, 0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0x04, 0xF0, 0x74, 0x81,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0xD3, 0x94, 0x16, 0x40, 0x18, 0x90, 0x12,\r
+  0xE2, 0xE0, 0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0x74, 0x16, 0xF0, 0x90, 0xF1,\r
+  0x0A, 0x74, 0x02, 0xF0, 0x80, 0x29, 0x90, 0x12,\r
+  0x92, 0xE0, 0xD3, 0x94, 0x00, 0x50, 0x08, 0x90,\r
+  0x12, 0x60, 0xE0, 0x94, 0x00, 0x40, 0x09, 0x30,\r
+  0x04, 0x06, 0x90, 0xF1, 0x0A, 0x74, 0x01, 0xF0,\r
+  0x90, 0x12, 0x93, 0xE0, 0xD3, 0x94, 0x00, 0x40,\r
+  0x06, 0x90, 0xF1, 0x0A, 0x74, 0x01, 0xF0, 0xC2,\r
+  0x0F, 0xC2, 0x11, 0x90, 0x12, 0xE2, 0xE0, 0xFF,\r
+  0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0x90, 0x13, 0x2C, 0xE0, 0xFA,\r
+  0xA3, 0xE0, 0xFB, 0xD3, 0x9D, 0xEA, 0x94, 0x00,\r
+  0x40, 0x13, 0xD2, 0x0F, 0xD2, 0x11, 0x74, 0x77,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0x74, 0x01, 0xF0, 0x80, 0x04, 0xC2, 0x0F, 0xC2,\r
+  0x11, 0x90, 0x12, 0xE2, 0xE0, 0x24, 0x77, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xB4,\r
+  0x01, 0x13, 0xD3, 0xEB, 0x94, 0x01, 0xEA, 0x94,\r
+  0x00, 0x40, 0x06, 0xD2, 0x0F, 0xD2, 0x11, 0x80,\r
+  0x04, 0xC2, 0x0F, 0xC2, 0x11, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFF, 0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0x64, 0x01, 0x60, 0x03,\r
+  0x02, 0x0C, 0x7F, 0x90, 0x12, 0xE1, 0xE0, 0xFE,\r
+  0x24, 0x0A, 0xF5, 0x82, 0xE4, 0x34, 0x13, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0x74, 0xCA, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xC3, 0x9D,\r
+  0x50, 0x4D, 0xC2, 0x0D, 0x90, 0x12, 0xE2, 0xE0,\r
+  0x24, 0x3C, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x24, 0x14,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x13, 0xF5, 0x83, 0xE0,\r
+  0xFA, 0xA3, 0xE0, 0xD3, 0x9D, 0x74, 0x80, 0xF8,\r
+  0xEA, 0x64, 0x80, 0x98, 0x50, 0x10, 0x74, 0xCA,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0x04, 0xF0, 0x02, 0x0C, 0x81, 0x90, 0x12,\r
+  0xE2, 0xE0, 0x24, 0xCA, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x80, 0x72, 0x90,\r
+  0x12, 0xE2, 0xE0, 0xFF, 0x24, 0xC0, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x74,\r
+  0xCA, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x94, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xD2, 0x0D, 0x80, 0x02, 0xD2,\r
+  0x0D, 0x30, 0x01, 0x57, 0x90, 0x12, 0xE1, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0x90, 0x12, 0xE2, 0xE0, 0xFE,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3,\r
+  0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0,\r
+  0x02, 0x0D, 0x60, 0x20, 0x0F, 0x03, 0x02, 0x0D,\r
+  0x60, 0x30, 0x11, 0x7C, 0x30, 0x0D, 0x79, 0x90,\r
+  0x13, 0x2C, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xD3,\r
+  0x94, 0x78, 0xEE, 0x94, 0x00, 0x40, 0x06, 0x90,\r
+  0x12, 0x92, 0xE0, 0x04, 0xF0, 0xD3, 0xEF, 0x94,\r
+  0x72, 0xEE, 0x94, 0x01, 0x40, 0x06, 0x90, 0x12,\r
+  0x93, 0xE0, 0x04, 0xF0, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0,\r
+  0x90, 0x12, 0xE1, 0xE0, 0xFF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x90,\r
+  0x12, 0xE2, 0xE0, 0xFE, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12, 0xE1, 0xE0,\r
+  0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0xE0, 0xFE, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFD, 0x24, 0x14, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0x74, 0x28, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xE0, 0xFF,\r
+  0x74, 0x3C, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0xEF, 0xF0, 0x74, 0xE5, 0x2D, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0x74, 0x02,\r
+  0xF0, 0x90, 0x12, 0xE1, 0xE0, 0x24, 0xA0, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x12, 0xDF, 0xE0, 0x04, 0xF0, 0x90, 0x88,\r
+  0xC0, 0xE0, 0x14, 0xF0, 0x90, 0x88, 0xC1, 0xE0,\r
+  0x14, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0,\r
+  0x02, 0x06, 0x0E, 0x90, 0x88, 0xC1, 0xE0, 0x24,\r
+  0xE3, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0xFF, 0x90, 0x88, 0xC0, 0xE0, 0xFE, 0xEF,\r
+  0x6E, 0x70, 0x03, 0x02, 0x10, 0x2F, 0x75, 0x9E,\r
+  0x55, 0xE4, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x88,\r
+  0xC0, 0xE0, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFE,\r
+  0xC3, 0x9F, 0x50, 0x14, 0x74, 0xE9, 0x2E, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0, 0x80, 0xDE,\r
+  0xC2, 0x19, 0xE4, 0x90, 0x12, 0xDA, 0xF0, 0x90,\r
+  0x88, 0xC1, 0xE0, 0xFF, 0x90, 0x12, 0xDA, 0xE0,\r
+  0xFE, 0xC3, 0x9F, 0x50, 0x4E, 0x74, 0xE4, 0x2E,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0xFF, 0x90, 0x88, 0xC0, 0xE0, 0xFE, 0xEF, 0xB5,\r
+  0x06, 0x04, 0xD2, 0x19, 0x80, 0x35, 0x74, 0xE9,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0x70, 0x1C, 0x90, 0x12, 0xDA, 0xE0, 0x24,\r
+  0xE4, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0x24, 0xE9, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0x74, 0x01, 0xF0, 0x80, 0x04, 0xD2,\r
+  0x19, 0x80, 0x08, 0x90, 0x12, 0xDA, 0xE0, 0x04,\r
+  0xF0, 0x80, 0xA4, 0x90, 0x12, 0xF6, 0x12, 0x5B,\r
+  0x94, 0x00, 0x00, 0x00, 0x00, 0x30, 0x19, 0x03,\r
+  0x02, 0x0F, 0xCC, 0xE4, 0x90, 0x12, 0xDA, 0xF0,\r
+  0x90, 0x88, 0xC1, 0xE0, 0xFF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFE, 0xC3, 0x9F, 0x50, 0x77, 0xE0, 0xFF,\r
+  0x24, 0xE4, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0x74, 0xFA, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xED, 0xF0, 0x90,\r
+  0x12, 0xF6, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9, 0xA3,\r
+  0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0x74, 0xE4, 0x2E,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0,\r
+  0x82, 0x90, 0x12, 0xDA, 0xE0, 0xD0, 0x82, 0xD0,\r
+  0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xEB, 0x2F, 0xFF, 0xEA, 0x3E, 0xFE,\r
+  0xE9, 0x3D, 0xFD, 0xE8, 0x3C, 0xFC, 0x90, 0x12,\r
+  0xF6, 0x12, 0x5B, 0x88, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x04, 0xF0, 0x02, 0x0E, 0xE0, 0x90, 0x12, 0xF2,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0xA3, 0xE0, 0xF8, 0xA3, 0xE0,\r
+  0xF9, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0xC3,\r
+  0x12, 0x5B, 0x51, 0x50, 0x47, 0x90, 0x12, 0xF6,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x90, 0x12, 0xF2, 0x12, 0x5B,\r
+  0x88, 0xE4, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x88,\r
+  0xC1, 0xE0, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFE,\r
+  0xC3, 0x9F, 0x50, 0x20, 0x74, 0xFA, 0x2E, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xFF,\r
+  0x74, 0xFF, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x04, 0xF0, 0x80, 0xD2, 0xC2, 0x18, 0xE4, 0x90,\r
+  0x12, 0xDA, 0xF0, 0x90, 0x88, 0xC1, 0xE0, 0x14,\r
+  0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFE, 0xC3, 0x9F,\r
+  0x50, 0x3E, 0x74, 0xE4, 0x2E, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x12, 0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x88,\r
+  0xC0, 0xE0, 0xFE, 0xEF, 0xB5, 0x06, 0x21, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xFF, 0x24, 0xE4, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x74,\r
+  0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0x04, 0xF0, 0xD2, 0x18, 0x80, 0x08,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0, 0x80, 0xB3,\r
+  0x30, 0x18, 0x03, 0x02, 0x0E, 0x23, 0x90, 0x12,\r
+  0xE4, 0xE0, 0x04, 0xF0, 0x02, 0x0E, 0x23, 0x90,\r
+  0x88, 0xC1, 0xE0, 0x90, 0x12, 0xE0, 0xF0, 0xE4,\r
+  0x90, 0x12, 0xDA, 0xF0, 0x90, 0x12, 0xE0, 0xE0,\r
+  0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xC3, 0x9F, 0x40,\r
+  0x03, 0x02, 0x18, 0x51, 0xE0, 0xFF, 0x24, 0xFF,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0x24, 0x04, 0xF5, 0x82, 0xE4, 0x34, 0x13,\r
+  0xF5, 0x83, 0xE0, 0x90, 0x12, 0xE2, 0xF0, 0x90,\r
+  0x12, 0xE1, 0xEF, 0xF0, 0xC2, 0x0F, 0xC2, 0x11,\r
+  0xEE, 0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83,\r
+  0xC0, 0x82, 0x90, 0x12, 0xDA, 0xE0, 0xD0, 0x82,\r
+  0xD0, 0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x74, 0xFF, 0xFB, 0xFA, 0xF9,\r
+  0xF8, 0xD3, 0x12, 0x5B, 0x51, 0x50, 0x03, 0x02,\r
+  0x18, 0x48, 0x90, 0x12, 0xDA, 0xE0, 0x75, 0xF0,\r
+  0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0, 0x82, 0x90,\r
+  0x12, 0xE1, 0xE0, 0xD0, 0x82, 0xD0, 0x83, 0x75,\r
+  0xF0, 0x04, 0x12, 0x5B, 0xC5, 0xE0, 0xFC, 0xA3,\r
+  0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xE4, 0x7B, 0xE0, 0x7A, 0x2E, 0xF9, 0xF8, 0xC3,\r
+  0x12, 0x5B, 0x51, 0x50, 0x57, 0x90, 0x12, 0xE1,\r
+  0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0,\r
+  0xA3, 0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED,\r
+  0xF0, 0x02, 0x14, 0x1A, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x75, 0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0,\r
+  0x82, 0x90, 0x12, 0xE1, 0xE0, 0xD0, 0x82, 0xD0,\r
+  0x83, 0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xE4, 0x7B, 0xB8, 0x7A, 0x0B, 0xF9,\r
+  0xF8, 0xC3, 0x12, 0x5B, 0x51, 0x40, 0x03, 0x02,\r
+  0x12, 0x63, 0x90, 0x12, 0xE1, 0xE0, 0xFD, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xA3, 0xE0, 0x25, 0xE0,\r
+  0xFF, 0x05, 0x82, 0xD5, 0x82, 0x02, 0x15, 0x83,\r
+  0x15, 0x82, 0xE0, 0x33, 0xFE, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFC, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E, 0xFE,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFA,\r
+  0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E, 0xFE, 0xEF,\r
+  0x78, 0x02, 0xCE, 0xC3, 0x13, 0xCE, 0x13, 0xD8,\r
+  0xF9, 0xFF, 0xEC, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE1,\r
+  0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xA3,\r
+  0xE0, 0x25, 0xE0, 0xFF, 0x05, 0x82, 0xD5, 0x82,\r
+  0x02, 0x15, 0x83, 0x15, 0x82, 0xE0, 0x33, 0xFE,\r
+  0x90, 0x12, 0xE2, 0xE0, 0xFC, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF,\r
+  0xEA, 0x3E, 0xFE, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA,\r
+  0x3E, 0xFE, 0xEF, 0x78, 0x02, 0xCE, 0xC3, 0x13,\r
+  0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0xEC, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x02, 0x14, 0x1A, 0x90, 0x12, 0xDA, 0xE0, 0x75,\r
+  0xF0, 0x14, 0xA4, 0x24, 0xB4, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x37, 0xF5, 0x83, 0xC0, 0x83, 0xC0, 0x82,\r
+  0x90, 0x12, 0xE1, 0xE0, 0xD0, 0x82, 0xD0, 0x83,\r
+  0x75, 0xF0, 0x04, 0x12, 0x5B, 0xC5, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0xE4, 0x7B, 0xDC, 0x7A, 0x05, 0xF9, 0xF8,\r
+  0xC3, 0x12, 0x5B, 0x51, 0x40, 0x03, 0x02, 0x13,\r
+  0x34, 0x90, 0x12, 0xE2, 0xE0, 0xFD, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x12, 0xE1, 0xE0, 0xFC, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF,\r
+  0xEA, 0x3E, 0xC3, 0x13, 0xFE, 0xEF, 0x13, 0xFF,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE2, 0xE0, 0xFD,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xEC, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E,\r
+  0xC3, 0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xED, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0x02, 0x14, 0x1A, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xA3, 0xE0,\r
+  0x25, 0xE0, 0xFF, 0x05, 0x82, 0xD5, 0x82, 0x02,\r
+  0x15, 0x83, 0x15, 0x82, 0xE0, 0x33, 0xFE, 0x90,\r
+  0x12, 0xE1, 0xE0, 0xFC, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA,\r
+  0x3E, 0xFE, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xE0, 0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E,\r
+  0xFE, 0xEF, 0x78, 0x02, 0xCE, 0xC3, 0x13, 0xCE,\r
+  0x13, 0xD8, 0xF9, 0xFF, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xA3, 0xE0, 0x25, 0xE0, 0xFF, 0x05, 0x82,\r
+  0xD5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xE0,\r
+  0x33, 0xFE, 0xEC, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF, 0xEC, 0x3E,\r
+  0xFE, 0x90, 0x12, 0xE2, 0xE0, 0xFD, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F,\r
+  0xFF, 0xEA, 0x3E, 0xFE, 0xEF, 0x78, 0x02, 0xCE,\r
+  0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0xED,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xC3, 0x9D, 0xFF, 0xEE, 0x9C,\r
+  0xFE, 0x12, 0x78, 0xF1, 0x90, 0x13, 0x28, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xC3, 0x9D, 0xFF,\r
+  0xEE, 0x9C, 0xFE, 0x12, 0x78, 0xF1, 0x90, 0x13,\r
+  0x2A, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x13,\r
+  0x2A, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x13,\r
+  0x29, 0xE0, 0x2F, 0xFF, 0x90, 0x13, 0x28, 0xE0,\r
+  0x3E, 0xFE, 0x90, 0x13, 0x2C, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0xD3, 0x94, 0x0C, 0xEE, 0x94, 0x00, 0x40,\r
+  0x4A, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x24, 0x81,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0xD3, 0x94, 0x04, 0x40, 0x0E, 0x74, 0x81, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0x24, 0xFC, 0xF0, 0x90, 0x12, 0xE2, 0xE0, 0xFF,\r
+  0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xC3, 0x94, 0x01, 0x50, 0x0C, 0x74,\r
+  0x81, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x90, 0xF1, 0x0A, 0x74, 0x01,\r
+  0xF0, 0x80, 0x66, 0x90, 0x12, 0xE2, 0xE0, 0xFF,\r
+  0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0x04, 0xF0, 0x74, 0x81, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xD3,\r
+  0x94, 0x16, 0x40, 0x18, 0x90, 0x12, 0xE2, 0xE0,\r
+  0x24, 0x81, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0x74, 0x16, 0xF0, 0x90, 0xF1, 0x0A, 0x74,\r
+  0x02, 0xF0, 0x80, 0x29, 0x90, 0x12, 0x92, 0xE0,\r
+  0xD3, 0x94, 0x00, 0x50, 0x08, 0x90, 0x12, 0x60,\r
+  0xE0, 0x94, 0x00, 0x40, 0x09, 0x30, 0x04, 0x06,\r
+  0x90, 0xF1, 0x0A, 0x74, 0x01, 0xF0, 0x90, 0x12,\r
+  0x93, 0xE0, 0xD3, 0x94, 0x00, 0x40, 0x06, 0x90,\r
+  0xF1, 0x0A, 0x74, 0x01, 0xF0, 0xC2, 0x0F, 0xC2,\r
+  0x11, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x24, 0x81,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0xFD, 0x90, 0x13, 0x2C, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0xFB, 0xD3, 0x9D, 0xEA, 0x94, 0x00, 0x40, 0x13,\r
+  0xD2, 0x0F, 0xD2, 0x11, 0x74, 0x77, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0x74, 0x01,\r
+  0xF0, 0x80, 0x04, 0xC2, 0x0F, 0xC2, 0x11, 0x90,\r
+  0x12, 0xE2, 0xE0, 0x24, 0x77, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x12, 0xF5, 0x83, 0xE0, 0xB4, 0x01, 0x13,\r
+  0xD3, 0xEB, 0x94, 0x01, 0xEA, 0x94, 0x00, 0x40,\r
+  0x06, 0xD2, 0x0F, 0xD2, 0x11, 0x80, 0x04, 0xC2,\r
+  0x0F, 0xC2, 0x11, 0x90, 0x12, 0xE2, 0xE0, 0xFF,\r
+  0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x16,\r
+  0xAD, 0x90, 0x12, 0xE1, 0xE0, 0xFE, 0x24, 0x0A,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x13, 0xF5, 0x83, 0xE0,\r
+  0xFD, 0x74, 0xCA, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0xC3, 0x9D, 0x50, 0x4D,\r
+  0xC2, 0x0D, 0x90, 0x12, 0xE2, 0xE0, 0x24, 0x3C,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xE0,\r
+  0xFD, 0xEE, 0x25, 0xE0, 0x24, 0x14, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x13, 0xF5, 0x83, 0xE0, 0xFA, 0xA3,\r
+  0xE0, 0xD3, 0x9D, 0x74, 0x80, 0xF8, 0xEA, 0x64,\r
+  0x80, 0x98, 0x50, 0x10, 0x74, 0xCA, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0x04,\r
+  0xF0, 0x02, 0x16, 0xAF, 0x90, 0x12, 0xE2, 0xE0,\r
+  0x24, 0xCA, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x80, 0x72, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFF, 0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0xCA, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4,\r
+  0xF0, 0xD2, 0x0D, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x94, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x80, 0x02, 0xD2, 0x0D, 0x30,\r
+  0x01, 0x57, 0x90, 0x12, 0xE1, 0xE0, 0xFF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0x90, 0x12, 0xE2, 0xE0, 0xFE, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0,\r
+  0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x02, 0x17,\r
+  0x8E, 0x20, 0x0F, 0x03, 0x02, 0x17, 0x8E, 0x30,\r
+  0x11, 0x7C, 0x30, 0x0D, 0x79, 0x90, 0x13, 0x2C,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xD3, 0x94, 0x78,\r
+  0xEE, 0x94, 0x00, 0x40, 0x06, 0x90, 0x12, 0x92,\r
+  0xE0, 0x04, 0xF0, 0xD3, 0xEF, 0x94, 0x72, 0xEE,\r
+  0x94, 0x01, 0x40, 0x06, 0x90, 0x12, 0x93, 0xE0,\r
+  0x04, 0xF0, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12, 0xE2, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12,\r
+  0xE1, 0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82,\r
+  0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xEC, 0xF0, 0xA3,\r
+  0xED, 0xF0, 0x90, 0x12, 0xE1, 0xE0, 0xFF, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83,\r
+  0xE0, 0xFE, 0x90, 0x12, 0xE2, 0xE0, 0xFD, 0x24,\r
+  0x14, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0x74, 0x28, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8A, 0xF5, 0x83, 0xE0, 0xFF, 0x74, 0x3C,\r
+  0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83,\r
+  0xEF, 0xF0, 0x74, 0xE5, 0x2D, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x88, 0xF5, 0x83, 0x74, 0x02, 0xF0, 0x90,\r
+  0x12, 0xE1, 0xE0, 0x24, 0xA0, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x37, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x12,\r
+  0xDF, 0xE0, 0x04, 0xF0, 0x90, 0x88, 0xC0, 0xE0,\r
+  0x14, 0xF0, 0x90, 0x88, 0xC1, 0xE0, 0x14, 0xF0,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x10,\r
+  0x3C, 0x90, 0x12, 0xDF, 0xE0, 0xC3, 0x95, 0x0D,\r
+  0x40, 0x03, 0x02, 0x18, 0xE0, 0x90, 0x88, 0xC0,\r
+  0xE0, 0x94, 0x00, 0x40, 0x7B, 0xE4, 0x90, 0x12,\r
+  0xDB, 0xF0, 0x90, 0x12, 0xDB, 0xE0, 0xFF, 0xC3,\r
+  0x95, 0x0D, 0x50, 0x6C, 0x74, 0xE5, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0x64,\r
+  0x04, 0x70, 0x55, 0x90, 0x12, 0xDF, 0xE0, 0xC3,\r
+  0x95, 0x0D, 0x50, 0x4C, 0x90, 0x12, 0xDB, 0xE0,\r
+  0x24, 0xE5, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0x74, 0x03, 0xF0, 0x74, 0x77, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x88, 0xC0, 0xE0, 0x14, 0xF0, 0x90, 0x12,\r
+  0xDF, 0xE0, 0x04, 0xF0, 0x74, 0xD1, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x74, 0xCA, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x74, 0xC0, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x04, 0xF0, 0x80, 0x8A,\r
+  0x90, 0x12, 0xDF, 0xE0, 0xC3, 0x95, 0x0D, 0x40,\r
+  0x03, 0x02, 0x26, 0x16, 0x90, 0x88, 0xC1, 0xE0,\r
+  0x94, 0x00, 0x50, 0x03, 0x02, 0x26, 0x16, 0xE4,\r
+  0x90, 0x12, 0xDC, 0xF0, 0x90, 0x88, 0xB0, 0xE0,\r
+  0xFF, 0x90, 0x12, 0xDC, 0xE0, 0xFE, 0xC3, 0x9F,\r
+  0x40, 0x03, 0x02, 0x26, 0x16, 0x74, 0xA0, 0x2E,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5, 0x83, 0xE0,\r
+  0x70, 0x03, 0x02, 0x1B, 0x17, 0xE4, 0x90, 0x12,\r
+  0xDB, 0xF0, 0x90, 0x12, 0xDB, 0xE0, 0xFF, 0xC3,\r
+  0x95, 0x0D, 0x40, 0x03, 0x02, 0x1B, 0x17, 0x74,\r
+  0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0xE0, 0x60, 0x03, 0x02, 0x1B, 0x0E, 0x90,\r
+  0x12, 0xDF, 0xE0, 0xC3, 0x95, 0x0D, 0x40, 0x03,\r
+  0x02, 0x1B, 0x0E, 0x90, 0x12, 0xDC, 0xE0, 0xFF,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3,\r
+  0xE0, 0xFD, 0x90, 0x12, 0xDB, 0xE0, 0xFE, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED,\r
+  0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x90,\r
+  0x12, 0xDC, 0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED,\r
+  0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x90,\r
+  0x12, 0xDC, 0xE0, 0xFF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED,\r
+  0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x90,\r
+  0x12, 0xDC, 0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xE0, 0xFE, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFD, 0x24, 0x14, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xEE, 0xF0, 0x74,\r
+  0x28, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5,\r
+  0x83, 0xE0, 0xFF, 0x74, 0x3C, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xEF, 0xF0, 0x74,\r
+  0xC0, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0x74, 0x01, 0xF0, 0x90, 0x12, 0xDC, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0x90, 0x12, 0xDB, 0xE0, 0xFE,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x94, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xEC, 0xF0, 0xA3,\r
+  0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0,\r
+  0x74, 0xE5, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x88,\r
+  0xF5, 0x83, 0x74, 0x01, 0xF0, 0x90, 0x12, 0xDC,\r
+  0xE0, 0x24, 0xA0, 0xF5, 0x82, 0xE4, 0x34, 0x37,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x74, 0xD1, 0x2E, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x88, 0xC1, 0xE0, 0x14, 0xF0, 0x90, 0x12,\r
+  0xDF, 0xE0, 0x04, 0xF0, 0x80, 0x09, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x04, 0xF0, 0x02, 0x19, 0x22, 0x90,\r
+  0x12, 0xDC, 0xE0, 0x04, 0xF0, 0x02, 0x18, 0xFC,\r
+  0xE4, 0x90, 0x88, 0xC0, 0xF0, 0xF5, 0xDC, 0xF5,\r
+  0xDD, 0xF5, 0xDE, 0x90, 0x12, 0xDB, 0xF0, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFF, 0xC3, 0x95, 0x0D, 0x50,\r
+  0x5A, 0x74, 0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x88, 0xF5, 0x83, 0xE0, 0x64, 0x01, 0x60, 0x20,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x24, 0xE5, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0x64, 0x02,\r
+  0x60, 0x0E, 0x74, 0xE5, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x88, 0xF5, 0x83, 0xE0, 0xB4, 0x04, 0x14,\r
+  0x90, 0x88, 0xC0, 0xE0, 0x04, 0xF0, 0x90, 0x12,\r
+  0xDB, 0xE0, 0xFF, 0x7B, 0x01, 0xE4, 0xFD, 0x12,\r
+  0x4C, 0x38, 0x80, 0x0F, 0x90, 0x12, 0xDB, 0xE0,\r
+  0x24, 0xE5, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x90, 0x12, 0xDB, 0xE0, 0x04,\r
+  0xF0, 0x80, 0x9C, 0xE4, 0xF5, 0xD9, 0xF5, 0xDA,\r
+  0xF5, 0xDB, 0x90, 0x12, 0xDC, 0xF0, 0x90, 0x88,\r
+  0xC1, 0xE0, 0xFE, 0x90, 0x12, 0xDC, 0xE0, 0xFF,\r
+  0xC3, 0x9E, 0x50, 0x0E, 0xE4, 0xFB, 0xFD, 0x12,\r
+  0x4C, 0x38, 0x90, 0x12, 0xDC, 0xE0, 0x04, 0xF0,\r
+  0x80, 0xE4, 0x90, 0x88, 0xC0, 0xE0, 0xFF, 0x90,\r
+  0x88, 0xC1, 0xE0, 0xC3, 0x9F, 0x50, 0x07, 0xE0,\r
+  0x90, 0x12, 0xE3, 0xF0, 0x80, 0x08, 0x90, 0x88,\r
+  0xC0, 0xE0, 0x90, 0x12, 0xE3, 0xF0, 0xE4, 0x90,\r
+  0x12, 0xDD, 0xF0, 0x90, 0x12, 0xE3, 0xE0, 0xFF,\r
+  0x90, 0x12, 0xDD, 0xE0, 0xC3, 0x9F, 0x40, 0x03,\r
+  0x02, 0x23, 0x57, 0xC2, 0x0F, 0xC2, 0x11, 0xD2,\r
+  0xB4, 0x20, 0xB4, 0x06, 0x30, 0x0E, 0x03, 0x20,\r
+  0xDD, 0x05, 0x75, 0x9E, 0x55, 0x80, 0xF2, 0xC2,\r
+  0xDD, 0xC2, 0x0E, 0xAF, 0xE2, 0xEF, 0xFE, 0xAD,\r
+  0xE3, 0x7C, 0x00, 0xE4, 0x2D, 0xFF, 0xEC, 0x3E,\r
+  0xAD, 0x07, 0xFC, 0xC3, 0xED, 0x94, 0x20, 0xEC,\r
+  0x94, 0x4E, 0x40, 0x03, 0x02, 0x23, 0x57, 0xED,\r
+  0x94, 0xC8, 0xEC, 0x94, 0x00, 0x40, 0x57, 0xAF,\r
+  0xDF, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xAB, 0xE1, 0xEB, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0xAF, 0xDF, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xAB, 0xE1,\r
+  0xEB, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x02, 0x1E, 0xFC, 0xD3, 0xED,\r
+  0x94, 0x64, 0xEC, 0x94, 0x00, 0x50, 0x03, 0x02,\r
+  0x1D, 0x73, 0xAF, 0xDF, 0xEF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xA3, 0xE0, 0x25, 0xE0, 0xFF, 0x05,\r
+  0x82, 0xD5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82,\r
+  0xE0, 0x33, 0xFE, 0xAB, 0xDF, 0xEB, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0x2F,\r
+  0xFF, 0xEA, 0x3E, 0xFE, 0xAB, 0xE1, 0xEB, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0x2F, 0xFF, 0xEA, 0x3E, 0xFE, 0xEF, 0x78, 0x02,\r
+  0xCE, 0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF,\r
+  0xAB, 0xE1, 0xEB, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0xDF, 0xEF,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82,\r
+  0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xA3, 0xE0, 0x25,\r
+  0xE0, 0xFF, 0x05, 0x82, 0xD5, 0x82, 0x02, 0x15,\r
+  0x83, 0x15, 0x82, 0xE0, 0x33, 0xFE, 0xAB, 0xDF,\r
+  0xEB, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFA,\r
+  0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E, 0xFE, 0xAB,\r
+  0xE1, 0xEB, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFA, 0xA3, 0xE0, 0x2F, 0xFF, 0xEA, 0x3E, 0xFE,\r
+  0xEF, 0x78, 0x02, 0xCE, 0xC3, 0x13, 0xCE, 0x13,\r
+  0xD8, 0xF9, 0xFF, 0xAB, 0xE1, 0xEB, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x02, 0x1E, 0xFC, 0xAE, 0x04, 0xAF, 0x05, 0xD3,\r
+  0xED, 0x94, 0x32, 0xEC, 0x94, 0x00, 0x50, 0x03,\r
+  0x02, 0x1E, 0x16, 0xAF, 0xE1, 0xEF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xAD, 0xDF, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF, 0xEC, 0x3E,\r
+  0xC3, 0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xAD, 0xE1,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xAF, 0xE1, 0xEF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xAD, 0xDF, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF, 0xEC, 0x3E,\r
+  0xC3, 0x13, 0xFE, 0xEF, 0x13, 0xFF, 0xAD, 0xE1,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x02, 0x1E, 0xFC, 0xAF, 0xE1,\r
+  0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xA3, 0xE0,\r
+  0x25, 0xE0, 0xFF, 0x05, 0x82, 0xD5, 0x82, 0x02,\r
+  0x15, 0x83, 0x15, 0x82, 0xE0, 0x33, 0xFE, 0xAD,\r
+  0xE1, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0x2F, 0xFF, 0xEC, 0x3E, 0xFE,\r
+  0xAD, 0xDF, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF, 0xEC, 0x3E,\r
+  0xFE, 0xEF, 0x78, 0x02, 0xCE, 0xC3, 0x13, 0xCE,\r
+  0x13, 0xD8, 0xF9, 0xFF, 0xAD, 0xE1, 0xED, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0xAF, 0xE1, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xA3, 0xE0, 0x25, 0xE0, 0xFF, 0x05, 0x82,\r
+  0xD5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xE0,\r
+  0x33, 0xFE, 0xAD, 0xE1, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0x2F, 0xFF,\r
+  0xEC, 0x3E, 0xFE, 0xAD, 0xDF, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0x2F,\r
+  0xFF, 0xEC, 0x3E, 0xFE, 0xEF, 0x78, 0x02, 0xCE,\r
+  0xC3, 0x13, 0xCE, 0x13, 0xD8, 0xF9, 0xFF, 0xAD,\r
+  0xE1, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0xE1, 0xEF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0xAD, 0xE1, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xC3, 0x9F, 0xFF,\r
+  0xEC, 0x9E, 0xFE, 0x12, 0x78, 0xF1, 0x90, 0x13,\r
+  0x28, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0xE1,\r
+  0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0xAD, 0xE1, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xC3,\r
+  0x9F, 0xFF, 0xEC, 0x9E, 0xFE, 0x12, 0x78, 0xF1,\r
+  0x90, 0x13, 0x2A, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x90, 0x13, 0x2A, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x13, 0x29, 0xE0, 0x2F, 0xFF, 0x90, 0x13,\r
+  0x28, 0xE0, 0x3E, 0xFE, 0x90, 0x13, 0x2C, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xD3, 0x94, 0x0C, 0xEE, 0x94,\r
+  0x00, 0x40, 0x4E, 0xD2, 0x0F, 0xD2, 0x11, 0xAF,\r
+  0xE1, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0xD3, 0x94, 0x04, 0x40,\r
+  0x10, 0xAF, 0xE1, 0x74, 0x81, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0x24, 0xFC,\r
+  0xF0, 0xAF, 0xE1, 0x74, 0x81, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xC3, 0x94,\r
+  0x01, 0x50, 0x0E, 0xAF, 0xE1, 0x74, 0x81, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4,\r
+  0xF0, 0x90, 0xF1, 0x0A, 0x74, 0x01, 0xF0, 0x80,\r
+  0x65, 0xAF, 0xE1, 0x74, 0x81, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0x04, 0xF0,\r
+  0xAF, 0xE1, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x12, 0xF5, 0x83, 0xE0, 0xD3, 0x94, 0x16,\r
+  0x40, 0x17, 0xAF, 0xE1, 0x74, 0x81, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0x74, 0x16,\r
+  0xF0, 0x90, 0xF1, 0x0A, 0x74, 0x02, 0xF0, 0x80,\r
+  0x29, 0x90, 0x12, 0x92, 0xE0, 0xD3, 0x94, 0x00,\r
+  0x50, 0x08, 0x90, 0x12, 0x60, 0xE0, 0x94, 0x00,\r
+  0x40, 0x09, 0x30, 0x04, 0x06, 0x90, 0xF1, 0x0A,\r
+  0x74, 0x01, 0xF0, 0x90, 0x12, 0x93, 0xE0, 0xD3,\r
+  0x94, 0x00, 0x40, 0x06, 0x90, 0xF1, 0x0A, 0x74,\r
+  0x01, 0xF0, 0xC2, 0x0F, 0xC2, 0x11, 0xAF, 0xE1,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x13, 0x2C, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xD3, 0x9F, 0xEC, 0x94,\r
+  0x00, 0x40, 0x15, 0xD2, 0x0F, 0xD2, 0x11, 0xAF,\r
+  0xE1, 0x74, 0x77, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x80, 0x04,\r
+  0xC2, 0x0F, 0xC2, 0x11, 0xAF, 0xE1, 0x74, 0x77,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83,\r
+  0xE0, 0xB4, 0x01, 0x13, 0xD3, 0xED, 0x94, 0x01,\r
+  0xEC, 0x94, 0x00, 0x40, 0x06, 0xD2, 0x0F, 0xD2,\r
+  0x11, 0x80, 0x04, 0xC2, 0x0F, 0xC2, 0x11, 0xAF,\r
+  0xE1, 0x74, 0xC0, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0x64, 0x01, 0x60, 0x03,\r
+  0x02, 0x21, 0x95, 0xAF, 0xDF, 0x74, 0x0A, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x13, 0xF5, 0x83, 0xE0,\r
+  0xFF, 0xAE, 0xE1, 0x74, 0xCA, 0x2E, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xC3, 0x9F,\r
+  0x50, 0x4F, 0xC2, 0x0D, 0xAF, 0xE1, 0x74, 0x3C,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83,\r
+  0xE0, 0xFF, 0xAD, 0xDF, 0xED, 0x25, 0xE0, 0x24,\r
+  0x14, 0xF5, 0x82, 0xE4, 0x34, 0x13, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xD3, 0x9F, 0x74, 0x80,\r
+  0xF8, 0xEC, 0x64, 0x80, 0x98, 0x50, 0x12, 0xAF,\r
+  0xE1, 0x74, 0xCA, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0x04, 0xF0, 0x02, 0x21,\r
+  0x97, 0xAF, 0xE1, 0x74, 0xCA, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x80,\r
+  0x76, 0xAF, 0xE1, 0x74, 0xC0, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0, 0xAF,\r
+  0xE1, 0x74, 0xCA, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE4, 0xF0, 0xAF, 0xE1, 0xEF,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x94, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xAD, 0xE1, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF,\r
+  0xE1, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x96,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xAD, 0xE1, 0xED, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0xD2, 0x0D, 0x80, 0x02, 0xD2, 0x0D, 0x30,\r
+  0x01, 0x57, 0xAF, 0xDF, 0xEF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xAD,\r
+  0xE1, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0xDF, 0xEF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0xAD, 0xE1, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0x22,\r
+  0x81, 0x20, 0x0F, 0x03, 0x02, 0x22, 0x81, 0x20,\r
+  0x11, 0x03, 0x02, 0x22, 0x81, 0x20, 0x0D, 0x03,\r
+  0x02, 0x22, 0x81, 0xD3, 0x90, 0x13, 0x2D, 0xE0,\r
+  0x94, 0x78, 0x90, 0x13, 0x2C, 0xE0, 0x94, 0x00,\r
+  0x40, 0x06, 0x90, 0x12, 0x92, 0xE0, 0x04, 0xF0,\r
+  0xD3, 0x90, 0x13, 0x2D, 0xE0, 0x94, 0x72, 0x90,\r
+  0x13, 0x2C, 0xE0, 0x94, 0x01, 0x40, 0x06, 0x90,\r
+  0x12, 0x93, 0xE0, 0x04, 0xF0, 0xAF, 0xE1, 0xEF,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0xAD, 0xE1, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF,\r
+  0xE1, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xAD, 0xE1, 0xED, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0xAF, 0xDF, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xAD, 0xE1,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xAF, 0xDF, 0xEF, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0xF2, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xAD, 0xE1, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x52, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xAF, 0xDF, 0x74,\r
+  0x00, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5,\r
+  0x83, 0xE0, 0xFF, 0xAE, 0xE1, 0x74, 0x14, 0x2E,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xEF,\r
+  0xF0, 0xAF, 0xDF, 0x74, 0x28, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xE0, 0xFF, 0xAE,\r
+  0xE1, 0x74, 0x3C, 0x2E, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x8A, 0xF5, 0x83, 0xEF, 0xF0, 0xAF, 0xE1, 0x74,\r
+  0xE5, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0x74, 0x02, 0xF0, 0x90, 0x12, 0xDF, 0xE0,\r
+  0x04, 0xF0, 0x90, 0x88, 0xC0, 0xE0, 0x14, 0xF0,\r
+  0x90, 0x88, 0xC1, 0xE0, 0x14, 0xF0, 0xAF, 0xE1,\r
+  0x74, 0xD1, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x7B, 0x01, 0x7D, 0x01,\r
+  0xAF, 0xE1, 0x12, 0x4C, 0x38, 0xE4, 0xFB, 0x7D,\r
+  0x01, 0xAF, 0xDF, 0x12, 0x4C, 0x38, 0x90, 0x12,\r
+  0xDD, 0xE0, 0x04, 0xF0, 0x02, 0x1B, 0xDB, 0x90,\r
+  0x12, 0xDF, 0xE0, 0xC3, 0x95, 0x0D, 0x40, 0x03,\r
+  0x02, 0x23, 0xE4, 0x90, 0x88, 0xC0, 0xE0, 0x94,\r
+  0x00, 0x40, 0x79, 0xE4, 0x90, 0x12, 0xDB, 0xF0,\r
+  0x90, 0x12, 0xDB, 0xE0, 0xFF, 0xC3, 0x95, 0x0D,\r
+  0x50, 0x6A, 0x7B, 0x01, 0x7D, 0x02, 0x12, 0x4C,\r
+  0x38, 0x90, 0x12, 0xDE, 0xEF, 0xF0, 0x60, 0x54,\r
+  0xA3, 0xE0, 0xC3, 0x95, 0x0D, 0x50, 0x4D, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFF, 0x24, 0xCA, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x74,\r
+  0xC0, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x74, 0xE5, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x88, 0xF5, 0x83, 0x74, 0x03, 0xF0,\r
+  0x74, 0x77, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x12,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x88, 0xC0, 0xE0,\r
+  0x14, 0xF0, 0x90, 0x12, 0xDF, 0xE0, 0x04, 0xF0,\r
+  0x74, 0xD1, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x12, 0xDB, 0xE0,\r
+  0x04, 0xF0, 0x80, 0x8C, 0x90, 0x12, 0xDF, 0xE0,\r
+  0xC3, 0x95, 0x0D, 0x40, 0x03, 0x02, 0x26, 0x16,\r
+  0x90, 0x88, 0xC1, 0xE0, 0x94, 0x00, 0x50, 0x03,\r
+  0x02, 0x26, 0x16, 0xE4, 0x90, 0x12, 0xDC, 0xF0,\r
+  0x90, 0x88, 0xB0, 0xE0, 0xFE, 0x90, 0x12, 0xDC,\r
+  0xE0, 0xFF, 0xC3, 0x9E, 0x40, 0x03, 0x02, 0x26,\r
+  0x16, 0xE4, 0xFB, 0x7D, 0x02, 0x12, 0x4C, 0x38,\r
+  0x90, 0x12, 0xDE, 0xEF, 0xF0, 0x70, 0x03, 0x02,\r
+  0x26, 0x0D, 0xE4, 0x90, 0x12, 0xDB, 0xF0, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFF, 0xC3, 0x95, 0x0D, 0x40,\r
+  0x03, 0x02, 0x26, 0x0D, 0x74, 0xE5, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0x60,\r
+  0x03, 0x02, 0x26, 0x04, 0x90, 0x12, 0xDF, 0xE0,\r
+  0xC3, 0x95, 0x0D, 0x40, 0x03, 0x02, 0x26, 0x04,\r
+  0x90, 0x12, 0xDC, 0xE0, 0xFF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFE, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x50, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52,\r
+  0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12, 0xDC, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x02,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12, 0xDC, 0xE0,\r
+  0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0xE0, 0xFE, 0x90, 0x12, 0xDB, 0xE0,\r
+  0xFD, 0x24, 0x14, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0x74, 0x28, 0x2F, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xE0, 0xFF,\r
+  0x74, 0x3C, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x12, 0xDC, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0x90, 0x12, 0xDB, 0xE0, 0xFE,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3,\r
+  0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2, 0xF5, 0x83,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0,\r
+  0x74, 0xE5, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x88,\r
+  0xF5, 0x83, 0x74, 0x01, 0xF0, 0x74, 0xC0, 0x2E,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0x74,\r
+  0x01, 0xF0, 0x90, 0x12, 0xDC, 0xE0, 0xFF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0xF2, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEE, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x94,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEE,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x96, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xEC, 0xF0, 0xA3,\r
+  0xED, 0xF0, 0x74, 0xD1, 0x2E, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x88, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x88,\r
+  0xC1, 0xE0, 0x14, 0xF0, 0x90, 0x12, 0xDF, 0xE0,\r
+  0x04, 0xF0, 0x80, 0x09, 0x90, 0x12, 0xDB, 0xE0,\r
+  0x04, 0xF0, 0x02, 0x24, 0x27, 0x90, 0x12, 0xDC,\r
+  0xE0, 0x04, 0xF0, 0x02, 0x24, 0x00, 0x22, 0xE4,\r
+  0xF5, 0x99, 0x75, 0x96, 0x03, 0x75, 0x9E, 0x55,\r
+  0xF5, 0xA1, 0xF5, 0xA1, 0xF5, 0xA1, 0xC2, 0x09,\r
+  0xC2, 0x0A, 0xC2, 0x0E, 0xC2, 0x15, 0xC2, 0x05,\r
+  0xC2, 0x06, 0x90, 0x12, 0x81, 0xF0, 0xA3, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,\r
+  0x90, 0x12, 0x77, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x12,\r
+  0xC0, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xD2, 0xB1, 0xC2, 0xB6,\r
+  0xC2, 0xB7, 0x75, 0xA0, 0x02, 0xF5, 0xAE, 0x90,\r
+  0xF0, 0xC4, 0xF0, 0x90, 0x8F, 0xF0, 0xF0, 0xFF,\r
+  0xFE, 0xAD, 0x07, 0x74, 0xE5, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE4, 0xF0, 0x74,\r
+  0xA0, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x37, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x0F, 0xBF, 0x00, 0x01, 0x0E,\r
+  0xEF, 0x64, 0x14, 0x4E, 0x70, 0xDB, 0xE4, 0x90,\r
+  0x88, 0xC0, 0xF0, 0x90, 0x88, 0xC1, 0xF0, 0xF5,\r
+  0xDC, 0xF5, 0xDD, 0xF5, 0xDE, 0xF5, 0xD9, 0xF5,\r
+  0xDA, 0xF5, 0xDB, 0x90, 0x88, 0xC2, 0xF0, 0x90,\r
+  0x88, 0xC6, 0xF0, 0x90, 0x88, 0xCD, 0xF0, 0xC2,\r
+  0x0C, 0xC2, 0x0B, 0xC2, 0x14, 0x75, 0x8A, 0x8F,\r
+  0xF5, 0x8B, 0x90, 0x8F, 0xFF, 0xF0, 0xC2, 0x03,\r
+  0xC2, 0x16, 0x90, 0x28, 0x11, 0x93, 0xF5, 0x08,\r
+  0x90, 0x28, 0x10, 0xE4, 0x93, 0xFD, 0xF5, 0x0D,\r
+  0x90, 0x8B, 0x7C, 0xED, 0xF0, 0x90, 0x28, 0x12,\r
+  0xE4, 0x93, 0x90, 0x8B, 0x7D, 0xF0, 0x90, 0x28,\r
+  0x13, 0xE4, 0x93, 0x90, 0x8B, 0x7E, 0xF0, 0x90,\r
+  0x28, 0x0B, 0xE4, 0x93, 0xF5, 0x0B, 0x90, 0x28,\r
+  0x0C, 0xE4, 0x93, 0xF5, 0x0C, 0x90, 0x8B, 0x78,\r
+  0x74, 0x05, 0xF0, 0xA3, 0xE4, 0xF0, 0x90, 0x8B,\r
+  0x7A, 0x74, 0x03, 0xF0, 0xA3, 0x74, 0x20, 0xF0,\r
+  0xE4, 0x90, 0x3F, 0xFE, 0xF0, 0xC2, 0x10, 0x90,\r
+  0x12, 0xBC, 0xF0, 0x90, 0x12, 0x58, 0xF0, 0x90,\r
+  0x12, 0x59, 0xF0, 0x90, 0x12, 0x63, 0xF0, 0xA3,\r
+  0x74, 0x03, 0xF0, 0xE4, 0x90, 0x8F, 0xFE, 0xF0,\r
+  0xFE, 0xFF, 0x75, 0x9E, 0x55, 0xAD, 0x07, 0x74,\r
+  0x00, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x74, 0x78, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xE4, 0xF0, 0x0F,\r
+  0xBF, 0x00, 0x01, 0x0E, 0xEF, 0x64, 0x3C, 0x4E,\r
+  0x70, 0xD8, 0xE4, 0xFE, 0xFF, 0xAD, 0x07, 0x74,\r
+  0xCA, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x74, 0x65, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE4, 0xF0, 0x0F,\r
+  0xBF, 0x00, 0x01, 0x0E, 0xEF, 0x64, 0x0A, 0x4E,\r
+  0x70, 0xDB, 0xE4, 0x90, 0x12, 0x71, 0xF0, 0xA3,\r
+  0xF0, 0x90, 0x12, 0xBD, 0xF0, 0xA3, 0xF0, 0x90,\r
+  0x12, 0xBF, 0xF0, 0x90, 0x3F, 0xFD, 0x04, 0xF0,\r
+  0x22, 0xE4, 0x90, 0x12, 0xDA, 0xF0, 0xA3, 0xF0,\r
+  0x90, 0x8F, 0xFE, 0x74, 0xAA, 0xF0, 0x90, 0x8F,\r
+  0xFD, 0xE0, 0x64, 0xBB, 0x60, 0x1A, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x75, 0x9E, 0x55, 0x7F,\r
+  0xFA, 0x7E, 0x00, 0x12, 0x67, 0xEE, 0x80, 0xDE,\r
+  0xE4, 0x90, 0x8F, 0xFD, 0xF0, 0x90, 0x8F, 0xFE,\r
+  0xF0, 0xD2, 0xD8, 0xA2, 0xD9, 0x33, 0x90, 0x8E,\r
+  0x01, 0xF0, 0x90, 0xF0, 0xC4, 0x74, 0x01, 0xF0,\r
+  0x22, 0xD2, 0xD8, 0x22, 0xD2, 0x0E, 0x32, 0x32,\r
+  0x1C, 0x1C, 0x20, 0x1E, 0x28, 0x03, 0xE8, 0x1E,\r
+  0xC8, 0x14, 0x01, 0x40, 0x40, 0x20, 0x20, 0x02,\r
+  0x0A, 0x0A, 0x01, 0x05, 0xE4, 0x90, 0x12, 0xE8,\r
+  0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3,\r
+  0xF0, 0xA3, 0xF0, 0x90, 0xF1, 0x03, 0xE0, 0xD3,\r
+  0x94, 0x50, 0x40, 0x0F, 0xE0, 0x90, 0xF2, 0xA5,\r
+  0xF0, 0x90, 0xF1, 0x03, 0xE0, 0x90, 0xF2, 0xA4,\r
+  0xF0, 0x80, 0x0A, 0x90, 0xF2, 0xA5, 0x74, 0xFA,\r
+  0xF0, 0x90, 0xF2, 0xA4, 0xF0, 0x90, 0xF1, 0x03,\r
+  0xE0, 0x90, 0xF2, 0xB1, 0xF0, 0xD2, 0xB6, 0xD2,\r
+  0xB7, 0xD2, 0xB2, 0x20, 0xB2, 0x06, 0x30, 0x0E,\r
+  0x03, 0x20, 0xDC, 0x05, 0x75, 0x9E, 0x55, 0x80,\r
+  0xF2, 0xC2, 0xDC, 0xC2, 0x0E, 0x90, 0xF2, 0xB0,\r
+  0xE0, 0x64, 0x01, 0x70, 0x35, 0x90, 0x12, 0xFA,\r
+  0x74, 0x16, 0xF0, 0x90, 0x12, 0x92, 0xE0, 0xD3,\r
+  0x94, 0x00, 0x50, 0x08, 0x90, 0x12, 0x60, 0xE0,\r
+  0x94, 0x00, 0x40, 0x09, 0x30, 0x04, 0x06, 0x90,\r
+  0x12, 0xFA, 0x74, 0x12, 0xF0, 0x90, 0x12, 0x93,\r
+  0xE0, 0xD3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x29,\r
+  0xC6, 0x90, 0x12, 0xFA, 0x74, 0x10, 0xF0, 0x02,\r
+  0x29, 0xC6, 0x90, 0xF2, 0xB0, 0xE0, 0x64, 0x02,\r
+  0x70, 0x35, 0x90, 0x12, 0xFA, 0x74, 0x16, 0xF0,\r
+  0x90, 0x12, 0x92, 0xE0, 0xD3, 0x94, 0x00, 0x50,\r
+  0x08, 0x90, 0x12, 0x60, 0xE0, 0x94, 0x00, 0x40,\r
+  0x09, 0x30, 0x04, 0x06, 0x90, 0x12, 0xFA, 0x74,\r
+  0x12, 0xF0, 0x90, 0x12, 0x93, 0xE0, 0xD3, 0x94,\r
+  0x00, 0x50, 0x03, 0x02, 0x29, 0xC6, 0x90, 0x12,\r
+  0xFA, 0x74, 0x10, 0xF0, 0x02, 0x29, 0xC6, 0x90,\r
+  0xF2, 0xB0, 0xE0, 0x64, 0x03, 0x70, 0x35, 0x90,\r
+  0x12, 0xFA, 0x74, 0x16, 0xF0, 0x90, 0x12, 0x92,\r
+  0xE0, 0xD3, 0x94, 0x00, 0x50, 0x08, 0x90, 0x12,\r
+  0x60, 0xE0, 0x94, 0x00, 0x40, 0x09, 0x30, 0x04,\r
+  0x06, 0x90, 0x12, 0xFA, 0x74, 0x12, 0xF0, 0x90,\r
+  0x12, 0x93, 0xE0, 0xD3, 0x94, 0x00, 0x50, 0x03,\r
+  0x02, 0x29, 0xC6, 0x90, 0x12, 0xFA, 0x74, 0x10,\r
+  0xF0, 0x02, 0x29, 0xC6, 0x90, 0xF2, 0xB0, 0xE0,\r
+  0x64, 0x04, 0x70, 0x31, 0x90, 0x12, 0xFA, 0x74,\r
+  0x18, 0xF0, 0x90, 0x12, 0x92, 0xE0, 0xD3, 0x94,\r
+  0x00, 0x50, 0x08, 0x90, 0x12, 0x60, 0xE0, 0x94,\r
+  0x00, 0x40, 0x09, 0x30, 0x04, 0x06, 0x90, 0x12,\r
+  0xFA, 0x74, 0x16, 0xF0, 0x90, 0x12, 0x93, 0xE0,\r
+  0xD3, 0x94, 0x00, 0x40, 0x79, 0x90, 0x12, 0xFA,\r
+  0x74, 0x12, 0xF0, 0x80, 0x71, 0x90, 0xF2, 0xB0,\r
+  0xE0, 0x64, 0x05, 0x70, 0x31, 0x90, 0x12, 0xFA,\r
+  0x74, 0x19, 0xF0, 0x90, 0x12, 0x92, 0xE0, 0xD3,\r
+  0x94, 0x00, 0x50, 0x08, 0x90, 0x12, 0x60, 0xE0,\r
+  0x94, 0x00, 0x40, 0x09, 0x30, 0x04, 0x06, 0x90,\r
+  0x12, 0xFA, 0x74, 0x17, 0xF0, 0x90, 0x12, 0x93,\r
+  0xE0, 0xD3, 0x94, 0x00, 0x40, 0x40, 0x90, 0x12,\r
+  0xFA, 0x74, 0x12, 0xF0, 0x80, 0x38, 0x90, 0xF2,\r
+  0xB0, 0xE0, 0xD3, 0x94, 0x05, 0x40, 0x2F, 0x90,\r
+  0x12, 0xFA, 0x74, 0x19, 0xF0, 0x90, 0x12, 0x92,\r
+  0xE0, 0xD3, 0x94, 0x00, 0x50, 0x08, 0x90, 0x12,\r
+  0x60, 0xE0, 0x94, 0x00, 0x40, 0x09, 0x30, 0x04,\r
+  0x06, 0x90, 0x12, 0xFA, 0x74, 0x17, 0xF0, 0x90,\r
+  0x12, 0x93, 0xE0, 0xD3, 0x94, 0x00, 0x40, 0x06,\r
+  0x90, 0x12, 0xFA, 0x74, 0x12, 0xF0, 0x90, 0xF2,\r
+  0xB0, 0xE0, 0xD3, 0x94, 0x00, 0x50, 0x03, 0x02,\r
+  0x35, 0x7F, 0xE4, 0x90, 0x12, 0xDA, 0xF0, 0xA3,\r
+  0xF0, 0x90, 0xF2, 0xB0, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xC3, 0x9F,\r
+  0xEC, 0x94, 0x00, 0x40, 0x03, 0x02, 0x35, 0x7F,\r
+  0x30, 0xD9, 0x03, 0x02, 0x2A, 0x95, 0xED, 0x25,\r
+  0xE0, 0xFD, 0xEC, 0x33, 0xFC, 0x74, 0x81, 0x2D,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3C, 0xF5, 0x83, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x29, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x80, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x81, 0x2D,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3C, 0xF5, 0x83, 0xE0,\r
+  0x25, 0xE0, 0x24, 0x28, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x80, 0xF5, 0x83, 0xE0, 0x7C, 0x00, 0x24, 0x00,\r
+  0xFF, 0xEC, 0x3E, 0xFE, 0x7D, 0x14, 0x12, 0x59,\r
+  0x93, 0x90, 0x12, 0xF4, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFD,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x33, 0xFC, 0x74, 0x80,\r
+  0x2D, 0xF5, 0x82, 0x74, 0x81, 0x3C, 0xF5, 0x83,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x01, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x80, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x80,\r
+  0x2D, 0xF5, 0x82, 0x74, 0x81, 0x3C, 0xF5, 0x83,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x80, 0xF5, 0x83, 0xE0, 0x7C, 0x00, 0x24,\r
+  0x00, 0xFF, 0xEC, 0x3E, 0xFE, 0x7D, 0x1E, 0x12,\r
+  0x59, 0x93, 0x90, 0x12, 0xF6, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0x02, 0x2B, 0x37, 0x90, 0x12, 0xDB,\r
+  0xE0, 0x25, 0xE0, 0xFD, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x33, 0xFC, 0x74, 0x81, 0x2D, 0xF5, 0x82, 0x74,\r
+  0x81, 0x3C, 0xF5, 0x83, 0xE0, 0x25, 0xE0, 0x24,\r
+  0xE9, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5, 0x83,\r
+  0xE0, 0xFE, 0x74, 0x81, 0x2D, 0xF5, 0x82, 0x74,\r
+  0x81, 0x3C, 0xF5, 0x83, 0xE0, 0x25, 0xE0, 0x24,\r
+  0xE8, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5, 0x83,\r
+  0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF, 0xEC, 0x3E,\r
+  0xFE, 0x7D, 0x14, 0x12, 0x59, 0x93, 0x90, 0x12,\r
+  0xF4, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x25, 0xE0, 0xFD, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x33, 0xFC, 0x74, 0x80, 0x2D, 0xF5, 0x82,\r
+  0x74, 0x81, 0x3C, 0xF5, 0x83, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xC1, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0x74, 0x80, 0x2D, 0xF5, 0x82,\r
+  0x74, 0x81, 0x3C, 0xF5, 0x83, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5,\r
+  0x83, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF, 0xEC,\r
+  0x3E, 0xFE, 0x7D, 0x1E, 0x12, 0x59, 0x93, 0x90,\r
+  0x12, 0xF6, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90,\r
+  0x12, 0xF4, 0xE0, 0xC4, 0xF8, 0x54, 0xF0, 0xC8,\r
+  0x68, 0xFE, 0xA3, 0xE0, 0xC4, 0x54, 0x0F, 0x48,\r
+  0xFF, 0x7C, 0x00, 0x7D, 0x03, 0x12, 0x59, 0x81,\r
+  0x90, 0x12, 0xF4, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0xA3, 0xE0, 0xC4, 0xF8, 0x54, 0xF0, 0xC8, 0x68,\r
+  0xFE, 0xA3, 0xE0, 0xC4, 0x54, 0x0F, 0x48, 0xFF,\r
+  0x12, 0x59, 0x81, 0x90, 0x12, 0xF6, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0xE4, 0x90, 0x12, 0xE2, 0xF0,\r
+  0xA3, 0xF0, 0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0,\r
+  0xFD, 0x90, 0x12, 0xDA, 0xE0, 0x33, 0xFC, 0x74,\r
+  0x81, 0x2D, 0xF5, 0x82, 0x74, 0x81, 0x3C, 0xF5,\r
+  0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0xFF, 0x74,\r
+  0x80, 0x2D, 0xF5, 0x82, 0x74, 0x81, 0x3C, 0xF5,\r
+  0x83, 0xE0, 0x7C, 0x00, 0x2F, 0xFF, 0xEC, 0x35,\r
+  0xF0, 0xFE, 0xEF, 0x25, 0xE0, 0xFF, 0xEE, 0x33,\r
+  0xFE, 0xA2, 0xD9, 0xE4, 0x33, 0x2F, 0xFF, 0xEC,\r
+  0x3E, 0x90, 0x12, 0xF0, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x81, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0x60, 0x03, 0x02, 0x2C, 0x7C, 0x90, 0x12, 0xF0,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x24, 0x00, 0xF5,\r
+  0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xFD,\r
+  0x74, 0x50, 0x2F, 0xF5, 0x82, 0x74, 0x60, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x9C,\r
+  0xFE, 0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0,\r
+  0x24, 0x0A, 0xFD, 0xE4, 0x33, 0xFC, 0xC3, 0xEF,\r
+  0x9D, 0xEC, 0x64, 0x80, 0xF8, 0xEE, 0x64, 0x80,\r
+  0x98, 0x50, 0x0E, 0x90, 0x12, 0xE3, 0xE0, 0x04,\r
+  0xF0, 0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04,\r
+  0xF0, 0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0x24, 0x28, 0xF5, 0x82, 0x74, 0x60, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0xFD, 0x74, 0x00, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xC3,\r
+  0x9D, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78,\r
+  0xF1, 0x90, 0x12, 0xFA, 0xE0, 0x24, 0x0A, 0xFD,\r
+  0xE4, 0x33, 0xFC, 0xC3, 0xEF, 0x9D, 0xEC, 0x64,\r
+  0x80, 0xF8, 0xEE, 0x64, 0x80, 0x98, 0x40, 0x03,\r
+  0x02, 0x2E, 0xD9, 0x90, 0x12, 0xE3, 0xE0, 0x04,\r
+  0xF0, 0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04,\r
+  0xF0, 0x02, 0x2E, 0xD9, 0x90, 0x12, 0xDB, 0xE0,\r
+  0x25, 0xE0, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0x33,\r
+  0xFE, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81,\r
+  0x3E, 0xF5, 0x83, 0xE0, 0x64, 0x1D, 0x60, 0x03,\r
+  0x02, 0x2D, 0x3B, 0x90, 0x12, 0xF0, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0x74,\r
+  0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0xB0,\r
+  0x2F, 0xF5, 0x82, 0x74, 0x5F, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x94, 0x00, 0xFE,\r
+  0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0, 0x24,\r
+  0x0A, 0xFD, 0xE4, 0x33, 0xFC, 0xC3, 0xEF, 0x9D,\r
+  0xEC, 0x64, 0x80, 0xF8, 0xEE, 0x64, 0x80, 0x98,\r
+  0x50, 0x0E, 0x90, 0x12, 0xE3, 0xE0, 0x04, 0xF0,\r
+  0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04, 0xF0,\r
+  0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x24, 0xD8, 0xF5, 0x82, 0x74, 0x5F, 0x3E, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0x74, 0x00, 0x2F, 0xF5, 0x82,\r
+  0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xC3, 0x9D,\r
+  0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78, 0xF1,\r
+  0x90, 0x12, 0xFA, 0xE0, 0x24, 0x0A, 0xFD, 0xE4,\r
+  0x33, 0xFC, 0xC3, 0xEF, 0x9D, 0xEC, 0x64, 0x80,\r
+  0xF8, 0xEE, 0x64, 0x80, 0x98, 0x40, 0x03, 0x02,\r
+  0x2E, 0xD9, 0x90, 0x12, 0xE3, 0xE0, 0x04, 0xF0,\r
+  0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04, 0xF0,\r
+  0x02, 0x2E, 0xD9, 0x90, 0x12, 0xF0, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x24, 0xFF, 0xF5, 0x82, 0x74,\r
+  0x5F, 0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0xD7,\r
+  0x2F, 0xF5, 0x82, 0x74, 0x5F, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x94, 0x00, 0xFE,\r
+  0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0, 0xFD,\r
+  0xC3, 0xEF, 0x9D, 0x74, 0x80, 0xF8, 0x6E, 0x98,\r
+  0x50, 0x0E, 0x90, 0x12, 0xE3, 0xE0, 0x04, 0xF0,\r
+  0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04, 0xF0,\r
+  0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x24, 0x27, 0xF5, 0x82, 0x74, 0x60, 0x3E, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0x74, 0xFF, 0x2F, 0xF5, 0x82,\r
+  0x74, 0x5F, 0x3E, 0xF5, 0x83, 0xE0, 0xC3, 0x9D,\r
+  0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78, 0xF1,\r
+  0x90, 0x12, 0xFA, 0xE0, 0xFD, 0xC3, 0xEF, 0x9D,\r
+  0x74, 0x80, 0xF8, 0x6E, 0x98, 0x50, 0x0E, 0x90,\r
+  0x12, 0xE3, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90,\r
+  0x12, 0xE2, 0xE0, 0x04, 0xF0, 0x90, 0x12, 0xF0,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x24, 0x00, 0xF5,\r
+  0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xFD,\r
+  0x74, 0xD8, 0x2F, 0xF5, 0x82, 0x74, 0x5F, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x94,\r
+  0x00, 0xFE, 0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA,\r
+  0xE0, 0xFD, 0xC3, 0xEF, 0x9D, 0x74, 0x80, 0xF8,\r
+  0x6E, 0x98, 0x50, 0x0E, 0x90, 0x12, 0xE3, 0xE0,\r
+  0x04, 0xF0, 0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0,\r
+  0x04, 0xF0, 0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x24, 0x28, 0xF5, 0x82, 0x74, 0x60,\r
+  0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0x00, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0xC3, 0x9D, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12,\r
+  0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0, 0xFD, 0xC3,\r
+  0xEF, 0x9D, 0x74, 0x80, 0xF8, 0x6E, 0x98, 0x50,\r
+  0x0E, 0x90, 0x12, 0xE3, 0xE0, 0x04, 0xF0, 0x70,\r
+  0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04, 0xF0, 0x90,\r
+  0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x24,\r
+  0x01, 0xF5, 0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0xFD, 0x74, 0xD9, 0x2F, 0xF5, 0x82, 0x74,\r
+  0x5F, 0x3E, 0xF5, 0x83, 0xE0, 0xC3, 0x9D, 0xFF,\r
+  0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78, 0xF1, 0x90,\r
+  0x12, 0xFA, 0xE0, 0xFD, 0xC3, 0xEF, 0x9D, 0x74,\r
+  0x80, 0xF8, 0x6E, 0x98, 0x50, 0x0E, 0x90, 0x12,\r
+  0xE3, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90, 0x12,\r
+  0xE2, 0xE0, 0x04, 0xF0, 0x90, 0x12, 0xF0, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0x24, 0x29, 0xF5, 0x82,\r
+  0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74,\r
+  0x01, 0x2F, 0xF5, 0x82, 0x74, 0x60, 0x3E, 0xF5,\r
+  0x83, 0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x94, 0x00,\r
+  0xFE, 0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0,\r
+  0xFD, 0xC3, 0xEF, 0x9D, 0x74, 0x80, 0xF8, 0x6E,\r
+  0x98, 0x50, 0x0E, 0x90, 0x12, 0xE3, 0xE0, 0x04,\r
+  0xF0, 0x70, 0x06, 0x90, 0x12, 0xE2, 0xE0, 0x04,\r
+  0xF0, 0xE4, 0x90, 0x12, 0xE4, 0xF0, 0xA3, 0xF0,\r
+  0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x24, 0xD8, 0xF5, 0x82, 0x74, 0x5F, 0x3E, 0xF5,\r
+  0x83, 0xE0, 0xFD, 0x74, 0xD7, 0x2F, 0xF5, 0x82,\r
+  0x74, 0x5F, 0x3E, 0xF5, 0x83, 0xE0, 0xC3, 0x9D,\r
+  0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78, 0xF1,\r
+  0x90, 0x12, 0xFA, 0xE0, 0xFD, 0xD3, 0xEF, 0x9D,\r
+  0x74, 0x80, 0xF8, 0x6E, 0x98, 0x40, 0x0E, 0x90,\r
+  0x12, 0xE5, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90,\r
+  0x12, 0xE4, 0xE0, 0x04, 0xF0, 0x90, 0x12, 0xF0,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x24, 0xD9, 0xF5,\r
+  0x82, 0x74, 0x5F, 0x3E, 0xF5, 0x83, 0xE0, 0xFD,\r
+  0x74, 0xD8, 0x2F, 0xF5, 0x82, 0x74, 0x5F, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x94,\r
+  0x00, 0xFE, 0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA,\r
+  0xE0, 0xFD, 0xD3, 0xEF, 0x9D, 0x74, 0x80, 0xF8,\r
+  0x6E, 0x98, 0x40, 0x0E, 0x90, 0x12, 0xE5, 0xE0,\r
+  0x04, 0xF0, 0x70, 0x06, 0x90, 0x12, 0xE4, 0xE0,\r
+  0x04, 0xF0, 0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0x74, 0x60,\r
+  0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74, 0xFF, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x5F, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0xC3, 0x9D, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12,\r
+  0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0, 0xFD, 0xD3,\r
+  0xEF, 0x9D, 0x74, 0x80, 0xF8, 0x6E, 0x98, 0x40,\r
+  0x0E, 0x90, 0x12, 0xE5, 0xE0, 0x04, 0xF0, 0x70,\r
+  0x06, 0x90, 0x12, 0xE4, 0xE0, 0x04, 0xF0, 0x90,\r
+  0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x24,\r
+  0x01, 0xF5, 0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0xFD, 0x74, 0x00, 0x2F, 0xF5, 0x82, 0x74,\r
+  0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xC3, 0x9D, 0xFF,\r
+  0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78, 0xF1, 0x90,\r
+  0x12, 0xFA, 0xE0, 0xFD, 0xD3, 0xEF, 0x9D, 0x74,\r
+  0x80, 0xF8, 0x6E, 0x98, 0x40, 0x0E, 0x90, 0x12,\r
+  0xE5, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90, 0x12,\r
+  0xE4, 0xE0, 0x04, 0xF0, 0x90, 0x12, 0xF0, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0x24, 0x28, 0xF5, 0x82,\r
+  0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74,\r
+  0x27, 0x2F, 0xF5, 0x82, 0x74, 0x60, 0x3E, 0xF5,\r
+  0x83, 0xE0, 0xC3, 0x9D, 0xFF, 0xE4, 0x94, 0x00,\r
+  0xFE, 0x12, 0x78, 0xF1, 0x90, 0x12, 0xFA, 0xE0,\r
+  0xFD, 0xD3, 0xEF, 0x9D, 0x74, 0x80, 0xF8, 0x6E,\r
+  0x98, 0x40, 0x0E, 0x90, 0x12, 0xE5, 0xE0, 0x04,\r
+  0xF0, 0x70, 0x06, 0x90, 0x12, 0xE4, 0xE0, 0x04,\r
+  0xF0, 0x90, 0x12, 0xF0, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0x24, 0x29, 0xF5, 0x82, 0x74, 0x60, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0xFD, 0x74, 0x28, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x60, 0x3E, 0xF5, 0x83, 0xE0, 0xC3,\r
+  0x9D, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x12, 0x78,\r
+  0xF1, 0x90, 0x12, 0xFA, 0xE0, 0xFD, 0xD3, 0xEF,\r
+  0x9D, 0x74, 0x80, 0xF8, 0x6E, 0x98, 0x40, 0x0E,\r
+  0x90, 0x12, 0xE5, 0xE0, 0x04, 0xF0, 0x70, 0x06,\r
+  0x90, 0x12, 0xE4, 0xE0, 0x04, 0xF0, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5, 0x82,\r
+  0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFD, 0x74,\r
+  0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5,\r
+  0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10, 0xF5, 0x83,\r
+  0xE5, 0x82, 0x2D, 0xF5, 0x82, 0xE4, 0x35, 0x83,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x90, 0xF1, 0x03, 0xE0,\r
+  0xFF, 0x90, 0x12, 0xF5, 0xE0, 0x2F, 0xFF, 0x90,\r
+  0x12, 0xF4, 0xE0, 0x34, 0x00, 0xFE, 0x90, 0x12,\r
+  0xF0, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x24, 0x00,\r
+  0xF5, 0x82, 0x74, 0x60, 0x3C, 0xF5, 0x83, 0xE0,\r
+  0xD3, 0x9F, 0xE4, 0x9E, 0x40, 0x62, 0x90, 0xF1,\r
+  0x03, 0xE0, 0xFF, 0x90, 0x12, 0xF7, 0xE0, 0x2F,\r
+  0xFF, 0x90, 0x12, 0xF6, 0xE0, 0x34, 0x00, 0xFE,\r
+  0x74, 0x00, 0x2D, 0xF5, 0x82, 0x74, 0x60, 0x3C,\r
+  0xF5, 0x83, 0xE0, 0xD3, 0x9F, 0xE4, 0x9E, 0x40,\r
+  0x3F, 0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80,\r
+  0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0xFD, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74,\r
+  0x81, 0x3E, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14,\r
+  0xA4, 0x24, 0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34,\r
+  0x10, 0xF5, 0x83, 0xE5, 0x82, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x35, 0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0,\r
+  0x90, 0x12, 0xDA, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0x25, 0xE0, 0xFB, 0xEC, 0x33, 0xFA, 0x74, 0x81,\r
+  0x2B, 0xF5, 0x82, 0x74, 0x81, 0x3A, 0xF5, 0x83,\r
+  0xE0, 0x70, 0x4D, 0xD3, 0x90, 0x12, 0xE3, 0xE0,\r
+  0x94, 0x01, 0x90, 0x12, 0xE2, 0xE0, 0x94, 0x00,\r
+  0x50, 0x03, 0x02, 0x32, 0x5E, 0xED, 0x25, 0xE0,\r
+  0xFF, 0xEC, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFD,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2D, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0xE4, 0xF0, 0x02, 0x32, 0x5E,\r
+  0x74, 0x81, 0x2B, 0xF5, 0x82, 0x74, 0x81, 0x3A,\r
+  0xF5, 0x83, 0xE0, 0x64, 0x1D, 0x70, 0x52, 0xD3,\r
+  0x90, 0x12, 0xE3, 0xE0, 0x94, 0x01, 0x90, 0x12,\r
+  0xE2, 0xE0, 0x94, 0x00, 0x50, 0x03, 0x02, 0x32,\r
+  0x5E, 0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80,\r
+  0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0xFD, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74,\r
+  0x81, 0x3E, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14,\r
+  0xA4, 0x24, 0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34,\r
+  0x10, 0xF5, 0x83, 0xE5, 0x82, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x35, 0x83, 0xF5, 0x83, 0xE4, 0xF0, 0x80,\r
+  0x4D, 0xD3, 0x90, 0x12, 0xE3, 0xE0, 0x94, 0x05,\r
+  0x90, 0x12, 0xE2, 0xE0, 0x94, 0x00, 0x40, 0x3E,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0xFD, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81,\r
+  0x3E, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10,\r
+  0xF5, 0x83, 0xE5, 0x82, 0x2D, 0xF5, 0x82, 0xE4,\r
+  0x35, 0x83, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5, 0x82,\r
+  0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xF5, 0xCB,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0xF5, 0xCC, 0xD2, 0xB5, 0x30,\r
+  0xB5, 0x05, 0x75, 0x9E, 0x55, 0x80, 0xF8, 0x7D,\r
+  0x19, 0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x81,\r
+  0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0x70, 0x03, 0x02, 0x35, 0x6E, 0x74, 0x81,\r
+  0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83,\r
+  0xE0, 0x64, 0x1D, 0x70, 0x03, 0x02, 0x35, 0x6E,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0x70, 0x03, 0x02, 0x35, 0x6E, 0x74, 0x80, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0x64, 0x13, 0x70, 0x03, 0x02, 0x35, 0x6E, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0x25,\r
+  0xE0, 0xFF, 0xEA, 0x33, 0xFE, 0x74, 0x80, 0x2F,\r
+  0xF5, 0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81,\r
+  0x3E, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10,\r
+  0xF5, 0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4,\r
+  0x35, 0x83, 0xF5, 0x83, 0xE0, 0x64, 0x01, 0x60,\r
+  0x03, 0x02, 0x35, 0x6E, 0xC3, 0xE5, 0xCA, 0x95,\r
+  0xB7, 0xC3, 0x9D, 0x50, 0x39, 0xEB, 0x25, 0xE0,\r
+  0xFF, 0xEA, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0xEB, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x0F, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xB9, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0xEC, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x0F, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xBA, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0xED, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x0F, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xBD, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0xFF, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x0F, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xBE, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0x01, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xC2, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0x13, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xC3, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0x14, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2C, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0xC3, 0xE5,\r
+  0xCA, 0x95, 0xC4, 0xC3, 0x9D, 0x50, 0x3F, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x33, 0xFE, 0x74, 0x80, 0x2F, 0xF5,\r
+  0x82, 0x74, 0x81, 0x3E, 0xF5, 0x83, 0xE0, 0xFD,\r
+  0x74, 0x81, 0x2F, 0xF5, 0x82, 0x74, 0x81, 0x3E,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x14, 0xA4, 0x24,\r
+  0x15, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x10, 0xF5,\r
+  0x83, 0xE5, 0x82, 0x2D, 0xF5, 0x82, 0xE4, 0x35,\r
+  0x83, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x90, 0x12,\r
+  0xDB, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x29, 0xD9, 0x22,\r
+  0xE4, 0x90, 0x8F, 0xF0, 0xF0, 0xD2, 0x18, 0x30,\r
+  0x14, 0x03, 0x02, 0x3B, 0x5F, 0x90, 0x12, 0x5F,\r
+  0xF0, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFF, 0xC3, 0x95, 0x0D, 0x40, 0x03, 0x02,\r
+  0x3A, 0x13, 0x74, 0xE5, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x88, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0x02,\r
+  0x3A, 0x0A, 0x90, 0x12, 0xDA, 0xE0, 0x24, 0xC0,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x12, 0xF5, 0x83, 0xE0,\r
+  0x60, 0x03, 0x02, 0x3A, 0x0A, 0x74, 0x14, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xE0,\r
+  0xC3, 0x94, 0x01, 0x74, 0x80, 0x94, 0x88, 0x40,\r
+  0x03, 0x02, 0x3A, 0x0A, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x24, 0xE5, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0xE0, 0x64, 0x03, 0x60, 0x04, 0xC2, 0x18,\r
+  0x80, 0x07, 0x7F, 0x70, 0x7E, 0x17, 0x12, 0x67,\r
+  0xEE, 0x90, 0x12, 0xDA, 0xE0, 0x24, 0xE5, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0xB4,\r
+  0x02, 0x08, 0x90, 0x12, 0x5F, 0xE0, 0x04, 0xF0,\r
+  0x80, 0x06, 0x90, 0x12, 0x5F, 0xE0, 0x14, 0xF0,\r
+  0x90, 0x12, 0xDA, 0xE0, 0xFF, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xFD, 0xA3, 0xE0, 0x90, 0x12,\r
+  0xDB, 0xCD, 0xF0, 0xA3, 0xED, 0xF0, 0xEF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFD, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x90, 0x12, 0xDB, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE1, 0x74, 0x1E,\r
+  0xF0, 0xA3, 0x74, 0x14, 0xF0, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0xEE, 0x33, 0x95, 0xE0, 0xFD, 0xFC, 0xE4, 0xFB,\r
+  0x7A, 0x05, 0xF9, 0xF8, 0x12, 0x5A, 0x34, 0x78,\r
+  0x04, 0x12, 0x5B, 0x75, 0x90, 0x12, 0xDD, 0x12,\r
+  0x5B, 0x88, 0x90, 0x12, 0xE1, 0xE0, 0xFF, 0x90,\r
+  0x28, 0x0B, 0xE4, 0x93, 0x8F, 0xF0, 0xA4, 0xFF,\r
+  0xAE, 0xF0, 0xFB, 0xAA, 0x06, 0xE4, 0xF9, 0xF8,\r
+  0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x12, 0x5A,\r
+  0xBF, 0xAC, 0x00, 0xAD, 0x01, 0xAE, 0x02, 0xAF,\r
+  0x03, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x12, 0xE1,\r
+  0xE0, 0xFF, 0x90, 0x28, 0x0B, 0xE4, 0x93, 0x8F,\r
+  0xF0, 0xA4, 0xFF, 0xE5, 0xF0, 0xA2, 0xE7, 0x13,\r
+  0xFE, 0xEF, 0x13, 0xFF, 0xFB, 0xAA, 0x06, 0xEA,\r
+  0x33, 0x95, 0xE0, 0xF9, 0xF8, 0xD0, 0x07, 0xD0,\r
+  0x06, 0xD3, 0x12, 0x5B, 0x51, 0x50, 0x3C, 0x90,\r
+  0x12, 0xE1, 0xE0, 0xFF, 0x90, 0x28, 0x0B, 0xE4,\r
+  0x93, 0x8F, 0xF0, 0xA4, 0xFF, 0xAE, 0xF0, 0xFB,\r
+  0xAA, 0x06, 0xE4, 0xF9, 0xF8, 0x90, 0x12, 0xDD,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x12, 0x5A, 0xBF, 0xEF, 0x24,\r
+  0x01, 0xFF, 0xE4, 0x3E, 0xFE, 0xE4, 0x3D, 0xFD,\r
+  0xE4, 0x3C, 0xFC, 0x90, 0x12, 0xDD, 0x12, 0x5B,\r
+  0x88, 0x80, 0x33, 0x90, 0x12, 0xDD, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0xC0, 0x06, 0xC0, 0x07, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x28, 0x0B, 0xE4, 0x93, 0x8F, 0xF0, 0xA4,\r
+  0xFF, 0xAE, 0xF0, 0xFB, 0xAA, 0x06, 0xE4, 0xF9,\r
+  0xF8, 0xD0, 0x07, 0xD0, 0x06, 0x12, 0x5A, 0xBF,\r
+  0x90, 0x12, 0xDD, 0x12, 0x5B, 0x88, 0x90, 0x12,\r
+  0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0x78, 0x04, 0x12, 0x5B,\r
+  0x62, 0x90, 0x12, 0xDA, 0xE0, 0xFD, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0xEE, 0x33, 0x95, 0xE0, 0xFD,\r
+  0xFC, 0xE4, 0x7B, 0x20, 0x7A, 0x03, 0xF9, 0xF8,\r
+  0x12, 0x5A, 0x34, 0x78, 0x04, 0x12, 0x5B, 0x75,\r
+  0x90, 0x12, 0xDD, 0x12, 0x5B, 0x88, 0x90, 0x12,\r
+  0xE2, 0xE0, 0xFF, 0x90, 0x28, 0x0C, 0xE4, 0x93,\r
+  0x8F, 0xF0, 0xA4, 0xFF, 0xAE, 0xF0, 0xFB, 0xAA,\r
+  0x06, 0xE4, 0xF9, 0xF8, 0x90, 0x12, 0xDD, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x12, 0x5A, 0xBF, 0xAC, 0x00, 0xAD,\r
+  0x01, 0xAE, 0x02, 0xAF, 0x03, 0xC0, 0x06, 0xC0,\r
+  0x07, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x90, 0x28,\r
+  0x0C, 0xE4, 0x93, 0x8F, 0xF0, 0xA4, 0xFF, 0xE5,\r
+  0xF0, 0xA2, 0xE7, 0x13, 0xFE, 0xEF, 0x13, 0xFF,\r
+  0xFB, 0xAA, 0x06, 0xEA, 0x33, 0x95, 0xE0, 0xF9,\r
+  0xF8, 0xD0, 0x07, 0xD0, 0x06, 0xD3, 0x12, 0x5B,\r
+  0x51, 0x50, 0x3C, 0x90, 0x12, 0xE2, 0xE0, 0xFF,\r
+  0x90, 0x28, 0x0C, 0xE4, 0x93, 0x8F, 0xF0, 0xA4,\r
+  0xFF, 0xAE, 0xF0, 0xFB, 0xAA, 0x06, 0xE4, 0xF9,\r
+  0xF8, 0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x12,\r
+  0x5A, 0xBF, 0xEF, 0x24, 0x01, 0xFF, 0xE4, 0x3E,\r
+  0xFE, 0xE4, 0x3D, 0xFD, 0xE4, 0x3C, 0xFC, 0x90,\r
+  0x12, 0xDD, 0x12, 0x5B, 0x88, 0x80, 0x35, 0x90,\r
+  0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC0, 0x06, 0xC0,\r
+  0x07, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x90, 0x28,\r
+  0x0C, 0xE4, 0x93, 0x8F, 0xF0, 0xA4, 0xFF, 0xAE,\r
+  0xF0, 0xFB, 0xAA, 0x06, 0xE4, 0xF9, 0xF8, 0xD0,\r
+  0x07, 0xD0, 0x06, 0x12, 0x5A, 0xBF, 0x90, 0x12,\r
+  0xDD, 0x12, 0x5B, 0x88, 0x90, 0x12, 0xDD, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x78, 0x04, 0x12, 0x5B, 0x62, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x04,\r
+  0xFF, 0x33, 0x33, 0x33, 0x54, 0xF8, 0xFF, 0x74,\r
+  0xE5, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5,\r
+  0x83, 0xE0, 0x4F, 0xFF, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x03, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xEF, 0xF0, 0xED,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0x78, 0x04, 0xCE, 0xA2, 0xE7, 0x13, 0xCE,\r
+  0x13, 0xD8, 0xF8, 0xFF, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xEF, 0xF0, 0xED,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0x78, 0x04, 0xCE, 0xA2, 0xE7, 0x13, 0xCE,\r
+  0x13, 0xD8, 0xF8, 0xFF, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x01, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xEF, 0xF0, 0xED,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xA3, 0xE0, 0xC4,\r
+  0xF8, 0x54, 0x0F, 0xC8, 0x68, 0xFF, 0x05, 0x82,\r
+  0xD5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xE0,\r
+  0xC4, 0x54, 0xF0, 0x48, 0xEF, 0x54, 0xF0, 0xFF,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xA3,\r
+  0xE0, 0x54, 0x0F, 0x4F, 0xFF, 0x90, 0x8F, 0xF0,\r
+  0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x02, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xEF, 0xF0,\r
+  0x90, 0x3F, 0xFE, 0xE0, 0xB4, 0x01, 0x2D, 0xE5,\r
+  0x09, 0xFF, 0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0,\r
+  0x06, 0xA4, 0x24, 0x04, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x8F, 0xF5, 0x83, 0xEF, 0xF0, 0xAF, 0x0A, 0x90,\r
+  0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24,\r
+  0x05, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83,\r
+  0xEF, 0xF0, 0x80, 0x28, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x04, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74, 0x08, 0xF0,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x05, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0x74, 0x08, 0xF0, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x04, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0,\r
+  0x02, 0x35, 0x95, 0x90, 0x8F, 0xF0, 0xE0, 0xFF,\r
+  0x90, 0x12, 0x5F, 0xE0, 0xB5, 0x07, 0x04, 0xD2,\r
+  0x04, 0x80, 0x02, 0xC2, 0x04, 0x20, 0x16, 0x03,\r
+  0x02, 0x3A, 0xC4, 0x78, 0x10, 0xE6, 0x60, 0x02,\r
+  0xC2, 0x18, 0x78, 0x11, 0xE6, 0x24, 0x14, 0xFF,\r
+  0x33, 0x33, 0x33, 0x54, 0xF8, 0xFF, 0x78, 0x10,\r
+  0xE6, 0xFE, 0x4F, 0xFF, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xEF, 0xF0, 0x90,\r
+  0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24,\r
+  0x01, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83,\r
+  0xE4, 0xF0, 0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0,\r
+  0x06, 0xA4, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x8F, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x8F, 0xF0,\r
+  0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x03, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xE4, 0xF0,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x04, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xE4, 0xF0, 0x90, 0x8F, 0xF0, 0xE0, 0x75,\r
+  0xF0, 0x06, 0xA4, 0x24, 0x05, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8F, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x8F,\r
+  0xF0, 0xE0, 0x04, 0xF0, 0xEE, 0x70, 0x05, 0x78,\r
+  0x11, 0xF6, 0xC2, 0x16, 0x30, 0x0B, 0x03, 0x02,\r
+  0x3B, 0x4A, 0x90, 0x8F, 0xF0, 0xE0, 0x90, 0x12,\r
+  0xDA, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0xFF, 0xC3,\r
+  0x95, 0x0D, 0x50, 0x6E, 0xEF, 0x75, 0xF0, 0x06,\r
+  0xA4, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x8F,\r
+  0xF5, 0x83, 0x74, 0xFF, 0xF0, 0xEF, 0x75, 0xF0,\r
+  0x06, 0xA4, 0x24, 0x01, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x8F, 0xF5, 0x83, 0x74, 0xFF, 0xF0, 0xEF, 0x75,\r
+  0xF0, 0x06, 0xA4, 0x24, 0x02, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8F, 0xF5, 0x83, 0x74, 0xFF, 0xF0, 0xEF,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x03, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74, 0xFF, 0xF0,\r
+  0xEF, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x04, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74, 0xFF,\r
+  0xF0, 0xEF, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x05,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74,\r
+  0xFF, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0,\r
+  0x80, 0x88, 0x90, 0x8F, 0xF0, 0xE0, 0xD3, 0x94,\r
+  0x00, 0x50, 0x03, 0x02, 0x41, 0x2C, 0x20, 0x18,\r
+  0x03, 0x02, 0x41, 0x2C, 0xD2, 0x0C, 0x22, 0xE4,\r
+  0x90, 0x12, 0xDA, 0xF0, 0x90, 0x12, 0xDA, 0xE0,\r
+  0xFF, 0xC3, 0x95, 0x0D, 0x40, 0x03, 0x02, 0x3F,\r
+  0xE7, 0xE4, 0x90, 0x12, 0x5F, 0xF0, 0x74, 0xE5,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83,\r
+  0xE0, 0x70, 0x03, 0x02, 0x3F, 0xDE, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x12, 0xF5, 0x83, 0xE0, 0x60, 0x03, 0x02, 0x3F,\r
+  0xDE, 0x74, 0x14, 0x2F, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x8A, 0xF5, 0x83, 0xE0, 0xC3, 0x94, 0x01, 0x74,\r
+  0x80, 0x94, 0x88, 0x40, 0x03, 0x02, 0x3F, 0xDE,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x24, 0xE5, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0x64, 0x03,\r
+  0x60, 0x04, 0xC2, 0x18, 0x80, 0x07, 0x7F, 0x70,\r
+  0x7E, 0x17, 0x12, 0x67, 0xEE, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x24, 0xE5, 0xF5, 0x82, 0xE4, 0x34, 0x88,\r
+  0xF5, 0x83, 0xE0, 0xB4, 0x02, 0x08, 0x90, 0x12,\r
+  0x5F, 0xE0, 0x04, 0xF0, 0x80, 0x06, 0x90, 0x12,\r
+  0x5F, 0xE0, 0x14, 0xF0, 0x90, 0x12, 0xDA, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFD,\r
+  0xA3, 0xE0, 0x90, 0x12, 0xDB, 0xCD, 0xF0, 0xA3,\r
+  0xED, 0xF0, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xDB, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90,\r
+  0x12, 0xE1, 0x74, 0x1E, 0xF0, 0xA3, 0x74, 0x14,\r
+  0xF0, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xEE, 0x33, 0x95, 0xE0,\r
+  0xFD, 0xFC, 0xE4, 0xFB, 0x7A, 0x05, 0xF9, 0xF8,\r
+  0x12, 0x5A, 0x34, 0x78, 0x04, 0x12, 0x5B, 0x75,\r
+  0x90, 0x12, 0xDD, 0x12, 0x5B, 0x88, 0x90, 0x12,\r
+  0xE1, 0xE0, 0xFF, 0x90, 0x28, 0x0B, 0xE4, 0x93,\r
+  0x8F, 0xF0, 0xA4, 0xFF, 0xAE, 0xF0, 0xFB, 0xAA,\r
+  0x06, 0xE4, 0xF9, 0xF8, 0x90, 0x12, 0xDD, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x12, 0x5A, 0xBF, 0xAC, 0x00, 0xAD,\r
+  0x01, 0xAE, 0x02, 0xAF, 0x03, 0xC0, 0x06, 0xC0,\r
+  0x07, 0x90, 0x12, 0xE1, 0xE0, 0xFF, 0x90, 0x28,\r
+  0x0B, 0xE4, 0x93, 0x8F, 0xF0, 0xA4, 0xFF, 0xE5,\r
+  0xF0, 0xA2, 0xE7, 0x13, 0xFE, 0xEF, 0x13, 0xFF,\r
+  0xFB, 0xAA, 0x06, 0xEA, 0x33, 0x95, 0xE0, 0xF9,\r
+  0xF8, 0xD0, 0x07, 0xD0, 0x06, 0xD3, 0x12, 0x5B,\r
+  0x51, 0x50, 0x3C, 0x90, 0x12, 0xE1, 0xE0, 0xFF,\r
+  0x90, 0x28, 0x0B, 0xE4, 0x93, 0x8F, 0xF0, 0xA4,\r
+  0xFF, 0xAE, 0xF0, 0xFB, 0xAA, 0x06, 0xE4, 0xF9,\r
+  0xF8, 0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x12,\r
+  0x5A, 0xBF, 0xEF, 0x24, 0x01, 0xFF, 0xE4, 0x3E,\r
+  0xFE, 0xE4, 0x3D, 0xFD, 0xE4, 0x3C, 0xFC, 0x90,\r
+  0x12, 0xDD, 0x12, 0x5B, 0x88, 0x80, 0x33, 0x90,\r
+  0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC0, 0x06, 0xC0,\r
+  0x07, 0xA3, 0xE0, 0xFF, 0x90, 0x28, 0x0B, 0xE4,\r
+  0x93, 0x8F, 0xF0, 0xA4, 0xFF, 0xAE, 0xF0, 0xFB,\r
+  0xAA, 0x06, 0xE4, 0xF9, 0xF8, 0xD0, 0x07, 0xD0,\r
+  0x06, 0x12, 0x5A, 0xBF, 0x90, 0x12, 0xDD, 0x12,\r
+  0x5B, 0x88, 0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3,\r
+  0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x78, 0x04, 0x12, 0x5B, 0x62, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFD, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xEE,\r
+  0x33, 0x95, 0xE0, 0xFD, 0xFC, 0xE4, 0x7B, 0x20,\r
+  0x7A, 0x03, 0xF9, 0xF8, 0x12, 0x5A, 0x34, 0x78,\r
+  0x04, 0x12, 0x5B, 0x75, 0x90, 0x12, 0xDD, 0x12,\r
+  0x5B, 0x88, 0x90, 0x12, 0xE2, 0xE0, 0xFF, 0x90,\r
+  0x28, 0x0C, 0xE4, 0x93, 0x8F, 0xF0, 0xA4, 0xFF,\r
+  0xAE, 0xF0, 0xFB, 0xAA, 0x06, 0xE4, 0xF9, 0xF8,\r
+  0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x12, 0x5A,\r
+  0xBF, 0xAC, 0x00, 0xAD, 0x01, 0xAE, 0x02, 0xAF,\r
+  0x03, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFF, 0x90, 0x28, 0x0C, 0xE4, 0x93, 0x8F,\r
+  0xF0, 0xA4, 0xFF, 0xE5, 0xF0, 0xA2, 0xE7, 0x13,\r
+  0xFE, 0xEF, 0x13, 0xFF, 0xFB, 0xAA, 0x06, 0xEA,\r
+  0x33, 0x95, 0xE0, 0xF9, 0xF8, 0xD0, 0x07, 0xD0,\r
+  0x06, 0xD3, 0x12, 0x5B, 0x51, 0x50, 0x3C, 0x90,\r
+  0x12, 0xE2, 0xE0, 0xFF, 0x90, 0x28, 0x0C, 0xE4,\r
+  0x93, 0x8F, 0xF0, 0xA4, 0xFF, 0xAE, 0xF0, 0xFB,\r
+  0xAA, 0x06, 0xE4, 0xF9, 0xF8, 0x90, 0x12, 0xDD,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x12, 0x5A, 0xBF, 0xEF, 0x24,\r
+  0x01, 0xFF, 0xE4, 0x3E, 0xFE, 0xE4, 0x3D, 0xFD,\r
+  0xE4, 0x3C, 0xFC, 0x90, 0x12, 0xDD, 0x12, 0x5B,\r
+  0x88, 0x80, 0x35, 0x90, 0x12, 0xDD, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x12, 0xE2,\r
+  0xE0, 0xFF, 0x90, 0x28, 0x0C, 0xE4, 0x93, 0x8F,\r
+  0xF0, 0xA4, 0xFF, 0xAE, 0xF0, 0xFB, 0xAA, 0x06,\r
+  0xE4, 0xF9, 0xF8, 0xD0, 0x07, 0xD0, 0x06, 0x12,\r
+  0x5A, 0xBF, 0x90, 0x12, 0xDD, 0x12, 0x5B, 0x88,\r
+  0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x78, 0x04,\r
+  0x12, 0x5B, 0x62, 0x90, 0x12, 0xDA, 0xE0, 0xFD,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0xED, 0x04, 0xFF, 0x33, 0x33, 0x33,\r
+  0x54, 0xF8, 0xFF, 0x74, 0xE5, 0x2D, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0x4F, 0xFF,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xEF, 0xF0, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0x78, 0x04, 0xCE,\r
+  0xA2, 0xE7, 0x13, 0xCE, 0x13, 0xD8, 0xF8, 0xFF,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x78, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xEF, 0xF0, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0x78, 0x04, 0xCE,\r
+  0xA2, 0xE7, 0x13, 0xCE, 0x13, 0xD8, 0xF8, 0xFF,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x79, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xEF, 0xF0, 0xED, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xA3, 0xE0, 0xC4, 0xF8, 0x54, 0x0F, 0xC8,\r
+  0x68, 0xFF, 0x05, 0x82, 0xD5, 0x82, 0x02, 0x15,\r
+  0x83, 0x15, 0x82, 0xE0, 0xC4, 0x54, 0xF0, 0x48,\r
+  0xEF, 0x54, 0xF0, 0xFF, 0xED, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xA3, 0xE0, 0x54, 0x0F, 0x4F,\r
+  0xFF, 0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06,\r
+  0xA4, 0x24, 0x7A, 0xF5, 0x82, 0xE4, 0x34, 0x8F,\r
+  0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x3F, 0xFE, 0xE0,\r
+  0xB4, 0x01, 0x2D, 0xE5, 0x09, 0xFF, 0x90, 0x8F,\r
+  0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x7C,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xEF,\r
+  0xF0, 0xAF, 0x0A, 0x90, 0x8F, 0xF0, 0xE0, 0x75,\r
+  0xF0, 0x06, 0xA4, 0x24, 0x7D, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8F, 0xF5, 0x83, 0xEF, 0xF0, 0x80, 0x28,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x7C, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0x74, 0x08, 0xF0, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x7D, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74, 0x08, 0xF0,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x04, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x3B, 0x64, 0x90,\r
+  0x8F, 0xF0, 0xE0, 0xFF, 0x90, 0x12, 0x5F, 0xE0,\r
+  0xB5, 0x07, 0x04, 0xD2, 0x04, 0x80, 0x02, 0xC2,\r
+  0x04, 0x20, 0x16, 0x03, 0x02, 0x40, 0x98, 0x78,\r
+  0x10, 0xE6, 0x60, 0x02, 0xC2, 0x18, 0x78, 0x11,\r
+  0xE6, 0x24, 0x14, 0xFF, 0x33, 0x33, 0x33, 0x54,\r
+  0xF8, 0xFF, 0x78, 0x10, 0xE6, 0xFE, 0x4F, 0xFF,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x78, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xEF, 0xF0, 0x90, 0x8F, 0xF0, 0xE0, 0x75,\r
+  0xF0, 0x06, 0xA4, 0x24, 0x79, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8F, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x8F,\r
+  0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x7A,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xE4,\r
+  0xF0, 0x90, 0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06,\r
+  0xA4, 0x24, 0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x8F,\r
+  0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x8F, 0xF0, 0xE0,\r
+  0x75, 0xF0, 0x06, 0xA4, 0x24, 0x7C, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8F, 0xF5, 0x83, 0xE4, 0xF0, 0x90,\r
+  0x8F, 0xF0, 0xE0, 0x75, 0xF0, 0x06, 0xA4, 0x24,\r
+  0x7D, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83,\r
+  0xE4, 0xF0, 0x90, 0x8F, 0xF0, 0xE0, 0x04, 0xF0,\r
+  0xEE, 0x70, 0x05, 0x78, 0x11, 0xF6, 0xC2, 0x16,\r
+  0x30, 0x0B, 0x03, 0x02, 0x41, 0x1E, 0x90, 0x8F,\r
+  0xF0, 0xE0, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFF, 0xC3, 0x95, 0x0D, 0x50, 0x6E,\r
+  0xEF, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x78, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74, 0xFF,\r
+  0xF0, 0xEF, 0x75, 0xF0, 0x06, 0xA4, 0x24, 0x79,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83, 0x74,\r
+  0xFF, 0xF0, 0xEF, 0x75, 0xF0, 0x06, 0xA4, 0x24,\r
+  0x7A, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5, 0x83,\r
+  0x74, 0xFF, 0xF0, 0xEF, 0x75, 0xF0, 0x06, 0xA4,\r
+  0x24, 0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0x74, 0xFF, 0xF0, 0xEF, 0x75, 0xF0, 0x06,\r
+  0xA4, 0x24, 0x7C, 0xF5, 0x82, 0xE4, 0x34, 0x8F,\r
+  0xF5, 0x83, 0x74, 0xFF, 0xF0, 0xEF, 0x75, 0xF0,\r
+  0x06, 0xA4, 0x24, 0x7D, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x8F, 0xF5, 0x83, 0x74, 0xFF, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x80, 0x88, 0x90, 0x8F,\r
+  0xF0, 0xE0, 0xD3, 0x94, 0x00, 0x40, 0x05, 0x30,\r
+  0x18, 0x02, 0xD2, 0x0C, 0x22, 0x90, 0xF1, 0x93,\r
+  0x74, 0x01, 0xF0, 0xE4, 0x90, 0xF1, 0x46, 0xF0,\r
+  0x90, 0xF1, 0x1B, 0x04, 0xF0, 0x90, 0xF0, 0x02,\r
+  0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x01, 0xF0,\r
+  0x90, 0xF0, 0x04, 0x74, 0x08, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0x03, 0xF0, 0x90, 0xF0, 0x06, 0x74, 0x08,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0x05, 0xF0, 0x90, 0xF0,\r
+  0x08, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x07,\r
+  0xF0, 0x90, 0xF0, 0x0A, 0x74, 0x08, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0x09, 0xF0, 0x90, 0xF0, 0x0C, 0x74,\r
+  0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x0B, 0xF0, 0x90,\r
+  0xF0, 0x0E, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0,\r
+  0x0D, 0xF0, 0x90, 0xF0, 0x10, 0x74, 0x20, 0xF0,\r
+  0xE4, 0x90, 0xF0, 0x0F, 0xF0, 0x90, 0xF0, 0x12,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x11, 0x74, 0x01,\r
+  0xF0, 0x90, 0xF0, 0x14, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x13, 0x74, 0x02, 0xF0, 0x90, 0xF0, 0x16,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x15, 0x74, 0x03,\r
+  0xF0, 0x90, 0xF0, 0x18, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x17, 0x74, 0x04, 0xF0, 0x90, 0xF0, 0x1A,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x19, 0x74, 0x05,\r
+  0xF0, 0x90, 0xF0, 0x1C, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x1B, 0x74, 0x06, 0xF0, 0x90, 0xF0, 0x1E,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x1D, 0x74, 0x07,\r
+  0xF0, 0x90, 0xF0, 0x20, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x1F, 0x74, 0x08, 0xF0, 0x90, 0xF0, 0x22,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x21, 0x74, 0x09,\r
+  0xF0, 0x90, 0xF0, 0x24, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x23, 0x74, 0x0A, 0xF0, 0x90, 0xF0, 0x26,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x25, 0x74, 0x0B,\r
+  0xF0, 0x90, 0xF0, 0x28, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x27, 0x74, 0x0C, 0xF0, 0x90, 0xF0, 0x2A,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x29, 0x74, 0x0D,\r
+  0xF0, 0x90, 0xF0, 0x2C, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x2B, 0x74, 0x0E, 0xF0, 0x90, 0xF0, 0x2E,\r
+  0x74, 0x20, 0xF0, 0x90, 0xF0, 0x2D, 0x74, 0x0F,\r
+  0xF0, 0x90, 0xF0, 0x30, 0x74, 0x20, 0xF0, 0x90,\r
+  0xF0, 0x2F, 0x74, 0x10, 0xF0, 0x90, 0xF0, 0x32,\r
+  0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x31, 0xF0,\r
+  0x90, 0xF0, 0x34, 0x74, 0x08, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0x33, 0xF0, 0x90, 0xF0, 0x36, 0x74, 0x08,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0x35, 0xF0, 0x90, 0xF0,\r
+  0x38, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x37,\r
+  0xF0, 0x90, 0xF0, 0x3A, 0x74, 0x08, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0x39, 0xF0, 0x90, 0xF0, 0x3C, 0x74,\r
+  0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x3B, 0xF0, 0x90,\r
+  0xF0, 0x3E, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0,\r
+  0x3D, 0xF0, 0x90, 0xF0, 0x40, 0x74, 0x08, 0xF0,\r
+  0xE4, 0x90, 0xF0, 0x3F, 0xF0, 0x90, 0xF0, 0x42,\r
+  0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x41, 0xF0,\r
+  0x90, 0xF0, 0x44, 0x74, 0x08, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0x43, 0xF0, 0x90, 0xF0, 0x46, 0x74, 0x08,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0x45, 0xF0, 0x90, 0xF0,\r
+  0x48, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x47,\r
+  0xF0, 0x90, 0xF0, 0x4A, 0x74, 0x08, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0x49, 0xF0, 0x90, 0xF0, 0x4C, 0x74,\r
+  0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x4B, 0xF0, 0x90,\r
+  0xF0, 0x4E, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0,\r
+  0x4D, 0xF0, 0x90, 0xF0, 0x50, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x4F, 0x74, 0x11, 0xF0, 0x90, 0xF0,\r
+  0x52, 0x74, 0x20, 0xF0, 0x90, 0xF0, 0x51, 0x74,\r
+  0x12, 0xF0, 0x90, 0xF0, 0x54, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x53, 0x74, 0x13, 0xF0, 0x90, 0xF0,\r
+  0x56, 0x74, 0x20, 0xF0, 0x90, 0xF0, 0x55, 0x74,\r
+  0x14, 0xF0, 0x90, 0xF0, 0x58, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x57, 0x74, 0x15, 0xF0, 0x90, 0xF0,\r
+  0x5A, 0x74, 0x20, 0xF0, 0x90, 0xF0, 0x59, 0x74,\r
+  0x16, 0xF0, 0x90, 0xF0, 0x5C, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x5B, 0x74, 0x17, 0xF0, 0x90, 0xF0,\r
+  0x5E, 0x74, 0x20, 0xF0, 0x90, 0xF0, 0x5D, 0x74,\r
+  0x18, 0xF0, 0x90, 0xF0, 0x60, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x5F, 0x74, 0x19, 0xF0, 0x90, 0xF0,\r
+  0x62, 0x74, 0x20, 0xF0, 0x90, 0xF0, 0x61, 0x74,\r
+  0x1A, 0xF0, 0x90, 0xF0, 0x64, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x63, 0x74, 0x1B, 0xF0, 0x90, 0xF0,\r
+  0x66, 0x74, 0x20, 0xF0, 0x90, 0xF0, 0x65, 0x74,\r
+  0x1C, 0xF0, 0x90, 0xF0, 0x68, 0x74, 0x20, 0xF0,\r
+  0x90, 0xF0, 0x67, 0x74, 0x1D, 0xF0, 0x90, 0xF0,\r
+  0x6A, 0x74, 0x16, 0xF0, 0x90, 0xF0, 0x69, 0x74,\r
+  0x01, 0xF0, 0x90, 0xF0, 0x6C, 0x74, 0x16, 0xF0,\r
+  0xE4, 0x90, 0xF0, 0x6B, 0xF0, 0x90, 0xF0, 0x6E,\r
+  0x74, 0x15, 0xF0, 0x90, 0xF0, 0x6D, 0x74, 0x02,\r
+  0xF0, 0x90, 0xF0, 0x70, 0x74, 0x15, 0xF0, 0x90,\r
+  0xF0, 0x6F, 0x74, 0x01, 0xF0, 0x90, 0xF0, 0x72,\r
+  0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x71, 0xF0,\r
+  0x90, 0xF0, 0x74, 0x74, 0x08, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0x73, 0xF0, 0x90, 0xF0, 0x76, 0x74, 0x08,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0x75, 0xF0, 0x90, 0xF0,\r
+  0x78, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x77,\r
+  0xF0, 0x90, 0xF0, 0x7A, 0x74, 0x08, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0x79, 0xF0, 0x90, 0xF0, 0x7C, 0x74,\r
+  0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x7B, 0xF0, 0x90,\r
+  0xF0, 0x7E, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0,\r
+  0x7D, 0xF0, 0x90, 0xF0, 0x80, 0x74, 0x08, 0xF0,\r
+  0xE4, 0x90, 0xF0, 0x7F, 0xF0, 0x90, 0xF0, 0x82,\r
+  0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x81, 0xF0,\r
+  0x90, 0xF0, 0x84, 0x74, 0x08, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0x83, 0xF0, 0x90, 0xF0, 0x86, 0x74, 0x08,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0x85, 0xF0, 0x90, 0xF0,\r
+  0x88, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x87,\r
+  0xF0, 0x90, 0xF0, 0x8A, 0x74, 0x08, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0x89, 0xF0, 0x90, 0xF0, 0x8C, 0x74,\r
+  0x08, 0xF0, 0xE4, 0x90, 0xF0, 0x8B, 0xF0, 0x90,\r
+  0xF0, 0x8E, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0,\r
+  0x8D, 0xF0, 0x90, 0xF0, 0x90, 0x74, 0x08, 0xF0,\r
+  0xE4, 0x90, 0xF0, 0x8F, 0xF0, 0x90, 0xF0, 0x92,\r
+  0x74, 0x15, 0xF0, 0xE4, 0x90, 0xF0, 0x91, 0xF0,\r
+  0x90, 0xF0, 0x94, 0x74, 0x14, 0xF0, 0x90, 0xF0,\r
+  0x93, 0x74, 0x02, 0xF0, 0x90, 0xF0, 0x96, 0x74,\r
+  0x14, 0xF0, 0x90, 0xF0, 0x95, 0x74, 0x01, 0xF0,\r
+  0x90, 0xF0, 0x98, 0x74, 0x14, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0x97, 0xF0, 0x90, 0xF0, 0x9A, 0x74, 0x13,\r
+  0xF0, 0x90, 0xF0, 0x99, 0x74, 0x02, 0xF0, 0x90,\r
+  0xF0, 0x9C, 0x74, 0x13, 0xF0, 0x90, 0xF0, 0x9B,\r
+  0x74, 0x01, 0xF0, 0x90, 0xF0, 0x9E, 0x74, 0x13,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0x9D, 0xF0, 0x90, 0xF0,\r
+  0xA0, 0x74, 0x12, 0xF0, 0x90, 0xF0, 0x9F, 0x74,\r
+  0x02, 0xF0, 0x90, 0xF0, 0xA2, 0x74, 0x12, 0xF0,\r
+  0x90, 0xF0, 0xA1, 0x74, 0x01, 0xF0, 0x90, 0xF0,\r
+  0xA4, 0x74, 0x12, 0xF0, 0xE4, 0x90, 0xF0, 0xA3,\r
+  0xF0, 0x90, 0xF0, 0xA6, 0x74, 0x11, 0xF0, 0x90,\r
+  0xF0, 0xA5, 0x74, 0x02, 0xF0, 0x90, 0xF0, 0xA8,\r
+  0x74, 0x11, 0xF0, 0x90, 0xF0, 0xA7, 0x74, 0x01,\r
+  0xF0, 0x90, 0xF0, 0xAA, 0x74, 0x11, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0xA9, 0xF0, 0x90, 0xF0, 0xAC, 0x74,\r
+  0x10, 0xF0, 0x90, 0xF0, 0xAB, 0x74, 0x02, 0xF0,\r
+  0x90, 0xF0, 0xAE, 0x74, 0x10, 0xF0, 0x90, 0xF0,\r
+  0xAD, 0x74, 0x01, 0xF0, 0x90, 0xF0, 0xB0, 0x74,\r
+  0x10, 0xF0, 0xE4, 0x90, 0xF0, 0xAF, 0xF0, 0x90,\r
+  0xF0, 0xB2, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0,\r
+  0xB1, 0xF0, 0x90, 0xF0, 0xB4, 0x74, 0x08, 0xF0,\r
+  0xE4, 0x90, 0xF0, 0xB3, 0xF0, 0x90, 0xF0, 0xB6,\r
+  0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0xB5, 0xF0,\r
+  0x90, 0xF0, 0xB8, 0x74, 0x08, 0xF0, 0xE4, 0x90,\r
+  0xF0, 0xB7, 0xF0, 0x90, 0xF0, 0xBA, 0x74, 0x08,\r
+  0xF0, 0xE4, 0x90, 0xF0, 0xB9, 0xF0, 0x90, 0xF0,\r
+  0xBC, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0xF0, 0xBB,\r
+  0xF0, 0x90, 0xF0, 0xBE, 0x74, 0x08, 0xF0, 0xE4,\r
+  0x90, 0xF0, 0xBD, 0xF0, 0x90, 0xF0, 0xC0, 0x74,\r
+  0x08, 0xF0, 0xE4, 0x90, 0xF0, 0xBF, 0xF0, 0x90,\r
+  0xF1, 0x06, 0x74, 0x14, 0xF0, 0x90, 0xF1, 0x07,\r
+  0x74, 0x1E, 0xF0, 0x90, 0xF1, 0x0E, 0x74, 0x03,\r
+  0xF0, 0x90, 0xF1, 0x0F, 0xF0, 0x90, 0xF1, 0x10,\r
+  0xF0, 0x90, 0xF1, 0x11, 0xF0, 0x90, 0xF1, 0x12,\r
+  0xF0, 0x90, 0xF1, 0x13, 0xF0, 0x90, 0xF1, 0x14,\r
+  0x14, 0xF0, 0xE4, 0x90, 0xF1, 0x15, 0xF0, 0x90,\r
+  0xF1, 0x1F, 0x74, 0x08, 0xF0, 0x90, 0xF1, 0x22,\r
+  0x74, 0x03, 0xF0, 0x90, 0xF1, 0x1D, 0x74, 0x08,\r
+  0xF0, 0x90, 0xF1, 0x21, 0x74, 0x0A, 0xF0, 0xE4,\r
+  0x90, 0xF1, 0x1C, 0xF0, 0x90, 0xF1, 0x43, 0x74,\r
+  0x3A, 0xF0, 0x90, 0xF2, 0xA4, 0x74, 0x32, 0xF0,\r
+  0x90, 0xF2, 0xA5, 0xF0, 0x90, 0x28, 0x01, 0xE4,\r
+  0x93, 0x90, 0xF1, 0x01, 0xF0, 0x90, 0x28, 0x00,\r
+  0xE4, 0x93, 0x90, 0xF1, 0x02, 0xF0, 0x90, 0x28,\r
+  0x02, 0xE4, 0x93, 0x90, 0xF1, 0x03, 0xF0, 0x90,\r
+  0x28, 0x03, 0xE4, 0x93, 0x90, 0xF1, 0x04, 0xF0,\r
+  0x90, 0x28, 0x04, 0xE4, 0x93, 0x90, 0xF1, 0x05,\r
+  0xF0, 0x90, 0x28, 0x05, 0xE4, 0x93, 0x90, 0xF1,\r
+  0x08, 0xF0, 0x90, 0x28, 0x06, 0xE4, 0x93, 0x90,\r
+  0xF1, 0x09, 0xF0, 0x90, 0x28, 0x0F, 0xE4, 0x93,\r
+  0x90, 0xF1, 0x0A, 0xF0, 0x90, 0x28, 0x07, 0xE4,\r
+  0x93, 0x90, 0xF1, 0x0B, 0xF0, 0x90, 0xF0, 0xC5,\r
+  0x74, 0x07, 0xF0, 0x90, 0xF1, 0x18, 0x74, 0xF4,\r
+  0xF0, 0xE0, 0x54, 0x0F, 0xB4, 0x09, 0x00, 0x50,\r
+  0x6A, 0x90, 0x46, 0x50, 0xF8, 0x28, 0x28, 0x73,\r
+  0x02, 0x46, 0x6B, 0x02, 0x46, 0x73, 0x02, 0x46,\r
+  0x7B, 0x02, 0x46, 0x83, 0x02, 0x46, 0x8B, 0x02,\r
+  0x46, 0x93, 0x02, 0x46, 0x9B, 0x02, 0x46, 0xA3,\r
+  0x02, 0x46, 0xAB, 0x90, 0xF1, 0x0C, 0x74, 0x02,\r
+  0xF0, 0x80, 0x46, 0x90, 0xF1, 0x0C, 0x74, 0x04,\r
+  0xF0, 0x80, 0x3E, 0x90, 0xF1, 0x0C, 0x74, 0x08,\r
+  0xF0, 0x80, 0x36, 0x90, 0xF1, 0x0C, 0x74, 0x10,\r
+  0xF0, 0x80, 0x2E, 0x90, 0xF1, 0x0C, 0x74, 0x20,\r
+  0xF0, 0x80, 0x26, 0x90, 0xF1, 0x0C, 0x74, 0x40,\r
+  0xF0, 0x80, 0x1E, 0x90, 0xF1, 0x0C, 0x74, 0x80,\r
+  0xF0, 0x80, 0x16, 0x90, 0xF1, 0x0C, 0x74, 0x80,\r
+  0xF0, 0x80, 0x0E, 0x90, 0xF1, 0x0C, 0x74, 0x80,\r
+  0xF0, 0x80, 0x06, 0x90, 0xF1, 0x0C, 0x74, 0x02,\r
+  0xF0, 0x90, 0x28, 0x08, 0xE4, 0x93, 0x90, 0xF1,\r
+  0x0D, 0xF0, 0x90, 0x28, 0x09, 0xE4, 0x93, 0x90,\r
+  0xF1, 0x16, 0xF0, 0xD2, 0xAD, 0xE4, 0x90, 0xF1,\r
+  0x17, 0xF0, 0x90, 0xF0, 0xC4, 0x04, 0xF0, 0x20,\r
+  0x0A, 0x07, 0x75, 0x9E, 0x55, 0xB2, 0x83, 0x80,\r
+  0xF6, 0x22, 0x90, 0x12, 0xDB, 0xE4, 0xF0, 0xA3,\r
+  0x74, 0x40, 0xF0, 0xE4, 0x90, 0x12, 0xDF, 0xF0,\r
+  0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x12,\r
+  0xDD, 0xF0, 0xA3, 0x74, 0x40, 0xF0, 0xE4, 0x90,\r
+  0x12, 0xE3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3,\r
+  0xF0, 0x90, 0x12, 0xDA, 0xF0, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFF, 0xC3, 0x95, 0x0D, 0x40, 0x03, 0x02,\r
+  0x4C, 0x37, 0x74, 0xE5, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x88, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0x02,\r
+  0x4C, 0x2E, 0x90, 0x12, 0xDA, 0xE0, 0xF9, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0x90, 0x12, 0xDB, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0xFB, 0xC3, 0xED, 0x9B, 0xEA, 0x64, 0x80, 0xF8,\r
+  0xEC, 0x64, 0x80, 0x98, 0x40, 0x03, 0x02, 0x48,\r
+  0x22, 0x90, 0x28, 0x0D, 0xE4, 0x93, 0xFB, 0xFD,\r
+  0xE9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xC3, 0x9D, 0xFF, 0xEE, 0x94, 0x00,\r
+  0xFE, 0xE9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xDF, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x90, 0x12, 0xDC,\r
+  0xE0, 0x9F, 0xFF, 0x90, 0x12, 0xDB, 0xE0, 0x9E,\r
+  0xFE, 0x90, 0x12, 0xDA, 0xE0, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x12,\r
+  0x59, 0x81, 0xEB, 0xFD, 0xC3, 0x90, 0x12, 0xDC,\r
+  0xE0, 0x9D, 0xFD, 0x90, 0x12, 0xDB, 0xE0, 0x94,\r
+  0x00, 0xFC, 0x12, 0x59, 0xE8, 0x90, 0x12, 0xE0,\r
+  0xE0, 0x2F, 0xFF, 0x90, 0x12, 0xDF, 0xE0, 0x3E,\r
+  0xFE, 0x90, 0x12, 0xDA, 0xE0, 0xFD, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xC3, 0xEE, 0x64, 0x80, 0x94, 0x80,\r
+  0x40, 0x03, 0x02, 0x49, 0xAC, 0xED, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE4, 0xF0, 0xA3, 0xF0, 0x02,\r
+  0x49, 0xAC, 0x90, 0xF1, 0x06, 0xE0, 0xFF, 0xAE,\r
+  0x0B, 0xEE, 0x8F, 0xF0, 0xA4, 0xFF, 0x90, 0x12,\r
+  0xDB, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xC3, 0xEF,\r
+  0x9D, 0xFF, 0xE5, 0xF0, 0x9C, 0xFE, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFC, 0xA3, 0xE0, 0xD3, 0x9F, 0xEE, 0x64, 0x80,\r
+  0xF8, 0xEC, 0x64, 0x80, 0x98, 0x50, 0x03, 0x02,\r
+  0x49, 0x82, 0x90, 0xF1, 0x06, 0xE0, 0xFF, 0xAE,\r
+  0x0B, 0xEE, 0x8F, 0xF0, 0xA4, 0xFF, 0x90, 0x12,\r
+  0xDB, 0xE0, 0xFC, 0xA3, 0xE0, 0xC3, 0xEF, 0x9D,\r
+  0xFF, 0xE5, 0xF0, 0x9C, 0xFE, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xF9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x50,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0,\r
+  0xFA, 0xA3, 0xE0, 0xC3, 0x9F, 0xFF, 0xEA, 0x9E,\r
+  0xFE, 0xE9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12, 0xE1, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0xED, 0x9F, 0xFF,\r
+  0xEC, 0x9E, 0xFE, 0xE9, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x12, 0x59,\r
+  0x81, 0x90, 0x28, 0x0D, 0xE4, 0x93, 0xFD, 0x90,\r
+  0x12, 0xDB, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0xC3,\r
+  0x9D, 0xFD, 0xEA, 0x94, 0x00, 0xFC, 0x12, 0x59,\r
+  0xE8, 0x90, 0x12, 0xE2, 0xE0, 0x2F, 0xFF, 0x90,\r
+  0x12, 0xE1, 0xE0, 0x3E, 0xFE, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xF9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0xF1, 0x06, 0xE0,\r
+  0xFF, 0xAE, 0x0B, 0xEE, 0x8F, 0xF0, 0xA4, 0xC3,\r
+  0x9B, 0xFF, 0xE5, 0xF0, 0x9A, 0xFE, 0xE9, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xEE, 0x8F, 0xF0, 0x12,\r
+  0x5A, 0x1E, 0x90, 0xF1, 0x06, 0xE0, 0xFF, 0xAE,\r
+  0x0B, 0xEE, 0x8F, 0xF0, 0xA4, 0xFF, 0xE9, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xD3, 0x9F, 0xE5, 0xF0, 0x64, 0x80, 0xF8, 0xEC,\r
+  0x64, 0x80, 0x98, 0x40, 0x4F, 0x90, 0xF1, 0x06,\r
+  0xE0, 0xFF, 0xAE, 0x0B, 0xEE, 0x8F, 0xF0, 0xA4,\r
+  0xFF, 0x90, 0x12, 0xDA, 0xE0, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0xAC, 0xF5, 0x82, 0xE4, 0x34, 0x89,\r
+  0xF5, 0x83, 0xE5, 0xF0, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x80, 0x2A, 0x90, 0x12, 0xDA, 0xE0, 0xFF, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0x50, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAC,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEC,\r
+  0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12, 0xDA, 0xE0,\r
+  0xF9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0x90, 0x12, 0xDD, 0xE0, 0xFA,\r
+  0xA3, 0xE0, 0xFB, 0xC3, 0xED, 0x9B, 0xEA, 0x64,\r
+  0x80, 0xF8, 0xEC, 0x64, 0x80, 0x98, 0x40, 0x03,\r
+  0x02, 0x4A, 0xA4, 0x90, 0x28, 0x0E, 0xE4, 0x93,\r
+  0xFB, 0xFD, 0xE9, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xC3, 0x9D, 0xFF, 0xEE,\r
+  0x94, 0x00, 0xFE, 0xE9, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xE3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x90,\r
+  0x12, 0xDE, 0xE0, 0x9F, 0xFF, 0x90, 0x12, 0xDD,\r
+  0xE0, 0x9E, 0xFE, 0x90, 0x12, 0xDA, 0xE0, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0,\r
+  0xFD, 0x12, 0x59, 0x81, 0xEB, 0xFD, 0xC3, 0x90,\r
+  0x12, 0xDE, 0xE0, 0x9D, 0xFD, 0x90, 0x12, 0xDD,\r
+  0xE0, 0x94, 0x00, 0xFC, 0x12, 0x59, 0xE8, 0x90,\r
+  0x12, 0xE4, 0xE0, 0x2F, 0xFF, 0x90, 0x12, 0xE3,\r
+  0xE0, 0x3E, 0xFE, 0x90, 0x12, 0xDA, 0xE0, 0xFD,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0xED, 0x25, 0xE0, 0x25, 0xE0, 0x24,\r
+  0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83,\r
+  0xE0, 0xFE, 0xA3, 0xE0, 0xC3, 0xEE, 0x64, 0x80,\r
+  0x94, 0x80, 0x40, 0x03, 0x02, 0x4C, 0x2E, 0xED,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE4, 0xF0, 0xA3,\r
+  0xF0, 0x02, 0x4C, 0x2E, 0x90, 0xF1, 0x07, 0xE0,\r
+  0xFF, 0xAE, 0x0C, 0xEE, 0x8F, 0xF0, 0xA4, 0xFF,\r
+  0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xC3, 0xEF, 0x9D, 0xFF, 0xE5, 0xF0, 0x9C, 0xFE,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xD3, 0x9F, 0xEE,\r
+  0x64, 0x80, 0xF8, 0xEC, 0x64, 0x80, 0x98, 0x50,\r
+  0x03, 0x02, 0x4C, 0x04, 0x90, 0xF1, 0x07, 0xE0,\r
+  0xFF, 0xAE, 0x0C, 0xEE, 0x8F, 0xF0, 0xA4, 0xFF,\r
+  0x90, 0x12, 0xDD, 0xE0, 0xFC, 0xA3, 0xE0, 0xC3,\r
+  0xEF, 0x9D, 0xFF, 0xE5, 0xF0, 0x9C, 0xFE, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xF9, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xE0, 0xFA, 0xA3, 0xE0, 0xC3, 0x9F, 0xFF,\r
+  0xEA, 0x9E, 0xFE, 0xE9, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xE5, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0xED,\r
+  0x9F, 0xFF, 0xEC, 0x9E, 0xFE, 0xE9, 0x25, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x89, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0x12, 0x59, 0x81, 0x90, 0x28, 0x0E, 0xE4, 0x93,\r
+  0xFD, 0x90, 0x12, 0xDD, 0xE0, 0xFA, 0xA3, 0xE0,\r
+  0xFB, 0xC3, 0x9D, 0xFD, 0xEA, 0x94, 0x00, 0xFC,\r
+  0x12, 0x59, 0xE8, 0x90, 0x12, 0xE6, 0xE0, 0x2F,\r
+  0xFF, 0x90, 0x12, 0xE5, 0xE0, 0x3E, 0xFE, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xF9, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0xF1,\r
+  0x07, 0xE0, 0xFF, 0xAE, 0x0C, 0xEE, 0x8F, 0xF0,\r
+  0xA4, 0xC3, 0x9B, 0xFF, 0xE5, 0xF0, 0x9A, 0xFE,\r
+  0xE9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xEE, 0x8F,\r
+  0xF0, 0x12, 0x5A, 0x1E, 0x90, 0xF1, 0x07, 0xE0,\r
+  0xFF, 0xAE, 0x0C, 0xEE, 0x8F, 0xF0, 0xA4, 0xFF,\r
+  0xE9, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xD3, 0x9F, 0xE5, 0xF0, 0x64, 0x80,\r
+  0xF8, 0xEC, 0x64, 0x80, 0x98, 0x40, 0x4F, 0x90,\r
+  0xF1, 0x07, 0xE0, 0xFF, 0xAE, 0x0C, 0xEE, 0x8F,\r
+  0xF0, 0xA4, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0x25,\r
+  0xE0, 0x25, 0xE0, 0x24, 0xAE, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x89, 0xF5, 0x83, 0xE5, 0xF0, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0x80, 0x2A, 0x90, 0x12, 0xDA, 0xE0,\r
+  0xFF, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x52, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x89, 0xF5, 0x83, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xEF, 0x25, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xAE, 0xF5, 0x82, 0xE4, 0x34, 0x89, 0xF5,\r
+  0x83, 0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x47, 0x0D, 0x22,\r
+  0x90, 0x13, 0x2E, 0xEF, 0xF0, 0xA9, 0x03, 0xA3,\r
+  0xED, 0xF0, 0x60, 0x03, 0x02, 0x4D, 0xE7, 0xE9,\r
+  0x60, 0x03, 0x02, 0x4D, 0x20, 0x90, 0x13, 0x2E,\r
+  0xE0, 0xB4, 0x14, 0x00, 0x40, 0x03, 0x02, 0x4D,\r
+  0x14, 0x90, 0x4C, 0x60, 0xF8, 0x28, 0x28, 0x73,\r
+  0x02, 0x4C, 0x9C, 0x02, 0x4C, 0xA2, 0x02, 0x4C,\r
+  0xA8, 0x02, 0x4C, 0xAE, 0x02, 0x4C, 0xB4, 0x02,\r
+  0x4C, 0xBA, 0x02, 0x4C, 0xC0, 0x02, 0x4C, 0xC6,\r
+  0x02, 0x4C, 0xCC, 0x02, 0x4C, 0xD2, 0x02, 0x4C,\r
+  0xD8, 0x02, 0x4C, 0xDE, 0x02, 0x4C, 0xE4, 0x02,\r
+  0x4C, 0xEA, 0x02, 0x4C, 0xF0, 0x02, 0x4C, 0xF6,\r
+  0x02, 0x4C, 0xFC, 0x02, 0x4D, 0x02, 0x02, 0x4D,\r
+  0x08, 0x02, 0x4D, 0x0E, 0x43, 0xDB, 0x01, 0x02,\r
+  0x4D, 0xE4, 0x43, 0xDB, 0x02, 0x02, 0x4D, 0xE4,\r
+  0x43, 0xDB, 0x04, 0x02, 0x4D, 0xE4, 0x43, 0xDB,\r
+  0x08, 0x02, 0x4D, 0xE4, 0x43, 0xDB, 0x10, 0x02,\r
+  0x4D, 0xE4, 0x43, 0xDB, 0x20, 0x02, 0x4D, 0xE4,\r
+  0x43, 0xDB, 0x40, 0x02, 0x4D, 0xE4, 0x43, 0xDB,\r
+  0x80, 0x02, 0x4D, 0xE4, 0x43, 0xDA, 0x01, 0x02,\r
+  0x4D, 0xE4, 0x43, 0xDA, 0x02, 0x02, 0x4D, 0xE4,\r
+  0x43, 0xDA, 0x04, 0x02, 0x4D, 0xE4, 0x43, 0xDA,\r
+  0x08, 0x02, 0x4D, 0xE4, 0x43, 0xDA, 0x10, 0x02,\r
+  0x4D, 0xE4, 0x43, 0xDA, 0x20, 0x02, 0x4D, 0xE4,\r
+  0x43, 0xDA, 0x40, 0x02, 0x4D, 0xE4, 0x43, 0xDA,\r
+  0x80, 0x02, 0x4D, 0xE4, 0x43, 0xD9, 0x01, 0x02,\r
+  0x4D, 0xE4, 0x43, 0xD9, 0x02, 0x02, 0x4D, 0xE4,\r
+  0x43, 0xD9, 0x04, 0x02, 0x4D, 0xE4, 0x43, 0xD9,\r
+  0x08, 0x02, 0x4D, 0xE4, 0x85, 0xD9, 0xD9, 0x85,\r
+  0xDA, 0xDA, 0x85, 0xDB, 0xDB, 0x02, 0x4D, 0xE4,\r
+  0xE9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x4D, 0xE4,\r
+  0x90, 0x13, 0x2E, 0xE0, 0xB4, 0x14, 0x00, 0x40,\r
+  0x03, 0x02, 0x4D, 0xDB, 0x90, 0x4D, 0x3B, 0xF8,\r
+  0x28, 0x28, 0x73, 0x02, 0x4D, 0x77, 0x02, 0x4D,\r
+  0x7C, 0x02, 0x4D, 0x81, 0x02, 0x4D, 0x86, 0x02,\r
+  0x4D, 0x8B, 0x02, 0x4D, 0x90, 0x02, 0x4D, 0x95,\r
+  0x02, 0x4D, 0x9A, 0x02, 0x4D, 0x9F, 0x02, 0x4D,\r
+  0xA4, 0x02, 0x4D, 0xA9, 0x02, 0x4D, 0xAE, 0x02,\r
+  0x4D, 0xB3, 0x02, 0x4D, 0xB8, 0x02, 0x4D, 0xBD,\r
+  0x02, 0x4D, 0xC2, 0x02, 0x4D, 0xC7, 0x02, 0x4D,\r
+  0xCC, 0x02, 0x4D, 0xD1, 0x02, 0x4D, 0xD6, 0x43,\r
+  0xDE, 0x01, 0x80, 0x68, 0x43, 0xDE, 0x02, 0x80,\r
+  0x63, 0x43, 0xDE, 0x04, 0x80, 0x5E, 0x43, 0xDE,\r
+  0x08, 0x80, 0x59, 0x43, 0xDE, 0x10, 0x80, 0x54,\r
+  0x43, 0xDE, 0x20, 0x80, 0x4F, 0x43, 0xDE, 0x40,\r
+  0x80, 0x4A, 0x43, 0xDE, 0x80, 0x80, 0x45, 0x43,\r
+  0xDD, 0x01, 0x80, 0x40, 0x43, 0xDD, 0x02, 0x80,\r
+  0x3B, 0x43, 0xDD, 0x04, 0x80, 0x36, 0x43, 0xDD,\r
+  0x08, 0x80, 0x31, 0x43, 0xDD, 0x10, 0x80, 0x2C,\r
+  0x43, 0xDD, 0x20, 0x80, 0x27, 0x43, 0xDD, 0x40,\r
+  0x80, 0x22, 0x43, 0xDD, 0x80, 0x80, 0x1D, 0x43,\r
+  0xDC, 0x01, 0x80, 0x18, 0x43, 0xDC, 0x02, 0x80,\r
+  0x13, 0x43, 0xDC, 0x04, 0x80, 0x0E, 0x43, 0xDC,\r
+  0x08, 0x80, 0x09, 0x85, 0xDC, 0xDC, 0x85, 0xDD,\r
+  0xDD, 0x85, 0xDE, 0xDE, 0x7F, 0x00, 0x22, 0x90,\r
+  0x13, 0x2F, 0xE0, 0x64, 0x01, 0x60, 0x03, 0x02,\r
+  0x4F, 0x92, 0xE9, 0x60, 0x03, 0x02, 0x4E, 0xCB,\r
+  0x90, 0x13, 0x2E, 0xE0, 0xB4, 0x14, 0x00, 0x40,\r
+  0x03, 0x02, 0x4E, 0xBF, 0x90, 0x4E, 0x0B, 0xF8,\r
+  0x28, 0x28, 0x73, 0x02, 0x4E, 0x47, 0x02, 0x4E,\r
+  0x4D, 0x02, 0x4E, 0x53, 0x02, 0x4E, 0x59, 0x02,\r
+  0x4E, 0x5F, 0x02, 0x4E, 0x65, 0x02, 0x4E, 0x6B,\r
+  0x02, 0x4E, 0x71, 0x02, 0x4E, 0x77, 0x02, 0x4E,\r
+  0x7D, 0x02, 0x4E, 0x83, 0x02, 0x4E, 0x89, 0x02,\r
+  0x4E, 0x8F, 0x02, 0x4E, 0x95, 0x02, 0x4E, 0x9B,\r
+  0x02, 0x4E, 0xA1, 0x02, 0x4E, 0xA7, 0x02, 0x4E,\r
+  0xAD, 0x02, 0x4E, 0xB3, 0x02, 0x4E, 0xB9, 0x53,\r
+  0xDB, 0xFE, 0x02, 0x4F, 0x8F, 0x53, 0xDB, 0xFD,\r
+  0x02, 0x4F, 0x8F, 0x53, 0xDB, 0xFB, 0x02, 0x4F,\r
+  0x8F, 0x53, 0xDB, 0xF7, 0x02, 0x4F, 0x8F, 0x53,\r
+  0xDB, 0xEF, 0x02, 0x4F, 0x8F, 0x53, 0xDB, 0xDF,\r
+  0x02, 0x4F, 0x8F, 0x53, 0xDB, 0xBF, 0x02, 0x4F,\r
+  0x8F, 0x53, 0xDB, 0x7F, 0x02, 0x4F, 0x8F, 0x53,\r
+  0xDA, 0xFE, 0x02, 0x4F, 0x8F, 0x53, 0xDA, 0xFD,\r
+  0x02, 0x4F, 0x8F, 0x53, 0xDA, 0xFB, 0x02, 0x4F,\r
+  0x8F, 0x53, 0xDA, 0xF7, 0x02, 0x4F, 0x8F, 0x53,\r
+  0xDA, 0xEF, 0x02, 0x4F, 0x8F, 0x53, 0xDA, 0xDF,\r
+  0x02, 0x4F, 0x8F, 0x53, 0xDA, 0xBF, 0x02, 0x4F,\r
+  0x8F, 0x53, 0xDA, 0x7F, 0x02, 0x4F, 0x8F, 0x53,\r
+  0xD9, 0xFE, 0x02, 0x4F, 0x8F, 0x53, 0xD9, 0xFD,\r
+  0x02, 0x4F, 0x8F, 0x53, 0xD9, 0xFB, 0x02, 0x4F,\r
+  0x8F, 0x53, 0xD9, 0xF7, 0x02, 0x4F, 0x8F, 0x85,\r
+  0xD9, 0xD9, 0x85, 0xDA, 0xDA, 0x85, 0xDB, 0xDB,\r
+  0x02, 0x4F, 0x8F, 0xE9, 0x64, 0x01, 0x60, 0x03,\r
+  0x02, 0x4F, 0x8F, 0x90, 0x13, 0x2E, 0xE0, 0xB4,\r
+  0x14, 0x00, 0x40, 0x03, 0x02, 0x4F, 0x86, 0x90,\r
+  0x4E, 0xE6, 0xF8, 0x28, 0x28, 0x73, 0x02, 0x4F,\r
+  0x22, 0x02, 0x4F, 0x27, 0x02, 0x4F, 0x2C, 0x02,\r
+  0x4F, 0x31, 0x02, 0x4F, 0x36, 0x02, 0x4F, 0x3B,\r
+  0x02, 0x4F, 0x40, 0x02, 0x4F, 0x45, 0x02, 0x4F,\r
+  0x4A, 0x02, 0x4F, 0x4F, 0x02, 0x4F, 0x54, 0x02,\r
+  0x4F, 0x59, 0x02, 0x4F, 0x5E, 0x02, 0x4F, 0x63,\r
+  0x02, 0x4F, 0x68, 0x02, 0x4F, 0x6D, 0x02, 0x4F,\r
+  0x72, 0x02, 0x4F, 0x77, 0x02, 0x4F, 0x7C, 0x02,\r
+  0x4F, 0x81, 0x53, 0xDE, 0xFE, 0x80, 0x68, 0x53,\r
+  0xDE, 0xFD, 0x80, 0x63, 0x53, 0xDE, 0xFB, 0x80,\r
+  0x5E, 0x53, 0xDE, 0xF7, 0x80, 0x59, 0x53, 0xDE,\r
+  0xEF, 0x80, 0x54, 0x53, 0xDE, 0xDF, 0x80, 0x4F,\r
+  0x53, 0xDE, 0xBF, 0x80, 0x4A, 0x53, 0xDE, 0x7F,\r
+  0x80, 0x45, 0x53, 0xDD, 0xFE, 0x80, 0x40, 0x53,\r
+  0xDD, 0xFD, 0x80, 0x3B, 0x53, 0xDD, 0xFB, 0x80,\r
+  0x36, 0x53, 0xDD, 0xF7, 0x80, 0x31, 0x53, 0xDD,\r
+  0xEF, 0x80, 0x2C, 0x53, 0xDD, 0xDF, 0x80, 0x27,\r
+  0x53, 0xDD, 0xBF, 0x80, 0x22, 0x53, 0xDD, 0x7F,\r
+  0x80, 0x1D, 0x53, 0xDC, 0xFE, 0x80, 0x18, 0x53,\r
+  0xDC, 0xFD, 0x80, 0x13, 0x53, 0xDC, 0xFB, 0x80,\r
+  0x0E, 0x53, 0xDC, 0xF7, 0x80, 0x09, 0x85, 0xDC,\r
+  0xDC, 0x85, 0xDD, 0xDD, 0x85, 0xDE, 0xDE, 0x7F,\r
+  0x00, 0x22, 0x90, 0x13, 0x2F, 0xE0, 0x64, 0x02,\r
+  0x60, 0x03, 0x02, 0x51, 0x6E, 0xE9, 0x60, 0x03,\r
+  0x02, 0x50, 0x85, 0x90, 0x13, 0x2E, 0xE0, 0xB4,\r
+  0x14, 0x00, 0x40, 0x03, 0x02, 0x50, 0x80, 0x90,\r
+  0x4F, 0xB6, 0xF8, 0x28, 0x28, 0x73, 0x02, 0x4F,\r
+  0xF2, 0x02, 0x4F, 0xFA, 0x02, 0x50, 0x02, 0x02,\r
+  0x50, 0x09, 0x02, 0x50, 0x10, 0x02, 0x50, 0x17,\r
+  0x02, 0x50, 0x1E, 0x02, 0x50, 0x25, 0x02, 0x50,\r
+  0x2C, 0x02, 0x50, 0x33, 0x02, 0x50, 0x3A, 0x02,\r
+  0x50, 0x41, 0x02, 0x50, 0x48, 0x02, 0x50, 0x4F,\r
+  0x02, 0x50, 0x56, 0x02, 0x50, 0x5D, 0x02, 0x50,\r
+  0x64, 0x02, 0x50, 0x6B, 0x02, 0x50, 0x72, 0x02,\r
+  0x50, 0x79, 0xE5, 0xDB, 0x54, 0x01, 0xFE, 0x02,\r
+  0x50, 0x82, 0xE5, 0xDB, 0x54, 0x02, 0xFE, 0x02,\r
+  0x50, 0x82, 0xE5, 0xDB, 0x54, 0x04, 0xFE, 0x80,\r
+  0x79, 0xE5, 0xDB, 0x54, 0x08, 0xFE, 0x80, 0x72,\r
+  0xE5, 0xDB, 0x54, 0x10, 0xFE, 0x80, 0x6B, 0xE5,\r
+  0xDB, 0x54, 0x20, 0xFE, 0x80, 0x64, 0xE5, 0xDB,\r
+  0x54, 0x40, 0xFE, 0x80, 0x5D, 0xE5, 0xDB, 0x54,\r
+  0x80, 0xFE, 0x80, 0x56, 0xE5, 0xDA, 0x54, 0x01,\r
+  0xFE, 0x80, 0x4F, 0xE5, 0xDA, 0x54, 0x02, 0xFE,\r
+  0x80, 0x48, 0xE5, 0xDA, 0x54, 0x04, 0xFE, 0x80,\r
+  0x41, 0xE5, 0xDA, 0x54, 0x08, 0xFE, 0x80, 0x3A,\r
+  0xE5, 0xDA, 0x54, 0x10, 0xFE, 0x80, 0x33, 0xE5,\r
+  0xDA, 0x54, 0x20, 0xFE, 0x80, 0x2C, 0xE5, 0xDA,\r
+  0x54, 0x40, 0xFE, 0x80, 0x25, 0xE5, 0xDA, 0x54,\r
+  0x80, 0xFE, 0x80, 0x1E, 0xE5, 0xD9, 0x54, 0x01,\r
+  0xFE, 0x80, 0x17, 0xE5, 0xD9, 0x54, 0x02, 0xFE,\r
+  0x80, 0x10, 0xE5, 0xD9, 0x54, 0x04, 0xFE, 0x80,\r
+  0x09, 0xE5, 0xD9, 0x54, 0x08, 0xFE, 0x80, 0x02,\r
+  0xE4, 0xFE, 0xAF, 0x06, 0x22, 0xE9, 0x64, 0x01,\r
+  0x60, 0x03, 0x02, 0x51, 0x6E, 0x90, 0x13, 0x2E,\r
+  0xE0, 0xB4, 0x14, 0x00, 0x40, 0x03, 0x02, 0x51,\r
+  0x6A, 0x90, 0x50, 0xA0, 0xF8, 0x28, 0x28, 0x73,\r
+  0x02, 0x50, 0xDC, 0x02, 0x50, 0xE4, 0x02, 0x50,\r
+  0xEC, 0x02, 0x50, 0xF3, 0x02, 0x50, 0xFA, 0x02,\r
+  0x51, 0x01, 0x02, 0x51, 0x08, 0x02, 0x51, 0x0F,\r
+  0x02, 0x51, 0x16, 0x02, 0x51, 0x1D, 0x02, 0x51,\r
+  0x24, 0x02, 0x51, 0x2B, 0x02, 0x51, 0x32, 0x02,\r
+  0x51, 0x39, 0x02, 0x51, 0x40, 0x02, 0x51, 0x47,\r
+  0x02, 0x51, 0x4E, 0x02, 0x51, 0x55, 0x02, 0x51,\r
+  0x5C, 0x02, 0x51, 0x63, 0xE5, 0xDE, 0x54, 0x01,\r
+  0xFE, 0x02, 0x51, 0x6C, 0xE5, 0xDE, 0x54, 0x02,\r
+  0xFE, 0x02, 0x51, 0x6C, 0xE5, 0xDE, 0x54, 0x04,\r
+  0xFE, 0x80, 0x79, 0xE5, 0xDE, 0x54, 0x08, 0xFE,\r
+  0x80, 0x72, 0xE5, 0xDE, 0x54, 0x10, 0xFE, 0x80,\r
+  0x6B, 0xE5, 0xDE, 0x54, 0x20, 0xFE, 0x80, 0x64,\r
+  0xE5, 0xDE, 0x54, 0x40, 0xFE, 0x80, 0x5D, 0xE5,\r
+  0xDE, 0x54, 0x80, 0xFE, 0x80, 0x56, 0xE5, 0xDD,\r
+  0x54, 0x01, 0xFE, 0x80, 0x4F, 0xE5, 0xDD, 0x54,\r
+  0x02, 0xFE, 0x80, 0x48, 0xE5, 0xDD, 0x54, 0x04,\r
+  0xFE, 0x80, 0x41, 0xE5, 0xDD, 0x54, 0x08, 0xFE,\r
+  0x80, 0x3A, 0xE5, 0xDD, 0x54, 0x10, 0xFE, 0x80,\r
+  0x33, 0xE5, 0xDD, 0x54, 0x20, 0xFE, 0x80, 0x2C,\r
+  0xE5, 0xDD, 0x54, 0x40, 0xFE, 0x80, 0x25, 0xE5,\r
+  0xDD, 0x54, 0x80, 0xFE, 0x80, 0x1E, 0xE5, 0xDC,\r
+  0x54, 0x01, 0xFE, 0x80, 0x17, 0xE5, 0xDC, 0x54,\r
+  0x02, 0xFE, 0x80, 0x10, 0xE5, 0xDC, 0x54, 0x04,\r
+  0xFE, 0x80, 0x09, 0xE5, 0xDC, 0x54, 0x08, 0xFE,\r
+  0x80, 0x02, 0xE4, 0xFE, 0xAF, 0x06, 0x22, 0x90,\r
+  0x19, 0x40, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x40, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x41,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x41,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x42, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x42, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x43, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x43, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x44, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x44, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x45,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x45,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x46, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x46, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x47, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x48, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x49,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x4A, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x4B, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x4C, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x4D,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x4E, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x4F, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x50, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x51,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x52, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x53, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x54, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x55,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x56, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x57, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x58, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x58, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x59,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x59,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x5A, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x5A, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x5B, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x5B, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x5C, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x5C, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x5D,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x5D,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x5E, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x5E, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x5F, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x5F, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x60, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x60, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x61,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x61,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x62, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x62, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x63, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x63, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x64, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x64, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x65,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x65,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x66, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x66, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x67, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x68, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x69,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x6A, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x6B, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x6C, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x6D,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x6E, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x6F, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x70, 0x74, 0x01, 0xF0, 0x90, 0x19, 0x71,\r
+  0x74, 0x01, 0xF0, 0x90, 0x19, 0x72, 0x74, 0x01,\r
+  0xF0, 0x90, 0x19, 0x73, 0x74, 0x01, 0xF0, 0x90,\r
+  0x19, 0x74, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x75,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x76, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x77, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x78, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x78, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x79,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x79,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x7A, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x7A, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x7B, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x7B, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x7C, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x7C, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x7D,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x7D,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x7E, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x7E, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x7F, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x7F, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x80, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x80, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x81,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x81,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x82, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x82, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x83, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x83, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x84, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x84, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x85,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x85,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x86, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x86, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x87, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x87, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x88, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x89,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x8A, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x8B, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x8C, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x8D,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x8E, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x8F, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x90, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x91,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x92, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x93, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x94, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x95,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x96, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x97, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x98, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x98, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x99,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x99,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x9A, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x9A, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x9B, 0x74, 0x02, 0xF0, 0x80,\r
+  0x06, 0x90, 0x19, 0x9B, 0x74, 0x03, 0xF0, 0x90,\r
+  0x19, 0x9C, 0x74, 0x02, 0xF0, 0x80, 0x06, 0x90,\r
+  0x19, 0x9C, 0x74, 0x03, 0xF0, 0x90, 0x19, 0x9D,\r
+  0x74, 0x02, 0xF0, 0x80, 0x06, 0x90, 0x19, 0x9D,\r
+  0x74, 0x03, 0xF0, 0x90, 0x19, 0x9E, 0x74, 0x02,\r
+  0xF0, 0x80, 0x06, 0x90, 0x19, 0x9E, 0x74, 0x03,\r
+  0xF0, 0x90, 0x19, 0x9F, 0x74, 0x02, 0xF0, 0x22,\r
+  0x90, 0x19, 0x9F, 0x74, 0x03, 0xF0, 0x22, 0xE4,\r
+  0x90, 0x88, 0xB0, 0xF0, 0x90, 0x12, 0xDA, 0xF0,\r
+  0x90, 0x12, 0xDA, 0xE0, 0xFF, 0xC3, 0x94, 0x50,\r
+  0x50, 0x14, 0x74, 0x60, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x88, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x04, 0xF0, 0x80, 0xE2, 0xD2, 0xB3,\r
+  0x30, 0xB3, 0x05, 0x75, 0x9E, 0x55, 0x80, 0xF8,\r
+  0xC2, 0xDB, 0xC2, 0x0E, 0xE4, 0x90, 0x12, 0xDA,\r
+  0xF0, 0x90, 0xF2, 0xA8, 0xE0, 0xFF, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFE, 0xC3, 0x9F, 0x40, 0x03, 0x02,\r
+  0x58, 0x78, 0x74, 0x00, 0x2E, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x50, 0xF5, 0x83, 0xE0, 0xB5, 0x06, 0x06,\r
+  0x90, 0x88, 0xB0, 0xE0, 0x04, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFF, 0x75, 0xF0, 0x04, 0xA4, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x18, 0xF5,\r
+  0x83, 0xE0, 0x90, 0x88, 0xC3, 0xF0, 0x75, 0xF0,\r
+  0x04, 0xEF, 0xA4, 0x24, 0x01, 0xF5, 0x82, 0xE5,\r
+  0xF0, 0x34, 0x18, 0xF5, 0x83, 0xE0, 0x90, 0x88,\r
+  0xC4, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0xFF, 0x75,\r
+  0xF0, 0x04, 0xA4, 0x24, 0x00, 0xF5, 0x82, 0xE5,\r
+  0xF0, 0x34, 0x18, 0xF5, 0x83, 0xE0, 0x90, 0x88,\r
+  0xC5, 0xF0, 0x75, 0xF0, 0x04, 0xEF, 0xA4, 0x24,\r
+  0x02, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x30, 0xF5,\r
+  0x83, 0xE0, 0x90, 0x88, 0xC7, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFF, 0x75, 0xF0, 0x04, 0xA4, 0x24,\r
+  0x01, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x30, 0xF5,\r
+  0x83, 0xE0, 0x90, 0x88, 0xC8, 0xF0, 0x75, 0xF0,\r
+  0x04, 0xEF, 0xA4, 0x24, 0x00, 0xF5, 0x82, 0xE5,\r
+  0xF0, 0x34, 0x30, 0xF5, 0x83, 0xE0, 0x90, 0x88,\r
+  0xC9, 0xF0, 0x90, 0x12, 0xDA, 0xE0, 0xFF, 0x75,\r
+  0xF0, 0x04, 0xA4, 0x24, 0x52, 0xF5, 0x82, 0xE5,\r
+  0xF0, 0x34, 0x82, 0xF5, 0x83, 0xE0, 0x90, 0x88,\r
+  0xCE, 0xF0, 0x75, 0xF0, 0x04, 0xEF, 0xA4, 0x24,\r
+  0x51, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x82, 0xF5,\r
+  0x83, 0xE0, 0x90, 0x88, 0xCF, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xE0, 0xFF, 0x75, 0xF0, 0x04, 0xA4, 0x24,\r
+  0x50, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x82, 0xF5,\r
+  0x83, 0xE0, 0x90, 0x88, 0xD0, 0xF0, 0x74, 0x00,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x50, 0xF5, 0x83,\r
+  0xE0, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x88,\r
+  0xF5, 0x83, 0xE0, 0x60, 0x03, 0x02, 0x57, 0x45,\r
+  0x90, 0x12, 0xDA, 0xE0, 0xFB, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x50, 0xF5, 0x83, 0xE0, 0x24,\r
+  0x60, 0xF5, 0x82, 0xE4, 0x34, 0x88, 0xF5, 0x83,\r
+  0x74, 0x01, 0xF0, 0x90, 0x88, 0xC2, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0x74, 0x00, 0x2B, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x50, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x04, 0xA4,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x84,\r
+  0xF5, 0x83, 0x12, 0x5B, 0x88, 0x90, 0x88, 0xC6,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE,\r
+  0xA3, 0xE0, 0xFF, 0x90, 0x12, 0xDA, 0xE0, 0xFB,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x50, 0xF5,\r
+  0x83, 0xE0, 0x75, 0xF0, 0x04, 0xA4, 0x24, 0x40,\r
+  0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x85, 0xF5, 0x83,\r
+  0x12, 0x5B, 0x88, 0x90, 0x88, 0xCD, 0xE0, 0xFC,\r
+  0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0x74, 0x00, 0x2B, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x50, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x04, 0xA4,\r
+  0x24, 0x80, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x86,\r
+  0xF5, 0x83, 0x12, 0x5B, 0x88, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFD, 0x25, 0xE0, 0x24, 0x53, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x50, 0xF5, 0x83, 0xE0, 0xFE, 0xED,\r
+  0x25, 0xE0, 0x24, 0x52, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x50, 0xF5, 0x83, 0xE0, 0x7C, 0x00, 0x24, 0x00,\r
+  0xFF, 0xEC, 0x3E, 0xFE, 0x90, 0x12, 0xDA, 0xE0,\r
+  0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x50, 0xF5,\r
+  0x83, 0xE0, 0x25, 0xE0, 0x24, 0xC0, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x87, 0xF5, 0x83, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0x02, 0x58, 0x6F, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x50,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x04, 0xA4, 0x24,\r
+  0x00, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x84, 0xF5,\r
+  0x83, 0xC0, 0x83, 0xC0, 0x82, 0xE0, 0xFC, 0xA3,\r
+  0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x88, 0xC2, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9,\r
+  0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0xEF, 0x2B,\r
+  0xFF, 0xEE, 0x3A, 0xFE, 0xED, 0x39, 0xFD, 0xEC,\r
+  0x38, 0xFC, 0xD0, 0x82, 0xD0, 0x83, 0x12, 0x5B,\r
+  0x88, 0x90, 0x12, 0xDA, 0xE0, 0x24, 0x00, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x50, 0xF5, 0x83, 0xE0, 0x75,\r
+  0xF0, 0x04, 0xA4, 0x24, 0x40, 0xF5, 0x82, 0xE5,\r
+  0xF0, 0x34, 0x85, 0xF5, 0x83, 0xC0, 0x83, 0xC0,\r
+  0x82, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0,\r
+  0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x88, 0xC6, 0xE0,\r
+  0xF8, 0xA3, 0xE0, 0xF9, 0xA3, 0xE0, 0xFA, 0xA3,\r
+  0xE0, 0xFB, 0xEF, 0x2B, 0xFF, 0xEE, 0x3A, 0xFE,\r
+  0xED, 0x39, 0xFD, 0xEC, 0x38, 0xFC, 0xD0, 0x82,\r
+  0xD0, 0x83, 0x12, 0x5B, 0x88, 0x90, 0x12, 0xDA,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x50,\r
+  0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x04, 0xA4, 0x24,\r
+  0x80, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x86, 0xF5,\r
+  0x83, 0xC0, 0x83, 0xC0, 0x82, 0xE0, 0xFC, 0xA3,\r
+  0xE0, 0xFD, 0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,\r
+  0x90, 0x88, 0xCD, 0xE0, 0xF8, 0xA3, 0xE0, 0xF9,\r
+  0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0xEF, 0x2B,\r
+  0xFF, 0xEE, 0x3A, 0xFE, 0xED, 0x39, 0xFD, 0xEC,\r
+  0x38, 0xFC, 0xD0, 0x82, 0xD0, 0x83, 0x12, 0x5B,\r
+  0x88, 0x90, 0x12, 0xDA, 0xE0, 0xFD, 0x25, 0xE0,\r
+  0x24, 0x53, 0xF5, 0x82, 0xE4, 0x34, 0x50, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xED, 0x25, 0xE0, 0x24, 0x52,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x50, 0xF5, 0x83, 0xE0,\r
+  0x7C, 0x00, 0x24, 0x00, 0xFF, 0xEC, 0x3E, 0xFE,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x50, 0xF5, 0x83, 0xE0, 0x25, 0xE0,\r
+  0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0xF5,\r
+  0x83, 0xEE, 0x8F, 0xF0, 0x12, 0x5A, 0x1E, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x55, 0x59,\r
+  0x22, 0xE7, 0x09, 0xF6, 0x08, 0xDF, 0xFA, 0x80,\r
+  0x46, 0xE7, 0x09, 0xF2, 0x08, 0xDF, 0xFA, 0x80,\r
+  0x3E, 0x88, 0x82, 0x8C, 0x83, 0xE7, 0x09, 0xF0,\r
+  0xA3, 0xDF, 0xFA, 0x80, 0x32, 0xE3, 0x09, 0xF6,\r
+  0x08, 0xDF, 0xFA, 0x80, 0x78, 0xE3, 0x09, 0xF2,\r
+  0x08, 0xDF, 0xFA, 0x80, 0x70, 0x88, 0x82, 0x8C,\r
+  0x83, 0xE3, 0x09, 0xF0, 0xA3, 0xDF, 0xFA, 0x80,\r
+  0x64, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0xA3, 0xF6,\r
+  0x08, 0xDF, 0xFA, 0x80, 0x58, 0x89, 0x82, 0x8A,\r
+  0x83, 0xE0, 0xA3, 0xF2, 0x08, 0xDF, 0xFA, 0x80,\r
+  0x4C, 0x80, 0xD2, 0x80, 0xFA, 0x80, 0xC6, 0x80,\r
+  0xD4, 0x80, 0x69, 0x80, 0xF2, 0x80, 0x33, 0x80,\r
+  0x10, 0x80, 0xA6, 0x80, 0xEA, 0x80, 0x9A, 0x80,\r
+  0xA8, 0x80, 0xDA, 0x80, 0xE2, 0x80, 0xCA, 0x80,\r
+  0x33, 0x89, 0x82, 0x8A, 0x83, 0xEC, 0xFA, 0xE4,\r
+  0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCC, 0xC5,\r
+  0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8,\r
+  0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xE9, 0xDE, 0xE7,\r
+  0x80, 0x0D, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93,\r
+  0xA3, 0xF6, 0x08, 0xDF, 0xF9, 0xEC, 0xFA, 0xA9,\r
+  0xF0, 0xED, 0xFB, 0x22, 0x89, 0x82, 0x8A, 0x83,\r
+  0xEC, 0xFA, 0xE0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8,\r
+  0xCC, 0xC5, 0x83, 0xCC, 0xF0, 0xA3, 0xC8, 0xC5,\r
+  0x82, 0xC8, 0xCC, 0xC5, 0x83, 0xCC, 0xDF, 0xEA,\r
+  0xDE, 0xE8, 0x80, 0xDB, 0x89, 0x82, 0x8A, 0x83,\r
+  0xE4, 0x93, 0xA3, 0xF2, 0x08, 0xDF, 0xF9, 0x80,\r
+  0xCC, 0x88, 0xF0, 0xEF, 0x60, 0x01, 0x0E, 0x4E,\r
+  0x60, 0xC3, 0x88, 0xF0, 0xED, 0x24, 0x02, 0xB4,\r
+  0x04, 0x00, 0x50, 0xB9, 0xF5, 0x82, 0xEB, 0x24,\r
+  0x02, 0xB4, 0x04, 0x00, 0x50, 0xAF, 0x23, 0x23,\r
+  0x45, 0x82, 0x23, 0x90, 0x58, 0xC9, 0x73, 0xBB,\r
+  0x01, 0x06, 0x89, 0x82, 0x8A, 0x83, 0xF0, 0x22,\r
+  0x50, 0x02, 0xF7, 0x22, 0xBB, 0xFE, 0x01, 0xF3,\r
+  0x22, 0xEF, 0x8D, 0xF0, 0xA4, 0xA8, 0xF0, 0xCF,\r
+  0x8C, 0xF0, 0xA4, 0x28, 0xCE, 0x8D, 0xF0, 0xA4,\r
+  0x2E, 0xFE, 0x22, 0xBC, 0x00, 0x0B, 0xBE, 0x00,\r
+  0x29, 0xEF, 0x8D, 0xF0, 0x84, 0xFF, 0xAD, 0xF0,\r
+  0x22, 0xE4, 0xCC, 0xF8, 0x75, 0xF0, 0x08, 0xEF,\r
+  0x2F, 0xFF, 0xEE, 0x33, 0xFE, 0xEC, 0x33, 0xFC,\r
+  0xEE, 0x9D, 0xEC, 0x98, 0x40, 0x05, 0xFC, 0xEE,\r
+  0x9D, 0xFE, 0x0F, 0xD5, 0xF0, 0xE9, 0xE4, 0xCE,\r
+  0xFD, 0x22, 0xED, 0xF8, 0xF5, 0xF0, 0xEE, 0x84,\r
+  0x20, 0xD2, 0x1C, 0xFE, 0xAD, 0xF0, 0x75, 0xF0,\r
+  0x08, 0xEF, 0x2F, 0xFF, 0xED, 0x33, 0xFD, 0x40,\r
+  0x07, 0x98, 0x50, 0x06, 0xD5, 0xF0, 0xF2, 0x22,\r
+  0xC3, 0x98, 0xFD, 0x0F, 0xD5, 0xF0, 0xEA, 0x22,\r
+  0xC2, 0xD5, 0xEC, 0x30, 0xE7, 0x09, 0xB2, 0xD5,\r
+  0xE4, 0xC3, 0x9D, 0xFD, 0xE4, 0x9C, 0xFC, 0xEE,\r
+  0x30, 0xE7, 0x15, 0xB2, 0xD5, 0xE4, 0xC3, 0x9F,\r
+  0xFF, 0xE4, 0x9E, 0xFE, 0x12, 0x59, 0x93, 0xC3,\r
+  0xE4, 0x9D, 0xFD, 0xE4, 0x9C, 0xFC, 0x80, 0x03,\r
+  0x12, 0x59, 0x93, 0x30, 0xD5, 0x07, 0xC3, 0xE4,\r
+  0x9F, 0xFF, 0xE4, 0x9E, 0xFE, 0x22, 0xC5, 0xF0,\r
+  0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, 0xF8,\r
+  0xE5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83,\r
+  0xE0, 0x38, 0xF0, 0x22, 0xE8, 0x8F, 0xF0, 0xA4,\r
+  0xCC, 0x8B, 0xF0, 0xA4, 0x2C, 0xFC, 0xE9, 0x8E,\r
+  0xF0, 0xA4, 0x2C, 0xFC, 0x8A, 0xF0, 0xED, 0xA4,\r
+  0x2C, 0xFC, 0xEA, 0x8E, 0xF0, 0xA4, 0xCD, 0xA8,\r
+  0xF0, 0x8B, 0xF0, 0xA4, 0x2D, 0xCC, 0x38, 0x25,\r
+  0xF0, 0xFD, 0xE9, 0x8F, 0xF0, 0xA4, 0x2C, 0xCD,\r
+  0x35, 0xF0, 0xFC, 0xEB, 0x8E, 0xF0, 0xA4, 0xFE,\r
+  0xA9, 0xF0, 0xEB, 0x8F, 0xF0, 0xA4, 0xCF, 0xC5,\r
+  0xF0, 0x2E, 0xCD, 0x39, 0xFE, 0xE4, 0x3C, 0xFC,\r
+  0xEA, 0xA4, 0x2D, 0xCE, 0x35, 0xF0, 0xFD, 0xE4,\r
+  0x3C, 0xFC, 0x22, 0x75, 0xF0, 0x08, 0x75, 0x82,\r
+  0x00, 0xEF, 0x2F, 0xFF, 0xEE, 0x33, 0xFE, 0xCD,\r
+  0x33, 0xCD, 0xCC, 0x33, 0xCC, 0xC5, 0x82, 0x33,\r
+  0xC5, 0x82, 0x9B, 0xED, 0x9A, 0xEC, 0x99, 0xE5,\r
+  0x82, 0x98, 0x40, 0x0C, 0xF5, 0x82, 0xEE, 0x9B,\r
+  0xFE, 0xED, 0x9A, 0xFD, 0xEC, 0x99, 0xFC, 0x0F,\r
+  0xD5, 0xF0, 0xD6, 0xE4, 0xCE, 0xFB, 0xE4, 0xCD,\r
+  0xFA, 0xE4, 0xCC, 0xF9, 0xA8, 0x82, 0x22, 0xB8,\r
+  0x00, 0xC1, 0xB9, 0x00, 0x59, 0xBA, 0x00, 0x2D,\r
+  0xEC, 0x8B, 0xF0, 0x84, 0xCF, 0xCE, 0xCD, 0xFC,\r
+  0xE5, 0xF0, 0xCB, 0xF9, 0x78, 0x18, 0xEF, 0x2F,\r
+  0xFF, 0xEE, 0x33, 0xFE, 0xED, 0x33, 0xFD, 0xEC,\r
+  0x33, 0xFC, 0xEB, 0x33, 0xFB, 0x10, 0xD7, 0x03,\r
+  0x99, 0x40, 0x04, 0xEB, 0x99, 0xFB, 0x0F, 0xD8,\r
+  0xE5, 0xE4, 0xF9, 0xFA, 0x22, 0x78, 0x18, 0xEF,\r
+  0x2F, 0xFF, 0xEE, 0x33, 0xFE, 0xED, 0x33, 0xFD,\r
+  0xEC, 0x33, 0xFC, 0xC9, 0x33, 0xC9, 0x10, 0xD7,\r
+  0x05, 0x9B, 0xE9, 0x9A, 0x40, 0x07, 0xEC, 0x9B,\r
+  0xFC, 0xE9, 0x9A, 0xF9, 0x0F, 0xD8, 0xE0, 0xE4,\r
+  0xC9, 0xFA, 0xE4, 0xCC, 0xFB, 0x22, 0x75, 0xF0,\r
+  0x10, 0xEF, 0x2F, 0xFF, 0xEE, 0x33, 0xFE, 0xED,\r
+  0x33, 0xFD, 0xCC, 0x33, 0xCC, 0xC8, 0x33, 0xC8,\r
+  0x10, 0xD7, 0x07, 0x9B, 0xEC, 0x9A, 0xE8, 0x99,\r
+  0x40, 0x0A, 0xED, 0x9B, 0xFD, 0xEC, 0x9A, 0xFC,\r
+  0xE8, 0x99, 0xF8, 0x0F, 0xD5, 0xF0, 0xDA, 0xE4,\r
+  0xCD, 0xFB, 0xE4, 0xCC, 0xFA, 0xE4, 0xC8, 0xF9,\r
+  0x22, 0xEB, 0x9F, 0xF5, 0xF0, 0xEA, 0x9E, 0x42,\r
+  0xF0, 0xE9, 0x9D, 0x42, 0xF0, 0xE8, 0x9C, 0x45,\r
+  0xF0, 0x22, 0xE8, 0x60, 0x0F, 0xEC, 0xC3, 0x13,\r
+  0xFC, 0xED, 0x13, 0xFD, 0xEE, 0x13, 0xFE, 0xEF,\r
+  0x13, 0xFF, 0xD8, 0xF1, 0x22, 0xE8, 0x60, 0x0F,\r
+  0xEF, 0xC3, 0x33, 0xFF, 0xEE, 0x33, 0xFE, 0xED,\r
+  0x33, 0xFD, 0xEC, 0x33, 0xFC, 0xD8, 0xF1, 0x22,\r
+  0xEC, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0xEE, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x22, 0xA8, 0x82, 0x85, 0x83,\r
+  0xF0, 0xD0, 0x83, 0xD0, 0x82, 0x12, 0x5B, 0xAB,\r
+  0x12, 0x5B, 0xAB, 0x12, 0x5B, 0xAB, 0x12, 0x5B,\r
+  0xAB, 0xE4, 0x73, 0xE4, 0x93, 0xA3, 0xC5, 0x83,\r
+  0xC5, 0xF0, 0xC5, 0x83, 0xC8, 0xC5, 0x82, 0xC8,\r
+  0xF0, 0xA3, 0xC5, 0x83, 0xC5, 0xF0, 0xC5, 0x83,\r
+  0xC8, 0xC5, 0x82, 0xC8, 0x22, 0xA4, 0x25, 0x82,\r
+  0xF5, 0x82, 0xE5, 0xF0, 0x35, 0x83, 0xF5, 0x83,\r
+  0x22, 0x75, 0x81, 0x64, 0xD2, 0xAF, 0xD2, 0xAE,\r
+  0x12, 0x00, 0x40, 0x12, 0x7F, 0xF0, 0x7F, 0x64,\r
+  0x7E, 0x00, 0x12, 0x67, 0xEE, 0x12, 0x78, 0x00,\r
+  0x12, 0x51, 0x6F, 0xC2, 0x12, 0xE4, 0x90, 0x12,\r
+  0x5B, 0xF0, 0xC2, 0x01, 0x75, 0x9E, 0x55, 0x20,\r
+  0x0A, 0x03, 0x02, 0x5D, 0xFE, 0xC2, 0x0A, 0x85,\r
+  0x0E, 0x09, 0x85, 0x0F, 0x0A, 0xE4, 0xF5, 0x0E,\r
+  0xF5, 0x0F, 0x20, 0x12, 0x03, 0x12, 0x78, 0xE5,\r
+  0x30, 0x03, 0x06, 0x12, 0x27, 0xB1, 0x02, 0x5D,\r
+  0xFE, 0x20, 0x12, 0x03, 0x02, 0x5C, 0xB2, 0xE4,\r
+  0x90, 0xF1, 0x0A, 0xF0, 0x90, 0xF1, 0x1B, 0xF0,\r
+  0x90, 0xF1, 0x1F, 0x74, 0x0F, 0xF0, 0x90, 0xF1,\r
+  0x22, 0x74, 0x05, 0xF0, 0xE4, 0x90, 0xF1, 0x1C,\r
+  0xF0, 0x90, 0xF1, 0x06, 0x04, 0xF0, 0xA3, 0xF0,\r
+  0x90, 0xF1, 0x0E, 0xF0, 0xE4, 0xA3, 0xF0, 0xA3,\r
+  0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3,\r
+  0xF0, 0xA3, 0xF0, 0xA3, 0x74, 0x05, 0xF0, 0xE4,\r
+  0xFD, 0xFC, 0xED, 0x25, 0xE0, 0xFE, 0xEC, 0x33,\r
+  0x90, 0x12, 0xD8, 0xF0, 0xA3, 0xCE, 0xF0, 0x90,\r
+  0x12, 0xD8, 0xE0, 0xFE, 0xA3, 0xE0, 0x7B, 0x01,\r
+  0x7A, 0xF0, 0x79, 0x01, 0x24, 0x01, 0xF9, 0x74,\r
+  0xF0, 0x3E, 0xFA, 0xE4, 0x12, 0x59, 0x6F, 0x04,\r
+  0x29, 0xF9, 0xE4, 0x3A, 0xFA, 0x74, 0x08, 0x12,\r
+  0x59, 0x6F, 0x0D, 0xBD, 0x00, 0x01, 0x0C, 0xED,\r
+  0x64, 0x60, 0x4C, 0x70, 0xC5, 0x12, 0x5E, 0xE7,\r
+  0x90, 0x12, 0x5B, 0xE0, 0x04, 0xF0, 0xE0, 0x64,\r
+  0x60, 0x60, 0x03, 0x02, 0x5D, 0xFE, 0xF0, 0x90,\r
+  0x8F, 0xFD, 0x74, 0xBB, 0xF0, 0xC2, 0x12, 0x02,\r
+  0x5D, 0xFE, 0x90, 0x12, 0xBF, 0xE0, 0xFF, 0x12,\r
+  0x63, 0xD9, 0x12, 0x27, 0xF9, 0xA2, 0xD9, 0xE4,\r
+  0x33, 0x90, 0x8E, 0x01, 0xF0, 0x90, 0xF0, 0xC4,\r
+  0x74, 0x01, 0xF0, 0x30, 0x15, 0x09, 0x12, 0x28,\r
+  0x14, 0x12, 0x55, 0x1F, 0x12, 0x61, 0x81, 0x12,\r
+  0x00, 0x4F, 0x12, 0x46, 0xE2, 0x12, 0x35, 0x80,\r
+  0x90, 0x3F, 0xFD, 0xE0, 0xB4, 0x02, 0x19, 0xE5,\r
+  0x91, 0x30, 0xE4, 0x05, 0x75, 0x9E, 0x55, 0x80,\r
+  0xF6, 0x90, 0x8F, 0xF0, 0xE0, 0xD3, 0x94, 0x00,\r
+  0x40, 0x04, 0xC2, 0x84, 0x80, 0x02, 0xD2, 0x84,\r
+  0xE5, 0x91, 0x30, 0xE4, 0x03, 0x02, 0x5D, 0xEA,\r
+  0x90, 0x8F, 0xF0, 0xE0, 0xD3, 0x94, 0x00, 0x40,\r
+  0x7C, 0xE4, 0x90, 0x12, 0x63, 0xF0, 0xA3, 0xF0,\r
+  0xB2, 0x14, 0x75, 0x8A, 0x8B, 0xF5, 0x8B, 0x30,\r
+  0x14, 0x2C, 0x90, 0x12, 0xD5, 0xF0, 0x90, 0x12,\r
+  0xD5, 0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8F, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x00,\r
+  0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x8B, 0xF5, 0x83,\r
+  0xEE, 0xF0, 0x90, 0x12, 0xD5, 0xE0, 0x04, 0xF0,\r
+  0xE0, 0xB4, 0x3C, 0xDA, 0x80, 0x2B, 0xE4, 0x90,\r
+  0x12, 0xD5, 0xF0, 0x90, 0x12, 0xD5, 0xE0, 0xFF,\r
+  0x24, 0x78, 0xF5, 0x82, 0xE4, 0x34, 0x8F, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0x74, 0x00, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x8B, 0xF5, 0x83, 0xEE, 0xF0, 0x90,\r
+  0x12, 0xD5, 0xE0, 0x04, 0xF0, 0xE0, 0xB4, 0x3C,\r
+  0xDA, 0x90, 0x3F, 0xFD, 0xE0, 0x64, 0x01, 0x70,\r
+  0x7B, 0xC2, 0x84, 0x7F, 0x32, 0xFE, 0x12, 0x67,\r
+  0xEE, 0xD2, 0x84, 0x80, 0x6F, 0x30, 0x0C, 0x6C,\r
+  0x30, 0x07, 0x16, 0x90, 0x3F, 0xFD, 0xE0, 0xB4,\r
+  0x01, 0x0B, 0xC2, 0x84, 0x7F, 0x32, 0x7E, 0x00,\r
+  0x12, 0x67, 0xEE, 0xD2, 0x84, 0xC2, 0x07, 0x80,\r
+  0x53, 0x90, 0x12, 0x8B, 0xE4, 0xF0, 0xA3, 0x74,\r
+  0x64, 0xF0, 0x7F, 0x19, 0x7E, 0x00, 0x12, 0x67,\r
+  0xEE, 0x90, 0x12, 0x8C, 0xE0, 0x24, 0xFF, 0xF0,\r
+  0x90, 0x12, 0x8B, 0xE0, 0x34, 0xFF, 0xF0, 0x75,\r
+  0x9E, 0x55, 0x30, 0x0C, 0x0D, 0xD3, 0xA3, 0xE0,\r
+  0x94, 0x00, 0x90, 0x12, 0x8B, 0xE0, 0x94, 0x00,\r
+  0x50, 0xD8, 0x30, 0x0C, 0x1F, 0xC2, 0x84, 0x7F,\r
+  0x19, 0x7E, 0x00, 0x12, 0x67, 0xEE, 0xD2, 0x84,\r
+  0x80, 0x12, 0x90, 0x8F, 0xF0, 0xE0, 0xD3, 0x94,\r
+  0x00, 0x40, 0x09, 0x30, 0x0C, 0x04, 0xD2, 0x0B,\r
+  0x80, 0x02, 0xC2, 0x0B, 0xC2, 0x15, 0x20, 0x05,\r
+  0x03, 0x02, 0x5E, 0xDB, 0xC2, 0x05, 0xC2, 0x03,\r
+  0x90, 0x8F, 0xFF, 0xE0, 0x64, 0xAF, 0x70, 0x2A,\r
+  0xF0, 0x12, 0x67, 0x75, 0xE4, 0xF5, 0xA1, 0x7F,\r
+  0x32, 0xFE, 0x12, 0x67, 0xEE, 0xE4, 0xF5, 0xA1,\r
+  0x7F, 0x32, 0xFE, 0x12, 0x67, 0xEE, 0xE4, 0xF5,\r
+  0xA1, 0x7F, 0x32, 0xFE, 0x12, 0x67, 0xEE, 0x75,\r
+  0x87, 0x02, 0x75, 0x97, 0x55, 0x00, 0x00, 0x02,\r
+  0x5E, 0xE0, 0x90, 0x8F, 0xFF, 0xE0, 0x64, 0xAE,\r
+  0x70, 0x03, 0x02, 0x5E, 0xE0, 0x90, 0x8F, 0xFF,\r
+  0xE0, 0xB4, 0xBF, 0x05, 0xD2, 0x03, 0x02, 0x5E,\r
+  0xE0, 0x90, 0x8F, 0xFF, 0xE0, 0xB4, 0xCC, 0x24,\r
+  0xC2, 0x84, 0x7F, 0x64, 0x7E, 0x00, 0x12, 0x67,\r
+  0xEE, 0xD2, 0x84, 0x7F, 0xF8, 0x7E, 0x8E, 0x12,\r
+  0x67, 0xEE, 0xC2, 0x84, 0x7F, 0x64, 0x7E, 0x00,\r
+  0x12, 0x67, 0xEE, 0xD2, 0x84, 0xE4, 0x90, 0x8F,\r
+  0xFF, 0xF0, 0x80, 0x64, 0x90, 0x8F, 0xFF, 0xE0,\r
+  0xB4, 0xC3, 0x04, 0xD2, 0x01, 0x80, 0x59, 0x90,\r
+  0x8F, 0xFF, 0xE0, 0x64, 0xC5, 0x70, 0x38, 0xF0,\r
+  0x90, 0x8F, 0xFD, 0x74, 0xAA, 0xF0, 0xD2, 0x12,\r
+  0xE4, 0x90, 0x12, 0x5B, 0xF0, 0x90, 0xF1, 0x0A,\r
+  0xF0, 0x90, 0xF1, 0x1F, 0x74, 0x14, 0xF0, 0x90,\r
+  0xF1, 0x22, 0xF0, 0xE4, 0x90, 0xF1, 0x1C, 0xF0,\r
+  0x75, 0x9E, 0x55, 0x90, 0xF0, 0xC5, 0xE0, 0x44,\r
+  0x01, 0xF0, 0x12, 0x27, 0xF9, 0x90, 0xF0, 0xC4,\r
+  0x74, 0x01, 0xF0, 0xC2, 0x0A, 0x80, 0x19, 0x90,\r
+  0x8F, 0xFF, 0xE0, 0x64, 0xD1, 0x60, 0x11, 0x90,\r
+  0x8F, 0xFF, 0xE0, 0xB4, 0xE1, 0x0A, 0x12, 0x66,\r
+  0x0C, 0x80, 0x05, 0x30, 0x06, 0x02, 0xC2, 0x06,\r
+  0x12, 0x79, 0x05, 0x02, 0x5B, 0xF4, 0x22, 0x90,\r
+  0x12, 0x5B, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54,\r
+  0x1F, 0x90, 0x12, 0xDA, 0xF0, 0xEF, 0x54, 0x07,\r
+  0xA3, 0xF0, 0x90, 0x12, 0x5B, 0xE0, 0x24, 0x40,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x19, 0xF5, 0x83, 0xE0,\r
+  0xB4, 0x01, 0x1A, 0x74, 0x41, 0x2F, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x19, 0xF5, 0x83, 0xE0, 0xB4, 0x02,\r
+  0x0C, 0x90, 0x12, 0x5B, 0xE0, 0xD3, 0x94, 0x00,\r
+  0x40, 0x03, 0x02, 0x5F, 0xAB, 0x90, 0x12, 0x5B,\r
+  0xE0, 0xFF, 0x24, 0x40, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x19, 0xF5, 0x83, 0xE0, 0xB4, 0x01, 0x17, 0x74,\r
+  0x41, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x19, 0xF5,\r
+  0x83, 0xE0, 0xB4, 0x03, 0x09, 0x90, 0x12, 0x5B,\r
+  0xE0, 0xD3, 0x94, 0x00, 0x50, 0x5D, 0x90, 0x12,\r
+  0x5B, 0xE0, 0xFF, 0x24, 0x40, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x19, 0xF5, 0x83, 0xE0, 0xB4, 0x03, 0x17,\r
+  0x74, 0x41, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x19,\r
+  0xF5, 0x83, 0xE0, 0xB4, 0x02, 0x09, 0x90, 0x12,\r
+  0x5B, 0xE0, 0xD3, 0x94, 0x00, 0x50, 0x34, 0x90,\r
+  0x12, 0x5B, 0xE0, 0xFF, 0x24, 0x40, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x19, 0xF5, 0x83, 0xE0, 0x64, 0x03,\r
+  0x60, 0x03, 0x02, 0x60, 0x58, 0x74, 0x41, 0x2F,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x19, 0xF5, 0x83, 0xE0,\r
+  0x64, 0x01, 0x60, 0x03, 0x02, 0x60, 0x58, 0x90,\r
+  0x12, 0x5B, 0xE0, 0xD3, 0x94, 0x00, 0x50, 0x03,\r
+  0x02, 0x60, 0x58, 0x90, 0x12, 0x5B, 0xE0, 0x75,\r
+  0xF0, 0x02, 0xA4, 0xFF, 0xAE, 0xF0, 0x90, 0x12,\r
+  0x75, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x7A, 0xF0,\r
+  0x79, 0x01, 0x24, 0x01, 0xF9, 0x74, 0xF0, 0x3E,\r
+  0xFA, 0x90, 0x12, 0x5C, 0x74, 0x01, 0xF0, 0xA3,\r
+  0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x90, 0x12, 0x5C,\r
+  0xE0, 0xFB, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9,\r
+  0xE4, 0x12, 0x59, 0x6F, 0x90, 0x12, 0x5D, 0x75,\r
+  0xF0, 0x01, 0x12, 0x5A, 0x1E, 0x90, 0x12, 0x5C,\r
+  0xE0, 0xFB, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9,\r
+  0x74, 0x20, 0x12, 0x59, 0x6F, 0x90, 0x12, 0x5B,\r
+  0xE0, 0x24, 0xFF, 0xFF, 0xE4, 0x34, 0xFF, 0xFE,\r
+  0xEF, 0x25, 0xE0, 0xFF, 0xEE, 0x33, 0xFE, 0x90,\r
+  0x12, 0x75, 0xF0, 0xA3, 0xEF, 0xF0, 0x7A, 0xF0,\r
+  0x79, 0x01, 0x24, 0x01, 0xF9, 0x74, 0xF0, 0x3E,\r
+  0xFA, 0x90, 0x12, 0x5C, 0x74, 0x01, 0xF0, 0xA3,\r
+  0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x90, 0x12, 0x5C,\r
+  0xE0, 0xFB, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9,\r
+  0xE4, 0x12, 0x59, 0x6F, 0x90, 0x12, 0x5D, 0x75,\r
+  0xF0, 0x01, 0x12, 0x5A, 0x1E, 0x90, 0x12, 0x5C,\r
+  0xE0, 0xFB, 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9,\r
+  0x74, 0x10, 0x12, 0x59, 0x6F, 0x02, 0x61, 0x4A,\r
+  0x90, 0x12, 0x5B, 0xE0, 0xFF, 0x24, 0x40, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x19, 0xF5, 0x83, 0xE0, 0xB4,\r
+  0x01, 0x0F, 0x74, 0x41, 0x2F, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x19, 0xF5, 0x83, 0xE0, 0x64, 0x01, 0x60,\r
+  0x28, 0x90, 0x12, 0x5B, 0xE0, 0xFF, 0x24, 0x40,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x19, 0xF5, 0x83, 0xE0,\r
+  0x64, 0x03, 0x60, 0x03, 0x02, 0x61, 0x4A, 0x74,\r
+  0x41, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x19, 0xF5,\r
+  0x83, 0xE0, 0x64, 0x03, 0x60, 0x03, 0x02, 0x61,\r
+  0x4A, 0x90, 0x12, 0x5B, 0xE0, 0x75, 0xF0, 0x02,\r
+  0xA4, 0xFF, 0xAE, 0xF0, 0x90, 0x12, 0x75, 0xEE,\r
+  0xF0, 0xA3, 0xEF, 0xF0, 0x7A, 0xF0, 0x79, 0x01,\r
+  0x24, 0x01, 0xF9, 0x74, 0xF0, 0x3E, 0xFA, 0x90,\r
+  0x12, 0x5C, 0x74, 0x01, 0xF0, 0xA3, 0xEA, 0xF0,\r
+  0xA3, 0xE9, 0xF0, 0x90, 0x12, 0x5C, 0xE0, 0xFB,\r
+  0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0xE4, 0x12,\r
+  0x59, 0x6F, 0x90, 0x12, 0x5D, 0x75, 0xF0, 0x01,\r
+  0x12, 0x5A, 0x1E, 0x90, 0x12, 0x5C, 0xE0, 0xFB,\r
+  0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x74, 0x10,\r
+  0x12, 0x59, 0x6F, 0x90, 0x12, 0x5B, 0xE0, 0x24,\r
+  0x01, 0xFF, 0xE4, 0x33, 0xFE, 0xEF, 0x25, 0xE0,\r
+  0xFF, 0xEE, 0x33, 0xFE, 0x90, 0x12, 0x75, 0xF0,\r
+  0xA3, 0xEF, 0xF0, 0x7A, 0xF0, 0x79, 0x01, 0x24,\r
+  0x01, 0xF9, 0x74, 0xF0, 0x3E, 0xFA, 0x90, 0x12,\r
+  0x5C, 0x74, 0x01, 0xF0, 0xA3, 0xEA, 0xF0, 0xA3,\r
+  0xE9, 0xF0, 0x90, 0x12, 0x5C, 0xE0, 0xFB, 0xA3,\r
+  0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0xE4, 0x12, 0x59,\r
+  0x6F, 0x90, 0x12, 0x5D, 0x75, 0xF0, 0x01, 0x12,\r
+  0x5A, 0x1E, 0x90, 0x12, 0x5C, 0xE0, 0xFB, 0xA3,\r
+  0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x74, 0x20, 0x12,\r
+  0x59, 0x6F, 0x12, 0x27, 0xF9, 0x90, 0xF0, 0xC4,\r
+  0x74, 0x01, 0xF0, 0x20, 0x0A, 0x05, 0x75, 0x9E,\r
+  0x55, 0x80, 0xF8, 0x90, 0x00, 0x01, 0xE0, 0xFE,\r
+  0x90, 0x00, 0x00, 0xE0, 0x7C, 0x00, 0x24, 0x00,\r
+  0xFF, 0xEC, 0x3E, 0xFE, 0x90, 0x12, 0x5B, 0xE0,\r
+  0x25, 0xE0, 0x24, 0xA0, 0xF5, 0x82, 0xE4, 0x34,\r
+  0x19, 0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0x22, 0xE4, 0x90, 0x12, 0xDB, 0xF0, 0x90, 0x12,\r
+  0xDA, 0xF0, 0x90, 0xF2, 0xA8, 0xE0, 0xFF, 0x90,\r
+  0x12, 0xDA, 0xE0, 0xFE, 0xC3, 0x9F, 0x40, 0x03,\r
+  0x02, 0x63, 0xD0, 0x74, 0x60, 0x2E, 0xF5, 0x82,\r
+  0xE4, 0x34, 0x88, 0xF5, 0x83, 0xE0, 0x64, 0x01,\r
+  0x60, 0x03, 0x02, 0x63, 0xB5, 0xEE, 0x25, 0xE0,\r
+  0x24, 0xC0, 0xF5, 0x82, 0xE4, 0x34, 0x87, 0xF5,\r
+  0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xD3, 0x94, 0xFF,\r
+  0xEE, 0x94, 0x00, 0x40, 0x12, 0x90, 0x12, 0xDB,\r
+  0xE0, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x8A,\r
+  0xF5, 0x83, 0x74, 0xFF, 0xF0, 0x80, 0x22, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x25, 0xE0, 0x24, 0xC0, 0xF5,\r
+  0x82, 0xE4, 0x34, 0x87, 0xF5, 0x83, 0xE0, 0xA3,\r
+  0xE0, 0xFF, 0x90, 0x12, 0xDB, 0xE0, 0x24, 0x00,\r
+  0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83, 0xEF,\r
+  0xF0, 0x90, 0x12, 0xDA, 0xE0, 0x75, 0xF0, 0x04,\r
+  0xA4, 0x24, 0x80, 0xF5, 0x82, 0xE5, 0xF0, 0x34,\r
+  0x86, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x78, 0x02,\r
+  0x12, 0x5B, 0x62, 0xE4, 0x7B, 0xFF, 0xFA, 0xF9,\r
+  0xF8, 0xC3, 0x12, 0x5B, 0x51, 0x50, 0x12, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x24, 0x28, 0xF5, 0x82, 0xE4,\r
+  0x34, 0x8A, 0xF5, 0x83, 0x74, 0xFF, 0xF0, 0x80,\r
+  0x31, 0x90, 0x12, 0xDA, 0xE0, 0x75, 0xF0, 0x04,\r
+  0xA4, 0x24, 0x80, 0xF5, 0x82, 0xE5, 0xF0, 0x34,\r
+  0x86, 0xF5, 0x83, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD,\r
+  0xA3, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x78, 0x02,\r
+  0x12, 0x5B, 0x62, 0x90, 0x12, 0xDB, 0xE0, 0x24,\r
+  0x28, 0xF5, 0x82, 0xE4, 0x34, 0x8A, 0xF5, 0x83,\r
+  0xEF, 0xF0, 0x85, 0x0B, 0xAF, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFF, 0x75, 0xF0, 0x04, 0xA4, 0x24, 0x01,\r
+  0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x84, 0xF5, 0x83,\r
+  0xE0, 0xF5, 0xA9, 0x75, 0xF0, 0x04, 0xEF, 0xA4,\r
+  0x24, 0x02, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x84,\r
+  0xF5, 0x83, 0xE0, 0xF5, 0xAA, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFF, 0x75, 0xF0, 0x04, 0xA4, 0x24, 0x03,\r
+  0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x84, 0xF5, 0x83,\r
+  0xE0, 0xF5, 0xAB, 0x75, 0xF0, 0x04, 0xEF, 0xA4,\r
+  0x24, 0x81, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x86,\r
+  0xF5, 0x83, 0xE0, 0xF5, 0xA2, 0x90, 0x12, 0xDA,\r
+  0xE0, 0xFF, 0x75, 0xF0, 0x04, 0xA4, 0x24, 0x82,\r
+  0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x86, 0xF5, 0x83,\r
+  0xE0, 0xF5, 0xA3, 0x75, 0xF0, 0x04, 0xEF, 0xA4,\r
+  0x24, 0x83, 0xF5, 0x82, 0xE5, 0xF0, 0x34, 0x86,\r
+  0xF5, 0x83, 0xE0, 0xF5, 0xA4, 0xD2, 0xB0, 0x85,\r
+  0x0C, 0xAF, 0x90, 0x12, 0xDA, 0xE0, 0xFF, 0x75,\r
+  0xF0, 0x04, 0xA4, 0x24, 0x41, 0xF5, 0x82, 0xE5,\r
+  0xF0, 0x34, 0x85, 0xF5, 0x83, 0xE0, 0xF5, 0xA9,\r
+  0x75, 0xF0, 0x04, 0xEF, 0xA4, 0x24, 0x42, 0xF5,\r
+  0x82, 0xE5, 0xF0, 0x34, 0x85, 0xF5, 0x83, 0xE0,\r
+  0xF5, 0xAA, 0x90, 0x12, 0xDA, 0xE0, 0x75, 0xF0,\r
+  0x04, 0xA4, 0x24, 0x43, 0xF5, 0x82, 0xE5, 0xF0,\r
+  0x34, 0x85, 0xF5, 0x83, 0xE0, 0xF5, 0xAB, 0x20,\r
+  0xB0, 0x06, 0x30, 0x0E, 0x03, 0x20, 0xDA, 0x05,\r
+  0x75, 0x9E, 0x55, 0x80, 0xF2, 0xC2, 0xDA, 0xC2,\r
+  0x0E, 0xAF, 0xA6, 0xEF, 0xFE, 0xAD, 0xA7, 0x7C,\r
+  0x00, 0xE4, 0x2D, 0xFF, 0xEC, 0x3E, 0xFE, 0x90,\r
+  0x28, 0x0B, 0xE4, 0x93, 0xFD, 0xC3, 0x13, 0x2F,\r
+  0xFF, 0xEC, 0x3E, 0xFE, 0x90, 0x12, 0xDB, 0xE0,\r
+  0x25, 0xE0, 0x25, 0xE0, 0x24, 0x00, 0xF5, 0x82,\r
+  0xE4, 0x34, 0xF2, 0xF5, 0x83, 0xEE, 0xF0, 0xA3,\r
+  0xEF, 0xF0, 0xD2, 0xB0, 0x20, 0xB0, 0x06, 0x30,\r
+  0x0E, 0x03, 0x20, 0xDA, 0x05, 0x75, 0x9E, 0x55,\r
+  0x80, 0xF2, 0xC2, 0xDA, 0xC2, 0x0E, 0xAF, 0xA6,\r
+  0xEF, 0xFE, 0xAD, 0xA7, 0x7C, 0x00, 0xE4, 0x2D,\r
+  0xFF, 0xEC, 0x3E, 0xFE, 0x90, 0x28, 0x0C, 0xE4,\r
+  0x93, 0xFD, 0xC3, 0x13, 0x2F, 0xFF, 0xEC, 0x3E,\r
+  0xFE, 0x90, 0x12, 0xDB, 0xE0, 0x25, 0xE0, 0x25,\r
+  0xE0, 0x24, 0x02, 0xF5, 0x82, 0xE4, 0x34, 0xF2,\r
+  0xF5, 0x83, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x04, 0xF0, 0x90, 0x12, 0xDB,\r
+  0xE0, 0xFF, 0x65, 0x08, 0x60, 0x12, 0x90, 0x88,\r
+  0xB0, 0xE0, 0xFE, 0xEF, 0x6E, 0x60, 0x09, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x04, 0xF0, 0x02, 0x61, 0x8A,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x90, 0x88, 0xB0, 0xF0,\r
+  0x22, 0xAB, 0x07, 0xC2, 0x18, 0xEB, 0x25, 0xE0,\r
+  0xFE, 0xE4, 0x33, 0x90, 0x12, 0xDC, 0xF0, 0xA3,\r
+  0xCE, 0xF0, 0xE4, 0xFA, 0xEA, 0xFF, 0x7E, 0x00,\r
+  0x7C, 0x00, 0x7D, 0x28, 0x12, 0x59, 0x81, 0xAC,\r
+  0x06, 0xAD, 0x07, 0xEB, 0x25, 0xE0, 0xFF, 0xE4,\r
+  0x33, 0xFE, 0xED, 0x2F, 0xFF, 0xEC, 0x3E, 0x90,\r
+  0x12, 0xDC, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x12,\r
+  0xDC, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0x24, 0x01,\r
+  0xF5, 0x82, 0x74, 0x20, 0x3C, 0xF5, 0x83, 0xE0,\r
+  0xFE, 0x74, 0x00, 0x2D, 0xF5, 0x82, 0x74, 0x20,\r
+  0x3C, 0xF5, 0x83, 0xE0, 0xFD, 0xEE, 0xED, 0xFF,\r
+  0x90, 0x12, 0xDA, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0,\r
+  0xA3, 0xE0, 0xA3, 0xE0, 0xFD, 0x24, 0x01, 0xF5,\r
+  0x82, 0x74, 0x00, 0x3C, 0xF5, 0x83, 0xE0, 0xFE,\r
+  0x74, 0x00, 0x2D, 0xF5, 0x82, 0x74, 0x00, 0x3C,\r
+  0xF5, 0x83, 0xE0, 0xFD, 0xEE, 0xED, 0xFF, 0x90,\r
+  0x12, 0xDB, 0xE0, 0x24, 0xFA, 0xFD, 0x90, 0x12,\r
+  0xDA, 0xE0, 0x34, 0x00, 0xFC, 0xD3, 0xEF, 0x9D,\r
+  0xEE, 0x9C, 0x40, 0x0E, 0x90, 0x12, 0x72, 0xE0,\r
+  0x04, 0xF0, 0x70, 0x06, 0x90, 0x12, 0x71, 0xE0,\r
+  0x04, 0xF0, 0xEF, 0x24, 0xFA, 0xFF, 0xE4, 0x3E,\r
+  0xFE, 0xD3, 0x90, 0x12, 0xDB, 0xE0, 0x9F, 0x90,\r
+  0x12, 0xDA, 0xE0, 0x9E, 0x40, 0x0E, 0x90, 0x12,\r
+  0xBE, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90, 0x12,\r
+  0xBD, 0xE0, 0x04, 0xF0, 0x0A, 0xEA, 0x64, 0x1E,\r
+  0x60, 0x03, 0x02, 0x63, 0xEC, 0x90, 0x12, 0xBF,\r
+  0xE0, 0x04, 0xF0, 0xE0, 0x64, 0x14, 0x70, 0x37,\r
+  0xF0, 0x90, 0x12, 0xBD, 0xE0, 0xFE, 0xA3, 0xE0,\r
+  0xFF, 0xD3, 0x90, 0x12, 0x72, 0xE0, 0x9F, 0x90,\r
+  0x12, 0x71, 0xE0, 0x9E, 0x40, 0x02, 0xD2, 0x18,\r
+  0x30, 0x18, 0x1C, 0xC2, 0x18, 0xE4, 0x90, 0x12,\r
+  0x71, 0xF0, 0xA3, 0xF0, 0x90, 0x12, 0xBD, 0xF0,\r
+  0xA3, 0xF0, 0x90, 0xF1, 0x04, 0x74, 0x1E, 0xF0,\r
+  0x90, 0xF0, 0xC5, 0xE0, 0x44, 0x01, 0xF0, 0x22,\r
+  0x30, 0x98, 0x04, 0xD2, 0x05, 0xC2, 0x98, 0x30,\r
+  0x99, 0x24, 0xD2, 0x06, 0xC2, 0x99, 0x30, 0x0B,\r
+  0x19, 0xB2, 0x14, 0x30, 0x14, 0x08, 0x75, 0x8A,\r
+  0x8F, 0x75, 0x8B, 0x00, 0x80, 0x06, 0x75, 0x8A,\r
+  0x8F, 0x75, 0x8B, 0x78, 0xC2, 0x0B, 0xD2, 0x07,\r
+  0x80, 0x04, 0xC2, 0x0C, 0xC2, 0x07, 0x32, 0x32,\r
+  0x05, 0x00, 0x03, 0x20, 0x03, 0x03, 0xE5, 0xC0,\r
+  0x54, 0x02, 0x70, 0x03, 0x02, 0x5B, 0xD1, 0xE5,\r
+  0xC0, 0x54, 0x02, 0x60, 0x13, 0x90, 0x00, 0x00,\r
+  0x7F, 0x00, 0x7E, 0x90, 0xE4, 0x74, 0xFF, 0xF0,\r
+  0xA3, 0x75, 0x9E, 0x55, 0xDF, 0xF9, 0xDE, 0xF7,\r
+  0x02, 0x5B, 0xD1, 0xC2, 0xD3, 0xC2, 0xD4, 0x75,\r
+  0x9E, 0x55, 0x12, 0x65, 0xEF, 0x12, 0x65, 0xEF,\r
+  0x78, 0x01, 0x74, 0x55, 0xF6, 0x64, 0xFF, 0x08,\r
+  0xB8, 0x60, 0xF9, 0x78, 0x80, 0x74, 0x55, 0xF6,\r
+  0x64, 0xFF, 0x08, 0xB8, 0x00, 0xF9, 0x75, 0x9E,\r
+  0x55, 0x12, 0x65, 0xEF, 0x12, 0x65, 0xEF, 0x78,\r
+  0x01, 0x74, 0x55, 0xC0, 0xE0, 0x66, 0x70, 0x22,\r
+  0xD0, 0xE0, 0x63, 0xE0, 0xFF, 0x08, 0xB8, 0x60,\r
+  0xF2, 0x78, 0x80, 0x74, 0x55, 0xC0, 0xE0, 0x66,\r
+  0x70, 0x10, 0xD0, 0xE0, 0x63, 0xE0, 0xFF, 0x08,\r
+  0xB8, 0x00, 0xF2, 0x90, 0x00, 0x00, 0x74, 0x01,\r
+  0xF0, 0x22, 0x90, 0x00, 0x00, 0x74, 0x00, 0xF0,\r
+  0xA3, 0x90, 0x00, 0x01, 0xE8, 0xF0, 0xD0, 0xE0,\r
+  0x22, 0x78, 0x60, 0x74, 0x55, 0xF6, 0x64, 0xFF,\r
+  0x08, 0xB8, 0x81, 0xF9, 0x75, 0x9E, 0x55, 0x12,\r
+  0x65, 0xEF, 0x12, 0x65, 0xEF, 0x78, 0x60, 0x74,\r
+  0x55, 0xC0, 0xE0, 0x66, 0x70, 0x11, 0xD0, 0xE0,\r
+  0x63, 0xE0, 0xFF, 0x08, 0xB8, 0x81, 0xF2, 0x90,\r
+  0x00, 0x00, 0xE0, 0x44, 0x02, 0xF0, 0x22, 0x90,\r
+  0x00, 0x00, 0xE0, 0x44, 0x00, 0xF0, 0x90, 0x00,\r
+  0x02, 0xE8, 0xF0, 0xD0, 0xE0, 0x22, 0xC0, 0xE0,\r
+  0xC0, 0xD0, 0xD0, 0xD0, 0xD0, 0xE0, 0x32, 0x78,\r
+  0x00, 0xD8, 0xFE, 0x22, 0x78, 0x96, 0x79, 0xFA,\r
+  0xD9, 0xFE, 0xD8, 0xFA, 0x22, 0x78, 0x02, 0x79,\r
+  0xFA, 0x7A, 0xFA, 0xDA, 0xFE, 0xD9, 0xFA, 0xD8,\r
+  0xF6, 0x22, 0x00, 0x00, 0xE4, 0x90, 0x12, 0xDE,\r
+  0xF0, 0xA3, 0xF0, 0x90, 0x12, 0xDA, 0xF0, 0xA3,\r
+  0xF0, 0xB2, 0x86, 0xB2, 0x86, 0xFD, 0xFC, 0xB2,\r
+  0x85, 0x75, 0x9E, 0x55, 0xED, 0xAE, 0x04, 0x78,\r
+  0x07, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,\r
+  0xFF, 0x90, 0x12, 0xDA, 0xEE, 0xF0, 0xA3, 0xEF,\r
+  0xF0, 0xE4, 0x90, 0x12, 0xE0, 0xF0, 0xA3, 0xF0,\r
+  0x90, 0x12, 0xDA, 0xE0, 0xFA, 0xA3, 0xE0, 0xFB,\r
+  0xEA, 0xA3, 0xF0, 0xEB, 0xA3, 0xF0, 0xE4, 0xF9,\r
+  0xFB, 0xFA, 0x90, 0x12, 0xDA, 0xE0, 0xFE, 0xA3,\r
+  0xE0, 0xFF, 0x12, 0x78, 0xFD, 0xEF, 0x29, 0xF9,\r
+  0x90, 0x12, 0xDB, 0xE0, 0x04, 0xF0, 0x70, 0x06,\r
+  0x90, 0x12, 0xDA, 0xE0, 0x04, 0xF0, 0x0B, 0xBB,\r
+  0x00, 0x01, 0x0A, 0xEB, 0x64, 0x08, 0x4A, 0x70,\r
+  0xD9, 0x90, 0x12, 0xDC, 0xE0, 0x29, 0xFF, 0xA3,\r
+  0xE0, 0x2F, 0x24, 0x08, 0xF9, 0xF4, 0x04, 0xF9,\r
+  0xFF, 0x90, 0x12, 0xDF, 0xE0, 0x2F, 0xF0, 0x90,\r
+  0x12, 0xDE, 0xE0, 0x34, 0x00, 0xF0, 0x90, 0x12,\r
+  0xE1, 0xE0, 0x04, 0xF0, 0x70, 0x06, 0x90, 0x12,\r
+  0xE0, 0xE0, 0x04, 0xF0, 0xC3, 0x90, 0x12, 0xE1,\r
+  0xE0, 0x94, 0x10, 0x90, 0x12, 0xE0, 0xE0, 0x64,\r
+  0x80, 0x94, 0x80, 0x40, 0x8B, 0x0D, 0xBD, 0x00,\r
+  0x01, 0x0C, 0xED, 0x70, 0x03, 0xEC, 0x64, 0x01,\r
+  0x60, 0x03, 0x02, 0x66, 0x1F, 0x90, 0x12, 0xDE,\r
+  0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0x90, 0x8E,\r
+  0x0E, 0xF0, 0xED, 0x90, 0x8E, 0x0F, 0xF0, 0x90,\r
+  0x8E, 0x0D, 0x74, 0xAA, 0xF0, 0xB2, 0x86, 0xB2,\r
+  0x86, 0x75, 0x9E, 0x55, 0x80, 0xFB, 0x22, 0x75,\r
+  0x9E, 0x55, 0x90, 0xF1, 0x40, 0x74, 0x03, 0xF0,\r
+  0x7F, 0x01, 0x7E, 0x00, 0x12, 0x78, 0x5A, 0x7F,\r
+  0x01, 0x7E, 0x00, 0x12, 0x78, 0x5A, 0x75, 0x9E,\r
+  0x55, 0x90, 0xF1, 0x41, 0x74, 0x01, 0xF0, 0x7F,\r
+  0x05, 0x7E, 0x00, 0x12, 0x78, 0x5A, 0x7F, 0x05,\r
+  0x7E, 0x00, 0x12, 0x78, 0x5A, 0x75, 0x9E, 0x55,\r
+  0x90, 0xF1, 0x41, 0x74, 0x13, 0xF0, 0x7F, 0x05,\r
+  0x7E, 0x00, 0x12, 0x78, 0x5A, 0x7F, 0x05, 0x7E,\r
+  0x00, 0x12, 0x78, 0x5A, 0x75, 0x9E, 0x55, 0x90,\r
+  0xF1, 0x41, 0x74, 0x1F, 0xF0, 0x7F, 0x05, 0x7E,\r
+  0x00, 0x12, 0x78, 0x5A, 0x7F, 0x05, 0x7E, 0x00,\r
+  0x12, 0x78, 0x5A, 0x75, 0x9E, 0x55, 0x90, 0xF1,\r
+  0x41, 0x74, 0x3F, 0xF0, 0x7F, 0x05, 0x7E, 0x00,\r
+  0x12, 0x78, 0x5A, 0x7F, 0x05, 0x7E, 0x00, 0x12,\r
+  0x78, 0x5A, 0x75, 0x9E, 0x55, 0x90, 0xF1, 0x40,\r
+  0x74, 0x83, 0xF0, 0x7F, 0x01, 0x7E, 0x00, 0x12,\r
+  0x78, 0x5A, 0x7F, 0x01, 0x7E, 0x00, 0x12, 0x78,\r
+  0x5A, 0x75, 0x9E, 0x55, 0x22, 0xE4, 0x90, 0xF0,\r
+  0xC4, 0xF0, 0x75, 0x9E, 0x55, 0xFD, 0xFC, 0x90,\r
+  0xF1, 0x47, 0xE0, 0xFE, 0x90, 0xF1, 0x48, 0xE0,\r
+  0x7A, 0x00, 0x24, 0x00, 0xFB, 0xEA, 0x3E, 0xFA,\r
+  0x90, 0xF1, 0x49, 0xE0, 0x7F, 0x00, 0xFE, 0xEF,\r
+  0x2B, 0xFF, 0xEA, 0x3E, 0xFE, 0x90, 0xF1, 0x4A,\r
+  0xE0, 0x7A, 0x00, 0x2F, 0xFD, 0xEA, 0x3E, 0xFC,\r
+  0x90, 0xF1, 0x40, 0x74, 0xE3, 0xF0, 0xE4, 0x90,\r
+  0xF1, 0x41, 0xF0, 0xAE, 0x04, 0xAF, 0x05, 0x12,\r
+  0x78, 0xB6, 0x75, 0x9E, 0x55, 0x90, 0xF1, 0x41,\r
+  0x74, 0x40, 0xF0, 0x7F, 0x05, 0x7E, 0x00, 0x12,\r
+  0x78, 0x5A, 0x7F, 0x05, 0x7E, 0x00, 0x12, 0x78,\r
+  0x5A, 0x75, 0x9E, 0x55, 0xE4, 0x90, 0xF1, 0x41,\r
+  0xF0, 0x90, 0xF1, 0x40, 0xF0, 0x7F, 0x02, 0xFE,\r
+  0x12, 0x78, 0x5A, 0x7F, 0x02, 0x7E, 0x00, 0x12,\r
+  0x78, 0x5A, 0x75, 0x9E, 0x55, 0x22, 0xEF, 0x1F,\r
+  0x70, 0x01, 0x1E, 0x75, 0x9E, 0x55, 0xD3, 0xEF,\r
+  0x94, 0x00, 0xEE, 0x94, 0x00, 0x50, 0xEF, 0x22,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0xE5, 0xC0, 0x30, 0xE3, 0x1B, 0x12, 0x67, 0x75,\r
+  0x7F, 0x32, 0x7E, 0x00, 0x12, 0x78, 0x5A, 0x12,\r
+  0x66, 0xE7, 0x12, 0x26, 0x17, 0x12, 0x00, 0x36,\r
+  0x12, 0x78, 0xD8, 0x12, 0x41, 0x2D, 0x80, 0x36,\r
+  0xE5, 0xC0, 0x30, 0xE2, 0x0D, 0x12, 0x66, 0xE7,\r
+  0x90, 0xF0, 0xC4, 0x74, 0x01, 0xF0, 0xD2, 0xAF,\r
+  0x80, 0x24, 0xE5, 0xC0, 0x30, 0xE0, 0x0B, 0x12,\r
+  0x66, 0xE7, 0x90, 0xF0, 0xC4, 0x74, 0x01, 0xF0,\r
+  0x80, 0x14, 0xE5, 0xC0, 0x30, 0xE1, 0x0F, 0x12,\r
+  0x66, 0xE7, 0x12, 0x26, 0x17, 0x12, 0x00, 0x36,\r
+  0x12, 0x78, 0xD8, 0x12, 0x41, 0x2D, 0xE4, 0xF5,\r
+  0xC0, 0x22, 0xE4, 0xFD, 0xFC, 0xC3, 0xED, 0x9F,\r
+  0xEC, 0x9E, 0x50, 0x18, 0xE4, 0xFB, 0xFA, 0x75,\r
+  0x9E, 0x55, 0x0B, 0xBB, 0x00, 0x01, 0x0A, 0xBA,\r
+  0x03, 0xF5, 0xBB, 0x20, 0xF2, 0x0D, 0xBD, 0x00,\r
+  0x01, 0x0C, 0x80, 0xE1, 0x22, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,\r
+  0x04, 0x04, 0x04, 0x04, 0x00, 0x03, 0x00, 0x03,\r
+  0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03,\r
+  0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03,\r
+  0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xD2, 0x0A,\r
+  0x90, 0xF0, 0xC4, 0xE4, 0xF0, 0xC2, 0xD8, 0xD0,\r
+  0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32, 0xE4, 0xFD,\r
+  0xFC, 0xC3, 0xED, 0x9F, 0xEC, 0x9E, 0x50, 0x08,\r
+  0x00, 0x0D, 0xBD, 0x00, 0x01, 0x0C, 0x80, 0xF1,\r
+  0x22, 0xC0, 0xE0, 0xD2, 0x09, 0x05, 0x0F, 0xE5,\r
+  0x0F, 0x70, 0x02, 0x05, 0x0E, 0xD0, 0xE0, 0x32,\r
+  0x75, 0x91, 0x01, 0x90, 0x28, 0x0A, 0xE4, 0x93,\r
+  0xF5, 0x89, 0xD2, 0xAC, 0x22, 0x90, 0xF0, 0xC5,\r
+  0x74, 0x06, 0xF0, 0x30, 0xF8, 0x02, 0xD2, 0x15,\r
+  0x22, 0xEE, 0x30, 0xE7, 0x07, 0xC3, 0xE4, 0x9F,\r
+  0xFF, 0xE4, 0x9E, 0xFE, 0x22, 0x8F, 0x82, 0x8E,\r
+  0x83, 0xE4, 0x93, 0xFF, 0x22, 0x00, 0x22, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+  0x90, 0x3F, 0xFF, 0x74, 0x03, 0xF0, 0x22, 0x00,\r
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
\ No newline at end of file
index a1087d18b8f724d5a0054db20bc4a03967c15333..3564b2b70a10a9dfd0a8915f4bbfa3479d49e115 100755 (executable)
@@ -29,7 +29,7 @@ static unsigned char binary_data[] = {
 #if(TB1_USE_F402)
 #include "f307&f317&f316_CT363S_01_V10_F7E9_140212.dat"
 #else
-#include "lx--js77_97_CT365_V01_E7DA_130419.dat"
+#include "LX20JS06_A1_CT363_V03_5198_121015.dat"
 #endif
 };
 
index fee03f2d9945eb6c6ba8a024f1df9ad8414151a8..6fe2224e8a63e15769c0a4ca4db363cae3e18f7f 100755 (executable)
@@ -23,6 +23,8 @@
 #include <asm/pgtable.h>
 #include <linux/of.h>
 #include <linux/rockchip/sysmmu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
 
 #include "rockchip-iommu.h"
 
@@ -66,6 +68,10 @@ typedef enum sysmmu_entry_flags
 
 #define SYSMMU_REG_POLL_COUNT_FAST 1000
 
+/*rk3036:vpu and hevc share ahb interface*/
+#define BIT_VCODEC_SEL (1<<3)
+
+
 /**
  * MMU register numbers
  * Used in the register read/write routines.
@@ -150,6 +156,22 @@ typedef enum sysmmu_status_bits
 #define INVALID_PAGE ((u32)(~0))
 
 static struct kmem_cache *lv2table_kmem_cache;
+
+static void rockchip_vcodec_select(const char *string)
+{
+       if(strstr(string,"hevc"))
+       {
+               writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) |
+                             (BIT_VCODEC_SEL) | (BIT_VCODEC_SEL << 16),
+                             RK_GRF_VIRT + RK3036_GRF_SOC_CON1);
+       }
+       else if(strstr(string,"vpu"))
+       {
+               writel_relaxed((readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON1) &
+                              (~BIT_VCODEC_SEL)) | (BIT_VCODEC_SEL << 16),
+                              RK_GRF_VIRT + RK3036_GRF_SOC_CON1);
+       }
+}
 static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
 {
        return pgtable + lv1ent_offset(iova);
@@ -192,13 +214,12 @@ static bool is_sysmmu_active(struct sysmmu_drvdata *data)
 {
        return data->activations > 0;
 }
-static void sysmmu_disable_stall(void __iomem *sfrbase)
+static void sysmmu_disable_stall(void __iomem *base)
 {
        int i;
-       u32 mmu_status = __raw_readl(sfrbase+SYSMMU_REGISTER_STATUS);
+       u32 mmu_status = __raw_readl(base+SYSMMU_REGISTER_STATUS);
        if ( 0 == (mmu_status & SYSMMU_STATUS_BIT_PAGING_ENABLED )) 
        {
-               //pr_err("MMU disable skipped since it was not enabled.\n");
                return;
        }
        if (mmu_status & SYSMMU_STATUS_BIT_PAGE_FAULT_ACTIVE) 
@@ -207,11 +228,11 @@ static void sysmmu_disable_stall(void __iomem *sfrbase)
                return;
        }
        
-       __raw_writel(SYSMMU_COMMAND_DISABLE_STALL, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_DISABLE_STALL, base + SYSMMU_REGISTER_COMMAND);
        
        for (i = 0; i < SYSMMU_REG_POLL_COUNT_FAST; ++i) 
        {
-               u32 status = __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS);
+               u32 status = __raw_readl(base + SYSMMU_REGISTER_STATUS);
                if ( 0 == (status & SYSMMU_STATUS_BIT_STALL_ACTIVE) ) 
                {
                        break;
@@ -226,16 +247,16 @@ static void sysmmu_disable_stall(void __iomem *sfrbase)
                }
        }
        if (SYSMMU_REG_POLL_COUNT_FAST == i) 
-               pr_err("Disable stall request failed, MMU status is 0x%08X\n", __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS));
+               pr_err("Disable stall request failed, MMU status is 0x%08X\n", __raw_readl(base + SYSMMU_REGISTER_STATUS));
 }
-static bool sysmmu_enable_stall(void __iomem *sfrbase)
+static bool sysmmu_enable_stall(void __iomem *base)
 {
        int i;
-       u32 mmu_status = __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS);
+       u32 mmu_status = __raw_readl(base + SYSMMU_REGISTER_STATUS);
 
        if ( 0 == (mmu_status & SYSMMU_STATUS_BIT_PAGING_ENABLED) ) 
        {
-               //pr_info("MMU stall is implicit when Paging is not enabled.\n");
+               /*pr_info("MMU stall is implicit when Paging is not enabled.\n");*/
                return true;
        }
        if ( mmu_status & SYSMMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) 
@@ -244,11 +265,11 @@ static bool sysmmu_enable_stall(void __iomem *sfrbase)
                return false;
        }
        
-       __raw_writel(SYSMMU_COMMAND_ENABLE_STALL, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_ENABLE_STALL, base + SYSMMU_REGISTER_COMMAND);
 
        for (i = 0; i < SYSMMU_REG_POLL_COUNT_FAST; ++i) 
        {
-               mmu_status = __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS);
+               mmu_status = __raw_readl(base + SYSMMU_REGISTER_STATUS);
                if (mmu_status & SYSMMU_STATUS_BIT_PAGE_FAULT_ACTIVE) 
                {
                        break;
@@ -264,126 +285,126 @@ static bool sysmmu_enable_stall(void __iomem *sfrbase)
        }
        if (SYSMMU_REG_POLL_COUNT_FAST == i) 
        {
-               pr_info("Enable stall request failed, MMU status is 0x%08X\n", __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS));
+               pr_err("Enable stall request failed, MMU status is 0x%08X\n", __raw_readl(base + SYSMMU_REGISTER_STATUS));
                return false;
        }
        if ( mmu_status & SYSMMU_STATUS_BIT_PAGE_FAULT_ACTIVE ) 
        {
-               pr_info("Aborting MMU stall request since it has a pagefault.\n");
+               pr_err("Aborting MMU stall request since it has a pagefault.\n");
                return false;
        }
        return true;
 }
 
-static bool sysmmu_enable_paging(void __iomem *sfrbase)
+static bool sysmmu_enable_paging(void __iomem *base)
 {
        int i;
-       __raw_writel(SYSMMU_COMMAND_ENABLE_PAGING, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_ENABLE_PAGING, base + SYSMMU_REGISTER_COMMAND);
 
        for (i = 0; i < SYSMMU_REG_POLL_COUNT_FAST; ++i) 
        {
-               if (__raw_readl(sfrbase + SYSMMU_REGISTER_STATUS) & SYSMMU_STATUS_BIT_PAGING_ENABLED) 
+               if (__raw_readl(base + SYSMMU_REGISTER_STATUS) & SYSMMU_STATUS_BIT_PAGING_ENABLED) 
                {
-                       //pr_info("Enable paging request success.\n");
+                       /*pr_info("Enable paging request success.\n");*/
                        break;
                }
        }
        if (SYSMMU_REG_POLL_COUNT_FAST == i)
        {
-               pr_err("Enable paging request failed, MMU status is 0x%08X\n", __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS));
+               pr_err("Enable paging request failed, MMU status is 0x%08X\n", __raw_readl(base + SYSMMU_REGISTER_STATUS));
                return false;
        }
        return true;
 }
-static bool sysmmu_disable_paging(void __iomem *sfrbase)
+static bool sysmmu_disable_paging(void __iomem *base)
 {
        int i;
-       __raw_writel(SYSMMU_COMMAND_DISABLE_PAGING, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_DISABLE_PAGING, base + SYSMMU_REGISTER_COMMAND);
 
        for (i = 0; i < SYSMMU_REG_POLL_COUNT_FAST; ++i) 
        {
-               if (!(__raw_readl(sfrbase + SYSMMU_REGISTER_STATUS) & SYSMMU_STATUS_BIT_PAGING_ENABLED)) 
+               if (!(__raw_readl(base + SYSMMU_REGISTER_STATUS) & SYSMMU_STATUS_BIT_PAGING_ENABLED)) 
                {
-                       //pr_info("Disable paging request success.\n");
+                       /*pr_info("Disable paging request success.\n");*/
                        break;
                }
        }
        if (SYSMMU_REG_POLL_COUNT_FAST == i)
        {
-               pr_err("Disable paging request failed, MMU status is 0x%08X\n", __raw_readl(sfrbase + SYSMMU_REGISTER_STATUS));
+               pr_err("Disable paging request failed, MMU status is 0x%08X\n", __raw_readl(base + SYSMMU_REGISTER_STATUS));
                return false;
        }
        return true;
 }
 
-void sysmmu_page_fault_done(void __iomem *sfrbase,const char *dbgname)
+static void sysmmu_page_fault_done(void __iomem *base,const char *dbgname)
 {
        pr_info("MMU: %s: Leaving page fault mode\n", dbgname);
-       __raw_writel(SYSMMU_COMMAND_PAGE_FAULT_DONE, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_PAGE_FAULT_DONE, base + SYSMMU_REGISTER_COMMAND);
 }
-bool sysmmu_zap_tlb(void __iomem *sfrbase)
+static bool sysmmu_zap_tlb(void __iomem *base)
 {
-       bool stall_success = sysmmu_enable_stall(sfrbase);
+       bool stall_success = sysmmu_enable_stall(base);
        
-       __raw_writel(SYSMMU_COMMAND_ZAP_CACHE, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_ZAP_CACHE, base + SYSMMU_REGISTER_COMMAND);
        if (false == stall_success) 
        {
                /* False means that it is in Pagefault state. Not possible to disable_stall then */
                return false;
        }
-       sysmmu_disable_stall(sfrbase);
+       sysmmu_disable_stall(base);
        return true;
 }
-static inline bool sysmmu_raw_reset(void __iomem *sfrbase)
+static inline bool sysmmu_raw_reset(void __iomem *base)
 {
        int i;
-       __raw_writel(0xCAFEBABE, sfrbase + SYSMMU_REGISTER_DTE_ADDR);
+       __raw_writel(0xCAFEBABE, base + SYSMMU_REGISTER_DTE_ADDR);
 
-       if(!(0xCAFEB000 == __raw_readl(sfrbase+SYSMMU_REGISTER_DTE_ADDR)))
+       if(!(0xCAFEB000 == __raw_readl(base+SYSMMU_REGISTER_DTE_ADDR)))
        {
                pr_err("error when %s.\n",__func__);
                return false;
        }
-       __raw_writel(SYSMMU_COMMAND_HARD_RESET, sfrbase + SYSMMU_REGISTER_COMMAND);
+       __raw_writel(SYSMMU_COMMAND_HARD_RESET, base + SYSMMU_REGISTER_COMMAND);
 
        for (i = 0; i < SYSMMU_REG_POLL_COUNT_FAST; ++i) 
        {
-               if(__raw_readl(sfrbase + SYSMMU_REGISTER_DTE_ADDR) == 0)
+               if(__raw_readl(base + SYSMMU_REGISTER_DTE_ADDR) == 0)
                {
                        break;
                }
        }
        if (SYSMMU_REG_POLL_COUNT_FAST == i) {
-               pr_err("%s,Reset request failed, MMU status is 0x%08X\n", __func__,__raw_readl(sfrbase + SYSMMU_REGISTER_DTE_ADDR));
+               pr_err("%s,Reset request failed, MMU status is 0x%08X\n", __func__,__raw_readl(base + SYSMMU_REGISTER_DTE_ADDR));
                return false;
        }
        return true;
 }
 
-static void __sysmmu_set_ptbase(void __iomem *sfrbase,unsigned long pgd)
+static void __sysmmu_set_ptbase(void __iomem *base,unsigned long pgd)
 {
-       __raw_writel(pgd, sfrbase + SYSMMU_REGISTER_DTE_ADDR);
+       __raw_writel(pgd, base + SYSMMU_REGISTER_DTE_ADDR);
 
 }
 
-static bool sysmmu_reset(void __iomem *sfrbase,const char *dbgname)
+static bool sysmmu_reset(void __iomem *base,const char *dbgname)
 {
        bool err = true;
        
-       err = sysmmu_enable_stall(sfrbase);
+       err = sysmmu_enable_stall(base);
        if(!err)
        {
-               pr_info("%s:stall failed: %s\n",__func__,dbgname);
+               pr_err("%s:stall failed: %s\n",__func__,dbgname);
                return err;
        }
-       err = sysmmu_raw_reset(sfrbase);
+       err = sysmmu_raw_reset(base);
        if(err)
        {
-               __raw_writel(SYSMMU_INTERRUPT_PAGE_FAULT|SYSMMU_INTERRUPT_READ_BUS_ERROR, sfrbase+SYSMMU_REGISTER_INT_MASK);
+               __raw_writel(SYSMMU_INTERRUPT_PAGE_FAULT|SYSMMU_INTERRUPT_READ_BUS_ERROR, base+SYSMMU_REGISTER_INT_MASK);
        }
-       sysmmu_disable_stall(sfrbase);
+       sysmmu_disable_stall(base);
        if(!err)
-               pr_info("%s: failed: %s\n", __func__,dbgname);
+               pr_err("%s: failed: %s\n", __func__,dbgname);
        return err;
 }
 
@@ -420,7 +441,7 @@ static int default_fault_handler(struct device *dev,
 
        if(!data)
        {
-               pr_info("%s,iommu device not assigned yet\n",__func__);
+               pr_err("%s,iommu device not assigned yet\n",__func__);
                return 0;
        }
        if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT))
@@ -445,14 +466,6 @@ static int default_fault_handler(struct device *dev,
 }
 static void dump_pagetbl(u32 fault_address,u32 addr_dte)
 {
-#if 0
-       u32  offset1;
-       u32  offset2;
-       u32 *level2_base;
-       u32 *level1_entry;
-       u32 *level2_entry;
-#endif
-       #if 1
        u32 lv1_offset;
        u32 lv2_offset;
        
@@ -483,19 +496,6 @@ static void dump_pagetbl(u32 fault_address,u32 addr_dte)
        pr_info("lv1_entry_value(*lv1_entry_va) = 0x%08x,lv2_base = 0x%08x\n",(u32)lv1_entry_value,(u32)lv2_base);
        pr_info("lv2_offset = 0x%x,lv2_entry_pa = 0x%08x,lv2_entry_va = 0x%08x\n",lv2_offset,(u32)lv2_entry_pa,(u32)lv2_entry_va);
        pr_info("lv2_entry value(*lv2_entry_va) = 0x%08x\n",(u32)lv2_entry_value);
-       
-       #endif
-#if 0
-       offset1 = lv1ent_offset(fault_address);
-       offset2 = lv2ent_offset(fault_address);
-       level1_entry = (u32 *)__va(addr_dte)+offset1;
-       level2_base = (u32 *)__va((*level1_entry)&0xfffffffe);
-       level2_entry = level2_base+offset2;
-       pr_info("level1 offset=%d,level2 offset=%d,level1_entry=0x%08x\n",offset1,offset2,(u32)level1_entry);
-       pr_info("*level1_entry = 0x%08x\n",*level1_entry);
-       pr_info("*level2_entry = 0x%08x\n",*level2_entry);
-#endif
-
 }
 static irqreturn_t rockchip_sysmmu_irq(int irq, void *dev_id)
 {
@@ -521,6 +521,8 @@ static irqreturn_t rockchip_sysmmu_irq(int irq, void *dev_id)
                return IRQ_HANDLED;
        }
 #endif 
+       rockchip_vcodec_select(data->dbgname);
+
        pdev = to_platform_device(data->sysmmu);
 
        for (i = 0; i < data->num_res_irq; i++) 
@@ -537,6 +539,7 @@ static irqreturn_t rockchip_sysmmu_irq(int irq, void *dev_id)
        else 
        {
                int_status = __raw_readl(data->res_bases[i] + SYSMMU_REGISTER_INT_STATUS);
+               
                if(int_status != 0)
                {
                        /*mask status*/
@@ -683,6 +686,8 @@ void rockchip_sysmmu_tlb_invalidate(struct device *dev)
        struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
 
        read_lock_irqsave(&data->lock, flags);
+       
+       rockchip_vcodec_select(data->dbgname);
 
        if (is_sysmmu_active(data)) 
        {
@@ -838,6 +843,8 @@ static void rockchip_iommu_detach_device(struct iommu_domain *domain,
        }
        if (!found)
                goto finish;
+       
+       rockchip_vcodec_select(data->dbgname);
 
        if (__rockchip_sysmmu_disable(data)) 
        {
@@ -860,6 +867,8 @@ static int rockchip_iommu_attach_device(struct iommu_domain *domain,struct devic
        int ret;
 
        spin_lock_irqsave(&priv->lock, flags);
+       
+       rockchip_vcodec_select(data->dbgname);
 
        ret = __rockchip_sysmmu_enable(data, __pa(priv->pgtable), domain);
 
@@ -898,9 +907,10 @@ static void rockchip_iommu_domain_destroy(struct iommu_domain *domain)
        WARN_ON(!list_empty(&priv->clients));
 
        spin_lock_irqsave(&priv->lock, flags);
-
+       
        list_for_each_entry(data, &priv->clients, node) 
        {
+               rockchip_vcodec_select(data->dbgname);
                while (!rockchip_sysmmu_disable(data->dev))
                        ; /* until System MMU is actually disabled */
        }
@@ -1115,6 +1125,9 @@ static int rockchip_sysmmu_probe(struct platform_device *pdev)
                        ret = -ENOENT;
                        goto err_res;
                }
+               
+               rockchip_vcodec_select(data->dbgname);
+               
                if(!strstr(data->dbgname,"isp"))
                {
                        /*reset sysmmu*/
@@ -1184,6 +1197,7 @@ static const struct of_device_id sysmmu_dt_ids[] =
        { .compatible = HEVC_SYSMMU_COMPATIBLE_NAME},
        { .compatible = VPU_SYSMMU_COMPATIBLE_NAME},
        { .compatible = ISP_SYSMMU_COMPATIBLE_NAME},
+       { .compatible = VOP_SYSMMU_COMPATIBLE_NAME},
        { /* end */ }
 };
 MODULE_DEVICE_TABLE(of, sysmmu_dt_ids);
@@ -1201,12 +1215,6 @@ static struct platform_driver rk_sysmmu_driver =
        },
 };
 
-#if 0
-/*I don't know why this can't work*/
-#ifdef CONFIG_OF
-module_platform_driver(rk_sysmmu_driver);
-#endif
-#endif
 static int __init rockchip_sysmmu_init_driver(void)
 {
        dump_iommu_sysfs_init();
index 6ba3d084cef8e79c35187fbb7a93139f32151253..c365f27add4345137f4158f42835ea5ecefc45ad 100755 (executable)
@@ -68,8 +68,6 @@ dma_addr_t iovmm_map(struct device *dev,struct scatterlist *sg, off_t offset,siz
                ret = -ENOMEM;
                goto err_map_nomem;
        }
-
-       //start = (dma_addr_t)gen_pool_alloc_aligned(vmm->vmm_pool, size, order);
        
        start = (dma_addr_t)gen_pool_alloc(vmm->vmm_pool, size);
        if (!start) 
@@ -176,9 +174,9 @@ void iovmm_unmap(struct device *dev, dma_addr_t iova)
        region->start = round_down(region->start, PAGE_SIZE);
 
        unmapped_size = iommu_unmap(vmm->domain, region->start, region->size);
-
+       /*
        rockchip_sysmmu_tlb_invalidate(dev);
-
+       */
        gen_pool_free(vmm->vmm_pool, region->start, region->size);
 
        WARN_ON(unmapped_size != region->size);
@@ -196,7 +194,7 @@ int iovmm_map_oto(struct device *dev, phys_addr_t phys, size_t size)
 
        if (WARN_ON((phys + size) >= IOVA_START)) 
        {
-               dev_err(dev,"Unable to create one to one mapping for %#x @ %#x\n",size, phys);
+               pr_err("Unable to create one to one mapping for %#x @ %#x\n",size, phys);
                return -EINVAL;
        }
 
@@ -258,7 +256,7 @@ void iovmm_unmap_oto(struct device *dev, phys_addr_t phys)
        unmapped_size = iommu_unmap(vmm->domain, region->start, region->size);
        rockchip_sysmmu_tlb_invalidate(dev);
        WARN_ON(unmapped_size != region->size);
-       dev_dbg(dev, "IOVMM: Unmapped %#x bytes from %#x.\n",unmapped_size, region->start);
+       pr_err("IOVMM: Unmapped %#x bytes from %#x.\n",unmapped_size, region->start);
 
        kfree(region);
 }
@@ -295,7 +293,7 @@ int rockchip_init_iovmm(struct device *sysmmu, struct rk_iovmm *vmm)
 err_setup_domain:
        gen_pool_destroy(vmm->vmm_pool);
 err_setup_genalloc:
-       dev_dbg(sysmmu, "IOVMM: Failed to create IOVMM (%d)\n", ret);
+       pr_err("IOVMM: Failed to create IOVMM (%d)\n", ret);
 
        return ret;
 }
@@ -317,14 +315,14 @@ struct device *rockchip_get_sysmmu_device_by_compatible(const char *compt)
        dn = of_find_compatible_node(NULL,NULL,compt);
        if(!dn)
        {
-               printk("can't find device node %s \r\n",compt);
+               pr_err("can't find device node %s \r\n",compt);
                return NULL;
        }
        
        pd = of_find_device_by_node(dn);
        if(!pd)
        {       
-               printk("can't find platform device in device node %s \r\n",compt);
+               pr_err("can't find platform device in device node %s \r\n",compt);
                return  NULL;
        }
        ret = &pd->dev;
index 230a57b15d50e6c066a06087ea281599f98af158..761e0808dcf08eb7b2c1bce7ab831ded5f56e5ff 100755 (executable)
@@ -533,13 +533,6 @@ config MMC_DW_IDMAC
          Designware Mobile Storage IP block. This disables the external DMA
          interface.
 
-config MMC_DW_EDMAC
-       bool "External DMAC interface"
-       depends on MMC_DW && MMC_DW_ROCKCHIP && (!MMC_DW_IDMAC)
-       help
-         This selects support for the external DMAC block outside the Synopsys
-          Designware Mobile Storage IP block. This disables the internal DMA
-          interface.
 config MMC_DW_PLTFM
        tristate "Synopsys Designware MCI Support as platform device"
        depends on MMC_DW
index 527b2c8d86fdf259676880e2b0d04ab832406c6f..501db7858610a7846431ac19067ccdd4b887501d 100755 (executable)
@@ -49,7 +49,7 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
        host->irq_flags = 0;
        host->pdata = pdev->dev.platform_data;
        host->regs = devm_ioremap_resource(&pdev->dev, regs);
-        #ifdef CONFIG_MMC_DW_EDMAC
+        #ifdef CONFIG_MMC_DW_IDMAC
         host->phy_regs = (void *)(regs->start);
         #endif
        if (IS_ERR(host->regs))
index e0691fe975eb9da3d9fc45758155ad4595d21730..0057e78be97c5c4b1fe6916626efa62c16d8948f 100755 (executable)
@@ -84,6 +84,7 @@ enum dw_mci_rockchip_type {
        DW_MCI_TYPE_RK3188,
        DW_MCI_TYPE_RK3288,
        DW_MCI_TYPE_RK3036,
+       DW_MCI_TYPE_RK312X,
 };
 
 /* Rockchip implementation specific driver private data */
@@ -108,6 +109,9 @@ static struct dw_mci_rockchip_compatible {
        },{
                .compatible     = "rockchip,rk3036-sdmmc",
                .ctrl_type      = DW_MCI_TYPE_RK3036,
+       },{
+               .compatible     = "rockchip,rk312x-sdmmc",
+               .ctrl_type      = DW_MCI_TYPE_RK312X,
        },
 };
 
@@ -137,7 +141,8 @@ static int dw_mci_rockchip_setup_clock(struct dw_mci *host)
        struct dw_mci_rockchip_priv_data *priv = host->priv;
 
        if ((priv->ctrl_type == DW_MCI_TYPE_RK3288) ||
-               (priv->ctrl_type == DW_MCI_TYPE_RK3036))
+                (priv->ctrl_type == DW_MCI_TYPE_RK3036) ||
+                (priv->ctrl_type == DW_MCI_TYPE_RK312X))
                host->bus_hz /= (priv->ciu_div + 1);
 
        return 0;
@@ -270,11 +275,6 @@ static void dw_mci_rockchip_load_tuning_base(void)
         /* load tuning base */
         if(cpu_is_rk3288())
                 cru_tuning_base =  RK3288_CRU_SDMMC_CON0;
-
-     /* Fixme: 3036
-        else if(cpu_is_rk3036())
-                cru_tuning_base =  RK3036_CRU_SDMMC_CON0;
-     */
 }
 
 static int inline __dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
@@ -359,7 +359,6 @@ static int dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
            0.9 / 60ps = 15 delayline
          */
         if(cpu_is_rk3288()){
-                /* Fixme: 3036:  dose it compatitable? */
                  ref = ((FREQ_REF_150MHZ + host->bus_hz - 1) / host->bus_hz);
                  step = (15 * ref);
 
index 9abd49180f54be4bcd94df3f4907fb4307e618f3..0bdaf81e81f06f1c008b891bd061be7972904718 100755 (executable)
@@ -564,9 +564,8 @@ static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
        .complete = dw_mci_idmac_complete_dma,
        .cleanup = dw_mci_dma_cleanup,
 };
-#endif /* CONFIG_MMC_DW_IDMAC */
 
-#ifdef CONFIG_MMC_DW_EDMAC
+
 static void dw_mci_edma_cleanup(struct dw_mci *host)
 {
        struct mmc_data *data = host->data;
@@ -673,9 +672,6 @@ static void dw_mci_edmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 
 static int dw_mci_edmac_init(struct dw_mci *host)
 {
-        MMC_DBG_BOOT_FUNC(host->mmc,"dw_mci_edmac_init: Soc is 0x%x [%s]\n",
-                                (unsigned int)(rockchip_soc_id & ROCKCHIP_CPU_MASK), mmc_hostname(host->mmc));
-
         /* 1) request external dma channel, SHOULD decide chn in dts */
         host->dms = (struct dw_mci_dma_slave *)kmalloc(sizeof(struct dw_mci_dma_slave),GFP_KERNEL);
         host->dms->ch = dma_request_slave_channel(host->dev, "dw_mci");
@@ -707,7 +703,8 @@ static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
         .complete = dw_mci_edmac_complete_dma,
         .cleanup = dw_mci_edma_cleanup,
 };
-#endif
+#endif /* CONFIG_MMC_DW_IDMAC */
+
 static int dw_mci_pre_dma_transfer(struct dw_mci *host,
                                   struct mmc_data *data,
                                   bool next)
@@ -786,7 +783,7 @@ static void dw_mci_post_req(struct mmc_host *mmc,
 
 static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
 {
-#if defined(CONFIG_MMC_DW_IDMAC) || defined(CONFIG_MMC_DW_EDMAC)
+#ifdef CONFIG_MMC_DW_IDMAC
        unsigned int blksz = data->blksz;
        const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256};
        u32 fifo_width = 1 << host->data_shift;
@@ -1849,12 +1846,9 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
        struct dw_mci_tuning_data tuning_data;
        int err = -ENOSYS;
 
-        /* Fixme: 3036/3126 doesn't support 1.8 io domain, no sense exe tuning
-        if(cpu_is_3036() || cpu_is_3126())
-                return ENOSYS;
-        AND
-                what about audi-b?
-        */
+        /* Fixme: 3036/3126 doesn't support 1.8 io domain, no sense exe tuning */
+        if(cpu_is_rk3036() || cpu_is_rk312x())
+                return err;
 
        if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
                if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
@@ -2869,13 +2863,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
        }
 
 #ifdef CONFIG_MMC_DW_IDMAC
-       /* Handle DMA interrupts */
-       pending = mci_readl(host, IDSTS);
-       if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
-               mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
-               mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
-               host->dma_ops->complete((void *)host);
-       }
+        /* External DMA Soc platform NOT need to ack interrupt IDSTS */
+        if(!(cpu_is_rk3036() || cpu_is_rk312x())){
+                /* Handle DMA interrupts */
+                pending = mci_readl(host, IDSTS);
+                if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+                        mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
+                        mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+                        host->dma_ops->complete((void *)host);
+                }
+        }
 #endif
 
        return IRQ_HANDLED;
@@ -2960,7 +2957,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
                                /* Clear down the FIFO */
                                dw_mci_fifo_reset(host);
 #ifdef CONFIG_MMC_DW_IDMAC
-                               dw_mci_idmac_reset(host);
+                                if(!(cpu_is_rk3036() || cpu_is_rk312x()))
+                                       dw_mci_idmac_reset(host);
 #endif
 
                        }
@@ -3265,6 +3263,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->max_blk_count = host->ring_size;
                mmc->max_seg_size = 0x1000;
                mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
+               if(cpu_is_rk3036() || cpu_is_rk312x()){
+                        /* fixup for external dmac setting */
+                        mmc->max_segs = 64;
+                       mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
+                       mmc->max_blk_count = 65535;
+                       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+                       mmc->max_seg_size = mmc->max_req_size; 
+                }
 #else
                mmc->max_segs = 64;
                mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
@@ -3272,6 +3278,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
                mmc->max_seg_size = mmc->max_req_size;
 #endif /* CONFIG_MMC_DW_IDMAC */
+                
        }
         /* pwr_en */   
         slot->pwr_en_gpio = dw_mci_of_get_pwr_en_gpio(host->dev, slot->id);
@@ -3380,11 +3387,13 @@ static void dw_mci_init_dma(struct dw_mci *host)
 
        /* Determine which DMA interface to use */
 #if defined(CONFIG_MMC_DW_IDMAC)
-       host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(host->dev, "Using internal DMA controller.\n");
-#elif defined(CONFIG_MMC_DW_EDMAC)
-        host->dma_ops = &dw_mci_edmac_ops;
-        dev_info(host->dev, "Using external DMA controller.\n");
+        if(cpu_is_rk3036() || cpu_is_rk312x()){
+                host->dma_ops = &dw_mci_edmac_ops;
+                dev_info(host->dev, "Using external DMA controller.\n");
+        }else{
+                host->dma_ops = &dw_mci_idmac_ops;
+                dev_info(host->dev, "Using internal DMA controller.\n");
+        }
 #endif
 
        if (!host->dma_ops)
@@ -3571,8 +3580,9 @@ static void dw_mci_dealwith_timeout(struct dw_mci *host)
 
                         /* NO requirement to reclaim slave chn using external dmac */
                         #ifdef CONFIG_MMC_DW_IDMAC
-                        if (host->use_dma && host->dma_ops->init)
-                               host->dma_ops->init(host);
+                        if(!(cpu_is_rk3036() || cpu_is_rk312x()))
+                                if (host->use_dma && host->dma_ops->init)
+                                       host->dma_ops->init(host);
                         #endif
 
                         /*
@@ -3948,14 +3958,11 @@ int dw_mci_resume(struct dw_mci *host)
                /* Disable jtag*/
                if(cpu_is_rk3288())
                         grf_writel(((1 << 12) << 16) | (0 << 12), RK3288_GRF_SOC_CON0);
-                /*
                 else if(cpu_is_rk3036())
                         grf_writel(((1 << 11) << 16) | (0 << 11), RK3036_GRF_SOC_CON0);
-                else if(cpu_is_rk3126())
-                        TODO;
-                else if audi-b
-                        TODO;
-                */
+                else if(cpu_is_rk312x())
+                        /* RK3036_GRF_SOC_CON0 is compatible with rk312x, tmp setting */
+                        grf_writel(((1 << 8) << 16) | (0 << 8), RK3036_GRF_SOC_CON0);
        }
        if(host->vmmc){
                ret = regulator_enable(host->vmmc);
index 16e69c4e2510df07cb32070043933879ce34ff0b..99b7af0dfae83d3772753805273ed926fe3f8fe2 100755 (executable)
 #include <linux/completion.h>\r
 #include <linux/of.h>\r
 #include <linux/of_platform.h>\r
-\r
+#include <linux/of.h>\r
+#include <linux/of_net.h>\r
+#include <linux/gpio.h>\r
+#include <linux/of_gpio.h>\r
+#include <linux/of_device.h>\r
 #include "rk29_vmac.h"\r
 \r
 //static struct wake_lock idlelock; /* add by lyx @ 20110302 */\r
@@ -766,7 +770,7 @@ static irqreturn_t vmac_intr(int irq, void *dev_instance)
        if (unlikely(ap->shutdown))\r
                dev_err(&ap->pdev->dev, "ISR during close\n");\r
 \r
-       if (unlikely(!status & (RXINT_MASK|MDIO_MASK|ERR_MASK)))\r
+       if (unlikely((!status) & (RXINT_MASK|MDIO_MASK|ERR_MASK)))\r
                dev_err(&ap->pdev->dev, "No source of IRQ found\n");\r
 #endif\r
 \r
@@ -1017,12 +1021,8 @@ int vmac_open(struct net_device *dev)
        struct phy_device *phydev;\r
        unsigned int temp;\r
        int err = 0;\r
-       struct clk *mac_clk = NULL;\r
-       struct clk *mac_parent = NULL;\r
-       struct clk *arm_clk = NULL;\r
        struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
        unsigned char current_mac[6];\r
-       int ret = 0;\r
        struct pinctrl_state *clkout_state;\r
 \r
        printk("enter func %s...\n", __func__);\r
@@ -1033,7 +1033,7 @@ int vmac_open(struct net_device *dev)
        wake_lock_timeout(&ap->resume_lock, 5*HZ);\r
 \r
        ap->shutdown = 0;\r
-       \r
+\r
        // switch to rmii\r
        printk("ap->pdev->dev.pins->p = %p\n", ap->pdev->dev.pins->p);\r
        clkout_state = pinctrl_lookup_state(ap->pdev->dev.pins->p, "default");\r
@@ -1041,45 +1041,41 @@ int vmac_open(struct net_device *dev)
                dev_err(&ap->pdev->dev, "no clkout pinctrl state\n");\r
                goto err_out;\r
        }\r
-       \r
+\r
        printk("in pinctrl_select_state.\n");\r
        pinctrl_select_state(ap->pdev->dev.pins->p, clkout_state);\r
                \r
        //set rmii ref clock 50MHz\r
-       mac_clk = devm_clk_get(&ap->pdev->dev, "clk_mac");\r
-       /*if (IS_ERR(mac_clk))\r
-               mac_clk = NULL;\r
-       arm_clk = clk_get(NULL, "arm_pll");\r
-       if (IS_ERR(arm_clk))\r
-               arm_clk = NULL;\r
-       if (mac_clk) {\r
-               mac_parent = clk_get_parent(mac_clk);\r
-               if (IS_ERR(mac_parent))\r
-                       mac_parent = NULL;\r
+       pdata->clk_mac_pll_div = clk_get(&ap->pdev->dev, "clk_mac_pll_div");\r
+       if (IS_ERR(pdata->clk_mac_pll_div)) {\r
+               printk("get clk_mac_pll_div failed\n");\r
        }\r
-       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
-               wake_lock(&idlelock);\r
-\r
-        if(pdata && pdata->rmii_extclk_sel && pdata->rmii_extclk_sel())\r
-        {\r
-            struct clk * mac_clkin = NULL;\r
-            mac_clkin = clk_get(NULL, "rmii_clkin");\r
-            if (IS_ERR(mac_clkin)) {\r
-                pr_err("mac_clkin get fail\n");\r
-            }\r
-            clk_set_parent(mac_clk, mac_clkin); \r
-        }*/\r
-        \r
-       clk_set_rate(mac_clk, 50000000);\r
-       clk_prepare_enable(mac_clk);\r
-       //clk_enable(clk_get(NULL,"mii_rx"));\r
-       //clk_enable(clk_get(NULL,"mii_tx"));\r
-       //clk_enable(clk_get(NULL,"hclk_mac"));\r
+\r
+       pdata->clk_mac_ref_div = clk_get(&ap->pdev->dev, "clk_mac_ref_div");\r
+       if (IS_ERR(pdata->clk_mac_ref_div)) {\r
+               printk("get clk_mac_ref_div failed\n");\r
+       }\r
+\r
+       pdata->hclk_mac = clk_get(&ap->pdev->dev, "hclk_mac");\r
+       if (IS_ERR(pdata->hclk_mac)) {\r
+               printk("get hclk_mac failed\n");\r
+       }\r
+\r
+       clk_prepare_enable(pdata->hclk_mac);\r
+       clk_prepare_enable(pdata->clk_mac_pll_div);\r
+       clk_prepare_enable(pdata->clk_mac_ref_div);\r
 \r
        //phy power on\r
        if (pdata && pdata->rmii_power_control)\r
                pdata->rmii_power_control(1);\r
 \r
+       if (gpio_is_valid(pdata->reset_io)) {\r
+               gpio_direction_output(pdata->reset_io, pdata->reset_io_enable);\r
+               gpio_set_value(pdata->reset_io, pdata->reset_io_enable);\r
+               msleep(20);\r
+               gpio_set_value(pdata->reset_io, !pdata->reset_io_enable);\r
+       }\r
+\r
        msleep(1000);\r
 \r
        vmac_hw_init(dev);\r
@@ -1090,7 +1086,7 @@ int vmac_open(struct net_device *dev)
        }\r
 \r
 #ifdef CONFIG_ETH_MAC_FROM_EEPROM\r
-       ret = eeprom_read_data(0,dev->dev_addr,6);\r
+       err = eeprom_read_data(0,dev->dev_addr,6);\r
        if (ret != 6){\r
                printk("read mac from Eeprom fail.\n");\r
        }else {\r
@@ -1215,9 +1211,6 @@ int vmac_close(struct net_device *dev)
 {\r
        struct vmac_priv *ap = netdev_priv(dev);\r
        unsigned int temp;\r
-       struct clk *mac_clk = NULL;\r
-       struct clk *arm_clk = NULL;\r
-       struct clk *mac_parent = NULL;\r
        struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
 \r
        printk("enter func %s...\n", __func__);\r
@@ -1259,26 +1252,13 @@ int vmac_close(struct net_device *dev)
        if (pdata && pdata->rmii_power_control)\r
                pdata->rmii_power_control(0);\r
 \r
-       //clock close\r
-       /*mac_clk = clk_get(NULL, "mac_ref_div");\r
-       if (IS_ERR(mac_clk))\r
-               mac_clk = NULL;\r
-       if (mac_clk) {\r
-               mac_parent = clk_get_parent(mac_clk);\r
-               if (IS_ERR(mac_parent))\r
-                       mac_parent = NULL;\r
+       if (gpio_is_valid(pdata->reset_io)) {\r
+               gpio_set_value(pdata->reset_io, !pdata->reset_io_enable);\r
        }\r
-       arm_clk = clk_get(NULL, "arm_pll");\r
-       if (IS_ERR(arm_clk))\r
-               arm_clk = NULL;\r
 \r
-       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
-               wake_unlock(&idlelock);*/\r
-       \r
-       clk_disable(clk_get(&ap->pdev->dev,"clk_mac"));\r
-       //clk_disable(clk_get(NULL,"mii_tx"));\r
-       //clk_disable(clk_get(NULL,"hclk_mac"));\r
-       //clk_disable(clk_get(NULL,"clk_mac_pll"));\r
+       clk_disable_unprepare(pdata->clk_mac_ref_div);\r
+       clk_disable_unprepare(pdata->clk_mac_pll_div);\r
+       clk_disable_unprepare(pdata->hclk_mac);\r
 \r
        return 0;\r
 }\r
@@ -1413,7 +1393,7 @@ void vmac_tx_timeout(struct net_device *dev)
 \r
        spin_unlock_irqrestore(&ap->lock, flags);\r
 }\r
-\r
+#if 0\r
 static void create_multicast_filter(struct net_device *dev,\r
        unsigned long *bitmask)\r
 {\r
@@ -1463,6 +1443,7 @@ static void create_multicast_filter(struct net_device *dev,
        }\r
 #endif\r
 }\r
+\r
 static void vmac_set_multicast_list(struct net_device *dev)\r
 {\r
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
@@ -1519,6 +1500,7 @@ static void vmac_set_multicast_list(struct net_device *dev)
        spin_unlock_irqrestore(&ap->lock, flags);\r
 #endif\r
 }\r
+#endif\r
 \r
 static struct ethtool_ops vmac_ethtool_ops = {\r
        .get_settings           = vmacether_get_settings,\r
@@ -1549,13 +1531,32 @@ static int vmac_probe(struct platform_device *pdev)
        int err;\r
        struct rk29_vmac_platform_data *pdata;\r
        struct device_node *np = pdev->dev.of_node;\r
-       \r
+       enum of_gpio_flags flags;\r
+\r
        printk("vmac_probe.\n");\r
        dev_dbg(&pdev->dev, "vmac_probe 1.\n");\r
        \r
        pdev->dev.platform_data = &board_vmac_data;\r
        pdata = pdev->dev.platform_data;\r
 \r
+       pdata->reset_io = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);\r
+       if (!gpio_is_valid(pdata->reset_io)) {\r
+               printk("%s: Get reset-gpio failed.\n", __func__);\r
+               return -EINVAL;\r
+        } else {\r
+                err = gpio_request(pdata->reset_io, "phy_reset");\r
+                if (err) {\r
+                        pr_err("%s: ERROR: Request phy reset pin failed.\n", __func__);\r
+                        //return -EINVAL;\r
+                }\r
+        }\r
+\r
+       if(flags & OF_GPIO_ACTIVE_LOW) {\r
+               pdata->reset_io_enable = 0;\r
+       } else {\r
+               pdata->reset_io_enable = 1;\r
+       }\r
+\r
        dev = alloc_etherdev(sizeof(*ap));\r
        if (!dev) {\r
                dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");\r
@@ -1588,7 +1589,7 @@ static int vmac_probe(struct platform_device *pdev)
        }\r
        \r
        printk("mem_base = 0x%08x, mem_size = 0x%08x, irq = %d, regs = 0x%08x\n", \r
-               mem_base, mem_size, irq, ap->regs);\r
+               mem_base, mem_size, irq, (unsigned int)(ap->regs));\r
 \r
        /* no checksum support, hence no scatter/gather */\r
        dev->features |= NETIF_F_HIGHDMA;\r
@@ -1692,25 +1693,6 @@ static int vmac_remove(struct platform_device *pdev)
        return 0;\r
 }\r
 \r
-static void rk29_vmac_power_off(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
-\r
-       printk("enter func %s...\n", __func__);\r
-\r
-       //phy power off\r
-       if (pdata && pdata->rmii_power_control)\r
-               pdata->rmii_power_control(0);\r
-\r
-       //clock close\r
-       clk_disable(clk_get(&ap->pdev->dev,"clk_mac"));\r
-       //clk_disable(clk_get(NULL,"mii_tx"));\r
-       //clk_disable(clk_get(NULL,"hclk_mac"));\r
-       //clk_disable(clk_get(NULL,"clk_mac_pll"));\r
-\r
-}\r
-\r
 static int\r
 rk29_vmac_suspend(struct device *dev)\r
 {\r
index a6cf94e28ea05480848ebc2c305f1dd5e1d82274..9f577d3f41ba31df26375656b73518b42fa018f2 100755 (executable)
@@ -275,11 +275,17 @@ static inline int fifo_inc_ct(int ct, int size)
 \r
 /*vmac*/\r
 struct rk29_vmac_platform_data {\r
-    int (*vmac_register_set)(void);\r
-    int (*rmii_io_init)(void);\r
-    int (*rmii_io_deinit)(void);\r
-    int (*rmii_power_control)(int enable);\r
-    int(*rmii_speed_switch)(int speed);\r
+       int (*vmac_register_set)(void);\r
+       int (*rmii_io_init)(void);\r
+       int (*rmii_io_deinit)(void);\r
+       int (*rmii_power_control)(int enable);\r
+       int (*rmii_speed_switch)(int speed);\r
+       struct clk *clk_mac_pll_div;\r
+       struct clk *clk_mac_ref_div;\r
+       struct clk *mac_parent;\r
+       struct clk *hclk_mac;\r
+       int reset_io;\r
+       int reset_io_enable;\r
 };\r
 \r
 extern struct rk29_vmac_platform_data board_vmac_data;\r
index 3b328d3ffbdfa1aa4109a53cd77171e951b16c0d..20ba49169a1f69d82312e249ff0cf45fbab64970 100755 (executable)
 #include <linux/rockchip/grf.h>
 
 #include "rk29_vmac.h"
-
+#if 0
 struct vmac_phy_data {
        int power_io;
        int power_io_enable;
 };
 struct vmac_phy_data g_vmac_phy_data;
+#endif
 
-#define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
-#define grf_writel(v, offset)  do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
+#define grf_readl(offset)       readl_relaxed(RK_GRF_VIRT + offset)
+#define grf_writel(v, offset)   do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
 
 static int rk30_vmac_register_set(void)
 {
        //config rk30 vmac as rmii
-       writel_relaxed(0x3 << 16 | 0x2, RK_GRF_VIRT + RK3188_GRF_SOC_CON1);
+       grf_writel((0<<8) | ((1<<8)<<16), RK3036_GRF_SOC_CON0);
+       //newrev_en
+       grf_writel((1<<15) | ((1<<15)<<16), RK3036_GRF_SOC_CON0);
        return 0;
 }
 
@@ -48,7 +51,7 @@ static int rk30_rmii_io_init(void)
        printk("enter %s \n",__func__);
 
        //rk3188 gpio3 and sdio drive strength , 
-       grf_writel((0x0f<<16)|0x0f, RK3188_GRF_IO_CON3);
+       //grf_writel((0x0f<<16)|0x0f, RK3188_GRF_IO_CON3);
 
        return 0;
 }
@@ -62,6 +65,7 @@ static int rk30_rmii_io_deinit(void)
 
 static int rk30_rmii_power_control(int enable)
 {
+#if 0
        struct vmac_phy_data *pdata = &g_vmac_phy_data;
        
        printk("enter %s ,enable = %d \n",__func__,enable);
@@ -76,18 +80,17 @@ static int rk30_rmii_power_control(int enable)
                        gpio_set_value(pdata->power_io, !pdata->power_io_enable);
                }
        }
+#endif
        return 0;
 }
 
-#define BIT_EMAC_SPEED_100M      (1 << 1)
-#define BIT_EMAC_SPEED_10M       (0 << 1)
 static int rk29_vmac_speed_switch(int speed)
 {
        //printk("%s: speed = %d\n", __func__, speed);
        if (10 == speed) {
-           writel_relaxed((2<<16)|BIT_EMAC_SPEED_10M, RK_GRF_VIRT + RK3188_GRF_SOC_CON1);
+           grf_writel((0<<9) | ((1<<9)<<16), RK3036_GRF_SOC_CON0);
        } else {
-           writel_relaxed((2<<16)|BIT_EMAC_SPEED_100M, RK_GRF_VIRT + RK3188_GRF_SOC_CON1);
+           grf_writel((1<<9) | ((1<<9)<<16), RK3036_GRF_SOC_CON0);
        }
        return 0;
 }
@@ -99,7 +102,7 @@ struct rk29_vmac_platform_data board_vmac_data = {
        .rmii_power_control = rk30_rmii_power_control,
        .rmii_speed_switch = rk29_vmac_speed_switch,
 };
-
+#if 0
 static int vmac_phy_probe(struct platform_device *pdev)
 {
        struct vmac_phy_data *pdata = pdev->dev.platform_data;
@@ -167,3 +170,4 @@ module_platform_driver(vmac_phy_driver);
 
 MODULE_DESCRIPTION("VMAC PHY Power Driver");
 MODULE_LICENSE("GPL");
+#endif
old mode 100644 (file)
new mode 100755 (executable)
index 721973f..5c63bb6
@@ -13,3 +13,4 @@ obj-$(CONFIG_MT5931_MT6622)    += rockchip_wlan/mt5931/
 obj-$(CONFIG_RTL8723BS)        += rockchip_wlan/rtl8723bs/
 obj-$(CONFIG_MTK_COMBO_WIFI)   += rockchip_wlan/combo_mt66xx/
 obj-$(CONFIG_MTK_MT5931)       += rockchip_wlan/mt5931_kk/
+obj-$(CONFIG_ESP8089)   += rockchip_wlan/esp8089/
\ No newline at end of file
index 620c5cfe719d9116973918badb526f80ca7f7350..f8bdee84eaf6eeb72caea5ae6de145d0ceca1b66 100755 (executable)
@@ -1,5 +1,5 @@
-  config ESP8089
-      depends on WLAN_80211 && MMC
+config ESP8089
+#      depends on WLAN_80211 && MMC
       select WIRELESS_EXT
       select WEXT_PRIV
       select CFG80211
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/Makefile b/drivers/net/wireless/rockchip_wlan/esp8089/Makefile
new file mode 100755 (executable)
index 0000000..2f04b4e
--- /dev/null
@@ -0,0 +1,21 @@
+DRIVER_NAME := wlan
+include drivers/net/wireless/rockchip_wlan/esp8089/esp_config.mk
+
+EXTRA_CFLAGS += -DDEBUG -DSIP_DEBUG -DFAST_TX_STATUS -DANDROID -DKERNEL_IV_WAR -DRX_SENDUP_SYNC -DDEBUGFS -DHAS_FW -DTEST_MODE -DHAS_INIT_DATA
+
+obj-$(CONFIG_ESP8089) := $(DRIVER_NAME).o
+$(DRIVER_NAME)-y += esp_debug.o
+$(DRIVER_NAME)-y += sdio_sif_esp.o
+$(DRIVER_NAME)-y += spi_sif_esp.o
+$(DRIVER_NAME)-y += esp_io.o
+$(DRIVER_NAME)-y += esp_android.o
+$(DRIVER_NAME)-y += esp_main.o
+$(DRIVER_NAME)-y += esp_sip.o
+$(DRIVER_NAME)-y += esp_ext.o
+$(DRIVER_NAME)-y += esp_ctrl.o
+$(DRIVER_NAME)-y += esp_mac80211.o
+$(DRIVER_NAME)-y += esp_debug.o
+$(DRIVER_NAME)-y += esp_utils.o
+$(DRIVER_NAME)-y += esp_pm.o
+$(DRIVER_NAME)-y += testmode.o
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/eagle_fw1.h b/drivers/net/wireless/rockchip_wlan/esp8089/eagle_fw1.h
new file mode 100755 (executable)
index 0000000..bfebb1e
--- /dev/null
@@ -0,0 +1,2743 @@
+/* 
+ * Copyright (c) Espressif System
+
+ * Apr 13 2013 16:44:24 
+ */ 
+
+
+static u8 eagle_fw1[] =
+{ 
+        0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x40, 0xd8, 0xa1, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x05, 0x35, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x00, 0x06, 0x00, 0x60, 0x0c, 0x0a, 0x31, 0xfe, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x63, 0xc1, 0x3c, 
+        0x89, 0xc0, 0x20, 0x00, 0x82, 0x23, 0xc0, 0x90, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x82, 0x63, 0xc0, 
+        0x7c, 0x97, 0x0c, 0x46, 0xc0, 0x20, 0x00, 0x52, 0x23, 0xc0, 0x70, 0x55, 0x10, 0x60, 0x55, 0x20, 
+        0xc0, 0x20, 0x00, 0x52, 0x63, 0xc0, 0x0c, 0x14, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xc0, 0x40, 0x22, 
+        0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xc0, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x05, 0xfb, 0xff, 0x06, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xef, 0x3f, 0x8c, 0x82, 0xfe, 0x3f, 
+        0xcc, 0x24, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x41, 0xfb, 0xff, 0xc0, 0x20, 0x00, 0x02, 
+        0x24, 0x97, 0xc0, 0x20, 0x00, 0x42, 0x24, 0x96, 0xdc, 0x50, 0x49, 0x11, 0x09, 0x21, 0x29, 0x31, 
+        0xcc, 0xd4, 0x21, 0xf6, 0xff, 0x01, 0xf6, 0xff, 0xc0, 0x00, 0x00, 0x28, 0x31, 0x08, 0x21, 0x48, 
+        0x11, 0x00, 0x50, 0x75, 0xdc, 0xc5, 0x02, 0x42, 0x04, 0x3c, 0x46, 0x7c, 0xe7, 0x1c, 0x88, 0x40, 
+        0x98, 0x75, 0x00, 0xa8, 0x41, 0xa2, 0x42, 0x03, 0x92, 0x42, 0x05, 0x82, 0x42, 0x00, 0x72, 0x42, 
+        0x01, 0x62, 0x42, 0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0xc0, 0x88, 0xfe, 0x3f, 
+        0x40, 0x4f, 0x00, 0x40, 0x0c, 0xc3, 0x52, 0xa1, 0x00, 0x62, 0xa1, 0x00, 0x0c, 0x17, 0x12, 0xc1, 
+        0xe0, 0x09, 0x61, 0x22, 0xc1, 0x10, 0x29, 0x01, 0x02, 0xc1, 0x14, 0x21, 0xf8, 0xff, 0x09, 0x11, 
+        0x42, 0xc2, 0x10, 0x01, 0xf7, 0xff, 0xc0, 0x00, 0x00, 0x28, 0x41, 0x08, 0x61, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x3f, 0x28, 0x03, 0x00, 0x60, 0x00, 0x0a, 0x00, 0x60, 
+        0xd0, 0x4c, 0x00, 0x40, 0x04, 0x4d, 0x00, 0x40, 0xc0, 0x5d, 0x00, 0x40, 0xb8, 0x5d, 0x00, 0x40, 
+        0x12, 0xc1, 0xe0, 0xe9, 0x41, 0xf9, 0x51, 0x39, 0x01, 0x09, 0x11, 0xd9, 0x31, 0xc9, 0x21, 0xdd, 
+        0x02, 0x20, 0xc0, 0x75, 0xb6, 0x8c, 0x06, 0x0c, 0x10, 0x0c, 0x1c, 0x46, 0x00, 0x00, 0x0c, 0x00, 
+        0x0c, 0x1f, 0x9c, 0xfc, 0x26, 0x1c, 0x1f, 0xf6, 0x4c, 0x02, 0xf6, 0x2c, 0x0e, 0x22, 0xcc, 0xfc, 
+        0x16, 0x82, 0x14, 0x26, 0x5c, 0x05, 0x32, 0xcc, 0xfa, 0x16, 0xf3, 0x13, 0x0c, 0x04, 0x49, 0x61, 
+        0x0c, 0x02, 0xc6, 0x01, 0x00, 0x0c, 0x10, 0x0c, 0x12, 0x0c, 0x05, 0x59, 0x61, 0xd0, 0xe0, 0x34, 
+        0x00, 0x1e, 0x40, 0x00, 0xff, 0xa1, 0x9c, 0x62, 0x4d, 0x0f, 0x0c, 0x05, 0x00, 0x20, 0xa1, 0x7c, 
+        0xf3, 0x30, 0x30, 0x30, 0x00, 0x33, 0xa1, 0x01, 0xe2, 0xff, 0xc0, 0x00, 0x00, 0x46, 0x03, 0x00, 
+        0x0c, 0x02, 0x0c, 0x03, 0x0c, 0x04, 0x5d, 0x0f, 0x01, 0xde, 0xff, 0xc0, 0x00, 0x00, 0x21, 0x9c, 
+        0xff, 0xd0, 0x09, 0x54, 0xa2, 0xae, 0xcf, 0x2a, 0x00, 0xc0, 0x20, 0x00, 0x92, 0x20, 0x80, 0xa0, 
+        0x99, 0x10, 0xc0, 0x20, 0x00, 0x92, 0x60, 0x80, 0x0c, 0x48, 0xd0, 0x74, 0x24, 0xd0, 0x64, 0x14, 
+        0x80, 0x77, 0x10, 0xe0, 0x77, 0x11, 0x70, 0x66, 0x20, 0xc0, 0x66, 0x11, 0xc0, 0x20, 0x00, 0x52, 
+        0x20, 0x80, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x48, 0x61, 0x52, 0x60, 0x80, 0xdc, 0x34, 0x42, 
+        0xaf, 0x7f, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x80, 0x40, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x60, 
+        0x80, 0x46, 0x04, 0x00, 0x62, 0xa0, 0x80, 0xc0, 0x20, 0x00, 0x52, 0x20, 0x80, 0x60, 0x55, 0x20, 
+        0xc0, 0x20, 0x00, 0x52, 0x60, 0x80, 0x21, 0xbf, 0xff, 0xb6, 0x2c, 0x44, 0x26, 0x5c, 0x44, 0x41, 
+        0xbe, 0xff, 0xe0, 0x3e, 0x11, 0x4a, 0x33, 0xc0, 0x20, 0x00, 0x42, 0xac, 0x7f, 0x38, 0x03, 0x68, 
+        0x01, 0x40, 0x33, 0x10, 0x42, 0xcc, 0xfe, 0x90, 0x44, 0x11, 0x40, 0x33, 0x20, 0x26, 0x2c, 0x05, 
+        0x52, 0xa4, 0x00, 0x50, 0x33, 0x20, 0x16, 0x96, 0x06, 0x72, 0x12, 0x01, 0x09, 0x71, 0xf0, 0x77, 
+        0x20, 0x72, 0x52, 0x01, 0x2d, 0x0e, 0x01, 0xb3, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x71, 0xc6, 0x02, 
+        0x00, 0x66, 0x5c, 0x08, 0x82, 0x12, 0x03, 0x80, 0x8f, 0x20, 0x82, 0x52, 0x03, 0xa2, 0xaf, 0xbf, 
+        0xc0, 0x20, 0x00, 0x92, 0x20, 0x80, 0xa0, 0x99, 0x10, 0xc0, 0x20, 0x00, 0x92, 0x60, 0x80, 0xdc, 
+        0xac, 0x2d, 0x0e, 0x01, 0xa9, 0xff, 0xc0, 0x00, 0x00, 0xd0, 0x27, 0x14, 0x01, 0xa8, 0xff, 0xc0, 
+        0x00, 0x00, 0x0c, 0x0b, 0xc1, 0xa2, 0xff, 0xc0, 0x20, 0x00, 0xb2, 0x6c, 0x6d, 0xc8, 0x21, 0xd8, 
+        0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x0c, 0x1e, 0xe9, 0x61, 
+        0x06, 0xaf, 0xff, 0x42, 0x12, 0x00, 0x26, 0x2c, 0x0a, 0x40, 0x4f, 0x20, 0x42, 0x52, 0x00, 0x09, 
+        0x71, 0xc6, 0xe3, 0xff, 0x7c, 0xf5, 0x62, 0x12, 0x03, 0x50, 0x5f, 0x30, 0x40, 0x45, 0x10, 0x60, 
+        0x55, 0x10, 0x52, 0x52, 0x03, 0xc6, 0xf8, 0xff, 0x5c, 0x00, 0x10, 0x40, 0xa0, 0x88, 0xfe, 0x3f, 
+        0xb8, 0x1c, 0x00, 0x40, 0x68, 0x2e, 0x00, 0x40, 0x48, 0x2c, 0x00, 0x40, 0x48, 0x1d, 0x00, 0x40, 
+        0xc4, 0x2c, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x22, 0x61, 0x00, 0x02, 0x61, 0x01, 0x45, 0xde, 0xff, 
+        0x01, 0xf8, 0xff, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x05, 0x16, 0x03, 0x01, 0xf6, 0xff, 0xc0, 0x00, 
+        0x00, 0x31, 0xf1, 0xff, 0x21, 0xf2, 0xff, 0x0c, 0x04, 0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x01, 
+        0xf3, 0xff, 0xc0, 0x00, 0x00, 0x45, 0x4f, 0x00, 0x21, 0xed, 0xff, 0x0c, 0xa3, 0x0c, 0x04, 0x01, 
+        0xf0, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x98, 0x82, 0xfe, 0x3f, 
+        0xa0, 0x82, 0xfe, 0x3f, 0xb0, 0x82, 0xfe, 0x3f, 0xbc, 0x82, 0xfe, 0x3f, 0xc8, 0x82, 0xfe, 0x3f, 
+        0x00, 0x00, 0x06, 0x00, 0x00, 0xde, 0xff, 0x3f, 0x00, 0xe1, 0xff, 0x3f, 0x00, 0x02, 0x00, 0x60, 
+        0xd4, 0x82, 0xfe, 0x3f, 0xc4, 0x56, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 
+        0x00, 0x45, 0x0a, 0x00, 0x21, 0xf2, 0xff, 0x31, 0xf2, 0xff, 0x01, 0x41, 0xff, 0xc0, 0x00, 0x00, 
+        0x21, 0xf1, 0xff, 0x31, 0xf1, 0xff, 0x41, 0xf1, 0xff, 0x01, 0x3d, 0xff, 0xc0, 0x00, 0x00, 0x45, 
+        0x32, 0x00, 0xc1, 0x62, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x2c, 0x66, 0x16, 0x2c, 0x02, 0xc0, 0x20, 
+        0xf4, 0x8c, 0xb2, 0x0c, 0x03, 0x85, 0xd8, 0xff, 0x21, 0x5b, 0xff, 0x0c, 0x10, 0x02, 0x42, 0x0a, 
+        0xc0, 0x00, 0xf5, 0x16, 0xa0, 0x00, 0x21, 0xe6, 0xff, 0x0c, 0x13, 0x20, 0x20, 0x20, 0x05, 0xd7, 
+        0xff, 0x01, 0xe8, 0xff, 0xc0, 0x00, 0x00, 0x22, 0xa2, 0x0c, 0x05, 0x41, 0x00, 0xc5, 0x09, 0x00, 
+        0x85, 0x46, 0x00, 0x01, 0xe0, 0xff, 0x21, 0xe1, 0xff, 0x02, 0x20, 0xfe, 0x41, 0xdf, 0xff, 0x66, 
+        0x20, 0x0b, 0x32, 0x14, 0x7e, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x42, 0xc6, 0x02, 0x00, 0x66, 0x30, 
+        0x08, 0x52, 0x14, 0x7e, 0xc0, 0x20, 0x00, 0x52, 0x62, 0x41, 0x21, 0xd9, 0xff, 0x01, 0x20, 0xff, 
+        0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x38, 0xf3, 0xfe, 0x3f, 
+        0x98, 0x88, 0xfe, 0x3f, 0xe4, 0x82, 0xfe, 0x3f, 0x41, 0xfd, 0xff, 0x12, 0xc1, 0xf0, 0x31, 0xfc, 
+        0xff, 0x09, 0x01, 0x47, 0xb3, 0x0b, 0x0c, 0x06, 0x0d, 0x03, 0x62, 0x40, 0x00, 0x1b, 0x00, 0x47, 
+        0x90, 0xf7, 0x21, 0xf8, 0xff, 0x01, 0x12, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3c, 0x05, 0x10, 0x40, 0x00, 0x10, 0x00, 0x00, 
+        0x00, 0x00, 0x04, 0x00, 0xfc, 0x82, 0xfe, 0x3f, 0xf9, 0x84, 0x2e, 0x00, 0xf9, 0x84, 0x2a, 0x00, 
+        0xa8, 0x58, 0x00, 0x40, 0x88, 0x0f, 0x00, 0x40, 0xa8, 0x0f, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x11, 0x09, 0x01, 0x01, 0xfb, 0xff, 0xc0, 0x00, 0x00, 0x41, 0x98, 0xff, 0x38, 0xc2, 0x39, 0x54, 
+        0xc1, 0x27, 0xff, 0x21, 0xf0, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x57, 0x20, 0x00, 0x20, 0xc0, 
+        0x20, 0x00, 0x0c, 0x12, 0x31, 0xed, 0xff, 0x0c, 0x04, 0x02, 0x6c, 0x57, 0x01, 0xf2, 0xff, 0xc0, 
+        0x00, 0x00, 0x51, 0x1c, 0xff, 0x41, 0xac, 0xff, 0x52, 0x05, 0x0a, 0x01, 0xaa, 0xff, 0x16, 0x25, 
+        0x06, 0x02, 0x20, 0xfe, 0x31, 0xaa, 0xff, 0x66, 0x20, 0x0b, 0x22, 0x14, 0x7e, 0xc0, 0x20, 0x00, 
+        0x22, 0x63, 0x42, 0xc6, 0x02, 0x00, 0x66, 0x30, 0x08, 0x52, 0x14, 0x7e, 0xc0, 0x20, 0x00, 0x52, 
+        0x63, 0x41, 0x71, 0xde, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x2c, 0x6c, 0x70, 0xaa, 0x20, 0xc0, 0x20, 
+        0x00, 0xa2, 0x6c, 0x6c, 0x91, 0xdb, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x2c, 0x44, 0x90, 0x88, 0x20, 
+        0xc0, 0x20, 0x00, 0x82, 0x6c, 0x44, 0xc0, 0x20, 0x00, 0x62, 0x2c, 0x6d, 0x70, 0x66, 0x20, 0xc0, 
+        0x20, 0x00, 0x62, 0x6c, 0x6d, 0x21, 0xd3, 0xff, 0x01, 0xde, 0xfe, 0xc0, 0x00, 0x00, 0x01, 0xd2, 
+        0xff, 0x86, 0x00, 0x00, 0x01, 0xd2, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x6c, 0x43, 0xc0, 0x20, 0x00, 
+        0xb2, 0x2c, 0x43, 0x0c, 0x22, 0x01, 0xd0, 0xff, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xf9, 0x04, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 
+        0xff, 0xff, 0xfe, 0xff, 0x04, 0x83, 0xfe, 0x3f, 0x0c, 0x83, 0xfe, 0x3f, 0x41, 0x82, 0xff, 0x12, 
+        0xc1, 0xe0, 0xc9, 0x11, 0xe9, 0x31, 0xd9, 0x21, 0x09, 0x01, 0xf9, 0x41, 0x01, 0xbd, 0xff, 0xf1, 
+        0xbb, 0xff, 0xd1, 0xee, 0xfe, 0xe1, 0xf3, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x2d, 0x42, 0x16, 0xec, 
+        0x0d, 0x27, 0x7c, 0x47, 0x32, 0x24, 0xfe, 0x66, 0x23, 0x11, 0x91, 0x77, 0xff, 0x92, 0x19, 0x7e, 
+        0xc0, 0x20, 0x00, 0xa1, 0x76, 0xff, 0x92, 0x6a, 0x42, 0x46, 0x04, 0x00, 0x66, 0x33, 0x0e, 0xa1, 
+        0x72, 0xff, 0xa2, 0x1a, 0x7e, 0xc0, 0x20, 0x00, 0xb1, 0x71, 0xff, 0xa2, 0x6b, 0x41, 0xc0, 0x20, 
+        0x00, 0x22, 0x2d, 0x6c, 0xf0, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x6d, 0x6c, 0xc0, 0x20, 0x00, 
+        0xb2, 0x2d, 0x44, 0x00, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x6d, 0x44, 0x17, 0x7c, 0x1a, 0xc0, 
+        0x20, 0x00, 0x21, 0x46, 0xff, 0x31, 0xdc, 0xff, 0x28, 0x52, 0x32, 0x6d, 0x44, 0x08, 0x52, 0x28, 
+        0x82, 0xc0, 0x00, 0x00, 0x01, 0x9f, 0xff, 0x41, 0x5f, 0xff, 0xf7, 0x6c, 0x24, 0xc0, 0x20, 0x00, 
+        0x51, 0xd7, 0xff, 0x52, 0x6d, 0x44, 0xc0, 0x20, 0x00, 0x32, 0x2d, 0x53, 0x38, 0x23, 0x9c, 0x03, 
+        0x21, 0x3b, 0xff, 0x28, 0x52, 0x08, 0x62, 0x28, 0x82, 0xc0, 0x00, 0x00, 0x01, 0x95, 0xff, 0x41, 
+        0x55, 0xff, 0x07, 0x7c, 0x20, 0xc0, 0x20, 0x00, 0x51, 0xce, 0xff, 0x62, 0x2d, 0x43, 0x50, 0x66, 
+        0x10, 0xc0, 0x20, 0x00, 0x62, 0x6d, 0x43, 0xc0, 0x20, 0x00, 0x32, 0x2d, 0x44, 0x50, 0x33, 0x10, 
+        0xc0, 0x20, 0x00, 0x32, 0x6d, 0x44, 0xe7, 0x8c, 0x02, 0xc6, 0xce, 0xff, 0x37, 0xfc, 0x0e, 0x57, 
+        0xfc, 0x2c, 0xa7, 0xec, 0x3b, 0xc0, 0x20, 0x00, 0x72, 0x2d, 0x44, 0x46, 0xca, 0xff, 0x21, 0xc1, 
+        0xff, 0x31, 0xc1, 0xff, 0x42, 0xa2, 0x4a, 0x01, 0x8e, 0xfe, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 
+        0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x21, 
+        0xb9, 0xff, 0x31, 0xb9, 0xff, 0x42, 0xa2, 0x51, 0x01, 0x86, 0xfe, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x21, 0xb4, 0xff, 0x31, 0xb5, 0xff, 0x42, 0xa2, 0x58, 0x01, 0x81, 0xfe, 0xc0, 0x00, 0x00, 
+        0x06, 0xff, 0xff, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x66, 0x92, 0x0c, 0x0c, 0xd2, 0x45, 0x05, 
+        0x00, 0x0c, 0xa2, 0x05, 0x05, 0x00, 0xc6, 0x01, 0x00, 0x0c, 0xd0, 0x07, 0x12, 0x02, 0x45, 0x04, 
+        0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x74, 0x06, 0x10, 0x40, 0x18, 0x83, 0xfe, 0x3f, 
+        0x2c, 0x24, 0x00, 0x40, 0x21, 0xfd, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfd, 0xff, 0xc0, 
+        0x00, 0x00, 0x21, 0xfa, 0xff, 0x01, 0x6e, 0xfe, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x5f, 0x4c, 0x3f, 0x00, 0x40, 
+        0xcc, 0x2e, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 0x09, 0x01, 0xdd, 0x02, 0x01, 
+        0xfb, 0xff, 0xc0, 0x00, 0x00, 0x22, 0x02, 0x40, 0xc1, 0xf7, 0xff, 0x01, 0xf7, 0xff, 0x20, 0xcc, 
+        0xd1, 0x0a, 0xcc, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x87, 0xd9, 0x31, 0x77, 0x70, 0x19, 0xd1, 0xf3, 
+        0xfe, 0x0c, 0x12, 0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x48, 0x6d, 0x1b, 0x44, 0x49, 0x6d, 0xc0, 
+        0x20, 0x00, 0x32, 0x2c, 0x87, 0x77, 0xf3, 0xe8, 0xc0, 0x20, 0x00, 0x0c, 0x02, 0x08, 0x01, 0x58, 
+        0x31, 0xd8, 0x21, 0x52, 0x6c, 0x80, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0xff, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xe4, 0xff, 0xc0, 0x00, 0x00, 0x01, 
+        0xfc, 0xff, 0x72, 0x02, 0x40, 0x51, 0xdf, 0xff, 0x61, 0xe0, 0xff, 0x70, 0x55, 0xd1, 0x6a, 0x55, 
+        0xc0, 0x20, 0x00, 0x22, 0x25, 0x87, 0x27, 0x00, 0x08, 0xc0, 0x20, 0x00, 0x82, 0x25, 0x87, 0x07, 
+        0x88, 0xf6, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xd0, 0x89, 0xfe, 0x3f, 
+        0x60, 0x8e, 0xfe, 0x3f, 0x80, 0x61, 0x00, 0x00, 0x94, 0x5e, 0x00, 0x40, 0x51, 0xfe, 0xff, 0x0c, 
+        0x07, 0x21, 0xfa, 0xff, 0x12, 0xc1, 0xe0, 0x32, 0xa1, 0x04, 0x6d, 0x03, 0x09, 0x61, 0x48, 0x02, 
+        0x02, 0xc1, 0x14, 0x22, 0xc2, 0x10, 0x32, 0x54, 0x02, 0x41, 0xf5, 0xff, 0x32, 0xc1, 0x10, 0x09, 
+        0x11, 0x39, 0x01, 0x32, 0xa4, 0x80, 0x01, 0x4a, 0xfe, 0xc0, 0x00, 0x00, 0x28, 0x41, 0x38, 0x51, 
+        0x42, 0xa0, 0x60, 0x01, 0xf1, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x61, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x4c, 0x08, 0x10, 0x40, 0x4c, 0x54, 0x00, 0x40, 0x8c, 0x60, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x29, 
+        0x01, 0x09, 0x11, 0x01, 0x1f, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xe4, 0xff, 0x29, 0x00, 0x21, 0xf8, 
+        0xff, 0x01, 0xf8, 0xff, 0xc0, 0x00, 0x00, 0x31, 0xe1, 0xff, 0x38, 0x03, 0x28, 0x01, 0x22, 0x53, 
+        0x03, 0x01, 0xf5, 0xff, 0xc0, 0x00, 0x00, 0x45, 0xf8, 0xff, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x80, 0x51, 0x00, 0x40, 0x08, 0x58, 0x00, 0x40, 0x0c, 0x02, 0x1c, 0x03, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfb, 0xff, 0xc0, 0x00, 0x00, 0x3d, 0x02, 0x01, 0xfa, 0xff, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x0c, 0x02, 0x0c, 0x03, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x3d, 0x02, 0x01, 0xf2, 0xff, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x22, 
+        0x22, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x07, 0x32, 0x02, 0x06, 0x80, 0x00, 0x11, 0x30, 0x00, 
+        0x20, 0x32, 0x02, 0x05, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 0x02, 0x04, 0x80, 0x00, 0x11, 
+        0x30, 0x00, 0x20, 0x66, 0x70, 0x05, 0x22, 0xc2, 0x0c, 0x85, 0xa6, 0xff, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x00, 0x0e, 0x00, 0x60, 0x20, 0x53, 0xc0, 0x3b, 0x45, 0x50, 0x45, 0xb3, 
+        0x40, 0x42, 0x21, 0x1b, 0x34, 0xa6, 0x13, 0x17, 0x20, 0x63, 0xa0, 0x31, 0xfa, 0xff, 0xc0, 0x20, 
+        0x00, 0x78, 0x02, 0xc0, 0x20, 0x00, 0x72, 0x63, 0x80, 0x4b, 0x22, 0x4b, 0x33, 0x67, 0x92, 0xed, 
+        0x0d, 0xf0, 0x00, 0x00, 0x20, 0x63, 0xc0, 0x3b, 0x56, 0x60, 0x56, 0xb3, 0x50, 0x52, 0x21, 0x1b, 
+        0x55, 0xa6, 0x15, 0x1a, 0x61, 0xf0, 0xff, 0x31, 0xef, 0xff, 0x60, 0x65, 0xa0, 0xc0, 0x20, 0x00, 
+        0x72, 0x23, 0x80, 0xc0, 0x20, 0x00, 0x79, 0x02, 0x4b, 0x33, 0x4b, 0x22, 0x67, 0x93, 0xed, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0xe0, 0xef, 0xfe, 0x3f, 0x20, 0x73, 0x04, 0x20, 0x61, 0x04, 0x20, 0x50, 
+        0x04, 0x12, 0xc1, 0xe0, 0x09, 0x31, 0xc9, 0x41, 0x6a, 0x55, 0xc1, 0xfa, 0xff, 0x20, 0x62, 0x04, 
+        0x7a, 0x66, 0x20, 0x05, 0x04, 0x20, 0x76, 0x04, 0x7a, 0x00, 0x20, 0x74, 0x04, 0x7a, 0x00, 0x6a, 
+        0x00, 0x5a, 0x00, 0x30, 0x53, 0x24, 0x00, 0x20, 0x74, 0x0c, 0x40, 0xf6, 0x52, 0x01, 0x0d, 0x02, 
+        0x00, 0x20, 0x90, 0x1c, 0xd0, 0x50, 0x22, 0x90, 0x20, 0x20, 0x74, 0x27, 0x30, 0x01, 0x0d, 0x02, 
+        0x0c, 0x42, 0x00, 0x50, 0x74, 0x0c, 0x13, 0x08, 0x0c, 0x40, 0x45, 0xb0, 0x68, 0x14, 0x02, 0x20, 
+        0x2b, 0x48, 0x04, 0x60, 0x79, 0x84, 0x79, 0x11, 0x40, 0x50, 0x84, 0x60, 0x60, 0x84, 0x69, 0x21, 
+        0x59, 0x01, 0x40, 0x49, 0x84, 0xc0, 0x00, 0x00, 0x48, 0x11, 0x08, 0x0c, 0x0c, 0x52, 0x02, 0x20, 
+        0x2b, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0x48, 0x01, 0x08, 0x0c, 0x0c, 0x42, 0x02, 0x20, 0x2b, 0x0c, 
+        0x23, 0xc0, 0x00, 0x00, 0x48, 0x21, 0x08, 0x0c, 0x0c, 0x52, 0x02, 0x20, 0x2b, 0x0c, 0x23, 0xc0, 
+        0x00, 0x00, 0xc8, 0x41, 0x08, 0x31, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x24, 0x83, 0xfe, 0x3f, 
+        0x7c, 0x83, 0xfe, 0x3f, 0x00, 0x00, 0x80, 0x00, 0x98, 0x83, 0xfe, 0x3f, 0xa4, 0x83, 0xfe, 0x3f, 
+        0x14, 0x1d, 0x00, 0x40, 0xad, 0x05, 0x9d, 0x06, 0x12, 0xc1, 0xb0, 0x29, 0xd1, 0x09, 0x51, 0xf9, 
+        0x91, 0xc9, 0x61, 0x39, 0xf1, 0xe9, 0x81, 0xd9, 0x71, 0x49, 0xa1, 0xd1, 0xca, 0xff, 0x6c, 0xf4, 
+        0xed, 0x07, 0x31, 0x62, 0xfe, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xe4, 0x40, 0x22, 0x10, 0xc0, 0x20, 
+        0x00, 0x1c, 0x24, 0x0c, 0x75, 0x0c, 0x06, 0x0c, 0x07, 0xa9, 0xb1, 0x99, 0xe1, 0x08, 0x0d, 0x22, 
+        0x63, 0xe4, 0x22, 0xa0, 0x77, 0x02, 0x20, 0x27, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 
+        0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x08, 0x0d, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 
+        0x00, 0x00, 0x0c, 0x13, 0x0c, 0x52, 0x0c, 0x0c, 0x48, 0xd1, 0xc2, 0x61, 0x13, 0x40, 0x23, 0x93, 
+        0x29, 0xc1, 0x08, 0xc1, 0xf2, 0x21, 0x13, 0x07, 0x2f, 0x02, 0x06, 0xa7, 0x00, 0x16, 0x4f, 0x28, 
+        0x0b, 0x3f, 0x16, 0x43, 0x28, 0x42, 0xcf, 0xfe, 0x16, 0x34, 0x28, 0x52, 0xcf, 0xfd, 0x16, 0xb5, 
+        0x2a, 0x62, 0xcf, 0xfc, 0x16, 0x06, 0x2b, 0x0c, 0x0c, 0x0c, 0x07, 0x72, 0x61, 0x10, 0x32, 0x21, 
+        0x13, 0x0c, 0x82, 0x08, 0x0d, 0x0c, 0x0f, 0x02, 0x20, 0x34, 0x30, 0xf2, 0x83, 0x2d, 0x0f, 0xc0, 
+        0x00, 0x00, 0x42, 0x21, 0x13, 0xf6, 0x24, 0x13, 0x0c, 0x02, 0x3d, 0x0f, 0x42, 0xa1, 0xf4, 0x08, 
+        0x0d, 0x0c, 0xc5, 0x02, 0x20, 0x3a, 0x62, 0xc1, 0x10, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0xd1, 0x9d, 
+        0xff, 0x32, 0xa1, 0x04, 0x08, 0x0d, 0x4d, 0x0c, 0x02, 0x20, 0x15, 0x1c, 0x65, 0xc0, 0x00, 0x00, 
+        0x2d, 0x0c, 0x1c, 0x63, 0x48, 0xb1, 0x05, 0xe6, 0xff, 0xac, 0xde, 0x7d, 0x0c, 0x6d, 0x0f, 0x21, 
+        0xbf, 0xff, 0x0c, 0x03, 0x1c, 0x6a, 0xa9, 0x01, 0x92, 0x01, 0x10, 0x42, 0xa1, 0x04, 0x80, 0x99, 
+        0x01, 0x90, 0x98, 0x31, 0x99, 0x11, 0x82, 0x01, 0x11, 0x52, 0x21, 0x10, 0x80, 0x88, 0x01, 0x80, 
+        0x88, 0x31, 0x89, 0x21, 0x01, 0xbb, 0xff, 0xc0, 0x00, 0x00, 0xd1, 0x8a, 0xff, 0x08, 0x0d, 0x02, 
+        0x20, 0x10, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x0c, 0x0f, 0x0c, 0x12, 0x38, 0xf1, 0x42, 0x21, 0x10, 
+        0x0c, 0x05, 0x0c, 0x06, 0x69, 0x01, 0x69, 0x11, 0x69, 0x21, 0x08, 0x0d, 0x0c, 0x07, 0x02, 0x20, 
+        0x1a, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x08, 0x0d, 0x0c, 0x12, 0x08, 0xd0, 0x32, 0xa4, 0x00, 0xc0, 
+        0x00, 0x00, 0xc0, 0x20, 0x00, 0x08, 0x0d, 0xc1, 0x15, 0xfe, 0x08, 0xc0, 0xc2, 0x2c, 0xf9, 0xc0, 
+        0x00, 0x00, 0x8c, 0xde, 0x21, 0xa3, 0xff, 0xc0, 0x38, 0x21, 0x41, 0x88, 0xfe, 0x01, 0xa4, 0xff, 
+        0xc0, 0x00, 0x00, 0x21, 0xa0, 0xff, 0x02, 0x21, 0x10, 0xc7, 0xa2, 0x10, 0x22, 0xc0, 0x18, 0x1b, 
+        0xff, 0xf0, 0xf0, 0x74, 0x20, 0x00, 0x74, 0x02, 0x61, 0x10, 0x66, 0x2f, 0x9b, 0x02, 0x2d, 0x00, 
+        0x02, 0x20, 0x1b, 0x22, 0xa0, 0x01, 0xc0, 0x00, 0x00, 0xc2, 0xa0, 0x00, 0x0c, 0x0f, 0x0c, 0x0d, 
+        0x0c, 0x02, 0x0c, 0x03, 0x32, 0x61, 0x11, 0x22, 0x61, 0x12, 0x0c, 0xe2, 0x38, 0xf1, 0x42, 0x21, 
+        0x10, 0x52, 0xc1, 0x12, 0x68, 0xe1, 0x7d, 0x0e, 0x05, 0x5e, 0x05, 0x9c, 0xbe, 0x21, 0x8e, 0xff, 
+        0x3d, 0x0c, 0x52, 0x01, 0x13, 0x42, 0x01, 0x12, 0x80, 0x55, 0x01, 0x80, 0x44, 0x01, 0x40, 0x48, 
+        0x31, 0x50, 0x58, 0x31, 0x01, 0x8b, 0xff, 0xc0, 0x00, 0x00, 0xbc, 0x0c, 0x22, 0x01, 0x12, 0x01, 
+        0x59, 0xff, 0x80, 0x22, 0x01, 0x08, 0x00, 0x20, 0x28, 0x31, 0x08, 0x00, 0x20, 0x2d, 0xc0, 0xc0, 
+        0x00, 0x00, 0xe6, 0x22, 0x18, 0x22, 0x01, 0x13, 0x01, 0x53, 0xff, 0x80, 0x22, 0x01, 0x08, 0x00, 
+        0x20, 0x28, 0x31, 0x08, 0x00, 0x20, 0x2f, 0xc0, 0xc0, 0x00, 0x00, 0xa6, 0x22, 0x31, 0x32, 0x21, 
+        0x12, 0x22, 0x21, 0x11, 0xd2, 0x01, 0x12, 0xf2, 0x01, 0x13, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x80, 
+        0xff, 0x01, 0x80, 0xdd, 0x01, 0xd0, 0xd8, 0x31, 0xf0, 0xf8, 0x31, 0x2a, 0x2f, 0x3a, 0x3d, 0x32, 
+        0x61, 0x12, 0x22, 0x61, 0x11, 0x26, 0x4c, 0x02, 0x86, 0xdb, 0xff, 0x0c, 0x00, 0x46, 0x00, 0x00, 
+        0x0c, 0x10, 0x6c, 0x13, 0x56, 0x40, 0x09, 0xd2, 0x21, 0x12, 0x02, 0x21, 0x11, 0x2b, 0xdd, 0x2b, 
+        0x00, 0x00, 0x02, 0x21, 0xd0, 0xd2, 0x21, 0x80, 0xdd, 0x01, 0xd0, 0xd8, 0x31, 0x7c, 0x12, 0x80, 
+        0xf0, 0x01, 0xf0, 0xf8, 0x31, 0x0d, 0x02, 0x27, 0x2d, 0x01, 0x0d, 0x0d, 0x0c, 0xf2, 0x7d, 0x02, 
+        0xe6, 0xb0, 0x01, 0x7d, 0x00, 0x0d, 0x03, 0x80, 0xd7, 0x01, 0xd0, 0xd8, 0x31, 0x37, 0x2f, 0x01, 
+        0x0d, 0x0f, 0x1c, 0xff, 0x7d, 0x0f, 0xe6, 0xc0, 0x01, 0x7d, 0x00, 0x80, 0xf7, 0x01, 0x08, 0xd1, 
+        0xf0, 0xf8, 0x31, 0xdc, 0x50, 0x38, 0xa1, 0x70, 0x00, 0x54, 0xd0, 0x20, 0x44, 0xa0, 0x22, 0x11, 
+        0x20, 0x00, 0x20, 0x22, 0x21, 0x13, 0x30, 0x22, 0x90, 0x02, 0x52, 0x00, 0x8c, 0xee, 0x5d, 0x0f, 
+        0x4d, 0x0d, 0x21, 0x52, 0xff, 0x32, 0x21, 0x13, 0x01, 0x52, 0xff, 0xc0, 0x00, 0x00, 0xc0, 0x50, 
+        0x14, 0xd1, 0x20, 0xff, 0x32, 0x21, 0x13, 0x68, 0x1d, 0x1b, 0x43, 0x40, 0x30, 0x74, 0x32, 0x61, 
+        0x13, 0xe0, 0x66, 0x11, 0x60, 0x55, 0x20, 0x59, 0x1d, 0x46, 0x65, 0xff, 0x02, 0x01, 0x13, 0x22, 
+        0x01, 0x12, 0x80, 0x00, 0x01, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0x00, 0x08, 0x31, 0xfa, 0x00, 
+        0xda, 0xd2, 0x1b, 0xdd, 0x1b, 0x00, 0x00, 0x01, 0x21, 0xd0, 0xd1, 0x21, 0x80, 0xdd, 0x01, 0xd0, 
+        0xd8, 0x31, 0xc6, 0xd5, 0xff, 0x0c, 0x0c, 0x86, 0x63, 0xff, 0x4c, 0x0c, 0x46, 0x62, 0xff, 0xc2, 
+        0xa0, 0x60, 0x0c, 0xf2, 0x22, 0x61, 0x10, 0xc6, 0x60, 0xff, 0x1c, 0x05, 0xc0, 0x20, 0x00, 0x41, 
+        0xa3, 0xfd, 0x32, 0x24, 0xe4, 0x50, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x64, 0xe4, 0xc8, 0x61, 
+        0xd8, 0x71, 0xe8, 0x81, 0xf8, 0x91, 0x08, 0x51, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0xc2, 0xa0, 0x70, 
+        0x2c, 0x86, 0x62, 0x61, 0x10, 0x46, 0x55, 0xff, 0xc2, 0xa0, 0x78, 0x4c, 0x17, 0x72, 0x61, 0x10, 
+        0x86, 0x52, 0xff, 0x00, 0xc8, 0x83, 0xfe, 0x3f, 0x10, 0x80, 0xfe, 0x3f, 0x12, 0xc1, 0xc0, 0xc9, 
+        0x21, 0xd9, 0x31, 0xe9, 0x41, 0xf9, 0x51, 0x09, 0x11, 0x59, 0xa1, 0x79, 0x91, 0x29, 0x71, 0x49, 
+        0x81, 0x22, 0xa0, 0x7f, 0x80, 0x43, 0x01, 0x40, 0x48, 0x31, 0x40, 0x32, 0xa3, 0x39, 0x61, 0xe6, 
+        0x13, 0x02, 0x46, 0x40, 0x00, 0x0c, 0x0c, 0x0c, 0x00, 0x0c, 0x0f, 0x58, 0xa1, 0x0b, 0x76, 0xdd, 
+        0x05, 0x7a, 0x55, 0x59, 0xb1, 0x1c, 0x83, 0xa2, 0x0d, 0x00, 0xf0, 0x6c, 0xc0, 0x80, 0xe6, 0x01, 
+        0xe0, 0xe8, 0x31, 0x80, 0xaa, 0x01, 0xa0, 0xa8, 0x31, 0xa7, 0x2e, 0x3e, 0x80, 0x66, 0x01, 0x28, 
+        0xb1, 0x60, 0x68, 0x31, 0x27, 0xad, 0x33, 0xa0, 0x70, 0x74, 0xcc, 0xa7, 0x82, 0x0d, 0x01, 0x80, 
+        0x88, 0x01, 0x80, 0x88, 0x31, 0x87, 0x26, 0x22, 0xd8, 0xa1, 0x1b, 0x00, 0xa0, 0x20, 0x74, 0x2a, 
+        0xff, 0x00, 0x00, 0x74, 0x0a, 0xdd, 0xf0, 0x6c, 0xc0, 0x80, 0xe6, 0x01, 0xa2, 0x0d, 0x00, 0xe0, 
+        0xe8, 0x31, 0x80, 0xaa, 0x01, 0xa0, 0xa8, 0x31, 0xa7, 0xae, 0xc0, 0x09, 0xc1, 0x37, 0x2e, 0x0d, 
+        0x62, 0xce, 0xe8, 0x0c, 0xfe, 0x80, 0x66, 0x01, 0x60, 0x68, 0x31, 0x86, 0x09, 0x00, 0xe0, 0x2e, 
+        0x20, 0x32, 0xa0, 0x06, 0x85, 0x1e, 0x09, 0x0d, 0x02, 0x0c, 0x63, 0x2d, 0x0e, 0x00, 0x10, 0x40, 
+        0x0c, 0x1e, 0x00, 0xee, 0xa1, 0x0b, 0xee, 0xe0, 0xe0, 0xf4, 0xc5, 0x23, 0x09, 0x08, 0xc1, 0x80, 
+        0x62, 0x01, 0x60, 0x68, 0x31, 0xa6, 0x56, 0x04, 0x0c, 0x56, 0x86, 0x00, 0x00, 0x60, 0x60, 0xf4, 
+        0x09, 0xc1, 0x69, 0x01, 0x78, 0x91, 0x98, 0x81, 0x88, 0x71, 0x90, 0x90, 0x90, 0x42, 0x19, 0x00, 
+        0x80, 0x8c, 0x90, 0x40, 0x4e, 0xb0, 0x4a, 0x46, 0x40, 0x40, 0xf4, 0x42, 0x58, 0x00, 0x9c, 0x47, 
+        0x52, 0x19, 0x00, 0x21, 0xc0, 0xff, 0x3d, 0x0c, 0x6d, 0x0e, 0x78, 0x01, 0x01, 0xe9, 0xfe, 0xc0, 
+        0x00, 0x00, 0x08, 0xc1, 0x68, 0x01, 0x0c, 0xfa, 0xa7, 0x9e, 0x0b, 0x66, 0x56, 0x08, 0xb1, 0xba, 
+        0xff, 0xc2, 0x4b, 0x00, 0xc6, 0x03, 0x00, 0xe8, 0x61, 0x1b, 0xcc, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 
+        0x31, 0xe0, 0xec, 0xc0, 0x56, 0xde, 0xf0, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 
+        0x11, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 
+        0x02, 0x1c, 0x70, 0x27, 0x20, 0x1d, 0x1c, 0x12, 0xc7, 0x22, 0x12, 0xe6, 0xac, 0x09, 0x4c, 0x00, 
+        0xe6, 0x6c, 0x13, 0x0c, 0x00, 0x86, 0x03, 0x00, 0x02, 0xa0, 0x60, 0x06, 0x02, 0x00, 0x02, 0xa0, 
+        0x70, 0x86, 0x00, 0x00, 0x02, 0xa0, 0x78, 0x21, 0x9f, 0xfe, 0x00, 0x40, 0xf4, 0x02, 0x22, 0x00, 
+        0x32, 0xa0, 0x01, 0x02, 0x20, 0x2b, 0x22, 0xa0, 0x03, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x0c, 0x63, 
+        0x45, 0x17, 0x09, 0x0c, 0x23, 0x0c, 0x65, 0xd0, 0x42, 0x11, 0x01, 0x96, 0xfe, 0x0c, 0x32, 0x08, 
+        0x00, 0x50, 0x44, 0x20, 0x02, 0x20, 0x2b, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x60, 0x00, 0x00, 0x03, 0x00, 
+        0xa0, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x9e, 0x00, 0x60, 
+        0x9d, 0x04, 0x12, 0xc1, 0xa0, 0xc9, 0xb1, 0x29, 0x71, 0x09, 0xa1, 0xe9, 0xd1, 0x4d, 0x05, 0xf9, 
+        0xe1, 0xd9, 0xc1, 0x0c, 0x4f, 0xd1, 0xf4, 0xff, 0x49, 0x61, 0x92, 0x61, 0x12, 0xed, 0x06, 0x08, 
+        0x02, 0x6d, 0x07, 0x62, 0x61, 0x11, 0x00, 0x00, 0x05, 0x56, 0xd0, 0x1d, 0x41, 0xf0, 0xff, 0xc1, 
+        0x7d, 0xfe, 0x31, 0x16, 0xfd, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xf2, 0x40, 0x22, 0x20, 0xc0, 0x20, 
+        0x00, 0x22, 0x63, 0xf2, 0xc0, 0x20, 0x00, 0x08, 0x0c, 0x22, 0xa1, 0xe0, 0x02, 0x20, 0x28, 0x22, 
+        0x6d, 0x1a, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x08, 0x0c, 0x0c, 0x75, 
+        0x02, 0x20, 0x25, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x55, 0x0c, 0x56, 
+        0x08, 0x0c, 0x29, 0x81, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x1c, 
+        0x84, 0x0c, 0x55, 0x0c, 0x56, 0x0c, 0x07, 0x08, 0x0c, 0x29, 0x91, 0x02, 0x20, 0x27, 0x22, 0xa0, 
+        0x77, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 
+        0x06, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x16, 0xbe, 0x0d, 0x0c, 0x06, 0x0c, 0x0c, 
+        0x22, 0x01, 0x68, 0x29, 0xf1, 0x22, 0x21, 0x11, 0x20, 0x2c, 0x90, 0x22, 0x12, 0x00, 0xf0, 0x9f, 
+        0x20, 0x20, 0x00, 0xe4, 0x20, 0x84, 0x04, 0x20, 0x47, 0x04, 0x20, 0x76, 0x04, 0x20, 0x35, 0x04, 
+        0x20, 0x59, 0x04, 0x20, 0xb8, 0x04, 0x50, 0xbb, 0x80, 0x70, 0x33, 0x80, 0x4a, 0xbb, 0x3a, 0xbb, 
+        0x1c, 0xd3, 0x20, 0x23, 0x04, 0x8a, 0x22, 0x2a, 0xbb, 0xb0, 0xb0, 0x74, 0xb7, 0x3f, 0x01, 0x9d, 
+        0x0b, 0x62, 0x61, 0x13, 0x00, 0xb0, 0x24, 0x90, 0xa0, 0x74, 0x9d, 0x03, 0xa0, 0xaa, 0x90, 0xb0, 
+        0xaa, 0x90, 0xa0, 0xa0, 0xf4, 0xa7, 0x33, 0x01, 0x9d, 0x0a, 0x90, 0x20, 0xf4, 0x22, 0x61, 0x10, 
+        0x00, 0x02, 0x40, 0x60, 0xb0, 0x91, 0x07, 0xeb, 0x5b, 0x00, 0x20, 0xb4, 0xc5, 0x5f, 0x02, 0x21, 
+        0xb4, 0xff, 0x32, 0xc1, 0x10, 0x01, 0x3f, 0xfe, 0x0c, 0xa4, 0x08, 0x00, 0x58, 0xf1, 0x02, 0x20, 
+        0x3b, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x62, 0x21, 0x13, 0x0c, 0x18, 0x32, 0x21, 0x12, 0x42, 0x91, 
+        0x08, 0x22, 0x91, 0x09, 0x92, 0x21, 0x10, 0x52, 0x91, 0x0a, 0x72, 0x91, 0x0b, 0x50, 0x50, 0x84, 
+        0x70, 0x70, 0x84, 0x00, 0x19, 0x40, 0x20, 0x20, 0x84, 0x40, 0x40, 0x84, 0x30, 0x39, 0xb0, 0x70, 
+        0x44, 0x11, 0x70, 0x22, 0x11, 0x00, 0x88, 0xa1, 0x80, 0x66, 0x20, 0x70, 0x22, 0x20, 0x50, 0x44, 
+        0x20, 0x49, 0x03, 0x29, 0x13, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0xc0, 0x4e, 0xc0, 0x56, 0x44, 0xf3, 
+        0xc1, 0x29, 0xfe, 0x08, 0xf1, 0x86, 0x00, 0x00, 0x02, 0x01, 0x68, 0x72, 0x01, 0x64, 0x62, 0x01, 
+        0x60, 0x0c, 0x02, 0x0c, 0x83, 0x48, 0x61, 0x52, 0x21, 0x12, 0x09, 0x01, 0x45, 0x94, 0xff, 0x41, 
+        0x95, 0xff, 0xc0, 0x20, 0x00, 0x31, 0xb9, 0xfc, 0x22, 0x23, 0xf2, 0x40, 0x22, 0x10, 0xc0, 0x20, 
+        0x00, 0x78, 0x91, 0x1c, 0x84, 0x0c, 0x55, 0x0c, 0x56, 0x22, 0x63, 0xf2, 0x08, 0x0c, 0x22, 0xa0, 
+        0x77, 0x02, 0x20, 0x27, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x78, 0x81, 0x22, 0xa0, 0x77, 0x0c, 0x03, 
+        0x1c, 0x24, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x08, 0x0c, 
+        0x02, 0x20, 0x32, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x31, 0xc0, 0x00, 0x00, 0x08, 0x0c, 
+        0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0x62, 0x21, 0x11, 0x92, 0x21, 0x12, 0x38, 0x71, 0x51, 0x7e, 
+        0xff, 0x28, 0x03, 0x48, 0x61, 0x50, 0x22, 0x20, 0x29, 0x03, 0x16, 0x5e, 0x0d, 0xa1, 0x7b, 0xff, 
+        0x0c, 0x0c, 0x60, 0x0c, 0x90, 0x02, 0x10, 0x00, 0x1c, 0xd3, 0x00, 0x78, 0x04, 0x00, 0xb4, 0x04, 
+        0x00, 0x83, 0x04, 0xba, 0x88, 0x00, 0xf6, 0x04, 0x00, 0xb5, 0x04, 0xfa, 0xbb, 0x00, 0xf9, 0x04, 
+        0xfa, 0x77, 0x00, 0xf7, 0x04, 0x00, 0x00, 0xe4, 0xfa, 0x77, 0xba, 0x77, 0x0c, 0x4f, 0x2d, 0x0f, 
+        0x8a, 0x77, 0x00, 0x80, 0x24, 0x70, 0x70, 0x74, 0xf6, 0x57, 0x01, 0x2d, 0x07, 0x20, 0x50, 0x74, 
+        0x2d, 0x03, 0x50, 0x75, 0x90, 0x80, 0x77, 0x90, 0x70, 0x70, 0xf4, 0x77, 0x33, 0x01, 0x2d, 0x07, 
+        0x20, 0xb0, 0xf4, 0x90, 0xbb, 0xb0, 0x78, 0x1b, 0xb8, 0x0b, 0x70, 0xf9, 0x84, 0xb0, 0x30, 0x84, 
+        0x70, 0x70, 0x84, 0xb0, 0xb9, 0x84, 0xc0, 0x20, 0x00, 0x80, 0xbb, 0x11, 0xf0, 0x80, 0x01, 0x1c, 
+        0xe2, 0x22, 0x6d, 0x1a, 0xba, 0x88, 0x30, 0xb1, 0x41, 0xa0, 0x2c, 0xa0, 0xba, 0x88, 0xc0, 0x20, 
+        0x00, 0x89, 0x02, 0xc0, 0x20, 0x00, 0x1c, 0xfb, 0xb2, 0x6d, 0x1a, 0xc0, 0x20, 0x00, 0x10, 0x33, 
+        0x01, 0xa0, 0xff, 0x01, 0x89, 0x02, 0x3a, 0xff, 0x40, 0x35, 0x90, 0x32, 0x13, 0x00, 0x30, 0x77, 
+        0x11, 0x30, 0x30, 0xa4, 0x70, 0x33, 0xa0, 0x3a, 0xff, 0xc0, 0x20, 0x00, 0x72, 0xa1, 0xe0, 0x72, 
+        0x6d, 0x1a, 0xc0, 0x20, 0x00, 0xf9, 0x02, 0xc0, 0x20, 0x00, 0x32, 0xa1, 0xe1, 0x32, 0x6d, 0x1a, 
+        0xc0, 0x20, 0x00, 0xf9, 0x02, 0x1b, 0xcc, 0x22, 0x21, 0x14, 0xc0, 0xc0, 0x74, 0xc0, 0x7e, 0xc0, 
+        0x56, 0xe7, 0xf2, 0xc8, 0xb1, 0xd8, 0xc1, 0xe8, 0xd1, 0xf8, 0xe1, 0x08, 0xa1, 0x12, 0xc1, 0x60, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xc0, 0xd2, 0x61, 0x0c, 0xc2, 0x61, 0x0b, 0x09, 0xa1, 0xcd, 
+        0x02, 0x21, 0x62, 0xfc, 0xc0, 0x20, 0x00, 0x52, 0x22, 0xe3, 0x50, 0x59, 0x21, 0xc0, 0x20, 0x00, 
+        0x42, 0x22, 0xe0, 0x40, 0x49, 0x21, 0x5a, 0x44, 0xc0, 0x20, 0x00, 0x52, 0x22, 0xe2, 0x50, 0x59, 
+        0x21, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xe1, 0x00, 0x09, 0x21, 0x50, 0x00, 0xc0, 0x09, 0x31, 0xc0, 
+        0x20, 0x00, 0x62, 0x22, 0xf7, 0x60, 0x68, 0x21, 0x69, 0x01, 0xc0, 0x20, 0x00, 0x52, 0x22, 0xf8, 
+        0x50, 0x58, 0x21, 0x59, 0x11, 0xc0, 0x20, 0x00, 0x22, 0x22, 0xf9, 0x7c, 0xcd, 0x52, 0xc3, 0xfe, 
+        0x00, 0x0f, 0x31, 0x09, 0x21, 0x00, 0x05, 0x40, 0xd0, 0xd3, 0x90, 0x40, 0x5f, 0x31, 0x20, 0x20, 
+        0xb1, 0x29, 0x0c, 0x3d, 0x05, 0x2d, 0x04, 0x85, 0x2d, 0x08, 0x29, 0x51, 0x39, 0x41, 0x58, 0x21, 
+        0x48, 0x31, 0x3d, 0x05, 0x2d, 0x04, 0x85, 0x2c, 0x08, 0x4d, 0x03, 0x68, 0x51, 0x38, 0x41, 0x2a, 
+        0x26, 0x4a, 0x33, 0x67, 0xb2, 0x01, 0x1b, 0x33, 0x4d, 0x0d, 0xc5, 0xe5, 0x08, 0x29, 0x1c, 0x48, 
+        0x01, 0x68, 0x11, 0x69, 0x71, 0x40, 0x5f, 0x31, 0x60, 0x6f, 0x31, 0x69, 0x61, 0x3d, 0x05, 0x2d, 
+        0x04, 0xc5, 0x29, 0x08, 0x29, 0x91, 0x39, 0x81, 0x58, 0x61, 0x48, 0x71, 0x3d, 0x05, 0x2d, 0x04, 
+        0xc5, 0x28, 0x08, 0x4d, 0x03, 0x88, 0x91, 0x38, 0x81, 0x2a, 0x28, 0x4a, 0x33, 0x87, 0xb2, 0x01, 
+        0x1b, 0x33, 0x4d, 0x0d, 0x05, 0xe2, 0x08, 0x08, 0xa1, 0x29, 0x2c, 0xd8, 0xc1, 0xc8, 0xb1, 0x12, 
+        0xc1, 0x40, 0x0d, 0xf0, 0x37, 0x22, 0x02, 0x27, 0xa4, 0x11, 0x00, 0x15, 0x40, 0x31, 0x91, 0xfd, 
+        0x0c, 0x14, 0x28, 0x23, 0x00, 0x44, 0xa1, 0x40, 0x22, 0x20, 0x29, 0x23, 0x0d, 0xf0, 0x00, 0x00, 
+        0xfd, 0x7f, 0xfd, 0xff, 0x82, 0xae, 0x00, 0x72, 0xa1, 0x42, 0x31, 0xfb, 0xfe, 0xc0, 0x20, 0x00, 
+        0x62, 0x23, 0x59, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x63, 0x59, 0x51, 
+        0xf8, 0xff, 0x0c, 0x24, 0xc0, 0x20, 0x00, 0x22, 0x23, 0x58, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 
+        0xc0, 0x20, 0x00, 0x22, 0x63, 0x58, 0x0d, 0xf0, 0x00, 0x0a, 0xf2, 0x3f, 0x12, 0xc1, 0xe0, 0x09, 
+        0x11, 0x29, 0x01, 0xd9, 0x31, 0xe9, 0x41, 0xc9, 0x21, 0xed, 0x05, 0xc1, 0xeb, 0xfe, 0xd1, 0xfa, 
+        0xff, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x58, 0x49, 0x51, 0x17, 0xe0, 0x24, 0x2d, 0x03, 0x01, 0xf0, 
+        0xfc, 0xc0, 0x00, 0x00, 0x01, 0x74, 0xfd, 0x08, 0x00, 0x02, 0x20, 0x19, 0x28, 0x01, 0xc0, 0x00, 
+        0x00, 0x08, 0x51, 0xc0, 0x20, 0x00, 0x22, 0x2c, 0x58, 0x17, 0xe2, 0x13, 0x0c, 0x02, 0x06, 0x07, 
+        0x00, 0xc0, 0x20, 0x00, 0x52, 0x2d, 0x80, 0x40, 0x55, 0xc0, 0x57, 0xbe, 0xc3, 0xc6, 0x02, 0x00, 
+        0xc0, 0x20, 0x00, 0x62, 0x2d, 0x80, 0x00, 0x66, 0xc0, 0x67, 0xbe, 0xd6, 0x0c, 0x12, 0xc8, 0x21, 
+        0xd8, 0x31, 0xe8, 0x41, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xf7, 
+        0x51, 0xff, 0xff, 0x31, 0xd1, 0xfe, 0xc0, 0x20, 0x00, 0x42, 0x23, 0x42, 0x50, 0x44, 0x10, 0xc0, 
+        0x20, 0x00, 0x42, 0x63, 0x42, 0xc0, 0x20, 0x00, 0x29, 0xb3, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x08, 
+        0xff, 0xff, 0xf7, 0xff, 0x41, 0xc9, 0xfe, 0xc0, 0x20, 0x00, 0x71, 0xfc, 0xff, 0x28, 0xb4, 0xc0, 
+        0x20, 0x00, 0x62, 0x24, 0x42, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x64, 0x42, 0x51, 0xf8, 
+        0xff, 0xc0, 0x20, 0x00, 0x38, 0xb4, 0x50, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x39, 0xb4, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x01, 0x4b, 0xfd, 0x02, 0x20, 0x00, 0x02, 0x20, 0x11, 0x32, 
+        0xa0, 0x80, 0xc0, 0x00, 0x00, 0xc5, 0x1a, 0x03, 0x22, 0xa0, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0xf0, 0xef, 0xfe, 0x3f, 0x0c, 0xf1, 0xfe, 0x3f, 0xec, 0xef, 0xfe, 0x3f, 
+        0x60, 0xf1, 0xfe, 0x3f, 0x12, 0xc1, 0xc0, 0xd2, 0x61, 0x07, 0xf2, 0x61, 0x09, 0xe9, 0x81, 0xc9, 
+        0x61, 0xc1, 0x3c, 0xfd, 0x09, 0x51, 0x08, 0x4c, 0xe2, 0xcc, 0x51, 0x00, 0x02, 0x05, 0x56, 0x20, 
+        0x16, 0x08, 0x0c, 0x02, 0x20, 0x28, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x30, 0x0c, 0x12, 
+        0xc0, 0x00, 0x00, 0xd1, 0x39, 0xfe, 0x22, 0x1d, 0x01, 0x20, 0x20, 0xb4, 0xc5, 0x33, 0x02, 0x22, 
+        0x1d, 0x01, 0x32, 0xc1, 0x10, 0x45, 0x52, 0x03, 0x08, 0x0c, 0x08, 0x60, 0x0c, 0x02, 0xc0, 0x00, 
+        0x00, 0xd2, 0x01, 0x12, 0x0c, 0x0c, 0xf1, 0xe7, 0xff, 0xf9, 0xa1, 0x4b, 0xff, 0x9c, 0x6c, 0x26, 
+        0x1c, 0x0f, 0x26, 0x2c, 0x07, 0x66, 0x3c, 0x10, 0x0c, 0xed, 0xc6, 0x02, 0x00, 0x0c, 0xbd, 0x86, 
+        0x01, 0x00, 0x0c, 0x6d, 0x46, 0x00, 0x00, 0x0c, 0x1d, 0xf0, 0x7f, 0x20, 0x62, 0x21, 0x0a, 0x42, 
+        0xa0, 0x64, 0x31, 0xdd, 0xff, 0x80, 0x2d, 0x01, 0x52, 0x93, 0x75, 0x20, 0x28, 0x31, 0x32, 0x03, 
+        0x91, 0x49, 0x01, 0x0c, 0x04, 0x45, 0xf3, 0x02, 0x4c, 0x02, 0x2c, 0x83, 0x0c, 0x24, 0x0c, 0x05, 
+        0xd0, 0x6d, 0x90, 0x6a, 0x6e, 0x45, 0x5e, 0x04, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x4c, 0xac, 
+        0x01, 0xd3, 0xff, 0x0c, 0x0f, 0x0c, 0x3d, 0xd9, 0xb1, 0x0a, 0xef, 0x0c, 0xed, 0xc2, 0xa0, 0x00, 
+        0xf6, 0x6c, 0x22, 0xc0, 0x2c, 0x20, 0x32, 0xa0, 0x05, 0x02, 0x0e, 0x48, 0x09, 0xe1, 0x45, 0xb9, 
+        0x08, 0x3d, 0x02, 0x42, 0x0e, 0x57, 0x28, 0xe1, 0x01, 0xc9, 0xff, 0x20, 0x44, 0xc0, 0x40, 0x33, 
+        0x82, 0x3a, 0x22, 0xc6, 0x13, 0x00, 0x52, 0xa0, 0x0a, 0xc7, 0x35, 0x21, 0x32, 0xa0, 0x05, 0x22, 
+        0xcc, 0xfb, 0x42, 0x0e, 0x66, 0x52, 0x0e, 0x57, 0x52, 0x61, 0x0d, 0x50, 0x44, 0xc0, 0x40, 0x22, 
+        0x82, 0xc5, 0xaa, 0x08, 0x68, 0xd1, 0x01, 0xbd, 0xff, 0x6a, 0x22, 0xc6, 0x09, 0x00, 0x22, 0x0e, 
+        0x6f, 0x72, 0xa0, 0x0c, 0xc7, 0x37, 0x1e, 0xc0, 0x8c, 0xa0, 0x32, 0x0e, 0x66, 0x32, 0x61, 0x0c, 
+        0x82, 0xc8, 0xce, 0x30, 0x22, 0xc0, 0x20, 0x28, 0x82, 0x32, 0xa0, 0x16, 0x05, 0xa8, 0x08, 0x98, 
+        0xc1, 0x01, 0xb2, 0xff, 0x9a, 0x22, 0x0b, 0xdd, 0xc0, 0x3c, 0x90, 0x3a, 0x3f, 0x1b, 0xcc, 0xc0, 
+        0xc0, 0x74, 0x3a, 0x30, 0x22, 0x43, 0x48, 0x56, 0x5d, 0xf7, 0xc1, 0xee, 0xfc, 0x0c, 0xed, 0x48, 
+        0xb1, 0x1b, 0xff, 0xf0, 0xf0, 0x74, 0x0a, 0xef, 0x0b, 0x44, 0x49, 0xb1, 0x56, 0xd4, 0xf5, 0x08, 
+        0x0c, 0x02, 0x20, 0x32, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x31, 0xc0, 0x00, 0x00, 0x08, 
+        0x0c, 0x02, 0x20, 0x2f, 0xd1, 0xbb, 0xfb, 0xc0, 0x00, 0x00, 0x28, 0x4c, 0xd0, 0x22, 0x20, 0x29, 
+        0x4c, 0x46, 0x07, 0x00, 0x31, 0x9f, 0xff, 0x22, 0x03, 0x18, 0x32, 0x03, 0x18, 0x80, 0x22, 0x01, 
+        0x20, 0x28, 0x31, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0x30, 0x22, 0x90, 0x20, 0x2e, 0x80, 0x05, 
+        0x74, 0x02, 0xc2, 0x21, 0x06, 0xd2, 0x21, 0x07, 0xe8, 0x81, 0xf8, 0x91, 0x08, 0x51, 0x12, 0xc1, 
+        0x40, 0x0d, 0xf0, 0x00, 0x97, 0xf1, 0xfe, 0x3f, 0x32, 0xf0, 0xfe, 0x3f, 0x31, 0xf0, 0xfe, 0x3f, 
+        0x10, 0xf2, 0xfe, 0x3f, 0x79, 0xf1, 0xfe, 0x3f, 0x42, 0xa0, 0x00, 0x51, 0xfb, 0xff, 0x12, 0xc1, 
+        0xd0, 0xd9, 0x81, 0xf9, 0xa1, 0xc9, 0x71, 0x09, 0x61, 0xe9, 0x91, 0x02, 0xa0, 0x64, 0x62, 0xc5, 
+        0xbe, 0x72, 0xc5, 0xc2, 0xed, 0x03, 0xcd, 0x02, 0x31, 0xf3, 0xff, 0x80, 0x22, 0x01, 0x20, 0x28, 
+        0x31, 0x52, 0x95, 0xe2, 0x32, 0x03, 0x06, 0x09, 0x01, 0x05, 0xdd, 0x02, 0x31, 0xf0, 0xff, 0xc0, 
+        0x2c, 0x90, 0x3a, 0x22, 0x85, 0x6d, 0x02, 0x66, 0x6c, 0x02, 0xc5, 0x4e, 0x03, 0x0c, 0x0d, 0x21, 
+        0xec, 0xff, 0xf2, 0xc1, 0x10, 0xf0, 0x3d, 0x80, 0x20, 0x0d, 0x80, 0x02, 0x00, 0x00, 0x02, 0x43, 
+        0x00, 0xd2, 0xcd, 0x01, 0xd0, 0xd0, 0x74, 0x66, 0x6d, 0xea, 0x66, 0x1e, 0x26, 0x0c, 0x0e, 0x0c, 
+        0x0d, 0x22, 0xc1, 0x10, 0x05, 0x60, 0x03, 0xea, 0xe2, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0x00, 0xee, 
+        0x11, 0xe0, 0xe0, 0x31, 0x66, 0x4d, 0xe9, 0x2b, 0x0e, 0x5b, 0xee, 0x00, 0xe0, 0xb3, 0xe0, 0xe2, 
+        0x21, 0x46, 0x00, 0x00, 0x0c, 0x0e, 0x0c, 0x1d, 0x7c, 0xfb, 0x1b, 0x4d, 0xfa, 0x3d, 0x22, 0x03, 
+        0x00, 0x40, 0xd0, 0x74, 0xe0, 0x22, 0xc0, 0x22, 0x43, 0x00, 0x66, 0x6d, 0xec, 0xe0, 0x90, 0x74, 
+        0x26, 0x1c, 0x12, 0x66, 0x6c, 0x02, 0xc6, 0x20, 0x00, 0x62, 0xcc, 0xf5, 0x0c, 0x25, 0x0c, 0x32, 
+        0x60, 0x25, 0x83, 0x46, 0x00, 0x00, 0x0c, 0x02, 0xd0, 0xa2, 0x11, 0x61, 0x38, 0xfb, 0x00, 0x1a, 
+        0x40, 0xa2, 0xa0, 0xff, 0x00, 0xaa, 0xa1, 0x00, 0x99, 0xa1, 0xb0, 0xaa, 0x30, 0xc0, 0x20, 0x00, 
+        0x82, 0x26, 0xff, 0xa0, 0x88, 0x10, 0x90, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x71, 0xc2, 0xff, 0x82, 
+        0x66, 0xff, 0x72, 0x07, 0x55, 0x66, 0x17, 0x08, 0xe0, 0xb0, 0xf4, 0xc0, 0x20, 0x00, 0xb2, 0x66, 
+        0xff, 0x32, 0xc1, 0x10, 0x42, 0xa0, 0x06, 0x52, 0xa0, 0x1f, 0x81, 0xba, 0xff, 0x92, 0xa1, 0x38, 
+        0x20, 0x72, 0x90, 0x61, 0x91, 0xfd, 0x22, 0xa0, 0x40, 0x62, 0x16, 0x01, 0x99, 0x01, 0x82, 0x08, 
+        0x61, 0x89, 0x11, 0x81, 0xb8, 0xff, 0xf0, 0x77, 0x11, 0x8a, 0x77, 0x45, 0x56, 0x04, 0xc8, 0x71, 
+        0xd8, 0x81, 0xe8, 0x91, 0xf8, 0xa1, 0x08, 0x61, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x0c, 0x12, 0x46, 
+        0xe1, 0xff, 0x00, 0x00, 0x02, 0xf1, 0xfe, 0x3f, 0x4b, 0xf1, 0xfe, 0x3f, 0xc6, 0xf1, 0xfe, 0x3f, 
+        0x20, 0x42, 0xa0, 0x12, 0xc1, 0xc0, 0x09, 0x41, 0x39, 0xd1, 0xc9, 0x51, 0xe9, 0x71, 0xd9, 0x61, 
+        0xf9, 0x81, 0x42, 0xc4, 0xc9, 0x49, 0x31, 0x0c, 0x0f, 0xd1, 0xf6, 0xff, 0x0c, 0x6e, 0xcd, 0x02, 
+        0x32, 0xc2, 0xfa, 0x39, 0x91, 0x0b, 0x22, 0x29, 0xc1, 0xf6, 0x7c, 0x2a, 0x32, 0xa0, 0x05, 0x22, 
+        0x21, 0x0c, 0x42, 0x0d, 0x7d, 0x52, 0x0d, 0x77, 0x52, 0x61, 0x0b, 0x80, 0x44, 0x01, 0x80, 0x55, 
+        0x01, 0x50, 0x58, 0x31, 0x40, 0x48, 0x31, 0x50, 0x44, 0xc0, 0x40, 0x22, 0x82, 0x05, 0x85, 0x08, 
+        0x08, 0xb1, 0x0a, 0x02, 0x86, 0x16, 0x00, 0xf6, 0xac, 0x2a, 0x32, 0xa0, 0x05, 0x22, 0x21, 0x09, 
+        0x42, 0x0d, 0x83, 0x52, 0x0d, 0x7d, 0x52, 0x61, 0x0a, 0x80, 0x44, 0x01, 0x80, 0x55, 0x01, 0x50, 
+        0x58, 0x31, 0x40, 0x48, 0x31, 0x50, 0x44, 0xc0, 0x40, 0x22, 0x82, 0x45, 0x82, 0x08, 0x08, 0xa1, 
+        0x0a, 0x02, 0x06, 0x0b, 0x00, 0x02, 0x0d, 0x89, 0x22, 0xa0, 0x0d, 0x80, 0x00, 0x01, 0x00, 0x08, 
+        0x31, 0xc7, 0x32, 0x1d, 0x32, 0xa0, 0x16, 0x22, 0x21, 0x03, 0x42, 0x0d, 0x83, 0x49, 0x21, 0x80, 
+        0x44, 0x01, 0x40, 0x48, 0x31, 0x40, 0x40, 0xc0, 0x40, 0x22, 0x82, 0x45, 0x7f, 0x08, 0x08, 0x21, 
+        0x0a, 0x02, 0xd2, 0xcd, 0x01, 0x22, 0x21, 0x0d, 0xe2, 0xce, 0xff, 0x2a, 0x2f, 0x02, 0x42, 0x00, 
+        0x1b, 0xff, 0x56, 0x3e, 0xf6, 0xd1, 0xcc, 0xff, 0x32, 0x0d, 0xa0, 0x42, 0x0d, 0xae, 0x26, 0x13, 
+        0x28, 0x26, 0x14, 0x25, 0x0c, 0x05, 0xe2, 0xaf, 0x80, 0x6d, 0x0e, 0xe2, 0x4d, 0x4d, 0x52, 0x4d, 
+        0x4e, 0x21, 0xc6, 0xff, 0x0c, 0xd3, 0x48, 0xd1, 0x05, 0x57, 0x03, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 
+        0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 0x52, 0x0d, 0x97, 0xf2, 0x0d, 0x9b, 
+        0xdc, 0x55, 0xb6, 0x3c, 0x02, 0x86, 0x43, 0x00, 0x01, 0xbb, 0xff, 0x02, 0x00, 0x79, 0x0c, 0x15, 
+        0x80, 0xe0, 0x01, 0xe0, 0xe8, 0x31, 0xc6, 0xef, 0xff, 0xc7, 0x3f, 0x57, 0x01, 0xb6, 0xff, 0xe2, 
+        0x0d, 0x99, 0x00, 0xee, 0x80, 0xe2, 0x0e, 0x77, 0x02, 0x0d, 0x9c, 0x80, 0xee, 0x01, 0xe0, 0xe8, 
+        0x31, 0x66, 0x10, 0x3a, 0x32, 0xa0, 0x05, 0x22, 0x0d, 0x34, 0xc2, 0x0d, 0x2e, 0x80, 0x22, 0x01, 
+        0x80, 0xcc, 0x01, 0xc0, 0xc8, 0x31, 0x20, 0x28, 0x31, 0xc0, 0x22, 0xc0, 0x20, 0x2f, 0x82, 0x05, 
+        0x75, 0x08, 0x2a, 0x3c, 0x80, 0x33, 0x01, 0x28, 0xc1, 0x30, 0x38, 0x31, 0xe0, 0x33, 0xc0, 0x30, 
+        0x22, 0x82, 0x3d, 0x0f, 0x85, 0x73, 0x08, 0x2a, 0xee, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x0c, 
+        0x15, 0x06, 0xd9, 0xff, 0x22, 0x0d, 0x9a, 0x02, 0xa0, 0x0f, 0x20, 0x00, 0xc0, 0x07, 0x2c, 0x48, 
+        0x01, 0x9d, 0xff, 0xe2, 0x0d, 0x98, 0x00, 0xee, 0x80, 0xe2, 0x0e, 0x89, 0x32, 0x0d, 0x9c, 0x80, 
+        0xee, 0x01, 0xe0, 0xe8, 0x31, 0x66, 0x13, 0xd6, 0x02, 0x0d, 0x3a, 0x80, 0x00, 0x01, 0x00, 0x08, 
+        0x31, 0x02, 0x61, 0x01, 0xf6, 0xac, 0x29, 0x22, 0x0d, 0x34, 0x0c, 0x83, 0x80, 0x22, 0x01, 0xf0, 
+        0x33, 0xc0, 0x20, 0x28, 0x31, 0x29, 0x01, 0x20, 0x20, 0xc0, 0x30, 0x22, 0x82, 0x0c, 0x53, 0x05, 
+        0x6e, 0x08, 0x08, 0x01, 0x2a, 0x00, 0x06, 0x0b, 0x00, 0x0c, 0x05, 0xe2, 0xaf, 0x80, 0xc6, 0xc1, 
+        0xff, 0x32, 0xa0, 0x16, 0x21, 0xc7, 0xfe, 0x42, 0xa0, 0x03, 0x22, 0x02, 0x2b, 0xf0, 0x44, 0xc0, 
+        0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0x00, 0x22, 0xc0, 0x40, 0x22, 0x82, 0x20, 0x22, 0xa0, 0x05, 
+        0x6b, 0x08, 0x08, 0x11, 0x2a, 0x00, 0x0c, 0xe3, 0x80, 0x20, 0x01, 0x20, 0x28, 0x31, 0xc0, 0x33, 
+        0xc0, 0xe0, 0x22, 0xc0, 0x30, 0x22, 0x82, 0x3d, 0x0f, 0x45, 0x69, 0x08, 0x2a, 0xee, 0x80, 0xee, 
+        0x01, 0xe0, 0xe8, 0x31, 0xc6, 0xd5, 0xff, 0xb6, 0x9c, 0x08, 0x01, 0x76, 0xff, 0x02, 0x00, 0x85, 
+        0x86, 0xba, 0xff, 0xe2, 0xaf, 0x80, 0x0c, 0x05, 0x46, 0xab, 0xff, 0x00, 0x00, 0x00, 0x10, 0x00, 
+        0x12, 0xc1, 0xd0, 0xd2, 0x61, 0x06, 0x22, 0x61, 0x09, 0xc9, 0x51, 0x09, 0x41, 0xf9, 0x81, 0xe9, 
+        0x71, 0xe1, 0xec, 0xfb, 0xfd, 0x02, 0x08, 0x4e, 0xc1, 0xf0, 0xfc, 0x00, 0x04, 0x05, 0x56, 0x00, 
+        0x08, 0x08, 0x0e, 0x02, 0x20, 0x28, 0xc0, 0x00, 0x00, 0x08, 0x0e, 0x02, 0x20, 0x30, 0x0c, 0x12, 
+        0xc0, 0x00, 0x00, 0x22, 0x1c, 0x01, 0x20, 0x20, 0xb4, 0x05, 0xe0, 0x01, 0x22, 0x1c, 0x01, 0x3d, 
+        0x01, 0x85, 0xfe, 0x02, 0x08, 0x0e, 0x08, 0x60, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0xd2, 0x01, 0x02, 
+        0x0c, 0x0c, 0x9c, 0x6c, 0x26, 0x1c, 0x0f, 0x26, 0x2c, 0x07, 0x66, 0x3c, 0x10, 0x0c, 0xed, 0xc6, 
+        0x02, 0x00, 0x0c, 0xbd, 0x86, 0x01, 0x00, 0x0c, 0x1d, 0x46, 0x00, 0x00, 0x0c, 0x6d, 0x3d, 0x0f, 
+        0x2d, 0x0d, 0x45, 0xc1, 0xff, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x4c, 0xd4, 0x08, 0x0e, 0x02, 
+        0x20, 0x32, 0xc0, 0x00, 0x00, 0x08, 0x0e, 0x02, 0x20, 0x31, 0xc0, 0x00, 0x00, 0x08, 0x0e, 0x02, 
+        0x20, 0x2f, 0xc1, 0xda, 0xff, 0xc0, 0x00, 0x00, 0x28, 0x4e, 0xc0, 0x22, 0x20, 0x29, 0x4e, 0x46, 
+        0x04, 0x00, 0x22, 0x1c, 0x01, 0x10, 0x31, 0x20, 0x05, 0xf8, 0x02, 0x22, 0x1c, 0x01, 0x10, 0x31, 
+        0x20, 0xc5, 0xed, 0x02, 0x0c, 0xe2, 0x8b, 0x31, 0x45, 0xd1, 0xff, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 
+        0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x00, 0x00, 0x21, 0x2f, 0xfd, 0xc0, 
+        0x20, 0x00, 0x22, 0x22, 0x59, 0x20, 0x24, 0xb5, 0x1b, 0x22, 0x20, 0x21, 0x41, 0x22, 0xd2, 0xf8, 
+        0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x0d, 0xf0, 0x41, 0x28, 0xfd, 0x1b, 0x92, 0x2b, 0x82, 0x90, 
+        0x89, 0xb3, 0x80, 0x81, 0x21, 0x82, 0xd8, 0x02, 0x92, 0xae, 0x00, 0x80, 0x80, 0x84, 0xc0, 0x20, 
+        0x00, 0x72, 0x24, 0x59, 0x90, 0x77, 0x10, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x64, 0x59, 
+        0x61, 0x20, 0xfe, 0x0c, 0x25, 0xc0, 0x20, 0x00, 0x32, 0x24, 0x58, 0x60, 0x33, 0x10, 0x50, 0x33, 
+        0x20, 0xc0, 0x20, 0x00, 0x32, 0x64, 0x58, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xff, 0xff, 
+        0x28, 0xf3, 0xfe, 0x3f, 0x71, 0xfe, 0xff, 0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x09, 0x11, 0x62, 0xa2, 
+        0x00, 0x41, 0x11, 0xfd, 0x01, 0xfb, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x24, 0x59, 0x70, 0x55, 0x10, 
+        0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x64, 0x59, 0x52, 0x10, 0x00, 0xc0, 0x20, 0x00, 0x42, 
+        0x24, 0x58, 0x29, 0x01, 0x17, 0x64, 0x02, 0xb6, 0x95, 0x5f, 0xc1, 0x96, 0xfb, 0x39, 0x31, 0xb6, 
+        0x95, 0x05, 0x02, 0xae, 0xd4, 0x86, 0x05, 0x00, 0x08, 0x0c, 0x08, 0xa0, 0xc0, 0x00, 0x00, 0x38, 
+        0x31, 0x02, 0xae, 0xd4, 0x27, 0x20, 0x01, 0x0d, 0x02, 0x00, 0x00, 0x11, 0x00, 0x00, 0x31, 0x22, 
+        0x9c, 0xcb, 0x27, 0x20, 0x42, 0x20, 0x42, 0x90, 0x4a, 0x00, 0x42, 0xc0, 0xfe, 0x1b, 0x00, 0x40, 
+        0x04, 0xb3, 0x00, 0x02, 0x21, 0x00, 0x20, 0x11, 0x20, 0x20, 0x31, 0x22, 0x5c, 0xcb, 0x8c, 0x63, 
+        0x08, 0x0c, 0x02, 0x20, 0x16, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x19, 0x28, 0x01, 0xc0, 
+        0x00, 0x00, 0x01, 0xdb, 0xff, 0x0c, 0x02, 0x46, 0x00, 0x00, 0x1b, 0x25, 0xc8, 0x21, 0x22, 0x50, 
+        0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0a, 0x02, 0x1b, 0x40, 0x2b, 0x00, 0x40, 0x04, 
+        0xb3, 0x00, 0x01, 0x21, 0x46, 0xef, 0xff, 0x00, 0x18, 0xf2, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xbf, 
+        0x00, 0x00, 0x20, 0x00, 0x12, 0xc1, 0xc0, 0xc9, 0x61, 0xd9, 0x71, 0xe9, 0x81, 0xf9, 0x91, 0x09, 
+        0x51, 0x92, 0x21, 0x10, 0x39, 0xe1, 0x38, 0x09, 0x01, 0x6f, 0xfb, 0x30, 0x35, 0x05, 0x56, 0x83, 
+        0x16, 0x81, 0xf5, 0xff, 0xe2, 0xae, 0xac, 0x0c, 0x0b, 0xb9, 0xa1, 0xc8, 0xa1, 0x1b, 0xdc, 0x80, 
+        0xfc, 0x90, 0xe2, 0x5f, 0x00, 0xd0, 0xc0, 0x74, 0xc9, 0xa1, 0x66, 0x4c, 0xed, 0xb2, 0xaf, 0xd8, 
+        0xa2, 0xae, 0x7c, 0x69, 0x01, 0x60, 0xab, 0x93, 0xa2, 0x50, 0xcb, 0x7c, 0xed, 0xa1, 0xd2, 0xfc, 
+        0xc0, 0x20, 0x00, 0x78, 0xba, 0x79, 0x21, 0xc0, 0x20, 0x00, 0x32, 0x2a, 0xc8, 0x39, 0x31, 0xc0, 
+        0x20, 0x00, 0xf2, 0x2a, 0xd0, 0xf9, 0x41, 0xc0, 0x20, 0x00, 0xc8, 0xba, 0xd0, 0xcc, 0x10, 0xc0, 
+        0x20, 0x00, 0xc9, 0xba, 0xb1, 0xe2, 0xff, 0xc0, 0x20, 0x00, 0x72, 0x2a, 0xc8, 0xb0, 0x77, 0x10, 
+        0xc0, 0x20, 0x00, 0x72, 0x6a, 0xc8, 0xc1, 0xd4, 0xfd, 0x99, 0x11, 0x29, 0xd1, 0x49, 0xc1, 0x59, 
+        0xb1, 0x0c, 0x03, 0x39, 0xa1, 0xc0, 0x20, 0x00, 0xf2, 0x2c, 0x80, 0x42, 0x21, 0x0a, 0x22, 0xa0, 
+        0x0e, 0x40, 0x34, 0xa0, 0x42, 0xc4, 0xfd, 0x32, 0xc3, 0x01, 0x40, 0x23, 0x93, 0x80, 0x22, 0x01, 
+        0x20, 0x28, 0x31, 0x05, 0x9b, 0x02, 0x48, 0xe1, 0x01, 0xd0, 0xff, 0xbc, 0xa4, 0xd8, 0xa1, 0x0c, 
+        0x0c, 0x00, 0xdd, 0x90, 0x4d, 0x0f, 0x28, 0xd1, 0x38, 0xc1, 0x58, 0xb1, 0xc5, 0x70, 0xff, 0xec, 
+        0x32, 0x01, 0x40, 0xfb, 0x08, 0x00, 0x08, 0xa0, 0xc0, 0x00, 0x00, 0x02, 0x9d, 0x00, 0x07, 0xa2, 
+        0x04, 0x0d, 0x02, 0x22, 0x5d, 0x00, 0x28, 0xe1, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x07, 0xae, 0x02, 
+        0xe2, 0x5d, 0x00, 0xc7, 0x92, 0xcd, 0xc1, 0xb8, 0xfd, 0xc0, 0x20, 0x00, 0x21, 0xa7, 0xfc, 0x08, 
+        0xd2, 0x7c, 0xe3, 0x30, 0x00, 0x10, 0xc0, 0x20, 0x00, 0xd8, 0xa1, 0x09, 0xd2, 0x1b, 0xfd, 0xf0, 
+        0xd0, 0x74, 0xd9, 0xa1, 0x26, 0x4d, 0x02, 0x86, 0xde, 0xff, 0xc0, 0x20, 0x00, 0x61, 0x9e, 0xfc, 
+        0x88, 0x21, 0x89, 0xb6, 0xc0, 0x20, 0x00, 0x78, 0x31, 0x72, 0x66, 0xc8, 0xc0, 0x20, 0x00, 0x58, 
+        0x41, 0x48, 0x01, 0x52, 0x66, 0xd0, 0xbc, 0x84, 0x31, 0xb0, 0xff, 0xc1, 0x26, 0xfb, 0x0c, 0x09, 
+        0x22, 0x9c, 0xcb, 0x99, 0xa1, 0x00, 0xa2, 0x11, 0xa0, 0xa0, 0x31, 0x08, 0xa1, 0x48, 0xa1, 0x30, 
+        0x00, 0x90, 0x1b, 0x54, 0x50, 0x40, 0x74, 0x02, 0x90, 0x00, 0x49, 0xa1, 0xa7, 0xa0, 0x04, 0x2d, 
+        0x00, 0x02, 0x5c, 0xcb, 0x00, 0xa2, 0x11, 0x66, 0x44, 0xdd, 0x08, 0x0c, 0x02, 0x20, 0x16, 0xc0, 
+        0x00, 0x00, 0x21, 0x18, 0xfb, 0x22, 0x92, 0xcb, 0xe7, 0xa2, 0x19, 0x48, 0x11, 0x51, 0xa0, 0xff, 
+        0x38, 0x04, 0x50, 0x33, 0x20, 0x39, 0x04, 0x86, 0x02, 0x00, 0x68, 0x00, 0x62, 0x26, 0x16, 0x22, 
+        0x90, 0xcb, 0xc0, 0x06, 0x00, 0xc8, 0x61, 0xd8, 0x71, 0xe8, 0x81, 0xf8, 0x91, 0x08, 0x51, 0x12, 
+        0xc1, 0x40, 0x0d, 0xf0, 0x4a, 0xf1, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x03, 0x10, 0x31, 
+        0x20, 0x20, 0xc2, 0x20, 0x21, 0xfc, 0xff, 0x09, 0x21, 0x22, 0x02, 0x2e, 0x05, 0xa2, 0xff, 0x01, 
+        0xf9, 0xff, 0x0c, 0x02, 0x5d, 0x01, 0x1b, 0x62, 0x5a, 0x42, 0x32, 0x04, 0x00, 0x60, 0x20, 0x74, 
+        0xca, 0x33, 0x32, 0x44, 0x00, 0x66, 0x62, 0xed, 0x21, 0x81, 0xfe, 0x0c, 0xd3, 0x4d, 0x01, 0x62, 
+        0x00, 0x4e, 0x52, 0x00, 0x4f, 0x80, 0x66, 0x01, 0x60, 0x68, 0x31, 0x05, 0x05, 0x03, 0xc8, 0x31, 
+        0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x94, 0x83, 0xfe, 0x3f, 0x7d, 0x02, 0x12, 0xc1, 
+        0xe0, 0x39, 0x01, 0x21, 0xfd, 0xff, 0x09, 0x11, 0xc9, 0x21, 0xd9, 0x31, 0xcd, 0x05, 0xdd, 0x04, 
+        0x79, 0x41, 0x01, 0x1f, 0xfb, 0xc0, 0x00, 0x00, 0x08, 0x41, 0xc0, 0x20, 0x00, 0x28, 0x0d, 0xc7, 
+        0x92, 0xf7, 0x2d, 0x00, 0x01, 0x67, 0xfa, 0xc0, 0x00, 0x00, 0x01, 0xea, 0xfa, 0x08, 0x00, 0x28, 
+        0x01, 0x02, 0x20, 0x19, 0x20, 0x20, 0x74, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0xd8, 0x31, 0x08, 0x11, 
+        0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x90, 0x80, 0xfe, 0x3f, 0x32, 0xf1, 0xfe, 0x3f, 
+        0xff, 0x03, 0xfc, 0xff, 0x42, 0xa0, 0x00, 0x12, 0xc1, 0xe0, 0xe2, 0x61, 0x05, 0xd2, 0x61, 0x04, 
+        0x09, 0x21, 0xc9, 0x31, 0x01, 0xfa, 0xff, 0xcd, 0x02, 0xdd, 0x03, 0x0c, 0x22, 0x31, 0xf6, 0xff, 
+        0xe2, 0x00, 0x7d, 0x3a, 0x44, 0x80, 0xee, 0x01, 0x3a, 0x22, 0x42, 0x14, 0x00, 0x42, 0x51, 0x00, 
+        0x22, 0x02, 0x00, 0xe0, 0xe8, 0x31, 0x22, 0x41, 0x02, 0x0c, 0xd2, 0xe6, 0x7c, 0x20, 0x0c, 0x53, 
+        0x4d, 0x00, 0x42, 0x04, 0x7c, 0x0b, 0x2c, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x49, 0x11, 0x40, 
+        0x4e, 0xc0, 0x40, 0x22, 0x82, 0x85, 0x1d, 0x08, 0xe8, 0x11, 0x2a, 0xee, 0x06, 0x08, 0x00, 0x32, 
+        0x00, 0x7e, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0xe0, 0x33, 0xc0, 0xc7, 0xa2, 0x02, 0x46, 0x42, 
+        0x00, 0x22, 0xcc, 0xfa, 0x20, 0x23, 0x82, 0x32, 0xa0, 0x05, 0x45, 0x1b, 0x08, 0x20, 0xee, 0x80, 
+        0x66, 0x1d, 0x0b, 0xd2, 0xaf, 0xfa, 0xd2, 0x41, 0x00, 0xd2, 0x41, 0x02, 0xc6, 0x08, 0x00, 0x32, 
+        0xcd, 0xfe, 0x56, 0x93, 0x0b, 0x01, 0xd9, 0xff, 0x32, 0x00, 0x7f, 0x32, 0x41, 0x00, 0x22, 0x00, 
+        0x80, 0x22, 0x41, 0x01, 0x02, 0x00, 0x81, 0x02, 0x41, 0x02, 0xd2, 0x01, 0x01, 0x80, 0xdd, 0x01, 
+        0xd0, 0xd8, 0x31, 0xe6, 0x7c, 0x2c, 0x32, 0x01, 0x00, 0x22, 0xcc, 0xff, 0x80, 0x33, 0x01, 0x30, 
+        0x38, 0x31, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0x30, 0x3d, 0xc0, 0x30, 0x22, 0x82, 0x32, 0xa0, 
+        0x05, 0xc5, 0x15, 0x08, 0x02, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x08, 0x31, 0x20, 0x00, 0x80, 
+        0x06, 0x08, 0x00, 0x02, 0x01, 0x02, 0x22, 0xa0, 0x0d, 0x80, 0x00, 0x01, 0x00, 0x08, 0x31, 0xd0, 
+        0x00, 0xc0, 0xc7, 0x22, 0x74, 0x32, 0xa0, 0x05, 0x22, 0xcc, 0xfa, 0x20, 0x20, 0x82, 0x05, 0x13, 
+        0x08, 0xd0, 0x02, 0x80, 0xa1, 0xbf, 0xff, 0x0a, 0x9e, 0x41, 0x0f, 0xfc, 0x90, 0x90, 0x74, 0x60, 
+        0x99, 0x11, 0xc0, 0x20, 0x00, 0x82, 0x24, 0xda, 0xa0, 0x88, 0x10, 0x90, 0x88, 0x20, 0xc0, 0x20, 
+        0x00, 0x82, 0x64, 0xda, 0x0c, 0x17, 0xc0, 0x20, 0x00, 0x68, 0xd4, 0x70, 0x66, 0x20, 0xc0, 0x20, 
+        0x00, 0x69, 0xd4, 0x7c, 0xe5, 0xc0, 0x20, 0x00, 0x38, 0xd4, 0x50, 0x33, 0x10, 0xc0, 0x20, 0x00, 
+        0x39, 0xd4, 0xc8, 0x31, 0xd8, 0x41, 0xe8, 0x51, 0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0xa2, 
+        0xcd, 0xfd, 0x56, 0x4a, 0xf5, 0x01, 0xa9, 0xff, 0x32, 0x00, 0x82, 0x32, 0x41, 0x00, 0x22, 0x00, 
+        0x83, 0x22, 0x41, 0x01, 0x02, 0x00, 0x84, 0x06, 0xcf, 0xff, 0x0c, 0x53, 0x22, 0xcc, 0xfe, 0x20, 
+        0x20, 0x82, 0xc5, 0x0b, 0x08, 0x06, 0xe2, 0xff, 0x00, 0x00, 0x00, 0x22, 0xcc, 0xfe, 0x20, 0x23, 
+        0x82, 0x0c, 0x53, 0xc5, 0x0a, 0x08, 0xc6, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x02, 
+        0x61, 0x03, 0x01, 0x7c, 0xfa, 0x02, 0x20, 0x04, 0x29, 0x21, 0x27, 0x70, 0x0f, 0x31, 0x79, 0xfa, 
+        0x20, 0x22, 0x90, 0x32, 0xc3, 0x51, 0x3a, 0x22, 0x45, 0xdb, 0x01, 0x28, 0x21, 0x41, 0xf6, 0xfc, 
+        0xc0, 0x20, 0x00, 0x42, 0x24, 0x9c, 0x17, 0x64, 0x22, 0x20, 0x20, 0x74, 0x3d, 0x01, 0x05, 0x7d, 
+        0xff, 0x0c, 0x02, 0x85, 0x5a, 0x00, 0x21, 0x6f, 0xfa, 0x08, 0x02, 0x02, 0x20, 0x16, 0x22, 0x92, 
+        0xcb, 0xc0, 0x00, 0x00, 0x1c, 0xe2, 0x01, 0xe6, 0xf9, 0xc0, 0x00, 0x00, 0x08, 0x31, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x3e, 0xf1, 0xfe, 0x3f, 0x94, 0x80, 0xfe, 0x3f, 0xc0, 0x5d, 0x00, 0x00, 
+        0x00, 0x00, 0x24, 0x40, 0x99, 0x99, 0x49, 0x40, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe9, 0x40, 
+        0x00, 0x96, 0x00, 0x60, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x12, 0xc1, 0xb0, 0xd9, 
+        0xc1, 0xf9, 0xe1, 0x29, 0x71, 0xc9, 0xb1, 0xe9, 0xd1, 0xe1, 0xf2, 0xff, 0x09, 0xa1, 0x02, 0x0e, 
+        0x5f, 0xcd, 0x03, 0xcc, 0x30, 0x2c, 0x8d, 0xc6, 0x04, 0x00, 0x66, 0x10, 0x04, 0x1c, 0xad, 0xc6, 
+        0x02, 0x00, 0x32, 0xc0, 0xfe, 0x22, 0xa0, 0x18, 0xd2, 0xa0, 0x28, 0x30, 0xd2, 0x83, 0x2d, 0x0c, 
+        0x3d, 0x0d, 0x45, 0x05, 0x08, 0xe6, 0x92, 0x17, 0x2d, 0x0c, 0x3d, 0x0d, 0x05, 0xfe, 0x07, 0x20, 
+        0x0d, 0x82, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0xa0, 0xf0, 0x20, 0x11, 0x29, 0x61, 0xc6, 0x08, 0x00, 
+        0x20, 0x4d, 0xc0, 0xe6, 0x94, 0x17, 0xc0, 0x2c, 0x20, 0xd0, 0x3d, 0x20, 0x05, 0xfc, 0x07, 0x02, 
+        0xc2, 0x01, 0x00, 0x0d, 0x82, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0xa0, 0x46, 0xf6, 0xff, 0x22, 0xa0, 
+        0x00, 0x22, 0x61, 0x06, 0x32, 0x0e, 0x7b, 0x22, 0x0e, 0x9e, 0x16, 0x83, 0x06, 0x32, 0x61, 0x05, 
+        0xf2, 0x0e, 0x7a, 0x80, 0x22, 0x11, 0x2a, 0xff, 0x16, 0xaf, 0x05, 0x2d, 0x03, 0x7c, 0x6d, 0xc0, 
+        0xdd, 0x82, 0xc0, 0x22, 0xc1, 0x30, 0x33, 0xa0, 0xf0, 0x33, 0x11, 0x29, 0xf1, 0x32, 0x61, 0x12, 
+        0x3d, 0x0f, 0x45, 0xfe, 0x07, 0x02, 0x21, 0x12, 0x48, 0xf1, 0x07, 0x22, 0x02, 0x06, 0x4a, 0x00, 
+        0x2d, 0x04, 0x3d, 0x0f, 0x85, 0xf6, 0x07, 0x85, 0x0b, 0x08, 0x29, 0x21, 0x2d, 0x0f, 0x05, 0x0b, 
+        0x08, 0xfd, 0x02, 0x28, 0x51, 0x05, 0x0a, 0x08, 0x3d, 0x02, 0x2d, 0x0f, 0x05, 0xde, 0x06, 0x3d, 
+        0x02, 0x28, 0x21, 0x85, 0xc7, 0x06, 0xf1, 0xc0, 0xff, 0x38, 0x0f, 0x05, 0xc7, 0x06, 0xc5, 0xe8, 
+        0x06, 0x2a, 0xfd, 0x06, 0x02, 0x00, 0xf2, 0xa0, 0x00, 0xd2, 0xaf, 0xf6, 0xc0, 0xdd, 0x82, 0x02, 
+        0x0e, 0x9a, 0xf2, 0x61, 0x13, 0x16, 0x70, 0x06, 0x02, 0x61, 0x04, 0x22, 0x0e, 0x9f, 0xf2, 0x0e, 
+        0x99, 0x80, 0x22, 0x11, 0x2a, 0xff, 0x16, 0x6f, 0x05, 0x3d, 0x0f, 0xc0, 0x20, 0xc1, 0x22, 0x61, 
+        0x10, 0x00, 0xc0, 0xa0, 0xf0, 0xcc, 0x11, 0x05, 0xf7, 0x07, 0x02, 0x21, 0x10, 0xc7, 0x22, 0x02, 
+        0x86, 0x3d, 0x00, 0x3d, 0x0f, 0x2d, 0x00, 0x85, 0xef, 0x07, 0x45, 0x04, 0x08, 0x29, 0x31, 0xc8, 
+        0x41, 0x2d, 0x0f, 0xc5, 0x03, 0x08, 0xfd, 0x02, 0x2d, 0x0c, 0xc5, 0x02, 0x08, 0x3d, 0x02, 0xc8, 
+        0x31, 0x2d, 0x0f, 0xc5, 0xd6, 0x06, 0x3d, 0x02, 0x2d, 0x0c, 0x05, 0xc0, 0x06, 0x31, 0xa2, 0xff, 
+        0x38, 0x03, 0x85, 0xbf, 0x06, 0x45, 0xe1, 0x06, 0xf2, 0x21, 0x13, 0x2a, 0x3d, 0x06, 0x01, 0x00, 
+        0xf2, 0x21, 0x13, 0x0c, 0x03, 0x32, 0x61, 0x11, 0x21, 0x9d, 0xff, 0xc2, 0x1e, 0x50, 0x01, 0x01, 
+        0xfa, 0xca, 0xcd, 0x08, 0x00, 0x2a, 0xcc, 0x08, 0x00, 0x2d, 0x0c, 0xc0, 0x00, 0x00, 0x01, 0x97, 
+        0xff, 0x41, 0xfc, 0xf9, 0x0c, 0x03, 0x52, 0xa0, 0x64, 0x57, 0x22, 0x01, 0xcd, 0x03, 0x68, 0x04, 
+        0x22, 0x1e, 0x51, 0x68, 0x06, 0x2a, 0xdd, 0x0a, 0xdd, 0x2d, 0x0d, 0xc0, 0x06, 0x00, 0x32, 0x21, 
+        0x11, 0x01, 0xf4, 0xf9, 0x48, 0x71, 0x72, 0x10, 0xed, 0x0b, 0x44, 0x00, 0x04, 0x40, 0x70, 0x70, 
+        0xb1, 0x07, 0x67, 0x02, 0x56, 0x4f, 0x11, 0x52, 0x10, 0xfd, 0x00, 0x04, 0x40, 0x50, 0x50, 0xb1, 
+        0x07, 0x65, 0x02, 0x56, 0x73, 0x11, 0x56, 0xfc, 0x08, 0x62, 0xa0, 0x64, 0x67, 0x22, 0x01, 0x0c, 
+        0x0d, 0xc8, 0x61, 0xd0, 0xcd, 0x93, 0xc6, 0x1f, 0x00, 0x20, 0x7f, 0xc0, 0x07, 0x27, 0x02, 0x86, 
+        0x3b, 0x00, 0x2d, 0x04, 0x3d, 0x0f, 0x85, 0xe3, 0x07, 0x1b, 0x22, 0x45, 0xf8, 0x07, 0x29, 0x01, 
+        0x2d, 0x0f, 0xc5, 0xf7, 0x07, 0x29, 0x11, 0x28, 0x51, 0xc5, 0xf6, 0x07, 0x3d, 0x02, 0xf8, 0x01, 
+        0x28, 0x11, 0xc5, 0xca, 0x06, 0x3d, 0x02, 0x2d, 0x0f, 0x05, 0xb4, 0x06, 0x31, 0x73, 0xff, 0x38, 
+        0x03, 0x85, 0xb3, 0x06, 0x45, 0xd5, 0x06, 0x86, 0xb1, 0xff, 0x20, 0x4f, 0xc0, 0xc7, 0x24, 0x02, 
+        0x86, 0x2c, 0x00, 0x3d, 0x0f, 0x2d, 0x00, 0x85, 0xdf, 0x07, 0x1b, 0x22, 0x05, 0xf4, 0x07, 0xcd, 
+        0x02, 0x2d, 0x0f, 0xc5, 0xf3, 0x07, 0xfd, 0x02, 0x28, 0x41, 0xc5, 0xf2, 0x07, 0x3d, 0x02, 0x2d, 
+        0x0f, 0xc5, 0xc6, 0x06, 0x3d, 0x02, 0x2d, 0x0c, 0x05, 0xb0, 0x06, 0x31, 0x63, 0xff, 0x38, 0x03, 
+        0x85, 0xaf, 0x06, 0x85, 0xd1, 0x06, 0x86, 0xbf, 0xff, 0xe1, 0x61, 0xff, 0xd2, 0xa0, 0x00, 0x2d, 
+        0x0c, 0x05, 0xf5, 0x07, 0x29, 0x91, 0x39, 0x81, 0x51, 0x5f, 0xff, 0x41, 0x5f, 0xff, 0x05, 0xe7, 
+        0x06, 0x5d, 0x0e, 0x4d, 0x0d, 0xc5, 0x10, 0x07, 0xc5, 0x22, 0x07, 0x38, 0x81, 0x51, 0x5b, 0xff, 
+        0xfd, 0x02, 0x41, 0x59, 0xff, 0x28, 0x91, 0x85, 0xe5, 0x06, 0x4d, 0x0d, 0x5d, 0x0e, 0x45, 0x0f, 
+        0x07, 0xd1, 0x57, 0xff, 0x05, 0x21, 0x07, 0x71, 0x58, 0xff, 0x51, 0x56, 0xff, 0xf0, 0x60, 0x94, 
+        0x50, 0x52, 0x10, 0xc0, 0x66, 0x01, 0x2d, 0x0c, 0xc0, 0x20, 0x00, 0x42, 0x2d, 0xa8, 0x70, 0x44, 
+        0x10, 0x60, 0x44, 0x20, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0xc8, 0xb1, 0xe8, 0xd1, 0x42, 0x6d, 
+        0xa8, 0xf8, 0xe1, 0xd8, 0xc1, 0x08, 0xa1, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0xcd, 0x0f, 0xc6, 0xe1, 
+        0xff, 0x0c, 0x0f, 0x06, 0x86, 0xff, 0xf2, 0x21, 0x13, 0x0c, 0x03, 0x86, 0xa1, 0xff, 0xcd, 0x03, 
+        0x46, 0xdd, 0xff, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x09, 0x11, 0xcc, 0x52, 0x0c, 0x00, 0x0c, 
+        0x0c, 0x86, 0x10, 0x00, 0xe6, 0x12, 0x02, 0xc6, 0x70, 0x00, 0x32, 0xa0, 0x64, 0xb0, 0xc2, 0x11, 
+        0xc0, 0x2c, 0x20, 0xc5, 0xd1, 0x07, 0x0d, 0x02, 0x0c, 0xa3, 0x2d, 0x0c, 0x80, 0xc0, 0x01, 0xc0, 
+        0xc8, 0x31, 0xc5, 0xd0, 0x07, 0x0c, 0xa3, 0x05, 0xd7, 0x07, 0xa6, 0x22, 0x02, 0x06, 0x73, 0x00, 
+        0x0c, 0x10, 0x46, 0x04, 0x00, 0xc2, 0x01, 0x01, 0x02, 0x01, 0x00, 0x80, 0xcc, 0x01, 0x80, 0x00, 
+        0x01, 0x00, 0x08, 0x31, 0xc0, 0xc8, 0x31, 0xe6, 0x1c, 0x05, 0x00, 0x41, 0x21, 0xc6, 0x01, 0x00, 
+        0x0b, 0x2c, 0x00, 0x12, 0x40, 0x00, 0x40, 0xa1, 0x21, 0x2a, 0xff, 0xc0, 0x20, 0x00, 0x42, 0x62, 
+        0xb5, 0x62, 0xcc, 0x1e, 0x0c, 0x05, 0x00, 0x16, 0x40, 0x00, 0x30, 0xa1, 0xc0, 0x35, 0xb3, 0xc0, 
+        0x20, 0x00, 0x32, 0x62, 0xa7, 0xe6, 0x1c, 0x05, 0x00, 0x41, 0x21, 0xc6, 0x01, 0x00, 0x0b, 0x7c, 
+        0x00, 0x17, 0x40, 0x00, 0x40, 0xa1, 0xc0, 0x20, 0x00, 0x0c, 0x06, 0x42, 0x62, 0xec, 0xa2, 0xcc, 
+        0x1e, 0x0c, 0x09, 0x00, 0x1a, 0x40, 0x00, 0x80, 0xa1, 0xc0, 0x89, 0xb3, 0xc0, 0x20, 0x00, 0x82, 
+        0x62, 0xa1, 0x26, 0x10, 0x14, 0x66, 0x20, 0x04, 0x0c, 0x85, 0x86, 0x03, 0x00, 0x32, 0xc0, 0xfd, 
+        0x0c, 0xab, 0x5d, 0x06, 0x30, 0x5b, 0x83, 0x46, 0x00, 0x00, 0x0c, 0x25, 0xa6, 0xbc, 0x0d, 0x6c, 
+        0x04, 0x40, 0x4c, 0x90, 0x00, 0x14, 0x40, 0x00, 0x45, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x04, 0xc0, 
+        0x20, 0x00, 0x42, 0x62, 0xa3, 0x7c, 0x0b, 0xa6, 0x1c, 0x10, 0xe6, 0xbc, 0x0d, 0x7c, 0xe7, 0x70, 
+        0x7c, 0x90, 0x00, 0x17, 0x40, 0x00, 0x75, 0xa1, 0xc6, 0x01, 0x00, 0x0c, 0x08, 0x50, 0x72, 0x21, 
+        0xc0, 0x78, 0x93, 0xc0, 0x20, 0x00, 0x6c, 0x1a, 0x72, 0x62, 0xa2, 0x81, 0xd3, 0xfa, 0xc7, 0xab, 
+        0x10, 0xd6, 0xdc, 0x00, 0x1c, 0xe9, 0x90, 0x9c, 0x90, 0x00, 0x19, 0x40, 0x00, 0x75, 0xa1, 0x46, 
+        0x00, 0x00, 0x0c, 0x07, 0x7c, 0x19, 0xc0, 0x20, 0x00, 0x72, 0x68, 0xc3, 0xc7, 0xaa, 0x10, 0x97, 
+        0xac, 0x0d, 0x3c, 0xc3, 0x30, 0x3c, 0x90, 0x00, 0x13, 0x40, 0x00, 0x45, 0xa1, 0x46, 0x00, 0x00, 
+        0x0c, 0x04, 0xc0, 0x20, 0x00, 0x42, 0x68, 0xc2, 0x26, 0x10, 0x14, 0x66, 0x20, 0x04, 0x0c, 0x40, 
+        0x86, 0x03, 0x00, 0x52, 0xc0, 0xfd, 0x0c, 0x54, 0x50, 0x64, 0x83, 0x0d, 0x06, 0x46, 0x00, 0x00, 
+        0x0c, 0x10, 0xa6, 0xbc, 0x0d, 0x6c, 0x06, 0x60, 0x6c, 0x90, 0x00, 0x16, 0x40, 0x00, 0x40, 0xa1, 
+        0x46, 0x00, 0x00, 0x0c, 0x04, 0xc0, 0x20, 0x00, 0x42, 0x62, 0xef, 0xa6, 0x1c, 0x10, 0xe6, 0xbc, 
+        0x0d, 0x7c, 0xe7, 0x70, 0x7c, 0x90, 0x00, 0x17, 0x40, 0x00, 0x50, 0xa1, 0xc6, 0x01, 0x00, 0x0c, 
+        0x08, 0x00, 0x52, 0x21, 0xc0, 0x58, 0x93, 0xc0, 0x20, 0x00, 0x52, 0x62, 0xee, 0xc7, 0xab, 0x10, 
+        0xd6, 0xdc, 0x00, 0x1c, 0xeb, 0xb0, 0xbc, 0x90, 0x00, 0x1b, 0x40, 0x00, 0x50, 0xa1, 0x46, 0x00, 
+        0x00, 0x0c, 0x05, 0xc0, 0x20, 0x00, 0x52, 0x62, 0xeb, 0xc7, 0xaa, 0x10, 0x97, 0xac, 0x0d, 0x3c, 
+        0xc3, 0x30, 0x3c, 0x90, 0x00, 0x13, 0x40, 0x00, 0x00, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x00, 0xc0, 
+        0x20, 0x00, 0xc8, 0x21, 0x02, 0x62, 0xea, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xd6, 0x32, 
+        0xe6, 0x32, 0xa0, 0x64, 0xb0, 0xc2, 0x11, 0xc0, 0x2c, 0x20, 0x45, 0xb5, 0x07, 0x0d, 0x02, 0x0c, 
+        0xa3, 0x2d, 0x0c, 0x0b, 0xc0, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 0x31, 0x45, 0xb4, 0x07, 0x0c, 0xa3, 
+        0x45, 0xba, 0x07, 0x7c, 0x83, 0x37, 0xa2, 0x11, 0x0c, 0x10, 0x46, 0x92, 0xff, 0x0c, 0x30, 0xe6, 
+        0x82, 0x02, 0x46, 0x90, 0xff, 0x0c, 0x20, 0x06, 0x8f, 0xff, 0x0c, 0x30, 0x7c, 0xe4, 0x47, 0xa2, 
+        0x02, 0x86, 0x8c, 0xff, 0x0c, 0x20, 0x46, 0x8b, 0xff, 0x00, 0x00, 0x00, 0xf8, 0xf0, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xb1, 0xf7, 0xdc, 0x22, 0x1c, 0x04, 0xc0, 0x20, 0x00, 0x32, 
+        0x20, 0xe4, 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x60, 0xe4, 0x06, 0x04, 0x00, 0x6c, 0xf6, 
+        0xc0, 0x20, 0x00, 0x52, 0x20, 0xe4, 0x60, 0x55, 0x10, 0xc0, 0x20, 0x00, 0x52, 0x60, 0xe4, 0x41, 
+        0xf3, 0xff, 0x80, 0x32, 0x01, 0x22, 0x04, 0x80, 0x30, 0x38, 0x31, 0x80, 0x22, 0x01, 0x20, 0x28, 
+        0x31, 0x05, 0x8a, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 
+        0x61, 0x01, 0x02, 0x61, 0x00, 0x20, 0xc2, 0x20, 0x45, 0x3b, 0x01, 0x2d, 0x0c, 0x05, 0xfa, 0xff, 
+        0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0x7f, 0x80, 0x81, 0xbc, 0x14, 0x09, 0x98, 0x41, 0xc6, 0x5a, 
+        0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00, 0x90, 0x01, 0xff, 0xff, 0xff, 0xfb, 
+        0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0xff, 0x80, 0xff, 0x0f, 0xf0, 0xff, 
+        0x00, 0x20, 0x02, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xa6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 
+        0x54, 0x58, 0x38, 0x00, 0x00, 0xff, 0x0f, 0xf0, 0xe6, 0x00, 0x20, 0x0b, 0x3f, 0xf0, 0xff, 0xdf, 
+        0x40, 0x0c, 0x00, 0x20, 0xff, 0xff, 0x80, 0xff, 0x00, 0x00, 0x13, 0x00, 0x3f, 0xf0, 0xff, 0xff, 
+        0x80, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x24, 0x01, 0xfe, 0x03, 0xff, 0xff, 0xff, 0x0f, 
+        0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x00, 0x24, 0x00, 
+        0xff, 0xff, 0xbf, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x83, 0x00, 0x80, 0x00, 0xff, 0xf7, 0xff, 0xff, 
+        0x20, 0xf2, 0xfe, 0x3f, 0x40, 0x80, 0xfe, 0x3f, 0x9f, 0xf1, 0xfe, 0x3f, 0x74, 0xf0, 0xfe, 0x3f, 
+        0x64, 0xf1, 0xfe, 0x3f, 0x61, 0xd6, 0xff, 0xb1, 0xd6, 0xff, 0x41, 0xd7, 0xf9, 0x51, 0x52, 0xfb, 
+        0x12, 0xc1, 0xe0, 0xc9, 0x51, 0x09, 0x41, 0xd9, 0x61, 0x82, 0xaf, 0x80, 0x21, 0x3f, 0xfa, 0xd1, 
+        0x6c, 0xfe, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x58, 0x60, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x62, 
+        0x58, 0xc0, 0x20, 0x00, 0x02, 0x22, 0x43, 0xb0, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x62, 0x43, 
+        0xc1, 0xc9, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x22, 0xd0, 0xc0, 0xaa, 0x10, 0xb0, 0xaa, 0x20, 0xc0, 
+        0x20, 0x00, 0xa2, 0x62, 0xd0, 0x91, 0xc4, 0xff, 0xc0, 0x20, 0x00, 0x92, 0x62, 0x5b, 0x71, 0xc3, 
+        0xff, 0xc0, 0x20, 0x00, 0x72, 0x62, 0x5a, 0x61, 0xc2, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x54, 
+        0x60, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x54, 0xc0, 0x20, 0x00, 0xc2, 0xa1, 0x90, 0x02, 
+        0x22, 0xc6, 0xc0, 0x20, 0x00, 0xc2, 0x62, 0xc6, 0xb1, 0xbb, 0xff, 0xa1, 0xbb, 0xff, 0xc0, 0x20, 
+        0x00, 0x92, 0x2d, 0xbb, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x6d, 0xbb, 
+        0x71, 0xb7, 0xff, 0xc0, 0x20, 0x00, 0x62, 0x2d, 0xe2, 0x70, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 
+        0x6d, 0xe2, 0x42, 0x04, 0x00, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x52, 0x80, 0x33, 0x10, 0x40, 0x33, 
+        0x20, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x52, 0x01, 0xae, 0xff, 0xc1, 0xae, 0xff, 0xc0, 0x20, 0x00, 
+        0xb2, 0x22, 0x4a, 0x00, 0xbb, 0x10, 0xc0, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x62, 0x4a, 0xa1, 
+        0xaa, 0xff, 0xc0, 0x20, 0x00, 0x98, 0xd2, 0xa0, 0x99, 0x10, 0xc0, 0x20, 0x00, 0x99, 0xd2, 0x2c, 
+        0x67, 0xc0, 0x20, 0x00, 0x62, 0x22, 0x51, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 
+        0x62, 0x62, 0x51, 0x42, 0xaf, 0xc0, 0x1c, 0x13, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xdc, 0x40, 0x00, 
+        0x10, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x62, 0xdc, 0xc1, 0x2f, 0xfe, 0xc0, 0x20, 0x00, 
+        0xb2, 0x2d, 0xa8, 0xc0, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x6d, 0xa8, 0xa1, 0x98, 0xff, 0x91, 
+        0x98, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x22, 0x59, 0xa0, 0x88, 0x10, 0x90, 0x88, 0x20, 0xc0, 0x20, 
+        0x00, 0x82, 0x62, 0x59, 0x71, 0x94, 0xff, 0x61, 0x94, 0xff, 0xc0, 0x20, 0x00, 0x42, 0x22, 0x59, 
+        0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x62, 0x59, 0x31, 0x90, 0xff, 0x01, 
+        0x90, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x22, 0x57, 0x30, 0xcc, 0x10, 0x00, 0xcc, 0x20, 0xc0, 0x20, 
+        0x00, 0xc2, 0x62, 0x57, 0xb1, 0x8c, 0xff, 0xa1, 0x8c, 0xff, 0xc0, 0x20, 0x00, 0x92, 0x22, 0x54, 
+        0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x62, 0x54, 0xc0, 0x20, 0x00, 0x72, 
+        0xa0, 0x80, 0x82, 0x22, 0xc6, 0xc0, 0x20, 0x00, 0x72, 0x62, 0xc6, 0x0c, 0x46, 0xc0, 0x20, 0x00, 
+        0x42, 0x22, 0xc4, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x62, 0xc4, 0x31, 0x80, 0xff, 0x01, 
+        0x80, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x22, 0xdc, 0x30, 0xcc, 0x10, 0x00, 0xcc, 0x20, 0xc0, 0x20, 
+        0x00, 0xc2, 0x62, 0xdc, 0xb1, 0x7c, 0xff, 0xa1, 0x7c, 0xff, 0xc0, 0x20, 0x00, 0x92, 0x22, 0xc9, 
+        0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x62, 0xc9, 0x81, 0x78, 0xff, 0x71, 
+        0x78, 0xff, 0xc0, 0x20, 0x00, 0x62, 0x22, 0x56, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 
+        0x00, 0x62, 0x62, 0x56, 0x41, 0x74, 0xff, 0x31, 0x74, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xd3, 
+        0x40, 0x00, 0x10, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x62, 0xd3, 0xc1, 0x70, 0xff, 0xb1, 
+        0x70, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x22, 0xc8, 0xc0, 0xaa, 0x10, 0xb0, 0xaa, 0x20, 0xc0, 0x20, 
+        0x00, 0xa2, 0x62, 0xc8, 0x91, 0x6c, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x2d, 0xe2, 0x90, 0x88, 0x20, 
+        0xc0, 0x20, 0x00, 0x82, 0x6d, 0xe2, 0x71, 0x68, 0xff, 0x61, 0x68, 0xff, 0xc0, 0x20, 0x00, 0x42, 
+        0x25, 0x9c, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x65, 0x9c, 0x31, 0x64, 
+        0xff, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xd1, 0x30, 0x00, 0x10, 0xc0, 0x20, 0x00, 0x02, 0x62, 0xd1, 
+        0x0c, 0x02, 0xc5, 0xc8, 0xff, 0xc1, 0x3b, 0xf8, 0x08, 0x0c, 0x08, 0x30, 0x0c, 0x02, 0xc0, 0x00, 
+        0x00, 0xb2, 0xaf, 0xcf, 0x2c, 0x0a, 0x31, 0xd1, 0xf6, 0x61, 0x17, 0xf6, 0x21, 0x5a, 0xff, 0xc0, 
+        0x20, 0x00, 0x92, 0x2d, 0x8e, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x6d, 
+        0x8e, 0xc0, 0x20, 0x00, 0xa1, 0xa1, 0xf9, 0x71, 0x54, 0xff, 0x82, 0x2a, 0x92, 0xc0, 0x20, 0x00, 
+        0x72, 0x6a, 0x92, 0x0c, 0x65, 0xc0, 0x20, 0x00, 0x42, 0x2a, 0x93, 0x50, 0x44, 0x20, 0xc0, 0x20, 
+        0x00, 0x42, 0x6a, 0x93, 0xc0, 0x20, 0x00, 0x22, 0x6a, 0xc7, 0xc0, 0x20, 0x00, 0x02, 0x2a, 0xc7, 
+        0x20, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x6a, 0xc7, 0xb1, 0x48, 0xff, 0xc0, 0x20, 0x00, 0x98, 
+        0xaa, 0xb0, 0x99, 0x10, 0xc0, 0x20, 0x00, 0x99, 0xaa, 0x7c, 0x98, 0x0c, 0x27, 0xc0, 0x20, 0x00, 
+        0x52, 0x26, 0x89, 0x80, 0x55, 0x10, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 0x89, 0x7c, 
+        0xe4, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xf0, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x08, 0x0c, 0x02, 
+        0x20, 0x28, 0x22, 0x63, 0xf0, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 
+        0x2b, 0x0c, 0xc4, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 
+        0xa1, 0x84, 0xc0, 0x00, 0x00, 0x0c, 0x32, 0x08, 0x0c, 0x0c, 0x23, 0x02, 0x20, 0x2b, 0x0c, 0x64, 
+        0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0x28, 0x4c, 0x01, 0x2c, 0xff, 
+        0x07, 0xf2, 0x14, 0x32, 0xa0, 0x7f, 0x41, 0x2b, 0xff, 0x51, 0x2b, 0xff, 0x1c, 0x06, 0x0c, 0x07, 
+        0x2d, 0x00, 0x85, 0x41, 0xfe, 0x01, 0x26, 0xff, 0x21, 0xbb, 0xfa, 0x41, 0x28, 0xff, 0x51, 0x28, 
+        0xff, 0x32, 0x2c, 0x24, 0x61, 0x01, 0xf9, 0x0c, 0x07, 0x62, 0x06, 0x00, 0x79, 0x01, 0x79, 0x11, 
+        0x79, 0x21, 0x1b, 0x66, 0x60, 0x60, 0x74, 0x7d, 0x00, 0x45, 0x5b, 0xfe, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x1c, 0x24, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x72, 0xa0, 0xe8, 0xc0, 
+        0x00, 0x00, 0x0c, 0x13, 0xc0, 0x20, 0x00, 0x22, 0x2d, 0x98, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 
+        0x22, 0x6d, 0x98, 0xc8, 0x51, 0xd8, 0x61, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0xff, 0xff, 0x1f, 0xf0, 0x00, 0x00, 0x80, 0x01, 0xff, 0xff, 0xff, 0x1f, 0xff, 0x3f, 0xe0, 0xff, 
+        0x00, 0x40, 0x1f, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xab, 0x00, 0xff, 0x00, 0xff, 0xff, 
+        0xb1, 0xf8, 0xff, 0xa1, 0xf8, 0xff, 0x31, 0x79, 0xf6, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xe6, 0xb0, 
+        0x22, 0x10, 0xa0, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe6, 0xc0, 0x20, 0x00, 0x92, 0x23, 
+        0xe7, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x63, 0xe7, 0x81, 0xee, 0xff, 
+        0x71, 0x76, 0xfd, 0xc0, 0x20, 0x00, 0x62, 0x23, 0xe5, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 
+        0x20, 0x00, 0x62, 0x63, 0xe5, 0x51, 0xe9, 0xff, 0x41, 0xea, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x23, 
+        0xe6, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe6, 0xb1, 0xe5, 0xff, 
+        0xa1, 0xe6, 0xff, 0xc0, 0x20, 0x00, 0x92, 0x23, 0xe8, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 
+        0x20, 0x00, 0x92, 0x63, 0xe8, 0x81, 0xe1, 0xff, 0x72, 0xa1, 0x00, 0xc0, 0x20, 0x00, 0x62, 0x23, 
+        0xf2, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x63, 0xf2, 0x52, 0xaf, 0x80, 
+        0x4c, 0x74, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xe6, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 
+        0x00, 0x22, 0x63, 0xe6, 0x0d, 0xf0, 0x00, 0x00, 0x53, 0xf1, 0xfe, 0x3f, 0xff, 0x0f, 0xff, 0xff, 
+        0x00, 0x20, 0x00, 0x00, 0x42, 0xaf, 0xbc, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xc1, 0xfb, 0xff, 0x09, 
+        0x01, 0x22, 0x0c, 0x82, 0x01, 0x7b, 0xf5, 0x66, 0x22, 0x13, 0x4c, 0x15, 0xc0, 0x20, 0x00, 0x32, 
+        0x20, 0x68, 0x40, 0x33, 0x10, 0x50, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x60, 0x68, 0x32, 0x0c, 
+        0x83, 0x26, 0x13, 0x02, 0x66, 0x33, 0x27, 0x0c, 0x18, 0xc0, 0x20, 0x00, 0x72, 0x20, 0x68, 0x40, 
+        0x77, 0x10, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x60, 0x68, 0x7c, 0xe6, 0xc0, 0x20, 0x00, 
+        0x52, 0x20, 0x5d, 0x60, 0x55, 0x10, 0xc0, 0x20, 0x00, 0x52, 0x60, 0x5d, 0x32, 0x0c, 0x83, 0x42, 
+        0xae, 0xff, 0x26, 0x23, 0x02, 0x66, 0x33, 0x28, 0xc0, 0x20, 0x00, 0x91, 0x65, 0xf5, 0x82, 0x29, 
+        0x8d, 0xa2, 0xae, 0xff, 0xa0, 0x88, 0x10, 0xc0, 0x20, 0x00, 0x82, 0x69, 0x8d, 0x0c, 0x02, 0x0c, 
+        0x03, 0x0c, 0x04, 0x0c, 0x15, 0x01, 0x9e, 0xf5, 0xc0, 0x00, 0x00, 0x01, 0x5d, 0xf5, 0x42, 0xae, 
+        0xff, 0x32, 0x0c, 0x7c, 0x26, 0x13, 0x11, 0xc0, 0x20, 0x00, 0xb2, 0x20, 0x8d, 0x40, 0xbb, 0x10, 
+        0xc0, 0x20, 0x00, 0xb2, 0x60, 0x8d, 0x32, 0x0c, 0x7c, 0x66, 0x23, 0x11, 0x32, 0xa1, 0x00, 0xc0, 
+        0x20, 0x00, 0x22, 0x20, 0x85, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x60, 0x85, 0x62, 0xae, 
+        0xcf, 0x32, 0x0c, 0x81, 0x3c, 0x05, 0x66, 0x13, 0x14, 0xc0, 0x20, 0x00, 0x42, 0x20, 0x86, 0x60, 
+        0x44, 0x10, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x60, 0x86, 0x46, 0x0d, 0x00, 0x66, 0x23, 
+        0x11, 0xc0, 0x20, 0x00, 0x72, 0x20, 0x8e, 0x40, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x72, 0x60, 0x8e, 
+        0x06, 0x08, 0x00, 0xc0, 0x20, 0x00, 0x92, 0x20, 0x86, 0x60, 0x99, 0x10, 0x50, 0x99, 0x20, 0xc0, 
+        0x20, 0x00, 0x92, 0x60, 0x86, 0xc0, 0x20, 0x00, 0x82, 0x20, 0x8e, 0x40, 0x88, 0x10, 0xc0, 0x20, 
+        0x00, 0x82, 0x60, 0x8e, 0xa2, 0x0c, 0x7e, 0x66, 0x1a, 0x64, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x86, 
+        0x60, 0x33, 0x10, 0x50, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x60, 0x86, 0xc0, 0x20, 0x00, 0x22, 
+        0x20, 0x85, 0x60, 0x22, 0x10, 0x50, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x60, 0x85, 0xb2, 0x0c, 
+        0x7f, 0x66, 0x1b, 0x1e, 0x0c, 0x22, 0x0c, 0x03, 0x0c, 0x24, 0x0c, 0x05, 0x01, 0x6d, 0xf5, 0xc0, 
+        0x00, 0x00, 0x0c, 0x02, 0x0c, 0x83, 0x0c, 0x84, 0x0c, 0x05, 0x01, 0x69, 0xf5, 0xc0, 0x00, 0x00, 
+        0xc6, 0x06, 0x00, 0x0c, 0x02, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x05, 0x01, 0x65, 0xf5, 0xc0, 0x00, 
+        0x00, 0x0c, 0x82, 0x0c, 0x03, 0x0c, 0x84, 0x0c, 0x05, 0x01, 0x61, 0xf5, 0xc0, 0x00, 0x00, 0x41, 
+        0x5f, 0xf5, 0x02, 0x0c, 0x7d, 0x31, 0x9d, 0xff, 0x66, 0x10, 0x15, 0x61, 0x28, 0xf6, 0xc0, 0x20, 
+        0x00, 0x58, 0x14, 0x30, 0x55, 0x10, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x59, 0x14, 0x46, 0x05, 
+        0x00, 0x66, 0x20, 0x12, 0x71, 0x97, 0xff, 0xc0, 0x20, 0x00, 0x68, 0x14, 0x30, 0x66, 0x10, 0x70, 
+        0x66, 0x20, 0xc0, 0x20, 0x00, 0x69, 0x14, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x80, 0x3f, 0xe0, 0x0f, 0xff, 0xff, 0xcf, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0x71, 0xfa, 
+        0x22, 0x00, 0x80, 0x56, 0x62, 0x08, 0x01, 0x3f, 0xf7, 0x22, 0xa0, 0x66, 0x08, 0x00, 0x0c, 0x33, 
+        0x02, 0x20, 0x24, 0x0c, 0x14, 0xc0, 0x00, 0x00, 0x31, 0x3b, 0xf7, 0x22, 0x63, 0x87, 0x21, 0xd3, 
+        0xf5, 0xc0, 0x20, 0x00, 0x52, 0x22, 0xe5, 0x52, 0x63, 0x88, 0xc0, 0x20, 0x00, 0x42, 0x22, 0xe6, 
+        0x42, 0x63, 0x89, 0xc0, 0x20, 0x00, 0x0c, 0x14, 0x0c, 0x55, 0x0c, 0x06, 0x3c, 0xc7, 0x22, 0x22, 
+        0xe7, 0x22, 0x63, 0x8a, 0x08, 0x03, 0x22, 0xa0, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x33, 0xc0, 0x00, 
+        0x00, 0x01, 0x5c, 0xfa, 0x21, 0xe7, 0xff, 0xc0, 0x20, 0x00, 0x71, 0xc4, 0xf5, 0xb2, 0x27, 0xe7, 
+        0x20, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x67, 0xe7, 0xa1, 0x44, 0xfe, 0xc0, 0x20, 0x00, 0x92, 
+        0x27, 0xe6, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x67, 0xe6, 0x81, 0xde, 0xff, 0xc0, 0x20, 
+        0x00, 0x62, 0x27, 0xe5, 0x80, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 0x67, 0xe5, 0x0c, 0x13, 0x32, 
+        0x40, 0x80, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xf1, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfd, 0xff, 0x22, 0x00, 0x7d, 0x66, 0x12, 0x38, 0x22, 0xa0, 
+        0x66, 0x0c, 0x33, 0x01, 0x14, 0xf7, 0x0c, 0x14, 0x08, 0x00, 0x51, 0xf8, 0xff, 0x02, 0x20, 0x26, 
+        0x52, 0x05, 0x80, 0xc0, 0x00, 0x00, 0x01, 0xf5, 0xff, 0x31, 0xa8, 0xf5, 0x52, 0x20, 0x21, 0xc0, 
+        0x20, 0x00, 0x52, 0x63, 0xe5, 0x42, 0x20, 0x22, 0xc0, 0x20, 0x00, 0x42, 0x63, 0xe6, 0x22, 0x20, 
+        0x23, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe7, 0x0c, 0x06, 0x62, 0x40, 0x7d, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x66, 0x12, 0x05, 0x85, 0xef, 0xff, 0x86, 
+        0x00, 0x00, 0xc5, 0xf9, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x40, 0x00, 
+        0x6c, 0xf0, 0xfe, 0x3f, 0x10, 0xf1, 0xfe, 0x3f, 0x00, 0x78, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0xc2, 
+        0x61, 0x05, 0x09, 0x41, 0xd9, 0x61, 0x21, 0xd8, 0xf4, 0xd1, 0xf6, 0xf6, 0xc0, 0x20, 0x00, 0x42, 
+        0x22, 0x97, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x96, 0xc0, 0x20, 0x00, 0x10, 0x48, 0x40, 0x0c, 0x13, 
+        0x0c, 0x74, 0x0c, 0x35, 0x0c, 0x26, 0x0c, 0x07, 0x08, 0x0d, 0x22, 0x22, 0x97, 0x02, 0x20, 0x27, 
+        0x22, 0xa0, 0x61, 0xc0, 0x00, 0x00, 0x85, 0xc2, 0xff, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 
+        0x0c, 0x05, 0x08, 0x0d, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x05, 0x6b, 
+        0x02, 0xc1, 0xa0, 0xf9, 0x2d, 0x0c, 0x32, 0xcc, 0x3c, 0x45, 0xaa, 0x01, 0x28, 0x4d, 0x67, 0xf2, 
+        0x0e, 0x0c, 0x02, 0x45, 0xee, 0x00, 0x51, 0xe1, 0xff, 0x48, 0x4d, 0x50, 0x44, 0x20, 0x49, 0x4d, 
+        0x05, 0x67, 0xfe, 0x22, 0xa0, 0x01, 0x85, 0xba, 0xfe, 0xc0, 0x2c, 0x20, 0x31, 0xdd, 0xff, 0x4c, 
+        0x05, 0x0c, 0x07, 0x0c, 0x06, 0x0c, 0x19, 0x0c, 0x0a, 0x41, 0xdb, 0xf7, 0x81, 0xda, 0xff, 0x42, 
+        0x14, 0x01, 0x82, 0x08, 0x80, 0xa9, 0x01, 0x99, 0x11, 0x80, 0x88, 0x01, 0x80, 0x88, 0x31, 0x82, 
+        0xc8, 0x1f, 0x80, 0x88, 0x01, 0x80, 0x88, 0x31, 0x80, 0x68, 0xb3, 0x60, 0x60, 0x74, 0x05, 0x39, 
+        0x02, 0x0c, 0x62, 0x05, 0x7c, 0x01, 0xc5, 0x7d, 0xff, 0x0c, 0x27, 0x61, 0x4b, 0xf9, 0xc0, 0x20, 
+        0x00, 0x52, 0x26, 0x9c, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 0x9c, 0x3c, 0x22, 0x01, 
+        0x40, 0xf6, 0xc0, 0x00, 0x00, 0x08, 0x0d, 0x02, 0x20, 0x16, 0x22, 0xae, 0x7c, 0xc0, 0x00, 0x00, 
+        0x72, 0xac, 0x00, 0x62, 0xa0, 0xc9, 0x31, 0x30, 0xf8, 0xc0, 0x20, 0x00, 0x58, 0xd3, 0x70, 0x55, 
+        0x10, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x59, 0xd3, 0x7c, 0xe4, 0xc0, 0x20, 0x00, 0x28, 0xd3, 
+        0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x29, 0xd3, 0x3c, 0x22, 0x01, 0x31, 0xf6, 0xc0, 0x00, 0x00, 
+        0xc9, 0x01, 0x0c, 0x12, 0x0c, 0x73, 0x0c, 0x54, 0x51, 0xb8, 0xff, 0x0c, 0x16, 0x0c, 0x07, 0x45, 
+        0xcf, 0xfe, 0x0c, 0x02, 0xc8, 0x51, 0xd8, 0x61, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 
+        0x9c, 0xf1, 0xfe, 0x3f, 0x6d, 0x02, 0xfb, 0x72, 0x91, 0xfe, 0xff, 0x42, 0x02, 0x00, 0x5d, 0x09, 
+        0x42, 0x49, 0x00, 0x32, 0x02, 0x01, 0x82, 0xc9, 0xc0, 0x30, 0x31, 0x04, 0x32, 0x49, 0x02, 0xa2, 
+        0x06, 0x02, 0xa2, 0x45, 0x03, 0x1b, 0x66, 0x1b, 0x55, 0x77, 0x96, 0xf2, 0x5d, 0x09, 0x6d, 0x02, 
+        0x3b, 0x72, 0x32, 0x06, 0x11, 0x1b, 0x55, 0x1b, 0x66, 0x32, 0x45, 0x11, 0x42, 0x06, 0x13, 0x80, 
+        0xb3, 0x01, 0x4a, 0x33, 0x32, 0x45, 0x14, 0x32, 0x06, 0x16, 0xb0, 0xb8, 0x31, 0x3a, 0xbb, 0xb2, 
+        0x45, 0x17, 0x77, 0x96, 0xdc, 0x6d, 0x02, 0x5d, 0x09, 0x4b, 0x72, 0x42, 0x02, 0x1a, 0x42, 0x48, 
+        0x5c, 0x32, 0x02, 0x1b, 0x32, 0x48, 0x5d, 0xb2, 0x02, 0x1c, 0xa2, 0x02, 0x1d, 0xb0, 0xb0, 0x54, 
+        0x80, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xa2, 0x58, 0x2f, 0xa2, 0x06, 0x1e, 0xa2, 0x45, 0x20, 0x1b, 
+        0x66, 0x1b, 0x55, 0x77, 0x96, 0xf2, 0x5d, 0x09, 0x6d, 0x02, 0x6b, 0x72, 0xb2, 0x06, 0x22, 0xb2, 
+        0x45, 0x24, 0x1b, 0x66, 0x1b, 0x55, 0x77, 0x96, 0xf2, 0x5d, 0x09, 0x6d, 0x02, 0x8b, 0x72, 0x32, 
+        0x06, 0x28, 0x32, 0x45, 0x2a, 0x1b, 0x66, 0x1b, 0x55, 0x77, 0x96, 0xf2, 0x0c, 0x55, 0x32, 0x02, 
+        0x30, 0x32, 0x48, 0x41, 0xb2, 0x02, 0x31, 0xb2, 0x48, 0x73, 0xa2, 0x02, 0x32, 0xa2, 0x48, 0x74, 
+        0x92, 0x02, 0x33, 0x92, 0x48, 0x75, 0x72, 0x02, 0x34, 0x72, 0x48, 0x76, 0x62, 0x02, 0x35, 0x62, 
+        0x48, 0x77, 0x42, 0x02, 0x36, 0x42, 0x48, 0x78, 0x32, 0x02, 0x37, 0x32, 0x48, 0x79, 0xb2, 0x02, 
+        0x38, 0xb2, 0x48, 0x7a, 0xa2, 0x02, 0x40, 0xa2, 0x48, 0x7b, 0x92, 0x02, 0x41, 0x92, 0x48, 0x7c, 
+        0x72, 0x02, 0x42, 0x62, 0x02, 0x43, 0x70, 0x70, 0x54, 0x80, 0x77, 0x11, 0x70, 0x66, 0x20, 0x62, 
+        0x58, 0x3f, 0x42, 0x02, 0x44, 0x42, 0x48, 0x80, 0x32, 0x02, 0x45, 0x32, 0x48, 0x81, 0xb2, 0x02, 
+        0x47, 0xa2, 0x02, 0x46, 0x80, 0xbb, 0x01, 0x80, 0xaa, 0x01, 0xa0, 0xa8, 0x31, 0xb0, 0xb8, 0x31, 
+        0x80, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xa2, 0x58, 0x41, 0x92, 0x02, 0x49, 0x72, 0x02, 0x48, 0x80, 
+        0x99, 0x01, 0x80, 0x77, 0x01, 0x70, 0x78, 0x31, 0x90, 0x98, 0x31, 0x80, 0x99, 0x11, 0x90, 0x77, 
+        0x20, 0x72, 0x58, 0x42, 0x62, 0x02, 0x4a, 0x62, 0x48, 0x86, 0x42, 0x02, 0x4b, 0x6d, 0x05, 0x40, 
+        0x40, 0x34, 0x42, 0x48, 0x88, 0xf6, 0x64, 0x01, 0x6d, 0x04, 0x62, 0x48, 0x88, 0x92, 0x02, 0x4b, 
+        0x90, 0x94, 0x24, 0x92, 0x48, 0x8a, 0x72, 0x02, 0x4b, 0x70, 0x77, 0x04, 0x72, 0x48, 0x8c, 0x62, 
+        0x02, 0x4c, 0x60, 0x60, 0x34, 0x62, 0x48, 0x87, 0x67, 0x35, 0x01, 0x5d, 0x06, 0x52, 0x48, 0x87, 
+        0xa2, 0x02, 0x4c, 0xa0, 0xa4, 0x24, 0xa2, 0x48, 0x89, 0x92, 0x02, 0x4c, 0x90, 0x97, 0x04, 0x92, 
+        0x48, 0x8b, 0x72, 0x02, 0x4d, 0x70, 0x70, 0x34, 0x72, 0x48, 0x8e, 0x62, 0x02, 0x4d, 0x60, 0x64, 
+        0x34, 0x62, 0x48, 0x8d, 0x42, 0x02, 0x4e, 0x42, 0x48, 0x8f, 0x32, 0x02, 0x4f, 0x32, 0x48, 0x90, 
+        0xb2, 0x02, 0x50, 0xb2, 0x48, 0x91, 0xa2, 0x02, 0x51, 0xa2, 0x48, 0x92, 0x92, 0x02, 0x52, 0x92, 
+        0x48, 0x93, 0x72, 0x02, 0x53, 0x72, 0x48, 0x94, 0x62, 0x02, 0x54, 0x62, 0x48, 0x95, 0x42, 0x02, 
+        0x55, 0x42, 0x48, 0x96, 0x32, 0x02, 0x56, 0x32, 0x48, 0x97, 0xb2, 0x02, 0x57, 0xb2, 0x48, 0x98, 
+        0xa2, 0x02, 0x58, 0xa2, 0x48, 0x99, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x1d, 0xf1, 0xfe, 0x3f, 
+        0x08, 0x6b, 0x00, 0x40, 0x14, 0x3a, 0x00, 0x40, 0xa4, 0x38, 0x00, 0x40, 0xd8, 0x39, 0x00, 0x40, 
+        0x12, 0xc1, 0xf0, 0x09, 0x11, 0x01, 0xf9, 0xff, 0x02, 0x00, 0x80, 0x16, 0xa0, 0x09, 0x01, 0xf8, 
+        0xff, 0xc0, 0x00, 0x00, 0x41, 0xf6, 0xff, 0x42, 0x04, 0x80, 0x29, 0x01, 0x66, 0x14, 0x26, 0x22, 
+        0xa0, 0x67, 0x0c, 0x43, 0x08, 0x01, 0x0c, 0x24, 0x02, 0x20, 0x26, 0x52, 0xa0, 0x91, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x67, 0x0c, 0x43, 0x08, 0x01, 0x0c, 0x14, 0x02, 0x20, 0x26, 0x52, 0xa0, 0x88, 
+        0xc0, 0x00, 0x00, 0x46, 0x05, 0x00, 0x66, 0x24, 0x12, 0x0c, 0x43, 0x0c, 0x24, 0x0c, 0x75, 0x0c, 
+        0x56, 0x0c, 0x27, 0x02, 0x22, 0x27, 0x22, 0xa0, 0x67, 0xc0, 0x00, 0x00, 0x01, 0xb0, 0xf4, 0xc0, 
+        0x20, 0x00, 0x22, 0x20, 0x46, 0x27, 0x72, 0x35, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x46, 0x41, 0xdc, 
+        0xf3, 0x30, 0x3d, 0x25, 0x66, 0x23, 0x26, 0xc0, 0x20, 0x00, 0x42, 0x24, 0x88, 0x87, 0x64, 0x1d, 
+        0x0c, 0x12, 0x01, 0xdc, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x01, 0xdb, 0xff, 0xc0, 0x00, 0x00, 
+        0x0c, 0x12, 0x32, 0xa2, 0xb6, 0x01, 0xd9, 0xff, 0xc0, 0x00, 0x00, 0x86, 0x02, 0x00, 0x0c, 0x02, 
+        0x32, 0xa2, 0xb6, 0x01, 0xd6, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0xa0, 0x80, 0xfe, 0x3f, 0xc0, 0x80, 0xfe, 0x3f, 0xe0, 0x80, 0xfe, 0x3f, 0xf0, 0x83, 0xfe, 0x3f, 
+        0x44, 0x84, 0xfe, 0x3f, 0x31, 0xfb, 0xff, 0x1c, 0xc4, 0x22, 0xa0, 0xf0, 0x20, 0x11, 0xc0, 0xc2, 
+        0x61, 0x34, 0xd2, 0x61, 0x35, 0xe2, 0x61, 0x36, 0xf2, 0x61, 0x37, 0x22, 0xc1, 0x50, 0x02, 0x61, 
+        0x33, 0x85, 0xd7, 0x06, 0x22, 0xc1, 0x70, 0x31, 0xf3, 0xff, 0x1c, 0xc4, 0xc5, 0xd6, 0x06, 0x31, 
+        0xf2, 0xff, 0x1c, 0xc4, 0x22, 0xc1, 0x7f, 0x22, 0xc2, 0x11, 0x05, 0xd6, 0x06, 0x0c, 0x02, 0x05, 
+        0xce, 0x04, 0xf1, 0x86, 0xf4, 0xc0, 0x20, 0x00, 0x0c, 0x1c, 0x42, 0x2f, 0xff, 0xd2, 0xd1, 0xff, 
+        0xe2, 0xd1, 0xff, 0xe2, 0xce, 0x70, 0xd2, 0xcd, 0x50, 0x40, 0x30, 0xf5, 0x40, 0x58, 0x75, 0x52, 
+        0x61, 0x32, 0x80, 0x33, 0x01, 0x00, 0x44, 0x11, 0x30, 0x38, 0x31, 0x32, 0x61, 0x31, 0x40, 0x40, 
+        0x31, 0x42, 0x61, 0x30, 0xc0, 0x2c, 0x20, 0xc5, 0xa1, 0x03, 0xc0, 0x20, 0x00, 0xe0, 0x2c, 0x90, 
+        0x02, 0x2f, 0xff, 0x02, 0x52, 0x7f, 0xd0, 0x2c, 0x90, 0x00, 0x00, 0xf5, 0xc2, 0xcc, 0x01, 0xc0, 
+        0xc0, 0x74, 0x02, 0x52, 0x7f, 0x22, 0xa0, 0x0f, 0x27, 0x9c, 0xd8, 0x0c, 0x1c, 0xd1, 0xd5, 0xf5, 
+        0xe1, 0xda, 0xf6, 0x0c, 0xe3, 0x32, 0x61, 0x38, 0x08, 0x0d, 0x02, 0x20, 0x28, 0xc0, 0x00, 0x00, 
+        0x08, 0x0d, 0x02, 0x20, 0x30, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x22, 0x1e, 0x01, 0x20, 0x20, 0xb4, 
+        0x85, 0x5a, 0x00, 0x22, 0x1e, 0x01, 0x32, 0xc1, 0x7f, 0x32, 0xc3, 0x31, 0xc5, 0x78, 0x01, 0x08, 
+        0x0d, 0x08, 0x60, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x0c, 0x13, 0x85, 0x3d, 0xfe, 0x32, 
+        0xc1, 0x90, 0x30, 0x3c, 0x90, 0xc0, 0x20, 0x00, 0x08, 0x0d, 0x22, 0x2f, 0xff, 0x02, 0x20, 0x32, 
+        0x22, 0x53, 0x7f, 0xc0, 0x00, 0x00, 0x08, 0x0d, 0x02, 0x20, 0x31, 0xc0, 0x00, 0x00, 0x08, 0x0d, 
+        0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0x22, 0x1e, 0x01, 0x32, 0xc1, 0x7f, 0x32, 0xc3, 0x31, 0xc5, 
+        0x74, 0x01, 0x22, 0x1e, 0x01, 0x32, 0xc1, 0x7f, 0x32, 0xc3, 0x31, 0x45, 0x6a, 0x01, 0x0c, 0xe2, 
+        0x32, 0xc1, 0x7f, 0x32, 0xc3, 0x39, 0x85, 0x4d, 0xfe, 0x42, 0x21, 0x38, 0x1b, 0xcc, 0xc0, 0xc0, 
+        0x74, 0x0b, 0x44, 0x42, 0x61, 0x38, 0x56, 0xe4, 0xf6, 0xf2, 0x91, 0x29, 0xf9, 0x01, 0xe2, 0x91, 
+        0x39, 0xe9, 0x11, 0xd2, 0x91, 0x2a, 0xd9, 0x21, 0xc2, 0x91, 0x3a, 0xc9, 0x31, 0xb2, 0x91, 0x2b, 
+        0xb9, 0x41, 0xa2, 0x91, 0x3b, 0xa9, 0x51, 0x92, 0x91, 0x2c, 0x99, 0x61, 0x82, 0x91, 0x3c, 0x89, 
+        0x71, 0x72, 0x91, 0x2d, 0x79, 0x81, 0x62, 0x91, 0x3d, 0x69, 0x91, 0x52, 0x91, 0x2e, 0x59, 0xa1, 
+        0x42, 0x91, 0x3e, 0x52, 0x21, 0x30, 0x49, 0xb1, 0x42, 0x21, 0x31, 0x32, 0x91, 0x2f, 0x39, 0xc1, 
+        0x22, 0x91, 0x3f, 0x32, 0x21, 0x32, 0x29, 0xd1, 0x21, 0x9d, 0xff, 0x02, 0x91, 0x30, 0x09, 0xe1, 
+        0xf2, 0x91, 0x40, 0xf9, 0xf1, 0xe2, 0x91, 0x31, 0xe2, 0x61, 0x10, 0xd2, 0x91, 0x41, 0xd2, 0x61, 
+        0x11, 0x62, 0x91, 0x28, 0x72, 0x91, 0x38, 0x01, 0xc2, 0xf5, 0xc0, 0x00, 0x00, 0xc2, 0x21, 0x30, 
+        0xd2, 0x21, 0x31, 0xe2, 0x21, 0x32, 0xf2, 0x91, 0x32, 0x62, 0x91, 0x44, 0x69, 0x01, 0x52, 0x91, 
+        0x35, 0x59, 0x11, 0x42, 0x91, 0x45, 0x49, 0x21, 0x32, 0x91, 0x48, 0x39, 0x31, 0x22, 0x91, 0x49, 
+        0x29, 0x41, 0x02, 0x91, 0x4a, 0x09, 0x51, 0xb2, 0x91, 0x4b, 0xb9, 0x61, 0xa2, 0x91, 0x4c, 0xa9, 
+        0x71, 0x92, 0x91, 0x4d, 0x99, 0x81, 0x82, 0x91, 0x4e, 0x89, 0x91, 0x72, 0x91, 0x4f, 0x79, 0xa1, 
+        0x62, 0x91, 0x50, 0x69, 0xb1, 0x52, 0x91, 0x51, 0x59, 0xc1, 0x42, 0x91, 0x52, 0x49, 0xd1, 0x32, 
+        0x91, 0x53, 0x39, 0xe1, 0x22, 0x91, 0x54, 0x3d, 0x0f, 0x29, 0xf1, 0x21, 0x7d, 0xff, 0x02, 0x91, 
+        0x55, 0x02, 0x61, 0x10, 0x42, 0x91, 0x42, 0x52, 0x91, 0x33, 0x62, 0x91, 0x43, 0x72, 0x91, 0x34, 
+        0x01, 0xa4, 0xf5, 0xc0, 0x00, 0x00, 0x22, 0x91, 0x29, 0x29, 0x01, 0x02, 0x91, 0x39, 0x09, 0x11, 
+        0xb2, 0x91, 0x2a, 0xb9, 0x21, 0xa2, 0x91, 0x3a, 0xa9, 0x31, 0x92, 0x91, 0x2b, 0x99, 0x41, 0x82, 
+        0x91, 0x3b, 0x89, 0x51, 0x72, 0x91, 0x2c, 0x79, 0x61, 0x62, 0x91, 0x3c, 0x69, 0x71, 0x52, 0x91, 
+        0x2d, 0x59, 0x81, 0x42, 0x91, 0x3d, 0x5d, 0x0c, 0x49, 0x91, 0x4d, 0x0d, 0x32, 0x91, 0x2e, 0x39, 
+        0xa1, 0x22, 0x91, 0x3e, 0x3d, 0x0e, 0x29, 0xb1, 0x21, 0x65, 0xff, 0x02, 0x91, 0x2f, 0x09, 0xc1, 
+        0xb2, 0x91, 0x3f, 0xb9, 0xd1, 0xa2, 0x91, 0x30, 0xa9, 0xe1, 0x92, 0x91, 0x40, 0x99, 0xf1, 0x82, 
+        0x91, 0x31, 0x82, 0x61, 0x10, 0x72, 0x91, 0x41, 0x72, 0x61, 0x11, 0x62, 0x91, 0x28, 0x72, 0x91, 
+        0x38, 0x01, 0x3b, 0xf3, 0xc0, 0x00, 0x00, 0x52, 0x91, 0x44, 0x59, 0x01, 0x42, 0x91, 0x35, 0x49, 
+        0x11, 0x32, 0x91, 0x45, 0x39, 0x21, 0x22, 0x91, 0x48, 0x29, 0x31, 0x02, 0x91, 0x49, 0x21, 0x54, 
+        0xff, 0x09, 0x41, 0xe2, 0x91, 0x4a, 0xe9, 0x51, 0xd2, 0x91, 0x4b, 0xd9, 0x61, 0xc2, 0x91, 0x4c, 
+        0xc9, 0x71, 0xb2, 0x91, 0x4d, 0xb9, 0x81, 0xa2, 0x91, 0x4e, 0xa9, 0x91, 0x92, 0x91, 0x4f, 0x99, 
+        0xa1, 0x82, 0x91, 0x50, 0x89, 0xb1, 0x72, 0x91, 0x51, 0x79, 0xc1, 0x62, 0x91, 0x52, 0x69, 0xd1, 
+        0x52, 0x91, 0x53, 0x59, 0xe1, 0x42, 0x91, 0x54, 0x49, 0xf1, 0x32, 0x91, 0x55, 0x32, 0x61, 0x10, 
+        0x3d, 0x0f, 0x42, 0x91, 0x42, 0x52, 0x91, 0x33, 0x62, 0x91, 0x43, 0x72, 0x91, 0x34, 0x01, 0x20, 
+        0xf3, 0xc0, 0x00, 0x00, 0xc2, 0x21, 0x34, 0xd2, 0x21, 0x35, 0xe2, 0x21, 0x36, 0xf2, 0x21, 0x37, 
+        0x22, 0xa0, 0xf0, 0x02, 0x21, 0x33, 0x2a, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x40, 0x3d, 0x10, 0x40, 
+        0x98, 0x5f, 0x10, 0x40, 0xd4, 0x5d, 0x10, 0x40, 0x7c, 0x58, 0x10, 0x40, 0xa8, 0x36, 0x10, 0x40, 
+        0xdc, 0x39, 0x10, 0x40, 0xec, 0x19, 0x10, 0x40, 0x08, 0x1a, 0x10, 0x40, 0xd8, 0x57, 0x10, 0x40, 
+        0xa0, 0x3e, 0x10, 0x40, 0x2a, 0xf3, 0xfe, 0x3f, 0x34, 0xf1, 0xfe, 0x3f, 0x14, 0x80, 0xfe, 0x3f, 
+        0x94, 0xf1, 0xfe, 0x3f, 0x21, 0x43, 0x65, 0x87, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x02, 
+        0xff, 0x1f, 0x00, 0x00, 0xc0, 0x0c, 0xf2, 0x3f, 0xac, 0x84, 0xfe, 0x3f, 0x12, 0xc1, 0xd0, 0xc9, 
+        0x91, 0xe9, 0xb1, 0x09, 0x81, 0x01, 0x1f, 0xf5, 0xd9, 0xa1, 0x38, 0x40, 0xdd, 0x02, 0x97, 0xf3, 
+        0x44, 0x01, 0xeb, 0xfe, 0xc0, 0x00, 0x00, 0x51, 0xee, 0xff, 0x61, 0xec, 0xff, 0x71, 0xea, 0xff, 
+        0x81, 0xe9, 0xff, 0x91, 0xe7, 0xff, 0xa1, 0xe5, 0xff, 0xb1, 0xe3, 0xff, 0xc1, 0xe2, 0xff, 0xe1, 
+        0xe0, 0xff, 0x01, 0x14, 0xf5, 0x31, 0xdd, 0xff, 0x29, 0x00, 0x32, 0x62, 0x1f, 0xe2, 0x62, 0x43, 
+        0xc2, 0x62, 0x12, 0xb2, 0x62, 0x3a, 0xa2, 0x62, 0x28, 0x92, 0x62, 0x22, 0x89, 0xa2, 0x72, 0x62, 
+        0x16, 0x69, 0x92, 0x52, 0x62, 0x36, 0x41, 0xdf, 0xff, 0xc1, 0xdf, 0xff, 0x42, 0x04, 0x00, 0xe2, 
+        0x0c, 0x44, 0xcc, 0xa4, 0x2d, 0x0d, 0xc5, 0x96, 0xff, 0xdd, 0x02, 0x0c, 0xee, 0x06, 0x02, 0x00, 
+        0xd2, 0xa0, 0x00, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x45, 0xb5, 0xff, 0x45, 0x53, 0xff, 0x05, 
+        0x7a, 0xff, 0x21, 0xd6, 0xff, 0xc5, 0x46, 0x05, 0x01, 0xd3, 0xff, 0x02, 0x00, 0x00, 0x66, 0x10, 
+        0x08, 0xe0, 0x2e, 0x20, 0xc5, 0x07, 0x01, 0xc6, 0x07, 0x00, 0x31, 0xd1, 0xff, 0x61, 0xd3, 0xff, 
+        0x71, 0xd1, 0xff, 0x21, 0xb6, 0xf7, 0x81, 0xd0, 0xff, 0x82, 0x62, 0x00, 0x42, 0x22, 0x01, 0x72, 
+        0x62, 0x6a, 0x60, 0x44, 0x20, 0x49, 0x12, 0x05, 0x37, 0xfd, 0x92, 0x0c, 0xb8, 0x0c, 0x0e, 0x66, 
+        0x19, 0x05, 0x05, 0xbd, 0xff, 0xe2, 0x4c, 0xb8, 0xa2, 0x0c, 0xb9, 0x08, 0x81, 0x66, 0x1a, 0x3d, 
+        0xb2, 0x0c, 0xba, 0x66, 0x1b, 0x4c, 0x0c, 0x12, 0x85, 0x79, 0xff, 0x22, 0x0c, 0xbb, 0x85, 0x44, 
+        0x05, 0x0c, 0xa2, 0x0c, 0x03, 0x41, 0xc2, 0xff, 0x51, 0x5a, 0xf6, 0x62, 0xa0, 0xbf, 0x71, 0x58, 
+        0xf6, 0x0c, 0x0d, 0xd9, 0x01, 0xd9, 0x11, 0xd9, 0x21, 0xd9, 0x31, 0xd9, 0x41, 0x05, 0x14, 0x03, 
+        0x01, 0x62, 0xf7, 0xc0, 0x20, 0x00, 0xe2, 0x60, 0xf0, 0x0c, 0x0d, 0x06, 0x11, 0x00, 0xc8, 0x91, 
+        0x31, 0xb1, 0xff, 0x0c, 0x12, 0xe8, 0xb1, 0x22, 0x43, 0x00, 0x2d, 0x0d, 0xd8, 0xa1, 0x12, 0xc1, 
+        0x30, 0x0d, 0xf0, 0x22, 0xa0, 0x00, 0xc5, 0x74, 0xff, 0x22, 0x0c, 0xbb, 0x85, 0x3f, 0x05, 0x22, 
+        0xa0, 0x0a, 0x32, 0xa0, 0x00, 0x0c, 0x06, 0x0c, 0x07, 0x42, 0xa3, 0xfc, 0x0c, 0x05, 0x59, 0x11, 
+        0x59, 0x21, 0x59, 0x31, 0x49, 0x01, 0x59, 0x41, 0x42, 0xa4, 0x00, 0x0c, 0x45, 0x05, 0x0f, 0x03, 
+        0xd2, 0xa7, 0xd0, 0x05, 0x42, 0x05, 0x21, 0xa7, 0xff, 0x0c, 0x03, 0x85, 0x08, 0x03, 0x21, 0xa6, 
+        0xff, 0x32, 0x0c, 0xbb, 0x42, 0x0c, 0xbc, 0x01, 0xaa, 0xf2, 0xc0, 0x00, 0x00, 0x0c, 0xa2, 0x32, 
+        0x0c, 0xbc, 0x0c, 0x14, 0x5d, 0x0d, 0x85, 0x4f, 0x03, 0x06, 0xfc, 0xff, 0x0c, 0x23, 0x12, 0xc1, 
+        0xe0, 0xc9, 0x31, 0xd9, 0x41, 0xd1, 0xbf, 0xf4, 0x09, 0x21, 0x08, 0x0d, 0xcd, 0x02, 0x02, 0x20, 
+        0x2c, 0x0c, 0x32, 0xc0, 0x00, 0x00, 0x0c, 0x13, 0x08, 0x0d, 0x29, 0x01, 0x02, 0x20, 0x2c, 0x0c, 
+        0x22, 0xc0, 0x00, 0x00, 0x0c, 0x13, 0xc0, 0x49, 0x04, 0x08, 0x0d, 0xc0, 0x58, 0x04, 0xc0, 0x66, 
+        0x04, 0x29, 0x11, 0xc0, 0x77, 0x04, 0x0c, 0x32, 0xe0, 0x77, 0x11, 0xd0, 0x66, 0x11, 0xf0, 0x55, 
+        0x11, 0x02, 0x20, 0x2b, 0x50, 0x44, 0x20, 0x70, 0x66, 0x20, 0xc0, 0x53, 0x04, 0xc0, 0x74, 0x04, 
+        0xa0, 0x55, 0x11, 0xb0, 0x77, 0x11, 0x70, 0x55, 0x20, 0xc0, 0x75, 0x04, 0xc0, 0x77, 0x11, 0x70, 
+        0x55, 0x20, 0x60, 0x55, 0x20, 0x50, 0x44, 0x20, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0x0c, 0x32, 
+        0x0c, 0x23, 0x08, 0x0d, 0x48, 0x01, 0x52, 0xa1, 0xc7, 0x50, 0x44, 0x10, 0x02, 0x20, 0x2b, 0xc0, 
+        0x50, 0x24, 0xd0, 0x55, 0x11, 0x50, 0x44, 0x20, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0x0c, 0x22, 
+        0x0c, 0x13, 0x08, 0x0d, 0x48, 0x11, 0x52, 0xa1, 0x85, 0x50, 0x44, 0x10, 0x02, 0x20, 0x2b, 0xc0, 
+        0x5b, 0x34, 0xd0, 0x55, 0x11, 0x50, 0x44, 0x20, 0xc0, 0x5a, 0x04, 0xf0, 0x55, 0x11, 0x50, 0x44, 
+        0x20, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0xc8, 0x31, 0xd8, 0x41, 0x08, 0x21, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x12, 0xc1, 0xe0, 0xd9, 0x21, 0xe9, 0x31, 0x09, 
+        0x01, 0xc9, 0x11, 0xf9, 0x41, 0x4d, 0x00, 0xf1, 0x0c, 0xf7, 0xc1, 0x24, 0xf3, 0xc0, 0x20, 0x00, 
+        0x22, 0x2c, 0xe5, 0x07, 0xe2, 0x41, 0xc0, 0x20, 0x00, 0x52, 0x2f, 0x9c, 0x17, 0x65, 0x38, 0xd1, 
+        0x85, 0xf4, 0x08, 0x0d, 0x02, 0x20, 0x1d, 0xc0, 0x00, 0x00, 0x0c, 0x52, 0x01, 0xfd, 0xf3, 0xc0, 
+        0x00, 0x00, 0xe2, 0xa1, 0x84, 0x08, 0x0d, 0x0c, 0x22, 0x02, 0x20, 0x2c, 0x0c, 0x13, 0xc0, 0x00, 
+        0x00, 0xe7, 0xc2, 0xf0, 0x08, 0x0d, 0x0c, 0x32, 0x02, 0x20, 0x2c, 0x0c, 0x23, 0xc0, 0x00, 0x00, 
+        0x0c, 0x63, 0x30, 0x22, 0x10, 0x66, 0x62, 0xdc, 0x91, 0x1d, 0xf7, 0x81, 0xe7, 0xf5, 0xc0, 0x20, 
+        0x00, 0x72, 0x28, 0x42, 0x90, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x68, 0x42, 0xc0, 0x20, 0x00, 
+        0x52, 0x2c, 0xe5, 0x0c, 0x16, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x6c, 0xe5, 0xc0, 0x20, 
+        0x00, 0x42, 0x2f, 0x9c, 0x01, 0xdc, 0xff, 0x17, 0x64, 0x11, 0xc0, 0x20, 0x00, 0xa2, 0x2c, 0xe8, 
+        0xe7, 0xfa, 0x08, 0xc0, 0x20, 0x00, 0xb2, 0x2c, 0xe8, 0x07, 0x0b, 0xf6, 0xc8, 0x11, 0xd8, 0x21, 
+        0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x0c, 0x13, 0x42, 0xa0, 
+        0x81, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 0xd1, 0x5f, 0xf4, 0x09, 0x01, 0x08, 0x0d, 0xcd, 
+        0x02, 0x02, 0x20, 0x2b, 0x0c, 0x22, 0xc0, 0x00, 0x00, 0x0c, 0x72, 0x08, 0x0d, 0x0c, 0x13, 0x02, 
+        0x20, 0x2b, 0xc0, 0x45, 0x41, 0xc0, 0x00, 0x00, 0xc0, 0x40, 0x44, 0x08, 0x0d, 0x0c, 0x02, 0x02, 
+        0x20, 0x2b, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 
+        0x42, 0xa0, 0x7f, 0xc0, 0x00, 0x00, 0x0c, 0x62, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 
+        0xa0, 0x7f, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x00, 0x00, 0xf0, 0x00, 0xe4, 0x84, 0xfe, 0x3f, 0xff, 0xff, 0x0f, 0xff, 0x12, 0xc1, 0xe0, 0x09, 
+        0x11, 0x29, 0x61, 0xe9, 0x41, 0xd9, 0x31, 0xf9, 0x51, 0xc9, 0x21, 0xfd, 0x02, 0xc1, 0x41, 0xf4, 
+        0xdd, 0x04, 0xed, 0x03, 0x41, 0xf7, 0xff, 0x31, 0xd9, 0xf2, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xf2, 
+        0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x37, 0x22, 0x63, 0xf2, 0xc0, 0x00, 
+        0x00, 0x4d, 0x0d, 0x3d, 0x0f, 0x2d, 0x0e, 0x5d, 0x01, 0x85, 0x71, 0x00, 0x08, 0x0c, 0x02, 0x20, 
+        0x38, 0x2d, 0x01, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x36, 0xc0, 0x00, 0x00, 0x22, 0xa0, 
+        0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x87, 
+        0xc0, 0x00, 0x00, 0x0c, 0x0d, 0xf2, 0xa0, 0x63, 0xe2, 0xa0, 0x64, 0x3c, 0x22, 0x01, 0xa4, 0xf3, 
+        0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x74, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 
+        0x25, 0x0c, 0x76, 0xc0, 0x00, 0x00, 0xdc, 0x22, 0xf7, 0x9d, 0x08, 0x21, 0xda, 0xff, 0x01, 0x50, 
+        0xf4, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0xe7, 0x9d, 0xce, 0x01, 0xd7, 0xff, 0xc0, 
+        0x20, 0x00, 0xf1, 0xb6, 0xf2, 0xe2, 0x2f, 0xf2, 0x00, 0xee, 0x10, 0xc0, 0x20, 0x00, 0xc8, 0x21, 
+        0xe2, 0x6f, 0xf2, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x32, 0xa0, 0x01, 0x42, 0xa0, 0x05, 0x0c, 0x75, 0x0c, 0x06, 0x12, 0xc1, 0xe0, 0xd9, 0x21, 0xf9, 
+        0x41, 0xc9, 0x11, 0xe9, 0x31, 0xe1, 0x0f, 0xf4, 0x09, 0x01, 0x08, 0x0e, 0xcd, 0x02, 0x02, 0x20, 
+        0x25, 0x22, 0xa0, 0x62, 0xc0, 0x00, 0x00, 0x0c, 0x0d, 0xfd, 0x02, 0x32, 0xae, 0xac, 0x20, 0x22, 
+        0x90, 0x30, 0x22, 0xb0, 0x32, 0xa0, 0xe3, 0x85, 0x6c, 0x06, 0x00, 0x52, 0x11, 0x0c, 0xf4, 0x0d, 
+        0x04, 0x50, 0x50, 0x31, 0x2d, 0x0d, 0x50, 0x25, 0xb3, 0xe6, 0xb2, 0x01, 0x0d, 0x02, 0x32, 0xa0, 
+        0xcf, 0xf0, 0x2f, 0x90, 0xf0, 0x22, 0xf0, 0x22, 0xc2, 0x1d, 0x00, 0xf0, 0x11, 0xf0, 0xf0, 0x31, 
+        0xc5, 0x69, 0x06, 0x98, 0x0e, 0x00, 0x42, 0x11, 0x0c, 0xf3, 0x0d, 0x03, 0x40, 0x40, 0x31, 0x92, 
+        0x29, 0x27, 0x40, 0xd4, 0xb3, 0xe6, 0xbd, 0x01, 0x0d, 0x0d, 0x00, 0xd0, 0x11, 0xd0, 0xd0, 0x31, 
+        0xb6, 0x3c, 0x1c, 0x0c, 0x82, 0xa6, 0x8f, 0x01, 0x7c, 0x82, 0x0c, 0x03, 0x0c, 0x44, 0x0c, 0x35, 
+        0x0c, 0x06, 0x2a, 0x7f, 0x70, 0x70, 0x74, 0x22, 0xa0, 0x64, 0xc0, 0x09, 0x00, 0x06, 0x04, 0x00, 
+        0xf0, 0x70, 0x74, 0x22, 0xa0, 0x64, 0x0c, 0x03, 0x0c, 0x44, 0x0c, 0x35, 0x0c, 0x06, 0xc0, 0x09, 
+        0x00, 0x98, 0x0e, 0x0c, 0x80, 0x92, 0x29, 0x27, 0xb6, 0x2c, 0x1a, 0xa6, 0x8d, 0x01, 0x7c, 0x80, 
+        0x22, 0xa0, 0x64, 0x0c, 0x03, 0x0c, 0x74, 0x0c, 0x35, 0x0c, 0x06, 0x0a, 0x7d, 0x70, 0x70, 0x74, 
+        0xc0, 0x09, 0x00, 0x06, 0x04, 0x00, 0xd0, 0x70, 0x74, 0x22, 0xa0, 0x64, 0x0c, 0x03, 0x0c, 0x74, 
+        0x0c, 0x35, 0x0c, 0x06, 0xc0, 0x09, 0x00, 0x98, 0x0e, 0x92, 0x29, 0x27, 0xac, 0x6c, 0x22, 0xa0, 
+        0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x35, 0x0c, 0x26, 0x0c, 0x37, 0xc0, 0x09, 0x00, 0x22, 0xa0, 
+        0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x15, 0x08, 0x0e, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x37, 
+        0xc0, 0x00, 0x00, 0x06, 0x09, 0x00, 0x22, 0xa0, 0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x35, 0x0c, 
+        0x26, 0x0c, 0x07, 0xc0, 0x09, 0x00, 0x22, 0xa0, 0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x15, 0x08, 
+        0x0e, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 
+        0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x22, 0xa0, 0x61, 0x12, 
+        0xc1, 0xf0, 0x09, 0x01, 0x01, 0xc0, 0xf3, 0x0c, 0x13, 0x08, 0x00, 0x0c, 0x84, 0x02, 0x20, 0x26, 
+        0x1c, 0x15, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x85, 0xe9, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x72, 0xaf, 0xdf, 
+        0x21, 0xbf, 0xf1, 0xc0, 0x20, 0x00, 0x62, 0x22, 0xd4, 0x70, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 
+        0x62, 0xd4, 0x51, 0x3b, 0xf8, 0xc0, 0x20, 0x00, 0x42, 0x22, 0xd7, 0x50, 0x44, 0x20, 0xc0, 0x20, 
+        0x00, 0x42, 0x62, 0xd7, 0x31, 0xf4, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xd7, 0x30, 0x00, 0x10, 
+        0xc0, 0x20, 0x00, 0x02, 0x62, 0xd7, 0x22, 0xa0, 0xc8, 0x01, 0x21, 0xf3, 0xc0, 0x00, 0x00, 0x22, 
+        0xa0, 0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x01, 0xa3, 0xf3, 0x0c, 0x65, 0x08, 0x00, 0x0c, 0x66, 0x02, 
+        0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x01, 0x9d, 
+        0xf3, 0x0c, 0x65, 0x08, 0x00, 0x0c, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x2c, 
+        0x04, 0xc0, 0x20, 0x00, 0x31, 0xa2, 0xf1, 0x22, 0x23, 0xd4, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 
+        0x0c, 0x24, 0x0c, 0x75, 0x01, 0x94, 0xf3, 0x0c, 0x06, 0x08, 0x00, 0x22, 0x63, 0xd4, 0x22, 0xa0, 
+        0x6c, 0x02, 0x20, 0x25, 0x0c, 0x23, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0xff, 0xff, 0xdf, 0xff, 0x12, 0xc1, 0xe0, 0xc9, 0x11, 0xd9, 0x21, 0xd1, 0x8a, 0xf3, 0x09, 0x01, 
+        0x08, 0x0d, 0xe9, 0x31, 0x02, 0x20, 0x28, 0xf9, 0x41, 0xc0, 0x00, 0x00, 0x08, 0x0d, 0x0c, 0x62, 
+        0x02, 0x20, 0x2c, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0x0c, 0x23, 0x0c, 0x94, 0x0c, 0x25, 0x0c, 0x06, 
+        0x08, 0x0d, 0xfd, 0x02, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x6b, 0xc0, 0x00, 0x00, 0x0c, 0x23, 0x0c, 
+        0x04, 0x0c, 0x55, 0x0c, 0x56, 0x08, 0x0d, 0xcd, 0x02, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x6c, 0xc0, 
+        0x00, 0x00, 0x0c, 0x13, 0xc9, 0x61, 0x08, 0x0d, 0xed, 0x02, 0x0c, 0x24, 0x0c, 0x62, 0x40, 0x4f, 
+        0x20, 0x02, 0x20, 0x2b, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 
+        0x94, 0x0c, 0x75, 0x0c, 0x76, 0x08, 0x0d, 0x0c, 0x17, 0x02, 0x20, 0x27, 0xe9, 0x51, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x94, 0x0c, 0x25, 0x08, 0x0d, 0x0c, 0x06, 0x02, 0x20, 
+        0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x0c, 0x2c, 0x22, 0xa0, 0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x0c, 
+        0x55, 0x08, 0x0d, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x81, 0x8d, 0xf3, 
+        0xe1, 0x6b, 0xf1, 0xc0, 0x20, 0x00, 0x72, 0x2e, 0xd7, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 
+        0x6e, 0xd7, 0x61, 0xcf, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x2e, 0xd7, 0x60, 0x55, 0x10, 0xc0, 0x20, 
+        0x00, 0x52, 0x6e, 0xd7, 0x7c, 0xd4, 0xc0, 0x20, 0x00, 0x32, 0x2e, 0xd4, 0x40, 0x33, 0x10, 0xc0, 
+        0x20, 0x00, 0x32, 0x6e, 0xd4, 0xc0, 0x20, 0x00, 0x22, 0x2e, 0xd4, 0xc0, 0x22, 0x20, 0xc0, 0x20, 
+        0x00, 0x22, 0x6e, 0xd4, 0x1c, 0x92, 0x01, 0xca, 0xf2, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x0c, 
+        0xe0, 0x20, 0xa0, 0xc0, 0x20, 0x00, 0x22, 0x22, 0xe0, 0x1b, 0x00, 0x00, 0x00, 0x74, 0x20, 0x20, 
+        0xb4, 0x20, 0xcc, 0xc0, 0xc2, 0xdc, 0x08, 0xc0, 0xc0, 0xf4, 0x66, 0x80, 0xe2, 0xf0, 0x40, 0xf4, 
+        0x08, 0x0d, 0x0c, 0x62, 0x02, 0x20, 0x2b, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0xf8, 0x61, 0x22, 0xa0, 
+        0x6b, 0x0c, 0x23, 0x0c, 0x94, 0x0c, 0x75, 0x08, 0x0d, 0x0c, 0x76, 0x02, 0x20, 0x27, 0x0c, 0x07, 
+        0xc0, 0x00, 0x00, 0xf0, 0x70, 0x74, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x94, 0x0c, 0x25, 0x08, 
+        0x0d, 0x0c, 0x06, 0x02, 0x20, 0x27, 0xe8, 0x51, 0xc0, 0x00, 0x00, 0xe0, 0x70, 0x74, 0x22, 0xa0, 
+        0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x08, 0x0d, 0x0c, 0x55, 0x02, 0x20, 0x27, 0x0c, 0x56, 0xc0, 0x00, 
+        0x00, 0x08, 0x0d, 0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0x08, 0x01, 0xd8, 0x21, 0xe8, 0x31, 0x60, 
+        0x2c, 0x11, 0xf8, 0x41, 0xc8, 0x11, 0x22, 0xd2, 0x08, 0x20, 0x2c, 0xf4, 0x12, 0xc1, 0x20, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x33, 0x0d, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x29, 0x01, 0x09, 
+        0x11, 0x05, 0xe6, 0xff, 0x01, 0xfc, 0xff, 0x0c, 0x0c, 0x07, 0x32, 0x02, 0x86, 0x0a, 0x00, 0xc1, 
+        0x21, 0xf3, 0x08, 0x0c, 0x08, 0xe0, 0x0c, 0x33, 0xc0, 0x00, 0x00, 0x0c, 0x33, 0x08, 0x0c, 0xcd, 
+        0x02, 0x08, 0xe0, 0x21, 0xf4, 0xff, 0xc0, 0x00, 0x00, 0x20, 0xcc, 0xc0, 0xf0, 0xcc, 0x11, 0x00, 
+        0xcc, 0x11, 0xc0, 0xc0, 0x31, 0x2b, 0xcc, 0xc0, 0xc2, 0x21, 0xc5, 0xd7, 0xff, 0x0c, 0x00, 0x51, 
+        0x44, 0xf6, 0x28, 0x01, 0x41, 0x67, 0xfc, 0xca, 0xc2, 0x00, 0xcc, 0x11, 0xc0, 0xc0, 0x31, 0x2d, 
+        0x0c, 0x5a, 0x60, 0x1b, 0x70, 0x4a, 0x30, 0x32, 0x03, 0x24, 0x70, 0x00, 0x74, 0x3a, 0x3c, 0x32, 
+        0x46, 0x00, 0x66, 0x60, 0xeb, 0xc8, 0x21, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0x0c, 0x0d, 0x16, 0x1d, 0x04, 
+        0x26, 0x1d, 0x20, 0x66, 0x2d, 0x56, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x65, 0x01, 
+        0x01, 0xf3, 0x0c, 0x46, 0x08, 0x00, 0xda, 0x7c, 0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 
+        0x00, 0x06, 0x0e, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x35, 0x01, 0xf9, 0xf2, 
+        0x0c, 0x06, 0x08, 0x00, 0xda, 0x7c, 0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x86, 
+        0x06, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x14, 0x0c, 0x35, 0x01, 0xf2, 0xf2, 0x0c, 0x06, 
+        0x08, 0x00, 0xda, 0x7c, 0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 0xd0, 
+        0xd0, 0x74, 0x66, 0x3d, 0x97, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xe0, 0x09, 0x11, 0x39, 0x01, 0xc9, 0x21, 0xd9, 0x31, 0xe9, 0x41, 0xdd, 0x02, 0xed, 
+        0x04, 0xc1, 0xe4, 0xf2, 0x16, 0x22, 0x0f, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xc4, 0x0c, 0x05, 
+        0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x1c, 0xa4, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 
+        0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x55, 0x08, 
+        0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 
+        0x1c, 0xa4, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x04, 0x0c, 0x75, 0x0c, 0x06, 0x08, 0x0c, 0x78, 0x01, 0x02, 
+        0x20, 0x27, 0x70, 0x7c, 0x74, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x14, 0x0c, 
+        0x75, 0x0c, 0x06, 0x08, 0x0c, 0x78, 0x01, 0x02, 0x20, 0x27, 0x70, 0x74, 0x74, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x24, 0x0c, 0x35, 0x0c, 0x06, 0x08, 0x0c, 0x78, 0x01, 0x02, 
+        0x20, 0x27, 0x70, 0x70, 0x34, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x44, 0x0c, 
+        0x75, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0xe0, 0x70, 0x74, 0xc0, 0x00, 0x00, 0x22, 0xa0, 
+        0x77, 0x0c, 0x03, 0x0c, 0x34, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0xe0, 0x78, 
+        0x74, 0xc0, 0x00, 0x00, 0xe0, 0x70, 0x35, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x24, 0x08, 0x0c, 
+        0x0c, 0x75, 0x02, 0x20, 0x27, 0x0c, 0x46, 0xc0, 0x00, 0x00, 0x0c, 0xf4, 0x0c, 0x35, 0x0c, 0x36, 
+        0xd0, 0x30, 0x04, 0x0c, 0x12, 0x08, 0x0c, 0x0c, 0x0e, 0x02, 0x20, 0x27, 0x30, 0xe2, 0x83, 0x7d, 
+        0x0e, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x7d, 0x0e, 0x22, 0xa0, 0x77, 0x0c, 0x03, 
+        0x1c, 0x84, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x7d, 0x0d, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xc4, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x27, 0x0c, 0x06, 
+        0xc0, 0x00, 0x00, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x65, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xc1, 0x8d, 
+        0xf2, 0x09, 0x01, 0x08, 0x0c, 0x0c, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 
+        0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 
+        0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 
+        0x56, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 
+        0x0c, 0x65, 0x08, 0x0c, 0x0c, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0xc8, 0x11, 
+        0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0xc0, 0x41, 
+        0x00, 0x00, 0xd0, 0x41, 0x00, 0x00, 0x80, 0x43, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x80, 0x44, 
+        0x00, 0x00, 0x00, 0xc2, 0x12, 0xc1, 0xe0, 0xd9, 0x31, 0x09, 0x11, 0xc9, 0x21, 0xe9, 0x41, 0xcd, 
+        0x05, 0xe1, 0xf5, 0xff, 0x8c, 0xd3, 0x26, 0x13, 0x08, 0x66, 0x23, 0x08, 0xe1, 0xf4, 0xff, 0x86, 
+        0x00, 0x00, 0xe1, 0xf3, 0xff, 0xd1, 0xf3, 0xff, 0x60, 0x22, 0x11, 0x20, 0x24, 0x80, 0xe0, 0x22, 
+        0x11, 0x85, 0x1c, 0x06, 0x51, 0xf1, 0xff, 0x0c, 0x04, 0x85, 0x39, 0x05, 0x05, 0x50, 0x05, 0x29, 
+        0x01, 0x31, 0xee, 0xff, 0x2d, 0x0e, 0x45, 0xd5, 0x04, 0x3d, 0x02, 0x28, 0x01, 0x05, 0xeb, 0x04, 
+        0x31, 0xec, 0xff, 0xc5, 0xae, 0x04, 0xed, 0x02, 0x05, 0xfa, 0x04, 0x22, 0x4c, 0x00, 0x20, 0x20, 
+        0x74, 0xc5, 0x15, 0x06, 0x3d, 0x02, 0x2d, 0x0e, 0xc5, 0xbb, 0x04, 0x3d, 0x0d, 0xc5, 0xd2, 0x04, 
+        0xed, 0x02, 0x85, 0xf8, 0x04, 0x22, 0x4c, 0x01, 0x20, 0x20, 0x74, 0x45, 0x14, 0x06, 0x3d, 0x02, 
+        0x2d, 0x0e, 0x45, 0xba, 0x04, 0x3d, 0x0d, 0x45, 0xd1, 0x04, 0x05, 0xf7, 0x04, 0x08, 0x11, 0xd8, 
+        0x31, 0x22, 0x4c, 0x02, 0xe8, 0x41, 0xc8, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x65, 0x40, 0x10, 0x40, 0xb4, 0x09, 0x00, 0x00, 0xc7, 0x40, 0x10, 0x40, 0x04, 0x85, 0xfe, 0x3f, 
+        0x05, 0x42, 0x10, 0x40, 0x6c, 0x09, 0x00, 0x00, 0xa8, 0x09, 0x00, 0x00, 0xa3, 0x09, 0x00, 0x00, 
+        0x9e, 0x09, 0x00, 0x00, 0x99, 0x09, 0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0x8f, 0x09, 0x00, 0x00, 
+        0x8a, 0x09, 0x00, 0x00, 0x85, 0x09, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x7b, 0x09, 0x00, 0x00, 
+        0x76, 0x09, 0x00, 0x00, 0x71, 0x09, 0x00, 0x00, 0x12, 0xc1, 0xd0, 0xc9, 0x61, 0x49, 0xa1, 0x69, 
+        0x41, 0x39, 0x31, 0x09, 0x51, 0xe9, 0x81, 0xd9, 0x71, 0xf9, 0x91, 0xdd, 0x02, 0xfd, 0x04, 0x2d, 
+        0x05, 0x29, 0x21, 0xa6, 0x1d, 0x0c, 0x0c, 0xd0, 0xd7, 0x20, 0x07, 0x0b, 0xed, 0xe0, 0xe0, 0x74, 
+        0x46, 0x00, 0x00, 0x0c, 0xde, 0x41, 0xe2, 0xfd, 0xc1, 0x2b, 0xf2, 0x31, 0xc4, 0xf0, 0xc0, 0x20, 
+        0x00, 0x22, 0x23, 0xf2, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x37, 0x22, 
+        0x63, 0xf2, 0xc0, 0x00, 0x00, 0x0c, 0xe5, 0x57, 0xbd, 0x34, 0x71, 0xd9, 0xff, 0xd0, 0x6d, 0x90, 
+        0x7a, 0x66, 0xa0, 0x06, 0x00, 0x86, 0x09, 0x00, 0xc6, 0x79, 0x00, 0x06, 0x91, 0x00, 0x46, 0x8e, 
+        0x00, 0x86, 0x8b, 0x00, 0xc6, 0x88, 0x00, 0x06, 0x86, 0x00, 0x46, 0x83, 0x00, 0x86, 0x80, 0x00, 
+        0xc6, 0x7d, 0x00, 0x06, 0x7b, 0x00, 0x46, 0x78, 0x00, 0x86, 0x75, 0x00, 0xc6, 0x72, 0x00, 0x81, 
+        0xcd, 0xff, 0x89, 0x11, 0x56, 0x9f, 0x05, 0x98, 0x31, 0x3c, 0xb0, 0xf6, 0x29, 0x52, 0x0b, 0xa9, 
+        0x56, 0xea, 0x13, 0x42, 0xaf, 0xb7, 0xb2, 0xaf, 0x83, 0xa2, 0xa0, 0x76, 0x5c, 0xe3, 0x5c, 0xd9, 
+        0x5c, 0xc5, 0x5c, 0xb6, 0x0c, 0xee, 0xe7, 0x3d, 0x02, 0x86, 0x83, 0x00, 0x21, 0xc3, 0xff, 0xd0, 
+        0xfd, 0x90, 0x2a, 0xff, 0xa0, 0x0f, 0x00, 0x06, 0x80, 0x00, 0x06, 0x20, 0x00, 0x86, 0x82, 0x00, 
+        0x46, 0xad, 0x00, 0xc6, 0xa9, 0x00, 0x06, 0xa6, 0x00, 0x06, 0x83, 0x00, 0x86, 0xa2, 0x00, 0x46, 
+        0x9e, 0x00, 0x46, 0x9a, 0x00, 0xc6, 0x96, 0x00, 0x86, 0x92, 0x00, 0x06, 0x8f, 0x00, 0x86, 0x8b, 
+        0x00, 0x00, 0x0e, 0x40, 0x38, 0x21, 0xd8, 0x41, 0x38, 0x03, 0xd0, 0xde, 0xa0, 0x30, 0x30, 0x91, 
+        0x07, 0xe3, 0x35, 0x4d, 0x0f, 0x38, 0x31, 0x28, 0x11, 0x5d, 0x01, 0x85, 0xe1, 0xff, 0x00, 0x1e, 
+        0x40, 0x0c, 0x12, 0x08, 0x21, 0x32, 0x01, 0x02, 0x52, 0x01, 0x01, 0x42, 0x01, 0x00, 0x80, 0x55, 
+        0x11, 0x00, 0x44, 0x11, 0x50, 0x44, 0x20, 0x40, 0x33, 0x20, 0x39, 0x0d, 0xf8, 0x00, 0x00, 0x22, 
+        0xa1, 0x20, 0xff, 0x20, 0xf9, 0x00, 0x06, 0x08, 0x00, 0x78, 0x0d, 0x70, 0x70, 0xf5, 0x72, 0x41, 
+        0x00, 0x68, 0x0d, 0x60, 0x68, 0x41, 0x62, 0x41, 0x01, 0x08, 0x0d, 0x06, 0x02, 0x00, 0x62, 0x41, 
+        0x00, 0x32, 0xaf, 0xb1, 0x32, 0x41, 0x01, 0x02, 0x41, 0x02, 0x08, 0x0c, 0x02, 0x20, 0x38, 0x2d, 
+        0x01, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x36, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 
+        0x13, 0x0c, 0x04, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x87, 0xc0, 0x00, 
+        0x00, 0x0c, 0x0d, 0xf2, 0xa0, 0x63, 0xe2, 0xa0, 0x64, 0x1c, 0x42, 0x01, 0x51, 0xf1, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x74, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 0x25, 0x0c, 
+        0x76, 0xc0, 0x00, 0x00, 0xdc, 0x22, 0xf7, 0x9d, 0x08, 0x21, 0x88, 0xff, 0x01, 0xfd, 0xf1, 0xc0, 
+        0x00, 0x00, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0xe7, 0x9d, 0xce, 0x08, 0x11, 0x31, 0x83, 0xfd, 0xc0, 
+        0x20, 0x00, 0x21, 0x62, 0xf0, 0xf2, 0x22, 0xf2, 0x30, 0xff, 0x10, 0xc0, 0x20, 0x00, 0xc8, 0x61, 
+        0xd8, 0x71, 0xf2, 0x62, 0xf2, 0xe8, 0x81, 0xf8, 0x91, 0x2d, 0x00, 0x08, 0x51, 0x12, 0xc1, 0x30, 
+        0x0d, 0xf0, 0x3c, 0x04, 0x3c, 0x2e, 0x32, 0xa0, 0x66, 0xb2, 0xaf, 0x91, 0x52, 0xaf, 0xbb, 0x6c, 
+        0x69, 0x1c, 0x16, 0x3c, 0x1a, 0x0c, 0xe7, 0x77, 0xbd, 0x34, 0xf1, 0x75, 0xff, 0xd0, 0x8d, 0x90, 
+        0xfa, 0x88, 0xa0, 0x08, 0x00, 0x86, 0x09, 0x00, 0x06, 0x0f, 0x00, 0xc6, 0x09, 0x00, 0xc6, 0x3c, 
+        0x00, 0x06, 0x3d, 0x00, 0x46, 0x40, 0x00, 0x46, 0x08, 0x00, 0x46, 0x27, 0x00, 0x86, 0x27, 0x00, 
+        0x86, 0x3b, 0x00, 0x06, 0x27, 0x00, 0x46, 0x33, 0x00, 0x86, 0x33, 0x00, 0x86, 0x05, 0x00, 0x4d, 
+        0x0e, 0x62, 0xaf, 0xcc, 0xbd, 0x06, 0x5d, 0x06, 0x0d, 0x0b, 0xad, 0x04, 0x3d, 0x05, 0x4d, 0x0a, 
+        0x02, 0x41, 0x01, 0x06, 0x01, 0x00, 0x4d, 0x0e, 0x32, 0x41, 0x01, 0x0d, 0x03, 0x42, 0x41, 0x00, 
+        0xc6, 0xc0, 0xff, 0x01, 0x60, 0xff, 0x09, 0x11, 0x06, 0x8e, 0xff, 0x21, 0x5f, 0xff, 0x29, 0x11, 
+        0x06, 0x8c, 0xff, 0x31, 0x5e, 0xff, 0x39, 0x11, 0x06, 0x8a, 0xff, 0x41, 0x5d, 0xff, 0x49, 0x11, 
+        0x06, 0x88, 0xff, 0x51, 0x5c, 0xff, 0x59, 0x11, 0x06, 0x86, 0xff, 0x61, 0x5b, 0xff, 0x69, 0x11, 
+        0x06, 0x84, 0xff, 0x71, 0x5a, 0xff, 0x79, 0x11, 0x06, 0x82, 0xff, 0x81, 0x59, 0xff, 0x89, 0x11, 
+        0x06, 0x80, 0xff, 0x91, 0x58, 0xff, 0x99, 0x11, 0x06, 0x7e, 0xff, 0xa1, 0x57, 0xff, 0xa9, 0x11, 
+        0x06, 0x7c, 0xff, 0xb1, 0x56, 0xff, 0xb9, 0x11, 0x06, 0x7a, 0xff, 0x01, 0x55, 0xff, 0x09, 0x11, 
+        0x06, 0x78, 0xff, 0x21, 0x54, 0xff, 0x29, 0x11, 0x06, 0x76, 0xff, 0x6d, 0x03, 0xbd, 0x06, 0x3d, 
+        0x06, 0x9d, 0x0b, 0x4d, 0x0a, 0x92, 0x41, 0x01, 0xc6, 0xdf, 0xff, 0x0d, 0x0a, 0x32, 0xa0, 0x62, 
+        0x5c, 0xf4, 0x42, 0x41, 0x00, 0x32, 0x41, 0x01, 0xc6, 0x9e, 0xff, 0x62, 0x41, 0x00, 0x02, 0xaf, 
+        0xdf, 0x7c, 0x25, 0x52, 0x41, 0x01, 0x46, 0x9b, 0xff, 0x52, 0x41, 0x00, 0x02, 0xa0, 0x6f, 0x7c, 
+        0x96, 0x62, 0x41, 0x01, 0xc6, 0x97, 0xff, 0x5d, 0x06, 0x0d, 0x05, 0x3d, 0x05, 0x4d, 0x0e, 0x02, 
+        0x41, 0x01, 0x46, 0xd1, 0xff, 0x3d, 0x05, 0x9d, 0x03, 0x5d, 0x03, 0x0d, 0x09, 0xad, 0x04, 0x46, 
+        0xca, 0xff, 0x3d, 0x05, 0x9d, 0x03, 0x46, 0xea, 0xff, 0x5d, 0x06, 0x0d, 0x05, 0xc6, 0xc6, 0xff, 
+        0x32, 0x41, 0x00, 0x6c, 0xc0, 0x32, 0xaf, 0xc4, 0x06, 0x8a, 0xff, 0x32, 0x41, 0x00, 0xb2, 0x41, 
+        0x01, 0x4c, 0x80, 0x06, 0x88, 0xff, 0x32, 0x41, 0x00, 0x02, 0xaf, 0xa4, 0x4c, 0x17, 0x72, 0x41, 
+        0x01, 0x86, 0x84, 0xff, 0x0c, 0x00, 0x02, 0x41, 0x01, 0x32, 0x41, 0x00, 0xc6, 0x81, 0xff, 0x0d, 
+        0x06, 0x3d, 0x09, 0x82, 0xaf, 0xbe, 0x82, 0x41, 0x01, 0x06, 0xfb, 0xff, 0x92, 0x41, 0x00, 0x02, 
+        0xa0, 0x7c, 0x02, 0x41, 0x01, 0x0d, 0x04, 0x06, 0x7b, 0xff, 0x92, 0x41, 0x00, 0x1c, 0x34, 0xc6, 
+        0xfb, 0xff, 0x52, 0x41, 0x00, 0x42, 0x41, 0x01, 0x02, 0xaf, 0xcb, 0x06, 0x76, 0xff, 0x52, 0x41, 
+        0x00, 0xa2, 0x41, 0x01, 0x2c, 0x70, 0x46, 0x73, 0xff, 0x0d, 0x0b, 0x52, 0x41, 0x00, 0x3c, 0x49, 
+        0x92, 0x41, 0x01, 0x06, 0x70, 0xff, 0x00, 0x00, 0x6c, 0xf1, 0xfe, 0x3f, 0xe5, 0x43, 0x10, 0x40, 
+        0x60, 0x09, 0x00, 0x00, 0x08, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x81, 0xfb, 0xff, 0x9d, 
+        0x04, 0x12, 0xc1, 0xe0, 0xc9, 0x11, 0xe9, 0x31, 0xf9, 0x41, 0x09, 0x01, 0xd9, 0x21, 0x4d, 0x05, 
+        0xdd, 0x02, 0x22, 0x48, 0x0c, 0x5d, 0x06, 0x99, 0x51, 0x6d, 0x07, 0x72, 0x11, 0x10, 0x85, 0xc3, 
+        0xff, 0xfd, 0x02, 0x08, 0x51, 0x0c, 0xe9, 0x97, 0xbd, 0x34, 0xb1, 0xf0, 0xff, 0xd0, 0xad, 0x90, 
+        0xba, 0xaa, 0xa0, 0x0a, 0x00, 0x86, 0x09, 0x00, 0x86, 0x2a, 0x00, 0xc6, 0x44, 0x00, 0xc6, 0x41, 
+        0x00, 0xc6, 0x3e, 0x00, 0xc6, 0x3b, 0x00, 0xc6, 0x38, 0x00, 0xc6, 0x35, 0x00, 0xc6, 0x32, 0x00, 
+        0xc6, 0x2f, 0x00, 0xc6, 0x2c, 0x00, 0xc6, 0x29, 0x00, 0xc6, 0x26, 0x00, 0xc6, 0x23, 0x00, 0xc2, 
+        0xa0, 0x6a, 0xe2, 0xa1, 0x08, 0xbc, 0xf0, 0x01, 0x33, 0xf1, 0x21, 0xb3, 0xf3, 0xc0, 0x20, 0x00, 
+        0x22, 0x22, 0x9c, 0x17, 0xe2, 0x16, 0x22, 0xa0, 0x67, 0x01, 0x2e, 0xf1, 0x0c, 0x43, 0x08, 0x00, 
+        0x0c, 0x74, 0x02, 0x20, 0x26, 0x0c, 0x45, 0xc0, 0x00, 0x00, 0x01, 0x2a, 0xf1, 0xe0, 0x3f, 0x82, 
+        0x0c, 0x12, 0x08, 0x00, 0x41, 0xd7, 0xff, 0x02, 0x20, 0x1f, 0x40, 0x4e, 0xc1, 0xc0, 0x00, 0x00, 
+        0x0c, 0x52, 0x01, 0x9f, 0xf0, 0xc0, 0x00, 0x00, 0xf0, 0x3f, 0x20, 0xd0, 0x2d, 0x20, 0x71, 0xd2, 
+        0xff, 0x81, 0xd0, 0xff, 0x61, 0x91, 0xf2, 0x8a, 0x8c, 0xf0, 0x88, 0x01, 0xc0, 0x20, 0x00, 0x52, 
+        0x26, 0x45, 0x50, 0x50, 0xc4, 0x80, 0x55, 0x20, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 
+        0x45, 0x85, 0xae, 0xfd, 0xc5, 0xdc, 0xfd, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 
+        0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0xc2, 0xa2, 0xe1, 0xe2, 0xa1, 0x09, 0x46, 0xdd, 0xff, 0xc2, 
+        0xa0, 0xd1, 0xe2, 0xa1, 0x08, 0x06, 0xdb, 0xff, 0xc2, 0xa0, 0xfc, 0xe2, 0xa1, 0x08, 0xc6, 0xd8, 
+        0xff, 0xc2, 0xa1, 0x27, 0xe2, 0xa1, 0x02, 0x86, 0xd6, 0xff, 0xc2, 0xa1, 0x53, 0xe2, 0xa1, 0x01, 
+        0x46, 0xd4, 0xff, 0xc2, 0xa1, 0x7e, 0xe2, 0xa1, 0x08, 0x06, 0xd2, 0xff, 0xc2, 0xa1, 0xaa, 0xe2, 
+        0xa1, 0x1b, 0xc6, 0xcf, 0xff, 0xc2, 0xa1, 0xd6, 0xe2, 0xa0, 0xff, 0x86, 0xcd, 0xff, 0xc2, 0xa2, 
+        0x02, 0xe2, 0xa1, 0x0d, 0x46, 0xcb, 0xff, 0xc2, 0xa2, 0x2e, 0xe2, 0xa1, 0x09, 0x06, 0xc9, 0xff, 
+        0xc2, 0xa2, 0x5a, 0xe2, 0xa1, 0x09, 0xc6, 0xc6, 0xff, 0xc2, 0xa2, 0x87, 0xe2, 0xa1, 0x08, 0x86, 
+        0xc4, 0xff, 0xe2, 0xa1, 0x05, 0xc2, 0xa2, 0xb4, 0x46, 0xc2, 0xff, 0x00, 0x24, 0x85, 0xfe, 0x3f, 
+        0x42, 0xc2, 0xff, 0x12, 0xc1, 0xe0, 0x02, 0x61, 0x04, 0xd2, 0x61, 0x06, 0x00, 0x14, 0x40, 0xc9, 
+        0x51, 0x7c, 0xf4, 0xcd, 0x02, 0xdd, 0x03, 0x21, 0xad, 0xf3, 0x0c, 0x13, 0x00, 0x33, 0xa1, 0x40, 
+        0x33, 0x30, 0x08, 0x12, 0x4d, 0x0d, 0x30, 0x00, 0x10, 0x09, 0x12, 0x3d, 0x0c, 0x21, 0xf3, 0xff, 
+        0x01, 0x18, 0xf1, 0xc0, 0x00, 0x00, 0x5d, 0x0d, 0x2d, 0x0c, 0x0c, 0x04, 0x61, 0xa2, 0xf3, 0x31, 
+        0x38, 0xfa, 0x72, 0xa0, 0x64, 0x32, 0x03, 0x01, 0x79, 0x01, 0x4b, 0x76, 0xc5, 0xe4, 0xff, 0x2d, 
+        0x0c, 0x85, 0x98, 0xfd, 0xc8, 0x51, 0xd8, 0x61, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 
+        0xf6, 0xf1, 0xfe, 0x3f, 0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x06, 0x09, 0x51, 0xcd, 0x02, 0x45, 0xe0, 
+        0xfc, 0x0c, 0x04, 0x02, 0xa0, 0x64, 0x31, 0x2a, 0xfa, 0x51, 0xf9, 0xff, 0x29, 0x41, 0x61, 0x91, 
+        0xf3, 0x2d, 0x0c, 0x4b, 0x76, 0x52, 0x95, 0x00, 0x32, 0x03, 0x01, 0x09, 0x01, 0xc5, 0xe0, 0xff, 
+        0x2d, 0x0c, 0x85, 0x94, 0xfd, 0x28, 0x41, 0x85, 0xdb, 0xfc, 0xc8, 0x61, 0x08, 0x51, 0x12, 0xc1, 
+        0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1c, 
+        0xff, 0xff, 0xff, 0xcf, 0x00, 0x00, 0x00, 0x0c, 0x61, 0x65, 0xf3, 0x12, 0xc1, 0xf0, 0x09, 0x11, 
+        0x29, 0x01, 0xc9, 0x21, 0xd9, 0x31, 0x51, 0x5d, 0xef, 0xd1, 0x8d, 0xee, 0xc1, 0xc2, 0xf0, 0xc0, 
+        0x20, 0x00, 0x42, 0x25, 0xfa, 0x60, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x65, 0xfa, 0x31, 0x97, 
+        0xfb, 0xc0, 0x20, 0x00, 0x22, 0x2d, 0x44, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x0c, 0x23, 0x0c, 
+        0x04, 0x2c, 0x75, 0x08, 0x0c, 0x22, 0x6d, 0x44, 0x02, 0x20, 0x26, 0x22, 0xa0, 0x6a, 0xc0, 0x00, 
+        0x00, 0x08, 0x0c, 0x02, 0x20, 0x35, 0xc0, 0x00, 0x00, 0x21, 0xe6, 0xff, 0x31, 0x33, 0xf3, 0xc0, 
+        0x20, 0x00, 0x02, 0x2d, 0x44, 0x20, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x6d, 0x44, 0xb1, 0xe2, 
+        0xff, 0xa1, 0xe2, 0xff, 0xc0, 0x20, 0x00, 0x61, 0x45, 0xef, 0x92, 0x26, 0xe8, 0xb0, 0x99, 0x10, 
+        0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x66, 0xe8, 0x81, 0xdd, 0xff, 0x71, 0xa9, 0xf7, 0xc0, 
+        0x20, 0x00, 0x52, 0x26, 0xe6, 0x80, 0x55, 0x10, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 
+        0xe6, 0x7c, 0xd4, 0xc0, 0x20, 0x00, 0x22, 0x23, 0x9c, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 
+        0x63, 0x9c, 0x0c, 0x22, 0x01, 0x17, 0xf0, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x28, 0xc0, 
+        0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 0xa0, 0x81, 0xc0, 0x00, 
+        0x00, 0x31, 0xcc, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x2d, 0x44, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 
+        0x08, 0x0c, 0x02, 0x20, 0x32, 0x22, 0x6d, 0x44, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 
+        0x08, 0x0c, 0x0c, 0x04, 0x02, 0x20, 0x26, 0x2c, 0x45, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 
+        0x31, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x08, 0x0c, 0x0c, 0x04, 0x02, 0x20, 0x26, 
+        0x2c, 0x55, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x2f, 0xd8, 0x01, 0xc0, 0x00, 0x00, 0x62, 
+        0xa9, 0xff, 0x31, 0x8a, 0xee, 0xc0, 0x20, 0x00, 0x52, 0x23, 0xd0, 0x60, 0x55, 0x10, 0xc0, 0x20, 
+        0x00, 0x52, 0x63, 0xd0, 0x7c, 0x34, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xd0, 0x40, 0x22, 0x10, 0xc0, 
+        0x20, 0x00, 0x22, 0x63, 0xd0, 0x2d, 0x0d, 0xc5, 0xe6, 0xff, 0x08, 0x0c, 0x02, 0x20, 0x23, 0xc0, 
+        0x00, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x08, 0x0c, 0x0c, 0x14, 0x02, 0x20, 0x26, 0x4c, 0x85, 
+        0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x22, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6c, 0x0c, 0x23, 
+        0x0c, 0x04, 0x0c, 0x05, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x0c, 0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 
+        0x0c, 0x17, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x13, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 
+        0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 
+        0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 
+        0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x45, 
+        0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x1c, 0xa4, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 
+        0x00, 0x0c, 0x02, 0xc8, 0x21, 0xd8, 0x31, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x26, 0x42, 0x14, 0x26, 0xb2, 0x09, 0x1c, 0x23, 0x37, 0x12, 0x10, 0x1c, 0x44, 0x47, 0x12, 0x03, 
+        0x0c, 0x12, 0x0d, 0xf0, 0x0c, 0x32, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x0c, 0x22, 0x0d, 0xf0, 
+        0x8c, 0xf2, 0x26, 0x12, 0x05, 0x26, 0x22, 0x0e, 0x26, 0x32, 0x03, 0x1c, 0x02, 0x0d, 0xf0, 0x1c, 
+        0x42, 0x0d, 0xf0, 0x0c, 0x42, 0x0d, 0xf0, 0x1c, 0x22, 0x0d, 0xf0, 0x00, 0x12, 0x80, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xe0, 0x09, 0x21, 0xd9, 0x41, 0xe9, 0x51, 0xc9, 0x31, 0xed, 0x03, 0xcd, 0x02, 0xd1, 
+        0x35, 0xf0, 0x21, 0xfa, 0xff, 0x08, 0x0d, 0x22, 0x12, 0x00, 0x02, 0x20, 0x29, 0x20, 0x20, 0x44, 
+        0xc0, 0x00, 0x00, 0x0c, 0x12, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x1c, 0xf4, 0xc0, 0x00, 
+        0x00, 0x28, 0x0c, 0xc9, 0x11, 0x37, 0xf2, 0x4b, 0x0c, 0x0c, 0x2d, 0x0c, 0x05, 0xfa, 0xff, 0x42, 
+        0xa1, 0xf4, 0x0c, 0xc5, 0x6d, 0x01, 0x08, 0x0d, 0x3d, 0x02, 0x02, 0x20, 0x3a, 0x0c, 0x02, 0xc0, 
+        0x00, 0x00, 0x02, 0x01, 0x00, 0x22, 0x01, 0x01, 0x80, 0x00, 0x01, 0x80, 0x22, 0x01, 0x20, 0x28, 
+        0x31, 0x00, 0x08, 0x31, 0x80, 0x22, 0x11, 0x20, 0x00, 0x20, 0xe0, 0x2c, 0x90, 0x02, 0x52, 0x00, 
+        0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x4c, 0xc1, 0x48, 0x11, 0x51, 0xee, 0xee, 0x38, 0x04, 0x50, 
+        0x33, 0x20, 0x39, 0x04, 0x21, 0xde, 0xff, 0x3d, 0x01, 0x22, 0x12, 0x00, 0xc5, 0x0b, 0x00, 0x08, 
+        0x0d, 0x02, 0x20, 0x2a, 0xc0, 0x00, 0x00, 0xc8, 0x31, 0xd8, 0x41, 0xe8, 0x51, 0x08, 0x21, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0xf0, 0x00, 0xc0, 0xff, 0xff, 
+        0x80, 0x92, 0x11, 0x81, 0xfc, 0xff, 0x71, 0xa5, 0xee, 0xb1, 0xfb, 0xff, 0xa1, 0xfc, 0xff, 0x12, 
+        0xc1, 0xf0, 0xc9, 0x11, 0xe9, 0x31, 0x09, 0x01, 0xd9, 0x21, 0x0c, 0x00, 0x1c, 0x8d, 0x70, 0x50, 
+        0xa0, 0xc0, 0x20, 0x00, 0x42, 0x25, 0xc1, 0x80, 0x44, 0x10, 0x90, 0x44, 0x20, 0xc0, 0x20, 0x00, 
+        0x42, 0x65, 0xc1, 0x00, 0x21, 0x41, 0x70, 0x22, 0xa0, 0x62, 0x03, 0x01, 0x52, 0x03, 0x00, 0x80, 
+        0x66, 0x01, 0x80, 0x55, 0x01, 0x50, 0x58, 0x31, 0x60, 0x68, 0x31, 0x07, 0x60, 0x1d, 0x20, 0xe5, 
+        0x11, 0xb0, 0x46, 0x01, 0xc0, 0x20, 0x00, 0xc2, 0x22, 0x81, 0xb0, 0xcc, 0x10, 0x40, 0xcc, 0x20, 
+        0xe0, 0xcc, 0x20, 0xc0, 0x20, 0x00, 0xc2, 0x62, 0x81, 0xc6, 0x05, 0x00, 0x90, 0x46, 0x11, 0xc0, 
+        0x20, 0x00, 0xe2, 0x22, 0x81, 0xa0, 0xee, 0x10, 0x40, 0xee, 0x20, 0x50, 0xee, 0x20, 0xc0, 0x20, 
+        0x00, 0xe2, 0x62, 0x81, 0x1b, 0x00, 0x00, 0x00, 0x74, 0xd7, 0x90, 0x91, 0xc8, 0x11, 0xd8, 0x21, 
+        0xe8, 0x31, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x20, 0x44, 0x12, 
+        0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x03, 0x45, 0xe6, 0xff, 0x0c, 0x23, 0x01, 0xe1, 0xef, 
+        0x5d, 0x02, 0x61, 0x9e, 0xf2, 0x0c, 0x02, 0x60, 0x55, 0x90, 0x62, 0x15, 0x20, 0x62, 0x4c, 0x00, 
+        0x42, 0x0c, 0x00, 0x52, 0x15, 0x20, 0x80, 0x44, 0x01, 0x50, 0x58, 0x41, 0x52, 0x4c, 0x01, 0x08, 
+        0x00, 0x40, 0x48, 0x31, 0x02, 0x20, 0x2b, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x0c, 
+        0x23, 0x42, 0x0c, 0x01, 0x01, 0xd4, 0xef, 0x80, 0x44, 0x01, 0x08, 0x00, 0x40, 0x48, 0x31, 0x02, 
+        0x20, 0x2b, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0xe4, 0x0b, 0x00, 0x00, 0xe4, 0x09, 0x00, 0x00, 0xf2, 0x0f, 0x00, 0x00, 
+        0xf4, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0d, 0x00, 0x00, 0x47, 0xa2, 0x3c, 0x31, 
+        0xf9, 0xff, 0x20, 0x24, 0xc0, 0x4b, 0x22, 0x20, 0x22, 0x21, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 
+        0x26, 0x12, 0x55, 0x26, 0x22, 0x52, 0x31, 0xf4, 0xff, 0x26, 0x32, 0x47, 0x26, 0x42, 0x44, 0x32, 
+        0xa7, 0xe4, 0x26, 0x52, 0x3e, 0x26, 0x62, 0x3b, 0x32, 0xa5, 0xe4, 0x26, 0x72, 0x4b, 0x26, 0x82, 
+        0x48, 0x0c, 0x94, 0x47, 0x12, 0x48, 0x22, 0xa3, 0xe4, 0x86, 0x08, 0x00, 0x37, 0xa4, 0x22, 0x40, 
+        0x33, 0xc0, 0x4b, 0x33, 0x30, 0x32, 0x21, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0x26, 0x13, 0x23, 
+        0x26, 0x23, 0x1a, 0x21, 0xe6, 0xff, 0x26, 0x33, 0x05, 0x26, 0x43, 0x02, 0x21, 0xe5, 0xff, 0x22, 
+        0x55, 0x00, 0x0d, 0xf0, 0x2d, 0x03, 0x46, 0xfd, 0xff, 0x2d, 0x03, 0x06, 0xfc, 0xff, 0x21, 0xe1, 
+        0xff, 0x86, 0xfa, 0xff, 0x21, 0xe1, 0xff, 0x06, 0xf9, 0xff, 0x2d, 0x03, 0xc6, 0xf7, 0xff, 0x2d, 
+        0x03, 0x86, 0xf6, 0xff, 0x12, 0xc1, 0xe0, 0x29, 0x41, 0x09, 0x71, 0x2d, 0x01, 0x45, 0xd1, 0x00, 
+        0x0c, 0x33, 0x22, 0x11, 0x03, 0x92, 0x11, 0x05, 0x42, 0x11, 0x04, 0x82, 0x11, 0x07, 0x52, 0x11, 
+        0x06, 0x72, 0x11, 0x02, 0x01, 0x9c, 0xef, 0x62, 0x11, 0x01, 0x08, 0x00, 0x7a, 0x66, 0x8a, 0x55, 
+        0x9a, 0x44, 0x08, 0xe0, 0x40, 0x44, 0x90, 0x50, 0x55, 0x90, 0x6a, 0x22, 0x50, 0x22, 0xd0, 0x50, 
+        0x44, 0xc0, 0x00, 0x44, 0x11, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x40, 0x40, 0x31, 0x49, 0x51, 
+        0xc0, 0x00, 0x00, 0x01, 0x90, 0xef, 0x0c, 0x33, 0x08, 0x00, 0x29, 0x61, 0x08, 0xe0, 0x28, 0x51, 
+        0xc0, 0x00, 0x00, 0x38, 0x61, 0x08, 0x71, 0x20, 0x33, 0xc0, 0x28, 0x41, 0x12, 0xc1, 0x20, 0x3a, 
+        0x22, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x0b, 0x00, 0x00, 
+        0x15, 0xf2, 0xfe, 0x3f, 0xf8, 0xf1, 0xfe, 0x3f, 0x0c, 0x13, 0x5c, 0xf4, 0x21, 0xfc, 0xff, 0x12, 
+        0xc1, 0xe0, 0xc9, 0x61, 0x09, 0x51, 0xc1, 0x45, 0xff, 0x01, 0x7e, 0xef, 0x22, 0x5c, 0x00, 0x08, 
+        0x00, 0x22, 0x5c, 0x00, 0x02, 0x20, 0x2b, 0x0c, 0x72, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x01, 0x79, 
+        0xef, 0x0c, 0x13, 0x08, 0x00, 0x42, 0x1c, 0x00, 0x02, 0x20, 0x2b, 0x40, 0x40, 0x44, 0xc0, 0x00, 
+        0x00, 0x22, 0x1c, 0x00, 0x32, 0xc1, 0x10, 0x45, 0xe3, 0xff, 0x4c, 0x02, 0x31, 0xed, 0xff, 0x0c, 
+        0x14, 0x1c, 0xf5, 0x72, 0xc1, 0x12, 0x81, 0xeb, 0xff, 0x62, 0x1c, 0x00, 0x92, 0xa1, 0x38, 0x60, 
+        0x60, 0x44, 0x99, 0x01, 0x82, 0x08, 0x00, 0x89, 0x11, 0x45, 0x0f, 0x01, 0x0c, 0x15, 0x0c, 0x10, 
+        0x42, 0x01, 0x12, 0x2c, 0x06, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0xa6, 0xa4, 0x01, 0x0c, 0x05, 
+        0x47, 0x26, 0x01, 0x0c, 0x00, 0x50, 0x70, 0x20, 0xbc, 0x17, 0x2c, 0x02, 0x0c, 0xc3, 0x5d, 0x0c, 
+        0x85, 0xe6, 0xff, 0x0c, 0x72, 0x01, 0x5f, 0xef, 0x0c, 0x13, 0x08, 0x00, 0x42, 0x1c, 0x00, 0x02, 
+        0x20, 0x2b, 0x40, 0x45, 0x41, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x01, 0x5a, 0xef, 0x0c, 0x13, 0x08, 
+        0x00, 0x42, 0x1c, 0x00, 0x02, 0x20, 0x2b, 0x40, 0x40, 0x44, 0xc0, 0x00, 0x00, 0x22, 0x1c, 0x00, 
+        0x32, 0xc1, 0x10, 0x85, 0xdb, 0xff, 0x22, 0x1c, 0x00, 0x32, 0xc1, 0x10, 0x05, 0xd1, 0xff, 0xc8, 
+        0x61, 0x08, 0x51, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x0c, 0x05, 0x0c, 0x06, 0x0c, 0x07, 0x20, 0x40, 
+        0x74, 0x0c, 0x03, 0x12, 0xc1, 0xe0, 0xc9, 0x51, 0xd9, 0x61, 0x09, 0x41, 0xe9, 0x71, 0x39, 0x21, 
+        0x39, 0x11, 0xe1, 0x48, 0xef, 0x39, 0x01, 0x08, 0x0e, 0x0c, 0x12, 0x02, 0x20, 0x1a, 0x4c, 0x03, 
+        0xc0, 0x00, 0x00, 0x0c, 0x0d, 0x0c, 0x0c, 0x08, 0x0e, 0x08, 0xb0, 0x22, 0xa1, 0x38, 0xc0, 0x00, 
+        0x00, 0x1b, 0xdd, 0xca, 0xc2, 0x00, 0xcc, 0x11, 0xc0, 0xc0, 0x31, 0x66, 0x4d, 0xe8, 0x08, 0x0e, 
+        0x02, 0x20, 0x1b, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x08, 0x41, 0xd8, 0x61, 0x4b, 0x3c, 0xbb, 0x2c, 
+        0xe8, 0x71, 0xc8, 0x51, 0x30, 0x23, 0xb3, 0x20, 0x23, 0x21, 0x12, 0xc1, 0x20, 0x00, 0x22, 0x11, 
+        0x20, 0x20, 0x31, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x14, 0x1c, 0xf5, 0x82, 0xa1, 0x38, 0x61, 
+        0xf7, 0xfe, 0x12, 0xc1, 0xc0, 0xc9, 0x61, 0xe9, 0x81, 0xf9, 0x91, 0x72, 0xc1, 0x10, 0x09, 0x51, 
+        0xd9, 0x71, 0x01, 0xa8, 0xff, 0xdd, 0x02, 0x62, 0x16, 0x00, 0x4c, 0x02, 0x3d, 0x0d, 0x89, 0x01, 
+        0x60, 0x60, 0x44, 0x02, 0x00, 0x00, 0x09, 0x11, 0x45, 0xfe, 0x00, 0x0c, 0x0c, 0x0c, 0x00, 0xe2, 
+        0xa0, 0x6f, 0x7c, 0x97, 0x52, 0x0d, 0x05, 0x32, 0x0d, 0x00, 0x42, 0x01, 0x10, 0x0c, 0x09, 0x99, 
+        0xb1, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x50, 0x33, 0xc0, 0x00, 0x33, 0x11, 0x42, 0xc4, 0x1f, 
+        0x42, 0x41, 0x10, 0x30, 0x30, 0x31, 0x70, 0x73, 0x90, 0x79, 0xa1, 0x42, 0x01, 0x10, 0x2d, 0x0e, 
+        0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x0a, 0x04, 0x02, 0x41, 0x10, 0x0a, 0xd3, 0x80, 0x00, 0x01, 
+        0x00, 0x08, 0x31, 0x07, 0x2e, 0x01, 0x2d, 0x00, 0x22, 0x41, 0x10, 0x39, 0xe1, 0x85, 0xf0, 0xff, 
+        0x80, 0x5d, 0x01, 0xfd, 0x02, 0x0c, 0x1d, 0x50, 0x58, 0x31, 0x59, 0xd1, 0x57, 0x2e, 0x01, 0x0c, 
+        0x0d, 0x28, 0xd1, 0xd0, 0x2e, 0x93, 0x05, 0xef, 0xff, 0x78, 0xa1, 0x38, 0xc1, 0x20, 0x6f, 0xc0, 
+        0x00, 0x06, 0x11, 0x00, 0x00, 0x31, 0xc0, 0x32, 0x83, 0x39, 0xc1, 0x77, 0x20, 0x05, 0x42, 0xa0, 
+        0xa8, 0xf7, 0xa4, 0x51, 0x8c, 0xec, 0x58, 0xb1, 0x2c, 0xc7, 0x07, 0x25, 0x08, 0x77, 0x20, 0x05, 
+        0x82, 0xa0, 0xa8, 0xf7, 0xa8, 0x3f, 0x38, 0xe1, 0x5c, 0x09, 0x97, 0x22, 0x38, 0xa8, 0xd1, 0x0c, 
+        0x2b, 0xd0, 0xae, 0x93, 0xe7, 0x1a, 0x2e, 0x2b, 0x70, 0x1b, 0x80, 0x1b, 0xcc, 0x00, 0xd6, 0x11, 
+        0xd0, 0xd0, 0x31, 0xc0, 0xc0, 0x74, 0x0d, 0x0b, 0x92, 0xcc, 0xf6, 0x80, 0x78, 0xb3, 0x70, 0x71, 
+        0x21, 0x70, 0x73, 0xc0, 0x0b, 0x77, 0x80, 0x77, 0x01, 0x70, 0x78, 0x31, 0xa6, 0x27, 0x01, 0x0d, 
+        0x07, 0xd9, 0xb1, 0x56, 0x49, 0xf5, 0x08, 0x51, 0xc8, 0x61, 0xd8, 0x71, 0xe8, 0x81, 0x38, 0xc1, 
+        0xf8, 0x91, 0x20, 0x23, 0xc0, 0x1b, 0x32, 0x2b, 0x22, 0x30, 0x23, 0xb3, 0x12, 0xc1, 0x40, 0x20, 
+        0x21, 0x21, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x0d, 0xf0, 0x00, 0x00, 0xad, 0x06, 0xbd, 0x05, 
+        0x9d, 0x03, 0x82, 0xaf, 0x79, 0x12, 0xc1, 0xd0, 0xf9, 0x81, 0x09, 0x41, 0xd9, 0x61, 0xc9, 0x51, 
+        0xe9, 0x71, 0xcd, 0x02, 0xed, 0x04, 0xd2, 0xd1, 0xff, 0x0c, 0x04, 0xd2, 0xcd, 0x7d, 0xda, 0x24, 
+        0x16, 0x34, 0x05, 0x26, 0x14, 0x4a, 0x26, 0x24, 0x41, 0x26, 0x34, 0x38, 0x26, 0x44, 0x24, 0x26, 
+        0x54, 0x1b, 0x26, 0x64, 0x12, 0x26, 0x74, 0x09, 0x4a, 0x0c, 0x8a, 0x00, 0x02, 0x00, 0x7f, 0x06, 
+        0x05, 0x00, 0x02, 0x0c, 0x00, 0x86, 0x03, 0x00, 0x02, 0x0c, 0x02, 0x06, 0x02, 0x00, 0x02, 0x0c, 
+        0x04, 0x86, 0x00, 0x00, 0x02, 0x0c, 0x06, 0x02, 0x42, 0x83, 0x1b, 0x44, 0x40, 0x40, 0x74, 0x66, 
+        0xb4, 0xbb, 0xc6, 0x05, 0x00, 0x02, 0x0c, 0x00, 0xc6, 0xfa, 0xff, 0x02, 0x0c, 0x01, 0x46, 0xf9, 
+        0xff, 0x02, 0x0c, 0x03, 0xc6, 0xf7, 0xff, 0x02, 0x0c, 0x05, 0x46, 0xf6, 0xff, 0x22, 0xa0, 0x77, 
+        0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x0c, 0x06, 0x0c, 0x07, 0x01, 0xc2, 0xee, 0x99, 0x91, 0x08, 
+        0x00, 0xa9, 0xa1, 0x02, 0x20, 0x27, 0xb9, 0xb1, 0xc0, 0x00, 0x00, 0x28, 0xa1, 0x38, 0x91, 0x0c, 
+        0x04, 0x1c, 0x8b, 0x61, 0x56, 0xed, 0xa2, 0xaf, 0x00, 0x08, 0xb1, 0xf1, 0x67, 0xfd, 0x8c, 0xa0, 
+        0x26, 0x24, 0x25, 0x26, 0x34, 0x22, 0x26, 0x64, 0x1f, 0x26, 0x74, 0x1c, 0x0c, 0x05, 0x60, 0x84, 
+        0xa0, 0xf6, 0x84, 0x2e, 0x80, 0x75, 0x01, 0x52, 0x0c, 0x00, 0x70, 0x78, 0x31, 0x7a, 0x55, 0x5a, 
+        0x5e, 0x52, 0x05, 0x00, 0x3a, 0x55, 0x86, 0x0b, 0x00, 0x51, 0x01, 0xf8, 0x92, 0x0f, 0x0c, 0x82, 
+        0x05, 0x4e, 0x80, 0x99, 0x01, 0x52, 0x05, 0x4d, 0x90, 0x98, 0x31, 0xe6, 0x79, 0xcf, 0x5d, 0x08, 
+        0x86, 0xf2, 0xff, 0xda, 0x54, 0x52, 0x05, 0x7b, 0xea, 0x55, 0x52, 0x05, 0x00, 0x80, 0x55, 0x01, 
+        0x50, 0x58, 0x31, 0x27, 0xa5, 0x01, 0x5d, 0x02, 0x50, 0x90, 0x60, 0x90, 0x90, 0x74, 0xc0, 0x20, 
+        0x00, 0x72, 0x28, 0xc1, 0xa0, 0x77, 0x10, 0x90, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x68, 0xc1, 
+        0x1b, 0x44, 0x40, 0x40, 0x74, 0xb7, 0x94, 0x85, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 
+        0x08, 0x41, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0xf0, 
+        0xff, 0xff, 0xff, 0xf0, 0x91, 0xfe, 0xff, 0x60, 0x82, 0x01, 0x12, 0xc1, 0xf0, 0x72, 0xa1, 0x00, 
+        0x30, 0x77, 0xc0, 0x69, 0x11, 0x59, 0x01, 0xc9, 0x31, 0x09, 0x21, 0xcd, 0x02, 0x01, 0x8d, 0xee, 
+        0x51, 0x27, 0xed, 0x61, 0xf5, 0xff, 0x70, 0x70, 0x74, 0x60, 0x77, 0x11, 0x60, 0x64, 0x20, 0xc0, 
+        0x20, 0x00, 0x22, 0x25, 0xee, 0x90, 0x22, 0x10, 0x80, 0x22, 0x20, 0x70, 0x22, 0x20, 0x60, 0x22, 
+        0x20, 0xc0, 0x20, 0x00, 0x0c, 0xa3, 0x08, 0x00, 0x22, 0x65, 0xee, 0x02, 0x20, 0x1c, 0x0c, 0x42, 
+        0xc0, 0x00, 0x00, 0xd0, 0x5c, 0x11, 0xc0, 0x70, 0x04, 0x0c, 0x16, 0x88, 0x01, 0x0c, 0x04, 0x22, 
+        0x58, 0x00, 0x70, 0x46, 0x83, 0x50, 0x44, 0x20, 0x80, 0x44, 0x01, 0x51, 0xe5, 0xff, 0xc0, 0x20, 
+        0x00, 0x31, 0x12, 0xed, 0x22, 0x23, 0xee, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 
+        0x01, 0x75, 0xee, 0x08, 0x00, 0x22, 0x63, 0xee, 0x0c, 0x42, 0x02, 0x20, 0x1c, 0x0c, 0xa3, 0xc0, 
+        0x00, 0x00, 0x08, 0x21, 0x98, 0x11, 0xc8, 0x31, 0x22, 0x59, 0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0xe8, 0xef, 0xfe, 0x3f, 0x44, 0x85, 0xfe, 0x3f, 0x9d, 0x03, 0x0c, 0x0b, 0x12, 0xc1, 0xb0, 0x69, 
+        0x91, 0x52, 0x61, 0x10, 0xf9, 0x61, 0x29, 0xc1, 0x09, 0x21, 0xc9, 0x31, 0xd9, 0x41, 0xe9, 0x51, 
+        0xdd, 0x04, 0x0c, 0x0e, 0x0c, 0x0c, 0xb9, 0xe1, 0x99, 0x11, 0x0c, 0x00, 0x0c, 0x02, 0xf2, 0x21, 
+        0x10, 0x38, 0xc1, 0x29, 0xf1, 0x09, 0xd1, 0x0c, 0x72, 0x0c, 0x30, 0x32, 0xc3, 0xf4, 0x70, 0x02, 
+        0x93, 0x30, 0x30, 0x74, 0x39, 0xb1, 0x09, 0xa1, 0xf6, 0x3c, 0x45, 0x4d, 0x0f, 0x01, 0x59, 0xee, 
+        0x32, 0xa0, 0x80, 0xe0, 0x2e, 0xd1, 0x3a, 0x22, 0x08, 0x00, 0x38, 0xf1, 0x20, 0x28, 0x21, 0x29, 
+        0x81, 0x02, 0x20, 0x42, 0x3a, 0x22, 0x0c, 0x13, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0xc0, 0x00, 
+        0x00, 0x4d, 0x0f, 0x38, 0x81, 0x01, 0x4f, 0xee, 0x30, 0x32, 0xc0, 0x08, 0x00, 0x2d, 0x0e, 0x80, 
+        0x33, 0x01, 0x30, 0x38, 0x31, 0x39, 0xf1, 0x02, 0x20, 0x42, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0xed, 
+        0x02, 0x22, 0xa0, 0x01, 0x32, 0x21, 0x0b, 0x48, 0x11, 0x5d, 0x01, 0x2b, 0x61, 0x45, 0xec, 0xff, 
+        0x72, 0x91, 0x01, 0x52, 0x91, 0x00, 0x0d, 0x07, 0x77, 0xa5, 0x01, 0x0d, 0x05, 0x0c, 0x14, 0x00, 
+        0x30, 0x11, 0x50, 0x27, 0xc0, 0x50, 0x22, 0x11, 0x30, 0x30, 0x31, 0x00, 0x34, 0x83, 0x05, 0xfa, 
+        0x04, 0x02, 0xc2, 0x10, 0x00, 0x05, 0x21, 0x02, 0x4d, 0x00, 0x8c, 0x9f, 0x28, 0xf1, 0xd6, 0x52, 
+        0x00, 0x00, 0x30, 0x60, 0x32, 0x4d, 0x00, 0x0c, 0x02, 0x38, 0xc1, 0x48, 0x11, 0x5d, 0x01, 0x2b, 
+        0x61, 0x05, 0xe8, 0xff, 0x22, 0x91, 0x00, 0x42, 0x91, 0x01, 0x2a, 0x34, 0x40, 0x22, 0xc0, 0x40, 
+        0x22, 0x11, 0xc5, 0xf6, 0x04, 0x52, 0xc2, 0x10, 0x50, 0x55, 0x21, 0x52, 0x4d, 0x01, 0x8c, 0x7f, 
+        0xd6, 0x5e, 0x00, 0x50, 0x50, 0x60, 0x52, 0x4d, 0x01, 0x02, 0x0d, 0x00, 0x28, 0xf1, 0x80, 0x00, 
+        0x01, 0x00, 0x08, 0x31, 0xf6, 0x3c, 0x16, 0x50, 0xee, 0xc0, 0x00, 0x32, 0xc0, 0x80, 0x33, 0x01, 
+        0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x30, 0x28, 0x31, 0x29, 0xf1, 0x46, 0x1a, 0x00, 0x28, 0xd1, 
+        0x48, 0xe1, 0x2a, 0x35, 0x4a, 0x60, 0x80, 0x66, 0x01, 0x80, 0x33, 0x01, 0x30, 0x28, 0x31, 0x60, 
+        0x48, 0x31, 0x49, 0xe1, 0x29, 0xd1, 0x66, 0x6c, 0x4e, 0x38, 0xf1, 0x28, 0xe1, 0x01, 0x19, 0xee, 
+        0x2b, 0x22, 0x08, 0x00, 0x20, 0x22, 0x21, 0x20, 0x43, 0xc0, 0x80, 0x44, 0x01, 0x40, 0x38, 0x31, 
+        0x39, 0xf1, 0x38, 0xd1, 0x08, 0x00, 0x2b, 0x33, 0x30, 0x32, 0x21, 0x39, 0x71, 0x30, 0xee, 0xc0, 
+        0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0xc0, 0x00, 0x00, 0xe6, 0x52, 0x0e, 0x01, 0x0e, 0xee, 0x08, 
+        0x00, 0x08, 0x00, 0x28, 0x71, 0xc0, 0x00, 0x00, 0xa6, 0x52, 0x0c, 0x31, 0x9d, 0xff, 0x41, 0x54, 
+        0xf6, 0x28, 0x03, 0x40, 0x22, 0x20, 0x29, 0x03, 0x58, 0x91, 0x9c, 0x95, 0x21, 0x9a, 0xff, 0x42, 
+        0x0d, 0x01, 0x32, 0x0d, 0x00, 0x80, 0x44, 0x01, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0x40, 0x48, 
+        0x31, 0x01, 0xe3, 0xeb, 0xc0, 0x00, 0x00, 0x58, 0xa1, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0xc0, 0x55, 
+        0xc0, 0x56, 0x35, 0xe8, 0x0c, 0x13, 0x4d, 0x0f, 0x01, 0xfb, 0xed, 0x28, 0xf1, 0x08, 0x00, 0x80, 
+        0x22, 0x01, 0x02, 0x20, 0x42, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 0x4d, 0x0f, 0x01, 0xf5, 0xed, 
+        0x0c, 0x03, 0x08, 0x00, 0x80, 0x2e, 0x01, 0x02, 0x20, 0x42, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 
+        0x08, 0x21, 0xc8, 0x31, 0xf8, 0x61, 0xe2, 0x4d, 0x01, 0x28, 0xf1, 0x22, 0x4d, 0x00, 0xe8, 0x51, 
+        0xd8, 0x41, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0x00, 0x50, 0x85, 0xfe, 0x3f, 0xff, 0xff, 0x00, 0xe0, 
+        0x30, 0x93, 0x20, 0x12, 0xc1, 0xc0, 0xc2, 0x61, 0x0a, 0xf2, 0x61, 0x0d, 0x59, 0xf1, 0x69, 0x41, 
+        0x49, 0x31, 0x79, 0x11, 0x09, 0x91, 0xd9, 0xb1, 0xe9, 0xc1, 0xdd, 0x02, 0xe1, 0x81, 0xf3, 0x08, 
+        0x02, 0x99, 0x21, 0x00, 0x01, 0x05, 0x56, 0x60, 0x1c, 0xf8, 0xf1, 0x22, 0xa0, 0x77, 0x0c, 0x03, 
+        0xc1, 0xdd, 0xed, 0x1c, 0x04, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x25, 0x0c, 0x06, 0xc0, 0x00, 
+        0x00, 0x0c, 0x03, 0x0c, 0xf4, 0x0c, 0x65, 0x0c, 0x66, 0x08, 0x0c, 0x29, 0x61, 0x02, 0x20, 0x25, 
+        0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x0c, 0x06, 0x08, 0x0c, 
+        0x29, 0x71, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x28, 
+        0x29, 0x81, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x30, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x28, 
+        0x31, 0x20, 0x20, 0xb4, 0x45, 0x59, 0xfe, 0x28, 0x31, 0x3d, 0x01, 0x05, 0x78, 0xff, 0x08, 0x0c, 
+        0x08, 0x60, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x08, 0xf0, 0x0c, 0x12, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 
+        0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 0x25, 0x08, 0x0c, 
+        0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x28, 0x41, 0x72, 0x01, 0x44, 0x3d, 
+        0x0f, 0x2b, 0x41, 0xf2, 0x01, 0x40, 0x58, 0x11, 0x6d, 0x0f, 0xc5, 0xd1, 0xff, 0x08, 0x0c, 0x02, 
+        0x20, 0x1b, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 0x05, 
+        0x0c, 0x06, 0x08, 0x0c, 0x78, 0x61, 0x02, 0x20, 0x27, 0x79, 0x51, 0xc0, 0x00, 0x00, 0x78, 0x71, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0xf4, 0x08, 0x0c, 0x0c, 0x65, 0x02, 0x20, 0x27, 0x0c, 0x66, 
+        0xc0, 0x00, 0x00, 0x78, 0x81, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x94, 0x08, 0x0c, 0x0c, 0x75, 
+        0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 
+        0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x58, 0x11, 0x2c, 
+        0x03, 0x21, 0x09, 0xef, 0xc0, 0x20, 0x00, 0x08, 0xa2, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x09, 
+        0xa2, 0x0c, 0x2a, 0x7c, 0x0b, 0xc0, 0x20, 0x00, 0x92, 0x2e, 0x8f, 0xb0, 0x99, 0x10, 0xa0, 0x99, 
+        0x20, 0xc0, 0x20, 0x00, 0x92, 0x6e, 0x8f, 0x0c, 0x17, 0x82, 0xae, 0x0e, 0xc0, 0x20, 0x00, 0x62, 
+        0x2e, 0x99, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x0c, 0xf2, 0x62, 0x6e, 0x99, 
+        0x42, 0x01, 0x02, 0x7c, 0x10, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x07, 0x24, 0x01, 0x0d, 0x04, 
+        0x42, 0x01, 0x03, 0x07, 0x22, 0x01, 0x2d, 0x00, 0x6c, 0x10, 0x22, 0x41, 0x02, 0x80, 0x44, 0x01, 
+        0x80, 0x32, 0x01, 0x30, 0x38, 0x31, 0x40, 0x48, 0x31, 0x1c, 0xf2, 0x07, 0x24, 0x01, 0x0d, 0x04, 
+        0x07, 0x22, 0x01, 0x2d, 0x00, 0x22, 0x41, 0x03, 0x80, 0x42, 0x01, 0x40, 0x48, 0x31, 0x8c, 0xe5, 
+        0x58, 0x51, 0x8c, 0xa5, 0x30, 0x30, 0x60, 0x32, 0x41, 0x02, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 
+        0x8c, 0xdf, 0x21, 0x89, 0xff, 0x01, 0x56, 0xeb, 0xc0, 0x00, 0x00, 0x42, 0x01, 0x03, 0x32, 0x01, 
+        0x02, 0x80, 0xf3, 0x01, 0xf0, 0xf8, 0x31, 0x77, 0x63, 0x44, 0xf2, 0xc3, 0x20, 0x86, 0x0f, 0x00, 
+        0xc2, 0x13, 0x00, 0xc0, 0xf8, 0x41, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 0x31, 0x80, 0x0f, 0x01, 0x21, 
+        0xdb, 0xee, 0xe0, 0xfc, 0x01, 0x20, 0xff, 0x20, 0x21, 0x7d, 0xff, 0xc0, 0x20, 0x00, 0xd2, 0x2e, 
+        0x98, 0x20, 0xdd, 0x10, 0x00, 0xdd, 0x20, 0xf0, 0xdd, 0x20, 0xc0, 0x20, 0x00, 0xc8, 0xa1, 0xd2, 
+        0x6e, 0x98, 0xf8, 0xd1, 0xd8, 0xb1, 0xe8, 0xc1, 0x08, 0x91, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 0x80, 
+        0x04, 0x01, 0x00, 0x08, 0x31, 0x77, 0x64, 0x07, 0x22, 0xc4, 0x40, 0x29, 0xe1, 0x46, 0x00, 0x00, 
+        0x09, 0xe1, 0x08, 0x0c, 0xc8, 0xe1, 0x02, 0x20, 0x2a, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 0x31, 0xc0, 
+        0x00, 0x00, 0x21, 0x65, 0xec, 0x08, 0x0d, 0x38, 0xe1, 0x80, 0x4f, 0x11, 0x80, 0x33, 0x01, 0x30, 
+        0x38, 0x31, 0x40, 0x33, 0x20, 0x48, 0x21, 0x20, 0x00, 0x20, 0x32, 0x54, 0x00, 0x09, 0x0d, 0x46, 
+        0xe2, 0xff, 0x00, 0x00, 0x2b, 0x64, 0x82, 0x93, 0x00, 0x00, 0x04, 0x40, 0x80, 0x90, 0xb1, 0x90, 
+        0x88, 0xc0, 0x00, 0x16, 0x40, 0x8a, 0x82, 0x00, 0x25, 0xa1, 0x00, 0x88, 0x11, 0x80, 0x80, 0x31, 
+        0x82, 0x53, 0x00, 0x27, 0x28, 0x11, 0x20, 0x48, 0xc0, 0x80, 0x25, 0x01, 0x20, 0x28, 0x31, 0x42, 
+        0x53, 0x00, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x20, 0x40, 0x60, 0x87, 0x24, 0xf5, 0x2a, 0x48, 
+        0x50, 0x20, 0x60, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0x86, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x01, 
+        0xa1, 0xf7, 0xef, 0x12, 0xc1, 0xf0, 0xd9, 0x21, 0xe9, 0x31, 0xc9, 0x11, 0x09, 0x01, 0xc1, 0x35, 
+        0xed, 0x08, 0x1a, 0xe1, 0xe1, 0xfb, 0x77, 0xf0, 0x35, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x0c, 0x04, 
+        0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x91, 0x80, 
+        0xf6, 0xa8, 0x0c, 0x22, 0x09, 0x01, 0xa2, 0x2a, 0x27, 0x16, 0xd2, 0x04, 0x22, 0xa0, 0x6a, 0x0c, 
+        0x23, 0x0c, 0x44, 0x0c, 0x75, 0x0c, 0x46, 0x0c, 0x17, 0xc0, 0x0a, 0x00, 0x86, 0x12, 0x00, 0xd2, 
+        0x0e, 0x02, 0x22, 0xa0, 0x61, 0x0c, 0x13, 0x0c, 0x24, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x06, 0x02, 
+        0x20, 0x27, 0x7d, 0x0d, 0xc0, 0x00, 0x00, 0x72, 0x0e, 0x03, 0x22, 0xa0, 0x66, 0x0c, 0x33, 0x0c, 
+        0x14, 0x08, 0x0c, 0x0c, 0x55, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0xd8, 
+        0x21, 0xe8, 0x31, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x0c, 
+        0x44, 0x0c, 0x75, 0x0c, 0x46, 0x0c, 0x27, 0xc0, 0x0a, 0x00, 0x22, 0xa0, 0x68, 0x0c, 0x33, 0x0c, 
+        0x14, 0x0c, 0x05, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 
+        0xa0, 0x6a, 0x0c, 0x23, 0x0c, 0x64, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 
+        0x87, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x0c, 0x44, 0x0c, 0x05, 0x08, 0x0c, 0x0c, 
+        0x06, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x0c, 0x34, 
+        0x0c, 0x65, 0x08, 0x0c, 0x0c, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 
+        0x6a, 0x0c, 0x23, 0x0c, 0x44, 0x0c, 0x35, 0x08, 0x0c, 0x0c, 0x36, 0x02, 0x20, 0x27, 0x0c, 0x07, 
+        0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x0c, 0x44, 0x0c, 0x35, 0x08, 0x0c, 0x0c, 0x36, 
+        0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x64, 0x01, 0x6d, 0xec, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x0c, 0x54, 0x08, 0x0c, 0x0c, 0x55, 0x02, 0x20, 0x25, 0x0c, 
+        0x06, 0xc0, 0x00, 0x00, 0x0c, 0x33, 0x0c, 0x14, 0x0c, 0x05, 0x0c, 0x06, 0x0c, 0x07, 0x08, 0x0c, 
+        0xdd, 0x02, 0x02, 0x20, 0x27, 0x22, 0xa0, 0x68, 0xc0, 0x00, 0x00, 0x01, 0x39, 0xf6, 0x41, 0x78, 
+        0xfe, 0x62, 0x00, 0x01, 0xb6, 0x3d, 0x04, 0x3c, 0xc2, 0xd7, 0xb2, 0x09, 0x51, 0xa8, 0xff, 0x38, 
+        0x04, 0x50, 0x33, 0x20, 0x39, 0x04, 0x16, 0xa6, 0x03, 0x32, 0xa0, 0x1e, 0xc0, 0x2d, 0x11, 0x22, 
+        0xc2, 0xd9, 0xc5, 0xa1, 0x04, 0xd0, 0x3d, 0xf0, 0x20, 0xd0, 0x74, 0xd2, 0x4e, 0x02, 0xe0, 0x23, 
+        0x11, 0x20, 0x20, 0xf4, 0x0c, 0x93, 0xc5, 0xab, 0x04, 0x71, 0x02, 0xed, 0x61, 0x94, 0xef, 0x20, 
+        0x40, 0x74, 0x2b, 0x44, 0x58, 0x16, 0x40, 0x42, 0x21, 0x42, 0x4e, 0x03, 0x70, 0x55, 0x20, 0x59, 
+        0x16, 0x46, 0xab, 0xff, 0x1c, 0x43, 0xd0, 0x2d, 0xa0, 0xd0, 0x22, 0x90, 0x22, 0xc2, 0xf2, 0x05, 
+        0x9e, 0x04, 0xc6, 0xef, 0xff, 0x00, 0x00, 0x00, 0x70, 0x85, 0xfe, 0x3f, 0x78, 0x85, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xc0, 0xc9, 0x71, 0xe9, 0x91, 0x69, 0x51, 0x79, 0xd1, 0x49, 0xc1, 0x59, 0x41, 0x09, 
+        0x61, 0x29, 0xb1, 0xd9, 0x81, 0xf9, 0xa1, 0xdd, 0x03, 0xfd, 0x07, 0x22, 0xa1, 0x38, 0x45, 0x47, 
+        0xff, 0xcd, 0x02, 0xb2, 0xaf, 0x7a, 0xe2, 0x01, 0x40, 0xac, 0x7f, 0xb6, 0x8e, 0x09, 0xea, 0x0d, 
+        0xba, 0x00, 0x02, 0x00, 0x7f, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x21, 0xef, 0xff, 0x58, 0xb1, 0x3d, 
+        0x0e, 0x5a, 0x50, 0x52, 0x05, 0x00, 0x4d, 0x0c, 0xe0, 0x55, 0x11, 0x01, 0x99, 0xea, 0xc0, 0x00, 
+        0x00, 0xb2, 0xaf, 0x7a, 0xb6, 0x8e, 0x09, 0xea, 0x0d, 0xba, 0x00, 0x02, 0x00, 0x7f, 0x46, 0x00, 
+        0x00, 0x0c, 0x00, 0x38, 0x41, 0x28, 0xb1, 0x0c, 0x44, 0x2a, 0x20, 0x22, 0x02, 0x00, 0x0c, 0x15, 
+        0xe0, 0x22, 0x11, 0x20, 0x2c, 0xc0, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x29, 0x21, 0x45, 0xd7, 
+        0xff, 0xcd, 0x02, 0xd9, 0x31, 0x9c, 0x2f, 0x38, 0x21, 0x21, 0xdb, 0xff, 0x48, 0x41, 0x5d, 0x0c, 
+        0x42, 0x94, 0x00, 0x01, 0x87, 0xea, 0xc0, 0x00, 0x00, 0xd9, 0x31, 0x58, 0x51, 0xd1, 0x3b, 0xeb, 
+        0x16, 0x75, 0x04, 0x16, 0x4c, 0x04, 0x6d, 0x01, 0x0c, 0x04, 0x08, 0xc1, 0xd0, 0xa4, 0xa0, 0x6a, 
+        0xb4, 0xc0, 0x20, 0x00, 0x1b, 0x94, 0x4a, 0x80, 0xa2, 0x2a, 0xd3, 0xa2, 0x4b, 0x00, 0xc0, 0xaa, 
+        0xc0, 0xa2, 0x4b, 0x00, 0x72, 0x08, 0x00, 0x90, 0x40, 0x74, 0xc0, 0x77, 0xc0, 0x72, 0x48, 0x00, 
+        0x66, 0x64, 0xd8, 0x28, 0x31, 0x0c, 0xd3, 0x51, 0x40, 0xfb, 0x4d, 0x01, 0x62, 0x05, 0x2c, 0x52, 
+        0x05, 0x2d, 0x80, 0x66, 0x01, 0x60, 0x68, 0x31, 0x05, 0x6a, 0xff, 0x9c, 0x3f, 0xd0, 0x3e, 0xa0, 
+        0x21, 0xc3, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x23, 0xc1, 0x30, 0x30, 0x74, 0x01, 0x6d, 0xea, 0xc0, 
+        0x00, 0x00, 0xc8, 0x71, 0xd8, 0x81, 0xe8, 0x91, 0xf8, 0xa1, 0x08, 0x61, 0x12, 0xc1, 0x40, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0x09, 0x41, 0x51, 0x8c, 0xea, 0xc0, 0x20, 0x00, 0x02, 
+        0x25, 0xd8, 0x00, 0x08, 0x45, 0xc0, 0x20, 0x00, 0x52, 0x25, 0xd4, 0xf7, 0xf5, 0x7c, 0x09, 0x01, 
+        0x7d, 0x04, 0x5d, 0x02, 0x6d, 0x03, 0x21, 0xaa, 0xef, 0x31, 0xfc, 0xef, 0x41, 0xaa, 0xef, 0x05, 
+        0xec, 0xff, 0x61, 0xeb, 0xf8, 0x7c, 0xea, 0xc0, 0x20, 0x00, 0x71, 0x80, 0xea, 0x52, 0x27, 0xd7, 
+        0x60, 0x55, 0x10, 0xc0, 0x20, 0x00, 0x52, 0x67, 0xd7, 0x41, 0xba, 0xf8, 0xc0, 0x20, 0x00, 0x32, 
+        0x27, 0xd7, 0x40, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x67, 0xd7, 0xc0, 0x20, 0x00, 0x22, 0x27, 
+        0xd4, 0xa0, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 0x67, 0xd4, 0x0c, 0x20, 0xc0, 0x20, 0x00, 0xb2, 
+        0x27, 0xd8, 0x00, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x67, 0xd8, 0xc0, 0x20, 0x00, 0x92, 0x27, 
+        0xd8, 0xa0, 0x99, 0x10, 0xc0, 0x20, 0x00, 0x92, 0x67, 0xd8, 0xc0, 0x20, 0x00, 0x62, 0x27, 0xd8, 
+        0x0c, 0x18, 0x80, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x67, 0xd8, 0x08, 0x41, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x00, 0x00, 0x91, 0x66, 0xea, 0x81, 0xd3, 0xeb, 0x0c, 0x0b, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x11, 0x09, 0x01, 0xd9, 0x21, 0x0c, 0x00, 0xd2, 0xa0, 0xff, 0x7c, 0xfc, 0x90, 0x60, 0xa0, 0x20, 
+        0x70, 0x90, 0x5d, 0x0d, 0xad, 0x0b, 0xc0, 0x20, 0x00, 0x32, 0xa1, 0x17, 0x62, 0x26, 0xe0, 0x1b, 
+        0x00, 0x00, 0x00, 0x74, 0xc0, 0x66, 0x30, 0x60, 0x40, 0x74, 0x42, 0xc4, 0xeb, 0x60, 0x60, 0xa4, 
+        0x62, 0x57, 0x00, 0x40, 0xa4, 0xb3, 0x30, 0xaa, 0x82, 0x80, 0x36, 0x10, 0xa0, 0xa8, 0x21, 0xa7, 
+        0x2d, 0x01, 0x5d, 0x0a, 0x3a, 0x35, 0x32, 0x57, 0x00, 0x66, 0x80, 0xbf, 0xc8, 0x11, 0xd8, 0x21, 
+        0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xe0, 0x09, 0x61, 0x39, 0x41, 0x29, 
+        0x51, 0x7c, 0xd5, 0x21, 0x4a, 0xea, 0xc0, 0x20, 0x00, 0x42, 0x22, 0xd4, 0x50, 0x44, 0x10, 0xc0, 
+        0x20, 0x00, 0x42, 0x62, 0xd4, 0x0c, 0x23, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xd4, 0x30, 0x00, 0x20, 
+        0xc0, 0x20, 0x00, 0x02, 0x62, 0xd4, 0x1c, 0x92, 0x01, 0xb2, 0xeb, 0xc0, 0x00, 0x00, 0x2d, 0x01, 
+        0x05, 0xf6, 0xff, 0x28, 0x51, 0x02, 0x11, 0x03, 0x42, 0x11, 0x02, 0x32, 0x11, 0x01, 0x92, 0x11, 
+        0x07, 0x72, 0x11, 0x05, 0x62, 0x11, 0x04, 0x82, 0x11, 0x06, 0x7a, 0x66, 0x9a, 0x88, 0x4a, 0x33, 
+        0x3a, 0x00, 0x80, 0x88, 0x90, 0x60, 0x66, 0x90, 0x60, 0x60, 0xf4, 0x80, 0x70, 0xf4, 0xf0, 0x90, 
+        0x11, 0x90, 0x90, 0xf4, 0x77, 0x39, 0x05, 0x80, 0x80, 0xd0, 0x46, 0x00, 0x00, 0x0c, 0x08, 0x82, 
+        0x52, 0x00, 0x08, 0x41, 0x77, 0x36, 0x05, 0x70, 0x26, 0xc0, 0x46, 0x00, 0x00, 0x0c, 0x02, 0x22, 
+        0x50, 0x00, 0x08, 0x61, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xf1, 0x3c, 0x11, 0x01, 
+        0xf3, 0x3c, 0x11, 0x01, 0xf0, 0x3c, 0x11, 0x01, 0xff, 0xff, 0x03, 0x00, 0x8d, 0x04, 0x12, 0xc1, 
+        0xc0, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x59, 0xc1, 0x69, 0x21, 0x30, 0x40, 0xf4, 0x09, 0x31, 
+        0x29, 0x11, 0xc9, 0x41, 0xc1, 0x14, 0xec, 0x0c, 0x02, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 
+        0x89, 0x91, 0xc0, 0x00, 0x00, 0x28, 0xc1, 0xf1, 0x19, 0xea, 0x16, 0x22, 0x10, 0x4c, 0x0c, 0x4c, 
+        0x0d, 0x1c, 0xce, 0x0c, 0x08, 0x0c, 0x09, 0x0c, 0x0a, 0xb2, 0xc2, 0xfc, 0xb9, 0x81, 0xa9, 0x01, 
+        0x99, 0xa1, 0x89, 0xb1, 0x01, 0x08, 0xec, 0x0c, 0x12, 0x08, 0x00, 0x0c, 0x23, 0x02, 0x20, 0x2b, 
+        0xd0, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0x01, 0x03, 0xec, 0x0c, 0x02, 0x08, 0x00, 0x0c, 0x23, 0x02, 
+        0x20, 0x2b, 0xc0, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x31, 0xe0, 0xff, 0x32, 0x6f, 
+        0xd3, 0xc0, 0x20, 0x00, 0x21, 0xdf, 0xff, 0x22, 0x6f, 0xd3, 0x28, 0x91, 0x01, 0x75, 0xeb, 0xc0, 
+        0x00, 0x00, 0x08, 0x01, 0x92, 0xa0, 0x7f, 0xc0, 0x20, 0x00, 0x42, 0x2f, 0xd3, 0x0c, 0x15, 0x40, 
+        0x4f, 0x05, 0x50, 0x44, 0x30, 0xc0, 0x20, 0x00, 0x31, 0x63, 0xf7, 0x62, 0x2f, 0xd3, 0x0c, 0x0b, 
+        0x30, 0x66, 0x10, 0x60, 0xb5, 0x83, 0x9c, 0x24, 0xad, 0x09, 0xca, 0xce, 0x00, 0xcc, 0x11, 0xc0, 
+        0xc0, 0x31, 0xc7, 0x29, 0x01, 0xad, 0x0c, 0xcd, 0x0a, 0x46, 0x03, 0x00, 0xe0, 0x2c, 0xc0, 0x0c, 
+        0x0c, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x20, 0xc2, 0xb3, 0x52, 0xce, 0xfe, 0x9c, 0x2b, 0x3d, 
+        0x09, 0xda, 0xde, 0x00, 0xdd, 0x11, 0xd0, 0xd0, 0x31, 0xd7, 0x29, 0x01, 0x3d, 0x0d, 0xdd, 0x03, 
+        0x46, 0x03, 0x00, 0xe0, 0x2d, 0xc0, 0x0c, 0x0d, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x20, 0xd2, 
+        0xb3, 0xe0, 0x41, 0x21, 0x38, 0x81, 0x0c, 0x1e, 0x1b, 0x44, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 
+        0x50, 0xe4, 0x93, 0x37, 0x20, 0x17, 0x58, 0xa1, 0x78, 0xb1, 0xda, 0x65, 0xca, 0x87, 0x00, 0x88, 
+        0x11, 0x00, 0x66, 0x11, 0x60, 0x50, 0x31, 0x80, 0x70, 0x31, 0x79, 0xb1, 0x59, 0xa1, 0x78, 0xc1, 
+        0x1b, 0x00, 0x00, 0x00, 0x74, 0x09, 0x01, 0x00, 0x77, 0xc0, 0x56, 0x67, 0xf1, 0xc6, 0x01, 0x00, 
+        0x0c, 0x02, 0x0c, 0x03, 0x39, 0xa1, 0x29, 0xb1, 0x0c, 0x12, 0x0c, 0x23, 0xe8, 0xa1, 0xc1, 0xc9, 
+        0xeb, 0x2b, 0xee, 0x08, 0x0c, 0xe0, 0x42, 0xf4, 0x02, 0x20, 0x2b, 0xe0, 0xe2, 0x21, 0xc0, 0x00, 
+        0x00, 0x0c, 0x02, 0x0c, 0x23, 0xd8, 0xb1, 0x08, 0x0c, 0x2b, 0xdd, 0xd0, 0x42, 0xf4, 0x02, 0x20, 
+        0x2b, 0xd0, 0xd2, 0x21, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 
+        0x42, 0xa0, 0x7f, 0xc0, 0x00, 0x00, 0x41, 0x9f, 0xff, 0xc0, 0x20, 0x00, 0x28, 0x11, 0x38, 0x21, 
+        0x42, 0x6f, 0xd3, 0xd2, 0x43, 0x00, 0xe2, 0x43, 0x01, 0x9c, 0xf2, 0xe0, 0x7d, 0x01, 0x91, 0x9a, 
+        0xff, 0x70, 0x8e, 0x01, 0x61, 0x53, 0xf1, 0xc0, 0x20, 0x00, 0x52, 0x26, 0x99, 0x90, 0x55, 0x10, 
+        0x80, 0x55, 0x20, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 0x99, 0xc8, 0x41, 0xd8, 0x51, 
+        0xe8, 0x61, 0xf8, 0x71, 0x08, 0x31, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 0x00, 0x0c, 0x04, 0x8b, 0x52, 
+        0x22, 0xa0, 0x7f, 0x30, 0x55, 0xe0, 0x00, 0x55, 0x11, 0x50, 0x50, 0x31, 0x50, 0x45, 0xb3, 0x00, 
+        0x44, 0x11, 0x40, 0x30, 0x31, 0xe6, 0xe3, 0x01, 0x2d, 0x03, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 
+        0x0d, 0xf0, 0x00, 0x00, 0x80, 0x85, 0xfe, 0x3f, 0x9c, 0x85, 0xfe, 0x3f, 0x0c, 0x07, 0x12, 0xc1, 
+        0xb0, 0xe9, 0x81, 0xf9, 0x91, 0xd9, 0x71, 0x09, 0x51, 0xc9, 0x61, 0x69, 0xa1, 0x49, 0xe1, 0x52, 
+        0x61, 0x10, 0x0c, 0x94, 0x0c, 0x75, 0x0c, 0x06, 0xcd, 0x03, 0x01, 0x96, 0xeb, 0xdd, 0x02, 0x08, 
+        0x00, 0x22, 0xa0, 0x77, 0x02, 0x20, 0x27, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x4d, 0x0c, 0x3d, 0x0d, 
+        0x0c, 0x05, 0x0c, 0x06, 0x01, 0x90, 0xeb, 0x0c, 0x02, 0x29, 0x01, 0x29, 0x11, 0x29, 0x21, 0x08, 
+        0x00, 0x0c, 0x07, 0x02, 0x20, 0x1a, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x33, 0x52, 
+        0x01, 0x10, 0x59, 0xb1, 0x39, 0xc1, 0x0c, 0x0d, 0x0c, 0x0f, 0x98, 0xa1, 0x0c, 0x08, 0x8c, 0x4c, 
+        0x26, 0x1c, 0x09, 0x66, 0x2c, 0x0a, 0x0c, 0x76, 0x69, 0xb1, 0xc6, 0x00, 0x00, 0x0c, 0xf7, 0x79, 
+        0xb1, 0xa8, 0xb1, 0xca, 0x99, 0x99, 0xd1, 0x82, 0x49, 0x00, 0x1b, 0xaa, 0xa9, 0xf1, 0xbc, 0xac, 
+        0x26, 0x1c, 0x1d, 0x66, 0x2c, 0x53, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 0x01, 0x79, 0xeb, 
+        0x0c, 0x65, 0x08, 0x00, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x7d, 0x0d, 0xc0, 0x00, 0x00, 0x06, 0x0e, 
+        0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 0x01, 0x73, 0xeb, 0x0c, 0x35, 0x08, 0x00, 0x0c, 
+        0x06, 0x02, 0x20, 0x27, 0x7d, 0x0d, 0xc0, 0x00, 0x00, 0x46, 0x07, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 
+        0x23, 0x0c, 0x14, 0x0c, 0x35, 0x0c, 0x06, 0x01, 0x6b, 0xeb, 0x0c, 0x17, 0x08, 0x00, 0x70, 0x7d, 
+        0x90, 0x02, 0x20, 0x27, 0x70, 0x70, 0x74, 0xc0, 0x00, 0x00, 0x01, 0x66, 0xeb, 0x08, 0x00, 0x28, 
+        0xe1, 0x02, 0x20, 0x1c, 0x0c, 0xa3, 0xc0, 0x00, 0x00, 0xed, 0x02, 0x22, 0x21, 0x10, 0x8c, 0xb2, 
+        0x21, 0xc1, 0xff, 0x3d, 0x0d, 0x4d, 0x0e, 0x01, 0x42, 0xe9, 0xc0, 0x00, 0x00, 0xe7, 0xaf, 0x0e, 
+        0xfd, 0x0e, 0x48, 0xd1, 0x0c, 0x13, 0x30, 0x3d, 0x90, 0xc0, 0x3d, 0x93, 0x32, 0x44, 0x00, 0x48, 
+        0xf1, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0xd0, 0x44, 0xc0, 0x56, 0x14, 0xf6, 0xe2, 0x21, 0x10, 0x8c, 
+        0xee, 0x21, 0xb5, 0xff, 0x48, 0xd1, 0x3d, 0x0c, 0x42, 0x04, 0x00, 0x01, 0x35, 0xe9, 0xc0, 0x00, 
+        0x00, 0xac, 0x2c, 0x26, 0x1c, 0x65, 0x66, 0x2c, 0x38, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 
+        0x0c, 0x65, 0x01, 0x4c, 0xeb, 0x0c, 0x46, 0x08, 0x00, 0x78, 0xd1, 0x02, 0x20, 0x27, 0x72, 0x07, 
+        0x00, 0xc0, 0x00, 0x00, 0x86, 0x06, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x14, 0x0c, 0x35, 
+        0x01, 0x45, 0xeb, 0x0c, 0x06, 0x08, 0x00, 0x78, 0xd1, 0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 
+        0x00, 0x00, 0x28, 0xc1, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x0b, 0x22, 0x29, 0xc1, 0x56, 0x52, 0xed, 
+        0x01, 0x3d, 0xeb, 0x08, 0x00, 0x02, 0x20, 0x1b, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0xc8, 0x61, 0xd8, 
+        0x71, 0xe8, 0x81, 0xf8, 0x91, 0x08, 0x51, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0x22, 0xa0, 0x6b, 0x0c, 
+        0x23, 0x0c, 0x24, 0x0c, 0x35, 0x01, 0x33, 0xeb, 0x0c, 0x06, 0x08, 0x00, 0x78, 0xd1, 0x02, 0x20, 
+        0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 0x00, 0xc6, 0xed, 0xff, 0x00, 0x00, 0xb4, 0x85, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xa0, 0xf9, 0x81, 0x09, 0x41, 0xd9, 0x61, 0xc9, 0x51, 0xe9, 0x71, 0x79, 0xb1, 0x59, 
+        0xe1, 0x39, 0xc1, 0x49, 0xd1, 0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x0c, 0x07, 0xed, 0x06, 0xc1, 
+        0x25, 0xeb, 0xdd, 0x02, 0x08, 0x0c, 0x22, 0xa0, 0x77, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 
+        0x00, 0x28, 0xd1, 0x16, 0xb2, 0x14, 0xf2, 0xaf, 0x80, 0x0c, 0x0a, 0xe0, 0x60, 0x24, 0xe0, 0x53, 
+        0x14, 0xd9, 0x91, 0x32, 0x11, 0x30, 0x42, 0x01, 0x64, 0x0c, 0x07, 0x72, 0x61, 0x12, 0x49, 0xa1, 
+        0x32, 0x61, 0x15, 0xd2, 0xa0, 0x7f, 0x50, 0x55, 0x90, 0x0c, 0x0e, 0x60, 0x55, 0x90, 0x50, 0x50, 
+        0x74, 0x59, 0xf1, 0x92, 0x21, 0x12, 0x88, 0xc1, 0xa2, 0x61, 0x13, 0x9a, 0x88, 0x98, 0xe1, 0x82, 
+        0x08, 0x00, 0x82, 0x61, 0x11, 0x90, 0x88, 0xc0, 0x82, 0x61, 0x10, 0x32, 0x21, 0x10, 0x28, 0xf1, 
+        0xe0, 0x33, 0xc0, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0x05, 0xd8, 0xff, 0x0c, 0x00, 0x20, 0x02, 
+        0xb3, 0x80, 0xc0, 0x01, 0xc0, 0xc8, 0x31, 0xc7, 0xad, 0x04, 0x0b, 0xcd, 0x06, 0x01, 0x00, 0xf7, 
+        0xac, 0x01, 0x1b, 0xcf, 0x0c, 0x12, 0x38, 0x91, 0xc0, 0x40, 0x74, 0x0c, 0x05, 0x01, 0x01, 0xeb, 
+        0x0c, 0x06, 0x69, 0x01, 0x69, 0x11, 0x69, 0x21, 0x08, 0x00, 0x0c, 0x07, 0x02, 0x20, 0x1a, 0x0c, 
+        0x06, 0xc0, 0x00, 0x00, 0x01, 0xfc, 0xea, 0x08, 0x00, 0x08, 0xb0, 0x22, 0x21, 0x15, 0xc0, 0x00, 
+        0x00, 0x01, 0xf8, 0xea, 0x08, 0x00, 0x22, 0x61, 0x14, 0x08, 0xb0, 0x22, 0x21, 0x15, 0xc0, 0x00, 
+        0x00, 0x02, 0x21, 0x14, 0x62, 0x21, 0x11, 0x2a, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x31, 0x4b, 
+        0x00, 0x00, 0x03, 0x21, 0x60, 0x60, 0xc0, 0x00, 0x66, 0x11, 0x60, 0x60, 0x31, 0xe6, 0x16, 0x08, 
+        0x80, 0xdc, 0x01, 0xd0, 0xd8, 0x31, 0x46, 0x01, 0x00, 0x80, 0xfc, 0x01, 0xf0, 0xf8, 0x31, 0xac, 
+        0x46, 0x26, 0x06, 0x22, 0x80, 0x2c, 0x01, 0x20, 0x28, 0x31, 0xcc, 0x12, 0x96, 0x76, 0x01, 0x1b, 
+        0x3f, 0x37, 0x1d, 0x12, 0x42, 0x21, 0x13, 0xea, 0xe6, 0x1b, 0x54, 0x50, 0x40, 0x74, 0x42, 0x61, 
+        0x13, 0x42, 0xc4, 0xf6, 0x56, 0x34, 0xf4, 0x78, 0xa1, 0x92, 0x21, 0x12, 0x68, 0xe1, 0x88, 0xb1, 
+        0x60, 0x6c, 0xc0, 0x9a, 0x88, 0x62, 0x48, 0x00, 0x9c, 0x97, 0x42, 0x21, 0x11, 0x21, 0xab, 0xff, 
+        0x32, 0x21, 0x12, 0x80, 0x66, 0x01, 0x80, 0x50, 0x01, 0x50, 0x58, 0x31, 0x60, 0x68, 0x31, 0x01, 
+        0x04, 0xeb, 0xc0, 0x00, 0x00, 0xf2, 0xaf, 0x80, 0xd2, 0xa0, 0x7f, 0x0c, 0x0e, 0x0c, 0x0a, 0x72, 
+        0x21, 0x12, 0x68, 0xd1, 0x1b, 0x87, 0x80, 0x70, 0x74, 0x72, 0x61, 0x12, 0x70, 0x66, 0xc0, 0x56, 
+        0x06, 0xee, 0x01, 0xcc, 0xea, 0x08, 0x00, 0x02, 0x20, 0x1b, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0xc8, 
+        0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 0x60, 0x0d, 0xf0, 0x00, 0x00, 
+        0xfc, 0x85, 0xfe, 0x3f, 0x82, 0xc2, 0xfe, 0x12, 0xc1, 0xa0, 0xc2, 0x61, 0x0a, 0xe2, 0x61, 0x0c, 
+        0xf9, 0xd1, 0x09, 0x91, 0x69, 0xe1, 0x52, 0x61, 0x13, 0xd9, 0xb1, 0x89, 0x11, 0xd1, 0x57, 0xe9, 
+        0xc0, 0x20, 0x00, 0x92, 0x2d, 0xe0, 0x00, 0x08, 0x40, 0x90, 0x90, 0xb1, 0xc0, 0x20, 0x00, 0xa2, 
+        0x2d, 0xe3, 0x00, 0x08, 0x40, 0xa0, 0xa0, 0xb1, 0xa0, 0xf9, 0xc0, 0xc0, 0x20, 0x00, 0x62, 0x2d, 
+        0xe2, 0x00, 0x08, 0x40, 0x60, 0x60, 0xb1, 0xc0, 0x20, 0x00, 0x79, 0x01, 0x02, 0x2d, 0xe1, 0x00, 
+        0x08, 0x40, 0xaa, 0x99, 0x2d, 0x09, 0x88, 0xe1, 0x00, 0x00, 0xb1, 0x0a, 0xe6, 0x80, 0x85, 0x30, 
+        0x60, 0x00, 0xc0, 0xcd, 0x00, 0x40, 0x63, 0x30, 0x80, 0x66, 0x30, 0x60, 0x60, 0x74, 0x8c, 0x66, 
+        0xcd, 0x0e, 0x2d, 0x0f, 0xed, 0x00, 0xfd, 0x09, 0x22, 0x61, 0x10, 0xc0, 0xdf, 0x31, 0x4d, 0x02, 
+        0x20, 0x5f, 0x31, 0x59, 0xf1, 0x3d, 0x05, 0x85, 0x6a, 0x03, 0x5d, 0x0d, 0x4d, 0x0c, 0x39, 0x31, 
+        0x29, 0x41, 0x3d, 0x0d, 0x2d, 0x0c, 0x85, 0x69, 0x03, 0x0c, 0x06, 0x0c, 0x10, 0x0c, 0x07, 0x58, 
+        0x31, 0xb8, 0x41, 0x3a, 0x55, 0x2a, 0x4b, 0x40, 0x70, 0x83, 0xb7, 0xb4, 0x01, 0x1b, 0x55, 0xbd, 
+        0x04, 0xad, 0x05, 0x50, 0x60, 0x83, 0x77, 0x06, 0x03, 0xbd, 0x00, 0x0c, 0x0a, 0xf0, 0x4f, 0x20, 
+        0xf2, 0x61, 0x06, 0xe2, 0x61, 0x12, 0x38, 0xf1, 0x22, 0x21, 0x10, 0xa2, 0x61, 0x14, 0xb2, 0x61, 
+        0x15, 0xe0, 0x8f, 0x31, 0xf0, 0x5f, 0x31, 0x59, 0x51, 0x82, 0x61, 0x11, 0x05, 0x65, 0x03, 0xe2, 
+        0x21, 0x15, 0xf2, 0x21, 0x14, 0x52, 0x21, 0x11, 0x42, 0x21, 0x12, 0x39, 0x71, 0x29, 0x81, 0x3d, 
+        0x0d, 0x2d, 0x0c, 0xc5, 0x63, 0x03, 0x08, 0x71, 0x30, 0x00, 0xc0, 0x38, 0x81, 0x20, 0xa3, 0xc0, 
+        0xa7, 0xb3, 0x01, 0x0b, 0x00, 0x70, 0x2a, 0x11, 0xf0, 0x5f, 0x20, 0x4d, 0x0e, 0x10, 0x47, 0x40, 
+        0xa0, 0x30, 0x81, 0x45, 0x65, 0x03, 0x38, 0x01, 0x80, 0x42, 0x01, 0x58, 0xe1, 0x40, 0x48, 0x31, 
+        0x1b, 0x44, 0x40, 0x41, 0x21, 0x40, 0x20, 0x60, 0x50, 0x24, 0x83, 0x58, 0x51, 0x48, 0x61, 0x22, 
+        0x43, 0x00, 0x29, 0x21, 0x3d, 0x0d, 0x2d, 0x0c, 0x45, 0x5f, 0x03, 0x52, 0x21, 0x11, 0x42, 0x21, 
+        0x12, 0xdd, 0x03, 0xcd, 0x02, 0x38, 0xf1, 0x22, 0x21, 0x10, 0x45, 0x5e, 0x03, 0x3a, 0x0d, 0x2a, 
+        0x2c, 0xc7, 0xb2, 0x01, 0x1b, 0x00, 0xe0, 0x4e, 0x20, 0xf0, 0x5f, 0x20, 0xc2, 0x21, 0x00, 0x10, 
+        0x47, 0x40, 0xd2, 0x21, 0x13, 0x20, 0x30, 0x81, 0x70, 0x22, 0x11, 0xc5, 0x5f, 0x03, 0x52, 0x01, 
+        0x60, 0x80, 0x62, 0x01, 0x60, 0x68, 0x31, 0x1b, 0x66, 0x60, 0x61, 0x21, 0x60, 0x00, 0x60, 0xd0, 
+        0x06, 0x83, 0x02, 0x4c, 0x01, 0xac, 0x65, 0x21, 0x9e, 0xff, 0xc0, 0x20, 0x00, 0x31, 0xfb, 0xe8, 
+        0x48, 0x11, 0x80, 0x50, 0x01, 0x50, 0x58, 0x31, 0x00, 0x04, 0x40, 0x32, 0x23, 0xf9, 0x48, 0x21, 
+        0x30, 0x30, 0xb1, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x01, 0x89, 0xea, 0xc0, 0x00, 0x00, 0xc8, 
+        0xa1, 0xd8, 0xb1, 0xe8, 0xc1, 0xf8, 0xd1, 0x08, 0x91, 0x12, 0xc1, 0x60, 0x0d, 0xf0, 0x00, 0x00, 
+        0x00, 0x40, 0x00, 0x00, 0x2c, 0xf3, 0xfe, 0x3f, 0x9d, 0x03, 0x12, 0xc1, 0xb0, 0x79, 0x71, 0x49, 
+        0x51, 0x62, 0x61, 0x12, 0x52, 0x61, 0x11, 0x09, 0x81, 0x22, 0x61, 0x10, 0xf9, 0xc1, 0xd9, 0xa1, 
+        0xe9, 0xb1, 0xc9, 0x91, 0x0c, 0x0e, 0x0c, 0x0c, 0xd1, 0x4b, 0xea, 0xf2, 0x01, 0x54, 0x99, 0x61, 
+        0x0c, 0x22, 0x02, 0x21, 0x10, 0x22, 0x61, 0x13, 0x52, 0x21, 0x12, 0x62, 0x21, 0x11, 0x62, 0x41, 
+        0x10, 0x52, 0x41, 0x11, 0x0c, 0x12, 0x00, 0x10, 0x40, 0x00, 0x22, 0xa1, 0x02, 0x01, 0x58, 0x09, 
+        0xe1, 0x20, 0x20, 0xf4, 0x29, 0xd1, 0x0c, 0x14, 0x5d, 0x0f, 0x32, 0xa0, 0x80, 0x08, 0x0d, 0xc0, 
+        0x2c, 0xd1, 0x02, 0x20, 0x3e, 0x3a, 0x22, 0x20, 0x28, 0x21, 0x32, 0xc1, 0x10, 0x29, 0xf1, 0x20, 
+        0x2e, 0xc0, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 0x32, 0xc1, 0x11, 0x0c, 0x04, 
+        0x5d, 0x0f, 0x08, 0x0d, 0xed, 0x02, 0x02, 0x20, 0x3e, 0x2d, 0x0c, 0xc0, 0x00, 0x00, 0x38, 0xd1, 
+        0x08, 0x0d, 0xcd, 0x02, 0x08, 0xd0, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x22, 0x21, 0x10, 0x38, 0x61, 
+        0x52, 0x01, 0x11, 0x82, 0x21, 0x11, 0x62, 0x01, 0x10, 0x0c, 0x19, 0x80, 0x66, 0xc0, 0x82, 0x21, 
+        0x12, 0x60, 0x69, 0x93, 0x62, 0x41, 0x10, 0x80, 0x55, 0xc0, 0x88, 0xe1, 0x50, 0x59, 0x93, 0x52, 
+        0x41, 0x11, 0x89, 0x01, 0x08, 0x0d, 0x48, 0x51, 0x02, 0x20, 0x12, 0x72, 0xc1, 0x12, 0xc0, 0x00, 
+        0x00, 0x28, 0xf1, 0x02, 0x01, 0x12, 0x2a, 0x2e, 0x80, 0xe0, 0x01, 0x02, 0x01, 0x13, 0xe0, 0xe8, 
+        0x31, 0x2a, 0xee, 0x80, 0x00, 0x01, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x00, 0x08, 0x31, 0x00, 
+        0xcc, 0xc0, 0x08, 0x0d, 0x80, 0xcc, 0x01, 0x08, 0xc0, 0xc0, 0xc8, 0x31, 0xc0, 0x00, 0x00, 0x32, 
+        0x21, 0x13, 0x0b, 0x33, 0x32, 0x61, 0x13, 0x56, 0xb3, 0xf4, 0x22, 0x01, 0x12, 0x08, 0x0d, 0x80, 
+        0x22, 0x01, 0x08, 0x00, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 0xe6, 0x52, 0x12, 0x22, 0x01, 0x13, 
+        0x08, 0x0d, 0x80, 0x22, 0x01, 0x08, 0x00, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 0xa6, 0x52, 0x17, 
+        0x71, 0xb4, 0xff, 0x41, 0x9b, 0xfb, 0x61, 0xb3, 0xff, 0x38, 0x04, 0x52, 0x06, 0x00, 0x70, 0x33, 
+        0x20, 0x1b, 0x55, 0x52, 0x46, 0x00, 0x39, 0x04, 0x0c, 0xf2, 0x7c, 0x10, 0x07, 0x2e, 0x01, 0x0d, 
+        0x0e, 0x07, 0x22, 0x01, 0x2d, 0x00, 0x6c, 0x10, 0x80, 0xe2, 0x01, 0xe0, 0xe8, 0x31, 0x1c, 0xf2, 
+        0x07, 0x2c, 0x01, 0x0d, 0x0c, 0x07, 0x22, 0x01, 0x2d, 0x00, 0x32, 0xc1, 0x10, 0x0c, 0x14, 0x5d, 
+        0x0f, 0x80, 0xc2, 0x01, 0x08, 0x0d, 0xc0, 0xc8, 0x31, 0x02, 0x20, 0x3e, 0x2d, 0x0e, 0xc0, 0x00, 
+        0x00, 0x5d, 0x0f, 0x2d, 0x0c, 0x08, 0x0d, 0x32, 0xc1, 0x11, 0x02, 0x20, 0x3e, 0x0c, 0x04, 0xc0, 
+        0x00, 0x00, 0x08, 0x81, 0xd8, 0xa1, 0xf8, 0xc1, 0x38, 0x71, 0x22, 0x21, 0x14, 0xe2, 0x43, 0x00, 
+        0xc2, 0x42, 0x00, 0xe8, 0xb1, 0xc8, 0x91, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0x9d, 0x05, 0xad, 0x03, 
+        0x12, 0xc1, 0xb0, 0xd9, 0xe1, 0xe9, 0xf1, 0x79, 0x81, 0x0c, 0x03, 0x0c, 0x05, 0xf2, 0x61, 0x10, 
+        0x09, 0xc1, 0xc9, 0xd1, 0x62, 0x61, 0x13, 0x29, 0x51, 0x49, 0x61, 0x22, 0xa0, 0x77, 0x1c, 0x04, 
+        0x0c, 0x06, 0xc1, 0xe0, 0xe9, 0xa2, 0x61, 0x11, 0x08, 0x0c, 0x92, 0x61, 0x12, 0x02, 0x20, 0x25, 
+        0xf2, 0x21, 0x13, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x0c, 0xf4, 0x0c, 0x65, 0x0c, 0x66, 0x08, 0x0c, 
+        0xed, 0x02, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 
+        0x55, 0x0c, 0x56, 0x08, 0x0c, 0xdd, 0x02, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 
+        0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x35, 0x0c, 0x36, 0x08, 0x0c, 0x29, 0x91, 0x02, 0x20, 0x25, 0x22, 
+        0xa0, 0x77, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x0c, 0x06, 0x08, 0x0c, 0x29, 
+        0xa1, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x29, 0x71, 0x02, 0x20, 
+        0x10, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0xe2, 0x41, 0x10, 0xd2, 0x41, 0x11, 0x8c, 0xcf, 0x08, 0x0c, 
+        0x22, 0xc1, 0x10, 0x02, 0x20, 0x45, 0x32, 0xc1, 0x11, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x1c, 0x04, 0x0c, 0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 
+        0x00, 0xe9, 0xb1, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x17, 
+        0x92, 0x01, 0x10, 0x82, 0x01, 0x11, 0xe0, 0x99, 0xc0, 0xd0, 0x88, 0xc0, 0x80, 0x87, 0x93, 0x90, 
+        0x97, 0x93, 0x92, 0x41, 0x10, 0x82, 0x41, 0x11, 0x02, 0x20, 0x27, 0x0c, 0x76, 0xc0, 0x00, 0x00, 
+        0x08, 0x0c, 0xe2, 0x21, 0x11, 0x02, 0x20, 0x14, 0x28, 0x61, 0xc0, 0x00, 0x00, 0x0c, 0x05, 0x0c, 
+        0x06, 0x0c, 0x07, 0x4d, 0x02, 0x0c, 0x03, 0x39, 0x21, 0x39, 0x11, 0x39, 0x01, 0x08, 0x0c, 0x0c, 
+        0x12, 0x02, 0x20, 0x1a, 0x3d, 0x0e, 0xc0, 0x00, 0x00, 0x28, 0x51, 0x78, 0x81, 0x62, 0xc1, 0x13, 
+        0x42, 0x01, 0x11, 0x58, 0x91, 0x32, 0x01, 0x10, 0xed, 0x05, 0xf9, 0x11, 0x69, 0x01, 0x79, 0x21, 
+        0x72, 0xc1, 0x12, 0x08, 0x0c, 0x68, 0xa1, 0x02, 0x20, 0x43, 0xfd, 0x06, 0xc0, 0x00, 0x00, 0x08, 
+        0x0c, 0x02, 0x20, 0x1b, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x78, 0xb1, 0x22, 0xa0, 0x77, 0x0c, 0x03, 
+        0x1c, 0x04, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x7d, 0x0d, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0xf4, 0x08, 0x0c, 0x0c, 0x65, 0x02, 0x20, 0x27, 0x0c, 0x66, 
+        0xc0, 0x00, 0x00, 0x7d, 0x0e, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x08, 0x0c, 0x0c, 0x55, 
+        0x02, 0x20, 0x27, 0x0c, 0x56, 0xc0, 0x00, 0x00, 0x7d, 0x0f, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 
+        0x84, 0x0c, 0x35, 0x08, 0x0c, 0x0c, 0x36, 0x02, 0x20, 0x27, 0xd8, 0x71, 0xc0, 0x00, 0x00, 0x7d, 
+        0x0d, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x94, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 0x27, 0x0c, 
+        0x06, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 
+        0x76, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 
+        0x0c, 0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x08, 0x0c, 
+        0xd2, 0x21, 0x12, 0x02, 0x20, 0x10, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x08, 0xc1, 0xc8, 0xd1, 0xe8, 
+        0xf1, 0x32, 0x01, 0x12, 0xf2, 0x21, 0x10, 0x32, 0x4d, 0x00, 0x22, 0x01, 0x13, 0x22, 0x4d, 0x01, 
+        0xd8, 0xe1, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 
+        0x31, 0x23, 0xec, 0x0c, 0x02, 0x29, 0x13, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf2, 0x3f, 
+        0x0c, 0x02, 0x31, 0xfe, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x80, 0xc0, 0x20, 0x00, 0x22, 0x63, 
+        0x83, 0x0d, 0xf0, 0x00, 0xb4, 0x63, 0x10, 0x40, 0xc4, 0x0d, 0xf2, 0x3f, 0xf0, 0x0c, 0xf2, 0x3f, 
+        0x1c, 0x0d, 0xf2, 0x3f, 0x34, 0x0d, 0xf2, 0x3f, 0x4c, 0x0d, 0xf2, 0x3f, 0x64, 0x0d, 0xf2, 0x3f, 
+        0x7c, 0x0d, 0xf2, 0x3f, 0x94, 0x0d, 0xf2, 0x3f, 0xac, 0x0d, 0xf2, 0x3f, 0xc8, 0x0c, 0xf2, 0x3f, 
+        0xdc, 0x0c, 0xf2, 0x3f, 0x1c, 0xc3, 0x37, 0xb2, 0x5e, 0x51, 0xf2, 0xff, 0x20, 0x42, 0x90, 0x5a, 
+        0x44, 0xa0, 0x04, 0x00, 0x06, 0x14, 0x00, 0x86, 0x14, 0x00, 0x06, 0x1f, 0x00, 0x06, 0x1d, 0x00, 
+        0x06, 0x11, 0x00, 0x46, 0x10, 0x00, 0x86, 0x0f, 0x00, 0xc6, 0x0e, 0x00, 0x06, 0x0e, 0x00, 0x46, 
+        0x0d, 0x00, 0x86, 0x0c, 0x00, 0xc6, 0x15, 0x00, 0xc6, 0x13, 0x00, 0xc6, 0x11, 0x00, 0xc6, 0x0f, 
+        0x00, 0xc6, 0x0d, 0x00, 0xc6, 0x0b, 0x00, 0xc6, 0x09, 0x00, 0x86, 0x06, 0x00, 0xc6, 0x05, 0x00, 
+        0x06, 0x05, 0x00, 0x46, 0x0e, 0x00, 0x46, 0x0c, 0x00, 0x46, 0x0a, 0x00, 0x46, 0x08, 0x00, 0x46, 
+        0x06, 0x00, 0x46, 0x04, 0x00, 0x46, 0x02, 0x00, 0x21, 0xdc, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 
+        0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 
+        0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 
+        0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xd9, 0xff, 0x0d, 0xf0, 0x21, 0xd9, 0xff, 0x0d, 0xf0, 0x00, 
+        0x80, 0x64, 0x10, 0x40, 0xc8, 0x0d, 0xf2, 0x3f, 0xf4, 0x0c, 0xf2, 0x3f, 0x20, 0x0d, 0xf2, 0x3f, 
+        0x38, 0x0d, 0xf2, 0x3f, 0x50, 0x0d, 0xf2, 0x3f, 0x68, 0x0d, 0xf2, 0x3f, 0x80, 0x0d, 0xf2, 0x3f, 
+        0x98, 0x0d, 0xf2, 0x3f, 0xb0, 0x0d, 0xf2, 0x3f, 0xcc, 0x0c, 0xf2, 0x3f, 0xe0, 0x0c, 0xf2, 0x3f, 
+        0x1c, 0xc3, 0x37, 0xb2, 0x5e, 0x51, 0xf2, 0xff, 0x20, 0x42, 0x90, 0x5a, 0x44, 0xa0, 0x04, 0x00, 
+        0x06, 0x14, 0x00, 0x86, 0x14, 0x00, 0x06, 0x1f, 0x00, 0x06, 0x1d, 0x00, 0x06, 0x11, 0x00, 0x46, 
+        0x10, 0x00, 0x86, 0x0f, 0x00, 0xc6, 0x0e, 0x00, 0x06, 0x0e, 0x00, 0x46, 0x0d, 0x00, 0x86, 0x0c, 
+        0x00, 0xc6, 0x15, 0x00, 0xc6, 0x13, 0x00, 0xc6, 0x11, 0x00, 0xc6, 0x0f, 0x00, 0xc6, 0x0d, 0x00, 
+        0xc6, 0x0b, 0x00, 0xc6, 0x09, 0x00, 0x86, 0x06, 0x00, 0xc6, 0x05, 0x00, 0x06, 0x05, 0x00, 0x46, 
+        0x0e, 0x00, 0x46, 0x0c, 0x00, 0x46, 0x0a, 0x00, 0x46, 0x08, 0x00, 0x46, 0x06, 0x00, 0x46, 0x04, 
+        0x00, 0x46, 0x02, 0x00, 0x21, 0xdc, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 
+        0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 
+        0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 
+        0xf0, 0x21, 0xd9, 0xff, 0x0d, 0xf0, 0x21, 0xd9, 0xff, 0x0d, 0xf0, 0x00, 0x4c, 0x65, 0x10, 0x40, 
+        0xcc, 0x0d, 0xf2, 0x3f, 0xf8, 0x0c, 0xf2, 0x3f, 0x24, 0x0d, 0xf2, 0x3f, 0x3c, 0x0d, 0xf2, 0x3f, 
+        0x54, 0x0d, 0xf2, 0x3f, 0x6c, 0x0d, 0xf2, 0x3f, 0x84, 0x0d, 0xf2, 0x3f, 0x9c, 0x0d, 0xf2, 0x3f, 
+        0xb4, 0x0d, 0xf2, 0x3f, 0xd0, 0x0c, 0xf2, 0x3f, 0xe4, 0x0c, 0xf2, 0x3f, 0x1c, 0xc3, 0x37, 0xb2, 
+        0x5e, 0x51, 0xf2, 0xff, 0x20, 0x42, 0x90, 0x5a, 0x44, 0xa0, 0x04, 0x00, 0x06, 0x14, 0x00, 0x86, 
+        0x14, 0x00, 0x06, 0x1f, 0x00, 0x06, 0x1d, 0x00, 0x06, 0x11, 0x00, 0x46, 0x10, 0x00, 0x86, 0x0f, 
+        0x00, 0xc6, 0x0e, 0x00, 0x06, 0x0e, 0x00, 0x46, 0x0d, 0x00, 0x86, 0x0c, 0x00, 0xc6, 0x15, 0x00, 
+        0xc6, 0x13, 0x00, 0xc6, 0x11, 0x00, 0xc6, 0x0f, 0x00, 0xc6, 0x0d, 0x00, 0xc6, 0x0b, 0x00, 0xc6, 
+        0x09, 0x00, 0x86, 0x06, 0x00, 0xc6, 0x05, 0x00, 0x06, 0x05, 0x00, 0x46, 0x0e, 0x00, 0x46, 0x0c, 
+        0x00, 0x46, 0x0a, 0x00, 0x46, 0x08, 0x00, 0x46, 0x06, 0x00, 0x46, 0x04, 0x00, 0x46, 0x02, 0x00, 
+        0x21, 0xdc, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 
+        0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xdb, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xda, 
+        0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xda, 0xff, 0x0d, 0xf0, 0x21, 0xd9, 0xff, 
+        0x0d, 0xf0, 0x21, 0xd9, 0xff, 0x0d, 0xf0, 0x00, 0xc0, 0x0d, 0xf2, 0x3f, 0x18, 0x0d, 0xf2, 0x3f, 
+        0xa8, 0x0d, 0xf2, 0x3f, 0x90, 0x0d, 0xf2, 0x3f, 0x78, 0x0d, 0xf2, 0x3f, 0x60, 0x0d, 0xf2, 0x3f, 
+        0x48, 0x0d, 0xf2, 0x3f, 0x30, 0x0d, 0xf2, 0x3f, 0x26, 0x92, 0x1e, 0x0c, 0xb3, 0x37, 0x12, 0x23, 
+        0x26, 0xa2, 0x25, 0x0c, 0xd4, 0x47, 0x12, 0x25, 0x0c, 0xe5, 0x57, 0x12, 0x25, 0x0c, 0xf6, 0x67, 
+        0x12, 0x25, 0x26, 0xb2, 0x27, 0x1c, 0x17, 0x77, 0x12, 0x04, 0x21, 0xef, 0xff, 0x0d, 0xf0, 0x21, 
+        0xef, 0xff, 0x0d, 0xf0, 0x21, 0xef, 0xff, 0x0d, 0xf0, 0x21, 0xee, 0xff, 0x0d, 0xf0, 0x21, 0xee, 
+        0xff, 0x0d, 0xf0, 0x21, 0xee, 0xff, 0x0d, 0xf0, 0x21, 0xee, 0xff, 0x0d, 0xf0, 0x21, 0xed, 0xff, 
+        0x0d, 0xf0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x39, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0xb9, 0x00, 0x01, 
+        0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x90, 0x02, 0x00, 0x00, 0x90, 0xfe, 0x3f, 
+        0x04, 0x90, 0xfe, 0x3f, 0x00, 0x94, 0xfe, 0x3f, 0x08, 0x90, 0xfe, 0x3f, 0x10, 0x90, 0xfe, 0x3f, 
+        0x14, 0x90, 0xfe, 0x3f, 0x00, 0x9c, 0xfe, 0x3f, 0x18, 0x90, 0xfe, 0x3f, 0x20, 0x90, 0xfe, 0x3f, 
+        0x24, 0x90, 0xfe, 0x3f, 0x00, 0xa2, 0xfe, 0x3f, 0x28, 0x90, 0xfe, 0x3f, 0x30, 0x90, 0xfe, 0x3f, 
+        0x34, 0x90, 0xfe, 0x3f, 0x00, 0x9d, 0xfe, 0x3f, 0x38, 0x90, 0xfe, 0x3f, 0x10, 0x81, 0xfe, 0x3f, 
+        0x82, 0xa0, 0xf0, 0x80, 0x11, 0xc0, 0xe2, 0x61, 0x33, 0xf2, 0x61, 0x34, 0x22, 0x61, 0x36, 0x32, 
+        0x61, 0x39, 0x72, 0x61, 0x2f, 0x62, 0x61, 0x2e, 0x02, 0x61, 0x30, 0xc2, 0x61, 0x31, 0xd2, 0x61, 
+        0x32, 0xcd, 0x05, 0xdd, 0x04, 0x85, 0xc9, 0xff, 0xe2, 0x21, 0x36, 0xe0, 0xe0, 0x74, 0x2d, 0x0e, 
+        0x05, 0xcd, 0xff, 0xfd, 0x02, 0x2d, 0x0e, 0x85, 0xd9, 0xff, 0x22, 0x61, 0x35, 0xf2, 0x61, 0x2d, 
+        0x2d, 0x0e, 0x85, 0xe5, 0xff, 0xfd, 0x02, 0x2d, 0x0e, 0xc5, 0xf0, 0xff, 0x0c, 0x03, 0xf2, 0x61, 
+        0x2c, 0x05, 0xf5, 0xff, 0x80, 0x5d, 0x11, 0x02, 0x21, 0x39, 0xf2, 0x21, 0x40, 0x42, 0x21, 0x3d, 
+        0x32, 0x21, 0x3e, 0x00, 0x44, 0x11, 0x90, 0x33, 0x01, 0x10, 0xff, 0x01, 0x00, 0x20, 0x34, 0x5a, 
+        0x22, 0x2a, 0xff, 0xf6, 0xb0, 0x1c, 0x22, 0x21, 0x35, 0x3a, 0x34, 0x40, 0x50, 0x11, 0xd0, 0x40, 
+        0xb4, 0x5a, 0x44, 0x4a, 0x33, 0xc5, 0xf1, 0xff, 0x3d, 0x0f, 0x22, 0x21, 0x2c, 0x45, 0xf1, 0xff, 
+        0x06, 0x1d, 0x00, 0x30, 0x74, 0x20, 0x81, 0xc5, 0xff, 0x31, 0xc5, 0xff, 0x80, 0x77, 0x20, 0xc0, 
+        0x20, 0x00, 0x82, 0x21, 0x35, 0x1c, 0x36, 0x79, 0x08, 0xe7, 0xb6, 0x1e, 0x6c, 0xfe, 0x3a, 0x3f, 
+        0x22, 0x21, 0x2c, 0x05, 0xef, 0xff, 0xc0, 0x20, 0x00, 0xa1, 0xe3, 0xea, 0x92, 0x2a, 0xa2, 0xe0, 
+        0x99, 0x10, 0xc0, 0x20, 0x00, 0x92, 0x6a, 0xa2, 0x06, 0x0f, 0x00, 0xa2, 0x21, 0x36, 0xa0, 0xa8, 
+        0x74, 0xec, 0x0a, 0x6c, 0xfe, 0x31, 0xb7, 0xff, 0x22, 0x21, 0x2c, 0x3a, 0x3f, 0x45, 0xec, 0xff, 
+        0xc0, 0x20, 0x00, 0x51, 0xd9, 0xea, 0x42, 0x25, 0xa2, 0xe0, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 
+        0x65, 0xa2, 0x86, 0x04, 0x00, 0x3a, 0x3f, 0x22, 0x21, 0x2c, 0x85, 0xea, 0xff, 0x1c, 0x05, 0xc0, 
+        0x20, 0x00, 0x61, 0xd1, 0xea, 0x52, 0x66, 0xa2, 0xfc, 0x5c, 0x72, 0x21, 0x2e, 0xfc, 0x07, 0x92, 
+        0x21, 0x3c, 0x82, 0x21, 0x2f, 0x92, 0x61, 0x37, 0xec, 0xb8, 0xec, 0x99, 0x41, 0x2f, 0xfc, 0x32, 
+        0x21, 0x3f, 0x22, 0x21, 0x2d, 0x40, 0x33, 0x10, 0x85, 0xe7, 0xff, 0xc2, 0x21, 0x31, 0xd2, 0x21, 
+        0x32, 0xe2, 0x21, 0x33, 0xf2, 0x21, 0x34, 0x22, 0xa0, 0xf0, 0x02, 0x21, 0x30, 0x2a, 0x11, 0x0d, 
+        0xf0, 0x42, 0x21, 0x3c, 0x42, 0x61, 0x37, 0x22, 0x21, 0x2d, 0x31, 0x9b, 0xff, 0x45, 0xe5, 0xff, 
+        0x52, 0x21, 0x37, 0x16, 0x35, 0x11, 0x0c, 0x4e, 0x86, 0x00, 0x00, 0xe2, 0xa0, 0x03, 0x21, 0x97, 
+        0xff, 0x40, 0x4c, 0x11, 0x52, 0xce, 0xff, 0xf1, 0xd8, 0xed, 0x31, 0x3d, 0xef, 0x32, 0x61, 0x38, 
+        0x50, 0x3f, 0x83, 0x40, 0x33, 0x80, 0x3a, 0x3c, 0x85, 0xe2, 0xff, 0x21, 0x91, 0xff, 0x31, 0x91, 
+        0xff, 0x05, 0xe2, 0xff, 0x21, 0x91, 0xff, 0x31, 0x91, 0xff, 0x85, 0xe1, 0xff, 0x21, 0x8f, 0xff, 
+        0x62, 0xce, 0xfe, 0x32, 0x21, 0x2e, 0x42, 0x21, 0x38, 0x40, 0x53, 0x11, 0x60, 0x4f, 0x83, 0x5a, 
+        0x44, 0x4a, 0x33, 0x05, 0xe0, 0xff, 0x21, 0x8a, 0xff, 0x31, 0x8a, 0xff, 0x45, 0xdf, 0xff, 0x21, 
+        0x8a, 0xff, 0x31, 0x8a, 0xff, 0xc5, 0xde, 0xff, 0x21, 0x89, 0xff, 0x62, 0xce, 0xfd, 0x32, 0x21, 
+        0x2f, 0x42, 0x21, 0x38, 0x40, 0x53, 0x11, 0x60, 0x4f, 0x83, 0x5a, 0x44, 0x4a, 0x33, 0x45, 0xdd, 
+        0xff, 0x21, 0x83, 0xff, 0x31, 0x84, 0xff, 0xc5, 0xdc, 0xff, 0x21, 0x83, 0xff, 0x31, 0x83, 0xff, 
+        0x05, 0xdc, 0xff, 0x21, 0x82, 0xff, 0x62, 0xce, 0xfc, 0x32, 0x21, 0x37, 0x42, 0x21, 0x38, 0x40, 
+        0x53, 0x11, 0x60, 0x4f, 0x83, 0x5a, 0x44, 0x4a, 0x33, 0x85, 0xda, 0xff, 0x21, 0x7d, 0xff, 0x31, 
+        0x7d, 0xff, 0x05, 0xda, 0xff, 0x21, 0x7c, 0xff, 0x0c, 0x03, 0x85, 0xd9, 0xff, 0x2d, 0x01, 0x31, 
+        0x7b, 0xff, 0x42, 0xa0, 0xb0, 0x45, 0x5d, 0x03, 0x16, 0xfd, 0xf0, 0x2d, 0x01, 0x0c, 0x00, 0xb1, 
+        0x75, 0xff, 0xa1, 0x70, 0xff, 0x51, 0x6b, 0xff, 0x41, 0x67, 0xff, 0x62, 0x21, 0x2e, 0x72, 0x21, 
+        0x2f, 0x6a, 0x6c, 0x7a, 0x76, 0xc7, 0xb0, 0x09, 0x88, 0x02, 0x82, 0x44, 0x00, 0x1b, 0x44, 0x46, 
+        0x07, 0x00, 0x00, 0x30, 0x74, 0x67, 0xb0, 0x07, 0x32, 0x45, 0x00, 0x1b, 0x55, 0xc6, 0x03, 0x00, 
+        0x77, 0xb0, 0x07, 0x32, 0x4a, 0x00, 0x1b, 0xaa, 0x06, 0x01, 0x00, 0x32, 0x4b, 0x00, 0x1b, 0xbb, 
+        0x4b, 0x22, 0x1b, 0x00, 0x07, 0x9d, 0xcd, 0x06, 0xb0, 0xff, 0x92, 0x21, 0x2f, 0x56, 0xa9, 0xee, 
+        0xb2, 0x21, 0x2e, 0x0c, 0x2a, 0x0c, 0x1e, 0xb0, 0xea, 0x93, 0x06, 0xb8, 0xff, 0x00, 0x00, 0x00, 
+        0x02, 0x00, 0x00, 0x40, 0x20, 0x86, 0xfe, 0x3f, 0x54, 0x86, 0xfe, 0x3f, 0x00, 0xfe, 0xf1, 0x3f, 
+        0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x70, 0x86, 0xfe, 0x3f, 0xa0, 0x86, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 0x20, 0xc2, 0x20, 0x45, 0x08, 0x02, 0x2d, 
+        0x0c, 0x05, 0xa5, 0xff, 0xa1, 0xf3, 0xff, 0x0d, 0x02, 0xc1, 0x63, 0xea, 0x21, 0x35, 0xf1, 0xc0, 
+        0x20, 0x00, 0xa2, 0x6c, 0x82, 0x0c, 0x49, 0xc0, 0x20, 0x00, 0x82, 0x2c, 0x86, 0x90, 0x88, 0x20, 
+        0xc0, 0x20, 0x00, 0x82, 0x6c, 0x86, 0x0c, 0x37, 0xc0, 0x20, 0x00, 0x62, 0x2c, 0x89, 0x70, 0x66, 
+        0x20, 0xc0, 0x20, 0x00, 0x62, 0x6c, 0x89, 0x7c, 0x05, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0x86, 0x50, 
+        0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x6c, 0x86, 0x32, 0x02, 0x59, 0x66, 0x13, 0x45, 0x09, 0x21, 
+        0x32, 0x02, 0x55, 0x42, 0x02, 0x57, 0x52, 0x02, 0x58, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 
+        0x02, 0x56, 0x80, 0x33, 0x01, 0x00, 0x55, 0x11, 0x50, 0x33, 0x20, 0x40, 0x33, 0x20, 0x9c, 0x43, 
+        0x21, 0xd9, 0xff, 0xc0, 0x20, 0x00, 0x48, 0x03, 0x01, 0xaa, 0xe5, 0xc0, 0x00, 0x00, 0x08, 0x21, 
+        0x21, 0x18, 0xf1, 0x46, 0x03, 0x00, 0x21, 0xd4, 0xff, 0x01, 0xa5, 0xe5, 0xc0, 0x00, 0x00, 0x08, 
+        0x21, 0x21, 0x13, 0xf1, 0x0c, 0x06, 0x0c, 0x23, 0x91, 0xd1, 0xff, 0xc0, 0x20, 0x00, 0x62, 0x69, 
+        0x9b, 0x7c, 0xd5, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xa2, 0x50, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 
+        0x6c, 0xa2, 0x7c, 0x7b, 0xc0, 0x20, 0x00, 0xa2, 0x2c, 0xa2, 0xb0, 0xaa, 0x10, 0xc0, 0x20, 0x00, 
+        0xa2, 0x6c, 0xa2, 0x6c, 0xf8, 0xc0, 0x20, 0x00, 0x72, 0x2c, 0xa2, 0x80, 0x77, 0x10, 0xc0, 0x20, 
+        0x00, 0x72, 0x6c, 0xa2, 0x61, 0xc3, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x2c, 0xa2, 0x60, 0x55, 0x10, 
+        0xc0, 0x20, 0x00, 0x52, 0x6c, 0xa2, 0x41, 0xdf, 0xf6, 0xc0, 0x20, 0x00, 0xb2, 0x29, 0x80, 0x40, 
+        0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x69, 0x80, 0xa1, 0xbb, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x29, 
+        0x9c, 0xa0, 0x88, 0x10, 0xc0, 0x20, 0x00, 0x82, 0x69, 0x9c, 0x71, 0x43, 0xed, 0xc0, 0x20, 0x00, 
+        0x68, 0x00, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x69, 0x00, 0xc0, 0x20, 0x00, 0x52, 0x2c, 0x87, 
+        0x17, 0xe5, 0x08, 0xc0, 0x20, 0x00, 0x72, 0x2c, 0x87, 0x37, 0x07, 0xf6, 0x82, 0x02, 0x59, 0x66, 
+        0x18, 0x39, 0x32, 0x02, 0x55, 0x42, 0x02, 0x57, 0x52, 0x02, 0x58, 0x80, 0x44, 0x11, 0x50, 0x44, 
+        0x20, 0x52, 0x02, 0x56, 0x80, 0x33, 0x01, 0x00, 0x55, 0x11, 0x50, 0x33, 0x20, 0x40, 0x33, 0x20, 
+        0x8c, 0xf3, 0x21, 0xa5, 0xff, 0xc0, 0x20, 0x00, 0x48, 0x03, 0x01, 0x71, 0xe5, 0xc0, 0x00, 0x00, 
+        0x06, 0x02, 0x00, 0x21, 0xa2, 0xff, 0x01, 0x6e, 0xe5, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xb0, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0xf9, 0x51, 0x59, 0x01, 0x09, 0x11, 0xd9, 0x31, 0xc9, 0x21, 0xe9, 0x41, 0xcd, 
+        0x03, 0xed, 0x04, 0xdd, 0x02, 0x85, 0x98, 0xff, 0xfd, 0x02, 0x2d, 0x0d, 0xc5, 0xa4, 0xff, 0x31, 
+        0xf6, 0xff, 0x01, 0xc6, 0xef, 0xf6, 0xbc, 0x22, 0x40, 0x5c, 0x11, 0xc0, 0x20, 0x00, 0x48, 0x0f, 
+        0x00, 0x44, 0x10, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x49, 0x0f, 0xc0, 0x20, 0x00, 0x28, 0x0f, 
+        0x30, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x29, 0x0f, 0x86, 0x0e, 0x00, 0xa1, 0xec, 0xff, 0xc0, 0x20, 
+        0x00, 0x98, 0x0f, 0x00, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x99, 0x0f, 0x91, 0x33, 
+        0xfa, 0xc0, 0x20, 0x00, 0x88, 0x0f, 0x30, 0x88, 0x10, 0x90, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x89, 
+        0x0f, 0x7c, 0x07, 0xc0, 0x60, 0x34, 0xc0, 0x20, 0x00, 0x58, 0x02, 0x70, 0x55, 0x10, 0x60, 0x55, 
+        0x20, 0xc0, 0x20, 0x00, 0x59, 0x02, 0x9c, 0x7e, 0xf8, 0x01, 0x0c, 0x0c, 0xf0, 0xf0, 0xf4, 0x2d, 
+        0x0d, 0xc5, 0xdd, 0xff, 0x2d, 0x0f, 0x01, 0xda, 0xe6, 0xc0, 0x00, 0x00, 0x1b, 0xcc, 0xe7, 0x9c, 
+        0xed, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x00, 0x60, 0x09, 0x00, 0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x01, 0xd2, 0x61, 0x02, 0xe9, 0x31, 0xf9, 
+        0x41, 0x09, 0x01, 0x0c, 0xe0, 0x27, 0x30, 0x04, 0x8c, 0x12, 0xc5, 0xde, 0x01, 0x0c, 0x0c, 0xe1, 
+        0xd2, 0xe9, 0xc0, 0x20, 0x00, 0x0c, 0x72, 0x0c, 0x53, 0x51, 0xf5, 0xff, 0x42, 0x2e, 0x80, 0xc5, 
+        0x73, 0xfa, 0x8c, 0x42, 0x22, 0xac, 0xe0, 0x46, 0x02, 0x00, 0x01, 0x4a, 0xe7, 0x08, 0x00, 0x08, 
+        0xa0, 0xc0, 0x00, 0x00, 0xcc, 0x5c, 0xfd, 0x02, 0xdd, 0x02, 0x06, 0x05, 0x00, 0x27, 0xad, 0x04, 
+        0xdd, 0x02, 0x06, 0x03, 0x00, 0x0d, 0x0f, 0xf7, 0xa2, 0x01, 0x0d, 0x02, 0x00, 0xf0, 0x11, 0xf0, 
+        0xf0, 0x31, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x5c, 0xb7, 0xe1, 0x91, 0xf0, 0xe2, 0x0e, 0x50, 
+        0x66, 0x1e, 0x11, 0x00, 0x2d, 0x11, 0xf0, 0x00, 0xf4, 0x20, 0x00, 0x20, 0x21, 0xd4, 0xe5, 0xc0, 
+        0x20, 0x00, 0x02, 0x62, 0xff, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0x32, 0xa0, 0x0e, 0x12, 0xc1, 0xe0, 0xd2, 0x61, 0x02, 0x02, 0x61, 0x00, 
+        0xf9, 0x41, 0xe9, 0x31, 0xc9, 0x11, 0x0c, 0x1e, 0xc1, 0xb0, 0xe9, 0x0c, 0xff, 0xe7, 0x33, 0x06, 
+        0x8c, 0x3e, 0x2d, 0x0e, 0x05, 0xd5, 0x01, 0x0c, 0x0d, 0xc0, 0x20, 0x00, 0x22, 0xa0, 0x07, 0x32, 
+        0xa0, 0x05, 0x42, 0x2c, 0x80, 0x51, 0xce, 0xff, 0x05, 0x6a, 0xfa, 0x20, 0x40, 0x74, 0x16, 0x54, 
+        0x00, 0x22, 0xac, 0xe0, 0x46, 0x02, 0x00, 0x01, 0x23, 0xe7, 0x08, 0x00, 0x08, 0xa0, 0xc0, 0x00, 
+        0x00, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0x66, 0x5d, 0xcf, 0x0c, 0xe3, 0x1b, 0xee, 0xe0, 0xe0, 0x74, 
+        0xf7, 0x9e, 0xb9, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x00, 0x00, 0x21, 0xb2, 0xe5, 0xc0, 0x20, 0x00, 0x22, 0x22, 0xff, 0x0d, 0xf0, 0x00, 
+        0x10, 0x82, 0xfe, 0x3f, 0x12, 0xc1, 0xd0, 0xf2, 0x61, 0x08, 0x02, 0x61, 0x04, 0xe9, 0x71, 0xc9, 
+        0x51, 0xd9, 0x61, 0xcd, 0x04, 0xdd, 0x02, 0xed, 0x03, 0x2d, 0x01, 0x31, 0xf9, 0xff, 0x1c, 0x04, 
+        0x85, 0x1d, 0x03, 0xf6, 0x3c, 0x12, 0x2d, 0x0d, 0x3d, 0x0e, 0x0c, 0x34, 0xc0, 0x44, 0xc0, 0x05, 
+        0x3d, 0x03, 0xed, 0x03, 0xdd, 0x02, 0x06, 0x04, 0x00, 0xd0, 0x2d, 0x20, 0xe0, 0x3e, 0x20, 0x42, 
+        0xcc, 0xfd, 0xc5, 0x3e, 0x03, 0x30, 0xe3, 0x20, 0xdd, 0x02, 0x3c, 0xfc, 0x0c, 0x1f, 0xf0, 0x2f, 
+        0x20, 0x32, 0xa0, 0x00, 0x4d, 0x0c, 0x85, 0x3a, 0x03, 0x20, 0x2d, 0x10, 0x30, 0x3e, 0x10, 0x4d, 
+        0x0c, 0xc5, 0x3c, 0x03, 0x0c, 0x17, 0x30, 0x37, 0x93, 0x20, 0x27, 0x93, 0x30, 0x62, 0x20, 0xcc, 
+        0x66, 0x0b, 0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x2c, 0xd4, 0xc2, 0xcc, 0xfd, 0x80, 0xcc, 0x01, 0xc0, 
+        0xc8, 0x31, 0xe6, 0x2c, 0x26, 0x08, 0x41, 0xe8, 0x71, 0xf8, 0x81, 0xb0, 0x4c, 0x11, 0xd0, 0x20, 
+        0x34, 0xc0, 0x3c, 0x11, 0xd8, 0x61, 0x1a, 0x22, 0xc8, 0x51, 0x22, 0x02, 0x00, 0x4a, 0x33, 0x3a, 
+        0x22, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0xd0, 0x2d, 0x20, 0xe0, 
+        0x3e, 0x20, 0x42, 0xcc, 0xff, 0x85, 0x37, 0x03, 0xdd, 0x02, 0xc6, 0xf1, 0xff, 0x00, 0x00, 0x00, 
+        0xbc, 0x86, 0xfe, 0x3f, 0xe4, 0x86, 0xfe, 0x3f, 0x0c, 0x87, 0xfe, 0x3f, 0x24, 0x87, 0xfe, 0x3f, 
+        0xe4, 0xfb, 0x07, 0x00, 0x30, 0x87, 0xfe, 0x3f, 0x58, 0x87, 0xfe, 0x3f, 0x80, 0x87, 0xfe, 0x3f, 
+        0x52, 0xa0, 0xd0, 0x50, 0x11, 0xc0, 0xd2, 0x61, 0x1b, 0xe2, 0x61, 0x1c, 0x02, 0x61, 0x19, 0x22, 
+        0x61, 0x21, 0x32, 0x61, 0x11, 0x42, 0x61, 0x32, 0xc2, 0x61, 0x1a, 0xf2, 0x61, 0x1d, 0xc1, 0x6f, 
+        0xe5, 0xfd, 0x04, 0x16, 0x54, 0x06, 0x21, 0xee, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xe0, 0xc0, 
+        0x20, 0x00, 0x42, 0x2c, 0xe1, 0xc0, 0x20, 0x00, 0x52, 0x2c, 0xe2, 0xc0, 0x20, 0x00, 0x62, 0x2c, 
+        0xe3, 0x01, 0xfb, 0xe6, 0xc0, 0x00, 0x00, 0x21, 0xe7, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf3, 
+        0xc0, 0x20, 0x00, 0x42, 0x2c, 0xf4, 0xc0, 0x20, 0x00, 0x52, 0x2c, 0xf5, 0xc0, 0x20, 0x00, 0x62, 
+        0x2c, 0xf6, 0x01, 0xf3, 0xe6, 0xc0, 0x00, 0x00, 0x21, 0xe0, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x2c, 
+        0xf7, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xf8, 0x01, 0xee, 0xe6, 0xc0, 0x00, 0x00, 0x21, 0xdb, 0xff, 
+        0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf9, 0x01, 0xea, 0xe6, 0xc0, 0x00, 0x00, 0xd1, 0xd9, 0xff, 0x0c, 
+        0x0e, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xe3, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xe0, 0x5d, 0x0e, 0x4a, 
+        0x33, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x71, 0x02, 0x39, 0xf1, 0x22, 0x61, 
+        0x26, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xe2, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xe1, 0x5d, 0x0e, 0x40, 
+        0x33, 0xc0, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x6f, 0x02, 0x32, 0x61, 0x10, 
+        0x29, 0xe1, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xf6, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf3, 0x5d, 0x0e, 
+        0x4a, 0x33, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x6d, 0x02, 0x32, 0x61, 0x1e, 
+        0x22, 0x61, 0x31, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xf5, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf4, 0x5d, 
+        0x0e, 0x40, 0x33, 0xc0, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0x85, 0x6b, 0x02, 0x08, 
+        0xe1, 0x42, 0x21, 0x31, 0xa2, 0x21, 0x10, 0x58, 0xf1, 0x72, 0x21, 0x26, 0xbd, 0x05, 0x1b, 0x67, 
+        0x77, 0xb6, 0x01, 0x1b, 0xb5, 0x7d, 0x0a, 0x1b, 0x50, 0x07, 0xb5, 0x01, 0x1b, 0x7a, 0xa2, 0x21, 
+        0x1e, 0x1b, 0x04, 0x1b, 0x82, 0x82, 0x61, 0x12, 0x47, 0xb0, 0x01, 0x1b, 0xaa, 0x4d, 0x03, 0x27, 
+        0xb8, 0x01, 0x1b, 0x43, 0x22, 0x21, 0x12, 0x00, 0x41, 0x40, 0x50, 0x57, 0x81, 0x00, 0x3a, 0x81, 
+        0x60, 0x9b, 0x81, 0x92, 0x61, 0x23, 0x32, 0x61, 0x2e, 0x52, 0x61, 0x2c, 0x20, 0x24, 0x81, 0x70, 
+        0x01, 0x21, 0x02, 0x61, 0x2b, 0x22, 0x61, 0x1f, 0xb0, 0x51, 0x21, 0x52, 0x61, 0x22, 0x3d, 0x05, 
+        0xa0, 0xb1, 0x21, 0x2d, 0x09, 0x40, 0xa1, 0x21, 0xb2, 0x61, 0x2d, 0x4d, 0x09, 0xa2, 0x61, 0x20, 
+        0xc5, 0x60, 0x02, 0x22, 0x61, 0x28, 0x32, 0x61, 0x27, 0x52, 0x21, 0x2b, 0x42, 0x21, 0x2c, 0x3d, 
+        0x05, 0x2d, 0x04, 0xc5, 0x5f, 0x02, 0x22, 0x61, 0x2a, 0x32, 0x61, 0x29, 0x52, 0x21, 0x2d, 0x42, 
+        0x21, 0x2e, 0x3d, 0x05, 0x2d, 0x04, 0x85, 0x5e, 0x02, 0x22, 0x61, 0x2f, 0x32, 0x61, 0x30, 0x52, 
+        0x21, 0x20, 0x42, 0x21, 0x1f, 0x3d, 0x05, 0x2d, 0x04, 0x45, 0x5d, 0x02, 0x72, 0x21, 0x2f, 0x62, 
+        0x21, 0x28, 0x02, 0x21, 0x29, 0xa2, 0x21, 0x27, 0xb2, 0x21, 0x30, 0x0a, 0xaa, 0x02, 0x21, 0x2a, 
+        0x3a, 0xbb, 0x0a, 0x06, 0x67, 0xb0, 0x01, 0x1b, 0xaa, 0x2a, 0x67, 0x77, 0xb6, 0x01, 0x1b, 0xbb, 
+        0xba, 0xaa, 0x6a, 0xb0, 0xb9, 0xc1, 0x07, 0xbb, 0x01, 0x1b, 0xaa, 0xa9, 0xd1, 0xac, 0xff, 0x52, 
+        0x21, 0x22, 0x42, 0x21, 0x23, 0x72, 0x21, 0x2b, 0x62, 0x21, 0x2c, 0x02, 0x21, 0x2e, 0x22, 0x21, 
+        0x2d, 0x88, 0xc1, 0x98, 0xd1, 0xa2, 0x21, 0x1f, 0xb2, 0x21, 0x20, 0xb9, 0x31, 0xa9, 0x21, 0x99, 
+        0x51, 0x89, 0x41, 0x29, 0x11, 0x09, 0x01, 0x21, 0x77, 0xff, 0x01, 0x85, 0xe6, 0xc0, 0x00, 0x00, 
+        0xc0, 0x20, 0x00, 0x42, 0x2c, 0xe3, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xe0, 0x5d, 0x0e, 0x40, 0x33, 
+        0xc0, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x58, 0x02, 0x39, 0xf1, 0x22, 0x61, 
+        0x26, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xe2, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xe1, 0x5d, 0x0e, 0x4a, 
+        0x33, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x56, 0x02, 0x32, 0x61, 0x10, 0x29, 
+        0xe1, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xf6, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf3, 0x5d, 0x0e, 0x40, 
+        0x33, 0xc0, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x54, 0x02, 0x32, 0x61, 0x1e, 
+        0x22, 0x61, 0x31, 0x5d, 0x0e, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xf5, 0xc0, 0x20, 0x00, 0x32, 0x2c, 
+        0xf4, 0x4a, 0x33, 0x10, 0x23, 0x11, 0x4d, 0x0d, 0x30, 0x31, 0x31, 0xc5, 0x52, 0x02, 0x02, 0x21, 
+        0x1e, 0x42, 0x21, 0x10, 0xd2, 0x21, 0x31, 0xa8, 0xe1, 0x58, 0xf1, 0x72, 0x21, 0x26, 0xbd, 0x05, 
+        0x1b, 0x67, 0x77, 0xb6, 0x01, 0x1b, 0xb5, 0x7d, 0x04, 0x1b, 0x5a, 0xa7, 0xb5, 0x01, 0x1b, 0x74, 
+        0xad, 0x00, 0xed, 0x03, 0x1b, 0x4d, 0xd7, 0xb4, 0x01, 0x1b, 0xa0, 0x0d, 0x04, 0x1b, 0xd2, 0x27, 
+        0xbd, 0x01, 0x1b, 0xe3, 0x00, 0x41, 0x40, 0xa0, 0x81, 0x21, 0x70, 0x91, 0x21, 0x92, 0x61, 0x2b, 
+        0x82, 0x61, 0x2d, 0x50, 0x27, 0x81, 0x00, 0x0a, 0x81, 0xd0, 0xde, 0x81, 0x60, 0x4b, 0x81, 0x42, 
+        0x61, 0x23, 0xe0, 0xe1, 0x21, 0x02, 0x61, 0x2e, 0x22, 0x61, 0x2c, 0xb0, 0x51, 0x21, 0x52, 0x61, 
+        0x22, 0x3d, 0x05, 0x2d, 0x04, 0x85, 0x48, 0x02, 0x22, 0x61, 0x28, 0x32, 0x61, 0x27, 0x52, 0x21, 
+        0x2b, 0x42, 0x21, 0x2c, 0x3d, 0x05, 0x2d, 0x04, 0x45, 0x47, 0x02, 0x22, 0x61, 0x2a, 0x32, 0x61, 
+        0x29, 0x52, 0x21, 0x2d, 0x42, 0x21, 0x2e, 0x3d, 0x05, 0x2d, 0x04, 0x45, 0x46, 0x02, 0x5d, 0x0e, 
+        0x4d, 0x0d, 0x32, 0x61, 0x30, 0x22, 0x61, 0x2f, 0x3d, 0x0e, 0x2d, 0x0d, 0x05, 0x45, 0x02, 0xb2, 
+        0x21, 0x2f, 0x72, 0x21, 0x30, 0x68, 0xc1, 0x02, 0x21, 0x29, 0xa2, 0x21, 0x27, 0x42, 0x21, 0x28, 
+        0x0a, 0xaa, 0x02, 0x21, 0x2a, 0x58, 0xd1, 0x0a, 0x04, 0x47, 0xb0, 0x01, 0x1b, 0xaa, 0x3a, 0x77, 
+        0x2a, 0x4b, 0xb7, 0xb4, 0x01, 0x1b, 0x77, 0x7a, 0xba, 0x4a, 0xa0, 0x07, 0xba, 0x01, 0x1b, 0xbb, 
+        0x22, 0x21, 0x21, 0x5a, 0x3b, 0xb9, 0x72, 0xa9, 0x62, 0x6a, 0x2a, 0xa7, 0xb2, 0x01, 0x1b, 0x33, 
+        0x22, 0x61, 0x25, 0x32, 0x61, 0x24, 0xac, 0xaf, 0xe9, 0x31, 0xd9, 0x21, 0x52, 0x21, 0x22, 0x42, 
+        0x21, 0x23, 0x72, 0x21, 0x2b, 0x62, 0x21, 0x2c, 0x21, 0x17, 0xff, 0x82, 0x21, 0x25, 0x9d, 0x03, 
+        0xa2, 0x21, 0x2e, 0xb2, 0x21, 0x2d, 0xb9, 0x11, 0xa9, 0x01, 0x99, 0x51, 0x89, 0x41, 0x01, 0x20, 
+        0xe6, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0xd2, 0x2c, 0xf7, 0xd0, 0xd3, 0x21, 0xd0, 0x7f, 0x31, 
+        0xc0, 0x20, 0x00, 0xa2, 0x2c, 0xf8, 0x1b, 0x6d, 0xa0, 0xa3, 0x21, 0xa0, 0x4f, 0x31, 0xd7, 0xb6, 
+        0x01, 0x1b, 0x77, 0x0d, 0x04, 0x1b, 0x5a, 0xa7, 0xb5, 0x01, 0x1b, 0x04, 0x00, 0xd1, 0x21, 0x00, 
+        0x41, 0x40, 0x50, 0xe0, 0x81, 0x60, 0x47, 0x81, 0x42, 0x61, 0x0b, 0x40, 0x24, 0x20, 0x70, 0x51, 
+        0x21, 0x59, 0xa1, 0x3d, 0x05, 0x85, 0x39, 0x02, 0x5d, 0x0d, 0x4d, 0x0e, 0x32, 0x61, 0x13, 0x22, 
+        0x61, 0x14, 0x3d, 0x0d, 0x2d, 0x0e, 0x85, 0x38, 0x02, 0x02, 0x21, 0x13, 0xd9, 0x91, 0x3a, 0x00, 
+        0x32, 0x21, 0x14, 0xe9, 0x81, 0x2a, 0xa3, 0x37, 0xba, 0x01, 0x1b, 0x00, 0xa0, 0xda, 0x20, 0x00, 
+        0xe0, 0x20, 0x16, 0x4f, 0x02, 0x21, 0xf4, 0xfe, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf7, 0xc0, 0x20, 
+        0x00, 0x78, 0xa1, 0x58, 0x81, 0x68, 0x91, 0x42, 0x2c, 0xf8, 0xa9, 0x21, 0x09, 0x31, 0x69, 0x11, 
+        0x59, 0x01, 0x68, 0xb1, 0x01, 0xfb, 0xe5, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0xf9, 
+        0x42, 0x21, 0x11, 0x2d, 0x03, 0x6b, 0x44, 0x30, 0x3f, 0x31, 0x45, 0xec, 0x02, 0x0d, 0x02, 0x4d, 
+        0x03, 0xe0, 0x53, 0xc0, 0xd0, 0x72, 0xc0, 0x77, 0xb2, 0x01, 0x0b, 0x55, 0x32, 0x21, 0x24, 0x62, 
+        0x21, 0x25, 0x30, 0x35, 0xc0, 0x60, 0x67, 0xc0, 0x67, 0xb7, 0x01, 0x0b, 0x33, 0x0c, 0x07, 0x0c, 
+        0x05, 0xe6, 0x13, 0x07, 0xcc, 0x03, 0xcc, 0x26, 0x6d, 0x05, 0x3d, 0x07, 0x62, 0x61, 0x17, 0x32, 
+        0x61, 0x18, 0x42, 0x61, 0x16, 0x02, 0x61, 0x15, 0x9c, 0xff, 0x21, 0xd8, 0xfe, 0xc0, 0x20, 0x00, 
+        0x32, 0x2c, 0xf9, 0x52, 0x21, 0x16, 0x42, 0x21, 0x15, 0x72, 0x21, 0x18, 0x62, 0x21, 0x17, 0x01, 
+        0xe0, 0xe5, 0xc0, 0x00, 0x00, 0x02, 0x21, 0x15, 0x42, 0x21, 0x16, 0xc2, 0x21, 0x17, 0xf2, 0x21, 
+        0x18, 0x22, 0x21, 0x25, 0x82, 0x21, 0x21, 0x32, 0x21, 0x24, 0xe9, 0x58, 0xd9, 0x48, 0x39, 0x38, 
+        0x29, 0x28, 0x49, 0x18, 0x09, 0x08, 0x0c, 0x34, 0x85, 0xa4, 0xff, 0x3d, 0x0f, 0xdd, 0x02, 0x0c, 
+        0x34, 0x2d, 0x0c, 0x05, 0xa4, 0xff, 0x02, 0x21, 0x19, 0xc2, 0x21, 0x1a, 0xe2, 0x21, 0x1c, 0xf2, 
+        0x21, 0x1d, 0x20, 0x2d, 0xc0, 0x32, 0xa0, 0xd0, 0xd2, 0x21, 0x1b, 0x00, 0x22, 0x11, 0x20, 0x20, 
+        0x31, 0x3a, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x82, 0xfe, 0x3f, 0x08, 0x00, 0x24, 0x00, 
+        0x07, 0x00, 0x24, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x88, 0x13, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x32, 
+        0xa0, 0x00, 0x42, 0xa0, 0x12, 0x52, 0xa0, 0x07, 0x0c, 0x06, 0x12, 0xc1, 0xa0, 0xd9, 0xf1, 0xc9, 
+        0xe1, 0xc1, 0x90, 0xe5, 0x09, 0xd1, 0x08, 0x0c, 0xe2, 0x61, 0x10, 0x02, 0x20, 0x25, 0xf2, 0x61, 
+        0x11, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x28, 0x29, 0xc1, 0xc0, 0x00, 0x00, 0x08, 0x0c, 
+        0x02, 0x20, 0x34, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x0c, 0x72, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 
+        0x2b, 0x0c, 0xf4, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 
+        0xa1, 0x04, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x0c, 0x03, 0x42, 0xa1, 0xf4, 0x08, 0x0c, 0x0c, 0xc5, 
+        0x02, 0x20, 0x3a, 0x6d, 0x01, 0xc0, 0x00, 0x00, 0x6c, 0xf3, 0xd1, 0x14, 0xe4, 0xc0, 0x20, 0x00, 
+        0x22, 0x2d, 0xe4, 0x30, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x0c, 0x03, 0x0c, 0x94, 0x0c, 0x75, 0x0c, 
+        0x06, 0x0c, 0x07, 0x08, 0x0c, 0x22, 0x6d, 0xe4, 0x02, 0x20, 0x27, 0x22, 0xa0, 0x77, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 
+        0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 0x25, 0x08, 
+        0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 
+        0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x76, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 
+        0x0c, 0x0d, 0x0c, 0x6f, 0x0c, 0x0e, 0x0c, 0x0a, 0xb1, 0x89, 0xec, 0xb2, 0x61, 0x12, 0xa2, 0x61, 
+        0x13, 0x61, 0xc1, 0xff, 0x52, 0x21, 0x13, 0x6a, 0x55, 0x52, 0x05, 0x00, 0x42, 0xa1, 0x00, 0x80, 
+        0x55, 0x01, 0x50, 0x58, 0x31, 0x50, 0x44, 0xc0, 0x40, 0x40, 0x74, 0x60, 0x44, 0x11, 0xc0, 0x20, 
+        0x00, 0x31, 0xee, 0xe3, 0x51, 0x70, 0xec, 0x62, 0x23, 0xee, 0x71, 0xb8, 0xff, 0x50, 0x66, 0x10, 
+        0x40, 0x66, 0x20, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x63, 0xee, 0xc0, 0x20, 0x00, 0x22, 
+        0x23, 0xef, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0x41, 0xb2, 0xff, 0x40, 0x22, 0x20, 0xc0, 0x20, 
+        0x00, 0x4d, 0x0e, 0x08, 0x0c, 0x22, 0x63, 0xef, 0x0c, 0x32, 0x02, 0x20, 0x2b, 0x0c, 0x13, 0xc0, 
+        0x00, 0x00, 0x0c, 0x32, 0x08, 0x0c, 0x0c, 0x23, 0x02, 0x20, 0x2b, 0x4d, 0x0f, 0xc0, 0x00, 0x00, 
+        0x2d, 0x0e, 0x3d, 0x0f, 0x42, 0x21, 0x12, 0x05, 0x50, 0xf9, 0x08, 0x0c, 0x08, 0xf0, 0x0c, 0x12, 
+        0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x10, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x0c, 
+        0x12, 0x08, 0xd0, 0x32, 0xa4, 0x00, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x21, 0xd0, 0xe3, 0x08, 
+        0x0c, 0x22, 0x22, 0xf9, 0x08, 0xc0, 0x22, 0x61, 0x14, 0xc0, 0x00, 0x00, 0x31, 0xbd, 0xe9, 0x02, 
+        0x21, 0x14, 0x1b, 0xdd, 0x37, 0x20, 0x08, 0x21, 0x97, 0xff, 0x07, 0xa2, 0x36, 0x37, 0xa0, 0x1f, 
+        0x66, 0x6f, 0x04, 0x1c, 0xef, 0x86, 0x08, 0x00, 0x0c, 0x6f, 0xcc, 0x3e, 0x4c, 0x0e, 0xc6, 0x02, 
+        0x00, 0x42, 0xa0, 0x60, 0x52, 0xce, 0xc0, 0xe0, 0xe0, 0xf4, 0x50, 0xe4, 0x83, 0x86, 0x02, 0x00, 
+        0x62, 0x21, 0x13, 0x1b, 0x76, 0x70, 0x60, 0x74, 0x62, 0x61, 0x13, 0xd0, 0xd0, 0x74, 0x82, 0xcd, 
+        0xfb, 0x56, 0xc8, 0xf0, 0x0c, 0x0e, 0x0c, 0x0d, 0x08, 0x0c, 0x0c, 0x12, 0x08, 0xd0, 0x31, 0xc8, 
+        0xfa, 0xc0, 0x00, 0x00, 0x22, 0xc1, 0x10, 0x0c, 0xe3, 0x0c, 0x04, 0x45, 0x8f, 0xff, 0x08, 0x0c, 
+        0x08, 0xc0, 0xfd, 0x02, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0xe7, 0xaf, 0x01, 0xfd, 
+        0x0e, 0x00, 0xef, 0x11, 0xe0, 0xe0, 0x31, 0x66, 0x4d, 0xcd, 0x32, 0xa0, 0x23, 0x41, 0x7a, 0xff, 
+        0x52, 0xa0, 0x07, 0x22, 0xce, 0x08, 0x20, 0x24, 0x21, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x45, 
+        0xde, 0xf9, 0xd1, 0xa6, 0xe3, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 0x75, 0x0c, 0x06, 
+        0x08, 0x0c, 0x78, 0xc1, 0x02, 0x20, 0x27, 0x70, 0x70, 0x74, 0xc0, 0x00, 0x00, 0x1c, 0x04, 0xc0, 
+        0x20, 0x00, 0x22, 0x2d, 0xe4, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x0c, 0x03, 0x0c, 0x25, 0x0c, 
+        0x26, 0x0c, 0x07, 0x08, 0x0c, 0x22, 0x6d, 0xe4, 0x02, 0x20, 0x27, 0x22, 0xa0, 0x77, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x76, 0x02, 0x20, 
+        0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x1b, 0x0c, 0x02, 0xc0, 0x00, 0x00, 
+        0x08, 0x0c, 0x02, 0x20, 0x10, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x08, 0xc0, 0xc0, 0x00, 
+        0x00, 0x08, 0x0c, 0x02, 0x20, 0x32, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x31, 0xc0, 0x00, 
+        0x00, 0x08, 0x0c, 0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0xc8, 0xe1, 0xd8, 0xf1, 0xe2, 0x21, 0x10, 
+        0xf2, 0x21, 0x11, 0x08, 0xd1, 0x12, 0xc1, 0x60, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x13, 0x40, 0x12, 
+        0xc1, 0xf0, 0x49, 0x01, 0xc9, 0x21, 0x09, 0x11, 0xcd, 0x03, 0x01, 0xe2, 0xe4, 0x0c, 0x13, 0x08, 
+        0x00, 0x00, 0x33, 0xa1, 0x08, 0xd0, 0x30, 0x30, 0xf4, 0xc0, 0x00, 0x00, 0x21, 0x78, 0xe3, 0x6b, 
+        0x5c, 0x0b, 0x6c, 0x0c, 0x14, 0x00, 0x16, 0x40, 0x00, 0x44, 0xa1, 0xc0, 0x20, 0x00, 0x38, 0x01, 
+        0x62, 0x22, 0xf7, 0x00, 0x05, 0x40, 0x4a, 0x66, 0x60, 0x60, 0xb1, 0x62, 0x53, 0x00, 0xc0, 0x20, 
+        0x00, 0x00, 0x05, 0x40, 0x22, 0x22, 0xf8, 0x01, 0xd3, 0xe4, 0x4a, 0x22, 0x08, 0x00, 0x20, 0x20, 
+        0xb1, 0x08, 0xc0, 0x22, 0x53, 0x01, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0x08, 0x11, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 0x75, 0x0c, 0x06, 0x12, 
+        0xc1, 0xb0, 0xc9, 0x41, 0xd9, 0x51, 0xd1, 0xc7, 0xe4, 0x09, 0x31, 0x08, 0x0d, 0xe9, 0x61, 0x02, 
+        0x20, 0x25, 0xf9, 0x71, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 0x75, 0x0c, 0x06, 0x0c, 
+        0x07, 0x08, 0x0d, 0xed, 0x02, 0x02, 0x20, 0x27, 0x22, 0xa0, 0x77, 0xc0, 0x00, 0x00, 0x6c, 0xf3, 
+        0xc1, 0x57, 0xe3, 0xc0, 0x20, 0x00, 0x22, 0x2c, 0xe4, 0x30, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x08, 
+        0x0d, 0xe2, 0x61, 0x13, 0x02, 0x20, 0x28, 0x22, 0x6c, 0xe4, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 
+        0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x0c, 0x04, 0xc0, 0x00, 0x00, 0x0c, 0x32, 0x08, 0x0d, 0x0c, 
+        0x13, 0x02, 0x20, 0x2b, 0x0c, 0x04, 0xc0, 0x00, 0x00, 0x0c, 0x32, 0x08, 0x0d, 0x0c, 0x23, 0x02, 
+        0x20, 0x2b, 0x0c, 0x64, 0xc0, 0x00, 0x00, 0x08, 0x0d, 0x02, 0x20, 0x10, 0x0c, 0x12, 0xc0, 0x00, 
+        0x00, 0x0c, 0x0c, 0x0c, 0x0f, 0x0c, 0x0e, 0x22, 0xa2, 0x00, 0x0c, 0x15, 0x0c, 0x16, 0x0c, 0x17, 
+        0x0c, 0x18, 0x0c, 0x09, 0x0c, 0x0a, 0xa9, 0x21, 0x99, 0x11, 0x89, 0xc1, 0x79, 0xd1, 0x69, 0xe1, 
+        0x59, 0xf1, 0x22, 0x61, 0x12, 0x0c, 0x42, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x4d, 0x0c, 
+        0xc0, 0x00, 0x00, 0x0c, 0x42, 0x08, 0x0d, 0x0c, 0x23, 0x02, 0x20, 0x2b, 0x4d, 0x0c, 0xc0, 0x00, 
+        0x00, 0x0c, 0x52, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x4d, 0x0c, 0xc0, 0x00, 0x00, 0x0c, 
+        0x52, 0x08, 0x0d, 0x0c, 0x23, 0x02, 0x20, 0x2b, 0x4d, 0x0c, 0xc0, 0x00, 0x00, 0x0c, 0xa2, 0x01, 
+        0x0c, 0xe4, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x0c, 0x63, 0x4d, 0x01, 0x05, 0xea, 0xff, 0x08, 0x11, 
+        0x48, 0x21, 0x92, 0xaf, 0x00, 0xa2, 0xa0, 0xff, 0x78, 0xe1, 0x28, 0xf1, 0x62, 0x91, 0x00, 0x8c, 
+        0xc2, 0x67, 0xa9, 0x0a, 0x0b, 0x3c, 0x0c, 0x05, 0x59, 0xf1, 0x30, 0x30, 0xf4, 0x39, 0xb1, 0x28, 
+        0xd1, 0x52, 0x91, 0x01, 0x8c, 0xc7, 0x57, 0xa9, 0x0a, 0x0b, 0x8c, 0x0c, 0x0b, 0xb9, 0xe1, 0x80, 
+        0x80, 0xf4, 0x89, 0xa1, 0x88, 0xc1, 0x8c, 0x72, 0xa7, 0x96, 0x05, 0xc9, 0x91, 0x0c, 0x03, 0x39, 
+        0xd1, 0x8c, 0x78, 0xa7, 0x95, 0x05, 0xc9, 0x81, 0x0c, 0x0b, 0xb9, 0xc1, 0x16, 0x7c, 0x04, 0x82, 
+        0x21, 0x10, 0x80, 0x86, 0xc0, 0x00, 0x88, 0x11, 0x80, 0x80, 0x31, 0x7d, 0x08, 0xe7, 0xa8, 0x01, 
+        0x7d, 0x0e, 0xb2, 0x21, 0x11, 0x00, 0xe7, 0x11, 0xe0, 0xe0, 0x31, 0xb0, 0xb5, 0xc0, 0x87, 0xa0, 
+        0x01, 0x8d, 0x00, 0x00, 0x08, 0x11, 0x00, 0x00, 0x31, 0x00, 0x8b, 0x11, 0x80, 0x80, 0x31, 0x7d, 
+        0x08, 0xf7, 0xa8, 0x01, 0x7d, 0x0f, 0x00, 0xf7, 0x11, 0xf0, 0xf0, 0x31, 0x87, 0xa4, 0x01, 0x8d, 
+        0x04, 0x00, 0x48, 0x11, 0x40, 0x40, 0x31, 0x52, 0x61, 0x11, 0x62, 0x61, 0x10, 0x49, 0x21, 0x09, 
+        0x11, 0x72, 0x21, 0x12, 0x1b, 0xcc, 0xc0, 0xc0, 0xf4, 0x0b, 0x77, 0x72, 0x61, 0x12, 0x56, 0x37, 
+        0xf0, 0x08, 0x0d, 0x02, 0x20, 0x10, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x42, 0x21, 0x13, 0x51, 0xf0, 
+        0xf5, 0x01, 0x33, 0xe3, 0xe6, 0x6e, 0x04, 0x28, 0x11, 0xd6, 0x62, 0x00, 0x38, 0x05, 0x00, 0x33, 
+        0x20, 0x39, 0x05, 0x88, 0xb1, 0xe6, 0x6f, 0x04, 0x68, 0x21, 0xd6, 0x66, 0x00, 0x78, 0x05, 0x00, 
+        0x77, 0x20, 0x79, 0x05, 0x02, 0xa0, 0x6d, 0x87, 0xb0, 0x11, 0x98, 0xa1, 0xa8, 0x91, 0x97, 0xb0, 
+        0x0a, 0x02, 0xa1, 0x90, 0xa7, 0x30, 0x04, 0xb8, 0x81, 0xb7, 0xb0, 0x09, 0xe1, 0x22, 0xe3, 0xc8, 
+        0x05, 0xe0, 0xcc, 0x20, 0xc9, 0x05, 0xc1, 0xe5, 0xe2, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x75, 
+        0x0c, 0x06, 0x08, 0x0d, 0x40, 0x70, 0x74, 0x02, 0x20, 0x27, 0x1c, 0x24, 0xc0, 0x00, 0x00, 0x1c, 
+        0x03, 0xc0, 0x20, 0x00, 0x22, 0x2c, 0xe4, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x08, 0x0d, 0x02, 
+        0x20, 0x2f, 0x22, 0x6c, 0xe4, 0xc0, 0x00, 0x00, 0xc8, 0x41, 0xd8, 0x51, 0xe8, 0x61, 0xf8, 0x71, 
+        0x08, 0x31, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0x00, 0x30, 0x82, 0xfe, 0x3f, 0x40, 0x82, 0xfe, 0x3f, 
+        0x50, 0x82, 0xfe, 0x3f, 0x31, 0xfd, 0xff, 0x42, 0xa0, 0x0e, 0x22, 0xa0, 0xa0, 0x20, 0x11, 0xc0, 
+        0xd2, 0x61, 0x1e, 0xe2, 0x61, 0x1f, 0xf2, 0x61, 0x20, 0x22, 0xc1, 0x10, 0xc2, 0x61, 0x1d, 0x02, 
+        0x61, 0x1c, 0xc1, 0x30, 0xe4, 0x45, 0x66, 0x02, 0x02, 0x2c, 0x00, 0x02, 0x20, 0x28, 0xc0, 0x00, 
+        0x00, 0xd1, 0xf2, 0xf3, 0x08, 0x0c, 0x22, 0x1d, 0x00, 0x02, 0x20, 0x34, 0x20, 0x20, 0x44, 0xc0, 
+        0x00, 0x00, 0x22, 0x1d, 0x00, 0x32, 0xc1, 0x20, 0x05, 0x10, 0xfd, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 
+        0x13, 0x02, 0x20, 0x2b, 0x0c, 0x04, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x31, 0xc0, 0x00, 
+        0x00, 0x08, 0x0c, 0x02, 0x20, 0x10, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x0c, 0xf7, 0x0c, 0xea, 0x51, 
+        0xe3, 0xff, 0x31, 0xe3, 0xff, 0x0c, 0x00, 0x0c, 0x08, 0x82, 0x61, 0x21, 0xf0, 0xd0, 0x11, 0x30, 
+        0x30, 0x90, 0x5a, 0x50, 0x02, 0x61, 0x22, 0x72, 0x61, 0x25, 0x32, 0x13, 0x00, 0x98, 0x0c, 0x52, 
+        0x05, 0x00, 0x92, 0x29, 0x15, 0xa7, 0x90, 0x09, 0x0c, 0x02, 0x4c, 0x04, 0xc0, 0x09, 0x00, 0x06, 
+        0x02, 0x00, 0x4d, 0x05, 0x0c, 0x02, 0x0c, 0x65, 0xc0, 0x09, 0x00, 0x21, 0x81, 0xe5, 0x32, 0xc1, 
+        0x50, 0x0c, 0xa4, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x3b, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x0c, 
+        0x12, 0x4c, 0x03, 0x1c, 0x44, 0x0c, 0x05, 0x0c, 0x07, 0xe2, 0xd1, 0xff, 0x0c, 0x06, 0x69, 0x01, 
+        0x69, 0x11, 0x69, 0x21, 0x08, 0x0c, 0xe2, 0xce, 0x30, 0x02, 0x20, 0x1a, 0x0c, 0x06, 0xc0, 0x00, 
+        0x00, 0x0c, 0x0f, 0xea, 0x0d, 0x02, 0x61, 0x23, 0xd2, 0xa0, 0x80, 0xf2, 0x61, 0x24, 0xf2, 0xaf, 
+        0x80, 0x22, 0xa0, 0x77, 0x32, 0xa0, 0x00, 0x42, 0xa0, 0x09, 0x52, 0xa0, 0x07, 0x08, 0x0c, 0x0c, 
+        0x06, 0x02, 0x20, 0x27, 0x7d, 0x0d, 0xc0, 0x00, 0x00, 0x0c, 0x52, 0x01, 0x71, 0xe3, 0xc0, 0x00, 
+        0x00, 0x08, 0x0c, 0x0c, 0x12, 0x08, 0xd0, 0x32, 0xa4, 0x00, 0xc0, 0x00, 0x00, 0x22, 0xc1, 0x60, 
+        0x0c, 0xa3, 0x05, 0x89, 0xf9, 0x08, 0x0c, 0x08, 0xc0, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x22, 0x21, 
+        0x18, 0x08, 0xe0, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x0c, 0x03, 0x08, 0x0c, 0xed, 0x02, 0x08, 0xe0, 
+        0x22, 0x21, 0x19, 0xc0, 0x00, 0x00, 0x7c, 0x10, 0x42, 0x21, 0x23, 0x4b, 0x22, 0x4b, 0x3e, 0x30, 
+        0x33, 0x21, 0x20, 0x23, 0x21, 0x22, 0x54, 0x80, 0x00, 0x33, 0x11, 0x30, 0x30, 0x31, 0x00, 0x22, 
+        0x11, 0x20, 0x20, 0x31, 0x30, 0x22, 0xc0, 0x27, 0x20, 0x04, 0x1c, 0xe4, 0x47, 0xa3, 0x1c, 0x3c, 
+        0xc5, 0x57, 0xa3, 0x28, 0xf0, 0x33, 0x11, 0x30, 0x3f, 0xc0, 0x32, 0xc3, 0x78, 0x00, 0xf3, 0x11, 
+        0xf0, 0xf0, 0x31, 0xa6, 0xef, 0x02, 0x46, 0x53, 0x00, 0x30, 0xd0, 0x74, 0x42, 0x21, 0x24, 0x1b, 
+        0x54, 0x50, 0x40, 0x74, 0x42, 0x61, 0x24, 0x42, 0xc4, 0xf8, 0x56, 0x34, 0xf5, 0xd0, 0x7d, 0x20, 
+        0x22, 0xa0, 0x77, 0x32, 0xa0, 0x00, 0x42, 0xa0, 0x09, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 0x27, 
+        0x0c, 0x06, 0xc0, 0x00, 0x00, 0x0c, 0x52, 0x01, 0x46, 0xe3, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x0c, 
+        0x12, 0x08, 0xd0, 0x31, 0x9e, 0xe2, 0xc0, 0x00, 0x00, 0x22, 0xc1, 0x60, 0x0c, 0xc3, 0x45, 0x7e, 
+        0xf9, 0x08, 0x0c, 0x08, 0xc0, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x22, 0x21, 0x19, 0x08, 0xe0, 0x0c, 
+        0x03, 0xc0, 0x00, 0x00, 0x32, 0x21, 0x23, 0x02, 0xcf, 0x50, 0x4b, 0xe2, 0xd2, 0xcf, 0x51, 0x22, 
+        0x21, 0x22, 0xe0, 0xe3, 0x21, 0x00, 0xd0, 0xb3, 0xd0, 0xd1, 0x21, 0xd0, 0x0e, 0xc0, 0x02, 0x53, 
+        0x80, 0xbc, 0x02, 0xf6, 0x42, 0x02, 0xc6, 0x25, 0x00, 0x42, 0xc1, 0x90, 0x22, 0x21, 0x23, 0x32, 
+        0x21, 0x22, 0x22, 0x92, 0x7f, 0x4a, 0x33, 0x32, 0x03, 0x7f, 0x20, 0x20, 0xc0, 0x30, 0x22, 0xc0, 
+        0x08, 0x0c, 0x80, 0x22, 0x01, 0x08, 0x00, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 0xa6, 0x52, 0x70, 
+        0x0c, 0x13, 0x32, 0x61, 0x21, 0x08, 0x0c, 0x08, 0xc0, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 
+        0x1b, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0x0c, 0xea, 0x51, 0x6d, 0xff, 0x31, 0x6d, 0xff, 0x72, 0x21, 
+        0x25, 0x02, 0x21, 0x22, 0x0b, 0x77, 0x1b, 0x20, 0x20, 0x00, 0x74, 0xf0, 0xd0, 0x11, 0x30, 0x30, 
+        0x90, 0x5a, 0x50, 0x56, 0xd7, 0xe1, 0x08, 0x0c, 0x02, 0x20, 0x10, 0x0c, 0x02, 0xc0, 0x00, 0x00, 
+        0x08, 0x0c, 0x02, 0x20, 0x32, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x31, 0xc0, 0x00, 0x00, 
+        0x08, 0x0c, 0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0x22, 0x21, 0x21, 0xc2, 0x21, 0x1d, 0xd2, 0x21, 
+        0x1e, 0xe2, 0x21, 0x1f, 0xf2, 0x21, 0x20, 0x32, 0xa0, 0xa0, 0x02, 0x21, 0x1c, 0x3a, 0x11, 0x0d, 
+        0xf0, 0x22, 0x21, 0x22, 0xb6, 0x22, 0x8d, 0xd0, 0x2e, 0xc0, 0x52, 0xc1, 0x90, 0x32, 0x21, 0x22, 
+        0x08, 0x0c, 0x42, 0x21, 0x23, 0x08, 0x00, 0x42, 0x94, 0x7f, 0x5a, 0x33, 0x32, 0x03, 0x7f, 0x40, 
+        0x22, 0xc0, 0x30, 0x22, 0xc0, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0xc0, 0x00, 0x00, 0xa6, 0x72, 
+        0x02, 0xc6, 0xd6, 0xff, 0x46, 0xd7, 0xff, 0xd2, 0xa0, 0x7f, 0xf2, 0xa0, 0x7f, 0x06, 0xaf, 0xff, 
+        0x70, 0x82, 0xfe, 0x3f, 0x41, 0xff, 0xff, 0x32, 0xa0, 0x00, 0x12, 0xc1, 0xd0, 0xd9, 0x71, 0x22, 
+        0xc1, 0x10, 0xf9, 0x91, 0xe9, 0x81, 0xc9, 0x61, 0x09, 0x51, 0x0c, 0x0c, 0x0c, 0x20, 0xe1, 0x35, 
+        0xe6, 0xe9, 0xa1, 0x4a, 0x33, 0x4a, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xfe, 0x32, 0x13, 0x00, 0xe2, 
+        0xce, 0x44, 0x32, 0x52, 0x00, 0x02, 0x42, 0x02, 0x7d, 0x0f, 0x0c, 0x04, 0x68, 0xa1, 0x02, 0xa0, 
+        0x64, 0x31, 0xc3, 0xec, 0x51, 0x93, 0xf2, 0xc0, 0xdc, 0xa0, 0x1b, 0xdd, 0x52, 0x95, 0x00, 0x32, 
+        0x03, 0x01, 0x80, 0x2d, 0x01, 0x20, 0x28, 0x31, 0x09, 0x01, 0x05, 0x87, 0xfc, 0xc0, 0x2c, 0x11, 
+        0xc0, 0x22, 0xc0, 0x2a, 0x2e, 0x85, 0x17, 0xfc, 0xd0, 0x20, 0x74, 0x85, 0xcb, 0xff, 0x42, 0xc1, 
+        0x10, 0x4a, 0x4c, 0x22, 0x44, 0x00, 0x32, 0x01, 0x10, 0x52, 0x01, 0x11, 0x9c, 0x03, 0x8c, 0xe5, 
+        0x62, 0x01, 0x12, 0x8c, 0x96, 0x0c, 0x12, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x55, 0x45, 0x72, 0xf9, 
+        0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x3c, 0x9f, 0xc8, 0x61, 0xd8, 0x71, 0xe8, 0x81, 0xf8, 0x91, 
+        0x08, 0x51, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x00, 0xf6, 0x93, 0x03, 0x2c, 0x72, 0x0d, 0xf0, 0x0c, 
+        0xc4, 0x37, 0x34, 0x03, 0x2c, 0x42, 0x0d, 0xf0, 0x66, 0x22, 0x03, 0x2c, 0x12, 0x0d, 0xf0, 0x66, 
+        0x32, 0x03, 0x1c, 0xe2, 0x0d, 0xf0, 0x66, 0x42, 0x03, 0x1c, 0xb2, 0x0d, 0xf0, 0xf6, 0x72, 0x06, 
+        0xb6, 0x52, 0x03, 0x1c, 0x82, 0x0d, 0xf0, 0xf6, 0x92, 0x06, 0xb6, 0x72, 0x03, 0x1c, 0x52, 0x0d, 
+        0xf0, 0x0c, 0xd3, 0x27, 0x33, 0x06, 0xb6, 0x92, 0x03, 0x1c, 0x22, 0x0d, 0xf0, 0x1c, 0x66, 0x27, 
+        0x36, 0x06, 0x27, 0xb3, 0x03, 0x0c, 0xf2, 0x0d, 0xf0, 0x2c, 0x93, 0x27, 0x33, 0x06, 0x27, 0xb6, 
+        0x03, 0x0c, 0xc2, 0x0d, 0xf0, 0x5c, 0x86, 0x27, 0x36, 0x06, 0x27, 0xb3, 0x03, 0x0c, 0x92, 0x0d, 
+        0xf0, 0x32, 0xa1, 0x0a, 0x27, 0x33, 0x06, 0x27, 0xb6, 0x03, 0x0c, 0x62, 0x0d, 0xf0, 0x52, 0xa3, 
+        0x20, 0x27, 0x35, 0x06, 0x27, 0xb3, 0x03, 0x0c, 0x32, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 
+        0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x12, 0xc1, 0xa0, 0xf9, 0xf1, 0x39, 0xa1, 0x49, 
+        0x81, 0x69, 0x91, 0xd9, 0xd1, 0x09, 0xb1, 0xc9, 0xc1, 0xe9, 0xe1, 0xe1, 0x2e, 0xe3, 0xcd, 0x05, 
+        0x08, 0x0e, 0xdd, 0x02, 0x08, 0xf0, 0x0c, 0x12, 0xc0, 0x00, 0x00, 0xf1, 0xf5, 0xff, 0xd2, 0x61, 
+        0x17, 0x01, 0xc2, 0xe1, 0x41, 0xf4, 0xff, 0x0c, 0x03, 0x0c, 0x15, 0x2d, 0x03, 0xc0, 0x20, 0x00, 
+        0xb2, 0x20, 0xf1, 0x40, 0xbb, 0x10, 0x48, 0xa1, 0x40, 0xbb, 0x20, 0xf0, 0xbb, 0x20, 0xc0, 0x20, 
+        0x00, 0x32, 0x61, 0x10, 0x0c, 0x0f, 0x00, 0x1d, 0x40, 0x0c, 0x06, 0x0c, 0x07, 0x0c, 0x08, 0x0c, 
+        0x09, 0xb2, 0x60, 0xf1, 0x39, 0x1c, 0x39, 0x0c, 0x39, 0x3c, 0x39, 0x2c, 0x39, 0x5c, 0x39, 0x4c, 
+        0x39, 0x7c, 0x39, 0x6c, 0x92, 0x61, 0x11, 0x82, 0x61, 0x14, 0x72, 0x61, 0x12, 0x62, 0x61, 0x13, 
+        0x00, 0x45, 0xa1, 0x42, 0x61, 0x16, 0xe6, 0x14, 0x02, 0x06, 0x2b, 0x00, 0xf8, 0x81, 0x0c, 0x0d, 
+        0x00, 0x1f, 0x40, 0x00, 0x65, 0xa1, 0x60, 0x60, 0xf4, 0x62, 0x61, 0x15, 0x08, 0x0e, 0x0c, 0x12, 
+        0x08, 0xd0, 0x32, 0x21, 0x15, 0xc0, 0x00, 0x00, 0x3d, 0x0f, 0x2d, 0x01, 0x0c, 0x04, 0x05, 0x0b, 
+        0xff, 0x48, 0x2c, 0x58, 0x21, 0x38, 0x31, 0x08, 0x1c, 0x28, 0x0c, 0x3a, 0x00, 0x5a, 0x52, 0x27, 
+        0xb5, 0x01, 0x1b, 0x00, 0x38, 0x4c, 0x09, 0x1c, 0x59, 0x0c, 0x08, 0x3c, 0x28, 0x11, 0x58, 0x01, 
+        0x2a, 0x00, 0x5a, 0x54, 0x47, 0xb5, 0x01, 0x1b, 0x00, 0x09, 0x3c, 0x59, 0x2c, 0x08, 0x5c, 0x28, 
+        0x51, 0x58, 0x41, 0x2a, 0x00, 0x5a, 0x53, 0x37, 0xb5, 0x01, 0x1b, 0x00, 0x38, 0x6c, 0x09, 0x5c, 
+        0x59, 0x4c, 0x08, 0x7c, 0x28, 0x71, 0x58, 0x61, 0x2a, 0x00, 0x5a, 0x53, 0x37, 0xb5, 0x01, 0x1b, 
+        0x00, 0x28, 0x0e, 0x09, 0x7c, 0x08, 0xc2, 0x59, 0x6c, 0xc0, 0x00, 0x00, 0x32, 0x21, 0x16, 0x1b, 
+        0xdd, 0xd0, 0xd0, 0x74, 0xd0, 0x33, 0xc0, 0x56, 0x13, 0xf8, 0x38, 0x1c, 0x28, 0x0c, 0xf8, 0x4c, 
+        0x08, 0x6c, 0x48, 0x7c, 0x58, 0x5c, 0x68, 0x2c, 0x78, 0x3c, 0x72, 0x61, 0x10, 0x62, 0x61, 0x11, 
+        0x52, 0x61, 0x14, 0x42, 0x61, 0x12, 0x02, 0x61, 0x13, 0xd2, 0x21, 0x17, 0xd0, 0x4d, 0x20, 0x05, 
+        0x37, 0x02, 0x22, 0x6c, 0x00, 0x32, 0x6c, 0x01, 0x42, 0x21, 0x14, 0x32, 0x21, 0x10, 0x82, 0x21, 
+        0x11, 0x40, 0x33, 0xc0, 0xf0, 0x28, 0xc0, 0x27, 0xb8, 0x01, 0x0b, 0x33, 0xd0, 0x4d, 0x20, 0x05, 
+        0x35, 0x02, 0x4d, 0x0d, 0x29, 0x2c, 0x39, 0x3c, 0x2d, 0x0f, 0x32, 0x21, 0x14, 0x05, 0x34, 0x02, 
+        0x4d, 0x0d, 0x39, 0x5c, 0x29, 0x4c, 0x32, 0x21, 0x12, 0x22, 0x21, 0x13, 0x05, 0x33, 0x02, 0x39, 
+        0x7c, 0x29, 0x6c, 0x0c, 0x34, 0xc5, 0xef, 0xfe, 0x58, 0x0c, 0x48, 0x7c, 0x38, 0x1c, 0xdd, 0x02, 
+        0x28, 0x6c, 0x40, 0x33, 0xc0, 0x20, 0x25, 0xc0, 0x27, 0xb5, 0x01, 0x0b, 0x33, 0xc8, 0x91, 0xf1, 
+        0x67, 0xe1, 0x0c, 0x34, 0xc5, 0xed, 0xfe, 0x20, 0x4d, 0xc0, 0x00, 0x44, 0x11, 0x40, 0x40, 0x31, 
+        0x8b, 0x44, 0x40, 0x44, 0x21, 0x42, 0x5c, 0x00, 0xc0, 0x20, 0x00, 0x31, 0x92, 0xff, 0x22, 0x2f, 
+        0xf1, 0x30, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x08, 0x0e, 0x22, 0x6f, 0xf1, 0x08, 0xf0, 0x0c, 0x02, 
+        0xc0, 0x00, 0x00, 0xc8, 0xc1, 0xd8, 0xd1, 0xe8, 0xe1, 0xf8, 0xf1, 0x08, 0xb1, 0x12, 0xc1, 0x60, 
+        0x0d, 0xf0, 0x00, 0x00, 0xcf, 0x09, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xac, 0x87, 0xfe, 0x3f, 
+        0x24, 0x88, 0xfe, 0x3f, 0xcc, 0x87, 0xfe, 0x3f, 0xf4, 0x87, 0xfe, 0x3f, 0x04, 0x88, 0xfe, 0x3f, 
+        0x42, 0xa0, 0x12, 0x52, 0xa0, 0x07, 0x62, 0xa0, 0x00, 0x32, 0xa1, 0x10, 0x30, 0x11, 0xc0, 0xd2, 
+        0x61, 0x35, 0xe2, 0x61, 0x36, 0xf2, 0x61, 0x37, 0x0c, 0x03, 0xc2, 0x61, 0x34, 0xc1, 0xad, 0xe2, 
+        0x02, 0x61, 0x33, 0x08, 0x0c, 0x22, 0x61, 0x3d, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x77, 0xc0, 0x00, 
+        0x00, 0x6c, 0xf4, 0xed, 0x02, 0xd1, 0x41, 0xe1, 0x21, 0xfa, 0xeb, 0xc0, 0x20, 0x00, 0x32, 0x2d, 
+        0xe4, 0x40, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x0c, 0x04, 0x32, 0x6d, 0xe4, 0x52, 0xa0, 0x64, 0x31, 
+        0xe5, 0xff, 0x22, 0x02, 0x01, 0x45, 0x96, 0xfb, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 
+        0x75, 0x0c, 0x06, 0x08, 0x0c, 0x0c, 0x07, 0x02, 0x20, 0x27, 0xe2, 0x61, 0x41, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 
+        0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0c, 
+        0x0c, 0x76, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x0c, 0x0f, 0x3c, 0x3d, 0xe0, 0x8d, 
+        0x11, 0xc0, 0x20, 0x00, 0xe1, 0xfd, 0xe3, 0x78, 0xde, 0x92, 0xac, 0x00, 0x90, 0x77, 0x10, 0x80, 
+        0x77, 0x20, 0x0c, 0x18, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x79, 0xde, 0x0c, 0x52, 0x01, 0x00, 
+        0xe2, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x0c, 0x12, 0x08, 0xd0, 0x32, 0xa4, 0x00, 0xc0, 0x00, 0x00, 
+        0xc0, 0x20, 0x00, 0x08, 0x0c, 0xe1, 0x19, 0xe1, 0x08, 0xc0, 0xe2, 0x2e, 0xf9, 0xc0, 0x00, 0x00, 
+        0x01, 0xc2, 0xff, 0x1b, 0xff, 0xe7, 0xa0, 0x0e, 0xe2, 0x61, 0x30, 0x21, 0xa6, 0xe2, 0xd2, 0x61, 
+        0x2f, 0xe7, 0xa2, 0x1c, 0xe7, 0x20, 0x13, 0x3b, 0x3d, 0x30, 0xd0, 0x74, 0xf0, 0xf0, 0x74, 0x66, 
+        0x4f, 0x9b, 0xe2, 0x61, 0x30, 0xd2, 0x61, 0x2f, 0x46, 0x01, 0x00, 0x32, 0xcd, 0xfd, 0xc6, 0xf9, 
+        0xff, 0x0c, 0x0d, 0x0c, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x04, 0x0c, 0x05, 0x0c, 0x06, 0x62, 
+        0x61, 0x40, 0x52, 0x61, 0x3e, 0x42, 0x61, 0x3f, 0x0c, 0x62, 0x0c, 0x94, 0x52, 0xc1, 0x60, 0x32, 
+        0xcd, 0x2f, 0x62, 0xc1, 0x7f, 0x1b, 0x66, 0x00, 0x33, 0x11, 0x30, 0x30, 0x31, 0x85, 0xcc, 0xff, 
+        0x0c, 0x93, 0x0c, 0x00, 0x62, 0x21, 0x18, 0xa2, 0x21, 0x19, 0x42, 0xc1, 0x10, 0x40, 0x7d, 0xb0, 
+        0xa9, 0x17, 0x69, 0x07, 0xe7, 0x3a, 0x07, 0xe7, 0x9a, 0x02, 0x67, 0xbc, 0x01, 0x0c, 0x10, 0x9c, 
+        0xa0, 0xed, 0x0a, 0xcd, 0x06, 0x00, 0xfd, 0x11, 0x02, 0x91, 0x40, 0x22, 0x21, 0x1a, 0x52, 0x21, 
+        0x1b, 0x52, 0x61, 0x3e, 0x22, 0x61, 0x3f, 0x02, 0x61, 0x40, 0xf0, 0xf0, 0x31, 0x1b, 0xdd, 0xd0, 
+        0xd0, 0x74, 0x37, 0x9d, 0xa2, 0x22, 0x21, 0x3f, 0x72, 0x21, 0x3e, 0x0c, 0x00, 0x4d, 0x00, 0xe0, 
+        0x77, 0xc0, 0xc0, 0x62, 0xc0, 0x67, 0xb2, 0x01, 0x0b, 0x77, 0x3d, 0x07, 0x77, 0x20, 0x09, 0x07, 
+        0x97, 0x02, 0x67, 0x34, 0x03, 0x6d, 0x04, 0x3d, 0x00, 0xdd, 0x06, 0x2d, 0x0c, 0x32, 0x61, 0x3c, 
+        0x0c, 0x34, 0x3d, 0x0e, 0xc5, 0xcc, 0xfe, 0x32, 0x21, 0x3c, 0x22, 0x61, 0x39, 0x0c, 0x34, 0x2d, 
+        0x0d, 0x05, 0xcc, 0xfe, 0x82, 0x21, 0x3d, 0x22, 0x61, 0x3a, 0xac, 0x38, 0x6d, 0x0d, 0x72, 0x21, 
+        0x3c, 0x5d, 0x0e, 0x92, 0x21, 0x39, 0x4d, 0x0c, 0x20, 0x99, 0xc0, 0x21, 0x84, 0xff, 0x00, 0x99, 
+        0x11, 0x90, 0x90, 0x31, 0x8b, 0x99, 0x90, 0x94, 0x21, 0x99, 0x01, 0x01, 0x69, 0xe2, 0xc0, 0x00, 
+        0x00, 0xd1, 0x38, 0xe2, 0x08, 0x0d, 0x08, 0x00, 0x22, 0xcf, 0xfc, 0xc0, 0x00, 0x00, 0x4c, 0xe0, 
+        0x00, 0x0f, 0xd1, 0x02, 0x61, 0x28, 0x66, 0x42, 0x19, 0xa6, 0x4f, 0x02, 0x06, 0xd8, 0x00, 0x02, 
+        0xa1, 0x11, 0xd2, 0x21, 0x28, 0x0c, 0x0e, 0xd0, 0xd0, 0xc0, 0x00, 0xdd, 0x11, 0xd0, 0xd0, 0x31, 
+        0x46, 0x0b, 0x00, 0x72, 0x21, 0x3a, 0x62, 0x21, 0x39, 0x1c, 0xe2, 0x70, 0x66, 0xc0, 0x00, 0x56, 
+        0x11, 0x50, 0x50, 0x31, 0x8b, 0x35, 0x30, 0x34, 0x21, 0x37, 0x22, 0x02, 0x46, 0x49, 0x00, 0x82, 
+        0xa1, 0x48, 0x00, 0x08, 0xc0, 0x00, 0xe3, 0x11, 0x00, 0xd0, 0x11, 0xd0, 0xd0, 0x31, 0xe0, 0xe0, 
+        0x31, 0xf2, 0x21, 0x3d, 0x8c, 0x9f, 0x21, 0x66, 0xff, 0x3d, 0x0d, 0x01, 0x4d, 0xe2, 0xc0, 0x00, 
+        0x00, 0x22, 0x21, 0x30, 0x01, 0x61, 0xff, 0x27, 0xa0, 0x02, 0x46, 0xb4, 0x00, 0x02, 0x21, 0x2f, 
+        0x02, 0xc0, 0x14, 0x32, 0xa0, 0x2a, 0x42, 0xa0, 0x36, 0x1c, 0x15, 0x00, 0xc0, 0x74, 0x2d, 0x0c, 
+        0x05, 0x20, 0xf9, 0x31, 0x58, 0xff, 0xc2, 0x61, 0x31, 0x22, 0xa3, 0xe8, 0xd0, 0x22, 0xd1, 0x05, 
+        0xef, 0x01, 0x7c, 0x63, 0x0c, 0xa4, 0x0c, 0x85, 0x80, 0xf2, 0x01, 0xf0, 0xf8, 0x31, 0x2d, 0x0f, 
+        0x05, 0x1e, 0xf9, 0x2d, 0x0e, 0x1c, 0x13, 0x41, 0x74, 0xfc, 0x0c, 0x95, 0x45, 0x1d, 0xf9, 0x22, 
+        0x21, 0x40, 0x32, 0xaf, 0x38, 0x6c, 0x24, 0x0c, 0xa5, 0xc2, 0x21, 0x41, 0x45, 0x1c, 0xf9, 0x7d, 
+        0x0c, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x01, 0x03, 0xe2, 0x1c, 0x24, 0x08, 0x00, 0x0c, 0x75, 0x02, 
+        0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0xc1, 0xfd, 
+        0xe1, 0x0c, 0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 
+        0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x76, 0x02, 0x20, 0x27, 0x0c, 
+        0x07, 0xc0, 0x00, 0x00, 0x1c, 0x03, 0xc0, 0x20, 0x00, 0xc1, 0x8c, 0xe0, 0x22, 0x2c, 0xe4, 0x30, 
+        0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x6c, 0xe4, 0x0c, 0xe2, 0x85, 0x44, 0xfc, 0x41, 0x40, 0xeb, 
+        0x42, 0x04, 0x50, 0x1c, 0x00, 0x66, 0x14, 0x1d, 0xf0, 0x60, 0x74, 0xe0, 0x50, 0xf4, 0x00, 0x66, 
+        0x11, 0x60, 0x55, 0x20, 0x62, 0x21, 0x31, 0x80, 0x66, 0x01, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 
+        0x61, 0x7f, 0xe0, 0x52, 0x66, 0xff, 0xc2, 0x21, 0x34, 0xe2, 0x21, 0x36, 0xf2, 0x21, 0x37, 0xd0, 
+        0x20, 0xc0, 0x32, 0xa1, 0x10, 0x02, 0x21, 0x33, 0xd2, 0x21, 0x35, 0x00, 0x22, 0x11, 0x20, 0x20, 
+        0x31, 0x3a, 0x11, 0x0d, 0xf0, 0x0c, 0x03, 0x52, 0x61, 0x29, 0x02, 0x61, 0x28, 0xa2, 0xd1, 0xfe, 
+        0xa2, 0xca, 0x18, 0xa0, 0xaf, 0xb0, 0x72, 0x2a, 0x81, 0x42, 0x2a, 0x7c, 0xb2, 0x2a, 0x80, 0xb2, 
+        0x61, 0x2b, 0xa2, 0x2a, 0x7d, 0x72, 0x61, 0x2a, 0x77, 0x3a, 0x07, 0x77, 0x9a, 0x02, 0x47, 0xbb, 
+        0x01, 0x0c, 0x13, 0xa2, 0x61, 0x26, 0x42, 0x61, 0x25, 0x62, 0x61, 0x24, 0x82, 0x21, 0x28, 0x72, 
+        0xa1, 0x38, 0x0c, 0x12, 0x7c, 0xf0, 0x10, 0x4c, 0x40, 0xb2, 0xcf, 0x2f, 0x0c, 0x05, 0xc0, 0x9c, 
+        0x11, 0x92, 0x61, 0x2d, 0x52, 0x61, 0x38, 0x00, 0xbb, 0x11, 0xc0, 0xde, 0x81, 0xd2, 0x61, 0x2c, 
+        0xb0, 0xb0, 0x31, 0x30, 0x02, 0x93, 0x02, 0x61, 0x3b, 0xb2, 0x61, 0x2e, 0x80, 0x77, 0xc0, 0x72, 
+        0x61, 0x27, 0xa2, 0x21, 0x3b, 0x42, 0x21, 0x2b, 0x66, 0x1a, 0x08, 0x52, 0x21, 0x26, 0x42, 0x21, 
+        0x25, 0x86, 0x00, 0x00, 0x52, 0x21, 0x2a, 0x32, 0x21, 0x2c, 0x22, 0x21, 0x2d, 0x85, 0x7e, 0x01, 
+        0xb2, 0x21, 0x3d, 0x20, 0xd0, 0xf4, 0xd2, 0xcd, 0x01, 0xd0, 0xd1, 0xf4, 0xc2, 0xcd, 0x04, 0xc0, 
+        0xc3, 0xf4, 0x16, 0xeb, 0x00, 0x3d, 0x0f, 0x21, 0xfb, 0xfe, 0x4d, 0x0c, 0x5d, 0x0d, 0x01, 0xe0, 
+        0xe1, 0xc0, 0x00, 0x00, 0x3d, 0x0d, 0x2d, 0x0c, 0xc5, 0x95, 0xff, 0xe2, 0xa1, 0x38, 0xc2, 0x21, 
+        0x3b, 0xd2, 0x21, 0x28, 0xc0, 0xc2, 0xd1, 0x00, 0x3c, 0x11, 0x30, 0x30, 0x31, 0xd0, 0xd3, 0xc0, 
+        0xea, 0xdd, 0xe2, 0x21, 0x3d, 0x8c, 0x7e, 0x21, 0xf0, 0xfe, 0x01, 0xd5, 0xe1, 0xc0, 0x00, 0x00, 
+        0x31, 0xe9, 0xfe, 0x52, 0xa0, 0x64, 0x21, 0xf6, 0xea, 0xc0, 0x40, 0x60, 0x00, 0x44, 0x11, 0x40, 
+        0x40, 0x31, 0x22, 0x02, 0x01, 0x45, 0x56, 0xfb, 0x22, 0xa0, 0x06, 0x32, 0x21, 0x2e, 0x42, 0xa0, 
+        0x09, 0x52, 0xc1, 0x60, 0x62, 0xc1, 0x7f, 0x62, 0xc6, 0x01, 0xc5, 0x99, 0xff, 0x0c, 0x0b, 0x72, 
+        0x21, 0x1a, 0x32, 0x21, 0x1b, 0x0c, 0x05, 0x02, 0x21, 0x18, 0x42, 0x21, 0x19, 0x42, 0x61, 0x23, 
+        0x02, 0x61, 0x22, 0xad, 0x05, 0x40, 0x33, 0xc0, 0x00, 0x67, 0xc0, 0x67, 0xb7, 0x01, 0x0b, 0x33, 
+        0x7d, 0x03, 0xe6, 0x13, 0x07, 0xcc, 0x03, 0xcc, 0x26, 0x6d, 0x0b, 0x7d, 0x0a, 0xcd, 0x07, 0xed, 
+        0x06, 0x32, 0x21, 0x23, 0x22, 0x21, 0x22, 0x0c, 0x34, 0x85, 0x9d, 0xfe, 0xe2, 0x61, 0x21, 0x3d, 
+        0x0c, 0x22, 0x61, 0x32, 0x0c, 0x34, 0x2d, 0x0e, 0x85, 0x9c, 0xfe, 0xe2, 0x21, 0x32, 0x62, 0x21, 
+        0x3d, 0x20, 0xee, 0xc0, 0xe2, 0x61, 0x42, 0x00, 0xee, 0x11, 0xe0, 0xe0, 0x31, 0x9c, 0x96, 0x7d, 
+        0x0c, 0x52, 0x21, 0x23, 0x42, 0x21, 0x22, 0x62, 0x21, 0x21, 0x21, 0xc8, 0xfe, 0x8b, 0x0e, 0x00, 
+        0x04, 0x21, 0x09, 0x01, 0x01, 0xab, 0xe1, 0xc0, 0x00, 0x00, 0x22, 0x21, 0x42, 0x32, 0x21, 0x29, 
+        0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x37, 0xa2, 0x34, 0x32, 0x21, 0x38, 0x02, 0x21, 0x38, 0x42, 
+        0x21, 0x3b, 0x1b, 0x20, 0x40, 0x50, 0x60, 0x80, 0x55, 0x01, 0x20, 0x00, 0x74, 0x02, 0x61, 0x38, 
+        0x50, 0x48, 0x31, 0x42, 0x61, 0x3b, 0x66, 0x13, 0x0b, 0xe2, 0x21, 0x24, 0xd2, 0x21, 0x27, 0x00, 
+        0xee, 0x11, 0xe0, 0xe0, 0x31, 0x02, 0xc0, 0xfe, 0x56, 0x60, 0xea, 0x46, 0x01, 0x00, 0x32, 0x91, 
+        0x40, 0x32, 0x61, 0x40, 0x02, 0xcd, 0x10, 0x8b, 0x3e, 0x30, 0x34, 0x21, 0x46, 0x41, 0xff, 0x01, 
+        0x65, 0xe1, 0x08, 0x00, 0x20, 0x28, 0x21, 0x08, 0xe0, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x01, 0x61, 
+        0xe1, 0x0c, 0x03, 0x08, 0x00, 0xcd, 0x02, 0x08, 0xe0, 0x21, 0xa9, 0xe9, 0xc0, 0x00, 0x00, 0x02, 
+        0x21, 0x2f, 0x20, 0x2c, 0xc0, 0x8b, 0x22, 0x20, 0x24, 0x21, 0x20, 0x00, 0xc0, 0x86, 0x40, 0xff, 
+        0x02, 0xa1, 0x5f, 0xc6, 0x26, 0xff, 0x00, 0x00, 0x0c, 0x68, 0xb2, 0xa0, 0x70, 0x92, 0xa0, 0x60, 
+        0x1c, 0xe7, 0xa2, 0x13, 0x00, 0xbc, 0x54, 0x26, 0x6a, 0x29, 0x42, 0x12, 0x00, 0xcc, 0x84, 0x7d, 
+        0x08, 0x4c, 0x06, 0x62, 0x52, 0x00, 0x86, 0x06, 0x00, 0x26, 0xd4, 0x04, 0x97, 0x94, 0x09, 0x9d, 
+        0x0b, 0x92, 0x52, 0x00, 0x7d, 0x08, 0x86, 0x02, 0x00, 0xb7, 0x94, 0x0f, 0x72, 0xa0, 0x78, 0x72, 
+        0x52, 0x00, 0x7d, 0x08, 0x72, 0x53, 0x00, 0x0d, 0xf0, 0x26, 0xd4, 0x25, 0x0d, 0xf0, 0x77, 0x1a, 
+        0x27, 0x42, 0x12, 0x00, 0x82, 0xa0, 0x78, 0x87, 0x94, 0x07, 0x8d, 0x07, 0xb2, 0x52, 0x00, 0x86, 
+        0x05, 0x00, 0xb7, 0x14, 0x04, 0x97, 0x94, 0xe0, 0x4c, 0x09, 0x8d, 0x07, 0x92, 0x52, 0x00, 0x86, 
+        0x01, 0x00, 0x8d, 0x07, 0x0c, 0x09, 0x92, 0x52, 0x00, 0x82, 0x53, 0x00, 0x0d, 0xf0, 0x00, 0x00, 
+        0x80, 0x82, 0xfe, 0x3f, 0x5b, 0xf0, 0xfe, 0x3f, 0x32, 0xa0, 0x00, 0x42, 0xa0, 0x12, 0x52, 0xa0, 
+        0x07, 0x0c, 0x06, 0x12, 0xc1, 0x90, 0xd2, 0x61, 0x15, 0xf2, 0x61, 0x17, 0xc2, 0x61, 0x14, 0xe2, 
+        0x61, 0x16, 0xe1, 0x30, 0xe1, 0x02, 0x61, 0x13, 0x08, 0x0e, 0xcd, 0x02, 0x02, 0x20, 0x25, 0x22, 
+        0xa0, 0x77, 0xc0, 0x00, 0x00, 0x31, 0x6f, 0xfe, 0x52, 0xa0, 0x64, 0x4d, 0x0c, 0xd1, 0x7c, 0xea, 
+        0xcd, 0x02, 0x22, 0x0d, 0x01, 0x45, 0x38, 0xfb, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 
+        0x75, 0x0c, 0x06, 0x08, 0x0e, 0x0c, 0x07, 0x02, 0x20, 0x27, 0xc2, 0x61, 0x12, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 0x25, 0x08, 0x0e, 0x0c, 0x26, 0x02, 0x20, 0x27, 
+        0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0e, 
+        0x0c, 0x76, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x6c, 0xf3, 0xc1, 0xb0, 0xdf, 0xc0, 
+        0x20, 0x00, 0x22, 0x2c, 0xe4, 0x30, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x08, 0x0e, 0x02, 0x20, 0x28, 
+        0x22, 0x6c, 0xe4, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x3c, 0x33, 0x0c, 0x04, 0x0c, 0x05, 0x0c, 0x06, 
+        0x69, 0x21, 0x69, 0x11, 0x69, 0x01, 0x08, 0x0e, 0x0c, 0x07, 0x02, 0x20, 0x1a, 0x0c, 0x06, 0xc0, 
+        0x00, 0x00, 0x61, 0xcf, 0xff, 0x0c, 0x57, 0x0c, 0x00, 0x21, 0x30, 0xe8, 0x22, 0x61, 0x18, 0x02, 
+        0x61, 0x10, 0x72, 0x61, 0x11, 0x0c, 0x22, 0x0c, 0x13, 0x08, 0x0e, 0xc2, 0x21, 0x10, 0x02, 0x20, 
+        0x2b, 0x60, 0x4c, 0x90, 0x42, 0x14, 0x00, 0xf0, 0xcc, 0x11, 0xc0, 0x00, 0x00, 0x52, 0x21, 0x10, 
+        0x1c, 0xe0, 0x22, 0xc1, 0x20, 0x32, 0xc1, 0x10, 0x3a, 0xdc, 0x2a, 0xfc, 0x02, 0x5f, 0x00, 0xb6, 
+        0x25, 0x02, 0x86, 0x65, 0x00, 0x62, 0xa0, 0x78, 0x62, 0x5d, 0x00, 0x0c, 0x0c, 0x22, 0xa0, 0x03, 
+        0x02, 0x2e, 0x00, 0x32, 0xa0, 0x01, 0x02, 0x20, 0x2b, 0x42, 0x1d, 0x00, 0xc0, 0x00, 0x00, 0x0c, 
+        0x32, 0x08, 0x0e, 0x0c, 0x23, 0x02, 0x20, 0x2b, 0x42, 0x1f, 0x00, 0xc0, 0x00, 0x00, 0x22, 0x1d, 
+        0x00, 0x32, 0x1f, 0x00, 0x42, 0x21, 0x18, 0x05, 0x3b, 0xf8, 0x08, 0x0e, 0x0c, 0x12, 0x08, 0xd0, 
+        0x32, 0xa4, 0x00, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x21, 0x80, 0xdf, 0x08, 0x0e, 0x22, 0x22, 
+        0xf9, 0x08, 0xc0, 0x22, 0x61, 0x19, 0xc0, 0x00, 0x00, 0x02, 0x21, 0x19, 0x21, 0x27, 0xfe, 0x31, 
+        0x0d, 0xe1, 0x07, 0xa2, 0x02, 0x07, 0xa3, 0x3b, 0x32, 0x1d, 0x00, 0x07, 0x22, 0x19, 0x42, 0xa0, 
+        0x78, 0x47, 0x93, 0x07, 0x52, 0x1f, 0x00, 0x1c, 0xe6, 0x67, 0x15, 0x27, 0x2d, 0x0d, 0x3d, 0x0f, 
+        0x0c, 0x14, 0x45, 0xe0, 0xff, 0x06, 0x04, 0x00, 0xcc, 0x43, 0x72, 0x1f, 0x00, 0x26, 0x67, 0x13, 
+        0x2d, 0x0d, 0x3d, 0x0f, 0x0c, 0x04, 0x05, 0xdf, 0xff, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x26, 0x5c, 
+        0x02, 0x06, 0xda, 0xff, 0xf2, 0x21, 0x10, 0xd2, 0xa0, 0x00, 0x0c, 0x0c, 0x08, 0x0e, 0x0c, 0x12, 
+        0x08, 0xd0, 0x32, 0xa2, 0x00, 0xc0, 0x00, 0x00, 0x22, 0xc1, 0x30, 0x0c, 0x93, 0x45, 0xbf, 0xf8, 
+        0x08, 0x0e, 0x08, 0xc0, 0xc0, 0x00, 0x00, 0x28, 0xd1, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0xda, 0xd2, 
+        0x66, 0xcc, 0xd8, 0x08, 0x0e, 0x28, 0xc1, 0x08, 0xe0, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x2d, 0x0d, 
+        0x08, 0x0e, 0xc2, 0x21, 0x11, 0x08, 0xe0, 0x0c, 0x53, 0xc0, 0x00, 0x00, 0x61, 0x85, 0xff, 0x1b, 
+        0xff, 0x0b, 0xcc, 0xc2, 0x61, 0x11, 0xf0, 0xf0, 0x74, 0xf2, 0x61, 0x10, 0x56, 0x5c, 0xed, 0x08, 
+        0x0e, 0x02, 0x20, 0x1b, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x08, 0x0e, 0x02, 0x20, 0x2f, 0xc0, 0x00, 
+        0x00, 0x72, 0x21, 0x12, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x08, 0x0e, 0x0c, 0x75, 0x02, 
+        0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x0c, 0x25, 
+        0x08, 0x0e, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0xc1, 0x44, 0xdf, 0x22, 
+        0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x0c, 0x75, 0x08, 0x0e, 0x0c, 0x76, 0x02, 0x20, 0x27, 0x0c, 
+        0x07, 0xc0, 0x00, 0x00, 0x1c, 0x05, 0xc0, 0x20, 0x00, 0x42, 0x2c, 0xe4, 0x50, 0x44, 0x20, 0xc0, 
+        0x20, 0x00, 0x22, 0xa0, 0x64, 0x61, 0x5b, 0xe3, 0x31, 0xf2, 0xe9, 0x42, 0x6c, 0xe4, 0x51, 0xc0, 
+        0xef, 0x0c, 0x04, 0x52, 0x95, 0x00, 0x32, 0x03, 0x01, 0x4b, 0x76, 0x29, 0x01, 0x0c, 0xe2, 0xc5, 
+        0xd2, 0xfb, 0x21, 0x60, 0xff, 0x85, 0x63, 0xfb, 0xc2, 0x21, 0x14, 0xd2, 0x21, 0x15, 0xe2, 0x21, 
+        0x16, 0xf2, 0x21, 0x17, 0x02, 0x21, 0x13, 0x12, 0xc1, 0x70, 0x0d, 0xf0, 0x62, 0xa0, 0x60, 0x62, 
+        0x5d, 0x00, 0x46, 0x99, 0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0x90, 0x42, 0x61, 0x12, 0x02, 0x61, 
+        0x0d, 0xf2, 0x61, 0x11, 0xe2, 0x61, 0x10, 0xc2, 0x61, 0x0e, 0xd2, 0x61, 0x0f, 0x5d, 0x03, 0xd1, 
+        0xfa, 0xe1, 0xc0, 0x20, 0x00, 0x71, 0x2d, 0xe3, 0xe8, 0xbd, 0xc0, 0x20, 0x00, 0x62, 0x2d, 0x42, 
+        0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x6d, 0x42, 0x41, 0x29, 0xe3, 0xc0, 0x20, 0x00, 0x38, 
+        0xbd, 0x40, 0x33, 0x10, 0x4d, 0x05, 0xc0, 0x20, 0x00, 0x52, 0xa0, 0x64, 0x39, 0xbd, 0x01, 0xd0, 
+        0xe9, 0x3d, 0x02, 0x22, 0x00, 0x01, 0x45, 0x0d, 0xfb, 0xc1, 0x7a, 0xe0, 0x08, 0x0c, 0x02, 0x20, 
+        0x28, 0xe2, 0x61, 0x18, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x10, 0x0c, 0x12, 0xc0, 0x00, 
+        0x00, 0x0c, 0x02, 0x32, 0xa1, 0xf4, 0x08, 0x0c, 0x0c, 0x04, 0x02, 0x20, 0x15, 0x0c, 0x65, 0xc0, 
+        0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 0xa1, 0x84, 0xc0, 0x00, 
+        0x00, 0x21, 0xdf, 0xe1, 0x32, 0xc1, 0x10, 0x0c, 0xa4, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x3b, 
+        0x0c, 0x06, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 0xa1, 
+        0xf4, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x42, 0xaf, 0x9c, 0x52, 0xa0, 0x79, 0x62, 0xa0, 0x7b, 0x0c, 
+        0x07, 0x72, 0x61, 0x15, 0x62, 0x61, 0x14, 0x52, 0x61, 0x16, 0x49, 0xc1, 0x22, 0x61, 0x13, 0x1c, 
+        0x00, 0x0c, 0x0d, 0x0c, 0x08, 0x82, 0x61, 0x17, 0x92, 0x21, 0x15, 0x22, 0xcd, 0x70, 0xcc, 0xa9, 
+        0x20, 0xf0, 0x74, 0xe2, 0xa0, 0x7b, 0x02, 0x61, 0x19, 0x06, 0x02, 0x00, 0xf2, 0x21, 0x16, 0x20, 
+        0xe0, 0x74, 0x02, 0x61, 0x19, 0x22, 0xa0, 0x64, 0x32, 0xa0, 0x00, 0x02, 0x2c, 0x00, 0x42, 0xa0, 
+        0x04, 0x02, 0x20, 0x26, 0x5d, 0x0f, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x64, 0x0c, 0x03, 0x08, 0x0c, 
+        0x0c, 0x74, 0x02, 0x20, 0x26, 0x5d, 0x0e, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x4c, 0x03, 0x0c, 0x04, 
+        0x0c, 0x05, 0x0c, 0x06, 0x69, 0x01, 0x69, 0x11, 0x69, 0x21, 0x08, 0x0c, 0x0c, 0x07, 0x02, 0x20, 
+        0x1a, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x0c, 0x52, 0x01, 0xbe, 0xdf, 0xc0, 0x00, 0x00, 0x08, 0x0c, 
+        0x0c, 0x12, 0x08, 0xd0, 0x32, 0xa4, 0x00, 0xc0, 0x00, 0x00, 0x22, 0xc1, 0x20, 0x0c, 0xa3, 0x45, 
+        0x9c, 0xf8, 0x08, 0x0c, 0x08, 0xc0, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x28, 0x81, 0x08, 0xe0, 0x0c, 
+        0x03, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x28, 0x91, 0x08, 0xe0, 0x0c, 0x03, 0xc0, 0x00, 0x00, 0x08, 
+        0xc1, 0x4b, 0x22, 0x20, 0x23, 0x21, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x27, 0xa0, 0x0f, 0xe2, 
+        0x61, 0x14, 0xf2, 0x61, 0x16, 0x29, 0xc1, 0x0c, 0x03, 0x32, 0x61, 0x17, 0x06, 0x04, 0x00, 0x00, 
+        0x92, 0xc0, 0x72, 0x21, 0x17, 0x0c, 0x18, 0x70, 0x70, 0x74, 0x90, 0x78, 0x83, 0x72, 0x61, 0x17, 
+        0x08, 0x0c, 0x08, 0xc0, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x1b, 0x0c, 0x12, 0xc0, 0x00, 
+        0x00, 0x1b, 0xdd, 0x02, 0x21, 0x19, 0xd0, 0xd0, 0x74, 0x0b, 0x00, 0x56, 0x90, 0xf1, 0xe2, 0x21, 
+        0x15, 0x0c, 0x1f, 0x0c, 0x02, 0x62, 0x21, 0x15, 0x02, 0x21, 0x17, 0x1b, 0x76, 0x0b, 0x00, 0x00, 
+        0x2f, 0x83, 0x70, 0x60, 0x74, 0xdc, 0x3e, 0x32, 0x21, 0x16, 0x42, 0x21, 0x12, 0x30, 0x30, 0x34, 
+        0xf0, 0x33, 0x11, 0x30, 0x32, 0x20, 0x32, 0x44, 0x00, 0x46, 0x04, 0x00, 0x42, 0x21, 0x14, 0x52, 
+        0x21, 0x12, 0x40, 0x40, 0x34, 0xf0, 0x44, 0x11, 0x40, 0x42, 0x20, 0x42, 0x45, 0x01, 0x52, 0x21, 
+        0x13, 0x62, 0x61, 0x15, 0x0b, 0x55, 0x52, 0x61, 0x13, 0x56, 0x25, 0xec, 0x08, 0x0c, 0x02, 0x20, 
+        0x10, 0x0c, 0x02, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0xd2, 0x21, 0x18, 0x02, 0x20, 0x2f, 0xe1, 0x7a, 
+        0xe1, 0xc0, 0x00, 0x00, 0x31, 0xa6, 0xe2, 0xc0, 0x20, 0x00, 0x22, 0x2e, 0x42, 0x30, 0x22, 0x10, 
+        0xc0, 0x20, 0x00, 0x22, 0x6e, 0x42, 0xc0, 0x20, 0x00, 0xc8, 0xe1, 0xd9, 0xbe, 0xf2, 0x21, 0x11, 
+        0xd8, 0xf1, 0xe2, 0x21, 0x10, 0x08, 0xd1, 0x12, 0xc1, 0x70, 0x0d, 0xf0, 0x30, 0xf3, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfd, 0xff, 0x08, 0x00, 0x80, 0x42, 0x01, 0x08, 0x00, 0x40, 
+        0x28, 0x31, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xf6, 0xff, 0x08, 0x00, 0x08, 0x60, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x03, 0x01, 0xef, 0xff, 
+        0x80, 0x32, 0x01, 0x08, 0x00, 0x30, 0x28, 0x31, 0x08, 0x00, 0x3d, 0x0c, 0xc0, 0x00, 0x00, 0x01, 
+        0xeb, 0xff, 0x08, 0x00, 0x08, 0x60, 0x2d, 0x0c, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x03, 0x12, 0xc1, 0xf0, 0x5d, 0x02, 0x09, 0x01, 0x01, 0xe3, 0xff, 
+        0x0c, 0x12, 0x59, 0x00, 0xc5, 0xfb, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xdd, 0xff, 0x08, 0x00, 0x08, 0x10, 0xc0, 0x00, 0x00, 0x0c, 
+        0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xd7, 0xff, 
+        0x08, 0x00, 0x80, 0x32, 0x01, 0x08, 0x20, 0x30, 0x28, 0x31, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xd0, 0xff, 0x08, 0x00, 0x08, 0x30, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xca, 0xff, 0x08, 0x00, 0x08, 0x40, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xc4, 0xff, 0x08, 0x00, 0x08, 0x50, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xbe, 0xff, 0x08, 0x00, 0x08, 0x60, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xb8, 0xff, 0x08, 0x00, 0x08, 0x70, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x21, 0x33, 0xe2, 0xc0, 
+        0x20, 0x00, 0x22, 0x22, 0x80, 0x0d, 0xf0, 0x00, 0xc0, 0x20, 0x00, 0x28, 0x02, 0x0d, 0xf0, 0x00, 
+        0xc0, 0x20, 0x00, 0x39, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0xf0, 0x7f, 
+        0x00, 0x00, 0x00, 0x38, 0x67, 0xc3, 0x04, 0x70, 0x72, 0x11, 0x8c, 0x07, 0x0d, 0xf0, 0x2d, 0x03, 
+        0x0d, 0xf0, 0x00, 0x00, 0x80, 0x76, 0x11, 0x70, 0x33, 0x30, 0xc6, 0x3c, 0x00, 0x00, 0x00, 0x00, 
+        0x61, 0xf6, 0xff, 0x30, 0x72, 0x30, 0x96, 0xa7, 0xfe, 0x67, 0x42, 0xd7, 0x67, 0x43, 0xde, 0x20, 
+        0x77, 0x85, 0x30, 0x87, 0x85, 0x87, 0x37, 0x4c, 0x67, 0x03, 0x28, 0x60, 0x33, 0x20, 0x80, 0x33, 
+        0x11, 0x30, 0x38, 0x41, 0x80, 0xa7, 0xc0, 0xf6, 0xca, 0x29, 0x00, 0x0a, 0x40, 0x0c, 0x09, 0x90, 
+        0x93, 0x81, 0x30, 0x30, 0x91, 0x3a, 0x22, 0x20, 0xa7, 0x85, 0x77, 0x1a, 0x4a, 0x8d, 0x07, 0x46, 
+        0x15, 0x00, 0x00, 0x00, 0x70, 0x33, 0x11, 0x30, 0x39, 0x41, 0x67, 0x02, 0x04, 0x1b, 0x88, 0x46, 
+        0xf4, 0xff, 0x3a, 0x22, 0x0d, 0xf0, 0x00, 0x00, 0x70, 0x22, 0x11, 0x20, 0x29, 0x41, 0x1b, 0x77, 
+        0x46, 0x03, 0x00, 0x00, 0x00, 0x67, 0x02, 0xef, 0x60, 0x22, 0x20, 0x80, 0x22, 0x11, 0x20, 0x28, 
+        0x41, 0x70, 0xa8, 0xc0, 0xf6, 0xca, 0x1c, 0x00, 0x0a, 0x40, 0x00, 0x92, 0xa1, 0x20, 0x20, 0x91, 
+        0x3a, 0x22, 0x20, 0xa7, 0x85, 0x87, 0x9a, 0x0f, 0xd6, 0x69, 0x00, 0x1b, 0x22, 0xf0, 0x99, 0x11, 
+        0xac, 0xc9, 0x0d, 0xf0, 0x2d, 0x03, 0x0d, 0xf0, 0xad, 0x02, 0x20, 0x21, 0x41, 0x1b, 0x88, 0xa0, 
+        0x88, 0x01, 0x8a, 0x22, 0x67, 0x42, 0x08, 0x07, 0x6a, 0x03, 0x1b, 0x22, 0x9c, 0x09, 0x0d, 0xf0, 
+        0x20, 0x27, 0x85, 0x90, 0x22, 0x01, 0xf0, 0x88, 0x11, 0x80, 0x22, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x67, 0xc3, 0x05, 0x41, 0x70, 0xe8, 0x40, 0x22, 
+        0x20, 0x0d, 0xf0, 0x00, 0x80, 0x76, 0x11, 0x70, 0x23, 0x30, 0x0d, 0xf0, 0x80, 0x76, 0x11, 0x70, 
+        0x33, 0x30, 0xc6, 0xc8, 0xff, 0x00, 0x00, 0x00, 0x61, 0xbc, 0xff, 0x30, 0x72, 0x30, 0x96, 0xa7, 
+        0xfe, 0x67, 0x42, 0xd3, 0x67, 0x43, 0xdc, 0x20, 0x77, 0x75, 0x30, 0x87, 0x75, 0x37, 0x32, 0x4b, 
+        0x67, 0x03, 0x2d, 0x60, 0x33, 0x20, 0x80, 0x33, 0x11, 0x30, 0x38, 0x41, 0x80, 0xa7, 0xc0, 0xf6, 
+        0xca, 0x37, 0x00, 0x0a, 0x40, 0x0c, 0x09, 0x90, 0x93, 0x81, 0x30, 0x30, 0x91, 0x30, 0x22, 0xc0, 
+        0x90, 0x90, 0x60, 0x0b, 0xa2, 0x90, 0x2a, 0x93, 0x20, 0xa7, 0x75, 0x77, 0x1a, 0x51, 0xc6, 0x1b, 
+        0x00, 0x37, 0x12, 0x68, 0x70, 0x33, 0x11, 0x30, 0x39, 0x41, 0x67, 0x02, 0xce, 0x1b, 0x88, 0x46, 
+        0xf2, 0xff, 0x00, 0x00, 0x80, 0x76, 0x11, 0x70, 0x23, 0x30, 0x0d, 0xf0, 0x67, 0x02, 0x3c, 0x60, 
+        0x22, 0x20, 0x80, 0x22, 0x11, 0x20, 0x28, 0x41, 0x70, 0xa8, 0xc0, 0xf6, 0xca, 0xe5, 0x00, 0x0a, 
+        0x40, 0x0c, 0x09, 0x90, 0x92, 0x81, 0x20, 0x20, 0x91, 0x80, 0xb6, 0x11, 0xb0, 0x33, 0x30, 0x20, 
+        0x23, 0xc0, 0x90, 0x90, 0x60, 0x0b, 0xa2, 0x90, 0x2a, 0x93, 0x20, 0xa7, 0x75, 0x87, 0x9a, 0x20, 
+        0xd6, 0x69, 0x00, 0x1b, 0x22, 0xf0, 0x99, 0x11, 0xbc, 0xc9, 0x0d, 0xf0, 0x37, 0x12, 0x0d, 0x70, 
+        0x22, 0x11, 0x20, 0x29, 0x41, 0x67, 0x03, 0xbf, 0x1b, 0x77, 0x86, 0xee, 0xff, 0x0c, 0x02, 0x0d, 
+        0xf0, 0x70, 0x82, 0x11, 0xac, 0x88, 0x60, 0xf8, 0x40, 0x80, 0x89, 0x41, 0xa7, 0xa6, 0x2e, 0x1b, 
+        0x66, 0x00, 0x16, 0x40, 0x90, 0x88, 0x81, 0x00, 0x99, 0xa1, 0x20, 0x27, 0x85, 0x60, 0x22, 0xc0, 
+        0x90, 0x22, 0x01, 0x8a, 0x22, 0xc6, 0xed, 0xff, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 
+        0x16, 0x99, 0xfc, 0xb2, 0xca, 0xe8, 0x1c, 0x86, 0xb0, 0x6a, 0xa3, 0x86, 0xf4, 0xff, 0x6d, 0x0a, 
+        0x46, 0xf3, 0xff, 0x00, 0xf0, 0x22, 0x11, 0x20, 0x21, 0x41, 0xac, 0xe2, 0xa0, 0xf2, 0x40, 0xa2, 
+        0xca, 0xf8, 0x00, 0x1a, 0x40, 0x00, 0x22, 0xa1, 0x0c, 0x18, 0xa0, 0x88, 0xc0, 0xc6, 0x1e, 0x00, 
+        0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x9c, 0x23, 0xa0, 0xf3, 0x40, 0xa2, 0xca, 0xf8, 0x00, 0x1a, 
+        0x40, 0x00, 0x33, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x86, 0x18, 0x00, 0x70, 0x2f, 0x05, 0x10, 
+        0x22, 0x01, 0x06, 0x34, 0x00, 0xf0, 0x83, 0x11, 0xcc, 0x88, 0x41, 0x18, 0xe8, 0x40, 0x22, 0x20, 
+        0x86, 0x30, 0x00, 0x00, 0x67, 0xc3, 0x06, 0x70, 0x83, 0x11, 0x8c, 0x08, 0x2d, 0x03, 0x70, 0x7f, 
+        0x05, 0xf0, 0x22, 0x11, 0x00, 0x41, 0x40, 0x20, 0x27, 0x81, 0x06, 0x2a, 0x00, 0xf0, 0x82, 0x11, 
+        0x56, 0x88, 0xfe, 0x71, 0x0e, 0xe8, 0x70, 0x23, 0x20, 0x46, 0x26, 0x00, 0x12, 0xc1, 0xe0, 0xc9, 
+        0x41, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x61, 0x5c, 0xff, 0x30, 0x72, 0x30, 0x67, 0x42, 0xb4, 
+        0x67, 0x43, 0xd9, 0x20, 0x87, 0x75, 0x30, 0x97, 0x75, 0x16, 0x78, 0xf6, 0x16, 0x09, 0xf8, 0x9a, 
+        0x88, 0xa1, 0x0b, 0xe6, 0x60, 0x22, 0x20, 0xa0, 0x22, 0x10, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 
+        0x20, 0x40, 0xf5, 0x30, 0x50, 0xf5, 0x50, 0x62, 0xc1, 0x30, 0xb4, 0xc1, 0x0c, 0x09, 0xba, 0x66, 
+        0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x10, 0x40, 0x40, 0x60, 0x99, 0x81, 0x30, 0xb2, 0xc1, 0x00, 0x66, 
+        0xa1, 0xba, 0x66, 0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x50, 0x24, 0xc1, 0x9a, 0x22, 0x0c, 0x94, 0x20, 
+        0x5f, 0x41, 0x8c, 0x25, 0x0b, 0x44, 0x1b, 0x88, 0x00, 0x14, 0x40, 0x60, 0x22, 0x81, 0x00, 0x66, 
+        0xa1, 0x42, 0xa0, 0x80, 0x40, 0x88, 0xc0, 0x42, 0xa0, 0xfe, 0x47, 0xb8, 0x2f, 0xd6, 0x76, 0x00, 
+        0x1b, 0x22, 0xf0, 0x66, 0x11, 0x16, 0xb6, 0x01, 0x90, 0x88, 0x01, 0x8a, 0x22, 0x70, 0x7f, 0x05, 
+        0x10, 0x77, 0x01, 0x70, 0x22, 0x20, 0xc8, 0x41, 0xd8, 0x51, 0xe8, 0x61, 0xf8, 0x71, 0x12, 0xc1, 
+        0x20, 0x0d, 0xf0, 0x00, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x86, 0xf6, 0xff, 0x96, 0x88, 0x00, 
+        0x82, 0xa0, 0xff, 0x90, 0x28, 0x01, 0xc6, 0xf4, 0xff, 0x80, 0x80, 0x60, 0x9d, 0x06, 0x00, 0x08, 
+        0x40, 0xf6, 0xc8, 0x13, 0x00, 0x62, 0xa1, 0x20, 0x20, 0x91, 0x0c, 0x08, 0x16, 0xd9, 0xfa, 0x0c, 
+        0x19, 0x90, 0x66, 0x20, 0x46, 0xe9, 0xff, 0x00, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x06, 0xed, 
+        0xff, 0x00, 0x00, 0x00, 0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x9c, 0x33, 0xa0, 0xf3, 0x40, 0xa2, 
+        0xca, 0xf8, 0x00, 0x1a, 0x40, 0x00, 0x33, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x06, 0x1d, 0x00, 
+        0x00, 0xf0, 0x42, 0x11, 0x40, 0x41, 0x41, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x60, 0x22, 0x20, 
+        0xcc, 0x44, 0x41, 0xc6, 0xe7, 0x40, 0x22, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0xf0, 0x22, 0x11, 0x20, 
+        0x21, 0x41, 0x9c, 0x22, 0xa0, 0xf2, 0x40, 0xa2, 0xca, 0xf8, 0x00, 0x1a, 0x40, 0x00, 0x22, 0xa1, 
+        0x0c, 0x18, 0xa0, 0x88, 0xc0, 0xc6, 0x0f, 0x00, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x0d, 0xf0, 
+        0x30, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x22, 0x30, 0x67, 0xc3, 0x05, 0x41, 0xb8, 0xe7, 0x40, 
+        0x22, 0x20, 0x0d, 0xf0, 0x70, 0x83, 0x11, 0x16, 0xd8, 0xfd, 0x2d, 0x03, 0x0d, 0xf0, 0x00, 0x00, 
+        0x61, 0x06, 0xff, 0x30, 0x72, 0x30, 0x67, 0x42, 0xd6, 0x67, 0x43, 0xe7, 0x20, 0x87, 0x75, 0x30, 
+        0x97, 0x75, 0x16, 0xe9, 0xf6, 0x16, 0x38, 0xfa, 0x90, 0x88, 0xc0, 0xa1, 0xb5, 0xe5, 0x60, 0x22, 
+        0x20, 0xa0, 0x22, 0x10, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 0x27, 0x33, 0x04, 0xf0, 0x22, 0x11, 
+        0x0b, 0x88, 0x30, 0x22, 0xc0, 0xf0, 0x22, 0x11, 0x0c, 0x1a, 0x92, 0xa0, 0x17, 0xf0, 0xaa, 0x11, 
+        0x37, 0x32, 0x04, 0x1b, 0xaa, 0x30, 0x22, 0xc0, 0xf0, 0x22, 0x11, 0x0b, 0x99, 0x56, 0xc9, 0xfe, 
+        0x82, 0xc8, 0x7e, 0x42, 0xa0, 0xfe, 0x47, 0xb8, 0x17, 0x37, 0x32, 0x04, 0x1b, 0xaa, 0x37, 0x12, 
+        0x1a, 0x90, 0x88, 0x01, 0x8a, 0x2a, 0x70, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x22, 0x20, 0x0d, 
+        0xf0, 0x96, 0x08, 0x01, 0x1b, 0x84, 0x90, 0x28, 0x01, 0x46, 0xfa, 0xff, 0xa0, 0xa1, 0x41, 0xf0, 
+        0xaa, 0x11, 0xc6, 0xf6, 0xff, 0x80, 0x80, 0x60, 0x00, 0x08, 0x40, 0xf6, 0xc8, 0x22, 0x00, 0x6a, 
+        0xa1, 0xa0, 0xa0, 0x91, 0x0c, 0x08, 0x8c, 0x32, 0x0c, 0x19, 0x90, 0x66, 0x20, 0xd6, 0x06, 0xfc, 
+        0x1b, 0xaa, 0xf0, 0x66, 0x11, 0x56, 0x86, 0xfb, 0xa0, 0xa1, 0x41, 0xf0, 0xaa, 0x11, 0xc6, 0xeb, 
+        0xff, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x61, 0xd7, 0xfe, 0x67, 
+        0x42, 0x22, 0x20, 0x47, 0x75, 0x42, 0xc4, 0x82, 0xe6, 0xc4, 0x20, 0xa6, 0x14, 0x29, 0x60, 0x72, 
+        0x20, 0x80, 0x57, 0x11, 0x00, 0x14, 0x40, 0x50, 0x50, 0x91, 0x50, 0x20, 0x60, 0x70, 0x25, 0xb3, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x70, 0x42, 0x11, 0x8c, 0x04, 0x0c, 0x02, 0x80, 0x46, 0x11, 0x0b, 
+        0x54, 0x20, 0x45, 0xb3, 0x2d, 0x04, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x61, 0xc7, 0xfe, 0x67, 
+        0x42, 0x25, 0x20, 0x47, 0x75, 0x42, 0xc4, 0x81, 0xe6, 0xc4, 0x25, 0x96, 0xe4, 0x02, 0x60, 0x72, 
+        0x20, 0x80, 0x57, 0x11, 0x1b, 0x44, 0x26, 0xc4, 0x27, 0x00, 0x14, 0x40, 0x50, 0x50, 0x91, 0x50, 
+        0x20, 0x60, 0x70, 0x25, 0xb3, 0x0d, 0xf0, 0x00, 0x70, 0x42, 0x11, 0x8c, 0x24, 0x7c, 0xf2, 0x0d, 
+        0xf0, 0x80, 0x46, 0x11, 0x7c, 0xf5, 0x20, 0x45, 0xb3, 0x2d, 0x04, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 
+        0xf0, 0x96, 0x32, 0x00, 0x2d, 0x05, 0x0d, 0xf0, 0x80, 0x26, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x20, 0xa3, 0x20, 0x16, 0x4a, 0x08, 0x9c, 0x53, 0xa0, 0xf3, 
+        0x40, 0xa2, 0xca, 0xf5, 0x00, 0x1a, 0x40, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x0c, 0x18, 0xa0, 
+        0x88, 0xc0, 0x86, 0x36, 0x00, 0xa0, 0xf2, 0x40, 0xa2, 0xca, 0xf5, 0x6c, 0x18, 0xa0, 0x88, 0xc0, 
+        0x00, 0x1a, 0x40, 0x96, 0x9a, 0x00, 0x00, 0x32, 0xa1, 0x0c, 0x02, 0x46, 0x30, 0x00, 0x00, 0x00, 
+        0x20, 0x30, 0x91, 0x00, 0x22, 0xa1, 0x86, 0x2d, 0x00, 0xf0, 0x55, 0x11, 0x50, 0x51, 0x41, 0x40, 
+        0xa5, 0x20, 0xbc, 0xba, 0x9c, 0x55, 0xa0, 0xf5, 0x40, 0xa2, 0xca, 0xf5, 0x00, 0x1a, 0x40, 0x40, 
+        0x55, 0x81, 0x00, 0x44, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x46, 0x25, 0x00, 0xa0, 0xf4, 0x40, 
+        0xa2, 0xca, 0xf5, 0x6c, 0x19, 0xa0, 0x99, 0xc0, 0x00, 0x1a, 0x40, 0x96, 0x9a, 0x00, 0x00, 0x54, 
+        0xa1, 0x0c, 0x04, 0x06, 0x1f, 0x00, 0x00, 0x00, 0x40, 0x50, 0x91, 0x00, 0x44, 0xa1, 0x46, 0x1c, 
+        0x00, 0x70, 0x3f, 0x05, 0x10, 0x33, 0x01, 0x0c, 0x02, 0x46, 0x64, 0x00, 0xcc, 0xd4, 0xf0, 0x85, 
+        0x11, 0xcc, 0x88, 0x41, 0x08, 0xdd, 0x40, 0x33, 0x20, 0x46, 0x60, 0x00, 0x00, 0x67, 0xc5, 0x0b, 
+        0x40, 0x85, 0x11, 0x40, 0x88, 0x20, 0x8c, 0x28, 0x3d, 0x05, 0x2d, 0x04, 0x70, 0x7f, 0x05, 0xf0, 
+        0x33, 0x11, 0x00, 0x41, 0x40, 0x30, 0x37, 0x81, 0x86, 0x58, 0x00, 0x00, 0x56, 0x82, 0xfe, 0xf0, 
+        0x83, 0x11, 0x56, 0x28, 0xfe, 0x71, 0xfb, 0xdc, 0x70, 0x35, 0x20, 0xc6, 0x53, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0xc9, 0x41, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x61, 0x78, 0xfe, 0x50, 0x73, 
+        0x30, 0x67, 0x43, 0xa7, 0x67, 0x45, 0xd4, 0x30, 0x84, 0xa5, 0x50, 0x94, 0xa5, 0x16, 0xf8, 0xef, 
+        0x16, 0x59, 0xf4, 0x9a, 0x88, 0xa1, 0x60, 0xfb, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 0x60, 0x55, 
+        0x20, 0xa0, 0x55, 0x10, 0x79, 0x11, 0x20, 0xc0, 0xf5, 0x40, 0xd0, 0xf5, 0x30, 0xe0, 0xf5, 0x50, 
+        0xf0, 0xf5, 0xd0, 0xa2, 0xc1, 0x40, 0xbc, 0xc1, 0x0c, 0x09, 0xba, 0xaa, 0xb7, 0xba, 0x01, 0x1b, 
+        0x99, 0x10, 0x40, 0x40, 0xa0, 0x69, 0x81, 0x40, 0xb2, 0xc1, 0x00, 0xaa, 0xa1, 0xba, 0xaa, 0xb7, 
+        0xba, 0x02, 0x62, 0xc6, 0x01, 0x0c, 0x09, 0x50, 0xb2, 0xc1, 0xba, 0x66, 0xb7, 0xb6, 0x01, 0x1b, 
+        0x99, 0xd0, 0xbc, 0xc1, 0xb0, 0x66, 0x80, 0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x40, 0xb3, 0xc1, 0xba, 
+        0x66, 0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x8c, 0x3a, 0x0c, 0x1b, 0xb0, 0x66, 0x20, 0xf0, 0x72, 0xc1, 
+        0x40, 0xbe, 0xc1, 0x0c, 0x0a, 0x7a, 0xbb, 0x77, 0xbb, 0x02, 0xa2, 0xca, 0x01, 0x50, 0x7c, 0xc1, 
+        0x70, 0xbb, 0x80, 0x77, 0xbb, 0x02, 0xa2, 0xca, 0x01, 0xd0, 0x73, 0xc1, 0x70, 0xbb, 0x80, 0x77, 
+        0xbb, 0x02, 0xa2, 0xca, 0x01, 0xb0, 0xaa, 0x81, 0x9a, 0xaa, 0x00, 0xbb, 0xa1, 0xba, 0x66, 0xb7, 
+        0xb6, 0x02, 0xa2, 0xca, 0x01, 0x0c, 0x09, 0xf0, 0x2c, 0xc1, 0xaa, 0x22, 0xa7, 0xb2, 0x01, 0x1b, 
+        0x99, 0x50, 0xa3, 0xc1, 0xa0, 0x22, 0x80, 0xa7, 0xb2, 0x02, 0x92, 0xc9, 0x01, 0xd0, 0xae, 0xc1, 
+        0xaa, 0x22, 0xa7, 0xb2, 0x02, 0x92, 0xc9, 0x01, 0xf0, 0xb3, 0xc1, 0x50, 0x7e, 0xc1, 0x0c, 0x0a, 
+        0x70, 0xbb, 0x80, 0x77, 0xbb, 0x02, 0xa2, 0xca, 0x01, 0xb0, 0xaa, 0x81, 0x9a, 0xaa, 0x00, 0xbb, 
+        0xa1, 0xba, 0x22, 0xb7, 0xb2, 0x01, 0x1b, 0xaa, 0xf0, 0x3e, 0xc1, 0xaa, 0x33, 0x78, 0x11, 0x0c, 
+        0xb4, 0x30, 0x59, 0x41, 0xcc, 0x45, 0x42, 0xc4, 0x01, 0x82, 0xc8, 0xff, 0x00, 0x14, 0x40, 0x20, 
+        0x33, 0x81, 0x60, 0x22, 0x81, 0x00, 0x66, 0xa1, 0x42, 0xa3, 0xff, 0x40, 0x88, 0xc0, 0xf0, 0x44, 
+        0x11, 0x47, 0xb8, 0x37, 0xd6, 0x86, 0x00, 0x1b, 0x22, 0xac, 0x82, 0xf0, 0x66, 0x11, 0x9c, 0xa6, 
+        0xc0, 0x88, 0x01, 0x8a, 0x33, 0x70, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x33, 0x20, 0xc8, 0x41, 
+        0xd8, 0x51, 0xe8, 0x61, 0xf8, 0x71, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x20, 0x21, 0x41, 0xf0, 
+        0x22, 0x11, 0x86, 0xf6, 0xff, 0x1b, 0x33, 0x46, 0xf5, 0xff, 0x00, 0x00, 0x96, 0x98, 0x00, 0x1b, 
+        0x84, 0xc0, 0x38, 0x01, 0x0c, 0x02, 0xc6, 0xf2, 0xff, 0x80, 0x80, 0x60, 0x9d, 0x06, 0x00, 0x08, 
+        0x40, 0xf6, 0xc8, 0x0b, 0x00, 0x62, 0xa1, 0x20, 0x23, 0x81, 0x30, 0x30, 0x91, 0x06, 0x04, 0x00, 
+        0xf6, 0xd8, 0x1c, 0x00, 0xa2, 0xa1, 0x20, 0x63, 0x81, 0x30, 0x20, 0x91, 0x0c, 0x03, 0xa0, 0x99, 
+        0x20, 0x0c, 0x08, 0x16, 0xd9, 0xf8, 0x0c, 0x19, 0x90, 0x66, 0x20, 0x46, 0xe1, 0xff, 0x00, 0x00, 
+        0x70, 0x3f, 0x05, 0x10, 0x33, 0x01, 0x0c, 0x02, 0x86, 0xe4, 0xff, 0x00, 0xf0, 0x55, 0x11, 0x50, 
+        0x51, 0x41, 0x40, 0xa5, 0x20, 0xbc, 0xba, 0x9c, 0x55, 0xa0, 0xf5, 0x40, 0xa2, 0xca, 0xf5, 0x00, 
+        0x1a, 0x40, 0x40, 0x55, 0x81, 0x00, 0x44, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x06, 0x36, 0x00, 
+        0xa0, 0xf4, 0x40, 0xa2, 0xca, 0xf5, 0x6c, 0x19, 0xa0, 0x99, 0xc0, 0x00, 0x1a, 0x40, 0x96, 0x7a, 
+        0x00, 0x00, 0x54, 0xa1, 0x0c, 0x04, 0xc6, 0x2f, 0x00, 0x40, 0x50, 0x91, 0x00, 0x44, 0xa1, 0x86, 
+        0x2d, 0x00, 0x00, 0x00, 0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x30, 0x22, 0x20, 0x70, 0x3f, 0x05, 
+        0x10, 0x33, 0x01, 0x60, 0x33, 0x20, 0xcc, 0x42, 0x41, 0x73, 0xdc, 0x40, 0x33, 0x20, 0x0c, 0x02, 
+        0x0d, 0xf0, 0x00, 0x00, 0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x20, 0xa3, 0x20, 0xbc, 0xba, 0x9c, 
+        0x53, 0xa0, 0xf3, 0x40, 0xa2, 0xca, 0xf5, 0x00, 0x1a, 0x40, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 
+        0x0c, 0x18, 0xa0, 0x88, 0xc0, 0xc6, 0x1c, 0x00, 0xa0, 0xf2, 0x40, 0xa2, 0xca, 0xf5, 0x6c, 0x18, 
+        0xa0, 0x88, 0xc0, 0x00, 0x1a, 0x40, 0x96, 0x7a, 0x00, 0x00, 0x32, 0xa1, 0x0c, 0x02, 0x86, 0x16, 
+        0x00, 0x20, 0x30, 0x91, 0x00, 0x22, 0xa1, 0x46, 0x14, 0x00, 0x00, 0x00, 0x70, 0x3f, 0x05, 0x10, 
+        0x33, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x50, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x33, 
+        0x30, 0x67, 0xc5, 0x05, 0x41, 0x58, 0xdc, 0x40, 0x33, 0x20, 0x0d, 0xf0, 0x40, 0x85, 0x11, 0x40, 
+        0x88, 0x20, 0x16, 0x68, 0xfd, 0x3d, 0x05, 0x2d, 0x04, 0x0d, 0xf0, 0x00, 0x47, 0x32, 0x37, 0x46, 
+        0x0f, 0x00, 0x00, 0x00, 0x61, 0xd2, 0xfd, 0x50, 0x73, 0x30, 0x67, 0x43, 0xca, 0x67, 0x45, 0xdb, 
+        0x30, 0x84, 0xa5, 0x50, 0x94, 0xa5, 0x16, 0x29, 0xf0, 0x16, 0x78, 0xf6, 0x90, 0x88, 0xc0, 0xa1, 
+        0xba, 0xfa, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 0x60, 0x55, 0x20, 0xa0, 0x55, 0x10, 0x10, 0x4f, 
+        0x40, 0x37, 0x35, 0x0b, 0x37, 0x15, 0xc4, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x82, 0xc8, 0xff, 
+        0x50, 0x33, 0xc0, 0x47, 0xb2, 0x02, 0x32, 0xc3, 0xff, 0x40, 0x22, 0xc0, 0x20, 0x33, 0x81, 0x00, 
+        0x22, 0xa1, 0x0c, 0x0a, 0x0c, 0x1b, 0x3c, 0x49, 0xb0, 0xaa, 0x81, 0x00, 0xbb, 0xa1, 0x57, 0x33, 
+        0x0f, 0x57, 0x13, 0x3f, 0x1b, 0xbb, 0x50, 0x33, 0xc0, 0x47, 0xb2, 0x01, 0x0b, 0x33, 0x40, 0x22, 
+        0xc0, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x0b, 0x99, 0x56, 0xb9, 0xfd, 0x92, 0xa3, 0xfe, 0x9a, 
+        0x88, 0x92, 0xd9, 0x04, 0x97, 0xb8, 0x38, 0x57, 0x33, 0x07, 0x57, 0x13, 0x1e, 0x1b, 0xbb, 0x16, 
+        0x5b, 0x08, 0x2d, 0x0b, 0xc0, 0x88, 0x01, 0x8a, 0x3a, 0x70, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 
+        0x33, 0x20, 0x0d, 0xf0, 0x47, 0xb2, 0xbc, 0x86, 0xf1, 0xff, 0x00, 0x00, 0x47, 0x32, 0xe2, 0x47, 
+        0x92, 0xda, 0x1b, 0xbb, 0x16, 0x0b, 0x06, 0xb0, 0xb1, 0x41, 0xf0, 0xbb, 0x11, 0x46, 0xf4, 0xff, 
+        0x96, 0x98, 0x00, 0x1b, 0x89, 0xc0, 0x38, 0x01, 0x0c, 0x02, 0xc6, 0xf2, 0xff, 0x80, 0x80, 0x60, 
+        0x00, 0x08, 0x40, 0xf6, 0xc8, 0x0d, 0x00, 0x6b, 0xa1, 0xb0, 0xba, 0x81, 0xa0, 0xa0, 0x91, 0x86, 
+        0x04, 0x00, 0x00, 0x00, 0xf6, 0xd8, 0x35, 0x00, 0x9b, 0xa1, 0xb0, 0x6a, 0x81, 0xa0, 0xb0, 0x91, 
+        0x0c, 0x0a, 0x90, 0x22, 0x20, 0x0c, 0x08, 0x20, 0x33, 0x20, 0x8c, 0x33, 0x0c, 0x19, 0x90, 0x66, 
+        0x20, 0xd6, 0xd6, 0xf8, 0x1b, 0xbb, 0x8c, 0xeb, 0xf0, 0x66, 0x11, 0x56, 0x36, 0xf8, 0xb0, 0xb1, 
+        0x41, 0xf0, 0xbb, 0x11, 0x86, 0xde, 0xff, 0x00, 0x1b, 0xaa, 0x06, 0xdd, 0xff, 0x70, 0x3f, 0x05, 
+        0x10, 0x33, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x61, 0x89, 0xfd, 0x67, 0x43, 0x25, 0x30, 0x44, 
+        0xa5, 0x60, 0x53, 0x95, 0x50, 0x44, 0xc0, 0xe6, 0xc4, 0x25, 0xa6, 0x14, 0x2e, 0x60, 0x73, 0x20, 
+        0x10, 0x45, 0x40, 0x20, 0x57, 0x81, 0x00, 0x14, 0x40, 0x50, 0x50, 0x91, 0x50, 0x20, 0x60, 0x70, 
+        0x25, 0xb3, 0x0d, 0xf0, 0x40, 0x43, 0x11, 0x20, 0x44, 0x20, 0x16, 0x24, 0x00, 0x32, 0xa0, 0x00, 
+        0x50, 0x46, 0x11, 0x0b, 0x54, 0x30, 0x45, 0xb3, 0x2d, 0x04, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 
+        0x41, 0x78, 0xfd, 0x40, 0x53, 0xc0, 0x50, 0x63, 0x30, 0x96, 0x36, 0x05, 0x50, 0x64, 0xa5, 0x16, 
+        0xd6, 0x04, 0x42, 0xa0, 0xff, 0x47, 0xa6, 0x27, 0x10, 0x4d, 0x40, 0x20, 0x55, 0x81, 0x00, 0x42, 
+        0xa1, 0x30, 0x6f, 0x05, 0x10, 0x66, 0x01, 0x50, 0x26, 0x20, 0xd6, 0x64, 0x00, 0x1b, 0x22, 0xf0, 
+        0x44, 0x11, 0x8c, 0x24, 0x0d, 0xf0, 0x00, 0x00, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 
+        0x41, 0x67, 0xfd, 0x47, 0xc3, 0x0a, 0x40, 0x53, 0x11, 0x20, 0x55, 0x20, 0x8c, 0x15, 0x40, 0x41, 
+        0x41, 0xc0, 0x44, 0x11, 0x30, 0x6f, 0x05, 0x00, 0x41, 0x40, 0x40, 0x26, 0x81, 0x0d, 0xf0, 0x00, 
+        0x30, 0x64, 0xa5, 0x52, 0xa3, 0x80, 0x60, 0x65, 0xc0, 0x1b, 0x66, 0xf6, 0xc6, 0x29, 0x30, 0x55, 
+        0x11, 0x30, 0x55, 0x20, 0x50, 0x55, 0x11, 0x50, 0x5b, 0x41, 0x10, 0x4d, 0x40, 0x20, 0x55, 0x81, 
+        0x00, 0x42, 0xa1, 0x00, 0x06, 0x40, 0x00, 0x74, 0xa1, 0x40, 0x45, 0x81, 0x50, 0x50, 0x91, 0x16, 
+        0xe7, 0xf8, 0x60, 0x44, 0x20, 0x06, 0xe2, 0xff, 0x30, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xd0, 0x22, 0x61, 0x00, 0x52, 0x61, 0x03, 0x42, 0x61, 0x02, 0x09, 0x61, 0x39, 0x11, 
+        0xc9, 0x71, 0xd9, 0x81, 0xcd, 0x02, 0xdd, 0x04, 0x3d, 0x04, 0x45, 0xc7, 0x00, 0x48, 0x31, 0x08, 
+        0x11, 0xc0, 0x44, 0x82, 0xd0, 0x00, 0x82, 0xc8, 0x71, 0xd8, 0x81, 0x4a, 0x00, 0x0a, 0x33, 0x08, 
+        0x61, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x00, 0x00, 0x8d, 0x04, 0x7d, 0x05, 0x62, 0xa0, 0xf0, 0x60, 
+        0x11, 0xc0, 0x39, 0x11, 0x29, 0x01, 0x59, 0x31, 0x49, 0x21, 0xd2, 0x61, 0x2b, 0x02, 0x61, 0x29, 
+        0xc2, 0x61, 0x2a, 0x0d, 0x02, 0xcd, 0x03, 0x96, 0x53, 0x19, 0x0c, 0x0d, 0xc9, 0x51, 0x9d, 0x00, 
+        0x28, 0x31, 0x99, 0x41, 0xd6, 0x02, 0x01, 0x40, 0x80, 0x60, 0x72, 0xaf, 0xff, 0x70, 0xdd, 0x30, 
+        0x70, 0x75, 0x30, 0x1b, 0x37, 0x40, 0x73, 0x83, 0x79, 0x71, 0x89, 0x61, 0x5d, 0x00, 0x3d, 0x08, 
+        0x0d, 0x08, 0x16, 0xa7, 0x17, 0x77, 0xbc, 0x27, 0x0c, 0x0c, 0x0c, 0x00, 0x3d, 0x00, 0x16, 0xed, 
+        0x43, 0xd2, 0x21, 0x2b, 0x42, 0xa0, 0xf0, 0xc0, 0x20, 0x60, 0x7c, 0xf9, 0x90, 0x30, 0x30, 0x1b, 
+        0x83, 0xc0, 0x38, 0x83, 0x02, 0x21, 0x29, 0xc2, 0x21, 0x2a, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x00, 
+        0x82, 0x61, 0x26, 0xa0, 0xf7, 0x40, 0xa2, 0x61, 0x27, 0xcc, 0xca, 0xc7, 0x37, 0x05, 0x87, 0xb5, 
+        0x02, 0x46, 0x07, 0x01, 0x0c, 0x1c, 0x06, 0xf0, 0xff, 0x52, 0x61, 0x14, 0x32, 0x21, 0x26, 0x52, 
+        0x21, 0x27, 0x2c, 0x06, 0x50, 0x66, 0xc0, 0x00, 0x06, 0x40, 0x62, 0x61, 0x1e, 0xc0, 0x20, 0x91, 
+        0x00, 0x15, 0x40, 0x22, 0x61, 0x1f, 0x30, 0x37, 0x81, 0x32, 0x61, 0x24, 0x30, 0x30, 0xf5, 0x32, 
+        0x61, 0x25, 0x05, 0xa5, 0x00, 0x02, 0x21, 0x14, 0x32, 0x21, 0x1e, 0x22, 0x61, 0x23, 0x42, 0x21, 
+        0x27, 0x22, 0x61, 0x35, 0x00, 0x14, 0x40, 0x22, 0x21, 0x1f, 0x00, 0xcc, 0xa1, 0x00, 0x03, 0x40, 
+        0x00, 0x00, 0x91, 0x32, 0x21, 0x25, 0x00, 0xcc, 0x20, 0xc2, 0x61, 0x20, 0xc0, 0xc0, 0xf5, 0x45, 
+        0xb3, 0x00, 0x00, 0x42, 0x11, 0x02, 0x21, 0x35, 0x22, 0x21, 0x24, 0x40, 0x4c, 0x20, 0xcd, 0x04, 
+        0x20, 0x20, 0xf4, 0x22, 0x61, 0x21, 0x00, 0x22, 0x82, 0x27, 0xb4, 0x1a, 0x0b, 0x60, 0x52, 0x21, 
+        0x24, 0x62, 0x61, 0x23, 0x4a, 0xc5, 0x57, 0x3c, 0x0d, 0x27, 0xbc, 0x0a, 0x82, 0xc0, 0xfe, 0x72, 
+        0x21, 0x24, 0x82, 0x61, 0x23, 0xca, 0xc7, 0x32, 0x21, 0x25, 0x20, 0xcc, 0xc0, 0x2d, 0x0c, 0x45, 
+        0x9e, 0x00, 0x32, 0x21, 0x25, 0x22, 0x61, 0x37, 0x22, 0x61, 0x36, 0x92, 0x21, 0x20, 0x2d, 0x0c, 
+        0x90, 0x90, 0xf4, 0x92, 0x61, 0x22, 0xc5, 0xad, 0x00, 0x02, 0x21, 0x37, 0x52, 0x21, 0x36, 0x00, 
+        0xa2, 0x11, 0x92, 0x21, 0x22, 0x22, 0x21, 0x21, 0xa0, 0x99, 0x20, 0x4d, 0x09, 0x50, 0x22, 0x82, 
+        0x27, 0xb9, 0x13, 0xb2, 0x21, 0x24, 0x0b, 0x05, 0x90, 0x4b, 0x80, 0xb7, 0x34, 0x08, 0x27, 0xb4, 
+        0x05, 0x40, 0x4b, 0x80, 0x02, 0xc5, 0xfe, 0x32, 0x21, 0x26, 0x52, 0x21, 0x27, 0x20, 0x44, 0xc0, 
+        0x42, 0x61, 0x38, 0x22, 0x21, 0x23, 0x00, 0x15, 0x40, 0x00, 0x33, 0xa1, 0x00, 0x22, 0x11, 0x20, 
+        0x20, 0x20, 0x22, 0x61, 0x1b, 0xcd, 0x02, 0x85, 0xac, 0x00, 0x02, 0x21, 0x38, 0x37, 0x30, 0x17, 
+        0x30, 0x40, 0xc0, 0x56, 0x34, 0xeb, 0x62, 0x21, 0x27, 0x52, 0x21, 0x14, 0x00, 0x16, 0x40, 0x00, 
+        0x55, 0xa1, 0x27, 0x35, 0x02, 0x46, 0xa8, 0xff, 0xc2, 0x21, 0x1b, 0x0b, 0xcc, 0x46, 0xa6, 0xff, 
+        0x7c, 0xfd, 0xd0, 0xc3, 0x30, 0x1b, 0x0c, 0x20, 0xc0, 0x83, 0x20, 0x00, 0x60, 0xc6, 0x96, 0xff, 
+        0x92, 0x61, 0x15, 0x87, 0x3c, 0x02, 0x86, 0x39, 0x00, 0xc2, 0x61, 0x28, 0x82, 0x61, 0x1c, 0x40, 
+        0xf8, 0x40, 0x9c, 0x34, 0x00, 0x14, 0x40, 0x00, 0x25, 0xa1, 0x50, 0x6c, 0x81, 0x00, 0x78, 0xa1, 
+        0x72, 0x61, 0x1c, 0x62, 0x61, 0x28, 0x22, 0x61, 0x15, 0xc2, 0x21, 0x15, 0x32, 0x21, 0x1c, 0x22, 
+        0x21, 0x28, 0x30, 0x30, 0xf5, 0x32, 0x61, 0x18, 0x85, 0x90, 0x00, 0x32, 0x21, 0x18, 0x22, 0x61, 
+        0x10, 0x22, 0x61, 0x2f, 0xc0, 0x40, 0xf5, 0x42, 0x61, 0x16, 0x22, 0x21, 0x28, 0x45, 0xa0, 0x00, 
+        0x42, 0x21, 0x2f, 0x00, 0x62, 0x11, 0x02, 0x21, 0x1c, 0x52, 0x21, 0x16, 0x00, 0x00, 0xf4, 0x60, 
+        0x55, 0x20, 0x52, 0x61, 0x19, 0x02, 0x61, 0x1d, 0x40, 0x00, 0x82, 0x07, 0xb5, 0x27, 0x82, 0x21, 
+        0x1c, 0x0b, 0x94, 0x92, 0x61, 0x10, 0x80, 0x75, 0x80, 0x72, 0x61, 0x19, 0x87, 0x37, 0x16, 0xa2, 
+        0x21, 0x19, 0x07, 0xba, 0x10, 0xb2, 0x21, 0x19, 0x32, 0xc4, 0xfe, 0x22, 0x21, 0x1c, 0x32, 0x61, 
+        0x10, 0xba, 0xb2, 0xb2, 0x61, 0x19, 0x22, 0x21, 0x19, 0x32, 0x21, 0x18, 0x00, 0x22, 0xc0, 0x22, 
+        0x61, 0x19, 0x05, 0x8a, 0x00, 0x32, 0x21, 0x18, 0x22, 0x61, 0x31, 0x22, 0x61, 0x30, 0xc0, 0x40, 
+        0xf4, 0x42, 0x61, 0x17, 0x22, 0x21, 0x19, 0xc5, 0x99, 0x00, 0x02, 0x21, 0x31, 0x42, 0x21, 0x10, 
+        0x32, 0x21, 0x30, 0x00, 0x62, 0x11, 0x52, 0x21, 0x17, 0x82, 0x21, 0x1d, 0x60, 0x55, 0x20, 0x30, 
+        0x88, 0x82, 0x87, 0xb5, 0x0f, 0x72, 0x21, 0x1c, 0x0b, 0x03, 0x7a, 0x55, 0x77, 0x35, 0x05, 0x87, 
+        0xb5, 0x02, 0x02, 0xc3, 0xfe, 0x00, 0xc4, 0x11, 0xc0, 0xc0, 0x20, 0x0c, 0x00, 0xc6, 0x66, 0xff, 
+        0x56, 0xe8, 0x00, 0x52, 0x61, 0x14, 0x22, 0xa0, 0x01, 0x85, 0x84, 0x00, 0x20, 0x02, 0x20, 0x52, 
+        0x21, 0x14, 0x02, 0x61, 0x1c, 0x30, 0xf0, 0x40, 0xec, 0x03, 0x02, 0x61, 0x1c, 0x00, 0x40, 0xf5, 
+        0x0c, 0x12, 0x00, 0x30, 0xf4, 0x00, 0x5c, 0xc0, 0x52, 0x61, 0x28, 0x32, 0x61, 0x1d, 0x22, 0x61, 
+        0x11, 0x42, 0x61, 0x18, 0xc2, 0x21, 0x18, 0x06, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x13, 0x40, 0x2c, 
+        0x0a, 0x30, 0xaa, 0xc0, 0x00, 0x60, 0xa1, 0x62, 0x61, 0x1c, 0x00, 0x0a, 0x40, 0xc0, 0x20, 0x91, 
+        0x00, 0x13, 0x40, 0x29, 0xc1, 0x60, 0x30, 0xf5, 0x00, 0x75, 0xa1, 0x50, 0x8c, 0x81, 0x82, 0x61, 
+        0x28, 0x72, 0x61, 0x15, 0x32, 0x61, 0x18, 0xc5, 0x7e, 0x00, 0xb2, 0x21, 0x28, 0x29, 0xf1, 0x22, 
+        0x61, 0x2c, 0xc2, 0x21, 0x18, 0x28, 0xc1, 0x3d, 0x0c, 0xb0, 0xb0, 0xf5, 0xb9, 0xd1, 0x45, 0x8e, 
+        0x00, 0x02, 0x21, 0x2c, 0x00, 0x52, 0x11, 0x32, 0x21, 0x1c, 0x48, 0xd1, 0x30, 0x30, 0xf4, 0x50, 
+        0x44, 0x20, 0x42, 0x61, 0x13, 0x32, 0x61, 0x1d, 0x00, 0x33, 0x82, 0x37, 0xb4, 0x24, 0x72, 0x21, 
+        0x1c, 0x0b, 0x80, 0x89, 0xf1, 0x7a, 0x64, 0x62, 0x61, 0x13, 0x77, 0x36, 0x15, 0x92, 0x21, 0x13, 
+        0x37, 0xb9, 0x0f, 0xa2, 0x21, 0x13, 0x22, 0xc0, 0xfe, 0xb2, 0x21, 0x1c, 0x29, 0xf1, 0xaa, 0xab, 
+        0xa2, 0x61, 0x13, 0x22, 0x21, 0x13, 0x30, 0x22, 0xc0, 0x22, 0x61, 0x13, 0x3d, 0x0c, 0x45, 0x78, 
+        0x00, 0x22, 0x61, 0x2e, 0x32, 0x21, 0x28, 0x22, 0x61, 0x2d, 0x30, 0x30, 0xf4, 0x22, 0x21, 0x13, 
+        0x39, 0xe1, 0x3d, 0x0c, 0xc5, 0x87, 0x00, 0x02, 0x21, 0x2e, 0x32, 0x21, 0x2d, 0x52, 0x21, 0x1d, 
+        0x88, 0xe1, 0x00, 0x92, 0x11, 0x90, 0x88, 0x20, 0x4d, 0x08, 0x30, 0x55, 0x82, 0x57, 0xb8, 0x11, 
+        0xa2, 0x21, 0x1c, 0x0b, 0x03, 0xaa, 0x48, 0xa7, 0x34, 0x07, 0x57, 0xb4, 0x04, 0x02, 0xc3, 0xfe, 
+        0x4a, 0x4a, 0x50, 0x34, 0xc0, 0x28, 0xf1, 0x32, 0x61, 0x28, 0x00, 0x22, 0x11, 0x20, 0x20, 0x20, 
+        0x22, 0x61, 0x11, 0x22, 0x21, 0x28, 0x3d, 0x0c, 0x85, 0x72, 0x00, 0xc0, 0x3c, 0x20, 0x22, 0x61, 
+        0x12, 0x22, 0x61, 0x32, 0x42, 0x21, 0x15, 0x22, 0x21, 0x28, 0x40, 0x40, 0xf5, 0x42, 0x61, 0x16, 
+        0x05, 0x82, 0x00, 0x42, 0x21, 0x32, 0x02, 0x21, 0x1d, 0x52, 0x21, 0x16, 0x00, 0x62, 0x11, 0x60, 
+        0x55, 0x20, 0x52, 0x61, 0x1a, 0x40, 0x00, 0x82, 0x07, 0xb5, 0x27, 0x82, 0x21, 0x1c, 0x0b, 0x94, 
+        0x92, 0x61, 0x12, 0x8a, 0x75, 0x72, 0x61, 0x1a, 0x87, 0x37, 0x17, 0xa2, 0x21, 0x1a, 0x07, 0xba, 
+        0x11, 0xb2, 0x21, 0x1a, 0x32, 0xc4, 0xfe, 0x22, 0x21, 0x1c, 0x32, 0x61, 0x12, 0xb0, 0xb2, 0x80, 
+        0xb2, 0x61, 0x1a, 0x22, 0x21, 0x1a, 0x3d, 0x0c, 0x00, 0x22, 0xc0, 0x22, 0x61, 0x1a, 0x45, 0x6c, 
+        0x00, 0xc0, 0x3c, 0x20, 0x22, 0x61, 0x34, 0x22, 0x61, 0x33, 0x42, 0x21, 0x15, 0x22, 0x21, 0x1a, 
+        0x40, 0x40, 0xf4, 0x42, 0x61, 0x17, 0xc5, 0x7b, 0x00, 0x42, 0x21, 0x34, 0x02, 0x21, 0x33, 0x82, 
+        0x21, 0x17, 0x00, 0x92, 0x11, 0x90, 0x88, 0x20, 0x92, 0x21, 0x1d, 0x52, 0x21, 0x12, 0x00, 0x99, 
+        0x82, 0x97, 0xb8, 0x0f, 0xa2, 0x21, 0x1c, 0x0b, 0x40, 0xaa, 0x88, 0xa7, 0x38, 0x05, 0x97, 0xb8, 
+        0x02, 0x42, 0xc0, 0xfe, 0x02, 0x21, 0x11, 0x00, 0xc5, 0x11, 0xc0, 0xc4, 0x20, 0xc6, 0xee, 0xfe, 
+        0x02, 0x21, 0x29, 0xd2, 0x21, 0x2b, 0x2d, 0x0c, 0x42, 0xa0, 0xf0, 0xc2, 0x21, 0x2a, 0x4a, 0x11, 
+        0x0d, 0xf0, 0x0c, 0x0c, 0x86, 0xe8, 0xfe, 0x00, 0x8d, 0x02, 0x62, 0xa0, 0xc0, 0x60, 0x11, 0xc0, 
+        0x89, 0x01, 0x59, 0x31, 0x49, 0x21, 0x39, 0x11, 0x02, 0x61, 0x1e, 0xd2, 0x61, 0x20, 0xe2, 0x61, 
+        0x21, 0xc2, 0x61, 0x1f, 0xed, 0x02, 0xcd, 0x03, 0xdd, 0x03, 0x0d, 0x04, 0x3d, 0x04, 0x16, 0xb5, 
+        0x17, 0x57, 0xbc, 0x17, 0x0c, 0x03, 0x0c, 0x02, 0xe2, 0x21, 0x21, 0xd2, 0x21, 0x20, 0xc2, 0x21, 
+        0x1f, 0x42, 0xa0, 0xc0, 0x02, 0x21, 0x1e, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x42, 0x61, 0x2e, 0xd0, 
+        0xf5, 0x40, 0xdc, 0xed, 0xc7, 0x35, 0x05, 0x47, 0xb2, 0x02, 0xc6, 0xfc, 0x00, 0x0c, 0x03, 0x0c, 
+        0x12, 0xe2, 0x21, 0x21, 0xd2, 0x21, 0x20, 0xc2, 0x21, 0x1f, 0x42, 0xa0, 0xc0, 0x02, 0x21, 0x1e, 
+        0x4a, 0x11, 0x0d, 0xf0, 0x82, 0x61, 0x12, 0xe2, 0x21, 0x2e, 0x2c, 0x04, 0xd0, 0x44, 0xc0, 0x00, 
+        0x04, 0x40, 0x42, 0x61, 0x16, 0xc0, 0x20, 0x91, 0x00, 0x1d, 0x40, 0x22, 0x61, 0x17, 0xe0, 0x35, 
+        0x81, 0x32, 0x61, 0x1c, 0x30, 0x30, 0xf5, 0x32, 0x61, 0x1d, 0x85, 0x5c, 0x00, 0x02, 0x21, 0x12, 
+        0x32, 0x21, 0x16, 0x22, 0x61, 0x1b, 0x22, 0x61, 0x2b, 0x00, 0x1d, 0x40, 0x00, 0xcc, 0xa1, 0x22, 
+        0x21, 0x17, 0x00, 0x03, 0x40, 0x00, 0x00, 0x91, 0x32, 0x21, 0x1d, 0x00, 0xcc, 0x20, 0xc2, 0x61, 
+        0x18, 0xc0, 0xc0, 0xf5, 0xc5, 0x6a, 0x00, 0x00, 0x42, 0x11, 0x02, 0x21, 0x2b, 0x22, 0x21, 0x1c, 
+        0x40, 0x4c, 0x20, 0xcd, 0x04, 0x20, 0x20, 0xf4, 0x22, 0x61, 0x19, 0x00, 0x22, 0x82, 0x27, 0xb4, 
+        0x1b, 0x0b, 0x60, 0x52, 0x21, 0x1c, 0x62, 0x61, 0x1b, 0x40, 0xc5, 0x80, 0x57, 0x3c, 0x0d, 0x27, 
+        0xbc, 0x0a, 0x82, 0xc0, 0xfe, 0x72, 0x21, 0x1c, 0x82, 0x61, 0x1b, 0xca, 0xc7, 0x32, 0x21, 0x1d, 
+        0x20, 0xcc, 0xc0, 0x2d, 0x0c, 0xc5, 0x55, 0x00, 0x32, 0x21, 0x1d, 0x22, 0x61, 0x2d, 0x22, 0x61, 
+        0x2c, 0x92, 0x21, 0x18, 0x2d, 0x0c, 0x90, 0x90, 0xf4, 0x92, 0x61, 0x1a, 0x45, 0x65, 0x00, 0x02, 
+        0x21, 0x2d, 0x32, 0x21, 0x2c, 0x00, 0x52, 0x11, 0x42, 0x21, 0x1a, 0x22, 0x21, 0x19, 0x50, 0x44, 
+        0x20, 0xcd, 0x04, 0x30, 0x22, 0x82, 0x27, 0xb4, 0x11, 0x62, 0x21, 0x1c, 0x0b, 0x03, 0x4a, 0xc6, 
+        0x67, 0x3c, 0x07, 0x27, 0xbc, 0x04, 0xca, 0xc6, 0x02, 0xc3, 0xfe, 0x20, 0xcc, 0xc0, 0x00, 0x1d, 
+        0x40, 0x22, 0x21, 0x1b, 0x00, 0x3e, 0xa1, 0x00, 0x22, 0x11, 0x20, 0x20, 0x20, 0x22, 0x61, 0x15, 
+        0xed, 0x02, 0xc5, 0x64, 0x00, 0x37, 0x3c, 0x0e, 0x37, 0x9c, 0x28, 0x32, 0x21, 0x12, 0x00, 0x1d, 
+        0x40, 0x00, 0x33, 0xa1, 0x27, 0xb3, 0x1c, 0x0c, 0x03, 0x02, 0x21, 0x1e, 0xc2, 0x21, 0x1f, 0xd2, 
+        0x21, 0x20, 0xe2, 0x21, 0x15, 0x42, 0xa0, 0xc0, 0x0b, 0xee, 0x2d, 0x0e, 0xe2, 0x21, 0x21, 0x4a, 
+        0x11, 0x0d, 0xf0, 0x00, 0x0c, 0x03, 0x02, 0x21, 0x1e, 0xc2, 0x21, 0x1f, 0xd2, 0x21, 0x20, 0x2d, 
+        0x0e, 0x42, 0xa0, 0xc0, 0xe2, 0x21, 0x21, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x47, 0x3c, 0x02, 
+        0x86, 0x36, 0x00, 0x09, 0xd1, 0x40, 0xf4, 0x40, 0x16, 0xe4, 0x00, 0x00, 0x14, 0x40, 0x20, 0xdc, 
+        0x81, 0x00, 0xe2, 0xa1, 0x00, 0x03, 0xa1, 0x02, 0x61, 0x0d, 0xc8, 0xd1, 0x2d, 0x0d, 0xc0, 0x30, 
+        0xf5, 0x32, 0x61, 0x13, 0xc5, 0x48, 0x00, 0x29, 0xc1, 0x22, 0x61, 0x25, 0xe0, 0x30, 0xf5, 0x32, 
+        0x61, 0x10, 0x2d, 0x0d, 0x32, 0x21, 0x13, 0xc5, 0x58, 0x00, 0x42, 0x21, 0x25, 0x00, 0x32, 0x11, 
+        0xc0, 0x00, 0xf4, 0x22, 0x21, 0x10, 0x09, 0xe1, 0x30, 0x22, 0x20, 0xdd, 0x02, 0x40, 0x00, 0x82, 
+        0x07, 0xb2, 0x12, 0xca, 0xd2, 0x0b, 0x54, 0x59, 0xc1, 0xc7, 0x3d, 0x09, 0x07, 0xbd, 0x06, 0xda, 
+        0xdc, 0x62, 0xc4, 0xfe, 0x69, 0xc1, 0x32, 0x21, 0x13, 0x00, 0xdd, 0xc0, 0x2d, 0x0d, 0x45, 0x44, 
+        0x00, 0xe0, 0xe0, 0xf4, 0x22, 0x61, 0x27, 0x22, 0x61, 0x26, 0x32, 0x21, 0x13, 0x2d, 0x0d, 0x45, 
+        0x54, 0x00, 0x02, 0x21, 0x27, 0x32, 0x21, 0x26, 0x00, 0x22, 0x11, 0x48, 0xe1, 0x20, 0x2e, 0x20, 
+        0x30, 0x44, 0x82, 0x47, 0xb2, 0x29, 0x0b, 0x03, 0xca, 0x22, 0xc7, 0x32, 0x22, 0x47, 0xb2, 0x1f, 
+        0xc2, 0x21, 0x1f, 0xd2, 0x21, 0x20, 0xe2, 0x21, 0x21, 0x42, 0xa0, 0xc0, 0x02, 0xc3, 0xfe, 0x28, 
+        0xc1, 0x0c, 0x03, 0x00, 0x22, 0x11, 0x20, 0x20, 0x20, 0x02, 0x21, 0x1e, 0x4a, 0x11, 0x0d, 0xf0, 
+        0x0c, 0x03, 0xc2, 0x21, 0x1f, 0xd2, 0x21, 0x20, 0xe2, 0x21, 0x21, 0x28, 0xc1, 0x42, 0xa0, 0xc0, 
+        0x00, 0x22, 0x11, 0x20, 0x20, 0x20, 0x02, 0x21, 0x1e, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0xcc, 0xb4, 
+        0x82, 0x61, 0x12, 0x0c, 0x12, 0xc5, 0x3c, 0x00, 0x82, 0x21, 0x12, 0x0d, 0x02, 0x09, 0xd1, 0x30, 
+        0xf0, 0x40, 0xdc, 0x33, 0x09, 0xd1, 0x0c, 0x13, 0x00, 0xdc, 0xc0, 0x00, 0x40, 0xf4, 0x00, 0xc0, 
+        0xf5, 0x49, 0xe1, 0x39, 0xb1, 0x86, 0x32, 0x00, 0x00, 0x00, 0x13, 0x40, 0x58, 0xd1, 0x2c, 0x00, 
+        0x30, 0x00, 0xc0, 0x00, 0x55, 0xa1, 0x59, 0xd1, 0x00, 0x00, 0x40, 0xc0, 0x20, 0x91, 0x29, 0x81, 
+        0x00, 0x13, 0x40, 0x80, 0xdc, 0x81, 0x00, 0xe8, 0xa1, 0x50, 0xc0, 0xf5, 0x3d, 0x0c, 0x45, 0x38, 
+        0x00, 0x29, 0xa1, 0x22, 0x61, 0x22, 0xd0, 0x30, 0xf5, 0x39, 0x91, 0x28, 0x81, 0x3d, 0x0c, 0x45, 
+        0x48, 0x00, 0x02, 0x21, 0x22, 0x00, 0x52, 0x11, 0x38, 0xd1, 0x48, 0x91, 0x30, 0x30, 0xf4, 0x50, 
+        0x44, 0x20, 0x42, 0x61, 0x11, 0x39, 0xe1, 0x00, 0x33, 0x82, 0x37, 0xb4, 0x22, 0x78, 0xd1, 0x0b, 
+        0x80, 0x89, 0xa1, 0x7a, 0x64, 0x62, 0x61, 0x11, 0x77, 0x36, 0x14, 0x92, 0x21, 0x11, 0x37, 0xb9, 
+        0x0e, 0xa2, 0x21, 0x11, 0x22, 0xc0, 0xfe, 0xb8, 0xd1, 0x29, 0xa1, 0xaa, 0xab, 0xa2, 0x61, 0x11, 
+        0x22, 0x21, 0x11, 0x30, 0x22, 0xc0, 0x22, 0x61, 0x11, 0x3d, 0x0c, 0x85, 0x32, 0x00, 0xd0, 0xd0, 
+        0xf4, 0x22, 0x61, 0x24, 0x22, 0x61, 0x23, 0x3d, 0x0c, 0x22, 0x21, 0x11, 0x45, 0x42, 0x00, 0x02, 
+        0x21, 0x24, 0x32, 0x21, 0x23, 0x58, 0xe1, 0x00, 0x82, 0x11, 0x80, 0x8d, 0x20, 0x4d, 0x08, 0x30, 
+        0x55, 0x82, 0x57, 0xb8, 0x10, 0x98, 0xd1, 0x0b, 0x03, 0x9a, 0x48, 0x97, 0x34, 0x07, 0x57, 0xb4, 
+        0x04, 0x02, 0xc3, 0xfe, 0x4a, 0x49, 0xb8, 0xa1, 0x50, 0xd4, 0xc0, 0x00, 0xbb, 0x11, 0xb0, 0xb0, 
+        0x20, 0xb9, 0xb1, 0x2d, 0x0d, 0x3d, 0x0c, 0xc5, 0x2d, 0x00, 0x3d, 0x0c, 0x29, 0xf1, 0x22, 0x61, 
+        0x28, 0xe0, 0x00, 0xf5, 0x02, 0x61, 0x10, 0x2d, 0x0d, 0x85, 0x3d, 0x00, 0x42, 0x21, 0x28, 0xd8, 
+        0xe1, 0x52, 0x21, 0x10, 0x00, 0x62, 0x11, 0x60, 0x55, 0x20, 0x52, 0x61, 0x14, 0x40, 0x0d, 0x82, 
+        0x07, 0xb5, 0x22, 0x88, 0xd1, 0x0b, 0x94, 0x99, 0xf1, 0x8a, 0x75, 0x72, 0x61, 0x14, 0x87, 0x37, 
+        0x14, 0xa2, 0x21, 0x14, 0x07, 0xba, 0x0e, 0xb2, 0x21, 0x14, 0x32, 0xc4, 0xfe, 0x28, 0xd1, 0x39, 
+        0xf1, 0xba, 0xb2, 0xb2, 0x61, 0x14, 0x22, 0x21, 0x14, 0x3d, 0x0c, 0x00, 0x22, 0xc0, 0x22, 0x61, 
+        0x14, 0x05, 0x28, 0x00, 0xe0, 0xe0, 0xf4, 0x22, 0x61, 0x2a, 0x22, 0x61, 0x29, 0x3d, 0x0c, 0x22, 
+        0x21, 0x14, 0x05, 0x38, 0x00, 0x02, 0x21, 0x2a, 0x00, 0x52, 0x11, 0x42, 0x21, 0x29, 0x50, 0x5e, 
+        0x20, 0x40, 0x8d, 0x82, 0x87, 0xb5, 0x2c, 0x68, 0xd1, 0x0b, 0x04, 0x6a, 0x55, 0x67, 0x35, 0x23, 
+        0x87, 0xb5, 0x20, 0x38, 0xb1, 0xc2, 0x21, 0x1f, 0xd2, 0x21, 0x20, 0xe2, 0x21, 0x21, 0x02, 0xc4, 
+        0xfe, 0x28, 0xf1, 0x42, 0xa0, 0xc0, 0x00, 0x22, 0x11, 0x20, 0x20, 0x20, 0x02, 0x21, 0x1e, 0x4a, 
+        0x11, 0x0d, 0xf0, 0x00, 0x38, 0xb1, 0xc2, 0x21, 0x1f, 0xd2, 0x21, 0x20, 0xe2, 0x21, 0x21, 0x28, 
+        0xf1, 0x42, 0xa0, 0xc0, 0x00, 0x22, 0x11, 0x20, 0x20, 0x20, 0x02, 0x21, 0x1e, 0x4a, 0x11, 0x0d, 
+        0xf0, 0x0c, 0x02, 0x0c, 0x03, 0xc2, 0x21, 0x1f, 0xd2, 0x21, 0x20, 0xe2, 0x21, 0x21, 0x42, 0xa0, 
+        0xc0, 0x02, 0x21, 0x1e, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x8c, 0xd4, 0x4a, 0x73, 0x62, 0x03, 0x00, 
+        0x1b, 0x33, 0x62, 0x45, 0x00, 0x1b, 0x55, 0x77, 0x23, 0xf2, 0x0d, 0xf0, 0xb6, 0x74, 0xe9, 0x62, 
+        0x03, 0x00, 0x1b, 0x33, 0x42, 0xc4, 0xff, 0x62, 0x45, 0x00, 0x52, 0xc5, 0x01, 0x17, 0x65, 0x24, 
+        0xb6, 0x64, 0xd5, 0x62, 0x03, 0x00, 0x72, 0x03, 0x01, 0x2b, 0x33, 0x42, 0xc4, 0xfe, 0x62, 0x45, 
+        0x00, 0x72, 0x45, 0x01, 0x2b, 0x55, 0xc6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x52, 0x20, 0x07, 
+        0xe2, 0xc9, 0x17, 0xe2, 0xda, 0x40, 0x74, 0x41, 0x0c, 0x38, 0x87, 0x83, 0x62, 0x9c, 0xc7, 0xc0, 
+        0x87, 0x11, 0x3a, 0x88, 0x68, 0x03, 0x78, 0x13, 0x69, 0x05, 0x68, 0x23, 0x79, 0x15, 0x78, 0x33, 
+        0x69, 0x25, 0x32, 0xc3, 0x10, 0x79, 0x35, 0x52, 0xc5, 0x10, 0x87, 0x23, 0xe6, 0x37, 0x64, 0x0b, 
+        0x68, 0x03, 0x78, 0x13, 0x8b, 0x33, 0x69, 0x05, 0x79, 0x15, 0x8b, 0x55, 0x27, 0xe4, 0x08, 0x17, 
+        0xe4, 0x15, 0x07, 0xe4, 0x22, 0x0d, 0xf0, 0x00, 0x68, 0x03, 0x4b, 0x33, 0x69, 0x05, 0x4b, 0x55, 
+        0x17, 0xe4, 0x04, 0x07, 0xe4, 0x11, 0x0d, 0xf0, 0x62, 0x13, 0x00, 0x2b, 0x33, 0x62, 0x55, 0x00, 
+        0x2b, 0x55, 0x07, 0xe4, 0x02, 0x0d, 0xf0, 0x00, 0x62, 0x03, 0x00, 0x62, 0x45, 0x00, 0x0d, 0xf0, 
+        0x16, 0xa4, 0xff, 0x00, 0x23, 0x40, 0x80, 0xb3, 0x10, 0xb0, 0x33, 0xc0, 0x68, 0x03, 0xac, 0xa7, 
+        0xc0, 0xa7, 0x11, 0x30, 0xaa, 0x80, 0x78, 0x13, 0x88, 0x23, 0x60, 0x67, 0x81, 0x69, 0x05, 0x98, 
+        0x33, 0x70, 0x78, 0x81, 0x79, 0x15, 0x68, 0x43, 0x80, 0x89, 0x81, 0x89, 0x25, 0x32, 0xc3, 0x10, 
+        0x90, 0x96, 0x81, 0x92, 0x65, 0x03, 0x52, 0xc5, 0x10, 0xa7, 0x23, 0xd9, 0x37, 0x64, 0x14, 0x78, 
+        0x13, 0x88, 0x23, 0x60, 0x67, 0x81, 0x69, 0x05, 0x8b, 0x33, 0x70, 0x78, 0x81, 0x79, 0x15, 0x8b, 
+        0x55, 0x80, 0x68, 0x20, 0x27, 0x64, 0x0c, 0x78, 0x13, 0x4b, 0x33, 0x60, 0x67, 0x81, 0x69, 0x05, 
+        0x4b, 0x55, 0x6d, 0x07, 0xba, 0x33, 0x17, 0xe4, 0x06, 0x07, 0xe4, 0x18, 0x0d, 0xf0, 0x00, 0x00, 
+        0x62, 0x03, 0x00, 0x72, 0x03, 0x01, 0x2b, 0x33, 0x62, 0x45, 0x00, 0x72, 0x45, 0x01, 0x2b, 0x55, 
+        0x07, 0xe4, 0x01, 0x0d, 0xf0, 0x62, 0x03, 0x00, 0x62, 0x45, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x30, 0x72, 0x30, 0x20, 0x61, 0x60, 0x30, 0x31, 0x60, 0xb6, 0x23, 0x37, 0x60, 0x51, 0x41, 0x37, 
+        0x35, 0x3d, 0x50, 0xf6, 0x40, 0x40, 0xf3, 0x40, 0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 0x00, 0x33, 
+        0xa1, 0x22, 0xa0, 0x00, 0x37, 0x36, 0x04, 0x30, 0x66, 0xc0, 0x1b, 0x22, 0xf0, 0x22, 0x11, 0x30, 
+        0x31, 0x41, 0x0b, 0x44, 0x56, 0xc4, 0xfe, 0x37, 0x36, 0x01, 0x1b, 0x22, 0x20, 0x50, 0x60, 0x70, 
+        0x25, 0xa3, 0x0d, 0xf0, 0x9c, 0x53, 0x60, 0x20, 0x60, 0x70, 0x26, 0xb3, 0x0d, 0xf0, 0x00, 0x00, 
+        0x37, 0x36, 0x10, 0x0c, 0x12, 0x7c, 0xf4, 0x70, 0x24, 0xa3, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 
+        0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 0x7d, 0x02, 0x20, 0x21, 0x60, 0x30, 0x31, 0x60, 
+        0xb6, 0x23, 0x30, 0x50, 0xf2, 0x40, 0x40, 0xf3, 0x40, 0x47, 0xb5, 0x17, 0x50, 0x44, 0xc0, 0x00, 
+        0x14, 0x40, 0x00, 0x33, 0xa1, 0x37, 0x32, 0x02, 0x30, 0x22, 0xc0, 0x30, 0x31, 0x41, 0x42, 0xc4, 
+        0xff, 0x56, 0x04, 0xff, 0x37, 0x32, 0x02, 0x30, 0x22, 0xc0, 0xd6, 0x27, 0x00, 0x20, 0x20, 0x60, 
+        0x0d, 0xf0, 0x00, 0x00, 0xcc, 0x53, 0x00, 0x00, 0x00, 0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0xb6, 0x23, 0x30, 0x6d, 0x02, 0x50, 0xf6, 0x40, 0x40, 0xf3, 0x40, 0x47, 
+        0xb5, 0x29, 0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 0x00, 0x33, 0xa1, 0x0c, 0x02, 0x37, 0x36, 0x04, 
+        0x30, 0x66, 0xc0, 0x1b, 0x22, 0xf0, 0x22, 0x11, 0x30, 0x31, 0x41, 0x0b, 0x44, 0x56, 0xc4, 0xfe, 
+        0x37, 0x36, 0x01, 0x1b, 0x22, 0x0d, 0xf0, 0x00, 0x8c, 0x93, 0x0d, 0xf0, 0x37, 0x36, 0x0c, 0x0c, 
+        0x12, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 
+        0x00, 0x14, 0x40, 0xe6, 0xc4, 0x09, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x0d, 0xf0, 0x00, 0x00, 
+        0x00, 0x32, 0xa1, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x04, 0x40, 0xe6, 0xc4, 0x09, 0x20, 0x23, 
+        0x81, 0x30, 0x30, 0xb1, 0x0d, 0xf0, 0x00, 0x00, 0x30, 0x20, 0xb1, 0x30, 0x3f, 0x31, 0x0d, 0xf0, 
+        0x00, 0x04, 0x40, 0xe6, 0xc4, 0x09, 0x20, 0x23, 0x81, 0x30, 0x30, 0x91, 0x0d, 0xf0, 0x00, 0x00, 
+        0x30, 0x20, 0x91, 0x0c, 0x03, 0x0d, 0xf0, 0x00, 0xbc, 0x62, 0x0c, 0x07, 0x06, 0x02, 0x00, 0x00, 
+        0xac, 0xe2, 0x20, 0x7f, 0x05, 0x20, 0x21, 0x60, 0x40, 0xf2, 0x40, 0x00, 0x14, 0x40, 0x00, 0x52, 
+        0xa1, 0x50, 0x28, 0x41, 0x80, 0x65, 0x01, 0x52, 0xa0, 0x9d, 0x40, 0x55, 0xc0, 0x90, 0x55, 0x01, 
+        0x5a, 0x22, 0x10, 0x77, 0x01, 0x70, 0x22, 0x20, 0xd6, 0x66, 0x00, 0x1b, 0x22, 0xf0, 0x66, 0x11, 
+        0x8c, 0x06, 0x0d, 0xf0, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 0xac, 0xe2, 0x0c, 0x07, 
+        0x06, 0x02, 0x00, 0x00, 0xac, 0x62, 0x20, 0x7f, 0x05, 0x20, 0x21, 0x60, 0x40, 0xf2, 0x40, 0x00, 
+        0x14, 0x40, 0x00, 0x52, 0xa1, 0x50, 0x3b, 0x41, 0xb0, 0x25, 0x01, 0x52, 0xa4, 0x1d, 0x40, 0x55, 
+        0xc0, 0xc0, 0x55, 0x01, 0x5a, 0x33, 0x10, 0x77, 0x01, 0x70, 0x33, 0x20, 0x0d, 0xf0, 0x0c, 0x03, 
+        0x0d, 0xf0, 0x00, 0x00, 0xb6, 0x23, 0x28, 0x50, 0xf2, 0x40, 0x40, 0xf3, 0x40, 0x47, 0xb5, 0x17, 
+        0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 0x00, 0x33, 0xa1, 0x37, 0x32, 0x02, 0x30, 0x22, 0xc0, 0x30, 
+        0x31, 0x41, 0x42, 0xc4, 0xff, 0x56, 0x04, 0xff, 0x37, 0x32, 0x02, 0x30, 0x22, 0xc0, 0x0d, 0xf0, 
+        0xcc, 0x53, 0x00, 0x00, 0x00, 0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0xc9, 0x41, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x20, 0x40, 0xf5, 0x30, 0x50, 
+        0xf5, 0x50, 0x62, 0xc1, 0x30, 0xb4, 0xc1, 0x0c, 0x09, 0xba, 0x66, 0xb7, 0xb6, 0x02, 0x92, 0xc9, 
+        0x01, 0x10, 0x40, 0x40, 0x60, 0x99, 0x81, 0x30, 0xb2, 0xc1, 0x00, 0x66, 0xa1, 0xba, 0x66, 0xb7, 
+        0xb6, 0x01, 0x1b, 0x99, 0x50, 0x34, 0xc1, 0x9a, 0x33, 0x2d, 0x06, 0xc8, 0x41, 0xd8, 0x51, 0xe8, 
+        0x61, 0xf8, 0x71, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x80, 0xfe, 0x3f, 0x90, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x5a, 0x00, 0xf0, 0x0b, 0xc8, 0x45, 0x10, 0x40, 0xb0, 0x13, 0x10, 0x40, 0x74, 0x45, 0x10, 0x40, 
+        0x50, 0x63, 0x10, 0x40, 0xec, 0x60, 0x00, 0x40, 0xd0, 0x60, 0x00, 0x40, 0xfc, 0x2c, 0x10, 0x40, 
+        0x48, 0x63, 0x10, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 
+        0x00, 0x40, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00, 0x70, 0x00, 0x74, 0x00, 0x78, 0x00, 0x7c, 
+        0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 
+        0xf8, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xf8, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 
+        0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xf8, 0x01, 0xf8, 0x01, 
+        0x90, 0x80, 0xfe, 0x3f, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 
+        0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 0x9d, 0xff, 
+        0x9d, 0xff, 0x9d, 0xff, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x80, 0x43, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 
+        0x3a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 
+        0xe4, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 
+        0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 
+        0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 
+        0xe4, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 
+        0x60, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
+        0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 
+        0x64, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 
+        0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
+        0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
+        0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x0c, 0x10, 0x13, 0x16, 0x19, 
+        0x1c, 0x1f, 0x22, 0x24, 0x27, 0x29, 0x2c, 0x2e, 0x18, 0x24, 0x30, 0x3c, 0x48, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x3a, 0xe8, 0xee, 0x0d, 0x0c, 0xe4, 0x0c, 
+        0x00, 0x00, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 
+        0x60, 0x50, 0x18, 0x44, 0x06, 0x07, 0x2e, 0x00, 0x84, 0x01, 0xa4, 0x01, 0xe4, 0x01, 0xb4, 0x01, 
+        0xa6, 0x01, 0xac, 0x01, 0xae, 0x01, 0xa4, 0x01, 0xa4, 0x01, 0xa4, 0x01, 0xa4, 0x01, 0xa4, 0x01, 
+        0xa4, 0x01, 0xa4, 0x01, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0xa4, 0x01, 0xb6, 0x01, 0xc4, 0x01, 
+        0xe4, 0x01, 0x00, 0x00, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x6f, 0x74, 0x70, 0x0a, 0x00, 0x00, 
+        0x76, 0x65, 0x72, 0x3a, 0x25, 0x73, 0x0a, 0x00, 0x30, 0x61, 0x39, 0x39, 0x37, 0x62, 0x33, 0x65, 
+        0x31, 0x62, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00, 0x65, 0x74, 0x73, 0x20, 0x25, 0x73, 0x20, 0x25, 
+        0x73, 0x0a, 0x00, 0x00, 0x41, 0x70, 0x72, 0x20, 0x31, 0x32, 0x20, 0x32, 0x30, 0x31, 0x34, 0x00, 
+        0x31, 0x36, 0x3a, 0x30, 0x35, 0x3a, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6e, 0x74, 
+        0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x6f, 0x6e, 0x0a, 0x00, 0x00, 0x62, 0x73, 0x73, 0x20, 
+        0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x70, 0x2c, 0x65, 0x6e, 0x64, 0x20, 0x25, 0x70, 0x0a, 
+        0x00, 0x00, 0x00, 0x00, 0x6f, 0x6f, 0x62, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x25, 0x73, 0x20, 0x25, 
+        0x75, 0x0a, 0x00, 0x00, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x63, 0x00, 0x00, 
+        0x6e, 0x65, 0x77, 0x20, 0x70, 0x75, 0x74, 0x63, 0x21, 0x0a, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5f, 
+        0x72, 0x78, 0x5f, 0x67, 0x61, 0x69, 0x6e, 0x3a, 0x20, 0x72, 0x66, 0x74, 0x78, 0x3d, 0x25, 0x78, 
+        0x2c, 0x20, 0x72, 0x66, 0x72, 0x78, 0x3d, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x61, 0x74, 0x74, 0x3d, 
+        0x25, 0x64, 0x2c, 0x20, 0x74, 0x78, 0x62, 0x62, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x62, 
+        0x62, 0x72, 0x78, 0x31, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x62, 0x62, 0x72, 0x78, 0x32, 
+        0x3d, 0x30, 0x78, 0x25, 0x78, 0x2c, 0x20, 0x74, 0x64, 0x63, 0x3a, 0x25, 0x64, 0x2c, 0x25, 0x64, 
+        0x0a, 0x00, 0x00, 0x00, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x77, 0x72, 0x3d, 0x25, 0x6c, 
+        0x64, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x3d, 0x25, 0x6c, 0x64, 0x2c, 0x20, 0x0a, 0x00, 0x00, 0x00, 
+        0x25, 0x64, 0x5f, 0x25, 0x64, 0x5f, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x72, 0x78, 0x69, 0x71, 
+        0x5f, 0x72, 0x65, 0x67, 0x3a, 0x20, 0x69, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x61, 0x5f, 0x6d, 0x69, 
+        0x73, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x70, 0x5f, 0x6d, 0x69, 0x73, 0x3d, 0x25, 0x64, 0x0a, 0x00, 
+        0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x20, 0x25, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 
+        0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 
+        0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x50, 0x53, 0x54, 0x0a, 0x46, 0x54, 0x3a, 
+        0x25, 0x64, 0x2c, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x0a, 0x52, 0x4e, 0x3a, 0x25, 0x64, 0x2c, 0x25, 
+        0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 
+        0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 
+        0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 
+        0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x2c, 0x25, 
+        0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 0x2c, 0x25, 0x64, 0x3b, 0x25, 0x64, 
+        0x2c, 0x25, 0x64, 0x0a, 0x54, 0x42, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 
+        0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 
+        0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 
+        0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 
+        0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x2c, 0x25, 0x30, 0x32, 0x78, 0x0a, 0x41, 0x50, 0x45, 
+        0x44, 0x0a, 0x00, 0x00, 0x0a, 0x74, 0x78, 0x20, 0x20, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 
+        0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x20, 0x0a, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 
+        0x6c, 0x3a, 0x20, 0x25, 0x64, 0x20, 0x20, 0x0a, 0x20, 0x72, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 
+        0x66, 0x73, 0x65, 0x74, 0x3a, 0x20, 0x25, 0x64, 0x20, 0x0a, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 
+        0x72, 0x3a, 0x20, 0x70, 0x6c, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 
+        0x64, 0x73, 0x20, 0x35, 0x6d, 0x73, 0x21, 0x21, 0x21, 0x0a, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 
+        0x72, 0x3a, 0x20, 0x70, 0x6c, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 
+        0x64, 0x73, 0x20, 0x32, 0x6d, 0x73, 0x21, 0x21, 0x21, 0x0a, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6e, 
+        0x6e, 0x65, 0x6c, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6f, 0x66, 0x66, 
+        0x73, 0x65, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x25, 0x33, 0x64, 0x2c, 
+        0x25, 0x33, 0x64, 0x3b, 0x20, 0x00, 0x00, 0x00, 0x74, 0x78, 0x69, 0x71, 0x5f, 0x67, 0x61, 0x69, 
+        0x6e, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x74, 0x78, 0x69, 0x71, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 
+        0x3d, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x2c, 0x20, 
+        0x25, 0x64, 0x2c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x75, 0x6d, 0x5f, 0x6b, 0x3d, 0x25, 0x64, 
+        0x2c, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6f, 0x75, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x67, 0x5f, 0x69, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x69, 0x6e, 
+        0x64, 0x61, 0x74, 0x61, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x00, 0x00, 0x70, 0x77, 0x63, 0x74, 
+        0x72, 0x6c, 0x3a, 0x20, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x74, 
+        0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3d, 0x25, 0x64, 0x2c, 
+        0x20, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x69, 0x71, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x69, 0x73, 
+        0x3a, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x77, 0x72, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x25, 0x64, 0x2d, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 
+        0x78, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x72, 0x65, 0x67, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3a, 
+        0x20, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x20, 0x20, 0x20, 0x3b, 0x20, 0x20, 0x20, 0x72, 0x65, 
+        0x73, 0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x62, 0x65, 0x66, 0x6f, 
+        0x72, 0x65, 0x20, 0x74, 0x78, 0x20, 0x72, 0x65, 0x67, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3d, 
+        0x3d, 0x30, 0x20, 0x0a, 0x20, 0x00, 0x00, 0x00, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x78, 
+        0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x72, 0x65, 0x67, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3a, 0x20, 
+        0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x20, 0x20, 0x20, 0x3b, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 
+        0x3a, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x78, 
+        0x20, 0x72, 0x65, 0x67, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3d, 0x3d, 0x30, 0x20, 0x0a, 0x20, 
+        0x00, 0x00, 0x00, 0x00, 0x69, 0x69, 0x31, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x20, 0x69, 0x71, 0x31, 
+        0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x20, 0x71, 0x69, 0x31, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x20, 0x71, 
+        0x71, 0x31, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x69, 0x69, 0x32, 0x3d, 
+        0x25, 0x6c, 0x64, 0x3b, 0x20, 0x69, 0x71, 0x32, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x20, 0x71, 0x69, 
+        0x32, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x20, 0x71, 0x71, 0x32, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x0a, 
+        0x00, 0x00, 0x00, 0x00, 0x64, 0x63, 0x5f, 0x69, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x20, 0x64, 0x63, 
+        0x5f, 0x71, 0x3d, 0x25, 0x6c, 0x64, 0x3b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x70, 0x77, 0x72, 0x3d, 
+        0x25, 0x6c, 0x64, 0x3b, 0x0a, 0x00, 0x00, 0x00, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x25, 0x6c, 
+        0x6c, 0x64, 0x2c, 0x20, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 
+        0x73, 0x69, 0x67, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3d, 0x25, 0x6c, 0x6c, 0x64, 0x0a, 0x00, 
+        0x25, 0x6c, 0x64, 0x2c, 0x20, 0x25, 0x6c, 0x64, 0x2c, 0x20, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 
+        0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x64, 0x63, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3d, 0x25, 
+        0x6c, 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x25, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x6f, 0x74, 
+        0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3d, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x6e, 
+        0x6f, 0x69, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3d, 0x25, 0x6c, 0x6c, 0x64, 0x0a, 
+        0x00, 0x00, 0x00, 0x00, 0x70, 0x77, 0x72, 0x31, 0x3d, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x70, 
+        0x77, 0x72, 0x32, 0x3d, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x53, 0x4e, 0x52, 0x31, 0x3d, 0x25, 
+        0x64, 0x2c, 0x20, 0x00, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x6d, 0x61, 0x78, 0x5f, 0x64, 0x69, 0x76, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x5f, 
+        0x64, 0x69, 0x76, 0x33, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6c, 0x5f, 
+        0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x70, 0x77, 0x72, 0x31, 
+        0x3d, 0x25, 0x6c, 0x6c, 0x64, 0x2c, 0x20, 0x70, 0x77, 0x72, 0x32, 0x3d, 0x25, 0x6c, 0x6c, 0x64, 
+        0x2c, 0x20, 0x53, 0x4e, 0x52, 0x32, 0x3d, 0x25, 0x64, 0x2c, 0x20, 0x00, 0x46, 0x52, 0x45, 0x51, 
+        0x5f, 0x4f, 0x46, 0x46, 0x53, 0x45, 0x54, 0x3d, 0x25, 0x64, 0x6b, 0x48, 0x7a, 0x2c, 0x20, 0x0a, 
+        0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7c, 
+        0x00, 0x0c, 0x01, 0x00, 0x08, 0x01, 0x08, 0x0c, 0x08, 0x0d, 0x08, 0x0e, 0x08, 0x0f, 0x00, 0x00, 
+        0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x95, 0x10, 0x40, 0xaf, 0x04, 0x00, 0x00, 
+        0x0e, 0xf0, 0x01, 0x80, 0x13, 0x8c, 0x12, 0x8d, 0x11, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 
+        0x3c, 0x00, 0x00, 0x00, 0xe8, 0x99, 0x10, 0x40, 0x60, 0x04, 0x00, 0x00, 0x0e, 0xc0, 0x01, 0x80, 
+        0x12, 0x8c, 0x11, 0x8d, 0x10, 0x8e, 0x0f, 0x00, 0x98, 0x88, 0xfe, 0x3f, 0x38, 0xf3, 0xfe, 0x3f, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 
+        
+       };
+
+ // const static int eagle_fw1_size = 43680;
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/eagle_fw2.h b/drivers/net/wireless/rockchip_wlan/esp8089/eagle_fw2.h
new file mode 100755 (executable)
index 0000000..826d2f6
--- /dev/null
@@ -0,0 +1,4244 @@
+/* 
+ * Copyright (c) Espressif System
+
+ * Apr 13 2013 16:44:24 
+ */ 
+
+
+static u8 eagle_fw2[] =
+{ 
+        0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x40, 0x68, 0xf9, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x05, 0x45, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x00, 0x06, 0x00, 0x60, 0x0c, 0x0a, 0x31, 0xfe, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x63, 0xc1, 0x3c, 
+        0x89, 0xc0, 0x20, 0x00, 0x82, 0x23, 0xc0, 0x90, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x82, 0x63, 0xc0, 
+        0x7c, 0x97, 0x0c, 0x46, 0xc0, 0x20, 0x00, 0x52, 0x23, 0xc0, 0x70, 0x55, 0x10, 0x60, 0x55, 0x20, 
+        0xc0, 0x20, 0x00, 0x52, 0x63, 0xc0, 0x0c, 0x14, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xc0, 0x40, 0x22, 
+        0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xc0, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x05, 0xfb, 0xff, 0x06, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xef, 0x3f, 0xe0, 0x88, 0xfe, 0x3f, 
+        0xcc, 0x24, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x41, 0xfb, 0xff, 0xc0, 0x20, 0x00, 0x02, 
+        0x24, 0x97, 0xc0, 0x20, 0x00, 0x42, 0x24, 0x96, 0xdc, 0x50, 0x49, 0x11, 0x09, 0x21, 0x29, 0x31, 
+        0xcc, 0xd4, 0x21, 0xf6, 0xff, 0x01, 0xf6, 0xff, 0xc0, 0x00, 0x00, 0x28, 0x31, 0x08, 0x21, 0x48, 
+        0x11, 0x00, 0x50, 0x75, 0xdc, 0xc5, 0x02, 0x42, 0x04, 0x3c, 0x46, 0x7c, 0xe7, 0x1c, 0x88, 0x40, 
+        0x98, 0x75, 0x00, 0xa8, 0x41, 0xa2, 0x42, 0x03, 0x92, 0x42, 0x05, 0x82, 0x42, 0x00, 0x72, 0x42, 
+        0x01, 0x62, 0x42, 0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x80, 0xfe, 0x3f, 
+        0x28, 0x03, 0x00, 0x60, 0x00, 0x0a, 0x00, 0x60, 0xd0, 0x4c, 0x00, 0x40, 0x04, 0x4d, 0x00, 0x40, 
+        0xc0, 0x5d, 0x00, 0x40, 0xb8, 0x5d, 0x00, 0x40, 0x12, 0xc1, 0xe0, 0xe9, 0x41, 0xf9, 0x51, 0x39, 
+        0x01, 0x09, 0x11, 0xd9, 0x31, 0xc9, 0x21, 0xdd, 0x02, 0x20, 0xc0, 0x75, 0xb6, 0x8c, 0x06, 0x0c, 
+        0x10, 0x0c, 0x1c, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x1f, 0x9c, 0xfc, 0x26, 0x1c, 0x1f, 0xf6, 
+        0x4c, 0x02, 0xf6, 0x2c, 0x0e, 0x22, 0xcc, 0xfc, 0x16, 0x82, 0x14, 0x26, 0x5c, 0x05, 0x32, 0xcc, 
+        0xfa, 0x16, 0xf3, 0x13, 0x0c, 0x04, 0x49, 0x61, 0x0c, 0x02, 0xc6, 0x01, 0x00, 0x0c, 0x10, 0x0c, 
+        0x12, 0x0c, 0x05, 0x59, 0x61, 0xd0, 0xe0, 0x34, 0x00, 0x1e, 0x40, 0x00, 0xff, 0xa1, 0x9c, 0x62, 
+        0x4d, 0x0f, 0x0c, 0x05, 0x00, 0x20, 0xa1, 0x7c, 0xf3, 0x30, 0x30, 0x30, 0x00, 0x33, 0xa1, 0x01, 
+        0xe2, 0xff, 0xc0, 0x00, 0x00, 0x46, 0x03, 0x00, 0x0c, 0x02, 0x0c, 0x03, 0x0c, 0x04, 0x5d, 0x0f, 
+        0x01, 0xde, 0xff, 0xc0, 0x00, 0x00, 0x21, 0xaa, 0xff, 0xd0, 0x09, 0x54, 0xa2, 0xae, 0xcf, 0x2a, 
+        0x00, 0xc0, 0x20, 0x00, 0x92, 0x20, 0x80, 0xa0, 0x99, 0x10, 0xc0, 0x20, 0x00, 0x92, 0x60, 0x80, 
+        0x0c, 0x48, 0xd0, 0x74, 0x24, 0xd0, 0x64, 0x14, 0x80, 0x77, 0x10, 0xe0, 0x77, 0x11, 0x70, 0x66, 
+        0x20, 0xc0, 0x66, 0x11, 0xc0, 0x20, 0x00, 0x52, 0x20, 0x80, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 
+        0x48, 0x61, 0x52, 0x60, 0x80, 0xdc, 0x34, 0x42, 0xaf, 0x7f, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x80, 
+        0x40, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x60, 0x80, 0x46, 0x04, 0x00, 0x62, 0xa0, 0x80, 0xc0, 
+        0x20, 0x00, 0x52, 0x20, 0x80, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x60, 0x80, 0x21, 0xbf, 
+        0xff, 0xb6, 0x2c, 0x44, 0x26, 0x5c, 0x44, 0x41, 0xbe, 0xff, 0xe0, 0x3e, 0x11, 0x4a, 0x33, 0xc0, 
+        0x20, 0x00, 0x42, 0xac, 0x7f, 0x38, 0x03, 0x68, 0x01, 0x40, 0x33, 0x10, 0x42, 0xcc, 0xfe, 0x90, 
+        0x44, 0x11, 0x40, 0x33, 0x20, 0x26, 0x2c, 0x05, 0x52, 0xa4, 0x00, 0x50, 0x33, 0x20, 0x16, 0x96, 
+        0x06, 0x72, 0x12, 0x01, 0x09, 0x71, 0xf0, 0x77, 0x20, 0x72, 0x52, 0x01, 0x2d, 0x0e, 0x01, 0xb3, 
+        0xff, 0xc0, 0x00, 0x00, 0x08, 0x71, 0xc6, 0x02, 0x00, 0x66, 0x5c, 0x08, 0x82, 0x12, 0x03, 0x80, 
+        0x8f, 0x20, 0x82, 0x52, 0x03, 0xa2, 0xaf, 0xbf, 0xc0, 0x20, 0x00, 0x92, 0x20, 0x80, 0xa0, 0x99, 
+        0x10, 0xc0, 0x20, 0x00, 0x92, 0x60, 0x80, 0xdc, 0xac, 0x2d, 0x0e, 0x01, 0xa9, 0xff, 0xc0, 0x00, 
+        0x00, 0xd0, 0x27, 0x14, 0x01, 0xa8, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x0b, 0xc1, 0xa2, 0xff, 0xc0, 
+        0x20, 0x00, 0xb2, 0x6c, 0x6d, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0x0c, 0x1e, 0xe9, 0x61, 0x06, 0xaf, 0xff, 0x42, 0x12, 0x00, 0x26, 0x2c, 
+        0x0a, 0x40, 0x4f, 0x20, 0x42, 0x52, 0x00, 0x09, 0x71, 0xc6, 0xe3, 0xff, 0x7c, 0xf5, 0x62, 0x12, 
+        0x03, 0x50, 0x5f, 0x30, 0x40, 0x45, 0x10, 0x60, 0x55, 0x10, 0x52, 0x52, 0x03, 0xc6, 0xf8, 0xff, 
+        0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0xc1, 0x8d, 0xff, 0x52, 0xaf, 0xff, 0x62, 0x1c, 0x04, 0x09, 
+        0x01, 0x50, 0x06, 0x30, 0x00, 0x02, 0x10, 0x00, 0x00, 0xf4, 0x16, 0x30, 0x06, 0x22, 0x1c, 0x01, 
+        0x09, 0x21, 0x07, 0x02, 0x0f, 0x05, 0xe7, 0x06, 0x05, 0xda, 0xff, 0x08, 0x21, 0x7c, 0xf5, 0x22, 
+        0x1c, 0x01, 0x62, 0x1c, 0x04, 0x50, 0x82, 0x30, 0x72, 0x1c, 0x02, 0x80, 0x80, 0x10, 0x70, 0x78, 
+        0x20, 0x60, 0x88, 0x20, 0x82, 0x5c, 0x04, 0x70, 0x60, 0xf4, 0x62, 0x5c, 0x02, 0x71, 0x7d, 0xff, 
+        0xc0, 0x20, 0x00, 0x32, 0x1c, 0x00, 0x02, 0x1c, 0x03, 0x22, 0x27, 0x69, 0x00, 0x40, 0x11, 0x40, 
+        0x00, 0x20, 0x50, 0x40, 0x30, 0x40, 0x42, 0x10, 0x47, 0x83, 0x15, 0x20, 0x90, 0x10, 0x90, 0x96, 
+        0x20, 0xc0, 0x20, 0x00, 0x92, 0x67, 0x69, 0x0c, 0xa2, 0x45, 0x43, 0x0a, 0x0c, 0x0a, 0xa2, 0x5c, 
+        0x02, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0xcc, 0x4d, 0x00, 0x40, 
+        0x12, 0xc1, 0xf0, 0x09, 0x21, 0x71, 0x6b, 0xff, 0xc0, 0x20, 0x00, 0x0c, 0x05, 0x72, 0x27, 0x68, 
+        0x79, 0x01, 0x70, 0x60, 0xf5, 0x70, 0x30, 0xf5, 0x39, 0x11, 0x4d, 0x03, 0x70, 0x66, 0x10, 0x60, 
+        0x60, 0xf4, 0x2d, 0x06, 0x60, 0x33, 0x30, 0x01, 0x64, 0xff, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x38, 
+        0x11, 0x7c, 0xf0, 0x00, 0x33, 0x30, 0x30, 0x22, 0x10, 0x20, 0x20, 0xf4, 0x9c, 0x32, 0x51, 0x5b, 
+        0xff, 0x42, 0x15, 0x04, 0x00, 0x62, 0x30, 0x60, 0x44, 0x10, 0x42, 0x55, 0x04, 0x01, 0xeb, 0xff, 
+        0xc0, 0x00, 0x00, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0xb0, 0xbc, 0xff, 0x3f, 
+        0x50, 0xcc, 0x10, 0x40, 0xec, 0x88, 0xfe, 0x3f, 0xb8, 0x1c, 0x00, 0x40, 0x68, 0x2e, 0x00, 0x40, 
+        0x88, 0x0f, 0x00, 0x40, 0xa8, 0x0f, 0x00, 0x40, 0x48, 0x1d, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc2, 
+        0x61, 0x03, 0x02, 0x61, 0x02, 0x20, 0xc2, 0x20, 0xc5, 0x4f, 0x0c, 0x01, 0xf7, 0xff, 0xc0, 0x00, 
+        0x00, 0x2d, 0x0c, 0x05, 0x80, 0x03, 0x01, 0xf5, 0xff, 0xc0, 0x00, 0x00, 0x85, 0x9a, 0x01, 0x45, 
+        0xc3, 0x09, 0x02, 0x0c, 0x33, 0x66, 0x20, 0x02, 0x45, 0xbe, 0x08, 0x22, 0x0c, 0x39, 0x66, 0x12, 
+        0x02, 0x85, 0xbe, 0x08, 0x2d, 0x01, 0xc5, 0xc9, 0xff, 0x21, 0xe8, 0xff, 0x45, 0x4f, 0x0d, 0x45, 
+        0x68, 0x05, 0x05, 0x7e, 0x0c, 0x0c, 0x02, 0x31, 0xe6, 0xff, 0x0c, 0x04, 0x01, 0xe9, 0xff, 0xc0, 
+        0x00, 0x00, 0x0c, 0x12, 0x01, 0xe8, 0xff, 0xc0, 0x00, 0x00, 0x85, 0x52, 0x00, 0x45, 0xe9, 0x07, 
+        0xc5, 0x94, 0x01, 0x2d, 0x01, 0xc5, 0x99, 0x00, 0x21, 0xdf, 0xff, 0x01, 0x19, 0xff, 0xc0, 0x00, 
+        0x00, 0x01, 0xe1, 0xff, 0xc0, 0x00, 0x00, 0xc8, 0x31, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x20, 0x89, 0xfe, 0x3f, 0x28, 0x89, 0xfe, 0x3f, 0x38, 0x89, 0xfe, 0x3f, 0xf8, 0x88, 0xfe, 0x3f, 
+        0x04, 0x89, 0xfe, 0x3f, 0x90, 0x02, 0x10, 0x40, 0x00, 0x00, 0x06, 0x00, 0x00, 0xde, 0xff, 0x3f, 
+        0x00, 0xe1, 0xff, 0x3f, 0x00, 0x02, 0x00, 0x60, 0x10, 0x89, 0xfe, 0x3f, 0x50, 0x4c, 0x00, 0x40, 
+        0x28, 0x4e, 0x00, 0x40, 0xc4, 0x56, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 
+        0x00, 0x85, 0x0b, 0x00, 0x21, 0xef, 0xff, 0x31, 0xef, 0xff, 0x01, 0x01, 0xff, 0xc0, 0x00, 0x00, 
+        0x21, 0xee, 0xff, 0x31, 0xee, 0xff, 0x41, 0xee, 0xff, 0x01, 0xfd, 0xfe, 0xc0, 0x00, 0x00, 0x45, 
+        0x41, 0x00, 0x01, 0xf2, 0xff, 0xc0, 0x00, 0x00, 0x21, 0xeb, 0xff, 0x32, 0xa0, 0x00, 0x01, 0xf0, 
+        0xff, 0xc0, 0x00, 0x00, 0xc1, 0x10, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x2c, 0x66, 0xac, 0x1c, 0xc0, 
+        0x20, 0xf4, 0x8c, 0xb2, 0x0c, 0x03, 0x05, 0xc4, 0xff, 0x21, 0x08, 0xff, 0x0c, 0x10, 0x02, 0x42, 
+        0x0a, 0xc0, 0x00, 0xf5, 0x16, 0xa0, 0x00, 0x21, 0xe0, 0xff, 0x0c, 0x13, 0x20, 0x20, 0x20, 0x85, 
+        0xc2, 0xff, 0x01, 0xe4, 0xff, 0xc0, 0x00, 0x00, 0x22, 0xa2, 0x0c, 0x45, 0x50, 0x00, 0xc5, 0x09, 
+        0x00, 0xc5, 0xa5, 0x00, 0x01, 0xda, 0xff, 0x21, 0xdb, 0xff, 0x02, 0x20, 0xfe, 0x41, 0xd8, 0xff, 
+        0x66, 0x20, 0x0b, 0x32, 0x14, 0x7e, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x42, 0xc6, 0x02, 0x00, 0x66, 
+        0x30, 0x08, 0x52, 0x14, 0x7e, 0xc0, 0x20, 0x00, 0x52, 0x62, 0x41, 0x21, 0xd3, 0xff, 0x01, 0xdc, 
+        0xfe, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x98, 0xbe, 0xff, 0x3f, 0xf0, 0x8e, 0xfe, 0x3f, 0x44, 0x89, 0xfe, 0x3f, 0x41, 0xfd, 0xff, 0x12, 
+        0xc1, 0xf0, 0x31, 0xfc, 0xff, 0x09, 0x01, 0x47, 0xb3, 0x0b, 0x0c, 0x06, 0x0d, 0x03, 0x62, 0x40, 
+        0x00, 0x1b, 0x00, 0x47, 0x90, 0xf7, 0x21, 0xf8, 0xff, 0x01, 0xcd, 0xfe, 0xc0, 0x00, 0x00, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0xf0, 0x8e, 0xfe, 0x3f, 0x00, 0x00, 0x08, 0x00, 
+        0x54, 0x06, 0x10, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x5c, 0x89, 0xfe, 0x3f, 
+        0xf9, 0x84, 0x2e, 0x00, 0xf9, 0x84, 0x2a, 0x00, 0xa8, 0x58, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x11, 0x09, 0x01, 0x01, 0xfd, 0xff, 0xc0, 0x00, 0x00, 0x41, 0xf3, 0xff, 0x38, 0xc2, 0x39, 0x04, 
+        0xc1, 0xd5, 0xfe, 0x21, 0xf2, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x57, 0x20, 0x00, 0x20, 0xc0, 
+        0x20, 0x00, 0x0c, 0x12, 0x31, 0xef, 0xff, 0x0c, 0x04, 0x02, 0x6c, 0x57, 0x01, 0x7d, 0xff, 0xc0, 
+        0x00, 0x00, 0x51, 0xca, 0xfe, 0x41, 0xa6, 0xff, 0x52, 0x05, 0x0a, 0x01, 0xa4, 0xff, 0x16, 0x25, 
+        0x06, 0x02, 0x20, 0xfe, 0x31, 0xa4, 0xff, 0x66, 0x20, 0x0b, 0x22, 0x14, 0x7e, 0xc0, 0x20, 0x00, 
+        0x22, 0x63, 0x42, 0xc6, 0x02, 0x00, 0x66, 0x30, 0x08, 0x52, 0x14, 0x7e, 0xc0, 0x20, 0x00, 0x52, 
+        0x63, 0x41, 0x71, 0xe0, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x2c, 0x6c, 0x70, 0xaa, 0x20, 0xc0, 0x20, 
+        0x00, 0xa2, 0x6c, 0x6c, 0x91, 0xdd, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x2c, 0x44, 0x90, 0x88, 0x20, 
+        0xc0, 0x20, 0x00, 0x82, 0x6c, 0x44, 0xc0, 0x20, 0x00, 0x62, 0x2c, 0x6d, 0x70, 0x66, 0x20, 0xc0, 
+        0x20, 0x00, 0x62, 0x6c, 0x6d, 0x21, 0xd5, 0xff, 0x01, 0x9a, 0xfe, 0xc0, 0x00, 0x00, 0x01, 0xd4, 
+        0xff, 0x86, 0x00, 0x00, 0x01, 0xd4, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x6c, 0x43, 0xc0, 0x20, 0x00, 
+        0xb2, 0x2c, 0x43, 0x0c, 0x22, 0x01, 0x5b, 0xff, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xf9, 0x04, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 
+        0xff, 0xff, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x02, 0x64, 0x89, 0xfe, 0x3f, 0x6c, 0x89, 0xfe, 0x3f, 
+        0xf0, 0x4c, 0x00, 0x40, 0x0c, 0x07, 0x12, 0xc1, 0xe0, 0xc9, 0x11, 0x09, 0x01, 0xe9, 0x31, 0xd9, 
+        0x21, 0xf9, 0x41, 0x79, 0x51, 0xf1, 0xbb, 0xff, 0xd1, 0x9b, 0xfe, 0xe1, 0xf2, 0xff, 0xc0, 0x20, 
+        0x00, 0xc2, 0x2d, 0x42, 0x16, 0xdc, 0x1a, 0x27, 0x7c, 0x4d, 0x01, 0x70, 0xff, 0x02, 0x20, 0xfe, 
+        0x66, 0x20, 0x11, 0x31, 0x6f, 0xff, 0x32, 0x13, 0x7e, 0xc0, 0x20, 0x00, 0x41, 0x6e, 0xff, 0x32, 
+        0x64, 0x42, 0x46, 0x04, 0x00, 0x66, 0x30, 0x0e, 0x41, 0x6a, 0xff, 0x42, 0x14, 0x7e, 0xc0, 0x20, 
+        0x00, 0x51, 0x68, 0xff, 0x42, 0x65, 0x41, 0xc0, 0x20, 0x00, 0x72, 0x2d, 0x6c, 0xf0, 0x77, 0x20, 
+        0xc0, 0x20, 0x00, 0x72, 0x6d, 0x6c, 0xc0, 0x20, 0x00, 0x61, 0xa7, 0xff, 0x52, 0x2d, 0x44, 0x60, 
+        0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x6d, 0x44, 0x17, 0x7c, 0x14, 0xc0, 0x20, 0x00, 0x21, 0x9e, 
+        0xff, 0x31, 0xd9, 0xff, 0x28, 0x02, 0x32, 0x6d, 0x44, 0x08, 0x52, 0x28, 0x82, 0xc0, 0x00, 0x00, 
+        0xf7, 0x6c, 0x22, 0xc0, 0x20, 0x00, 0x41, 0xd5, 0xff, 0x42, 0x6d, 0x44, 0xc0, 0x20, 0x00, 0x32, 
+        0x2d, 0x53, 0x38, 0x23, 0x8c, 0xa3, 0x21, 0x94, 0xff, 0x28, 0x02, 0x08, 0x62, 0x28, 0x82, 0xc0, 
+        0x00, 0x00, 0x0c, 0x13, 0x39, 0x51, 0x07, 0x7c, 0x20, 0xc0, 0x20, 0x00, 0x51, 0xcd, 0xff, 0x62, 
+        0x2d, 0x43, 0x50, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 0x6d, 0x43, 0xc0, 0x20, 0x00, 0x42, 0x2d, 
+        0x44, 0x50, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x6d, 0x44, 0xe7, 0x8c, 0x02, 0x46, 0xcf, 0xff, 
+        0xc0, 0x73, 0x05, 0x56, 0xc7, 0x0d, 0xc0, 0x85, 0x05, 0x56, 0x38, 0x10, 0xc0, 0x9a, 0x04, 0x56, 
+        0xf9, 0x10, 0x07, 0x6c, 0x10, 0xc0, 0x20, 0x00, 0x0c, 0x1b, 0xb2, 0x6d, 0x44, 0xc0, 0x20, 0x00, 
+        0xa1, 0xbd, 0xff, 0xa2, 0x6d, 0x6a, 0x37, 0x6c, 0x3c, 0xc0, 0x20, 0x00, 0x0c, 0x80, 0x02, 0x6d, 
+        0x44, 0x01, 0xbb, 0xff, 0xc0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x42, 0x2d, 0x69, 0x61, 0x57, 0xfe, 
+        0x7c, 0xf7, 0x82, 0x16, 0x03, 0x62, 0x16, 0x00, 0x00, 0x38, 0x11, 0x70, 0x78, 0x30, 0x80, 0x52, 
+        0x10, 0x50, 0x50, 0xf4, 0x70, 0x66, 0x10, 0x60, 0x44, 0x10, 0x50, 0x33, 0x20, 0x40, 0x33, 0x20, 
+        0xc0, 0x20, 0x00, 0x32, 0x6d, 0x69, 0x47, 0x6c, 0x12, 0xc0, 0x20, 0x00, 0x1c, 0x07, 0x72, 0x6d, 
+        0x44, 0xc0, 0x20, 0x00, 0x22, 0x2d, 0x66, 0x0c, 0x03, 0xc5, 0x93, 0xff, 0x57, 0x6c, 0x0b, 0xc0, 
+        0x20, 0x00, 0x82, 0xa0, 0x20, 0x82, 0x6d, 0x44, 0x45, 0xb6, 0xff, 0x67, 0x6c, 0x36, 0xc0, 0x20, 
+        0x00, 0x02, 0xa0, 0x40, 0x02, 0x6d, 0x44, 0xc0, 0x20, 0x00, 0xb1, 0x40, 0xfe, 0x92, 0x1b, 0x02, 
+        0xb2, 0x1b, 0x03, 0xa2, 0x2d, 0x69, 0x00, 0x0b, 0x11, 0x00, 0xbb, 0x20, 0xb0, 0xaa, 0x10, 0xa0, 
+        0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x6d, 0x69, 0x0c, 0xa2, 0x45, 0xf5, 0x09, 0x41, 0x37, 0xfe, 
+        0x0c, 0x03, 0x32, 0x54, 0x02, 0x77, 0x6c, 0x0d, 0xc0, 0x20, 0x00, 0x0c, 0x92, 0x52, 0xa0, 0x80, 
+        0x52, 0x6d, 0x44, 0xc5, 0xf3, 0x09, 0xc0, 0x20, 0x00, 0x72, 0x2d, 0x44, 0x0c, 0x16, 0x69, 0x51, 
+        0x86, 0x96, 0xff, 0x21, 0x8d, 0xff, 0x31, 0x8d, 0xff, 0x42, 0xa2, 0x4a, 0x01, 0x15, 0xfe, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0x82, 0x21, 0x05, 0x16, 0x58, 0x00, 0x22, 0xa0, 0x02, 0x85, 0xec, 
+        0x07, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x21, 0x82, 0xff, 0x31, 0x82, 0xff, 0x42, 0xa2, 0x51, 0x01, 0x09, 0xfe, 0xc0, 0x00, 0x00, 0x06, 
+        0xff, 0xff, 0x21, 0x7d, 0xff, 0x31, 0x7d, 0xff, 0x42, 0xa2, 0x58, 0x01, 0x05, 0xfe, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x66, 0x92, 0x0c, 0x0c, 0xd2, 0x45, 0x05, 
+        0x00, 0x0c, 0xa2, 0x05, 0x05, 0x00, 0xc6, 0x01, 0x00, 0x0c, 0xd0, 0x07, 0x12, 0x02, 0x45, 0x04, 
+        0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x64, 0x08, 0x10, 0x40, 0x78, 0x89, 0xfe, 0x3f, 
+        0x2c, 0x24, 0x00, 0x40, 0x21, 0xfd, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfd, 0xff, 0xc0, 
+        0x00, 0x00, 0x21, 0xfa, 0xff, 0x01, 0xf2, 0xfd, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x5f, 0x4c, 0x3f, 0x00, 0x40, 
+        0xcc, 0x2e, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 0x09, 0x01, 0xdd, 0x02, 0x01, 
+        0xfb, 0xff, 0xc0, 0x00, 0x00, 0x22, 0x02, 0x40, 0xc1, 0xf7, 0xff, 0x01, 0xf7, 0xff, 0x20, 0xcc, 
+        0xd1, 0x0a, 0xcc, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x87, 0xd9, 0x31, 0x77, 0x70, 0x19, 0xd1, 0x16, 
+        0xff, 0x0c, 0x12, 0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x48, 0x1d, 0x1b, 0x44, 0x49, 0x1d, 0xc0, 
+        0x20, 0x00, 0x32, 0x2c, 0x87, 0x77, 0xf3, 0xe8, 0xc0, 0x20, 0x00, 0x0c, 0x02, 0x08, 0x01, 0x58, 
+        0x31, 0xd8, 0x21, 0x52, 0x6c, 0x80, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0xff, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xe4, 0xff, 0xc0, 0x00, 0x00, 0x01, 
+        0xfc, 0xff, 0x72, 0x02, 0x40, 0x51, 0xdf, 0xff, 0x61, 0xe0, 0xff, 0x70, 0x55, 0xd1, 0x6a, 0x55, 
+        0xc0, 0x20, 0x00, 0x22, 0x25, 0x87, 0x27, 0x00, 0x08, 0xc0, 0x20, 0x00, 0x82, 0x25, 0x87, 0x07, 
+        0x88, 0xf6, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xfe, 0x3f, 
+        0x90, 0x93, 0xfe, 0x3f, 0x80, 0x61, 0x00, 0x00, 0x40, 0x4f, 0x00, 0x40, 0x94, 0x5e, 0x00, 0x40, 
+        0x51, 0xfd, 0xff, 0x0c, 0x07, 0x21, 0xf9, 0xff, 0x12, 0xc1, 0xe0, 0x32, 0xa1, 0x04, 0x6d, 0x03, 
+        0x09, 0x61, 0x48, 0x02, 0x02, 0xc1, 0x14, 0x22, 0xc2, 0x10, 0x32, 0x54, 0x02, 0x41, 0xf4, 0xff, 
+        0x32, 0xc1, 0x10, 0x09, 0x11, 0x39, 0x01, 0x32, 0xa4, 0x80, 0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 
+        0x28, 0x41, 0x38, 0x51, 0x42, 0xa0, 0x60, 0x01, 0xf1, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x61, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0xd4, 0x0f, 0x10, 0x40, 0x7c, 0xd2, 0x10, 0x40, 0xc8, 0xd3, 0x10, 0x40, 
+        0x34, 0x0a, 0x10, 0x40, 0x4c, 0x54, 0x00, 0x40, 0x5c, 0x54, 0x00, 0x40, 0x8c, 0x60, 0x00, 0x40, 
+        0x12, 0xc1, 0xf0, 0x29, 0x01, 0x09, 0x11, 0x01, 0xe4, 0xfe, 0xc0, 0x00, 0x00, 0x01, 0xdf, 0xff, 
+        0x29, 0x00, 0x21, 0xf4, 0xff, 0x01, 0xf7, 0xff, 0xc0, 0x00, 0x00, 0x31, 0xdc, 0xff, 0x41, 0xf2, 
+        0xff, 0x38, 0x03, 0x21, 0xf2, 0xff, 0x22, 0x63, 0x13, 0x42, 0x63, 0x12, 0x21, 0xf1, 0xff, 0x01, 
+        0xf2, 0xff, 0xc0, 0x00, 0x00, 0x51, 0xd5, 0xff, 0x58, 0x05, 0x48, 0x01, 0x42, 0x55, 0x03, 0x01, 
+        0xef, 0xff, 0xc0, 0x00, 0x00, 0x85, 0xf5, 0xff, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0xff, 0xff, 0xff, 0x00, 0xff, 0x0f, 0x00, 0xff, 0x00, 0x0a, 0xf2, 0x3f, 0xc0, 0x31, 0x00, 0x40, 
+        0xc0, 0x52, 0x00, 0x40, 0x30, 0x53, 0x20, 0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x01, 0xf2, 0x61, 0x04, 
+        0x09, 0x01, 0x31, 0xc6, 0xff, 0xe9, 0x31, 0xd9, 0x21, 0x59, 0x51, 0xdd, 0x02, 0xe8, 0x12, 0x38, 
+        0x03, 0x42, 0x0e, 0x02, 0x22, 0x0e, 0x03, 0x32, 0x13, 0x02, 0x80, 0x22, 0x11, 0x40, 0x22, 0x20, 
+        0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0xfd, 0x02, 0x28, 0x1d, 0x45, 0x7b, 0x04, 0x08, 0x51, 0xcd, 
+        0x02, 0xcc, 0xe2, 0x2d, 0x0d, 0xf0, 0x40, 0xf4, 0x3d, 0x00, 0x01, 0xed, 0xff, 0xc0, 0x00, 0x00, 
+        0x86, 0x51, 0x00, 0x02, 0x62, 0x01, 0xd2, 0x62, 0x00, 0x62, 0x2d, 0x01, 0xf2, 0x52, 0x04, 0xcb, 
+        0x66, 0x69, 0x1d, 0x22, 0xa0, 0xf0, 0x0c, 0x1f, 0x61, 0xe2, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x1d, 
+        0x01, 0x00, 0x55, 0x11, 0xc0, 0x20, 0x00, 0x72, 0x1d, 0x00, 0x70, 0x55, 0x20, 0x60, 0x55, 0x10, 
+        0x50, 0x5c, 0x41, 0x52, 0xc5, 0xf4, 0x50, 0x50, 0xb4, 0x61, 0xda, 0xff, 0x40, 0x55, 0x11, 0xc0, 
+        0x20, 0x00, 0x42, 0x1d, 0x01, 0x00, 0x44, 0x11, 0xc0, 0x20, 0x00, 0x72, 0x1d, 0x00, 0x70, 0x44, 
+        0x20, 0x60, 0x44, 0x10, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x5d, 0x00, 0x40, 0x40, 0xf5, 
+        0xc0, 0x20, 0x00, 0xb2, 0xa0, 0x8f, 0x2b, 0x3e, 0x98, 0x7c, 0x42, 0x5d, 0x01, 0x02, 0x03, 0x01, 
+        0x32, 0x03, 0x00, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x02, 0xc0, 0xf4, 0x02, 0x5c, 0x08, 0x82, 
+        0x09, 0x06, 0xa2, 0x0e, 0x05, 0xb0, 0x88, 0x10, 0xa0, 0xa0, 0x24, 0xc0, 0xaa, 0x11, 0xa0, 0x88, 
+        0x20, 0x82, 0x49, 0x06, 0x68, 0x7c, 0x72, 0x0e, 0x04, 0x52, 0x06, 0x04, 0x70, 0x70, 0x34, 0x20, 
+        0x55, 0x10, 0x70, 0x55, 0x20, 0x52, 0x46, 0x04, 0x41, 0xc0, 0xff, 0xb8, 0x7c, 0xc0, 0x20, 0x00, 
+        0x92, 0xa0, 0xfe, 0xa2, 0x0b, 0x0d, 0x42, 0x24, 0x80, 0x49, 0x4b, 0x32, 0x0e, 0x07, 0x32, 0x4b, 
+        0x0c, 0x02, 0x0e, 0x06, 0x20, 0xaa, 0x10, 0x00, 0x01, 0x34, 0x00, 0xaa, 0x20, 0xa2, 0x4b, 0x0d, 
+        0x78, 0x7c, 0x82, 0x0e, 0x06, 0x62, 0x07, 0x00, 0x80, 0x80, 0x04, 0x90, 0x66, 0x10, 0x80, 0x66, 
+        0x20, 0x62, 0x47, 0x00, 0x48, 0x7c, 0x52, 0xa0, 0xfd, 0x32, 0x04, 0x00, 0x22, 0x0e, 0x00, 0x50, 
+        0x33, 0x10, 0x20, 0x57, 0x04, 0x20, 0x24, 0x24, 0xf0, 0x55, 0x11, 0x50, 0x33, 0x20, 0x32, 0x44, 
+        0x00, 0x05, 0x9c, 0x0b, 0x29, 0x5c, 0x72, 0x0e, 0x06, 0x98, 0x7c, 0x70, 0x71, 0x41, 0x9c, 0x17, 
+        0x88, 0x09, 0x80, 0xa6, 0x41, 0x80, 0x80, 0x54, 0xf0, 0xaa, 0x20, 0xa0, 0xaa, 0x11, 0xa0, 0x88, 
+        0x20, 0x89, 0x09, 0xb2, 0x0e, 0x00, 0xb0, 0xb0, 0x34, 0x66, 0x2b, 0x17, 0xe8, 0x7c, 0xf8, 0x0e, 
+        0x01, 0x6a, 0xfe, 0xf0, 0xd0, 0x54, 0xf0, 0xf6, 0x41, 0x00, 0xff, 0x20, 0xa0, 0xff, 0x11, 0xf0, 
+        0xdd, 0x20, 0xd9, 0x0e, 0xc0, 0x2c, 0x20, 0x85, 0xed, 0x07, 0xc2, 0x21, 0x01, 0xd2, 0x21, 0x02, 
+        0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0xe8, 0x2a, 0x00, 0x40, 
+        0x08, 0x58, 0x00, 0x40, 0x32, 0xa0, 0x0c, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 
+        0xcd, 0x02, 0x08, 0x02, 0x28, 0x32, 0x29, 0x10, 0x01, 0xf9, 0xff, 0xc0, 0x00, 0x00, 0xa1, 0x88, 
+        0xff, 0x58, 0x0c, 0xb8, 0x1c, 0x58, 0x15, 0xc0, 0x20, 0x00, 0x82, 0x1b, 0x01, 0x00, 0x88, 0x11, 
+        0xc0, 0x20, 0x00, 0x7c, 0x04, 0x38, 0x7c, 0x2b, 0x75, 0xb2, 0x1b, 0x00, 0x62, 0x1c, 0x04, 0x91, 
+        0x4f, 0xff, 0x0b, 0x66, 0x98, 0x09, 0xb0, 0x88, 0x20, 0xa0, 0x88, 0x10, 0x92, 0x19, 0x03, 0x80, 
+        0x8c, 0x41, 0x90, 0x66, 0xd1, 0x8a, 0x66, 0x62, 0x47, 0x00, 0x60, 0x68, 0x41, 0x62, 0x47, 0x01, 
+        0x22, 0x05, 0x00, 0x32, 0x13, 0x00, 0x40, 0x22, 0x10, 0x30, 0x30, 0xb4, 0x47, 0x63, 0x21, 0x0c, 
+        0x20, 0x00, 0x62, 0x20, 0x62, 0x45, 0x00, 0x28, 0x0c, 0x38, 0x1c, 0x01, 0xe1, 0xff, 0xc0, 0x00, 
+        0x00, 0x2d, 0x0c, 0x0c, 0x73, 0x85, 0x6d, 0x04, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x0c, 0x10, 0x86, 0xf6, 0xff, 0x00, 0x00, 0x80, 0x51, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0x36, 0xff, 0x08, 0x00, 0x22, 0x00, 0x44, 0xdc, 0x42, 0x28, 0xe0, 0xdc, 0x02, 0x0c, 
+        0x02, 0x0c, 0x53, 0x01, 0xf9, 0xff, 0xc0, 0x00, 0x00, 0x3d, 0x02, 0x01, 0xd1, 0xff, 0xc0, 0x00, 
+        0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x41, 0x2d, 0xff, 0x48, 0x04, 0x0c, 0x12, 0x32, 
+        0x04, 0x44, 0x58, 0xe4, 0xcc, 0x73, 0xcc, 0x55, 0x78, 0x84, 0x0c, 0x06, 0x70, 0x26, 0x83, 0x20, 
+        0x20, 0x74, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x21, 0x29, 0x01, 0x39, 0x11, 0x0c, 0x42, 0x0c, 
+        0xf3, 0x01, 0xe9, 0xff, 0xc0, 0x00, 0x00, 0x3d, 0x02, 0x48, 0x01, 0x28, 0x12, 0x08, 0x11, 0x02, 
+        0x42, 0x0e, 0x42, 0x42, 0x0c, 0x00, 0x08, 0x41, 0x40, 0x48, 0x41, 0x42, 0x42, 0x0d, 0x02, 0x42, 
+        0x0f, 0x2d, 0x03, 0x01, 0xbb, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x22, 0xa0, 0x00, 0x32, 0xa0, 0x00, 0x42, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x05, 0x30, 
+        0x0c, 0x0c, 0x02, 0x0c, 0x13, 0xc5, 0xfa, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x0c, 0xb3, 0x12, 0xc1, 0xf0, 0x29, 0x01, 0x09, 0x11, 0x0c, 0x42, 0x01, 0xd3, 0xff, 0xc0, 0x00, 
+        0x00, 0x3d, 0x02, 0x28, 0x12, 0x08, 0x01, 0x02, 0x42, 0x0c, 0x00, 0x08, 0x41, 0x02, 0x42, 0x0d, 
+        0x00, 0x08, 0x41, 0x02, 0x42, 0x0e, 0x00, 0x08, 0x41, 0x02, 0x42, 0x0f, 0x2d, 0x03, 0x01, 0xa4, 
+        0xff, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0xb4, 0x18, 0x00, 0x40, 
+        0x12, 0xc1, 0xf0, 0x09, 0x31, 0x29, 0x01, 0x39, 0x11, 0x2c, 0x42, 0x0c, 0xc3, 0x01, 0xc2, 0xff, 
+        0xc0, 0x00, 0x00, 0x38, 0x11, 0x29, 0x21, 0x48, 0x01, 0x28, 0x12, 0x40, 0x58, 0x41, 0x42, 0x42, 
+        0x0c, 0x52, 0x42, 0x0d, 0xe0, 0x44, 0x11, 0xeb, 0x22, 0x01, 0xf4, 0xff, 0xc0, 0x00, 0x00, 0x38, 
+        0x21, 0x2d, 0x03, 0x01, 0x93, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x31, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x08, 0x6b, 0x00, 0x40, 0x12, 0xc1, 0xe0, 0x29, 0x01, 0x09, 0x41, 0x01, 0xef, 0xfd, 0xc0, 0x00, 
+        0x00, 0x29, 0x11, 0x0c, 0x13, 0x1c, 0x02, 0x01, 0xb0, 0xff, 0xc0, 0x00, 0x00, 0x38, 0x01, 0x0c, 
+        0x25, 0x0c, 0x36, 0x29, 0x21, 0x78, 0x11, 0x28, 0x12, 0x82, 0x17, 0x02, 0x82, 0x42, 0x0c, 0xcb, 
+        0x42, 0x49, 0x31, 0x80, 0x98, 0x41, 0x0c, 0x64, 0x92, 0x42, 0x0d, 0x72, 0x17, 0x03, 0x62, 0x42, 
+        0x16, 0x72, 0x42, 0x14, 0x52, 0x42, 0x17, 0x70, 0x78, 0x41, 0x72, 0x42, 0x15, 0xeb, 0x22, 0x01, 
+        0xdb, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xea, 0xff, 0xc0, 0x00, 0x00, 0x08, 0xa2, 0xc0, 0x00, 0x00, 
+        0x2b, 0x22, 0x38, 0x31, 0x20, 0x22, 0x21, 0x22, 0x43, 0x0c, 0x20, 0x28, 0x41, 0x22, 0x43, 0x0d, 
+        0x38, 0x21, 0x2d, 0x03, 0x01, 0x73, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x10, 0xf5, 0xfe, 0x3f, 0x0c, 0x33, 0x12, 0xc1, 0xf0, 0x29, 0x01, 0x09, 
+        0x11, 0x0c, 0x42, 0x01, 0x91, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x14, 0x3d, 0x02, 0x08, 0x01, 0x28, 
+        0x12, 0x00, 0x04, 0x93, 0x02, 0x42, 0x0e, 0x00, 0x08, 0x41, 0x02, 0x42, 0x0f, 0x2d, 0x03, 0x01, 
+        0x64, 0xff, 0xc0, 0x00, 0x00, 0x61, 0xf3, 0xff, 0x0c, 0x05, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x52, 
+        0x46, 0x00, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x49, 0x21, 0x09, 0x41, 0x29, 0x01, 0x39, 0x11, 0x0c, 
+        0x82, 0x0c, 0xe3, 0x01, 0x81, 0xff, 0xc0, 0x00, 0x00, 0x38, 0x21, 0x0c, 0x64, 0x29, 0x31, 0x58, 
+        0x11, 0x28, 0x12, 0x68, 0x01, 0x62, 0x42, 0x0c, 0x52, 0x42, 0x0d, 0xeb, 0x22, 0x01, 0xb3, 0xff, 
+        0xc0, 0x00, 0x00, 0x38, 0x31, 0x2d, 0x03, 0x01, 0x52, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x41, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0x0c, 0x03, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0x85, 
+        0xc5, 0x0c, 0x2d, 0x0c, 0x0c, 0x03, 0x05, 0xc6, 0x0c, 0x2d, 0x0c, 0x05, 0x7b, 0x0c, 0x3d, 0x0c, 
+        0x0c, 0x12, 0x0c, 0x04, 0x85, 0x14, 0x0c, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x0c, 0x02, 0x1c, 0x13, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0x67, 0xff, 0xc0, 0x00, 0x00, 0x3d, 
+        0x02, 0x01, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x84, 0x89, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 0x20, 0xc2, 0x20, 
+        0x21, 0xfc, 0xff, 0x3d, 0x0c, 0x01, 0x5a, 0xfc, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x3d, 0x0c, 0x0c, 
+        0x04, 0xc5, 0x0f, 0x0c, 0x2d, 0x0c, 0xc5, 0xb5, 0x0c, 0xcc, 0x72, 0xc5, 0x83, 0x0c, 0x85, 0x6b, 
+        0x07, 0x45, 0x54, 0x06, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x0c, 0x02, 0x0c, 0x03, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0x4f, 0xff, 0xc0, 0x00, 0x00, 0x3d, 
+        0x02, 0x01, 0x27, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x11, 0x10, 0x10, 0x40, 0x80, 0x8a, 0xfe, 0x3f, 0x0c, 0x8a, 0xfe, 0x3f, 0x3c, 0x8a, 0xfe, 0x3f, 
+        0x68, 0x8a, 0xfe, 0x3f, 0x9c, 0x89, 0xfe, 0x3f, 0xbc, 0x1d, 0x10, 0x40, 0x90, 0x89, 0xfe, 0x3f, 
+        0x90, 0x8a, 0xfe, 0x3f, 0x88, 0x8a, 0xfe, 0x3f, 0x74, 0x8a, 0xfe, 0x3f, 0xfc, 0x89, 0xfe, 0x3f, 
+        0xb0, 0x89, 0xfe, 0x3f, 0xc0, 0x89, 0xfe, 0x3f, 0xd0, 0x89, 0xfe, 0x3f, 0x04, 0x8a, 0xfe, 0x3f, 
+        0x14, 0xf5, 0xfe, 0x3f, 0x00, 0x0d, 0x10, 0x40, 0xf4, 0x89, 0xfe, 0x3f, 0xdc, 0x89, 0xfe, 0x3f, 
+        0xe8, 0x89, 0xfe, 0x3f, 0x74, 0x0f, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0x9c, 0x26, 0x00, 0x40, 
+        0xdc, 0x26, 0x00, 0x40, 0xa4, 0x27, 0x00, 0x40, 0xac, 0x27, 0x00, 0x40, 0xb8, 0x27, 0x00, 0x40, 
+        0x78, 0x25, 0x00, 0x40, 0x44, 0x25, 0x00, 0x40, 0x40, 0x2d, 0x00, 0x40, 0x48, 0x2c, 0x00, 0x40, 
+        0xc4, 0x2c, 0x00, 0x40, 0x0c, 0x57, 0x0c, 0x14, 0x12, 0xc1, 0x80, 0x1c, 0x33, 0x88, 0x12, 0x02, 
+        0x61, 0x1b, 0x62, 0x08, 0x04, 0x92, 0x08, 0x05, 0x52, 0x08, 0x07, 0xa2, 0x08, 0x06, 0x80, 0x55, 
+        0x11, 0xa0, 0x55, 0x20, 0x80, 0x55, 0x11, 0x90, 0x55, 0x20, 0x80, 0x55, 0x11, 0x60, 0x55, 0x20, 
+        0x22, 0xc5, 0xf9, 0x37, 0xb2, 0x5e, 0x91, 0xd2, 0xff, 0x20, 0x62, 0x90, 0x9a, 0x66, 0xa0, 0x06, 
+        0x00, 0x46, 0x17, 0x00, 0x46, 0x13, 0x00, 0xc6, 0xeb, 0x00, 0x06, 0xd4, 0x00, 0x46, 0xc1, 0x00, 
+        0x46, 0x10, 0x00, 0xc6, 0x08, 0x00, 0xc6, 0xb1, 0x00, 0x86, 0xa9, 0x00, 0x46, 0xa1, 0x00, 0x86, 
+        0x9d, 0x00, 0xc6, 0x71, 0x00, 0xc6, 0x5c, 0x00, 0x06, 0x57, 0x00, 0x86, 0x09, 0x00, 0xc6, 0x49, 
+        0x00, 0xc6, 0x11, 0x00, 0x46, 0x07, 0x00, 0x86, 0x0c, 0x00, 0x22, 0x08, 0x0c, 0x32, 0x08, 0x0d, 
+        0x42, 0x08, 0x0e, 0x52, 0x08, 0x0f, 0x62, 0x08, 0x11, 0x72, 0x08, 0x10, 0x80, 0x66, 0x11, 0x70, 
+        0x66, 0x20, 0x05, 0x96, 0x04, 0x22, 0xa0, 0x80, 0x02, 0x21, 0x1b, 0x2a, 0x11, 0x0d, 0xf0, 0x00, 
+        0x00, 0x00, 0xcb, 0x28, 0x45, 0x32, 0xff, 0x86, 0xfa, 0xff, 0x00, 0x00, 0x00, 0x32, 0x08, 0x0c, 
+        0x21, 0xb5, 0xff, 0x01, 0xfb, 0xfb, 0xc0, 0x00, 0x00, 0x06, 0xf6, 0xff, 0x22, 0x08, 0x0c, 0x32, 
+        0xc8, 0x10, 0x42, 0x08, 0x0d, 0xcb, 0x98, 0x72, 0x08, 0x0e, 0x92, 0x61, 0x1a, 0x16, 0x77, 0x07, 
+        0x52, 0x08, 0x17, 0x62, 0x08, 0x16, 0x80, 0x55, 0x11, 0x60, 0x55, 0x20, 0x45, 0x27, 0x0b, 0x22, 
+        0x61, 0x13, 0x82, 0x21, 0x1a, 0x21, 0xa8, 0xff, 0x32, 0x08, 0x00, 0x42, 0x08, 0x01, 0x52, 0x08, 
+        0x04, 0x62, 0x08, 0x05, 0x72, 0x08, 0x06, 0xa2, 0x08, 0x07, 0xa9, 0x01, 0x92, 0x08, 0x08, 0x99, 
+        0x11, 0x82, 0x08, 0x09, 0x89, 0x21, 0x01, 0xe6, 0xfb, 0xc0, 0x00, 0x00, 0xb2, 0x21, 0x13, 0x16, 
+        0x8b, 0x06, 0x22, 0x21, 0x1a, 0x22, 0x02, 0x00, 0xc5, 0xa3, 0x0c, 0x29, 0xc1, 0x52, 0x21, 0x1a, 
+        0x22, 0x21, 0x13, 0x32, 0x05, 0x03, 0x42, 0x05, 0x0c, 0x52, 0x05, 0x0d, 0x85, 0xf5, 0x09, 0x01, 
+        0xa9, 0xff, 0xc0, 0x00, 0x00, 0x22, 0x21, 0x13, 0x0c, 0x03, 0x48, 0xc1, 0xc5, 0xfb, 0x09, 0x01, 
+        0xa6, 0xff, 0xc0, 0x00, 0x00, 0x86, 0x0c, 0x00, 0x45, 0x2e, 0x0b, 0x22, 0x21, 0x1a, 0x22, 0x02, 
+        0x00, 0x45, 0xf2, 0x07, 0x82, 0x21, 0x1a, 0x21, 0x8d, 0xff, 0x32, 0x08, 0x00, 0x42, 0x08, 0x04, 
+        0x52, 0x08, 0x05, 0x62, 0x08, 0x06, 0x72, 0x08, 0x07, 0x92, 0x08, 0x08, 0x92, 0x61, 0x00, 0x82, 
+        0x08, 0x09, 0x82, 0x61, 0x01, 0x01, 0xca, 0xfb, 0xc0, 0x00, 0x00, 0xc5, 0xe7, 0x07, 0x16, 0x32, 
+        0xf1, 0x05, 0x41, 0x0b, 0x22, 0x61, 0x12, 0x96, 0x12, 0x42, 0x05, 0x97, 0x0c, 0x16, 0xb2, 0x41, 
+        0x22, 0x21, 0x12, 0x45, 0x64, 0x06, 0xc6, 0xbe, 0xff, 0xcb, 0x08, 0x02, 0x61, 0x16, 0x02, 0x08, 
+        0x13, 0x32, 0x08, 0x0c, 0xb2, 0xc0, 0xfe, 0x56, 0xbb, 0x27, 0x21, 0x79, 0xff, 0x01, 0xbc, 0xfb, 
+        0xc0, 0x00, 0x00, 0x42, 0x21, 0x16, 0x22, 0x04, 0x00, 0x32, 0x04, 0x08, 0x42, 0x04, 0x09, 0xc5, 
+        0x92, 0x0c, 0xc6, 0xb3, 0xff, 0x00, 0x00, 0x00, 0xcb, 0x28, 0x32, 0xc1, 0x10, 0x85, 0x54, 0x00, 
+        0x32, 0xc1, 0x10, 0xc5, 0xbb, 0xff, 0xc6, 0xae, 0xff, 0x00, 0x00, 0x00, 0x21, 0x6e, 0xff, 0x32, 
+        0x08, 0x0f, 0x42, 0x08, 0x0e, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x42, 0x08, 0x0d, 0x80, 0x33, 
+        0x11, 0x40, 0x33, 0x20, 0x42, 0x08, 0x0c, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0xcb, 0x48, 0x49, 
+        0xf1, 0x01, 0xa7, 0xfb, 0xc0, 0x00, 0x00, 0x38, 0xf1, 0x22, 0x03, 0x03, 0x42, 0x03, 0x02, 0x80, 
+        0x22, 0x11, 0x40, 0x22, 0x20, 0x80, 0x22, 0x11, 0x42, 0x03, 0x01, 0x32, 0x03, 0x00, 0x40, 0x22, 
+        0x20, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x85, 0xb2, 0xff, 0xc6, 0x99, 0xff, 0xcb, 0x38, 0x0c, 
+        0x02, 0x32, 0x61, 0x10, 0x31, 0x59, 0xff, 0x01, 0x69, 0xff, 0xc0, 0x00, 0x00, 0x62, 0x21, 0x10, 
+        0x82, 0x06, 0x01, 0x72, 0x06, 0x0e, 0x32, 0x06, 0x02, 0x22, 0x06, 0x03, 0x42, 0x06, 0x0b, 0x52, 
+        0x06, 0x0f, 0x80, 0x44, 0x11, 0x80, 0x55, 0x11, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x70, 0x55, 
+        0x20, 0x80, 0x55, 0x11, 0x72, 0x06, 0x0a, 0x32, 0x06, 0x07, 0x80, 0x22, 0x11, 0x80, 0x22, 0x20, 
+        0x80, 0x22, 0x11, 0x80, 0x33, 0x11, 0x82, 0x06, 0x09, 0x70, 0x44, 0x20, 0x80, 0x44, 0x11, 0x72, 
+        0x06, 0x06, 0x80, 0x44, 0x20, 0x82, 0x06, 0x08, 0x70, 0x33, 0x20, 0x80, 0x44, 0x11, 0x72, 0x06, 
+        0x0d, 0x80, 0x33, 0x11, 0x70, 0x55, 0x20, 0x80, 0x44, 0x20, 0x72, 0x06, 0x05, 0x80, 0x55, 0x11, 
+        0x70, 0x33, 0x20, 0x72, 0x06, 0x0c, 0x80, 0x33, 0x11, 0x70, 0x55, 0x20, 0x72, 0x06, 0x04, 0x62, 
+        0x06, 0x00, 0x70, 0x33, 0x20, 0x60, 0x22, 0x20, 0x0c, 0x06, 0x01, 0x49, 0xff, 0xc0, 0x00, 0x00, 
+        0x0c, 0x02, 0x01, 0x48, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x01, 0x47, 0xff, 0xc0, 0x00, 0x00, 
+        0x01, 0x47, 0xff, 0xc0, 0x00, 0x00, 0xc6, 0x6e, 0xff, 0x21, 0x30, 0xff, 0x01, 0x71, 0xfb, 0xc0, 
+        0x00, 0x00, 0xc6, 0x6b, 0xff, 0x21, 0x2e, 0xff, 0x01, 0x42, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x02, 
+        0x0c, 0xa3, 0x01, 0x6d, 0xfe, 0xc0, 0x00, 0x00, 0x3d, 0x02, 0x01, 0x45, 0xfe, 0xc0, 0x00, 0x00, 
+        0x46, 0x64, 0xff, 0x21, 0x28, 0xff, 0x01, 0x3b, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x0c, 0x93, 
+        0x01, 0x66, 0xfe, 0xc0, 0x00, 0x00, 0x3d, 0x02, 0x01, 0x3e, 0xfe, 0xc0, 0x00, 0x00, 0xc6, 0x5c, 
+        0xff, 0x32, 0xc8, 0x0c, 0x02, 0x08, 0x0c, 0x32, 0x61, 0x15, 0x16, 0xc0, 0x2e, 0x42, 0xc0, 0xff, 
+        0x16, 0xf4, 0x30, 0x52, 0xc0, 0xfe, 0x16, 0xd5, 0x31, 0x62, 0xc0, 0xfd, 0x56, 0x56, 0xd5, 0x22, 
+        0x08, 0x0d, 0x32, 0xc8, 0x12, 0xc5, 0x1b, 0x0b, 0x42, 0x21, 0x15, 0x0c, 0x13, 0x42, 0x04, 0x02, 
+        0x85, 0x4a, 0x0a, 0x86, 0x4f, 0xff, 0x02, 0xc8, 0x0c, 0x22, 0x08, 0x13, 0x32, 0x08, 0x12, 0x80, 
+        0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x08, 0x18, 0x52, 0xc2, 0xfe, 0x56, 0x65, 0x0f, 0x02, 0x61, 
+        0x19, 0x42, 0x08, 0x17, 0x52, 0x08, 0x16, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 0x08, 0x15, 
+        0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 0x08, 0x14, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x16, 
+        0x24, 0x22, 0x22, 0xa0, 0x02, 0x00, 0x40, 0x20, 0x45, 0xca, 0x0b, 0xc6, 0x86, 0x00, 0xcb, 0x58, 
+        0x52, 0x61, 0x14, 0x05, 0x36, 0x0d, 0x32, 0x21, 0x14, 0x62, 0x12, 0x02, 0x22, 0x03, 0x01, 0x32, 
+        0x03, 0x00, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x20, 0x66, 0xc0, 0x16, 0x66, 0xcd, 0x32, 0xa0, 
+        0x80, 0x05, 0x58, 0x0c, 0x29, 0xe1, 0xc5, 0x33, 0x0d, 0x08, 0xe1, 0x31, 0xf8, 0xfb, 0x00, 0x00, 
+        0x90, 0x30, 0x00, 0xa0, 0x02, 0xc0, 0x28, 0x02, 0x61, 0x11, 0x07, 0x12, 0x07, 0x2d, 0x00, 0xc5, 
+        0x32, 0x0d, 0x02, 0x21, 0x11, 0x21, 0xf1, 0xfb, 0x22, 0x22, 0x37, 0x00, 0x22, 0xc0, 0x56, 0x72, 
+        0x16, 0x05, 0x1f, 0x07, 0x06, 0x59, 0x00, 0x00, 0x00, 0x00, 0x32, 0x08, 0x15, 0xcb, 0x68, 0x52, 
+        0x08, 0x16, 0x62, 0x61, 0x1c, 0x16, 0x85, 0x1e, 0x62, 0x08, 0x13, 0x16, 0xf6, 0x08, 0x0b, 0x76, 
+        0x16, 0x37, 0x1d, 0x82, 0xc6, 0xfe, 0x16, 0x28, 0x1d, 0xa2, 0xc6, 0xfd, 0x0c, 0x49, 0x0c, 0x00, 
+        0xa0, 0x09, 0x83, 0x86, 0x20, 0x00, 0xb2, 0xc0, 0xff, 0x56, 0x4b, 0x12, 0x21, 0xdf, 0xfe, 0x01, 
+        0x1c, 0xfb, 0xc0, 0x00, 0x00, 0x22, 0x21, 0x16, 0x1b, 0x32, 0x39, 0xd1, 0x22, 0x02, 0x00, 0xc5, 
+        0xb0, 0x0b, 0x52, 0x21, 0x16, 0x38, 0xd1, 0x22, 0x05, 0x00, 0x42, 0x05, 0x08, 0x52, 0x05, 0x09, 
+        0xc5, 0x5e, 0x0c, 0x66, 0x12, 0x02, 0x85, 0x34, 0x0c, 0x22, 0x21, 0x16, 0x22, 0x02, 0x00, 0x45, 
+        0xa7, 0xff, 0xc6, 0x0b, 0xff, 0x42, 0x61, 0x18, 0x52, 0xc2, 0xff, 0x56, 0x95, 0x0c, 0x22, 0xa0, 
+        0x02, 0x4d, 0x00, 0xc5, 0xbc, 0x0b, 0x21, 0xcd, 0xfe, 0x71, 0xcc, 0xfb, 0x0c, 0x56, 0x69, 0x17, 
+        0x01, 0x08, 0xfb, 0xc0, 0x00, 0x00, 0x01, 0xd3, 0xfe, 0xc0, 0x00, 0x00, 0x45, 0x27, 0x0d, 0x81, 
+        0xc7, 0xfb, 0x22, 0x68, 0x37, 0x01, 0xd0, 0xfe, 0xc0, 0x00, 0x00, 0x86, 0xfd, 0xfe, 0x92, 0x08, 
+        0x17, 0x92, 0xc9, 0xf3, 0x90, 0x47, 0x83, 0x0d, 0x04, 0x22, 0x21, 0x1c, 0x02, 0x61, 0x17, 0x22, 
+        0x02, 0x00, 0xb6, 0x63, 0x19, 0x3d, 0x00, 0x05, 0x68, 0x0c, 0x32, 0x21, 0x1c, 0x21, 0xbc, 0xfe, 
+        0x32, 0x03, 0x09, 0x01, 0xf7, 0xfa, 0xc0, 0x00, 0x00, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 
+        0x61, 0x17, 0x56, 0x36, 0x02, 0x00, 0x30, 0x20, 0xc5, 0x65, 0x0c, 0x22, 0x21, 0x1c, 0x32, 0x21, 
+        0x17, 0x22, 0x02, 0x00, 0x05, 0x66, 0x0c, 0x32, 0x21, 0x1c, 0x21, 0xb2, 0xfe, 0x32, 0x03, 0x08, 
+        0x01, 0xec, 0xfa, 0xc0, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x30, 0x20, 0x85, 0x64, 0x0c, 0x32, 
+        0x21, 0x1c, 0x21, 0xad, 0xfe, 0x32, 0x03, 0x09, 0x01, 0xe6, 0xfa, 0xc0, 0x00, 0x00, 0x72, 0x21, 
+        0x1c, 0x22, 0x21, 0x17, 0x1b, 0x57, 0x32, 0x07, 0x00, 0x42, 0x07, 0x08, 0x62, 0x07, 0x09, 0x82, 
+        0x07, 0x0b, 0x89, 0x01, 0xcb, 0x77, 0xc5, 0xfc, 0x0b, 0x32, 0x21, 0x1c, 0x22, 0x03, 0x00, 0x32, 
+        0x03, 0x07, 0x45, 0x0d, 0x0c, 0x06, 0xd7, 0xfe, 0x2d, 0x03, 0x85, 0x99, 0xff, 0x21, 0x9f, 0xfe, 
+        0x51, 0x9b, 0xfb, 0x42, 0x21, 0x18, 0x49, 0x15, 0x01, 0xd6, 0xfa, 0xc0, 0x00, 0x00, 0xc6, 0xd0, 
+        0xfe, 0x2d, 0x03, 0x05, 0x9d, 0xff, 0xc6, 0xce, 0xfe, 0x05, 0x05, 0x07, 0x72, 0x21, 0x14, 0x62, 
+        0x07, 0x03, 0x72, 0x07, 0x02, 0x80, 0x66, 0x11, 0x70, 0x66, 0x20, 0x16, 0x66, 0xb2, 0x22, 0xa0, 
+        0x01, 0x32, 0xa0, 0x01, 0xc5, 0x77, 0xff, 0x21, 0x92, 0xfe, 0x01, 0x9f, 0xfe, 0xc0, 0x00, 0x00, 
+        0x21, 0x90, 0xfe, 0x31, 0x90, 0xfe, 0x42, 0xa0, 0x00, 0x01, 0x9c, 0xfe, 0xc0, 0x00, 0x00, 0x42, 
+        0x21, 0x14, 0x21, 0x8b, 0xfe, 0x32, 0x04, 0x03, 0x42, 0x04, 0x02, 0x80, 0x33, 0x11, 0x40, 0x33, 
+        0x20, 0x0c, 0x04, 0x01, 0x97, 0xfe, 0xc0, 0x00, 0x00, 0x06, 0xba, 0xfe, 0xc5, 0x13, 0x06, 0x86, 
+        0xb8, 0xfe, 0x00, 0x00, 0x00, 0x2d, 0x03, 0xc5, 0x91, 0xff, 0x42, 0x21, 0x19, 0x21, 0x82, 0xfe, 
+        0x32, 0x04, 0x0b, 0x52, 0x04, 0x0a, 0x80, 0x33, 0x11, 0x50, 0x33, 0x20, 0x80, 0x33, 0x11, 0x52, 
+        0x04, 0x09, 0x42, 0x04, 0x08, 0x50, 0x33, 0x20, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x01, 0xb0, 
+        0xfa, 0xc0, 0x00, 0x00, 0x46, 0xab, 0xfe, 0x0c, 0x20, 0x06, 0xaf, 0xff, 0x0c, 0x30, 0xc6, 0xad, 
+        0xff, 0x2d, 0x03, 0x45, 0xfd, 0x0b, 0x32, 0x21, 0x1c, 0x32, 0x03, 0x09, 0xf6, 0x63, 0x0e, 0x21, 
+        0x73, 0xfe, 0x01, 0xa7, 0xfa, 0xc0, 0x00, 0x00, 0x46, 0xa2, 0xfe, 0x00, 0x00, 0x00, 0x21, 0x70, 
+        0xfe, 0x01, 0xa3, 0xfa, 0xc0, 0x00, 0x00, 0x86, 0x9e, 0xfe, 0x22, 0x08, 0x0d, 0x32, 0xc8, 0x12, 
+        0x42, 0x08, 0x0e, 0x52, 0x08, 0x11, 0x62, 0x08, 0x10, 0x80, 0x55, 0x11, 0x60, 0x55, 0x20, 0x62, 
+        0x08, 0x0f, 0x45, 0x0a, 0x0c, 0x22, 0x21, 0x15, 0x22, 0x02, 0x02, 0xc5, 0x07, 0x08, 0xc6, 0x94, 
+        0xfe, 0x00, 0x00, 0x22, 0x08, 0x0d, 0xc5, 0x0f, 0x0c, 0x22, 0x21, 0x15, 0x22, 0x02, 0x02, 0xc5, 
+        0x06, 0x08, 0xc6, 0x8f, 0xfe, 0x00, 0x00, 0x22, 0x08, 0x0d, 0x32, 0xc8, 0x12, 0x45, 0xea, 0x0a, 
+        0x42, 0x21, 0x15, 0x0c, 0x23, 0x42, 0x04, 0x02, 0x05, 0x19, 0x0a, 0x86, 0x89, 0xfe, 0x00, 0x00, 
+        0x0c, 0x80, 0xfe, 0x3f, 0x31, 0xff, 0xff, 0x29, 0x03, 0x0d, 0xf0, 0x00, 0x21, 0xfd, 0xff, 0x28, 
+        0x02, 0x0d, 0xf0, 0x00, 0x21, 0xfb, 0xff, 0x28, 0x12, 0x0d, 0xf0, 0x00, 0x31, 0xf9, 0xff, 0x0c, 
+        0x02, 0x29, 0x13, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x21, 0xf6, 0xff, 0x28, 0x22, 0x0d, 0xf0, 0x00, 
+        0xff, 0xff, 0xff, 0x2f, 0xff, 0xff, 0xff, 0x6f, 0x31, 0xfe, 0xff, 0x41, 0xfe, 0xff, 0x27, 0xb3, 
+        0x06, 0x27, 0x34, 0x03, 0x0c, 0x12, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x29, 0x17, 0x10, 0x40, 
+        0x64, 0x8b, 0xfe, 0x3f, 0x2c, 0x8b, 0xfe, 0x3f, 0x00, 0x96, 0x00, 0x60, 0x00, 0x9a, 0x00, 0x60, 
+        0xff, 0xff, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x00, 0x64, 0x00, 
+        0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x8b, 0xfe, 0x3f, 0xd4, 0x8a, 0xfe, 0x3f, 
+        0xc4, 0x8a, 0xfe, 0x3f, 0xb0, 0x8a, 0xfe, 0x3f, 0x9c, 0x8a, 0xfe, 0x3f, 0x68, 0x8b, 0xfe, 0x3f, 
+        0xea, 0x00, 0xc0, 0xed, 0x00, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x8b, 0xfe, 0x3f, 
+        0x44, 0x8b, 0xfe, 0x3f, 0xf0, 0x8a, 0xfe, 0x3f, 0x61, 0xd6, 0xff, 0x0c, 0xf4, 0x12, 0xc1, 0xf0, 
+        0x09, 0x01, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x02, 0xcd, 0x03, 0x02, 0x02, 0x03, 0x32, 0x02, 0x02, 
+        0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 0x02, 0x01, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 
+        0x02, 0x00, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 0xa1, 0x01, 0x47, 0xb0, 0x37, 0x51, 0xdb, 
+        0xff, 0x00, 0x40, 0x90, 0x5a, 0x44, 0xa0, 0x04, 0x00, 0x06, 0x12, 0x00, 0x86, 0x0a, 0x01, 0x86, 
+        0xf3, 0x00, 0x86, 0xdd, 0x00, 0x06, 0xca, 0x00, 0x86, 0xbb, 0x00, 0x46, 0x97, 0x00, 0xc6, 0x82, 
+        0x00, 0x86, 0x6e, 0x00, 0x46, 0x51, 0x00, 0xc6, 0x4d, 0x00, 0xc6, 0x49, 0x00, 0x86, 0x45, 0x00, 
+        0x46, 0x25, 0x00, 0x86, 0x1a, 0x00, 0x0c, 0x02, 0x29, 0x0c, 0x06, 0x03, 0x00, 0x62, 0xa1, 0x01, 
+        0x60, 0x60, 0xc0, 0x16, 0x46, 0x50, 0x09, 0x0c, 0x0c, 0x12, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x22, 0x02, 0x0b, 0x32, 0x0d, 0x0a, 0x80, 0x22, 0x11, 0x30, 0x22, 
+        0x20, 0x32, 0x0d, 0x09, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x08, 0x80, 0x22, 0x11, 
+        0x30, 0x22, 0x20, 0x45, 0xee, 0xff, 0x16, 0xe2, 0xfc, 0x32, 0x0d, 0x0b, 0x42, 0x0d, 0x0a, 0x80, 
+        0x33, 0x11, 0x40, 0x33, 0x20, 0x42, 0x0d, 0x09, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x42, 0x0d, 
+        0x08, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x38, 0x03, 0x39, 0x0c, 0x86, 0xe9, 
+        0xff, 0x42, 0x02, 0x0b, 0x52, 0x02, 0x0a, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 0x02, 0x09, 
+        0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 0x02, 0x08, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0xc0, 
+        0x20, 0x00, 0x48, 0x04, 0x49, 0x0c, 0x86, 0xdf, 0xff, 0x85, 0x83, 0x0a, 0x02, 0x0d, 0x0b, 0x32, 
+        0x0d, 0x0a, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 0x0d, 0x09, 0x80, 0x00, 0x11, 0x30, 0x00, 
+        0x20, 0x32, 0x0d, 0x08, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x52, 0xc0, 0xff, 0x16, 0x65, 0x46, 
+        0x22, 0xc0, 0xfe, 0x16, 0xa2, 0x43, 0x42, 0x0d, 0x0f, 0x52, 0x0d, 0x0e, 0x80, 0x44, 0x11, 0x50, 
+        0x44, 0x20, 0x52, 0x0d, 0x0d, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 0x0d, 0x0c, 0x80, 0x44, 
+        0x11, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x60, 0x00, 0x42, 0xcd, 0x08, 0x32, 0x04, 0x03, 
+        0x52, 0x04, 0x02, 0x80, 0x33, 0x11, 0x50, 0x33, 0x20, 0x52, 0x04, 0x01, 0x80, 0x33, 0x11, 0x42, 
+        0x04, 0x00, 0x50, 0x33, 0x20, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x0c, 0x12, 
+        0x38, 0x03, 0x39, 0x0c, 0x86, 0xc0, 0xff, 0x2d, 0x0c, 0x85, 0x94, 0x0a, 0x20, 0x20, 0xf4, 0xc6, 
+        0xbd, 0xff, 0x00, 0x00, 0x00, 0xc5, 0x7a, 0x0a, 0x3d, 0x0c, 0x85, 0x90, 0x0a, 0xc6, 0xfa, 0xff, 
+        0x00, 0x00, 0x2d, 0x0c, 0x85, 0x49, 0x05, 0x46, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x45, 0x79, 0x0a, 
+        0x52, 0xa0, 0x20, 0x02, 0x0d, 0x0b, 0x32, 0x0d, 0x0a, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 
+        0x0d, 0x09, 0x80, 0x00, 0x11, 0x30, 0x00, 0x20, 0x32, 0x0d, 0x08, 0x80, 0x00, 0x11, 0x30, 0x00, 
+        0x20, 0x07, 0xb5, 0x02, 0xc6, 0xdc, 0x00, 0x00, 0x30, 0x74, 0x05, 0x86, 0x0a, 0x22, 0x0d, 0x0b, 
+        0x32, 0x0d, 0x0a, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x09, 0x80, 0x22, 0x11, 0x30, 
+        0x22, 0x20, 0x32, 0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x85, 0x34, 0x05, 0x02, 0x0d, 
+        0x0b, 0x22, 0x0d, 0x0a, 0x80, 0x00, 0x11, 0x20, 0x00, 0x20, 0x22, 0x0d, 0x09, 0x80, 0x00, 0x11, 
+        0x20, 0x00, 0x20, 0x22, 0x0d, 0x08, 0x80, 0x00, 0x11, 0x20, 0x00, 0x20, 0x86, 0x99, 0xff, 0x02, 
+        0x02, 0x0b, 0x22, 0x02, 0x0a, 0x80, 0x00, 0x11, 0x20, 0x00, 0x20, 0x22, 0x0d, 0x09, 0x80, 0x00, 
+        0x11, 0x20, 0x00, 0x20, 0x22, 0x0d, 0x08, 0x80, 0x00, 0x11, 0x20, 0x00, 0x20, 0x42, 0xd0, 0xff, 
+        0x56, 0x54, 0x2c, 0x21, 0x5b, 0xff, 0x01, 0xd2, 0xf9, 0xc0, 0x00, 0x00, 0x02, 0x0d, 0x0b, 0x22, 
+        0x0d, 0x0a, 0x80, 0x00, 0x11, 0x20, 0x00, 0x20, 0x22, 0x0d, 0x09, 0x80, 0x00, 0x11, 0x20, 0x00, 
+        0x20, 0x22, 0x0d, 0x08, 0x80, 0x00, 0x11, 0x20, 0x00, 0x20, 0x06, 0x86, 0xff, 0x32, 0x02, 0x0b, 
+        0x42, 0x02, 0x0a, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x42, 0x02, 0x09, 0x80, 0x33, 0x11, 0x40, 
+        0x33, 0x20, 0x42, 0x02, 0x08, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x39, 0x26, 0x39, 0x0c, 0x22, 
+        0x02, 0x0b, 0x32, 0x0d, 0x0a, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x09, 0x80, 0x22, 
+        0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x16, 0x42, 0x2b, 
+        0x21, 0x41, 0xff, 0x01, 0xb7, 0xf9, 0xc0, 0x00, 0x00, 0xc6, 0x72, 0xff, 0x01, 0x40, 0xff, 0x42, 
+        0x02, 0x0b, 0x52, 0x02, 0x0a, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x52, 0x02, 0x09, 0x80, 0x44, 
+        0x11, 0x50, 0x44, 0x20, 0x80, 0x44, 0x11, 0x52, 0x02, 0x08, 0x21, 0x37, 0xff, 0x50, 0x44, 0x20, 
+        0x0b, 0x44, 0x56, 0x54, 0x23, 0x41, 0x36, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x54, 0x40, 0x33, 
+        0x10, 0xc0, 0x20, 0x00, 0x32, 0x60, 0x54, 0x0c, 0xac, 0xd1, 0x32, 0xff, 0xc0, 0x20, 0x00, 0xb2, 
+        0x20, 0xc6, 0xd0, 0xbb, 0x10, 0xc0, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x60, 0xc6, 0x91, 0x2f, 
+        0xff, 0xa1, 0x2d, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x22, 0xbb, 0xa0, 0x88, 0x10, 0x90, 0x88, 0x20, 
+        0xc0, 0x20, 0x00, 0x82, 0x62, 0xbb, 0x61, 0x2b, 0xff, 0x71, 0x29, 0xff, 0xc0, 0x20, 0x00, 0x52, 
+        0x22, 0xe2, 0x70, 0x55, 0x10, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x62, 0xe2, 0x21, 0x26, 
+        0xff, 0x01, 0x93, 0xf9, 0xc0, 0x00, 0x00, 0x46, 0x4f, 0xff, 0x22, 0x02, 0x0b, 0x32, 0x0d, 0x0a, 
+        0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x09, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 
+        0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0xb6, 0x22, 0x02, 0x46, 0x46, 0xff, 0x1b, 0x32, 
+        0x39, 0x16, 0x16, 0x92, 0x20, 0x21, 0x19, 0xff, 0x01, 0x86, 0xf9, 0xc0, 0x00, 0x00, 0x86, 0x41, 
+        0xff, 0x42, 0xa0, 0x0e, 0x22, 0x02, 0x0b, 0x32, 0x0d, 0x0a, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 
+        0x32, 0x0d, 0x09, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 
+        0x22, 0x20, 0x27, 0xb4, 0x02, 0xc6, 0x37, 0xff, 0x16, 0xc2, 0xcd, 0x32, 0xa0, 0x80, 0x05, 0xf0, 
+        0x0b, 0x32, 0xa0, 0x00, 0x29, 0x0c, 0x0c, 0x04, 0x20, 0x20, 0xf4, 0x85, 0x26, 0x00, 0x38, 0x0c, 
+        0x21, 0x08, 0xff, 0x01, 0x73, 0xf9, 0xc0, 0x00, 0x00, 0xc6, 0x2e, 0xff, 0x22, 0x02, 0x0b, 0x32, 
+        0x0d, 0x0a, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x09, 0x80, 0x22, 0x11, 0x30, 0x22, 
+        0x20, 0x32, 0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x2c, 0x03, 0x27, 0xb3, 0x02, 0x46, 
+        0x25, 0xff, 0x05, 0xb7, 0xff, 0x21, 0xfb, 0xfe, 0x32, 0x0d, 0x0b, 0x42, 0x0d, 0x0a, 0x80, 0x33, 
+        0x11, 0x40, 0x33, 0x20, 0x42, 0x0d, 0x09, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x42, 0x0d, 0x08, 
+        0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x39, 0x0c, 0x01, 0x5e, 0xf9, 0xc0, 0x00, 0x00, 0x86, 0x19, 
+        0xff, 0x22, 0x02, 0x0b, 0x32, 0x0d, 0x0a, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x09, 
+        0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0xb6, 
+        0x32, 0x02, 0x86, 0x10, 0xff, 0x20, 0x20, 0x74, 0xc5, 0x26, 0x00, 0x21, 0xe7, 0xfe, 0x32, 0x0d, 
+        0x0b, 0x42, 0x0d, 0x0a, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x42, 0x0d, 0x09, 0x80, 0x33, 0x11, 
+        0x40, 0x33, 0x20, 0x42, 0x0d, 0x08, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0x39, 0x0c, 0x01, 0x48, 
+        0xf9, 0xc0, 0x00, 0x00, 0x06, 0x04, 0xff, 0x00, 0x00, 0x00, 0x22, 0x02, 0x0b, 0x32, 0x0d, 0x0a, 
+        0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 0x0d, 0x09, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0x32, 
+        0x0d, 0x08, 0x80, 0x22, 0x11, 0x30, 0x22, 0x20, 0xc5, 0xaf, 0xff, 0x16, 0x92, 0xbe, 0x62, 0x0d, 
+        0x0a, 0x72, 0x0d, 0x0d, 0x42, 0x0d, 0x0f, 0x52, 0x0d, 0x0e, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 
+        0x80, 0x44, 0x11, 0x52, 0x0d, 0x0b, 0x70, 0x44, 0x20, 0x72, 0x0d, 0x0c, 0x80, 0x55, 0x11, 0x80, 
+        0x44, 0x11, 0x60, 0x55, 0x20, 0x62, 0x0d, 0x09, 0x80, 0x55, 0x11, 0x70, 0x44, 0x20, 0x60, 0x55, 
+        0x20, 0x62, 0x0d, 0x08, 0x80, 0x55, 0x11, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x49, 0x05, 0x8b, 
+        0x4d, 0x32, 0x04, 0x03, 0x52, 0x04, 0x02, 0x80, 0x33, 0x11, 0x50, 0x33, 0x20, 0x52, 0x04, 0x01, 
+        0x80, 0x33, 0x11, 0x42, 0x04, 0x00, 0x50, 0x33, 0x20, 0x80, 0x33, 0x11, 0x40, 0x33, 0x20, 0xc0, 
+        0x20, 0x00, 0x38, 0x03, 0x39, 0x0c, 0x86, 0xdf, 0xfe, 0x30, 0x50, 0xc0, 0x56, 0x65, 0xb7, 0x21, 
+        0xb7, 0xfe, 0x01, 0x1f, 0xf9, 0xc0, 0x00, 0x00, 0x06, 0x4c, 0xff, 0x91, 0xb5, 0xfe, 0xc0, 0x20, 
+        0x00, 0x92, 0x60, 0x54, 0x82, 0xa1, 0x90, 0xc0, 0x20, 0x00, 0x82, 0x60, 0xc6, 0x71, 0xb1, 0xfe, 
+        0xc0, 0x20, 0x00, 0x72, 0x62, 0xbb, 0x61, 0xb0, 0xfe, 0xc0, 0x20, 0x00, 0x62, 0x62, 0xe2, 0x21, 
+        0xaf, 0xfe, 0x01, 0x13, 0xf9, 0xc0, 0x00, 0x00, 0x06, 0xcf, 0xfe, 0x32, 0xa0, 0xf7, 0xa2, 0xd0, 
+        0xff, 0x56, 0x8a, 0xb2, 0xb2, 0x02, 0x14, 0x0c, 0x80, 0x30, 0xbb, 0x10, 0x00, 0xbb, 0x20, 0xb2, 
+        0x42, 0x14, 0x06, 0x26, 0xff, 0x21, 0xa6, 0xfe, 0x01, 0x0a, 0xf9, 0xc0, 0x00, 0x00, 0x86, 0xc5, 
+        0xfe, 0x2d, 0x0c, 0x05, 0x5f, 0x0a, 0x20, 0x20, 0xf4, 0x46, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x21, 
+        0xa1, 0xfe, 0x01, 0x03, 0xf9, 0xc0, 0x00, 0x00, 0x06, 0xbf, 0xfe, 0x02, 0x02, 0x14, 0x30, 0x00, 
+        0x10, 0x02, 0x42, 0x14, 0x86, 0x19, 0xff, 0x3d, 0x0c, 0x05, 0x58, 0x0a, 0x86, 0xf5, 0xff, 0x00, 
+        0x28, 0xf5, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfd, 0xff, 0x08, 0x00, 0x80, 0x42, 
+        0x01, 0x08, 0x00, 0x40, 0x28, 0x31, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xf6, 0xff, 0x08, 0x00, 0x08, 0x60, 0xc0, 0x00, 0x00, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 
+        0x03, 0x01, 0xef, 0xff, 0x80, 0x32, 0x01, 0x08, 0x00, 0x30, 0x28, 0x31, 0x08, 0x00, 0x3d, 0x0c, 
+        0xc0, 0x00, 0x00, 0x01, 0xeb, 0xff, 0x08, 0x00, 0x08, 0x60, 0x2d, 0x0c, 0xc0, 0x00, 0x00, 0xc8, 
+        0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x03, 0x12, 0xc1, 0xf0, 0x5d, 0x02, 0x09, 
+        0x01, 0x01, 0xe3, 0xff, 0x0c, 0x12, 0x59, 0x00, 0xc5, 0xfb, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xdd, 0xff, 0x08, 0x00, 0x08, 0x10, 
+        0xc0, 0x00, 0x00, 0x0c, 0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xd7, 0xff, 0x08, 0x00, 0x80, 0x32, 0x01, 0x08, 0x20, 0x30, 0x28, 0x31, 0xc0, 0x00, 
+        0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xd0, 0xff, 
+        0x08, 0x00, 0x08, 0x30, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xca, 0xff, 0x08, 0x00, 0x08, 0x40, 0xc0, 0x00, 0x00, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xc4, 0xff, 
+        0x08, 0x00, 0x08, 0x50, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xbe, 0xff, 0x08, 0x00, 0x08, 0x60, 0xc0, 0x00, 0x00, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xb8, 0xff, 
+        0x08, 0x00, 0x08, 0x70, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x21, 0x1e, 0xfb, 0xc0, 0x20, 0x00, 0x22, 0x22, 0x80, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0x02, 
+        0x61, 0x00, 0x05, 0x91, 0x0c, 0x22, 0x02, 0x06, 0x32, 0xa0, 0x01, 0xc5, 0xee, 0xff, 0x02, 0x21, 
+        0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x28, 0x02, 0x0d, 0xf0, 0x00, 
+        0xc0, 0x20, 0x00, 0x39, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x0e, 0x00, 0x60, 0x20, 0x53, 0xc0, 0x3b, 
+        0x45, 0x50, 0x45, 0xb3, 0x40, 0x42, 0x21, 0x1b, 0x34, 0xa6, 0x13, 0x17, 0x20, 0x63, 0xa0, 0x31, 
+        0xfa, 0xff, 0xc0, 0x20, 0x00, 0x78, 0x02, 0xc0, 0x20, 0x00, 0x72, 0x63, 0x80, 0x4b, 0x22, 0x4b, 
+        0x33, 0x67, 0x92, 0xed, 0x0d, 0xf0, 0x00, 0x00, 0x20, 0x63, 0xc0, 0x3b, 0x56, 0x60, 0x56, 0xb3, 
+        0x50, 0x52, 0x21, 0x1b, 0x55, 0xa6, 0x15, 0x1a, 0x61, 0xf0, 0xff, 0x31, 0xef, 0xff, 0x60, 0x65, 
+        0xa0, 0xc0, 0x20, 0x00, 0x72, 0x23, 0x80, 0xc0, 0x20, 0x00, 0x79, 0x02, 0x4b, 0x33, 0x4b, 0x22, 
+        0x67, 0x93, 0xed, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x30, 0xf5, 0xfe, 0x3f, 0x20, 0x73, 0x04, 0x20, 
+        0x61, 0x04, 0x20, 0x50, 0x04, 0x12, 0xc1, 0xe0, 0x09, 0x31, 0xc9, 0x41, 0x6a, 0x55, 0xc1, 0xfa, 
+        0xff, 0x20, 0x62, 0x04, 0x7a, 0x66, 0x20, 0x05, 0x04, 0x20, 0x76, 0x04, 0x7a, 0x00, 0x20, 0x74, 
+        0x04, 0x7a, 0x00, 0x6a, 0x00, 0x5a, 0x00, 0x30, 0x53, 0x24, 0x00, 0x20, 0x74, 0x0c, 0x40, 0xf6, 
+        0x52, 0x01, 0x0d, 0x02, 0x00, 0x20, 0x90, 0x1c, 0xd0, 0x50, 0x22, 0x90, 0x20, 0x20, 0x74, 0x27, 
+        0x30, 0x01, 0x0d, 0x02, 0x0c, 0x42, 0x00, 0x50, 0x74, 0x0c, 0x13, 0x08, 0x0c, 0x40, 0x45, 0xb0, 
+        0x68, 0x14, 0x02, 0x20, 0x2b, 0x48, 0x04, 0x60, 0x79, 0x84, 0x79, 0x11, 0x40, 0x50, 0x84, 0x60, 
+        0x60, 0x84, 0x69, 0x21, 0x59, 0x01, 0x40, 0x49, 0x84, 0xc0, 0x00, 0x00, 0x48, 0x11, 0x08, 0x0c, 
+        0x0c, 0x52, 0x02, 0x20, 0x2b, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0x48, 0x01, 0x08, 0x0c, 0x0c, 0x42, 
+        0x02, 0x20, 0x2b, 0x0c, 0x23, 0xc0, 0x00, 0x00, 0x48, 0x21, 0x08, 0x0c, 0x0c, 0x52, 0x02, 0x20, 
+        0x2b, 0x0c, 0x23, 0xc0, 0x00, 0x00, 0xc8, 0x41, 0x08, 0x31, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 
+        0x70, 0x8b, 0xfe, 0x3f, 0x20, 0x80, 0xfe, 0x3f, 0x14, 0x1d, 0x00, 0x40, 0x12, 0xc1, 0xc0, 0xc9, 
+        0x21, 0xd9, 0x31, 0xe9, 0x41, 0xf9, 0x51, 0x09, 0x11, 0x59, 0xa1, 0x79, 0x91, 0x29, 0x71, 0x49, 
+        0x81, 0x22, 0xa0, 0x7f, 0x80, 0x43, 0x01, 0x40, 0x48, 0x31, 0x40, 0x32, 0xa3, 0x39, 0x61, 0xe6, 
+        0x13, 0x02, 0x46, 0x40, 0x00, 0x0c, 0x0c, 0x0c, 0x00, 0x0c, 0x0f, 0x58, 0xa1, 0x0b, 0x76, 0xdd, 
+        0x05, 0x7a, 0x55, 0x59, 0xb1, 0x1c, 0x83, 0xa2, 0x0d, 0x00, 0xf0, 0x6c, 0xc0, 0x80, 0xe6, 0x01, 
+        0xe0, 0xe8, 0x31, 0x80, 0xaa, 0x01, 0xa0, 0xa8, 0x31, 0xa7, 0x2e, 0x3e, 0x80, 0x66, 0x01, 0x28, 
+        0xb1, 0x60, 0x68, 0x31, 0x27, 0xad, 0x33, 0xa0, 0x70, 0x74, 0xcc, 0xa7, 0x82, 0x0d, 0x01, 0x80, 
+        0x88, 0x01, 0x80, 0x88, 0x31, 0x87, 0x26, 0x22, 0xd8, 0xa1, 0x1b, 0x00, 0xa0, 0x20, 0x74, 0x2a, 
+        0xff, 0x00, 0x00, 0x74, 0x0a, 0xdd, 0xf0, 0x6c, 0xc0, 0x80, 0xe6, 0x01, 0xa2, 0x0d, 0x00, 0xe0, 
+        0xe8, 0x31, 0x80, 0xaa, 0x01, 0xa0, 0xa8, 0x31, 0xa7, 0xae, 0xc0, 0x09, 0xc1, 0x37, 0x2e, 0x0d, 
+        0x62, 0xce, 0xe8, 0x0c, 0xfe, 0x80, 0x66, 0x01, 0x60, 0x68, 0x31, 0x86, 0x09, 0x00, 0xe0, 0x2e, 
+        0x20, 0x32, 0xa0, 0x06, 0x05, 0x7c, 0x0d, 0x0d, 0x02, 0x0c, 0x63, 0x2d, 0x0e, 0x00, 0x10, 0x40, 
+        0x0c, 0x1e, 0x00, 0xee, 0xa1, 0x0b, 0xee, 0xe0, 0xe0, 0xf4, 0x45, 0x81, 0x0d, 0x08, 0xc1, 0x80, 
+        0x62, 0x01, 0x60, 0x68, 0x31, 0xa6, 0x56, 0x04, 0x0c, 0x56, 0x86, 0x00, 0x00, 0x60, 0x60, 0xf4, 
+        0x09, 0xc1, 0x69, 0x01, 0x78, 0x91, 0x98, 0x81, 0x88, 0x71, 0x90, 0x90, 0x90, 0x42, 0x19, 0x00, 
+        0x80, 0x8c, 0x90, 0x40, 0x4e, 0xb0, 0x4a, 0x46, 0x40, 0x40, 0xf4, 0x42, 0x58, 0x00, 0x9c, 0x47, 
+        0x52, 0x19, 0x00, 0x21, 0xbf, 0xff, 0x3d, 0x0c, 0x6d, 0x0e, 0x78, 0x01, 0x01, 0xbf, 0xff, 0xc0, 
+        0x00, 0x00, 0x08, 0xc1, 0x68, 0x01, 0x0c, 0xfa, 0xa7, 0x9e, 0x0b, 0x66, 0x56, 0x08, 0xb1, 0xb9, 
+        0xff, 0xc2, 0x4b, 0x00, 0xc6, 0x03, 0x00, 0xe8, 0x61, 0x1b, 0xcc, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 
+        0x31, 0xe0, 0xec, 0xc0, 0x56, 0xde, 0xf0, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 
+        0x11, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 
+        0x02, 0x1c, 0x70, 0x27, 0x20, 0x1d, 0x1c, 0x12, 0xc7, 0x22, 0x12, 0xe6, 0xac, 0x09, 0x4c, 0x00, 
+        0xe6, 0x6c, 0x13, 0x0c, 0x00, 0x86, 0x03, 0x00, 0x02, 0xa0, 0x60, 0x06, 0x02, 0x00, 0x02, 0xa0, 
+        0x70, 0x86, 0x00, 0x00, 0x02, 0xa0, 0x78, 0x21, 0x78, 0xff, 0x00, 0x40, 0xf4, 0x02, 0x22, 0x00, 
+        0x32, 0xa0, 0x01, 0x02, 0x20, 0x2b, 0x22, 0xa0, 0x03, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x0c, 0x63, 
+        0xc5, 0x74, 0x0d, 0x0c, 0x23, 0x0c, 0x65, 0xd0, 0x42, 0x11, 0x01, 0x6f, 0xff, 0x0c, 0x32, 0x08, 
+        0x00, 0x50, 0x44, 0x20, 0x02, 0x20, 0x2b, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x60, 0x12, 0xc1, 0xe0, 0xd9, 
+        0x21, 0xe9, 0x31, 0x09, 0x01, 0xc9, 0x11, 0xf9, 0x41, 0x16, 0x76, 0x0d, 0xb1, 0x78, 0xfd, 0xc1, 
+        0xfa, 0xff, 0x0c, 0x00, 0x0c, 0x4d, 0x70, 0x80, 0x90, 0x82, 0x18, 0x00, 0x9d, 0x0d, 0x80, 0xe8, 
+        0x04, 0x80, 0x24, 0x04, 0x80, 0xf3, 0x04, 0x2a, 0xff, 0x80, 0x36, 0x04, 0x80, 0x25, 0x04, 0x3a, 
+        0x22, 0x80, 0x39, 0x04, 0x3a, 0xee, 0x80, 0x37, 0x04, 0x80, 0x80, 0xe4, 0x3a, 0xee, 0x2a, 0xee, 
+        0xfa, 0xee, 0x80, 0xf0, 0x24, 0xe0, 0xe0, 0x74, 0xf6, 0x5e, 0x01, 0x9d, 0x0e, 0x90, 0xa0, 0x74, 
+        0xa0, 0xea, 0x90, 0xf0, 0xee, 0x90, 0xe0, 0xe0, 0xf4, 0x1c, 0xdf, 0x9d, 0x0f, 0xe7, 0x3f, 0x01, 
+        0x9d, 0x0e, 0x90, 0x30, 0xf4, 0x40, 0x33, 0xb0, 0xd8, 0x13, 0x38, 0x03, 0xd0, 0xe9, 0x84, 0x30, 
+        0x20, 0x84, 0xd0, 0xd0, 0x84, 0x30, 0x39, 0x84, 0xc0, 0x20, 0x00, 0xf0, 0xf8, 0x01, 0x80, 0x33, 
+        0x11, 0x1c, 0xe8, 0x3a, 0xff, 0x82, 0x6b, 0x1a, 0x20, 0x31, 0x41, 0x3a, 0xff, 0xc0, 0x30, 0xa0, 
+        0xc0, 0x20, 0x00, 0xf9, 0x03, 0xc0, 0x20, 0x00, 0x1c, 0xf8, 0x82, 0x6b, 0x1a, 0xc0, 0x20, 0x00, 
+        0xa0, 0x8e, 0x01, 0x10, 0x22, 0x01, 0xf9, 0x03, 0x8a, 0x22, 0x50, 0x8a, 0x90, 0x82, 0x18, 0x00, 
+        0x30, 0xdd, 0x11, 0x80, 0x80, 0xa4, 0xd0, 0x88, 0xa0, 0x8a, 0x22, 0xc0, 0x20, 0x00, 0xd2, 0xa1, 
+        0xe0, 0xd2, 0x6b, 0x1a, 0xc0, 0x20, 0x00, 0x29, 0x03, 0xc0, 0x20, 0x00, 0x82, 0xa1, 0xe1, 0x82, 
+        0x6b, 0x1a, 0xc0, 0x20, 0x00, 0x29, 0x03, 0x88, 0x51, 0x1b, 0x00, 0x00, 0x00, 0x74, 0x00, 0xd6, 
+        0xc0, 0x56, 0xfd, 0xf2, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 
+        0x20, 0x0d, 0xf0, 0x00, 0xfd, 0x7f, 0xfd, 0xff, 0x82, 0xae, 0x00, 0x72, 0xa1, 0x42, 0x31, 0x3b, 
+        0xfd, 0xc0, 0x20, 0x00, 0x62, 0x23, 0x59, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 
+        0x62, 0x63, 0x59, 0x51, 0xf8, 0xff, 0x0c, 0x24, 0xc0, 0x20, 0x00, 0x22, 0x23, 0x58, 0x50, 0x22, 
+        0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x58, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x09, 
+        0x11, 0x29, 0x01, 0xd9, 0x31, 0xe9, 0x41, 0xc9, 0x21, 0xed, 0x05, 0xc1, 0x2c, 0xfd, 0xd1, 0x0e, 
+        0xfa, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x58, 0x49, 0x51, 0x17, 0xe0, 0x24, 0x2d, 0x03, 0x01, 0xb0, 
+        0xf9, 0xc0, 0x00, 0x00, 0x01, 0x11, 0xff, 0x08, 0x00, 0x02, 0x20, 0x19, 0x28, 0x01, 0xc0, 0x00, 
+        0x00, 0x08, 0x51, 0xc0, 0x20, 0x00, 0x22, 0x2c, 0x58, 0x17, 0xe2, 0x13, 0x0c, 0x02, 0x06, 0x07, 
+        0x00, 0xc0, 0x20, 0x00, 0x52, 0x2d, 0x80, 0x40, 0x55, 0xc0, 0x57, 0xbe, 0xc3, 0xc6, 0x02, 0x00, 
+        0xc0, 0x20, 0x00, 0x62, 0x2d, 0x80, 0x00, 0x66, 0xc0, 0x67, 0xbe, 0xd6, 0x0c, 0x12, 0xc8, 0x21, 
+        0xd8, 0x31, 0xe8, 0x41, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xf7, 
+        0x51, 0xff, 0xff, 0x31, 0x12, 0xfd, 0xc0, 0x20, 0x00, 0x42, 0x23, 0x42, 0x50, 0x44, 0x10, 0xc0, 
+        0x20, 0x00, 0x42, 0x63, 0x42, 0xc0, 0x20, 0x00, 0x29, 0xb3, 0x0d, 0xf0, 0xff, 0xff, 0xf7, 0xff, 
+        0x41, 0x0b, 0xfd, 0xc0, 0x20, 0x00, 0x71, 0x18, 0xfd, 0x28, 0xb4, 0xc0, 0x20, 0x00, 0x62, 0x24, 
+        0x42, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x64, 0x42, 0x51, 0xf8, 0xff, 0xc0, 0x20, 0x00, 
+        0x38, 0xb4, 0x50, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x39, 0xb4, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x02, 
+        0x61, 0x00, 0x01, 0xe9, 0xfe, 0x02, 0x20, 0x00, 0x02, 0x20, 0x11, 0x32, 0xa0, 0x80, 0xc0, 0x00, 
+        0x00, 0xc5, 0x5e, 0x02, 0x22, 0xa0, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0xb0, 0xf6, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x01, 0xdf, 0xfe, 0x22, 0x20, 0x02, 
+        0x27, 0x72, 0x20, 0x41, 0xfb, 0xff, 0x32, 0xc0, 0x49, 0x22, 0x04, 0x10, 0x42, 0x04, 0x10, 0x80, 
+        0x22, 0x01, 0x20, 0x28, 0x31, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x40, 0x22, 0x90, 0x30, 0x22, 
+        0x80, 0x85, 0xcf, 0x01, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x4a, 0xf6, 0xfe, 0x3f, 
+        0x93, 0xf6, 0xfe, 0x3f, 0x0e, 0xf7, 0xfe, 0x3f, 0x20, 0x42, 0xa0, 0x12, 0xc1, 0xc0, 0x09, 0x41, 
+        0x39, 0xd1, 0xc9, 0x51, 0xe9, 0x71, 0xd9, 0x61, 0xf9, 0x81, 0x42, 0xc4, 0xc9, 0x49, 0x31, 0x0c, 
+        0x0f, 0xd1, 0xf6, 0xff, 0x0c, 0x6e, 0xcd, 0x02, 0x32, 0xc2, 0xfa, 0x39, 0x91, 0x0b, 0x22, 0x29, 
+        0xc1, 0xf6, 0x7c, 0x2a, 0x32, 0xa0, 0x05, 0x22, 0x21, 0x0c, 0x42, 0x0d, 0x7d, 0x52, 0x0d, 0x77, 
+        0x52, 0x61, 0x0b, 0x80, 0x44, 0x01, 0x80, 0x55, 0x01, 0x50, 0x58, 0x31, 0x40, 0x48, 0x31, 0x50, 
+        0x44, 0xc0, 0x40, 0x22, 0x82, 0x05, 0x41, 0x0d, 0x08, 0xb1, 0x0a, 0x02, 0x86, 0x16, 0x00, 0xf6, 
+        0xac, 0x2a, 0x32, 0xa0, 0x05, 0x22, 0x21, 0x09, 0x42, 0x0d, 0x83, 0x52, 0x0d, 0x7d, 0x52, 0x61, 
+        0x0a, 0x80, 0x44, 0x01, 0x80, 0x55, 0x01, 0x50, 0x58, 0x31, 0x40, 0x48, 0x31, 0x50, 0x44, 0xc0, 
+        0x40, 0x22, 0x82, 0x45, 0x3e, 0x0d, 0x08, 0xa1, 0x0a, 0x02, 0x06, 0x0b, 0x00, 0x02, 0x0d, 0x89, 
+        0x22, 0xa0, 0x0d, 0x80, 0x00, 0x01, 0x00, 0x08, 0x31, 0xc7, 0x32, 0x1d, 0x32, 0xa0, 0x16, 0x22, 
+        0x21, 0x03, 0x42, 0x0d, 0x83, 0x49, 0x21, 0x80, 0x44, 0x01, 0x40, 0x48, 0x31, 0x40, 0x40, 0xc0, 
+        0x40, 0x22, 0x82, 0x45, 0x3b, 0x0d, 0x08, 0x21, 0x0a, 0x02, 0xd2, 0xcd, 0x01, 0x22, 0x21, 0x0d, 
+        0xe2, 0xce, 0xff, 0x2a, 0x2f, 0x02, 0x42, 0x00, 0x1b, 0xff, 0x56, 0x3e, 0xf6, 0xd1, 0xcc, 0xff, 
+        0x32, 0x0d, 0xa0, 0x42, 0x0d, 0xab, 0x26, 0x13, 0x28, 0x26, 0x14, 0x25, 0x0c, 0x05, 0xe2, 0xaf, 
+        0x80, 0x6d, 0x0e, 0xe2, 0x4d, 0x4d, 0x52, 0x4d, 0x4e, 0x21, 0xc6, 0xff, 0x0c, 0xd3, 0x48, 0xd1, 
+        0x45, 0x90, 0x02, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 0x40, 
+        0x0d, 0xf0, 0x52, 0x0d, 0x97, 0xf2, 0x0d, 0x9b, 0xdc, 0x55, 0xb6, 0x3c, 0x02, 0x86, 0x43, 0x00, 
+        0x01, 0xbb, 0xff, 0x02, 0x00, 0x79, 0x0c, 0x15, 0x80, 0xe0, 0x01, 0xe0, 0xe8, 0x31, 0xc6, 0xef, 
+        0xff, 0xc7, 0x3f, 0x57, 0x01, 0xb6, 0xff, 0xe2, 0x0d, 0x99, 0x00, 0xee, 0x80, 0xe2, 0x0e, 0x77, 
+        0x02, 0x0d, 0x9c, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x66, 0x10, 0x3a, 0x32, 0xa0, 0x05, 0x22, 
+        0x0d, 0x34, 0xc2, 0x0d, 0x2e, 0x80, 0x22, 0x01, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 0x31, 0x20, 0x28, 
+        0x31, 0xc0, 0x22, 0xc0, 0x20, 0x2f, 0x82, 0x05, 0x31, 0x0d, 0x2a, 0x3c, 0x80, 0x33, 0x01, 0x28, 
+        0xc1, 0x30, 0x38, 0x31, 0xe0, 0x33, 0xc0, 0x30, 0x22, 0x82, 0x3d, 0x0f, 0x85, 0x2f, 0x0d, 0x2a, 
+        0xee, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x0c, 0x15, 0x06, 0xd9, 0xff, 0x22, 0x0d, 0x9a, 0x02, 
+        0xa0, 0x0f, 0x20, 0x00, 0xc0, 0x07, 0x2c, 0x48, 0x01, 0x9d, 0xff, 0xe2, 0x0d, 0x98, 0x00, 0xee, 
+        0x80, 0xe2, 0x0e, 0x89, 0x32, 0x0d, 0x9c, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0x66, 0x13, 0xd6, 
+        0x02, 0x0d, 0x3a, 0x80, 0x00, 0x01, 0x00, 0x08, 0x31, 0x02, 0x61, 0x01, 0xf6, 0xac, 0x29, 0x22, 
+        0x0d, 0x34, 0x0c, 0x83, 0x80, 0x22, 0x01, 0xf0, 0x33, 0xc0, 0x20, 0x28, 0x31, 0x29, 0x01, 0x20, 
+        0x20, 0xc0, 0x30, 0x22, 0x82, 0x0c, 0x53, 0x05, 0x2a, 0x0d, 0x08, 0x01, 0x2a, 0x00, 0x06, 0x0b, 
+        0x00, 0x0c, 0x05, 0xe2, 0xaf, 0x80, 0xc6, 0xc1, 0xff, 0x32, 0xa0, 0x16, 0x21, 0x79, 0xff, 0x42, 
+        0xa0, 0x03, 0x22, 0x02, 0x23, 0xf0, 0x44, 0xc0, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0x00, 0x22, 
+        0xc0, 0x40, 0x22, 0x82, 0x20, 0x22, 0xa0, 0x05, 0x27, 0x0d, 0x08, 0x11, 0x2a, 0x00, 0x0c, 0xe3, 
+        0x80, 0x20, 0x01, 0x20, 0x28, 0x31, 0xc0, 0x33, 0xc0, 0xe0, 0x22, 0xc0, 0x30, 0x22, 0x82, 0x3d, 
+        0x0f, 0x45, 0x25, 0x0d, 0x2a, 0xee, 0x80, 0xee, 0x01, 0xe0, 0xe8, 0x31, 0xc6, 0xd5, 0xff, 0xb6, 
+        0x9c, 0x08, 0x01, 0x76, 0xff, 0x02, 0x00, 0x85, 0x86, 0xba, 0xff, 0xe2, 0xaf, 0x80, 0x0c, 0x05, 
+        0x46, 0xab, 0xff, 0x00, 0x12, 0xc1, 0xe0, 0x02, 0x61, 0x04, 0x01, 0x43, 0xfe, 0x02, 0x20, 0x02, 
+        0x47, 0x70, 0x15, 0x21, 0x6c, 0xfe, 0x3d, 0x01, 0x22, 0x12, 0x01, 0xc5, 0x6c, 0x02, 0x21, 0x69, 
+        0xfe, 0x3d, 0x01, 0x22, 0x12, 0x01, 0x45, 0x62, 0x02, 0x0c, 0xe2, 0x8b, 0x31, 0x85, 0xda, 0xff, 
+        0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x21, 0x4d, 0xfc, 0xc0, 0x20, 0x00, 0x22, 0x22, 
+        0x59, 0x20, 0x24, 0xb5, 0x1b, 0x22, 0x20, 0x21, 0x41, 0x22, 0xd2, 0xf8, 0x00, 0x22, 0x11, 0x20, 
+        0x20, 0x31, 0x0d, 0xf0, 0x41, 0x46, 0xfc, 0x1b, 0x92, 0x2b, 0x82, 0x90, 0x89, 0xb3, 0x80, 0x81, 
+        0x21, 0x82, 0xd8, 0x02, 0x92, 0xae, 0x00, 0x80, 0x80, 0x84, 0xc0, 0x20, 0x00, 0x72, 0x24, 0x59, 
+        0x90, 0x77, 0x10, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x64, 0x59, 0x61, 0xfe, 0xfe, 0x0c, 
+        0x25, 0xc0, 0x20, 0x00, 0x32, 0x24, 0x58, 0x60, 0x33, 0x10, 0x50, 0x33, 0x20, 0xc0, 0x20, 0x00, 
+        0x32, 0x64, 0x58, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xff, 0xff, 0x80, 0xf8, 0xfe, 0x3f, 
+        0x71, 0xfe, 0xff, 0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x09, 0x11, 0x62, 0xa2, 0x00, 0x41, 0x2f, 0xfc, 
+        0x01, 0xfb, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x24, 0x59, 0x70, 0x55, 0x10, 0x60, 0x55, 0x20, 0xc0, 
+        0x20, 0x00, 0x52, 0x64, 0x59, 0x52, 0x10, 0x00, 0xc0, 0x20, 0x00, 0x42, 0x24, 0x58, 0x29, 0x01, 
+        0x17, 0x64, 0x02, 0xb6, 0x95, 0x5f, 0xc1, 0x10, 0xfe, 0x39, 0x31, 0xb6, 0x95, 0x05, 0x02, 0xae, 
+        0xd4, 0x86, 0x05, 0x00, 0x08, 0x0c, 0x08, 0xa0, 0xc0, 0x00, 0x00, 0x38, 0x31, 0x02, 0xae, 0xd4, 
+        0x27, 0x20, 0x01, 0x0d, 0x02, 0x00, 0x00, 0x11, 0x00, 0x00, 0x31, 0x22, 0x9c, 0xc7, 0x27, 0x20, 
+        0x42, 0x20, 0x42, 0x90, 0x4a, 0x00, 0x42, 0xc0, 0xfe, 0x1b, 0x00, 0x40, 0x04, 0xb3, 0x00, 0x02, 
+        0x21, 0x00, 0x20, 0x11, 0x20, 0x20, 0x31, 0x22, 0x5c, 0xc7, 0x8c, 0x63, 0x08, 0x0c, 0x02, 0x20, 
+        0x16, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x19, 0x28, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xdb, 
+        0xff, 0x0c, 0x02, 0x46, 0x00, 0x00, 0x1b, 0x25, 0xc8, 0x21, 0x22, 0x50, 0x00, 0x08, 0x11, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x0a, 0x02, 0x1b, 0x40, 0x2b, 0x00, 0x40, 0x04, 0xb3, 0x00, 0x01, 0x21, 
+        0x46, 0xef, 0xff, 0x00, 0x60, 0xf7, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x20, 0x00, 
+        0x12, 0xc1, 0xc0, 0xc9, 0x61, 0xd9, 0x71, 0xe9, 0x81, 0xf9, 0x91, 0x09, 0x51, 0x92, 0x21, 0x10, 
+        0x39, 0xe1, 0x38, 0x09, 0x01, 0xe9, 0xfd, 0x30, 0x35, 0x05, 0x56, 0x83, 0x16, 0x81, 0xf5, 0xff, 
+        0xe2, 0xae, 0xac, 0x0c, 0x0b, 0xb9, 0xa1, 0xc8, 0xa1, 0x1b, 0xdc, 0x80, 0xfc, 0x90, 0xe2, 0x5f, 
+        0x00, 0xd0, 0xc0, 0x74, 0xc9, 0xa1, 0x66, 0x4c, 0xed, 0xb2, 0xaf, 0xd8, 0xa2, 0xae, 0x7c, 0x69, 
+        0x01, 0x60, 0xab, 0x93, 0xa2, 0x50, 0xc7, 0x7c, 0xed, 0xa1, 0xf0, 0xfb, 0xc0, 0x20, 0x00, 0x78, 
+        0xba, 0x79, 0x21, 0xc0, 0x20, 0x00, 0x32, 0x2a, 0xc8, 0x39, 0x31, 0xc0, 0x20, 0x00, 0xf2, 0x2a, 
+        0xd0, 0xf9, 0x41, 0xc0, 0x20, 0x00, 0xc8, 0xba, 0xd0, 0xcc, 0x10, 0xc0, 0x20, 0x00, 0xc9, 0xba, 
+        0xb1, 0xe2, 0xff, 0xc0, 0x20, 0x00, 0x72, 0x2a, 0xc8, 0xb0, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x72, 
+        0x6a, 0xc8, 0xc1, 0xc5, 0xf8, 0x99, 0x11, 0x29, 0xd1, 0x49, 0xc1, 0x59, 0xb1, 0x0c, 0x03, 0x39, 
+        0xa1, 0xc0, 0x20, 0x00, 0xf2, 0x2c, 0x80, 0x42, 0x21, 0x0a, 0x22, 0xa0, 0x0e, 0x40, 0x34, 0xa0, 
+        0x42, 0xc4, 0xfd, 0x32, 0xc3, 0x01, 0x40, 0x23, 0x93, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0x05, 
+        0x16, 0x02, 0x48, 0xe1, 0x01, 0xd0, 0xff, 0xbc, 0xa4, 0xd8, 0xa1, 0x0c, 0x0c, 0x00, 0xdd, 0x90, 
+        0x4d, 0x0f, 0x28, 0xd1, 0x38, 0xc1, 0x58, 0xb1, 0x05, 0xa8, 0xff, 0xec, 0x32, 0x01, 0xba, 0xfd, 
+        0x08, 0x00, 0x08, 0xa0, 0xc0, 0x00, 0x00, 0x02, 0x9d, 0x00, 0x07, 0xa2, 0x04, 0x0d, 0x02, 0x22, 
+        0x5d, 0x00, 0x28, 0xe1, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x07, 0xae, 0x02, 0xe2, 0x5d, 0x00, 0xc7, 
+        0x92, 0xcd, 0xc1, 0xa9, 0xf8, 0xc0, 0x20, 0x00, 0x21, 0xc5, 0xfb, 0x08, 0xd2, 0x7c, 0xe3, 0x30, 
+        0x00, 0x10, 0xc0, 0x20, 0x00, 0xd8, 0xa1, 0x09, 0xd2, 0x1b, 0xfd, 0xf0, 0xd0, 0x74, 0xd9, 0xa1, 
+        0x26, 0x4d, 0x02, 0x86, 0xde, 0xff, 0xc0, 0x20, 0x00, 0x61, 0xbc, 0xfb, 0x88, 0x21, 0x89, 0xb6, 
+        0xc0, 0x20, 0x00, 0x78, 0x31, 0x72, 0x66, 0xc8, 0xc0, 0x20, 0x00, 0x58, 0x41, 0x48, 0x01, 0x52, 
+        0x66, 0xd0, 0xbc, 0x84, 0x31, 0xb0, 0xff, 0xc1, 0xa0, 0xfd, 0x0c, 0x09, 0x22, 0x9c, 0xc7, 0x99, 
+        0xa1, 0x00, 0xa2, 0x11, 0xa0, 0xa0, 0x31, 0x08, 0xa1, 0x48, 0xa1, 0x30, 0x00, 0x90, 0x1b, 0x54, 
+        0x50, 0x40, 0x74, 0x02, 0x90, 0x00, 0x49, 0xa1, 0xa7, 0xa0, 0x04, 0x2d, 0x00, 0x02, 0x5c, 0xc7, 
+        0x00, 0xa2, 0x11, 0x66, 0x44, 0xdd, 0x08, 0x0c, 0x02, 0x20, 0x16, 0xc0, 0x00, 0x00, 0x21, 0x92, 
+        0xfd, 0x22, 0x92, 0xc7, 0xe7, 0xa2, 0x19, 0x48, 0x11, 0x51, 0xa0, 0xff, 0x38, 0x04, 0x50, 0x33, 
+        0x20, 0x39, 0x04, 0x86, 0x02, 0x00, 0x68, 0x00, 0x62, 0x26, 0x16, 0x22, 0x90, 0xc7, 0xc0, 0x06, 
+        0x00, 0xc8, 0x61, 0xd8, 0x71, 0xe8, 0x81, 0xf8, 0x91, 0x08, 0x51, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 
+        0x80, 0x87, 0xfe, 0x3f, 0x7a, 0xf6, 0xfe, 0x3f, 0xff, 0x03, 0xfc, 0xff, 0x42, 0xa0, 0x00, 0x12, 
+        0xc1, 0xe0, 0xe2, 0x61, 0x05, 0xd2, 0x61, 0x04, 0x09, 0x21, 0xc9, 0x31, 0x01, 0xfa, 0xff, 0xcd, 
+        0x02, 0xdd, 0x03, 0x0c, 0x22, 0x31, 0xf6, 0xff, 0xe2, 0x00, 0x7d, 0x3a, 0x44, 0x80, 0xee, 0x01, 
+        0x3a, 0x22, 0x42, 0x14, 0x00, 0x42, 0x51, 0x00, 0x22, 0x02, 0x00, 0xe0, 0xe8, 0x31, 0x22, 0x41, 
+        0x02, 0x0c, 0xd2, 0xe6, 0x7c, 0x20, 0x0c, 0x53, 0x4d, 0x00, 0x42, 0x04, 0x7c, 0x0b, 0x2c, 0x80, 
+        0x44, 0x01, 0x40, 0x48, 0x31, 0x49, 0x11, 0x40, 0x4e, 0xc0, 0x40, 0x22, 0x82, 0x85, 0xed, 0x0c, 
+        0xe8, 0x11, 0x2a, 0xee, 0x06, 0x08, 0x00, 0x32, 0x00, 0x7e, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 
+        0xe0, 0x33, 0xc0, 0xc7, 0xa2, 0x02, 0x46, 0x42, 0x00, 0x22, 0xcc, 0xfa, 0x20, 0x23, 0x82, 0x32, 
+        0xa0, 0x05, 0x45, 0xeb, 0x0c, 0x20, 0xee, 0x80, 0x66, 0x1d, 0x0b, 0xd2, 0xaf, 0xfa, 0xd2, 0x41, 
+        0x00, 0xd2, 0x41, 0x02, 0xc6, 0x08, 0x00, 0x32, 0xcd, 0xfe, 0x56, 0x93, 0x0b, 0x01, 0xd9, 0xff, 
+        0x32, 0x00, 0x7f, 0x32, 0x41, 0x00, 0x22, 0x00, 0x80, 0x22, 0x41, 0x01, 0x02, 0x00, 0x81, 0x02, 
+        0x41, 0x02, 0xd2, 0x01, 0x01, 0x80, 0xdd, 0x01, 0xd0, 0xd8, 0x31, 0xe6, 0x7c, 0x2c, 0x32, 0x01, 
+        0x00, 0x22, 0xcc, 0xff, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 0x80, 0x33, 0x01, 0x30, 0x38, 0x31, 
+        0x30, 0x3d, 0xc0, 0x30, 0x22, 0x82, 0x32, 0xa0, 0x05, 0xc5, 0xe5, 0x0c, 0x02, 0x01, 0x00, 0x80, 
+        0x00, 0x01, 0x00, 0x08, 0x31, 0x20, 0x00, 0x80, 0x06, 0x08, 0x00, 0x02, 0x01, 0x02, 0x22, 0xa0, 
+        0x0d, 0x80, 0x00, 0x01, 0x00, 0x08, 0x31, 0xd0, 0x00, 0xc0, 0xc7, 0x22, 0x74, 0x32, 0xa0, 0x05, 
+        0x22, 0xcc, 0xfa, 0x20, 0x20, 0x82, 0x05, 0xe3, 0x0c, 0xd0, 0x02, 0x80, 0xa1, 0xbf, 0xff, 0x0a, 
+        0x9e, 0x41, 0x56, 0xfb, 0x90, 0x90, 0x74, 0x60, 0x99, 0x11, 0xc0, 0x20, 0x00, 0x82, 0x24, 0xda, 
+        0xa0, 0x88, 0x10, 0x90, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x82, 0x64, 0xda, 0x0c, 0x17, 0xc0, 0x20, 
+        0x00, 0x68, 0xd4, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x69, 0xd4, 0x7c, 0xe5, 0xc0, 0x20, 0x00, 
+        0x38, 0xd4, 0x50, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x39, 0xd4, 0xc8, 0x31, 0xd8, 0x41, 0xe8, 0x51, 
+        0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0xa2, 0xcd, 0xfd, 0x56, 0x4a, 0xf5, 0x01, 0xa9, 0xff, 
+        0x32, 0x00, 0x82, 0x32, 0x41, 0x00, 0x22, 0x00, 0x83, 0x22, 0x41, 0x01, 0x02, 0x00, 0x84, 0x06, 
+        0xcf, 0xff, 0x0c, 0x53, 0x22, 0xcc, 0xfe, 0x20, 0x20, 0x82, 0xc5, 0xdb, 0x0c, 0x06, 0xe2, 0xff, 
+        0x00, 0x00, 0x00, 0x22, 0xcc, 0xfe, 0x20, 0x23, 0x82, 0x0c, 0x53, 0xc5, 0xda, 0x0c, 0xc6, 0xbc, 
+        0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x03, 0x01, 0x1f, 0xfd, 0x02, 0x20, 0x02, 
+        0x29, 0x21, 0x27, 0x70, 0x0f, 0x31, 0x1c, 0xfd, 0x20, 0x22, 0x90, 0x32, 0xc3, 0x49, 0x3a, 0x22, 
+        0x85, 0x60, 0x01, 0x28, 0x21, 0x41, 0x10, 0xf8, 0xc0, 0x20, 0x00, 0x42, 0x24, 0x9c, 0x17, 0x64, 
+        0x22, 0x20, 0x20, 0x74, 0x3d, 0x01, 0x05, 0x91, 0xff, 0x0c, 0x02, 0xc5, 0x59, 0x00, 0x21, 0x12, 
+        0xfd, 0x08, 0x02, 0x02, 0x20, 0x16, 0x22, 0x92, 0xc7, 0xc0, 0x00, 0x00, 0x1c, 0xe2, 0x01, 0xac, 
+        0xf7, 0xc0, 0x00, 0x00, 0x08, 0x31, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x85, 0xf6, 0xfe, 0x3f, 
+        0x84, 0x87, 0xfe, 0x3f, 0xc0, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x99, 0x99, 0x49, 0x40, 
+        0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe9, 0x40, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 
+        0x12, 0xc1, 0xb0, 0xd9, 0xb1, 0xe9, 0xc1, 0x29, 0x61, 0xc9, 0xa1, 0xf9, 0xd1, 0xf1, 0xf3, 0xff, 
+        0x09, 0x91, 0x02, 0x0f, 0x60, 0xcd, 0x03, 0xcc, 0x30, 0x2c, 0x8d, 0xc6, 0x04, 0x00, 0x66, 0x10, 
+        0x04, 0x1c, 0xad, 0xc6, 0x02, 0x00, 0x32, 0xc0, 0xfe, 0x22, 0xa0, 0x18, 0xd2, 0xa0, 0x28, 0x30, 
+        0xd2, 0x83, 0x2d, 0x0c, 0x3d, 0x0d, 0x85, 0xd5, 0x0c, 0xe6, 0x92, 0x17, 0x2d, 0x0c, 0x3d, 0x0d, 
+        0x45, 0xce, 0x0c, 0x20, 0x0d, 0x82, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0xa0, 0xf0, 0x20, 0x11, 0x29, 
+        0x51, 0xc6, 0x08, 0x00, 0x20, 0x4d, 0xc0, 0xe6, 0x94, 0x17, 0xc0, 0x2c, 0x20, 0xd0, 0x3d, 0x20, 
+        0x45, 0xcc, 0x0c, 0x02, 0xc2, 0x01, 0x00, 0x0d, 0x82, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0xa0, 0x46, 
+        0xf6, 0xff, 0x22, 0xa0, 0x00, 0x22, 0x61, 0x05, 0x32, 0x0f, 0x7c, 0x22, 0x0f, 0x9f, 0x16, 0x83, 
+        0x06, 0x32, 0x61, 0x04, 0xe2, 0x0f, 0x7b, 0x80, 0x22, 0x11, 0x2a, 0xee, 0x16, 0xae, 0x05, 0x2d, 
+        0x03, 0x7c, 0x6d, 0xc0, 0xdd, 0x82, 0xc0, 0x22, 0xc1, 0x30, 0x33, 0xa0, 0xf0, 0x33, 0x11, 0x29, 
+        0xe1, 0x32, 0x61, 0x10, 0x3d, 0x0e, 0x85, 0xce, 0x0c, 0x02, 0x21, 0x10, 0x48, 0xe1, 0x07, 0x22, 
+        0x02, 0x86, 0x47, 0x00, 0x2d, 0x04, 0x3d, 0x0e, 0xc5, 0xc6, 0x0c, 0x45, 0xd7, 0x0c, 0x29, 0x21, 
+        0x2d, 0x0e, 0xc5, 0xd6, 0x0c, 0xed, 0x02, 0x28, 0x41, 0xc5, 0xd5, 0x0c, 0x3d, 0x02, 0x2d, 0x0e, 
+        0xc5, 0x07, 0x0c, 0x3d, 0x02, 0x28, 0x21, 0x45, 0xf1, 0x0b, 0xe1, 0xc1, 0xff, 0x38, 0x0e, 0xc5, 
+        0xf0, 0x0b, 0x85, 0x12, 0x0c, 0x2a, 0xed, 0x06, 0x02, 0x00, 0xe2, 0xa0, 0x00, 0xd2, 0xaf, 0xf6, 
+        0xc0, 0xdd, 0x82, 0x02, 0x0f, 0x9b, 0xe2, 0x61, 0x11, 0x16, 0x30, 0x06, 0x02, 0x61, 0x03, 0x22, 
+        0x0f, 0xa0, 0xe2, 0x0f, 0x9a, 0x80, 0x22, 0x11, 0x2a, 0xee, 0x16, 0x2e, 0x05, 0x3d, 0x0e, 0x00, 
+        0xf0, 0xa0, 0xc0, 0x20, 0xc1, 0x29, 0xf1, 0xf0, 0xff, 0x11, 0x45, 0xc7, 0x0c, 0xc8, 0x31, 0x08, 
+        0xf1, 0xf7, 0x22, 0x02, 0x06, 0x3b, 0x00, 0x3d, 0x0e, 0x2d, 0x00, 0xc5, 0xbf, 0x0c, 0x05, 0xd0, 
+        0x0c, 0xfd, 0x02, 0x2d, 0x0e, 0x85, 0xcf, 0x0c, 0xed, 0x02, 0x2d, 0x0c, 0x85, 0xce, 0x0c, 0x3d, 
+        0x02, 0x2d, 0x0e, 0xc5, 0x00, 0x0c, 0x3d, 0x02, 0x2d, 0x0f, 0x05, 0xea, 0x0b, 0x31, 0xa4, 0xff, 
+        0x38, 0x03, 0x85, 0xe9, 0x0b, 0x45, 0x0b, 0x0c, 0xe2, 0x21, 0x11, 0x2a, 0xfd, 0x06, 0x01, 0x00, 
+        0xe2, 0x21, 0x11, 0x0c, 0x0f, 0xc1, 0xa8, 0xfc, 0x21, 0x9f, 0xff, 0x08, 0x0c, 0xc2, 0x1c, 0xfb, 
+        0x08, 0x00, 0xca, 0xcd, 0x2a, 0xcc, 0x2d, 0x0c, 0xc0, 0x00, 0x00, 0x01, 0x9a, 0xff, 0x41, 0xa2, 
+        0xfc, 0x0c, 0x03, 0x52, 0xa0, 0x64, 0x57, 0x22, 0x01, 0xcd, 0x03, 0x68, 0x04, 0x22, 0x14, 0xfc, 
+        0x68, 0x06, 0x2a, 0xdd, 0x0a, 0xdd, 0x2d, 0x0d, 0xc0, 0x06, 0x00, 0x01, 0x9b, 0xfc, 0x38, 0x61, 
+        0x72, 0x10, 0xe9, 0x0b, 0x33, 0x00, 0x03, 0x40, 0x70, 0x70, 0xb1, 0x07, 0x67, 0x02, 0x56, 0x4e, 
+        0x11, 0x42, 0x10, 0xf9, 0x00, 0x03, 0x40, 0x40, 0x40, 0xb1, 0x07, 0x64, 0x02, 0x56, 0x7f, 0x11, 
+        0x56, 0xfc, 0x08, 0x52, 0xa0, 0x64, 0x57, 0x22, 0x01, 0x0c, 0x0d, 0xc8, 0x51, 0xd0, 0xcd, 0x93, 
+        0xc6, 0x1f, 0x00, 0x20, 0x6e, 0xc0, 0x07, 0x26, 0x02, 0x86, 0x3b, 0x00, 0x2d, 0x04, 0x3d, 0x0e, 
+        0x45, 0xb4, 0x0c, 0x1b, 0x22, 0x85, 0xc4, 0x0c, 0x29, 0x01, 0x2d, 0x0e, 0x05, 0xc4, 0x0c, 0x29, 
+        0x11, 0x28, 0x41, 0x45, 0xc3, 0x0c, 0x3d, 0x02, 0xe8, 0x01, 0x28, 0x11, 0x05, 0xf5, 0x0b, 0x3d, 
+        0x02, 0x2d, 0x0e, 0x85, 0xde, 0x0b, 0x31, 0x76, 0xff, 0x38, 0x03, 0x05, 0xde, 0x0b, 0xc5, 0xff, 
+        0x0b, 0x06, 0xb4, 0xff, 0x20, 0x4e, 0xc0, 0xf7, 0x24, 0x02, 0x86, 0x2c, 0x00, 0x3d, 0x0e, 0x2d, 
+        0x00, 0x45, 0xb0, 0x0c, 0x1b, 0x22, 0x85, 0xc0, 0x0c, 0xfd, 0x02, 0x2d, 0x0e, 0x05, 0xc0, 0x0c, 
+        0xed, 0x02, 0x2d, 0x0c, 0x05, 0xbf, 0x0c, 0x3d, 0x02, 0x2d, 0x0e, 0x45, 0xf1, 0x0b, 0x3d, 0x02, 
+        0x2d, 0x0f, 0x85, 0xda, 0x0b, 0x31, 0x66, 0xff, 0x38, 0x03, 0x05, 0xda, 0x0b, 0xc5, 0xfb, 0x0b, 
+        0x06, 0xc1, 0xff, 0xe1, 0x65, 0xff, 0xd2, 0xa0, 0x00, 0x2d, 0x0c, 0x85, 0xc1, 0x0c, 0x29, 0x81, 
+        0x39, 0x71, 0x51, 0x62, 0xff, 0x41, 0x62, 0xff, 0x45, 0x11, 0x0c, 0x5d, 0x0e, 0x4d, 0x0d, 0x45, 
+        0x3b, 0x0c, 0x45, 0x4d, 0x0c, 0x38, 0x71, 0x51, 0x5f, 0xff, 0xfd, 0x02, 0x41, 0x5d, 0xff, 0x28, 
+        0x81, 0xc5, 0x0f, 0x0c, 0x4d, 0x0d, 0x5d, 0x0e, 0x85, 0x39, 0x0c, 0xd1, 0x73, 0xfa, 0x85, 0x4b, 
+        0x0c, 0x71, 0x5a, 0xff, 0x51, 0x59, 0xff, 0xf0, 0x60, 0x94, 0x50, 0x52, 0x10, 0xc0, 0x66, 0x01, 
+        0x2d, 0x0c, 0xc0, 0x20, 0x00, 0x42, 0x2d, 0xa8, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0x50, 0x44, 
+        0x20, 0xc0, 0x20, 0x00, 0xc8, 0xa1, 0xe8, 0xc1, 0x42, 0x6d, 0xa8, 0xf8, 0xd1, 0xd8, 0xb1, 0x08, 
+        0x91, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0xcd, 0x0e, 0xc6, 0xe1, 0xff, 0x0c, 0x0e, 0x86, 0x88, 0xff, 
+        0xe2, 0x21, 0x11, 0x0c, 0x0f, 0x06, 0xa3, 0xff, 0xcd, 0x0f, 0x46, 0xdd, 0xff, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x09, 0x11, 0xcc, 0x52, 0x0c, 0x00, 0x0c, 0x0c, 0x86, 0x10, 0x00, 
+        0xe6, 0x12, 0x02, 0xc6, 0x70, 0x00, 0x32, 0xa0, 0x64, 0xb0, 0xc2, 0x11, 0xc0, 0x2c, 0x20, 0x85, 
+        0xa2, 0x0c, 0x0d, 0x02, 0x0c, 0xa3, 0x2d, 0x0c, 0x80, 0xc0, 0x01, 0xc0, 0xc8, 0x31, 0x85, 0xa1, 
+        0x0c, 0x0c, 0xa3, 0xc5, 0xa7, 0x0c, 0xa6, 0x22, 0x02, 0x06, 0x73, 0x00, 0x0c, 0x10, 0x46, 0x04, 
+        0x00, 0xc2, 0x01, 0x01, 0x02, 0x01, 0x00, 0x80, 0xcc, 0x01, 0x80, 0x00, 0x01, 0x00, 0x08, 0x31, 
+        0xc0, 0xc8, 0x31, 0xe6, 0x1c, 0x05, 0x00, 0x41, 0x21, 0xc6, 0x01, 0x00, 0x0b, 0x2c, 0x00, 0x12, 
+        0x40, 0x00, 0x40, 0xa1, 0x21, 0x45, 0xfa, 0xc0, 0x20, 0x00, 0x42, 0x62, 0xb5, 0x62, 0xcc, 0x1e, 
+        0x0c, 0x05, 0x00, 0x16, 0x40, 0x00, 0x30, 0xa1, 0xc0, 0x35, 0xb3, 0xc0, 0x20, 0x00, 0x32, 0x62, 
+        0xa7, 0xe6, 0x1c, 0x05, 0x00, 0x41, 0x21, 0xc6, 0x01, 0x00, 0x0b, 0x7c, 0x00, 0x17, 0x40, 0x00, 
+        0x40, 0xa1, 0xc0, 0x20, 0x00, 0x0c, 0x06, 0x42, 0x62, 0xec, 0xa2, 0xcc, 0x1e, 0x0c, 0x09, 0x00, 
+        0x1a, 0x40, 0x00, 0x80, 0xa1, 0xc0, 0x89, 0xb3, 0xc0, 0x20, 0x00, 0x82, 0x62, 0xa1, 0x26, 0x10, 
+        0x14, 0x66, 0x20, 0x04, 0x0c, 0x85, 0x86, 0x03, 0x00, 0x32, 0xc0, 0xfd, 0x0c, 0xab, 0x5d, 0x06, 
+        0x30, 0x5b, 0x83, 0x46, 0x00, 0x00, 0x0c, 0x25, 0xa6, 0xbc, 0x0d, 0x6c, 0x04, 0x40, 0x4c, 0x90, 
+        0x00, 0x14, 0x40, 0x00, 0x45, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x04, 0xc0, 0x20, 0x00, 0x42, 0x62, 
+        0xa3, 0x7c, 0x0b, 0xa6, 0x1c, 0x10, 0xe6, 0xbc, 0x0d, 0x7c, 0xe7, 0x70, 0x7c, 0x90, 0x00, 0x17, 
+        0x40, 0x00, 0x75, 0xa1, 0xc6, 0x01, 0x00, 0x0c, 0x08, 0x50, 0x72, 0x21, 0xc0, 0x78, 0x93, 0xc0, 
+        0x20, 0x00, 0x6c, 0x1a, 0x72, 0x62, 0xa2, 0x81, 0x1d, 0xfa, 0xc7, 0xab, 0x10, 0xd6, 0xdc, 0x00, 
+        0x1c, 0xe9, 0x90, 0x9c, 0x90, 0x00, 0x19, 0x40, 0x00, 0x75, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x07, 
+        0x7c, 0x19, 0xc0, 0x20, 0x00, 0x72, 0x68, 0xc3, 0xc7, 0xaa, 0x10, 0x97, 0xac, 0x0d, 0x3c, 0xc3, 
+        0x30, 0x3c, 0x90, 0x00, 0x13, 0x40, 0x00, 0x45, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x04, 0xc0, 0x20, 
+        0x00, 0x42, 0x68, 0xc2, 0x26, 0x10, 0x14, 0x66, 0x20, 0x04, 0x0c, 0x40, 0x86, 0x03, 0x00, 0x52, 
+        0xc0, 0xfd, 0x0c, 0x54, 0x50, 0x64, 0x83, 0x0d, 0x06, 0x46, 0x00, 0x00, 0x0c, 0x10, 0xa6, 0xbc, 
+        0x0d, 0x6c, 0x06, 0x60, 0x6c, 0x90, 0x00, 0x16, 0x40, 0x00, 0x40, 0xa1, 0x46, 0x00, 0x00, 0x0c, 
+        0x04, 0xc0, 0x20, 0x00, 0x42, 0x62, 0xef, 0xa6, 0x1c, 0x10, 0xe6, 0xbc, 0x0d, 0x7c, 0xe7, 0x70, 
+        0x7c, 0x90, 0x00, 0x17, 0x40, 0x00, 0x50, 0xa1, 0xc6, 0x01, 0x00, 0x0c, 0x08, 0x00, 0x52, 0x21, 
+        0xc0, 0x58, 0x93, 0xc0, 0x20, 0x00, 0x52, 0x62, 0xee, 0xc7, 0xab, 0x10, 0xd6, 0xdc, 0x00, 0x1c, 
+        0xeb, 0xb0, 0xbc, 0x90, 0x00, 0x1b, 0x40, 0x00, 0x50, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x05, 0xc0, 
+        0x20, 0x00, 0x52, 0x62, 0xeb, 0xc7, 0xaa, 0x10, 0x97, 0xac, 0x0d, 0x3c, 0xc3, 0x30, 0x3c, 0x90, 
+        0x00, 0x13, 0x40, 0x00, 0x00, 0xa1, 0x46, 0x00, 0x00, 0x0c, 0x00, 0xc0, 0x20, 0x00, 0xc8, 0x21, 
+        0x02, 0x62, 0xea, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xd6, 0x32, 0xe6, 0x32, 0xa0, 0x64, 
+        0xb0, 0xc2, 0x11, 0xc0, 0x2c, 0x20, 0x05, 0x86, 0x0c, 0x0d, 0x02, 0x0c, 0xa3, 0x2d, 0x0c, 0x0b, 
+        0xc0, 0x80, 0xcc, 0x01, 0xc0, 0xc8, 0x31, 0x05, 0x85, 0x0c, 0x0c, 0xa3, 0x05, 0x8b, 0x0c, 0x7c, 
+        0x83, 0x37, 0xa2, 0x11, 0x0c, 0x10, 0x46, 0x92, 0xff, 0x0c, 0x30, 0xe6, 0x82, 0x02, 0x46, 0x90, 
+        0xff, 0x0c, 0x20, 0x06, 0x8f, 0xff, 0x0c, 0x30, 0x7c, 0xe4, 0x47, 0xa2, 0x02, 0x86, 0x8c, 0xff, 
+        0x0c, 0x20, 0x46, 0x8b, 0xff, 0x00, 0x00, 0x00, 0x40, 0xf6, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0x3c, 0xf5, 0xdc, 0x22, 0x1c, 0x04, 0xc0, 0x20, 0x00, 0x32, 0x20, 0xe4, 0x40, 0x33, 
+        0x20, 0xc0, 0x20, 0x00, 0x32, 0x60, 0xe4, 0x06, 0x04, 0x00, 0x6c, 0xf6, 0xc0, 0x20, 0x00, 0x52, 
+        0x20, 0xe4, 0x60, 0x55, 0x10, 0xc0, 0x20, 0x00, 0x52, 0x60, 0xe4, 0x41, 0xf3, 0xff, 0x80, 0x32, 
+        0x01, 0x22, 0x04, 0x80, 0x30, 0x38, 0x31, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0xc5, 0x8a, 0xff, 
+        0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 
+        0x00, 0x20, 0xc2, 0x20, 0x05, 0xed, 0x00, 0x2d, 0x0c, 0x05, 0xfa, 0xff, 0xc8, 0x11, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 
+        0xff, 0xff, 0x7f, 0x80, 0x81, 0xbc, 0x14, 0x09, 0x98, 0x41, 0xc6, 0x5a, 0x00, 0x00, 0x00, 0x80, 
+        0x00, 0x00, 0x90, 0x01, 0xff, 0xff, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0xff, 0x80, 
+        0xff, 0x0f, 0xf0, 0xff, 0x00, 0x20, 0x02, 0x00, 0xa6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 
+        0x54, 0x58, 0x38, 0x00, 0x00, 0xff, 0x0f, 0xf0, 0xe6, 0x00, 0x20, 0x0b, 0x3f, 0xf0, 0xff, 0xdf, 
+        0x40, 0x0c, 0x00, 0x20, 0xff, 0xff, 0x80, 0xff, 0x00, 0x00, 0x13, 0x00, 0x3f, 0xf0, 0xff, 0xff, 
+        0x80, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x24, 0x01, 0xfe, 0x03, 0xff, 0xff, 0xff, 0x0f, 
+        0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x00, 0x24, 0x00, 
+        0xff, 0xff, 0xbf, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x83, 0x00, 0x80, 0x00, 0xff, 0xf7, 0xff, 0xff, 
+        0x50, 0x80, 0xfe, 0x3f, 0xe7, 0xf6, 0xfe, 0x3f, 0x70, 0xf7, 0xfe, 0x3f, 0x38, 0xf5, 0xfe, 0x3f, 
+        0xbc, 0xf5, 0xfe, 0x3f, 0xac, 0xf6, 0xfe, 0x3f, 0x61, 0xd8, 0xff, 0xb1, 0xd8, 0xff, 0x41, 0xa5, 
+        0xfb, 0x51, 0x71, 0xf6, 0x12, 0xc1, 0xe0, 0xc9, 0x51, 0x09, 0x41, 0xd9, 0x61, 0x82, 0xaf, 0x80, 
+        0x21, 0x8b, 0xf9, 0xd1, 0x89, 0xf9, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x58, 0x60, 0x33, 0x20, 0xc0, 
+        0x20, 0x00, 0x32, 0x62, 0x58, 0xc0, 0x20, 0x00, 0x02, 0x22, 0x43, 0xb0, 0x00, 0x20, 0xc0, 0x20, 
+        0x00, 0x02, 0x62, 0x43, 0xc1, 0xcb, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x22, 0xd0, 0xc0, 0xaa, 0x10, 
+        0xb0, 0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x62, 0xd0, 0x91, 0xc6, 0xff, 0xc0, 0x20, 0x00, 0x92, 
+        0x62, 0x5b, 0x71, 0xc5, 0xff, 0xc0, 0x20, 0x00, 0x72, 0x62, 0x5a, 0x61, 0xc4, 0xff, 0xc0, 0x20, 
+        0x00, 0x32, 0x22, 0x54, 0x60, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x54, 0xc0, 0x20, 0x00, 
+        0xc2, 0xa1, 0x90, 0x02, 0x22, 0xc6, 0xc0, 0x20, 0x00, 0xc2, 0x62, 0xc6, 0xb1, 0x73, 0xf9, 0xa1, 
+        0xbc, 0xff, 0xc0, 0x20, 0x00, 0x92, 0x2d, 0xbb, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 
+        0x00, 0x92, 0x6d, 0xbb, 0x71, 0xb8, 0xff, 0xc0, 0x20, 0x00, 0x62, 0x2d, 0xe2, 0x70, 0x66, 0x10, 
+        0xc0, 0x20, 0x00, 0x62, 0x6d, 0xe2, 0x42, 0x04, 0x00, 0xc0, 0x20, 0x00, 0x32, 0x22, 0x52, 0x80, 
+        0x33, 0x10, 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x52, 0x01, 0x41, 0xf6, 0xc1, 0xae, 
+        0xff, 0xc0, 0x20, 0x00, 0xb2, 0x22, 0x4a, 0x00, 0xbb, 0x10, 0xc0, 0xbb, 0x20, 0xc0, 0x20, 0x00, 
+        0xb2, 0x62, 0x4a, 0xa1, 0xaa, 0xff, 0xc0, 0x20, 0x00, 0x98, 0xd2, 0xa0, 0x99, 0x10, 0xc0, 0x20, 
+        0x00, 0x99, 0xd2, 0x2c, 0x67, 0xc0, 0x20, 0x00, 0x62, 0x22, 0x51, 0x80, 0x66, 0x10, 0x70, 0x66, 
+        0x20, 0xc0, 0x20, 0x00, 0x62, 0x62, 0x51, 0x42, 0xaf, 0xc0, 0x1c, 0x13, 0xc0, 0x20, 0x00, 0x02, 
+        0x22, 0xdc, 0x40, 0x00, 0x10, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x62, 0xdc, 0xc1, 0x33, 
+        0xfe, 0xc0, 0x20, 0x00, 0xb2, 0x2d, 0xa8, 0xc0, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x6d, 0xa8, 
+        0xa1, 0x98, 0xff, 0x91, 0x98, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x22, 0x59, 0xa0, 0x88, 0x10, 0x90, 
+        0x88, 0x20, 0xc0, 0x20, 0x00, 0x82, 0x62, 0x59, 0x71, 0x43, 0xf9, 0x61, 0x93, 0xff, 0xc0, 0x20, 
+        0x00, 0x42, 0x22, 0x59, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x62, 0x59, 
+        0x31, 0x8f, 0xff, 0x01, 0x8f, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x22, 0x57, 0x30, 0xcc, 0x10, 0x00, 
+        0xcc, 0x20, 0xc0, 0x20, 0x00, 0xc2, 0x62, 0x57, 0xb1, 0x8b, 0xff, 0xa1, 0x8b, 0xff, 0xc0, 0x20, 
+        0x00, 0x92, 0x22, 0x54, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x62, 0x54, 
+        0xc0, 0x20, 0x00, 0x72, 0xa0, 0x80, 0x82, 0x22, 0xc6, 0xc0, 0x20, 0x00, 0x72, 0x62, 0xc6, 0x0c, 
+        0x46, 0xc0, 0x20, 0x00, 0x42, 0x22, 0xc4, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x62, 0xc4, 
+        0x31, 0x7f, 0xff, 0x01, 0x7f, 0xff, 0xc0, 0x20, 0x00, 0xc2, 0x22, 0xdc, 0x30, 0xcc, 0x10, 0x00, 
+        0xcc, 0x20, 0xc0, 0x20, 0x00, 0xc2, 0x62, 0xdc, 0xb1, 0x7b, 0xff, 0xa1, 0x7b, 0xff, 0xc0, 0x20, 
+        0x00, 0x92, 0x22, 0xc9, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x62, 0xc9, 
+        0x81, 0x77, 0xff, 0x71, 0x77, 0xff, 0xc0, 0x20, 0x00, 0x62, 0x22, 0x56, 0x80, 0x66, 0x10, 0x70, 
+        0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x62, 0x56, 0x41, 0x73, 0xff, 0x31, 0x73, 0xff, 0xc0, 0x20, 
+        0x00, 0x02, 0x22, 0xd3, 0x40, 0x00, 0x10, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x62, 0xd3, 
+        0xc1, 0x6f, 0xff, 0xb1, 0x6f, 0xff, 0xc0, 0x20, 0x00, 0xa2, 0x22, 0xc8, 0xc0, 0xaa, 0x10, 0xb0, 
+        0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x62, 0xc8, 0x91, 0x6b, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x2d, 
+        0xe2, 0x90, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x82, 0x6d, 0xe2, 0x71, 0x67, 0xff, 0x61, 0x67, 0xff, 
+        0xc0, 0x20, 0x00, 0x42, 0x25, 0x9c, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 
+        0x65, 0x9c, 0x31, 0x63, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xd1, 0x30, 0x00, 0x10, 0xc0, 0x20, 
+        0x00, 0x02, 0x62, 0xd1, 0x0c, 0x02, 0x45, 0xc9, 0xff, 0xc1, 0xe3, 0xfa, 0x08, 0x0c, 0x08, 0x30, 
+        0x0c, 0x02, 0xc0, 0x00, 0x00, 0xb2, 0xaf, 0xcf, 0x2c, 0x0a, 0x31, 0x5e, 0xf4, 0x61, 0x66, 0xf3, 
+        0x21, 0x59, 0xff, 0xc0, 0x20, 0x00, 0x92, 0x2d, 0x8e, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 
+        0x20, 0x00, 0x92, 0x6d, 0x8e, 0xc0, 0x20, 0x00, 0xa1, 0xed, 0xf8, 0x71, 0x53, 0xff, 0x82, 0x2a, 
+        0x92, 0xc0, 0x20, 0x00, 0x72, 0x6a, 0x92, 0x0c, 0x65, 0xc0, 0x20, 0x00, 0x42, 0x2a, 0x93, 0x50, 
+        0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x6a, 0x93, 0xc0, 0x20, 0x00, 0x22, 0x6a, 0xc7, 0xc0, 0x20, 
+        0x00, 0x02, 0x2a, 0xc7, 0x20, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x6a, 0xc7, 0xb1, 0x47, 0xff, 
+        0xc0, 0x20, 0x00, 0x98, 0xaa, 0xb0, 0x99, 0x10, 0xc0, 0x20, 0x00, 0x99, 0xaa, 0x7c, 0x98, 0x0c, 
+        0x27, 0xc0, 0x20, 0x00, 0x52, 0x26, 0x89, 0x80, 0x55, 0x10, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 
+        0x52, 0x66, 0x89, 0x7c, 0xe4, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xf0, 0x40, 0x22, 0x10, 0xc0, 0x20, 
+        0x00, 0x08, 0x0c, 0x02, 0x20, 0x28, 0x22, 0x63, 0xf0, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x08, 0x0c, 
+        0x0c, 0x13, 0x02, 0x20, 0x2b, 0x0c, 0xc4, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 
+        0x02, 0x20, 0x2b, 0x42, 0xa1, 0x84, 0xc0, 0x00, 0x00, 0x0c, 0x32, 0x08, 0x0c, 0x0c, 0x23, 0x02, 
+        0x20, 0x2b, 0x0c, 0x64, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x2f, 0xc0, 0x00, 0x00, 0x32, 
+        0xa0, 0x7f, 0x41, 0x2b, 0xff, 0x51, 0x2b, 0xff, 0x1c, 0x06, 0x21, 0x2b, 0xff, 0x0c, 0x07, 0xc5, 
+        0xb5, 0xfe, 0x21, 0x2a, 0xff, 0x41, 0x2a, 0xff, 0x51, 0x2b, 0xff, 0x32, 0x2c, 0x22, 0x61, 0xd1, 
+        0xfa, 0x0c, 0x07, 0x62, 0x06, 0x00, 0x79, 0x01, 0x79, 0x11, 0x79, 0x21, 0x1b, 0x66, 0x60, 0x60, 
+        0x74, 0x71, 0x21, 0xff, 0x45, 0xce, 0xfe, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x24, 0x0c, 0x75, 
+        0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x72, 0xa0, 0xe8, 0xc0, 0x00, 0x00, 0x0c, 0x13, 0xc0, 
+        0x20, 0x00, 0x22, 0x2d, 0x98, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x6d, 0x98, 0xc8, 0x51, 
+        0xd8, 0x61, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0xf0, 
+        0x00, 0x00, 0x80, 0x01, 0xff, 0xff, 0xff, 0x1f, 0xff, 0x3f, 0xe0, 0xff, 0x00, 0x40, 0x1f, 0x00, 
+        0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xab, 0x00, 0xff, 0x00, 0xff, 0xff, 0xb1, 0xf8, 0xff, 0xa1, 
+        0xf8, 0xff, 0x31, 0x08, 0xf4, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xe6, 0xb0, 0x22, 0x10, 0xa0, 0x22, 
+        0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe6, 0xc0, 0x20, 0x00, 0x92, 0x23, 0xe7, 0xb0, 0x99, 0x10, 
+        0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x63, 0xe7, 0x81, 0xee, 0xff, 0x71, 0x7c, 0xfd, 0xc0, 
+        0x20, 0x00, 0x62, 0x23, 0xe5, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x63, 
+        0xe5, 0x51, 0xe9, 0xff, 0x41, 0xea, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xe6, 0x50, 0x22, 0x10, 
+        0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe6, 0xb1, 0xe5, 0xff, 0xa1, 0xe6, 0xff, 0xc0, 
+        0x20, 0x00, 0x92, 0x23, 0xe8, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x63, 
+        0xe8, 0x81, 0xe1, 0xff, 0x72, 0xa1, 0x00, 0xc0, 0x20, 0x00, 0x62, 0x23, 0xf2, 0x80, 0x66, 0x10, 
+        0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x63, 0xf2, 0x52, 0xaf, 0x80, 0x4c, 0x74, 0xc0, 0x20, 
+        0x00, 0x22, 0x23, 0xe6, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe6, 
+        0x0d, 0xf0, 0x00, 0x00, 0x9b, 0xf6, 0xfe, 0x3f, 0xff, 0x0f, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 
+        0x42, 0xaf, 0xbc, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xc1, 0xfb, 0xff, 0x09, 0x01, 0x22, 0x0c, 0x82, 
+        0x01, 0xcc, 0xf2, 0x66, 0x22, 0x13, 0x4c, 0x15, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x68, 0x40, 0x33, 
+        0x10, 0x50, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x60, 0x68, 0x32, 0x0c, 0x83, 0x26, 0x13, 0x02, 
+        0x66, 0x33, 0x27, 0x0c, 0x18, 0xc0, 0x20, 0x00, 0x72, 0x20, 0x68, 0x40, 0x77, 0x10, 0x80, 0x77, 
+        0x20, 0xc0, 0x20, 0x00, 0x72, 0x60, 0x68, 0x7c, 0xe6, 0xc0, 0x20, 0x00, 0x52, 0x20, 0x5d, 0x60, 
+        0x55, 0x10, 0xc0, 0x20, 0x00, 0x52, 0x60, 0x5d, 0x32, 0x0c, 0x83, 0x42, 0xae, 0xff, 0x26, 0x23, 
+        0x02, 0x66, 0x33, 0x28, 0xc0, 0x20, 0x00, 0x91, 0xb6, 0xf2, 0x82, 0x29, 0x8d, 0xa2, 0xae, 0xff, 
+        0xa0, 0x88, 0x10, 0xc0, 0x20, 0x00, 0x82, 0x69, 0x8d, 0x0c, 0x02, 0x0c, 0x03, 0x0c, 0x04, 0x0c, 
+        0x15, 0x01, 0xe1, 0xf2, 0xc0, 0x00, 0x00, 0x01, 0xae, 0xf2, 0x42, 0xae, 0xff, 0x32, 0x0c, 0x7c, 
+        0x26, 0x13, 0x11, 0xc0, 0x20, 0x00, 0xb2, 0x20, 0x8d, 0x40, 0xbb, 0x10, 0xc0, 0x20, 0x00, 0xb2, 
+        0x60, 0x8d, 0x32, 0x0c, 0x7c, 0x66, 0x23, 0x11, 0x32, 0xa1, 0x00, 0xc0, 0x20, 0x00, 0x22, 0x20, 
+        0x85, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x60, 0x85, 0x62, 0xae, 0xcf, 0x32, 0x0c, 0x81, 
+        0x3c, 0x05, 0x66, 0x13, 0x14, 0xc0, 0x20, 0x00, 0x42, 0x20, 0x86, 0x60, 0x44, 0x10, 0x50, 0x44, 
+        0x20, 0xc0, 0x20, 0x00, 0x42, 0x60, 0x86, 0x46, 0x0d, 0x00, 0x66, 0x23, 0x11, 0xc0, 0x20, 0x00, 
+        0x72, 0x20, 0x8e, 0x40, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x72, 0x60, 0x8e, 0x06, 0x08, 0x00, 0xc0, 
+        0x20, 0x00, 0x92, 0x20, 0x86, 0x60, 0x99, 0x10, 0x50, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x60, 
+        0x86, 0xc0, 0x20, 0x00, 0x82, 0x20, 0x8e, 0x40, 0x88, 0x10, 0xc0, 0x20, 0x00, 0x82, 0x60, 0x8e, 
+        0xa2, 0x0c, 0x7e, 0x66, 0x1a, 0x64, 0xc0, 0x20, 0x00, 0x32, 0x20, 0x86, 0x60, 0x33, 0x10, 0x50, 
+        0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x60, 0x86, 0xc0, 0x20, 0x00, 0x22, 0x20, 0x85, 0x60, 0x22, 
+        0x10, 0x50, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x60, 0x85, 0xb2, 0x0c, 0x7f, 0x66, 0x1b, 0x1e, 
+        0x0c, 0x22, 0x0c, 0x03, 0x0c, 0x24, 0x0c, 0x05, 0x01, 0xb0, 0xf2, 0xc0, 0x00, 0x00, 0x0c, 0x02, 
+        0x0c, 0x83, 0x0c, 0x84, 0x0c, 0x05, 0x01, 0xac, 0xf2, 0xc0, 0x00, 0x00, 0xc6, 0x06, 0x00, 0x0c, 
+        0x02, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x05, 0x01, 0xa8, 0xf2, 0xc0, 0x00, 0x00, 0x0c, 0x82, 0x0c, 
+        0x03, 0x0c, 0x84, 0x0c, 0x05, 0x01, 0xa4, 0xf2, 0xc0, 0x00, 0x00, 0x41, 0xa2, 0xf2, 0x02, 0x0c, 
+        0x7d, 0x31, 0x9d, 0xff, 0x66, 0x10, 0x15, 0x61, 0xbf, 0xf3, 0xc0, 0x20, 0x00, 0x58, 0x14, 0x30, 
+        0x55, 0x10, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x59, 0x14, 0x46, 0x05, 0x00, 0x66, 0x20, 0x12, 
+        0x71, 0x97, 0xff, 0xc0, 0x20, 0x00, 0x68, 0x14, 0x30, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 
+        0x00, 0x69, 0x14, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xbe, 0xf6, 0xfe, 0x3f, 
+        0x80, 0x3f, 0xe0, 0x0f, 0xff, 0xff, 0xcf, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfb, 0xff, 
+        0x22, 0x00, 0x80, 0x56, 0x62, 0x08, 0x01, 0xe8, 0xf9, 0x22, 0xa0, 0x66, 0x08, 0x00, 0x0c, 0x33, 
+        0x02, 0x20, 0x24, 0x0c, 0x14, 0xc0, 0x00, 0x00, 0x31, 0xe4, 0xf9, 0x22, 0x63, 0x84, 0x21, 0x61, 
+        0xf3, 0xc0, 0x20, 0x00, 0x52, 0x22, 0xe5, 0x52, 0x63, 0x85, 0xc0, 0x20, 0x00, 0x42, 0x22, 0xe6, 
+        0x42, 0x63, 0x86, 0xc0, 0x20, 0x00, 0x0c, 0x14, 0x0c, 0x55, 0x0c, 0x06, 0x3c, 0xc7, 0x22, 0x22, 
+        0xe7, 0x22, 0x63, 0x87, 0x08, 0x03, 0x22, 0xa0, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x33, 0xc0, 0x00, 
+        0x00, 0x01, 0xe6, 0xff, 0x21, 0xe7, 0xff, 0xc0, 0x20, 0x00, 0x71, 0x52, 0xf3, 0xb2, 0x27, 0xe7, 
+        0x20, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x67, 0xe7, 0xa1, 0x44, 0xfe, 0xc0, 0x20, 0x00, 0x92, 
+        0x27, 0xe6, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x67, 0xe6, 0x81, 0xde, 0xff, 0xc0, 0x20, 
+        0x00, 0x62, 0x27, 0xe5, 0x80, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 0x67, 0xe5, 0x0c, 0x13, 0x32, 
+        0x40, 0x80, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xc0, 0xf6, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xfd, 0xff, 0x22, 0x00, 0x7e, 0x66, 0x12, 0x38, 0x22, 0xa0, 
+        0x66, 0x0c, 0x33, 0x01, 0xbd, 0xf9, 0x0c, 0x14, 0x08, 0x00, 0x51, 0xf8, 0xff, 0x02, 0x20, 0x26, 
+        0x52, 0x05, 0x80, 0xc0, 0x00, 0x00, 0x01, 0xf5, 0xff, 0x31, 0x36, 0xf3, 0x52, 0x20, 0x21, 0xc0, 
+        0x20, 0x00, 0x52, 0x63, 0xe5, 0x42, 0x20, 0x22, 0xc0, 0x20, 0x00, 0x42, 0x63, 0xe6, 0x22, 0x20, 
+        0x23, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xe7, 0x0c, 0x06, 0x62, 0x40, 0x7e, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x66, 0x12, 0x05, 0x85, 0xef, 0xff, 0x86, 
+        0x00, 0x00, 0xc5, 0xf9, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xb4, 0xf5, 0xfe, 0x3f, 
+        0x58, 0xf6, 0xfe, 0x3f, 0x00, 0x78, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0xc9, 0x51, 0x09, 0x41, 0x21, 
+        0x2a, 0xf2, 0x01, 0xa1, 0xf9, 0xc0, 0x20, 0x00, 0x42, 0x22, 0x97, 0xc0, 0x20, 0x00, 0x32, 0x22, 
+        0x96, 0xc0, 0x20, 0x00, 0x10, 0x48, 0x40, 0x0c, 0x13, 0x0c, 0x74, 0x0c, 0x35, 0x0c, 0x26, 0x0c, 
+        0x07, 0x08, 0x00, 0x22, 0x22, 0x97, 0x02, 0x20, 0x27, 0x22, 0xa0, 0x61, 0xc0, 0x00, 0x00, 0xc5, 
+        0xc2, 0xff, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x04, 0x01, 0x93, 0xf9, 0x0c, 0x05, 0x08, 0x00, 
+        0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x45, 0x6b, 0x01, 0xc1, 0x0f, 0xfe, 
+        0x2d, 0x0c, 0x32, 0xcc, 0x3c, 0x05, 0x31, 0x01, 0x85, 0xaa, 0xfe, 0x0c, 0x12, 0x45, 0xd1, 0xfe, 
+        0x2d, 0x0c, 0x31, 0xe2, 0xff, 0x4c, 0x05, 0x0c, 0x07, 0x0c, 0x06, 0x0c, 0x19, 0x0c, 0x0a, 0x41, 
+        0xb1, 0xf9, 0x81, 0xdf, 0xff, 0x42, 0x14, 0x01, 0x82, 0x08, 0x80, 0xa9, 0x01, 0x99, 0x11, 0x80, 
+        0x88, 0x01, 0x80, 0x88, 0x31, 0x82, 0xc8, 0x1f, 0x80, 0x88, 0x01, 0x80, 0x88, 0x31, 0x80, 0x68, 
+        0xb3, 0x60, 0x60, 0x74, 0x45, 0x5e, 0x01, 0x0c, 0x62, 0x45, 0x04, 0x01, 0x85, 0x7f, 0xff, 0x0c, 
+        0x27, 0x61, 0x71, 0xf4, 0xc0, 0x20, 0x00, 0x52, 0x26, 0x9c, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 
+        0x52, 0x66, 0x9c, 0x3c, 0x22, 0x01, 0x12, 0xf4, 0xc0, 0x00, 0x00, 0x01, 0x73, 0xf9, 0x08, 0x00, 
+        0x02, 0x20, 0x16, 0x22, 0xae, 0x7c, 0xc0, 0x00, 0x00, 0x72, 0xac, 0x00, 0x62, 0xa0, 0xc9, 0x31, 
+        0x83, 0xf7, 0xc0, 0x20, 0x00, 0x58, 0xd3, 0x70, 0x55, 0x10, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 
+        0x59, 0xd3, 0x7c, 0xe4, 0xc0, 0x20, 0x00, 0x28, 0xd3, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x29, 
+        0xd3, 0x3c, 0x22, 0x01, 0x03, 0xf4, 0xc0, 0x00, 0x00, 0xc9, 0x01, 0x0c, 0x12, 0x0c, 0x73, 0x0c, 
+        0x54, 0x51, 0xbc, 0xff, 0x0c, 0x16, 0x0c, 0x07, 0x45, 0xdc, 0xfe, 0x0c, 0x02, 0xc8, 0x51, 0x08, 
+        0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0xe4, 0xf6, 0xfe, 0x3f, 0x6d, 0x02, 0xfb, 0x72, 
+        0x91, 0xfe, 0xff, 0x42, 0x02, 0x00, 0x5d, 0x09, 0x42, 0x49, 0x00, 0x32, 0x02, 0x01, 0x82, 0xc9, 
+        0xc0, 0x30, 0x31, 0x04, 0x32, 0x49, 0x02, 0xa2, 0x06, 0x02, 0xa2, 0x45, 0x03, 0x1b, 0x66, 0x1b, 
+        0x55, 0x77, 0x96, 0xf2, 0x5d, 0x09, 0x6d, 0x02, 0x3b, 0x72, 0x32, 0x06, 0x11, 0x1b, 0x55, 0x1b, 
+        0x66, 0x32, 0x45, 0x11, 0x42, 0x06, 0x13, 0x80, 0xb3, 0x01, 0x4a, 0x33, 0x32, 0x45, 0x14, 0x32, 
+        0x06, 0x16, 0xb0, 0xb8, 0x31, 0x3a, 0xbb, 0xb2, 0x45, 0x17, 0x77, 0x96, 0xdc, 0x6d, 0x02, 0x5d, 
+        0x09, 0x4b, 0x72, 0x42, 0x02, 0x1a, 0x42, 0x48, 0x5c, 0x32, 0x02, 0x1b, 0x32, 0x48, 0x5d, 0xb2, 
+        0x02, 0x1c, 0xa2, 0x02, 0x1d, 0xb0, 0xb0, 0x54, 0x80, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xa2, 0x58, 
+        0x2f, 0xa2, 0x06, 0x1e, 0xa2, 0x45, 0x20, 0x1b, 0x66, 0x1b, 0x55, 0x77, 0x96, 0xf2, 0x5d, 0x09, 
+        0x6d, 0x02, 0x6b, 0x72, 0xb2, 0x06, 0x22, 0xb2, 0x45, 0x24, 0x1b, 0x66, 0x1b, 0x55, 0x77, 0x96, 
+        0xf2, 0x5d, 0x09, 0x6d, 0x02, 0x8b, 0x72, 0x32, 0x06, 0x28, 0x32, 0x45, 0x2a, 0x1b, 0x66, 0x1b, 
+        0x55, 0x77, 0x96, 0xf2, 0x0c, 0x55, 0x32, 0x02, 0x30, 0x32, 0x48, 0x41, 0xb2, 0x02, 0x31, 0xb2, 
+        0x48, 0x73, 0xa2, 0x02, 0x32, 0xa2, 0x48, 0x74, 0x92, 0x02, 0x33, 0x92, 0x48, 0x75, 0x72, 0x02, 
+        0x34, 0x72, 0x48, 0x76, 0x62, 0x02, 0x35, 0x62, 0x48, 0x77, 0x42, 0x02, 0x36, 0x42, 0x48, 0x78, 
+        0x32, 0x02, 0x37, 0x32, 0x48, 0x79, 0xb2, 0x02, 0x38, 0xb2, 0x48, 0x7a, 0xa2, 0x02, 0x40, 0xa2, 
+        0x48, 0x7b, 0x92, 0x02, 0x41, 0x92, 0x48, 0x7c, 0x72, 0x02, 0x42, 0x62, 0x02, 0x43, 0x70, 0x70, 
+        0x54, 0x80, 0x77, 0x11, 0x70, 0x66, 0x20, 0x62, 0x58, 0x3f, 0x42, 0x02, 0x44, 0x42, 0x48, 0x80, 
+        0x32, 0x02, 0x45, 0x32, 0x48, 0x81, 0xb2, 0x02, 0x47, 0xa2, 0x02, 0x46, 0x80, 0xbb, 0x01, 0x80, 
+        0xaa, 0x01, 0xa0, 0xa8, 0x31, 0xb0, 0xb8, 0x31, 0x80, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xa2, 0x58, 
+        0x41, 0x92, 0x02, 0x49, 0x72, 0x02, 0x48, 0x80, 0x99, 0x01, 0x80, 0x77, 0x01, 0x70, 0x78, 0x31, 
+        0x90, 0x98, 0x31, 0x80, 0x99, 0x11, 0x90, 0x77, 0x20, 0x72, 0x58, 0x42, 0x62, 0x02, 0x4a, 0x62, 
+        0x48, 0x86, 0x42, 0x02, 0x4b, 0x6d, 0x05, 0x40, 0x40, 0x34, 0x42, 0x48, 0x88, 0xf6, 0x64, 0x01, 
+        0x6d, 0x04, 0x62, 0x48, 0x88, 0x92, 0x02, 0x4b, 0x90, 0x94, 0x24, 0x92, 0x48, 0x8a, 0x72, 0x02, 
+        0x4b, 0x70, 0x77, 0x04, 0x72, 0x48, 0x8c, 0x62, 0x02, 0x4c, 0x60, 0x60, 0x34, 0x62, 0x48, 0x87, 
+        0x67, 0x35, 0x01, 0x5d, 0x06, 0x52, 0x48, 0x87, 0xa2, 0x02, 0x4c, 0xa0, 0xa4, 0x24, 0xa2, 0x48, 
+        0x89, 0x92, 0x02, 0x4c, 0x90, 0x97, 0x04, 0x92, 0x48, 0x8b, 0x72, 0x02, 0x4d, 0x70, 0x70, 0x34, 
+        0x72, 0x48, 0x8e, 0x62, 0x02, 0x4d, 0x60, 0x64, 0x34, 0x62, 0x48, 0x8d, 0x42, 0x02, 0x4e, 0x42, 
+        0x48, 0x8f, 0x32, 0x02, 0x4f, 0x32, 0x48, 0x90, 0xb2, 0x02, 0x50, 0xb2, 0x48, 0x91, 0xa2, 0x02, 
+        0x51, 0xa2, 0x48, 0x92, 0x92, 0x02, 0x52, 0x92, 0x48, 0x93, 0x72, 0x02, 0x53, 0x72, 0x48, 0x94, 
+        0x62, 0x02, 0x54, 0x62, 0x48, 0x95, 0x42, 0x02, 0x55, 0x42, 0x48, 0x96, 0x32, 0x02, 0x56, 0x32, 
+        0x48, 0x97, 0xb2, 0x02, 0x57, 0xb2, 0x48, 0x98, 0xa2, 0x02, 0x58, 0xa2, 0x48, 0x99, 0x0c, 0x02, 
+        0x0d, 0xf0, 0x00, 0x00, 0x65, 0xf6, 0xfe, 0x3f, 0x14, 0x3a, 0x00, 0x40, 0xa4, 0x38, 0x00, 0x40, 
+        0xd8, 0x39, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x01, 0xfa, 0xff, 0x02, 0x00, 0x80, 0x16, 
+        0xa0, 0x09, 0x01, 0xaf, 0xf4, 0xc0, 0x00, 0x00, 0x41, 0xf7, 0xff, 0x42, 0x04, 0x80, 0x29, 0x01, 
+        0x66, 0x14, 0x26, 0x22, 0xa0, 0x67, 0x0c, 0x43, 0x08, 0x01, 0x0c, 0x24, 0x02, 0x20, 0x26, 0x52, 
+        0xa0, 0x91, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x67, 0x0c, 0x43, 0x08, 0x01, 0x0c, 0x14, 0x02, 0x20, 
+        0x26, 0x52, 0xa0, 0x88, 0xc0, 0x00, 0x00, 0x46, 0x05, 0x00, 0x66, 0x24, 0x12, 0x0c, 0x43, 0x0c, 
+        0x24, 0x0c, 0x75, 0x0c, 0x56, 0x0c, 0x27, 0x02, 0x22, 0x27, 0x22, 0xa0, 0x67, 0xc0, 0x00, 0x00, 
+        0x01, 0x45, 0xf2, 0xc0, 0x20, 0x00, 0x22, 0x20, 0x46, 0x27, 0x72, 0x35, 0xc0, 0x20, 0x00, 0x32, 
+        0x20, 0x46, 0x41, 0x33, 0xf1, 0x30, 0x3d, 0x25, 0x66, 0x23, 0x26, 0xc0, 0x20, 0x00, 0x42, 0x24, 
+        0x88, 0x87, 0x64, 0x1d, 0x0c, 0x12, 0x01, 0xdc, 0xff, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x01, 0xdb, 
+        0xff, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xa2, 0xb6, 0x01, 0xd9, 0xff, 0xc0, 0x00, 0x00, 0x86, 
+        0x02, 0x00, 0x0c, 0x02, 0x32, 0xa2, 0xb6, 0x01, 0xd6, 0xff, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x82, 0xf8, 0xfe, 0x3f, 0x34, 0xf5, 0xfe, 0x3f, 0xdc, 0xf6, 0xfe, 0x3f, 
+        0x6c, 0x40, 0x10, 0x40, 0x90, 0x3c, 0x10, 0x40, 0xc4, 0x3f, 0x10, 0x40, 0x68, 0x25, 0x10, 0x40, 
+        0x84, 0x25, 0x10, 0x40, 0x34, 0x51, 0x10, 0x40, 0xcc, 0x41, 0x10, 0x40, 0x24, 0x80, 0xfe, 0x3f, 
+        0x00, 0x00, 0x00, 0x02, 0x12, 0xc1, 0xf0, 0xd9, 0x31, 0xc9, 0x21, 0xc1, 0xf2, 0xff, 0x09, 0x11, 
+        0x02, 0x0c, 0x00, 0xdd, 0x02, 0xcc, 0x70, 0x21, 0xf0, 0xff, 0x31, 0xf0, 0xff, 0x85, 0x24, 0xfe, 
+        0x0c, 0x16, 0x31, 0x40, 0xf1, 0xc0, 0x20, 0x00, 0x52, 0x23, 0xd2, 0x60, 0x55, 0x20, 0xc0, 0x20, 
+        0x00, 0x52, 0x63, 0xd2, 0x7c, 0xe4, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xd2, 0x40, 0x22, 0x10, 0xc0, 
+        0x20, 0x00, 0x22, 0x63, 0xd2, 0x01, 0x6a, 0xf4, 0xc0, 0x00, 0x00, 0x72, 0x0c, 0x00, 0x81, 0xea, 
+        0xff, 0x91, 0xe8, 0xff, 0xa1, 0xe7, 0xff, 0xb1, 0xe5, 0xff, 0x31, 0xe3, 0xff, 0x41, 0xe1, 0xff, 
+        0x01, 0x8e, 0xf8, 0x51, 0xdf, 0xff, 0x29, 0x00, 0x52, 0x62, 0x1f, 0x42, 0x62, 0x28, 0x32, 0x62, 
+        0x22, 0xb9, 0xa2, 0xa2, 0x62, 0x16, 0x99, 0x92, 0x82, 0x62, 0x36, 0xcc, 0xc7, 0x2d, 0x0d, 0xc5, 
+        0xca, 0xff, 0xdd, 0x02, 0x0c, 0xe6, 0x69, 0x01, 0x46, 0x04, 0x00, 0x71, 0xc3, 0xfc, 0x72, 0x07, 
+        0x80, 0xd2, 0xa0, 0x00, 0x80, 0x77, 0x01, 0x70, 0x78, 0x31, 0x72, 0x61, 0x00, 0x45, 0xe8, 0xff, 
+        0xc5, 0x87, 0xff, 0xc5, 0xae, 0xff, 0x21, 0xd5, 0xff, 0xc5, 0x08, 0xfe, 0x82, 0x0c, 0x00, 0xa1, 
+        0x7a, 0xf8, 0x66, 0x18, 0x07, 0x28, 0x01, 0x85, 0xc3, 0x00, 0x46, 0x02, 0x00, 0xb1, 0xd0, 0xff, 
+        0x98, 0x2a, 0xb0, 0x99, 0x20, 0x99, 0x2a, 0x2d, 0x0d, 0x0c, 0x10, 0x02, 0x4c, 0x00, 0xd8, 0x31, 
+        0xc8, 0x21, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 
+        0x12, 0xc1, 0xe0, 0xd9, 0x21, 0xe9, 0x31, 0x09, 0x01, 0xc9, 0x11, 0xf9, 0x41, 0x4d, 0x00, 0xf1, 
+        0x62, 0xf3, 0xc1, 0xe8, 0xf1, 0xc0, 0x20, 0x00, 0x22, 0x2c, 0xe5, 0x07, 0xe2, 0x41, 0xc0, 0x20, 
+        0x00, 0x52, 0x2f, 0x9c, 0x17, 0x65, 0x38, 0xd1, 0x64, 0xf8, 0x08, 0x0d, 0x02, 0x20, 0x1d, 0xc0, 
+        0x00, 0x00, 0x0c, 0x52, 0x01, 0xff, 0xf2, 0xc0, 0x00, 0x00, 0xe2, 0xa1, 0x84, 0x08, 0x0d, 0x0c, 
+        0x22, 0x02, 0x20, 0x2c, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0xe7, 0xc2, 0xf0, 0x08, 0x0d, 0x0c, 0x32, 
+        0x02, 0x20, 0x2c, 0x0c, 0x23, 0xc0, 0x00, 0x00, 0x0c, 0x63, 0x30, 0x22, 0x10, 0x66, 0x62, 0xdc, 
+        0x91, 0x7a, 0xf6, 0x81, 0x6a, 0xf6, 0xc0, 0x20, 0x00, 0x72, 0x28, 0x42, 0x90, 0x77, 0x20, 0xc0, 
+        0x20, 0x00, 0x72, 0x68, 0x42, 0xc0, 0x20, 0x00, 0x52, 0x2c, 0xe5, 0x0c, 0x16, 0x60, 0x55, 0x20, 
+        0xc0, 0x20, 0x00, 0x52, 0x6c, 0xe5, 0xc0, 0x20, 0x00, 0x42, 0x2f, 0x9c, 0x01, 0xdc, 0xff, 0x17, 
+        0x64, 0x11, 0xc0, 0x20, 0x00, 0xa2, 0x2c, 0xe8, 0xe7, 0xfa, 0x08, 0xc0, 0x20, 0x00, 0xb2, 0x2c, 
+        0xe8, 0x07, 0x0b, 0xf6, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 
+        0x20, 0x0d, 0xf0, 0x00, 0x0c, 0x13, 0x42, 0xa0, 0x81, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 
+        0xd1, 0x3e, 0xf8, 0x09, 0x01, 0x08, 0x0d, 0xcd, 0x02, 0x02, 0x20, 0x2b, 0x0c, 0x22, 0xc0, 0x00, 
+        0x00, 0x0c, 0x72, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0xc0, 0x45, 0x41, 0xc0, 0x00, 0x00, 
+        0xc0, 0x40, 0x44, 0x08, 0x0d, 0x0c, 0x02, 0x02, 0x20, 0x2b, 0x0c, 0x13, 0xc0, 0x00, 0x00, 0x0c, 
+        0x12, 0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 0xa0, 0x7f, 0xc0, 0x00, 0x00, 0x0c, 0x62, 
+        0x08, 0x0d, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x42, 0xa0, 0x7f, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0xd8, 
+        0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x8b, 0xfe, 0x3f, 
+        0xff, 0xff, 0x0f, 0xff, 0x12, 0xc1, 0xe0, 0x09, 0x11, 0x29, 0x61, 0xe9, 0x41, 0xd9, 0x31, 0xf9, 
+        0x51, 0xc9, 0x21, 0xfd, 0x02, 0xc1, 0x20, 0xf8, 0xdd, 0x04, 0xed, 0x03, 0x41, 0xf7, 0xff, 0x31, 
+        0x9d, 0xf1, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xf2, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x08, 0x0c, 
+        0x02, 0x20, 0x37, 0x22, 0x63, 0xf2, 0xc0, 0x00, 0x00, 0x4d, 0x0d, 0x3d, 0x0f, 0x2d, 0x0e, 0x5d, 
+        0x01, 0xc5, 0x45, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x38, 0x2d, 0x01, 0xc0, 0x00, 0x00, 0x08, 0x0c, 
+        0x02, 0x20, 0x36, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x45, 0x08, 
+        0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x87, 0xc0, 0x00, 0x00, 0x0c, 0x0d, 0xf2, 0xa0, 0x63, 
+        0xe2, 0xa0, 0x64, 0x3c, 0x22, 0x01, 0xa6, 0xf2, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 
+        0x0c, 0x74, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 0x25, 0x0c, 0x76, 0xc0, 0x00, 0x00, 0xdc, 0x22, 
+        0xf7, 0x9d, 0x08, 0x21, 0xda, 0xff, 0x01, 0x2c, 0xf8, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 0xd0, 0xd0, 
+        0x74, 0xe7, 0x9d, 0xce, 0x01, 0xd7, 0xff, 0xc0, 0x20, 0x00, 0xf1, 0x7a, 0xf1, 0xe2, 0x2f, 0xf2, 
+        0x00, 0xee, 0x10, 0xc0, 0x20, 0x00, 0xc8, 0x21, 0xe2, 0x6f, 0xf2, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 
+        0x51, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x32, 0xa0, 0x01, 0x42, 0xa0, 0x05, 0x0c, 0x75, 
+        0x0c, 0x06, 0x12, 0xc1, 0xe0, 0xd9, 0x21, 0xf9, 0x41, 0xc9, 0x11, 0xe9, 0x31, 0xe1, 0xee, 0xf7, 
+        0x09, 0x01, 0x08, 0x0e, 0xcd, 0x02, 0x02, 0x20, 0x25, 0x22, 0xa0, 0x62, 0xc0, 0x00, 0x00, 0x0c, 
+        0x0d, 0xfd, 0x02, 0x32, 0xae, 0xac, 0x20, 0x22, 0x90, 0x30, 0x22, 0xb0, 0x32, 0xa0, 0xe3, 0x85, 
+        0x8b, 0x0b, 0x00, 0x52, 0x11, 0x0c, 0xf4, 0x0d, 0x04, 0x50, 0x50, 0x31, 0x2d, 0x0d, 0x50, 0x25, 
+        0xb3, 0xe6, 0xb2, 0x01, 0x0d, 0x02, 0x32, 0xa0, 0xcf, 0xf0, 0x2f, 0x90, 0xf0, 0x22, 0xf0, 0x22, 
+        0xc2, 0x1d, 0x00, 0xf0, 0x11, 0xf0, 0xf0, 0x31, 0xc5, 0x88, 0x0b, 0x98, 0x0e, 0x00, 0x42, 0x11, 
+        0x0c, 0xf3, 0x0d, 0x03, 0x40, 0x40, 0x31, 0x92, 0x29, 0x27, 0x40, 0xd4, 0xb3, 0xe6, 0xbd, 0x01, 
+        0x0d, 0x0d, 0x00, 0xd0, 0x11, 0xd0, 0xd0, 0x31, 0xb6, 0x3c, 0x1c, 0x0c, 0x82, 0xa6, 0x8f, 0x01, 
+        0x7c, 0x82, 0x0c, 0x03, 0x0c, 0x44, 0x0c, 0x35, 0x0c, 0x06, 0x2a, 0x7f, 0x70, 0x70, 0x74, 0x22, 
+        0xa0, 0x64, 0xc0, 0x09, 0x00, 0x06, 0x04, 0x00, 0xf0, 0x70, 0x74, 0x22, 0xa0, 0x64, 0x0c, 0x03, 
+        0x0c, 0x44, 0x0c, 0x35, 0x0c, 0x06, 0xc0, 0x09, 0x00, 0x98, 0x0e, 0x0c, 0x80, 0x92, 0x29, 0x27, 
+        0xb6, 0x2c, 0x1a, 0xa6, 0x8d, 0x01, 0x7c, 0x80, 0x22, 0xa0, 0x64, 0x0c, 0x03, 0x0c, 0x74, 0x0c, 
+        0x35, 0x0c, 0x06, 0x0a, 0x7d, 0x70, 0x70, 0x74, 0xc0, 0x09, 0x00, 0x06, 0x04, 0x00, 0xd0, 0x70, 
+        0x74, 0x22, 0xa0, 0x64, 0x0c, 0x03, 0x0c, 0x74, 0x0c, 0x35, 0x0c, 0x06, 0xc0, 0x09, 0x00, 0x98, 
+        0x0e, 0x92, 0x29, 0x27, 0xac, 0x6c, 0x22, 0xa0, 0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x35, 0x0c, 
+        0x26, 0x0c, 0x37, 0xc0, 0x09, 0x00, 0x22, 0xa0, 0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x15, 0x08, 
+        0x0e, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x37, 0xc0, 0x00, 0x00, 0x06, 0x09, 0x00, 0x22, 0xa0, 
+        0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x35, 0x0c, 0x26, 0x0c, 0x07, 0xc0, 0x09, 0x00, 0x22, 0xa0, 
+        0x61, 0x0c, 0x13, 0x0c, 0x54, 0x0c, 0x15, 0x08, 0x0e, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x07, 
+        0xc0, 0x00, 0x00, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x00, 0x00, 0x22, 0xa0, 0x61, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0x9f, 0xf7, 0x0c, 
+        0x13, 0x08, 0x00, 0x0c, 0x84, 0x02, 0x20, 0x26, 0x1c, 0x15, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x85, 
+        0xe9, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0x0c, 0x0d, 0x16, 0x1d, 0x04, 0x26, 0x1d, 0x20, 0x66, 
+        0x2d, 0x56, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x65, 0x01, 0x8f, 0xf7, 0x0c, 0x46, 
+        0x08, 0x00, 0xda, 0x7c, 0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x06, 0x0e, 0x00, 
+        0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x35, 0x01, 0x87, 0xf7, 0x0c, 0x06, 0x08, 0x00, 
+        0xda, 0x7c, 0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x86, 0x06, 0x00, 0x22, 0xa0, 
+        0x6b, 0x0c, 0x23, 0x0c, 0x14, 0x0c, 0x35, 0x01, 0x80, 0xf7, 0x0c, 0x06, 0x08, 0x00, 0xda, 0x7c, 
+        0x02, 0x20, 0x27, 0x72, 0x07, 0x00, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0x66, 0x3d, 
+        0x97, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x09, 
+        0x11, 0x39, 0x01, 0xc9, 0x21, 0xd9, 0x31, 0xe9, 0x41, 0xdd, 0x02, 0xed, 0x04, 0xc1, 0x72, 0xf7, 
+        0x16, 0x22, 0x0f, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xc4, 0x0c, 0x05, 0x08, 0x0c, 0x0c, 0x06, 
+        0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 
+        0x45, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 
+        0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 
+        0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 
+        0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x55, 
+        0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x0c, 0x04, 0x0c, 0x75, 0x0c, 0x06, 0x08, 0x0c, 0x78, 0x01, 0x02, 0x20, 0x27, 0x70, 0x7c, 
+        0x74, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x14, 0x0c, 0x75, 0x0c, 0x06, 0x08, 
+        0x0c, 0x78, 0x01, 0x02, 0x20, 0x27, 0x70, 0x74, 0x74, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x0c, 0x24, 0x0c, 0x35, 0x0c, 0x06, 0x08, 0x0c, 0x78, 0x01, 0x02, 0x20, 0x27, 0x70, 0x70, 
+        0x34, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x44, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 
+        0x06, 0x02, 0x20, 0x27, 0xe0, 0x70, 0x74, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 
+        0x34, 0x0c, 0x75, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0xe0, 0x78, 0x74, 0xc0, 0x00, 0x00, 
+        0xe0, 0x70, 0x35, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x24, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 
+        0x27, 0x0c, 0x46, 0xc0, 0x00, 0x00, 0x0c, 0xf4, 0x0c, 0x35, 0x0c, 0x36, 0xd0, 0x30, 0x04, 0x0c, 
+        0x12, 0x08, 0x0c, 0x0c, 0x0e, 0x02, 0x20, 0x27, 0x30, 0xe2, 0x83, 0x7d, 0x0e, 0x22, 0xa0, 0x77, 
+        0x0c, 0x03, 0xc0, 0x00, 0x00, 0x7d, 0x0e, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0x84, 0x08, 0x0c, 
+        0x0c, 0x05, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0x7d, 0x0d, 0x22, 0xa0, 0x77, 0x0c, 
+        0x03, 0x1c, 0xc4, 0x08, 0x0c, 0x0c, 0x05, 0x02, 0x20, 0x27, 0x0c, 0x06, 0xc0, 0x00, 0x00, 0xc8, 
+        0x21, 0xd8, 0x31, 0xe8, 0x41, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x22, 0xa0, 0x62, 0x0c, 
+        0x13, 0x0c, 0x04, 0x0c, 0x65, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xc1, 0x1b, 0xf7, 0x09, 0x01, 0x08, 
+        0x0c, 0x0c, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 
+        0x0c, 0x04, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 
+        0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 0x65, 0x08, 0x0c, 
+        0x0c, 0x66, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x00, 0xd0, 0x41, 
+        0x00, 0x00, 0x80, 0x43, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x80, 0x44, 0x00, 0x00, 0x00, 0xc2, 
+        0x12, 0xc1, 0xe0, 0xd9, 0x31, 0x09, 0x11, 0xc9, 0x21, 0xe9, 0x41, 0xcd, 0x05, 0xe1, 0xf5, 0xff, 
+        0x8c, 0xd3, 0x26, 0x13, 0x08, 0x66, 0x23, 0x08, 0xe1, 0xf4, 0xff, 0x86, 0x00, 0x00, 0xe1, 0xf3, 
+        0xff, 0xd1, 0xf3, 0xff, 0x60, 0x22, 0x11, 0x20, 0x24, 0x80, 0xe0, 0x22, 0x11, 0xc5, 0x62, 0x0b, 
+        0x51, 0xf1, 0xff, 0x0c, 0x04, 0xc5, 0xdd, 0x0a, 0x45, 0xf4, 0x0a, 0x29, 0x01, 0x31, 0xee, 0xff, 
+        0x2d, 0x0e, 0x85, 0x79, 0x0a, 0x3d, 0x02, 0x28, 0x01, 0x45, 0x8f, 0x0a, 0x31, 0xec, 0xff, 0x05, 
+        0x53, 0x0a, 0xed, 0x02, 0x45, 0x9e, 0x0a, 0x22, 0x4c, 0x00, 0x20, 0x20, 0x74, 0x05, 0x5c, 0x0b, 
+        0x3d, 0x02, 0x2d, 0x0e, 0x05, 0x60, 0x0a, 0x3d, 0x0d, 0x05, 0x77, 0x0a, 0xed, 0x02, 0xc5, 0x9c, 
+        0x0a, 0x22, 0x4c, 0x01, 0x20, 0x20, 0x74, 0x85, 0x5a, 0x0b, 0x3d, 0x02, 0x2d, 0x0e, 0x85, 0x5e, 
+        0x0a, 0x3d, 0x0d, 0x85, 0x75, 0x0a, 0x45, 0x9b, 0x0a, 0x08, 0x11, 0xd8, 0x31, 0x22, 0x4c, 0x02, 
+        0xe8, 0x41, 0xc8, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x91, 0x43, 0x10, 0x40, 
+        0xb4, 0x09, 0x00, 0x00, 0xf3, 0x43, 0x10, 0x40, 0xb8, 0x8b, 0xfe, 0x3f, 0x31, 0x45, 0x10, 0x40, 
+        0x6c, 0x09, 0x00, 0x00, 0xa8, 0x09, 0x00, 0x00, 0xa3, 0x09, 0x00, 0x00, 0x9e, 0x09, 0x00, 0x00, 
+        0x99, 0x09, 0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0x8f, 0x09, 0x00, 0x00, 0x8a, 0x09, 0x00, 0x00, 
+        0x85, 0x09, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x7b, 0x09, 0x00, 0x00, 0x76, 0x09, 0x00, 0x00, 
+        0x71, 0x09, 0x00, 0x00, 0x12, 0xc1, 0xd0, 0xc9, 0x61, 0x49, 0xa1, 0x69, 0x41, 0x39, 0x31, 0x09, 
+        0x51, 0xe9, 0x81, 0xd9, 0x71, 0xf9, 0x91, 0xdd, 0x02, 0xfd, 0x04, 0x2d, 0x05, 0x29, 0x21, 0xa6, 
+        0x1d, 0x0c, 0x0c, 0xd0, 0xd7, 0x20, 0x07, 0x0b, 0xed, 0xe0, 0xe0, 0x74, 0x46, 0x00, 0x00, 0x0c, 
+        0xde, 0x41, 0x91, 0xfe, 0xc1, 0xb9, 0xf6, 0x31, 0x37, 0xf0, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xf2, 
+        0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x37, 0x22, 0x63, 0xf2, 0xc0, 0x00, 
+        0x00, 0x0c, 0xe5, 0x57, 0xbd, 0x34, 0x71, 0xd9, 0xff, 0xd0, 0x6d, 0x90, 0x7a, 0x66, 0xa0, 0x06, 
+        0x00, 0x86, 0x09, 0x00, 0xc6, 0x79, 0x00, 0x06, 0x91, 0x00, 0x46, 0x8e, 0x00, 0x86, 0x8b, 0x00, 
+        0xc6, 0x88, 0x00, 0x06, 0x86, 0x00, 0x46, 0x83, 0x00, 0x86, 0x80, 0x00, 0xc6, 0x7d, 0x00, 0x06, 
+        0x7b, 0x00, 0x46, 0x78, 0x00, 0x86, 0x75, 0x00, 0xc6, 0x72, 0x00, 0x81, 0xcd, 0xff, 0x89, 0x11, 
+        0x56, 0x9f, 0x05, 0x98, 0x31, 0x3c, 0xb0, 0xf6, 0x29, 0x52, 0x0b, 0xa9, 0x56, 0xea, 0x13, 0x42, 
+        0xaf, 0xb7, 0xb2, 0xaf, 0x83, 0xa2, 0xa0, 0x76, 0x5c, 0xe3, 0x5c, 0xd9, 0x5c, 0xc5, 0x5c, 0xb6, 
+        0x0c, 0xee, 0xe7, 0x3d, 0x02, 0x86, 0x83, 0x00, 0x21, 0xc3, 0xff, 0xd0, 0xfd, 0x90, 0x2a, 0xff, 
+        0xa0, 0x0f, 0x00, 0x06, 0x80, 0x00, 0x06, 0x20, 0x00, 0x86, 0x82, 0x00, 0x46, 0xad, 0x00, 0xc6, 
+        0xa9, 0x00, 0x06, 0xa6, 0x00, 0x06, 0x83, 0x00, 0x86, 0xa2, 0x00, 0x46, 0x9e, 0x00, 0x46, 0x9a, 
+        0x00, 0xc6, 0x96, 0x00, 0x86, 0x92, 0x00, 0x06, 0x8f, 0x00, 0x86, 0x8b, 0x00, 0x00, 0x0e, 0x40, 
+        0x38, 0x21, 0xd8, 0x41, 0x38, 0x03, 0xd0, 0xde, 0xa0, 0x30, 0x30, 0x91, 0x07, 0xe3, 0x35, 0x4d, 
+        0x0f, 0x38, 0x31, 0x28, 0x11, 0x5d, 0x01, 0x85, 0xe1, 0xff, 0x00, 0x1e, 0x40, 0x0c, 0x12, 0x08, 
+        0x21, 0x32, 0x01, 0x02, 0x52, 0x01, 0x01, 0x42, 0x01, 0x00, 0x80, 0x55, 0x11, 0x00, 0x44, 0x11, 
+        0x50, 0x44, 0x20, 0x40, 0x33, 0x20, 0x39, 0x0d, 0xf8, 0x00, 0x00, 0x22, 0xa1, 0x20, 0xff, 0x20, 
+        0xf9, 0x00, 0x06, 0x08, 0x00, 0x78, 0x0d, 0x70, 0x70, 0xf5, 0x72, 0x41, 0x00, 0x68, 0x0d, 0x60, 
+        0x68, 0x41, 0x62, 0x41, 0x01, 0x08, 0x0d, 0x06, 0x02, 0x00, 0x62, 0x41, 0x00, 0x32, 0xaf, 0xb1, 
+        0x32, 0x41, 0x01, 0x02, 0x41, 0x02, 0x08, 0x0c, 0x02, 0x20, 0x38, 0x2d, 0x01, 0xc0, 0x00, 0x00, 
+        0x08, 0x0c, 0x02, 0x20, 0x36, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 0x0c, 0x13, 0x0c, 0x04, 0x0c, 
+        0x45, 0x08, 0x0c, 0x0c, 0x06, 0x02, 0x20, 0x27, 0x0c, 0x87, 0xc0, 0x00, 0x00, 0x0c, 0x0d, 0xf2, 
+        0xa0, 0x63, 0xe2, 0xa0, 0x64, 0x1c, 0x42, 0x01, 0x02, 0xf1, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x62, 
+        0x0c, 0x13, 0x0c, 0x74, 0x08, 0x0c, 0x0c, 0x75, 0x02, 0x20, 0x25, 0x0c, 0x76, 0xc0, 0x00, 0x00, 
+        0xdc, 0x22, 0xf7, 0x9d, 0x08, 0x21, 0x88, 0xff, 0x01, 0x88, 0xf6, 0xc0, 0x00, 0x00, 0x1b, 0xdd, 
+        0xd0, 0xd0, 0x74, 0xe7, 0x9d, 0xce, 0x08, 0x11, 0x31, 0x32, 0xfe, 0xc0, 0x20, 0x00, 0x21, 0xd5, 
+        0xef, 0xf2, 0x22, 0xf2, 0x30, 0xff, 0x10, 0xc0, 0x20, 0x00, 0xc8, 0x61, 0xd8, 0x71, 0xf2, 0x62, 
+        0xf2, 0xe8, 0x81, 0xf8, 0x91, 0x2d, 0x00, 0x08, 0x51, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x3c, 0x04, 
+        0x3c, 0x2e, 0x32, 0xa0, 0x66, 0xb2, 0xaf, 0x91, 0x52, 0xaf, 0xbb, 0x6c, 0x69, 0x1c, 0x16, 0x3c, 
+        0x1a, 0x0c, 0xe7, 0x77, 0xbd, 0x34, 0xf1, 0x75, 0xff, 0xd0, 0x8d, 0x90, 0xfa, 0x88, 0xa0, 0x08, 
+        0x00, 0x86, 0x09, 0x00, 0x06, 0x0f, 0x00, 0xc6, 0x09, 0x00, 0xc6, 0x3c, 0x00, 0x06, 0x3d, 0x00, 
+        0x46, 0x40, 0x00, 0x46, 0x08, 0x00, 0x46, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x3b, 0x00, 0x06, 
+        0x27, 0x00, 0x46, 0x33, 0x00, 0x86, 0x33, 0x00, 0x86, 0x05, 0x00, 0x4d, 0x0e, 0x62, 0xaf, 0xcc, 
+        0xbd, 0x06, 0x5d, 0x06, 0x0d, 0x0b, 0xad, 0x04, 0x3d, 0x05, 0x4d, 0x0a, 0x02, 0x41, 0x01, 0x06, 
+        0x01, 0x00, 0x4d, 0x0e, 0x32, 0x41, 0x01, 0x0d, 0x03, 0x42, 0x41, 0x00, 0xc6, 0xc0, 0xff, 0x01, 
+        0x60, 0xff, 0x09, 0x11, 0x06, 0x8e, 0xff, 0x21, 0x5f, 0xff, 0x29, 0x11, 0x06, 0x8c, 0xff, 0x31, 
+        0x5e, 0xff, 0x39, 0x11, 0x06, 0x8a, 0xff, 0x41, 0x5d, 0xff, 0x49, 0x11, 0x06, 0x88, 0xff, 0x51, 
+        0x5c, 0xff, 0x59, 0x11, 0x06, 0x86, 0xff, 0x61, 0x5b, 0xff, 0x69, 0x11, 0x06, 0x84, 0xff, 0x71, 
+        0x5a, 0xff, 0x79, 0x11, 0x06, 0x82, 0xff, 0x81, 0x59, 0xff, 0x89, 0x11, 0x06, 0x80, 0xff, 0x91, 
+        0x58, 0xff, 0x99, 0x11, 0x06, 0x7e, 0xff, 0xa1, 0x57, 0xff, 0xa9, 0x11, 0x06, 0x7c, 0xff, 0xb1, 
+        0x56, 0xff, 0xb9, 0x11, 0x06, 0x7a, 0xff, 0x01, 0x55, 0xff, 0x09, 0x11, 0x06, 0x78, 0xff, 0x21, 
+        0x54, 0xff, 0x29, 0x11, 0x06, 0x76, 0xff, 0x6d, 0x03, 0xbd, 0x06, 0x3d, 0x06, 0x9d, 0x0b, 0x4d, 
+        0x0a, 0x92, 0x41, 0x01, 0xc6, 0xdf, 0xff, 0x0d, 0x0a, 0x32, 0xa0, 0x62, 0x5c, 0xf4, 0x42, 0x41, 
+        0x00, 0x32, 0x41, 0x01, 0xc6, 0x9e, 0xff, 0x62, 0x41, 0x00, 0x02, 0xaf, 0xdf, 0x7c, 0x25, 0x52, 
+        0x41, 0x01, 0x46, 0x9b, 0xff, 0x52, 0x41, 0x00, 0x02, 0xa0, 0x6f, 0x7c, 0x96, 0x62, 0x41, 0x01, 
+        0xc6, 0x97, 0xff, 0x5d, 0x06, 0x0d, 0x05, 0x3d, 0x05, 0x4d, 0x0e, 0x02, 0x41, 0x01, 0x46, 0xd1, 
+        0xff, 0x3d, 0x05, 0x9d, 0x03, 0x5d, 0x03, 0x0d, 0x09, 0xad, 0x04, 0x46, 0xca, 0xff, 0x3d, 0x05, 
+        0x9d, 0x03, 0x46, 0xea, 0xff, 0x5d, 0x06, 0x0d, 0x05, 0xc6, 0xc6, 0xff, 0x32, 0x41, 0x00, 0x6c, 
+        0xc0, 0x32, 0xaf, 0xc4, 0x06, 0x8a, 0xff, 0x32, 0x41, 0x00, 0xb2, 0x41, 0x01, 0x4c, 0x80, 0x06, 
+        0x88, 0xff, 0x32, 0x41, 0x00, 0x02, 0xaf, 0xa4, 0x4c, 0x17, 0x72, 0x41, 0x01, 0x86, 0x84, 0xff, 
+        0x0c, 0x00, 0x02, 0x41, 0x01, 0x32, 0x41, 0x00, 0xc6, 0x81, 0xff, 0x0d, 0x06, 0x3d, 0x09, 0x82, 
+        0xaf, 0xbe, 0x82, 0x41, 0x01, 0x06, 0xfb, 0xff, 0x92, 0x41, 0x00, 0x02, 0xa0, 0x7c, 0x02, 0x41, 
+        0x01, 0x0d, 0x04, 0x06, 0x7b, 0xff, 0x92, 0x41, 0x00, 0x1c, 0x34, 0xc6, 0xfb, 0xff, 0x52, 0x41, 
+        0x00, 0x42, 0x41, 0x01, 0x02, 0xaf, 0xcb, 0x06, 0x76, 0xff, 0x52, 0x41, 0x00, 0xa2, 0x41, 0x01, 
+        0x2c, 0x70, 0x46, 0x73, 0xff, 0x0d, 0x0b, 0x52, 0x41, 0x00, 0x3c, 0x49, 0x92, 0x41, 0x01, 0x06, 
+        0x70, 0xff, 0x00, 0x00, 0xb4, 0xf6, 0xfe, 0x3f, 0x11, 0x47, 0x10, 0x40, 0x60, 0x09, 0x00, 0x00, 
+        0x08, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x81, 0xfb, 0xff, 0x9d, 0x04, 0x12, 0xc1, 0xe0, 
+        0xc9, 0x11, 0xe9, 0x31, 0xf9, 0x41, 0x09, 0x01, 0xd9, 0x21, 0x4d, 0x05, 0xdd, 0x02, 0x22, 0x48, 
+        0x0c, 0x5d, 0x06, 0x99, 0x51, 0x6d, 0x07, 0x72, 0x11, 0x10, 0x85, 0xc3, 0xff, 0xfd, 0x02, 0x08, 
+        0x51, 0x0c, 0xe9, 0x97, 0xbd, 0x34, 0xb1, 0xf0, 0xff, 0xd0, 0xad, 0x90, 0xba, 0xaa, 0xa0, 0x0a, 
+        0x00, 0x86, 0x09, 0x00, 0x86, 0x2a, 0x00, 0xc6, 0x44, 0x00, 0xc6, 0x41, 0x00, 0xc6, 0x3e, 0x00, 
+        0xc6, 0x3b, 0x00, 0xc6, 0x38, 0x00, 0xc6, 0x35, 0x00, 0xc6, 0x32, 0x00, 0xc6, 0x2f, 0x00, 0xc6, 
+        0x2c, 0x00, 0xc6, 0x29, 0x00, 0xc6, 0x26, 0x00, 0xc6, 0x23, 0x00, 0xc2, 0xa0, 0x6a, 0xe2, 0xa1, 
+        0x08, 0xbc, 0xf0, 0x01, 0xc1, 0xf5, 0x21, 0xb8, 0xf0, 0xc0, 0x20, 0x00, 0x22, 0x22, 0x9c, 0x17, 
+        0xe2, 0x16, 0x22, 0xa0, 0x67, 0x01, 0xbc, 0xf5, 0x0c, 0x43, 0x08, 0x00, 0x0c, 0x74, 0x02, 0x20, 
+        0x26, 0x0c, 0x45, 0xc0, 0x00, 0x00, 0x01, 0xb8, 0xf5, 0xe0, 0x3f, 0x82, 0x0c, 0x12, 0x08, 0x00, 
+        0x41, 0xd7, 0xff, 0x02, 0x20, 0x1f, 0x40, 0x4e, 0xc1, 0xc0, 0x00, 0x00, 0x0c, 0x52, 0x01, 0x50, 
+        0xf0, 0xc0, 0x00, 0x00, 0xf0, 0x3f, 0x20, 0xd0, 0x2d, 0x20, 0x71, 0xd2, 0xff, 0x81, 0xd0, 0xff, 
+        0x61, 0xc3, 0xf3, 0x8a, 0x8c, 0xf0, 0x88, 0x01, 0xc0, 0x20, 0x00, 0x52, 0x26, 0x45, 0x50, 0x50, 
+        0xc4, 0x80, 0x55, 0x20, 0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 0x45, 0x05, 0x29, 0xfe, 
+        0xc5, 0x56, 0xfe, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0xc2, 0xa2, 0xe1, 0xe2, 0xa1, 0x09, 0x46, 0xdd, 0xff, 0xc2, 0xa0, 0xd1, 0xe2, 0xa1, 
+        0x08, 0x06, 0xdb, 0xff, 0xc2, 0xa0, 0xfc, 0xe2, 0xa1, 0x08, 0xc6, 0xd8, 0xff, 0xc2, 0xa1, 0x27, 
+        0xe2, 0xa1, 0x02, 0x86, 0xd6, 0xff, 0xc2, 0xa1, 0x53, 0xe2, 0xa1, 0x01, 0x46, 0xd4, 0xff, 0xc2, 
+        0xa1, 0x7e, 0xe2, 0xa1, 0x08, 0x06, 0xd2, 0xff, 0xc2, 0xa1, 0xaa, 0xe2, 0xa1, 0x1b, 0xc6, 0xcf, 
+        0xff, 0xc2, 0xa1, 0xd6, 0xe2, 0xa0, 0xff, 0x86, 0xcd, 0xff, 0xc2, 0xa2, 0x02, 0xe2, 0xa1, 0x0d, 
+        0x46, 0xcb, 0xff, 0xc2, 0xa2, 0x2e, 0xe2, 0xa1, 0x09, 0x06, 0xc9, 0xff, 0xc2, 0xa2, 0x5a, 0xe2, 
+        0xa1, 0x09, 0xc6, 0xc6, 0xff, 0xc2, 0xa2, 0x87, 0xe2, 0xa1, 0x08, 0x86, 0xc4, 0xff, 0xe2, 0xa1, 
+        0x05, 0xc2, 0xa2, 0xb4, 0x46, 0xc2, 0xff, 0x00, 0xd8, 0x8b, 0xfe, 0x3f, 0x42, 0xc2, 0xff, 0x12, 
+        0xc1, 0xe0, 0x02, 0x61, 0x04, 0xd2, 0x61, 0x06, 0x00, 0x14, 0x40, 0xc9, 0x51, 0x7c, 0xf4, 0xcd, 
+        0x02, 0xdd, 0x03, 0x21, 0xcd, 0xfc, 0x0c, 0x13, 0x00, 0x33, 0xa1, 0x40, 0x33, 0x30, 0x08, 0x12, 
+        0x4d, 0x0d, 0x30, 0x00, 0x10, 0x09, 0x12, 0x3d, 0x0c, 0x21, 0xf3, 0xff, 0x01, 0xa3, 0xf5, 0xc0, 
+        0x00, 0x00, 0x5d, 0x0d, 0x2d, 0x0c, 0x0c, 0x04, 0x61, 0xf5, 0xf9, 0x31, 0x17, 0xfc, 0x72, 0xa0, 
+        0x64, 0x32, 0x03, 0x01, 0x79, 0x01, 0x4b, 0x76, 0xc5, 0xe4, 0xff, 0x2d, 0x0c, 0x45, 0x13, 0xfe, 
+        0xc8, 0x51, 0xd8, 0x61, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x54, 0xf7, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x06, 0x09, 0x51, 0xcd, 0x02, 0x45, 0x9c, 0xfd, 0x0c, 0x04, 0x02, 
+        0xa0, 0x64, 0x31, 0x09, 0xfc, 0x51, 0xf9, 0xff, 0x29, 0x41, 0x61, 0xe4, 0xf9, 0x2d, 0x0c, 0x4b, 
+        0x76, 0x52, 0x95, 0x00, 0x32, 0x03, 0x01, 0x09, 0x01, 0xc5, 0xe0, 0xff, 0x2d, 0x0c, 0x45, 0x0f, 
+        0xfe, 0x28, 0x41, 0xc5, 0x97, 0xfd, 0xc8, 0x61, 0x08, 0x51, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 
+        0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0xcf, 
+        0x61, 0x57, 0xf6, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x29, 0x01, 0xc9, 0x21, 0xd9, 0x31, 0x51, 0xd1, 
+        0xee, 0xd1, 0xc3, 0xed, 0xc1, 0x51, 0xf5, 0xc0, 0x20, 0x00, 0x42, 0x25, 0xfa, 0x60, 0x44, 0x10, 
+        0xc0, 0x20, 0x00, 0x42, 0x65, 0xfa, 0x31, 0xa6, 0xfc, 0xc0, 0x20, 0x00, 0x22, 0x2d, 0x44, 0x30, 
+        0x22, 0x20, 0xc0, 0x20, 0x00, 0x0c, 0x23, 0x0c, 0x04, 0x2c, 0x75, 0x08, 0x0c, 0x22, 0x6d, 0x44, 
+        0x02, 0x20, 0x26, 0x22, 0xa0, 0x6a, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x35, 0xc0, 0x00, 
+        0x00, 0x21, 0xe7, 0xff, 0x31, 0x39, 0xf0, 0xc0, 0x20, 0x00, 0x02, 0x2d, 0x44, 0x20, 0x00, 0x20, 
+        0xc0, 0x20, 0x00, 0x02, 0x6d, 0x44, 0xb1, 0xe3, 0xff, 0xa1, 0xe3, 0xff, 0xc0, 0x20, 0x00, 0x61, 
+        0xb9, 0xee, 0x92, 0x26, 0xe8, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x66, 
+        0xe8, 0x81, 0xde, 0xff, 0x71, 0x92, 0xf9, 0xc0, 0x20, 0x00, 0x52, 0x26, 0xe6, 0x80, 0x55, 0x10, 
+        0x70, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x66, 0xe6, 0x7c, 0xd4, 0xc0, 0x20, 0x00, 0x22, 0x23, 
+        0x9c, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x9c, 0x0c, 0x22, 0x01, 0xc9, 0xef, 0xc0, 
+        0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x28, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 0x0c, 0x0c, 0x13, 
+        0x02, 0x20, 0x2b, 0x42, 0xa0, 0x81, 0xc0, 0x00, 0x00, 0x31, 0x3e, 0xf3, 0xc0, 0x20, 0x00, 0x22, 
+        0x2d, 0x44, 0x30, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x32, 0x22, 0x6d, 0x44, 
+        0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 0x23, 0x08, 0x0c, 0x0c, 0x04, 0x02, 0x20, 0x26, 0x2c, 
+        0x45, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x31, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6a, 0x0c, 
+        0x23, 0x08, 0x0c, 0x0c, 0x04, 0x02, 0x20, 0x26, 0x2c, 0x55, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 
+        0x20, 0x2f, 0xd8, 0x01, 0xc0, 0x00, 0x00, 0x62, 0xa9, 0xff, 0x31, 0xb2, 0xed, 0xc0, 0x20, 0x00, 
+        0x52, 0x23, 0xd0, 0x60, 0x55, 0x10, 0xc0, 0x20, 0x00, 0x52, 0x63, 0xd0, 0x7c, 0x34, 0xc0, 0x20, 
+        0x00, 0x22, 0x23, 0xd0, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xd0, 0x2d, 0x0d, 0x05, 
+        0xe7, 0xff, 0x08, 0x0c, 0x02, 0x20, 0x23, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6b, 0x0c, 0x23, 0x08, 
+        0x0c, 0x0c, 0x14, 0x02, 0x20, 0x26, 0x4c, 0x85, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 0x20, 0x22, 
+        0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x0c, 0x05, 0x08, 0x0c, 0x0c, 0x06, 
+        0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x6c, 0x0c, 0x23, 0x0c, 0x04, 0x0c, 
+        0x25, 0x08, 0x0c, 0x0c, 0x26, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x08, 0x0c, 0x02, 
+        0x20, 0x13, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x45, 0x08, 0x0c, 
+        0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 
+        0xa4, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 0x22, 
+        0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x45, 0x08, 0x0c, 0x0c, 0x46, 0x02, 0x20, 0x27, 0x0c, 
+        0x17, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xa4, 0x0c, 0x55, 0x08, 0x0c, 0x0c, 
+        0x56, 0x02, 0x20, 0x27, 0x0c, 0x17, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0xc8, 0x21, 0xd8, 0x31, 0x08, 
+        0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x26, 0x42, 0x14, 0x26, 0xb2, 0x09, 0x1c, 0x23, 
+        0x37, 0x12, 0x10, 0x1c, 0x44, 0x47, 0x12, 0x03, 0x0c, 0x12, 0x0d, 0xf0, 0x0c, 0x32, 0x0d, 0xf0, 
+        0x0c, 0x02, 0x0d, 0xf0, 0x0c, 0x22, 0x0d, 0xf0, 0x8c, 0xf2, 0x26, 0x12, 0x05, 0x26, 0x22, 0x0e, 
+        0x26, 0x32, 0x03, 0x1c, 0x02, 0x0d, 0xf0, 0x1c, 0x42, 0x0d, 0xf0, 0x0c, 0x42, 0x0d, 0xf0, 0x1c, 
+        0x22, 0x0d, 0xf0, 0x00, 0x22, 0x80, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x01, 0xc6, 0xf4, 
+        0x21, 0xfd, 0xff, 0x08, 0x00, 0x22, 0x12, 0x00, 0x02, 0x20, 0x29, 0x20, 0x20, 0x44, 0xc0, 0x00, 
+        0x00, 0x01, 0xc1, 0xf4, 0x0c, 0x12, 0x08, 0x00, 0x0c, 0x13, 0x02, 0x20, 0x2b, 0x1c, 0xf4, 0xc0, 
+        0x00, 0x00, 0x21, 0xf4, 0xff, 0x3d, 0x01, 0x22, 0x12, 0x00, 0xc5, 0x0b, 0x00, 0x01, 0xba, 0xf4, 
+        0x08, 0x00, 0x02, 0x20, 0x2a, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0xff, 0x00, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0xf0, 0x00, 0xc0, 0xff, 0xff, 0x80, 0x92, 0x11, 0x81, 
+        0xfc, 0xff, 0x71, 0x30, 0xee, 0xb1, 0xfb, 0xff, 0xa1, 0xfc, 0xff, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 
+        0xe9, 0x31, 0x09, 0x01, 0xd9, 0x21, 0x0c, 0x00, 0x1c, 0x8d, 0x70, 0x50, 0xa0, 0xc0, 0x20, 0x00, 
+        0x42, 0x25, 0xc1, 0x80, 0x44, 0x10, 0x90, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x65, 0xc1, 0x00, 
+        0x21, 0x41, 0x70, 0x22, 0xa0, 0x62, 0x03, 0x01, 0x52, 0x03, 0x00, 0x80, 0x66, 0x01, 0x80, 0x55, 
+        0x01, 0x50, 0x58, 0x31, 0x60, 0x68, 0x31, 0x07, 0x60, 0x1d, 0x20, 0xe5, 0x11, 0xb0, 0x46, 0x01, 
+        0xc0, 0x20, 0x00, 0xc2, 0x22, 0x81, 0xb0, 0xcc, 0x10, 0x40, 0xcc, 0x20, 0xe0, 0xcc, 0x20, 0xc0, 
+        0x20, 0x00, 0xc2, 0x62, 0x81, 0xc6, 0x05, 0x00, 0x90, 0x46, 0x11, 0xc0, 0x20, 0x00, 0xe2, 0x22, 
+        0x81, 0xa0, 0xee, 0x10, 0x40, 0xee, 0x20, 0x50, 0xee, 0x20, 0xc0, 0x20, 0x00, 0xe2, 0x62, 0x81, 
+        0x1b, 0x00, 0x00, 0x00, 0x74, 0xd7, 0x90, 0x91, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x20, 0x44, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 
+        0x09, 0x01, 0xcd, 0x03, 0x05, 0xec, 0xff, 0x0c, 0x23, 0x01, 0x87, 0xf4, 0x5d, 0x02, 0x61, 0xd6, 
+        0xfb, 0x0c, 0x02, 0x60, 0x55, 0x90, 0x62, 0x15, 0x20, 0x62, 0x4c, 0x00, 0x42, 0x0c, 0x00, 0x52, 
+        0x15, 0x20, 0x80, 0x44, 0x01, 0x50, 0x58, 0x41, 0x52, 0x4c, 0x01, 0x08, 0x00, 0x40, 0x48, 0x31, 
+        0x02, 0x20, 0x2b, 0x40, 0x40, 0xf4, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x0c, 0x23, 0x42, 0x0c, 0x01, 
+        0x01, 0x7a, 0xf4, 0x80, 0x44, 0x01, 0x08, 0x00, 0x40, 0x48, 0x31, 0x02, 0x20, 0x2b, 0x40, 0x40, 
+        0xf4, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0x29, 0x41, 0x09, 0x71, 0x2d, 0x01, 0x45, 0x44, 0x00, 0x0c, 0x33, 0x22, 0x11, 
+        0x03, 0x92, 0x11, 0x05, 0x42, 0x11, 0x04, 0x82, 0x11, 0x07, 0x52, 0x11, 0x06, 0x72, 0x11, 0x02, 
+        0x01, 0x6a, 0xf4, 0x62, 0x11, 0x01, 0x08, 0x00, 0x7a, 0x66, 0x8a, 0x55, 0x9a, 0x44, 0x08, 0xe0, 
+        0x40, 0x44, 0x90, 0x50, 0x55, 0x90, 0x6a, 0x22, 0x50, 0x22, 0xd0, 0x50, 0x44, 0xc0, 0x00, 0x44, 
+        0x11, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x40, 0x40, 0x31, 0x49, 0x51, 0xc0, 0x00, 0x00, 0x01, 
+        0x5e, 0xf4, 0x0c, 0x33, 0x08, 0x00, 0x29, 0x61, 0x08, 0xe0, 0x28, 0x51, 0xc0, 0x00, 0x00, 0x38, 
+        0x61, 0x08, 0x71, 0x20, 0x33, 0xc0, 0x28, 0x41, 0x12, 0xc1, 0x20, 0x3a, 0x22, 0x00, 0x22, 0x11, 
+        0x20, 0x20, 0x31, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xad, 0x06, 0xbd, 0x05, 0x9d, 0x03, 0x82, 0xaf, 
+        0x79, 0x12, 0xc1, 0xd0, 0xf9, 0x81, 0x09, 0x41, 0xd9, 0x61, 0xc9, 0x51, 0xe9, 0x71, 0xcd, 0x02, 
+        0xed, 0x04, 0xd2, 0xd1, 0xff, 0x0c, 0x04, 0xd2, 0xcd, 0x7d, 0xda, 0x24, 0x16, 0x34, 0x05, 0x26, 
+        0x14, 0x4a, 0x26, 0x24, 0x41, 0x26, 0x34, 0x38, 0x26, 0x44, 0x24, 0x26, 0x54, 0x1b, 0x26, 0x64, 
+        0x12, 0x26, 0x74, 0x09, 0x4a, 0x0c, 0x8a, 0x00, 0x02, 0x00, 0x7f, 0x06, 0x05, 0x00, 0x02, 0x0c, 
+        0x00, 0x86, 0x03, 0x00, 0x02, 0x0c, 0x02, 0x06, 0x02, 0x00, 0x02, 0x0c, 0x04, 0x86, 0x00, 0x00, 
+        0x02, 0x0c, 0x06, 0x02, 0x42, 0x83, 0x1b, 0x44, 0x40, 0x40, 0x74, 0x66, 0xb4, 0xbb, 0xc6, 0x05, 
+        0x00, 0x02, 0x0c, 0x00, 0xc6, 0xfa, 0xff, 0x02, 0x0c, 0x01, 0x46, 0xf9, 0xff, 0x02, 0x0c, 0x03, 
+        0xc6, 0xf7, 0xff, 0x02, 0x0c, 0x05, 0x46, 0xf6, 0xff, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x0c, 0x94, 
+        0x0c, 0x75, 0x0c, 0x06, 0x0c, 0x07, 0x01, 0x30, 0xf4, 0x99, 0x91, 0x08, 0x00, 0xa9, 0xa1, 0x02, 
+        0x20, 0x27, 0xb9, 0xb1, 0xc0, 0x00, 0x00, 0x28, 0xa1, 0x38, 0x91, 0x0c, 0x04, 0x1c, 0x8b, 0x61, 
+        0xa9, 0xed, 0xa2, 0xaf, 0x00, 0x08, 0xb1, 0xf1, 0x47, 0xfe, 0x8c, 0xa0, 0x26, 0x24, 0x25, 0x26, 
+        0x34, 0x22, 0x26, 0x64, 0x1f, 0x26, 0x74, 0x1c, 0x0c, 0x05, 0x60, 0x84, 0xa0, 0xf6, 0x84, 0x2e, 
+        0x80, 0x75, 0x01, 0x52, 0x0c, 0x00, 0x70, 0x78, 0x31, 0x7a, 0x55, 0x5a, 0x5e, 0x52, 0x05, 0x00, 
+        0x3a, 0x55, 0x86, 0x0b, 0x00, 0x51, 0xc0, 0xfa, 0x92, 0x0f, 0x0c, 0x82, 0x05, 0x4e, 0x80, 0x99, 
+        0x01, 0x52, 0x05, 0x4d, 0x90, 0x98, 0x31, 0xe6, 0x79, 0xcf, 0x5d, 0x08, 0x86, 0xf2, 0xff, 0xda, 
+        0x54, 0x52, 0x05, 0x7b, 0xea, 0x55, 0x52, 0x05, 0x00, 0x80, 0x55, 0x01, 0x50, 0x58, 0x31, 0x27, 
+        0xa5, 0x01, 0x5d, 0x02, 0x50, 0x90, 0x60, 0x90, 0x90, 0x74, 0xc0, 0x20, 0x00, 0x72, 0x28, 0xc1, 
+        0xa0, 0x77, 0x10, 0x90, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x68, 0xc1, 0x1b, 0x44, 0x40, 0x40, 
+        0x74, 0xb7, 0x94, 0x85, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 
+        0x30, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0xe0, 0x51, 0x17, 0xf2, 0x48, 
+        0x02, 0x81, 0xfc, 0xff, 0x17, 0x74, 0x0b, 0x22, 0x13, 0x00, 0x20, 0x38, 0x41, 0x80, 0x22, 0x01, 
+        0x20, 0x28, 0x31, 0xe0, 0x62, 0x01, 0x80, 0x73, 0x01, 0x80, 0x66, 0x20, 0x81, 0xf7, 0xff, 0xc0, 
+        0x20, 0x00, 0x42, 0x25, 0x98, 0x80, 0x44, 0x10, 0x70, 0x44, 0x20, 0x60, 0x44, 0x20, 0xc0, 0x20, 
+        0x00, 0x42, 0x65, 0x98, 0x0d, 0xf0, 0x00, 0x00, 0x2b, 0x64, 0x82, 0x93, 0x00, 0x00, 0x04, 0x40, 
+        0x80, 0x90, 0xb1, 0x90, 0x88, 0xc0, 0x00, 0x16, 0x40, 0x8a, 0x82, 0x00, 0x25, 0xa1, 0x00, 0x88, 
+        0x11, 0x80, 0x80, 0x31, 0x82, 0x53, 0x00, 0x27, 0x28, 0x11, 0x20, 0x48, 0xc0, 0x80, 0x25, 0x01, 
+        0x20, 0x28, 0x31, 0x42, 0x53, 0x00, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x20, 0x40, 0x60, 0x87, 
+        0x24, 0xf5, 0x2a, 0x48, 0x50, 0x20, 0x60, 0x80, 0x22, 0x01, 0x20, 0x28, 0x31, 0x86, 0xf8, 0xff, 
+        0x22, 0xa0, 0x61, 0x0c, 0x13, 0x0c, 0x24, 0x0c, 0x45, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xde, 
+        0xf3, 0x0c, 0x06, 0x08, 0x00, 0x71, 0xfb, 0xfd, 0x02, 0x20, 0x27, 0x72, 0x07, 0x02, 0xc0, 0x00, 
+        0x00, 0x22, 0xa0, 0x66, 0x0c, 0x33, 0x0c, 0x14, 0x0c, 0x55, 0x01, 0xd7, 0xf3, 0x0c, 0x06, 0x08, 
+        0x00, 0x71, 0xf4, 0xfd, 0x02, 0x20, 0x27, 0x72, 0x07, 0x03, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xf8, 0x8b, 0xfe, 0x3f, 0x00, 0x8c, 0xfe, 0x3f, 0x12, 0xc1, 0xc0, 0xc9, 
+        0x71, 0xe9, 0x91, 0x69, 0x51, 0x79, 0xd1, 0x49, 0xc1, 0x59, 0x41, 0x09, 0x61, 0x29, 0xb1, 0xd9, 
+        0x81, 0xf9, 0xa1, 0xdd, 0x03, 0xfd, 0x07, 0x22, 0xa1, 0x38, 0x45, 0xd5, 0xff, 0xcd, 0x02, 0xb2, 
+        0xaf, 0x7a, 0xe2, 0x01, 0x40, 0xac, 0x7f, 0xb6, 0x8e, 0x09, 0xea, 0x0d, 0xba, 0x00, 0x02, 0x00, 
+        0x7f, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x21, 0xef, 0xff, 0x58, 0xb1, 0x3d, 0x0e, 0x5a, 0x50, 0x52, 
+        0x05, 0x00, 0x4d, 0x0c, 0xe0, 0x55, 0x11, 0x01, 0x46, 0xec, 0xc0, 0x00, 0x00, 0xb2, 0xaf, 0x7a, 
+        0xb6, 0x8e, 0x09, 0xea, 0x0d, 0xba, 0x00, 0x02, 0x00, 0x7f, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x38, 
+        0x41, 0x28, 0xb1, 0x0c, 0x44, 0x2a, 0x20, 0x22, 0x02, 0x00, 0x0c, 0x15, 0xe0, 0x22, 0x11, 0x20, 
+        0x2c, 0xc0, 0x00, 0x22, 0x11, 0x20, 0x20, 0x31, 0x29, 0x21, 0xc5, 0xee, 0xff, 0xcd, 0x02, 0xd9, 
+        0x31, 0x9c, 0x2f, 0x38, 0x21, 0x21, 0xdb, 0xff, 0x48, 0x41, 0x5d, 0x0c, 0x42, 0x94, 0x00, 0x01, 
+        0x34, 0xec, 0xc0, 0x00, 0x00, 0xd9, 0x31, 0x58, 0x51, 0xd1, 0x26, 0xed, 0x16, 0x75, 0x04, 0x16, 
+        0x4c, 0x04, 0x6d, 0x01, 0x0c, 0x04, 0x08, 0xc1, 0xd0, 0xa4, 0xa0, 0x6a, 0xb4, 0xc0, 0x20, 0x00, 
+        0x1b, 0x94, 0x4a, 0x80, 0xa2, 0x2a, 0xd3, 0xa2, 0x4b, 0x00, 0xc0, 0xaa, 0xc0, 0xa2, 0x4b, 0x00, 
+        0x72, 0x08, 0x00, 0x90, 0x40, 0x74, 0xc0, 0x77, 0xc0, 0x72, 0x48, 0x00, 0x66, 0x64, 0xd8, 0x28, 
+        0x31, 0x0c, 0xd3, 0x51, 0xb8, 0xfd, 0x4d, 0x01, 0x62, 0x05, 0x2c, 0x52, 0x05, 0x2d, 0x80, 0x66, 
+        0x01, 0x60, 0x68, 0x31, 0x05, 0xd0, 0xff, 0x9c, 0x3f, 0xd0, 0x3e, 0xa0, 0x21, 0xc3, 0xff, 0xc0, 
+        0x20, 0x00, 0x32, 0x23, 0xc1, 0x30, 0x30, 0x74, 0x01, 0x1a, 0xec, 0xc0, 0x00, 0x00, 0xc8, 0x71, 
+        0xd8, 0x81, 0xe8, 0x91, 0xf8, 0xa1, 0x08, 0x61, 0x12, 0xc1, 0x40, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x78, 0xf8, 0xfe, 0x3f, 0xc1, 0xf6, 0xfe, 0x3f, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x7f, 0xff, 
+        0x12, 0xc1, 0xe0, 0x09, 0x41, 0x51, 0x27, 0xec, 0xc0, 0x20, 0x00, 0x02, 0x25, 0xd8, 0x00, 0x08, 
+        0x45, 0xc0, 0x20, 0x00, 0x52, 0x25, 0xd4, 0xf7, 0xf5, 0x7c, 0x09, 0x01, 0x7d, 0x04, 0x5d, 0x02, 
+        0x6d, 0x03, 0x21, 0xf3, 0xff, 0x31, 0xab, 0xf4, 0x41, 0xf3, 0xff, 0x05, 0xeb, 0xff, 0x61, 0xf2, 
+        0xff, 0x7c, 0xea, 0xc0, 0x20, 0x00, 0x71, 0x1b, 0xec, 0x52, 0x27, 0xd7, 0x60, 0x55, 0x10, 0xc0, 
+        0x20, 0x00, 0x52, 0x67, 0xd7, 0x41, 0xed, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x27, 0xd7, 0x40, 0x33, 
+        0x10, 0xc0, 0x20, 0x00, 0x32, 0x67, 0xd7, 0xc0, 0x20, 0x00, 0x22, 0x27, 0xd4, 0xa0, 0x22, 0x10, 
+        0xc0, 0x20, 0x00, 0x22, 0x67, 0xd4, 0x0c, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x27, 0xd8, 0x00, 0xbb, 
+        0x20, 0xc0, 0x20, 0x00, 0xb2, 0x67, 0xd8, 0xc0, 0x20, 0x00, 0x92, 0x27, 0xd8, 0xa0, 0x99, 0x10, 
+        0xc0, 0x20, 0x00, 0x92, 0x67, 0xd8, 0xc0, 0x20, 0x00, 0x62, 0x27, 0xd8, 0x0c, 0x18, 0x80, 0x66, 
+        0x20, 0xc0, 0x20, 0x00, 0x62, 0x67, 0xd8, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0x91, 0x01, 0xec, 0x81, 0xf8, 0xed, 0x0c, 0x0b, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xd9, 
+        0x21, 0x0c, 0x00, 0xd2, 0xa0, 0xff, 0x7c, 0xfc, 0x90, 0x60, 0xa0, 0x20, 0x70, 0x90, 0x5d, 0x0d, 
+        0xad, 0x0b, 0xc0, 0x20, 0x00, 0x32, 0xa1, 0x17, 0x62, 0x26, 0xe0, 0x1b, 0x00, 0x00, 0x00, 0x74, 
+        0xc0, 0x66, 0x30, 0x60, 0x40, 0x74, 0x42, 0xc4, 0xeb, 0x60, 0x60, 0xa4, 0x62, 0x57, 0x00, 0x40, 
+        0xa4, 0xb3, 0x30, 0xaa, 0x82, 0x80, 0x36, 0x10, 0xa0, 0xa8, 0x21, 0xa7, 0x2d, 0x01, 0x5d, 0x0a, 
+        0x3a, 0x35, 0x32, 0x57, 0x00, 0x66, 0x80, 0xbf, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xe0, 0x09, 0x61, 0x39, 0x41, 0x29, 0x51, 0x7c, 0xd5, 0x21, 
+        0xe5, 0xeb, 0xc0, 0x20, 0x00, 0x42, 0x22, 0xd4, 0x50, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x62, 
+        0xd4, 0x0c, 0x23, 0xc0, 0x20, 0x00, 0x02, 0x22, 0xd4, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 
+        0x62, 0xd4, 0x1c, 0x92, 0x01, 0xd7, 0xed, 0xc0, 0x00, 0x00, 0x2d, 0x01, 0x05, 0xf6, 0xff, 0x28, 
+        0x51, 0x02, 0x11, 0x03, 0x42, 0x11, 0x02, 0x32, 0x11, 0x01, 0x92, 0x11, 0x07, 0x72, 0x11, 0x05, 
+        0x62, 0x11, 0x04, 0x82, 0x11, 0x06, 0x7a, 0x66, 0x9a, 0x88, 0x4a, 0x33, 0x3a, 0x00, 0x80, 0x88, 
+        0x90, 0x60, 0x66, 0x90, 0x60, 0x60, 0xf4, 0x80, 0x70, 0xf4, 0xf0, 0x90, 0x11, 0x90, 0x90, 0xf4, 
+        0x77, 0x39, 0x05, 0x80, 0x80, 0xd0, 0x46, 0x00, 0x00, 0x0c, 0x08, 0x82, 0x52, 0x00, 0x08, 0x41, 
+        0x77, 0x36, 0x05, 0x70, 0x26, 0xc0, 0x46, 0x00, 0x00, 0x0c, 0x02, 0x22, 0x50, 0x00, 0x08, 0x61, 
+        0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 
+        0x31, 0x6e, 0xfa, 0x0c, 0x02, 0x29, 0x13, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x90, 0xf8, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x66, 0x72, 0x0b, 0x01, 0xfd, 0xff, 0x08, 0x40, 0x0c, 0x02, 0xcc, 
+        0xc0, 0xc6, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x01, 
+        0x69, 0xef, 0xc0, 0x00, 0x00, 0x51, 0xf5, 0xff, 0x0c, 0x02, 0x38, 0x45, 0x39, 0x11, 0x48, 0x63, 
+        0x49, 0x45, 0x29, 0x63, 0x01, 0x65, 0xef, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x86, 0xf5, 0xff, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x21, 0x01, 0xed, 0xff, 0x29, 0x01, 0x08, 0x00, 0x0c, 0x02, 0xcc, 0x10, 
+        0x86, 0x0e, 0x00, 0x01, 0x5c, 0xef, 0xc0, 0x00, 0x00, 0x51, 0xe8, 0xff, 0x0c, 0x02, 0x38, 0x05, 
+        0x39, 0x11, 0x48, 0x63, 0x49, 0x05, 0x29, 0x63, 0x01, 0x58, 0xef, 0xc0, 0x00, 0x00, 0x78, 0x11, 
+        0x68, 0x01, 0x98, 0x77, 0xb1, 0x9e, 0xf8, 0xa8, 0x09, 0x2d, 0x07, 0xa0, 0x80, 0x54, 0xa0, 0xa6, 
+        0x41, 0xb0, 0xaa, 0x20, 0xa0, 0xaa, 0x11, 0xa0, 0x88, 0x20, 0x89, 0x09, 0x69, 0x37, 0x08, 0x21, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x0c, 0x02, 0x12, 0xc1, 
+        0xf0, 0x09, 0x01, 0x01, 0xd6, 0xff, 0x66, 0x43, 0x42, 0x38, 0x10, 0x16, 0xf3, 0x07, 0x01, 0x45, 
+        0xef, 0xc0, 0x00, 0x00, 0x71, 0xd2, 0xff, 0x0c, 0x04, 0x58, 0x17, 0x59, 0x11, 0x68, 0x65, 0x69, 
+        0x17, 0x49, 0x65, 0x01, 0x41, 0xef, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x98, 0x00, 0x88, 0x30, 0x89, 
+        0x19, 0x58, 0x70, 0x38, 0x05, 0x21, 0xf0, 0xff, 0x30, 0xa0, 0x54, 0x30, 0xb6, 0x41, 0x20, 0xbb, 
+        0x20, 0xa0, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xa9, 0x05, 0xc6, 0x0f, 0x00, 0x66, 0x53, 0x30, 0x38, 
+        0x20, 0xbc, 0x93, 0x01, 0x34, 0xef, 0xc0, 0x00, 0x00, 0x71, 0xc0, 0xff, 0x0c, 0x04, 0x58, 0x27, 
+        0x59, 0x11, 0x68, 0x65, 0x69, 0x27, 0x49, 0x65, 0x01, 0x30, 0xef, 0xc0, 0x00, 0x00, 0x08, 0x11, 
+        0x98, 0x00, 0x88, 0x30, 0x89, 0x19, 0x58, 0x70, 0x21, 0xd1, 0xec, 0x38, 0x05, 0xc6, 0xed, 0xff, 
+        0x66, 0x63, 0x06, 0xa8, 0x30, 0x8c, 0x5a, 0x86, 0x02, 0x00, 0x0d, 0x02, 0x2d, 0x00, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x01, 0x23, 0xef, 0xc0, 0x00, 0x00, 0x31, 0xb0, 0xff, 0x0c, 0x0b, 
+        0x08, 0x33, 0x09, 0x11, 0x28, 0x60, 0x29, 0x33, 0xb9, 0x60, 0x01, 0x1f, 0xef, 0xc0, 0x00, 0x00, 
+        0x08, 0x11, 0x58, 0x70, 0x21, 0xd6, 0xf4, 0x38, 0x05, 0xc6, 0xde, 0xff, 0xa4, 0x18, 0x00, 0x40, 
+        0x0b, 0x43, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x29, 0x01, 0x16, 0xd4, 0x0a, 0x52, 0xc3, 0xfe, 0x16, 
+        0x75, 0x0a, 0x66, 0x43, 0x25, 0x28, 0x72, 0x0c, 0x03, 0x1c, 0x84, 0x01, 0xf8, 0xff, 0xc0, 0x00, 
+        0x00, 0x01, 0x10, 0xef, 0xc0, 0x00, 0x00, 0x41, 0x9d, 0xff, 0x38, 0x01, 0x58, 0x14, 0x59, 0x63, 
+        0x39, 0x14, 0x01, 0x0d, 0xef, 0xc0, 0x00, 0x00, 0xc6, 0x1d, 0x00, 0x66, 0x53, 0x25, 0x28, 0x72, 
+        0x0c, 0x03, 0x1c, 0x84, 0x01, 0xee, 0xff, 0xc0, 0x00, 0x00, 0x01, 0x06, 0xef, 0xc0, 0x00, 0x00, 
+        0x41, 0x93, 0xff, 0x38, 0x01, 0x58, 0x24, 0x59, 0x63, 0x39, 0x24, 0x01, 0x03, 0xef, 0xc0, 0x00, 
+        0x00, 0x86, 0x13, 0x00, 0x66, 0x63, 0x25, 0x28, 0x72, 0x0c, 0x03, 0x1c, 0x84, 0x01, 0xe3, 0xff, 
+        0xc0, 0x00, 0x00, 0x01, 0xfc, 0xee, 0xc0, 0x00, 0x00, 0x41, 0x88, 0xff, 0x38, 0x01, 0x58, 0x34, 
+        0x59, 0x63, 0x39, 0x34, 0x01, 0xf9, 0xee, 0xc0, 0x00, 0x00, 0x46, 0x09, 0x00, 0x66, 0x73, 0x22, 
+        0x28, 0x72, 0x0c, 0x03, 0x0c, 0xc4, 0x01, 0xd9, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xf2, 0xee, 0xc0, 
+        0x00, 0x00, 0x41, 0x7e, 0xff, 0x38, 0x01, 0x58, 0x44, 0x59, 0x63, 0x39, 0x44, 0x01, 0xee, 0xee, 
+        0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x03, 0x28, 0x01, 0x1c, 0x84, 
+        0x28, 0x72, 0x01, 0xce, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xe7, 0xee, 0xc0, 0x00, 0x00, 0x41, 0x73, 
+        0xff, 0x38, 0x01, 0x58, 0x04, 0x59, 0x63, 0x39, 0x04, 0x01, 0xe3, 0xee, 0xc0, 0x00, 0x00, 0x06, 
+        0xf4, 0xff, 0x00, 0x00, 0xd0, 0x13, 0xff, 0x3f, 0xb0, 0xf8, 0xfe, 0x3f, 0x70, 0x0e, 0xff, 0x3f, 
+        0x00, 0xf0, 0x00, 0x00, 0xa0, 0x12, 0xff, 0x3f, 0xb0, 0x1e, 0xff, 0x3f, 0x12, 0xc1, 0xe0, 0xf9, 
+        0x41, 0x09, 0x01, 0xe9, 0x31, 0xd9, 0x21, 0xc9, 0x11, 0xd2, 0xa0, 0x68, 0xc1, 0xf7, 0xff, 0xe1, 
+        0xf5, 0xff, 0xe9, 0x7c, 0x2d, 0x0c, 0x0c, 0x13, 0x45, 0xee, 0xff, 0xc2, 0xcc, 0x20, 0xe2, 0xce, 
+        0x18, 0x0b, 0xdd, 0xe6, 0x1d, 0xeb, 0x0c, 0x4d, 0xf1, 0xf1, 0xff, 0xc0, 0x20, 0x00, 0x81, 0xf0, 
+        0xff, 0x72, 0x1f, 0x00, 0x80, 0x77, 0x10, 0x82, 0xa1, 0x00, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 
+        0x72, 0x5f, 0x00, 0xf9, 0x0c, 0xf9, 0x1c, 0xe9, 0x7c, 0x2d, 0x0c, 0x0c, 0x43, 0xcb, 0x5f, 0x0c, 
+        0x16, 0x62, 0x5c, 0x04, 0x59, 0x3c, 0x85, 0xea, 0xff, 0xc2, 0xcc, 0x20, 0xe2, 0xce, 0x18, 0x0b, 
+        0xdd, 0x92, 0xa1, 0x0c, 0x9a, 0xff, 0xe6, 0x1d, 0xc1, 0x0c, 0x4d, 0xf1, 0xe2, 0xff, 0xc0, 0x20, 
+        0x00, 0x31, 0xdf, 0xff, 0x22, 0x1f, 0x00, 0x30, 0x22, 0x10, 0x4c, 0x03, 0x30, 0x22, 0x20, 0xc0, 
+        0x20, 0x00, 0xf9, 0x0c, 0xf9, 0x1c, 0xe9, 0x7c, 0x0c, 0x53, 0x0c, 0x10, 0x22, 0x5f, 0x00, 0xcb, 
+        0xbf, 0xb9, 0x3c, 0x2d, 0x0c, 0x02, 0x5c, 0x04, 0x45, 0xe6, 0xff, 0xc2, 0xcc, 0x20, 0xf2, 0xcf, 
+        0x4c, 0xe2, 0xce, 0x18, 0x0b, 0xdd, 0xe6, 0x1d, 0xc4, 0x0c, 0x4d, 0xe9, 0x7c, 0x2d, 0x0c, 0x0c, 
+        0x63, 0xc5, 0xe4, 0xff, 0xc2, 0xcc, 0x20, 0xe2, 0xce, 0x18, 0x0b, 0xdd, 0xe6, 0x1d, 0xeb, 0x3c, 
+        0xad, 0xe1, 0xcd, 0xff, 0xe9, 0x7c, 0x2d, 0x0c, 0x0c, 0x73, 0x45, 0xe3, 0xff, 0xc2, 0xcc, 0x20, 
+        0xcb, 0xee, 0x0b, 0xdd, 0xe6, 0x1d, 0xec, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 
+        0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x70, 0x21, 0xff, 0x3f, 0x31, 0xff, 0xff, 0x32, 
+        0x03, 0x00, 0x0c, 0x12, 0xb6, 0x83, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0xa0, 0x21, 0xff, 0x3f, 
+        0x0c, 0x13, 0x51, 0xfe, 0xff, 0x20, 0x42, 0xb0, 0x50, 0x44, 0xa0, 0x42, 0x04, 0x11, 0x0c, 0x02, 
+        0x40, 0x23, 0x83, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x64, 0x89, 0xfe, 0x3f, 0x08, 0x8c, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x11, 0x01, 0xf0, 0xff, 0x08, 0x90, 0x29, 0x01, 0xdc, 0x00, 0x21, 0xfa, 
+        0xff, 0x31, 0xfa, 0xff, 0x42, 0xa0, 0xec, 0x01, 0xbe, 0xea, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 
+        0x30, 0x23, 0x20, 0x32, 0xa0, 0x03, 0x85, 0xc9, 0x07, 0x38, 0x01, 0x22, 0x43, 0x10, 0x0c, 0xa2, 
+        0x05, 0xc2, 0x07, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xe1, 0xff, 0x08, 0x90, 0x9d, 0x02, 0xdc, 0x00, 0x21, 0xeb, 0xff, 0x31, 0xeb, 0xff, 
+        0x42, 0xa0, 0xf7, 0x01, 0xaf, 0xea, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x30, 0x23, 0x20, 0x32, 
+        0x09, 0x10, 0xc5, 0xc5, 0x07, 0x22, 0xa0, 0x0a, 0x05, 0xc3, 0x07, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x45, 0x01, 0x00, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 
+        0x81, 0xce, 0xff, 0x12, 0xc1, 0xd0, 0xf9, 0x81, 0x09, 0x41, 0xe9, 0x71, 0xc9, 0x51, 0xd9, 0x61, 
+        0xcd, 0x02, 0xdd, 0x03, 0xcc, 0x33, 0xe8, 0x02, 0x46, 0x00, 0x00, 0xe8, 0x98, 0x0c, 0x07, 0x92, 
+        0xa0, 0x80, 0x08, 0x7e, 0x38, 0x0e, 0x48, 0x00, 0x52, 0x1e, 0x08, 0x40, 0x26, 0x41, 0x90, 0x92, 
+        0x10, 0x87, 0x74, 0x06, 0xf8, 0x13, 0x4b, 0xff, 0x46, 0x00, 0x00, 0xf8, 0x13, 0x32, 0x10, 0x03, 
+        0x62, 0x0c, 0x11, 0x30, 0x37, 0x41, 0x77, 0x62, 0x04, 0x67, 0xe2, 0x01, 0x0c, 0x17, 0x9c, 0x66, 
+        0x26, 0x36, 0x14, 0x26, 0x26, 0x11, 0x21, 0xc4, 0xff, 0x31, 0xc4, 0xff, 0x42, 0xa1, 0x14, 0x01, 
+        0x88, 0xea, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x0c, 0x06, 0x79, 0x21, 0x59, 0x31, 0x0c, 0x14, 
+        0x49, 0x91, 0x67, 0x72, 0x0b, 0x08, 0x7e, 0x32, 0x5f, 0x01, 0x0c, 0x15, 0x0c, 0x13, 0x46, 0x15, 
+        0x00, 0x52, 0x0c, 0x0b, 0xcc, 0x45, 0x72, 0x0c, 0x0d, 0x16, 0x67, 0x24, 0x72, 0x9c, 0x0b, 0x52, 
+        0x9c, 0x0a, 0x48, 0xa8, 0x00, 0x93, 0x11, 0x90, 0x90, 0x31, 0x48, 0x74, 0x70, 0x55, 0xc0, 0x42, 
+        0x14, 0x03, 0x52, 0x5c, 0x0a, 0xa2, 0x9c, 0x0a, 0x02, 0x10, 0x05, 0x40, 0x47, 0x41, 0x4a, 0x00, 
+        0x30, 0x00, 0xc0, 0x00, 0x00, 0x11, 0x00, 0x00, 0x31, 0x02, 0x5c, 0x0b, 0x00, 0x0a, 0xc0, 0x07, 
+        0x29, 0x08, 0x32, 0x5f, 0x01, 0x62, 0x4c, 0x0c, 0x86, 0x00, 0x00, 0x02, 0x5f, 0x01, 0x32, 0xa0, 
+        0x00, 0x02, 0x2e, 0x07, 0x52, 0xa0, 0x00, 0x78, 0x00, 0x92, 0xa1, 0x00, 0x70, 0x26, 0x41, 0x90, 
+        0x82, 0x10, 0x9c, 0xc5, 0x39, 0xa1, 0x69, 0xb1, 0xe7, 0x67, 0x16, 0x22, 0x00, 0x08, 0x05, 0x6b, 
+        0x05, 0x68, 0xb1, 0x08, 0x7e, 0x38, 0xa1, 0x28, 0x00, 0x82, 0xa1, 0x00, 0x20, 0x26, 0x41, 0x80, 
+        0x82, 0x10, 0x42, 0xa4, 0x02, 0x47, 0x82, 0x0b, 0x20, 0x56, 0x05, 0x16, 0x35, 0x18, 0x20, 0x73, 
+        0x05, 0x56, 0xd7, 0x17, 0x0c, 0x05, 0x46, 0x02, 0x00, 0x20, 0xa3, 0x05, 0x58, 0x91, 0x0c, 0x29, 
+        0xa0, 0x59, 0x93, 0xb1, 0xb4, 0xff, 0xa8, 0x0e, 0x92, 0x1f, 0x01, 0x50, 0x70, 0x24, 0x80, 0x77, 
+        0x01, 0xf1, 0xb1, 0xff, 0x51, 0xc1, 0xec, 0xe2, 0x9c, 0x0a, 0xb0, 0xaa, 0x10, 0xb8, 0x31, 0x00, 
+        0x99, 0x11, 0xb0, 0xb0, 0xb4, 0x16, 0x9d, 0x15, 0x97, 0x62, 0x01, 0xcc, 0x33, 0x0c, 0x0c, 0x86, 
+        0x00, 0x00, 0xc1, 0x1e, 0xf6, 0x16, 0x48, 0x14, 0x16, 0x13, 0x14, 0x31, 0xe3, 0xef, 0xe6, 0x1e, 
+        0x0c, 0x88, 0x21, 0x80, 0x80, 0x74, 0xcc, 0x48, 0xd2, 0x00, 0x08, 0xb6, 0xbd, 0x04, 0x0c, 0x02, 
+        0x86, 0x00, 0x00, 0x21, 0xa2, 0xff, 0x30, 0x4c, 0x20, 0xa0, 0x82, 0x20, 0x40, 0x47, 0x20, 0x80, 
+        0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x65, 0xb7, 0xc0, 0x20, 0x00, 0x92, 0x65, 0xba, 0x32, 0x00, 
+        0x0c, 0x22, 0x00, 0x08, 0x00, 0x33, 0x11, 0x20, 0x70, 0x34, 0x40, 0x77, 0x11, 0x70, 0x7b, 0x20, 
+        0xf6, 0xb2, 0x01, 0xfd, 0x06, 0x30, 0x8f, 0x20, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x65, 
+        0xb8, 0x22, 0x00, 0x08, 0xf6, 0xb2, 0x02, 0x06, 0x32, 0x00, 0x32, 0xa0, 0x87, 0x0c, 0x88, 0x98, 
+        0x00, 0x02, 0xc2, 0xf0, 0x90, 0x9c, 0x05, 0x90, 0x68, 0x93, 0xe6, 0x80, 0x01, 0x0c, 0x73, 0x00, 
+        0xa0, 0x24, 0xc8, 0x31, 0x60, 0xb3, 0x20, 0x80, 0xbb, 0x01, 0x80, 0xcc, 0x11, 0xc0, 0xaa, 0x20, 
+        0xb0, 0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x65, 0xb9, 0x86, 0x25, 0x00, 0x31, 0x84, 0xff, 0xe2, 
+        0x0c, 0x04, 0x6c, 0x8d, 0x80, 0x22, 0x20, 0xa0, 0x33, 0x20, 0x20, 0x77, 0x20, 0xe0, 0xed, 0xd1, 
+        0x5a, 0xee, 0x30, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x6e, 0xf1, 0x42, 0x0c, 0x04, 0x40, 0x4d, 
+        0xd1, 0x5a, 0x44, 0xc0, 0x20, 0x00, 0x92, 0x64, 0xf4, 0x22, 0x00, 0x08, 0x32, 0x00, 0x0c, 0x72, 
+        0x0c, 0x04, 0x00, 0x33, 0x11, 0x70, 0x7d, 0xd1, 0x5a, 0x77, 0xf6, 0xb2, 0x01, 0xfd, 0x06, 0x30, 
+        0x8f, 0x20, 0x20, 0x40, 0x34, 0x40, 0x44, 0x11, 0x40, 0x4b, 0x20, 0x80, 0x44, 0x20, 0xc0, 0x20, 
+        0x00, 0x42, 0x67, 0xf2, 0x22, 0x00, 0x08, 0xb6, 0xb2, 0x38, 0x32, 0xa0, 0x87, 0x82, 0x0c, 0x04, 
+        0x6c, 0x87, 0x0c, 0x89, 0xa8, 0x00, 0x02, 0xc2, 0xf0, 0xa0, 0xac, 0x05, 0xa0, 0x69, 0x93, 0x80, 
+        0x77, 0xd1, 0x5a, 0x57, 0xe6, 0x80, 0x01, 0x0c, 0x73, 0x00, 0xb0, 0x24, 0xd8, 0x31, 0x60, 0xc3, 
+        0x20, 0x80, 0xcc, 0x01, 0x80, 0xdd, 0x11, 0xd0, 0xbb, 0x20, 0xc0, 0xbb, 0x20, 0xc0, 0x20, 0x00, 
+        0xb2, 0x65, 0xf3, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 0x30, 
+        0x0d, 0xf0, 0x20, 0x44, 0x05, 0x16, 0x04, 0xe8, 0x0c, 0x35, 0x46, 0xa1, 0xff, 0x0c, 0x03, 0xc6, 
+        0xae, 0xff, 0x97, 0x62, 0x01, 0xcc, 0x33, 0x0c, 0x02, 0x86, 0x00, 0x00, 0x21, 0xc8, 0xf5, 0x9c, 
+        0xb8, 0x9c, 0x93, 0x81, 0x8d, 0xef, 0xe6, 0x1e, 0x0f, 0xd8, 0x21, 0xd0, 0xd0, 0x74, 0xcc, 0x7d, 
+        0xe2, 0x00, 0x08, 0xf6, 0xbe, 0x02, 0x86, 0xc8, 0xff, 0x0c, 0x03, 0x06, 0xc8, 0xff, 0x0c, 0x08, 
+        0x86, 0xf8, 0xff, 0x42, 0x1c, 0x0c, 0x16, 0xe4, 0x05, 0x32, 0x5f, 0x01, 0x08, 0x7e, 0x2d, 0x03, 
+        0x78, 0x00, 0x39, 0x11, 0x07, 0xf7, 0x24, 0x77, 0xe7, 0x21, 0x69, 0xb1, 0xc7, 0x77, 0x04, 0x69, 
+        0xb1, 0x97, 0x77, 0x17, 0x32, 0x21, 0x01, 0x22, 0x00, 0x00, 0x42, 0x1c, 0x0c, 0x20, 0x22, 0x34, 
+        0x45, 0xfe, 0x04, 0x62, 0x21, 0x0b, 0x02, 0x2e, 0x07, 0x22, 0x5f, 0x01, 0x48, 0x11, 0x40, 0x40, 
+        0xf4, 0x27, 0xb4, 0x0f, 0x22, 0x5c, 0x0a, 0x58, 0x91, 0x62, 0x5c, 0x0b, 0x52, 0x4c, 0x0c, 0x0c, 
+        0x15, 0x86, 0x03, 0x00, 0x62, 0x5c, 0x0a, 0x0c, 0x05, 0x86, 0x01, 0x00, 0x62, 0x5c, 0x0a, 0x0c, 
+        0x05, 0x08, 0x7e, 0x0c, 0x13, 0x86, 0x67, 0xff, 0x32, 0x61, 0x00, 0x16, 0x99, 0x02, 0x62, 0x61, 
+        0x0b, 0x67, 0xe2, 0x23, 0x22, 0x00, 0x00, 0x20, 0x22, 0x34, 0x45, 0xa5, 0x03, 0x68, 0xb1, 0x38, 
+        0x01, 0x32, 0x5f, 0x01, 0x39, 0x11, 0x16, 0x42, 0x05, 0x48, 0x72, 0x42, 0x14, 0x05, 0x0c, 0x15, 
+        0x3a, 0x44, 0x42, 0x5f, 0x01, 0x06, 0xf2, 0xff, 0xa7, 0xe2, 0x18, 0x69, 0xb1, 0x17, 0xe2, 0x13, 
+        0x22, 0x00, 0x00, 0x20, 0x22, 0x34, 0x85, 0xa2, 0x03, 0x68, 0xb1, 0x81, 0xef, 0xfe, 0x06, 0x01, 
+        0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x08, 0x01, 0x02, 0x5f, 0x01, 0x16, 0xd2, 0xf9, 0x48, 0x72, 
+        0x42, 0x14, 0x05, 0x32, 0x18, 0x16, 0x0a, 0x04, 0x07, 0x23, 0x90, 0x58, 0x91, 0x02, 0x5f, 0x01, 
+        0x02, 0x5c, 0x0a, 0x62, 0x5c, 0x0b, 0x52, 0x4c, 0x0c, 0x0c, 0x15, 0x86, 0xe0, 0xff, 0x0c, 0x05, 
+        0x46, 0xdf, 0xff, 0x00, 0x0c, 0x05, 0x0c, 0x02, 0x71, 0xe5, 0xfe, 0x50, 0x65, 0xb0, 0x1b, 0x55, 
+        0x70, 0x66, 0xa0, 0x62, 0x96, 0x0a, 0x50, 0x50, 0x74, 0x67, 0xa2, 0x02, 0x60, 0x20, 0xf4, 0x66, 
+        0x45, 0xe8, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x29, 0x01, 0x39, 0x11, 0x09, 0x21, 0xe9, 0x51, 0xc9, 
+        0x31, 0xd9, 0x41, 0xcd, 0x06, 0xdd, 0x05, 0xed, 0x04, 0x01, 0x72, 0xed, 0xc0, 0x00, 0x00, 0x31, 
+        0xd7, 0xfe, 0x28, 0x11, 0x08, 0x01, 0x0b, 0x22, 0x00, 0x00, 0xb0, 0x30, 0x00, 0xa0, 0xe2, 0x40, 
+        0x07, 0x22, 0x40, 0x05, 0x22, 0x00, 0x06, 0xd2, 0x40, 0x08, 0x27, 0x3d, 0x04, 0xe7, 0xb2, 0x04, 
+        0xdd, 0x0e, 0xd2, 0x40, 0x06, 0xd1, 0xc8, 0xfe, 0x22, 0x1d, 0x16, 0x27, 0xbc, 0x0d, 0x32, 0x10, 
+        0x0c, 0x27, 0x93, 0x0a, 0xc2, 0x50, 0x0c, 0xc5, 0xf8, 0xff, 0xcd, 0x02, 0xc2, 0x5d, 0x16, 0x01, 
+        0x62, 0xed, 0xc0, 0x00, 0x00, 0xc8, 0x31, 0xd8, 0x41, 0xe8, 0x51, 0x08, 0x21, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x00, 0x00, 0x0c, 0x07, 0x91, 0xc1, 0xfe, 0x20, 0x82, 0xb0, 0x90, 0x88, 0xa0, 0x22, 
+        0x48, 0x04, 0x32, 0x48, 0x05, 0x52, 0x48, 0x08, 0x42, 0x48, 0x07, 0x42, 0x48, 0x06, 0x62, 0x58, 
+        0x0c, 0x72, 0x48, 0x09, 0x72, 0x48, 0x0a, 0x72, 0x48, 0x11, 0x79, 0x78, 0x79, 0x88, 0x0d, 0xf0, 
+        0xc0, 0x0b, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x05, 0x01, 0x01, 0x22, 0xa0, 0x02, 
+        0x0c, 0x33, 0x0c, 0x44, 0x0c, 0xa5, 0x0c, 0x06, 0x85, 0xfb, 0xff, 0x0c, 0x32, 0x0c, 0x73, 0x0c, 
+        0x44, 0x0c, 0xa5, 0x0c, 0x06, 0xc5, 0xfa, 0xff, 0x0c, 0x12, 0x0c, 0x23, 0x0c, 0x34, 0x0c, 0x45, 
+        0x61, 0xf4, 0xff, 0x05, 0xfa, 0xff, 0x0c, 0x02, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x35, 0x62, 0xa5, 
+        0xe0, 0x05, 0xf9, 0xff, 0x0c, 0x42, 0x0c, 0x23, 0x0c, 0x44, 0x0c, 0xa5, 0x0c, 0x06, 0x45, 0xf8, 
+        0xff, 0x0c, 0x72, 0x0c, 0x23, 0x0c, 0x54, 0x0c, 0xa5, 0x0c, 0x06, 0x85, 0xf7, 0xff, 0x45, 0xee, 
+        0xff, 0x01, 0x99, 0xfe, 0x0c, 0x13, 0x22, 0x50, 0x16, 0x0c, 0x82, 0x22, 0x40, 0x00, 0x22, 0x10, 
+        0x0e, 0x45, 0x25, 0x05, 0x45, 0x4f, 0x06, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x32, 0xc2, 0xf6, 0x12, 0xc1, 0xf0, 0x41, 0x90, 0xfe, 0x09, 0x11, 0x02, 0x04, 0x00, 0x5d, 0x02, 
+        0x30, 0x50, 0x83, 0x50, 0x00, 0x74, 0xb6, 0x80, 0x11, 0x21, 0x97, 0xfe, 0x31, 0x98, 0xfe, 0x42, 
+        0xa2, 0x2d, 0x01, 0x5b, 0xe9, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x32, 0xc4, 0x30, 0x00, 0x00, 
+        0xb0, 0x30, 0x00, 0xa0, 0x62, 0x00, 0x11, 0x26, 0x16, 0x11, 0x21, 0x8f, 0xfe, 0x31, 0x8f, 0xfe, 
+        0x42, 0xa2, 0x35, 0x01, 0x53, 0xe9, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x52, 0x44, 0x00, 0x09, 
+        0x01, 0x66, 0x92, 0x12, 0x2d, 0x00, 0x3d, 0x04, 0x32, 0x03, 0x2e, 0x05, 0xa6, 0xff, 0x08, 0x01, 
+        0x51, 0x7a, 0xfe, 0x0c, 0x04, 0x49, 0x95, 0x68, 0x00, 0xdc, 0x06, 0x21, 0x83, 0xfe, 0x31, 0x83, 
+        0xfe, 0x42, 0xa2, 0x3c, 0x01, 0x47, 0xe9, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x00, 0x20, 0x20, 
+        0x72, 0xa0, 0x02, 0x72, 0x40, 0x11, 0xc5, 0x00, 0x00, 0x85, 0x8a, 0x00, 0x02, 0x21, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0xc9, 0x21, 0x48, 0x02, 0xcd, 0x02, 0xdc, 
+        0x04, 0x21, 0x75, 0xfe, 0x31, 0x76, 0xfe, 0x42, 0xa2, 0x53, 0x01, 0x39, 0xe9, 0xc0, 0x00, 0x00, 
+        0x06, 0xff, 0xff, 0x21, 0x65, 0xfe, 0x08, 0xa2, 0x38, 0x92, 0x9c, 0x00, 0x21, 0x6f, 0xfe, 0x31, 
+        0x6f, 0xfe, 0x42, 0xa2, 0x54, 0x01, 0x32, 0xe9, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x9c, 0x03, 
+        0x21, 0x6a, 0xfe, 0x31, 0x6a, 0xfe, 0x42, 0xa2, 0x55, 0x01, 0x2d, 0xe9, 0xc0, 0x00, 0x00, 0x06, 
+        0xff, 0xff, 0x49, 0xa2, 0x08, 0x74, 0x0c, 0x06, 0x58, 0x00, 0x69, 0x0c, 0x50, 0x5c, 0x05, 0x56, 
+        0x85, 0x0e, 0x49, 0x01, 0x72, 0x0c, 0x0b, 0xa2, 0x1c, 0x0c, 0xcc, 0x97, 0x82, 0x9c, 0x0a, 0xa6, 
+        0x18, 0x04, 0x0c, 0x19, 0x92, 0x4c, 0x0d, 0x16, 0x8a, 0x04, 0xb2, 0x0c, 0x0b, 0x22, 0x0c, 0x0c, 
+        0x8c, 0x0b, 0xcc, 0x32, 0x32, 0x0c, 0x0d, 0xbc, 0x83, 0x22, 0x00, 0x00, 0x20, 0x22, 0x34, 0x05, 
+        0x7e, 0x03, 0x02, 0x21, 0x00, 0x02, 0x20, 0x07, 0x16, 0x72, 0x02, 0x48, 0x00, 0x40, 0x56, 0x41, 
+        0x40, 0x30, 0x05, 0x56, 0xd3, 0x0a, 0x40, 0x67, 0x04, 0x56, 0x76, 0x0a, 0x71, 0x43, 0xfe, 0x0c, 
+        0x13, 0x29, 0x97, 0x2d, 0x0c, 0xc5, 0x9a, 0xff, 0x2d, 0x0c, 0x32, 0xa0, 0xd4, 0x05, 0x93, 0xff, 
+        0xc6, 0x21, 0x00, 0x42, 0x20, 0x00, 0xd7, 0x64, 0x26, 0xc7, 0xe4, 0x23, 0x22, 0x00, 0x00, 0x20, 
+        0x22, 0x34, 0xc5, 0x79, 0x03, 0x16, 0x72, 0x01, 0x31, 0x38, 0xfe, 0x22, 0x63, 0x09, 0x2d, 0x0c, 
+        0x0c, 0x13, 0x05, 0x98, 0xff, 0x2d, 0x0c, 0x32, 0xa0, 0xd4, 0x45, 0x90, 0xff, 0x86, 0x16, 0x00, 
+        0x42, 0x0c, 0x0b, 0x52, 0x0c, 0x0c, 0x8c, 0x04, 0xcc, 0x45, 0x62, 0x0c, 0x0d, 0x16, 0xa6, 0x04, 
+        0x22, 0x21, 0x00, 0x22, 0x22, 0x07, 0x22, 0x02, 0x00, 0x20, 0x22, 0x34, 0x05, 0x76, 0x03, 0x16, 
+        0x82, 0x03, 0x48, 0x01, 0x48, 0x74, 0x48, 0x04, 0x07, 0xf4, 0x19, 0x77, 0xe4, 0x16, 0x51, 0x26, 
+        0xfe, 0x0c, 0x13, 0x29, 0x95, 0x2d, 0x0c, 0xc5, 0x93, 0xff, 0x2d, 0x0c, 0x32, 0xa0, 0xd4, 0x05, 
+        0x8c, 0xff, 0x46, 0x05, 0x00, 0x22, 0x6c, 0x00, 0x32, 0xa0, 0x00, 0xc0, 0x2c, 0x20, 0x45, 0x92, 
+        0xff, 0x22, 0x0c, 0x04, 0x0c, 0x03, 0x0c, 0x04, 0xc5, 0x1f, 0x07, 0xc8, 0x21, 0x08, 0x11, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x57, 0x65, 0x08, 0x62, 0x00, 0x04, 0x60, 0x64, 0x41, 0xa6, 0x26, 0xea, 
+        0x22, 0x6c, 0x00, 0x32, 0xa0, 0x00, 0xc0, 0x2c, 0x20, 0x85, 0x8f, 0xff, 0x22, 0x0c, 0x04, 0x0c, 
+        0x03, 0x0c, 0x04, 0x45, 0x1d, 0x07, 0x46, 0xf4, 0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x11, 0x09, 0x01, 0xcd, 0x03, 0x45, 0x83, 0xff, 0xdc, 0x02, 0x21, 0x17, 0xfe, 0x31, 0x17, 0xfe, 
+        0x42, 0xa2, 0x90, 0x01, 0xdb, 0xe8, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0x07, 0xfe, 0x08, 
+        0xa2, 0x42, 0x02, 0x00, 0xdc, 0x00, 0x21, 0x10, 0xfe, 0x31, 0x10, 0xfe, 0x42, 0xa2, 0x93, 0x01, 
+        0xd4, 0xe8, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x52, 0x02, 0x00, 0x32, 0xc2, 0x30, 0x50, 0x24, 
+        0xb0, 0x30, 0x22, 0xa0, 0x32, 0x02, 0x11, 0x26, 0x23, 0x11, 0x21, 0x07, 0xfe, 0x31, 0x07, 0xfe, 
+        0x42, 0xa2, 0x94, 0x01, 0xcb, 0xe8, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x08, 0x70, 0x0c, 0x06, 
+        0x38, 0x00, 0x82, 0xa4, 0x02, 0x30, 0x76, 0x41, 0x87, 0x87, 0x05, 0xc7, 0x73, 0x50, 0x97, 0xf3, 
+        0x4d, 0x62, 0x42, 0x09, 0x62, 0x42, 0x0a, 0xc2, 0xaf, 0xff, 0x92, 0x02, 0x07, 0x92, 0x42, 0x06, 
+        0xa2, 0x20, 0x00, 0xc2, 0x40, 0x09, 0xb7, 0x6a, 0x28, 0x52, 0x00, 0x04, 0x50, 0x34, 0x41, 0xe6, 
+        0x23, 0x1f, 0xc2, 0xc3, 0x01, 0x50, 0xb0, 0x34, 0x0c, 0x13, 0xc0, 0xc0, 0x34, 0xc0, 0xcc, 0x11, 
+        0xc0, 0xbb, 0x20, 0xb2, 0x40, 0x04, 0x45, 0x2a, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x0c, 0x03, 0x0c, 0x50, 0x02, 0x42, 0x11, 0x05, 0x29, 0x00, 0x46, 0xfa, 0xff, 0x32, 
+        0x02, 0x07, 0x87, 0xe7, 0x08, 0x32, 0x42, 0x06, 0x62, 0x42, 0x09, 0x46, 0xec, 0xff, 0x32, 0x42, 
+        0x06, 0x62, 0x42, 0x09, 0x62, 0x42, 0x0a, 0x46, 0xe9, 0xff, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0x09, 
+        0x01, 0x59, 0x51, 0xf9, 0x41, 0xe9, 0x31, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x03, 0xdd, 0x04, 0xed, 
+        0x02, 0xfd, 0x05, 0x38, 0x8e, 0x28, 0x7c, 0x1b, 0x33, 0x39, 0x8e, 0x08, 0x02, 0xd2, 0x42, 0x0f, 
+        0xd7, 0x60, 0x0c, 0xc7, 0xe0, 0x09, 0x2d, 0x0c, 0x0c, 0x03, 0x45, 0xf4, 0x00, 0x06, 0x02, 0x00, 
+        0xf0, 0x3f, 0x20, 0xc0, 0x2c, 0x20, 0x85, 0xf3, 0x00, 0x22, 0x2c, 0x07, 0x08, 0x02, 0xd7, 0x60, 
+        0x10, 0xc7, 0xe0, 0x0d, 0x22, 0x02, 0x00, 0x20, 0x22, 0x34, 0x45, 0x60, 0x03, 0xcd, 0x02, 0x56, 
+        0x02, 0xfc, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x31, 0xc2, 0xfd, 0x20, 0x22, 0xb0, 0x30, 0x22, 0xa0, 0x0d, 0xf0, 0x00, 
+        0x5d, 0x04, 0x12, 0xc1, 0xf0, 0x0c, 0x44, 0x09, 0x01, 0x05, 0xf8, 0xff, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x6d, 0x02, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x2d, 0x03, 0x0c, 0x10, 0x3d, 
+        0x04, 0x58, 0x76, 0x48, 0x72, 0x1b, 0x55, 0x59, 0x76, 0x02, 0x44, 0x0f, 0x05, 0xed, 0x00, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x24, 0x0e, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x09, 
+        0x11, 0x32, 0x02, 0x11, 0x08, 0x02, 0x26, 0x63, 0x11, 0x21, 0xb3, 0xfd, 0x31, 0xb4, 0xfd, 0x42, 
+        0xa2, 0xda, 0x01, 0x77, 0xe8, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x42, 0xa0, 0x00, 0x42, 0x42, 
+        0x11, 0x62, 0x20, 0x07, 0x02, 0x61, 0x00, 0x38, 0x06, 0x49, 0x02, 0xb7, 0x73, 0x2a, 0x22, 0x06, 
+        0x00, 0x32, 0x06, 0x04, 0x20, 0x22, 0x34, 0x30, 0x34, 0x41, 0x2b, 0x33, 0x30, 0x30, 0x74, 0x45, 
+        0xc7, 0x03, 0x48, 0x01, 0x48, 0x74, 0x2c, 0x02, 0x42, 0x04, 0x00, 0x0c, 0x63, 0x40, 0x42, 0x34, 
+        0x01, 0xea, 0xff, 0xc0, 0x00, 0x00, 0x46, 0x0d, 0x00, 0x02, 0x21, 0x00, 0xc7, 0x73, 0x0b, 0x32, 
+        0xa0, 0x01, 0x00, 0x20, 0x20, 0x45, 0xad, 0x04, 0xc6, 0x08, 0x00, 0x71, 0x8f, 0xfd, 0x52, 0x06, 
+        0x05, 0x72, 0x07, 0x0d, 0x50, 0x50, 0x54, 0x77, 0x35, 0x0b, 0x0c, 0x24, 0x0c, 0x15, 0x3d, 0x00, 
+        0x85, 0xec, 0xff, 0x06, 0x02, 0x00, 0x0c, 0x34, 0x0c, 0x15, 0x3d, 0x00, 0xc5, 0xeb, 0xff, 0x08, 
+        0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x42, 0x02, 0x0d, 0x0c, 0x05, 0x8c, 0x44, 0x32, 
+        0x42, 0x0b, 0x52, 0x42, 0x0d, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 
+        0x00, 0x02, 0x02, 0x0b, 0x20, 0xc2, 0x20, 0xac, 0xa0, 0x22, 0x02, 0x0c, 0x0c, 0x00, 0x9c, 0x02, 
+        0x28, 0x0c, 0x28, 0x72, 0x22, 0x02, 0x00, 0x20, 0x22, 0x34, 0x45, 0x49, 0x03, 0x29, 0x0c, 0x46, 
+        0x01, 0x00, 0x00, 0x20, 0x20, 0x22, 0x6c, 0x00, 0x16, 0xe2, 0x01, 0x2d, 0x0c, 0x0c, 0x03, 0x05, 
+        0x74, 0x00, 0x86, 0x01, 0x00, 0x0c, 0x03, 0x05, 0xfb, 0xff, 0x0c, 0x02, 0x0c, 0x93, 0x08, 0x01, 
+        0x32, 0x4c, 0x12, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x02, 0x0c, 0x04, 0x42, 0x4c, 
+        0x0b, 0xc6, 0xf9, 0xff, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0x02, 0x02, 0x0b, 0xcd, 0x02, 
+        0x8c, 0x60, 0x0c, 0x02, 0x22, 0x4c, 0x0b, 0x46, 0x01, 0x00, 0x32, 0xa0, 0x00, 0x85, 0xf7, 0xff, 
+        0x21, 0x62, 0xfd, 0x22, 0x22, 0x09, 0x05, 0x4a, 0x03, 0x32, 0xa0, 0x0c, 0x08, 0x01, 0x32, 0x4c, 
+        0x12, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x13, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 
+        0x11, 0x01, 0x59, 0xfd, 0xcd, 0x02, 0x08, 0x90, 0x09, 0x02, 0x45, 0x6d, 0x00, 0x0c, 0xb3, 0x08, 
+        0x01, 0x32, 0x4c, 0x12, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0x02, 
+        0x61, 0x00, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x03, 0xdd, 0x02, 0x0c, 0x03, 0x32, 0x42, 0x11, 0x85, 
+        0xf2, 0xff, 0x28, 0x5c, 0x45, 0x31, 0x06, 0xac, 0x52, 0x28, 0x7c, 0xc5, 0x44, 0x05, 0x28, 0x7c, 
+        0x22, 0x02, 0x00, 0x0c, 0x13, 0x20, 0x22, 0x34, 0x85, 0xb2, 0x03, 0x48, 0x7c, 0x2c, 0x02, 0x42, 
+        0x04, 0x00, 0x0c, 0x63, 0x40, 0x42, 0x34, 0x01, 0x98, 0xff, 0xc0, 0x00, 0x00, 0x06, 0x02, 0x00, 
+        0xc0, 0x2c, 0x20, 0x32, 0xa0, 0x01, 0x45, 0xa2, 0x04, 0x02, 0x21, 0x00, 0x0c, 0x85, 0xc8, 0x11, 
+        0x52, 0x4d, 0x12, 0xd8, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x0c, 0x34, 0x81, 0x6b, 
+        0xfd, 0x52, 0xa0, 0x94, 0x12, 0xc1, 0xd0, 0xe9, 0x71, 0x09, 0x41, 0xc9, 0x51, 0xf9, 0x81, 0xd9, 
+        0x61, 0x0c, 0x0f, 0xd1, 0x35, 0xfd, 0xcd, 0x02, 0x02, 0x0c, 0x11, 0x2d, 0x03, 0x32, 0xa0, 0xd4, 
+        0xec, 0x92, 0x0c, 0x1e, 0x22, 0xc0, 0xfa, 0x56, 0x12, 0x09, 0xf2, 0x4c, 0x11, 0x08, 0xad, 0x48, 
+        0x0c, 0x56, 0x20, 0x18, 0x8c, 0x34, 0x38, 0x9d, 0x16, 0x73, 0x37, 0x21, 0x37, 0xfd, 0x31, 0x37, 
+        0xfd, 0x42, 0xa3, 0x37, 0x01, 0xfb, 0xe7, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x26, 0x20, 0x14, 
+        0x26, 0x10, 0x11, 0x21, 0x31, 0xfd, 0x31, 0x31, 0xfd, 0x42, 0xa3, 0xa1, 0x01, 0xf5, 0xe7, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0x02, 0x2d, 0x0a, 0x62, 0x2d, 0x09, 0x56, 0x50, 0x01, 0x2d, 0x0c, 
+        0x0c, 0x03, 0x0c, 0x34, 0x42, 0x4c, 0x11, 0x85, 0x5e, 0x00, 0xed, 0x02, 0x0c, 0x50, 0x02, 0x4c, 
+        0x12, 0x86, 0x26, 0x00, 0x16, 0xe6, 0x01, 0x72, 0x20, 0x07, 0x72, 0x27, 0x00, 0x2d, 0x0c, 0x70, 
+        0x79, 0x05, 0x70, 0x35, 0x93, 0x45, 0x4c, 0xff, 0x82, 0x0c, 0x0e, 0x28, 0x9d, 0x56, 0xe8, 0x0b, 
+        0x45, 0x36, 0x03, 0xc6, 0x2e, 0x00, 0x98, 0x0c, 0xbc, 0x09, 0x21, 0x1b, 0xfd, 0x31, 0x1b, 0xfd, 
+        0x42, 0xa3, 0xb4, 0x01, 0xdf, 0xe7, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x26, 0x50, 0x02, 0x86, 
+        0x22, 0x00, 0x08, 0xad, 0xf2, 0x4c, 0x11, 0x56, 0x00, 0x0b, 0x21, 0x13, 0xfd, 0x31, 0x13, 0xfd, 
+        0x42, 0xa3, 0x62, 0x01, 0xd7, 0xe7, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x28, 0x70, 0xa8, 0x02, 
+        0xa0, 0xa6, 0x41, 0x87, 0x0a, 0x1a, 0x22, 0x02, 0x04, 0x20, 0x24, 0x41, 0xa6, 0x12, 0x11, 0x52, 
+        0x10, 0x08, 0x32, 0x1d, 0x07, 0x57, 0xb3, 0x02, 0x46, 0x6e, 0x00, 0xa6, 0x32, 0x02, 0xc6, 0x6c, 
+        0x00, 0x09, 0x0c, 0x62, 0x0c, 0x0b, 0x42, 0x4c, 0x11, 0x8c, 0x16, 0xf2, 0x4c, 0x0b, 0xc0, 0x2c, 
+        0x20, 0x32, 0xa0, 0x00, 0x85, 0x54, 0x00, 0x20, 0xe2, 0x20, 0x0c, 0x77, 0x72, 0x4c, 0x12, 0x0c, 
+        0x00, 0xf9, 0xad, 0x82, 0x0c, 0x0d, 0xb8, 0x9d, 0x92, 0x0d, 0x00, 0x0c, 0x8a, 0xe0, 0x9a, 0x83, 
+        0x00, 0xbf, 0x83, 0xb9, 0x9d, 0x92, 0x4d, 0x00, 0x16, 0x68, 0x0d, 0x21, 0xf7, 0xfc, 0x31, 0xf7, 
+        0xfc, 0x42, 0xa3, 0xc9, 0x01, 0xbb, 0xe7, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xf2, 0xfc, 
+        0x31, 0xf3, 0xfc, 0x42, 0xa3, 0x9b, 0x01, 0xb6, 0xe7, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x05, 
+        0x58, 0x04, 0xc0, 0x2c, 0x20, 0x32, 0xa0, 0x00, 0x0c, 0x30, 0xe8, 0xad, 0xe9, 0x0c, 0x02, 0x4c, 
+        0x11, 0xc5, 0x4e, 0x00, 0xed, 0x02, 0x0c, 0x60, 0x86, 0xc0, 0xff, 0x22, 0x2d, 0x09, 0x16, 0x32, 
+        0x05, 0x42, 0x20, 0x07, 0x42, 0x24, 0x00, 0x2d, 0x0c, 0x40, 0x49, 0x05, 0x40, 0x35, 0x93, 0x32, 
+        0x4d, 0x2e, 0x3d, 0x0e, 0x05, 0xd4, 0xff, 0x22, 0x0c, 0x04, 0x58, 0x9d, 0x59, 0x0c, 0x45, 0xdd, 
+        0x06, 0xe2, 0x4c, 0x11, 0xf2, 0x4c, 0x12, 0x2d, 0x0c, 0x38, 0xad, 0x0c, 0x04, 0x45, 0xc6, 0xff, 
+        0x0c, 0x10, 0x0c, 0x1e, 0x46, 0xda, 0xff, 0x68, 0x9d, 0x09, 0x31, 0x16, 0x16, 0x08, 0x09, 0x91, 
+        0x16, 0xa4, 0x1c, 0x21, 0xd5, 0xfc, 0x31, 0xd5, 0xfc, 0x42, 0xa3, 0x3c, 0x01, 0x99, 0xe7, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0x72, 0x2c, 0x00, 0x56, 0x57, 0x04, 0x02, 0x20, 0x07, 0x08, 0x00, 
+        0x00, 0x89, 0x05, 0x16, 0xc8, 0x0f, 0x2d, 0x01, 0x2b, 0x31, 0x4b, 0x41, 0x8b, 0x51, 0x85, 0x4f, 
+        0x07, 0x58, 0x21, 0x08, 0xad, 0x48, 0x11, 0x08, 0x70, 0x32, 0x11, 0x01, 0x22, 0x00, 0x00, 0x68, 
+        0x00, 0x20, 0x22, 0x34, 0x60, 0x6b, 0x05, 0x56, 0x16, 0x15, 0x0c, 0x06, 0x45, 0x8f, 0x03, 0x06, 
+        0x56, 0x00, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 0x08, 0x41, 0x12, 0xc1, 0x30, 0x0d, 
+        0xf0, 0x2d, 0x0c, 0x3d, 0x0e, 0x05, 0xcb, 0xff, 0xe2, 0x4c, 0x11, 0x38, 0xad, 0x0c, 0x42, 0x0c, 
+        0x04, 0x22, 0x4c, 0x12, 0x2d, 0x0c, 0xc5, 0xbd, 0xff, 0x0c, 0x1e, 0x0c, 0x00, 0x06, 0xb8, 0xff, 
+        0xdc, 0x74, 0x2d, 0x0c, 0x3d, 0x0f, 0x05, 0xc9, 0xff, 0x32, 0x0c, 0x0b, 0x8c, 0x13, 0xf2, 0x4c, 
+        0x0b, 0x0c, 0x0e, 0x0c, 0xa4, 0x42, 0x4c, 0x12, 0x46, 0x05, 0x00, 0xe0, 0x3e, 0x20, 0xc0, 0x2c, 
+        0x20, 0x45, 0xc7, 0xff, 0xe2, 0xa0, 0x01, 0x0c, 0xd5, 0x0c, 0x16, 0x62, 0x4c, 0x11, 0x52, 0x4c, 
+        0x12, 0x08, 0x31, 0x08, 0x70, 0x48, 0x00, 0xb7, 0x74, 0x2a, 0x22, 0x00, 0x00, 0x32, 0x00, 0x04, 
+        0x20, 0x22, 0x34, 0x30, 0x34, 0x41, 0x2b, 0x33, 0x30, 0x30, 0x74, 0x85, 0x86, 0x03, 0x48, 0x31, 
+        0x48, 0x74, 0x2c, 0x02, 0x42, 0x04, 0x00, 0x0c, 0x63, 0x40, 0x42, 0x34, 0x01, 0xe7, 0xfe, 0xc0, 
+        0x00, 0x00, 0x46, 0xe5, 0xff, 0xc7, 0x74, 0x18, 0x28, 0x31, 0x0c, 0x13, 0xc5, 0x6c, 0x04, 0x06, 
+        0xe2, 0xff, 0x00, 0x00, 0x00, 0x2d, 0x0c, 0x3d, 0x00, 0x05, 0xce, 0xff, 0x0c, 0x0e, 0x46, 0x97, 
+        0xff, 0x72, 0x0d, 0x0d, 0x92, 0x0c, 0x11, 0x0c, 0x18, 0x42, 0x00, 0x05, 0x0c, 0x05, 0x40, 0x60, 
+        0x54, 0x90, 0x58, 0x83, 0x77, 0x36, 0x5a, 0x38, 0x31, 0x2d, 0x0c, 0x0c, 0x24, 0xc5, 0xaa, 0xff, 
+        0xc6, 0xd5, 0xff, 0xc7, 0x70, 0x29, 0xc0, 0x2c, 0x20, 0xf0, 0x3f, 0x20, 0x85, 0xbe, 0xff, 0x28, 
+        0xad, 0x0c, 0x23, 0x32, 0x4c, 0x12, 0x28, 0x52, 0x05, 0xfd, 0x05, 0x4d, 0x02, 0x28, 0xad, 0x16, 
+        0x64, 0x0c, 0x28, 0x72, 0x22, 0x02, 0x04, 0x20, 0x20, 0x34, 0x05, 0x6e, 0x03, 0x06, 0x07, 0x00, 
+        0x2d, 0x0c, 0x3d, 0x0f, 0x05, 0xbc, 0xff, 0x32, 0x0c, 0x0b, 0x8c, 0x13, 0xf2, 0x4c, 0x0b, 0x2d, 
+        0x0c, 0x0c, 0x34, 0x38, 0xad, 0x42, 0x4c, 0x12, 0x0c, 0x14, 0x85, 0xae, 0xff, 0x0c, 0x0e, 0x06, 
+        0xc2, 0xff, 0x62, 0x00, 0x06, 0x72, 0x0d, 0x0c, 0x80, 0x66, 0x11, 0x40, 0x66, 0x20, 0x60, 0x66, 
+        0x54, 0x77, 0x36, 0x0b, 0x38, 0x31, 0x2d, 0x0c, 0x0c, 0x34, 0x05, 0xa4, 0xff, 0x86, 0xba, 0xff, 
+        0x38, 0x31, 0x2d, 0x0c, 0x0c, 0x44, 0x45, 0xa3, 0xff, 0x86, 0xb7, 0xff, 0x62, 0x00, 0x04, 0x60, 
+        0x64, 0x41, 0x62, 0xc6, 0x01, 0x60, 0x60, 0x74, 0x85, 0x79, 0x03, 0x42, 0x2d, 0x0a, 0x42, 0x24, 
+        0x07, 0x2c, 0x02, 0x42, 0x04, 0x00, 0x0c, 0x63, 0x40, 0x42, 0x34, 0x01, 0xaf, 0xfe, 0xc0, 0x00, 
+        0x00, 0x2d, 0x0c, 0x0c, 0x03, 0x05, 0xb5, 0xff, 0xe2, 0x4c, 0x12, 0x86, 0xe7, 0xff, 0x68, 0x70, 
+        0x2d, 0x0c, 0x68, 0x06, 0xed, 0x00, 0x60, 0x69, 0x05, 0x60, 0x35, 0x93, 0xc5, 0x1b, 0xff, 0x48, 
+        0x7e, 0x48, 0x04, 0xd7, 0x64, 0x18, 0xc7, 0xe4, 0x15, 0x2d, 0x0c, 0x85, 0xb9, 0xff, 0x0c, 0x0e, 
+        0x46, 0xaf, 0xff, 0x49, 0x31, 0x2d, 0x0c, 0x05, 0xb3, 0xff, 0xed, 0x02, 0x46, 0xac, 0xff, 0x2d, 
+        0x0c, 0x45, 0xbb, 0xff, 0xed, 0x02, 0xc6, 0xa9, 0xff, 0x0c, 0x13, 0x05, 0x64, 0x04, 0xc6, 0xd6, 
+        0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x01, 0xd2, 0x61, 0x02, 0xe2, 0x61, 0x03, 
+        0xf9, 0x41, 0x09, 0x01, 0x45, 0xd6, 0x06, 0xcd, 0x02, 0xbc, 0x42, 0x0c, 0x1f, 0xc6, 0x06, 0x00, 
+        0xd0, 0xe0, 0x74, 0xe0, 0x2e, 0x20, 0x05, 0xd3, 0x06, 0x2d, 0x0e, 0x45, 0x03, 0x00, 0x7c, 0xf0, 
+        0x00, 0x1d, 0x40, 0x00, 0x2f, 0xa1, 0x00, 0x22, 0x30, 0x20, 0xcc, 0x10, 0xc0, 0xd0, 0x60, 0xc0, 
+        0xdd, 0x10, 0xd0, 0xfd, 0x40, 0xd0, 0xd0, 0x60, 0xd2, 0xcd, 0x1f, 0xd6, 0x1d, 0xfd, 0xc5, 0xd3, 
+        0x06, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xb6, 0x82, 0x11, 0x21, 0x38, 0xfc, 0x31, 0x38, 0xfc, 0x42, 0xa3, 
+        0xe9, 0x01, 0xfb, 0xe6, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x01, 0x2c, 0xfc, 0x20, 0x22, 0xb0, 
+        0x00, 0x22, 0xa0, 0x38, 0x02, 0xdc, 0x03, 0x21, 0x30, 0xfc, 0x31, 0x30, 0xfc, 0x42, 0xa3, 0xeb, 
+        0x01, 0xf4, 0xe6, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x42, 0x02, 0x11, 0x26, 0x14, 0x11, 0x21, 
+        0x2a, 0xfc, 0x31, 0x2a, 0xfc, 0x42, 0xa3, 0xec, 0x01, 0xee, 0xe6, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x52, 0x23, 0x07, 0x72, 0x13, 0x08, 0x52, 0x25, 0x00, 0x62, 0xa3, 0x00, 0x50, 0x56, 0x41, 
+        0x67, 0x85, 0x13, 0x62, 0xc0, 0xd0, 0x62, 0x16, 0x07, 0x77, 0xb6, 0x0a, 0x85, 0x29, 0x00, 0x02, 
+        0x21, 0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x14, 0xc5, 0x00, 0x00, 0xc6, 0xfb, 0xff, 0x00, 
+        0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x01, 0x40, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 
+        0x21, 0xcd, 0x02, 0xdd, 0x03, 0xdc, 0x03, 0x21, 0x14, 0xfc, 0x31, 0x14, 0xfc, 0x42, 0xa4, 0x09, 
+        0x01, 0xd8, 0xe6, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x01, 0x03, 0xfc, 0x72, 0x02, 0x09, 0x22, 
+        0x00, 0x0d, 0x3d, 0x07, 0x27, 0xb7, 0x0a, 0x1b, 0x37, 0x32, 0x4c, 0x09, 0x22, 0x00, 0x0d, 0x30, 
+        0x30, 0x74, 0x27, 0xb3, 0x10, 0x22, 0x0c, 0x06, 0x52, 0x0c, 0x08, 0x1b, 0x62, 0x57, 0xb2, 0x0b, 
+        0x62, 0x4c, 0x06, 0x46, 0x01, 0x00, 0x72, 0x0c, 0x07, 0x72, 0x4c, 0x06, 0xb8, 0x7d, 0x82, 0x00, 
+        0x00, 0x22, 0x0b, 0x05, 0xa2, 0xa0, 0xc0, 0xa0, 0xa2, 0x10, 0x20, 0x20, 0x54, 0x1b, 0x22, 0x20, 
+        0x20, 0x54, 0x20, 0xaa, 0x20, 0xa2, 0x4b, 0x05, 0x92, 0x0c, 0x04, 0x97, 0x98, 0x28, 0x28, 0x7d, 
+        0x72, 0x02, 0x04, 0xb2, 0x02, 0x05, 0x70, 0x34, 0x41, 0x8c, 0x94, 0xb0, 0xb0, 0x54, 0xb7, 0xa3, 
+        0x17, 0x48, 0x02, 0xc7, 0xf4, 0x12, 0x70, 0x50, 0x34, 0x1b, 0x63, 0x60, 0x60, 0x34, 0xc0, 0x66, 
+        0x11, 0x60, 0x55, 0x20, 0x52, 0x42, 0x04, 0x28, 0x7d, 0x32, 0x0c, 0x11, 0x26, 0x23, 0x14, 0x26, 
+        0x13, 0x11, 0x21, 0xed, 0xfb, 0x31, 0xed, 0xfb, 0x42, 0xa4, 0x1a, 0x01, 0xb1, 0xe6, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0x45, 0x9f, 0x05, 0x01, 0xdc, 0xfb, 0x20, 0x72, 0x20, 0x22, 0x2d, 0x07, 
+        0x56, 0x87, 0x01, 0x82, 0x02, 0x05, 0x92, 0x00, 0x0d, 0x80, 0x80, 0x54, 0x97, 0xb8, 0x0c, 0x2d, 
+        0x0d, 0xc5, 0xf1, 0xff, 0x01, 0xd5, 0xfb, 0x16, 0xe2, 0x05, 0x28, 0x7d, 0x98, 0x02, 0xa1, 0xc5, 
+        0xff, 0x90, 0x96, 0x41, 0xa7, 0xc9, 0x2c, 0xb2, 0x1d, 0x08, 0x32, 0x02, 0x04, 0xa2, 0x10, 0x07, 
+        0x30, 0x30, 0x34, 0xb7, 0xba, 0x35, 0x1c, 0x00, 0x0c, 0x04, 0x00, 0x53, 0x20, 0x52, 0x42, 0x04, 
+        0x3d, 0x0d, 0x2d, 0x0c, 0x49, 0x0c, 0x45, 0x9d, 0xff, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x72, 0x0c, 0x04, 0x0c, 0x68, 0x62, 0x00, 0x00, 0x82, 0x4c, 0x11, 0x77, 
+        0x96, 0x0e, 0x2d, 0x0c, 0x0c, 0x03, 0x45, 0xa1, 0xff, 0x06, 0xf7, 0xff, 0x3c, 0x00, 0x86, 0xf1, 
+        0xff, 0x2d, 0x0c, 0x85, 0x84, 0xff, 0xc6, 0xf3, 0xff, 0xa2, 0x0c, 0x04, 0x92, 0x00, 0x00, 0xa7, 
+        0x99, 0x1a, 0xb8, 0xa0, 0xd7, 0x9b, 0x3a, 0x08, 0x7d, 0x08, 0x00, 0xc7, 0xf0, 0x33, 0xb7, 0xf0, 
+        0x30, 0x28, 0x0d, 0x87, 0x70, 0x1e, 0x08, 0x12, 0x4b, 0x00, 0x46, 0x06, 0x00, 0x22, 0x0c, 0x11, 
+        0x26, 0x12, 0x28, 0x21, 0xbd, 0xfb, 0x31, 0xbd, 0xfb, 0x42, 0xa4, 0x3b, 0x01, 0x81, 0xe6, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0x08, 0x12, 0x32, 0x00, 0x01, 0x0c, 0x84, 0x40, 0x33, 0x20, 0x32, 
+        0x40, 0x01, 0x2d, 0x0c, 0x0c, 0x13, 0x45, 0x9b, 0xff, 0x06, 0xdf, 0xff, 0xc0, 0x2c, 0x20, 0x32, 
+        0xa0, 0x00, 0x52, 0xa0, 0x04, 0x52, 0x4c, 0x11, 0x45, 0x00, 0x00, 0x86, 0xda, 0xff, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x02, 0x02, 0x61, 0x01, 0x02, 0x02, 0x0e, 0xcd, 0x02, 0xec, 0x70, 
+        0x02, 0x02, 0x0b, 0x16, 0xb3, 0x03, 0x16, 0x80, 0x08, 0x22, 0x02, 0x04, 0x45, 0x8f, 0x06, 0x0c, 
+        0x03, 0x0c, 0x12, 0x0c, 0x04, 0x22, 0x4c, 0x11, 0x22, 0x0c, 0x04, 0xc5, 0x7e, 0x06, 0x0c, 0x12, 
+        0xc8, 0x21, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x32, 0xa0, 0x00, 0x32, 0x42, 0x0e, 0x22, 
+        0x22, 0x00, 0xc5, 0x03, 0x04, 0x22, 0xa0, 0x00, 0x0c, 0x04, 0x49, 0x0c, 0x42, 0x4c, 0x11, 0x46, 
+        0xf7, 0xff, 0x16, 0x10, 0x06, 0x22, 0x22, 0x00, 0x32, 0x22, 0x07, 0x28, 0x52, 0x42, 0x13, 0x03, 
+        0x52, 0x03, 0x08, 0x59, 0x01, 0x40, 0x47, 0x41, 0x42, 0x5c, 0x0b, 0xc5, 0x3b, 0x05, 0x28, 0x0c, 
+        0x08, 0x72, 0x78, 0x01, 0x62, 0x00, 0x08, 0x77, 0x16, 0x06, 0x85, 0x23, 0x04, 0x08, 0x0c, 0x08, 
+        0x70, 0x22, 0x9c, 0x0b, 0x42, 0x10, 0x03, 0x32, 0x10, 0x05, 0x40, 0x47, 0x41, 0x40, 0x33, 0xc0, 
+        0x30, 0x22, 0x80, 0x22, 0x5c, 0x0b, 0xc0, 0x2c, 0x20, 0x85, 0x4b, 0x00, 0x22, 0xa0, 0x01, 0x46, 
+        0xe3, 0xff, 0x32, 0xa0, 0x00, 0x05, 0x7d, 0xff, 0x22, 0x2c, 0x00, 0x32, 0x0c, 0x04, 0x05, 0x36, 
+        0x00, 0x22, 0xa0, 0x00, 0x06, 0xde, 0xff, 0x32, 0xa0, 0x00, 0xc5, 0x7b, 0xff, 0x32, 0x2c, 0x00, 
+        0x28, 0x53, 0x38, 0x73, 0x05, 0x36, 0x05, 0x28, 0x0c, 0x32, 0x0c, 0x04, 0x05, 0x34, 0x00, 0x0c, 
+        0x02, 0xc6, 0xd6, 0xff, 0x3f, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x52, 0x02, 0x0a, 0x09, 0x01, 
+        0xc9, 0x11, 0xd9, 0x21, 0xd1, 0x69, 0xfb, 0xcd, 0x02, 0x02, 0x0d, 0x0c, 0x2d, 0x05, 0x07, 0xb5, 
+        0x0a, 0x1b, 0x25, 0x22, 0x4c, 0x0a, 0x02, 0x0d, 0x0c, 0x20, 0x20, 0x74, 0x07, 0xb2, 0x10, 0x02, 
+        0x0c, 0x06, 0x32, 0x0c, 0x08, 0x1b, 0x40, 0x37, 0xb0, 0x0b, 0x42, 0x4c, 0x06, 0x46, 0x01, 0x00, 
+        0x52, 0x0c, 0x07, 0x52, 0x4c, 0x06, 0x28, 0xad, 0x62, 0x0d, 0x00, 0x98, 0x72, 0x81, 0xed, 0xff, 
+        0xa2, 0x09, 0x06, 0xb2, 0x09, 0x05, 0x80, 0xaa, 0x11, 0xb0, 0xaa, 0x20, 0x80, 0x8a, 0x10, 0xa0, 
+        0xa6, 0x54, 0x1b, 0xaa, 0xa0, 0xa0, 0x54, 0xa0, 0xaa, 0x11, 0xa0, 0x88, 0x20, 0x82, 0x49, 0x05, 
+        0x80, 0x88, 0x41, 0x82, 0x49, 0x06, 0x72, 0x0c, 0x04, 0x77, 0x96, 0x18, 0x08, 0x72, 0x32, 0x00, 
+        0x04, 0x30, 0xb0, 0x34, 0x30, 0x34, 0x41, 0x1b, 0x33, 0x30, 0x30, 0x34, 0xc0, 0x33, 0x11, 0x30, 
+        0xbb, 0x20, 0xb2, 0x40, 0x04, 0x02, 0x0c, 0x11, 0x26, 0x20, 0x14, 0x26, 0x10, 0x11, 0x21, 0x52, 
+        0xfb, 0x31, 0x52, 0xfb, 0x42, 0xa4, 0x8b, 0x01, 0x16, 0xe6, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 
+        0x22, 0x22, 0x07, 0x85, 0x78, 0x05, 0x56, 0xe2, 0x01, 0x22, 0x2d, 0x0a, 0x68, 0x72, 0x52, 0x0d, 
+        0x0c, 0x42, 0x06, 0x06, 0x62, 0x06, 0x05, 0x80, 0x44, 0x11, 0x60, 0x44, 0x20, 0x40, 0x46, 0x54, 
+        0x57, 0xb4, 0x04, 0xc5, 0xca, 0xff, 0xac, 0x62, 0x82, 0x0c, 0x04, 0x0c, 0x69, 0x72, 0x0d, 0x00, 
+        0x92, 0x4c, 0x11, 0x87, 0x97, 0x09, 0x2d, 0x0c, 0x0c, 0x03, 0x05, 0x7e, 0xff, 0x06, 0x01, 0x00, 
+        0x2d, 0x0c, 0x85, 0x61, 0xff, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0xb2, 0x0c, 0x04, 0xa2, 0x0d, 0x00, 0xb7, 0x9a, 0x2b, 0x28, 0xad, 0x48, 0x72, 0x48, 0x04, 0xc7, 
+        0xf4, 0x18, 0x08, 0x02, 0x87, 0x74, 0x06, 0x08, 0x10, 0x4b, 0x00, 0x46, 0x00, 0x00, 0x08, 0x10, 
+        0x22, 0x00, 0x01, 0x0c, 0x83, 0x30, 0x22, 0x20, 0x22, 0x40, 0x01, 0x2d, 0x0c, 0x0c, 0x13, 0xc5, 
+        0x79, 0xff, 0xc6, 0xef, 0xff, 0x42, 0x0c, 0x11, 0x26, 0x14, 0x11, 0x21, 0x2b, 0xfb, 0x31, 0x2b, 
+        0xfb, 0x42, 0xa4, 0xa1, 0x01, 0xef, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x2d, 0x0c, 0x0c, 
+        0x03, 0x0c, 0x45, 0x52, 0x4c, 0x11, 0x85, 0xdd, 0xff, 0x06, 0xe6, 0xff, 0x31, 0x1c, 0xfb, 0x12, 
+        0xc1, 0xf0, 0x09, 0x01, 0x20, 0x02, 0xb0, 0x30, 0x20, 0xa0, 0x38, 0x02, 0xdc, 0x03, 0x21, 0x1e, 
+        0xfb, 0x31, 0x1e, 0xfb, 0x42, 0xa4, 0xb7, 0x01, 0xe2, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 
+        0x42, 0x02, 0x11, 0x26, 0x14, 0x11, 0x21, 0x18, 0xfb, 0x31, 0x18, 0xfb, 0x42, 0xa4, 0xb8, 0x01, 
+        0xdc, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x0c, 0x14, 0xc5, 0xbe, 0xff, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x05, 0xc1, 0xfe, 0xdc, 0x02, 0x21, 0x0e, 
+        0xfb, 0x31, 0x0e, 0xfb, 0x42, 0xa4, 0xc9, 0x01, 0xd2, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 
+        0x41, 0xfe, 0xfa, 0x38, 0xa4, 0x22, 0x04, 0x00, 0x52, 0x04, 0x00, 0x08, 0x73, 0x42, 0xc4, 0x30, 
+        0x50, 0x22, 0xb0, 0x08, 0x00, 0x40, 0x22, 0xa0, 0xe7, 0x60, 0x10, 0x0c, 0x06, 0x72, 0x02, 0x07, 
+        0x72, 0x42, 0x06, 0x62, 0x42, 0x09, 0x05, 0xe2, 0xff, 0x06, 0x01, 0x00, 0x0c, 0x04, 0x85, 0xb9, 
+        0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x31, 0xf0, 0xfa, 0x22, 0x43, 0x00, 0x0d, 0xf0, 
+        0x10, 0x8c, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0xdd, 
+        0x03, 0x85, 0xba, 0xfe, 0xdc, 0x02, 0x21, 0xf4, 0xfa, 0x31, 0xf4, 0xfa, 0x42, 0xa4, 0xe6, 0x01, 
+        0xb8, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xe4, 0xfa, 0x02, 0x02, 0x00, 0x07, 0x1d, 
+        0x11, 0x21, 0xed, 0xfa, 0x31, 0xee, 0xfa, 0x42, 0xa4, 0xe7, 0x01, 0xb1, 0xe5, 0xc0, 0x00, 0x00, 
+        0x06, 0xff, 0xff, 0x26, 0x1c, 0x38, 0x32, 0xa0, 0xc0, 0x37, 0x1c, 0x1c, 0x21, 0xed, 0xff, 0x3d, 
+        0x0c, 0x01, 0xab, 0xe5, 0xc0, 0x00, 0x00, 0x21, 0xe4, 0xfa, 0x31, 0xe4, 0xfa, 0x42, 0xa4, 0xf7, 
+        0x01, 0xa8, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x0c, 0x03, 0x0c, 0x64, 0x22, 0xc2, 0x30, 
+        0x00, 0x50, 0xb0, 0x20, 0x25, 0xa0, 0x42, 0x42, 0x11, 0x05, 0x65, 0xff, 0x06, 0x01, 0x00, 0x2d, 
+        0x0d, 0x85, 0xed, 0xff, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x24, 0x8c, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0xc5, 0xb1, 0xfe, 
+        0xdc, 0x02, 0x21, 0xd1, 0xfa, 0x31, 0xd1, 0xfa, 0x42, 0xa5, 0x0a, 0x01, 0x95, 0xe5, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0x26, 0x1c, 0x41, 0x02, 0xa0, 0xc0, 0x07, 0x1c, 0x1c, 0x21, 0xf4, 0xff, 
+        0x3d, 0x0c, 0x01, 0x8f, 0xe5, 0xc0, 0x00, 0x00, 0x21, 0xc8, 0xfa, 0x31, 0xc8, 0xfa, 0x42, 0xa5, 
+        0x1a, 0x01, 0x8b, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x0c, 0x03, 0x51, 0xb7, 0xfa, 0x0c, 
+        0x64, 0x22, 0x05, 0x00, 0x62, 0x05, 0x00, 0x52, 0xc5, 0x30, 0x60, 0x22, 0xb0, 0x50, 0x22, 0xa0, 
+        0x42, 0x42, 0x11, 0x85, 0x5d, 0xff, 0x86, 0x00, 0x00, 0x85, 0xea, 0xff, 0xc8, 0x11, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x2a, 0x09, 0x00, 0x00, 0x21, 0x6e, 0xf1, 0x42, 
+        0xa1, 0x5f, 0x0c, 0x95, 0x61, 0xfd, 0xff, 0x0c, 0x77, 0x31, 0xa7, 0xfa, 0x82, 0xa2, 0x00, 0x89, 
+        0x13, 0x89, 0x23, 0x72, 0x43, 0x0d, 0x72, 0x43, 0x0c, 0x62, 0x53, 0x08, 0x62, 0x53, 0x07, 0x52, 
+        0x53, 0x0a, 0x42, 0x53, 0x0e, 0x22, 0x53, 0x0f, 0x0d, 0xf0, 0x00, 0x00, 0xff, 0xef, 0xff, 0x03, 
+        0x12, 0xc1, 0xf0, 0xc9, 0x31, 0x09, 0x21, 0x01, 0xa1, 0xfa, 0x30, 0xc3, 0xb0, 0x00, 0xcc, 0xa0, 
+        0x02, 0x0c, 0x11, 0x9c, 0x60, 0x26, 0x30, 0x14, 0x26, 0x40, 0x2a, 0x21, 0xa3, 0xfa, 0x31, 0xa3, 
+        0xfa, 0x42, 0xa5, 0xb9, 0x01, 0x67, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x26, 0x40, 0x15, 
+        0x29, 0x0c, 0xec, 0xa2, 0x21, 0x9d, 0xfa, 0x31, 0x9d, 0xfa, 0x42, 0xa5, 0xc1, 0x01, 0x60, 0xe5, 
+        0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x38, 0x0c, 0x20, 0x33, 0xc0, 0x16, 0x53, 0x0b, 0x21, 0x96, 
+        0xfa, 0x31, 0x96, 0xfa, 0x42, 0xa5, 0xbc, 0x01, 0x5a, 0xe5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 
+        0x82, 0xa1, 0x00, 0x71, 0xe6, 0xff, 0x52, 0x12, 0x08, 0x68, 0x72, 0x41, 0x83, 0xfa, 0x38, 0x06, 
+        0x42, 0x14, 0x07, 0x30, 0x06, 0x41, 0x57, 0xb4, 0x22, 0x77, 0xe3, 0x1f, 0x80, 0x50, 0x20, 0x30, 
+        0x40, 0x54, 0xa0, 0x55, 0x11, 0x50, 0x44, 0x20, 0x40, 0x30, 0x54, 0x40, 0x46, 0x41, 0x70, 0x44, 
+        0x10, 0xa0, 0x44, 0x11, 0x40, 0x33, 0x20, 0x39, 0x06, 0x30, 0x06, 0x41, 0xc7, 0x60, 0x5d, 0x92, 
+        0x0c, 0x11, 0x66, 0x39, 0x57, 0xa2, 0x06, 0x04, 0xa0, 0xa4, 0x41, 0xa6, 0x3a, 0x4e, 0x41, 0x05, 
+        0xff, 0x30, 0x90, 0x54, 0x52, 0x06, 0x05, 0x80, 0xa0, 0x20, 0xa0, 0xaa, 0x11, 0x50, 0xb0, 0x54, 
+        0xa0, 0x99, 0x20, 0x90, 0xa6, 0x41, 0x70, 0xaa, 0x10, 0x90, 0x90, 0x54, 0xa0, 0xaa, 0x11, 0xa0, 
+        0x99, 0x20, 0xa2, 0x06, 0x06, 0xa0, 0xbb, 0x11, 0x80, 0xaa, 0x11, 0x50, 0xaa, 0x20, 0x40, 0xaa, 
+        0x10, 0xb0, 0xaa, 0x20, 0xa2, 0x46, 0x05, 0xa0, 0xa8, 0x41, 0xa2, 0x46, 0x06, 0x48, 0x72, 0x99, 
+        0x06, 0xb2, 0x04, 0x05, 0x52, 0xa0, 0xc0, 0x50, 0xbb, 0x10, 0xb2, 0x44, 0x05, 0x2d, 0x0c, 0x0c, 
+        0x03, 0xc5, 0xa3, 0xfe, 0xb2, 0x0c, 0x06, 0xb2, 0x61, 0x00, 0x85, 0xba, 0x07, 0x29, 0x11, 0x85, 
+        0xaa, 0xfa, 0x32, 0x0c, 0x05, 0x68, 0x01, 0x1c, 0xf5, 0x48, 0x11, 0x60, 0x55, 0xc0, 0x00, 0x05, 
+        0x40, 0x0c, 0x15, 0x40, 0x40, 0xb1, 0x40, 0x41, 0x41, 0x52, 0x4c, 0x11, 0x40, 0x42, 0x82, 0x22, 
+        0x0c, 0x04, 0x40, 0x42, 0xf4, 0x05, 0x2d, 0x06, 0xc8, 0x31, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x32, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 
+        0xcd, 0x02, 0xc5, 0x9e, 0xfe, 0x22, 0x0c, 0x04, 0x0c, 0x03, 0x0c, 0x04, 0x0c, 0x10, 0x02, 0x4c, 
+        0x11, 0x45, 0x2a, 0x06, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0xa0, 0x80, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x29, 0x01, 0x09, 0x11, 0x01, 0xde, 0xe8, 0xc0, 0x00, 
+        0x00, 0x0c, 0x00, 0x21, 0xfb, 0xff, 0x38, 0x01, 0x32, 0x42, 0x00, 0x09, 0x22, 0x09, 0x32, 0x09, 
+        0x12, 0x09, 0x42, 0x01, 0xd9, 0xe8, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 0x30, 0xc3, 0x20, 0x01, 0xf1, 0xff, 0x32, 
+        0x03, 0x08, 0x02, 0x00, 0x00, 0x30, 0x00, 0xc0, 0x56, 0xb0, 0x0a, 0x05, 0x6a, 0x05, 0x16, 0xd2, 
+        0x07, 0x02, 0x0c, 0x08, 0xb6, 0xb0, 0x77, 0x22, 0xc0, 0xf0, 0x20, 0x20, 0x24, 0xa6, 0x32, 0x6e, 
+        0x38, 0x0c, 0x51, 0xe7, 0xff, 0x30, 0x3c, 0x05, 0x16, 0xb3, 0x08, 0x48, 0x25, 0x78, 0x45, 0x02, 
+        0x0c, 0x05, 0xb8, 0x35, 0x00, 0x00, 0x54, 0x0a, 0xbb, 0xb9, 0x35, 0xa2, 0x0c, 0x04, 0x98, 0x15, 
+        0xa0, 0xa4, 0x41, 0xaa, 0x99, 0x99, 0x15, 0x82, 0x0c, 0x06, 0x92, 0x0c, 0x05, 0x80, 0x88, 0x11, 
+        0x90, 0x88, 0x20, 0x92, 0x0c, 0x04, 0x80, 0x86, 0x54, 0x90, 0x94, 0x41, 0x90, 0x88, 0x82, 0x8a, 
+        0x77, 0x79, 0x45, 0x72, 0x0c, 0x05, 0x62, 0x0c, 0x06, 0x82, 0x0c, 0x0f, 0x80, 0x66, 0x11, 0x0b, 
+        0x88, 0x70, 0x66, 0x20, 0x72, 0x0c, 0x04, 0x60, 0x66, 0x54, 0x70, 0x74, 0x41, 0x1b, 0x97, 0x60, 
+        0x77, 0x82, 0x90, 0x66, 0x82, 0x80, 0x67, 0x93, 0x6a, 0x44, 0x49, 0x25, 0xc6, 0x09, 0x00, 0x41, 
+        0xcc, 0xff, 0x22, 0x0c, 0x04, 0x08, 0x24, 0x20, 0x24, 0x41, 0x2a, 0x00, 0x1b, 0x30, 0x39, 0x24, 
+        0x22, 0x0c, 0x0f, 0x51, 0xc7, 0xff, 0x66, 0x12, 0x07, 0x38, 0x34, 0x09, 0x24, 0x1b, 0x33, 0x39, 
+        0x34, 0x48, 0x15, 0x1b, 0x44, 0x49, 0x15, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x31, 0xc0, 0xff, 0x72, 0x03, 0x00, 0x79, 0x02, 0x68, 0x43, 0x69, 0x12, 0x58, 0x13, 0x59, 0x22, 
+        0x48, 0x23, 0x49, 0x32, 0x38, 0x33, 0x39, 0x42, 0x0c, 0x52, 0x0d, 0xf0, 0xd8, 0x8d, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x03, 0xcd, 0x02, 0x05, 0x1d, 
+        0x03, 0x38, 0x7c, 0x08, 0x03, 0x97, 0x60, 0x07, 0xc7, 0xf0, 0x04, 0x28, 0x5c, 0x05, 0x64, 0x04, 
+        0x0c, 0x42, 0xc5, 0x9d, 0x03, 0x16, 0xcd, 0x04, 0x28, 0x7c, 0x22, 0x02, 0x06, 0x01, 0xf3, 0xf9, 
+        0x20, 0x24, 0x24, 0x20, 0xd2, 0xb0, 0x00, 0xdd, 0xa0, 0x45, 0x7c, 0xfe, 0xcc, 0xa2, 0x32, 0x0d, 
+        0x12, 0x21, 0xee, 0xff, 0x01, 0xbb, 0xe4, 0xc0, 0x00, 0x00, 0x28, 0x7c, 0x22, 0x02, 0x06, 0x20, 
+        0x24, 0x24, 0xc5, 0x7a, 0xfe, 0xdc, 0x02, 0x21, 0xf0, 0xf9, 0x31, 0xf0, 0xf9, 0x42, 0xa6, 0x4b, 
+        0x01, 0xb4, 0xe4, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x22, 0x2c, 0x07, 0x22, 0x02, 0x06, 0x20, 
+        0x24, 0x24, 0x85, 0x0f, 0x02, 0xc2, 0x21, 0x01, 0xd2, 0x21, 0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x45, 0x1c, 0x03, 0x22, 0xa0, 0x05, 
+        0xc5, 0x96, 0x03, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x40, 0x22, 0x11, 0x12, 
+        0xc1, 0xf0, 0x02, 0x61, 0x00, 0x45, 0xa3, 0x08, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x80, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x30, 0x22, 0x82, 0x20, 0x2c, 0x41, 0x0d, 0xf0, 0xc0, 0x22, 0xff, 0x3f, 
+        0x51, 0xff, 0xff, 0x41, 0x83, 0xe4, 0xc0, 0x20, 0x00, 0x32, 0x24, 0x47, 0x39, 0x05, 0x3a, 0x32, 
+        0x39, 0x15, 0xc0, 0x20, 0x00, 0x32, 0x64, 0x41, 0x0d, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xff, 
+        0x00, 0x00, 0x01, 0x00, 0x12, 0xc1, 0xf0, 0x39, 0x01, 0x09, 0x11, 0x01, 0xab, 0xf2, 0xc9, 0x21, 
+        0x02, 0x00, 0x39, 0xc1, 0x77, 0xe4, 0xdc, 0x20, 0x7c, 0xc5, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0x59, 
+        0x50, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x6c, 0x59, 0x86, 0x07, 0x00, 0x66, 0x10, 0x07, 0x2c, 
+        0x06, 0x60, 0x44, 0x20, 0xc6, 0x04, 0x00, 0x66, 0x20, 0x10, 0x0c, 0x38, 0xc0, 0x20, 0x00, 0x72, 
+        0x2c, 0x59, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x6c, 0x59, 0x0c, 0x03, 0x01, 0xf6, 0xeb, 
+        0xc0, 0x20, 0x00, 0x32, 0x6c, 0x50, 0xc0, 0x20, 0x00, 0x22, 0x6c, 0x51, 0xc0, 0x20, 0x00, 0x22, 
+        0xa0, 0x77, 0x0c, 0x55, 0x0c, 0x56, 0x0c, 0x17, 0x08, 0x00, 0x42, 0x6c, 0x40, 0x02, 0x20, 0x27, 
+        0x1c, 0xc4, 0xc0, 0x00, 0x00, 0x51, 0xe1, 0xff, 0x41, 0xe2, 0xff, 0x31, 0x6a, 0xe5, 0xc0, 0x20, 
+        0x00, 0x22, 0x23, 0xf2, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xf2, 
+        0x0c, 0x12, 0x01, 0x83, 0xe6, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x77, 0x0c, 0x03, 0x1c, 0xc4, 0x01, 
+        0xe2, 0xeb, 0x0c, 0x55, 0x08, 0x00, 0x0c, 0x56, 0x02, 0x20, 0x27, 0x0c, 0x07, 0xc0, 0x00, 0x00, 
+        0xc0, 0x20, 0x00, 0x28, 0x01, 0x08, 0x11, 0x22, 0x6c, 0x44, 0xc8, 0x21, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x82, 0xaf, 0xc0, 0x51, 0x4a, 0xe4, 0xc0, 0x20, 0x00, 0x72, 0x25, 0x46, 
+        0x80, 0x77, 0x10, 0x20, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x65, 0x46, 0x7c, 0xe6, 0xc0, 0x20, 
+        0x00, 0x42, 0x25, 0x6a, 0x60, 0x44, 0x10, 0x30, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x65, 0x6a, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x31, 0xc5, 0xe5, 0x41, 0xfb, 0xff, 0x01, 0x4f, 0xe4, 0xc0, 0x20, 
+        0x00, 0x22, 0x20, 0x96, 0x30, 0x22, 0x10, 0x20, 0x2f, 0x41, 0x66, 0x12, 0x2c, 0xc0, 0x20, 0x00, 
+        0x02, 0x20, 0x95, 0x40, 0x50, 0x10, 0x50, 0x58, 0x75, 0x26, 0x25, 0x0c, 0x0c, 0x42, 0x0c, 0x03, 
+        0x41, 0xf2, 0xff, 0x05, 0xed, 0xff, 0x46, 0x02, 0x00, 0x0c, 0x42, 0x0c, 0x03, 0x41, 0xef, 0xff, 
+        0x05, 0xec, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x02, 0x20, 0x97, 
+        0xc6, 0xf3, 0xff, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x31, 0xb0, 0xe5, 0x41, 0xe6, 0xff, 0x01, 
+        0x3a, 0xe4, 0xc0, 0x20, 0x00, 0x22, 0x20, 0x96, 0x30, 0x22, 0x10, 0x20, 0x2f, 0x41, 0x66, 0x12, 
+        0x2c, 0xc0, 0x20, 0x00, 0x02, 0x20, 0x95, 0x40, 0x50, 0x10, 0x50, 0x58, 0x75, 0x26, 0x25, 0x0c, 
+        0x0c, 0x02, 0x0c, 0x03, 0x41, 0xdd, 0xff, 0xc5, 0xe7, 0xff, 0x46, 0x02, 0x00, 0x0c, 0x02, 0x0c, 
+        0x03, 0x41, 0xda, 0xff, 0xc5, 0xe6, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xc0, 0x20, 
+        0x00, 0x02, 0x20, 0x97, 0xc6, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0xc9, 0x11, 0xd9, 0x21, 0x51, 0xb2, 0xe9, 0xdd, 0x02, 0xc1, 0x1a, 0xe5, 0xc0, 0x20, 0x00, 
+        0x42, 0x2c, 0x5c, 0x50, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x6c, 0x5c, 0x32, 0xa1, 0x01, 0xc0, 
+        0x20, 0x00, 0x32, 0x6c, 0x5b, 0x21, 0xf5, 0xef, 0xc0, 0x20, 0x00, 0x02, 0x2c, 0x5b, 0x20, 0x00, 
+        0x20, 0xc0, 0x20, 0x00, 0x22, 0xa0, 0x64, 0x02, 0x6c, 0x5b, 0x01, 0x2d, 0xe6, 0xc0, 0x00, 0x00, 
+        0xc0, 0x20, 0x00, 0x62, 0x2c, 0x5c, 0x96, 0x86, 0x00, 0xc0, 0x20, 0x00, 0x72, 0x2c, 0x5c, 0xd6, 
+        0x67, 0xff, 0x31, 0xfe, 0xef, 0xc0, 0x20, 0x00, 0x01, 0x2c, 0xf2, 0x22, 0x2c, 0x5c, 0x02, 0x00, 
+        0x01, 0x30, 0x22, 0x10, 0x8c, 0x40, 0x26, 0x10, 0x07, 0x26, 0x20, 0x54, 0x2c, 0x83, 0x86, 0x00, 
+        0x00, 0x32, 0xa0, 0x1a, 0xc0, 0x22, 0x11, 0xc2, 0x2d, 0x01, 0x05, 0x7d, 0x08, 0x3d, 0x02, 0xdc, 
+        0x3c, 0x29, 0x1d, 0x21, 0xdd, 0xff, 0x45, 0x7c, 0x08, 0x29, 0x0d, 0xc8, 0x11, 0xd8, 0x21, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x27, 0xbc, 0x05, 0xc0, 0x02, 0xc0, 0x86, 0x00, 0x00, 0x20, 
+        0x0c, 0xc0, 0x22, 0xa1, 0xff, 0x07, 0x32, 0xe2, 0x30, 0x43, 0xa0, 0x21, 0xd3, 0xff, 0xc0, 0x3c, 
+        0x90, 0x4a, 0x33, 0x30, 0x33, 0x41, 0x39, 0x1d, 0x05, 0x79, 0x08, 0x86, 0xf2, 0xff, 0x00, 0x00, 
+        0x00, 0x1c, 0x83, 0x46, 0xeb, 0xff, 0x00, 0x00, 0x64, 0x80, 0x0c, 0x00, 0x21, 0xff, 0xff, 0x31, 
+        0xdc, 0xe3, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x43, 0x0d, 0xf0, 0x00, 0x00, 0x31, 0x0b, 0xf2, 0x22, 
+        0x03, 0x39, 0x32, 0x03, 0x3a, 0x26, 0x22, 0x10, 0x26, 0x13, 0x0d, 0x26, 0x33, 0x0a, 0x0c, 0x23, 
+        0x41, 0xd4, 0xe3, 0xc0, 0x20, 0x00, 0x32, 0x64, 0x68, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 
+        0x7c, 0xf5, 0x31, 0xcf, 0xe3, 0xc0, 0x20, 0x00, 0x52, 0x63, 0x49, 0x41, 0xfc, 0xff, 0xc0, 0x20, 
+        0x00, 0x22, 0x23, 0x42, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x42, 0x0d, 0xf0, 0x00, 
+        0x7c, 0xd4, 0x31, 0x4d, 0xe6, 0xc0, 0x20, 0x00, 0x22, 0x23, 0x9c, 0x40, 0x22, 0x10, 0xc0, 0x20, 
+        0x00, 0x22, 0x63, 0x9c, 0x0d, 0xf0, 0x00, 0x00, 0x31, 0xc2, 0xe3, 0xc0, 0x20, 0x00, 0x22, 0x23, 
+        0x4a, 0x20, 0x20, 0x14, 0xcc, 0xa2, 0xc0, 0x20, 0x00, 0x42, 0x23, 0x4a, 0x40, 0x40, 0x14, 0x16, 
+        0x34, 0xff, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xfe, 0x81, 0xff, 0xff, 0x31, 0xc6, 0xe4, 0x61, 0xb8, 
+        0xe3, 0xc0, 0x20, 0x00, 0x82, 0x66, 0x44, 0x0c, 0x07, 0xc0, 0x20, 0x00, 0x72, 0x66, 0x51, 0x51, 
+        0x2a, 0xf9, 0xc0, 0x20, 0x00, 0x52, 0x66, 0x40, 0x41, 0x35, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x23, 
+        0xf2, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xf2, 0x0d, 0xf0, 0xd0, 0x22, 0xff, 0x3f, 
+        0x22, 0xa0, 0x6a, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x01, 0x37, 0xeb, 0x32, 0xa0, 0x02, 0x02, 
+        0x20, 0x00, 0x0c, 0x84, 0x02, 0x20, 0x26, 0x0c, 0x05, 0xc0, 0x00, 0x00, 0x21, 0xf8, 0xff, 0xc5, 
+        0xe4, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xf2, 0xff, 0x02, 0x00, 0x2c, 0x47, 0xe0, 0x08, 0x45, 0xd8, 0xff, 0x46, 0x01, 0x00, 
+        0x00, 0x00, 0x00, 0x05, 0xdd, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x22, 0x61, 0x00, 0x21, 0xe9, 0xff, 0x02, 0x61, 0x01, 0x28, 0x12, 0xc5, 0xed, 
+        0xff, 0x01, 0xe6, 0xff, 0x02, 0x00, 0x2c, 0x0c, 0x02, 0x07, 0x60, 0x0f, 0x28, 0x01, 0x05, 0xc3, 
+        0xff, 0x01, 0xe2, 0xff, 0x0c, 0x82, 0x02, 0x00, 0x2c, 0xc6, 0xff, 0xff, 0x17, 0x60, 0x04, 0x1c, 
+        0x03, 0x30, 0x22, 0x20, 0x27, 0x60, 0x04, 0x0c, 0x44, 0x40, 0x22, 0x20, 0x00, 0x33, 0x04, 0x45, 
+        0xcf, 0xff, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf1, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x05, 0xf2, 0xff, 0x01, 0x67, 0xe7, 0xc0, 0x00, 0x00, 0x0c, 
+        0x02, 0x05, 0x9a, 0xfc, 0xc5, 0x5d, 0x01, 0x31, 0x6d, 0xef, 0x21, 0xf8, 0xff, 0xc0, 0x20, 0x00, 
+        0x02, 0x22, 0x81, 0x30, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x02, 0x62, 0x81, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x61, 0xca, 0xff, 0x22, 0x06, 0x2e, 0x51, 0xfb, 0xe5, 0xac, 0x12, 0xc0, 
+        0x20, 0x00, 0x42, 0x06, 0x36, 0x52, 0x25, 0x80, 0x28, 0x56, 0x38, 0xa6, 0x50, 0x22, 0xc0, 0x40, 
+        0x33, 0x82, 0x27, 0x33, 0x0c, 0x82, 0x26, 0x11, 0x72, 0x16, 0x12, 0x8a, 0x77, 0x27, 0xb7, 0x01, 
+        0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x87, 0x13, 0x00, 0x00, 0x00, 0x02, 0xf2, 0x3f, 
+        0x34, 0x8c, 0xfe, 0x3f, 0x1c, 0x42, 0x12, 0xc1, 0xe0, 0xc9, 0x11, 0xd9, 0x21, 0xe9, 0x31, 0xf9, 
+        0x41, 0x09, 0x01, 0x01, 0x8f, 0xe5, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0xf1, 0xf7, 0xff, 0xd1, 0xf7, 
+        0xff, 0xe1, 0xda, 0xff, 0xc0, 0x20, 0x00, 0x02, 0x2d, 0x84, 0x00, 0x00, 0x34, 0xcc, 0xa0, 0xc0, 
+        0x20, 0x00, 0x22, 0x2e, 0xf4, 0x20, 0x2c, 0x34, 0x16, 0x32, 0x06, 0x0c, 0x22, 0x01, 0x84, 0xe5, 
+        0xc0, 0x00, 0x00, 0x3d, 0x0c, 0x1b, 0xcc, 0xc0, 0xc0, 0xf4, 0x37, 0xbf, 0xd6, 0x1c, 0x42, 0x01, 
+        0x80, 0xe5, 0xc0, 0x00, 0x00, 0xf2, 0xa7, 0xcf, 0xc0, 0x20, 0x00, 0x02, 0x2d, 0x84, 0x00, 0x00, 
+        0x34, 0xcc, 0x90, 0xc0, 0x20, 0x00, 0x22, 0x2e, 0xf4, 0x20, 0x2c, 0x34, 0xac, 0xf2, 0x0c, 0x22, 
+        0x01, 0x78, 0xe5, 0xc0, 0x00, 0x00, 0x3d, 0x0c, 0x1b, 0xcc, 0xc0, 0xc0, 0xf4, 0x37, 0xbf, 0xd7, 
+        0x0c, 0x0c, 0x21, 0xdf, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x2d, 0x84, 0xc0, 0x20, 0x00, 0x42, 0x2e, 
+        0xf4, 0x01, 0x5b, 0xe3, 0xc0, 0x00, 0x00, 0x1b, 0xcc, 0xc0, 0xc0, 0xf4, 0x66, 0xdc, 0xe2, 0xc8, 
+        0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0x64, 0x89, 0xfe, 0x3f, 0x58, 0x8c, 0xfe, 0x3f, 0x60, 0x8c, 0xfe, 0x3f, 0x3f, 0xfe, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x02, 0x09, 0x11, 0xcd, 0x02, 0x45, 0xe2, 0xff, 0x31, 0x87, 0xff, 
+        0x22, 0x23, 0x11, 0x38, 0x13, 0x20, 0x2c, 0xc0, 0x05, 0xa9, 0xff, 0xcd, 0x02, 0x51, 0xb6, 0xe5, 
+        0xc0, 0x20, 0x00, 0x42, 0xa1, 0x2c, 0x52, 0x25, 0x80, 0x59, 0x01, 0x27, 0x34, 0x02, 0x46, 0x22, 
+        0x00, 0x85, 0xe2, 0xff, 0x81, 0xcf, 0xe8, 0x71, 0xa5, 0xff, 0xc0, 0x20, 0x00, 0x62, 0x27, 0x81, 
+        0x80, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 0x67, 0x81, 0x0c, 0x12, 0x0c, 0x13, 0x05, 0x25, 0xfb, 
+        0x05, 0xef, 0xff, 0xc0, 0x20, 0x00, 0x48, 0x01, 0x21, 0xa8, 0xe5, 0x31, 0x74, 0xff, 0x22, 0x22, 
+        0x80, 0x38, 0x13, 0x40, 0x22, 0xc0, 0x45, 0xa4, 0xff, 0x29, 0x31, 0x01, 0x02, 0xe7, 0xc0, 0x00, 
+        0x00, 0x42, 0xa1, 0xff, 0x08, 0x31, 0x31, 0x4b, 0xe3, 0xc0, 0x20, 0x00, 0x32, 0x23, 0x6a, 0x22, 
+        0xae, 0xd4, 0x47, 0x93, 0x47, 0x2a, 0x5c, 0x42, 0xa3, 0xe8, 0x4a, 0x40, 0x57, 0xb4, 0x3d, 0x00, 
+        0x5c, 0xc0, 0x2a, 0x25, 0x85, 0xde, 0xff, 0xc1, 0x65, 0xff, 0x02, 0x0c, 0x2d, 0x72, 0x0c, 0x2c, 
+        0x00, 0x61, 0x24, 0x26, 0x26, 0x34, 0x07, 0x67, 0x31, 0x21, 0xd1, 0xff, 0x31, 0xd2, 0xff, 0x42, 
+        0xa0, 0xea, 0x01, 0x23, 0xe3, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xcf, 0xff, 0x01, 0x20, 
+        0xe3, 0xc0, 0x00, 0x00, 0x01, 0xed, 0xe6, 0xc0, 0x00, 0x00, 0x86, 0x00, 0x00, 0x05, 0xe0, 0xff, 
+        0x0c, 0x12, 0xc8, 0x21, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xa2, 0x0c, 0x2c, 0x92, 0xa0, 
+        0x06, 0x82, 0xa0, 0xf1, 0x80, 0x80, 0x10, 0x90, 0x88, 0x20, 0x80, 0x80, 0x74, 0x91, 0xc3, 0xff, 
+        0x80, 0x88, 0x11, 0xa0, 0x88, 0x20, 0x90, 0x88, 0x10, 0x82, 0x4c, 0x2c, 0x80, 0x88, 0x41, 0x82, 
+        0x4c, 0x2d, 0x85, 0xc7, 0xff, 0xa1, 0xf6, 0xe2, 0xc0, 0x20, 0x00, 0xa2, 0x2a, 0x47, 0xa9, 0x7c, 
+        0xc0, 0x20, 0x00, 0x91, 0x79, 0xe5, 0x92, 0x29, 0x80, 0x99, 0x8c, 0x45, 0xc8, 0xff, 0x85, 0xcb, 
+        0xff, 0x0c, 0x02, 0xc6, 0xea, 0xff, 0x00, 0x00, 0x6c, 0x23, 0xff, 0x3f, 0x70, 0x8c, 0xfe, 0x3f, 
+        0x98, 0x7b, 0x10, 0x40, 0xc0, 0x0d, 0x00, 0x40, 0x21, 0xfc, 0xff, 0x12, 0xc1, 0xf0, 0x02, 0x61, 
+        0x00, 0x01, 0xd5, 0xe6, 0xc0, 0x00, 0x00, 0x01, 0x39, 0xff, 0x02, 0x00, 0x34, 0x56, 0x00, 0x02, 
+        0x31, 0x37, 0xff, 0x22, 0xa0, 0x00, 0x22, 0x43, 0x35, 0x21, 0xf4, 0xff, 0x01, 0xf9, 0xe2, 0xc0, 
+        0x00, 0x00, 0x05, 0x49, 0xf9, 0x21, 0xf2, 0xff, 0x31, 0x31, 0xff, 0x01, 0xf2, 0xff, 0xc0, 0x00, 
+        0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x45, 0x47, 
+        0xf9, 0x31, 0x2a, 0xff, 0x21, 0xeb, 0xff, 0x01, 0xeb, 0xff, 0xc0, 0x00, 0x00, 0x21, 0x27, 0xff, 
+        0x02, 0x02, 0x2d, 0x32, 0xa0, 0xf1, 0x30, 0x00, 0x10, 0x32, 0xa0, 0x04, 0x30, 0x00, 0x20, 0x02, 
+        0x42, 0x2d, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x30, 0x23, 0xff, 0x3f, 
+        0x74, 0x8c, 0xfe, 0x3f, 0x00, 0x90, 0x01, 0x00, 0x1c, 0x23, 0xff, 0x3f, 0x91, 0xfc, 0xff, 0x12, 
+        0xc1, 0xe0, 0x09, 0x01, 0xf9, 0x41, 0xe9, 0x31, 0xd9, 0x21, 0xc9, 0x11, 0xc2, 0xc9, 0xec, 0xd2, 
+        0xc9, 0xa0, 0xe1, 0x49, 0xe5, 0xc0, 0x20, 0x00, 0x02, 0x0d, 0x2e, 0x32, 0xa0, 0xf1, 0x22, 0x0d, 
+        0x2d, 0xe2, 0x2e, 0x80, 0x30, 0x22, 0x10, 0x0c, 0x83, 0x30, 0x22, 0x20, 0x22, 0x4d, 0x2d, 0x16, 
+        0x10, 0x09, 0x58, 0x4d, 0x38, 0xad, 0xe0, 0xf5, 0xc0, 0xf7, 0xb3, 0x4c, 0x0c, 0x0c, 0x42, 0x0d, 
+        0x36, 0xf2, 0xa0, 0x64, 0x1b, 0xcc, 0x30, 0x64, 0x82, 0x59, 0x6d, 0x08, 0x5d, 0x5a, 0x53, 0x59, 
+        0x4d, 0x50, 0x20, 0xc0, 0x27, 0xb6, 0x03, 0x0a, 0x76, 0x79, 0x5d, 0xf7, 0x9c, 0x24, 0x21, 0xe4, 
+        0xff, 0x6d, 0x0e, 0x01, 0xc7, 0xe2, 0xc0, 0x00, 0x00, 0x91, 0xe0, 0xff, 0x58, 0x4d, 0xa1, 0xe1, 
+        0xff, 0x38, 0xad, 0x42, 0x0d, 0x36, 0x0c, 0x1b, 0x40, 0x4b, 0x83, 0x42, 0x4d, 0x36, 0x30, 0x3a, 
+        0x83, 0x39, 0xad, 0xe0, 0x85, 0xc0, 0x87, 0x33, 0xba, 0x90, 0x29, 0x20, 0xc1, 0xdb, 0xff, 0x01, 
+        0x92, 0xe6, 0xc0, 0x00, 0x00, 0xc0, 0x2c, 0x20, 0x01, 0x90, 0xe6, 0xc0, 0x00, 0x00, 0x32, 0xa3, 
+        0xe8, 0x42, 0x2d, 0x11, 0x52, 0x2d, 0x04, 0x22, 0x2d, 0x12, 0xe0, 0x55, 0xc0, 0x5a, 0x22, 0x40, 
+        0x22, 0xc0, 0x85, 0x27, 0x08, 0x3d, 0x02, 0x0c, 0x04, 0x2d, 0x0c, 0x01, 0x89, 0xe6, 0xc0, 0x00, 
+        0x00, 0x06, 0x07, 0x00, 0x2d, 0x09, 0x01, 0x84, 0xe6, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x01, 0x82, 
+        0xe6, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x32, 0xa0, 0x69, 0x0c, 0x04, 0x01, 0x81, 0xe6, 0xc0, 0x00, 
+        0x00, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x0c, 0x02, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc5, 0xdb, 0x00, 0x21, 0xdc, 0xfe, 0x02, 0x02, 0x2d, 
+        0x32, 0xa0, 0xf1, 0x30, 0x00, 0x10, 0x0c, 0xc3, 0x30, 0x00, 0x20, 0x02, 0x42, 0x2d, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x21, 0xd4, 0xfe, 0x02, 0x61, 
+        0x00, 0x02, 0x02, 0x2d, 0x32, 0xa0, 0xf1, 0x30, 0x00, 0x10, 0x02, 0x42, 0x2d, 0x45, 0x59, 0x01, 
+        0x21, 0xcf, 0xfe, 0x22, 0x02, 0x38, 0x85, 0x43, 0x06, 0x16, 0x72, 0x00, 0x31, 0xcc, 0xfe, 0x32, 
+        0x03, 0x30, 0x8c, 0x13, 0x05, 0xe3, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x22, 0xa0, 0x00, 0x32, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x09, 0x01, 0x01, 0x85, 
+        0xff, 0xc0, 0x00, 0x00, 0xc1, 0xc2, 0xfe, 0x32, 0xa0, 0xbf, 0x02, 0x0c, 0x2d, 0x22, 0xcc, 0x4c, 
+        0x30, 0x00, 0x10, 0x02, 0x4c, 0x2d, 0x01, 0x58, 0xe6, 0xc0, 0x00, 0x00, 0x21, 0x9c, 0xff, 0x01, 
+        0x56, 0xe6, 0xc0, 0x00, 0x00, 0x02, 0x0c, 0x2d, 0x42, 0x0c, 0x33, 0x47, 0xe0, 0x29, 0xec, 0x64, 
+        0x0c, 0x05, 0x52, 0x4c, 0x35, 0x57, 0x60, 0x13, 0x0c, 0xe7, 0x62, 0xa0, 0xf1, 0x60, 0x60, 0x10, 
+        0x70, 0x66, 0x20, 0x62, 0x4c, 0x2d, 0xc5, 0x51, 0x01, 0x86, 0x00, 0x00, 0x85, 0xf6, 0xff, 0xc8, 
+        0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x45, 0xf3, 0xff, 0x06, 0xfc, 0xff, 0x00, 0x00, 
+        0x88, 0x8c, 0xfe, 0x3f, 0xb8, 0x0b, 0x00, 0x00, 0x28, 0x23, 0x00, 0x00, 0x21, 0xfd, 0xff, 0x61, 
+        0xda, 0xe4, 0x71, 0xa6, 0xfe, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x42, 0x07, 0x32, 0x32, 0x07, 0x2d, 
+        0x58, 0x37, 0x30, 0x31, 0x24, 0x78, 0x27, 0xc0, 0x20, 0x00, 0x62, 0x26, 0x80, 0x70, 0x66, 0xc0, 
+        0x01, 0x64, 0xe2, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0xdf, 0x41, 0xf3, 0xff, 0x51, 0xf2, 0xff, 0x31, 
+        0x9b, 0xfe, 0x0c, 0x06, 0x62, 0x43, 0x2e, 0x69, 0xa3, 0x62, 0x43, 0x36, 0x69, 0x63, 0x69, 0x43, 
+        0x69, 0x53, 0x69, 0x83, 0x52, 0x63, 0x11, 0x42, 0x63, 0x12, 0x02, 0x03, 0x2d, 0x42, 0x03, 0x2c, 
+        0x20, 0x00, 0x10, 0x00, 0x00, 0x74, 0x21, 0x05, 0xff, 0x80, 0x00, 0x11, 0x40, 0x00, 0x20, 0x42, 
+        0xa0, 0xfe, 0x20, 0x00, 0x10, 0x00, 0x20, 0x74, 0x00, 0x58, 0x41, 0x52, 0x43, 0x2d, 0x40, 0x22, 
+        0x10, 0x22, 0x43, 0x2c, 0x00, 0x09, 0x24, 0x26, 0x60, 0x04, 0x8c, 0x10, 0x05, 0xf0, 0xff, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x21, 0x84, 0xfe, 0x02, 0x61, 
+        0x01, 0x02, 0xa0, 0x00, 0x02, 0x42, 0x30, 0x21, 0x40, 0xff, 0x22, 0x61, 0x00, 0x01, 0x1a, 0xe6, 
+        0xc0, 0x00, 0x00, 0x31, 0x7e, 0xfe, 0x32, 0x03, 0x2d, 0x57, 0xe3, 0x11, 0xc5, 0xc7, 0x04, 0xcc, 
+        0xb2, 0x28, 0x01, 0x32, 0xa1, 0xf4, 0x0c, 0x04, 0x01, 0x16, 0xe6, 0xc0, 0x00, 0x00, 0x08, 0x11, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x21, 0x74, 0xfe, 0x09, 0x01, 
+        0x0c, 0x10, 0x02, 0x42, 0x30, 0x05, 0xcd, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0xa0, 0x8c, 0xfe, 0x3f, 0x09, 0x23, 0xff, 0x3f, 0x12, 0xc1, 0xf0, 0xd2, 0x61, 0x03, 0xc2, 0x61, 
+        0x02, 0x02, 0x61, 0x01, 0xcd, 0x02, 0xc5, 0xcd, 0x04, 0x29, 0x01, 0x16, 0x22, 0x09, 0x21, 0x26, 
+        0xff, 0xd1, 0x66, 0xfe, 0x2c, 0x03, 0x02, 0x0d, 0x2d, 0x42, 0xa0, 0xdf, 0x40, 0x00, 0x10, 0x30, 
+        0x00, 0x20, 0x02, 0x4d, 0x2d, 0x01, 0xfc, 0xe5, 0xc0, 0x00, 0x00, 0x21, 0xf1, 0xff, 0x32, 0x0d, 
+        0x2d, 0x42, 0x0d, 0x32, 0x30, 0x31, 0x24, 0x01, 0x22, 0xe2, 0xc0, 0x00, 0x00, 0x42, 0x0d, 0x2d, 
+        0x40, 0x01, 0x24, 0x56, 0x50, 0x06, 0x0c, 0xe6, 0x52, 0xa0, 0xf1, 0x50, 0x54, 0x10, 0x60, 0x55, 
+        0x20, 0x52, 0x4d, 0x2d, 0x22, 0xa0, 0x00, 0x0c, 0x03, 0x01, 0x16, 0xff, 0xc0, 0x00, 0x00, 0x38, 
+        0x01, 0x21, 0xe4, 0xff, 0x42, 0x13, 0x10, 0xc2, 0x4d, 0x38, 0x42, 0x5d, 0x20, 0x32, 0xc3, 0x1a, 
+        0x0c, 0x64, 0x01, 0x4e, 0xe5, 0xc0, 0x00, 0x00, 0x72, 0x0d, 0x2c, 0x82, 0xa0, 0xfe, 0x80, 0x77, 
+        0x10, 0x0c, 0x18, 0x80, 0x77, 0x20, 0x72, 0x4d, 0x2c, 0x61, 0x7b, 0xe4, 0xc0, 0x20, 0x00, 0x0c, 
+        0x05, 0x62, 0x26, 0x80, 0x69, 0x2d, 0x59, 0x3d, 0x85, 0xd6, 0x00, 0x05, 0xfd, 0x00, 0xc5, 0xfe, 
+        0x00, 0xc8, 0x21, 0xd8, 0x31, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x26, 0x60, 0xa4, 0x92, 
+        0x0d, 0x2c, 0x07, 0x69, 0x9e, 0x21, 0xae, 0xfe, 0x31, 0xaf, 0xfe, 0x42, 0xa2, 0x18, 0x01, 0x00, 
+        0xe2, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0xb8, 0x8c, 0xfe, 0x3f, 
+        0xb4, 0x8c, 0xfe, 0x3f, 0x12, 0xc1, 0xe0, 0xd9, 0x41, 0xf9, 0x61, 0xc9, 0x31, 0xe9, 0x51, 0x09, 
+        0x21, 0xed, 0x03, 0x30, 0x04, 0xc0, 0xa6, 0xa0, 0x3e, 0xcb, 0x0e, 0x32, 0x13, 0x04, 0xc1, 0x2f, 
+        0xfe, 0x60, 0x33, 0x11, 0x39, 0xac, 0x00, 0x34, 0xc0, 0xa6, 0x23, 0x3a, 0x0c, 0x0d, 0x52, 0x00, 
+        0x01, 0x72, 0x00, 0x00, 0x2b, 0x65, 0x67, 0x23, 0x1e, 0x66, 0x57, 0x01, 0xdd, 0x00, 0x0a, 0x05, 
+        0x2b, 0x00, 0x00, 0x34, 0xc0, 0xe6, 0x23, 0xe5, 0x86, 0x07, 0x00, 0x8c, 0x9e, 0x47, 0xe0, 0x04, 
+        0x22, 0x0c, 0x33, 0x8c, 0x12, 0x85, 0xd0, 0xff, 0xc8, 0x31, 0xd8, 0x41, 0xe8, 0x51, 0xf8, 0x61, 
+        0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0xd2, 0xa0, 0x00, 0x22, 0x61, 0x07, 0x16, 0x7d, 0xfe, 
+        0x20, 0xf2, 0x20, 0x21, 0xfd, 0xfe, 0x01, 0xb4, 0xe5, 0xc0, 0x00, 0x00, 0x48, 0xac, 0x38, 0x1e, 
+        0x28, 0x0e, 0x72, 0x1c, 0x63, 0x0c, 0x05, 0x1b, 0x77, 0x52, 0x5c, 0x62, 0x72, 0x5c, 0x63, 0xe2, 
+        0x0d, 0x03, 0x62, 0x0d, 0x02, 0x49, 0x01, 0x60, 0x6e, 0x83, 0x40, 0x66, 0x82, 0x69, 0x11, 0x45, 
+        0x9d, 0x07, 0x82, 0x0c, 0x2e, 0xa8, 0x7f, 0xb8, 0x01, 0xa8, 0x1a, 0x98, 0x11, 0x20, 0xaa, 0xc0, 
+        0xa9, 0x6c, 0xaa, 0x99, 0x99, 0x5c, 0xba, 0xaa, 0xa9, 0x4c, 0x9c, 0x68, 0xb2, 0x0c, 0x36, 0xe7, 
+        0x1b, 0x14, 0x21, 0x77, 0xfe, 0x31, 0x77, 0xfe, 0x42, 0xa2, 0x9d, 0x01, 0xc9, 0xe1, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0xe2, 0x4c, 0x36, 0x0c, 0x00, 0x0c, 0x1f, 0x92, 0xa0, 0xfe, 0x82, 0x1c, 
+        0x20, 0x0c, 0x1a, 0xa2, 0x4c, 0x2e, 0x80, 0x23, 0xa4, 0x32, 0x0d, 0x04, 0x42, 0x0d, 0x01, 0x90, 
+        0x93, 0x10, 0x9a, 0x44, 0x30, 0x30, 0x04, 0x32, 0x4c, 0x26, 0x42, 0xc4, 0xfc, 0x40, 0x40, 0x74, 
+        0x97, 0x32, 0x18, 0x27, 0x34, 0x15, 0x80, 0xe0, 0x24, 0x90, 0xbd, 0xc0, 0xba, 0xb2, 0xb2, 0x0b, 
+        0x05, 0x00, 0x0e, 0x40, 0xb0, 0xb0, 0xb1, 0x07, 0x6b, 0x01, 0x0d, 0x0a, 0x00, 0x20, 0x74, 0x22, 
+        0x4c, 0x27, 0xcc, 0x33, 0x0c, 0x0e, 0x20, 0xfe, 0x83, 0xf0, 0xe0, 0x74, 0x00, 0x30, 0x74, 0x8c, 
+        0x73, 0x21, 0xb2, 0xff, 0x01, 0xaf, 0xe1, 0xc0, 0x00, 0x00, 0xf0, 0x40, 0x74, 0x56, 0x04, 0x05, 
+        0x62, 0x0d, 0x03, 0x02, 0x0c, 0x37, 0x0c, 0x85, 0x60, 0x60, 0xc1, 0x67, 0xa5, 0x06, 0x0c, 0x1e, 
+        0x0c, 0x00, 0x02, 0x4c, 0x37, 0x52, 0xc0, 0x01, 0x02, 0x0c, 0x2d, 0x52, 0x4c, 0x37, 0x00, 0x31, 
+        0x24, 0x16, 0x03, 0x07, 0x72, 0xc3, 0xff, 0x16, 0x07, 0xee, 0x26, 0x23, 0x28, 0x26, 0x33, 0x64, 
+        0x26, 0x43, 0x3e, 0x26, 0x53, 0x43, 0x82, 0xc3, 0xfa, 0x16, 0xb8, 0xed, 0x92, 0xc3, 0xf9, 0x56, 
+        0x59, 0xed, 0x56, 0x2e, 0xed, 0x85, 0xc8, 0x00, 0x16, 0xc2, 0xec, 0x45, 0xe5, 0x00, 0x86, 0xb1, 
+        0xff, 0x0c, 0x05, 0x46, 0xf0, 0xff, 0x16, 0xee, 0xeb, 0x0c, 0x02, 0x0c, 0x03, 0x01, 0x91, 0xfe, 
+        0xc0, 0x00, 0x00, 0xa2, 0x0c, 0x2d, 0xa0, 0xa4, 0x04, 0x16, 0xba, 0xea, 0x05, 0xbb, 0xff, 0x46, 
+        0xa9, 0xff, 0xbc, 0xde, 0x85, 0xba, 0xff, 0x46, 0xa7, 0xff, 0x16, 0xae, 0x05, 0x21, 0xa7, 0xfe, 
+        0x01, 0x62, 0xe5, 0xc0, 0x00, 0x00, 0xb2, 0x0c, 0x2d, 0xb0, 0xb4, 0x04, 0x16, 0x8b, 0xe8, 0x05, 
+        0xb9, 0xff, 0x86, 0xa0, 0xff, 0x21, 0x8a, 0xff, 0x00, 0x45, 0x04, 0x01, 0x85, 0xe1, 0xc0, 0x00, 
+        0x00, 0x21, 0x2f, 0xfe, 0x31, 0x30, 0xfe, 0x42, 0xa2, 0xdb, 0x01, 0x81, 0xe1, 0xc0, 0x00, 0x00, 
+        0x06, 0xff, 0xff, 0x47, 0xe0, 0x1b, 0x0c, 0x12, 0x85, 0x92, 0x00, 0xd2, 0x0c, 0x2d, 0xe2, 0xa0, 
+        0xf1, 0xe0, 0xdd, 0x10, 0x0c, 0x2e, 0xe0, 0xdd, 0x20, 0xd2, 0x4c, 0x2d, 0x06, 0x92, 0xff, 0x00, 
+        0x00, 0x00, 0x45, 0xa1, 0xff, 0xc6, 0x8f, 0xff, 0xf2, 0x0c, 0x2f, 0xf2, 0xcf, 0xf8, 0x56, 0x6f, 
+        0xe3, 0x45, 0xa0, 0xff, 0x06, 0x8c, 0xff, 0x00, 0x41, 0xad, 0xfd, 0x78, 0x44, 0x68, 0x54, 0x38, 
+        0x34, 0x58, 0x64, 0x2a, 0x33, 0x20, 0x55, 0xc0, 0x20, 0x66, 0xc0, 0x20, 0x77, 0xc0, 0x79, 0x44, 
+        0x69, 0x54, 0x59, 0x64, 0x39, 0x34, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x09, 0x21, 0xc9, 0x31, 0xd9, 
+        0x41, 0xcd, 0x02, 0xd1, 0xa2, 0xfd, 0x26, 0x22, 0x13, 0x26, 0x42, 0x08, 0x66, 0x82, 0x02, 0x86, 
+        0x20, 0x00, 0x66, 0xb2, 0x3d, 0x02, 0x2d, 0x32, 0x1b, 0x00, 0x02, 0x6d, 0x32, 0x32, 0x2d, 0x33, 
+        0x22, 0x0d, 0x2d, 0x1b, 0x33, 0x32, 0x6d, 0x33, 0x57, 0x62, 0x27, 0x21, 0x78, 0xfe, 0x29, 0x11, 
+        0x01, 0x32, 0xe5, 0xc0, 0x00, 0x00, 0x28, 0x11, 0x52, 0xa0, 0xbf, 0x42, 0x0d, 0x2d, 0x0c, 0xa3, 
+        0x50, 0x44, 0x10, 0x4c, 0x05, 0x50, 0x44, 0x20, 0x42, 0x4d, 0x2d, 0x0c, 0x04, 0x01, 0x2c, 0xe5, 
+        0xc0, 0x00, 0x00, 0xc5, 0x6d, 0xff, 0x02, 0x0d, 0x2d, 0xc2, 0x4d, 0x2f, 0x00, 0x61, 0x24, 0x26, 
+        0x36, 0x11, 0x21, 0xfb, 0xfd, 0x31, 0xfb, 0xfd, 0x42, 0xa3, 0x14, 0x01, 0x4d, 0xe1, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0xc8, 0x31, 0x22, 0xa0, 0xf1, 0x20, 0x20, 0x10, 0x57, 0x60, 0x10, 0x0c, 
+        0xa0, 0x00, 0x02, 0x20, 0x02, 0x4d, 0x2d, 0xd8, 0x41, 0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 
+        0x0d, 0x02, 0x86, 0xfb, 0xff, 0x22, 0xcd, 0x4c, 0x22, 0x61, 0x00, 0x01, 0x17, 0xe5, 0xc0, 0x00, 
+        0x00, 0x32, 0xa3, 0xe8, 0x22, 0x2d, 0x12, 0x45, 0xca, 0x07, 0x20, 0x32, 0x20, 0x42, 0xa0, 0x00, 
+        0x28, 0x01, 0x01, 0x13, 0xe5, 0xc0, 0x00, 0x00, 0xc6, 0xe5, 0xff, 0x00, 0xb0, 0x8c, 0xfe, 0x3f, 
+        0x58, 0x23, 0xff, 0x3f, 0x40, 0x42, 0x0f, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x09, 0x11, 0x01, 
+        0x02, 0xe5, 0xc0, 0x00, 0x00, 0xc1, 0x6d, 0xfd, 0x02, 0x0c, 0x2d, 0x00, 0x31, 0x24, 0x66, 0x23, 
+        0x07, 0x47, 0x60, 0x04, 0x42, 0x0c, 0x32, 0x9c, 0x64, 0x57, 0x60, 0x14, 0x21, 0xf4, 0xff, 0x42, 
+        0x0c, 0x32, 0x00, 0x54, 0x04, 0x01, 0x2a, 0xe1, 0xc0, 0x00, 0x00, 0x02, 0x0c, 0x2d, 0x00, 0x31, 
+        0x24, 0x66, 0x23, 0x07, 0x47, 0x60, 0x04, 0x52, 0x0c, 0x32, 0x9c, 0x35, 0x57, 0x60, 0x11, 0x21, 
+        0xd0, 0xfd, 0x31, 0xd0, 0xfd, 0x42, 0xa3, 0x24, 0x01, 0x22, 0xe1, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x67, 0xe0, 0x59, 0x00, 0x67, 0x41, 0x56, 0x36, 0x05, 0xc5, 0x0a, 0xf9, 0x8c, 0x42, 0x72, 
+        0x0c, 0x2c, 0x57, 0x67, 0x48, 0x0c, 0x12, 0x45, 0x05, 0x01, 0x26, 0x12, 0x40, 0x01, 0xe5, 0xe4, 
+        0xc0, 0x00, 0x00, 0x22, 0xa1, 0xff, 0x01, 0x2f, 0xe1, 0xc0, 0x20, 0x00, 0x92, 0x20, 0x6a, 0xa2, 
+        0x0c, 0x2c, 0x27, 0x19, 0x54, 0x17, 0x6a, 0x4b, 0xc1, 0x2b, 0xe1, 0x45, 0x2a, 0xf9, 0xc0, 0x20, 
+        0x00, 0xb2, 0xa1, 0xff, 0xb2, 0x6c, 0x6a, 0x01, 0xdc, 0xe4, 0xc0, 0x00, 0x00, 0x46, 0x03, 0x00, 
+        0x00, 0x85, 0x8a, 0xff, 0x0c, 0x02, 0x0c, 0x03, 0x01, 0x07, 0xfe, 0xc0, 0x00, 0x00, 0x01, 0xd5, 
+        0xe4, 0xc0, 0x00, 0x00, 0xc1, 0xcf, 0xff, 0x2d, 0x0c, 0x01, 0xdb, 0xe4, 0xc0, 0x00, 0x00, 0x2d, 
+        0x0c, 0x0c, 0x03, 0x0c, 0x04, 0x01, 0xda, 0xe4, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0x08, 0x11, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x22, 0x60, 0x6a, 0x01, 0xcb, 0xe4, 0xc0, 0x00, 0x00, 
+        0x21, 0xc5, 0xff, 0x02, 0x0c, 0x2c, 0x0c, 0x03, 0x39, 0x01, 0x00, 0x40, 0x04, 0x40, 0x23, 0x93, 
+        0x07, 0x60, 0x05, 0x05, 0x5a, 0xff, 0x16, 0x72, 0xfa, 0x45, 0x69, 0xff, 0x8c, 0x42, 0xc5, 0x84, 
+        0xff, 0xc6, 0xe7, 0xff, 0x21, 0xdb, 0xe0, 0x42, 0x2c, 0x07, 0xc0, 0x20, 0x00, 0x22, 0x22, 0x47, 
+        0x32, 0x2c, 0x01, 0x40, 0x22, 0xc0, 0xc5, 0x13, 0xff, 0x31, 0x5b, 0xe3, 0xc0, 0x20, 0x00, 0x42, 
+        0x2c, 0x08, 0x32, 0x23, 0x80, 0x4a, 0x22, 0x30, 0x22, 0xc0, 0xc5, 0xdd, 0xff, 0xc0, 0x20, 0x00, 
+        0x01, 0xd0, 0xe0, 0x22, 0x20, 0x4a, 0x20, 0x40, 0x14, 0xdc, 0x04, 0x21, 0x91, 0xfd, 0x31, 0x91, 
+        0xfd, 0x42, 0xa3, 0x56, 0x01, 0xe3, 0xe0, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x07, 0x62, 0x0b, 
+        0xc0, 0x20, 0x00, 0x22, 0x20, 0x46, 0x20, 0x28, 0x54, 0x46, 0x02, 0x00, 0x20, 0x41, 0x04, 0x28, 
+        0x01, 0x0c, 0x23, 0x40, 0x23, 0x93, 0x1c, 0x05, 0x20, 0x82, 0x04, 0x0c, 0x47, 0x80, 0x27, 0x93, 
+        0x0b, 0x62, 0x60, 0x62, 0x10, 0x60, 0x25, 0x93, 0xc5, 0xda, 0xff, 0x46, 0xc9, 0xff, 0x00, 0x00, 
+        0xbc, 0x8c, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x41, 0x0d, 0xfd, 0x09, 0x01, 0x02, 0x04, 0x2d, 0x00, 
+        0x31, 0x24, 0x66, 0x63, 0x19, 0x57, 0x60, 0x26, 0x0c, 0xe2, 0x32, 0xa0, 0xf1, 0x30, 0x00, 0x10, 
+        0x20, 0x00, 0x20, 0x02, 0x44, 0x2d, 0xc5, 0xe6, 0x00, 0xc6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x21, 
+        0xf4, 0xff, 0x01, 0xc7, 0xe0, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x85, 
+        0x8a, 0xff, 0x86, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xc4, 0x8c, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xfa, 0xfc, 0x02, 0x00, 0x2d, 0x00, 0x31, 0x24, 0x66, 0x13, 0x14, 0x57, 0xe0, 0x2c, 
+        0x21, 0x68, 0xfd, 0x31, 0x68, 0xfd, 0x42, 0xa3, 0x9c, 0x01, 0xb9, 0xe0, 0xc0, 0x00, 0x00, 0x06, 
+        0xff, 0xff, 0x21, 0xf5, 0xff, 0x01, 0xb6, 0xe0, 0xc0, 0x00, 0x00, 0x21, 0x61, 0xfd, 0x31, 0x61, 
+        0xfd, 0x42, 0xa3, 0xa5, 0x01, 0xb3, 0xe0, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x45, 0x48, 0xff, 
+        0x8c, 0x42, 0x45, 0x6f, 0xff, 0x06, 0x03, 0x00, 0x0c, 0x02, 0x0c, 0x03, 0x01, 0xaa, 0xfd, 0xc0, 
+        0x00, 0x00, 0x85, 0x72, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x44, 0x23, 0xff, 0x3f, 
+        0xd4, 0x23, 0xff, 0x3f, 0x40, 0x89, 0xfe, 0x3f, 0xaf, 0x36, 0x00, 0x00, 0xcc, 0x8c, 0xfe, 0x3f, 
+        0x20, 0x42, 0x20, 0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x03, 0xd2, 0x61, 0x04, 0x21, 0xf8, 0xff, 0x09, 
+        0x21, 0x49, 0x11, 0x01, 0x75, 0xe4, 0xc0, 0x00, 0x00, 0xd1, 0xd8, 0xfc, 0x38, 0x11, 0x42, 0x0d, 
+        0x2d, 0x0c, 0x0c, 0x40, 0x01, 0x24, 0xbc, 0xa0, 0xc2, 0x4d, 0x33, 0xc2, 0x4d, 0x32, 0x38, 0x73, 
+        0x01, 0xf0, 0xff, 0x32, 0x03, 0x0f, 0x62, 0x0d, 0x35, 0x26, 0x13, 0x32, 0x45, 0x8b, 0x06, 0x42, 
+        0x0d, 0x35, 0x0d, 0x02, 0x66, 0x24, 0x08, 0xc2, 0x4d, 0x35, 0x45, 0x7b, 0xff, 0xc6, 0x04, 0x00, 
+        0x42, 0x0d, 0x2d, 0x0c, 0x12, 0x57, 0x64, 0x08, 0x09, 0x01, 0x40, 0x57, 0x41, 0xbc, 0xd5, 0xcd, 
+        0x02, 0xc2, 0x4d, 0x35, 0xc8, 0x31, 0xd8, 0x41, 0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0xc2, 
+        0x40, 0x00, 0x1c, 0x08, 0x72, 0xa0, 0xef, 0x70, 0x74, 0x10, 0x80, 0x77, 0x20, 0x72, 0x4d, 0x2d, 
+        0x66, 0x26, 0x08, 0xc2, 0x4d, 0x35, 0x85, 0x77, 0xff, 0xc6, 0xf5, 0xff, 0x21, 0xda, 0xff, 0x01, 
+        0x80, 0xe0, 0xc0, 0x00, 0x00, 0xc2, 0x4d, 0x35, 0x05, 0xef, 0xff, 0x46, 0xf1, 0xff, 0x45, 0x3b, 
+        0xff, 0x81, 0xd5, 0xff, 0x27, 0x38, 0x08, 0xc2, 0x4d, 0x35, 0x05, 0x66, 0xff, 0xc6, 0xec, 0xff, 
+        0x21, 0xd3, 0xff, 0x51, 0xe5, 0xe2, 0xc1, 0xce, 0xff, 0x31, 0x38, 0xe1, 0x48, 0x01, 0x32, 0x23, 
+        0x37, 0x42, 0x04, 0x06, 0x32, 0x03, 0x06, 0xc0, 0x20, 0x00, 0x52, 0x25, 0xa1, 0x01, 0x70, 0xe0, 
+        0xc0, 0x00, 0x00, 0x42, 0x0c, 0x00, 0x0c, 0xe2, 0x1b, 0x04, 0x47, 0x32, 0x0a, 0x0c, 0x12, 0x02, 
+        0x4c, 0x00, 0x05, 0x4e, 0x00, 0xc6, 0xde, 0xff, 0x22, 0x4c, 0x00, 0x0c, 0x12, 0x45, 0x4d, 0x00, 
+        0x06, 0xdc, 0xff, 0x00, 0xd5, 0x23, 0xff, 0x3f, 0x14, 0x8d, 0xfe, 0x3f, 0xf0, 0x8c, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0xd2, 0x61, 0x02, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 0xcd, 0x02, 0x21, 0xb7, 
+        0xff, 0x01, 0x35, 0xe4, 0xc0, 0x00, 0x00, 0xd1, 0x99, 0xfc, 0x22, 0x0d, 0x2d, 0x20, 0x01, 0x24, 
+        0x16, 0x50, 0x04, 0x0c, 0x00, 0x02, 0x4d, 0x32, 0x02, 0x4d, 0x34, 0x38, 0x7c, 0x82, 0x0d, 0x35, 
+        0x32, 0x03, 0x0f, 0xc1, 0xf0, 0xff, 0x26, 0x13, 0x3a, 0x85, 0x7b, 0x06, 0x42, 0x0d, 0x35, 0x0d, 
+        0x02, 0x66, 0x14, 0x16, 0x21, 0xff, 0xfc, 0x31, 0xff, 0xfc, 0x42, 0xa3, 0xf9, 0x0c, 0x05, 0x52, 
+        0x4d, 0x35, 0x01, 0x4f, 0xe0, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x62, 0x0d, 0x2d, 0x0c, 0x27, 
+        0x60, 0x67, 0x41, 0x16, 0x86, 0x04, 0x72, 0x4d, 0x35, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x02, 0x4c, 0x00, 0x92, 0xa0, 0xef, 0x90, 0x22, 0x10, 0x22, 0x4d, 0x2d, 
+        0x66, 0x18, 0x17, 0x57, 0x62, 0x14, 0x21, 0xee, 0xfc, 0x31, 0xee, 0xfc, 0x42, 0xa4, 0x20, 0x02, 
+        0x4d, 0x35, 0x01, 0x3f, 0xe0, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xd7, 0xff, 0x01, 0x3c, 
+        0xe0, 0xc0, 0x00, 0x00, 0x0c, 0x0a, 0xa2, 0x4d, 0x35, 0x85, 0xd9, 0xff, 0x46, 0xee, 0xff, 0x51, 
+        0xa6, 0xe2, 0x31, 0xfa, 0xe0, 0x21, 0xd1, 0xff, 0x32, 0x23, 0x37, 0x42, 0x00, 0x06, 0x32, 0x03, 
+        0x06, 0xc0, 0x20, 0x00, 0x52, 0x25, 0xa1, 0x01, 0x32, 0xe0, 0xc0, 0x00, 0x00, 0x22, 0x0d, 0x38, 
+        0xc5, 0xaa, 0x05, 0x16, 0xb2, 0x01, 0x42, 0x0d, 0x30, 0x56, 0x54, 0x01, 0x22, 0x0d, 0x38, 0x31, 
+        0xf9, 0xfd, 0x05, 0x51, 0x04, 0xcc, 0xf2, 0x0c, 0x05, 0x52, 0x4d, 0x35, 0x45, 0xd5, 0xff, 0x86, 
+        0xdd, 0xff, 0x45, 0x49, 0xff, 0x06, 0xdc, 0xff, 0x62, 0x0c, 0x00, 0x22, 0xa0, 0x0e, 0x02, 0xc6, 
+        0x01, 0x67, 0x32, 0x0b, 0x22, 0xa0, 0x00, 0x02, 0x4c, 0x00, 0x85, 0x3b, 0x00, 0x06, 0xd6, 0xff, 
+        0x22, 0x4c, 0x00, 0x0c, 0x02, 0xc5, 0x3a, 0x00, 0x46, 0xd3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x31, 0x57, 0xfc, 0x21, 0x89, 0xe2, 0xc0, 0x20, 0x00, 0x22, 0x22, 0x80, 0x22, 0x63, 0x34, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x3c, 0x0f, 0x00, 0x00, 0xb4, 0x2d, 0x00, 0x00, 0x1b, 0x0c, 0x00, 0x00, 
+        0xcb, 0x10, 0x00, 0x00, 0x20, 0x32, 0x20, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0xd2, 0x61, 0x02, 
+        0xc1, 0x4b, 0xfc, 0x09, 0x01, 0xd2, 0x1c, 0x62, 0x29, 0x31, 0x1b, 0xdd, 0xd0, 0xd0, 0xf4, 0xd2, 
+        0x5c, 0x62, 0x16, 0x6d, 0x05, 0x22, 0x1c, 0x63, 0x3d, 0x0d, 0x05, 0x7d, 0x07, 0x38, 0x31, 0x20, 
+        0x20, 0xf4, 0x0c, 0xa0, 0x27, 0x30, 0x1f, 0x02, 0x2c, 0x11, 0x41, 0xee, 0xff, 0x61, 0xee, 0xff, 
+        0x07, 0x34, 0x05, 0x52, 0xc0, 0x64, 0x52, 0x6c, 0x11, 0x02, 0x2c, 0x12, 0x72, 0xa1, 0x2c, 0x07, 
+        0x36, 0x04, 0x7a, 0x70, 0x72, 0x6c, 0x12, 0x1c, 0x38, 0x27, 0xb8, 0x1f, 0x02, 0x2c, 0x11, 0x91, 
+        0xe7, 0xff, 0xb1, 0xe7, 0xff, 0x07, 0xb9, 0x05, 0xa2, 0xc0, 0x9c, 0xa2, 0x6c, 0x11, 0x02, 0x2c, 
+        0x12, 0x22, 0xae, 0xd4, 0x07, 0xbb, 0x04, 0x2a, 0x20, 0x22, 0x6c, 0x12, 0x0c, 0x04, 0x42, 0x5c, 
+        0x63, 0xb6, 0x2d, 0x07, 0x8c, 0x73, 0x85, 0x59, 0xff, 0x86, 0x00, 0x00, 0xc5, 0x43, 0xff, 0xc8, 
+        0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x21, 0x59, 0xe2, 0x31, 0x26, 0xfc, 0xc0, 0x20, 0x00, 0x02, 0x03, 0x2d, 0x22, 0x22, 0x80, 
+        0x00, 0x01, 0x24, 0x66, 0x50, 0x05, 0x42, 0x03, 0x2f, 0x26, 0x84, 0x14, 0x26, 0x40, 0x11, 0x21, 
+        0x90, 0xfc, 0x31, 0x90, 0xfc, 0x42, 0xa4, 0x54, 0x01, 0xe2, 0xdf, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x0c, 0x12, 0x05, 0xf3, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x21, 0x16, 0xfc, 0x09, 0x01, 0x02, 0x02, 0x2d, 0x32, 0xa0, 0xbf, 0x30, 0x00, 
+        0x10, 0x02, 0x42, 0x2d, 0x00, 0x31, 0x24, 0x26, 0x53, 0x11, 0x21, 0x81, 0xfc, 0x31, 0x81, 0xfc, 
+        0x42, 0xa4, 0x81, 0x01, 0xd3, 0xdf, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x47, 0x60, 0x2e, 0x42, 
+        0x02, 0x32, 0xcc, 0x94, 0xc5, 0x0f, 0xff, 0x9c, 0x62, 0xc5, 0x36, 0xff, 0x86, 0x07, 0x00, 0x21, 
+        0x78, 0xfc, 0x31, 0x78, 0xfc, 0x42, 0xa4, 0x95, 0x01, 0xca, 0xdf, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x0c, 0x02, 0x0c, 0x03, 0x01, 0xc3, 0xfc, 0xc0, 0x00, 0x00, 0x05, 0x39, 0xff, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x18, 0x8d, 0xfe, 0x3f, 0x00, 0x0e, 0xf2, 0x3f, 
+        0x3c, 0x8d, 0xfe, 0x3f, 0x00, 0x8a, 0xfe, 0x3f, 0x12, 0xc1, 0xe0, 0xc2, 0x61, 0x01, 0xd2, 0x61, 
+        0x02, 0xe2, 0x61, 0x03, 0xf9, 0x41, 0x09, 0x01, 0x85, 0x54, 0x06, 0xfd, 0x02, 0xc1, 0x26, 0xe2, 
+        0xc0, 0x20, 0x00, 0x02, 0x2c, 0xb1, 0x0c, 0x0d, 0x9c, 0xc0, 0xe2, 0xa0, 0x63, 0xc0, 0x20, 0x00, 
+        0x22, 0x2c, 0xb1, 0x16, 0x12, 0x09, 0x0c, 0xa2, 0x01, 0xc6, 0xe1, 0xc0, 0x00, 0x00, 0x3d, 0x0d, 
+        0x1b, 0xdd, 0xd0, 0xd0, 0x74, 0x37, 0xbe, 0xe4, 0x31, 0x71, 0xe0, 0x21, 0xeb, 0xff, 0x32, 0x23, 
+        0x37, 0x42, 0x0f, 0x06, 0x32, 0x03, 0x06, 0xc0, 0x20, 0x00, 0x52, 0x2c, 0xa1, 0x01, 0xa8, 0xdf, 
+        0xc0, 0x00, 0x00, 0xf1, 0x0a, 0xfc, 0xe1, 0x25, 0xfc, 0xd1, 0xe4, 0xff, 0x21, 0xe5, 0xff, 0xc0, 
+        0x20, 0x00, 0x38, 0xed, 0x01, 0xa3, 0xdf, 0xc0, 0x00, 0x00, 0x21, 0xe1, 0xff, 0xc0, 0x20, 0x00, 
+        0x32, 0x2f, 0xf4, 0x01, 0x9f, 0xdf, 0xc0, 0x00, 0x00, 0x21, 0xdd, 0xff, 0xc0, 0x20, 0x00, 0x32, 
+        0x2e, 0x84, 0x01, 0x9b, 0xdf, 0xc0, 0x00, 0x00, 0x21, 0xda, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x2c, 
+        0xb1, 0x01, 0x97, 0xdf, 0xc0, 0x00, 0x00, 0x21, 0xd6, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x2c, 0x9f, 
+        0x01, 0x94, 0xdf, 0xc0, 0x00, 0x00, 0x21, 0xd3, 0xff, 0x01, 0x91, 0xdf, 0xc0, 0x00, 0x00, 0xc0, 
+        0x20, 0x00, 0x42, 0x2c, 0xb1, 0x56, 0x34, 0xfa, 0xc8, 0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 
+        0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x31, 0xc5, 0xfb, 0x22, 0x03, 0x2c, 0x42, 0xa0, 
+        0xdf, 0x40, 0x22, 0x10, 0x2c, 0x04, 0x40, 0x22, 0x20, 0x22, 0x43, 0x2c, 0x0d, 0xf0, 0x00, 0x00, 
+        0xc4, 0x09, 0x00, 0x00, 0xe0, 0x7d, 0x10, 0x40, 0xe0, 0x7e, 0x10, 0x40, 0xbc, 0x80, 0x10, 0x40, 
+        0x00, 0x81, 0x10, 0x40, 0x78, 0x81, 0x10, 0x40, 0x00, 0x80, 0x10, 0x40, 0x88, 0x77, 0x10, 0x40, 
+        0x80, 0x23, 0xff, 0x3f, 0xfc, 0x85, 0x10, 0x40, 0x44, 0x87, 0x10, 0x40, 0xb0, 0x23, 0xff, 0x3f, 
+        0xd0, 0x0d, 0x00, 0x40, 0x32, 0xa0, 0x04, 0x92, 0xa0, 0xdf, 0xb2, 0xa0, 0xfb, 0x21, 0xaf, 0xfb, 
+        0x82, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x82, 0x42, 0x2e, 0xa2, 0x02, 0x2c, 0x02, 0x02, 
+        0x2d, 0xb0, 0xaa, 0x10, 0x90, 0x00, 0x10, 0x02, 0x42, 0x2d, 0x30, 0xaa, 0x20, 0xb2, 0xa0, 0xfe, 
+        0xa2, 0x42, 0x2c, 0xb0, 0xaa, 0x10, 0xa2, 0x42, 0x2c, 0xb2, 0xa0, 0xfd, 0xb0, 0xaa, 0x10, 0x0c, 
+        0x2b, 0xb0, 0xaa, 0x20, 0xa2, 0x42, 0x2c, 0xb2, 0xa0, 0xf7, 0xb0, 0xaa, 0x10, 0x0c, 0x8b, 0xb0, 
+        0xaa, 0x20, 0xa2, 0x42, 0x2c, 0xb2, 0xa0, 0xef, 0xb0, 0xaa, 0x10, 0x1c, 0x0b, 0xb0, 0xaa, 0x20, 
+        0xa2, 0x42, 0x2c, 0x90, 0x9a, 0x10, 0x92, 0x42, 0x2c, 0x61, 0xd2, 0xe0, 0x71, 0x76, 0xdf, 0xc0, 
+        0x20, 0x00, 0x01, 0xed, 0xfc, 0x41, 0xeb, 0xfc, 0x62, 0x67, 0x6a, 0x51, 0xd5, 0xff, 0x52, 0x52, 
+        0x12, 0x42, 0x62, 0x11, 0x02, 0x62, 0x12, 0x21, 0xd3, 0xff, 0x85, 0x8a, 0x00, 0x21, 0xd2, 0xff, 
+        0x0c, 0x53, 0x05, 0x8a, 0x00, 0x21, 0x70, 0xfc, 0x31, 0xd1, 0xff, 0x0c, 0x04, 0x01, 0x27, 0xe3, 
+        0xc0, 0x00, 0x00, 0x21, 0x6a, 0xfc, 0x31, 0xce, 0xff, 0x0c, 0x04, 0x01, 0x24, 0xe3, 0xc0, 0x00, 
+        0x00, 0x21, 0xa2, 0xfe, 0x31, 0xcc, 0xff, 0x0c, 0x04, 0x01, 0x20, 0xe3, 0xc0, 0x00, 0x00, 0x21, 
+        0x10, 0xfe, 0x31, 0xc9, 0xff, 0x0c, 0x04, 0x01, 0x1d, 0xe3, 0xc0, 0x00, 0x00, 0x21, 0x3e, 0xfc, 
+        0x31, 0xc7, 0xff, 0x0c, 0x04, 0x01, 0x19, 0xe3, 0xc0, 0x00, 0x00, 0x21, 0xc5, 0xff, 0x31, 0xc5, 
+        0xff, 0x0c, 0x04, 0x01, 0x16, 0xe3, 0xc0, 0x00, 0x00, 0x21, 0xc3, 0xff, 0x1c, 0x43, 0x41, 0xc3, 
+        0xff, 0x0c, 0x35, 0x01, 0xc3, 0xff, 0xc0, 0x00, 0x00, 0x31, 0x74, 0xfb, 0x0c, 0x12, 0x22, 0x43, 
+        0x31, 0x45, 0x3b, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x80, 0x01, 0x00, 
+        0xf7, 0xff, 0xff, 0x03, 0x0c, 0x25, 0x12, 0xc1, 0xd0, 0x31, 0x6c, 0xfb, 0x09, 0xa1, 0x0c, 0x00, 
+        0x42, 0x03, 0x33, 0x09, 0x41, 0xdc, 0x74, 0x62, 0x03, 0x34, 0x8c, 0x56, 0x5d, 0x02, 0x0c, 0x10, 
+        0x06, 0x03, 0x00, 0x72, 0x03, 0x2d, 0x0c, 0x16, 0x70, 0x77, 0x41, 0x16, 0x67, 0x15, 0x0d, 0x06, 
+        0x20, 0x50, 0x93, 0x52, 0x43, 0x35, 0x06, 0x51, 0x00, 0x22, 0x21, 0x08, 0x22, 0x22, 0x00, 0x1c, 
+        0x83, 0x28, 0x12, 0x29, 0x51, 0x01, 0xfd, 0xe1, 0xc0, 0x00, 0x00, 0x38, 0x81, 0x1c, 0x87, 0x72, 
+        0x53, 0x08, 0xa8, 0x03, 0x72, 0xa0, 0x80, 0xc0, 0x20, 0x00, 0x62, 0x0a, 0x03, 0x60, 0x60, 0x64, 
+        0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x4a, 0x03, 0x4c, 0x04, 0x52, 0xa0, 0xbf, 0xc0, 0x20, 
+        0x00, 0x22, 0x0a, 0x03, 0x50, 0x22, 0x10, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x4a, 0x03, 
+        0x02, 0xa0, 0xdf, 0xc0, 0x20, 0x00, 0xb2, 0x0a, 0x03, 0x00, 0xbb, 0x10, 0x08, 0x71, 0x00, 0xbb, 
+        0x20, 0xc0, 0x20, 0x00, 0xb2, 0x4a, 0x03, 0x01, 0x7b, 0xe1, 0xb1, 0xd8, 0xff, 0xc0, 0x20, 0x00, 
+        0x92, 0x1a, 0x01, 0x00, 0x99, 0x11, 0xc0, 0x20, 0x00, 0x22, 0x1a, 0x00, 0x20, 0x99, 0x20, 0x00, 
+        0x99, 0x10, 0xb0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x5a, 0x00, 0x90, 0x90, 0xf5, 0xc0, 0x20, 
+        0x00, 0x0c, 0x02, 0x4c, 0x84, 0x92, 0x5a, 0x01, 0x0c, 0x05, 0x91, 0xce, 0xfc, 0x61, 0xc3, 0xdf, 
+        0x7d, 0x09, 0x82, 0xc9, 0xc7, 0x82, 0x08, 0x38, 0x99, 0x01, 0xc0, 0x88, 0x11, 0x8a, 0x66, 0x9b, 
+        0x66, 0x05, 0x74, 0x05, 0xa8, 0x81, 0xb1, 0x68, 0xe1, 0x08, 0x7a, 0xc0, 0x20, 0x00, 0x0c, 0x68, 
+        0x92, 0xa0, 0xf0, 0x32, 0xa0, 0x8f, 0x22, 0x00, 0x06, 0xb2, 0x2b, 0x80, 0x30, 0x22, 0x10, 0x32, 
+        0xa0, 0xfd, 0x22, 0x40, 0x06, 0x78, 0x7a, 0xb9, 0x40, 0x62, 0x07, 0x04, 0x21, 0x2c, 0xfb, 0x90, 
+        0x66, 0x10, 0x98, 0x71, 0x80, 0x66, 0x20, 0x62, 0x47, 0x04, 0x08, 0x7a, 0x88, 0x91, 0x58, 0x00, 
+        0x61, 0xb8, 0xff, 0x50, 0x40, 0x54, 0x50, 0x56, 0x41, 0x60, 0x55, 0x10, 0xa0, 0x55, 0x11, 0x50, 
+        0x44, 0x20, 0x49, 0x00, 0xb2, 0x00, 0x00, 0x22, 0x02, 0x38, 0x30, 0xbb, 0x10, 0x20, 0x20, 0x04, 
+        0xf0, 0x22, 0x11, 0x20, 0xbb, 0x20, 0xb2, 0x40, 0x00, 0x99, 0x5a, 0x16, 0xc8, 0x06, 0x38, 0x51, 
+        0x22, 0x03, 0x01, 0x1c, 0x00, 0x00, 0x22, 0x20, 0x22, 0x43, 0x01, 0x38, 0x81, 0x21, 0x33, 0xfe, 
+        0x38, 0x73, 0x29, 0x61, 0x02, 0x43, 0x0e, 0x01, 0xb0, 0xe2, 0xc0, 0x00, 0x00, 0x28, 0x61, 0x3c, 
+        0x73, 0x0c, 0x04, 0x01, 0xaf, 0xe2, 0xc0, 0x00, 0x00, 0x28, 0x81, 0x45, 0x58, 0x00, 0x08, 0xa1, 
+        0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x29, 0x91, 0x62, 0x43, 0x32, 0x09, 0x71, 0xcc, 0x42, 0x62, 0x43, 
+        0x34, 0x86, 0x00, 0x00, 0x62, 0x43, 0x33, 0x22, 0xc1, 0x10, 0x32, 0xa0, 0x18, 0x42, 0xa0, 0x00, 
+        0x85, 0x63, 0x05, 0x22, 0x61, 0x08, 0x56, 0xf2, 0xe8, 0x21, 0x75, 0xfb, 0x31, 0x76, 0xfb, 0x42, 
+        0xa5, 0x02, 0x01, 0xc7, 0xde, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x2c, 0x00, 0x86, 0xe6, 0xff, 
+        0x41, 0xff, 0xfa, 0x42, 0x04, 0x2d, 0x0c, 0x02, 0x40, 0x31, 0x24, 0x66, 0x73, 0x04, 0x57, 0x64, 
+        0x01, 0x0c, 0x12, 0x20, 0x20, 0x74, 0x0d, 0xf0, 0x48, 0x8d, 0xfe, 0x3f, 0x21, 0xff, 0xff, 0x12, 
+        0xc1, 0xf0, 0x02, 0x61, 0x00, 0x01, 0xba, 0xde, 0xc0, 0x00, 0x00, 0x21, 0xf4, 0xfa, 0x02, 0x02, 
+        0x2d, 0x32, 0xa0, 0x80, 0x00, 0x00, 0x64, 0x30, 0x00, 0x20, 0x02, 0x42, 0x2d, 0xc5, 0x27, 0x00, 
+        0x21, 0x38, 0xff, 0x01, 0x89, 0xe2, 0xc0, 0x00, 0x00, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x80, 
+        0x00, 0x00, 0x00, 0x00, 0x21, 0x33, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x29, 0x01, 0x01, 0x82, 
+        0xe2, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x32, 0xa0, 0x69, 0x0c, 0x04, 0x01, 0x81, 0xe2, 0xc0, 0x00, 
+        0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x21, 0x2a, 0xff, 0x12, 0xc1, 0xf0, 0x02, 0x61, 
+        0x00, 0x01, 0x79, 0xe2, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x00, 0x05, 0x01, 0x00, 0x02, 0x21, 0x00, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x21, 
+        0xfe, 0xff, 0xc9, 0x11, 0xc1, 0xd6, 0xfa, 0x09, 0x01, 0x32, 0x0c, 0x2d, 0x42, 0x0c, 0x35, 0x30, 
+        0x31, 0x24, 0x01, 0x97, 0xde, 0xc0, 0x00, 0x00, 0x02, 0x0c, 0x2d, 0x42, 0x0c, 0x32, 0x00, 0x50, 
+        0x64, 0x52, 0x4c, 0x2d, 0xfc, 0x24, 0x42, 0x0c, 0x35, 0x0c, 0x02, 0x66, 0x14, 0x34, 0x22, 0x4c, 
+        0x35, 0x00, 0x61, 0x24, 0x26, 0x16, 0x4f, 0x21, 0x3a, 0xfb, 0x31, 0x3a, 0xfb, 0x42, 0xa5, 0x4d, 
+        0x01, 0x8c, 0xde, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x45, 0xf1, 0xff, 0x8c, 0xa2, 0x10, 0x11, 
+        0x20, 0x85, 0x1c, 0x00, 0x10, 0x11, 0x20, 0x45, 0x1e, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x66, 0x24, 0xe2, 0x22, 0x4c, 0x35, 0x00, 0x71, 0x24, 0x26, 0x67, 0x11, 0x21, 
+        0x2c, 0xfb, 0x31, 0x2c, 0xfb, 0x42, 0xa5, 0x52, 0x01, 0x7e, 0xde, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x05, 0xd2, 0xff, 0x86, 0xf4, 0xff, 0x0c, 0x12, 0x85, 0xd1, 0xff, 0x86, 0xf2, 0xff, 0x00, 
+        0x41, 0xb3, 0xfa, 0x0c, 0x13, 0x42, 0x04, 0x2d, 0x0c, 0x02, 0x40, 0x47, 0x41, 0x40, 0x23, 0x83, 
+        0x0d, 0xf0, 0x00, 0x00, 0x61, 0xae, 0xfa, 0x42, 0x06, 0x2d, 0x0c, 0x15, 0x40, 0x41, 0x24, 0x26, 
+        0x74, 0x09, 0x8c, 0x64, 0x72, 0x06, 0x38, 0x27, 0x97, 0x01, 0x0c, 0x05, 0x50, 0x20, 0x74, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0xd4, 0x18, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xa3, 0xfa, 
+        0x32, 0x00, 0x2d, 0x57, 0x63, 0x11, 0x0c, 0x64, 0x32, 0xc0, 0x39, 0x01, 0xfa, 0xff, 0xc0, 0x00, 
+        0x00, 0xcc, 0x32, 0x0c, 0x10, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x20, 0x74, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xd0, 0x23, 0xff, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0x97, 0xfa, 
+        0xc9, 0x11, 0x02, 0x00, 0x31, 0xcd, 0x02, 0xbc, 0x00, 0x01, 0x26, 0xe2, 0xc0, 0x00, 0x00, 0x21, 
+        0xf9, 0xff, 0x2a, 0x2c, 0x02, 0x02, 0x00, 0x8c, 0x90, 0x01, 0x23, 0xe2, 0xc0, 0x00, 0x00, 0x0c, 
+        0x02, 0x86, 0x05, 0x00, 0x1b, 0x30, 0x32, 0x42, 0x00, 0x01, 0x1f, 0xe2, 0xc0, 0x00, 0x00, 0x3d, 
+        0x0c, 0x1c, 0x42, 0x0c, 0x04, 0x01, 0xd0, 0xf5, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x41, 0xec, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x08, 0x02, 0x52, 0xd4, 
+        0xff, 0xac, 0x90, 0x26, 0x10, 0x60, 0x29, 0x01, 0x66, 0x20, 0x54, 0x01, 0x12, 0xe2, 0xc0, 0x00, 
+        0x00, 0x28, 0x01, 0x31, 0xe4, 0xff, 0x28, 0x02, 0x3a, 0x22, 0x02, 0x02, 0x00, 0x0b, 0x00, 0x02, 
+        0x42, 0x00, 0x01, 0x0d, 0xe2, 0xc0, 0x00, 0x00, 0xc5, 0xfc, 0xfe, 0x46, 0x0c, 0x00, 0x40, 0x40, 
+        0x80, 0x32, 0x04, 0x00, 0x22, 0xa0, 0x01, 0x32, 0xc3, 0xff, 0x32, 0x44, 0x00, 0xc5, 0x4c, 0x00, 
+        0xdc, 0xc2, 0xc5, 0xdc, 0xff, 0x9c, 0x72, 0x0c, 0x12, 0x85, 0xc0, 0xff, 0x71, 0x70, 0xfa, 0x62, 
+        0x07, 0x2d, 0x82, 0xa0, 0xf1, 0x80, 0x66, 0x10, 0x0c, 0x28, 0x80, 0x66, 0x20, 0x62, 0x47, 0x2d, 
+        0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x4a, 0xa0, 0x92, 0x0a, 0x00, 0x02, 0x05, 0x2d, 0x0b, 
+        0x99, 0x92, 0x4a, 0x00, 0x57, 0x60, 0xe8, 0x00, 0x01, 0x24, 0x26, 0x70, 0xe2, 0x26, 0x60, 0xdf, 
+        0xc5, 0xe6, 0xfe, 0x46, 0xf6, 0xff, 0x00, 0x00, 0x22, 0xa0, 0x01, 0x32, 0xa0, 0x01, 0x12, 0xc1, 
+        0xf0, 0x02, 0x61, 0x00, 0x85, 0xde, 0xf9, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0xe0, 0x23, 0xff, 0x3f, 0x21, 0xff, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xf3, 0xe1, 0xc0, 
+        0x00, 0x00, 0x45, 0xfd, 0xff, 0x21, 0xfa, 0xff, 0x32, 0xa0, 0x64, 0x0c, 0x14, 0x01, 0xf0, 0xe1, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x21, 0xf5, 0xff, 0x0c, 
+        0x03, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x32, 0x42, 0x14, 0x22, 0xc2, 0x18, 0x01, 0xe7, 0xe1, 0xc0, 
+        0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x04, 0x21, 0xec, 
+        0xff, 0x0c, 0x13, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x32, 0x42, 0x14, 0x22, 0xc2, 0x18, 0x32, 0xa0, 
+        0xc8, 0x01, 0xdf, 0xe1, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xe2, 0xff, 0x22, 0x00, 0x14, 0xdc, 0x12, 0x0c, 0x04, 0x0c, 
+        0x13, 0x22, 0xc0, 0x18, 0x32, 0x40, 0x14, 0x32, 0xa0, 0xc8, 0x01, 0xd5, 0xe1, 0xc0, 0x00, 0x00, 
+        0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x80, 0x26, 0xff, 0x3f, 0x64, 0x89, 0xfe, 0x3f, 
+        0x58, 0x8d, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0x08, 0x02, 0x21, 
+        0xfa, 0xff, 0xf6, 0x40, 0x1a, 0x3d, 0x02, 0x3a, 0x30, 0x42, 0x03, 0x00, 0x00, 0x20, 0x74, 0x0b, 
+        0x04, 0x02, 0x43, 0x00, 0x45, 0x5f, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x26, 0x40, 0x5b, 0x26, 0x50, 0x7e, 0x26, 0x60, 0x25, 0x26, 0x70, 0xea, 0x66, 0x80, 0x02, 0x86, 
+        0x25, 0x00, 0x0c, 0x94, 0x47, 0x90, 0x02, 0xc6, 0x28, 0x00, 0x26, 0x90, 0x1d, 0x21, 0xeb, 0xff, 
+        0x31, 0xec, 0xff, 0x42, 0xa0, 0xb9, 0x01, 0xe2, 0xdd, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x22, 
+        0x0c, 0x04, 0x05, 0x27, 0x01, 0x86, 0xef, 0xff, 0x00, 0x00, 0x00, 0x01, 0xaa, 0xe1, 0xc0, 0x00, 
+        0x00, 0x71, 0xe1, 0xff, 0x62, 0x2c, 0x00, 0x70, 0x66, 0x80, 0x52, 0x06, 0x00, 0x52, 0xc5, 0xff, 
+        0x52, 0x46, 0x00, 0x01, 0xa5, 0xe1, 0xc0, 0x00, 0x00, 0x05, 0x36, 0xf8, 0xc6, 0xe5, 0xff, 0x01, 
+        0xa1, 0xe1, 0xc0, 0x00, 0x00, 0xa1, 0xd8, 0xff, 0x92, 0x2c, 0x00, 0xa0, 0x99, 0x80, 0x82, 0x09, 
+        0x00, 0x82, 0xc8, 0xff, 0x82, 0x49, 0x00, 0x01, 0x9c, 0xe1, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x85, 
+        0x3f, 0x00, 0x46, 0xdc, 0xff, 0x01, 0x97, 0xe1, 0xc0, 0x00, 0x00, 0x21, 0xcf, 0xff, 0x02, 0x2c, 
+        0x00, 0x20, 0x00, 0x80, 0xb2, 0x00, 0x00, 0xb2, 0xcb, 0xff, 0xb2, 0x40, 0x00, 0x01, 0x92, 0xe1, 
+        0xc0, 0x00, 0x00, 0x05, 0x9d, 0x00, 0x46, 0xd3, 0xff, 0x20, 0x42, 0x20, 0x40, 0x40, 0x80, 0x32, 
+        0x04, 0x00, 0x32, 0xc3, 0xff, 0x32, 0x44, 0x00, 0x05, 0xc5, 0x01, 0x06, 0xce, 0xff, 0x01, 0x89, 
+        0xe1, 0xc0, 0x00, 0x00, 0x71, 0xc1, 0xff, 0x62, 0x2c, 0x00, 0x7a, 0x66, 0x52, 0x06, 0x00, 0x0b, 
+        0x55, 0x52, 0x46, 0x00, 0x01, 0x85, 0xe1, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x45, 0x55, 0xf8, 0x0c, 
+        0x12, 0x05, 0x55, 0xf8, 0x05, 0x8a, 0xff, 0x06, 0xc3, 0xff, 0x00, 0x00, 0xb8, 0x80, 0xfe, 0x3f, 
+        0x60, 0x8d, 0xfe, 0x3f, 0x00, 0x08, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x78, 0x72, 0x09, 0x01, 0x08, 
+        0x07, 0x48, 0x02, 0x00, 0x56, 0x41, 0x87, 0x70, 0x06, 0x68, 0x14, 0x4b, 0x66, 0x46, 0x00, 0x00, 
+        0x68, 0x14, 0x0c, 0xca, 0x82, 0x06, 0x04, 0x0c, 0x24, 0x07, 0x68, 0x10, 0x00, 0x00, 0x54, 0x40, 
+        0x35, 0x20, 0xa0, 0x33, 0x11, 0x30, 0x00, 0x20, 0x09, 0x07, 0x00, 0x56, 0x41, 0x92, 0x06, 0x00, 
+        0x82, 0xa0, 0xf0, 0xa0, 0x49, 0x10, 0x80, 0x89, 0x10, 0x66, 0x84, 0x46, 0x00, 0x00, 0x54, 0x0c, 
+        0x83, 0x30, 0x35, 0x20, 0xa0, 0x33, 0x11, 0x30, 0x00, 0x20, 0x09, 0x07, 0x26, 0xd8, 0x05, 0x42, 
+        0xa0, 0xc0, 0x47, 0x98, 0x13, 0x00, 0x50, 0x54, 0x31, 0x62, 0xfe, 0x00, 0x06, 0x41, 0x30, 0x00, 
+        0x10, 0xa0, 0x00, 0x11, 0x00, 0x05, 0x20, 0x09, 0x07, 0x00, 0x56, 0x41, 0x08, 0x01, 0x27, 0x75, 
+        0x0c, 0x58, 0x02, 0x42, 0x16, 0x0b, 0x58, 0x15, 0x40, 0x44, 0x41, 0x42, 0x45, 0x03, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0xa7, 0x89, 0xe5, 0x66, 0xe8, 0x38, 0x69, 0x11, 0x00, 0xa0, 0x54, 0x91, 0xd7, 
+        0xff, 0xb1, 0x32, 0xf9, 0x98, 0x09, 0xb0, 0xb5, 0x20, 0xa0, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xa9, 
+        0x07, 0x82, 0x29, 0x9a, 0x29, 0x21, 0x1b, 0x88, 0x82, 0x69, 0x9a, 0xb6, 0x68, 0x0e, 0x21, 0xd0, 
+        0xff, 0x01, 0x7f, 0xdd, 0xc0, 0x00, 0x00, 0x28, 0x21, 0x78, 0x72, 0x68, 0x11, 0x08, 0x07, 0x86, 
+        0xe9, 0xff, 0x66, 0xd8, 0xa6, 0x17, 0xe5, 0xa3, 0x31, 0xcb, 0xff, 0x00, 0x00, 0x54, 0x30, 0x35, 
+        0x20, 0xa0, 0x33, 0x11, 0x30, 0x00, 0x20, 0x09, 0x07, 0x06, 0xe3, 0xff, 0x64, 0x8d, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0x58, 0x72, 0xcd, 0x02, 0x32, 0x05, 0x06, 0x02, 0x05, 
+        0x04, 0x30, 0x34, 0x24, 0x00, 0x00, 0x34, 0x9c, 0x30, 0x26, 0x30, 0x11, 0xa6, 0x30, 0x09, 0x0c, 
+        0x12, 0xa6, 0x60, 0x0b, 0x0c, 0x02, 0x86, 0x01, 0x00, 0x0c, 0x32, 0x46, 0x00, 0x00, 0x0c, 0x22, 
+        0x37, 0x12, 0x11, 0x21, 0x6e, 0xff, 0x31, 0x6e, 0xff, 0x42, 0xa1, 0x1d, 0x01, 0x65, 0xdd, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0xc0, 0x2c, 0x20, 0xc5, 0xec, 0xff, 0x2d, 0x0c, 0x45, 0xc9, 0x01, 
+        0x0b, 0x42, 0x16, 0xf4, 0x09, 0x01, 0x2b, 0xe1, 0xc0, 0x00, 0x00, 0x28, 0x5c, 0x38, 0x7c, 0x45, 
+        0xea, 0x02, 0x01, 0x29, 0xe1, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x85, 0xe4, 0x01, 0x2d, 0x0c, 0x85, 
+        0xb1, 0x01, 0x0c, 0x05, 0x41, 0xa6, 0xff, 0x56, 0x32, 0x04, 0x01, 0x22, 0xe1, 0xc0, 0x00, 0x00, 
+        0x61, 0xa3, 0xff, 0x78, 0x7c, 0x0c, 0x08, 0x89, 0x6c, 0x82, 0x07, 0x00, 0x68, 0x06, 0x80, 0x82, 
+        0x34, 0xb0, 0x88, 0x11, 0x8a, 0x86, 0x88, 0x78, 0xc9, 0x08, 0x72, 0x07, 0x00, 0x52, 0xcc, 0x18, 
+        0x70, 0x72, 0x34, 0xb0, 0x77, 0x11, 0x7a, 0x66, 0x59, 0x76, 0x01, 0x17, 0xe1, 0xc0, 0x00, 0x00, 
+        0x28, 0x7c, 0x22, 0x02, 0x06, 0x20, 0x24, 0x24, 0x45, 0xbe, 0x01, 0xc6, 0x12, 0x00, 0x66, 0x12, 
+        0x27, 0x68, 0x7c, 0x59, 0x6c, 0x82, 0x06, 0x00, 0x78, 0x04, 0x80, 0x81, 0x04, 0x70, 0x88, 0xb0, 
+        0x82, 0x28, 0x8b, 0xc9, 0x08, 0x62, 0x06, 0x00, 0x32, 0xcc, 0x18, 0x60, 0x61, 0x04, 0x70, 0x66, 
+        0xb0, 0x32, 0x66, 0x8b, 0x0c, 0x02, 0x06, 0x08, 0x00, 0x66, 0x22, 0xf7, 0x21, 0xc4, 0xff, 0x01, 
+        0x38, 0xdd, 0xc0, 0x00, 0x00, 0x01, 0x03, 0xe1, 0xc0, 0x00, 0x00, 0xc0, 0x2c, 0x20, 0x05, 0xb8, 
+        0x01, 0x01, 0x01, 0xe1, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x01, 0xc2, 0x21, 0x01, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x05, 0xa1, 0x01, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x71, 0x7a, 0xff, 0x0c, 0x18, 0x78, 0x07, 0x62, 0xa1, 0xc8, 0x6a, 0x67, 
+        0x52, 0x06, 0x80, 0x00, 0x03, 0x40, 0x50, 0x40, 0xb1, 0x07, 0x64, 0x03, 0x2d, 0x08, 0x0d, 0xf0, 
+        0x00, 0x13, 0x40, 0x70, 0x93, 0xa0, 0x00, 0xa8, 0xa1, 0xa0, 0xa5, 0x20, 0xa2, 0x46, 0x80, 0x22, 
+        0x69, 0x93, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x50, 0x50, 0x00, 0x40, 0x12, 0xc1, 0xf0, 0xc2, 
+        0x61, 0x01, 0x02, 0x61, 0x00, 0x20, 0xc2, 0x20, 0x28, 0x02, 0x38, 0x3c, 0x39, 0x12, 0x08, 0x7c, 
+        0x02, 0x10, 0x00, 0x42, 0x1c, 0x04, 0x00, 0x00, 0xb4, 0x47, 0xe0, 0x07, 0x38, 0x1c, 0xc5, 0x65, 
+        0x04, 0xc6, 0x09, 0x00, 0x32, 0xc4, 0xff, 0x30, 0x30, 0xf4, 0x01, 0xf3, 0xff, 0xc0, 0x00, 0x00, 
+        0x3d, 0x02, 0x42, 0x1c, 0x04, 0x0c, 0x05, 0x0b, 0x44, 0x59, 0x22, 0x28, 0x0c, 0x40, 0x40, 0xf4, 
+        0x85, 0x63, 0x04, 0x38, 0x1c, 0x0c, 0x14, 0x2d, 0x03, 0xc5, 0x77, 0x04, 0x2d, 0x0c, 0x0c, 0x73, 
+        0xc5, 0x6e, 0xfc, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0xd9, 
+        0x21, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0x8c, 0x42, 0x01, 0xce, 0xe0, 0xc0, 0x00, 0x00, 0x0c, 
+        0x0d, 0xd0, 0x2d, 0x20, 0x85, 0x8c, 0xfc, 0x16, 0xc2, 0x07, 0xd2, 0xcd, 0x01, 0xd0, 0xd0, 0x74, 
+        0x66, 0x4d, 0xed, 0xd1, 0x4a, 0xff, 0x02, 0x2d, 0x00, 0x38, 0x00, 0x30, 0x20, 0x60, 0x30, 0x22, 
+        0x10, 0x20, 0xf2, 0x40, 0x20, 0x20, 0x60, 0x22, 0xc2, 0x1f, 0x96, 0xe2, 0x06, 0xb0, 0x42, 0x11, 
+        0x4a, 0x40, 0x58, 0x64, 0x56, 0xf5, 0x04, 0x58, 0xb4, 0x42, 0x04, 0x24, 0x56, 0x75, 0x04, 0x9c, 
+        0x34, 0x26, 0x34, 0x11, 0xb6, 0x34, 0x09, 0x0c, 0x15, 0xb6, 0x64, 0x0b, 0x0c, 0x05, 0x86, 0x01, 
+        0x00, 0x0c, 0x35, 0x46, 0x00, 0x00, 0x0c, 0x25, 0x72, 0xa0, 0x01, 0x50, 0x90, 0x74, 0x20, 0xa0, 
+        0x74, 0x00, 0x1a, 0x40, 0x00, 0x99, 0xa0, 0x82, 0x29, 0x01, 0xa2, 0xaf, 0xff, 0x00, 0x77, 0xa1, 
+        0xa0, 0x77, 0x30, 0x70, 0x88, 0x10, 0x89, 0x19, 0x68, 0x00, 0x0c, 0x82, 0x70, 0x66, 0x10, 0x69, 
+        0x00, 0xc5, 0xa4, 0x01, 0x86, 0xe3, 0xff, 0x8c, 0x4c, 0x01, 0xab, 0xe0, 0xc0, 0x00, 0x00, 0x0c, 
+        0x12, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xb8, 0x60, 0x56, 0x5b, 
+        0xfe, 0xd8, 0xe0, 0x56, 0x0d, 0xfe, 0x22, 0x20, 0x8a, 0x56, 0xa2, 0xfd, 0x32, 0x20, 0x8c, 0x56, 
+        0x43, 0xfd, 0x8c, 0x4c, 0x01, 0xa1, 0xe0, 0xc0, 0x00, 0x00, 0x0c, 0x02, 0x46, 0xf4, 0xff, 0x00, 
+        0x00, 0x2b, 0xff, 0x3f, 0xf8, 0x23, 0xff, 0x3f, 0x0c, 0x06, 0x12, 0xc1, 0xe0, 0xc9, 0x21, 0xd9, 
+        0x31, 0x09, 0x11, 0xe9, 0x41, 0xf9, 0x51, 0x69, 0x61, 0x7c, 0xff, 0x0c, 0x1e, 0x45, 0x20, 0x01, 
+        0x16, 0x92, 0x0e, 0x51, 0x16, 0xff, 0xd8, 0x72, 0x02, 0xa1, 0xc8, 0xd2, 0x0d, 0x0e, 0x29, 0x01, 
+        0xd0, 0xc0, 0x60, 0xd0, 0xcc, 0x10, 0xc0, 0xfc, 0x40, 0xc0, 0xc0, 0x60, 0xc2, 0xcc, 0x1f, 0x96, 
+        0xfc, 0x02, 0x68, 0x05, 0x0a, 0x36, 0x32, 0x03, 0x80, 0x00, 0x0c, 0x40, 0x30, 0x30, 0x91, 0x07, 
+        0x63, 0x10, 0x60, 0x0c, 0xa0, 0x02, 0x20, 0x93, 0x28, 0x01, 0xc0, 0x00, 0x00, 0x02, 0xa1, 0xc8, 
+        0x51, 0x07, 0xff, 0x00, 0x1c, 0x40, 0x00, 0x3e, 0xa1, 0xf0, 0x33, 0x30, 0x30, 0xdd, 0x10, 0x46, 
+        0xef, 0xff, 0x38, 0x01, 0x38, 0x73, 0x08, 0x03, 0x37, 0x70, 0x6a, 0x28, 0x01, 0x28, 0x52, 0x05, 
+        0xea, 0xfd, 0x38, 0x01, 0x38, 0x73, 0x08, 0x03, 0x00, 0x56, 0x41, 0x87, 0xf0, 0x12, 0x97, 0x60, 
+        0x0f, 0x38, 0x01, 0x28, 0x53, 0x05, 0x4d, 0x03, 0x38, 0x01, 0x38, 0x73, 0x58, 0x03, 0x50, 0x56, 
+        0x41, 0xb7, 0x65, 0x13, 0x42, 0x03, 0x0f, 0x66, 0x14, 0x0d, 0x22, 0x03, 0x00, 0x20, 0x21, 0x04, 
+        0x45, 0x29, 0x00, 0x8c, 0x12, 0xc5, 0xdf, 0xf7, 0x48, 0x01, 0x0c, 0x0c, 0x28, 0x04, 0x58, 0x34, 
+        0x59, 0x12, 0x38, 0x14, 0x42, 0x14, 0x04, 0xc9, 0x23, 0x01, 0x0d, 0xdf, 0xc0, 0x00, 0x00, 0x0c, 
+        0x29, 0x88, 0x01, 0x71, 0xcb, 0xff, 0x82, 0x18, 0x04, 0x62, 0x07, 0x00, 0x99, 0x61, 0x8a, 0x66, 
+        0x62, 0x47, 0x00, 0xc6, 0x03, 0x00, 0x47, 0x70, 0x19, 0x0c, 0x49, 0x99, 0x61, 0x46, 0x01, 0x00, 
+        0x00, 0xab, 0x05, 0x56, 0x6a, 0xf2, 0x28, 0x01, 0x38, 0x61, 0x45, 0x51, 0xfc, 0x06, 0xc7, 0xff, 
+        0x00, 0x00, 0x00, 0x57, 0x70, 0xe9, 0x0c, 0x5b, 0xb9, 0x61, 0x06, 0xfa, 0xff, 0xd1, 0xbc, 0xff, 
+        0xd2, 0x0d, 0x00, 0xc2, 0xa0, 0x1d, 0xd7, 0xbc, 0x0a, 0x01, 0xb9, 0xff, 0x0c, 0x0f, 0xf2, 0x40, 
+        0x00, 0x85, 0xe2, 0xf7, 0xd1, 0xb8, 0xff, 0x0c, 0x02, 0xc2, 0xcd, 0xe8, 0x22, 0x4c, 0x14, 0x2d, 
+        0x0d, 0x01, 0x59, 0xe0, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x05, 0xdf, 0xff, 0xdc, 0x82, 0x05, 0x6f, 
+        0xff, 0x9c, 0x32, 0xc5, 0x81, 0xff, 0x8c, 0xe2, 0x2d, 0x0d, 0xe2, 0x4c, 0x14, 0x32, 0xa0, 0xc8, 
+        0x0c, 0x04, 0x01, 0x53, 0xe0, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 
+        0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x22, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 
+        0x00, 0x45, 0x85, 0xff, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0xd2, 
+        0x61, 0x02, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 0xcd, 0x02, 0x01, 0x3a, 0xe0, 0xc0, 0x00, 0x00, 
+        0x2d, 0x0c, 0xc5, 0x67, 0xfc, 0xcc, 0x92, 0x01, 0x38, 0xe0, 0xc0, 0x00, 0x00, 0x7c, 0xf2, 0xc6, 
+        0x17, 0x00, 0xc0, 0x2c, 0x20, 0x05, 0x2b, 0x01, 0x20, 0xd2, 0x20, 0x56, 0xa2, 0x00, 0x01, 0x32, 
+        0xe0, 0xc0, 0x00, 0x00, 0x7c, 0xe2, 0x06, 0x12, 0x00, 0x22, 0x22, 0x07, 0x32, 0x22, 0x00, 0x01, 
+        0xaf, 0xfe, 0x87, 0x73, 0x13, 0x28, 0x5d, 0x45, 0x41, 0x03, 0x16, 0xf2, 0x03, 0x2d, 0x0d, 0x05, 
+        0x8d, 0x00, 0x01, 0xaa, 0xfe, 0xdd, 0x02, 0x28, 0x72, 0x48, 0x02, 0x68, 0x00, 0xd7, 0x74, 0x0f, 
+        0x52, 0x26, 0x99, 0x72, 0x26, 0x9a, 0x1b, 0x55, 0x0b, 0x77, 0x72, 0x66, 0x9a, 0x52, 0x66, 0x99, 
+        0x01, 0x22, 0xe0, 0xc0, 0x00, 0x00, 0xc0, 0x3c, 0x20, 0xd0, 0x2d, 0x20, 0x05, 0xb8, 0xfd, 0x22, 
+        0xa0, 0x00, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xd0, 0x2d, 0x20, 
+        0x05, 0x78, 0x00, 0x52, 0x2d, 0x06, 0x01, 0x99, 0xfe, 0x16, 0x75, 0x05, 0x50, 0x25, 0x20, 0x78, 
+        0x1d, 0x0c, 0x06, 0x69, 0x6d, 0x69, 0x27, 0x88, 0x12, 0x3d, 0x02, 0x28, 0x62, 0x69, 0x28, 0x56, 
+        0x42, 0xff, 0x28, 0x7d, 0x92, 0x02, 0x00, 0x78, 0x00, 0x90, 0x92, 0x34, 0xb0, 0x99, 0x11, 0x9a, 
+        0x97, 0x98, 0x69, 0x99, 0x63, 0xcc, 0xe9, 0xb2, 0x02, 0x00, 0xa2, 0xc3, 0x18, 0xb0, 0xb2, 0x34, 
+        0xb0, 0xbb, 0x11, 0xba, 0xb7, 0xa9, 0x7b, 0x42, 0x02, 0x00, 0x40, 0x42, 0x34, 0xb0, 0x44, 0x11, 
+        0x4a, 0x47, 0x59, 0x64, 0x32, 0x02, 0x00, 0x30, 0x32, 0x34, 0xb0, 0x33, 0x11, 0x3a, 0x37, 0x69, 
+        0xb3, 0x06, 0xd9, 0xff, 0x28, 0x7d, 0xc6, 0xd7, 0xff, 0x00, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 
+        0x31, 0x7f, 0xfe, 0x0c, 0x02, 0x22, 0x43, 0x04, 0x0d, 0xf0, 0x00, 0x00, 0x31, 0x7c, 0xfe, 0x0c, 
+        0x02, 0x22, 0x43, 0x05, 0x0d, 0xf0, 0x00, 0x00, 0x21, 0x79, 0xfe, 0x22, 0x02, 0x05, 0x0d, 0xf0, 
+        0x90, 0x26, 0xff, 0x3f, 0x90, 0x29, 0xff, 0x3f, 0xd0, 0x29, 0xff, 0x3f, 0xbe, 0x80, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x21, 0x01, 0x71, 0xfe, 0x29, 0x11, 0x02, 0x00, 0x04, 0x39, 0x01, 0x56, 
+        0xe0, 0x04, 0x30, 0x33, 0x90, 0x21, 0xf6, 0xff, 0x90, 0x33, 0x11, 0x3a, 0x22, 0x38, 0x11, 0x42, 
+        0xa1, 0x80, 0x38, 0x33, 0x01, 0x56, 0xdf, 0xc0, 0x00, 0x00, 0x2c, 0x04, 0x38, 0x01, 0x21, 0xf1, 
+        0xff, 0xb0, 0x33, 0x11, 0x3a, 0x22, 0x38, 0x11, 0x01, 0x51, 0xdf, 0xc0, 0x00, 0x00, 0x41, 0xee, 
+        0xff, 0x28, 0x01, 0x38, 0x11, 0x20, 0x22, 0x90, 0x38, 0x03, 0x40, 0x22, 0xa0, 0x0c, 0xc4, 0x01, 
+        0x4b, 0xdf, 0xc0, 0x00, 0x00, 0x61, 0xe9, 0xff, 0x58, 0x01, 0x0c, 0x14, 0x6a, 0x55, 0x42, 0x45, 
+        0x00, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x51, 0x59, 0xfe, 0x32, 0x05, 0x04, 0xcc, 0x73, 
+        0x0c, 0x04, 0x6b, 0x65, 0x6a, 0x62, 0x42, 0x46, 0x00, 0x0d, 0xf0, 0x00, 0x51, 0x54, 0xfe, 0x42, 
+        0x05, 0x04, 0xcc, 0x74, 0x8b, 0x75, 0x70, 0x33, 0xa0, 0x68, 0x03, 0x8c, 0x26, 0x0c, 0x02, 0x0d, 
+        0xf0, 0x29, 0x03, 0x0c, 0x12, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x03, 0x20, 0xc2, 
+        0x20, 0x21, 0x4a, 0xfe, 0x02, 0x61, 0x02, 0x02, 0x02, 0x04, 0xdc, 0xb0, 0x8b, 0x02, 0x00, 0x0c, 
+        0xa0, 0x38, 0x00, 0x9c, 0x23, 0x6b, 0x32, 0x3a, 0x3c, 0x32, 0x03, 0x00, 0x09, 0x11, 0x8c, 0x73, 
+        0x0c, 0x72, 0xc5, 0x13, 0xfc, 0x29, 0x01, 0xcc, 0x32, 0x0c, 0x02, 0x46, 0x20, 0x00, 0x31, 0xc9, 
+        0xff, 0xb0, 0x4c, 0x11, 0x4a, 0x33, 0x2c, 0x04, 0x01, 0x29, 0xdf, 0xc0, 0x00, 0x00, 0x41, 0xc6, 
+        0xff, 0x28, 0x11, 0xc0, 0x3c, 0x90, 0x28, 0x02, 0x40, 0x33, 0xa0, 0x0c, 0xc4, 0x01, 0x23, 0xdf, 
+        0xc0, 0x00, 0x00, 0x28, 0x01, 0x71, 0x54, 0xde, 0x88, 0x72, 0xc0, 0x20, 0x00, 0x72, 0x27, 0x80, 
+        0x68, 0x11, 0x79, 0x18, 0x0c, 0x18, 0x98, 0x06, 0x99, 0x02, 0x68, 0x06, 0x69, 0x12, 0x98, 0x19, 
+        0x99, 0x32, 0x82, 0x52, 0x04, 0x72, 0xa0, 0xbf, 0xc0, 0x20, 0x00, 0x52, 0x06, 0x03, 0x70, 0x55, 
+        0x10, 0xc0, 0x20, 0x00, 0x31, 0xb3, 0xff, 0x52, 0x46, 0x03, 0xc0, 0x4c, 0x90, 0x90, 0x44, 0x11, 
+        0x28, 0x32, 0x4a, 0x33, 0x42, 0xa1, 0x80, 0x01, 0x11, 0xdf, 0xc0, 0x00, 0x00, 0xa8, 0x11, 0xc8, 
+        0x01, 0x0c, 0x09, 0x2d, 0x0c, 0xb8, 0x3c, 0xc8, 0x0c, 0xb2, 0xcb, 0x18, 0xb9, 0x1c, 0x99, 0x0a, 
+        0xc8, 0x31, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x70, 0x8d, 0xfe, 0x3f, 
+        0x90, 0x87, 0xfe, 0x3f, 0xff, 0x00, 0x00, 0xff, 0x0c, 0xc7, 0x12, 0xc1, 0xe0, 0xd9, 0x61, 0x29, 
+        0x01, 0xe9, 0x71, 0x09, 0x41, 0xe8, 0x02, 0xc9, 0x51, 0xe8, 0x1e, 0xcd, 0x03, 0x62, 0x0e, 0x00, 
+        0x02, 0x03, 0x03, 0x70, 0x36, 0x10, 0x47, 0xe0, 0x05, 0x00, 0x26, 0x04, 0x16, 0x42, 0x12, 0x57, 
+        0xe0, 0x09, 0x00, 0x47, 0x41, 0xcc, 0x34, 0x0c, 0x0d, 0x86, 0x00, 0x00, 0xd2, 0xa0, 0x02, 0x66, 
+        0x83, 0x36, 0x21, 0xec, 0xfe, 0x52, 0xa0, 0x00, 0x62, 0xc2, 0xe8, 0x52, 0x46, 0x14, 0x01, 0x8e, 
+        0xdf, 0xc0, 0x00, 0x00, 0x85, 0x3c, 0xff, 0x16, 0x32, 0x05, 0x45, 0x4f, 0xff, 0x16, 0xd2, 0x04, 
+        0x32, 0xa0, 0xc8, 0x0c, 0x04, 0x91, 0x92, 0xfd, 0x0c, 0x18, 0x82, 0x49, 0x14, 0x22, 0xc9, 0x18, 
+        0x01, 0x88, 0xdf, 0xc0, 0x00, 0x00, 0x06, 0x0d, 0x00, 0xfc, 0x13, 0xa2, 0xa0, 0xf0, 0xa0, 0xa6, 
+        0x10, 0x66, 0xea, 0x29, 0x70, 0xb6, 0x10, 0xb2, 0xcb, 0xfc, 0x56, 0xfb, 0x0d, 0x21, 0xdb, 0xff, 
+        0x31, 0xdc, 0xff, 0x01, 0xa7, 0xdb, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x22, 0xa0, 0x01, 0x32, 
+        0x21, 0x03, 0x05, 0x2f, 0x03, 0x8c, 0x52, 0x28, 0x01, 0x0c, 0x13, 0x45, 0xdf, 0xff, 0xb6, 0x2d, 
+        0x02, 0x06, 0x24, 0x00, 0x2d, 0x0d, 0xab, 0x3e, 0x85, 0x2d, 0x03, 0x08, 0x01, 0x3d, 0x0c, 0x29, 
+        0x50, 0xc5, 0x1f, 0x02, 0x32, 0x0c, 0x00, 0x5b, 0x33, 0x32, 0x4c, 0x00, 0x22, 0x0e, 0x01, 0x42, 
+        0x0e, 0x04, 0x67, 0x62, 0x6f, 0x40, 0x40, 0x04, 0x16, 0x64, 0x08, 0x2d, 0x0d, 0x85, 0x8d, 0x04, 
+        0x72, 0xc2, 0xfe, 0x0c, 0x16, 0x0c, 0x05, 0x70, 0x56, 0x83, 0x16, 0x75, 0x05, 0x81, 0xc5, 0xff, 
+        0x92, 0x1c, 0x03, 0xa2, 0x1c, 0x01, 0xd1, 0x7e, 0xf0, 0xa0, 0xb0, 0xb4, 0xb2, 0xcb, 0xfc, 0xd0, 
+        0xaa, 0x10, 0xb0, 0xb0, 0xb4, 0xb0, 0xaa, 0x20, 0xa2, 0x5c, 0x01, 0xa2, 0x1c, 0x02, 0x00, 0x99, 
+        0x11, 0xa0, 0x99, 0x20, 0x80, 0x89, 0x10, 0x90, 0x98, 0xf4, 0x92, 0xc9, 0xfc, 0x90, 0x90, 0xf4, 
+        0x80, 0x99, 0x11, 0x90, 0x88, 0x20, 0x82, 0x5c, 0x02, 0x80, 0x80, 0xf5, 0x82, 0x5c, 0x03, 0x45, 
+        0x3e, 0xf8, 0x02, 0x0e, 0x04, 0x00, 0x00, 0x04, 0x1b, 0x00, 0x07, 0x92, 0x07, 0x7c, 0x52, 0x22, 
+        0x4c, 0x08, 0x85, 0x3d, 0xf8, 0x0c, 0x02, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0x08, 0x41, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0x57, 0xe0, 0x05, 0x00, 0x47, 0x41, 0x16, 0xf4, 0x08, 0x0c, 0x1d, 0x06, 
+        0xb7, 0xff, 0x2d, 0x0d, 0x05, 0x84, 0x04, 0x46, 0xdd, 0xff, 0x00, 0x00, 0x00, 0x72, 0xa0, 0x88, 
+        0x1c, 0x88, 0x1c, 0xe0, 0x92, 0x0e, 0x01, 0x52, 0xa0, 0x8c, 0x50, 0x56, 0x10, 0x90, 0x90, 0x14, 
+        0x92, 0xc9, 0xfd, 0x90, 0x08, 0x93, 0x77, 0x95, 0x01, 0x2b, 0x00, 0x62, 0x0c, 0x01, 0x09, 0x21, 
+        0x60, 0x66, 0x41, 0xcc, 0x96, 0x72, 0x1c, 0x01, 0x70, 0x70, 0xb4, 0x79, 0x11, 0x46, 0x04, 0x00, 
+        0x82, 0x1c, 0x03, 0x92, 0x1c, 0x02, 0x00, 0x88, 0x11, 0x90, 0x88, 0x20, 0x80, 0x88, 0xf4, 0x82, 
+        0x61, 0x01, 0x22, 0xce, 0x0a, 0x29, 0x31, 0x05, 0x3d, 0xff, 0x9c, 0x82, 0x28, 0x01, 0x58, 0x21, 
+        0x48, 0x11, 0x32, 0xce, 0x18, 0x50, 0x44, 0xc0, 0x42, 0xc4, 0xfc, 0x40, 0x40, 0xf4, 0x4a, 0x4e, 
+        0x42, 0xc4, 0x18, 0x05, 0x57, 0xfe, 0x22, 0xa0, 0x00, 0x32, 0x21, 0x03, 0x45, 0x1b, 0x03, 0x16, 
+        0x92, 0xeb, 0x22, 0x21, 0x00, 0x0c, 0x03, 0x85, 0xcb, 0xff, 0x06, 0xb0, 0xff, 0x0c, 0x2d, 0x06, 
+        0x93, 0xff, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0x46, 0x01, 0x00, 0xc0, 0x2c, 
+        0x20, 0x85, 0x8b, 0xff, 0x05, 0xc6, 0x00, 0x20, 0xc2, 0x20, 0x16, 0x62, 0x03, 0xc5, 0x48, 0x04, 
+        0x08, 0x3c, 0x48, 0x0c, 0x32, 0xc0, 0x18, 0x39, 0x14, 0x28, 0x7c, 0x22, 0x12, 0x00, 0xcb, 0x30, 
+        0x20, 0x20, 0xb4, 0x47, 0xe2, 0x12, 0x22, 0x00, 0x14, 0x52, 0xa0, 0xf5, 0x8c, 0x12, 0x57, 0x92, 
+        0xcc, 0x2d, 0x0c, 0x45, 0xdd, 0xff, 0x56, 0xa2, 0xfc, 0x2d, 0x0c, 0x85, 0x86, 0xf7, 0x86, 0xf0, 
+        0xff, 0x00, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x11, 0xf6, 0xb2, 0x2e, 0x01, 0x85, 0xfd, 0x08, 0x00, 0xb0, 0x32, 0x11, 
+        0x3a, 0x00, 0x02, 0x00, 0x27, 0x39, 0x01, 0xdc, 0xc0, 0x01, 0xfe, 0xde, 0xc0, 0x00, 0x00, 0x21, 
+        0x7f, 0xfd, 0x38, 0x01, 0x28, 0x02, 0x3a, 0x22, 0x28, 0x62, 0x29, 0x21, 0x01, 0xfb, 0xde, 0xc0, 
+        0x00, 0x00, 0x08, 0x21, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x8c, 0x70, 0x38, 0x70, 0x38, 0x03, 0x87, 
+        0x73, 0x01, 0x0c, 0x00, 0x2d, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0xf6, 0xb2, 0x2b, 0x41, 0x72, 0xfd, 0x48, 0x04, 0xb0, 0x52, 0x11, 0x5a, 0x44, 0x32, 0x04, 0x27, 
+        0x28, 0x64, 0xdc, 0x93, 0x9c, 0x92, 0x58, 0x72, 0x58, 0x05, 0x68, 0x62, 0x87, 0xf5, 0x11, 0x69, 
+        0x64, 0x0c, 0x08, 0xcc, 0x36, 0x72, 0xc4, 0x18, 0x79, 0x74, 0x89, 0x62, 0x46, 0x00, 0x00, 0x0c, 
+        0x02, 0x8c, 0x72, 0x98, 0x72, 0x98, 0x09, 0x87, 0x79, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 
+        0xf6, 0xb2, 0x1e, 0x41, 0x62, 0xfd, 0x48, 0x04, 0xb0, 0x52, 0x11, 0x5a, 0x44, 0x28, 0x64, 0x9c, 
+        0x12, 0x0c, 0x07, 0x58, 0x62, 0x59, 0x64, 0xcc, 0x35, 0x62, 0xc4, 0x18, 0x69, 0x74, 0x79, 0x62, 
+        0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x58, 0x72, 0x41, 0x58, 0xfd, 0x52, 0x05, 0x00, 
+        0x48, 0x04, 0x50, 0x52, 0x34, 0xb0, 0x55, 0x11, 0x5a, 0x44, 0x38, 0x64, 0x39, 0x62, 0xcc, 0x33, 
+        0x62, 0xc2, 0x18, 0x69, 0x74, 0x29, 0x64, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xff, 0x3f, 
+        0x0f, 0xf8, 0x00, 0x00, 0x32, 0xa0, 0x06, 0x42, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x31, 0x29, 
+        0x01, 0x09, 0x21, 0x0c, 0x02, 0x45, 0xdf, 0xfb, 0x38, 0x01, 0x61, 0xf8, 0xff, 0x30, 0x53, 0xb0, 
+        0x60, 0x55, 0xa0, 0x59, 0x11, 0x1c, 0x86, 0x59, 0x02, 0x62, 0x52, 0x08, 0xcd, 0x02, 0x71, 0xe4, 
+        0xef, 0xc0, 0x20, 0x00, 0x42, 0x15, 0x00, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0xc0, 0x20, 0x00, 
+        0x0c, 0x16, 0x42, 0x55, 0x00, 0x30, 0x30, 0x24, 0x58, 0x0c, 0xc0, 0x33, 0x11, 0x62, 0x52, 0x04, 
+        0x28, 0x72, 0x59, 0x1c, 0x02, 0x02, 0x06, 0x42, 0xa0, 0x8f, 0x40, 0x00, 0x10, 0x30, 0x00, 0x20, 
+        0x02, 0x42, 0x06, 0x01, 0xb4, 0xde, 0xc0, 0x00, 0x00, 0x28, 0x5c, 0x38, 0x7c, 0x45, 0x4c, 0x02, 
+        0x01, 0xb2, 0xde, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x85, 0x46, 0x01, 0xb1, 0xe1, 0xff, 0x31, 0xd0, 
+        0xef, 0x0c, 0x07, 0x92, 0xaf, 0x84, 0x22, 0x1c, 0x08, 0x88, 0x11, 0x20, 0x20, 0xb4, 0x02, 0x18, 
+        0x06, 0xa2, 0x08, 0x0e, 0x92, 0x48, 0x10, 0x72, 0x48, 0x11, 0x80, 0xaa, 0x11, 0x30, 0x00, 0x10, 
+        0x20, 0x00, 0x20, 0x02, 0x58, 0x06, 0x2d, 0x0c, 0x00, 0x08, 0x74, 0xc8, 0x31, 0x00, 0xaa, 0x20, 
+        0x08, 0x21, 0xb0, 0xaa, 0x10, 0x12, 0xc1, 0x10, 0xa2, 0x48, 0x0d, 0xb2, 0xa0, 0xcf, 0xa0, 0xa8, 
+        0x74, 0xb0, 0xaa, 0x10, 0xa2, 0x48, 0x0e, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0xd9, 0x51, 0x09, 0x31, 0x49, 0x01, 0xc9, 0x41, 0x59, 0x21, 0xcd, 0x02, 0x9c, 
+        0x32, 0x26, 0x32, 0x11, 0xb6, 0x32, 0x09, 0x0c, 0x10, 0xb6, 0x62, 0x0b, 0x0c, 0x00, 0x86, 0x01, 
+        0x00, 0x0c, 0x30, 0x46, 0x00, 0x00, 0x0c, 0x20, 0x21, 0xf9, 0xdb, 0xc0, 0x40, 0x34, 0x52, 0xa0, 
+        0xf0, 0x81, 0x0e, 0xfd, 0x61, 0xbe, 0xff, 0x88, 0x08, 0x00, 0xd0, 0x74, 0x80, 0x8d, 0xa0, 0x82, 
+        0x28, 0x86, 0xd0, 0xdd, 0xb0, 0x08, 0x78, 0x89, 0x11, 0xb2, 0x00, 0x04, 0x60, 0xdd, 0xa0, 0x50, 
+        0xbb, 0x10, 0x40, 0xbb, 0x20, 0xb2, 0x40, 0x04, 0xb8, 0x78, 0x92, 0xcd, 0x10, 0xa8, 0x0b, 0x78, 
+        0x08, 0xa0, 0x06, 0x41, 0x20, 0x00, 0x20, 0xa0, 0xa0, 0x54, 0xa0, 0x00, 0x11, 0x00, 0xaa, 0x20, 
+        0xa9, 0x0b, 0x99, 0x17, 0x52, 0xa0, 0x80, 0x82, 0x18, 0x08, 0xc0, 0x20, 0x00, 0x42, 0x07, 0x03, 
+        0x40, 0x40, 0x64, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x47, 0x03, 0x4c, 0x00, 0x22, 0xa0, 
+        0xbf, 0xc0, 0x20, 0x00, 0xb2, 0x07, 0x03, 0x20, 0xbb, 0x10, 0x00, 0xbb, 0x20, 0xc0, 0x20, 0x00, 
+        0xb2, 0x47, 0x03, 0xa2, 0xa0, 0xdf, 0xc0, 0x20, 0x00, 0x92, 0x07, 0x03, 0xa0, 0x99, 0x10, 0xc0, 
+        0x20, 0x00, 0x92, 0x47, 0x03, 0x80, 0x80, 0xb4, 0x91, 0x0b, 0xdd, 0x40, 0x88, 0x11, 0xc0, 0x20, 
+        0x00, 0x62, 0x17, 0x01, 0x00, 0x66, 0x11, 0xc0, 0x20, 0x00, 0xa2, 0x17, 0x00, 0xa0, 0x66, 0x20, 
+        0x90, 0x66, 0x10, 0x80, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x57, 0x00, 0x60, 0x60, 0xf5, 0xc0, 
+        0x20, 0x00, 0x22, 0xcd, 0x14, 0x0c, 0x64, 0x62, 0x57, 0x01, 0x02, 0x0d, 0x11, 0x52, 0xa0, 0xf7, 
+        0x50, 0x00, 0x10, 0x02, 0x4d, 0x11, 0x01, 0xc9, 0xdd, 0xc0, 0x00, 0x00, 0x38, 0x01, 0x22, 0xcd, 
+        0x1a, 0x0c, 0x64, 0x01, 0xc6, 0xdd, 0xc0, 0x00, 0x00, 0x98, 0x31, 0x08, 0x11, 0x31, 0xbb, 0xff, 
+        0xb1, 0x78, 0xef, 0x40, 0xac, 0x11, 0x28, 0x21, 0xc8, 0x41, 0xc0, 0x22, 0x11, 0xb0, 0xaa, 0x10, 
+        0x30, 0x22, 0x10, 0x22, 0x4d, 0x22, 0x0c, 0x4b, 0xb0, 0xaa, 0x20, 0x20, 0x28, 0x41, 0x22, 0x4d, 
+        0x23, 0xa2, 0x4d, 0x20, 0x2d, 0x00, 0xa0, 0xa8, 0x41, 0xa2, 0x4d, 0x21, 0x0d, 0x09, 0xd8, 0x51, 
+        0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 
+        0x58, 0x02, 0x58, 0x15, 0x0c, 0x43, 0x22, 0x15, 0x00, 0x62, 0x05, 0x02, 0x20, 0x40, 0x14, 0x40, 
+        0x33, 0xc0, 0x30, 0x30, 0x74, 0x40, 0x43, 0x93, 0x20, 0x38, 0x74, 0x80, 0x26, 0x11, 0x30, 0x22, 
+        0x20, 0x20, 0x24, 0x64, 0x40, 0x22, 0xa0, 0x20, 0x20, 0xf4, 0x0d, 0xf0, 0xfc, 0xff, 0x00, 0x00, 
+        0xff, 0xfe, 0xb3, 0x03, 0x12, 0xc1, 0xf0, 0x52, 0x22, 0x00, 0x72, 0x25, 0x01, 0x09, 0x01, 0x72, 
+        0x17, 0x00, 0xc9, 0x11, 0x70, 0x70, 0xb4, 0x72, 0x52, 0x08, 0x62, 0xa0, 0xdf, 0xcd, 0x02, 0xc0, 
+        0x20, 0x00, 0x42, 0x05, 0x03, 0x60, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x45, 0x03, 0x51, 0xcc, 
+        0xdc, 0x41, 0xf2, 0xff, 0x28, 0x02, 0xc0, 0x20, 0x00, 0x32, 0x12, 0x01, 0x00, 0x33, 0x11, 0xc0, 
+        0x20, 0x00, 0x62, 0x12, 0x00, 0x60, 0x33, 0x20, 0x50, 0x33, 0x10, 0x30, 0x3c, 0x41, 0x4a, 0x33, 
+        0x30, 0x30, 0xb4, 0x41, 0xc4, 0xdc, 0x40, 0x33, 0x11, 0xc0, 0x20, 0x00, 0x02, 0x12, 0x01, 0x00, 
+        0x00, 0x11, 0xc0, 0x20, 0x00, 0x52, 0x12, 0x00, 0x50, 0x00, 0x20, 0x40, 0x00, 0x10, 0x30, 0x00, 
+        0x20, 0xc0, 0x20, 0x00, 0x02, 0x52, 0x00, 0x00, 0x00, 0xf5, 0xc0, 0x20, 0x00, 0xb8, 0x0c, 0xa8, 
+        0x1b, 0x02, 0x52, 0x01, 0x4b, 0xaa, 0xa9, 0x1b, 0xa8, 0x7c, 0x92, 0x0a, 0x04, 0x90, 0x90, 0x34, 
+        0x92, 0x4a, 0x04, 0x78, 0x7c, 0x62, 0x07, 0x05, 0x82, 0xa0, 0xc0, 0x80, 0x66, 0x10, 0x62, 0x47, 
+        0x05, 0x48, 0x7c, 0x5b, 0x54, 0x32, 0x05, 0x01, 0x52, 0x05, 0x00, 0x80, 0x33, 0x11, 0x50, 0x33, 
+        0x20, 0x51, 0x00, 0xf4, 0x5b, 0x44, 0x50, 0x33, 0x10, 0x32, 0x44, 0x00, 0x30, 0x38, 0x41, 0x32, 
+        0x44, 0x01, 0x38, 0x7c, 0x28, 0x03, 0x41, 0xce, 0xff, 0x20, 0x00, 0x54, 0x20, 0x26, 0x41, 0x40, 
+        0x22, 0x10, 0xa0, 0x22, 0x11, 0x20, 0x00, 0x20, 0x28, 0x5c, 0x09, 0x03, 0x45, 0x20, 0x02, 0x2d, 
+        0x0c, 0x05, 0x1b, 0x01, 0xb2, 0xa0, 0xbf, 0x4c, 0x0a, 0x98, 0x1c, 0xc0, 0x20, 0x00, 0x82, 0x09, 
+        0x03, 0xb0, 0x88, 0x10, 0xa0, 0x88, 0x20, 0xc0, 0x20, 0x00, 0x82, 0x49, 0x03, 0xc8, 0x11, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0xb4, 0x31, 0x00, 0x40, 
+        0x12, 0xc1, 0xb0, 0xd9, 0xd1, 0xf9, 0xf1, 0x68, 0x02, 0x58, 0x72, 0xe9, 0xe1, 0xc9, 0xc1, 0x09, 
+        0xb1, 0xcd, 0x01, 0x08, 0x52, 0xed, 0x02, 0x78, 0x7e, 0x09, 0xa1, 0x78, 0x07, 0x22, 0x05, 0x04, 
+        0x52, 0x05, 0x00, 0x20, 0x20, 0x34, 0x29, 0x81, 0x50, 0x52, 0x34, 0xe9, 0x61, 0x48, 0x16, 0x52, 
+        0x61, 0x10, 0x42, 0x04, 0x03, 0x49, 0x91, 0x46, 0x00, 0x00, 0xcd, 0x0d, 0xd8, 0x6c, 0x56, 0x8d, 
+        0xff, 0x0c, 0x0d, 0xc7, 0xf7, 0x29, 0xf8, 0x16, 0x22, 0x1f, 0x00, 0x0c, 0x43, 0x20, 0x20, 0xb4, 
+        0x01, 0xeb, 0xff, 0xc0, 0x00, 0x00, 0x32, 0x0f, 0x02, 0x02, 0x0f, 0x01, 0x80, 0xf3, 0x11, 0x00, 
+        0xff, 0x20, 0xf0, 0xf4, 0x64, 0x1b, 0xff, 0x20, 0xff, 0xa0, 0xf0, 0xf0, 0xf4, 0x06, 0x08, 0x00, 
+        0x2d, 0x0c, 0xc5, 0xe4, 0xff, 0xf2, 0x1e, 0x08, 0x58, 0x1c, 0x2a, 0xff, 0xc0, 0x20, 0x00, 0x42, 
+        0x05, 0x03, 0x62, 0xa0, 0xbf, 0x60, 0x44, 0x10, 0xd0, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x45, 
+        0x03, 0x01, 0x3d, 0xdb, 0x81, 0x52, 0xfc, 0x62, 0x21, 0x10, 0x58, 0x08, 0xb0, 0x66, 0x11, 0x6a, 
+        0x55, 0x48, 0x65, 0x62, 0x61, 0x11, 0xdd, 0x04, 0x16, 0x84, 0x09, 0x78, 0x74, 0x78, 0x07, 0x70, 
+        0x76, 0x41, 0x07, 0x87, 0x02, 0xc6, 0x22, 0x00, 0x28, 0x04, 0x28, 0x12, 0x22, 0x61, 0x12, 0x22, 
+        0x12, 0x00, 0x0c, 0x43, 0x20, 0x20, 0xb4, 0x01, 0xcd, 0xff, 0xc0, 0x00, 0x00, 0x02, 0x21, 0x12, 
+        0x81, 0x43, 0xfc, 0x38, 0xa1, 0x20, 0x50, 0xf4, 0x32, 0x13, 0x39, 0xfa, 0x45, 0x47, 0x33, 0x14, 
+        0x78, 0x91, 0x48, 0xa1, 0x62, 0x00, 0x03, 0x42, 0x04, 0x75, 0x70, 0x66, 0xc0, 0x60, 0x60, 0x74, 
+        0x0b, 0x44, 0x67, 0xa4, 0x04, 0x0c, 0x06, 0x86, 0x05, 0x00, 0x62, 0x00, 0x02, 0x72, 0x00, 0x01, 
+        0x80, 0x66, 0x11, 0x70, 0x66, 0x20, 0x60, 0x64, 0x64, 0x1b, 0x66, 0x50, 0x66, 0xa0, 0x60, 0x60, 
+        0xf4, 0xac, 0x86, 0x01, 0x1d, 0xdb, 0x72, 0x21, 0x11, 0x58, 0x08, 0xfa, 0xf6, 0x7a, 0x55, 0x48, 
+        0x65, 0xb8, 0x0d, 0x48, 0x64, 0x49, 0x65, 0xcc, 0x34, 0x92, 0xc5, 0x18, 0x99, 0x75, 0xd9, 0x6c, 
+        0xc8, 0x1c, 0x0c, 0x0a, 0xb9, 0x2c, 0xcd, 0x0d, 0xa9, 0x6d, 0x06, 0xda, 0xff, 0x62, 0x21, 0x11, 
+        0x58, 0x08, 0x6a, 0x55, 0x16, 0xae, 0x0f, 0x78, 0x7e, 0x52, 0x15, 0x11, 0x78, 0x07, 0x68, 0x0e, 
+        0x87, 0x77, 0x06, 0x08, 0x16, 0x4b, 0x00, 0x46, 0x00, 0x00, 0x08, 0x16, 0x68, 0x0c, 0x50, 0x90, 
+        0x74, 0x68, 0x16, 0x78, 0xa1, 0x62, 0x06, 0x03, 0x72, 0x07, 0x75, 0x90, 0x66, 0xc0, 0x62, 0xd6, 
+        0x01, 0x60, 0x60, 0x74, 0x70, 0x66, 0xc0, 0x1b, 0x66, 0xa6, 0x16, 0x04, 0x5a, 0x56, 0x50, 0x50, 
+        0xb4, 0x22, 0x21, 0x08, 0x32, 0xc0, 0x04, 0x42, 0xc0, 0x0a, 0x45, 0xbe, 0xff, 0x2d, 0x0c, 0x05, 
+        0xd3, 0xff, 0x08, 0x7e, 0x20, 0x2f, 0xc0, 0x22, 0x5e, 0x08, 0xd2, 0x00, 0x04, 0xd0, 0xd0, 0x34, 
+        0xd2, 0x40, 0x04, 0xa8, 0x7e, 0x92, 0x0a, 0x05, 0xb2, 0xa0, 0xc0, 0xb0, 0x99, 0x10, 0x92, 0x4a, 
+        0x05, 0x98, 0x7e, 0xa1, 0x7c, 0xf3, 0x82, 0x09, 0x06, 0xb2, 0x09, 0x05, 0x80, 0x88, 0x11, 0xb0, 
+        0x88, 0x20, 0xa0, 0x88, 0x10, 0x82, 0x49, 0x05, 0x80, 0x88, 0x41, 0x82, 0x49, 0x06, 0x38, 0x7e, 
+        0x28, 0x5e, 0x78, 0x03, 0x81, 0x89, 0xff, 0x70, 0x60, 0x54, 0x70, 0x76, 0x41, 0x80, 0x77, 0x20, 
+        0xa0, 0x77, 0x11, 0x70, 0x66, 0x20, 0x69, 0x03, 0x05, 0x0a, 0x02, 0x38, 0x7e, 0x32, 0x03, 0x08, 
+        0xf6, 0xb3, 0x11, 0x21, 0xb2, 0xfb, 0x31, 0xb2, 0xfb, 0x42, 0xa4, 0xb6, 0x01, 0xa9, 0xd9, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0xe0, 0x2e, 0x20, 0x85, 0xf7, 0x00, 0xa2, 0xa0, 0x40, 0x92, 0x2c, 
+        0x01, 0xc0, 0x20, 0x00, 0x82, 0x09, 0x03, 0xb2, 0xa0, 0xbf, 0xb0, 0x88, 0x10, 0xa0, 0x88, 0x20, 
+        0xc0, 0x20, 0x00, 0x0c, 0x14, 0x82, 0x49, 0x03, 0x72, 0x21, 0x11, 0x51, 0xec, 0xfb, 0x62, 0x21, 
+        0x10, 0x58, 0x05, 0xb0, 0x66, 0x11, 0x5a, 0x77, 0xe9, 0xb7, 0x6a, 0x55, 0x42, 0x45, 0x21, 0x06, 
+        0x02, 0x00, 0x2d, 0x0e, 0x0c, 0x0c, 0xc9, 0xb5, 0x85, 0xca, 0xff, 0x08, 0xb1, 0xc8, 0xc1, 0xd8, 
+        0xd1, 0x2d, 0x0e, 0xf8, 0xf1, 0xe8, 0xe1, 0x12, 0xc1, 0x50, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 
+        0x21, 0x9c, 0x32, 0x26, 0x32, 0x11, 0xb6, 0x32, 0x09, 0x0c, 0x10, 0xb6, 0x62, 0x0c, 0x0c, 0x00, 
+        0xc6, 0x01, 0x00, 0x0c, 0x30, 0x86, 0x00, 0x00, 0x02, 0xa0, 0x02, 0x41, 0xd8, 0xfb, 0x00, 0x30, 
+        0x74, 0x42, 0x24, 0x00, 0x39, 0x01, 0x40, 0x33, 0xa0, 0x32, 0x23, 0x86, 0x78, 0x73, 0x62, 0x07, 
+        0x05, 0x82, 0xa0, 0xc0, 0x80, 0x66, 0x10, 0x62, 0x47, 0x05, 0x68, 0x73, 0x71, 0x42, 0xf3, 0x52, 
+        0x06, 0x06, 0x82, 0x06, 0x05, 0x80, 0x55, 0x11, 0x80, 0x55, 0x20, 0x70, 0x55, 0x10, 0x52, 0x46, 
+        0x05, 0x50, 0x58, 0x41, 0x52, 0x46, 0x06, 0x58, 0x73, 0x42, 0x05, 0x04, 0x39, 0x11, 0x40, 0x40, 
+        0x34, 0x42, 0x45, 0x04, 0x28, 0x53, 0x38, 0x73, 0xc5, 0x02, 0x02, 0x41, 0x74, 0xfe, 0x38, 0x01, 
+        0x28, 0x11, 0x30, 0x33, 0xb0, 0x58, 0x02, 0x40, 0x33, 0xa0, 0x32, 0xc3, 0x10, 0x39, 0x15, 0x62, 
+        0x12, 0x08, 0x32, 0xa0, 0x80, 0xc0, 0x20, 0x00, 0x02, 0x05, 0x03, 0x00, 0x00, 0x64, 0x30, 0x00, 
+        0x20, 0xc0, 0x20, 0x00, 0x02, 0x45, 0x03, 0xb2, 0xa0, 0xbf, 0x4c, 0x0a, 0xc0, 0x20, 0x00, 0x92, 
+        0x05, 0x03, 0xb0, 0x99, 0x10, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x45, 0x03, 0x82, 0xa0, 
+        0xdf, 0xc0, 0x20, 0x00, 0x72, 0x05, 0x03, 0x80, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x72, 0x45, 0x03, 
+        0x60, 0x60, 0xb4, 0x40, 0x66, 0x11, 0x71, 0xcb, 0xdb, 0xc0, 0x20, 0x00, 0x42, 0x15, 0x01, 0x00, 
+        0x44, 0x11, 0xc0, 0x20, 0x00, 0x82, 0x15, 0x00, 0x80, 0x44, 0x20, 0x70, 0x44, 0x10, 0x60, 0x44, 
+        0x20, 0xc0, 0x20, 0x00, 0x42, 0x55, 0x00, 0x40, 0x40, 0xf5, 0xc0, 0x20, 0x00, 0x38, 0x72, 0x42, 
+        0x55, 0x01, 0x32, 0x03, 0x06, 0x30, 0x34, 0x24, 0x45, 0xf8, 0xfc, 0x08, 0x21, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x41, 0x9e, 0xfb, 0x48, 0x04, 0xb0, 0x52, 0x11, 0x5a, 0x44, 0x32, 0x44, 
+        0x20, 0x0d, 0xf0, 0x00, 0x81, 0x9a, 0xfb, 0x88, 0x08, 0xb0, 0x92, 0x11, 0x9a, 0x88, 0x32, 0x58, 
+        0x11, 0x59, 0xc8, 0x72, 0x08, 0x20, 0x49, 0xd8, 0x6a, 0x77, 0x72, 0x48, 0x20, 0x0d, 0xf0, 0x00, 
+        0x84, 0x8d, 0xfe, 0x3f, 0x32, 0xa0, 0xa0, 0x30, 0x11, 0xc0, 0xd2, 0x61, 0x1e, 0x02, 0x61, 0x1c, 
+        0xc2, 0x61, 0x1d, 0xf2, 0x61, 0x20, 0xf1, 0x8d, 0xfb, 0xe2, 0x61, 0x1f, 0xe8, 0x0f, 0xb0, 0xc2, 
+        0x11, 0xca, 0xee, 0xe2, 0x0e, 0x24, 0x22, 0x61, 0x1a, 0x9c, 0x3e, 0x26, 0x3e, 0x11, 0xb6, 0x3e, 
+        0x09, 0x0c, 0x12, 0xb6, 0x6e, 0x0c, 0x0c, 0x02, 0xc6, 0x01, 0x00, 0x0c, 0x32, 0x86, 0x00, 0x00, 
+        0x22, 0xa0, 0x02, 0x05, 0x29, 0xfc, 0x02, 0x2f, 0x00, 0x20, 0x62, 0x20, 0xca, 0x00, 0x32, 0x00, 
+        0x21, 0xd8, 0xb0, 0xdc, 0x03, 0x21, 0x35, 0xfb, 0x31, 0x36, 0xfb, 0x42, 0xa5, 0x58, 0x01, 0x2c, 
+        0xd9, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0xdc, 0x0d, 0x21, 0x30, 0xfb, 0x31, 0x31, 0xfb, 0x42, 
+        0xa5, 0x5a, 0x01, 0x27, 0xd9, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x2d, 0x01, 0x38, 0x7d, 0x1c, 
+        0x84, 0x62, 0x61, 0x1b, 0x01, 0x5e, 0xdc, 0xc0, 0x00, 0x00, 0x32, 0xc1, 0x18, 0x52, 0xc1, 0x38, 
+        0x91, 0xe1, 0xf2, 0x5b, 0x81, 0xb2, 0xa0, 0xc0, 0xa2, 0x01, 0x05, 0x0c, 0x5f, 0xf2, 0x41, 0x0f, 
+        0xb0, 0xaa, 0x10, 0xa2, 0x41, 0x05, 0x72, 0x08, 0x01, 0xa2, 0x08, 0x00, 0x80, 0x77, 0x11, 0xa0, 
+        0x77, 0x20, 0x90, 0x77, 0x10, 0x72, 0x48, 0x00, 0x70, 0x78, 0x41, 0x72, 0x48, 0x01, 0xf2, 0x1d, 
+        0x08, 0x28, 0x7d, 0x48, 0x0d, 0x68, 0x5d, 0x62, 0x61, 0x13, 0x59, 0x13, 0x49, 0x25, 0xd9, 0x63, 
+        0x22, 0x02, 0x04, 0xf2, 0x61, 0x15, 0x20, 0x24, 0x41, 0x22, 0x61, 0x14, 0x01, 0xda, 0xdc, 0xc0, 
+        0x00, 0x00, 0x01, 0x5a, 0xfb, 0x08, 0x00, 0xca, 0x00, 0x28, 0xc0, 0x38, 0xd0, 0x42, 0x10, 0x11, 
+        0x42, 0x61, 0x12, 0x32, 0x61, 0x17, 0x22, 0x61, 0x18, 0x02, 0x00, 0x20, 0x02, 0x61, 0x16, 0x01, 
+        0xd2, 0xdc, 0xc0, 0x00, 0x00, 0xc2, 0x61, 0x11, 0x92, 0x21, 0x12, 0x0c, 0x06, 0x0c, 0x07, 0x82, 
+        0xc1, 0x18, 0x82, 0x61, 0x25, 0x72, 0x61, 0x19, 0x62, 0x61, 0x24, 0x90, 0x90, 0x74, 0x92, 0x61, 
+        0x21, 0xc2, 0x21, 0x25, 0x21, 0xbc, 0xf2, 0xc8, 0x6c, 0x5b, 0x31, 0x16, 0x2c, 0x15, 0x42, 0x03, 
+        0x01, 0x52, 0x03, 0x00, 0x80, 0x44, 0x11, 0x50, 0x44, 0x20, 0x20, 0x24, 0x10, 0x40, 0x46, 0x54, 
+        0x1b, 0x44, 0x40, 0x40, 0x54, 0xa0, 0x44, 0x11, 0x40, 0x22, 0x20, 0x22, 0x43, 0x00, 0x20, 0x28, 
+        0x41, 0x22, 0x43, 0x01, 0x08, 0x0c, 0x08, 0x10, 0x22, 0x21, 0x21, 0x02, 0x00, 0x03, 0x2c, 0x05, 
+        0x20, 0x00, 0xc0, 0x02, 0xd0, 0x01, 0x00, 0x00, 0x74, 0xe6, 0xd0, 0x3c, 0x07, 0x25, 0x2a, 0x00, 
+        0x00, 0x40, 0x02, 0x21, 0x17, 0x00, 0x00, 0x91, 0x07, 0x60, 0x2d, 0x22, 0xa0, 0xc0, 0x32, 0x01, 
+        0x05, 0x0c, 0x14, 0x42, 0x61, 0x23, 0x20, 0x23, 0x10, 0x30, 0x30, 0x54, 0x1b, 0x33, 0x30, 0x30, 
+        0x54, 0x30, 0x22, 0x20, 0x22, 0x41, 0x05, 0x46, 0x07, 0x00, 0x22, 0xc0, 0xe0, 0x02, 0x21, 0x18, 
+        0x00, 0x02, 0x40, 0x00, 0x00, 0x91, 0x86, 0xf3, 0xff, 0xc0, 0x2c, 0x20, 0x05, 0x7e, 0xfc, 0x16, 
+        0x32, 0x0a, 0x32, 0xa0, 0x00, 0x32, 0x61, 0x23, 0x42, 0x2c, 0x06, 0xcc, 0xa4, 0x2d, 0x0c, 0x05, 
+        0x97, 0xff, 0xfa, 0xf2, 0x0c, 0x15, 0x52, 0x61, 0x19, 0x22, 0x2c, 0x00, 0x22, 0x22, 0x01, 0x22, 
+        0x61, 0x22, 0x22, 0x12, 0x00, 0x32, 0xa0, 0x04, 0x20, 0x20, 0xb4, 0x01, 0xa4, 0xfe, 0xc0, 0x00, 
+        0x00, 0x0c, 0x07, 0x68, 0x7c, 0x32, 0x21, 0x22, 0x92, 0x21, 0x25, 0xa8, 0x1c, 0x08, 0x19, 0xb8, 
+        0x2a, 0x42, 0x03, 0x01, 0x88, 0x06, 0x32, 0x03, 0x02, 0x80, 0x50, 0x54, 0x80, 0x86, 0x41, 0x80, 
+        0x33, 0x11, 0x40, 0x33, 0x20, 0xb9, 0x20, 0x30, 0x34, 0x64, 0x1b, 0x33, 0x79, 0x2a, 0x20, 0x33, 
+        0xa0, 0xa1, 0x1e, 0xee, 0x30, 0xff, 0xc0, 0xa0, 0x88, 0x20, 0xa0, 0x88, 0x11, 0x80, 0x55, 0x20, 
+        0x88, 0x6c, 0x89, 0x69, 0x79, 0x6c, 0x59, 0x06, 0x01, 0x87, 0xdc, 0xc0, 0x00, 0x00, 0x42, 0x21, 
+        0x23, 0x8c, 0xb4, 0x3d, 0x0c, 0x22, 0x21, 0x1b, 0x0c, 0x04, 0x85, 0x0b, 0xfc, 0x46, 0x02, 0x00, 
+        0x3d, 0x0c, 0x22, 0x21, 0x1b, 0x0c, 0x04, 0x85, 0x09, 0xfc, 0x01, 0x7f, 0xdc, 0xc0, 0x00, 0x00, 
+        0x46, 0xb3, 0xff, 0x00, 0x00, 0x00, 0xc2, 0x61, 0x24, 0x58, 0x7c, 0x22, 0x21, 0x25, 0x58, 0x05, 
+        0x08, 0x0c, 0x87, 0x75, 0x06, 0x08, 0x10, 0x4b, 0x00, 0x46, 0x00, 0x00, 0x08, 0x10, 0x32, 0x00, 
+        0x01, 0x0c, 0x84, 0x40, 0x33, 0x20, 0x32, 0x40, 0x01, 0x28, 0x62, 0x22, 0x61, 0x25, 0xc6, 0xa7, 
+        0xff, 0x62, 0x21, 0x19, 0x8c, 0xa6, 0x72, 0x21, 0x24, 0x8c, 0x57, 0x2d, 0x07, 0x05, 0x8a, 0xff, 
+        0xfa, 0xf2, 0x82, 0x21, 0x16, 0xcc, 0xb8, 0x0c, 0x1a, 0xa2, 0x41, 0x0f, 0x98, 0x7d, 0x92, 0x09, 
+        0x09, 0x92, 0x41, 0x09, 0xd2, 0x21, 0x14, 0xc2, 0x21, 0x13, 0x10, 0x31, 0x20, 0x2d, 0x0c, 0x05, 
+        0xe4, 0xfc, 0x2d, 0x0c, 0x3d, 0x01, 0x42, 0x21, 0x15, 0xb2, 0x01, 0x04, 0xd0, 0x00, 0x34, 0xc0, 
+        0x00, 0x11, 0xb0, 0xb0, 0x34, 0x00, 0xbb, 0x20, 0xb2, 0x41, 0x04, 0x45, 0x64, 0x01, 0x2d, 0x0c, 
+        0xd2, 0xc1, 0x18, 0xd8, 0x6d, 0x45, 0x4d, 0x02, 0x0c, 0x00, 0x31, 0xdc, 0xfa, 0xac, 0x82, 0x38, 
+        0x03, 0x22, 0x21, 0x11, 0x3a, 0x22, 0xd9, 0xb2, 0x16, 0x3d, 0x09, 0x58, 0x7d, 0x68, 0x05, 0x71, 
+        0x5e, 0xfe, 0x60, 0x40, 0x54, 0x60, 0x66, 0x41, 0x70, 0x66, 0x20, 0xa0, 0x66, 0x11, 0x60, 0x44, 
+        0x20, 0x49, 0x05, 0xf2, 0x5d, 0x08, 0x46, 0x1d, 0x00, 0x16, 0x9d, 0x06, 0x82, 0x21, 0x11, 0x78, 
+        0x03, 0x8a, 0x77, 0x78, 0xb7, 0xd7, 0x97, 0x12, 0x01, 0x4b, 0xdc, 0xc0, 0x00, 0x00, 0x2d, 0x0d, 
+        0x05, 0x84, 0xff, 0x01, 0x49, 0xdc, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x92, 0x21, 0x24, 0xcd, 0x0d, 
+        0x97, 0x1d, 0x0b, 0xa2, 0x21, 0x24, 0xb8, 0x1c, 0xc8, 0x6c, 0x09, 0x2b, 0xa7, 0x9c, 0xf3, 0x01, 
+        0x41, 0xdc, 0xc0, 0x00, 0x00, 0x01, 0xc1, 0xfa, 0x22, 0x21, 0x11, 0x08, 0x00, 0xf2, 0x21, 0x24, 
+        0x2a, 0x00, 0xc8, 0x60, 0xc9, 0x6f, 0xcc, 0x6c, 0x22, 0x21, 0x24, 0x22, 0xc2, 0x18, 0x29, 0x70, 
+        0xd9, 0x60, 0x01, 0x39, 0xdc, 0xc0, 0x00, 0x00, 0x21, 0x26, 0xff, 0x01, 0x69, 0xd8, 0xc0, 0x00, 
+        0x00, 0x0c, 0x00, 0x31, 0xb6, 0xfa, 0x42, 0x21, 0x11, 0x38, 0x03, 0x3a, 0x44, 0x09, 0xb4, 0x52, 
+        0x21, 0x1a, 0xb0, 0x55, 0x11, 0x5a, 0x53, 0x02, 0x45, 0x20, 0x02, 0x45, 0x21, 0x9c, 0x3e, 0x26, 
+        0x3e, 0x11, 0xb6, 0x3e, 0x09, 0x0c, 0x12, 0xb6, 0x6e, 0x0b, 0x0c, 0x02, 0x86, 0x01, 0x00, 0x0c, 
+        0x32, 0x46, 0x00, 0x00, 0x0c, 0x22, 0x45, 0xfa, 0xfe, 0xc2, 0x21, 0x1d, 0xd2, 0x21, 0x1e, 0xe2, 
+        0x21, 0x1f, 0xf2, 0x21, 0x20, 0x32, 0xa0, 0xa0, 0x02, 0x21, 0x1c, 0x3a, 0x11, 0x0d, 0xf0, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xdc, 0x02, 0x21, 0x59, 0xfa, 0x31, 0x59, 0xfa, 0x42, 0xa5, 0xd2, 
+        0x01, 0x50, 0xd8, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x31, 0x9c, 0xfa, 0x02, 0xc2, 0x18, 0x38, 
+        0x03, 0x0c, 0x05, 0x42, 0x23, 0x8f, 0x59, 0x62, 0x29, 0x04, 0x02, 0x63, 0x8f, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0x01, 0x12, 0xdc, 0xc0, 0x00, 
+        0x00, 0x01, 0x92, 0xfa, 0x08, 0x00, 0xc2, 0x20, 0x8e, 0x9c, 0x1c, 0x0c, 0x04, 0x28, 0x6c, 0x22, 
+        0x60, 0x8e, 0xcc, 0x62, 0x32, 0xa2, 0x38, 0x3a, 0x30, 0x32, 0x60, 0x8f, 0x49, 0x6c, 0x01, 0x0a, 
+        0xdc, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x08, 0x01, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x41, 0x87, 0xfa, 0x32, 0xc2, 0x18, 0x48, 0x04, 0x0c, 0x06, 0x52, 0x24, 0x91, 0x69, 0x62, 0x29, 
+        0x05, 0x32, 0x64, 0x91, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0x01, 
+        0xfd, 0xdb, 0xc0, 0x00, 0x00, 0x01, 0x7d, 0xfa, 0x08, 0x00, 0xc2, 0x20, 0x90, 0x9c, 0x1c, 0x0c, 
+        0x04, 0x28, 0x6c, 0x22, 0x60, 0x90, 0xcc, 0x62, 0x32, 0xa2, 0x40, 0x3a, 0x30, 0x32, 0x60, 0x91, 
+        0x49, 0x6c, 0x01, 0xf5, 0xdb, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x08, 0x01, 0xc8, 0x11, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x94, 0x88, 0x10, 0x40, 0x80, 0x2a, 0xff, 0x3f, 0x98, 0x8e, 0x10, 0x40, 
+        0xd8, 0x87, 0x10, 0x40, 0x0c, 0x05, 0x0c, 0x16, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xd9, 
+        0x21, 0xd1, 0x6a, 0xfa, 0x0c, 0x00, 0x28, 0x0d, 0xb0, 0x30, 0x11, 0x1b, 0x00, 0x3a, 0x32, 0x59, 
+        0x63, 0x52, 0x43, 0x27, 0x00, 0x00, 0x74, 0x42, 0xc3, 0x18, 0x49, 0x73, 0x66, 0xb0, 0xe8, 0x0c, 
+        0x00, 0x0c, 0x74, 0xb0, 0x30, 0x11, 0x1b, 0x00, 0x3a, 0x32, 0x62, 0x43, 0x27, 0x42, 0x43, 0x24, 
+        0x00, 0x00, 0x74, 0x66, 0x20, 0xec, 0x59, 0x02, 0x0c, 0x00, 0x00, 0x60, 0xf0, 0x20, 0x40, 0xa0, 
+        0x59, 0x14, 0xf0, 0x66, 0x11, 0x2a, 0x40, 0x3b, 0x36, 0x60, 0x36, 0xb3, 0x1b, 0x00, 0x00, 0x00, 
+        0x74, 0x30, 0x32, 0x21, 0x2b, 0x33, 0x32, 0x44, 0x14, 0x66, 0x40, 0xdd, 0x0c, 0x00, 0x62, 0xa2, 
+        0x28, 0x20, 0x30, 0xb0, 0x52, 0x63, 0x8a, 0x02, 0xc0, 0x01, 0x60, 0x43, 0x80, 0x42, 0x63, 0x8b, 
+        0x00, 0x00, 0x74, 0x66, 0x20, 0xea, 0x52, 0x62, 0x8e, 0x52, 0x62, 0x90, 0x62, 0xa2, 0x38, 0x60, 
+        0x62, 0x80, 0x62, 0x62, 0x8f, 0x52, 0xa2, 0x40, 0x5a, 0x52, 0x52, 0x62, 0x91, 0xc5, 0x3a, 0xfb, 
+        0x0c, 0x0c, 0x2d, 0x0c, 0xc5, 0x3d, 0xff, 0x08, 0x0d, 0x00, 0x0c, 0xa0, 0x22, 0x60, 0x86, 0x1b, 
+        0xcc, 0xc0, 0xc0, 0x74, 0x66, 0x4c, 0xea, 0x21, 0xcf, 0xff, 0x2c, 0x03, 0x41, 0xcf, 0xff, 0x1c, 
+        0x05, 0x01, 0x77, 0xf8, 0xc0, 0x00, 0x00, 0x21, 0x1f, 0xfb, 0x31, 0xcc, 0xff, 0x0c, 0x04, 0x01, 
+        0xc3, 0xdb, 0xc0, 0x00, 0x00, 0x31, 0xca, 0xff, 0xc1, 0xca, 0xf9, 0x0c, 0x04, 0x2d, 0x0c, 0x01, 
+        0xbf, 0xdb, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x01, 0xbc, 0xdb, 0xc0, 0x00, 0x00, 0x85, 0x6f, 0xfe, 
+        0x2d, 0x0c, 0x32, 0xa0, 0x64, 0x0c, 0x14, 0x01, 0xba, 0xdb, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0xd8, 
+        0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0xd9, 0x31, 0xc9, 0x21, 0xc1, 
+        0x2b, 0xfa, 0x09, 0x11, 0x08, 0x0c, 0xb0, 0xd2, 0x11, 0xda, 0x00, 0x02, 0x00, 0x24, 0x9c, 0x30, 
+        0x26, 0x30, 0x11, 0xb6, 0x30, 0x09, 0x0c, 0x12, 0xb6, 0x60, 0x0c, 0x0c, 0x02, 0xc6, 0x01, 0x00, 
+        0x0c, 0x32, 0x86, 0x00, 0x00, 0x22, 0xa0, 0x02, 0x85, 0xd0, 0xfb, 0x52, 0x2c, 0x00, 0x20, 0x02, 
+        0x20, 0xda, 0x55, 0x62, 0x05, 0x21, 0x0c, 0x0c, 0xcc, 0x96, 0x28, 0xb5, 0x8c, 0x32, 0xcd, 0x02, 
+        0x46, 0x00, 0x00, 0x8c, 0xb6, 0x08, 0x11, 0x2d, 0x0c, 0xd8, 0x31, 0xc8, 0x21, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x09, 0x01, 0xc8, 0x65, 0x0c, 0x00, 0x16, 0x9c, 0xfe, 0x68, 0x6c, 0x69, 0x65, 0xcc, 
+        0x36, 0x72, 0xc5, 0x18, 0x79, 0x75, 0xc0, 0x2c, 0x20, 0x02, 0x6c, 0x06, 0x05, 0x38, 0xfc, 0x16, 
+        0x22, 0xfd, 0x3d, 0x0c, 0x28, 0x01, 0x0c, 0x04, 0x45, 0xcc, 0xfb, 0x51, 0x0c, 0xfa, 0x58, 0x05, 
+        0xda, 0x55, 0x86, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0xc9, 0x21, 0xe9, 0x41, 0xf9, 
+        0x51, 0xd9, 0x31, 0x09, 0x11, 0xdd, 0x02, 0x85, 0x0e, 0x00, 0x01, 0x04, 0xfa, 0x0c, 0x1f, 0x08, 
+        0x00, 0xe0, 0xed, 0x11, 0x0a, 0x2d, 0x00, 0x4d, 0xa0, 0x48, 0x14, 0x22, 0x02, 0x14, 0xec, 0xfd, 
+        0x00, 0x02, 0x40, 0x40, 0x30, 0x91, 0x07, 0x63, 0x0a, 0xb0, 0x52, 0x11, 0x5a, 0x50, 0x52, 0x05, 
+        0x28, 0x26, 0x15, 0x1c, 0x0c, 0x0c, 0x29, 0x61, 0xc0, 0x20, 0x74, 0xc5, 0xf2, 0xff, 0x56, 0x32, 
+        0x06, 0x1b, 0xcc, 0x66, 0x2c, 0xf1, 0x41, 0xf5, 0xf9, 0x48, 0x04, 0x28, 0x61, 0xea, 0x44, 0x48, 
+        0x14, 0xd9, 0x01, 0x00, 0x12, 0x40, 0x00, 0xcf, 0xa1, 0x0b, 0xcc, 0xc0, 0xc4, 0x10, 0xc0, 0xe4, 
+        0x30, 0xe0, 0xd0, 0x60, 0xe0, 0xdd, 0x10, 0xd0, 0xfd, 0x40, 0xd0, 0xd0, 0x60, 0xd2, 0xcd, 0x1f, 
+        0x96, 0x0d, 0x04, 0xd0, 0x20, 0x74, 0x05, 0xef, 0xff, 0x9c, 0x52, 0x01, 0xe8, 0xf9, 0xe8, 0x01, 
+        0x08, 0x00, 0x0a, 0xee, 0xd2, 0x4e, 0x14, 0xb0, 0x3d, 0x11, 0x3a, 0x30, 0xf2, 0x43, 0x28, 0x86, 
+        0x04, 0x00, 0x7c, 0xf5, 0x00, 0x1d, 0x40, 0x00, 0x4f, 0xa1, 0x50, 0x44, 0x30, 0x40, 0xee, 0x10, 
+        0x46, 0xef, 0xff, 0x0c, 0x02, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0xc0, 0xd0, 0x60, 0xc0, 0xdd, 0x10, 0xd0, 0xfd, 0x40, 0xd0, 0xd0, 0x60, 
+        0xd2, 0xcd, 0x1f, 0x96, 0xcd, 0xfd, 0xd0, 0x20, 0x74, 0xc5, 0xe9, 0xff, 0xcc, 0xf2, 0x7c, 0xf0, 
+        0x00, 0x1d, 0x40, 0x00, 0xef, 0xa1, 0x00, 0xee, 0x30, 0xe0, 0xcc, 0x10, 0x06, 0xf5, 0xff, 0x01, 
+        0xcf, 0xf9, 0x38, 0x01, 0x08, 0x00, 0x0a, 0x33, 0xd2, 0x43, 0x14, 0x06, 0xe6, 0xff, 0x00, 0x00, 
+        0x0c, 0x19, 0x12, 0xc1, 0xf0, 0x81, 0xc9, 0xf9, 0x09, 0x21, 0x08, 0x08, 0xe0, 0x72, 0x11, 0x00, 
+        0x52, 0xa0, 0x0a, 0x42, 0x42, 0x04, 0x14, 0x38, 0x15, 0x00, 0x04, 0x40, 0x30, 0x30, 0x91, 0x07, 
+        0xe3, 0x02, 0x46, 0x20, 0x00, 0xb0, 0x64, 0x11, 0x6a, 0x60, 0xa2, 0x06, 0x28, 0x7c, 0xf8, 0x16, 
+        0x4a, 0x07, 0x0c, 0x0b, 0xa8, 0x66, 0xb2, 0x46, 0x28, 0xfc, 0xba, 0x79, 0x11, 0x49, 0x01, 0x38, 
+        0xb6, 0x29, 0x31, 0xfc, 0x13, 0x78, 0x15, 0x88, 0x01, 0x0c, 0x16, 0x00, 0x18, 0x40, 0x7c, 0xf8, 
+        0x00, 0x66, 0xa1, 0x80, 0x66, 0x30, 0x60, 0x77, 0x10, 0x79, 0x15, 0x48, 0x00, 0x0c, 0x82, 0x60, 
+        0x44, 0x10, 0x49, 0x00, 0x85, 0x45, 0x00, 0x28, 0x31, 0x48, 0x01, 0x7c, 0xf8, 0x01, 0xaf, 0xf9, 
+        0x58, 0x11, 0x08, 0x00, 0x0c, 0x19, 0x0a, 0x55, 0x58, 0x15, 0xac, 0x95, 0x00, 0x14, 0x40, 0x00, 
+        0x69, 0xa1, 0x80, 0x76, 0x30, 0x0b, 0x66, 0x60, 0x65, 0x10, 0x60, 0xa5, 0x30, 0xa0, 0x77, 0x10, 
+        0x70, 0x40, 0x60, 0x70, 0x44, 0x10, 0x40, 0xf4, 0x40, 0x40, 0x40, 0x60, 0x42, 0xc4, 0x1f, 0x96, 
+        0xb4, 0x00, 0x0a, 0x72, 0x42, 0x47, 0x14, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x60, 0x40, 
+        0x60, 0x60, 0x44, 0x10, 0x40, 0xf4, 0x40, 0x40, 0x40, 0x60, 0x42, 0xc4, 0x1f, 0xd6, 0x14, 0xfe, 
+        0xc6, 0xf8, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x0c, 0x1b, 0x0c, 0x08, 0xa1, 0x98, 0xf9, 0x12, 
+        0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 0xa8, 0x0a, 0x09, 0x01, 0xa0, 0x75, 0xa0, 0x08, 0x17, 0xd8, 
+        0x0a, 0x56, 0x10, 0x04, 0xaa, 0x95, 0x92, 0x09, 0x14, 0x00, 0x09, 0x40, 0xd0, 0xc0, 0x91, 0x07, 
+        0xec, 0x33, 0x0d, 0x09, 0x00, 0x19, 0x40, 0xb0, 0x59, 0x11, 0x5a, 0x5a, 0x42, 0x45, 0x24, 0x32, 
+        0x45, 0x25, 0x82, 0x45, 0x28, 0x22, 0x45, 0x26, 0x28, 0x17, 0x00, 0x3b, 0xa1, 0x30, 0x22, 0x20, 
+        0x29, 0x17, 0x68, 0x0a, 0x30, 0x66, 0x20, 0x69, 0x0a, 0xc8, 0x11, 0xd8, 0x21, 0x2d, 0x00, 0x08, 
+        0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x7c, 0xfc, 0x00, 0x80, 0x60, 0x00, 0x88, 0x10, 0x80, 0xf8, 
+        0x40, 0x80, 0x80, 0x60, 0x82, 0xc8, 0x1f, 0x96, 0x88, 0x02, 0xb0, 0x98, 0x11, 0x9a, 0x9a, 0x62, 
+        0x09, 0x24, 0x00, 0x18, 0x40, 0x47, 0x96, 0x0e, 0x62, 0x09, 0x25, 0x72, 0x09, 0x26, 0x37, 0x96, 
+        0x05, 0x20, 0x77, 0xc0, 0x16, 0xc7, 0x08, 0x00, 0x9b, 0xa1, 0xc0, 0x99, 0x30, 0x90, 0x00, 0x10, 
+        0x86, 0xf0, 0xff, 0xc1, 0xd8, 0xff, 0x0c, 0x38, 0xaa, 0x95, 0x92, 0x09, 0x14, 0x80, 0x8d, 0x20, 
+        0x00, 0x19, 0x40, 0xc0, 0x98, 0x30, 0x00, 0x7b, 0xa1, 0x0b, 0x77, 0x90, 0x77, 0x10, 0x00, 0xf7, 
+        0x40, 0x1c, 0xf9, 0x00, 0x09, 0xc0, 0xd6, 0x30, 0x01, 0x70, 0x08, 0x30, 0xc0, 0x00, 0x30, 0x00, 
+        0xf0, 0x40, 0x00, 0x09, 0xc0, 0xd6, 0x40, 0x00, 0x1c, 0x00, 0xc6, 0xde, 0xff, 0xa0, 0x75, 0xa0, 
+        0x00, 0x10, 0x40, 0x00, 0x8b, 0xa1, 0x0b, 0x88, 0xd0, 0x58, 0x10, 0x50, 0xf5, 0x40, 0x50, 0x69, 
+        0xc0, 0x96, 0x56, 0x03, 0x50, 0x00, 0xc0, 0x0c, 0x08, 0x62, 0xc0, 0x20, 0x02, 0xc0, 0x21, 0x60, 
+        0x06, 0xb3, 0x00, 0x01, 0x74, 0x00, 0x10, 0x40, 0xb0, 0x60, 0x11, 0x6a, 0x6a, 0x82, 0x46, 0x28, 
+        0x32, 0x46, 0x25, 0x42, 0x46, 0x24, 0x22, 0x46, 0x26, 0x28, 0x17, 0x00, 0x3b, 0xa1, 0x30, 0x22, 
+        0x20, 0xc6, 0xca, 0xff, 0x80, 0x00, 0x74, 0x86, 0xcb, 0xff, 0x7c, 0xf5, 0x50, 0x58, 0x30, 0x50, 
+        0x5d, 0x10, 0x50, 0xf5, 0x40, 0x50, 0x50, 0xc0, 0x62, 0xc5, 0x2d, 0x52, 0xc5, 0x2e, 0x60, 0x56, 
+        0xb3, 0x0c, 0x06, 0x50, 0x51, 0x21, 0x0d, 0x05, 0xa6, 0xb5, 0x02, 0x02, 0xc5, 0xf2, 0x00, 0x00, 
+        0x74, 0x00, 0x10, 0x40, 0xb0, 0x50, 0x11, 0x5a, 0x5a, 0x42, 0x45, 0x24, 0x32, 0x45, 0x25, 0x62, 
+        0x45, 0x28, 0x22, 0x45, 0x26, 0x28, 0x17, 0x00, 0x3b, 0xa1, 0x30, 0x22, 0x20, 0xc6, 0xb7, 0xff, 
+        0x12, 0xc1, 0xc0, 0xc9, 0x91, 0xd9, 0xa1, 0xf9, 0xc1, 0xe9, 0xb1, 0x09, 0x81, 0xed, 0x02, 0x01, 
+        0xb9, 0xda, 0xc0, 0x00, 0x00, 0xc1, 0x39, 0xf9, 0xc8, 0x0c, 0xc8, 0x0c, 0x01, 0xb7, 0xda, 0xc0, 
+        0x00, 0x00, 0xf1, 0x9c, 0xff, 0x0c, 0x3d, 0xd0, 0xdc, 0x20, 0xf0, 0xdd, 0x30, 0x16, 0x2d, 0x0e, 
+        0x01, 0x33, 0xf9, 0x42, 0xa2, 0x28, 0x08, 0x00, 0xd0, 0xfe, 0x11, 0x00, 0x0e, 0xb0, 0xd2, 0x20, 
+        0x8a, 0xf9, 0xd1, 0x16, 0xcd, 0x0c, 0xd9, 0x61, 0x4a, 0x40, 0x0c, 0x03, 0x32, 0x60, 0x8a, 0x42, 
+        0x60, 0x8b, 0xc6, 0x05, 0x00, 0x51, 0x29, 0xf9, 0x62, 0x21, 0x0d, 0x52, 0x25, 0x00, 0x72, 0xa0, 
+        0x00, 0x6a, 0x55, 0x62, 0x25, 0x8b, 0x79, 0x6c, 0xc9, 0x06, 0xe2, 0x65, 0x8b, 0xcd, 0x0d, 0x16, 
+        0xfd, 0x08, 0x0c, 0x0e, 0xd8, 0x6d, 0xd9, 0x61, 0xe9, 0x6c, 0x01, 0x9e, 0xda, 0xc0, 0x00, 0x00, 
+        0x38, 0x5c, 0x48, 0x7c, 0x32, 0x03, 0x76, 0x22, 0x04, 0x00, 0x52, 0x04, 0x06, 0x20, 0x21, 0x04, 
+        0x42, 0x04, 0x04, 0x50, 0x54, 0x24, 0x40, 0x40, 0x34, 0xc5, 0xdf, 0xff, 0xfd, 0x02, 0x01, 0x96, 
+        0xda, 0xc0, 0x00, 0x00, 0xe2, 0xcc, 0x18, 0x26, 0xbf, 0xaa, 0x72, 0xa0, 0xc3, 0x58, 0x7c, 0xf0, 
+        0x60, 0x34, 0x42, 0x05, 0x00, 0xe0, 0x66, 0x11, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0x42, 0x45, 
+        0x00, 0x01, 0x8c, 0xda, 0xc0, 0x00, 0x00, 0xf1, 0x0d, 0xf9, 0x88, 0x7c, 0x0c, 0x0a, 0xa9, 0x6c, 
+        0x92, 0x08, 0x00, 0x78, 0x0f, 0x90, 0x92, 0x34, 0xb0, 0x99, 0x11, 0x9a, 0x97, 0x98, 0x79, 0xc9, 
+        0x09, 0x82, 0x08, 0x00, 0x80, 0x82, 0x34, 0xb0, 0x88, 0x11, 0x8a, 0x77, 0xe9, 0x77, 0x01, 0x82, 
+        0xda, 0xc0, 0x00, 0x00, 0x28, 0x7c, 0x22, 0x02, 0x06, 0x20, 0x24, 0x24, 0x05, 0x19, 0x00, 0x86, 
+        0xda, 0xff, 0x0c, 0x12, 0xc8, 0x91, 0xd8, 0xa1, 0xe8, 0xb1, 0xf8, 0xc1, 0x08, 0x81, 0x12, 0xc1, 
+        0x40, 0x0d, 0xf0, 0x0c, 0x02, 0xc6, 0xfa, 0xff, 0x01, 0x2b, 0xff, 0x3f, 0x12, 0xc1, 0xe0, 0x02, 
+        0x61, 0x00, 0xe2, 0x61, 0x03, 0xc2, 0x61, 0x01, 0xd9, 0x21, 0xf9, 0x41, 0xf1, 0xfb, 0xff, 0x7c, 
+        0xfd, 0xc2, 0x0f, 0x00, 0x0c, 0x0e, 0x2d, 0x0c, 0x85, 0x0b, 0xfe, 0x8c, 0x62, 0x2d, 0x0c, 0x05, 
+        0xec, 0xff, 0x20, 0xdc, 0x93, 0x02, 0x0f, 0x00, 0x1b, 0xcc, 0xc0, 0xc0, 0x74, 0x22, 0xcc, 0xfe, 
+        0x20, 0xce, 0x83, 0xc7, 0x90, 0xdf, 0xc8, 0x11, 0x26, 0x0d, 0x0c, 0x1b, 0x0d, 0x00, 0x20, 0x74, 
+        0x26, 0x22, 0x01, 0xed, 0x00, 0xe2, 0x4f, 0x00, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 
+        0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 
+        0x02, 0x28, 0x72, 0x09, 0x01, 0x28, 0x02, 0x08, 0x0c, 0x87, 0x72, 0x06, 0xd8, 0x10, 0x4b, 0xdd, 
+        0x46, 0x00, 0x00, 0xd8, 0x10, 0x45, 0xf8, 0xff, 0x0c, 0x78, 0x72, 0xa0, 0xf0, 0x02, 0xa0, 0xc3, 
+        0x58, 0x7c, 0x62, 0xa0, 0x8f, 0x42, 0x05, 0x00, 0x38, 0x5c, 0x40, 0x21, 0x04, 0xfc, 0x03, 0xe0, 
+        0xd2, 0x11, 0x00, 0xb4, 0x10, 0xd0, 0xbb, 0x20, 0xb2, 0x45, 0x00, 0xb8, 0x7c, 0xa2, 0x0b, 0x06, 
+        0x60, 0xaa, 0x10, 0xa2, 0x4b, 0x06, 0xa8, 0x7c, 0x92, 0x0a, 0x04, 0x70, 0x99, 0x10, 0x80, 0x99, 
+        0x20, 0x92, 0x4a, 0x04, 0x0c, 0x02, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x32, 0x0d, 0x00, 0xe0, 0xd2, 0x11, 0x30, 0x32, 0x14, 0xec, 0x33, 0x00, 0xb4, 0x10, 0xd0, 
+        0xbb, 0x20, 0xb2, 0x45, 0x00, 0xb8, 0x7c, 0xa2, 0x0b, 0x06, 0x60, 0xaa, 0x10, 0xa2, 0x4b, 0x06, 
+        0xa8, 0x7c, 0x92, 0x0a, 0x04, 0x70, 0x99, 0x10, 0x80, 0x99, 0x20, 0x92, 0x4a, 0x04, 0x86, 0xf0, 
+        0xff, 0x05, 0xfe, 0xfd, 0x56, 0x12, 0x01, 0x02, 0x2c, 0x07, 0x08, 0x00, 0x37, 0x70, 0x09, 0x0c, 
+        0x12, 0x45, 0x02, 0xfe, 0x0c, 0x12, 0x06, 0xeb, 0xff, 0x01, 0x32, 0xda, 0xc0, 0x00, 0x00, 0x38, 
+        0x5c, 0x48, 0x7c, 0x32, 0x03, 0x76, 0x22, 0x04, 0x00, 0x52, 0x04, 0x06, 0x20, 0x21, 0x04, 0x42, 
+        0x04, 0x04, 0x50, 0x54, 0x24, 0x40, 0x40, 0x34, 0xc5, 0xc4, 0xff, 0xdd, 0x02, 0x01, 0x2a, 0xda, 
+        0xc0, 0x00, 0x00, 0x26, 0xbd, 0xcd, 0x72, 0xa0, 0xc3, 0x58, 0x7c, 0xd0, 0x60, 0x34, 0x42, 0x05, 
+        0x00, 0xe0, 0x66, 0x11, 0x70, 0x44, 0x10, 0x60, 0x44, 0x20, 0x42, 0x45, 0x00, 0xc6, 0xd8, 0xff, 
+        0x0c, 0x04, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x38, 0x72, 0x0c, 0x40, 0x42, 0x43, 0x0e, 0x02, 0x43, 
+        0x0f, 0xc5, 0x7e, 0xff, 0x0c, 0x42, 0x85, 0x00, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0x01, 0x16, 0xda, 0xc0, 0x00, 0x00, 0x21, 
+        0x4e, 0xf8, 0x2a, 0x2c, 0x02, 0x02, 0x00, 0x8c, 0x90, 0x01, 0x13, 0xda, 0xc0, 0x00, 0x00, 0x0c, 
+        0x02, 0x86, 0x05, 0x00, 0x1b, 0x30, 0x32, 0x42, 0x00, 0x01, 0x0f, 0xda, 0xc0, 0x00, 0x00, 0x3d, 
+        0x0c, 0x2c, 0x02, 0x0c, 0x04, 0x01, 0xc0, 0xed, 0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x08, 0x72, 0x58, 0x52, 0x02, 0x00, 0x0d, 
+        0xa2, 0x12, 0x08, 0x00, 0x00, 0x34, 0x8c, 0xd0, 0x26, 0x10, 0x10, 0x32, 0xc0, 0xfe, 0x16, 0x83, 
+        0x0c, 0x42, 0xc0, 0xfd, 0x16, 0x84, 0x12, 0x0c, 0x40, 0x46, 0x00, 0x00, 0x0c, 0x80, 0x0a, 0xaa, 
+        0xa2, 0x52, 0x08, 0xb1, 0x9b, 0xd8, 0x88, 0x12, 0xc0, 0x20, 0x00, 0x92, 0x18, 0x01, 0x00, 0x99, 
+        0x11, 0xc0, 0x20, 0x00, 0x32, 0x18, 0x00, 0xa1, 0x97, 0xd8, 0x30, 0x99, 0x20, 0xb0, 0x99, 0x10, 
+        0x90, 0x9c, 0x41, 0x0a, 0x99, 0x90, 0x90, 0xb4, 0x40, 0x99, 0x11, 0xc0, 0x20, 0x00, 0x72, 0x18, 
+        0x01, 0x00, 0x77, 0x11, 0xc0, 0x20, 0x00, 0xb2, 0x18, 0x00, 0xb0, 0x77, 0x20, 0xa0, 0x77, 0x10, 
+        0x90, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x58, 0x00, 0x70, 0x70, 0xf5, 0xc0, 0x20, 0x00, 0x68, 
+        0x72, 0x4c, 0x03, 0x68, 0x06, 0x72, 0x58, 0x01, 0x87, 0x76, 0x06, 0xec, 0x35, 0x0c, 0x12, 0x06, 
+        0x06, 0x00, 0x42, 0xa0, 0xbf, 0x08, 0x12, 0xc0, 0x20, 0x00, 0xb2, 0x00, 0x03, 0x40, 0xbb, 0x10, 
+        0x30, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x40, 0x03, 0x0c, 0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x2c, 0x06, 0x72, 0xa0, 0xdf, 0x48, 0x02, 0xc0, 0x20, 0x00, 0x32, 0x04, 0x03, 0x70, 
+        0x33, 0x10, 0x60, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x44, 0x03, 0x08, 0x72, 0x02, 0x00, 0x0d, 
+        0x00, 0x00, 0x34, 0x26, 0x30, 0x18, 0x9c, 0x50, 0x21, 0x0d, 0xf8, 0x31, 0x0d, 0xf8, 0x42, 0xa7, 
+        0xbf, 0x01, 0x03, 0xd6, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x1c, 0x00, 0x86, 0xcf, 0xff, 0x41, 
+        0x93, 0xfb, 0x32, 0x12, 0x08, 0x28, 0x02, 0x4a, 0x33, 0x28, 0x12, 0x41, 0xed, 0xea, 0x02, 0x12, 
+        0x00, 0x30, 0x30, 0xb4, 0x40, 0x00, 0x10, 0x30, 0x00, 0x20, 0x32, 0x02, 0x02, 0x02, 0x52, 0x00, 
+        0x52, 0x05, 0x74, 0x62, 0x02, 0x01, 0x00, 0x00, 0xb4, 0x4b, 0x80, 0x80, 0x33, 0x11, 0x60, 0x33, 
+        0x20, 0x87, 0x25, 0x08, 0x00, 0x05, 0xc0, 0x00, 0x02, 0x21, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x51, 
+        0xf0, 0xfa, 0x00, 0x40, 0x64, 0xc0, 0x44, 0x11, 0x50, 0x33, 0x10, 0x40, 0x33, 0x20, 0x32, 0x42, 
+        0x01, 0x42, 0xa0, 0xcf, 0x30, 0x38, 0x74, 0x40, 0x33, 0x10, 0x32, 0x42, 0x02, 0x06, 0xd6, 0xff, 
+        0x0c, 0xc0, 0x06, 0xb6, 0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x31, 0x09, 0x21, 0xcd, 
+        0x03, 0x01, 0x32, 0xf8, 0x3d, 0x04, 0x39, 0x01, 0x08, 0x00, 0xb0, 0x42, 0x11, 0x4a, 0x00, 0x02, 
+        0x00, 0x27, 0x49, 0x11, 0x56, 0x50, 0x04, 0x01, 0xab, 0xd9, 0xc0, 0x00, 0x00, 0x01, 0x2b, 0xf8, 
+        0x28, 0x11, 0x08, 0x00, 0x2a, 0x00, 0x08, 0x60, 0xac, 0xb0, 0x68, 0x70, 0x28, 0x06, 0x87, 0xf2, 
+        0x25, 0x22, 0x16, 0x05, 0x38, 0x01, 0xca, 0xc2, 0xc0, 0xc0, 0xf4, 0xdc, 0x00, 0x21, 0xdb, 0xf7, 
+        0x31, 0xdc, 0xf7, 0x42, 0xa7, 0xd6, 0x01, 0xd2, 0xd5, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x37, 
+        0xbc, 0x15, 0x08, 0x60, 0x56, 0x20, 0xfd, 0x01, 0x9c, 0xd9, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x08, 
+        0x21, 0xc8, 0x31, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x01, 0x98, 0xd9, 0xc0, 0x00, 0x00, 0xc8, 0x01, 
+        0x46, 0xfa, 0xff, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x02, 0x61, 0x00, 0x02, 0x22, 0x07, 
+        0xcd, 0x02, 0x28, 0x00, 0x97, 0x72, 0x0a, 0x22, 0x00, 0x08, 0x05, 0x47, 0x00, 0x08, 0x7c, 0x86, 
+        0x05, 0x00, 0x07, 0xf2, 0x10, 0x77, 0xe2, 0x0d, 0x22, 0x00, 0x08, 0x45, 0x41, 0x00, 0x08, 0x7c, 
+        0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa0, 0x00, 0x20, 0x40, 0x84, 0x32, 0x10, 0x03, 0x22, 
+        0x2c, 0x07, 0x90, 0x44, 0x11, 0x30, 0x30, 0x64, 0x40, 0x33, 0x20, 0x32, 0x50, 0x03, 0x32, 0x1c, 
+        0x08, 0x42, 0x12, 0x03, 0x22, 0x02, 0x08, 0x40, 0x47, 0x41, 0x85, 0x3f, 0x00, 0x02, 0x21, 0x00, 
+        0x58, 0x7c, 0xc8, 0x11, 0x22, 0x55, 0x05, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0xe2, 
+        0x61, 0x04, 0xf2, 0x61, 0x05, 0x32, 0x61, 0x00, 0xc9, 0x21, 0xd9, 0x31, 0xcd, 0x02, 0x28, 0x72, 
+        0x09, 0x11, 0xd2, 0x02, 0x00, 0x22, 0x02, 0x06, 0xd0, 0xd2, 0x34, 0x20, 0x24, 0x24, 0x45, 0x45, 
+        0xfb, 0xfd, 0x02, 0xe1, 0x02, 0xeb, 0x0c, 0x08, 0x41, 0xf1, 0xf7, 0x0c, 0x03, 0x48, 0x04, 0xb0, 
+        0x5d, 0x11, 0x5a, 0x44, 0x39, 0xb4, 0x32, 0x44, 0x20, 0x32, 0x44, 0x21, 0x92, 0x2c, 0x01, 0x62, 
+        0x2c, 0x07, 0xd2, 0x2c, 0x06, 0x78, 0x06, 0x89, 0x6c, 0x70, 0x50, 0x54, 0x89, 0x29, 0x70, 0x76, 
+        0x41, 0xe0, 0x77, 0x20, 0xa0, 0x77, 0x11, 0x70, 0x55, 0x20, 0x59, 0x06, 0x8c, 0xad, 0x3d, 0x0c, 
+        0x2d, 0x0f, 0x0c, 0x04, 0x85, 0x41, 0xfb, 0xc6, 0x02, 0x00, 0xc0, 0x3c, 0x20, 0xf0, 0x2f, 0x20, 
+        0x42, 0x21, 0x00, 0xc5, 0x40, 0xfb, 0xcd, 0x0d, 0x0c, 0x08, 0x56, 0xed, 0xfb, 0xc8, 0x21, 0xd8, 
+        0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x09, 
+        0x11, 0x39, 0x01, 0xe9, 0x41, 0xc9, 0x21, 0xd9, 0x31, 0xf9, 0x51, 0xdd, 0x02, 0xf8, 0x72, 0xcd, 
+        0x02, 0xf2, 0x0f, 0x00, 0x0c, 0x0e, 0xf0, 0xf2, 0x34, 0x46, 0x01, 0x00, 0x28, 0x1d, 0xdd, 0x00, 
+        0xe9, 0x22, 0x08, 0x6d, 0x56, 0x40, 0xff, 0x2d, 0x0c, 0x85, 0xc4, 0xfe, 0x08, 0x01, 0x31, 0xcb, 
+        0xf7, 0xb0, 0x2f, 0x11, 0x38, 0x03, 0xb0, 0x5f, 0x11, 0x5a, 0x53, 0x3a, 0x22, 0x48, 0x62, 0x49, 
+        0x6d, 0xcc, 0x34, 0x42, 0xcd, 0x18, 0x49, 0x72, 0xe9, 0xb2, 0xc9, 0x62, 0xe2, 0x45, 0x20, 0xe2, 
+        0x45, 0x21, 0x8c, 0x90, 0x28, 0x7c, 0x22, 0x02, 0x06, 0x20, 0x24, 0x24, 0x05, 0xc9, 0xff, 0xc8, 
+        0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0xb6, 0x52, 0x13, 0xb6, 0x82, 0x09, 0x2c, 0x44, 0xf6, 0xb2, 0x07, 0x1c, 0x44, 0x86, 0x00, 0x00, 
+        0x42, 0xa0, 0x60, 0x2d, 0x04, 0x0d, 0xf0, 0x22, 0xa0, 0xc0, 0x0d, 0xf0, 0x10, 0x2b, 0xff, 0x3f, 
+        0x2e, 0xba, 0x00, 0x00, 0x17, 0x5d, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 
+        0xc7, 0x71, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xe3, 0x38, 0x00, 0x00, 0xaa, 0x2a, 0x00, 0x00, 
+        0x71, 0x1c, 0x00, 0x00, 0x55, 0x15, 0x00, 0x00, 0xf6, 0x12, 0x00, 0x00, 0x89, 0x9d, 0x00, 0x00, 
+        0xc4, 0x4e, 0x00, 0x00, 0x83, 0x34, 0x00, 0x00, 0x62, 0x27, 0x00, 0x00, 0x41, 0x1a, 0x00, 0x00, 
+        0xb1, 0x13, 0x00, 0x00, 0x81, 0x11, 0x00, 0x00, 0xc8, 0x8d, 0x00, 0x00, 0xe4, 0x46, 0x00, 0x00, 
+        0x42, 0x2f, 0x00, 0x00, 0x72, 0x23, 0x00, 0x00, 0xa1, 0x17, 0x00, 0x00, 0xb9, 0x11, 0x00, 0x00, 
+        0x2d, 0x0e, 0x00, 0x00, 0x91, 0xe7, 0xff, 0x41, 0x84, 0xd6, 0xb1, 0xbb, 0xd6, 0x71, 0xe5, 0xff, 
+        0x0c, 0x75, 0x0c, 0x36, 0x0c, 0x02, 0x0c, 0x1a, 0x31, 0xe1, 0xff, 0x0c, 0x28, 0x82, 0x43, 0x36, 
+        0x82, 0x43, 0x14, 0x82, 0x43, 0x15, 0x82, 0x43, 0x16, 0xa2, 0x43, 0x2e, 0xa2, 0x43, 0x0c, 0xa2, 
+        0x43, 0x0d, 0xa2, 0x43, 0x0e, 0x22, 0x43, 0x04, 0x22, 0x43, 0x05, 0x22, 0x43, 0x06, 0x22, 0x43, 
+        0x26, 0x62, 0x43, 0x3e, 0x62, 0x43, 0x1c, 0x62, 0x43, 0x1d, 0x62, 0x43, 0x1e, 0x52, 0x43, 0x3c, 
+        0x52, 0x43, 0x3d, 0x52, 0x43, 0x46, 0x52, 0x43, 0x66, 0x79, 0xe3, 0x79, 0x63, 0xb9, 0xa3, 0xb9, 
+        0x23, 0x49, 0x03, 0x99, 0xc3, 0x99, 0x43, 0x49, 0x83, 0x91, 0xcf, 0xff, 0x0c, 0xb4, 0x0c, 0xab, 
+        0x0c, 0x67, 0x72, 0x43, 0x34, 0x72, 0x43, 0x35, 0x72, 0x43, 0x4e, 0x72, 0x43, 0x6e, 0x72, 0x43, 
+        0x9e, 0x72, 0x43, 0xa6, 0x72, 0x43, 0xae, 0x72, 0x43, 0xb6, 0x72, 0x43, 0xbe, 0x72, 0x43, 0xde, 
+        0x72, 0x43, 0xe6, 0x72, 0x43, 0xee, 0x72, 0x43, 0xf6, 0x72, 0x43, 0xfe, 0xb2, 0x43, 0x54, 0xb2, 
+        0x43, 0x55, 0xb2, 0x43, 0x74, 0xb2, 0x43, 0x75, 0xb2, 0x43, 0x8c, 0xb2, 0x43, 0x8d, 0xb2, 0x43, 
+        0x94, 0xb2, 0x43, 0x95, 0xb2, 0x43, 0xcc, 0xb2, 0x43, 0xcd, 0xb2, 0x43, 0xd4, 0xb2, 0x43, 0xd5, 
+        0x42, 0x43, 0x5c, 0x42, 0x43, 0x5d, 0x42, 0x43, 0x7c, 0x42, 0x43, 0x7d, 0x42, 0x43, 0x84, 0x42, 
+        0x43, 0x85, 0x42, 0x43, 0xc4, 0x42, 0x43, 0xc5, 0x92, 0x63, 0x2e, 0x92, 0x63, 0x3c, 0x51, 0xb4, 
+        0xff, 0x61, 0xb2, 0xff, 0x0c, 0x42, 0x0c, 0x5a, 0x0c, 0x98, 0x82, 0x43, 0x4c, 0x82, 0x43, 0x4d, 
+        0x82, 0x43, 0x6c, 0x82, 0x43, 0x6d, 0x82, 0x43, 0x44, 0x82, 0x43, 0x45, 0x82, 0x43, 0x64, 0x82, 
+        0x43, 0x65, 0x82, 0x43, 0x9c, 0x82, 0x43, 0x9d, 0x82, 0x43, 0xa4, 0x82, 0x43, 0xa5, 0x82, 0x43, 
+        0xac, 0x82, 0x43, 0xad, 0x82, 0x43, 0xb4, 0x82, 0x43, 0xb5, 0x82, 0x43, 0xbc, 0x82, 0x43, 0xbd, 
+        0x82, 0x43, 0xdc, 0x82, 0x43, 0xdd, 0x82, 0x43, 0xe4, 0x82, 0x43, 0xe5, 0x82, 0x43, 0xec, 0x82, 
+        0x43, 0xed, 0x82, 0x43, 0xf4, 0x82, 0x43, 0xf5, 0x82, 0x43, 0xfc, 0x82, 0x43, 0xfd, 0xa2, 0x43, 
+        0x2c, 0xa2, 0x43, 0x2d, 0xa2, 0x43, 0x56, 0xa2, 0x43, 0x76, 0xa2, 0x43, 0x8e, 0xa2, 0x43, 0x96, 
+        0xa2, 0x43, 0xce, 0xa2, 0x43, 0xd6, 0x22, 0x43, 0x24, 0x22, 0x43, 0x25, 0x22, 0x43, 0x5e, 0x22, 
+        0x43, 0x7e, 0x22, 0x43, 0x86, 0x22, 0x43, 0xc6, 0x62, 0x63, 0x16, 0x52, 0x63, 0x1e, 0x91, 0x95, 
+        0xff, 0x92, 0x63, 0x10, 0x51, 0x98, 0xff, 0x61, 0x96, 0xff, 0x62, 0x63, 0x22, 0x52, 0x63, 0x24, 
+        0x91, 0x9a, 0xff, 0x92, 0x63, 0x30, 0x51, 0x9c, 0xff, 0x61, 0x9a, 0xff, 0x62, 0x63, 0x36, 0x52, 
+        0x63, 0x38, 0x21, 0x89, 0xff, 0x41, 0x87, 0xff, 0x42, 0x63, 0x14, 0x22, 0x63, 0x1c, 0x41, 0x8e, 
+        0xff, 0x21, 0x8e, 0xff, 0xa1, 0x87, 0xff, 0xa2, 0x63, 0x1a, 0x22, 0x63, 0x28, 0x42, 0x63, 0x26, 
+        0x21, 0x94, 0xff, 0xb1, 0x82, 0xff, 0x41, 0x91, 0xff, 0xa1, 0x8a, 0xff, 0xa2, 0x63, 0x2c, 0x42, 
+        0x63, 0x3a, 0xb2, 0x63, 0x12, 0x22, 0x63, 0x3e, 0xb1, 0x86, 0xff, 0x71, 0x80, 0xff, 0x72, 0x63, 
+        0x20, 0xb2, 0x63, 0x2a, 0x71, 0x87, 0xff, 0x72, 0x63, 0x34, 0x81, 0x7b, 0xff, 0x82, 0x63, 0x18, 
+        0x81, 0x83, 0xff, 0x82, 0x63, 0x32, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x02, 0xa1, 0x5f, 
+        0x07, 0xc2, 0x05, 0x05, 0xe1, 0xff, 0xc6, 0x0b, 0x00, 0x41, 0x68, 0xff, 0x0c, 0x58, 0x0c, 0x75, 
+        0x0c, 0x32, 0x0b, 0x93, 0x0c, 0x17, 0x0c, 0x06, 0x90, 0x67, 0x83, 0x60, 0x25, 0x93, 0x60, 0x78, 
+        0x93, 0x72, 0x44, 0x5c, 0x72, 0x44, 0x7c, 0x72, 0x44, 0x54, 0x22, 0x44, 0x74, 0x22, 0x44, 0x4c, 
+        0x22, 0x44, 0x6c, 0x22, 0x44, 0x44, 0x22, 0x44, 0x64, 0x0c, 0x02, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x00, 0x00, 0x31, 0x5a, 0xff, 0x30, 0x22, 0xb0, 0x22, 0x02, 0x05, 0x0d, 0xf0, 0x00, 
+        0x31, 0x57, 0xff, 0x30, 0x22, 0xb0, 0x22, 0x02, 0x04, 0x0d, 0xf0, 0x00, 0xd0, 0x80, 0xfe, 0x3f, 
+        0x31, 0x53, 0xff, 0x30, 0x22, 0xb0, 0x31, 0xfd, 0xff, 0x22, 0x02, 0x05, 0x30, 0x22, 0x90, 0x22, 
+        0x12, 0x00, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x39, 0x01, 0x49, 0x11, 0xc9, 0x31, 0x09, 0x21, 0xcd, 
+        0x02, 0xc5, 0xd0, 0xff, 0x29, 0x41, 0x38, 0x01, 0x2d, 0x0c, 0xc5, 0x05, 0x00, 0x08, 0x41, 0x38, 
+        0x11, 0x0c, 0xa4, 0x2a, 0x23, 0xb6, 0x8c, 0x01, 0x1c, 0x04, 0xc8, 0x31, 0x4a, 0x50, 0x5a, 0x22, 
+        0x08, 0x21, 0x12, 0xc1, 0x20, 0x20, 0x20, 0xf4, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x31, 0x09, 0x21, 0x01, 0x3e, 0xff, 0x0c, 0xac, 0x00, 0x02, 0xb0, 0x22, 0x00, 0x05, 0x09, 0x01, 
+        0xb6, 0x82, 0x01, 0x1c, 0x0c, 0x85, 0xcc, 0xff, 0x29, 0x11, 0x28, 0x01, 0x2c, 0x03, 0x22, 0x02, 
+        0x05, 0x45, 0x01, 0x00, 0x38, 0x11, 0x08, 0x21, 0x3a, 0x3c, 0xc8, 0x31, 0x3a, 0x22, 0x20, 0x20, 
+        0xf4, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0xd0, 0x43, 0x11, 0x51, 0x30, 0xff, 0x40, 0x30, 
+        0xf4, 0x41, 0xf0, 0xe9, 0x50, 0x52, 0xb0, 0x58, 0x05, 0xb6, 0x82, 0x05, 0x32, 0xc3, 0x16, 0x30, 
+        0x30, 0xf4, 0x30, 0x35, 0x82, 0x4a, 0x33, 0x30, 0x32, 0xd5, 0xb6, 0x82, 0x06, 0x7c, 0xc4, 0x3b, 
+        0x33, 0x40, 0x33, 0x10, 0x30, 0x20, 0xf4, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x62, 0xc0, 0x37, 
+        0x32, 0x03, 0x2d, 0x06, 0x0d, 0xf0, 0x0b, 0x26, 0x0d, 0xf0, 0x00, 0x00, 0x48, 0x12, 0x00, 0x00, 
+        0xa8, 0x2a, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x78, 0x1e, 0x00, 0x00, 0x90, 0x24, 0x00, 0x00, 
+        0x1c, 0x13, 0x37, 0x12, 0x38, 0x1c, 0x24, 0x47, 0x12, 0x3d, 0x1c, 0x35, 0x57, 0x12, 0x3d, 0x1c, 
+        0x46, 0x67, 0x12, 0x3d, 0x1c, 0x77, 0x27, 0x27, 0x04, 0x1c, 0x58, 0x87, 0xa2, 0x24, 0x1c, 0x99, 
+        0x97, 0x12, 0x1a, 0x1c, 0xaa, 0xa7, 0x12, 0x1f, 0x1c, 0xbb, 0xb7, 0x12, 0x1f, 0x1c, 0xc3, 0x37, 
+        0x12, 0x1f, 0xe6, 0xc2, 0x04, 0x1c, 0xd4, 0x47, 0xa2, 0x08, 0x0c, 0x02, 0x0d, 0xf0, 0x21, 0xeb, 
+        0xff, 0x0d, 0xf0, 0x21, 0xeb, 0xff, 0x0d, 0xf0, 0x21, 0xeb, 0xff, 0x0d, 0xf0, 0x21, 0xea, 0xff, 
+        0x0d, 0xf0, 0x21, 0xea, 0xff, 0x0d, 0xf0, 0x00, 0xda, 0xae, 0x10, 0x40, 0xf6, 0xc2, 0x6a, 0x41, 
+        0xfe, 0xff, 0x20, 0x32, 0x90, 0x4a, 0x33, 0xa0, 0x03, 0x00, 0x46, 0x22, 0x00, 0x86, 0x20, 0x00, 
+        0x86, 0x15, 0x00, 0xc6, 0x14, 0x00, 0x06, 0x14, 0x00, 0x86, 0x1d, 0x00, 0x86, 0x12, 0x00, 0xc6, 
+        0x11, 0x00, 0x06, 0x11, 0x00, 0x46, 0x10, 0x00, 0x86, 0x0f, 0x00, 0xc6, 0x0e, 0x00, 0x06, 0x0e, 
+        0x00, 0x46, 0x0d, 0x00, 0x86, 0x0c, 0x00, 0xc6, 0x0b, 0x00, 0x46, 0x14, 0x00, 0x86, 0x12, 0x00, 
+        0xc6, 0x10, 0x00, 0x06, 0x0f, 0x00, 0x46, 0x0d, 0x00, 0x86, 0x0b, 0x00, 0xc6, 0x09, 0x00, 0x06, 
+        0x08, 0x00, 0x06, 0x05, 0x00, 0x46, 0x04, 0x00, 0x86, 0x03, 0x00, 0xc6, 0x02, 0x00, 0x06, 0x02, 
+        0x00, 0x46, 0x01, 0x00, 0x86, 0x00, 0x00, 0x06, 0x01, 0x00, 0x22, 0xa0, 0xff, 0x0d, 0xf0, 0x0c, 
+        0x02, 0x0d, 0xf0, 0x0c, 0x12, 0x0d, 0xf0, 0x0c, 0x22, 0x0d, 0xf0, 0x0c, 0x32, 0x0d, 0xf0, 0x0c, 
+        0x42, 0x0d, 0xf0, 0x0c, 0x52, 0x0d, 0xf0, 0x0c, 0x62, 0x0d, 0xf0, 0x0c, 0x72, 0x0d, 0xf0, 0x0c, 
+        0x82, 0x0d, 0xf0, 0x0c, 0x92, 0x0d, 0xf0, 0x0c, 0xa2, 0x0d, 0xf0, 0x00, 0x7e, 0xaf, 0x10, 0x40, 
+        0xf6, 0xb2, 0x3a, 0x41, 0xfe, 0xff, 0x20, 0x32, 0x90, 0x4a, 0x33, 0xa0, 0x03, 0x00, 0x46, 0x15, 
+        0x00, 0x86, 0x13, 0x00, 0x86, 0x09, 0x00, 0xc6, 0x08, 0x00, 0x06, 0x08, 0x00, 0x86, 0x10, 0x00, 
+        0x86, 0x06, 0x00, 0xc6, 0x05, 0x00, 0x46, 0x0d, 0x00, 0x86, 0x0b, 0x00, 0xc6, 0x09, 0x00, 0x06, 
+        0x08, 0x00, 0x46, 0x03, 0x00, 0x86, 0x05, 0x00, 0xc6, 0x03, 0x00, 0x06, 0x02, 0x00, 0x22, 0xa0, 
+        0xff, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x0c, 0x62, 0x0d, 0xf0, 0x0c, 0x42, 0x0d, 0xf0, 0x0c, 
+        0x22, 0x0d, 0xf0, 0x0c, 0x72, 0x0d, 0xf0, 0x0c, 0x52, 0x0d, 0xf0, 0x0c, 0x32, 0x0d, 0xf0, 0x0c, 
+        0x12, 0x0d, 0xf0, 0x0c, 0x82, 0x0d, 0xf0, 0x0c, 0x92, 0x0d, 0xf0, 0x00, 0xac, 0x12, 0x26, 0x12, 
+        0x17, 0x26, 0x22, 0x18, 0x26, 0x32, 0x0d, 0x26, 0x52, 0x0e, 0x26, 0x62, 0x0f, 0x26, 0x72, 0x04, 
+        0x22, 0xa0, 0xff, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x0c, 0x22, 0x0d, 0xf0, 0x0c, 0x12, 0x0d, 
+        0xf0, 0x0c, 0x32, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x8c, 0xd3, 0x0c, 0x06, 0x62, 0x42, 0x0a, 0xcb, 
+        0x22, 0x1b, 0x66, 0x60, 0x60, 0x74, 0x67, 0x93, 0xf2, 0x0d, 0xf0, 0x00, 0x0c, 0x05, 0x42, 0x02, 
+        0x0b, 0x00, 0x05, 0x40, 0x40, 0x40, 0x91, 0x07, 0x64, 0x04, 0x5a, 0x62, 0x32, 0x46, 0x0c, 0x1b, 
+        0x55, 0x50, 0x50, 0x74, 0x66, 0x85, 0xe6, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x62, 0x12, 0x38, 0x67, 
+        0xb3, 0x04, 0x32, 0x52, 0x39, 0x0d, 0xf0, 0x3d, 0x06, 0x46, 0xfd, 0xff, 0xff, 0x1f, 0x00, 0x00, 
+        0xff, 0x5f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x32, 0x62, 0x17, 0xf6, 0x43, 0x35, 0xb6, 0x23, 
+        0x32, 0x31, 0xfa, 0xff, 0x8c, 0xa4, 0x26, 0x14, 0x2c, 0xe6, 0x44, 0x05, 0xa6, 0x24, 0x02, 0x31, 
+        0xf8, 0xff, 0x32, 0x52, 0x38, 0x0c, 0x84, 0xe6, 0x45, 0x02, 0xd6, 0xe5, 0x00, 0x26, 0x45, 0x20, 
+        0x26, 0x55, 0x22, 0x26, 0x65, 0x15, 0x32, 0xaf, 0x94, 0x46, 0x00, 0x00, 0x0c, 0xc3, 0x32, 0x42, 
+        0x74, 0x42, 0x42, 0x75, 0x0d, 0xf0, 0x31, 0xef, 0xff, 0x46, 0xf5, 0xff, 0x4c, 0xc3, 0x06, 0xfb, 
+        0xff, 0x1c, 0x43, 0xc6, 0xf9, 0xff, 0x2c, 0x83, 0x86, 0xf8, 0xff, 0x00, 0x00, 0x83, 0xfe, 0x3f, 
+        0xdc, 0xaf, 0x10, 0x40, 0x20, 0x82, 0xfe, 0x3f, 0x70, 0xaf, 0x10, 0x40, 0x24, 0x83, 0xfe, 0x3f, 
+        0x74, 0x82, 0xfe, 0x3f, 0x90, 0x81, 0xfe, 0x3f, 0xcc, 0xae, 0x10, 0x40, 0x0c, 0x37, 0x61, 0xf8, 
+        0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x32, 0x42, 0x15, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x04, 0xcd, 
+        0x02, 0x0c, 0x02, 0x02, 0x2c, 0x17, 0x41, 0xf1, 0xff, 0x8c, 0xd0, 0x1c, 0x58, 0x1c, 0xda, 0x0c, 
+        0x29, 0x26, 0x10, 0x17, 0x26, 0x20, 0x78, 0x26, 0x30, 0x7c, 0x42, 0x6c, 0x1a, 0x42, 0x6c, 0x18, 
+        0x22, 0x4c, 0x04, 0x72, 0x4c, 0x05, 0x62, 0x6c, 0x1b, 0x46, 0x0e, 0x00, 0x22, 0x4c, 0x04, 0xa2, 
+        0xc4, 0x80, 0x01, 0xe8, 0xff, 0x62, 0xa0, 0x07, 0x52, 0xa0, 0x09, 0xb1, 0xe7, 0xff, 0xb2, 0x6c, 
+        0x1b, 0xd0, 0x56, 0x93, 0xd0, 0x0a, 0x83, 0x02, 0x6c, 0x1a, 0x52, 0x4c, 0x05, 0xa6, 0xa3, 0x02, 
+        0x06, 0x30, 0x00, 0x92, 0xa0, 0x09, 0x8c, 0x3d, 0xb6, 0x89, 0x01, 0x0c, 0x79, 0x90, 0x29, 0x90, 
+        0x00, 0x22, 0xa0, 0x22, 0x6c, 0x18, 0x41, 0xdd, 0xff, 0x31, 0xdd, 0xff, 0x2d, 0x0c, 0xd0, 0x34, 
+        0x83, 0x32, 0x6c, 0x19, 0xc5, 0x0f, 0x00, 0x08, 0x01, 0xd8, 0x21, 0x7c, 0xf5, 0x52, 0x4c, 0x00, 
+        0x52, 0x4c, 0x01, 0x52, 0x4c, 0x02, 0x52, 0x4c, 0x03, 0xc8, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x0c, 0x12, 0x0c, 0x10, 0x46, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x4c, 0x04, 0x41, 0xd2, 0xff, 0x0c, 
+        0x87, 0x0c, 0xa6, 0xb1, 0xd1, 0xff, 0xb2, 0x6c, 0x1b, 0xd0, 0x67, 0x93, 0x62, 0x4c, 0x05, 0x02, 
+        0xc4, 0x90, 0xd0, 0x04, 0x83, 0x02, 0x6c, 0x1a, 0xe6, 0xa3, 0x3c, 0x0c, 0xa9, 0x22, 0xa0, 0x05, 
+        0x16, 0x5d, 0x00, 0xb6, 0x89, 0x02, 0x92, 0xa0, 0x07, 0xf6, 0x69, 0x01, 0x2d, 0x09, 0x90, 0x39, 
+        0x90, 0x20, 0x20, 0x74, 0x20, 0x22, 0x90, 0x00, 0x33, 0xa0, 0x32, 0x6c, 0x18, 0x00, 0x22, 0xa0, 
+        0x22, 0x02, 0x00, 0x22, 0x4c, 0x08, 0x85, 0xca, 0xff, 0x3d, 0x02, 0x2d, 0x0c, 0xc5, 0xe6, 0xff, 
+        0x2d, 0x0c, 0x85, 0x05, 0x00, 0x46, 0xdb, 0xff, 0x1c, 0x04, 0x37, 0x24, 0x04, 0x0c, 0x79, 0x86, 
+        0xee, 0xff, 0x37, 0x28, 0x04, 0x0c, 0x59, 0x86, 0xec, 0xff, 0x1c, 0xa5, 0x37, 0x25, 0x23, 0x0c, 
+        0x49, 0x06, 0xea, 0xff, 0x1c, 0x06, 0x37, 0x26, 0x04, 0x0c, 0x59, 0xc6, 0xcd, 0xff, 0x37, 0x28, 
+        0x04, 0x9d, 0x07, 0xc6, 0xcb, 0xff, 0x1c, 0xe7, 0x77, 0xa3, 0x02, 0xc6, 0xc9, 0xff, 0x9d, 0x02, 
+        0x86, 0xc8, 0xff, 0x37, 0x2a, 0x04, 0x0c, 0x39, 0x46, 0xe0, 0xff, 0x20, 0x20, 0x74, 0x2c, 0x28, 
+        0x87, 0xa3, 0x02, 0x86, 0xdd, 0xff, 0x9d, 0x02, 0x46, 0xdc, 0xff, 0x00, 0x0c, 0x43, 0x12, 0xc1, 
+        0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0x45, 0xde, 0xff, 0x2d, 0x0c, 0x0c, 0x43, 0x85, 0x0a, 
+        0x01, 0x2d, 0x0c, 0x05, 0x03, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x20, 0xa1, 0x07, 0x00, 0x31, 0xff, 0xff, 0x52, 0x22, 0x18, 0x0c, 0x04, 0x42, 0x45, 0x0b, 0x49, 
+        0xa2, 0x49, 0x92, 0x49, 0xe2, 0x42, 0x42, 0x16, 0x42, 0x42, 0x17, 0x42, 0x42, 0x06, 0x32, 0x62, 
+        0x16, 0x0d, 0xf0, 0x00, 0x31, 0xf7, 0xff, 0x52, 0x22, 0x18, 0x0c, 0x04, 0x42, 0x45, 0x0b, 0x42, 
+        0x62, 0x10, 0x49, 0xf2, 0x42, 0x62, 0x11, 0x42, 0x42, 0x18, 0x42, 0x42, 0x19, 0x42, 0x42, 0x0a, 
+        0x42, 0x62, 0x15, 0x32, 0x62, 0x16, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xd9, 0x21, 0xc9, 
+        0x11, 0xdd, 0x03, 0xcd, 0x02, 0xc5, 0xfa, 0xff, 0x02, 0x2c, 0x18, 0x41, 0xdf, 0xd5, 0x32, 0x00, 
+        0x0a, 0x22, 0x0c, 0x05, 0xda, 0x33, 0x37, 0x22, 0x1b, 0xd0, 0x2d, 0x90, 0x00, 0x52, 0xa0, 0x52, 
+        0x6c, 0x18, 0xc0, 0x20, 0x00, 0x08, 0x01, 0x42, 0x24, 0x80, 0x49, 0xbc, 0xd8, 0x21, 0xc8, 0x11, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x20, 0x22, 0x90, 0x02, 0x2c, 0x1a, 0x46, 0xf7, 0xff, 0x00, 0x00, 
+        0x72, 0xa0, 0xff, 0x77, 0x13, 0x2b, 0x62, 0x02, 0x01, 0x52, 0x02, 0x00, 0x0c, 0x04, 0x32, 0x42, 
+        0x00, 0x5a, 0x33, 0x70, 0x55, 0xc0, 0x30, 0x31, 0x74, 0x50, 0x34, 0x83, 0x77, 0x16, 0x0f, 0x60, 
+        0x46, 0x90, 0x4a, 0x43, 0xe0, 0x44, 0x11, 0xfb, 0x34, 0x40, 0x34, 0xb3, 0x30, 0x34, 0x21, 0x32, 
+        0x42, 0x01, 0x0d, 0xf0, 0x10, 0x2c, 0xff, 0x3f, 0x61, 0xff, 0xff, 0x00, 0x43, 0x11, 0x58, 0x06, 
+        0x40, 0x42, 0x20, 0x1b, 0x75, 0x79, 0x06, 0x50, 0x50, 0x24, 0x62, 0xc6, 0x10, 0x60, 0x55, 0xa0, 
+        0x49, 0x05, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0xdd, 
+        0x03, 0x32, 0x22, 0x18, 0x08, 0xa2, 0x32, 0x03, 0x01, 0x1b, 0x00, 0xd7, 0x33, 0x46, 0x28, 0x92, 
+        0x09, 0xac, 0x2a, 0x0d, 0x1b, 0x00, 0x2d, 0x0d, 0x09, 0x9c, 0xc5, 0xfb, 0xff, 0x0c, 0xa3, 0xb6, 
+        0x6d, 0x0d, 0x02, 0x0c, 0x06, 0x1b, 0x00, 0x00, 0x00, 0x74, 0x02, 0x4c, 0x06, 0xc6, 0x03, 0x00, 
+        0xf6, 0x3d, 0x09, 0x0c, 0x00, 0x0c, 0x02, 0x22, 0x4c, 0x06, 0x86, 0x00, 0x00, 0x02, 0x0c, 0x06, 
+        0x07, 0xb3, 0x06, 0x2d, 0x0c, 0x0c, 0x13, 0x05, 0xf1, 0xff, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x28, 0x92, 0x09, 0xac, 0x2a, 0x0d, 0x2b, 0x00, 0x46, 0xed, 0xff, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0xdd, 0x03, 0xbc, 0x62, 0x02, 
+        0x22, 0x18, 0xbc, 0x10, 0x28, 0x53, 0x07, 0x92, 0x2d, 0x38, 0xec, 0x1b, 0x33, 0x39, 0xec, 0x22, 
+        0x0d, 0x0f, 0x66, 0x12, 0x1b, 0x42, 0x0c, 0x14, 0x27, 0xe4, 0x07, 0x2d, 0x0c, 0x32, 0x0d, 0x09, 
+        0xc5, 0xf0, 0xff, 0x32, 0x0d, 0x04, 0x2d, 0x0c, 0x30, 0x34, 0x41, 0x85, 0xf5, 0xff, 0x46, 0x01, 
+        0x00, 0x26, 0x22, 0x0d, 0x26, 0x32, 0x0a, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x2d, 0x0c, 0x32, 0x00, 0x08, 0xc5, 0xf3, 0xff, 0x46, 0xfa, 0xff, 0x00, 0x00, 0x00, 
+        0x32, 0x03, 0x00, 0xbc, 0x82, 0x42, 0x02, 0x14, 0x82, 0xa0, 0xff, 0x07, 0xe4, 0x30, 0x62, 0x02, 
+        0x02, 0x72, 0x02, 0x03, 0x87, 0x96, 0x07, 0x32, 0x42, 0x02, 0x0c, 0x06, 0x46, 0x02, 0x00, 0x32, 
+        0x42, 0x02, 0x6a, 0x63, 0x60, 0x61, 0x74, 0x3d, 0x06, 0x87, 0x17, 0x0f, 0x70, 0x47, 0x90, 0x4a, 
+        0x46, 0xe0, 0x44, 0x11, 0xfb, 0x34, 0x40, 0x34, 0xb3, 0x30, 0x34, 0x21, 0x32, 0x42, 0x03, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x41, 0xb2, 0xff, 0x38, 
+        0x14, 0x1b, 0x53, 0x59, 0x14, 0x30, 0x30, 0x24, 0x42, 0xc4, 0x30, 0x40, 0x33, 0xa0, 0x29, 0x03, 
+        0x0d, 0xf0, 0x00, 0x00, 0x3f, 0x0d, 0x03, 0x00, 0x00, 0x09, 0x3d, 0x00, 0x40, 0x0d, 0x03, 0x00, 
+        0x12, 0xc1, 0xd0, 0xf2, 0x61, 0x08, 0x02, 0x61, 0x04, 0xd2, 0x61, 0x06, 0xc9, 0x51, 0xe9, 0x71, 
+        0xcd, 0x02, 0xed, 0x03, 0xd2, 0x03, 0x06, 0x02, 0x03, 0x05, 0x80, 0xdd, 0x11, 0x00, 0xf0, 0x54, 
+        0x00, 0xdd, 0x20, 0x02, 0x03, 0x04, 0xd0, 0xd6, 0x54, 0x00, 0x00, 0x34, 0x16, 0x7d, 0x16, 0x09, 
+        0x21, 0x32, 0x22, 0x18, 0x49, 0x11, 0x16, 0xd3, 0x15, 0x05, 0xe6, 0x00, 0x16, 0x72, 0x15, 0x42, 
+        0xa7, 0xff, 0x02, 0x0e, 0x04, 0x38, 0x11, 0x00, 0x04, 0x41, 0x4a, 0x33, 0x42, 0x0e, 0x0f, 0x30, 
+        0x3b, 0x21, 0x66, 0x14, 0x18, 0x52, 0x0c, 0x14, 0x00, 0x23, 0x82, 0x2a, 0xdd, 0xd0, 0xd0, 0x74, 
+        0x27, 0xe5, 0x1c, 0x2d, 0x0c, 0x32, 0x0e, 0x09, 0x45, 0xe0, 0xff, 0x46, 0x04, 0x00, 0x30, 0x40, 
+        0xc1, 0x52, 0xc0, 0xff, 0x50, 0x53, 0x82, 0x50, 0xdd, 0x80, 0xf0, 0xd4, 0x83, 0xd0, 0xd0, 0x74, 
+        0x22, 0x0c, 0x08, 0x02, 0x2c, 0x1b, 0x38, 0xfc, 0x42, 0x2c, 0x10, 0x3a, 0x3d, 0x4a, 0x4f, 0x42, 
+        0x6c, 0x10, 0x39, 0xfc, 0xc0, 0x00, 0x00, 0x29, 0x01, 0x2d, 0x0c, 0x45, 0x7f, 0x00, 0x29, 0x91, 
+        0x3d, 0x0d, 0x90, 0x2f, 0x11, 0x05, 0x25, 0x04, 0xd8, 0x91, 0xf8, 0x01, 0xf6, 0xd2, 0x1c, 0x32, 
+        0x0c, 0x0a, 0x1b, 0x33, 0x30, 0x30, 0x74, 0x32, 0x4c, 0x0a, 0x56, 0x52, 0x0f, 0x02, 0x0e, 0x04, 
+        0x00, 0x04, 0x41, 0xe6, 0x40, 0x02, 0x06, 0x37, 0x00, 0x86, 0x37, 0x00, 0x27, 0xbd, 0x04, 0x0c, 
+        0x02, 0x22, 0x4c, 0x0a, 0xe1, 0x39, 0xd5, 0xc0, 0x20, 0x00, 0xe2, 0x2e, 0x80, 0x32, 0x2c, 0x12, 
+        0xe0, 0x2e, 0x20, 0x85, 0x8f, 0xff, 0x32, 0x2c, 0x0f, 0x02, 0xa1, 0xf3, 0x16, 0x73, 0x0a, 0x37, 
+        0x30, 0x02, 0x46, 0x28, 0x00, 0x41, 0xbf, 0xff, 0x27, 0x34, 0x02, 0x06, 0x26, 0x00, 0xe2, 0x6c, 
+        0x12, 0x22, 0x2c, 0x10, 0x42, 0x2c, 0x15, 0x90, 0x22, 0x11, 0x1b, 0x44, 0x42, 0x6c, 0x15, 0xc5, 
+        0x29, 0x04, 0x20, 0x00, 0x74, 0x52, 0x0c, 0x19, 0x59, 0x31, 0x02, 0x4c, 0x18, 0x16, 0xe5, 0x04, 
+        0x28, 0x31, 0x20, 0x22, 0x90, 0x2a, 0x20, 0x20, 0x22, 0x74, 0x22, 0x4c, 0x19, 0xc5, 0xea, 0xff, 
+        0x22, 0x0c, 0x19, 0xd7, 0x32, 0x02, 0x46, 0x26, 0x00, 0x38, 0x31, 0xd7, 0x33, 0x02, 0x46, 0x24, 
+        0x00, 0x42, 0x0c, 0x22, 0x8c, 0xd4, 0x02, 0x2c, 0x16, 0x51, 0xab, 0xff, 0x07, 0x35, 0x05, 0xf0, 
+        0x60, 0x11, 0x62, 0x6c, 0x16, 0x2d, 0x0e, 0x32, 0x2c, 0x13, 0x05, 0x88, 0xff, 0x71, 0xa7, 0xff, 
+        0x27, 0xb7, 0x29, 0x3d, 0x0f, 0x2d, 0x0c, 0x0c, 0x04, 0x05, 0x35, 0x00, 0xc6, 0x09, 0x00, 0x42, 
+        0xa0, 0x80, 0xd0, 0x3d, 0x90, 0x4a, 0x33, 0x30, 0x32, 0x74, 0x32, 0x4c, 0x19, 0x2d, 0x03, 0x07, 
+        0xb3, 0x07, 0x3a, 0x20, 0x20, 0x21, 0x74, 0x22, 0x4c, 0x19, 0x05, 0xe5, 0xff, 0x0c, 0x03, 0x32, 
+        0x6c, 0x10, 0x39, 0xfc, 0x32, 0x6c, 0x11, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 0x08, 
+        0x41, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x7c, 0xd4, 0x40, 0x00, 0x90, 0x3a, 0x30, 0x30, 0x30, 0x74, 
+        0x32, 0x4c, 0x0a, 0xb6, 0x53, 0x05, 0x42, 0x0c, 0x08, 0xb6, 0x54, 0x07, 0x0c, 0xe5, 0x37, 0x35, 
+        0x02, 0xc6, 0xc3, 0xff, 0xf0, 0x3f, 0x20, 0xc0, 0x2c, 0x20, 0x42, 0x21, 0x02, 0xc5, 0x2e, 0x00, 
+        0xc6, 0xf0, 0xff, 0x62, 0x0c, 0x22, 0x8c, 0xc6, 0x71, 0x02, 0xff, 0x0c, 0x08, 0x82, 0x4c, 0x22, 
+        0x72, 0x6c, 0x16, 0x86, 0xe9, 0xff, 0x92, 0x0c, 0x04, 0xf7, 0x19, 0xa0, 0x32, 0x0c, 0x08, 0x1c, 
+        0x3a, 0xa7, 0x13, 0x76, 0xd2, 0xa0, 0x79, 0x1c, 0x4b, 0xb7, 0x13, 0x7d, 0x02, 0xc3, 0xeb, 0x16, 
+        0x20, 0x09, 0x42, 0xc3, 0xea, 0x16, 0x54, 0x09, 0x52, 0xc3, 0xe9, 0x16, 0x85, 0x09, 0x1c, 0xf6, 
+        0x67, 0x13, 0x72, 0x0d, 0x0d, 0x27, 0x30, 0x02, 0x46, 0xdc, 0xff, 0x78, 0x31, 0x77, 0x30, 0x02, 
+        0x46, 0xda, 0xff, 0x2d, 0x0e, 0x32, 0x2c, 0x14, 0x05, 0x7b, 0xff, 0x82, 0x2c, 0x16, 0x27, 0x38, 
+        0x02, 0x06, 0xd6, 0xff, 0xc0, 0x20, 0x00, 0x0c, 0x19, 0x31, 0xdf, 0xd4, 0x0b, 0x2f, 0x20, 0x20, 
+        0x74, 0x32, 0x23, 0x80, 0x32, 0x6c, 0x14, 0x32, 0x2c, 0x1a, 0x20, 0x22, 0x90, 0x30, 0x22, 0xa0, 
+        0x22, 0x02, 0x00, 0x22, 0x4c, 0x08, 0x92, 0x4c, 0x22, 0x45, 0x7a, 0xff, 0x3d, 0x02, 0x2d, 0x0c, 
+        0x85, 0x96, 0xff, 0x2d, 0x0c, 0xc5, 0xb9, 0xff, 0xc6, 0xca, 0xff, 0x22, 0x0c, 0x01, 0x45, 0x43, 
+        0x00, 0xd2, 0xa0, 0x74, 0x06, 0x05, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0c, 0x01, 0x45, 0x42, 0x00, 
+        0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0c, 0x01, 0x85, 0x41, 0x00, 0x20, 0x0d, 0xc0, 0x22, 
+        0x0c, 0x19, 0xc6, 0xdf, 0xff, 0x22, 0x0c, 0x01, 0x85, 0x40, 0x00, 0x46, 0xfb, 0xff, 0x22, 0x0c, 
+        0x01, 0x05, 0x40, 0x00, 0x06, 0xf9, 0xff, 0x22, 0x0c, 0x01, 0x85, 0x3f, 0x00, 0xc6, 0xf6, 0xff, 
+        0x0c, 0x33, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0xd9, 0x21, 0x09, 0x01, 0xdd, 0x02, 0xc5, 0x8e, 0xff, 
+        0x2d, 0x0d, 0x0c, 0x33, 0x05, 0xbb, 0x00, 0x02, 0x2d, 0x1a, 0x2d, 0x0d, 0x02, 0xc0, 0x30, 0x02, 
+        0x6d, 0x18, 0x05, 0xb1, 0xff, 0x0c, 0x0c, 0x22, 0x0d, 0x0b, 0x00, 0x0c, 0x40, 0x20, 0x20, 0x91, 
+        0x07, 0x62, 0x08, 0x2d, 0x0d, 0x0c, 0x33, 0x4d, 0x0c, 0x05, 0x07, 0x00, 0x1b, 0xcc, 0xc0, 0xc0, 
+        0x74, 0x66, 0x8c, 0xe2, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xd9, 0x21, 0x02, 0x22, 0x1a, 0xdd, 0x02, 0x02, 0x00, 
+        0x24, 0x02, 0x42, 0x08, 0x45, 0xaa, 0xff, 0x0c, 0x0c, 0x22, 0x0d, 0x0b, 0x00, 0x0c, 0x40, 0x20, 
+        0x20, 0x91, 0x07, 0x62, 0x08, 0x2d, 0x0d, 0x0c, 0x23, 0x4d, 0x0c, 0x05, 0x03, 0x00, 0x1b, 0xcc, 
+        0xc0, 0xc0, 0x74, 0x66, 0x8c, 0xe2, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x64, 0x89, 0xfe, 0x3f, 0x8c, 0x8d, 0xfe, 0x3f, 0xa8, 0x8d, 0xfe, 0x3f, 
+        0xb4, 0x8d, 0xfe, 0x3f, 0x94, 0x8d, 0xfe, 0x3f, 0xa0, 0x8d, 0xfe, 0x3f, 0x12, 0xc1, 0xe0, 0x09, 
+        0x21, 0xd9, 0x41, 0xc9, 0x31, 0xdd, 0x03, 0xcd, 0x02, 0x40, 0x00, 0x74, 0xb6, 0x80, 0x13, 0x21, 
+        0xf5, 0xff, 0x31, 0xf5, 0xff, 0x42, 0xa3, 0x5f, 0x01, 0x22, 0xd2, 0xc0, 0x00, 0x00, 0x3d, 0xf0, 
+        0x86, 0xfe, 0xff, 0x0c, 0x12, 0x09, 0x11, 0x66, 0x23, 0x57, 0x42, 0x0c, 0x0b, 0x32, 0x0c, 0x14, 
+        0x00, 0x10, 0x40, 0x00, 0x52, 0xa1, 0xca, 0x00, 0x09, 0x01, 0x30, 0x30, 0x64, 0x50, 0x44, 0x20, 
+        0x42, 0x4c, 0x0b, 0x42, 0xa0, 0x80, 0x40, 0x33, 0x20, 0x32, 0x4c, 0x14, 0x02, 0x00, 0x0c, 0x02, 
+        0xc0, 0xfe, 0x56, 0xf0, 0x09, 0x21, 0xe3, 0xff, 0x31, 0xe4, 0xff, 0x42, 0xa3, 0x64, 0x01, 0x10, 
+        0xd2, 0xc0, 0x00, 0x00, 0x3d, 0xf0, 0x86, 0xfe, 0xff, 0xd2, 0xa0, 0x21, 0xc0, 0x2c, 0x20, 0x0c, 
+        0x33, 0x85, 0x7d, 0xff, 0x2d, 0x0c, 0x0c, 0x33, 0xc5, 0xa9, 0x00, 0x0c, 0x12, 0xd2, 0x4c, 0x15, 
+        0x0c, 0x3d, 0x08, 0x11, 0x26, 0x1d, 0x56, 0x66, 0x3d, 0x2f, 0x26, 0x1d, 0x50, 0x0c, 0x1d, 0x21, 
+        0xd7, 0xff, 0x3d, 0x00, 0xca, 0x70, 0x0c, 0x16, 0x62, 0x47, 0x0c, 0x01, 0x01, 0xd2, 0xc0, 0x00, 
+        0x00, 0x32, 0x0c, 0x09, 0x66, 0x33, 0x1d, 0x3d, 0x0d, 0x2d, 0x0c, 0xc5, 0xa6, 0x00, 0x06, 0x02, 
+        0x00, 0x21, 0xcf, 0xff, 0x01, 0xfb, 0xd1, 0xc0, 0x00, 0x00, 0xc8, 0x31, 0xd8, 0x41, 0x08, 0x21, 
+        0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x66, 0x43, 0xe8, 0x21, 0xca, 0xff, 0x01, 0xf5, 0xd1, 0xc0, 0x00, 
+        0x00, 0x3d, 0x0d, 0x2d, 0x0c, 0x05, 0xa4, 0x00, 0x86, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x82, 0x0c, 
+        0x0b, 0x7c, 0xfa, 0x00, 0x10, 0x40, 0x00, 0x92, 0xa1, 0xa0, 0x99, 0x30, 0x90, 0x88, 0x10, 0x82, 
+        0x4c, 0x0b, 0x46, 0xe6, 0xff, 0x21, 0xbf, 0xff, 0x38, 0x11, 0x01, 0xe9, 0xd1, 0xc0, 0x00, 0x00, 
+        0x32, 0x0c, 0x09, 0x26, 0x43, 0x3c, 0x26, 0x23, 0x39, 0x66, 0x13, 0x0b, 0x21, 0xbb, 0xff, 0x01, 
+        0xe4, 0xd1, 0xc0, 0x00, 0x00, 0x06, 0x02, 0x00, 0x21, 0xb8, 0xff, 0x01, 0xe1, 0xd1, 0xc0, 0x00, 
+        0x00, 0x2c, 0x12, 0xb2, 0x0c, 0x15, 0x1c, 0x04, 0xb7, 0x34, 0x11, 0x02, 0x0c, 0x01, 0x07, 0x34, 
+        0x02, 0x06, 0xcd, 0xff, 0xd2, 0xa0, 0xff, 0xd0, 0xd0, 0xc0, 0x16, 0xbd, 0xf2, 0x22, 0x4c, 0x15, 
+        0x86, 0xdd, 0xff, 0x22, 0x21, 0x00, 0x02, 0xa0, 0x02, 0xd0, 0x3d, 0x20, 0x02, 0x42, 0x0c, 0x2d, 
+        0x0c, 0x45, 0x9c, 0x00, 0x46, 0xf2, 0xff, 0x00, 0xbc, 0x8d, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x21, 0x09, 0x11, 0x02, 0x02, 0x14, 0xcd, 0x02, 0x67, 0xe0, 0x52, 0x49, 0x01, 0x66, 0x53, 0x1e, 
+        0xc5, 0x3b, 0x00, 0x32, 0x0c, 0x19, 0x32, 0xc3, 0x14, 0x27, 0xb3, 0x3c, 0x21, 0xf7, 0xff, 0x01, 
+        0xc8, 0xd1, 0xc0, 0x00, 0x00, 0x2d, 0x0c, 0x38, 0x01, 0x45, 0xdc, 0xff, 0x86, 0x0b, 0x00, 0x41, 
+        0x32, 0xd4, 0xc0, 0x20, 0x00, 0x42, 0x24, 0x80, 0x42, 0x62, 0x13, 0x1b, 0x23, 0x32, 0x2c, 0x1a, 
+        0x20, 0x20, 0x74, 0x20, 0x22, 0x90, 0x30, 0x22, 0xa0, 0x22, 0x02, 0x00, 0x22, 0x4c, 0x08, 0x05, 
+        0x4f, 0xff, 0x3d, 0x02, 0x2d, 0x0c, 0x45, 0x6b, 0xff, 0x2d, 0x0c, 0x85, 0x8e, 0xff, 0xc8, 0x21, 
+        0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0xc4, 0x8d, 0xfe, 0x3f, 0x00, 0x08, 0x20, 0x00, 
+        0x10, 0x81, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0xdd, 
+        0x03, 0x9c, 0x12, 0x02, 0x22, 0x18, 0x8c, 0xc0, 0x08, 0x03, 0x00, 0x26, 0x41, 0x77, 0x60, 0x41, 
+        0x22, 0x2c, 0x19, 0x06, 0x02, 0x00, 0x22, 0x0d, 0x00, 0x07, 0x62, 0x49, 0x21, 0xbd, 0xfd, 0x29, 
+        0x5d, 0xcc, 0x72, 0x21, 0xf1, 0xff, 0x01, 0xa6, 0xd1, 0xc0, 0x00, 0x00, 0x8c, 0xfc, 0x32, 0x0c, 
+        0x14, 0x02, 0x0c, 0x07, 0x67, 0x63, 0x07, 0x48, 0x0d, 0x97, 0x64, 0x02, 0x06, 0x01, 0x00, 0x08, 
+        0x5d, 0x02, 0x00, 0x00, 0x02, 0x4d, 0x08, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x97, 0x60, 0x16, 0x22, 0x0c, 0x14, 0x37, 0x62, 0x27, 0x2d, 0x0c, 0x05, 0x62, 0x00, 
+        0xc6, 0xee, 0xff, 0x00, 0x00, 0x00, 0x21, 0xa9, 0xfd, 0x86, 0xec, 0xff, 0x31, 0xe0, 0xff, 0x27, 
+        0x03, 0x0a, 0x42, 0x2c, 0x17, 0x21, 0xde, 0xff, 0x8c, 0x14, 0x46, 0xe8, 0xff, 0x22, 0x2c, 0x19, 
+        0xc6, 0xe6, 0xff, 0xc0, 0x2c, 0x20, 0x05, 0x36, 0x00, 0x22, 0x2c, 0x18, 0x62, 0x2d, 0x00, 0x71, 
+        0xc5, 0xd2, 0x60, 0x50, 0x54, 0x60, 0x66, 0x41, 0x70, 0x66, 0x20, 0xa0, 0x66, 0x11, 0x60, 0x55, 
+        0x20, 0x52, 0x6d, 0x00, 0xc6, 0xdd, 0xff, 0x00, 0xcc, 0x8d, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x21, 0x09, 0x11, 0x02, 0x02, 0x14, 0xcd, 0x03, 0x67, 0x60, 0x19, 0x02, 0x02, 0x07, 0x02, 0x43, 
+        0x08, 0xb6, 0xb0, 0x08, 0x22, 0xc0, 0xf0, 0x20, 0x20, 0x24, 0xe6, 0x32, 0x32, 0x1c, 0x33, 0x32, 
+        0x4c, 0x08, 0x86, 0x0a, 0x00, 0x29, 0x01, 0x37, 0xe0, 0x2e, 0x32, 0x03, 0x04, 0x30, 0x30, 0x34, 
+        0x2a, 0x43, 0x42, 0x04, 0x0c, 0x29, 0x01, 0x66, 0x14, 0x0f, 0x48, 0x01, 0x21, 0xef, 0xff, 0x42, 
+        0x04, 0x09, 0x01, 0x73, 0xd1, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x02, 0x02, 0x08, 0x02, 0x4c, 0x08, 
+        0xc8, 0x21, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x45, 0x57, 0x00, 0x29, 0x5c, 0x02, 0x02, 
+        0x00, 0x06, 0xfa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x48, 0x03, 0x0c, 0x06, 0x40, 0xb6, 0x41, 0xc7, 
+        0xf4, 0x2a, 0x0c, 0x07, 0x82, 0x03, 0x04, 0x98, 0x53, 0x80, 0x84, 0x41, 0x90, 0xa6, 0x90, 0x42, 
+        0x0a, 0x01, 0x1b, 0x66, 0x7a, 0x74, 0x70, 0x70, 0x74, 0x87, 0x27, 0x12, 0x8c, 0x72, 0x52, 0x02, 
+        0x14, 0x67, 0x65, 0x02, 0x37, 0xeb, 0x10, 0x22, 0x0a, 0x00, 0x22, 0x43, 0x08, 0x0d, 0xf0, 0x60, 
+        0x60, 0x74, 0x66, 0x46, 0xd6, 0x06, 0xfd, 0xff, 0x22, 0x02, 0x07, 0xc6, 0xfa, 0xff, 0x00, 0x00, 
+        0x25, 0xbb, 0x10, 0x40, 0x62, 0xa0, 0xff, 0xf6, 0xc3, 0x7c, 0x51, 0xfd, 0xff, 0x30, 0x43, 0x90, 
+        0x5a, 0x44, 0xa0, 0x04, 0x00, 0x86, 0x1b, 0x00, 0xc6, 0x6c, 0x00, 0xc6, 0x64, 0x00, 0x46, 0x5c, 
+        0x00, 0x86, 0x18, 0x00, 0xc6, 0x69, 0x00, 0xc6, 0x61, 0x00, 0x46, 0x59, 0x00, 0xc6, 0x50, 0x00, 
+        0x46, 0x48, 0x00, 0x46, 0x40, 0x00, 0xc6, 0x37, 0x00, 0x46, 0x2f, 0x00, 0xc6, 0x26, 0x00, 0x46, 
+        0x1e, 0x00, 0x46, 0x16, 0x00, 0x06, 0x34, 0x00, 0x06, 0x3b, 0x00, 0x46, 0x1b, 0x00, 0xc6, 0x40, 
+        0x00, 0x86, 0x21, 0x00, 0x06, 0x47, 0x00, 0xc6, 0x27, 0x00, 0x06, 0x0d, 0x00, 0x06, 0x2e, 0x00, 
+        0x06, 0x35, 0x00, 0x46, 0x15, 0x00, 0xc6, 0x3a, 0x00, 0x86, 0x1b, 0x00, 0x06, 0x41, 0x00, 0xc6, 
+        0x21, 0x00, 0x06, 0x07, 0x00, 0x32, 0xc2, 0xdf, 0x22, 0xc2, 0xe0, 0x30, 0x23, 0xb3, 0x20, 0x21, 
+        0x21, 0x20, 0x22, 0x90, 0x20, 0x20, 0x74, 0x2c, 0x03, 0x27, 0xb3, 0x03, 0x2d, 0x03, 0x0d, 0xf0, 
+        0x0d, 0xf0, 0x2c, 0x14, 0x27, 0xb4, 0x02, 0x67, 0x92, 0xda, 0x0c, 0x02, 0x06, 0xf9, 0xff, 0xb6, 
+        0x92, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0x46, 0xf6, 0xff, 0x32, 0xc2, 0xf7, 0x22, 0xc2, 0xf8, 
+        0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0xc6, 0xf1, 0xff, 0x0c, 0xd4, 0x27, 0xb4, 
+        0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0x86, 0xee, 0xff, 0x32, 0xc2, 0xf3, 0x22, 0xc2, 0xf4, 0x30, 
+        0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0x06, 0xea, 0xff, 0x1c, 0x54, 0x27, 0xb4, 0x02, 
+        0x67, 0x92, 0x04, 0x0c, 0x02, 0xc6, 0xe6, 0xff, 0x32, 0xc2, 0xeb, 0x22, 0xc2, 0xec, 0x30, 0x23, 
+        0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0x46, 0xe2, 0xff, 0x1c, 0xd4, 0x27, 0xb4, 0x02, 0x67, 
+        0x92, 0x04, 0x0c, 0x02, 0x06, 0xdf, 0xff, 0x32, 0xc2, 0xe3, 0x22, 0xc2, 0xe4, 0x30, 0x23, 0xb3, 
+        0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0x86, 0xda, 0xff, 0x0c, 0x84, 0x27, 0xb4, 0x02, 0x67, 0x92, 
+        0x04, 0x0c, 0x02, 0x46, 0xd7, 0xff, 0x32, 0xc2, 0xf8, 0x22, 0xc2, 0xf9, 0x30, 0x23, 0xb3, 0x20, 
+        0x21, 0x21, 0x20, 0x22, 0x90, 0xc6, 0xd2, 0xff, 0xb6, 0xa2, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 
+        0x06, 0xd0, 0xff, 0x32, 0xc2, 0xf5, 0x22, 0xc2, 0xf6, 0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 
+        0x22, 0x90, 0x86, 0xcb, 0xff, 0x1c, 0x04, 0x27, 0xb4, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0x46, 
+        0xc8, 0xff, 0x32, 0xc2, 0xf0, 0x22, 0xc2, 0xf1, 0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 
+        0x90, 0xc6, 0xc3, 0xff, 0x1c, 0xa4, 0x27, 0xb4, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0x86, 0xc0, 
+        0xff, 0x32, 0xc2, 0xe6, 0x22, 0xc2, 0xe7, 0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 
+        0x06, 0xbc, 0xff, 0x0c, 0xe4, 0x27, 0xb4, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0xc6, 0xb8, 0xff, 
+        0x32, 0xc2, 0xf2, 0x22, 0xc2, 0xf3, 0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0x46, 
+        0xb4, 0xff, 0xb6, 0xa2, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0x86, 0xb1, 0xff, 0x32, 0xc2, 0xf5, 
+        0x22, 0xc2, 0xf6, 0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0x06, 0xad, 0xff, 0x0c, 
+        0xa4, 0x27, 0xb4, 0x02, 0x67, 0x92, 0x04, 0x0c, 0x02, 0xc6, 0xa9, 0xff, 0x32, 0xc2, 0xf6, 0x22, 
+        0xc2, 0xf7, 0x30, 0x23, 0xb3, 0x20, 0x21, 0x21, 0x20, 0x22, 0x90, 0x46, 0xa5, 0xff, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x32, 0x02, 0x08, 0x1c, 0x30, 0x07, 0x13, 0x20, 0x1c, 0x44, 0x47, 
+        0x13, 0x48, 0x1c, 0x55, 0x57, 0x13, 0x54, 0x02, 0xa0, 0x72, 0x1c, 0x67, 0x77, 0x13, 0x32, 0x1c, 
+        0x78, 0x87, 0x13, 0x58, 0x1c, 0xf9, 0x97, 0x13, 0x19, 0x2d, 0x00, 0x46, 0x03, 0x00, 0x22, 0x02, 
+        0x01, 0x05, 0xde, 0xff, 0x3d, 0x02, 0x22, 0xa0, 0x6c, 0x30, 0x22, 0xc0, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x22, 0x02, 0x01, 0xc5, 0xdc, 0xff, 0x42, 0xa0, 0x72, 0x20, 0x24, 0xc0, 0x46, 
+        0xfa, 0xff, 0x22, 0x02, 0x01, 0xc5, 0xdb, 0xff, 0x46, 0xfb, 0xff, 0x22, 0x02, 0x01, 0x45, 0xdb, 
+        0xff, 0x3d, 0x02, 0x22, 0xa0, 0x6d, 0x30, 0x22, 0xc0, 0xc6, 0xf3, 0xff, 0x22, 0x02, 0x01, 0x45, 
+        0xda, 0xff, 0x3d, 0x02, 0x22, 0xa0, 0x73, 0x30, 0x22, 0xc0, 0x86, 0xef, 0xff, 0x22, 0x02, 0x01, 
+        0x05, 0xd9, 0xff, 0x3d, 0x02, 0x22, 0xa0, 0x73, 0x30, 0x22, 0xc0, 0x46, 0xeb, 0xff, 0x00, 0x00, 
+        0x9f, 0x86, 0x01, 0x00, 0xa0, 0x86, 0x01, 0x00, 0x12, 0xc1, 0xe0, 0xe2, 0x61, 0x04, 0x02, 0x61, 
+        0x01, 0xd2, 0x61, 0x03, 0xc9, 0x21, 0xcd, 0x02, 0xd1, 0x20, 0xd3, 0xc0, 0x20, 0x00, 0xd2, 0x2d, 
+        0x80, 0x38, 0xd2, 0x2d, 0x0d, 0x45, 0x09, 0xff, 0x38, 0x9c, 0xe1, 0xf5, 0xff, 0x16, 0x93, 0x06, 
+        0x58, 0xec, 0x42, 0xa0, 0x63, 0x57, 0x34, 0x02, 0x27, 0xbe, 0x5e, 0xd9, 0xdc, 0xe1, 0x51, 0xfd, 
+        0x28, 0xac, 0x48, 0x2e, 0x90, 0x22, 0x11, 0x1b, 0x44, 0x49, 0x2e, 0x05, 0xa4, 0x03, 0x20, 0x20, 
+        0x74, 0x02, 0x0c, 0x17, 0x22, 0x4c, 0x16, 0x16, 0x30, 0x09, 0x0a, 0x52, 0x38, 0xcc, 0x2d, 0x0d, 
+        0x50, 0x51, 0x21, 0x52, 0x4c, 0x17, 0x45, 0x05, 0xff, 0xe2, 0x0c, 0x17, 0x29, 0x01, 0x32, 0x2c, 
+        0x18, 0x22, 0x0c, 0x01, 0x32, 0x03, 0x00, 0xc5, 0xd0, 0xff, 0x02, 0x2c, 0x18, 0x20, 0x21, 0x74, 
+        0x32, 0x00, 0x09, 0x4c, 0x05, 0x56, 0x93, 0x09, 0x5c, 0xa4, 0x20, 0x44, 0xc0, 0x0c, 0x12, 0xe7, 
+        0xb4, 0x02, 0xc6, 0x2d, 0x00, 0x0c, 0x02, 0x86, 0x2c, 0x00, 0x32, 0x2c, 0x0d, 0x22, 0x2c, 0x12, 
+        0x85, 0x01, 0xff, 0x20, 0xd2, 0x20, 0xc0, 0x2c, 0x20, 0x05, 0x4d, 0x00, 0x16, 0x52, 0x06, 0xd7, 
+        0xbe, 0x62, 0x2d, 0x0c, 0x52, 0x2c, 0x12, 0xd2, 0x2c, 0x18, 0x61, 0x01, 0xfd, 0xd2, 0x0d, 0x0a, 
+        0x62, 0x6c, 0x16, 0x59, 0xdc, 0xc5, 0x3f, 0xff, 0x02, 0x2c, 0x1b, 0x22, 0x0c, 0x08, 0xc0, 0x00, 
+        0x00, 0x32, 0x2c, 0x1a, 0x20, 0x02, 0x90, 0x30, 0x00, 0xa0, 0x02, 0x6c, 0x18, 0x02, 0x00, 0x0a, 
+        0x07, 0x3d, 0x02, 0x46, 0x49, 0x00, 0x42, 0x2c, 0x12, 0x49, 0xbc, 0x86, 0x07, 0x00, 0x02, 0x2c, 
+        0x18, 0x02, 0x00, 0x09, 0x32, 0xa0, 0x80, 0x00, 0x00, 0x90, 0x3a, 0x00, 0x00, 0x02, 0x74, 0x02, 
+        0x4c, 0x17, 0x27, 0xb0, 0x07, 0x0a, 0x32, 0x30, 0x31, 0x21, 0x32, 0x4c, 0x17, 0x0c, 0x04, 0x49, 
+        0xac, 0x49, 0x9c, 0x49, 0xec, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0x08, 0x11, 0x12, 0xc1, 0x20, 
+        0x0d, 0xf0, 0x37, 0x35, 0x0f, 0x62, 0xa0, 0x64, 0x20, 0x66, 0xc0, 0x0c, 0x12, 0xe7, 0x36, 0x1c, 
+        0x0c, 0x02, 0xc6, 0x05, 0x00, 0x0c, 0x06, 0x72, 0xa0, 0x6e, 0x20, 0x77, 0xc0, 0xe7, 0xb7, 0x09, 
+        0x20, 0x83, 0xc0, 0x2b, 0x88, 0xe7, 0xb8, 0x01, 0x0c, 0x16, 0x60, 0x20, 0x74, 0x0c, 0x1e, 0x8c, 
+        0xb2, 0xa8, 0x01, 0x92, 0x2c, 0x16, 0xa7, 0xb9, 0x04, 0x0d, 0x0e, 0x46, 0x16, 0x00, 0xb2, 0x00, 
+        0x0b, 0x07, 0xeb, 0x0a, 0x21, 0x08, 0xfd, 0x28, 0x22, 0x20, 0x20, 0x14, 0x56, 0xd2, 0xf9, 0x22, 
+        0x0c, 0x01, 0x32, 0x00, 0x00, 0xc5, 0xc0, 0xff, 0x32, 0x0c, 0x17, 0x02, 0x2c, 0x18, 0x20, 0x51, 
+        0x74, 0x42, 0x00, 0x09, 0x22, 0x00, 0x0b, 0x50, 0x44, 0xc0, 0x47, 0xa3, 0x16, 0x07, 0x62, 0x0e, 
+        0x02, 0x2c, 0x16, 0x61, 0x51, 0xfd, 0x07, 0x36, 0x05, 0xf0, 0x70, 0x11, 0x72, 0x6c, 0x16, 0x0c, 
+        0x20, 0xc6, 0x04, 0x00, 0x07, 0x62, 0x0e, 0x81, 0xc6, 0xfc, 0x92, 0xa0, 0xfe, 0x90, 0x92, 0x10, 
+        0x92, 0x40, 0x0b, 0x82, 0x6c, 0x16, 0x0c, 0x00, 0x66, 0x10, 0x30, 0x2d, 0x0c, 0x45, 0x30, 0xff, 
+        0x02, 0x2c, 0x18, 0xa2, 0x0c, 0x04, 0xb2, 0x00, 0x0a, 0xb7, 0x3a, 0x02, 0x46, 0xcf, 0xff, 0x32, 
+        0xc0, 0xf4, 0x32, 0x6c, 0x18, 0x22, 0x03, 0x0b, 0xe0, 0x22, 0x20, 0x22, 0x43, 0x0b, 0xc0, 0x20, 
+        0x00, 0xd1, 0xad, 0xd2, 0xd2, 0x2d, 0x80, 0xd9, 0xcc, 0x06, 0xc8, 0xff, 0x32, 0xc0, 0xfe, 0x56, 
+        0xa3, 0xf1, 0x2d, 0x0d, 0x38, 0xbc, 0x45, 0xec, 0xfe, 0x41, 0x82, 0xff, 0x27, 0x34, 0x02, 0x86, 
+        0xc2, 0xff, 0x2d, 0x0c, 0x0c, 0x13, 0x05, 0x30, 0xff, 0x06, 0xc0, 0xff, 0xd7, 0x30, 0x02, 0x86, 
+        0xbe, 0xff, 0x52, 0x2c, 0x12, 0x59, 0xcc, 0x86, 0xbc, 0xff, 0x00, 0x00, 0x32, 0x02, 0x04, 0x48, 
+        0x52, 0x0c, 0x12, 0x42, 0x04, 0x08, 0x30, 0x34, 0x41, 0x47, 0xa3, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 
+        0xdc, 0x8d, 0xfe, 0x3f, 0x20, 0x81, 0xfe, 0x3f, 0x80, 0x82, 0xfe, 0x3f, 0x21, 0xfd, 0xff, 0x12, 
+        0xc1, 0xf0, 0x09, 0x01, 0x01, 0x27, 0xd0, 0xc0, 0x00, 0x00, 0x41, 0xce, 0xfc, 0x0c, 0x05, 0x52, 
+        0x44, 0x0c, 0x02, 0xc4, 0x50, 0x42, 0xc4, 0x52, 0x52, 0x40, 0x00, 0x1b, 0x00, 0x47, 0x90, 0xf7, 
+        0x21, 0x35, 0xfc, 0x0c, 0xb3, 0x05, 0x01, 0xff, 0x21, 0xf3, 0xff, 0x0c, 0x93, 0x85, 0x00, 0xff, 
+        0x21, 0xf2, 0xff, 0x0c, 0xa3, 0x05, 0x00, 0xff, 0x21, 0x2b, 0xfc, 0x0c, 0x83, 0x85, 0xff, 0xfe, 
+        0x21, 0x27, 0xfc, 0x0c, 0x43, 0x05, 0xff, 0xfe, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x70, 0x2c, 0xff, 0x3f, 0x21, 0xff, 0xff, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x83, 0xfe, 0x3f, 
+        0x22, 0x22, 0x17, 0x41, 0xfe, 0xff, 0x8c, 0x72, 0x26, 0x12, 0x0d, 0x26, 0x22, 0x0f, 0x26, 0x32, 
+        0x03, 0x2d, 0x04, 0x0d, 0xf0, 0xcb, 0x24, 0x0d, 0xf0, 0x22, 0xc4, 0x24, 0x0d, 0xf0, 0x22, 0xc4, 
+        0x18, 0x0d, 0xf0, 0x00, 0x74, 0x21, 0xff, 0x3f, 0x58, 0x72, 0x52, 0x05, 0x08, 0xbc, 0x55, 0x26, 
+        0x15, 0x44, 0x26, 0x55, 0x41, 0x26, 0x95, 0x5c, 0x0c, 0xb6, 0x67, 0x15, 0x48, 0x0c, 0xf7, 0x77, 
+        0x15, 0x61, 0x26, 0xb5, 0x40, 0x1c, 0x18, 0x87, 0x15, 0x4a, 0x1c, 0x89, 0x97, 0x15, 0x36, 0x1c, 
+        0x9a, 0xa7, 0x15, 0x40, 0xb1, 0xf4, 0xff, 0x32, 0x12, 0x08, 0xb2, 0x1b, 0x05, 0x0c, 0x12, 0x37, 
+        0x3b, 0x12, 0x0c, 0x02, 0x0d, 0xf0, 0x32, 0xa2, 0x71, 0x42, 0x12, 0x08, 0x0c, 0x12, 0x47, 0x33, 
+        0x03, 0x0c, 0x02, 0x0d, 0xf0, 0x0d, 0xf0, 0x52, 0xa3, 0xe8, 0x62, 0x12, 0x08, 0x0c, 0x12, 0x67, 
+        0x35, 0xf2, 0x0c, 0x02, 0x0d, 0xf0, 0x72, 0xa2, 0xbc, 0x82, 0x12, 0x08, 0x0c, 0x12, 0x87, 0x37, 
+        0xe3, 0x0c, 0x02, 0x0d, 0xf0, 0x92, 0xa4, 0x60, 0xa2, 0x12, 0x08, 0x0c, 0x12, 0xa7, 0x39, 0xd4, 
+        0x0c, 0x02, 0x0d, 0xf0, 0xb2, 0xa4, 0x1a, 0x32, 0x12, 0x08, 0x0c, 0x12, 0x37, 0x3b, 0xc5, 0x0c, 
+        0x02, 0x0d, 0xf0, 0x00, 0x0d, 0xf0, 0x00, 0x00, 0x32, 0x02, 0x14, 0x42, 0xa0, 0xfe, 0x40, 0x33, 
+        0x10, 0x0c, 0x14, 0x40, 0x33, 0x20, 0x42, 0xa0, 0xfb, 0x40, 0x33, 0x10, 0x0c, 0x44, 0x40, 0x33, 
+        0x20, 0x32, 0x42, 0x14, 0x0d, 0xf0, 0x00, 0x00, 0x32, 0x02, 0x14, 0x42, 0xa0, 0xfe, 0x40, 0x33, 
+        0x10, 0x42, 0xa0, 0xfb, 0x40, 0x33, 0x10, 0x32, 0x42, 0x14, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x03, 0xcd, 0x02, 0x02, 0x02, 0x14, 0x22, 0xa0, 0xbf, 0x20, 
+        0x00, 0x10, 0x66, 0xc3, 0x0f, 0x2d, 0x0c, 0x02, 0x4c, 0x14, 0x05, 0x1d, 0x00, 0xec, 0xd2, 0x22, 
+        0x0c, 0x08, 0x86, 0x0b, 0x00, 0xd2, 0x4c, 0x07, 0x2d, 0x0c, 0x4c, 0x03, 0x30, 0x30, 0x20, 0x32, 
+        0x4c, 0x14, 0x85, 0x1b, 0x00, 0x8c, 0xa2, 0x2d, 0x0d, 0x45, 0xd1, 0xfe, 0x3d, 0x02, 0x2d, 0x0c, 
+        0x85, 0xed, 0xfe, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x22, 0x0c, 
+        0x07, 0x22, 0x4c, 0x08, 0x85, 0xcf, 0xfe, 0x3d, 0x02, 0x2d, 0x0c, 0x05, 0xec, 0xfe, 0x46, 0xf8, 
+        0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x29, 0x01, 0x39, 0x11, 0x09, 0x21, 0x01, 0x85, 0xd3, 
+        0xc0, 0x00, 0x00, 0x08, 0x01, 0x28, 0x11, 0x32, 0x00, 0x01, 0x39, 0x02, 0x02, 0x00, 0x03, 0x09, 
+        0x12, 0x01, 0x81, 0xd3, 0xc0, 0x00, 0x00, 0x0c, 0x22, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x20, 0x2c, 0xff, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x02, 0xcd, 
+        0x02, 0x01, 0x78, 0xd3, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x21, 0xf9, 0xff, 0x20, 0x30, 0xa0, 0x1b, 
+        0x00, 0x38, 0x03, 0x39, 0x0d, 0x00, 0x00, 0x74, 0x4b, 0xdd, 0x66, 0x80, 0xee, 0x01, 0x72, 0xd3, 
+        0xc0, 0x00, 0x00, 0xc0, 0x3d, 0xc0, 0x08, 0x01, 0xc8, 0x11, 0xd8, 0x21, 0x3b, 0x23, 0x30, 0x23, 
+        0xb3, 0x20, 0x22, 0xf4, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x29, 
+        0x01, 0x39, 0x11, 0x09, 0x21, 0x01, 0x67, 0xd3, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x28, 0x11, 0x82, 
+        0x00, 0x08, 0x89, 0x02, 0x72, 0x00, 0x09, 0x79, 0x12, 0x62, 0x00, 0x19, 0x69, 0x22, 0x52, 0x20, 
+        0x10, 0x59, 0x32, 0x48, 0xf0, 0x49, 0x42, 0x32, 0x00, 0x0a, 0x39, 0x52, 0x02, 0x20, 0x15, 0x09, 
+        0x62, 0x01, 0x5d, 0xd3, 0xc0, 0x00, 0x00, 0x0c, 0x72, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x40, 0x2c, 0xff, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x02, 0xcd, 
+        0x02, 0x01, 0x54, 0xd3, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x21, 0xf9, 0xff, 0x20, 0x30, 0xa0, 0x1b, 
+        0x00, 0x38, 0x03, 0x39, 0x0d, 0x00, 0x00, 0x74, 0x4b, 0xdd, 0x66, 0x80, 0xee, 0x01, 0x4e, 0xd3, 
+        0xc0, 0x00, 0x00, 0xc0, 0x3d, 0xc0, 0x08, 0x01, 0xc8, 0x11, 0xd8, 0x21, 0x3b, 0x23, 0x30, 0x23, 
+        0xb3, 0x20, 0x22, 0xf4, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x22, 0x02, 0x14, 0x20, 
+        0x27, 0x41, 0x0d, 0xf0, 0xe8, 0x8d, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x21, 0xbc, 0xd2, 0x02, 
+        0x22, 0x18, 0xbc, 0x80, 0x42, 0x02, 0x14, 0x40, 0x47, 0x41, 0xbc, 0x04, 0x58, 0x73, 0x52, 0x05, 
+        0x04, 0x50, 0x50, 0x34, 0x5a, 0x52, 0x52, 0x05, 0x0c, 0x66, 0x15, 0x21, 0x39, 0x11, 0x62, 0x00, 
+        0x0a, 0x29, 0x01, 0xf6, 0x46, 0x17, 0x21, 0xf3, 0xff, 0x01, 0x69, 0xcf, 0xc0, 0x00, 0x00, 0x38, 
+        0x11, 0x38, 0x73, 0x32, 0x03, 0x04, 0x28, 0x01, 0x30, 0x30, 0x34, 0x45, 0x49, 0xff, 0x08, 0x21, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x29, 0x01, 0x39, 0x11, 0x09, 
+        0x21, 0x01, 0x2c, 0xd3, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x08, 0x11, 0x02, 0x42, 0x09, 0x01, 0x2a, 
+        0xd3, 0xc0, 0x00, 0x00, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x0c, 0x13, 0x42, 0x02, 
+        0x09, 0x0c, 0x02, 0x42, 0xc4, 0xfe, 0x40, 0x23, 0x83, 0x0d, 0xf0, 0x00, 0xf0, 0x8d, 0xfe, 0x3f, 
+        0xf8, 0x8d, 0xfe, 0x3f, 0x0c, 0x19, 0x81, 0x3e, 0xff, 0x12, 0xc1, 0xe0, 0xd9, 0x41, 0x39, 0x01, 
+        0xf9, 0x61, 0x09, 0x21, 0xe9, 0x51, 0xc9, 0x31, 0x72, 0xc8, 0xa0, 0xcd, 0x04, 0xe2, 0xc8, 0xf0, 
+        0xea, 0xe2, 0x00, 0x0c, 0x40, 0x4d, 0x05, 0x02, 0x07, 0x0c, 0x49, 0x11, 0x00, 0x50, 0x91, 0x07, 
+        0x65, 0x2b, 0xf2, 0x0e, 0x00, 0xf0, 0xf0, 0x91, 0x07, 0x6f, 0x7f, 0x0c, 0x64, 0xd2, 0xa0, 0x78, 
+        0xc0, 0xdd, 0xc1, 0xda, 0xd8, 0xf2, 0xcd, 0x1a, 0x2d, 0x0f, 0x01, 0xd6, 0xf0, 0xc0, 0x00, 0x00, 
+        0x56, 0x72, 0x06, 0x71, 0xe8, 0xfb, 0x0c, 0x19, 0x02, 0x07, 0x0c, 0x06, 0x03, 0x00, 0x22, 0xc8, 
+        0x1a, 0xf2, 0xa0, 0x78, 0xc0, 0xff, 0xc1, 0x8a, 0xdf, 0x2a, 0xff, 0x00, 0x1c, 0x40, 0x00, 0x29, 
+        0xa1, 0x00, 0x32, 0x20, 0x32, 0x47, 0x0c, 0x02, 0x0e, 0x00, 0x32, 0xa0, 0x78, 0x20, 0x00, 0x20, 
+        0x2d, 0x0d, 0x02, 0x4e, 0x00, 0x01, 0x0d, 0xd2, 0xc0, 0x00, 0x00, 0x2d, 0x0f, 0xc2, 0x4d, 0x76, 
+        0x48, 0x11, 0x38, 0x01, 0x42, 0x5d, 0x10, 0x0c, 0x64, 0x01, 0x68, 0xd2, 0xc0, 0x00, 0x00, 0x3d, 
+        0x0c, 0x21, 0xd6, 0xff, 0x01, 0x2b, 0xcf, 0xc0, 0x00, 0x00, 0x08, 0x21, 0xc8, 0x31, 0xe8, 0x51, 
+        0x2d, 0x0d, 0xf8, 0x61, 0xd8, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x21, 0xd1, 0xff, 0x01, 0x24, 
+        0xcf, 0xc0, 0x00, 0x00, 0x0c, 0x0d, 0x06, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x21, 0xca, 0xfb, 0x22, 
+        0x02, 0x0c, 0x0d, 0xf0, 0x60, 0x2c, 0xff, 0x3f, 0x08, 0x8e, 0xfe, 0x3f, 0x14, 0x8e, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x11, 0xc9, 0x21, 0x01, 0xfb, 0xff, 0xcd, 0x04, 0x0a, 0x42, 0x49, 0x01, 
+        0x42, 0x04, 0x00, 0x00, 0x0c, 0x40, 0x40, 0x40, 0x91, 0x07, 0x64, 0x47, 0x22, 0xc0, 0x10, 0x42, 
+        0xa0, 0x78, 0xc0, 0x44, 0xd1, 0x4a, 0x22, 0x22, 0xc2, 0x1a, 0x0c, 0x64, 0x01, 0xa6, 0xf0, 0xc0, 
+        0x00, 0x00, 0xec, 0xe2, 0x21, 0xf1, 0xff, 0x98, 0x01, 0x7c, 0xf8, 0x61, 0xb6, 0xfb, 0x00, 0x1c, 
+        0x40, 0x0c, 0x17, 0x00, 0x77, 0xa1, 0x52, 0x06, 0x0c, 0x80, 0x77, 0x30, 0x82, 0x09, 0x00, 0x70, 
+        0x55, 0x10, 0x52, 0x46, 0x0c, 0x70, 0x88, 0x10, 0x82, 0x49, 0x00, 0x01, 0x05, 0xcf, 0xc0, 0x00, 
+        0x00, 0x06, 0x02, 0x00, 0x21, 0xe6, 0xff, 0x01, 0x02, 0xcf, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0x08, 
+        0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x61, 0xa7, 0xfb, 0x0c, 0x03, 0x72, 0x06, 0x0c, 
+        0x42, 0xc6, 0x50, 0x4a, 0x42, 0x52, 0x04, 0x00, 0x32, 0x44, 0x00, 0x70, 0x55, 0x30, 0x52, 0x46, 
+        0x0c, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x01, 0x01, 0xd6, 0xff, 0x00, 0x02, 0x80, 
+        0x22, 0x00, 0x00, 0x22, 0x61, 0x00, 0x05, 0xe0, 0x02, 0x52, 0xa0, 0x78, 0x48, 0x01, 0x08, 0x11, 
+        0x40, 0x30, 0x60, 0x12, 0xc1, 0x10, 0x40, 0x33, 0x10, 0x0b, 0x42, 0x30, 0xf3, 0x40, 0x30, 0x30, 
+        0x60, 0x21, 0xd7, 0xfe, 0x32, 0xc3, 0x1f, 0x50, 0x33, 0x82, 0x3a, 0x22, 0x0c, 0x03, 0x40, 0x23, 
+        0x93, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xe0, 0xd9, 0x21, 0xf9, 0x41, 0x09, 0x01, 0xc9, 0x11, 0xc1, 
+        0xc5, 0xff, 0xe9, 0x31, 0xca, 0xc2, 0xc2, 0x0c, 0x00, 0xed, 0x03, 0xc0, 0xd0, 0x60, 0xc0, 0xdd, 
+        0x10, 0xd0, 0xfd, 0x40, 0xd0, 0xd0, 0x60, 0xd2, 0xcd, 0x1f, 0x96, 0xfd, 0x02, 0x3d, 0x0e, 0x0c, 
+        0x64, 0xf1, 0xc7, 0xfe, 0x02, 0xa0, 0x78, 0x00, 0x0d, 0x82, 0x0a, 0xff, 0x22, 0xcf, 0x1a, 0x01, 
+        0x6d, 0xf0, 0xc0, 0x00, 0x00, 0xac, 0x52, 0x7c, 0xf0, 0x00, 0x1d, 0x40, 0x0c, 0x1f, 0x00, 0xff, 
+        0xa1, 0x00, 0xff, 0x30, 0xf0, 0xcc, 0x10, 0xc0, 0xc0, 0x74, 0x46, 0xef, 0xff, 0x0c, 0x02, 0xc8, 
+        0x11, 0xd8, 0x21, 0xe8, 0x31, 0xf8, 0x41, 0x08, 0x01, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x2d, 0x0f, 
+        0xc6, 0xfa, 0xff, 0x00, 0x41, 0x74, 0xfb, 0x00, 0x02, 0x40, 0x32, 0x04, 0x0c, 0x52, 0xc4, 0x60, 
+        0x30, 0x30, 0x91, 0x07, 0x63, 0x09, 0x32, 0xa0, 0x78, 0x20, 0x23, 0xc1, 0x2a, 0x25, 0x0d, 0xf0, 
+        0x0c, 0x02, 0x0d, 0xf0, 0x21, 0x6c, 0xfb, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x22, 0x02, 0x0c, 
+        0x45, 0xd3, 0x02, 0x02, 0x21, 0x00, 0x66, 0x12, 0x10, 0x41, 0x66, 0xfb, 0x32, 0xa0, 0x01, 0x42, 
+        0x04, 0x50, 0x0c, 0x02, 0x40, 0x23, 0x83, 0x46, 0x00, 0x00, 0x7c, 0xf2, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x64, 0x89, 0xfe, 0x3f, 0x24, 0x8e, 0xfe, 0x3f, 0x60, 0x83, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xe0, 0x32, 0x61, 0x01, 0x42, 0x61, 0x02, 0x52, 0x61, 0x03, 0x69, 0x41, 0x29, 0x01, 
+        0x09, 0x51, 0x0c, 0x72, 0x85, 0xc2, 0xf8, 0xdc, 0x02, 0x21, 0xf6, 0xff, 0x31, 0xf7, 0xff, 0x42, 
+        0xa0, 0xe7, 0x01, 0xab, 0xce, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x92, 0x21, 0x03, 0xb2, 0x21, 
+        0x04, 0x01, 0xf2, 0xff, 0x32, 0x22, 0x07, 0x48, 0x01, 0x49, 0x23, 0x08, 0x00, 0x48, 0x21, 0xa2, 
+        0x10, 0x00, 0x88, 0x10, 0xb9, 0x13, 0x90, 0xaa, 0xc0, 0xa2, 0x50, 0x00, 0x49, 0x12, 0x89, 0x02, 
+        0x92, 0x52, 0x04, 0x88, 0x18, 0x89, 0x32, 0x62, 0xa0, 0xbf, 0x0c, 0x08, 0xc0, 0x20, 0x00, 0x72, 
+        0x04, 0x03, 0x60, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x38, 0x11, 0x72, 0x44, 0x03, 0x58, 0x24, 0x59, 
+        0x10, 0x89, 0x24, 0x16, 0x33, 0x08, 0x52, 0x00, 0x02, 0x98, 0x30, 0x0b, 0x55, 0x78, 0x29, 0x79, 
+        0x30, 0x52, 0x40, 0x02, 0x89, 0x29, 0x38, 0x12, 0xc0, 0x20, 0x00, 0x42, 0x13, 0x00, 0x40, 0x40, 
+        0xb4, 0x51, 0xfc, 0xd0, 0x40, 0x44, 0x11, 0xc0, 0x20, 0x00, 0xb2, 0x13, 0x01, 0x00, 0xbb, 0x11, 
+        0xc0, 0x20, 0x00, 0x72, 0x13, 0x00, 0x70, 0xbb, 0x20, 0x50, 0xbb, 0x10, 0x40, 0xbb, 0x20, 0xc0, 
+        0x20, 0x00, 0xb2, 0x53, 0x00, 0xb0, 0xb0, 0xf5, 0xc0, 0x20, 0x00, 0xa8, 0x12, 0xb2, 0x53, 0x01, 
+        0x99, 0x2a, 0x99, 0x12, 0xc0, 0x20, 0x00, 0x72, 0x09, 0x03, 0x60, 0x77, 0x10, 0x80, 0x77, 0x20, 
+        0xc0, 0x20, 0x00, 0x31, 0x6f, 0xe3, 0x72, 0x49, 0x03, 0x52, 0x12, 0x04, 0x48, 0x72, 0x1b, 0x55, 
+        0x52, 0x52, 0x04, 0x52, 0x14, 0x00, 0x1c, 0x07, 0x30, 0x35, 0x10, 0x50, 0x50, 0xb4, 0x70, 0x55, 
+        0x20, 0x50, 0x50, 0xb4, 0x50, 0x33, 0x20, 0x32, 0x54, 0x00, 0x85, 0x72, 0xfa, 0x08, 0x51, 0x12, 
+        0xc1, 0x20, 0x0d, 0xf0, 0xd0, 0x2e, 0xff, 0x3f, 0x6d, 0x02, 0x71, 0xfe, 0xff, 0x4d, 0x03, 0x12, 
+        0xc1, 0xf0, 0x09, 0x01, 0x31, 0xba, 0xff, 0x58, 0x22, 0x38, 0x03, 0x28, 0x17, 0x59, 0x17, 0x02, 
+        0x13, 0x00, 0x0c, 0x05, 0x40, 0x00, 0xc0, 0x59, 0x26, 0x02, 0x53, 0x00, 0x3d, 0x06, 0xc5, 0xba, 
+        0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0x32, 0x61, 0x06, 0xc2, 0x61, 
+        0x03, 0x42, 0x61, 0x01, 0xc1, 0xae, 0xff, 0x09, 0x21, 0xc8, 0x0c, 0xe9, 0x51, 0xc8, 0x1c, 0xd9, 
+        0x41, 0xc8, 0x1c, 0xdd, 0x02, 0xe2, 0x0c, 0x13, 0xcb, 0xcc, 0xe0, 0xe3, 0x04, 0x45, 0xfd, 0x01, 
+        0xdc, 0x02, 0x21, 0xa4, 0xff, 0x31, 0xa4, 0xff, 0x42, 0xa1, 0x2e, 0x01, 0x59, 0xce, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0x91, 0xe4, 0xff, 0x82, 0x1c, 0x06, 0xa2, 0xa0, 0xf0, 0x29, 0x01, 0x32, 
+        0x0c, 0x0a, 0x22, 0x02, 0x06, 0xa0, 0x33, 0x10, 0x20, 0x20, 0x34, 0x30, 0x22, 0x20, 0x22, 0x4c, 
+        0x0a, 0xbc, 0xce, 0x01, 0xb2, 0xea, 0xc0, 0x20, 0x00, 0x42, 0x20, 0x88, 0x38, 0x39, 0x47, 0x13, 
+        0x11, 0x21, 0x94, 0xff, 0x31, 0x95, 0xff, 0x42, 0xa1, 0x35, 0x01, 0x49, 0xce, 0xc0, 0x00, 0x00, 
+        0x06, 0xff, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x20, 0x89, 0x66, 0x15, 0x02, 0xc6, 0x22, 0x00, 0x21, 
+        0x8d, 0xff, 0x31, 0x8d, 0xff, 0x42, 0xa1, 0x37, 0x01, 0x42, 0xce, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x02, 0x0c, 0x03, 0x47, 0xe0, 0x02, 0x57, 0x60, 0x7d, 0x80, 0x00, 0x34, 0x16, 0x00, 0x0c, 
+        0x62, 0xc0, 0xfc, 0x16, 0xb6, 0x09, 0x72, 0xc0, 0xf8, 0x16, 0xa7, 0x0d, 0x82, 0x29, 0x5b, 0x0c, 
+        0x10, 0x1b, 0x88, 0x82, 0x69, 0x5b, 0x8c, 0x80, 0x2d, 0x0d, 0x38, 0x61, 0x85, 0xf0, 0xff, 0xc6, 
+        0x0e, 0x00, 0xa1, 0x9f, 0xd0, 0xc0, 0x20, 0x00, 0x92, 0x1d, 0x01, 0x00, 0x99, 0x11, 0xc0, 0x20, 
+        0x00, 0xb2, 0x1d, 0x00, 0xb0, 0x99, 0x20, 0xa0, 0x99, 0x10, 0x90, 0x9c, 0x41, 0xdc, 0x09, 0x21, 
+        0x75, 0xff, 0x31, 0x75, 0xff, 0x42, 0xa1, 0xb7, 0x01, 0x2a, 0xce, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x4d, 0x0d, 0x3d, 0x0e, 0x28, 0x01, 0x58, 0x61, 0x68, 0x11, 0x45, 0xdc, 0xff, 0xc8, 0x31, 
+        0xd8, 0x41, 0xe8, 0x51, 0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0xa2, 0x29, 0x52, 0x1b, 0xaa, 
+        0xa2, 0x69, 0x52, 0x0c, 0x00, 0x46, 0xe7, 0xff, 0x67, 0xe0, 0x05, 0x00, 0xb7, 0x41, 0x16, 0x8b, 
+        0x07, 0x22, 0x29, 0x59, 0x80, 0x00, 0x34, 0x16, 0x10, 0x04, 0x26, 0x40, 0x0a, 0x26, 0x80, 0x51, 
+        0xc2, 0x29, 0x5b, 0x1b, 0xcc, 0xc2, 0x69, 0x5b, 0x0c, 0x10, 0x1b, 0x22, 0x22, 0x69, 0x59, 0xc6, 
+        0xdc, 0xff, 0xa0, 0x08, 0x10, 0x26, 0xe0, 0x56, 0x32, 0xa0, 0x90, 0x37, 0x10, 0x68, 0x42, 0xa0, 
+        0xa0, 0x47, 0x10, 0x55, 0x52, 0x29, 0x56, 0x1b, 0x55, 0x52, 0x69, 0x56, 0x0c, 0x10, 0x06, 0xd5, 
+        0xff, 0x62, 0x29, 0x57, 0x1b, 0x66, 0x62, 0x69, 0x57, 0x86, 0xe9, 0xff, 0x80, 0x00, 0x74, 0x26, 
+        0xd0, 0x0f, 0x5c, 0x07, 0x77, 0x10, 0xc0, 0x66, 0xe0, 0xbd, 0x82, 0x29, 0x5a, 0x1b, 0x88, 0x82, 
+        0x69, 0x5a, 0x0c, 0x00, 0x86, 0xec, 0xff, 0xa2, 0x29, 0x58, 0x2d, 0x0c, 0x1b, 0xaa, 0xa2, 0x69, 
+        0x58, 0x05, 0xbd, 0xfe, 0xc6, 0xde, 0xff, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x86, 0xc5, 0xff, 0xb2, 
+        0x29, 0x53, 0x1b, 0xbb, 0xb2, 0x69, 0x53, 0x46, 0xec, 0xff, 0xc2, 0x29, 0x55, 0x0c, 0x00, 0x1b, 
+        0xcc, 0xc2, 0x69, 0x55, 0x86, 0xbf, 0xff, 0x02, 0x29, 0x54, 0x1b, 0x00, 0x02, 0x69, 0x54, 0x46, 
+        0xe6, 0xff, 0x00, 0x00, 0x50, 0x30, 0xff, 0x3f, 0x0c, 0xc3, 0x52, 0xa1, 0x00, 0x62, 0xa1, 0x00, 
+        0x0c, 0x17, 0x12, 0xc1, 0xe0, 0x09, 0x61, 0x22, 0xc1, 0x10, 0x29, 0x01, 0x02, 0xc1, 0x14, 0x21, 
+        0xf9, 0xff, 0x09, 0x11, 0x42, 0xc2, 0x60, 0x01, 0x28, 0xd0, 0xc0, 0x00, 0x00, 0x28, 0x41, 0x38, 
+        0x51, 0x27, 0x13, 0x11, 0x21, 0x30, 0xff, 0x31, 0x30, 0xff, 0x42, 0xa1, 0xf1, 0x01, 0xe4, 0xcd, 
+        0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x48, 0x22, 0x08, 0x61, 0x9c, 0x04, 0x21, 0x2a, 0xff, 0x31, 
+        0x2a, 0xff, 0x42, 0xa1, 0xf2, 0x01, 0xde, 0xcd, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x12, 0xc1, 
+        0x20, 0x0d, 0xf0, 0x00, 0x00, 0xa0, 0x80, 0x00, 0xf7, 0xbf, 0xdf, 0x7f, 0x91, 0xfe, 0xff, 0x81, 
+        0x17, 0xee, 0x31, 0x45, 0xd0, 0xc0, 0x20, 0x00, 0x72, 0x23, 0xa2, 0x90, 0x77, 0x20, 0xc0, 0x20, 
+        0x00, 0x72, 0x63, 0xa2, 0x61, 0xf9, 0xff, 0xc0, 0x20, 0x00, 0x52, 0x23, 0xa2, 0x60, 0x55, 0x10, 
+        0xc0, 0x20, 0x00, 0x52, 0x63, 0xa2, 0x0c, 0x84, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xa4, 0x40, 0x22, 
+        0x20, 0xc0, 0x20, 0x00, 0x22, 0x63, 0xa4, 0x0c, 0x3b, 0xc0, 0x20, 0x00, 0xa2, 0x23, 0xa5, 0xb0, 
+        0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x63, 0xa5, 0x92, 0xaf, 0x0f, 0xc0, 0x20, 0x00, 0x78, 0x28, 
+        0x90, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x79, 0x28, 0x62, 0xaf, 0x00, 0x0c, 0x45, 0xc0, 0x20, 0x00, 
+        0x42, 0x23, 0x9b, 0x60, 0x44, 0x10, 0x50, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x63, 0x9b, 0x21, 
+        0xa6, 0xda, 0xb2, 0xa4, 0x00, 0xc0, 0x20, 0x00, 0xa2, 0x23, 0x9b, 0x20, 0xaa, 0x10, 0xb0, 0xaa, 
+        0x20, 0xc0, 0x20, 0x00, 0xa2, 0x63, 0x9b, 0x91, 0x43, 0xd3, 0x82, 0xa0, 0xf0, 0xc0, 0x20, 0x00, 
+        0x72, 0x23, 0x85, 0x90, 0x77, 0x10, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x63, 0x85, 0x61, 
+        0x87, 0xd9, 0xc0, 0x20, 0x00, 0x52, 0x23, 0x85, 0x60, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x63, 
+        0x85, 0x41, 0xb2, 0xdc, 0xc0, 0x20, 0x00, 0x22, 0x23, 0x85, 0x40, 0x22, 0x20, 0xc0, 0x20, 0x00, 
+        0x22, 0x63, 0x85, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xa0, 0x3b, 0xff, 0x3f, 0xe0, 0x7f, 0x00, 0x00, 
+        0xb0, 0x38, 0xff, 0x3f, 0x5c, 0x30, 0xff, 0x3f, 0x80, 0xbb, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x20, 
+        0x32, 0xa2, 0xe8, 0x41, 0xf9, 0xff, 0x51, 0xf9, 0xff, 0x62, 0xa2, 0x10, 0x0c, 0x17, 0x21, 0xf8, 
+        0xff, 0x12, 0xc1, 0xd0, 0xc9, 0x61, 0xf9, 0x91, 0xd9, 0x71, 0xf1, 0xe4, 0xfe, 0x09, 0x51, 0x88, 
+        0x0f, 0xe9, 0x81, 0x8b, 0x08, 0x09, 0x11, 0x4b, 0x88, 0x89, 0x01, 0x01, 0xd3, 0xcf, 0xc0, 0x00, 
+        0x00, 0x08, 0x0f, 0x3c, 0xe9, 0xc8, 0x10, 0x92, 0x50, 0x00, 0x16, 0x5c, 0x06, 0xd1, 0x80, 0xe2, 
+        0xe1, 0xfd, 0xcf, 0xc0, 0x20, 0x00, 0x22, 0x1c, 0x00, 0x20, 0x20, 0xb4, 0x22, 0xc2, 0xfc, 0x20, 
+        0x20, 0xb4, 0xc0, 0x20, 0x00, 0x02, 0x1c, 0x00, 0xd0, 0x00, 0x10, 0x20, 0x00, 0x20, 0xc0, 0x20, 
+        0x00, 0x02, 0x5c, 0x00, 0xc0, 0x20, 0x00, 0xb2, 0x1c, 0x00, 0xb0, 0xb0, 0xb4, 0x40, 0xbb, 0x11, 
+        0xc0, 0x20, 0x00, 0xa2, 0x1c, 0x01, 0x00, 0xaa, 0x11, 0xc0, 0x20, 0x00, 0x02, 0x1c, 0x00, 0x00, 
+        0xaa, 0x20, 0xe0, 0xaa, 0x10, 0xb0, 0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x5c, 0x00, 0xa0, 0xa0, 
+        0xf5, 0xc0, 0x20, 0x00, 0xa2, 0x5c, 0x01, 0x2d, 0x0c, 0x05, 0xd0, 0x00, 0xc8, 0x2c, 0x56, 0x1c, 
+        0xfa, 0x08, 0x0f, 0x21, 0xd4, 0xff, 0x52, 0xa7, 0x00, 0x62, 0xa1, 0x00, 0x0c, 0x17, 0xd1, 0xd0, 
+        0xff, 0xcb, 0x40, 0x32, 0xc0, 0x10, 0x39, 0x11, 0x49, 0x01, 0x5c, 0x43, 0x42, 0xdd, 0xf9, 0x01, 
+        0xae, 0xcf, 0xc0, 0x00, 0x00, 0x3c, 0x03, 0x52, 0xc1, 0x10, 0x68, 0x0f, 0xc1, 0xcb, 0xff, 0x0c, 
+        0x77, 0x2d, 0x0c, 0x72, 0x46, 0x02, 0x42, 0xcc, 0x30, 0x0c, 0x17, 0x59, 0x11, 0x62, 0xc6, 0x14, 
+        0x69, 0x01, 0x52, 0xa1, 0x00, 0x4c, 0x06, 0x01, 0xa4, 0xcf, 0xc0, 0x00, 0x00, 0xb8, 0x0f, 0x48, 
+        0x41, 0x38, 0x5b, 0x39, 0x24, 0x91, 0xc5, 0xe9, 0xc0, 0x20, 0x00, 0xd2, 0x69, 0xa0, 0xc0, 0x20, 
+        0x00, 0xc2, 0x69, 0x9f, 0x21, 0x6c, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x69, 0xa2, 0xc0, 0x20, 0x00, 
+        0xd2, 0x69, 0xa1, 0x02, 0xaf, 0x00, 0x0c, 0xcf, 0xc0, 0x20, 0x00, 0xe2, 0x29, 0x80, 0x00, 0xee, 
+        0x10, 0xf0, 0xee, 0x20, 0xc0, 0x20, 0x00, 0xe2, 0x69, 0x80, 0xd8, 0x1b, 0xc0, 0x20, 0x00, 0xd2, 
+        0x69, 0x82, 0xc8, 0x3b, 0xc0, 0x20, 0x00, 0xc2, 0x69, 0x83, 0xb8, 0x5b, 0xc0, 0x20, 0x00, 0xb2, 
+        0x69, 0x84, 0xa1, 0xae, 0xff, 0xc0, 0x20, 0x00, 0x82, 0x29, 0x80, 0xa0, 0x88, 0x20, 0xc0, 0x20, 
+        0x00, 0x82, 0x69, 0x80, 0xc8, 0x61, 0xd8, 0x71, 0xe8, 0x81, 0xf8, 0x91, 0x08, 0x51, 0x12, 0xc1, 
+        0x30, 0x0d, 0xf0, 0x00, 0x10, 0x32, 0x50, 0x76, 0x21, 0xff, 0xff, 0x31, 0xc4, 0xe9, 0xc0, 0x20, 
+        0x00, 0x22, 0x63, 0x80, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x72, 0xa7, 0x07, 
+        0x21, 0xa3, 0xe9, 0xc0, 0x20, 0x00, 0x62, 0x22, 0x9b, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 
+        0x62, 0x9b, 0x51, 0x74, 0xce, 0xc0, 0x20, 0x00, 0x42, 0x22, 0x9b, 0x50, 0x44, 0x20, 0xc0, 0x20, 
+        0x00, 0x42, 0x62, 0x9b, 0x1c, 0x03, 0xc0, 0x20, 0x00, 0x02, 0x22, 0x9b, 0x30, 0x00, 0x20, 0xc0, 
+        0x20, 0x00, 0x0c, 0x03, 0x02, 0x62, 0x9b, 0x0c, 0x04, 0x0c, 0x02, 0x45, 0x46, 0x00, 0x0c, 0x02, 
+        0x0c, 0x13, 0x0c, 0x04, 0x85, 0x45, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x00, 0x03, 0x9f, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x0c, 0x03, 0x21, 0x97, 0xcf, 0xc0, 0x20, 
+        0x00, 0x32, 0x62, 0x86, 0x7c, 0xf0, 0xc0, 0x20, 0x00, 0x02, 0x62, 0x89, 0xc5, 0xd2, 0xff, 0x85, 
+        0xa3, 0x00, 0xc5, 0xe0, 0xff, 0x05, 0xf7, 0xff, 0xc5, 0xf7, 0xff, 0x91, 0xf5, 0xff, 0x51, 0x83, 
+        0xe9, 0xc0, 0x20, 0x00, 0xa1, 0x8d, 0xcf, 0x92, 0x6a, 0x86, 0x0c, 0x28, 0xc0, 0x20, 0x00, 0x72, 
+        0x25, 0xde, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x65, 0xde, 0x61, 0xa5, 0xd2, 0xc0, 0x20, 
+        0x00, 0x42, 0x25, 0x81, 0x60, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x65, 0x81, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x0b, 0x07, 0x00, 0x07, 0x0c, 0x07, 0x00, 0x41, 0x90, 0xe9, 0x8c, 
+        0x92, 0x31, 0xfc, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x64, 0x83, 0x0d, 0xf0, 0x21, 0xfb, 0xff, 0xc0, 
+        0x20, 0x00, 0x22, 0x64, 0x83, 0x0d, 0xf0, 0x00, 0xff, 0xff, 0xfb, 0xff, 0xf0, 0x2e, 0xff, 0x3f, 
+        0x12, 0xc1, 0xd0, 0xc9, 0x51, 0xe9, 0x71, 0xf9, 0x81, 0xd9, 0x61, 0xd1, 0x73, 0xcf, 0x09, 0x41, 
+        0xc0, 0x20, 0x00, 0xc2, 0x2d, 0x88, 0xcc, 0xdc, 0xc8, 0x51, 0xd8, 0x61, 0xe8, 0x71, 0xf8, 0x81, 
+        0x08, 0x41, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0xe2, 0x2d, 0xa1, 0xc0, 0x20, 0x00, 
+        0xc2, 0x6d, 0x89, 0xc0, 0x9c, 0x05, 0x56, 0xb9, 0x19, 0x87, 0x6c, 0x6b, 0xc0, 0x20, 0x00, 0x21, 
+        0x5b, 0xe9, 0xa1, 0x84, 0xfe, 0x22, 0x22, 0x87, 0xa8, 0x1a, 0x20, 0xaa, 0xc0, 0x56, 0x2a, 0x17, 
+        0xc0, 0x20, 0x00, 0x31, 0x56, 0xe9, 0xf2, 0x23, 0x85, 0xc0, 0x20, 0x00, 0x41, 0x30, 0xed, 0x42, 
+        0x24, 0xbf, 0x49, 0x21, 0xc0, 0x20, 0x00, 0x32, 0x23, 0x86, 0x30, 0x30, 0x74, 0x39, 0x31, 0x01, 
+        0xce, 0xef, 0xc0, 0x00, 0x00, 0xf0, 0x52, 0xc0, 0x56, 0x35, 0x1b, 0x16, 0x2f, 0x1c, 0x68, 0x2f, 
+        0x16, 0xf6, 0x1c, 0xc0, 0x20, 0x00, 0x72, 0x0f, 0x03, 0x70, 0x70, 0x64, 0x70, 0x76, 0x41, 0x0b, 
+        0x77, 0x56, 0x67, 0x17, 0x2d, 0x0f, 0x38, 0x31, 0x48, 0x21, 0xc5, 0x9e, 0xff, 0x91, 0x6d, 0xfe, 
+        0x82, 0x29, 0x51, 0x1b, 0x88, 0x82, 0x69, 0x51, 0x91, 0x4f, 0xe0, 0xc7, 0x09, 0x17, 0xb2, 0xaf, 
+        0xe8, 0xe0, 0x2c, 0x34, 0xb0, 0xb2, 0x82, 0xd0, 0xbb, 0x80, 0xc0, 0x20, 0x00, 0xa2, 0xa0, 0x00, 
+        0xa2, 0x6b, 0xf0, 0x45, 0xc5, 0xf9, 0x37, 0xfc, 0x02, 0x06, 0x2d, 0x00, 0xc0, 0x20, 0x00, 0x01, 
+        0x13, 0xed, 0x08, 0x10, 0xe0, 0xfc, 0x34, 0x87, 0x70, 0x05, 0x00, 0x00, 0x75, 0x86, 0x00, 0x00, 
+        0x02, 0xa0, 0xff, 0x02, 0x61, 0x01, 0xb6, 0x8f, 0x07, 0x09, 0x11, 0x32, 0xcf, 0xf6, 0x56, 0x53, 
+        0x0f, 0x85, 0x7e, 0xf8, 0x51, 0x05, 0xce, 0x50, 0x5c, 0x10, 0x59, 0x01, 0xdc, 0x72, 0x61, 0x02, 
+        0xce, 0x67, 0x0c, 0x12, 0x2d, 0x0f, 0x85, 0xd8, 0xf8, 0x81, 0xbb, 0xff, 0x71, 0xff, 0xcd, 0x80, 
+        0xcc, 0x10, 0x70, 0x7c, 0x10, 0x79, 0x01, 0xe0, 0x0c, 0x35, 0x16, 0x10, 0x05, 0x26, 0x10, 0x3e, 
+        0x26, 0x20, 0x2e, 0x26, 0x40, 0x1d, 0x92, 0xc0, 0xfb, 0x56, 0x09, 0x0f, 0xf9, 0x91, 0x45, 0xb9, 
+        0xf9, 0x31, 0xb2, 0xff, 0xb8, 0x91, 0x30, 0xbb, 0xa0, 0xa8, 0xcb, 0x08, 0x01, 0x1b, 0xaa, 0xa9, 
+        0xcb, 0x86, 0x10, 0x00, 0xe0, 0x20, 0x75, 0xc5, 0xc6, 0xf9, 0xf9, 0x91, 0x46, 0xf8, 0xff, 0x00, 
+        0x00, 0x00, 0x2d, 0x0f, 0x45, 0xb2, 0xf9, 0xf9, 0x91, 0x06, 0xf5, 0xff, 0x00, 0x00, 0x00, 0xe0, 
+        0x20, 0x75, 0x3d, 0x0f, 0xc5, 0xbb, 0xf9, 0xf9, 0x91, 0x06, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x32, 
+        0x21, 0x01, 0xf0, 0x2f, 0x20, 0x30, 0x30, 0x74, 0x05, 0xf2, 0xf8, 0xf2, 0x61, 0x09, 0xc6, 0xeb, 
+        0xff, 0x01, 0xe1, 0xcd, 0x00, 0x0c, 0x10, 0x8c, 0xd0, 0xe0, 0x2c, 0x34, 0xb6, 0x82, 0x02, 0x66, 
+        0x92, 0x66, 0x10, 0x11, 0x20, 0x85, 0xcf, 0xf8, 0x47, 0x7c, 0x05, 0x10, 0x11, 0x20, 0x45, 0x62, 
+        0xf9, 0x97, 0x6c, 0x0a, 0x41, 0x2c, 0xfe, 0x32, 0x24, 0x5d, 0x1b, 0x33, 0x32, 0x64, 0x5d, 0xc0, 
+        0x47, 0x05, 0x16, 0xa4, 0xe5, 0x61, 0x27, 0xfe, 0x52, 0x26, 0x5e, 0x1b, 0x55, 0x52, 0x66, 0x5e, 
+        0x06, 0x93, 0xff, 0x21, 0xe0, 0xfd, 0x31, 0xe0, 0xfd, 0x42, 0xa2, 0xf2, 0x01, 0x95, 0xcc, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xdb, 0xfd, 0x31, 0xdc, 0xfd, 0x42, 0xa2, 0xeb, 0x01, 0x90, 
+        0xcc, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xd7, 0xfd, 0x31, 0xd7, 0xfd, 0x42, 0xa3, 0x1a, 
+        0x01, 0x8c, 0xcc, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xd2, 0xfd, 0x31, 0xd3, 0xfd, 0x42, 
+        0xa3, 0x39, 0x01, 0x87, 0xcc, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xce, 0xfd, 0x31, 0xce, 
+        0xfd, 0x42, 0xa3, 0x01, 0x01, 0x83, 0xcc, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 0xc9, 0xfd, 
+        0x31, 0xca, 0xfd, 0x42, 0xa3, 0x32, 0x01, 0x7e, 0xcc, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x21, 
+        0xc5, 0xfd, 0x31, 0xc5, 0xfd, 0x42, 0xa2, 0xf7, 0x01, 0x7a, 0xcc, 0xc0, 0x00, 0x00, 0x06, 0xff, 
+        0xff, 0x21, 0xc0, 0xfd, 0x31, 0xc1, 0xfd, 0x42, 0xa2, 0xff, 0x01, 0x75, 0xcc, 0xc0, 0x00, 0x00, 
+        0x06, 0xff, 0xff, 0x21, 0xbc, 0xfd, 0x31, 0xbc, 0xfd, 0x42, 0xa3, 0x00, 0x01, 0x71, 0xcc, 0xc0, 
+        0x00, 0x00, 0x06, 0xff, 0xff, 0x00, 0x00, 0x00, 0x91, 0xdc, 0xce, 0x6c, 0x88, 0x30, 0xa0, 0x34, 
+        0x40, 0xb0, 0x94, 0x40, 0xbb, 0x11, 0x80, 0xaa, 0x01, 0x20, 0x88, 0xd1, 0x9a, 0x88, 0xb0, 0xaa, 
+        0x20, 0xc0, 0x20, 0x00, 0xa2, 0x68, 0xf0, 0x91, 0xd9, 0xd6, 0xc0, 0x20, 0x00, 0x72, 0x28, 0xf1, 
+        0x90, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x61, 0x59, 0xff, 0x60, 0x62, 0xa0, 0x58, 0x06, 0x72, 0x68, 
+        0xf1, 0x1b, 0x55, 0x59, 0x06, 0x0d, 0xf0, 0x00, 0xff, 0xff, 0xff, 0x3f, 0x6c, 0x84, 0x51, 0xca, 
+        0xce, 0x20, 0x44, 0xd1, 0x5a, 0x44, 0x51, 0xfc, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x24, 0xf1, 0x50, 
+        0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x64, 0xf1, 0x0d, 0xf0, 0x00, 0x00, 0x7c, 0xf9, 0x81, 0xc0, 
+        0xe7, 0x72, 0x03, 0x03, 0x52, 0x03, 0x01, 0x62, 0x03, 0x00, 0x80, 0x55, 0x11, 0x60, 0x55, 0x20, 
+        0x62, 0x03, 0x02, 0x80, 0x77, 0x01, 0x00, 0x66, 0x11, 0x70, 0x66, 0x20, 0x71, 0x02, 0xf5, 0x60, 
+        0x55, 0x20, 0x61, 0xb9, 0xce, 0xbc, 0x32, 0xc0, 0x20, 0x00, 0x52, 0x66, 0x94, 0xb2, 0x03, 0x05, 
+        0xa2, 0x03, 0x04, 0x80, 0xbb, 0x11, 0xb0, 0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x66, 0x95, 0xc0, 
+        0x20, 0x00, 0x92, 0x66, 0x98, 0xc0, 0x20, 0x00, 0x72, 0x66, 0x99, 0xc0, 0x20, 0x00, 0x42, 0x26, 
+        0x99, 0x80, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x66, 0x99, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x52, 
+        0x66, 0x92, 0x22, 0x03, 0x05, 0xb2, 0x03, 0x04, 0x80, 0x22, 0x11, 0x20, 0xbb, 0x20, 0xc0, 0x20, 
+        0x00, 0xb2, 0x66, 0x93, 0xc0, 0x20, 0x00, 0x92, 0x66, 0x96, 0xc0, 0x20, 0x00, 0x72, 0x66, 0x97, 
+        0xc0, 0x20, 0x00, 0xa2, 0x26, 0x97, 0x80, 0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 0x66, 0x97, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x71, 0xd1, 0xff, 0x6c, 0x84, 0x31, 0x9b, 0xce, 0x20, 0x44, 0xd1, 0x3a, 
+        0x44, 0xc0, 0x20, 0x00, 0x82, 0x23, 0xb7, 0x70, 0x88, 0x10, 0xc0, 0x20, 0x00, 0x82, 0x64, 0xf1, 
+        0xc0, 0x20, 0x00, 0x62, 0x23, 0xb8, 0x70, 0x66, 0x10, 0xc0, 0x20, 0x00, 0x62, 0x64, 0xf2, 0xc0, 
+        0x20, 0x00, 0x52, 0x23, 0xb9, 0xc0, 0x20, 0x00, 0x52, 0x64, 0xf3, 0xc0, 0x20, 0x00, 0x32, 0x23, 
+        0xba, 0xc0, 0x20, 0x00, 0x32, 0x64, 0xf4, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x31, 0x8a, 
+        0xce, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x82, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x68, 0x83, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xdc, 0x82, 0x01, 0x8a, 0xcd, 0x21, 0x83, 0xce, 0xfc, 0x13, 0xc0, 
+        0x20, 0x00, 0x32, 0x22, 0x8f, 0x00, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x62, 0x8f, 0x46, 0x06, 
+        0x00, 0x66, 0x12, 0x0a, 0x2d, 0x03, 0x31, 0xf5, 0xff, 0x85, 0x02, 0x00, 0xc6, 0x02, 0x00, 0x66, 
+        0x22, 0x08, 0x8c, 0x54, 0x2d, 0x03, 0x3d, 0x04, 0x85, 0x01, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x42, 0x22, 0x91, 0x00, 0x44, 0x10, 0xc0, 0x20, 0x00, 0x42, 0x62, 
+        0x91, 0x86, 0xf9, 0xff, 0x7c, 0xfa, 0x81, 0x6e, 0xe7, 0x71, 0xb6, 0xf4, 0x51, 0x75, 0xcd, 0x61, 
+        0x6e, 0xce, 0x16, 0x12, 0x06, 0xc0, 0x20, 0x00, 0xb2, 0x26, 0x91, 0x50, 0xbb, 0x10, 0xc0, 0x20, 
+        0x00, 0xb2, 0x66, 0x91, 0xb2, 0x03, 0x03, 0x92, 0x03, 0x01, 0x42, 0x03, 0x00, 0x80, 0x99, 0x11, 
+        0x90, 0x44, 0x20, 0x92, 0x03, 0x02, 0x80, 0xbb, 0x01, 0x00, 0x99, 0x11, 0xb0, 0x99, 0x20, 0x90, 
+        0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x66, 0x8c, 0x22, 0x03, 0x05, 0xb2, 0x03, 0x04, 0x80, 0x22, 
+        0x11, 0x20, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x66, 0x8d, 0xc0, 0x20, 0x00, 0xa2, 0x66, 0x90, 
+        0xc0, 0x20, 0x00, 0x72, 0x66, 0x91, 0xc0, 0x20, 0x00, 0x92, 0x26, 0x91, 0x80, 0x99, 0x20, 0xc0, 
+        0x20, 0x00, 0x92, 0x66, 0x91, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x42, 0x26, 0x8f, 0x50, 0x44, 0x10, 
+        0xc0, 0x20, 0x00, 0x42, 0x66, 0x8f, 0x42, 0x03, 0x03, 0x22, 0x03, 0x01, 0xb2, 0x03, 0x00, 0x80, 
+        0x22, 0x11, 0x20, 0xbb, 0x20, 0x22, 0x03, 0x02, 0x80, 0x44, 0x01, 0x00, 0x22, 0x11, 0x40, 0x22, 
+        0x20, 0x20, 0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x66, 0x8a, 0x92, 0x03, 0x05, 0x42, 0x03, 0x04, 
+        0x80, 0x99, 0x11, 0x90, 0x44, 0x20, 0xc0, 0x20, 0x00, 0x42, 0x66, 0x8b, 0xc0, 0x20, 0x00, 0xa2, 
+        0x66, 0x8e, 0xc0, 0x20, 0x00, 0x72, 0x66, 0x8f, 0xc0, 0x20, 0x00, 0x22, 0x26, 0x8f, 0x80, 0x22, 
+        0x20, 0xc0, 0x20, 0x00, 0x22, 0x66, 0x8f, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x41, 0x41, 0xcd, 0x51, 
+        0x3a, 0xce, 0x8c, 0xf2, 0xc0, 0x20, 0x00, 0x32, 0x25, 0x91, 0x40, 0x33, 0x10, 0xc0, 0x20, 0x00, 
+        0x32, 0x65, 0x91, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x22, 0x25, 0x8f, 0x40, 0x22, 0x10, 0xc0, 0x20, 
+        0x00, 0x22, 0x65, 0x8f, 0x0d, 0xf0, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 
+        0x02, 0x85, 0xd8, 0xff, 0x21, 0xb6, 0xfe, 0x20, 0x2c, 0xa0, 0x02, 0x22, 0x18, 0xc8, 0x11, 0x1b, 
+        0x00, 0x02, 0x62, 0x18, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x21, 0x27, 0xce, 0xc0, 
+        0x20, 0x00, 0x22, 0x22, 0xb0, 0x20, 0x20, 0xb4, 0x0d, 0xf0, 0x00, 0x00, 0x41, 0x42, 0xd1, 0x31, 
+        0x22, 0xce, 0xc0, 0x20, 0x00, 0x22, 0x23, 0xb0, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 0x63, 
+        0xb0, 0x0d, 0xf0, 0x00, 0x7c, 0x08, 0x20, 0x70, 0x34, 0x51, 0x1b, 0xce, 0xc0, 0x20, 0x00, 0x62, 
+        0x25, 0xac, 0x80, 0x66, 0x10, 0x70, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x65, 0xac, 0x6c, 0xc4, 
+        0x20, 0x44, 0xd1, 0x71, 0x33, 0xd1, 0x5a, 0x44, 0xc0, 0x20, 0x00, 0x62, 0x24, 0xe9, 0x70, 0x66, 
+        0x10, 0xc0, 0x20, 0x00, 0x62, 0x64, 0xe9, 0x51, 0xa9, 0xda, 0xc0, 0x20, 0x00, 0x32, 0x24, 0xe9, 
+        0x50, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x64, 0xe9, 0x0d, 0xf0, 0x00, 0x6c, 0xc4, 0x51, 0x0a, 
+        0xce, 0x20, 0x44, 0xd1, 0x5a, 0x44, 0x51, 0x20, 0xd5, 0xc0, 0x20, 0x00, 0x32, 0x24, 0xe9, 0x50, 
+        0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 0x64, 0xe9, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x3f, 
+        0x20, 0x84, 0x34, 0x20, 0x72, 0x14, 0x80, 0x83, 0x41, 0x80, 0x77, 0x90, 0x81, 0xfc, 0xff, 0x70, 
+        0x70, 0x74, 0xe0, 0x77, 0x11, 0x8a, 0x77, 0x42, 0xd7, 0x0c, 0x0c, 0xf8, 0xc0, 0x20, 0x00, 0x72, 
+        0xd7, 0x0c, 0x42, 0x24, 0x26, 0x7c, 0xf9, 0x20, 0x64, 0x24, 0x1c, 0xc5, 0xe0, 0x66, 0x11, 0x60, 
+        0x55, 0xc0, 0x50, 0x50, 0x74, 0x00, 0x15, 0x40, 0x00, 0x88, 0xa1, 0x00, 0x15, 0x40, 0x90, 0x88, 
+        0x30, 0x80, 0x84, 0x10, 0x00, 0x63, 0xa1, 0x80, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x67, 0x26, 
+        0x00, 0x05, 0x40, 0x40, 0x20, 0x91, 0x20, 0x20, 0x34, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xd0, 0x09, 
+        0x21, 0x49, 0x81, 0x29, 0x01, 0x29, 0x71, 0x39, 0x11, 0xc9, 0x31, 0xe9, 0x51, 0xd9, 0x41, 0xf9, 
+        0x61, 0xdd, 0x02, 0x0c, 0x0f, 0x16, 0xb2, 0x08, 0xe1, 0xe3, 0xcd, 0xcd, 0x0f, 0xc0, 0x20, 0x00, 
+        0xa2, 0x0d, 0x03, 0xb2, 0xa0, 0x80, 0xa0, 0xa0, 0x64, 0xb0, 0xaa, 0x20, 0xc0, 0x20, 0x00, 0xa2, 
+        0x4d, 0x03, 0xc0, 0x20, 0x00, 0x82, 0x0d, 0x03, 0x92, 0xa0, 0xbf, 0x90, 0x88, 0x10, 0xf0, 0x88, 
+        0x20, 0xc0, 0x20, 0x00, 0x82, 0x4d, 0x03, 0xc0, 0x20, 0x00, 0x62, 0x0d, 0x03, 0x72, 0xa0, 0xdf, 
+        0x70, 0x66, 0x10, 0xf0, 0x66, 0x20, 0xc0, 0x20, 0x00, 0x62, 0x4d, 0x03, 0xc0, 0x20, 0x00, 0x52, 
+        0x1d, 0x00, 0x50, 0x50, 0xb4, 0x40, 0x55, 0x11, 0xc0, 0x20, 0x00, 0x42, 0x1d, 0x01, 0x00, 0x44, 
+        0x11, 0xc0, 0x20, 0x00, 0x62, 0x1d, 0x00, 0x60, 0x44, 0x20, 0xe0, 0x44, 0x10, 0x50, 0x44, 0x20, 
+        0xc0, 0x20, 0x00, 0x42, 0x5d, 0x00, 0x40, 0x40, 0xf5, 0xc0, 0x20, 0x00, 0x42, 0x5d, 0x01, 0xd0, 
+        0x2d, 0x20, 0x85, 0x47, 0x00, 0xc2, 0xcc, 0x01, 0xd2, 0x2d, 0x02, 0xc0, 0xc0, 0xf4, 0x56, 0xbd, 
+        0xf7, 0x46, 0x00, 0x00, 0xcd, 0x0f, 0xd8, 0x81, 0xc7, 0x1d, 0x11, 0x21, 0x9a, 0xfc, 0x31, 0x9a, 
+        0xfc, 0x42, 0xa4, 0x1b, 0x01, 0x4f, 0xcb, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x22, 0x21, 0x00, 
+        0x32, 0xa0, 0x00, 0x85, 0xd1, 0xfb, 0x16, 0x42, 0x01, 0x08, 0x11, 0xe8, 0x01, 0x28, 0x01, 0x07, 
+        0x1e, 0x63, 0x48, 0x81, 0x38, 0x22, 0x39, 0x71, 0xf9, 0x22, 0x0b, 0x44, 0x49, 0x81, 0x22, 0x21, 
+        0x07, 0x32, 0xa0, 0x01, 0x20, 0xc2, 0x20, 0x45, 0xcf, 0xfb, 0x8c, 0xf2, 0x58, 0x11, 0x57, 0x1c, 
+        0x44, 0x78, 0x81, 0x68, 0x2c, 0x69, 0x71, 0xf9, 0x2c, 0x0b, 0x77, 0x79, 0x81, 0x01, 0x09, 0xcf, 
+        0xc0, 0x00, 0x00, 0x01, 0x86, 0xfc, 0x08, 0x00, 0x48, 0x71, 0x88, 0x10, 0x58, 0x20, 0xcc, 0xe8, 
+        0x28, 0x71, 0x29, 0x10, 0x31, 0x9a, 0xe7, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x82, 0x46, 0x00, 0x00, 
+        0x49, 0x25, 0x78, 0x81, 0x62, 0x10, 0x00, 0x88, 0x11, 0x89, 0x20, 0x7a, 0x66, 0x62, 0x50, 0x00, 
+        0x01, 0xfe, 0xce, 0xc0, 0x00, 0x00, 0xc8, 0x31, 0xd8, 0x41, 0xe8, 0x51, 0xf8, 0x61, 0x08, 0x21, 
+        0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x39, 0x01, 0x09, 0x11, 0xd9, 
+        0x31, 0xc9, 0x21, 0xdd, 0x04, 0xcd, 0x02, 0x16, 0x52, 0x08, 0x0c, 0x08, 0x92, 0xa0, 0xdf, 0xa2, 
+        0xa0, 0xbf, 0xb2, 0xa0, 0x80, 0x61, 0x8f, 0xcd, 0x0c, 0x00, 0xc0, 0x20, 0x00, 0x32, 0x02, 0x03, 
+        0x30, 0x30, 0x64, 0xb0, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x42, 0x03, 0xc0, 0x20, 0x00, 0x72, 
+        0x02, 0x03, 0xa0, 0x77, 0x10, 0x80, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x42, 0x03, 0xc0, 0x20, 
+        0x00, 0x52, 0x02, 0x03, 0x90, 0x55, 0x10, 0x80, 0x55, 0x20, 0xc0, 0x20, 0x00, 0x52, 0x42, 0x03, 
+        0xc0, 0x20, 0x00, 0x42, 0x12, 0x00, 0x40, 0x40, 0xb4, 0x40, 0x44, 0x11, 0xc0, 0x20, 0x00, 0x32, 
+        0x12, 0x01, 0x00, 0x33, 0x11, 0xc0, 0x20, 0x00, 0x52, 0x12, 0x00, 0x50, 0x33, 0x20, 0x60, 0x33, 
+        0x10, 0x40, 0x33, 0x20, 0xc0, 0x20, 0x00, 0x32, 0x52, 0x00, 0x30, 0x30, 0xf5, 0xc0, 0x20, 0x00, 
+        0x1b, 0x00, 0x32, 0x52, 0x01, 0x28, 0x22, 0x00, 0x00, 0xf4, 0x56, 0xc2, 0xf8, 0x46, 0x00, 0x00, 
+        0x0c, 0x00, 0x07, 0x1d, 0x11, 0x21, 0x4b, 0xfc, 0x31, 0x4c, 0xfc, 0x42, 0xa4, 0x51, 0x01, 0x00, 
+        0xcb, 0xc0, 0x00, 0x00, 0x06, 0xff, 0xff, 0x01, 0xcb, 0xce, 0xc0, 0x00, 0x00, 0x01, 0x47, 0xfc, 
+        0x08, 0x00, 0x48, 0x30, 0x38, 0x40, 0xcc, 0xc4, 0xc9, 0x30, 0x21, 0x5c, 0xe7, 0xc0, 0x20, 0x00, 
+        0xc2, 0x62, 0x83, 0x46, 0x00, 0x00, 0xc9, 0x23, 0x42, 0x00, 0x02, 0x58, 0x01, 0x59, 0x40, 0xda, 
+        0x44, 0x42, 0x40, 0x02, 0x01, 0xc1, 0xce, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0xd8, 0x31, 0x08, 0x11, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf2, 0x3f, 0x00, 0x06, 0xf2, 0x3f, 
+        0x08, 0x14, 0xf2, 0x3f, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xb2, 0x05, 0x05, 0xa2, 0x05, 0x04, 0x80, 
+        0xbb, 0x11, 0xba, 0xaa, 0x66, 0x52, 0x06, 0x0c, 0x19, 0x0c, 0x12, 0x46, 0x00, 0x00, 0x0c, 0x09, 
+        0x79, 0x21, 0x81, 0xf5, 0xff, 0x72, 0x05, 0x01, 0xb2, 0x05, 0x00, 0x80, 0x77, 0x11, 0x7a, 0xbb, 
+        0x72, 0x05, 0x03, 0x52, 0x05, 0x02, 0x80, 0x77, 0x01, 0x00, 0x55, 0x11, 0x7a, 0x55, 0x5a, 0xbb, 
+        0x60, 0x56, 0xa0, 0xd0, 0x55, 0x11, 0x8a, 0x85, 0x26, 0x12, 0x09, 0x0c, 0x60, 0xa6, 0x66, 0x06, 
+        0x0c, 0x20, 0x46, 0x00, 0x00, 0x0c, 0x70, 0xc0, 0x20, 0x00, 0x20, 0x74, 0x01, 0x00, 0x00, 0x24, 
+        0xb2, 0x68, 0x80, 0x90, 0x90, 0x14, 0xa0, 0xb0, 0xf4, 0x00, 0x99, 0x11, 0xba, 0x99, 0xb0, 0x00, 
+        0x01, 0x20, 0xb0, 0x24, 0xe0, 0xbb, 0x01, 0x0a, 0xbb, 0xba, 0x99, 0x30, 0xb0, 0x04, 0x80, 0xbb, 
+        0x01, 0xba, 0x77, 0x9a, 0x77, 0xc0, 0x20, 0x00, 0x72, 0x68, 0x81, 0x00, 0x16, 0x40, 0x0c, 0x10, 
+        0x00, 0x00, 0xa1, 0xc0, 0x20, 0x00, 0x81, 0xd9, 0xff, 0x72, 0x28, 0x83, 0x00, 0x77, 0x20, 0xc0, 
+        0x20, 0x00, 0x72, 0x68, 0x83, 0x98, 0x11, 0x78, 0x21, 0xf6, 0x23, 0x11, 0xa6, 0x26, 0x0e, 0x91, 
+        0x0b, 0xfc, 0x98, 0x09, 0x90, 0x93, 0xa0, 0x88, 0x69, 0x80, 0x80, 0x20, 0x89, 0x69, 0x3d, 0x07, 
+        0x21, 0xd0, 0xff, 0x48, 0x41, 0x2a, 0x25, 0x01, 0xf5, 0xcd, 0xc0, 0x00, 0x00, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xff, 0xff, 0x1f, 0xff, 0x71, 0xc9, 0xff, 0x00, 0x12, 0x40, 0x0c, 0x18, 
+        0x7c, 0xf9, 0x00, 0x88, 0xa1, 0x90, 0x88, 0x30, 0xc0, 0x20, 0x00, 0x62, 0x27, 0x83, 0x80, 0x66, 
+        0x10, 0xc0, 0x20, 0x00, 0x62, 0x67, 0x83, 0x51, 0xc0, 0xff, 0x20, 0x42, 0xa0, 0x50, 0x44, 0xb0, 
+        0x51, 0xf5, 0xff, 0xc0, 0x20, 0x00, 0x32, 0x24, 0x81, 0x50, 0x33, 0x10, 0xc0, 0x20, 0x00, 0x32, 
+        0x64, 0x81, 0x0d, 0xf0, 0x03, 0x03, 0x03, 0x00, 0x61, 0xff, 0xff, 0x71, 0x78, 0xd6, 0x51, 0xb7, 
+        0xff, 0xdc, 0x72, 0xc0, 0x20, 0x00, 0x62, 0x65, 0x80, 0xec, 0x63, 0xc0, 0x20, 0x00, 0x22, 0x25, 
+        0x80, 0x70, 0x22, 0x20, 0xc0, 0x20, 0x00, 0x22, 0x65, 0x80, 0x0d, 0xf0, 0xc0, 0x20, 0x00, 0x62, 
+        0x65, 0x81, 0xcc, 0xd3, 0xc0, 0x20, 0x00, 0x32, 0x25, 0x81, 0x70, 0x33, 0x20, 0xc0, 0x20, 0x00, 
+        0x32, 0x65, 0x81, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xe0, 0x09, 0x41, 0x71, 0x7b, 0xfe, 
+        0x21, 0x05, 0xde, 0x31, 0xa6, 0xff, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x80, 0xc0, 0x20, 0x00, 0x0c, 
+        0x04, 0x5d, 0x07, 0x0c, 0x06, 0x22, 0x63, 0x81, 0x0c, 0x60, 0x0c, 0x32, 0x0c, 0x03, 0x09, 0x01, 
+        0x05, 0xe8, 0xff, 0x0c, 0x32, 0x0c, 0x13, 0x0c, 0x16, 0x71, 0x70, 0xfe, 0x0c, 0x64, 0x49, 0x01, 
+        0x5d, 0x07, 0x0c, 0x04, 0xc5, 0xe6, 0xff, 0x0c, 0x05, 0xc0, 0x20, 0x00, 0x61, 0x98, 0xff, 0x08, 
+        0x41, 0x12, 0xc1, 0x20, 0x52, 0x66, 0x82, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x61, 0xcc, 0xfb, 0x41, 
+        0x93, 0xff, 0x68, 0x06, 0x51, 0xf0, 0xdd, 0x60, 0x62, 0xa0, 0x68, 0x66, 0xcc, 0x72, 0xc0, 0x20, 
+        0x00, 0x52, 0x64, 0x80, 0x46, 0x01, 0x00, 0xc0, 0x20, 0x00, 0x52, 0x64, 0x81, 0x7c, 0xf8, 0x80, 
+        0x86, 0x30, 0xc0, 0x20, 0x00, 0x72, 0x24, 0x83, 0x80, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x72, 0x64, 
+        0x83, 0x0d, 0xf0, 0x00, 0x05, 0x00, 0x00, 0xc0, 0xb2, 0x03, 0x03, 0xa2, 0x03, 0x01, 0x6c, 0x88, 
+        0x91, 0xd3, 0xe6, 0x20, 0x88, 0xd1, 0x9a, 0x88, 0x92, 0x03, 0x00, 0x80, 0xaa, 0x11, 0xa0, 0x99, 
+        0x20, 0xa2, 0x03, 0x02, 0x80, 0xbb, 0x01, 0x00, 0xaa, 0x11, 0xb0, 0xaa, 0x20, 0xa0, 0x99, 0x20, 
+        0xc0, 0x20, 0x00, 0x92, 0x68, 0xd5, 0x72, 0x03, 0x05, 0xb2, 0x03, 0x04, 0x80, 0x77, 0x11, 0x70, 
+        0xbb, 0x20, 0xc0, 0x20, 0x00, 0xb2, 0x68, 0xd4, 0x60, 0xa0, 0x64, 0x50, 0x90, 0xb4, 0x30, 0xaa, 
+        0x11, 0xa0, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x40, 0x70, 0x34, 0x92, 0x68, 0xd6, 0x91, 0xe9, 0xff, 
+        0x40, 0x77, 0x11, 0x90, 0x77, 0x20, 0xc0, 0x20, 0x00, 0x72, 0x68, 0xd3, 0x0d, 0xf0, 0x00, 0x00, 
+        0x4c, 0x01, 0xf2, 0x3f, 0x0c, 0x03, 0x6c, 0x84, 0x51, 0xfe, 0xff, 0x20, 0x44, 0xd1, 0x5a, 0x44, 
+        0xc0, 0x20, 0x00, 0x39, 0x04, 0x0d, 0xf0, 0x00, 0x61, 0xb5, 0xe6, 0xc0, 0x20, 0x00, 0x92, 0x26, 
+        0xdd, 0x90, 0x9c, 0x34, 0x92, 0x42, 0x00, 0xc0, 0x20, 0x00, 0x82, 0x26, 0xdd, 0x80, 0x80, 0xb4, 
+        0x82, 0x53, 0x00, 0xc0, 0x20, 0x00, 0x72, 0x26, 0xda, 0x79, 0x04, 0xc0, 0x20, 0x00, 0x62, 0x26, 
+        0xd9, 0x69, 0x05, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x41, 0xd2, 0xcf, 0x31, 0xa8, 0xe6, 0xc0, 0x20, 
+        0x00, 0x22, 0x23, 0x81, 0x40, 0x22, 0x10, 0xc0, 0x20, 0x00, 0x22, 0x63, 0x81, 0x0d, 0xf0, 0x00, 
+        0x41, 0x17, 0xd6, 0x31, 0xa2, 0xe6, 0xc0, 0x20, 0x00, 0x22, 0x23, 0x81, 0x40, 0x22, 0x20, 0xc0, 
+        0x20, 0x00, 0x22, 0x63, 0x81, 0x0d, 0xf0, 0x00, 0xef, 0xbe, 0xad, 0xde, 0x68, 0x12, 0x31, 0xfe, 
+        0xff, 0x39, 0x06, 0xc0, 0x20, 0x00, 0x52, 0x12, 0x00, 0x48, 0x12, 0x50, 0x50, 0xb4, 0x5a, 0x44, 
+        0x39, 0x04, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc0, 0x20, 0x00, 0x48, 0x22, 0x32, 0x12, 
+        0x00, 0x08, 0x12, 0x30, 0x30, 0xb4, 0x3a, 0x00, 0x31, 0xf4, 0xff, 0x08, 0x00, 0x48, 0x14, 0x37, 
+        0x10, 0x11, 0x21, 0x74, 0xfb, 0x31, 0x74, 0xfb, 0x42, 0xa5, 0x16, 0x01, 0x29, 0xca, 0xc0, 0x00, 
+        0x00, 0x06, 0xff, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x11, 0x09, 0x01, 0x08, 0x72, 0xd9, 0x21, 0x02, 0x10, 0x00, 0xdd, 0x02, 0x00, 0x00, 0xb4, 0x47, 
+        0x60, 0x16, 0xc8, 0x02, 0x28, 0x12, 0x38, 0x2c, 0x37, 0x12, 0x0d, 0x2d, 0x0c, 0x45, 0xfa, 0xff, 
+        0xc8, 0x2c, 0x48, 0x1d, 0x58, 0x2c, 0x57, 0x94, 0xf1, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x92, 0xa2, 0x83, 0x72, 0xa0, 0x83, 0x81, 0xb5, 0xda, 0x62, 0xc2, 0x3c, 
+        0x0c, 0xe3, 0x52, 0xc2, 0x78, 0x12, 0xc1, 0xd0, 0xd9, 0x31, 0x09, 0x11, 0xc9, 0x21, 0xf9, 0x51, 
+        0xe9, 0x41, 0x59, 0x61, 0xe1, 0xb3, 0xda, 0x0c, 0x0f, 0xcd, 0x02, 0x02, 0xa0, 0x9c, 0xdd, 0x02, 
+        0x39, 0xcd, 0x0a, 0x0d, 0x32, 0xa0, 0x83, 0x22, 0xa0, 0xa8, 0x2a, 0x2d, 0x29, 0x01, 0x79, 0xdc, 
+        0xd7, 0x1c, 0x23, 0x67, 0x1c, 0x09, 0xa8, 0x61, 0xa7, 0x1c, 0x04, 0x99, 0xdc, 0x32, 0xa2, 0x83, 
+        0xd7, 0x1c, 0x13, 0x67, 0x1c, 0x10, 0xb8, 0x61, 0x28, 0x01, 0xb7, 0x1c, 0x09, 0x27, 0x1c, 0x06, 
+        0x7c, 0xd4, 0x40, 0x33, 0x10, 0x39, 0xdc, 0x69, 0x71, 0x52, 0x0c, 0x3a, 0x09, 0x81, 0xc7, 0x30, 
+        0x08, 0xe2, 0x5c, 0x1c, 0x07, 0x9c, 0x02, 0x82, 0x5c, 0x1c, 0xdc, 0x45, 0x22, 0x1c, 0x1c, 0x45, 
+        0x08, 0x00, 0x08, 0x81, 0x68, 0x71, 0x72, 0xa0, 0x83, 0x81, 0x95, 0xda, 0x92, 0xa2, 0x83, 0x22, 
+        0x4c, 0x3a, 0x5b, 0xee, 0x32, 0xa0, 0x83, 0xa2, 0x0c, 0x3b, 0x1b, 0xff, 0xcc, 0xda, 0xb2, 0x0c, 
+        0x3d, 0x80, 0xbb, 0x01, 0xb0, 0xb8, 0x31, 0xf0, 0xbb, 0x11, 0xb2, 0x4c, 0x3b, 0x28, 0xcd, 0xcb, 
+        0xcc, 0x27, 0x2f, 0x89, 0xc8, 0x21, 0xd8, 0x31, 0xe8, 0x41, 0xf8, 0x51, 0x08, 0x11, 0x12, 0xc1, 
+        0x30, 0x0d, 0xf0, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 0x02, 0x0c, 0x00, 0x09, 
+        0x12, 0x02, 0x42, 0x28, 0xc5, 0xf2, 0xff, 0x2d, 0x0c, 0x85, 0xe7, 0x01, 0x2d, 0x0c, 0x85, 0x61, 
+        0x00, 0x21, 0xa2, 0xca, 0xc5, 0xc0, 0x00, 0x2d, 0x0c, 0x45, 0x65, 0x00, 0xc8, 0x11, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xb3, 0x09, 0x00, 0x00, 0x99, 0xf6, 0xff, 0xff, 
+        0x30, 0xf6, 0xff, 0xff, 0x61, 0xfd, 0xff, 0x71, 0xfd, 0xff, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 
+        0x01, 0x74, 0xda, 0x77, 0x63, 0x11, 0x07, 0x12, 0x3c, 0x27, 0x36, 0x27, 0x70, 0x22, 0x80, 0x32, 
+        0xa0, 0x05, 0x45, 0xe3, 0x01, 0x06, 0x05, 0x00, 0x07, 0x12, 0x2a, 0x27, 0x36, 0x0c, 0x7a, 0x22, 
+        0x0c, 0x53, 0x45, 0xe2, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xf2, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x01, 0xef, 0xff, 0x32, 0xa0, 0x14, 0x00, 0x22, 0x80, 0xc5, 0xeb, 0x01, 
+        0x22, 0xc2, 0x0f, 0x86, 0xf9, 0xff, 0x0c, 0xe2, 0x46, 0xf8, 0xff, 0x00, 0xcc, 0x22, 0x0c, 0x02, 
+        0x0d, 0xf0, 0x51, 0x74, 0xf2, 0x57, 0x12, 0x04, 0x22, 0x02, 0x06, 0x0d, 0xf0, 0x2d, 0x05, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x67, 0x09, 0x00, 0x00, 0xa4, 0x08, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 
+        0x0c, 0xe7, 0x0c, 0xd8, 0x61, 0xfc, 0xff, 0x91, 0xfc, 0xff, 0x77, 0x63, 0x0d, 0x77, 0x12, 0x1f, 
+        0x27, 0xb8, 0x15, 0x20, 0x22, 0xa0, 0x90, 0x22, 0xa0, 0x0d, 0xf0, 0x77, 0x12, 0x11, 0x27, 0xb8, 
+        0x07, 0x1c, 0xa3, 0x27, 0xb3, 0xec, 0x61, 0xf5, 0xff, 0x20, 0x22, 0xa0, 0x6a, 0x22, 0x0d, 0xf0, 
+        0x21, 0x4c, 0xda, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x68, 0xc2, 0xa6, 0x16, 0x1a, 0x60, 0x76, 0x90, 
+        0x20, 0x77, 0xa0, 0x82, 0x12, 0x1c, 0x98, 0xd2, 0x87, 0x93, 0x07, 0x47, 0x09, 0x04, 0x22, 0xc2, 
+        0x34, 0x0d, 0xf0, 0xcb, 0x22, 0x77, 0x92, 0xea, 0x0c, 0x02, 0x0d, 0xf0, 0x68, 0xc2, 0xa6, 0x16, 
+        0x1a, 0x60, 0x76, 0x90, 0x20, 0x77, 0xa0, 0x82, 0x02, 0x3a, 0x98, 0xd2, 0x87, 0x93, 0x07, 0x47, 
+        0x09, 0x04, 0x22, 0xc2, 0x34, 0x0d, 0xf0, 0xcb, 0x22, 0x77, 0x92, 0xea, 0x0c, 0x02, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0x52, 0x61, 0x01, 0x02, 0x61, 0x02, 0xc9, 0x31, 0x49, 0x01, 0xcd, 0x02, 0x21, 
+        0x57, 0xca, 0xc0, 0x4c, 0x11, 0x4a, 0x22, 0x9b, 0x22, 0x0c, 0x64, 0x01, 0xcc, 0xcc, 0xc0, 0x00, 
+        0x00, 0x2d, 0x0c, 0x38, 0x01, 0x48, 0x11, 0x45, 0x08, 0x00, 0x00, 0x1c, 0x40, 0x51, 0x4f, 0xca, 
+        0x0c, 0x13, 0x22, 0x05, 0x28, 0x00, 0x33, 0xa1, 0x30, 0x22, 0x20, 0x20, 0x20, 0x74, 0x22, 0x45, 
+        0x28, 0x45, 0x85, 0x01, 0x20, 0x20, 0x74, 0xc8, 0x31, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x31, 0x47, 0xca, 0x32, 0x03, 0x28, 0x00, 0x02, 0x40, 0x30, 0x20, 0x91, 0x20, 0x20, 0x04, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x00, 0x01, 0x40, 0xca, 0x42, 0xa0, 0x01, 
+        0x02, 0x00, 0x28, 0x00, 0x02, 0x40, 0x00, 0x30, 0x91, 0x07, 0x63, 0x1d, 0x00, 0x12, 0x40, 0x00, 
+        0x34, 0xa1, 0x42, 0xaf, 0xff, 0x40, 0x33, 0x30, 0x41, 0x39, 0xca, 0x30, 0x30, 0x10, 0x32, 0x44, 
+        0x28, 0x45, 0x9d, 0xfe, 0x01, 0x36, 0xca, 0x02, 0x00, 0x28, 0x00, 0x20, 0x20, 0x85, 0x7f, 0x01, 
+        0x20, 0x20, 0x74, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x80, 0x00, 0x00, 0x51, 0x30, 0xca, 0xc0, 
+        0x62, 0x11, 0x6a, 0x55, 0x39, 0x45, 0x42, 0x45, 0x14, 0x0d, 0xf0, 0x00, 0x41, 0x2c, 0xca, 0xc0, 
+        0x52, 0x11, 0x5a, 0x44, 0x38, 0x44, 0x0c, 0x02, 0x26, 0x13, 0x07, 0x72, 0x04, 0x14, 0x0c, 0x16, 
+        0x70, 0x26, 0x83, 0x20, 0x20, 0x74, 0x0d, 0xf0, 0x31, 0x25, 0xca, 0xc0, 0x22, 0x11, 0x2a, 0x23, 
+        0x22, 0x02, 0x15, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x31, 0x21, 0xca, 0xc0, 0x22, 0x11, 0x2a, 0x23, 
+        0x22, 0x02, 0x16, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x41, 0x1d, 0xca, 0xc0, 0x52, 0x11, 0x5a, 0x44, 
+        0x32, 0x44, 0x15, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x41, 0x19, 0xca, 0xc0, 0x52, 0x11, 0x5a, 0x44, 
+        0x32, 0x44, 0x16, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x31, 0x15, 0xca, 0xc0, 0x22, 0x11, 0x2a, 0x23, 
+        0x22, 0x02, 0x14, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x2c, 0x8e, 0xfe, 0x3f, 0xc0, 0x87, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x58, 0x02, 0x02, 0xa0, 0xc0, 0x07, 0x45, 0x14, 0x32, 0xa4, 0x80, 
+        0x37, 0x45, 0x0e, 0x42, 0xa0, 0xa0, 0x47, 0xc5, 0x0d, 0x0c, 0x12, 0x08, 0x01, 0x12, 0xc1, 0x10, 
+        0x0d, 0xf0, 0x0c, 0x22, 0xc6, 0xfc, 0xff, 0x42, 0x12, 0x02, 0x31, 0xf4, 0xff, 0x21, 0xf2, 0xff, 
+        0x01, 0x40, 0xc9, 0xc0, 0x00, 0x00, 0xc6, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x11, 0xc9, 0x21, 0x29, 0x01, 0xcd, 0x03, 0x4a, 0x23, 0x0c, 0x43, 0x01, 0x10, 0xef, 0xc0, 0x00, 
+        0x00, 0x4d, 0x02, 0x02, 0xa1, 0x00, 0x27, 0xb0, 0x04, 0x0c, 0x02, 0x06, 0x07, 0x00, 0x32, 0xa0, 
+        0x04, 0x22, 0xa0, 0x41, 0x27, 0xb4, 0x02, 0x32, 0xa0, 0x05, 0x0c, 0x02, 0xc5, 0x6c, 0xf7, 0x8c, 
+        0x82, 0x38, 0x02, 0x38, 0x13, 0x48, 0x01, 0x3a, 0x3c, 0x39, 0x04, 0xc8, 0x21, 0x08, 0x11, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xd0, 0xc9, 0x41, 0x59, 0x11, 0x09, 0x31, 0xf9, 0x71, 0xd9, 
+        0x51, 0xe9, 0x61, 0xdd, 0x07, 0xed, 0x02, 0xf8, 0xc1, 0x2d, 0x03, 0x29, 0x21, 0x08, 0x02, 0x3d, 
+        0x06, 0x39, 0x01, 0x68, 0x72, 0x0c, 0xc3, 0x68, 0x06, 0x30, 0x34, 0x10, 0x87, 0x76, 0x06, 0xc8, 
+        0x10, 0x4b, 0xcc, 0x46, 0x00, 0x00, 0xc8, 0x10, 0x0c, 0x10, 0x42, 0x4c, 0x00, 0x4b, 0x2c, 0x52, 
+        0xcc, 0x10, 0xab, 0x6c, 0x69, 0x81, 0x59, 0x91, 0x66, 0x83, 0x27, 0x3d, 0x0f, 0x0c, 0x64, 0x02, 
+        0x4c, 0x01, 0x01, 0x52, 0xcc, 0xc0, 0x00, 0x00, 0x28, 0x81, 0x38, 0x01, 0x0c, 0x64, 0x01, 0x4f, 
+        0xcc, 0xc0, 0x00, 0x00, 0x28, 0x91, 0x3d, 0x0d, 0x0c, 0x64, 0x01, 0x4c, 0xcc, 0xc0, 0x00, 0x00, 
+        0x86, 0x09, 0x00, 0x0c, 0x04, 0x3d, 0x0d, 0x42, 0x4c, 0x01, 0x0c, 0x64, 0x01, 0x48, 0xcc, 0xc0, 
+        0x00, 0x00, 0x28, 0x81, 0x38, 0x01, 0x0c, 0x64, 0x01, 0x45, 0xcc, 0xc0, 0x00, 0x00, 0x3d, 0x0f, 
+        0x28, 0x91, 0x0c, 0x64, 0x01, 0x42, 0xcc, 0xc0, 0x00, 0x00, 0x0c, 0x05, 0x52, 0x5c, 0x01, 0x9c, 
+        0x1e, 0x88, 0x11, 0xe0, 0x88, 0x90, 0x62, 0x18, 0x03, 0x1b, 0x76, 0x72, 0x58, 0x03, 0xc0, 0x66, 
+        0x11, 0x62, 0x5c, 0x0b, 0x92, 0x0d, 0x00, 0x08, 0x31, 0x07, 0x69, 0x2a, 0xb8, 0x21, 0xb8, 0x7b, 
+        0xd2, 0xa4, 0x00, 0xe8, 0x0b, 0x0c, 0x2f, 0xe0, 0xc0, 0x54, 0xe0, 0xe6, 0x41, 0xf0, 0xee, 0x20, 
+        0xa0, 0xee, 0x11, 0xe0, 0xcc, 0x20, 0xc0, 0xa0, 0x54, 0xc0, 0xc6, 0x41, 0xd0, 0xcc, 0x20, 0xa0, 
+        0xcc, 0x11, 0xc0, 0xaa, 0x20, 0xa9, 0x0b, 0xc8, 0x41, 0xd8, 0x51, 0xe8, 0x61, 0xf8, 0x71, 0x12, 
+        0xc1, 0x30, 0x0d, 0xf0, 0x60, 0x8e, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x48, 0x72, 0x09, 0x01, 0x38, 
+        0x04, 0x08, 0x02, 0x87, 0x73, 0x06, 0x08, 0x10, 0x4b, 0x00, 0x46, 0x00, 0x00, 0x08, 0x10, 0x42, 
+        0x04, 0x0f, 0x21, 0xf8, 0xff, 0x32, 0x10, 0x00, 0x01, 0xe6, 0xc8, 0xc0, 0x00, 0x00, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xd9, 0x21, 0xc9, 0x11, 0x09, 
+        0x01, 0xcd, 0x02, 0x0c, 0x10, 0x02, 0x42, 0x00, 0x02, 0x03, 0x00, 0x0c, 0x8d, 0x07, 0x2d, 0x01, 
+        0xdd, 0x00, 0xd2, 0x4c, 0x01, 0x1b, 0x33, 0x2b, 0x2c, 0x4d, 0x0d, 0x01, 0x14, 0xcc, 0xc0, 0x00, 
+        0x00, 0xca, 0x2d, 0x08, 0x01, 0xc8, 0x11, 0xd8, 0x21, 0x2b, 0x22, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0xc9, 0x21, 0x09, 0x11, 0xcd, 0x02, 0x02, 0x03, 0x00, 0x0c, 0x82, 0x07, 0xb2, 
+        0x1c, 0x9b, 0x33, 0x2b, 0x2c, 0x3c, 0x25, 0x42, 0xc0, 0xf8, 0x49, 0x01, 0x52, 0x4c, 0x00, 0x42, 
+        0x4c, 0x01, 0x01, 0x06, 0xcc, 0xc0, 0x00, 0x00, 0x08, 0x01, 0xca, 0xc0, 0x2b, 0xcc, 0x2d, 0x0c, 
+        0x08, 0x11, 0xc8, 0x21, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x42, 
+        0x42, 0x01, 0x09, 0x01, 0xd9, 0x21, 0xc9, 0x11, 0xdd, 0x02, 0xcd, 0x04, 0x0c, 0x00, 0x02, 0x42, 
+        0x00, 0x8c, 0x64, 0x2b, 0x22, 0x01, 0xf9, 0xcb, 0xc0, 0x00, 0x00, 0xca, 0x2d, 0x08, 0x01, 0xc8, 
+        0x11, 0xd8, 0x21, 0x2b, 0x22, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x78, 0x8e, 0xfe, 0x3f, 
+        0x12, 0xc1, 0xc0, 0xc9, 0xd1, 0x39, 0x81, 0x59, 0x61, 0x69, 0x51, 0x09, 0xc1, 0x01, 0x77, 0xc9, 
+        0x79, 0x91, 0x22, 0x20, 0x38, 0x49, 0x71, 0xcc, 0x32, 0x3c, 0x54, 0x46, 0x01, 0x00, 0x42, 0x12, 
+        0x00, 0x42, 0xc4, 0x35, 0x22, 0xc1, 0x10, 0x32, 0xa0, 0x18, 0x05, 0xdc, 0xff, 0x20, 0xc2, 0x20, 
+        0x56, 0xd2, 0x01, 0x21, 0x6e, 0xc9, 0x22, 0x22, 0x38, 0x0c, 0x03, 0xcc, 0x12, 0x86, 0x00, 0x00, 
+        0x32, 0x12, 0x00, 0x21, 0xee, 0xff, 0x01, 0xa6, 0xc8, 0xc0, 0x00, 0x00, 0x0c, 0x12, 0x86, 0x45, 
+        0x00, 0x38, 0x51, 0x48, 0x91, 0x28, 0x41, 0x45, 0xf7, 0xff, 0x0d, 0x02, 0x29, 0xa1, 0x31, 0x63, 
+        0xc9, 0x29, 0x41, 0x32, 0x23, 0x38, 0x39, 0xb1, 0x9c, 0x83, 0x48, 0xb1, 0x28, 0xa1, 0x2b, 0x34, 
+        0x42, 0x14, 0x00, 0x01, 0xd6, 0xcb, 0xc0, 0x00, 0x00, 0x08, 0xb1, 0x28, 0xa1, 0x02, 0x10, 0x00, 
+        0x2a, 0x00, 0x09, 0x41, 0x52, 0x2c, 0x00, 0x62, 0x25, 0x01, 0x60, 0x60, 0xc0, 0x62, 0x5c, 0x08, 
+        0x02, 0xa0, 0x80, 0xc0, 0x20, 0x00, 0xb2, 0x05, 0x03, 0xb0, 0xb0, 0x64, 0x00, 0xbb, 0x20, 0xc0, 
+        0x20, 0x00, 0xb2, 0x45, 0x03, 0xa2, 0xa0, 0xbf, 0x42, 0xa0, 0x40, 0xc0, 0x20, 0x00, 0x92, 0x05, 
+        0x03, 0xa0, 0x99, 0x10, 0x40, 0x99, 0x20, 0xc0, 0x20, 0x00, 0x92, 0x45, 0x03, 0x82, 0xa0, 0xdf, 
+        0xc0, 0x20, 0x00, 0x72, 0x05, 0x03, 0x80, 0x77, 0x10, 0xc0, 0x20, 0x00, 0x72, 0x45, 0x03, 0x60, 
+        0x60, 0xb4, 0x40, 0x66, 0x11, 0x71, 0xef, 0xca, 0xc0, 0x20, 0x00, 0x32, 0x15, 0x01, 0x00, 0x33, 
+        0x11, 0xc0, 0x20, 0x00, 0x82, 0x15, 0x00, 0x80, 0x33, 0x20, 0x70, 0x33, 0x10, 0x60, 0x33, 0x20, 
+        0xc0, 0x20, 0x00, 0x32, 0x55, 0x00, 0x30, 0x30, 0xf5, 0xc0, 0x20, 0x00, 0x68, 0x81, 0x78, 0x71, 
+        0x32, 0x55, 0x01, 0x28, 0x61, 0x3d, 0x0c, 0x1c, 0x05, 0x29, 0x01, 0x0c, 0x02, 0x45, 0xd2, 0xff, 
+        0x0c, 0x19, 0x22, 0xa0, 0xf0, 0xa2, 0x01, 0x40, 0x48, 0x7c, 0x72, 0xa0, 0x8f, 0x58, 0x04, 0x62, 
+        0x04, 0x06, 0x50, 0x30, 0x54, 0x70, 0x66, 0x10, 0x50, 0x56, 0x41, 0x62, 0x44, 0x06, 0x08, 0x7c, 
+        0x1c, 0x06, 0x60, 0x55, 0x20, 0xa0, 0x55, 0x11, 0x50, 0x33, 0x20, 0x39, 0x04, 0xb2, 0x00, 0x04, 
+        0x00, 0x1a, 0x40, 0x20, 0xbb, 0x10, 0x0c, 0x72, 0x20, 0xbb, 0x20, 0xb2, 0x40, 0x04, 0x88, 0x7c, 
+        0x00, 0x99, 0xa1, 0x92, 0x48, 0x0e, 0x71, 0xd0, 0xca, 0x2d, 0x0c, 0xc0, 0x20, 0x00, 0x72, 0x27, 
+        0x80, 0x79, 0x48, 0xc5, 0xba, 0xfa, 0x0c, 0x02, 0xc8, 0xd1, 0x08, 0xc1, 0x12, 0xc1, 0x40, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0xb8, 0xdc, 0x10, 0x40, 0x32, 0xa0, 0x02, 0x41, 0x93, 0xc9, 0x12, 0xc1, 
+        0xf0, 0x20, 0x52, 0x20, 0x02, 0x61, 0x00, 0x08, 0xb5, 0x21, 0xfa, 0xff, 0x40, 0x00, 0x20, 0x09, 
+        0xb5, 0x05, 0xca, 0xfa, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x98, 0xbd, 0xff, 0x3f, 
+        0xe8, 0xe3, 0x10, 0x40, 0xdc, 0xbd, 0xff, 0x3f, 0xfc, 0xe3, 0x10, 0x40, 0xa0, 0xbd, 0xff, 0x3f, 
+        0x88, 0xe4, 0x10, 0x40, 0xb4, 0xbd, 0xff, 0x3f, 0x60, 0xe4, 0x10, 0x40, 0x30, 0xe3, 0x10, 0x40, 
+        0x42, 0xa0, 0x14, 0x32, 0xa1, 0x68, 0x52, 0xa0, 0x78, 0x12, 0xc1, 0xf0, 0x62, 0xa0, 0xff, 0x02, 
+        0x61, 0x00, 0x01, 0xf2, 0xff, 0x02, 0x62, 0x00, 0x62, 0x40, 0xc3, 0x52, 0x60, 0x17, 0x22, 0xc0, 
+        0x30, 0x32, 0x60, 0x19, 0x42, 0x60, 0x18, 0x31, 0xee, 0xff, 0x0c, 0x04, 0x01, 0x14, 0xcc, 0xc0, 
+        0x00, 0x00, 0x21, 0xec, 0xff, 0x31, 0xec, 0xff, 0x0c, 0x04, 0x01, 0x10, 0xcc, 0xc0, 0x00, 0x00, 
+        0x21, 0xeb, 0xff, 0x31, 0xeb, 0xff, 0x42, 0xc2, 0xfc, 0x01, 0x0c, 0xcc, 0xc0, 0x00, 0x00, 0x21, 
+        0xe9, 0xff, 0x31, 0xe9, 0xff, 0x0c, 0x04, 0x01, 0x09, 0xcc, 0xc0, 0x00, 0x00, 0x21, 0xe7, 0xff, 
+        0x0c, 0x13, 0x05, 0xc1, 0xfa, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0xc0, 0xe1, 0x10, 0x40, 
+        0x12, 0xc1, 0xf0, 0x52, 0x61, 0x01, 0x02, 0x61, 0x02, 0xc2, 0x61, 0x03, 0x49, 0x01, 0xcd, 0x02, 
+        0x0c, 0x04, 0x2d, 0x03, 0x31, 0xfa, 0xff, 0x05, 0x57, 0x00, 0x66, 0x32, 0x04, 0x7c, 0xf2, 0x46, 
+        0x0d, 0x00, 0x0c, 0x10, 0x28, 0x11, 0x31, 0xd1, 0xff, 0x48, 0x01, 0xc9, 0x13, 0x42, 0x63, 0x1b, 
+        0x22, 0x63, 0x1c, 0x02, 0x43, 0x75, 0xc7, 0xec, 0x10, 0x0c, 0x06, 0x52, 0x03, 0xc3, 0x72, 0xa1, 
+        0x00, 0x70, 0x7c, 0x10, 0x70, 0x56, 0x93, 0x52, 0x43, 0x74, 0x22, 0xa0, 0x00, 0x85, 0x0d, 0xfe, 
+        0x22, 0xa0, 0x00, 0x85, 0x3e, 0x00, 0x0c, 0x02, 0xc8, 0x31, 0x08, 0x21, 0x12, 0xc1, 0x10, 0x0d, 
+        0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x01, 0xc0, 0xff, 0x22, 0x00, 0x75, 0x07, 
+        0x62, 0x16, 0x22, 0xc0, 0x44, 0x29, 0x01, 0x01, 0xe4, 0xcb, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x0c, 
+        0x03, 0x0c, 0x04, 0x01, 0xe3, 0xcb, 0xc0, 0x00, 0x00, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x85, 0x2e, 0x00, 0x8c, 0x42, 0xc5, 0x01, 0x00, 0x86, 0x01, 0x00, 
+        0x0c, 0x02, 0x0c, 0x03, 0x85, 0x15, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0xc0, 0xe0, 0x10, 0x40, 0x00, 0xe1, 0x10, 0x40, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xab, 0xff, 
+        0x6d, 0x02, 0x28, 0x10, 0x51, 0xbe, 0xc8, 0xe7, 0xe2, 0x10, 0x42, 0x20, 0x18, 0x58, 0x15, 0x32, 
+        0x20, 0x17, 0x52, 0xc5, 0xfb, 0x50, 0x34, 0x83, 0x86, 0x00, 0x00, 0x32, 0x20, 0x19, 0x60, 0x26, 
+        0x20, 0x41, 0xf3, 0xff, 0x51, 0xf4, 0xff, 0x72, 0x00, 0x75, 0x82, 0xa0, 0x08, 0x80, 0x77, 0x20, 
+        0x72, 0x40, 0x75, 0xc5, 0x4e, 0x00, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 
+        0x0c, 0x24, 0x52, 0xa0, 0xf7, 0x61, 0x99, 0xff, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x32, 0x06, 0x75, 
+        0x08, 0x16, 0x50, 0x33, 0x10, 0x32, 0x46, 0x75, 0x40, 0x33, 0x20, 0x32, 0x46, 0x75, 0xe7, 0xe0, 
+        0x12, 0x78, 0x02, 0x97, 0xe7, 0x0d, 0x00, 0x8d, 0x04, 0x0c, 0x09, 0x92, 0x46, 0xc2, 0x82, 0x46, 
+        0xc2, 0x45, 0x1a, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0xc8, 0xbd, 0xff, 0x3f, 
+        0x21, 0xff, 0xff, 0x12, 0xc1, 0xf0, 0x39, 0x11, 0x09, 0x01, 0x01, 0xaf, 0xcb, 0xc0, 0x00, 0x00, 
+        0x31, 0x87, 0xff, 0x08, 0x11, 0x22, 0x03, 0x75, 0x52, 0xa0, 0xf7, 0x37, 0x62, 0x57, 0x50, 0x42, 
+        0x10, 0x42, 0x43, 0x75, 0x21, 0x84, 0xff, 0x16, 0x00, 0x02, 0x01, 0xa7, 0xcb, 0xc0, 0x00, 0x00, 
+        0x22, 0xa0, 0x00, 0x61, 0x7e, 0xff, 0x32, 0xa0, 0x01, 0x52, 0x06, 0x75, 0x72, 0xa0, 0xfb, 0x70, 
+        0x55, 0x10, 0x52, 0x46, 0x75, 0x85, 0x07, 0x00, 0x86, 0x08, 0x00, 0x08, 0x13, 0x87, 0x60, 0x0b, 
+        0x01, 0x9e, 0xcb, 0xc0, 0x00, 0x00, 0x85, 0xef, 0xff, 0x46, 0x04, 0x00, 0x97, 0xe0, 0x05, 0x01, 
+        0x9a, 0xcb, 0xc0, 0x00, 0x00, 0x22, 0xa0, 0x00, 0x32, 0xa0, 0x00, 0x45, 0x05, 0x00, 0x02, 0x21, 
+        0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x17, 0x62, 0xaa, 0x52, 0xa0, 0xfd, 0x86, 0xe7, 0xff, 0x00, 
+        0x12, 0xc1, 0xf0, 0x02, 0x61, 0x01, 0x01, 0x69, 0xff, 0x02, 0x00, 0x75, 0x07, 0x60, 0x23, 0x85, 
+        0x4e, 0x00, 0x21, 0x68, 0xff, 0x22, 0x61, 0x00, 0x01, 0x8c, 0xcb, 0xc0, 0x00, 0x00, 0x22, 0x21, 
+        0x00, 0x0c, 0x03, 0x0c, 0x04, 0x01, 0x8a, 0xcb, 0xc0, 0x00, 0x00, 0x31, 0x60, 0xff, 0x0c, 0x02, 
+        0x22, 0x43, 0x75, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x98, 0x8e, 0xfe, 0x3f, 
+        0x21, 0xff, 0xff, 0x12, 0xc1, 0xf0, 0x32, 0x61, 0x00, 0xd9, 0x31, 0xc9, 0x21, 0xd1, 0x57, 0xff, 
+        0x09, 0x11, 0xc2, 0x2d, 0x1b, 0x01, 0xa6, 0xc7, 0xc0, 0x00, 0x00, 0x05, 0x4d, 0x00, 0xc5, 0x3a, 
+        0x00, 0x32, 0xa0, 0xfa, 0x22, 0x0d, 0x75, 0x0c, 0x00, 0x09, 0x1d, 0x30, 0x22, 0x10, 0x22, 0x4d, 
+        0x75, 0x21, 0x50, 0xff, 0x01, 0x75, 0xcb, 0xc0, 0x00, 0x00, 0x41, 0x60, 0xc8, 0x0c, 0x05, 0x48, 
+        0x14, 0x52, 0x6d, 0x1b, 0x66, 0x54, 0x0b, 0x0c, 0x22, 0x0c, 0x03, 0x0c, 0x04, 0x05, 0xe0, 0xfe, 
+        0xc6, 0x02, 0x00, 0x22, 0xa0, 0x00, 0x32, 0xa0, 0x00, 0x42, 0xa0, 0x00, 0x05, 0xdf, 0xfe, 0x8c, 
+        0x6c, 0x22, 0x2d, 0x1c, 0x38, 0x01, 0xc0, 0x0c, 0x00, 0x22, 0xa0, 0x00, 0x85, 0xed, 0xfd, 0x22, 
+        0xa0, 0x00, 0x45, 0xbf, 0xf2, 0xc8, 0x21, 0xd8, 0x31, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0xc9, 0x11, 0xd9, 0x21, 0xcd, 0x02, 0xdd, 0x05, 0xf6, 0x32, 0x21, 
+        0x01, 0x37, 0xff, 0x66, 0x15, 0x16, 0x5d, 0x00, 0x20, 0x22, 0xb0, 0x50, 0x22, 0xa0, 0x42, 0x62, 
+        0x1e, 0x22, 0xc2, 0x7c, 0x01, 0xbe, 0xca, 0xc0, 0x00, 0x00, 0x01, 0x30, 0xff, 0x0a, 0x6c, 0xd2, 
+        0x46, 0xc0, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0xf6, 0x32, 0x12, 0x0c, 0x03, 0x51, 0x29, 0xff, 0x20, 0x42, 0xb0, 0x50, 0x44, 0xa0, 0x5a, 0x52, 
+        0x32, 0x45, 0xc0, 0x32, 0x64, 0x1e, 0x0d, 0xf0, 0x12, 0xc1, 0xe0, 0xc9, 0x51, 0xc1, 0x23, 0xff, 
+        0x09, 0x41, 0x02, 0x0c, 0xc2, 0x51, 0x59, 0xfb, 0xf6, 0x20, 0x16, 0xca, 0x20, 0x22, 0x02, 0xc0, 
+        0x8c, 0x32, 0x0c, 0x13, 0x46, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x74, 0x02, 0x4c, 0xc2, 0x66, 
+        0x20, 0xe8, 0x32, 0xa0, 0x00, 0x16, 0xc3, 0x05, 0xc0, 0x30, 0x80, 0x32, 0x03, 0xc0, 0x91, 0x2b, 
+        0xc8, 0x66, 0x23, 0x1c, 0x50, 0x45, 0x20, 0x0c, 0x02, 0x0c, 0x06, 0x0c, 0x07, 0x32, 0x09, 0xe4, 
+        0x0c, 0x18, 0x89, 0x01, 0xc0, 0x33, 0x11, 0x3a, 0x39, 0x9b, 0x33, 0x45, 0xaa, 0xff, 0xc6, 0x0a, 
+        0x00, 0x66, 0x13, 0x28, 0x00, 0x30, 0xb0, 0xc0, 0x33, 0xa0, 0x02, 0x23, 0x1e, 0x16, 0xc0, 0x01, 
+        0x50, 0x45, 0x20, 0x22, 0xa0, 0x00, 0x00, 0x70, 0x74, 0x62, 0xc3, 0x7c, 0x0c, 0x18, 0x32, 0x09, 
+        0xe4, 0x89, 0x01, 0xc0, 0x33, 0x11, 0x3a, 0x39, 0x9b, 0x33, 0x45, 0xa7, 0xff, 0x92, 0x0c, 0xc2, 
+        0x1b, 0x99, 0x92, 0x4c, 0xc2, 0xc8, 0x51, 0x08, 0x41, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x05, 0xf6, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 
+        0x0c, 0xd2, 0x0c, 0x03, 0x71, 0x0e, 0xc8, 0x52, 0xa0, 0xff, 0x61, 0xf8, 0xfe, 0x12, 0xc1, 0xf0, 
+        0xd9, 0x21, 0xc9, 0x11, 0x09, 0x01, 0x42, 0x06, 0xc3, 0x02, 0x06, 0x74, 0x40, 0xc4, 0x90, 0x50, 
+        0x44, 0xc0, 0x70, 0xcc, 0xa0, 0xc2, 0xcc, 0x34, 0x40, 0xc3, 0x83, 0x07, 0x32, 0x39, 0xa2, 0x27, 
+        0x37, 0x0c, 0xe8, 0x21, 0xab, 0xe2, 0xb1, 0xb1, 0xc8, 0xd8, 0x16, 0x91, 0x8e, 0xe9, 0xb0, 0xbd, 
+        0x10, 0x90, 0x9d, 0x10, 0x20, 0xdd, 0x10, 0x00, 0x20, 0x90, 0x70, 0x22, 0xa0, 0x58, 0xd2, 0x22, 
+        0xc2, 0x34, 0x07, 0x65, 0x07, 0x17, 0x65, 0x04, 0x9c, 0x99, 0xa7, 0x92, 0x17, 0x1b, 0x00, 0x00, 
+        0x00, 0x74, 0x02, 0x46, 0x74, 0x87, 0x90, 0xde, 0x0c, 0x02, 0xc8, 0x11, 0xd8, 0x21, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x8c, 0x1b, 0xc7, 0x92, 0xe2, 0x8c, 0x1d, 0x97, 0xe5, 0xdd, 0x1b, 
+        0x30, 0x32, 0x46, 0x74, 0x86, 0xf8, 0xff, 0x00, 0x0c, 0x04, 0x71, 0xec, 0xc7, 0x7c, 0xd6, 0x0c, 
+        0xe5, 0x1b, 0x84, 0x40, 0x34, 0x90, 0x70, 0x33, 0xa0, 0x28, 0xd3, 0x80, 0x40, 0x74, 0x60, 0x22, 
+        0x10, 0x29, 0xd3, 0x57, 0x94, 0xea, 0x0d, 0xf0, 0x22, 0xa0, 0x00, 0x12, 0xc1, 0xf0, 0x02, 0x61, 
+        0x00, 0xc5, 0x23, 0x00, 0x02, 0x21, 0x00, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x12, 0xc1, 0xf0, 0x61, 
+        0xcb, 0xfe, 0x09, 0x01, 0x02, 0x06, 0x75, 0x22, 0xc6, 0x44, 0x07, 0x60, 0x24, 0x0c, 0xa3, 0x07, 
+        0x03, 0x0c, 0x0c, 0x03, 0x0c, 0x04, 0x01, 0xee, 0xca, 0xc0, 0x00, 0x00, 0x86, 0x04, 0x00, 0x48, 
+        0x16, 0x97, 0x64, 0x0a, 0x32, 0x26, 0x16, 0x0c, 0x04, 0x01, 0xe9, 0xca, 0xc0, 0x00, 0x00, 0x05, 
+        0xc2, 0xff, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x02, 
+        0x61, 0x00, 0x85, 0x2c, 0x00, 0x01, 0xb9, 0xfe, 0x22, 0x40, 0xc3, 0x02, 0x21, 0x00, 0x12, 0xc1, 
+        0x10, 0x80, 0x00, 0x00, 0x21, 0xb6, 0xfe, 0x28, 0x12, 0x0d, 0xf0, 0x00, 0xff, 0xbf, 0xff, 0xff, 
+        0x12, 0xc1, 0xf0, 0x41, 0xc6, 0xc7, 0x02, 0x61, 0x00, 0x02, 0x24, 0x0b, 0xe7, 0x60, 0x0d, 0x31, 
+        0xfb, 0xff, 0x22, 0xa0, 0x03, 0x30, 0x00, 0x10, 0x09, 0xb4, 0xc5, 0x9a, 0xf2, 0x08, 0x01, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0xa4, 0x8e, 0xfe, 0x3f, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x01, 0x02, 0x22, 
+        0x00, 0x22, 0xa0, 0x01, 0x09, 0x01, 0x45, 0x7c, 0xfa, 0x41, 0xb8, 0xc7, 0x31, 0x77, 0xdb, 0x08, 
+        0xb4, 0xec, 0x82, 0x28, 0x04, 0x31, 0xed, 0xff, 0x22, 0xc2, 0x1c, 0x30, 0x30, 0x10, 0x39, 0xb4, 
+        0x01, 0xc6, 0xca, 0xc0, 0x00, 0x00, 0x21, 0xf3, 0xff, 0x01, 0xed, 0xc6, 0xc0, 0x00, 0x00, 0x28, 
+        0x01, 0x0c, 0x33, 0x0c, 0x04, 0x0c, 0x05, 0x85, 0xaf, 0xff, 0x06, 0x01, 0x00, 0x30, 0x30, 0x20, 
+        0x39, 0xb4, 0x08, 0x11, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 
+        0x01, 0x01, 0xa6, 0xc7, 0x28, 0xb0, 0xe7, 0x62, 0x06, 0x28, 0x00, 0x4b, 0x22, 0x85, 0xf9, 0xff, 
+        0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x5c, 0xbe, 0xff, 0x3f, 0x7c, 0xbe, 0xff, 0x3f, 
+        0x64, 0xe6, 0x10, 0x40, 0x12, 0xc1, 0xf0, 0x02, 0x61, 0x01, 0xc2, 0x61, 0x02, 0x01, 0xfa, 0xff, 
+        0x20, 0xc2, 0x20, 0x29, 0x00, 0x01, 0xa3, 0xca, 0xc0, 0x00, 0x00, 0x22, 0xcc, 0x34, 0x29, 0x01, 
+        0x22, 0x6c, 0x37, 0x01, 0xa1, 0xca, 0xc0, 0x00, 0x00, 0x28, 0x01, 0x05, 0x1b, 0x00, 0x21, 0xf3, 
+        0xff, 0x31, 0xf3, 0xff, 0x0c, 0x04, 0x01, 0xa5, 0xca, 0xc0, 0x00, 0x00, 0xc8, 0x21, 0x08, 0x11, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 0x11, 0x09, 0x01, 0xcd, 
+        0x02, 0x01, 0xe9, 0xff, 0x2d, 0x04, 0x42, 0x00, 0x38, 0x52, 0x00, 0x39, 0x9c, 0x44, 0x29, 0x31, 
+        0x39, 0x21, 0xc7, 0xb5, 0x04, 0x0c, 0x32, 0xc6, 0x05, 0x00, 0xc5, 0x10, 0x00, 0x28, 0x31, 0x01, 
+        0xe2, 0xff, 0x38, 0x21, 0xc2, 0x40, 0x39, 0x39, 0x60, 0x29, 0x70, 0x0c, 0x16, 0x0c, 0x02, 0x62, 
+        0x40, 0x38, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x31, 0xdb, 0xff, 0x0c, 
+        0x02, 0x29, 0x73, 0x29, 0x63, 0x22, 0x43, 0x38, 0x22, 0x43, 0x39, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0xd4, 0xff, 0x78, 0x10, 0x8c, 0x37, 0x0c, 0x32, 0x86, 0x03, 
+        0x00, 0x29, 0x10, 0x39, 0x20, 0x49, 0x40, 0x59, 0x50, 0x69, 0x30, 0x05, 0x01, 0x00, 0x0c, 0x02, 
+        0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x60, 0xbe, 0xff, 0x3f, 0x12, 0xc1, 0xe0, 0xd9, 
+        0x41, 0xc9, 0x31, 0xd1, 0xc9, 0xff, 0x09, 0x21, 0xc8, 0x4d, 0x08, 0x3d, 0x09, 0x01, 0x45, 0x0f, 
+        0x00, 0x3d, 0x02, 0x28, 0x1d, 0x32, 0x13, 0x02, 0x42, 0x12, 0x02, 0x47, 0x13, 0x02, 0xc5, 0x0e, 
+        0x00, 0x48, 0x2d, 0xcc, 0xc4, 0x21, 0xf4, 0xff, 0x1c, 0x43, 0x01, 0x78, 0xc9, 0xc0, 0x00, 0x00, 
+        0x86, 0x05, 0x00, 0x21, 0xbe, 0xff, 0x29, 0x11, 0x01, 0x70, 0xca, 0xc0, 0x00, 0x00, 0x28, 0x11, 
+        0x38, 0x2d, 0x0c, 0x04, 0x01, 0x6f, 0xca, 0xc0, 0x00, 0x00, 0x8c, 0x5c, 0x28, 0x01, 0x0c, 0x03, 
+        0xc0, 0x0c, 0x00, 0xc8, 0x31, 0xd8, 0x41, 0x08, 0x21, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0x7c, 0xc3, 0x12, 0xc1, 0xf0, 0x09, 0x11, 0x01, 0xb0, 0xff, 0x29, 0x01, 0x37, 0x10, 0x1d, 0x2d, 
+        0x00, 0x38, 0x52, 0x39, 0x21, 0x4b, 0x22, 0x1c, 0x43, 0x01, 0x64, 0xc9, 0xc0, 0x00, 0x00, 0x58, 
+        0x21, 0x8c, 0x85, 0x21, 0xa9, 0xff, 0x38, 0x01, 0x28, 0x32, 0xc0, 0x05, 0x00, 0x08, 0x11, 0x12, 
+        0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x02, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x45, 0xfc, 0xff, 0x08, 0x01, 
+        0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0x09, 0x01, 0x01, 0x9e, 0xff, 
+        0x28, 0x10, 0x9c, 0x12, 0x2d, 0x00, 0x22, 0xc2, 0x20, 0x01, 0x4f, 0xca, 0xc0, 0x00, 0x00, 0x0c, 
+        0x42, 0xc5, 0xf9, 0xff, 0x01, 0x99, 0xff, 0x58, 0x60, 0x8c, 0x55, 0x0c, 0x43, 0x28, 0x70, 0xc0, 
+        0x05, 0x00, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x12, 0xc1, 0xf0, 0xc9, 
+        0x11, 0xc1, 0x32, 0xc7, 0x09, 0x01, 0xc2, 0x2c, 0x37, 0x85, 0x01, 0x00, 0x02, 0x12, 0x02, 0x22, 
+        0x1c, 0x02, 0x27, 0x10, 0x04, 0x2d, 0x0c, 0x45, 0x01, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x21, 0x89, 0xff, 0x28, 0xd2, 0x0d, 0xf0, 0x00, 0x32, 0xa0, 0x01, 0x42, 
+        0xa0, 0x00, 0x12, 0xc1, 0xf0, 0xc2, 0x61, 0x01, 0x09, 0x01, 0xcd, 0x02, 0x22, 0x12, 0x02, 0x45, 
+        0x61, 0xf3, 0x01, 0x2c, 0xca, 0xc0, 0x00, 0x00, 0x01, 0x80, 0xff, 0xc9, 0xd0, 0x01, 0x2a, 0xca, 
+        0xc0, 0x00, 0x00, 0xc8, 0x11, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 0x0c, 0x05, 0x61, 0x7a, 
+        0xff, 0x0c, 0xe7, 0x68, 0x06, 0x50, 0x85, 0x90, 0x60, 0x88, 0xa0, 0x82, 0x18, 0x1c, 0x27, 0x98, 
+        0x03, 0x2d, 0x05, 0x0d, 0xf0, 0x1b, 0x55, 0x50, 0x50, 0x74, 0x77, 0x95, 0xe7, 0x22, 0xa0, 0xff, 
+        0x0d, 0xf0, 0x00, 0x00, 0x70, 0x87, 0xfe, 0x3f, 0x2d, 0xf4, 0x51, 0x58, 0x2d, 0x7f, 0x95, 0x4c, 
+        0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0xf0, 0x7f, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x38, 
+        0xe0, 0x87, 0xfe, 0x3f, 0x41, 0xf8, 0xff, 0x48, 0x04, 0x0c, 0x03, 0x22, 0x64, 0x2a, 0x32, 0x64, 
+        0x2b, 0x0d, 0xf0, 0x00, 0x51, 0xf5, 0xff, 0x41, 0xf5, 0xff, 0x21, 0xf2, 0xff, 0x12, 0xc1, 0xf0, 
+        0x02, 0x61, 0x00, 0x22, 0x22, 0x00, 0x22, 0x61, 0x01, 0x32, 0x22, 0x2b, 0x22, 0x22, 0x2a, 0x05, 
+        0xaf, 0x00, 0x08, 0x11, 0x4d, 0x02, 0x1b, 0x22, 0x47, 0xb2, 0x14, 0x22, 0x60, 0x2a, 0x41, 0xc4, 
+        0xcb, 0x1b, 0x23, 0x22, 0x60, 0x2b, 0x40, 0x22, 0x10, 0x08, 0x01, 0x12, 0xc1, 0x10, 0x0d, 0xf0, 
+        0x22, 0x60, 0x2a, 0x32, 0x60, 0x2b, 0x21, 0xbe, 0xcb, 0x08, 0x01, 0x20, 0x23, 0x10, 0x12, 0xc1, 
+        0x10, 0x0d, 0xf0, 0x00, 0x67, 0xc3, 0x04, 0x70, 0x72, 0x11, 0x8c, 0x07, 0x0d, 0xf0, 0x2d, 0x03, 
+        0x0d, 0xf0, 0x00, 0x00, 0x80, 0x76, 0x11, 0x70, 0x33, 0x30, 0xc6, 0x3c, 0x00, 0x00, 0x00, 0x00, 
+        0x61, 0xdc, 0xff, 0x30, 0x72, 0x30, 0x96, 0xa7, 0xfe, 0x67, 0x42, 0xd7, 0x67, 0x43, 0xde, 0x20, 
+        0x77, 0x85, 0x30, 0x87, 0x85, 0x87, 0x37, 0x4c, 0x67, 0x03, 0x28, 0x60, 0x33, 0x20, 0x80, 0x33, 
+        0x11, 0x30, 0x38, 0x41, 0x80, 0xa7, 0xc0, 0xf6, 0xca, 0x29, 0x00, 0x0a, 0x40, 0x0c, 0x09, 0x90, 
+        0x93, 0x81, 0x30, 0x30, 0x91, 0x3a, 0x22, 0x20, 0xa7, 0x85, 0x77, 0x1a, 0x4a, 0x8d, 0x07, 0x46, 
+        0x15, 0x00, 0x00, 0x00, 0x70, 0x33, 0x11, 0x30, 0x39, 0x41, 0x67, 0x02, 0x04, 0x1b, 0x88, 0x46, 
+        0xf4, 0xff, 0x3a, 0x22, 0x0d, 0xf0, 0x00, 0x00, 0x70, 0x22, 0x11, 0x20, 0x29, 0x41, 0x1b, 0x77, 
+        0x46, 0x03, 0x00, 0x00, 0x00, 0x67, 0x02, 0xef, 0x60, 0x22, 0x20, 0x80, 0x22, 0x11, 0x20, 0x28, 
+        0x41, 0x70, 0xa8, 0xc0, 0xf6, 0xca, 0x1c, 0x00, 0x0a, 0x40, 0x00, 0x92, 0xa1, 0x20, 0x20, 0x91, 
+        0x3a, 0x22, 0x20, 0xa7, 0x85, 0x87, 0x9a, 0x0f, 0xd6, 0x69, 0x00, 0x1b, 0x22, 0xf0, 0x99, 0x11, 
+        0xac, 0xc9, 0x0d, 0xf0, 0x2d, 0x03, 0x0d, 0xf0, 0xad, 0x02, 0x20, 0x21, 0x41, 0x1b, 0x88, 0xa0, 
+        0x88, 0x01, 0x8a, 0x22, 0x67, 0x42, 0x08, 0x07, 0x6a, 0x03, 0x1b, 0x22, 0x9c, 0x09, 0x0d, 0xf0, 
+        0x20, 0x27, 0x85, 0x90, 0x22, 0x01, 0xf0, 0x88, 0x11, 0x80, 0x22, 0x20, 0x0d, 0xf0, 0x00, 0x00, 
+        0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x67, 0xc3, 0x05, 0x41, 0x54, 0xdb, 0x40, 0x22, 
+        0x20, 0x0d, 0xf0, 0x00, 0x80, 0x76, 0x11, 0x70, 0x23, 0x30, 0x0d, 0xf0, 0x80, 0x76, 0x11, 0x70, 
+        0x33, 0x30, 0xc6, 0xc8, 0xff, 0x00, 0x00, 0x00, 0x61, 0xa2, 0xff, 0x30, 0x72, 0x30, 0x96, 0xa7, 
+        0xfe, 0x67, 0x42, 0xd3, 0x67, 0x43, 0xdc, 0x20, 0x77, 0x75, 0x30, 0x87, 0x75, 0x37, 0x32, 0x4b, 
+        0x67, 0x03, 0x2d, 0x60, 0x33, 0x20, 0x80, 0x33, 0x11, 0x30, 0x38, 0x41, 0x80, 0xa7, 0xc0, 0xf6, 
+        0xca, 0x37, 0x00, 0x0a, 0x40, 0x0c, 0x09, 0x90, 0x93, 0x81, 0x30, 0x30, 0x91, 0x30, 0x22, 0xc0, 
+        0x90, 0x90, 0x60, 0x0b, 0xa2, 0x90, 0x2a, 0x93, 0x20, 0xa7, 0x75, 0x77, 0x1a, 0x51, 0xc6, 0x1b, 
+        0x00, 0x37, 0x12, 0x68, 0x70, 0x33, 0x11, 0x30, 0x39, 0x41, 0x67, 0x02, 0xce, 0x1b, 0x88, 0x46, 
+        0xf2, 0xff, 0x00, 0x00, 0x80, 0x76, 0x11, 0x70, 0x23, 0x30, 0x0d, 0xf0, 0x67, 0x02, 0x3c, 0x60, 
+        0x22, 0x20, 0x80, 0x22, 0x11, 0x20, 0x28, 0x41, 0x70, 0xa8, 0xc0, 0xf6, 0xca, 0xe5, 0x00, 0x0a, 
+        0x40, 0x0c, 0x09, 0x90, 0x92, 0x81, 0x20, 0x20, 0x91, 0x80, 0xb6, 0x11, 0xb0, 0x33, 0x30, 0x20, 
+        0x23, 0xc0, 0x90, 0x90, 0x60, 0x0b, 0xa2, 0x90, 0x2a, 0x93, 0x20, 0xa7, 0x75, 0x87, 0x9a, 0x20, 
+        0xd6, 0x69, 0x00, 0x1b, 0x22, 0xf0, 0x99, 0x11, 0xbc, 0xc9, 0x0d, 0xf0, 0x37, 0x12, 0x0d, 0x70, 
+        0x22, 0x11, 0x20, 0x29, 0x41, 0x67, 0x03, 0xbf, 0x1b, 0x77, 0x86, 0xee, 0xff, 0x0c, 0x02, 0x0d, 
+        0xf0, 0x70, 0x82, 0x11, 0xac, 0x88, 0x60, 0xf8, 0x40, 0x80, 0x89, 0x41, 0xa7, 0xa6, 0x2e, 0x1b, 
+        0x66, 0x00, 0x16, 0x40, 0x90, 0x88, 0x81, 0x00, 0x99, 0xa1, 0x20, 0x27, 0x85, 0x60, 0x22, 0xc0, 
+        0x90, 0x22, 0x01, 0x8a, 0x22, 0xc6, 0xed, 0xff, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 
+        0x16, 0x99, 0xfc, 0xb2, 0xca, 0xe8, 0x1c, 0x86, 0xb0, 0x6a, 0xa3, 0x86, 0xf4, 0xff, 0x6d, 0x0a, 
+        0x46, 0xf3, 0xff, 0x00, 0xf0, 0x22, 0x11, 0x20, 0x21, 0x41, 0xac, 0xe2, 0xa0, 0xf2, 0x40, 0xa2, 
+        0xca, 0xf8, 0x00, 0x1a, 0x40, 0x00, 0x22, 0xa1, 0x0c, 0x18, 0xa0, 0x88, 0xc0, 0xc6, 0x1e, 0x00, 
+        0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x9c, 0x23, 0xa0, 0xf3, 0x40, 0xa2, 0xca, 0xf8, 0x00, 0x1a, 
+        0x40, 0x00, 0x33, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x86, 0x18, 0x00, 0x70, 0x2f, 0x05, 0x10, 
+        0x22, 0x01, 0x06, 0x34, 0x00, 0xf0, 0x83, 0x11, 0xcc, 0x88, 0x41, 0xfc, 0xda, 0x40, 0x22, 0x20, 
+        0x86, 0x30, 0x00, 0x00, 0x67, 0xc3, 0x06, 0x70, 0x83, 0x11, 0x8c, 0x08, 0x2d, 0x03, 0x70, 0x7f, 
+        0x05, 0xf0, 0x22, 0x11, 0x00, 0x41, 0x40, 0x20, 0x27, 0x81, 0x06, 0x2a, 0x00, 0xf0, 0x82, 0x11, 
+        0x56, 0x88, 0xfe, 0x71, 0xf2, 0xda, 0x70, 0x23, 0x20, 0x46, 0x26, 0x00, 0x12, 0xc1, 0xe0, 0xc9, 
+        0x41, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x61, 0x42, 0xff, 0x30, 0x72, 0x30, 0x67, 0x42, 0xb4, 
+        0x67, 0x43, 0xd9, 0x20, 0x87, 0x75, 0x30, 0x97, 0x75, 0x16, 0x78, 0xf6, 0x16, 0x09, 0xf8, 0x9a, 
+        0x88, 0xa1, 0xf3, 0xc7, 0x60, 0x22, 0x20, 0xa0, 0x22, 0x10, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 
+        0x20, 0x40, 0xf5, 0x30, 0x50, 0xf5, 0x50, 0x62, 0xc1, 0x30, 0xb4, 0xc1, 0x0c, 0x09, 0xba, 0x66, 
+        0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x10, 0x40, 0x40, 0x60, 0x99, 0x81, 0x30, 0xb2, 0xc1, 0x00, 0x66, 
+        0xa1, 0xba, 0x66, 0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x50, 0x24, 0xc1, 0x9a, 0x22, 0x0c, 0x94, 0x20, 
+        0x5f, 0x41, 0x8c, 0x25, 0x0b, 0x44, 0x1b, 0x88, 0x00, 0x14, 0x40, 0x60, 0x22, 0x81, 0x00, 0x66, 
+        0xa1, 0x42, 0xa0, 0x80, 0x40, 0x88, 0xc0, 0x42, 0xa0, 0xfe, 0x47, 0xb8, 0x2f, 0xd6, 0x76, 0x00, 
+        0x1b, 0x22, 0xf0, 0x66, 0x11, 0x16, 0xb6, 0x01, 0x90, 0x88, 0x01, 0x8a, 0x22, 0x70, 0x7f, 0x05, 
+        0x10, 0x77, 0x01, 0x70, 0x22, 0x20, 0xc8, 0x41, 0xd8, 0x51, 0xe8, 0x61, 0xf8, 0x71, 0x12, 0xc1, 
+        0x20, 0x0d, 0xf0, 0x00, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x86, 0xf6, 0xff, 0x96, 0x88, 0x00, 
+        0x82, 0xa0, 0xff, 0x90, 0x28, 0x01, 0xc6, 0xf4, 0xff, 0x80, 0x80, 0x60, 0x9d, 0x06, 0x00, 0x08, 
+        0x40, 0xf6, 0xc8, 0x13, 0x00, 0x62, 0xa1, 0x20, 0x20, 0x91, 0x0c, 0x08, 0x16, 0xd9, 0xfa, 0x0c, 
+        0x19, 0x90, 0x66, 0x20, 0x46, 0xe9, 0xff, 0x00, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x06, 0xed, 
+        0xff, 0x00, 0x00, 0x00, 0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x9c, 0x33, 0xa0, 0xf3, 0x40, 0xa2, 
+        0xca, 0xf8, 0x00, 0x1a, 0x40, 0x00, 0x33, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x06, 0x1d, 0x00, 
+        0x00, 0xf0, 0x42, 0x11, 0x40, 0x41, 0x41, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x60, 0x22, 0x20, 
+        0xcc, 0x44, 0x41, 0xaa, 0xda, 0x40, 0x22, 0x20, 0x0d, 0xf0, 0x00, 0x00, 0xf0, 0x22, 0x11, 0x20, 
+        0x21, 0x41, 0x9c, 0x22, 0xa0, 0xf2, 0x40, 0xa2, 0xca, 0xf8, 0x00, 0x1a, 0x40, 0x00, 0x22, 0xa1, 
+        0x0c, 0x18, 0xa0, 0x88, 0xc0, 0xc6, 0x0f, 0x00, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x0d, 0xf0, 
+        0x30, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x22, 0x30, 0x67, 0xc3, 0x05, 0x41, 0x9c, 0xda, 0x40, 
+        0x22, 0x20, 0x0d, 0xf0, 0x70, 0x83, 0x11, 0x16, 0xd8, 0xfd, 0x2d, 0x03, 0x0d, 0xf0, 0x00, 0x00, 
+        0x61, 0xec, 0xfe, 0x30, 0x72, 0x30, 0x67, 0x42, 0xd6, 0x67, 0x43, 0xe7, 0x20, 0x87, 0x75, 0x30, 
+        0x97, 0x75, 0x16, 0xe9, 0xf6, 0x16, 0x38, 0xfa, 0x90, 0x88, 0xc0, 0xa1, 0x9d, 0xc7, 0x60, 0x22, 
+        0x20, 0xa0, 0x22, 0x10, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 0x27, 0x33, 0x04, 0xf0, 0x22, 0x11, 
+        0x0b, 0x88, 0x30, 0x22, 0xc0, 0xf0, 0x22, 0x11, 0x0c, 0x1a, 0x92, 0xa0, 0x17, 0xf0, 0xaa, 0x11, 
+        0x37, 0x32, 0x04, 0x1b, 0xaa, 0x30, 0x22, 0xc0, 0xf0, 0x22, 0x11, 0x0b, 0x99, 0x56, 0xc9, 0xfe, 
+        0x82, 0xc8, 0x7e, 0x42, 0xa0, 0xfe, 0x47, 0xb8, 0x17, 0x37, 0x32, 0x04, 0x1b, 0xaa, 0x37, 0x12, 
+        0x1a, 0x90, 0x88, 0x01, 0x8a, 0x2a, 0x70, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x22, 0x20, 0x0d, 
+        0xf0, 0x96, 0x08, 0x01, 0x1b, 0x84, 0x90, 0x28, 0x01, 0x46, 0xfa, 0xff, 0xa0, 0xa1, 0x41, 0xf0, 
+        0xaa, 0x11, 0xc6, 0xf6, 0xff, 0x80, 0x80, 0x60, 0x00, 0x08, 0x40, 0xf6, 0xc8, 0x22, 0x00, 0x6a, 
+        0xa1, 0xa0, 0xa0, 0x91, 0x0c, 0x08, 0x8c, 0x32, 0x0c, 0x19, 0x90, 0x66, 0x20, 0xd6, 0x06, 0xfc, 
+        0x1b, 0xaa, 0xf0, 0x66, 0x11, 0x56, 0x86, 0xfb, 0xa0, 0xa1, 0x41, 0xf0, 0xaa, 0x11, 0xc6, 0xeb, 
+        0xff, 0x70, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x61, 0xbd, 0xfe, 0x67, 
+        0x42, 0x22, 0x20, 0x47, 0x75, 0x42, 0xc4, 0x82, 0xe6, 0xc4, 0x20, 0xa6, 0x14, 0x29, 0x60, 0x72, 
+        0x20, 0x80, 0x57, 0x11, 0x00, 0x14, 0x40, 0x50, 0x50, 0x91, 0x50, 0x20, 0x60, 0x70, 0x25, 0xb3, 
+        0x0d, 0xf0, 0x00, 0x00, 0x00, 0x70, 0x42, 0x11, 0x8c, 0x04, 0x0c, 0x02, 0x80, 0x46, 0x11, 0x0b, 
+        0x54, 0x20, 0x45, 0xb3, 0x2d, 0x04, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 0x61, 0xad, 0xfe, 0x67, 
+        0x42, 0x25, 0x20, 0x47, 0x75, 0x42, 0xc4, 0x81, 0xe6, 0xc4, 0x25, 0x96, 0xe4, 0x02, 0x60, 0x72, 
+        0x20, 0x80, 0x57, 0x11, 0x1b, 0x44, 0x26, 0xc4, 0x27, 0x00, 0x14, 0x40, 0x50, 0x50, 0x91, 0x50, 
+        0x20, 0x60, 0x70, 0x25, 0xb3, 0x0d, 0xf0, 0x00, 0x70, 0x42, 0x11, 0x8c, 0x24, 0x7c, 0xf2, 0x0d, 
+        0xf0, 0x80, 0x46, 0x11, 0x7c, 0xf5, 0x20, 0x45, 0xb3, 0x2d, 0x04, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 
+        0xf0, 0x96, 0x32, 0x00, 0x2d, 0x05, 0x0d, 0xf0, 0x80, 0x26, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x20, 0xa3, 0x20, 0x16, 0x4a, 0x08, 0x9c, 0x53, 0xa0, 0xf3, 
+        0x40, 0xa2, 0xca, 0xf5, 0x00, 0x1a, 0x40, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x0c, 0x18, 0xa0, 
+        0x88, 0xc0, 0x86, 0x36, 0x00, 0xa0, 0xf2, 0x40, 0xa2, 0xca, 0xf5, 0x6c, 0x18, 0xa0, 0x88, 0xc0, 
+        0x00, 0x1a, 0x40, 0x96, 0x9a, 0x00, 0x00, 0x32, 0xa1, 0x0c, 0x02, 0x46, 0x30, 0x00, 0x00, 0x00, 
+        0x20, 0x30, 0x91, 0x00, 0x22, 0xa1, 0x86, 0x2d, 0x00, 0xf0, 0x55, 0x11, 0x50, 0x51, 0x41, 0x40, 
+        0xa5, 0x20, 0xbc, 0xba, 0x9c, 0x55, 0xa0, 0xf5, 0x40, 0xa2, 0xca, 0xf5, 0x00, 0x1a, 0x40, 0x40, 
+        0x55, 0x81, 0x00, 0x44, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x46, 0x25, 0x00, 0xa0, 0xf4, 0x40, 
+        0xa2, 0xca, 0xf5, 0x6c, 0x19, 0xa0, 0x99, 0xc0, 0x00, 0x1a, 0x40, 0x96, 0x9a, 0x00, 0x00, 0x54, 
+        0xa1, 0x0c, 0x04, 0x06, 0x1f, 0x00, 0x00, 0x00, 0x40, 0x50, 0x91, 0x00, 0x44, 0xa1, 0x46, 0x1c, 
+        0x00, 0x70, 0x3f, 0x05, 0x10, 0x33, 0x01, 0x0c, 0x02, 0x46, 0x64, 0x00, 0xcc, 0xd4, 0xf0, 0x85, 
+        0x11, 0xcc, 0x88, 0x41, 0xf2, 0xc5, 0x40, 0x33, 0x20, 0x46, 0x60, 0x00, 0x00, 0x67, 0xc5, 0x0b, 
+        0x40, 0x85, 0x11, 0x40, 0x88, 0x20, 0x8c, 0x28, 0x3d, 0x05, 0x2d, 0x04, 0x70, 0x7f, 0x05, 0xf0, 
+        0x33, 0x11, 0x00, 0x41, 0x40, 0x30, 0x37, 0x81, 0x86, 0x58, 0x00, 0x00, 0x56, 0x82, 0xfe, 0xf0, 
+        0x83, 0x11, 0x56, 0x28, 0xfe, 0x71, 0xe5, 0xc5, 0x70, 0x35, 0x20, 0xc6, 0x53, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0xc9, 0x41, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x61, 0x5e, 0xfe, 0x50, 0x73, 
+        0x30, 0x67, 0x43, 0xa7, 0x67, 0x45, 0xd4, 0x30, 0x84, 0xa5, 0x50, 0x94, 0xa5, 0x16, 0xf8, 0xef, 
+        0x16, 0x59, 0xf4, 0x9a, 0x88, 0xa1, 0x58, 0xfe, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 0x60, 0x55, 
+        0x20, 0xa0, 0x55, 0x10, 0x79, 0x11, 0x20, 0xc0, 0xf5, 0x40, 0xd0, 0xf5, 0x30, 0xe0, 0xf5, 0x50, 
+        0xf0, 0xf5, 0xd0, 0xa2, 0xc1, 0x40, 0xbc, 0xc1, 0x0c, 0x09, 0xba, 0xaa, 0xb7, 0xba, 0x01, 0x1b, 
+        0x99, 0x10, 0x40, 0x40, 0xa0, 0x69, 0x81, 0x40, 0xb2, 0xc1, 0x00, 0xaa, 0xa1, 0xba, 0xaa, 0xb7, 
+        0xba, 0x02, 0x62, 0xc6, 0x01, 0x0c, 0x09, 0x50, 0xb2, 0xc1, 0xba, 0x66, 0xb7, 0xb6, 0x01, 0x1b, 
+        0x99, 0xd0, 0xbc, 0xc1, 0xb0, 0x66, 0x80, 0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x40, 0xb3, 0xc1, 0xba, 
+        0x66, 0xb7, 0xb6, 0x01, 0x1b, 0x99, 0x8c, 0x3a, 0x0c, 0x1b, 0xb0, 0x66, 0x20, 0xf0, 0x72, 0xc1, 
+        0x40, 0xbe, 0xc1, 0x0c, 0x0a, 0x7a, 0xbb, 0x77, 0xbb, 0x02, 0xa2, 0xca, 0x01, 0x50, 0x7c, 0xc1, 
+        0x70, 0xbb, 0x80, 0x77, 0xbb, 0x02, 0xa2, 0xca, 0x01, 0xd0, 0x73, 0xc1, 0x70, 0xbb, 0x80, 0x77, 
+        0xbb, 0x02, 0xa2, 0xca, 0x01, 0xb0, 0xaa, 0x81, 0x9a, 0xaa, 0x00, 0xbb, 0xa1, 0xba, 0x66, 0xb7, 
+        0xb6, 0x02, 0xa2, 0xca, 0x01, 0x0c, 0x09, 0xf0, 0x2c, 0xc1, 0xaa, 0x22, 0xa7, 0xb2, 0x01, 0x1b, 
+        0x99, 0x50, 0xa3, 0xc1, 0xa0, 0x22, 0x80, 0xa7, 0xb2, 0x02, 0x92, 0xc9, 0x01, 0xd0, 0xae, 0xc1, 
+        0xaa, 0x22, 0xa7, 0xb2, 0x02, 0x92, 0xc9, 0x01, 0xf0, 0xb3, 0xc1, 0x50, 0x7e, 0xc1, 0x0c, 0x0a, 
+        0x70, 0xbb, 0x80, 0x77, 0xbb, 0x02, 0xa2, 0xca, 0x01, 0xb0, 0xaa, 0x81, 0x9a, 0xaa, 0x00, 0xbb, 
+        0xa1, 0xba, 0x22, 0xb7, 0xb2, 0x01, 0x1b, 0xaa, 0xf0, 0x3e, 0xc1, 0xaa, 0x33, 0x78, 0x11, 0x0c, 
+        0xb4, 0x30, 0x59, 0x41, 0xcc, 0x45, 0x42, 0xc4, 0x01, 0x82, 0xc8, 0xff, 0x00, 0x14, 0x40, 0x20, 
+        0x33, 0x81, 0x60, 0x22, 0x81, 0x00, 0x66, 0xa1, 0x42, 0xa3, 0xff, 0x40, 0x88, 0xc0, 0xf0, 0x44, 
+        0x11, 0x47, 0xb8, 0x37, 0xd6, 0x86, 0x00, 0x1b, 0x22, 0xac, 0x82, 0xf0, 0x66, 0x11, 0x9c, 0xa6, 
+        0xc0, 0x88, 0x01, 0x8a, 0x33, 0x70, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x33, 0x20, 0xc8, 0x41, 
+        0xd8, 0x51, 0xe8, 0x61, 0xf8, 0x71, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x20, 0x21, 0x41, 0xf0, 
+        0x22, 0x11, 0x86, 0xf6, 0xff, 0x1b, 0x33, 0x46, 0xf5, 0xff, 0x00, 0x00, 0x96, 0x98, 0x00, 0x1b, 
+        0x84, 0xc0, 0x38, 0x01, 0x0c, 0x02, 0xc6, 0xf2, 0xff, 0x80, 0x80, 0x60, 0x9d, 0x06, 0x00, 0x08, 
+        0x40, 0xf6, 0xc8, 0x0b, 0x00, 0x62, 0xa1, 0x20, 0x23, 0x81, 0x30, 0x30, 0x91, 0x06, 0x04, 0x00, 
+        0xf6, 0xd8, 0x1c, 0x00, 0xa2, 0xa1, 0x20, 0x63, 0x81, 0x30, 0x20, 0x91, 0x0c, 0x03, 0xa0, 0x99, 
+        0x20, 0x0c, 0x08, 0x16, 0xd9, 0xf8, 0x0c, 0x19, 0x90, 0x66, 0x20, 0x46, 0xe1, 0xff, 0x00, 0x00, 
+        0x70, 0x3f, 0x05, 0x10, 0x33, 0x01, 0x0c, 0x02, 0x86, 0xe4, 0xff, 0x00, 0xf0, 0x55, 0x11, 0x50, 
+        0x51, 0x41, 0x40, 0xa5, 0x20, 0xbc, 0xba, 0x9c, 0x55, 0xa0, 0xf5, 0x40, 0xa2, 0xca, 0xf5, 0x00, 
+        0x1a, 0x40, 0x40, 0x55, 0x81, 0x00, 0x44, 0xa1, 0x0c, 0x19, 0xa0, 0x99, 0xc0, 0x06, 0x36, 0x00, 
+        0xa0, 0xf4, 0x40, 0xa2, 0xca, 0xf5, 0x6c, 0x19, 0xa0, 0x99, 0xc0, 0x00, 0x1a, 0x40, 0x96, 0x7a, 
+        0x00, 0x00, 0x54, 0xa1, 0x0c, 0x04, 0xc6, 0x2f, 0x00, 0x40, 0x50, 0x91, 0x00, 0x44, 0xa1, 0x86, 
+        0x2d, 0x00, 0x00, 0x00, 0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x30, 0x22, 0x20, 0x70, 0x3f, 0x05, 
+        0x10, 0x33, 0x01, 0x60, 0x33, 0x20, 0xcc, 0x42, 0x41, 0x5d, 0xc5, 0x40, 0x33, 0x20, 0x0c, 0x02, 
+        0x0d, 0xf0, 0x00, 0x00, 0xf0, 0x33, 0x11, 0x30, 0x31, 0x41, 0x20, 0xa3, 0x20, 0xbc, 0xba, 0x9c, 
+        0x53, 0xa0, 0xf3, 0x40, 0xa2, 0xca, 0xf5, 0x00, 0x1a, 0x40, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 
+        0x0c, 0x18, 0xa0, 0x88, 0xc0, 0xc6, 0x1c, 0x00, 0xa0, 0xf2, 0x40, 0xa2, 0xca, 0xf5, 0x6c, 0x18, 
+        0xa0, 0x88, 0xc0, 0x00, 0x1a, 0x40, 0x96, 0x7a, 0x00, 0x00, 0x32, 0xa1, 0x0c, 0x02, 0x86, 0x16, 
+        0x00, 0x20, 0x30, 0x91, 0x00, 0x22, 0xa1, 0x46, 0x14, 0x00, 0x00, 0x00, 0x70, 0x3f, 0x05, 0x10, 
+        0x33, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x50, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 0x33, 
+        0x30, 0x67, 0xc5, 0x05, 0x41, 0x42, 0xc5, 0x40, 0x33, 0x20, 0x0d, 0xf0, 0x40, 0x85, 0x11, 0x40, 
+        0x88, 0x20, 0x16, 0x68, 0xfd, 0x3d, 0x05, 0x2d, 0x04, 0x0d, 0xf0, 0x00, 0x47, 0x32, 0x37, 0x46, 
+        0x0f, 0x00, 0x00, 0x00, 0x61, 0xb8, 0xfd, 0x50, 0x73, 0x30, 0x67, 0x43, 0xca, 0x67, 0x45, 0xdb, 
+        0x30, 0x84, 0xa5, 0x50, 0x94, 0xa5, 0x16, 0x29, 0xf0, 0x16, 0x78, 0xf6, 0x90, 0x88, 0xc0, 0xa1, 
+        0xb2, 0xfd, 0x60, 0x33, 0x20, 0xa0, 0x33, 0x10, 0x60, 0x55, 0x20, 0xa0, 0x55, 0x10, 0x10, 0x4f, 
+        0x40, 0x37, 0x35, 0x0b, 0x37, 0x15, 0xc4, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x82, 0xc8, 0xff, 
+        0x50, 0x33, 0xc0, 0x47, 0xb2, 0x02, 0x32, 0xc3, 0xff, 0x40, 0x22, 0xc0, 0x20, 0x33, 0x81, 0x00, 
+        0x22, 0xa1, 0x0c, 0x0a, 0x0c, 0x1b, 0x3c, 0x49, 0xb0, 0xaa, 0x81, 0x00, 0xbb, 0xa1, 0x57, 0x33, 
+        0x0f, 0x57, 0x13, 0x3f, 0x1b, 0xbb, 0x50, 0x33, 0xc0, 0x47, 0xb2, 0x01, 0x0b, 0x33, 0x40, 0x22, 
+        0xc0, 0x20, 0x33, 0x81, 0x00, 0x22, 0xa1, 0x0b, 0x99, 0x56, 0xb9, 0xfd, 0x92, 0xa3, 0xfe, 0x9a, 
+        0x88, 0x92, 0xd9, 0x04, 0x97, 0xb8, 0x38, 0x57, 0x33, 0x07, 0x57, 0x13, 0x1e, 0x1b, 0xbb, 0x16, 
+        0x5b, 0x08, 0x2d, 0x0b, 0xc0, 0x88, 0x01, 0x8a, 0x3a, 0x70, 0x7f, 0x05, 0x10, 0x77, 0x01, 0x70, 
+        0x33, 0x20, 0x0d, 0xf0, 0x47, 0xb2, 0xbc, 0x86, 0xf1, 0xff, 0x00, 0x00, 0x47, 0x32, 0xe2, 0x47, 
+        0x92, 0xda, 0x1b, 0xbb, 0x16, 0x0b, 0x06, 0xb0, 0xb1, 0x41, 0xf0, 0xbb, 0x11, 0x46, 0xf4, 0xff, 
+        0x96, 0x98, 0x00, 0x1b, 0x89, 0xc0, 0x38, 0x01, 0x0c, 0x02, 0xc6, 0xf2, 0xff, 0x80, 0x80, 0x60, 
+        0x00, 0x08, 0x40, 0xf6, 0xc8, 0x0d, 0x00, 0x6b, 0xa1, 0xb0, 0xba, 0x81, 0xa0, 0xa0, 0x91, 0x86, 
+        0x04, 0x00, 0x00, 0x00, 0xf6, 0xd8, 0x35, 0x00, 0x9b, 0xa1, 0xb0, 0x6a, 0x81, 0xa0, 0xb0, 0x91, 
+        0x0c, 0x0a, 0x90, 0x22, 0x20, 0x0c, 0x08, 0x20, 0x33, 0x20, 0x8c, 0x33, 0x0c, 0x19, 0x90, 0x66, 
+        0x20, 0xd6, 0xd6, 0xf8, 0x1b, 0xbb, 0x8c, 0xeb, 0xf0, 0x66, 0x11, 0x56, 0x36, 0xf8, 0xb0, 0xb1, 
+        0x41, 0xf0, 0xbb, 0x11, 0x86, 0xde, 0xff, 0x00, 0x1b, 0xaa, 0x06, 0xdd, 0xff, 0x70, 0x3f, 0x05, 
+        0x10, 0x33, 0x01, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x61, 0x6f, 0xfd, 0x67, 0x43, 0x25, 0x30, 0x44, 
+        0xa5, 0x60, 0x53, 0x95, 0x50, 0x44, 0xc0, 0xe6, 0xc4, 0x25, 0xa6, 0x14, 0x2e, 0x60, 0x73, 0x20, 
+        0x10, 0x45, 0x40, 0x20, 0x57, 0x81, 0x00, 0x14, 0x40, 0x50, 0x50, 0x91, 0x50, 0x20, 0x60, 0x70, 
+        0x25, 0xb3, 0x0d, 0xf0, 0x40, 0x43, 0x11, 0x20, 0x44, 0x20, 0x16, 0x24, 0x00, 0x32, 0xa0, 0x00, 
+        0x50, 0x46, 0x11, 0x0b, 0x54, 0x30, 0x45, 0xb3, 0x2d, 0x04, 0x0d, 0xf0, 0x0c, 0x02, 0x0d, 0xf0, 
+        0x41, 0x5f, 0xfd, 0x40, 0x53, 0xc0, 0x50, 0x63, 0x30, 0x96, 0x36, 0x05, 0x50, 0x64, 0xa5, 0x16, 
+        0xd6, 0x04, 0x42, 0xa0, 0xff, 0x47, 0xa6, 0x27, 0x10, 0x4d, 0x40, 0x20, 0x55, 0x81, 0x00, 0x42, 
+        0xa1, 0x30, 0x6f, 0x05, 0x10, 0x66, 0x01, 0x50, 0x26, 0x20, 0xd6, 0x64, 0x00, 0x1b, 0x22, 0xf0, 
+        0x44, 0x11, 0x8c, 0x24, 0x0d, 0xf0, 0x00, 0x00, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 
+        0x41, 0x4d, 0xfd, 0x47, 0xc3, 0x0a, 0x40, 0x53, 0x11, 0x20, 0x55, 0x20, 0x8c, 0x15, 0x40, 0x41, 
+        0x41, 0xc0, 0x44, 0x11, 0x30, 0x6f, 0x05, 0x00, 0x41, 0x40, 0x40, 0x26, 0x81, 0x0d, 0xf0, 0x00, 
+        0x30, 0x64, 0xa5, 0x52, 0xa3, 0x80, 0x60, 0x65, 0xc0, 0x1b, 0x66, 0xf6, 0xc6, 0x29, 0x30, 0x55, 
+        0x11, 0x30, 0x55, 0x20, 0x50, 0x55, 0x11, 0x50, 0x5b, 0x41, 0x10, 0x4d, 0x40, 0x20, 0x55, 0x81, 
+        0x00, 0x42, 0xa1, 0x00, 0x06, 0x40, 0x00, 0x74, 0xa1, 0x40, 0x45, 0x81, 0x50, 0x50, 0x91, 0x16, 
+        0xe7, 0xf8, 0x60, 0x44, 0x20, 0x06, 0xe2, 0xff, 0x30, 0x2f, 0x05, 0x10, 0x22, 0x01, 0x0d, 0xf0, 
+        0x12, 0xc1, 0xd0, 0x22, 0x61, 0x00, 0x52, 0x61, 0x03, 0x42, 0x61, 0x02, 0x09, 0x61, 0x39, 0x11, 
+        0xc9, 0x71, 0xd9, 0x81, 0xcd, 0x02, 0xdd, 0x04, 0x3d, 0x04, 0x45, 0x69, 0x00, 0x48, 0x31, 0x08, 
+        0x11, 0xc0, 0x44, 0x82, 0xd0, 0x00, 0x82, 0xc8, 0x71, 0xd8, 0x81, 0x4a, 0x00, 0x0a, 0x33, 0x08, 
+        0x61, 0x12, 0xc1, 0x30, 0x0d, 0xf0, 0x00, 0x00, 0x1c, 0x89, 0x1c, 0x0a, 0x71, 0x29, 0xfd, 0x0c, 
+        0x04, 0x0c, 0x88, 0x00, 0x04, 0x40, 0x20, 0x60, 0x91, 0x00, 0x08, 0x40, 0x60, 0x60, 0x74, 0x6a, 
+        0x67, 0x20, 0x80, 0x91, 0x80, 0x80, 0x74, 0x00, 0x0a, 0x40, 0x20, 0x50, 0x91, 0x50, 0x50, 0x74, 
+        0x00, 0x09, 0x40, 0x20, 0x30, 0x91, 0x62, 0x06, 0x00, 0x8a, 0x87, 0x30, 0x30, 0x74, 0x5a, 0x57, 
+        0x52, 0x05, 0x00, 0x3a, 0x37, 0x82, 0x08, 0x00, 0x32, 0x03, 0x00, 0x8a, 0x26, 0x5a, 0x22, 0x3a, 
+        0x22, 0x0d, 0xf0, 0x00, 0x62, 0xa0, 0xb0, 0x60, 0x11, 0xc0, 0x59, 0x31, 0x49, 0x21, 0x39, 0x11, 
+        0x02, 0x61, 0x1f, 0xd2, 0x61, 0x21, 0xc2, 0x61, 0x20, 0xe2, 0x61, 0x22, 0xf2, 0x61, 0x23, 0xed, 
+        0x02, 0xfd, 0x04, 0xcd, 0x03, 0xdd, 0x03, 0x0d, 0x02, 0x09, 0x01, 0x40, 0x34, 0x20, 0x16, 0xb5, 
+        0x1e, 0x57, 0xbc, 0x02, 0x06, 0x73, 0x00, 0x42, 0x61, 0x29, 0x02, 0x61, 0x2a, 0xf0, 0xf5, 0x40, 
+        0x56, 0x5f, 0x04, 0xc7, 0x35, 0x05, 0x47, 0xb2, 0x02, 0xc6, 0x03, 0x01, 0x30, 0x20, 0xc0, 0x27, 
+        0x30, 0x1a, 0xd2, 0x21, 0x21, 0xe2, 0x21, 0x22, 0xf2, 0x21, 0x23, 0x50, 0x0c, 0xc0, 0x42, 0xa0, 
+        0xb0, 0xc2, 0x21, 0x20, 0x3d, 0x00, 0x02, 0x21, 0x1f, 0x4a, 0x11, 0x0d, 0xf0, 0xd2, 0x21, 0x21, 
+        0xe2, 0x21, 0x22, 0xf2, 0x21, 0x23, 0x50, 0x0c, 0xc0, 0x42, 0xa0, 0xb0, 0xc2, 0x21, 0x20, 0x0b, 
+        0x30, 0x02, 0x21, 0x1f, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0xd2, 0x21, 0x29, 0xed, 0x02, 0x2c, 0x04, 
+        0xf0, 0x44, 0xc0, 0x00, 0x04, 0x40, 0x42, 0x61, 0x17, 0xc0, 0x20, 0x91, 0x00, 0x1f, 0x40, 0x22, 
+        0x61, 0x18, 0xd0, 0x35, 0x81, 0x32, 0x61, 0x1d, 0x30, 0x30, 0xf5, 0x32, 0x61, 0x1e, 0xc5, 0x47, 
+        0x00, 0x32, 0x21, 0x17, 0x22, 0x61, 0x1a, 0x22, 0x61, 0x26, 0x00, 0x1f, 0x40, 0x00, 0xcc, 0xa1, 
+        0x22, 0x21, 0x18, 0x00, 0x03, 0x40, 0xe0, 0x00, 0x91, 0x32, 0x21, 0x1e, 0x00, 0xcc, 0x20, 0xc2, 
+        0x61, 0x19, 0xc0, 0xc0, 0xf5, 0xc5, 0x51, 0x00, 0x00, 0x42, 0x11, 0x02, 0x21, 0x26, 0x22, 0x21, 
+        0x1d, 0x40, 0x4c, 0x20, 0xcd, 0x04, 0x20, 0x20, 0xf4, 0x22, 0x61, 0x1b, 0x00, 0x22, 0x82, 0x27, 
+        0xb4, 0x1b, 0x0b, 0x60, 0x52, 0x21, 0x1d, 0x62, 0x61, 0x1a, 0x4a, 0xc5, 0x57, 0x3c, 0x0e, 0x27, 
+        0xbc, 0x0b, 0x82, 0xc0, 0xfe, 0x72, 0x21, 0x1d, 0x82, 0x61, 0x1a, 0xc0, 0xc7, 0x80, 0x32, 0x21, 
+        0x1e, 0x20, 0xcc, 0xc0, 0xc0, 0x2c, 0x20, 0x45, 0x41, 0x00, 0x32, 0x21, 0x1e, 0x22, 0x61, 0x28, 
+        0x22, 0x61, 0x27, 0x92, 0x21, 0x19, 0x2d, 0x0c, 0x90, 0x90, 0xf4, 0x92, 0x61, 0x1c, 0x45, 0x4c, 
+        0x00, 0x02, 0x21, 0x28, 0x42, 0x21, 0x1a, 0x32, 0x21, 0x27, 0x00, 0x62, 0x11, 0x52, 0x21, 0x1c, 
+        0x22, 0x21, 0x1b, 0x60, 0x55, 0x20, 0xcd, 0x05, 0x30, 0x22, 0x82, 0x27, 0xb5, 0x11, 0x72, 0x21, 
+        0x1d, 0x0b, 0x03, 0x5a, 0xc7, 0x77, 0x3c, 0x07, 0x27, 0xbc, 0x04, 0x02, 0xc3, 0xfe, 0xca, 0xc7, 
+        0x20, 0xcc, 0xc0, 0x00, 0x1f, 0x40, 0x00, 0x24, 0x11, 0x00, 0xdd, 0xa1, 0x3d, 0x0d, 0x20, 0x20, 
+        0x20, 0xc5, 0x4b, 0x00, 0x5d, 0x02, 0x0d, 0x03, 0x37, 0x3c, 0x10, 0x00, 0x1f, 0x40, 0x00, 0x4e, 
+        0xa1, 0x37, 0x9c, 0x20, 0x27, 0xb4, 0x1d, 0xc6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x00, 
+        0x4e, 0xa1, 0x0c, 0x13, 0xd0, 0x25, 0xc0, 0x27, 0x35, 0x01, 0x0c, 0x03, 0x52, 0x21, 0x1d, 0x50, 
+        0x50, 0xc0, 0x30, 0x35, 0xc0, 0x30, 0x3c, 0xc0, 0x02, 0x21, 0x17, 0x20, 0x54, 0xc0, 0x57, 0x34, 
+        0x27, 0xe2, 0x21, 0x22, 0xd2, 0x21, 0x21, 0xc2, 0x21, 0x20, 0x00, 0x10, 0x40, 0x00, 0x43, 0xa1, 
+        0x02, 0x21, 0x1f, 0x00, 0x0f, 0x40, 0x30, 0x30, 0x91, 0x50, 0x20, 0x91, 0xf2, 0x21, 0x23, 0x40, 
+        0x22, 0x20, 0x42, 0xa0, 0xb0, 0x4a, 0x11, 0x0d, 0xf0, 0xc2, 0x21, 0x20, 0xd2, 0x21, 0x21, 0xe2, 
+        0x21, 0x22, 0x00, 0x10, 0x40, 0x0b, 0x33, 0x02, 0x21, 0x1f, 0x00, 0x43, 0xa1, 0x00, 0x0f, 0x40, 
+        0x30, 0x30, 0x91, 0x50, 0x20, 0x91, 0xf2, 0x21, 0x23, 0x40, 0x22, 0x20, 0x42, 0xa0, 0xb0, 0x4a, 
+        0x11, 0x0d, 0xf0, 0x00, 0x02, 0x21, 0x1f, 0xd2, 0x21, 0x21, 0xe2, 0x21, 0x22, 0xf2, 0x21, 0x23, 
+        0x3d, 0x0c, 0x42, 0xa0, 0xb0, 0xc2, 0x21, 0x20, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x47, 0x3c, 0x02, 
+        0x06, 0x2a, 0x00, 0x20, 0xf4, 0x40, 0x29, 0xb1, 0x8c, 0xc2, 0x29, 0xb1, 0x00, 0x12, 0x40, 0x00, 
+        0xf4, 0xa1, 0x00, 0xdc, 0x81, 0x00, 0xe0, 0xa1, 0x2d, 0x0d, 0xe0, 0x40, 0xf5, 0xf0, 0x30, 0xf5, 
+        0x32, 0x61, 0x14, 0x42, 0x61, 0x12, 0xc5, 0x3a, 0x00, 0x32, 0x21, 0x14, 0xc2, 0x21, 0x12, 0x00, 
+        0x02, 0x11, 0xf0, 0x50, 0xf4, 0x52, 0x61, 0x11, 0x2d, 0x0d, 0x00, 0xcc, 0x20, 0xc9, 0xe1, 0xc5, 
+        0x2c, 0x00, 0x02, 0x21, 0x11, 0x20, 0x00, 0x82, 0x07, 0xbc, 0x0b, 0xc8, 0xe1, 0xfa, 0xcc, 0xf7, 
+        0x3c, 0x04, 0x07, 0xbc, 0x01, 0xca, 0xcf, 0xe0, 0xd0, 0xf4, 0x32, 0x21, 0x14, 0x00, 0xcc, 0xc0, 
+        0x2d, 0x0c, 0x05, 0x37, 0x00, 0x00, 0xe2, 0x11, 0x32, 0x21, 0x14, 0x2d, 0x0c, 0xe0, 0xed, 0x20, 
+        0xdd, 0x0e, 0x85, 0x29, 0x00, 0x02, 0x21, 0x11, 0x20, 0x00, 0x82, 0x07, 0xbe, 0x09, 0xfa, 0xde, 
+        0xf7, 0x3d, 0x04, 0x07, 0xbd, 0x01, 0xda, 0xdf, 0xc2, 0x21, 0x20, 0xe2, 0x21, 0x22, 0xf2, 0x21, 
+        0x23, 0x42, 0xa0, 0xb0, 0x00, 0x2d, 0xc0, 0x38, 0xb1, 0x02, 0x21, 0x1f, 0xd2, 0x21, 0x21, 0x00, 
+        0x03, 0x40, 0x20, 0x20, 0x91, 0x0c, 0x03, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x02, 0x61, 0x2a, 0x56, 
+        0xb4, 0x00, 0x22, 0xa0, 0x01, 0x45, 0x25, 0x00, 0x02, 0x21, 0x2a, 0x20, 0xf2, 0x20, 0x40, 0xff, 
+        0x40, 0xdc, 0x14, 0x49, 0xb1, 0xf0, 0xd0, 0xf4, 0xf0, 0x4c, 0xc0, 0x42, 0x61, 0x15, 0xf0, 0xc0, 
+        0xf5, 0xc6, 0x28, 0x00, 0x00, 0x00, 0x49, 0xb1, 0x2c, 0x03, 0x00, 0x14, 0x40, 0x00, 0xff, 0xa1, 
+        0x40, 0x33, 0xc0, 0x00, 0x03, 0x40, 0xc0, 0x20, 0x91, 0x29, 0xc1, 0x00, 0x14, 0x40, 0x00, 0xe0, 
+        0xa1, 0x00, 0xdc, 0x81, 0xd2, 0x61, 0x15, 0xf0, 0xc0, 0xf5, 0xd0, 0xd0, 0xf5, 0x3d, 0x0c, 0x45, 
+        0x2d, 0x00, 0x00, 0x42, 0x11, 0x3d, 0x0c, 0x28, 0xc1, 0x40, 0x4d, 0x20, 0x49, 0x91, 0x42, 0x61, 
+        0x10, 0xf0, 0xd0, 0xf4, 0x45, 0x1f, 0x00, 0x52, 0x21, 0x10, 0x20, 0x0d, 0x82, 0x07, 0xb5, 0x11, 
+        0x68, 0x91, 0xfa, 0x66, 0x62, 0x61, 0x10, 0xf7, 0x36, 0x07, 0x07, 0xb6, 0x04, 0x6a, 0x8f, 0x82, 
+        0x61, 0x10, 0x3d, 0x0c, 0x92, 0x21, 0x15, 0x22, 0x21, 0x10, 0x90, 0x90, 0xf4, 0x00, 0x22, 0xc0, 
+        0x22, 0x61, 0x10, 0x99, 0xd1, 0xc5, 0x28, 0x00, 0x3d, 0x0c, 0x00, 0xb2, 0x11, 0xa8, 0xd1, 0x22, 
+        0x21, 0x10, 0xb0, 0xaa, 0x20, 0xa9, 0xa1, 0xa2, 0x61, 0x25, 0x05, 0x1b, 0x00, 0x02, 0x21, 0x25, 
+        0x20, 0x2d, 0x82, 0x27, 0xb0, 0x0b, 0x08, 0xa1, 0xfa, 0x00, 0xf7, 0x30, 0x04, 0x27, 0xb0, 0x01, 
+        0x0a, 0x0f, 0x20, 0x30, 0xc0, 0x32, 0x61, 0x15, 0x22, 0x21, 0x15, 0x3d, 0x0c, 0xe0, 0x40, 0xf5, 
+        0x42, 0x61, 0x12, 0x05, 0x25, 0x00, 0x3d, 0x0c, 0x00, 0x62, 0x11, 0x52, 0x21, 0x12, 0x22, 0x21, 
+        0x15, 0x60, 0x55, 0x20, 0x59, 0xf1, 0x52, 0x61, 0x16, 0x05, 0x17, 0x00, 0x72, 0x21, 0x16, 0x20, 
+        0x0d, 0x82, 0x07, 0xb7, 0x12, 0x88, 0xf1, 0xfa, 0x88, 0x82, 0x61, 0x16, 0xf7, 0x38, 0x08, 0x07, 
+        0xb8, 0x05, 0x80, 0xaf, 0x80, 0xa2, 0x61, 0x16, 0x3d, 0x0c, 0x22, 0x21, 0x16, 0xe0, 0xb0, 0xf4, 
+        0xb2, 0x61, 0x13, 0x00, 0x22, 0xc0, 0x22, 0x61, 0x16, 0x85, 0x20, 0x00, 0xe8, 0xb1, 0x00, 0x22, 
+        0x11, 0x02, 0x21, 0x13, 0x3d, 0x0c, 0x20, 0x00, 0x20, 0x22, 0x21, 0x16, 0x09, 0x81, 0x02, 0x61, 
+        0x24, 0x85, 0x12, 0x00, 0x02, 0x21, 0x24, 0x20, 0x2d, 0x82, 0x27, 0xb0, 0x2c, 0x08, 0x81, 0xfa, 
+        0x00, 0xf7, 0x30, 0x25, 0x27, 0xb0, 0x22, 0x0c, 0x03, 0xc2, 0x21, 0x20, 0xd2, 0x21, 0x21, 0x42, 
+        0xa0, 0xb0, 0x00, 0x0e, 0x40, 0x0a, 0x0f, 0xe2, 0x21, 0x22, 0xf2, 0x21, 0x23, 0x20, 0x20, 0xc0, 
+        0x20, 0x20, 0x91, 0x02, 0x21, 0x1f, 0x4a, 0x11, 0x0d, 0xf0, 0x0c, 0x03, 0xc2, 0x21, 0x20, 0xd2, 
+        0x21, 0x21, 0xf2, 0x21, 0x23, 0x42, 0xa0, 0xb0, 0x20, 0x20, 0xc0, 0x00, 0x0e, 0x40, 0x02, 0x21, 
+        0x1f, 0xe2, 0x21, 0x22, 0x20, 0x20, 0x91, 0x4a, 0x11, 0x0d, 0xf0, 0x00, 0x02, 0x21, 0x1f, 0xc2, 
+        0x21, 0x20, 0xe2, 0x21, 0x22, 0xf2, 0x21, 0x23, 0x3d, 0x0d, 0x42, 0xa0, 0xb0, 0xd2, 0x21, 0x21, 
+        0x4a, 0x11, 0x0d, 0xf0, 0x0d, 0xf0, 0x00, 0x00, 0x30, 0x72, 0x30, 0x20, 0x61, 0x60, 0x30, 0x31, 
+        0x60, 0xb6, 0x23, 0x37, 0x60, 0x51, 0x41, 0x37, 0x35, 0x3d, 0x50, 0xf6, 0x40, 0x40, 0xf3, 0x40, 
+        0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 0x00, 0x33, 0xa1, 0x22, 0xa0, 0x00, 0x37, 0x36, 0x04, 0x30, 
+        0x66, 0xc0, 0x1b, 0x22, 0xf0, 0x22, 0x11, 0x30, 0x31, 0x41, 0x0b, 0x44, 0x56, 0xc4, 0xfe, 0x37, 
+        0x36, 0x01, 0x1b, 0x22, 0x20, 0x50, 0x60, 0x70, 0x25, 0xa3, 0x0d, 0xf0, 0x9c, 0x53, 0x60, 0x20, 
+        0x60, 0x70, 0x26, 0xb3, 0x0d, 0xf0, 0x00, 0x00, 0x37, 0x36, 0x10, 0x0c, 0x12, 0x7c, 0xf4, 0x70, 
+        0x24, 0xa3, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 
+        0x7d, 0x02, 0x20, 0x21, 0x60, 0x30, 0x31, 0x60, 0xb6, 0x23, 0x30, 0x50, 0xf2, 0x40, 0x40, 0xf3, 
+        0x40, 0x47, 0xb5, 0x17, 0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 0x00, 0x33, 0xa1, 0x37, 0x32, 0x02, 
+        0x30, 0x22, 0xc0, 0x30, 0x31, 0x41, 0x42, 0xc4, 0xff, 0x56, 0x04, 0xff, 0x37, 0x32, 0x02, 0x30, 
+        0x22, 0xc0, 0xd6, 0x27, 0x00, 0x20, 0x20, 0x60, 0x0d, 0xf0, 0x00, 0x00, 0xcc, 0x53, 0x00, 0x00, 
+        0x00, 0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0xb6, 0x23, 0x30, 0x6d, 
+        0x02, 0x50, 0xf6, 0x40, 0x40, 0xf3, 0x40, 0x47, 0xb5, 0x29, 0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 
+        0x00, 0x33, 0xa1, 0x0c, 0x02, 0x37, 0x36, 0x04, 0x30, 0x66, 0xc0, 0x1b, 0x22, 0xf0, 0x22, 0x11, 
+        0x30, 0x31, 0x41, 0x0b, 0x44, 0x56, 0xc4, 0xfe, 0x37, 0x36, 0x01, 0x1b, 0x22, 0x0d, 0xf0, 0x00, 
+        0x8c, 0x93, 0x0d, 0xf0, 0x37, 0x36, 0x0c, 0x0c, 0x12, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 0xbc, 0x62, 0x0c, 0x07, 0x06, 0x02, 0x00, 0x00, 
+        0xac, 0xe2, 0x20, 0x7f, 0x05, 0x20, 0x21, 0x60, 0x40, 0xf2, 0x40, 0x00, 0x14, 0x40, 0x00, 0x52, 
+        0xa1, 0x50, 0x28, 0x41, 0x80, 0x65, 0x01, 0x52, 0xa0, 0x9d, 0x40, 0x55, 0xc0, 0x90, 0x55, 0x01, 
+        0x5a, 0x22, 0x10, 0x77, 0x01, 0x70, 0x22, 0x20, 0xd6, 0x66, 0x00, 0x1b, 0x22, 0xf0, 0x66, 0x11, 
+        0x8c, 0x06, 0x0d, 0xf0, 0x20, 0x21, 0x41, 0xf0, 0x22, 0x11, 0x0d, 0xf0, 0xac, 0xe2, 0x0c, 0x07, 
+        0x06, 0x02, 0x00, 0x00, 0xac, 0x62, 0x20, 0x7f, 0x05, 0x20, 0x21, 0x60, 0x40, 0xf2, 0x40, 0x00, 
+        0x14, 0x40, 0x00, 0x52, 0xa1, 0x50, 0x3b, 0x41, 0xb0, 0x25, 0x01, 0x52, 0xa4, 0x1d, 0x40, 0x55, 
+        0xc0, 0xc0, 0x55, 0x01, 0x5a, 0x33, 0x10, 0x77, 0x01, 0x70, 0x33, 0x20, 0x0d, 0xf0, 0x0c, 0x03, 
+        0x0d, 0xf0, 0x00, 0x00, 0xb6, 0x23, 0x28, 0x50, 0xf2, 0x40, 0x40, 0xf3, 0x40, 0x47, 0xb5, 0x17, 
+        0x50, 0x44, 0xc0, 0x00, 0x14, 0x40, 0x00, 0x33, 0xa1, 0x37, 0x32, 0x02, 0x30, 0x22, 0xc0, 0x30, 
+        0x31, 0x41, 0x42, 0xc4, 0xff, 0x56, 0x04, 0xff, 0x37, 0x32, 0x02, 0x30, 0x22, 0xc0, 0x0d, 0xf0, 
+        0xcc, 0x53, 0x00, 0x00, 0x00, 0x44, 0x49, 0x56, 0x30, 0x0c, 0x02, 0x0d, 0xf0, 0x00, 0x00, 0x00, 
+        0x12, 0xc1, 0xe0, 0xc9, 0x41, 0xd9, 0x51, 0xe9, 0x61, 0xf9, 0x71, 0x20, 0x40, 0xf5, 0x30, 0x50, 
+        0xf5, 0x50, 0x62, 0xc1, 0x30, 0xb4, 0xc1, 0x0c, 0x09, 0xba, 0x66, 0xb7, 0xb6, 0x02, 0x92, 0xc9, 
+        0x01, 0x10, 0x40, 0x40, 0x60, 0x99, 0x81, 0x30, 0xb2, 0xc1, 0x00, 0x66, 0xa1, 0xba, 0x66, 0xb7, 
+        0xb6, 0x01, 0x1b, 0x99, 0x50, 0x34, 0xc1, 0x9a, 0x33, 0x2d, 0x06, 0xc8, 0x41, 0xd8, 0x51, 0xe8, 
+        0x61, 0xf8, 0x71, 0x12, 0xc1, 0x20, 0x0d, 0xf0, 0x00, 0x80, 0xfe, 0x3f, 0x74, 0x07, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x5a, 0x00, 0xf0, 0x0b, 0xf0, 0x48, 0x10, 0x40, 0x9c, 0x22, 0x10, 0x40, 0xa0, 0x48, 0x10, 0x40, 
+        0xd0, 0x51, 0x10, 0x40, 0xec, 0x60, 0x00, 0x40, 0xd0, 0x60, 0x00, 0x40, 0xb8, 0x37, 0x10, 0x40, 
+        0xc8, 0x51, 0x10, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 
+        0x00, 0x40, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00, 0x70, 0x00, 0x74, 0x00, 0x78, 0x00, 0x7c, 
+        0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 
+        0xf8, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xf8, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 
+        0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xfa, 0x01, 0xf8, 0x01, 0xf8, 0x01, 
+        0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x24, 0xff, 0x3f, 0x01, 0x01, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x3a, 0x01, 0x02, 0x01, 0xdf, 0x00, 0xd5, 0x00, 0x3a, 0x01, 0xa2, 0x00, 0x7f, 0x00, 0x75, 0x00, 
+        0x2c, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x3c, 0x00, 
+        0x3c, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x0b, 0x02, 0x0b, 0x01, 0x0b, 0x02, 0x0b, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x1f, 0x02, 0x16, 0x02, 0x11, 0x01, 0x10, 0x02, 0x07, 0x72, 0x00, 0x00, 0x17, 0x02, 0x15, 0x02, 
+        0x11, 0x01, 0x10, 0x02, 0x07, 0x72, 0x00, 0x00, 0x16, 0x02, 0x14, 0x02, 0x11, 0x01, 0x10, 0x02, 
+        0x07, 0x72, 0x00, 0x00, 0x15, 0x02, 0x13, 0x02, 0x11, 0x01, 0x10, 0x02, 0x07, 0x60, 0x00, 0x00, 
+        0x14, 0x02, 0x12, 0x02, 0x11, 0x01, 0x10, 0x02, 0x07, 0x55, 0x00, 0x00, 0x13, 0x02, 0x12, 0x01, 
+        0x11, 0x02, 0x10, 0x02, 0x07, 0x4b, 0x00, 0x00, 0x12, 0x02, 0x11, 0x01, 0x10, 0x02, 0x10, 0x02, 
+        0x07, 0x40, 0x00, 0x00, 0x11, 0x02, 0x10, 0x01, 0x10, 0x02, 0x10, 0x02, 0x07, 0x3b, 0x00, 0x00, 
+        0x10, 0x02, 0x10, 0x01, 0x10, 0x01, 0x10, 0x03, 0x07, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x1f, 0x02, 0x16, 0x02, 0x11, 0x01, 0x10, 0x02, 0x07, 0x72, 0x00, 0x00, 0x17, 0x02, 0x15, 0x02, 
+        0x11, 0x01, 0x10, 0x02, 0x07, 0x72, 0x00, 0x00, 0x16, 0x02, 0x14, 0x02, 0x11, 0x01, 0x10, 0x02, 
+        0x07, 0x72, 0x00, 0x00, 0x15, 0x02, 0x13, 0x02, 0x11, 0x01, 0x10, 0x02, 0x07, 0x60, 0x00, 0x00, 
+        0x14, 0x02, 0x12, 0x02, 0x11, 0x01, 0x10, 0x02, 0x07, 0x55, 0x00, 0x00, 0x13, 0x02, 0x12, 0x01, 
+        0x11, 0x02, 0x10, 0x02, 0x07, 0x4b, 0x00, 0x00, 0x12, 0x02, 0x11, 0x01, 0x10, 0x02, 0x00, 0x02, 
+        0x07, 0x40, 0x00, 0x00, 0x11, 0x02, 0x10, 0x01, 0x05, 0x02, 0x00, 0x02, 0x07, 0x3b, 0x00, 0x00, 
+        0x10, 0x02, 0x05, 0x01, 0x05, 0x01, 0x00, 0x03, 0x07, 0x32, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 
+        0x00, 0x01, 0x00, 0x03, 0x07, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 
+        0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x0c, 0x02, 0x08, 0x01, 0x0d, 0x02, 0x0b, 0x02, 0x07, 0x72, 0x00, 0x00, 0x08, 0x02, 0x0d, 0x02, 
+        0x09, 0x01, 0x0b, 0x02, 0x07, 0x65, 0x00, 0x00, 0x0d, 0x02, 0x09, 0x02, 0x0e, 0x01, 0x0b, 0x02, 
+        0x07, 0x5c, 0x00, 0x00, 0x09, 0x02, 0x0e, 0x01, 0x0a, 0x02, 0x0b, 0x02, 0x07, 0x58, 0x00, 0x00, 
+        0x0e, 0x02, 0x0a, 0x02, 0x0f, 0x01, 0x0b, 0x02, 0x07, 0x52, 0x00, 0x00, 0x0a, 0x02, 0x0f, 0x01, 
+        0x0b, 0x02, 0x0b, 0x02, 0x07, 0x4b, 0x00, 0x00, 0x0f, 0x02, 0x0b, 0x02, 0x0b, 0x01, 0x0b, 0x02, 
+        0x07, 0x38, 0x00, 0x00, 0x0b, 0x02, 0x0b, 0x01, 0x0b, 0x02, 0x0b, 0x02, 0x07, 0x40, 0x00, 0x00, 
+        0x0c, 0x02, 0x08, 0x01, 0x0d, 0x02, 0x0b, 0x02, 0x07, 0x72, 0x00, 0x00, 0x08, 0x02, 0x0d, 0x02, 
+        0x09, 0x01, 0x0b, 0x02, 0x07, 0x65, 0x00, 0x00, 0x0d, 0x02, 0x09, 0x02, 0x0e, 0x01, 0x0b, 0x02, 
+        0x07, 0x5c, 0x00, 0x00, 0x09, 0x02, 0x0e, 0x01, 0x0a, 0x02, 0x0b, 0x02, 0x07, 0x58, 0x00, 0x00, 
+        0x0e, 0x02, 0x0a, 0x02, 0x0f, 0x01, 0x0b, 0x02, 0x07, 0x52, 0x00, 0x00, 0x0a, 0x02, 0x07, 0x01, 
+        0x06, 0x02, 0x00, 0x02, 0x07, 0x4b, 0x00, 0x00, 0x0f, 0x02, 0x0b, 0x02, 0x06, 0x01, 0x00, 0x02, 
+        0x07, 0x38, 0x00, 0x00, 0x0b, 0x02, 0x06, 0x01, 0x05, 0x02, 0x00, 0x02, 0x07, 0x40, 0x00, 0x00, 
+        0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x07, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 
+        0x00, 0x01, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x07, 0x02, 0x06, 0x02, 0x05, 0x02, 0x00, 0x01, 0x07, 0x40, 0x00, 0x00, 0x06, 0x02, 0x01, 0x02, 
+        0x00, 0x02, 0x00, 0x01, 0x07, 0x39, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 
+        0x07, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 
+        0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x1f, 0x02, 0x1d, 0x02, 
+        0x1b, 0x01, 0x19, 0x02, 0x07, 0x00, 0x00, 0x00, 0x17, 0x02, 0x15, 0x02, 0x13, 0x01, 0x11, 0x02, 
+        0x07, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0d, 0x02, 0x0b, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 
+        0xd0, 0x2e, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x5c, 0x86, 0xfe, 0x3f, 0xb8, 0x86, 0xfe, 0x3f, 0x14, 0x87, 0xfe, 0x3f, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0xa8, 0x8e, 0xfe, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x0e, 0x33, 0xcd, 0xab, 0x34, 0x12, 0x6d, 0xe6, 0xec, 0xde, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x70, 0x83, 0xfe, 0x3f, 0x80, 0x87, 0xfe, 0x3f, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x80, 0x43, 0x69, 0x65, 0x65, 0x65, 
+        0x38, 0x30, 0x32, 0x31, 0x31, 0x5f, 0x68, 0x64, 0x72, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x65, 0x65, 0x65, 
+        0x38, 0x30, 0x32, 0x31, 0x31, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x32, 0x6d, 0x6f, 0x64, 0x65, 0x00, 
+        0x70, 0x83, 0xfe, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 
+        0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, 
+        0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 
+        0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 
+        0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x01, 0x02, 0x02, 0x03, 
+        0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 
+        0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 
+        0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 
+        0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, 0x02, 0x03, 
+        0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 
+        0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 
+        0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 
+        0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, 0x04, 
+        0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 
+        0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 
+        0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x04, 0x05, 0x05, 0x06, 
+        0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, 0x65, 0x6d, 0x70, 0x74, 
+        0x79, 0x20, 0x6f, 0x74, 0x70, 0x0a, 0x00, 0x00, 0x62, 0x6f, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x20, 
+        0x6f, 0x6b, 0x0a, 0x00, 0x41, 0x70, 0x72, 0x20, 0x31, 0x32, 0x20, 0x32, 0x30, 0x31, 0x34, 0x00, 
+        0x31, 0x36, 0x3a, 0x30, 0x35, 0x3a, 0x34, 0x38, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6e, 0x74, 
+        0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x6f, 0x6e, 0x0a, 0x00, 0x00, 0x76, 0x65, 0x72, 0x3a, 
+        0x25, 0x73, 0x0a, 0x00, 0x30, 0x61, 0x39, 0x39, 0x37, 0x62, 0x33, 0x65, 0x31, 0x62, 0x36, 0x63, 
+        0x00, 0x00, 0x00, 0x00, 0x65, 0x74, 0x73, 0x20, 0x25, 0x73, 0x20, 0x25, 0x73, 0x0a, 0x00, 0x00, 
+        0x62, 0x73, 0x73, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x70, 0x2c, 0x65, 0x6e, 0x64, 
+        0x20, 0x25, 0x70, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x6f, 0x62, 0x0a, 0x00, 0x00, 0x00, 0x00, 
+        0x25, 0x73, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 
+        0x2e, 0x63, 0x00, 0x00, 0x6e, 0x65, 0x77, 0x20, 0x70, 0x75, 0x74, 0x63, 0x21, 0x0a, 0x00, 0x00, 
+        0x64, 0x65, 0x6c, 0x20, 0x69, 0x66, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x50, 0x52, 0x45, 0x20, 
+        0x44, 0x4f, 0x57, 0x4e, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6f, 0x20, 0x77, 0x61, 0x6b, 
+        0x65, 0x2c, 0x20, 0x63, 0x68, 0x6b, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 
+        0x70, 0x74, 0x6b, 0x20, 0x25, 0x64, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 
+        0x77, 0x65, 0x70, 0x20, 0x6b, 0x65, 0x79, 0x25, 0x64, 0x21, 0x0a, 0x00, 0x73, 0x65, 0x74, 0x20, 
+        0x67, 0x74, 0x6b, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x72, 0x6d, 0x20, 0x67, 0x74, 0x6b, 0x25, 0x64, 
+        0x0a, 0x00, 0x00, 0x00, 0x72, 0x6d, 0x20, 0x70, 0x74, 0x6b, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 
+        0x62, 0x63, 0x6e, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x63, 0x6e, 0x74, 0x20, 0x0a, 0x00, 0x00, 0x00, 
+        0x75, 0x6e, 0x63, 0x6e, 0x74, 0x20, 0x0a, 0x00, 0x69, 0x66, 0x25, 0x64, 0x20, 0x61, 0x64, 0x64, 
+        0x20, 0x73, 0x74, 0x61, 0x25, 0x64, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 
+        0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 
+        0x25, 0x30, 0x32, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x69, 0x66, 0x25, 0x64, 0x20, 0x72, 0x6d, 0x20, 
+        0x73, 0x74, 0x61, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 
+        0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 0x78, 0x3a, 0x25, 0x30, 0x32, 
+        0x78, 0x0a, 0x00, 0x00, 0x63, 0x68, 0x67, 0x20, 0x69, 0x66, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 
+        0x61, 0x64, 0x64, 0x20, 0x69, 0x66, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x73, 0x70, 0x20, 
+        0x25, 0x64, 0x0a, 0x00, 0x48, 0x42, 0x20, 0x72, 0x65, 0x71, 0x0a, 0x00, 0x52, 0x53, 0x54, 0x20, 
+        0x4d, 0x41, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x65, 
+        0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x74, 0x78, 0x20, 0x72, 
+        0x61, 0x74, 0x65, 0x20, 0x66, 0x69, 0x78, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 
+        0x73, 0x65, 0x74, 0x20, 0x66, 0x72, 0x65, 0x71, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x0a, 0x00, 
+        0x67, 0x74, 0x6b, 0x20, 0x74, 0x6b, 0x69, 0x70, 0x20, 0x6d, 0x69, 0x63, 0x20, 0x65, 0x72, 0x72, 
+        0x6f, 0x72, 0x20, 0x73, 0x65, 0x74, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x70, 0x74, 0x6b, 0x20, 
+        0x74, 0x6b, 0x69, 0x70, 0x20, 0x6d, 0x69, 0x63, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x73, 
+        0x65, 0x74, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x72, 0x69, 0x66, 0x73, 0x20, 0x73, 0x65, 0x74, 
+        0x20, 0x6f, 0x6b, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x72, 0x69, 0x66, 0x73, 0x20, 0x64, 0x69, 0x73, 
+        0x61, 0x62, 0x6c, 0x65, 0x21, 0x0a, 0x00, 0x00, 0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x20, 
+        0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x74, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 
+        0x62, 0x61, 0x63, 0x6b, 0x6f, 0x66, 0x66, 0x20, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x66, 
+        0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 
+        0x6f, 0x6e, 0x0a, 0x00, 0x6f, 0x66, 0x66, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x64, 0x65, 
+        0x78, 0x3a, 0x20, 0x25, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x20, 0x30, 0x78, 0x25, 
+        0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 
+        0x0a, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6c, 0x6c, 0x5f, 0x63, 
+        0x61, 0x6c, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x73, 0x20, 0x35, 0x6d, 0x73, 0x21, 0x21, 
+        0x21, 0x0a, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6c, 0x6c, 0x5f, 0x63, 
+        0x61, 0x6c, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x73, 0x20, 0x32, 0x6d, 0x73, 0x21, 0x21, 
+        0x21, 0x0a, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x66, 0x72, 0x65, 0x71, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x25, 0x64, 0x2c, 0x20, 
+        0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x2c, 0x20, 0x25, 0x64, 0x2c, 0x20, 
+        0x00, 0x00, 0x00, 0x00, 0x6c, 0x6d, 0x61, 0x63, 0x2e, 0x63, 0x00, 0x00, 0x74, 0x78, 0x20, 0x72, 
+        0x74, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 
+        0x74, 0x78, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, 
+        0x57, 0x44, 0x45, 0x56, 0x44, 0x49, 0x41, 0x47, 0x38, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 
+        0x20, 0x57, 0x44, 0x45, 0x56, 0x44, 0x49, 0x41, 0x47, 0x35, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 
+        0x78, 0x20, 0x0a, 0x00, 0x70, 0x6d, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x71, 0x75, 0x69, 0x74, 
+        0x53, 0x6c, 0x70, 0x50, 0x6f, 0x72, 0x63, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x0a, 0x00, 
+        0x77, 0x68, 0x79, 0x20, 0x25, 0x75, 0x20, 0x25, 0x75, 0x20, 0x25, 0x75, 0x20, 0x25, 0x75, 0x0a, 
+        0x00, 0x00, 0x00, 0x00, 0x70, 0x6d, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x25, 0x64, 0x20, 
+        0x25, 0x64, 0x20, 0x25, 0x75, 0x2f, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x70, 0x6d, 0x20, 0x6f, 
+        0x70, 0x65, 0x6e, 0x20, 0x25, 0x64, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x58, 0x25, 0x64, 0x20, 
+        0x25, 0x64, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x6f, 0x66, 0x66, 0x53, 0x54, 0x25, 0x64, 0x00, 
+        0x6f, 0x6e, 0x53, 0x54, 0x25, 0x64, 0x0a, 0x00, 0x6e, 0x4f, 0x4e, 0x66, 0x61, 0x69, 0x6c, 0x65, 
+        0x64, 0x2c, 0x20, 0x68, 0x63, 0x68, 0x20, 0x25, 0x64, 0x20, 0x63, 0x63, 0x68, 0x20, 0x25, 0x64, 
+        0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x4f, 0x46, 0x46, 
+        0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x68, 0x63, 0x68, 0x20, 0x25, 0x64, 0x20, 0x63, 
+        0x63, 0x68, 0x20, 0x25, 0x64, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 
+        0x77, 0x0a, 0x00, 0x00, 0x6e, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x75, 0x74, 0x2c, 0x20, 
+        0x68, 0x63, 0x68, 0x20, 0x25, 0x64, 0x20, 0x63, 0x63, 0x68, 0x20, 0x25, 0x64, 0x20, 0x30, 0x78, 
+        0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 
+        0x00, 0x00, 0x00, 0x00, 0x73, 0x6c, 0x0a, 0x00, 0x73, 0x75, 0x6c, 0x20, 0x25, 0x64, 0x20, 0x25, 
+        0x64, 0x0a, 0x00, 0x00, 0x70, 0x70, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 
+        0x6d, 0x61, 0x70, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20, 
+        0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 
+        0x72, 0x62, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x74, 0x72, 0x63, 0x2e, 0x63, 0x00, 0x00, 0x00, 
+        0x61, 0x6d, 0x20, 0x6f, 0x6e, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x66, 0x31, 0x73, 0x25, 
+        0x64, 0x0a, 0x00, 0x00, 0x61, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 
+        0x66, 0x32, 0x73, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x4e, 0x61, 0x6d, 0x0a, 0x00, 0x00, 0x00, 0x00, 
+        0x3d, 0x3d, 0x64, 0x6c, 0x0a, 0x00, 0x00, 0x00, 0x74, 0x69, 0x64, 0x20, 0x25, 0x64, 0x20, 0x67, 
+        0x65, 0x74, 0x3f, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x74, 0x72, 0x63, 0x20, 0x30, 0x37, 0x31, 0x31, 
+        0x0a, 0x00, 0x00, 0x00, 0x47, 0x6f, 0x61, 0x6d, 0x0a, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x20, 
+        0x25, 0x64, 0x0a, 0x00, 0x61, 0x64, 0x64, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 
+        0x0a, 0x00, 0x00, 0x00, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x00, 
+        0x72, 0x6d, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, 0x00, 0x00, 0x00, 
+        0x77, 0x64, 0x65, 0x76, 0x2e, 0x63, 0x00, 0x00, 0x25, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x6e, 0x6e, 
+        0x6f, 0x74, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x20, 0x74, 
+        0x6f, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x3b, 0x20, 0x66, 0x72, 0x65, 0x71, 0x20, 0x25, 0x75, 0x20, 
+        0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x66, 0x63, 0x20, 0x30, 
+        0x78, 0x25, 0x30, 0x34, 0x78, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x25, 0x64, 
+        0x0a, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 
+        0x72, 0x6f, 0x62, 0x65, 0x2c, 0x20, 0x69, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x20, 0x25, 0x64, 0x0a, 
+        0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 
+        0x62, 0x67, 0x0a, 0x00, 0x43, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x01, 0x00, 0x01, 0x7c, 0x00, 0x0c, 0x01, 0x00, 0x08, 0x01, 0x08, 0x0c, 0x08, 0x0d, 0x08, 0x0e, 
+        0x08, 0x0f, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xf4, 0xf2, 0x10, 0x40, 
+        0x70, 0x04, 0x00, 0x00, 0x0e, 0xb0, 0x01, 0x80, 0x0d, 0x8c, 0x0c, 0x8d, 0x0b, 0x8e, 0x0a, 0x8f, 
+        0x09, 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xfe, 0x3f, 0x98, 0xbe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0xe6, 
+        
+       };
+
+ // const static int eagle_fw2_size = 67696;
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_android.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_android.c
new file mode 100755 (executable)
index 0000000..95ca47b
--- /dev/null
@@ -0,0 +1,408 @@
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/netdevice.h>
+#include <linux/aio.h>
+
+#include "esp_android.h"
+#include "esp_debug.h"
+#include "esp_sif.h"
+
+#ifdef ANDROID
+#include "esp_path.h"
+#include "esp_conf.h"
+
+int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length)
+{
+        int ret = 0;
+        struct file *filp = (struct file *)-ENOENT;
+        mm_segment_t oldfs;
+        oldfs = get_fs();
+        set_fs(KERNEL_DS);
+        do {
+                int mode = (wbuf) ? O_RDWR | O_CREAT : O_RDONLY;
+                filp = filp_open(filename, mode, S_IRUSR);
+                if (IS_ERR(filp) || !filp->f_op) {
+                        esp_dbg(ESP_DBG_ERROR, "%s: file %s filp_open error\n", __FUNCTION__, filename);
+                        ret = -ENOENT;
+                        break;
+                }
+
+                if (length==0) {
+                        /* Read the length of the file only */
+                        struct inode    *inode;
+
+                        inode = GET_INODE_FROM_FILEP(filp);
+                        if (!inode) {
+                                esp_dbg(ESP_DBG_ERROR, "%s: Get inode from %s failed\n", __FUNCTION__, filename);
+                                ret = -ENOENT;
+                                break;
+                        }
+                        ret = i_size_read(inode->i_mapping->host);
+                        break;
+                }
+
+                if (wbuf) {
+                        if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) {
+                                esp_dbg(ESP_DBG_ERROR, "%s: Write %u bytes to file %s error %d\n", __FUNCTION__,
+                                        length, filename, ret);
+                                break;
+                        }
+                } else {
+                        if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) {
+                                esp_dbg(ESP_DBG_ERROR, "%s: Read %u bytes from file %s error %d\n", __FUNCTION__,
+                                        length, filename, ret);
+                                break;
+                        }
+                }
+        } while (0);
+
+        if (!IS_ERR(filp)) {
+                filp_close(filp, NULL);
+        }
+        set_fs(oldfs);
+
+        return ret;
+}
+
+int android_request_firmware(const struct firmware **firmware_p, const char *name,
+                             struct device *device)
+{
+        int ret = 0;
+        struct firmware *firmware;
+        char filename[256];
+        const char *raw_filename = name;
+        *firmware_p = firmware = kmalloc((sizeof(*firmware)), GFP_KERNEL);
+        if (!firmware)
+                return -ENOMEM;
+
+        memset(firmware, 0, sizeof(*firmware));
+
+       if (mod_eagle_path_get() == NULL)
+               sprintf(filename, "%s/%s", FWPATH, raw_filename);
+       else 
+               sprintf(filename, "%s/%s", mod_eagle_path_get(), raw_filename);
+
+        do {
+                size_t length, bufsize, bmisize;
+
+                if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) {
+                        break;
+                } else {
+                        length = ret;
+                }
+
+                bufsize = ALIGN(length, PAGE_SIZE);
+                bmisize = E_ROUND_UP(length, 4);
+                bufsize = max(bmisize, bufsize);
+                firmware->data = vmalloc(bufsize);
+                firmware->size = length;
+                if (!firmware->data) {
+                        esp_dbg(ESP_DBG_ERROR, "%s: Cannot allocate buffer for firmware\n", __FUNCTION__);
+                        ret = -ENOMEM;
+                        break;
+                }
+
+                if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) {
+                        esp_dbg(ESP_DBG_ERROR, "%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length);
+                        ret = -1;
+                        break;
+                }
+
+        } while (0);
+
+        if (ret<0) {
+                if (firmware) {
+                        if (firmware->data)
+                                vfree(firmware->data);
+
+                        kfree(firmware);
+                }
+                *firmware_p = NULL;
+        } else {
+                ret = 0;
+        }
+
+        return ret;
+}
+
+void android_release_firmware(const struct firmware *firmware)
+{
+        if (firmware) {
+                if (firmware->data)
+                        vfree(firmware->data);
+
+                kfree((struct firmware *)firmware);
+        }
+}
+
+int logger_write( const unsigned char prio,
+                  const char __kernel * const tag,
+                  const char __kernel * const fmt,
+                  ...)
+{
+        int ret = 0;
+        va_list vargs;
+        struct file *filp = (struct file *)-ENOENT;
+        mm_segment_t oldfs;
+        struct iovec vec[3];
+        int tag_bytes = strlen(tag) + 1, msg_bytes;
+        char *msg;
+        va_start(vargs, fmt);
+        msg = kvasprintf(GFP_ATOMIC, fmt, vargs);
+        va_end(vargs);
+        if (!msg)
+                return -ENOMEM;
+        if (in_interrupt()) {
+                /* we have no choice since aio_write may be blocked */
+                printk(KERN_ALERT "%s", msg);
+                goto out_free_message;
+        }
+        msg_bytes = strlen(msg) + 1;
+        if (msg_bytes <= 1) /* empty message? */
+                goto out_free_message; /* don't bother, then */
+        if ((msg_bytes + tag_bytes + 1) > 2048) {
+                ret = -E2BIG;
+                goto out_free_message;
+        }
+
+        vec[0].iov_base  = (unsigned char *) &prio;
+        vec[0].iov_len    = 1;
+        vec[1].iov_base   = (void *) tag;
+        vec[1].iov_len    = strlen(tag) + 1;
+        vec[2].iov_base   = (void *) msg;
+        vec[2].iov_len    = strlen(msg) + 1;
+
+        oldfs = get_fs();
+        set_fs(KERNEL_DS);
+        do {
+                filp = filp_open("/dev/log/main", O_WRONLY, S_IRUSR);
+                if (IS_ERR(filp) || !filp->f_op) {
+
+                        esp_dbg(ESP_DBG_ERROR, "%s: filp open /dev/log/main error\n", __FUNCTION__);
+                        ret = -ENOENT;
+                        break;
+                }
+
+                if (filp->f_op->aio_write) {
+                        int nr_segs = sizeof(vec) / sizeof(vec[0]);
+                        int len = vec[0].iov_len + vec[1].iov_len + vec[2].iov_len;
+                        struct kiocb kiocb;
+                        init_sync_kiocb(&kiocb, filp);
+                        kiocb.ki_pos = 0;
+                        kiocb.ki_left = len;
+                        kiocb.ki_nbytes = len;
+                        ret = filp->f_op->aio_write(&kiocb, vec, nr_segs, kiocb.ki_pos);
+                }
+
+        } while (0);
+
+        if (!IS_ERR(filp)) {
+                filp_close(filp, NULL);
+        }
+        set_fs(oldfs);
+out_free_message:
+        if (msg) {
+                kfree(msg);
+        }
+        return ret;
+}
+
+
+
+struct esp_init_table_elem esp_init_table[MAX_ATTR_NUM] = {
+       {"crystal_26M_en",      48, -1}, 
+       {"test_xtal",           49, -1},
+       {"sdio_configure",      50, -1},
+       {"bt_configure",        51, -1},
+       {"bt_protocol",         52, -1},
+       {"dual_ant_configure",  53, -1},
+       {"test_uart_configure", 54, -1},
+       {"share_xtal",          55, -1},
+       {"gpio_wake",           56, -1},
+       {"no_auto_sleep",       57, -1},
+       {"attr10",              -1, -1},
+       {"attr11",              -1, -1},
+       {"attr12",              -1, -1},
+       {"attr13",              -1, -1},
+       {"attr14",              -1, -1},
+       {"attr15",              -1, -1},
+       //attr that is not send to target
+       {"ext_rst",              -1, -1},
+       {"wakeup_gpio",         -1, -1},
+        {"attr18",              -1, -1},
+        {"attr19",              -1, -1},
+        {"attr20",              -1, -1},
+        {"attr21",              -1, -1},
+        {"attr22",              -1, -1},
+        {"attr23",              -1, -1},
+       
+};
+
+int esp_atoi(char *str)
+{
+        int num = 0;
+        int ng_flag = 0;
+
+        if (*str == '-') {
+                str++;
+                ng_flag = 1;
+        }
+
+        while(*str != '\0') {
+                num = num * 10 + *str++ - '0';
+        }
+
+        return ng_flag ? 0-num : num;
+}
+
+void show_esp_init_table(struct esp_init_table_elem *econf)
+{
+       int i;
+       for (i = 0; i < MAX_ATTR_NUM; i++)
+               if (esp_init_table[i].offset > -1)
+                       esp_dbg(ESP_DBG_ERROR, "%s: esp_init_table[%d] attr[%s] offset[%d] value[%d]\n", 
+                               __FUNCTION__, i,
+                               esp_init_table[i].attr,
+                               esp_init_table[i].offset,
+                               esp_init_table[i].value);
+}
+       
+int android_request_init_conf(void)
+{
+
+       u8 *conf_buf;
+       u8 *pbuf;
+       int flag;
+       int str_len;    
+       int length;
+       int ret;
+       int i;
+       char attr_name[CONF_ATTR_LEN];
+       char num_buf[CONF_VAL_LEN];
+#ifdef INIT_DATA_CONF
+       char filename[256];
+
+       if (mod_eagle_path_get() == NULL)
+               sprintf(filename, "%s/%s", FWPATH, INIT_CONF_FILE);
+       else
+               sprintf(filename, "%s/%s", mod_eagle_path_get(), INIT_CONF_FILE);
+
+       if ((ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0 || ret > MAX_BUF_LEN) {
+               esp_dbg(ESP_DBG_ERROR, "%s: file read length error, ret %d\n", __FUNCTION__, ret);
+               return -1;
+       } else {
+                length = ret;
+        }
+#endif /* INIT_DATA_CONF */
+       conf_buf = (u8 *)kmalloc(MAX_BUF_LEN, GFP_KERNEL);
+        if (conf_buf == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "%s: failed kmalloc memory for read init_data_conf", __func__);
+                return -ENOMEM;
+        }
+
+#ifdef INIT_DATA_CONF
+       if ((ret=android_readwrite_file(filename, conf_buf, NULL, length)) != length) {
+               esp_dbg(ESP_DBG_ERROR, "%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length);
+               goto failed;
+       }
+#else
+       length = strlen(INIT_DATA_CONF_BUF);
+       strncpy(conf_buf, INIT_DATA_CONF_BUF, length); 
+#endif
+       conf_buf[length] = '\0';
+
+       flag = 0;
+       str_len = 0;
+       for (pbuf = conf_buf; *pbuf != '$' && *pbuf != '\n'; pbuf++) {
+               if (*pbuf == '=') {
+                       flag = 1;
+                       *(attr_name+str_len) = '\0';
+                       str_len = 0;
+                       continue;
+               }
+
+               if (*pbuf == ';') {
+                       int value;
+                       flag = 0;
+                       *(num_buf+str_len) = '\0';
+                       if((value = esp_atoi(num_buf)) > 255 || value < 0){
+                               esp_dbg(ESP_DBG_ERROR, "%s: value is too big", __FUNCTION__);
+                               goto failed;
+                       }
+
+                       for (i = 0; i < MAX_ATTR_NUM; i++) {
+                               if (esp_init_table[i].value > -1)
+                                       continue;
+                               if (strcmp(esp_init_table[i].attr, attr_name) == 0) {
+                                       esp_dbg(ESP_DBG_TRACE, "%s: attr_name[%s]", __FUNCTION__, attr_name); /* add by th */
+                                       esp_init_table[i].value = value;
+                               }
+                               if(strcmp(esp_init_table[i].attr, "share_xtal") == 0){
+                                       sif_record_bt_config(esp_init_table[i].value);
+                               }
+
+                               if(strcmp(esp_init_table[i].attr, "ext_rst") == 0){
+                                       sif_record_rst_config(esp_init_table[i].value);
+                               }
+
+                               if(strcmp(esp_init_table[i].attr, "wakeup_gpio") == 0){
+                                       sif_record_wakeup_gpio_config(esp_init_table[i].value);
+                               }
+                       }
+                       str_len = 0;
+                       continue;
+               }
+
+               if (flag == 0) {
+                       *(attr_name+str_len) = *pbuf;
+                       if (++str_len > CONF_ATTR_LEN) {
+                               esp_dbg(ESP_DBG_ERROR, "%s: attr len is too long", __FUNCTION__);
+                               goto failed;
+                       }
+               } else {
+                       *(num_buf+str_len) = *pbuf;
+                       if (++str_len > CONF_VAL_LEN) {
+                               esp_dbg(ESP_DBG_ERROR, "%s: value len is too long", __FUNCTION__);
+                               goto failed;
+                       }       
+               }
+       }
+
+       //show_esp_init_table(esp_init_table);
+
+       ret = 0;
+failed:
+       if (conf_buf)
+               kfree(conf_buf);
+       return ret;
+}
+
+void fix_init_data(u8 *init_data_buf, int buf_size)
+{
+       int i;
+
+       for (i = 0; i < MAX_FIX_ATTR_NUM; i++) {
+               if (esp_init_table[i].offset > -1 && esp_init_table[i].offset < buf_size && esp_init_table[i].value > -1) {
+                       *(u8 *)(init_data_buf + esp_init_table[i].offset) = esp_init_table[i].value;
+                } else if (esp_init_table[i].offset > buf_size) {
+                       esp_dbg(ESP_DBG_ERROR, "%s: offset[%d] longer than init_data_buf len[%d] Ignore\n", __FUNCTION__, esp_init_table[i].offset, buf_size);
+               }
+        }
+
+}
+
+void show_init_buf(u8 *buf, int size)
+{
+       int i = 0;
+       
+       for (i = 0; i < size; i++)
+                       printk(KERN_ERR "offset[%d] [0x%02x]", i, buf[i]);
+       printk(KERN_ERR "\n");
+               
+}
+
+#endif //ANDROID
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_android.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_android.h
new file mode 100755 (executable)
index 0000000..ddd9a7d
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _ESP_ANDROID_H
+#define _ESP_ANDROID_H
+
+#include <linux/version.h>
+#include <linux/firmware.h>
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+#define GET_INODE_FROM_FILEP(filp) \
+    (filp)->f_path.dentry->d_inode
+#else
+#define GET_INODE_FROM_FILEP(filp) \
+    (filp)->f_dentry->d_inode
+#endif
+
+#define E_ROUND_UP(x, y)  ((((x) + ((y) - 1)) / (y)) * (y))
+
+#ifdef ANDROID
+int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length);
+
+int android_request_firmware(const struct firmware **firmware_p, const char *name, struct device *device);
+
+void android_release_firmware(const struct firmware *firmware);
+
+#ifdef INIT_DATA_CONF
+#define INIT_CONF_FILE "init_data.conf"
+#endif /* def INIT_DATA_CONF */
+
+#define CONF_ATTR_LEN 24
+#define CONF_VAL_LEN 3
+#define MAX_ATTR_NUM 24
+#define MAX_FIX_ATTR_NUM 16
+#define MAX_BUF_LEN ((CONF_ATTR_LEN + CONF_VAL_LEN + 2) * MAX_ATTR_NUM + 2)
+
+struct esp_init_table_elem {
+       char attr[CONF_ATTR_LEN];
+       int offset;
+       short value;
+};
+
+int android_request_init_conf(void);
+void fix_init_data(u8 *init_data_buf, int buf_size);
+void show_init_buf(u8 *buf, int size);
+
+
+#endif
+
+#if defined(ANDROID) && defined(ESP_ANDROID_LOGGER)
+extern int logger_write( const unsigned char prio,
+                         const char __kernel * const tag,
+                         const char __kernel * const fmt,
+                         ...);
+
+
+#endif // ANDROID
+#endif
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_cfg80211.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_cfg80211.c
new file mode 100755 (executable)
index 0000000..cdada7d
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2010 - 2012 Espressif System.
+ */
+#if 0
+#define RATETAB_ENT(_rate, _rateid, _flags) {   \
+       .bitrate    = (_rate),                  \
+       .flags      = (_flags),                 \
+       .hw_value   = (_rateid),                \
+}
+
+#define CHAN2G(_channel, _freq, _flags) {   \
+       .band           = IEEE80211_BAND_2GHZ,  \
+       .hw_value       = (_channel),           \
+       .center_freq    = (_freq),              \
+       .flags          = (_flags),             \
+       .max_antenna_gain   = 0,                \
+       .max_power      = 30,                   \
+}
+
+static struct ieee80211_channel esp_2ghz_channels[] = {
+        CHAN2G(1, 2412, 0),
+        CHAN2G(2, 2417, 0),
+        CHAN2G(3, 2422, 0),
+        CHAN2G(4, 2427, 0),
+        CHAN2G(5, 2432, 0),
+        CHAN2G(6, 2437, 0),
+        CHAN2G(7, 2442, 0),
+        CHAN2G(8, 2447, 0),
+        CHAN2G(9, 2452, 0),
+        CHAN2G(10, 2457, 0),
+        CHAN2G(11, 2462, 0),
+        CHAN2G(12, 2467, 0),
+        CHAN2G(13, 2472, 0),
+        CHAN2G(14, 2484, 0),
+};
+
+static int esp_cfg80211_change_iface(struct wiphy *wiphy,
+                                     struct net_device *ndev,
+                                     enum nl80211_iftype type, u32 *flags,
+                                     struct vif_params *params)
+{
+        struct esp_pub *epub = wdev_priv(dev->ieee80211_ptr);
+        struct wireless_dev *wdev = epub->wdev;
+
+
+        /* only support STA mode for now */
+        if (type != NL80211_IFTYPE_STATION)
+                return -EOPNOTSUPP;
+}
+
+wdev->iftype = type;
+
+return 0;
+}
+
+static int esp_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+                             struct cfg80211_scan_request *request)
+{
+        struct esp_pub *epub = wdev_priv(dev->ieee80211_ptr);
+        int ret = 0;
+
+        if (!esp_ready(ar))
+                return -EIO;
+
+        if (request->n_ssids && request->ssids[0].ssid_len) {
+                u8 i;
+
+                if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
+                        request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
+
+                for (i = 0; i < request->n_ssids; i++)
+                        esp_wl_probedssid_cmd(epub->wl, i + 1,
+                                              SPECIFIC_SSID_FLAG,
+                                              request->ssids[i].ssid_len,
+                                              request->ssids[i].ssid);
+        }
+
+        if (esp_wl_startscan_cmd(epub->wl, WL_LONG_SCAN, 0,
+                                 false, 0, 0, 0, NULL) != 0) {
+                esp_dbg(ESP_DBG_ERROR, "wl_startscan_cmd failed\n");
+                ret = -EIO;
+        }
+
+        epub->wl->scan_req = request;
+
+        return ret;
+}
+
+static struct cfg80211_ops esp_cfg80211_ops = {
+        .change_virtual_intf = esp_cfg80211_change_iface,
+        .scan = esp_cfg80211_scan,
+        .connect = esp_cfg80211_connect,
+        .disconnect = esp_cfg80211_disconnect,
+        .add_key = esp_cfg80211_add_key,
+        .get_key = esp_cfg80211_get_key,
+        .del_key = esp_cfg80211_del_key,
+        .set_default_key = esp_cfg80211_set_default_key,
+        .set_wiphy_params = esp_cfg80211_set_wiphy_params,
+        .set_tx_power = esp_cfg80211_set_txpower,
+        .get_tx_power = esp_cfg80211_get_txpower,
+        .set_power_mgmt = esp_cfg80211_set_power_mgmt,
+        .join_ibss = esp_cfg80211_join_ibss,
+        .leave_ibss = esp_cfg80211_leave_ibss,
+        .get_station = esp_get_station,
+        .set_pmksa = esp_set_pmksa,
+        .del_pmksa = esp_del_pmksa,
+        .flush_pmksa = esp_flush_pmksa,
+};
+
+static struct ieee80211_ops esp_ieee80211_ops = {
+}
+
+static struct cfg80211_ops esp_cfg80211_ops = {0};
+
+static struct ieee80211_rate esp_g_rates[] = {
+        RATETAB_ENT(10, 0x1, 0),
+        RATETAB_ENT(20, 0x2, 0),
+        RATETAB_ENT(55, 0x4, 0),
+        RATETAB_ENT(110, 0x8, 0),
+        RATETAB_ENT(60, 0x10, 0),
+        RATETAB_ENT(90, 0x20, 0),
+        RATETAB_ENT(120, 0x40, 0),
+        RATETAB_ENT(180, 0x80, 0),
+        RATETAB_ENT(240, 0x100, 0),
+        RATETAB_ENT(360, 0x200, 0),
+        RATETAB_ENT(480, 0x400, 0),
+        RATETAB_ENT(540, 0x800, 0),
+};
+
+#define esp_g_rates_size 12
+static struct ieee80211_supported_band esp_band_2ghz = {
+        .n_channels = ARRAY_SIZE(esp_2ghz_channels),
+        .channels = esp_2ghz_channels,
+        .n_bitrates = esp_g_rates_size,
+        .bitrates = esp_g_rates,
+};
+
+static const u32 cipher_suites[] = {
+        WLAN_CIPHER_SUITE_WEP40,
+        WLAN_CIPHER_SUITE_WEP104,
+        WLAN_CIPHER_SUITE_TKIP,
+        WLAN_CIPHER_SUITE_CCMP,
+};
+
+static struct wireless_dev *
+esp_cfg80211_init(struct device *dev) {
+        int ret = 0;
+        struct wireless_dev *wdev;
+
+        wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+
+        if (!wdev) {
+                esp_dbg(ESP_DBG_ERROR, "couldn't allocate wireless device\n");
+                return NULL;
+        }
+
+        wdev->wiphy = wiphy_new(&esp_cfg80211_ops, sizeof(struct esp_pub));
+
+        if (!wdev->wiphy) {
+                esp_dbg(ESP_DBG_ERROR, "couldn't allocate wiphy device\n");
+                kfree(wdev);
+                return NULL;
+        }
+
+        set_wiphy_dev(wdev->wiphy, dev);
+
+        wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+        wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
+        wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &esp_band_2ghz;
+        //wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &esp_band_5ghz;
+        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+        wdev->wiphy->cipher_suites = cipher_suites;
+        wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
+        ret = wiphy_register(wdev->wiphy);
+
+        if (ret < 0) {
+                esp_dbg(ESP_DBG_ERROR, "couldn't register wiphy device\n");
+                wiphy_free(wdev->wiphy);
+                kfree(wdev);
+                return NULL;
+        }
+
+        return wdev;
+}
+
+static void
+esp_cfg80211_descory(struct esp_pub *pub)
+{
+        return;
+}
+
+static int esp_open(struct net_device *dev)
+{
+        return 0;
+}
+
+static struct net_device_stats *
+esp_get_stats(struct net_device *dev) {
+        struct net_device_stats *stats = NULL;
+        return stats;
+}
+
+static int esp_close(struct net_device *dev)
+{
+        return 0;
+}
+
+
+static int esp_data_tx(struct sk_buff *skb, struct net_device *dev)
+{
+        return 0;
+}
+
+static struct net_device_ops esp_netdev_ops = {
+        .ndo_open               = esp_open,
+        .ndo_stop               = esp_close,
+        .ndo_start_xmit         = esp_data_tx,
+        .ndo_get_stats          = esp_get_stats,
+};
+
+static inline void
+esp_init_netdev(struct net_device *dev)
+{
+        dev->netdev_ops = &esp_netdev_ops;
+        dev->watchdog_timeo = 10;
+
+        dev->needed_headroom = ETH_HLEN + sizeof(struct llc_snap_hdr) + SIP_HDR_LEN;
+
+        return;
+}
+
+static void
+esp_disconnect(struct esp_pub *epub)
+{
+        return;
+}
+
+static void
+esp_disconnect_timeout_handler(unsigned long ptr)
+{
+        struct net_device *netdev = (struct net_device *)ptr;
+        struct esp_pub *epub = wdev_priv(netdev->ieee80211_ptr);
+
+        //esp_init_profile(epub);
+        esp_disconnect(epub);
+}
+
+struct esp_pub *
+esp_pub_alloc_cfg80211(struct device *dev) {
+        struct net_device *netdev;
+        struct wireless_dev *wdev;
+        struct esp_pub *epub;
+        struct esp_wl *wl;
+
+        wdev = esp_cfg80211_init(dev);
+
+        if (wdev == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "%s: cfg80211_init failed \n", __func__);
+                return NULL;
+        }
+
+        epub = wdev_priv(wdev);
+        epub->dev = dev;
+        epub->wdev = wdev;
+        wdev->iftype = NL80211_IFTYPE_STATION;
+
+        /* Still register ethernet device */
+        netdev = alloc_netdev(0, "wlan%d", ether_setup);
+
+        if (!netdev) {
+                esp_dbg(ESP_DBG_ERROR, "%s: alloc_netdev failed \n", __func__);
+                esp_cfg80211_descory(epub);
+                return NULL;
+        }
+
+        netdev->ieee80211_ptr = wdev;
+        SET_NETDEV_DEV(netdev, wiphy_dev(wdev->wiphy));
+        wdev->netdev = netdev;
+
+        esp_init_netdev(netdev);
+
+        epub->net_dev = netdev;
+
+        //spin_lock_init(&epub->lock);
+
+        wl = &epub->wl;
+        //esp_init_wl(wl);
+        init_waitqueue_head(&epub->ev_waitq);
+        //sema_init(epub->sem, 1);
+
+        INIT_LIST_HEAD(&wl->amsdu_rx_buffer_queue);
+
+        setup_timer(&wl->disconnect_timer, esp_disconnect_timeout_handler,
+                    (unsigned long) netdev);
+
+        return epub;
+}
+
+#endif
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_conf.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_conf.h
new file mode 100755 (executable)
index 0000000..f21c921
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ESP_CONF_H_
+#define _ESP_CONF_H_
+
+#define INIT_DATA_CONF_BUF "crystal_26M_en=1;test_xtal=0;sdio_configure=2;bt_configure=0;bt_protocol=0;dual_ant_configure=0;test_uart_configure=2;share_xtal=0;gpio_wake=0;no_auto_sleep=0;ext_rst=0;$"
+
+#endif /*_ESP_CONF_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_config.mk b/drivers/net/wireless/rockchip_wlan/esp8089/esp_config.mk
new file mode 100755 (executable)
index 0000000..2026cdf
--- /dev/null
@@ -0,0 +1 @@
+EXTRA_CFLAGS += -DP2P_CONCURRENT -DESP_ACK_INTERRUPT -DESP_USE_SDIO
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_ctrl.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_ctrl.c
new file mode 100755 (executable)
index 0000000..8c7c555
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * Copyright (c) 2009 - 2012 Espressif System.
+ */
+
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/firmware.h>
+
+#include "esp_pub.h"
+#include "esp_sip.h"
+#include "esp_ctrl.h"
+#include "esp_sif.h"
+#include "esp_debug.h"
+#include "slc_host_register.h"
+#include "esp_wmac.h"
+#include "esp_utils.h"
+#include "esp_wl.h"
+#ifdef ANDROID
+#include "esp_android.h"
+#include "esp_path.h"
+#endif /* ANDROID */
+#ifdef TEST_MODE
+#include "testmode.h"
+#endif /* TEST_MODE */
+#include "esp_version.h"
+
+extern struct completion *gl_bootup_cplx; 
+
+#ifdef ESP_RX_COPYBACK_TEST
+static void sip_show_copyback_buf(void)
+{
+        //show_buf(copyback_buf, copyback_offset);
+}
+#endif /* ESP_RX_COPYBACK_TEST */
+
+static void esp_tx_ba_session_op(struct esp_sip *sip, struct esp_node *node, trc_ampdu_state_t state, u8 tid )
+{
+        struct esp_tx_tid *txtid;
+
+        txtid = &node->tid[tid];
+        if (state == TRC_TX_AMPDU_STOPPED) {
+                if (txtid->state == ESP_TID_STATE_OPERATIONAL) {
+                        esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT\n", __func__, tid);
+
+                        spin_lock_bh(&sip->epub->tx_ampdu_lock);
+                        txtid->state = ESP_TID_STATE_WAIT_STOP;
+                        spin_unlock_bh(&sip->epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                        ieee80211_stop_tx_ba_session(sip->epub->hw, node->addr, (u16)tid, WLAN_BACK_INITIATOR);
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
+                        ieee80211_stop_tx_ba_session(sip->epub->hw, node->sta->addr, (u16)tid, WLAN_BACK_INITIATOR);
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+                        ieee80211_stop_tx_ba_session(node->sta, (u16)tid, WLAN_BACK_INITIATOR);
+#else
+                        ieee80211_stop_tx_ba_session(node->sta, (u16)tid);
+#endif /* KERNEL_VERSION 2.6.39 */
+                } else {
+                        esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
+                }
+        } else if (state == TRC_TX_AMPDU_OPERATIONAL) {
+                if (txtid->state == ESP_TID_STATE_STOP) {
+                        esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL\n", __func__, tid);
+
+                        spin_lock_bh(&sip->epub->tx_ampdu_lock);
+                        txtid->state = ESP_TID_STATE_TRIGGER;
+                        spin_unlock_bh(&sip->epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                        ieee80211_start_tx_ba_session(sip->epub->hw, node->addr, tid);
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
+                        ieee80211_start_tx_ba_session(sip->epub->hw, node->sta->addr, tid);
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 37))
+                        ieee80211_start_tx_ba_session(node->sta, (u16)tid);
+#else
+                        ieee80211_start_tx_ba_session(node->sta, (u16)tid, 0);
+#endif /* KERNEL_VERSION 2.6.39 */
+
+                } else if(txtid->state == ESP_TID_STATE_OPERATIONAL) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                       sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->addr, tid, node->ifidx, 0);
+#else
+                       sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->sta->addr, tid, node->ifidx, 0);
+#endif
+               } else {
+                        esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
+                }
+        }
+}
+
+int sip_parse_events(struct esp_sip *sip, u8 *buf)
+{
+        struct sip_hdr *hdr = (struct sip_hdr *)buf;
+
+        switch (hdr->c_evtid) {
+       case SIP_EVT_TARGET_ON: {
+               /* use rx work queue to send... */
+               if (atomic_read(&sip->state) == SIP_PREPARE_BOOT || atomic_read(&sip->state) == SIP_BOOT) {
+                       atomic_set(&sip->state, SIP_SEND_INIT);
+                       queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
+               } else {
+                       esp_dbg(ESP_DBG_ERROR, "%s boot during wrong state %d\n", __func__, atomic_read(&sip->state));
+               }
+                break;
+       }
+
+        case SIP_EVT_BOOTUP: {
+               struct sip_evt_bootup2 *bootup_evt = (struct sip_evt_bootup2 *)(buf + SIP_CTRL_HDR_LEN);
+               if (sip->rawbuf)
+                       kfree(sip->rawbuf);
+               
+               sip_post_init(sip, bootup_evt);
+               
+               if (gl_bootup_cplx)     
+                       complete(gl_bootup_cplx);
+                
+               break;
+        }
+       case SIP_EVT_RESETTING:{
+               if (gl_bootup_cplx)     
+                       complete(gl_bootup_cplx);
+               break;
+       }
+       case SIP_EVT_SLEEP:{
+               //atomic_set(&sip->epub->ps.state, ESP_PM_ON);
+               break;
+       }
+       case SIP_EVT_TXIDLE:{
+               //struct sip_evt_txidle *txidle = (struct sip_evt_txidle *)(buf + SIP_CTRL_HDR_LEN);
+               //sip_txdone_clear(sip, txidle->last_seq);
+               break;
+       }
+#ifndef FAST_TX_STATUS
+        case SIP_EVT_TX_STATUS: {
+                struct sip_evt_tx_report *report = (struct sip_evt_tx_report *)(buf + SIP_CTRL_HDR_LEN);
+                sip_txdoneq_process(sip, report);
+
+                break;
+        }
+#endif /* FAST_TX_STATUS */
+
+        case SIP_EVT_SCAN_RESULT: {
+                struct sip_evt_scan_report *report = (struct sip_evt_scan_report *)(buf + SIP_CTRL_HDR_LEN);
+                if (atomic_read(&sip->epub->wl.off)) {
+                        esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
+                        return 0;
+                }
+                sip_scandone_process(sip, report);
+
+                break;
+        }
+
+               case SIP_EVT_ROC: {
+                struct sip_evt_roc* report = (struct sip_evt_roc *)(buf + SIP_CTRL_HDR_LEN);
+                esp_rocdone_process(sip->epub->hw, report);
+                break;
+        }
+
+
+#ifdef ESP_RX_COPYBACK_TEST
+
+        case SIP_EVT_COPYBACK: {
+                u32 len = hdr->len - SIP_CTRL_HDR_LEN;
+
+                esp_dbg(ESP_DBG_TRACE, "%s copyback len %d   seq %u\n", __func__, len, hdr->seq);
+
+                memcpy(copyback_buf + copyback_offset, pkt->buf + SIP_CTRL_HDR_LEN, len);
+                copyback_offset += len;
+
+                //show_buf(pkt->buf, 256);
+
+                //how about totlen % 256 == 0??
+                if (hdr->hdr.len < 256) {
+                        //sip_show_copyback_buf();
+                        kfree(copyback_buf);
+                }
+        }
+        break;
+#endif /* ESP_RX_COPYBACK_TEST */
+        case SIP_EVT_CREDIT_RPT:
+                break;
+
+#ifdef TEST_MODE
+        case SIP_EVT_WAKEUP: {
+                u8 check_str[12];
+                struct sip_evt_wakeup* wakeup_evt=  (struct sip_evt_wakeup *)(buf + SIP_CTRL_HDR_LEN);
+                sprintf((char *)&check_str, "%d", wakeup_evt->check_data);
+                esp_test_cmd_event(TEST_CMD_WAKEUP, (char *)&check_str);
+                break;
+        }
+
+        case SIP_EVT_DEBUG: {
+                u8 check_str[100];
+                int i;
+                char * ptr_str = (char *)& check_str;
+                struct sip_evt_debug* debug_evt =  (struct sip_evt_debug *)(buf + SIP_CTRL_HDR_LEN);
+                for(i = 0; i < debug_evt->len; i++)
+                        ptr_str += sprintf(ptr_str, "0x%x%s", debug_evt->results[i], i == debug_evt->len -1 ? "":" " );
+                esp_test_cmd_event(TEST_CMD_DEBUG, (char *)&check_str);
+                break;
+        }
+
+        case SIP_EVT_LOOPBACK: {
+                u8 check_str[12];
+                struct sip_evt_loopback *loopback_evt = (struct sip_evt_loopback *)(buf + SIP_CTRL_HDR_LEN);
+                esp_dbg(ESP_DBG_LOG, "%s loopback len %d seq %u\n", __func__,hdr->len, hdr->seq);
+
+                if(loopback_evt->pack_id!=get_loopback_id()) {
+                        sprintf((char *)&check_str, "seq id error %d, expect %d", loopback_evt->pack_id, get_loopback_id());
+                        esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
+                }
+
+                if((loopback_evt->pack_id+1) <get_loopback_num()) {
+                        inc_loopback_id();
+                        sip_send_loopback_mblk(sip, loopback_evt->txlen, loopback_evt->rxlen, get_loopback_id());
+                } else {
+                        sprintf((char *)&check_str, "test over!");
+                        esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
+                }
+                break;
+        }
+#endif  /*TEST_MODE*/
+
+        case SIP_EVT_SNPRINTF_TO_HOST: {
+                u8 *p = (buf + sizeof(struct sip_hdr) + sizeof(u16));
+                u16 *len = (u16 *)(buf + sizeof(struct sip_hdr));
+               char test_res_str[560];
+               sprintf(test_res_str, "esp_host:%llx\nesp_target: %.*s", DRIVER_VER, *len, p);
+               
+                esp_dbg(ESP_SHOW, "%s\n", test_res_str);
+#ifdef ANDROID
+               if(*len && sip->epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+                       char filename[256];
+                       if (mod_eagle_path_get() == NULL)
+                               sprintf(filename, "%s/%s", FWPATH, "test_results");
+                       else
+                               sprintf(filename, "%s/%s", mod_eagle_path_get(), "test_results");
+                       android_readwrite_file(filename, NULL, test_res_str, strlen(test_res_str));
+               }
+#endif
+                break;
+        }
+        case SIP_EVT_TRC_AMPDU: {
+                struct sip_evt_trc_ampdu *ep = (struct sip_evt_trc_ampdu*)(buf + SIP_CTRL_HDR_LEN);
+                struct esp_node *node = NULL;
+                int i = 0;
+
+                if (atomic_read(&sip->epub->wl.off)) {
+                        esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
+                        return 0;
+                }
+               
+               node = esp_get_node_by_addr(sip->epub, ep->addr);
+               if(node == NULL)
+                       break;
+#if 0
+                esp_tx_ba_session_op(sip, node, ep->state, ep->tid);
+#else
+                for (i = 0; i < 8; i++) {
+                        if (ep->tid & (1<<i)) {
+                                esp_tx_ba_session_op(sip, node, ep->state, i);
+                        }
+                }
+#endif
+                break;
+        }
+
+        default:
+                break;
+        }
+
+        return 0;
+}
+
+#ifdef HAS_INIT_DATA
+#include "esp_init_data.h"
+#else
+#define ESP_INIT_NAME "esp_init_data.bin"
+#endif /* HAS_INIT_DATA */
+
+void sip_send_chip_init(struct esp_sip *sip)
+{
+       size_t size = 0;
+#ifndef HAS_INIT_DATA
+        const struct firmware *fw_entry;
+        u8 * esp_init_data = NULL;
+        int ret = 0;
+  #ifdef ANDROID
+        ret = android_request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
+  #else
+        ret = request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
+  #endif /* ANDROID */
+        
+        if (ret) {
+                esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO INIT DATA!!=================\n", __func__);
+               return;
+        }
+        esp_init_data = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+
+       size = fw_entry->size;
+
+  #ifdef ANDROID
+        android_release_firmware(fw_entry);
+  #else
+        release_firmware(fw_entry);
+  #endif /* ANDROID */
+
+        if (esp_init_data == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO MEMORY!!=================\n", __func__);
+               return;
+        }
+#else
+       size = sizeof(esp_init_data);
+
+#endif /* !HAS_INIT_DATA */
+
+#ifdef ANDROID
+       //show_init_buf(esp_init_data,size); 
+       fix_init_data(esp_init_data, size);
+       //show_init_buf(esp_init_data,size);
+#endif
+       atomic_sub(1, &sip->tx_credits);
+       
+       sip_send_cmd(sip, SIP_CMD_INIT, size, (void *)esp_init_data);
+
+#ifndef HAS_INIT_DATA
+        kfree(esp_init_data);
+#endif /* !HAS_INIT_DATA */
+}
+
+int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf)
+{
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_config *configcmd;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
+        if (!skb)
+                return -1;
+       // esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->channel->center_freq); add libing
+        configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
+       // configcmd->center_freq= conf->chandef.chan->center_freq; //add libing
+               configcmd->duration= 0;
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+int  sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc)
+{
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_bss_info_update*bsscmd;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_bss_info_update) + sizeof(struct sip_hdr), SIP_CMD_BSS_INFO_UPDATE);
+        if (!skb)
+                return -1;
+
+        bsscmd = (struct sip_cmd_bss_info_update *)(skb->data + sizeof(struct sip_hdr));
+        if (assoc == 2) { //hack for softAP mode
+                       bsscmd->beacon_int = evif->beacon_interval;
+               } else if (assoc == 1) {
+                       set_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
+        } else {
+                       clear_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
+        }
+               bsscmd->bssid_no = evif->index;
+               bsscmd->isassoc= assoc;
+        memcpy(bsscmd->bssid, bssid, ETH_ALEN);
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+int  sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params)
+{
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_set_wmm_params* bsscmd;
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_set_wmm_params) + sizeof(struct sip_hdr), SIP_CMD_SET_WMM_PARAM);
+        if (!skb)
+                return -1;
+
+        bsscmd = (struct sip_cmd_set_wmm_params *)(skb->data + sizeof(struct sip_hdr));
+        bsscmd->aci= aci;
+        bsscmd->aifs=params->aifs;
+        bsscmd->txop_us=params->txop*32;
+
+        bsscmd->ecw_min = 32 - __builtin_clz(params->cw_min);
+        bsscmd->ecw_max= 32 -__builtin_clz(params->cw_max);
+
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+//since we only support ba for only one ta for each tid, so index = tid
+static u8 find_empty_index(struct esp_pub *epub)
+{
+        return 0;
+}
+
+int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size)
+{
+        u8 index = find_empty_index(epub);
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_ampdu_action * action;
+        if(index < 0)
+                return -1;
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ampdu_action) + sizeof(struct sip_hdr), SIP_CMD_AMPDU_ACTION);
+        if(!skb)
+                return -1;
+
+        action = (struct sip_cmd_ampdu_action *)(skb->data + sizeof(struct sip_hdr));
+        action->action = action_num;
+       //for TX, it means interface index
+       action->index = ssn;
+
+        switch(action_num) {
+        case SIP_AMPDU_RX_START:
+                action->ssn = ssn;
+        case SIP_AMPDU_RX_STOP:
+                action->index = tid;
+        case SIP_AMPDU_TX_OPERATIONAL:
+        case SIP_AMPDU_TX_STOP:
+                action->win_size = buf_size;
+                action->tid = tid;
+                memcpy(action->addr, addr, ETH_ALEN);
+                break;
+        }
+
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+#ifdef HW_SCAN
+/*send cmd to target, if aborted is true, inform target stop scan, report scan complete imediately
+  return 1: complete over, 0: success, still have next scan, -1: hardware failure
+  */
+int sip_send_scan(struct esp_pub *epub)
+{
+        struct cfg80211_scan_request *scan_req = epub->wl.scan_req;
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_scan *scancmd;
+        u8 *ptr = NULL;
+        int i;
+       u8 append_len, ssid_len;
+
+        ASSERT(scan_req != NULL);
+        ssid_len = scan_req->n_ssids == 0 ? 0:
+                (scan_req->n_ssids == 1 ? scan_req->ssids->ssid_len: scan_req->ssids->ssid_len + (scan_req->ssids + 1)->ssid_len);
+        append_len = ssid_len + scan_req->n_channels + scan_req->ie_len;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_scan) + sizeof(struct sip_hdr) + append_len, SIP_CMD_SCAN);
+
+        if (!skb)
+                return -1;
+
+        ptr = skb->data;
+        scancmd = (struct sip_cmd_scan *)(ptr + sizeof(struct sip_hdr));
+        ptr += sizeof(struct sip_hdr);
+
+        scancmd->aborted= false;
+
+        if (scancmd->aborted==false) {
+               ptr += sizeof(struct sip_cmd_scan);
+                if (scan_req->n_ssids <=0 || (scan_req->n_ssids == 1&& ssid_len == 0)) {
+                        scancmd->ssid_len = 0;
+                } else { 
+                        scancmd->ssid_len = ssid_len;
+                       if(scan_req->ssids->ssid_len == ssid_len)
+                               memcpy(ptr, scan_req->ssids->ssid, scancmd->ssid_len);
+                       else
+                               memcpy(ptr, (scan_req->ssids + 1)->ssid, scancmd->ssid_len);
+                }
+
+               ptr += scancmd->ssid_len;
+                scancmd->n_channels=scan_req->n_channels;
+                for (i=0; i<scan_req->n_channels; i++)
+                        ptr[i] = scan_req->channels[i]->hw_value;
+               
+               ptr += scancmd->n_channels;
+               if (scan_req->ie_len && scan_req->ie != NULL) {
+                        scancmd->ie_len=scan_req->ie_len;
+                        memcpy(ptr, scan_req->ie, scan_req->ie_len);
+                } else {
+                       scancmd->ie_len = 0;
+               }
+               //add a flag that support two ssids,
+               if(scan_req->n_ssids > 1)
+                       scancmd->ssid_len |= 0x80;
+
+        }
+        
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+#endif
+
+int sip_send_suspend_config(struct esp_pub *epub, u8 suspend)
+{
+        struct sip_cmd_suspend *cmd = NULL;
+       struct sk_buff *skb = NULL;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_suspend) + sizeof(struct sip_hdr), SIP_CMD_SUSPEND);
+
+        if (!skb)
+                return -1;
+
+        cmd = (struct sip_cmd_suspend *)(skb->data + sizeof(struct sip_hdr));
+       cmd->suspend = suspend;
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps)
+{
+        struct sip_cmd_ps *pscmd = NULL;
+        struct sk_buff *skb = NULL;
+        struct sip_hdr *shdr = NULL;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ps) + sizeof(struct sip_hdr), SIP_CMD_PS);
+
+        if (!skb)
+               return -1;
+
+        shdr = (struct sip_hdr *)skb->data;
+        pscmd = (struct sip_cmd_ps *)(skb->data + sizeof(struct sip_hdr));
+
+        pscmd->dtim_period = ps->dtim_period;
+        pscmd->max_sleep_period = ps->max_sleep_period;
+#if 0
+        if (atomic_read(&ps->state) == ESP_PM_TURNING_ON) {
+                pscmd->on = 1;
+                SIP_HDR_SET_PM_TURNING_ON(shdr);
+        } else if (atomic_read(&ps->state) == ESP_PM_TURNING_OFF) {
+                pscmd->on = 0;
+                SIP_HDR_SET_PM_TURNING_OFF(shdr);
+        } else {
+                esp_dbg(ESP_DBG_ERROR, "%s PM WRONG STATE %d\n", __func__, atomic_read(&ps->state));
+                ASSERT(0);
+        }
+#endif
+
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report)
+{
+        struct esp_pub *epub = sip->epub;
+
+        esp_dbg(ESP_DBG_TRACE, "eagle hw scan report\n");
+
+        if (epub->wl.scan_req) {
+                hw_scan_done(epub, scan_report->aborted);
+                epub->wl.scan_req = NULL;
+        }
+}
+
+int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid)
+{
+        struct sip_cmd_setkey *setkeycmd;
+        struct sk_buff *skb = NULL;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setkey) + sizeof(struct sip_hdr), SIP_CMD_SETKEY);
+
+        if (!skb)
+                return -1;
+
+        setkeycmd = (struct sip_cmd_setkey *)(skb->data + sizeof(struct sip_hdr));
+
+        if (peer_addr) {
+                memcpy(setkeycmd->addr, peer_addr, ETH_ALEN);
+        } else {
+                memset(setkeycmd->addr, 0, ETH_ALEN);
+        }
+
+               setkeycmd->bssid_no = bssid_no;
+        setkeycmd->hw_key_idx= key->hw_key_idx;
+
+        if (isvalid) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+                setkeycmd->alg= key->alg;
+#else
+                setkeycmd->alg= esp_cipher2alg(key->cipher);
+#endif /* NEW_KERNEL */
+                setkeycmd->keyidx = key->keyidx;
+                setkeycmd->keylen = key->keylen;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+                if (key->alg == ALG_TKIP) {
+#else
+                if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+#endif /* NEW_KERNEL */
+                        memcpy(setkeycmd->key, key->key, 16);
+                        memcpy(setkeycmd->key+16,key->key+24,8);
+                        memcpy(setkeycmd->key+24,key->key+16,8);
+                } else {
+                        memcpy(setkeycmd->key, key->key, key->keylen);
+                }
+
+                setkeycmd->flags=1;
+        } else {
+                setkeycmd->flags=0;
+        }
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+#ifdef FPGA_LOOPBACK
+#define LOOPBACK_PKT_LEN 200
+int sip_send_loopback_cmd_mblk(struct esp_sip *sip)
+{
+        int cnt, ret;
+
+        for (cnt = 0; cnt < 4; cnt++) {
+                if (0!=(ret=sip_send_loopback_mblk(sip, LOOPBACK_PKT_LEN, LOOPBACK_PKT_LEN, 0)))
+                        return ret;
+        }
+        return 0;
+}
+#endif /* FPGA_LOOPBACK */
+
+int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id)
+{
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_loopback *cmd;
+        u8 *ptr = NULL;
+        int i, ret;
+
+        //send 100 loopback pkt
+        if(txpacket_len)
+                skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr) +  txpacket_len, SIP_CMD_LOOPBACK);
+        else
+                skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr), SIP_CMD_LOOPBACK);
+
+        if (!skb)
+                return -ENOMEM;
+
+        ptr = skb->data;
+        cmd = (struct sip_cmd_loopback *)(ptr + sizeof(struct sip_hdr));
+        ptr += sizeof(struct sip_hdr);
+        cmd->txlen = txpacket_len;
+        cmd->rxlen = rxpacket_len;
+        cmd->pack_id = packet_id;
+
+        if (txpacket_len) {
+                ptr += sizeof(struct sip_cmd_loopback);
+                /* fill up pkt payload */
+                for (i = 0; i < txpacket_len; i++) {
+                        ptr[i] = i;
+                }
+        }
+
+        ret = sip_cmd_enqueue(sip, skb);
+        if (ret <0)
+                return ret;
+
+        return 0;
+}
+
+//remain_on_channel 
+int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration)
+{
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_config *configcmd;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
+        if (!skb)
+                return -1;
+
+        configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
+        configcmd->center_freq= center_freq;
+        configcmd->duration= duration;
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index)
+#else
+int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node, struct ieee80211_vif *vif, u8 index)
+#endif
+{
+       struct sk_buff *skb = NULL;
+       struct sip_cmd_setsta *setstacmd;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+       struct ieee80211_ht_info ht_info = node->ht_info;
+#endif
+       skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setsta) + sizeof(struct sip_hdr), SIP_CMD_SETSTA);
+       if (!skb)
+       return -1;
+
+       setstacmd = (struct sip_cmd_setsta *)(skb->data + sizeof(struct sip_hdr));
+       setstacmd->ifidx = ifidx;
+       setstacmd->index = index;
+       setstacmd->set = set;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+       if(sta->aid == 0)
+               setstacmd->aid = vif->bss_conf.aid;
+       else
+               setstacmd->aid = sta->aid;
+       memcpy(setstacmd->mac, sta->addr, ETH_ALEN);
+       if(set){
+               if(sta->ht_cap.ht_supported){
+                       if(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
+                               setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
+                       else
+                               setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
+                       setstacmd->ampdu_factor = sta->ht_cap.ampdu_factor;
+                       setstacmd->ampdu_density = sta->ht_cap.ampdu_density;
+               } else {
+                       if(sta->supp_rates[IEEE80211_BAND_2GHZ] & (~(u32)CONF_HW_BIT_RATE_11B_MASK)){
+                               setstacmd->phymode = ESP_IEEE80211_T_OFDM;
+                       } else {
+                               setstacmd->phymode = ESP_IEEE80211_T_CCK;
+                       }
+               }
+       }
+#else
+    setstacmd->aid = node->aid;
+    memcpy(setstacmd->mac, node->addr, ETH_ALEN);
+    if(set){
+        if(ht_info.ht_supported){
+            if(ht_info.cap & IEEE80211_HT_CAP_SGI_20)
+                setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
+            else
+                setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
+            setstacmd->ampdu_factor = ht_info.ampdu_factor;
+            setstacmd->ampdu_density = ht_info.ampdu_density;
+        } else {
+            //note supp_rates is u64[] in 2.6.27
+            if(node->supp_rates[IEEE80211_BAND_2GHZ] & (~(u64)CONF_HW_BIT_RATE_11B_MASK)){
+                setstacmd->phymode = ESP_IEEE80211_T_OFDM;
+            } else {
+                setstacmd->phymode = ESP_IEEE80211_T_CCK;
+            }   
+        }   
+    }   
+#endif
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+
+int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len)
+{
+       struct sk_buff *skb = NULL;
+
+       skb = sip_alloc_ctrl_skbuf(epub->sip, cmd_len + sizeof(struct sip_hdr), cmd_id);
+       if (!skb)
+               return -1;
+
+       memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len);
+
+       return sip_cmd_enqueue(epub->sip, skb);
+}
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_ctrl.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_ctrl.h
new file mode 100755 (executable)
index 0000000..7523e2d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2009- 2012 Espressif System.
+ *
+ */
+#ifndef _ESP_CTRL_H_
+#define _ESP_CTRL_H_
+
+int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id);
+
+int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf);
+
+int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid);
+
+int sip_send_scan(struct esp_pub *epub);
+
+void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report);
+
+int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc);
+
+int  sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params);
+
+int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size);
+
+int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index);
+#else
+int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node,  struct ieee80211_vif *vif, u8 index);
+#endif
+
+int sip_send_suspend_config(struct esp_pub *epub, u8 suspend);
+
+int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps);
+
+int sip_parse_events(struct esp_sip *sip, u8 *buf);
+
+int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len);
+
+#ifdef ESP_RX_COPYBACK_TEST
+int sip_show_copyback_buf(void);
+#endif /* ESP_RX_COPYBACK_TEST */
+
+#endif /* _ESP_CTRL_H_ */
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_debug.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_debug.c
new file mode 100755 (executable)
index 0000000..ecc3d92
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2011 Espressif System.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <net/mac80211.h>
+#include "sip2_common.h"
+
+#include "esp_debug.h"
+
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG_FS)
+
+static struct dentry *esp_debugfs_root = NULL;
+
+static int esp_debugfs_open(struct inode *inode, struct file *filp)
+{
+        filp->private_data = inode->i_private;
+        return 0;
+}
+
+static ssize_t esp_debugfs_read(struct file *filp, char __user *buffer,
+                                size_t count, loff_t *ppos)
+{
+        if (*ppos >= 32)
+                return 0;
+        if (*ppos + count > 32)
+                count = 32 - *ppos;
+
+        if (copy_to_user(buffer, filp->private_data + *ppos, count))
+                return -EFAULT;
+
+        *ppos += count;
+
+        return count;
+}
+
+static ssize_t esp_debugfs_write(struct file *filp, const char __user *buffer,
+                                 size_t count, loff_t *ppos)
+{
+        if (*ppos >= 32)
+                return 0;
+        if (*ppos + count > 32)
+                count = 32 - *ppos;
+
+        if (copy_from_user(filp->private_data + *ppos, buffer, count))
+                return -EFAULT;
+
+        *ppos += count;
+
+        return count;
+}
+
+struct file_operations esp_debugfs_fops = {
+        .owner = THIS_MODULE,
+        .open = esp_debugfs_open,
+        .read = esp_debugfs_read,
+        .write = esp_debugfs_write,
+};
+
+
+struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type) {
+        struct dentry *rc = NULL;
+        umode_t mode = 0644;
+
+        if(!esp_debugfs_root)
+                return NULL;
+
+        if(!parent)
+                parent = esp_debugfs_root;
+
+        switch(type) {
+        case ESP_U8:
+                rc = debugfs_create_u8(name, mode, parent, (u8*)value);
+                break;
+        case ESP_U16:
+                rc = debugfs_create_u16(name, mode, parent, (u16*)value);
+                break;
+        case ESP_U32:
+                rc = debugfs_create_u32(name, mode, parent, (u32*)value);
+                break;
+        case ESP_U64:
+                rc = debugfs_create_u64(name, mode, parent, (u64*)value);
+                break;
+        case ESP_BOOL:
+                rc = debugfs_create_bool(name, mode, parent, (u32*)value);
+                break;
+        default: //32
+                rc = debugfs_create_u32(name, mode, parent, (u32*)value);
+        }
+
+        if (!rc)
+                goto Fail;
+        else
+                return rc;
+Fail:
+        debugfs_remove_recursive(esp_debugfs_root);
+        esp_debugfs_root = NULL;
+        esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
+        return NULL;
+}
+
+struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob) {
+        struct dentry * rc = NULL;
+        umode_t mode = 0644;
+
+        if(!esp_debugfs_root)
+                return NULL;
+
+        if(!parent)
+                parent = esp_debugfs_root;
+
+        rc = debugfs_create_blob(name, mode, parent, blob);
+
+        if (!rc)
+                goto Fail;
+        else
+                return rc;
+
+Fail:
+        debugfs_remove_recursive(esp_debugfs_root);
+        esp_debugfs_root = NULL;
+        esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
+        return NULL;
+}
+
+struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size) {
+        struct dentry *rc;
+        umode_t mode = 0644;
+
+        if(!esp_debugfs_root)
+                return NULL;
+
+        if(!parent)
+                parent = esp_debugfs_root;
+
+        rc = debugfs_create_file(name, mode, parent, data, &esp_debugfs_fops);
+
+        if (!rc)
+                goto Fail;
+        else
+                return rc;
+
+Fail:
+        debugfs_remove_recursive(esp_debugfs_root);
+        esp_debugfs_root = NULL;
+        esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
+        return NULL;
+}
+
+struct dentry *esp_debugfs_add_sub_dir(const char *name) {
+        struct dentry *sub_dir = NULL;
+
+        sub_dir = debugfs_create_dir(name, esp_debugfs_root);
+
+        if (!sub_dir)
+                goto Fail;
+
+        return sub_dir;
+
+Fail:
+        debugfs_remove_recursive(esp_debugfs_root);
+        esp_debugfs_root = NULL;
+        esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; dir name: %s\n", __FUNCTION__, name);
+        return NULL;
+
+}
+
+int esp_debugfs_init(void)
+{
+        esp_dbg(ESP_DBG, "esp debugfs init\n");
+        esp_debugfs_root = debugfs_create_dir("esp_debug", NULL);
+
+        if (!esp_debugfs_root || IS_ERR_OR_NULL(esp_debugfs_root)) {
+                return -ENOENT;
+        }
+
+        return 0;
+}
+
+void esp_debugfs_exit(void)
+{
+        esp_dbg(ESP_DBG, "esp debugfs exit");
+
+        debugfs_remove_recursive(esp_debugfs_root);
+
+        return;
+}
+
+#else
+
+inline struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type) {
+        return NULL;
+}
+
+inline struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob) {
+        return NULL;
+}
+
+inline struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size) {
+        return NULL;
+}
+
+struct dentry *esp_debugfs_add_sub_dir(const char *name) {
+        return NULL;
+}
+
+inline int esp_debugfs_init(void)
+{
+        return -1;
+}
+
+inline void esp_debugfs_exit(void)
+{
+
+}
+
+#endif
+
+
+void show_buf(u8 *buf, u32 len)
+{
+//     print_hex_dump(KERN_DEBUG, "",  DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
+#if 1
+        int i = 0, j;
+
+        printk(KERN_INFO "\n++++++++++++++++show rbuf+++++++++++++++\n");
+        for (i = 0; i < (len / 16); i++) {
+                j = i * 16;
+                printk(KERN_INFO "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x \n", buf[j], buf[j+1],buf[j+2],buf[j+3],buf[j+4],buf[j+5],buf[j+6],buf[j+7],buf[j+8],buf[j+9],buf[j+10],buf[j+11],buf[j+12],buf[j+13],buf[j+14],buf[j+15]);
+        }
+        printk(KERN_INFO "\n++++++++++++++++++++++++++++++++++++++++\n");
+#endif//0000
+}
+
+#ifdef HOST_RC
+static u8 get_cnt(u32 cnt_store, int idx)
+{
+        int shift = idx << 2;
+
+        return (u8)((cnt_store>>shift) & 0xf);
+}
+
+void esp_show_rcstatus(struct sip_rc_status *rcstatus)
+{
+        int i;
+        char msg[82];
+        char rcstr[16];
+        u32 cnt_store = rcstatus->rc_cnt_store;
+
+        memset(msg, 0 ,sizeof(msg));
+        memset(rcstr, 0 ,sizeof(rcstr));
+
+        printk(KERN_INFO "rcstatus map 0x%08x cntStore 0x%08x\n", rcstatus->rc_map, rcstatus->rc_cnt_store);
+
+        for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+                if (rcstatus->rc_map & BIT(i)) {
+                        sprintf(rcstr, "rcIdx %d, cnt %d ", i, get_cnt(cnt_store, i));
+                        strcat(msg, rcstr);
+                }
+        }
+        printk(KERN_INFO "%s \n", msg);
+}
+
+void esp_show_tx_rates(struct ieee80211_tx_rate* rates)
+{
+        int i;
+        char msg[128];
+        char rcstr[32];
+
+        memset(msg, 0 ,sizeof(msg));
+        memset(rcstr, 0 ,sizeof(rcstr));
+
+        for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+                if (rates->idx != -1 ) {
+                        sprintf(rcstr, "Idx %d, cnt %d, flag %02x ", rates->idx, rates->count, rates->flags);
+                        strcat(msg, rcstr);
+                }
+                rates++;
+        }
+        strcat(msg, "\n");
+        printk(KERN_INFO "%s \n", msg);
+}
+#endif /* HOST_RC */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_debug.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_debug.h
new file mode 100755 (executable)
index 0000000..7f19892
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011 Espressif System.
+ *
+ */
+
+#ifndef _DEBUG_H_
+
+#define assert(v) BUG_ON(!(v))
+
+#define ASSERT(v) BUG_ON(!(v))
+
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+
+typedef enum esp_type {
+        ESP_BOOL,
+        ESP_U8,
+        ESP_U16,
+        ESP_U32,
+        ESP_U64
+} esp_type;
+
+struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type);
+
+struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob);
+
+struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size);
+
+struct dentry *esp_debugfs_add_sub_dir(const char *name);
+
+int esp_debugfs_init(void);
+
+void esp_debugfs_exit(void);
+
+enum {
+        ESP_DBG_ERROR = BIT(0),
+        ESP_DBG_TRACE = BIT(1),
+        ESP_DBG_LOG = BIT(2),
+        ESP_DBG = BIT(3),
+        ESP_SHOW = BIT(4),
+        ESP_DBG_TXAMPDU = BIT(5),
+        ESP_DBG_OP = BIT(6),
+       ESP_DBG_PS = BIT(7),
+        ESP_DBG_ALL = 0xffffffff
+};
+
+extern unsigned int esp_msg_level;
+
+#ifdef ESP_ANDROID_LOGGER
+extern bool log_off;
+#endif /* ESP_ANDROID_LOGGER */
+
+#if defined(ANDROID) && defined(ESP_ANDROID_LOGGER)
+#include "esp_android.h"
+#define esp_dbg(mask, fmt, args...) do {                  \
+        if (esp_msg_level & mask)                        \
+       {                                                 \
+               if (log_off)                              \
+                       printk(fmt, ##args);              \
+               else                                                  \
+                       logger_write(4, "esp_wifi", fmt, ##args);     \
+       }                                                             \
+    } while (0)
+#else
+#define esp_dbg(mask, fmt, args...) do {                  \
+        if (esp_msg_level & mask)                         \
+            printk(fmt, ##args);                          \
+    } while (0)
+#endif /* ANDROID && ESP_ANDROID_LOGGER */
+
+void show_buf(u8 *buf, u32 len);
+
+#ifdef HOST_RC
+struct sip_rc_status;
+struct ieee80211_tx_rate;
+
+void esp_show_rcstatus(struct sip_rc_status *rcstatus);
+
+void esp_show_tx_rates(struct ieee80211_tx_rate *rates);
+#endif /* HOST_RC */
+
+#endif /* _DEBUG_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_ext.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_ext.c
new file mode 100755 (executable)
index 0000000..72003ff
--- /dev/null
@@ -0,0 +1,457 @@
+#ifdef USE_EXT_GPIO
+
+#include <net/cfg80211.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/version.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/completion.h>
+
+#include "esp_ext.h"
+#include "esp_debug.h"
+#include "esp_sip.h"
+#include "esp_sif.h"
+
+#ifdef EXT_GPIO_OPS
+extern void register_ext_gpio_ops(struct esp_ext_gpio_ops *ops);
+extern void unregister_ext_gpio_ops(void);
+
+static struct esp_ext_gpio_ops ext_gpio_ops = {
+        .gpio_request    = ext_gpio_request,                             /* gpio_request gpio_no from 0x0 to 0xf*/
+        .gpio_release    = ext_gpio_release,                             /* gpio_release */
+        .gpio_set_mode   = ext_gpio_set_mode,                            /* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */
+        .gpio_get_mode   = ext_gpio_get_mode,                            /* gpio_get_mode, current mode */
+        .gpio_set_state  = ext_gpio_set_output_state,                    /* only output state, high level or low level */
+        .gpio_get_state  = ext_gpio_get_state,                           /* current state */
+        .irq_ack         = ext_irq_ack,                                  /* ack interrupt */
+};
+
+
+#endif
+
+static struct esp_pub *ext_epub = NULL;
+
+static u16 intr_mask_reg = 0x0000;
+struct workqueue_struct *ext_irq_wkq;
+struct work_struct ext_irq_work;
+static struct mutex ext_mutex_lock;
+
+static struct ext_gpio_info gpio_list[EXT_GPIO_MAX_NUM] = {
+       { 0, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 1, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 2, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 3, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 4, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 5, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 6, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 7, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 8, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       { 9, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       {10, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       {11, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       {12, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       {13, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       {14, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+       {15, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
+};
+
+static struct pending_intr_list_info esp_pending_intr_list = {
+       .start_pos = 0,
+       .end_pos = 0,
+       .curr_num = 0,
+};
+
+u16 ext_gpio_get_int_mask_reg(void)
+{
+       return intr_mask_reg;
+}
+
+int ext_gpio_request(int gpio_no)
+{
+       mutex_lock(&ext_mutex_lock);
+
+       ASSERT(ext_epub != NULL);
+
+       if (atomic_read(&ext_epub->sip->state) != SIP_RUN) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s esp state is not ok\n", __func__);
+               return -3;
+       }
+
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               return -1;
+       }
+
+       if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_DISABLE) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s gpio is already in used by other\n", __func__);
+               return -2;
+       } else {
+               gpio_list[gpio_no].gpio_mode = EXT_GPIO_MODE_MAX;
+               mutex_unlock(&ext_mutex_lock);
+               return 0;
+       }
+}
+EXPORT_SYMBOL(ext_gpio_request);
+       
+int ext_gpio_release(int gpio_no)
+{
+       int ret;
+
+       mutex_lock(&ext_mutex_lock);
+
+       ASSERT(ext_epub != NULL);
+
+       if (atomic_read(&ext_epub->sip->state) != SIP_RUN) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s esp state is not ok\n", __func__);
+               return -3;
+       }
+
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               return -1;
+       }
+       sif_lock_bus(ext_epub);
+       sif_raw_dummy_read(ext_epub);
+       ret = sif_config_gpio_mode(ext_epub, (u8)gpio_no, EXT_GPIO_MODE_DISABLE);
+       sif_unlock_bus(ext_epub);       
+       if (ret) {
+               esp_dbg(ESP_DBG_ERROR, "%s gpio release error\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return ret;
+       }
+
+       gpio_list[gpio_no].gpio_mode  = EXT_GPIO_MODE_DISABLE;
+       gpio_list[gpio_no].gpio_state  = EXT_GPIO_STATE_IDLE;
+       gpio_list[gpio_no].irq_handler = NULL;
+       intr_mask_reg &= ~(1<<gpio_no);
+       
+       mutex_unlock(&ext_mutex_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(ext_gpio_release);
+
+int ext_gpio_set_mode(int gpio_no, int mode, void *data)
+{
+       u8 gpio_mode;
+       int ret;
+       struct ext_gpio_info backup_info;
+
+       ASSERT(ext_epub);
+
+       mutex_lock(&ext_mutex_lock);
+
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               return -1;
+       }
+
+       if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_DISABLE) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s gpio is not in occupy, please request gpio\n", __func__);
+               return -2;
+       }
+
+       if (mode <= EXT_GPIO_MODE_OOB || mode >= EXT_GPIO_MODE_MAX) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s gpio mode unknown\n", __func__);
+               return -3;
+       }
+
+       memcpy(&backup_info, &gpio_list[gpio_no], sizeof(struct ext_gpio_info));
+
+       gpio_list[gpio_no].gpio_mode = mode;
+       gpio_mode = (u8)mode;
+
+       switch (mode) {
+               case EXT_GPIO_MODE_INTR_POSEDGE:
+               case EXT_GPIO_MODE_INTR_NEGEDGE:
+               case EXT_GPIO_MODE_INTR_LOLEVEL:
+               case EXT_GPIO_MODE_INTR_HILEVEL:
+                       if (!data) {
+                               memcpy(&gpio_list[gpio_no], &backup_info, sizeof(struct ext_gpio_info));
+                               esp_dbg(ESP_DBG_ERROR, "%s irq_handler is NULL\n", __func__);
+                               mutex_unlock(&ext_mutex_lock);
+                               return -4;
+                       }
+                       gpio_list[gpio_no].irq_handler = (ext_irq_handler_t)data;
+                       intr_mask_reg |= (1<<gpio_no);
+                       break;
+               case EXT_GPIO_MODE_OUTPUT:
+                       if (!data) {
+                               memcpy(&gpio_list[gpio_no], &backup_info, sizeof(struct ext_gpio_info));
+                               esp_dbg(ESP_DBG_ERROR, "%s output default value is NULL\n", __func__);
+                               mutex_unlock(&ext_mutex_lock);
+                               return -4;
+                       }
+                       *(int *)data = (*(int *)data == 0 ? 0 : 1);
+                       gpio_mode = (u8)(((*(int *)data)<<4) | gpio_mode);
+               default:
+                       gpio_list[gpio_no].irq_handler = NULL;
+                       intr_mask_reg &= ~(1<<gpio_no);
+                       break;
+       }
+
+       sif_lock_bus(ext_epub);
+       sif_raw_dummy_read(ext_epub);
+       ret = sif_config_gpio_mode(ext_epub, (u8)gpio_no, gpio_mode);
+       sif_unlock_bus(ext_epub);
+       if (ret) {
+               memcpy(&gpio_list[gpio_no], &backup_info, sizeof(struct ext_gpio_info));
+               esp_dbg(ESP_DBG_ERROR, "%s gpio set error\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return ret;
+       }
+
+       mutex_unlock(&ext_mutex_lock);
+       return 0;
+}
+EXPORT_SYMBOL(ext_gpio_set_mode);
+
+int ext_gpio_get_mode(int gpio_no)
+{
+       int gpio_mode;
+
+       mutex_lock(&ext_mutex_lock);
+
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return -1;
+       }
+
+       gpio_mode = gpio_list[gpio_no].gpio_mode;
+
+       mutex_unlock(&ext_mutex_lock);
+
+       return gpio_mode;
+}
+EXPORT_SYMBOL(ext_gpio_get_mode);
+
+
+int ext_gpio_set_output_state(int gpio_no, int state)
+{
+       int ret;
+
+       mutex_lock(&ext_mutex_lock);
+
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               return -1;
+       }
+
+       if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_OUTPUT) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s gpio is not in output state, please request gpio or set output state\n", __func__);
+               return -2;
+       }
+
+       if (state != EXT_GPIO_STATE_LOW && state != EXT_GPIO_STATE_HIGH) {
+               mutex_unlock(&ext_mutex_lock);
+               esp_dbg(ESP_DBG_ERROR, "%s gpio state unknown\n", __func__);
+               return -3;
+       }
+
+       sif_lock_bus(ext_epub);
+       sif_raw_dummy_read(ext_epub);
+       ret = sif_set_gpio_output(ext_epub, 1<<gpio_no, state<<gpio_no);
+       sif_unlock_bus(ext_epub);       
+       if (ret) {
+               esp_dbg(ESP_DBG_ERROR, "%s gpio state set error\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return ret;
+       }
+       gpio_list[gpio_no].gpio_state = state;
+       
+       mutex_unlock(&ext_mutex_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(ext_gpio_set_output_state);
+
+int ext_gpio_get_state(int gpio_no)
+{
+       int ret;
+       u16 state;
+       u16 mask;
+
+       mutex_lock(&ext_mutex_lock);
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return -1;
+       }
+
+       if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_OUTPUT) {
+               state = gpio_list[gpio_no].gpio_state;
+        } else if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_INPUT) {
+               sif_lock_bus(ext_epub);
+               sif_raw_dummy_read(ext_epub);
+               ret = sif_get_gpio_input(ext_epub, &mask, &state);
+               sif_unlock_bus(ext_epub);
+               if (ret) {
+                       esp_dbg(ESP_DBG_ERROR, "%s get gpio_input state error\n", __func__);
+                       mutex_unlock(&ext_mutex_lock);
+                       return ret;
+               }       
+        } else {
+               esp_dbg(ESP_DBG_ERROR, "%s gpio_state is not input or output\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return -2;
+       }
+       mutex_unlock(&ext_mutex_lock);
+
+       return (state & (1<<gpio_no)) ? 1 : 0;
+}
+EXPORT_SYMBOL(ext_gpio_get_state);
+
+int ext_irq_ack(int gpio_no)
+{
+       int ret;
+
+       mutex_lock(&ext_mutex_lock);
+       if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
+               esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return -1;
+       }
+
+       if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_POSEDGE 
+                       && gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_NEGEDGE
+                       && gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_LOLEVEL
+                       && gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_HILEVEL) {
+               esp_dbg(ESP_DBG_ERROR, "%s gpio mode is not intr mode\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return -2;
+       }
+
+       sif_lock_bus(ext_epub);
+       sif_raw_dummy_read(ext_epub);
+       ret = sif_set_gpio_output(ext_epub, 0x00, 1<<gpio_no);
+       sif_unlock_bus(ext_epub);
+       if (ret) {
+               esp_dbg(ESP_DBG_ERROR, "%s gpio intr ack error\n", __func__);
+               mutex_unlock(&ext_mutex_lock);
+               return ret;
+       }
+
+       mutex_unlock(&ext_mutex_lock);
+       return 0;
+}
+EXPORT_SYMBOL(ext_irq_ack);
+
+void show_status(void)
+{
+       int i=0;
+       for (i = 0; i < MAX_PENDING_INTR_LIST;i++)
+               esp_dbg(ESP_DBG_ERROR, "status[%d] = [0x%04x]\n", i, esp_pending_intr_list.pending_intr_list[i]);
+
+       esp_dbg(ESP_DBG_ERROR, "start_pos[%d]\n",esp_pending_intr_list.start_pos);
+       esp_dbg(ESP_DBG_ERROR, "end_pos[%d]\n",esp_pending_intr_list.end_pos);
+       esp_dbg(ESP_DBG_ERROR, "curr_num[%d]\n",esp_pending_intr_list.curr_num);
+       
+}
+void esp_tx_work(struct work_struct *work)
+{
+       int i;
+       u16 tmp_intr_status_reg;
+
+       esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__);
+
+       spin_lock(&esp_pending_intr_list.spin_lock);
+       /* assert cycle queue is not empty */   
+       ASSERT(esp_pending_intr_list.curr_num > 0);
+
+       tmp_intr_status_reg = esp_pending_intr_list.pending_intr_list[esp_pending_intr_list.start_pos];
+       
+       esp_pending_intr_list.pending_intr_list[esp_pending_intr_list.start_pos] = 0x0000;
+       esp_pending_intr_list.start_pos = (esp_pending_intr_list.start_pos + 1) % MAX_PENDING_INTR_LIST;
+       esp_pending_intr_list.curr_num--;
+       
+       spin_unlock(&esp_pending_intr_list.spin_lock);
+       
+       for (i = 0; i < EXT_GPIO_MAX_NUM; i++) {
+               if (tmp_intr_status_reg & (1<<i) && (gpio_list[i].irq_handler))
+                       gpio_list[i].irq_handler();
+       }
+
+       spin_lock(&esp_pending_intr_list.spin_lock);
+       if (esp_pending_intr_list.curr_num > 0)
+               queue_work(ext_irq_wkq, &ext_irq_work);
+       spin_unlock(&esp_pending_intr_list.spin_lock);
+}
+
+void ext_gpio_int_process(u16 value) {
+       if (value == 0x00)
+               return;
+
+       esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__);
+
+       /* intr cycle queue is full, wait */
+       while (esp_pending_intr_list.curr_num >= MAX_PENDING_INTR_LIST)
+       {
+               udelay(1);
+       }
+
+       spin_lock(&esp_pending_intr_list.spin_lock);
+       
+       ASSERT(esp_pending_intr_list.curr_num < MAX_PENDING_INTR_LIST);
+       
+       esp_pending_intr_list.pending_intr_list[esp_pending_intr_list.end_pos] = value;
+       esp_pending_intr_list.end_pos = (esp_pending_intr_list.end_pos + 1) % MAX_PENDING_INTR_LIST;
+       esp_pending_intr_list.curr_num++;
+
+       queue_work(ext_irq_wkq, &ext_irq_work);
+       
+       spin_unlock(&esp_pending_intr_list.spin_lock);
+}
+
+int ext_gpio_init(struct esp_pub *epub)
+{
+       esp_dbg(ESP_DBG_LOG, "%s enter\n", __func__);
+
+       ext_epub = epub;
+       ASSERT(ext_epub != NULL);
+
+       ext_irq_wkq = create_singlethread_workqueue("esp_ext_irq_wkq");
+       if (ext_irq_wkq == NULL) {
+               esp_dbg(ESP_DBG_ERROR, "%s create workqueue error\n", __func__);
+               return -2;
+       }
+
+#ifdef EXT_GPIO_OPS
+       register_ext_gpio_ops(&ext_gpio_ops);
+#endif
+       
+       INIT_WORK(&ext_irq_work, esp_tx_work);
+       mutex_init(&ext_mutex_lock);
+
+       return 0;
+}
+
+void ext_gpio_deinit(void)
+{
+       esp_dbg(ESP_DBG_LOG, "%s enter\n", __func__);
+
+       ext_epub = NULL;
+#ifdef EXT_GPIO_OPS
+       unregister_ext_gpio_ops();
+#endif
+        cancel_work_sync(&ext_irq_work);
+       destroy_workqueue(ext_irq_wkq);
+}
+
+#endif /* USE_EXT_GPIO */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_ext.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_ext.h
new file mode 100755 (executable)
index 0000000..9385c54
--- /dev/null
@@ -0,0 +1,100 @@
+#ifdef USE_EXT_GPIO
+
+#ifndef _ESP_EXT_H_
+#define _ESP_EXT_H_
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include "esp_sip.h"
+
+#define MAX_PENDING_INTR_LIST 16
+
+#ifdef EXT_GPIO_OPS
+typedef struct esp_ext_gpio_ops {
+        int (*gpio_request)(int gpio_no);                             /* gpio_request gpio_no from 0x0 to 0xf*/
+        int (*gpio_release)(int gpio_no);                             /* gpio_release */
+        int (*gpio_set_mode)(int gpio_no, int mode , void *data);     /* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */
+        int (*gpio_get_mode)(int gpio_no);                            /* gpio_get_mode, current mode */
+        int (*gpio_set_state)(int gpio_no, int state);                /* only output state, high level or low level */
+        int (*gpio_get_state)(int gpio_no);                           /* current state */
+       int (*irq_ack)(int gpio_no);                                  /* ack interrupt */
+} esp_ext_gpio_ops_t;
+#endif
+
+typedef enum EXT_GPIO_NO {
+       EXT_GPIO_GPIO0 = 0,
+       EXT_GPIO_U0TXD,
+       EXT_GPIO_GPIO2,
+       EXT_GPIO_U0RXD,
+       EXT_GPIO_GPIO4,
+       EXT_GPIO_GPIO5,
+       EXT_GPIO_SD_CLK,
+       EXT_GPIO_SD_DATA0,
+       EXT_GPIO_SD_DATA1,
+       EXT_GPIO_SD_DATA2,
+       EXT_GPIO_SD_DATA3,
+       EXT_GPIO_SD_CMD,
+       EXT_GPIO_MTDI,
+       EXT_GPIO_MTCK,
+       EXT_GPIO_MTMS,
+       EXT_GPIO_MTDO,
+       EXT_GPIO_MAX_NUM
+} EXT_GPIO_NO_T;
+       
+typedef enum EXT_GPIO_MODE {           //dir           def     pullup  mode    wake
+       EXT_GPIO_MODE_OOB = 0,          //output        1       0       n/a     n/a
+       EXT_GPIO_MODE_OUTPUT,           //output        /       0       n/a     n/a
+       EXT_GPIO_MODE_DISABLE,          //input         n/a     0       DIS     n/a
+       EXT_GPIO_MODE_INTR_POSEDGE,     //input         n/a     0       POS     1
+       EXT_GPIO_MODE_INTR_NEGEDGE,     //input         n/a     1       NEG     1
+       EXT_GPIO_MODE_INPUT,            //input         n/a     0       ANY     1
+       EXT_GPIO_MODE_INTR_LOLEVEL,     //input         n/a     1       LOW     1
+       EXT_GPIO_MODE_INTR_HILEVEL,     //input         n/a     0       HIGH    1
+       EXT_GPIO_MODE_MAX,
+} EXT_GPIO_MODE_T;
+
+typedef enum EXT_GPIO_STATE {
+       EXT_GPIO_STATE_LOW,
+       EXT_GPIO_STATE_HIGH,
+       EXT_GPIO_STATE_IDLE
+} EXT_GPIO_STATE_T;
+
+typedef irqreturn_t (*ext_irq_handler_t)(void);
+
+struct ext_gpio_info {
+       int gpio_no;
+       int gpio_mode;
+       int gpio_state;
+       ext_irq_handler_t irq_handler;
+};
+
+struct pending_intr_list_info {
+       u16 pending_intr_list[MAX_PENDING_INTR_LIST];
+       int start_pos;
+       int end_pos;
+       int curr_num;
+       spinlock_t spin_lock;
+};
+
+u16 ext_gpio_get_int_mask_reg(void);
+
+/* for extern user start */
+int ext_gpio_request(int gpio_no);
+int ext_gpio_release(int gpio_no);
+
+int ext_gpio_set_mode(int gpio_no, int mode, void *data);
+int ext_gpio_get_mode(int gpio_no);
+
+int ext_gpio_set_output_state(int gpio_no, int state);
+int ext_gpio_get_state(int gpio_no);
+
+int ext_irq_ack(int gpio_no);
+/* for extern user end */
+
+void ext_gpio_int_process(u16 value);
+
+int ext_gpio_init(struct esp_pub *epub);
+void ext_gpio_deinit(void);
+#endif /* _ESP_EXT_H_ */
+
+#endif /* USE_EXT_GPIO */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_init_data.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_init_data.h
new file mode 100755 (executable)
index 0000000..38a349d
--- /dev/null
@@ -0,0 +1 @@
+static char esp_init_data[] = {0x5,0x0,4,2,5,5,5,2,5,0,4,5,5,4,5,5,4,-2,-3,-1,-16,-16,-16,-32,-32,-32,204,1,0xff,0xff,0,0,0,0,82,78,74,68,64,56,0,0,1,1,2,3,4,5,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,240,10,0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
\ No newline at end of file
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_io.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_io.c
new file mode 100755 (executable)
index 0000000..3c0dd73
--- /dev/null
@@ -0,0 +1,596 @@
+#include <linux/mmc/sdio_func.h>
+#include "esp_sif.h"
+#include "slc_host_register.h"
+#include "esp_debug.h"
+
+#ifdef SIF_DEBUG_DSR_DUMP_REG
+static void dump_slc_regs(struct slc_host_regs *regs);
+#endif /* SIF_DEBUG_DSR_DUMP_REG */
+
+int esp_common_read(struct esp_pub *epub, u8 *buf, u32 len, int sync, bool noround)
+{
+       if (sync) {
+#ifdef ESP_USE_SDIO
+               return sif_lldesc_read_sync(epub, buf, len);
+#endif
+#ifdef ESP_USE_SPI
+               //return sif_spi_read_sync(epub, buf, len, NOT_CHECK_IDLE);
+               return sif_spi_read_sync(epub, buf, len, CHECK_IDLE);
+#endif
+       } else {
+#ifdef ESP_USE_SDIO
+               return sif_lldesc_read_raw(epub, buf, len, noround);
+#endif
+#ifdef ESP_USE_SPI
+               //return sif_spi_read_nosync(epub, buf, len, NOT_CHECK_IDLE, noround);
+               return sif_spi_read_nosync(epub, buf, len, CHECK_IDLE, noround);
+#endif
+       }
+}
+
+
+int esp_common_write(struct esp_pub *epub, u8 *buf, u32 len, int sync)
+{
+       if (sync) {
+#ifdef ESP_USE_SDIO
+               return sif_lldesc_write_sync(epub, buf, len);
+#endif
+#ifdef ESP_USE_SPI
+               //return sif_spi_write_sync(epub, buf, len, NOT_CHECK_IDLE);
+               return sif_spi_write_sync(epub, buf, len, CHECK_IDLE);
+#endif
+       } else {
+#ifdef ESP_USE_SDIO
+               return sif_lldesc_write_raw(epub, buf, len);
+#endif
+#ifdef ESP_USE_SPI
+               //return sif_spi_write_nosync(epub, buf, len, NOT_CHECK_IDLE);
+               return sif_spi_write_nosync(epub, buf, len, CHECK_IDLE);
+#endif
+       }
+}
+
+
+int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync)
+{
+       if (sync) {
+#ifdef ESP_USE_SDIO
+               return sif_io_sync(epub, addr, buf, len, SIF_FROM_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR);
+#endif
+#ifdef ESP_USE_SPI
+               return sif_spi_epub_read_mix_sync(epub, addr, buf, len, CHECK_IDLE);
+#endif
+       } else {
+#ifdef ESP_USE_SDIO
+               return sif_io_raw(epub, addr, buf, len, SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
+#endif
+#ifdef ESP_USE_SPI
+               return sif_spi_epub_read_mix_nosync(epub, addr, buf, len, CHECK_IDLE);
+#endif
+       }
+
+}
+
+
+int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync)
+{
+       if (sync) {
+#ifdef ESP_USE_SDIO
+               return sif_io_sync(epub, addr, buf, len, SIF_TO_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR);
+#endif
+#ifdef ESP_USE_SPI
+               return sif_spi_epub_write_mix_sync(epub, addr, buf, len, CHECK_IDLE);
+#endif
+       } else {
+#ifdef ESP_USE_SDIO
+               return sif_io_raw(epub, addr, buf, len, SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
+#endif
+#ifdef ESP_USE_SPI
+               return sif_spi_epub_write_mix_nosync(epub, addr, buf, len, CHECK_IDLE);
+#endif
+       }
+}
+
+int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, int sync)
+{
+       if(sync){
+#ifdef ESP_USE_SDIO
+       int res;
+       sif_lock_bus(epub);
+       *buf = sdio_io_readb(epub, addr, &res);
+       sif_unlock_bus(epub);
+       return res;
+#endif
+#ifdef ESP_USE_SPI
+       return sif_spi_epub_read_mix_sync(epub, addr, buf, 1, CHECK_IDLE);
+#endif
+       } else {
+#ifdef ESP_USE_SDIO
+       int res;
+       *buf = sdio_io_readb(epub, addr, &res);
+       return res;
+#endif
+#ifdef ESP_USE_SPI
+       return sif_spi_epub_read_mix_nosync(epub, addr, buf, 1, CHECK_IDLE);
+#endif
+       }
+
+}
+
+
+
+int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, int sync)
+{
+       if(sync){
+#ifdef ESP_USE_SDIO
+               int res;
+               sif_lock_bus(epub);
+               sdio_io_writeb(epub, buf, addr, &res);
+               sif_unlock_bus(epub);
+               return res;
+#endif
+#ifdef ESP_USE_SPI
+               return sif_spi_epub_write_mix_sync(epub, addr, &buf, 1, CHECK_IDLE);
+#endif
+       } else {
+#ifdef ESP_USE_SDIO
+               int res;
+               sdio_io_writeb(epub, buf, addr, &res);
+               return res;
+#endif
+#ifdef ESP_USE_SPI
+               return sif_spi_epub_write_mix_nosync(epub, addr, &buf, 1, CHECK_IDLE);
+#endif
+       }
+}
+
+typedef enum _SDIO_INTR_MODE {
+       SDIO_INTR_IB = 0,
+       SDIO_INTR_OOB_TOGGLE,
+       SDIO_INTR_OOB_HIGH_LEVEL,
+       SDIO_INTR_OOB_LOW_LEVEL,
+} SDIO_INTR_MODE;
+
+#define GEN_GPIO_SEL(_gpio_num, _sel_func, _intr_mode, _offset) (((_offset)<< 9 ) |((_intr_mode) << 7)|((_sel_func) << 4)|(_gpio_num))
+//bit[3:0] = gpio num, 2
+//bit[6:4] = gpio sel func, 0
+//bit[8:7] = gpio intr mode, SDIO_INTR_OOB_TOGGLE
+//bit[15:9] = register offset, 0x38
+
+u16 gpio_sel_sets[17] = {
+       GEN_GPIO_SEL(0, 0, SDIO_INTR_OOB_TOGGLE, 0x34),//GPIO0
+       GEN_GPIO_SEL(1, 3, SDIO_INTR_OOB_TOGGLE, 0x18),//U0TXD
+       GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38),//GPIO2
+       GEN_GPIO_SEL(3, 3, SDIO_INTR_OOB_TOGGLE, 0x14),//U0RXD
+       GEN_GPIO_SEL(4, 0, SDIO_INTR_OOB_TOGGLE, 0x3C),//GPIO4
+       GEN_GPIO_SEL(5, 0, SDIO_INTR_OOB_TOGGLE, 0x40),//GPIO5
+       GEN_GPIO_SEL(6, 3, SDIO_INTR_OOB_TOGGLE, 0x1C),//SD_CLK
+       GEN_GPIO_SEL(7, 3, SDIO_INTR_OOB_TOGGLE, 0x20),//SD_DATA0
+       GEN_GPIO_SEL(8, 3, SDIO_INTR_OOB_TOGGLE, 0x24),//SD_DATA1
+       GEN_GPIO_SEL(9, 3, SDIO_INTR_OOB_TOGGLE, 0x28),//SD_DATA2
+       GEN_GPIO_SEL(10, 3, SDIO_INTR_OOB_TOGGLE, 0x2C),//SD_DATA3
+       GEN_GPIO_SEL(11, 3, SDIO_INTR_OOB_TOGGLE, 0x30),//SD_CMD
+       GEN_GPIO_SEL(12, 3, SDIO_INTR_OOB_TOGGLE, 0x04),//MTDI
+       GEN_GPIO_SEL(13, 3, SDIO_INTR_OOB_TOGGLE, 0x08),//MTCK
+       GEN_GPIO_SEL(14, 3, SDIO_INTR_OOB_TOGGLE, 0x0C),//MTMS
+       GEN_GPIO_SEL(15, 3, SDIO_INTR_OOB_TOGGLE, 0x10),//MTDO
+       //pls do not change sel before, if you want to change intr mode,change the one blow
+       //GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38)
+       GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_LOW_LEVEL, 0x38)
+};
+#if defined(USE_EXT_GPIO)
+u16 gpio_forbidden = 0;
+#endif
+
+int sif_interrupt_target(struct esp_pub *epub, u8 index)
+{
+       u8 low_byte = BIT(index);
+       return esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W4 + 2, low_byte, ESP_SIF_NOSYNC);
+       
+}
+
+#ifdef USE_EXT_GPIO
+int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode)
+{
+       u32 *p_tbuf = NULL;
+       int err;
+    
+       if((BIT(gpio_num) & gpio_forbidden) || gpio_num > 15)
+               return 1;    
+
+       p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
+       ASSERT(p_tbuf != NULL);
+       *p_tbuf = (gpio_mode << 16) | gpio_sel_sets[gpio_num];
+       err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W1, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+       if (err)
+               return err;
+
+       kfree(p_tbuf);
+       
+       return sif_interrupt_target(epub, 4);
+}
+
+int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value)
+{
+       u32 *p_tbuf = NULL;
+       int err;
+        
+       mask &= ~gpio_forbidden;
+       p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
+       ASSERT(p_tbuf != NULL);
+       *p_tbuf = (mask << 16) | value;
+       err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W2, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+       if (err)
+               return err;
+
+       kfree(p_tbuf);
+       
+       return sif_interrupt_target(epub, 5);
+}
+
+int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 *value)
+{
+       u32 *p_tbuf = NULL;
+       int err;
+        
+       p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
+       ASSERT(p_tbuf != NULL);
+       *p_tbuf = 0;
+       err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W3, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+       if (err)
+               return err;
+
+       *value = *p_tbuf & intr_mask;
+       kfree(p_tbuf);
+       if(*value == 0)
+               return 0;
+       return sif_interrupt_target(epub, 6);
+}
+
+int sif_get_gpio_input(struct esp_pub *epub, u16 *mask, u16 *value)
+{
+       u32 *p_tbuf = NULL;
+       int err;
+        
+       err = sif_interrupt_target(epub, 3);
+       if (err)
+               return err;
+
+       udelay(20);
+       p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
+       ASSERT(p_tbuf != NULL);
+       *p_tbuf = 0;
+       err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W3, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+       if (err)
+               return err;
+
+       *mask = *p_tbuf >> 16;
+       *value = *p_tbuf & *mask;
+       kfree(p_tbuf);
+       
+       return 0;
+}
+#endif
+
+void sif_raw_dummy_read(struct esp_pub *epub)
+{
+       int retry = 0;
+        u32 *p_tbuf = NULL;
+       static u32 read_err_cnt = 0;
+       static u32 write_err_cnt = 0;
+       static u32 unknow_err_cnt = 0;
+       static u32 check_cnt = 0;
+       int ext_cnt = 0;      
+
+       if (atomic_read(&epub->ps.state) == ESP_PM_ON) {
+               atomic_set(&epub->ps.state, ESP_PM_OFF);
+        } else {
+               return ;
+       }
+
+
+       p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
+       ASSERT(p_tbuf != NULL);
+       *p_tbuf = 0;
+               
+       *p_tbuf = 0x010001ff;
+
+       esp_common_write_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+
+        do {
+               *p_tbuf = 0xffffffff;
+               udelay(20);
+               esp_common_read_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+
+               if(*p_tbuf == 0x020001ff){
+#ifdef ESP_USE_SPI
+                       if(--ext_cnt >= 0){
+                               mdelay(10);
+                               esp_common_write_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+                               retry = -1;
+                               continue;
+                       }
+#endif
+                       break;
+               }
+               
+               if(*p_tbuf == 0x010001ff){
+                       if(retry < 5)
+                               continue;
+               }else if(*p_tbuf == 0x000001ff){
+                       write_err_cnt++;
+                       ext_cnt = 3;
+               }else if(*p_tbuf == 0xffffffff){
+                       read_err_cnt++;
+                       write_err_cnt++;
+                       ext_cnt = 3;
+               }else {
+                       unknow_err_cnt++;
+                       ext_cnt = 3;
+               }
+
+               *p_tbuf = 0x010001ff;
+               udelay(20);
+               esp_common_write_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
+
+        } while (retry++ < 1000);
+       
+       kfree(p_tbuf);
+
+       if(read_err_cnt || write_err_cnt || unknow_err_cnt){
+               if((check_cnt & 0xf) == 0)
+                       //esp_dbg(ESP_DBG_ERROR, "==============sdio err===============\n,read:%u, write:%u, unknow:%u\n", read_err_cnt,write_err_cnt,unknow_err_cnt);
+                       esp_dbg(ESP_DBG_ERROR, "r%u,w%u,u%u\n", read_err_cnt,write_err_cnt,unknow_err_cnt);
+               check_cnt++;
+       }
+
+        if (retry > 1) {
+                esp_dbg(ESP_DBG_ERROR, "=========%s tried %d times===========\n", __func__, retry - 1);
+                //if (retry>=100)
+                //        ASSERT(0);
+        }
+}
+
+void check_target_id(struct esp_pub *epub)
+{
+       u32 date;
+        int err = 0;
+        int i;
+
+       EPUB_CTRL_CHECK(epub);
+
+       sif_lock_bus(epub);
+
+        for(i = 0; i < 4; i++) {
+                err = esp_common_readbyte_with_addr(epub, SLC_HOST_DATE + i, (u8 *)&date + i, ESP_SIF_NOSYNC);
+                err = esp_common_readbyte_with_addr(epub, SLC_HOST_ID + i, (u8 *)&EPUB_TO_CTRL(epub)->target_id + i, ESP_SIF_NOSYNC);
+        }
+
+       sif_unlock_bus(epub);
+
+        esp_dbg(ESP_DBG_LOG, "\n\n \t\t SLC data 0x%08x, ID 0x%08x\n\n", date, EPUB_TO_CTRL(epub)->target_id);
+
+        switch(EPUB_TO_CTRL(epub)->target_id) {
+        case 0x100:
+                EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000;
+                break;
+        case 0x600:
+                EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000 - 0x800;
+
+               do{
+                       u16 gpio_sel;
+                       u8 low_byte = 0;
+                       u8 high_byte = 0;
+                       u8 byte2 = 0;
+                       u8 byte3 = 0;
+#ifdef USE_OOB_INTR 
+                       gpio_sel = gpio_sel_sets[16];
+                       low_byte = gpio_sel;
+                       high_byte = gpio_sel >> 8;
+#ifdef USE_EXT_GPIO
+                       gpio_forbidden |= BIT(gpio_sel & 0xf);
+#endif /* USE_EXT_GPIO */
+#endif /* USE_OOB_INTR */
+
+                       if(sif_get_bt_config() == 1 && sif_get_rst_config() != 1){
+                               u8 gpio_num = sif_get_wakeup_gpio_config();
+                               gpio_sel = gpio_sel_sets[gpio_num];
+                               byte2 = gpio_sel;
+                               byte3 = gpio_sel >> 8;
+#ifdef USE_EXT_GPIO
+                               gpio_forbidden |= BIT(gpio_num);
+#endif
+                       }
+                       sif_lock_bus(epub);
+                       err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1, low_byte, ESP_SIF_NOSYNC);
+                       err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 1, high_byte, ESP_SIF_NOSYNC);
+                       err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 2, byte2, ESP_SIF_NOSYNC);
+                       err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 3, byte3, ESP_SIF_NOSYNC);
+                       sif_unlock_bus(epub);
+               }while(0);
+                break;
+        default:
+                EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000;
+                break;
+        }
+
+       return;
+}
+
+u32 sif_get_blksz(struct esp_pub *epub)
+{
+        EPUB_CTRL_CHECK(epub);
+
+        return EPUB_TO_CTRL(epub)->slc_blk_sz;
+}
+
+u32 sif_get_target_id(struct esp_pub *epub)
+{
+        EPUB_CTRL_CHECK(epub);
+
+        return EPUB_TO_CTRL(epub)->target_id;
+}
+
+
+#ifdef SIF_CHECK_FIRST_INTR
+static bool first_intr_checked = false;
+#endif //SIF_CHECK_FIRST_INTR
+
+#ifdef ESP_USE_SDIO
+void sif_dsr(struct sdio_func *func)
+{
+        struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func);
+#else
+void sif_dsr(struct spi_device *spi)
+{
+        struct esp_spi_ctrl *sctrl = spi_get_drvdata(spi);
+#endif
+#ifdef SIF_DSR_WAR
+        static int dsr_cnt = 0, real_intr_cnt = 0, bogus_intr_cnt = 0;
+        struct slc_host_regs *regs = &(sctrl->slc_regs);
+       esp_dbg(ESP_DBG_TRACE, " %s enter %d \n", __func__, dsr_cnt++);
+#endif /* SIF_DSR_WAR */
+
+        atomic_set(&sctrl->irq_handling, 1);
+
+#ifdef ESP_USE_SDIO
+        sdio_release_host(sctrl->func);
+#endif
+
+#ifdef SIF_DSR_WAR
+        do {
+#ifdef SIF_CHECK_FIRST_INTR 
+                if (likely(first_intr_checked)) {
+                        esp_dsr(sctrl->epub);
+                        break;
+                } 
+#endif //SIF_CHECK_FIRST_INTR
+          
+                memset(regs, 0x0, sizeof(struct slc_host_regs));
+                esp_common_read_with_addr(sctrl->epub, REG_SLC_HOST_BASE + 8, (u8 *)regs, sizeof(struct slc_host_regs), ESP_SIF_SYNC);
+
+                if (regs->intr_status & SLC_HOST_RX_ST) {
+#ifdef SIF_CHECK_FIRST_INTR 
+                       first_intr_checked = true;
+#endif //SIF_CHECK_FIRST_INTR
+                        esp_dbg(ESP_DBG_TRACE, "%s eal intr cnt: %d", __func__, ++real_intr_cnt);
+               
+                       esp_dsr(sctrl->epub);
+
+                } else {
+#ifdef ESP_ACK_INTERRUPT
+                       sif_lock_bus(sctrl->epub);
+                       sif_platform_ack_interrupt(sctrl->epub);
+                       sif_unlock_bus(sctrl->epub);
+#endif //ESP_ACK_INTERRUPT
+
+                        esp_dbg(ESP_DBG_TRACE, "%s bogus_intr_cnt %d\n", __func__, ++bogus_intr_cnt);
+                }
+
+#ifdef SIF_DEBUG_DSR_DUMP_REG
+                dump_slc_regs(regs);
+#endif /* SIF_DEBUG_DUMP_DSR */
+
+        } while (0);
+
+#else
+               esp_dsr(sctrl->epub);
+#endif /* SIF_DSR_WAR */
+
+#ifdef ESP_USE_SDIO
+        sdio_claim_host(func);
+#endif
+
+        atomic_set(&sctrl->irq_handling, 0);
+}
+
+
+struct slc_host_regs * sif_get_regs(struct esp_pub *epub) 
+{
+        EPUB_CTRL_CHECK(epub);
+
+        return &EPUB_TO_CTRL(epub)->slc_regs;
+}
+
+void sif_disable_target_interrupt(struct esp_pub *epub)
+{
+       EPUB_FUNC_CHECK(epub);
+       sif_lock_bus(epub);
+#ifdef HOST_RESET_BUG
+       mdelay(10);
+#endif
+       sif_raw_dummy_read(epub);
+       memset(EPUB_TO_CTRL(epub)->dma_buffer, 0x00, sizeof(u32));
+       esp_common_write_with_addr(epub, SLC_HOST_INT_ENA, EPUB_TO_CTRL(epub)->dma_buffer, sizeof(u32), ESP_SIF_NOSYNC);
+#ifdef HOST_RESET_BUG
+       mdelay(10);
+#endif
+
+       sif_unlock_bus(epub);
+}
+
+#ifdef SIF_DEBUG_DSR_DUMP_REG
+static void dump_slc_regs(struct slc_host_regs *regs) 
+{
+        esp_dbg(ESP_DBG_TRACE, "\n\n ------- %s --------------\n", __func__);
+
+        esp_dbg(ESP_DBG_TRACE, " \
+                        intr_raw 0x%08X \t \n  \
+                        state_w0 0x%08X \t state_w1 0x%08X \n  \
+                        config_w0 0x%08X \t config_w1 0x%08X \n \
+                        intr_status 0x%08X \t config_w2 0x%08X \n \
+                        config_w3 0x%08X \t config_w4 0x%08X \n \
+                        token_wdata 0x%08X \t intr_clear 0x%08X \n \
+                        intr_enable 0x%08X \n\n", regs->intr_raw, \
+                        regs->state_w0, regs->state_w1, regs->config_w0, regs->config_w1, \
+                        regs->intr_status, \
+                        regs->config_w2, regs->config_w3, regs->config_w4, regs->token_wdata, \
+                        regs->intr_clear, regs->intr_enable);
+}
+#endif /* SIF_DEBUG_DSR_DUMP_REG */
+
+static int bt_config = 0;
+void sif_record_bt_config(int value)
+{
+       bt_config = value;
+}
+
+int sif_get_bt_config(void)
+{
+       return bt_config;
+}
+
+static int rst_config = 0;
+void sif_record_rst_config(int value)
+{
+        rst_config = value;
+}
+
+int sif_get_rst_config(void)
+{
+        return rst_config;
+}
+
+static int retry_reset = 0;
+void sif_record_retry_config(void)
+{
+       retry_reset = 1;
+}
+
+int sif_get_retry_config(void)
+{
+       return retry_reset;
+}
+
+static int wakeup_gpio = 12;
+void sif_record_wakeup_gpio_config(int value)
+{
+       wakeup_gpio = value;
+}
+
+int sif_get_wakeup_gpio_config(void)
+{
+       return wakeup_gpio;
+}
+
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_mac80211.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_mac80211.c
new file mode 100755 (executable)
index 0000000..85ecf56
--- /dev/null
@@ -0,0 +1,2008 @@
+/*
+ * Copyright (c) 2011 Espressif System.
+ *
+ *     MAC80211 support module
+ */
+#include <linux/etherdevice.h>
+#include <linux/workqueue.h>
+#include <linux/nl80211.h>
+#include <linux/ieee80211.h>
+#include <linux/slab.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+#include <net/regulatory.h>
+#endif
+/* for support scan in p2p concurrent */
+#include <../net/mac80211/ieee80211_i.h>
+#include "esp_pub.h"
+#include "esp_sip.h"
+#include "esp_ctrl.h"
+#include "esp_sif.h"
+#include "esp_debug.h"
+#include "esp_wl.h"
+#include "esp_utils.h"
+
+#define ESP_IEEE80211_DBG esp_dbg
+
+#define GET_NEXT_SEQ(seq) (((seq) +1) & 0x0fff)
+
+#ifdef P2P_CONCURRENT
+static u8 esp_mac_addr[ETH_ALEN * 2];
+#endif
+static u8 getaddr_index(u8 * addr, struct esp_pub *epub);
+#if 1
+/*
+static
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+void
+#else
+int
+#endif  NEW_KERNEL */
+//static void esp_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void esp_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb)
+{
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+       ESP_IEEE80211_DBG(ESP_DBG_LOG, "%s enter\n", __func__);
+       if (!mod_support_no_txampdu() /*&&
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                       hw->conf.channel_type != NL80211_CHAN_NO_HT
+#else
+                       !(hw->conf.flags&IEEE80211_CONF_SUPPORT_HT_MODE) add libing
+#endif   */        
+          ) {
+               struct ieee80211_tx_info * tx_info = IEEE80211_SKB_CB(skb);
+               
+               struct ieee80211_hdr * wh = (struct ieee80211_hdr *)skb->data;
+               if(ieee80211_is_data_qos(wh->frame_control)) {
+                       if(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
+                               u8 tidno = ieee80211_get_qos_ctl(wh)[0] & IEEE80211_QOS_CTL_TID_MASK;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+                               struct ieee80211_sta *sta; // = tx_info->control.sta  add libing
+                               struct esp_node * node = (struct esp_node *)sta->drv_priv; 
+#else
+                               struct esp_node * node = esp_get_node_by_addr(epub, wh->addr1);
+#endif
+                               struct esp_tx_tid *tid = &node->tid[tidno];
+                               //record ssn
+                               spin_lock_bh(&epub->tx_ampdu_lock);
+                               tid->ssn = GET_NEXT_SEQ(le16_to_cpu(wh->seq_ctrl)>>4);
+                               ESP_IEEE80211_DBG(ESP_DBG_TRACE, "tidno:%u,ssn:%u\n", tidno, tid->ssn);
+                               spin_unlock_bh(&epub->tx_ampdu_lock);
+                       } else {
+                               ESP_IEEE80211_DBG(ESP_DBG_TRACE, "tx ampdu pkt, sn:%u, %u\n", le16_to_cpu(wh->seq_ctrl)>>4, skb->len);
+                       }
+               }
+       }
+
+#ifdef GEN_ERR_CHECKSUM
+       esp_gen_err_checksum(skb);
+#endif
+
+       sip_tx_data_pkt_enqueue(epub, skb);
+       if (epub)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+               ieee80211_queue_work(hw, &epub->tx_work);
+#else
+               queue_work(hw->workqueue,&epub->tx_work);    
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+       //return NETDEV_TX_OK;
+#endif /*2.6.39*/
+}
+#endif
+static int esp_op_start(struct ieee80211_hw *hw)
+{
+       struct esp_pub *epub;
+
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s\n", __func__);
+
+       if (!hw) {
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no hw!\n", __func__);
+               return -1;
+       }
+
+       epub = (struct esp_pub *)hw->priv;
+
+       if (!epub) {
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no epub!\n", __func__);
+               return -1;
+       }
+       /*add rfkill poll function*/
+
+       atomic_set(&epub->wl.off, 0);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+       wiphy_rfkill_start_polling(hw->wiphy);
+#endif
+       return 0;
+}
+
+static void esp_op_stop(struct ieee80211_hw *hw)
+{
+       struct esp_pub *epub;
+
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s\n", __func__);
+
+       if (!hw) {
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no hw!\n", __func__);
+               return;
+       }
+
+       epub = (struct esp_pub *)hw->priv;
+
+       if (!epub) {
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s no epub!\n", __func__);
+               return;
+       }
+
+       atomic_set(&epub->wl.off, 1);
+
+#ifdef HOST_RESET_BUG
+       mdelay(200);
+#endif
+
+       if (epub->wl.scan_req) {
+               hw_scan_done(epub, true);
+               epub->wl.scan_req=NULL;
+               //msleep(2);
+       }
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))        
+#ifdef CONFIG_PM
+static int esp_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+{
+       esp_dbg(ESP_DBG_OP, "%s\n", __func__);
+
+       return 0;
+}
+
+static int esp_op_resume(struct ieee80211_hw *hw)
+{
+       esp_dbg(ESP_DBG_OP, "%s\n", __func__);
+
+       return 0;
+}
+#endif //CONFIG_PM
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+static int esp_op_add_interface(struct ieee80211_hw *hw,
+               struct ieee80211_if_init_conf *conf)
+#else
+static int esp_op_add_interface(struct ieee80211_hw *hw,
+               struct ieee80211_vif *vif)
+#endif
+{
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       struct ieee80211_vif *vif = conf->vif;
+#endif
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       struct sip_cmd_setvif svif;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter: type %d, addr %pM\n", __func__, vif->type, conf->mac_addr);
+#else
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter: type %d, addr %pM\n", __func__, vif->type, vif->addr);
+#endif
+
+       memset(&svif, 0, sizeof(struct sip_cmd_setvif));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       memcpy(svif.mac, conf->mac_addr, ETH_ALEN);
+       evif->index = svif.index = getaddr_index(conf->mac_addr, epub);
+#else
+       memcpy(svif.mac, vif->addr, ETH_ALEN);
+       evif->index = svif.index = getaddr_index(vif->addr, epub);
+#endif
+       evif->epub = epub;
+       epub->vif = vif;
+       svif.set = 1;
+       if((1 << svif.index) & epub->vif_slot){
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s interface %d already used\n", __func__, svif.index);
+               return -EOPNOTSUPP;
+       }
+       epub->vif_slot |= 1 << svif.index;
+
+       if (svif.index == ESP_PUB_MAX_VIF) {
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s only support MAX %d interface\n", __func__, ESP_PUB_MAX_VIF);
+               return -EOPNOTSUPP;
+       }
+
+       switch (vif->type) {
+               case NL80211_IFTYPE_STATION:
+                       //if (svif.index == 1)
+                       //      vif->type = NL80211_IFTYPE_UNSPECIFIED;
+                       ESP_IEEE80211_DBG(ESP_SHOW, "%s STA \n", __func__);
+                       svif.op_mode = 0;
+                       svif.is_p2p = 0;
+                       break;
+               case NL80211_IFTYPE_AP:
+                       ESP_IEEE80211_DBG(ESP_SHOW, "%s AP \n", __func__);
+                       svif.op_mode = 1;
+                       svif.is_p2p = 0;
+                       break;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+               case NL80211_IFTYPE_P2P_CLIENT:
+                       ESP_IEEE80211_DBG(ESP_SHOW, "%s P2P_CLIENT \n", __func__);
+                       svif.op_mode = 0;
+                       svif.is_p2p = 1;
+                       break;
+               case NL80211_IFTYPE_P2P_GO:
+                       ESP_IEEE80211_DBG(ESP_SHOW, "%s P2P_GO \n", __func__);
+                       svif.op_mode = 1;
+                       svif.is_p2p = 1;
+                       break;
+#endif
+               case NL80211_IFTYPE_UNSPECIFIED:
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_WDS:
+               case NL80211_IFTYPE_MONITOR:
+               default:
+                       ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s does NOT support type %d\n", __func__, vif->type);
+                       return -EOPNOTSUPP;
+       }
+
+       sip_cmd(epub, SIP_CMD_SETVIF, (u8 *)&svif, sizeof(struct sip_cmd_setvif));
+       return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+static int esp_op_change_interface(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif,
+                                   enum nl80211_iftype new_type, bool p2p)
+{
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       struct sip_cmd_setvif svif;
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter,change to if:%d \n", __func__, new_type);
+       
+       if (new_type == NL80211_IFTYPE_AP) {
+               ESP_IEEE80211_DBG(ESP_SHOW, "%s enter,change to AP \n", __func__);
+       }
+
+       if (vif->type != new_type) {
+               ESP_IEEE80211_DBG(ESP_SHOW, "%s type from %d to %d\n", __func__, vif->type, new_type);
+       }
+       
+       memset(&svif, 0, sizeof(struct sip_cmd_setvif));
+       memcpy(svif.mac, vif->addr, ETH_ALEN);
+       svif.index = evif->index;
+       svif.set = 2;
+       
+       switch (new_type) {
+        case NL80211_IFTYPE_STATION:
+                svif.op_mode = 0;
+                svif.is_p2p = p2p;
+                break;
+        case NL80211_IFTYPE_AP:
+                svif.op_mode = 1;
+                svif.is_p2p = p2p;
+                break;
+        case NL80211_IFTYPE_P2P_CLIENT:
+                svif.op_mode = 0;
+                svif.is_p2p = 1;
+                break;
+        case NL80211_IFTYPE_P2P_GO:
+                svif.op_mode = 1;
+                svif.is_p2p = 1;
+                break;
+        case NL80211_IFTYPE_UNSPECIFIED:
+        case NL80211_IFTYPE_ADHOC:
+        case NL80211_IFTYPE_AP_VLAN:
+        case NL80211_IFTYPE_WDS:
+        case NL80211_IFTYPE_MONITOR:
+        default:
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s does NOT support type %d\n", __func__, vif->type);
+                return -EOPNOTSUPP;
+        }
+       sip_cmd(epub, SIP_CMD_SETVIF, (u8 *)&svif, sizeof(struct sip_cmd_setvif));
+        return 0;
+}
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+static void esp_op_remove_interface(struct ieee80211_hw *hw,
+                                    struct ieee80211_if_init_conf *conf)
+#else
+static void esp_op_remove_interface(struct ieee80211_hw *hw,
+                                    struct ieee80211_vif *vif)
+#endif
+{
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       struct ieee80211_vif *vif = conf->vif;
+#endif
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       struct sip_cmd_setvif svif;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 30))
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, vif addr %pM\n", __func__, conf->mac_addr);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, vif addr %pM, beacon enable %x\n", __func__, conf->mac_addr, vif->bss_conf.enable_beacon);
+#else
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, vif addr %pM, beacon enable %x\n", __func__, vif->addr, vif->bss_conf.enable_beacon);
+#endif
+
+       memset(&svif, 0, sizeof(struct sip_cmd_setvif));
+       svif.index = evif->index;
+       epub->vif_slot &= ~(1 << svif.index);
+
+       if(evif->ap_up){
+               evif->beacon_interval = 0;
+               del_timer_sync(&evif->beacon_timer);
+               evif->ap_up = false;
+       }
+       epub->vif = NULL;
+       evif->epub = NULL;
+
+       sip_cmd(epub, SIP_CMD_SETVIF, (u8 *)&svif, sizeof(struct sip_cmd_setvif));
+
+       /* clean up tx/rx queue */
+
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static void drv_handle_beacon(unsigned long data)
+{
+       struct ieee80211_vif *vif = (struct ieee80211_vif *) data;
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       struct sk_buff *beacon;
+       struct sk_buff *skb;
+       static int dbgcnt = 0;
+
+       if(evif->epub == NULL)
+               return;
+       beacon = ieee80211_beacon_get(evif->epub->hw, vif);
+
+       if (beacon && !(dbgcnt++ % 600)) {
+               ESP_IEEE80211_DBG(ESP_SHOW, " beacon length:%d,fc:0x%x\n", beacon->len,
+                       ((struct ieee80211_mgmt *)(beacon->data))->frame_control);
+
+       }
+
+       sip_tx_data_pkt_enqueue(evif->epub, beacon);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))    
+       mod_timer(&evif->beacon_timer, jiffies+msecs_to_jiffies(vif->bss_conf.beacon_int));
+#else
+    mod_timer(&evif->beacon_timer, jiffies+msecs_to_jiffies(evif->beacon_interval));
+#endif
+       //FIXME:the packets must be sent at home channel
+       //send buffer mcast frames
+       skb = ieee80211_get_buffered_bc(evif->epub->hw, vif);
+       while (skb) {
+               sip_tx_data_pkt_enqueue(evif->epub, skb);
+               skb = ieee80211_get_buffered_bc(evif->epub->hw, vif);
+       }
+}
+
+static void init_beacon_timer(struct ieee80211_vif *vif)
+{
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+
+       ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: beacon interval %x\n", __func__, evif->beacon_interval);
+
+       init_timer(&evif->beacon_timer);  //TBD, not init here...
+       evif->beacon_timer.expires=jiffies+msecs_to_jiffies(evif->beacon_interval*1024/1000);
+       evif->beacon_timer.data = (unsigned long) vif;
+       evif->beacon_timer.function = drv_handle_beacon;
+       add_timer(&evif->beacon_timer);
+}
+#endif
+
+/*
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+    static void init_beacon_timer(struct ieee80211_vif *vif)
+#else
+    static void init_beacon_timer(struct ieee80211_conf *conf)
+#endif
+{
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+       ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: beacon interval %x\n", __func__, vif->bss_conf.beacon_int);
+#else
+       ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: beacon interval %x\n", __func__, conf->beacon_int);
+#endif
+       init_timer(&evif->beacon_timer);  //TBD, not init here...
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+       evif->beacon_timer.expires=jiffies+msecs_to_jiffies(vif->bss_conf.beacon_int*102/100);
+       evif->beacon_timer.data = (unsigned long) vif;
+#else
+       evif->beacon_timer.expires=jiffies+msecs_to_jiffies(conf->beacon_int*102/100);
+       evif->beacon_timer.data = (unsigned long) conf;
+#endif
+       //evif->beacon_timer.data = (unsigned long) vif;
+       evif->beacon_timer.function = drv_handle_beacon;
+       add_timer(&evif->beacon_timer);
+}
+*/
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static int esp_op_config(struct ieee80211_hw *hw, u32 changed)
+#else
+static int esp_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+#endif
+{
+       //struct ieee80211_conf *conf = &hw->conf;
+
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
+       //struct esp_vif *evif = (struct esp_vif *)epub->vif->drv_priv;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter 0x%08x\n", __func__, changed);
+
+        if (changed&IEEE80211_CONF_CHANGE_CHANNEL) {
+                sip_send_config(epub, &hw->conf);
+       }
+#else
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter 0x%08x\n", __func__, conf->flags);
+        sip_send_config(epub, &hw->conf);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29))
+       //evif->beacon_interval = conf->beacon_int;
+       //init_beacon_timer(epub->vif);
+#endif
+
+
+#if 0
+       if (changed & IEEE80211_CONF_CHANGE_PS) {
+               struct esp_ps *ps = &epub->ps;
+
+               ps->dtim_period = conf->ps_dtim_period;
+               ps->max_sleep_period = conf->max_sleep_period;
+               esp_ps_config(epub, ps, (conf->flags & IEEE80211_CONF_PS));
+       }
+#endif
+    return 0;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+static int esp_op_config_interface (struct ieee80211_hw *hw, 
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_if_conf *conf)
+{
+       // assoc = 2 means AP
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       //struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: changed %x, bssid %pM,vif->type = %d\n", __func__, conf->changed, conf->bssid,vif->type);
+
+       if(conf->bssid)
+               memcpy(epub->wl.bssid, conf->bssid, ETH_ALEN);
+       else
+               memset(epub->wl.bssid, 0, ETH_ALEN);
+
+       if(vif->type == NL80211_IFTYPE_AP){
+               if((conf->changed & IEEE80211_IFCC_BEACON)){
+                       sip_send_bss_info_update(epub, evif, (u8*)conf->bssid, 2);
+                       //evif->beacon_interval = conf->beacon_int;
+               }
+               else{
+                       ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s op----1-- mode unspecified\n", __func__);
+               }
+       }
+       else{
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s op----2-- mode unspecified\n", __func__);
+       }
+       return 0;
+}
+#endif
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static void esp_op_bss_info_changed(struct ieee80211_hw *hw,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_bss_conf *info,
+                                    u32 changed)
+{
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+        struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+#endif
+
+       // ieee80211_bss_conf(include/net/mac80211.h) is included in ieee80211_sub_if_data(net/mac80211/ieee80211_i.h) , does bssid=ieee80211_if_ap's ssid ?
+       // in 2.6.27, ieee80211_sub_if_data has ieee80211_bss_conf while in 2.6.32 ieee80211_sub_if_data don't have ieee80211_bss_conf
+       // in 2.6.27, ieee80211_bss_conf->enable_beacon don't exist, does it mean it support beacon always?
+       // ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: vif addr %pM, changed %x, assoc %x, bssid %pM\n", __func__, vif->addr, changed, info->assoc, info->bssid);
+       // sdata->u.sta.bssid
+
+        ESP_IEEE80211_DBG(ESP_DBG_OP, " %s enter: changed %x, assoc %x, bssid %pM\n", __func__, changed, info->assoc, info->bssid);
+
+        if (vif->type == NL80211_IFTYPE_STATION) {
+               if ((changed & BSS_CHANGED_BSSID) ||
+                               ((changed & BSS_CHANGED_ASSOC) && (info->assoc)))
+               {
+                       ESP_IEEE80211_DBG(ESP_DBG_TRACE, " %s STA change bssid or assoc\n", __func__);
+                       memcpy(epub->wl.bssid, (u8*)info->bssid, ETH_ALEN);
+                       sip_send_bss_info_update(epub, evif, (u8*)info->bssid, info->assoc);
+               } else if ((changed & BSS_CHANGED_ASSOC) && (!info->assoc)) {
+                       ESP_IEEE80211_DBG(ESP_DBG_TRACE, " %s STA change disassoc\n", __func__);
+                       memset(epub->wl.bssid, 0, ETH_ALEN);
+                       sip_send_bss_info_update(epub, evif, (u8*)info->bssid, info->assoc);
+               } else {
+                       ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s wrong mode of STA mode\n", __func__);
+               }
+       } else if (vif->type == NL80211_IFTYPE_AP) {
+               if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
+                               (changed & BSS_CHANGED_BEACON_INT)) {
+                       ESP_IEEE80211_DBG(ESP_DBG_TRACE, " %s AP change enable %d, interval is %d, bssid %pM\n", __func__, info->enable_beacon, info->beacon_int, info->bssid);
+                       if (info->enable_beacon && evif->ap_up != true) {
+                               evif->beacon_interval = info->beacon_int;
+                               init_beacon_timer(vif);
+                               sip_send_bss_info_update(epub, evif, (u8*)info->bssid, 2);
+                               evif->ap_up = true;
+                       } else if (!info->enable_beacon && evif->ap_up &&
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+                    !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)
+#else
+                    true
+#endif
+                    ) {
+                               ESP_IEEE80211_DBG(ESP_DBG_TRACE, " %s AP disable beacon, interval is %d\n", __func__, info->beacon_int);
+                               evif->beacon_interval = 0;
+                               del_timer_sync(&evif->beacon_timer);
+                               sip_send_bss_info_update(epub, evif, (u8*)info->bssid, 2);
+                               evif->ap_up = false;
+                       }
+               }
+       } else {
+               ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s op mode unspecified\n", __func__);
+       }
+}
+#endif
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+static u64 esp_op_prepare_multicast(struct ieee80211_hw *hw,
+                                    int mc_count, struct dev_addr_list *mc_list)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+#else
+static u64 esp_op_prepare_multicast(struct ieee80211_hw *hw,
+                                    struct netdev_hw_addr_list *mc_list)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+
+#endif /* NEW_KERNEL && KERNEL_35 */
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+static void esp_op_configure_filter(struct ieee80211_hw *hw,
+                                    unsigned int changed_flags,
+                                    unsigned int *total_flags,
+                                    u64 multicast)
+#else
+static void esp_op_configure_filter(struct ieee80211_hw *hw,
+                                    unsigned int changed_flags,
+                                    unsigned int *total_flags,
+                                    int mc_count,
+                                    struct dev_addr_list *mc_list)
+#endif
+{
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        epub->rx_filter = 0;
+
+        if (*total_flags & FIF_PROMISC_IN_BSS)
+                epub->rx_filter |= FIF_PROMISC_IN_BSS;
+
+        if (*total_flags & FIF_ALLMULTI)
+                epub->rx_filter |= FIF_ALLMULTI;
+
+        *total_flags = epub->rx_filter;
+}
+
+#if 0
+static int esp_op_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+                          bool set)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+static int esp_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                          struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                          struct ieee80211_key_conf *key)
+#else
+static int esp_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                          const u8 *local_address,const u8 *address,
+                          struct ieee80211_key_conf *key)
+#endif
+{
+        u8 i;
+        int  ret;
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+        u8 ifidx = evif->index;
+#else
+        u8 ifidx = getaddr_index((u8 *)(local_address), epub); 
+#endif
+        u8 *peer_addr,isvalid;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, flags = %x keyindx = %x cmd = %x mac = %pM cipher = %x\n", __func__, key->flags, key->keyidx, cmd, vif->addr, key->cipher);
+#else
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, flags = %x keyindx = %x cmd = %x cipher = %x\n", __func__, key->flags, key->keyidx, cmd, key->alg);
+#endif
+
+        key->flags= key->flags|IEEE80211_KEY_FLAG_GENERATE_IV;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        if (sta) {
+                if (memcmp(sta->addr, epub->wl.bssid, ETH_ALEN))
+                        peer_addr = sta->addr;
+                else
+                        peer_addr = epub->wl.bssid;
+        } else {
+                peer_addr=epub->wl.bssid;
+        }
+#else
+        peer_addr = (u8 *)address;
+#endif
+        isvalid = (cmd==SET_KEY) ? 1 : 0;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+        if ((key->flags&IEEE80211_KEY_FLAG_PAIRWISE) || (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104))
+#else
+        if ((key->flags&IEEE80211_KEY_FLAG_PAIRWISE) || (key->alg == ALG_WEP))
+#endif
+           {
+               if (isvalid) {
+                       for (i = 0; i < 19; i++) {
+                               if (epub->hi_map[i].flag == 0) {
+                                       epub->hi_map[i].flag = 1;
+                                       key->hw_key_idx = i + 6;
+                                       memcpy(epub->hi_map[i].mac, peer_addr, ETH_ALEN);
+                                       break;
+                               }
+                       }
+               } else {
+                       u8 index = key->hw_key_idx - 6;
+                       epub->hi_map[index].flag = 0;
+                       memset(epub->hi_map[index].mac, 0, ETH_ALEN);
+               }
+        } else {
+               if(isvalid){
+                       for(i = 0; i < 2; i++)
+                               if (epub->low_map[ifidx][i].flag == 0) {
+                                       epub->low_map[ifidx][i].flag = 1;
+                                        key->hw_key_idx = i + ifidx * 2 + 2;
+                                        memcpy(epub->low_map[ifidx][i].mac, peer_addr, ETH_ALEN);
+                                        break;
+                                }
+               } else {
+                       u8 index = key->hw_key_idx - 2 - ifidx * 2;
+                               epub->low_map[ifidx][index].flag = 0;
+                               memset(epub->low_map[ifidx][index].mac, 0, ETH_ALEN);
+               }
+               //key->hw_key_idx = key->keyidx + ifidx * 2 + 1;
+        }
+
+        if (key->hw_key_idx >= 6) {
+               /*send sub_scan task to target*/
+               //epub->wl.ptk = (cmd==SET_KEY) ? key : NULL;
+               if(isvalid)
+                       atomic_inc(&epub->wl.ptk_cnt);
+               else
+                       atomic_dec(&epub->wl.ptk_cnt);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+               if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104)
+#else
+               if (key->alg == ALG_WEP)
+#endif
+               {
+                       if(isvalid)
+                               atomic_inc(&epub->wl.gtk_cnt);
+                       else
+                               atomic_dec(&epub->wl.gtk_cnt);
+               }
+        } else {
+               /*send sub_scan task to target*/
+               if(isvalid)
+                       atomic_inc(&epub->wl.gtk_cnt);
+               else
+                       atomic_dec(&epub->wl.gtk_cnt);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+               if((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104))
+#else
+        if((key->alg == ALG_WEP))
+#endif
+               {
+                       if(isvalid)
+                               atomic_inc(&epub->wl.ptk_cnt);
+                       else
+                               atomic_dec(&epub->wl.ptk_cnt);
+                       //epub->wl.ptk = (cmd==SET_KEY) ? key : NULL;
+               }
+        }
+
+        ret = sip_send_setkey(epub, ifidx, peer_addr, key, isvalid);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+       if((key->cipher == WLAN_CIPHER_SUITE_TKIP || key->cipher == WLAN_CIPHER_SUITE_TKIP))
+#else
+       if((key->alg == ALG_TKIP))
+#endif
+       {
+               if(ret == 0)
+                       atomic_set(&epub->wl.tkip_key_set, 1);
+       }
+
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s exit\n", __func__);
+        return ret;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+static void esp_op_update_tkip_key(struct ieee80211_hw *hw,
+                                   struct ieee80211_key_conf *conf, const u8 *address,
+                                   u32 iv32, u16 *phase1key)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+}
+#else
+static void esp_op_update_tkip_key(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_key_conf *conf,
+                                   struct ieee80211_sta *sta,
+                                   u32 iv32, u16 *phase1key)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+}
+#endif /* KERNEL_35 NEW_KERNEL*/
+
+
+void hw_scan_done(struct esp_pub *epub, bool aborted)
+{
+        cancel_delayed_work_sync(&epub->scan_timeout_work);
+
+        ASSERT(epub->wl.scan_req != NULL);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        ieee80211_scan_completed(epub->hw, aborted);
+#else
+        ieee80211_scan_completed(epub->hw);
+#endif
+        if (test_and_clear_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags)) {
+                sip_trigger_txq_process(epub->sip);
+        }
+}
+
+static void hw_scan_timeout_report(struct work_struct *work)
+{
+        struct esp_pub *epub =
+                container_of(work, struct esp_pub, scan_timeout_work.work);
+        bool aborted;
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "eagle hw scan done\n");
+
+        if (test_and_clear_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags)) {
+                sip_trigger_txq_process(epub->sip);
+        }
+        /*check if normally complete or aborted like timeout/hw error */
+        aborted = (epub->wl.scan_req) ? true : false;
+
+        if (aborted==true) {
+                epub->wl.scan_req = NULL;
+        }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        ieee80211_scan_completed(epub->hw, aborted);
+#else
+        ieee80211_scan_completed(epub->hw);
+#endif  
+}
+
+#if 0
+static void esp_op_sw_scan_start(struct ieee80211_hw *hw)
+{}
+
+static void esp_op_sw_scan_complete(struct ieee80211_hw *hw)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+}
+#endif
+
+#if 0
+static int esp_op_get_stats(struct ieee80211_hw *hw,
+                            struct ieee80211_low_level_stats *stats)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+
+static void esp_op_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
+                                u32 *iv32, u16 *iv16)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+}
+#endif
+
+static int esp_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static int esp_node_attach(struct ieee80211_hw *hw, u8 ifidx, struct ieee80211_sta *sta)
+#else
+static int esp_node_attach(struct ieee80211_hw *hw, u8 ifidx, const u8 *addr)
+#endif
+{
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+        struct esp_node *node;
+        u8 tidno;
+        struct esp_tx_tid *tid;
+           int i;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+        struct sta_info *info = sta_info_get(container_of(hw,struct ieee80211_local,hw),(u8 *)addr);
+        struct ieee80211_ht_info *ht_info = &info->ht_info;
+#endif
+
+       spin_lock_bh(&epub->tx_ampdu_lock);
+
+       if(hweight32(epub->enodes_maps[ifidx]) < ESP_PUB_MAX_STA && (i = ffz(epub->enodes_map)) < ESP_PUB_MAX_STA + 1){
+               epub->enodes_map |= (1 << i);
+               epub->enodes_maps[ifidx] |= (1 << i);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+               node = (struct esp_node *)sta->drv_priv;
+        epub->enodes[i] = node;
+               node->sta = sta;
+#else
+               node = &epub->nodes[i];
+        epub->enodes[i] = node;
+               memcpy(node->addr, addr, ETH_ALEN);
+        memcpy(&node->aid, &info->aid, sizeof(node->aid)); 
+        memcpy(node->supp_rates, info->supp_rates, sizeof(node->supp_rates));
+        memcpy(&node->ht_info.cap, &ht_info->cap, sizeof(node->ht_info.cap));
+        memcpy(&node->ht_info.ht_supported, &ht_info->ht_supported, sizeof(node->ht_info.ht_supported));
+        memcpy(&node->ht_info.ampdu_factor, &ht_info->ampdu_factor, sizeof(node->ht_info.ampdu_factor));
+        memcpy(&node->ht_info.ampdu_density, &ht_info->ampdu_density, sizeof(node->ht_info.ampdu_density));
+#endif
+               node->ifidx = ifidx;
+               node->index = i;
+
+               for(tidno = 0, tid = &node->tid[tidno]; tidno < WME_NUM_TID; tidno++) {
+                tid->ssn = 0;
+                tid->cnt = 0;
+                tid->state = ESP_TID_STATE_INIT;
+        }
+
+
+       } else {
+               i = -1;
+       }
+
+       spin_unlock_bh(&epub->tx_ampdu_lock);
+       return i;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static int esp_node_detach(struct ieee80211_hw *hw, u8 ifidx, struct ieee80211_sta *sta)
+#else
+static int esp_node_detach(struct ieee80211_hw *hw, u8 ifidx, const u8 *addr)
+#endif
+{
+    struct esp_pub *epub = (struct esp_pub *)hw->priv;
+       u8 map;
+       int i;
+    struct esp_node *node = NULL;
+
+       spin_lock_bh(&epub->tx_ampdu_lock);
+       map = epub->enodes_maps[ifidx];
+       while(map != 0){
+               i = ffs(map) - 1;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+               if(epub->enodes[i]->sta == sta){
+                       epub->enodes[i]->sta = NULL;
+#else
+               if(memcmp(epub->enodes[i]->addr, addr, ETH_ALEN) == 0){
+#endif
+            node = epub->enodes[i];
+                       epub->enodes[i] = NULL;
+                       epub->enodes_map &= ~(1 << i);
+                       epub->enodes_maps[ifidx] &= ~(1 << i);
+                       
+                       spin_unlock_bh(&epub->tx_ampdu_lock);
+                       return i;
+               }
+               map &= ~(1 << i);
+       }
+
+       spin_unlock_bh(&epub->tx_ampdu_lock);
+       return -1;
+}
+
+struct esp_node * esp_get_node_by_addr(struct esp_pub * epub, const u8 *addr)
+{
+       int i;
+       u8 map;
+       struct esp_node *node = NULL;
+       if(addr == NULL)
+               return NULL;
+       spin_lock_bh(&epub->tx_ampdu_lock);
+       map = epub->enodes_map;
+       while(map != 0){
+               i = ffs(map) - 1;
+               map &= ~(1 << i);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+               if(memcmp(epub->enodes[i]->sta->addr, addr, ETH_ALEN) == 0)
+#else
+               if(memcmp(epub->enodes[i]->addr, addr, ETH_ALEN) == 0)
+#endif
+               {
+                       node = epub->enodes[i];
+                       break;
+               }
+       }
+
+       spin_unlock_bh(&epub->tx_ampdu_lock);
+       return node;
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static int esp_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+#else
+static int esp_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *addr)
+#endif
+{
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       int index;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+       struct esp_node *node;
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, addr %pM\n", __func__, addr);
+       index = esp_node_attach(hw, evif->index, addr);
+
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, sta addr %pM\n", __func__, sta->addr);
+#else 
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, vif addr %pM, sta addr %pM\n", __func__, vif->addr, sta->addr);
+#endif
+       index = esp_node_attach(hw, evif->index, sta);
+#endif
+
+       if(index < 0)
+               return -1;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+       sip_send_set_sta(epub, evif->index, 1, sta, vif, (u8)index);
+#else
+       node = esp_get_node_by_addr(epub, addr);
+       sip_send_set_sta(epub, evif->index, 1, node, vif, (u8)index);
+#endif
+    return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static int esp_op_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+#else
+static int esp_op_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *addr)
+#endif
+{      
+       struct esp_pub *epub = (struct esp_pub *)hw->priv;
+       struct esp_vif *evif = (struct esp_vif *)vif->drv_priv;
+       int index;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+       struct esp_node *node;
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, addr %pM\n", __func__, addr);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, sta addr %pM\n", __func__, sta->addr);
+#else 
+       ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, vif addr %pM, sta addr %pM\n", __func__, vif->addr, sta->addr);
+#endif
+       
+       //remove a connect in target
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+       index = esp_node_detach(hw, evif->index, sta);
+       sip_send_set_sta(epub, evif->index, 0, sta, vif, (u8)index);
+#else
+       node = esp_get_node_by_addr(epub, addr);
+       index = esp_node_detach(hw, evif->index, addr);
+       sip_send_set_sta(epub, evif->index, 0, node, vif, node->index);
+#endif
+
+       return 0;
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static void esp_op_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
+#else
+static void esp_op_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, const u8 *addr)
+#endif
+{
+        //struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        switch (cmd) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+        case STA_NOTIFY_ADD:
+            ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s cmd add\n", __func__);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+            esp_op_sta_add(hw, vif, sta);
+#else
+            esp_op_sta_add(hw, vif, addr);
+#endif
+            break;
+
+        case STA_NOTIFY_REMOVE:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+            esp_op_sta_remove(hw, vif, sta);
+#else
+            esp_op_sta_remove(hw, vif, addr);
+#endif
+            break;
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+        case STA_NOTIFY_SLEEP:
+                break;
+
+        case STA_NOTIFY_AWAKE:
+                break;
+#endif /* NEW_KERNEL */
+
+        default:
+                break;
+        }
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+static int esp_op_conf_tx(struct ieee80211_hw *hw, 
+                         struct ieee80211_vif *vif,
+                         u16 queue,
+                          const struct ieee80211_tx_queue_params *params)
+
+#else
+static int esp_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+                          const struct ieee80211_tx_queue_params *params)
+#endif
+{
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+        return sip_send_wmm_params(epub, queue, params);
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+static int esp_op_get_tx_stats(struct ieee80211_hw *hw,
+                               struct ieee80211_tx_queue_stats *stats)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+#endif /* !NEW_KERNEL && !KERNEL_35*/
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+static u64 esp_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+#else
+static u64 esp_op_get_tsf(struct ieee80211_hw *hw)
+#endif
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+static void esp_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf)
+#else
+static void esp_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+#endif
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+}
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+static void esp_op_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+#else
+static void esp_op_reset_tsf(struct ieee80211_hw *hw)
+#endif
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+static void esp_op_rfkill_poll(struct ieee80211_hw *hw)
+{
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        wiphy_rfkill_set_hw_state(hw->wiphy,
+                                  test_bit(ESP_WL_FLAG_RFKILL, &epub->wl.flags) ? true : false);
+}
+#endif
+
+#ifdef HW_SCAN
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+static int esp_op_hw_scan(struct ieee80211_hw *hw,
+                          struct cfg80211_scan_request *req)
+#else
+static int esp_op_hw_scan(struct ieee80211_hw *hw,
+                          struct ieee80211_vif *vif,
+                          struct cfg80211_scan_request *req)
+#endif /* NEW_KERNEL && KERNEL_35 */
+{
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+        int i, ret;
+        bool scan_often = true;
+
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s\n", __func__);
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "scan, %d\n", req->n_ssids);
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "scan, len 1:%d,ssid 1:%s\n", req->ssids->ssid_len, req->ssids->ssid_len == 0? "":(char *)req->ssids->ssid);
+        if(req->n_ssids > 1)
+                ESP_IEEE80211_DBG(ESP_DBG_TRACE, "scan, len 2:%d,ssid 2:%s\n", (req->ssids+1)->ssid_len, (req->ssids+1)->ssid_len == 0? "":(char *)(req->ssids + 1)->ssid);
+
+        /*scan_request is keep allocate untill scan_done,record it
+          to split request into multi sdio_cmd*/
+       if (atomic_read(&epub->wl.off)) {
+               esp_dbg(ESP_DBG_ERROR, "%s scan but wl off \n", __func__);
+               return -1;
+       }
+
+        if(req->n_ssids > 1){
+                struct cfg80211_ssid *ssid2 = req->ssids + 1;
+                if((req->ssids->ssid_len > 0 && ssid2->ssid_len > 0) || req->n_ssids > 2){
+                        ESP_IEEE80211_DBG(ESP_DBG_ERROR, "scan ssid num: %d, ssid1:%s, ssid2:%s,not support\n", req->n_ssids, 
+                                       req->ssids->ssid_len == 0 ? "":(char *)req->ssids->ssid, ssid2->ssid_len == 0? "":(char *)ssid2->ssid);
+                               return -1;
+                       }
+        }
+
+        epub->wl.scan_req = req;
+
+        for (i = 0; i < req->n_channels; i++)
+                ESP_IEEE80211_DBG(ESP_DBG_TRACE, "eagle hw_scan freq %d\n",
+                                  req->channels[i]->center_freq);
+#if 0
+        for (i = 0; i < req->n_ssids; i++) {
+                if (req->ssids->ssid_len> 0) {
+                        req->ssids->ssid[req->ssids->ssid_len]='\0';
+                        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "scan_ssid %d:%s\n",
+                                          i, req->ssids->ssid);
+                }
+        }
+#endif
+
+        /*in connect state, suspend tx data*/
+        if(epub->sip->support_bgscan &&
+               test_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags) &&
+               req->n_channels > 0)
+       {
+
+                scan_often = epub->scan_permit_valid && time_before(jiffies, epub->scan_permit);
+                epub->scan_permit_valid = true;
+
+                if (!scan_often) {
+/*                        epub->scan_permit = jiffies + msecs_to_jiffies(900);
+                        set_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags);
+                        if (atomic_read(&epub->txq_stopped) == false) {
+                                atomic_set(&epub->txq_stopped, true);
+                                ieee80211_stop_queues(hw);
+                        }
+*/
+                } else {
+                        ESP_IEEE80211_DBG(ESP_DBG_LOG, "scan too often\n");
+                       return -1;
+                }
+        } else {
+               scan_often = false;
+       }
+
+        /*send sub_scan task to target*/
+        ret = sip_send_scan(epub);
+
+        if (ret) {
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "fail to send scan_cmd\n");
+               return -1;
+        } else {
+               if(!scan_often) {
+                       epub->scan_permit = jiffies + msecs_to_jiffies(900);
+                        set_bit(ESP_WL_FLAG_STOP_TXQ, &epub->wl.flags);
+                        if (atomic_read(&epub->txq_stopped) == false) {
+                                atomic_set(&epub->txq_stopped, true);
+                                ieee80211_stop_queues(hw);
+                        }
+                       /*force scan complete in case target fail to report in time*/
+                       ieee80211_queue_delayed_work(hw, &epub->scan_timeout_work, req->n_channels * HZ / 4);
+               }
+        }
+
+        return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+static int esp_op_remain_on_channel(struct ieee80211_hw *hw,
+                                    struct ieee80211_channel *chan,
+                                    enum nl80211_channel_type channel_type,
+                                    int duration)
+{
+      struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+      ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, center_freq = %d duration = %d\n", __func__, chan->center_freq, duration);
+      sip_send_roc(epub, chan->center_freq, duration);
+      return 0;
+}
+
+static int esp_op_cancel_remain_on_channel(struct ieee80211_hw *hw)
+{
+      struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+      ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__);
+      epub->roc_flags= 0;  // to disable roc state
+      sip_send_roc(epub, 0, 0);
+     return 0;
+}
+#endif /* > 2.6.38 */
+#endif
+
+void esp_rocdone_process(struct ieee80211_hw *hw, struct sip_evt_roc *report)
+{    
+      struct esp_pub *epub = (struct esp_pub *)hw->priv;
+
+      ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter, state = %d is_ok = %d\n", __func__, report->state, report->is_ok);
+
+      //roc process begin 
+      if((report->state==1)&&(report->is_ok==1)) 
+      {
+           epub->roc_flags=1;  //flags in roc state, to fix channel, not change
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+           ieee80211_ready_on_channel(hw);
+#endif
+      }
+      else if ((report->state==0)&&(report->is_ok==1))    //roc process timeout
+      {
+           epub->roc_flags= 0;  // to disable roc state
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+           ieee80211_remain_on_channel_expired(hw);     
+#endif
+       }
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))        
+static int esp_op_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                               const struct cfg80211_bitrate_mask *mask)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__);
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s vif->macaddr[%pM], mask[%d]\n", __func__, vif->addr, mask->control[0].legacy);
+
+       return 0;
+}
+#endif
+
+//void esp_op_flush(struct ieee80211_hw *hw, bool drop)
+void esp_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)      
+{
+       
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__);
+       do{
+               
+               struct esp_pub *epub = (struct esp_pub *)hw->priv;
+               unsigned long time = jiffies + msecs_to_jiffies(15);
+               while(atomic_read(&epub->sip->tx_data_pkt_queued)){
+                       if(!time_before(jiffies, time)){
+                               break;
+                       }
+#if  !defined(FPGA_LOOPBACK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+            ieee80211_queue_work(epub->hw, &epub->tx_work);
+#else
+            queue_work(epub->esp_wkq, &epub->tx_work);
+#endif
+                       //sip_txq_process(epub);
+               }
+               mdelay(10);
+               
+       }while(0);
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+static int esp_op_ampdu_action(struct ieee80211_hw *hw,
+                enum ieee80211_ampdu_mlme_action action,
+                           struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+#else
+static int esp_op_ampdu_action(struct ieee80211_hw *hw,
+                enum ieee80211_ampdu_mlme_action action,
+                           const u8 *addr, u16 tid, u16 *ssn)
+#endif
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+static int esp_op_ampdu_action(struct ieee80211_hw *hw,
+                struct ieee80211_vif *vif,
+                               enum ieee80211_ampdu_mlme_action action,
+                               struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+#else
+static int esp_op_ampdu_action(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               enum ieee80211_ampdu_mlme_action action,
+                               struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+                               u8 buf_size)
+#endif
+#endif /* NEW_KERNEL && KERNEL_35 */
+{
+        int ret = -EOPNOTSUPP;
+        struct esp_pub *epub = (struct esp_pub *)hw->priv;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+        struct esp_node * node = (struct esp_node *)sta->drv_priv;
+#else
+        struct esp_node * node = esp_get_node_by_addr(epub, addr);
+#endif
+        struct esp_tx_tid * tid_info = &node->tid[tid];
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+       u8 buf_size = 64;
+#endif
+
+        ESP_IEEE80211_DBG(ESP_DBG_OP, "%s enter \n", __func__);
+        switch(action) {
+        case IEEE80211_AMPDU_TX_START:
+                if (mod_support_no_txampdu() /*||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                       hw->conf.channel_type == NL80211_CHAN_NO_HT 
+#else
+                        !(hw->conf.flags&IEEE80211_CONF_SUPPORT_HT_MODE)
+#endif*/ //add libing
+                            )
+                        return ret;
+
+               //if (vif->p2p || vif->type != NL80211_IFTYPE_STATION)
+               //      return ret;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s TX START, addr:%pM,tid:%u\n", __func__, addr, tid);
+#else
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s TX START, addr:%pM,tid:%u,state:%d\n", __func__, sta->addr, tid, tid_info->state);
+#endif
+                spin_lock_bh(&epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))                
+                ASSERT(tid_info->state == ESP_TID_STATE_TRIGGER);
+                *ssn = tid_info->ssn;
+                tid_info->state = ESP_TID_STATE_PROGRESS;
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ieee80211_start_tx_ba_cb_irqsafe(hw, addr, tid);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
+                ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+#else
+                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+#endif
+                spin_unlock_bh(&epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                ret = 0;
+#else
+                spin_lock_bh(&epub->tx_ampdu_lock);
+               
+                if (tid_info->state != ESP_TID_STATE_PROGRESS) {
+                        if (tid_info->state == ESP_TID_STATE_INIT) {
+                                               printk(KERN_ERR "%s WIFI RESET, IGNORE\n", __func__);
+                                spin_unlock_bh(&epub->tx_ampdu_lock);
+                                               return -ENETRESET;
+                        } else {
+                                               ASSERT(0);
+                        }
+                }
+                       
+                tid_info->state = ESP_TID_STATE_OPERATIONAL;
+                spin_unlock_bh(&epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_TX_OPERATIONAL, sta->addr, tid, node->ifidx, buf_size);
+#else
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_TX_OPERATIONAL, addr, tid, node->ifidx, buf_size);
+#endif
+#endif
+                break;
+  /*      case IEEE80211_AMPDU_TX_STOP:
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s TX STOP, addr:%pM,tid:%u\n", __func__, addr, tid);
+#else
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s TX STOP, addr:%pM,tid:%u,state:%d\n", __func__, sta->addr, tid, tid_info->state);
+#endif
+                spin_lock_bh(&epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+                if(tid_info->state == ESP_TID_STATE_WAIT_STOP)
+                        tid_info->state = ESP_TID_STATE_STOP;
+                else
+                        tid_info->state = ESP_TID_STATE_INIT;
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ieee80211_stop_tx_ba_cb_irqsafe(hw, addr, tid);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
+                ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+#else
+                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+#endif
+                spin_unlock_bh(&epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_TX_STOP, addr, tid, node->ifidx, 0);
+#else
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_TX_STOP, sta->addr, tid, node->ifidx, 0);
+#endif
+                break;*/ //add libing
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        case IEEE80211_AMPDU_TX_OPERATIONAL:
+#else
+        case IEEE80211_AMPDU_TX_RESUME:
+#endif
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s TX OPERATION, addr:%pM,tid:%u,state:%d\n", __func__, sta->addr, tid, tid_info->state);
+                spin_lock_bh(&epub->tx_ampdu_lock);
+               
+                if (tid_info->state != ESP_TID_STATE_PROGRESS) {
+                        if (tid_info->state == ESP_TID_STATE_INIT) {
+                                               printk(KERN_ERR "%s WIFI RESET, IGNORE\n", __func__);
+                                spin_unlock_bh(&epub->tx_ampdu_lock);
+                                               return -ENETRESET;
+                        } else {
+                                               ASSERT(0);
+                        }
+                }
+                       
+                tid_info->state = ESP_TID_STATE_OPERATIONAL;
+                spin_unlock_bh(&epub->tx_ampdu_lock);
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_TX_OPERATIONAL, sta->addr, tid, node->ifidx, buf_size);
+                break;
+#endif
+        case IEEE80211_AMPDU_RX_START:
+                if(mod_support_no_rxampdu() /*||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                        hw->conf.channel_type == NL80211_CHAN_NO_HT
+#else
+                        !(hw->conf.flags&IEEE80211_CONF_SUPPORT_HT_MODE)
+#endif*/// add libing
+                        )
+                        return ret;
+
+               if (
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+                vif->p2p 
+#else
+                false
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
+                || false
+#else
+                || vif->type != NL80211_IFTYPE_STATION
+#endif
+           )
+                       return ret;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s RX START %pM tid %u %u\n", __func__, addr, tid, *ssn);
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_RX_START, addr, tid, *ssn, 64);
+#else
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s RX START %pM tid %u %u\n", __func__, sta->addr, tid, *ssn);
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_RX_START, sta->addr, tid, *ssn, 64);
+#endif
+                break;
+        case IEEE80211_AMPDU_RX_STOP:
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s RX STOP %pM tid %u\n", __func__, addr, tid);
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_RX_STOP, addr, tid, 0, 0);
+#else
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "%s RX STOP %pM tid %u\n", __func__, sta->addr, tid);
+                ret = sip_send_ampdu_action(epub, SIP_AMPDU_RX_STOP, sta->addr, tid, 0, 0);
+#endif
+                break;
+        default:
+                break;
+        }
+        return ret;
+}
+
+#if 0
+static int esp_op_tx_last_beacon(struct ieee80211_hw *hw)
+{
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+
+#ifdef CONFIG_NL80211_TESTMODE
+static int esp_op_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
+{
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter \n", __func__);
+
+        return 0;
+}
+#endif /* CONFIG_NL80211_TESTMODE */
+#endif
+
+static void
+esp_tx_work(struct work_struct *work)
+{
+        struct esp_pub *epub = container_of(work, struct esp_pub, tx_work);
+
+        mutex_lock(&epub->tx_mtx);
+        sip_txq_process(epub);
+        mutex_unlock(&epub->tx_mtx);
+}
+
+#ifndef RX_SENDUP_SYNC
+//for debug
+static int data_pkt_dequeue_cnt = 0;
+static void _esp_flush_rxq(struct esp_pub *epub)
+{
+        struct sk_buff *skb = NULL;
+
+        while ((skb = skb_dequeue(&epub->rxq))) {
+                esp_dbg(ESP_DBG_TRACE, "%s call ieee80211_rx \n", __func__);
+                //local_bh_disable();
+                ieee80211_rx(epub->hw, skb);
+                //local_bh_enable();
+        }
+}
+
+static void
+esp_sendup_work(struct work_struct *work)
+{
+        struct esp_pub *epub = container_of(work, struct esp_pub, sendup_work);
+        spin_lock_bh(&epub->rx_lock);
+        _esp_flush_rxq(epub);
+        spin_unlock_bh(&epub->rx_lock);
+}
+#endif /* !RX_SENDUP_SYNC */
+
+static struct ieee80211_ops esp_mac80211_ops = {
+        .tx = esp_op_tx,
+        .start = esp_op_start,
+        .stop = esp_op_stop,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))        
+#ifdef CONFIG_PM
+        .suspend = esp_op_suspend,
+        .resume = esp_op_resume,
+#endif
+#endif
+        .add_interface = esp_op_add_interface,
+        .remove_interface = esp_op_remove_interface,
+        .config = esp_op_config,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+        .bss_info_changed = esp_op_bss_info_changed,
+#else
+        .config_interface = esp_op_config_interface,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+        .prepare_multicast = esp_op_prepare_multicast,
+#endif
+        .configure_filter = esp_op_configure_filter,
+        .set_key = esp_op_set_key,
+        .update_tkip_key = esp_op_update_tkip_key,
+        //.sched_scan_start = esp_op_sched_scan_start,
+        //.sched_scan_stop = esp_op_sched_scan_stop,
+        .set_rts_threshold = esp_op_set_rts_threshold,
+        .sta_notify = esp_op_sta_notify,
+        .conf_tx = esp_op_conf_tx,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+        .get_tx_stats = esp_op_get_tx_stats,
+#endif /* KERNEL_VERSION < 2.6.35*/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       .change_interface = esp_op_change_interface,
+#endif
+        .get_tsf = esp_op_get_tsf,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        .set_tsf = esp_op_set_tsf,
+#endif
+        .reset_tsf = esp_op_reset_tsf,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+        .rfkill_poll= esp_op_rfkill_poll,
+#endif
+#ifdef HW_SCAN
+        .hw_scan = esp_op_hw_scan,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+        .remain_on_channel= esp_op_remain_on_channel,
+        .cancel_remain_on_channel=esp_op_cancel_remain_on_channel,
+#endif /* >=2.6.38 */
+#endif
+        .ampdu_action = esp_op_ampdu_action,
+        //.get_survey = esp_op_get_survey,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
+        .sta_add = esp_op_sta_add,
+        .sta_remove = esp_op_sta_remove,
+#endif /* >= 2.6.34 */
+#ifdef CONFIG_NL80211_TESTMODE
+        //CFG80211_TESTMODE_CMD(esp_op_tm_cmd)
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
+       .set_bitrate_mask = esp_op_set_bitrate_mask,
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
+       .flush = esp_op_flush,
+#endif
+};
+
+struct esp_pub * esp_pub_alloc_mac80211(struct device *dev)
+{
+        struct ieee80211_hw *hw;
+        struct esp_pub *epub;
+        int ret = 0;
+
+        hw = ieee80211_alloc_hw(sizeof(struct esp_pub), &esp_mac80211_ops);
+
+        if (hw == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "ieee80211 can't alloc hw!\n");
+                ret = -ENOMEM;
+                return ERR_PTR(ret);
+        }
+
+        epub = hw->priv;
+        memset(epub, 0, sizeof(*epub));
+        epub->hw = hw;
+        SET_IEEE80211_DEV(hw, dev);
+        epub->dev = dev;
+
+        skb_queue_head_init(&epub->txq);
+        skb_queue_head_init(&epub->txdoneq);
+        skb_queue_head_init(&epub->rxq);
+
+       spin_lock_init(&epub->tx_ampdu_lock);
+        spin_lock_init(&epub->tx_lock);
+        mutex_init(&epub->tx_mtx);
+        spin_lock_init(&epub->rx_lock);
+
+        INIT_WORK(&epub->tx_work, esp_tx_work);
+#ifndef RX_SENDUP_SYNC
+        INIT_WORK(&epub->sendup_work, esp_sendup_work);
+#endif //!RX_SENDUP_SYNC
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+        //epub->esp_wkq = create_freezeable_workqueue("esp_wkq"); 
+        epub->esp_wkq = create_singlethread_workqueue("esp_wkq");
+#else
+        //epub->esp_wkq = create_freezable_workqueue("esp_wkq"); 
+        epub->esp_wkq = create_singlethread_workqueue("esp_wkq");
+#endif /* NEW_KERNEL */
+
+        if (epub->esp_wkq == NULL) {
+                ret = -ENOMEM;
+                return ERR_PTR(ret);
+        }
+        epub->scan_permit_valid = false;
+        INIT_DELAYED_WORK(&epub->scan_timeout_work, hw_scan_timeout_report);
+
+        return epub;
+}
+
+
+int esp_pub_dealloc_mac80211(struct esp_pub *epub)
+{
+        set_bit(ESP_WL_FLAG_RFKILL, &epub->wl.flags);
+
+        destroy_workqueue(epub->esp_wkq);
+        mutex_destroy(&epub->tx_mtx);
+
+#ifdef ESP_NO_MAC80211
+        free_netdev(epub->net_dev);
+        wiphy_free(epub->wdev->wiphy);
+        kfree(epub->wdev);
+#else
+        if (epub->hw) {
+                ieee80211_free_hw(epub->hw);
+        }
+#endif
+
+        return 0;
+}
+
+#if 0
+static int esp_reg_notifier(struct wiphy *wiphy,
+                            struct regulatory_request *request)
+{
+        struct ieee80211_supported_band *sband;
+        struct ieee80211_channel *ch;
+        int i;
+
+        ESP_IEEE80211_DBG(ESP_DBG_TRACE, "%s enter %d\n", __func__, request->initiator
+                         );
+
+        //TBD
+}
+#endif
+
+/* 2G band channels */
+static struct ieee80211_channel esp_channels_2ghz[] = {
+        { .hw_value = 1, .center_freq = 2412, .max_power = 25 },
+        { .hw_value = 2, .center_freq = 2417, .max_power = 25 },
+        { .hw_value = 3, .center_freq = 2422, .max_power = 25 },
+        { .hw_value = 4, .center_freq = 2427, .max_power = 25 },
+        { .hw_value = 5, .center_freq = 2432, .max_power = 25 },
+        { .hw_value = 6, .center_freq = 2437, .max_power = 25 },
+        { .hw_value = 7, .center_freq = 2442, .max_power = 25 },
+        { .hw_value = 8, .center_freq = 2447, .max_power = 25 },
+        { .hw_value = 9, .center_freq = 2452, .max_power = 25 },
+        { .hw_value = 10, .center_freq = 2457, .max_power = 25 },
+        { .hw_value = 11, .center_freq = 2462, .max_power = 25 },
+        { .hw_value = 12, .center_freq = 2467, .max_power = 25 },
+        { .hw_value = 13, .center_freq = 2472, .max_power = 25 },
+        //{ .hw_value = 14, .center_freq = 2484, .max_power = 25 },
+};
+
+/* 11G rate */
+static struct ieee80211_rate esp_rates_2ghz[] = {
+        {
+                .bitrate = 10,
+                .hw_value = CONF_HW_BIT_RATE_1MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_1MBPS,
+        },
+        {
+                .bitrate = 20,
+                .hw_value = CONF_HW_BIT_RATE_2MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_2MBPS,
+                .flags = IEEE80211_RATE_SHORT_PREAMBLE
+        },
+        {
+                .bitrate = 55,
+                .hw_value = CONF_HW_BIT_RATE_5_5MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS,
+                .flags = IEEE80211_RATE_SHORT_PREAMBLE
+        },
+        {
+                .bitrate = 110,
+                .hw_value = CONF_HW_BIT_RATE_11MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_11MBPS,
+                .flags = IEEE80211_RATE_SHORT_PREAMBLE
+        },
+        {
+                .bitrate = 60,
+                .hw_value = CONF_HW_BIT_RATE_6MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_6MBPS,
+        },
+        {
+                .bitrate = 90,
+                .hw_value = CONF_HW_BIT_RATE_9MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_9MBPS,
+        },
+        {
+                .bitrate = 120,
+                .hw_value = CONF_HW_BIT_RATE_12MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_12MBPS,
+        },
+        {
+                .bitrate = 180,
+                .hw_value = CONF_HW_BIT_RATE_18MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_18MBPS,
+        },
+        {
+                .bitrate = 240,
+                .hw_value = CONF_HW_BIT_RATE_24MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_24MBPS,
+        },
+        {
+                .bitrate = 360,
+                .hw_value = CONF_HW_BIT_RATE_36MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_36MBPS,
+        },
+        {
+                .bitrate = 480,
+                .hw_value = CONF_HW_BIT_RATE_48MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_48MBPS,
+        },
+        {
+                .bitrate = 540,
+                .hw_value = CONF_HW_BIT_RATE_54MBPS,
+                .hw_value_short = CONF_HW_BIT_RATE_54MBPS,
+        },
+};
+
+static void
+esp_pub_init_mac80211(struct esp_pub *epub)
+{
+        struct ieee80211_hw *hw = epub->hw;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+        static const u32 cipher_suites[] = {
+                WLAN_CIPHER_SUITE_WEP40,
+                WLAN_CIPHER_SUITE_WEP104,
+                WLAN_CIPHER_SUITE_TKIP,
+                WLAN_CIPHER_SUITE_CCMP,
+        };
+#endif
+
+        hw->channel_change_time = 420000; /* in us */
+        hw->max_listen_interval = 10;
+
+        hw->flags = IEEE80211_HW_SIGNAL_DBM |
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+                    IEEE80211_HW_HAS_RATE_CONTROL |
+#endif /* >= 2.6.33 */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+                    IEEE80211_HW_SUPPORTS_PS |
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                IEEE80211_HW_AMPDU_AGGREGATION |
+#endif
+                               IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+   //IEEE80211_HW_PS_NULLFUNC_STACK |  
+        //IEEE80211_HW_CONNECTION_MONITOR |
+        //IEEE80211_HW_BEACON_FILTER |
+        //IEEE80211_HW_AMPDU_AGGREGATION |
+        //IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+        hw->max_rx_aggregation_subframes = 0x40;
+        hw->max_tx_aggregation_subframes = 0x40;
+#endif /* >= 2.6.39 */
+        
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+        hw->wiphy->cipher_suites = cipher_suites;
+        hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+        hw->wiphy->max_scan_ie_len = epub->sip->tx_blksz - sizeof(struct sip_hdr) - sizeof(struct sip_cmd_scan);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+        /* ONLY station for now, support P2P soon... */
+        hw->wiphy->interface_modes = 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+            BIT(NL80211_IFTYPE_P2P_GO) |
+                   BIT(NL80211_IFTYPE_P2P_CLIENT) |
+#endif
+            BIT(NL80211_IFTYPE_STATION) |
+                   BIT(NL80211_IFTYPE_AP);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        hw->wiphy->max_scan_ssids = 2;
+        //hw->wiphy->max_sched_scan_ssids = 16;
+        //hw->wiphy->max_match_sets = 16;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+               hw->wiphy->max_remain_on_channel_duration = 5000;
+#endif
+
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].channels = esp_channels_2ghz;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].bitrates = esp_rates_2ghz;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].n_channels = ARRAY_SIZE(esp_channels_2ghz);
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].n_bitrates = ARRAY_SIZE(esp_rates_2ghz);
+        /*add to support 11n*/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.ht_supported = true;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.cap = 0x116C;//IEEE80211_HT_CAP_RX_STBC; //IEEE80211_HT_CAP_SGI_20;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+#else
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.ampdu_factor = 1;//IEEE80211_HT_MAX_AMPDU_16K;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.ampdu_density = 0;//IEEE80211_HT_MPDU_DENSITY_NONE;
+#endif
+        memset(&epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.mcs, 0,
+               sizeof(epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.mcs));
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.mcs.rx_mask[0] = 0xff;
+        //epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.mcs.rx_highest = 7;
+        //epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+#else
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.ht_supported = true;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.cap = 0x116C;//IEEE80211_HT_CAP_RX_STBC; //IEEE80211_HT_CAP_SGI_20;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.ampdu_factor = 1;//IEEE80211_HT_MAX_AMPDU_16K;
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.ampdu_density = 0;//IEEE80211_HT_MPDU_DENSITY_NONE;
+        memset(&epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.supp_mcs_set, 0,
+               sizeof(epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.supp_mcs_set));
+        epub->wl.sbands[IEEE80211_BAND_2GHZ].ht_info.supp_mcs_set[0] = 0xff;
+#endif
+
+
+        /* BAND_5GHZ TBD */
+
+        hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                &epub->wl.sbands[IEEE80211_BAND_2GHZ];
+        /* BAND_5GHZ TBD */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+        /*no fragment*/
+        hw->wiphy->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+#endif
+
+        /* handle AC queue in f/w */
+        hw->queues = 4;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
+        hw->max_rates = 4;
+#else
+        hw->max_altrates = 4;
+#endif
+#endif
+        //hw->wiphy->reg_notifier = esp_reg_notify;
+
+        hw->vif_data_size = sizeof(struct esp_vif);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+        hw->sta_data_size = sizeof(struct esp_node);
+#endif
+
+        //hw->max_rx_aggregation_subframes = 8;
+}
+
+int
+esp_register_mac80211(struct esp_pub *epub)
+{
+        int ret = 0;
+#ifdef P2P_CONCURRENT
+       u8 *paddr;
+#endif
+
+        esp_pub_init_mac80211(epub);
+
+#ifdef P2P_CONCURRENT
+       epub->hw->wiphy->addresses = (struct mac_address *)esp_mac_addr;
+       memcpy(&epub->hw->wiphy->addresses[0], epub->mac_addr, ETH_ALEN);
+       memcpy(&epub->hw->wiphy->addresses[1], epub->mac_addr, ETH_ALEN);
+       paddr = (u8 *)&epub->hw->wiphy->addresses[1];
+       (*paddr) |= 0x02;
+       epub->hw->wiphy->n_addresses = 2;
+#else
+
+        SET_IEEE80211_PERM_ADDR(epub->hw, epub->mac_addr);
+#endif
+
+        ret = ieee80211_register_hw(epub->hw);
+
+        if (ret < 0) {
+                ESP_IEEE80211_DBG(ESP_DBG_ERROR, "unable to register mac80211 hw: %d\n", ret);
+                return ret;
+        } else {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+#ifdef MAC80211_NO_CHANGE
+               rtnl_lock();
+               if (epub->hw->wiphy->interface_modes &
+                (BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT))) {
+                ret = ieee80211_if_add(hw_to_local(epub->hw), "p2p%d", NULL,
+                                          NL80211_IFTYPE_STATION, NULL);
+                if (ret)
+                        wiphy_warn(epub->hw->wiphy,
+                                   "Failed to add default virtual iface\n");
+               }
+
+               rtnl_unlock();
+#endif
+#endif
+       }
+
+        set_bit(ESP_WL_FLAG_HW_REGISTERED, &epub->wl.flags);
+
+        return ret;
+}
+
+static u8 getaddr_index(u8 * addr, struct esp_pub *epub)
+{
+#ifdef P2P_CONCURRENT
+       int i;
+       for(i = 0; i < ESP_PUB_MAX_VIF; i++)
+               if(memcmp(addr, (u8 *)&epub->hw->wiphy->addresses[i], ETH_ALEN) == 0)
+                       return i;
+       return ESP_PUB_MAX_VIF;
+#else
+       return 0;
+#endif
+}
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_main.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_main.c
new file mode 100755 (executable)
index 0000000..5d0629f
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2010 - 2012 Espressif System.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <linux/time.h>
+#include <linux/moduleparam.h>
+
+#include "esp_pub.h"
+#include "esp_sip.h"
+#include "esp_sif.h"
+#include "esp_debug.h"
+#ifdef ANDROID
+#include "esp_android.h"
+#endif /* ANDROID */
+#include "esp_wl.h"
+#include "slc_host_register.h"
+#include "esp_android.h"
+
+struct completion *gl_bootup_cplx = NULL;
+
+#ifndef FPGA_DEBUG
+static int esp_download_fw(struct esp_pub * epub);
+#endif /* !FGPA_DEBUG */
+
+static bool modparam_no_txampdu = false;
+static bool modparam_no_rxampdu = false;
+module_param_named(no_txampdu, modparam_no_txampdu, bool, 0444);
+MODULE_PARM_DESC(no_txampdu, "Disable tx ampdu.");
+module_param_named(no_rxampdu, modparam_no_rxampdu, bool, 0444);
+MODULE_PARM_DESC(no_rxampdu, "Disable rx ampdu.");
+
+static char *modparam_eagle_path = "";
+module_param_named(eagle_path, modparam_eagle_path, charp, 0444);
+MODULE_PARM_DESC(eagle_path, "eagle path");
+
+bool mod_support_no_txampdu()
+{
+        return modparam_no_txampdu;
+}
+
+bool mod_support_no_rxampdu()
+{
+        return modparam_no_rxampdu;
+}
+
+void mod_support_no_txampdu_set(bool value)
+{
+       modparam_no_txampdu = value;
+}
+
+char *mod_eagle_path_get(void)
+{
+       if (modparam_eagle_path[0] == '\0')
+               return NULL;
+
+       return modparam_eagle_path;
+}
+
+int esp_pub_init_all(struct esp_pub *epub)
+{
+        int ret = 0;
+        
+       /* completion for bootup event poll*/
+       DECLARE_COMPLETION_ONSTACK(complete);
+       atomic_set(&epub->ps.state, ESP_PM_OFF);
+       if(epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               epub->sip = sip_attach(epub);
+
+               esp_dump_var("esp_msg_level", NULL, &esp_msg_level, ESP_U32);
+
+#if defined(ANDROID) && defined (ESP_ANDROID_LOGGER)
+               esp_dump_var("log_off", NULL, &log_off, ESP_U32);
+#endif /* ESP_ANDROID_LOGGER */
+
+               ret = sip_prepare_boot(epub->sip);
+               if (ret)
+                       return ret;
+       } else {
+               atomic_set(&epub->sip->state, SIP_PREPARE_BOOT);
+               atomic_set(&epub->sip->tx_credits, 0);
+       }
+
+#ifndef FPGA_DEBUG
+        ret = esp_download_fw(epub);
+
+        if (ret) {
+                esp_dbg(ESP_DBG_ERROR, "download firmware failed\n");
+                return ret;
+        }
+
+        esp_dbg(ESP_DBG_TRACE, "download firmware OK \n");
+#else
+#ifndef SDIO_TEST
+        sip_send_bootup(epub->sip);
+#endif /* !SDIO_TEST */
+
+#endif /* FPGA_DEBUG */
+
+       gl_bootup_cplx = &complete;
+
+       sif_enable_irq(epub);
+       
+       if(epub->sdio_state == ESP_SDIO_STATE_SECOND_INIT){
+               sip_poll_bootup_event(epub->sip);
+       } else {
+               sip_poll_resetting_event(epub->sip);
+       }
+
+       gl_bootup_cplx = NULL;
+
+        return ret;
+}
+
+#if 0
+void esp_ps_config(struct esp_pub *epub, struct esp_ps *ps, bool on)
+{
+        unsigned long time = jiffies - ps->last_config_time;
+        u32 time_msec = jiffies_to_msecs(time);
+
+        ps->last_config_time = jiffies;
+
+        if (on && (atomic_read(&ps->state) == ESP_PM_TURNING_ON || atomic_read(&ps->state) == ESP_PM_ON)) {
+                esp_dbg(ESP_DBG_PS, "%s same state\n", __func__);
+                return;
+        }
+
+       ps->nulldata_pm_on = false;
+
+        esp_dbg(ESP_DBG_PS, "%s PS %s, dtim %u maxslp %u period %u\n", __func__, on?"ON":"OFF", ps->dtim_period, ps->max_sleep_period, time_msec);
+
+        //NB: turn on ps may need additional check, make sure don't hurt iperf downlink since pkt may be sparse during rx
+
+        if (on) {
+                esp_dbg(ESP_DBG_PS, "%s ps state %d => turning ON\n", __func__, atomic_read(&ps->state));
+                atomic_set(&ps->state, ESP_PM_TURNING_ON);
+        } else {
+                esp_dbg(ESP_DBG_PS, "%s ps state %d => turning OFF\n", __func__, atomic_read(&ps->state));
+                atomic_set(&ps->state, ESP_PM_TURNING_OFF);
+        }
+
+        sip_send_ps_config(epub, ps);
+}
+#endif
+
+void
+esp_dsr(struct esp_pub *epub)
+{
+        sip_rx(epub);
+}
+
+
+struct esp_fw_hdr {
+        u8 magic;
+        u8 blocks;
+        u8 pad[2];
+        u32 entry_addr;
+} __packed;
+
+struct esp_fw_blk_hdr {
+        u32 load_addr;
+        u32 data_len;
+} __packed;
+
+#define ESP_FW_NAME1 "eagle_fw1.bin"
+#define ESP_FW_NAME2 "eagle_fw2.bin"
+
+#ifndef FPGA_DEBUG
+static int esp_download_fw(struct esp_pub * epub)
+{
+#ifndef HAS_FW
+        const struct firmware *fw_entry;
+#endif /* !HAS_FW */
+        u8 * fw_buf = NULL;
+        u32 offset = 0;
+        int ret = 0;
+        u8 blocks;
+        struct esp_fw_hdr *fhdr;
+        struct esp_fw_blk_hdr *bhdr=NULL;
+        struct sip_cmd_bootup bootcmd;
+
+#ifndef HAS_FW
+
+char * esp_fw_name = epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT ? ESP_FW_NAME1 : ESP_FW_NAME2;
+
+#ifdef ANDROID
+        ret = android_request_firmware(&fw_entry, esp_fw_name, epub->dev);
+#else
+        ret = request_firmware(&fw_entry, esp_fw_name, epub->dev);
+#endif //ANDROID
+
+        if (ret)
+                return ret;
+
+        fw_buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+
+#ifdef ANDROID
+        android_release_firmware(fw_entry);
+#else
+        release_firmware(fw_entry);
+#endif //ANDROID
+
+        if (fw_buf == NULL) {
+                return -ENOMEM;
+        }
+#else
+
+#include "eagle_fw1.h"
+#include "eagle_fw2.h"
+        fw_buf = epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT ? &eagle_fw1[0] : &eagle_fw2[0];
+
+#endif /* HAS_FW */
+
+        fhdr = (struct esp_fw_hdr *)fw_buf;
+
+        if (fhdr->magic != 0xE9) {
+                esp_dbg(ESP_DBG_ERROR, "%s wrong magic! \n", __func__);
+                goto _err;
+        }
+
+        blocks = fhdr->blocks;
+        offset += sizeof(struct esp_fw_hdr);
+
+        while (blocks) {
+
+                bhdr = (struct esp_fw_blk_hdr *)(&fw_buf[offset]);
+                offset += sizeof(struct esp_fw_blk_hdr);
+
+                ret = sip_write_memory(epub->sip, bhdr->load_addr, &fw_buf[offset], bhdr->data_len);
+
+                if (ret) {
+                        esp_dbg(ESP_DBG_ERROR, "%s Failed to write fw, err: %d\n", __func__, ret);
+                        goto _err;
+                }
+
+                blocks--;
+                offset += bhdr->data_len;
+        }
+
+        /* TODO: last byte should be the checksum and skip checksum for now */
+
+        bootcmd.boot_addr = fhdr->entry_addr;
+        ret = sip_send_cmd(epub->sip, SIP_CMD_BOOTUP, sizeof(struct sip_cmd_bootup), &bootcmd);
+
+        if (ret)
+                goto _err;
+
+_err:
+#ifndef HAS_FW
+        kfree(fw_buf);
+#endif /* !HAS_FW */
+
+        return ret;
+
+}
+#endif /* !FPGA_DEBUG */
+
+
+
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_os.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_os.h
new file mode 100755 (executable)
index 0000000..4128725
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *  Copyright (c) 2012 Espressif System
+ */
+
+#ifndef _ESP_OS_H_
+#define _ESP_OS_H_
+
+#ifndef __packed
+#define __packed __attribute__ ((packed))
+#endif /* __packed */
+
+#include "net/mac80211.h"
+
+#endif /*__ESP_OS_H_*/
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_path.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_path.h
new file mode 100755 (executable)
index 0000000..514f79c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ESP_PATH_H_
+#define _ESP_PATH_H_
+#define FWPATH "/system/lib/modules"
+//module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
+
+#endif /* _ESP_PATH_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_pm.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_pm.c
new file mode 100755 (executable)
index 0000000..5b68fde
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 -2013 Espressif System.
+ *
+ */
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include "esp_pub.h"
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+
+static void esp_early_suspend(struct early_suspend *h)
+{
+        printk("%s\n", __func__);
+}
+
+static void esp_late_resume(struct early_suspend*h)
+{
+        printk("%s\n", __func__);
+}
+
+static struct early_suspend esp_early_suspend_ctrl =  {
+        .suspend = esp_early_suspend,
+        .resume = esp_late_resume,
+        .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20,
+};
+#endif /* EARLYSUSPEND */
+
+void esp_register_early_suspend(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+        register_early_suspend(&esp_early_suspend_ctrl);
+#endif
+}
+
+void esp_unregister_early_suspend(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+        unregister_early_suspend(&esp_early_suspend_ctrl);
+#endif  
+}
+
+#ifdef CONFIG_HAS_WAKELOCK
+static struct wake_lock esp_wake_lock_;
+#endif /* WAKELOCK */
+
+void esp_wakelock_init(void)
+{
+#ifdef CONFIG_HAS_WAKELOCK
+        wake_lock_init(&esp_wake_lock_, WAKE_LOCK_SUSPEND, "eagle");
+#endif
+}
+
+void esp_wakelock_destroy(void)
+{
+#ifdef CONFIG_HAS_WAKELOCK
+        wake_lock_destroy(&esp_wake_lock_);
+#endif
+}
+
+void esp_wake_lock(void)
+{
+#ifdef CONFIG_HAS_WAKELOCK
+        wake_lock(&esp_wake_lock_);
+#endif
+}
+
+void esp_wake_unlock(void)
+{
+#ifdef CONFIG_HAS_WAKELOCK
+        wake_unlock(&esp_wake_lock_);
+#endif
+}
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_pub.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_pub.h
new file mode 100755 (executable)
index 0000000..74853f1
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2011-2012 Espressif System.
+ *
+ *   wlan device header file
+ */
+
+#ifndef _ESP_PUB_H_
+#define _ESP_PUB_H_
+
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include <linux/version.h>
+#include "sip2_common.h"
+
+// to support kernel < 2.6.28 there's no ieee80211_sta
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+#include <net/wireless.h>
+#endif
+
+enum esp_sdio_state{
+       ESP_SDIO_STATE_FIRST_INIT,
+       ESP_SDIO_STATE_FIRST_NORMAL_EXIT,
+       ESP_SDIO_STATE_FIRST_ERROR_EXIT,
+       ESP_SDIO_STATE_SECOND_INIT,
+       ESP_SDIO_STATE_SECOND_ERROR_EXIT,
+};
+
+enum esp_tid_state {
+        ESP_TID_STATE_INIT,
+        ESP_TID_STATE_TRIGGER,
+        ESP_TID_STATE_PROGRESS,
+        ESP_TID_STATE_OPERATIONAL,
+        ESP_TID_STATE_WAIT_STOP,
+        ESP_TID_STATE_STOP,
+};
+
+struct esp_tx_tid {
+        u8 state;
+       u8 cnt;
+        u16 ssn;
+};
+
+#define WME_NUM_TID 16
+struct esp_node {
+        struct esp_tx_tid tid[WME_NUM_TID];
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+        struct ieee80211_sta *sta;
+#else
+       u8 addr[ETH_ALEN];
+    u16 aid;
+    u64 supp_rates[IEEE80211_NUM_BANDS];
+    struct ieee80211_ht_info ht_info;
+#endif
+       u8 ifidx;
+       u8 index;
+};
+
+#define WME_AC_BE 2
+#define WME_AC_BK 3
+#define WME_AC_VI 1
+#define WME_AC_VO 0
+
+struct llc_snap_hdr {
+        u8 dsap;
+        u8 ssap;
+        u8 cntl;
+        u8 org_code[3];
+        __be16 eth_type;
+} __packed;
+
+struct esp_vif {
+       struct esp_pub *epub;
+       u8 index;
+       u32 beacon_interval;
+       bool ap_up;
+       struct timer_list beacon_timer;
+};
+
+/* WLAN related, mostly... */
+/*struct hw_scan_timeout {
+        struct delayed_work w;
+        struct ieee80211_hw *hw;
+};*/
+
+typedef struct esp_wl {
+        u8 ssid[IEEE80211_MAX_SSID_LEN];
+        u8 dot11_auth_mode;
+        u8 auth_mode;
+        u8 prwise_crypto;
+        u8 prwise_crypto_len;
+        u8 grp_crypto;
+        u8 grp_crpto_len;
+        u8 def_txkey_index;
+        u32 used_key_entries;   //each bit represent an entry, 0: avail 1: used
+
+        u8 bssid[ETH_ALEN];
+        u8 req_bssid[ETH_ALEN];
+        u16 ch_hint;
+        u16 bss_ch;
+        u16 listen_intvl_b;
+        u16 listen_intvl_t;
+
+        //struct hw_scan_timeout *hsd;
+        struct cfg80211_scan_request *scan_req;
+       atomic_t ptk_cnt;
+       atomic_t gtk_cnt;
+       atomic_t tkip_key_set;
+        //struct ieee80211_key_conf *ptk;
+        //struct ieee80211_key_conf *gtk[4];
+
+        struct list_head amsdu_rx_buffer_queue;
+        struct timer_list disconnect_timer;
+
+        /* so far only 2G band */
+        struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+
+        unsigned long flags;
+        atomic_t off;
+} esp_wl_t;
+
+typedef struct esp_hw_idx_map {
+       u8 mac[ETH_ALEN];
+       u8 flag;
+} esp_hw_idx_map_t;
+
+#define ESP_TXQ_MAX_LEN 64 /* TBD: better #? */
+#define ESP_PUB_F_TXPAUSE  0x1
+
+#define ESP_WL_FLAG_RFKILL                     BIT(0)
+#define ESP_WL_FLAG_HW_REGISTERED              BIT(1)
+#define ESP_WL_FLAG_CONNECT                            BIT(2)
+#define ESP_WL_FLAG_STOP_TXQ                   BIT(3)
+
+#define ESP_PUB_MAX_VIF                2
+#define ESP_PUB_MAX_STA                4 //for one interface
+
+enum {
+        ESP_PM_OFF = 0,
+        ESP_PM_TURNING_ON,
+        ESP_PM_ON,
+        ESP_PM_TURNING_OFF,  /* Do NOT change the order */
+};
+
+struct esp_ps {
+       u32 dtim_period;
+       u32 max_sleep_period;
+       unsigned long last_config_time;
+        atomic_t state;
+        bool nulldata_pm_on;
+};
+
+struct esp_pub {
+        struct device *dev;
+#ifdef ESP_NO_MAC80211
+        struct net_device *net_dev;
+        struct wireless_dev *wdev;
+        struct net_device_stats *net_stats;
+#else
+        struct ieee80211_hw *hw;
+        struct ieee80211_vif *vif;
+        u8 vif_slot;
+#endif /* ESP_MAC80211 */
+
+        void *sif; /* serial interface control block, e.g. sdio */
+        enum esp_sdio_state sdio_state;
+        struct esp_sip *sip;
+        struct esp_wl wl;
+        struct esp_hw_idx_map hi_map[19];
+        struct esp_hw_idx_map low_map[ESP_PUB_MAX_VIF][2];
+        u32 flags; //flags to represent rfkill switch,start
+        u8 roc_flags;   //0: not in remain on channel state, 1: in roc state
+
+        struct work_struct tx_work; /* attach to ieee80211 workqueue */
+        /* latest mac80211 has multiple tx queue, but we stick with single queue now */
+        spinlock_t rx_lock;
+        spinlock_t tx_ampdu_lock;
+       spinlock_t tx_lock;
+        struct mutex tx_mtx;
+        struct sk_buff_head txq;
+        atomic_t txq_stopped;
+
+        struct work_struct sendup_work; /* attach to ieee80211 workqueue */
+        struct sk_buff_head txdoneq;
+        struct sk_buff_head rxq;
+
+        struct workqueue_struct *esp_wkq;
+
+        u8 bssid[ETH_ALEN];
+        u8 mac_addr[ETH_ALEN];
+
+        u32 rx_filter;
+        unsigned long scan_permit;
+        bool scan_permit_valid;
+        struct delayed_work scan_timeout_work;
+       u8 enodes_map;
+       u8 enodes_maps[ESP_PUB_MAX_VIF];
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+        struct esp_node nodes[ESP_PUB_MAX_STA + 1];
+#endif
+        struct esp_node * enodes[ESP_PUB_MAX_STA + 1];
+       struct esp_ps ps;
+};
+
+typedef struct esp_pub esp_pub_t;
+
+struct esp_pub *esp_pub_alloc_mac80211(struct device *dev);
+int esp_pub_dealloc_mac80211(struct esp_pub  *epub);
+int esp_register_mac80211(struct esp_pub *epub);
+
+int esp_pub_init_all(struct esp_pub *epub);
+
+char *mod_eagle_path_get(void);
+
+void esp_dsr(struct esp_pub *epub);
+void hw_scan_done(struct esp_pub *epub, bool aborted);
+void esp_rocdone_process(struct ieee80211_hw *hw, struct sip_evt_roc *report);
+
+void esp_ps_config(struct esp_pub *epub, struct esp_ps *ps, bool on);
+
+
+void esp_register_early_suspend(void);
+void esp_unregister_early_suspend(void);
+void esp_wakelock_init(void);
+void esp_wakelock_destroy(void);
+void esp_wake_lock(void);
+void esp_wake_unlock(void);
+struct esp_node * esp_get_node_by_addr(struct esp_pub * epub, const u8 *addr);
+
+#ifdef TEST_MODE
+int test_init_netlink(struct esp_sip *sip);
+void test_exit_netlink(void);
+void esp_test_cmd_event(u32 cmd_type, char *reply_info);
+#endif
+#endif /* _ESP_PUB_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_sif.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_sif.h
new file mode 100755 (executable)
index 0000000..940cecf
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2011 - 2013 Espressif System.
+ *
+ *   Serial I/F wrapper layer for eagle WLAN device,
+ *    abstraction of buses like SDIO/SIP, and provides
+ *    flow control for tx/rx layer
+ *
+ */
+
+#ifndef _ESP_SIF_H_
+#define _ESP_SIF_H_
+
+#include "esp_pub.h"
+#include <linux/mmc/host.h>
+#include <linux/spi/spi.h>
+
+/*
+ *  H/W SLC module definitions
+ */
+
+#define SIF_SLC_BLOCK_SIZE                512
+
+#define SIF_DMA_BUFFER_SIZE (64 * 1024)
+
+/* to make the last byte located at :xffff, increase 1 byte here */
+//#define SIF_SLC_WINDOW_END_ADDR  (0xffff + 1)
+//#define SIF_SLC_WINDOW_END_ADDR  (0x1ffff + 1 - 0x800)
+
+#define SIF_MAX_SCATTER_REQUESTS             4
+#define SIF_MAX_SCATTER_ENTRIES_PER_REQ      16
+#define SIF_MAX_SCATTER_REQ_TRANSFER_SIZE    (32 * 1024)
+
+
+/* SIF bus request */
+#define SIF_REQ_MAX_NUM                64
+
+/* S/W struct mapping to slc registers */
+typedef struct slc_host_regs {
+        /* do NOT read token_rdata
+         *
+                u32 pf_data;
+                u32 token_rdata;
+        */
+        u32 intr_raw;
+        u32 state_w0;
+        u32 state_w1;
+        u32 config_w0;
+        u32 config_w1;
+        u32 intr_status;
+        u32 config_w2;
+        u32 config_w3;
+        u32 config_w4;
+        u32 token_wdata;
+        u32 intr_clear;
+        u32 intr_enable;
+} sif_slc_reg_t;
+
+
+struct sif_req {
+        struct list_head list;
+
+        u32 address;
+
+        u8 *buffer;
+        u32 length;
+        u32 flag;
+        int status;
+        void * context;
+};
+
+enum io_sync_type {    
+       ESP_SIF_NOSYNC = 0,
+       ESP_SIF_SYNC, 
+};
+
+#ifdef ESP_USE_SDIO
+typedef struct esp_sdio_ctrl {
+        struct sdio_func *func;
+#else
+typedef struct esp_spi_ctrl {
+        struct spi_device *spi;
+#endif
+        struct esp_pub *epub;
+
+
+        struct list_head free_req;
+        struct sif_req reqs[SIF_REQ_MAX_NUM];
+
+        u8 *dma_buffer;
+
+        spinlock_t scat_lock;
+        struct list_head scat_req;
+
+        bool off;
+        atomic_t irq_handling;
+#ifdef ESP_USE_SDIO
+        const struct sdio_device_id *id;
+#else
+        const struct spi_device_id *id;
+#endif
+        u32 slc_blk_sz;
+        u32 target_id;
+        u32 slc_window_end_addr;
+
+        struct slc_host_regs slc_regs;
+        atomic_t       irq_installed;
+
+#ifdef ESP_USE_SDIO
+} esp_sdio_ctrl_t;
+#else
+} esp_spi_ctrl_t;
+#endif
+
+#define SIF_TO_DEVICE                    0x1
+#define SIF_FROM_DEVICE                    0x2
+
+#define SIF_SYNC             0x00000010
+#define SIF_ASYNC           0x00000020
+
+#define SIF_BYTE_BASIS              0x00000040
+#define SIF_BLOCK_BASIS             0x00000080
+
+#define SIF_FIXED_ADDR           0x00000100
+#define SIF_INC_ADDR     0x00000200
+
+#ifdef ESP_USE_SDIO
+#define EPUB_CTRL_CHECK(_epub) do{\
+ASSERT((_epub) != NULL);\
+ASSERT((_epub)->sif != NULL);\
+}while(0)
+
+#define EPUB_FUNC_CHECK(_epub) do{\
+ASSERT((_epub) != NULL);\
+ASSERT((_epub)->sif != NULL);\
+ASSERT(((struct esp_sdio_ctrl *)(_epub)->sif)->func != NULL);\
+}while(0)
+
+#define EPUB_TO_CTRL(_epub) (((struct esp_sdio_ctrl *)(_epub)->sif))
+
+#define EPUB_TO_FUNC(_epub) (((struct esp_sdio_ctrl *)(_epub)->sif)->func)
+#endif
+
+
+#ifdef ESP_USE_SPI
+#define EPUB_CTRL_CHECK(_epub) do{\
+ASSERT((_epub) != NULL);\
+ASSERT((_epub)->sif != NULL);\
+}while(0)
+
+#define EPUB_FUNC_CHECK(_epub) do{\
+ASSERT((_epub) != NULL);\
+ASSERT((_epub)->sif != NULL);\
+ASSERT(((struct esp_spi_ctrl *)(_epub)->sif)->spi != NULL);\
+}while(0)
+
+#define EPUB_TO_CTRL(_epub) (((struct esp_spi_ctrl *)(_epub)->sif))
+
+#define EPUB_TO_FUNC(_epub) (((struct esp_spi_ctrl *)(_epub)->sif)->spi)
+#endif
+
+static void inline sif_setup_req(struct sif_req *req, u32 addr, u32 flag, u32 len,
+                                 u8 * buf, void *context)
+{
+        req->address = addr;
+        req->flag = flag;
+        req->length = len;
+        req->buffer = buf;
+        req->context = context;
+}
+
+void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res);
+u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res);
+
+
+void sif_enable_irq(struct esp_pub *epub);
+void sif_disable_irq(struct esp_pub *epub);
+void sif_disable_target_interrupt(struct esp_pub *epub);
+
+u32 sif_get_blksz(struct esp_pub *epub);
+u32 sif_get_target_id(struct esp_pub *epub);
+
+#ifdef ESP_USE_SDIO
+void sif_dsr(struct sdio_func *func);
+int sif_io_raw(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag);
+int sif_io_sync(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag);
+int sif_io_async(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag, void * context);
+int sif_lldesc_read_sync(struct esp_pub *epub, u8 *buf, u32 len);
+int sif_lldesc_write_sync(struct esp_pub *epub, u8 *buf, u32 len);
+int sif_lldesc_read_raw(struct esp_pub *epub, u8 *buf, u32 len, bool noround);
+int sif_lldesc_write_raw(struct esp_pub *epub, u8 *buf, u32 len);
+void sif_platform_check_r1_ready(struct esp_pub *epub);
+#endif 
+
+#ifdef ESP_USE_SPI
+enum if_check_idle {
+       NOT_CHECK_IDLE = 0,
+       CHECK_IDLE,
+};
+
+#ifdef REGISTER_SPI_BOARD_INFO
+void sif_platform_register_board_info(void);
+#endif
+
+void sif_dsr(struct spi_device *spi);
+int sif_spi_read_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle);
+int sif_spi_epub_read_mix_sync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int check_idle);
+int sif_spi_epub_read_mix_nosync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int check_idle);
+int sif_spi_read_sync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle);
+int sif_spi_read_nosync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle, bool noround);
+
+int sif_spi_write_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle);
+int sif_spi_epub_write_mix_sync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int check_idle);
+int sif_spi_epub_write_mix_nosync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int check_idle);
+int sif_spi_write_sync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle);
+int sif_spi_write_nosync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle);
+
+int sif_platform_get_irq_no(void);
+int sif_platform_is_irq_occur(void);
+void sif_platform_irq_clear(void);
+void sif_platform_irq_mask(int enable_mask);
+int sif_platform_irq_init(void);
+void sif_platform_irq_deinit(void);
+#endif
+
+int esp_common_read(struct esp_pub *epub, u8 *buf, u32 len, int sync, bool noround);
+int esp_common_write(struct esp_pub *epub, u8 *buf, u32 len, int sync);
+int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync);
+int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync);
+
+int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, int sync);
+int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, int sync);
+
+struct slc_host_regs * sif_get_regs(struct esp_pub *epub);
+
+void sif_lock_bus(struct esp_pub *epub);
+void sif_unlock_bus(struct esp_pub *epub);
+
+void sif_platform_target_poweroff(void);
+void sif_platform_target_poweron(void);
+void sif_platform_target_speed(int high_speed);
+
+void sif_platform_reset_target(void);
+void sif_platform_rescan_card(unsigned insert);
+
+int sif_interrupt_target(struct esp_pub *epub, u8 index);
+#ifdef USE_EXT_GPIO
+int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode);
+int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value);
+int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 *value);
+int sif_get_gpio_input(struct esp_pub *epub, u16 *mask, u16 *value);
+#endif
+
+void sif_raw_dummy_read(struct esp_pub *epub);
+void check_target_id(struct esp_pub *epub);
+
+void sif_record_bt_config(int value);
+int sif_get_bt_config(void);
+void sif_record_rst_config(int value);
+int sif_get_rst_config(void);
+void sif_record_retry_config(void);
+int sif_get_retry_config(void);
+void sif_record_wakeup_gpio_config(int value);
+int sif_get_wakeup_gpio_config(void);
+
+#ifdef ESP_ACK_INTERRUPT
+//extern void sif_platform_ack_interrupt(struct mmc_host *mmc);
+extern void sif_platform_ack_interrupt(struct esp_pub *epub);
+#endif //ESP_ACK_INTERRUPT
+
+#define sif_reg_read_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR)
+
+#define sif_reg_write_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR)
+
+#endif /* _ESP_SIF_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_sip.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_sip.c
new file mode 100755 (executable)
index 0000000..35ec99d
--- /dev/null
@@ -0,0 +1,2354 @@
+/*
+ * Copyright (c) 2009 - 2013 Espressif System.
+ */
+
+#include <linux/ieee80211.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/version.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/completion.h> 
+
+#include "esp_pub.h"
+#include "esp_sip.h"
+#include "esp_ctrl.h"
+#include "esp_sif.h"
+#include "esp_debug.h"
+#include "slc_host_register.h"
+#include "esp_wmac.h"
+#include "esp_utils.h"
+#ifdef TEST_MODE
+#include "testmode.h"
+#endif
+
+#ifdef USE_EXT_GPIO
+#include "esp_ext.h"
+#endif /* USE_EXT_GPIO */
+
+extern struct completion *gl_bootup_cplx; 
+static u32 bcn_counter = 0;
+static u32 probe_rsp_counter = 0;
+
+#define TID_TO_AC(_tid) ((_tid)== 0||((_tid)==3)?WME_AC_BE:((_tid)<3)?WME_AC_BK:((_tid)<6)?WME_AC_VI:WME_AC_VO)
+
+#ifdef SIP_DEBUG
+#define esp_sip_dbg esp_dbg
+struct sip_trace {
+        u32 tx_data;
+        u32 tx_cmd;
+        u32 rx_data;
+        u32 rx_evt;
+        u32 rx_tx_status;
+        u32 tx_out_of_credit;
+        u32 tx_one_shot_overflow;
+};
+static struct sip_trace str;
+#define STRACE_TX_DATA_INC() (str.tx_data++)
+#define STRACE_TX_CMD_INC()  (str.tx_cmd++)
+#define STRACE_RX_DATA_INC() (str.rx_data++)
+#define STRACE_RX_EVENT_INC() (str.rx_evt++)
+#define STRACE_RX_TXSTATUS_INC() (str.rx_tx_status++)
+#define STRACE_TX_OUT_OF_CREDIT_INC() (str.tx_out_of_credit++)
+#define STRACE_TX_ONE_SHOT_INC() (str.tx_one_shot_overflow++)
+
+#if 0
+static void sip_show_trace(struct esp_sip *sip);
+#endif //0000
+
+#define STRACE_SHOW(sip)  sip_show_trace(sip)
+#else
+#define esp_sip_dbg(...)
+#define STRACE_TX_DATA_INC()
+#define STRACE_TX_CMD_INC()
+#define STRACE_RX_DATA_INC()
+#define STRACE_RX_EVENT_INC()
+#define STRACE_RX_TXSTATUS_INC()
+#define STRACE_TX_OUT_OF_CREDIT_INC()
+#define STRACE_TX_ONE_SHOT_INC()
+#define STRACE_SHOW(sip)
+#endif /* SIP_DEBUG */
+
+#define SIP_STOP_QUEUE_THRESHOLD 48
+#define SIP_RESUME_QUEUE_THRESHOLD  12
+#ifndef FAST_TX_STATUS
+#define SIP_PENDING_STOP_TX_THRESHOLD 6
+#define SIP_PENDING_RESUME_TX_THRESHOLD 6
+#endif /* !FAST_TX_STATUS */
+
+#define SIP_MIN_DATA_PKT_LEN    (sizeof(struct esp_mac_rx_ctrl) + 24) //24 is min 80211hdr
+#define TARGET_RX_SIZE 524
+
+static struct sip_pkt *sip_get_ctrl_buf(struct esp_sip *sip, SIP_BUF_TYPE bftype);
+
+static void sip_reclaim_ctrl_buf(struct esp_sip *sip, struct sip_pkt *pkt, SIP_BUF_TYPE bftype);
+
+static void sip_free_init_ctrl_buf(struct esp_sip *sip);
+
+static void sip_dec_credit(struct esp_sip *sip);
+
+
+static int sip_pack_pkt(struct esp_sip *sip, struct sk_buff *skb, int *pm_state);
+
+static struct esp_mac_rx_ctrl *sip_parse_normal_mac_ctrl(struct sk_buff *skb, int * pkt_len_enc, int *buf_len, int *pulled_len);
+
+static struct sk_buff * sip_parse_data_rx_info(struct esp_sip *sip, struct sk_buff *skb, int pkt_len_enc, int buf_len, struct esp_mac_rx_ctrl *mac_ctrl, int *pulled_len);
+
+#ifndef RX_SYNC
+static inline void sip_rx_pkt_enqueue(struct esp_sip *sip, struct sk_buff *skb);
+
+static inline struct sk_buff * sip_rx_pkt_dequeue(struct esp_sip *sip);
+#endif /* RX_SYNC */
+#ifndef FAST_TX_STATUS
+static void sip_after_tx_status_update(struct esp_sip *sip);
+#endif /* !FAST_TX_STATUS */
+
+static void sip_after_write_pkts(struct esp_sip *sip);
+
+//static void show_data_seq(u8 *pkt);
+
+static void sip_update_tx_credits(struct esp_sip *sip, u16 recycled_credits);
+
+//static void sip_trigger_txq_process(struct esp_sip *sip);
+
+#ifndef RX_SYNC
+static bool sip_rx_pkt_process(struct esp_sip * sip, struct sk_buff *skb);
+#else
+static void sip_rx_pkt_process_sync(struct esp_sip *sip, struct sk_buff *skb);
+#endif /* RX_SYNC */
+
+#ifdef FAST_TX_STATUS
+static void sip_tx_status_report(struct esp_sip *sip, struct sk_buff *skb, struct ieee80211_tx_info* tx_info, bool success);
+#endif /* FAST_TX_STATUS */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+static void sip_check_skb_alignment(struct sk_buff *skb);
+#endif /* NEW_KERNEL */
+
+#ifdef ESP_RX_COPYBACK_TEST
+/* only for rx test */
+static u8 *copyback_buf;
+static u32 copyback_offset = 0;
+#endif /* ESP_RX_COPYBACK_TEST */
+
+#ifdef FPGA_TXDATA
+int sip_send_tx_data(struct esp_sip *sip);
+#endif/* FPGA_TXDATA */
+
+#ifdef FPGA_LOOPBACK
+int sip_send_loopback_cmd_mblk(struct esp_sip *sip);
+#endif /* FPGA_LOOPBACK */
+
+#ifdef SIP_DEBUG
+#if 0
+static void sip_show_trace(struct esp_sip *sip)
+{
+        esp_sip_dbg(ESP_DBG_TRACE, "\n \t tx_data %u \t tx_cmd %u \t rx_data %u \t rx_evt %u \t rx_tx_status %u \n\n", \
+                    str.tx_data, str.tx_cmd, str.rx_data, str.rx_evt, str.rx_tx_status);
+}
+#endif //0000
+#endif //SIP_DEBUG
+
+#if 0
+static void show_data_seq(u8 *pkt)
+{
+        struct ieee80211_hdr * wh = (struct ieee80211_hdr *)pkt;
+        u16 seq = 0;
+
+        if (ieee80211_is_data(wh->frame_control)) {
+                seq = (le16_to_cpu(wh->seq_ctrl) >> 4);
+                esp_sip_dbg(ESP_DBG_TRACE, " ieee80211 seq %u addr1 %pM\n", seq, wh->addr1);
+        } else if (ieee80211_is_beacon(wh->frame_control) || ieee80211_is_probe_resp(wh->frame_control))
+                esp_sip_dbg(ESP_DBG_TRACE, " ieee80211 probe resp or beacon 0x%04x\n", wh->frame_control);
+        else
+                esp_sip_dbg(ESP_DBG_TRACE, " ieee80211 other mgmt pkt 0x%04x\n", wh->frame_control);
+}
+#endif //0000
+
+//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+static bool check_ac_tid(u8 *pkt, u8 ac, u8 tid)
+{
+        struct ieee80211_hdr * wh = (struct ieee80211_hdr *)pkt;
+#ifdef TID_DEBUG
+        u16 real_tid = 0;
+#endif //TID_DEBUG
+
+        if (ieee80211_is_data_qos(wh->frame_control)) {
+#ifdef TID_DEBUG
+               real_tid = *ieee80211_get_qos_ctl(wh) & IEEE80211_QOS_CTL_TID_MASK;
+
+                esp_sip_dbg(ESP_SHOW, "ac:%u, tid:%u, tid in pkt:%u\n", ac, tid, real_tid);
+                if (tid != real_tid) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "111 ac:%u, tid:%u, tid in pkt:%u\n", ac, tid, real_tid);
+                }
+                if (TID_TO_AC(tid) != ac) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "222 ac:%u, tid:%u, tid in pkt:%u\n", ac, tid, real_tid);
+                }
+
+                //ASSERT(tid == real_tid);
+                //ASSERT(TID_TO_AC(tid) == ac);
+#endif /* TID_DEBUG*/
+        } else if (ieee80211_is_mgmt(wh->frame_control)) {
+#ifdef TID_DEBUG
+                esp_sip_dbg(ESP_SHOW, "ac:%u, tid:%u\n", ac, tid);
+                if (tid != 7 || ac != WME_AC_VO) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "333 ac:%u, tid:%u\n", ac, tid);
+                }
+                //ASSERT(tid == 7);
+                //ASSERT(ac == WME_AC_VO);
+#endif /* TID_DEBUG*/
+        } else {
+                if (ieee80211_is_ctl(wh->frame_control)) {
+#ifdef TID_DEBUG
+                        esp_sip_dbg(ESP_SHOW, "%s is ctrl pkt fc 0x%04x ac:%u, tid:%u, tid in pkt:%u\n", __func__, wh->frame_control, ac, tid, real_tid);
+#endif /* TID_DEBUG*/
+                } else {
+                        if (tid != 0 || ac != WME_AC_BE) {
+                                //show_buf(pkt, 24);
+                                esp_sip_dbg(ESP_DBG_LOG, "444 ac:%u, tid:%u \n", ac, tid);
+                                if (tid == 7 && ac == WME_AC_VO)
+                                        return false;
+                        }
+                        return true; //hack to modify non-qos null data.
+
+                }
+                //ASSERT(tid == 0);
+                //ASSERT(ac = WME_AC_BE);
+        }
+
+        return false;
+}
+//#endif /* NEW_KERNEL || KERNEL_35 */
+
+static void sip_update_tx_credits(struct esp_sip *sip, u16 recycled_credits)
+{
+        esp_sip_dbg(ESP_DBG_TRACE, "%s:before add, credits is %d\n", __func__, atomic_read(&sip->tx_credits));
+        atomic_add(recycled_credits, &sip->tx_credits);
+        esp_sip_dbg(ESP_DBG_TRACE, "%s:after add %d, credits is %d\n", __func__, recycled_credits, atomic_read(&sip->tx_credits));
+}
+
+void sip_trigger_txq_process(struct esp_sip *sip)
+{
+        if (atomic_read(&sip->tx_credits) <= sip->credit_to_reserve)  //no credits, do nothing
+                return;
+
+        if (sip_queue_may_resume(sip)) {
+                /* wakeup upper queue only if we have sufficient credits */
+                esp_sip_dbg(ESP_DBG_TRACE, "%s wakeup ieee80211 txq \n", __func__);
+                atomic_set(&sip->epub->txq_stopped, false);
+                ieee80211_wake_queues(sip->epub->hw);
+        } else if (atomic_read(&sip->epub->txq_stopped) ) {
+                esp_sip_dbg(ESP_DBG_TRACE, "%s can't wake txq, credits: %d \n", __func__, atomic_read(&sip->tx_credits) );
+        }
+
+        if (!skb_queue_empty(&sip->epub->txq)) {
+                /* try to send out pkt already in sip queue once we have credits */
+                esp_sip_dbg(ESP_DBG_TRACE, "%s resume sip txq \n", __func__);
+#if !defined(FPGA_LOOPBACK) && !defined(FPGA_TXDATA) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+                ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work);
+#else
+                queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
+#endif
+        }
+}
+
+static bool sip_ampdu_occupy_buf(struct esp_sip *sip, struct esp_rx_ampdu_len * ampdu_len)
+{
+        return (ampdu_len->substate == 0 || esp_wmac_rxsec_error(ampdu_len->substate) || (sip->dump_rpbm_err && ampdu_len->substate == RX_RPBM_ERR));
+}
+
+#ifdef RX_SYNC
+static void sip_rx_pkt_process_sync(struct esp_sip *sip, struct sk_buff *skb)
+#else
+static bool sip_rx_pkt_process(struct esp_sip * sip, struct sk_buff *skb)
+#endif /* RX_SYNC */
+{
+#define DO_NOT_COPY false
+#define DO_COPY true
+
+       struct sip_hdr * hdr = NULL;
+       struct sk_buff * rskb = NULL;
+       int remains_len = 0;
+       int first_pkt_len = 0;
+       u8 *bufptr = NULL;
+       int ret = 0;
+       bool trigger_rxq = false;
+#ifdef RX_SYNC
+       bool trigger_txq = false;
+#endif/* RX_SYNC */
+
+       if (skb == NULL) {
+               esp_sip_dbg(ESP_DBG_ERROR, "%s NULL SKB!!!!!!!! \n", __func__);
+#ifdef RX_SYNC
+               return;
+#else
+               return trigger_rxq;
+#endif /* RX_SYNC */
+       }
+
+       hdr = (struct sip_hdr *)skb->data;
+       bufptr = skb->data;
+
+
+       esp_sip_dbg(ESP_DBG_TRACE, "%s Hcredits 0x%08x, realCredits %d\n", __func__, hdr->h_credits, hdr->h_credits & SIP_CREDITS_MASK);
+       if (hdr->h_credits & SIP_CREDITS_MASK) {
+               sip_update_tx_credits(sip, hdr->h_credits & SIP_CREDITS_MASK);
+#ifdef RX_SYNC
+               trigger_txq = true;
+#endif/* RX_SYNC */
+       }
+
+       hdr->h_credits &= ~SIP_CREDITS_MASK; /* clean credits in sip_hdr, prevent over-add */
+
+       esp_sip_dbg(ESP_DBG_TRACE, "%s credits %d\n", __func__, hdr->h_credits);
+
+       /*
+        * first pkt's length is stored in  recycled_credits first 20 bits
+        * config w3 [31:12]
+        * repair hdr->len of first pkt
+        */
+       remains_len = hdr->len;
+       first_pkt_len = hdr->h_credits >> 12;
+       hdr->len = first_pkt_len;
+
+       esp_dbg(ESP_DBG_TRACE, "%s first_pkt_len %d, whole pkt len %d \n", __func__, first_pkt_len, remains_len);
+       if (first_pkt_len > remains_len) {
+               printk("first_pkt_len %d, whole pkt len %d\n", first_pkt_len, remains_len);
+               show_buf((u8 *)hdr, first_pkt_len);
+               ASSERT(0);
+       }
+
+       /*
+        * pkts handling, including the first pkt, should alloc new skb for each data pkt.
+        * free the original whole skb after parsing is done.
+        */
+       while (remains_len) {
+               ASSERT(remains_len >= sizeof(struct sip_hdr));
+               hdr = (struct sip_hdr *)bufptr;
+               ASSERT(hdr->len > 0);
+               if((hdr->len & 3) != 0) {
+                       show_buf((u8 *)hdr, 512);
+               }
+               ASSERT((hdr->len & 3) == 0);
+               if (unlikely(hdr->seq != sip->rxseq++)) {
+                       esp_dbg(ESP_DBG_ERROR, "%s seq mismatch! got %u, expect %u\n", __func__, hdr->seq, sip->rxseq-1);
+                       show_buf(bufptr, 32);
+                       ASSERT(0);
+               }
+
+               if (SIP_HDR_IS_CTRL(hdr)) {
+                       STRACE_RX_EVENT_INC();
+                       esp_sip_dbg(ESP_DBG_TRACE, "seq %u \n", hdr->seq);
+
+                       ret = sip_parse_events(sip, bufptr);
+
+                       skb_pull(skb, hdr->len);
+
+               } else if (SIP_HDR_IS_DATA(hdr)) {
+                       struct esp_mac_rx_ctrl * mac_ctrl = NULL;
+                       int pkt_len_enc = 0, buf_len = 0, pulled_len = 0;
+
+                       STRACE_RX_DATA_INC();
+                       esp_sip_dbg(ESP_DBG_TRACE, "seq %u \n", hdr->seq);
+                       mac_ctrl = sip_parse_normal_mac_ctrl(skb, &pkt_len_enc, &buf_len, &pulled_len);
+                       rskb = sip_parse_data_rx_info(sip, skb, pkt_len_enc, buf_len, mac_ctrl, &pulled_len);
+
+                       if(rskb == NULL)
+                               goto _move_on;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+                       sip_check_skb_alignment(rskb);
+#endif /* !NEW_KERNEL */
+                       if (likely(atomic_read(&sip->epub->wl.off) == 0)) {
+#ifndef RX_SENDUP_SYNC
+                               skb_queue_tail(&sip->epub->rxq, rskb);
+                               trigger_rxq = true;
+#else
+#ifdef RX_CHECKSUM_TEST
+                               esp_rx_checksum_test(rskb);
+#endif
+                               local_bh_disable();
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+                               ieee80211_rx(sip->epub->hw, rskb);
+#else
+                //simulate IEEE80211_SKB_RXCB in 2.6.32 
+                ieee80211_rx(sip->epub->hw, rskb ,(struct ieee80211_rx_status *)rskb->cb);
+#endif
+                               local_bh_enable();
+#endif /* RX_SENDUP_SYNC */
+                       } else {
+                               /* still need go thro parsing as skb_pull should invoke */
+                               kfree_skb(rskb);
+                       }
+               } else if (SIP_HDR_IS_AMPDU(hdr)) {
+                       struct esp_mac_rx_ctrl * mac_ctrl = NULL;
+                       struct esp_mac_rx_ctrl new_mac_ctrl;
+                       struct esp_rx_ampdu_len *ampdu_len;
+                       int pkt_num;
+                       int pulled_len = 0;
+                       static int pkt_dropped = 0;
+                       static int pkt_total = 0;
+                       bool have_rxabort = false;
+                       bool have_goodpkt = false;
+                       static u8 frame_head[16];
+                       static u8 frame_buf_ttl = 0;
+
+                       ampdu_len = (struct esp_rx_ampdu_len *)(skb->data + hdr->len/sip->rx_blksz * sip->rx_blksz);
+                       esp_sip_dbg(ESP_DBG_TRACE, "%s rx ampdu total len %u\n", __func__, hdr->len);
+                       if(skb->data != (u8 *)hdr) {
+                               printk("%p %p\n", skb->data, hdr);
+                               show_buf(skb->data, 512);
+                               show_buf((u8 *)hdr, 512);
+                       }
+                       ASSERT(skb->data == (u8 *)hdr);
+                       mac_ctrl = sip_parse_normal_mac_ctrl(skb, NULL, NULL, &pulled_len);
+                       memcpy(&new_mac_ctrl, mac_ctrl, sizeof(struct esp_mac_rx_ctrl));
+                       mac_ctrl = &new_mac_ctrl;
+                       pkt_num = mac_ctrl->ampdu_cnt;
+                       esp_sip_dbg(ESP_DBG_TRACE, "%s %d rx ampdu %u pkts, %d pkts dumped, first len %u\n",
+                                       __func__, __LINE__, (unsigned int)((hdr->len % sip->rx_blksz) / sizeof(struct esp_rx_ampdu_len)), pkt_num, (unsigned int)ampdu_len->sublen);
+
+                       pkt_total += mac_ctrl->ampdu_cnt;
+                       //esp_sip_dbg(ESP_DBG_ERROR, "%s ampdu dropped %d/%d\n", __func__, pkt_dropped, pkt_total);
+                       while (pkt_num > 0) {
+                               esp_sip_dbg(ESP_DBG_TRACE, "%s %d ampdu sub state %02x,\n", __func__, __LINE__, ampdu_len->substate);
+
+                               if (sip_ampdu_occupy_buf(sip, ampdu_len)) { //pkt is dumped
+
+                                       rskb = sip_parse_data_rx_info(sip, skb, ampdu_len->sublen - FCS_LEN, 0, mac_ctrl, &pulled_len);
+                                       assert(rskb != NULL);
+
+                                       if (likely(atomic_read(&sip->epub->wl.off) == 0) &&
+                                                       (ampdu_len->substate == 0 || ampdu_len->substate == RX_TKIPMIC_ERR ||
+                                                        (sip->sendup_rpbm_pkt && ampdu_len->substate == RX_RPBM_ERR)) &&
+                                                       (sip->rxabort_fixed || !have_rxabort) ) 
+                                       {
+                                               if(!have_goodpkt) {
+                                                       have_goodpkt = true;
+                                                       memcpy(frame_head, rskb->data, 16);
+                                                       frame_head[1] &= ~0x80;
+                                                       frame_buf_ttl = 3;
+                                               }
+#ifndef RX_SENDUP_SYNC
+                                               skb_queue_tail(&sip->epub->rxq, rskb);
+                                               trigger_rxq = true;
+#else
+#ifdef RX_CHECKSUM_TEST
+                                               esp_rx_checksum_test(rskb);
+#endif
+                                               local_bh_disable();
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+                               ieee80211_rx(sip->epub->hw, rskb);
+#else
+                //simulate IEEE80211_SKB_RXCB in 2.6.32 
+                ieee80211_rx(sip->epub->hw, rskb ,(struct ieee80211_rx_status *)rskb->cb);
+#endif
+                                               local_bh_enable();
+#endif /* RX_SENDUP_SYNC */
+
+                                       } else {
+                                               kfree_skb(rskb);
+                                       }
+                               } else {
+                                       if (ampdu_len->substate == RX_ABORT) {
+                                               u8 * a;
+                                               have_rxabort = true;
+                                               esp_sip_dbg(ESP_DBG_TRACE, "rx abort %d %d\n", frame_buf_ttl, pkt_num);
+                                               if(frame_buf_ttl && !sip->rxabort_fixed) {
+                                                       struct esp_rx_ampdu_len * next_good_ampdu_len = ampdu_len + 1;
+                                                       a = frame_head;
+                                                       esp_sip_dbg(ESP_DBG_TRACE, "frame:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+                                                                       a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
+                                                       while(!sip_ampdu_occupy_buf(sip, next_good_ampdu_len)) {
+                                                               if(next_good_ampdu_len > ampdu_len + pkt_num - 1)
+                                                                       break;
+                                                               next_good_ampdu_len++;
+
+                                                       }
+                                                       if(next_good_ampdu_len <= ampdu_len + pkt_num -1) {
+                                                               bool b0, b10, b11;
+                                                               a = skb->data;
+                                                               esp_sip_dbg(ESP_DBG_TRACE, "buf:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+                                                                               a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
+                                                               b0 = memcmp(frame_head + 4, skb->data + 4, 12) == 0;
+                                                               b10 = memcmp(frame_head + 10, skb->data, 6) == 0;
+                                                               b11 = memcpy(frame_head + 11, skb->data, 5) == 0;
+                                                               esp_sip_dbg(ESP_DBG_TRACE, "com %d %d %d\n", b0, b10, b11);
+                                                               if(b0 && !b10 && !b11) {
+                                                                       have_rxabort = false;
+                                                                       esp_sip_dbg(ESP_DBG_TRACE, "repair 0\n");
+                                                               } else if(!b0 && b10 && !b11) {
+                                                                       skb_push(skb, 10);
+                                                                       memcpy(skb->data, frame_head, 10);
+                                                                       have_rxabort = false;
+                                                                       pulled_len -= 10;
+                                                                       esp_sip_dbg(ESP_DBG_TRACE, "repair 10\n");
+                                                               } else if(!b0 && !b10 && b11) {
+                                                                       skb_push(skb, 11);
+                                                                       memcpy(skb->data, frame_head, 11);
+                                                                       have_rxabort = false;
+                                                                       pulled_len -= 11;
+                                                                       esp_sip_dbg(ESP_DBG_TRACE, "repair 11\n");
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       pkt_dropped++;
+                                       esp_sip_dbg(ESP_DBG_LOG, "%s ampdu dropped %d/%d\n", __func__, pkt_dropped, pkt_total);
+                               }
+                               pkt_num--;
+                               ampdu_len++;
+                       }
+                       if(frame_buf_ttl)
+                               frame_buf_ttl--;
+                       skb_pull(skb, hdr->len - pulled_len);
+               } else {
+                       esp_sip_dbg(ESP_DBG_ERROR, "%s %d unknown type\n", __func__, __LINE__);
+               }
+
+_move_on:
+               if (hdr->len < remains_len) {
+                       remains_len -= hdr->len;
+               } else {
+                       break;
+               }
+               bufptr += hdr->len;
+       }
+
+       do {
+               ASSERT(skb != rskb);
+               kfree_skb(skb);
+       } while (0);
+
+#ifdef RX_SYNC
+       if (trigger_rxq) {
+               queue_work(sip->epub->esp_wkq, &sip->epub->sendup_work);
+       }
+       if (trigger_txq) {
+               sip_trigger_txq_process(sip);
+       }
+#else
+       return trigger_rxq;
+#endif /* RX_SYNC */
+
+#undef DO_NOT_COPY
+#undef DO_COPY
+}
+
+#ifndef RX_SYNC
+static void _sip_rxq_process(struct esp_sip *sip)
+{
+        struct sk_buff *skb = NULL;
+        bool sendup = false;
+
+        while ((skb = skb_dequeue(&sip->rxq))) {
+                if (sip_rx_pkt_process(sip, skb))
+                        sendup = true;
+        }
+#ifndef RX_SENDUP_SYNC
+        if (sendup) {
+                queue_work(sip->epub->esp_wkq, &sip->epub->sendup_work);
+        }
+#endif /* !RX_SENDUP_SYNC */
+
+        /* probably tx_credit is updated, try txq */
+        sip_trigger_txq_process(sip);
+}
+
+void sip_rxq_process(struct work_struct *work)
+{
+        struct esp_sip *sip = container_of(work, struct esp_sip, rx_process_work);
+        ASSERT(sip != NULL);
+
+       if (unlikely(atomic_read(&sip->state) == SIP_SEND_INIT)) {
+               sip_send_chip_init(sip);
+               atomic_set(&sip->state, SIP_WAIT_BOOTUP);
+               return;
+       }
+
+        spin_lock(&sip->rx_lock);
+        _sip_rxq_process(sip);
+        spin_unlock(&sip->rx_lock);
+}
+
+static inline void sip_rx_pkt_enqueue(struct esp_sip *sip, struct sk_buff *skb)
+{
+        skb_queue_tail(&sip->rxq, skb);
+}
+
+static inline struct sk_buff * sip_rx_pkt_dequeue(struct esp_sip *sip) {
+        return skb_dequeue(&sip->rxq);
+}
+#endif /* RX_SYNC */
+
+static u32 sip_rx_count = 0;
+void sip_debug_show(struct esp_sip *sip)
+{
+       esp_sip_dbg(ESP_DBG_ERROR, "txq left %d %d\n", skb_queue_len(&sip->epub->txq), atomic_read(&sip->tx_data_pkt_queued));
+       esp_sip_dbg(ESP_DBG_ERROR, "tx queues stop ? %d\n", atomic_read(&sip->epub->txq_stopped));
+       esp_sip_dbg(ESP_DBG_ERROR, "txq stop?  %d\n", test_bit(ESP_WL_FLAG_STOP_TXQ, &sip->epub->wl.flags));
+       esp_sip_dbg(ESP_DBG_ERROR, "tx credit %d\n", atomic_read(&sip->tx_credits));
+       esp_sip_dbg(ESP_DBG_ERROR, "rx collect %d\n", sip_rx_count);
+       sip_rx_count = 0;
+}
+
+#ifndef LOOKAHEAD
+int sip_rx(struct esp_pub *epub)
+{
+        struct sip_hdr *shdr = NULL;
+        struct esp_sip *sip = epub->sip;
+        int err = 0;
+        struct sk_buff *first_skb = NULL;
+        struct sk_buff *next_skb = NULL;
+        u8 *rx_buf = NULL;
+        u32 rx_blksz;
+        u32 first_sz = 4;
+        struct sk_buff *rx_skb = NULL;
+
+        esp_sip_dbg(ESP_DBG_LOG, "%s enter\n", __func__);
+
+
+        /* first read one block out, if we luck enough, that's it
+         *
+         *  To make design as simple as possible, we allocate skb(s)
+         *  separately for each sif read operation to avoid global
+         *  read_buf_pointe access.  It coule be optimized late.
+         */
+        rx_blksz = sif_get_blksz(epub);
+        first_skb = __dev_alloc_skb(first_sz, GFP_KERNEL);
+        if (first_skb == NULL) {
+                esp_sip_dbg(ESP_DBG_ERROR, "%s first no memory \n", __func__);
+                goto _err;
+        }
+        rx_buf = skb_put(first_skb, first_sz);
+        esp_sip_dbg(ESP_DBG_LOG, "%s rx_buf ptr %p, first_sz %d\n", __func__, rx_buf, first_sz);
+
+        sif_lock_bus(epub);
+
+#ifdef USE_EXT_GPIO
+       do{
+               int err2;
+               u16 value = 0;
+               u16 intr_mask = ext_gpio_get_int_mask_reg();
+               if(!intr_mask)
+                       break;
+               err2 = sif_get_gpio_intr(epub, intr_mask, &value);
+               if(!err2 && value) {
+                       esp_sip_dbg(ESP_DBG_TRACE, "%s intr_mask[0x%04x] value[0x%04x]\n", __func__, intr_mask, value);
+                       ext_gpio_int_process(value);
+               }
+       }while(0);
+#endif
+#ifdef ESP_ACK_INTERRUPT
+#ifdef ESP_ACK_LATER
+               err = esp_common_read(epub, rx_buf, first_sz, ESP_SIF_NOSYNC, true);
+        sif_platform_ack_interrupt(epub);
+#else
+        sif_platform_ack_interrupt(epub);
+               err = esp_common_read(epub, rx_buf, first_sz, ESP_SIF_NOSYNC, true);
+#endif /* ESP_ACK_LATER */
+#else
+        err = esp_common_read(epub, rx_buf, first_sz, ESP_SIF_NOSYNC, true);
+#endif //ESP_ACK_INTERRUPT
+
+       sip_rx_count++;
+        if (unlikely(err)) {
+                esp_dbg(ESP_DBG_ERROR, " %s first read err %d %d\n", __func__, err, sif_get_regs(epub)->config_w0);
+                kfree_skb(first_skb);
+               sif_unlock_bus(epub);
+                goto _err;
+        }
+
+        shdr = (struct sip_hdr *)rx_buf;
+       if(SIP_HDR_IS_CTRL(shdr) && (shdr->c_evtid == SIP_EVT_SLEEP)) {
+               atomic_set(&sip->epub->ps.state, ESP_PM_ON);
+               esp_dbg(ESP_DBG_TRACE, "s\n");
+       }
+
+        ASSERT((shdr->len & 3) == 0);
+        //ASSERT(shdr->len >= SIP_HDR_LEN && shdr->len <= SIP_PKT_MAX_LEN);
+        if (shdr->len > first_sz)  {
+                /* larger than one blk, fetch the rest */
+                next_skb = __dev_alloc_skb(roundup(shdr->len, rx_blksz) + first_sz, GFP_KERNEL);
+                if (unlikely(next_skb == NULL)) {
+                        sif_unlock_bus(epub);
+                        esp_sip_dbg(ESP_DBG_ERROR, "%s next no memory \n", __func__);
+                        kfree_skb(first_skb);
+                        goto _err;
+                }
+                rx_buf = skb_put(next_skb, shdr->len);
+                rx_buf += first_sz; /* skip the first block */
+
+               err = esp_common_read(epub, rx_buf, (shdr->len - first_sz), ESP_SIF_NOSYNC, false);
+               sif_unlock_bus(epub);
+
+                if (unlikely(err)) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "%s next read err %d \n", __func__, err);
+                        kfree(first_skb);
+                        kfree(next_skb);
+                        goto _err;
+                }
+                /* merge two skbs, TBD: could be optimized by skb_linearize*/
+                memcpy(next_skb->data, first_skb->data, first_sz);
+                esp_dbg(ESP_DBG_TRACE, " %s  next skb\n", __func__);
+
+                rx_skb = next_skb;
+                kfree_skb(first_skb);
+        } else {
+               sif_unlock_bus(epub);
+                skb_trim(first_skb, shdr->len);
+                esp_dbg(ESP_DBG_TRACE, " %s first_skb only\n", __func__);
+
+                rx_skb = first_skb;
+        }
+        if (atomic_read(&sip->state) == SIP_STOP) {
+               kfree_skb(rx_skb);
+                esp_sip_dbg(ESP_DBG_ERROR, "%s when sip stopped\n", __func__);
+                return 0;
+        }
+#ifndef RX_SYNC
+        sip_rx_pkt_enqueue(sip, rx_skb);
+        queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
+#else
+        sip_rx_pkt_process_sync(sip, rx_skb);
+#endif /* RX_SYNC */
+
+_err:
+
+        return err;
+}
+
+#else
+
+int sip_rx(struct esp_pub *epub)
+{
+        struct sip_hdr *shdr = NULL;
+        struct esp_sip *sip = epub->sip;
+        int err = 0;
+        struct sk_buff *rx_skb = NULL;
+        u8 *rx_buf = NULL;
+        u32 lookahead = 0;
+        struct slc_host_regs *regs = sif_get_regs(epub);
+        bool free_skb = false;
+
+        esp_sip_dbg(ESP_DBG_LOG, "%s enter\n", __func__);
+
+        lookahead = regs->config_w0;
+
+        esp_sip_dbg(ESP_DBG_TRACE, "%s lookahead %u \n", __func__, lookahead);
+        rx_skb = __dev_alloc_skb(lookahead, GFP_KERNEL);
+        if (rx_skb == NULL) {
+                esp_sip_dbg(ESP_DBG_ERROR, "%s no memory \n", __func__);
+                goto __out;
+        }
+        rx_buf = skb_put(rx_skb, lookahead);
+        err = sif_lldesc_read_raw(epub, rx_buf, lookahead);
+        if (unlikely(err)) {
+                esp_dbg(ESP_DBG_ERROR, " %s read err %d \n", __func__, err);
+                goto __out;
+        }
+
+        shdr = (struct sip_hdr *)rx_buf;
+        esp_sip_dbg(ESP_DBG_TRACE, "%s len %d totlen %d\n", __func__, shdr->len, (shdr->h_credits >> 12));
+        show_buf(rx_buf, 32);
+        //ASSERT(shdr->len >= SIP_HDR_LEN && shdr->len <= SIP_PKT_MAX_LEN);
+
+        esp_sip_dbg(ESP_DBG_TRACE, "%s credits %d\n", __func__, shdr->h_credits);
+        if (shdr->h_credits & SIP_CREDITS_MASK) {
+                sip_update_tx_credits(sip, shdr->h_credits & SIP_CREDITS_MASK);
+        }
+#if 0
+        if (SIP_HDR_IS_CREDIT_RPT(shdr)) {
+                esp_sip_dbg(ESP_DBG_TRACE, "%s credit update %d\n", __func__, shdr->h_credits & SIP_CREDITS_MASK);
+                if (unlikely(shdr->seq != sip->rxseq++)) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "%s seq mismatch! got %u, expect %u\n", __func__, shdr->seq, sip->rxseq-1);
+                }
+
+                free_skb = true;
+                goto __out;
+        }
+#endif
+        shdr->h_credits &= ~SIP_CREDITS_MASK; /* clean credits in sip_hdr, prevent over-add */
+
+        /* we need some place to store the total length of the pkt chain, the simple way is make it consistent with
+         * non-lookahead case
+         */
+        shdr->h_credits = (shdr->len << 12);
+        shdr->len = lookahead;
+
+        sip_rx_pkt_enqueue(sip, rx_skb);
+        queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
+
+__out:
+        if (free_skb)
+                kfree_skb(rx_skb);
+
+        sip_trigger_txq_process(sip);
+
+        return err;
+}
+#endif /* LOOKAHEAD */
+
+int sip_get_raw_credits(struct esp_sip *sip)
+{
+#if 1
+        unsigned long timeout;
+        int err = 0;
+
+        esp_dbg(ESP_DBG_TRACE, "%s entern \n", __func__);
+
+        /* 1s timeout */
+        timeout = jiffies + msecs_to_jiffies(1000);
+
+        while (time_before(jiffies, timeout) && !sip->boot_credits) {
+
+               err = esp_common_read_with_addr(sip->epub, SLC_HOST_TOKEN_RDATA, (u8 *)&sip->boot_credits, 4, ESP_SIF_SYNC);
+
+                if (err) {
+                        esp_dbg(ESP_DBG_ERROR, "Can't read credits\n");
+                        return err;
+                }
+                sip->boot_credits &= SLC_HOST_TOKEN0_MASK;
+#ifdef SIP_DEBUG
+                if (sip->boot_credits == 0) {
+                        esp_dbg(ESP_DBG_ERROR, "no credit, try again\n");
+                        mdelay(50);
+                }
+#endif /* SIP_DEBUG */
+        }
+
+        if (!sip->boot_credits) {
+                esp_dbg(ESP_DBG_ERROR, "read credits timeout\n");
+                return -1;
+        }
+
+        esp_dbg(ESP_DBG_TRACE, "%s got credits: %d\n", __func__, sip->boot_credits);
+#endif //0000
+
+        return 0;
+}
+
+
+/* Only cooperate with get_raw_credits */
+static void
+sip_dec_credit(struct esp_sip *sip)
+{
+#if 0
+        u32 reg = 0;
+        int err = 0;
+
+        reg = SLC_HOST_TOKEN0_WR | SLC_HOST_TOKEN0_DEC;
+        memcpy(sip->rawbuf, &reg, sizeof(u32));
+        err = sif_io_sync(sip->epub, SLC_HOST_INT_CLR, sip->rawbuf, sizeof(u32), SIF_TO_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR);
+
+        if (err)
+                esp_dbg(ESP_DBG_ERROR, "%s can't clear target token0 \n", __func__);
+
+#endif //0000
+        /* SLC 2.0, token reg is read-to-clean, thus no need to access target */
+        sip->boot_credits--;
+}
+
+int sip_post_init(struct esp_sip *sip, struct sip_evt_bootup2 *bevt)
+{
+        struct esp_pub *epub;
+        int po = 0;
+
+        ASSERT(sip != NULL);
+
+        epub = sip->epub;
+
+        po = get_order(SIP_TX_AGGR_BUF_SIZE);
+        sip->tx_aggr_buf = (u8 *)__get_free_pages(GFP_ATOMIC, po);
+        if (sip->tx_aggr_buf == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "no mem for tx_aggr_buf! \n");
+                return -ENOMEM;
+        }
+#if 0
+        po = get_order(SIP_RX_AGGR_BUF_SIZE);
+        sip->rx_aggr_buf = (u8 *)__get_free_pages(GFP_ATOMIC, po);
+
+        if (sip->rx_aggr_buf == NULL) {
+                po = get_order(SIP_TX_AGGR_BUF_SIZE);
+                free_pages((unsigned long)sip->tx_aggr_buf, po);
+                esp_dbg(ESP_DBG_ERROR, "no mem for rx_aggr_buf! \n");
+                return -ENOMEM;
+        }
+#endif
+
+        sip->tx_aggr_write_ptr = sip->tx_aggr_buf;
+
+        sip->tx_blksz = bevt->tx_blksz;
+        sip->rx_blksz = bevt->rx_blksz;
+        sip->credit_to_reserve = bevt->credit_to_reserve;
+
+        sip->dump_rpbm_err = (bevt->options & SIP_DUMP_RPBM_ERR);
+        sip->rxabort_fixed = (bevt->options & SIP_RXABORT_FIXED);
+        sip->support_bgscan = (bevt->options & SIP_SUPPORT_BGSCAN);
+
+        sip->sendup_rpbm_pkt = sip->dump_rpbm_err && false;
+
+        /* print out MAC addr... */
+        memcpy(epub->mac_addr, bevt->mac_addr, ETH_ALEN);
+       sip->noise_floor = bevt->noise_floor;
+
+        esp_sip_dbg(ESP_DBG_TRACE, "%s tx_blksz %d rx_blksz %d mac addr %pM\n", __func__, sip->tx_blksz, sip->rx_blksz, epub->mac_addr);
+
+               return 0;
+}
+
+/* write pkts in aggr buf to target memory */
+static void sip_write_pkts(struct esp_sip *sip, int pm_state)
+{
+        int tx_aggr_len = 0;
+        struct sip_hdr *first_shdr = NULL;
+       int err = 0;
+
+        tx_aggr_len = sip->tx_aggr_write_ptr - sip->tx_aggr_buf;
+        if (tx_aggr_len < sizeof(struct sip_hdr)) {
+                printk("%s tx_aggr_len %d \n", __func__, tx_aggr_len);
+                ASSERT(0);
+        }
+        //ASSERT(tx_aggr_len >= sizeof(struct sip_hdr));
+        ASSERT((tx_aggr_len & 0x3) == 0);
+
+        first_shdr = (struct sip_hdr *)sip->tx_aggr_buf;
+
+        if (atomic_read(&sip->tx_credits) <= SIP_CREDITS_LOW_THRESHOLD) {
+                first_shdr->fc[1] |= SIP_HDR_F_NEED_CRDT_RPT;
+        }
+
+        ASSERT(tx_aggr_len == sip->tx_tot_len);
+
+        /* still use lock bus instead of sif_lldesc_write_sync since we want to protect several global varibles assignments */
+        sif_lock_bus(sip->epub);
+
+        /* add a dummy read in power saving mode, although target may not really in
+         * sleep
+         */
+        //if (atomic_read(&sip->epub->ps.state) == ESP_PM_ON) {
+       //      atomic_set(&sip->epub->ps.state, ESP_PM_OFF);
+                sif_raw_dummy_read(sip->epub);
+        //}
+       //esp_dbg(ESP_DBG_ERROR, "%s write len %u\n", __func__, tx_aggr_len);
+
+               err = esp_common_write(sip->epub, sip->tx_aggr_buf, tx_aggr_len, ESP_SIF_NOSYNC);
+
+        sip->tx_aggr_write_ptr = sip->tx_aggr_buf;
+        sip->tx_tot_len = 0;
+
+#if 0
+        if (pm_state == ESP_PM_TURNING_ON) {
+                ASSERT(atomic_read(&sip->epub->ps.state) == ESP_PM_TURNING_ON);
+                atomic_set(&sip->epub->ps.state, ESP_PM_ON);
+        } else if (pm_state == ESP_PM_TURNING_OFF) {
+                ASSERT(atomic_read(&sip->epub->ps.state) == ESP_PM_TURNING_OFF);
+                atomic_set(&sip->epub->ps.state, ESP_PM_OFF);
+                esp_dbg(ESP_DBG_PS, "----beacon %d, probe rsp %d -------\n", bcn_counter, probe_rsp_counter);
+                bcn_counter = 0; probe_rsp_counter = 0;
+        } else if (pm_state && atomic_read(&sip->epub->ps.state)) {
+                esp_dbg(ESP_DBG_ERROR, "%s wrong pm_state %d ps.state %d \n", __func__, pm_state, atomic_read(&sip->epub->ps.state));
+        }
+#endif
+        sif_unlock_bus(sip->epub);
+
+       if (err)
+               esp_sip_dbg(ESP_DBG_ERROR, "func %s err!!!!!!!!!: %d\n", __func__, err);
+
+}
+
+/* setup sip header and tx info, copy pkt into aggr buf */
+static int sip_pack_pkt(struct esp_sip *sip, struct sk_buff *skb, int *pm_state)
+{
+        struct ieee80211_tx_info *itx_info;
+        struct sip_hdr *shdr;
+        u32 tx_len = 0, offset = 0;
+        bool is_data = true;
+
+        itx_info = IEEE80211_SKB_CB(skb);
+
+        if (itx_info->flags == 0xffffffff) {
+                shdr = (struct sip_hdr *)skb->data;
+                is_data = false;
+                tx_len = skb->len;
+        } else {
+                struct ieee80211_hdr * wh = (struct ieee80211_hdr *)skb->data;
+                struct esp_vif *evif = (struct esp_vif *)itx_info->control.vif->drv_priv;
+                u8 sta_index;
+                struct esp_node *node; 
+                /* update sip header */
+                shdr = (struct sip_hdr *)sip->tx_aggr_write_ptr;
+                
+                shdr->fc[0] = 0;
+                shdr->fc[1] = 0;
+
+                if ((itx_info->flags & IEEE80211_TX_CTL_AMPDU) && (true || esp_is_ip_pkt(skb)))
+                        SIP_HDR_SET_TYPE(shdr->fc[0], SIP_DATA_AMPDU);
+                else
+                        SIP_HDR_SET_TYPE(shdr->fc[0], SIP_DATA);
+
+               if(evif->epub == NULL){
+#ifndef FAST_TX_STATUS
+                       /* TBD */
+#else
+                       sip_tx_status_report(sip, skb, itx_info, false);
+                       atomic_dec(&sip->tx_data_pkt_queued);
+                       return -1;
+#endif /* FAST_TX_STATUS */
+               }
+
+                /* make room for encrypted pkt */
+                if (itx_info->control.hw_key) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+                        shdr->d_enc_flag= itx_info->control.hw_key->alg+1;
+#else
+                        int alg = esp_cipher2alg(itx_info->control.hw_key->cipher);
+                        if (unlikely(alg == -1)) {
+#ifndef FAST_TX_STATUS
+                                /* TBD */
+#else
+                                sip_tx_status_report(sip, skb, itx_info, false);
+                                atomic_dec(&sip->tx_data_pkt_queued);
+                                return -1;
+#endif /* FAST_TX_STATUS */
+                        } else {
+                                shdr->d_enc_flag = alg + 1;
+                        }
+
+#endif /* NEW_KERNEL */
+                         shdr->d_hw_kid =  itx_info->control.hw_key->hw_key_idx | (evif->index<<7);
+                } else {
+                        shdr->d_enc_flag=0;
+                        shdr->d_hw_kid = (evif->index << 7 | evif->index);
+                }
+
+                /* update sip tx info */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+               /* if(itx_info->control.sta == NULL){
+                        node = NULL;
+                } else {
+                        node = esp_get_node_by_addr(sip->epub, itx_info->control.sta->addr);
+                }*/
+#else
+               
+                node = esp_get_node_by_addr(sip->epub, wh->addr1);
+#endif
+                if(node != NULL)
+                        sta_index = node->index;
+                else
+                        sta_index = ESP_PUB_MAX_STA + 1;
+                SIP_HDR_SET_IFIDX(shdr->fc[0], evif->index << 3 | sta_index);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+                shdr->d_p2p = itx_info->control.vif->p2p;
+                if(evif->index == 1)
+                        shdr->d_p2p = 1;
+#endif
+                shdr->d_ac = skb_get_queue_mapping(skb);
+                shdr->d_tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+                wh = (struct ieee80211_hdr *)skb->data;
+                if (ieee80211_is_mgmt(wh->frame_control)) {
+               /* addba/delba/bar may use different tid/ac */
+                        if (ieee80211_is_beacon(wh->frame_control)||shdr->d_ac == WME_AC_VO) {
+                                shdr->d_tid = 7;
+                        }
+                }
+//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+                if (check_ac_tid(skb->data, shdr->d_ac, shdr->d_tid)) {
+                        shdr->d_ac = WME_AC_BE;
+                        shdr->d_tid = 0;
+                }
+//#endif  /* NEW_KERNEL || KERNEL_35 */
+
+
+                /* make sure data is start at 4 bytes aligned addr. */
+                offset = roundup(sizeof(struct sip_hdr), 4);
+
+#ifdef HOST_RC
+                esp_sip_dbg(ESP_DBG_TRACE, "%s offset0 %d \n", __func__, offset);
+                memcpy(sip->tx_aggr_write_ptr + offset, (void *)&itx_info->control,
+                       sizeof(struct sip_tx_rc));
+
+                offset += roundup(sizeof(struct sip_tx_rc), 4);
+                esp_show_tx_rates(&itx_info->control.rates[0]);
+
+#endif /* HOST_RC */
+
+                if (SIP_HDR_IS_AMPDU(shdr)) {
+                        memset(sip->tx_aggr_write_ptr + offset, 0, sizeof(struct esp_tx_ampdu_entry));
+                        offset += roundup(sizeof(struct esp_tx_ampdu_entry), 4);
+                }
+
+                tx_len = offset + skb->len;
+                shdr->len = tx_len;  /* actual len */
+
+                esp_sip_dbg(ESP_DBG_TRACE, "%s offset %d skblen %d txlen %d\n", __func__, offset, skb->len, tx_len);
+
+        }
+
+        shdr->seq = sip->txseq++;
+        //esp_sip_dbg(ESP_DBG_ERROR, "%s seq %u, %u %u\n", __func__, shdr->seq, SIP_HDR_GET_TYPE(shdr->fc[0]),shdr->c_cmdid);
+
+        /* copy skb to aggr buf */
+        memcpy(sip->tx_aggr_write_ptr + offset, skb->data, skb->len);
+
+        if (is_data) {
+                       spin_lock_bh(&sip->epub->tx_lock);
+                       sip->txdataseq = shdr->seq;
+                       spin_unlock_bh(&sip->epub->tx_lock);
+#ifndef FAST_TX_STATUS
+                /* store seq in driver data, need seq to pick pkt during tx status report */
+                *(u32 *)itx_info->driver_data = shdr->seq;
+                atomic_inc(&sip->pending_tx_status);
+#else
+                /* fake a tx_status and report to mac80211 stack to speed up tx, may affect
+                 *  1) rate control (now it's all in target, so should be OK)
+                 *  2) ps mode, mac80211 want to check ACK of ps/nulldata to see if AP is awake
+                 *  3) BAR, mac80211 do BAR by checking ACK
+                 */
+                /*
+                 *  XXX: need to adjust for 11n, e.g. report tx_status according to BA received in target
+                 *
+                 */
+                sip_tx_status_report(sip, skb, itx_info, true);
+                atomic_dec(&sip->tx_data_pkt_queued);
+
+#endif /* FAST_TX_STATUS */
+                STRACE_TX_DATA_INC();
+        } else {
+                /* check pm state here */
+#if 0
+                if (*pm_state == 0) {
+                        if (SIP_HDR_IS_PM_TURNING_ON(shdr))
+                                *pm_state = ESP_PM_TURNING_ON;
+                        else if (SIP_HDR_IS_PM_TURNING_OFF(shdr))
+                                *pm_state = ESP_PM_TURNING_OFF;
+                } else {
+                        if (SIP_HDR_IS_PM_TURNING_ON(shdr) || SIP_HDR_IS_PM_TURNING_OFF(shdr)) {
+                                esp_dbg(ESP_DBG_ERROR, "%s two pm states in one bunch - prev: %d; curr %d\n", __func__,
+                                        *pm_state, SIP_HDR_IS_PM_TURNING_ON(shdr)?ESP_PM_TURNING_ON:ESP_PM_TURNING_OFF);
+                                if (*pm_state == ESP_PM_TURNING_ON && SIP_HDR_IS_PM_TURNING_OFF(shdr)) {
+                                        *pm_state = 0;
+                                        atomic_set(&sip->epub->ps.state, ESP_PM_OFF);
+                                } else if (*pm_state == ESP_PM_TURNING_OFF && SIP_HDR_IS_PM_TURNING_ON(shdr)) {
+                                        *pm_state = 0;
+                                        atomic_set(&sip->epub->ps.state, ESP_PM_ON);
+                                } else {
+                                        ASSERT(0);
+                                }
+                        }
+                }
+#endif
+                /* no need to hold ctrl skb */
+                sip_free_ctrl_skbuff(sip, skb);
+                STRACE_TX_CMD_INC();
+        }
+
+        /* TBD: roundup here or whole aggr-buf */
+        tx_len = roundup(tx_len, sip->tx_blksz);
+
+        sip->tx_aggr_write_ptr += tx_len;
+        sip->tx_tot_len += tx_len;
+
+        return 0;
+}
+
+#ifndef FAST_TX_STATUS
+static void
+sip_after_tx_status_update(struct esp_sip *sip)
+{
+        if (atomic_read(&sip->data_tx_stopped) == true && sip_tx_data_may_resume(sip)) {
+                atomic_set(&sip->data_tx_stopped, false);
+                if (sip_is_tx_mblk_avail(sip) == false) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "%s mblk still unavail \n", __func__);
+                } else {
+                        esp_sip_dbg(ESP_DBG_TRACE, "%s trigger txq \n", __func__);
+                        sip_trigger_txq_process(sip);
+                }
+        } else if (!sip_tx_data_may_resume(sip)) { //JLU: this is redundant
+                STRACE_SHOW(sip);
+        }
+}
+#endif /* !FAST_TX_STATUS */
+
+#ifdef HOST_RC
+static void sip_set_tx_rate_status(struct sip_rc_status *rcstatus, struct ieee80211_tx_rate *irates)
+{
+        int i;
+        u8 shift = 0;
+        u32 cnt = 0;
+
+        for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+                if (rcstatus->rc_map & BIT(i)) {
+                        shift = i << 2;
+                        cnt = (rcstatus->rc_cnt_store >> shift) & RC_CNT_MASK;
+                        irates[i].idx = i;
+                        irates[i].count = (u8)cnt;
+                } else {
+                        irates[i].idx = -1;
+                        irates[i].count = 0;
+                }
+        }
+
+        esp_show_rcstatus(rcstatus);
+        esp_show_tx_rates(irates);
+}
+#endif /* HOST_RC */
+
+#ifndef FAST_TX_STATUS
+static void
+sip_txdoneq_process(struct esp_sip *sip, struct sip_evt_tx_report *tx_report)
+{
+        struct sk_buff *skb, *tmp;
+        struct esp_pub *epub = sip->epub;
+        int matchs = 0;
+        struct ieee80211_tx_info *tx_info;
+        struct sip_tx_status *tx_status;
+        int i;
+
+        esp_sip_dbg(ESP_DBG_LOG, "%s enter, report->pkts %d, pending tx_status %d\n", __func__, tx_report->pkts, atomic_read(&sip->pending_tx_status));
+
+        /* traversal the txdone queue, find out matched skb by seq, hand over
+         * to up layer stack
+         */
+        for (i = 0; i < tx_report->pkts; i++) {
+                //esp_sip_dbg(ESP_DBG_TRACE, "%s status %d seq %u\n", __func__, i, tx_report->status[i].sip_seq);
+                skb_queue_walk_safe(&epub->txdoneq, skb, tmp) {
+                        tx_info = IEEE80211_SKB_CB(skb);
+
+                        //esp_sip_dbg(ESP_DBG_TRACE, "%s skb seq %u\n", __func__, *(u32 *)tx_info->driver_data);
+                        if (tx_report->status[i].sip_seq == *(u32 *)tx_info->driver_data) {
+                                tx_status = &tx_report->status[i];
+                                __skb_unlink(skb, &epub->txdoneq);
+
+                                //fill up ieee80211_tx_info
+                                //TBD: lock ??
+                                if (tx_status->errno == SIP_TX_ST_OK &&
+                                    !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+                                        tx_info->flags |= IEEE80211_TX_STAT_ACK;
+                                }
+#ifdef HOST_RC
+                                sip_set_tx_rate_status(&tx_report->status[i].rcstatus, &tx_info->status.rates[0]);
+                                esp_sip_dbg(ESP_DBG_TRACE, "%s idx0 %d, cnt0 %d, flags0 0x%02x\n", __func__, tx_info->status.rates[0].idx,tx_info->status.rates[0].count, tx_info->status.rates[0].flags);
+
+#else
+                                /* manipulate rate status... */
+                                tx_info->status.rates[0].idx = 0;
+                                tx_info->status.rates[0].count = 1;
+                                tx_info->status.rates[0].flags = 0;
+                                tx_info->status.rates[1].idx = -1;
+#endif /* HOST_RC */
+
+                                ieee80211_tx_status(epub->hw, skb);
+                                matchs++;
+                                atomic_dec(&sip->pending_tx_status);
+                                STRACE_RX_TXSTATUS_INC();
+                        }
+                }
+        }
+
+        if (matchs < tx_report->pkts) {
+                esp_sip_dbg(ESP_DBG_ERROR, "%s tx report mismatch! \n", __func__);
+        } else {
+                //esp_sip_dbg(ESP_DBG_TRACE, "%s tx report %d pkts! \n", __func__, matchs);
+        }
+
+        sip_after_tx_status_update(sip);
+}
+#else
+#ifndef FAST_TX_NOWAIT
+
+static void
+sip_txdoneq_process(struct esp_sip *sip)
+{
+        struct esp_pub *epub = sip->epub;
+        struct sk_buff *skb;
+        while ((skb = skb_dequeue(&epub->txdoneq))) {
+                ieee80211_tx_status(epub->hw, skb);
+        }
+}
+#endif
+#endif /* !FAST_TX_STATUS */
+
+#ifdef FAST_TX_STATUS
+static void sip_tx_status_report(struct esp_sip *sip, struct sk_buff *skb, struct ieee80211_tx_info *tx_info, bool success)
+{
+        if(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
+                if (likely(success))
+                        tx_info->flags |= IEEE80211_TX_STAT_ACK;
+                else
+                        tx_info->flags &= ~IEEE80211_TX_STAT_ACK;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                /* manipulate rate status... */
+                tx_info->status.rates[0].idx = 11;
+                tx_info->status.rates[0].count = 1;
+                tx_info->status.rates[0].flags = 0;
+                tx_info->status.rates[1].idx = -1;
+#else
+                tx_info->status.retry_count = 1;
+                tx_info->status.excessive_retries = false;
+#endif
+
+        } else {
+                tx_info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_ACK;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+                tx_info->status.ampdu_ack_map = 1;
+#else
+                tx_info->status.ampdu_len = 1;
+#endif
+                tx_info->status.ampdu_ack_len = 1;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                /* manipulate rate status... */
+                tx_info->status.rates[0].idx = 7;
+                tx_info->status.rates[0].count = 1;
+                tx_info->status.rates[0].flags = IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_SHORT_GI;
+                tx_info->status.rates[1].idx = -1;
+#else
+                tx_info->status.retry_count = 1;
+                tx_info->status.excessive_retries = false;
+#endif
+
+        }
+
+        if(tx_info->flags & IEEE80211_TX_STAT_AMPDU)
+                esp_sip_dbg(ESP_DBG_TRACE, "%s ampdu status! \n", __func__);
+
+        if (!mod_support_no_txampdu() /*&&
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+                sip->epub->hw->conf.channel_type != NL80211_CHAN_NO_HT
+#else
+                !(sip->epub->hw->conf.flags&IEEE80211_CONF_SUPPORT_HT_MODE)
+#endif*/ //add libing
+                ) {
+                struct ieee80211_tx_info * tx_info = IEEE80211_SKB_CB(skb);
+                struct ieee80211_hdr * wh = (struct ieee80211_hdr *)skb->data;
+                if(ieee80211_is_data_qos(wh->frame_control)) {
+                        if(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
+                                u8 tidno = ieee80211_get_qos_ctl(wh)[0] & IEEE80211_QOS_CTL_TID_MASK;
+                                struct esp_node * node;
+                                struct esp_tx_tid *tid;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+ /*                               struct ieee80211_sta *sta;
+                                sta = tx_info->control.sta;
+                                if(sta == NULL)
+                                        goto _exit;
+                                node = (struct esp_node *)sta->drv_priv;
+                                ASSERT(node != NULL);
+                                if(node->sta == NULL) 
+                                        goto _exit;*/ //add libing
+#else
+                                node = esp_get_node_by_addr(sip->epub, wh->addr1);
+                                if(node == NULL)
+                                        goto _exit;
+#endif
+                                tid = &node->tid[tidno];
+                                spin_lock_bh(&sip->epub->tx_ampdu_lock);
+                                //start session
+                                ASSERT(tid != NULL);
+                                if ((tid->state == ESP_TID_STATE_INIT) && 
+                                               (TID_TO_AC(tidno) != WME_AC_VO) && tid->cnt >= 10) {
+                                        tid->state = ESP_TID_STATE_TRIGGER;
+                                        esp_sip_dbg(ESP_DBG_ERROR, "start tx ba session,addr:%pM,tid:%u\n", wh->addr1, tidno);
+                                        spin_unlock_bh(&sip->epub->tx_ampdu_lock);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+                                        ieee80211_start_tx_ba_session(sip->epub->hw, wh->addr1, tidno);
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
+                                        ieee80211_start_tx_ba_session(sip->epub->hw, sta->addr, tidno);
+#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 37))
+                                        ieee80211_start_tx_ba_session(sta, tidno);
+#else
+                                       // ieee80211_start_tx_ba_session(sta, tidno, 0);
+#endif
+                                } else {
+                                       if(tid->state == ESP_TID_STATE_INIT)
+                                               tid->cnt++;
+                                       else
+                                               tid->cnt = 0;
+                                        spin_unlock_bh(&sip->epub->tx_ampdu_lock);
+                                }
+                        }
+                }
+        }
+/*_exit:
+#ifndef FAST_TX_NOWAIT 
+        skb_queue_tail(&sip->epub->txdoneq, skb);
+#else
+        ieee80211_tx_status(sip->epub->hw, skb);
+#endif*/ //add libing
+}
+#endif /* FAST_TX_STATUS */
+
+/*
+ *  NB: this routine should be locked when calling
+ */
+void
+sip_txq_process(struct esp_pub *epub)
+{
+        struct sk_buff *skb;
+        struct esp_sip *sip = epub->sip;
+        u32 pkt_len = 0, tx_len = 0, blknum = 0;
+        bool queued_back = false;
+        bool out_of_credits = false;
+        struct ieee80211_tx_info *itx_info;
+        int pm_state = 0;
+       
+        while ((skb = skb_dequeue(&epub->txq))) {
+
+                /* cmd skb->len does not include sip_hdr too */
+                pkt_len = skb->len;
+                itx_info = IEEE80211_SKB_CB(skb);
+                if (itx_info->flags != 0xffffffff) {
+                        pkt_len += roundup(sizeof(struct sip_hdr), 4);
+                        if ((itx_info->flags & IEEE80211_TX_CTL_AMPDU) && (true || esp_is_ip_pkt(skb)))
+                                pkt_len += roundup(sizeof(struct esp_tx_ampdu_entry), 4);
+                }
+
+                /* current design simply requires every sip_hdr must be at the begin of mblk, that definitely
+                 * need to be optimized, e.g. calulate remain length in the previous mblk, if it larger than
+                 * certain threshold (e.g, whole pkt or > 50% of pkt or 2 x sizeof(struct sip_hdr), append pkt
+                 * to the previous mblk.  This might be done in sip_pack_pkt()
+                 */
+                pkt_len = roundup(pkt_len, sip->tx_blksz);
+                blknum = pkt_len / sip->tx_blksz;
+                esp_dbg(ESP_DBG_TRACE, "%s skb_len %d pkt_len %d blknum %d\n", __func__, skb->len, pkt_len, blknum);
+
+                if (unlikely(blknum > atomic_read(&sip->tx_credits) - sip->credit_to_reserve)) {
+                        esp_dbg(ESP_DBG_TRACE, "%s out of credits!\n", __func__);
+                        STRACE_TX_OUT_OF_CREDIT_INC();
+                        queued_back = true;
+                        out_of_credits = true;
+                       /*
+                        if (epub->hw) {
+                                ieee80211_stop_queues(epub->hw);
+                                atomic_set(&epub->txq_stopped, true);
+                        }
+                       */
+                        /* we will be back */
+                        break;
+                }
+
+                tx_len += pkt_len;
+                if (tx_len >= SIP_TX_AGGR_BUF_SIZE) {
+                        /* do we need to have limitation likemax 8 pkts in a row? */
+                        esp_dbg(ESP_DBG_TRACE, "%s too much pkts in one shot!\n", __func__);
+                        STRACE_TX_ONE_SHOT_INC();
+                        tx_len -= pkt_len;
+                        queued_back = true;
+                        break;
+                }
+
+                if (sip_pack_pkt(sip, skb, &pm_state) != 0) {
+                        /* wrong pkt, won't send to target */
+                        tx_len -= pkt_len;
+                        continue;
+                }
+
+                esp_sip_dbg(ESP_DBG_TRACE, "%s:before sub, credits is %d\n", __func__, atomic_read(&sip->tx_credits));
+                atomic_sub(blknum, &sip->tx_credits);
+                esp_sip_dbg(ESP_DBG_TRACE, "%s:after sub %d,credits remains %d\n", __func__, blknum, atomic_read(&sip->tx_credits));
+
+        }
+
+        if (queued_back) {
+                skb_queue_head(&epub->txq, skb);
+        }
+
+        if (atomic_read(&sip->state) == SIP_STOP 
+#ifdef HOST_RESET_BUG
+               || atomic_read(&epub->wl.off) == 1
+#endif
+               )
+       {
+               queued_back = 1;
+               tx_len = 0;
+                sip_after_write_pkts(sip);
+       }
+
+        if (tx_len) {
+       
+               sip_write_pkts(sip, pm_state);
+
+                sip_after_write_pkts(sip);
+        }
+
+        if (queued_back && !out_of_credits) {
+
+                /* skb pending, do async process again */
+                //     if (!skb_queue_empty(&epub->txq))
+                sip_trigger_txq_process(sip);
+        }
+}
+
+static void sip_after_write_pkts(struct esp_sip *sip)
+{
+        //enable txq
+#if 0
+        if (atomic_read(&sip->epub->txq_stopped) == true && sip_queue_may_resume(sip)) {
+                atomic_set(&sip->epub->txq_stopped, false);
+                ieee80211_wake_queues(sip->epub->hw);
+                esp_sip_dbg(ESP_DBG_TRACE, "%s resume ieee80211 tx \n", __func__);
+        }
+#endif
+
+#ifndef FAST_TX_NOWAIT
+        sip_txdoneq_process(sip);
+#endif
+        //disable tx_data
+#ifndef FAST_TX_STATUS
+        if (atomic_read(&sip->data_tx_stopped) == false && sip_tx_data_need_stop(sip)) {
+                esp_sip_dbg(ESP_DBG_TRACE, "%s data_tx_stopped \n", __func__);
+                atomic_set(&sip->data_tx_stopped, true);
+        }
+#endif /* FAST_TX_STATUS */
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+/*
+ * old mac80211 (2.6.32.x) needs payload is 4 byte aligned, thus we need this hack.
+ * TBD: However, the latest mac80211 stack does not need this. we may
+ * need to check kernel version here...
+ */
+static void sip_check_skb_alignment(struct sk_buff *skb)
+{
+        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+        int hdrlen;
+
+        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+#if 0
+
+        /* TBD */
+        if (rx->flags & IEEE80211_RX_AMSDU)
+                hdrlen += ETH_HLEN;
+
+#endif
+
+        if (unlikely(((unsigned long)(skb->data + hdrlen)) & 3)) {
+
+                esp_sip_dbg(ESP_DBG_TRACE, "%s adjust skb data postion \n", __func__);
+                skb_push(skb, 2);
+                memmove(skb->data, skb->data+2, skb->len-2);
+                skb_trim(skb, skb->len-2);
+        }
+}
+#endif /* !NEW_KERNEL */
+
+int sip_channel_value_inconsistency(u8 *start, size_t len, unsigned channel)
+{
+        size_t left = len;
+        u8 *pos = start;
+        u8 *DS_Param = NULL;
+        u8 channel_parsed = 0xff;
+        bool found = false;
+        u8 ssid[33];
+
+        while(left >=2 && !found) {
+                u8 id, elen;
+                id = *pos++;
+                elen = *pos++;
+                left -= 2;
+
+                if(elen > left)
+                        break;
+
+                switch (id) {
+                case WLAN_EID_SSID:
+                        ASSERT(elen < 33);
+                        memcpy(ssid, pos, elen);
+                        ssid[elen] = 0;
+                        esp_sip_dbg(ESP_DBG_TRACE, "ssid:%s\n", ssid);
+                        break;
+                case WLAN_EID_SUPP_RATES:
+                        break;
+                case WLAN_EID_FH_PARAMS:
+                        break;
+                case WLAN_EID_DS_PARAMS:
+                        DS_Param = pos;
+                        found = true;
+                        break;
+                default:
+                        break;
+                }
+
+                left -= elen;
+                pos += elen;
+        }
+
+        if (DS_Param) {
+                channel_parsed = DS_Param[0];
+        } else {
+                esp_dbg(ESP_DBG_ERROR, "DS_Param not found\n");
+                return -1;
+        }
+
+        return channel_parsed != channel;
+}
+
+/*  parse mac_rx_ctrl and return length */
+static int sip_parse_mac_rx_info(struct esp_sip *sip, struct esp_mac_rx_ctrl * mac_ctrl, struct sk_buff *skb)
+{
+        struct ieee80211_rx_status *rx_status = NULL;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+        rx_status = IEEE80211_SKB_RXCB(skb);
+#else
+        rx_status = (struct ieee80211_rx_status *)skb->cb;
+#endif
+        rx_status->freq = esp_ieee2mhz(mac_ctrl->channel);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+        rx_status->signal = mac_ctrl->rssi + sip->noise_floor;  /* snr actually, need to offset noise floor e.g. -85 */
+#else
+        rx_status->signal = mac_ctrl->rssi;  /* snr actually, need to offset noise floor e.g. -85 */
+#endif /* NEW_KERNEL */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35))
+#define ESP_RSSI_MIN_RSSI (-90)
+#define ESP_RSSI_MAX_RSSI (-45)
+        rx_status->noise = 0;  /* TBD */
+        rx_status->qual = (mac_ctrl->rssi - ESP_RSSI_MIN_RSSI)* 100/(ESP_RSSI_MAX_RSSI - ESP_RSSI_MIN_RSSI);
+        rx_status->qual = min(rx_status->qual, 100);
+        rx_status->qual = max(rx_status->qual, 0);
+#undef ESP_RSSI_MAX_RSSI
+#undef ESP_RSSI_MIN_RSSI
+#endif /* !NEW_KERNEL && KERNEL_35*/
+        rx_status->antenna = 0;  /* one antenna for now */
+        rx_status->band = IEEE80211_BAND_2GHZ;
+        rx_status->flag = RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED;
+        if (mac_ctrl->sig_mode) {
+            // 2.6.27 has RX_FLAG_RADIOTAP in enum mac80211_rx_flags in include/net/mac80211.h
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))                
+                rx_status->flag |= RX_FLAG_HT;
+                rx_status->rate_idx = mac_ctrl->MCS;
+                if(mac_ctrl->SGI)
+                        rx_status->flag |= RX_FLAG_SHORT_GI;
+#else
+                rx_status->rate_idx = esp_wmac_rate2idx(0xc);//ESP_RATE_54
+#endif
+        } else {
+                rx_status->rate_idx = esp_wmac_rate2idx(mac_ctrl->rate);
+        }
+        if (mac_ctrl->rxend_state == RX_FCS_ERR)
+                rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+
+        /* Mic error frame flag */
+        if (mac_ctrl->rxend_state == RX_TKIPMIC_ERR || mac_ctrl->rxend_state == RX_CCMPMIC_ERR){
+                if(atomic_read(&sip->epub->wl.tkip_key_set) == 1){
+                       rx_status->flag|= RX_FLAG_MMIC_ERROR;
+                       atomic_set(&sip->epub->wl.tkip_key_set, 0);
+                       printk("mic err\n");
+               } else {
+                       printk("mic err discard\n");
+               }
+       }
+
+        //esp_dbg(ESP_DBG_LOG, "%s freq: %u; signal: %d;  rate_idx %d; flag: %d \n", __func__, rx_status->freq, rx_status->signal, rx_status->rate_idx, rx_status->flag);
+
+        do {
+                struct ieee80211_hdr * wh = (struct ieee80211_hdr *)((u8 *)skb->data);
+
+                if (ieee80211_is_beacon(wh->frame_control) || ieee80211_is_probe_resp(wh->frame_control)) {
+                        struct ieee80211_mgmt * mgmt = (struct ieee80211_mgmt *)((u8 *)skb->data);
+                        u8 *start = NULL;
+                        size_t baselen, len = skb->len;
+                        int inconsistency = 0;
+
+                        if (ieee80211_is_beacon(wh->frame_control)) {
+                                start = mgmt->u.beacon.variable;
+                                baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+                                bcn_counter++;
+                        } else if(ieee80211_is_probe_resp(wh->frame_control)) {
+                                start = mgmt->u.probe_resp.variable;
+                                baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
+                                probe_rsp_counter++;
+                        }
+
+                        if (baselen > len)
+                                return -1;
+
+                        inconsistency = sip_channel_value_inconsistency(start, len-baselen, mac_ctrl->channel);
+
+                        if (inconsistency) {
+                                return -1;
+                        }
+                }
+
+#ifdef KERNEL_IV_WAR
+               /* some kernel e.g. 3.0.8 wrongly handles non-encrypted pkt like eapol */
+               if (ieee80211_is_data(wh->frame_control)) {
+                        if( !ieee80211_has_protected(wh->frame_control)) {
+                                esp_sip_dbg(ESP_DBG_TRACE, "%s kiv_war, add iv_stripped flag \n", __func__);
+                                rx_status->flag |= RX_FLAG_IV_STRIPPED;
+                        } else {
+                                if ((atomic_read(&sip->epub->wl.ptk_cnt) == 0 && !(wh->addr1[0] & 0x1)) || 
+                                       (atomic_read(&sip->epub->wl.gtk_cnt) == 0 && (wh->addr1[0] & 0x1))) 
+                               {
+                                        esp_dbg(ESP_DBG_TRACE, "%s ==kiv_war, got bogus enc pkt==\n", __func__);
+                                        rx_status->flag |= RX_FLAG_IV_STRIPPED;
+                                        //show_buf(skb->data, 32);
+                                }
+
+                                esp_sip_dbg(ESP_DBG_TRACE, "%s kiv_war, got enc pkt \n", __func__);
+                        }
+                }
+#endif /* KERNEL_IV_WAR*/
+        } while (0);
+
+        return 0;
+}
+
+static struct esp_mac_rx_ctrl *sip_parse_normal_mac_ctrl(struct sk_buff *skb, int * pkt_len_enc, int *buf_len, int *pulled_len) 
+{
+        struct esp_mac_rx_ctrl *mac_ctrl = NULL;
+        struct sip_hdr *hdr =(struct sip_hdr *)skb->data;
+        int len_in_hdr = hdr->len;
+
+        ASSERT(skb != NULL);
+        ASSERT(skb->len > SIP_MIN_DATA_PKT_LEN);
+
+        skb_pull(skb, sizeof(struct sip_hdr));
+        *pulled_len += sizeof(struct sip_hdr);
+        mac_ctrl = (struct esp_mac_rx_ctrl *)skb->data;
+        if(!mac_ctrl->Aggregation) {
+                ASSERT(pkt_len_enc != NULL);
+                ASSERT(buf_len != NULL);
+                *pkt_len_enc = (mac_ctrl->sig_mode?mac_ctrl->HT_length:mac_ctrl->legacy_length) - FCS_LEN;
+                *buf_len = len_in_hdr - sizeof(struct sip_hdr) - sizeof(struct esp_mac_rx_ctrl);
+        }
+        skb_pull(skb, sizeof(struct esp_mac_rx_ctrl));
+        *pulled_len += sizeof(struct esp_mac_rx_ctrl);
+
+        return mac_ctrl;
+}
+
+/*
+ * for one MPDU (including subframe in AMPDU)
+ *
+ */
+static struct sk_buff * sip_parse_data_rx_info(struct esp_sip *sip, struct sk_buff *skb, int pkt_len_enc, int buf_len, struct esp_mac_rx_ctrl *mac_ctrl, int *pulled_len) {
+        /*
+         *   | mac_rx_ctrl | real_data_payload | ampdu_entries |
+         */
+        //without enc
+        int pkt_len = 0;
+        struct sk_buff *rskb = NULL;
+        int ret;
+
+        if (mac_ctrl->Aggregation) {
+                struct ieee80211_hdr * wh = (struct ieee80211_hdr *)skb->data;
+                pkt_len = pkt_len_enc;
+                if (ieee80211_has_protected(wh->frame_control))//ampdu, it is CCMP enc
+                        pkt_len -= 8;
+                buf_len = roundup(pkt_len, 4);
+        } else
+                pkt_len  = buf_len - 3 + ((pkt_len_enc - 1) & 0x3);
+        esp_dbg(ESP_DBG_TRACE, "%s pkt_len %u, pkt_len_enc %u!, delta %d \n", __func__, pkt_len, pkt_len_enc, pkt_len_enc - pkt_len);
+        do {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+                rskb = __dev_alloc_skb(pkt_len_enc + 2, GFP_ATOMIC);
+#else
+                rskb = __dev_alloc_skb(pkt_len_enc, GFP_ATOMIC);
+#endif/* NEW_KERNEL */
+                if (unlikely(rskb == NULL)) {
+                        esp_sip_dbg(ESP_DBG_ERROR, "%s no mem for rskb\n", __func__);
+                        return NULL;
+                }
+                skb_put(rskb, pkt_len_enc);
+        } while(0);
+
+        do {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+                do {
+                        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+                        int hdrlen;
+
+                        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+                        if (unlikely(((unsigned long)(rskb->data + hdrlen)) & 3)) {
+                                skb_put(rskb, 2);
+                                skb_pull(rskb, 2);
+                        }
+                } while(0);
+#endif /* < KERNEL_VERSION(2, 6, 39) */
+                memcpy(rskb->data, skb->data, pkt_len);
+                if (pkt_len_enc > pkt_len) {
+                        memset(rskb->data + pkt_len, 0, pkt_len_enc - pkt_len);
+                }
+                /* strip out current pkt, move to the next one */
+                skb_pull(skb, buf_len);
+                *pulled_len += buf_len;
+        } while (0);
+
+        ret = sip_parse_mac_rx_info(sip, mac_ctrl, rskb);
+        if(ret == -1 && !mac_ctrl->Aggregation) {
+                kfree_skb(rskb);
+                return NULL;
+        }
+
+        esp_dbg(ESP_DBG_LOG, "%s after pull headers, skb->len %d rskb->len %d \n", __func__, skb->len, rskb->len);
+
+        return rskb;
+}
+
+struct esp_sip * sip_attach(struct esp_pub *epub) 
+{
+        struct esp_sip *sip = NULL;
+        struct sip_pkt *pkt = NULL;
+        int i;
+
+        sip = kzalloc(sizeof(struct esp_sip), GFP_KERNEL);
+        ASSERT(sip != NULL);
+
+#ifdef ESP_RX_COPYBACK_TEST
+        /* alloc 64KB for rx test */
+        copyback_buf = kzalloc(0x10000, GFP_KERNEL);
+#endif /* ESP_RX_COPYBACK_TEST */
+
+        spin_lock_init(&sip->lock);
+
+        INIT_LIST_HEAD(&sip->free_ctrl_txbuf);
+        INIT_LIST_HEAD(&sip->free_ctrl_rxbuf);
+
+        for (i = 0; i < SIP_CTRL_BUF_N; i++) {
+                pkt = kzalloc(sizeof(struct sip_pkt), GFP_KERNEL);
+
+                if (!pkt) break;
+
+                pkt->buf_begin = kzalloc(SIP_CTRL_BUF_SZ, GFP_KERNEL);
+
+                if (pkt->buf_begin == NULL) {
+                        kfree(pkt);
+                        break;
+                }
+
+                pkt->buf_len = SIP_CTRL_BUF_SZ;
+                pkt->buf = pkt->buf_begin;
+
+                if (i < SIP_CTRL_TXBUF_N) {
+                        list_add_tail(&pkt->list, &sip->free_ctrl_txbuf);
+                } else {
+                        list_add_tail(&pkt->list, &sip->free_ctrl_rxbuf);
+                }
+        }
+
+        spin_lock_init(&sip->rx_lock);
+        skb_queue_head_init(&sip->rxq);
+#ifndef RX_SYNC
+        INIT_WORK(&sip->rx_process_work, sip_rxq_process);
+#endif/* RX_SYNC */
+
+        sip->epub = epub;
+       sip->noise_floor = -96;
+
+        atomic_set(&sip->state, SIP_INIT);
+       atomic_set(&sip->tx_credits, 0);
+
+        return sip;
+}
+
+static void sip_free_init_ctrl_buf(struct esp_sip *sip)
+{
+        struct sip_pkt *pkt, *tpkt;
+
+        list_for_each_entry_safe(pkt, tpkt,
+                                 &sip->free_ctrl_txbuf, list) {
+                list_del(&pkt->list);
+                kfree(pkt->buf_begin);
+                kfree(pkt);
+        }
+
+        list_for_each_entry_safe(pkt, tpkt,
+                                 &sip->free_ctrl_rxbuf, list) {
+                list_del(&pkt->list);
+                kfree(pkt->buf_begin);
+                kfree(pkt);
+        }
+}
+
+void sip_detach(struct esp_sip *sip)
+{
+        int po;
+
+        sip_free_init_ctrl_buf(sip);
+
+        if (atomic_read(&sip->state) == SIP_RUN) {
+
+                sif_disable_target_interrupt(sip->epub);
+
+                atomic_set(&sip->state, SIP_STOP);
+
+                /* disable irq here */
+                sif_disable_irq(sip->epub);
+#ifndef RX_SYNC
+                cancel_work_sync(&sip->rx_process_work);
+#endif/* RX_SYNC */
+
+                skb_queue_purge(&sip->rxq);
+                cancel_work_sync(&sip->epub->sendup_work);
+                skb_queue_purge(&sip->epub->rxq);
+
+#ifdef ESP_NO_MAC80211
+                unregister_netdev(sip->epub->net_dev);
+                wiphy_unregister(sip->epub->wdev->wiphy);
+#else
+                if (test_and_clear_bit(ESP_WL_FLAG_HW_REGISTERED, &sip->epub->wl.flags)) {
+                        ieee80211_unregister_hw(sip->epub->hw);
+                }
+#endif
+
+                /* cancel all worker/timer */
+                cancel_work_sync(&sip->epub->tx_work);
+                skb_queue_purge(&sip->epub->txq);
+                skb_queue_purge(&sip->epub->txdoneq);
+
+                po = get_order(SIP_TX_AGGR_BUF_SIZE);
+                free_pages((unsigned long)sip->tx_aggr_buf, po);
+                sip->tx_aggr_buf = NULL;
+#if 0
+                po = get_order(SIP_RX_AGGR_BUF_SIZE);
+                free_pages((unsigned long)sip->rx_aggr_buf, po);
+                sip->rx_aggr_buf = NULL;
+#endif
+                atomic_set(&sip->state, SIP_INIT);
+        } else if (atomic_read(&sip->state) >= SIP_BOOT && atomic_read(&sip->state) <= SIP_WAIT_BOOTUP) {
+
+                sif_disable_target_interrupt(sip->epub);
+                atomic_set(&sip->state, SIP_STOP);
+                sif_disable_irq(sip->epub);
+
+                if (sip->rawbuf)
+                        kfree(sip->rawbuf);
+
+                if (atomic_read(&sip->state) == SIP_SEND_INIT) {
+#ifndef RX_SYNC
+                        cancel_work_sync(&sip->rx_process_work);
+#endif/* RX_SYNC */
+                        skb_queue_purge(&sip->rxq);
+                        cancel_work_sync(&sip->epub->sendup_work);
+                        skb_queue_purge(&sip->epub->rxq);
+                }
+
+#ifdef ESP_NO_MAC80211
+                unregister_netdev(sip->epub->net_dev);
+                wiphy_unregister(sip->epub->wdev->wiphy);
+#else
+                if (test_and_clear_bit(ESP_WL_FLAG_HW_REGISTERED, &sip->epub->wl.flags)) {
+                        ieee80211_unregister_hw(sip->epub->hw);
+                }
+#endif
+                        atomic_set(&sip->state, SIP_INIT);
+        } else
+                esp_dbg(ESP_DBG_ERROR, "%s wrong state %d\n", __func__, atomic_read(&sip->state));
+
+        kfree(sip);
+}
+
+int sip_prepare_boot(struct esp_sip *sip)
+{
+        if (atomic_read(&sip->state) != SIP_INIT) {
+                esp_dbg(ESP_DBG_ERROR, "%s wrong state %d\n", __func__, atomic_read(&sip->state));
+                return -1;
+        }
+
+        if (sip->rawbuf == NULL) {
+                sip->rawbuf = kzalloc(SIP_BOOT_BUF_SIZE, GFP_KERNEL);
+
+                if (sip->rawbuf == NULL)
+                        return -ENOMEM;
+        }
+
+        atomic_set(&sip->state, SIP_PREPARE_BOOT);
+        
+       return 0;
+}
+
+int sip_write_memory(struct esp_sip *sip, u32 addr, u8 *buf, u16 len)
+{
+        struct sip_cmd_write_memory *cmd;
+        struct sip_hdr *chdr;
+        u16 remains, hdrs, bufsize;
+        u32 loadaddr;
+        u8 *src;
+        int err = 0;
+        u32 *t = 0;
+
+        ASSERT(sip->rawbuf != NULL);
+
+        memset(sip->rawbuf, 0, SIP_BOOT_BUF_SIZE);
+
+        chdr = (struct sip_hdr *)sip->rawbuf;
+        SIP_HDR_SET_TYPE(chdr->fc[0], SIP_CTRL);
+        chdr->c_cmdid = SIP_CMD_WRITE_MEMORY;
+
+        remains = len;
+        hdrs = sizeof(struct sip_hdr) + sizeof(struct sip_cmd_write_memory);
+
+        while (remains) {
+                src = &buf[len - remains];
+                loadaddr = addr + (len - remains);
+
+                if (remains < (SIP_BOOT_BUF_SIZE - hdrs)) {
+                        /* aligned with 4 bytes */
+                        bufsize = roundup(remains, 4);
+                        memset(sip->rawbuf + hdrs, 0, bufsize);
+                        remains = 0;
+                } else {
+                        bufsize = SIP_BOOT_BUF_SIZE - hdrs;
+                        remains -=  bufsize;
+                }
+
+                chdr->len = bufsize + hdrs;
+                chdr->seq = sip->txseq++;
+                cmd = (struct sip_cmd_write_memory *)(sip->rawbuf + SIP_CTRL_HDR_LEN);
+                cmd->len = bufsize;
+                cmd->addr = loadaddr;
+                memcpy(sip->rawbuf+hdrs, src, bufsize);
+
+                t = (u32 *)sip->rawbuf;
+                esp_dbg(ESP_DBG_TRACE, "%s t0: 0x%08x t1: 0x%08x t2:0x%08x loadaddr 0x%08x \n", __func__, t[0], t[1], t[2], loadaddr);
+
+                               err = esp_common_write(sip->epub, sip->rawbuf, chdr->len, ESP_SIF_SYNC);
+
+                if (err) {
+                        esp_dbg(ESP_DBG_ERROR, "%s send buffer failed\n", __func__);
+                        return err;
+                }
+
+                // 1ms is enough, in fact on dell-d430, need not delay at all.
+                mdelay(1);
+
+                sip_dec_credit(sip);
+        }
+
+        return err;
+}
+
+int sip_send_cmd(struct esp_sip *sip, int cid, u32 cmdlen, void *cmd)
+{
+        struct sip_hdr *chdr;
+        struct sip_pkt *pkt = NULL;
+        int ret = 0;
+
+        pkt = sip_get_ctrl_buf(sip, SIP_TX_CTRL_BUF);
+
+        if (pkt == NULL)
+                return -ENOMEM;
+
+        chdr = (struct sip_hdr *)pkt->buf_begin;
+        chdr->len = SIP_CTRL_HDR_LEN + cmdlen;
+        chdr->seq = sip->txseq++;
+        chdr->c_cmdid = cid;
+       
+
+       if (cmd) {
+               memset(pkt->buf, 0, cmdlen);
+               memcpy(pkt->buf, (u8 *)cmd, cmdlen);
+       }
+
+        esp_dbg(ESP_DBG_TRACE, "cid %d, len %u, seq %u \n", chdr->c_cmdid, chdr->len, chdr->seq);
+
+        esp_dbg(ESP_DBG_TRACE, "c1 0x%08x   c2 0x%08x\n", *(u32 *)&pkt->buf[0], *(u32 *)&pkt->buf[4]);
+
+               ret = esp_common_write(sip->epub, pkt->buf_begin, chdr->len, ESP_SIF_SYNC);
+
+        if (ret)
+                esp_dbg(ESP_DBG_ERROR, "%s send cmd %d failed \n", __func__, cid);
+
+        sip_dec_credit(sip);
+
+        sip_reclaim_ctrl_buf(sip, pkt, SIP_TX_CTRL_BUF);
+
+        /*
+         *  Hack here: reset tx/rx seq before target ram code is up...
+         */
+        if (cid == SIP_CMD_BOOTUP) {
+                sip->rxseq = 0;
+                sip->txseq = 0;
+               sip->txdataseq = 0;
+        }
+
+        return ret;
+}
+
+struct sk_buff *
+sip_alloc_ctrl_skbuf(struct esp_sip *sip, u16 len, u32 cid) {
+        struct sip_hdr *si = NULL;
+        struct ieee80211_tx_info *ti = NULL;
+        struct sk_buff *skb = NULL;
+
+        ASSERT(len <= sip->tx_blksz);
+
+        /* no need to reserve space for net stack */
+        skb = __dev_alloc_skb(len, GFP_KERNEL);
+
+        if (skb == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "no skb for ctrl !\n");
+                return NULL;
+        }
+
+        skb->len = len;
+
+        ti = IEEE80211_SKB_CB(skb);
+        /* set tx_info flags to 0xffffffff to indicate sip_ctrl pkt */
+        ti->flags = 0xffffffff;
+        si = (struct sip_hdr *)skb->data;
+        memset(si, 0, sizeof(struct sip_hdr));
+        SIP_HDR_SET_TYPE(si->fc[0], SIP_CTRL);
+        si->len = len;
+        si->c_cmdid = cid;
+
+        return skb;
+}
+
+void
+sip_free_ctrl_skbuff(struct esp_sip *sip, struct sk_buff *skb)
+{
+        memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info));
+        kfree_skb(skb);
+}
+
+static struct sip_pkt *
+sip_get_ctrl_buf(struct esp_sip *sip, SIP_BUF_TYPE bftype) {
+        struct sip_pkt *pkt = NULL;
+        struct list_head *bflist;
+        struct sip_hdr *chdr;
+
+        bflist = (bftype == SIP_TX_CTRL_BUF) ? &sip->free_ctrl_txbuf :&sip->free_ctrl_rxbuf;
+
+        spin_lock_bh(&sip->lock);
+
+        if (list_empty(bflist)) {
+                spin_unlock_bh(&sip->lock);
+                return NULL;
+        }
+
+        pkt = list_first_entry(bflist, struct sip_pkt, list);
+        list_del(&pkt->list);
+        spin_unlock_bh(&sip->lock);
+
+        if (bftype == SIP_TX_CTRL_BUF) {
+                chdr = (struct sip_hdr *)pkt->buf_begin;
+                SIP_HDR_SET_TYPE(chdr->fc[0], SIP_CTRL);
+                pkt->buf = pkt->buf_begin + SIP_CTRL_HDR_LEN;
+        } else {
+                pkt->buf = pkt->buf_begin;
+        }
+
+        return pkt;
+}
+
+static void
+sip_reclaim_ctrl_buf(struct esp_sip *sip, struct sip_pkt *pkt, SIP_BUF_TYPE bftype)
+{
+        struct list_head *bflist = NULL;
+
+        if (bftype == SIP_TX_CTRL_BUF)
+                bflist = &sip->free_ctrl_txbuf;
+        else if (bftype == SIP_RX_CTRL_BUF)
+                bflist = &sip->free_ctrl_rxbuf;
+        else return;
+
+        pkt->buf = pkt->buf_begin;
+        pkt->payload_len = 0;
+
+        spin_lock_bh(&sip->lock);
+        list_add_tail(&pkt->list, bflist);
+        spin_unlock_bh(&sip->lock);
+}
+
+int
+sip_poll_bootup_event(struct esp_sip *sip)
+{
+       int ret = 0;
+
+        esp_dbg(ESP_DBG_TRACE, "polling bootup event... \n");
+
+       if (gl_bootup_cplx)
+               ret = wait_for_completion_timeout(gl_bootup_cplx, 2 * HZ);
+
+       esp_dbg(ESP_DBG_TRACE, "******time remain****** = [%d]\n", ret);
+       if (ret <= 0) {
+               esp_dbg(ESP_DBG_ERROR, "bootup event timeout\n");
+               return ret;
+       }       
+
+#ifndef FPGA_LOOPBACK
+        ret = esp_register_mac80211(sip->epub);
+#endif /* !FPGA_LOOPBACK */
+
+#ifdef TEST_MODE
+        ret = test_init_netlink(sip);
+        if (ret < 0) {
+                esp_sip_dbg(ESP_DBG_TRACE, "esp_sdio: failed initializing netlink\n");
+               return ret;
+       }
+#endif
+        
+       atomic_set(&sip->state, SIP_RUN);
+        esp_dbg(ESP_DBG_TRACE, "target booted up\n");
+
+       return ret;
+}
+
+int
+sip_poll_resetting_event(struct esp_sip *sip)
+{
+       int ret = 0;
+
+        esp_dbg(ESP_DBG_TRACE, "polling resetting event... \n");
+
+       if (gl_bootup_cplx)
+               ret = wait_for_completion_timeout(gl_bootup_cplx, 10 * HZ);
+
+       esp_dbg(ESP_DBG_TRACE, "******time remain****** = [%d]\n", ret);
+       if (ret <= 0) {
+               esp_dbg(ESP_DBG_ERROR, "resetting event timeout\n");
+               return ret;
+       }       
+      
+        esp_dbg(ESP_DBG_TRACE, "target resetting %d %p\n", ret, gl_bootup_cplx);
+
+       return ret;
+}
+
+
+#ifdef FPGA_DEBUG
+
+/* bogus bootup cmd for FPGA debugging */
+int
+sip_send_bootup(struct esp_sip *sip)
+{
+        int ret;
+        struct sip_cmd_bootup bootcmd;
+
+        esp_dbg(ESP_DBG_LOG, "sending bootup\n");
+
+        bootcmd.boot_addr = 0;
+        ret = sip_send_cmd(sip, SIP_CMD_BOOTUP, sizeof(struct sip_cmd_bootup), &bootcmd);
+
+        return ret;
+}
+
+#endif /* FPGA_DEBUG */
+
+bool
+sip_queue_need_stop(struct esp_sip *sip)
+{
+        return atomic_read(&sip->tx_data_pkt_queued) >= SIP_STOP_QUEUE_THRESHOLD
+               || (atomic_read(&sip->tx_credits) < 8
+               && atomic_read(&sip->tx_data_pkt_queued) >= SIP_STOP_QUEUE_THRESHOLD / 4 * 3);
+}
+
+bool
+sip_queue_may_resume(struct esp_sip *sip)
+{
+       return atomic_read(&sip->epub->txq_stopped)
+               && !test_bit(ESP_WL_FLAG_STOP_TXQ, &sip->epub->wl.flags)
+               && ((atomic_read(&sip->tx_credits) >= 16
+               && atomic_read(&sip->tx_data_pkt_queued) < SIP_RESUME_QUEUE_THRESHOLD * 2)
+               || atomic_read(&sip->tx_data_pkt_queued) < SIP_RESUME_QUEUE_THRESHOLD);
+}
+
+#ifndef FAST_TX_STATUS
+bool
+sip_tx_data_need_stop(struct esp_sip *sip)
+{
+        return atomic_read(&sip->pending_tx_status) >= SIP_PENDING_STOP_TX_THRESHOLD;
+}
+
+bool
+sip_tx_data_may_resume(struct esp_sip *sip)
+{
+        return atomic_read(&sip->pending_tx_status) < SIP_PENDING_RESUME_TX_THRESHOLD;
+}
+#endif /* FAST_TX_STATUS */
+
+int
+sip_cmd_enqueue(struct esp_sip *sip, struct sk_buff *skb)
+{
+       if (!sip || !sip->epub) {
+               esp_dbg(ESP_DBG_ERROR, "func %s, sip->epub->txq is NULL\n", __func__);
+               return -1;
+       }
+       
+       if (!skb) {
+               esp_dbg(ESP_DBG_ERROR, "func %s, skb is NULL\n", __func__);
+               return -2;
+       }
+
+        skb_queue_tail(&sip->epub->txq, skb);
+
+#if  !defined(FPGA_LOOPBACK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+        ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work);
+#else
+        queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
+#endif
+        return 0;
+}
+
+void sip_tx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb)
+{
+       if(!epub || !epub->sip) {
+               if (!epub)
+                       esp_dbg(ESP_DBG_ERROR, "func %s, epub is NULL\n", __func__);
+               else
+                       esp_dbg(ESP_DBG_ERROR, "func %s, epub->sip is NULL\n", __func__);
+
+               return;
+       }
+       if (!skb) {
+                esp_dbg(ESP_DBG_ERROR, "func %s, skb is NULL\n", __func__);
+                return;
+        }
+        skb_queue_tail(&epub->txq, skb);
+        atomic_inc(&epub->sip->tx_data_pkt_queued);
+       if(sip_queue_need_stop(epub->sip)){
+               if (epub->hw) {
+                       ieee80211_stop_queues(epub->hw);
+                       atomic_set(&epub->txq_stopped, true);
+               }
+
+       }
+}
+
+#ifdef FPGA_TXDATA
+int sip_send_tx_data(struct esp_sip *sip)
+{
+        struct sk_buff *skb = NULL;
+        struct sip_cmd_bss_info_update*bsscmd;
+
+        skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_bss_info_update), SIP_CMD_BSS_INFO_UPDATE);
+        if (!skb)
+                return -1;
+
+        bsscmd = (struct sip_cmd_bss_info_update *)(skb->data + sizeof(struct sip_tx_info));
+        bsscmd->isassoc= (assoc==true)? 1: 0;
+        memcpy(bsscmd->bssid, bssid, ETH_ALEN);
+        STRACE_SHOW(epub->sip);
+        return sip_cmd_enqueue(epub->sip, skb);
+}
+#endif /* FPGA_TXDATA */
+
+#ifdef SIP_DEBUG
+void sip_dump_pending_data(struct esp_pub *epub)
+{
+#if 0
+        struct sk_buff *tskb, *tmp;
+
+        skb_queue_walk_safe(&epub->txdoneq, tskb, tmp) {
+                show_buf(tskb->data, 32);
+        }
+#endif //0000
+}
+#else
+void sip_dump_pending_data(struct esp_pub *epub)
+{}
+#endif /* SIP_DEBUG */
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_sip.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_sip.h
new file mode 100755 (executable)
index 0000000..118d863
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  Copyright (c) 2009- 2012 Espressif System.
+ *
+ *    Serial Interconnctor Protocol
+ */
+
+#ifndef _ESP_SIP_H
+#define _ESP_SIP_H
+
+#include "sip2_common.h"
+
+#define SIP_PKT_MAX_LEN (1024*16)
+
+/* 16KB on normal X86 system, should check before porting to orhters */
+
+#define SIP_TX_AGGR_BUF_SIZE (4 * PAGE_SIZE)
+#define SIP_RX_AGGR_BUF_SIZE (4 * PAGE_SIZE)
+
+struct sk_buff;
+
+struct sip_pkt {
+        struct list_head list;
+
+        u8 * buf_begin;
+        u32  buf_len;
+        u8 * buf;
+        u32  payload_len;
+#if 0
+        union {
+                struct sip_tx_pkt_info tx;
+                struct sip_rx_pkt_info rx;
+        } info;
+#endif
+        void *context;
+        int status;
+        //void (* completion)(struct esp_sip *sip, struct sip_pkt *pkt);
+};
+
+typedef enum SIP_STATE {
+        SIP_INIT = 0,
+       SIP_PREPARE_BOOT,
+        SIP_BOOT,
+       SIP_SEND_INIT,
+       SIP_WAIT_BOOTUP,
+        SIP_RUN,
+        SIP_SUSPEND,
+        SIP_STOP
+} SIP_STATE;
+
+enum sip_notifier {
+        SIP_TX_DONE = 1,
+        SIP_RX_DONE = 2,
+};
+
+#define SIP_CREDITS_LOW_THRESHOLD  64  //i.e. 4k
+
+struct esp_sip {
+        struct list_head free_ctrl_txbuf;
+        struct list_head free_ctrl_rxbuf;
+
+        u32 rxseq; /* sip pkt seq, should match target side */
+        u32 txseq;
+       u32 txdataseq;
+
+        atomic_t state;
+        spinlock_t lock;
+        int boot_credits;
+        atomic_t tx_credits;
+
+        atomic_t tx_ask_credit_update;
+
+        u8 * rawbuf;  /* used in boot stage, free once chip is fully up */
+        u8 * tx_aggr_buf;
+        u8 * tx_aggr_write_ptr;  /* update after insertion of each pkt */
+        u8 * tx_aggr_lastpkt_ptr;
+#if 0
+        u8 * rx_aggr_buf;
+        u8 * rx_aggr_write_ptr;
+        u8 * rx_aggr_lastpkt_ptr;
+#endif
+
+        spinlock_t rx_lock;
+        struct sk_buff_head rxq;
+#ifndef RX_SYNC
+        struct work_struct rx_process_work;
+#endif/* RX_SYNC */
+
+        u16 tx_blksz;
+        u16 rx_blksz;
+
+        bool dump_rpbm_err;
+        bool sendup_rpbm_pkt;
+        bool rxabort_fixed;
+        bool support_bgscan;
+        u8 credit_to_reserve;
+       s16 noise_floor;
+
+        u32 tx_tot_len; /* total len for one transaction */
+        u32 rx_tot_len;
+
+        atomic_t rx_handling;
+        atomic_t tx_data_pkt_queued;
+
+#ifndef FAST_TX_STATUS
+        atomic_t pending_tx_status;
+#endif /* !FAST_TX_STATUS */
+
+        atomic_t data_tx_stopped;
+        atomic_t tx_stopped;
+
+        struct esp_pub *epub;
+};
+
+int sip_rx(struct esp_pub * epub);
+//int sip_download_fw(struct esp_sip *sip, u32 load_addr, u32 boot_addr);
+
+/* tx must pad as 4-byte aligned */
+int sip_tx(struct esp_pub * epub, struct sip_pkt *pkt);
+
+int sip_get_raw_credits(struct esp_sip *);
+
+int sip_write_memory(struct esp_sip *, u32 addr, u8* buf, u16 len);
+
+void sip_credit_process(struct esp_pub *, u8 credits);
+
+int sip_prepare_boot(struct esp_sip *sip);
+
+int sip_send_cmd(struct esp_sip *sip, int cid, u32 cmdlen, void * cmd);
+
+struct esp_sip * sip_attach(struct esp_pub *);
+
+int sip_post_init(struct esp_sip *sip, struct sip_evt_bootup2 *bevt);
+
+void sip_detach(struct esp_sip *sip);
+
+void sip_txq_process(struct esp_pub *epub);
+
+struct sk_buff * sip_alloc_ctrl_skbuf(struct esp_sip *sip, u16 len, u32 cid);
+
+void sip_free_ctrl_skbuff(struct esp_sip *sip, struct sk_buff* skb);
+
+bool sip_queue_need_stop(struct esp_sip *sip);
+bool sip_queue_may_resume(struct esp_sip *sip);
+bool sip_tx_data_need_stop(struct esp_sip *sip);
+bool sip_tx_data_may_resume(struct esp_sip *sip);
+
+void sip_tx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb);
+void sip_rx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb);
+
+int sip_cmd_enqueue(struct esp_sip *sip, struct sk_buff *skb);
+
+void sip_dump_pending_data(struct esp_pub *epub);
+
+int sip_poll_bootup_event(struct esp_sip *sip);
+
+int sip_poll_resetting_event(struct esp_sip *sip);
+
+void sip_trigger_txq_process(struct esp_sip *sip);
+
+void sip_send_chip_init(struct esp_sip *sip);
+
+bool mod_support_no_txampdu(void);
+
+bool mod_support_no_rxampdu(void);
+
+void mod_support_no_txampdu_set(bool value);
+
+#ifdef FPGA_DEBUG
+int sip_send_bootup(struct esp_sip *sip);
+#endif /* FPGA_DEBUG */
+void sip_debug_show(struct esp_sip *sip);
+#endif
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_utils.c b/drivers/net/wireless/rockchip_wlan/esp8089/esp_utils.c
new file mode 100755 (executable)
index 0000000..aa697bd
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2012 Espressif System.
+ */
+
+#include "linux/types.h"
+#include "linux/kernel.h"
+#include <linux/ieee80211.h>
+#include <net/mac80211.h>
+#include <linux/skbuff.h>
+
+#include <net/tcp.h>
+#include <linux/ip.h>
+#include <asm/checksum.h>
+
+#include "esp_pub.h"
+#include "esp_utils.h"
+#include "esp_wmac.h"
+#include "esp_debug.h"
+
+/*
+ * Convert IEEE channel number to MHz frequency.
+ */
+u32
+esp_ieee2mhz(u8 chan)
+{
+        if (chan == 14)
+                return 2484;
+
+        if (chan < 14)
+                return 2407 + chan*5;
+        else
+                return 2512 + ((chan-15)*20);
+}
+enum {
+        ESP_RATE_1_LONG = 0x0,
+        ESP_RATE_2_LONG = 0x1,
+        ESP_RATE_2_SHORT = 0x5,
+        ESP_RATE_5_SHORT = 0x6,
+        ESP_RATE_5_LONG = 0x2,
+        ESP_RATE_11_SHORT = 0x7,
+        ESP_RATE_11_LONG = 0x3,
+        ESP_RATE_6 = 0xb,
+        ESP_RATE_9 = 0xf,
+        ESP_RATE_12 = 0xa,
+        ESP_RATE_18 = 0xe,
+        ESP_RATE_24 = 0x9,
+        ESP_RATE_36 = 0xd,
+        ESP_RATE_48 = 0x8,
+        ESP_RATE_54 = 0xc,
+        /*        ESP_RATE_MCS0 =0x10,
+                ESP_RATE_MCS1 =0x11,
+                ESP_RATE_MCS2 =0x12,
+                ESP_RATE_MCS3 =0x13,
+                ESP_RATE_MCS4 =0x14,
+                ESP_RATE_MCS5 =0x15,
+                ESP_RATE_MCS6 =0x16,
+                ESP_RATE_MCS7 =0x17,
+        */
+};
+
+static u8 esp_rate_table[20] = {
+        ESP_RATE_1_LONG,
+        ESP_RATE_2_SHORT,
+        ESP_RATE_5_SHORT,
+        ESP_RATE_11_SHORT,
+        ESP_RATE_6,
+        ESP_RATE_9,
+        ESP_RATE_12,
+        ESP_RATE_18,
+        ESP_RATE_24,
+        ESP_RATE_36,
+        ESP_RATE_48,
+        ESP_RATE_54,
+        /*        ESP_RATE_MCS0,
+                ESP_RATE_MCS1,
+                ESP_RATE_MCS2,
+                ESP_RATE_MCS3,
+                ESP_RATE_MCS4,
+                ESP_RATE_MCS5,
+                ESP_RATE_MCS6,
+                ESP_RATE_MCS7,
+        */
+};
+
+s8 esp_wmac_rate2idx(u8 rate)
+{
+        int i;
+
+        for (i = 0; i < 20; i++) {
+                if (rate == esp_rate_table[i])
+                        return i;
+        }
+
+        if (rate == ESP_RATE_2_LONG)
+                return 1;
+        if (rate == ESP_RATE_5_LONG)
+                return 2;
+        if (rate == ESP_RATE_11_LONG)
+                return 3;
+
+        esp_dbg(ESP_DBG_ERROR,"%s unknown rate 0x%02x \n", __func__, rate);
+
+        return 0;
+}
+
+bool esp_wmac_rxsec_error(u8 error)
+{
+        return (error >= RX_SECOV_ERR && error <= RX_SECFIFO_TIMEOUT) || (error >= RX_WEPICV_ERR && error <= RX_WAPIMIC_ERR);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+int esp_cipher2alg(int cipher)
+{
+        if (cipher == WLAN_CIPHER_SUITE_TKIP)
+                return ALG_TKIP;
+
+        if (cipher == WLAN_CIPHER_SUITE_CCMP)
+                return ALG_CCMP;
+
+        if (cipher == WLAN_CIPHER_SUITE_WEP40 || cipher == WLAN_CIPHER_SUITE_WEP104)
+                return ALG_WEP;
+       
+       if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
+                       return ALG_AES_CMAC;
+
+        //printk("%s wrong cipher 0x%x!\n",__func__,cipher);
+
+        return -1;
+}
+#endif /* NEW_KERNEL */
+
+#ifdef RX_CHECKSUM_TEST
+atomic_t g_iv_len;
+void esp_rx_checksum_test(struct sk_buff *skb)
+{
+       static u32 ip_err = 0;
+       static u32 tcp_err = 0;
+       struct ieee80211_hdr *pwh = (struct ieee80211_hdr *)skb->data;
+       int hdrlen = ieee80211_hdrlen(pwh->frame_control);
+       
+       if(ieee80211_has_protected(pwh->frame_control))
+               hdrlen += atomic_read(&g_iv_len);
+
+       if (ieee80211_is_data(pwh->frame_control)) {
+               struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
+               if (ntohs(llc->eth_type) == ETH_P_IP) {
+                       int llclen = sizeof(struct llc_snap_hdr);
+                       struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
+                       __sum16 csum_bak = iph->check;
+
+                       iph->check = 0;
+                       iph->check = ip_fast_csum(iph, iph->ihl);
+                       if (iph->check != csum_bak) {
+                               esp_dbg(ESP_DBG_ERROR, "total ip checksum error %d\n", ++ip_err);
+                       }
+                       iph->check = csum_bak;
+
+                       if (iph->protocol == 0x06) {
+                               struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
+                               int datalen = skb->len - (hdrlen + llclen + iph->ihl * 4);
+                               csum_bak = tcph->check;
+
+                               tcph->check = 0;
+                               tcph->check = tcp_v4_check(datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0));
+                               if (tcph->check != csum_bak)
+                               {
+                                       esp_dbg(ESP_DBG_ERROR, "total tcp checksum error %d\n", ++tcp_err);
+                               }
+                               tcph->check = csum_bak;
+                       }
+        }
+       }
+}
+
+#endif
+
+#ifdef GEN_ERR_CHECKSUM
+
+void esp_gen_err_checksum(struct sk_buff *skb)
+{
+        static u32 tx_seq = 0;
+       if ((tx_seq++ % 16) == 0)
+       {
+               struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+               int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+       
+               if(ieee80211_has_protected(pwh->frame_control))
+                       hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
+
+               struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
+               if (ntohs(llc->eth_type) == ETH_P_IP) {
+                       int llclen = sizeof(struct llc_snap_hdr);
+                       struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
+
+                       iph->check = ~iph->check;
+
+                       if (iph->protocol == 0x06) {
+                               struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
+                               tcph->check = ~tcph->check;
+                       }
+               }
+       }
+}
+#endif
+
+bool esp_is_ip_pkt(struct sk_buff *skb)
+{
+                struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+                int hdrlen;
+                struct llc_snap_hdr * llc;
+               
+               if (!ieee80211_is_data(hdr->frame_control))
+                       return false;
+               
+               hdrlen = ieee80211_hdrlen(hdr->frame_control);
+               if(ieee80211_has_protected(hdr->frame_control))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
+                       hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
+#else
+                       hdrlen += IEEE80211_SKB_CB(skb)->control.iv_len;
+#endif
+#ifdef RX_CHECKSUM_TEST
+               atomic_set(&g_iv_len, IEEE80211_SKB_CB(skb)->control.hw_key->iv_len);
+#endif
+               if(skb->len < hdrlen + sizeof(struct llc_snap_hdr))
+                       return false;
+               llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
+                if (ntohs(llc->eth_type) != ETH_P_IP)
+                       return false;
+               else
+                       return true;
+}
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_utils.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_utils.h
new file mode 100755 (executable)
index 0000000..7de7463
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011-2012 Espressif System.
+ */
+
+#ifndef _ESP_UTILS_H_
+#define _ESP_UTILS_H_
+
+#include "linux/types.h"
+#include <linux/version.h>
+
+#ifndef BIT
+#define BIT(x) (0x1 << (x))
+#endif
+
+u32 esp_ieee2mhz(u8 chan);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+enum ieee80211_key_alg {
+        ALG_WEP,
+        ALG_TKIP,
+        ALG_CCMP,
+        ALG_AES_CMAC
+};
+
+int esp_cipher2alg(int cipher);
+
+void esp_rx_checksum_test(struct sk_buff *skb);
+void esp_gen_err_checksum(struct sk_buff *skb);
+
+#endif /* NEW_KERNEL */
+
+bool esp_is_ip_pkt(struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_version.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_version.h
new file mode 100755 (executable)
index 0000000..635b80b
--- /dev/null
@@ -0,0 +1 @@
+#define DRIVER_VER 0x18a2bc815cc5ll
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_wl.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_wl.h
new file mode 100755 (executable)
index 0000000..8bc5491
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _ESP_WL_H_
+#define _ESP_WL_H_
+
+//#define MAX_PROBED_SSID_INDEX 9
+
+
+enum {
+        CONF_HW_BIT_RATE_1MBPS   = BIT(0),
+        CONF_HW_BIT_RATE_2MBPS   = BIT(1),
+        CONF_HW_BIT_RATE_5_5MBPS = BIT(2),
+        CONF_HW_BIT_RATE_11MBPS  = BIT(3),
+        CONF_HW_BIT_RATE_6MBPS   = BIT(4),
+        CONF_HW_BIT_RATE_9MBPS   = BIT(5),
+        CONF_HW_BIT_RATE_12MBPS  = BIT(6),
+        CONF_HW_BIT_RATE_18MBPS  = BIT(7),
+        CONF_HW_BIT_RATE_22MBPS  = BIT(8),
+        CONF_HW_BIT_RATE_24MBPS  = BIT(9),
+        CONF_HW_BIT_RATE_36MBPS  = BIT(10),
+        CONF_HW_BIT_RATE_48MBPS  = BIT(11),
+        CONF_HW_BIT_RATE_54MBPS  = BIT(12),
+       CONF_HW_BIT_RATE_11B_MASK = (CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS),
+};
+
+#if 0
+enum {
+        CONF_HW_RATE_INDEX_1MBPS   = 0,
+        CONF_HW_RATE_INDEX_2MBPS   = 1,
+        CONF_HW_RATE_INDEX_5_5MBPS = 2,
+        CONF_HW_RATE_INDEX_6MBPS   = 3,
+        CONF_HW_RATE_INDEX_9MBPS   = 4,
+        CONF_HW_RATE_INDEX_11MBPS  = 5,
+        CONF_HW_RATE_INDEX_12MBPS  = 6,
+        CONF_HW_RATE_INDEX_18MBPS  = 7,
+        CONF_HW_RATE_INDEX_22MBPS  = 8,
+        CONF_HW_RATE_INDEX_24MBPS  = 9,
+        CONF_HW_RATE_INDEX_36MBPS  = 10,
+        CONF_HW_RATE_INDEX_48MBPS  = 11,
+        CONF_HW_RATE_INDEX_54MBPS  = 12,
+        CONF_HW_RATE_INDEX_MAX,
+};
+
+enum {
+        CONF_HW_RXTX_RATE_54 = 0,
+        CONF_HW_RXTX_RATE_48,
+        CONF_HW_RXTX_RATE_36,
+        CONF_HW_RXTX_RATE_24,
+        CONF_HW_RXTX_RATE_22,
+        CONF_HW_RXTX_RATE_18,
+        CONF_HW_RXTX_RATE_12,
+        CONF_HW_RXTX_RATE_11,
+        CONF_HW_RXTX_RATE_9,
+        CONF_HW_RXTX_RATE_6,
+        CONF_HW_RXTX_RATE_5_5,
+        CONF_HW_RXTX_RATE_2,
+        CONF_HW_RXTX_RATE_1,
+        CONF_HW_RXTX_RATE_MAX,
+        CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff
+};
+#endif
+
+#endif /* _ESP_WL_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/esp_wmac.h b/drivers/net/wireless/rockchip_wlan/esp8089/esp_wmac.h
new file mode 100755 (executable)
index 0000000..3987314
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011-2012 Espressif System.
+ *
+ *   MAC header
+ */
+
+#ifndef _ESP_WMAC_H_
+#define _ESP_WMAC_H_
+
+struct esp_mac_rx_ctrl {
+        signed rssi:8;
+        unsigned rate:4;
+        unsigned is_group:1;
+        unsigned:1;
+        unsigned sig_mode:2;
+        unsigned legacy_length:12;
+        unsigned damatch0:1;
+        unsigned damatch1:1;
+        unsigned bssidmatch0:1;
+        unsigned bssidmatch1:1;
+        unsigned MCS:7;
+        unsigned CWB:1;
+        unsigned HT_length:16;
+        unsigned Smoothing:1;
+        unsigned Not_Sounding:1;
+        unsigned:1;
+        unsigned Aggregation:1;
+        unsigned STBC:2;
+        unsigned FEC_CODING:1;
+        unsigned SGI:1;
+        unsigned rxend_state:8;
+        unsigned ampdu_cnt:8;
+        unsigned channel:4;
+        unsigned:12;
+};
+
+struct esp_rx_ampdu_len {
+        unsigned substate:8;
+        unsigned sublen:12;
+        unsigned :12;
+};
+
+struct esp_tx_ampdu_entry {
+        u32 sub_len:12,
+            dili_num:7,
+            :1,
+            null_byte:2,
+            data:1,
+            enc:1,
+            seq:8;
+};
+
+//rxend_state flags
+#define RX_PYH_ERR_MIN 0x42
+#define RX_AGC_ERR_MIN 0x42
+#define RX_AGC_ERR_MAX 0x47
+#define RX_OFDM_ERR_MIN 0x50
+#define RX_OFDM_ERR_MAX 0x58
+#define RX_CCK_ERR_MIN 0x59
+#define RX_CCK_ERR_MAX 0x5F
+#define RX_ABORT 0x80
+#define RX_SF_ERR 0x40
+#define RX_FCS_ERR 0x41
+#define RX_AHBOV_ERR 0xC0
+#define RX_BUFOV_ERR 0xC1
+#define RX_BUFINV_ERR 0xC2
+#define RX_AMPDUSF_ERR 0xC3
+#define RX_AMPDUBUFOV_ERR 0xC4
+#define RX_MACBBFIFOOV_ERR 0xC5
+#define RX_RPBM_ERR 0xC6
+#define RX_BTFORCE_ERR 0xC7
+#define RX_SECOV_ERR 0xE1
+#define RX_SECPROT_ERR0 0xE2
+#define RX_SECPROT_ERR1 0xE3
+#define RX_SECKEY_ERR 0xE4
+#define RX_SECCRLEN_ERR 0xE5
+#define RX_SECFIFO_TIMEOUT 0xE6
+#define RX_WEPICV_ERR 0xF0
+#define RX_TKIPICV_ERR 0xF4
+#define RX_TKIPMIC_ERR 0xF5
+#define RX_CCMPMIC_ERR 0xF8
+#define RX_WAPIMIC_ERR 0xFC
+
+s8 esp_wmac_rate2idx(u8 rate);
+bool esp_wmac_rxsec_error(u8 error);
+
+#endif /* _ESP_WMAC_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/init_data.conf b/drivers/net/wireless/rockchip_wlan/esp8089/init_data.conf
new file mode 100755 (executable)
index 0000000..d48a202
--- /dev/null
@@ -0,0 +1 @@
+crystal_26M_en=0;test_xtal=0;sdio_configure=2;bt_configure=0;bt_protocol=0;dual_ant_configure=0;test_uart_configure=2;share_xtal=0;gpio_wake=0;no_auto_sleep=0;ext_rst=0;$
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/rk2.env b/drivers/net/wireless/rockchip_wlan/esp8089/rk2.env
new file mode 100755 (executable)
index 0000000..ff1cf3a
--- /dev/null
@@ -0,0 +1,3 @@
+#export TOOLCHAIN_PREFIX=/cold/RK2/newsdk/sdk4_2_for_esp_20130723/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
+export KERNEL_DIR=/cold/RK2/newsdk/sdk4_2_for_esp_20130723/kernel_ds1006h_v1.3
+export EAGLE_BASE_DIR=$(pwd)
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/sdio_sif_esp.c b/drivers/net/wireless/rockchip_wlan/esp8089/sdio_sif_esp.c
new file mode 100755 (executable)
index 0000000..3624e3f
--- /dev/null
@@ -0,0 +1,937 @@
+/*
+ * Copyright (c) 2010 -2013 Espressif System.
+ *
+ *   sdio serial i/f driver
+ *    - sdio device control routines
+ *    - sync/async DMA/PIO read/write
+ *
+ */
+#ifdef ESP_USE_SDIO
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/module.h>
+#include <net/mac80211.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+
+#include "esp_pub.h"
+#include "esp_sif.h"
+#include "esp_sip.h"
+#include "esp_debug.h"
+#include "slc_host_register.h"
+#include "esp_version.h"
+#include "esp_ctrl.h"
+#ifdef ANDROID
+#include "esp_android.h"
+#endif /* ANDROID */
+#ifdef USE_EXT_GPIO
+#include "esp_ext.h"
+#endif /* USE_EXT_GPIO */
+
+static int /*__init*/ esp_sdio_init(void);
+static void  /*__exit*/ esp_sdio_exit(void);
+
+
+#define ESP_DMA_IBUFSZ   2048
+
+//unsigned int esp_msg_level = 0;
+unsigned int esp_msg_level = ESP_DBG_ERROR | ESP_SHOW;
+
+static struct semaphore esp_powerup_sem;
+
+static enum esp_sdio_state sif_sdio_state;
+struct esp_sdio_ctrl *sif_sctrl = NULL;
+
+#ifdef ESP_ANDROID_LOGGER
+bool log_off = false;
+#endif /* ESP_ANDROID_LOGGER */
+
+static int esdio_power_off(struct esp_sdio_ctrl *sctrl);
+static int esdio_power_on(struct esp_sdio_ctrl *sctrl);
+
+void sif_set_clock(struct sdio_func *func, int clk);
+
+struct sif_req * sif_alloc_req(struct esp_sdio_ctrl *sctrl);
+
+#include "sdio_stub.c"
+
+void sif_lock_bus(struct esp_pub *epub)
+{
+        EPUB_FUNC_CHECK(epub);
+
+        sdio_claim_host(EPUB_TO_FUNC(epub));
+}
+
+void sif_unlock_bus(struct esp_pub *epub)
+{
+        EPUB_FUNC_CHECK(epub);
+
+        sdio_release_host(EPUB_TO_FUNC(epub));
+}
+
+#ifdef SDIO_TEST
+static void sif_test_tx(struct esp_sdio_ctrl *sctrl)
+{
+        int i, err = 0;
+
+        for (i = 0; i < 500; i++) {
+                sctrl->dma_buffer[i] = i;
+        }
+
+        sdio_claim_host(sctrl->func);
+        err = sdio_memcpy_toio(sctrl->func, 0x10001 - 500, sctrl->dma_buffer, 500);
+        sif_platform_check_r1_ready(sctrl->epub);
+        sdio_release_host(sctrl->func);
+
+        esp_dbg(ESP_DBG, "%s toio err %d\n", __func__, err);
+}
+
+static void sif_test_dsr(struct sdio_func *func)
+{
+        struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func);
+
+        sdio_release_host(sctrl->func);
+
+        /* no need to read out registers in normal operation any more */
+        //sif_io_sync(sctrl->epub, SIF_SLC_WINDOW_END_ADDR - 64, sctrl->dma_buffer, 64, SIF_FROM_DEVICE | SIF_INC_ADDR | SIF_SYNC | SIF_BYTE_BASIS);
+        //
+        esp_dsr(sctrl->epub);
+
+        sdio_claim_host(func);
+
+        //show_buf(sctrl->dma_buffer, 64);
+}
+
+void sif_test_rx(struct esp_sdio_ctrl *sctrl)
+{
+        int err = 0;
+
+        sdio_claim_host(sctrl->func);
+
+        err = sdio_claim_irq(sctrl->func, sif_test_dsr);
+
+        if (err)
+                esp_dbg(ESP_DBG_ERROR, "sif %s failed\n", __func__);
+
+        sdio_release_host(sctrl->func);
+}
+#endif //SDIO_TEST
+
+static inline bool bad_buf(u8 * buf)
+{
+       return ((unsigned long) buf & 0x3) || !virt_addr_valid(buf);
+}
+
+u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        struct sdio_func *func = NULL;
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+        func = sctrl->func;
+
+       if(func->num == 0)
+               return sdio_f0_readb(func, addr, res);
+       else
+               return sdio_readb(func, addr, res);
+}
+
+void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        struct sdio_func *func = NULL;
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+        func = sctrl->func;
+       
+       if(func->num == 0)
+               sdio_f0_writeb(func, value, addr, res);
+       else
+               sdio_writeb(func, value, addr, res);
+       sif_platform_check_r1_ready(epub);
+}
+
+int sif_io_raw(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag)
+{
+        int err = 0;
+        u8 *ibuf = NULL;
+        bool need_ibuf = false;
+        struct esp_sdio_ctrl *sctrl = NULL;
+        struct sdio_func *func = NULL;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+        func = sctrl->func;
+        ASSERT(func != NULL);
+
+        if (bad_buf(buf)) {
+                esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", __func__, addr, len);
+                need_ibuf = true;
+                ibuf = sctrl->dma_buffer;
+        } else {
+                ibuf = buf;
+        }
+
+        if (flag & SIF_BLOCK_BASIS) {
+                /* round up for block data transcation */
+        }
+
+        if (flag & SIF_TO_DEVICE) {
+
+                if (need_ibuf)
+                        memcpy(ibuf, buf, len);
+
+                if (flag & SIF_FIXED_ADDR)
+                        err = sdio_writesb(func, addr, ibuf, len);
+                else if (flag & SIF_INC_ADDR) {
+                        err = sdio_memcpy_toio(func, addr, ibuf, len);
+                }
+                sif_platform_check_r1_ready(epub);
+        } else if (flag & SIF_FROM_DEVICE) {
+
+                if (flag & SIF_FIXED_ADDR)
+                        err = sdio_readsb(func, ibuf, addr, len);
+                else if (flag & SIF_INC_ADDR) {
+                        err = sdio_memcpy_fromio(func, ibuf, addr, len);
+                }
+
+
+                if (!err && need_ibuf)
+                        memcpy(buf, ibuf, len);
+        }
+
+       return err;
+}
+
+int sif_io_sync(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag)
+{
+        int err = 0;
+        u8 * ibuf = NULL;
+        bool need_ibuf = false;
+        struct esp_sdio_ctrl *sctrl = NULL;
+        struct sdio_func *func = NULL;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+        func = sctrl->func;
+        ASSERT(func != NULL);
+
+        if (bad_buf(buf)) {
+                esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", __func__, addr, len);
+                need_ibuf = true;
+                ibuf = sctrl->dma_buffer;
+        } else {
+                ibuf = buf;
+        }
+
+        if (flag & SIF_BLOCK_BASIS) {
+                /* round up for block data transcation */
+        }
+
+        if (flag & SIF_TO_DEVICE) {
+
+                esp_dbg(ESP_DBG_TRACE, "%s to addr 0x%08x, len %d \n", __func__, addr, len);
+                if (need_ibuf)
+                        memcpy(ibuf, buf, len);
+
+                sdio_claim_host(func);
+
+                if (flag & SIF_FIXED_ADDR)
+                        err = sdio_writesb(func, addr, ibuf, len);
+                else if (flag & SIF_INC_ADDR) {
+                        err = sdio_memcpy_toio(func, addr, ibuf, len);
+                }
+                sif_platform_check_r1_ready(epub);
+                sdio_release_host(func);
+        } else if (flag & SIF_FROM_DEVICE) {
+
+                esp_dbg(ESP_DBG_TRACE, "%s from addr 0x%08x, len %d \n", __func__, addr, len);
+
+                sdio_claim_host(func);
+
+                if (flag & SIF_FIXED_ADDR)
+                        err = sdio_readsb(func, ibuf, addr, len);
+                else if (flag & SIF_INC_ADDR) {
+                        err = sdio_memcpy_fromio(func, ibuf, addr, len);
+                }
+
+                sdio_release_host(func);
+
+                if (!err && need_ibuf)
+                        memcpy(buf, ibuf, len);
+        }
+
+        return err;
+}
+
+int sif_lldesc_read_sync(struct esp_pub *epub, u8 *buf, u32 len)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        u32 read_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                read_len = len;
+                break;
+        case 0x600:
+                read_len = roundup(len, sctrl->slc_blk_sz);
+                break;
+        default:
+                read_len = len;
+                break;
+        }
+
+        return sif_io_sync((epub), (sctrl->slc_window_end_addr - 2 - (len)), (buf), (read_len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
+}
+
+int sif_lldesc_write_sync(struct esp_pub *epub, u8 *buf, u32 len)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        u32 write_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                write_len = len;
+                break;
+        case 0x600:
+                write_len = roundup(len, sctrl->slc_blk_sz);
+                break;
+        default:
+                write_len = len;
+                break;
+        }
+
+        return sif_io_sync((epub), (sctrl->slc_window_end_addr - (len)), (buf), (write_len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
+}
+
+int sif_lldesc_read_raw(struct esp_pub *epub, u8 *buf, u32 len, bool noround)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        u32 read_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                read_len = len;
+                break;
+        case 0x600:
+               if(!noround)
+                       read_len = roundup(len, sctrl->slc_blk_sz);
+               else
+                       read_len = len;
+                break;
+        default:
+                read_len = len;
+                break;
+        }
+
+        return sif_io_raw((epub), (sctrl->slc_window_end_addr - 2 - (len)), (buf), (read_len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
+}
+
+int sif_lldesc_write_raw(struct esp_pub *epub, u8 *buf, u32 len)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        u32 write_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                write_len = len;
+                break;
+        case 0x600:
+                write_len = roundup(len, sctrl->slc_blk_sz);
+                break;
+        default:
+                write_len = len;
+                break;
+        }
+        return sif_io_raw((epub), (sctrl->slc_window_end_addr - (len)), (buf), (write_len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
+
+}
+
+#define MANUFACTURER_ID_EAGLE_BASE        0x1110
+#define MANUFACTURER_ID_EAGLE_BASE_MASK     0xFF00
+#define MANUFACTURER_CODE                  0x6666
+
+static const struct sdio_device_id esp_sdio_devices[] = {
+        {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_EAGLE_BASE | 0x1))},
+        {},
+};
+
+static int esdio_power_on(struct esp_sdio_ctrl *sctrl)
+{
+        int err = 0;
+
+        assert(sctrl != NULL);
+
+        if (sctrl->off == false)
+                return err;
+
+        sdio_claim_host(sctrl->func);
+        err = sdio_enable_func(sctrl->func);
+
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "Unable to enable sdio func: %d\n", err);
+                sdio_release_host(sctrl->func);
+                return err;
+        }
+
+        sdio_release_host(sctrl->func);
+
+        /* ensure device is up */
+        msleep(5);
+
+        sctrl->off = false;
+
+        return err;
+}
+
+static int esdio_power_off(struct esp_sdio_ctrl *sctrl)
+{
+        int err;
+
+        if (sctrl->off)
+                return 0;
+
+        sdio_claim_host(sctrl->func);
+        err = sdio_disable_func(sctrl->func);
+        sdio_release_host(sctrl->func);
+
+        if (err)
+                return err;
+
+        sctrl->off = true;
+
+        return err;
+}
+
+void sif_enable_irq(struct esp_pub *epub) 
+{
+        int err;
+        struct esp_sdio_ctrl *sctrl = NULL;
+
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+
+        sdio_claim_host(sctrl->func);
+
+        err = sdio_claim_irq(sctrl->func, sif_dsr);
+
+        if (err)
+                esp_dbg(ESP_DBG_ERROR, "sif %s failed\n", __func__);
+
+        atomic_set(&epub->sip->state, SIP_BOOT);
+
+        atomic_set(&sctrl->irq_installed, 1);
+
+        sdio_release_host(sctrl->func);
+}
+
+void sif_disable_irq(struct esp_pub *epub) 
+{
+        int err;
+        struct esp_sdio_ctrl *sctrl = (struct esp_sdio_ctrl *)epub->sif;
+        int i = 0;
+                
+        if (atomic_read(&sctrl->irq_installed) == 0)
+                return;
+        
+           sdio_claim_host(sctrl->func);
+
+        while (atomic_read(&sctrl->irq_handling)) {
+                sdio_release_host(sctrl->func);
+                schedule_timeout(HZ / 100);
+                sdio_claim_host(sctrl->func);
+                if (i++ >= 400) {
+                        esp_dbg(ESP_DBG_ERROR, "%s force to stop irq\n", __func__);
+                        break;
+                }
+        }
+
+        err = sdio_release_irq(sctrl->func);
+
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "%s release irq failed\n", __func__);
+        }
+
+        atomic_set(&sctrl->irq_installed, 0);
+
+        sdio_release_host(sctrl->func);
+
+}
+
+void sif_set_clock(struct sdio_func *func, int clk)
+{
+       struct mmc_host *host = NULL;
+       struct mmc_card *card = NULL;
+       
+       card = func->card;
+       host = card->host;
+
+       sdio_claim_host(func);
+
+       //currently only set clock
+       host->ios.clock = clk * 1000000;
+
+       esp_dbg(ESP_SHOW, "%s clock is %u\n", __func__, host->ios.clock);
+       if (host->ios.clock > host->f_max) {
+               host->ios.clock = host->f_max;
+       }
+       host->ops->set_ios(host, &host->ios);
+
+       mdelay(2);
+
+       sdio_release_host(func);
+}
+
+static int esp_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id);
+static void esp_sdio_remove(struct sdio_func *func);
+
+static int esp_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) 
+{
+        int err = 0;
+        struct esp_pub *epub;
+        struct esp_sdio_ctrl *sctrl;
+
+        esp_dbg(ESP_DBG_TRACE,
+                        "sdio_func_num: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n",
+                        func->num, func->vendor, func->device, func->max_blksize,
+                        func->cur_blksize);
+       if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               sctrl = kzalloc(sizeof(struct esp_sdio_ctrl), GFP_KERNEL);
+
+               if (sctrl == NULL) {
+                       assert(0);
+                       return -ENOMEM;
+               }
+
+               /* temp buffer reserved for un-dma-able request */
+               sctrl->dma_buffer = kzalloc(ESP_DMA_IBUFSZ, GFP_KERNEL);
+
+               if (sctrl->dma_buffer == NULL) {
+                       assert(0);
+                       goto _err_last;
+               }
+               sif_sctrl = sctrl;
+               sctrl->slc_blk_sz = SIF_SLC_BLOCK_SIZE;
+               
+               epub = esp_pub_alloc_mac80211(&func->dev);
+
+               if (epub == NULL) {
+                       esp_dbg(ESP_DBG_ERROR, "no mem for epub \n");
+                       err = -ENOMEM;
+                       goto _err_dma;
+               }
+               epub->sif = (void *)sctrl;
+               sctrl->epub = epub;
+       
+#ifdef USE_EXT_GPIO    
+               err = ext_gpio_init(epub);
+               if (err) {
+                       esp_dbg(ESP_DBG_ERROR, "ext_irq_work_init failed %d\n", err);
+                       return err;
+               }
+#endif
+                       
+       } else {
+               ASSERT(sif_sctrl != NULL);
+               sctrl = sif_sctrl;
+               sif_sctrl = NULL;
+               epub = sctrl->epub;
+               SET_IEEE80211_DEV(epub->hw, &func->dev);
+               epub->dev = &func->dev;
+       }
+
+        epub->sdio_state = sif_sdio_state;
+
+        sctrl->func = func;
+        sdio_set_drvdata(func, sctrl);
+
+        sctrl->id = id;
+        sctrl->off = true;
+
+        /* give us some time to enable, in ms */
+        func->enable_timeout = 100;
+
+        err = esdio_power_on(sctrl);
+        esp_dbg(ESP_DBG_TRACE, " %s >> power_on err %d \n", __func__, err);
+
+        if (err){
+                if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT)
+                       goto _err_epub;
+                 else
+                       goto _err_second_init;
+        }
+        check_target_id(epub);
+
+        sdio_claim_host(func);
+
+        err = sdio_set_block_size(func, sctrl->slc_blk_sz);
+
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "Set sdio block size %d failed: %d)\n",
+                                sctrl->slc_blk_sz, err);
+                sdio_release_host(func);
+                goto _err_off;
+        }
+
+        sdio_release_host(func);
+
+#ifdef SDIO_TEST
+        sif_test_tx(sctrl);
+#else
+
+#ifdef LOWER_CLK 
+        /* fix clock for dongle */
+       sif_set_clock(func, 23);
+#endif //LOWER_CLK
+
+        err = esp_pub_init_all(epub);
+
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "esp_init_all failed: %d\n", err);
+                if(sif_sdio_state == ESP_SDIO_STATE_SECOND_INIT)
+                       goto _err_second_init;
+        }
+
+#endif //SDIO_TEST
+        esp_dbg(ESP_DBG_TRACE, " %s return  %d\n", __func__, err);
+       if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               esp_dbg(ESP_DBG_ERROR, "first normal exit\n");
+               sif_sdio_state = ESP_SDIO_STATE_FIRST_NORMAL_EXIT;
+               up(&esp_powerup_sem);
+       }
+
+        return err;
+
+_err_off:
+        esdio_power_off(sctrl);
+_err_epub:
+        esp_pub_dealloc_mac80211(epub);
+_err_dma:
+        kfree(sctrl->dma_buffer);
+_err_last:
+        kfree(sctrl);
+
+       if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               sif_sdio_state = ESP_SDIO_STATE_FIRST_ERROR_EXIT;
+               up(&esp_powerup_sem);
+       }
+        return err;
+_err_second_init:
+       sif_sdio_state = ESP_SDIO_STATE_SECOND_ERROR_EXIT;
+       esp_sdio_remove(func);
+       return err;
+}
+
+static void esp_sdio_remove(struct sdio_func *func) 
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+
+        sctrl = sdio_get_drvdata(func);
+
+        if (sctrl == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "%s no sctrl\n", __func__);
+                return;
+        }
+
+        do {
+                if (sctrl->epub == NULL) {
+                        esp_dbg(ESP_DBG_ERROR, "%s epub null\n", __func__);
+                        break;
+                }
+               sctrl->epub->sdio_state = sif_sdio_state;
+               if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
+                       do{
+                               int err;
+                               sif_lock_bus(sctrl->epub);
+                               sif_raw_dummy_read(sctrl->epub);
+                               err = sif_interrupt_target(sctrl->epub, 7);
+                               sif_unlock_bus(sctrl->epub);
+                       }while(0);
+       
+                       if (sctrl->epub->sip) {
+                               sip_detach(sctrl->epub->sip);
+                               sctrl->epub->sip = NULL;
+                               esp_dbg(ESP_DBG_TRACE, "%s sip detached \n", __func__);
+#ifdef USE_EXT_GPIO    
+                               ext_gpio_deinit();
+#endif
+                       }
+               } else {
+                       //sif_disable_target_interrupt(sctrl->epub);
+                       atomic_set(&sctrl->epub->sip->state, SIP_STOP);
+                       sif_disable_irq(sctrl->epub);
+               }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0))
+                esdio_power_off(sctrl);
+                esp_dbg(ESP_DBG_TRACE, "%s power off \n", __func__);
+#endif /* kernel < 3.3.0 */
+
+#ifdef TEST_MODE
+                test_exit_netlink();
+#endif /* TEST_MODE */
+               if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
+                       esp_pub_dealloc_mac80211(sctrl->epub);
+                       esp_dbg(ESP_DBG_TRACE, "%s dealloc mac80211 \n", __func__);
+                       
+                       if (sctrl->dma_buffer) {
+                               kfree(sctrl->dma_buffer);
+                               sctrl->dma_buffer = NULL;
+                               esp_dbg(ESP_DBG_TRACE, "%s free dma_buffer \n", __func__);
+                       }
+
+                       kfree(sctrl);
+               }
+
+        } while (0);
+        
+       sdio_set_drvdata(func,NULL);
+       
+        esp_dbg(ESP_DBG_TRACE, "eagle sdio remove complete\n");
+}
+
+MODULE_DEVICE_TABLE(sdio, esp_sdio_devices);
+
+static int esp_sdio_suspend(struct device *dev)
+{
+    //#define dev_to_sdio_func(d)     container_of(d, struct sdio_func, dev)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+    struct sdio_func *func = dev_to_sdio_func(dev);
+#else
+    struct sdio_func *func = container_of(dev, struct sdio_func, dev);
+#endif
+       struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func);
+       struct esp_pub *epub = sctrl->epub;     
+
+        printk("%s", __func__);
+#if 0
+       sip_send_suspend_config(epub, 1);
+#endif
+       atomic_set(&epub->ps.state, ESP_PM_ON);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
+    do{
+        u32 sdio_flags = 0;
+        int ret = 0;
+        sdio_flags = sdio_get_host_pm_caps(func);
+
+        if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+            printk("%s can't keep power while host is suspended\n", __func__);
+        }
+
+        /* keep power while host suspended */
+        ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+        if (ret) {
+                printk("%s error while trying to keep power\n", __func__);
+        }
+    }while(0);
+#endif
+
+
+        return 0;
+
+}
+
+static int esp_sdio_resume(struct device *dev)
+{
+        esp_dbg(ESP_DBG_ERROR, "%s", __func__);
+
+        return 0;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+static const struct dev_pm_ops esp_sdio_pm_ops = {
+        .suspend= esp_sdio_suspend,
+        .resume= esp_sdio_resume,
+};
+#else
+static struct pm_ops esp_sdio_pm_ops = {
+        .suspend= esp_sdio_suspend,
+        .resume= esp_sdio_resume,
+};
+#endif
+
+static struct sdio_driver esp_sdio_driver = {
+                .name = "eagle_sdio",
+                .id_table = esp_sdio_devices,
+                .probe = esp_sdio_probe,
+                .remove = esp_sdio_remove,
+                .drv = { .pm = &esp_sdio_pm_ops, },
+};
+
+static int esp_sdio_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id)
+{
+        esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__);
+
+        up(&esp_powerup_sem);
+        
+        return 0;
+}
+
+static void esp_sdio_dummy_remove(struct sdio_func *func) 
+{
+        return;
+}
+
+static struct sdio_driver esp_sdio_dummy_driver = {
+                .name = "eagle_sdio_dummy",
+                .id_table = esp_sdio_devices,
+                .probe = esp_sdio_dummy_probe,
+                .remove = esp_sdio_dummy_remove,
+};
+
+static int /*__init*/ esp_sdio_init(void) 
+{
+#define ESP_WAIT_UP_TIME_MS 11000
+        int err;
+        u64 ver;
+        int retry = 3;
+        bool powerup = false;
+        int edf_ret = 0;
+
+        esp_dbg(ESP_DBG_TRACE, "%s \n", __func__);
+
+#ifdef DRIVER_VER
+        ver = DRIVER_VER;
+        esp_dbg(ESP_SHOW, "\n*****%s %s EAGLE DRIVER VER:%llx*****\n\n", __DATE__, __TIME__, ver);
+#endif
+        edf_ret = esp_debugfs_init();
+
+#ifdef ANDROID
+       android_request_init_conf();
+#endif /* defined(ANDROID)*/
+
+        esp_wakelock_init();
+        esp_wake_lock();
+
+        do {
+                sema_init(&esp_powerup_sem, 0);
+
+                sif_platform_target_poweron();
+
+                sif_platform_rescan_card(1);
+
+                err = sdio_register_driver(&esp_sdio_dummy_driver);
+                if (err) {
+                        esp_dbg(ESP_DBG_ERROR, "eagle sdio driver registration failed, error code: %d\n", err);
+                        goto _fail;
+                }
+
+                if (down_timeout(&esp_powerup_sem,
+                                 msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0) 
+               {
+
+                        powerup = true;
+                       msleep(200);
+                        break;
+                }
+
+                esp_dbg(ESP_SHOW, "%s ------ RETRY ------ \n", __func__);
+
+               sif_record_retry_config();
+
+                sdio_unregister_driver(&esp_sdio_dummy_driver);
+
+                sif_platform_rescan_card(0);
+                
+                sif_platform_target_poweroff();
+                
+        } while (retry--);
+
+        if (!powerup) {
+                esp_dbg(ESP_DBG_ERROR, "eagle sdio can not power up!\n");
+
+                err = -ENODEV;
+                goto _fail;
+        }
+
+        esp_dbg(ESP_SHOW, "%s power up OK\n", __func__);
+
+        sdio_unregister_driver(&esp_sdio_dummy_driver);
+
+        sif_sdio_state = ESP_SDIO_STATE_FIRST_INIT;
+        sema_init(&esp_powerup_sem, 0);
+
+        sdio_register_driver(&esp_sdio_driver);
+
+        if (down_timeout(&esp_powerup_sem,
+                                 msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0) 
+       {
+               if(sif_sdio_state == ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
+                       sdio_unregister_driver(&esp_sdio_driver);
+
+                       sif_platform_rescan_card(0);
+
+                       msleep(80);
+                
+                       sif_platform_rescan_card(1);
+
+                       sif_sdio_state = ESP_SDIO_STATE_SECOND_INIT;
+               
+                       sdio_register_driver(&esp_sdio_driver);
+               }
+                
+        }
+
+
+        esp_register_early_suspend();
+       esp_wake_unlock();
+        return err;
+
+_fail:
+        esp_wake_unlock();
+        esp_wakelock_destroy();
+
+        return err;
+}
+
+static void  /*__exit*/ esp_sdio_exit(void) 
+{
+       esp_dbg(ESP_DBG_TRACE, "%s \n", __func__);
+
+       esp_debugfs_exit();
+       
+        esp_unregister_early_suspend();
+
+       sdio_unregister_driver(&esp_sdio_driver);
+       
+       sif_platform_rescan_card(0);
+
+#ifndef FPGA_DEBUG
+       sif_platform_target_poweroff();
+#endif /* !FPGA_DEBUG */
+
+        esp_wakelock_destroy();
+}
+
+MODULE_AUTHOR("Espressif System");
+MODULE_DESCRIPTION("Driver for SDIO interconnected eagle low-power WLAN devices");
+MODULE_LICENSE("GPL");
+#endif /* ESP_USE_SDIO */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/sdio_stub.c b/drivers/net/wireless/rockchip_wlan/esp8089/sdio_stub.c
new file mode 100755 (executable)
index 0000000..4bd4107
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013 Espressif System.
+ *
+ *  sdio stub code for RK
+ */
+
+//#include <mach/gpio.h> libing
+//#include <mach/iomux.h> libing
+
+#define ESP8089_DRV_VERSION "2.20"
+//extern int rk29sdk_wifi_power(int on); libing
+extern int rockchip_wifi_power(int on);
+//extern int rk29sdk_wifi_set_carddetect(int val); libing
+extern int rockchip_wifi_set_carddetect(int val);
+int rockchip_wifi_init_module(void)
+{
+               
+return esp_sdio_init();                
+}
+
+void rockchip_wifi_exit_module(void)
+{
+       esp_sdio_exit(); 
+                
+}
+void sif_platform_rescan_card(unsigned insert)
+{
+               //rk29sdk_wifi_set_carddetect(insert); libing
+        rockchip_wifi_set_carddetect(insert);
+}
+
+void sif_platform_reset_target(void)
+{
+       if(sif_get_bt_config() == 1 && sif_get_retry_config() == 0){
+               if(sif_get_rst_config() == 1){
+                       //TODO, use gpio to reset target
+               }// else {
+               //      iomux_set(GPIO3_D2);
+               //      gpio_request(RK30_PIN3_PD2, "esp8089-sdio-wifi");
+
+               //      mdelay(100);
+               //      gpio_direction_output(RK30_PIN3_PD2, 0);
+               //      mdelay(50);
+               //      gpio_direction_output(RK30_PIN3_PD2, 1);
+       //      }
+       } else {
+               //rk29sdk_wifi_set_carddetect(0);
+               //rk29sdk_wifi_power(0); //libing
+                       rockchip_wifi_power(0);
+               //rk29sdk_wifi_power(1); //libing
+               rockchip_wifi_power(1);
+               //rk29sdk_wifi_set_carddetect(1);
+       }
+}
+
+void sif_platform_target_poweroff(void)
+{
+       printk("=======================================================\n");
+       printk("==== Dislaunching Wi-Fi driver! (Powered by Rockchip) ====\n");
+       printk("=======================================================\n");
+       printk("Espressif ESP8089 SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", ESP8089_DRV_VERSION);
+
+       //rk29sdk_wifi_set_carddetect(0);
+       if(sif_get_bt_config() != 1)
+               //rk29sdk_wifi_power(0); libing
+                       rockchip_wifi_power(0);
+}
+
+void sif_platform_target_poweron(void)
+{
+       printk("=======================================================\n");
+       printk("==== Launching Wi-Fi driver! (Powered by Rockchip) ====\n");
+       printk("=======================================================\n");
+       printk("Espressif ESP8089 SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", ESP8089_DRV_VERSION);
+
+       if(sif_get_bt_config() == 1){
+               sif_platform_reset_target();
+       }
+       
+       //rk29sdk_wifi_power(1); libing
+       rockchip_wifi_power(1);
+        //rk29sdk_wifi_set_carddetect(1);
+}
+
+void sif_platform_target_speed(int high_speed)
+{
+}
+
+void sif_platform_check_r1_ready(struct esp_pub *epub)
+{
+}
+
+
+#ifdef ESP_ACK_INTERRUPT
+//extern void sdmmc_ack_interrupt(struct mmc_host *mmc); libing
+
+void sif_platform_ack_interrupt(struct esp_pub *epub)
+{
+        struct esp_sdio_ctrl *sctrl = NULL;
+        struct sdio_func *func = NULL;
+
+        ASSERT(epub != NULL);
+        sctrl = (struct esp_sdio_ctrl *)epub->sif;
+        func = sctrl->func;
+        ASSERT(func != NULL);
+
+        //sdmmc_ack_interrupt(func->card->host);libing
+
+}
+#endif //ESP_ACK_INTERRUPT
+ EXPORT_SYMBOL(rockchip_wifi_init_module);
+ EXPORT_SYMBOL(rockchip_wifi_exit_module);
+
+//late_initcall(esp_sdio_init);
+//module_exit(esp_sdio_exit);
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/sip2_common.h b/drivers/net/wireless/rockchip_wlan/esp8089/sip2_common.h
new file mode 100755 (executable)
index 0000000..9978f8c
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ *  Copyright (c) 2010 - 2012 Espressif System.
+ *
+ *   Common definitions of Serial Interconnctor Protocol
+ *
+ *   little endian
+ */
+
+#ifndef _SIP2_COMMON_H
+#define _SIP2_COMMON_H
+
+#ifdef __ets__
+#include "utils.h"
+#endif /*__ets__*/
+
+/* max 16 types */
+typedef enum {
+        SIP_CTRL = 0,
+        SIP_DATA,
+        SIP_DATA_AMPDU,
+} SIP_TYPE;
+
+typedef enum {
+        SIP_TX_CTRL_BUF = 0,  /* from host */
+        SIP_RX_CTRL_BUF,  /* to host */
+        SIP_TX_DATA_BUF, /* from host */
+        SIP_RX_DATA_BUF /* to host */
+} SIP_BUF_TYPE;
+
+enum sip_cmd_id {
+        SIP_CMD_GET_VER = 0,
+        SIP_CMD_WRITE_MEMORY,//1 ROM code
+        SIP_CMD_READ_MEMORY,//2
+        SIP_CMD_WRITE_REG,//3 ROM code
+        SIP_CMD_READ_REG,     //4
+        SIP_CMD_BOOTUP,//5 ROM code
+        SIP_CMD_COPYBACK,//6
+        SIP_CMD_INIT,          //7
+        SIP_CMD_SCAN,//8
+        SIP_CMD_SETKEY,//9
+        SIP_CMD_CONFIG,//10
+        SIP_CMD_BSS_INFO_UPDATE,//11
+        SIP_CMD_LOOPBACK,//12  ROM code
+        //do not add cmd before this line
+        SIP_CMD_SET_WMM_PARAM,
+        SIP_CMD_AMPDU_ACTION,
+        SIP_CMD_HB_REQ, //15
+        SIP_CMD_RESET_MAC, //16
+        SIP_CMD_PRE_DOWN,  //17
+        SIP_CMD_SLEEP,        /* for sleep testing */
+        SIP_CMD_WAKEUP,       /* for sleep testing */
+        SIP_CMD_DEBUG,          /* for general testing */
+        SIP_CMD_GET_FW_VER,  /* get fw rev. */
+        SIP_CMD_SETVIF,
+        SIP_CMD_SETSTA,
+        SIP_CMD_PS,
+       SIP_CMD_SUSPEND,
+        SIP_CMD_MAX
+};
+
+enum {
+        SIP_EVT_TARGET_ON = 0,    //
+        SIP_EVT_BOOTUP,//1 in ROM code
+        SIP_EVT_COPYBACK,//2
+        SIP_EVT_SCAN_RESULT,  //3
+        SIP_EVT_TX_STATUS,//4
+        SIP_EVT_CREDIT_RPT,     //5, in ROM code
+        SIP_EVT_ERROR,//6
+        SIP_EVT_LOOPBACK,//7, in ROM code
+        SIP_EVT_SNPRINTF_TO_HOST, //8  in ROM code
+        //do not add evt before this line
+        SIP_EVT_HB_ACK,  //9
+        SIP_EVT_RESET_MAC_ACK, //10
+        SIP_EVT_WAKEUP,//11        /* for sleep testing */
+        SIP_EVT_DEBUG,//12          /* for general testing */
+        SIP_EVT_PRINT_TO_HOST, //13
+        SIP_EVT_TRC_AMPDU, //14
+       SIP_EVT_ROC,              //15
+       SIP_EVT_RESETTING,
+       SIP_EVT_SLEEP,
+       SIP_EVT_TXIDLE,
+        SIP_EVT_MAX
+};
+
+#define SIP_IFIDX_MASK 0xf0
+#define SIP_IFIDX_S 4
+#define SIP_TYPE_MASK 0x0f
+#define SIP_TYPE_S 0
+
+#define SIP_HDR_GET_IFIDX(fc0) (((fc0) & SIP_IFIDX_MASK) >> SIP_IFIDX_S)
+#define SIP_HDR_SET_IFIDX(fc0, ifidx) ( (fc0) = ((fc0) & ~SIP_IFIDX_MASK) | ((ifidx) << SIP_IFIDX_S & SIP_IFIDX_MASK) )
+#define SIP_HDR_GET_TYPE(fc0) ((fc0) & SIP_TYPE_MASK )
+/* assume type field is cleared */
+#define SIP_HDR_SET_TYPE(fc0, type) ((fc0) = ((fc0) & ~ SIP_TYPE_MASK) | ((type) & SIP_TYPE_MASK))
+
+/* sip 2.0, not hybrid header so far */
+#define SIP_HDR_IS_CTRL(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_CTRL)
+#define SIP_HDR_IS_DATA(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA)
+#define SIP_HDR_IS_AMPDU(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA_AMPDU)
+
+/* fc[1] flags, only for data pkt. Ctrl pkts use fc[1] as eventID */
+#define SIP_HDR_SET_FLAGS(hdr, flags) ((hdr)->fc[1] |= (flags))
+#define SIP_HDR_F_MORE_PKT 0x1
+#define SIP_HDR_F_NEED_CRDT_RPT 0x2
+#define SIP_HDR_F_SYNC 0x4
+#define SIP_HDR_F_SYNC_RESET 0x8
+#define SIP_HDR_F_PM_TURNING_ON 0x10
+#define SIP_HDR_F_PM_TURNING_OFF 0x20
+
+#define SIP_HDR_NEED_CREDIT_UPDATE(hdr) ((hdr)->fc[1] & SIP_HDR_F_NEED_CRDT_RPT)
+#define SIP_HDR_IS_MORE_PKT(hdr) ((hdr)->fc[1] & SIP_HDR_F_MORE_PKT)
+#define SIP_HDR_IS_CRDT_RPT(hdr) ((hdr)->fc[1] & SIP_HDR_F_CRDT_RPT)
+#define SIP_HDR_IS_SYNC(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC)
+#define SIP_HDR_IS_SYNC_RESET(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC_RESET)
+#define SIP_HDR_IS_SYNC_PKT(hdr) (SIP_HDR_IS_SYNC(hdr) | SIP_HDR_IS_SYNC_RESET(hdr))
+#define SIP_HDR_SET_SYNC(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC)
+#define SIP_HDR_SET_SYNC_RESET(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC_RESET)
+#define SIP_HDR_SET_MORE_PKT(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_MORE_PKT)
+#define SIP_HDR_SET_PM_TURNING_ON(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_ON)
+#define SIP_HDR_IS_PM_TURNING_ON(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_ON)
+#define SIP_HDR_SET_PM_TURNING_OFF(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_OFF)
+#define SIP_HDR_IS_PM_TURNING_OFF(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_OFF)
+
+/*
+ * fc[0]: first 4bit: ifidx; last 4bit: type
+ * fc[1]: flags
+ *
+ *   Don't touch the header definitons
+ */
+struct sip_hdr_min {
+        u8 fc[2];
+        __le16 len;
+} __packed;
+
+/* not more than 4byte long */
+struct sip_tx_data_info {
+        u8 tid;
+        u8 ac;
+        u8 p2p:1,
+           enc_flag:7;
+        u8 hw_kid;
+}  __packed;
+
+/* NB: this structure should be not more than 4byte !! */
+struct sip_tx_info {
+        union {
+                u32 cmdid;
+                struct sip_tx_data_info dinfo;
+        } u;
+} __packed;
+
+struct sip_hdr {
+        u8 fc[2];  //fc[0]: type and ifidx ; fc[1] is eventID if the first ctrl pkt in the chain. data pkt still can use fc[1] to set flag
+        __le16 len;
+        union {
+                volatile u32 recycled_credits; /* last 12bits is credits, first 20 bits is actual length of the first pkt in the chain */
+                struct sip_tx_info tx_info;
+        } u;
+        u32 seq;
+} __packed;
+
+#define h_credits u.recycled_credits
+#define c_evtid fc[1]
+#define c_cmdid u.tx_info.u.cmdid
+#define d_ac u.tx_info.u.dinfo.ac
+#define d_tid  u.tx_info.u.dinfo.tid
+#define d_p2p   u.tx_info.u.dinfo.p2p
+#define d_enc_flag u.tx_info.u.dinfo.enc_flag
+#define d_hw_kid   u.tx_info.u.dinfo.hw_kid
+
+#define SIP_CREDITS_MASK  0xfff  /* last 12 bits */
+
+#ifdef HOST_RC
+
+#define RC_CNT_MASK 0xf
+
+struct sip_rc_status {
+        u32 rc_map;
+        union {
+                u32 rc_cnt1:4,
+                    rc_cnt2:4,
+                    rc_cnt3:4,
+                    rc_cnt4:4,
+                    rc_cnt5:4;
+
+                u32 rc_cnt_store;
+        };
+};
+
+/* copy from mac80211.h */
+struct sip_tx_rc {
+        struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
+        s8 rts_cts_rate_idx;
+};
+#endif /* HOST_RC */
+
+#define SIP_HDR_MIN_LEN 4
+#define SIP_HDR_LEN            sizeof(struct sip_hdr)
+#define SIP_CTRL_HDR_LEN       SIP_HDR_LEN  /* same as sip_hdr in sip2 design */
+#define SIP_BOOT_BUF_SIZE 256
+#define SIP_CTRL_BUF_SZ 256 /* too much?? */
+#define SIP_CTRL_BUF_N 6
+#define SIP_CTRL_TXBUF_N 2
+#define SIP_CTRL_RXBUF_N 4
+
+/* WAR for mblk */
+#define SIP_RX_ADDR_PREFIX_MASK 0xfc000000
+#define SIP_RX_ADDR_SHIFT 6  /* [31:5],  shift 6 bits*/
+
+struct sip_cmd_write_memory {
+        u32 addr;
+        u32 len;
+} __packed;
+
+struct sip_cmd_read_memory {
+        u32 addr;
+        u32 len;
+} __packed;
+
+struct sip_cmd_write_reg {
+        u32 addr;
+        u32 val;
+} __packed;
+
+struct sip_cmd_bootup {
+        u32 boot_addr;
+} __packed;
+
+struct sip_cmd_loopback {
+        u32 txlen;       //host to target packet len, 0 means no txpacket
+        u32 rxlen;      //target to host packet len, 0 means no rxpacket
+        u32 pack_id;   //sequence of packet
+} __packed;
+
+struct sip_evt_loopback {
+        u32 txlen;       //host to target packet len, 0 means no txpacket
+        u32 rxlen;      //target to host packet len, 0 means no rxpacket
+        u32 pack_id;   //sequence of packet
+} __packed;
+
+struct sip_cmd_copyback {
+        u32 addr;
+        u32 len;
+} __packed;
+
+struct sip_cmd_scan {
+//        u8  ssid[32];
+        u8 ssid_len;
+//        u8 hw_channel[14];
+        u8 n_channels;
+        u8 ie_len;
+        u8 aborted;
+} __packed; // ie[] append at the end
+
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif /* ETH_ALEN */
+
+struct sip_cmd_setkey {
+        u8 bssid_no;
+        u8 addr[ETH_ALEN];
+        u8 alg;
+        u8 keyidx;
+        u8 hw_key_idx;
+        u8 flags;
+        u8 keylen;
+        u8 key[32];
+} __packed;
+
+struct sip_cmd_config {
+        u16  center_freq;
+        u16  duration;
+} __packed;
+
+struct sip_cmd_bss_info_update {
+        u8  bssid[ETH_ALEN];
+        u16 isassoc;
+        u32 beacon_int;
+        u8  bssid_no;
+} __packed;
+
+struct sip_evt_bootup {
+        u16 tx_blksz;
+        u8 mac_addr[ETH_ALEN];
+        /* anything else ? */
+} __packed;
+
+struct sip_cmd_setvif {
+        u8 index;
+        u8 mac[ETH_ALEN];
+        u8 set;
+        u8 op_mode;
+        u8 is_p2p;
+} __packed;
+
+enum esp_ieee80211_phytype{
+        ESP_IEEE80211_T_CCK = 0,
+        ESP_IEEE80211_T_OFDM = 1,
+        ESP_IEEE80211_T_HT20_L = 2,
+        ESP_IEEE80211_T_HT20_S = 3,
+};
+
+struct sip_cmd_setsta {
+        u8 ifidx;
+        u8 index;
+        u8 set;
+        u8 phymode;
+        u8 mac[ETH_ALEN];
+       u16 aid;
+        u8 ampdu_factor;
+        u8 ampdu_density;
+       u16 resv;
+} __packed;
+
+struct sip_cmd_ps {
+       u8 dtim_period;
+       u8 max_sleep_period;
+        u8 on;
+        u8 resv;
+} __packed;
+
+struct sip_cmd_suspend {
+       u8 suspend;
+       u8 resv[3];
+} __packed;
+
+#define SIP_DUMP_RPBM_ERR      BIT(0)
+#define SIP_RXABORT_FIXED      BIT(1)
+#define SIP_SUPPORT_BGSCAN     BIT(2)
+struct sip_evt_bootup2 {
+        u16 tx_blksz;
+        u8 mac_addr[ETH_ALEN];
+        u16 rx_blksz;
+        u8 credit_to_reserve;
+        u8 options;
+       s16 noise_floor;
+       u8 resv[2];
+        /* anything else ? */
+} __packed;
+
+typedef enum {
+        TRC_TX_AMPDU_STOPPED = 1,
+        TRC_TX_AMPDU_OPERATIONAL,
+        TRC_TX_AMPDU_WAIT_STOP,
+        TRC_TX_AMPDU_WAIT_OPERATIONAL,
+        TRC_TX_AMPDU_START,
+} trc_ampdu_state_t;
+
+struct sip_evt_trc_ampdu {
+        u8 state;
+        u8 tid;
+        u8 addr[ETH_ALEN];
+} __packed;
+
+struct sip_cmd_set_wmm_params {
+        u8 aci;
+        u8 aifs;
+        u8 ecw_min;
+        u8 ecw_max;
+        u16 txop_us;
+} __packed;
+
+#define SIP_AMPDU_RX_START 0
+#define SIP_AMPDU_RX_STOP 1
+#define SIP_AMPDU_TX_OPERATIONAL 2
+#define SIP_AMPDU_TX_STOP 3
+struct sip_cmd_ampdu_action {
+        u8 action;
+        u8 index;
+        u8 tid;
+        u8 win_size;
+        u16 ssn;
+        u8 addr[ETH_ALEN];
+} __packed;
+
+#define SIP_TX_ST_OK 0
+#define SIP_TX_ST_NOEB 1
+#define SIP_TX_ST_ACKTO 2
+#define SIP_TX_ST_ENCERR 3
+
+//NB: sip_tx_status must be 4 bytes aligned
+struct sip_tx_status {
+        u32 sip_seq;
+#ifdef HOST_RC
+        struct sip_rc_status rcstatus;
+#endif /* HOST_RC */
+        u8 errno;  /* success or failure code */
+        u8 rate_index;
+        char ack_signal;
+        u8 pad;
+} __packed;
+
+struct sip_evt_tx_report {
+        u32 pkts;
+        struct sip_tx_status status[0];
+} __packed;
+
+struct sip_evt_tx_mblk {
+        u32 mblk_map;
+} __packed;
+
+struct sip_evt_scan_report {
+        u16 scan_id;
+        u16 aborted;
+} __packed;
+
+struct sip_evt_roc {
+     u16    state;     //start:1, end :0
+     u16    is_ok;
+} __packed;
+
+struct sip_evt_txidle {
+       u32     last_seq;
+} __packed;
+
+/*
+ *  for mblk direct memory access, no need for sip_hdr. tx: first 2k for contrl msg,
+ *  rest of 14k for data.  rx, same.
+ */
+#ifdef TEST_MODE
+
+struct sip_cmd_sleep {
+        u32  sleep_mode;
+        u32  sleep_tm_ms;
+        u32  wakeup_tm_ms;            //zero: after receive bcn, then sleep, nozero: delay nozero ms to sleep
+        u32  sleep_times;                 //zero: always sleep, nozero: after nozero number sleep/wakeup, then end up sleep
+} __packed;
+
+struct sip_cmd_wakeup {
+        u32     check_data;            //0:copy to event
+} __packed;
+
+struct sip_evt_wakeup {
+        u32    check_data;
+} __packed;
+
+//general debug command
+struct sip_cmd_debug {
+        u32  cmd_type;
+        u32  para_num;
+        u32  para[10];
+} __packed;
+
+struct sip_evt_debug {
+        u16    len;
+        u32    results[8];
+        u16    pad;
+} __packed;
+
+#endif  //ifdef TEST_MODE
+
+#endif /* _SIP_COMMON_H_ */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/slc_host_register.h b/drivers/net/wireless/rockchip_wlan/esp8089/slc_host_register.h
new file mode 100755 (executable)
index 0000000..c628dc3
--- /dev/null
@@ -0,0 +1,242 @@
+//Generated at 2012-10-23 20:11:08\r
+/*\r
+ *  Copyright (c) 2011 Espressif System\r
+ *\r
+ */\r
+\r
+#ifndef SLC_HOST_REGISTER_H_INCLUDED\r
+#define SLC_HOST_REGISTER_H_INCLUDED\r
+\r
+/* #define REG_SLC_HOST_BASE  0x00000000 */\r
+/* skip the token1, since reading it will clean the credit */\r
+#define REG_SLC_HOST_BASE  0x00000000\r
+\r
+\r
+#define SLC_HOST_PF                          (REG_SLC_HOST_BASE + 0x0)\r
+#define SLC_HOST_TOKEN_RDATA                 (REG_SLC_HOST_BASE + 0x4)\r
+#define SLC_HOST_RX_PF_EOF 0x0000000F\r
+#define SLC_HOST_RX_PF_EOF_S                 28\r
+#define SLC_HOST_TOKEN1 0x00000FFF\r
+#define SLC_HOST_TOKEN1_S 16\r
+#define SLC_HOST_RX_PF_VALID (BIT(15))\r
+#define SLC_HOST_TOKEN0               0x00000FFF\r
+#define SLC_HOST_TOKEN0_S 0\r
+\r
+#define SLC_HOST_TOKEN0_MASK SLC_HOST_TOKEN0\r
+\r
+#define SLC_HOST_INT_RAW                     (REG_SLC_HOST_BASE + 0x8)\r
+#define SLC_HOST_EXT_BIT3_INT_RAW (BIT(22))\r
+#define SLC_HOST_EXT_BIT2_INT_RAW (BIT(21))\r
+#define SLC_HOST_EXT_BIT1_INT_RAW (BIT(20))\r
+#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_RAW (BIT(19))\r
+#define SLC_HOST_RX_PF_VALID_INT_RAW (BIT(18))\r
+#define SLC_HOST_TX_OVF_INT_RAW (BIT(17))\r
+#define SLC_HOST_RX_UDF_INT_RAW (BIT(16))\r
+#define SLC_HOST_TX_START_INT_RAW (BIT(15))\r
+#define SLC_HOST_RX_START_INT_RAW (BIT(14))\r
+#define SLC_HOST_RX_EOF_INT_RAW (BIT(13))\r
+#define SLC_HOST_RX_SOF_INT_RAW (BIT(12))\r
+#define SLC_HOST_TOKEN1_0TO1_INT_RAW (BIT(11))\r
+#define SLC_HOST_TOKEN0_0TO1_INT_RAW (BIT(10))\r
+#define SLC_HOST_TOKEN1_1TO0_INT_RAW (BIT(9))\r
+#define SLC_HOST_TOKEN0_1TO0_INT_RAW (BIT(8))\r
+#define SLC_HOST_TOHOST_BIT7_INT_RAW (BIT(7))\r
+#define SLC_HOST_TOHOST_BIT6_INT_RAW (BIT(6))\r
+#define SLC_HOST_TOHOST_BIT5_INT_RAW (BIT(5))\r
+#define SLC_HOST_TOHOST_BIT4_INT_RAW (BIT(4))\r
+#define SLC_HOST_TOHOST_BIT3_INT_RAW (BIT(3))\r
+#define SLC_HOST_TOHOST_BIT2_INT_RAW (BIT(2))\r
+#define SLC_HOST_TOHOST_BIT1_INT_RAW (BIT(1))\r
+#define SLC_HOST_TOHOST_BIT0_INT_RAW (BIT(0))\r
+\r
+#define SLC_HOST_STATE_W0                    (REG_SLC_HOST_BASE + 0xC)\r
+#define SLC_HOST_STATE3 0x000000FF\r
+#define SLC_HOST_STATE3_S 24\r
+#define SLC_HOST_STATE2 0x000000FF\r
+#define SLC_HOST_STATE2_S 16\r
+#define SLC_HOST_STATE1 0x000000FF\r
+#define SLC_HOST_STATE1_S 8\r
+#define SLC_HOST_STATE0 0x000000FF\r
+#define SLC_HOST_STATE0_S 0\r
+\r
+#define SLC_HOST_STATE_W1                    (REG_SLC_HOST_BASE + 0x10)\r
+#define SLC_HOST_STATE7 0x000000FF\r
+#define SLC_HOST_STATE7_S 24\r
+#define SLC_HOST_STATE6 0x000000FF\r
+#define SLC_HOST_STATE6_S 16\r
+#define SLC_HOST_STATE5 0x000000FF\r
+#define SLC_HOST_STATE5_S 8\r
+#define SLC_HOST_STATE4 0x000000FF\r
+#define SLC_HOST_STATE4_S 0\r
+\r
+#define SLC_HOST_CONF_W0                     (REG_SLC_HOST_BASE + 0x14)\r
+#define SLC_HOST_CONF3 0x000000FF\r
+#define SLC_HOST_CONF3_S 24\r
+#define SLC_HOST_CONF2 0x000000FF\r
+#define SLC_HOST_CONF2_S 16\r
+#define SLC_HOST_CONF1 0x000000FF\r
+#define SLC_HOST_CONF1_S 8\r
+#define SLC_HOST_CONF0 0x000000FF\r
+#define SLC_HOST_CONF0_S 0\r
+\r
+#define SLC_HOST_CONF_W1                     (REG_SLC_HOST_BASE + 0x18)\r
+#define SLC_HOST_CONF7 0x000000FF\r
+#define SLC_HOST_CONF7_S 24\r
+#define SLC_HOST_CONF6 0x000000FF\r
+#define SLC_HOST_CONF6_S 16\r
+#define SLC_HOST_CONF5 0x000000FF\r
+#define SLC_HOST_CONF5_S 8\r
+#define SLC_HOST_CONF4 0x000000FF\r
+#define SLC_HOST_CONF4_S 0\r
+\r
+#define SLC_HOST_INT_ST                      (REG_SLC_HOST_BASE + 0x1C)\r
+#define SLC_HOST_RX_ST (BIT(23))\r
+#define SLC_HOST_EXT_BIT3_INT_ST (BIT(22))\r
+#define SLC_HOST_EXT_BIT2_INT_ST (BIT(21))\r
+#define SLC_HOST_EXT_BIT1_INT_ST (BIT(20))\r
+#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_ST (BIT(19))\r
+#define SLC_HOST_RX_PF_VALID_INT_ST (BIT(18))\r
+#define SLC_HOST_TX_OVF_INT_ST (BIT(17))\r
+#define SLC_HOST_RX_UDF_INT_ST (BIT(16))\r
+#define SLC_HOST_TX_START_INT_ST (BIT(15))\r
+#define SLC_HOST_RX_START_INT_ST (BIT(14))\r
+#define SLC_HOST_RX_EOF_INT_ST (BIT(13))\r
+#define SLC_HOST_RX_SOF_INT_ST (BIT(12))\r
+#define SLC_HOST_TOKEN1_0TO1_INT_ST (BIT(11))\r
+#define SLC_HOST_TOKEN0_0TO1_INT_ST (BIT(10))\r
+#define SLC_HOST_TOKEN1_1TO0_INT_ST (BIT(9))\r
+#define SLC_HOST_TOKEN0_1TO0_INT_ST (BIT(8))\r
+#define SLC_HOST_TOHOST_BIT7_INT_ST (BIT(7))\r
+#define SLC_HOST_TOHOST_BIT6_INT_ST (BIT(6))\r
+#define SLC_HOST_TOHOST_BIT5_INT_ST (BIT(5))\r
+#define SLC_HOST_TOHOST_BIT4_INT_ST (BIT(4))\r
+#define SLC_HOST_TOHOST_BIT3_INT_ST (BIT(3))\r
+#define SLC_HOST_TOHOST_BIT2_INT_ST (BIT(2))\r
+#define SLC_HOST_TOHOST_BIT1_INT_ST (BIT(1))\r
+#define SLC_HOST_TOHOST_BIT0_INT_ST (BIT(0))\r
+\r
+#define SLC_HOST_CONF_W2                     (REG_SLC_HOST_BASE + 0x20)\r
+#define SLC_HOST_CONF11 0x000000FF\r
+#define SLC_HOST_CONF11_S 24\r
+#define SLC_HOST_CONF10 0x000000FF\r
+#define SLC_HOST_CONF10_S 16\r
+#define SLC_HOST_CONF9 0x000000FF\r
+#define SLC_HOST_CONF9_S 8\r
+#define SLC_HOST_CONF8 0x000000FF\r
+#define SLC_HOST_CONF8_S 0\r
+\r
+#define SLC_HOST_CONF_W3                     (REG_SLC_HOST_BASE + 0x24)\r
+#define SLC_HOST_CONF15 0x000000FF\r
+#define SLC_HOST_CONF15_S 24\r
+#define SLC_HOST_CONF14 0x000000FF\r
+#define SLC_HOST_CONF14_S 16\r
+#define SLC_HOST_CONF13 0x000000FF\r
+#define SLC_HOST_CONF13_S 8\r
+#define SLC_HOST_CONF12 0x000000FF\r
+#define SLC_HOST_CONF12_S 0\r
+\r
+#define SLC_HOST_GEN_TXDONE_INT  BIT(16)\r
+#define SLC_HOST_GEN_RXDONE_INT  BIT(17)\r
+\r
+#define SLC_HOST_CONF_W4                     (REG_SLC_HOST_BASE + 0x28)\r
+#define SLC_HOST_CONF19 0x000000FF\r
+#define SLC_HOST_CONF19_S 24\r
+#define SLC_HOST_CONF18 0x000000FF\r
+#define SLC_HOST_CONF18_S 16\r
+#define SLC_HOST_CONF17 0x000000FF\r
+#define SLC_HOST_CONF17_S 8\r
+#define SLC_HOST_CONF16 0x000000FF\r
+#define SLC_HOST_CONF16_S 0\r
+\r
+#define SLC_HOST_TOKEN_WDATA                 (REG_SLC_HOST_BASE + 0x2C)\r
+#define SLC_HOST_TOKEN1_WD 0x00000FFF\r
+#define SLC_HOST_TOKEN1_WD_S 16\r
+#define SLC_HOST_TOKEN0_WD 0x00000FFF\r
+#define SLC_HOST_TOKEN0_WD_S 0\r
+\r
+#define SLC_HOST_INT_CLR                     (REG_SLC_HOST_BASE + 0x30)\r
+#define SLC_HOST_TOKEN1_WR (BIT(31))\r
+#define SLC_HOST_TOKEN0_WR (BIT(30))\r
+#define SLC_HOST_TOKEN1_DEC (BIT(29))\r
+#define SLC_HOST_TOKEN0_DEC (BIT(28))\r
+#define SLC_HOST_EXT_BIT3_INT_CLR (BIT(22))\r
+#define SLC_HOST_EXT_BIT2_INT_CLR (BIT(21))\r
+#define SLC_HOST_EXT_BIT1_INT_CLR (BIT(20))\r
+#define SLC_HOST_EXT_BIT0_INT_CLR (BIT(19))\r
+#define SLC_HOST_RX_PF_VALID_INT_CLR (BIT(18))\r
+#define SLC_HOST_TX_OVF_INT_CLR (BIT(17))\r
+#define SLC_HOST_RX_UDF_INT_CLR (BIT(16))\r
+#define SLC_HOST_TX_START_INT_CLR (BIT(15))\r
+#define SLC_HOST_RX_START_INT_CLR (BIT(14))\r
+#define SLC_HOST_RX_EOF_INT_CLR (BIT(13))\r
+#define SLC_HOST_RX_SOF_INT_CLR (BIT(12))\r
+#define SLC_HOST_TOKEN1_0TO1_INT_CLR (BIT(11))\r
+#define SLC_HOST_TOKEN0_0TO1_INT_CLR (BIT(10))\r
+#define SLC_HOST_TOKEN1_1TO0_INT_CLR (BIT(9))\r
+#define SLC_HOST_TOKEN0_1TO0_INT_CLR (BIT(8))\r
+#define SLC_HOST_TOHOST_BIT7_INT_CLR (BIT(7))\r
+#define SLC_HOST_TOHOST_BIT6_INT_CLR (BIT(6))\r
+#define SLC_HOST_TOHOST_BIT5_INT_CLR (BIT(5))\r
+#define SLC_HOST_TOHOST_BIT4_INT_CLR (BIT(4))\r
+#define SLC_HOST_TOHOST_BIT3_INT_CLR (BIT(3))\r
+#define SLC_HOST_TOHOST_BIT2_INT_CLR (BIT(2))\r
+#define SLC_HOST_TOHOST_BIT1_INT_CLR (BIT(1))\r
+#define SLC_HOST_TOHOST_BIT0_INT_CLR (BIT(0))\r
+\r
+#define SLC_HOST_INT_ENA                     (REG_SLC_HOST_BASE + 0x34)\r
+#define SLC_HOST_EXT_BIT3_INT_ENA (BIT(22))\r
+#define SLC_HOST_EXT_BIT2_INT_ENA (BIT(21))\r
+#define SLC_HOST_EXT_BIT1_INT_ENA (BIT(20))\r
+#define SLC_HOST_EXT_BIT0_INT_ENA (BIT(19))\r
+#define SLC_HOST_RX_PF_VALID_INT_ENA (BIT(18))\r
+#define SLC_HOST_TX_OVF_INT_ENA (BIT(17))\r
+#define SLC_HOST_RX_UDF_INT_ENA (BIT(16))\r
+#define SLC_HOST_TX_START_INT_ENA (BIT(15))\r
+#define SLC_HOST_RX_START_INT_ENA (BIT(14))\r
+#define SLC_HOST_RX_EOF_INT_ENA (BIT(13))\r
+#define SLC_HOST_RX_SOF_INT_ENA (BIT(12))\r
+#define SLC_HOST_TOKEN1_0TO1_INT_ENA (BIT(11))\r
+#define SLC_HOST_TOKEN0_0TO1_INT_ENA (BIT(10))\r
+#define SLC_HOST_TOKEN1_1TO0_INT_ENA (BIT(9))\r
+#define SLC_HOST_TOKEN0_1TO0_INT_ENA (BIT(8))\r
+#define SLC_HOST_TOHOST_BIT7_INT_ENA (BIT(7))\r
+#define SLC_HOST_TOHOST_BIT6_INT_ENA (BIT(6))\r
+#define SLC_HOST_TOHOST_BIT5_INT_ENA (BIT(5))\r
+#define SLC_HOST_TOHOST_BIT4_INT_ENA (BIT(4))\r
+#define SLC_HOST_TOHOST_BIT3_INT_ENA (BIT(3))\r
+#define SLC_HOST_TOHOST_BIT2_INT_ENA (BIT(2))\r
+#define SLC_HOST_TOHOST_BIT1_INT_ENA (BIT(1))\r
+#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT(0))\r
+\r
+#define SLC_HOST_CONF_W5                     (REG_SLC_HOST_BASE + 0x3C)\r
+#define SLC_HOST_CONF23 0x000000FF\r
+#define SLC_HOST_CONF23_S 24\r
+#define SLC_HOST_CONF22 0x000000FF\r
+#define SLC_HOST_CONF22_S 16\r
+#define SLC_HOST_CONF21 0x000000FF\r
+#define SLC_HOST_CONF21_S 8\r
+#define SLC_HOST_CONF20 0x000000FF\r
+#define SLC_HOST_CONF20_S 0\r
+\r
+\r
+#define SLC_HOST_DATE                         (REG_SLC_HOST_BASE + 0x78)\r
+#define SLC_HOST_ID                           (REG_SLC_HOST_BASE + 0x7C)\r
+\r
+#define SLC_ADDR_WINDOW_CLEAR_MASK   (~(0xf<<12))\r
+#define SLC_FROM_HOST_ADDR_WINDOW  (0x1<<12)\r
+#define SLC_TO_HOST_ADDR_WINDOW    (0x3<<12)\r
+\r
+#define SLC_SET_FROM_HOST_ADDR_WINDOW(v)   do { \\r
+        (v) &= 0xffff;    \\r
+       (v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \\r
+       (v) |= SLC_FROM_HOST_ADDR_WINDOW; \\r
+} while (0);\r
+\r
+#define SLC_SET_TO_HOST_ADDR_WINDOW(v)   do { \\r
+        (v) &= 0xffff;    \\r
+       (v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \\r
+       (v) |= SLC_TO_HOST_ADDR_WINDOW; \\r
+} while (0);\r
+\r
+\r
+#endif // SLC_HOST_REGISTER_H_INCLUDED\r
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/spi_sif_esp.c b/drivers/net/wireless/rockchip_wlan/esp8089/spi_sif_esp.c
new file mode 100755 (executable)
index 0000000..49571a8
--- /dev/null
@@ -0,0 +1,1938 @@
+/*
+ * Copyright (c) 2010 -2013 Espressif System.
+ *
+ *   sdio serial i/f driver
+ *    - sdio device control routines
+ *    - sync/async DMA/PIO read/write
+ *
+ */
+#ifdef ESP_USE_SPI
+
+#include <linux/module.h>
+#include <net/mac80211.h>
+#include <linux/time.h>
+#include <linux/pm.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+
+
+#include "esp_pub.h"
+#include "esp_sif.h"
+#include "esp_sip.h"
+#include "esp_debug.h"
+#include "slc_host_register.h"
+#include "esp_version.h"
+#include "esp_ctrl.h"
+#ifdef ANDROID
+#include "esp_android.h"
+#endif /* ANDROID */
+#ifdef USE_EXT_GPIO
+#include "esp_ext.h"
+#endif /* USE_EXT_GPIO */
+
+static int __init esp_spi_init(void);
+static void __exit esp_spi_exit(void);
+
+#define SPI_BLOCK_SIZE              (512)
+
+#define MAX_BUF_SIZE        (48*1024)
+
+static unsigned char *buf_addr = NULL;
+static unsigned char *tx_cmd;
+static unsigned char *rx_cmd;
+
+struct task_struct *sif_irq_thread;
+
+#define ESP_DMA_IBUFSZ   2048
+
+//unsigned int esp_msg_level = 0;
+unsigned int esp_msg_level = ESP_DBG_ERROR | ESP_SHOW;
+
+static struct semaphore esp_powerup_sem;
+
+static enum esp_sdio_state sif_sdio_state;
+struct esp_spi_ctrl *sif_sctrl = NULL;
+
+#ifdef ESP_ANDROID_LOGGER
+bool log_off = false;
+#endif /* ESP_ANDROID_LOGGER */
+
+struct sif_req * sif_alloc_req(struct esp_spi_ctrl *sctrl);
+
+#include "spi_stub.c"
+
+void sif_lock_bus(struct esp_pub *epub)
+{
+        EPUB_FUNC_CHECK(epub);
+
+        spi_bus_lock(EPUB_TO_FUNC(epub)->master);
+}
+
+void sif_unlock_bus(struct esp_pub *epub)
+{
+        EPUB_FUNC_CHECK(epub);
+
+        spi_bus_unlock(EPUB_TO_FUNC(epub)->master);
+}
+
+int sif_spi_write_then_read(struct spi_device *spi, unsigned char* bufwrite, int sizesend, unsigned char* bufread, int sizeread)
+{
+       int error;
+
+        error = spi_write_then_read(spi, bufwrite,sizesend, bufread, sizeread);
+    
+       if (error) {
+               esp_dbg(ESP_DBG_ERROR, "%s: failed, error: %d\n",
+                       __func__, error);
+               return error;
+       }
+
+       return 0;
+}
+
+
+int sif_spi_write_async_read(struct spi_device *spi, unsigned char* bufwrite,unsigned char* bufread,int size)
+{
+       struct spi_transfer xfer = {
+              .rx_buf          = bufread,
+               .tx_buf         = bufwrite,
+               .len            = size,
+               .bits_per_word  = 8,
+               .speed_hz       = SPI_FREQ,
+       };
+       struct spi_message msg;
+       int error;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       error = spi_sync_locked(spi, &msg);
+       if (error) {
+               esp_dbg(ESP_DBG_ERROR, "%s: failed, error: %d\n",
+                       __func__, error);
+               return error;
+       }
+
+       return 0;
+}
+
+int sif_spi_write_raw(struct spi_device *spi, unsigned char* buf, int size)
+{
+       int err;
+       struct spi_transfer xfer = {
+               .tx_buf         = buf,
+               .len            = size,
+               .bits_per_word  = 8,
+               .speed_hz       = SPI_FREQ,
+       };
+       struct spi_message msg;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+       
+       err = spi_sync_locked(spi, &msg);
+
+       if (err) {
+               esp_dbg(ESP_DBG_ERROR, "%s: failed, error: %d\n",
+                       __func__, err);
+               return err;
+       }
+
+       return 0;
+}
+
+int sif_spi_read_raw(struct spi_device *spi, unsigned char* buf, int size)
+{
+        memset(buf,0xff,size);
+        return sif_spi_write_async_read(spi,buf,buf,size);
+}
+
+int sif_spi_write_bytes(struct spi_device *spi, unsigned int addr, unsigned char *src,int count, int check_idle)
+{
+       int i;
+        int pos,len;       
+        unsigned char *tx_data = (unsigned char*)src;
+        int err_ret = 0;     
+
+       u32 timeout = 25000;
+       u32 busy_state = 0x00;
+       
+       ASSERT(spi != NULL);
+              
+       if (check_idle) {
+               timeout = 25000;
+               do {
+                       busy_state = 0x00;
+                       sif_spi_read_raw(spi, (u8 *)&busy_state, 4);
+            
+                    if(busy_state != 0xffffffff)
+                            esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); 
+                        
+               } while (busy_state != 0xffffffff && --timeout > 0);
+       }
+
+       if (timeout < 24000)
+               esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout); 
+
+
+         if(count > 512 )
+        {
+                err_ret = -1;
+                goto goto_err;
+        }
+        
+        tx_cmd[0]=0x75;
+
+        if( addr >= (1<<17) )
+        {
+                err_ret = -2;
+                goto goto_err;
+
+        }
+        else
+        {
+             tx_cmd[1]=0x90|0x04|(addr>>15);    //0x94;
+             tx_cmd[2]=addr>>7;    
+
+             if(count == 512 )
+            {
+                    tx_cmd[3]=( addr<<1|0x0 );
+                    tx_cmd[4]= 0x00;     //0x08;
+            }
+            else
+            {
+                    tx_cmd[3]=( addr<<1|count>>7 );
+                    tx_cmd[4]= count;     //0x08;
+            }
+        }
+        
+        tx_cmd[5]=0x01;
+        pos = 5+1;
+
+//Add cmd respon
+        memset(tx_cmd+pos,0xff,CMD_RESP_SIZE);
+        pos =pos+ CMD_RESP_SIZE;
+
+//Add token        
+        tx_cmd[pos]=0xFE;
+        pos = pos+1;
+
+//Add data  
+        memcpy(tx_cmd+pos,tx_data,count);
+        pos = pos+count;
+
+//Add data respon
+        memset(tx_cmd+pos,0xff,DATA_RESP_SIZE_W);
+        pos = pos+ DATA_RESP_SIZE_W;
+
+        
+        if( pos%8 )
+        {
+            len = (8 - pos%8);
+            memset(tx_cmd+pos,0xff,len);
+        }
+        else
+            len = 0;
+        sif_spi_write_async_read(spi, tx_cmd,tx_cmd,pos+len);
+        
+        
+
+        pos = 5+1;
+        for(i=0;i<CMD_RESP_SIZE;i++)
+        {
+                if(tx_cmd[pos+i] == 0x00 && tx_cmd[pos+i-1] == 0xff)
+                {
+                        if(tx_cmd[pos+i+1] == 0x00 && tx_cmd[pos+i+2] == 0xff)
+                            break;      
+                }
+        }
+        if(i>=CMD_RESP_SIZE)
+        {
+                esp_dbg(ESP_DBG_ERROR, "write data resp 0x00 no recv\n");
+               err_ret = -3;
+                goto goto_err;
+       }
+        
+        pos = pos+CMD_RESP_SIZE+count+1;
+        for(i=0;i<DATA_RESP_SIZE_W;i++)
+        {
+                if(tx_cmd[pos+i] == 0xE5)
+                {
+                       //esp_dbg(ESP_DBG_ERROR, "0xE5 pos:%d",i);
+                        for(i++;i<DATA_RESP_SIZE_W;i++)
+                        {
+                             if( tx_cmd[pos+i] == 0xFF)
+                             {
+                               //esp_dbg(ESP_DBG_ERROR, "0xFF pos:%d",i);
+                                  break;
+                             }
+                        }
+                        break;      
+                }
+        }
+        if(i>=DATA_RESP_SIZE_W)
+        {
+                esp_dbg(ESP_DBG_ERROR, "write data resp 0xE5 no recv\n");
+               err_ret = -3;
+                goto goto_err;
+       }
+
+goto_err:
+       return err_ret;
+}
+
+int sif_spi_write_blocks(struct spi_device *spi, unsigned int addr,unsigned char *src, int count, int check_idle)
+{
+       int err_ret = 0;
+        int i,j;
+        int n;
+        int pos,len; 
+        unsigned char *tx_data = (unsigned char*)src;
+       u32 busy_state = 0x00;
+       u32 timeout = 25000;    
+       //esp_dbg(ESP_DBG_ERROR, "Block Write ---------");    
+      
+       ASSERT(spi != NULL);
+       
+
+#if 1  
+       if (check_idle) {
+               timeout = 25000;
+               do {
+                       busy_state = 0x00;
+                       sif_spi_read_raw(spi, (u8 *)&busy_state, 4);
+            
+                    if(busy_state != 0xffffffff)
+                            esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); 
+
+               } while (busy_state != 0xffffffff && --timeout > 0);
+       }
+
+       if (timeout < 24000)
+               esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout);
+#endif
+
+//esp_dbg(ESP_DBG_ERROR, "Block Write ---------");    
+        tx_cmd[0]=0x75;
+
+        if( count <=0 )
+        {
+                err_ret = -1;
+                goto goto_err;
+        }
+
+        if( addr >= (1<<17) )
+        {
+                err_ret = -2;
+                goto goto_err;
+        }
+        else
+        {
+             tx_cmd[1]=0x90|0x0C|(addr>>15);   
+             tx_cmd[2]=addr>>7;    
+
+             if(count >= 512 )
+            {
+                    tx_cmd[3]=( addr<<1|0x0 );
+                    tx_cmd[4]= 0x00;     
+            }
+            else
+            {
+                    tx_cmd[3]=( addr<<1|count>>7 );
+                    tx_cmd[4]= count;     
+            }
+        }
+        tx_cmd[5]=0x01;
+        
+        pos = 5+1;
+//Add cmd respon
+       memset(tx_cmd+pos,0xff,CMD_RESP_SIZE);
+       pos =pos+ CMD_RESP_SIZE;
+
+         for(j=0;j<count;j++)
+         {
+//Add token   
+                tx_cmd[pos]=0xFC;
+                pos = pos+1;
+//Add data    
+                memcpy(tx_cmd+pos,tx_data+j*SPI_BLOCK_SIZE, SPI_BLOCK_SIZE);
+                pos = pos+SPI_BLOCK_SIZE;
+//Add data respon
+                if( j==(count- 1) )
+                {
+                        memset(tx_cmd+pos , 0xff , BLOCK_W_DATA_RESP_SIZE_FINAL);
+                        pos = pos+ BLOCK_W_DATA_RESP_SIZE_FINAL;
+                        continue;
+                }
+                memset(tx_cmd+pos , 0xff , BLOCK_W_DATA_RESP_SIZE_EACH);
+                pos = pos+ BLOCK_W_DATA_RESP_SIZE_EACH;
+         }
+         
+        if( pos%8 )
+        {
+            len = (8 - pos%8);
+            memset(tx_cmd+pos,0xff,len);
+        }
+        else
+            len = 0;
+        
+        sif_spi_write_async_read(spi, tx_cmd,tx_cmd,pos+len);
+//Judge Write cmd resp, and 1st block data resp.        
+        pos = 5+1;
+        for(i=0;i<CMD_RESP_SIZE;i++)
+        {
+               if(tx_cmd[pos+i] == 0x00 && tx_cmd[pos+i-1] == 0xff)
+                {
+                        if(tx_cmd[pos+i+1] == 0x00 && tx_cmd[pos+i+2] == 0xff)
+                            break;      
+                }
+
+        }
+        if(i>=CMD_RESP_SIZE)
+        {
+                esp_dbg(ESP_DBG_ERROR, "1st block write cmd resp 0x00 no recv, %d\n", count);
+                err_ret = -3;
+               goto goto_err;
+       }
+
+        pos = pos+CMD_RESP_SIZE;
+      
+        for(j=0;j<count;j++)
+        {
+//Judge block data resp
+                pos = pos+1;                   
+                pos = pos+SPI_BLOCK_SIZE;
+                
+                if( j==(count-1) )
+                    n = BLOCK_W_DATA_RESP_SIZE_FINAL;
+                else
+                    n= BLOCK_W_DATA_RESP_SIZE_EACH;
+                
+                for(i=0;i<n;i++)
+                {
+                       if (tx_cmd[pos+i] != 0xff && tx_cmd[pos+i] != 0xe5)
+                               esp_dbg(ESP_DBG_ERROR, " %s [0x%02x] %d block ,!0xff pos:%d\n", __func__, tx_cmd[pos+i], j,i);
+                        //if(tx_cmd[pos+i] == 0xE5)
+                        if( (tx_cmd[pos+i]&0x0F) == 0x05 )
+                        {
+//esp_dbg(ESP_DBG_ERROR, "%d block ,0xE5 pos:%d",j,i);
+                                for(i++;i<n;i++)
+                                {
+                                     if( tx_cmd[pos+i] == 0xFF)
+                                     {
+//esp_dbg(ESP_DBG_ERROR, "%d block ,0xFF pos:%d",j,i);
+                                          break;
+                                     }
+                                }
+                                break;     
+                        }
+                }
+                if(i>=n)
+                {      
+                       esp_dbg(ESP_DBG_ERROR, "%s block%d write data rsp error, %d\n", __func__, j+1, count);
+                        err_ret = -4;
+                       goto goto_err;
+               }
+                pos = pos+n;   
+        }
+#if 0
+//Add stop token     
+        pos = 0;
+        tx_cmd[pos]=0xFD;
+        pos = pos+1;
+//Add data respon
+        memset(tx_cmd+pos , 0xff , BLOCK_W_DATA_RESP_SIZE_FINAL);
+        pos = pos+ BLOCK_W_DATA_RESP_SIZE_FINAL;
+        eagle_spi_write_async_read(tx_cmd,tx_cmd,pos);
+
+//Judge Final busy bits.
+        pos = 1;
+        for(i=0;i<BLOCK_W_DATA_RESP_SIZE_FINAL;i++)
+        {
+                if(tx_cmd[pos+i] != 0xFF)
+                {
+//esp_dbg(ESP_DBG_ERROR, "Final 0x00 pos:%d",i);
+                        for(i++;i<BLOCK_W_DATA_RESP_SIZE_FINAL;i++)
+                        {
+                             if( tx_cmd[pos+i] == 0xFF)
+                             {
+//esp_dbg(ESP_DBG_ERROR, "Final 0xFF pos:%d",i);
+                                  break;
+                             }
+                        }
+                        break;
+                }
+        }
+
+        if(i>=BLOCK_W_DATA_RESP_SIZE_FINAL)
+        {
+                mutex_unlock(&RWMutex);
+                esp_dbg(ESP_DBG_ERROR, "blocks final busy bit no recv");
+                return -5;
+       }
+#endif
+
+goto_err:
+
+       return err_ret;
+}
+
+int sif_spi_write_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle)
+{
+       int blk_cnt;
+       int remain_len;
+       int err;
+
+       blk_cnt = len/SPI_BLOCK_SIZE;
+       remain_len = len%SPI_BLOCK_SIZE;
+
+       if (blk_cnt > 0) {
+               err  = sif_spi_write_blocks(spi, addr, buf, blk_cnt, check_idle);
+               if (err) 
+                       return err;
+       }
+
+       if (remain_len > 0) {
+               err = sif_spi_write_bytes(spi, addr, (buf + (blk_cnt*SPI_BLOCK_SIZE)), remain_len, check_idle);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+
+}
+
+int sif_spi_write_mix_sync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle) 
+{
+       int err;
+
+       spi_bus_lock(spi->master);
+       err = sif_spi_write_mix_nosync(spi, addr, buf, len, check_idle);
+       spi_bus_unlock(spi->master);
+
+       return err;
+}
+
+int sif_spi_epub_write_mix_nosync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+       
+       ASSERT(epub != NULL);
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+       return sif_spi_write_mix_nosync(spi, addr, buf, len, check_idle);
+}
+
+int sif_spi_epub_write_mix_sync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+       
+       ASSERT(epub != NULL);
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+       return sif_spi_write_mix_sync(spi, addr, buf, len, check_idle);
+}
+
+int sif_spi_read_bytes(struct spi_device *spi, unsigned int addr,unsigned char *dst, int count, int check_idle)
+{      
+       int pos,total_num,len;
+        int i;
+        unsigned char *rx_data = (unsigned char *)dst;
+       int err_ret = 0;
+       
+       u32 timeout = 25000;
+       u32 busy_state = 0x00;
+
+       ASSERT(spi != NULL);
+        
+
+       rx_cmd[0]=0x75;
+        
+       if (check_idle) {       
+               timeout = 25000;
+               do {
+                       busy_state = 0x00;
+                       sif_spi_read_raw(spi, (u8 *)&busy_state, 4);
+            
+                    if(busy_state != 0xffffffff)
+                            esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); 
+            
+               } while (busy_state != 0xffffffff && --timeout > 0);
+       }
+
+       if (timeout < 24000)
+               esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout); 
+
+        if(count > 512 )
+        {
+               err_ret = -1;
+               goto goto_err;
+        }
+
+        if( addr >= (1<<17) )
+        {
+                err_ret = -2;
+               goto goto_err;
+        }
+        else
+        {
+             rx_cmd[1]=0x10|0x04|(addr>>15);    //0x94;
+             rx_cmd[2]=addr>>7;    
+
+             if(count == 512 )
+            {
+                    rx_cmd[3]=( addr<<1|0x0 );
+                    rx_cmd[4]= 0x00;     //0x08;
+            }
+            else
+            {
+                    rx_cmd[3]=( addr<<1|count>>7 );
+                    rx_cmd[4]= count;     //0x08;
+            }
+        }
+        
+        rx_cmd[5]=0x01;
+
+#if 1        // one shot read 
+        total_num = CMD_RESP_SIZE+DATA_RESP_SIZE_R+count+2;
+        memset(rx_cmd+6 , 0xFF ,total_num);
+
+
+        if( (6+total_num)%8 )
+        {
+            len = (8 - (6+total_num)%8);
+            memset(rx_cmd+6+total_num,0xff,len);
+        }
+        else
+            len = 0;
+        sif_spi_write_async_read(spi, rx_cmd,rx_cmd,6+total_num+len);
+
+        pos = 5+1;
+        for(i=0;i<CMD_RESP_SIZE;i++)
+        {
+               if(rx_cmd[pos+i] == 0x00 && rx_cmd[pos+i-1] == 0xff)
+                {
+                        if(rx_cmd[pos+i+1] == 0x00 && rx_cmd[pos+i+2] == 0xff)
+                            break;      
+                }
+        }
+        if(i>=CMD_RESP_SIZE)
+        {
+                esp_dbg(ESP_DBG_ERROR, "read cmd resp 0x00 no recv\n");
+/***********error info************************/
+/*
+       char t = pos;
+       while ( t < pos+32) {
+               printk(KERN_ERR "rx:[0x%02x] ", rx_cmd[t]);
+               t++;
+               if ((t-pos)%8 == 0)
+                       printk(KERN_ERR "\n");
+       }
+*/
+                err_ret = -3;
+               goto goto_err;
+       }
+//esp_dbg(ESP_DBG_ERROR, "0x00 pos:%d",pos+i);
+       pos = pos+i+2;
+       
+        for(i=0;i<DATA_RESP_SIZE_R;i++)
+        {
+                if(rx_cmd[pos+i]==0xFE)
+                    break;
+        }
+        if(i>=DATA_RESP_SIZE_R)
+        {
+                esp_dbg(ESP_DBG_ERROR, "read data resp 0xFE no recv\n");
+               err_ret = -4;
+               goto goto_err;
+       }
+//esp_dbg(ESP_DBG_ERROR, "0xFE pos:%d",pos+i);
+       pos = pos+i+1;
+        memcpy(rx_data,rx_cmd+pos,count);
+#else       //wait method
+  
+        memset(rx_cmd+6,0xFF,CMD_RESP_SIZE+DATA_RESP_SIZE_R+count+2);
+//printk(KERN_ERR "mark 1",pos+i);     
+        sif_spi_write_async_read(spi, rx_cmd,rx_cmd,6+CMD_RESP_SIZE+DATA_RESP_SIZE_R+count+2);
+//printk(KERN_ERR "mark 2",pos+i);
+        pos = 5+1;
+        for(i=0;i<CMD_RESP_SIZE;i++)
+        {
+               if(rx_cmd[pos+i] == 0x00 && rx_cmd[pos+i-1] == 0xff)
+                {
+                        if(rx_cmd[pos+i+1] == 0x00 && rx_cmd[pos+i+2] == 0xff)
+                            break;      
+                }
+        }
+        if(i>=CMD_RESP_SIZE)
+        {
+                printk(KERN_ERR "read cmd resp 0x00 no recv\n");
+                //kfree(rx_cmd);
+                err_ret = -3;
+               goto goto_err;
+       }
+//printk(KERN_ERR "0x00 pos:%d",pos+i);
+       pos = pos+i+2;
+       
+        for(i=0;i<DATA_RESP_SIZE_R;i++)
+        {
+                if(rx_cmd[pos+i]==0xFE)
+                    break;
+        }
+        if(i>=DATA_RESP_SIZE_R)
+        {
+                printk(KERN_ERR "read data resp 0xFE no recv\n");
+               err_ret = -4;
+               goto goto_err;
+       }
+//printk(KERN_ERR "0xFE pos:%d",pos+i);
+       pos = pos+i+1;
+
+        for(i=0;i<count;i++)
+        {
+                *(rx_data+i) = rx_cmd[pos+i];
+        }
+
+
+#endif
+goto_err:
+
+        return err_ret;
+}
+
+int sif_spi_read_blocks(struct spi_device *spi, unsigned int addr, unsigned char *dst, int count, int check_idle)
+{
+       int err_ret = 0;
+       int pos,len;
+       int i,j;
+       unsigned char *rx_data = (unsigned char *)dst;
+       int total_num;
+       u32 busy_state = 0x00;
+       u32 timeout = 25000;
+
+       //esp_dbg(ESP_DBG_ERROR, "Block Read ---------");               
+       ASSERT(spi != NULL);
+   
+
+#if 1 
+       if (check_idle) {
+               timeout = 25000;
+               do {
+                       busy_state = 0x00;
+                       sif_spi_read_raw(spi, (u8 *)&busy_state, 4);
+            
+                    if(busy_state != 0xffffffff)
+                            esp_dbg(ESP_DBG_ERROR, "%s busy_state:%x\n", __func__, busy_state); 
+               } while (busy_state != 0xffffffff && --timeout > 0);
+       }
+
+       if (timeout < 24000)
+               esp_dbg(ESP_DBG_ERROR, "%s timeout[%d]\n", __func__, timeout);
+#endif
+        rx_cmd[0]=0x75;
+
+        if( count <=0 )
+        {
+                err_ret = -1;
+                goto goto_err;
+        }
+        if( addr >= (1<<17) )
+        {
+                err_ret = -2;
+               goto goto_err;
+        }
+        else
+        {
+             rx_cmd[1]=0x10|0x0C|(addr>>15);   
+             rx_cmd[2]=addr>>7;    
+
+            if(count >= 512 )
+            {
+                    rx_cmd[3]=( addr<<1|0x0 );
+                    rx_cmd[4]= 0x00;     
+            }
+            else
+            {
+                    rx_cmd[3]=( addr<<1|count>>7 );
+                    rx_cmd[4]= count;     
+            }
+        }
+        rx_cmd[5]=0x01;
+       total_num = CMD_RESP_SIZE+BLOCK_R_DATA_RESP_SIZE_1ST+SPI_BLOCK_SIZE+ 2 + (count-1)*(BLOCK_R_DATA_RESP_SIZE_EACH+SPI_BLOCK_SIZE+2);
+       memset(rx_cmd+6, 0xFF ,total_num);
+    
+        if( (6+total_num)%8 )
+        {
+            len = (8 - (6+total_num)%8);
+            memset(rx_cmd+6+total_num,0xff,len);
+        }
+        else
+            len = 0;
+        
+        sif_spi_write_async_read(spi, rx_cmd,rx_cmd,6+total_num+len );
+        
+        pos = 5+1;
+        for(i=0;i<CMD_RESP_SIZE;i++)
+        {
+               if(rx_cmd[pos+i] == 0x00 && rx_cmd[pos+i-1] == 0xff)
+                {
+                        if(rx_cmd[pos+i+1] == 0x00 && rx_cmd[pos+i+2] == 0xff)
+                            break;      
+                }
+
+        }
+        if(i>=CMD_RESP_SIZE)
+        {
+               esp_dbg(ESP_DBG_ERROR, "block read cmd resp 0x00 no recv\n");
+#if 0
+       char t = pos;
+       while ( t < pos+32) {
+               printk(KERN_ERR "rx:[0x%02x] ", rx_cmd[t]);
+               t++;
+               if ((t-pos)%8 == 0)
+                       printk(KERN_ERR "\n");
+       }
+#endif
+
+                err_ret = -3;
+               goto goto_err;
+        }
+
+        pos = pos+i+2;
+
+       for(i=0;i<BLOCK_R_DATA_RESP_SIZE_1ST;i++)
+        {
+                if(rx_cmd[pos+i]==0xFE)
+                {
+//esp_dbg(ESP_DBG_ERROR, "0xFE pos:%d",i);
+                    break;
+                }
+        }
+        if(i>=BLOCK_R_DATA_RESP_SIZE_1ST)
+        {
+                esp_dbg(ESP_DBG_ERROR, "1st block read data resp 0xFE no recv\n");
+                err_ret = -4;
+               goto goto_err;
+        }
+
+        pos = pos+i+1;
+
+        memcpy(rx_data,rx_cmd+pos,SPI_BLOCK_SIZE);
+
+        pos = pos +SPI_BLOCK_SIZE + 2;
+
+        for(j=1;j<count;j++)
+        {
+
+               for(i=0;i<BLOCK_R_DATA_RESP_SIZE_EACH;i++)
+               {
+                               if(rx_cmd[pos+i]==0xFE)
+                       {
+                       //esp_dbg(ESP_DBG_ERROR, "0xFE pos:%d",i);
+                       break;
+                       }
+               }
+               if(i>=BLOCK_R_DATA_RESP_SIZE_EACH)
+               {
+                       esp_dbg(ESP_DBG_ERROR, "block%d read data resp 0xFE no recv,total:%d\n",j+1,count);
+                        err_ret = -4;
+                       goto goto_err;
+                }
+
+                pos = pos+i+1;
+                memcpy(rx_data+j*SPI_BLOCK_SIZE,rx_cmd+pos,SPI_BLOCK_SIZE);
+                
+               pos = pos +SPI_BLOCK_SIZE + 2;
+        }
+     
+goto_err:       
+
+       return err_ret;
+}
+
+int sif_spi_read_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle)
+{
+       int blk_cnt;
+       int remain_len;
+       int err;
+
+       blk_cnt = len/SPI_BLOCK_SIZE;
+       remain_len = len%SPI_BLOCK_SIZE;
+
+       if (blk_cnt > 0) {
+               err  = sif_spi_read_blocks(spi, addr, buf, blk_cnt, check_idle);
+               if (err) 
+                       return err;
+       }
+
+       if (remain_len > 0) {
+               err = sif_spi_read_bytes(spi, addr, (buf + (blk_cnt*SPI_BLOCK_SIZE)), remain_len, check_idle);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+int sif_spi_read_mix_sync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int check_idle)
+{
+       int err;
+       
+       spi_bus_lock(spi->master);
+       err = sif_spi_read_mix_nosync(spi, addr, buf, len, check_idle);
+       spi_bus_unlock(spi->master);
+
+       return err;
+}
+
+int sif_spi_epub_read_mix_nosync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+       
+       ASSERT(epub != NULL);
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+       return sif_spi_read_mix_nosync(spi, addr, buf, len, check_idle);
+}
+
+int sif_spi_epub_read_mix_sync(struct esp_pub *epub, unsigned int addr, unsigned char *buf,int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+       
+       ASSERT(epub != NULL);
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+       return sif_spi_read_mix_sync(spi, addr, buf, len, check_idle);
+}
+
+int sif_spi_read_sync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+       u32 read_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                read_len = len;
+                break;
+        case 0x600:
+                read_len = roundup(len, sctrl->slc_blk_sz);
+                break;
+        default:
+                read_len = len;
+                break;
+        }
+       
+       return sif_spi_read_mix_sync(spi, sctrl->slc_window_end_addr - 2 - (len), buf, read_len, check_idle);
+}
+
+int sif_spi_write_sync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+        u32 write_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                write_len = len;
+                break;
+        case 0x600:
+                write_len = roundup(len, sctrl->slc_blk_sz);
+                break;
+        default:
+                write_len = len;
+                break;
+        }
+       return sif_spi_write_mix_sync(spi, sctrl->slc_window_end_addr - (len), buf, write_len, check_idle);
+}
+
+int sif_spi_read_nosync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle, bool noround)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+       u32 read_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                read_len = len;
+                break;
+        case 0x600:
+               if (!noround)
+                       read_len = roundup(len, sctrl->slc_blk_sz);
+               else
+                       read_len = len;
+                break;
+        default:
+                read_len = len;
+                break;
+        }
+       
+       return sif_spi_read_mix_nosync(spi, sctrl->slc_window_end_addr - 2 - (len), buf, read_len, check_idle);
+}
+
+int sif_spi_write_nosync(struct esp_pub *epub, unsigned char *buf, int len, int check_idle)
+{
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+        u32 write_len;
+
+        ASSERT(epub != NULL);
+        ASSERT(buf != NULL);
+
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+        switch(sctrl->target_id) {
+        case 0x100:
+                write_len = len;
+                break;
+        case 0x600:
+                write_len = roundup(len, sctrl->slc_blk_sz);
+                break;
+        default:
+                write_len = len;
+                break;
+        }
+       return sif_spi_write_mix_nosync(spi, sctrl->slc_window_end_addr - (len), buf, write_len, check_idle);
+}
+
+void sif_spi_protocol_init(struct spi_device *spi)
+{
+       unsigned char spi_proto_ini_status = 0;
+        unsigned char rx_buf1[10];
+        unsigned char tx_buf1[10];
+        unsigned char dummy_tx_buf[10];
+        memset(dummy_tx_buf,0xff,sizeof(dummy_tx_buf));      
+        do
+        {            
+                 if( spi_proto_ini_status == 0 )
+                 {
+                        do
+                        { 
+                                tx_buf1[0]=0x40;
+                                tx_buf1[1]=0x00;
+                                tx_buf1[2]=0x00;
+                                tx_buf1[3]=0x00;
+                                tx_buf1[4]=0x00;
+                                tx_buf1[5]=0x95;
+                                //printf("CMD0 \n");
+                                sif_spi_write_raw(spi, tx_buf1, 6);
+                                sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                            esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                                mdelay(100);
+                        }while( rx_buf1[2] != 0x01 );
+                        //  }while(1);
+                 }
+                else if( spi_proto_ini_status == 1 )
+                {
+                        tx_buf1[0]=0x45;
+                        tx_buf1[1]=0x00;
+                        tx_buf1[2]=0x20;               //0x04;
+                        tx_buf1[3]=0x00;
+                        tx_buf1[4]=0x00;
+                        tx_buf1[5]=0x01;
+                        //spi_err("CMD 5 1st\n");
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                 }
+                else if( spi_proto_ini_status == 2 )
+                {
+                        tx_buf1[0]=0x45;
+                        tx_buf1[1]=0x00;
+                        tx_buf1[2]=0x20;               
+                        tx_buf1[3]=0x00;
+                        tx_buf1[4]=0x00;
+                        tx_buf1[5]=0x01;
+                        //spi_err("CMD5 2nd\n");
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+               }
+               else if( spi_proto_ini_status == 3 )                  //CMD 52   addr 0x2,   data 0x02;
+                {
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x80;
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x04;
+                        tx_buf1[4]=0x02;
+                        tx_buf1[5]=0x01;
+                        //spi_err("CMD52 Write  addr 02 \n");  
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                 }
+                else if( spi_proto_ini_status == 4 )           
+                {
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x80;
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x08;
+                        tx_buf1[4]=0x03;
+                        tx_buf1[5]=0x01;
+                        //spi_err("CMD52 Write  addr 04 \n"); 
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                 } 
+                else if( spi_proto_ini_status == 5 )           
+                {
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x00;
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x04;
+                        tx_buf1[4]=0x00;
+                        tx_buf1[5]=0x01;
+                        //spi_err("CMD52 Read  addr 0x2 \n");
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                                      
+                 }
+                 else if( spi_proto_ini_status == 6 )           
+                {
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x00;
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x08;
+                        tx_buf1[4]=0x00;
+                        tx_buf1[5]=0x01;
+                        //spi_err("CMD52 Read addr 0x4 \n");
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                 }
+                 else if (spi_proto_ini_status>6 && spi_proto_ini_status<15)
+                {
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x10;
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0xF0+2*(spi_proto_ini_status-7);
+                        tx_buf1[4]=0x00;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                 }
+                else if (spi_proto_ini_status==15)
+                {
+                        //spi_err("CMD52 Write  Reg addr 0x110 \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x80;              //func0 should be
+                        tx_buf1[2]=0x02;               
+                        tx_buf1[3]=0x20;
+                        tx_buf1[4]=(unsigned char)(SPI_BLOCK_SIZE & 0xff);                       //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                        
+                        //spi_err("CMD52 Write Reg addr 0x111 \n");  
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x80;
+                        tx_buf1[2]=0x02;               
+                        tx_buf1[3]=0x22;
+                        tx_buf1[4]=(unsigned char)(SPI_BLOCK_SIZE>>8);                      //0x00;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+
+                        //spi_err("CMD52 Write Reg addr 0x111 \n");   /* set boot mode */
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x80;
+                        tx_buf1[2]=0x41;               
+                        tx_buf1[3]=0xe0;
+                        tx_buf1[4]=0x01;          //0x00;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                                       esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+
+                }
+                else if (spi_proto_ini_status==16)
+                {
+#if 0                                                        
+                        //printf("CMD52 Write  Reg addr 0x40 \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;              
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x80;
+                        tx_buf1[4]=0x91;                       //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                
+                        //sif_spi_read_bytes( 0x0c,rx_buf1, 4);
+
+                        //printf("CMD52 Write  Reg addr 0x3c \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;            
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x78;
+                        tx_buf1[4]=0x3f;                     
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                        esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                        
+                                                                //printf("CMD52 Write  Reg addr 0x3d \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;              
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x7a;
+                        tx_buf1[4]=0x34;                        //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                        esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                        
+                                                               // printf("CMD52 Write  Reg addr 0x3e \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;              
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x7c;
+                        tx_buf1[4]=0xfe;                       //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                        esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                        
+                                                                //printf("CMD52 Write  Reg addr 0x3f \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;              
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x7e;
+                        tx_buf1[4]=0x00;                       //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                        esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                        
+                                                                //printf("CMD52 Write  Reg addr 0x40 \n"); 
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;              
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x80;
+                        tx_buf1[4]=0xd1;                      //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                        esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+
+                        tx_buf1[0]=0x74;
+                        tx_buf1[1]=0x90;              
+                        tx_buf1[2]=0x00;               
+                        tx_buf1[3]=0x52;
+                        tx_buf1[4]=0x30;                      //0x02;
+                        tx_buf1[5]=0x01;
+                        sif_spi_write_raw(spi, tx_buf1, 6);
+                        sif_spi_write_async_read(spi,dummy_tx_buf, rx_buf1,10);
+                        esp_dbg(ESP_DBG_ERROR, "rx:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_buf1[0],rx_buf1[1]
+                ,rx_buf1[2],rx_buf1[3],rx_buf1[4],rx_buf1[5],rx_buf1[6],rx_buf1[7],rx_buf1[8],rx_buf1[9]);
+                        
+#endif                    
+                }
+                else
+                {
+                        break;
+               }
+                                            //  mdelay(500);
+                   spi_proto_ini_status++;   
+        } while (1);
+}
+
+int sif_spi_read_reg(struct spi_device *spi, unsigned int addr, unsigned char *value )
+{
+        unsigned char tx_cmd[6];
+        unsigned char rx_cmd[20];
+        int err_ret = 0;
+
+
+        tx_cmd[0]=0x74;
+
+        if( addr >= (1<<17) )
+        {
+                err_ret = -1;
+               goto goto_err;
+                //return err_ret;
+        }
+        else
+        {
+                tx_cmd[1]=0x10|0x00|(addr>>15);    
+                tx_cmd[2]=addr>>7;    
+
+                tx_cmd[3]=( addr<<1 );
+                tx_cmd[4]= 0x00;    
+        }
+        
+        tx_cmd[5]=0x01;
+
+        sif_spi_write_raw(spi, tx_cmd,6);
+                //printf("CMD52 Read \n");
+#if 0
+//Response read
+      
+        sif_spi_read_raw(spi, rx_cmd,20);  
+        
+                                       esp_dbg(ESP_DBG_ERROR, "write resp:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_cmd[0],rx_cmd[1]
+                ,rx_cmd[2],rx_cmd[3],rx_cmd[4],rx_cmd[5],rx_cmd[6],rx_cmd[7],rx_cmd[8],rx_cmd[9]);
+        return 0;
+ #else
+
+ //Read Response.        
+        do
+        {
+                rx_cmd[0]=0xFF;
+                sif_spi_read_raw(spi, rx_cmd,1);
+         }while(rx_cmd[0]==0xFF);
+        rx_cmd[1]=0xFF;
+                sif_spi_read_raw(spi, rx_cmd+1,1);
+        
+          esp_dbg(ESP_DBG_ERROR, "read resp:[0x%02x],[0x%02x]\n",rx_cmd[0],rx_cmd[1]);
+
+        if(rx_cmd[0]!=0)
+            err_ret = -1;
+        else
+            err_ret = 0;
+
+        *value = rx_cmd[1]; 
+       
+        //return err_ret;       
+ #endif
+
+goto_err:
+
+        return err_ret;       
+}
+
+
+int sif_spi_write_reg(struct spi_device *spi, unsigned int addr, unsigned char value)
+{
+        unsigned char tx_cmd[6];
+        unsigned char rx_cmd[20];
+        int err_ret = 0;
+       
+
+        
+       tx_cmd[0]=0x74;
+
+        if( addr >= (1<<17) )
+        {
+                err_ret = -1;
+               goto goto_err;
+                //return err_ret;
+        }
+        else
+        {
+                tx_cmd[1]=0x90|0x00|(addr>>15);    //0x94;
+                tx_cmd[2]=addr>>7;    
+
+                tx_cmd[3]=( addr<<1 );
+                tx_cmd[4]= value;
+        }
+        
+        tx_cmd[5]=0x01;
+        sif_spi_write_raw(spi, tx_cmd,6);
+                //printf("CMD52 <Write config> stauts=16 \n");
+
+
+#if 0
+        //memset(rx_cmd,0xFF,20);
+                sif_spi_read_raw(spi, rx_cmd,20);
+
+                                       esp_dbg(ESP_DBG_ERROR, "write resp:[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x],[0x%02x]\n", rx_cmd[0],rx_cmd[1]
+                ,rx_cmd[2],rx_cmd[3],rx_cmd[4],rx_cmd[5],rx_cmd[6],rx_cmd[7],rx_cmd[8],rx_cmd[9]);
+        return 0;
+#else
+
+        do
+        {
+                rx_cmd[0]=0xFF;
+                sif_spi_read_raw(spi, rx_cmd,1);
+         }while(rx_cmd[0]==0xFF);
+        rx_cmd[1]=0xFF;
+                sif_spi_read_raw(spi, rx_cmd+1,1);
+
+         if( rx_cmd[1]!=value )    
+         {
+                //printf("Write error,%X,%X", rx_cmd[0],rx_cmd[1]);
+                 esp_dbg(ESP_DBG_ERROR, "write resp:[0x%02x],[0x%02x]\n",rx_cmd[0],rx_cmd[1]);
+                err_ret = -1;
+               goto goto_err;
+               
+         }
+
+goto_err:
+
+        return err_ret;
+        
+#endif
+//Read Response.        
+
+}
+
+static int spi_irq_thread(void *data)
+{
+       struct spi_device *spi = (struct spi_device *)data;
+
+       do {
+               sif_dsr(spi);
+               
+               set_current_state(TASK_INTERRUPTIBLE);
+               sif_platform_irq_mask(0);
+
+               if (!kthread_should_stop())
+                       schedule();
+
+               set_current_state(TASK_RUNNING);
+
+       } while (!kthread_should_stop());
+       return 0;       
+}
+
+int sif_setup_irq_thread(struct spi_device *spi)
+{
+       sif_irq_thread = kthread_run(spi_irq_thread, spi, "kspiirqd/eagle");
+       if (IS_ERR(sif_irq_thread)) {
+               esp_dbg(ESP_DBG_ERROR, "setup irq thread error!\n");
+               return -1;
+       }
+       return 0;
+}
+
+static irqreturn_t sif_irq_handler(int irq, void *dev_id)
+{
+       sif_platform_irq_mask(1);
+
+       if (sif_platform_is_irq_occur()) {
+               wake_up_process(sif_irq_thread);
+       } else {
+               sif_platform_irq_mask(0);
+               return IRQ_NONE;
+       }
+
+       return IRQ_HANDLED;
+}
+
+void sif_enable_irq(struct esp_pub *epub) 
+{
+        int err;
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+
+        ASSERT(epub != NULL);
+
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+       mdelay(100);
+
+       sif_platform_irq_init();
+       err = sif_setup_irq_thread(spi);
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "%s setup sif irq failed\n", __func__);
+               return;
+       }
+
+       err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_LOW, "esp_spi_irq", spi);
+       //err = request_irq(sif_platform_get_irq_no(), sif_irq_handler, IRQF_TRIGGER_FALLING, "esp_spi_irq", spi);
+
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "sif %s failed\n", __func__);
+               return ;
+       }
+
+        atomic_set(&sctrl->irq_installed, 1);
+}
+
+void sif_disable_irq(struct esp_pub *epub) 
+{
+       int i = 0;
+       struct esp_spi_ctrl *sctrl = NULL;
+        struct spi_device *spi = NULL;
+
+        ASSERT(epub != NULL);
+
+        sctrl = (struct esp_spi_ctrl *)epub->sif;
+        spi = sctrl->spi;
+        ASSERT(spi != NULL);
+
+
+        if (atomic_read(&sctrl->irq_installed) == 0)
+                return;
+        
+        while (atomic_read(&sctrl->irq_handling)) {
+                schedule_timeout(HZ / 100);
+                if (i++ >= 400) {
+                        esp_dbg(ESP_DBG_ERROR, "%s force to stop irq\n", __func__);
+                        break;
+                }
+        }
+
+        free_irq(sif_platform_get_irq_no(), spi);
+       kthread_stop(sif_irq_thread);
+
+       sif_platform_irq_deinit();
+
+        atomic_set(&sctrl->irq_installed, 0);
+}
+
+
+int esp_setup_spi(struct spi_device *spi)
+{
+       /**** alloc buffer for spi io */
+       if (sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT) {
+               buf_addr = (unsigned char *)kmalloc (MAX_BUF_SIZE, GFP_KERNEL);
+               if (buf_addr == NULL)
+                       return -ENOMEM;
+
+               tx_cmd = buf_addr;
+                       rx_cmd = buf_addr;
+       }
+
+#if 0
+       spi->mode = 0x03;
+       spi->bits_per_word = 8;
+       spi->max_speed_hz = SPI_FREQ;
+
+       return spi_setup(spi);
+#endif
+       return 0;
+}
+
+
+static int esp_spi_probe(struct spi_device *spi);
+static int esp_spi_remove(struct spi_device *spi); 
+
+static int esp_spi_probe(struct spi_device *spi) 
+{
+        int err;
+        struct esp_pub *epub;
+        struct esp_spi_ctrl *sctrl;
+
+        esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__);
+       
+       err = esp_setup_spi(spi);
+       if (err) {
+               esp_dbg(ESP_DBG_ERROR, "%s setup_spi error[%d]\n", __func__, err);
+               goto _err_spi;
+       }
+       esp_dbg(ESP_DBG_ERROR, "%s init_protocol\n", __func__);
+       sif_spi_protocol_init(spi);
+
+       if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               sctrl = kzalloc(sizeof(struct esp_spi_ctrl), GFP_KERNEL);
+
+               if (sctrl == NULL) {
+                       assert(0);
+                       return -ENOMEM;
+               }
+
+               /* temp buffer reserved for un-dma-able request */
+               sctrl->dma_buffer = kzalloc(ESP_DMA_IBUFSZ, GFP_KERNEL);
+
+               if (sctrl->dma_buffer == NULL) {
+                       assert(0);
+                       goto _err_last;
+               }
+               sif_sctrl = sctrl;
+               sctrl->slc_blk_sz = SIF_SLC_BLOCK_SIZE;
+               
+               epub = esp_pub_alloc_mac80211(&spi->dev);
+
+               if (epub == NULL) {
+                       esp_dbg(ESP_DBG_ERROR, "no mem for epub \n");
+                       err = -ENOMEM;
+                       goto _err_dma;
+               }
+               epub->sif = (void *)sctrl;
+               sctrl->epub = epub;
+       
+#ifdef USE_EXT_GPIO    
+               err = ext_gpio_init(epub);
+               if (err) {
+                       esp_dbg(ESP_DBG_ERROR, "ext_irq_work_init failed %d\n", err);
+                       return err;
+               }
+#endif
+                       
+       } else {
+               ASSERT(sif_sctrl != NULL);
+               sctrl = sif_sctrl;
+               sif_sctrl = NULL;
+               epub = sctrl->epub;
+               SET_IEEE80211_DEV(epub->hw, &spi->dev);
+               epub->dev = &spi->dev;
+       }
+
+        epub->sdio_state = sif_sdio_state;
+
+        sctrl->spi = spi;
+        spi_set_drvdata(spi, sctrl);
+
+        if (err){
+                if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT)
+                       goto _err_epub;
+                 else
+                       goto _err_second_init;
+        }
+        check_target_id(epub);
+
+#ifdef SDIO_TEST
+        sif_test_tx(sctrl);
+#else
+        err = esp_pub_init_all(epub);
+
+        if (err) {
+                esp_dbg(ESP_DBG_ERROR, "esp_init_all failed: %d\n", err);
+                if(sif_sdio_state == ESP_SDIO_STATE_SECOND_INIT)
+                       goto _err_second_init;
+        }
+
+#endif //SDIO_TEST
+        esp_dbg(ESP_DBG_TRACE, " %s return  %d\n", __func__, err);
+       if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               esp_dbg(ESP_DBG_ERROR, "first normal exit\n");
+               sif_sdio_state = ESP_SDIO_STATE_FIRST_NORMAL_EXIT;
+               up(&esp_powerup_sem);
+       }
+
+        return err;
+
+_err_epub:
+        esp_pub_dealloc_mac80211(epub);
+_err_dma:
+        kfree(sctrl->dma_buffer);
+_err_last:
+        kfree(sctrl);
+       if (buf_addr) {
+               kfree(buf_addr);
+               buf_addr = NULL;
+               tx_cmd = NULL;
+               rx_cmd = NULL;
+       }
+       if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
+               sif_sdio_state = ESP_SDIO_STATE_FIRST_ERROR_EXIT;
+               up(&esp_powerup_sem);
+       }
+        return err;
+_err_second_init:
+       sif_sdio_state = ESP_SDIO_STATE_SECOND_ERROR_EXIT;
+       esp_spi_remove(spi);
+       return err;
+_err_spi:
+       if (buf_addr) {
+               kfree(buf_addr);
+               buf_addr = NULL;
+               tx_cmd = NULL;
+               rx_cmd = NULL;
+       }
+       return err;
+}
+
+static int esp_spi_remove(struct spi_device *spi) 
+{
+        struct esp_spi_ctrl *sctrl = NULL;
+
+        sctrl = spi_get_drvdata(spi);
+
+        if (sctrl == NULL) {
+                esp_dbg(ESP_DBG_ERROR, "%s no sctrl\n", __func__);
+                return -1;
+        }
+
+        do {
+                if (sctrl->epub == NULL) {
+                        esp_dbg(ESP_DBG_ERROR, "%s epub null\n", __func__);
+                        break;
+                }
+               sctrl->epub->sdio_state = sif_sdio_state;
+               if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
+                       do{
+                               int err;
+                               sif_lock_bus(sctrl->epub);
+                               err = sif_interrupt_target(sctrl->epub, 7);
+                               sif_unlock_bus(sctrl->epub);
+                       }while(0);
+       
+                       if (sctrl->epub->sip) {
+                               sip_detach(sctrl->epub->sip);
+                               sctrl->epub->sip = NULL;
+                               esp_dbg(ESP_DBG_TRACE, "%s sip detached \n", __func__);
+#ifdef USE_EXT_GPIO    
+                               ext_gpio_deinit();
+#endif
+                       }
+               } else {
+                       //sif_disable_target_interrupt(sctrl->epub);
+                       atomic_set(&sctrl->epub->sip->state, SIP_STOP);
+                       sif_disable_irq(sctrl->epub);
+               }
+
+#ifdef TEST_MODE
+                test_exit_netlink();
+#endif /* TEST_MODE */
+               if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
+                       esp_pub_dealloc_mac80211(sctrl->epub);
+                       esp_dbg(ESP_DBG_TRACE, "%s dealloc mac80211 \n", __func__);
+                       
+                       if (sctrl->dma_buffer) {
+                               kfree(sctrl->dma_buffer);
+                               sctrl->dma_buffer = NULL;
+                               esp_dbg(ESP_DBG_TRACE, "%s free dma_buffer \n", __func__);
+                       }
+
+                       kfree(sctrl);
+
+                       if (buf_addr) {
+                               kfree(buf_addr);
+                               buf_addr = NULL;
+                               rx_cmd = NULL;
+                               tx_cmd = NULL;
+                       }
+
+               }
+
+        } while (0);
+        
+       spi_set_drvdata(spi,NULL);
+       
+        esp_dbg(ESP_DBG_TRACE, "eagle spi remove complete\n");
+
+       return 0;
+}
+
+static int esp_spi_suspend(struct device *dev)
+{        return 0;
+
+}
+
+static int esp_spi_resume(struct device *dev)
+{
+        esp_dbg(ESP_DBG_ERROR, "%s", __func__);
+
+        return 0;
+}
+
+static const struct dev_pm_ops esp_spi_pm_ops = {
+        .suspend= esp_spi_suspend,
+        .resume= esp_spi_resume,
+};
+
+extern struct spi_device_id esp_spi_id[];
+
+struct spi_driver esp_spi_driver = {
+       .id_table = esp_spi_id,
+       .driver = {
+               .name   = "eagle",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = esp_spi_probe,
+       .remove = esp_spi_remove,
+};
+
+static int esp_spi_dummy_probe(struct spi_device *spi)
+{
+        esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__);
+
+        up(&esp_powerup_sem);
+        
+        return 0;
+}
+
+static int esp_spi_dummy_remove(struct spi_device *spi) 
+{
+        return 0;
+}
+
+struct spi_driver esp_spi_dummy_driver = {
+       .id_table = esp_spi_id,
+       .driver = {
+               .name   = "eagle_dummy",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = esp_spi_dummy_probe,
+       .remove = esp_spi_dummy_remove,
+};
+
+static int __init esp_spi_init(void) 
+{
+#define ESP_WAIT_UP_TIME_MS 11000
+        int err;
+        u64 ver;
+        int retry = 3;
+        bool powerup = false;
+        int edf_ret = 0;
+
+        esp_dbg(ESP_DBG_TRACE, "%s \n", __func__);
+
+#ifdef REGISTER_SPI_BOARD_INFO
+       sif_platform_register_board_info();
+#endif
+
+#ifdef DRIVER_VER
+        ver = DRIVER_VER;
+        esp_dbg(ESP_SHOW, "\n*****%s %s EAGLE DRIVER VER:%llx*****\n\n", __DATE__, __TIME__, ver);
+#endif
+        edf_ret = esp_debugfs_init();
+
+#ifdef ANDROID
+       android_request_init_conf();
+#endif /* defined(ANDROID)*/
+
+        esp_wakelock_init();
+        esp_wake_lock();
+
+        do {
+                sema_init(&esp_powerup_sem, 0);
+
+                sif_platform_target_poweron();
+
+                err = spi_register_driver(&esp_spi_dummy_driver);
+                if (err) {
+                        esp_dbg(ESP_DBG_ERROR, "eagle spi driver registration failed, error code: %d\n", err);
+                        goto _fail;
+                }
+
+                if (down_timeout(&esp_powerup_sem,
+                                 msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0) 
+               {
+
+                        powerup = true;
+                       msleep(200);
+                        break;
+                }
+
+                esp_dbg(ESP_SHOW, "%s ------ RETRY ------ \n", __func__);
+
+               sif_record_retry_config();
+
+                spi_unregister_driver(&esp_spi_dummy_driver);
+
+                sif_platform_target_poweroff();
+                
+        } while (retry--);
+
+        if (!powerup) {
+                esp_dbg(ESP_DBG_ERROR, "eagle spi can not power up!\n");
+
+                err = -ENODEV;
+                goto _fail;
+        }
+
+        esp_dbg(ESP_SHOW, "%s power up OK\n", __func__);
+
+        spi_unregister_driver(&esp_spi_dummy_driver);
+
+        sif_sdio_state = ESP_SDIO_STATE_FIRST_INIT;
+        sema_init(&esp_powerup_sem, 0);
+
+        spi_register_driver(&esp_spi_driver);
+
+        if (down_timeout(&esp_powerup_sem,
+                                 msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0) 
+       {
+               if(sif_sdio_state == ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
+                       spi_unregister_driver(&esp_spi_driver);
+
+                       msleep(80);
+                
+                       sif_sdio_state = ESP_SDIO_STATE_SECOND_INIT;
+               
+                       spi_register_driver(&esp_spi_driver);
+               }
+                
+        }
+
+
+        esp_register_early_suspend();
+       esp_wake_unlock();
+        return err;
+
+_fail:
+        esp_wake_unlock();
+        esp_wakelock_destroy();
+
+        return err;
+}
+
+static void __exit esp_spi_exit(void) 
+{
+       esp_dbg(ESP_DBG_TRACE, "%s \n", __func__);
+
+       esp_debugfs_exit();
+       
+        esp_unregister_early_suspend();
+
+       spi_unregister_driver(&esp_spi_driver);
+       
+#ifndef FPGA_DEBUG
+       sif_platform_target_poweroff();
+#endif /* !FPGA_DEBUG */
+
+        esp_wakelock_destroy();
+}
+
+MODULE_AUTHOR("Espressif System");
+MODULE_DESCRIPTION("Driver for SPI interconnected eagle low-power WLAN devices");
+MODULE_LICENSE("GPL");
+#endif /* ESP_USE_SPI */
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/testmode.c b/drivers/net/wireless/rockchip_wlan/esp8089/testmode.c
new file mode 100755 (executable)
index 0000000..ec14cf6
--- /dev/null
@@ -0,0 +1,634 @@
+
+/*
+ * Copyright (c) 2011 Espressif System.
+ *
+ *     MAC80211 support module
+ */
+#ifdef TEST_MODE
+
+#include <linux/etherdevice.h>
+#include <linux/workqueue.h>
+#include <linux/nl80211.h>
+#include <linux/ieee80211.h>
+#include <linux/slab.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <net/genetlink.h>
+#include "esp_pub.h"
+#include "esp_sip.h"
+#include "esp_ctrl.h"
+#include "esp_sif.h"
+#include "esp_debug.h"
+#include "esp_wl.h"
+#include "testmode.h"
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+    #include <net/regulatory.h>
+#endif
+
+static u32 connected_nl;
+static struct genl_info info_copy;
+static struct esp_sip *sip_copy = NULL;
+static u8 *sdio_buff = NULL;
+
+#define SIP sip_copy
+#define OUT_DONE() \
+        do { \
+            printk(KERN_DEBUG "esp_sdio: error occured in %s\n", __func__); \
+        } while(0)
+
+/* ESP TEST netlinf family */
+static struct genl_family test_genl_family = {
+        .id = GENL_ID_GENERATE,
+        .hdrsize = 0,
+        .name = "esp_sdio",
+        .version = 1,
+        .maxattr = TEST_ATTR_MAX,
+};
+
+struct loopback_param_s {
+        u32 packet_num;
+        u32 packet_id;
+};
+
+static struct loopback_param_s loopback_param;
+u32 get_loopback_num()
+{
+        return loopback_param.packet_num;
+}
+
+u32 get_loopback_id()
+{
+        return loopback_param.packet_id;
+}
+
+void inc_loopback_id()
+{
+        loopback_param.packet_id++;
+}
+
+#define REGISTER_REPLY(info) \
+        memcpy((char *)&info_copy, (char *)(info), sizeof(struct genl_info))
+
+
+static void sip_send_test_cmd(struct esp_sip *sip, struct sk_buff *skb)
+{
+        skb_queue_tail(&sip->epub->txq, skb);
+
+#if  !defined(FPGA_LOOPBACK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+        ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work);
+#else
+        queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
+#endif
+
+}
+
+static int esp_test_cmd_reply(struct genl_info *info, u32 cmd_type, char *reply_info)
+{
+        struct sk_buff *skb;
+        void *hdr;
+
+        /*directly send ask_info to target, and waiting for report*/
+        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+        if (skb == NULL)
+                goto out;
+
+        //hdr = genlmsg_put(skb,  info->snd_pid, info->snd_seq, &test_genl_family, 0, cmd_type);libing
+        hdr = genlmsg_put(skb,  info->snd_portid, info->snd_seq, &test_genl_family, 0, cmd_type);
+        if (hdr == NULL)
+                goto nla_put_failure;
+
+        //NLA_PUT_STRING(skb, TEST_ATTR_STR, reply_info); libing
+
+        nla_put_string(skb, TEST_ATTR_STR, reply_info); 
+
+        genlmsg_end(skb, hdr);
+        genlmsg_reply(skb, info);
+        return 0;
+
+nla_put_failure:
+        nlmsg_free(skb);
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_echo(struct sk_buff *skb_2,
+                         struct genl_info *info)
+{
+        char *echo_info;
+        int res;
+
+        if (info == NULL)
+                goto out;
+
+       // connected_nl = info->snd_pid;
+        //printk(KERN_DEBUG "esp_sdio: received a echo, "
+        //       "from pid %d\n", info->snd_pid);  libing
+        
+        connected_nl = info->snd_portid;
+        printk(KERN_DEBUG "esp_sdio: received a echo, "
+               "from pid %d\n", info->snd_portid);
+           sip_debug_show(SIP);
+       
+        /*get echo info*/
+        echo_info = nla_data(info->attrs[TEST_ATTR_STR]);
+
+        res=esp_test_cmd_reply(info, TEST_CMD_ECHO, echo_info);
+        return res;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_sdiospeed(struct sk_buff *skb_2,
+                              struct genl_info *info)
+{
+        char *speed_info;
+        int res;
+
+        if (info == NULL)
+                goto out;
+
+        //connected_nl = info->snd_pid; add libing
+        connected_nl = info->snd_portid;
+
+        /*get echo info*/
+        speed_info = nla_data(info->attrs[TEST_ATTR_STR]);
+
+       // printk(KERN_DEBUG "esp_sdio: received a sdio speed %s, "
+        //       "from pid %d\n", speed_info, info->snd_pid); libing
+                printk(KERN_DEBUG "esp_sdio: received a sdio speed %s, "
+               "from pid %d\n", speed_info, info->snd_portid);
+
+        if (!strcmp(speed_info, "high")) {
+                sif_platform_target_speed(1);
+        } else if (!strcmp(speed_info, "low")) {
+                sif_platform_target_speed(0);
+        } else {
+                printk(KERN_DEBUG "%s:  %s unsupported\n", __func__, speed_info);
+        }
+
+        res=esp_test_cmd_reply(info, TEST_CMD_SDIOSPEED, speed_info);
+        return res;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_ask(struct sk_buff *skb_2,
+                        struct genl_info *info)
+{
+        char *ask_info;
+        int res;
+
+        if (info == NULL)
+                goto out;
+
+        /*get echo info*/
+        ask_info = nla_data(info->attrs[TEST_ATTR_STR]);
+
+        /*directly send ask_info to target, and waiting for report*/
+        res=esp_test_cmd_reply(info, TEST_CMD_ASK, "ok");
+        return res;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_sleep(struct sk_buff *skb_2,
+                          struct genl_info *info)
+{
+        struct sip_cmd_sleep *sleepcmd;
+        struct sk_buff *skb = NULL;
+        int res;
+
+        if (info == NULL)
+                goto out;
+
+        skb = sip_alloc_ctrl_skbuf(SIP, sizeof(struct sip_cmd_sleep), SIP_CMD_SLEEP);
+        if (!skb)
+                goto out;
+
+        sleepcmd = (struct sip_cmd_sleep *)(skb->data + sizeof(struct sip_tx_info));
+        sleepcmd->sleep_mode       =  nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
+        sleepcmd->sleep_tm_ms     =  nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
+        sleepcmd->wakeup_tm_ms  =  nla_get_u32(info->attrs[TEST_ATTR_PARA2]);
+        sleepcmd->sleep_times       =  nla_get_u32(info->attrs[TEST_ATTR_PARA3]);
+
+        sip_send_test_cmd(SIP, skb);
+
+        /*directly send ask_info to target, and waiting for report*/
+        res=esp_test_cmd_reply(info, TEST_CMD_SLEEP, "ok");
+        return res;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_wakeup(struct sk_buff *skb_2,
+                           struct genl_info *info)
+{
+        struct sip_cmd_wakeup *wakeupcmd;
+        struct sk_buff *skb = NULL;
+        //int res;
+
+        if (info == NULL)
+                goto out;
+
+        skb = sip_alloc_ctrl_skbuf(SIP, sizeof(struct sip_cmd_wakeup), SIP_CMD_WAKEUP);
+        if (!skb)
+                goto out;
+        wakeupcmd = (struct sip_cmd_wakeup *)(skb->data + sizeof(struct sip_tx_info));
+        wakeupcmd->check_data = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
+
+        /*directly send reply_info to target, and waiting for report*/
+        REGISTER_REPLY(info);
+        //res=esp_test_cmd_reply(info, TEST_CMD_WAKEUP, "ok");
+
+        sip_send_test_cmd(SIP, skb);
+        return 0;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_loopback(struct sk_buff *skb_2,
+                             struct genl_info *info)
+{
+        u32 txpacket_len;
+        u32 rxpacket_len;
+
+        if (info == NULL)
+                goto out;
+
+        txpacket_len   = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
+        rxpacket_len   = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
+        loopback_param.packet_num    = nla_get_u32(info->attrs[TEST_ATTR_PARA2]);
+        loopback_param.packet_id=0;
+        REGISTER_REPLY(info);
+        return sip_send_loopback_mblk(SIP, txpacket_len, rxpacket_len, 0);
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+/*
+u8 probe_req_frm[] = {0x40,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0x8F,0x11,0x22,0x88,
+                      0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x08,0x82,0x84,0x8B,0x96,
+                      0x0C,0x12,0x18,0x24,0x32,0x04,0x30,0x48,0x60,0x6C
+                     };
+*/
+
+static int sip_send_tx_frame(struct esp_sip *sip, u32 packet_len)
+{
+
+        struct sk_buff *skb = NULL;
+        u8 *ptr = NULL;
+        int i;
+
+        skb = alloc_skb(packet_len, GFP_KERNEL);
+        skb->len = packet_len;
+        ptr = skb->data;
+        /* fill up pkt payload */
+        for (i = 0; i < skb->len; i++) {
+                ptr[i] = i;
+        }
+#ifdef FPGA_LOOPBACK
+        skb_queue_tail(&sip->epub->txq, skb);
+        queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
+#else
+        sip_tx_data_pkt_enqueue(sip->epub, skb);
+    #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
+        ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work);
+    #else
+        queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
+    #endif
+#endif
+        return 0;
+}
+
+static int esp_test_tx(struct sk_buff *skb_2,
+                       struct genl_info *info)
+{
+        u32 txpacket_len;
+        u32 res;
+
+        if (info == NULL)
+                goto out;
+
+        txpacket_len     = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
+        REGISTER_REPLY(info);
+        sip_send_tx_frame(SIP, txpacket_len);
+        res=esp_test_cmd_reply(info, TEST_CMD_TX, "tx out");
+        return res;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_genl(struct sk_buff *skb_2,
+                         struct genl_info *info)
+{
+        struct sip_cmd_debug *dbgcmd;
+        struct sk_buff *skb = NULL;
+        int i;
+
+        if (info == NULL)
+                goto out;
+
+        skb = sip_alloc_ctrl_skbuf(SIP, sizeof(struct sip_cmd_debug), SIP_CMD_DEBUG);
+        if (!skb)
+                goto out;
+
+        dbgcmd = (struct sip_cmd_debug *)(skb->data + sizeof(struct sip_hdr));
+        dbgcmd->cmd_type = nla_get_u32(info->attrs[TEST_ATTR_CMD_TYPE]);
+        dbgcmd->para_num = nla_get_u32(info->attrs[TEST_ATTR_PARA_NUM]);
+        printk(KERN_DEBUG "%s dbgcmdType %d paraNum %d\n", __func__, dbgcmd->cmd_type, dbgcmd->para_num);
+        for (i=0; i<dbgcmd->para_num; i++)
+                dbgcmd->para[i] = nla_get_u32(info->attrs[TEST_ATTR_PARA(i)]);
+
+        /*directly send reply_info to target, and waiting for report*/
+        REGISTER_REPLY(info);
+
+        sip_send_test_cmd(SIP, skb);
+        return 0;
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_sdio_wr(struct sk_buff *skb_2,
+                            struct genl_info *info)
+{
+        int res;
+        u32 func_no, addr, value;
+
+        if (info == NULL)
+                goto out;
+
+        func_no = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
+        addr = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
+        value = nla_get_u32(info->attrs[TEST_ATTR_PARA2]);
+
+        if(!func_no) {
+               res = esp_common_writebyte_with_addr(SIP->epub, addr, (u8)value, ESP_SIF_SYNC);
+        } else {
+                memcpy(sdio_buff, (u8 *)&value, 4);
+               res = esp_common_write_with_addr(SIP->epub, addr, sdio_buff, 4, ESP_SIF_SYNC);
+        }
+
+        /*directly send reply_info to target, and waiting for report*/
+        REGISTER_REPLY(info);
+        if (!res)
+                esp_test_cmd_reply(info, TEST_CMD_SDIO_WR, "write ok!");
+        else
+                esp_test_cmd_reply(info, TEST_CMD_SDIO_WR, "write fail!");
+
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+static int esp_test_sdio_rd(struct sk_buff *skb_2,
+                            struct genl_info *info)
+{
+        int res;
+        u32 func_no, addr, value;
+        char value_str[12];
+
+        if (info == NULL)
+                goto out;
+
+        func_no = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
+        addr = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
+
+        if(!func_no) {
+                memset(sdio_buff, 0, 4);
+                res = esp_common_readbyte_with_addr(SIP->epub, addr, &sdio_buff[0], ESP_SIF_SYNC);
+        } else {
+                res = esp_common_read_with_addr(SIP->epub, addr, sdio_buff, 4, ESP_SIF_SYNC);
+        }
+        memcpy((u8 *)&value, sdio_buff, 4);
+
+        /*directly send reply_info to target, and waiting for report*/
+        REGISTER_REPLY(info);
+        if (!res) {
+                sprintf((char *)&value_str, "0x%x", value);
+                esp_test_cmd_reply(info, TEST_CMD_SDIO_RD, value_str);
+        } else
+                esp_test_cmd_reply(info, TEST_CMD_SDIO_RD, "read fail!");
+
+out:
+        OUT_DONE();
+        return -EINVAL;
+}
+
+/* TEST_CMD netlink policy */
+
+static struct nla_policy test_genl_policy[TEST_ATTR_MAX + 1] = {
+        [TEST_ATTR_CMD_NAME]= { .type = NLA_NUL_STRING, .len = GENL_NAMSIZ - 1 },
+        [TEST_ATTR_CMD_TYPE] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA_NUM] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA0] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA1] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA2] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA3] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA4] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA5] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA6] = { .type = NLA_U32 },
+        [TEST_ATTR_PARA7] = { .type = NLA_U32 },
+        [TEST_ATTR_STR]        = { .type = NLA_NUL_STRING, .len = 256-1 },
+};
+
+/* Generic Netlink operations array */
+static struct genl_ops esp_test_ops[] = {
+        {
+                .cmd = TEST_CMD_ECHO,
+                .policy = test_genl_policy,
+                .doit = esp_test_echo,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_ASK,
+                .policy = test_genl_policy,
+                .doit = esp_test_ask,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_SLEEP,
+                .policy = test_genl_policy,
+                .doit = esp_test_sleep,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_WAKEUP,
+                .policy = test_genl_policy,
+                .doit = esp_test_wakeup,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_LOOPBACK,
+                .policy = test_genl_policy,
+                .doit = esp_test_loopback,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_TX,
+                .policy = test_genl_policy,
+                .doit = esp_test_tx,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_DEBUG,
+                .policy = test_genl_policy,
+                .doit = esp_test_genl,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_SDIO_WR,
+                .policy = test_genl_policy,
+                .doit = esp_test_sdio_wr,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_SDIO_RD,
+                .policy = test_genl_policy,
+                .doit = esp_test_sdio_rd,
+                .flags = GENL_ADMIN_PERM,
+        },
+        {
+                .cmd = TEST_CMD_SDIOSPEED,
+                .policy = test_genl_policy,
+                .doit = esp_test_sdiospeed,
+                .flags = GENL_ADMIN_PERM,
+        },
+};
+
+static int esp_test_netlink_notify(struct notifier_block *nb,
+                                   unsigned long state,
+                                   void *_notify)
+{
+        struct netlink_notify *notify = _notify;
+
+        if (state != NETLINK_URELEASE)
+                return NOTIFY_DONE;
+
+        /*if (notify->pid == connected_nl) {
+                printk(KERN_INFO "esp_sdio: user released netlink"
+                       " socket \n");
+                connected_nl = 0;
+        }*/ // libing
+        if (notify->portid == connected_nl) {
+                printk(KERN_INFO "esp_sdio: user released netlink"
+                       " socket \n");
+                connected_nl = 0;
+        }
+        return NOTIFY_DONE;
+
+}
+
+static struct notifier_block test_netlink_notifier = {
+        .notifier_call = esp_test_netlink_notify,
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
+/**
+ * copy from net/netlink/genetlink.c(linux kernel 2.6.32)
+ *
+ * genl_register_family_with_ops - register a generic netlink family
+ * @family: generic netlink family
+ * @ops: operations to be registered
+ * @n_ops: number of elements to register
+ * 
+ * Registers the specified family and operations from the specified table.
+ * Only one family may be registered with the same family name or identifier.
+ * 
+ * The family id may equal GENL_ID_GENERATE causing an unique id to
+ * be automatically generated and assigned.
+ * 
+ * Either a doit or dumpit callback must be specified for every registered
+ * operation or the function will fail. Only one operation structure per
+ * command identifier may be registered.
+ * 
+ * See include/net/genetlink.h for more documenation on the operations
+ * structure.
+ * 
+ * This is equivalent to calling genl_register_family() followed by
+ * genl_register_ops() for every operation entry in the table taking
+ * care to unregister the family on error path.
+ * 
+ * Return 0 on success or a negative error code.
+ */
+int genl_register_family_with_ops(struct genl_family *family,
+        struct genl_ops *ops, size_t n_ops)
+{
+    int err, i;
+
+    err = genl_register_family(family);
+    if (err)
+        return err;
+
+    for (i = 0; i < n_ops; ++i, ++ops) {
+        err = genl_register_ops(family, ops);
+        if (err)
+            goto err_out;
+    }
+    return 0;
+err_out:
+    genl_unregister_family(family);
+    return err;
+}
+#endif
+
+int test_init_netlink(struct esp_sip *sip)
+{
+        int rc;
+        printk(KERN_INFO "esp_sdio: initializing netlink\n");
+
+        sip_copy=sip;
+        /* temp buffer for sdio test */
+        sdio_buff = kzalloc(8, GFP_KERNEL);
+
+        rc = genl_register_family_with_ops(&test_genl_family,
+                                           esp_test_ops, ARRAY_SIZE(esp_test_ops));
+        if (rc)
+                goto failure;
+
+        rc = netlink_register_notifier(&test_netlink_notifier);
+        if (rc)
+                goto failure;
+
+        return 0;
+
+failure:
+        printk(KERN_DEBUG "esp_sdio: error occured in %s\n", __func__);
+        kfree(sdio_buff);
+        return -EINVAL;
+}
+
+void test_exit_netlink(void)
+{
+        int ret;
+
+       if (sdio_buff == NULL)
+               return;
+
+        kfree(sdio_buff);
+       sdio_buff = NULL;
+       sip_copy = NULL;
+       
+        printk(KERN_INFO "esp_sdio: closing netlink\n");
+        /* unregister the notifier */
+        netlink_unregister_notifier(&test_netlink_notifier);
+        /* unregister the family */
+        ret = genl_unregister_family(&test_genl_family);
+        if (ret)
+                printk(KERN_DEBUG "esp_sdio: "
+                       "unregister family %i\n", ret);
+}
+void esp_test_cmd_event(u32 cmd_type, char *reply_info)
+{
+        esp_test_cmd_reply(&info_copy, cmd_type, reply_info);
+}
+#endif  //ifdef TEST_MODE
+
diff --git a/drivers/net/wireless/rockchip_wlan/esp8089/testmode.h b/drivers/net/wireless/rockchip_wlan/esp8089/testmode.h
new file mode 100755 (executable)
index 0000000..b8be32e
--- /dev/null
@@ -0,0 +1,46 @@
+\r
+#ifndef __TEST_MODE\r
+#define __TEST_MODE\r
+\r
+enum {\r
+        TEST_CMD_UNSPEC,\r
+        TEST_CMD_ECHO,\r
+        TEST_CMD_ASK,\r
+        TEST_CMD_SLEEP,\r
+        TEST_CMD_WAKEUP,\r
+        TEST_CMD_LOOPBACK,\r
+        TEST_CMD_TX,\r
+        TEST_CMD_RX,\r
+        TEST_CMD_DEBUG,\r
+        TEST_CMD_SDIO_WR,\r
+        TEST_CMD_SDIO_RD,\r
+        TEST_CMD_SDIOSPEED,\r
+        __TEST_CMD_MAX,\r
+};\r
+#define TEST_CMD_MAX (__TEST_CMD_MAX - 1)\r
+\r
+enum {\r
+        TEST_ATTR_UNSPEC,\r
+        TEST_ATTR_CMD_NAME,\r
+        TEST_ATTR_CMD_TYPE,\r
+        TEST_ATTR_PARA_NUM,\r
+        TEST_ATTR_PARA0,\r
+        TEST_ATTR_PARA1,\r
+        TEST_ATTR_PARA2,\r
+        TEST_ATTR_PARA3,\r
+        TEST_ATTR_PARA4,\r
+        TEST_ATTR_PARA5,\r
+        TEST_ATTR_PARA6,\r
+        TEST_ATTR_PARA7,\r
+        TEST_ATTR_STR,\r
+        __TEST_ATTR_MAX,\r
+};\r
+#define TEST_ATTR_MAX (__TEST_ATTR_MAX - 1)\r
+#define TEST_ATTR_PARA(i) (TEST_ATTR_PARA0+(i))\r
+\r
+u32 get_loopback_num(void);\r
+u32 get_loopback_id(void);\r
+void inc_loopback_id(void);\r
+#endif\r
+\r
+\r
index acb7a09163354ff2725203e6b5bdf8b0ba8d8840..9974404ae4cfcb6737fc4d58afb9aaae5b5ee244 100755 (executable)
@@ -81,6 +81,8 @@ enum rockchip_pinctrl_type {
        RK3066B,
        RK3188,
        RK3288,
+       RK3036,
+       RK312X,
 };
 
 enum rockchip_pin_bank_type {
@@ -371,7 +373,7 @@ static ssize_t  pinctrl_show_regs(struct file *file, char __user *user_buf,
        len += snprintf(buf + len, PINCTRL_REGS_BUFSIZE - len,
                        "=================================\n\n");
 
-       if(bank0)
+       if(bank0 && bank0->reg_mux_bank0 && bank0->reg_pull_bank0 && bank0->reg_drv_bank0)
        {
                len += snprintf(buf + len, PINCTRL_REGS_BUFSIZE - len,
                                "BANK0 GRF registers:\n");
@@ -1211,6 +1213,46 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
 }
 
 
+static void rk3036_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+                                   int pin_num, void __iomem **reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       void __iomem *reg_base;
+       int pin = pin_num;
+       
+       *reg = info->reg_pull;
+       *reg += bank->bank_num * RK3036_PULL_BANK_STRIDE;
+       *reg += (pin_num / RK3036_PULL_PINS_PER_REG) * 4;
+
+       *bit = pin_num % RK3036_PULL_PINS_PER_REG;
+
+       reg_base = info->reg_pull;
+
+       DBG_PINCTRL("%s:GPIO%d-%d, pull_reg=0x%x, bit=%d\n", __func__, bank->bank_num, pin_num, *reg - reg_base, *bit);
+}
+
+
+static void rk312x_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+                                   int pin_num, void __iomem **reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       void __iomem *reg_base;
+       int pin = pin_num;
+       
+       *reg = info->reg_pull;
+       *reg += bank->bank_num * RK312X_PULL_BANK_STRIDE;
+       *reg += (pin_num / RK312X_PULL_PINS_PER_REG) * 4;
+
+       *bit = pin_num % RK312X_PULL_PINS_PER_REG;
+
+       reg_base = info->reg_pull;
+
+       DBG_PINCTRL("%s:GPIO%d-%d, pull_reg=0x%x, bit=%d\n", __func__, bank->bank_num, pin_num, *reg - reg_base, *bit);
+}
+
+
+
+
 #if 0
 static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 {
@@ -1279,11 +1321,15 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 
        switch (ctrl->type) {
        case RK2928:
+       case RK3036:
+       case RK312X:
                spin_lock_irqsave(&bank->slock, flags);
 
                data = BIT(bit + 16);
                if (pull == PIN_CONFIG_BIAS_DISABLE)
                        data |= BIT(bit);
+               
+               if(pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
                writel(data, reg);
 
                spin_unlock_irqrestore(&bank->slock, flags);
@@ -1337,6 +1383,8 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
 {
        switch (ctrl->type) {
        case RK2928:
+       case RK3036:
+       case RK312X:
                return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT ||
                                        pull == PIN_CONFIG_BIAS_DISABLE);
        case RK3066B:
@@ -1685,6 +1733,76 @@ static int _rockchip_pinconf_set(struct rockchip_pin_bank *bank,
 
                break;
 
+               case RK3036:
+
+               switch(config_type)
+               {                       
+                       case TYPE_DRV_REG:
+
+                               if((bank->bank_num == 1) && (pin_num >= 0) && (pin_num <= 3))
+                               {
+                                       bit = pin_num*2 + 4;
+                                       reg = info->reg_drv;
+                                       spin_lock_irqsave(&bank->slock, flags);
+
+                                       data = arg << bit;
+                                       data &= (3<<bit);
+                                       data |= (3<<(bit+16));
+                                       
+                                       writel_relaxed(data, reg);
+                                       spin_unlock_irqrestore(&bank->slock, flags);
+                               }
+                               else
+                               {
+                                       printk("%s:RK3036 GPIO%d-%d could not support driver setting\n",__func__, bank->bank_num, pin_num);
+                               }
+                               break;
+                       default:
+                               break;
+
+               }
+
+               break;
+
+               case RK312X:
+
+               switch(config_type)
+               {                       
+                       case TYPE_DRV_REG:
+
+                               if((bank->bank_num == 0)&&((pin_num == GPIO_A6)|| (pin_num == GPIO_A7)||(pin_num == GPIO_B7)||(pin_num == GPIO_C4)))
+                               {
+                                       if(pin_num == GPIO_A6)
+                                       bit = 4;
+                                       else if(pin_num == GPIO_A7)
+                                       bit = 6;
+                                       else if(pin_num == GPIO_B7)
+                                       bit = 8;
+                                       else if(pin_num == GPIO_C4)
+                                       bit = 10;
+
+                                       reg = info->reg_drv;
+                                       spin_lock_irqsave(&bank->slock, flags);
+
+                                       data = arg << bit;
+                                       data &= (3<<bit);
+                                       data |= (3<<(bit+16));
+                                       
+                                       writel_relaxed(data, reg);
+                                       spin_unlock_irqrestore(&bank->slock, flags);
+                               }
+                               else
+                               {
+                                       printk("%s:RK312X GPIO%d-%d could not support driver setting\n",__func__, bank->bank_num, pin_num);
+                               }
+                               break;
+                       default:
+                               break;
+
+               }
+
+               break;
+
                default:
                break;
        }
@@ -2007,6 +2125,8 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np,
                                pull = PIN_CONFIG_BIAS_PULL_DOWN;
                        else if (val == 3)
                                pull = PIN_CONFIG_BIAS_BUS_HOLD;
+                       else if (val == 4)
+                               pull = PIN_CONFIG_BIAS_PULL_PIN_DEFAULT;
                        
                        pinconfig[j++] = pinconf_to_config_packed(pull, val);
                }
@@ -3051,6 +3171,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
                        break;
 
                case RK3188:
+               case RK3036:
+               case RK312X:
                        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                        info->reg_base = devm_ioremap_resource(&pdev->dev, res);
                        if (IS_ERR(info->reg_base))
@@ -3243,6 +3365,44 @@ static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
 };
 
 
+static struct rockchip_pin_bank rk3036_pin_banks[] = {
+       PIN_BANK(0, 32, "gpio0"),
+       PIN_BANK(1, 32, "gpio1"),
+       PIN_BANK(2, 32, "gpio2"),
+       
+       PIN_BANK(15, 32, "gpio15"),//virtual bank
+};
+
+static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
+               .pin_banks              = rk3036_pin_banks,
+               .nr_banks               = ARRAY_SIZE(rk3036_pin_banks),
+               .label                  = "rk3036-GPIO",
+               .type                   = RK3036,
+               .mux_offset             = 0xa8,
+               .pull_calc_reg  = rk3036_calc_pull_reg_and_bit,
+};
+
+
+static struct rockchip_pin_bank rk312x_pin_banks[] = {
+       PIN_BANK(0, 32, "gpio0"),
+       PIN_BANK(1, 32, "gpio1"),
+       PIN_BANK(2, 32, "gpio2"),
+       PIN_BANK(3, 32, "gpio3"),
+       
+       PIN_BANK(15, 32, "gpio15"),//virtual bank
+};
+
+static struct rockchip_pin_ctrl rk312x_pin_ctrl = {
+               .pin_banks              = rk312x_pin_banks,
+               .nr_banks               = ARRAY_SIZE(rk312x_pin_banks),
+               .label                  = "rk312x-GPIO",
+               .type                   = RK312X,
+               .mux_offset             = 0xa8,
+               .pull_calc_reg  = rk312x_calc_pull_reg_and_bit,
+};
+
+
+
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
        { .compatible = "rockchip,rk2928-pinctrl",
                .data = (void *)&rk2928_pin_ctrl },
@@ -3254,6 +3414,10 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
                .data = (void *)&rk3188_pin_ctrl },
        { .compatible = "rockchip,rk3288-pinctrl",
                .data = (void *)&rk3288_pin_ctrl },
+       { .compatible = "rockchip,rk3036-pinctrl",
+               .data = (void *)&rk3036_pin_ctrl },
+       { .compatible = "rockchip,rk312x-pinctrl",
+               .data = (void *)&rk312x_pin_ctrl },
        {},
 };
 MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);
index 713afa0d605c6636ae696bd7920985fd55c21e75..0d362e5fa0ee692aaef2ffc3d90518a196f3c881 100644 (file)
@@ -789,31 +789,6 @@ static int _autosleep_disable(struct battery_info *di)
 }
 
 #endif
-static void  _set_relax_thres(struct battery_info *di)
-{
-       u8 buf;
-       int enter_thres,exit_thres;
-       struct cell_state *cell = &di->cell;
-
-       enter_thres = (cell->config->ocv->sleep_enter_current)*1000/1506;
-       exit_thres = (cell->config->ocv->sleep_exit_current)*1000/1506;
-
-       buf  =  enter_thres&0xff;
-       battery_write(di->rk818, RELAX_ENTRY_THRES_REGL, &buf,1);
-       buf =   (enter_thres>>8)&0xff;
-       battery_write(di->rk818, RELAX_ENTRY_THRES_REGH, &buf,1);
-
-       buf  =  exit_thres&0xff;
-       battery_write(di->rk818, RELAX_EXIT_THRES_REGL, &buf,1);
-       buf  =  (exit_thres>>8)&0xff;
-       battery_write(di->rk818, RELAX_EXIT_THRES_REGH, &buf,1);
-
-       //set sample time
-        battery_read(di->rk818,GGCON, &buf, 1);
-       buf &= ~(3<<2);
-       battery_write(di->rk818, GGCON, &buf,1);
- }
-
 static int rk818_battery_voltage(struct battery_info *di)
 {
        int ret;
@@ -1013,77 +988,6 @@ static int _get_realtime_capacity(struct battery_info *di)
 
 }
 
-static int _get_relax_vol1(struct battery_info *di)
-{
-       int ret;
-       int temp = 0,voltage_now;
-       u8 buf;
-
-       ret = battery_read(di->rk818,RELAX_VOL1_REGL, &buf, 1);
-       temp = buf;
-       ret = battery_read(di->rk818,RELAX_VOL1_REGH, &buf, 1);
-       temp |= buf<<8;
-//     ret = battery_read(di->rk818,RELAX_VOL1_REGH, &buf, 2);
-//     temp  = (buf[0]<<8)|buf[1];
-       voltage_now = di ->voltage_k*temp + di->voltage_b;
-
-       return voltage_now;
-}
-
-static int _get_relax_vol2(struct battery_info *di)
-{
-       int ret;
-       int temp = 0,voltage_now;
-       u8 buf;
-
-       ret = battery_read(di->rk818,RELAX_VOL2_REGL, &buf, 1);
-       temp = buf;
-       ret = battery_read(di->rk818,RELAX_VOL2_REGH, &buf, 1);
-       temp |= buf<<8;
-//     ret = battery_read(di->rk818,RELAX_VOL2_REGH, &buf, 2);
-//     temp  = (buf[0]<<8)|buf[1];
-       voltage_now = di ->voltage_k*temp + di->voltage_b;
-
-       return temp;
-}
-
-static bool  _is_relax_mode(struct battery_info *di)
-{
-       int ret;
-       u8 status;
-       int relax_vol1,relax_vol2;
-
-       struct cell_state *cell = &di->cell;
-       
-       ret = battery_read(di->rk818,GGSTS, &status, 1);
-       DBG(" GGSTS the value is %2x the realsoc = %d \n", status, di->real_soc);
-       
-       if(!(status&RELAX_STS))
-               return false;
-       if((!(status&RELAX_VOL1_UPD))||(!(status&RELAX_VOL2_UPD)))
-               return false;
-       else{
-               if ((di->real_soc>= cell->config->ocv->flat_zone_low)
-                       && (di->real_soc <= cell->config->ocv->flat_zone_high))
-                       return false;                           
-               relax_vol1 = _get_relax_vol1(di);
-               relax_vol2 = _get_relax_vol2(di);
-               DBG("relax_vol1 = %d relax_vol2 =%d \n", relax_vol1,relax_vol2);
-               if((abs_int((relax_vol2 - relax_vol1)))/8/60 > 4 )
-                       return false;
-       }
-
-       return true;
-}
-
-
-static int relax_soc(struct battery_info *di)
-{
-       //int relax_soc;
-       _voltage_to_capacity( di, di->voltage);
-       return di->temp_soc;
-}
-
 static int _get_vcalib0(struct battery_info *di)
 {
 
@@ -1334,15 +1238,6 @@ static int _copy_soc(struct  battery_info * di, u8 save_soc)
        
        return 0;
 }
-static void  _save_rsoc_nac(struct  battery_info * di)
-{
-       u8 buf;
-
-       buf = di->real_soc;
-       
-       battery_write(di->rk818, SOC_REG, &buf, 1);
-       
-}
 
 static int _rsoc_init(struct  battery_info * di)
 {
@@ -1922,7 +1817,6 @@ static int rk818_battery_parse_dt(struct rk818 *rk818)
 
        return 0;
 }
-
 static struct of_device_id rk818_battery_of_match[] = {
        { .compatible = "rk818_battery" },
        { }
@@ -1939,7 +1833,6 @@ static int rk818_battery_parse_dt(struct device *dev)
 static int  battery_probe(struct platform_device *pdev)
 {
        struct rk818 *chip = dev_get_drvdata(pdev->dev.parent);
-       struct rk818_platform_data *rk818_platform_data = chip->dev->platform_data;
 //     struct battery_platform_data *pdata ;//= rk818_platform_data->battery_data;
 //     struct battery_platform_data defdata ;//= rk818_platform_data->battery_data;
        struct battery_info *di;
@@ -2035,7 +1928,6 @@ static int  battery_remove(struct platform_device *dev)
 #if 1
 static int battery_suspend(struct platform_device *dev,pm_message_t state)
 {
-       int irq;
        struct battery_info *di = platform_get_drvdata(dev);
        DBG("%s--------------------\n",__FUNCTION__);
        if(di == NULL)
@@ -2048,7 +1940,6 @@ static int battery_suspend(struct platform_device *dev,pm_message_t state)
 
 static int battery_resume(struct platform_device *dev)
 {
-       int irq;
        
        u8 buf;
        int ret;
@@ -2074,7 +1965,7 @@ static struct platform_driver battery_driver = {
        .driver         = {
                .name   = "rk818-battery",
                //.pm   = &pm_ops,
-       //      .of_match_table = of_match_ptr(rk818_battery_parse_dt),
+               .of_match_table = of_match_ptr(rk818_battery_of_match),
        },
 };
 
index ea05d7d66991c4f81dfdc03beaddd67590b150bc..c20f4b867bfe6ea9fd21a023ad0bcb302408106a 100755 (executable)
@@ -569,6 +569,7 @@ static int  hym8563_probe(struct i2c_client *client, const struct i2c_device_id
        gClient = client;       
        hym8563->client = client;
        hym8563->alarm.enabled = 0;
+       client->irq = 0;
        mutex_init(&hym8563->mutex);
        wake_lock_init(&hym8563->wake_lock, WAKE_LOCK_SUSPEND, "rtc_hym8563");
        i2c_set_clientdata(client, hym8563);
@@ -591,15 +592,17 @@ static int  hym8563_probe(struct i2c_client *client, const struct i2c_device_id
        }       
        
        client->irq = of_get_named_gpio_flags(np, "irq_gpio", 0,(enum of_gpio_flags *)&irq_flags);
-       
-       hym8563->irq = gpio_to_irq(client->irq);
-       result = devm_request_threaded_irq(&client->dev, hym8563->irq, NULL, hym8563_wakeup_irq, irq_flags | IRQF_ONESHOT, client->dev.driver->name,hym8563 );
-       if (result) {
-               printk(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, hym8563->irq, result);           
-               goto exit;             
-       }
-       enable_irq_wake(hym8563->irq);
-       device_init_wakeup(&client->dev, 1);    
+       if(client->irq >= 0)
+        {
+               hym8563->irq = gpio_to_irq(client->irq);
+               result = devm_request_threaded_irq(&client->dev, hym8563->irq, NULL, hym8563_wakeup_irq, irq_flags | IRQF_ONESHOT, client->dev.driver->name,hym8563 );
+               if (result) {
+                       printk(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, hym8563->irq, result);
+                       goto exit;
+               }
+               enable_irq_wake(hym8563->irq);
+               device_init_wakeup(&client->dev, 1);
+        }
        rtc = devm_rtc_device_register(&client->dev,
                        client->name,
                                &hym8563_rtc_ops, THIS_MODULE);
index c26e3cee6dd41c8b5d7220558cf9766d9a3a996f..41a537eeea8a0ae06c62d76070d716e34ee9f04e 100755 (executable)
@@ -932,7 +932,7 @@ static int ion_debug_client_show_buffer_map(struct seq_file *s, struct ion_buffe
 int ion_map_iommu(struct device *iommu_dev, struct ion_client *client,
                 struct ion_handle *handle, unsigned long *iova, unsigned long *size)
 {
-       return 0;
+       return 0;
 }
 void ion_unmap_iommu(struct device *iommu_dev, struct ion_client *client,
                         struct ion_handle *handle)
index 9af238ce165b0d2a38095827d0017e15e133fbf9..b1656829613ba3fcfc481040f780a8cb7a0ad0bf 100755 (executable)
@@ -25,5 +25,5 @@ endif
 dwc_otg-objs   += common_port/dwc_common_linux.o
 
 #objs relative to RK platform
-dwc_otg-objs   += usbdev_rk30.o usbdev_rk32.o usbdev_bc.o
+dwc_otg-objs   += usbdev_rk30.o usbdev_rk32.o usbdev_rk3036.o usbdev_rk3126.o usbdev_bc.o
 obj-$(CONFIG_DWC_OTG_310) := dwc_otg.o
index 3afba4084333f0474c65466660b59ba0e8642a36..57034a80f4ee13cd7dad13225cd7ef223e6ceb7a 100755 (executable)
@@ -86,6 +86,14 @@ static struct usb20otg_pdata_id usb20otg_pdata[] = {
         .name = "rk3288-usb20otg",
         .pdata = &usb20otg_pdata_rk3288,
         },
+       {
+        .name = "rk3036-usb20otg",
+        .pdata = &usb20otg_pdata_rk3036,
+        },
+       {
+        .name = "rk3126-usb20otg",
+        .pdata = &usb20otg_pdata_rk3126,
+        },
        {},
 };
 #endif
@@ -100,6 +108,14 @@ static struct usb20host_pdata_id usb20host_pdata[] = {
         .name = "rk3288-usb20host",
         .pdata = &usb20host_pdata_rk3288,
         },
+       {
+        .name = "rk3036-usb20host",
+        .pdata = &usb20host_pdata_rk3036,
+        },
+       {
+        .name = "rk3126-usb20host",
+        .pdata = &usb20host_pdata_rk3126,
+        },
        {},
 };
 #endif
@@ -972,6 +988,14 @@ static const struct of_device_id usb20_host_of_match[] = {
         .compatible = "rockchip,rk3288_usb20_host",
         .data = &usb20host_pdata[RK3288_USB_CTLR],
         },
+       {
+        .compatible = "rockchip,rk3036_usb20_host",
+        .data = &usb20host_pdata[RK3036_USB_CTLR],
+        },
+       {
+        .compatible = "rockchip,rk3126_usb20_host",
+        .data = &usb20host_pdata[RK3126_USB_CTLR],
+        },
        {},
 };
 
@@ -1326,6 +1350,14 @@ static const struct of_device_id usb20_otg_of_match[] = {
         .compatible = "rockchip,rk3288_usb20_otg",
         .data = &usb20otg_pdata[RK3288_USB_CTLR],
         },
+       {
+        .compatible = "rockchip,rk3036_usb20_otg",
+        .data = &usb20otg_pdata[RK3036_USB_CTLR],
+        },
+       {
+        .compatible = "rockchip,rk3126_usb20_otg",
+        .data = &usb20otg_pdata[RK3126_USB_CTLR],
+        },
        {
         },
 };
index ad382069033e8f79fd66117e10e0c8ba73cbfba8..5a23309071058f53939e320115397389b9311ef9 100755 (executable)
@@ -143,8 +143,7 @@ int usb_battery_charger_detect_rk(bool wait)
 
 int usb_battery_charger_detect_inno(bool wait)
 {
-
-       return -1;
+       return readl(RK_GRF_VIRT + RK312X_GRF_SOC_STATUS0) & (1 << 8);
 }
 
 /* When do BC detect PCD pull-up register should be disabled  */
old mode 100644 (file)
new mode 100755 (executable)
index 319581b..8b4a727
@@ -8,6 +8,7 @@ typedef volatile struct tag_grf_uoc0_reg {
        u32 CON2;
        u32 CON3;
        u32 CON4;
+       u32 CON5;
 } GRF_UOC0_REG, *pGRF_UOC0_REG;
 
 typedef volatile struct tag_grf_uoc1_reg {
@@ -20,6 +21,7 @@ typedef volatile struct tag_grf_uoc1_reg {
        u32 CON2;
        u32 CON3;
        u32 CON4;
+       u32 CON5;
 } GRF_UOC1_REG, *pGRF_UOC1_REG;
 
 typedef volatile struct tag_grf_uoc2_reg {
index 0c6e48a57d9812482ec4d16e1add619b84cfb963..06584dd516ca443b3e981a9a18a02af220870b0d 100755 (executable)
@@ -22,6 +22,7 @@
 #include <linux/rockchip/cru.h>
 #include <linux/rockchip/grf.h>
 #include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
 
 #include "usbdev_grf_regs.h"
 #include "usbdev_bc.h"
@@ -41,6 +42,9 @@
 #define USB_REMOTE_WAKEUP     (6)
 #define USB_IRQ_WAKEUP        (7)
 
+#define UOC_HIWORD_UPDATE(val, mask, shift) \
+               ((val) << (shift) | (mask) << ((shift) + 16))
+
 enum rkusb_rst_flag {
        RST_POR = 0, /* Reset power-on */
        RST_RECNT,      /* Reset re-connect */
@@ -60,6 +64,13 @@ extern struct dwc_otg_platform_data usb20host_pdata_rk3288;
 extern struct rkehci_platform_data rkhsic_pdata_rk3288;
 extern struct rkehci_platform_data rkehci_pdata_rk3288;
 extern struct rkehci_platform_data rkohci_pdata_rk3288;
+/* rk3036 platform data */
+extern struct dwc_otg_platform_data usb20otg_pdata_rk3036;
+extern struct dwc_otg_platform_data usb20host_pdata_rk3036;
+/* rk3126 platform data */
+extern struct dwc_otg_platform_data usb20otg_pdata_rk3126;
+extern struct dwc_otg_platform_data usb20host_pdata_rk3126;
+
 
 struct dwc_otg_platform_data {
        void *privdata;
@@ -108,6 +119,7 @@ struct dwc_otg_control_usb {
        pGRF_SOC_STATUS2_RK3288 grf_soc_status2_rk3288;
        pGRF_SOC_STATUS19_RK3288 grf_soc_status19_rk3288;
        pGRF_SOC_STATUS21_RK3288 grf_soc_status21_rk3288;
+
        struct gpio *host_gpios;
        struct gpio *otg_gpios;
        struct clk *hclk_usb_peri;
@@ -122,6 +134,8 @@ struct dwc_otg_control_usb {
 enum {
        RK3188_USB_CTLR = 0,    /* rk3188 chip usb */
        RK3288_USB_CTLR,        /* rk3288 chip usb */
+       RK3036_USB_CTLR,        /* rk3036 chip usb */
+       RK3126_USB_CTLR,
 };
 
 struct usb20otg_pdata_id {
diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3036.c b/drivers/usb/dwc_otg_310/usbdev_rk3036.c
new file mode 100755 (executable)
index 0000000..b8fe46c
--- /dev/null
@@ -0,0 +1,608 @@
+#include "usbdev_rk.h"
+#include "usbdev_grf_regs.h"
+#include "dwc_otg_regs.h"
+static struct dwc_otg_control_usb *control_usb;
+
+#ifdef CONFIG_USB20_OTG
+static void usb20otg_hw_init(void)
+{
+       /* other haredware init,include:
+        * DRV_VBUS GPIO init */
+       if (gpio_is_valid(control_usb->otg_gpios->gpio)) {
+               if (gpio_get_value(control_usb->otg_gpios->gpio))
+                       gpio_set_value(control_usb->otg_gpios->gpio, 0);
+       }
+}
+
+static void usb20otg_phy_suspend(void *pdata, int suspend)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (suspend) {
+               /* enable soft control */
+               writel(UOC_HIWORD_UPDATE(0x55, 0x7f, 0),
+                      RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+               usbpdata->phy_status = 1;
+       } else {
+               /* exit suspend */
+               writel(UOC_HIWORD_UPDATE(0x0, 0x1, 0),
+                      RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+               usbpdata->phy_status = 0;
+       }
+}
+
+static void usb20otg_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct reset_control *rst_otg_h, *rst_otg_p, *rst_otg_c;
+
+       rst_otg_h = devm_reset_control_get(usbpdata->dev, "otg_ahb");
+       rst_otg_p = devm_reset_control_get(usbpdata->dev, "otg_phy");
+       rst_otg_c = devm_reset_control_get(usbpdata->dev, "otg_controller");
+       if (IS_ERR(rst_otg_h) || IS_ERR(rst_otg_p) || IS_ERR(rst_otg_c)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
+
+       switch(rst_type) {
+       case RST_POR:
+               /* PHY reset */
+               writel(UOC_HIWORD_UPDATE(0x1, 0x3, 0),
+                          RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+               reset_control_assert(rst_otg_p);
+               udelay(15);
+               writel(UOC_HIWORD_UPDATE(0x2, 0x3, 0),
+                          RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+               udelay(1500);
+               reset_control_deassert(rst_otg_p);
+               udelay(2);
+
+               /* Controller reset */
+               reset_control_assert(rst_otg_c);
+               reset_control_assert(rst_otg_h);
+
+               udelay(2);
+
+               reset_control_deassert(rst_otg_c);
+               reset_control_deassert(rst_otg_h);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void usb20otg_clock_init(void *pdata)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct clk *ahbclk, *phyclk;
+
+       ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb0");
+       if (IS_ERR(ahbclk)) {
+               dev_err(usbpdata->dev, "Failed to get hclk_usb0\n");
+               return;
+       }
+
+       phyclk = devm_clk_get(usbpdata->dev, "clk_usbphy0");
+       if (IS_ERR(phyclk)) {
+               dev_err(usbpdata->dev, "Failed to get clk_usbphy0\n");
+               return;
+       }
+
+       usbpdata->phyclk = phyclk;
+       usbpdata->ahbclk = ahbclk;
+}
+
+static void usb20otg_clock_enable(void *pdata, int enable)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (enable) {
+               clk_prepare_enable(usbpdata->ahbclk);
+               clk_prepare_enable(usbpdata->phyclk);
+       } else {
+               clk_disable_unprepare(usbpdata->ahbclk);
+               /*
+                  clk_disable_unprepare(usbpdata->phyclk);
+                */
+       }
+}
+
+static int usb20otg_get_status(int id)
+{
+       int ret = -1;
+       u32 soc_status0 = readl(RK_GRF_VIRT + RK3036_GRF_SOC_STATUS0);
+
+       switch (id) {
+       case USB_STATUS_BVABLID:
+               /* bvalid in grf */
+               ret = soc_status0 & (0x1 << 8);
+               break;
+       case USB_STATUS_DPDM:
+               /* dpdm in grf */
+               ret = soc_status0 & (0x3 << 9);
+               break;
+       case USB_STATUS_ID:
+               /* id in grf */
+               ret = soc_status0 & (0x1 << 11);
+               break;
+       case USB_CHIP_ID:
+               ret = control_usb->chip_id;
+               break;
+       case USB_REMOTE_WAKEUP:
+               ret = control_usb->remote_wakeup;
+               break;
+       case USB_IRQ_WAKEUP:
+               ret = control_usb->usb_irq_wakeup;
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode)
+{
+#ifdef CONFIG_RK_USB_UART
+       if (1 == enter_usb_uart_mode) {
+               /* bypass dm, enter uart mode */
+               writel(UOC_HIWORD_UPDATE(0x3, 0x3, 12),
+                      RK_GRF_VIRT + RK3036_GRF_UOC1_CON4);
+       } else if (0 == enter_usb_uart_mode) {
+               /* enter usb mode */
+               writel(UOC_HIWORD_UPDATE(0x0, 0x3, 12),
+                      RK_GRF_VIRT + RK3036_GRF_UOC1_CON4);
+       }
+#endif
+}
+
+static void usb20otg_power_enable(int enable)
+{
+       if (0 == enable) {
+               /* disable otg_drv power */
+               if (gpio_is_valid(control_usb->otg_gpios->gpio))
+                       gpio_set_value(control_usb->otg_gpios->gpio, 0);
+       } else if (1 == enable) {
+               /* enable otg_drv power */
+               if (gpio_is_valid(control_usb->otg_gpios->gpio))
+                       gpio_set_value(control_usb->otg_gpios->gpio, 1);
+       }
+}
+
+struct dwc_otg_platform_data usb20otg_pdata_rk3036 = {
+       .phyclk = NULL,
+       .ahbclk = NULL,
+       .busclk = NULL,
+       .phy_status = 0,
+       .hw_init = usb20otg_hw_init,
+       .phy_suspend = usb20otg_phy_suspend,
+       .soft_reset = usb20otg_soft_reset,
+       .clock_init = usb20otg_clock_init,
+       .clock_enable = usb20otg_clock_enable,
+       .get_status = usb20otg_get_status,
+       .power_enable = usb20otg_power_enable,
+       .dwc_otg_uart_mode = dwc_otg_uart_mode,
+       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+};
+#endif
+
+#ifdef CONFIG_USB20_HOST
+static void usb20host_hw_init(void)
+{
+       /* other haredware init,include:
+        * DRV_VBUS GPIO init */
+       if (gpio_is_valid(control_usb->host_gpios->gpio)) {
+               if (!gpio_get_value(control_usb->host_gpios->gpio))
+                       gpio_set_value(control_usb->host_gpios->gpio, 1);
+       }
+}
+
+static void usb20host_phy_suspend(void *pdata, int suspend)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (suspend) {
+               /* enable soft control */
+               writel(UOC_HIWORD_UPDATE(0x1d5, 0x1ff, 0),
+                      RK_GRF_VIRT + RK3036_GRF_UOC1_CON5);
+               usbpdata->phy_status = 1;
+       } else {
+               /* exit suspend */
+               writel(UOC_HIWORD_UPDATE(0x0, 0x1, 0),
+                      RK_GRF_VIRT + RK3036_GRF_UOC1_CON5);
+               usbpdata->phy_status = 0;
+       }
+}
+
+static void usb20host_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct reset_control *rst_host_h, *rst_host_p, *rst_host_c;
+
+       rst_host_h = devm_reset_control_get(usbpdata->dev, "host_ahb");
+       rst_host_p = devm_reset_control_get(usbpdata->dev, "host_phy");
+       rst_host_c = devm_reset_control_get(usbpdata->dev, "host_controller");
+       if (IS_ERR(rst_host_h) || IS_ERR(rst_host_p) || IS_ERR(rst_host_c)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
+
+       switch(rst_type) {
+       case RST_POR:
+               /* PHY reset */
+               writel(UOC_HIWORD_UPDATE(0x1, 0x3, 0),
+                          RK_GRF_VIRT + RK3036_GRF_UOC1_CON5);
+               reset_control_assert(rst_host_p);
+               udelay(15);
+               writel(UOC_HIWORD_UPDATE(0x2, 0x3, 0),
+                          RK_GRF_VIRT + RK3036_GRF_UOC1_CON5);
+
+               udelay(1500);
+               reset_control_deassert(rst_host_p);
+
+               /* Controller reset */
+               reset_control_assert(rst_host_c);
+               reset_control_assert(rst_host_h);
+
+               udelay(5);
+
+               reset_control_deassert(rst_host_c);
+               reset_control_deassert(rst_host_h);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void usb20host_clock_init(void *pdata)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct clk *ahbclk, *phyclk;
+
+       ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb1");
+       if (IS_ERR(ahbclk)) {
+               dev_err(usbpdata->dev, "Failed to get hclk_usb1\n");
+               return;
+       }
+
+       phyclk = devm_clk_get(usbpdata->dev, "clk_usbphy1");
+       if (IS_ERR(phyclk)) {
+               dev_err(usbpdata->dev, "Failed to get clk_usbphy1\n");
+               return;
+       }
+
+       usbpdata->phyclk = phyclk;
+       usbpdata->ahbclk = ahbclk;
+}
+
+static void usb20host_clock_enable(void *pdata, int enable)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (enable) {
+               clk_prepare_enable(usbpdata->ahbclk);
+               clk_prepare_enable(usbpdata->phyclk);
+       } else {
+               clk_disable_unprepare(usbpdata->ahbclk);
+               clk_disable_unprepare(usbpdata->phyclk);
+       }
+}
+
+static int usb20host_get_status(int id)
+{
+       int ret = -1;
+       u32 soc_status0 = readl(RK_GRF_VIRT + RK3036_GRF_SOC_STATUS0);
+
+       switch (id) {
+       case USB_STATUS_BVABLID:
+               /* bvalid in grf */
+               ret = soc_status0 & (0x1 << 13);
+               break;
+       case USB_STATUS_DPDM:
+               /* dpdm in grf */
+               ret = soc_status0 & (0x3 << 14);
+               break;
+       case USB_STATUS_ID:
+               /* id in grf */
+               ret = 0;
+               break;
+       case USB_CHIP_ID:
+               ret = control_usb->chip_id;
+               break;
+       case USB_REMOTE_WAKEUP:
+               ret = control_usb->remote_wakeup;
+               break;
+       case USB_IRQ_WAKEUP:
+               ret = control_usb->usb_irq_wakeup;
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static void usb20host_power_enable(int enable)
+{
+       if (0 == enable) {
+               /* disable host_drv power */
+               /* do not disable power in default */
+       } else if (1 == enable) {
+               /* enable host_drv power */
+               if (gpio_is_valid(control_usb->host_gpios->gpio))
+                       gpio_set_value(control_usb->host_gpios->gpio, 1);
+       }
+}
+
+struct dwc_otg_platform_data usb20host_pdata_rk3036 = {
+       .phyclk = NULL,
+       .ahbclk = NULL,
+       .busclk = NULL,
+       .phy_status = 0,
+       .hw_init = usb20host_hw_init,
+       .phy_suspend = usb20host_phy_suspend,
+       .soft_reset = usb20host_soft_reset,
+       .clock_init = usb20host_clock_init,
+       .clock_enable = usb20host_clock_enable,
+       .get_status = usb20host_get_status,
+       .power_enable = usb20host_power_enable,
+};
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id rk_usb_control_id_table[] = {
+       {
+        .compatible = "rockchip,rk3036-usb-control",
+        },
+       {},
+};
+#endif
+/*********************************************************************
+                       rk3036 usb detections
+*********************************************************************/
+
+#define WAKE_LOCK_TIMEOUT (HZ * 10)
+static inline void do_wakeup(struct work_struct *work)
+{
+       /* wake up the system */
+       rk_send_wakeup_key();
+}
+
+static void usb_battery_charger_detect_work(struct work_struct *work)
+{
+       rk_usb_charger_status = usb_battery_charger_detect(0);
+}
+
+/********** handler for bvalid irq **********/
+static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
+{
+       /* clear irq */
+       writel(UOC_HIWORD_UPDATE(0x1, 0x1, 15),
+              RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+#ifdef CONFIG_RK_USB_UART
+       /* usb otg dp/dm switch to usb phy */
+       dwc_otg_uart_mode(NULL, PHY_USB_MODE);
+#endif
+
+       if (control_usb->usb_irq_wakeup) {
+               wake_lock_timeout(&control_usb->usb_wakelock,
+                                 WAKE_LOCK_TIMEOUT);
+               schedule_delayed_work(&control_usb->usb_det_wakeup_work,
+                                     HZ / 10);
+       }
+
+       rk_usb_charger_status = USB_BC_TYPE_SDP;
+       schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
+
+       return IRQ_HANDLED;
+}
+
+/************* register usb detection irqs **************/
+static int otg_irq_detect_init(struct platform_device *pdev)
+{
+       int ret = 0;
+       int irq = 0;
+
+       if (control_usb->usb_irq_wakeup) {
+               wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND,
+                              "usb_detect");
+               INIT_DELAYED_WORK(&control_usb->usb_det_wakeup_work, do_wakeup);
+       }
+
+       /*register otg_bvalid irq */
+       irq = platform_get_irq_byname(pdev, "otg_bvalid");
+       if ((irq > 0) && control_usb->usb_irq_wakeup) {
+               ret = request_irq(irq, bvalid_irq_handler,
+                                 0, "otg_bvalid", NULL);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "request_irq %d failed!\n", irq);
+               } else {
+                       /* enable bvalid irq  */
+                       writel(UOC_HIWORD_UPDATE(0x1, 0x1, 14),
+                              RK_GRF_VIRT + RK3036_GRF_UOC0_CON5);
+               }
+       }
+       return ret;
+}
+
+/********** end of rk3036 usb detections **********/
+static int rk_usb_control_probe(struct platform_device *pdev)
+{
+       int gpio, err;
+       struct device_node *np = pdev->dev.of_node;
+       int ret = 0;
+
+       control_usb =
+           devm_kzalloc(&pdev->dev, sizeof(*control_usb), GFP_KERNEL);
+       if (!control_usb) {
+               dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       control_usb->chip_id = RK3036_USB_CTLR;
+       control_usb->remote_wakeup = of_property_read_bool(np,
+                                                          "rockchip,remote_wakeup");
+       control_usb->usb_irq_wakeup = of_property_read_bool(np,
+                                                           "rockchip,usb_irq_wakeup");
+
+       INIT_DELAYED_WORK(&control_usb->usb_charger_det_work,
+                         usb_battery_charger_detect_work);
+
+       control_usb->host_gpios =
+           devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
+       if (!control_usb->host_gpios) {
+               dev_err(&pdev->dev, "unable to alloc memory for host_gpios\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       gpio = of_get_named_gpio(np, "host_drv_gpio", 0);
+       control_usb->host_gpios->gpio = gpio;
+
+       if (!gpio_is_valid(gpio)) {
+               dev_err(&pdev->dev, "invalid host gpio%d\n", gpio);
+       } else {
+               err = devm_gpio_request(&pdev->dev, gpio, "host_drv_gpio");
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO%d for host_drv\n",
+                               gpio);
+                       ret = err;
+                       goto out;
+               }
+               gpio_direction_output(control_usb->host_gpios->gpio, 1);
+       }
+
+       control_usb->otg_gpios =
+           devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
+       if (!control_usb->otg_gpios) {
+               dev_err(&pdev->dev, "unable to alloc memory for otg_gpios\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       gpio = of_get_named_gpio(np, "otg_drv_gpio", 0);
+       control_usb->otg_gpios->gpio = gpio;
+
+       if (!gpio_is_valid(gpio)) {
+               dev_err(&pdev->dev, "invalid otg gpio%d\n", gpio);
+       } else {
+               err = devm_gpio_request(&pdev->dev, gpio, "otg_drv_gpio");
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO%d for otg_drv\n", gpio);
+                       ret = err;
+                       goto out;
+               }
+               gpio_direction_output(control_usb->otg_gpios->gpio, 0);
+       }
+
+out:
+       return ret;
+}
+
+static int rk_usb_control_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static struct platform_driver rk_usb_control_driver = {
+       .probe = rk_usb_control_probe,
+       .remove = rk_usb_control_remove,
+       .driver = {
+                  .name = "rk3036-usb-control",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(rk_usb_control_id_table),
+                  },
+};
+
+#ifdef CONFIG_OF
+
+static const struct of_device_id dwc_otg_control_usb_id_table[] = {
+       {
+        .compatible = "rockchip,rk3036-dwc-control-usb",
+        },
+       {},
+};
+
+#endif
+static int dwc_otg_control_usb_probe(struct platform_device *pdev)
+{
+       struct clk *hclk_usb_peri;
+       int ret = 0;
+
+       if (!control_usb) {
+               dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri");
+       if (IS_ERR(hclk_usb_peri)) {
+               dev_err(&pdev->dev, "Failed to get hclk_usb_peri\n");
+               ret = -EINVAL;
+               goto err1;
+       }
+
+       control_usb->hclk_usb_peri = hclk_usb_peri;
+       clk_prepare_enable(hclk_usb_peri);
+
+#ifdef CONFIG_USB20_OTG
+       if (usb20otg_get_status(USB_STATUS_BVABLID)) {
+               rk_usb_charger_status = USB_BC_TYPE_SDP;
+               schedule_delayed_work(&control_usb->usb_charger_det_work,
+                                     HZ / 10);
+       }
+#endif
+
+       ret = otg_irq_detect_init(pdev);
+       if (ret < 0)
+               goto err2;
+
+       return 0;
+
+err2:
+       clk_disable_unprepare(hclk_usb_peri);
+err1:
+       return ret;
+}
+
+static int dwc_otg_control_usb_remove(struct platform_device *pdev)
+{
+       clk_disable_unprepare(control_usb->hclk_usb_peri);
+       return 0;
+}
+
+static struct platform_driver dwc_otg_control_usb_driver = {
+       .probe = dwc_otg_control_usb_probe,
+       .remove = dwc_otg_control_usb_remove,
+       .driver = {
+                  .name = "rk3036-dwc-control-usb",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table),
+                  },
+};
+
+static int __init dwc_otg_control_usb_init(void)
+{
+       int retval = 0;
+
+       retval |= platform_driver_register(&rk_usb_control_driver);
+       retval |= platform_driver_register(&dwc_otg_control_usb_driver);
+       return retval;
+}
+
+subsys_initcall(dwc_otg_control_usb_init);
+
+static void __exit dwc_otg_control_usb_exit(void)
+{
+       platform_driver_unregister(&rk_usb_control_driver);
+       platform_driver_unregister(&dwc_otg_control_usb_driver);
+}
+
+module_exit(dwc_otg_control_usb_exit);
+MODULE_ALIAS("platform: dwc_control_usb");
+MODULE_AUTHOR("RockChip Inc.");
+MODULE_DESCRIPTION("RockChip Control Module USB Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/dwc_otg_310/usbdev_rk3126.c b/drivers/usb/dwc_otg_310/usbdev_rk3126.c
new file mode 100755 (executable)
index 0000000..098a4b7
--- /dev/null
@@ -0,0 +1,607 @@
+#include "usbdev_rk.h"
+#include "usbdev_grf_regs.h"
+#include "dwc_otg_regs.h"
+static struct dwc_otg_control_usb *control_usb;
+
+#ifdef CONFIG_USB20_OTG
+static void usb20otg_hw_init(void)
+{
+       /* other haredware init,include:
+        * DRV_VBUS GPIO init */
+       if (gpio_is_valid(control_usb->otg_gpios->gpio)) {
+               if (gpio_get_value(control_usb->otg_gpios->gpio))
+                       gpio_set_value(control_usb->otg_gpios->gpio, 0);
+       }
+}
+
+static void usb20otg_phy_suspend(void *pdata, int suspend)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       if (suspend) {
+               /* enable soft control */
+               writel(UOC_HIWORD_UPDATE(0x55, 0x7f, 0),
+                      RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+               usbpdata->phy_status = 1;
+       } else {
+               /* exit suspend */
+               writel(UOC_HIWORD_UPDATE(0x0, 0x1, 0),
+                      RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+               usbpdata->phy_status = 0;
+       }
+}
+
+static void usb20otg_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct reset_control *rst_otg_h, *rst_otg_p, *rst_otg_c;
+
+       rst_otg_h = devm_reset_control_get(usbpdata->dev, "otg_ahb");
+       rst_otg_p = devm_reset_control_get(usbpdata->dev, "otg_phy");
+       rst_otg_c = devm_reset_control_get(usbpdata->dev, "otg_controller");
+       if (IS_ERR(rst_otg_h) || IS_ERR(rst_otg_p) || IS_ERR(rst_otg_c)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
+
+       switch(rst_type) {
+       case RST_POR:
+               /* PHY reset */
+               writel(UOC_HIWORD_UPDATE(0x1, 0x3, 0),
+                          RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+               reset_control_assert(rst_otg_p);
+               udelay(15);
+               writel(UOC_HIWORD_UPDATE(0x2, 0x3, 0),
+                          RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+               udelay(1500);
+               reset_control_deassert(rst_otg_p);
+               udelay(2);
+
+               /* Controller reset */
+               reset_control_assert(rst_otg_c);
+               reset_control_assert(rst_otg_h);
+
+               udelay(2);
+
+               reset_control_deassert(rst_otg_c);
+               reset_control_deassert(rst_otg_h);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void usb20otg_clock_init(void *pdata)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct clk *ahbclk, *phyclk;
+
+       ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb0");
+       if (IS_ERR(ahbclk)) {
+               dev_err(usbpdata->dev, "Failed to get hclk_usb0\n");
+               return;
+       }
+
+       phyclk = devm_clk_get(usbpdata->dev, "clk_usbphy0");
+       if (IS_ERR(phyclk)) {
+               dev_err(usbpdata->dev, "Failed to get clk_usbphy0\n");
+               return;
+       }
+
+       usbpdata->phyclk = phyclk;
+       usbpdata->ahbclk = ahbclk;
+}
+
+static void usb20otg_clock_enable(void *pdata, int enable)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (enable) {
+               clk_prepare_enable(usbpdata->ahbclk);
+               clk_prepare_enable(usbpdata->phyclk);
+       } else {
+               clk_disable_unprepare(usbpdata->ahbclk);
+               /*
+                  clk_disable_unprepare(usbpdata->phyclk);
+                */
+       }
+}
+
+static int usb20otg_get_status(int id)
+{
+       int ret = -1;
+       u32 soc_status0 = readl(RK_GRF_VIRT + RK312X_GRF_SOC_STATUS0);
+       switch (id) {
+       case USB_STATUS_BVABLID:
+               /* bvalid in grf */
+               ret = soc_status0 & (0x1 << 5);
+               break;
+       case USB_STATUS_DPDM:
+               /* dpdm in grf */
+               ret = soc_status0 & (0x3 << 6);
+               break;
+       case USB_STATUS_ID:
+               /* id in grf */
+               ret = soc_status0 & (0x1 << 8);
+               break;
+       case USB_CHIP_ID:
+               ret = control_usb->chip_id;
+               break;
+       case USB_REMOTE_WAKEUP:
+               ret = control_usb->remote_wakeup;
+               break;
+       case USB_IRQ_WAKEUP:
+               ret = control_usb->usb_irq_wakeup;
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static void dwc_otg_uart_mode(void *pdata, int enter_usb_uart_mode)
+{
+#ifdef CONFIG_RK_USB_UART
+       if (1 == enter_usb_uart_mode) {
+               /* bypass dm, enter uart mode */
+               writel(UOC_HIWORD_UPDATE(0x3, 0x3, 12),
+                      RK_GRF_VIRT + RK312X_GRF_UOC1_CON4);
+       } else if (0 == enter_usb_uart_mode) {
+               /* enter usb mode */
+               writel(UOC_HIWORD_UPDATE(0x0, 0x3, 12),
+                      RK_GRF_VIRT + RK312X_GRF_UOC1_CON4);
+       }
+#endif
+}
+
+static void usb20otg_power_enable(int enable)
+{
+       if (0 == enable) {
+               /* disable otg_drv power */
+               if (gpio_is_valid(control_usb->otg_gpios->gpio))
+                       gpio_set_value(control_usb->otg_gpios->gpio, 0);
+       } else if (1 == enable) {
+               /* enable otg_drv power */
+               if (gpio_is_valid(control_usb->otg_gpios->gpio))
+                       gpio_set_value(control_usb->otg_gpios->gpio, 1);
+       }
+}
+
+struct dwc_otg_platform_data usb20otg_pdata_rk3126 = {
+       .phyclk = NULL,
+       .ahbclk = NULL,
+       .busclk = NULL,
+       .phy_status = 0,
+       .hw_init = usb20otg_hw_init,
+       .phy_suspend = usb20otg_phy_suspend,
+       .soft_reset = usb20otg_soft_reset,
+       .clock_init = usb20otg_clock_init,
+       .clock_enable = usb20otg_clock_enable,
+       .get_status = usb20otg_get_status,
+       .power_enable = usb20otg_power_enable,
+       .dwc_otg_uart_mode = dwc_otg_uart_mode,
+       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+};
+#endif
+
+#ifdef CONFIG_USB20_HOST
+static void usb20host_hw_init(void)
+{
+       /* other haredware init,include:
+        * DRV_VBUS GPIO init */
+       if (gpio_is_valid(control_usb->host_gpios->gpio)) {
+               if (!gpio_get_value(control_usb->host_gpios->gpio))
+                       gpio_set_value(control_usb->host_gpios->gpio, 1);
+       }
+}
+
+static void usb20host_phy_suspend(void *pdata, int suspend)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (suspend) {
+               /* enable soft control */
+               writel(UOC_HIWORD_UPDATE(0x1d5, 0x1ff, 0),
+                      RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+               usbpdata->phy_status = 1;
+       } else {
+               /* exit suspend */
+               writel(UOC_HIWORD_UPDATE(0x0, 0x1, 0),
+                      RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+               usbpdata->phy_status = 0;
+       }
+}
+
+static void usb20host_soft_reset(void *pdata, enum rkusb_rst_flag rst_type)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct reset_control *rst_host_h, *rst_host_p, *rst_host_c;
+
+       rst_host_h = devm_reset_control_get(usbpdata->dev, "host_ahb");
+       rst_host_p = devm_reset_control_get(usbpdata->dev, "host_phy");
+       rst_host_c = devm_reset_control_get(usbpdata->dev, "host_controller");
+       if (IS_ERR(rst_host_h) || IS_ERR(rst_host_p) || IS_ERR(rst_host_c)) {
+               dev_err(usbpdata->dev, "Fail to get reset control from dts\n");
+               return;
+       }
+
+       switch(rst_type) {
+       case RST_POR:
+               /* PHY reset */
+               writel(UOC_HIWORD_UPDATE(0x1, 0x3, 0),
+                          RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+               reset_control_assert(rst_host_p);
+               udelay(15);
+               writel(UOC_HIWORD_UPDATE(0x2, 0x3, 0),
+                          RK_GRF_VIRT + RK312X_GRF_UOC1_CON5);
+
+               udelay(1500);
+               reset_control_deassert(rst_host_p);
+
+               /* Controller reset */
+               reset_control_assert(rst_host_c);
+               reset_control_assert(rst_host_h);
+
+               udelay(5);
+
+               reset_control_deassert(rst_host_c);
+               reset_control_deassert(rst_host_h);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void usb20host_clock_init(void *pdata)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+       struct clk *ahbclk, *phyclk;
+
+       ahbclk = devm_clk_get(usbpdata->dev, "hclk_usb1");
+       if (IS_ERR(ahbclk)) {
+               dev_err(usbpdata->dev, "Failed to get hclk_usb1\n");
+               return;
+       }
+
+       phyclk = devm_clk_get(usbpdata->dev, "clk_usbphy1");
+       if (IS_ERR(phyclk)) {
+               dev_err(usbpdata->dev, "Failed to get clk_usbphy1\n");
+               return;
+       }
+
+       usbpdata->phyclk = phyclk;
+       usbpdata->ahbclk = ahbclk;
+}
+
+static void usb20host_clock_enable(void *pdata, int enable)
+{
+       struct dwc_otg_platform_data *usbpdata = pdata;
+
+       if (enable) {
+               clk_prepare_enable(usbpdata->ahbclk);
+               clk_prepare_enable(usbpdata->phyclk);
+       } else {
+               clk_disable_unprepare(usbpdata->ahbclk);
+               clk_disable_unprepare(usbpdata->phyclk);
+       }
+}
+
+static int usb20host_get_status(int id)
+{
+       int ret = -1;
+       u32 soc_status0 = readl(RK_GRF_VIRT + RK312X_GRF_SOC_STATUS0);
+
+       switch (id) {
+       case USB_STATUS_BVABLID:
+               /* bvalid in grf */
+               ret = soc_status0 & (0x1 << 10);
+               break;
+       case USB_STATUS_DPDM:
+               /* dpdm in grf */
+               ret = soc_status0 & (0x3 << 11);
+               break;
+       case USB_STATUS_ID:
+               /* id in grf */
+               ret = 0;
+               break;
+       case USB_CHIP_ID:
+               ret = control_usb->chip_id;
+               break;
+       case USB_REMOTE_WAKEUP:
+               ret = control_usb->remote_wakeup;
+               break;
+       case USB_IRQ_WAKEUP:
+               ret = control_usb->usb_irq_wakeup;
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static void usb20host_power_enable(int enable)
+{
+       if (0 == enable) {
+               /* disable host_drv power */
+               /* do not disable power in default */
+       } else if (1 == enable) {
+               /* enable host_drv power */
+               if (gpio_is_valid(control_usb->host_gpios->gpio))
+                       gpio_set_value(control_usb->host_gpios->gpio, 1);
+       }
+}
+
+struct dwc_otg_platform_data usb20host_pdata_rk3126 = {
+       .phyclk = NULL,
+       .ahbclk = NULL,
+       .busclk = NULL,
+       .phy_status = 0,
+       .hw_init = usb20host_hw_init,
+       .phy_suspend = usb20host_phy_suspend,
+       .soft_reset = usb20host_soft_reset,
+       .clock_init = usb20host_clock_init,
+       .clock_enable = usb20host_clock_enable,
+       .get_status = usb20host_get_status,
+       .power_enable = usb20host_power_enable,
+};
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id rk_usb_control_id_table[] = {
+       {
+        .compatible = "rockchip,rk3126-usb-control",
+        },
+       {},
+};
+#endif
+/*********************************************************************
+                       rk3126 usb detections
+*********************************************************************/
+
+#define WAKE_LOCK_TIMEOUT (HZ * 10)
+static inline void do_wakeup(struct work_struct *work)
+{
+       /* wake up the system */
+       rk_send_wakeup_key();
+}
+
+static void usb_battery_charger_detect_work(struct work_struct *work)
+{
+       rk_usb_charger_status = usb_battery_charger_detect(0);
+}
+
+/********** handler for bvalid irq **********/
+static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
+{
+       /* clear irq */
+       writel(UOC_HIWORD_UPDATE(0x1, 0x1, 15),
+              RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+#ifdef CONFIG_RK_USB_UART
+       /* usb otg dp/dm switch to usb phy */
+       dwc_otg_uart_mode(NULL, PHY_USB_MODE);
+#endif
+
+       if (control_usb->usb_irq_wakeup) {
+               wake_lock_timeout(&control_usb->usb_wakelock,
+                                 WAKE_LOCK_TIMEOUT);
+               schedule_delayed_work(&control_usb->usb_det_wakeup_work,
+                                     HZ / 10);
+       }
+
+       rk_usb_charger_status = USB_BC_TYPE_SDP;
+       schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
+
+       return IRQ_HANDLED;
+}
+
+/************* register usb detection irqs **************/
+static int otg_irq_detect_init(struct platform_device *pdev)
+{
+       int ret = 0;
+       int irq = 0;
+
+       if (control_usb->usb_irq_wakeup) {
+               wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND,
+                              "usb_detect");
+               INIT_DELAYED_WORK(&control_usb->usb_det_wakeup_work, do_wakeup);
+       }
+
+       /*register otg_bvalid irq */
+       irq = platform_get_irq_byname(pdev, "otg_bvalid");
+       if ((irq > 0) && control_usb->usb_irq_wakeup) {
+               ret = request_irq(irq, bvalid_irq_handler,
+                                 0, "otg_bvalid", NULL);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "request_irq %d failed!\n", irq);
+               } else {
+                       /* enable bvalid irq  */
+                       writel(UOC_HIWORD_UPDATE(0x1, 0x1, 14),
+                              RK_GRF_VIRT + RK312X_GRF_UOC0_CON0);
+               }
+       }
+       return ret;
+}
+
+/********** end of rk3126 usb detections **********/
+static int rk_usb_control_probe(struct platform_device *pdev)
+{
+       int gpio, err;
+       struct device_node *np = pdev->dev.of_node;
+       int ret = 0;
+
+       control_usb =
+           devm_kzalloc(&pdev->dev, sizeof(*control_usb), GFP_KERNEL);
+       if (!control_usb) {
+               dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       control_usb->chip_id = RK3126_USB_CTLR;
+       control_usb->remote_wakeup = of_property_read_bool(np,
+                                                          "rockchip,remote_wakeup");
+       control_usb->usb_irq_wakeup = of_property_read_bool(np,
+                                                           "rockchip,usb_irq_wakeup");
+
+       INIT_DELAYED_WORK(&control_usb->usb_charger_det_work,
+                         usb_battery_charger_detect_work);
+
+       control_usb->host_gpios =
+           devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
+       if (!control_usb->host_gpios) {
+               dev_err(&pdev->dev, "unable to alloc memory for host_gpios\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       gpio = of_get_named_gpio(np, "host_drv_gpio", 0);
+       control_usb->host_gpios->gpio = gpio;
+
+       if (!gpio_is_valid(gpio)) {
+               dev_err(&pdev->dev, "invalid host gpio%d\n", gpio);
+       } else {
+               err = devm_gpio_request(&pdev->dev, gpio, "host_drv_gpio");
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO%d for host_drv\n",
+                               gpio);
+                       ret = err;
+                       goto out;
+               }
+               gpio_direction_output(control_usb->host_gpios->gpio, 1);
+       }
+
+       control_usb->otg_gpios =
+           devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
+       if (!control_usb->otg_gpios) {
+               dev_err(&pdev->dev, "unable to alloc memory for otg_gpios\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       gpio = of_get_named_gpio(np, "otg_drv_gpio", 0);
+       control_usb->otg_gpios->gpio = gpio;
+
+       if (!gpio_is_valid(gpio)) {
+               dev_err(&pdev->dev, "invalid otg gpio%d\n", gpio);
+       } else {
+               err = devm_gpio_request(&pdev->dev, gpio, "otg_drv_gpio");
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO%d for otg_drv\n", gpio);
+                       ret = err;
+                       goto out;
+               }
+               gpio_direction_output(control_usb->otg_gpios->gpio, 0);
+       }
+
+out:
+       return ret;
+}
+
+static int rk_usb_control_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static struct platform_driver rk_usb_control_driver = {
+       .probe = rk_usb_control_probe,
+       .remove = rk_usb_control_remove,
+       .driver = {
+                  .name = "rk3126-usb-control",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(rk_usb_control_id_table),
+                  },
+};
+
+#ifdef CONFIG_OF
+
+static const struct of_device_id dwc_otg_control_usb_id_table[] = {
+       {
+        .compatible = "rockchip,rk3126-dwc-control-usb",
+        },
+       {},
+};
+
+#endif
+static int dwc_otg_control_usb_probe(struct platform_device *pdev)
+{
+       struct clk *hclk_usb_peri;
+       int ret = 0;
+
+       if (!control_usb) {
+               dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri");
+       if (IS_ERR(hclk_usb_peri)) {
+               dev_err(&pdev->dev, "Failed to get hclk_usb_peri\n");
+               ret = -EINVAL;
+               goto err1;
+       }
+
+       control_usb->hclk_usb_peri = hclk_usb_peri;
+       clk_prepare_enable(hclk_usb_peri);
+
+#ifdef CONFIG_USB20_OTG
+       if (usb20otg_get_status(USB_STATUS_BVABLID)) {
+               rk_usb_charger_status = USB_BC_TYPE_SDP;
+               schedule_delayed_work(&control_usb->usb_charger_det_work,
+                                     HZ / 10);
+       }
+#endif
+
+       ret = otg_irq_detect_init(pdev);
+       if (ret < 0)
+               goto err2;
+
+       return 0;
+
+err2:
+       clk_disable_unprepare(hclk_usb_peri);
+err1:
+       return ret;
+}
+
+static int dwc_otg_control_usb_remove(struct platform_device *pdev)
+{
+       clk_disable_unprepare(control_usb->hclk_usb_peri);
+       return 0;
+}
+
+static struct platform_driver dwc_otg_control_usb_driver = {
+       .probe = dwc_otg_control_usb_probe,
+       .remove = dwc_otg_control_usb_remove,
+       .driver = {
+                  .name = "rk3126-dwc-control-usb",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table),
+                  },
+};
+
+static int __init dwc_otg_control_usb_init(void)
+{
+       int retval = 0;
+
+       retval |= platform_driver_register(&rk_usb_control_driver);
+       retval |= platform_driver_register(&dwc_otg_control_usb_driver);
+       return retval;
+}
+
+subsys_initcall(dwc_otg_control_usb_init);
+
+static void __exit dwc_otg_control_usb_exit(void)
+{
+       platform_driver_unregister(&rk_usb_control_driver);
+       platform_driver_unregister(&dwc_otg_control_usb_driver);
+}
+
+module_exit(dwc_otg_control_usb_exit);
+MODULE_ALIAS("platform: dwc_control_usb");
+MODULE_AUTHOR("RockChip Inc.");
+MODULE_DESCRIPTION("RockChip Control Module USB Driver");
+MODULE_LICENSE("GPL v2");
+
index 6aca9688c6e083d6daef8724bc4c2d3fb84b921a..a45746bebf8b6e3ec1546e08ba4c50af557efc8b 100644 (file)
@@ -25,6 +25,10 @@ source "drivers/gpu/host1x/Kconfig"
 
 source "drivers/gpu/arm/midgard/Kconfig"
 
+source "drivers/gpu/arm/mali400/mali/Kconfig"
+
+source "drivers/gpu/arm/mali400/ump/Kconfig"
+
 config VGASTATE
        tristate
        default n
index e03c30460300cad518d25ce34fb32cf41bce1ce9..03f76012b5334cc5e2c276c4607979966f1819d8 100755 (executable)
@@ -7,4 +7,6 @@ obj-$(CONFIG_ROCKCHIP_RGA) += rga/
 obj-$(CONFIG_ROCKCHIP_RGA2) += rga2/
 obj-$(CONFIG_RK_HDMI) += display-sys.o hdmi/
 obj-$(CONFIG_IEP) += iep/
+obj-$(CONFIG_RK_TVENCODER) += tve/
+
 
index 932cec6853e43c1bc662173891ff2a791abfb745..0fbb96fe910ea75c5d09d8a9e8b79cb49bf7036e 100644 (file)
@@ -224,12 +224,12 @@ static int display_resume(struct device *dev)
 
 void rk_display_device_enable(struct rk_display_device *ddev)
 {
-#ifndef CONFIG_DISPLAY_AUTO_SWITCH     
-       return;
-#else
+//#ifndef CONFIG_DISPLAY_AUTO_SWITCH   
+//     return;
+//#else
        struct list_head *pos, *head = &display_device_list;
        struct rk_display_device *dev = NULL, *dev_enabled = NULL, *dev_enable = NULL;
-       int enable = 0,connect, has_connect = 0;
+       int enable = 0,connect;
        
        list_for_each(pos, head) {
                dev = list_entry(pos, struct rk_display_device, list);
@@ -257,7 +257,7 @@ void rk_display_device_enable(struct rk_display_device *ddev)
        }
                
 
-#endif
+//#endif
 }
 EXPORT_SYMBOL(rk_display_device_enable);
 
index b8797ffdeab8f842346026dfeb6f312a6296385b..93462410064a695b2bf5ffc550bd1bb36455a3b3 100755 (executable)
@@ -39,7 +39,7 @@ endif
 
 config  HDMI_RK616
         bool "RK616 HDMI support"
-        depends on MFD_RK616 || ARCH_RK3026
+depends on MFD_RK616 || ARCH_RK3026
                default y
         help
            Support rk616 hdmi if you say y here
@@ -48,6 +48,16 @@ if HDMI_RK616
 source "drivers/video/rockchip/hdmi/chips/rk616/Kconfig"
 endif
 
+config  HDMI_RK3036
+        bool "RK3036 HDMI support"
+               default y
+        help
+           Support rk3036 hdmi if you say y here
+
+if HDMI_RK3036
+source "drivers/video/rockchip/hdmi/chips/rk3036/Kconfig"
+endif
+
 choice
        prompt "HDMI Source LCDC select"
 config HDMI_SOURCE_LCDC0
index 0f2e4a1f146d5f9253cefa05e00fae44884ecc25..e61356c98eefe9cff3c9df0d79d3abbc0cb7bd09 100755 (executable)
@@ -9,4 +9,5 @@ obj-$(CONFIG_HDMI_RK2928) += rk2928/
 obj-$(CONFIG_HDMI_RK610) += rk610/
 obj-$(CONFIG_HDMI_CAT66121) += cat66121/
 obj-$(CONFIG_HDMI_RK616) += rk616/
+obj-$(CONFIG_HDMI_RK3036) += rk3036/
 obj-y += rk3288/
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/Kconfig b/drivers/video/rockchip/hdmi/chips/rk3036/Kconfig
new file mode 100755 (executable)
index 0000000..7c210a7
--- /dev/null
@@ -0,0 +1,19 @@
+config HDCP_RK3036
+       bool "RK3036 HDCP support"
+        default n
+       help
+         HDCP Interface. This adds the High Definition Content Protection Interface.
+         See http://www.digital-cp.com/ for HDCP specification.
+
+config HDCP_RK3036_DEBUG
+       bool "RK3036 HDCP Debugging"
+        depends on HDCP_RK3036
+        default n
+       help
+         Enableds verbose debugging the the HDCP drivers
+
+config CEC_RK3036
+       bool "RK3036 CEC support"
+        default n
+       help
+         CEC Interface. This adds the HDMI CEC Interface.
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/Makefile b/drivers/video/rockchip/hdmi/chips/rk3036/Makefile
new file mode 100755 (executable)
index 0000000..0766e06
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for HDMI linux kernel module.
+#
+
+ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
+ccflags-$(CONFIG_HDCP_RK616_DEBUG) = -DHDCP_DEBUG
+
+obj-$(CONFIG_HDMI_RK3036) += rk3036_hdmi_hw.o rk3036_hdmi.o
+obj-$(CONFIG_HDCP_RK3036) += rk3036_hdmi_hdcp.o rk3036_hdcp.o
+obj-$(CONFIG_CEC_RK3036) += rk3036_hdmi_cec.o
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdcp.c
new file mode 100755 (executable)
index 0000000..0ca7744
--- /dev/null
@@ -0,0 +1,585 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include "rk3036_hdmi.h"
+#include "rk3036_hdcp.h"
+
+struct hdcp *hdcp = NULL;
+
+static void hdcp_work_queue(struct work_struct *work);
+
+#define AUTH_TIMEOUT (2*HZ)
+static struct timer_list auth_timer;
+static int timer_state;
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_submit_work
+ *-----------------------------------------------------------------------------
+ */
+static struct delayed_work *hdcp_submit_work(int event, int delay)
+{
+       struct hdcp_delayed_work *work;
+
+       DBG("%s event %04x delay %d\n", __func__, event, delay);
+       work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+       if (work) {
+               INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
+               work->event = event;
+               queue_delayed_work(hdcp->workqueue,
+                                  &work->work,
+                                  msecs_to_jiffies(delay));
+       } else {
+               HDCP_WARN("HDCP:Cannot allocate memory to create work\n");
+               return 0;
+       }
+
+       return &work->work;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_cancel_work
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_cancel_work(struct delayed_work **work)
+{
+       int ret = 0;
+
+       if (*work) {
+               ret = cancel_delayed_work(*work);
+               if (ret != 1) {
+                       ret = cancel_work_sync(&((*work)->work));
+                       HDCP_WARN("Canceling sync work failed %d\n", ret);
+               }
+               kfree(*work);
+               *work = 0;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: auth_timer_func
+ *-----------------------------------------------------------------------------
+ */
+static void auth_timer_func(unsigned long data)
+{
+       HDCP_WARN("hdcp auth 2 second timeout\n");
+       if (hdcp->auth_state == 0) {
+               mod_timer(&auth_timer, jiffies + AUTH_TIMEOUT);
+               if ((hdcp->hdcp_state != HDCP_DISABLED) &&
+                   (hdcp->hdcp_state != HDCP_ENABLE_PENDING)) {
+                       if (is_1b_03_test())
+                               return;
+                       hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+               }
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_failure
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_failure(void)
+{
+       if (hdcp->hdmi_state == HDMI_STOPPED)
+               return;
+
+       rk3036_hdcp_disable();
+/*
+       rk3036_hdmi_control_output(false);
+ */
+       rk3036_set_colorbar(1);
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
+               if (hdcp->retry_cnt <= HDCP_INFINITE_REAUTH) {
+                       hdcp->retry_cnt--;
+                       HDCP_WARN("authentication failed attempts=%d\n",
+                                 hdcp->retry_cnt);
+               } else
+                       HDCP_WARN("authentication failed retrying\n");
+
+               hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+
+               if (hdcp->auth_state == 1 && timer_state == 0) {
+                       DBG("add auth timer\n");
+                       hdcp->auth_state = 0;
+                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+                       auth_timer.expires = jiffies + AUTH_TIMEOUT;
+                       add_timer(&auth_timer);
+                       timer_state = 1;
+               }
+
+               hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
+                                                        HDCP_REAUTH_DELAY);
+       } else {
+               HDCP_WARN("authentication failed HDCP disabled\n");
+               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+
+               if (timer_state == 1) {
+                       DBG("delete auth timer\n");
+                       del_timer_sync(&auth_timer);
+                       timer_state = 0;
+               }
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_start_authentication
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_start_authentication(void)
+{
+       int status = HDCP_OK;
+
+       hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+       DBG("HDCP: authentication start\n");
+       status = rk3036_hdcp_start_authentication();
+       if (status != HDCP_OK) {
+               DBG("HDCP: authentication failed\n");
+               hdcp_wq_authentication_failure();
+       } else {
+               /*hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;*/
+               hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+       }
+}
+#if 0
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_check_bksv
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_check_bksv(void)
+{
+       int status = HDCP_OK;
+
+       DBG("Check BKSV start");
+       status = rk3036_hdcp_check_bksv();
+       if (status != HDCP_OK) {
+               HDCP_WARN("HDCP: Check BKSV failed");
+               hdcp->retry_cnt = 0;
+               hdcp_wq_authentication_failure();
+       } else {
+               DBG("HDCP: Check BKSV successful");
+               hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+               /* Restore retry counter */
+               if (hdcp->retry_times == 0)
+                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+               else
+                       hdcp->retry_cnt = hdcp->retry_times;
+       }
+}
+#endif
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_sucess
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_sucess(void)
+{
+       hdcp->auth_state = 1;
+       if (timer_state == 1) {
+               DBG("delete auth timer\n");
+               timer_state = 0;
+               del_timer_sync(&auth_timer);
+       }
+/*
+       rk616_hdmi_control_output(true);
+ */
+       rk3036_set_colorbar(0);
+       HDCP_WARN("HDCP: authentication pass\n");
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_disable
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_disable(int event)
+{
+       HDCP_WARN("HDCP: disabled\n");
+
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       rk3036_hdcp_disable();
+       if (event == HDCP_DISABLE_CTL) {
+               hdcp->hdcp_state = HDCP_DISABLED;
+               if (hdcp->hdmi_state == HDMI_STARTED)
+                       rk3036_set_colorbar(0);
+       } else if (event == HDCP_STOP_FRAME_EVENT) {
+               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_work_queue
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_work_queue(struct work_struct *work)
+{
+       struct hdcp_delayed_work *hdcp_w =
+               container_of(work, struct hdcp_delayed_work, work.work);
+       int event = hdcp_w->event;
+
+       mutex_lock(&hdcp->lock);
+       DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d\n",
+           jiffies_to_msecs(jiffies),
+           hdcp->hdmi_state,
+           hdcp->hdcp_state,
+           (event & 0xFF00) >> 8,
+           event & 0xFF);
+
+       if (event == HDCP_STOP_FRAME_EVENT)
+               hdcp->hdmi_state = HDMI_STOPPED;
+       if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT)
+               hdcp_wq_disable(event);
+       if (event & HDCP_WORKQUEUE_SRC)
+               hdcp->pending_wq_event = 0;
+       /* First handle HDMI state */
+       if (event == HDCP_START_FRAME_EVENT) {
+               hdcp->pending_start = 0;
+               hdcp->hdmi_state = HDMI_STARTED;
+       }
+
+       /**********************/
+       /* HDCP state machine */
+       /**********************/
+       switch (hdcp->hdcp_state) {
+       case HDCP_DISABLED:
+               /* HDCP enable control or re-authentication event */
+               if (event == HDCP_ENABLE_CTL) {
+                       /*if (hdcp->retry_times == 0)
+                               hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+                       else
+                               hdcp->retry_cnt = hdcp->retry_times;*/
+                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+                       if (hdcp->hdmi_state == HDMI_STARTED)
+                               hdcp_wq_start_authentication();
+                       else
+                               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+               }
+               break;
+       case HDCP_ENABLE_PENDING:
+               /* HDMI start frame event */
+               if (event == HDCP_START_FRAME_EVENT)
+                       hdcp_wq_start_authentication();
+               break;
+       case HDCP_AUTHENTICATION_START:
+               /* Re-authentication */
+               if (event == HDCP_AUTH_REATT_EVENT)
+                       hdcp_wq_start_authentication();
+               break;
+#if 0
+       case HDCP_WAIT_KSV_LIST:
+               /* KSV failure */
+               if (event == HDCP_FAIL_EVENT) {
+                       HDCP_WARN("HDCP: KSV switch failure\n");
+                       hdcp_wq_authentication_failure();
+               }
+               /* KSV list ready event */
+               else if (event == HDCP_KSV_LIST_RDY_EVENT)
+                       hdcp_wq_check_bksv();
+               break;
+#endif
+       case HDCP_LINK_INTEGRITY_CHECK:
+               /* authentication failure */
+               if (event == HDCP_FAIL_EVENT) {
+                       HDCP_WARN("HDCP: Ri check failure\n");
+                       hdcp_wq_authentication_failure();
+               } else if (event == HDCP_AUTH_PASS_EVENT)
+                       hdcp_wq_authentication_sucess();
+               break;
+       default:
+               HDCP_WARN("HDCP: error - unknow HDCP state\n");
+               break;
+       }
+       kfree(hdcp_w);
+       if (event == HDCP_STOP_FRAME_EVENT)
+               complete(&hdcp->complete);
+       mutex_unlock(&hdcp->lock);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_start_frame_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_start_frame_cb(void)
+{
+       DBG("hdcp_start_frame_cb()\n");
+
+       /* Cancel any pending work */
+       if (hdcp->pending_start)
+               hdcp_cancel_work(&hdcp->pending_start);
+       if (hdcp->pending_wq_event)
+               hdcp_cancel_work(&hdcp->pending_wq_event);
+
+       if (timer_state == 0) {
+               DBG("add auth timer\n");
+               auth_timer.expires = jiffies + AUTH_TIMEOUT;
+               add_timer(&auth_timer);
+               timer_state = 1;
+       }
+
+       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+       hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
+                                                       HDCP_ENABLE_DELAY);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_irq_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_irq_cb(int status)
+{
+       char interrupt1;
+       char interrupt2;
+
+       rk3036_hdcp_interrupt(&interrupt1, &interrupt2);
+       DBG("%s 0x%02x 0x%02x\n", __func__, interrupt1, interrupt2);
+       if (interrupt1 & m_INT_HDCP_ERR) {
+               if ((hdcp->hdcp_state != HDCP_DISABLED) &&
+                   (hdcp->hdcp_state != HDCP_ENABLE_PENDING))
+                       hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+       }
+/*
+       else if (interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
+               hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
+ */
+       else if (interrupt1 & m_INT_AUTH_SUCCESS)
+               hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_on_cb
+ *-----------------------------------------------------------------------------
+ */
+static int hdcp_power_on_cb(void)
+{
+       DBG("%s", __func__);
+       return rk3036_hdcp_load_key2mem(hdcp->keys);
+       return HDCP_OK;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_off_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_power_off_cb(void)
+{
+       DBG("%s\n", __func__);
+       if (timer_state == 1) {
+               DBG("delete auth timer\n");
+               timer_state = 0;
+               del_timer_sync(&auth_timer);
+       }
+       hdcp->auth_state = 0;
+
+       if (!hdcp->enable)
+               return;
+       rk3036_hdcp_stop_authentication();
+       hdcp_cancel_work(&hdcp->pending_start);
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       init_completion(&hdcp->complete);
+       /* Post event to workqueue */
+       if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0))
+               wait_for_completion_interruptible_timeout(&hdcp->complete,
+                                                         msecs_to_jiffies(5000));
+}
+
+/*
+ * Load HDCP key to external HDCP memory
+ */
+static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
+{
+       if (!fw) {
+               pr_err("HDCP: failed to load keys\n");
+               return;
+       }
+       if (fw->size < HDCP_KEY_SIZE) {
+               pr_err("HDCP: firmware wrong size %d\n", fw->size);
+               return;
+       }
+       hdcp->keys =  kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
+       if (hdcp->keys == NULL) {
+               pr_err("HDCP: can't allocated space for keys\n");
+               return;
+       }
+       memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
+       HDCP_WARN("HDCP: load hdcp key success\n");
+
+       if (fw->size > HDCP_KEY_SIZE) {
+               DBG("%s invalid key size %d\n", __func__,
+                   fw->size - HDCP_KEY_SIZE);
+               if ((fw->size - HDCP_KEY_SIZE) % 5) {
+                       pr_err("HDCP: failed to load invalid keys\n");
+                       return;
+               }
+               hdcp->invalidkeys =
+                       kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
+               if (hdcp->invalidkeys == NULL) {
+                       pr_err("HDCP: can't allocated space for invalid keys\n");
+                       return;
+               }
+               memcpy(hdcp->invalidkeys, fw->data +
+                      HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
+               hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
+               HDCP_WARN("HDCP: loaded hdcp invalid key success\n");
+       }
+}
+
+static ssize_t hdcp_enable_read(struct device *device,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       int enable = 0;
+
+       if (hdcp)
+               enable = hdcp->enable;
+       return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t hdcp_enable_write(struct device *device,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       int enable;
+
+       if (hdcp == NULL)
+               return -EINVAL;
+       sscanf(buf, "%d", &enable);
+       if (hdcp->enable != enable) {
+               /* Post event to workqueue */
+               if (enable) {
+                       if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
+                               return -EFAULT;
+               } else {
+                       hdcp_cancel_work(&hdcp->pending_start);
+                       hdcp_cancel_work(&hdcp->pending_wq_event);
+
+                       /* Post event to workqueue */
+                       if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
+                               return -EFAULT;
+               }
+               hdcp->enable =  enable;
+       }
+       return count;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
+                        hdcp_enable_read, hdcp_enable_write);
+
+static ssize_t hdcp_trytimes_read(struct device *device,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       int trytimes = 0;
+
+       if (hdcp)
+               trytimes = hdcp->retry_times;
+       return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
+}
+
+static ssize_t hdcp_trytimes_wrtie(struct device *device,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       int trytimes;
+
+       if (hdcp == NULL)
+               return -EINVAL;
+       sscanf(buf, "%d", &trytimes);
+       if (hdcp->retry_times != trytimes)
+               hdcp->retry_times = trytimes;
+       return count;
+}
+
+
+static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR,
+                        hdcp_trytimes_read, hdcp_trytimes_wrtie);
+static struct miscdevice mdev;
+
+static int __init rk3036_hdcp_init(void)
+{
+       int ret;
+
+       DBG("[%s] %u\n", __func__, jiffies_to_msecs(jiffies));
+       hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
+       if (!hdcp) {
+               HDCP_WARN(">>HDCP: kmalloc fail!\n");
+               ret = -ENOMEM;
+               goto error0;
+       }
+       memset(hdcp, 0, sizeof(struct hdcp));
+       mutex_init(&hdcp->lock);
+       mdev.minor = MISC_DYNAMIC_MINOR;
+       mdev.name = "hdcp";
+       mdev.mode = 0666;
+       if (misc_register(&mdev)) {
+               HDCP_WARN("HDCP: Could not add character driver\n");
+               ret = HDMI_ERROR_FALSE;
+               goto error1;
+       }
+       ret = device_create_file(mdev.this_device, &dev_attr_enable);
+       if (ret) {
+               HDCP_WARN("HDCP: Could not add sys file enable\n");
+               ret = -EINVAL;
+               goto error2;
+       }
+       ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
+       if (ret) {
+               HDCP_WARN("HDCP: Could not add sys file trytimes\n");
+               ret = -EINVAL;
+                       goto error3;
+       }
+       hdcp->workqueue = create_singlethread_workqueue("hdcp");
+       if (hdcp->workqueue == NULL) {
+               HDCP_WARN("HDCP,: create workqueue failed.\n");
+               goto error4;
+       }
+       ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+                                     "hdcp.keys", mdev.this_device,
+                                     GFP_KERNEL, hdcp,
+                                     hdcp_load_keys_cb);
+       if (ret < 0) {
+               HDCP_WARN("HDCP: request_firmware_nowait failed: %d\n", ret);
+               goto error5;
+       }
+
+       rk3036_hdmi_register_hdcp_callbacks(hdcp_start_frame_cb,
+                                           hdcp_irq_cb,
+                                           hdcp_power_on_cb,
+                                           hdcp_power_off_cb);
+
+       init_timer(&auth_timer);
+       auth_timer.data = 0;
+       auth_timer.function = auth_timer_func;
+       DBG("%s success %u\n", __func__, jiffies_to_msecs(jiffies));
+       return 0;
+error5:
+       destroy_workqueue(hdcp->workqueue);
+error4:
+       device_remove_file(mdev.this_device, &dev_attr_trytimes);
+error3:
+       device_remove_file(mdev.this_device, &dev_attr_enable);
+error2:
+       misc_deregister(&mdev);
+error1:
+       kfree(hdcp->keys);
+       kfree(hdcp->invalidkeys);
+       kfree(hdcp);
+error0:
+       return ret;
+}
+
+static void __exit rk3036_hdcp_exit(void)
+{
+       device_remove_file(mdev.this_device, &dev_attr_enable);
+       misc_deregister(&mdev);
+       kfree(hdcp->keys);
+       kfree(hdcp->invalidkeys);
+       kfree(hdcp);
+}
+
+/* module_init(rk3036_hdcp_init); */
+late_initcall_sync(rk3036_hdcp_init);
+module_exit(rk3036_hdcp_exit);
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdcp.h b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdcp.h
new file mode 100755 (executable)
index 0000000..57c3126
--- /dev/null
@@ -0,0 +1,202 @@
+#ifndef __RK3036_HDCP_H__
+#define __RK3036_HDCP_H__
+
+/***************************/
+/* Definitions             */
+/***************************/
+
+/* Status / error codes */
+#define HDCP_OK                        0
+#define HDCP_KEY_ERR   1
+#define HDCP_KSV_ERR   2
+#define HDCP_KEY_VALID         3
+#define HDCP_KEY_INVALID       4
+
+/* Delays */
+#define HDCP_ENABLE_DELAY      300
+#define HDCP_REAUTH_DELAY      100
+
+/* Event source */
+#define HDCP_SRC_SHIFT         8
+#define HDCP_IOCTL_SRC         (0x1 << HDCP_SRC_SHIFT)
+#define HDCP_HDMI_SRC          (0x2 << HDCP_SRC_SHIFT)
+#define HDCP_IRQ_SRC           (0x4 << HDCP_SRC_SHIFT)
+#define HDCP_WORKQUEUE_SRC     (0x8 << HDCP_SRC_SHIFT)
+
+/* Event */
+#define HDCP_ENABLE_CTL                        (HDCP_IOCTL_SRC         | 0)
+#define HDCP_DISABLE_CTL               (HDCP_IOCTL_SRC         | 1)
+#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC          | 2)
+#define HDCP_STOP_FRAME_EVENT  (HDCP_HDMI_SRC          | 3)
+#define HDCP_KSV_LIST_RDY_EVENT        (HDCP_IRQ_SRC           | 4)
+#define HDCP_FAIL_EVENT                        (HDCP_IRQ_SRC           | 5)
+#define HDCP_AUTH_PASS_EVENT   (HDCP_IRQ_SRC           | 6)
+#define HDCP_AUTH_REATT_EVENT  (HDCP_WORKQUEUE_SRC     | 7)
+
+/* Key size */
+#define HDCP_KEY_SIZE                  308
+
+/* HDCP DDC Clock */
+#define HDCP_DDC_CLK                   100000
+
+/* Authentication retry times */
+#define HDCP_INFINITE_REAUTH   0x100
+
+/* HDCP Regs */
+#define HDCP_CTRL1                             0x52
+       #define m_AUTH_START            (1 << 7)
+       #define m_BKSV_VALID            (1 << 6)
+       #define m_BKSV_INVALID          (1 << 5)
+       #define m_ENCRYPT_ENABLE        (1 << 4)
+       #define m_AUTH_STOP                     (1 << 3)
+       #define m_ADVANED_ENABLE        (1 << 2)
+       #define m_HDMI_DVI                      (1 << 1)
+       #define m_HDCP_RESET            (1 << 0)
+
+       #define v_AUTH_START(n)         (n << 7)
+       #define v_BKSV_VALID(n)         (n << 6)
+       #define v_BKSV_INVALID(n)       (n << 5)
+       #define v_ENCRYPT_ENABLE(n)     (n << 4)
+       #define v_AUTH_STOP(n)          (n << 3)
+       #define v_ADVANED_ENABLE(n)     (n << 2)
+       #define v_HDMI_DVI(n)           (n << 1)
+       #define v_HDCP_RESET(n)         (n << 0)
+
+#define HDCP_CTRL2                             0x53
+       #define m_DISABLE_127_CHECK                             (1 << 7)
+       #define m_SKIP_BKSV_CHECK                               (1 << 6)
+       #define m_ENABLE_PJ_CHECK                               (1 << 5)
+       #define m_DISABLE_DEVICE_NUMBER_CHECK   (1 << 4)
+       #define m_DELAY_RI_1_CLK                                (1 << 3)
+       #define m_USE_PRESET_AN                                 (1 << 2)
+       #define m_KEY_COMBINATION                               (3 << 0)
+
+       #define v_DISABLE_127_CHECK(n)                  (n << 7)
+       #define v_SKIP_BKSV_CHECK(n)                    (n << 6)
+       #define v_ENABLE_PJ_CHECK(n)                    (n << 5)
+       #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
+       #define v_DELAY_RI_1_CLK(n)                             (n << 3)
+       #define v_USE_PRESET_AN(n)                              (n << 2)
+       #define v_KEY_COMBINATION(n)                    (n << 0)
+
+#define HDCP_KEY_STATUS                        0x54
+       #define m_KEY_READY                     (1 << 0)
+
+#define HDCP_CTRL_SOFT                 0x57
+       #define m_DISABLE_127_CHECK                             (1 << 7)
+       #define m_SKIP_BKSV_CHECK                               (1 << 6)
+       #define m_NOT_AUTHENTICATED                             (1 << 5)
+       #define m_ENCRYPTED                                             (1 << 4)
+       #define m_ADVANCED_CIPHER                               (1 << 3)
+
+#define HDCP_BCAPS_RX                  0x58
+#define HDCP_TIMER_100MS               0x63
+#define HDCP_TIMER_5S                  0x64
+#define HDCP_ERROR                             0x65
+       #define m_DDC_NO_ACK            (1 << 3)
+       #define m_PJ_MISMACH            (1 << 2)
+       #define m_RI_MISMACH            (1 << 1)
+       #define m_BKSV_WRONG            (1 << 0)
+
+#define HDCP_KSV_BYTE0                 0x66
+#define HDCP_KSV_BYTE1                 0x67
+#define HDCP_KSV_BYTE2                 0x68
+#define HDCP_KSV_BYTE3                 0x69
+#define HDCP_KSV_BYTE4                 0x6a
+
+#define HDCP_AN_SEED                   0x6c
+
+#define HDCP_BCAPS_TX                  0x80
+#define HDCP_BSTATE_0                  0x81
+#define HDCP_BSTATE_1                  0x82
+
+#define HDCP_KEY_FIFO                  0x98
+
+#define HDCP_INT_MASK1                 0xc2
+#define HDCP_INT_STATUS1               0xc3
+       #define m_INT_HDCP_ERR          (1 << 7)
+       #define m_INT_BKSV_READY        (1 << 6)
+       #define m_INT_BKSV_UPDATE       (1 << 5)
+       #define m_INT_AUTH_SUCCESS      (1 << 4)
+       #define m_INT_AUTH_READY        (1 << 3)
+
+#define HDCP_INT_MASK2                 0xc4
+#define HDCP_INT_STATUS2               0xc5
+       #define m_INT_SOFT_MODE_READY                   (1 << 7)
+       #define m_INT_AUTH_M0_REDAY                             (1 << 6)
+       #define m_INT_1st_FRAME_ARRIVE                  (1 << 5)
+       #define m_INT_AN_READY                                  (1 << 4)
+       #define m_INT_ENCRYPTED                                 (1 << 2)
+       #define m_INT_NOT_ENCRYPTED_AVMUTE              (1 << 1)
+       #define m_INT_NOT_ENCRYPTED_AVUNMUTE    (1 << 0)
+
+enum hdcp_states {
+       HDCP_DISABLED,
+       HDCP_ENABLE_PENDING,
+       HDCP_AUTHENTICATION_START,
+       HDCP_WAIT_KSV_LIST,
+       HDCP_LINK_INTEGRITY_CHECK,
+};
+
+enum hdmi_states {
+       HDMI_STOPPED,
+       HDMI_STARTED
+};
+
+#define HDCP_PRIVATE_KEY_SIZE  280
+#define HDCP_KEY_SHA_SIZE              20
+
+struct hdcp_keys {
+       u8 ksv[8];
+       u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
+       u8 sha1[HDCP_KEY_SHA_SIZE];
+};
+
+struct hdcp_delayed_work {
+       struct delayed_work work;
+       int event;
+};
+
+struct hdcp {
+       int     enable;
+       int retry_times;
+       struct hdcp_keys *keys;
+       int invalidkey;
+       char *invalidkeys;
+       struct mutex lock;
+       struct completion       complete;
+       struct workqueue_struct *workqueue;
+
+       enum hdmi_states hdmi_state;
+       enum hdcp_states hdcp_state;
+
+       struct delayed_work *pending_start;
+       struct delayed_work *pending_wq_event;
+       int retry_cnt;
+       int auth_state;
+};
+
+extern struct hdcp *hdcp;
+
+#ifdef HDCP_DEBUG
+#define DBG(format, ...) \
+               printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+#if 1
+#define HDCP_WARN(x...) printk(KERN_INFO x)
+#else
+#define I2S_DBG(x...) do { } while (0)
+#endif
+
+extern void rk3036_hdcp_disable(void);
+extern int     rk3036_hdcp_start_authentication(void);
+extern int     rk3036_hdcp_check_bksv(void);
+extern int     rk3036_hdcp_load_key2mem(struct hdcp_keys *key);
+extern void rk3036_hdcp_interrupt(char *status1, char *status2);
+extern void rk3036_set_colorbar(int enable);
+extern int rk3036_hdcp_stop_authentication(void);
+extern int is_1b_03_test(void);
+#endif /* __rk3036_HDCP_H__ */
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.c b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.c
new file mode 100755 (executable)
index 0000000..6067eec
--- /dev/null
@@ -0,0 +1,503 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+
+#include <linux/of_gpio.h>
+#include <linux/rk_fb.h>
+
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#endif
+
+#include "rk3036_hdmi.h"
+#include "rk3036_hdmi_hw.h"
+
+struct rk_hdmi_device *hdmi_dev;
+
+#if defined(CONFIG_DEBUG_FS)
+static int rk3036_hdmi_reg_show(struct seq_file *s, void *v)
+{
+       int i = 0;
+       u32 val = 0;
+
+       seq_puts(s, "\n\n>>>rk3036_ctl reg");
+       for (i = 0; i < 16; i++)
+               seq_printf(s, " %2x", i);
+
+       seq_puts(s,
+                  "\n-----------------------------------------------------------------");
+
+       for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
+               hdmi_readl(hdmi_dev, i, &val);
+               if (i % 16 == 0)
+                       seq_printf(s, "\n>>>rk3036_ctl %2x:", i);
+               seq_printf(s, " %02x", val);
+
+       }
+       seq_puts(s,
+                  "\n-----------------------------------------------------------------\n");
+
+       return 0;
+}
+
+static ssize_t rk3036_hdmi_reg_write(struct file *file, const char __user *buf,
+                                   size_t count, loff_t *ppos)
+{
+       u32 reg;
+       u32 val;
+       char kbuf[25];
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+
+       if (copy_from_user(kbuf, buf, count))
+               return -EFAULT;
+       sscanf(kbuf, "%x%x", &reg, &val);
+       if ((reg < 0) || (reg > 0xed)) {
+               dev_info(hdmi_drv->dev, "it is no hdmi reg\n");
+               return count;
+       }
+       dev_info(hdmi_drv->dev, "/**********rk3036 reg config******/");
+       dev_info(hdmi_drv->dev, "\n reg=%x val=%x\n", reg, val);
+       hdmi_writel(hdmi_dev, reg, val);
+
+       return count;
+}
+
+static int rk3036_hdmi_reg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rk3036_hdmi_reg_show, NULL);
+}
+
+static const struct file_operations rk3036_hdmi_reg_fops = {
+       .owner = THIS_MODULE,
+       .open = rk3036_hdmi_reg_open,
+       .read = seq_read,
+       .write = rk3036_hdmi_reg_write,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+#endif
+
+static int rk3036_hdmi_clk_enable(struct rk_hdmi_device *hdmi_dev)
+{
+       if (!hdmi_dev->clk_on) {
+               clk_prepare_enable(hdmi_dev->hclk);
+               spin_lock(&hdmi_dev->reg_lock);
+               hdmi_dev->clk_on = 1;
+               spin_unlock(&hdmi_dev->reg_lock);
+       }
+
+       return 0;
+}
+
+static int rk3036_hdmi_clk_disable(struct rk_hdmi_device *hdmi_dev)
+{
+       if (!hdmi_dev->clk_on) {
+               spin_lock(&hdmi_dev->reg_lock);
+               hdmi_dev->clk_on = 0;
+               spin_unlock(&hdmi_dev->reg_lock);
+               clk_disable_unprepare(hdmi_dev->hclk);
+       }
+
+       return 0;
+}
+
+int rk3036_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
+                                      void (*hdcp_irq_cb)(int status),
+                                      int (*hdcp_power_on_cb)(void),
+                                      void (*hdcp_power_off_cb)(void))
+{
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+
+       if (hdmi_drv == NULL)
+               return HDMI_ERROR_FALSE;
+
+       hdmi_drv->hdcp_cb = hdcp_cb;
+       hdmi_drv->hdcp_irq_cb = hdcp_irq_cb;
+       hdmi_drv->hdcp_power_on_cb = hdcp_power_on_cb;
+       hdmi_drv->hdcp_power_off_cb = hdcp_power_off_cb;
+
+       return HDMI_ERROR_SUCESS;
+}
+
+int rk3036_hdmi_register_cec_callbacks(void (*cec_irq)(void),
+                                              void (*cec_set_device_pa)(int addr),
+                                              int (*cec_enumerate)(void))
+{
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+
+       if (hdmi_drv == NULL)
+               return HDMI_ERROR_FALSE;
+
+       hdmi_drv->cec_irq = cec_irq;
+       hdmi_drv->cec_set_device_pa = cec_set_device_pa;
+       hdmi_drv->cec_enumerate = cec_enumerate;
+
+       return HDMI_ERROR_SUCESS;
+}
+
+static void rk3036_hdmi_early_suspend(void)
+{
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+
+       hdmi_dbg(hdmi_drv->dev, "hdmi enter early suspend pwr %d state %d\n",
+                hdmi_drv->pwr_mode, hdmi_drv->state);
+
+       flush_delayed_work(&hdmi_drv->delay_work);
+       mutex_lock(&hdmi_drv->enable_mutex);
+       if (!hdmi_drv->suspend) {
+               hdmi_drv->suspend = 1;
+               if (!hdmi_drv->enable) {
+                       mutex_unlock(&hdmi_drv->enable_mutex);
+                       return;
+               }
+       
+               if (hdmi_drv->irq)
+                       disable_irq(hdmi_drv->irq);
+       
+               mutex_unlock(&hdmi_drv->enable_mutex);
+               hdmi_drv->command = HDMI_CONFIG_ENABLE;
+               init_completion(&hdmi_drv->complete);
+               hdmi_drv->wait = 1;
+               queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, 0);
+               wait_for_completion_interruptible_timeout(&hdmi_drv->complete,
+                                                         msecs_to_jiffies(5000));
+               flush_delayed_work(&hdmi_drv->delay_work);
+       }
+}
+
+static void rk3036_hdmi_early_resume(void)
+{
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+
+       hdmi_dbg(hdmi_drv->dev, "hdmi exit early resume\n");
+
+       mutex_lock(&hdmi_drv->enable_mutex);
+       if (hdmi_drv->suspend) {
+               hdmi_drv->suspend = 0;
+               rk3036_hdmi_initial(hdmi_drv);
+               if (hdmi_drv->enable && hdmi_drv->irq) {
+                       enable_irq(hdmi_drv->irq);
+                       rk3036_hdmi_irq(hdmi_drv);
+               }
+       
+               queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
+                                  msecs_to_jiffies(10));
+       }
+       mutex_unlock(&hdmi_drv->enable_mutex);
+}
+
+static int rk3036_hdmi_fb_event_notify(struct notifier_block *self,
+                                     unsigned long action, void *data)
+{
+       struct fb_event *event = data;
+       int blank_mode = *((int *)event->data);
+
+       if (action == FB_EARLY_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       break;
+               default:
+                       rk3036_hdmi_early_suspend();
+                       break;
+               }
+       } else if (action == FB_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       rk3036_hdmi_early_resume();
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block rk3036_hdmi_fb_notifier = {
+       .notifier_call = rk3036_hdmi_fb_event_notify,
+};
+
+
+static void rk3036_delay_work_func(struct work_struct *work)
+{
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+
+       if (hdmi_drv->suspend == 0) {
+               if (hdmi_drv->enable == 1)
+                       rk3036_hdmi_irq(hdmi_drv);
+               if (hdmi_drv->irq == 0)
+                       queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->rk3036_delay_work,
+                               msecs_to_jiffies(100));                 
+       }
+}
+
+static irqreturn_t rk3036_hdmi_irq_func(int irq, void *dev_id)
+{
+       struct hdmi *hdmi_drv = &hdmi_dev->driver;
+       if ((hdmi_drv->suspend == 0) && (hdmi_drv->enable == 1)) {
+               hdmi_dbg(hdmi_drv->dev,
+                        "line = %d, rk3036_hdmi_irq_func irq triggered.\n",
+                        __LINE__);
+               rk3036_hdmi_irq(hdmi_drv);
+       }
+       
+       return IRQ_HANDLED;
+}
+
+static int rk3036_hdmi_drv_init(struct hdmi *hdmi_drv)
+{
+       int ret = 0;
+       int lcdc_id = 0;
+       struct rk_screen screen;
+
+       rk_fb_get_prmry_screen(&screen);
+
+       /* hdmi is extend as default,TODO modify if hdmi is primary */
+       /*lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;*/
+       lcdc_id = screen.lcdc_id;//for box,hdmi is primary
+       
+       if (lcdc_id == 0)
+               hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
+       else
+               hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
+
+       if (IS_ERR(hdmi_drv->lcdc)) {
+               dev_err(hdmi_drv->dev,
+                       "can not connect to video source lcdc\n");
+               ret = -ENXIO;
+               return ret;
+       }
+
+       hdmi_drv->xscale = 100;
+       hdmi_drv->yscale = 100;
+
+       /*spin_lock_init(&hdmi_drv->irq_lock);*/
+       mutex_init(&hdmi_drv->enable_mutex);
+       hdmi_sys_init(hdmi_drv);
+       ret = rk3036_hdmi_initial(hdmi_drv);
+
+       hdmi_drv_register(hdmi_drv);
+       return ret;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk3036_hdmi_of_match[] = {
+       {.compatible = "rockchip,rk3036-hdmi",},
+       {.compatible = "rockchip,rk312x-hdmi",},
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rk3036_hdmi_of_match);
+#endif
+
+static int rk3036_hdmi_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct hdmi *hdmi_drv;
+       struct resource *res;
+
+       hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct rk_hdmi_device),
+                               GFP_KERNEL);
+       if (!hdmi_dev) {
+               dev_err(&pdev->dev, ">>rk3036_hdmi kmalloc fail!");
+               return -ENOMEM;
+       }
+
+       hdmi_drv = &hdmi_dev->driver;
+       hdmi_drv->dev = &pdev->dev;
+       platform_set_drvdata(pdev, hdmi_dev);
+       spin_lock_init(&hdmi_dev->reg_lock);
+
+#ifdef CONFIG_SWITCH
+       hdmi_drv->switch_hdmi.name = "hdmi";
+       switch_dev_register(&(hdmi_drv->switch_hdmi));
+#endif
+       hdmi_register_display_sysfs(hdmi_drv, NULL);
+       fb_register_client(&rk3036_hdmi_fb_notifier);
+
+       hdmi_drv->workqueue = create_singlethread_workqueue("hdmi");
+       INIT_DELAYED_WORK(&(hdmi_drv->delay_work), hdmi_work);
+       INIT_DELAYED_WORK(&hdmi_dev->rk3036_delay_work, rk3036_delay_work_func);
+
+       /* enable clk */
+       hdmi_dev->hclk = devm_clk_get(hdmi_drv->dev, "pclk_hdmi");
+       if (IS_ERR(hdmi_dev->hclk)) {
+               dev_err(hdmi_drv->dev, "Unable to get hdmi hclk\n");
+               ret = -ENXIO;
+               goto err1;
+       }
+       rk3036_hdmi_clk_enable(hdmi_dev);       /* enable clk may move to irq func */
+       hdmi_dev->hclk_rate = clk_get_rate(hdmi_dev->hclk);
+       /* request and remap iomem */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(hdmi_drv->dev, "Unable to get register resource\n");
+               ret = -ENXIO;
+               goto err2;
+       }
+       hdmi_dev->regbase_phy = res->start;
+       hdmi_dev->regsize_phy = resource_size(res);
+       hdmi_dev->regbase = devm_ioremap_resource(hdmi_drv->dev, res);
+       if (IS_ERR(hdmi_dev->regbase)) {
+               ret = PTR_ERR(hdmi_dev->regbase);
+               dev_err(hdmi_drv->dev, "cannot ioremap registers,err=%d\n",
+                       ret);
+               goto err2;
+       }
+       if (rk3036_hdmi_drv_init(hdmi_drv))
+               goto err0;
+
+       /* get the IRQ */
+       hdmi_drv->irq = platform_get_irq(pdev, 0);
+       if (hdmi_drv->irq <= 0) {
+               dev_err(hdmi_drv->dev, "failed to get hdmi irq resource (%d).\n",
+                       hdmi_drv->irq);
+               hdmi_drv->irq = 0;
+       } else {
+               /* request the IRQ */
+               ret = devm_request_irq(hdmi_drv->dev, hdmi_drv->irq,
+                                      rk3036_hdmi_irq_func, 0,
+                                      dev_name(hdmi_drv->dev), hdmi_drv);
+               if (ret) {
+                       dev_err(hdmi_drv->dev, "hdmi request_irq failed (%d)\n",
+                               ret);
+                       goto err2;
+               }
+       }
+
+#if defined(CONFIG_DEBUG_FS)
+       hdmi_dev->debugfs_dir = debugfs_create_dir("rk3036", NULL);
+       if (IS_ERR(hdmi_dev->debugfs_dir)) {
+               dev_err(hdmi_drv->dev,
+                       "failed to create debugfs dir for rk3036!\n");
+       } else {
+               debugfs_create_file("hdmi", S_IRUSR,
+                                   hdmi_dev->debugfs_dir, hdmi_drv,
+                                   &rk3036_hdmi_reg_fops);
+       }
+       
+#endif
+
+       queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->rk3036_delay_work,
+                          msecs_to_jiffies(0));
+       dev_info(hdmi_drv->dev, "rk3036 hdmi probe success.\n");
+
+       return 0;
+
+err2:
+       rk3036_hdmi_clk_disable(hdmi_dev);
+err1:
+       fb_unregister_client(&rk3036_hdmi_fb_notifier);
+       hdmi_unregister_display_sysfs(hdmi_drv);
+#ifdef CONFIG_SWITCH
+       switch_dev_unregister(&(hdmi_drv->switch_hdmi));
+#endif
+
+err0:
+       hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi probe error.\n");
+       kfree(hdmi_dev);
+       hdmi_dev = NULL;
+       return ret;
+}
+
+static int rk3036_hdmi_remove(struct platform_device *pdev)
+{
+       struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
+       struct hdmi *hdmi_drv = NULL;
+
+       if (hdmi_dev) {
+               hdmi_drv = &hdmi_dev->driver;
+               mutex_lock(&hdmi_drv->enable_mutex);
+               if (!hdmi_drv->suspend && hdmi_drv->enable && hdmi_drv->irq)
+                       disable_irq(hdmi_drv->irq);
+               mutex_unlock(&hdmi_drv->enable_mutex);
+               if (hdmi_drv->irq)
+                       free_irq(hdmi_drv->irq, NULL);
+
+               flush_workqueue(hdmi_drv->workqueue);
+               destroy_workqueue(hdmi_drv->workqueue);
+#ifdef CONFIG_SWITCH
+               switch_dev_unregister(&(hdmi_drv->switch_hdmi));
+#endif
+               hdmi_unregister_display_sysfs(hdmi_drv);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+               unregister_early_suspend(&hdmi_drv->early_suspend);
+#endif
+               fb_destroy_modelist(&hdmi_drv->edid.modelist);
+               if (hdmi_drv->edid.audio)
+                       kfree(hdmi_drv->edid.audio);
+               if (hdmi_drv->edid.specs) {
+                       if (hdmi_drv->edid.specs->modedb)
+                               kfree(hdmi_drv->edid.specs->modedb);
+                       kfree(hdmi_drv->edid.specs);
+               }
+
+               hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi removed.\n");
+               kfree(hdmi_dev);
+               hdmi_dev = NULL;
+       }
+
+       return 0;
+}
+
+static void rk3036_hdmi_shutdown(struct platform_device *pdev)
+{
+       struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
+       struct hdmi *hdmi_drv = NULL;
+
+       if (hdmi_dev) {
+               hdmi_drv = &hdmi_dev->driver;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+               unregister_early_suspend(&hdmi_drv->early_suspend);
+#endif
+               flush_delayed_work(&hdmi_drv->delay_work);
+               mutex_lock(&hdmi_drv->enable_mutex);
+               hdmi_drv->suspend = 1;
+               if (!hdmi_drv->enable) {
+                       mutex_unlock(&hdmi_drv->enable_mutex);
+                       return;
+               }
+               if (hdmi_drv->irq)
+                       disable_irq(hdmi_drv->irq);
+               mutex_unlock(&hdmi_drv->enable_mutex);
+       }
+       hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi shut down.\n");
+}
+
+
+static struct platform_driver rk3036_hdmi_driver = {
+       .probe = rk3036_hdmi_probe,
+       .remove = rk3036_hdmi_remove,
+       .driver = {
+                  .name = "rk3036-hdmi",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(rk3036_hdmi_of_match),                   
+                  },
+       .shutdown = rk3036_hdmi_shutdown,
+};
+
+static int __init rk3036_hdmi_init(void)
+{
+       return platform_driver_register(&rk3036_hdmi_driver);
+}
+
+static void __exit rk3036_hdmi_exit(void)
+{
+       platform_driver_unregister(&rk3036_hdmi_driver);
+}
+
+device_initcall_sync(rk3036_hdmi_init);
+module_exit(rk3036_hdmi_exit);
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.h
new file mode 100755 (executable)
index 0000000..9c1d673
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __RK3036_HDMI_H__
+#define __RK3036_HDMI_H__
+
+#include "../../rk_hdmi.h"
+
+enum {
+       INPUT_IIS,
+       INPUT_SPDIF
+};
+
+#if defined(CONFIG_SND_RK_SOC_HDMI_SPDIF)
+#define HDMI_CODEC_SOURCE_SELECT INPUT_SPDIF
+#else
+#define HDMI_CODEC_SOURCE_SELECT INPUT_IIS
+#endif
+
+extern void rk3036_hdmi_control_output(struct hdmi *hdmi, int enable);
+extern int rk3036_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
+                                             void (*hdcp_irq_cb)(int status),
+                                             int (*hdcp_power_on_cb)(void),
+                                             void (*hdcp_power_off_cb)(void));
+extern int rk3036_hdmi_register_cec_callbacks(void (*cec_irq)(void),
+                                                     void (*cec_set_device_pa)(int addr),
+                                                     int (*cec_enumerate)(void));
+
+
+extern struct rk_hdmi_device *hdmi_dev;
+
+struct rk_hdmi_device {
+       int clk_on;
+       spinlock_t reg_lock;
+       struct hdmi driver;
+       void __iomem *regbase;
+       int regbase_phy;
+       int regsize_phy;
+       struct clk *pd;
+       struct clk *hclk;       /* HDMI AHP clk */
+       struct delayed_work rk3036_delay_work;
+       struct work_struct rk3036_irq_work_struct;
+       struct dentry *debugfs_dir;
+       unsigned int hclk_rate;
+};
+
+#endif /* __RK3036_HDMI_H__ */
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_cec.c b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_cec.c
new file mode 100755 (executable)
index 0000000..89337e6
--- /dev/null
@@ -0,0 +1,459 @@
+#include "rk3036_hdmi.h"
+#include "rk3036_hdmi_hw.h"
+#include "rk3036_hdmi_cec.h"
+
+static cec_t cec;
+static char la_player[3] = {CEC_LOGADDR_PLAYBACK1,
+                           CEC_LOGADDR_PLAYBACK2,
+                           CEC_LOGADDR_PLAYBACK3};
+
+static int cec_read_frame(cec_framedata_t *frame)
+{
+       int i, length,val;
+       char *data = (char *)frame;//modify by hjc
+       if(frame == NULL)
+               return -1;
+       
+       hdmi_readl(hdmi_dev, CEC_RX_LENGTH, &length);
+       hdmi_writel(hdmi_dev, CEC_RX_OFFSET, 0);
+       
+       printk("CEC: %s length is %d\n", __FUNCTION__, length);
+       for(i = 0; i < length; i++) {
+               hdmi_readl(hdmi_dev, CEC_DATA, &val);
+               data[i] = val;
+               printk("%02x\n", data[i]);
+       }
+       return 0;
+}
+
+static int cec_send_frame(cec_framedata_t *frame)
+{
+       int i;
+       
+       CECDBG("CEC: TX srcdestaddr %02x opcode %02x ",
+                frame->srcdestaddr, frame->opcode);
+       if(frame->argcount) {
+               CECDBG("args:");
+               for(i = 0; i < frame->argcount; i++) {
+                       CECDBG("%02x ", frame->args[i]);
+               }
+       }
+       CECDBG("\n");
+
+       hdmi_writel(hdmi_dev, CEC_TX_OFFSET, 0);
+       hdmi_writel(hdmi_dev, CEC_DATA, frame->srcdestaddr);
+       hdmi_writel(hdmi_dev, CEC_DATA, frame->opcode);
+
+       for(i = 0; i < frame->argcount; i++)
+               hdmi_writel(hdmi_dev, CEC_DATA, frame->args[i]);
+
+       hdmi_writel(hdmi_dev, CEC_TX_LENGTH, frame->argcount + 2);
+       
+       /*Wait for bus free*/
+       cec.busfree = 1;
+       hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE);
+       CECDBG("start wait bus free\n");
+       if(wait_event_interruptible_timeout(cec.wait, cec.busfree == 0, msecs_to_jiffies(17))) {
+               return -1;
+       }
+       CECDBG("end wait bus free,start tx,busfree=%d\n",cec.busfree);
+       /*Start TX*/
+       cec.tx_done = 0;
+       hdmi_writel(hdmi_dev, CEC_CTRL, m_BUSFREETIME_ENABLE|m_START_TX);
+       if(wait_event_interruptible_timeout(cec.wait, cec.tx_done != 0, msecs_to_jiffies(100)))
+               hdmi_writel(hdmi_dev, CEC_CTRL, 0);
+       CECDBG("end tx,tx_done=%d\n",cec.tx_done);
+       if (cec.tx_done == 1) {
+               cec.tx_done = 0;//hjc add ,need?
+               return 0;
+       } else
+               return -1;
+}
+
+static int cec_send_message(char opcode, char dest)
+{
+       cec_framedata_t cecframe;
+       CECDBG("CEC: cec_send_message\n");
+
+       cecframe.opcode = opcode;
+       cecframe.srcdestaddr = MAKE_SRCDEST(cec.address_logic, dest);
+       cecframe.argcount = 0;
+       return cec_send_frame(&cecframe);
+}
+
+static void cec_send_feature_abort ( cec_framedata_t *pcpi, char reason )
+{
+    cec_framedata_t cecFrame;
+    CECDBG("CEC: cec_send_feature_abort\n");
+
+    if (( pcpi->srcdestaddr & 0x0F) != CEC_LOGADDR_UNREGORBC )
+    {
+        cecFrame.opcode        = CECOP_FEATURE_ABORT;
+        cecFrame.srcdestaddr   = MAKE_SRCDEST( cec.address_logic, (pcpi->srcdestaddr & 0xF0) >> 4 );
+        cecFrame.args[0]       = pcpi->opcode;
+        cecFrame.args[1]       = reason;
+        cecFrame.argcount      = 2;
+        cec_send_frame( &cecFrame );
+    }
+}
+
+static void cec_send_active_source(void)
+{
+       cec_framedata_t    cecframe;
+       
+       CECDBG("CEC: start_active_source\n");
+       cecframe.opcode        = CECOP_ACTIVE_SOURCE;
+       cecframe.srcdestaddr   = MAKE_SRCDEST( cec.address_logic, CEC_LOGADDR_UNREGORBC);
+       cecframe.args[0]       = (cec.address_phy & 0xFF00) >> 8;        /* [Physical Address]*/
+       cecframe.args[1]       = (cec.address_phy & 0x00FF);             /* [Physical Address]*/
+       cecframe.argcount      = 2;
+       cec_send_frame( &cecframe );
+}
+
+static void start_active_source(void)
+{
+       int i;
+       CECDBG("CEC: start_active_source\n");
+       /* GPIO simulate CEC timing may be not correct, so we try more times.*/
+       /*send image view on first*/
+       for(i = 0; i < 1; i++) {
+               if(cec_send_message(CECOP_IMAGE_VIEW_ON,CEC_LOGADDR_TV) == 0) {
+                       cec_send_active_source();
+               }
+       }
+}
+
+static void cec_handle_inactive_source ( cec_framedata_t *pcpi )
+{
+       
+}
+
+static void cec_handle_feature_abort( cec_framedata_t *pcpi )
+{
+   
+}
+
+static bool validate_cec_message(cec_framedata_t *pcpi)
+{
+       char parametercount = 0;
+       bool countok = true;
+       CECDBG("CEC: validate_cec_message,opcode=%d\n",pcpi->opcode);
+
+       /* Determine required parameter count   */
+       switch (pcpi->opcode)
+       {
+       case CECOP_IMAGE_VIEW_ON:
+       case CECOP_TEXT_VIEW_ON:
+       case CECOP_STANDBY:
+       case CECOP_GIVE_PHYSICAL_ADDRESS:
+       case CECOP_GIVE_DEVICE_POWER_STATUS:
+       case CECOP_GET_MENU_LANGUAGE:
+       case CECOP_GET_CEC_VERSION:
+               parametercount = 0;
+               break;
+       case CECOP_REPORT_POWER_STATUS:         // power status*/
+       case CECOP_CEC_VERSION:                 // cec version*/
+               parametercount = 1;
+               break;
+       case CECOP_INACTIVE_SOURCE:             // physical address*/
+       case CECOP_FEATURE_ABORT:               // feature opcode / abort reason*/
+       case CECOP_ACTIVE_SOURCE:               // physical address*/
+               parametercount = 2;
+               break;
+       case CECOP_REPORT_PHYSICAL_ADDRESS:     // physical address / device type*/
+       case CECOP_DEVICE_VENDOR_ID:            // vendor id*/
+               parametercount = 3;
+               break;
+       case CECOP_SET_OSD_NAME:                // osd name (1-14 bytes)*/
+       case CECOP_SET_OSD_STRING:              // 1 + x   display control / osd string (1-13 bytes)*/
+               parametercount = 1;                 // must have a minimum of 1 operands*/
+               break;
+       case CECOP_ABORT:
+               break;
+       case CECOP_ARC_INITIATE:
+               break;
+       case CECOP_ARC_REPORT_INITIATED:
+               break;
+       case CECOP_ARC_REPORT_TERMINATED:
+               break;
+
+       case CECOP_ARC_REQUEST_INITIATION:
+               break;
+       case CECOP_ARC_REQUEST_TERMINATION:
+               break;
+       case CECOP_ARC_TERMINATE:
+               break;
+       default:
+               break;
+       }
+
+       /* Test for correct parameter count.    */
+
+       if (pcpi->argcount < parametercount) {
+               CECDBG("CEC: pcpi->argcount[%d] < parametercount[%d]\n",
+                       pcpi->argcount,parametercount);
+               countok = false;
+       }
+       return(countok );
+}
+
+static bool cec_rx_msg_handler_last(cec_framedata_t *pcpi)
+{
+       bool isdirectaddressed;
+       cec_framedata_t cecFrame;
+       
+       CECDBG("CEC: cec_rx_msg_handler_last,opcode=%d\n",pcpi->opcode);
+       isdirectaddressed = !((pcpi->srcdestaddr & 0x0F) == CEC_LOGADDR_UNREGORBC);
+
+       if (validate_cec_message(pcpi)) {/* If invalid message, ignore it, but treat it as handled*/
+               if (isdirectaddressed) {
+                       switch (pcpi->opcode) {
+                       case CECOP_FEATURE_ABORT:
+                               cec_handle_feature_abort(pcpi);
+                               break;
+                       case CECOP_IMAGE_VIEW_ON:       /*In our case, respond the same to both these messages*/
+                       case CECOP_TEXT_VIEW_ON:
+                               break;
+                       case CECOP_STANDBY:             /* Direct and Broadcast*/
+                               /* Setting this here will let the main task know    */
+                               /* (via SI_CecGetPowerState) and at the same time   */
+                               /* prevent us from broadcasting a STANDBY message   */
+                               /* of our own when the main task responds by        */
+                               /* calling SI_CecSetPowerState( STANDBY );          */
+                               cec.powerstatus = CEC_POWERSTATUS_STANDBY;
+                               break;
+                       case CECOP_INACTIVE_SOURCE:
+                               cec_handle_inactive_source(pcpi);
+                               break;
+                       case CECOP_GIVE_PHYSICAL_ADDRESS:
+                               /* TV responds by broadcasting its Physical Address: 0.0.0.0   */
+                               cecFrame.opcode        = CECOP_REPORT_PHYSICAL_ADDRESS;
+                               cecFrame.srcdestaddr   = MAKE_SRCDEST(cec.address_logic,
+                                                                     CEC_LOGADDR_UNREGORBC);
+                               cecFrame.args[0]       = (cec.address_phy&0xFF00)>>8;             /* [Physical Address]*/
+                               cecFrame.args[1]       = (cec.address_phy&0x00FF);             /*[Physical Address]*/
+                               cecFrame.args[2]       = cec.address_logic;/*CEC_LOGADDR_PLAYBACK1;//2011.08.03 CEC_LOGADDR_TV;   // [Device Type] = 0 = TV*/
+                               cecFrame.argcount      = 3;
+                               cec_send_frame(&cecFrame);
+                               break;
+                       case CECOP_GIVE_DEVICE_POWER_STATUS:
+                               /* TV responds with power status.   */
+                               cecFrame.opcode        = CECOP_REPORT_POWER_STATUS;
+                               cecFrame.srcdestaddr   = MAKE_SRCDEST(cec.address_logic, (pcpi->srcdestaddr & 0xF0) >> 4);
+                               cecFrame.args[0]       = cec.powerstatus;
+                               cecFrame.argcount      = 1;
+                               cec_send_frame(&cecFrame);
+                               break;
+                       case CECOP_GET_MENU_LANGUAGE:
+                               /* TV Responds with a Set Menu language command.    */
+                               cecFrame.opcode         = CECOP_SET_MENU_LANGUAGE;
+                               cecFrame.srcdestaddr    = CEC_LOGADDR_UNREGORBC;
+                               cecFrame.args[0]        = 'e';     /* [language code see iso/fdis 639-2]*/
+                               cecFrame.args[1]        = 'n';     /* [language code see iso/fdis 639-2]*/
+                               cecFrame.args[2]        = 'g';     /* [language code see iso/fdis 639-2]*/
+                               cecFrame.argcount       = 3;
+                               cec_send_frame(&cecFrame);
+                               break;
+                       case CECOP_GET_CEC_VERSION:
+                           /* TV responds to this request with it's CEC version support.   */
+                               cecFrame.srcdestaddr   = MAKE_SRCDEST(cec.address_logic, (pcpi->srcdestaddr & 0xF0) >> 4);
+                               cecFrame.opcode        = CECOP_CEC_VERSION;
+                               cecFrame.args[0]       = 0x04;       /* Report CEC1.3a*/
+                               cecFrame.argcount      = 1;
+                               cec_send_frame(&cecFrame);
+                               break;
+                       case CECOP_REPORT_POWER_STATUS:         /* Someone sent us their power state.*/
+                               /*l_sourcePowerStatus = pcpi->args[0];
+                               Let NEW SOURCE task know about it.   
+                               if  (l_cecTaskState.task == SI_CECTASK_NEWSOURCE)  {
+                               l_cecTaskState.cpiState = CPI_RESPONSE;
+                               }*/
+                               break;
+                       /* Do not reply to directly addressed 'Broadcast' msgs.  */
+                       case CECOP_ACTIVE_SOURCE:
+                       case CECOP_REPORT_PHYSICAL_ADDRESS:     /*A physical address was broadcast -- ignore it.*/
+                       case CECOP_REQUEST_ACTIVE_SOURCE:       /*We are not a source, so ignore this one.*/
+                       case CECOP_ROUTING_CHANGE:              /*We are not a downstream switch, so ignore this one.*/
+                       case CECOP_ROUTING_INFORMATION:         /*We are not a downstream switch, so ignore this one.*/
+                       case CECOP_SET_STREAM_PATH:             /*We are not a source, so ignore this one.*/
+                       case CECOP_SET_MENU_LANGUAGE:           /*As a TV, we can ignore this message*/
+                       case CECOP_DEVICE_VENDOR_ID:
+                               break;
+                       case CECOP_ABORT:       /*Send Feature Abort for all unsupported features.*/
+                       default:
+                               cec_send_feature_abort(pcpi, CECAR_UNRECOG_OPCODE);
+                               break;
+                       }
+               } else {
+               /* Respond to broadcast messages. */
+                       switch (pcpi->opcode) {
+                       case CECOP_STANDBY:
+
+                               /* Setting this here will let the main task know    */
+                               /* (via SI_CecGetPowerState) and at the same time   */
+                               /* prevent us from broadcasting a STANDBY message   */
+                               /* of our own when the main task responds by        */
+                               /* calling SI_CecSetPowerState( STANDBY );          */
+
+                           cec.powerstatus = CEC_POWERSTATUS_STANDBY;
+                           break;
+
+                       case CECOP_ACTIVE_SOURCE:
+                       /*CecHandleActiveSource( pcpi );*/
+                               break;
+                       case CECOP_REPORT_PHYSICAL_ADDRESS:
+                       /*CecHandleReportPhysicalAddress( pcpi );*/
+                               break;
+                       /* Do not reply to 'Broadcast' msgs that we don't need.  */
+                       case CECOP_REQUEST_ACTIVE_SOURCE:       /*We are not a source, so ignore this one.*/
+                       /*SI_StartActiveSource(0,0);//2011.08.03*/
+                               break;
+                       case CECOP_ROUTING_CHANGE:              /*We are not a downstream switch, so ignore this one.*/
+                       case CECOP_ROUTING_INFORMATION:         /*We are not a downstream switch, so ignore this one.*/
+                       case CECOP_SET_STREAM_PATH:             /*We are not a source, so ignore this one.*/
+                       case CECOP_SET_MENU_LANGUAGE:           /*As a TV, we can ignore this message*/
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+static void cec_work_func(struct work_struct *work)
+{
+       struct cec_delayed_work *cec_w =
+               container_of(work, struct cec_delayed_work, work.work);
+       cec_framedata_t cecFrame;
+       CECDBG(KERN_WARNING "CEC: cec_work_func,event=%d\n",cec_w->event);
+       switch(cec_w->event)
+       {
+               case EVENT_ENUMERATE:
+                       break;
+               case EVENT_RX_FRAME:
+                       memset(&cecFrame, 0, sizeof(cec_framedata_t));
+                       cec_read_frame(&cecFrame);
+                       cec_rx_msg_handler_last(&cecFrame);
+                       break;
+               default:
+                       break;
+       }
+
+       if(cec_w->data)
+               kfree(cec_w->data);
+       kfree(cec_w);
+}
+
+static void cec_submit_work(int event, int delay, void *data)
+{
+       struct cec_delayed_work *work;
+
+       CECDBG("%s event %04x delay %d", __func__, event, delay);
+       work = kmalloc(sizeof(struct cec_delayed_work), GFP_ATOMIC);
+
+       if (work) {
+               INIT_DELAYED_WORK(&work->work, cec_work_func);
+               work->event = event;
+               work->data = data;
+               queue_delayed_work(cec.workqueue,
+                                  &work->work,
+                                  msecs_to_jiffies(delay));
+       } else {
+               CECDBG(KERN_WARNING "CEC: GPIO CEC: Cannot allocate memory to "
+                                   "create work\n");;
+       }
+}
+
+int cec_enumerate(void)
+{
+       /*for(i = 0; i < 3; i++) {
+               if(Cec_Ping(la_player[i]) == 1) {
+                       cec.address_logic = la_player[i];
+                       break;
+               }
+       }
+       if(i == 3)
+               return -1;
+       //Broadcast our physical address.
+       GPIO_CecSendMessage(CECOP_GET_MENU_LANGUAGE,CEC_LOGADDR_TV);
+       msleep(100);*/
+       CECDBG("CEC: %s\n", __func__);  
+       cec.address_logic = la_player[0];
+       hdmi_writel(hdmi_dev, CEC_LOGICADDR, cec.address_logic);
+       start_active_source();
+       return 0;
+}
+
+void cec_set_device_pa(int addr)
+{
+       CECDBG("CEC: Physical Address is %02x", addr);
+       cec.address_phy = addr;
+}
+
+void rk3036_cec_isr(void)
+{
+       int tx_isr = 0, rx_isr = 0;
+       hdmi_readl(hdmi_dev, CEC_TX_INT, &tx_isr);
+       hdmi_readl(hdmi_dev, CEC_RX_INT, &rx_isr);
+
+       CECDBG("CEC: rk3036_cec_isr:tx_isr %02x  rx_isr %02x\n\n", tx_isr, rx_isr);
+       
+       hdmi_writel(hdmi_dev, CEC_TX_INT, tx_isr);
+       hdmi_writel(hdmi_dev, CEC_RX_INT, rx_isr);
+       
+       if (tx_isr & m_TX_BUSNOTFREE) {
+               cec.busfree = 0;
+               CECDBG("CEC: m_TX_BUSNOTFREE,busfree=%d\n",cec.busfree);                
+       } else if (tx_isr & m_TX_DONE) {
+               cec.tx_done = 1;
+               CECDBG("CEC: m_TX_DONE,busfree=%d\n",cec.tx_done);
+       } else {
+               cec.tx_done = -1;
+               CECDBG("CEC: else:busfree=%d\n",cec.tx_done);
+       }       
+       
+       wake_up_interruptible_all(&cec.wait);
+       if(rx_isr & m_RX_DONE)
+               cec_submit_work(EVENT_RX_FRAME, 0, NULL);
+}
+
+
+static int __init rk3036_cec_init(void)
+{
+       CECDBG(KERN_ERR "CEC: rk3036_cec_init start.\n");
+       memset(&cec, 0, sizeof(cec_t));
+       cec.workqueue = create_singlethread_workqueue("cec");
+       if (cec.workqueue == NULL) {
+               CECDBG(KERN_ERR "CEC: GPIO CEC: create workqueue failed.\n");
+               return -1;
+       }
+       init_waitqueue_head(&cec.wait);
+       
+       /*Fref = Fsys / ((register 0xd4 + 1)*(register 0xd5 + 1))*/
+       /*Fref = 0.5M, Fsys = 74.25M*/
+       hdmi_writel(hdmi_dev, CEC_CLK_H, 11);
+       hdmi_writel(hdmi_dev, CEC_CLK_L, 11);
+
+       /*Set bus free time to 16.8ms*/
+       hdmi_writel(hdmi_dev, CEC_BUSFREETIME_L, 0xd0);
+       hdmi_writel(hdmi_dev, CEC_BUSFREETIME_H, 0x20); 
+       
+       /*Enable TX/RX INT*/
+       hdmi_writel(hdmi_dev, CEC_TX_INT, 0xFF);
+       hdmi_writel(hdmi_dev, CEC_RX_INT, 0xFF);
+
+       rk3036_hdmi_register_cec_callbacks(rk3036_cec_isr,
+                                          cec_set_device_pa,
+                                          cec_enumerate);
+       
+       CECDBG(KERN_ERR "CEC: rk3036_cec_init sucess\n");
+
+       return 0;
+}
+
+static void __exit rk3036_cec_exit(void)
+{
+       kfree(&cec);
+}
+
+late_initcall_sync(rk3036_cec_init);
+module_exit(rk3036_cec_exit);
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_cec.h b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_cec.h
new file mode 100755 (executable)
index 0000000..e9f6cf2
--- /dev/null
@@ -0,0 +1,161 @@
+#ifndef __RK3036_CEC_H__
+#define __RK3036_CEC_H__
+
+typedef enum
+{
+       CEC_LOGADDR_TV          = 0x00,
+       CEC_LOGADDR_RECDEV1     = 0x01,
+       CEC_LOGADDR_RECDEV2     = 0x02,
+       CEC_LOGADDR_TUNER1      = 0x03,     /* STB1 in Spev v1.3*/
+       CEC_LOGADDR_PLAYBACK1   = 0x04,     /* DVD1 in Spev v1.3*/
+       CEC_LOGADDR_AUDSYS      = 0x05,
+       CEC_LOGADDR_TUNER2      = 0x06,     /* STB2 in Spec v1.3*/
+       CEC_LOGADDR_TUNER3      = 0x07,     /* STB3 in Spec v1.3*/
+       CEC_LOGADDR_PLAYBACK2   = 0x08,     /* DVD2 in Spec v1.3*/
+       CEC_LOGADDR_RECDEV3     = 0x09,
+       CEC_LOGADDR_TUNER4      = 0x0A,     /* RES1 in Spec v1.3*/
+       CEC_LOGADDR_PLAYBACK3   = 0x0B,     /* RES2 in Spec v1.3*/
+       CEC_LOGADDR_RES3        = 0x0C,
+       CEC_LOGADDR_RES4        = 0x0D,
+       CEC_LOGADDR_FREEUSE     = 0x0E,
+       CEC_LOGADDR_UNREGORBC   = 0x0F
+} cec_log_addr_t;
+
+typedef enum                    /* CEC Messages*/
+{
+       CECOP_FEATURE_ABORT             = 0x00,
+       CECOP_IMAGE_VIEW_ON             = 0x04,
+       CECOP_TUNER_STEP_INCREMENT      = 0x05,     /* N/A*/
+       CECOP_TUNER_STEP_DECREMENT      = 0x06,     /* N/A*/
+       CECOP_TUNER_DEVICE_STATUS       = 0x07,     /* N/A*/
+       CECOP_GIVE_TUNER_DEVICE_STATUS  = 0x08,     /* N/A*/
+       CECOP_RECORD_ON                 = 0x09,     /* N/A*/
+       CECOP_RECORD_STATUS             = 0x0A,     /* N/A*/
+       CECOP_RECORD_OFF                = 0x0B,     /* N/A*/
+       CECOP_TEXT_VIEW_ON              = 0x0D,
+       CECOP_RECORD_TV_SCREEN          = 0x0F,     /* N/A*/
+       CECOP_GIVE_DECK_STATUS          = 0x1A,
+       CECOP_DECK_STATUS               = 0x1B,
+       CECOP_SET_MENU_LANGUAGE         = 0x32,
+       CECOP_CLEAR_ANALOGUE_TIMER      = 0x33,     /* Spec 1.3A*/
+       CECOP_SET_ANALOGUE_TIMER        = 0x34,     /* Spec 1.3A*/
+       CECOP_TIMER_STATUS              = 0x35,     /* Spec 1.3A*/
+       CECOP_STANDBY                   = 0x36,
+       CECOP_PLAY                      = 0x41,
+       CECOP_DECK_CONTROL              = 0x42,
+       CECOP_TIMER_CLEARED_STATUS      = 0x43,     /* Spec 1.3A*/
+       CECOP_USER_CONTROL_PRESSED      = 0x44,
+       CECOP_USER_CONTROL_RELEASED     = 0x45,
+       CECOP_GIVE_OSD_NAME             = 0x46,
+       CECOP_SET_OSD_NAME              = 0x47,
+       CECOP_SET_OSD_STRING            = 0x64,
+       CECOP_SET_TIMER_PROGRAM_TITLE   = 0x67,     /* Spec 1.3A*/
+       CECOP_SYSTEM_AUDIO_MODE_REQUEST = 0x70,     /* Spec 1.3A*/
+       CECOP_GIVE_AUDIO_STATUS         = 0x71,     /* Spec 1.3A*/
+       CECOP_SET_SYSTEM_AUDIO_MODE     = 0x72,     /* Spec 1.3A*/
+       CECOP_REPORT_AUDIO_STATUS       = 0x7A,     /* Spec 1.3A*/
+       CECOP_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, /* Spec 1.3A*/
+       CECOP_SYSTEM_AUDIO_MODE_STATUS  = 0x7E,     /* Spec 1.3A*/
+       CECOP_ROUTING_CHANGE            = 0x80,
+       CECOP_ROUTING_INFORMATION       = 0x81,
+       CECOP_ACTIVE_SOURCE             = 0x82,
+       CECOP_GIVE_PHYSICAL_ADDRESS     = 0x83,
+       CECOP_REPORT_PHYSICAL_ADDRESS   = 0x84,
+       CECOP_REQUEST_ACTIVE_SOURCE     = 0x85,
+       CECOP_SET_STREAM_PATH           = 0x86,
+       CECOP_DEVICE_VENDOR_ID          = 0x87,
+       CECOP_VENDOR_COMMAND            = 0x89,
+       CECOP_VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+       CECOP_VENDOR_REMOTE_BUTTON_UP   = 0x8B,
+       CECOP_GIVE_DEVICE_VENDOR_ID     = 0x8C,
+       CECOP_MENU_REQUEST              = 0x8D,
+       CECOP_MENU_STATUS               = 0x8E,
+       CECOP_GIVE_DEVICE_POWER_STATUS  = 0x8F,
+       CECOP_REPORT_POWER_STATUS       = 0x90,
+       CECOP_GET_MENU_LANGUAGE         = 0x91,
+       CECOP_SELECT_ANALOGUE_SERVICE   = 0x92,     /* Spec 1.3A    N/A*/
+       CECOP_SELECT_DIGITAL_SERVICE    = 0x93,     /*              N/A*/
+       CECOP_SET_DIGITAL_TIMER         = 0x97,     /* Spec 1.3A*/
+       CECOP_CLEAR_DIGITAL_TIMER       = 0x99,     /* Spec 1.3A*/
+       CECOP_SET_AUDIO_RATE            = 0x9A,     /* Spec 1.3A*/
+       CECOP_INACTIVE_SOURCE           = 0x9D,     /* Spec 1.3A*/
+       CECOP_CEC_VERSION               = 0x9E,     /* Spec 1.3A*/
+       CECOP_GET_CEC_VERSION           = 0x9F,     /* Spec 1.3A*/
+       CECOP_VENDOR_COMMAND_WITH_ID    = 0xA0,     /* Spec 1.3A*/
+       CECOP_CLEAR_EXTERNAL_TIMER      = 0xA1,     /* Spec 1.3A*/
+       CECOP_SET_EXTERNAL_TIMER        = 0xA2,     /* Spec 1.3A*/
+       CDCOP_HEADER                    = 0xF8,
+       CECOP_ABORT                     = 0xFF,
+
+       CECOP_REPORT_SHORT_AUDIO        = 0xA3,     /* Spec 1.4*/
+       CECOP_REQUEST_SHORT_AUDIO       = 0xA4,     /* Spec 1.4*/
+
+       CECOP_ARC_INITIATE              = 0xC0,
+       CECOP_ARC_REPORT_INITIATED      = 0xC1,
+       CECOP_ARC_REPORT_TERMINATED     = 0xC2,
+
+       CECOP_ARC_REQUEST_INITIATION    = 0xC3,
+       CECOP_ARC_REQUEST_TERMINATION   = 0xC4,
+       CECOP_ARC_TERMINATE             = 0xC5,   
+} cec_opcode_t;
+
+typedef enum                        /* Operands for <Feature Abort> Opcode*/
+{
+       CECAR_UNRECOG_OPCODE            = 0x00,
+       CECAR_NOT_CORRECT_MODE,
+       CECAR_CANT_PROVIDE_SOURCE,
+       CECAR_INVALID_OPERAND,
+       CECAR_REFUSED
+} cec_abor_reason_t;
+    
+enum                        /* Operands for <Power Status> Opcode*/
+{
+       CEC_POWERSTATUS_ON              = 0x00,
+       CEC_POWERSTATUS_STANDBY         = 0x01,
+       CEC_POWERSTATUS_STANDBY_TO_ON   = 0x02,
+       CEC_POWERSTATUS_ON_TO_STANDBY   = 0x03,
+};
+
+enum {
+       EVENT_RX_FRAME,
+       EVENT_ENUMERATE,
+};
+
+#define MAKE_SRCDEST( src, dest)    (( src << 4) | dest )
+
+#define MAX_CMD_SIZE 16
+
+typedef struct
+{
+       char srcdestaddr;            /*Source in upper nybble, dest in lower nybble*/
+       char opcode;
+       char args[ MAX_CMD_SIZE ];
+       char argcount;
+       char nextframeargcount;
+} cec_framedata_t;
+
+struct cec_delayed_work {
+       struct delayed_work work;
+       int event;
+       void *data;
+};
+
+typedef struct
+{
+       struct workqueue_struct *workqueue;     
+       wait_queue_head_t wait;
+       int busfree;
+       int tx_done;
+       int address_phy;
+       int address_logic;
+       int powerstatus;
+} cec_t;
+
+//#define DEBUG
+#ifdef DEBUG
+#define CECDBG(format, ...) \
+               printk(KERN_INFO format, ## __VA_ARGS__)
+#else
+#define CECDBG(format, ...)
+#endif
+#endif
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hdcp.c
new file mode 100755 (executable)
index 0000000..b28dd0e
--- /dev/null
@@ -0,0 +1,286 @@
+#include <linux/delay.h>
+#include "rk3036_hdmi.h"
+#include "rk3036_hdmi_hw.h"
+#include "rk3036_hdcp.h"
+int is_1b_03_test(void)
+{
+       int reg_value;
+       int reg_val_1;
+
+       hdmi_readl(hdmi_dev, 0x58, &reg_value);
+       hdmi_readl(hdmi_dev, 0xc3, &reg_val_1);
+
+       if (reg_value != 0) {
+               if ((reg_val_1 & 0x40) == 0)
+                       return 1;
+       }
+       return 0;
+}
+
+void rk3036_set_colorbar(int enable)
+{
+       static int display_mask;
+       int reg_value;
+       int tmds_clk;
+
+       tmds_clk = hdmi_dev->driver.tmdsclk;
+       if (enable) {
+               if (!display_mask) {
+                       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+                               hdmi_readl(hdmi_dev, SYS_CTRL, &reg_value);
+                               hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                                            m_REG_CLK_SOURCE,
+                                            v_REG_CLK_SOURCE_SYS);
+                               hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x00);
+                               hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
+                       } else {
+                               hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x00);
+                       }
+                       display_mask = 1;
+               }
+       } else {
+               if (display_mask) {
+                       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+                               hdmi_readl(hdmi_dev, SYS_CTRL, &reg_value);
+                               hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                                            m_REG_CLK_SOURCE,
+                                            v_REG_CLK_SOURCE_SYS);
+                               hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x10);
+                               hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
+                       } else {
+                               hdmi_writel(hdmi_dev, HDMI_COLORBAR, 0x10);
+                       }
+                       display_mask = 0;
+               }
+       }
+}
+
+void rk3036_hdcp_disable(void)
+{
+       int reg_value;
+       int tmds_clk;
+
+       tmds_clk = hdmi_dev->driver.tmdsclk;
+       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+               hdmi_readl(hdmi_dev, SYS_CTRL, &reg_value);
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                            m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+       }
+
+       /* Diable HDCP Interrupt*/
+       hdmi_writel(hdmi_dev, HDCP_INT_MASK1, 0x00);
+       /* Stop and Reset HDCP*/
+       hdmi_msk_reg(hdmi_dev, HDCP_CTRL1,
+                    m_AUTH_START | m_AUTH_STOP | m_HDCP_RESET,
+                    v_AUTH_START(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1));
+
+       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
+               hdmi_writel(hdmi_dev, SYS_CTRL, reg_value);
+}
+
+int rk3036_hdcp_key_check(struct hdcp_keys *key)
+{
+       int i = 0;
+
+       DBG("HDCP: check hdcp key\n");
+       /*check 40 private key */
+       for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++) {
+               if (key->devicekey[i] != 0x00)
+                       return HDCP_KEY_VALID;
+       }
+       /*check aksv*/
+       for (i = 0; i < 5; i++) {
+               if (key->ksv[i] != 0x00)
+                       return HDCP_KEY_VALID;
+       }
+
+       return HDCP_KEY_INVALID;
+}
+int rk3036_hdcp_load_key2mem(struct hdcp_keys *key)
+{
+       int i;
+
+       DBG("HDCP: rk3036_hdcp_load_key2mem start\n");
+       /* Write 40 private key*/
+       for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
+               hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->devicekey[i]);
+       /* Write 1st aksv*/
+       for (i = 0; i < 5; i++)
+               hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->ksv[i]);
+       /* Write 2nd aksv*/
+       for (i = 0; i < 5; i++)
+               hdmi_writel(hdmi_dev, HDCP_KEY_FIFO, key->ksv[i]);
+       DBG("HDCP: rk3036_hdcp_load_key2mem end\n");
+       return HDCP_OK;
+}
+
+int rk3036_hdcp_start_authentication(void)
+{
+       int temp;
+       int retry = 0;
+       int tmds_clk;
+
+       tmds_clk = hdmi_dev->driver.tmdsclk;
+       if (hdcp->keys == NULL) {
+               HDCP_WARN("HDCP: key is not loaded\n");
+               return HDCP_KEY_ERR;
+       }
+       if (rk3036_hdcp_key_check(hdcp->keys) == HDCP_KEY_INVALID) {
+               HDCP_WARN("loaded HDCP key is incorrect\n");
+               return HDCP_KEY_ERR;
+       }
+       if (tmds_clk > (HDMI_SYS_FREG_CLK << 2)) {
+               /*Select TMDS CLK to configure regs*/
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                            m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);
+       } else {
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                            m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+       }
+       hdmi_writel(hdmi_dev, HDCP_TIMER_100MS, 0x28);
+       hdmi_readl(hdmi_dev, HDCP_KEY_STATUS, &temp);
+       while ((temp & m_KEY_READY) == 0) {
+               if (retry > 1000) {
+                       HDCP_WARN("HDCP: loaded key error\n");
+                       return HDCP_KEY_ERR;
+               }
+               rk3036_hdcp_load_key2mem(hdcp->keys);
+               msleep(1);
+               hdmi_readl(hdmi_dev, HDCP_KEY_STATUS, &temp);
+               retry++;
+       }
+       /*Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)*/
+       retry = hdmi_dev->hclk_rate/(HDCP_DDC_CLK << 2);
+       hdmi_writel(hdmi_dev, DDC_CLK_L, retry & 0xFF);
+       hdmi_writel(hdmi_dev, DDC_CLK_H, (retry >> 8) & 0xFF);
+       hdmi_writel(hdmi_dev, HDCP_CTRL2, 0x67);
+       /*Enable interrupt*/
+       hdmi_writel(hdmi_dev, HDCP_INT_MASK1,
+                   m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE |
+                   m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);
+       hdmi_writel(hdmi_dev, HDCP_INT_MASK2, 0x00);
+       /*Start authentication*/
+       hdmi_msk_reg(hdmi_dev, HDCP_CTRL1,
+                    m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE |
+                    m_AUTH_STOP | m_HDCP_RESET,
+                    v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) |
+                    v_ADVANED_ENABLE(0) | v_AUTH_STOP(0) | v_HDCP_RESET(0));
+
+       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2)) {
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_REG_CLK_SOURCE,
+                            v_REG_CLK_SOURCE_TMDS);
+       }
+       return HDCP_OK;
+}
+
+int rk3036_hdcp_stop_authentication(void)
+{
+       hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                    m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+       hdmi_writel(hdmi_dev, DDC_CLK_L, 0x1c);
+       hdmi_writel(hdmi_dev, DDC_CLK_H, 0x00);
+       hdmi_writel(hdmi_dev, HDCP_CTRL2, 0x08);
+       hdmi_writel(hdmi_dev, HDCP_INT_MASK2, 0x06);
+       hdmi_writel(hdmi_dev, HDCP_CTRL1, 0x02);
+       return 0;
+       /*hdmi_writel(HDCP_CTRL1, 0x0a);*/
+}
+#if 0
+int    rk3036_hdcp_check_bksv(void)
+{
+       int i, j;
+       char temp = 0, bksv[5];
+       char *invalidkey;
+
+       for (i = 0; i < 5; i++) {
+               hdmi_readl(HDCP_KSV_BYTE0 + (4 - i), &temp);
+               bksv[i] = temp & 0xFF;
+       }
+       DBG("bksv is 0x%02x%02x%02x%02x%02x",
+           bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
+
+       temp = 0;
+       for (i = 0; i < 5; i++) {
+               for (j = 0; j < 8; j++) {
+                       if (bksv[i] & 0x01)
+                               temp++;
+                       bksv[i] >>= 1;
+               }
+       }
+       if (temp != 20)
+               return HDCP_KSV_ERR;
+       for (i = 0; i < hdcp->invalidkey; i++) {
+               invalidkey = hdcp->invalidkeys + i*5;
+               if (memcmp(bksv, invalidkey, 5) == 0) {
+                       HDCP_WARN("HDCP:BKSV was revocated!\n");
+                       hdmi_msk_reg(HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE,
+                                    v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1));
+                       return HDCP_KSV_ERR;
+               }
+       }
+       hdmi_msk_reg(HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE,
+                    v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1));
+       return HDCP_OK;
+}
+#endif
+
+int rk3036_hdcp_error(int value)
+{
+       if (value & 0x80)
+               HDCP_WARN("Timed out waiting for downstream repeater\n");
+       else if (value & 0x40)
+               HDCP_WARN("Too many devices connected to repeater tree\n");
+       else if (value & 0x20)
+               HDCP_WARN("SHA-1 hash check of BKSV list failed\n");
+       else if (value & 0x10)
+               HDCP_WARN("SHA-1 hash check of BKSV list failed\n");
+       else if (value & 0x08)
+               HDCP_WARN("DDC channels no acknowledge\n");
+       else if (value & 0x04)
+               HDCP_WARN("Pj mismatch\n");
+       else if (value & 0x02)
+               HDCP_WARN("Ri mismatch\n");
+       else if (value & 0x01)
+               HDCP_WARN("Bksv is wrong\n");
+       else
+               return 0;
+       return 1;
+}
+void rk3036_hdcp_interrupt(char *status1, char *status2)
+{
+       int interrupt1 = 0;
+       int interrupt2 = 0;
+       int temp = 0;
+       int tmds_clk;
+
+       tmds_clk = hdmi_dev->driver.tmdsclk;
+       hdmi_readl(hdmi_dev, HDCP_INT_STATUS1, &interrupt1);
+       hdmi_readl(hdmi_dev, HDCP_INT_STATUS2, &interrupt2);
+
+       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL,
+                            m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_SYS);
+
+       if (interrupt1) {
+               hdmi_writel(hdmi_dev, HDCP_INT_STATUS1, interrupt1);
+               if (interrupt1 & m_INT_HDCP_ERR) {
+                       hdmi_readl(hdmi_dev, HDCP_ERROR, &temp);
+                       HDCP_WARN("HDCP: Error reg 0x65 = 0x%02x\n", temp);
+                       rk3036_hdcp_error(temp);
+                       hdmi_writel(hdmi_dev, HDCP_ERROR, temp);
+               }
+       }
+       if (interrupt2)
+               hdmi_writel(hdmi_dev, HDCP_INT_STATUS2, interrupt2);
+
+       *status1 = interrupt1;
+       *status2 = interrupt2;
+
+       if (tmds_clk <= (HDMI_SYS_FREG_CLK << 2))
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_REG_CLK_SOURCE,
+                            v_REG_CLK_SOURCE_TMDS);
+/*
+       hdmi_readl(HDCP_ERROR, &temp);
+       DBG("HDCP: Error reg 0x65 = 0x%02x\n", temp);
+*/
+}
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.c
new file mode 100755 (executable)
index 0000000..2804018
--- /dev/null
@@ -0,0 +1,578 @@
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include "rk3036_hdmi.h"
+#include "rk3036_hdmi_hw.h"
+
+static int __maybe_unused rk3036_hdmi_show_reg(struct hdmi *hdmi_drv)
+{
+       int i = 0;
+       u32 val = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       printk("\n>>>rk3036_ctl reg");
+       for (i = 0; i < 16; i++)
+               printk(" %2x", i);
+
+       printk("\n-----------------------------------------------------------------");
+
+       for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
+               hdmi_readl(hdmi_dev, i, &val);
+               if (i % 16 == 0)
+                       printk("\n>>>rk3036_ctl %2x:", i);
+               printk(" %02x", val);
+       }
+       printk("\n-----------------------------------------------------------------\n");
+
+       return 0;
+}
+
+static inline void delay100us(void)
+{
+       msleep(1);
+}
+
+static void rk3036_hdmi_av_mute(struct hdmi *hdmi_drv, bool enable)
+{
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       hdmi_writel(hdmi_dev, AV_MUTE,
+                   v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
+}
+
+static void rk3036_hdmi_sys_power(struct hdmi *hdmi_drv, bool enable)
+{
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       if (enable)
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
+       else
+               hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
+}
+
+static void rk3036_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
+{
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       if (hdmi_drv->pwr_mode == mode)
+               return;
+
+       hdmi_dbg(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
+                hdmi_drv->pwr_mode, mode);
+
+       switch (mode) {
+       case NORMAL:
+               hdmi_dbg(hdmi_drv->dev,
+                        "%s change pwr_mode NORMAL pwr_mode = %d, mode = %d\n",
+                        __func__, hdmi_drv->pwr_mode, mode);
+               rk3036_hdmi_sys_power(hdmi_drv, false);
+               hdmi_writel(hdmi_dev, PHY_DRIVER, 0xaa);
+               hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x6f);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x15);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x14);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x10);
+               hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
+               hdmi_writel(hdmi_dev, 0xce, 0x00);
+               hdmi_writel(hdmi_dev, 0xce, 0x01);
+               rk3036_hdmi_av_mute(hdmi_drv, 1);
+               rk3036_hdmi_sys_power(hdmi_drv, true);
+               break;
+       case LOWER_PWR:
+               hdmi_dbg(hdmi_drv->dev,
+                        "%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
+                        __func__, hdmi_drv->pwr_mode, mode);
+               rk3036_hdmi_av_mute(hdmi_drv, 0);
+               rk3036_hdmi_sys_power(hdmi_drv, false);
+               hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
+               hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
+               hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x17);
+               break;
+       default:
+               hdmi_dbg(hdmi_drv->dev, "unkown rk3036 hdmi pwr mode %d\n",
+                        mode);
+       }
+
+       hdmi_drv->pwr_mode = mode;
+}
+
+int rk3036_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
+{
+       int value = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       hdmi_dbg(hdmi_drv->dev, "[%s] value %02x\n", __func__, value);
+       hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
+       value &= m_HOTPLUG;
+       if (value == m_HOTPLUG)
+               return HDMI_HPD_ACTIVED;
+       else if (value)
+               return HDMI_HPD_INSERT;
+       else
+               return HDMI_HPD_REMOVED;
+}
+int rk3036_hdmi_insert(struct hdmi *hdmi_drv)
+{
+       rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
+       return 0;
+}
+
+
+int rk3036_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
+{
+       u32 c = 0;
+       u8 segment = 0;
+       u8 offset = 0;
+       int ret = -1;
+       int i, j;
+       int ddc_bus_freq;
+       int trytime;
+       int checksum = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+       if (block % 2)
+               offset = HDMI_EDID_BLOCK_SIZE;
+
+       if (block / 2)
+               segment = 1;
+       ddc_bus_freq = (hdmi_dev->hclk_rate >> 2) / HDMI_SCL_RATE;
+       hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
+       hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
+
+       hdmi_dbg(hdmi_drv->dev,
+                "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
+                (int)segment, (int)block, (int)offset);
+       disable_irq(hdmi_drv->irq);
+
+       /* Enable edid interrupt */
+       hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
+
+       for (trytime = 0; trytime < 10; trytime++) {
+               checksum = 0;
+               hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
+
+               /* Set edid fifo first addr */
+               hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
+
+               /* Set edid word address 0x00/0x80 */
+               hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
+
+               /* Set edid segment pointer */
+               hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
+
+               for (i = 0; i < 10; i++) {
+                       /* Wait edid interrupt */
+                       msleep(10);
+                       c = 0x00;
+                       hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
+
+                       if (c & m_INT_EDID_READY)
+                               break;
+               }
+
+               if (c & m_INT_EDID_READY) {
+                       for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
+                               c = 0;
+                               hdmi_readl(hdmi_dev, 0x50, &c);
+                               buf[j] = c;
+                               checksum += c;
+#ifdef HDMI_DEBUG
+                               if (j % 16 == 0)
+                                       printk("\n>>>0x%02x: ",j);
+
+                               printk("0x%02x ", c);
+#endif
+                       }
+
+                       /* clear EDID interrupt reg */
+                       hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
+                                   m_INT_EDID_READY);
+
+                       if ((checksum & 0xff) == 0) {
+                               ret = 0;
+                               hdmi_dbg(hdmi_drv->dev,
+                                        "[%s] edid read sucess\n", __func__);
+                               break;
+                       }
+               }
+       }
+       /*close edid irq*/
+       hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
+       enable_irq(hdmi_drv->irq);
+
+       return ret;
+}
+
+static void rk3036_hdmi_config_avi(struct hdmi *hdmi_drv,
+                                       unsigned char vic, unsigned char output_color)
+{
+       int i;
+       char info[SIZE_AVI_INFOFRAME];
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       memset(info, 0, SIZE_AVI_INFOFRAME);
+       hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+       info[0] = 0x82;
+       info[1] = 0x02;
+       info[2] = 0x0D;
+       info[3] = info[0] + info[1] + info[2];
+       info[4] = (AVI_COLOR_MODE_RGB << 5);
+       info[5] =
+           (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA <<
+                                             4) |
+           ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
+       info[6] = 0;
+       info[7] = vic;
+       if ((vic == HDMI_720X480I_60HZ_VIC) || (vic == HDMI_720X576I_50HZ_VIC))
+               info[8] = 1;
+       else
+               info[8] = 0;
+
+       /* Calculate AVI InfoFrame ChecKsum */
+       for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
+               info[3] += info[i];
+
+       info[3] = 0x100 - info[3];
+
+       for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
+               hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
+}
+
+static int rk3036_hdmi_config_video(struct hdmi *hdmi_drv,
+                                               struct hdmi_video_para *vpara)
+{
+       int value;
+       struct fb_videomode *mode;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       hdmi_dbg(hdmi_drv->dev, "[%s]\n", __func__);
+
+       if (vpara == NULL) {
+               hdmi_err(hdmi_drv->dev, "[%s] input parameter error\n",
+                        __func__);
+               return -1;
+       }
+
+       /* Output RGB as default */
+       vpara->output_color = VIDEO_OUTPUT_RGB444;
+       if (hdmi_drv->pwr_mode == LOWER_PWR)
+               rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
+
+       /* Disable video and audio output */
+       hdmi_writel(hdmi_dev, AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+
+       /* Input video mode is SDR RGB24bit, Data enable signal from external */
+       hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
+                   v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
+                   v_DE_EXTERNAL);
+       hdmi_writel(hdmi_dev, VIDEO_CONTRL2,
+                   v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
+                   v_VIDEO_OUTPUT_FORMAT(vpara->output_color & 0xFF));
+
+       /* Set HDMI Mode */
+       hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
+
+       /* Enable or disalbe color space convert */
+       if (vpara->input_color != vpara->output_color)
+               value = v_SOF_DISABLE | v_CSC_ENABLE;
+       else
+               value = v_SOF_DISABLE;
+       hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
+
+       /* Set ext video timing */
+#if 1
+       hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
+       mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
+       if (mode == NULL) {
+               hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
+                        vpara->vic);
+               return -ENOENT;
+       }
+       hdmi_drv->tmdsclk = mode->pixclock;
+#else
+       value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
+       if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+               value |= v_HSYNC_POLARITY(1);
+       if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+               value |= v_VSYNC_POLARITY(1);
+       hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
+
+       value = mode->left_margin + mode->xres + mode->right_margin +
+           mode->hsync_len;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
+
+       value = mode->left_margin + mode->right_margin + mode->hsync_len;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
+
+       value = mode->left_margin + mode->hsync_len;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
+
+       value = mode->hsync_len;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L, value & 0xFF);
+       hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
+
+       value = mode->upper_margin + mode->yres + mode->lower_margin +
+           mode->vsync_len;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
+       hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
+
+       value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
+
+       if (vpara->vic == HDMI_720x480p_60Hz_4_3 ||
+               vpara->vic == HDMI_720x480p_60Hz_16_9)
+               value = 42;
+       else
+               value = mode->upper_margin + mode->vsync_len;
+
+       hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
+
+       value = mode->vsync_len;
+       hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
+#endif
+
+       if (vpara->output_mode == OUTPUT_HDMI) {
+               rk3036_hdmi_config_avi(hdmi_drv, vpara->vic,
+                                       vpara->output_color);
+               hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n", __func__);
+       } else {
+               hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __func__);
+       }
+
+       /* rk3028a */
+       hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
+       hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
+       hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
+
+       return 0;
+}
+
+static void rk3036_hdmi_config_aai(struct hdmi *hdmi_drv)
+{
+       int i;
+       char info[SIZE_AUDIO_INFOFRAME];
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       memset(info, 0, SIZE_AUDIO_INFOFRAME);
+
+       info[0] = 0x84;
+       info[1] = 0x01;
+       info[2] = 0x0A;
+
+       info[3] = info[0] + info[1] + info[2];
+       for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
+               info[3] += info[i];
+
+       info[3] = 0x100 - info[3];
+
+       hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
+       for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
+               hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
+}
+
+static int rk3036_hdmi_config_audio(struct hdmi *hdmi_drv,
+                                               struct hdmi_audio *audio)
+{
+       int rate, N, channel, mclk_fs;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       if (audio->channel < 3)
+               channel = I2S_CHANNEL_1_2;
+       else if (audio->channel < 5)
+               channel = I2S_CHANNEL_3_4;
+       else if (audio->channel < 7)
+               channel = I2S_CHANNEL_5_6;
+       else
+               channel = I2S_CHANNEL_7_8;
+
+       switch (audio->rate) {
+       case HDMI_AUDIO_FS_32000:
+               rate = AUDIO_32K;
+               N = N_32K;
+               mclk_fs = MCLK_384FS;
+               break;
+       case HDMI_AUDIO_FS_44100:
+               rate = AUDIO_441K;
+               N = N_441K;
+               mclk_fs = MCLK_256FS;
+               break;
+       case HDMI_AUDIO_FS_48000:
+               rate = AUDIO_48K;
+               N = N_48K;
+               mclk_fs = MCLK_256FS;
+               break;
+       case HDMI_AUDIO_FS_88200:
+               rate = AUDIO_882K;
+               N = N_882K;
+               mclk_fs = MCLK_128FS;
+               break;
+       case HDMI_AUDIO_FS_96000:
+               rate = AUDIO_96K;
+               N = N_96K;
+               mclk_fs = MCLK_128FS;
+               break;
+       case HDMI_AUDIO_FS_176400:
+               rate = AUDIO_1764K;
+               N = N_1764K;
+               mclk_fs = MCLK_128FS;
+               break;
+       case HDMI_AUDIO_FS_192000:
+               rate = AUDIO_192K;
+               N = N_192K;
+               mclk_fs = MCLK_128FS;
+               break;
+       default:
+               dev_err(hdmi_drv->dev, "[%s] not support such sample rate %d\n",
+                       __func__, audio->rate);
+               return -ENOENT;
+       }
+
+       /* set_audio source I2S */
+       if (HDMI_CODEC_SOURCE_SELECT == INPUT_IIS) {
+               hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
+               hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
+               hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
+                           v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel));
+               hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
+               /* no swap */
+               hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
+       } else {
+               hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
+               /* no swap */
+               hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
+       }
+
+       /* Set N value */
+       hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
+       hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
+       hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
+       rk3036_hdmi_config_aai(hdmi_drv);
+
+       return 0;
+}
+
+void rk3036_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
+{
+       int mutestatus = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       if (enable) {
+               if (hdmi_drv->pwr_mode == LOWER_PWR)
+                       rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
+               hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
+               if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
+                       hdmi_writel(hdmi_dev, AV_MUTE,
+                                   v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
+               }
+               rk3036_hdmi_sys_power(hdmi_drv, true);
+               rk3036_hdmi_sys_power(hdmi_drv, false);
+               rk3036_hdmi_sys_power(hdmi_drv, true);
+               hdmi_writel(hdmi_dev, 0xce, 0x00);
+               delay100us();
+               hdmi_writel(hdmi_dev, 0xce, 0x01);
+       } else {
+               hdmi_writel(hdmi_dev, AV_MUTE,
+                           v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+       }
+}
+
+int rk3036_hdmi_removed(struct hdmi *hdmi_drv)
+{
+       dev_info(hdmi_drv->dev, "Removed.\n");
+       if (hdmi_drv->hdcp_power_off_cb)
+               hdmi_drv->hdcp_power_off_cb();
+       rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
+
+       return HDMI_ERROR_SUCESS;
+}
+
+void rk3036_hdmi_irq(struct hdmi *hdmi_drv)
+{
+       u32 interrupt = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+       hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
+       if(interrupt) {
+               hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
+       }
+       if (interrupt & m_INT_HOTPLUG) {
+               if (hdmi_drv->state == HDMI_SLEEP)
+                       hdmi_drv->state = WAIT_HOTPLUG;
+
+               queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
+                                  msecs_to_jiffies(40));
+
+       }/*plug out*/
+
+       if (hdmi_drv->hdcp_irq_cb)
+               hdmi_drv->hdcp_irq_cb(0);
+       if (hdmi_drv->cec_irq)
+               hdmi_drv->cec_irq();
+}
+
+static void rk3036_hdmi_reset(struct hdmi *hdmi_drv)
+{
+       u32 val = 0;
+       u32 msk = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
+       delay100us();
+       hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
+       delay100us();
+       msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
+       val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
+       hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
+
+       rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
+}
+
+int rk3036_hdmi_initial(struct hdmi *hdmi_drv)
+{
+       int rc = HDMI_ERROR_SUCESS;
+
+       hdmi_drv->pwr_mode = NORMAL;
+       hdmi_drv->remove = rk3036_hdmi_removed;
+       hdmi_drv->control_output = rk3036_hdmi_control_output;
+       hdmi_drv->config_video = rk3036_hdmi_config_video;
+       hdmi_drv->config_audio = rk3036_hdmi_config_audio;
+       hdmi_drv->detect_hotplug = rk3036_hdmi_detect_hotplug;
+       hdmi_drv->read_edid = rk3036_hdmi_read_edid;
+       hdmi_drv->insert    = rk3036_hdmi_insert;
+
+       rk3036_hdmi_reset_pclk();
+       rk3036_hdmi_reset(hdmi_drv);
+
+       if (hdmi_drv->hdcp_power_on_cb)
+               rc = hdmi_drv->hdcp_power_on_cb();
+
+       return rc;
+}
diff --git a/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.h
new file mode 100755 (executable)
index 0000000..d19c180
--- /dev/null
@@ -0,0 +1,360 @@
+#ifndef _RK3036_HDMI_HW_H
+#define _RK3036_HDMI_HW_H
+
+#include <linux/rockchip/iomap.h>
+#include <linux/delay.h>
+
+enum PWR_MODE {
+       NORMAL,
+       LOWER_PWR,
+};
+enum {
+       OUTPUT_DVI = 0,
+       OUTPUT_HDMI
+};
+
+#ifdef RK616_USE_MCLK_12M
+#define HDMI_SYS_FREG_CLK        12000000
+#else
+#define HDMI_SYS_FREG_CLK        11289600
+#endif
+
+#define HDMI_SCL_RATE            (100*1000)
+#define DDC_BUS_FREQ_L                 0x4b
+#define DDC_BUS_FREQ_H                 0x4c
+
+#define SYS_CTRL                       0x00
+#define m_RST_ANALOG           (1 << 6)
+#define v_RST_ANALOG           (0 << 6)
+#define v_NOT_RST_ANALOG       (1 << 6)
+
+#define m_RST_DIGITAL          (1 << 5)
+#define v_RST_DIGITAL          (0 << 5)
+#define v_NOT_RST_DIGITAL      (1 << 5)
+
+#define m_REG_CLK_INV          (1 << 4)
+#define v_REG_CLK_NOT_INV      (0 << 4)
+#define v_REG_CLK_INV          (1 << 4)
+#define m_VCLK_INV             (1 << 3)
+#define v_VCLK_NOT_INV         (0 << 3)
+#define v_VCLK_INV             (1 << 3)
+#define m_REG_CLK_SOURCE       (1 << 2)
+#define v_REG_CLK_SOURCE_TMDS  (0 << 2)
+#define v_REG_CLK_SOURCE_SYS   (1 << 2)
+#define m_POWER                        (1 << 1)
+#define v_PWR_ON               (0 << 1)
+#define v_PWR_OFF              (1 << 1)
+#define m_INT_POL              (1 << 0)
+#define v_INT_POL_HIGH         1
+#define v_INT_POL_LOW          0
+
+#define VIDEO_CONTRL1                  0x01
+#define m_VIDEO_INPUT_FORMAT   (7 << 1)
+#define m_DE_SOURCE            (1 << 0)
+enum {
+       VIDEO_INPUT_SDR_RGB444 = 0,
+       VIDEO_INPUT_DDR_RGB444 = 5,
+       VIDEO_INPUT_DDR_YCBCR422 = 6
+};
+#define v_VIDEO_INPUT_FORMAT(n)        (n << 1)
+#define v_DE_EXTERNAL          1
+#define v_DE_INTERANL          0
+
+#define VIDEO_CONTRL2                  0x02
+#define m_VIDEO_OUTPUT_FORMAT  (3 << 6)
+#define m_VIDEO_INPUT_BITS     (3 << 4)
+#define v_VIDEO_OUTPUT_FORMAT(n)(n << 6)
+#define v_VIDEO_INPUT_BITS(n)  (n << 4)
+enum {
+       VIDEO_INPUT_12BITS = 0,
+       VIDEO_INPUT_10BITS,
+       VIDEO_INPUT_8BITS
+};
+#define VIDEO_CONTRL3                  0x04
+#define m_SOF                  (1 << 3)
+#define m_CSC                  (1 << 0)
+#define v_SOF_ENABLE           (0 << 3)
+#define v_SOF_DISABLE          (1 << 3)
+#define v_CSC_ENABLE           1
+#define v_CSC_DISABLE          0
+
+#define AV_MUTE                                0x05
+#define m_AVMUTE_CLEAR         (1 << 7)
+#define m_AVMUTE_ENABLE                (1 << 6)
+#define m_AUDIO_MUTE           (1 << 1)
+#define m_VIDEO_BLACK          (1 << 0)
+#define v_AUDIO_MUTE(n)                (n << 1)
+#define v_VIDEO_MUTE(n)                (n << 0)
+
+#define VIDEO_TIMING_CTL               0x08
+#define v_HSYNC_POLARITY(n)    (n << 3)
+#define v_VSYNC_POLARITY(n)    (n << 2)
+#define v_INETLACE(n)          (n << 1)
+#define v_EXTERANL_VIDEO(n)    (n << 0)
+
+#define VIDEO_EXT_HTOTAL_L             0x09
+#define VIDEO_EXT_HTOTAL_H             0x0a
+#define VIDEO_EXT_HBLANK_L             0x0b
+#define VIDEO_EXT_HBLANK_H             0x0c
+#define VIDEO_EXT_HDELAY_L             0x0d
+#define VIDEO_EXT_HDELAY_H             0x0e
+#define VIDEO_EXT_HDURATION_L          0x0f
+#define VIDEO_EXT_HDURATION_H          0x10
+#define VIDEO_EXT_VTOTAL_L             0x11
+#define VIDEO_EXT_VTOTAL_H             0x12
+#define VIDEO_EXT_VBLANK               0x13
+#define VIDEO_EXT_VDELAY               0x14
+#define VIDEO_EXT_VDURATION            0x15
+
+#define AUDIO_CTRL1                    0x35
+enum {
+       CTS_SOURCE_INTERNAL = 0,
+       CTS_SOURCE_EXTERNAL
+};
+#define v_CTS_SOURCE(n)                (n << 7)
+enum {
+       DOWNSAMPLE_DISABLE = 0,
+       DOWNSAMPLE_1_2,
+       DOWNSAMPLE_1_4
+};
+#define v_DOWN_SAMPLE(n)       (n << 5)
+enum {
+       AUDIO_SOURCE_IIS = 0,
+       AUDIO_SOURCE_SPDIF
+};
+#define v_AUDIO_SOURCE(n)      (n << 3)
+#define v_MCLK_ENABLE(n)       (n << 2)
+enum {
+       MCLK_128FS = 0,
+       MCLK_256FS,
+       MCLK_384FS,
+       MCLK_512FS
+};
+#define v_MCLK_RATIO(n)                (n)
+
+#define AUDIO_SAMPLE_RATE              0x37
+enum {
+       AUDIO_32K = 0x3,
+       AUDIO_441K = 0x0,
+       AUDIO_48K = 0x2,
+       AUDIO_882K = 0x8,
+       AUDIO_96K = 0xa,
+       AUDIO_1764K = 0xc,
+       AUDIO_192K = 0xe,
+};
+
+#define AUDIO_I2S_MODE                 0x38
+enum {
+       I2S_CHANNEL_1_2 = 1,
+       I2S_CHANNEL_3_4 = 3,
+       I2S_CHANNEL_5_6 = 7,
+       I2S_CHANNEL_7_8 = 0xf
+};
+#define v_I2S_CHANNEL(n)       ((n) << 2)
+enum {
+       I2S_STANDARD = 0,
+       I2S_LEFT_JUSTIFIED,
+       I2S_RIGHT_JUSTIFIED
+};
+#define v_I2S_MODE(n)          (n)
+
+#define AUDIO_I2S_MAP                  0x39
+#define AUDIO_I2S_SWAPS_SPDIF          0x3a
+#define v_SPIDF_FREQ(n)                (n)
+
+#define N_32K          0x1000
+#define N_441K         0x1880
+#define N_882K         0x3100
+#define N_1764K                0x6200
+#define N_48K          0x1800
+#define N_96K          0x3000
+#define N_192K         0x6000
+
+#define AUDIO_N_H                      0x3f
+#define AUDIO_N_M                      0x40
+#define AUDIO_N_L                      0x41
+
+#define AUDIO_CTS_H                    0x45
+#define AUDIO_CTS_M                    0x46
+#define AUDIO_CTS_L                    0x47
+
+#define DDC_CLK_L                      0x4b
+#define DDC_CLK_H                      0x4c
+
+#define EDID_SEGMENT_POINTER           0x4d
+#define EDID_WORD_ADDR                 0x4e
+#define EDID_FIFO_OFFSET               0x4f
+#define EDID_FIFO_ADDR                 0x50
+
+/* CONTROL_PACKET_BUF_INDEX */
+#define CONTROL_PACKET_BUF_INDEX       0x9f
+enum {
+       INFOFRAME_AVI = 0x06,
+       INFOFRAME_AAI = 0x08
+};
+#define CONTROL_PACKET_ADDR            0xa0
+
+#define SIZE_AVI_INFOFRAME             0x11    /* 14 bytes */
+#define SIZE_AUDIO_INFOFRAME           0x0F    /* 15 bytes */
+enum {
+       AVI_COLOR_MODE_RGB = 0,
+       AVI_COLOR_MODE_YCBCR422,
+       AVI_COLOR_MODE_YCBCR444
+};
+enum {
+       AVI_COLORIMETRY_NO_DATA = 0,
+       AVI_COLORIMETRY_SMPTE_170M,
+       AVI_COLORIMETRY_ITU709,
+       AVI_COLORIMETRY_EXTENDED
+};
+enum {
+       AVI_CODED_FRAME_ASPECT_NO_DATA,
+       AVI_CODED_FRAME_ASPECT_4_3,
+       AVI_CODED_FRAME_ASPECT_16_9
+};
+enum {
+       ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
+       ACTIVE_ASPECT_RATE_4_3,
+       ACTIVE_ASPECT_RATE_16_9,
+       ACTIVE_ASPECT_RATE_14_9
+};
+
+#define HDCP_CTRL                      0x52
+#define m_HDMI_DVI             (1 << 1)
+#define v_HDMI_DVI(n)          (n << 1)
+
+#define INTERRUPT_MASK1                        0xc0
+#define INTERRUPT_STATUS1              0xc1
+#define        m_INT_ACTIVE_VSYNC      (1 << 5)
+#define m_INT_EDID_READY       (1 << 2)
+
+#define INTERRUPT_MASK2                        0xc2
+#define INTERRUPT_STATUS2              0xc3
+#define m_INT_HDCP_ERR         (1 << 7)
+#define m_INT_BKSV_FLAG                (1 << 6)
+#define m_INT_HDCP_OK          (1 << 4)
+
+#define HDMI_STATUS                    0xc8
+       #define m_HOTPLUG       (1 << 7)
+       #define m_MASK_INT_HOTPLUG      (1 << 5)
+       #define m_INT_HOTPLUG           (1 << 1)
+
+
+#define HDMI_COLORBAR                   0xc9
+
+#define PHY_SYNC                       0xce    /* sync phy parameter */
+#define PHY_SYS_CTL                    0xe0
+#define m_TMDS_CLK_SOURCE      (1 << 5)
+#define v_TMDS_FROM_PLL                (0 << 5)
+#define v_TMDS_FROM_GEN                (1 << 5)
+#define m_PHASE_CLK            (1 << 4)
+#define v_DEFAULT_PHASE                (0 << 4)
+#define v_SYNC_PHASE           (1 << 4)
+#define m_TMDS_CURRENT_PWR     (1 << 3)
+#define v_TURN_ON_CURRENT      (0 << 3)
+#define v_CAT_OFF_CURRENT      (1 << 3)
+#define m_BANDGAP_PWR          (1 << 2)
+#define v_BANDGAP_PWR_UP       (0 << 2)
+#define v_BANDGAP_PWR_DOWN     (1 << 2)
+#define m_PLL_PWR              (1 << 1)
+#define v_PLL_PWR_UP           (0 << 1)
+#define v_PLL_PWR_DOWN         (1 << 1)
+#define m_TMDS_CHG_PWR         (1 << 0)
+#define v_TMDS_CHG_PWR_UP      (0 << 0)
+#define v_TMDS_CHG_PWR_DOWN    (1 << 0)
+
+#define PHY_CHG_PWR                    0xe1
+#define v_CLK_CHG_PWR(n)       ((n & 1) << 3)
+#define v_DATA_CHG_PWR(n)      ((n & 7) << 0)
+
+#define PHY_DRIVER                     0xe2
+#define v_CLK_MAIN_DRIVER(n)   (n << 4)
+#define v_DATA_MAIN_DRIVER(n)  (n << 0)
+
+#define PHY_PRE_EMPHASIS               0xe3
+#define v_PRE_EMPHASIS(n)      ((n & 7) << 4)
+#define v_CLK_PRE_DRIVER(n)    ((n & 3) << 2)
+#define v_DATA_PRE_DRIVER(n)   ((n & 3) << 0)
+
+#define PHY_FEEDBACK_DIV_RATIO_LOW     0xe7
+#define v_FEEDBACK_DIV_LOW(n)  (n & 0xff)
+#define PHY_FEEDBACK_DIV_RATIO_HIGH    0xe8
+#define v_FEEDBACK_DIV_HIGH(n) (n & 1)
+
+#define PHY_PRE_DIV_RATIO              0xed
+#define v_PRE_DIV_RATIO(n)     (n & 0x1f)
+
+
+/*-----START----- HDMI CEC CTRL------START------*/
+#define CEC_CTRL               0xd0
+       #define m_ADJUST_FOR_HISENSE    (1 << 6)
+       #define m_REJECT_RX_BROADCAST   (1 << 5)
+       #define m_BUSFREETIME_ENABLE    (1 << 2)
+       #define m_REJECT_RX                             (1 << 1)
+       #define m_START_TX                              (1 << 0)
+
+#define CEC_DATA               0xd1
+#define CEC_TX_OFFSET  0xd2
+#define CEC_RX_OFFSET  0xd3
+#define CEC_CLK_H              0xd4
+#define CEC_CLK_L              0xd5
+#define CEC_TX_LENGTH  0xd6
+#define CEC_RX_LENGTH  0xd7
+#define CEC_TX_INT_MASK        0xd8
+       #define m_TX_DONE                       (1 << 3)
+       #define m_TX_NOACK                      (1 << 2)
+       #define m_TX_BROADCAST_REJ      (1 << 1)
+       #define m_TX_BUSNOTFREE         (1 << 0)
+
+#define CEC_RX_INT_MASK 0xd9
+       #define m_RX_LA_ERR                     (1 << 4)
+       #define m_RX_GLITCH                     (1 << 3)
+       #define m_RX_DONE                       (1 << 0)
+
+#define CEC_TX_INT             0xda
+#define CEC_RX_INT             0xdb
+#define CEC_BUSFREETIME_L      0xdc
+#define CEC_BUSFREETIME_H      0xdd
+#define CEC_LOGICADDR          0xde
+/*------END------ HDMI CEC CTRL------END-------*/
+
+
+static inline int hdmi_readl(struct rk_hdmi_device *hdmi_dev, u16 offset,
+                            u32 *val)
+{
+       int ret = 0;
+
+       *val = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04);
+       return ret;
+}
+
+static inline int hdmi_writel(struct rk_hdmi_device *hdmi_dev, u16 offset,
+                             u32 val)
+{
+       int ret = 0;
+
+       writel_relaxed(val, hdmi_dev->regbase + (offset) * 0x04);
+       return ret;
+}
+
+static inline int hdmi_msk_reg(struct rk_hdmi_device *hdmi_dev, u16 offset,
+                              u32 msk, u32 val)
+{
+       int ret = 0;
+       u32 temp;
+
+       temp = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04) & (0xFF - (msk));
+       writel_relaxed(temp | ((val) & (msk)), hdmi_dev->regbase + (offset) * 0x04);
+       return ret;
+}
+static inline void rk3036_hdmi_reset_pclk(void)
+{
+       writel_relaxed(0x00010001, RK_CRU_VIRT+ 0x128);
+       msleep(100);
+       writel_relaxed(0x00010000, RK_CRU_VIRT + 0x128);
+}
+
+extern int rk3036_hdmi_initial(struct hdmi *hdmi);
+extern void rk3036_hdmi_irq(struct hdmi *hdmi);
+
+#endif
old mode 100644 (file)
new mode 100755 (executable)
index 35c28d9..c599106
@@ -558,7 +558,7 @@ int rk3288_hdmi_video_sampler(struct hdmi *hdmi_drv,
 }
 
 #ifdef HDMI_DEBUG
-static int rk3288_hdmi_read_phy(struct rk3288_hdmi_device *hdmi_dev,
+static int __maybe_unused rk3288_hdmi_read_phy(struct rk3288_hdmi_device *hdmi_dev,
                                int reg_addr)
 {
        int trytime = 2, i = 0, op_status = 0;
index 1262dd579c9cbc3c738e1762928811585d2042dd..1a5f5be79ecd45eb6965bb58788540601687288a 100755 (executable)
@@ -92,7 +92,7 @@ static const struct file_operations rk616_hdmi_reg_fops = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_RK3026)
+#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
 static int rk616_hdmi_clk_enable(struct rk_hdmi_device *hdmi_dev)
 {
        if (!hdmi_dev->clk_on) {
@@ -249,7 +249,6 @@ static void __maybe_unused rk616_irq_work_func(struct work_struct *work)
        dev_info(hdmi_drv->dev, "func: %s, enable_irq\n", __func__);
        enable_irq(hdmi_drv->irq);
 }
-
 static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
 {
        struct work_struct *rk616_irq_work_struct;
@@ -261,7 +260,7 @@ static irqreturn_t rk616_hdmi_irq(int irq, void *dev_id)
                disable_irq_nosync(hdmi_drv->irq);
                queue_work(hdmi_drv->workqueue, rk616_irq_work_struct);
        } else {
-               /* 3028a hdmi */
+               /* 3028a/3036 hdmi */
                if ((hdmi_drv->suspend == 0) && (hdmi_drv->enable == 1)) {
                        hdmi_dbg(hdmi_drv->dev,
                                 "line = %d, rk616_hdmi_irq irq triggered.\n",
@@ -284,14 +283,16 @@ static int rk616_hdmi_drv_init(struct hdmi *hdmi_drv)
        lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;
        /* lcdc source select */
        /* wait to modify!!
-#if defined(CONFIG_ARCH_RK3026)
+#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
        grf_writel(HDMI_SEL_LCDC(lcdc_id), RK3036_GRF_SOC_CON6);
 #endif
        */
+       lcdc_id = 0;
        if (lcdc_id == 0)
                hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
        else
                hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
+
        if (IS_ERR(hdmi_drv->lcdc)) {
                dev_err(hdmi_drv->dev,
                        "can not connect to video source lcdc\n");
@@ -310,10 +311,20 @@ static int rk616_hdmi_drv_init(struct hdmi *hdmi_drv)
        return ret;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id rk616_hdmi_of_match[] = {
+       {.compatible = "rockchip,rk616-hdmi",},
+       {.compatible = "rockchip,rk3036-hdmi",},
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
+#endif
+
 static int rk616_hdmi_probe(struct platform_device *pdev)
 {
        int ret;
-       struct rk_hdmi_device *hdmi_dev;
+       //struct rk_hdmi_device *hdmi_dev;
        struct hdmi *hdmi_drv;
        struct resource __maybe_unused *mem;
        struct resource __maybe_unused *res;
@@ -330,7 +341,7 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, hdmi_dev);
        spin_lock_init(&hdmi_dev->reg_lock);
 
-#ifdef CONFIG_ARCH_RK3026
+#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
        hdmi_dev->rk616_drv = NULL;
 #else
        hdmi_dev->rk616_drv = dev_get_drvdata(pdev->dev.parent);
@@ -340,9 +351,6 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
        }
 #endif
 
-       if (rk616_hdmi_drv_init(hdmi_drv))
-               goto err0;
-
 #ifdef CONFIG_SWITCH
        hdmi_drv->switch_hdmi.name = "hdmi";
        switch_dev_register(&(hdmi_drv->switch_hdmi));
@@ -354,7 +362,7 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&(hdmi_drv->delay_work), hdmi_work);
        INIT_DELAYED_WORK(&hdmi_dev->rk616_delay_work, rk616_delay_work_func);
 
-#ifdef CONFIG_ARCH_RK3026
+#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
        /* enable clk */
        hdmi_dev->hclk = devm_clk_get(hdmi_drv->dev, "pclk_hdmi");
        if (IS_ERR(hdmi_dev->hclk)) {
@@ -362,12 +370,12 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
                ret = -ENXIO;
                goto err1;
        }
-       rk616_hdmi_clk_enable();        /* enable clk may move to irq func */
-
+       rk616_hdmi_clk_enable(hdmi_dev);        /* enable clk may move to irq func */
+       hdmi_dev->hclk_rate = clk_get_rate(hdmi_dev->hclk);
        /* request and remap iomem */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
-               dev_err(hdmi_dev->dev, "Unable to get register resource\n");
+               dev_err(hdmi_drv->dev, "Unable to get register resource\n");
                ret = -ENXIO;
                goto err2;
        }
@@ -380,12 +388,14 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
                        ret);
                goto err2;
        }
+       if (rk616_hdmi_drv_init(hdmi_drv))
+               goto err0;
 
        /* get the IRQ */
        hdmi_drv->irq = platform_get_irq(pdev, 0);
        if (hdmi_drv->irq <= 0) {
-               dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n",
-                       hdmi->irq);
+               dev_err(hdmi_drv->dev, "failed to get hdmi irq resource (%d).\n",
+                       hdmi_drv->irq);
                hdmi_drv->irq = 0;
        } else {
                /* request the IRQ */
@@ -418,6 +428,8 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
                        ret = -ENXIO;
                        goto err1;
                }
+               if (rk616_hdmi_drv_init(hdmi_drv))
+                       goto err0;
 
                /* request the IRQ */
                ret = devm_request_irq(hdmi_drv->dev, hdmi_drv->irq,
@@ -436,6 +448,8 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
 
 #endif
 
+       //rk616_hdmi_work(hdmi_drv);
+
 #if defined(CONFIG_DEBUG_FS)
        if (hdmi_dev->rk616_drv && hdmi_dev->rk616_drv->debugfs_dir) {
                debugfs_create_file("hdmi", S_IRUSR,
@@ -457,9 +471,10 @@ static int rk616_hdmi_probe(struct platform_device *pdev)
        queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->rk616_delay_work,
                           msecs_to_jiffies(0));
        dev_info(hdmi_drv->dev, "rk616 hdmi probe success.\n");
+
        return 0;
 
-#if defined(CONFIG_ARCH_RK3026)
+#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
 err2:
        rk616_hdmi_clk_disable(hdmi_dev);
 #endif
@@ -520,7 +535,8 @@ static int rk616_hdmi_remove(struct platform_device *pdev)
 
 static void rk616_hdmi_shutdown(struct platform_device *pdev)
 {
-       struct hdmi *hdmi_drv;
+       struct rk_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
+       struct hdmi *hdmi_drv = NULL;
 
        if (hdmi_dev) {
                hdmi_drv = &hdmi_dev->driver;
@@ -541,26 +557,14 @@ static void rk616_hdmi_shutdown(struct platform_device *pdev)
        hdmi_dbg(hdmi_drv->dev, "rk616 hdmi shut down.\n");
 }
 
-#if defined(CONFIG_OF)
-static const struct of_device_id rk616_hdmi_of_match[] = {
-       {.compatible = "rockchip,rk616-hdmi",},
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, rk616_hdmi_of_match);
-#endif
 
 static struct platform_driver rk616_hdmi_driver = {
        .probe = rk616_hdmi_probe,
        .remove = rk616_hdmi_remove,
        .driver = {
-#ifdef CONFIG_ARCH_RK3026
-                  .name = "rk3026-hdmi",
-#else
                   .name = "rk616-hdmi",
-#endif
                   .owner = THIS_MODULE,
-                  .of_match_table = of_match_ptr(rk616_hdmi_of_match),
+                  .of_match_table = of_match_ptr(rk616_hdmi_of_match),            
                   },
        .shutdown = rk616_hdmi_shutdown,
 };
index 35ff0927a75e5a2c1609f2967ac0491cb6326ce2..5184a68149f321aa2e38a2eae7aa06effad2c4a6 100755 (executable)
@@ -30,10 +30,12 @@ struct rk_hdmi_device {
        int regsize_phy;
        struct clk *pd;
        struct clk *hclk;       /* HDMI AHP clk */
+       struct clk *pclk;       /* HDMI APB clk */
        struct delayed_work rk616_delay_work;
        struct work_struct rk616_irq_work_struct;
        struct mfd_rk616 *rk616_drv;
        struct dentry *debugfs_dir;
+       unsigned int hclk_rate;
 };
 
 #endif /* __RK616_HDMI_H__ */
index 4b51345b6a3fb327a077ed07a7f02db75c13e601..23febddfa9ae6c7ee9b9498132c030ef98f3808e 100755 (executable)
@@ -5,7 +5,8 @@
 #include "rk616_hdmi.h"
 #include "rk616_hdmi_hw.h"
 
-#ifndef CONFIG_ARCH_RK3026
+#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
+
 static int rk616_set_polarity(struct mfd_rk616 *rk616_drv, int vic)
 {
        u32 val;
@@ -74,6 +75,31 @@ static int rk616_hdmi_init_pol_set(struct mfd_rk616 *rk616_drv, int pol)
 }
 #endif
 
+static int __maybe_unused rk616_hdmi_show_reg(struct hdmi *hdmi_drv)
+{
+       int i = 0;
+       u32 val = 0;
+       struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
+                                                      struct rk_hdmi_device,
+                                                      driver);
+
+       printk("\n>>>rk616_ctl reg");
+       for (i = 0; i < 16; i++)
+               printk(" %2x", i);
+
+       printk("\n-----------------------------------------------------------------");
+
+       for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
+               hdmi_readl(hdmi_dev, i, &val);
+               if (i % 16 == 0)
+                       printk("\n>>>rk616_ctl %2x:", i);
+               printk(" %02x", val);
+       }
+       printk("\n-----------------------------------------------------------------\n");
+
+       return 0;
+}
+
 static inline void delay100us(void)
 {
        msleep(1);
@@ -117,7 +143,7 @@ static void rk616_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
        case NORMAL:
                hdmi_dbg(hdmi_drv->dev,
                         "%s change pwr_mode NORMAL pwr_mode = %d, mode = %d\n",
-                        __func__, hdmi->pwr_mode, mode);
+                        __func__, hdmi_drv->pwr_mode, mode);
                rk616_hdmi_sys_power(hdmi_drv, false);
                if (!(hdmi_drv->set_vif)
                    && (hdmi_drv->vic == HDMI_1920x1080p_60Hz
@@ -129,11 +155,16 @@ static void rk616_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
                        hdmi_writel(hdmi_dev, PHY_DRIVER, 0x99);
                        hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x0f);
                }
-
-               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x2d);
-               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x2c);
-               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x28);
-               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x20);
+#ifdef SOC_CONFIG_RK3036
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x15);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x14);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x10);
+#else
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2d);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2c);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x28);
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x20);
+#endif
                hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
                hdmi_writel(hdmi_dev, 0xce, 0x00);
                hdmi_writel(hdmi_dev, 0xce, 0x01);
@@ -143,13 +174,17 @@ static void rk616_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
        case LOWER_PWR:
                hdmi_dbg(hdmi_drv->dev,
                         "%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
-                        __func__, hdmi->pwr_mode, mode);
+                        __func__, hdmi_drv->pwr_mode, mode);
                rk616_hdmi_av_mute(hdmi_drv, 0);
                rk616_hdmi_sys_power(hdmi_drv, false);
                hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
                hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
                hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
-               hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x2f);
+#ifdef SOC_CONFIG_RK3036
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x17);
+#else
+               hdmi_writel(hdmi_dev, PHY_SYS_CTL,0x2f);
+#endif
                break;
        default:
                hdmi_dbg(hdmi_drv->dev, "unkown rk616 hdmi pwr mode %d\n",
@@ -176,6 +211,12 @@ int rk616_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
        else
                return HDMI_HPD_REMOVED;
 }
+int rk616_hdmi_insert(struct hdmi *hdmi_drv)
+{
+       rk616_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
+       return 0;
+}
+
 
 int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
 {
@@ -190,14 +231,16 @@ int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
        struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
                                                       struct rk_hdmi_device,
                                                       driver);
-
        if (block % 2)
                offset = HDMI_EDID_BLOCK_SIZE;
 
        if (block / 2)
                segment = 1;
-
+#ifdef SOC_CONFIG_RK3036
+       ddc_bus_freq = (hdmi_dev->hclk_rate>> 2) / HDMI_SCL_RATE;
+#else
        ddc_bus_freq = (HDMI_SYS_FREG_CLK >> 2) / HDMI_SCL_RATE;
+#endif
        hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
        hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
 
@@ -207,10 +250,15 @@ int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
        disable_irq(hdmi_drv->irq);
 
        /* Enable edid interrupt */
+#ifdef SOC_CONFIG_RK3036
+       hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
+#else
        hdmi_writel(hdmi_dev, INTERRUPT_MASK1,
                    m_INT_HOTPLUG | m_INT_EDID_READY);
+#endif
 
        for (trytime = 0; trytime < 10; trytime++) {
+               checksum = 0;
                hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
 
                /* Set edid fifo first addr */
@@ -240,10 +288,9 @@ int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
                                checksum += c;
 #ifdef HDMI_DEBUG
                                if (j % 16 == 0)
-                                       dev_info(hdmi_drv->dev, "\n>>>0x%02x: ",
-                                                j);
+                                       printk("\n>>>0x%02x: ",j);
 
-                               dev_info(hdmi_drv->dev, "0x%02x ", c);
+                               printk("0x%02x ", c);
 #endif
                        }
 
@@ -259,8 +306,12 @@ int rk616_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
                        }
                }
        }
-
+       //close edid irq
+#ifdef SOC_CONFIG_RK3036
+       hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
+#else
        hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
+#endif
        enable_irq(hdmi_drv->irq);
 
        return ret;
@@ -401,9 +452,9 @@ static int rk616_hdmi_config_video(struct hdmi *hdmi_drv,
        if (vpara->output_mode == OUTPUT_HDMI) {
                rk616_hdmi_config_avi(hdmi_drv, vpara->vic,
                                      vpara->output_color);
-               hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __func__);
+               hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n", __func__);
        } else {
-               hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __func__);
+               hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __func__);
        }
 
        if (hdmi_drv->set_vif) {
@@ -569,19 +620,27 @@ void rk616_hdmi_work(struct hdmi *hdmi_drv)
        struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
                                                       struct rk_hdmi_device,
                                                       driver);
-
-       hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
-       if (interrupt)
+#ifdef SOC_CONFIG_RK3036
+       hdmi_readl(hdmi_dev, HDMI_STATUS,&interrupt);
+       if(interrupt){
+               hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
+       }
+       if (interrupt & m_INT_HOTPLUG)
+#else
+       hdmi_readl(hdmi_dev, INTERRUPT_STATUS1,&interrupt);
+       if(interrupt){
                hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
-
-       if (interrupt & m_HOTPLUG) {
+       }
+       if (interrupt & m_HOTPLUG)
+#endif
+       {
                if (hdmi_drv->state == HDMI_SLEEP)
                        hdmi_drv->state = WAIT_HOTPLUG;
 
                queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
                                   msecs_to_jiffies(40));
 
-       }
+       }//plug out?
 
        if (hdmi_drv->hdcp_irq_cb)
                hdmi_drv->hdcp_irq_cb(0);
@@ -602,14 +661,21 @@ static void rk616_hdmi_reset(struct hdmi *hdmi_drv)
        msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
        val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
        hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
-       hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);
-       rk616_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
+#ifdef SOC_CONFIG_RK3036
+       hdmi_readl(hdmi_dev, HDMI_STATUS,&val);//enable hpg
+       val |= m_MASK_INT_HOTPLUG;
+       //hdmi_writel(hdmi_dev, HDMI_STATUS,val);//do this will lead to clear hpd irq
+#else
+       hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_HOTPLUG);  
+#endif
+       rk616_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR); // hjc delete for audis
+       //rk616_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
 }
 
 int rk616_hdmi_initial(struct hdmi *hdmi_drv)
 {
        int rc = HDMI_ERROR_SUCESS;
-#ifndef CONFIG_ARCH_RK3026
+#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
        struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
                                                       struct rk_hdmi_device,
                                                       driver);
@@ -623,8 +689,12 @@ int rk616_hdmi_initial(struct hdmi *hdmi_drv)
        hdmi_drv->config_audio = rk616_hdmi_config_audio;
        hdmi_drv->detect_hotplug = rk616_hdmi_detect_hotplug;
        hdmi_drv->read_edid = rk616_hdmi_read_edid;
+       hdmi_drv->insert    = rk616_hdmi_insert;
 
-#ifdef CONFIG_ARCH_RK3026
+#if defined(CONFIG_ARCH_RK3026)
+       rk3028_hdmi_reset_pclk();
+       rk616_hdmi_reset(hdmi_drv);
+#elif defined(SOC_CONFIG_RK3036)
        rk3028_hdmi_reset_pclk();
        rk616_hdmi_reset(hdmi_drv);
 #else
index 1d3c24417d751eba87f44d7fbd6026d28c91972c..1bd7e5d02ff92c3d7fd3d691baf4c518cbada107 100755 (executable)
@@ -1,6 +1,8 @@
 #ifndef _RK616_HDMI_HW_H
 #define _RK616_HDMI_HW_H
 
+#define SOC_CONFIG_RK3036
+#include <linux/rockchip/iomap.h>
 #define RK616_HDMI_BASE 0x400
 enum PWR_MODE {
        NORMAL,
@@ -223,7 +225,9 @@ enum {
 
 #define INTERRUPT_MASK1                        0xc0
 #define INTERRUPT_STATUS1              0xc1
+#ifndef SOC_CONFIG_RK3036
 #define m_INT_HOTPLUG          (1 << 7)
+#endif
 #define        m_INT_ACTIVE_VSYNC      (1 << 5)
 #define m_INT_EDID_READY       (1 << 2)
 
@@ -234,9 +238,15 @@ enum {
 #define m_INT_HDCP_OK          (1 << 4)
 
 #define HDMI_STATUS                    0xc8
-#define m_HOTPLUG              (1 << 7)
-#define m_DDC_SDA              (1 << 5)
-#define m_DDC_SDC              (1 << 4)
+       #define m_HOTPLUG       (1 << 7)
+       #ifdef SOC_CONFIG_RK3036
+       #define m_MASK_INT_HOTPLUG      (1 << 5)
+       #define m_INT_HOTPLUG           (1 << 1)
+       #else
+       #define m_DDC_SDA       (1 << 5)
+       #define m_DDC_SDC       (1 << 4)        
+       #endif
+
 
 #define HDMI_COLORBAR                   0xc9
 
@@ -282,7 +292,7 @@ enum {
 #define PHY_PRE_DIV_RATIO              0xed
 #define v_PRE_DIV_RATIO(n)     (n & 0x1f)
 
-#ifndef CONFIG_ARCH_RK3026
+#if !defined(CONFIG_ARCH_RK3026) && !defined(SOC_CONFIG_RK3036)
 static inline int hdmi_readl(struct rk_hdmi_device *hdmi_dev,
                             u16 offset, u32 *val)
 {
@@ -342,18 +352,19 @@ static inline int hdmi_msk_reg(struct rk_hdmi_device *hdmi_dev, u16 offset,
        int ret = 0;
        u32 temp;
 
-       temp = readl_relaxed(hdmi->regbase + (offset) * 0x04) & (0xFF - (msk));
-       writel_relaxed(temp | ((val) & (msk)), hdmi->regbase + (offset) * 0x04);
+       temp = readl_relaxed(hdmi_dev->regbase + (offset) * 0x04) & (0xFF - (msk));
+       writel_relaxed(temp | ((val) & (msk)), hdmi_dev->regbase + (offset) * 0x04);
        return ret;
 }
-
+#if defined(CONFIG_ARCH_RK3026) || defined(SOC_CONFIG_RK3036)
 static inline void rk3028_hdmi_reset_pclk(void)
 {
-       writel_relaxed(0x00010001, RK2928_CRU_BASE + 0x128);
+       writel_relaxed(0x00010001, RK_CRU_VIRT+ 0x128);
        msleep(100);
-       writel_relaxed(0x00010000, RK2928_CRU_BASE + 0x128);
+       writel_relaxed(0x00010000, RK_CRU_VIRT + 0x128);
 }
 #endif
+#endif
 
 extern int rk616_hdmi_initial(struct hdmi *hdmi);
 extern void rk616_hdmi_work(struct hdmi *hdmi);
index a65e7aa740f1b90f9381f4ad66a5353b51893a6c..6ff89a998cfc90b324e397eb2410e2b89ed36fb9 100755 (executable)
 /* default HDMI output video mode */
 #define HDMI_VIDEO_DEFAULT_MODE                        HDMI_1280x720p_60Hz
 
+#define HDMI_720X480P_60HZ_VIC         2
+#define HDMI_720X480I_60HZ_VIC         6
+#define HDMI_720X576P_50HZ_VIC         17
+#define HDMI_720X576I_50HZ_VIC         21
+#define HDMI_1280X720P_50HZ_VIC                19
+#define HDMI_1280X720P_60HZ_VIC                4
+#define HDMI_1920X1080P_50HZ_VIC       31
+#define HDMI_1920X1080I_50HZ_VIC       20
+#define HDMI_1920X1080P_60HZ_VIC       16
+#define HDMI_1920X1080I_60HZ_VIC       5
+#define HDMI_3840X2160P_24HZ_VIC       93
+#define HDMI_3840X2160P_25HZ_VIC       94
+#define HDMI_3840X2160P_30HZ_VIC       95
+#define HDMI_3840X2160P_50HZ_VIC       96
+#define HDMI_3840X2160P_60HZ_VIC       97
+#define HDMI_4096X2160P_24HZ_VIC       98
+#define HDMI_4096X2160P_25HZ_VIC       99
+#define HDMI_4096X2160P_30HZ_VIC       100
+#define HDMI_4096X2160P_50HZ_VIC       101
+#define HDMI_4096X2160P_60HZ_VIC       102
+
 /* HDMI video source */
 enum {
        HDMI_SOURCE_LCDC0 = 0,
@@ -263,6 +284,7 @@ struct hdmi_edid {
        struct hdmi_audio *audio;       /* Device supported audio info */
        int audio_num;                  /* Device supported audio type number */
        int base_audio_support;         /* Device supported base audio */
+       unsigned int  cecaddress;                       //CEC physical address
 };
 
 /* RK HDMI Video Configure Parameters */
@@ -340,11 +362,16 @@ struct hdmi {
        int (*set_vif) (struct hdmi *hdmi, struct rk_screen *screen,
                        bool connect);
 
-       /* call back for hdcp operatoion */
+       /* call back for hdcp operation */
        void (*hdcp_cb) (void);
        void (*hdcp_irq_cb) (int);
        int (*hdcp_power_on_cb) (void);
        void (*hdcp_power_off_cb) (void);
+
+       /*call back for cec operation*/
+       void (*cec_irq) (void);
+       void (*cec_set_device_pa) (int);
+       int (*cec_enumerate) (void);
 };
 
 #define hdmi_err(dev, format, arg...)          \
index e0238ff47970a78189bdbda9bfde3e04c57fcc00..7921c8f5e11a603309e08e1bf86471d29701918e 100755 (executable)
@@ -223,6 +223,10 @@ static int hdmi_edid_parse_cea_sdb(unsigned char *buf, struct hdmi_edid *pedid)
        if (IEEEOUI == 0x0c03)
                pedid->sink_hdmi = 1;
 
+       pedid->cecaddress = buf[cur_offset + 5];
+       pedid->cecaddress |= buf[cur_offset + 4] << 8;
+       hdmi_edid_debug("[EDID-CEA] CEC Physical addres is 0x%08x.\n", pedid->cecaddress);
+
        if (count > 5) {
                pedid->deepcolor = (buf[6] >> 3) & 0x0F;
                supports_ai = buf[6] >> 7;
index fe65b3760f7696972e795e7c15e68ea8ae725dc8..497c55d7f5a14f03968537e2e87113c74690805e 100755 (executable)
 struct hdmi *m_hdmi_drv;
 
 static const struct fb_videomode hdmi_mode[] = {
-       /*      name            refresh xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw                    polariry                        PorI    flag(used for vic) */
+       /*      name            refresh xres    yres    pixclock                h_bp    h_fp    v_bp    v_fp    h_pw    v_pw                    polariry                        PorI    flag(used for vic) */
 /*
        {"640x480p@60Hz",       60,     640,    480,    25175000,       48,     16,     33,     10,     96,     2,                      0,                              0,      1 },
-       {"720x480i@60Hz",       60,     720,    480,    27000000,       114,    38,     15,     4,      124,    3,                      0,                              1,      6 },
-       {"720x576i@50Hz",       50,     720,    576,    27000000,       138,    24,     19,     2,      126,    3,                      0,                              1,      21},
 */
+       {"720x480i@60Hz",       60,     720,    480,    27000000,       57,     19,   15,     4,        62,     3,                      0,                              1,      6 },
+       {"720x576i@50Hz",       50,     720,    576,    27000000,       69,     12,     19,     2,      63,     3,                      0,                              1,      21},
        {"720x480p@60Hz",       60,     720,    480,    27000000,       60,     16,     30,     9,      62,     6,                      0,                              0,      2 },
        {"720x576p@50Hz",       50,     720,    576,    27000000,       68,     12,     39,     5,      64,     5,                      0,                              0,      17},
 /*
@@ -31,9 +31,9 @@ static const struct fb_videomode hdmi_mode[] = {
        {"1920x1080p@25Hz",     25,     1920,   1080,   74250000,       148,    528,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      33},
        {"1920x1080p@30Hz",     30,     1920,   1080,   74250000,       148,    88,     36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      34},
        {"1920x1080i@50Hz_2",   50,     1920,   1080,   72000000,       184,    32,     57,     23,     168,    5,      FB_SYNC_HOR_HIGH_ACT,                           1,      39},
+*/
        {"1920x1080i@50Hz",     50,     1920,   1080,   74250000,       148,    528,    15,     2,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   1,      20},
        {"1920x1080i@60Hz",     60,     1920,   1080,   74250000,       148,    88,     15,     2,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   1,      5 },
-*/
        {"1920x1080p@50Hz",     50,     1920,   1080,   148500000,      148,    528,    36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      31},
        {"1920x1080p@60Hz",     60,     1920,   1080,   148500000,      148,    88,     36,     4,      44,     5,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   0,      16},
 /*
@@ -121,7 +121,11 @@ int hdmi_set_info(struct rk_screen *screen, unsigned int vic)
        screen->mode.upper_margin = hdmi_mode[i].upper_margin;
        screen->mode.lower_margin = hdmi_mode[i].lower_margin;
        screen->mode.vsync_len = hdmi_mode[i].vsync_len;
+       screen->mode.vmode = hdmi_mode[i].vmode;
        screen->hdmi_resolution = hdmi_mode[i].flag;
+       if ((screen->hdmi_resolution == HDMI_720X480I_60HZ_VIC) ||
+               (screen->hdmi_resolution == HDMI_720X576I_50HZ_VIC))
+               screen->pixelrepeat = 1;
 
        /* Pin polarity */
 #if defined(CONFIG_HDMI_RK616) && !defined(CONFIG_ARCH_RK3026)
@@ -439,10 +443,11 @@ int hdmi_videomode_to_vic(struct fb_videomode *vmode)
                    vmode->lower_margin == hdmi_mode[i].lower_margin &&
                    vmode->hsync_len == hdmi_mode[i].hsync_len &&
                    vmode->vsync_len == hdmi_mode[i].vsync_len) {
-                       if ((vmode->vmode == FB_VMODE_NONINTERLACED
+                       /*if ((vmode->vmode == FB_VMODE_NONINTERLACED
                             && vmode->yres == hdmi_mode[i].yres)
                            || (vmode->vmode == FB_VMODE_INTERLACED
-                               && vmode->yres == hdmi_mode[i].yres / 2)) {
+                               && vmode->yres == hdmi_mode[i].yres / 2))*/
+                       {
                                vic = hdmi_mode[i].flag;
                                break;
                        }
index a653ed4e319a29b14963d402db8da21064d24c5c..321f7fa0fb3cfe30069eb47fe1fafa69f02efa68 100755 (executable)
@@ -41,10 +41,7 @@ static int hdmi_set_enable(struct rk_display_device *device, int enable)
        } else {
                if (hdmi->irq)
                        enable_irq(hdmi->irq);
-#if defined(CONFIG_HDMI_RK610) || defined(CONFIG_HDMI_RK2928)
-       || defined(CONFIG_HDMI_CAT66121) || defined(CONFIG_HDMI_RK616)
                queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
-#endif
                mutex_unlock(&hdmi->enable_mutex);
        }
        return 0;
index 94d8260e6c035215ca9043e66cef6ba654571b60..ba88a132145a57d257f67085e5f54d67b54bd234 100755 (executable)
@@ -217,6 +217,10 @@ void hdmi_work(struct work_struct *work)
                case READ_PARSE_EDID:
                        rc = hdmi_sys_parse_edid(hdmi);
                        if (rc == HDMI_ERROR_SUCESS) {
+                               if(hdmi->cec_set_device_pa)
+                                       hdmi->cec_set_device_pa(hdmi->edid.cecaddress);
+                               if(hdmi->cec_enumerate)
+                                       hdmi->cec_enumerate();
                                hdmi->state = SYSTEM_CONFIG;
                                kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD,
                                                   envp);
@@ -268,8 +272,9 @@ void hdmi_work(struct work_struct *work)
                        if (hdmi->display != HDMI_ENABLE) {
                                hdmi->control_output(hdmi, HDMI_ENABLE);
                                hdmi->display = HDMI_ENABLE;
-                               if (hdmi->hdcp_cb)
+                               if (hdmi->hdcp_cb) {
                                        hdmi->hdcp_cb();
+                               }
                        }
 
                        if (hdmi->wait == 1) {
index 04bff9588cb490b328604f320abac8e460bacdcb..5c69c75ffd161807ab8f14ef2ffc8943dad906df 100755 (executable)
@@ -31,3 +31,15 @@ config LCDC_RK3288
         depends on DRM_ROCKCHIP || FB_ROCKCHIP 
         help
           Driver for rk3288 lcdc.There are two lcd controllers on rk3288
+
+config LCDC_RK3036
+       bool "rk3036 lcdc support"
+       depends on DRM_ROCKCHIP || FB_ROCKCHIP 
+        help
+          Driver for rk3036 lcdc.
+
+config LCDC_RK312X
+        bool "rk312x lcdc support"
+        depends on DRM_ROCKCHIP || FB_ROCKCHIP
+        help
+          Driver for rk312x lcdc.
index c514092848260a73873367f85103d54818f5458b..5f075557dbe77181afb86c6c5b19a2f8e52d5e51 100644 (file)
@@ -3,3 +3,5 @@ obj-$(CONFIG_LCDC_RK2928) += rk2928_lcdc.o
 obj-$(CONFIG_LCDC_RK3066B) += rk3066b_lcdc.o
 obj-$(CONFIG_LCDC_RK3188) += rk3188_lcdc.o
 obj-$(CONFIG_LCDC_RK3288) += rk3288_lcdc.o
+obj-$(CONFIG_LCDC_RK3036) += rk3036_lcdc.o
+obj-$(CONFIG_LCDC_RK312X) += rk312x_lcdc.o
diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.c b/drivers/video/rockchip/lcdc/rk3036_lcdc.c
new file mode 100755 (executable)
index 0000000..08ab74b
--- /dev/null
@@ -0,0 +1,1546 @@
+/*
+ * drivers/video/rockchip/lcdc/rk3036_lcdc.c
+ *
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ * Author:zhengyang<zhengyang@rock-chips.com>
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <asm/div64.h>
+#include <linux/uaccess.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/common.h>
+#include <dt-bindings/clock/rk_system_status.h>
+#if defined(CONFIG_ION_ROCKCHIP)
+#include <linux/rockchip/iovmm.h>
+#include <linux/rockchip/sysmmu.h>
+#endif
+#include "rk3036_lcdc.h"
+
+static int dbg_thresd;
+module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
+
+#define DBG(level, x...) do {                  \
+       if (unlikely(dbg_thresd >= level))      \
+               dev_info(dev_drv->dev, x);              \
+       } while (0)
+
+#define grf_writel(offset, v)  do { \
+       writel_relaxed(v, RK_GRF_VIRT + offset); \
+       dsb(); \
+       } while (0)
+
+static struct rk_lcdc_win lcdc_win[] = {
+       [0] = {
+              .name = "win0",
+              .id = 0,
+              .support_3d = false,
+              },
+       [1] = {
+              .name = "win1",
+              .id = 1,
+              .support_3d = false,
+              },
+       [2] = {
+              .name = "hwc",
+              .id = 2,
+              .support_3d = false,
+              },
+};
+
+static irqreturn_t rk3036_lcdc_isr(int irq, void *dev_id)
+{
+       struct lcdc_device *lcdc_dev =
+           (struct lcdc_device *)dev_id;
+       ktime_t timestamp = ktime_get();
+       u32 int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
+
+       if (int_reg & m_FS_INT_STA) {
+               timestamp = ktime_get();
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
+                            v_FS_INT_CLEAR(1));
+               /*if (lcdc_dev->driver.wait_fs) {*/
+               if (0) {
+                       spin_lock(&(lcdc_dev->driver.cpl_lock));
+                       complete(&(lcdc_dev->driver.frame_done));
+                       spin_unlock(&(lcdc_dev->driver.cpl_lock));
+               }
+               lcdc_dev->driver.vsync_info.timestamp = timestamp;
+               wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
+
+       } else if (int_reg & m_LF_INT_STA) {
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
+                            v_LF_INT_CLEAR(1));
+       }
+       return IRQ_HANDLED;
+}
+
+static int rk3036_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
+{
+#ifdef CONFIG_RK_FPGA
+       lcdc_dev->clk_on = 1;
+       return 0;
+#endif
+       if (!lcdc_dev->clk_on) {
+               clk_prepare_enable(lcdc_dev->hclk);
+               clk_prepare_enable(lcdc_dev->dclk);
+               clk_prepare_enable(lcdc_dev->aclk);
+/*             clk_prepare_enable(lcdc_dev->pd);*/
+               spin_lock(&lcdc_dev->reg_lock);
+               lcdc_dev->clk_on = 1;
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+
+       return 0;
+}
+
+static int rk3036_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
+{
+#ifdef CONFIG_RK_FPGA
+       lcdc_dev->clk_on = 0;
+       return 0;
+#endif
+       if (lcdc_dev->clk_on) {
+               spin_lock(&lcdc_dev->reg_lock);
+               lcdc_dev->clk_on = 0;
+               spin_unlock(&lcdc_dev->reg_lock);
+               mdelay(25);
+               clk_disable_unprepare(lcdc_dev->dclk);
+               clk_disable_unprepare(lcdc_dev->hclk);
+               clk_disable_unprepare(lcdc_dev->aclk);
+/*             clk_disable_unprepare(lcdc_dev->pd);*/
+       }
+
+       return 0;
+}
+
+static int rk3036_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask, val;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+       mask = m_FS_INT_CLEAR | m_FS_INT_EN;
+       val = v_FS_INT_CLEAR(1) | v_FS_INT_EN(1);
+       lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+       return 0;
+}
+
+static int rk3036_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
+{
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_FS_INT_CLEAR | m_FS_INT_EN;
+               val = v_FS_INT_CLEAR(0) | v_FS_INT_EN(0);
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+       mdelay(1);
+       return 0;
+}
+
+static void rk_lcdc_read_reg_defalut_cfg(struct lcdc_device
+                                            *lcdc_dev)
+{
+       int reg = 0;
+       u32 value = 0;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       for (reg = 0; reg < 0xdc; reg += 4)
+               value = lcdc_readl(lcdc_dev, reg);
+
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
+{
+       int win0_top = 0;
+       u32 mask, val;
+       enum data_format win0_format = lcdc_dev->driver.win[0]->format;
+       enum data_format win1_format = lcdc_dev->driver.win[1]->format;
+
+       int win0_alpha_en = ((win0_format == ARGB888) ||
+                               (win0_format == ABGR888)) ? 1 : 0;
+       int win1_alpha_en = ((win1_format == ARGB888) ||
+                               (win1_format == ABGR888)) ? 1 : 0;
+       u32 *_pv = (u32 *)lcdc_dev->regsbak;
+
+       _pv += (DSP_CTRL0 >> 2);
+       win0_top = ((*_pv) & (m_WIN0_TOP)) >> 8;
+       if (win0_top && (lcdc_dev->atv_layer_cnt >= 2) && (win0_alpha_en)) {
+               mask =  m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN |
+                       m_WIN1_PREMUL_SCALE;
+               val = v_WIN0_ALPHA_EN(1) | v_WIN1_ALPHA_EN(0) |
+                       v_WIN1_PREMUL_SCALE(0);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+
+               mask = m_WIN0_ALPHA_MODE | m_PREMUL_ALPHA_ENABLE |
+                       m_ALPHA_MODE_SEL1;
+               val = v_WIN0_ALPHA_MODE(1) | v_PREMUL_ALPHA_ENABLE(1) |
+                       v_ALPHA_MODE_SEL1(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+       } else if ((!win0_top) && (lcdc_dev->atv_layer_cnt >= 2) &&
+                  (win1_alpha_en)) {
+               mask =  m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN |
+                       m_WIN1_PREMUL_SCALE;
+               val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(1) |
+                       v_WIN1_PREMUL_SCALE(0);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+
+               mask = m_WIN1_ALPHA_MODE | m_PREMUL_ALPHA_ENABLE |
+                       m_ALPHA_MODE_SEL1;
+               val = v_WIN1_ALPHA_MODE(1) | v_PREMUL_ALPHA_ENABLE(1) |
+                       v_ALPHA_MODE_SEL1(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+       } else {
+               mask = m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN;
+               val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(0);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+       }
+       return 0;
+}
+
+static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
+                                  struct rk_lcdc_win *win)
+{
+       u32 mask, val;
+
+       if (win->state == 1) {
+               if (win->id == 0) {
+                       mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP;
+                       val = v_WIN0_EN(win->state) |
+                             v_WIN0_FORMAT(win->fmt_cfg) |
+                             v_WIN0_RB_SWAP(win->swap_rb);
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+
+                       lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB,
+                                   v_X_SCL_FACTOR(win->scale_yrgb_x) |
+                                   v_Y_SCL_FACTOR(win->scale_yrgb_y));
+                       lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR,
+                                   v_X_SCL_FACTOR(win->scale_cbcr_x) |
+                                   v_Y_SCL_FACTOR(win->scale_cbcr_y));
+                       lcdc_msk_reg(lcdc_dev, WIN0_VIR,
+                                    m_YRGB_VIR | m_CBBR_VIR,
+                                    v_YRGB_VIR(win->area[0].y_vir_stride) |
+                                    v_CBBR_VIR(win->area[0].uv_vir_stride));
+                       lcdc_writel(lcdc_dev, WIN0_ACT_INFO,
+                                   v_ACT_WIDTH(win->area[0].xact) |
+                                   v_ACT_HEIGHT(win->area[0].yact));
+                       lcdc_writel(lcdc_dev, WIN0_DSP_ST,
+                                   v_DSP_STX(win->area[0].dsp_stx) |
+                                   v_DSP_STY(win->area[0].dsp_sty));
+                       lcdc_writel(lcdc_dev, WIN0_DSP_INFO,
+                                   v_DSP_WIDTH(win->post_cfg.xsize) |
+                                   v_DSP_HEIGHT(win->post_cfg.ysize));
+
+                       lcdc_writel(lcdc_dev, WIN0_YRGB_MST,
+                                   win->area[0].y_addr);
+                       lcdc_writel(lcdc_dev, WIN0_CBR_MST,
+                                   win->area[0].uv_addr);
+               } else if (win->id == 1) {
+                       mask = m_WIN1_EN | m_WIN1_FORMAT | m_WIN1_RB_SWAP;
+                       val = v_WIN1_EN(win->state) |
+                             v_WIN1_FORMAT(win->fmt_cfg) |
+                             v_WIN1_RB_SWAP(win->swap_rb);
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+
+                       lcdc_writel(lcdc_dev, WIN1_SCL_FACTOR_YRGB,
+                                   v_X_SCL_FACTOR(win->scale_yrgb_x) |
+                                   v_Y_SCL_FACTOR(win->scale_yrgb_y));
+
+                       lcdc_msk_reg(lcdc_dev, WIN1_VIR, m_YRGB_VIR,
+                                    v_YRGB_VIR(win->area[0].y_vir_stride));
+                       lcdc_writel(lcdc_dev, WIN1_ACT_INFO,
+                                   v_ACT_WIDTH(win->area[0].xact) |
+                                   v_ACT_HEIGHT(win->area[0].yact));
+                       lcdc_writel(lcdc_dev, WIN1_DSP_INFO,
+                                   v_DSP_WIDTH(win->post_cfg.xsize) |
+                                   v_DSP_HEIGHT(win->post_cfg.ysize));
+                       lcdc_writel(lcdc_dev, WIN1_DSP_ST,
+                                   v_DSP_STX(win->area[0].dsp_stx) |
+                                   v_DSP_STY(win->area[0].dsp_sty));
+                       lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr);
+               } /* else if (win->id == 2) {
+               }*/
+       } else {
+               win->area[0].y_addr = 0;
+               win->area[0].uv_addr = 0;
+               if (win->id == 0)
+                       lcdc_msk_reg(lcdc_dev,
+                                    SYS_CTRL, m_WIN0_EN, v_WIN0_EN(0));
+               else if (win->id == 1)
+                       lcdc_msk_reg(lcdc_dev,
+                                    SYS_CTRL, m_WIN1_EN, v_WIN1_EN(0));
+               else if (win->id == 2)
+                       lcdc_msk_reg(lcdc_dev,
+                                    SYS_CTRL, m_HWC_EN, v_HWC_EN(0));
+       }
+       rk3036_lcdc_alpha_cfg(lcdc_dev);
+}
+
+static void lcdc_layer_enable(struct lcdc_device *lcdc_dev,
+                             unsigned int win_id, bool open)
+{
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on) &&
+           lcdc_dev->driver.win[win_id]->state != open) {
+               if (open) {
+                       if (!lcdc_dev->atv_layer_cnt) {
+                               dev_info(lcdc_dev->dev,
+                                        "wakeup from standby!\n");
+                               lcdc_dev->standby = 0;
+                       }
+                       lcdc_dev->atv_layer_cnt++;
+               } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
+                       lcdc_dev->atv_layer_cnt--;
+               }
+               lcdc_dev->driver.win[win_id]->state = open;
+               if (!open) {
+                       lcdc_layer_update_regs(lcdc_dev,
+                                              lcdc_dev->driver.win[win_id]);
+                       lcdc_cfg_done(lcdc_dev);
+               }
+               /*if no layer used,disable lcdc*/
+               if (!lcdc_dev->atv_layer_cnt) {
+                       dev_info(lcdc_dev->dev,
+                                "no layer is used, go to standby!\n");
+                       lcdc_dev->standby = 1;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk3036_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
+       struct rk_lcdc_win *win1 = lcdc_dev->driver.win[1];
+       int timeout;
+       unsigned long flags;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(lcdc_dev->standby));
+               lcdc_layer_update_regs(lcdc_dev, win0);
+               lcdc_layer_update_regs(lcdc_dev, win1);
+               rk3036_lcdc_alpha_cfg(lcdc_dev);
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       /* if (dev_drv->wait_fs) { */
+       if (0) {
+               spin_lock_irqsave(&dev_drv->cpl_lock, flags);
+               init_completion(&dev_drv->frame_done);
+               spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
+               timeout = wait_for_completion_timeout(&dev_drv->frame_done,
+                                                     msecs_to_jiffies
+                                                     (dev_drv->cur_screen->ft
+                                                      + 5));
+               if (!timeout && (!dev_drv->frame_done.done)) {
+                       dev_warn(lcdc_dev->dev,
+                                "wait for new frame start time out!\n");
+                       return -ETIMEDOUT;
+               }
+       }
+       DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
+       return 0;
+}
+
+static void rk3036_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
+{
+       memcpy((u8 *)lcdc_dev->regs, (u8 *)lcdc_dev->regsbak, 0xdc);
+}
+
+static void rk3036_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask, val;
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_MMU_EN | m_AXI_MAX_OUTSTANDING_EN |
+                       m_AXI_OUTSTANDING_MAX_NUM;
+               val = v_MMU_EN(1) | v_AXI_OUTSTANDING_MAX_NUM(31) |
+                       v_AXI_MAX_OUTSTANDING_EN(1);
+               lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk3036_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
+{
+#ifdef CONFIG_RK_FPGA
+       return 0;
+#endif
+       int ret, fps;
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+
+       ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+       if (ret)
+               dev_err(dev_drv->dev,
+                       "set lcdc%d dclk failed\n", lcdc_dev->id);
+       lcdc_dev->pixclock =
+                div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
+
+       fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
+       screen->ft = 1000 / fps;
+       dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
+                lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
+       return 0;
+}
+
+/********do basic init*********/
+static int rk3036_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                               struct lcdc_device, driver);
+
+       if (lcdc_dev->pre_init)
+               return 0;
+       lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
+       lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
+       lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
+/*     lcdc_dev->pd   = devm_clk_get(lcdc_dev->dev, "pd_lcdc"); */
+
+       if (/*IS_ERR(lcdc_dev->pd) ||*/ (IS_ERR(lcdc_dev->aclk)) ||
+           (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
+               dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
+                       lcdc_dev->id);
+       }
+
+       rk_disp_pwr_enable(dev_drv);
+       rk3036_lcdc_clk_enable(lcdc_dev);
+
+       /*backup reg config at uboot*/
+       rk_lcdc_read_reg_defalut_cfg(lcdc_dev);
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_AUTO_GATING_EN,
+                    v_AUTO_GATING_EN(0));
+       lcdc_cfg_done(lcdc_dev);
+       if (dev_drv->iommu_enabled)
+               /*disable win0 to workaround iommu pagefault*/
+               lcdc_layer_enable(lcdc_dev, 0, 0);
+       lcdc_dev->pre_init = true;
+
+       return 0;
+}
+
+static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
+{
+       int ret = -EINVAL;
+       int fps;
+       u16 face = 0;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                               struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       u16 right_margin = screen->mode.right_margin;
+       u16 left_margin = screen->mode.left_margin;
+       u16 lower_margin = screen->mode.lower_margin;
+       u16 upper_margin = screen->mode.upper_margin;
+       u16 x_res = screen->mode.xres;
+       u16 y_res = screen->mode.yres;
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               switch (screen->type) {
+               case SCREEN_HDMI:
+                       mask = m_HDMI_DCLK_EN;
+                       val = v_HDMI_DCLK_EN(1);
+                       if (screen->pixelrepeat) {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(1);
+                       } else {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(0);
+                       }
+                       lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                       mask = (1 << 4) | (1 << 5) | (1 << 6);
+                       val = (screen->pin_hsync << 4) |
+                               (screen->pin_vsync << 5) |
+                               (screen->pin_den << 6);
+                       grf_writel(RK3036_GRF_SOC_CON2, (mask << 16) | val);
+                       break;
+               case SCREEN_TVOUT:
+                       mask = m_TVE_DAC_DCLK_EN;
+                       val = v_TVE_DAC_DCLK_EN(1);
+                       if (screen->pixelrepeat) {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(1);
+                       } else {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(0);
+                       }
+                       lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                       if ((x_res == 720) && (y_res == 576)) {
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
+                                            m_TVE_MODE, v_TVE_MODE(TV_PAL));
+                       } else if ((x_res == 720) && (y_res == 480)) {
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
+                                            m_TVE_MODE, v_TVE_MODE(TV_NTSC));
+                       } else {
+                               dev_err(lcdc_dev->dev,
+                                       "unsupported video timing!\n");
+                               return -1;
+                       }
+                       break;
+               default:
+                       dev_err(lcdc_dev->dev, "un supported interface!\n");
+                       break;
+               }
+
+               mask = m_DSP_OUT_FORMAT | m_HSYNC_POL | m_VSYNC_POL |
+                   m_DEN_POL | m_DCLK_POL;
+               val = v_DSP_OUT_FORMAT(face) |
+                       v_HSYNC_POL(screen->pin_hsync) |
+                       v_VSYNC_POL(screen->pin_vsync) |
+                       v_DEN_POL(screen->pin_den) |
+                       v_DCLK_POL(screen->pin_dclk);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+
+               mask = m_BG_COLOR | m_DSP_BG_SWAP | m_DSP_RB_SWAP |
+                   m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
+                   m_DSP_DUMMY_SWAP | m_BLANK_EN;
+
+               val = v_BG_COLOR(0x000000) | v_DSP_BG_SWAP(screen->swap_gb) |
+                   v_DSP_RB_SWAP(screen->swap_rb) |
+                   v_DSP_RG_SWAP(screen->swap_rg) |
+                   v_DSP_DELTA_SWAP(screen->swap_delta) |
+                                    v_DSP_DUMMY_SWAP(screen->swap_dumy) |
+                                                     v_BLANK_EN(0) |
+                                    v_BLACK_EN(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
+               val =
+                   v_HSYNC(screen->mode.hsync_len) | v_HORPRD(screen->mode.
+                                                              hsync_len +
+                                                              left_margin +
+                                                              x_res +
+                                                              right_margin);
+               lcdc_writel(lcdc_dev, DSP_HTOTAL_HS_END, val);
+               val = v_HAEP(screen->mode.hsync_len + left_margin + x_res) |
+                   v_HASP(screen->mode.hsync_len + left_margin);
+               lcdc_writel(lcdc_dev, DSP_HACT_ST_END, val);
+
+               if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+                       /*First Field Timing*/
+                       lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END,
+                                   v_VSYNC(screen->mode.vsync_len) |
+                                   v_VERPRD(2 * (screen->mode.vsync_len +
+                                                 upper_margin + lower_margin)
+                                            + y_res + 1));
+                       lcdc_writel(lcdc_dev, DSP_VACT_ST_END,
+                                   v_VAEP(screen->mode.vsync_len +
+                                       upper_margin + y_res/2) |
+                                   v_VASP(screen->mode.vsync_len +
+                                       upper_margin));
+                       /*Second Field Timing*/
+                       lcdc_writel(lcdc_dev, DSP_VS_ST_END_F1,
+                                   v_VSYNC_ST_F1(screen->mode.vsync_len +
+                                                 upper_margin + y_res/2 +
+                                                 lower_margin) |
+                                   v_VSYNC_END_F1(2 * screen->mode.vsync_len
+                                                  + upper_margin + y_res/2 +
+                                                  lower_margin));
+                       lcdc_writel(lcdc_dev, DSP_VACT_ST_END_F1,
+                                   v_VAEP(2 * (screen->mode.vsync_len +
+                                               upper_margin) + y_res +
+                                               lower_margin + 1) |
+                                   v_VASP(2 * (screen->mode.vsync_len +
+                                               upper_margin) + y_res/2 +
+                                               lower_margin + 1));
+
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
+                                    m_INTERLACE_DSP_EN |
+                                    m_INTERLACE_DSP_POL |
+                                    m_WIN1_DIFF_DCLK_EN |
+                                    m_WIN0_YRGB_DEFLICK_EN |
+                                    m_WIN0_CBR_DEFLICK_EN,
+                                    v_INTERLACE_DSP_EN(1) |
+                                    v_INTERLACE_DSP_POL(0) |
+                                    v_WIN1_DIFF_DCLK_EN(1) |
+                                    v_WIN0_YRGB_DEFLICK_EN(1) |
+                                    v_WIN0_CBR_DEFLICK_EN(1));
+               } else {
+                       val = v_VSYNC(screen->mode.vsync_len) |
+                             v_VERPRD(screen->mode.vsync_len + upper_margin +
+                                       y_res + lower_margin);
+                       lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, val);
+
+                       val = v_VAEP(screen->mode.vsync_len +
+                                    upper_margin + y_res) |
+                           v_VASP(screen->mode.vsync_len +
+                                  screen->mode.upper_margin);
+                       lcdc_writel(lcdc_dev, DSP_VACT_ST_END, val);
+
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
+                                    m_INTERLACE_DSP_EN |
+                                    m_WIN1_DIFF_DCLK_EN |
+                                    m_WIN0_YRGB_DEFLICK_EN |
+                                    m_WIN0_CBR_DEFLICK_EN,
+                                    v_INTERLACE_DSP_EN(0) |
+                                    v_WIN1_DIFF_DCLK_EN(0) |
+                                    v_WIN0_YRGB_DEFLICK_EN(0) |
+                                    v_WIN0_CBR_DEFLICK_EN(0));
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+       if (ret)
+               dev_err(dev_drv->dev,
+                       "set lcdc%d dclk failed\n", lcdc_dev->id);
+       lcdc_dev->pixclock =
+           div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
+
+       fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
+       screen->ft = 1000 / fps;
+       dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
+                lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+               dev_drv->trsm_ops->enable();
+       if (screen->init)
+               screen->init();
+
+       return 0;
+}
+
+static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
+                           bool open)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+
+       /*enable clk,when first layer open */
+       if ((open) && (!lcdc_dev->atv_layer_cnt)) {
+               rk3036_lcdc_pre_init(dev_drv);
+               rk3036_lcdc_clk_enable(lcdc_dev);
+               #if defined(CONFIG_ROCKCHIP_IOMMU)
+               if (dev_drv->iommu_enabled) {
+                       if (!dev_drv->mmu_dev) {
+                               dev_drv->mmu_dev =
+                               rockchip_get_sysmmu_device_by_compatible(
+                                       dev_drv->mmu_dts_name);
+                               if (dev_drv->mmu_dev) {
+                                       platform_set_sysmmu(dev_drv->mmu_dev,
+                                                           dev_drv->dev);
+                               } else {
+                                       dev_err(dev_drv->dev,
+                                               "failed to get iommu device\n"
+                                               );
+                                       return -1;
+                               }
+                       }
+                       iovmm_activate(dev_drv->dev);
+               }
+               #endif
+               rk3036_lcdc_reg_restore(lcdc_dev);
+               if (dev_drv->iommu_enabled)
+                       rk3036_lcdc_mmu_en(dev_drv);
+               if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
+                       rk3036_lcdc_set_dclk(dev_drv);
+                       rk3036_lcdc_enable_irq(dev_drv);
+               } else {
+                       rk3036_load_screen(dev_drv, 1);
+               }
+       }
+
+       if (win_id < ARRAY_SIZE(lcdc_win))
+               lcdc_layer_enable(lcdc_dev, win_id, open);
+       else
+               dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
+
+       /*when all layer closed,disable clk */
+       if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
+               rk3036_lcdc_disable_irq(lcdc_dev);
+               rk3036_lcdc_reg_update(dev_drv);
+               #if defined(CONFIG_ROCKCHIP_IOMMU)
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               iovmm_deactivate(dev_drv->dev);
+               }
+               #endif
+               rk3036_lcdc_clk_disable(lcdc_dev);
+       }
+
+       return 0;
+}
+
+static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       struct lcdc_device *lcdc_dev =
+                       container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       struct rk_lcdc_win *win = NULL;
+       char fmt[9] = "NULL";
+
+       if (!screen) {
+               dev_err(dev_drv->dev, "screen is null!\n");
+               return -ENOENT;
+       }
+
+       if (win_id == 0) {
+               win = dev_drv->win[0];
+       } else if (win_id == 1) {
+               win = dev_drv->win[1];
+       } else {
+               dev_err(dev_drv->dev, "un supported win number:%d\n", win_id);
+               return -EINVAL;
+       }
+
+       spin_lock(&lcdc_dev->reg_lock);
+       win->post_cfg.xpos = win->area[0].xpos * (dev_drv->overscan.left +
+               dev_drv->overscan.right)/200 + screen->mode.xres *
+                       (100 - dev_drv->overscan.left) / 200;
+
+       win->post_cfg.ypos = win->area[0].ypos * (dev_drv->overscan.top +
+               dev_drv->overscan.bottom)/200 +
+               screen->mode.yres *
+                       (100 - dev_drv->overscan.top) / 200;
+       win->post_cfg.xsize = win->area[0].xsize *
+                               (dev_drv->overscan.left +
+                               dev_drv->overscan.right)/200;
+       win->post_cfg.ysize = win->area[0].ysize *
+                               (dev_drv->overscan.top +
+                               dev_drv->overscan.bottom)/200;
+
+       win->area[0].dsp_stx = win->post_cfg.xpos + screen->mode.left_margin +
+                               screen->mode.hsync_len;
+       if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+               win->post_cfg.ysize /= 2;
+               win->area[0].dsp_sty = win->post_cfg.ypos/2 +
+                                       screen->mode.upper_margin +
+                                       screen->mode.vsync_len;
+       } else {
+               win->area[0].dsp_sty = win->post_cfg.ypos +
+                                       screen->mode.upper_margin +
+                                       screen->mode.vsync_len;
+       }
+       win->scale_yrgb_x = calscale(win->area[0].xact, win->post_cfg.xsize);
+       win->scale_yrgb_y = calscale(win->area[0].yact, win->post_cfg.ysize);
+       switch (win->format) {
+       case ARGB888:
+               win->fmt_cfg = VOP_FORMAT_ARGB888;
+               win->swap_rb = 0;
+               break;
+       case XBGR888:
+               win->fmt_cfg = VOP_FORMAT_ARGB888;
+               win->swap_rb = 1;
+               break;
+       case ABGR888:
+               win->fmt_cfg = VOP_FORMAT_ARGB888;
+               win->swap_rb = 1;
+               break;
+       case RGB888:
+               win->fmt_cfg = VOP_FORMAT_RGB888;
+               win->swap_rb = 0;
+               break;
+       case RGB565:
+               win->fmt_cfg = VOP_FORMAT_RGB565;
+               win->swap_rb = 0;
+               break;
+       case YUV444:
+               if (win_id == 0) {
+                       win->fmt_cfg = VOP_FORMAT_YCBCR444;
+                       win->scale_cbcr_x = calscale(win->area[0].xact,
+                                                    win->post_cfg.xsize);
+                       win->scale_cbcr_y = calscale(win->area[0].yact,
+                                                    win->post_cfg.ysize);
+                       win->swap_rb = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n",
+                               __func__);
+               }
+               break;
+       case YUV422:
+               if (win_id == 0) {
+                       win->fmt_cfg = VOP_FORMAT_YCBCR422;
+                       win->scale_cbcr_x = calscale((win->area[0].xact / 2),
+                                                    win->post_cfg.xsize);
+                       win->scale_cbcr_y = calscale(win->area[0].yact,
+                                                    win->post_cfg.ysize);
+                       win->swap_rb = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n",
+                               __func__);
+               }
+               break;
+       case YUV420:
+               if (win_id == 0) {
+                       win->fmt_cfg = VOP_FORMAT_YCBCR420;
+                       win->scale_cbcr_x = calscale(win->area[0].xact / 2,
+                                                    win->post_cfg.xsize);
+                       win->scale_cbcr_y = calscale(win->area[0].yact / 2,
+                                                    win->post_cfg.ysize);
+                       win->swap_rb = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n",
+                               __func__);
+               }
+               break;
+       default:
+               dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
+                       __func__);
+               break;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       DBG(2, "lcdc%d>>%s\n"
+               ">>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
+               ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
+               __func__, get_format_string(win->format, fmt),
+               win->area[0].xact, win->area[0].yact, win->post_cfg.xsize,
+               win->post_cfg.ysize, win->area[0].xvir, win->area[0].yvir,
+               win->post_cfg.xpos, win->post_cfg.ypos);
+       return 0;
+}
+
+static int rk3036_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                               struct lcdc_device, driver);
+       struct rk_lcdc_win *win = NULL;
+       struct rk_screen *screen = dev_drv->cur_screen;
+
+       if (!screen) {
+               dev_err(dev_drv->dev, "screen is null!\n");
+               return -ENOENT;
+       }
+
+       if (win_id == 0) {
+               win = dev_drv->win[0];
+       } else if (win_id == 1) {
+               win = dev_drv->win[1];
+       } else {
+               dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
+               return -EINVAL;
+       }
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               win->area[0].y_addr = win->area[0].smem_start +
+                                       win->area[0].y_offset;
+               win->area[0].uv_addr = win->area[0].cbr_start +
+                                       win->area[0].c_offset;
+               if (win->area[0].y_addr)
+                       lcdc_layer_update_regs(lcdc_dev, win);
+               /*lcdc_cfg_done(lcdc_dev);*/
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
+           lcdc_dev->id, __func__, win->area[0].y_addr,
+           win->area[0].uv_addr, win->area[0].y_offset);
+        /* this is the first frame of the system,
+               enable frame start interrupt*/
+       if ((dev_drv->first_frame))  {
+               dev_drv->first_frame = 0;
+               rk3036_lcdc_enable_irq(dev_drv);
+       }
+       return 0;
+}
+
+static int rk3036_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
+                            unsigned long arg, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+       u32 panel_size[2];
+       void __user *argp = (void __user *)arg;
+       struct color_key_cfg clr_key_cfg;
+
+       switch (cmd) {
+       case RK_FBIOGET_PANEL_SIZE:
+               panel_size[0] = lcdc_dev->screen->mode.xres;
+               panel_size[1] = lcdc_dev->screen->mode.yres;
+               if (copy_to_user(argp, panel_size, 8))
+                       return -EFAULT;
+               break;
+       case RK_FBIOPUT_COLOR_KEY_CFG:
+               if (copy_from_user(&clr_key_cfg, argp,
+                                  sizeof(struct color_key_cfg)))
+                       return -EFAULT;
+               lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
+                           clr_key_cfg.win0_color_key_cfg);
+               lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
+                           clr_key_cfg.win1_color_key_cfg);
+               break;
+
+       default:
+               break;
+       }
+       return 0;
+}
+
+static int rk3036_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
+                                 const char *id)
+{
+       int win_id = 0;
+
+       mutex_lock(&dev_drv->fb_win_id_mutex);
+       if (!strcmp(id, "fb0"))
+               win_id = dev_drv->fb0_win_id;
+       else if (!strcmp(id, "fb1"))
+               win_id = dev_drv->fb1_win_id;
+       else if (!strcmp(id, "fb2"))
+               win_id = dev_drv->fb2_win_id;
+       mutex_unlock(&dev_drv->fb_win_id_mutex);
+
+       return win_id;
+}
+
+static int rk3036_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
+                                    int win_id)
+{
+       return dev_drv->win[win_id]->state;
+}
+
+static int rk3036_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
+                              bool set)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       int ovl;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               if (set) {
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN0_TOP,
+                                    v_WIN0_TOP(swap));
+                       ovl = swap;
+               } else {
+                       ovl = lcdc_read_bit(lcdc_dev, DSP_CTRL0, m_WIN0_TOP);
+               }
+       } else {
+               ovl = -EPERM;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return ovl;
+}
+
+static int rk3036_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+       if (dev_drv->suspend_flag)
+               return 0;
+       dev_drv->suspend_flag = 1;
+       flush_kthread_worker(&dev_drv->update_regs_worker);
+
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
+               dev_drv->trsm_ops->disable();
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN,
+                            v_BLANK_EN(1));
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
+                            v_FS_INT_CLEAR(1));
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
+                            v_DSP_OUT_ZERO(1));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(1));
+               lcdc_cfg_done(lcdc_dev);
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               iovmm_deactivate(dev_drv->dev);
+               }
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+               return 0;
+       }
+       rk3036_lcdc_clk_disable(lcdc_dev);
+       rk_disp_pwr_disable(dev_drv);
+       return 0;
+}
+
+static int rk3036_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       if (!dev_drv->suspend_flag)
+               return 0;
+       rk_disp_pwr_enable(dev_drv);
+       dev_drv->suspend_flag = 0;
+
+       if (lcdc_dev->atv_layer_cnt) {
+               rk3036_lcdc_clk_enable(lcdc_dev);
+               rk3036_lcdc_reg_restore(lcdc_dev);
+
+               spin_lock(&lcdc_dev->reg_lock);
+
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
+                            v_DSP_OUT_ZERO(0));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(0));
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN,
+                            v_BLANK_EN(0));
+               lcdc_cfg_done(lcdc_dev);
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               iovmm_activate(dev_drv->dev);
+               }
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+               dev_drv->trsm_ops->enable();
+       return 0;
+}
+
+
+static int rk3036_lcdc_blank(struct rk_lcdc_driver *dev_drv,
+                            int win_id, int blank_mode)
+{
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               rk3036_lcdc_early_resume(dev_drv);
+               break;
+       case FB_BLANK_NORMAL:
+               rk3036_lcdc_early_suspend(dev_drv);
+               break;
+       default:
+               rk3036_lcdc_early_suspend(dev_drv);
+               break;
+       }
+
+       dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
+
+       return 0;
+}
+
+static int rk3036_lcdc_cfg_done(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                       struct lcdc_device, driver);
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(lcdc_dev->standby));
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+}
+
+/*
+       a:[-30~0]:
+           sin_hue = sin(a)*256 +0x100;
+           cos_hue = cos(a)*256;
+       a:[0~30]
+           sin_hue = sin(a)*256;
+           cos_hue = cos(a)*256;
+*/
+static int rk3036_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,
+                                   bcsh_hue_mode mode)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               val = lcdc_readl(lcdc_dev, BCSH_H);
+               switch (mode) {
+               case H_SIN:
+                       val &= m_BCSH_SIN_HUE;
+                       break;
+               case H_COS:
+                       val &= m_BCSH_COS_HUE;
+                       val >>= 8;
+                       break;
+               default:
+                       break;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return val;
+}
+
+
+static int rk3036_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,
+                                   int sin_hue, int cos_hue)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
+               val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
+               lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return 0;
+}
+
+static int rk3036_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
+                                   bcsh_bcs_mode mode, int value)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               switch (mode) {
+               case BRIGHTNESS:
+               /*from 0 to 255,typical is 128*/
+                       if (value < 0x20)
+                               value += 0x20;
+                       else if (value >= 0x20)
+                               value = value - 0x20;
+                       mask =  m_BCSH_BRIGHTNESS;
+                       val = v_BCSH_BRIGHTNESS(value);
+                       break;
+               case CONTRAST:
+               /*from 0 to 510,typical is 256*/
+                       mask =  m_BCSH_CONTRAST;
+                       val =  v_BCSH_CONTRAST(value);
+                       break;
+               case SAT_CON:
+               /*from 0 to 1015,typical is 256*/
+                       mask = m_BCSH_SAT_CON;
+                       val = v_BCSH_SAT_CON(value);
+                       break;
+               default:
+                       break;
+               }
+               lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return val;
+}
+
+static int rk3036_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
+                                   bcsh_bcs_mode mode)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               val = lcdc_readl(lcdc_dev, BCSH_BCS);
+               switch (mode) {
+               case BRIGHTNESS:
+                       val &= m_BCSH_BRIGHTNESS;
+                       if (val > 0x20)
+                               val -= 0x20;
+                       else if (val == 0x20)
+                               val = -32;
+                       break;
+               case CONTRAST:
+                       val &= m_BCSH_CONTRAST;
+                       val >>= 8;
+                       break;
+               case SAT_CON:
+                       val &= m_BCSH_SAT_CON;
+                       val >>= 16;
+                       break;
+               default:
+                       break;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return val;
+}
+
+
+static int rk3036_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               if (open) {
+                       lcdc_writel(lcdc_dev, BCSH_CTRL,
+                                   v_BCSH_EN(1) | v_BCSH_OUT_MODE(3));
+                       lcdc_writel(lcdc_dev, BCSH_BCS,
+                                   v_BCSH_BRIGHTNESS(0x00) |
+                                   v_BCSH_CONTRAST(0x80) |
+                                   v_BCSH_SAT_CON(0x80));
+                       lcdc_writel(lcdc_dev, BCSH_H, v_BCSH_COS_HUE(0x80));
+               } else {
+                       mask = m_BCSH_EN;
+                       val = v_BCSH_EN(0);
+                       lcdc_msk_reg(lcdc_dev, BCSH_CTRL, mask, val);
+               }
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+}
+
+static int rk3036_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
+                                   struct overscan *overscan)
+{
+       int i;
+
+       dev_drv->overscan = *overscan;
+       for (i = 0; i < dev_drv->lcdc_win_num; i++) {
+               if (dev_drv->win[i] && dev_drv->win[i]->state) {
+                       rk3036_lcdc_set_par(dev_drv, i);
+                       rk3036_lcdc_pan_display(dev_drv, i);
+               }
+       }
+       rk3036_lcdc_cfg_done(dev_drv);
+       return 0;
+}
+
+static int rk3036_fb_win_remap(struct rk_lcdc_driver *dev_drv,
+                              enum fb_win_map_order order)
+{
+       mutex_lock(&dev_drv->fb_win_id_mutex);
+       if (order == FB_DEFAULT_ORDER)
+               order = FB0_WIN1_FB1_WIN0_FB2_WIN2;
+       dev_drv->fb2_win_id = order / 100;
+       dev_drv->fb1_win_id = (order / 10) % 10;
+       dev_drv->fb0_win_id = order % 10;
+       mutex_unlock(&dev_drv->fb_win_id_mutex);
+
+       return 0;
+}
+
+static int rk3036_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
+                              bool set)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       u64 ft = 0;
+       u32 dotclk;
+       int ret;
+       u32 pixclock;
+       u32 x_total, y_total;
+
+       if (set) {
+               ft = div_u64(1000000000000llu, fps);
+               x_total =
+                   screen->mode.upper_margin + screen->mode.lower_margin +
+                   screen->mode.yres + screen->mode.vsync_len;
+               y_total =
+                   screen->mode.left_margin + screen->mode.right_margin +
+                   screen->mode.xres + screen->mode.hsync_len;
+               dev_drv->pixclock = div_u64(ft, x_total * y_total);
+               dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
+               ret = clk_set_rate(lcdc_dev->dclk, dotclk);
+       }
+
+       pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       lcdc_dev->pixclock = pixclock;
+       dev_drv->pixclock = pixclock;
+       fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
+       screen->ft = 1000 / fps;        /*one frame time in ms */
+
+       if (set)
+               dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
+                        clk_get_rate(lcdc_dev->dclk), fps);
+
+       return fps;
+}
+
+static int rk3036_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 int_reg;
+       int ret;
+
+       if (lcdc_dev->clk_on) {
+               int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
+               if (int_reg & m_LF_INT_STA) {
+                       lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
+                                    v_LF_INT_CLEAR(1));
+                       ret = RK_LF_STATUS_FC;
+               } else {
+                       ret = RK_LF_STATUS_FR;
+               }
+       } else {
+               ret = RK_LF_STATUS_NC;
+       }
+
+       return ret;
+}
+
+static int rk3036_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
+                                   unsigned int *dsp_addr)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       if (lcdc_dev->clk_on) {
+               dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+               dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
+       }
+       return 0;
+}
+
+static ssize_t rk3036_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
+                                        char *buf, int win_id)
+{
+       struct rk_lcdc_win *win = NULL;
+       char fmt[9] = "NULL";
+       u32     size;
+
+       if (win_id < ARRAY_SIZE(lcdc_win)) {
+               win = dev_drv->win[win_id];
+       } else {
+               dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
+               return 0;
+       }
+
+       size = snprintf(buf, PAGE_SIZE, "win%d: %s\n", win_id,
+                       get_format_string(win->format, fmt));
+       size += snprintf(buf + size, PAGE_SIZE - size,
+                        "      xact %d yact %d xvir %d yvir %d\n",
+               win->area[0].xact, win->area[0].yact,
+               win->area[0].xvir, win->area[0].yvir);
+       size += snprintf(buf + size, PAGE_SIZE - size,
+                        "      xpos %d ypos %d xsize %d ysize %d\n",
+               win->area[0].xpos, win->area[0].ypos,
+               win->area[0].xsize, win->area[0].ysize);
+       size += snprintf(buf + size, PAGE_SIZE - size,
+                        "      yaddr 0x%x uvaddr 0x%x\n",
+               win->area[0].y_addr, win->area[0].uv_addr);
+       return size;
+}
+
+static int rk3036_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                               struct lcdc_device,
+                                               driver);
+       int *cbase = (int *)lcdc_dev->regs;
+       int *regsbak = (int *)lcdc_dev->regsbak;
+       int i, j;
+
+       dev_info(dev_drv->dev, "back up reg:\n");
+       for (i = 0; i <= (0xDC >> 4); i++) {
+               for (j = 0; j < 4; j++)
+                       dev_info(dev_drv->dev, "%08x  ",
+                                *(regsbak + i * 4 + j));
+               dev_info(dev_drv->dev, "\n");
+       }
+
+       dev_info(dev_drv->dev, "lcdc reg:\n");
+       for (i = 0; i <= (0xDC >> 4); i++) {
+               for (j = 0; j < 4; j++)
+                       dev_info(dev_drv->dev, "%08x  ",
+                                readl_relaxed(cbase + i * 4 + j));
+               dev_info(dev_drv->dev, "\n");
+       }
+       return 0;
+}
+
+static struct rk_lcdc_drv_ops lcdc_drv_ops = {
+       .open                   = rk3036_lcdc_open,
+       .load_screen            = rk3036_load_screen,
+       .set_par                = rk3036_lcdc_set_par,
+       .pan_display            = rk3036_lcdc_pan_display,
+       .blank                  = rk3036_lcdc_blank,
+       .ioctl                  = rk3036_lcdc_ioctl,
+       .get_win_state          = rk3036_lcdc_get_win_state,
+       .ovl_mgr                = rk3036_lcdc_ovl_mgr,
+       .get_disp_info          = rk3036_lcdc_get_disp_info,
+       .fps_mgr                = rk3036_lcdc_fps_mgr,
+       .fb_get_win_id          = rk3036_lcdc_get_win_id,
+       .fb_win_remap           = rk3036_fb_win_remap,
+       .poll_vblank            = rk3036_lcdc_poll_vblank,
+       .get_dsp_addr           = rk3036_lcdc_get_dsp_addr,
+       .cfg_done               = rk3036_lcdc_cfg_done,
+       .dump_reg               = rk3036_lcdc_reg_dump,
+       .set_dsp_bcsh_hue       = rk3036_lcdc_set_bcsh_hue,
+       .set_dsp_bcsh_bcs       = rk3036_lcdc_set_bcsh_bcs,
+       .get_dsp_bcsh_hue       = rk3036_lcdc_get_bcsh_hue,
+       .get_dsp_bcsh_bcs       = rk3036_lcdc_get_bcsh_bcs,
+       .open_bcsh              = rk3036_lcdc_open_bcsh,
+       .set_overscan           = rk3036_lcdc_set_overscan,
+};
+
+static int rk3036_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
+{
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+       struct device_node *np = lcdc_dev->dev->of_node;
+       int val;
+
+       if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
+               lcdc_dev->driver.iommu_enabled = 0;
+       else
+               lcdc_dev->driver.iommu_enabled = val;
+#else
+       lcdc_dev->driver.iommu_enabled = 0;
+#endif
+       return 0;
+}
+
+static int rk3036_lcdc_probe(struct platform_device *pdev)
+{
+       struct lcdc_device *lcdc_dev = NULL;
+       struct rk_lcdc_driver *dev_drv;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int ret;
+
+       lcdc_dev = devm_kzalloc(dev,
+                               sizeof(struct lcdc_device), GFP_KERNEL);
+       if (!lcdc_dev) {
+               dev_err(&pdev->dev, "rk3036 lcdc device kmalloc fail!");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, lcdc_dev);
+       lcdc_dev->dev = dev;
+       rk3036_lcdc_parse_dt(lcdc_dev);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       lcdc_dev->reg_phy_base = res->start;
+       lcdc_dev->len = resource_size(res);
+       lcdc_dev->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(lcdc_dev->regs))
+               return PTR_ERR(lcdc_dev->regs);
+
+       lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
+       if (IS_ERR(lcdc_dev->regsbak))
+               return PTR_ERR(lcdc_dev->regsbak);
+
+       dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
+       dev_drv = &lcdc_dev->driver;
+       dev_drv->dev = dev;
+       dev_drv->prop = PRMRY;
+       dev_drv->id = lcdc_dev->id;
+       dev_drv->ops = &lcdc_drv_ops;
+       dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
+       spin_lock_init(&lcdc_dev->reg_lock);
+
+       lcdc_dev->irq = platform_get_irq(pdev, 0);
+       if (lcdc_dev->irq < 0) {
+               dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
+                       lcdc_dev->id);
+               return -ENXIO;
+       }
+
+       ret = devm_request_irq(dev, lcdc_dev->irq, rk3036_lcdc_isr,
+                              IRQF_DISABLED | IRQF_SHARED,
+                              dev_name(dev), lcdc_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
+                       lcdc_dev->irq, ret);
+               return ret;
+       }
+
+       if (dev_drv->iommu_enabled)
+               strcpy(dev_drv->mmu_dts_name, "iommu,vop_mmu");
+
+       ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
+       if (ret < 0) {
+               dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
+               return ret;
+       }
+       lcdc_dev->screen = dev_drv->screen0;
+
+       dev_info(dev, "lcdc probe ok, iommu %s\n",
+                dev_drv->iommu_enabled ? "enabled" : "disabled");
+
+       return 0;
+}
+
+#if defined(CONFIG_PM)
+static int rk3036_lcdc_suspend(struct platform_device *pdev,
+                              pm_message_t state)
+{
+       return 0;
+}
+
+static int rk3036_lcdc_resume(struct platform_device *pdev)
+{
+       return 0;
+}
+#else
+#define rk3036_lcdc_suspend NULL
+#define rk3036_lcdc_resume  NULL
+#endif
+
+static int rk3036_lcdc_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static void rk3036_lcdc_shutdown(struct platform_device *pdev)
+{
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk3036_lcdc_dt_ids[] = {
+       {.compatible = "rockchip,rk3036-lcdc",},
+       {}
+};
+#endif
+
+static struct platform_driver rk3036_lcdc_driver = {
+       .probe = rk3036_lcdc_probe,
+       .remove = rk3036_lcdc_remove,
+       .driver = {
+               .name = "rk3036-lcdc",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(rk3036_lcdc_dt_ids),
+       },
+       .suspend = rk3036_lcdc_suspend,
+       .resume = rk3036_lcdc_resume,
+       .shutdown = rk3036_lcdc_shutdown,
+};
+
+static int __init rk3036_lcdc_module_init(void)
+{
+       return platform_driver_register(&rk3036_lcdc_driver);
+}
+
+static void __exit rk3036_lcdc_module_exit(void)
+{
+       platform_driver_unregister(&rk3036_lcdc_driver);
+}
+
+fs_initcall(rk3036_lcdc_module_init);
+module_exit(rk3036_lcdc_module_exit);
\ No newline at end of file
diff --git a/drivers/video/rockchip/lcdc/rk3036_lcdc.h b/drivers/video/rockchip/lcdc/rk3036_lcdc.h
new file mode 100644 (file)
index 0000000..7919d38
--- /dev/null
@@ -0,0 +1,573 @@
+#ifndef _RK3036_LCDC_H_
+#define _RK3036_LCDC_H_
+
+#include<linux/rk_fb.h>
+#include<linux/io.h>
+#include<linux/clk.h>
+
+/*******************register definition**********************/
+
+#define SYS_CTRL               (0x00)
+       #define m_WIN0_EN               (1<<0)
+       #define m_WIN1_EN               (1<<1)
+       #define m_HWC_EN                (1<<2)
+       #define m_WIN0_FORMAT           (7<<3)
+       #define m_WIN1_FORMAT           (7<<6)
+       #define m_HWC_LUT_EN            (1<<9)
+       #define m_HWC_SIZE              (1<<10)
+       #define m_WIN0_RB_SWAP          (1<<15)
+       #define m_WIN0_ALPHA_SWAP       (1<<16)
+       #define m_WIN0_Y8_SWAP          (1<<17)
+       #define m_WIN0_UV_SWAP          (1<<18)
+       #define m_WIN1_RB_SWAP          (1<<19)
+       #define m_WIN1_ALPHA_SWAP       (1<<20)
+       #define m_WIN0_OTSD_DISABLE     (1<<22)
+       #define m_WIN1_OTSD_DISABLE     (1<<23)
+       #define m_DMA_BURST_LENGTH      (3<<24)
+       #define m_HWC_LODAD_EN          (1<<26)
+       #define m_DMA_STOP              (1<<29)
+       #define m_LCDC_STANDBY          (1<<30)
+       #define m_AUTO_GATING_EN        (1<<31)
+
+       #define v_WIN0_EN(x)            (((x)&1)<<0)
+       #define v_WIN1_EN(x)            (((x)&1)<<1)
+       #define v_HWC_EN(x)             (((x)&1)<<2)
+       #define v_WIN0_FORMAT(x)        (((x)&7)<<3)
+       #define v_WIN1_FORMAT(x)        (((x)&7)<<6)
+       #define v_HWC_LUT_EN(x)         (((x)&1)<<9)
+       #define v_HWC_SIZE(x)           (((x)&1)<<10)
+       #define v_WIN0_RB_SWAP(x)       (((x)&1)<<15)
+       #define v_WIN0_ALPHA_SWAP(x)    (((x)&1)<<16)
+       #define v_WIN0_Y8_SWAP(x)       (((x)&1)<<17)
+       #define v_WIN0_UV_SWAP(x)       (((x)&1)<<18)
+       #define v_WIN1_RB_SWAP(x)       (((x)&1)<<19)
+       #define v_WIN1_ALPHA_SWAP(x)    (((x)&1)<<20)
+       #define v_WIN0_OTSD_DISABLE(x)  (((x)&1)<<22)
+       #define v_WIN1_OTSD_DISABLE(x)  (((x)&1)<<23)
+       #define v_DMA_BURST_LENGTH(x)   (((x)&3)<<24)
+       #define v_HWC_LODAD_EN(x)       (((x)&1)<<26)
+       #define v_WIN1_LUT_EN(x)        (((x)&1)<<27)
+       #define v_DMA_STOP(x)           (((x)&1)<<29)
+       #define v_LCDC_STANDBY(x)       (((x)&1)<<30)
+       #define v_AUTO_GATING_EN(x)     (((x)&1)<<31)
+
+#define DSP_CTRL0              (0x04)
+       #define m_DSP_OUT_FORMAT        (0x0f<<0)
+       #define m_HSYNC_POL             (1<<4)
+       #define m_VSYNC_POL             (1<<5)
+       #define m_DEN_POL               (1<<6)
+       #define m_DCLK_POL              (1<<7)
+       #define m_WIN0_TOP              (1<<8)
+       #define m_DITHER_UP_EN          (1<<9)
+       #define m_INTERLACE_DSP_EN      (1<<12)
+       #define m_INTERLACE_DSP_POL     (1<<13)
+       #define m_WIN1_INTERLACE_EN     (1<<15)
+       #define m_WIN0_YRGB_DEFLICK_EN  (1<<16)
+       #define m_WIN0_CBR_DEFLICK_EN   (1<<17)
+       #define m_WIN0_ALPHA_MODE       (1<<18)
+       #define m_WIN1_ALPHA_MODE       (1<<19)
+       #define m_WIN0_CSC_MODE         (3<<20)
+       #define m_WIN0_YUV_CLIP         (1<<23)
+       #define m_TVE_MODE              (1<<25)
+       #define m_HWC_ALPHA_MODE        (1<<28)
+       #define m_PREMUL_ALPHA_ENABLE   (1<<29)
+       #define m_ALPHA_MODE_SEL1       (1<<30)
+       #define m_WIN1_DIFF_DCLK_EN     (1<<31)
+
+       #define v_DSP_OUT_FORMAT(x)     (((x)&0x0f)<<0)
+       #define v_HSYNC_POL(x)          (((x)&1)<<4)
+       #define v_VSYNC_POL(x)          (((x)&1)<<5)
+       #define v_DEN_POL(x)            (((x)&1)<<6)
+       #define v_DCLK_POL(x)           (((x)&1)<<7)
+       #define v_WIN0_TOP(x)           (((x)&1)<<8)
+       #define v_DITHER_UP_EN(x)       (((x)&1)<<9)
+       #define v_INTERLACE_DSP_EN(x)   (((x)&1)<<12)
+       #define v_INTERLACE_DSP_POL(x)  (((x)&1)<<13)
+       #define v_WIN1_INTERLACE_EN(x)  (((x)&1)<<15)
+       #define v_WIN0_YRGB_DEFLICK_EN(x)       (((x)&1)<<16)
+       #define v_WIN0_CBR_DEFLICK_EN(x)        (((x)&1)<<17)
+       #define v_WIN0_ALPHA_MODE(x)            (((x)&1)<<18)
+       #define v_WIN1_ALPHA_MODE(x)            (((x)&1)<<19)
+       #define v_WIN0_CSC_MODE(x)              (((x)&3)<<20)
+       #define v_WIN0_YUV_CLIP(x)              (((x)&1)<<23)
+       #define v_TVE_MODE(x)                   (((x)&1)<<25)
+       #define v_HWC_ALPHA_MODE(x)             (((x)&1)<<28)
+       #define v_PREMUL_ALPHA_ENABLE(x)        (((x)&1)<<29)
+       #define v_ALPHA_MODE_SEL1(x)            (((x)&1)<<30)
+       #define v_WIN1_DIFF_DCLK_EN(x)          (((x)&1)<<31)
+
+#define DSP_CTRL1              (0x08)
+       #define m_BG_COLOR              (0xffffff<<0)
+       #define m_BG_B                  (0xff<<0)
+       #define m_BG_G                  (0xff<<8)
+       #define m_BG_R                  (0xff<<16)
+       #define m_BLANK_EN              (1<<24)
+       #define m_BLACK_EN              (1<<25)
+       #define m_DSP_BG_SWAP           (1<<26)
+       #define m_DSP_RB_SWAP           (1<<27)
+       #define m_DSP_RG_SWAP           (1<<28)
+       #define m_DSP_DELTA_SWAP        (1<<29)
+       #define m_DSP_DUMMY_SWAP        (1<<30)
+       #define m_DSP_OUT_ZERO          (1<<31)
+
+       #define v_BG_COLOR(x)           (((x)&0xffffff)<<0)
+       #define v_BG_B(x)               (((x)&0xff)<<0)
+       #define v_BG_G(x)               (((x)&0xff)<<8)
+       #define v_BG_R(x)               (((x)&0xff)<<16)
+       #define v_BLANK_EN(x)           (((x)&1)<<24)
+       #define v_BLACK_EN(x)           (((x)&1)<<25)
+       #define v_DSP_BG_SWAP(x)        (((x)&1)<<26)
+       #define v_DSP_RB_SWAP(x)        (((x)&1)<<27)
+       #define v_DSP_RG_SWAP(x)        (((x)&1)<<28)
+       #define v_DSP_DELTA_SWAP(x)     (((x)&1)<<29)
+       #define v_DSP_DUMMY_SWAP(x)     (((x)&1)<<30)
+       #define v_DSP_OUT_ZERO(x)       (((x)&1)<<31)
+
+#define INT_STATUS             (0x10)
+       #define m_HS_INT_STA            (1<<0) /* status */
+       #define m_FS_INT_STA            (1<<1)
+       #define m_LF_INT_STA            (1<<2)
+       #define m_BUS_ERR_INT_STA       (1<<3)
+       #define m_HS_INT_EN             (1<<4) /* enable */
+       #define m_FS_INT_EN             (1<<5)
+       #define m_LF_INT_EN             (1<<6)
+       #define m_BUS_ERR_INT_EN        (1<<7)
+       #define m_HS_INT_CLEAR          (1<<8) /* auto clear*/
+       #define m_FS_INT_CLEAR          (1<<9)
+       #define m_LF_INT_CLEAR          (1<<10)
+       #define m_BUS_ERR_INT_CLEAR     (1<<11)
+       #define m_LF_INT_NUM            (0xfff<<12)
+       #define m_WIN0_EMPTY_INT_EN     (1<<24)
+       #define m_WIN1_EMPTY_INT_EN     (1<<25)
+       #define m_WIN0_EMPTY_INT_CLEAR  (1<<26)
+       #define m_WIN1_EMPTY_INT_CLEAR  (1<<27)
+       #define m_WIN0_EMPTY_INT_STA    (1<<28)
+       #define m_WIN1_EMPTY_INT_STA    (1<<29)
+       #define m_FS_RAW_STA            (1<<30)
+       #define m_LF_RAW_STA            (1<<31)
+
+       #define v_HS_INT_EN(x)                  (((x)&1)<<4)
+       #define v_FS_INT_EN(x)                  (((x)&1)<<5)
+       #define v_LF_INT_EN(x)                  (((x)&1)<<6)
+       #define v_BUS_ERR_INT_EN(x)             (((x)&1)<<7)
+       #define v_HS_INT_CLEAR(x)               (((x)&1)<<8)
+       #define v_FS_INT_CLEAR(x)               (((x)&1)<<9)
+       #define v_LF_INT_CLEAR(x)               (((x)&1)<<10)
+       #define v_BUS_ERR_INT_CLEAR(x)          (((x)&1)<<11)
+       #define v_LF_INT_NUM(x)                 (((x)&0xfff)<<12)
+       #define v_WIN0_EMPTY_INT_EN(x)          (((x)&1)<<24)
+       #define v_WIN1_EMPTY_INT_EN(x)          (((x)&1)<<25)
+       #define v_WIN0_EMPTY_INT_CLEAR(x)       (((x)&1)<<26)
+       #define v_WIN1_EMPTY_INT_CLEAR(x)       (((x)&1)<<27)
+
+
+#define ALPHA_CTRL             (0x14)
+       #define m_WIN0_ALPHA_EN         (1<<0)
+       #define m_WIN1_ALPHA_EN         (1<<1)
+       #define m_HWC_ALPAH_EN          (1<<2)
+       #define m_WIN1_PREMUL_SCALE     (1<<3)
+       #define m_WIN0_ALPHA_VAL        (0xff<<4)
+       #define m_WIN1_ALPHA_VAL        (0xff<<12)
+       #define m_HWC_ALPAH_VAL         (0xff<<20)
+
+       #define v_WIN0_ALPHA_EN(x)      (((x)&1)<<0)
+       #define v_WIN1_ALPHA_EN(x)      (((x)&1)<<1)
+       #define v_HWC_ALPAH_EN(x)       (((x)&1)<<2)
+       #define v_WIN1_PREMUL_SCALE(x)  (((x)&1)<<3)
+       #define v_WIN0_ALPHA_VAL(x)     (((x)&0xff)<<4)
+       #define v_WIN1_ALPHA_VAL(x)     (((x)&0xff)<<12)
+       #define v_HWC_ALPAH_VAL(x)      (((x)&0xff)<<20)
+
+#define WIN0_COLOR_KEY         (0x18)
+#define WIN1_COLOR_KEY         (0x1C)
+       #define m_COLOR_KEY_VAL         (0xffffff<<0)
+       #define m_COLOR_KEY_EN          (1<<24)
+       #define v_COLOR_KEY_VAL(x)      (((x)&0xffffff)<<0)
+       #define v_COLOR_KEY_EN(x)       (((x)&1)<<24)
+
+/* Layer Registers */
+#define WIN0_YRGB_MST          (0x20)
+#define WIN0_CBR_MST           (0x24)
+#define WIN1_MST               (0xa0)
+#define HWC_MST                        (0x58)
+
+#define WIN1_VIR               (0x28)
+#define WIN0_VIR               (0x30)
+       #define m_YRGB_VIR      (0x1fff << 0)
+       #define m_CBBR_VIR      (0x1fff << 16)
+
+       #define v_YRGB_VIR(x)   ((x & 0x1fff) << 0)
+       #define v_CBBR_VIR(x)   ((x & 0x1fff) << 16)
+
+       #define v_ARGB888_VIRWIDTH(x)   (((x) & 0x1fff) << 0)
+       #define v_RGB888_VIRWIDTH(x)    (((((x * 3) >> 2)+(x % 3))&0x1fff)<<0)
+       #define v_RGB565_VIRWIDTH(x)    ((DIV_ROUND_UP(x, 2)&0x1fff)<<0)
+       #define v_YUV_VIRWIDTH(x)       ((DIV_ROUND_UP(x, 4)&0x1fff)<<0)
+       #define v_CBCR_VIR(x)           ((x & 0x1fff) << 16)
+
+#define WIN0_ACT_INFO          (0x34)
+#define WIN1_ACT_INFO          (0xB4)
+       #define m_ACT_WIDTH             (0x1fff << 0)
+       #define m_ACT_HEIGHT            (0x1fff << 16)
+       #define v_ACT_WIDTH(x)          (((x-1) & 0x1fff)<<0)
+       #define v_ACT_HEIGHT(x)         (((x-1) & 0x1fff)<<16)
+
+#define WIN0_DSP_INFO          (0x38)
+#define WIN1_DSP_INFO          (0xB8)
+       #define v_DSP_WIDTH(x)          (((x-1)&0x7ff)<<0)
+       #define v_DSP_HEIGHT(x)         (((x-1)&0x7ff)<<16)
+
+#define WIN0_DSP_ST            (0x3C)
+#define WIN1_DSP_ST            (0xBC)
+#define HWC_DSP_ST             (0x5C)
+       #define v_DSP_STX(x)            (((x)&0xfff)<<0)
+       #define v_DSP_STY(x)            (((x)&0xfff)<<16)
+
+#define WIN0_SCL_FACTOR_YRGB   (0x40)
+#define WIN0_SCL_FACTOR_CBR    (0x44)
+#define WIN1_SCL_FACTOR_YRGB   (0xC0)
+       #define v_X_SCL_FACTOR(x)       (((x)&0xffff)<<0)
+       #define v_Y_SCL_FACTOR(x)       (((x)&0xffff)<<16)
+
+#define WIN0_SCL_OFFSET                (0x48)
+#define WIN1_SCL_OFFSET                (0xC8)
+
+/* LUT Registers */
+#define WIN1_LUT_ADDR                  (0x0400)
+#define HWC_LUT_ADDR                   (0x0800)
+
+/* Display Infomation Registers */
+#define DSP_HTOTAL_HS_END      (0x6C)
+       /*hsync pulse width*/
+       #define v_HSYNC(x)              (((x)&0xfff)<<0)
+       /*horizontal period*/
+       #define v_HORPRD(x)             (((x)&0xfff)<<16)
+
+#define DSP_HACT_ST_END                (0x70)
+       /*horizontal active end point*/
+       #define v_HAEP(x)               (((x)&0xfff)<<0)
+       /*horizontal active start point*/
+       #define v_HASP(x)               (((x)&0xfff)<<16)
+
+#define DSP_VTOTAL_VS_END      (0x74)
+       #define v_VSYNC(x)              (((x)&0xfff)<<0)
+       #define v_VERPRD(x)             (((x)&0xfff)<<16)
+
+#define DSP_VACT_ST_END                (0x78)
+       #define v_VAEP(x)               (((x)&0xfff)<<0)
+       #define v_VASP(x)               (((x)&0xfff)<<16)
+
+#define DSP_VS_ST_END_F1       (0x7C)
+       #define v_VSYNC_END_F1(x)       (((x)&0xfff)<<0)
+       #define v_VSYNC_ST_F1(x)        (((x)&0xfff)<<16)
+#define DSP_VACT_ST_END_F1     (0x80)
+
+/*BCSH Registers*/
+#define BCSH_CTRL                      (0xD0)
+       #define m_BCSH_EN               (1 << 0)
+       #define m_BCSH_OUT_MODE         (3 << 2)
+       #define m_BCSH_CSC_MODE         (3 << 4)
+
+       #define v_BCSH_EN(x)            ((1 & x) << 0)
+       #define v_BCSH_OUT_MODE(x)      ((3 & x) << 2)
+       #define v_BCSH_CSC_MODE(x)      ((3 & x) << 4)
+
+#define BCSH_COLOR_BAR                 (0xD4)
+       #define v_BCSH_COLOR_BAR_Y(x)           (((x)&0xf) << 0)
+       #define v_BCSH_COLOR_BAR_U(x)           (((x)&0xf) << 8)
+       #define v_BCSH_COLOR_BAR_V(x)           (((x)&0xf) << 16)
+
+       #define m_BCSH_COLOR_BAR_Y              (0xf << 0)
+       #define m_BCSH_COLOR_BAR_U              (0xf << 8)
+       #define m_BCSH_COLOR_BAR_V              (0xf << 16)
+
+#define BCSH_BCS                       (0xD8)
+       #define v_BCSH_BRIGHTNESS(x)            (((x)&0x3f) << 0)
+       #define v_BCSH_CONTRAST(x)              (((x)&0xff) << 8)
+       #define v_BCSH_SAT_CON(x)               (((x)&0x1ff) << 16)
+
+       #define m_BCSH_BRIGHTNESS               (0x3f << 0)
+       #define m_BCSH_CONTRAST                 (0xff << 8)
+       #define m_BCSH_SAT_CON                  (0x1ff << 16)
+
+#define BCSH_H                         (0xDC)
+       #define v_BCSH_SIN_HUE(x)               (((x)&0xff) << 0)
+       #define v_BCSH_COS_HUE(x)               (((x)&0xff) << 8)
+
+       #define m_BCSH_SIN_HUE                  (0xff << 0)
+       #define m_BCSH_COS_HUE                  (0xff << 8)
+
+/* Bus Register */
+#define AXI_BUS_CTRL           (0x2C)
+       #define m_IO_PAD_CLK                    (1 << 31)
+       #define m_CORE_CLK_DIV_EN               (1 << 30)
+       #define m_HDMI_DCLK_INVERT              (1 << 23)
+       #define m_HDMI_DCLK_EN                  (1 << 22)
+       #define m_TVE_DAC_DCLK_INVERT           (1 << 21)
+       #define m_TVE_DAC_DCLK_EN               (1 << 20)
+       #define m_HDMI_DCLK_DIV_EN              (1 << 19)
+       #define m_AXI_OUTSTANDING_MAX_NUM       (0x1f << 12)
+       #define m_AXI_MAX_OUTSTANDING_EN        (1 << 11)
+       #define m_MMU_EN                        (1 << 10)
+       #define m_NOC_HURRY_THRESHOLD           (0xf << 6)
+       #define m_NOC_HURRY_VALUE               (3 << 4)
+       #define m_NOC_HURRY_EN                  (1 << 3)
+       #define m_NOC_QOS_VALUE                 (3 << 1)
+       #define m_NOC_QOS_EN                    (1 << 0)
+
+       #define v_IO_PAD_CLK(x)                 ((x&1) << 31)
+       #define v_CORE_CLK_DIV_EN(x)            ((x&1) << 30)
+       #define v_HDMI_DCLK_INVERT(x)           ((x&1) << 23)
+       #define v_HDMI_DCLK_EN(x)               ((x&1) << 22)
+       #define v_TVE_DAC_DCLK_INVERT(x)        ((x&1) << 21)
+       #define v_TVE_DAC_DCLK_EN(x)            ((x&1) << 20)
+       #define v_HDMI_DCLK_DIV_EN(x)           ((x&1) << 19)
+       #define v_AXI_OUTSTANDING_MAX_NUM(x)    ((x&0x1f) << 12)
+       #define v_AXI_MAX_OUTSTANDING_EN(x)     ((x&1) << 11)
+       #define v_MMU_EN(x)                     ((x&1) << 10)
+       #define v_NOC_HURRY_THRESHOLD(x)        ((x&0xf) << 6)
+       #define v_NOC_HURRY_VALUE(x)            ((x&3) << 4)
+       #define v_NOC_HURRY_EN(x)               ((x&1) << 3)
+       #define v_NOC_QOS_VALUE(x)              ((x&3) << 1)
+       #define v_NOC_QOS_EN(x)                 ((x&1) << 0)
+
+#define GATHER_TRANSFER                (0x84)
+       #define m_WIN1_AXI_GATHER_NUM           (0xf << 12)
+       #define m_WIN0_CBCR_AXI_GATHER_NUM      (0x7 << 8)
+       #define m_WIN0_YRGB_AXI_GATHER_NUM      (0xf << 4)
+       #define m_WIN1_AXI_GAHTER_EN            (1 << 2)
+       #define m_WIN0_CBCR_AXI_GATHER_EN       (1 << 1)
+       #define m_WIN0_YRGB_AXI_GATHER_EN       (1 << 0)
+
+       #define v_WIN1_AXI_GATHER_NUM(x)        ((x & 0xf) << 12)
+       #define v_WIN0_CBCR_AXI_GATHER_NUM(x)   ((x & 0x7) << 8)
+       #define v_WIN0_YRGB_AXI_GATHER_NUM(x)   ((x & 0xf) << 4)
+       #define v_WIN1_AXI_GAHTER_EN(x)         ((x & 1) << 2)
+       #define v_WIN0_CBCR_AXI_GATHER_EN(x)    ((x & 1) << 1)
+       #define v_WIN0_YRGB_AXI_GATHER_EN(x)    ((x & 1) << 0)
+
+#define VERSION_INFO           (0x94)
+       #define m_MAJOR         (0xff << 24)
+       #define m_MINOR         (0xff << 16)
+       #define m_BUILD         (0xffff)
+
+#define REG_CFG_DONE           (0x90)
+
+/* TV Control Registers */
+#define TV_CTRL                        (0x200)
+#define TV_SYNC_TIMING         (0x204)
+#define TV_ACT_TIMING          (0x208)
+#define TV_ADJ_TIMING          (0x20c)
+#define TV_FREQ_SC             (0x210)
+#define TV_FILTER0             (0x214)
+#define TV_FILTER1             (0x218)
+#define TV_FILTER2             (0x21C)
+#define TV_ACT_ST              (0x234)
+#define TV_ROUTING             (0x238)
+#define TV_SYNC_ADJUST         (0x250)
+#define TV_STATUS              (0x254)
+#define TV_RESET               (0x268)
+#define TV_SATURATION          (0x278)
+#define TV_BW_CTRL             (0x28C)
+#define TV_BRIGHTNESS_CONTRAST (0x290)
+
+
+/* MMU registers */
+#define MMU_DTE_ADDR                   (0x0300)
+       #define v_MMU_DTE_ADDR(x)               (((x)&0xffffffff)<<0)
+       #define m_MMU_DTE_ADDR                  (0xffffffff<<0)
+
+#define MMU_STATUS                     (0x0304)
+       #define v_PAGING_ENABLED(x)             (((x)&1)<<0)
+       #define v_PAGE_FAULT_ACTIVE(x)          (((x)&1)<<1)
+       #define v_STAIL_ACTIVE(x)               (((x)&1)<<2)
+       #define v_MMU_IDLE(x)                   (((x)&1)<<3)
+       #define v_REPLAY_BUFFER_EMPTY(x)        (((x)&1)<<4)
+       #define v_PAGE_FAULT_IS_WRITE(x)        (((x)&1)<<5)
+       #define v_PAGE_FAULT_BUS_ID(x)          (((x)&0x1f)<<6)
+       #define m_PAGING_ENABLED                (1<<0)
+       #define m_PAGE_FAULT_ACTIVE             (1<<1)
+       #define m_STAIL_ACTIVE                  (1<<2)
+       #define m_MMU_IDLE                      (1<<3)
+       #define m_REPLAY_BUFFER_EMPTY           (1<<4)
+       #define m_PAGE_FAULT_IS_WRITE           (1<<5)
+       #define m_PAGE_FAULT_BUS_ID             (0x1f<<6)
+
+#define MMU_COMMAND                    (0x0308)
+       #define v_MMU_CMD(x)                    (((x)&0x3)<<0)
+       #define m_MMU_CMD                       (0x3<<0)
+
+#define MMU_PAGE_FAULT_ADDR            (0x030c)
+       #define v_PAGE_FAULT_ADDR(x)            (((x)&0xffffffff)<<0)
+       #define m_PAGE_FAULT_ADDR               (0xffffffff<<0)
+
+#define MMU_ZAP_ONE_LINE               (0x0310)
+       #define v_MMU_ZAP_ONE_LINE(x)           (((x)&0xffffffff)<<0)
+       #define m_MMU_ZAP_ONE_LINE              (0xffffffff<<0)
+
+#define MMU_INT_RAWSTAT                        (0x0314)
+       #define v_PAGE_FAULT_RAWSTAT(x)         (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_RAWSTAT(x)     (((x)&1)<<1)
+       #define m_PAGE_FAULT_RAWSTAT            (1<<0)
+       #define m_READ_BUS_ERROR_RAWSTAT        (1<<1)
+
+#define MMU_INT_CLEAR                  (0x0318)
+       #define v_PAGE_FAULT_CLEAR(x)           (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_CLEAR(x)       (((x)&1)<<1)
+       #define m_PAGE_FAULT_CLEAR              (1<<0)
+       #define m_READ_BUS_ERROR_CLEAR          (1<<1)
+
+#define MMU_INT_MASK                   (0x031c)
+       #define v_PAGE_FAULT_MASK(x)            (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_MASK(x)        (((x)&1)<<1)
+       #define m_PAGE_FAULT_MASK               (1<<0)
+       #define m_READ_BUS_ERROR_MASK           (1<<1)
+
+#define MMU_INT_STATUS                 (0x0320)
+       #define v_PAGE_FAULT_STATUS(x)          (((x)&1)<<0)
+       #define v_READ_BUS_ERROR_STATUS(x)      (((x)&1)<<1)
+       #define m_PAGE_FAULT_STATUS             (1<<0)
+       #define m_READ_BUS_ERROR_STATUS         (1<<1)
+
+#define MMU_AUTO_GATING                        (0x0324)
+       #define v_MMU_AUTO_GATING(x)            (((x)&1)<<0)
+       #define m_MMU_AUTO_GATING               (1<<0)
+
+enum _vop_dma_burst {
+       DMA_BURST_16 = 0,
+       DMA_BURST_8,
+       DMA_BURST_4
+};
+
+enum _vop_format_e {
+       VOP_FORMAT_ARGB888 = 0,
+       VOP_FORMAT_RGB888,
+       VOP_FORMAT_RGB565,
+       VOP_FORMAT_YCBCR420 = 4,
+       VOP_FORMAT_YCBCR422,
+       VOP_FORMAT_YCBCR444
+};
+
+enum _vop_tv_mode {
+       TV_NTSC,
+       TV_PAL,
+};
+
+enum _vop_csc_mode {
+       VOP_CSC_BT601 = 0,
+       VOP_CSC_JPEG,
+       VOP_CSC_BT709
+};
+
+enum _vop_hwc_size {
+       VOP_HWC_SIZE_32,
+       VOP_HWC_SIZE_64
+};
+
+#define calscale(x, y)         ((((u32)(x-1))*0x1000)/(y-1))
+
+struct lcdc_device {
+       int id;
+       struct rk_lcdc_driver driver;
+       struct device *dev;
+       struct rk_screen *screen;
+
+       void __iomem *regs;
+       void *regsbak;          /* back up reg */
+       u32 reg_phy_base;       /* physical basic address of lcdc register*/
+       u32 len;                /* physical map length of lcdc register*/
+       spinlock_t  reg_lock;   /* one time only one process allowed to
+                                  config the register*/
+
+       int __iomem *dsp_lut_addr_base;
+
+
+       int prop;                       /*used for primary or */
+                                       /*extended display device*/
+       bool pre_init;
+       bool pwr18;                     /*if lcdc use 1.8v power supply*/
+       bool clk_on;                    /*if aclk or hclk is closed,
+                                         acess to register is not allowed*/
+       u8 atv_layer_cnt;               /*active layer counter, when
+                                         atv_layer_cnt = 0,disable lcdc*/
+
+       unsigned int            irq;
+
+       struct clk              *pd;    /*lcdc power domain*/
+       struct clk              *hclk;  /*lcdc AHP clk*/
+       struct clk              *dclk;  /*lcdc dclk*/
+       struct clk              *aclk;  /*lcdc share memory frequency*/
+       u32 pixclock;
+
+       u32 standby;                    /*1:standby,0:work*/
+};
+
+static inline
+void lcdc_writel(struct lcdc_device *lcdc_dev, u32 offset, u32 v)
+{
+       u32 *_pv = (u32 *)lcdc_dev->regsbak;
+
+       _pv += (offset >> 2);
+       *_pv = v;
+       writel_relaxed(v, lcdc_dev->regs + offset);
+}
+
+static inline
+u32 lcdc_readl(struct lcdc_device *lcdc_dev, u32 offset)
+{
+       u32 v;
+       u32 *_pv = (u32 *)lcdc_dev->regsbak;
+
+       _pv += (offset >> 2);
+       v = readl_relaxed(lcdc_dev->regs + offset);
+       *_pv = v;
+       return v;
+}
+
+static inline
+u32 lcdc_read_bit(struct lcdc_device *lcdc_dev, u32 offset, u32 msk)
+{
+       u32 _v = readl_relaxed(lcdc_dev->regs + offset);
+
+       _v &= msk;
+       return _v ? 1 : 0;
+}
+
+static inline
+void  lcdc_set_bit(struct lcdc_device *lcdc_dev, u32 offset, u32 msk)
+{
+       u32 *_pv = (u32 *)lcdc_dev->regsbak;
+
+       _pv += (offset >> 2);
+       (*_pv) |= msk;
+       writel_relaxed(*_pv, lcdc_dev->regs + offset);
+}
+
+static inline
+void lcdc_clr_bit(struct lcdc_device *lcdc_dev, u32 offset, u32 msk)
+{
+       u32 *_pv = (u32 *)lcdc_dev->regsbak;
+
+       _pv += (offset >> 2);
+       (*_pv) &= (~msk);
+       writel_relaxed(*_pv, lcdc_dev->regs + offset);
+}
+
+static inline
+void  lcdc_msk_reg(struct lcdc_device *lcdc_dev, u32 offset, u32 msk, u32 v)
+{
+       u32 *_pv = (u32 *)lcdc_dev->regsbak;
+
+       _pv += (offset >> 2);
+       (*_pv) &= (~msk);
+       (*_pv) |= v;
+       writel_relaxed(*_pv, lcdc_dev->regs + offset);
+}
+
+static inline void lcdc_cfg_done(struct lcdc_device *lcdc_dev)
+{
+       writel_relaxed(0x01, lcdc_dev->regs + REG_CFG_DONE);
+       dsb();
+}
+
+#endif /* _RK3036_LCDC_H_ */
diff --git a/drivers/video/rockchip/lcdc/rk312x_lcdc.c b/drivers/video/rockchip/lcdc/rk312x_lcdc.c
new file mode 100755 (executable)
index 0000000..792757c
--- /dev/null
@@ -0,0 +1,2005 @@
+/*
+ * drivers/video/rockchip/lcdc/rk312x_lcdc.c
+ *
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ * Author:      zhuangwenlong<zwl@rock-chips.com>
+ *              zhengyang<zhengyang@rock-chips.com>
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <asm/div64.h>
+#include <asm/uaccess.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/common.h>
+#include <dt-bindings/clock/rk_system_status.h>
+#if defined(CONFIG_ION_ROCKCHIP)
+#include <linux/rockchip/iovmm.h>
+#include <linux/rockchip/sysmmu.h>
+#endif
+#include "rk312x_lcdc.h"
+
+static int dbg_thresd;
+module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
+
+#define DBG(level, x...) do {                  \
+       if (unlikely(dbg_thresd >= level))      \
+               printk(KERN_INFO x); } while (0)
+
+static struct rk_lcdc_win lcdc_win[] = {
+       [0] = {
+              .name = "win0",
+              .id = 0,
+              .support_3d = false,
+              },
+       [1] = {
+              .name = "win1",
+              .id = 1,
+              .support_3d = false,
+              },
+       [2] = {
+              .name = "hwc",
+              .id = 2,
+              .support_3d = false,
+              },
+};
+
+static irqreturn_t rk312x_lcdc_isr(int irq, void *dev_id)
+{
+       struct lcdc_device *lcdc_dev = (struct lcdc_device *)dev_id;
+       ktime_t timestamp = ktime_get();
+       u32 int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
+
+       if (int_reg & m_FS_INT_STA) {
+               timestamp = ktime_get();
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
+                            v_FS_INT_CLEAR(1));
+               //if (lcdc_dev->driver.wait_fs) {
+               if (0) {
+                       spin_lock(&(lcdc_dev->driver.cpl_lock));
+                       complete(&(lcdc_dev->driver.frame_done));
+                       spin_unlock(&(lcdc_dev->driver.cpl_lock));
+               }
+               lcdc_dev->driver.vsync_info.timestamp = timestamp;
+               wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
+
+       } else if (int_reg & m_LF_INT_STA) {
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
+                            v_LF_INT_CLEAR(1));
+       }
+       return IRQ_HANDLED;
+}
+
+static int rk312x_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
+{
+#ifdef CONFIG_RK_FPGA
+       lcdc_dev->clk_on = 1;
+       return 0;
+#endif
+       if (!lcdc_dev->clk_on) {
+               clk_prepare_enable(lcdc_dev->hclk);
+               clk_prepare_enable(lcdc_dev->dclk);
+               clk_prepare_enable(lcdc_dev->aclk);
+//              clk_prepare_enable(lcdc_dev->pd);
+               spin_lock(&lcdc_dev->reg_lock);
+               lcdc_dev->clk_on = 1;
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+
+       return 0;
+}
+
+static int rk312x_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
+{
+#ifdef CONFIG_RK_FPGA
+       lcdc_dev->clk_on = 0;
+       return 0;
+#endif
+       if (lcdc_dev->clk_on) {
+               spin_lock(&lcdc_dev->reg_lock);
+               lcdc_dev->clk_on = 0;
+               spin_unlock(&lcdc_dev->reg_lock);
+               mdelay(25);
+               clk_disable_unprepare(lcdc_dev->dclk);
+               clk_disable_unprepare(lcdc_dev->hclk);
+               clk_disable_unprepare(lcdc_dev->aclk);
+//              clk_disable_unprepare(lcdc_dev->pd);
+       }
+
+       return 0;
+}
+
+static int rk312x_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask, val;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+        struct rk_screen *screen = dev_drv->cur_screen;
+
+        spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_FS_INT_CLEAR | m_FS_INT_EN |
+                        m_LF_INT_CLEAR | m_LF_INT_EN | m_LF_INT_NUM |
+                        m_BUS_ERR_INT_CLEAR | m_BUS_ERR_INT_EN;
+               val = v_FS_INT_CLEAR(1) | v_FS_INT_EN(1) |
+                        v_LF_INT_CLEAR(1) | v_LF_INT_EN(1) |
+                        v_BUS_ERR_INT_CLEAR(1) | v_BUS_ERR_INT_EN(0) |
+                       v_LF_INT_NUM(screen->mode.vsync_len +
+                                    screen->mode.upper_margin +
+                                    screen->mode.yres);
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+                spin_unlock(&lcdc_dev->reg_lock);
+        } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+       return 0;
+}
+
+static int rk312x_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
+{
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_FS_INT_CLEAR | m_FS_INT_EN |
+                        m_LF_INT_CLEAR | m_LF_INT_EN |
+                        m_BUS_ERR_INT_CLEAR | m_BUS_ERR_INT_EN;
+               val = v_FS_INT_CLEAR(0) | v_FS_INT_EN(0) |
+                        v_LF_INT_CLEAR(0) | v_LF_INT_EN(0) |
+                        v_BUS_ERR_INT_CLEAR(0) | v_BUS_ERR_INT_EN(0);
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+       mdelay(1);
+       return 0;
+}
+
+static void rk_lcdc_read_reg_defalut_cfg(struct lcdc_device *lcdc_dev)
+{
+       int reg = 0;
+       u32 value = 0;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       for (reg = 0; reg < 0xdc; reg += 4) {
+               value = lcdc_readl(lcdc_dev, reg);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk312x_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
+{
+        int win0_top = 0;
+       u32 mask, val;
+       enum data_format win0_format = lcdc_dev->driver.win[0]->format;
+       enum data_format win1_format = lcdc_dev->driver.win[1]->format;
+
+       int win0_alpha_en = ((win0_format == ARGB888)
+                            || (win0_format == ABGR888)) ? 1 : 0;
+       int win1_alpha_en = ((win1_format == ARGB888)
+                            || (win1_format == ABGR888)) ? 1 : 0;
+       u32 *_pv = (u32 *) lcdc_dev->regsbak;
+
+       _pv += (DSP_CTRL0 >> 2);
+       win0_top = ((*_pv) & (m_WIN0_TOP)) >> 8;
+       if (win0_top && (lcdc_dev->atv_layer_cnt >= 2) && (win0_alpha_en)) {
+               mask =  m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN;
+               val = v_WIN0_ALPHA_EN(1) | v_WIN1_ALPHA_EN(0);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+
+               mask = m_WIN0_ALPHA_MODE | m_ALPHA_MODE_SEL0 | m_ALPHA_MODE_SEL1;
+               val = v_WIN0_ALPHA_MODE(1) | v_ALPHA_MODE_SEL0(1) | v_ALPHA_MODE_SEL1(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+       } else if ((!win0_top) && (lcdc_dev->atv_layer_cnt >= 2)
+                  && (win1_alpha_en)) {
+               mask =  m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN;
+               val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(1);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+
+               mask = m_WIN1_ALPHA_MODE | m_ALPHA_MODE_SEL0 | m_ALPHA_MODE_SEL1;
+               val = v_WIN1_ALPHA_MODE(1) | v_ALPHA_MODE_SEL0(1) | v_ALPHA_MODE_SEL1(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+       } else {
+               mask = m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN;
+               val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(0);
+               lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
+       }
+
+       return 0;
+}
+
+static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
+                                  struct rk_lcdc_win *win)
+{
+       u32 mask, val;
+
+       if (win->state == 1) {
+               if (win->id == 0) {
+                       mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP;
+                       val = v_WIN0_EN(win->state) |
+                                v_WIN0_FORMAT(win->fmt_cfg) |
+                                v_WIN0_RB_SWAP(win->swap_rb);
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+
+                       lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB,
+                                   v_X_SCL_FACTOR(win->scale_yrgb_x) |
+                                   v_Y_SCL_FACTOR(win->scale_yrgb_y));
+                       lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR,
+                                   v_X_SCL_FACTOR(win->scale_cbcr_x) |
+                                   v_Y_SCL_FACTOR(win->scale_cbcr_y));
+
+                       lcdc_msk_reg(lcdc_dev, WIN0_VIR,
+                                    m_YRGB_VIR | m_CBBR_VIR,
+                                    v_YRGB_VIR(win->area[0].y_vir_stride) |
+                                    v_CBCR_VIR(win->area[0].uv_vir_stride));
+                       lcdc_writel(lcdc_dev, WIN0_ACT_INFO,
+                                   v_ACT_WIDTH(win->area[0].xact) |
+                                   v_ACT_HEIGHT(win->area[0].yact));
+                       lcdc_writel(lcdc_dev, WIN0_DSP_ST,
+                                   v_DSP_STX(win->area[0].dsp_stx) |
+                                   v_DSP_STY(win->area[0].dsp_sty));
+                       lcdc_writel(lcdc_dev, WIN0_DSP_INFO,
+                                   v_DSP_WIDTH(win->area[0].xsize) |
+                                   v_DSP_HEIGHT(win->area[0].ysize));
+
+                       lcdc_writel(lcdc_dev, WIN0_YRGB_MST,
+                                   win->area[0].y_addr);
+                       lcdc_writel(lcdc_dev, WIN0_CBR_MST,
+                                   win->area[0].uv_addr);
+               } else if (win->id == 1) {
+                       mask = m_WIN1_EN | m_WIN1_FORMAT | m_WIN1_RB_SWAP;
+                       val = v_WIN1_EN(win->state) |
+                                v_WIN1_FORMAT(win->fmt_cfg) |
+                               v_WIN1_RB_SWAP(win->swap_rb);
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+
+                        /* rk312x unsupport win1 scale */
+                        if (lcdc_dev->soc_type == VOP_RK3036) 
+                               lcdc_writel(lcdc_dev, WIN1_SCL_FACTOR_YRGB,
+                                       v_X_SCL_FACTOR(win->scale_yrgb_x) |
+                                       v_Y_SCL_FACTOR(win->scale_yrgb_y));
+
+                       lcdc_msk_reg(lcdc_dev, WIN1_VIR, m_YRGB_VIR,
+                                    v_YRGB_VIR(win->area[0].y_vir_stride));
+                       lcdc_writel(lcdc_dev, WIN1_ACT_INFO,
+                                   v_ACT_WIDTH(win->area[0].xact) |
+                                   v_ACT_HEIGHT(win->area[0].yact));
+                       lcdc_writel(lcdc_dev, WIN1_DSP_INFO,
+                                   v_DSP_WIDTH(win->area[0].xsize) |
+                                   v_DSP_HEIGHT(win->area[0].ysize));
+                       lcdc_writel(lcdc_dev, WIN1_DSP_ST,
+                                   v_DSP_STX(win->area[0].dsp_stx) |
+                                   v_DSP_STY(win->area[0].dsp_sty));
+
+                       lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr);
+
+               } else if (win->id == 2) {
+               }
+       } else {
+               win->area[0].y_addr = 0;
+               win->area[0].uv_addr = 0;
+               if (win->id == 0)
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN0_EN,
+                                    v_WIN0_EN(0));
+               else if (win->id == 1)
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_WIN1_EN,
+                                    v_WIN1_EN(0));
+               else if (win->id == 2)
+                       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_HWC_EN, v_HWC_EN(0));
+       }
+}
+
+static void lcdc_layer_enable(struct lcdc_device *lcdc_dev, unsigned int win_id,
+                             bool open)
+{
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)
+           && lcdc_dev->driver.win[win_id]->state != open) {
+               if (open) {
+                       if (!lcdc_dev->atv_layer_cnt) {
+                               dev_info(lcdc_dev->dev,
+                                        "wakeup from standby!\n");
+                               lcdc_dev->standby = 0;
+                       }
+                       lcdc_dev->atv_layer_cnt++;
+               } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
+                       lcdc_dev->atv_layer_cnt--;
+               }
+               lcdc_dev->driver.win[win_id]->state = open;
+               if (!open) {
+                       lcdc_layer_update_regs(lcdc_dev,
+                                              lcdc_dev->driver.win[win_id]);
+                       lcdc_cfg_done(lcdc_dev);
+               }
+               /*if no layer used,disable lcdc */
+               if (!lcdc_dev->atv_layer_cnt) {
+                       dev_info(lcdc_dev->dev,
+                                "no layer is used,go to standby!\n");
+                       lcdc_dev->standby = 1;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk312x_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
+       struct rk_lcdc_win *win1 = lcdc_dev->driver.win[1];
+       int timeout;
+       unsigned long flags;
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(lcdc_dev->standby));
+               lcdc_layer_update_regs(lcdc_dev, win0);
+               lcdc_layer_update_regs(lcdc_dev, win1);
+               rk312x_lcdc_alpha_cfg(lcdc_dev);
+               lcdc_cfg_done(lcdc_dev);
+
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       //if (dev_drv->wait_fs) {
+       if (0) {
+               spin_lock_irqsave(&dev_drv->cpl_lock, flags);
+               init_completion(&dev_drv->frame_done);
+               spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
+               timeout = wait_for_completion_timeout(&dev_drv->frame_done,
+                                                     msecs_to_jiffies
+                                                     (dev_drv->cur_screen->ft +
+                                                      5));
+               if (!timeout && (!dev_drv->frame_done.done)) {
+                       dev_warn(lcdc_dev->dev,
+                                "wait for new frame start time out!\n");
+                       return -ETIMEDOUT;
+               }
+       }
+       DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
+       return 0;
+
+}
+
+static void rk312x_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
+{
+       memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0xdc);
+}
+
+static void rk312x_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
+{
+       u32 mask, val;
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               mask = m_MMU_EN | m_AXI_MAX_OUTSTANDING_EN |
+                       m_AXI_OUTSTANDING_MAX_NUM;
+               val = v_MMU_EN(1) | v_AXI_OUTSTANDING_MAX_NUM(31) |
+                       v_AXI_MAX_OUTSTANDING_EN(1);
+               lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+}
+
+static int rk312x_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
+{
+       int i = 0;
+       int __iomem *c;
+       int v;
+       struct lcdc_device *lcdc_dev =
+                container_of(dev_drv, struct lcdc_device, driver);
+
+        spin_lock(&lcdc_dev->reg_lock);
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
+       lcdc_cfg_done(lcdc_dev);
+       mdelay(25);
+       for (i = 0; i < 256; i++) {
+               v = dev_drv->cur_screen->dsp_lut[i];
+               c = lcdc_dev->dsp_lut_addr_base + i;
+               writel_relaxed(v, c);
+
+       }
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
+        lcdc_cfg_done(lcdc_dev);
+        spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+
+}
+
+static int rk312x_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
+{
+#ifdef CONFIG_RK_FPGA
+       return 0;
+#endif
+       int ret, fps;
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+
+       ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
+       if (ret)
+               dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
+       lcdc_dev->pixclock =
+           div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
+
+       fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
+       screen->ft = 1000 / fps;
+       dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
+                lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
+       return 0;
+
+}
+
+/********do basic init*********/
+static int rk312x_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       if (lcdc_dev->pre_init)
+               return 0;
+
+       lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
+       lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
+       lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
+//      lcdc_dev->pd   = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
+
+       if ( /*IS_ERR(lcdc_dev->pd) || */ (IS_ERR(lcdc_dev->aclk)) ||
+           (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
+               dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
+                       lcdc_dev->id);
+       }
+
+       rk_disp_pwr_enable(dev_drv);
+       rk312x_lcdc_clk_enable(lcdc_dev);
+
+       /* backup reg config at uboot */
+       rk_lcdc_read_reg_defalut_cfg(lcdc_dev);
+       lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_AUTO_GATING_EN, v_AUTO_GATING_EN(0));
+       lcdc_cfg_done(lcdc_dev);
+       if (dev_drv->iommu_enabled)     /* disable win0 to workaround iommu pagefault */
+               lcdc_layer_enable(lcdc_dev, 0, 0);
+       lcdc_dev->pre_init = true;
+
+       return 0;
+}
+
+static void rk312x_lcdc_deinit(struct lcdc_device *lcdc_dev)
+{
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+                mask = m_FS_INT_CLEAR | m_FS_INT_EN |
+                        m_LF_INT_CLEAR | m_LF_INT_EN |
+                        m_BUS_ERR_INT_CLEAR | m_BUS_ERR_INT_EN;
+               val = v_FS_INT_CLEAR(0) | v_FS_INT_EN(0) |
+                        v_LF_INT_CLEAR(0) | v_LF_INT_EN(0) |
+                        v_BUS_ERR_INT_CLEAR(0) | v_BUS_ERR_INT_EN(0);
+               lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
+               lcdc_set_bit(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY);
+               lcdc_cfg_done(lcdc_dev);
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+       mdelay(1);
+
+}
+
+static u32 calc_sclk(struct rk_screen *src_screen, struct rk_screen *dst_screen)
+{
+        u32 dsp_vtotal;
+        u64 dsp_htotal;
+        u32 dsp_in_vtotal;
+        u64 dsp_in_htotal;
+        u32 sclk;
+
+        if (!src_screen || !dst_screen)
+                return 0;
+
+        dsp_vtotal = dst_screen->mode.yres;
+        dsp_htotal = dst_screen->mode.left_margin + dst_screen->mode.hsync_len +
+                     dst_screen->mode.xres + dst_screen->mode.right_margin;
+        dsp_in_vtotal = src_screen->mode.yres;
+        dsp_in_htotal = src_screen->mode.left_margin +
+                        src_screen->mode.hsync_len +
+                        src_screen->mode.xres + src_screen->mode.right_margin;
+        sclk = dsp_vtotal * dsp_htotal * src_screen->mode.pixclock;
+        do_div(sclk, dsp_in_vtotal * dsp_in_htotal);
+
+        return sclk;
+}
+
+static int calc_dsp_frm_vst_hst(struct rk_screen *src, struct rk_screen *dst)
+{
+        u32 BP_in, BP_out;
+        u32 v_scale_ratio;
+#if defined(FLOAT_CALC) /* use float */
+        double T_frm_st;
+        double T_BP_in, T_BP_out, T_Delta, Tin;
+#else
+        long long  T_frm_st;
+        u64 T_BP_in, T_BP_out, T_Delta, Tin;
+        u64 rate = (1 << 16);
+        u64 temp;
+#endif
+        u32 dsp_htotal, src_htotal, src_vtotal;
+
+        if (unlikely(!src) || unlikely(!dst))
+                return -1;
+
+        dsp_htotal = dst->mode.left_margin + dst->mode.hsync_len +
+                     dst->mode.xres + dst->mode.right_margin;
+        src_htotal = src->mode.left_margin + src->mode.hsync_len +
+                     src->mode.xres + src->mode.right_margin;
+        src_vtotal = src->mode.upper_margin + src->mode.vsync_len +
+                     src->mode.yres + src->mode.lower_margin;
+        BP_in  = (src->mode.upper_margin + src->mode.vsync_len) * src_htotal;
+        BP_out = (dst->mode.upper_margin + dst->mode.vsync_len) * dsp_htotal;
+
+        v_scale_ratio = dst->mode.yres / src->mode.yres;
+
+#if defined(FLOAT_CALC)
+        T_BP_in = 1.0 * BP_in / src->mode.pixclock;
+        T_BP_out = 1.0 * BP_out / dst->mode.pixclock;
+        if (v_scale_ratio < 2)
+                T_Delta = 4.0 * src_htotal / src->mode.pixclock;
+        else
+                T_Delta = 12.0 * src_htotal / src->mode.pixclock;
+
+        Tin = 1.0 * src_vtotal * src_htotal / src->mode.pixclock;
+#else
+        T_BP_in = rate * BP_in;
+        do_div(T_BP_in, src->mode.pixclock);
+        T_BP_out = rate * BP_out;
+        do_div(T_BP_out, dst->mode.pixclock);
+        if (v_scale_ratio < 2)
+                T_Delta = rate * 4 * src_htotal;
+        else
+                T_Delta = rate * 12 * src_htotal;
+
+        do_div(T_Delta, src->mode.pixclock);
+        Tin = rate * src_vtotal * src_htotal;
+        do_div(Tin, src->mode.pixclock);
+#endif
+
+        T_frm_st = (T_BP_in + T_Delta - T_BP_out);
+        if (T_frm_st < 0)
+                T_frm_st  += Tin;
+
+#if defined(FLOAT_CALC)
+        dst->scl_vst = (u16)(T_frm_st * src->mode.pixclock / src_htotal);
+        dst->scl_hst = (u32)(T_frm_st * src->mode.pixclock) % src_htotal;
+#else
+        temp = T_frm_st * src->mode.pixclock;
+        dst->scl_hst = do_div(temp, src_htotal * rate);
+        dst->scl_vst = temp;
+#endif
+
+        return 0;
+}
+
+static int rk312x_lcdc_set_scaler(struct rk_lcdc_driver *dev_drv,
+                                  struct rk_screen *dst_screen, bool enable)
+{
+        u32 dsp_htotal, dsp_hs_end, dsp_hact_st, dsp_hact_end;
+       u32 dsp_vtotal, dsp_vs_end, dsp_vact_st, dsp_vact_end;
+        u32 dsp_hbor_end, dsp_hbor_st, dsp_vbor_end, dsp_vbor_st;
+       u32 scl_v_factor, scl_h_factor;
+       u32 dst_frame_hst, dst_frame_vst;
+       u32 src_w, src_h, dst_w, dst_h;
+       u16 bor_right = 0;
+       u16 bor_left = 0;
+       u16 bor_up = 0;
+       u16 bor_down = 0;
+       struct rk_screen *src;
+       struct rk_screen *dst;
+        struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+
+        if (unlikely(!lcdc_dev->clk_on))
+                return 0;
+
+       if(!enable) {
+                dev_info(lcdc_dev->dev, "%s: disable\n", __func__);
+               return 0;
+       }
+
+        /* rk312x used one lcdc to apply dual disp
+         * hdmi screen is used for scaler src
+         * prmry screen is used for scaler dst
+         */
+       dst = dst_screen;
+       if (!dst) {
+               dev_err(lcdc_dev->dev, "%s: dst screen is null!\n", __func__);
+               return -EINVAL;
+       }
+
+       src = dst_screen->ext_screen;
+
+       lcdc_dev->s_pixclock = calc_sclk(src, dst);
+       clk_set_rate(lcdc_dev->sclk, lcdc_dev->s_pixclock);
+
+        /* config scale timing */
+        calc_dsp_frm_vst_hst(src, dst);
+       dst_frame_vst = dst->scl_vst;
+       dst_frame_hst = dst->scl_hst;
+
+       dsp_htotal    = dst->mode.hsync_len + dst->mode.left_margin +
+                        dst->mode.xres + dst->mode.right_margin;
+       dsp_hs_end    = dst->mode.hsync_len;
+
+       dsp_vtotal    = dst->mode.vsync_len + dst->mode.upper_margin +
+                        dst->mode.yres + dst->mode.lower_margin;
+       dsp_vs_end    = dst->mode.vsync_len;
+
+       dsp_hbor_end  = dst->mode.hsync_len + dst->mode.left_margin +
+                        dst->mode.xres;
+       dsp_hbor_st   = dst->mode.hsync_len + dst->mode.left_margin;
+       dsp_vbor_end  = dst->mode.vsync_len + dst->mode.upper_margin +
+                        dst->mode.yres;
+       dsp_vbor_st   = dst->mode.vsync_len + dst->mode.upper_margin;
+
+       dsp_hact_st   = dsp_hbor_st  + bor_left;
+       dsp_hact_end  = dsp_hbor_end - bor_right;
+       dsp_vact_st   = dsp_vbor_st  + bor_up;
+       dsp_vact_end  = dsp_vbor_end - bor_down;
+
+       src_w = src->mode.xres;
+       src_h = src->mode.yres;
+       dst_w = dsp_hact_end - dsp_hact_st;
+       dst_h = dsp_vact_end - dsp_vact_st;
+
+        /* calc scale factor */
+        scl_h_factor = ((src_w - 1) << 12) / (dst_w - 1);
+        scl_v_factor = ((src_h - 1) << 12) / (dst_h - 1);
+
+        spin_lock(&lcdc_dev->reg_lock);
+       lcdc_writel(lcdc_dev, SCALER_FACTOR,
+                    v_SCALER_H_FACTOR(scl_h_factor) |
+                    v_SCALER_V_FACTOR(scl_v_factor));
+
+        lcdc_writel(lcdc_dev, SCALER_FRAME_ST,
+                    v_SCALER_FRAME_HST(dst_frame_hst) |
+                    v_SCALER_FRAME_VST(dst_frame_hst));
+       lcdc_writel(lcdc_dev, SCALER_DSP_HOR_TIMING,
+                    v_SCALER_HS_END(dsp_hs_end) |
+                    v_SCALER_HTOTAL(dsp_htotal));
+       lcdc_writel(lcdc_dev, SCALER_DSP_HACT_ST_END,
+                    v_SCALER_HAEP(dsp_hact_end) |
+                    v_SCALER_HASP(dsp_hact_st));
+       lcdc_writel(lcdc_dev, SCALER_DSP_VER_TIMING,
+                    v_SCALER_VS_END(dsp_vs_end) |
+                    v_SCALER_VTOTAL(dsp_vtotal));
+       lcdc_writel(lcdc_dev, SCALER_DSP_VACT_ST_END,
+                    v_SCALER_VAEP(dsp_vact_end) |
+                    v_SCALER_VASP(dsp_vact_st));
+       lcdc_writel(lcdc_dev, SCALER_DSP_HBOR_TIMING,
+                    v_SCALER_HBOR_END(dsp_hbor_end) |
+                    v_SCALER_HBOR_ST(dsp_hbor_st));
+       lcdc_writel(lcdc_dev, SCALER_DSP_VBOR_TIMING,
+                    v_SCALER_VBOR_END(dsp_vbor_end) |
+                    v_SCALER_VBOR_ST(dsp_vbor_st));
+       lcdc_msk_reg(lcdc_dev, SCALER_CTRL,
+                    m_SCALER_EN | m_SCALER_OUT_ZERO | m_SCALER_OUT_EN,
+                    v_SCALER_EN(1) | v_SCALER_OUT_ZERO(0) | v_SCALER_OUT_EN(1));
+        spin_unlock(&lcdc_dev->reg_lock);
+
+       return 0;
+}
+
+static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
+{
+       u16 face = 0;
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       u16 right_margin = screen->mode.right_margin;
+       u16 left_margin = screen->mode.left_margin;
+       u16 lower_margin = screen->mode.lower_margin;
+       u16 upper_margin = screen->mode.upper_margin;
+       u16 x_res = screen->mode.xres;
+       u16 y_res = screen->mode.yres;
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               switch (screen->type) {
+                case SCREEN_RGB:
+                        if (lcdc_dev->soc_type == VOP_RK312X) {
+                                mask = m_RGB_DCLK_EN | m_RGB_DCLK_INVERT;
+                               val = v_RGB_DCLK_EN(1) | v_RGB_DCLK_INVERT(0);
+                                lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                        }
+                        break;
+                case SCREEN_LVDS:
+                        if (lcdc_dev->soc_type == VOP_RK312X) {
+                                mask = m_LVDS_DCLK_EN | m_LVDS_DCLK_INVERT;
+                               val = v_LVDS_DCLK_EN(1) | v_LVDS_DCLK_INVERT(0);
+                                lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                        }
+                        break;
+                case SCREEN_MIPI:
+                        if (lcdc_dev->soc_type == VOP_RK312X) {
+                                mask = m_MIPI_DCLK_EN | m_MIPI_DCLK_INVERT;
+                               val = v_MIPI_DCLK_EN(1) | v_MIPI_DCLK_INVERT(0);
+                                lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                        }
+                        break;
+               case SCREEN_HDMI:
+                       mask = m_HDMI_DCLK_EN;
+                       val = v_HDMI_DCLK_EN(1);
+                       if (screen->pixelrepeat) {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(1);
+                       }
+                       lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                       break;
+               case SCREEN_TVOUT:
+                       mask = m_TVE_DAC_DCLK_EN;
+                       val = v_TVE_DAC_DCLK_EN(1);
+                       if (screen->pixelrepeat) {
+                               mask |= m_CORE_CLK_DIV_EN;
+                               val |= v_CORE_CLK_DIV_EN(1);
+                       }
+                       lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
+                       if (x_res == 720 && y_res == 576)
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_TVE_MODE,
+                                            v_TVE_MODE(TV_PAL));
+                       else if (x_res == 720 && y_res == 480)
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_TVE_MODE,
+                                            v_TVE_MODE(TV_NTSC));
+                       else {
+                               dev_err(lcdc_dev->dev,
+                                       "unsupported video timing!\n");
+                               return -1;
+                       }
+                       break;
+               default:
+                       dev_err(lcdc_dev->dev, "un supported interface!\n");
+                       break;
+               }
+
+                if (lcdc_dev->soc_type == VOP_RK312X) {
+                        switch (screen->face) {
+                       case OUT_P565:
+                               face = OUT_P565;
+                               mask = m_DITHER_DOWN_EN |
+                                        m_DITHER_DOWN_MODE |
+                                       m_DITHER_DOWN_SEL;
+                               val = v_DITHER_DOWN_EN(1) |
+                                        v_DITHER_DOWN_MODE(0) |
+                                       v_DITHER_DOWN_SEL(1);
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+                               break;
+                       case OUT_P666:
+                               face = OUT_P666;
+                               mask = m_DITHER_DOWN_EN |
+                                        m_DITHER_DOWN_MODE |
+                                       m_DITHER_DOWN_SEL;
+                               val = v_DITHER_DOWN_EN(1) |
+                                        v_DITHER_DOWN_MODE(1) |
+                                       v_DITHER_DOWN_SEL(1);
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+                               break;
+                       case OUT_D888_P565:
+                               face = OUT_P888;
+                               mask = m_DITHER_DOWN_EN |
+                                        m_DITHER_DOWN_MODE |
+                                       m_DITHER_DOWN_SEL;
+                               val = v_DITHER_DOWN_EN(1) |
+                                        v_DITHER_DOWN_MODE(0) |
+                                       v_DITHER_DOWN_SEL(1);
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+                               break;
+                       case OUT_D888_P666:
+                               face = OUT_P888;
+                               mask = m_DITHER_DOWN_EN |
+                                        m_DITHER_DOWN_MODE |
+                                       m_DITHER_DOWN_SEL;
+                               val = v_DITHER_DOWN_EN(1) |
+                                        v_DITHER_DOWN_MODE(1) |
+                                       v_DITHER_DOWN_SEL(1);
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+                               break;
+                       case OUT_P888:
+                               face = OUT_P888;
+                               mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
+                               val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
+                               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+                               break;
+                       default:
+                               dev_err(lcdc_dev->dev, "un supported interface!\n");
+                               break;
+                       }
+                }
+
+               mask = m_DSP_OUT_FORMAT | m_HSYNC_POL | m_VSYNC_POL |
+                   m_DEN_POL | m_DCLK_POL;
+               val = v_DSP_OUT_FORMAT(face) | v_HSYNC_POL(screen->pin_hsync) |
+                   v_VSYNC_POL(screen->pin_vsync) |
+                   v_DEN_POL(screen->pin_den) |
+                   v_DCLK_POL(screen->pin_dclk);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
+
+               mask = m_BG_COLOR | m_DSP_BG_SWAP | m_DSP_RB_SWAP |
+                   m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
+                   m_DSP_DUMMY_SWAP | m_BLANK_EN | m_BLACK_EN;
+
+               val = v_BG_COLOR(0x000000) | v_DSP_BG_SWAP(screen->swap_gb) |
+                   v_DSP_RB_SWAP(screen->swap_rb) |
+                   v_DSP_RG_SWAP(screen->swap_rg) |
+                   v_DSP_DELTA_SWAP(screen->swap_delta) |
+                   v_DSP_DUMMY_SWAP(screen->swap_dumy) |
+                   v_BLANK_EN(0) | v_BLACK_EN(0);
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
+
+                /* config timing */
+               val = v_HSYNC(screen->mode.hsync_len) |
+                   v_HORPRD(screen->mode.hsync_len + left_margin + x_res +
+                            right_margin);
+               lcdc_writel(lcdc_dev, DSP_HTOTAL_HS_END, val);
+               val = v_HAEP(screen->mode.hsync_len + left_margin + x_res) |
+                   v_HASP(screen->mode.hsync_len + left_margin);
+               lcdc_writel(lcdc_dev, DSP_HACT_ST_END, val);
+
+               if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+                       /* First Field Timing */
+                       lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END,
+                                   v_VSYNC(screen->mode.vsync_len) |
+                                   v_VERPRD(2 * (screen->mode.vsync_len + upper_margin + lower_margin) +
+                                            y_res + 1));
+                       lcdc_writel(lcdc_dev, DSP_VACT_ST_END,
+                                   v_VAEP(screen->mode.vsync_len +
+                                          upper_margin + y_res / 2) |
+                                   v_VASP(screen->mode.vsync_len +
+                                          upper_margin));
+                       /* Second Field Timing */
+                       lcdc_writel(lcdc_dev, DSP_VS_ST_END_F1,
+                                   v_VSYNC_ST_F1(screen->mode.vsync_len +
+                                                 upper_margin + y_res / 2 +
+                                                 lower_margin) |
+                                   v_VSYNC_END_F1(2 * screen->mode.vsync_len +
+                                                  upper_margin + y_res / 2 +
+                                                  lower_margin));
+                       lcdc_writel(lcdc_dev, DSP_VACT_ST_END_F1,
+                                   v_VAEP(2 * (screen->mode.vsync_len + upper_margin) +
+                                          y_res + lower_margin + 1) |
+                                   v_VASP(2 * (screen->mode.vsync_len + upper_margin) +
+                                          y_res / 2 + lower_margin + 1));
+
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
+                                    m_INTERLACE_DSP_EN |
+                                    m_WIN0_YRGB_DEFLICK_EN |
+                                    m_WIN0_CBR_DEFLICK_EN |
+                                    m_INTERLACE_FIELD_POL,
+                                    v_INTERLACE_DSP_EN(1) |
+                                    v_WIN0_YRGB_DEFLICK_EN(1) |
+                                    v_WIN0_CBR_DEFLICK_EN(1) |
+                                    v_INTERLACE_FIELD_POL(0));
+               } else {
+                       val = v_VSYNC(screen->mode.vsync_len) |
+                           v_VERPRD(screen->mode.vsync_len + upper_margin +
+                                    y_res + lower_margin);
+                       lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, val);
+
+                       val = v_VAEP(screen->mode.vsync_len + upper_margin + y_res) |
+                            v_VASP(screen->mode.vsync_len + upper_margin);
+                       lcdc_writel(lcdc_dev, DSP_VACT_ST_END, val);
+
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
+                                    m_INTERLACE_DSP_EN |
+                                    m_WIN0_YRGB_DEFLICK_EN |
+                                    m_WIN0_CBR_DEFLICK_EN |
+                                    m_INTERLACE_FIELD_POL,
+                                    v_INTERLACE_DSP_EN(0) |
+                                    v_WIN0_YRGB_DEFLICK_EN(0) |
+                                    v_WIN0_CBR_DEFLICK_EN(0) |
+                                    v_INTERLACE_FIELD_POL(0));
+               }
+
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+        
+        rk312x_lcdc_set_dclk(dev_drv);
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+               dev_drv->trsm_ops->enable();
+       if (screen->init)
+               screen->init();
+
+       return 0;
+}
+
+static int rk312x_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
+                           bool open)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+
+       /* enable clk,when first layer open */
+       if ((open) && (!lcdc_dev->atv_layer_cnt)) {
+                rockchip_set_system_status(SYS_STATUS_LCDC0);
+               rk312x_lcdc_pre_init(dev_drv);
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+               if (dev_drv->iommu_enabled) {
+                       if (!dev_drv->mmu_dev) {
+                               dev_drv->mmu_dev =
+                                   rockchip_get_sysmmu_device_by_compatible
+                                   (dev_drv->mmu_dts_name);
+                               if (dev_drv->mmu_dev)
+                                       platform_set_sysmmu(dev_drv->mmu_dev,
+                                                           dev_drv->dev);
+                               else {
+                                       dev_err(dev_drv->dev,
+                                               "failed to get rockchip iommu device\n");
+                                       return -1;
+                               }
+                       }
+                       iovmm_activate(dev_drv->dev);
+               }
+#endif
+               rk312x_lcdc_reg_restore(lcdc_dev);
+               if (dev_drv->iommu_enabled)
+                       rk312x_lcdc_mmu_en(dev_drv);
+               if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
+                       rk312x_lcdc_set_dclk(dev_drv);
+                       rk312x_lcdc_enable_irq(dev_drv);
+               } else {
+                       rk312x_load_screen(dev_drv, 1);
+               }
+
+                /* set screen lut */
+               if (dev_drv->cur_screen->dsp_lut)
+                       rk312x_lcdc_set_lut(dev_drv);
+       }
+
+       if (win_id < ARRAY_SIZE(lcdc_win))
+               lcdc_layer_enable(lcdc_dev, win_id, open);
+       else
+               dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
+
+       /* when all layer closed,disable clk */
+       if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
+               rk312x_lcdc_disable_irq(lcdc_dev);
+               rk312x_lcdc_reg_update(dev_drv);
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               iovmm_deactivate(dev_drv->dev);
+               }
+#endif
+               rk312x_lcdc_clk_disable(lcdc_dev);
+                rockchip_clear_system_status(SYS_STATUS_LCDC0);
+       }
+
+       return 0;
+}
+
+static int rk312x_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       struct rk_lcdc_win *win = NULL;
+       char fmt[9] = "NULL";
+
+       if (!screen) {
+               dev_err(dev_drv->dev, "screen is null!\n");
+               return -ENOENT;
+       }
+
+       if (win_id == 0) {
+               win = dev_drv->win[0];
+       } else if (win_id == 1) {
+               win = dev_drv->win[1];
+       } else {
+               dev_err(dev_drv->dev, "un supported win number:%d\n", win_id);
+               return -EINVAL;
+       }
+
+       spin_lock(&lcdc_dev->reg_lock);
+       win->area[0].dsp_stx = win->area[0].xpos + screen->mode.left_margin +
+                                screen->mode.hsync_len;
+       if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+               win->area[0].ysize /= 2;
+               win->area[0].dsp_sty = win->area[0].ypos / 2 +
+                                        screen->mode.upper_margin +
+                                        screen->mode.vsync_len;
+       } else {
+               win->area[0].dsp_sty = win->area[0].ypos +
+                                        screen->mode.upper_margin +
+                                       screen->mode.vsync_len;
+       }
+       win->scale_yrgb_x = CalScale(win->area[0].xact, win->area[0].xsize);
+       win->scale_yrgb_y = CalScale(win->area[0].yact, win->area[0].ysize);
+       switch (win->format) {
+       case ARGB888:
+               win->fmt_cfg = VOP_FORMAT_ARGB888;
+               win->swap_rb = 0;
+               break;
+       case XBGR888:
+               win->fmt_cfg = VOP_FORMAT_ARGB888;
+               win->swap_rb = 1;
+               break;
+       case ABGR888:
+               win->fmt_cfg = VOP_FORMAT_ARGB888;
+               win->swap_rb = 1;
+               break;
+       case RGB888:
+               win->fmt_cfg = VOP_FORMAT_RGB888;
+               win->swap_rb = 0;
+               break;
+       case RGB565:
+               win->fmt_cfg = VOP_FORMAT_RGB565;
+               win->swap_rb = 0;
+               break;
+       case YUV444:
+               if (win_id == 0) {
+                       win->fmt_cfg = VOP_FORMAT_YCBCR444;
+                       win->scale_cbcr_x =
+                           CalScale(win->area[0].xact, win->area[0].xsize);
+                       win->scale_cbcr_y =
+                           CalScale(win->area[0].yact, win->area[0].ysize);
+                       win->swap_rb = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n", __func__);
+               }
+               break;
+       case YUV422:
+               if (win_id == 0) {
+                       win->fmt_cfg = VOP_FORMAT_YCBCR422;
+                       win->scale_cbcr_x = CalScale((win->area[0].xact / 2),
+                                                     win->area[0].xsize);
+                       win->scale_cbcr_y =
+                           CalScale(win->area[0].yact, win->area[0].ysize);
+                       win->swap_rb = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n", __func__);
+               }
+               break;
+       case YUV420:
+               if (win_id == 0) {
+                       win->fmt_cfg = VOP_FORMAT_YCBCR420;
+                       win->scale_cbcr_x =
+                           CalScale(win->area[0].xact / 2, win->area[0].xsize);
+                       win->scale_cbcr_y =
+                           CalScale(win->area[0].yact / 2, win->area[0].ysize);
+                       win->swap_rb = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n", __func__);
+               }
+               break;
+       default:
+               dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
+                       __func__);
+               break;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       DBG(1,
+           "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
+           ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id, __func__,
+           get_format_string(win->format, fmt), win->area[0].xact,
+           win->area[0].yact, win->area[0].xsize, win->area[0].ysize,
+           win->area[0].xvir, win->area[0].yvir, win->area[0].xpos,
+           win->area[0].ypos);
+       return 0;
+}
+
+static int rk312x_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       struct rk_lcdc_win *win = NULL;
+       struct rk_screen *screen = dev_drv->cur_screen;
+
+       if (!screen) {
+               dev_err(dev_drv->dev, "screen is null!\n");
+               return -ENOENT;
+       }
+
+       if (win_id == 0) {
+               win = dev_drv->win[0];
+       } else if (win_id == 1) {
+               win = dev_drv->win[1];
+       } else {
+               dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
+               return -EINVAL;
+       }
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               win->area[0].y_addr =
+                   win->area[0].smem_start + win->area[0].y_offset;
+               win->area[0].uv_addr =
+                   win->area[0].cbr_start + win->area[0].c_offset;
+               if (win->area[0].y_addr)
+                       lcdc_layer_update_regs(lcdc_dev, win);
+               /* lcdc_cfg_done(lcdc_dev); */
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
+           lcdc_dev->id, __func__, win->area[0].y_addr, win->area[0].uv_addr,
+           win->area[0].y_offset);
+       /* this is the first frame of the system,enable frame start interrupt */
+       if ((dev_drv->first_frame)) {
+               dev_drv->first_frame = 0;
+               rk312x_lcdc_enable_irq(dev_drv);
+
+       }
+
+       return 0;
+}
+
+static int rk312x_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
+                            unsigned long arg, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       u32 panel_size[2];
+       void __user *argp = (void __user *)arg;
+       struct color_key_cfg clr_key_cfg;
+
+       switch (cmd) {
+       case RK_FBIOGET_PANEL_SIZE:
+               panel_size[0] = lcdc_dev->screen->mode.xres;
+               panel_size[1] = lcdc_dev->screen->mode.yres;
+               if (copy_to_user(argp, panel_size, 8))
+                       return -EFAULT;
+               break;
+       case RK_FBIOPUT_COLOR_KEY_CFG:
+               if (copy_from_user(&clr_key_cfg, argp,
+                                  sizeof(struct color_key_cfg)))
+                       return -EFAULT;
+               lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
+                           clr_key_cfg.win0_color_key_cfg);
+               lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
+                           clr_key_cfg.win1_color_key_cfg);
+               break;
+
+       default:
+               break;
+       }
+       return 0;
+}
+
+static int rk312x_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
+                                 const char *id)
+{
+       int win_id = 0;
+       mutex_lock(&dev_drv->fb_win_id_mutex);
+       if (!strcmp(id, "fb0"))
+               win_id = dev_drv->fb0_win_id;
+       else if (!strcmp(id, "fb1"))
+               win_id = dev_drv->fb1_win_id;
+       else if (!strcmp(id, "fb2"))
+               win_id = dev_drv->fb2_win_id;
+       mutex_unlock(&dev_drv->fb_win_id_mutex);
+
+       return win_id;
+}
+
+static int rk312x_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       return 0;
+}
+
+static int rk312x_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
+                              bool set)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       int ovl;
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               if (set) {
+                       lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN0_TOP,
+                                    v_WIN0_TOP(swap));
+                       ovl = swap;
+               } else {
+                       ovl = lcdc_read_bit(lcdc_dev, DSP_CTRL0, m_WIN0_TOP);
+               }
+       } else {
+               ovl = -EPERM;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return ovl;
+}
+
+static int rk312x_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
+{
+
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       if (dev_drv->suspend_flag)
+               return 0;
+       dev_drv->suspend_flag = 1;
+       flush_kthread_worker(&dev_drv->update_regs_worker);
+
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
+               dev_drv->trsm_ops->disable();
+       spin_lock(&lcdc_dev->reg_lock);
+       if (likely(lcdc_dev->clk_on)) {
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN, v_BLANK_EN(1));
+               lcdc_msk_reg(lcdc_dev, INT_STATUS,
+                             m_FS_INT_CLEAR | m_LF_INT_CLEAR,
+                            v_FS_INT_CLEAR(1) | v_LF_INT_CLEAR(1));
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
+                            v_DSP_OUT_ZERO(1));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(1));
+               lcdc_cfg_done(lcdc_dev);
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+               if (dev_drv->iommu_enabled) {
+                       if (dev_drv->mmu_dev)
+                               iovmm_deactivate(dev_drv->dev);
+               }
+#endif
+               spin_unlock(&lcdc_dev->reg_lock);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+               return 0;
+       }
+       rk312x_lcdc_clk_disable(lcdc_dev);
+       rk_disp_pwr_disable(dev_drv);
+       return 0;
+}
+
+static int rk312x_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       if (!dev_drv->suspend_flag)
+               return 0;
+       rk_disp_pwr_enable(dev_drv);
+       dev_drv->suspend_flag = 0;
+
+       if (lcdc_dev->atv_layer_cnt) {
+               rk312x_lcdc_clk_enable(lcdc_dev);
+               rk312x_lcdc_reg_restore(lcdc_dev);
+                /* set screen lut */
+               if (dev_drv->cur_screen->dsp_lut)
+                       rk312x_lcdc_set_lut(dev_drv);
+
+               spin_lock(&lcdc_dev->reg_lock);
+
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
+                            v_DSP_OUT_ZERO(0));
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
+                            v_LCDC_STANDBY(0));
+               lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN, v_BLANK_EN(0));
+               lcdc_cfg_done(lcdc_dev);
+
+               spin_unlock(&lcdc_dev->reg_lock);
+       }
+
+       if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+               dev_drv->trsm_ops->enable();
+       return 0;
+}
+
+static int rk312x_lcdc_blank(struct rk_lcdc_driver *dev_drv,
+                            int win_id, int blank_mode)
+{
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               rk312x_lcdc_early_resume(dev_drv);
+               break;
+       case FB_BLANK_NORMAL:
+               rk312x_lcdc_early_suspend(dev_drv);
+               break;
+       default:
+               rk312x_lcdc_early_suspend(dev_drv);
+               break;
+       }
+
+       dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
+
+       return 0;
+}
+
+static int rk312x_lcdc_cfg_done(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on)
+               lcdc_cfg_done(lcdc_dev);
+       spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+}
+
+/*
+       a:[-30~0]:
+           sin_hue = sin(a)*256 +0x100;
+           cos_hue = cos(a)*256;
+       a:[0~30]
+           sin_hue = sin(a)*256;
+           cos_hue = cos(a)*256;
+*/
+static int rk312x_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,
+                                   bcsh_hue_mode mode)
+{
+
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               val = lcdc_readl(lcdc_dev, BCSH_H);
+               switch (mode) {
+               case H_SIN:
+                       val &= m_BCSH_SIN_HUE;
+                       break;
+               case H_COS:
+                       val &= m_BCSH_COS_HUE;
+                       val >>= 16;
+                       break;
+               default:
+                       break;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return val;
+}
+
+static int rk312x_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv, int sin_hue,
+                                   int cos_hue)
+{
+
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
+               val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
+               lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+
+       return 0;
+}
+
+static int rk312x_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
+                                   bcsh_bcs_mode mode, int value)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               switch (mode) {
+               case BRIGHTNESS:
+                       /* from 0 to 255,typical is 128 */
+                       if (value < 0x80)
+                               value += 0x80;
+                       else if (value >= 0x80)
+                               value = value - 0x80;
+                       mask = m_BCSH_BRIGHTNESS;
+                       val = v_BCSH_BRIGHTNESS(value);
+                       break;
+               case CONTRAST:
+                       /* from 0 to 510,typical is 256 */
+                       mask = m_BCSH_CONTRAST;
+                       val = v_BCSH_CONTRAST(value);
+                       break;
+               case SAT_CON:
+                       /* from 0 to 1015,typical is 256 */
+                       mask = m_BCSH_SAT_CON;
+                       val = v_BCSH_SAT_CON(value);
+                       break;
+               default:
+                       break;
+               }
+               lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return val;
+}
+
+static int rk312x_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
+                                   bcsh_bcs_mode mode)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               val = lcdc_readl(lcdc_dev, BCSH_BCS);
+               switch (mode) {
+               case BRIGHTNESS:
+                       val &= m_BCSH_BRIGHTNESS;
+                       if (val > 0x80)
+                               val -= 0x80;
+                       else
+                               val += 0x80;
+                       break;
+               case CONTRAST:
+                       val &= m_BCSH_CONTRAST;
+                       val >>= 8;
+                       break;
+               case SAT_CON:
+                       val &= m_BCSH_SAT_CON;
+                       val >>= 20;
+                       break;
+               default:
+                       break;
+               }
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return val;
+}
+
+static int rk312x_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 mask, val;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+               if (open) {
+                       lcdc_writel(lcdc_dev, BCSH_CTRL, 0x1);
+                       lcdc_writel(lcdc_dev, BCSH_BCS, 0xd0010000);
+                       lcdc_writel(lcdc_dev, BCSH_H, 0x01000000);
+               } else {
+                       mask = m_BCSH_EN;
+                       val = v_BCSH_EN(0);
+                       lcdc_msk_reg(lcdc_dev, BCSH_CTRL, mask, val);
+               }
+               lcdc_cfg_done(lcdc_dev);
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return 0;
+}
+
+static int rk312x_fb_win_remap(struct rk_lcdc_driver *dev_drv,
+                              enum fb_win_map_order order)
+{
+       mutex_lock(&dev_drv->fb_win_id_mutex);
+       if (order == FB_DEFAULT_ORDER)
+               order = FB0_WIN0_FB1_WIN1_FB2_WIN2;     /* FB0_WIN1_FB1_WIN0_FB2_WIN2; for box */
+       dev_drv->fb2_win_id = order / 100;
+       dev_drv->fb1_win_id = (order / 10) % 10;
+       dev_drv->fb0_win_id = order % 10;
+       mutex_unlock(&dev_drv->fb_win_id_mutex);
+
+       return 0;
+}
+
+static int rk312x_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
+                              bool set)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       struct rk_screen *screen = dev_drv->cur_screen;
+       u64 ft = 0;
+       u32 dotclk;
+       int ret;
+       u32 pixclock;
+       u32 x_total, y_total;
+       if (set) {
+               ft = div_u64(1000000000000llu, fps);
+               x_total =
+                   screen->mode.upper_margin + screen->mode.lower_margin +
+                   screen->mode.yres + screen->mode.vsync_len;
+               y_total =
+                   screen->mode.left_margin + screen->mode.right_margin +
+                   screen->mode.xres + screen->mode.hsync_len;
+               dev_drv->pixclock = div_u64(ft, x_total * y_total);
+               dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
+               ret = clk_set_rate(lcdc_dev->dclk, dotclk);
+       }
+
+       pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
+       dev_drv->pixclock = lcdc_dev->pixclock = pixclock;
+       fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
+       screen->ft = 1000 / fps;        /*one frame time in ms */
+
+       if (set)
+               dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
+                        clk_get_rate(lcdc_dev->dclk), fps);
+
+       return fps;
+}
+
+static int rk312x_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+       u32 int_reg;
+       int ret;
+
+       if (lcdc_dev->clk_on && (!dev_drv->suspend_flag)) {
+               int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
+               if (int_reg & m_LF_INT_STA) {
+                        dev_drv->frame_time.last_framedone_t =
+                                       dev_drv->frame_time.framedone_t;
+                       dev_drv->frame_time.framedone_t = cpu_clock(0);
+                       lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
+                                    v_LF_INT_CLEAR(1));
+                       ret = RK_LF_STATUS_FC;
+               } else
+                       ret = RK_LF_STATUS_FR;
+       } else {
+               ret = RK_LF_STATUS_NC;
+       }
+
+       return ret;
+}
+
+static int rk312x_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
+                                   unsigned int *dsp_addr)
+{
+       struct lcdc_device *lcdc_dev =
+           container_of(dev_drv, struct lcdc_device, driver);
+
+       if (lcdc_dev->clk_on) {
+               dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+                if (lcdc_dev->soc_type == VOP_RK3036)
+                       dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
+                else if (lcdc_dev->soc_type == VOP_RK312X)
+                        dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST_RK312X);
+       }
+       return 0;
+}
+
+static ssize_t rk312x_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
+                                        char *buf, int win_id)
+{
+        struct lcdc_device *lcdc_dev = container_of(dev_drv, struct lcdc_device,
+                                                    driver);
+       char format_w0[9] = "NULL";
+       char format_w1[9] = "NULL";
+       char status_w0[9] = "NULL";
+       char status_w1[9] = "NULL";
+       u32 fmt_id, act_info, dsp_info, dsp_st, factor;
+       u16 xvir_w0, x_act_w0, y_act_w0, x_dsp_w0, y_dsp_w0, x_st_w0, y_st_w0;
+       u16 xvir_w1, x_act_w1, y_act_w1, x_dsp_w1, y_dsp_w1, x_st_w1, y_st_w1;
+       u16 x_factor, y_factor, x_scale, y_scale;
+        u16 ovl;
+        u32 win1_dsp_yaddr = 0;
+
+       spin_lock(&lcdc_dev->reg_lock);
+       if (lcdc_dev->clk_on) {
+                /* data format */
+               fmt_id = lcdc_readl(lcdc_dev, SYS_CTRL);
+                get_format_string((fmt_id & m_WIN0_FORMAT) >> 3, format_w0);
+                get_format_string((fmt_id & m_WIN1_FORMAT) >> 6, format_w1);
+
+                /* win status */
+               if (fmt_id & m_WIN0_EN)
+                       strcpy(status_w0, "enabled");
+               else
+                       strcpy(status_w0, "disabled");
+
+               if ((fmt_id & m_WIN1_EN) >> 1)
+                       strcpy(status_w1, "enabled");
+               else
+                       strcpy(status_w1, "disabled");
+
+                /* ovl */
+                ovl = lcdc_read_bit(lcdc_dev, DSP_CTRL0, m_WIN0_TOP);
+
+                /* xvir */
+               xvir_w0 = lcdc_readl(lcdc_dev, WIN0_VIR) & m_YRGB_VIR;
+                xvir_w1 = lcdc_readl(lcdc_dev, WIN1_VIR) & m_YRGB_VIR;
+
+                /* xact/yact */
+               act_info = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
+                x_act_w0 = (act_info & m_ACT_WIDTH) + 1;
+               y_act_w0 = ((act_info & m_ACT_HEIGHT) >> 16) + 1;
+
+                act_info = lcdc_readl(lcdc_dev, WIN1_ACT_INFO);
+                x_act_w1 = (act_info & m_ACT_WIDTH) + 1;
+               y_act_w1 = ((act_info & m_ACT_HEIGHT) >> 16) + 1;
+
+                /* xsize/ysize */
+               dsp_info = lcdc_readl(lcdc_dev, WIN0_DSP_INFO);
+                x_dsp_w0 = (dsp_info & m_DSP_WIDTH) + 1;
+               y_dsp_w0 = ((dsp_info & m_DSP_HEIGHT) >> 16) + 1;
+
+                dsp_info = lcdc_readl(lcdc_dev, WIN1_DSP_INFO);
+                x_dsp_w1 = (dsp_info & m_DSP_WIDTH) + 1;
+                y_dsp_w1 = ((dsp_info & m_DSP_HEIGHT) >> 16) + 1;
+
+                /* xpos/ypos */
+               dsp_st = lcdc_readl(lcdc_dev, WIN0_DSP_ST);
+                x_st_w0 = dsp_st & m_DSP_STX;
+               y_st_w0 = (dsp_st & m_DSP_STY) >> 16;
+
+                if (lcdc_dev->soc_type == VOP_RK3036)
+                        dsp_st = lcdc_readl(lcdc_dev, WIN1_DSP_ST);
+                else if (lcdc_dev->soc_type == VOP_RK312X)
+                        dsp_st = lcdc_readl(lcdc_dev, WIN1_DSP_ST_RK312X);
+                
+               x_st_w1 = dsp_st & m_DSP_STX;
+               y_st_w1 = (dsp_st & m_DSP_STY) >> 16;
+
+                /* scale factor */
+               factor = lcdc_readl(lcdc_dev, WIN0_SCL_FACTOR_YRGB);
+               x_factor = factor & m_X_SCL_FACTOR;
+               y_factor = (factor & m_Y_SCL_FACTOR) >> 16;
+               x_scale = 4096 * 100 / x_factor;
+               y_scale = 4096 * 100 / y_factor;
+
+                /* dsp addr */
+                if (lcdc_dev->soc_type == VOP_RK3036)
+                        win1_dsp_yaddr = lcdc_readl(lcdc_dev, WIN1_MST);
+                else if (lcdc_dev->soc_type == VOP_RK312X)
+                        win1_dsp_yaddr = lcdc_readl(lcdc_dev, WIN1_MST_RK312X);
+       } else {
+               spin_unlock(&lcdc_dev->reg_lock);
+               return -EPERM;
+       }
+       spin_unlock(&lcdc_dev->reg_lock);
+       return snprintf(buf, PAGE_SIZE,
+                       "win0:%s\n"
+                       "xvir:%d\n"
+                       "xact:%d\n"
+                       "yact:%d\n"
+                       "xdsp:%d\n"
+                       "ydsp:%d\n"
+                       "x_st:%d\n"
+                       "y_st:%d\n"
+                       "x_scale:%d.%d\n"
+                       "y_scale:%d.%d\n"
+                       "format:%s\n"
+                       "YRGB buffer addr:0x%08x\n"
+                       "CBR buffer addr:0x%08x\n\n"
+                       "win1:%s\n"
+                       "xvir:%d\n"
+                       "xact:%d\n"
+                       "yact:%d\n"
+                       "xdsp:%d\n"
+                       "ydsp:%d\n"
+                       "x_st:%d\n"
+                       "y_st:%d\n"
+                       "format:%s\n"
+                       "YRGB buffer addr:0x%08x\n"
+                       "overlay:%s\n",
+                       status_w0,
+                       xvir_w0,
+                       x_act_w0,
+                       y_act_w0,
+                       x_dsp_w0,
+                       y_dsp_w0,
+                       x_st_w0,
+                       y_st_w0,
+                       x_scale / 100,
+                       x_scale % 100,
+                       y_scale / 100,
+                       y_scale % 100,
+                       format_w0,
+                       lcdc_readl(lcdc_dev, WIN0_YRGB_MST),
+                       lcdc_readl(lcdc_dev, WIN0_CBR_MST),
+                       status_w1,
+                       xvir_w1,
+                       x_act_w1,
+                       y_act_w1,
+                       x_dsp_w1,
+                       y_dsp_w1,
+                       x_st_w1,
+                       y_st_w1,
+                       format_w1,
+                       win1_dsp_yaddr,
+                       ovl ? "win0 on the top of win1\n" :
+                       "win1 on the top of win0\n");
+}
+
+static int rk312x_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device,
+                                                   driver);
+       int *cbase = (int *)lcdc_dev->regs;
+       int *regsbak = (int *)lcdc_dev->regsbak;
+       int i, j;
+
+       printk("back up reg:\n");
+       for (i = 0; i <= (0xDC >> 4); i++) {
+               for (j = 0; j < 4; j++)
+                       printk("%08x  ", *(regsbak + i * 4 + j));
+               printk("\n");
+       }
+
+       printk("lcdc reg:\n");
+       for (i = 0; i <= (0xDC >> 4); i++) {
+               for (j = 0; j < 4; j++)
+                       printk("%08x  ", readl_relaxed(cbase + i * 4 + j));
+               printk("\n");
+       }
+       return 0;
+}
+
+static int rk312x_lcdc_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                    struct lcdc_device, driver);
+        if (lcdc_dev->soc_type == VOP_RK312X) { 
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN,
+                            v_DIRECT_PATH_EN(open));
+               lcdc_cfg_done(lcdc_dev);
+        }
+       return 0;
+}
+
+static int rk312x_lcdc_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                   struct lcdc_device, driver);
+
+        if (lcdc_dev->soc_type == VOP_RK312X) {
+               lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_LAYER,
+                            v_DIRECT_PATH_LAYER(win_id));
+               lcdc_cfg_done(lcdc_dev);
+        }
+       return 0;
+
+}
+
+static int rk312x_lcdc_dpi_status(struct rk_lcdc_driver *dev_drv)
+{
+       struct lcdc_device *lcdc_dev = container_of(dev_drv,
+                                                    struct lcdc_device, driver);
+       int ovl = 0;
+        
+        if (lcdc_dev->soc_type == VOP_RK312X)
+                ovl = lcdc_read_bit(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN);
+
+       return ovl;
+}
+
+static struct rk_lcdc_drv_ops lcdc_drv_ops = {
+       .open = rk312x_lcdc_open,
+       .load_screen = rk312x_load_screen,
+       .set_par = rk312x_lcdc_set_par,
+       .pan_display = rk312x_lcdc_pan_display,
+       .blank = rk312x_lcdc_blank,
+       .ioctl = rk312x_lcdc_ioctl,
+       .get_win_state = rk312x_lcdc_get_win_state,
+       .ovl_mgr = rk312x_lcdc_ovl_mgr,
+       .get_disp_info = rk312x_lcdc_get_disp_info,
+       .fps_mgr = rk312x_lcdc_fps_mgr,
+       .fb_get_win_id = rk312x_lcdc_get_win_id,
+       .fb_win_remap = rk312x_fb_win_remap,
+       .poll_vblank = rk312x_lcdc_poll_vblank,
+       .get_dsp_addr = rk312x_lcdc_get_dsp_addr,
+       .cfg_done = rk312x_lcdc_cfg_done,
+       .dump_reg = rk312x_lcdc_reg_dump,
+       .dpi_open = rk312x_lcdc_dpi_open,
+       .dpi_win_sel = rk312x_lcdc_dpi_win_sel,
+       .dpi_status = rk312x_lcdc_dpi_status,
+       .set_dsp_bcsh_hue = rk312x_lcdc_set_bcsh_hue,
+       .set_dsp_bcsh_bcs = rk312x_lcdc_set_bcsh_bcs,
+       .get_dsp_bcsh_hue = rk312x_lcdc_get_bcsh_hue,
+       .get_dsp_bcsh_bcs = rk312x_lcdc_get_bcsh_bcs,
+       .open_bcsh = rk312x_lcdc_open_bcsh,
+       .set_screen_scaler = rk312x_lcdc_set_scaler,
+};
+#if 0
+static const struct rk_lcdc_drvdata rk3036_lcdc_drvdata = {
+        .soc_type = VOP_RK3036,
+};
+#endif
+static const struct rk_lcdc_drvdata rk312x_lcdc_drvdata = {
+        .soc_type = VOP_RK312X,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk312x_lcdc_dt_ids[] = {
+#if 0
+       {
+                .compatible = "rockchip,rk3036-lcdc",
+                .data = (void *)&rk3036_lcdc_drvdata,
+        },
+#endif
+       {
+               .compatible = "rockchip,rk312x-lcdc",
+                .data = (void *)&rk312x_lcdc_drvdata,
+        },
+};
+#endif
+
+static int rk312x_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
+{
+        struct device_node *np = lcdc_dev->dev->of_node;
+        const struct of_device_id *match;
+        const struct rk_lcdc_drvdata *lcdc_drvdata;
+#if defined(CONFIG_ROCKCHIP_IOMMU)
+       int val;
+       if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
+               lcdc_dev->driver.iommu_enabled = 0;
+       else
+               lcdc_dev->driver.iommu_enabled = val;
+#else
+       lcdc_dev->driver.iommu_enabled = 0;
+#endif
+        match = of_match_node(rk312x_lcdc_dt_ids, np);
+        if (match) {
+                lcdc_drvdata = (const struct rk_lcdc_drvdata *)match->data;
+                lcdc_dev->soc_type = lcdc_drvdata->soc_type;
+        } else {
+                return PTR_ERR(match);
+        }
+
+       return 0;
+}
+
+static int rk312x_lcdc_probe(struct platform_device *pdev)
+{
+       struct lcdc_device *lcdc_dev = NULL;
+       struct rk_lcdc_driver *dev_drv;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int ret;
+
+       lcdc_dev = devm_kzalloc(dev, sizeof(struct lcdc_device), GFP_KERNEL);
+       if (!lcdc_dev) {
+               dev_err(&pdev->dev, "rk312x lcdc device kzalloc fail!\n");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, lcdc_dev);
+       lcdc_dev->dev = dev;
+       if (rk312x_lcdc_parse_dt(lcdc_dev)) {
+                dev_err(lcdc_dev->dev, "rk312x lcdc parse dt failed!\n");
+                goto err_parse_dt;
+        }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       lcdc_dev->reg_phy_base = res->start;
+       lcdc_dev->len = resource_size(res);
+       lcdc_dev->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(lcdc_dev->regs)) {
+               ret = PTR_ERR(lcdc_dev->regs);
+                goto err_remap_reg;
+        }
+
+       lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
+       if (IS_ERR(lcdc_dev->regsbak)) {
+                dev_err(&pdev->dev, "rk312x lcdc device kmalloc fail!\n");
+               ret = PTR_ERR(lcdc_dev->regsbak);
+                goto err_remap_reg;
+        }
+
+       dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
+       dev_drv = &lcdc_dev->driver;
+       dev_drv->dev = dev;
+       dev_drv->prop = PRMRY;
+       dev_drv->id = lcdc_dev->id;
+        dev_drv->ops = &lcdc_drv_ops;
+       dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
+       spin_lock_init(&lcdc_dev->reg_lock);
+
+       lcdc_dev->irq = platform_get_irq(pdev, 0);
+       if (lcdc_dev->irq < 0) {
+               dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
+                       lcdc_dev->id);
+               ret = -ENXIO;
+                goto err_request_irq;
+       }
+
+       ret = devm_request_irq(dev, lcdc_dev->irq, rk312x_lcdc_isr,
+                              IRQF_DISABLED, dev_name(dev), lcdc_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
+                       lcdc_dev->irq, ret);
+               goto err_request_irq;
+       }
+
+       if (dev_drv->iommu_enabled)
+               strcpy(dev_drv->mmu_dts_name, "iommu,vop_mmu");
+
+       ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
+       if (ret < 0) {
+               dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
+               goto err_register_fb;
+       }
+       lcdc_dev->screen = dev_drv->screen0;
+
+       dev_info(dev, "lcdc%d probe ok, iommu %s\n",
+                lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
+        return 0;
+        
+err_register_fb:
+err_request_irq:
+        devm_kfree(lcdc_dev->dev, lcdc_dev->regsbak);
+err_remap_reg:
+err_parse_dt:
+        devm_kfree(&pdev->dev, lcdc_dev);
+       return ret;
+}
+
+#if defined(CONFIG_PM)
+static int rk312x_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       return 0;
+}
+
+static int rk312x_lcdc_resume(struct platform_device *pdev)
+{
+       return 0;
+}
+#else
+#define rk312x_lcdc_suspend NULL
+#define rk312x_lcdc_resume  NULL
+#endif
+
+static int rk312x_lcdc_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static void rk312x_lcdc_shutdown(struct platform_device *pdev)
+{
+        struct lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
+
+       rk312x_lcdc_deinit(lcdc_dev);
+        rk312x_lcdc_clk_disable(lcdc_dev);
+       rk_disp_pwr_disable(&lcdc_dev->driver);
+}
+
+static struct platform_driver rk312x_lcdc_driver = {
+       .probe = rk312x_lcdc_probe,
+       .remove = rk312x_lcdc_remove,
+       .driver = {
+                  .name = "rk312x-lcdc",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(rk312x_lcdc_dt_ids),
+                  },
+       .suspend = rk312x_lcdc_suspend,
+       .resume = rk312x_lcdc_resume,
+       .shutdown = rk312x_lcdc_shutdown,
+};
+
+static int __init rk312x_lcdc_module_init(void)
+{
+       return platform_driver_register(&rk312x_lcdc_driver);
+}
+
+static void __exit rk312x_lcdc_module_exit(void)
+{
+       platform_driver_unregister(&rk312x_lcdc_driver);
+}
+
+fs_initcall(rk312x_lcdc_module_init);
+module_exit(rk312x_lcdc_module_exit);
diff --git a/drivers/video/rockchip/lcdc/rk312x_lcdc.h b/drivers/video/rockchip/lcdc/rk312x_lcdc.h
new file mode 100755 (executable)
index 0000000..57b475f
--- /dev/null
@@ -0,0 +1,738 @@
+#ifndef _RK312X_LCDC_H_
+#define _RK312X_LCDC_H_
+
+#include<linux/rk_fb.h>
+#include<linux/io.h>
+#include<linux/clk.h>
+
+enum _VOP_SOC_TYPE {
+        VOP_RK3036 = 0,
+        VOP_RK312X,
+};
+
+
+#define BITS(x, bit)            ((x) << (bit))
+#define BITS_MASK(x, mask, bit) BITS((x) & (mask), bit)
+
+/*******************register definition**********************/
+
+#define SYS_CTRL                (0x00)
+        #define m_WIN0_EN               BITS(1, 0)
+        #define m_WIN1_EN              BITS(1, 1)
+        #define m_HWC_EN               BITS(1, 2)
+        #define m_WIN0_FORMAT          BITS(7, 3)
+        #define m_WIN1_FORMAT          BITS(7, 6)
+        #define m_HWC_LUT_EN           BITS(1, 9)
+        #define m_HWC_SIZE             BITS(1, 10)
+        #define m_DIRECT_PATH_EN        BITS(1, 11)      /* rk312x */
+        #define m_DIRECT_PATH_LAYER     BITS(1, 12)      /* rk312x */
+        #define m_TVE_MODE_SEL          BITS(1, 13)      /* rk312x */
+        #define m_TVE_DAC_EN            BITS(1, 14)      /* rk312x */
+        #define m_WIN0_RB_SWAP         BITS(1, 15)
+        #define m_WIN0_ALPHA_SWAP      BITS(1, 16)
+        #define m_WIN0_Y8_SWAP         BITS(1, 17)
+        #define m_WIN0_UV_SWAP         BITS(1, 18)
+        #define m_WIN1_RB_SWAP         BITS(1, 19)
+        #define m_WIN1_ALPHA_SWAP      BITS(1, 20)
+        #define m_WIN1_ENDIAN_SWAP      BITS(1, 21)      /* rk312x */
+        #define m_WIN0_OTSD_DISABLE    BITS(1, 22)
+        #define m_WIN1_OTSD_DISABLE    BITS(1, 23)
+        #define m_DMA_BURST_LENGTH     BITS(3, 24)
+        #define m_HWC_LODAD_EN         BITS(1, 26)
+        #define m_WIN1_LUT_EN           BITS(1, 27)      /* rk312x */
+        #define m_DSP_LUT_EN            BITS(1, 28)      /* rk312x */
+        #define m_DMA_STOP             BITS(1, 29)
+        #define m_LCDC_STANDBY         BITS(1, 30)
+        #define m_AUTO_GATING_EN       BITS(1, 31)
+       
+        #define v_WIN0_EN(x)           BITS_MASK(x, 1, 0)
+        #define v_WIN1_EN(x)           BITS_MASK(x, 1, 1)
+        #define v_HWC_EN(x)            BITS_MASK(x, 1, 2)
+        #define v_WIN0_FORMAT(x)       BITS_MASK(x, 7, 3)
+        #define v_WIN1_FORMAT(x)       BITS_MASK(x, 7, 6)
+        #define v_HWC_LUT_EN(x)                BITS_MASK(x, 1, 9)
+        #define v_HWC_SIZE(x)          BITS_MASK(x, 1, 10)
+        #define v_DIRECT_PATH_EN(x)     BITS_MASK(x, 1, 11)
+        #define v_DIRECT_PATH_LAYER(x)  BITS_MASK(x, 1, 12)
+        #define v_TVE_MODE_SEL(x)       BITS_MASK(x, 1, 13)
+        #define v_TVE_DAC_EN(x)         BITS_MASK(x, 1, 14)
+        #define v_WIN0_RB_SWAP(x)      BITS_MASK(x, 1, 15)
+        #define v_WIN0_ALPHA_SWAP(x)   BITS_MASK(x, 1, 16)
+        #define v_WIN0_Y8_SWAP(x)      BITS_MASK(x, 1, 17)
+        #define v_WIN0_UV_SWAP(x)      BITS_MASK(x, 1, 18)
+        #define v_WIN1_RB_SWAP(x)      BITS_MASK(x, 1, 19)
+        #define v_WIN1_ALPHA_SWAP(x)   BITS_MASK(x, 1, 20)
+        #define v_WIN1_ENDIAN_SWAP(x)   BITS_MASK(x, 1, 21)
+        #define v_WIN0_OTSD_DISABLE(x) BITS_MASK(x, 1, 22)
+        #define v_WIN1_OTSD_DISABLE(x) BITS_MASK(x, 1, 23)
+        #define v_DMA_BURST_LENGTH(x)  BITS_MASK(x, 3, 24)
+        #define v_HWC_LODAD_EN(x)      BITS_MASK(x, 1, 26)
+        #define v_WIN1_LUT_EN(x)       BITS_MASK(x, 1, 27)
+        #define v_DSP_LUT_EN(x)         BITS_MASK(x, 1, 28)
+        #define v_DMA_STOP(x)          BITS_MASK(x, 1, 29)
+        #define v_LCDC_STANDBY(x)      BITS_MASK(x, 1, 30)
+        #define v_AUTO_GATING_EN(x)    BITS_MASK(x, 1, 31)
+
+#define DSP_CTRL0              (0x04)
+        #define m_DSP_OUT_FORMAT       BITS(0x0f, 0)
+        #define m_HSYNC_POL            BITS(1, 4)
+        #define m_VSYNC_POL            BITS(1, 5)
+        #define m_DEN_POL              BITS(1, 6)
+        #define m_DCLK_POL             BITS(1, 7)
+        #define m_WIN0_TOP             BITS(1, 8)
+        #define m_DITHER_UP_EN         BITS(1, 9)
+        #define m_DITHER_DOWN_MODE     BITS(1, 10)     /* use for rk312x */
+        #define m_DITHER_DOWN_EN       BITS(1, 11)     /* use for rk312x */
+        #define m_INTERLACE_DSP_EN     BITS(1, 12)
+        #define m_INTERLACE_FIELD_POL  BITS(1, 13)     /* use for rk312x */
+        #define m_WIN0_INTERLACE_EN    BITS(1, 14)     /* use for rk312x */
+        #define m_WIN1_INTERLACE_EN    BITS(1, 15)
+        #define m_WIN0_YRGB_DEFLICK_EN BITS(1, 16)
+        #define m_WIN0_CBR_DEFLICK_EN  BITS(1, 17)
+        #define m_WIN0_ALPHA_MODE      BITS(1, 18)
+        #define m_WIN1_ALPHA_MODE      BITS(1, 19)
+        #define m_WIN0_CSC_MODE                BITS(3, 20)
+        #define m_WIN0_YUV_CLIP                BITS(1, 23)
+        #define m_TVE_MODE             BITS(1, 25)
+        #define m_SW_UV_OFFSET_EN      BITS(1, 26)     /* use for rk312x */
+        #define m_DITHER_DOWN_SEL      BITS(1, 27)     /* use for rk312x */
+        #define m_HWC_ALPHA_MODE       BITS(1, 28)
+        #define m_ALPHA_MODE_SEL0       BITS(1, 29)
+        #define m_ALPHA_MODE_SEL1      BITS(1, 30)
+        #define m_WIN1_DIFF_DCLK_EN    BITS(1, 31)     /* use for rk3036 */
+        #define m_SW_OVERLAY_MODE      BITS(1, 31)     /* use for rk312x */
+       
+        #define v_DSP_OUT_FORMAT(x)    BITS_MASK(x, 0x0f, 0)
+        #define v_HSYNC_POL(x)         BITS_MASK(x, 1, 4)
+        #define v_VSYNC_POL(x)         BITS_MASK(x, 1, 5)
+        #define v_DEN_POL(x)           BITS_MASK(x, 1, 6)
+        #define v_DCLK_POL(x)          BITS_MASK(x, 1, 7)
+        #define v_WIN0_TOP(x)          BITS_MASK(x, 1, 8)
+        #define v_DITHER_UP_EN(x)      BITS_MASK(x, 1, 9)
+        #define v_DITHER_DOWN_MODE(x)  BITS_MASK(x, 1, 10)     /* rk312x */
+        #define v_DITHER_DOWN_EN(x)    BITS_MASK(x, 1, 11)     /* rk312x */
+        #define v_INTERLACE_DSP_EN(x)  BITS_MASK(x, 1, 12)
+        #define v_INTERLACE_FIELD_POL(x)       BITS_MASK(x, 1, 13)     /* rk312x */
+        #define v_WIN0_INTERLACE_EN(x)         BITS_MASK(x, 1, 14)     /* rk312x */
+        #define v_WIN1_INTERLACE_EN(x)         BITS_MASK(x, 1, 15)
+        #define v_WIN0_YRGB_DEFLICK_EN(x)      BITS_MASK(x, 1, 16)
+        #define v_WIN0_CBR_DEFLICK_EN(x)       BITS_MASK(x, 1, 17)
+        #define v_WIN0_ALPHA_MODE(x)           BITS_MASK(x, 1, 18)
+        #define v_WIN1_ALPHA_MODE(x)           BITS_MASK(x, 1, 19)
+        #define v_WIN0_CSC_MODE(x)             BITS_MASK(x, 3, 20)
+        #define v_WIN0_YUV_CLIP(x)             BITS_MASK(x, 1, 23)
+        #define v_TVE_MODE(x)                  BITS_MASK(x, 1, 25)
+        #define v_SW_UV_OFFSET_EN(x)           BITS_MASK(x, 1, 26)      /* rk312x */
+        #define v_DITHER_DOWN_SEL(x)           BITS_MASK(x, 1, 27)      /* rk312x */
+        #define v_HWC_ALPHA_MODE(x)            BITS_MASK(x, 1, 28)
+        #define v_ALPHA_MODE_SEL0(x)            BITS_MASK(x, 1, 29)
+        #define v_ALPHA_MODE_SEL1(x)           BITS_MASK(x, 1, 30)
+        #define v_WIN1_DIFF_DCLK_EN(x)         BITS_MASK(x, 1, 31)     /* rk3036 */
+        #define v_SW_OVERLAY_MODE(x)           BITS_MASK(x, 1, 31)     /* rk312x */
+
+#define DSP_CTRL1              (0x08)
+        #define m_BG_COLOR             BITS(0xffffff, 0)
+        #define m_BG_B                 BITS(0xff, 0)
+        #define m_BG_G                 BITS(0xff, 8)
+        #define m_BG_R                 BITS(0xff, 16)
+        #define m_BLANK_EN             BITS(1, 24)
+        #define m_BLACK_EN             BITS(1, 25)
+        #define m_DSP_BG_SWAP          BITS(1, 26)
+        #define m_DSP_RB_SWAP          BITS(1, 27)
+        #define m_DSP_RG_SWAP          BITS(1, 28)
+        #define m_DSP_DELTA_SWAP       BITS(1, 29)              /* rk3036 */
+        #define m_DSP_DUMMY_SWAP       BITS(1, 30)             /* rk3036 */
+        #define m_DSP_OUT_ZERO         BITS(1, 31)
+       
+        #define v_BG_COLOR(x)          BITS_MASK(x, 0xffffff, 0)
+        #define v_BG_B(x)              BITS_MASK(x, 0xff, 0)
+        #define v_BG_G(x)              BITS_MASK(x, 0xff, 8)
+        #define v_BG_R(x)              BITS_MASK(x, 0xff, 16)
+        #define v_BLANK_EN(x)          BITS_MASK(x, 1, 24)
+        #define v_BLACK_EN(x)          BITS_MASK(x, 1, 25)
+        #define v_DSP_BG_SWAP(x)       BITS_MASK(x, 1, 26)
+        #define v_DSP_RB_SWAP(x)       BITS_MASK(x, 1, 27)
+        #define v_DSP_RG_SWAP(x)       BITS_MASK(x, 1, 28)
+        #define v_DSP_DELTA_SWAP(x)    BITS_MASK(x, 1, 29)      /* rk3036 */
+        #define v_DSP_DUMMY_SWAP(x)    BITS_MASK(x, 1, 30)      /* rk3036 */
+        #define v_DSP_OUT_ZERO(x)      BITS_MASK(x, 1, 31)
+
+#define INT_SCALER              (0x0c)          /* only use for rk312x */
+        #define m_SCALER_EMPTY_INTR_EN  BITS(1, 0)
+        #define m_SCLAER_EMPTY_INTR_CLR BITS(1, 1)
+        #define m_SCLAER_EMPTY_INTR_STA BITS(1, 2)
+        #define m_FS_MASK_EN            BITS(1, 3)
+        #define m_HDMI_HSYNC_POL        BITS(1, 4)
+        #define m_HDMI_VSYNC_POL        BITS(1, 5)
+        #define m_HDMI_DEN_POL          BITS(1, 6)
+
+        #define v_SCALER_EMPTY_INTR_EN(x)       BITS_MASK(x, 1, 0)
+        #define v_SCLAER_EMPTY_INTR_CLR(x)      BITS_MASK(x, 1, 1)
+        #define v_SCLAER_EMPTY_INTR_STA(x)      BITS_MASK(x, 1, 2)
+        #define v_FS_MASK_EN(x)                 BITS_MASK(x, 1, 3)
+        #define v_HDMI_HSYNC_POL(x)             BITS_MASK(x, 1, 4)
+        #define v_HDMI_VSYNC_POL(x)             BITS_MASK(x, 1, 5)
+        #define v_HDMI_DEN_POL(x)               BITS_MASK(x. 1, 6)
+
+#define INT_STATUS             (0x10)
+        #define m_HS_INT_STA           BITS(1, 0)
+        #define m_FS_INT_STA           BITS(1, 1)
+        #define m_LF_INT_STA           BITS(1, 2)
+        #define m_BUS_ERR_INT_STA      BITS(1, 3)
+        #define m_HS_INT_EN            BITS(1, 4)
+        #define m_FS_INT_EN            BITS(1, 5)
+        #define m_LF_INT_EN            BITS(1, 6)
+        #define m_BUS_ERR_INT_EN       BITS(1, 7)
+        #define m_HS_INT_CLEAR         BITS(1, 8)
+        #define m_FS_INT_CLEAR         BITS(1, 9)
+        #define m_LF_INT_CLEAR         BITS(1, 10)
+        #define m_BUS_ERR_INT_CLEAR    BITS(1, 11)
+        #define m_LF_INT_NUM           BITS(0xfff, 12)
+        #define m_WIN0_EMPTY_INT_EN    BITS(1, 24)
+        #define m_WIN1_EMPTY_INT_EN    BITS(1, 25)
+        #define m_WIN0_EMPTY_INT_CLEAR BITS(1, 26)
+        #define m_WIN1_EMPTY_INT_CLEAR BITS(1, 27)
+        #define m_WIN0_EMPTY_INT_STA   BITS(1, 28)
+        #define m_WIN1_EMPTY_INT_STA   BITS(1, 29)
+        #define m_FS_RAW_STA           BITS(1, 30)
+        #define m_LF_RAW_STA           BITS(1, 31)
+       
+        #define v_HS_INT_EN(x)         BITS_MASK(x, 1, 4)
+        #define v_FS_INT_EN(x)         BITS_MASK(x, 1, 5)
+        #define v_LF_INT_EN(x)         BITS_MASK(x, 1, 6)
+        #define v_BUS_ERR_INT_EN(x)    BITS_MASK(x, 1, 7)
+        #define v_HS_INT_CLEAR(x)      BITS_MASK(x, 1, 8)
+        #define v_FS_INT_CLEAR(x)      BITS_MASK(x, 1, 9)
+        #define v_LF_INT_CLEAR(x)      BITS_MASK(x, 1, 10)
+        #define v_BUS_ERR_INT_CLEAR(x) BITS_MASK(x, 1, 11)
+        #define v_LF_INT_NUM(x)                BITS_MASK(x, 0xfff, 12)
+        #define v_WIN0_EMPTY_INT_EN(x) BITS_MASK(x, 1, 24)
+        #define v_WIN1_EMPTY_INT_EN(x) BITS_MASK(x, 1, 25)
+        #define v_WIN0_EMPTY_INT_CLEAR(x)      BITS_MASK(x, 1, 26)
+        #define v_WIN1_EMPTY_INT_CLEAR(x)      BITS_MASK(x, 1, 27)
+
+#define ALPHA_CTRL             (0x14)
+        #define m_WIN0_ALPHA_EN                BITS(1, 0)
+        #define m_WIN1_ALPHA_EN                BITS(1, 1)
+        #define m_HWC_ALPAH_EN         BITS(1, 2)
+        #define m_WIN1_PREMUL_SCALE    BITS(1, 3)               /* rk3036 */
+        #define m_WIN0_ALPHA_VAL       BITS(0xff, 4)
+        #define m_WIN1_ALPHA_VAL       BITS(0xff, 12)
+        #define m_HWC_ALPAH_VAL                BITS(0xff, 20)
+       
+        #define v_WIN0_ALPHA_EN(x)     BITS_MASK(x, 1, 0)
+        #define v_WIN1_ALPHA_EN(x)     BITS_MASK(x, 1, 1)
+        #define v_HWC_ALPAH_EN(x)      BITS_MASK(x, 1, 2)
+        #define v_WIN1_PREMUL_SCALE(x) BITS_MASK(x, 1, 3)       /* rk3036 */
+        #define v_WIN0_ALPHA_VAL(x)    BITS_MASK(x, 0xff, 4)
+        #define v_WIN1_ALPHA_VAL(x)    BITS_MASK(x, 0xff, 12)
+        #define v_HWC_ALPAH_VAL(x)     BITS_MASK(x, 0xff, 20)
+
+#define WIN0_COLOR_KEY         (0x18)
+#define WIN1_COLOR_KEY         (0x1c)
+        #define m_COLOR_KEY_VAL                BITS(0xffffff, 0)
+        #define m_COLOR_KEY_EN         BITS(1, 24)
+
+        #define v_COLOR_KEY_VAL(x)     BITS_MASK(x, 0xffffff, 0)
+        #define v_COLOR_KEY_EN(x)      BITS_MASK(x, 1, 24)
+
+/* Layer Registers */
+#define WIN0_YRGB_MST          (0x20)
+#define WIN0_CBR_MST           (0x24)
+#define WIN1_MST               (0xa0)                  /* rk3036 */
+#define WIN1_MST_RK312X         (0x4c)                  /* rk312x */
+#define HWC_MST                        (0x58)
+
+#define WIN1_VIR               (0x28)
+#define WIN0_VIR               (0x30)
+        #define m_YRGB_VIR             BITS(0x1fff, 0)
+        #define m_CBBR_VIR             BITS(0x1fff, 16)   
+       
+        #define v_YRGB_VIR(x)           BITS_MASK(x, 0x1fff, 0)
+        #define v_CBBR_VIR(x)           BITS_MASK(x, 0x1fff, 16)
+       
+       #define v_ARGB888_VIRWIDTH(x)   BITS_MASK(x, 0x1fff, 0)
+       #define v_RGB888_VIRWIDTH(x)    BITS_MASK(((x*3)>>2)+((x)%3), 0x1fff, 0)
+       #define v_RGB565_VIRWIDTH(x)    BITS_MASK(DIV_ROUND_UP(x, 2), 0x1fff, 0)
+       #define v_YUV_VIRWIDTH(x)       BITS_MASK(DIV_ROUND_UP(x, 4), 0x1fff, 0)
+       #define v_CBCR_VIR(x)           BITS_MASK(x, 0x1fff, 16)
+
+#define WIN0_ACT_INFO          (0x34)
+#define WIN1_ACT_INFO          (0xb4)          /* rk3036 */
+       #define m_ACT_WIDTH             BITS(0x1fff, 0)
+       #define m_ACT_HEIGHT            BITS(0x1fff, 16)
+       #define v_ACT_WIDTH(x)          BITS_MASK(x - 1, 0x1fff, 0)
+       #define v_ACT_HEIGHT(x)         BITS_MASK(x - 1, 0x1fff, 16)
+
+#define WIN0_DSP_INFO          (0x38)
+#define WIN1_DSP_INFO          (0xb8)          /* rk3036 */
+#define WIN1_DSP_INFO_RK312X    (0x50)          /* rk312x */
+        #define m_DSP_WIDTH            BITS(0x7ff, 0)
+       #define m_DSP_HEIGHT            BITS(0x7ff, 16)
+
+       #define v_DSP_WIDTH(x)          BITS_MASK(x - 1, 0x7ff, 0)
+       #define v_DSP_HEIGHT(x)         BITS_MASK(x - 1, 0x7ff, 16)
+       
+#define WIN0_DSP_ST            (0x3c)
+#define WIN1_DSP_ST            (0xbc)          /* rk3036 */
+#define WIN1_DSP_ST_RK312X      (0x54)          /* rk312x */
+#define HWC_DSP_ST             (0x5c)
+        #define m_DSP_STX               BITS(0xfff, 0)
+       #define m_DSP_STY               BITS(0xfff, 16)
+
+       #define v_DSP_STX(x)            BITS_MASK(x, 0xfff, 0)
+       #define v_DSP_STY(x)            BITS_MASK(x, 0xfff, 16)
+       
+#define WIN0_SCL_FACTOR_YRGB   (0x40)
+#define WIN0_SCL_FACTOR_CBR    (0x44)
+#define WIN1_SCL_FACTOR_YRGB   (0xc0)          /* rk3036 */
+        #define m_X_SCL_FACTOR          BITS(0xffff, 0)
+       #define m_Y_SCL_FACTOR          BITS(0xffff, 16)
+
+       #define v_X_SCL_FACTOR(x)       BITS_MASK(x, 0xffff, 0)
+       #define v_Y_SCL_FACTOR(x)       BITS_MASK(x, 0xffff, 16)
+       
+#define WIN0_SCL_OFFSET                (0x48)
+#define WIN1_SCL_OFFSET                (0xc8)          /* rk3036 */
+
+/* LUT Registers */
+#define WIN1_LUT_ADDR          (0x0400)        /* rk3036 */
+#define HWC_LUT_ADDR                   (0x0800)
+#define DSP_LUT_ADDR            (0x0c00)        /* rk312x */
+
+/* Display Infomation Registers */
+#define DSP_HTOTAL_HS_END      (0x6c)
+       #define v_HSYNC(x)              BITS_MASK(x, 0xfff, 0)   /* hsync pulse width */
+       #define v_HORPRD(x)             BITS_MASK(x, 0xfff, 16)  /* horizontal period */
+
+#define DSP_HACT_ST_END                (0x70)
+       #define v_HAEP(x)               BITS_MASK(x, 0xfff, 0)  /* horizontal active end point */
+       #define v_HASP(x)               BITS_MASK(x, 0xfff, 16) /* horizontal active start point */
+
+#define DSP_VTOTAL_VS_END      (0x74)
+       #define v_VSYNC(x)              BITS_MASK(x, 0xfff, 0)
+       #define v_VERPRD(x)             BITS_MASK(x, 0xfff, 16)
+       
+#define DSP_VACT_ST_END                (0x78)
+       #define v_VAEP(x)               BITS_MASK(x, 0xfff, 0)
+       #define v_VASP(x)               BITS_MASK(x, 0xfff, 16)
+
+#define DSP_VS_ST_END_F1       (0x7c)
+       #define v_VSYNC_END_F1(x)       BITS_MASK(x, 0xfff, 0)
+       #define v_VSYNC_ST_F1(x)        BITS_MASK(x, 0xfff, 16)
+#define DSP_VACT_ST_END_F1     (0x80)
+        #define v_VAEP_F1(x)           BITS_MASK(x, 0xfff, 0)
+       #define v_VASP_F1(x)            BITS_MASK(x, 0xfff, 16)
+
+/* Scaler Registers 
+ * Only used for rk312x
+ */
+#define SCALER_CTRL             (0xa0)
+        #define m_SCALER_EN             BITS(1, 0)
+        #define m_SCALER_SYNC_INVERT    BITS(1, 2)
+        #define m_SCALER_DEN_INVERT     BITS(1, 3)
+        #define m_SCALER_OUT_ZERO       BITS(1, 4)
+        #define m_SCALER_OUT_EN         BITS(1, 5)
+        #define m_SCALER_VSYNC_MODE     BITS(3, 6)
+        #define m_SCALER_VSYNC_VST      BITS(0xff, 8)
+
+        #define v_SCALER_EN(x)          BITS_MASK(x, 1, 0)
+        #define v_SCALER_SYNC_INVERT(x) BITS_MASK(x, 1, 2)
+        #define v_SCALER_DEN_INVERT(x)  BITS_MASK(x, 1, 3)
+        #define v_SCALER_OUT_ZERO(x)    BITS_MASK(x, 1, 4)
+        #define v_SCALER_OUT_EN(x)      BITS_MASK(x, 1, 5)
+        #define v_SCALER_VSYNC_MODE(x)  BITS_MASK(x, 3, 6)
+        #define v_SCALER_VSYNC_VST(x)   BITS_MASK(x, 0xff, 8)
+
+#define SCALER_FACTOR           (0xa4)
+        #define m_SCALER_H_FACTOR       BITS(0x3fff, 0)
+        #define m_SCALER_V_FACTOR       BITS(0x3fff, 16)
+
+        #define v_SCALER_H_FACTOR(x)    BITS_MASK(x, 0x3fff, 0)
+        #define v_SCALER_V_FACTOR(x)    BITS_MASK(x, 0x3fff, 16)
+
+#define SCALER_FRAME_ST         (0xa8)
+        #define m_SCALER_FRAME_HST      BITS(0xfff, 0)
+        #define m_SCALER_FRAME_VST      BITS(0xfff, 16)
+
+        #define v_SCALER_FRAME_HST(x)   BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_FRAME_VST(x)   BITS_MASK(x, 0xfff, 16)
+
+#define SCALER_DSP_HOR_TIMING   (0xac)
+        #define m_SCALER_HTOTAL         BITS(0xfff, 0)
+        #define m_SCALER_HS_END         BITS(0xff, 16)
+
+        #define v_SCALER_HTOTAL(x)      BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_HS_END(x)      BITS_MASK(x, 0xff, 16)
+
+#define SCALER_DSP_HACT_ST_END  (0xb0)
+        #define m_SCALER_HAEP           BITS(0xfff, 0)
+        #define m_SCALER_HASP           BITS(0x3ff, 16)
+
+        #define v_SCALER_HAEP(x)        BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_HASP(x)        BITS_MASK(x, 0x3ff, 16)
+
+#define SCALER_DSP_VER_TIMING   (0xb4)
+        #define m_SCALER_VTOTAL         BITS(0xfff, 0)
+        #define m_SCALER_VS_END         BITS(0xff, 16)
+
+        #define v_SCALER_VTOTAL(x)      BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_VS_END(x)      BITS_MASK(x, 0xff, 16)
+
+#define SCALER_DSP_VACT_ST_END  (0xb8)
+        #define m_SCALER_VAEP           BITS(0xfff, 0)
+        #define m_SCALER_VASP           BITS(0xff, 16)
+
+        #define v_SCALER_VAEP(x)        BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_VASP(x)        BITS_MASK(x, 0xff, 16)
+
+#define SCALER_DSP_HBOR_TIMING  (0xbc)
+        #define m_SCALER_HBOR_END       BITS(0xfff, 0)
+        #define m_SCALER_HBOR_ST        BITS(0x3ff, 16)
+
+        #define v_SCALER_HBOR_END(x)    BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_HBOR_ST(x)     BITS_MASK(x, 0x3ff, 16)
+
+#define SCALER_DSP_VBOR_TIMING  (0xc0)
+        #define m_SCALER_VBOR_END       BITS(0xfff, 0)
+        #define m_SCALER_VBOR_ST        BITS(0xff, 16)
+
+        #define v_SCALER_VBOR_END(x)    BITS_MASK(x, 0xfff, 0)
+        #define v_SCALER_VBOR_ST(x)     BITS_MASK(x, 0xff, 16)        
+
+/* BCSH Registers */
+#define BCSH_CTRL              (0xd0)
+       #define m_BCSH_EN               BITS(1, 0)
+        #define m_BCSH_R2Y_CSC_MODE     BITS(1, 1)       /* rk312x */
+       #define m_BCSH_OUT_MODE         BITS(3, 2)
+       #define m_BCSH_Y2R_CSC_MODE     BITS(3, 4)
+        #define m_BCSH_Y2R_EN           BITS(1, 6)       /* rk312x */
+        #define m_BCSH_R2Y_EN           BITS(1, 7)       /* rk312x */
+       
+       #define v_BCSH_EN(x)            BITS_MASK(x, 1, 0)
+        #define v_BCSH_R2Y_CSC_MODE(x)  BITS_MASK(x, 1, 1)       /* rk312x */
+       #define v_BCSH_OUT_MODE(x)      BITS_MASK(x, 3, 2)
+       #define v_BCSH_CSC_MODE(x)      BITS_MASK(x, 3, 4)
+        #define v_BCSH_Y2R_EN(x)        BITS_MASK(x, 1, 6)       /* rk312x */
+        #define v_BCSH_R2Y_EN(x)        BITS_MASK(x, 1, 7)       /* rk312x */
+
+#define BCSH_COLOR_BAR                 (0xd4)
+        #define m_BCSH_COLOR_BAR_Y      BITS(0xff, 0)
+       #define m_BCSH_COLOR_BAR_U      BITS(0xff, 8)
+       #define m_BCSH_COLOR_BAR_V      BITS(0xff, 16)
+
+       #define v_BCSH_COLOR_BAR_Y(x)   BITS_MASK(x, 0xff, 0)
+       #define v_BCSH_COLOR_BAR_U(x)   BITS_MASK(x, 0xff, 8)
+       #define v_BCSH_COLOR_BAR_V(x)   BITS_MASK(x, 0xff, 16)
+
+#define BCSH_BCS               (0xd8)  
+       #define m_BCSH_BRIGHTNESS       BITS(0x1f, 0)   
+       #define m_BCSH_CONTRAST         BITS(0xff, 8)
+       #define m_BCSH_SAT_CON          BITS(0x1ff, 16)
+
+       #define v_BCSH_BRIGHTNESS(x)    BITS_MASK(x, 0x1f, 0)   
+       #define v_BCSH_CONTRAST(x)      BITS_MASK(x, 0xff, 8)   
+       #define v_BCSH_SAT_CON(x)       BITS_MASK(x, 0x1ff, 16)                 
+
+#define BCSH_H                         (0xdc)  
+       #define m_BCSH_SIN_HUE          BITS(0xff, 0)
+       #define m_BCSH_COS_HUE          BITS(0xff, 16)
+
+       #define v_BCSH_SIN_HUE(x)       BITS_MASK(x, 0xff, 0)
+       #define v_BCSH_COS_HUE(x)       BITS_MASK(x, 0xff, 16)
+
+#define FRC_LOWER01_0           (0xe0)
+#define FRC_LOWER01_1           (0xe4)
+#define FRC_LOWER10_0           (0xe8)
+#define FRC_LOWER10_1           (0xec)
+#define FRC_LOWER11_0           (0xf0)
+#define FRC_LOWER11_1           (0xf4)
+
+/* Bus Register */
+#define AXI_BUS_CTRL           (0x2c)
+       #define m_IO_PAD_CLK                    BITS(1, 31)
+       #define m_CORE_CLK_DIV_EN               BITS(1, 30)
+        #define m_MIPI_DCLK_INVERT              BITS(1, 29)      /* rk312x */
+        #define m_MIPI_DCLK_EN                  BITS(1, 28)      /* rk312x */
+        #define m_LVDS_DCLK_INVERT              BITS(1, 27)      /* rk312x */
+        #define m_LVDS_DCLK_EN                  BITS(1, 26)      /* rk312x */
+        #define m_RGB_DCLK_INVERT               BITS(1, 25)      /* rk312x */
+        #define m_RGB_DCLK_EN                   BITS(1, 24)      /* rk312x */
+       #define m_HDMI_DCLK_INVERT              BITS(1, 23)
+       #define m_HDMI_DCLK_EN                  BITS(1, 22)
+       #define m_TVE_DAC_DCLK_INVERT           BITS(1, 21)
+       #define m_TVE_DAC_DCLK_EN               BITS(1, 20)
+       #define m_HDMI_DCLK_DIV_EN              BITS(1, 19)
+       #define m_AXI_OUTSTANDING_MAX_NUM       BITS(0x1f, 12)
+       #define m_AXI_MAX_OUTSTANDING_EN        BITS(1, 11)
+       #define m_MMU_EN                        BITS(1, 10)
+       #define m_NOC_HURRY_THRESHOLD           BITS(0xf, 6)
+       #define m_NOC_HURRY_VALUE               BITS(3, 4)
+       #define m_NOC_HURRY_EN                  BITS(1, 3)
+       #define m_NOC_QOS_VALUE                 BITS(3, 1)
+       #define m_NOC_QOS_EN                    BITS(1, 0)
+       
+       #define v_IO_PAD_CLK(x)                 BITS_MASK(x, 1, 31)
+       #define v_CORE_CLK_DIV_EN(x)            BITS_MASK(x, 1, 30)
+        #define v_MIPI_DCLK_INVERT(x)           BITS_MASK(x, 1, 29)
+        #define v_MIPI_DCLK_EN(x)               BITS_MASK(x, 1, 28)
+        #define v_LVDS_DCLK_INVERT(x)           BITS_MASK(x, 1, 27)
+        #define v_LVDS_DCLK_EN(x)               BITS_MASK(x, 1, 26)
+        #define v_RGB_DCLK_INVERT(x)            BITS_MASK(x, 1, 25)
+        #define v_RGB_DCLK_EN(x)                BITS_MASK(x, 1, 24)
+       #define v_HDMI_DCLK_INVERT(x)           BITS_MASK(x, 1, 23)
+       #define v_HDMI_DCLK_EN(x)               BITS_MASK(x, 1, 22)
+       #define v_TVE_DAC_DCLK_INVERT(x)        BITS_MASK(x, 1, 21)
+       #define v_TVE_DAC_DCLK_EN(x)            BITS_MASK(x, 1, 20)
+       #define v_HDMI_DCLK_DIV_EN(x)           BITS_MASK(x, 1, 19)
+       #define v_AXI_OUTSTANDING_MAX_NUM(x)    BITS_MASK(x, 0x1f, 12)
+       #define v_AXI_MAX_OUTSTANDING_EN(x)     BITS_MASK(x, 1, 11)
+       #define v_MMU_EN(x)                     BITS_MASK(x, 1, 10)
+       #define v_NOC_HURRY_THRESHOLD(x)        BITS_MASK(x, 0xf, 6)
+       #define v_NOC_HURRY_VALUE(x)            BITS_MASK(x, 3, 4)
+       #define v_NOC_HURRY_EN(x)               BITS_MASK(x, 1, 3)
+       #define v_NOC_QOS_VALUE(x)              BITS_MASK(x, 3, 1)
+       #define v_NOC_QOS_EN(x)                 BITS_MASK(x, 1, 0)
+       
+#define GATHER_TRANSFER                (0x84)
+       #define m_WIN1_AXI_GATHER_NUM           BITS(0xf, 12)
+       #define m_WIN0_CBCR_AXI_GATHER_NUM      BITS(0x7, 8)
+       #define m_WIN0_YRGB_AXI_GATHER_NUM      BITS(0xf, 4)
+       #define m_WIN1_AXI_GAHTER_EN            BITS(1, 2)
+       #define m_WIN0_CBCR_AXI_GATHER_EN       BITS(1, 1)
+       #define m_WIN0_YRGB_AXI_GATHER_EN       BITS(1, 0)
+       
+       #define v_WIN1_AXI_GATHER_NUM(x)        BITS_MASK(x, 0xf, 12)
+       #define v_WIN0_CBCR_AXI_GATHER_NUM(x)   BITS_MASK(x, 0x7, 8)
+       #define v_WIN0_YRGB_AXI_GATHER_NUM(x)   BITS_MASK(x, 0xf, 4)
+       #define v_WIN1_AXI_GAHTER_EN(x)         BITS_MASK(x, 1, 2)
+       #define v_WIN0_CBCR_AXI_GATHER_EN(x)    BITS_MASK(x, 1, 1)
+       #define v_WIN0_YRGB_AXI_GATHER_EN(x)    BITS_MASK(x, 1, 0)
+       
+#define VERSION_INFO           (0x94)
+       #define m_MAJOR                         BITS(0xff, 24)
+       #define m_MINOR                         BITS(0xff, 16)
+       #define m_BUILD                         BITS(0xffff)
+               
+#define REG_CFG_DONE           (0x90)
+
+/* TV Control Registers */
+#define TV_CTRL                        (0x200) 
+#define TV_SYNC_TIMING         (0x204)
+#define TV_ACT_TIMING          (0x208)
+#define TV_ADJ_TIMING          (0x20c)
+#define TV_FREQ_SC             (0x210)
+#define TV_FILTER0             (0x214)
+#define TV_FILTER1             (0x218)
+#define TV_FILTER2             (0x21C)
+#define TV_ACT_ST              (0x234)
+#define TV_ROUTING             (0x238)
+#define TV_SYNC_ADJUST         (0x250)
+#define TV_STATUS              (0x254)
+#define TV_RESET               (0x268)
+#define TV_SATURATION          (0x278)
+#define TV_BW_CTRL             (0x28C)
+#define TV_BRIGHTNESS_CONTRAST (0x290)
+
+
+/* MMU registers */
+#define MMU_DTE_ADDR           (0x0300)
+        #define m_MMU_DTE_ADDR                 BITS(0xffffffff, 0)
+       #define v_MMU_DTE_ADDR(x)               BITS_MASK(x, 0xffffffff, 0)
+
+#define MMU_STATUS             (0x0304)
+        #define m_PAGING_ENABLED               BITS(1, 0)
+       #define m_PAGE_FAULT_ACTIVE             BITS(1, 1)
+       #define m_STAIL_ACTIVE                  BITS(1, 2)
+       #define m_MMU_IDLE                      BITS(1, 3)
+       #define m_REPLAY_BUFFER_EMPTY           BITS(1, 4)
+       #define m_PAGE_FAULT_IS_WRITE           BITS(1, 5)
+       #define m_PAGE_FAULT_BUS_ID             BITS(0x1f, 6)
+
+       #define v_PAGING_ENABLED(x)             BITS_MASK(x, 1, 0)
+       #define v_PAGE_FAULT_ACTIVE(x)          BITS_MASK(x, 1, 1)
+       #define v_STAIL_ACTIVE(x)               BITS_MASK(x, 1, 2)
+       #define v_MMU_IDLE(x)                   BITS_MASK(x, 1, 3)
+       #define v_REPLAY_BUFFER_EMPTY(x)        BITS_MASK(x, 1, 4)
+       #define v_PAGE_FAULT_IS_WRITE(x)        BITS_MASK(x, 1, 5)
+       #define v_PAGE_FAULT_BUS_ID(x)          BITS_MASK(x, 0x1f, 6)
+       
+#define MMU_COMMAND            (0x0308)
+        #define m_MMU_CMD                      BITS(0x7, 0)
+       #define v_MMU_CMD(x)                    BITS_MASK(x, 0x7, 0)    
+
+#define MMU_PAGE_FAULT_ADDR    (0x030c)
+        #define m_PAGE_FAULT_ADDR              BITS(0xffffffff, 0)
+       #define v_PAGE_FAULT_ADDR(x)            BITS_MASK(x, 0xffffffff, 0)
+       
+#define MMU_ZAP_ONE_LINE       (0x0310)
+        #define m_MMU_ZAP_ONE_LINE             BITS(0xffffffff, 0)
+       #define v_MMU_ZAP_ONE_LINE(x)           BITS_MASK(x, 0xffffffff, 0)
+
+#define MMU_INT_RAWSTAT                (0x0314)
+        #define m_PAGE_FAULT_RAWSTAT           BITS(1, 0)
+       #define m_READ_BUS_ERROR_RAWSTAT        BITS(1, 1)
+       #define v_PAGE_FAULT_RAWSTAT(x)         BITS(x, 1, 0)
+       #define v_READ_BUS_ERROR_RAWSTAT(x)     BITS(x, 1, 1)
+       
+#define MMU_INT_CLEAR          (0x0318)
+        #define m_PAGE_FAULT_CLEAR             BITS(1, 0)
+       #define m_READ_BUS_ERROR_CLEAR          BITS(1, 1)
+
+       #define v_PAGE_FAULT_CLEAR(x)           BITS(x, 1, 0)
+       #define v_READ_BUS_ERROR_CLEAR(x)       BITS(x, 1, 1)
+       
+#define MMU_INT_MASK           (0x031c)
+        #define m_PAGE_FAULT_MASK              BITS(1, 0)
+       #define m_READ_BUS_ERROR_MASK           BITS(1, 1)
+
+       #define v_PAGE_FAULT_MASK(x)            BITS(x, 1, 0)
+       #define v_READ_BUS_ERROR_MASK(x)        BITS(x, 1, 1)
+       
+#define MMU_INT_STATUS         (0x0320)
+        #define m_PAGE_FAULT_STATUS            BITS(1, 0)
+       #define m_READ_BUS_ERROR_STATUS         BITS(1, 1)
+
+       #define v_PAGE_FAULT_STATUS(x)          BITS(x, 1, 0)
+       #define v_READ_BUS_ERROR_STATUS(x)      BITS(x, 1, 1)
+
+#define MMU_AUTO_GATING                (0x0324)
+        #define m_MMU_AUTO_GATING              BITS(1, 0)
+       #define v_MMU_AUTO_GATING(x)            BITS(x, 1, 0)
+
+
+enum _vop_dma_burst {
+       DMA_BURST_16 = 0,
+       DMA_BURST_8,
+       DMA_BURST_4
+};
+
+enum _vop_format_e {
+       VOP_FORMAT_ARGB888 = 0,
+       VOP_FORMAT_RGB888,
+       VOP_FORMAT_RGB565,
+       VOP_FORMAT_YCBCR420 = 4,
+       VOP_FORMAT_YCBCR422,
+       VOP_FORMAT_YCBCR444
+};
+
+enum _vop_tv_mode {
+       TV_NTSC,
+       TV_PAL,
+};
+
+enum _vop_csc_mode {
+       VOP_CSC_BT601 = 0,
+       VOP_CSC_JPEG,
+       VOP_CSC_BT709
+};
+
+enum _vop_hwc_size {
+       VOP_HWC_SIZE_32,
+       VOP_HWC_SIZE_64
+};
+
+#define CalScale(x, y)              ((((u32)(x - 1)) * 0x1000) / (y - 1))
+
+struct rk_lcdc_drvdata {
+     u8 soc_type;
+     u32 reserve;
+};
+
+struct lcdc_device {
+       int id;
+        u8 soc_type;
+       struct rk_lcdc_driver driver;
+       struct device *dev;
+       struct rk_screen *screen;
+
+       void __iomem *regs;
+       void *regsbak;                  /* back up reg */
+       u32 reg_phy_base;               /* physical basic address of lcdc register */
+       u32 len;                        /* physical map length of lcdc register */
+       spinlock_t  reg_lock;           /* one time only one process allowed to config the register */
+       
+       int __iomem *dsp_lut_addr_base;
+
+       int prop;                       /* used for primary or extended display device */
+       bool pre_init;
+       bool pwr18;                     /* if lcdc use 1.8v power supply */
+       bool clk_on;                    /* if aclk or hclk is closed ,acess to register is not allowed */
+       u8 atv_layer_cnt;               /* active layer counter,when atv_layer_cnt = 0,lcdc is disable*/
+
+       unsigned int            irq;
+
+       struct clk              *pd;    /* lcdc power domain */
+       struct clk              *hclk;  /* lcdc AHP clk */
+       struct clk              *dclk;  /* lcdc dclk */
+       struct clk              *aclk;  /* lcdc share memory frequency */
+        struct clk              *sclk;  /* scaler clk */
+       u32 pixclock;
+        u32 s_pixclock;
+
+       u32 standby;                    /* 1:standby,0:work */
+};
+
+static inline void lcdc_writel(struct lcdc_device *lcdc_dev, u32 offset, u32 v)
+{
+       u32 *_pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);   
+       *_pv = v;
+       writel_relaxed(v, lcdc_dev->regs + offset);     
+}
+
+static inline u32 lcdc_readl(struct lcdc_device *lcdc_dev, u32 offset)
+{
+       u32 v;
+       u32 *_pv = (u32*)lcdc_dev->regsbak;
+       _pv += (offset >> 2);
+       v = readl_relaxed(lcdc_dev->regs + offset);
+       *_pv = v;
+       return v;
+}
+
+static inline u32 lcdc_read_bit(struct lcdc_device *lcdc_dev, u32 offset,
+                                u32 msk) 
+{
+       u32 _v = readl_relaxed(lcdc_dev->regs + offset); 
+       _v &= msk;
+       return (_v? 1 : 0);   
+}
+
+static inline void  lcdc_set_bit(struct lcdc_device *lcdc_dev, u32 offset,
+                                 u32 msk) 
+{
+       u32* _pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);                           
+       (*_pv) |= msk;                          
+       writel_relaxed(*_pv, lcdc_dev->regs + offset); 
+} 
+
+static inline void lcdc_clr_bit(struct lcdc_device *lcdc_dev, u32 offset,
+                                u32 msk)
+{
+       u32* _pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);                           
+       (*_pv) &= (~msk);                               
+       writel_relaxed(*_pv, lcdc_dev->regs + offset); 
+} 
+
+static inline void  lcdc_msk_reg(struct lcdc_device *lcdc_dev, u32 offset,
+                                 u32 msk, u32 v)
+{
+       u32 *_pv = (u32*)lcdc_dev->regsbak;     
+       _pv += (offset >> 2);                   
+       (*_pv) &= (~msk);                               
+       (*_pv) |= v;                            
+       writel_relaxed(*_pv, lcdc_dev->regs + offset);  
+}
+
+static inline void lcdc_cfg_done(struct lcdc_device *lcdc_dev) 
+{
+       writel_relaxed(0x01, lcdc_dev->regs + REG_CFG_DONE); 
+       dsb();  
+} 
+
+#endif /* _RK312X_LCDC_H_ */
index 5f181a2056d74e9f736a2b864903d4873e762f5c..ebc9c0bd419b0926589627f8e19444e154088ddc 100755 (executable)
@@ -378,7 +378,7 @@ int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
                pr_err("parse display timing err\n");
                return -EINVAL;
        }
-       dt = display_timings_get(disp_timing, 0);
+       dt = display_timings_get(disp_timing, disp_timing->native_mode);
        rk_fb_video_mode_from_timing(dt, screen);
        return 0;
 
@@ -606,6 +606,22 @@ int rk_fb_set_prmry_screen_status(int status)
        return 0;
 }
 
+static int rk_fb_set_screen_scaler(struct rk_screen *screen, bool enable)
+{
+        struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+
+        if(unlikely(!dev_drv) || unlikely(!screen))
+                return -1;
+        if (!enable)
+                return 0;
+
+        rk_fb_set_prmry_screen_status(SCREEN_PREPARE_DDR_CHANGE);
+        if (dev_drv->ops->set_screen_scaler)
+                dev_drv->ops->set_screen_scaler(dev_drv, screen, enable);
+        rk_fb_set_prmry_screen_status(SCREEN_UNPREPARE_DDR_CHANGE);
+        return 0;
+}
+
 static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
 {
        struct rk_fb *inf = NULL;
@@ -640,13 +656,15 @@ u32 rk_fb_get_prmry_screen_pixclock(void)
 int rk_fb_poll_prmry_screen_vblank(void)
 {
        struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+
        if (likely(dev_drv)) {
                if (dev_drv->ops->poll_vblank)
                        return dev_drv->ops->poll_vblank(dev_drv);
                else
                        return RK_LF_STATUS_NC;
-       } else
+       } else {
                return RK_LF_STATUS_NC;
+       }
 }
 
 bool rk_fb_poll_wait_frame_complete(void)
@@ -684,6 +702,7 @@ static int rk_fb_open(struct fb_info *info, int user)
        int win_id;
 
        win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
+       dev_drv->win[win_id]->logicalstate++;
        /* if this win aready opened ,no need to reopen */
        if (dev_drv->win[win_id]->state)
                return 0;
@@ -697,6 +716,7 @@ static int get_extend_fb_id(struct fb_info *info)
        int fb_id = 0;
        char *id = info->fix.id;
        struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
+
        if (!strcmp(id, "fb0"))
                fb_id = 0;
        else if (!strcmp(id, "fb1"))
@@ -711,33 +731,37 @@ static int rk_fb_close(struct fb_info *info, int user)
        struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
        struct rk_lcdc_win *win = NULL;
        int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
+
        if (win_id >= 0) {
-               win = dev_drv->win[win_id];
-               info->fix.smem_start = win->reserved;
-
-               info->var.xres = dev_drv->screen0->mode.xres;
-               info->var.yres = dev_drv->screen0->mode.yres;
-               info->var.grayscale |=
-                   (info->var.xres << 8) + (info->var.yres << 20);
-               info->var.xres_virtual = info->var.xres;
-               info->var.yres_virtual = info->var.yres;
+               dev_drv->win[win_id]->logicalstate--;
+               if (!dev_drv->win[win_id]->logicalstate) {
+                       win = dev_drv->win[win_id];
+                       info->fix.smem_start = win->reserved;
+                       info->var.xres = dev_drv->screen0->mode.xres;
+                       info->var.yres = dev_drv->screen0->mode.yres;
+                       /*
+                       info->var.grayscale |=
+                           (info->var.xres << 8) + (info->var.yres << 20);
+                       */
+                       info->var.xres_virtual = info->var.xres;
+                       info->var.yres_virtual = info->var.yres;
 #if defined(CONFIG_LOGO_LINUX_BMP)
-               info->var.bits_per_pixel = 32;
+                       info->var.bits_per_pixel = 32;
 #else
-               info->var.bits_per_pixel = 16;
+                       info->var.bits_per_pixel = 16;
 #endif
-
-               info->fix.line_length =
-                   (info->var.xres_virtual) * (info->var.bits_per_pixel >> 3);
-               info->var.width = dev_drv->screen0->width;
-               info->var.height = dev_drv->screen0->height;
-               info->var.pixclock = dev_drv->pixclock;
-               info->var.left_margin = dev_drv->screen0->mode.left_margin;
-               info->var.right_margin = dev_drv->screen0->mode.right_margin;
-               info->var.upper_margin = dev_drv->screen0->mode.upper_margin;
-               info->var.lower_margin = dev_drv->screen0->mode.lower_margin;
-               info->var.vsync_len = dev_drv->screen0->mode.vsync_len;
-               info->var.hsync_len = dev_drv->screen0->mode.hsync_len;
+                       info->fix.line_length =
+                           (info->var.xres_virtual) * (info->var.bits_per_pixel >> 3);
+                       info->var.width = dev_drv->screen0->width;
+                       info->var.height = dev_drv->screen0->height;
+                       info->var.pixclock = dev_drv->pixclock;
+                       info->var.left_margin = dev_drv->screen0->mode.left_margin;
+                       info->var.right_margin = dev_drv->screen0->mode.right_margin;
+                       info->var.upper_margin = dev_drv->screen0->mode.upper_margin;
+                       info->var.lower_margin = dev_drv->screen0->mode.lower_margin;
+                       info->var.vsync_len = dev_drv->screen0->mode.vsync_len;
+                       info->var.hsync_len = dev_drv->screen0->mode.hsync_len;
+               }
        }
 
        return 0;
@@ -804,7 +828,6 @@ static void ipp_win_check(int *dst_w, int *dst_h, int *dst_vir_w,
                                *dst_vir_w = *dst_w;
                }
        } else {
-
                if ((*dst_w & align64) != 0)
                        *dst_w = (*dst_w + align64) & (~align64);
                if ((fmt > IPP_RGB_565) && ((*dst_h & 1) == 1))
@@ -812,7 +835,6 @@ static void ipp_win_check(int *dst_w, int *dst_h, int *dst_vir_w,
                if (*dst_vir_w < *dst_w)
                        *dst_vir_w = *dst_w;
        }
-
 }
 
 static void fb_copy_by_ipp(struct fb_info *dst_info,
@@ -845,7 +867,6 @@ static void fb_copy_by_ipp(struct fb_info *dst_info,
        default:
                rotation = IPP_ROT_270;
                break;
-
        }
 
        dst_w = dst_info->var.xres;
@@ -868,7 +889,6 @@ static void fb_copy_by_ipp(struct fb_info *dst_info,
        ipp_req.timeout = 100;
        ipp_req.flag = rotation;
        ipp_blit_sync(&ipp_req);
-
 }
 
 #endif
@@ -1257,10 +1277,10 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
 static int rk_fb_get_list_stat(struct rk_lcdc_driver *dev_drv)
 {
        int i, j;
+
        i = list_empty(&dev_drv->update_regs_list);
        j = list_empty(&saved_list);
        return i == j ? 0 : 1;
-
 }
 
 void rk_fd_fence_wait(struct rk_lcdc_driver *dev_drv, struct sync_fence *fence)
@@ -1432,7 +1452,6 @@ static void rk_fb_update_driver(struct rk_lcdc_win *win,
                win->z_order = -1;
        */
        }
-
 }
 
 static int rk_fb_update_hdmi_win(struct rk_lcdc_win *ext_win,
@@ -1763,7 +1782,6 @@ ext_win_exit:
        }
        g_last_win_num = regs->win_num;
        g_first_buf = 0;
-
 }
 
 static void rk_fb_update_regs_handler(struct kthread_work *work)
@@ -1902,8 +1920,8 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
        reg_win_data->data_format = fb_data_fmt;
        pixel_width = rk_fb_pixel_width(fb_data_fmt);
 
-       ppixel_a = ((fb_data_fmt == ARGB888)
-                   || (fb_data_fmt == ABGR888)) ? 1 : 0;
+       ppixel_a = ((fb_data_fmt == ARGB888) ||
+                   (fb_data_fmt == ABGR888)) ? 1 : 0;
        global_a = (win_par->g_alpha_val == 0) ? 0 : 1;
        reg_win_data->alpha_en = ppixel_a | global_a;
        reg_win_data->g_alpha_val = win_par->g_alpha_val;
@@ -1972,7 +1990,6 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
                                    xoffset * pixel_width / 8;
                        }
                }
-
        }
        switch (fb_data_fmt) {
        case YUV422:
@@ -2230,7 +2247,10 @@ int rk_get_real_fps(int before)
 EXPORT_SYMBOL(rk_get_real_fps);
 
 #endif
-
+#ifdef CONFIG_ROCKCHIP_IOMMU
+#define ION_MAX 10
+static struct ion_handle *ion_hanle[ION_MAX];
+#endif
 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,
                       unsigned long arg)
 {
@@ -2267,10 +2287,48 @@ static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,
        case RK_FBIOSET_YUV_ADDR:
                {
                        u32 yuv_phy[2];
+
                        if (copy_from_user(yuv_phy, argp, 8))
                                return -EFAULT;
-                       fix->smem_start = yuv_phy[0];
-                       fix->mmio_start = yuv_phy[1];
+                       #ifdef CONFIG_ROCKCHIP_IOMMU
+                       if (!dev_drv->iommu_enabled || !strcmp(info->fix.id, "fb0")) {
+                       #endif
+                               fix->smem_start = yuv_phy[0];
+                               fix->mmio_start = yuv_phy[1];
+                       #ifdef CONFIG_ROCKCHIP_IOMMU
+                       } else {
+                               int usr_fd, offset, tmp;
+                               struct ion_handle *hdl;
+                               ion_phys_addr_t phy_addr;
+                               size_t len;
+
+                               usr_fd = yuv_phy[0];
+                               offset = yuv_phy[1] - yuv_phy[0];
+
+                               if (!usr_fd) {
+                                       fix->smem_start = 0;
+                                       fix->mmio_start = 0;
+                                       break;
+                               }
+
+                               hdl = ion_import_dma_buf(rk_fb->ion_client, usr_fd);
+                               ion_map_iommu(dev_drv->dev, rk_fb->ion_client, hdl,
+                                               (unsigned long *)&phy_addr, (unsigned long *)&len);
+
+                               fix->smem_start = phy_addr;
+                               fix->mmio_start = phy_addr + offset;
+
+                               if (ion_hanle[ION_MAX - 1] != 0) {
+                                       ion_unmap_iommu(dev_drv->dev, rk_fb->ion_client, ion_hanle[ION_MAX - 1]);
+                                       ion_free(rk_fb->ion_client, ion_hanle[ION_MAX - 1]);
+                               }
+                               ion_hanle[0] = hdl;
+
+                               for (tmp = ION_MAX - 1; tmp > 0; tmp--)
+                                       ion_hanle[tmp] = ion_hanle[tmp - 1];
+                               ion_hanle[0] = 0;
+                       }
+                       #endif
                        break;
                }
        case RK_FBIOSET_ENABLE:
@@ -2406,8 +2464,8 @@ static int rk_fb_blank(int blank_mode, struct fb_info *info)
        if (win_id < 0)
                return -ENODEV;
 #if defined(CONFIG_RK_HDMI)
-       if ((rk_fb->disp_mode == ONE_DUAL)
-           && (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)) {
+       if ((rk_fb->disp_mode == ONE_DUAL) &&
+           (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)) {
                printk(KERN_INFO "hdmi is connect , not blank lcdc\n");
        } else
 #endif
@@ -2419,7 +2477,6 @@ static int rk_fb_blank(int blank_mode, struct fb_info *info)
 
 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-
        if ((0 == var->xres_virtual) || (0 == var->yres_virtual) ||
            (0 == var->xres) || (0 == var->yres) || (var->xres < 16) ||
            ((16 != var->bits_per_pixel) &&
@@ -2471,14 +2528,14 @@ static ssize_t rk_fb_read(struct fb_info *info, char __user *buf,
                win = dev_drv->win[win_id];
 
        /* only read the current frame buffer */
-       if (win->format == RGB565)
+       if (win->format == RGB565) {
                total_size = win->area[0].y_vir_stride * win->area[0].yact << 1;
-       else if (win->format == YUV420) {
+       else if (win->format == YUV420) {
                total_size =
                    (win->area[0].y_vir_stride * win->area[0].yact * 6);
-       } else
+       } else {
                total_size = win->area[0].y_vir_stride * win->area[0].yact << 2;
-
+       }
        if (p >= total_size)
                return 0;
 
@@ -2492,7 +2549,7 @@ static ssize_t rk_fb_read(struct fb_info *info, char __user *buf,
        if (!buffer)
                return -ENOMEM;
 
-       src = (u8 __iomem *) (info->screen_base + p + win->area[0].y_offset);
+       src = (u8 __iomem *)(info->screen_base + p + win->area[0].y_offset);
 
        while (count) {
                c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
@@ -2559,7 +2616,7 @@ static ssize_t rk_fb_write(struct fb_info *info, const char __user *buf,
        if (!buffer)
                return -ENOMEM;
 
-       dst = (u8 __iomem *) (info->screen_base + p + win->area[0].y_offset);
+       dst = (u8 __iomem *)(info->screen_base + p + win->area[0].y_offset);
 
        while (count) {
                c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
@@ -2582,7 +2639,6 @@ static ssize_t rk_fb_write(struct fb_info *info, const char __user *buf,
        kfree(buffer);
 
        return (cnt) ? cnt : err;
-
 }
 
 static int rk_fb_set_par(struct fb_info *info)
@@ -2597,6 +2653,7 @@ static int rk_fb_set_par(struct fb_info *info)
        struct rk_lcdc_win *extend_win = NULL;
        struct rk_lcdc_win *win = NULL;
        struct rk_screen *screen = dev_drv->cur_screen;
+       struct rk_screen screen_primary;
        int win_id = 0;
        u32 cblen = 0, crlen = 0;
        u16 xsize = 0, ysize = 0;       /* winx display window height/width --->LCDC_WINx_DSP_INFO */
@@ -2644,7 +2701,6 @@ static int rk_fb_set_par(struct fb_info *info)
 /*save winameter set by android*/
        if (rk_fb->disp_mode != DUAL) {
                if (screen->screen_id == 0) {
-
                        dev_drv->screen0->xsize = xsize;
                        dev_drv->screen0->ysize = ysize;
                        dev_drv->screen0->xpos = xpos;
@@ -2749,26 +2805,23 @@ static int rk_fb_set_par(struct fb_info *info)
                }
        }
 
+       rk_fb_get_prmry_screen(&screen_primary);
        win->format = fb_data_fmt;
        win->area[0].y_vir_stride = stride >> 2;
        win->area[0].uv_vir_stride = uv_stride >> 2;
-       win->area[0].xpos = xpos;
-       win->area[0].ypos = ypos;
-       win->area[0].xsize = xsize;
-       win->area[0].ysize = ysize;
-
-       win->area[0].smem_start = fix->smem_start;
-       win->area[0].cbr_start = fix->smem_start + stride * yvir;       /* fix->mmio_start; */
+       win->area[0].xpos = xpos*screen->mode.xres/screen_primary.mode.xres;
+       win->area[0].ypos = ypos*screen->mode.yres/screen_primary.mode.yres;
+       win->area[0].xsize = screen->mode.xres*xsize/screen_primary.mode.xres;
+       win->area[0].ysize = screen->mode.yres*ysize/screen_primary.mode.yres;
        win->area[0].xact = var->xres;  /* winx active window height,is a wint of vir */
        win->area[0].yact = var->yres;
        win->area[0].xvir = var->xres_virtual;  /* virtual resolution  stride --->LCDC_WINx_VIR */
        win->area[0].yvir = var->yres_virtual;
-       win->area[0].state = 1;
+
        win->area_num = 1;
-       win->state = 1;
        win->alpha_mode = 4;    /* AB_SRC_OVER; */
-       win->alpha_en = ((win->format == ARGB888)
-                        || (win->format == ABGR888)) ? 1 : 0;
+       win->alpha_en = ((win->format == ARGB888) ||
+                        (win->format == ABGR888)) ? 1 : 0;
        win->g_alpha_val = 0;
 
        if (rk_fb->disp_mode == DUAL) {
@@ -2801,8 +2854,8 @@ static int rk_fb_set_par(struct fb_info *info)
                                    win->area[0].y_vir_stride;
                                extend_win->area[0].uv_vir_stride =
                                    win->area[0].uv_vir_stride;
-                               if (win->area[0].xpos != 0
-                                   || win->area[0].ypos != 0) {
+                               if (win->area[0].xpos != 0 ||
+                                   win->area[0].ypos != 0) {
                                        extend_win->area[0].xsize =
                                            (extend_dev_drv->cur_screen->xsize * win->area[0].xsize) / screen->mode.xres;
                                        extend_win->area[0].ysize =
@@ -2981,7 +3034,7 @@ void rk_direct_fb_show(struct fb_info *fbi)
        rk_fb_pan_display(&fbi->var, fbi);
 }
 EXPORT_SYMBOL(rk_direct_fb_show);
-
+#if 0
 static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var,
                                  struct fb_var_screeninfo *hdmi_var)
 {
@@ -2996,15 +3049,15 @@ static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var,
        }
 
        return 0;
-
 }
-
+#endif
 int rk_fb_dpi_open(bool open)
 {
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
-       dev_drv->ops->dpi_open(dev_drv, open);
 
+       if (dev_drv->ops->dpi_open)
+               dev_drv->ops->dpi_open(dev_drv, open);
        return 0;
 }
 
@@ -3012,21 +3065,106 @@ int rk_fb_dpi_win_sel(int win_id)
 {
        struct rk_lcdc_driver *dev_drv = NULL;
        dev_drv = rk_get_prmry_lcdc_drv();
-       dev_drv->ops->dpi_win_sel(dev_drv, win_id);
 
+       if (dev_drv->ops->dpi_win_sel)
+               dev_drv->ops->dpi_win_sel(dev_drv, win_id);
        return 0;
 }
 
 int rk_fb_dpi_status(void)
 {
-       int ret;
+       int ret = 0;
        struct rk_lcdc_driver *dev_drv = NULL;
+
        dev_drv = rk_get_prmry_lcdc_drv();
-       ret = dev_drv->ops->dpi_status(dev_drv);
+       if (dev_drv->ops->dpi_status)
+               ret = dev_drv->ops->dpi_status(dev_drv);
 
        return ret;
 }
+#if 1
+/*
+ *function:this function will be called by display device, enable/disable lcdc
+ *screen: screen timing to be set to lcdc
+ *enable: 0 disable lcdc; 1 enable change lcdc timing; 2 just enable dclk
+ *lcdc_id: the lcdc id the display device attached ,0 or 1
+ */
+int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
+{
+       struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
+       struct fb_info *info = NULL;
+       struct rk_lcdc_driver *dev_drv = NULL;
+       char name[6];
+       int i, win_id, load_screen = 0;
+
+       if (screen == NULL)
+               return -ENODEV;
+
+       sprintf(name, "lcdc%d", lcdc_id);
+       for (i = 0; i < rk_fb->num_lcdc; i++) {
+               if (!strcmp(rk_fb->lcdc_dev_drv[i]->name, name)) {
+                       dev_drv = rk_fb->lcdc_dev_drv[i];
+                       break;
+               }
+       }
+       if (i == rk_fb->num_lcdc) {
+               printk(KERN_ERR "%s driver not found!", name);
+               return -ENODEV;
+       }
 
+       if (enable == 2 /*&& dev_drv->enable*/)
+               return 0;
+
+       if (!enable) {
+               /* if screen type is different, we do not disable lcdc. */
+               if (dev_drv->cur_screen->type != screen->type)
+                       return 0;
+
+               for (i = 0; i < dev_drv->lcdc_win_num; i++) {
+                       /* disable the layer which attached to this device */
+                       if (dev_drv->win[i] && dev_drv->win[i]->state)
+                               dev_drv->ops->open(dev_drv, i, 0);
+               }
+               return 0;
+       } else {
+               memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
+       }
+       for (i = 0; i < dev_drv->lcdc_win_num; i++) {
+               #ifdef DUAL_LCDC_MAP_TO_SAME_FB
+               info = rk_fb->fb[i];
+               dev_drv1 = (struct rk_lcdc_driver *)info->par;
+               if (dev_drv1 != dev_drv) {
+                       info->par = dev_drv;
+                       dev_drv->overscan = dev_drv1->overscan;
+                       dev_drv->vsync_info.active = dev_drv1->vsync_info.active;
+               }
+               memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
+               #else
+               info = rk_fb->fb[dev_drv->fb_index_base + i];
+               #endif
+               win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
+               if (dev_drv->win[win_id]) {
+                       #ifdef DUAL_LCDC_MAP_TO_SAME_FB
+                       if (dev_drv1 && dev_drv1->win[win_id]) {
+                               dev_drv->win[win_id]->logicalstate = dev_drv1->win[win_id]->logicalstate;
+                               memcpy(dev_drv->win[win_id]->area, dev_drv1->win[win_id]->area, RK_WIN_MAX_AREA * sizeof(struct rk_lcdc_win_area));
+                       }
+                       #endif
+                       if (dev_drv->win[win_id]->logicalstate) {
+                               dev_drv->ops->open(dev_drv, win_id, 1);
+                               if (!load_screen) {
+                                       dev_drv->ops->load_screen(dev_drv, 1);
+                                       load_screen = 1;
+                               }
+                               info->var.activate |= FB_ACTIVATE_FORCE;
+                               info->fbops->fb_set_par(info);
+                               info->fbops->fb_pan_display(&info->var, info);
+                       }
+               }
+       }
+       return 0;
+}
+#else
 /*
  * function:this function will be called by hdmi,when
  *             hdmi plug in/out
@@ -3054,8 +3192,10 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
 
        if (rk_fb->disp_mode != DUAL) {
                dev_drv = rk_fb->lcdc_dev_drv[0];
+                if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
+                        dev_drv->trsm_ops->disable();
+                rk_disp_pwr_disable(dev_drv);
        } else {
-
                for (i = 0; i < rk_fb->num_lcdc; i++) {
                        if (rk_fb->lcdc_dev_drv[i]->prop == EXTEND) {
                                dev_drv = rk_fb->lcdc_dev_drv[i];
@@ -3154,23 +3294,30 @@ int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
        hdmi_switch_complete = enable;
        info->fbops->fb_pan_display(hdmi_var, info);
 
-       /* info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0); */
        if (dev_drv->screen1) {
                if (dev_drv->screen0->sscreen_set) {
+                       /*
                        dev_drv->ops->blank(dev_drv, 0, FB_BLANK_NORMAL);
                        msleep(100);
+                       */
                        dev_drv->screen0->sscreen_set(dev_drv->screen0, enable);
+                        /*
                        dev_drv->ops->blank(dev_drv, 0, FB_BLANK_UNBLANK);
+                       */
                }
        }
-       /*
-       if (rk_fb->disp_mode != DUAL)
-               rk29_backlight_set(1);
-       */
-       return 0;
 
-}
+        info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0);
 
+       if (rk_fb->disp_mode != DUAL) {
+               /* rk29_backlight_set(1); */
+                rk_disp_pwr_enable(dev_drv);
+                if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
+                        dev_drv->trsm_ops->enable();
+       }
+       return 0;
+}
+#endif
 /*
  * function:this function current only called by hdmi for
  *     scale the display
@@ -3188,8 +3335,8 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
        u16 xpos, ypos;
        char name[6];
        int i = 0;
-       sprintf(name, "lcdc%d", lcdc_id);
 
+       sprintf(name, "lcdc%d", lcdc_id);
 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
        dev_drv = inf->lcdc_dev_drv[0];
 #else
@@ -3203,7 +3350,6 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
        if (i == inf->num_lcdc) {
                printk(KERN_ERR "%s driver not found!", name);
                return -ENODEV;
-
        }
 #endif
        if (inf->num_lcdc == 1)
@@ -3241,7 +3387,6 @@ int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
        /* info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0); */
        dev_drv->ops->cfg_done(dev_drv);
        return 0;
-
 }
 
 #if defined(CONFIG_ION_ROCKCHIP)
@@ -3254,6 +3399,7 @@ static int rk_fb_alloc_buffer_by_ion(struct fb_info *fbi,
        struct ion_handle *handle;
        ion_phys_addr_t phy_addr;
        size_t len;
+
        if (dev_drv->iommu_enabled)
                handle = ion_alloc(rk_fb->ion_client, (size_t) fb_mem_size, 0,
                                   ION_HEAP(ION_VMALLOC_HEAP_ID), 0);
@@ -3341,8 +3487,11 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
                        if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
                                return -ENOMEM;
 #else
-                       fb_mem_virt = dma_alloc_writecombine(fbi->dev,
-                                       fb_mem_size, &fb_mem_phys, GFP_KERNEL);
+                       fb_mem_virt =
+                               dma_alloc_writecombine(fbi->dev,
+                                                      fb_mem_size,
+                                                      &fb_mem_phys,
+                                                      GFP_KERNEL);
                        if (!fb_mem_virt) {
                                pr_err("%s: Failed to allocate framebuffer\n",
                                        __func__);
@@ -3382,7 +3531,6 @@ static int rk_release_fb_buffer(struct fb_info *fbi)
        iounmap(fbi->screen_base);
        release_mem_region(fbi->fix.smem_start, fbi->fix.smem_len);
        return 0;
-
 }
 #endif
 
@@ -3391,6 +3539,7 @@ static int init_lcdc_win(struct rk_lcdc_driver *dev_drv,
 {
        int i;
        int lcdc_win_num = dev_drv->lcdc_win_num;
+
        for (i = 0; i < lcdc_win_num; i++) {
                struct rk_lcdc_win *win = NULL;
                win = kzalloc(sizeof(struct rk_lcdc_win), GFP_KERNEL);
@@ -3415,6 +3564,7 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
        struct rk_screen *screen = devm_kzalloc(dev_drv->dev,
                                                sizeof(struct rk_screen),
                                                GFP_KERNEL);
+
        if (!screen) {
                dev_err(dev_drv->dev, "malloc screen for lcdc%d fail!",
                        dev_drv->id);
@@ -3435,10 +3585,11 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
        dev_drv->cur_screen = screen;
        /* devie use one lcdc + rk61x scaler for dual display */
        if (rk_fb->disp_mode == ONE_DUAL) {
-               struct rk_screen *screen1 = devm_kzalloc(dev_drv->dev,
-                                                        sizeof(struct rk_screen),
-                                                        GFP_KERNEL);
-               if (screen1) {
+               struct rk_screen *screen1 =
+                               devm_kzalloc(dev_drv->dev,
+                                            sizeof(struct rk_screen),
+                                            GFP_KERNEL);
+               if (!screen1) {
                        dev_err(dev_drv->dev, "malloc screen1 for lcdc%d fail!",
                                dev_drv->id);
                        return -ENOMEM;
@@ -3446,6 +3597,7 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
                screen1->screen_id = 1;
                screen1->lcdc_id = 1;
                dev_drv->screen1 = screen1;
+                dev_drv->screen0->sscreen_set = rk_fb_set_screen_scaler;
        }
        sprintf(dev_drv->name, "lcdc%d", dev_drv->id);
        init_lcdc_win(dev_drv, def_win);
@@ -3454,12 +3606,17 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
        mutex_init(&dev_drv->fb_win_id_mutex);
        dev_drv->ops->fb_win_remap(dev_drv, FB_DEFAULT_ORDER);
        dev_drv->first_frame = 1;
+       dev_drv->overscan.left = 100;
+       dev_drv->overscan.top = 100;
+       dev_drv->overscan.right = 100;
+       dev_drv->overscan.bottom = 100;
        rk_disp_pwr_ctr_parse_dt(dev_drv);
        if (dev_drv->prop == PRMRY) {
-               dev_drv->ops->set_dsp_cabc(dev_drv, dev_drv->cabc_mode);
+               if (dev_drv->ops->set_dsp_cabc)
+                       dev_drv->ops->set_dsp_cabc(dev_drv, dev_drv->cabc_mode);
                rk_fb_set_prmry_screen(screen);
-               rk_fb_get_prmry_screen(screen);
        }
+       rk_fb_get_prmry_screen(screen);
        dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
 
        return 0;
@@ -3488,7 +3645,6 @@ static void fb_show_bmp_logo(struct fb_info *info, int rotate)
        for (i = 0; i < Needheight; i++)
                memcpy(dst + info->var.xres * i * 4,
                       src + bmp_logo->width * i * 4, Needwidth * 4);
-
 }
 #endif
 
@@ -3499,11 +3655,11 @@ static void fb_show_bmp_logo(struct fb_info *info, int rotate)
 bool is_prmry_rk_lcdc_registered(void)
 {
        struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
+
        if (rk_fb->lcdc_dev_drv[0])
                return true;
        else
                return false;
-
 }
 
 int rk_fb_register(struct rk_lcdc_driver *dev_drv,
@@ -3512,9 +3668,11 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
        struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
        struct fb_info *fbi;
        int i = 0, ret = 0, index = 0;
+/*
 #if defined(CONFIG_ROCKCHIP_IOMMU)
        struct device *mmu_dev = NULL;
 #endif
+*/
        if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
                return -ENXIO;
 
@@ -3611,7 +3769,6 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                            sw_sync_timeline_create("fb-timeline");
                        dev_drv->timeline_max = 1;
                }
-
        }
 
        /* show logo for primary display device */
@@ -3619,6 +3776,7 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
        if (dev_drv->prop == PRMRY) {
                struct fb_info *main_fbi = rk_fb->fb[0];
                main_fbi->fbops->fb_open(main_fbi, 1);
+/*
 #if defined(CONFIG_ROCKCHIP_IOMMU)
                if (dev_drv->iommu_enabled) {
                        mmu_dev =
@@ -3633,12 +3791,13 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                                        "failed to get rockchip iommu device\n");
                }
 #endif
+*/
                rk_fb_alloc_buffer(main_fbi, 0);        /* only alloc memory for main fb */
                if (support_uboot_display()) {
                        if (dev_drv->iommu_enabled) {
                                rk_fb_copy_from_loader(main_fbi);
                                dev_drv->ops->direct_set_addr(dev_drv, 0,
-                                                             main_fbi->fix.smem_start);
+                                       main_fbi->fix.smem_start);
                        }
                        return 0;
                }
@@ -3659,18 +3818,16 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
 #if !defined(CONFIG_ROCKCHIP_IOMMU)
                struct fb_info *extend_fbi = rk_fb->fb[rk_fb->num_fb >> 1];
                int extend_fb_id = get_extend_fb_id(extend_fbi);
+
                rk_fb_alloc_buffer(extend_fbi, extend_fb_id);
 #endif
        }
 #endif
-
        return 0;
-
 }
 
 int rk_fb_unregister(struct rk_lcdc_driver *dev_drv)
 {
-
        struct rk_fb *fb_inf = platform_get_drvdata(fb_pdev);
        struct fb_info *fbi;
        int fb_index_base = dev_drv->fb_index_base;
@@ -3724,7 +3881,7 @@ static int rk_fb_probe(struct platform_device *pdev)
        }
 
        if (!of_property_read_u32(np, "rockchip,uboot-logo-on", &uboot_logo_on))
-               printk("uboot-logo-on:%d\n", uboot_logo_on);
+               printk(KERN_DEBUG "uboot-logo-on:%d\n", uboot_logo_on);
 
        dev_set_name(&pdev->dev, "rockchip-fb");
 #if defined(CONFIG_ION_ROCKCHIP)
@@ -3745,6 +3902,7 @@ static int rk_fb_probe(struct platform_device *pdev)
 static int rk_fb_remove(struct platform_device *pdev)
 {
        struct rk_fb *rk_fb = platform_get_drvdata(pdev);
+
        kfree(rk_fb);
        platform_set_drvdata(pdev, NULL);
        return 0;
@@ -3754,12 +3912,11 @@ static void rk_fb_shutdown(struct platform_device *pdev)
 {
        struct rk_fb *rk_fb = platform_get_drvdata(pdev);
        int i;
+
        for (i = 0; i < rk_fb->num_lcdc; i++) {
                if (!rk_fb->lcdc_dev_drv[i])
                        continue;
-
        }
-
 }
 
 static const struct of_device_id rkfb_dt_ids[] = {
index af48af11bef0d0189757b5226a69ccdcd8875b6a..9065168330bee470a8f7d12bfc89a3941542b9d1 100755 (executable)
@@ -40,9 +40,12 @@ static ssize_t show_screen_info(struct device *dev,
        struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
        struct rk_screen *screen = dev_drv->screen0;
        int fps;
-       u32 x = (screen->mode.left_margin + screen->mode.right_margin + screen->mode.xres + screen->mode.hsync_len);
-       u32 y = (screen->mode.upper_margin + screen->mode.lower_margin + screen->mode.yres + screen->mode.vsync_len);
-       u64 ft = (u64)x * y * (dev_drv->pixclock);      // one frame time ,(pico seconds)
+       u32 x = screen->mode.left_margin + screen->mode.right_margin +
+               screen->mode.xres + screen->mode.hsync_len;
+       u32 y = screen->mode.upper_margin + screen->mode.lower_margin +
+               screen->mode.yres + screen->mode.vsync_len;
+       u64 ft = (u64)x * y * (dev_drv->pixclock);
+
        fps = div64_u64(1000000000000llu, ft);
        return snprintf(buf, PAGE_SIZE, "xres:%d\nyres:%d\nfps:%d\n",
                        screen->mode.xres, screen->mode.yres, fps);
@@ -54,6 +57,7 @@ static ssize_t show_disp_info(struct device *dev,
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
        int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
+
        if (dev_drv->ops->get_disp_info)
                return dev_drv->ops->get_disp_info(dev_drv, buf, win_id);
 
@@ -64,6 +68,7 @@ static ssize_t show_phys(struct device *dev,
                         struct device_attribute *attr, char *buf)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
+
        return snprintf(buf, PAGE_SIZE, "0x%lx-----0x%x\n",
                        fbi->fix.smem_start, fbi->fix.smem_len);
 }
@@ -85,8 +90,8 @@ static ssize_t show_fb_state(struct device *dev,
            (struct rk_lcdc_driver *)fbi->par;
        int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
        int state = dev_drv->ops->get_win_state(dev_drv, win_id);
-       return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
 
+       return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
 }
 
 static ssize_t show_dual_mode(struct device *dev,
@@ -94,9 +99,9 @@ static ssize_t show_dual_mode(struct device *dev,
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
-       int mode= rk_fb->disp_mode; 
-       return snprintf(buf, PAGE_SIZE, "%d\n", mode);
+       int mode = rk_fb->disp_mode;
 
+       return snprintf(buf, PAGE_SIZE, "%d\n", mode);
 }
 
 static ssize_t set_fb_state(struct device *dev, struct device_attribute *attr,
@@ -108,11 +113,16 @@ static ssize_t set_fb_state(struct device *dev, struct device_attribute *attr,
        int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
        int state;
        int ret;
+
        ret = kstrtoint(buf, 0, &state);
-       if (ret) {
+       if (ret)
                return ret;
-       }
        dev_drv->ops->open(dev_drv, win_id, state);
+       if (state) {
+               dev_drv->ops->set_par(dev_drv, win_id);
+               dev_drv->ops->pan_display(dev_drv, win_id);
+               dev_drv->ops->cfg_done(dev_drv);
+       }
        return count;
 }
 
@@ -124,14 +134,13 @@ static ssize_t show_overlay(struct device *dev,
            (struct rk_lcdc_driver *)fbi->par;
        int ovl;
        ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
-       if (ovl < 0) {
+
+       if (ovl < 0)
                return ovl;
-       }
 
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        ovl ? "win0 on the top of win1" :
                        "win1 on the top of win0");
-
 }
 
 static ssize_t set_overlay(struct device *dev, struct device_attribute *attr,
@@ -142,14 +151,14 @@ static ssize_t set_overlay(struct device *dev, struct device_attribute *attr,
            (struct rk_lcdc_driver *)fbi->par;
        int ovl;
        int ret;
+
        ret = kstrtoint(buf, 0, &ovl);
-       if (ret) {
+       if (ret)
                return ret;
-       }
+
        ret = dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
-       if (ret < 0) {
+       if (ret < 0)
                return ret;
-       }
 
        return count;
 }
@@ -161,13 +170,12 @@ static ssize_t show_fps(struct device *dev,
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int fps;
+
        fps = dev_drv->ops->fps_mgr(dev_drv, 0, 0);
-       if (fps < 0) {
+       if (fps < 0)
                return fps;
-       }
 
        return snprintf(buf, PAGE_SIZE, "fps:%d\n", fps);
-
 }
 
 static ssize_t set_fps(struct device *dev, struct device_attribute *attr,
@@ -178,14 +186,13 @@ static ssize_t set_fps(struct device *dev, struct device_attribute *attr,
            (struct rk_lcdc_driver *)fbi->par;
        int fps;
        int ret;
+
        ret = kstrtoint(buf, 0, &fps);
-       if (ret) {
+       if (ret)
                return ret;
-       }
        ret = dev_drv->ops->fps_mgr(dev_drv, fps, 1);
-       if (ret < 0) {
+       if (ret < 0)
                return ret;
-       }
 
        return count;
 }
@@ -206,7 +213,6 @@ static ssize_t show_fb_win_map(struct device *dev,
        mutex_unlock(&dev_drv->fb_win_id_mutex);
 
        return ret;
-
 }
 
 static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
@@ -217,13 +223,14 @@ static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
            (struct rk_lcdc_driver *)fbi->par;
        int order;
        int ret;
+
        ret = kstrtoint(buf, 0, &order);
-       if ((order != FB0_WIN2_FB1_WIN1_FB2_WIN0)
-           && (order != FB0_WIN1_FB1_WIN2_FB2_WIN0)
-           && (order != FB0_WIN2_FB1_WIN0_FB2_WIN1)
-           && (order != FB0_WIN0_FB1_WIN2_FB2_WIN1)
-           && (order != FB0_WIN0_FB1_WIN1_FB2_WIN2)
-           && (order != FB0_WIN1_FB1_WIN0_FB2_WIN2)) {
+       if ((order != FB0_WIN2_FB1_WIN1_FB2_WIN0) &&
+           (order != FB0_WIN1_FB1_WIN2_FB2_WIN0) &&
+           (order != FB0_WIN2_FB1_WIN0_FB2_WIN1) &&
+           (order != FB0_WIN0_FB1_WIN2_FB2_WIN1) &&
+           (order != FB0_WIN0_FB1_WIN1_FB2_WIN2) &&
+           (order != FB0_WIN1_FB1_WIN0_FB2_WIN2)) {
                printk(KERN_ERR "un supported map\n"
                       "you can use the following order:\n" "201:\n"
                       "fb0-win1\n" "fb1-win0\n" "fb2-win2\n" "210:\n"
@@ -238,13 +245,11 @@ static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
        }
 
        return count;
-
 }
 
 static ssize_t show_dsp_lut(struct device *dev,
                            struct device_attribute *attr, char *buf)
 {
-
        return 0;
 }
 
@@ -262,11 +267,12 @@ static ssize_t set_dsp_lut(struct device *dev, struct device_attribute *attr,
 
        for (i = 0; i < 256; i++) {
                temp = i;
-               dsp_lut[i] = temp + (temp << 8) + (temp << 16); //init by default value
+               /*init by default value*/
+               dsp_lut[i] = temp + (temp << 8) + (temp << 16);
        }
-       //printk("count:%d\n>>%s\n\n",count,start);
+       /*printk("count:%d\n>>%s\n\n",count,start);*/
        for (i = 0; i < 256; i++) {
-               space_max = 10; //max space number 10;
+               space_max = 10; /*max space number 10*/
                temp = simple_strtoul(start, NULL, 10);
                dsp_lut[i] = temp;
                do {
@@ -289,10 +295,10 @@ static ssize_t set_dsp_lut(struct device *dev, struct device_attribute *attr,
        dev_drv->ops->set_dsp_lut(dev_drv, dsp_lut);
 
        return count;
-
 }
+
 static ssize_t show_dsp_cabc(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+                            struct device_attribute *attr, char *buf)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv =
@@ -304,101 +310,140 @@ static ssize_t show_dsp_cabc(struct device *dev,
 }
 
 static ssize_t set_dsp_cabc(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
+                           const char *buf, size_t count)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
-       int ret,mode=0;
-       
+       int ret, mode = 0;
+
        ret = kstrtoint(buf, 0, &mode);
        if (ret)
                return ret;
 
        ret = dev_drv->ops->set_dsp_cabc(dev_drv, mode);
-       if(ret < 0)
+       if (ret < 0)
                return ret;
-       
-       return count;
 
-       
+       return count;
 }
+
 static ssize_t show_dsp_bcsh(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+                            struct device_attribute *attr, char *buf)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int brightness, contrast, sat_con, sin_hue, cos_hue;
 
-       brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, BRIGHTNESS);
-       contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
-       sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
-       sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_SIN);
-       cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv,H_COS);
-
-       snprintf(buf, PAGE_SIZE, "brightness:%4d,contrast:%4d,sat_con:%4d,"
-                                "sin_hue:%4d,cos_hue:%4d\n",
-                                brightness, contrast,sat_con,sin_hue,cos_hue);
-       return 0;
+       if (dev_drv->ops->get_dsp_bcsh_bcs) {
+               brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv,
+                                                           BRIGHTNESS);
+               contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
+               sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
+       }
+       if (dev_drv->ops->get_dsp_bcsh_hue) {
+               sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_SIN);
+               cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_COS);
+       }
+       return snprintf(buf, PAGE_SIZE,
+                       "brightness:%4d,contrast:%4d,sat_con:%4d,"
+                       "sin_hue:%4d,cos_hue:%4d\n",
+                       brightness, contrast, sat_con, sin_hue, cos_hue);
 }
 
 static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
+                           const char *buf, size_t count)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        int brightness, contrast, sat_con, ret, sin_hue, cos_hue;
+
        if (!strncmp(buf, "open", 4)) {
-               ret = dev_drv->ops->open_bcsh(dev_drv, 1);
+               if (dev_drv->ops->open_bcsh)
+                       ret = dev_drv->ops->open_bcsh(dev_drv, 1);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "close", 5)) {
-               ret = dev_drv->ops->open_bcsh(dev_drv, 0);
+               if (dev_drv->ops->open_bcsh)
+                       ret = dev_drv->ops->open_bcsh(dev_drv, 0);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "brightness", 10)) {
                sscanf(buf, "brightness %d", &brightness);
                if (unlikely(brightness > 255)) {
-                       dev_err(fbi->dev,"brightness should be [0:255],now=%d\n\n",brightness);
+                       dev_err(fbi->dev,
+                               "brightness should be [0:255],now=%d\n\n",
+                               brightness);
                        brightness = 255;
                }
-               ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, BRIGHTNESS,brightness);
+               if (dev_drv->ops->set_dsp_bcsh_bcs)
+                       ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
+                                                            BRIGHTNESS,
+                                                            brightness);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "contrast", 8)) {
                sscanf(buf, "contrast %d", &contrast);
                if (unlikely(contrast > 510)) {
-                       dev_err(fbi->dev,"contrast should be [0:510],now=%d\n",contrast);
+                       dev_err(fbi->dev,
+                               "contrast should be [0:510],now=%d\n",
+                               contrast);
                        contrast = 510;
                }
-               ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, CONTRAST,contrast);
+               if (dev_drv->ops->set_dsp_bcsh_bcs)
+                       ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
+                                                            CONTRAST,
+                                                            contrast);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "sat_con", 7)) {
                sscanf(buf, "sat_con %d", &sat_con);
                if (unlikely(sat_con > 1015)) {
-                       dev_err(fbi->dev,"sat_con should be [0:1015],now=%d\n",sat_con);
+                       dev_err(fbi->dev,
+                               "sat_con should be [0:1015],now=%d\n",
+                               sat_con);
                        sat_con = 1015;
                }
-               ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv, SAT_CON,sat_con);
+               if (dev_drv->ops->set_dsp_bcsh_bcs)
+                       ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
+                                                            SAT_CON,
+                                                            sat_con);
+               else
+                       ret = -1;
        } else if (!strncmp(buf, "hue", 3)) {
-               sscanf(buf, "hue %d %d", &sin_hue,&cos_hue);
+               sscanf(buf, "hue %d %d", &sin_hue, &cos_hue);
                if (unlikely(sin_hue > 511 || cos_hue > 511)) {
-                       dev_err(fbi->dev,"sin_hue=%d,cos_hue=%d\n",sin_hue,cos_hue);
+                       dev_err(fbi->dev, "sin_hue=%d,cos_hue=%d\n",
+                               sin_hue, cos_hue);
                }
-               ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,sin_hue,cos_hue);
+               if (dev_drv->ops->set_dsp_bcsh_hue)
+                       ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,
+                                                            sin_hue,
+                                                            cos_hue);
+               else
+                       ret = -1;
        } else {
                printk("format error\n");
        }
 
-       if(ret < 0)
+       if (ret < 0)
                return ret;
-       
+
        return count;
 }
 
 static ssize_t show_scale(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+                         struct device_attribute *attr, char *buf)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv =
            (struct rk_lcdc_driver *)fbi->par;
        struct rk_screen *screen = dev_drv->cur_screen;
-       return snprintf(buf, PAGE_SIZE, "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
+
+       return snprintf(buf, PAGE_SIZE,
+               "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
                (screen->overscan.left + screen->overscan.right)/2,
                (screen->overscan.top + screen->overscan.bottom)/2,
                screen->overscan.left, screen->overscan.top,
@@ -406,7 +451,7 @@ static ssize_t show_scale(struct device *dev,
 }
 
 static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
+                        const char *buf, size_t count)
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct rk_lcdc_driver *dev_drv =
@@ -415,7 +460,8 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
        u32 left, top, right, bottom;
 
        if (!strncmp(buf, "overscan", 8)) {
-               sscanf(buf, "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
+               sscanf(buf,
+                      "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
                if (left > 0 && left <= 100)
                        screen->overscan.left = left;
                if (top > 0 && top <= 100)
@@ -461,9 +507,10 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
                        screen->overscan.bottom = left;
                }
        }
-//     printk("%d %d %d %d\n", dev_drv->overscan.left, dev_drv->overscan.top, dev_drv->overscan.right, dev_drv->overscan.bottom);
-       dev_drv->ops->load_screen(dev_drv, 1);
-       dev_drv->ops->cfg_done(dev_drv);
+
+       if (dev_drv->ops->set_overscan)
+               dev_drv->ops->set_overscan(dev_drv, &screen->overscan);
+
        return count;
 }
 
@@ -485,8 +532,8 @@ static struct device_attribute rkfb_attrs[] = {
 
 int rkfb_create_sysfs(struct fb_info *fbi)
 {
-       int r;
-       int t;
+       int r, t;
+
        for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++) {
                r = device_create_file(fbi->dev, &rkfb_attrs[t]);
                if (r) {
index 7558517f9e6d939adfb97e120e32b1f16530516b..295a8cbff33cb2935aa02c3c48a512771f30045c 100755 (executable)
@@ -16,6 +16,10 @@ config RK32_LVDS
        bool "RK32 lvds transmitter support"
        depends on RK_TRSM
 
+config RK31XX_LVDS
+        bool "RK312x/RK3190 lvds transmitter support"
+        depends on RK_TRSM
+
 config RK610_LVDS
        bool "RK610(Jetta) lvds transmitter support"
        depends on MFD_RK610 && RK_TRSM 
index 0c5f6e57bd27e2d6ee08695ab6ee36a56f49e3bf..a1bfe0078f8b49ea2f99bcae89b3189e2eefc095 100755 (executable)
@@ -6,6 +6,7 @@ obj-$(CONFIG_RK3026_LVDS)       += rk3026_lvds.o
 obj-$(CONFIG_RK610_LVDS)       += rk610_lcd.o
 obj-$(CONFIG_RK616_LVDS)        += rk616_lvds.o
 obj-$(CONFIG_RK32_LVDS)         += rk32_lvds.o
+obj-$(CONFIG_RK31XX_LVDS)      += rk31xx_lvds.o
 obj-$(CONFIG_DP_ANX6345)        += dp_anx6345.o
 obj-$(CONFIG_DP501)            += dp501.o
 obj-$(CONFIG_RK32_DP)          += rk32_dp.o rk32_dp_reg.o
diff --git a/drivers/video/rockchip/transmitter/rk31xx_lvds.c b/drivers/video/rockchip/transmitter/rk31xx_lvds.c
new file mode 100755 (executable)
index 0000000..13f64df
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * drivers/video/rockchip/transmitter/rk31xx_lvds.c
+ *
+ * Copyright (C) 2014 ROCKCHIP, Inc.
+ * Author: zhuangwenlong<zwl@rock-chips.com>
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/rk_fb.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+#include "rk31xx_lvds.h"
+
+
+#define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
+#define grf_writel(v,offset)                                    \
+        do {                                                    \
+                writel_relaxed(v, RK_GRF_VIRT + offset);        \
+                dsb();                                          \
+        } while (0)
+
+
+static struct rk_lvds_device *rk31xx_lvds;
+
+static int rk31xx_lvds_clk_init(struct rk_lvds_device *lvds)
+{
+        lvds->pclk = devm_clk_get(lvds->dev, "pclk_lvds");
+       if (IS_ERR(lvds->pclk)) {
+               dev_err(lvds->dev, "get clk failed\n");
+               return PTR_ERR(lvds->pclk);
+       }
+
+       return 0;       
+}
+
+static int rk31xx_lvds_clk_enable(struct rk_lvds_device *lvds)
+{
+       if (!lvds->clk_on) {
+               clk_prepare_enable(lvds->pclk);
+               lvds->clk_on = true;
+       }
+
+       return 0;
+}
+
+static int rk31xx_lvds_clk_disable(struct rk_lvds_device *lvds)
+{
+       if (lvds->clk_on) {
+               clk_disable_unprepare(lvds->pclk);
+               lvds->clk_on = false;
+       }
+
+       return 0;
+}
+
+static int rk31xx_lvds_pwr_on(void)
+{
+        struct rk_lvds_device *lvds = rk31xx_lvds;
+
+        if (lvds->screen.type == SCREEN_LVDS) {
+                /* power up lvds pll and ldo */
+               lvds_msk_reg(lvds, MIPIPHY_REG1,
+                            m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN,
+                            v_SYNC_RST(0) | v_LDO_PWR_DOWN(0) | v_PLL_PWR_DOWN(0));
+
+               /* enable lvds */
+               lvds_msk_reg(lvds, MIPIPHY_REGE3,
+                            m_MIPI_EN | m_LVDS_EN | m_TTL_EN,
+                            v_MIPI_EN(0) | v_LVDS_EN(1) | v_TTL_EN(0));
+        } else {
+                lvds_msk_reg(lvds, MIPIPHY_REGE3,
+                            m_MIPI_EN | m_LVDS_EN | m_TTL_EN,
+                            v_MIPI_EN(0) | v_LVDS_EN(0) | v_TTL_EN(1));
+        }
+        return 0;
+}
+
+static int rk31xx_lvds_pwr_off(void)
+{
+        struct rk_lvds_device *lvds = rk31xx_lvds;
+
+       /* power down lvds pll and bandgap */
+       lvds_msk_reg(lvds, MIPIPHY_REG1,
+                    m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN,
+                    v_SYNC_RST(1) | v_LDO_PWR_DOWN(1) | v_PLL_PWR_DOWN(1));
+
+       /* disable lvds */
+       lvds_msk_reg(lvds, MIPIPHY_REGE3, m_LVDS_EN | m_TTL_EN,
+                    v_LVDS_EN(0) | v_TTL_EN(0));
+        return 0;
+}
+
+static int rk31xx_lvds_disable(void)
+{
+       struct rk_lvds_device *lvds = rk31xx_lvds;
+
+        if (unlikely(!lvds) || !lvds->sys_state)
+                return 0;
+
+       grf_writel(v_LVDSMODE_EN(0) | v_MIPIPHY_TTL_EN(0), RK312X_GRF_LVDS_CON0);
+
+        rk31xx_lvds_pwr_off();
+       rk31xx_lvds_clk_disable(lvds);
+        if (lvds->screen.type == SCREEN_RGB)
+                pinctrl_select_state(lvds->dev->pins->p,
+                                     lvds->dev->pins->sleep_state);
+        lvds->sys_state = false;
+       return 0;
+}
+
+static void rk31xx_output_lvds(struct rk_lvds_device *lvds,
+                               struct rk_screen *screen)
+{
+       u32 val = 0;
+
+        /* if LVDS transmitter source from VOP, vop_dclk need get invert
+         * set iomux in dts pinctrl
+         */
+       val = 0;
+       val |= v_LVDSMODE_EN(1) | v_MIPIPHY_TTL_EN(0);  /* enable lvds mode */
+       val |= v_LVDS_DATA_SEL(LVDS_DATA_FROM_LCDC);    /* config data source */
+       val |= v_LVDS_OUTPUT_FORMAT(screen->lvds_format); /* config lvds_format */
+       val |= v_LVDS_MSBSEL(LVDS_MSB_D7);      /* LSB receive mode */
+        val |= v_MIPIPHY_LANE0_EN(1) | v_MIPIDPI_FORCEX_EN(1);
+       grf_writel(val, RK312X_GRF_LVDS_CON0);
+
+        /* enable lvds lane */
+        val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) |
+                v_LANECLK_EN(1) | v_PLL_PWR_OFF(0);
+       lvds_writel(lvds, MIPIPHY_REGEB, val);
+
+        /* set pll prediv and fbdiv */
+       lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0));
+       lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28));
+
+        lvds_writel(lvds, MIPIPHY_REGE8, 0xfc);
+
+        /* set lvds mode and reset phy config */
+       lvds_msk_reg(lvds, MIPIPHY_REGE0,
+                     m_MSB_SEL | m_DIG_INTER_RST,
+                     v_MSB_SEL(1) | v_DIG_INTER_RST(1));
+
+        lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1));
+
+#if 0
+        lvds_writel(lvds, MIPIPHY_REGE2, 0xa0); /* timing */
+        lvds_writel(lvds, MIPIPHY_REGE7, 0xfc); /* phase */
+#endif
+
+        rk31xx_lvds_pwr_on();
+
+}
+
+static void rk31xx_output_lvttl(struct rk_lvds_device *lvds,
+                                struct rk_screen *screen)
+{
+        u32 val = 0;
+        //struct pinctrl_state *lcdc_state;
+
+        /* iomux to lcdc */
+#if 1 /* defined(CONFIG_RK_FPGA) */
+        grf_writel(0xffff5555, RK312X_GRF_GPIO2B_IOMUX);
+        grf_writel(0x00ff0055, RK312X_GRF_GPIO2C_IOMUX);
+        grf_writel(0x77771111, 0x00e8); /* RK312X_GRF_GPIO2C_IOMUX2 */
+        grf_writel(0x700c1004, RK312X_GRF_GPIO2D_IOMUX);
+#else
+        lcdc_state = pinctrl_lookup_state(lvds->dev->pins->p, "lcdc");
+        pinctrl_select_state(lvds->dev->pins->p, lcdc_state);
+#endif
+
+       val |= v_LVDSMODE_EN(0) | v_MIPIPHY_TTL_EN(1);  /* enable lvds mode */
+       val |= v_LVDS_DATA_SEL(LVDS_DATA_FROM_LCDC);    /* config data source */
+       grf_writel(val, RK312X_GRF_LVDS_CON0);
+
+        /* set pll prediv and fbdiv */
+       lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(1) | v_FBDIV_MSB(0));
+       lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(7));
+
+        /* set ttl mode and reset phy config */
+        val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) |
+                v_MSB_SEL(1) | v_DIG_INTER_RST(1);
+       lvds_writel(lvds, MIPIPHY_REGE0, val);
+
+        lvds_writel(lvds, MIPIPHY_REGE1, 0x92);
+
+        /* enable ttl */
+       rk31xx_lvds_pwr_on();
+               
+}
+
+static int rk31xx_lvds_en(void)
+{
+       struct rk_lvds_device *lvds = rk31xx_lvds;
+       struct rk_screen *screen;
+
+        if (unlikely(!lvds) || lvds->sys_state)
+                return 0;
+
+        screen = &lvds->screen;
+       rk_fb_get_prmry_screen(screen);
+
+       /* enable clk */
+       rk31xx_lvds_clk_enable(lvds);
+
+       switch (screen->type) {
+        case SCREEN_LVDS:
+               rk31xx_output_lvds(lvds, screen);
+                break;
+        case SCREEN_RGB:
+               rk31xx_output_lvttl(lvds, screen);
+                break;
+        default:
+                printk("unsupport screen type\n");
+                break;
+       }
+
+        lvds->sys_state = true;
+       return 0;
+}
+
+static struct rk_fb_trsm_ops trsm_lvds_ops = {
+       .enable = rk31xx_lvds_en,
+       .disable = rk31xx_lvds_disable,
+       .dsp_pwr_on = rk31xx_lvds_pwr_on,
+       .dsp_pwr_off = rk31xx_lvds_pwr_off,
+};
+
+static int rk31xx_lvds_probe(struct platform_device *pdev)
+{
+        struct rk_lvds_device *lvds;
+       struct resource *res;
+       struct device_node *np = pdev->dev.of_node;
+        int ret = 0;
+
+       if (!np) {
+               dev_err(&pdev->dev, "Don't find lvds device tree node.\n");
+               return -EINVAL;
+       }       
+
+        lvds = devm_kzalloc(&pdev->dev, sizeof(struct rk_lvds_device), GFP_KERNEL);
+       if (!lvds) {
+               dev_err(&pdev->dev, "kzalloc rk31xx lvds failed\n");
+               return -ENOMEM;
+       }
+       lvds->dev = &pdev->dev;
+
+       rk_fb_get_prmry_screen(&lvds->screen);
+        if ((lvds->screen.type != SCREEN_RGB) && 
+               (lvds->screen.type != SCREEN_LVDS)) {
+               dev_err(&pdev->dev, "screen is not lvds/rgb!\n");
+               ret = -EINVAL;
+                goto err_screen_type;
+       }
+
+       platform_set_drvdata(pdev, lvds);
+       dev_set_name(lvds->dev, "rk31xx-lvds");
+
+        /* lvds regs on MIPIPHY_REG */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       lvds->regbase = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(lvds->regbase)) {
+               dev_err(&pdev->dev, "ioremap reg failed\n");
+               return PTR_ERR(lvds->regbase);
+       }
+
+       ret = rk31xx_lvds_clk_init(lvds);
+       if(ret < 0)
+               goto err_clk_init;
+
+        if (support_uboot_display())
+               rk31xx_lvds_clk_enable(lvds);
+
+       rk31xx_lvds = lvds;
+       rk_fb_trsm_ops_register(&trsm_lvds_ops, SCREEN_LVDS);
+       dev_info(&pdev->dev, "rk31xx lvds driver probe success\n");
+
+       return 0;
+
+err_clk_init:
+err_screen_type:
+        devm_kfree(&pdev->dev, lvds);
+        lvds = NULL;
+        return ret;    
+}
+
+static int rk31xx_lvds_remove(struct platform_device *pdev)
+{      
+       return 0;
+}
+
+static void rk31xx_lvds_shutdown(struct platform_device *pdev)
+{
+       return;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk31xx_lvds_dt_ids[] = {
+       {.compatible = "rockchip,rk31xx-lvds",},
+        {}
+};
+#endif
+
+static struct platform_driver rk31xx_lvds_driver = {
+       .driver         = {
+               .name   = "rk31xx-lvds",
+               .owner  = THIS_MODULE,
+#if defined(CONFIG_OF)
+               .of_match_table = of_match_ptr(rk31xx_lvds_dt_ids),
+#endif
+       },
+       .probe          = rk31xx_lvds_probe,
+       .remove         = rk31xx_lvds_remove,
+       .shutdown       = rk31xx_lvds_shutdown,
+};
+
+static int __init rk31xx_lvds_init(void)
+{
+       return platform_driver_register(&rk31xx_lvds_driver);
+}
+
+static void __exit rk31xx_lvds_exit(void)
+{
+       platform_driver_unregister(&rk31xx_lvds_driver);
+}
+
+fs_initcall(rk31xx_lvds_init);
+module_exit(rk31xx_lvds_exit);
+
diff --git a/drivers/video/rockchip/transmitter/rk31xx_lvds.h b/drivers/video/rockchip/transmitter/rk31xx_lvds.h
new file mode 100755 (executable)
index 0000000..818901a
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef _RK31XX_LVDS_H_
+#define _RK31XX_LVDS_H_
+
+#include <linux/rk_screen.h>
+
+
+#define BITS(x, bit)            ((x) << (bit))
+#define BITS_MASK(x, mask, bit)  BITS((x) & (mask), bit)
+#define BITS_EN(mask, bit)       BITS(mask, bit + 16)
+
+/* RK312X_GRF_LVDS_CON0 */
+#define v_LVDS_DATA_SEL(x)      (BITS_MASK(x, 1, 0) | BITS_EN(1, 0))
+#define v_LVDS_OUTPUT_FORMAT(x) (BITS_MASK(x, 3, 1) | BITS_EN(3, 1))
+#define v_LVDS_MSBSEL(x)        (BITS_MASK(x, 1, 3) | BITS_EN(1, 3))
+#define v_LVDSMODE_EN(x)        (BITS_MASK(x, 1, 6) | BITS_EN(1, 6))
+#define v_MIPIPHY_TTL_EN(x)     (BITS_MASK(x, 1, 7) | BITS_EN(1, 7))
+#define v_MIPIPHY_LANE0_EN(x)   (BITS_MASK(x, 1, 8) | BITS_EN(1, 8))
+#define v_MIPIDPI_FORCEX_EN(x)  (BITS_MASK(x, 1, 9) | BITS_EN(1, 9))
+
+enum {
+        LVDS_DATA_FROM_LCDC = 0,
+        LVDS_DATA_FORM_EBC,
+};
+
+enum {
+        LVDS_MSB_D0 = 0,
+        LVDS_MSB_D7,
+};
+
+#define MIPIPHY_REG1            0x0004
+#define m_SYNC_RST              BITS(1, 0)
+#define m_LDO_PWR_DOWN          BITS(1, 1)
+#define m_PLL_PWR_DOWN          BITS(1, 2)
+#define v_SYNC_RST(x)           BITS_MASK(x, 1, 0)
+#define v_LDO_PWR_DOWN(x)       BITS_MASK(x, 1, 1)
+#define v_PLL_PWR_DOWN(x)       BITS_MASK(x, 1, 2)
+
+#define MIPIPHY_REG3           0x000c
+#define m_PREDIV                BITS(0x1f, 0)
+#define m_FBDIV_MSB             BITS(1, 5)
+#define v_PREDIV(x)             BITS_MASK(x, 0x1f, 0)
+#define v_FBDIV_MSB(x)          BITS_MASK(x, 1, 5)
+
+#define MIPIPHY_REG4           0x0010
+#define v_FBDIV_LSB(x)          BITS_MASK(x, 0xff, 0)
+
+#define MIPIPHY_REGE0          0x0380
+#define m_MSB_SEL               BITS(1, 0)
+#define m_DIG_INTER_RST         BITS(1, 2)
+#define m_LVDS_MODE_EN          BITS(1, 5)
+#define m_TTL_MODE_EN           BITS(1, 6)
+#define m_MIPI_MODE_EN          BITS(1, 7)
+#define v_MSB_SEL(x)            BITS_MASK(x, 1, 0)
+#define v_DIG_INTER_RST(x)      BITS_MASK(x, 1, 2)
+#define v_LVDS_MODE_EN(x)       BITS_MASK(x, 1, 5)
+#define v_TTL_MODE_EN(x)        BITS_MASK(x, 1, 6)
+#define v_MIPI_MODE_EN(x)       BITS_MASK(x, 1, 7)
+
+#define MIPIPHY_REGE1           0x0384
+#define m_DIG_INTER_EN          BITS(1, 7)
+#define v_DIG_INTER_EN(x)       BITS_MASK(x, 1, 7)
+
+#define MIPIPHY_REGE3           0x038c
+#define m_MIPI_EN               BITS(1, 0)
+#define m_LVDS_EN               BITS(1, 1)
+#define m_TTL_EN                BITS(1, 2)
+#define v_MIPI_EN(x)            BITS_MASK(x, 1, 0)
+#define v_LVDS_EN(x)            BITS_MASK(x, 1, 1)
+#define v_TTL_EN(x)             BITS_MASK(x, 1, 2)
+
+#define MIPIPHY_REGE8           0x03a0
+
+#define MIPIPHY_REGEB           0x03ac
+#define v_PLL_PWR_OFF(x)        BITS_MASK(x, 1, 2)
+#define v_LANECLK_EN(x)         BITS_MASK(x, 1, 3)
+#define v_LANE3_EN(x)           BITS_MASK(x, 1, 4)
+#define v_LANE2_EN(x)           BITS_MASK(x, 1, 5)
+#define v_LANE1_EN(x)           BITS_MASK(x, 1, 6)
+#define v_LANE0_EN(x)           BITS_MASK(x, 1, 7)
+
+
+struct rk_lvds_device {
+       struct device           *dev;
+       void __iomem            *regbase;
+       struct clk              *pclk;  /*phb clk*/
+       struct rk_screen        screen;
+       bool                    clk_on;
+        bool                    sys_state;
+};
+
+static inline int lvds_writel(struct rk_lvds_device *lvds, u32 offset, u32 val)
+{
+       writel_relaxed(val, lvds->regbase + offset);
+       return 0;
+}
+
+static inline int lvds_msk_reg(struct rk_lvds_device *lvds, u32 offset,
+                              u32 msk, u32 val)
+{
+       u32 temp;
+
+       temp = readl_relaxed(lvds->regbase + offset) & (0xFF - (msk));
+       writel_relaxed(temp | ((val) & (msk)), lvds->regbase + offset);
+       return 0;
+}
+
+static inline u32 lvds_readl(struct rk_lvds_device *lvds, u32 offset)
+{
+       return readl_relaxed(lvds->regbase + offset);
+}
+
+#endif
+
index e7c5e172075fc8552b392619a536972a9bb6d4a1..392bbf42dc4d77b623e7ae21cb172329a11f3127 100755 (executable)
@@ -61,6 +61,8 @@
 #include "mipi_dsi.h"
 #include "rk32_mipi_dsi.h"
 #include <linux/rockchip/iomap.h>
+#include <linux/rockchip/cpu.h>
+
 #endif
 #ifdef CONFIG_RK32_MIPI_DSI
 #define        MIPI_DBG(x...)  //printk(KERN_INFO x)
@@ -149,13 +151,27 @@ int rk32_mipi_dsi_clk_disable(struct dsi *dsi)
 #endif
 static int rk32_dsi_read_reg(struct dsi *dsi, u16 reg, u32 *pval)
 {
-       *pval = __raw_readl(dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET));
+       if(cpu_is_rk3288())
+               *pval = __raw_readl(dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET));
+       else if(cpu_is_rk312x()){
+               if(reg >= MIPI_DSI_HOST_OFFSET)
+                       *pval = __raw_readl(dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET));
+               else if(reg >= MIPI_DSI_PHY_OFFSET)
+                       *pval = __raw_readl(dsi->phy.membase + (reg - MIPI_DSI_PHY_OFFSET));
+       }
        return 0;
 }
 
 static int rk32_dsi_write_reg(struct dsi *dsi, u16 reg, u32 *pval)
 {
-       __raw_writel(*pval, dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET));
+       if(cpu_is_rk3288())
+               __raw_writel(*pval, dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET));
+       else if(cpu_is_rk312x()){
+               if(reg >= MIPI_DSI_HOST_OFFSET)
+                       __raw_writel(*pval, dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET));
+               else if(reg >= MIPI_DSI_PHY_OFFSET)
+                       __raw_writel(*pval, dsi->phy.membase + (reg - MIPI_DSI_PHY_OFFSET));    
+       }
        return 0;
 }
 
@@ -275,6 +291,61 @@ static int rk32_phy_power_up(struct dsi *dsi)
        
        return 0;
 }
+static void rk312x_mipi_dsi_set_hs_clk(struct dsi *dsi) 
+{
+       rk32_dsi_set_bits(dsi, dsi->phy.prediv, reg_prediv);
+       rk32_dsi_set_bits(dsi, dsi->phy.fbdiv & 0xff, reg_fbdiv);
+       rk32_dsi_set_bits(dsi, (dsi->phy.fbdiv >> 8) & 0x01, reg_fbdiv_8);
+}
+
+static int rk312x_phy_power_up(struct dsi *dsi)
+{
+       //enable ref clock
+       #ifdef CONFIG_RK_3288_DSI_UBOOT
+       rk32_mipi_dsi_clk_enable(dsi);
+       #else
+       rk312x_mipi_dsi_set_hs_clk(dsi);
+       clk_prepare_enable(dsi->phy.refclk); 
+       clk_prepare_enable(dsi->dsi_pclk);
+       //clk_prepare_enable(dsi->dsi_pd);
+       #endif
+       udelay(10);
+    
+       rk32_dsi_set_bits(dsi, 0xe4, DPHY_REGISTER1);
+       switch(dsi->host.lane) {
+               case 4:
+                       rk32_dsi_set_bits(dsi, 1, lane_en_3);
+               case 3:
+                       rk32_dsi_set_bits(dsi, 1, lane_en_2);
+               case 2:
+                       rk32_dsi_set_bits(dsi, 1, lane_en_1);
+               case 1:
+                       rk32_dsi_set_bits(dsi, 1, lane_en_0);
+                       rk32_dsi_set_bits(dsi, 1, lane_en_ck);
+                       break;
+               default:
+                       break;  
+       }
+    
+       rk32_dsi_set_bits(dsi, 0xe0, DPHY_REGISTER1);
+       udelay(10);
+    
+       rk32_dsi_set_bits(dsi, 0x1e, DPHY_REGISTER20);
+       rk32_dsi_set_bits(dsi, 0x1f, DPHY_REGISTER20);
+
+       rk32_dsi_set_bits(dsi, 1, phy_enableclk);
+       
+       return 0;
+}
+
+static int rk_phy_power_up(struct dsi *dsi) 
+{
+       if(cpu_is_rk3288())
+               rk32_phy_power_up(dsi);
+       else if(cpu_is_rk312x())
+               rk312x_phy_power_up(dsi);
+       return 0;
+}
 
 static int rk32_phy_power_down(struct dsi *dsi)
 {
@@ -289,6 +360,31 @@ static int rk32_phy_power_down(struct dsi *dsi)
     return 0;
 }
 
+static int rk312x_phy_power_down(struct dsi *dsi)
+{
+    #ifdef CONFIG_RK_3288_DSI_UBOOT
+    rk32_mipi_dsi_clk_disable(dsi);
+    #else
+    
+    rk32_dsi_set_bits(dsi, 0x01, DPHY_REGISTER0);
+    rk32_dsi_set_bits(dsi, 0xe3, DPHY_REGISTER1);
+    
+    clk_disable_unprepare(dsi->phy.refclk); 
+    clk_disable_unprepare(dsi->dsi_pclk);
+   // clk_disable_unprepare(dsi->dsi_pd);
+    #endif
+    return 0;
+}
+
+static int rk_phy_power_down(struct dsi *dsi) 
+{
+       if(cpu_is_rk3288())
+               rk32_phy_power_down(dsi);
+       else if(cpu_is_rk312x())
+               rk312x_phy_power_down(dsi);
+       return 0;
+}
+
 static int rk32_phy_init(struct dsi *dsi)
 {
        u32 val = 0 , ddr_clk = 0, fbdiv = 0, prediv = 0;
@@ -445,6 +541,253 @@ static int rk32_phy_init(struct dsi *dsi)
 
     return 0;
 }
+static int rk321x_mipi_dsi_phy_set_gotp(struct dsi *dsi, u32 offset, int n) 
+{
+       u32 val = 0, temp = 0, Tlpx = 0;
+       u32 ddr_clk = dsi->phy.ddr_clk;
+       u32 Ttxbyte_clk = dsi->phy.Ttxbyte_clk;
+       u32 Tsys_clk = dsi->phy.Tsys_clk;
+       u32 Ttxclkesc = dsi->phy.Ttxclkesc;
+       
+       switch(offset) {
+               case DPHY_CLOCK_OFFSET:
+                       MIPI_DBG("******set DPHY_CLOCK_OFFSET gotp******\n");
+                       break;
+               case DPHY_LANE0_OFFSET:
+                       MIPI_DBG("******set DPHY_LANE0_OFFSET gotp******\n");
+                       break;
+               case DPHY_LANE1_OFFSET:
+                       MIPI_DBG("******set DPHY_LANE1_OFFSET gotp******\n");
+                       break;
+               case DPHY_LANE2_OFFSET:
+                       MIPI_DBG("******set DPHY_LANE2_OFFSET gotp******\n");
+                       break;
+               case DPHY_LANE3_OFFSET:
+                       MIPI_DBG("******set DPHY_LANE3_OFFSET gotp******\n");
+                       break;
+               default:
+                       break;                                  
+       }
+       
+       if(ddr_clk < 110 * MHz)
+               val = 0;
+       else if(ddr_clk < 150 * MHz)
+               val = 1;
+       else if(ddr_clk < 200 * MHz)
+               val = 2;
+       else if(ddr_clk < 250 * MHz)
+               val = 3;
+       else if(ddr_clk < 300 * MHz)
+               val = 4;
+       else if(ddr_clk < 400 * MHz)
+               val = 5;                
+       else if(ddr_clk < 500 * MHz)
+               val = 6;                
+       else if(ddr_clk < 600 * MHz)
+               val = 7;                
+       else if(ddr_clk < 700 * MHz)
+               val = 8;
+       else if(ddr_clk < 800 * MHz)
+               val = 9;                
+       else if(ddr_clk <= 1000 * MHz)
+               val = 10;       
+       rk32_dsi_set_bits(dsi, val, reg_ths_settle + offset);
+       
+       if(ddr_clk < 110 * MHz)
+               val = 0x20;
+       else if(ddr_clk < 150 * MHz)
+               val = 0x06;
+       else if(ddr_clk < 200 * MHz)
+               val = 0x18;
+       else if(ddr_clk < 250 * MHz)
+               val = 0x05;
+       else if(ddr_clk < 300 * MHz)
+               val = 0x51;
+       else if(ddr_clk < 400 * MHz)
+               val = 0x64;             
+       else if(ddr_clk < 500 * MHz)
+               val = 0x59;             
+       else if(ddr_clk < 600 * MHz)
+               val = 0x6a;             
+       else if(ddr_clk < 700 * MHz)
+               val = 0x3e;
+       else if(ddr_clk < 800 * MHz)
+               val = 0x21;
+       else if(ddr_clk <= 1000 * MHz)
+               val = 0x09;
+       rk32_dsi_set_bits(dsi, val, reg_hs_ths_prepare + offset);
+
+       if(offset != DPHY_CLOCK_OFFSET) {
+       
+               if(ddr_clk < 110 * MHz)
+                       val = 2;
+               else if(ddr_clk < 150 * MHz)
+                       val = 3;
+               else if(ddr_clk < 200 * MHz)
+                       val = 4;
+               else if(ddr_clk < 250 * MHz)
+                       val = 5;
+               else if(ddr_clk < 300 * MHz)
+                       val = 6;
+               else if(ddr_clk < 400 * MHz)
+                       val = 7;                
+               else if(ddr_clk < 500 * MHz)
+                       val = 7;                
+               else if(ddr_clk < 600 * MHz)
+                       val = 8;                
+               else if(ddr_clk < 700 * MHz)
+                       val = 8;
+               else if(ddr_clk < 800 * MHz)
+                       val = 9;                
+               else if(ddr_clk <= 1000 * MHz)
+                       val = 9;        
+       } else {
+       
+               if(ddr_clk < 110 * MHz)
+                       val = 0x16;
+               else if(ddr_clk < 150 * MHz)
+                       val = 0x16;
+               else if(ddr_clk < 200 * MHz)
+                       val = 0x17;
+               else if(ddr_clk < 250 * MHz)
+                       val = 0x17;
+               else if(ddr_clk < 300 * MHz)
+                       val = 0x18;
+               else if(ddr_clk < 400 * MHz)
+                       val = 0x19;             
+               else if(ddr_clk < 500 * MHz)
+                       val = 0x1b;             
+               else if(ddr_clk < 600 * MHz)
+                       val = 0x1d;             
+               else if(ddr_clk < 700 * MHz)
+                       val = 0x1e;
+               else if(ddr_clk < 800 * MHz)
+                       val = 0x1f;             
+               else if(ddr_clk <= 1000 * MHz)
+                       val = 0x20;     
+       }                               
+       rk32_dsi_set_bits(dsi, val, reg_hs_the_zero + offset);
+       
+       if(ddr_clk < 110 * MHz)
+               val = 0x22;
+       else if(ddr_clk < 150 * MHz)
+               val = 0x45;
+       else if(ddr_clk < 200 * MHz)
+               val = 0x0b;
+       else if(ddr_clk < 250 * MHz)
+               val = 0x16;
+       else if(ddr_clk < 300 * MHz)
+               val = 0x2c;
+       else if(ddr_clk < 400 * MHz)
+               val = 0x33;             
+       else if(ddr_clk < 500 * MHz)
+               val = 0x4e;             
+       else if(ddr_clk < 600 * MHz)
+               val = 0x3a;             
+       else if(ddr_clk < 700 * MHz)
+               val = 0x6a;
+       else if(ddr_clk < 800 * MHz)
+               val = 0x29;             
+       else if(ddr_clk <= 1000 * MHz)
+               val = 0x21;   //0x27
+
+       rk32_dsi_set_bits(dsi, val, reg_hs_ths_trail + offset);
+       val = 120000 / Ttxbyte_clk + 1;
+       MIPI_DBG("reg_hs_ths_exit: %d, %d\n", val, val*Ttxbyte_clk/1000);
+       rk32_dsi_set_bits(dsi, val, reg_hs_ths_exit + offset);
+       
+       if(offset == DPHY_CLOCK_OFFSET) {
+               val = (60000 + 52*dsi->phy.UI) / Ttxbyte_clk + 1;
+               MIPI_DBG("reg_hs_tclk_post: %d, %d\n", val, val*Ttxbyte_clk/1000);
+               rk32_dsi_set_bits(dsi, val, reg_hs_tclk_post + offset);
+               val = 10*dsi->phy.UI / Ttxbyte_clk + 1;
+               MIPI_DBG("reg_hs_tclk_pre: %d, %d\n", val, val*Ttxbyte_clk/1000);       
+               rk32_dsi_set_bits(dsi, val, reg_hs_tclk_pre + offset);
+       }
+
+       val = 1010000000 / Tsys_clk + 1;
+       MIPI_DBG("reg_hs_twakup: %d, %d\n", val, val*Tsys_clk/1000);
+       if(val > 0x3ff) {
+               val = 0x2ff;
+               MIPI_DBG("val is too large, 0x3ff is the largest\n");   
+       }
+       temp = (val >> 8) & 0x03;
+       val &= 0xff;    
+       rk32_dsi_set_bits(dsi, temp, reg_hs_twakup_h + offset); 
+       rk32_dsi_set_bits(dsi, val, reg_hs_twakup_l + offset);
+       
+       if(Ttxclkesc > 50000) {
+               val = 2*Ttxclkesc;
+               MIPI_DBG("Ttxclkesc:%d\n", Ttxclkesc);
+       }
+       val = val / Ttxbyte_clk;
+       Tlpx = val*Ttxbyte_clk;
+       MIPI_DBG("reg_hs_tlpx: %d, %d\n", val, Tlpx);
+       val -= 2;
+       rk32_dsi_set_bits(dsi, val, reg_hs_tlpx + offset);
+       
+       Tlpx = 2*Ttxclkesc;
+       val = 4*Tlpx / Ttxclkesc;
+       MIPI_DBG("reg_hs_tta_go: %d, %d\n", val, val*Ttxclkesc);
+       rk32_dsi_set_bits(dsi, val, reg_hs_tta_go + offset);
+       val = 3 * Tlpx / 2 / Ttxclkesc;
+       MIPI_DBG("reg_hs_tta_sure: %d, %d\n", val, val*Ttxclkesc);      
+       rk32_dsi_set_bits(dsi, val, reg_hs_tta_sure + offset);
+       val = 5 * Tlpx / Ttxclkesc;
+       MIPI_DBG("reg_hs_tta_wait: %d, %d\n", val, val*Ttxclkesc);
+       rk32_dsi_set_bits(dsi, val, reg_hs_tta_wait + offset);
+       return 0;
+}
+
+static int rk312x_phy_init(struct dsi *dsi, int n)
+{
+       //DPHY init
+       rk32_dsi_set_bits(dsi, 0x11, DSI_DPHY_BITS(0x06<<2, 32, 0));
+       rk32_dsi_set_bits(dsi, 0x11, DSI_DPHY_BITS(0x07<<2, 32, 0));
+       rk32_dsi_set_bits(dsi, 0xcc, DSI_DPHY_BITS(0x09<<2, 32, 0));
+#if 0
+       dsi_set_bits(0x4e, DSI_DPHY_BITS(0x08<<2, 32, 0));
+       dsi_set_bits(0x84, DSI_DPHY_BITS(0x0a<<2, 32, 0));
+#endif
+
+       /*reg1[4] 0: enable a function of "pll phase for serial data being captured 
+                                inside analog part" 
+                 1: disable it 
+         we disable it here because reg5[6:4] is not compatible with the HS speed.             
+       */
+
+       if(dsi->phy.ddr_clk >= 800*MHz) {
+               rk32_dsi_set_bits(dsi, 0x30, DSI_DPHY_BITS(0x05<<2, 32, 0));
+       } else {
+               rk32_dsi_set_bits(dsi, 1, reg_da_ppfc);
+       }
+
+       switch(dsi->host.lane) {
+               case 4:
+                       rk321x_mipi_dsi_phy_set_gotp(dsi, DPHY_LANE3_OFFSET, n);
+               case 3:
+                       rk321x_mipi_dsi_phy_set_gotp(dsi, DPHY_LANE2_OFFSET, n);
+               case 2:
+                       rk321x_mipi_dsi_phy_set_gotp(dsi, DPHY_LANE1_OFFSET, n);
+               case 1:
+                       rk321x_mipi_dsi_phy_set_gotp(dsi, DPHY_LANE0_OFFSET, n);
+                       rk321x_mipi_dsi_phy_set_gotp(dsi, DPHY_CLOCK_OFFSET, n);
+                       break;
+               default:
+                       break;  
+       }       
+       return 0;
+
+}
+
+static int rk_phy_init(struct dsi *dsi)
+{
+       if(cpu_is_rk3288())
+               rk32_phy_init(dsi);
+       else if(cpu_is_rk312x())
+               rk312x_phy_init(dsi, 4);
+       return 0;
+}
 
 static int rk32_mipi_dsi_host_power_up(struct dsi *dsi) 
 {
@@ -475,6 +818,9 @@ static int rk32_mipi_dsi_host_power_up(struct dsi *dsi)
        return ret;
 }
 
+
+
+
 static int rk32_mipi_dsi_host_power_down(struct dsi *dsi) 
 {      
        rk32_mipi_dsi_enable_video_mode(dsi, 0);
@@ -483,6 +829,8 @@ static int rk32_mipi_dsi_host_power_down(struct dsi *dsi)
        return 0;
 }
 
+
+
 static int rk32_mipi_dsi_host_init(struct dsi *dsi) 
 {
        u32 val = 0, bytes_px = 0;
@@ -707,9 +1055,9 @@ static int rk_mipi_dsi_init(void *arg, u32 n)
                                dsi->phy.Ttxbyte_clk);
        MIPI_DBG("txclkesc:%d, Ttxclkesc:%d\n", dsi->phy.txclkesc, dsi->phy.Ttxclkesc);
        
-       rk32_phy_power_up(dsi);
+       rk_phy_power_up(dsi);
        rk32_mipi_dsi_host_power_up(dsi);
-       rk32_phy_init(dsi);
+       rk_phy_init(dsi);
        rk32_mipi_dsi_host_init(dsi);
        
        return 0;
@@ -978,7 +1326,7 @@ static int rk32_mipi_dsi_power_down(void *arg)
                return -1;
 
        rk32_mipi_dsi_host_power_down(dsi);
-       rk32_phy_power_down(dsi);
+       rk_phy_power_down(dsi);
 
        MIPI_TRACE("%s:%d\n", __func__, __LINE__);
        return 0;
@@ -1393,6 +1741,10 @@ static void rk32_init_phy_mode(int lcdc_id)
        int val0 = 0, val1 = 0;
 
        MIPI_DBG("rk32_init_phy_mode----------lcdc_id=%d\n",lcdc_id);
+       
+       if(cpu_is_rk312x())
+               return;
+       
        //D-PHY mode select
        if( rk_mipi_get_dsi_num() ==1 ){
        
@@ -1418,6 +1770,7 @@ static void rk32_init_phy_mode(int lcdc_id)
                writel_relaxed(val1, RK_GRF_VIRT + RK3288_GRF_SOC_CON14);
        }
 }
+
 #ifdef CONFIG_RK_3288_DSI_UBOOT
 #ifdef CONFIG_OF_LIBFDT
 int rk_dsi_host_parse_dt(const void *blob, struct dsi *dsi)
@@ -1595,7 +1948,7 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
        struct mipi_dsi_ops *ops;
        struct rk_screen *screen;
        struct mipi_dsi_screen *dsi_screen;
-       struct resource *res_host;
+       struct resource *res_host, *res_phy;
  
        dsi = devm_kzalloc(&pdev->dev, sizeof(struct dsi), GFP_KERNEL);
        if(!dsi) {
@@ -1603,11 +1956,26 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       res_host = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       dsi->host.membase = devm_request_and_ioremap(&pdev->dev, res_host);
-       if (!dsi->host.membase){
-               dev_err(&pdev->dev, "get resource mipi host membase fail!\n");
-               return -ENOMEM;
+       if(cpu_is_rk3288()){
+               res_host = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               dsi->host.membase = devm_request_and_ioremap(&pdev->dev, res_host);
+               if (!dsi->host.membase){
+                       dev_err(&pdev->dev, "get resource mipi host membase fail!\n");
+                       return -ENOMEM;
+               }
+       }else if(cpu_is_rk312x()){
+               res_host = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mipi_dsi_host");
+               dsi->host.membase = devm_request_and_ioremap(&pdev->dev, res_host);
+               if (!dsi->host.membase){
+                       dev_err(&pdev->dev, "get resource mipi host membase fail!\n");
+                       return -ENOMEM;
+               }
+               res_phy = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mipi_dsi_phy");
+               dsi->phy.membase = devm_request_and_ioremap(&pdev->dev, res_host);
+               if (!dsi->phy.membase){
+                       dev_err(&pdev->dev, "get resource mipi phy membase fail!\n");
+                       return -ENOMEM;
+               }
        }
        
        dsi->phy.refclk  = devm_clk_get(&pdev->dev, "clk_mipi_24m"); 
@@ -1615,19 +1983,19 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "get clk_mipi_24m clock fail\n");
                return PTR_ERR(dsi->phy.refclk);
        }
-
+       
        dsi->dsi_pclk = devm_clk_get(&pdev->dev, "pclk_mipi_dsi");
        if (unlikely(IS_ERR(dsi->dsi_pclk))) {
                dev_err(&pdev->dev, "get pclk_mipi_dsi clock fail\n");
                return PTR_ERR(dsi->dsi_pclk);
        }
-
-       dsi->dsi_pd = devm_clk_get(&pdev->dev, "pd_mipi_dsi");
-       if (unlikely(IS_ERR(dsi->dsi_pd))) {
-               dev_err(&pdev->dev, "get pd_mipi_dsi clock fail\n");
-               return PTR_ERR(dsi->dsi_pd);
+       if(cpu_is_rk3288()){
+               dsi->dsi_pd = devm_clk_get(&pdev->dev, "pd_mipi_dsi");
+               if (unlikely(IS_ERR(dsi->dsi_pd))) {
+                       dev_err(&pdev->dev, "get pd_mipi_dsi clock fail\n");
+                       return PTR_ERR(dsi->dsi_pd);
+               }
        }
-
        dsi->host.irq = platform_get_irq(pdev, 0);
        if (dsi->host.irq < 0) {
                dev_err(&pdev->dev, "no irq resource?\n");
@@ -1728,7 +2096,8 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
     if(support_uboot_display()){
            clk_prepare_enable(dsi->phy.refclk); 
            clk_prepare_enable(dsi->dsi_pclk);
-           clk_prepare_enable(dsi->dsi_pd);
+           if(cpu_is_rk3288())
+                   clk_prepare_enable(dsi->dsi_pd);
            udelay(10);
     }
        dev_info(&pdev->dev,"rk mipi_dsi probe success!\n");
index f75d83335f4cbd4bb14bbe74c98848c0d2a61ad7..32a47161b9d304b5b9023761e25faa69db58d97a 100755 (executable)
@@ -15,6 +15,9 @@ drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
 #else
 #include <linux/rockchip/grf.h>
 #endif
+#define MIPI_DSI_PHY_OFFSET            0x0C00
+#define MIPI_DSI_PHY_SIZE              0x34c
+
 #define MIPI_DSI_HOST_OFFSET   0x1000
 
 //function bits definition    register addr | bits | offest
@@ -23,6 +26,8 @@ drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
 #define BITS_OFFSET(a)         (a)
 #define DSI_HOST_BITS(addr, bits, bit_offset)  (REG_ADDR((addr)+MIPI_DSI_HOST_OFFSET) \
                | REG_BITS(bits) | BITS_OFFSET(bit_offset))  
+#define DSI_DPHY_BITS(addr, bits, bit_offset)  (REG_ADDR((addr)+MIPI_DSI_PHY_OFFSET) \
+               | REG_BITS(bits) | BITS_OFFSET(bit_offset))             
 
 //DWC_DSI_VERSION_0x3133302A
 #define VERSION                                        DSI_HOST_BITS(0x000, 32, 0)
@@ -156,6 +161,51 @@ drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
 #define code_hstxdatalanepreparestatetime   0x71
 #define code_hstxdatalanehszerostatetime    0x72
 
+//rk312x MIPI DSI DPHY REGISTERS
+#define DPHY_REGISTER0                         DSI_DPHY_BITS(0x00, 32, 0)
+#define DPHY_REGISTER1                         DSI_DPHY_BITS(0x04, 32, 0)
+#define DPHY_REGISTER3                         DSI_DPHY_BITS(0x0c, 32, 0)
+#define DPHY_REGISTER4                         DSI_DPHY_BITS(0x10, 32, 0)
+#define DPHY_REGISTER20                                DSI_DPHY_BITS(0X80, 32, 0)
+
+#define lane_en_ck                                     DSI_DPHY_BITS(0x00, 1, 6)
+#define lane_en_3                                      DSI_DPHY_BITS(0x00, 1, 5)
+#define lane_en_2                                      DSI_DPHY_BITS(0x00, 1, 4)
+#define lane_en_1                                      DSI_DPHY_BITS(0x00, 1, 3)
+#define lane_en_0                                      DSI_DPHY_BITS(0x00, 1, 2)
+
+#define reg_da_ppfc                            DSI_DPHY_BITS(0x04, 1, 4)
+#define reg_da_syncrst                                 DSI_DPHY_BITS(0x04, 1, 2)
+#define reg_da_ldopd                           DSI_DPHY_BITS(0x04, 1, 1)
+#define reg_da_pllpd                           DSI_DPHY_BITS(0x04, 1, 0)
+
+#define reg_fbdiv_8                            DSI_DPHY_BITS(0x0c, 1, 5)
+#define reg_prediv                                     DSI_DPHY_BITS(0x0c, 5, 0)
+#define reg_fbdiv                                      DSI_DPHY_BITS(0x10, 8, 0)
+
+#define reg_dig_rstn                           DSI_DPHY_BITS(0X80, 1, 0)
+
+#define DPHY_CLOCK_OFFSET                      REG_ADDR(0X0100)
+#define DPHY_LANE0_OFFSET                      REG_ADDR(0X0180)
+#define DPHY_LANE1_OFFSET                      REG_ADDR(0X0200)
+#define DPHY_LANE2_OFFSET                      REG_ADDR(0X0280)
+#define DPHY_LANE3_OFFSET                      REG_ADDR(0X0300)
+
+#define reg_ths_settle                         DSI_DPHY_BITS(0x0000, 4, 0)
+#define reg_hs_tlpx                                    DSI_DPHY_BITS(0x0014, 6, 0)
+#define reg_hs_ths_prepare                     DSI_DPHY_BITS(0x0018, 7, 0)
+#define reg_hs_the_zero                                DSI_DPHY_BITS(0x001c, 6, 0)
+#define reg_hs_ths_trail                       DSI_DPHY_BITS(0x0020, 7, 0)
+#define reg_hs_ths_exit                                DSI_DPHY_BITS(0x0024, 5, 0)
+#define reg_hs_tclk_post                       DSI_DPHY_BITS(0x0028, 4, 0)
+#define reserved                                       DSI_DPHY_BITS(0x002c, 1, 0)
+#define reg_hs_twakup_h                                DSI_DPHY_BITS(0x0030, 2, 0)
+#define reg_hs_twakup_l                                DSI_DPHY_BITS(0x0034, 8, 0)
+#define reg_hs_tclk_pre                                DSI_DPHY_BITS(0x0038, 4, 0)
+#define reg_hs_tta_go                          DSI_DPHY_BITS(0x0040, 6, 0)
+#define reg_hs_tta_sure                                DSI_DPHY_BITS(0x0044, 6, 0)
+#define reg_hs_tta_wait                                DSI_DPHY_BITS(0x0048, 6, 0)
+//end of rk312x MIPI DSI DPHY REGISTERS
 
 //global operation timing parameter
 struct gotp_m {
index 74eaf28651be5d671687fb8031fbbd8f99b0a0b5..e165ee3250ef6f1d5b7943bfeaf040bb4330a37c 100644 (file)
@@ -1,14 +1,13 @@
-config RK610_TVOUT
-       bool "RK610(Jetta) tvout support"
-       depends on MFD_RK610
-       default n
+#
+# TV Encoder drivers configuration
+#
+
+menuconfig RK_TVENCODER
+       bool "Rockchip TV Encoder support"
+       depends on FB_ROCKCHIP
        help
-               Support Jetta(RK610) to output YPbPr and CVBS.
-               
-config RK610_TVOUT_YPbPr
-       bool "support YPbPr output"
-       depends on RK610_TVOUT
+               Support RockChip TV Encoder if you say y here.
+
+source "drivers/video/rockchip/tve/rk3036/Kconfig"
+source "drivers/video/rockchip/tve/rk610/Kconfig"
 
-config RK610_TVOUT_CVBS
-       bool "support CVBS output"
-       depends on RK610_TVOUT
index b7d457326d26caab608033da6be0614a1662335e..ea651687c417dfbfaeb287163db85b305ccd98bd 100644 (file)
@@ -1,6 +1,5 @@
 #
-# Makefile for the jetta tv control.
+# Makefile for tv encoder.
 #
-obj-$(CONFIG_RK610_TVOUT)                      += rk610_tv.o
-obj-$(CONFIG_RK610_TVOUT_YPbPr)                += rk610_tv_ypbpr.o
-obj-$(CONFIG_RK610_TVOUT_CVBS)         += rk610_tv_cvbs.o
\ No newline at end of file
+obj-$(CONFIG_RK610_TVOUT)              += rk610/
+obj-$(CONFIG_RK3036_TV_ENCODER)                += rk3036/
diff --git a/drivers/video/rockchip/tve/rk3036/Kconfig b/drivers/video/rockchip/tve/rk3036/Kconfig
new file mode 100644 (file)
index 0000000..eadde36
--- /dev/null
@@ -0,0 +1,7 @@
+config RK3036_TV_ENCODER
+       bool "rk3036/3128 tv encoder support"
+       depends on (LCDC_RK3036 || LCDC_RK312X) && RK_TVENCODER
+       default n
+       help
+               Support RK3036 output CVBS.
+
diff --git a/drivers/video/rockchip/tve/rk3036/Makefile b/drivers/video/rockchip/tve/rk3036/Makefile
new file mode 100644 (file)
index 0000000..850404a
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# Makefile for the rk3036 tv encoder control.
+#
+obj-$(CONFIG_RK3036_TV_ENCODER)        += rk3036_tve.o
diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.c b/drivers/video/rockchip/tve/rk3036/rk3036_tve.c
new file mode 100644 (file)
index 0000000..03c0cf9
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * rk3036_tve.c
+ *
+ * Driver for rockchip rk3036 tv encoder control
+ * Copyright (C) 2014
+ *
+ * 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.
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/rk_fb.h>
+#include <linux/display-sys.h>
+#include <linux/rockchip/grf.h>
+#include <linux/rockchip/iomap.h>
+#include "rk3036_tve.h"
+
+#ifdef DEBUG
+#define TVEDBG(format, ...) \
+               printk(KERN_INFO "RK3036 TVE: " format "\n", ## __VA_ARGS__)
+#else
+#define TVEDBG(format, ...)
+#endif
+
+static const struct fb_videomode rk3036_cvbs_mode[] = {
+       /*name          refresh xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw                    polariry                                PorI            flag*/
+       {"NTSC",        60,     720,    480,    27000000,       57,     19,     19,     0,      62,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
+       {"PAL",         50,     720,    576,    27000000,       69,     12,     19,     2,      63,     3,      FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,   FB_VMODE_INTERLACED,    0},
+};
+
+static struct rk3036_tve *rk3036_tve;
+
+#define tve_writel(offset, v)  writel_relaxed(v, rk3036_tve->regbase + offset)
+#define tve_readl(offset)      readl_relaxed(rk3036_tve->regbase + offset)
+
+static void dac_enable(bool enable)
+{
+       u32 mask, val;
+
+       TVEDBG("%s enable %d\n", __func__, enable);
+
+       if (enable) {
+               mask = m_VBG_EN | m_DAC_EN;
+               val = mask;
+       } else {
+               mask = m_VBG_EN | m_DAC_EN;
+               val = 0;
+       }
+       grf_writel(rk3036_tve->grfreg, (mask << 16) | val);
+       grf_writel(RK312X_GRF_TVE_CON, (mask << 16) | val);
+}
+
+static void tve_set_mode(int mode)
+{
+       TVEDBG("%s mode %d\n", __func__, mode);
+
+       tve_writel(TV_RESET, v_RESET(1));
+       udelay(100);
+       tve_writel(TV_RESET, v_RESET(0));
+
+       tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
+                       v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
+                       v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0));
+       tve_writel(TV_LUMA_FILTER0, 0x02ff0000);
+       tve_writel(TV_LUMA_FILTER1, 0xF40202fd);
+       tve_writel(TV_LUMA_FILTER2, 0xF332d919);
+
+       if (mode == TVOUT_CVBS_NTSC) {
+               tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) |
+                       v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
+                       v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
+               tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) |
+                       v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
+               tve_writel(TV_SATURATION, 0x0042543C);
+               tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
+
+               tve_writel(TV_FREQ_SC,  0x21F07BD7);
+               tve_writel(TV_SYNC_TIMING, 0x00C07a81);
+               tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70);
+               tve_writel(TV_ACT_ST,   0x001500D6);
+               tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28));
+
+       } else if (mode == TVOUT_CVBS_PAL) {
+               tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) |
+                       v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
+                       v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
+               tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) |
+                       v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
+               tve_writel(TV_SATURATION, 0x00325c40);
+               tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008b00);
+
+               tve_writel(TV_FREQ_SC,  0x2A098ACB);
+               tve_writel(TV_SYNC_TIMING, 0x00C28381);
+               tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80);
+               tve_writel(TV_ACT_ST,   0x001500F6);
+               tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
+               tve_writel(TV_ADJ_TIMING, (0xa << 28) | 0x06c00800 | 0x80);
+       }
+}
+
+static int tve_switch_fb(const struct fb_videomode *modedb, int enable)
+{
+       struct rk_screen *screen;
+
+       if (modedb == NULL)
+               return -1;
+       screen =  kzalloc(sizeof(screen), GFP_KERNEL);
+       if (screen == NULL)
+               return -1;
+
+       memset(screen, 0, sizeof(struct rk_screen));
+       /* screen type & face */
+       screen->type = SCREEN_TVOUT;
+       screen->face = OUT_P888;
+
+       screen->mode = *modedb;
+
+       /* Pin polarity */
+       if (FB_SYNC_HOR_HIGH_ACT & modedb->sync)
+               screen->pin_hsync = 1;
+       else
+               screen->pin_hsync = 0;
+       if (FB_SYNC_VERT_HIGH_ACT & modedb->sync)
+               screen->pin_vsync = 1;
+       else
+               screen->pin_vsync = 0;
+
+       screen->pin_den = 0;
+       screen->pin_dclk = 0;
+       screen->pixelrepeat = 1;
+
+       /* Swap rule */
+       screen->swap_rb = 0;
+       screen->swap_rg = 0;
+       screen->swap_gb = 0;
+       screen->swap_delta = 0;
+       screen->swap_dumy = 0;
+
+       /* Operation function*/
+       screen->init = NULL;
+       screen->standby = NULL;
+
+       rk_fb_switch_screen(screen, enable, 0);
+
+       kfree(screen);
+       if (enable) {
+               if (screen->mode.yres == 480)
+                       tve_set_mode(TVOUT_CVBS_NTSC);
+               else
+                       tve_set_mode(TVOUT_CVBS_PAL);
+       }
+       return 0;
+}
+
+static int cvbs_set_enable(struct rk_display_device *device, int enable)
+{
+       TVEDBG("%s enable %d\n", __func__, enable);
+       if (rk3036_tve->enable != enable) {
+               rk3036_tve->enable = enable;
+               if (rk3036_tve->suspend)
+                       return 0;
+
+               if (enable == 0) {
+                       dac_enable(false);
+                       tve_switch_fb(rk3036_tve->mode, 0);
+               } else if (enable == 1) {
+                       tve_switch_fb(rk3036_tve->mode, 1);
+                       dac_enable(true);
+               }
+       }
+       return 0;
+}
+
+static int cvbs_get_enable(struct rk_display_device *device)
+{
+       TVEDBG("%s enable %d\n", __func__, rk3036_tve->enable);
+       return rk3036_tve->enable;
+}
+
+static int cvbs_get_status(struct rk_display_device *device)
+{
+       return 1;
+}
+
+static int
+cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
+{
+       *modelist = &(rk3036_tve->modelist);
+       return 0;
+}
+
+static int
+cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++) {
+               if (fb_mode_is_equal(&rk3036_cvbs_mode[i], mode)) {
+                       if (rk3036_tve->mode != &rk3036_cvbs_mode[i]) {
+                               rk3036_tve->mode =
+                               (struct fb_videomode *)&rk3036_cvbs_mode[i];
+                               if (rk3036_tve->enable && !rk3036_tve->suspend)
+                                       dac_enable(false);
+                                       tve_switch_fb(rk3036_tve->mode, 1);
+                                       msleep(500);
+                                       dac_enable(true);
+                       }
+                       return 0;
+               }
+       }
+       TVEDBG("%s\n", __func__);
+       return -1;
+}
+
+static int
+cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       *mode = *(rk3036_tve->mode);
+       return 0;
+}
+
+static int
+tve_fb_event_notify(struct notifier_block *self,
+                   unsigned long action, void *data)
+{
+       struct fb_event *event = data;
+       int blank_mode = *((int *)event->data);
+
+       if (action == FB_EARLY_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       break;
+               default:
+                       TVEDBG("suspend hdmi\n");
+                       if (!rk3036_tve->suspend) {
+                               rk3036_tve->suspend = 1;
+                               if (rk3036_tve->enable) {
+                                       tve_switch_fb(rk3036_tve->mode, 0);
+                                       dac_enable(false);
+                               }
+                       }
+                       break;
+               }
+       } else if (action == FB_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       TVEDBG("resume hdmi\n");
+                       if (rk3036_tve->suspend) {
+                               rk3036_tve->suspend = 0;
+                               if (rk3036_tve->enable) {
+                                       tve_switch_fb(rk3036_tve->mode, 1);
+                                       dac_enable(true);
+                               }
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block tve_fb_notifier = {
+       .notifier_call = tve_fb_event_notify,
+};
+
+static struct rk_display_ops cvbs_display_ops = {
+       .setenable = cvbs_set_enable,
+       .getenable = cvbs_get_enable,
+       .getstatus = cvbs_get_status,
+       .getmodelist = cvbs_get_modelist,
+       .setmode = cvbs_set_mode,
+       .getmode = cvbs_get_mode,
+};
+
+static int
+display_cvbs_probe(struct rk_display_device *device, void *devdata)
+{
+       device->owner = THIS_MODULE;
+       strcpy(device->type, "TV");
+       device->name = "cvbs";
+       device->priority = DISPLAY_PRIORITY_TV;
+       device->priv_data = devdata;
+       device->ops = &cvbs_display_ops;
+       return 1;
+}
+
+static struct rk_display_driver display_cvbs = {
+       .probe = display_cvbs_probe,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id rk3036_tve_dt_ids[] = {
+       {.compatible = "rockchip,rk3036-tve",},
+       {.compatible = "rockchip,rk312x-tve",},
+       {}
+};
+#endif
+
+static int rk3036_tve_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res;
+       const struct of_device_id *match;
+       int i;
+
+       match = of_match_node(rk3036_tve_dt_ids, np);
+       if (!match)
+               return PTR_ERR(match);
+
+       rk3036_tve = devm_kzalloc(&pdev->dev,
+                                 sizeof(struct rk3036_tve), GFP_KERNEL);
+       if (!rk3036_tve) {
+               dev_err(&pdev->dev, "rk3036 tv encoder device kmalloc fail!");
+               return -ENOMEM;
+       }
+
+       if (!strcmp(match->compatible, "rockchip,rk3036-tve")) {
+               rk3036_tve->grfreg = RK3036_GRF_SOC_CON3;
+       } else if (!strcmp(match->compatible, "rockchip,rk312x-tve")) {
+               rk3036_tve->grfreg = RK312X_GRF_TVE_CON;
+       } else {
+               dev_err(&pdev->dev, "It is not a valid tv encoder!");
+               kfree(rk3036_tve);
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, rk3036_tve);
+       rk3036_tve->dev = &pdev->dev;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rk3036_tve->reg_phy_base = res->start;
+       rk3036_tve->len = resource_size(res);
+       rk3036_tve->regbase = ioremap(res->start, rk3036_tve->len);
+       if (IS_ERR(rk3036_tve->regbase)) {
+               dev_err(&pdev->dev,
+                       "rk3036 tv encoder device map registers failed!");
+               return PTR_ERR(rk3036_tve->regbase);
+       }
+
+       INIT_LIST_HEAD(&(rk3036_tve->modelist));
+       for (i = 0; i < ARRAY_SIZE(rk3036_cvbs_mode); i++)
+               fb_add_videomode(&rk3036_cvbs_mode[i], &(rk3036_tve->modelist));
+       rk3036_tve->mode = (struct fb_videomode *)&rk3036_cvbs_mode[1];
+       rk3036_tve->ddev =
+               rk_display_device_register(&display_cvbs, &pdev->dev, NULL);
+       rk_display_device_enable(rk3036_tve->ddev);
+
+       fb_register_client(&tve_fb_notifier);
+       dev_info(&pdev->dev, "rk3036 tv encoder probe ok\n");
+       return 0;
+}
+
+static void rk3036_tve_shutdown(struct platform_device *pdev)
+{
+}
+
+static struct platform_driver rk3036_tve_driver = {
+       .probe = rk3036_tve_probe,
+       .remove = NULL,
+       .driver = {
+               .name = "rk3036-tve",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(rk3036_tve_dt_ids),
+       },
+       .shutdown = rk3036_tve_shutdown,
+};
+
+static int __init rk3036_tve_init(void)
+{
+       return platform_driver_register(&rk3036_tve_driver);
+}
+
+static void __exit rk3036_tve_exit(void)
+{
+       platform_driver_unregister(&rk3036_tve_driver);
+}
+
+module_init(rk3036_tve_init);
+module_exit(rk3036_tve_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("ROCKCHIP RK3036 TV Encoder ");
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/drivers/video/rockchip/tve/rk3036/rk3036_tve.h b/drivers/video/rockchip/tve/rk3036/rk3036_tve.h
new file mode 100644 (file)
index 0000000..c5cbf52
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __RK3036_TVE_H__
+#define __RK3036_TVE_H__
+
+#define TV_CTRL                        (0x00)
+       #define m_CVBS_MODE                     (1 << 24)
+       #define m_CLK_UPSTREAM_EN               (3 << 18)
+       #define m_TIMING_EN                     (3 << 16)
+       #define m_LUMA_FILTER_GAIN              (3 << 9)
+       #define m_LUMA_FILTER_BW                (1 << 8)
+       #define m_CSC_PATH                      (3 << 1)
+
+       #define v_CVBS_MODE(x)                  ((x & 1) << 24)
+       #define v_CLK_UPSTREAM_EN(x)            ((x & 3) << 18)
+       #define v_TIMING_EN(x)                  ((x & 3) << 16)
+       #define v_LUMA_FILTER_GAIN(x)           ((x & 3) << 9)
+       #define v_LUMA_FILTER_UPSAMPLE(x)       ((x & 1) << 8)
+       #define v_CSC_PATH(x)                   ((x & 3) << 1)
+
+#define TV_SYNC_TIMING         (0x04)
+#define TV_ACT_TIMING          (0x08)
+#define TV_ADJ_TIMING          (0x0c)
+#define TV_FREQ_SC             (0x10)
+#define TV_LUMA_FILTER0                (0x14)
+#define TV_LUMA_FILTER1                (0x18)
+#define TV_LUMA_FILTER2                (0x1C)
+#define TV_ACT_ST              (0x34)
+#define TV_ROUTING             (0x38)
+       #define m_DAC_SENSE_EN          (1 << 27)
+       #define m_Y_IRE_7_5             (1 << 19)
+       #define m_Y_AGC_PULSE_ON        (1 << 15)
+       #define m_Y_VIDEO_ON            (1 << 11)
+       #define m_Y_SYNC_ON             (1 << 7)
+       #define m_YPP_MODE              (1 << 3)
+       #define m_MONO_EN               (1 << 2)
+       #define m_PIC_MODE              (1 << 1)
+
+       #define v_DAC_SENSE_EN(x)       ((x & 1) << 27)
+       #define v_Y_IRE_7_5(x)          ((x & 1) << 19)
+       #define v_Y_AGC_PULSE_ON(x)     ((x & 1) << 15)
+       #define v_Y_VIDEO_ON(x)         ((x & 1) << 11)
+       #define v_Y_SYNC_ON(x)          ((x & 1) << 7)
+       #define v_YPP_MODE(x)           ((x & 1) << 3)
+       #define v_MONO_EN(x)            ((x & 1) << 2)
+       #define v_PIC_MODE(x)           ((x & 1) << 1)
+
+#define TV_SYNC_ADJUST         (0x50)
+#define TV_STATUS              (0x54)
+#define TV_RESET               (0x68)
+       #define m_RESET                 (1 << 1)
+       #define v_RESET(x)              ((x & 1) << 1)
+#define TV_SATURATION          (0x78)
+#define TV_BW_CTRL             (0x8C)
+       #define m_CHROMA_BW     (3 << 4)
+       #define m_COLOR_DIFF_BW (0xf)
+
+       enum {
+               BP_FILTER_PASS = 0,
+               BP_FILTER_NTSC,
+               BP_FILTER_PAL,
+       };
+       enum {
+               COLOR_DIFF_FILTER_OFF = 0,
+               COLOR_DIFF_FILTER_BW_0_6,
+               COLOR_DIFF_FILTER_BW_1_3,
+               COLOR_DIFF_FILTER_BW_2_0
+       };
+
+       #define v_CHROMA_BW(x)          ((3 & x) << 4)
+       #define v_COLOR_DIFF_BW(x)      (0xF & x)
+
+#define TV_BRIGHTNESS_CONTRAST (0x90)
+
+#define m_EXTREF_EN            (1 << 0)
+#define m_VBG_EN               (1 << 1)
+#define m_DAC_EN               (1 << 2)
+#define m_SENSE_EN             (1 << 3)
+#define m_BIAS_EN              (7 << 4)
+#define m_DAC_GAIN             (0x3f << 7)
+#define v_DAC_GAIN(x)          ((x & 0x3f) << 7)
+
+enum {
+       TVOUT_CVBS_NTSC = 0,
+       TVOUT_CVBS_PAL,
+};
+
+#define TVOUT_DEAULT TVOUT_CVBS_PAL
+
+#define grf_writel(offset, v)  do { \
+       writel_relaxed(v, RK_GRF_VIRT + offset); \
+       dsb(); \
+       } while (0)
+
+struct rk3036_tve {
+       struct device                   *dev;
+       void __iomem                    *regbase;
+       u32                             reg_phy_base;
+       u32                             len;
+       int                             grfreg;
+
+       struct rk_display_device        *ddev;
+       unsigned int                    enable;
+       unsigned int                    suspend;
+       struct fb_videomode             *mode;
+       struct list_head                modelist;
+};
+
+#endif
\ No newline at end of file
diff --git a/drivers/video/rockchip/tve/rk610/Kconfig b/drivers/video/rockchip/tve/rk610/Kconfig
new file mode 100644 (file)
index 0000000..74eaf28
--- /dev/null
@@ -0,0 +1,14 @@
+config RK610_TVOUT
+       bool "RK610(Jetta) tvout support"
+       depends on MFD_RK610
+       default n
+       help
+               Support Jetta(RK610) to output YPbPr and CVBS.
+               
+config RK610_TVOUT_YPbPr
+       bool "support YPbPr output"
+       depends on RK610_TVOUT
+
+config RK610_TVOUT_CVBS
+       bool "support CVBS output"
+       depends on RK610_TVOUT
diff --git a/drivers/video/rockchip/tve/rk610/Makefile b/drivers/video/rockchip/tve/rk610/Makefile
new file mode 100644 (file)
index 0000000..b7d4573
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the jetta tv control.
+#
+obj-$(CONFIG_RK610_TVOUT)                      += rk610_tv.o
+obj-$(CONFIG_RK610_TVOUT_YPbPr)                += rk610_tv_ypbpr.o
+obj-$(CONFIG_RK610_TVOUT_CVBS)         += rk610_tv_cvbs.o
\ No newline at end of file
diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv.c b/drivers/video/rockchip/tve/rk610/rk610_tv.c
new file mode 100644 (file)
index 0000000..83a6cec
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * rk610_tv.c 
+ *
+ * Driver for rockchip rk610 tv control
+ *  Copyright (C) 2009 
+ *
+ *  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.
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#include "rk610_tv.h"
+#include "../../rk29_fb.h"
+
+#define DRV_NAME "rk610_tvout"
+#define RK610_I2C_RATE     100*1000
+
+volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT;
+static struct i2c_client *rk610_tv_i2c_client = NULL;
+
+int rk610_tv_wirte_reg(u8 reg, u8 data)
+{
+    int ret;
+       if(rk610_tv_i2c_client == NULL)
+               return -1;
+    ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE);
+       if (ret > 0)
+               ret = 0;
+       return ret;
+}
+
+int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode)
+{      
+       struct rk_screen *screen;
+       
+       if(modedb == NULL)
+               return -1;
+       screen =  kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
+       if(screen == NULL)
+               return -1;
+       
+       memset(screen, 0, sizeof(struct rk_screen));    
+       /* screen type & face */
+    screen->type = SCREEN_HDMI;
+       screen->mode = modedb->vmode;
+       screen->face = modedb->flag;
+       /* Screen size */
+       screen->x_res = modedb->xres;
+    screen->y_res = modedb->yres;
+
+    /* Timing */
+    screen->pixclock = modedb->pixclock;
+
+       screen->lcdc_aclk = 500000000;
+       screen->left_margin = modedb->left_margin;
+       screen->right_margin = modedb->right_margin;
+       screen->hsync_len = modedb->hsync_len;
+       screen->upper_margin = modedb->upper_margin;
+       screen->lower_margin = modedb->lower_margin;
+       screen->vsync_len = modedb->vsync_len;
+
+       /* Pin polarity */
+       if(FB_SYNC_HOR_HIGH_ACT & modedb->sync)
+               screen->pin_hsync = 1;
+       else
+               screen->pin_hsync = 0;
+       if(FB_SYNC_VERT_HIGH_ACT & modedb->sync)
+               screen->pin_vsync = 1;
+       else
+               screen->pin_vsync = 0;  
+       screen->pin_den = 0;
+       screen->pin_dclk = 0;
+
+       /* Swap rule */
+    screen->swap_rb = 0;
+    screen->swap_rg = 0;
+    screen->swap_gb = 0;
+    screen->swap_delta = 0;
+    screen->swap_dumy = 0;
+
+    /* Operation function*/
+    screen->init = NULL;
+    screen->standby = NULL;    
+    
+    switch(tv_mode)
+       {
+#ifdef CONFIG_RK610_TVOUT_CVBS
+               case TVOUT_CVBS_NTSC:
+               case TVOUT_CVBS_PAL:
+            screen->init = rk610_tv_cvbs_init;;
+               break;
+#endif
+
+#ifdef CONFIG_RK610_TVOUT_YPbPr
+               case TVOUT_YPbPr_720x480p_60:
+               case TVOUT_YPbPr_720x576p_50:
+               case TVOUT_YPbPr_1280x720p_50:
+               case TVOUT_YPbPr_1280x720p_60:
+               //case TVOUT_YPbPr_1920x1080i_50:
+               case TVOUT_YPbPr_1920x1080i_60:
+               case TVOUT_YPbPr_1920x1080p_50:
+               case TVOUT_YPbPr_1920x1080p_60:
+                       screen->init = rk610_tv_ypbpr_init;
+                       break;
+#endif
+               default:{
+                       kfree(screen);
+                       return -1;
+               }
+               break;
+       }
+       rk610_tv_output_status = tv_mode;
+       FB_Switch_Screen(screen, 1);
+       kfree(screen);
+       return 0;
+}
+
+int rk610_tv_standby(int type)
+{
+       int ret;
+
+       switch(type)
+       {
+               #ifdef CONFIG_RK610_TVOUT_CVBS
+               case RK610_TVOUT_CVBS:
+                       if(rk610_cvbs_monspecs.enable == 0)
+                               return 0;
+                       #ifdef CONFIG_RK610_TVOUT_YPbPr
+                       if(rk610_ypbpr_monspecs.enable == 1)
+                               return 0;
+                       #endif
+                       break;
+               #endif
+               #ifdef CONFIG_RK610_TVOUT_YPbPr
+               case RK610_TVOUT_YPBPR:
+                       if(rk610_ypbpr_monspecs.enable == 0)
+                               return 0;
+                       #ifdef CONFIG_RK610_TVOUT_CVBS
+                       if(rk610_cvbs_monspecs.enable == 1)
+                               return 0;
+                       #endif
+                       break;
+               #endif
+               default:
+                       break;
+       }
+
+       ret = rk610_tv_wirte_reg(TVE_POWERCR, 0);
+       if(ret < 0){
+               printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__);
+               return ret;
+       }
+       
+       ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0);
+       if(ret < 0){
+               printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__);
+               return ret;
+       }
+       return 0;
+}
+
+static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id)
+{
+       int rc = 0;
+       
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               rc = -ENODEV;
+               goto failout;
+       }
+       rk610_tv_i2c_client = client;
+
+#ifdef CONFIG_RK610_TVOUT_YPbPr
+       rk610_register_display_ypbpr(&client->dev);
+       if(rk610_tv_output_status > TVOUT_CVBS_PAL)
+               rk_display_device_enable(rk610_ypbpr_monspecs.ddev);
+#endif
+
+#ifdef CONFIG_RK610_TVOUT_CVBS
+       rk610_register_display_cvbs(&client->dev);
+       if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
+               rk_display_device_enable(rk610_cvbs_monspecs.ddev);
+#endif
+       
+    printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n");
+    return 0;
+failout:
+       kfree(client);
+       return rc;
+}
+
+static int rk610_tv_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+
+static const struct i2c_device_id rk610_tv_id[] = {
+       { DRV_NAME, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rk610_tv_id);
+
+static struct i2c_driver rk610_tv_driver = {
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+       .id_table = rk610_tv_id,
+       .probe = rk610_tv_probe,
+       .remove = rk610_tv_remove,
+};
+
+static int __init rk610_tv_init(void)
+{
+       int ret = 0;
+       ret = i2c_add_driver(&rk610_tv_driver);
+       if(ret < 0){
+               printk("i2c_add_driver err, ret = %d\n", ret);
+       }
+       return ret;
+}
+
+static void __exit rk610_tv_exit(void)
+{
+    i2c_del_driver(&rk610_tv_driver);
+}
+
+module_init(rk610_tv_init);
+//late_initcall(rk610_tv_init);
+module_exit(rk610_tv_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output");
+MODULE_LICENSE("GPL");
+
+
diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv.h b/drivers/video/rockchip/tve/rk610/rk610_tv.h
new file mode 100644 (file)
index 0000000..ead23a8
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef _RK610_TV_H
+#define _RK610_TV_H
+#include <linux/display-sys.h>
+#include <linux/rk_fb.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#ifdef CONFIG_ARCH_RK29
+#include <mach/rk29_iomap.h>
+#endif
+#include "../screen/screen.h"
+#include "../../rk29_fb.h"
+#include <linux/mfd/rk610_core.h>
+
+#define TVE_VFCR               0x00
+       #define TVE_VFCR_ENABLE_SUBCARRIER_RESET        0 << 6
+       #define TVE_VFCR_DISABLE_SUBCARRIER_RESET       1 << 6
+       #define TVE_VFCR_VIN_RANGE_16_235                       0 << 3
+       #define TVE_VFCR_VIN_RANGE_1_254                        1 << 3
+       #define TVE_VFCR_BLACK_7_5_IRE                          0 << 2
+       #define TVE_VFCR_BLACK_0_IRE                            1 << 2
+       #define TVE_VFCR_NTSC                                           0
+       #define TVE_VFCR_PAL_M                                          1
+       #define TVE_VFCR_PAL_B_N                                        2
+       #define TVE_VFCR_PAL_NC                                         3
+
+#define TVE_VINCR              0x01
+       #define TVE_VINCR_PIX_DATA_DELAY(n)                     (n << 5)
+       #define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE       0 << 4
+       #define TVE_VINCR_H_SYNC_POLARITY_POSITIVE      1 << 4
+       #define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE       0 << 3
+       #define TVE_VINCR_V_SYNC_POLARITY_POSITIVE      1 << 3
+enum {
+       INPUT_FORMAT_BT601_SLAVE = 0,
+       INPUT_FORMAT_BT656,
+       INPUT_FORMAT_BT601_MASTER,
+       INPUT_FORMAT_INTERNAL_COLLOR_BAR
+};
+       #define TVE_VINCR_INPUT_FORMAT(n)                       (n << 1)
+       #define TVE_VINCR_VSYNC_FUNCTION_VSYNC          0
+       #define TVE_VINCR_VSYNC_FUNCTION_FIELD          1
+
+#define TVE_VOUTCR             0x02
+       #define TVE_VOUTCR_OUTPUT_CVBS                          0 << 6
+       #define TVE_VOUTCR_OUTPUT_YPBPR                         1 << 6
+       #define TVE_VOUTCR_OUTPUT_ENABLE_BLUE           1 << 5
+       #define TVE_VOUTCR_OUTPUT_ENABLE_BLACK          1 << 4
+       #define TVE_VOUTCR_DISABLE_CVBS_COLOR           1 << 3
+       #define TVE_VOUTCR_CVBS_Y2C_DELAY(n)                            (n << 0)
+
+#define TVE_POWERCR            0x03
+       #define TVE_PIX_CLK_INVERSE_ENABLE                      1 << 4
+       #define TVE_DAC_CLK_INVERSE_DISABLE                     1 << 3
+       #define TVE_DAC_Y_ENABLE                                        1 << 2
+       #define TVE_DAC_U_ENABLE                                        1 << 1
+       #define TVE_DAC_V_ENABLE                                        1 << 0
+
+#define TVE_HDTVCR             0x05
+       #define TVE_RESET                                                       1 << 7
+       #define TVE_FILTER(n)                                           (n << 5)
+       #define TVE_COLOR_CONVERT_REC601                        0 << 4
+       #define TVE_COLOR_CONVERT_REC709                        1 << 4
+       #define TVE_INPUT_DATA_RGB                                      0 << 3
+       #define TVE_INPUT_DATA_YUV                                      1 << 3
+       #define TVE_OUTPUT_50HZ                                         0 << 2
+       #define TVE_OUTPUT_60HZ                                         1 << 2
+       #define TVE_OUTPUT_MODE_PAL_NTSC                        0
+       #define TVE_OUTPUT_MODE_576P                            1
+       #define TVE_OUTPUT_MODE_480P                            2
+       #define TVE_OUTPUT_MODE_720P                            3
+
+#define TVE_YADJCR             0x06
+       #define TVE_OUTPUT_MODE_1080P                           1 << 6
+       #define TVE_OUTPUT_MODE_1080I                           1 << 5
+       #define TVE_Y_ADJ_VALUE(n)                                      n
+#define TVE_YCBADJCR   0x07
+#define TVE_YCRADJCR   0x08
+
+/******************* TVOUT OUTPUT TYPE **********************/
+struct rk610_monspecs {
+       struct rk_display_device        *ddev;
+       unsigned int                            enable;
+       struct fb_videomode                     *mode;
+       struct list_head                        modelist;
+       unsigned int                            mode_set;
+};
+
+enum {
+       TVOUT_CVBS_NTSC = 1,
+       TVOUT_CVBS_PAL,
+       TVOUT_YPbPr_720x480p_60,
+       TVOUT_YPbPr_720x576p_50,
+       TVOUT_YPbPr_1280x720p_50,
+       TVOUT_YPbPr_1280x720p_60,
+       //TVOUT_YPbPr_1920x1080i_50,
+       TVOUT_YPbPr_1920x1080i_60,
+       TVOUT_YPbPr_1920x1080p_50,
+       TVOUT_YPbPr_1920x1080p_60
+};
+
+#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC
+
+enum {
+       RK610_TVOUT_CVBS = 0,
+       RK610_TVOUT_YC,
+       RK610_TVOUT_YPBPR,
+};
+
+extern volatile int rk610_tv_output_status;
+extern struct rk_display_ops rk610_display_ops;
+
+extern int FB_Switch_Screen( struct rk_screen *screen, u32 enable );
+
+extern int rk610_tv_wirte_reg(u8 reg, u8 data);
+extern int rk610_tv_standby(int type);
+extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode);
+extern int rk610_register_display(struct device *parent);
+
+#ifdef CONFIG_RK610_TVOUT_YPbPr
+extern int rk610_tv_ypbpr_init(void);
+extern int rk610_register_display_ypbpr(struct device *parent);
+extern struct rk610_monspecs rk610_ypbpr_monspecs;
+#endif
+
+#ifdef CONFIG_RK610_TVOUT_CVBS
+extern int rk610_tv_cvbs_init(void);
+extern int rk610_register_display_cvbs(struct device *parent);
+extern struct rk610_monspecs rk610_cvbs_monspecs;
+#endif
+
+#endif
+
diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c b/drivers/video/rockchip/tve/rk610/rk610_tv_cvbs.c
new file mode 100644 (file)
index 0000000..ea0fe8a
--- /dev/null
@@ -0,0 +1,209 @@
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/display-sys.h>
+#include "rk610_tv.h"
+
+
+#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
+#define RK610_LED_CVBS_PIN     RK29_PIN4_PD3
+#else
+#define RK610_LED_CVBS_PIN     INVALID_GPIO
+#endif
+
+#ifdef USE_RGB2CCIR
+static const struct fb_videomode rk610_cvbs_mode [] = {
+               //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
+       {       "NTSC",                         60,                     720,    480,    27000000,       116,    16,             25,             14,             6,              6,              0,                      1,              OUT_P888        },
+       {       "PAL",                          50,                     720,    576,    27000000,       126,    12,             37,             6,              6,              6,              0,                      1,              OUT_P888        },
+};
+#else
+static const struct fb_videomode rk610_cvbs_mode [] = {
+               //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
+       {       "NTSC",                         60,                     720,    480,    27000000,       116,    16,             16,             3,              6,              3,              0,                      1,              OUT_CCIR656     },
+       {       "PAL",                          50,                     720,    576,    27000000,       126,    12,             19,             2,              6,              3,              0,                      1,              OUT_CCIR656     },
+};
+#endif
+
+struct rk610_monspecs rk610_cvbs_monspecs;
+
+
+int rk610_tv_cvbs_init(void)
+{
+       unsigned char TVE_Regs[9];
+       unsigned char TVE_CON_Reg;
+       int ret, i;
+       
+       rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
+
+       memset(TVE_Regs, 0, 9);
+       TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE;
+       TVE_Regs[TVE_VINCR]     =       TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
+       TVE_Regs[TVE_POWERCR]   =       TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
+       TVE_Regs[TVE_VOUTCR]    =       TVE_VOUTCR_OUTPUT_CVBS;
+       TVE_Regs[TVE_YADJCR]    =       0x17;
+       TVE_Regs[TVE_YCBADJCR]  =       0x10;
+       TVE_Regs[TVE_YCRADJCR]  =       0x10;
+       
+       switch(rk610_tv_output_status) {
+               case TVOUT_CVBS_NTSC:
+                       TVE_Regs[TVE_VFCR]              = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC;
+                       #ifdef USE_RGB2CCIR
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
+                       TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE;
+                       #else
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
+                       #endif                  
+                       break;
+               case TVOUT_CVBS_PAL:
+                       TVE_Regs[TVE_VFCR]              = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N;               
+                       #ifdef USE_RGB2CCIR
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
+                       TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE;
+                       #else
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
+                       #endif                  
+                       break;
+               default:
+                       return -1;
+       }
+       
+       for(i = 0; i < sizeof(TVE_Regs); i++){
+//             printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
+               ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
+               if(ret < 0){
+                       printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i);
+                       return ret;
+               }
+       }
+//     printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg);
+       rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
+       #ifdef USE_RGB2CCIR
+       rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01);
+       #endif
+       return 0;
+}
+
+static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable)
+{
+       if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status)
+       {
+               if(enable == 0)
+               {
+                       rk610_tv_standby(RK610_TVOUT_CVBS);
+                       rk610_cvbs_monspecs.enable = 0;
+                       if(RK610_LED_CVBS_PIN != INVALID_GPIO)
+                               gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
+               }
+               else if(enable == 1)
+               {
+                       rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set);
+                       rk610_cvbs_monspecs.enable = 1;
+                       if(RK610_LED_CVBS_PIN != INVALID_GPIO)
+                               gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW);
+               }
+       }
+       return 0;
+}
+
+static int rk610_cvbs_get_enable(struct rk_display_device *device)
+{
+       return rk610_cvbs_monspecs.enable;
+}
+
+static int rk610_cvbs_get_status(struct rk_display_device *device)
+{
+       if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
+               return 1;
+       else
+               return 0;
+}
+
+static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
+{
+       *modelist = &(rk610_cvbs_monspecs.modelist);
+       return 0;
+}
+
+static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       int i;
+
+       for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
+       {
+               if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode))
+               {       
+                       if( ((i + 1) != rk610_tv_output_status) )
+                       {
+                               rk610_cvbs_monspecs.mode_set = i + 1;
+                               rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i];
+                       }
+                       return 0;
+               }
+       }
+       
+       return -1;
+}
+
+static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       *mode = *(rk610_cvbs_monspecs.mode);
+       return 0;
+}
+
+static struct rk_display_ops rk610_cvbs_display_ops = {
+       .setenable = rk610_cvbs_set_enable,
+       .getenable = rk610_cvbs_get_enable,
+       .getstatus = rk610_cvbs_get_status,
+       .getmodelist = rk610_cvbs_get_modelist,
+       .setmode = rk610_cvbs_set_mode,
+       .getmode = rk610_cvbs_get_mode,
+};
+
+static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata)
+{
+       device->owner = THIS_MODULE;
+       strcpy(device->type, "TV");
+       device->priority = DISPLAY_PRIORITY_TV;
+       device->priv_data = devdata;
+       device->ops = &rk610_cvbs_display_ops;
+       return 1;
+}
+
+static struct rk_display_driver display_rk610_cvbs = {
+       .probe = rk610_display_cvbs_probe,
+};
+
+int rk610_register_display_cvbs(struct device *parent)
+{
+       int i;
+       
+       memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs));
+       INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist);
+       for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
+               fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist);
+       if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) {
+               rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]);
+               rk610_cvbs_monspecs.mode_set = rk610_tv_output_status;
+       }
+       else {
+               rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]);
+               rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
+       }
+       rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL);
+       if(RK610_LED_CVBS_PIN != INVALID_GPIO)
+    {        
+        if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0)
+        {
+            gpio_free(RK610_LED_CVBS_PIN);
+            dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n ");
+            return -1;
+        }
+               gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp);
+               gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
+    }
+       return 0;
+}
diff --git a/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c b/drivers/video/rockchip/tve/rk610/rk610_tv_ypbpr.c
new file mode 100644 (file)
index 0000000..af74126
--- /dev/null
@@ -0,0 +1,229 @@
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/display-sys.h>
+#include "rk610_tv.h"
+
+
+#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
+#define RK610_LED_YPbPr_PIN    RK29_PIN4_PD5
+#else
+#define RK610_LED_YPbPr_PIN    INVALID_GPIO
+#endif
+#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg)
+
+static const struct fb_videomode rk610_YPbPr_mode [] = {
+               //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
+       {       "YPbPr480p",            60,                     720,    480,    27000000,       55,             19,             37,             5,              64,             5,              0,                      0,              OUT_P888        },
+       {       "YPbPr576p",            50,                     720,    576,    27000000,       68,             12,             39,             5,              64,             5,              0,                      0,              OUT_P888        },
+       {       "YPbPr720p@50",         50,                     1280,   720,    74250000,       600,    0,              20,             5,              100,    5,              0,                      0,              OUT_P888        },
+       {       "YPbPr720p@60",         60,                     1280,   720,    74250000,       270,    0,              20,             5,              100,    5,              0,                      0,              OUT_P888        },
+       //{     "YPbPr1080i@50",        50,                     1920,   1080,   148500000,      620,    0,              15,             2,              100,    5,              0,                      1,              OUT_CCIR656     },
+       {       "YPbPr1080i@60",        60,                     1920,   1080,   148500000,      180,    0,              15,             2,              100,    5,              0,                      1,              OUT_CCIR656     },
+       {       "YPbPr1080p@50",        50,                     1920,   1080,   148500000,      620,    0,              36,             4,              100,    5,              0,                      0,              OUT_P888        },
+       {       "YPbPr1080p@60",        60,                     1920,   1080,   148500000,      180,    0,              36,             4,              100,    5,              0,                      0,              OUT_P888        },
+};
+
+struct rk610_monspecs rk610_ypbpr_monspecs;
+
+int rk610_tv_ypbpr_init(void)
+{
+       unsigned char TVE_Regs[9];
+       unsigned char TVE_CON_Reg;
+       int i, ret;
+       
+       rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
+       memset(TVE_Regs, 0, 9); 
+       
+       TVE_CON_Reg = 0x00;
+       
+       TVE_Regs[TVE_VINCR]     =       TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
+       TVE_Regs[TVE_POWERCR]   =       TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
+       TVE_Regs[TVE_VOUTCR]    =       TVE_VOUTCR_OUTPUT_YPBPR;
+       TVE_Regs[TVE_YADJCR]    =       0x17;
+       TVE_Regs[TVE_YCBADJCR]  =       0x10;
+       TVE_Regs[TVE_YCRADJCR]  =       0x10;
+       
+       switch(rk610_tv_output_status)
+       {
+               case TVOUT_YPbPr_720x480p_60:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P;
+                       break;
+               case TVOUT_YPbPr_720x576p_50:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P;
+                       break;
+               case TVOUT_YPbPr_1280x720p_50:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P;
+                       break;
+               case TVOUT_YPbPr_1280x720p_60:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P;
+                       break;
+               /*case TVOUT_YPbPr_1920x1080i_50:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ;
+                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080I;
+                       break;
+                       */
+               case TVOUT_YPbPr_1920x1080i_60:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ;
+                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080I;
+                       break;
+               case TVOUT_YPbPr_1920x1080p_50:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ;
+                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080P;
+                       break;
+               case TVOUT_YPbPr_1920x1080p_60:
+                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
+                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
+                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ;
+                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080P;
+                       break;
+               default:
+                       return -1;
+       }
+       
+       rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
+       
+       for(i = 0; i < sizeof(TVE_Regs); i++){
+//             printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
+               ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
+               if(ret < 0){
+                       E("rk610_tv_wirte_reg %d err!\n", i);
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable)
+{
+       if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status)
+       {
+               if(enable == 0)
+               {
+                       rk610_tv_standby(RK610_TVOUT_YPBPR);
+                       rk610_ypbpr_monspecs.enable = 0;
+                       if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
+                               gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
+               }
+               else if(enable == 1)
+               {
+                       rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set);
+                       rk610_ypbpr_monspecs.enable = 1;
+                       if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
+                               gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW);
+               }
+       }
+       return 0;
+}
+
+static int rk610_ypbpr_get_enable(struct rk_display_device *device)
+{
+       return rk610_ypbpr_monspecs.enable;
+}
+
+static int rk610_ypbpr_get_status(struct rk_display_device *device)
+{
+       if(rk610_tv_output_status > TVOUT_CVBS_PAL)
+               return 1;
+       else
+               return 0;
+}
+
+static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist)
+{
+       *modelist = &(rk610_ypbpr_monspecs.modelist);
+       return 0;
+}
+
+static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       int i;
+
+       for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
+       {
+               if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode))
+               {       
+                       if( (i + 3) != rk610_tv_output_status )
+                       {
+                               rk610_ypbpr_monspecs.mode_set = i + 3;
+                               rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i];
+                       }
+                       return 0;
+               }
+       }
+       
+       return -1;
+}
+
+static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       *mode = *(rk610_ypbpr_monspecs.mode);
+       return 0;
+}
+
+static struct rk_display_ops rk610_ypbpr_display_ops = {
+       .setenable = rk610_ypbpr_set_enable,
+       .getenable = rk610_ypbpr_get_enable,
+       .getstatus = rk610_ypbpr_get_status,
+       .getmodelist = rk610_ypbpr_get_modelist,
+       .setmode = rk610_ypbpr_set_mode,
+       .getmode = rk610_ypbpr_get_mode,
+};
+
+static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata)
+{
+       device->owner = THIS_MODULE;
+       strcpy(device->type, "YPbPr");
+       device->priority = DISPLAY_PRIORITY_YPbPr;
+       device->priv_data = devdata;
+       device->ops = &rk610_ypbpr_display_ops;
+       return 1;
+}
+
+static struct rk_display_driver display_rk610_YPbPr = {
+       .probe = rk610_display_YPbPr_probe,
+};
+
+int rk610_register_display_ypbpr(struct device *parent)
+{
+       int i;
+       
+       memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs));
+       INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist);
+       for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
+               fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist);
+       if(rk610_tv_output_status > TVOUT_CVBS_PAL) {
+               rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]);
+               rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status;
+       }
+       else {
+               rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]);
+               rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60;
+       }
+       rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL);
+       if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
+    {        
+        if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0)
+        {
+            gpio_free(RK610_LED_YPbPr_PIN);
+            dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n ");
+            return -1;
+        }
+               gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp);
+               gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
+    }
+       return 0;
+}
diff --git a/drivers/video/rockchip/tve/rk610_tv.c b/drivers/video/rockchip/tve/rk610_tv.c
deleted file mode 100644 (file)
index 83a6cec..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * rk610_tv.c 
- *
- * Driver for rockchip rk610 tv control
- *  Copyright (C) 2009 
- *
- *  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.
- *
- *
- */
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <asm/uaccess.h>
-#include "rk610_tv.h"
-#include "../../rk29_fb.h"
-
-#define DRV_NAME "rk610_tvout"
-#define RK610_I2C_RATE     100*1000
-
-volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT;
-static struct i2c_client *rk610_tv_i2c_client = NULL;
-
-int rk610_tv_wirte_reg(u8 reg, u8 data)
-{
-    int ret;
-       if(rk610_tv_i2c_client == NULL)
-               return -1;
-    ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE);
-       if (ret > 0)
-               ret = 0;
-       return ret;
-}
-
-int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode)
-{      
-       struct rk_screen *screen;
-       
-       if(modedb == NULL)
-               return -1;
-       screen =  kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
-       if(screen == NULL)
-               return -1;
-       
-       memset(screen, 0, sizeof(struct rk_screen));    
-       /* screen type & face */
-    screen->type = SCREEN_HDMI;
-       screen->mode = modedb->vmode;
-       screen->face = modedb->flag;
-       /* Screen size */
-       screen->x_res = modedb->xres;
-    screen->y_res = modedb->yres;
-
-    /* Timing */
-    screen->pixclock = modedb->pixclock;
-
-       screen->lcdc_aclk = 500000000;
-       screen->left_margin = modedb->left_margin;
-       screen->right_margin = modedb->right_margin;
-       screen->hsync_len = modedb->hsync_len;
-       screen->upper_margin = modedb->upper_margin;
-       screen->lower_margin = modedb->lower_margin;
-       screen->vsync_len = modedb->vsync_len;
-
-       /* Pin polarity */
-       if(FB_SYNC_HOR_HIGH_ACT & modedb->sync)
-               screen->pin_hsync = 1;
-       else
-               screen->pin_hsync = 0;
-       if(FB_SYNC_VERT_HIGH_ACT & modedb->sync)
-               screen->pin_vsync = 1;
-       else
-               screen->pin_vsync = 0;  
-       screen->pin_den = 0;
-       screen->pin_dclk = 0;
-
-       /* Swap rule */
-    screen->swap_rb = 0;
-    screen->swap_rg = 0;
-    screen->swap_gb = 0;
-    screen->swap_delta = 0;
-    screen->swap_dumy = 0;
-
-    /* Operation function*/
-    screen->init = NULL;
-    screen->standby = NULL;    
-    
-    switch(tv_mode)
-       {
-#ifdef CONFIG_RK610_TVOUT_CVBS
-               case TVOUT_CVBS_NTSC:
-               case TVOUT_CVBS_PAL:
-            screen->init = rk610_tv_cvbs_init;;
-               break;
-#endif
-
-#ifdef CONFIG_RK610_TVOUT_YPbPr
-               case TVOUT_YPbPr_720x480p_60:
-               case TVOUT_YPbPr_720x576p_50:
-               case TVOUT_YPbPr_1280x720p_50:
-               case TVOUT_YPbPr_1280x720p_60:
-               //case TVOUT_YPbPr_1920x1080i_50:
-               case TVOUT_YPbPr_1920x1080i_60:
-               case TVOUT_YPbPr_1920x1080p_50:
-               case TVOUT_YPbPr_1920x1080p_60:
-                       screen->init = rk610_tv_ypbpr_init;
-                       break;
-#endif
-               default:{
-                       kfree(screen);
-                       return -1;
-               }
-               break;
-       }
-       rk610_tv_output_status = tv_mode;
-       FB_Switch_Screen(screen, 1);
-       kfree(screen);
-       return 0;
-}
-
-int rk610_tv_standby(int type)
-{
-       int ret;
-
-       switch(type)
-       {
-               #ifdef CONFIG_RK610_TVOUT_CVBS
-               case RK610_TVOUT_CVBS:
-                       if(rk610_cvbs_monspecs.enable == 0)
-                               return 0;
-                       #ifdef CONFIG_RK610_TVOUT_YPbPr
-                       if(rk610_ypbpr_monspecs.enable == 1)
-                               return 0;
-                       #endif
-                       break;
-               #endif
-               #ifdef CONFIG_RK610_TVOUT_YPbPr
-               case RK610_TVOUT_YPBPR:
-                       if(rk610_ypbpr_monspecs.enable == 0)
-                               return 0;
-                       #ifdef CONFIG_RK610_TVOUT_CVBS
-                       if(rk610_cvbs_monspecs.enable == 1)
-                               return 0;
-                       #endif
-                       break;
-               #endif
-               default:
-                       break;
-       }
-
-       ret = rk610_tv_wirte_reg(TVE_POWERCR, 0);
-       if(ret < 0){
-               printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__);
-               return ret;
-       }
-       
-       ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0);
-       if(ret < 0){
-               printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__);
-               return ret;
-       }
-       return 0;
-}
-
-static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id)
-{
-       int rc = 0;
-       
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               rc = -ENODEV;
-               goto failout;
-       }
-       rk610_tv_i2c_client = client;
-
-#ifdef CONFIG_RK610_TVOUT_YPbPr
-       rk610_register_display_ypbpr(&client->dev);
-       if(rk610_tv_output_status > TVOUT_CVBS_PAL)
-               rk_display_device_enable(rk610_ypbpr_monspecs.ddev);
-#endif
-
-#ifdef CONFIG_RK610_TVOUT_CVBS
-       rk610_register_display_cvbs(&client->dev);
-       if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
-               rk_display_device_enable(rk610_cvbs_monspecs.ddev);
-#endif
-       
-    printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n");
-    return 0;
-failout:
-       kfree(client);
-       return rc;
-}
-
-static int rk610_tv_remove(struct i2c_client *client)
-{
-       return 0;
-}
-
-
-static const struct i2c_device_id rk610_tv_id[] = {
-       { DRV_NAME, 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, rk610_tv_id);
-
-static struct i2c_driver rk610_tv_driver = {
-       .driver         = {
-               .name   = DRV_NAME,
-       },
-       .id_table = rk610_tv_id,
-       .probe = rk610_tv_probe,
-       .remove = rk610_tv_remove,
-};
-
-static int __init rk610_tv_init(void)
-{
-       int ret = 0;
-       ret = i2c_add_driver(&rk610_tv_driver);
-       if(ret < 0){
-               printk("i2c_add_driver err, ret = %d\n", ret);
-       }
-       return ret;
-}
-
-static void __exit rk610_tv_exit(void)
-{
-    i2c_del_driver(&rk610_tv_driver);
-}
-
-module_init(rk610_tv_init);
-//late_initcall(rk610_tv_init);
-module_exit(rk610_tv_exit);
-
-/* Module information */
-MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output");
-MODULE_LICENSE("GPL");
-
-
diff --git a/drivers/video/rockchip/tve/rk610_tv.h b/drivers/video/rockchip/tve/rk610_tv.h
deleted file mode 100644 (file)
index ead23a8..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef _RK610_TV_H
-#define _RK610_TV_H
-#include <linux/display-sys.h>
-#include <linux/rk_fb.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#ifdef CONFIG_ARCH_RK29
-#include <mach/rk29_iomap.h>
-#endif
-#include "../screen/screen.h"
-#include "../../rk29_fb.h"
-#include <linux/mfd/rk610_core.h>
-
-#define TVE_VFCR               0x00
-       #define TVE_VFCR_ENABLE_SUBCARRIER_RESET        0 << 6
-       #define TVE_VFCR_DISABLE_SUBCARRIER_RESET       1 << 6
-       #define TVE_VFCR_VIN_RANGE_16_235                       0 << 3
-       #define TVE_VFCR_VIN_RANGE_1_254                        1 << 3
-       #define TVE_VFCR_BLACK_7_5_IRE                          0 << 2
-       #define TVE_VFCR_BLACK_0_IRE                            1 << 2
-       #define TVE_VFCR_NTSC                                           0
-       #define TVE_VFCR_PAL_M                                          1
-       #define TVE_VFCR_PAL_B_N                                        2
-       #define TVE_VFCR_PAL_NC                                         3
-
-#define TVE_VINCR              0x01
-       #define TVE_VINCR_PIX_DATA_DELAY(n)                     (n << 5)
-       #define TVE_VINCR_H_SYNC_POLARITY_NEGTIVE       0 << 4
-       #define TVE_VINCR_H_SYNC_POLARITY_POSITIVE      1 << 4
-       #define TVE_VINCR_V_SYNC_POLARITY_NEGTIVE       0 << 3
-       #define TVE_VINCR_V_SYNC_POLARITY_POSITIVE      1 << 3
-enum {
-       INPUT_FORMAT_BT601_SLAVE = 0,
-       INPUT_FORMAT_BT656,
-       INPUT_FORMAT_BT601_MASTER,
-       INPUT_FORMAT_INTERNAL_COLLOR_BAR
-};
-       #define TVE_VINCR_INPUT_FORMAT(n)                       (n << 1)
-       #define TVE_VINCR_VSYNC_FUNCTION_VSYNC          0
-       #define TVE_VINCR_VSYNC_FUNCTION_FIELD          1
-
-#define TVE_VOUTCR             0x02
-       #define TVE_VOUTCR_OUTPUT_CVBS                          0 << 6
-       #define TVE_VOUTCR_OUTPUT_YPBPR                         1 << 6
-       #define TVE_VOUTCR_OUTPUT_ENABLE_BLUE           1 << 5
-       #define TVE_VOUTCR_OUTPUT_ENABLE_BLACK          1 << 4
-       #define TVE_VOUTCR_DISABLE_CVBS_COLOR           1 << 3
-       #define TVE_VOUTCR_CVBS_Y2C_DELAY(n)                            (n << 0)
-
-#define TVE_POWERCR            0x03
-       #define TVE_PIX_CLK_INVERSE_ENABLE                      1 << 4
-       #define TVE_DAC_CLK_INVERSE_DISABLE                     1 << 3
-       #define TVE_DAC_Y_ENABLE                                        1 << 2
-       #define TVE_DAC_U_ENABLE                                        1 << 1
-       #define TVE_DAC_V_ENABLE                                        1 << 0
-
-#define TVE_HDTVCR             0x05
-       #define TVE_RESET                                                       1 << 7
-       #define TVE_FILTER(n)                                           (n << 5)
-       #define TVE_COLOR_CONVERT_REC601                        0 << 4
-       #define TVE_COLOR_CONVERT_REC709                        1 << 4
-       #define TVE_INPUT_DATA_RGB                                      0 << 3
-       #define TVE_INPUT_DATA_YUV                                      1 << 3
-       #define TVE_OUTPUT_50HZ                                         0 << 2
-       #define TVE_OUTPUT_60HZ                                         1 << 2
-       #define TVE_OUTPUT_MODE_PAL_NTSC                        0
-       #define TVE_OUTPUT_MODE_576P                            1
-       #define TVE_OUTPUT_MODE_480P                            2
-       #define TVE_OUTPUT_MODE_720P                            3
-
-#define TVE_YADJCR             0x06
-       #define TVE_OUTPUT_MODE_1080P                           1 << 6
-       #define TVE_OUTPUT_MODE_1080I                           1 << 5
-       #define TVE_Y_ADJ_VALUE(n)                                      n
-#define TVE_YCBADJCR   0x07
-#define TVE_YCRADJCR   0x08
-
-/******************* TVOUT OUTPUT TYPE **********************/
-struct rk610_monspecs {
-       struct rk_display_device        *ddev;
-       unsigned int                            enable;
-       struct fb_videomode                     *mode;
-       struct list_head                        modelist;
-       unsigned int                            mode_set;
-};
-
-enum {
-       TVOUT_CVBS_NTSC = 1,
-       TVOUT_CVBS_PAL,
-       TVOUT_YPbPr_720x480p_60,
-       TVOUT_YPbPr_720x576p_50,
-       TVOUT_YPbPr_1280x720p_50,
-       TVOUT_YPbPr_1280x720p_60,
-       //TVOUT_YPbPr_1920x1080i_50,
-       TVOUT_YPbPr_1920x1080i_60,
-       TVOUT_YPbPr_1920x1080p_50,
-       TVOUT_YPbPr_1920x1080p_60
-};
-
-#define RK610_TVOUT_DEAULT TVOUT_CVBS_NTSC
-
-enum {
-       RK610_TVOUT_CVBS = 0,
-       RK610_TVOUT_YC,
-       RK610_TVOUT_YPBPR,
-};
-
-extern volatile int rk610_tv_output_status;
-extern struct rk_display_ops rk610_display_ops;
-
-extern int FB_Switch_Screen( struct rk_screen *screen, u32 enable );
-
-extern int rk610_tv_wirte_reg(u8 reg, u8 data);
-extern int rk610_tv_standby(int type);
-extern int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode);
-extern int rk610_register_display(struct device *parent);
-
-#ifdef CONFIG_RK610_TVOUT_YPbPr
-extern int rk610_tv_ypbpr_init(void);
-extern int rk610_register_display_ypbpr(struct device *parent);
-extern struct rk610_monspecs rk610_ypbpr_monspecs;
-#endif
-
-#ifdef CONFIG_RK610_TVOUT_CVBS
-extern int rk610_tv_cvbs_init(void);
-extern int rk610_register_display_cvbs(struct device *parent);
-extern struct rk610_monspecs rk610_cvbs_monspecs;
-#endif
-
-#endif
-
diff --git a/drivers/video/rockchip/tve/rk610_tv_cvbs.c b/drivers/video/rockchip/tve/rk610_tv_cvbs.c
deleted file mode 100644 (file)
index ea0fe8a..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/display-sys.h>
-#include "rk610_tv.h"
-
-
-#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
-#define RK610_LED_CVBS_PIN     RK29_PIN4_PD3
-#else
-#define RK610_LED_CVBS_PIN     INVALID_GPIO
-#endif
-
-#ifdef USE_RGB2CCIR
-static const struct fb_videomode rk610_cvbs_mode [] = {
-               //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
-       {       "NTSC",                         60,                     720,    480,    27000000,       116,    16,             25,             14,             6,              6,              0,                      1,              OUT_P888        },
-       {       "PAL",                          50,                     720,    576,    27000000,       126,    12,             37,             6,              6,              6,              0,                      1,              OUT_P888        },
-};
-#else
-static const struct fb_videomode rk610_cvbs_mode [] = {
-               //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
-       {       "NTSC",                         60,                     720,    480,    27000000,       116,    16,             16,             3,              6,              3,              0,                      1,              OUT_CCIR656     },
-       {       "PAL",                          50,                     720,    576,    27000000,       126,    12,             19,             2,              6,              3,              0,                      1,              OUT_CCIR656     },
-};
-#endif
-
-struct rk610_monspecs rk610_cvbs_monspecs;
-
-
-int rk610_tv_cvbs_init(void)
-{
-       unsigned char TVE_Regs[9];
-       unsigned char TVE_CON_Reg;
-       int ret, i;
-       
-       rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
-
-       memset(TVE_Regs, 0, 9);
-       TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE;
-       TVE_Regs[TVE_VINCR]     =       TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
-       TVE_Regs[TVE_POWERCR]   =       TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
-       TVE_Regs[TVE_VOUTCR]    =       TVE_VOUTCR_OUTPUT_CVBS;
-       TVE_Regs[TVE_YADJCR]    =       0x17;
-       TVE_Regs[TVE_YCBADJCR]  =       0x10;
-       TVE_Regs[TVE_YCRADJCR]  =       0x10;
-       
-       switch(rk610_tv_output_status) {
-               case TVOUT_CVBS_NTSC:
-                       TVE_Regs[TVE_VFCR]              = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC;
-                       #ifdef USE_RGB2CCIR
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
-                       TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE;
-                       #else
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
-                       #endif                  
-                       break;
-               case TVOUT_CVBS_PAL:
-                       TVE_Regs[TVE_VFCR]              = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N;               
-                       #ifdef USE_RGB2CCIR
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
-                       TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE;
-                       #else
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
-                       #endif                  
-                       break;
-               default:
-                       return -1;
-       }
-       
-       for(i = 0; i < sizeof(TVE_Regs); i++){
-//             printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
-               ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
-               if(ret < 0){
-                       printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i);
-                       return ret;
-               }
-       }
-//     printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg);
-       rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
-       #ifdef USE_RGB2CCIR
-       rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01);
-       #endif
-       return 0;
-}
-
-static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable)
-{
-       if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status)
-       {
-               if(enable == 0)
-               {
-                       rk610_tv_standby(RK610_TVOUT_CVBS);
-                       rk610_cvbs_monspecs.enable = 0;
-                       if(RK610_LED_CVBS_PIN != INVALID_GPIO)
-                               gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
-               }
-               else if(enable == 1)
-               {
-                       rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set);
-                       rk610_cvbs_monspecs.enable = 1;
-                       if(RK610_LED_CVBS_PIN != INVALID_GPIO)
-                               gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW);
-               }
-       }
-       return 0;
-}
-
-static int rk610_cvbs_get_enable(struct rk_display_device *device)
-{
-       return rk610_cvbs_monspecs.enable;
-}
-
-static int rk610_cvbs_get_status(struct rk_display_device *device)
-{
-       if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
-               return 1;
-       else
-               return 0;
-}
-
-static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
-{
-       *modelist = &(rk610_cvbs_monspecs.modelist);
-       return 0;
-}
-
-static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
-{
-       int i;
-
-       for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
-       {
-               if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode))
-               {       
-                       if( ((i + 1) != rk610_tv_output_status) )
-                       {
-                               rk610_cvbs_monspecs.mode_set = i + 1;
-                               rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i];
-                       }
-                       return 0;
-               }
-       }
-       
-       return -1;
-}
-
-static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
-{
-       *mode = *(rk610_cvbs_monspecs.mode);
-       return 0;
-}
-
-static struct rk_display_ops rk610_cvbs_display_ops = {
-       .setenable = rk610_cvbs_set_enable,
-       .getenable = rk610_cvbs_get_enable,
-       .getstatus = rk610_cvbs_get_status,
-       .getmodelist = rk610_cvbs_get_modelist,
-       .setmode = rk610_cvbs_set_mode,
-       .getmode = rk610_cvbs_get_mode,
-};
-
-static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata)
-{
-       device->owner = THIS_MODULE;
-       strcpy(device->type, "TV");
-       device->priority = DISPLAY_PRIORITY_TV;
-       device->priv_data = devdata;
-       device->ops = &rk610_cvbs_display_ops;
-       return 1;
-}
-
-static struct rk_display_driver display_rk610_cvbs = {
-       .probe = rk610_display_cvbs_probe,
-};
-
-int rk610_register_display_cvbs(struct device *parent)
-{
-       int i;
-       
-       memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs));
-       INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist);
-       for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
-               fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist);
-       if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) {
-               rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]);
-               rk610_cvbs_monspecs.mode_set = rk610_tv_output_status;
-       }
-       else {
-               rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]);
-               rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
-       }
-       rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL);
-       if(RK610_LED_CVBS_PIN != INVALID_GPIO)
-    {        
-        if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0)
-        {
-            gpio_free(RK610_LED_CVBS_PIN);
-            dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n ");
-            return -1;
-        }
-               gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp);
-               gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
-    }
-       return 0;
-}
diff --git a/drivers/video/rockchip/tve/rk610_tv_ypbpr.c b/drivers/video/rockchip/tve/rk610_tv_ypbpr.c
deleted file mode 100644 (file)
index af74126..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/display-sys.h>
-#include "rk610_tv.h"
-
-
-#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
-#define RK610_LED_YPbPr_PIN    RK29_PIN4_PD5
-#else
-#define RK610_LED_YPbPr_PIN    INVALID_GPIO
-#endif
-#define E(fmt, arg...) printk("<3>!!!%s:%d: " fmt, __FILE__, __LINE__, ##arg)
-
-static const struct fb_videomode rk610_YPbPr_mode [] = {
-               //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
-       {       "YPbPr480p",            60,                     720,    480,    27000000,       55,             19,             37,             5,              64,             5,              0,                      0,              OUT_P888        },
-       {       "YPbPr576p",            50,                     720,    576,    27000000,       68,             12,             39,             5,              64,             5,              0,                      0,              OUT_P888        },
-       {       "YPbPr720p@50",         50,                     1280,   720,    74250000,       600,    0,              20,             5,              100,    5,              0,                      0,              OUT_P888        },
-       {       "YPbPr720p@60",         60,                     1280,   720,    74250000,       270,    0,              20,             5,              100,    5,              0,                      0,              OUT_P888        },
-       //{     "YPbPr1080i@50",        50,                     1920,   1080,   148500000,      620,    0,              15,             2,              100,    5,              0,                      1,              OUT_CCIR656     },
-       {       "YPbPr1080i@60",        60,                     1920,   1080,   148500000,      180,    0,              15,             2,              100,    5,              0,                      1,              OUT_CCIR656     },
-       {       "YPbPr1080p@50",        50,                     1920,   1080,   148500000,      620,    0,              36,             4,              100,    5,              0,                      0,              OUT_P888        },
-       {       "YPbPr1080p@60",        60,                     1920,   1080,   148500000,      180,    0,              36,             4,              100,    5,              0,                      0,              OUT_P888        },
-};
-
-struct rk610_monspecs rk610_ypbpr_monspecs;
-
-int rk610_tv_ypbpr_init(void)
-{
-       unsigned char TVE_Regs[9];
-       unsigned char TVE_CON_Reg;
-       int i, ret;
-       
-       rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
-       memset(TVE_Regs, 0, 9); 
-       
-       TVE_CON_Reg = 0x00;
-       
-       TVE_Regs[TVE_VINCR]     =       TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
-       TVE_Regs[TVE_POWERCR]   =       TVE_DAC_CLK_INVERSE_DISABLE | TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
-       TVE_Regs[TVE_VOUTCR]    =       TVE_VOUTCR_OUTPUT_YPBPR;
-       TVE_Regs[TVE_YADJCR]    =       0x17;
-       TVE_Regs[TVE_YCBADJCR]  =       0x10;
-       TVE_Regs[TVE_YCRADJCR]  =       0x10;
-       
-       switch(rk610_tv_output_status)
-       {
-               case TVOUT_YPbPr_720x480p_60:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_480P;
-                       break;
-               case TVOUT_YPbPr_720x576p_50:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_576P;
-                       break;
-               case TVOUT_YPbPr_1280x720p_50:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ | TVE_OUTPUT_MODE_720P;
-                       break;
-               case TVOUT_YPbPr_1280x720p_60:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ | TVE_OUTPUT_MODE_720P;
-                       break;
-               /*case TVOUT_YPbPr_1920x1080i_50:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_50HZ;
-                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080I;
-                       break;
-                       */
-               case TVOUT_YPbPr_1920x1080i_60:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_60HZ;
-                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080I;
-                       break;
-               case TVOUT_YPbPr_1920x1080p_50:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_50HZ;
-                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080P;
-                       break;
-               case TVOUT_YPbPr_1920x1080p_60:
-                       TVE_Regs[TVE_VFCR]              =       TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_NC;
-                       TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
-                       TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC709 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_60HZ;
-                       TVE_Regs[TVE_YADJCR]    |=      TVE_OUTPUT_MODE_1080P;
-                       break;
-               default:
-                       return -1;
-       }
-       
-       rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
-       
-       for(i = 0; i < sizeof(TVE_Regs); i++){
-//             printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
-               ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
-               if(ret < 0){
-                       E("rk610_tv_wirte_reg %d err!\n", i);
-                       return ret;
-               }
-       }
-       return 0;
-}
-
-static int rk610_ypbpr_set_enable(struct rk_display_device *device, int enable)
-{
-       if(rk610_ypbpr_monspecs.enable != enable || rk610_ypbpr_monspecs.mode_set != rk610_tv_output_status)
-       {
-               if(enable == 0)
-               {
-                       rk610_tv_standby(RK610_TVOUT_YPBPR);
-                       rk610_ypbpr_monspecs.enable = 0;
-                       if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
-                               gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
-               }
-               else if(enable == 1)
-               {
-                       rk610_switch_fb(rk610_ypbpr_monspecs.mode, rk610_ypbpr_monspecs.mode_set);
-                       rk610_ypbpr_monspecs.enable = 1;
-                       if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
-                               gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_LOW);
-               }
-       }
-       return 0;
-}
-
-static int rk610_ypbpr_get_enable(struct rk_display_device *device)
-{
-       return rk610_ypbpr_monspecs.enable;
-}
-
-static int rk610_ypbpr_get_status(struct rk_display_device *device)
-{
-       if(rk610_tv_output_status > TVOUT_CVBS_PAL)
-               return 1;
-       else
-               return 0;
-}
-
-static int rk610_ypbpr_get_modelist(struct rk_display_device *device, struct list_head **modelist)
-{
-       *modelist = &(rk610_ypbpr_monspecs.modelist);
-       return 0;
-}
-
-static int rk610_ypbpr_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
-{
-       int i;
-
-       for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
-       {
-               if(fb_mode_is_equal(&rk610_YPbPr_mode[i], mode))
-               {       
-                       if( (i + 3) != rk610_tv_output_status )
-                       {
-                               rk610_ypbpr_monspecs.mode_set = i + 3;
-                               rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&rk610_YPbPr_mode[i];
-                       }
-                       return 0;
-               }
-       }
-       
-       return -1;
-}
-
-static int rk610_ypbpr_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
-{
-       *mode = *(rk610_ypbpr_monspecs.mode);
-       return 0;
-}
-
-static struct rk_display_ops rk610_ypbpr_display_ops = {
-       .setenable = rk610_ypbpr_set_enable,
-       .getenable = rk610_ypbpr_get_enable,
-       .getstatus = rk610_ypbpr_get_status,
-       .getmodelist = rk610_ypbpr_get_modelist,
-       .setmode = rk610_ypbpr_set_mode,
-       .getmode = rk610_ypbpr_get_mode,
-};
-
-static int rk610_display_YPbPr_probe(struct rk_display_device *device, void *devdata)
-{
-       device->owner = THIS_MODULE;
-       strcpy(device->type, "YPbPr");
-       device->priority = DISPLAY_PRIORITY_YPbPr;
-       device->priv_data = devdata;
-       device->ops = &rk610_ypbpr_display_ops;
-       return 1;
-}
-
-static struct rk_display_driver display_rk610_YPbPr = {
-       .probe = rk610_display_YPbPr_probe,
-};
-
-int rk610_register_display_ypbpr(struct device *parent)
-{
-       int i;
-       
-       memset(&rk610_ypbpr_monspecs, 0, sizeof(struct rk610_monspecs));
-       INIT_LIST_HEAD(&rk610_ypbpr_monspecs.modelist);
-       for(i = 0; i < ARRAY_SIZE(rk610_YPbPr_mode); i++)
-               fb_add_videomode(&rk610_YPbPr_mode[i], &rk610_ypbpr_monspecs.modelist);
-       if(rk610_tv_output_status > TVOUT_CVBS_PAL) {
-               rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[rk610_tv_output_status - 3]);
-               rk610_ypbpr_monspecs.mode_set = rk610_tv_output_status;
-       }
-       else {
-               rk610_ypbpr_monspecs.mode = (struct fb_videomode *)&(rk610_YPbPr_mode[3]);
-               rk610_ypbpr_monspecs.mode_set = TVOUT_YPbPr_1280x720p_60;
-       }
-       rk610_ypbpr_monspecs.ddev = rk_display_device_register(&display_rk610_YPbPr, parent, NULL);
-       if(RK610_LED_YPbPr_PIN != INVALID_GPIO)
-    {        
-        if(gpio_request(RK610_LED_YPbPr_PIN, NULL) != 0)
-        {
-            gpio_free(RK610_LED_YPbPr_PIN);
-            dev_err(rk610_ypbpr_monspecs.ddev->dev, ">>>>>> RK610_LED_YPbPr_PIN gpio_request err \n ");
-            return -1;
-        }
-               gpio_pull_updown(RK610_LED_YPbPr_PIN,GPIOPullUp);
-               gpio_direction_output(RK610_LED_YPbPr_PIN, GPIO_HIGH);
-    }
-       return 0;
-}
diff --git a/include/dt-bindings/clock/rockchip,rk3036.h b/include/dt-bindings/clock/rockchip,rk3036.h
new file mode 100644 (file)
index 0000000..019550c
--- /dev/null
@@ -0,0 +1,155 @@
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3036_H
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3036_H
+
+#include "rockchip.h"
+
+/* pll id */
+#define RK3036_APLL_ID         0
+#define RK3036_DPLL_ID         1
+#define RK3036_GPLL_ID         2
+#define RK3036_END_PLL_ID      3
+
+/* reset id */
+#define RK3036_RST_CORE0               0
+#define RK3036_RST_CORE1               1
+#define RK3036_RST_0RES2               2
+#define RK3036_RST_0RES3               3
+#define RK3036_RST_CORE0_DBG           4
+#define RK3036_RST_CORE1_DBG           5
+#define RK3036_RST_0RES6               6
+#define RK3036_RST_0RES7               7
+#define RK3036_RST_CORE0_POR           8
+#define RK3036_RST_CORE1_POR           9
+#define RK3036_RST_0RES10              10
+#define RK3036_RST_0RES11              11
+#define RK3036_RST_L2C                 12
+#define RK3036_RST_TOPDBG              13
+#define RK3036_RST_STRC_SYS_A          14
+#define RK3036_RST_PD_CORE_NIU         15
+
+#define RK3036_RST_TIMER2              16
+#define RK3036_RST_CPUSYS_H            17
+#define RK3036_RST_1RES2               18
+#define RK3036_RST_AHB2APB_H           19
+#define RK3036_RST_TIMER3              20
+#define RK3036_RST_INTMEM              21
+#define RK3036_RST_ROM                 22
+#define RK3036_RST_PERI_NIU            23
+#define RK3036_RST_I2S                 24
+#define RK3036_RST_DDR_PLL             25
+#define RK3036_RST_GPU_DLL             26
+#define RK3036_RST_TIMER0              27
+#define RK3036_RST_TIMER1              28
+#define RK3036_RST_CORE_DLL            29
+#define RK3036_RST_EFUSE_P             30
+#define RK3036_RST_ACODEC_P            31
+
+#define RK3036_RST_GPIO0               32
+#define RK3036_RST_GPIO1               33
+#define RK3036_RST_GPIO2               34
+#define RK3036_RST_2RES3               35
+#define RK3036_RST_2RES4               36
+#define RK3036_RST_2RES5               37
+#define RK3036_RST_2RES6               38
+#define RK3036_RST_UART0               39
+#define RK3036_RST_UART1               40
+#define RK3036_RST_UART2               41
+#define RK3036_RST_2RES10              42
+#define RK3036_RST_I2C0                        43
+#define RK3036_RST_I2C1                        44
+#define RK3036_RST_I2C2                        45
+#define RK3036_RST_2RES14              46
+#define RK3036_RST_SFC                 47
+
+#define RK3036_RST_PWM0                        48
+#define RK3036_RST_3RES1               49
+#define RK3036_RST_3RES2               50
+#define RK3036_RST_DAP                 51
+#define RK3036_RST_DAP_SYS             52
+#define RK3036_RST_3RES5               53
+#define RK3036_RST_3RES6               54
+#define RK3036_RST_GRF                 55
+#define RK3036_RST_3RES8               56
+#define RK3036_RST_PERIPHSYS_A         57
+#define RK3036_RST_PERIPHSYS_H         58
+#define RK3036_RST_PERIPHSYS_P         59
+#define RK3036_RST_3RES12              60
+#define RK3036_RST_CPU_PERI            61
+#define RK3036_RST_EMEM_PERI           62
+#define RK3036_RST_USB_PERI            63
+
+#define RK3036_RST_DMA2                        64
+#define RK3036_RST_4RES1               65
+#define RK3036_RST_MAC                 66
+#define RK3036_RST_4RES3               67
+#define RK3036_RST_NANDC               68
+#define RK3036_RST_USBOTG0             69
+#define RK3036_RST_4RES6               70
+#define RK3036_RST_OTGC0               71
+#define RK3036_RST_USBOTG1             72
+#define RK3036_RST_4RES9               73
+#define RK3036_RST_OTGC1               74
+#define RK3036_RST_4RES11              75
+#define RK3036_RST_4RES12              76
+#define RK3036_RST_4RES13              77
+#define RK3036_RST_4RES14              78
+#define RK3036_RST_DDRMSCH             79
+
+#define RK3036_RST_5RES0               80
+#define RK3036_RST_MMC0                        81
+#define RK3036_RST_SDIO                        82
+#define RK3036_RST_EMMC                        83
+#define RK3036_RST_SPI0                        84
+#define RK3036_RST_5RES5               85
+#define RK3036_RST_WDT                 86
+#define RK3036_RST_5RES7               87
+#define RK3036_RST_DDRPHY              88
+#define RK3036_RST_DDRPHY_P            89
+#define RK3036_RST_DDRCTRL             90
+#define RK3036_RST_DDRCTRL_P           91
+#define RK3036_RST_5RES12              92
+#define RK3036_RST_5RES13              93
+#define RK3036_RST_5RES14              94
+#define RK3036_RST_5RES15              95
+
+#define RK3036_RST_HDMI_P              96
+#define RK3036_RST_6RES1               97
+#define RK3036_RST_6RES2               98
+#define RK3036_RST_VIO_BUS_H           99
+#define RK3036_RST_6RES4               100
+#define RK3036_RST_6RES5               101
+#define RK3036_RST_6RES6               102
+#define RK3036_RST_UTMI0               103
+#define RK3036_RST_UTMI1               104
+#define RK3036_RST_USBPOR              105
+#define RK3036_RST_6RES10              106
+#define RK3036_RST_6RES11              107
+#define RK3036_RST_6RES12              108
+#define RK3036_RST_6RES13              109
+#define RK3036_RST_6RES14              110
+#define RK3036_RST_6RES15              111
+
+#define RK3036_RST_VCODEC_A            112
+#define RK3036_RST_VCODEC_H            113
+#define RK3036_RST_VIO1_A              114
+#define RK3036_RST_HEVC                        115
+#define RK3036_RST_VCODEC_NIU_A                116
+#define RK3036_RST_LCDC1_A             117
+#define RK3036_RST_LCDC1_H             118
+#define RK3036_RST_LCDC1_D             119
+#define RK3036_RST_GPU                 120
+#define RK3036_RST_7RES9               121
+#define RK3036_RST_GPU_NIU_A           122
+#define RK3036_RST_7RES11              123
+#define RK3036_RST_7RES12              124
+#define RK3036_RST_7RES13              125
+#define RK3036_RST_7RES14              126
+#define RK3036_RST_7RES15              127
+
+#define RK3036_RST_8RES0               128
+#define RK3036_RST_8RES1               129
+#define RK3036_RST_8RES2               130
+#define RK3036_RST_DBG_P               131
+/* con8[15:4] is reserved */
+
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3036_H */
diff --git a/include/dt-bindings/clock/rockchip,rk312x.h b/include/dt-bindings/clock/rockchip,rk312x.h
new file mode 100755 (executable)
index 0000000..0af5abc
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3128_H
+#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3128_H
+
+#include "rockchip.h"
+
+/* pll id */
+#define RK3128_APLL_ID         0
+#define RK3128_DPLL_ID         1
+#define RK3128_CPLL_ID         2
+#define RK3128_GPLL_ID         3
+#define RK3128_END_PLL_ID      4
+
+/* reset id */
+#define RK3128_RST_CORE0_PO            0
+#define RK3128_RST_CORE1_PO            1
+#define RK3128_RST_CORE2_PO            2
+#define RK3128_RST_CORE3_PO            3
+#define RK3128_RST_CORE0               4
+#define RK3128_RST_CORE1               5
+#define RK3128_RST_CORE2               6
+#define RK3128_RST_CORE3               7
+#define RK3128_RST_CORE0_DBG           8
+#define RK3128_RST_CORE1_DBG           9
+#define RK3128_RST_CORE2_DBG           10
+#define RK3128_RST_CORE3_DBG           11
+#define RK3128_RST_TOPDBG              12
+#define RK3128_RST_ACLK_CORE           13
+#define RK3128_RST_STRC_SYS_A          14
+#define RK3128_RST_L2C                 15
+
+#define RK3128_RST_1RES0               16
+#define RK3128_RST_1RES1               17
+#define RK3128_RST_CPUSYS_H            18
+#define RK3128_RST_AHB2APB_H           19
+#define RK3128_RST_SPDIF               20
+#define RK3128_RST_INTMEM              21
+#define RK3128_RST_ROM                 22
+#define RK3128_RST_PERI_NIU            23
+#define RK3128_RST_I2S_2CH                     24
+#define RK3128_RST_I2S_8CH                     25
+#define RK3128_RST_GPU_PVTM                    26
+#define RK3128_RST_FUNC_PVTM                   27
+#define RK3128_RST_1RES12              28
+#define RK3128_RST_CORE_PVTM           29
+#define RK3128_RST_EFUSE_P             30
+#define RK3128_RST_ACODEC_P            31
+
+#define RK3128_RST_GPIO0               32
+#define RK3128_RST_GPIO1               33
+#define RK3128_RST_GPIO2               34
+#define RK3128_RST_GPIO3               35
+#define RK3128_RST_MIPIPHY             36
+#define RK3128_RST_2RES5               37
+#define RK3128_RST_2RES6               38
+#define RK3128_RST_UART0               39
+#define RK3128_RST_UART1               40
+#define RK3128_RST_UART2               41
+#define RK3128_RST_2RES10              42
+#define RK3128_RST_I2C0                        43
+#define RK3128_RST_I2C1                        44
+#define RK3128_RST_I2C2                        45
+#define RK3128_RST_I2C3                        46
+#define RK3128_RST_SFC                 47
+
+#define RK3128_RST_PWM0                        48
+#define RK3128_RST_3RES1               49
+#define RK3128_RST_DAP_P                       50
+#define RK3128_RST_DAP                 51
+#define RK3128_RST_DAP_SYS             52
+#define RK3128_RST_CRYPTO              53
+#define RK3128_RST_3RES6               54
+#define RK3128_RST_GRF                 55
+#define RK3128_RST_GMAC                56
+#define RK3128_RST_PERIPHSYS_A         57
+#define RK3128_RST_PERIPHSYS_H         58
+#define RK3128_RST_PERIPHSYS_P         59
+#define RK3128_RST_SMART_CARD          60
+#define RK3128_RST_CPU_PERI            61
+#define RK3128_RST_EMEM_PERI           62
+#define RK3128_RST_USB_PERI            63
+
+#define RK3128_RST_DMA2                        64
+#define RK3128_RST_4RES1               65
+#define RK3128_RST_4RES2                       66
+#define RK3128_RST_GPS         67
+#define RK3128_RST_NANDC               68
+#define RK3128_RST_USBOTG0             69
+#define RK3128_RST_4RES6               70
+#define RK3128_RST_OTGC0               71
+#define RK3128_RST_USBOTG1             72
+#define RK3128_RST_4RES9               73
+#define RK3128_RST_OTGC1               74
+#define RK3128_RST_4RES11              75
+#define RK3128_RST_4RES12              76
+#define RK3128_RST_4RES13              77
+#define RK3128_RST_4RES14              78
+#define RK3128_RST_DDRMSCH             79
+
+#define RK3128_RST_5RES0               80
+#define RK3128_RST_MMC0                        81
+#define RK3128_RST_SDIO                        82
+#define RK3128_RST_EMMC                        83
+#define RK3128_RST_SPI0                        84
+#define RK3128_RST_5RES5               85
+#define RK3128_RST_WDT                 86
+#define RK3128_RST_SARADC              87
+#define RK3128_RST_DDRPHY              88
+#define RK3128_RST_DDRPHY_P            89
+#define RK3128_RST_DDRCTRL             90
+#define RK3128_RST_DDRCTRL_P           91
+#define RK3128_RST_TSP         92
+#define RK3128_RST_TSP_CLKIN0          93
+#define RK3128_RST_USBHOST0_EHCI               94
+#define RK3128_RST_5RES15              95
+
+#define RK3128_RST_HDMI_P              96
+#define RK3128_RST_VIO_ARBI_H          97
+#define RK3128_RST_VIO_A               98
+#define RK3128_RST_VIO_BUS_H           99
+#define RK3128_RST_LCDC0_A             100
+#define RK3128_RST_LCDC0_H             101
+#define RK3128_RST_LCDC0_D             102
+#define RK3128_RST_UTMI0               103
+#define RK3128_RST_UTMI1               104
+#define RK3128_RST_USBPOR              105
+#define RK3128_RST_IEP_A               106
+#define RK3128_RST_IEP_H               107
+#define RK3128_RST_RGA_A               108
+#define RK3128_RST_RGA_H               109
+#define RK3128_RST_CIF0                110
+#define RK3128_RST_PMU         111
+
+#define RK3128_RST_VCODEC_A            112
+#define RK3128_RST_VCODEC_H            113
+#define RK3128_RST_VIO1_A              114
+#define RK3128_RST_HEVC                        115
+#define RK3128_RST_VCODEC_NIU_A                116
+#define RK3128_RST_PMU_NIU             117
+#define RK3128_RST_7RES6               118
+#define RK3128_RST_LCDC0_S             119
+#define RK3128_RST_GPU                 120
+#define RK3128_RST_7RES9               121
+#define RK3128_RST_GPU_NIU_A           122
+#define RK3128_RST_EBC_A               123
+#define RK3128_RST_EBC_H               124
+#define RK3128_RST_7RES13              125
+#define RK3128_RST_7RES14              126
+#define RK3128_RST_7RES15              127
+
+#define RK3128_RST_CORE_DBG            128
+#define RK3128_RST_DBG_P               129
+#define RK3128_RST_TIMER0              130
+#define RK3128_RST_TIMER1              131
+#define RK3128_RST_TIMER2              132
+#define RK3128_RST_TIMER3              133
+#define RK3128_RST_TIMER4              134
+#define RK3128_RST_TIMER5              135
+#define RK3128_RST_VIO_H2P             136
+#define RK3128_RST_VIO_MIPI_DSI                137
+#define RK3128_RST_8RES10              138
+#define RK3128_RST_8RES11              139
+#define RK3128_RST_8RES12              140
+#define RK3128_RST_8RES13              141
+#define RK3128_RST_8RES14              142
+#define RK3128_RST_8RES15              143
+
+#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3128_H */
index b00ccd571df7877d1901dcc2d894d02fa1c09b43..8b9bc21e0e7e36a44a9df93754e563f89583b1bd 100644 (file)
@@ -40,6 +40,9 @@
 #define CLK_PLL_3188PLUS_APLL  BIT(3)
 #define CLK_PLL_3288_APLL      BIT(4)
 #define CLK_PLL_3188PLUS_AUTO  BIT(5)
+#define CLK_PLL_3036_APLL      BIT(6)
+#define CLK_PLL_3036PLUS_AUTO  BIT(7)
+#define CLK_PLL_312XPLUS       BIT(8)
 
 
 /* rate_ops index */
diff --git a/include/dt-bindings/pinctrl/rockchip-rk3036.h b/include/dt-bindings/pinctrl/rockchip-rk3036.h
new file mode 100644 (file)
index 0000000..01bf49e
--- /dev/null
@@ -0,0 +1,266 @@
+#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_RK3036_H__
+#define __DT_BINDINGS_ROCKCHIP_PINCTRL_RK3036_H__
+
+        /* GPIO0_A */
+        #define GPIO0_A0 0x0a00
+        #define I2C0_SCL 0x0a01
+        #define PWM1 0x0a02
+
+        #define GPIO0_A1 0x0a10
+        #define I2C0_SDA 0x0a11
+        #define PWM2 0x0a12
+
+        #define GPIO0_A2 0x0a20
+        #define I2C1_SCL 0x0a21
+
+        #define GPIO0_A3 0x0a30
+        #define I2C1_SDA 0x0a31
+
+
+        /* GPIO0_B */
+        #define GPIO0_B0 0x0b00
+        #define MMC1_CMD 0x0b01
+        #define I2S1_SDO 0x0b02
+
+        #define GPIO0_B1 0x0b10
+        #define MMC1_CLKOUT 0x0b11
+        #define I2S1_MCLK 0x0b12
+
+        #define GPIO0_B3 0x0b30
+        #define MMC1_D0 0x0b31
+        #define I2S1_LRCKRX 0x0b32
+
+        #define GPIO0_B4 0x0b40
+        #define MMC1_D1 0x0b41
+        #define I2S1_LRCKTX 0x0b42
+
+        #define GPIO0_B5 0x0b50
+        #define MMC1_D2 0x0b51
+        #define I2S1_SDI 0x0b52
+
+        #define GPIO0_B6 0x0b60
+        #define MMC1_D3 0x0b61
+        #define I2S1_SCLK 0x0b62
+
+
+        /* GPIO0_C */
+        #define GPIO0_C0 0x0c00
+        #define UART0_SOUT 0x0c01
+
+        #define GPIO0_C1 0x0c10
+        #define UART0_SIN 0x0c11
+
+        #define GPIO0_C2 0x0c20
+        #define UART0_RTSN 0x0c21
+
+        #define GPIO0_C3 0x0c30
+        #define UART0_CTSN 0x0c31
+
+        #define GPIO0_C4 0x0c40
+        #define DRIVE_VBUS 0x0c41
+
+
+        /* GPIO0_D */
+        #define GPIO0_D2 0x0d20
+        #define PWM0 0x0d21
+
+        #define GPIO0_D3 0x0d30
+        #define PWM3(IR) 0x0d31
+
+        #define GPIO0_D4 0x0d40
+        #define SPDIF_TX 0x0d41
+
+
+        /* GPIO1_A */
+        #define GPIO1_A0 0x1a00
+        #define I2S0_MCLK 0x1a01
+
+        #define GPIO1_A1 0x1a10
+        #define I2S0_SCLK 0x1a11
+
+        #define GPIO1_A2 0x1a20
+        #define I2S0_LRCKRX 0x1a21
+        #define PWM1_0 0x1a22
+
+        #define GPIO1_A3 0x1a30
+        #define I2S0_LRCKTX 0x1a31
+
+        #define GPIO1_A4 0x1a40
+        #define I2S0_SDO 0x1a41
+
+        #define GPIO1_A5 0x1a50
+        #define I2S0_SDI 0x1a51
+
+
+        /* GPIO1_B */
+        #define GPIO1_B0 0x1b00
+        #define HDMI_CEC 0x1b01
+
+        #define GPIO1_B1 0x1b10
+        #define HDMI_SDA 0x1b11
+
+        #define GPIO1_B2 0x1b20
+        #define HDMI_SCL 0x1b21
+
+        #define GPIO1_B3 0x1b30
+        #define HDMI_HPD 0x1b31
+
+        #define GPIO1_B7 0x1b70
+        #define MMC0_CMD 0x1b71
+
+
+        /* GPIO1_C */
+        #define GPIO1_C0 0x1c00
+        #define MMC0_CLKOUT 0x1c01
+
+        #define GPIO1_C1 0x1c10
+        #define MMC0_DETN 0x1c11
+
+        #define GPIO1_C2 0x1c20
+        #define MMC0_D0 0x1c21
+        #define UART2_SIN 0x1c22
+
+        #define GPIO1_C3 0x1c30
+        #define MMC0_D1 0x1c31
+        #define UART2_SOUT 0x1c32
+
+        #define GPIO1_C4 0x1c40
+        #define MMC0_D2 0x1c41
+        #define JTAG_TCK 0x1c42
+
+        #define GPIO1_C5 0x1c50
+        #define MMC0_D3 0x1c51
+        #define JTAG_TMS 0x1c52
+
+
+        /* GPIO1_D */
+        #define GPIO1_D0 0x1d00
+        #define NAND_D0 0x1d01
+        #define EMMC_D0 0x1d02
+        #define SFC_SIO0 0x1d03
+
+        #define GPIO1_D1 0x1d10
+        #define NAND_D1 0x1d11
+        #define EMMC_D1 0x1d12
+        #define SFC_SIO1 0x1d13
+
+        #define GPIO1_D2 0x1d20
+        #define NAND_D2 0x1d21
+        #define EMMC_D2 0x1d22
+        #define SFC_SIO2 0x1d23
+
+        #define GPIO1_D3 0x1d30
+        #define NAND_D3 0x1d31
+        #define EMMC_D3 0x1d32
+        #define SFC_SIO3 0x1d33
+
+        #define GPIO1_D4 0x1d40
+        #define NAND_D4 0x1d41
+        #define EMMC_D4 0x1d42
+        #define SPI0_RXD 0x1d43
+
+        #define GPIO1_D5 0x1d50
+        #define NAND_D5 0x1d51
+        #define EMMC_D5 0x1d52
+        #define SPI0_TXD 0x1d53
+
+        #define GPIO1_D6 0x1d60
+        #define NAND_D6 0x1d61
+        #define EMMC_D6 0x1d62
+        #define SPI0_CS0 0x1d63
+
+        #define GPIO1_D7 0x1d70
+        #define NAND_D7 0x1d71
+        #define EMMC_D7 0x1d72
+        #define SPI0_CS1 0x1d73
+
+
+        /* GPIO2_A */
+        #define GPIO2_A0 0x2a00
+        #define NAND_ALE 0x2a01
+        #define SPI0_CLK 0x2a02
+
+        #define GPIO2_A1 0x2a10
+        #define NAND_CLE 0x2a11
+        #define EMMC_CLKOUT 0x2a12
+
+        #define GPIO2_A2 0x2a20
+        #define NAND_WRN 0x2a21
+        #define SFC_CSN0 0x2a22
+
+        #define GPIO2_A3 0x2a30
+        #define NAND_RDN 0x2a31
+        #define SFC_CSN1 0x2a32
+
+        #define GPIO2_A4 0x2a40
+        #define NAND_RDY 0x2a41
+        #define EMMC_CMD 0x2a42
+        #define SFC_CLK 0x2a43
+
+        #define GPIO2_A6 0x2a60
+        #define NAND_CS0 0x2a61
+
+        #define GPIO2_A7 0x2a70
+        #define TESTCLK_OUT 0x2a71
+
+
+        /* GPIO2_B */
+        #define GPIO2_B2 0x2b20
+        #define MAC_CRS 0x2b21
+
+        #define GPIO2_B4 0x2b40
+        #define MAC_MDIO 0x2b41
+
+        #define GPIO2_B5 0x2b50
+        #define MAC_TXEN 0x2b51
+
+        #define GPIO2_B6 0x2b60
+        #define MAC_CLKOUT 0x2b61
+        #define MAC_CLKIN 0x2b62
+
+        #define GPIO2_B7 0x2b70
+        #define MAC_RXER 0x2b71
+
+
+        /* GPIO2_C */
+        #define GPIO2_C0 0x2c00
+        #define MAC_RXD1 0x2c01
+
+        #define GPIO2_C1 0x2c10
+        #define MAC_RXD0 0x2c11
+
+        #define GPIO2_C2 0x2c20
+        #define MAC_TXD1 0x2c21
+
+        #define GPIO2_C3 0x2c30
+        #define MAC_TXD0 0x2c31
+
+        #define GPIO2_C4 0x2c40
+        #define I2C2_SDA 0x2c41
+
+        #define GPIO2_C5 0x2c50
+        #define I2C2_SCL 0x2c51
+
+        #define GPIO2_C6 0x2c60
+        #define UART1_SIN 0x2c61
+
+        #define GPIO2_C7 0x2c70
+        #define UART1_SOUT 0x2c71
+        #define TESTCLK_OUT1 0x2c72
+
+
+        /* GPIO2_D */
+        #define GPIO2_D1 0x2d10
+        #define MAC_MDC 0x2d11
+
+        #define GPIO2_D4 0x2d40
+        #define I2S0_SDO3 0x2d41
+
+        #define GPIO2_D5 0x2d50
+        #define I2S0_SDO2 0x2d51
+
+        #define GPIO2_D6 0x2d60
+        #define I2S0_SDO1 0x2d61
+
+
+#endif
diff --git a/include/dt-bindings/pinctrl/rockchip-rk312x.h b/include/dt-bindings/pinctrl/rockchip-rk312x.h
new file mode 100755 (executable)
index 0000000..4bd5a16
--- /dev/null
@@ -0,0 +1,383 @@
+#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_RK312X_H__
+#define __DT_BINDINGS_ROCKCHIP_PINCTRL_RK312X_H__
+
+/* GPIO0_A */
+#define GPIO0_A0 0x0a00
+#define I2C0_SCL 0x0a01
+
+#define GPIO0_A1 0x0a10
+#define I2C0_SDA 0x0a11
+
+#define GPIO0_A2 0x0a20
+#define I2C1_SCL 0x0a21
+
+#define GPIO0_A3 0x0a30
+#define I2C1_SDA 0x0a31
+#define MMC1_CMD 0x0a32
+
+#define GPIO0_A6 0x0a60
+#define I2C3_SCL 0x0a61
+#define HDMI_DSCL 0x0a62
+
+#define GPIO0_A7 0x0a70
+#define I2C3_SDA 0x0a71
+#define HDMI_DSDA 0x0a72
+
+
+/* GPIO0_B */
+#define GPIO0_B0 0x0b00
+#define I2S0_MCLK_MUX0 0x0b01
+
+#define GPIO0_B1 0x0b10
+#define I2S0_SCLK_MUX0 0x0b11
+#define SPI0_CLK_MUX2 0x0b12
+
+#define GPIO0_B3 0x0b30
+#define I2S0_LRCKRX_MUX0 0x0b31
+#define SPI0_TXD_MUX2 0x0b32
+
+#define GPIO0_B4 0x0b40
+#define I2S0_LRCKTX_MUX0 0x0b41
+
+#define GPIO0_B5 0x0b50
+#define I2S0_SDO_MUX0 0x0b51
+#define SPI0_RXD_MUX2 0x0b52
+
+#define GPIO0_B6 0x0b60
+#define I2S0_SDI_MUX0 0x0b61
+#define SPI0_CS0_MUX2 0x0b62
+
+#define GPIO0_B7 0x0b70
+#define HDMI_HPD 0x0b71
+
+
+/* GPIO0_C */
+#define GPIO0_C1 0x0c10
+#define SC_IO 0x0c11
+#define UART0_RTSN 0x0c12
+
+#define GPIO0_C4 0x0c40
+#define HDMI_CEC 0x0c41
+
+#define GPIO0_C7 0x0c70
+#define NAND_CS1 0x0c71
+
+
+/* GPIO0_D */
+#define GPIO0_D0 0x0d00
+#define UART2_RTSN 0x0d01
+#define PMIC_SLEEP_MUX0 0x0d02
+
+#define GPIO0_D1 0x0d10
+#define UART2_CTSN 0x0d11
+
+#define GPIO0_D2 0x0d20
+#define PWM0 0x0d21
+
+#define GPIO0_D3 0x0d30
+#define PWM1 0x0d31
+
+#define GPIO0_D4 0x0d40
+#define PWM2 0x0d41
+
+#define GPIO0_D6 0x0d60
+#define MMC1_PWREN 0x0d61
+
+
+/* GPIO1_A */
+#define GPIO1_A0 0x1a00
+#define I2S0_MCLK_MUX1 0x1a01
+#define SDMMC_CLKOUT 0x1a02
+#define XIN32K 0x1a03
+
+#define GPIO1_A1 0x1a10
+#define I2S0_SCLK_MUX1 0x1a11
+#define SDMMC_DATA0 0x1a12
+#define PMIC_SLEEP_MUX1 0x1a13
+
+#define GPIO1_A2 0x1a20
+#define I2S0_LRCKRX_MUX1 0x1a21
+#define SDMMC_DATA1 0x1a22
+
+#define GPIO1_A3 0x1a30
+#define I2S0_LRCKTX_MUX1 0x1a31
+
+#define GPIO1_A4 0x1a40
+#define I2S0_SDO_MUX1 0x1a41
+#define SDMMC_DATA2 0x1a42
+
+#define GPIO1_A5 0x1a50
+#define I2S0_SDI_MUX1 0x1a51
+#define SDMMC_DATA3 0x1a52
+
+#define GPIO1_A7 0x1a70
+#define MMC0_WRPRT 0x1a71
+
+
+/* GPIO1_B */
+#define GPIO1_B0 0x1b00
+#define SPI0_CLK_MUX0 0x1b01
+#define UART1_CTSN 0x1b02
+
+#define GPIO1_B1 0x1b10
+#define SPI0_TXD_MUX0 0x1b11
+#define UART1_SOUT 0x1b12
+
+#define GPIO1_B2 0x1b20
+#define SPI0_RXD_MUX0 0x1b21
+#define UART1_SIN 0x1b22
+
+#define GPIO1_B3 0x1b30
+#define SPI0_CS0_MUX0 0x1b31
+#define UART1_RTSN 0x1b32
+
+#define GPIO1_B4 0x1b40
+#define SPI0_CS1_MUX0 0x1b41
+
+#define GPIO1_B6 0x1b60
+#define MMC0_PWREN 0x1b61
+
+#define GPIO1_B7 0x1b70
+#define MMC0_CMD 0x1b71
+
+
+/* GPIO1_C */
+#define GPIO1_C0 0x1c00
+#define MMC0_CLKOUT 0x1c01
+
+#define GPIO1_C1 0x1c10
+#define MMC0_DETN 0x1c11
+
+#define GPIO1_C2 0x1c20
+#define MMC0_D0 0x1c21
+#define UART2_SOUT 0x1c22
+
+#define GPIO1_C3 0x1c30
+#define MMC0_D1 0x1c31
+#define UART2_SIN 0x1c32
+
+#define GPIO1_C4 0x1c40
+#define MMC0_D2 0x1c41
+#define JTAG_TCK 0x1c42
+
+#define GPIO1_C5 0x1c50
+#define MMC0_D3 0x1c51
+#define JTAG_TMS 0x1c52
+
+#define GPIO1_C6 0x1c60
+#define NAND_CS2 0x1c61
+#define EMMC_CMD_MUX0 0x1c62
+
+#define GPIO1_C7 0x1c70
+#define NAND_CS3 0x1c71
+#define EMMC_RSTNOUT 0x1c72
+
+
+/* GPIO1_D */
+#define GPIO1_D0 0x1d00
+#define NAND_D0 0x1d01
+#define EMMC_D0 0x1d02
+#define SFC_D0 0x1d03
+
+#define GPIO1_D1 0x1d10
+#define NAND_D1 0x1d11
+#define EMMC_D1 0x1d12
+#define SFC_D1 0x1d13
+
+#define GPIO1_D2 0x1d20
+#define NAND_D2 0x1d21
+#define EMMC_D2 0x1d22
+#define SFC_D2 0x1d23
+
+#define GPIO1_D3 0x1d30
+#define NAND_D3 0x1d31
+#define EMMC_D3 0x1d32
+#define SFC_D3 0x1d33
+
+#define GPIO1_D4 0x1d40
+#define NAND_D4 0x1d41
+#define EMMC_D4 0x1d42
+#define SPI0_RXD_MUX1 0x1d43
+
+#define GPIO1_D5 0x1d50
+#define NAND_D5 0x1d51
+#define EMMC_D5 0x1d52
+#define SPI0_TXD_MUX1 0x1d53
+
+#define GPIO1_D6 0x1d60
+#define NAND_D6 0x1d61
+#define EMMC_D6 0x1d62
+#define SPI0_CS0_MUX1 0x1d63
+
+#define GPIO1_D7 0x1d70
+#define NAND_D7 0x1d71
+#define EMMC_D7 0x1d72
+#define SPI0_CS1_MUX1 0x1d73
+
+
+/* GPIO2_A */
+#define GPIO2_A0 0x2a00
+#define NAND_ALE 0x2a01
+#define SPI0_CLK_MUX1 0x2a02
+
+#define GPIO2_A1 0x2a10
+#define NAND_CLE 0x2a11
+
+#define GPIO2_A2 0x2a20
+#define NAND_WRN 0x2a21
+#define SFC_CSN0 0x2a22
+
+#define GPIO2_A3 0x2a30
+#define NAND_RDN 0x2a31
+#define SFC_CSN1 0x2a32
+
+#define GPIO2_A4 0x2a40
+#define NAND_RDY 0x2a41
+#define EMMC_CMD_MUX1 0x2a42
+#define SFC_CLK 0x2a43
+
+#define GPIO2_A5 0x2a50
+#define NAND_WP 0x2a51
+#define EMMC_PWREN 0x2a52
+
+#define GPIO2_A6 0x2a60
+#define NAND_CS0 0x2a61
+
+#define GPIO2_A7 0x2a70
+#define NAND_DQS 0x2a71
+#define EMMC_CLKOUT 0x2a72
+
+
+/* GPIO2_B */
+#define GPIO2_B0 0x2b00
+#define LCDC0_DCLK 0x2b01
+#define EBC_SDCLK 0x2b02
+#define GMAC_RXDV 0x2b03
+
+#define GPIO2_B1 0x2b10
+#define LCDC0_HSYNC 0x2b11
+#define EBC_SDLE 0x2b12
+#define GMAC_TXCLK 0x2b13
+
+#define GPIO2_B2 0x2b20
+#define LCDC0_VSYNC 0x2b21
+#define EBC_SDOE 0x2b22
+#define GMAC_CRS 0x2b23
+
+#define GPIO2_B3 0x2b30
+#define LCDC0_DEN 0x2b31
+#define EBC_GDCLK 0x2b32
+#define GMAC_RXCLK 0x2b33
+
+#define GPIO2_B4 0x2b40
+#define LCDC0_D10 0x2b41
+#define EBC_SDCE2 0x2b42
+#define GMAC_MDIO 0x2b43
+
+#define GPIO2_B5 0x2b50
+#define LCDC0_D11 0x2b51
+#define EBC_SDCE3 0x2b52
+#define GMAC_TXEN 0x2b53
+
+#define GPIO2_B6 0x2b60
+#define LCDC0_D12 0x2b61
+#define EBC_SDCE4 0x2b62
+#define GMAC_CLK 0x2b63
+
+#define GPIO2_B7 0x2b70
+#define LCDC0_D13 0x2b71
+#define EBC_SDCE5 0x2b72
+#define GMAC_RXER 0x2b73
+
+
+/* GPIO2_C */
+#define GPIO2_C0 0x2c00
+#define LCDC0_D14 0x2c01
+#define EBC_VCOM 0x2c02
+#define GMAC_RXD1 0x2c03
+
+#define GPIO2_C1 0x2c10
+#define LCDC0_D15 0x2c11
+#define EBC_GDOE 0x2c12
+#define GMAC_RXD0 0x2c13
+
+#define GPIO2_C2 0x2c20
+#define LCDC0_D16 0x2c21
+#define EBC_GDSP 0x2c22
+#define GMAC_TXD1 0x2c23
+
+#define GPIO2_C3 0x2c30
+#define LCDC0_D17 0x2c31
+#define EBC_GDPWR0 0x2c32
+#define GMAC_TXD0 0x2c33
+
+#define GPIO2_C4 0x2c40
+#define LCDC0_D18 0x2c41
+#define EBC_GDRL 0x2c42
+#define I2C2_SDA 0x2c43
+#define GMAC_RXD3 0x2c44
+
+#define GPIO2_C5 0x2c50
+#define LCDC0_D19 0x2c51
+#define EBC_SDSHR 0x2c52
+#define I2C2_SCL 0x2c53
+#define GMAC_RXD2 0x2c54
+
+#define GPIO2_C6 0x2c60
+#define LCDC0_D20 0x2c61
+#define EBC_BORDER0 0x2c62
+#define GPS_SIGN 0x2c63
+#define GMAC_TXD2 0x2c64
+
+#define GPIO2_C7 0x2c70
+#define LCDC0_D21 0x2c71
+#define EBC_BORDER1 0x2c72
+#define GPS_MAG 0x2c73
+#define GMAC_TXD3 0x2c74
+
+
+/* GPIO2_D */
+#define GPIO2_D0 0x2d00
+#define LCDC0_D22 0x2d01
+#define EBC_GDPWR1 0x2d02
+#define GPS_CLK 0x2d03
+#define GMAC_COL 0x2d04
+
+#define GPIO2_D1 0x2d10
+#define LCDC0_D23 0x2d11
+#define EBC_GDPWR2 0x2d12
+#define GMAC_MDC 0x2d13
+
+#define GPIO2_D2 0x2d20
+#define SC_RST 0x2d21
+#define UART0_SOUT 0x2d22
+
+#define GPIO2_D3 0x2d30
+#define SC_CLK 0x2d31
+#define UART0_SIN 0x2d32
+
+#define GPIO2_D5 0x2d50
+#define SC_DET 0x2d51
+#define UART0_CTSN 0x2d52
+
+
+/* GPIO3_A */
+/* GPIO3_B */
+#define GPIO3_B3 0x3b30
+#define TESTCLK_OUT 0x3b31
+
+
+/* GPIO3_C */
+#define GPIO3_C1 0x3c10
+#define OTG_DRVVBUS 0x3c11
+
+
+/* GPIO3_D */
+#define GPIO3_D2 0x3d20
+#define PWM_IRIN 0x3d21
+
+#define GPIO3_D3 0x3d30
+#define SPDIF_TX 0x3d31
+
+
+#endif
index faf5fc4646a02fed704d802bfc67db29ae6d7de3..976424b3fbdce0c0b7f972769396781405d3199c 100755 (executable)
 #define RK3188_PULL_PINS_PER_REG       8
 #define RK3188_PULL_BANK_STRIDE                16
 
+#define RK3036_PULL_BITS_PER_PIN       1
+#define RK3036_PULL_PINS_PER_REG       16
+#define RK3036_PULL_BANK_STRIDE                8
+
+#define RK312X_PULL_BITS_PER_PIN       1
+#define RK312X_PULL_PINS_PER_REG       16
+#define RK312X_PULL_BANK_STRIDE                8
+
 
 /*warning:don not chang the following value*/
 #define VALUE_PULL_NORMAL      0
 #define VALUE_PULL_DOWN                2
 #define VALUE_PULL_KEEP                3
 #define VALUE_PULL_DISABLE     4 //don't set and keep pull default
+#define VALUE_PULL_DEFAULT     4 //don't set and keep pull default
+
+
+//for rk2928,rk3036
+#define VALUE_PULL_UPDOWN_DISABLE              0
+#define VALUE_PULL_UPDOWN_ENABLE               1
 
 #define VALUE_VOL_DEFAULT      0
 #define VALUE_VOL_3V3          0
index 8c088b80dba2c33e54d5fdceae8995c3555bcb2a..d568335b3dd640696a24721a6372f029fffd4ec1 100755 (executable)
@@ -151,13 +151,10 @@ struct dw_mci {
        const struct dw_mci_dma_ops     *dma_ops;
 #ifdef CONFIG_MMC_DW_IDMAC
        unsigned int            ring_size;
-#else
-       struct dw_mci_dma_data  *dma_data;
-#endif
-
-#ifdef CONFIG_MMC_DW_EDMAC
         struct dw_mci_dma_slave *dms;
        void                    *phy_regs;
+#else
+       struct dw_mci_dma_data  *dma_data;
 #endif
        u32                     cmd_status;
        u32                     data_status;
index 37da53946f80d740fa2e1fa6cce80770f77d4be1..60c8e558a3ab3ae6ce7f15d566a5fd083714f1c7 100755 (executable)
 
 //#define USE_ION_MMU 1
 #if defined(CONFIG_ION_ROCKCHIP)
-extern struct ion_client *rockchip_ion_client_create(const char * name);
+extern struct ion_client *rockchip_ion_client_create(const char *name);
 #endif
 
 extern int rk_fb_poll_prmry_screen_vblank(void);
@@ -342,6 +342,7 @@ struct rk_lcdc_win_area{
 struct rk_lcdc_win {
        char name[5];
        int id;
+       u32 logicalstate;
        bool state;             /*on or off*/
        bool last_state;                /*on or off*/
        u32 pseudo_pal[16];
@@ -395,47 +396,50 @@ struct rk_fb_trsm_ops {
 };
 
 struct rk_lcdc_drv_ops {
-       int (*open) (struct rk_lcdc_driver * dev_drv, int layer_id, bool open);
+       int (*open) (struct rk_lcdc_driver *dev_drv, int layer_id, bool open);
        int (*win_direct_en)(struct rk_lcdc_driver *dev_drv, int win_id, int en);
-       int (*init_lcdc) (struct rk_lcdc_driver * dev_drv);
-       int (*ioctl) (struct rk_lcdc_driver * dev_drv, unsigned int cmd,
+       int (*init_lcdc) (struct rk_lcdc_driver *dev_drv);
+       int (*ioctl) (struct rk_lcdc_driver *dev_drv, unsigned int cmd,
                      unsigned long arg, int layer_id);
-       int (*suspend) (struct rk_lcdc_driver * dev_drv);
-       int (*resume) (struct rk_lcdc_driver * dev_drv);
-       int (*blank) (struct rk_lcdc_driver * dev_drv, int layer_id,
+       int (*suspend) (struct rk_lcdc_driver *dev_drv);
+       int (*resume) (struct rk_lcdc_driver *dev_drv);
+       int (*blank) (struct rk_lcdc_driver *dev_drv, int layer_id,
                      int blank_mode);
-       int (*set_par) (struct rk_lcdc_driver * dev_drv, int layer_id);
-       int (*pan_display) (struct rk_lcdc_driver * dev_drv, int layer_id);
+       int (*set_par) (struct rk_lcdc_driver *dev_drv, int layer_id);
+       int (*pan_display) (struct rk_lcdc_driver *dev_drv, int layer_id);
        int (*direct_set_addr)(struct rk_lcdc_driver *drv, int win_id, u32 addr);
-       int (*lcdc_reg_update) (struct rk_lcdc_driver * dev_drv);
-       ssize_t(*get_disp_info) (struct rk_lcdc_driver * dev_drv, char *buf,
+       int (*lcdc_reg_update) (struct rk_lcdc_driver *dev_drv);
+       ssize_t(*get_disp_info) (struct rk_lcdc_driver *dev_drv, char *buf,
                                  int layer_id);
-       int (*load_screen) (struct rk_lcdc_driver * dev_drv, bool initscreen);
-       int (*get_win_state) (struct rk_lcdc_driver * dev_drv, int layer_id);
-       int (*ovl_mgr) (struct rk_lcdc_driver * dev_drv, int swap, bool set);   //overlay manager
-       int (*fps_mgr) (struct rk_lcdc_driver * dev_drv, int fps, bool set);
-       int (*fb_get_win_id) (struct rk_lcdc_driver * dev_drv, const char *id); //find layer for fb
-       int (*fb_win_remap) (struct rk_lcdc_driver * dev_drv,
+       int (*load_screen) (struct rk_lcdc_driver *dev_drv, bool initscreen);
+       int (*get_win_state) (struct rk_lcdc_driver *dev_drv, int layer_id);
+       int (*ovl_mgr) (struct rk_lcdc_driver *dev_drv, int swap, bool set);    /*overlay manager*/
+       int (*fps_mgr) (struct rk_lcdc_driver *dev_drv, int fps, bool set);
+       int (*fb_get_win_id) (struct rk_lcdc_driver *dev_drv, const char *id);  /*find layer for fb*/
+       int (*fb_win_remap) (struct rk_lcdc_driver *dev_drv,
                               enum fb_win_map_order order);
-       int (*set_dsp_lut) (struct rk_lcdc_driver * dev_drv, int *lut);
-       int (*read_dsp_lut) (struct rk_lcdc_driver * dev_drv, int *lut);
-       int (*lcdc_hdmi_process) (struct rk_lcdc_driver * dev_drv, int mode);   //some lcdc need to some process in hdmi mode
+       int (*set_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut);
+       int (*read_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut);
+       int (*lcdc_hdmi_process) (struct rk_lcdc_driver *dev_drv, int mode);    /*some lcdc need to some process in hdmi mode*/
        int (*set_irq_to_cpu)(struct rk_lcdc_driver *dev_drv,int enable);
-       int (*poll_vblank) (struct rk_lcdc_driver * dev_drv);
-       int (*lcdc_rst) (struct rk_lcdc_driver * dev_drv);
-       int (*dpi_open) (struct rk_lcdc_driver * dev_drv, bool open);
-       int (*dpi_win_sel) (struct rk_lcdc_driver * dev_drv, int layer_id);
-       int (*dpi_status) (struct rk_lcdc_driver * dev_drv);
-       int (*get_dsp_addr)(struct rk_lcdc_driver * dev_drv,unsigned int *dsp_addr);
-       int (*set_dsp_cabc) (struct rk_lcdc_driver * dev_drv, int mode);
+       int (*poll_vblank) (struct rk_lcdc_driver *dev_drv);
+       int (*lcdc_rst) (struct rk_lcdc_driver *dev_drv);
+       int (*dpi_open) (struct rk_lcdc_driver *dev_drv, bool open);
+       int (*dpi_win_sel) (struct rk_lcdc_driver *dev_drv, int layer_id);
+       int (*dpi_status) (struct rk_lcdc_driver *dev_drv);
+       int (*get_dsp_addr)(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr);
+       int (*set_dsp_cabc) (struct rk_lcdc_driver *dev_drv, int mode);
        int (*set_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue);
        int (*set_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value);
        int (*get_dsp_bcsh_hue) (struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode);
        int (*get_dsp_bcsh_bcs)(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode);
        int (*open_bcsh)(struct rk_lcdc_driver *dev_drv, bool open);
-       int (*dump_reg) (struct rk_lcdc_driver * dev_drv);
-       int (*mmu_en) (struct rk_lcdc_driver * dev_drv);
-       int (*cfg_done) (struct rk_lcdc_driver * dev_drv);
+        int (*set_screen_scaler) (struct rk_lcdc_driver *dev_drv, struct rk_screen *screen, bool enable);
+       int (*dump_reg) (struct rk_lcdc_driver *dev_drv);
+       int (*mmu_en) (struct rk_lcdc_driver *dev_drv);
+       int (*cfg_done) (struct rk_lcdc_driver *dev_drv);
+       int (*set_overscan) (struct rk_lcdc_driver *dev_drv,
+                            struct overscan *overscan);
 };
 
 struct rk_fb_area_par {
@@ -546,17 +550,22 @@ struct rk_lcdc_driver {
        char fb1_win_id;
        char fb2_win_id;
        char fb3_win_id;
+       
        char mmu_dts_name[40];
+       struct device *mmu_dev;
        int iommu_enabled;
+
        struct rk_fb_reg_area_data reg_area_data;
        struct mutex fb_win_id_mutex;
 
-       struct completion frame_done;   //sync for pan_display,whe we set a new frame address to lcdc register,we must make sure the frame begain to display
-       spinlock_t cpl_lock;    //lock for completion  frame done
+       struct completion frame_done;   /*sync for pan_display,whe we set a new
+                                         frame address to lcdc register,we must
+                                         make sure the frame begain to display*/
+       spinlock_t cpl_lock;    /*lock for completion  frame done */
        int first_frame;
        struct rk_fb_vsync vsync_info;
        struct rk_fb_frame_time frame_time;
-       int wait_fs;            //wait for new frame start in kernel
+       int wait_fs;            /*wait for new frame start in kernel */
        struct sw_sync_timeline *timeline;
        int                     timeline_max;
        int                     suspend_flag;
@@ -576,7 +585,7 @@ struct rk_lcdc_driver {
 #ifdef CONFIG_DRM_ROCKCHIP
        void (*irq_call_back)(struct rk_lcdc_driver *driver);
 #endif
-
+       struct overscan overscan;
 };
 
 /*disp_mode: dual display mode
@@ -597,14 +606,14 @@ struct rk_fb {
        int num_lcdc;
 
 #if defined(CONFIG_ION_ROCKCHIP)
-       struct ion_client * ion_client;
+       struct ion_client *ion_client;
 #endif
 
 
 };
 
 extern int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type);
-extern struct rk_fb_trsm_ops * rk_fb_trsm_ops_get(int type);
+extern struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type);
 extern int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                                struct rk_lcdc_win *win, int id);
 extern int rk_fb_unregister(struct rk_lcdc_driver *dev_drv);
@@ -624,11 +633,11 @@ extern int rk_fb_dpi_open(bool open);
 extern int rk_fb_dpi_layer_sel(int layer_id);
 extern int rk_fb_dpi_status(void);
 
-extern int rk_fb_switch_screen(struct rk_screen * screen, int enable, int lcdc_id);
+extern int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id);
 extern int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id);
 extern int rkfb_create_sysfs(struct fb_info *fbi);
 extern char *get_format_string(enum data_format, char *fmt);
 extern int support_uboot_display(void);
-extern int  rk_fb_calc_fps(struct rk_screen * screen, u32 pixclock);
+extern int  rk_fb_calc_fps(struct rk_screen *screen, u32 pixclock);
 extern int rk_get_real_fps(int time);
 #endif
index 367d7c97ad79e56633f81534de4dee515037557e..013ccbb44c9cf0a6652e60c8d3fd54940c6ed92a 100755 (executable)
@@ -74,12 +74,13 @@ struct rk_screen {
        u16 x_mirror;
        u16 y_mirror;
        int interlace;
+       int pixelrepeat; //For 480i/576i format, pixel is repeated twice.
        u16 width;
        u16 height;
        u8  ft;
        int *dsp_lut; 
 
-#if defined(CONFIG_MFD_RK616)
+#if defined(CONFIG_MFD_RK616) || defined(CONFIG_LCDC_RK312X)
        u32 pll_cfg_val;  //bellow are for jettaB
        u32 frac;
        u16 scl_vst;
index b830fbe1cf863e12c0d5b1536ca13c6ec57fbb66..be6ff44f5fee7b0abd1b7bf66c9b27595e0f40d5 100644 (file)
@@ -64,4 +64,10 @@ extern int rockchip_tsadc_get_temp(int chn);
 static inline int rockchip_tsadc_get_temp(int chn) { return 0; }
 #endif
 
+#ifdef CONFIG_RK_LAST_LOG
+extern void rk_last_log_text(char *text, size_t size);
+#else
+static inline void rk_last_log_text(char *text, size_t size) {}
+#endif
+
 #endif
index 40f424207cc3f7bef023637dc25828ab5a3c84f7..e5a541236f70150d0826e48a0d4809c8296deec9 100644 (file)
@@ -8,6 +8,8 @@ static inline bool cpu_is_rockchip(void) { return rockchip_soc_id; }
 #define ROCKCHIP_CPU_MASK       0xffff0000
 #define ROCKCHIP_CPU_RK2928     0x29280000
 #define ROCKCHIP_CPU_RK3026     0x30260000
+#define ROCKCHIP_CPU_RK312X     0x31260000
+#define ROCKCHIP_CPU_RK3036     0x30360000
 #define ROCKCHIP_CPU_RK30XX     0x30660000
 #define ROCKCHIP_CPU_RK3066B    0x31680000
 #define ROCKCHIP_CPU_RK3188     0x31880000
@@ -16,6 +18,8 @@ static inline bool cpu_is_rockchip(void) { return rockchip_soc_id; }
 
 static inline bool cpu_is_rk2928(void)  { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK2928; }
 static inline bool cpu_is_rk3026(void)  { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK3026; }
+static inline bool cpu_is_rk312x(void)  { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK312X; }
+static inline bool cpu_is_rk3036(void)  { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK3036; }
 static inline bool cpu_is_rk30xx(void)  { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK30XX; }
 static inline bool cpu_is_rk3066b(void) { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK3066B; }
 static inline bool cpu_is_rk3188(void)  { return (rockchip_soc_id & ROCKCHIP_CPU_MASK) == ROCKCHIP_CPU_RK3188; }
@@ -27,6 +31,9 @@ static inline bool cpu_is_rk3288(void)  { return (rockchip_soc_id & ROCKCHIP_CPU
 #define ROCKCHIP_SOC_RK2928L    (ROCKCHIP_CPU_RK2928 | 0x02)
 #define ROCKCHIP_SOC_RK3028A    (ROCKCHIP_CPU_RK3026 | 0x03)
 #define ROCKCHIP_SOC_RK3026     (ROCKCHIP_CPU_RK3026 | 0x04)
+#define ROCKCHIP_SOC_RK3126     (ROCKCHIP_CPU_RK312X | 0x00)
+#define ROCKCHIP_SOC_RK3128     (ROCKCHIP_CPU_RK312X | 0x01)
+#define ROCKCHIP_SOC_RK3036     (ROCKCHIP_CPU_RK3036 | 0x00)
 #define ROCKCHIP_SOC_RK3000     (ROCKCHIP_CPU_RK30XX | 0x00)
 #define ROCKCHIP_SOC_RK3066     (ROCKCHIP_CPU_RK30XX | 0x01)
 #define ROCKCHIP_SOC_RK3068     (ROCKCHIP_CPU_RK30XX | 0x02)
@@ -43,6 +50,9 @@ static inline bool soc_is_rk2928g(void) { return rockchip_soc_id == ROCKCHIP_SOC
 static inline bool soc_is_rk2928l(void) { return rockchip_soc_id == ROCKCHIP_SOC_RK2928L; }
 static inline bool soc_is_rk3028a(void) { return rockchip_soc_id == ROCKCHIP_SOC_RK3028A; }
 static inline bool soc_is_rk3026(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3026; }
+static inline bool soc_is_rk3126(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3126; }
+static inline bool soc_is_rk3128(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3128; }
+static inline bool soc_is_rk3036(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3036; }
 static inline bool soc_is_rk3000(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3000; }
 static inline bool soc_is_rk3066(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3066; }
 static inline bool soc_is_rk3068(void)  { return rockchip_soc_id == ROCKCHIP_SOC_RK3068; }
index 0e1df2b347fc4567bf03052dff1178cdbcb3572c..bad44d358ccc1a6eb481f6456eb3a6246ba50169 100755 (executable)
@@ -125,4 +125,45 @@ static inline void rk3288_cru_set_soft_reset(u32 idx, bool on)
        dsb();
 }
 
+#define RK3036_CRU_MODE_CON 0x0040
+
+#define RK3036_CRU_GLB_SRST_FST_VALUE 0x00100
+#define RK3036_CRU_GLB_SRST_SND_VALUE 0x00104
+#define RK3036_CRU_SOFTRST0_CON 0x00110
+#define RK3036_CRU_SOFTRST1_CON 0x00114
+#define RK3036_CRU_SOFTRST2_CON 0x00118
+#define RK3036_CRU_SOFTRST3_CON 0x0011c
+#define RK3036_CRU_SOFTRST4_CON 0x00120
+#define RK3036_CRU_SOFTRST5_CON 0x00124
+#define RK3036_CRU_SOFTRST6_CON 0x00128
+#define RK3036_CRU_SOFTRST7_CON 0x0012c
+#define RK3036_CRU_SOFTRST8_CON 0x00130
+#define RK3036_CRU_MISC_CON 0x00134
+#define RK3036_CRU_GLB_CNT_TH 0x00140
+#define RK3036_CRU_SDMMC_CON0 0x00144
+#define RK3036_CRU_SDMMC_CON1 0x00148
+#define RK3036_CRU_SDIO_CON0 0x0014c
+#define RK3036_CRU_SDIO_CON1 0x00150
+#define RK3036_CRU_EMMC_CON0 0x00154
+#define RK3036_CRU_EMMC_CON1 0x00158
+#define RK3036_CRU_RST_ST 0x00160
+#define RK3036_CRU_PLL_MASK_CON 0x001f0
+
+#define RK3036_CRU_CLKSEL_CON          0x44
+#define RK3036_CRU_CLKGATE_CON         0xd0
+
+#define RK3036_CRU_CLKSELS_CON_CNT     (35)
+#define RK3036_CRU_CLKSELS_CON(i)      (RK3036_CRU_CLKSEL_CON + ((i) * 4))
+
+#define RK3036_CRU_CLKGATES_CON_CNT    (10)
+#define RK3036_CRU_CLKGATES_CON(i)     (RK3036_CRU_CLKGATE_CON + ((i) * 4))
+
+#define RK3036_CRU_SOFTRSTS_CON_CNT    (9)
+#define RK3036_CRU_SOFTRSTS_CON(i)     (RK3036_CRU_SOFTRST_CON + ((i) * 4))
+
+#define RK312X_CRU_SOFTRST_CON         0x110
+
+#define RK312X_CRU_SOFTRSTS_CON_CNT    (9)
+#define RK312X_CRU_SOFTRSTS_CON(i)     (RK312X_CRU_SOFTRST_CON + ((i) * 4))
+
 #endif
index 68191976855293265a30de414d7e0e9c28ec97b3..d65094439804d8d6a4f071a7e01ad5956750934d 100755 (executable)
 
 #define RK3288_SGRF_FAST_BOOT_ADDR      0x0120
 
+
+#define RK3036_GRF_GPIO0A_IOMUX         0x000a8
+#define RK3036_GRF_GPIO0B_IOMUX         0x000ac
+#define RK3036_GRF_GPIO0C_IOMUX         0x000b0
+#define RK3036_GRF_GPIO0D_IOMUX         0x000b4
+#define RK3036_GRF_GPIO1A_IOMUX         0x000b8
+#define RK3036_GRF_GPIO1B_IOMUX         0x000bc
+#define RK3036_GRF_GPIO1C_IOMUX         0x000c0
+#define RK3036_GRF_GPIO1D_IOMUX         0x000c4
+#define RK3036_GRF_GPIO2A_IOMUX         0x000c8
+#define RK3036_GRF_GPIO2B_IOMUX         0x000cc
+#define RK3036_GRF_GPIO2C_IOMUX         0x000d0
+#define RK3036_GRF_GPIO2D_IOMUX         0x000d4
+#define RK3036_GRF_GPIO_DS              0x00100
+#define RK3036_GRF_GPIO0L_PULL          0x00118
+#define RK3036_GRF_GPIO0H_PULL          0x0011c
+#define RK3036_GRF_GPIO1L_PULL          0x00120
+#define RK3036_GRF_GPIO1H_PULL          0x00124
+
+#define RK3036_GRF_GPIO2L_PULL 0x00128
+#define RK3036_GRF_GPIO2H_PULL 0x0012c
+#define RK3036_GRF_SOC_CON0 0x00140
+#define RK3036_GRF_SOC_CON1 0x00144
+#define RK3036_GRF_SOC_CON2 0x00148
+#define RK3036_GRF_SOC_STATUS0 0x0014c
+#define RK3036_GRF_SOC_CON3 0x00154
+#define RK3036_GRF_DMAC_CON0 0x0015c
+#define RK3036_GRF_DMAC_CON1 0x00160
+#define RK3036_GRF_DMAC_CON2 0x00164
+#define RK3036_GRF_UOC0_CON5 0x0017c
+#define RK3036_GRF_UOC1_CON4 0x00190
+#define RK3036_GRF_UOC1_CON5 0x00194
+#define RK3036_GRF_DDRC_STAT 0x0019c
+#define RK3036_GRF_UOC_CON6 0x001a0
+#define RK3036_GRF_SOC_STATUS1 0x001a4
+#define RK3036_GRF_CPU_CON0 0x001a8
+#define RK3036_GRF_CPU_CON1 0x001ac
+#define RK3036_GRF_CPU_CON2 0x001b0
+#define RK3036_GRF_CPU_CON3 0x001b4
+#define RK3036_GRF_CPU_STATUS0 0x001c0
+#define RK3036_GRF_CPU_STATUS1 0x001c4
+#define RK3036_GRF_OS_REG0 0x001c8
+#define RK3036_GRF_OS_REG1 0x001cc
+#define RK3036_GRF_OS_REG2 0x001d0
+#define RK3036_GRF_OS_REG3 0x001d4
+#define RK3036_GRF_OS_REG4 0x001d8
+#define RK3036_GRF_OS_REG5 0x001dc
+#define RK3036_GRF_OS_REG6 0x001e0
+#define RK3036_GRF_OS_REG7 0x001e4
+#define RK3036_GRF_DLL_CON0 0x00200
+#define RK3036_GRF_DLL_CON1 0x00204
+#define RK3036_GRF_DLL_CON2 0x00208
+#define RK3036_GRF_DLL_CON3 0x0020c
+#define RK3036_GRF_DLL_STATUS0 0x00210
+#define RK3036_GRF_DLL_STATUS1 0x00214
+
+#define RK3036_GRF_DLL_STATUS2 0x00218
+#define RK3036_GRF_DLL_STATUS3 0x0021c
+#define RK3036_GRF_DFI_WRNUM 0x00220
+#define RK3036_GRF_DFI_RDNUM 0x00224
+#define RK3036_GRF_DFI_ACTNUM 0x00228
+#define RK3036_GRF_DFI_TIMERVAL 0x0022c
+#define RK3036_GRF_NIF_FIFO0 0x00230
+#define RK3036_GRF_NIF_FIFO1 0x00234
+#define RK3036_GRF_NIF_FIFO2 0x00238
+#define RK3036_GRF_NIF_FIFO3 0x0023c
+#define RK3036_GRF_USBPHY0_CON0 0x00280
+#define RK3036_GRF_USBPHY0_CON1 0x00284
+#define RK3036_GRF_USBPHY0_CON2 0x00288
+#define RK3036_GRF_USBPHY0_CON3 0x0028c
+#define RK3036_GRF_USBPHY0_CON4 0x00290
+#define RK3036_GRF_USBPHY0_CON5 0x00294
+#define RK3036_GRF_USBPHY0_CON6 0x00298
+#define RK3036_GRF_USBPHY0_CON7 0x0029c
+#define RK3036_GRF_USBPHY1_CON0 0x002a0
+#define RK3036_GRF_USBPHY1_CON1 0x002a4
+#define RK3036_GRF_USBPHY1_CON2 0x002a8
+#define RK3036_GRF_USBPHY1_CON3 0x002ac
+#define RK3036_GRF_USBPHY1_CON4 0x002b0
+#define RK3036_GRF_USBPHY1_CON5 0x002b4
+#define RK3036_GRF_USBPHY1_CON6 0x002b8
+
+#define RK3036_GRF_USBPHY1_CON7 0x002bc
+#define RK3036_GRF_CHIP_TAG 0x00300
+#define RK3036_GRF_SDMMC_DET_CNT 0x00304
+
+#define RK312X_GRF_GPIO0A_IOMUX         0x000a8
+#define RK312X_GRF_GPIO0B_IOMUX         0x000ac
+#define RK312X_GRF_GPIO0C_IOMUX         0x000b0
+#define RK312X_GRF_GPIO0D_IOMUX         0x000b4
+#define RK312X_GRF_GPIO1A_IOMUX         0x000b8
+#define RK312X_GRF_GPIO1B_IOMUX         0x000bc
+#define RK312X_GRF_GPIO1C_IOMUX         0x000c0
+#define RK312X_GRF_GPIO1D_IOMUX         0x000c4
+#define RK312X_GRF_GPIO2A_IOMUX         0x000c8
+#define RK312X_GRF_GPIO2B_IOMUX         0x000cc
+#define RK312X_GRF_GPIO2C_IOMUX         0x000d0
+#define RK312X_GRF_GPIO2D_IOMUX         0x000d4
+#define RK312X_GRF_GPIO3A_IOMUX         0x000d8
+#define RK312X_GRF_GPIO3B_IOMUX         0x000dc
+#define RK312X_GRF_GPIO3C_IOMUX         0x000e0
+#define RK312X_GRF_GPIO3D_IOMUX         0x000e4
+#define RK312X_GRF_CIF_IOMUX           0x000ec
+#define RK312X_GRF_CIF_IOMUX1          0x000f0
+#define RK312X_GRF_GPIO_DS              0x00100
+#define RK312X_GRF_GPIO0L_PULL          0x00118
+#define RK312X_GRF_GPIO0H_PULL          0x0011c
+#define RK312X_GRF_GPIO1L_PULL          0x00120
+#define RK312X_GRF_GPIO1H_PULL          0x00124
+#define RK312X_GRF_GPIO2L_PULL          0x00128
+#define RK312X_GRF_GPIO2H_PULL          0x0012c
+#define RK312X_GRF_GPIO3L_PULL          0x00130
+#define RK312X_GRF_GPIO3H_PULL          0x00134
+#define RK312X_GRF_ACODEC_CON          0x0013c
+
+#define RK312X_GRF_SOC_CON0 0x00140
+#define RK312X_GRF_SOC_CON1 0x00144
+#define RK312X_GRF_SOC_CON2 0x00148
+#define RK312X_GRF_SOC_STATUS0 0x0014c
+#define RK312X_GRF_LVDS_CON0 0x00150
+#define RK312X_GRF_SOC_CON3 0x00154
+#define RK312X_GRF_DMAC_CON0 0x0015c
+#define RK312X_GRF_DMAC_CON1 0x00160
+#define RK312X_GRF_DMAC_CON2 0x00164
+#define RK312X_GRF_MAC_CON0 0x00168
+#define RK312X_GRF_MAC_CON1 0x0016c
+#define RK312X_GRF_TVE_CON 0x00170
+#define RK312X_GRF_UOC0_CON0 0x0017c
+#define RK312X_GRF_UOC1_CON1 0x00184
+#define RK312X_GRF_UOC1_CON2 0x00188
+#define RK312X_GRF_UOC1_CON3 0x0018c
+#define RK312X_GRF_UOC1_CON4 0x00190
+#define RK312X_GRF_UOC1_CON5 0x00194
+#define RK312X_GRF_DDRC_STAT 0x0019c
+#define RK312X_GRF_SOC_STATUS1 0x001a4
+#define RK312X_GRF_CPU_CON0 0x001a8
+#define RK312X_GRF_CPU_CON1 0x001ac
+#define RK312X_GRF_CPU_CON2 0x001b0
+#define RK312X_GRF_CPU_CON3 0x001b4
+#define RK312X_GRF_CPU_STATUS0 0x001c0
+#define RK312X_GRF_CPU_STATUS1 0x001c4
+#define RK312X_GRF_OS_REG0 0x001c8
+#define RK312X_GRF_OS_REG1 0x001cc
+#define RK312X_GRF_OS_REG2 0x001d0
+#define RK312X_GRF_OS_REG3 0x001d4
+#define RK312X_GRF_OS_REG4 0x001d8
+#define RK312X_GRF_OS_REG5 0x001dc
+#define RK312X_GRF_OS_REG6 0x001e0
+#define RK312X_GRF_OS_REG7 0x001e4
+#define RK312X_GRF_PVTM_CON0 0x00200
+#define RK312X_GRF_PVTM_CON1 0x00204
+#define RK312X_GRF_PVTM_CON2 0x00208
+#define RK312X_GRF_PVTM_CON3 0x0020c
+#define RK312X_GRF_PVTM_STATUS0 0x00210
+#define RK312X_GRF_PVTM_STATUS1 0x00214
+#define RK312X_GRF_PVTM_STATUS2 0x00218
+#define RK312X_GRF_PVTM_STATUS3 0x0021c
+#define RK312X_GRF_DFI_WRNUM 0x00220
+#define RK312X_GRF_DFI_RDNUM 0x00224
+#define RK312X_GRF_DFI_ACTNUM 0x00228
+#define RK312X_GRF_DFI_TIMERVAL 0x0022c
+#define RK312X_GRF_NIF_FIFO0 0x00230
+#define RK312X_GRF_NIF_FIFO1 0x00234
+#define RK312X_GRF_NIF_FIFO2 0x00238
+#define RK312X_GRF_NIF_FIFO3 0x0023c
+#define RK312X_GRF_USBPHY0_CON0 0x00280
+#define RK312X_GRF_USBPHY0_CON1 0x00284
+#define RK312X_GRF_USBPHY0_CON2 0x00288
+#define RK312X_GRF_USBPHY0_CON3 0x0028c
+#define RK312X_GRF_USBPHY0_CON4 0x00290
+#define RK312X_GRF_USBPHY0_CON5 0x00294
+#define RK312X_GRF_USBPHY0_CON6 0x00298
+#define RK312X_GRF_USBPHY0_CON7 0x0029c
+#define RK312X_GRF_USBPHY1_CON0 0x002a0
+#define RK312X_GRF_USBPHY1_CON1 0x002a4
+#define RK312X_GRF_USBPHY1_CON2 0x002a8
+#define RK312X_GRF_USBPHY1_CON3 0x002ac
+#define RK312X_GRF_USBPHY1_CON4 0x002b0
+#define RK312X_GRF_USBPHY1_CON5 0x002b4
+#define RK312X_GRF_USBPHY1_CON6 0x002b8
+#define RK312X_GRF_USBPHY1_CON7 0x002bc
+#define RK312X_GRF_UOC_STATUS0 0x002c0
+#define RK312X_GRF_CHIP_TAG 0x00300
+#define RK312X_GRF_SDMMC_DET_CNT 0x00304
+#define RK312X_GRF_EFUSE_PRG_EN 0x0037c
 #endif
index ae4e1fd6446d41db465288dfcf1b4475045d1be5..1adbcb2941874a4131f777ed2377f3473969e9dd 100755 (executable)
 #define RK3288_IMEM_PHYS                0xFF700000
 #define RK3288_IMEM_SZIE                0x00018000
 
+#define RK3036_IMEM_PHYS               0x10080000
+#define RK3036_IMEM_SIZE               SZ_8K
+#define RK3036_ROM_PHYS                        0x10100000
+#define RK3036_ROM_SIZE                        SZ_16K
+#define RK3036_CPU_AXI_BUS_PHYS                0x10128000
+#define RK3036_CPU_AXI_BUS_SIZE                SZ_32K
+#define RK3036_GIC_DIST_PHYS           0x10139000
+#define RK3036_GIC_DIST_SIZE           SZ_4K
+#define RK3036_GIC_CPU_PHYS            0x1013a000
+#define RK3036_GIC_CPU_SIZE            SZ_4K
+#define RK3036_CRU_PHYS                        0x20000000
+#define RK3036_CRU_SIZE                        SZ_4K
+#define RK3036_DDR_PCTL_PHYS           0x20004000
+#define RK3036_DDR_PCTL_SIZE           SZ_4K
+#define RK3036_GRF_PHYS                        0x20008000
+#define RK3036_GRF_SIZE                        SZ_4K
+#define RK3036_DDR_PHY_PHYS            0x2000a000
+#define RK3036_DDR_PHY_SIZE            SZ_4K
+#define RK3036_TIMER_PHYS              0x20044000
+#define RK3036_TIMER_SIZE              SZ_4K
+#define RK3036_UART0_PHYS              0x20060000
+#define RK3036_UART1_PHYS              0x20064000
+#define RK3036_UART2_PHYS              0x20068000
+#define RK3036_UART_SIZE               SZ_4K
+#define RK3036_GPIO0_PHYS              0x2007c000
+#define RK3036_GPIO1_PHYS              0x20080000
+#define RK3036_GPIO2_PHYS              0x20084000
+#define RK3036_GPIO_SIZE               SZ_4K
+#define RK3036_EFUSE_PHYS              0x20090000
+#define RK3036_EFUSE_SIZE              SZ_4K
+
+#define RK312X_IMEM_PHYS                RK3036_IMEM_PHYS
+#define RK312X_IMEM_SIZE                RK3036_IMEM_SIZE
+#define RK312X_ROM_PHYS                        RK3036_ROM_PHYS
+#define RK312X_ROM_SIZE                 RK3036_ROM_SIZE
+#define RK312X_CPU_AXI_BUS_PHYS         RK3036_CPU_AXI_BUS_PHYS
+#define RK312X_CPU_AXI_BUS_SIZE         RK3036_CPU_AXI_BUS_SIZE
+#define RK312X_GIC_DIST_PHYS            RK3036_GIC_DIST_PHYS
+#define RK312X_GIC_DIST_SIZE            RK3036_GIC_DIST_SIZE
+#define RK312X_GIC_CPU_PHYS             RK3036_GIC_CPU_PHYS
+#define RK312X_GIC_CPU_SIZE             RK3036_GIC_CPU_SIZE
+#define RK312X_CRU_PHYS                 RK3036_CRU_PHYS
+#define RK312X_CRU_SIZE                 RK3036_CRU_SIZE
+#define RK312X_DDR_PCTL_PHYS            RK3036_DDR_PCTL_PHYS
+#define RK312X_DDR_PCTL_SIZE            RK3036_DDR_PCTL_SIZE
+#define RK312X_GRF_PHYS                 RK3036_GRF_PHYS
+#define RK312X_GRF_SIZE                 RK3036_GRF_SIZE
+#define RK312X_DDR_PHY_PHYS             RK3036_DDR_PHY_PHYS
+#define RK312X_DDR_PHY_SIZE             RK3036_DDR_PHY_SIZE
+#define RK312X_TIMER_PHYS               RK3036_TIMER_PHYS
+#define RK312X_TIMER_SIZE               RK3036_TIMER_SIZE
+#define RK312X_UART0_PHYS               RK3036_UART0_PHYS
+#define RK312X_UART1_PHYS               RK3036_UART1_PHYS
+#define RK312X_UART2_PHYS               RK3036_UART2_PHYS
+#define RK312X_UART_SIZE                RK3036_UART_SIZE
+#define RK312X_GPIO0_PHYS               RK3036_GPIO0_PHYS
+#define RK312X_GPIO1_PHYS               RK3036_GPIO1_PHYS
+#define RK312X_GPIO2_PHYS               RK3036_GPIO2_PHYS
+#define RK312X_GPIO3_PHYS               0x20088000
+#define RK312X_GPIO_SIZE                RK3036_GPIO_SIZE
+#define RK312X_EFUSE_PHYS               RK3036_EFUSE_PHYS
+#define RK312X_EFUSE_SIZE               RK3036_EFUSE_SIZE
+
 #endif
index 41e06dfef4062141610c9cfd34a299bb7ae336ec..cba6c8f50593abde415f4f67ad539103a7342b0e 100755 (executable)
@@ -22,6 +22,8 @@
 #define VOPB_SYSMMU_COMPATIBLE_NAME "iommu,vopb_mmu"
 #define VOPL_SYSMMU_COMPATIBLE_NAME "iommu,vopl_mmu"
 
+#define VOP_SYSMMU_COMPATIBLE_NAME "iommu,vop_mmu"
+
 #define HEVC_SYSMMU_COMPATIBLE_NAME "iommu,hevc_mmu"
 #define VPU_SYSMMU_COMPATIBLE_NAME "iommu,vpu_mmu"
 
@@ -87,23 +89,6 @@ void rockchip_sysmmu_tlb_invalidate(struct device *owner);
  */
 void rockchip_sysmmu_set_fault_handler(struct device *dev,sysmmu_fault_handler_t handler);
 
-/** rockchip_sysmmu_set_prefbuf() - Initialize prefetch buffers of System MMU v3
- *     @owner: The device which need to set the prefetch buffers
- *     @base0: The start virtual address of the area of the @owner device that the
- *                     first prefetch buffer loads translation descriptors
- *     @size0: The last virtual address of the area of the @owner device that the
- *                     first prefetch buffer loads translation descriptors.
- *     @base1: The start virtual address of the area of the @owner device that the
- *                     second prefetch buffer loads translation descriptors. This will be
- *                     ignored if @size1 is 0 and this function assigns the 2 prefetch
- *                     buffers with each half of the area specified by @base0 and @size0
- *     @size1: The last virtual address of the area of the @owner device that the
- *                     prefetch buffer loads translation descriptors. This can be 0. See
- *                     the description of @base1 for more information with @size1 = 0
- */
-void rockchip_sysmmu_set_prefbuf(struct device *owner,
-                               unsigned long base0, unsigned long size0,
-                               unsigned long base1, unsigned long size1);
 #else /* CONFIG_ROCKCHIP_IOMMU */
 static inline int rockchip_sysmmu_enable(struct device *owner, unsigned long pgd)
 {
@@ -120,8 +105,8 @@ static inline void rockchip_sysmmu_set_fault_handler(struct device *dev,sysmmu_f
 {
 }
 static inline void rockchip_sysmmu_set_prefbuf(struct device *owner,
-                                              unsigned long base0, unsigned long size0,
-                                              unsigned long base1, unsigned long size1)
+                                              unsigned long base0, unsigned long size0,
+                                              unsigned long base1, unsigned long size1)
 {
 }
 #endif
index 629e6471d55e4558f21c0aa1e57f1d041f6331b8..e7ad8943f7161bc891fe7f95513948304763a257 100755 (executable)
@@ -35,6 +35,7 @@
 #include <linux/rockchip/iomap.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <linux/skbuff.h>
+#include <linux/rockchip/cpu.h>
 #ifdef CONFIG_OF
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -251,7 +252,7 @@ int rockchip_wifi_ref_voltage(int on)
         int ret = -1;
         char *ldostr;
         int level = mrfkill->pdata->ioregulator.enable;
-        int voltage = 1000 * mrfkill->pdata->sdio_vol;
+               int voltage = 1000 * mrfkill->pdata->sdio_vol;
 
         ldostr = mrfkill->pdata->ioregulator.pmu_regulator;
         if (ldostr == NULL) {
@@ -264,10 +265,18 @@ int rockchip_wifi_ref_voltage(int on)
             return -1;
         } else {
             if (on == level) {
-                regulator_set_voltage(ldo, voltage, voltage);
-                LOG("%s: %s enabled, level = %d\n", __func__, ldostr, voltage);
-                ret = regulator_enable(ldo);
-                LOG("wifi turn on io reference voltage.\n");
+               if(cpu_is_rk3036())
+               {
+                                       /*regulator_set_voltage(ldo, voltage, voltage);
+                                       LOG("%s: %s enabled, level = %d\n", __func__, ldostr, voltage);
+                                       ret = regulator_enable(ldo);
+                                       LOG("wifi turn on io reference voltage.\n");*/
+               }else{
+                                       regulator_set_voltage(ldo, voltage, voltage);
+                                       LOG("%s: %s enabled, level = %d\n", __func__, ldostr, voltage);
+                                       ret = regulator_enable(ldo);
+                                       LOG("wifi turn on io reference voltage.\n");
+               }
             } else {
                 LOG("%s: %s disabled\n", __func__, ldostr);
                 while (regulator_is_enabled(ldo) > 0) {
@@ -591,12 +600,21 @@ static int wlan_platdata_parse_dt(struct device *dev,
 
     memset(data, 0, sizeof(*data));
 
-    ret = of_property_read_u32(node, "sdio_vref", &value);
-    if (ret < 0) {
-        LOG("%s: Can't get sdio vref.", __func__);
-        return -1;
-    }
-    data->sdio_vol = value;
+       if(cpu_is_rk3036()){
+               /* ret = of_property_read_u32(node, "sdio_vref", &value);
+               if (ret < 0) {
+                       LOG("%s: Can't get sdio vref.", __func__);
+                       return -1;
+               }
+               data->sdio_vol = value;*/
+       }else{
+               ret = of_property_read_u32(node, "sdio_vref", &value);
+               if (ret < 0) {
+                       LOG("%s: Can't get sdio vref.", __func__);
+                       return -1;
+               }
+               data->sdio_vol = value;
+       }
 
     if (of_find_property(node, "vref_ctrl_enable", NULL)) {
         LOG("%s: enable wifi io reference voltage control.\n", __func__);
index 39a4c3f95956ea3822837ae207fb8254cd8c0562..34aec9a55f8df92524d6fac3fcda823ec1023eec 100644 (file)
@@ -63,6 +63,8 @@ $(obj)/pie_stage2.o: $(obj)/pie_stage1.o $(obj)/libpie_stage2.o
 # Drop everything but the pie sections
 OBJCOPYFLAGS_pie_stage3.o += -j ".pie.*"
 OBJCOPYFLAGS_pie_stage3.o += -j ".pie.text"
+OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3036.text" -j ".pie.rk3036.data"
+OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk312x.text" -j ".pie.rk312x.data"
 OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3188.text" -j ".pie.rk3188.data"
 OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3288.text" -j ".pie.rk3288.data"
 
index 998c628c479d7cc64cc06e089d6591191506316c..a11ae2b7dcb22dacb0a04c08080d83518c487618 100644 (file)
@@ -314,6 +314,9 @@ config SND_SOC_OMAP_HDMI_CODEC
 config SND_SOC_PCM3008
        tristate
 
+config SND_SOC_RK3036
+       tristate
+
 #Freescale sgtl5000 codec
 config SND_SOC_SGTL5000
        tristate
old mode 100755 (executable)
new mode 100644 (file)
index f02b0c1..7389cb5
@@ -129,12 +129,13 @@ snd-soc-rt5616-objs := rt5616.o
 snd-soc-rt5631-phone-objs := rt5631_phone.o
 snd-soc-rt5625-objs := rt5625.o
 obj-y := rt56xx_ioctl.o
-snd-soc-rt5639-objs := rt5639.o rt5639_ioctl.o 
+snd-soc-rt5639-objs := rt5639.o rt5639_ioctl.o
 snd-soc-rt5640-objs := rt5640.o rt5640-dsp.o rt5640_ioctl.o
 snd-soc-rt3224-objs := rt3261.o rt3261_ioctl.o rt_codec_ioctl.o
 snd-soc-rt3261-objs := rt3261-dsp.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-rk1000-objs := rk1000_codec.o
+snd-soc-rk3036-objs := rk3036_codec.o
 snd-soc-rk610-objs := rk610_codec.o
 snd-soc-rk616-objs := rk616_codec.o
 snd-soc-rk2928-objs := rk2928_codec.o
@@ -282,6 +283,7 @@ obj-$(CONFIG_SND_SOC_RT5639)    += snd-soc-rt5639.o
 obj-$(CONFIG_SND_SOC_RT5640)    += snd-soc-rt5640.o
 obj-$(CONFIG_SND_SOC_CS42L52)  += snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_RK1000)   += snd-soc-rk1000.o
+obj-$(CONFIG_SND_SOC_RK3036)   += snd-soc-rk3036.o
 obj-$(CONFIG_SND_SOC_RK610)    += snd-soc-rk610.o
 obj-$(CONFIG_SND_SOC_RK616)    += snd-soc-rk616.o
 obj-$(CONFIG_SND_SOC_RK2928)   += snd-soc-rk2928.o
index a5a1203b7a5d8834d6e33f7f583d1b2048bc6a58..f97de191c62c0dedb41298896cbd8013ccc39b15 100644 (file)
 #include <sound/pcm.h>
 #include <sound/initval.h>
 
+#undef  DEBUG_HDMI_SPDIF
+#define DEBUG_HDMI_SPDIF 0
+
+#if DEBUG_HDMI_SPDIF
+#define RK_HDMISPDIF_DBG(x...) pr_info("hdmi_spdif:"x)
+#else
+#define RK_HDMISPDIF_DBG(x...) do { } while (0)
+#endif
+
+
 #define DRV_NAME "spdif-dit"
 
 #define STUB_RATES     SNDRV_PCM_RATE_8000_96000
@@ -33,7 +43,7 @@ static struct snd_soc_codec_driver soc_codec_spdif_dit;
 
 static struct snd_soc_dai_driver dit_stub_dai = {
        .name           = "rk-hdmi-spdif-hifi",
-       .playback       = {
+       .playback       = {
                .stream_name    = "Playback",
                .channels_min   = 1,
                .channels_max   = 384,
@@ -42,23 +52,24 @@ static struct snd_soc_dai_driver dit_stub_dai = {
        },
 };
 
-static int rockchip_hdmi_spdif_audio_probe(struct platform_device *pdev)
+static int hdmi_spdif_audio_probe(struct platform_device *pdev)
 {
        int ret;
 
-       //set dev name to driver->name for sound card register
+       /* set dev name to driver->name for sound card register. */
        dev_set_name(&pdev->dev, "%s", pdev->dev.driver->name);
 
-       ret = snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
-                       &dit_stub_dai, 1);
+       ret = snd_soc_register_codec(&pdev->
+               dev, &soc_codec_spdif_dit, &dit_stub_dai, 1);
 
        if (ret)
-               printk("%s() register codec failed:%d\n", __FUNCTION__, ret);
+               RK_HDMISPDIF_DBG("%s register codec failed:%d\n"
+               , __func__, ret);
 
        return ret;
 }
 
-static int rockchip_hdmi_spdif_audio_remove(struct platform_device *pdev)
+static int hdmi_spdif_audio_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_codec(&pdev->dev);
 
@@ -66,24 +77,24 @@ static int rockchip_hdmi_spdif_audio_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static const struct of_device_id rockchip_hdmi_spdif_of_match[] = {
-        { .compatible = "hdmi-spdif", },
-        {},
+static const struct of_device_id hdmi_spdif_of_match[] = {
+       { .compatible = "hdmi-spdif", },
+       {},
 };
-MODULE_DEVICE_TABLE(of, rockchip_hdmi_spdif_of_match);
+MODULE_DEVICE_TABLE(of, hdmi_spdif_of_match);
 #endif /* CONFIG_OF */
 
-static struct platform_driver rockchip_hdmi_spdif_audio_driver = {
-        .driver         = {
-                .name   = "hdmi-spdif",
-                .owner  = THIS_MODULE,
-                .of_match_table = of_match_ptr(rockchip_hdmi_spdif_of_match),
-        },
-        .probe          = rockchip_hdmi_spdif_audio_probe,
-        .remove         = rockchip_hdmi_spdif_audio_remove,
+static struct platform_driver hdmi_spdif_audio_driver = {
+       .driver    = {
+               .name           = "hdmi-spdif",
+               .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(hdmi_spdif_of_match),
+       },
+       .probe     = hdmi_spdif_audio_probe,
+       .remove    = hdmi_spdif_audio_remove,
 };
 
-module_platform_driver(rockchip_hdmi_spdif_audio_driver);
+module_platform_driver(hdmi_spdif_audio_driver);
 
 MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
 MODULE_DESCRIPTION("SPDIF dummy codec driver");
diff --git a/sound/soc/codecs/rk3036_codec.c b/sound/soc/codecs/rk3036_codec.c
new file mode 100644 (file)
index 0000000..81c84e9
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * rk3036_codec.c
+ *
+ * Driver for rockchip rk3036 codec
+ * Copyright (C) 2014
+ *
+ * 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.
+ *
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include "rk3036_codec.h"
+
+#define DEBUGOPEN 0
+
+#if DEBUGOPEN
+#define dbg_codec(level, fmt, arg...) do {     \
+       if (debug >= level)                                     \
+               printk(fmt , ## arg); }                         \
+       while (0)
+
+#else
+#define        dbg_codec(level, fmt, arg...)
+#endif
+
+#define INVALID_GPIO -1
+#define SPK_CTRL_OPEN  1
+#define SPK_CTRL_CLOSE 0
+
+/* volume setting
+ *  0: -39dB
+ *  26: 0dB
+ *  31: 6dB
+ *  Step: 1.5dB
+*/
+#define  OUT_VOLUME    31
+
+/*with capacity or not*/
+#define WITH_CAP
+
+struct rk3036_codec_priv {
+       void __iomem    *regbase;
+       struct snd_soc_codec *codec;
+
+       unsigned int stereo_sysclk;
+       unsigned int rate;
+
+       struct delayed_work codec_delayed_work;
+       int spk_ctl_gpio;
+       int delay_time;
+
+       struct clk      *pclk;
+};
+static struct rk3036_codec_priv *rk3036_priv;
+
+static const unsigned int rk3036_reg_defaults[RK3036_CODEC_REG28+1] = {
+       [RK3036_CODEC_RESET] = 0x03,
+       [RK3036_CODEC_REG03] = 0x00,
+       [RK3036_CODEC_REG04] = 0x50,
+       [RK3036_CODEC_REG05] = 0x0E,
+       [RK3036_CODEC_REG22] = 0x00,
+       [RK3036_CODEC_REG23] = 0x00,
+       [RK3036_CODEC_REG24] = 0x00,
+       [RK3036_CODEC_REG25] = 0x00,
+       [RK3036_CODEC_REG26] = 0x00,
+       [RK3036_CODEC_REG27] = 0x05,
+       [RK3036_CODEC_REG28] = 0x00,
+};
+
+/* function declare: */
+static int rk3036_codec_register(
+       struct snd_soc_codec *codec, unsigned int reg);
+static int rk3036_volatile_register(
+       struct snd_soc_codec *codec, unsigned int reg);
+static int rk3036_set_bias_level(
+       struct snd_soc_codec *codec, enum snd_soc_bias_level level);
+static unsigned int rk3036_codec_read(
+       struct snd_soc_codec *codec, unsigned int reg);
+static inline void rk3036_write_reg_cache(
+       struct snd_soc_codec *codec, unsigned int reg, unsigned int value);
+
+static inline unsigned int rk3036_read_reg_cache(struct snd_soc_codec *
+       codec, unsigned int reg)
+{
+       unsigned int *cache = codec->reg_cache;
+
+       if (rk3036_codec_register(codec, reg))
+               return  cache[reg];
+
+       dbg_codec(2, "%s : reg error!\n", __func__);
+
+       return -EINVAL;
+}
+
+static inline void rk3036_write_reg_cache(struct snd_soc_codec *
+       codec, unsigned int reg, unsigned int value)
+{
+       unsigned int *cache = codec->reg_cache;
+
+       if (rk3036_codec_register(codec, reg)) {
+               cache[reg] = value;
+               return;
+       }
+
+       dbg_codec(2, "%s : reg error!\n", __func__);
+}
+
+static int rk3036_reset(struct snd_soc_codec *codec)
+{
+       writel(0x00, rk3036_priv->regbase+RK3036_CODEC_RESET);
+       mdelay(10);
+       writel(0x03, rk3036_priv->regbase+RK3036_CODEC_RESET);
+       mdelay(10);
+       memcpy(codec->
+               reg_cache, rk3036_reg_defaults,
+               sizeof(rk3036_reg_defaults));
+       return 0;
+}
+
+static int rk3036_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct rk3036_codec_priv *rk3036 = rk3036_priv;
+       unsigned int dac_aif1 = 0, dac_aif2  = 0;
+
+       if (!rk3036) {
+               dbg_codec(2, "%s : rk3036 is NULL\n", __func__);
+               return -EINVAL;
+       }
+       dac_aif2 |= RK3036_CR05_FRAMEH_32BITS;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               dac_aif1 |= RK3036_CR04_HFVALID_16BITS;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               dac_aif1 |= RK3036_CR04_HFVALID_20BITS;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               dac_aif1 |= RK3036_CR04_HFVALID_24BITS;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               dac_aif1 |= RK3036_CR04_HFVALID_32BITS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dac_aif1 |= RK3036_CR04_LR_SWAP_DIS;
+       dac_aif2 |= RK3036_CR05_DAC_RESET_DIS;
+
+       snd_soc_update_bits(
+               codec, RK3036_CODEC_REG04,
+               RK3036_CR04_HFVALID_MASK
+               |RK3036_CR04_LR_SWAP_MASK, dac_aif1);
+       snd_soc_update_bits(
+               codec, RK3036_CODEC_REG05,
+               RK3036_CR05_FRAMEH_MASK
+               |RK3036_CR05_DAC_RESET_MASK, dac_aif2);
+
+       return 0;
+}
+
+static int rk3036_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                             unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       unsigned int fmt_ms = 0,  dac_aif1 = 0, dac_aif2 = 0;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               fmt_ms |= RK3036_CR03_DIRECTION_IN|RK3036_CR03_I2SMODE_SLAVE;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               fmt_ms |= RK3036_CR03_DIRECTION_IOUT|RK3036_CR03_I2SMODE_MASTER;
+               break;
+       default:
+               dbg_codec(2, "%s : set master mask failed!\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               dac_aif1 |= RK3036_CR04_MODE_PCM;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               dac_aif1 |= RK3036_CR04_MODE_I2S;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               dac_aif1 |= RK3036_CR04_MODE_RIGHT;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               dac_aif1 |= RK3036_CR04_MODE_LEFT;
+               break;
+       default:
+               dbg_codec(2, "%s : set format failed!\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               dac_aif1 |= RK3036_CR04_I2SLRC_NORMAL;
+               dac_aif2 |= RK3036_CR05_BCLKPOL_NORMAL;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               dac_aif1 |= RK3036_CR04_I2SLRC_REVERSAL;
+               dac_aif2 |= RK3036_CR05_BCLKPOL_REVERSAL;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               dac_aif1 |= RK3036_CR04_I2SLRC_REVERSAL;
+               dac_aif2 |= RK3036_CR05_BCLKPOL_NORMAL;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               dac_aif1 |= RK3036_CR04_I2SLRC_NORMAL;
+               dac_aif2 |= RK3036_CR05_BCLKPOL_REVERSAL;
+               break;
+       default:
+               dbg_codec(2, "%s : set dai format failed!\n", __func__);
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(
+               codec, RK3036_CODEC_REG03,
+               RK3036_CR03_DIRECTION_MASK
+               |RK3036_CR03_I2SMODE_MASK, fmt_ms);
+       snd_soc_update_bits(
+               codec, RK3036_CODEC_REG04,
+               RK3036_CR04_I2SLRC_MASK
+               | RK3036_CR04_MODE_MASK, dac_aif1);
+       snd_soc_update_bits(
+               codec, RK3036_CODEC_REG05,
+               RK3036_CR05_BCLKPOL_MASK, dac_aif2);
+       return 0;
+}
+
+static int rk3036_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                                int clk_id, unsigned int freq, int dir)
+{
+       struct rk3036_codec_priv *rk3036 = rk3036_priv;
+
+       if (!rk3036) {
+               dbg_codec(2, "%s : rk3036 is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       rk3036->stereo_sysclk = freq;
+
+       return 0;
+}
+
+static int rk3036_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       unsigned int val;
+
+       if (mute) {
+               val = snd_soc_read(codec, RK3036_CODEC_REG27);
+               if (val & (RK3036_CR27_HPOUTL_G_WORK
+                       |RK3036_CR27_HPOUTR_G_WORK)) {
+                       val &= ~RK3036_CR27_HPOUTL_G_WORK;
+                       val &= ~RK3036_CR27_HPOUTR_G_WORK;
+                       snd_soc_write(codec, RK3036_CODEC_REG27, val);
+               }
+       } else {
+               val = snd_soc_read(codec, RK3036_CODEC_REG27);
+               if ((val | ~RK3036_CR27_HPOUTL_G_WORK) || (val
+                       | ~RK3036_CR27_HPOUTR_G_WORK)) {
+                       val |= RK3036_CR27_HPOUTL_G_WORK
+                               |RK3036_CR27_HPOUTR_G_WORK;
+                       snd_soc_write(codec, RK3036_CODEC_REG27, val);
+               }
+       }
+       return 0;
+}
+
+static struct rk3036_reg_val_typ playback_power_up_list[] = {
+       /*01*/{RK3036_CODEC_REG24,
+               RK3036_CR24_DAC_SOURCE_WORK},
+       /* open current source. */
+
+       /*02*/{RK3036_CODEC_REG22,
+       RK3036_CR22_DACL_PATH_REFV_WORK|RK3036_CR22_DACR_PATH_REFV_WORK},
+       /* power on dac path reference voltage. */
+
+       /*03*/{RK3036_CODEC_REG27,
+       RK3036_CR27_HPOUTL_POP_WORK|RK3036_CR27_HPOUTR_POP_WORK},
+       /* pop precharge work. */
+
+       /*04*/{RK3036_CODEC_REG23,
+       RK3036_CR23_HPOUTL_EN_WORK|RK3036_CR23_HPOUTR_EN_WORK},
+       /* start-up HPOUTL HPOUTR */
+
+       /*05*/{RK3036_CODEC_REG23,
+       RK3036_CR23_HPOUTL_EN_WORK|RK3036_CR23_HPOUTR_EN_WORK
+       |RK3036_CR23_HPOUTL_WORK|RK3036_CR23_HPOUTR_WORK},
+       /* end the init state of HPOUTL HPOUTR */
+
+       /*06*/{RK3036_CODEC_REG24,
+       RK3036_CR24_DAC_SOURCE_WORK
+       |RK3036_CR24_DAC_PRECHARGE
+       |RK3036_CR24_DACL_REFV_WORK|RK3036_CR24_DACR_REFV_WORK},
+       /* start-up special ref_v of DACL DACR */
+
+       /*07*/{RK3036_CODEC_REG22,
+       RK3036_CR22_DACL_PATH_REFV_WORK|RK3036_CR22_DACR_PATH_REFV_WORK
+       |RK3036_CR22_DACL_CLK_WORK|RK3036_CR22_DACR_CLK_WORK},
+       /* start-up clock modul of LR channel */
+
+       /*08*/{RK3036_CODEC_REG22,
+       RK3036_CR22_DACL_PATH_REFV_WORK|RK3036_CR22_DACR_PATH_REFV_WORK
+       |RK3036_CR22_DACL_CLK_WORK|RK3036_CR22_DACR_CLK_WORK
+       |RK3036_CR22_DACL_WORK|RK3036_CR22_DACR_WORK},
+       /* start-up DACL DACR module */
+
+       /*09*/{RK3036_CODEC_REG27,
+       RK3036_CR27_HPOUTL_POP_WORK|RK3036_CR27_HPOUTR_POP_WORK
+       |RK3036_CR27_DACL_WORK|RK3036_CR27_DACR_WORK},
+       /* end the init state of DACL DACR */
+
+       /*10*/{RK3036_CODEC_REG25, OUT_VOLUME},
+       /*11*/{RK3036_CODEC_REG26, OUT_VOLUME},
+
+       /*12*/{RK3036_CODEC_REG24,
+       RK3036_CR24_DAC_SOURCE_WORK
+       |RK3036_CR24_DAC_PRECHARGE
+       |RK3036_CR24_DACL_REFV_WORK|RK3036_CR24_DACR_REFV_WORK
+       |RK3036_CR24_VOUTL_ZEROD_WORK|RK3036_CR24_VOUTR_ZEROD_WORK},
+       /* according to the need, open the zero-crossing detection function. */
+
+       /*13*/{RK3036_CODEC_REG27,
+       RK3036_CR27_HPOUTL_POP_WORK|RK3036_CR27_HPOUTR_POP_WORK
+       |RK3036_CR27_DACL_WORK|RK3036_CR27_DACR_WORK
+       |RK3036_CR27_HPOUTL_G_WORK|RK3036_CR27_HPOUTR_G_WORK},
+       /* end initial status of HPOUTL HPOUTR module,start normal output. */
+};
+
+#define PLAYBACK_POWER_UP_LIST_LEN ARRAY_SIZE(playback_power_up_list)
+
+static int rk3036_codec_power_up(void)
+{
+       struct snd_soc_codec *codec = rk3036_priv->codec;
+       int i, volume = 0;
+
+       if (!rk3036_priv || !rk3036_priv->codec)
+               return -EINVAL;
+
+       for (i = 0; i < PLAYBACK_POWER_UP_LIST_LEN; i++) {
+               if ((playback_power_up_list[i].reg ==
+                       RK3036_CODEC_REG25) && (volume < OUT_VOLUME)) {
+                       snd_soc_write(codec, RK3036_CODEC_REG25, volume);
+                       snd_soc_write(codec, RK3036_CODEC_REG26, volume);
+                       volume++;
+                       mdelay(10);
+                       i--;
+               } else {
+                       snd_soc_write(codec, playback_power_up_list[i].
+                               reg, playback_power_up_list[i].value);
+                       mdelay(1);
+               }
+       }
+
+       return 0;
+}
+
+#define RK3036_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
+                             SNDRV_PCM_RATE_16000 |    \
+                             SNDRV_PCM_RATE_32000 |    \
+                             SNDRV_PCM_RATE_44100 |    \
+                             SNDRV_PCM_RATE_48000 |    \
+                             SNDRV_PCM_RATE_96000)
+
+#define RK3036_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                       SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE |\
+                       SNDRV_PCM_FMTBIT_S32_LE)
+
+
+static struct snd_soc_dai_ops rk3036_dai_ops = {
+       .hw_params      = rk3036_hw_params,
+       .set_fmt        = rk3036_set_dai_fmt,
+       .set_sysclk     = rk3036_set_dai_sysclk,
+       .digital_mute   = rk3036_digital_mute,
+};
+
+static struct snd_soc_dai_driver rk3036_dai[] = {
+       {
+               .name = "rk3036-voice",
+               .id = RK3036_VOICE,
+               .playback = {
+                       .stream_name = "RK3036 CODEC PCM",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RK3036_PLAYBACK_RATES,
+                       .formats = RK3036_FORMATS,
+               },
+               .ops = &rk3036_dai_ops,
+       },
+};
+
+static unsigned int rk3036_codec_read(struct snd_soc_codec *
+       codec, unsigned int reg)
+{
+       unsigned int value;
+
+       if (!rk3036_priv) {
+               dbg_codec(2, "%s : rk3036 is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (!rk3036_codec_register(codec, reg)) {
+               dbg_codec(2, "%s : reg error!\n", __func__);
+               return -EINVAL;
+       }
+
+       value = readl_relaxed(rk3036_priv->regbase+reg);
+       dbg_codec(2, "%s : reg = 0x%x, val= 0x%x\n", __func__, reg, value);
+
+       return value;
+}
+
+static int rk3036_hw_write(const struct i2c_client *
+       client, const char *buf, int count)
+{
+       unsigned int reg, value;
+
+       if (!rk3036_priv || !rk3036_priv->codec)
+               return -EINVAL;
+
+       if (count == 2) {
+               reg = (unsigned int)buf[0];
+               value = (unsigned int)buf[1];
+               writel(value, rk3036_priv->regbase+reg);
+       } else {
+               dbg_codec(2, "%s : i2c len error\n", __func__);
+       }
+
+       return  count;
+}
+
+static int rk3036_codec_write(struct snd_soc_codec *
+       codec, unsigned int reg, unsigned int value)
+{
+       int new_value = -1;
+
+       if (!rk3036_priv) {
+               dbg_codec(2, "%s : rk3036 is NULL\n", __func__);
+               return -EINVAL;
+       } else if (!rk3036_codec_register(codec, reg)) {
+               dbg_codec(2, "%s : reg error!\n", __func__);
+               return -EINVAL;
+       }
+
+       /*new_value = rk3036_set_init_value(codec, reg, value);*/
+       if (new_value == -1) {
+               writel(value, rk3036_priv->regbase+reg);
+               rk3036_write_reg_cache(codec, reg, value);
+       }
+
+       return 0;
+}
+
+static void spk_ctrl_fun(int status)
+{
+       if (rk3036_priv == NULL)
+               return;
+
+       if (rk3036_priv->spk_ctl_gpio != INVALID_GPIO)
+               gpio_set_value(rk3036_priv->spk_ctl_gpio, status);
+}
+
+static void rk3036_delayedwork_fun(struct work_struct *work)
+{
+       if (rk3036_priv == NULL)
+               return;
+       dbg_codec(2, "rk3036_delayedwork_fun\n");
+       spk_ctrl_fun(SPK_CTRL_OPEN);
+}
+
+static int rk3036_probe(struct snd_soc_codec *codec)
+{
+       struct rk3036_codec_priv *rk3036_codec
+               = snd_soc_codec_get_drvdata(codec);
+       unsigned int val;
+       int ret;
+
+       rk3036_codec->codec = codec;
+
+       clk_prepare_enable(rk3036_codec->pclk);
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+       if (ret != 0)
+               goto err__;
+
+       codec->hw_read = rk3036_codec_read;
+       codec->hw_write = (hw_write_t)rk3036_hw_write;
+       codec->read = rk3036_codec_read;
+       codec->write = rk3036_codec_write;
+
+       INIT_DELAYED_WORK(&rk3036_codec->
+               codec_delayed_work, rk3036_delayedwork_fun);
+
+       val = snd_soc_read(codec, RK3036_CODEC_RESET);
+       if (val != rk3036_reg_defaults[RK3036_CODEC_RESET]) {
+               ret = -ENODEV;
+               goto err__;
+       }
+
+       /* config i2s output to acodec module. */
+       val = readl_relaxed(RK_GRF_VIRT + RK3036_GRF_SOC_CON0);
+       writel_relaxed(val | 0x04000400, RK_GRF_VIRT + RK3036_GRF_SOC_CON0);
+
+       rk3036_reset(codec);
+
+       snd_soc_write(codec, RK3036_CODEC_REG24, RK3036_CR24_DAC_SOURCE_STOP
+                                               | RK3036_CR24_DAC_PRECHARGE
+                                               | RK3036_CR24_DACL_REFV_STOP
+                                               | RK3036_CR24_DACR_REFV_STOP
+                                               | RK3036_CR24_VOUTL_ZEROD_STOP
+                                               | RK3036_CR24_VOUTR_ZEROD_STOP);
+#ifdef WITH_CAP
+       /*set for capacity output,clear up noise*/
+       snd_soc_write(codec, RK3036_CODEC_REG28, 0x37);
+       mdelay(50);
+       /*snd_soc_write(codec, 0xbc,0x28);*/
+#endif
+
+       rk3036_codec_power_up();
+
+       schedule_delayed_work(&rk3036_codec->
+               codec_delayed_work, msecs_to_jiffies(5000));
+       codec->dapm.bias_level = SND_SOC_BIAS_PREPARE;
+
+       return 0;
+
+err__:
+       dbg_codec(2, "%s err ret=%d\n", __func__, ret);
+       return ret;
+}
+
+static int rk3036_remove(struct snd_soc_codec *codec)
+{
+       if (!rk3036_priv) {
+               dbg_codec(2, "%s : rk3036_priv is NULL\n", __func__);
+               return 0;
+       }
+
+       spk_ctrl_fun(SPK_CTRL_CLOSE);
+
+       mdelay(10);
+       snd_soc_write(codec, RK3036_CODEC_RESET, 0xfc);
+       mdelay(10);
+       snd_soc_write(codec, RK3036_CODEC_RESET, 0x3);
+       mdelay(10);
+
+       return 0;
+}
+
+static int rk3036_suspend(struct snd_soc_codec *codec)
+{
+       rk3036_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int rk3036_resume(struct snd_soc_codec *codec)
+{
+       rk3036_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+
+static int rk3036_set_bias_level(struct snd_soc_codec *codec, enum
+       snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               break;
+       }
+       codec->dapm.bias_level = level;
+       return 0;
+}
+
+static int rk3036_volatile_register(struct snd_soc_codec *
+                               codec, unsigned int reg)
+{
+       switch (reg) {
+       case RK3036_CODEC_RESET:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int rk3036_codec_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case RK3036_CODEC_RESET:
+       case RK3036_CODEC_REG03:
+       case RK3036_CODEC_REG04:
+       case RK3036_CODEC_REG05:
+       case RK3036_CODEC_REG22:
+       case RK3036_CODEC_REG23:
+       case RK3036_CODEC_REG24:
+       case RK3036_CODEC_REG25:
+       case RK3036_CODEC_REG26:
+       case RK3036_CODEC_REG27:
+       case RK3036_CODEC_REG28:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_rk3036 = {
+       .probe = rk3036_probe,
+       .remove = rk3036_remove,
+       .suspend = rk3036_suspend,
+       .resume = rk3036_resume,
+       .set_bias_level = rk3036_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(rk3036_reg_defaults),
+       .reg_word_size = sizeof(unsigned int),
+       .reg_cache_default = rk3036_reg_defaults,
+       .volatile_register = rk3036_volatile_register,
+       .readable_register = rk3036_codec_register,
+       .reg_cache_step = sizeof(unsigned int),
+};
+
+static int rk3036_platform_probe(struct platform_device *pdev)
+{
+       struct device_node *rk3036_np = pdev->dev.of_node;
+       struct rk3036_codec_priv *rk3036;
+       struct resource *res;
+       int ret;
+
+       rk3036 = devm_kzalloc(&pdev->dev, sizeof(*rk3036), GFP_KERNEL);
+       if (!rk3036) {
+               dbg_codec(2, "%s : rk3036 priv kzalloc failed!\n", __func__);
+               return -ENOMEM;
+       }
+       rk3036_priv = rk3036;
+       platform_set_drvdata(pdev, rk3036);
+
+       rk3036->spk_ctl_gpio = of_get_named_gpio(rk3036_np, "spk_ctl_io", 0);
+       if (!gpio_is_valid(rk3036->spk_ctl_gpio)) {
+               dbg_codec(2, "invalid reset_gpio: %d\n", rk3036->spk_ctl_gpio);
+               ret = -ENOENT;
+               goto err__;
+       }
+
+       ret = devm_gpio_request(&pdev->dev, rk3036->spk_ctl_gpio, "spk_ctl");
+       if (ret < 0) {
+               dbg_codec(2, "rk3036_platform_probe spk_ctl_gpio fail\n");
+               goto err__;
+       }
+
+       gpio_direction_output(rk3036->spk_ctl_gpio, SPK_CTRL_CLOSE);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rk3036->regbase = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(rk3036->regbase))
+               return PTR_ERR(rk3036->regbase);
+
+       rk3036->pclk = devm_clk_get(&pdev->dev, "g_pclk_acodec");
+       if (IS_ERR(rk3036->pclk)) {
+               dev_err(&pdev->dev, "Unable to get acodec hclk\n");
+               ret = -ENXIO;
+               goto err__;
+       }
+
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk3036,
+                               rk3036_dai, ARRAY_SIZE(rk3036_dai));
+
+err__:
+       platform_set_drvdata(pdev, NULL);
+       rk3036_priv = NULL;
+       return ret;
+}
+
+static int rk3036_platform_remove(struct platform_device *pdev)
+{
+       rk3036_priv = NULL;
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+void rk3036_platform_shutdown(struct platform_device *pdev)
+{
+       if (!rk3036_priv || !rk3036_priv->codec)
+               return;
+
+       spk_ctrl_fun(SPK_CTRL_CLOSE);
+
+       mdelay(10);
+       writel(0xfc, rk3036_priv->regbase+RK3036_CODEC_RESET);
+       mdelay(10);
+       writel(0x03, rk3036_priv->regbase+RK3036_CODEC_RESET);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id rk3036codec_of_match[] = {
+               { .compatible = "rk3036-codec"},
+               {},
+};
+MODULE_DEVICE_TABLE(of, rk3036codec_of_match);
+#endif
+
+static struct platform_driver rk3036_codec_driver = {
+       .driver = {
+                  .name = "rk3036-codec",
+                  .owner = THIS_MODULE,
+                  .of_match_table = of_match_ptr(rk3036codec_of_match),
+                  },
+       .probe = rk3036_platform_probe,
+       .remove = rk3036_platform_remove,
+       .shutdown = rk3036_platform_shutdown,
+};
+module_platform_driver(rk3036_codec_driver);
+
+/* Module information */
+MODULE_AUTHOR("rockchip");
+MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rk3036_codec.h b/sound/soc/codecs/rk3036_codec.h
new file mode 100644 (file)
index 0000000..f2bd981
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *
+ * Copyright (C) 2014 rockchip
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _RK3036_CODEC_H
+#define _RK3036_CODEC_H
+
+/* codec register */
+#define RK3036_CODEC_RESET                     (0x00 << 2)
+#define RK3036_CODEC_REG03                     (0x03 << 2)
+#define RK3036_CODEC_REG04                     (0x04 << 2)
+#define RK3036_CODEC_REG05                     (0x05 << 2)
+
+#define RK3036_CODEC_REG22                     (0x22 << 2)
+#define RK3036_CODEC_REG23                     (0x23 << 2)
+#define RK3036_CODEC_REG24                     (0x24 << 2)
+#define RK3036_CODEC_REG25                     (0x25 << 2)
+#define RK3036_CODEC_REG26                     (0x26 << 2)
+#define RK3036_CODEC_REG27                     (0x27 << 2)
+#define RK3036_CODEC_REG28                     (0x28 << 2)
+
+/* RK3036_CODEC_RESET */
+#define RK3036_CR00_DIGITAL_RESET           (0 << 1)
+#define RK3036_CR00_DIGITAL_WORK            (1 << 1)
+#define RK3036_CR00_SYSTEM_RESET            (0 << 0)
+#define RK3036_CR00_SYSTEM_WORK             (1 << 0)
+
+/*RK3036_CODEC_REG03*/
+#define RK3036_CR03_DIRECTION_MASK          (1 << 5)
+#define RK3036_CR03_DIRECTION_IN            (0 << 5)
+#define RK3036_CR03_DIRECTION_IOUT          (1 << 5)
+#define RK3036_CR03_I2SMODE_MASK            (1 << 4)
+#define RK3036_CR03_I2SMODE_SLAVE           (0 << 4)
+#define RK3036_CR03_I2SMODE_MASTER          (1 << 4)
+
+/*RK3036_CODEC_REG04*/
+#define RK3036_CR04_I2SLRC_MASK             (1 << 7)
+#define RK3036_CR04_I2SLRC_NORMAL           (0 << 7)
+#define RK3036_CR04_I2SLRC_REVERSAL         (1 << 7)
+#define RK3036_CR04_HFVALID_MASK            (3 << 5)
+#define RK3036_CR04_HFVALID_16BITS          (0 << 5)
+#define RK3036_CR04_HFVALID_20BITS          (1 << 5)
+#define RK3036_CR04_HFVALID_24BITS          (2 << 5)
+#define RK3036_CR04_HFVALID_32BITS          (3 << 5)
+#define RK3036_CR04_MODE_MASK               (3 << 3)
+#define RK3036_CR04_MODE_RIGHT              (0 << 3)
+#define RK3036_CR04_MODE_LEFT               (1 << 3)
+#define RK3036_CR04_MODE_I2S                (2 << 3)
+#define RK3036_CR04_MODE_PCM                (3 << 3)
+#define RK3036_CR04_LR_SWAP_MASK            (1 << 2)
+#define RK3036_CR04_LR_SWAP_DIS             (0 << 2)
+#define RK3036_CR04_LR_SWAP_EN              (1 << 2)
+
+/*RK3036_CODEC_REG05*/
+#define RK3036_CR05_FRAMEH_MASK             (3 << 2)
+#define RK3036_CR05_FRAMEH_16BITS           (0 << 2)
+#define RK3036_CR05_FRAMEH_20BITS           (1 << 2)
+#define RK3036_CR05_FRAMEH_24BITS           (2 << 2)
+#define RK3036_CR05_FRAMEH_32BITS           (3 << 2)
+#define RK3036_CR05_DAC_RESET_MASK          (1 << 1)
+#define RK3036_CR05_DAC_RESET_EN            (0 << 1)
+#define RK3036_CR05_DAC_RESET_DIS           (1 << 1)
+#define RK3036_CR05_BCLKPOL_MASK            (1 << 0)
+#define RK3036_CR05_BCLKPOL_NORMAL          (0 << 0)
+#define RK3036_CR05_BCLKPOL_REVERSAL        (1 << 0)
+
+/*RK3036_CODEC_REG22*/
+#define RK3036_CR22_DACL_PATH_REFV_MASK     (1 << 5)
+#define RK3036_CR22_DACL_PATH_REFV_STOP     (0 << 5)
+#define RK3036_CR22_DACL_PATH_REFV_WORK     (1 << 5)
+#define RK3036_CR22_DACR_PATH_REFV_MASK     (1 << 4)
+#define RK3036_CR22_DACR_PATH_REFV_STOP     (0 << 4)
+#define RK3036_CR22_DACR_PATH_REFV_WORK     (1 << 4)
+#define RK3036_CR22_DACL_CLK_STOP           (0 << 3)
+#define RK3036_CR22_DACL_CLK_WORK           (1 << 3)
+#define RK3036_CR22_DACR_CLK_STOP           (0 << 2)
+#define RK3036_CR22_DACR_CLK_WORK           (1 << 2)
+#define RK3036_CR22_DACL_STOP               (0 << 1)
+#define RK3036_CR22_DACL_WORK               (1 << 1)
+#define RK3036_CR22_DACR_STOP               (0 << 0)
+#define RK3036_CR22_DACR_WORK               (1 << 0)
+
+/*RK3036_CODEC_REG23*/
+#define RK3036_CR23_HPOUTL_INIT             (0 << 3)
+#define RK3036_CR23_HPOUTL_WORK             (1 << 3)
+#define RK3036_CR23_HPOUTR_INIT             (0 << 2)
+#define RK3036_CR23_HPOUTR_WORK             (1 << 2)
+#define RK3036_CR23_HPOUTL_EN_STOP          (0 << 1)
+#define RK3036_CR23_HPOUTL_EN_WORK          (1 << 1)
+#define RK3036_CR23_HPOUTR_EN_STOP          (0 << 0)
+#define RK3036_CR23_HPOUTR_EN_WORK          (1 << 0)
+
+/*RK3036_CODEC_REG24*/
+#define RK3036_CR24_DAC_SOURCE_STOP         (0 << 5)
+#define RK3036_CR24_DAC_SOURCE_WORK         (1 << 5)
+#define RK3036_CR24_DAC_PRECHARGE           (0 << 4)
+#define RK3036_CR24_DAC_DISCHARGE           (1 << 4)
+#define RK3036_CR24_DACL_REFV_STOP          (0 << 3)
+#define RK3036_CR24_DACL_REFV_WORK          (1 << 3)
+#define RK3036_CR24_DACR_REFV_STOP          (0 << 2)
+#define RK3036_CR24_DACR_REFV_WORK          (1 << 2)
+#define RK3036_CR24_VOUTL_ZEROD_STOP        (0 << 1)
+#define RK3036_CR24_VOUTL_ZEROD_WORK        (1 << 1)
+#define RK3036_CR24_VOUTR_ZEROD_STOP        (0 << 0)
+#define RK3036_CR24_VOUTR_ZEROD_WORK        (1 << 0)
+
+/*RK3036_CODEC_REG27*/
+#define RK3036_CR27_DACL_INIT               (0 << 7)
+#define RK3036_CR27_DACL_WORK               (1 << 7)
+#define RK3036_CR27_DACR_INIT               (0 << 6)
+#define RK3036_CR27_DACR_WORK               (1 << 6)
+#define RK3036_CR27_HPOUTL_G_MUTE           (0 << 5)
+#define RK3036_CR27_HPOUTL_G_WORK           (1 << 5)
+#define RK3036_CR27_HPOUTR_G_MUTE           (0 << 4)
+#define RK3036_CR27_HPOUTR_G_WORK           (1 << 4)
+#define RK3036_CR27_HPOUTL_POP_PRECHARGE    (1 << 2)
+#define RK3036_CR27_HPOUTL_POP_WORK         (2 << 2)
+#define RK3036_CR27_HPOUTR_POP_PRECHARGE    (1 << 0)
+#define RK3036_CR27_HPOUTR_POP_WORK         (2 << 0)
+
+/*RK3036_CODEC_REG28*/
+#define RK3036_CR28_YES_027I                (0 << 5)
+#define RK3036_CR28_NON_027I                (1 << 5)
+#define RK3036_CR28_YES_050I                (0 << 4)
+#define RK3036_CR28_NON_050I                (1 << 4)
+#define RK3036_CR28_YES_100I                (0 << 3)
+#define RK3036_CR28_NON_100I                (1 << 3)
+#define RK3036_CR28_YES_130I                (0 << 2)
+#define RK3036_CR28_NON_130I                (1 << 2)
+#define RK3036_CR28_YES_260I                (0 << 1)
+#define RK3036_CR28_NON_260I                (1 << 1)
+#define RK3036_CR28_YES_400I                (0 << 0)
+#define RK3036_CR28_NON_400I                (1 << 0)
+
+enum {
+       RK3036_HIFI,
+       RK3036_VOICE,
+};
+
+struct rk3036_reg_val_typ {
+       unsigned int reg;
+       unsigned int value;
+};
+
+struct rk3036_init_bit_typ {
+       unsigned int reg;
+       unsigned int power_bit;
+       unsigned int init2_bit;
+       unsigned int init1_bit;
+       unsigned int init0_bit;
+};
+
+#endif
old mode 100755 (executable)
new mode 100644 (file)
index 50f1edf..5e08eca
@@ -117,7 +117,7 @@ config SND_RK_SOC_RT5631
        help
          Say Y if you want to add support for SoC audio on rockchip
          with the RT5631.
-         
+
 config SND_RK_SOC_RT5631_PHONE
        tristate "SoC I2S Audio support for rockchip(phone) - RT5631"
        depends on SND_RK_SOC
@@ -127,7 +127,7 @@ config SND_RK_SOC_RT5631_PHONE
          Say Y if you want to add support for SoC audio on rockchip
          with the RT5631.
          Driver code to use on the phone or voice Tablet.
-         
+
 config SND_RK_SOC_RT5625
        tristate "SoC I2S Audio support for rockchip - RT5625"
        depends on SND_RK_SOC
@@ -160,7 +160,7 @@ config SND_RK_SOC_RT5640
        select SND_SOC_RT5640
        help
           RT5640 is pin to pin as RT5642, but not have dsp function.
-         
+
 config SND_RK_SOC_RT3224
        tristate "SoC I2S Audio support for rockchip - RT3224"
        depends on SND_RK_SOC
@@ -168,7 +168,7 @@ config SND_RK_SOC_RT3224
        select SND_SOC_RT3224
        help
          RT3224 is pin to pin as RT3261, but not have dsp function.
-         
+
 config SND_RK_SOC_RT5639
        tristate "SoC I2S Audio support for rockchip - RT5639"
        depends on SND_RK_SOC
@@ -176,7 +176,7 @@ config SND_RK_SOC_RT5639
        select SND_SOC_RT5639
        help
          rt5639
-         
+
 config SND_RK_SOC_RT5616
        tristate "SoC I2S Audio support for rockchip - RT5616"
        depends on SND_RK_SOC
@@ -185,7 +185,7 @@ config SND_RK_SOC_RT5616
        help
          Say Y if you want to add support for SoC audio on rockchip
          with the RT5616.
-         
+
 config SND_RK_SOC_RT3261
        tristate "SoC I2S Audio support for rockchip - RT3261"
        depends on SND_RK_SOC
@@ -240,6 +240,15 @@ config SND_RK_SOC_RK1000
          Say Y if you want to add support for SoC audio on rockchip
          with the RK1000.
 
+config SND_RK_SOC_RK3036
+       tristate "SoC I2S Audio support for rockchip - RK3036"
+       depends on SND_RK_SOC
+       select SND_RK_SOC_I2S
+       select SND_SOC_RK3036
+       help
+         Say Y if you want to add support for SoC audio on rockchip
+         with the RK3036 s40.
+
 config SND_RK_SOC_RK610
        tristate "SoC I2S Audio support for rockchip - RK610"
        depends on SND_RK_SOC && MFD_RK610
old mode 100755 (executable)
new mode 100644 (file)
index 2c731cc..16c7e03
@@ -27,6 +27,7 @@ snd-soc-cs42l52-objs := rk_cs42l52.o
 snd-soc-aic3111-objs := rk_aic3111.o
 snd-soc-wm8988-objs := rk_wm8988.o
 snd-soc-rk1000-objs := rk_rk1000codec.o
+snd-soc-rk3036-objs := rk_rk3036.o
 snd-soc-wm8994-objs := rk_wm8994.o
 snd-soc-rk610-objs := rk_jetta_codec.o
 snd-soc-rk616-objs := rk_rk616.o
@@ -54,6 +55,7 @@ obj-$(CONFIG_SND_RK_SOC_RT3224) += snd-soc-rt3224.o
 obj-$(CONFIG_SND_RK_SOC_RT5639) += snd-soc-rt5639.o
 obj-$(CONFIG_SND_RK_SOC_RT5616) += snd-soc-rt5616.o
 obj-$(CONFIG_SND_RK_SOC_RK1000) += snd-soc-rk1000.o
+obj-$(CONFIG_SND_RK_SOC_RK3036) += snd-soc-rk3036.o
 obj-$(CONFIG_SND_RK_SOC_CS42L52) += snd-soc-cs42l52.o
 obj-$(CONFIG_SND_RK_SOC_AIC3111) += snd-soc-aic3111.o
 obj-$(CONFIG_SND_RK_SOC_AIC3262) += snd-soc-aic3262.o
index 72784ab2058a76fb972957cb35ed5415fa7807f1..cb5d532f1fcd3cf46c96aa010e04f04fe9729bbd 100755 (executable)
@@ -494,14 +494,14 @@ static int rockchip_i2s_suspend_noirq(struct device *dev)
 {
        I2S_DBG("Enter %s, %d\n", __func__, __LINE__);
 
-       return pinctrl_select_state(dev->pins->p, dev->pins->sleep_state);
+       return pinctrl_pm_select_sleep_state(dev);
 }
 
 static int rockchip_i2s_resume_noirq(struct device *dev)
 {
        I2S_DBG("Enter %s, %d\n", __func__, __LINE__);
 
-       return pinctrl_select_state(dev->pins->p, dev->pins->default_state);
+       return pinctrl_pm_select_default_state(dev);
 }
 #else
 #define rockchip_i2s_suspend_noirq NULL
diff --git a/sound/soc/rockchip/rk_rk3036.c b/sound/soc/rockchip/rk_rk3036.c
new file mode 100644 (file)
index 0000000..ae413af
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+* rk_rk3036codec.c-- SoC audio for rockchip
+*
+* Driver for rockchip internal rk_rk3036codec audio
+*
+* 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.
+*
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include "../codecs/rk3036_codec.h"
+#include "card_info.h"
+#include "rk_pcm.h"
+#include "rk_i2s.h"
+
+static int rk30_hw_params(struct snd_pcm_substream *
+       substream, struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       unsigned int dai_fmt = rtd->dai_link->dai_fmt;
+       int ret;
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
+       if (ret < 0)
+               return ret;
+
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * Logic for a rk3036 codec as connected on a rockchip board.
+ */
+static int rk30_rk3036_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+       return 0;
+}
+
+static struct snd_soc_ops rk30_ops = {
+         .hw_params = rk30_hw_params,
+};
+
+static struct snd_soc_dai_link rk30_dai[] = {
+       {
+               .name = "RK3036",
+               .stream_name = "RK3036 CODEC PCM",
+               .codec_dai_name = "rk3036-voice",
+               .init = rk30_rk3036_codec_init,
+               .ops = &rk30_ops,
+       }
+};
+
+static struct snd_soc_card rockchip_rk3036_snd_card = {
+       .name = "RK_RK3036",
+       .dai_link = rk30_dai,
+       .num_links = 1,
+};
+
+static int rockchip_rk3036_audio_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct snd_soc_card *card = &rockchip_rk3036_snd_card;
+
+       card->dev = &pdev->dev;
+
+       ret = rockchip_of_get_sound_card_info(card);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_register_card(card);
+
+       return ret;
+}
+
+static int rockchip_rk3036_audio_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id rockchip_rk3036_of_match[] = {
+               { .compatible = "rk3036-audio", },
+               {},
+};
+MODULE_DEVICE_TABLE(of, rockchip_rk3036_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver rockchip_rk3036_audio_driver = {
+       .driver = {
+               .name   = "rk3036-audio",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(rockchip_rk3036_of_match),
+       },
+       .probe      = rockchip_rk3036_audio_probe,
+       .remove     = rockchip_rk3036_audio_remove,
+};
+module_platform_driver(rockchip_rk3036_audio_driver);
+
+/* Module information */
+MODULE_AUTHOR("rockchip");
+MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
+MODULE_LICENSE("GPL");
old mode 100755 (executable)
new mode 100644 (file)
index dcc13e5..7680946
 #include <sound/initval.h>
 #include <sound/soc.h>
 #include <sound/dmaengine_pcm.h>
-
 #include <linux/spinlock.h>
-
 #include "rk_pcm.h"
 
-#if 0
+#undef  DEBUG_SPDIF
+#define DEBUG_SPDIF 0
+
+#if DEBUG_SPDIF
 #define RK_SPDIF_DBG(x...) pr_info("rk_spdif:"x)
 #else
 #define RK_SPDIF_DBG(x...) do { } while (0)
 #endif
 
-
 /* Registers */
 #define CFGR                  0x00
 #define SDBLR                 0x04
 #define INTCR_SDBEIE_MASK           (1<<4)
 
 struct rockchip_spdif_info {
-       spinlock_t      lock;
+       spinlock_t      lock;/*lock parmeter setting.*/
        void __iomem    *regs;
        unsigned long   clk_rate;
        struct clk      *clk;
@@ -165,33 +165,33 @@ static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
                opr |= DMACR_TRAN_DMA_ENABLE;
                writel(xfer, regs + XFER);
                writel(opr, regs + DMACR);
-               RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n",
-                       readl(regs + XFER), readl(regs + DMACR));
+               RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n", readl(
+                       regs + XFER), readl(regs + DMACR));
        } else {
                xfer &= ~XFER_TRAN_START;
                opr &= ~DMACR_TRAN_DMA_ENABLE;
                writel(xfer, regs + XFER);
                writel(opr, regs + DMACR);
                writel(1<<7, regs + CFGR);
-               RK_SPDIF_DBG("off xfer=0x%x,opr=0x%x\n",
-                       readl(regs + XFER), readl(regs + DMACR));
+               RK_SPDIF_DBG("off xfer=0x%x,opr=0x%x\n", readl(
+                       regs + XFER), readl(regs + DMACR));
        }
 }
 
-static int spdif_set_syclk(struct snd_soc_dai *cpu_dai,
-                               int clk_id, unsigned int freq, int dir)
+static int spdif_set_syclk(struct snd_soc_dai *
+       cpu_dai, int clk_id, unsigned int freq, int dir)
 {
        struct rockchip_spdif_info *spdif = to_info(cpu_dai);
 
-       RK_SPDIF_DBG("Entered %s\n", __func__);
+       RK_SPDIF_DBG("Entered %s sysclk=%d\n", __func__, freq);
 
        spdif->clk_rate = freq;
 
        return 0;
 }
 
-static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
-                               struct snd_soc_dai *dai)
+static int spdif_trigger(struct snd_pcm_substream *
+               substream, int cmd, struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
@@ -221,10 +221,9 @@ static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
        return 0;
 }
 
-
-static int spdif_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *dai)
+static int spdif_hw_params(struct snd_pcm_substream *
+               substream, struct snd_pcm_hw_params *params,
+               struct snd_soc_dai *dai)
 {
        struct rockchip_spdif_info *spdif = to_info(dai);
        void __iomem *regs = spdif->regs;
@@ -235,9 +234,9 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
 
        RK_SPDIF_DBG("Entered %s\n", __func__);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                dai->playback_dma_data = &spdif->dma_playback;
-       else {
+       else {
                pr_err("spdif:Capture is not supported\n");
                return -EINVAL;
        }
@@ -314,8 +313,9 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
                chnsr_byte[0] |= (0x1<<1);
                chnsr_byte[4] = (0x0<<4)|(0x00<<1|0x0);
        }
-       writel((chnsr_byte[4] << 16) | (chnsr_byte[4]),
-               regs + SPDIF_CHNSR02_ADDR);
+       writel((chnsr_byte[4] << 16)
+                       | (chnsr_byte[4]),
+                       regs + SPDIF_CHNSR02_ADDR);
        writel((chnsr_byte[3] << 24) | (chnsr_byte[2] << 16) |
                (chnsr_byte[3] << 8) | (chnsr_byte[2]),
                regs + SPDIF_CHNSR01_ADDR);
@@ -412,61 +412,58 @@ static const struct snd_soc_component_driver rockchip_spdif_component = {
 
 static int spdif_probe(struct platform_device *pdev)
 {
+       /*struct device_node *spdif_np = pdev->dev.of_node;*/
+       struct resource *memregion;
        struct resource *mem_res;
        struct rockchip_spdif_info *spdif;
-       struct clk *spdif_hclk;
        int ret;
 
        RK_SPDIF_DBG("Entered %s\n", __func__);
 
-       spdif = devm_kzalloc(&pdev->dev,
-               sizeof(struct rockchip_spdif_info),
-               GFP_KERNEL);
+       spdif = devm_kzalloc(&pdev->dev, sizeof(
+               struct rockchip_spdif_info), GFP_KERNEL);
        if (!spdif) {
                dev_err(&pdev->dev, "Can't allocate spdif info\n");
                return -ENOMEM;
        }
+       platform_set_drvdata(pdev, spdif);
 
        spin_lock_init(&spdif->lock);
 
+       /* get spdif register regoin. */
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem_res) {
-               pr_err("spdif:Unable to get register resource.\n");
-               return -ENXIO;
+               dev_err(&pdev->dev, "No memory resource\n");
+               ret = -ENOENT;
+               goto err_;
+       }
+       memregion = devm_request_mem_region(&pdev->
+                       dev, mem_res->start,
+                       resource_size(mem_res), "rockchip-spdif");
+       if (!memregion) {
+               dev_err(&pdev->dev, "Memory region already claimed\n");
+               ret = -EBUSY;
+               goto err_;
+       }
+       spdif->regs = devm_ioremap(&pdev->dev, memregion->
+                       start, resource_size(memregion));
+       if (!spdif->regs) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               ret = -ENOMEM;
+               goto err_;
        }
 
-       spdif->clk = clk_get(&pdev->dev, "spdif_8ch_mclk");
+       /* get spdif clock and init. */
+       spdif->clk = devm_clk_get(&pdev->dev, "spdif_mclk");
        if (IS_ERR(spdif->clk)) {
                dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
-               return PTR_ERR(spdif->clk);
+               ret = -ENOMEM;
+               goto err_;
        }
        clk_set_rate(spdif->clk, 12288000);
        clk_set_rate(spdif->clk, 11289600);
        clk_prepare_enable(spdif->clk);
 
-       spdif_hclk = clk_get(&pdev->dev, "spdif_hclk");
-       if(IS_ERR(spdif_hclk) ) {
-               dev_err(&pdev->dev, "get spdif_hclk failed.\n");
-       } else {
-               clk_prepare_enable(spdif_hclk);
-       }
-
-       /* Request S/PDIF Register's memory region */
-       if (!request_mem_region(mem_res->start,
-               resource_size(mem_res), "rockchip-spdif")) {
-               pr_err("spdif:Unable to request register region\n");
-               ret = -EBUSY;
-               goto err_clk_put;
-       }
-
-       spdif->regs = devm_ioremap(&pdev->dev,
-               mem_res->start, resource_size(mem_res));
-       if (!spdif->regs) {
-               dev_err(&pdev->dev, "ioremap failed\n");
-               ret = -ENOMEM;
-               goto err_clk_put;
-       }
-
        spdif->dma_playback.addr = mem_res->start + DATA_OUTBUF;
        spdif->dma_playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        spdif->dma_playback.maxburst = 4;
@@ -474,33 +471,27 @@ static int spdif_probe(struct platform_device *pdev)
        /* set dev name to driver->name for sound card register */
        dev_set_name(&pdev->dev, "%s", pdev->dev.driver->name);
 
-       ret = snd_soc_register_component(&pdev->dev,
-               &rockchip_spdif_component,
-               &rockchip_spdif_dai, 1);
+       ret = snd_soc_register_component(&pdev->
+               dev, &rockchip_spdif_component, &rockchip_spdif_dai, 1);
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
                ret = -ENOMEM;
-               goto err_clk_put;
+               goto err_;
        }
 
        ret = rockchip_pcm_platform_register(&pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
-               goto err_unregister_component;
+               goto err_;
        }
 
-       dev_set_drvdata(&pdev->dev, spdif);
-       writel_relaxed(SPDIF_CHANNEL_SEL_8CH,
-               RK_GRF_VIRT + RK3288_GRF_SOC_CON2);
-
        RK_SPDIF_DBG("spdif:spdif probe ok!\n");
 
        return 0;
 
-err_unregister_component:
-       snd_soc_unregister_component(&pdev->dev);
-err_clk_put:
-       clk_put(spdif->clk);
+err_:
+       platform_set_drvdata(pdev, NULL);
+
        return ret;
 }