summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Konovalov <andrey.konovalov@linaro.org>2012-09-20 23:57:27 +0400
committerAndrey Konovalov <andrey.konovalov@linaro.org>2012-09-20 23:57:27 +0400
commit843d0cd3f41dfb7eb43a2b13809c9498bdfedcc5 (patch)
treeaa55087e252ca601da6ed64856ebc249f5e3cee8
parentf71817d607a828617841342d54ab3894f0bc7790 (diff)
parent29627b0b3c1f239674378a2ee7cc8aee0c9447c6 (diff)
Merge branch 'tracking-samslt-all' into merge-linux-linaro
-rw-r--r--Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt152
-rw-r--r--Documentation/devicetree/bindings/fb/samsung-fb.txt148
-rw-r--r--Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt36
-rw-r--r--Documentation/devicetree/bindings/mmc/samsung-sdhci.txt51
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt196
-rw-r--r--Documentation/devicetree/bindings/regulator/max8997-pmic.txt147
-rw-r--r--Documentation/devicetree/bindings/sound/samsung-i2s.txt62
-rw-r--r--Documentation/devicetree/bindings/usb/s3c-hsotg.txt16
-rw-r--r--Makefile7
-rw-r--r--arch/arm/boot/dts/exynos4210-origen.dts261
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi54
-rw-r--r--arch/arm/configs/android_origen_defconfig210
-rw-r--r--arch/arm/configs/exynos4_defconfig128
-rw-r--r--arch/arm/configs/ubuntu_origen_defconfig242
-rw-r--r--arch/arm/mach-exynos/Kconfig6
-rw-r--r--arch/arm/mach-exynos/Makefile1
-rw-r--r--arch/arm/mach-exynos/asv-4210.c339
-rw-r--r--arch/arm/mach-exynos/asv.c71
-rw-r--r--arch/arm/mach-exynos/clock-exynos4.c137
-rw-r--r--arch/arm/mach-exynos/common.c179
-rw-r--r--arch/arm/mach-exynos/dma.c2
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/asv.h43
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/cpufreq.h2
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/irqs.h1
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/mali/config.h173
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/map.h7
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/regs-audss.h8
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/regs-clock.h18
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/regs-gpio.h4
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/regs-iem.h27
-rw-r--r--arch/arm/mach-exynos/include/mach-exynos/ump/config.h18
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c64
-rw-r--r--arch/arm/mach-exynos/mach-origen.c289
-rw-r--r--arch/arm/mach-exynos/pm.c3
-rw-r--r--arch/arm/mach-exynos/pm_domains.c8
-rw-r--r--arch/arm/plat-samsung/Kconfig5
-rw-r--r--arch/arm/plat-samsung/clock.c10
-rw-r--r--arch/arm/plat-samsung/devs.c19
-rw-r--r--arch/arm/plat-samsung/include/plat-samsung/devs.h1
-rw-r--r--arch/arm/plat-samsung/include/plat-samsung/map-s5p.h2
-rw-r--r--arch/arm/plat-samsung/include/plat-samsung/regs-fb.h14
-rw-r--r--arch/arm/plat-samsung/s5p-dev-mfc.c51
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/base/power/domain.c4
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c53
-rw-r--r--drivers/cpufreq/exynos4210-cpufreq.c61
-rw-r--r--drivers/dma/pl330.c1
-rw-r--r--drivers/gpio/gpio-samsung.c21
-rw-r--r--drivers/gpu/Makefile2
-rw-r--r--drivers/gpu/arm/Kconfig2
-rw-r--r--drivers/gpu/arm/Makefile2
-rw-r--r--drivers/gpu/arm/mali/Kconfig75
-rwxr-xr-xdrivers/gpu/arm/mali/Makefile272
-rw-r--r--drivers/gpu/arm/mali/arch/config.h132
-rw-r--r--drivers/gpu/arm/mali/common/mali_block_allocator.c391
-rw-r--r--drivers/gpu/arm/mali/common/mali_block_allocator.h18
-rw-r--r--drivers/gpu/arm/mali/common/mali_cinstr_profiling_events_m200.h117
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_GP2.c1500
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_MALI200.c1286
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_common.h171
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_core.c911
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_core.h134
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.c183
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.h99
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_gp.h21
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c517
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_l2_cache.h25
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_mem.h17
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c1426
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c3158
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.h75
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_mem_os.c346
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_mem_os.h37
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_memory_engine.c363
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_memory_engine.h148
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_pp.h21
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_profiling.h121
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_rendercore.c2021
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_rendercore.h565
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_session_manager.h19
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_subsystem.h107
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_utilization.c221
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_utilization.h44
-rw-r--r--drivers/gpu/arm/mali/common/mali_kernel_vsync.c49
-rw-r--r--drivers/gpu/arm/mali/common/mali_osk.h1715
-rw-r--r--drivers/gpu/arm/mali/common/mali_osk_bitops.h166
-rw-r--r--drivers/gpu/arm/mali/common/mali_osk_list.h184
-rw-r--r--drivers/gpu/arm/mali/common/mali_osk_mali.h252
-rw-r--r--drivers/gpu/arm/mali/common/mali_osk_profiling.h181
-rw-r--r--drivers/gpu/arm/mali/common/mali_uk_types.h1167
-rw-r--r--drivers/gpu/arm/mali/common/mali_ukk.h718
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm.c1006
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm.h348
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.c350
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.h87
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.c243
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h155
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.c80
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.h62
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c470
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h80
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c721
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h295
-rw-r--r--drivers/gpu/arm/mali/common/pmm/mali_pmm_system.h66
-rw-r--r--drivers/gpu/arm/mali/include/cinstr/mali_cinstr_profiling_events_m200.h114
-rw-r--r--drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h31
-rw-r--r--drivers/gpu/arm/mali/linux/mali_device_pause_resume.c72
-rw-r--r--drivers/gpu/arm/mali/linux/mali_device_pause_resume.h19
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h78
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_linux.c494
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_linux.h46
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_pm.c645
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_pm.h19
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c402
-rw-r--r--drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h30
-rw-r--r--drivers/gpu/arm/mali/linux/mali_linux_pm.h53
-rw-r--r--drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h37
-rw-r--r--drivers/gpu/arm/mali/linux/mali_linux_trace.h124
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_atomics.c55
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.c92
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.h48
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_irq.c262
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_locks.c249
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c590
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_mali.c52
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_math.c22
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_memory.c61
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_misc.c68
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_notification.c190
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_pm.c208
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_profiling_gator.c248
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_profiling_internal.c317
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_specific.h130
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_time.c51
-rw-r--r--drivers/gpu/arm/mali/linux/mali_osk_timers.c65
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_core.c142
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_gp.c128
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_mem.c336
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_pp.c103
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_profiling.c157
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_vsync.c41
-rw-r--r--drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h71
-rw-r--r--drivers/gpu/arm/mali/platform/default/mali_platform.c43
-rw-r--r--drivers/gpu/arm/mali/platform/mali_platform.h99
-rw-r--r--drivers/gpu/arm/mali/readme.txt30
-rw-r--r--drivers/gpu/arm/mali/regs/mali_200_regs.h170
-rw-r--r--drivers/gpu/arm/mali/regs/mali_gp_regs.h219
-rw-r--r--drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.c13
-rw-r--r--drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h48
-rw-r--r--drivers/gpu/arm/mali/timestamp-default/mali_timestamp.c13
-rw-r--r--drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h26
-rw-r--r--drivers/gpu/arm/ump/Kconfig19
-rwxr-xr-xdrivers/gpu/arm/ump/Makefile67
-rw-r--r--drivers/gpu/arm/ump/arch/config.h18
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_api.c362
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_common.c395
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_common.h126
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.c166
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.h91
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_memory_backend.h50
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_ref_drv.c194
-rw-r--r--drivers/gpu/arm/ump/common/ump_kernel_types.h35
-rw-r--r--drivers/gpu/arm/ump/common/ump_osk.h48
-rw-r--r--drivers/gpu/arm/ump/common/ump_uk_types.h141
-rw-r--r--drivers/gpu/arm/ump/common/ump_ukk.h53
-rw-r--r--drivers/gpu/arm/ump/include/ump_kernel_interface.h236
-rw-r--r--drivers/gpu/arm/ump/include/ump_kernel_interface_ref_drv.h31
-rw-r--r--drivers/gpu/arm/ump/include/ump_kernel_platform.h48
-rw-r--r--drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h31
-rw-r--r--drivers/gpu/arm/ump/linux/ump_ioctl.h49
-rw-r--r--drivers/gpu/arm/ump/linux/ump_kernel_linux.c448
-rw-r--r--drivers/gpu/arm/ump/linux/ump_kernel_linux.h18
-rw-r--r--drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c285
-rw-r--r--drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.h23
-rw-r--r--drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c255
-rw-r--r--drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.h23
-rw-r--r--drivers/gpu/arm/ump/linux/ump_memory_backend.c70
-rw-r--r--drivers/gpu/arm/ump/linux/ump_osk_atomics.c27
-rw-r--r--drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c302
-rw-r--r--drivers/gpu/arm/ump/linux/ump_osk_misc.c37
-rw-r--r--drivers/gpu/arm/ump/linux/ump_ukk_ref_wrappers.c76
-rw-r--r--drivers/gpu/arm/ump/linux/ump_ukk_ref_wrappers.h35
-rw-r--r--drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c173
-rw-r--r--drivers/gpu/arm/ump/linux/ump_ukk_wrappers.h41
-rw-r--r--drivers/gpu/arm/ump/readme.txt28
-rw-r--r--drivers/gpu/drm/Kconfig7
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c2
-rw-r--r--drivers/gpu/drm/mali/Makefile20
-rw-r--r--drivers/gpu/drm/mali/mali_drv.c177
-rw-r--r--drivers/gpu/drm/mali/mali_drv.h25
-rw-r--r--drivers/input/touchscreen/Kconfig7
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/unidisplay_ts.c404
-rw-r--r--drivers/media/video/Kconfig45
-rw-r--r--drivers/media/video/Makefile2
-rwxr-xr-xdrivers/media/video/s5k4ecgx.c1358
-rw-r--r--drivers/media/video/s5k4ecgx_regs.h3121
-rwxr-xr-xdrivers/media/video/s5k4ecgx_regs_1_0.h4460
-rwxr-xr-xdrivers/media/video/s5k4ecgx_regs_1_1.h4386
-rw-r--r--drivers/media/video/s5k4ecgx_regs_1_1_slsi-4ec.h4474
-rw-r--r--drivers/media/video/s5k4ecgx_regset.h33
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_common.h1
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_dec.c16
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_opr.c4
-rw-r--r--drivers/media/video/s5p-tv/Kconfig1
-rw-r--r--drivers/media/video/s5p-tv/hdmi_drv.c178
-rw-r--r--drivers/media/video/s5p-tv/mixer.h2
-rw-r--r--drivers/media/video/s5p-tv/mixer_reg.c6
-rw-r--r--drivers/media/video/s5p-tv/mixer_video.c10
-rw-r--r--drivers/media/video/s5p-tv/regs-hdmi.h107
-rw-r--r--drivers/media/video/v4l2-ctrls.c7
-rw-r--r--drivers/media/video/videobuf2-fb.c565
-rw-r--r--drivers/mfd/max8997.c73
-rw-r--r--drivers/mmc/core/sdio_irq.c2
-rw-r--r--drivers/mmc/core/sdio_ops.c40
-rw-r--r--drivers/mmc/core/sdio_ops.h1
-rw-r--r--drivers/mmc/host/sdhci-s3c.c146
-rw-r--r--drivers/mmc/host/sdhci.c4
-rw-r--r--drivers/net/wireless/ath/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig12
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile28
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c11
-rw-r--r--drivers/net/wireless/ath/platform_data.c26
-rw-r--r--drivers/pinctrl/Kconfig9
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c560
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h217
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c888
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h239
-rw-r--r--drivers/pwm/pwm-samsung.c13
-rw-r--r--drivers/regulator/dummy.c29
-rw-r--r--drivers/regulator/max8997.c148
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/alc5625/Kconfig13
-rw-r--r--drivers/staging/alc5625/Makefile3
-rw-r--r--drivers/staging/alc5625/alc5625.c2276
-rw-r--r--drivers/staging/alc5625/alc5625.h865
-rw-r--r--drivers/staging/alc5625/origen_alc5625.c236
-rw-r--r--drivers/staging/bcm/nvm.c2
-rw-r--r--drivers/tty/serial/samsung.c3
-rw-r--r--drivers/usb/gadget/Kconfig7
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c20
-rw-r--r--drivers/usb/gadget/u_ether.c23
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/backlight/Kconfig7
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/lcd_pwrctrl.c226
-rw-r--r--drivers/video/backlight/pwm_bl.c10
-rw-r--r--drivers/video/s3c-fb.c286
-rw-r--r--include/linux/ath6kl.h38
-rw-r--r--include/linux/mfd/max8997-private.h1
-rw-r--r--include/linux/mfd/max8997.h1
-rw-r--r--include/linux/printk.h1
-rw-r--r--include/linux/pwm.h5
-rw-r--r--include/linux/videodev2.h4
-rw-r--r--include/linux/videodev2_samsung.h656
-rw-r--r--include/media/s5k4ecgx.h26
-rw-r--r--include/media/videobuf2-fb.h22
-rw-r--r--include/video/lcd_pwrctrl.h24
-rw-r--r--init/Kconfig2
-rw-r--r--init/main.c3
-rw-r--r--init/version.c3
-rw-r--r--linaro/configs/origen.conf126
-rwxr-xr-xscripts/setlocalversion5
-rw-r--r--sound/soc/samsung/dma.c17
-rw-r--r--sound/soc/samsung/dma.h1
-rw-r--r--sound/soc/samsung/i2s.c230
-rw-r--r--ubuntu/dm-raid4-5/dm-raid4-5.c4
278 files changed, 63589 insertions, 257 deletions
diff --git a/Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt b/Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt
new file mode 100644
index 00000000000..52aa0493914
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt
@@ -0,0 +1,152 @@
+* Samsung GPIO Wakeup Interrupt Controller
+
+This document is split into following sections.
+
+[1] Samsung Exynos4 GPIO Wakeup Interrupt Source Controller
+[2] Samsung Exynos5 GPIO Wakeup Interrupt Source Controller
+
+
+[1] Samsung Exynos4 GPIO Wakeup Interrupt Source Controller
+
+Samsung Exynos4 processor supports 32 external wakeup interrupt sources. First
+16 of these interrupts are directly connected to GIC and the rest 16 of the
+interrupts are grouped together to deliver a single interrupt to GIC.
+
+Required properties:
+
+ - compatible: should be "samsung,exynos4210-wakeup-eint".
+
+ - reg: physical base address of the controller and length of memory
+ mapped region.
+
+ - interrupt-controller: Identifies the node as an interrupt controller.
+
+ - interrupt-cells: Specifies the number of cells required to specify the
+ interrupt source number. The value of should be <2>. The first cell
+ represents the wakeup interrupt source number and the second cell
+ should be zero (currently unused).
+
+ - interrupts: List of interrupts generated by the gpio wakeup interrupt
+ controller which are connected to a parent interrupt controller. The
+ format of the interrupt specifier depends on the interrupt parent
+ controller.
+
+Optional properties:
+
+ - interrupt-parent: phandle of the parent interrupt controller, required
+ if not inheriting the interrupt parent from the parent node.
+
+Example:
+
+ The following example is from the Exynos4210 dtsi file.
+
+ wakeup_eint: interrupt-controller-wakeup-eint {
+ compatible = "samsung,exynos4210-wakeup-eint";
+ reg = <0x11000000 0x1000>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+ <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
+ <0 32 0>;
+ };
+
+
+[2] Samsung Exynos5 GPIO Wakeup Interrupt Source Controller
+
+Samsung Exynos5 processor supports 32 external wakeup interrupt sources. First
+16 of these interrupts are directly connected to GIC and the rest 16 of the
+interrupts are grouped together to deliver a single interrupt to interrupt
+combiner controller.
+
+Since the wakeup interrupts has two interrupt parents, a interrupt nexus
+child node is used that includes a interrupt-map used to translate wakeup
+interrupt specifiers into gic and combiner domain interrupts.
+
+Required properties:
+
+ - compatible: should be "samsung,exynos5210-wakeup-eint".
+
+ - reg: physical base address of the controller and length of memory
+ mapped region.
+
+ - interrupt-controller: Identifies the node as an interrupt controller.
+
+ - interrupt-cells: Specifies the number of cells required to specify the
+ interrupt source number. The value of should be <2>. The first cell
+ represents the wakeup interrupt source number and the second cell
+ should be zero (currently unused).
+
+ - interrupts: List of interrupts generated by the gpio wakeup interrupt
+ controller. Since both gic and combiner controllers are interrupt
+ parents, a interrupt nexus child node is used to translate the interrupt
+ specifiers into respective gic and combiner interrupt domains (see below).
+ The interrupt specifier should be two cells - the first cell should be the
+ interrupt number originating from the wakeup controller and the second
+ cell should be zero (unused).
+
+ - interrupt-parent: The phandle of the interrupt nexus child node.
+
+ - interrupt-nexus child node: This node is used to translate the interrupt
+ specifiers of the wakeup interrupt controller node to the respecitive
+ gic or combiner interrupt domain. The interrupt nexus node should include
+ the following properties.
+
+ - interrupt-cells: Specifies the number of cells required to specify the
+ interrupt source number. The value of should be <2>. The first cell
+ represents the wakeup interrupt source number and the second cell
+ should be zero (currently unused).
+
+ - #address-cells: value of this property should be zero.
+
+ - #size-cells: value of this property should be zero.
+
+ - interrupt-map: The interrpt-map specifies how interrupt specifiers are
+ translated. There should be a interrupt-map entry for each interrupt
+ generated by the wakeup interrupt controller. The format of each entry
+ in the interrupt map should be
+
+ <#intr 0 parent-phandle parent-interrupt-specifier>
+
+ where #intr is one of the entries in the 'interrupts' property of the
+ parent node.
+
+
+Example:
+
+ wakeup_eint: interrupt-controller@11400000 {
+ compatible = "samsung,exynos5210-wakeup-eint";
+ reg = <0x11400000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&eint_nexus>;
+ interrupts = <0x0 0>, <0x1 0>, <0x2 0>, <0x3 0>,
+ <0x4 0>, <0x5 0>, <0x6 0>, <0x7 0>,
+ <0x8 0>, <0x9 0>, <0xa 0>, <0xb 0>,
+ <0xc 0>, <0xd 0>, <0xe 0>, <0xf 0>,
+ <0x10 0>;
+
+ wakeup_map: interrupt-map {
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = <0x0 0 &combiner 23 0>,
+ <0x1 0 &combiner 24 0>,
+ <0x2 0 &combiner 25 0>,
+ <0x3 0 &combiner 25 1>,
+ <0x4 0 &combiner 26 0>,
+ <0x5 0 &combiner 26 1>,
+ <0x6 0 &combiner 27 0>,
+ <0x7 0 &combiner 27 1>,
+ <0x8 0 &combiner 28 0>,
+ <0x9 0 &combiner 28 1>,
+ <0xa 0 &combiner 29 0>,
+ <0xb 0 &combiner 29 1>,
+ <0xc 0 &combiner 30 0>,
+ <0xd 0 &combiner 30 1>,
+ <0xe 0 &combiner 31 0>,
+ <0xf 0 &combiner 31 1>,
+ <0x10 0 &gic 0 32 0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/fb/samsung-fb.txt b/Documentation/devicetree/bindings/fb/samsung-fb.txt
new file mode 100644
index 00000000000..612bd9f8327
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/samsung-fb.txt
@@ -0,0 +1,148 @@
+* Samsung Display Controller Framebuffer Controller
+
+The display controller is used to transfer image data from memory to a
+external display device such as an RGB interface LCD panel. It supports
+various color formats such as rgb and yuv. It also supports multiple window
+overlays.
+
+Required properties:
+
+ - compatible: should be one of the following
+ - samsung,exynos4210-fimd: for fimd compatible with Exynos4210 fimd
+ - samsung,s5pv210-fimd: for fimd compatible with s5pv210 fimd
+
+ - reg: physical base address of the controller and length of memory
+ mapped region.
+
+ - interrupts: Three interrupts should be specified. The format of the
+ interrupt specifier depends on the interrupt controller. The interrupts
+ should be specified in the following order.
+ - VSYNC (Video Frame) interrupt
+ - Video FIFO level interrupt
+ - FIMD System Interrupt
+
+ - gpios: The gpios used to interface with the external LCD panel. For a
+ panel with rgb interface, the gpio interface consists of video data
+ lines, HSYNC, VSYNC, Pixel Clock and Data Enable. The gpio's used for
+ these interface lines can be listed under this property in any order.
+
+ - samsung,fimd-display: The fimd controller is interfaced with the a
+ display device such as a lcd panel. This property should specify the
+ phandle of the display device node. For a display device node that
+ represents a RGB type display interface, it is expected to specify the
+ video interface timing using the following properties.
+
+ - lcd-htiming: Specifies the horizontal timing for the overlay. The
+ horizontal timing includes four parameters in the following order.
+
+ - horizontal back porch (in number of lcd clocks)
+ - horizontal front porch (in number of lcd clocks)
+ - hsync pulse width (in number of lcd clocks)
+ - Display panels X resolution.
+
+ - lcd-vtiming: Specifies the vertical timing for the overlay. The
+ vertical timing includes four parameters in the following order.
+
+ - vertical back porch (in number of lcd lines)
+ - vertical front porch (in number of lcd lines)
+ - vsync pulse width (in number of lcd clocks)
+ - Y resolution.
+
+ - Overlay/Windows: Multiple overlays/windows can be specified as child
+ nodes. Each window should have the following properties (optional
+ window properties are marked as 'optional').
+
+ - samsung,fimd-win-id: Specifies the window number of the fimd controller.
+
+ - samsung,fimd-win-bpp: Specifies the bits per pixel. Two values should
+ be specified in the following order.
+ - default-bpp: bpp supported by the overlay.
+ - max-bpp: maximum required bpp for the overlay.
+
+ - samsung,fimd-win-res: (OPTIONAL) Specifies the window resolution in
+ pixels. The resolution contains the X and Y pixel values with X being
+ specified first. If this property is not specified, the window
+ resolution is set to be equal to the display panel resolution.
+
+ - samsung,fimd-win-virtres: (OPTIONAL) Specifies the resolution of the
+ virtual frame buffer for the window. The resolution contains the X
+ and Y resolution in pixels with value of X being the specified first.
+
+Optional properties:
+
+ - samsung,fimd-vidout-rgb: Video output format is RGB.
+ - samsung,fimd-inv-hsync: invert hsync pulse polarity.
+ - samsung,fimd-inv-vsync: invert vsync pulse polarity.
+ - samsung,fimd-inv-vclk: invert video clock polarity.
+ - samsung,fimd-inv-vden: invert video enable signal polarity.
+ - samsung,fimd-frame-rate: Number of video frames per second.
+
+Example:
+
+ The following is an example for the fimd framebuffer controller is split
+ into two portions. The SoC specific portion can be specified in the SoC
+ specific dts file. The board specific portion can be specified in the
+ board specific dts file.
+
+ - SoC Specific portion
+
+ fimd@11C00000 {
+ compatible = "samsung,exynos4210-fimd";
+ interrupt-parent = <&combiner>;
+ reg = <0x11C00000 0x8000>;
+ interrupts = <11 1>, <11 0>, <11 2>;
+ };
+
+ - Board Specific portion
+
+ fimd@11C00000 {
+ samsung,fimd-display = <&lcd_fimd0>;
+ samsung,fimd-vidout-rgb;
+ samsung,fimd-inv-hsync;
+ samsung,fimd-inv-vsync;
+ samsung,fimd-inv-vclk;
+ samsung,fimd-frame-rate = <60>;
+
+ gpios = <&gpf0 0 2 0 0>,
+ <&gpf0 1 2 0 0>,
+ <&gpf0 2 2 0 0>,
+ <&gpf0 3 2 0 0>,
+ <&gpf0 4 2 0 0>,
+ <&gpf0 5 2 0 0>,
+ <&gpf0 6 2 0 0>,
+ <&gpf0 7 2 0 0>,
+ <&gpf1 0 2 0 0>,
+ <&gpf1 1 2 0 0>,
+ <&gpf1 2 2 0 0>,
+ <&gpf1 3 2 0 0>,
+ <&gpf1 4 2 0 0>,
+ <&gpf1 5 2 0 0>,
+ <&gpf1 6 2 0 0>,
+ <&gpf1 7 2 0 0>,
+ <&gpf2 0 2 0 0>,
+ <&gpf2 1 2 0 0>,
+ <&gpf2 2 2 0 0>,
+ <&gpf2 3 2 0 0>,
+ <&gpf2 4 2 0 0>,
+ <&gpf2 5 2 0 0>,
+ <&gpf2 6 2 0 0>,
+ <&gpf2 7 2 0 0>,
+ <&gpf3 0 2 0 0>,
+ <&gpf3 1 2 0 0>,
+ <&gpf3 2 2 0 0>,
+ <&gpf3 3 2 0 0>;
+
+ window0 {
+ samsung,fimd-win-id = <0>;
+ samsung,fimd-win-bpp = <32 24>;
+ samsung,fimd-win-res = <512 300>;
+ samsung,fimd-win-vres = <1024 600>;
+ };
+
+ window1 {
+ samsung,fimd-win-id = <1>;
+ samsung,fimd-win-bpp = <32 24>;
+ samsung,fimd-win-res = <1024 200>;
+ samsung,fimd-win-vres = <1024 600>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt b/Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt
new file mode 100644
index 00000000000..22604a208c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt
@@ -0,0 +1,36 @@
+* Power controller for simple lcd panels
+
+Some LCD panels provide a simple control interface for the host system. The
+control mechanism would include a nRESET line connected to a gpio of the host
+system and a Vcc supply line which the host can optionally be controlled using
+a voltage regulator. Such simple panels do not support serial command
+interface (such as i2c or spi) or memory-mapped-io interface.
+
+Required properties:
+- compatible: should be 'lcd-powercontrol'
+
+- lcd-reset-gpio: The GPIO number of the host system used to control the
+ nRESET line. The format of the gpio specifier depends on the gpio controller
+ of the host system.
+
+Optional properties:
+- lcd-reset-active-high: When the nRESET line is asserted low, the lcd panel
+ is reset and stays in reset mode as long as the nRESET line is asserted low.
+ This is the default behaviour of most lcd panels. If a lcd panel requires the
+ nRESET line to be asserted high for panel reset, then this property is used.
+ Note: Some platforms might allow inverting the polarity of the gpio output
+ in the 'lcd-reset-gpio' gpio specifier. On such platforms, if the polarity
+ is used to control the output of the gpio, then this property should not be
+ used.
+
+- vcc-lcd-supply: phandle of the regulator that controls the vcc supply to
+ the lcd panel.
+
+Example:
+
+ lcd_pwrctrl {
+ compatible = "lcd-powercontrol";
+ lcd-reset-gpio = <&gpe0 4 1 0 0>;
+ lcd-reset-active-high;
+ lcd-vcc-supply = <&regulator7>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
new file mode 100644
index 00000000000..398540be4a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
@@ -0,0 +1,51 @@
+* Samsung's SDHCI Controller device tree bindings
+
+Samsung's SDHCI controller is used as a connectivity interface with external
+MMC, SD and eMMC storage mediums. This file documents differences between the
+core mmc properties described by mmc.txt and the properties used by the
+Samsung implmentation of the SDHCI controller.
+
+Required SoC Specific Properties:
+- compatible: should be one of the following
+ - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
+ controller.
+ - "samsung,exynos4210-sdhci": For controllers compatible with Exynos4 sdhci
+ controller.
+
+Required Board Specific Properties:
+- gpios: Should specify the gpios used for clock, command and data lines. The
+ gpio specifier format depends on the gpio controller.
+
+Optional Board Specific Properties:
+- One of the following properties for card detect type.
+ - samsung,sdhci-cd-internal: Card detect line from the card slot is
+ connected to the card detect pad of the sdhci controller. A gpio is
+ used for this connection (with possible pin function settings).
+ - samsung,sdhci-cd-gpio: A gpio line (with possible pin function settings)
+ is used a card detect line. This gpio line is not connected to card detect
+ pad of the sdhci controller.
+ - samsung,sdhci-cd-none: There is no card detect line. Polling is used to
+ detect the presence of the card. (DEFAULT, if no card detect property
+ is specified).
+ - samsung,sdhci-cd-permanent: There is no card detect line. The card is
+ permanently connected to the sdhci controller.
+
+Example:
+ sdhci@12530000 {
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12530000 0x100>;
+ interrupts = <<0 75 0>;
+ bus-width = <4>;
+ samsung,sdhci-cd-internal;
+ cd-gpios = <&gpk2 2 2 3 3>;
+ gpios = <&gpk2 0 2 0 3>, /* clock line */
+ <&gpk2 1 2 0 3>, /* command line */
+ <&gpk2 3 2 3 3>, /* data line 0 */
+ <&gpk2 4 2 3 3>, /* data line 1 */
+ <&gpk2 5 2 3 3>, /* data line 2 */
+ <&gpk2 6 2 3 3>; /* data line 3 */
+ };
+
+ Note: This example shows both SoC specific and board specific properties
+ in a single device node. The properties can be actually be seperated
+ into SoC specific node and board specific node.
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
new file mode 100644
index 00000000000..000ca2056d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -0,0 +1,196 @@
+Samsung GPIO and Pin Mux/Config controller
+
+Samsung's ARM based SoC's integrates a GPIO and Pin mux/config hardware
+controller. It controls the input/output settings on the available pads/pins
+and also provides ability to multiplex and configure the output of various
+on-chip controllers onto these pads.
+
+Required Properties:
+- compatible: should be one of the following.
+ - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
+ - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
+
+- reg: Base address of the pin controller hardware module and length of
+ the address space it occupies.
+
+- interrupts: interrupt specifier for the controller. The format and value of
+ the interrupt specifier depends on the interrupt parent for the controller.
+
+- Pin mux/config groups as child nodes: The pin mux (selecting pin function
+ mode) and pin config (pull up/down, driver strength) settings are represented
+ as child nodes of the pin-controller node. There should be atleast one
+ child node and there is no limit on the count of these child nodes.
+
+ The child node should contain a list of pin(s) on which a particular pin
+ function selection or pin configuration (or both) have to applied. This
+ list of pins is specified using the property name "samsung,pins". There
+ should be atleast one pin specfied for this property and there is no upper
+ limit on the count of pins that can be specified. The pins are specified
+ using pin names which are derived from the hardware manual of the SoC. As
+ an example, the pins in GPA0 bank of the pin controller can be represented
+ as "gpa0-0", "gpa0-1", "gpa0-2" and so on. The names should be in lower case.
+ The format of the pin names should be (as per the hardware manual)
+ "[pin bank name]-[pin number within the bank]".
+
+ The pin function selection that should be applied on the pins listed in the
+ child node is specified using the "samsung,pin-function" property. The value
+ of this property that should be applied to each of the pins listed in the
+ "samsung,pins" property should be picked from the hardware manual of the SoC
+ for the specified pin group. This property is optional in the child node if
+ no specific function selection is desired for the pins listed in the child
+ node. The value of this property is used as-is to program the pin-controller
+ function selector register of the pin-bank.
+
+ The child node can also optionally specify one or more of the pin
+ configuration that should be applied on all the pins listed in the
+ "samsung,pins" property of the child node. The following pin configuration
+ properties are supported.
+
+ - samsung,pin-pud: Pull up/down configuration.
+ - samsung,pin-drv: Drive strength configuration.
+ - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
+ - samsung,pin-drv-pdn: Drive strength configuration in power down mode.
+
+ The values specified by these config properties should be dervied from the
+ hardware manual and these values are programmed as-is into the pin
+ pull up/down and driver strength register of the pin-controller.
+
+ Note: A child should include atleast a pin function selection property or
+ pin configuration property (one or more) or both.
+
+ The client nodes that require a particular pin function selection and/or
+ pin configuration should use the bindings listed in the "pinctrl-bindings.txt"
+ file.
+
+External GPIO and Wakeup Interrupts:
+
+The controller supports two types of external interrupts over gpio. The first
+is the external gpio interrupt and second is the external wakeup interrupts.
+The difference between the two is that the external wakeup interrupts can be
+used as system wakeup events.
+
+A. External GPIO Interrupts: For supporting external gpio interrupts, the
+ properties should be specified in the pin-controller device node.
+
+- interrupt-controller: identifies the controller node as interrupt-parent.
+- #interrupt-cells: the value of this property should be 2.
+ - First Cell: represents the external gpio interrupt number local to the
+ external gpio interrupt space of the controller.
+ - Second Cell: flags to identify the type of the interrupt
+ - 1 = rising edge triggered
+ - 2 = falling edge triggered
+ - 3 = rising and falling edge triggered
+ - 4 = high level triggered
+ - 8 = low level triggered
+
+B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
+ child node representing the external wakeup interrupt controller should be
+ included in the pin-controller device node. This child node should include
+ the following properties.
+
+ - compatible: identifies the type of the external wakeup interrupt controller
+ The possible values are:
+ - samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
+ found on Samsung Exynos4210 SoC.
+ - interrupt-parent: phandle of the interrupt parent to which the external
+ wakeup interrupts are forwarded to.
+ - interrupt-controller: identifies the node as interrupt-parent.
+ - #interrupt-cells: the value of this property should be 2
+ - First Cell: represents the external wakeup interrupt number local to
+ the external wakeup interrupt space of the controller.
+ - Second Cell: flags to identify the type of the interrupt
+ - 1 = rising edge triggered
+ - 2 = falling edge triggered
+ - 3 = rising and falling edge triggered
+ - 4 = high level triggered
+ - 8 = low level triggered
+
+Aliases:
+
+All the pin controller nodes should be represented in the aliases node using
+the following format 'pinctrl{n}' where n is a unique number for the alias.
+
+Example 1: A pin-controller node with pin groups.
+
+ pinctrl_0: pinctrl@11400000 {
+ compatible = "samsung,pinctrl-exynos4210";
+ reg = <0x11400000 0x1000>;
+ interrupts = <0 47 0>;
+
+ uart0_data: uart0-data {
+ samsung,pins = "gpa0-0", "gpa0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart0_fctl: uart0-fctl {
+ samsung,pins = "gpa0-2", "gpa0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart1_data: uart1-data {
+ samsung,pins = "gpa0-4", "gpa0-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart1_fctl: uart1-fctl {
+ samsung,pins = "gpa0-6", "gpa0-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c2_bus: i2c2-bus {
+ samsung,pins = "gpa0-6", "gpa0-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+ };
+
+Example 2: A pin-controller node with external wakeup interrupt controller node.
+
+ pinctrl_1: pinctrl@11000000 {
+ compatible = "samsung,pinctrl-exynos4210";
+ reg = <0x11000000 0x1000>;
+ interrupts = <0 46 0>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ wakup_eint: wakeup-interrupt-controller {
+ compatible = "samsung,exynos4210-wakeup-eint";
+ interrupt-parent = <&gic>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+ <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
+ <0 32 0>;
+ };
+ };
+
+Example 3: A uart client node that supports 'default' and 'flow-control' states.
+
+ uart@13800000 {
+ compatible = "samsung,exynos4210-uart";
+ reg = <0x13800000 0x100>;
+ interrupts = <0 52 0>;
+ pinctrl-names = "default", "flow-control;
+ pinctrl-0 = <&uart0_data>;
+ pinctrl-1 = <&uart0_data &uart0_fctl>;
+ };
+
+Example 4: Set up the default pin state for uart controller.
+
+ static int s3c24xx_serial_probe(struct platform_device *pdev) {
+ struct pinctrl *pinctrl;
+ ...
+ ...
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ }
diff --git a/Documentation/devicetree/bindings/regulator/max8997-pmic.txt b/Documentation/devicetree/bindings/regulator/max8997-pmic.txt
new file mode 100644
index 00000000000..5da0c70289e
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8997-pmic.txt
@@ -0,0 +1,147 @@
+* Maxim MAX8997 Voltage and Current Regulator
+
+The Maxim MAX8997 is a multi-function device which includes volatage and
+current regulators, rtc, charger controller and other sub-blocks. It is
+interfaced to the host controller using a i2c interface. Each sub-block is
+addressed by the host system using different i2c slave address. This document
+describes the bindings for 'pmic' sub-block of max8997.
+
+Required properties:
+- compatible: Should be "maxim,max8997-pmic".
+- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
+
+- max8997,pmic-buck1-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+ units for buck1 when changing voltage using gpio dvs. Refer to [1] below
+ for additional information.
+
+- max8997,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+ units for buck2 when changing voltage using gpio dvs. Refer to [1] below
+ for additional information.
+
+- max8997,pmic-buck5-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+ units for buck5 when changing voltage using gpio dvs. Refer to [1] below
+ for additional information.
+
+[1] If none of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+ property is specified, the 'max8997,pmic-buck[1/2/5]-dvs-voltage'
+ property should specify atleast one voltage level (which would be a
+ safe operating voltage).
+
+ If either of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+ property is specified, then all the eigth voltage values for the
+ 'max8997,pmic-buck[1/2/5]-dvs-voltage' should be specified.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+ the interrupts from max8997 are delivered to.
+- interrupts: Interrupt specifiers for two interrupt sources.
+ - First interrupt specifier is for 'irq1' interrupt.
+ - Second interrupt specifier is for 'alert' interrupt.
+- max8997,pmic-buck1-uses-gpio-dvs: 'buck1' can be controlled by gpio dvs.
+- max8997,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
+- max8997,pmic-buck5-uses-gpio-dvs: 'buck5' can be controlled by gpio dvs.
+
+Additional properties required if either of the optional properties are used:
+- max8997,pmic-ignore-gpiodvs-side-effect: When GPIO-DVS mode is used for
+ multiple bucks, changing the voltage value of one of the bucks may affect
+ that of another buck, which is the side effect of the change (set_voltage).
+ Use this property to ignore such side effects and change the voltage.
+
+- max8997,pmic-buck125-default-dvs-idx: Default voltage setting selected from
+ the possible 8 options selectable by the dvs gpios. The value of this
+ property should be between 0 and 7. If not specified or if out of range, the
+ default value of this property is set to 0.
+
+- max8997,pmic-buck125-dvs-gpios: GPIO specifiers for three host gpio's used
+ for dvs. The format of the gpio specifier depends in the gpio controller.
+
+
+Regulators: The regulators of max8997 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+ regulator_name {
+ standard regulator bindings here
+ };
+
+The following are the names of the regulators that the max8997 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of max8997.
+
+ - LDOn
+ - valid values for n are 1 to 18 and 21
+ - Example: LDO0, LD01, LDO2, LDO21
+ - BUCKn
+ - valid values for n are 1 to 7.
+ - Example: BUCK1, BUCK2, BUCK3, BUCK7
+
+ - ENVICHG: Battery Charging Current Monitor Output. This is a fixed
+ voltage type regulator
+
+ - ESAFEOUT1: (ldo19)
+ - ESAFEOUT2: (ld020)
+
+ - CHARGER_CV: main battery charger voltage control
+ - CHARGER: main battery charger current control
+ - CHARGER_TOPOFF: end of charge current threshold level
+
+The bindings inside the regulator nodes use the standard regulator bindings
+which are documented elsewhere.
+
+Example:
+
+ max8997_pmic@66 {
+ compatible = "maxim,max8997-pmic";
+ interrupt-parent = <&wakeup_eint>;
+ reg = <0x66>;
+ interrupts = <4 0>, <3 0>;
+
+ max8997,pmic-buck1-uses-gpio-dvs;
+ max8997,pmic-buck2-uses-gpio-dvs;
+ max8997,pmic-buck5-uses-gpio-dvs;
+
+ max8997,pmic-ignore-gpiodvs-side-effect;
+ max8997,pmic-buck125-default-dvs-idx = <0>;
+
+ max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+ <&gpx0 1 1 0 0>, /* SET2 */
+ <&gpx0 2 1 0 0>; /* SET3 */
+
+ max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+ <1250000>, <1200000>,
+ <1150000>, <1100000>,
+ <1000000>, <950000>;
+
+ max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
+ <1100000>, <1100000>,
+ <1000000>, <1000000>,
+ <1000000>, <1000000>;
+
+ max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+ <1200000>, <1200000>,
+ <1200000>, <1200000>,
+ <1200000>, <1200000>;
+
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ABB_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDD_ALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "VDD_ARM_1.2V";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
new file mode 100644
index 00000000000..74739a4e3dc
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
@@ -0,0 +1,62 @@
+* Samsung I2S controller
+
+Required SoC Specific properties:
+
+- compatible : "samsung,samsung-i2s"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- tx-dma-channel-secondary: The dma channel specifier for secondary tx
+ operations. The format of the dma specifier depends on the dma
+ controller.
+- tx-dma-channel: The dma channel specifier for tx operations. The format of
+ the dma specifier depends on the dma controller.
+- rx-dma-channel: The dma channel specifier for rx operations. The format of
+ the dma specifier depends on the dma controller.
+- supports-6ch: If the Primary DAI has 5.1 Channel support, this flag is
+ enabled.
+- supports-rstclr: This flag should be set if I2S software reset bit control is
+ required. When this flag is set I2S software reset bit will be enabled or
+ disabled based on need.
+- supports-secdai: If the I2S block has a secondary sound source support, then
+ this flag is enabled.
+
+Required Board Specific Properties:
+
+- gpios: The gpio specifier for data out,data in, LRCLK, CDCLK and SCLK
+ interface lines. The format of the gpio specifier depends on the gpio
+ controller.
+- idma-addr: Internal DMA register base address of the audio sub system(used in
+ secondary sound source).
+
+Aliases:
+
+- All the I2S controller nodes should be represented in the aliases node using
+ the following format 'i2s{n}' where n is a unique number for the alias.
+
+Example:
+
+- SoC Specific Portion:
+
+i2s@03830000 {
+ compatible = "samsung,samsung-i2s";
+ reg = <0x03830000 0x100>;
+ tx-dma-channel-secondary = <&pdma0 8>;
+ tx-dma-channel = <&pdma0 10>;
+ rx-dma-channel = <&pdma0 9>;
+ supports-6ch;
+ supports-rstclr;
+ supports-secdai;
+};
+
+- Board Specific Portion:
+
+i2s_0: i2s@03830000 {
+ gpios = <&gpz 0 2 0 0>,
+ <&gpz 1 2 0 0>,
+ <&gpz 2 2 0 0>,
+ <&gpz 3 2 0 0>,
+ <&gpz 4 2 0 0>,
+ <&gpz 5 2 0 0>,
+ <&gpz 6 2 0 0>;
+ idma-addr = <0x03000000>;
+};
diff --git a/Documentation/devicetree/bindings/usb/s3c-hsotg.txt b/Documentation/devicetree/bindings/usb/s3c-hsotg.txt
new file mode 100644
index 00000000000..30b26c03387
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/s3c-hsotg.txt
@@ -0,0 +1,16 @@
+Samsung HSOTG controller s3c-hsotg
+
+Required properties:
+ - compatible : should be "samsung,exynos-hsotg".
+ - reg : should contain at least address and length of the standard HSOTG
+ register set for the device.
+ - interrupts : one HSOTG interrupt should be described here.
+
+Example (Samsung Origen):
+
+ usb@12480000 {
+ compatible = "samsung,exynos-hsotg";
+ reg = <0x12480000 0x20000>;
+ interrupts = <0 71 0>;
+ };
+
diff --git a/Makefile b/Makefile
index 575a809ae4b..e88c8de6eba 100644
--- a/Makefile
+++ b/Makefile
@@ -383,6 +383,7 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
+KERNELVERSIONLOCAL= $(shell cat .scmversion 2> /dev/null)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
@@ -787,7 +788,8 @@ $(vmlinux-dirs): prepare scripts
include/config/kernel.release: include/config/auto.conf FORCE
$(Q)rm -f $@
$(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@
-
+ $(Q)rm -f .scmversion
+ $(Q)($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --save-scmversion $(srctree))
# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
@@ -838,7 +840,8 @@ define filechk_utsrelease.h
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
exit 1; \
fi; \
- (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
+ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
+ echo \#define KERNEL_VERSION_LOCAL \"$(KERNELVERSIONLOCAL)\";)
endef
define filechk_version.h
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 0c49caa0997..17c5e26f4b6 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -30,10 +30,12 @@
};
sdhci@12530000 {
- samsung,sdhci-bus-width = <4>;
- linux,mmc_cap_4_bit_data;
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12530000 0x100>;
+ interrupts = <0 75 0>;
+ bus-width = <4>;
samsung,sdhci-cd-internal;
- gpio-cd = <&gpk2 2 2 3 3>;
+ cd-gpios = <&gpk2 2 2 3 3>;
gpios = <&gpk2 0 2 0 3>,
<&gpk2 1 2 0 3>,
<&gpk2 3 2 3 3>,
@@ -43,10 +45,12 @@
};
sdhci@12510000 {
- samsung,sdhci-bus-width = <4>;
- linux,mmc_cap_4_bit_data;
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12510000 0x100>;
+ interrupts = <0 73 0>;
+ bus-width = <4>;
samsung,sdhci-cd-internal;
- gpio-cd = <&gpk0 2 2 3 3>;
+ cd-gpios = <&gpk0 2 2 3 3>;
gpios = <&gpk0 0 2 0 3>,
<&gpk0 1 2 0 3>,
<&gpk0 3 2 3 3>,
@@ -55,6 +59,66 @@
<&gpk0 6 2 3 3>;
};
+ lcd_fimd0: lcd_panel0 {
+ compatible = "lcd-powercontrol";
+ vcc-lcd-supply = <&buck7_reg>;
+ lcd-reset-gpio = <&gpe3 4 1 0 0>;
+ lcd-htiming = <64 16 48 1024>;
+ lcd-vtiming = <64 16 3 600>;
+ };
+
+ fimd@11C00000 {
+ samsung,fimd-display = <&lcd_fimd0>;
+ samsung,fimd-vidout-rgb;
+ samsung,fimd-inv-hsync;
+ samsung,fimd-inv-vsync;
+ samsung,fimd-inv-vclk;
+ samsung,fimd-frame-rate = <60>;
+
+ gpios = <&gpf0 0 2 0 0>,
+ <&gpf0 1 2 0 0>,
+ <&gpf0 2 2 0 0>,
+ <&gpf0 3 2 0 0>,
+ <&gpf0 4 2 0 0>,
+ <&gpf0 5 2 0 0>,
+ <&gpf0 6 2 0 0>,
+ <&gpf0 7 2 0 0>,
+ <&gpf1 0 2 0 0>,
+ <&gpf1 1 2 0 0>,
+ <&gpf1 2 2 0 0>,
+ <&gpf1 3 2 0 0>,
+ <&gpf1 4 2 0 0>,
+ <&gpf1 5 2 0 0>,
+ <&gpf1 6 2 0 0>,
+ <&gpf1 7 2 0 0>,
+ <&gpf2 0 2 0 0>,
+ <&gpf2 1 2 0 0>,
+ <&gpf2 2 2 0 0>,
+ <&gpf2 3 2 0 0>,
+ <&gpf2 4 2 0 0>,
+ <&gpf2 5 2 0 0>,
+ <&gpf2 6 2 0 0>,
+ <&gpf2 7 2 0 0>,
+ <&gpf3 0 2 0 0>,
+ <&gpf3 1 2 0 0>,
+ <&gpf3 2 2 0 0>,
+ <&gpf3 3 2 0 0>;
+
+ window0 {
+ samsung,fimd-win-id = <0>;
+ samsung,fimd-win-bpp = <32 24>;
+ samsung,fimd-win-res = <1024 600>;
+ samsung,fimd-win-vres = <1024 600>;
+ };
+
+ window1 {
+ samsung,fimd-win-id = <1>;
+ samsung,fimd-win-bpp = <32 24>;
+ samsung,fimd-win-res = <1024 600>;
+ samsung,fimd-win-vres = <1024 600>;
+ };
+ };
+
gpio_keys {
compatible = "gpio-keys";
#address-cells = <1>;
@@ -64,30 +128,35 @@
label = "Up";
gpios = <&gpx2 0 0 0 2>;
linux,code = <103>;
+ gpio-key,wakeup;
};
down {
label = "Down";
gpios = <&gpx2 1 0 0 2>;
linux,code = <108>;
+ gpio-key,wakeup;
};
back {
label = "Back";
gpios = <&gpx1 7 0 0 2>;
linux,code = <158>;
+ gpio-key,wakeup;
};
home {
label = "Home";
gpios = <&gpx1 6 0 0 2>;
linux,code = <102>;
+ gpio-key,wakeup;
};
menu {
label = "Menu";
gpios = <&gpx1 5 0 0 2>;
linux,code = <139>;
+ gpio-key,wakeup;
};
};
@@ -104,11 +173,126 @@
};
i2c@13860000 {
- status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ gpios = <&gpd1 0 2 3 0>,
+ <&gpd1 1 2 3 0>;
+
+ max8997_pmic@66 {
+ compatible = "maxim,max8997-pmic";
+ interrupt-parent = <&wakeup_eint>;
+ reg = <0x66>;
+ interrupts = <4 0>, <3 0>;
+
+ max8997,pmic-buck1-uses-gpio-dvs;
+ max8997,pmic-buck2-uses-gpio-dvs;
+ max8997,pmic-buck5-uses-gpio-dvs;
+ max8997,pmic-ignore-gpiodvs-side-effect;
+ max8997,pmic-buck125-default-dvs-idx = <0>;
+ max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+ <&gpx0 1 1 0 0>, /* SET2 */
+ <&gpx0 2 1 0 0>; /* SET3 */
+ max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+ <1250000>, <1200000>,
+ <1150000>, <1100000>,
+ <1000000>, <950000>;
+ max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
+ <1100000>, <1100000>,
+ <1000000>, <1000000>,
+ <1000000>, <1000000>;
+ max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+ <1200000>, <1200000>,
+ <1200000>, <1200000>,
+ <1200000>, <1200000>;
+
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ABB_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDD_ALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VMIPI_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VDD_RTC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VMIPI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VDD_AUD_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "VDD_AUD_3V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ buck7_reg: BUCK7 {
+ regulator-name = "VDD_LCD_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+ };
+ };
+
+ unidisplay_ts@41 {
+ compatible = "pixcir,unidisplay-ts";
+ interrupt-parent = <&wakeup_eint>;
+ reg = <0x41>;
+ interrupts = <25 0>;
+ };
};
i2c@13870000 {
- status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ gpios = <&gpd1 2 2 3 0>,
+ <&gpd1 3 2 3 0>;
+
+ codec: alc5625@1e {
+ compatible = "realtek,alc5625";
+ reg = <0x1e>;
+ };
+
};
i2c@13880000 {
@@ -146,4 +330,65 @@
spi_2: spi@13940000 {
status = "disabled";
};
+
+ pd_cam: pd-cam {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C00 0x10>;
+ };
+
+ pd_tv: pd-tv {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C20 0x10>;
+ };
+
+ pd_mfc: pd-mfc {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C40 0x10>;
+ };
+
+ pd_g3d: pd-g3d {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C60 0x10>;
+ };
+
+ pd_lcd0: pd-lcd0 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C80 0x10>;
+ };
+
+ pd_lcd1: pd-lcd1 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023CA0 0x10>;
+ };
+
+ pd_gps: pd-gps {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023CE0 0x10>;
+ samsung,exynos4210-pd_off;
+ };
+
+ usb@12480000 {
+ vusb_a-supply = <&ldo3_reg>;
+ vusb_d-supply = <&ldo3_reg>;
+ };
+
+ i2s_0: i2s@03830000 {
+ gpios = <&gpz 0 2 0 0>,
+ <&gpz 1 2 0 0>,
+ <&gpz 2 2 0 0>,
+ <&gpz 3 2 0 0>,
+ <&gpz 4 2 0 0>,
+ <&gpz 5 2 0 0>,
+ <&gpz 6 2 0 0>;
+ idma-addr = <0x03000000>;
+ };
+
+ asoc_dma {
+ compatible = "samsung,audio-dma";
+ };
+
+ origen_audio {
+ compatible = "samsung,origen_audio";
+ };
+
};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 02891fe876e..f1d91935c61 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -29,6 +29,7 @@
spi0 = &spi_0;
spi1 = &spi_1;
spi2 = &spi_2;
+ i2s0 = &i2s_0;
};
gic:interrupt-controller@10490000 {
@@ -50,6 +51,30 @@
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
};
+ wakeup_eint: interrupt-controller-wakeup-eint {
+ compatible = "samsung,exynos4210-wakeup-eint";
+ reg = <0x11000000 0x1000>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+ <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
+ <0 32 0>;
+ };
+
+ power-domain-lcd0 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023C00 0x10>;
+ };
+
+ fimd@11C00000 {
+ compatible = "samsung,exynos4210-fimd";
+ interrupt-parent = <&combiner>;
+ reg = <0x11C00000 0x8000>;
+ interrupts = <11 1>, <11 0>, <11 2>;
+ };
+
watchdog@10060000 {
compatible = "samsung,s3c2410-wdt";
reg = <0x10060000 0x100>;
@@ -442,4 +467,33 @@
#gpio-cells = <4>;
};
};
+
+ usb@12580000 {
+ compatible = "samsung,exynos-ehci", "usb-ehci";
+ reg = <0x12580000 0x100>;
+ interrupts = <0 70 0>;
+ };
+
+ usb@12590000 {
+ compatible = "samsung,exynos-ohci", "usb-ohci";
+ reg = <0x12590000 0x100>;
+ interrupts = <0 70 0>;
+ };
+
+ usb@12480000 {
+ compatible = "samsung,exynos-hsotg";
+ reg = <0x12480000 0x20000>;
+ interrupts = <0 71 0>;
+ };
+
+ i2s_0: i2s@03830000 {
+ compatible = "samsung,samsung-i2s";
+ reg = <0x03830000 0x100>;
+ tx-dma-channel-secondary = <&pdma0 10>;
+ tx-dma-channel = <&pdma0 12>;
+ rx-dma-channel = <&pdma0 11>;
+ supports-6ch;
+ supports-rstclr;
+ supports-secdai;
+ };
};
diff --git a/arch/arm/configs/android_origen_defconfig b/arch/arm/configs/android_origen_defconfig
new file mode 100644
index 00000000000..d04cf033d26
--- /dev/null
+++ b/arch/arm/configs/android_origen_defconfig
@@ -0,0 +1,210 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_GCOV_KERNEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_ARMLEX4210=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_ACCT=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=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_BT_HCIUART_BCSP=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_SENSORS_EXYNOS4_TMU=y
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+# CONFIG_VIDEO_IR_I2C is not set
+CONFIG_VIDEO_S5K4ECGX=y
+CONFIG_VIDEO_S5K4ECGX_V_1_1=y
+CONFIG_VIDEO_S5K4ECGX_SLSI_4EC=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_DRM=y
+CONFIG_ION=y
+CONFIG_MALI400MP=y
+CONFIG_USING_PMM=y
+CONFIG_UMP=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_HID_KYE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_PERSISTENT_TRACER=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_SWITCH=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_RAM=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
index bffe68e190a..acddcf3d251 100644
--- a/arch/arm/configs/exynos4_defconfig
+++ b/arch/arm/configs/exynos4_defconfig
@@ -5,43 +5,155 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_EXYNOS=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
CONFIG_MACH_SMDKC210=y
CONFIG_MACH_ARMLEX4210=y
CONFIG_MACH_UNIVERSAL_C210=y
CONFIG_MACH_NURI=y
CONFIG_MACH_ORIGEN=y
CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
CONFIG_NR_CPUS=2
CONFIG_PREEMPT=y
CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_POWER_SUPPLY=y
# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_VIDEO_S5P_FIMC=y
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+CONFIG_VIDEO_SAMSUNG_S5P_SDO=y
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_DBGP_PRINTK=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -54,7 +166,9 @@ CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_RT_MUTEXES=y
@@ -63,6 +177,4 @@ CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_INFO=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/ubuntu_origen_defconfig b/arch/arm/configs/ubuntu_origen_defconfig
new file mode 100644
index 00000000000..09ec48091b0
--- /dev/null
+++ b/arch/arm/configs/ubuntu_origen_defconfig
@@ -0,0 +1,242 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_ARMLEX4210=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_NR_CPUS=2
+CONFIG_THUMB2_KERNEL=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_NETLABEL=y
+CONFIG_NETFILTER=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_NAND=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_SENSORS_EXYNOS4_TMU=y
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_VIDEO_S5P_FIMC=y
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+CONFIG_VIDEO_SAMSUNG_S5P_SDO=y
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_DBGP_PRINTK=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_BTRFS_FS=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_DEBUG_USER=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_LSM_MMAP_MIN_ADDR=0
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_DEFAULT_SECURITY_APPARMOR=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b5b4c8c9db1..33c20f635e4 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -327,6 +327,8 @@ config MACH_ORIGEN
select S3C_DEV_WDT
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC2
+ select S3C_DEV_HSMMC3
+ select S3C_DEV_I2C1
select S3C_DEV_USB_HSOTG
select S5P_DEV_FIMC0
select S5P_DEV_FIMC1
@@ -334,6 +336,7 @@ config MACH_ORIGEN
select S5P_DEV_FIMC3
select S5P_DEV_FIMD0
select S5P_DEV_G2D
+ select S5P_DEV_G3D
select S5P_DEV_I2C_HDMIPHY
select S5P_DEV_JPEG
select S5P_DEV_MFC
@@ -346,6 +349,7 @@ config MACH_ORIGEN
select EXYNOS_DEV_DMA
select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_SETUP_FIMD0
+ select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_USB_PHY
help
@@ -405,6 +409,8 @@ config MACH_EXYNOS4_DT
select USE_OF
select ARM_AMBA
select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
+ select SAMSUNG_DEV_BACKLIGHT
+ select SAMSUNG_DEV_PWM
help
Machine support for Samsung Exynos4 machine with device tree enabled.
Select this if a fdt blob is available for the Exynos4 SoC based board.
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9b58024f7d4..5088695f4a7 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += asv.o asv-4210.o
obj-$(CONFIG_ARCH_EXYNOS) += pmu.o
diff --git a/arch/arm/mach-exynos/asv-4210.c b/arch/arm/mach-exynos/asv-4210.c
new file mode 100644
index 00000000000..8f08cb2898f
--- /dev/null
+++ b/arch/arm/mach-exynos/asv-4210.c
@@ -0,0 +1,339 @@
+/* linux/arch/arm/mach-exynos/asv-4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4210 - ASV(Adaptive Support Voltage) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+#include <mach/regs-iem.h>
+#include <mach/regs-clock.h>
+#include <mach/asv.h>
+
+/*
+ * exynos_result_of_asv is result of ASV group.
+ * Using by this value, other driver can adjust voltage.
+ */
+unsigned int exynos_result_of_asv;
+
+enum target_asv {
+ EXYNOS4210_1200,
+ EXYNOS4210_1400,
+ EXYNOS4210_SINGLE_1200,
+};
+
+struct asv_judge_table exynos4210_1200_limit[] = {
+ /* HPM , IDS */
+ {8 , 4},
+ {11 , 8},
+ {14 , 12},
+ {18 , 17},
+ {21 , 27},
+ {23 , 45},
+ {25 , 55},
+};
+
+static struct asv_judge_table exynos4210_1400_limit[] = {
+ /* HPM , IDS */
+ {13 , 8},
+ {17 , 12},
+ {22 , 32},
+ {26 , 52},
+};
+
+static struct asv_judge_table exynos4210_single_1200_limit[] = {
+ /* HPM , IDS */
+ {8 , 4},
+ {14 , 12},
+ {21 , 27},
+ {25 , 55},
+};
+
+static int exynos4210_asv_pre_clock_init(void)
+{
+ struct clk *clk_hpm;
+ struct clk *clk_copy;
+ struct clk *clk_parent;
+
+ /* PWI clock setting */
+ clk_copy = clk_get(NULL, "sclk_pwi");
+ if (IS_ERR(clk_copy))
+ goto clock_fail;
+ else {
+ clk_parent = clk_get(NULL, "xusbxti");
+
+ if (IS_ERR(clk_parent)) {
+ clk_put(clk_copy);
+
+ goto clock_fail;
+ }
+ if (clk_set_parent(clk_copy, clk_parent))
+ goto clock_fail;
+
+ clk_put(clk_parent);
+ }
+ clk_set_rate(clk_copy, (48 * MHZ));
+
+ clk_put(clk_copy);
+
+ /* HPM clock setting */
+ clk_copy = clk_get(NULL, "dout_copy");
+ if (IS_ERR(clk_copy))
+ goto clock_fail;
+ else {
+ clk_parent = clk_get(NULL, "mout_mpll");
+ if (IS_ERR(clk_parent)) {
+ clk_put(clk_copy);
+
+ goto clock_fail;
+ }
+ if (clk_set_parent(clk_copy, clk_parent))
+ goto clock_fail;
+
+ clk_put(clk_parent);
+ }
+
+ clk_set_rate(clk_copy, (400 * MHZ));
+
+ clk_put(clk_copy);
+
+ clk_hpm = clk_get(NULL, "sclk_hpm");
+ if (IS_ERR(clk_hpm))
+ goto clock_fail;
+
+ clk_set_rate(clk_hpm, (200 * MHZ));
+
+ clk_put(clk_hpm);
+
+ return 0;
+
+clock_fail:
+ pr_err("EXYNOS4210: ASV: Clock init fail\n");
+
+ return -EBUSY;
+}
+
+static int exynos4210_asv_pre_clock_setup(void)
+{
+ /* APLL_CON0 level register */
+ __raw_writel(0x80FA0601, EXYNOS4_APLL_CON0L8);
+ __raw_writel(0x80C80601, EXYNOS4_APLL_CON0L7);
+ __raw_writel(0x80C80602, EXYNOS4_APLL_CON0L6);
+ __raw_writel(0x80C80604, EXYNOS4_APLL_CON0L5);
+ __raw_writel(0x80C80601, EXYNOS4_APLL_CON0L4);
+ __raw_writel(0x80C80601, EXYNOS4_APLL_CON0L3);
+ __raw_writel(0x80C80601, EXYNOS4_APLL_CON0L2);
+ __raw_writel(0x80C80601, EXYNOS4_APLL_CON0L1);
+
+ /* IEM Divider register */
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L8);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L7);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L6);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L5);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L4);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L3);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L2);
+ __raw_writel(0x00500000, EXYNOS4_CLKDIV_IEM_L1);
+
+ return 0;
+}
+
+static int exynos4210_find_group(struct samsung_asv *asv_info,
+ enum target_asv exynos4_target)
+{
+ unsigned int ret = 0;
+ unsigned int i;
+
+ if (exynos4_target == EXYNOS4210_1200) {
+ ret = ARRAY_SIZE(exynos4210_1200_limit);
+
+ for (i = 0; i < ARRAY_SIZE(exynos4210_1200_limit); i++) {
+ if (asv_info->hpm_result <= exynos4210_1200_limit[i].hpm_limit ||
+ asv_info->ids_result <= exynos4210_1200_limit[i].ids_limit) {
+ ret = i;
+ break;
+ }
+ }
+ } else if (exynos4_target == EXYNOS4210_1400) {
+ ret = ARRAY_SIZE(exynos4210_1400_limit);
+
+ for (i = 0; i < ARRAY_SIZE(exynos4210_1400_limit); i++) {
+ if (asv_info->hpm_result <= exynos4210_1400_limit[i].hpm_limit ||
+ asv_info->ids_result <= exynos4210_1400_limit[i].ids_limit) {
+ ret = i;
+ break;
+ }
+ }
+ } else if (exynos4_target == EXYNOS4210_SINGLE_1200) {
+ ret = ARRAY_SIZE(exynos4210_single_1200_limit);
+
+ for (i = 0; i < ARRAY_SIZE(exynos4210_single_1200_limit); i++) {
+ if (asv_info->hpm_result <= exynos4210_single_1200_limit[i].hpm_limit ||
+ asv_info->ids_result <= exynos4210_single_1200_limit[i].ids_limit) {
+ ret = i;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+#define PACK_ID 8
+#define PACK_MASK 0x3
+
+#define SUPPORT_1400MHZ (1 << 31)
+#define SUPPORT_1200MHZ (1 << 30)
+#define SUPPORT_1000MHZ (1 << 29)
+
+static int exynos4210_get_hpm(struct samsung_asv *asv_info)
+{
+ unsigned int i;
+ unsigned int tmp;
+ unsigned int hpm_delay = 0;
+ void __iomem *iem_base;
+
+ iem_base = ioremap(EXYNOS4_PA_IEM, SZ_128K);
+
+ if (!iem_base) {
+ pr_err("EXYNOS4210: ASV: ioremap fail\n");
+ return -EPERM;
+ }
+
+ /* Clock setting to get asv value */
+ if (!asv_info->pre_clock_init)
+ goto err;
+ else {
+ if (asv_info->pre_clock_init())
+ goto err;
+ else {
+ /* HPM enable */
+ tmp = __raw_readl(iem_base + EXYNOS4_APC_CONTROL);
+ tmp |= APC_HPM_EN;
+ __raw_writel(tmp, (iem_base + EXYNOS4_APC_CONTROL));
+
+ asv_info->pre_clock_setup();
+
+ /* IEM enable */
+ tmp = __raw_readl(iem_base + EXYNOS4_IECDPCCR);
+ tmp |= IEC_EN;
+ __raw_writel(tmp, (iem_base + EXYNOS4_IECDPCCR));
+ }
+ }
+
+ /* Get HPM Delay value */
+ for (i = 0; i < EXYNOS4_LOOP_CNT; i++) {
+ tmp = __raw_readb(iem_base + EXYNOS4_APC_DBG_DLYCODE);
+ hpm_delay += tmp;
+ }
+
+ hpm_delay /= EXYNOS4_LOOP_CNT;
+
+ /* Store result of hpm value */
+ asv_info->hpm_result = hpm_delay;
+
+ return 0;
+
+err:
+ pr_err("EXYNOS4210: ASV: Failt to get hpm function\n");
+
+ iounmap(iem_base);
+
+ return -EPERM;
+}
+
+static int exynos4210_get_ids(struct samsung_asv *asv_info)
+{
+ unsigned int pkg_id_val;
+
+ if (!asv_info->ids_offset || !asv_info->ids_mask) {
+ pr_err("EXYNOS4210: ASV: No ids_offset or No ids_mask\n");
+
+ return -EPERM;
+ }
+
+ pkg_id_val = __raw_readl(S5P_VA_CHIPID + 0x4);
+ asv_info->pkg_id = pkg_id_val;
+ asv_info->ids_result = ((pkg_id_val >> asv_info->ids_offset) &
+ asv_info->ids_mask);
+
+ return 0;
+}
+
+static int exynos4210_asv_store_result(struct samsung_asv *asv_info)
+{
+ unsigned int result_grp;
+ char *support_freq;
+ unsigned int exynos_idcode = 0x0;
+
+ exynos_result_of_asv = 0;
+
+ exynos_idcode = __raw_readl(S5P_VA_CHIPID);
+
+ /* Single chip is only support 1.2GHz */
+ if (!((exynos_idcode >> PACK_ID) & PACK_MASK)) {
+ result_grp = exynos4210_find_group(asv_info, EXYNOS4210_SINGLE_1200);
+ result_grp |= SUPPORT_1200MHZ;
+ support_freq = "1.2GHz";
+
+ goto set_reg;
+ }
+
+ /* Check support freq */
+ switch (asv_info->pkg_id & 0x7) {
+ /* Support 1.2GHz */
+ case 1:
+ case 7:
+ result_grp = exynos4210_find_group(asv_info, EXYNOS4210_1200);
+ result_grp |= SUPPORT_1200MHZ;
+ support_freq = "1.2GHz";
+ break;
+ /* Support 1.4GHz */
+ case 5:
+ result_grp = exynos4210_find_group(asv_info, EXYNOS4210_1400);
+ result_grp |= SUPPORT_1200MHZ;
+ support_freq = "1.4GHz";
+ break;
+ /* Defalut support 1.0GHz */
+ default:
+ result_grp = exynos4210_find_group(asv_info, EXYNOS4210_1200);
+ result_grp |= SUPPORT_1000MHZ;
+ support_freq = "1.0GHz";
+ break;
+ }
+
+set_reg:
+ exynos_result_of_asv = result_grp;
+
+ pr_info("EXYNOS4: ASV: Support %s and Group is 0x%x\n",
+ support_freq, result_grp);
+
+ return 0;
+}
+
+void exynos4210_asv_init(struct samsung_asv *asv_info)
+{
+ pr_info("EXYNOS4210: Adaptive Support Voltage init\n");
+
+ asv_info->ids_offset = 24;
+ asv_info->ids_mask = 0xFF;
+
+ asv_info->get_ids = exynos4210_get_ids;
+ asv_info->get_hpm = exynos4210_get_hpm;
+ asv_info->pre_clock_init = exynos4210_asv_pre_clock_init;
+ asv_info->pre_clock_setup = exynos4210_asv_pre_clock_setup;
+ asv_info->store_result = exynos4210_asv_store_result;
+}
diff --git a/arch/arm/mach-exynos/asv.c b/arch/arm/mach-exynos/asv.c
new file mode 100644
index 00000000000..d0a33d3cecf
--- /dev/null
+++ b/arch/arm/mach-exynos/asv.c
@@ -0,0 +1,71 @@
+/* linux/arch/arm/mach-exynos/asv.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4 - ASV(Adaptive Support Voltage) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <plat/cpu.h>
+
+#include <mach/map.h>
+#include <mach/asv.h>
+
+static struct samsung_asv *exynos_asv;
+
+static int __init exynos_asv_init(void)
+{
+ exynos_asv = kzalloc(sizeof(struct samsung_asv), GFP_KERNEL);
+ if (!exynos_asv)
+ goto out;
+
+ if (soc_is_exynos4210())
+ exynos4210_asv_init(exynos_asv);
+ else
+ goto out;
+
+ if (exynos_asv->check_vdd_arm) {
+ if (exynos_asv->check_vdd_arm())
+ goto out;
+ }
+
+ /* Get HPM Delay value */
+ if (exynos_asv->get_hpm) {
+ if (exynos_asv->get_hpm(exynos_asv))
+ goto out;
+ } else
+ goto out;
+
+ /* Get IDS ARM Value */
+ if (exynos_asv->get_ids) {
+ if (exynos_asv->get_ids(exynos_asv))
+ goto out;
+ } else
+ goto out;
+
+ if (exynos_asv->store_result) {
+ if (exynos_asv->store_result(exynos_asv))
+ goto out;
+ } else
+ goto out;
+
+ return 0;
+out:
+ pr_err("EXYNOS : Fail to initialize ASV\n");
+
+ kfree(exynos_asv);
+
+ return -EINVAL;
+}
+device_initcall_sync(exynos_asv_init);
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
index af51a5fd638..35bf3ba6e18 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -25,12 +25,14 @@
#include <mach-exynos/map.h>
#include <mach-exynos/regs-clock.h>
#include <mach-exynos/sysmmu.h>
+#include <mach-exynos/regs-audss.h>
#include "common.h"
#include "clock-exynos4.h"
#ifdef CONFIG_PM_SLEEP
static struct sleep_save exynos4_clock_save[] = {
+ SAVE_ITEM(EXYNOS4_CLKSRC_AUDSS),
SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
@@ -118,6 +120,10 @@ static struct clk dummy_apb_pclk = {
.id = -1,
};
+static struct clk exynos4_clk_xxti = {
+ .name = "xxti",
+};
+
static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
@@ -313,6 +319,25 @@ static struct clksrc_clk exynos4_clk_periphclk = {
.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
};
+static struct clk *exynos4_clkset_mout_hpm_list[] = {
+ [0] = &exynos4_clk_mout_apll.clk,
+ [1] = &exynos4_clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources exynos4_clkset_sclk_hpm = {
+ .sources = exynos4_clkset_mout_hpm_list,
+ .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_hpm_list),
+};
+
+static struct clksrc_clk exynos4_clk_dout_copy = {
+ .clk = {
+ .name = "dout_copy",
+ },
+ .sources = &exynos4_clkset_sclk_hpm,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 20, .size = 1 },
+ .reg_div = { .reg = EXYNOS4_CLKDIV_CPU1, .shift = 0, .size = 3 },
+};
+
/* Core list of CMU_CORE side */
static struct clk *exynos4_clkset_corebus_list[] = {
@@ -793,6 +818,24 @@ static struct clk exynos4_clk_fimd0 = {
.ctrlbit = (1 << 0),
};
+static struct clk *exynos4_clkset_mout_audss_list[] = {
+ &exynos4_clk_xxti,
+ &clk_fout_epll,
+};
+
+static struct clksrc_sources exynos4_clkset_mout_audss = {
+ .sources = exynos4_clkset_mout_audss_list,
+ .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_audss_list),
+};
+
+static struct clksrc_clk exynos4_clk_mout_audss = {
+ .clk = {
+ .name = "busclk",
+ },
+ .sources = &exynos4_clkset_mout_audss,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_AUDSS, .shift = 0, .size = 1 },
+};
+
struct clk *exynos4_clkset_group_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
@@ -1110,7 +1153,20 @@ static struct clksrc_clk exynos4_clksrcs[] = {
.ctrlbit = (1 << 16),
},
.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
- }
+ }, {
+ .clk = {
+ .name = "sclk_hpm",
+ .parent = &exynos4_clk_dout_copy.clk,
+ },
+ .reg_div = { .reg = EXYNOS4_CLKDIV_CPU1, .shift = 4, .size = 3 },
+ }, {
+ .clk = {
+ .name = "sclk_pwi",
+ },
+ .sources = &exynos4_clkset_group,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 16, .size = 4 },
+ .reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 8, .size = 4 },
+ },
};
static struct clksrc_clk exynos4_clk_sclk_uart0 = {
@@ -1279,6 +1335,7 @@ static struct clksrc_clk *exynos4_sysclks[] = {
&exynos4_clk_armclk,
&exynos4_clk_aclk_corem0,
&exynos4_clk_aclk_cores,
+ &exynos4_clk_dout_copy,
&exynos4_clk_aclk_corem1,
&exynos4_clk_periphclk,
&exynos4_clk_mout_corebus,
@@ -1293,6 +1350,7 @@ static struct clksrc_clk *exynos4_sysclks[] = {
&exynos4_clk_aclk_100,
&exynos4_clk_aclk_160,
&exynos4_clk_aclk_133,
+ &exynos4_clk_mout_audss,
&exynos4_clk_dout_mmc0,
&exynos4_clk_dout_mmc1,
&exynos4_clk_dout_mmc2,
@@ -1342,6 +1400,7 @@ static struct clk_lookup exynos4_clk_lookup[] = {
CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
+ CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &exynos4_clk_mout_audss.clk),
};
static int xtal_rate;
@@ -1357,6 +1416,78 @@ static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
return 0;
}
+static u32 exynos4_epll_div[][6] = {
+ { 48000000, 0, 48, 3, 3, 0 },
+ { 96000000, 0, 48, 3, 2, 0 },
+ { 144000000, 1, 72, 3, 2, 0 },
+ { 192000000, 0, 48, 3, 1, 0 },
+ { 288000000, 1, 72, 3, 1, 0 },
+ { 84000000, 0, 42, 3, 2, 0 },
+ { 50000000, 0, 50, 3, 3, 0 },
+ { 80000000, 1, 80, 3, 3, 0 },
+ { 32750000, 1, 65, 3, 4, 35127 },
+ { 32768000, 1, 65, 3, 4, 35127 },
+ { 49152000, 0, 49, 3, 3, 9961 },
+ { 67737600, 1, 67, 3, 3, 48366 },
+ { 73728000, 1, 73, 3, 3, 47710 },
+ { 45158400, 0, 45, 3, 3, 10381 },
+ { 45000000, 0, 45, 3, 3, 10355 },
+ { 45158000, 0, 45, 3, 3, 10355 },
+ { 49125000, 0, 49, 3, 3, 9961 },
+ { 67738000, 1, 67, 3, 3, 48366 },
+ { 73800000, 1, 73, 3, 3, 47710 },
+ { 36000000, 1, 32, 3, 4, 0 },
+ { 60000000, 1, 60, 3, 3, 0 },
+ { 72000000, 1, 72, 3, 3, 0 },
+ { 191923200, 0, 47, 3, 1, 64278 },
+ { 180633600, 0, 45, 3, 1, 10381 },
+};
+
+static int exynos4_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int epll_con, epll_con_k;
+ unsigned int i;
+
+ /* Return if nothing changed */
+ if (clk->rate == rate)
+ return 0;
+
+ epll_con = __raw_readl(EXYNOS4_EPLL_CON0);
+ epll_con &= ~(0x1 << 27 | \
+ PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
+ PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
+ PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+ for (i = 0; i < ARRAY_SIZE(exynos4_epll_div); i++) {
+ if (exynos4_epll_div[i][0] == rate) {
+ epll_con_k = exynos4_epll_div[i][5] << 0;
+ epll_con |= exynos4_epll_div[i][1] << 27;
+ epll_con |= exynos4_epll_div[i][2] << PLL46XX_MDIV_SHIFT;
+ epll_con |= exynos4_epll_div[i][3] << PLL46XX_PDIV_SHIFT;
+ epll_con |= exynos4_epll_div[i][4] << PLL46XX_SDIV_SHIFT;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(exynos4_epll_div)) {
+ printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(epll_con, EXYNOS4_EPLL_CON0);
+ __raw_writel(epll_con_k, EXYNOS4_EPLL_CON1);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+static struct clk_ops exynos4_epll_ops = {
+ .get_rate = s5p_epll_get_rate,
+ .set_rate = exynos4_epll_set_rate,
+};
+
static struct clk_ops exynos4_fout_apll_ops = {
.get_rate = exynos4_fout_apll_get_rate,
};
@@ -1486,6 +1617,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
clk_fout_vpll.ops = &exynos4_vpll_ops;
clk_fout_vpll.rate = vpll;
+ clk_fout_epll.enable = s5p_epll_enable;
+ clk_fout_epll.ops = &exynos4_epll_ops;
+ clk_set_parent(&exynos4_clk_mout_audss.clk, &clk_fout_epll);
+
printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
apll, mpll, epll, vpll);
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 5fd3af4d4a3..3f9d89d77b2 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -53,6 +53,12 @@
#define L2_AUX_VAL 0x7C470001
#define L2_AUX_MASK 0xC200ffff
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
+#else
+#define s3c_irq_wake NULL
+#endif
+
static const char name_exynos4210[] = "EXYNOS4210";
static const char name_exynos4212[] = "EXYNOS4212";
static const char name_exynos4412[] = "EXYNOS4412";
@@ -64,6 +70,8 @@ static void exynos4_init_clocks(int xtal);
static void exynos5_init_clocks(int xtal);
static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
static int exynos_init(void);
+static int exynos_init_irq_eint(struct device_node *np,
+ struct device_node *parent);
static struct cpu_table cpu_ids[] __initdata = {
{
@@ -189,6 +197,11 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_64K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S5P_VA_AUDSS,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_AUDSS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)S3C_VA_USB_HSPHY,
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K,
@@ -603,6 +616,8 @@ static const struct of_device_id exynos4_dt_irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{ .compatible = "samsung,exynos4210-combiner",
.data = combiner_of_init, },
+ { .compatible = "samsung,exynos4210-wakeup-eint",
+ .data = exynos_init_irq_eint, },
{},
};
#endif
@@ -620,8 +635,10 @@ void __init exynos4_init_irq(void)
of_irq_init(exynos4_dt_irq_match);
#endif
- if (!of_have_populated_dt())
+ if (!of_have_populated_dt()) {
combiner_init(S5P_VA_COMBINER_BASE, NULL);
+ exynos_init_irq_eint(NULL, NULL);
+ }
/*
* The parameters of s5p_init_irq() are for VIC init.
@@ -629,14 +646,38 @@ void __init exynos4_init_irq(void)
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
+#ifdef CONFIG_PM
+ irq_get_chip(IRQ_RTC_ALARM)->irq_set_wake = s3c_irq_wake;
+#endif
}
void __init exynos5_init_irq(void)
{
+ int irq;
+ struct device_node *np;
+
#ifdef CONFIG_OF
of_irq_init(exynos4_dt_irq_match);
#endif
/*
+ * The Exynos5 wakeup interrupt controller has two-interrupt parents,
+ * gic and combiner. Hence, a interrupt nexus node is used to translate
+ * interrupt specifers for the interrupts which wakeup interrupt
+ * controller deliver to the gic and combiner.
+ *
+ * When using a interrupt nexus node (which is child node of the wakeup
+ * controller node), the interrupt parent of the wakeup controller node
+ * is set as the nexus node and the nexus node does not have a
+ * 'interrupt-controller' property. Hence, the of_irq_init function
+ * will not be able to invoke the intializer function for wakeup
+ * interrupt controller. So call the initiazer explicitly here.
+ */
+ np = of_find_compatible_node(NULL, NULL,
+ "samsung,exynos5210-wakeup-eint");
+ if (np)
+ exynos_init_irq_eint(np, NULL);
+
+ /*
* The parameters of s5p_init_irq() are for VIC init.
* Theses parameters should be NULL and 0 because EXYNOS4
* uses GIC instead of VIC.
@@ -742,6 +783,9 @@ static DEFINE_SPINLOCK(eint_lock);
static unsigned int eint0_15_data[16];
+#define EXYNOS_EINT_NR 32
+static struct irq_domain *irq_domain;
+
static inline int exynos4_irq_to_gpio(unsigned int irq)
{
if (irq < IRQ_EINT(0))
@@ -832,9 +876,9 @@ static inline void exynos_irq_eint_mask(struct irq_data *data)
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
- mask |= EINT_OFFSET_BIT(data->irq);
- __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->hwirq));
+ mask |= EINT_OFFSET_BIT(data->hwirq);
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
}
@@ -843,16 +887,16 @@ static void exynos_irq_eint_unmask(struct irq_data *data)
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
- mask &= ~(EINT_OFFSET_BIT(data->irq));
- __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->hwirq));
+ mask &= ~(EINT_OFFSET_BIT(data->hwirq));
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
}
static inline void exynos_irq_eint_ack(struct irq_data *data)
{
- __raw_writel(EINT_OFFSET_BIT(data->irq),
- EINT_PEND(exynos_eint_base, data->irq));
+ __raw_writel(EINT_OFFSET_BIT(data->hwirq),
+ EINT_PEND(exynos_eint_base, data->hwirq));
}
static void exynos_irq_eint_maskack(struct irq_data *data)
@@ -863,7 +907,7 @@ static void exynos_irq_eint_maskack(struct irq_data *data)
static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
- int offs = EINT_OFFSET(data->irq);
+ int offs = data->hwirq;
int shift;
u32 ctrl, mask;
u32 newvalue = 0;
@@ -898,10 +942,10 @@ static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
mask = 0x7 << shift;
spin_lock(&eint_lock);
- ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
+ ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->hwirq));
ctrl &= ~mask;
ctrl |= newvalue << shift;
- __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
+ __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
if (soc_is_exynos5250())
@@ -945,7 +989,7 @@ static inline void exynos_irq_demux_eint(unsigned int start)
while (status) {
irq = fls(status) - 1;
- generic_handle_irq(irq + start);
+ generic_handle_irq(irq_find_mapping(irq_domain, irq + start));
status &= ~(1 << irq);
}
}
@@ -954,8 +998,8 @@ static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
- exynos_irq_demux_eint(IRQ_EINT(16));
- exynos_irq_demux_eint(IRQ_EINT(24));
+ exynos_irq_demux_eint(16);
+ exynos_irq_demux_eint(24);
chained_irq_exit(chip, desc);
}
@@ -963,6 +1007,7 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
{
u32 *irq_data = irq_get_handler_data(irq);
struct irq_chip *chip = irq_get_chip(irq);
+ int eint_irq;
chained_irq_enter(chip, desc);
chip->irq_mask(&desc->irq_data);
@@ -970,50 +1015,94 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
if (chip->irq_ack)
chip->irq_ack(&desc->irq_data);
- generic_handle_irq(*irq_data);
+ eint_irq = irq_find_mapping(irq_domain, *irq_data);
+ generic_handle_irq(eint_irq);
chip->irq_unmask(&desc->irq_data);
chained_irq_exit(chip, desc);
}
-static int __init exynos_init_irq_eint(void)
+static int exynos_eint_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
{
- int irq;
+ irq_set_chip_and_handler(irq, &exynos_irq_eint, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ return 0;
+}
- if (soc_is_exynos5250())
- exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
- else
- exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+static struct irq_domain_ops exynos_eint_irq_domain_ops = {
+ .map = exynos_eint_irq_domain_map,
+};
+
+static int __init exynos_init_irq_eint(struct device_node *np,
+ struct device_node *parent)
+{
+ int irq, *src_int, irq_base, irq_eint;
+ unsigned int paddr;
+
+#ifdef CONFIG_PINCTRL_SAMSUNG
+ /*
+ * The Samsung pinctrl driver provides an integrated gpio/pinmux/pinconf
+ * functionality along with support for external gpio and wakeup
+ * interrupts. If the samsung pinctrl driver is enabled and includes
+ * the wakeup interrupt support, then the setting up external wakeup
+ * interrupts here can be skipped. This check here is temporary to
+ * allow exynos4 platforms that do not use Samsung pinctrl driver to
+ * co-exist with platforms that do. When all of the Samsung Exynos4
+ * platforms switch over to using the pinctrl driver, the wakeup
+ * interrupt support code here can be completely removed.
+ */
+ struct device_node *pctrl_np, *wkup_np;
+ const char *pctrl_compat = "samsung,pinctrl-exynos4210";
+ const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
+
+ for_each_compatible_node(pctrl_np, NULL, pctrl_compat) {
+ if (of_device_is_available(pctrl_np)) {
+ wkup_np = of_find_compatible_node(pctrl_np, NULL,
+ wkup_compat);
+ if (wkup_np)
+ return -ENODEV;
+ }
+ }
+#endif
- if (exynos_eint_base == NULL) {
+ if (!np) {
+ paddr = soc_is_exynos5250() ? EXYNOS5_PA_GPIO1 :
+ EXYNOS4_PA_GPIO2;
+ exynos_eint_base = ioremap(paddr, SZ_4K);
+ } else {
+ exynos_eint_base = of_iomap(np, 0);
+ }
+ if (!exynos_eint_base) {
pr_err("unable to ioremap for EINT base address\n");
- return -ENOMEM;
+ return -ENXIO;
}
- for (irq = 0 ; irq <= 31 ; irq++) {
- irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
- handle_level_irq);
- set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
+ irq_base = irq_alloc_descs(IRQ_EINT(0), 1, EXYNOS_EINT_NR, 0);
+ if (IS_ERR_VALUE(irq_base)) {
+ irq_base = IRQ_EINT(0);
+ pr_warning("%s: irq desc alloc failed. Continuing with %d as "
+ "linux irq base\n", __func__, irq_base);
}
- irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
-
- for (irq = 0 ; irq <= 15 ; irq++) {
- eint0_15_data[irq] = IRQ_EINT(irq);
-
- if (soc_is_exynos5250()) {
- irq_set_handler_data(exynos5_eint0_15_src_int[irq],
- &eint0_15_data[irq]);
- irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
- exynos_irq_eint0_15);
- } else {
- irq_set_handler_data(exynos4_eint0_15_src_int[irq],
- &eint0_15_data[irq]);
- irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
- exynos_irq_eint0_15);
- }
+ irq_domain = irq_domain_add_legacy(np, EXYNOS_EINT_NR, irq_base, 0,
+ &exynos_eint_irq_domain_ops, NULL);
+ if (WARN_ON(!irq_domain)) {
+ pr_warning("%s: irq domain init failed\n", __func__);
+ return 0;
+ }
+
+ irq_eint = np ? irq_of_parse_and_map(np, 16) : EXYNOS_IRQ_EINT16_31;
+ irq_set_chained_handler(irq_eint, exynos_irq_demux_eint16_31);
+
+ for (irq = 0 ; irq <= 15; irq++) {
+ eint0_15_data[irq] = irq;
+ src_int = soc_is_exynos5250() ? exynos5_eint0_15_src_int :
+ exynos4_eint0_15_src_int;
+ irq_eint = np ? irq_of_parse_and_map(np, irq) : src_int[irq];
+ irq_set_handler_data(irq_eint, &eint0_15_data[irq]);
+ irq_set_chained_handler(irq_eint, exynos_irq_eint0_15);
}
return 0;
}
-arch_initcall(exynos_init_irq_eint);
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
index 3538532265e..5ed7da5ded4 100644
--- a/arch/arm/mach-exynos/dma.c
+++ b/arch/arm/mach-exynos/dma.c
@@ -303,10 +303,12 @@ static int __init exynos_dma_init(void)
dma_cap_set(DMA_SLAVE, exynos_pdma0_pdata.cap_mask);
dma_cap_set(DMA_CYCLIC, exynos_pdma0_pdata.cap_mask);
+ dma_cap_set(DMA_PRIVATE, exynos_pdma0_pdata.cap_mask);
amba_device_register(&exynos_pdma0_device, &iomem_resource);
dma_cap_set(DMA_SLAVE, exynos_pdma1_pdata.cap_mask);
dma_cap_set(DMA_CYCLIC, exynos_pdma1_pdata.cap_mask);
+ dma_cap_set(DMA_PRIVATE, exynos_pdma1_pdata.cap_mask);
amba_device_register(&exynos_pdma1_device, &iomem_resource);
dma_cap_set(DMA_MEMCPY, exynos_mdma1_pdata.cap_mask);
diff --git a/arch/arm/mach-exynos/include/mach-exynos/asv.h b/arch/arm/mach-exynos/include/mach-exynos/asv.h
new file mode 100644
index 00000000000..5b48b74811e
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach-exynos/asv.h
@@ -0,0 +1,43 @@
+/* linux/arch/arm/mach-exynos/include/mach/asv.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4 - Adaptive Support Voltage Header file
+ *
+ * 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 __ASM_ARCH_ASV_H
+#define __ASM_ARCH_ASV_H __FILE__
+
+#define JUDGE_TABLE_END NULL
+#define EXYNOS4_LOOP_CNT 10
+
+struct asv_judge_table {
+ unsigned int hpm_limit; /* HPM value to decide group of target */
+ unsigned int ids_limit; /* IDS value to decide group of target */
+};
+
+struct samsung_asv {
+ unsigned int pkg_id; /* fused value for chip */
+ unsigned int ids_offset; /* ids_offset of chip */
+ unsigned int ids_mask; /* ids_mask of chip */
+ unsigned int hpm_result; /* hpm value of chip */
+ unsigned int ids_result; /* ids value of chip */
+ int (*check_vdd_arm)(void); /* check vdd_arm value, this function is selectable */
+ int (*pre_clock_init)(void); /* clock init function to get hpm */
+ int (*pre_clock_setup)(void); /* clock setup function to get hpm */
+ /* specific get ids function */
+ int (*get_ids)(struct samsung_asv *asv_info);
+ /* specific get hpm function */
+ int (*get_hpm)(struct samsung_asv *asv_info);
+ /* store into some repository to send result of asv */
+ int (*store_result)(struct samsung_asv *asv_info);
+};
+
+extern void exynos4210_asv_init(struct samsung_asv *asv_info);
+
+#endif /* __ASM_ARCH_ASV_H */
diff --git a/arch/arm/mach-exynos/include/mach-exynos/cpufreq.h b/arch/arm/mach-exynos/include/mach-exynos/cpufreq.h
index 7517c3f417a..be80017eace 100644
--- a/arch/arm/mach-exynos/include/mach-exynos/cpufreq.h
+++ b/arch/arm/mach-exynos/include/mach-exynos/cpufreq.h
@@ -10,6 +10,8 @@
* published by the Free Software Foundation.
*/
+extern unsigned int exynos_result_of_asv;
+
enum cpufreq_level_index {
L0, L1, L2, L3, L4,
L5, L6, L7, L8, L9,
diff --git a/arch/arm/mach-exynos/include/mach-exynos/irqs.h b/arch/arm/mach-exynos/include/mach-exynos/irqs.h
index 15beb1623b0..bb9f48e1221 100644
--- a/arch/arm/mach-exynos/include/mach-exynos/irqs.h
+++ b/arch/arm/mach-exynos/include/mach-exynos/irqs.h
@@ -461,6 +461,7 @@
#define S5P_GPIOINT_BASE (S5P_EINT_BASE1 + 32)
#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64)
+#define IRQ_TS (S5P_EINT_BASE1 + 25)
/* Set the default NR_IRQS */
diff --git a/arch/arm/mach-exynos/include/mach-exynos/mali/config.h b/arch/arm/mach-exynos/include/mach-exynos/mali/config.h
new file mode 100644
index 00000000000..ccd3cf7d245
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach-exynos/mali/config.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the EB platform with ZBT memory enabled */
+/*zepplin added 2010.08.17 for orion configuration*/
+#define MALI_BASE_ADDR 0x13000000
+#define GP_ADDR MALI_BASE_ADDR
+#define L2_ADDR MALI_BASE_ADDR+0x1000
+#define PMU_ADDR MALI_BASE_ADDR+0x2000
+#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000
+#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000
+#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000
+#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000
+#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000
+#define PP0_ADDR MALI_BASE_ADDR+0x8000
+#define PP1_ADDR MALI_BASE_ADDR+0xA000
+#define PP2_ADDR MALI_BASE_ADDR+0xC000
+#define PP3_ADDR MALI_BASE_ADDR+0xE000
+
+/*for mmu and os memory*/
+#define MEM_BASE_ADDR 0x40000000
+#define MEM_TOTAL_SIZE 0x40000000
+#define MEM_MALI_OS_SIZE 0x18000000
+
+/*for dedicated memory*/
+//#define MEM_MALI_BASE 0x58000000
+//#define MEM_MALI_SIZE 0x08000000
+#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024
+#define MEM_MALI_BASE 0x60000000 - MEM_MALI_SIZE
+
+//#define S5P_IRQ(x) (x+32)
+//#define IRQ_SPI(x) S5P_IRQ(x+32)
+#define MAX_IRQ_IN_COMBINER 8
+//#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
+
+#define IRQ_PPMMU0_3D COMBINER_IRQ(13, 0)
+#define IRQ_PPMMU1_3D COMBINER_IRQ(13, 1)
+#define IRQ_PPMMU2_3D COMBINER_IRQ(13, 2)
+#define IRQ_PPMMU3_3D COMBINER_IRQ(13, 3)
+#define IRQ_GPMMU_3D COMBINER_IRQ(13, 4)
+
+#define IRQ_PP0_3D COMBINER_IRQ(14, 0)
+#define IRQ_PP1_3D COMBINER_IRQ(14, 1)
+#define IRQ_PP2_3D COMBINER_IRQ(14, 2)
+#define IRQ_PP3_3D COMBINER_IRQ(14, 3)
+#define IRQ_GP_3D COMBINER_IRQ(14, 4)
+#define IRQ_PMU_3D COMBINER_IRQ(14, 5)
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+ {
+ .type = MALI400GP,
+ .description = "Mali-400 GP",
+ .base = GP_ADDR,
+ .irq = IRQ_GP_3D,
+ .mmu_id = 1
+ },
+ {
+ .type = MALI400PP,
+ .base = PP0_ADDR,
+ .irq = IRQ_PP0_3D,
+ .description = "Mali-400 PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MALI400PP,
+ .base = PP1_ADDR,
+ .irq = IRQ_PP1_3D,
+ .description = "Mali-400 PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MALI400PP,
+ .base = PP2_ADDR,
+ .irq = IRQ_PP2_3D,
+ .description = "Mali-400 PP 2",
+ .mmu_id = 4
+ },
+ {
+ .type = MALI400PP,
+ .base = PP3_ADDR,
+ .irq = IRQ_PP3_3D,
+ .description = "Mali-400 PP 3",
+ .mmu_id = 5
+ },
+#if USING_MMU
+ {
+ .type = MMU,
+ .base = GP_MMU_ADDR,
+ .irq = IRQ_GPMMU_3D,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = PP0_MMU_ADDR,
+ .irq = IRQ_PPMMU0_3D,
+ .description = "Mali-400 MMU for PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = PP1_MMU_ADDR,
+ .irq = IRQ_PPMMU1_3D,
+ .description = "Mali-400 MMU for PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MMU,
+ .base = PP2_MMU_ADDR,
+ .irq = IRQ_PPMMU2_3D,
+ .description = "Mali-400 MMU for PP 2",
+ .mmu_id = 4
+ },
+ {
+ .type = MMU,
+ .base = PP3_MMU_ADDR,
+ .irq = IRQ_PPMMU3_3D,
+ .description = "Mali-400 MMU for PP 3",
+ .mmu_id = 5
+ },
+#if USING_OS_MEMORY
+ {
+ .type = OS_MEMORY,
+ .description = "System Memory",
+ .size = MEM_MALI_OS_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+#endif
+#if USING_DED /* Dedicated Memory */
+ {
+ .type = MEMORY,
+ .description = "Dedicated Memory",
+ .base = MEM_MALI_BASE,
+ .size = MEM_MALI_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE
+ },
+#endif/* if USING_OS_MEMORY*/
+ {
+ .type = MEM_VALIDATION,
+ .description = "memory validation",
+ .base = MEM_BASE_ADDR,
+ .size = MEM_TOTAL_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE
+ },
+#else /* Not using MMU */
+ {
+ .type = MEMORY,
+ .description = "Dedicated Memory",
+ .base = MEM_MALI_BASE,
+ .size = MEM_MALI_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE
+ },
+#endif
+ {
+ .type = MALI400L2,
+ .base = L2_ADDR,
+ .description = "Mali-400 L2 cache"
+ },
+};
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/arch/arm/mach-exynos/include/mach-exynos/map.h b/arch/arm/mach-exynos/include/mach-exynos/map.h
index 9df5e30a69f..a79aade9070 100644
--- a/arch/arm/mach-exynos/include/mach-exynos/map.h
+++ b/arch/arm/mach-exynos/include/mach-exynos/map.h
@@ -39,6 +39,8 @@
#define EXYNOS4_PA_G2D 0x12800000
+#define EXYNOS4_PA_G3D 0x13000000
+
#define EXYNOS4_PA_I2S0 0x03830000
#define EXYNOS4_PA_I2S1 0xE3100000
#define EXYNOS4_PA_I2S2 0xE2A00000
@@ -79,6 +81,8 @@
#define EXYNOS4_PA_COMBINER 0x10440000
#define EXYNOS5_PA_COMBINER 0x10440000
+#define EXYNOS4_PA_IEM 0x10460000
+
#define EXYNOS4_PA_GIC_CPU 0x10480000
#define EXYNOS4_PA_GIC_DIST 0x10490000
#define EXYNOS5_PA_GIC_CPU 0x10482000
@@ -204,6 +208,8 @@
#define EXYNOS4_PA_ADC 0x13910000
#define EXYNOS4_PA_ADC1 0x13911000
+#define EXYNOS4_PA_AUDSS 0x03810000
+
#define EXYNOS4_PA_AC97 0x139A0000
#define EXYNOS4_PA_SPDIF 0x139B0000
@@ -242,6 +248,7 @@
#define S5P_PA_FIMC3 EXYNOS4_PA_FIMC3
#define S5P_PA_JPEG EXYNOS4_PA_JPEG
#define S5P_PA_G2D EXYNOS4_PA_G2D
+#define S5P_PA_G3D EXYNOS4_PA_G3D
#define S5P_PA_FIMD0 EXYNOS4_PA_FIMD0
#define S5P_PA_HDMI EXYNOS4_PA_HDMI
#define S5P_PA_IIC_HDMIPHY EXYNOS4_PA_IIC_HDMIPHY
diff --git a/arch/arm/mach-exynos/include/mach-exynos/regs-audss.h b/arch/arm/mach-exynos/include/mach-exynos/regs-audss.h
index ca5a8b64218..04494f0da4e 100644
--- a/arch/arm/mach-exynos/include/mach-exynos/regs-audss.h
+++ b/arch/arm/mach-exynos/include/mach-exynos/regs-audss.h
@@ -15,4 +15,12 @@
#define EXYNOS4_AUDSS_INT_MEM (0x03000000)
+#define EXYNOS_AUDSSREG(x) (S5P_VA_AUDSS + (x))
+
+#define EXYNOS4_CLKSRC_AUDSS EXYNOS_AUDSSREG(0x0)
+#define EXYNOS4_CLKDIV_AUDSS EXYNOS_AUDSSREG(0x4)
+#define EXYNOS4_CLKGATE_AUDSS EXYNOS_AUDSSREG(0x8)
+
+#define EXYNOS4_AUDSS_CLKGATE_I2SBUS (1<<2)
+
#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-exynos/include/mach-exynos/regs-clock.h b/arch/arm/mach-exynos/include/mach-exynos/regs-clock.h
index 920939b68a5..17235d68ba4 100644
--- a/arch/arm/mach-exynos/include/mach-exynos/regs-clock.h
+++ b/arch/arm/mach-exynos/include/mach-exynos/regs-clock.h
@@ -135,6 +135,24 @@
#define EXYNOS4_CLKGATE_SCLKCPU EXYNOS_CLKREG(0x14800)
#define EXYNOS4_CLKGATE_IP_CPU EXYNOS_CLKREG(0x14900)
+#define EXYNOS4_APLL_CON0L8 EXYNOS_CLKREG(0x15100)
+#define EXYNOS4_APLL_CON0L7 EXYNOS_CLKREG(0x15104)
+#define EXYNOS4_APLL_CON0L6 EXYNOS_CLKREG(0x15108)
+#define EXYNOS4_APLL_CON0L5 EXYNOS_CLKREG(0x1510C)
+#define EXYNOS4_APLL_CON0L4 EXYNOS_CLKREG(0x15110)
+#define EXYNOS4_APLL_CON0L3 EXYNOS_CLKREG(0x15114)
+#define EXYNOS4_APLL_CON0L2 EXYNOS_CLKREG(0x15118)
+#define EXYNOS4_APLL_CON0L1 EXYNOS_CLKREG(0x1511C)
+
+#define EXYNOS4_CLKDIV_IEM_L8 EXYNOS_CLKREG(0x15300)
+#define EXYNOS4_CLKDIV_IEM_L7 EXYNOS_CLKREG(0x15304)
+#define EXYNOS4_CLKDIV_IEM_L6 EXYNOS_CLKREG(0x15308)
+#define EXYNOS4_CLKDIV_IEM_L5 EXYNOS_CLKREG(0x1530C)
+#define EXYNOS4_CLKDIV_IEM_L4 EXYNOS_CLKREG(0x15310)
+#define EXYNOS4_CLKDIV_IEM_L3 EXYNOS_CLKREG(0x15314)
+#define EXYNOS4_CLKDIV_IEM_L2 EXYNOS_CLKREG(0x15318)
+#define EXYNOS4_CLKDIV_IEM_L1 EXYNOS_CLKREG(0x1531C)
+
#define EXYNOS4_CLKGATE_IP_ISP0 EXYNOS_CLKREG(0x18800)
#define EXYNOS4_CLKGATE_IP_ISP1 EXYNOS_CLKREG(0x18804)
diff --git a/arch/arm/mach-exynos/include/mach-exynos/regs-gpio.h b/arch/arm/mach-exynos/include/mach-exynos/regs-gpio.h
index 077ebfd55f6..31178953df1 100644
--- a/arch/arm/mach-exynos/include/mach-exynos/regs-gpio.h
+++ b/arch/arm/mach-exynos/include/mach-exynos/regs-gpio.h
@@ -16,13 +16,13 @@
#include <mach-exynos/map.h>
#include <mach-exynos/irqs.h>
-#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
+#define EINT_REG_NR(x) ((x) >> 3)
#define EINT_CON(b, x) (b + 0xE00 + (EINT_REG_NR(x) * 4))
#define EINT_FLTCON(b, x) (b + 0xE80 + (EINT_REG_NR(x) * 4))
#define EINT_MASK(b, x) (b + 0xF00 + (EINT_REG_NR(x) * 4))
#define EINT_PEND(b, x) (b + 0xF40 + (EINT_REG_NR(x) * 4))
-#define EINT_OFFSET_BIT(x) (1 << (EINT_OFFSET(x) & 0x7))
+#define EINT_OFFSET_BIT(x) (1 << ((x) & 0x7))
/* compatibility for plat-s5p/irq-pm.c */
#define EXYNOS4_EINT40CON (S5P_VA_GPIO2 + 0xE00)
diff --git a/arch/arm/mach-exynos/include/mach-exynos/regs-iem.h b/arch/arm/mach-exynos/include/mach-exynos/regs-iem.h
new file mode 100644
index 00000000000..d9bf1777858
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach-exynos/regs-iem.h
@@ -0,0 +1,27 @@
+/* linux/arch/arm/mach-exynos/include/mach/regs-iem.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4 - IEM(INTELLIGENT ENERGY MANAGEMENT) register discription
+ *
+ * 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 __ASM_ARCH_REGS_IEM_H
+#define __ASM_ARCH_REGS_IEM_H __FILE__
+
+/* Register for IEC */
+#define EXYNOS4_IECDPCCR (0x00000)
+
+/* Register for APC */
+#define EXYNOS4_APC_CONTROL (0x10010)
+#define EXYNOS4_APC_PREDLYSEL (0x10024)
+#define EXYNOS4_APC_DBG_DLYCODE (0x100E0)
+
+#define APC_HPM_EN (1 << 4)
+#define IEC_EN (1 << 0)
+
+#endif /* __ASM_ARCH_REGS_IEM_H */
diff --git a/arch/arm/mach-exynos/include/mach-exynos/ump/config.h b/arch/arm/mach-exynos/include/mach-exynos/ump/config.h
new file mode 100644
index 00000000000..a82934f2799
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach-exynos/ump/config.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT UMP_MEMORY_TYPE
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT CONFIG_UMP_MEM_SIZE * 1024UL * 1024UL
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 0c4fc418da9..ea0bcc9f955 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -14,15 +14,55 @@
#include <linux/of_platform.h>
#include <linux/serial_core.h>
+#include <linux/pwm_backlight.h>
+#include <plat/backlight.h>
+#include <plat/gpio-cfg.h>
+#include <linux/gpio.h>
+#include <plat/regs-fb-v4.h>
+#include <linux/fb.h>
+#include <plat/fb.h>
+#include <linux/lcd.h>
+#include <plat/devs.h>
+#include <linux/platform_data/s3c-hsotg.h>
+
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <mach-exynos/map.h>
+#include <mach-exynos/ohci.h>
#include <plat-samsung/cpu.h>
#include <plat-samsung/regs-serial.h>
+#include <plat-samsung/ehci.h>
+#include <plat-samsung/usb-phy.h>
#include "common.h"
+static struct s5p_ehci_platdata origen_ehci_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+static struct exynos4_ohci_platdata origen_ohci_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+static struct s3c_hsotg_plat origen_hsotg_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+ .no = EXYNOS4_GPD0(0),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data origen_bl_data = {
+ .pwm_id = 0,
+ .pwm_period_ns = 1000,
+};
+
/*
* The following lookup table is used to override device names when devices
* are registered from device tree. This is temporarily added to enable
@@ -55,6 +95,8 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
"exynos4-sdhci.3", NULL),
OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
"s3c2440-i2c.0", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(1),
+ "s3c2440-i2c.1", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
"exynos4210-spi.0", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
@@ -63,6 +105,17 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
"exynos4210-spi.2", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
+ OF_DEV_AUXDATA("samsung,exynos-ehci", EXYNOS4_PA_EHCI, "s5p-ehci",
+ &origen_ehci_pdata),
+ OF_DEV_AUXDATA("samsung,exynos-ohci", EXYNOS4_PA_OHCI, "exynos-ohci",
+ &origen_ohci_pdata),
+ OF_DEV_AUXDATA("samsung,exynos-hsotg", EXYNOS4_PA_HSOTG, "s3c-hsotg",
+ &origen_hsotg_pdata),
+ OF_DEV_AUXDATA("samsung,exynos4210-fimd", EXYNOS4_PA_FIMD0,
+ "exynos4-fb.0", NULL),
+ OF_DEV_AUXDATA("samsung,samsung-i2s", EXYNOS4_PA_I2S0,
+ "samsung-i2s.0", NULL),
+ OF_DEV_AUXDATA("samsung,audio-dma", 0, "samsung-audio", NULL),
{},
};
@@ -72,10 +125,21 @@ static void __init exynos4210_dt_map_io(void)
s3c24xx_init_clocks(24000000);
}
+static void __init exynos4_setup_fimd(void)
+{
+ unsigned int reg;
+
+ reg = __raw_readl(S3C_VA_SYS + 0x0210);
+ reg |= (1 << 1);
+ __raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
+
static void __init exynos4210_dt_machine_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
exynos4210_auxdata_lookup, NULL);
+ samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+ exynos4_setup_fimd();
}
static char const *exynos4210_dt_compat[] __initdata = {
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 55ae986ffe6..8704544d0c1 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/input.h>
+#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/gpio_keys.h>
#include <linux/i2c.h>
@@ -23,12 +24,19 @@
#include <linux/lcd.h>
#include <linux/rfkill-gpio.h>
#include <linux/platform_data/s3c-hsotg.h>
+#include <linux/ath6kl.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+
+#include <media/s5k4ecgx.h>
+#include <media/s5p_fimc.h>
+#include <media/v4l2-mediabus.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <asm/mach-types.h>
-#include <video/platform_lcd.h>
+#include <video/lcd_pwrctrl.h>
#include <plat-samsung/regs-serial.h>
#include <plat-samsung/regs-fb-v4.h>
@@ -43,6 +51,7 @@
#include <plat-samsung/fb.h>
#include <plat-samsung/mfc.h>
#include <plat-samsung/hdmi.h>
+#include <plat-samsung/camport.h>
#include <mach-exynos/ohci.h>
#include <mach-exynos/map.h>
@@ -99,6 +108,8 @@ static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
+ REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), /* OTG */
+ REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"), /* OTG */
};
static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
@@ -121,6 +132,7 @@ static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
};
static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+ REGULATOR_SUPPLY("vmmc", NULL),
};
static struct regulator_consumer_supply __initdata buck1_consumer[] = {
REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
@@ -132,7 +144,7 @@ static struct regulator_consumer_supply __initdata buck3_consumer[] = {
REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
};
static struct regulator_consumer_supply __initdata buck7_consumer[] = {
- REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+ REGULATOR_SUPPLY("vcc-lcd", "lcd-pwrctrl.0"), /* LCD */
};
static struct regulator_init_data __initdata max8997_ldo1_data = {
@@ -166,6 +178,7 @@ static struct regulator_init_data __initdata max8997_ldo3_data = {
.min_uV = 1100000,
.max_uV = 1100000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -209,6 +222,7 @@ static struct regulator_init_data __initdata max8997_ldo7_data = {
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -268,6 +282,7 @@ static struct regulator_init_data __initdata max8997_ldo11_data = {
.min_uV = 3000000,
.max_uV = 3000000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -358,7 +373,9 @@ static struct regulator_init_data __initdata max8997_buck3_data = {
.constraints = {
.name = "VDD_G3D_1.1V",
.min_uV = 900000,
- .max_uV = 1100000,
+ .max_uV = 1200000,
+ .always_on = 1,
+ .boot_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
.state_mem = {
@@ -387,7 +404,7 @@ static struct regulator_init_data __initdata max8997_buck7_data = {
.name = "VDD_LCD_3.3V",
.min_uV = 3300000,
.max_uV = 3300000,
- .boot_on = 1,
+ .boot_on = 0,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
@@ -470,6 +487,19 @@ static struct i2c_board_info i2c0_devs[] __initdata = {
.platform_data = &origen_max8997_pdata,
.irq = IRQ_EINT(4),
},
+#ifdef CONFIG_TOUCHSCREEN_UNIDISPLAY_TS
+ {
+ I2C_BOARD_INFO("unidisplay_ts", 0x41),
+ .irq = IRQ_TS,
+ },
+#endif
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("alc5625", 0x1E),
+ },
};
static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
@@ -480,6 +510,127 @@ static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
};
+
+/*
+ * WLAN: SDIO Host will call this func at booting time
+ */
+static int origen_wifi_status_register(void (*notify_func)
+ (struct platform_device *, int state));
+
+/* WLAN: MMC3-SDIO */
+static struct s3c_sdhci_platdata origen_hsmmc3_pdata __initdata = {
+ .max_width = 4,
+ .host_caps = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+ .pm_caps = MMC_PM_KEEP_POWER,
+ .cd_type = S3C_SDHCI_CD_EXTERNAL,
+ .ext_cd_init = origen_wifi_status_register,
+};
+
+/*
+ * WLAN: Save SDIO Card detect func into this pointer
+ */
+static void (*wifi_status_cb)(struct platform_device *, int state);
+
+static int origen_wifi_status_register(void (*notify_func)
+ (struct platform_device *, int state))
+{
+ /* Assign sdhci_s3c_notify_change to wifi_status_cb */
+ if (!notify_func)
+ return -EAGAIN;
+ else
+ wifi_status_cb = notify_func;
+
+ return 0;
+}
+
+#define ORIGEN_WLAN_WOW EXYNOS4_GPX2(3)
+#define ORIGEN_WLAN_RESET EXYNOS4_GPX2(4)
+
+
+static void origen_wlan_setup_power(bool val)
+{
+ int err;
+
+ if (val) {
+ err = gpio_request_one(ORIGEN_WLAN_RESET,
+ GPIOF_OUT_INIT_LOW, "GPX2_4");
+ if (err) {
+ pr_warning("ORIGEN: Not obtain WIFI gpios\n");
+ return;
+ }
+ s3c_gpio_cfgpin(ORIGEN_WLAN_RESET, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(ORIGEN_WLAN_RESET,
+ S3C_GPIO_PULL_NONE);
+ /* VDD33,I/O Supply must be done */
+ gpio_set_value(ORIGEN_WLAN_RESET, 0);
+ udelay(30); /*Tb */
+ gpio_direction_output(ORIGEN_WLAN_RESET, 1);
+ } else {
+ gpio_direction_output(ORIGEN_WLAN_RESET, 0);
+ gpio_free(ORIGEN_WLAN_RESET);
+ }
+
+ mdelay(100);
+
+ return;
+}
+
+/*
+ * This will be called at init time of WLAN driver
+ */
+static int origen_wifi_set_detect(bool val)
+{
+
+ if (!wifi_status_cb) {
+ pr_warning("ORIGEN: WLAN: No callback \n"
+ "ORIGEN: WLAN: MMC should boot earlier than net \n");
+
+ return -EAGAIN;
+ }
+ if (true == val) {
+ origen_wlan_setup_power(true);
+ wifi_status_cb(&s3c_device_hsmmc3, 1);
+ } else {
+ origen_wlan_setup_power(false);
+ wifi_status_cb(&s3c_device_hsmmc3, 0);
+ }
+
+ return 0;
+}
+
+struct ath6kl_platform_data origen_wlan_data __initdata = {
+ .setup_power = origen_wifi_set_detect,
+};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX
+static int origen_camera_power(int enable);
+static struct s5k4ecgx_platform_data s5k4ecgx_plat = {
+ .set_power = origen_camera_power,
+};
+
+static struct i2c_board_info s5k4ecgx_board_info = {
+ I2C_BOARD_INFO("S5K4ECGX", 0x5A >> 1),
+ .platform_data = &s5k4ecgx_plat,
+};
+
+static struct s5p_fimc_isp_info s5k4ecgx_camera_sensors[] = {
+ {
+ .flags = V4L2_MBUS_PCLK_SAMPLE_RISING |
+ V4L2_MBUS_VSYNC_ACTIVE_LOW,
+ .bus_type = FIMC_ITU_601,
+ .board_info = &s5k4ecgx_board_info,
+ .clk_frequency = 24000000UL,
+ .i2c_bus_num = 0,
+ },
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+ .isp_info = s5k4ecgx_camera_sensors,
+ .num_clients = ARRAY_SIZE(s5k4ecgx_camera_sensors),
+};
+#endif
+
/* USB EHCI */
static struct s5p_ehci_platdata origen_ehci_pdata;
@@ -587,33 +738,20 @@ static struct platform_device origen_device_gpiokeys = {
},
};
-static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
-{
- int ret;
-
- if (power)
- ret = gpio_request_one(EXYNOS4_GPE3(4),
- GPIOF_OUT_INIT_HIGH, "GPE3_4");
- else
- ret = gpio_request_one(EXYNOS4_GPE3(4),
- GPIOF_OUT_INIT_LOW, "GPE3_4");
-
- gpio_free(EXYNOS4_GPE3(4));
-
- if (ret)
- pr_err("failed to request gpio for LCD power: %d\n", ret);
-}
-
-static struct plat_lcd_data origen_lcd_hv070wsa_data = {
- .set_power = lcd_hv070wsa_set_power,
+static struct lcd_pwrctrl_data origen_lcd_hv070wsa_data = {
+ .gpio = EXYNOS4_GPE3(4),
};
static struct platform_device origen_lcd_hv070wsa = {
- .name = "platform-lcd",
+ .name = "lcd-pwrctrl",
.dev.parent = &s5p_device_fimd0.dev,
.dev.platform_data = &origen_lcd_hv070wsa_data,
};
+static struct pwm_lookup origen_pwm_lookup[] = {
+ PWM_LOOKUP("s3c24xx-pwm.0", 0, "pwm-backlight.0", NULL),
+};
+
#ifdef CONFIG_DRM_EXYNOS
static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
.panel = {
@@ -639,7 +777,25 @@ static struct s3c_fb_pd_win origen_fb_win0 = {
.xres = 1024,
.yres = 600,
.max_bpp = 32,
- .default_bpp = 24,
+ .default_bpp = 32,
+ .virtual_x = 1024,
+ .virtual_y = 2 * 600,
+};
+
+static struct s3c_fb_pd_win origen_fb_win1 = {
+ .xres = 1024,
+ .yres = 600,
+ .max_bpp = 32,
+ .default_bpp = 32,
+ .virtual_x = 1024,
+ .virtual_y = 2 * 600,
+};
+
+static struct s3c_fb_pd_win origen_fb_win2 = {
+ .xres = 1024,
+ .yres = 600,
+ .max_bpp = 32,
+ .default_bpp = 32,
.virtual_x = 1024,
.virtual_y = 2 * 600,
};
@@ -657,6 +813,8 @@ static struct fb_videomode origen_lcd_timing = {
static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
.win[0] = &origen_fb_win0,
+ .win[1] = &origen_fb_win1,
+ .win[2] = &origen_fb_win2,
.vtiming = &origen_lcd_timing,
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
@@ -682,10 +840,18 @@ static struct platform_device origen_device_bluetooth = {
},
};
+/* Audio device */
+static struct platform_device origen_device_audio = {
+ .name = "origen-audio",
+ .id = -1,
+};
+
static struct platform_device *origen_devices[] __initdata = {
&s3c_device_hsmmc2,
&s3c_device_hsmmc0,
+ &s3c_device_hsmmc3,
&s3c_device_i2c0,
+ &s3c_device_i2c1,
&s3c_device_rtc,
&s3c_device_usb_hsotg,
&s3c_device_wdt,
@@ -697,6 +863,7 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_fimc_md,
&s5p_device_fimd0,
&s5p_device_g2d,
+ &s5p_device_g3d,
&s5p_device_hdmi,
&s5p_device_i2c_hdmiphy,
&s5p_device_jpeg,
@@ -704,6 +871,8 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_mfc_l,
&s5p_device_mfc_r,
&s5p_device_mixer,
+ &samsung_asoc_dma,
+ &exynos4_device_i2s0,
#ifdef CONFIG_DRM_EXYNOS
&exynos_device_drm,
#endif
@@ -711,6 +880,7 @@ static struct platform_device *origen_devices[] __initdata = {
&origen_device_gpiokeys,
&origen_lcd_hv070wsa,
&origen_leds_gpio,
+ &origen_device_audio,
&origen_device_bluetooth,
};
@@ -762,9 +932,64 @@ static void __init origen_power_init(void)
s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
}
+#ifdef CONFIG_VIDEO_S5K4ECGX
+#define ORIGEN_GPIO_CAM_RESET EXYNOS4_GPE1(4)
+#define ORIGEN_GPIO_CAM_PWDN EXYNOS4_GPE1(0)
+#define ORIGEN_GPIO_CAM_2V8 EXYNOS4_GPE1(1)
+#define ORIGEN_GPIO_CAM_1V8 EXYNOS4_GPE1(2)
+struct gpio cam_gpio[] = {
+ {ORIGEN_GPIO_CAM_RESET, GPIOF_DIR_OUT, "reset"},
+ {ORIGEN_GPIO_CAM_PWDN, GPIOF_DIR_OUT, "power down"},
+ {ORIGEN_GPIO_CAM_2V8, GPIOF_DIR_OUT, "2v8"},
+ {ORIGEN_GPIO_CAM_1V8, GPIOF_DIR_OUT, "1v8"},
+};
+
+static void __init origen_camera_init(void)
+{
+ int ret;
+
+ ret = gpio_request_array(cam_gpio,
+ sizeof(cam_gpio) / sizeof(struct gpio));
+ if (ret) {
+ pr_err("%s: Could not request the gpio for camera\n", __func__);
+ return;
+ }
+
+ s3c_gpio_cfgpin(ORIGEN_GPIO_CAM_RESET, S3C_GPIO_OUTPUT);
+ s3c_gpio_cfgpin(ORIGEN_GPIO_CAM_PWDN, S3C_GPIO_OUTPUT);
+ s3c_gpio_cfgpin(ORIGEN_GPIO_CAM_2V8, S3C_GPIO_OUTPUT);
+ s3c_gpio_cfgpin(ORIGEN_GPIO_CAM_1V8, S3C_GPIO_OUTPUT);
+
+ if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A)) {
+ pr_err("%s: Camera port A setup failed\n", __func__);
+ return;
+ }
+}
+
+static int origen_camera_power(int enable)
+{
+ if (enable) {
+ gpio_set_value(ORIGEN_GPIO_CAM_2V8, 1);
+ gpio_set_value(ORIGEN_GPIO_CAM_1V8, 1);
+ udelay(10);
+ gpio_set_value(ORIGEN_GPIO_CAM_PWDN, 0);
+ udelay(15);
+ gpio_set_value(ORIGEN_GPIO_CAM_RESET, 1);
+ udelay(60);
+ } else {
+ gpio_set_value(ORIGEN_GPIO_CAM_RESET, 0);
+ udelay(50);
+ gpio_set_value(ORIGEN_GPIO_CAM_PWDN, 1);
+ gpio_set_value(ORIGEN_GPIO_CAM_2V8, 0);
+ gpio_set_value(ORIGEN_GPIO_CAM_1V8, 0);
+ }
+ return 0;
+}
+#endif
+
static void __init origen_reserve(void)
{
- s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+ s5p_mfc_reserve_mem(0x43000000, 32 << 20, 0x51000000, 32 << 20);
}
static void __init origen_machine_init(void)
@@ -774,12 +999,16 @@ static void __init origen_machine_init(void)
s3c_i2c0_set_platdata(NULL);
i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+ s3c_i2c1_set_platdata(NULL);
+ i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
/*
* Since sdhci instance 2 can contain a bootable media,
* sdhci instance 0 is registered after instance 2.
*/
s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+ s3c_sdhci3_set_platdata(&origen_hsmmc3_pdata);
origen_ehci_init();
origen_ohci_init();
@@ -798,9 +1027,17 @@ static void __init origen_machine_init(void)
platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+ pwm_add_table(origen_pwm_lookup, ARRAY_SIZE(origen_pwm_lookup));
samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
origen_bt_setup();
+
+ ath6kl_set_platform_data(&origen_wlan_data);
+#ifdef CONFIG_VIDEO_S5K4ECGX
+ s3c_set_platdata(&fimc_md_platdata, sizeof(fimc_md_platdata),
+ &s5p_device_fimc_md);
+ origen_camera_init();
+#endif
}
MACHINE_START(ORIGEN, "ORIGEN")
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index a9a1335d672..aed0dd84a7e 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -312,6 +312,9 @@ static void exynos_pm_resume(void)
}
early_wakeup:
+ /* Clear INFORM Register */
+ __raw_writel(0, S5P_INFORM1);
+
return;
}
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 3b3e6f6ed27..cfae825e933 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -191,6 +191,11 @@ static __init int exynos4_pm_init_power_domain(void)
#ifdef CONFIG_S5P_DEV_G2D
exynos_pm_add_dev_to_genpd(&s5p_device_g2d, &exynos4_pd_lcd0);
#endif
+#ifdef CONFIG_S5P_DEV_G3D
+ /* MALI requires the PD to be always on. */
+ exynos4_pd_g3d.pd.power_off = NULL;
+ exynos_pm_add_dev_to_genpd(&s5p_device_g3d, &exynos4_pd_g3d);
+#endif
#ifdef CONFIG_S5P_DEV_JPEG
exynos_pm_add_dev_to_genpd(&s5p_device_jpeg, &exynos4_pd_cam);
#endif
@@ -200,6 +205,7 @@ arch_initcall(exynos4_pm_init_power_domain);
int __init exynos_pm_late_initcall(void)
{
- pm_genpd_poweroff_unused();
+ if (!of_have_populated_dt())
+ pm_genpd_poweroff_unused();
return 0;
}
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 9c3b90c3538..9e7b40e2402 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -371,6 +371,11 @@ config S5P_DEV_G2D
help
Compile in platform device definitions for G2D device
+config S5P_DEV_G3D
+ bool
+ help
+ Compile in platform device definitions for G3D device
+
config S5P_DEV_I2C_HDMIPHY
bool
help
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index a328736d16c..3803dc9e07f 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -144,6 +144,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
int clk_set_rate(struct clk *clk, unsigned long rate)
{
+ unsigned long flags;
int ret;
if (IS_ERR(clk))
@@ -159,9 +160,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (clk->ops == NULL || clk->ops->set_rate == NULL)
return -EINVAL;
- spin_lock(&clocks_lock);
+ spin_lock_irqsave(&clocks_lock, flags);
ret = (clk->ops->set_rate)(clk, rate);
- spin_unlock(&clocks_lock);
+ spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
@@ -173,17 +174,18 @@ struct clk *clk_get_parent(struct clk *clk)
int clk_set_parent(struct clk *clk, struct clk *parent)
{
+ unsigned long flags;
int ret = 0;
if (IS_ERR(clk))
return -EINVAL;
- spin_lock(&clocks_lock);
+ spin_lock_irqsave(&clocks_lock, flags);
if (clk->ops && clk->ops->set_parent)
ret = (clk->ops->set_parent)(clk, parent);
- spin_unlock(&clocks_lock);
+ spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index de205e6fd9b..1f82fc23b0f 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -290,6 +290,25 @@ struct platform_device s5p_device_g2d = {
};
#endif /* CONFIG_S5P_DEV_G2D */
+/* G3D */
+
+#ifdef CONFIG_S5P_DEV_G3D
+static struct resource s5p_g3d_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_G3D, SZ_256K),
+};
+
+struct platform_device s5p_device_g3d = {
+ .name = "s5p-g3d",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_g3d_resource),
+ .resource = s5p_g3d_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S5P_DEV_G3D */
+
#ifdef CONFIG_S5P_DEV_JPEG
static struct resource s5p_jpeg_resource[] = {
[0] = DEFINE_RES_MEM(S5P_PA_JPEG, SZ_4K),
diff --git a/arch/arm/plat-samsung/include/plat-samsung/devs.h b/arch/arm/plat-samsung/include/plat-samsung/devs.h
index 5da4b4f38f4..5037810463e 100644
--- a/arch/arm/plat-samsung/include/plat-samsung/devs.h
+++ b/arch/arm/plat-samsung/include/plat-samsung/devs.h
@@ -83,6 +83,7 @@ extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_fimc_md;
extern struct platform_device s5p_device_jpeg;
extern struct platform_device s5p_device_g2d;
+extern struct platform_device s5p_device_g3d;
extern struct platform_device s5p_device_fimd0;
extern struct platform_device s5p_device_hdmi;
extern struct platform_device s5p_device_i2c_hdmiphy;
diff --git a/arch/arm/plat-samsung/include/plat-samsung/map-s5p.h b/arch/arm/plat-samsung/include/plat-samsung/map-s5p.h
index 19398af7dbc..eba5574807a 100644
--- a/arch/arm/plat-samsung/include/plat-samsung/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat-samsung/map-s5p.h
@@ -40,6 +40,8 @@
#define S5P_VA_GIC_CPU S3C_ADDR(0x02810000)
#define S5P_VA_GIC_DIST S3C_ADDR(0x02820000)
+#define S5P_VA_AUDSS S3C_ADDR(0X02A00000)
+
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
#define VA_VIC1 VA_VIC(1)
diff --git a/arch/arm/plat-samsung/include/plat-samsung/regs-fb.h b/arch/arm/plat-samsung/include/plat-samsung/regs-fb.h
index 9a78012d6f4..a053b9635ce 100644
--- a/arch/arm/plat-samsung/include/plat-samsung/regs-fb.h
+++ b/arch/arm/plat-samsung/include/plat-samsung/regs-fb.h
@@ -401,3 +401,17 @@
#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
+/* Blending control registers */
+#define S3C_WINCON_BLD_PIXEL (1 << 6)
+#define S3C_WINCON_BLD_MASK (1 << 6)
+#define S3C_WINCON_ALPHA1_SEL (1 << 1)
+#define S3C_WINCON_ALPHA_SEL_MASK (1 << 1)
+#define S3C_WINCON(x) (0x0020 + (x * 0x04))
+#define S3C_VIDOSD_C(x) (0x0048 + (x * 0x10))
+#define S3C_WINSHMAP (0x0034)
+#define S3C_WINSHMAP_CH_ENABLE(x) (1 << (x))
+#define S3C_WINCON_BLD_PLANE (0 << 6)
+#define S3C_WINCON_ALPHA0_SEL (0 << 1)
+#define S3C_VIDOSD_ALPHA0_SHIFT (12)
+#define S3C_VIDOSD_ALPHA1_SHIFT (0)
+
diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c
index 0e6d7aca81b..6a42d70624d 100644
--- a/arch/arm/plat-samsung/s5p-dev-mfc.c
+++ b/arch/arm/plat-samsung/s5p-dev-mfc.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
#include <linux/memblock.h>
#include <linux/ioport.h>
@@ -20,52 +21,14 @@
#include <plat-samsung/irqs.h>
#include <plat-samsung/mfc.h>
-struct s5p_mfc_reserved_mem {
- phys_addr_t base;
- unsigned long size;
- struct device *dev;
-};
-
-static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
-
void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
phys_addr_t lbase, unsigned int lsize)
{
- int i;
-
- s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
- s5p_mfc_mem[0].base = rbase;
- s5p_mfc_mem[0].size = rsize;
-
- s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
- s5p_mfc_mem[1].base = lbase;
- s5p_mfc_mem[1].size = lsize;
-
- for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
- struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
- if (memblock_remove(area->base, area->size)) {
- printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
- area->size, (unsigned long) area->base);
- area->base = 0;
- }
- }
-}
-
-static int __init s5p_mfc_memory_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
- struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
- if (!area->base)
- continue;
+ if (dma_declare_contiguous(&s5p_device_mfc_r.dev, rsize, rbase, 0))
+ printk(KERN_ERR "Failed to reserve memory for MFC device (%u bytes at 0x%08lx)\n",
+ rsize, (unsigned long) rbase);
- if (dma_declare_coherent_memory(area->dev, area->base,
- area->base, area->size,
- DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
- printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
- area->size, (unsigned long) area->base);
- }
- return 0;
+ if (dma_declare_contiguous(&s5p_device_mfc_l.dev, lsize, lbase, 0))
+ printk(KERN_ERR "Failed to reserve memory for MFC device (%u bytes at 0x%08lx)\n",
+ rsize, (unsigned long) rbase);
}
-device_initcall(s5p_mfc_memory_init);
diff --git a/drivers/Makefile b/drivers/Makefile
index 9aa5f373567..cdba3d65bf1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
obj-y += hsi/
+obj-y += mmc/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
@@ -98,7 +99,6 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
-obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-y += leds/
obj-$(CONFIG_SWITCH) += switch/
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index ba3487c9835..f6802cb6d39 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1323,7 +1323,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
}
ret = dev_pm_get_subsys_data(dev);
- if (ret)
+ if (ret < 0)
goto out;
genpd->device_count++;
@@ -1358,7 +1358,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (gpd_data != gpd_data_new)
__pm_genpd_free_dev_data(dev, gpd_data_new);
- return ret;
+ return (ret < 0) ? : 0;
}
/**
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 637782b7bb6..72a2a039d82 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -17,6 +17,8 @@
#include <linux/regulator/consumer.h>
#include <linux/cpufreq.h>
#include <linux/suspend.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
#include <mach-exynos/cpufreq.h>
@@ -46,7 +48,7 @@ static int exynos_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- unsigned int index, old_index;
+ unsigned int index, old_index = 0, i;
unsigned int arm_volt, safe_arm_volt = 0;
int ret = 0;
struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
@@ -214,8 +216,35 @@ static struct notifier_block exynos_cpufreq_nb = {
.notifier_call = exynos_cpufreq_pm_notifier,
};
+static int exynos_cpufreq_reboot_notifier(struct notifier_block *this,
+ unsigned long code, void *_cmd)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
+ mutex_lock(&cpufreq_lock);
+
+ if (frequency_locked)
+ goto out;
+ frequency_locked = true;
+
+ if (locking_frequency) {
+ mutex_unlock(&cpufreq_lock);
+ exynos_target(policy, locking_frequency, CPUFREQ_RELATION_H);
+ mutex_lock(&cpufreq_lock);
+ }
+
+out:
+ mutex_unlock(&cpufreq_lock);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block exynos_cpufreq_reboot_nb = {
+ .notifier_call = exynos_cpufreq_reboot_notifier,
+};
+
static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
+ int ret;
+
policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
@@ -238,16 +267,35 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpumask_setall(policy->cpus);
}
- return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ if (ret)
+ return ret;
+
+ cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
+ return 0;
+
}
+static int exynos4_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+static struct freq_attr *exynos4_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
static struct cpufreq_driver exynos_driver = {
.flags = CPUFREQ_STICKY,
.verify = exynos_verify_speed,
.target = exynos_target,
.get = exynos_getspeed,
.init = exynos_cpufreq_cpu_init,
+ .exit = exynos4_cpufreq_cpu_exit,
.name = "exynos_cpufreq",
+ .attr = exynos4_cpufreq_attr,
#ifdef CONFIG_PM
.suspend = exynos_cpufreq_suspend,
.resume = exynos_cpufreq_resume,
@@ -286,6 +334,7 @@ static int __init exynos_cpufreq_init(void)
}
register_pm_notifier(&exynos_cpufreq_nb);
+ register_reboot_notifier(&exynos_cpufreq_reboot_nb);
if (cpufreq_register_driver(&exynos_driver)) {
pr_err("%s: failed to register cpufreq driver\n", __func__);
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index 33d3d4cbb3b..8cb633deec5 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -20,6 +20,13 @@
#include <mach-exynos/regs-clock.h>
#include <mach-exynos/cpufreq.h>
+#define SUPPORT_1400MHZ (1 << 31)
+#define SUPPORT_1200MHZ (1 << 30)
+#define SUPPORT_1000MHZ (1 << 29)
+
+#define SUPPORT_FREQ_SHIFT 29
+#define SUPPORT_FREQ_MASK 7
+
#define CPUFREQ_LEVEL_END L5
static int max_support_idx = L0;
@@ -35,10 +42,7 @@ struct cpufreq_clkdiv {
unsigned int clkdiv;
};
-static unsigned int exynos4210_volt_table[CPUFREQ_LEVEL_END] = {
- 1250000, 1150000, 1050000, 975000, 950000,
-};
-
+static unsigned int exynos4210_volt_table[CPUFREQ_LEVEL_END];
static struct cpufreq_clkdiv exynos4210_clkdiv_table[CPUFREQ_LEVEL_END];
@@ -51,6 +55,28 @@ static struct cpufreq_frequency_table exynos4210_freq_table[] = {
{0, CPUFREQ_TABLE_END},
};
+/*
+ * ASV group voltage table
+ */
+static const unsigned int asv_voltage[CPUFREQ_LEVEL_END][8] = {
+ /*
+ * SS, A1, A2, B1, B2, C1, C2, D
+ * @1200 :
+ * @1000 :
+ * @800 : ASV_VOLTAGE_TABLE
+ * @500 :
+ * @200 :
+ */
+ { 1350000, 1350000, 1300000, 1275000, 1250000, 1225000, 1200000,
+ 1175000 },
+ { 1300000, 1250000, 1200000, 1175000, 1150000, 1125000, 1100000,
+ 1075000 },
+ { 1200000, 1150000, 1100000, 1075000, 1050000, 1025000, 1000000,
+ 975000 },
+ { 1100000, 1050000, 1000000, 975000, 975000, 950000, 925000, 925000 },
+ { 1050000, 1000000, 975000, 950000, 950000, 925000, 925000, 925000 },
+};
+
static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
/*
* Clock divider value for following
@@ -229,6 +255,31 @@ static void exynos4210_set_frequency(unsigned int old_index,
}
}
+static void __init set_volt_table(void)
+{
+ unsigned int tmp, i, asv_group = 0;
+
+ tmp = exynos_result_of_asv;
+
+ switch (tmp & (SUPPORT_FREQ_MASK << SUPPORT_FREQ_SHIFT)) {
+ case SUPPORT_1200MHZ:
+ asv_group = (tmp & 0xF);
+ break;
+ case SUPPORT_1400MHZ:
+ case SUPPORT_1000MHZ:
+ default:
+ /* Not supported and assign typical ASV group */
+ asv_group = 2;
+ break;
+ }
+
+ printk(KERN_INFO "DVFS: VDD_ARM Voltage table set with %d Group\n",
+ asv_group);
+
+ for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++)
+ exynos4210_volt_table[i] = asv_voltage[i][asv_group];
+}
+
int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
{
int i;
@@ -275,6 +326,8 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
exynos4210_clkdiv_table[i].clkdiv = tmp;
}
+ set_volt_table();
+
info->mpll_freq_khz = rate;
info->pm_lock_idx = L2;
info->pll_safe_idx = L2;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index e4feba6b03c..600ea5ea982 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2954,6 +2954,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
if (pi->pcfg.num_peri) {
dma_cap_set(DMA_SLAVE, pd->cap_mask);
dma_cap_set(DMA_CYCLIC, pd->cap_mask);
+ dma_cap_set(DMA_PRIVATE, pd->cap_mask);
}
}
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index e658c3d80d7..41db9cfa230 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2734,6 +2734,27 @@ static __init void exynos4_gpiolib_init(void)
int group = 0;
void __iomem *gpx_base;
+#ifdef CONFIG_PINCTRL_SAMSUNG
+ /*
+ * This gpio driver includes support for device tree support and
+ * there are platforms using it. In order to maintain
+ * compatibility with those platforms, and to allow non-dt
+ * Exynos4210 platforms to use this gpiolib support, a check
+ * is added to find out if there is a active pin-controller
+ * driver support available. If it is available, this gpiolib
+ * support is ignored and the gpiolib support available in
+ * pin-controller driver is used. This is a temporary check and
+ * will go away when all of the Exynos4210 platforms have
+ * switched to using device tree and the pin-ctrl driver.
+ */
+ struct device_node *pctrl_np;
+ const char *pctrl_compat = "samsung,pinctrl-exynos4210";
+ pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
+ if (pctrl_np)
+ if (of_device_is_available(pctrl_np))
+ return;
+#endif
+
/* gpio part1 */
gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
if (gpio_base1 == NULL) {
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index ca2d3b34dbf..633b375f4cf 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -1 +1 @@
-obj-y += drm/ vga/ stub/ ion/
+obj-y += drm/ vga/ stub/ ion/ arm/
diff --git a/drivers/gpu/arm/Kconfig b/drivers/gpu/arm/Kconfig
new file mode 100644
index 00000000000..efe78169ac0
--- /dev/null
+++ b/drivers/gpu/arm/Kconfig
@@ -0,0 +1,2 @@
+source "drivers/gpu/arm/mali/Kconfig"
+source "drivers/gpu/arm/ump/Kconfig"
diff --git a/drivers/gpu/arm/Makefile b/drivers/gpu/arm/Makefile
new file mode 100644
index 00000000000..ece84b5fbcd
--- /dev/null
+++ b/drivers/gpu/arm/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MALI400MP) +=mali/
+obj-$(CONFIG_UMP) +=ump/
diff --git a/drivers/gpu/arm/mali/Kconfig b/drivers/gpu/arm/mali/Kconfig
new file mode 100644
index 00000000000..1404f59d3de
--- /dev/null
+++ b/drivers/gpu/arm/mali/Kconfig
@@ -0,0 +1,75 @@
+config MALI400MP
+ bool "Enable MALI integration"
+ default n
+ ---help---
+ This enables MALI 3D graphics driver. Required to use hardware accelerated OpenGL ES 2.0 and 1.1.
+
+config USING_MMU
+ bool "Using MMU"
+ depends on MALI400MP
+ default y
+ ---help---
+ This enables MMU for Mali. Required hardware support for MMU.
+
+config USING_UMP
+ bool "Using UMP"
+ depends on MALI400MP && UMP
+ default y
+ ---help---
+ Using UMP for Mali memory.
+
+config USING_OS_MEMORY
+ bool "Using OS memory"
+ depends on MALI400MP
+ default y
+ ---help---
+ This enables for Mali to use OS memory.
+
+config USING_PMM
+ bool "Enable Power Management"
+ depends on MALI400MP
+ default n
+ ---help---
+ This enables for Mali Power Management.
+
+config USING_GPU_UTILIZATION
+ bool "GPU utilization"
+ depends on MALI400MP
+ default n
+ ---help---
+ This enables GPU utilization information.
+
+config USING_MALI_RUN_TIME_PM
+ bool "Using Run time Power Management"
+ depends on MALI400MP
+ default n
+ ---help---
+ This enables Mali working with run time power management.
+
+config USING_MALI_PMM_TESTSUITE
+ bool "Power Management Test Suite"
+ depends on MALI400MP
+ default n
+ ---help---
+ This enables Power management Test Suite.
+
+config USING_PROFILING
+ bool "Enable Profiling"
+ depends on MALI400MP
+ default n
+ ---help---
+ This support Profiling on Mali.
+
+config DEBUG_BUILD
+ bool "Enables debug messages"
+ depends on MALI400MP
+ default n
+ ---help---
+ This enables Mali driver debug messages.
+
+config MALI_MEM_SIZE
+ int "Mali memory size"
+ depends on MALI400MP
+ default "64"
+ ---help---
+ This value is memory size of Mali GPU(unit is MByte).
diff --git a/drivers/gpu/arm/mali/Makefile b/drivers/gpu/arm/mali/Makefile
new file mode 100755
index 00000000000..b4a9e259fd6
--- /dev/null
+++ b/drivers/gpu/arm/mali/Makefile
@@ -0,0 +1,272 @@
+#
+# Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the GNU General Public License version 2
+# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained from Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+USE_UMPV2=0
+
+OSKOS :=linux
+FILES_PREFIX=
+MALI_FILE_PREFIX := $(srctree)/drivers/gpu/arm/mali
+KBUILDROOT =
+
+# Add platform configuration file for Mali
+#ifeq ($(CONFIG_ARCH_EXYNOS4),y)
+MACHDIR := $(srctree)/arch/arm/mach-exynos
+MALICONFIGDIR :=$(MACHDIR)/include/mach-exynos/mali
+#endif
+
+USING_DED=0
+
+ifeq ($(CONFIG_USING_MMU),y)
+USING_MMU=1
+endif
+
+ifeq ($(CONFIG_USING_UMP),y)
+USING_UMP=1
+endif
+
+ifeq ($(CONFIG_USING_MMU),y)
+USING_MMU=1
+endif
+
+ifeq ($(CONFIG_USING_OS_MEMORY),y)
+USING_OS_MEMORY=1
+endif
+
+ifeq ($(CONFIG_USING_PMM),y)
+USING_PMM=1
+endif
+
+ifeq ($(CONFIG_USING_GPU_UTILIZATION),y)
+USING_GPU_UTILIZATION =1
+endif
+
+ifeq ($(CONFIG_USING_MALI_RUN_TIME_PM),y)
+USING_MALI_RUN_TIME_PM =1
+endif
+
+ifeq ($(CONFIG_USING_MALI_PMM_TESTSUITE),y)
+USING_MALI_PMM_TESTSUITE=1
+endif
+
+ifeq ($(CONFIG_USING_PROFILING),y)
+USING_PROFILING =1
+endif
+
+# set up defaults if not defined by the user
+ARCH ?= arm
+USING_MMU ?= 1
+USING_UMP ?= 0
+USING_OS_MEMORY ?= 0
+USING_PMM ?= 0
+USING_GPU_UTILIZATION ?= 0
+USING_MALI_RUN_TIME_PM ?= 0
+USING_MALI_PMM_TESTSUITE ?= 0
+OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 6
+USING_PROFILING ?= 0
+USING_INTERNAL_PROFILING ?= 0
+TIMESTAMP ?= default
+TARGET_PLATFORM ?= default
+
+ifeq ($(USING_UMP),1)
+ifeq ($(USE_UMPV2),1)
+ UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers
+else
+ UMP_SYMVERS_FILE ?= ../ump/Module.symvers
+endif
+ KBUILD_EXTRA_SYMBOLS = $(KBUILD_EXTMOD)/$(UMP_SYMVERS_FILE)
+endif
+
+# Check if a Mali Core sub module should be enabled, true or false returned
+submodule_enabled = $(shell gcc $(DEFINES) -E $(MALICONFIGDIR)/config.h | grep type | grep -c $(2))
+
+# Set up our defines, which will be passed to gcc
+DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY)
+DEFINES += -DUSING_MMU=$(USING_MMU)
+DEFINES += -DUSING_UMP=$(USING_UMP)
+DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP
+DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING)
+DEFINES += -DMALI_INTERNAL_TIMELINE_PROFILING_ENABLED=$(USING_INTERNAL_PROFILING)
+DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE)
+DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(USING_MALI_RUN_TIME_PM)
+
+# MALI_STATE_TRACKING is only supported on Linux kernels from version 2.6.32.
+DEFINES += -DMALI_STATE_TRACKING=1
+DEFINES += -DMALI_STATE_TRACKING_USING_PROC=1
+DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
+
+ifneq ($(call submodule_enabled, $M, PMU),0)
+ MALI_PLATFORM_FILE = platform/mali400-pmu/mali_platform.o
+else
+ MALI_PLATFORM_FILE = platform/$(TARGET_PLATFORM)/mali_platform.o
+endif
+
+DEFINES += -DUSING_MALI_PMM=$(USING_PMM)
+DEFINES += -DMALI_GPU_UTILIZATION=$(USING_GPU_UTILIZATION)
+
+ifeq ($(CONFIG_DEBUG_BUILD),y)
+DEFINES += -DDEBUG
+endif
+DEFINES += -DSVN_REV=$(SVN_REV)
+DEFINES += -DSVN_REV_STRING=\"$(SVN_REV)\"
+
+# Linux has its own mmap cleanup handlers (see mali_kernel_mem_mmu.c)
+DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP
+
+ifeq ($(USING_UMP),1)
+ DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1
+ EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/../ump/include
+else
+ DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0
+endif
+
+# Target build file
+obj-$(CONFIG_MALI400MP) += mali.o
+
+# Use our defines when compiling
+EXTRA_CFLAGS += $(DEFINES) -I$(MALI_FILE_PREFIX) -I$(MALI_FILE_PREFIX)/common -I$(MALI_FILE_PREFIX)/linux -I$(MALI_FILE_PREFIX)/platform
+
+ifneq ($(CONFIG_UMP),y)
+OSKFILES=$(FILES_PREFIX)$(OSKOS)/mali_osk_atomics.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_locks.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_math.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_memory.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_misc.o
+endif
+OSKFILES+=\
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_time.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.o
+
+UKKFILES=\
+ $(FILES_PREFIX)$(OSKOS)/mali_ukk_mem.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_ukk_gp.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_ukk_pp.o \
+ $(FILES_PREFIX)$(OSKOS)/mali_ukk_core.o
+
+ifeq ($(USING_PROFILING),1)
+UKKFILES+=\
+ $(FILES_PREFIX)$(OSKOS)/mali_ukk_profiling.o
+endif
+
+# 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 $(MALI_FILE_PREFIX)/linux/license/gpl/*),)
+EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/linux/license/proprietary
+else
+EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/linux/license/gpl
+endif
+EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/common/pmm
+
+# Source files which always are included in a build
+mali-y := \
+ common/mali_kernel_core.o \
+ linux/mali_kernel_linux.o \
+ $(OSKOS)/mali_osk_indir_mmap.o \
+ common/mali_kernel_rendercore.o \
+ common/mali_kernel_descriptor_mapping.o \
+ common/mali_kernel_vsync.o \
+ linux/mali_ukk_vsync.o \
+ linux/mali_kernel_sysfs.o \
+ $(MALI_PLATFORM_FILE) \
+ $(OSKFILES) \
+ $(UKKFILES)
+
+ifeq ($(USING_PROFILING),1)
+mali-y += \
+ linux/mali_osk_profiling_gator.o \
+ timestamp-$(TIMESTAMP)/mali_timestamp.o
+EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/timestamp-$(TIMESTAMP)
+endif
+
+ifeq ($(USING_INTERNAL_PROFILING),1)
+mali-y += \
+ common/mali_osk_profiling_internal.o \
+ timestamp-$(TIMESTAMP)/mali_timestamp.o
+EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/timestamp-$(TIMESTAMP)
+endif
+
+
+# Selecting files to compile by parsing the config file
+
+ifeq ($(USING_PMM),1)
+mali-y += \
+ common/pmm/mali_pmm.o \
+ common/pmm/mali_pmm_policy.o \
+ common/pmm/mali_pmm_policy_alwayson.o \
+ common/pmm/mali_pmm_policy_jobcontrol.o \
+ common/pmm/mali_pmm_state.o \
+ linux/mali_kernel_pm.o \
+ linux/mali_osk_pm.o \
+ linux/mali_device_pause_resume.o
+endif
+
+ifeq ($(USING_GPU_UTILIZATION),1)
+mali-y += \
+ common/mali_kernel_utilization.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI400PP),0)
+ # Mali-400 PP in use
+ EXTRA_CFLAGS += -DUSING_MALI400
+ mali-y += common/mali_kernel_MALI200.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI400GP),0)
+ # Mali-400 GP in use
+ mali-y += common/mali_kernel_GP2.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI300PP),0)
+ # Mali-400 PP in use
+ EXTRA_CFLAGS += -DUSING_MALI400
+ mali-y += common/mali_kernel_MALI200.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI300GP),0)
+ # Mali-400 GP in use
+ mali-y += common/mali_kernel_GP2.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI200),0)
+ # Mali200 in use
+ EXTRA_CFLAGS += -DUSING_MALI200
+ mali-y += common/mali_kernel_MALI200.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALIGP2),0)
+ # MaliGP2 in use
+ mali-y += common/mali_kernel_GP2.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MMU),0)
+ # Mali MMU in use
+ mali-y += common/mali_kernel_mem_mmu.o common/mali_kernel_memory_engine.o common/mali_block_allocator.o common/mali_kernel_mem_os.o
+else
+ # No Mali MMU in use
+ mali-y += common/mali_kernel_mem_buddy.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI400L2)$(),0)
+ # Mali Level2 cache in use
+ EXTRA_CFLAGS += -DUSING_MALI400_L2_CACHE
+ mali-y += common/mali_kernel_l2_cache.o
+endif
+
+ifneq ($(call submodule_enabled, $M, MALI300L2)$(),0)
+ # Mali Level2 cache in use
+ EXTRA_CFLAGS += -DUSING_MALI400_L2_CACHE
+ mali-y += common/mali_kernel_l2_cache.o
+endif
+
diff --git a/drivers/gpu/arm/mali/arch/config.h b/drivers/gpu/arm/mali/arch/config.h
new file mode 100644
index 00000000000..ae2fcf81d73
--- /dev/null
+++ b/drivers/gpu/arm/mali/arch/config.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the EB platform with ZBT memory enabled */
+
+#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+ {
+ .type = MALI400GP,
+ .description = "Mali-400 GP",
+ .base = 0xC0000000,
+ .irq = -1,
+ .mmu_id = 1
+ },
+ {
+ .type = MALI400PP,
+ .base = 0xc0008000,
+ .irq = -1,
+ .description = "Mali-400 PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MALI400PP,
+ .base = 0xc000A000,
+ .irq = -1,
+ .description = "Mali-400 PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MALI400PP,
+ .base = 0xc000C000,
+ .irq = -1,
+ .description = "Mali-400 PP 2",
+ .mmu_id = 4
+ },
+ {
+ .type = MALI400PP,
+ .base = 0xc000E000,
+ .irq = -1,
+ .description = "Mali-400 PP 3",
+ .mmu_id = 5
+ },
+#if USING_MMU
+ {
+ .type = MMU,
+ .base = 0xC0003000,
+ .irq = 102,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = 0xC0004000,
+ .irq = 102,
+ .description = "Mali-400 MMU for PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = 0xC0005000,
+ .irq = 102,
+ .description = "Mali-400 MMU for PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MMU,
+ .base = 0xC0006000,
+ .irq = 102,
+ .description = "Mali-400 MMU for PP 2",
+ .mmu_id = 4
+ },
+ {
+ .type = MMU,
+ .base = 0xC0007000,
+ .irq = 102,
+ .description = "Mali-400 MMU for PP 3",
+ .mmu_id = 5
+ },
+#endif
+#if ! ONLY_ZBT
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+ .base = 0xD2000000, /* Reserving 32MB for UMP devicedriver */
+ .size = MEM_MALI_SIZE,
+#else
+ .base = 0xD0000000,
+ .size = MEM_MALI_SIZE,
+#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+#endif
+#if USING_ZBT
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = MEM_MALI_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+#endif
+ {
+ .type = MEM_VALIDATION,
+ .description = "Framebuffer",
+ .base = 0xe0000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE
+ },
+ {
+ .type = MALI400L2,
+ .base = 0xC0001000,
+ .description = "Mali-400 L2 cache"
+ },
+};
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_block_allocator.c b/drivers/gpu/arm/mali/common/mali_block_allocator.c
new file mode 100644
index 00000000000..5c2c49a71a2
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_block_allocator.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_memory_engine.h"
+#include "mali_block_allocator.h"
+#include "mali_osk.h"
+
+#define MALI_BLOCK_SIZE (256UL * 1024UL) /* 256 kB, remember to keep the ()s */
+
+typedef struct block_info
+{
+ struct block_info * next;
+} block_info;
+
+/* The structure used as the handle produced by block_allocator_allocate,
+ * and removed by block_allocator_release */
+typedef struct block_allocator_allocation
+{
+ /* The list will be released in reverse order */
+ block_info *last_allocated;
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+ u32 start_offset;
+ u32 mapping_length;
+} block_allocator_allocation;
+
+
+typedef struct block_allocator
+{
+ _mali_osk_lock_t *mutex;
+ block_info * all_blocks;
+ block_info * first_free;
+ u32 base;
+ u32 cpu_usage_adjust;
+ u32 num_blocks;
+} block_allocator;
+
+MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block);
+static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
+static void block_allocator_release(void * ctx, void * handle);
+static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block);
+static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block );
+static void block_allocator_destroy(mali_physical_memory_allocator * allocator);
+static u32 block_allocator_stat(mali_physical_memory_allocator * allocator);
+
+mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name)
+{
+ mali_physical_memory_allocator * allocator;
+ 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;
+ }
+
+ allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator));
+ if (NULL != allocator)
+ {
+ info = _mali_osk_malloc(sizeof(block_allocator));
+ if (NULL != info)
+ {
+ info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, 105);
+ if (NULL != 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->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];
+ }
+
+ allocator->allocate = block_allocator_allocate;
+ allocator->allocate_page_table_block = block_allocator_allocate_page_table_block;
+ allocator->destroy = block_allocator_destroy;
+ allocator->stat = block_allocator_stat;
+ allocator->ctx = info;
+ allocator->name = name;
+
+ return allocator;
+ }
+ _mali_osk_lock_term(info->mutex);
+ }
+ _mali_osk_free(info);
+ }
+ _mali_osk_free(allocator);
+ }
+
+ return NULL;
+}
+
+static void block_allocator_destroy(mali_physical_memory_allocator * allocator)
+{
+ block_allocator * info;
+ MALI_DEBUG_ASSERT_POINTER(allocator);
+ MALI_DEBUG_ASSERT_POINTER(allocator->ctx);
+ info = (block_allocator*)allocator->ctx;
+
+ _mali_osk_free(info->all_blocks);
+ _mali_osk_lock_term(info->mutex);
+ _mali_osk_free(info);
+ _mali_osk_free(allocator);
+}
+
+MALI_STATIC_INLINE u32 get_phys(block_allocator * info, block_info * block)
+{
+ return info->base + ((block - info->all_blocks) * MALI_BLOCK_SIZE);
+}
+
+static mali_physical_memory_allocation_result block_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
+{
+ block_allocator * info;
+ u32 left;
+ block_info * last_allocated = NULL;
+ mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE;
+ block_allocator_allocation *ret_allocation;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(offset);
+ MALI_DEBUG_ASSERT_POINTER(alloc_info);
+
+ info = (block_allocator*)ctx;
+ left = descriptor->size - *offset;
+ MALI_DEBUG_ASSERT(0 != left);
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ ret_allocation = _mali_osk_malloc( sizeof(block_allocator_allocation) );
+
+ if ( NULL == ret_allocation )
+ {
+ /* Failure; try another allocator by returning MALI_MEM_ALLOC_NONE */
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+ return result;
+ }
+
+ ret_allocation->start_offset = *offset;
+ ret_allocation->mapping_length = 0;
+
+ while ((left > 0) && (info->first_free))
+ {
+ block_info * block;
+ u32 phys_addr;
+ u32 padding;
+ 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);
+
+ padding = *offset & (MALI_BLOCK_SIZE-1);
+
+ if (MALI_BLOCK_SIZE - padding < left)
+ {
+ current_mapping_size = MALI_BLOCK_SIZE - padding;
+ }
+ else
+ {
+ current_mapping_size = left;
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, phys_addr + padding, info->cpu_usage_adjust, current_mapping_size))
+ {
+ MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n"));
+ result = MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->start_offset, ret_allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0);
+
+ /* 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;
+ }
+
+ break;
+ }
+
+ *offset += current_mapping_size;
+ left -= current_mapping_size;
+ ret_allocation->mapping_length += current_mapping_size;
+ }
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+
+ if (last_allocated)
+ {
+ if (left) result = MALI_MEM_ALLOC_PARTIAL;
+ else result = MALI_MEM_ALLOC_FINISHED;
+
+ /* Record all the information about this allocation */
+ ret_allocation->last_allocated = last_allocated;
+ ret_allocation->engine = engine;
+ ret_allocation->descriptor = descriptor;
+
+ alloc_info->ctx = info;
+ alloc_info->handle = ret_allocation;
+ alloc_info->release = block_allocator_release;
+ }
+ else
+ {
+ /* Free the allocation information - nothing to be passed back */
+ _mali_osk_free( ret_allocation );
+ }
+
+ return result;
+}
+
+static void block_allocator_release(void * ctx, void * handle)
+{
+ block_allocator * info;
+ block_info * block, * next;
+ block_allocator_allocation *allocation;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(handle);
+
+ info = (block_allocator*)ctx;
+ allocation = (block_allocator_allocation*)handle;
+ block = allocation->last_allocated;
+
+ MALI_DEBUG_ASSERT_POINTER(block);
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW))
+ {
+ MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n"));
+ return;
+ }
+
+ /* unmap */
+ mali_allocation_engine_unmap_physical(allocation->engine, allocation->descriptor, allocation->start_offset, allocation->mapping_length, (_mali_osk_mem_mapregion_flags_t)0);
+
+ 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;
+ }
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+
+ _mali_osk_free( allocation );
+}
+
+
+static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block)
+{
+ block_allocator * info;
+ mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(block);
+ info = (block_allocator*)ctx;
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ if (NULL != info->first_free)
+ {
+ void * virt;
+ u32 phys;
+ u32 size;
+ block_info * alloc;
+ alloc = info->first_free;
+
+ phys = get_phys(info, alloc); /* Does not modify info or alloc */
+ size = MALI_BLOCK_SIZE; /* Must be multiple of MALI_MMU_PAGE_SIZE */
+ virt = _mali_osk_mem_mapioregion( phys, size, "Mali block allocator page tables" );
+
+ /* Failure of _mali_osk_mem_mapioregion will result in MALI_MEM_ALLOC_INTERNAL_FAILURE,
+ * because it's unlikely another allocator will be able to map in. */
+
+ if ( NULL != virt )
+ {
+ block->ctx = info; /* same as incoming ctx */
+ block->handle = alloc;
+ block->phys_base = phys;
+ block->size = size;
+ block->release = block_allocator_release_page_table_block;
+ block->mapping = virt;
+
+ info->first_free = alloc->next;
+
+ alloc->next = NULL; /* Could potentially link many blocks together instead */
+
+ result = MALI_MEM_ALLOC_FINISHED;
+ }
+ }
+ else result = MALI_MEM_ALLOC_NONE;
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+
+ return result;
+}
+
+
+static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block )
+{
+ block_allocator * info;
+ block_info * block, * next;
+
+ MALI_DEBUG_ASSERT_POINTER( page_table_block );
+
+ info = (block_allocator*)page_table_block->ctx;
+ block = (block_info*)page_table_block->handle;
+
+ MALI_DEBUG_ASSERT_POINTER(info);
+ MALI_DEBUG_ASSERT_POINTER(block);
+
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW))
+ {
+ MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n"));
+ return;
+ }
+
+ /* Unmap all the physical memory at once */
+ _mali_osk_mem_unmapioregion( page_table_block->phys_base, page_table_block->size, page_table_block->mapping );
+
+ /** @note This loop handles the case where more than one block_info was linked.
+ * Probably unnecssary for page table block releasing. */
+ while (block)
+ {
+ next = block->next;
+
+ MALI_DEBUG_ASSERT(!((block < info->all_blocks) || (block > (info->all_blocks + info->num_blocks))));
+
+ block->next = info->first_free;
+ info->first_free = block;
+
+ block = next;
+ }
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+}
+
+static u32 block_allocator_stat(mali_physical_memory_allocator * allocator)
+{
+ block_allocator * info;
+ block_info *block;
+ u32 free_blocks = 0;
+
+ MALI_DEBUG_ASSERT_POINTER(allocator);
+
+ info = (block_allocator*)allocator->ctx;
+ block = info->first_free;
+
+ while(block)
+ {
+ free_blocks++;
+ block = block->next;
+ }
+ return (info->num_blocks - free_blocks) * MALI_BLOCK_SIZE;
+}
diff --git a/drivers/gpu/arm/mali/common/mali_block_allocator.h b/drivers/gpu/arm/mali/common/mali_block_allocator.h
new file mode 100644
index 00000000000..6c6f13eec34
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_block_allocator.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_BLOCK_ALLOCATOR_H__
+#define __MALI_BLOCK_ALLOCATOR_H__
+
+#include "mali_kernel_memory_engine.h"
+
+mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name);
+
+#endif /* __MALI_BLOCK_ALLOCATOR_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_cinstr_profiling_events_m200.h b/drivers/gpu/arm/mali/common/mali_cinstr_profiling_events_m200.h
new file mode 100644
index 00000000000..47f37636a93
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_cinstr_profiling_events_m200.h
@@ -0,0 +1,117 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms of
+ * such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _CINSTR_PROFILING_EVENTS_M200_H_
+#define _CINSTR_PROFILING_EVENTS_M200_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
+} 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
+ */
+typedef enum
+{
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0,
+ MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1,
+} 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,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT= 27,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC= 28,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP = 29,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE = 30,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL = 31,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS = 32,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE= 33,
+} 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,
+} cinstr_profiling_event_reason_single_gpu_t;
+
+#endif /*_CINSTR_PROFILING_EVENTS_M200_H_*/
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_GP2.c b/drivers/gpu/arm/mali/common/mali_kernel_GP2.c
new file mode 100644
index 00000000000..7ccdd8e2e57
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_GP2.c
@@ -0,0 +1,1500 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_subsystem.h"
+#include "regs/mali_gp_regs.h"
+#include "mali_kernel_rendercore.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.h"
+#endif
+#if defined(USING_MALI400_L2_CACHE)
+#include "mali_kernel_l2_cache.h"
+#endif
+#if USING_MMU
+#include "mali_kernel_mem_mmu.h" /* Needed for mali_kernel_mmu_force_bus_reset() */
+#endif
+
+#if defined(USING_MALI200)
+#define MALI_GP_SUBSYSTEM_NAME "MaliGP2"
+#define MALI_GP_CORE_TYPE _MALI_GP2
+#elif defined(USING_MALI400)
+#define MALI_GP_SUBSYSTEM_NAME "Mali-400 GP"
+#define MALI_GP_CORE_TYPE _MALI_400_GP
+#else
+#error "No supported mali core defined"
+#endif
+
+#define GET_JOB_EMBEDDED_PTR(job) (&((job)->embedded_core_job))
+#define GET_JOBGP2_PTR(job_extern) _MALI_OSK_CONTAINER_OF(job_extern, maligp_job, embedded_core_job)
+
+/* Initialized when this subsystem is initialized. This is determined by the
+ * position in subsystems[], and so the value used to initialize this is
+ * determined at compile time */
+static mali_kernel_subsystem_identifier mali_subsystem_gp_id = -1;
+
+static mali_core_renderunit * last_gp_core_cookie = NULL;
+
+/* Describing a maligp job settings */
+typedef struct maligp_job
+{
+ /* The general job struct common for all mali cores */
+ mali_core_job embedded_core_job;
+ _mali_uk_gp_start_job_s user_input;
+
+ u32 irq_status;
+ u32 status_reg_on_stop;
+ u32 perf_counter0;
+ u32 perf_counter1;
+ u32 vscl_stop_addr;
+ u32 plbcl_stop_addr;
+ u32 heap_current_addr;
+
+ /* The data we will return back to the user */
+ _mali_osk_notification_t *notification_obj;
+
+ int is_stalled_waiting_for_more_memory;
+
+ u32 active_mask;
+ /* progress checking */
+ u32 last_vscl;
+ u32 last_plbcl;
+ /* extended progress checking, only enabled when we can use one of the performance counters */
+ u32 have_extended_progress_checking;
+ u32 vertices;
+
+#if defined(USING_MALI400_L2_CACHE)
+ u32 perf_counter_l2_src0;
+ u32 perf_counter_l2_src1;
+ u32 perf_counter_l2_val0;
+ u32 perf_counter_l2_val1;
+#endif
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ u32 pid;
+ u32 tid;
+#endif
+} maligp_job;
+
+/*Functions Exposed to the General External System through
+ function pointers.*/
+
+static _mali_osk_errcode_t maligp_subsystem_startup(mali_kernel_subsystem_identifier id);
+#if USING_MMU
+static _mali_osk_errcode_t maligp_subsystem_mmu_connect(mali_kernel_subsystem_identifier id);
+#endif
+static void maligp_subsystem_terminate(mali_kernel_subsystem_identifier id);
+static _mali_osk_errcode_t maligp_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+static void maligp_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
+static _mali_osk_errcode_t maligp_subsystem_core_system_info_fill(_mali_system_info* info);
+static _mali_osk_errcode_t maligp_renderunit_create(_mali_osk_resource_t * resource);
+#if USING_MMU
+static void maligp_subsystem_broadcast_notification(mali_core_notification_message message, u32 data);
+#endif
+#if MALI_STATE_TRACKING
+u32 maligp_subsystem_dump_state(char *buf, u32 size);
+#endif
+
+/* Internal support functions */
+static _mali_osk_errcode_t maligp_core_version_legal( mali_core_renderunit *core );
+static void maligp_raw_reset( mali_core_renderunit *core);
+static void maligp_reset_hard(struct mali_core_renderunit * core);
+static void maligp_reset(mali_core_renderunit *core);
+static void maligp_initialize_registers_mgmt(mali_core_renderunit *core );
+
+#ifdef DEBUG
+static void maligp_print_regs(int debug_level, mali_core_renderunit *core);
+#endif
+
+/* Functions exposed to mali_core system through functionpointers
+ in the subsystem struct. */
+static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_core_renderunit * core);
+static u32 subsystem_maligp_irq_handler_upper_half(mali_core_renderunit * core);
+static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core);
+static _mali_osk_errcode_t subsystem_maligp_get_new_job_from_user(struct mali_core_session * session, void * argument);
+static _mali_osk_errcode_t subsystem_maligp_suspend_response(struct mali_core_session * session, void * argument);
+static void subsystem_maligp_return_job_to_user(mali_core_job * job, mali_subsystem_job_end_code end_status);
+static void subsystem_maligp_renderunit_delete(mali_core_renderunit * core);
+static void subsystem_maligp_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style );
+static void subsystem_maligp_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core);
+static _mali_osk_errcode_t subsystem_maligp_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core);
+static void subsystem_maligp_renderunit_stop_bus(struct mali_core_renderunit* core);
+
+/* Variables */
+static register_address_and_value default_mgmt_regs[] =
+{
+ { MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED }
+};
+
+
+/* This will be one of the subsystems in the array of subsystems:
+ static struct mali_kernel_subsystem * subsystems[];
+ found in file: mali_kernel_core.c
+*/
+
+struct mali_kernel_subsystem mali_subsystem_gp2=
+{
+ maligp_subsystem_startup, /* startup */
+ maligp_subsystem_terminate, /* shutdown */
+#if USING_MMU
+ maligp_subsystem_mmu_connect, /* load_complete */
+#else
+ NULL,
+#endif
+ maligp_subsystem_core_system_info_fill, /* system_info_fill */
+ maligp_subsystem_session_begin, /* session_begin */
+ maligp_subsystem_session_end, /* session_end */
+#if USING_MMU
+ maligp_subsystem_broadcast_notification, /* broadcast_notification */
+#else
+ NULL,
+#endif
+#if MALI_STATE_TRACKING
+ maligp_subsystem_dump_state, /* dump_state */
+#endif
+} ;
+
+static mali_core_subsystem subsystem_maligp ;
+
+static _mali_osk_errcode_t maligp_subsystem_startup(mali_kernel_subsystem_identifier id)
+{
+ mali_core_subsystem * subsystem;
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_startup\n") ) ;
+
+ mali_subsystem_gp_id = id;
+
+ /* All values get 0 as default */
+ _mali_osk_memset(&subsystem_maligp, 0, sizeof(*subsystem));
+
+ subsystem = &subsystem_maligp;
+ subsystem->start_job = &subsystem_maligp_start_job;
+ subsystem->irq_handler_upper_half = &subsystem_maligp_irq_handler_upper_half;
+ subsystem->irq_handler_bottom_half = &subsystem_maligp_irq_handler_bottom_half;
+ subsystem->get_new_job_from_user = &subsystem_maligp_get_new_job_from_user;
+ subsystem->suspend_response = &subsystem_maligp_suspend_response;
+ subsystem->return_job_to_user = &subsystem_maligp_return_job_to_user;
+ subsystem->renderunit_delete = &subsystem_maligp_renderunit_delete;
+ subsystem->reset_core = &subsystem_maligp_renderunit_reset_core;
+ subsystem->stop_bus = &subsystem_maligp_renderunit_stop_bus;
+ subsystem->probe_core_irq_trigger = &subsystem_maligp_renderunit_probe_core_irq_trigger;
+ subsystem->probe_core_irq_acknowledge = &subsystem_maligp_renderunit_probe_core_irq_finished;
+
+ /* Setting variables in the general core part of the subsystem.*/
+ subsystem->name = MALI_GP_SUBSYSTEM_NAME;
+ subsystem->core_type = MALI_GP_CORE_TYPE;
+ subsystem->id = id;
+
+ /* Initiates the rest of the general core part of the subsystem */
+ MALI_CHECK_NO_ERROR(mali_core_subsystem_init( subsystem ));
+
+ /* This will register the function for adding MALIGP2 cores to the subsystem */
+#if defined(USING_MALI200)
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALIGP2, maligp_renderunit_create));
+#endif
+#if defined(USING_MALI400)
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALI400GP, maligp_renderunit_create));
+#endif
+
+ MALI_DEBUG_PRINT(6, ("Mali GP: maligp_subsystem_startup\n") ) ;
+
+ MALI_SUCCESS;
+}
+
+#if USING_MMU
+static _mali_osk_errcode_t maligp_subsystem_mmu_connect(mali_kernel_subsystem_identifier id)
+{
+ mali_core_subsystem_attach_mmu(&subsystem_maligp);
+ MALI_SUCCESS; /* OK */
+}
+#endif
+
+static void maligp_subsystem_terminate(mali_kernel_subsystem_identifier id)
+{
+ MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_terminate\n") ) ;
+ mali_core_subsystem_cleanup(&subsystem_maligp);
+}
+
+static _mali_osk_errcode_t maligp_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
+{
+ mali_core_session * session;
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_session_begin\n") ) ;
+ MALI_CHECK_NON_NULL(session = _mali_osk_malloc( sizeof(*session) ), _MALI_OSK_ERR_FAULT);
+
+ _mali_osk_memset(session, 0, sizeof(*session) );
+ *slot = (mali_kernel_subsystem_session_slot)session;
+
+ session->subsystem = &subsystem_maligp;
+
+ session->notification_queue = queue;
+
+#if USING_MMU
+ session->mmu_session = mali_session_data;
+#endif
+
+ mali_core_session_begin(session);
+
+ MALI_DEBUG_PRINT(6, ("Mali GP: maligp_subsystem_session_begin\n") ) ;
+
+ MALI_SUCCESS;
+}
+
+static void maligp_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
+{
+ mali_core_session * session;
+ /** @note mali_session_data not needed here */
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: maligp_subsystem_session_end\n") ) ;
+ if ( NULL==slot || NULL==*slot)
+ {
+ MALI_PRINT_ERROR(("Input slot==NULL"));
+ return;
+ }
+ session = (mali_core_session *)*slot;
+ mali_core_session_close(session);
+
+ _mali_osk_free(session);
+ *slot = NULL;
+
+ MALI_DEBUG_PRINT(6, ("Mali GP: maligp_subsystem_session_end\n") ) ;
+}
+
+/**
+ * We fill in info about all the cores we have
+ * @param info Pointer to system info struct to update
+ * @return _MALI_OSK_ERR_OK on success, or another _mali_osk_errcode_t for errors.
+ */
+static _mali_osk_errcode_t maligp_subsystem_core_system_info_fill(_mali_system_info* info)
+{
+ return mali_core_subsystem_system_info_fill(&subsystem_maligp, info);
+}
+
+static _mali_osk_errcode_t maligp_renderunit_create(_mali_osk_resource_t * resource)
+{
+ mali_core_renderunit *core;
+ int err;
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: maligp_renderunit_create\n") ) ;
+ /* Checking that the resource settings are correct */
+#if defined(USING_MALI200)
+ if(MALIGP2 != resource->type)
+ {
+ MALI_PRINT_ERROR(("Can not register this resource as a " MALI_GP_SUBSYSTEM_NAME " core."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#elif defined(USING_MALI400)
+ if(MALI400GP != resource->type)
+ {
+ MALI_PRINT_ERROR(("Can not register this resource as a " MALI_GP_SUBSYSTEM_NAME " core."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#endif
+ if ( 0 != resource->size )
+ {
+ MALI_PRINT_ERROR(("Memory size set to " MALI_GP_SUBSYSTEM_NAME " core should be zero."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ if ( NULL == resource->description )
+ {
+ MALI_PRINT_ERROR(("A " MALI_GP_SUBSYSTEM_NAME " core needs a unique description field"));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Create a new core object */
+ core = (mali_core_renderunit*) _mali_osk_malloc(sizeof(*core));
+ if ( NULL == core )
+ {
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Variables set to be able to open and register the core */
+ core->subsystem = &subsystem_maligp ;
+ core->registers_base_addr = resource->base ;
+ core->size = MALIGP2_REGISTER_ADDRESS_SPACE_SIZE ;
+ core->description = resource->description;
+ core->irq_nr = resource->irq ;
+#if USING_MMU
+ core->mmu_id = resource->mmu_id;
+ core->mmu = NULL;
+#endif
+#if USING_MALI_PMM
+ /* Set up core's PMM id */
+ core->pmm_id = MALI_PMM_CORE_GP;
+#endif
+
+ err = mali_core_renderunit_init( core );
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to initialize renderunit\n"));
+ goto exit_on_error0;
+ }
+
+ /* Map the new core object, setting: core->registers_mapped */
+ err = mali_core_renderunit_map_registers(core);
+ if (_MALI_OSK_ERR_OK != err) goto exit_on_error1;
+
+ /* Check that the register mapping of the core works.
+ Return 0 if maligp core is present and accessible. */
+ if (mali_benchmark) {
+ core->core_version = MALI_GP_PRODUCT_ID << 16;
+ } else {
+ core->core_version = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VERSION);
+ }
+
+ err = maligp_core_version_legal(core);
+ if (_MALI_OSK_ERR_OK != err) goto exit_on_error2;
+
+ /* Reset the core. Put the core into a state where it can start to render. */
+ maligp_reset(core);
+
+ /* Registering IRQ, init the work_queue_irq_handle */
+ /* Adding this core as an available renderunit in the subsystem. */
+ err = mali_core_subsystem_register_renderunit(&subsystem_maligp, core);
+ if (_MALI_OSK_ERR_OK != err) goto exit_on_error2;
+
+#ifdef DEBUG
+ MALI_DEBUG_PRINT(4, ("Mali GP: Initial Register settings:\n"));
+ maligp_print_regs(4, core);
+#endif
+
+ MALI_DEBUG_PRINT(6, ("Mali GP: maligp_renderunit_create\n") ) ;
+
+ MALI_SUCCESS;
+
+exit_on_error2:
+ mali_core_renderunit_unmap_registers(core);
+exit_on_error1:
+ mali_core_renderunit_term(core);
+exit_on_error0:
+ _mali_osk_free( core ) ;
+ MALI_PRINT_ERROR(("Renderunit NOT created."));
+ MALI_ERROR((_mali_osk_errcode_t)err);
+}
+
+#if USING_MMU
+/* Used currently only for signalling when MMU has a pagefault */
+static void maligp_subsystem_broadcast_notification(mali_core_notification_message message, u32 data)
+{
+ mali_core_subsystem_broadcast_notification(&subsystem_maligp, message, data);
+}
+#endif
+
+#ifdef DEBUG
+static void maligp_print_regs(int debug_level, mali_core_renderunit *core)
+{
+ if (debug_level <= mali_debug_level)
+ {
+ MALI_DEBUG_PRINT(1, (" VS 0x%08X 0x%08X, PLBU 0x%08X 0x%08X ALLOC 0x%08X 0x%08X\n",
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_END_ADDR),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBUCL_END_ADDR),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR))
+ );
+ MALI_DEBUG_PRINT(1, (" IntRaw 0x%08X IntMask 0x%08X, Status 0x%02X Ver: 0x%08X \n",
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_MASK),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_STATUS),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VERSION)));
+
+ MALI_DEBUG_PRINT(1, (" PERF_CNT Enbl:%d %d Src: %02d %02d VAL: 0x%08X 0x%08X\n",
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE)));
+
+ MALI_DEBUG_PRINT(1, (" VS_START 0x%08X PLBU_START 0x%08X AXI_ERR 0x%08X\n",
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR_READ),
+ mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBCL_START_ADDR_READ),
+ mali_core_renderunit_register_read(core, MALIGP2_CONTR_AXI_BUS_ERROR_STAT)));
+ }
+}
+#endif
+
+static _mali_osk_errcode_t maligp_core_version_legal( mali_core_renderunit *core )
+{
+ u32 mali_type;
+
+ mali_type = core->core_version >> 16;
+
+#if defined(USING_MALI400)
+ if ( MALI400_GP_PRODUCT_ID != mali_type && MALI300_GP_PRODUCT_ID != mali_type )
+#else
+ if ( MALI_GP_PRODUCT_ID != mali_type )
+#endif
+ {
+ MALI_PRINT_ERROR(("Error: reading this from maligp version register: 0x%x\n", core->core_version));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ MALI_DEBUG_PRINT(3, ("Mali GP: core_version_legal: Reads correct mali version: %d\n", core->core_version )) ;
+ MALI_SUCCESS;
+}
+
+static void subsystem_maligp_renderunit_stop_bus(struct mali_core_renderunit* core)
+{
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
+}
+
+static void maligp_reset( mali_core_renderunit *core )
+{
+ if (!mali_benchmark) {
+ maligp_raw_reset(core);
+ maligp_initialize_registers_mgmt(core);
+ }
+}
+
+
+static void maligp_reset_hard( mali_core_renderunit *core )
+{
+ const int reset_finished_loop_count = 15;
+ 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_core_renderunit_register_write(core, reset_wait_target_register, reset_invalid_value);
+
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET);
+
+ for (i = 0; i < reset_finished_loop_count; i++)
+ {
+ mali_core_renderunit_register_write(core, reset_wait_target_register, reset_check_value);
+ if (reset_check_value == mali_core_renderunit_register_read(core, reset_wait_target_register))
+ {
+ MALI_DEBUG_PRINT(5, ("Reset loop exiting after %d iterations\n", i));
+ break;
+ }
+ }
+
+ if (i == reset_finished_loop_count)
+ {
+ MALI_DEBUG_PRINT(1, ("The reset loop didn't work\n"));
+ }
+
+ mali_core_renderunit_register_write(core, reset_wait_target_register, reset_default_value); /* set it back to the default */
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+
+
+}
+
+static void maligp_raw_reset( mali_core_renderunit *core )
+{
+ int i;
+ const int request_loop_count = 20;
+
+ MALI_DEBUG_PRINT(4, ("Mali GP: maligp_raw_reset: %s\n", core->description)) ;
+ if (mali_benchmark) return;
+
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+
+#if defined(USING_MALI200)
+
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED) break;
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ MALI_DEBUG_PRINT_IF(1, request_loop_count == i, ("Mali GP: Bus was never stopped during core reset\n"));
+
+ if (request_loop_count==i)
+ {
+ /* Could not stop bus connections from core, probably because some of the already pending
+ bus request has had a page fault, and therefore can not complete before the MMU does PageFault
+ handling. This can be treated as a heavier reset function - which unfortunately reset all
+ the cores on this MMU in addition to the MMU itself */
+#if USING_MMU
+ if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
+ {
+ MALI_DEBUG_PRINT(1, ("Mali GP: Forcing MMU bus reset\n"));
+ mali_kernel_mmu_force_bus_reset(core->mmu);
+ return;
+ }
+#endif
+ MALI_PRINT(("A MMU reset did not allow GP to stop its bus, system failure, unable to recover\n"));
+ return;
+ }
+
+ /* the bus was stopped OK, complete the reset */
+ /* use the hard reset routine to do the actual reset */
+ maligp_reset_hard(core);
+
+#elif defined(USING_MALI400)
+
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & /*Bitwise OR*/
+ MALI400GP_REG_VAL_IRQ_RESET_COMPLETED) break;
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if ( request_loop_count==i )
+ {
+#if USING_MMU
+ /* Could not stop bus connections from core, probably because some of the already pending
+ bus request has had a page fault, and therefore can not complete before the MMU does PageFault
+ handling. This can be treated as a heavier reset function - which unfortunately reset all
+ the cores on this MMU in addition to the MMU itself */
+ if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
+ {
+ MALI_DEBUG_PRINT(1, ("Mali GP: Forcing Bus reset\n"));
+ mali_kernel_mmu_force_bus_reset(core->mmu);
+ return;
+ }
+#endif
+ MALI_PRINT(("A MMU reset did not allow GP to stop its bus, system failure, unable to recover\n"));
+ }
+ else
+ {
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+ }
+
+#else
+#error "no supported mali core defined"
+#endif
+}
+
+/* Sets the registers on maligp according to the const default_mgmt_regs array. */
+static void maligp_initialize_registers_mgmt(mali_core_renderunit *core )
+{
+ int i;
+
+ MALI_DEBUG_PRINT(6, ("Mali GP: maligp_initialize_registers_mgmt: %s\n", core->description)) ;
+ for(i=0 ; i< (sizeof(default_mgmt_regs)/sizeof(*default_mgmt_regs)) ; ++i)
+ {
+ mali_core_renderunit_register_write_relaxed(core, default_mgmt_regs[i].address, default_mgmt_regs[i].value);
+ }
+ _mali_osk_write_mem_barrier();
+}
+
+
+/* Start this job on this core. Return MALI_TRUE if the job was started. */
+static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_core_renderunit * core)
+{
+ maligp_job *jobgp;
+ u32 startcmd;
+ /* The local extended version of the general structs */
+ jobgp = _MALI_OSK_CONTAINER_OF(job, maligp_job, embedded_core_job);
+
+ startcmd = 0;
+ if ( jobgp->user_input.frame_registers[0] != jobgp->user_input.frame_registers[1] )
+ {
+ startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS;
+ }
+
+ if ( jobgp->user_input.frame_registers[2] != jobgp->user_input.frame_registers[3] )
+ {
+ startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU;
+ }
+
+ if(0 == startcmd)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali GP: Job: 0x%08x WILL NOT START SINCE JOB HAS ILLEGAL ADDRESSES\n",
+ (u32)jobgp->user_input.user_job_ptr));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+
+#ifdef DEBUG
+ MALI_DEBUG_PRINT(4, ("Mali GP: Registers Start\n"));
+ maligp_print_regs(4, core);
+#endif
+
+
+ mali_core_renderunit_register_write_array(
+ core,
+ MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR,
+ &(jobgp->user_input.frame_registers[0]),
+ sizeof(jobgp->user_input.frame_registers)/sizeof(jobgp->user_input.frame_registers[0]));
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ /*
+ * If the hardware counters are not turned on, ask the external profiler
+ * if they should be.
+ */
+ if (jobgp->user_input.perf_counter_flag == 0)
+ {
+ mali_bool src0_enabled = _mali_osk_profiling_query_hw_counter(COUNTER_VP_C0,
+ &(jobgp->user_input.perf_counter_src0));
+ mali_bool src1_enabled = _mali_osk_profiling_query_hw_counter(COUNTER_VP_C1,
+ &(jobgp->user_input.perf_counter_src1));
+
+ if (src0_enabled == MALI_TRUE)
+ {
+ jobgp->user_input.perf_counter_flag |=
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE;
+ }
+
+ if (src1_enabled == MALI_TRUE)
+ {
+ jobgp->user_input.perf_counter_flag |=
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE;
+ }
+ }
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+
+ /* This selects which performance counters we are reading */
+ if ( 0 != jobgp->user_input.perf_counter_flag )
+ {
+ if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
+ {
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC,
+ jobgp->user_input.perf_counter_src0);
+
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE,
+ MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+
+ if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
+ {
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC,
+ jobgp->user_input.perf_counter_src1);
+
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE,
+ MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+
+#if defined(USING_MALI400_L2_CACHE)
+ if ( jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
+ {
+ int force_reset = ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET ) ? 1 : 0;
+ u32 src0 = 0;
+ u32 src1 = 0;
+
+ if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE )
+ {
+ src0 = jobgp->user_input.perf_counter_l2_src0;
+ }
+ if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE )
+ {
+ src1 = jobgp->user_input.perf_counter_l2_src1;
+ }
+
+ mali_kernel_l2_cache_set_perf_counters(src0, src1, force_reset); /* will activate and possibly reset counters */
+
+ /* Now, retrieve the current values, so we can substract them when the job has completed */
+ mali_kernel_l2_cache_get_perf_counters(&jobgp->perf_counter_l2_src0,
+ &jobgp->perf_counter_l2_val0,
+ &jobgp->perf_counter_l2_src1,
+ &jobgp->perf_counter_l2_val1);
+ }
+#endif
+ }
+
+ if ( 0 == (jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))
+ {
+ /* extended progress checking can be enabled */
+
+ jobgp->have_extended_progress_checking = 1;
+
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC,
+ MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED
+ );
+
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE,
+ MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+
+ subsystem_flush_mapped_mem_cache();
+
+ MALI_DEBUG_PRINT(4, ("Mali GP: STARTING GP WITH CMD: 0x%x\n", startcmd));
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_started);
+#endif
+
+ /* This is the command that starts the Core */
+ mali_core_renderunit_register_write(core,
+ MALIGP2_REG_ADDR_MGMT_CMD,
+ startcmd);
+ _mali_osk_write_mem_barrier();
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+ jobgp->user_input.frame_builder_id, jobgp->user_input.flush_id, 0, 0, 0);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), jobgp->pid, jobgp->tid, 0, 0, 0);
+#endif
+
+ MALI_SUCCESS;
+}
+
+/* Check if given core has an interrupt pending. Return MALI_TRUE and set mask to 0 if pending */
+
+static u32 subsystem_maligp_irq_handler_upper_half(mali_core_renderunit * core)
+{
+ u32 irq_readout;
+
+ if (mali_benchmark) {
+ return (core->current_job ? 1 : 0); /* simulate irq is pending when a job is pending */
+ }
+
+ irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+
+ if ( MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout )
+ {
+ /* Mask out all IRQs from this core until IRQ is handled */
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
+#endif
+
+ /* We do need to handle this in a bottom half, return 1 */
+ return 1;
+ }
+ return 0;
+}
+
+/* This function should check if the interrupt indicates that job was finished.
+If so it should update the job-struct, reset the core registers, and return MALI_TRUE, .
+If the job is still working after this function it should return MALI_FALSE.
+The function must also enable the bits in the interrupt mask for the core.
+Called by the bottom half interrupt function. */
+static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core)
+{
+ mali_core_job * job;
+ maligp_job * jobgp;
+ u32 irq_readout;
+ u32 core_status;
+ u32 vscl;
+ u32 plbcl;
+
+ job = core->current_job;
+
+ if (mali_benchmark) {
+ MALI_DEBUG_PRINT(3, ("MaliGP: Job: Benchmark\n") );
+ irq_readout = MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST;
+ core_status = 0;
+ } else {
+ irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
+ core_status = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_STATUS);
+ }
+
+ if (NULL == job)
+ {
+ MALI_DEBUG_ASSERT(CORE_IDLE==core->state);
+ if ( 0 != irq_readout )
+ {
+ MALI_PRINT_ERROR(("Interrupt from a core not running a job. IRQ: 0x%04x Status: 0x%04x", irq_readout, core_status));
+ }
+ return JOB_STATUS_END_UNKNOWN_ERR;
+ }
+ MALI_DEBUG_ASSERT(CORE_IDLE!=core->state);
+
+ jobgp = GET_JOBGP2_PTR(job);
+
+ jobgp->heap_current_addr = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR);
+
+ vscl = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR);
+ plbcl = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBUCL_START_ADDR);
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: Job: 0x%08x IRQ RECEIVED Rawstat: 0x%x Status: 0x%x\n",
+ (u32)jobgp->user_input.user_job_ptr, irq_readout , core_status )) ;
+
+ jobgp->irq_status |= irq_readout;
+ jobgp->status_reg_on_stop = core_status;
+
+ if ( 0 != jobgp->is_stalled_waiting_for_more_memory )
+ {
+ /* Readback the performance counters */
+ if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
+ {
+ jobgp->perf_counter0 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+ jobgp->perf_counter1 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ /* Report the hardware counter values to the external profiler */
+ _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, jobgp->perf_counter0);
+ _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, jobgp->perf_counter1);
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+ }
+
+#if defined(USING_MALI400_L2_CACHE)
+ if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
+ {
+ u32 src0;
+ u32 val0;
+ u32 src1;
+ u32 val1;
+ mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);
+
+ if (jobgp->perf_counter_l2_src0 == src0)
+ {
+ jobgp->perf_counter_l2_val0 = val0 - jobgp->perf_counter_l2_val0;
+ }
+ else
+ {
+ jobgp->perf_counter_l2_val0 = 0;
+ }
+
+ if (jobgp->perf_counter_l2_src1 == src1)
+ {
+ jobgp->perf_counter_l2_val1 = val1 - jobgp->perf_counter_l2_val1;
+ }
+ else
+ {
+ jobgp->perf_counter_l2_val1 = 0;
+ }
+ }
+#endif
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
+#endif
+
+ MALI_DEBUG_PRINT(2, ("Mali GP: Job aborted - userspace would not provide more heap memory.\n"));
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+ return JOB_STATUS_END_OOM; /* Core is ready for more jobs.*/
+ }
+ /* finished ? */
+ else if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
+ {
+#ifdef DEBUG
+ MALI_DEBUG_PRINT(4, ("Mali GP: Registers On job end:\n"));
+ maligp_print_regs(4, core);
+#endif
+ MALI_DEBUG_PRINT_IF(5, irq_readout & 0x04, ("OOM when done, ignoring (reg.current = 0x%x, reg.end = 0x%x)\n",
+ (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR),
+ (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR))
+ );
+
+
+ if (0 != jobgp->user_input.perf_counter_flag )
+ {
+ /* Readback the performance counters */
+ if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
+ {
+ jobgp->perf_counter0 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+ jobgp->perf_counter1 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ /* Report the hardware counter values to the external profiler */
+ _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, jobgp->perf_counter0);
+ _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, jobgp->perf_counter1);
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+ }
+
+#if defined(USING_MALI400_L2_CACHE)
+ if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
+ {
+ u32 src0;
+ u32 val0;
+ u32 src1;
+ u32 val1;
+ mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);
+
+ if (jobgp->perf_counter_l2_src0 == src0)
+ {
+ jobgp->perf_counter_l2_val0 = val0 - jobgp->perf_counter_l2_val0;
+ }
+ else
+ {
+ jobgp->perf_counter_l2_val0 = 0;
+ }
+
+ if (jobgp->perf_counter_l2_src1 == src1)
+ {
+ jobgp->perf_counter_l2_val1 = val1 - jobgp->perf_counter_l2_val1;
+ }
+ else
+ {
+ jobgp->perf_counter_l2_val1 = 0;
+ }
+ }
+#endif
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number),
+ jobgp->perf_counter0, jobgp->perf_counter1,
+ jobgp->user_input.perf_counter_src0 | (jobgp->user_input.perf_counter_src1 << 8)
+#if defined(USING_MALI400_L2_CACHE)
+ | (jobgp->user_input.perf_counter_l2_src0 << 16) | (jobgp->user_input.perf_counter_l2_src1 << 24),
+ jobgp->perf_counter_l2_val0,
+ jobgp->perf_counter_l2_val1
+#else
+ ,0, 0
+#endif
+ );
+#endif
+
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+ return JOB_STATUS_END_SUCCESS; /* core idle */
+ }
+ /* sw watchdog timeout handling or time to do hang checking ? */
+ else if (
+ (CORE_WATCHDOG_TIMEOUT == core->state) ||
+ (
+ (CORE_HANG_CHECK_TIMEOUT == core->state) &&
+ (
+ (jobgp->have_extended_progress_checking ? (mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE) == jobgp->vertices) : 1/*TRUE*/) &&
+ ((core_status & MALIGP2_REG_VAL_STATUS_VS_ACTIVE) ? (vscl == jobgp->last_vscl) : 1/*TRUE*/) &&
+ ((core_status & MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) ? (plbcl == jobgp->last_plbcl) : 1/*TRUE*/)
+ )
+ )
+ )
+ {
+ /* no progress detected, killed by the watchdog */
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
+#endif
+
+ MALI_DEBUG_PRINT(1, ("Mali GP: SW-Timeout. Regs:\n"));
+ if (core_status & MALIGP2_REG_VAL_STATUS_VS_ACTIVE) MALI_DEBUG_PRINT(1, ("vscl current = 0x%x last = 0x%x\n", (void*)vscl, (void*)jobgp->last_vscl));
+ if (core_status & MALIGP2_REG_VAL_STATUS_PLBU_ACTIVE) MALI_DEBUG_PRINT(1, ("plbcl current = 0x%x last = 0x%x\n", (void*)plbcl, (void*)jobgp->last_plbcl));
+ if (jobgp->have_extended_progress_checking) MALI_DEBUG_PRINT(1, ("vertices processed = %d, last = %d\n", mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE),
+ jobgp->vertices));
+#ifdef DEBUG
+ maligp_print_regs(2, core);
+#endif
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+
+ return JOB_STATUS_END_HANG;
+ }
+ /* if hang timeout checking was enabled and we detected progress, will be fall down to this check */
+ /* check for PLBU OOM before the hang check to avoid the race condition of the hw wd trigging while waiting for us to handle the OOM interrupt */
+ else if ( 0 != (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM))
+ {
+ mali_core_session *session;
+ _mali_osk_notification_t *notific;
+ _mali_uk_gp_job_suspended_s * suspended_job;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
+#endif
+
+ session = job->session;
+
+ MALI_DEBUG_PRINT(4, ("OOM, new heap requested by GP\n"));
+ MALI_DEBUG_PRINT(4, ("Status when OOM: current = 0x%x, end = 0x%x\n",
+ (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR),
+ (void*)mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR))
+ );
+
+ notific = _mali_osk_notification_create(
+
+ _MALI_NOTIFICATION_GP_STALLED,
+ sizeof( _mali_uk_gp_job_suspended_s )
+ );
+ if ( NULL == notific)
+ {
+ MALI_PRINT_ERROR( ("Mali GP: Could not get notification object\n")) ;
+ return JOB_STATUS_END_OOM; /* Core is ready for more jobs.*/
+ }
+
+ core->state = CORE_WORKING;
+ jobgp->is_stalled_waiting_for_more_memory = 1;
+ suspended_job = (_mali_uk_gp_job_suspended_s *)notific->result_buffer; /* this is ok - result_buffer was malloc'd */
+
+ suspended_job->user_job_ptr = jobgp->user_input.user_job_ptr;
+ suspended_job->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY ;
+ suspended_job->cookie = (u32) core;
+ last_gp_core_cookie = core;
+
+ _mali_osk_notification_queue_send( session->notification_queue, notific);
+
+#ifdef DEBUG
+ maligp_print_regs(4, core);
+#endif
+
+ /* stop all active timers */
+ _mali_osk_timer_del( core->timer);
+ _mali_osk_timer_del( core->timer_hang_detection);
+ MALI_DEBUG_PRINT(4, ("Mali GP: PLBU heap empty, sending memory request to userspace\n"));
+ /* save to watchdog_jiffies what was remaining WD timeout value when OOM was triggered */
+ job->watchdog_jiffies = (long)job->watchdog_jiffies - (long)_mali_osk_time_tickcount();
+ /* reuse core->timer as the userspace response timeout handler */
+ _mali_osk_timer_add( core->timer, _mali_osk_time_mstoticks(1000) ); /* wait max 1 sec for userspace to respond */
+ return JOB_STATUS_CONTINUE_RUN; /* The core is NOT available for new jobs. */
+ }
+ /* hw watchdog is reporting a new hang or an existing progress-during-hang check passed? */
+ else if ((CORE_HANG_CHECK_TIMEOUT == core->state) || (irq_readout & jobgp->active_mask & MALIGP2_REG_VAL_IRQ_HANG))
+ {
+ /* check interval in ms */
+ u32 timeout = mali_core_hang_check_timeout_get();
+ MALI_DEBUG_PRINT(3, ("Mali GP: HW/SW Watchdog triggered, checking for progress in %d ms\n", timeout));
+ core->state = CORE_WORKING;
+
+ /* save state for the progress checking */
+ jobgp->last_vscl = vscl;
+ jobgp->last_plbcl = plbcl;
+ if (jobgp->have_extended_progress_checking)
+ {
+ jobgp->vertices = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+ }
+ /* hw watchdog triggered, set up a progress checker every HANGCHECK ms */
+ _mali_osk_timer_add( core->timer_hang_detection, _mali_osk_time_mstoticks(timeout));
+ jobgp->active_mask &= ~MALIGP2_REG_VAL_IRQ_HANG; /* ignore the hw watchdog from now on */
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask);
+ return JOB_STATUS_CONTINUE_RUN; /* not finihsed */ }
+ /* no errors, but still working */
+ else if ( ( 0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ERROR)) &&
+ ( 0 != (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE ))
+ )
+ {
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask);
+ return JOB_STATUS_CONTINUE_RUN;
+ }
+ /* Else there must be some error */
+ else
+ {
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */
+#endif
+
+ MALI_DEBUG_PRINT(1, ("Mali GP: Core crashed? *IRQ: 0x%x Status: 0x%x\n", irq_readout, core_status ));
+ #ifdef DEBUG
+ MALI_DEBUG_PRINT(1, ("Mali GP: Registers Before reset:\n"));
+ maligp_print_regs(1, core);
+ #endif
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+ return JOB_STATUS_END_UNKNOWN_ERR;
+ }
+}
+
+
+/* This function is called from the ioctl function and should return a mali_core_job pointer
+to a created mali_core_job object with the data given from userspace */
+static _mali_osk_errcode_t subsystem_maligp_get_new_job_from_user(struct mali_core_session * session, void * argument)
+{
+ maligp_job *jobgp;
+ mali_core_job *job = NULL;
+ mali_core_job *previous_replaced_job;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_uk_gp_start_job_s * user_ptr_job_input;
+
+ user_ptr_job_input = (_mali_uk_gp_start_job_s *)argument;
+
+ MALI_CHECK_NON_NULL(jobgp = (maligp_job *) _mali_osk_calloc(1, sizeof(maligp_job)), _MALI_OSK_ERR_FAULT);
+
+ /* Copy the job data from the U/K interface */
+ if ( NULL == _mali_osk_memcpy(&jobgp->user_input, user_ptr_job_input, sizeof(_mali_uk_gp_start_job_s) ) )
+ {
+ MALI_PRINT_ERROR( ("Mali GP: Could not copy data from U/K interface.\n")) ;
+ err = _MALI_OSK_ERR_FAULT;
+ goto function_exit;
+ }
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: subsystem_maligp_get_new_job_from_user 0x%x\n", (void*)jobgp->user_input.user_job_ptr));
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: Job Regs: 0x%08X 0x%08X, 0x%08X 0x%08X 0x%08X 0x%08X\n",
+ jobgp->user_input.frame_registers[0],
+ jobgp->user_input.frame_registers[1],
+ jobgp->user_input.frame_registers[2],
+ jobgp->user_input.frame_registers[3],
+ jobgp->user_input.frame_registers[4],
+ jobgp->user_input.frame_registers[5]) );
+
+
+ job = GET_JOB_EMBEDDED_PTR(jobgp);
+
+ job->session = session;
+ job->flags = MALI_UK_START_JOB_FLAG_DEFAULT; /* Current flags only make sence for PP jobs */
+ job_priority_set(job, jobgp->user_input.priority);
+ job_watchdog_set(job, jobgp->user_input.watchdog_msecs );
+ jobgp->heap_current_addr = jobgp->user_input.frame_registers[4];
+
+ job->abort_id = jobgp->user_input.abort_id;
+
+ jobgp->is_stalled_waiting_for_more_memory = 0;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ jobgp->pid = _mali_osk_get_pid();
+ jobgp->tid = _mali_osk_get_tid();
+#endif
+
+ if (mali_job_queue_full(session))
+ {
+ /* Cause jobgp to free: */
+ user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
+ goto function_exit;
+ }
+
+ /* We now know that we have a job, and a slot to put it in */
+
+ jobgp->active_mask = MALIGP2_REG_VAL_IRQ_MASK_USED;
+
+ /* Allocating User Return Data */
+ jobgp->notification_obj = _mali_osk_notification_create(
+ _MALI_NOTIFICATION_GP_FINISHED,
+ sizeof(_mali_uk_gp_job_finished_s) );
+
+ if ( NULL == jobgp->notification_obj )
+ {
+ MALI_PRINT_ERROR( ("Mali GP: Could not get notification_obj.\n")) ;
+ err = _MALI_OSK_ERR_NOMEM;
+ goto function_exit;
+ }
+
+ _MALI_OSK_INIT_LIST_HEAD( &(job->list) ) ;
+
+ MALI_DEBUG_PRINT(4, ("Mali GP: Job: 0x%08x INPUT from user.\n", (u32)jobgp->user_input.user_job_ptr)) ;
+
+ /* This should not happen since we have the checking of priority above */
+ err = mali_core_session_add_job(session, job, &previous_replaced_job);
+ if ( _MALI_OSK_ERR_OK != err )
+ {
+ MALI_PRINT_ERROR( ("Mali GP: Internal error\n")) ;
+ /* Cause jobgp to free: */
+ user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
+ _mali_osk_notification_delete( jobgp->notification_obj );
+ goto function_exit;
+ }
+
+ /* If MALI_TRUE: This session had a job with lower priority which were removed.
+ This replaced job is given back to userspace. */
+ if ( NULL != previous_replaced_job )
+ {
+ maligp_job *previous_replaced_jobgp;
+
+ previous_replaced_jobgp = GET_JOBGP2_PTR(previous_replaced_job);
+
+ MALI_DEBUG_PRINT(4, ("Mali GP: Replacing job: 0x%08x\n", (u32)previous_replaced_jobgp->user_input.user_job_ptr)) ;
+
+ /* Copy to the input data (which also is output data) the
+ pointer to the job that were replaced, so that the userspace
+ driver can put this job in the front of its job-queue */
+ user_ptr_job_input->returned_user_job_ptr = previous_replaced_jobgp->user_input.user_job_ptr;
+
+ /** @note failure to 'copy to user' at this point must not free jobgp,
+ * and so no transaction rollback required in the U/K interface */
+
+ /* This does not cause jobgp to free: */
+ user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED;
+ MALI_DEBUG_PRINT(5, ("subsystem_maligp_get_new_job_from_user: Job added, prev returned\n")) ;
+ }
+ else
+ {
+ /* This does not cause jobgp to free: */
+ user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED;
+ MALI_DEBUG_PRINT(5, ("subsystem_maligp_get_new_job_from_user: Job added\n")) ;
+ }
+
+function_exit:
+ if ( _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE == user_ptr_job_input->status
+ || _MALI_OSK_ERR_OK != err )
+ {
+ _mali_osk_free(jobgp);
+ }
+#if MALI_STATE_TRACKING
+ if (_MALI_UK_START_JOB_STARTED==user_ptr_job_input->status)
+ {
+ if(job)
+ {
+ job->job_nr=_mali_osk_atomic_inc_return(&session->jobs_received);
+ }
+ }
+#endif
+
+ MALI_ERROR(err);
+}
+
+
+static _mali_osk_errcode_t subsystem_maligp_suspend_response(struct mali_core_session * session, void * argument)
+{
+ mali_core_renderunit *core;
+ maligp_job *jobgp;
+ mali_core_job *job;
+
+ _mali_uk_gp_suspend_response_s * suspend_response;
+
+ MALI_DEBUG_PRINT(5, ("subsystem_maligp_suspend_response\n"));
+
+ suspend_response = (_mali_uk_gp_suspend_response_s *)argument;
+
+ /* We read job data from User */
+ /* On a single mali_gp system we can only have one Stalled GP,
+ and therefore one stalled request with a cookie. This checks
+ that we get the correct cookie */
+ if ( last_gp_core_cookie != (mali_core_renderunit *)suspend_response->cookie )
+ {
+ MALI_DEBUG_PRINT(2, ("Mali GP: Got an illegal cookie from Userspace.\n")) ;
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ core = (mali_core_renderunit *)suspend_response->cookie;
+ last_gp_core_cookie = NULL;
+ job = core->current_job;
+ jobgp = GET_JOBGP2_PTR(job);
+
+ switch( suspend_response->code )
+ {
+ case _MALIGP_JOB_RESUME_WITH_NEW_HEAP :
+ MALI_DEBUG_PRINT(5, ("MALIGP_JOB_RESUME_WITH_NEW_HEAP jiffies: %li\n", _mali_osk_time_tickcount()));
+ MALI_DEBUG_PRINT(4, ("New Heap addr 0x%08x - 0x%08x\n", suspend_response->arguments[0], suspend_response->arguments[1]));
+
+ jobgp->is_stalled_waiting_for_more_memory = 0;
+ job->watchdog_jiffies += _mali_osk_time_tickcount(); /* convert to absolute time again */
+ _mali_osk_timer_mod( core->timer, job->watchdog_jiffies); /* update the timer */
+
+
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG));
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask);
+ mali_core_renderunit_register_write_relaxed(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, suspend_response->arguments[0]);
+ mali_core_renderunit_register_write_relaxed(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, suspend_response->arguments[1]);
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC);
+ _mali_osk_write_mem_barrier();
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0);
+#endif
+
+ MALI_DEBUG_PRINT(4, ("GP resumed with new heap\n"));
+
+ break;
+
+ case _MALIGP_JOB_ABORT:
+ MALI_DEBUG_PRINT(3, ("MALIGP_JOB_ABORT on heap extend request\n"));
+ _mali_osk_irq_schedulework( core->irq );
+ break;
+
+ default:
+ MALI_PRINT_ERROR(("Wrong Suspend response from userspace\n"));
+ }
+ MALI_SUCCESS;
+}
+
+/* This function is called from the ioctl function and should write the necessary data
+to userspace telling which job was finished and the status and debuginfo for this job.
+The function must also free and cleanup the input job object. */
+static void subsystem_maligp_return_job_to_user( mali_core_job * job, mali_subsystem_job_end_code end_status )
+{
+ maligp_job *jobgp;
+ _mali_uk_gp_job_finished_s * job_out;
+ _mali_uk_gp_start_job_s* job_input;
+ mali_core_session *session;
+
+
+ jobgp = _MALI_OSK_CONTAINER_OF(job, maligp_job, embedded_core_job);
+ job_out = (_mali_uk_gp_job_finished_s *)jobgp->notification_obj->result_buffer; /* OK - this should've been malloc'd */
+ job_input= &(jobgp->user_input);
+ session = job->session;
+
+ MALI_DEBUG_PRINT(5, ("Mali GP: Job: 0x%08x OUTPUT to user. Runtime: %d us, irq readout %x\n",
+ (u32)jobgp->user_input.user_job_ptr,
+ job->render_time_usecs,
+ jobgp->irq_status)) ;
+
+ _mali_osk_memset(job_out, 0 , sizeof(_mali_uk_gp_job_finished_s));
+
+ job_out->user_job_ptr = job_input->user_job_ptr;
+
+ switch( end_status )
+ {
+ case JOB_STATUS_CONTINUE_RUN:
+ case JOB_STATUS_END_SUCCESS:
+ case JOB_STATUS_END_OOM:
+ case JOB_STATUS_END_ABORT:
+ case JOB_STATUS_END_TIMEOUT_SW:
+ case JOB_STATUS_END_HANG:
+ case JOB_STATUS_END_SEG_FAULT:
+ case JOB_STATUS_END_ILLEGAL_JOB:
+ case JOB_STATUS_END_UNKNOWN_ERR:
+ case JOB_STATUS_END_SHUTDOWN:
+ case JOB_STATUS_END_SYSTEM_UNUSABLE:
+ job_out->status = (mali_subsystem_job_end_code) end_status;
+ break;
+ default:
+ job_out->status = JOB_STATUS_END_UNKNOWN_ERR ;
+ }
+
+ job_out->irq_status = jobgp->irq_status;
+ job_out->status_reg_on_stop = jobgp->status_reg_on_stop;
+ job_out->vscl_stop_addr = 0;
+ job_out->plbcl_stop_addr = 0;
+ job_out->heap_current_addr = jobgp->heap_current_addr;
+ job_out->perf_counter0 = jobgp->perf_counter0;
+ job_out->perf_counter1 = jobgp->perf_counter1;
+ job_out->perf_counter_src0 = jobgp->user_input.perf_counter_src0 ;
+ job_out->perf_counter_src1 = jobgp->user_input.perf_counter_src1 ;
+ job_out->render_time = job->render_time_usecs;
+#if defined(USING_MALI400_L2_CACHE)
+ job_out->perf_counter_l2_src0 = jobgp->perf_counter_l2_src0;
+ job_out->perf_counter_l2_src1 = jobgp->perf_counter_l2_src1;
+ job_out->perf_counter_l2_val0 = jobgp->perf_counter_l2_val0;
+ job_out->perf_counter_l2_val1 = jobgp->perf_counter_l2_val1;
+#endif
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&session->jobs_returned);
+#endif
+ _mali_osk_notification_queue_send( session->notification_queue, jobgp->notification_obj);
+ jobgp->notification_obj = NULL;
+
+ _mali_osk_free(jobgp);
+
+ last_gp_core_cookie = NULL;
+}
+
+static void subsystem_maligp_renderunit_delete(mali_core_renderunit * core)
+{
+ MALI_DEBUG_PRINT(5, ("Mali GP: maligp_renderunit_delete\n"));
+ _mali_osk_free(core);
+}
+
+static void subsystem_maligp_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style)
+{
+ MALI_DEBUG_PRINT(5, ("Mali GP: renderunit_reset_core\n"));
+
+ switch (style)
+ {
+ case MALI_CORE_RESET_STYLE_RUNABLE:
+ maligp_reset(core);
+ break;
+ case MALI_CORE_RESET_STYLE_DISABLE:
+ maligp_raw_reset(core); /* do the raw reset */
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* then disable the IRQs */
+ break;
+ case MALI_CORE_RESET_STYLE_HARD:
+ maligp_reset_hard(core);
+ maligp_initialize_registers_mgmt(core);
+ break;
+ default:
+ MALI_DEBUG_PRINT(1, ("Unknown reset type %d\n", style));
+ break;
+ }
+}
+
+static void subsystem_maligp_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core)
+{
+ mali_core_renderunit_register_write(core , MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+ mali_core_renderunit_register_write(core , MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG );
+ _mali_osk_mem_barrier();
+}
+
+static _mali_osk_errcode_t subsystem_maligp_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core)
+{
+ u32 irq_readout;
+
+ irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+
+ if ( MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout )
+ {
+ mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG);
+ _mali_osk_mem_barrier();
+ MALI_SUCCESS;
+ }
+
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+}
+
+_mali_osk_errcode_t _mali_ukk_gp_start_job( _mali_uk_gp_start_job_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_start_job(session, args);
+}
+
+_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_number_of_cores_get(session, &args->number_of_cores);
+}
+
+_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_core_version_get(session, &args->version);
+}
+
+_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_suspend_response(session, args);
+}
+
+void _mali_ukk_gp_abort_job( _mali_uk_gp_abort_job_s * args)
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ if (NULL == args->ctx) return;
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_gp_id);
+ if (NULL == session) return;
+ mali_core_subsystem_ioctl_abort_job(session, args->abort_id);
+
+}
+
+#if USING_MALI_PMM
+
+_mali_osk_errcode_t maligp_signal_power_up( mali_bool queue_only )
+{
+ MALI_DEBUG_PRINT(4, ("Mali GP: signal power up core - queue_only: %d\n", queue_only ));
+
+ return( mali_core_subsystem_signal_power_up( &subsystem_maligp, 0, queue_only ) );
+}
+
+_mali_osk_errcode_t maligp_signal_power_down( mali_bool immediate_only )
+{
+ MALI_DEBUG_PRINT(4, ("Mali GP: signal power down core - immediate_only: %d\n", immediate_only ));
+
+ return( mali_core_subsystem_signal_power_down( &subsystem_maligp, 0, immediate_only ) );
+}
+
+#endif
+
+#if MALI_STATE_TRACKING
+u32 maligp_subsystem_dump_state(char *buf, u32 size)
+{
+ return mali_core_renderunit_dump_state(&subsystem_maligp, buf, size);
+}
+#endif
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c b/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c
new file mode 100644
index 00000000000..7bce5862a9d
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c
@@ -0,0 +1,1286 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_kernel_pp.h"
+#include "mali_kernel_subsystem.h"
+#include "mali_kernel_core.h"
+#include "regs/mali_200_regs.h"
+#include "mali_kernel_rendercore.h"
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.h"
+#endif
+#ifdef USING_MALI400_L2_CACHE
+#include "mali_kernel_l2_cache.h"
+#endif
+#if USING_MMU
+#include "mali_kernel_mem_mmu.h" /* Needed for mali_kernel_mmu_force_bus_reset() */
+#endif
+
+#include "mali_osk_list.h"
+
+#if defined(USING_MALI200)
+#define MALI_PP_SUBSYSTEM_NAME "Mali200"
+#define MALI_PP_CORE_TYPE _MALI_200
+#elif defined(USING_MALI400)
+#define MALI_PP_SUBSYSTEM_NAME "Mali-400 PP"
+#define MALI_PP_CORE_TYPE _MALI_400_PP
+#else
+#error "No supported mali core defined"
+#endif
+
+#define GET_JOB_EMBEDDED_PTR(job) (&((job)->embedded_core_job))
+#define GET_JOB200_PTR(job_extern) _MALI_OSK_CONTAINER_OF(job_extern, mali200_job, embedded_core_job)
+
+/* Initialized when this subsystem is initialized. This is determined by the
+ * position in subsystems[], and so the value used to initialize this is
+ * determined at compile time */
+static mali_kernel_subsystem_identifier mali_subsystem_mali200_id = -1;
+
+/* Describing a mali200 job settings */
+typedef struct mali200_job
+{
+ /* The general job struct common for all mali cores */
+ mali_core_job embedded_core_job;
+ _mali_uk_pp_start_job_s user_input;
+
+ u32 irq_status;
+ u32 perf_counter0;
+ u32 perf_counter1;
+ u32 last_tile_list_addr; /* Neccessary to continue a stopped job */
+
+ u32 active_mask;
+
+ /* The data we will return back to the user */
+ _mali_osk_notification_t *notification_obj;
+
+#if defined(USING_MALI400_L2_CACHE)
+ u32 perf_counter_l2_src0;
+ u32 perf_counter_l2_src1;
+ u32 perf_counter_l2_val0;
+ u32 perf_counter_l2_val1;
+ u32 perf_counter_l2_val0_raw;
+ u32 perf_counter_l2_val1_raw;
+#endif
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ u32 pid;
+ u32 tid;
+#endif
+} mali200_job;
+
+
+/*Functions Exposed to the General External System through
+ funciont pointers.*/
+
+static _mali_osk_errcode_t mali200_subsystem_startup(mali_kernel_subsystem_identifier id);
+#if USING_MMU
+static _mali_osk_errcode_t mali200_subsystem_mmu_connect(mali_kernel_subsystem_identifier id);
+#endif
+static void mali200_subsystem_terminate(mali_kernel_subsystem_identifier id);
+static _mali_osk_errcode_t mali200_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+static void mali200_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
+static _mali_osk_errcode_t mali200_subsystem_core_system_info_fill(_mali_system_info* info);
+static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * resource);
+#if USING_MMU
+static void mali200_subsystem_broadcast_notification(mali_core_notification_message message, u32 data);
+#endif
+#if MALI_STATE_TRACKING
+u32 mali200_subsystem_dump_state(char *buf, u32 size);
+#endif
+
+/* Internal support functions */
+static _mali_osk_errcode_t mali200_core_version_legal( mali_core_renderunit *core );
+static void mali200_reset(mali_core_renderunit *core);
+static void mali200_reset_hard(struct mali_core_renderunit * core);
+static void mali200_raw_reset(mali_core_renderunit * core);
+static void mali200_initialize_registers_mgmt(mali_core_renderunit *core );
+
+/* Functions exposed to mali_core system through functionpointers
+ in the subsystem struct. */
+static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali_core_renderunit * core);
+static _mali_osk_errcode_t subsystem_mali200_get_new_job_from_user(struct mali_core_session * session, void * argument);
+static void subsystem_mali200_return_job_to_user( mali_core_job * job, mali_subsystem_job_end_code end_status);
+static void subsystem_mali200_renderunit_delete(mali_core_renderunit * core);
+static void subsystem_mali200_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style);
+static void subsystem_mali200_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core);
+static _mali_osk_errcode_t subsystem_mali200_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core);
+
+static void subsystem_mali200_renderunit_stop_bus(struct mali_core_renderunit* core);
+static u32 subsystem_mali200_irq_handler_upper_half(struct mali_core_renderunit * core);
+static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit* core);
+
+/* This will be one of the subsystems in the array of subsystems:
+ static struct mali_kernel_subsystem * subsystems[];
+ found in file: mali_kernel_core.c
+*/
+
+struct mali_kernel_subsystem mali_subsystem_mali200=
+{
+ mali200_subsystem_startup, /* startup */
+ mali200_subsystem_terminate, /* shutdown */
+#if USING_MMU
+ mali200_subsystem_mmu_connect, /* load_complete */
+#else
+ NULL,
+#endif
+ mali200_subsystem_core_system_info_fill, /* system_info_fill */
+ mali200_subsystem_session_begin, /* session_begin */
+ mali200_subsystem_session_end, /* session_end */
+#if USING_MMU
+ mali200_subsystem_broadcast_notification, /* broadcast_notification */
+#else
+ NULL,
+#endif
+#if MALI_STATE_TRACKING
+ mali200_subsystem_dump_state, /* dump_state */
+#endif
+} ;
+
+static mali_core_subsystem subsystem_mali200 ;
+
+static _mali_osk_errcode_t mali200_subsystem_startup(mali_kernel_subsystem_identifier id)
+{
+ mali_core_subsystem * subsystem;
+
+ MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_startup\n") ) ;
+
+ mali_subsystem_mali200_id = id;
+
+ /* All values get 0 as default */
+ _mali_osk_memset(&subsystem_mali200, 0, sizeof(subsystem_mali200));
+
+ subsystem = &subsystem_mali200;
+ subsystem->start_job = &subsystem_mali200_start_job;
+ subsystem->irq_handler_upper_half = &subsystem_mali200_irq_handler_upper_half;
+ subsystem->irq_handler_bottom_half = &subsystem_mali200_irq_handler_bottom_half;
+ subsystem->get_new_job_from_user = &subsystem_mali200_get_new_job_from_user;
+ subsystem->return_job_to_user = &subsystem_mali200_return_job_to_user;
+ subsystem->renderunit_delete = &subsystem_mali200_renderunit_delete;
+ subsystem->reset_core = &subsystem_mali200_renderunit_reset_core;
+ subsystem->stop_bus = &subsystem_mali200_renderunit_stop_bus;
+ subsystem->probe_core_irq_trigger = &subsystem_mali200_renderunit_probe_core_irq_trigger;
+ subsystem->probe_core_irq_acknowledge = &subsystem_mali200_renderunit_probe_core_irq_finished;
+
+ /* Setting variables in the general core part of the subsystem.*/
+ subsystem->name = MALI_PP_SUBSYSTEM_NAME;
+ subsystem->core_type = MALI_PP_CORE_TYPE;
+ subsystem->id = id;
+
+ /* Initiates the rest of the general core part of the subsystem */
+ MALI_CHECK_NO_ERROR(mali_core_subsystem_init( subsystem ));
+
+ /* This will register the function for adding MALI200 cores to the subsystem */
+#if defined(USING_MALI200)
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALI200, mali200_renderunit_create));
+#endif
+#if defined(USING_MALI400)
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MALI400PP, mali200_renderunit_create));
+#endif
+
+ MALI_DEBUG_PRINT(6, ("Mali PP: mali200_subsystem_startup\n") ) ;
+
+ MALI_SUCCESS;
+}
+
+#if USING_MMU
+static _mali_osk_errcode_t mali200_subsystem_mmu_connect(mali_kernel_subsystem_identifier id)
+{
+ mali_core_subsystem_attach_mmu(&subsystem_mali200);
+ MALI_SUCCESS; /* OK */
+}
+#endif
+
+static void mali200_subsystem_terminate(mali_kernel_subsystem_identifier id)
+{
+ MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_terminate\n") ) ;
+ mali_core_subsystem_cleanup(&subsystem_mali200);
+}
+
+static _mali_osk_errcode_t mali200_subsystem_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
+{
+ mali_core_session * session;
+
+ MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_session_begin\n") ) ;
+ MALI_CHECK_NON_NULL(session = _mali_osk_malloc( sizeof(mali_core_session) ), _MALI_OSK_ERR_NOMEM);
+
+ _mali_osk_memset(session, 0, sizeof(*session) );
+ *slot = (mali_kernel_subsystem_session_slot)session;
+
+ session->subsystem = &subsystem_mali200;
+
+ session->notification_queue = queue;
+
+#if USING_MMU
+ session->mmu_session = mali_session_data;
+#endif
+
+ mali_core_session_begin(session);
+
+ MALI_DEBUG_PRINT(6, ("Mali PP: mali200_subsystem_session_begin\n") ) ;
+
+ MALI_SUCCESS;
+}
+
+static void mali200_subsystem_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
+{
+ mali_core_session * session;
+
+ MALI_DEBUG_PRINT(3, ("Mali PP: mali200_subsystem_session_end\n") ) ;
+ if ( NULL==slot || NULL==*slot)
+ {
+ MALI_PRINT_ERROR(("Input slot==NULL"));
+ return;
+ }
+ session = (mali_core_session*) *slot;
+ mali_core_session_close(session);
+
+ _mali_osk_free(session);
+ *slot = NULL;
+
+ MALI_DEBUG_PRINT(6, ("Mali PP: mali200_subsystem_session_end\n") ) ;
+}
+
+/**
+ * We fill in info about all the cores we have
+ * @param info Pointer to system info struct to update
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali200_subsystem_core_system_info_fill(_mali_system_info* info)
+{
+ return mali_core_subsystem_system_info_fill(&subsystem_mali200, info);
+}
+
+
+static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * resource)
+{
+ mali_core_renderunit *core;
+ _mali_osk_errcode_t err;
+
+ MALI_DEBUG_PRINT(3, ("Mali PP: mali200_renderunit_create\n") ) ;
+ /* Checking that the resource settings are correct */
+#if defined(USING_MALI200)
+ if(MALI200 != resource->type)
+ {
+ MALI_PRINT_ERROR(("Can not register this resource as a " MALI_PP_SUBSYSTEM_NAME " core."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#elif defined(USING_MALI400)
+ if(MALI400PP != resource->type)
+ {
+ MALI_PRINT_ERROR(("Can not register this resource as a " MALI_PP_SUBSYSTEM_NAME " core."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#endif
+ if ( 0 != resource->size )
+ {
+ MALI_PRINT_ERROR(("Memory size set to " MALI_PP_SUBSYSTEM_NAME " core should be zero."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ if ( NULL == resource->description )
+ {
+ MALI_PRINT_ERROR(("A " MALI_PP_SUBSYSTEM_NAME " core needs a unique description field"));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Create a new core object */
+ core = (mali_core_renderunit*) _mali_osk_malloc(sizeof(*core));
+ if ( NULL == core )
+ {
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ /* Variables set to be able to open and register the core */
+ core->subsystem = &subsystem_mali200 ;
+ core->registers_base_addr = resource->base ;
+ core->size = MALI200_REG_SIZEOF_REGISTER_BANK ;
+ core->irq_nr = resource->irq ;
+ core->description = resource->description;
+#if USING_MMU
+ core->mmu_id = resource->mmu_id;
+ core->mmu = NULL;
+#endif
+#if USING_MALI_PMM
+ /* Set up core's PMM id */
+ switch( subsystem_mali200.number_of_cores )
+ {
+ case 0:
+ core->pmm_id = MALI_PMM_CORE_PP0;
+ break;
+ case 1:
+ core->pmm_id = MALI_PMM_CORE_PP1;
+ break;
+ case 2:
+ core->pmm_id = MALI_PMM_CORE_PP2;
+ break;
+ case 3:
+ core->pmm_id = MALI_PMM_CORE_PP3;
+ break;
+ default:
+ MALI_DEBUG_PRINT(1, ("Unknown supported core for PMM\n"));
+ err = _MALI_OSK_ERR_FAULT;
+ goto exit_on_error0;
+ }
+#endif
+
+ err = mali_core_renderunit_init( core );
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to initialize renderunit\n"));
+ goto exit_on_error0;
+ }
+
+ /* Map the new core object, setting: core->registers_mapped */
+ err = mali_core_renderunit_map_registers(core);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to map register\n"));
+ goto exit_on_error1;
+ }
+
+ /* Check that the register mapping of the core works.
+ Return 0 if Mali PP core is present and accessible. */
+ if (mali_benchmark) {
+#if defined(USING_MALI200)
+ core->core_version = (((u32)MALI_PP_PRODUCT_ID) << 16) | 5 /* Fake Mali200-r0p5 */;
+#elif defined(USING_MALI400)
+ core->core_version = (((u32)MALI_PP_PRODUCT_ID) << 16) | 0x0101 /* Fake Mali400-r1p1 */;
+#else
+#error "No supported mali core defined"
+#endif
+ } else {
+ core->core_version = mali_core_renderunit_register_read(
+ core,
+ MALI200_REG_ADDR_MGMT_VERSION);
+ }
+
+ err = mali200_core_version_legal(core);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(1, ("Invalid core\n"));
+ goto exit_on_error2;
+ }
+
+ /* Reset the core. Put the core into a state where it can start to render. */
+ mali200_reset(core);
+
+ /* Registering IRQ, init the work_queue_irq_handle */
+ /* Adding this core as an available renderunit in the subsystem. */
+ err = mali_core_subsystem_register_renderunit(&subsystem_mali200, core);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to register with core\n"));
+ goto exit_on_error2;
+ }
+ MALI_DEBUG_PRINT(6, ("Mali PP: mali200_renderunit_create\n") ) ;
+
+ MALI_SUCCESS;
+
+exit_on_error2:
+ mali_core_renderunit_unmap_registers(core);
+exit_on_error1:
+ mali_core_renderunit_term(core);
+exit_on_error0:
+ _mali_osk_free( core ) ;
+ MALI_PRINT_ERROR(("Renderunit NOT created."));
+ MALI_ERROR(err);
+}
+
+#if USING_MMU
+/* Used currently only for signalling when MMU has a pagefault */
+static void mali200_subsystem_broadcast_notification(mali_core_notification_message message, u32 data)
+{
+ mali_core_subsystem_broadcast_notification(&subsystem_mali200, message, data);
+}
+#endif
+
+static _mali_osk_errcode_t mali200_core_version_legal( mali_core_renderunit *core )
+{
+ u32 mali_type;
+
+ mali_type = core->core_version >> 16;
+#if defined(USING_MALI400)
+ /* Mali300 and Mali400 is compatible, accept either core. */
+ if (MALI400_PP_PRODUCT_ID != mali_type && MALI300_PP_PRODUCT_ID != mali_type)
+#else
+ if (MALI_PP_PRODUCT_ID != mali_type)
+#endif
+ {
+ MALI_PRINT_ERROR(("Error: reading this from " MALI_PP_SUBSYSTEM_NAME " version register: 0x%x\n", core->core_version));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ MALI_DEBUG_PRINT(3, ("Mali PP: core_version_legal: Reads correct mali version: %d\n", mali_type) ) ;
+ MALI_SUCCESS;
+}
+
+static void subsystem_mali200_renderunit_stop_bus(struct mali_core_renderunit* core)
+{
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
+}
+
+static void mali200_raw_reset( mali_core_renderunit *core )
+{
+ int i;
+ const int request_loop_count = 20;
+
+ MALI_DEBUG_PRINT(4, ("Mali PP: mali200_raw_reset: %s\n", core->description));
+ if (mali_benchmark) return;
+
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable IRQs */
+
+#if defined(USING_MALI200)
+
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED) break;
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ MALI_DEBUG_PRINT_IF(1, request_loop_count == i, ("Mali PP: Bus was never stopped during core reset\n"));
+
+
+ if (request_loop_count==i)
+ {
+#if USING_MMU
+ if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
+ {
+ /* Could not stop bus connections from core, probably because some of the already pending
+ bus request has had a page fault, and therefore can not complete before the MMU does PageFault
+ handling. This can be treated as a heavier reset function - which unfortunately reset all
+ the cores on this MMU in addition to the MMU itself */
+ MALI_DEBUG_PRINT(1, ("Mali PP: Forcing Bus reset\n"));
+ mali_kernel_mmu_force_bus_reset(core->mmu);
+ return;
+ }
+#endif
+ MALI_PRINT(("A MMU reset did not allow PP to stop its bus, system failure, unable to recover\n"));
+ return;
+ }
+
+ /* use the hard reset routine to do the actual reset */
+ mali200_reset_hard(core);
+
+#elif defined(USING_MALI400)
+
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED);
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED) break;
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count==i)
+ {
+#if USING_MMU
+ if ((NULL!=core->mmu) && (MALI_FALSE == core->error_recovery))
+ {
+ /* Could not stop bus connections from core, probably because some of the already pending
+ bus request has had a page fault, and therefore can not complete before the MMU does PageFault
+ handling. This can be treated as a heavier reset function - which unfortunately reset all
+ the cores on this MMU in addition to the MMU itself */
+ MALI_DEBUG_PRINT(1, ("Mali PP: Forcing Bus reset\n"));
+ mali_kernel_mmu_force_bus_reset(core->mmu);
+ return;
+ }
+#endif
+ MALI_PRINT(("A MMU reset did not allow PP to stop its bus, system failure, unable to recover\n"));
+ return;
+ }
+ else
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
+
+#else
+#error "no supported mali core defined"
+#endif
+}
+
+static void mali200_reset( mali_core_renderunit *core )
+{
+ if (!mali_benchmark) {
+ mali200_raw_reset(core);
+ mali200_initialize_registers_mgmt(core);
+ }
+}
+
+/* Sets the registers on mali200 according to the const default_mgmt_regs array. */
+static void mali200_initialize_registers_mgmt(mali_core_renderunit *core )
+{
+ MALI_DEBUG_PRINT(6, ("Mali PP: mali200_initialize_registers_mgmt: %s\n", core->description)) ;
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+}
+
+/* Start this job on this core. Return MALI_TRUE if the job was started. */
+static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali_core_renderunit * core)
+{
+ mali200_job *job200;
+
+ /* The local extended version of the general structs */
+ job200 = _MALI_OSK_CONTAINER_OF(job, mali200_job, embedded_core_job);
+
+ if ( (0 == job200->user_input.frame_registers[0]) ||
+ (0 == job200->user_input.frame_registers[1]) )
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x WILL NOT START SINCE JOB HAS ILLEGAL ADDRESSES\n",
+ (u32)job200->user_input.user_job_ptr));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x START_RENDER Tile_list: 0x%08x\n",
+ (u32)job200->user_input.user_job_ptr,
+ job200->user_input.frame_registers[0]));
+ MALI_DEBUG_PRINT(6, ("Mali PP: RSW base addr: 0x%08x Vertex base addr: 0x%08x\n",
+ job200->user_input.frame_registers[1], job200->user_input.frame_registers[2]));
+
+ /* Frame registers. Copy from mem to physical registers */
+ mali_core_renderunit_register_write_array(
+ core,
+ MALI200_REG_ADDR_FRAME,
+ &(job200->user_input.frame_registers[0]),
+ MALI200_NUM_REGS_FRAME);
+
+ /* Write Back unit 0. Copy from mem to physical registers only if the WB unit will be used. */
+ if (job200->user_input.wb0_registers[0])
+ {
+ mali_core_renderunit_register_write_array(
+ core,
+ MALI200_REG_ADDR_WB0,
+ &(job200->user_input.wb0_registers[0]),
+ MALI200_NUM_REGS_WBx);
+ }
+
+ /* Write Back unit 1. Copy from mem to physical registers only if the WB unit will be used. */
+ if (job200->user_input.wb1_registers[0])
+ {
+ mali_core_renderunit_register_write_array(
+ core,
+ MALI200_REG_ADDR_WB1,
+ &(job200->user_input.wb1_registers[0]),
+ MALI200_NUM_REGS_WBx);
+ }
+
+ /* Write Back unit 2. Copy from mem to physical registers only if the WB unit will be used. */
+ if (job200->user_input.wb2_registers[0])
+ {
+ mali_core_renderunit_register_write_array(
+ core,
+ MALI200_REG_ADDR_WB2,
+ &(job200->user_input.wb2_registers[0]),
+ MALI200_NUM_REGS_WBx);
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ /*
+ * If the hardware counters are not turned on, ask the external profiler
+ * if they should be.
+ */
+ if (job200->user_input.perf_counter_flag == 0)
+ {
+ /*
+ * Work out the correct counter offset to use. Each fragment processor
+ * has two hardware counters.
+ */
+ u32 counter0_offset = MALI_PROFILING_PP_CORE_COUNTER0_OFFSET(core->core_number);
+ u32 counter1_offset = MALI_PROFILING_PP_CORE_COUNTER1_OFFSET(core->core_number);
+
+ mali_bool src0_enabled = _mali_osk_profiling_query_hw_counter(counter0_offset,
+ &(job200->user_input.perf_counter_src0));
+ mali_bool src1_enabled = _mali_osk_profiling_query_hw_counter(counter1_offset,
+ &(job200->user_input.perf_counter_src1));
+
+ if (src0_enabled == MALI_TRUE)
+ {
+ job200->user_input.perf_counter_flag |=
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE;
+ }
+
+ if (src1_enabled == MALI_TRUE)
+ {
+ job200->user_input.perf_counter_flag |=
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE;
+ }
+ }
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+
+ /* This selects which performance counters we are reading */
+ if ( 0 != job200->user_input.perf_counter_flag )
+ {
+ if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
+ {
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE,
+ MALI200_REG_VAL_PERF_CNT_ENABLE);
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC,
+ job200->user_input.perf_counter_src0);
+
+ }
+
+ if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
+ {
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE,
+ MALI200_REG_VAL_PERF_CNT_ENABLE);
+ mali_core_renderunit_register_write_relaxed(
+ core,
+ MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC,
+ job200->user_input.perf_counter_src1);
+
+ }
+
+#if defined(USING_MALI400_L2_CACHE)
+ if ( job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
+ {
+ int force_reset = ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET ) ? 1 : 0;
+ u32 src0 = 0;
+ u32 src1 = 0;
+
+ if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE )
+ {
+ src0 = job200->user_input.perf_counter_l2_src0;
+ }
+ if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE )
+ {
+ src1 = job200->user_input.perf_counter_l2_src1;
+ }
+
+ mali_kernel_l2_cache_set_perf_counters(src0, src1, force_reset); /* will activate and possibly reset counters */
+
+ /* Now, retrieve the current values, so we can substract them when the job has completed */
+ mali_kernel_l2_cache_get_perf_counters(&job200->perf_counter_l2_src0,
+ &job200->perf_counter_l2_val0,
+ &job200->perf_counter_l2_src1,
+ &job200->perf_counter_l2_val1);
+ }
+#endif
+ }
+
+ subsystem_flush_mapped_mem_cache();
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_started);
+#endif
+
+ /* This is the command that starts the Core */
+ mali_core_renderunit_register_write(
+ core,
+ MALI200_REG_ADDR_MGMT_CTRL_MGMT,
+ MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
+ _mali_osk_write_mem_barrier();
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job200->user_input.frame_builder_id, job200->user_input.flush_id, 0, 0, 0);
+ _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), job200->pid, job200->tid,
+#if defined(USING_MALI400_L2_CACHE)
+ (job200->user_input.perf_counter_l2_src0 << 16) | (job200->user_input.perf_counter_l2_src1 << 24),
+ job200->perf_counter_l2_val0, job200->perf_counter_l2_val1
+#else
+ 0, 0, 0
+#endif
+ );
+#endif
+
+ MALI_SUCCESS;
+}
+
+static u32 subsystem_mali200_irq_handler_upper_half(mali_core_renderunit * core)
+{
+ u32 irq_readout;
+
+ if (mali_benchmark) {
+ return (core->current_job ? 1 : 0); /* simulate irq is pending when a job is pending */
+ }
+
+ irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+
+ if ( MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout )
+ {
+ /* Mask out all IRQs from this core until IRQ is handled */
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
+#endif
+
+ return 1;
+ }
+ return 0;
+}
+
+static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit* core)
+{
+ u32 irq_readout;
+ u32 current_tile_addr;
+ u32 core_status;
+ mali_core_job * job;
+ mali200_job * job200;
+
+ job = core->current_job;
+ job200 = GET_JOB200_PTR(job);
+
+
+ if (mali_benchmark) {
+ irq_readout = MALI200_REG_VAL_IRQ_END_OF_FRAME;
+ current_tile_addr = 0;
+ core_status = 0;
+ } else {
+ irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
+ current_tile_addr = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR);
+ core_status = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_STATUS);
+ }
+
+ if (NULL == job)
+ {
+ MALI_DEBUG_ASSERT(CORE_IDLE==core->state);
+ if ( 0 != irq_readout )
+ {
+ MALI_PRINT_ERROR(("Interrupt from a core not running a job. IRQ: 0x%04x Status: 0x%04x", irq_readout, core_status));
+ }
+ return JOB_STATUS_END_UNKNOWN_ERR;
+ }
+ MALI_DEBUG_ASSERT(CORE_IDLE!=core->state);
+
+ job200->irq_status |= irq_readout;
+
+ MALI_DEBUG_PRINT_IF( 3, ( 0 != irq_readout ),
+ ("Mali PP: Job: 0x%08x IRQ RECEIVED Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n",
+ (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status));
+
+ if ( MALI200_REG_VAL_IRQ_END_OF_FRAME & irq_readout)
+ {
+#if defined(USING_MALI200)
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES);
+#endif
+
+ if (0 != job200->user_input.perf_counter_flag )
+ {
+ if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) )
+ {
+#if MALI_TIMELINE_PROFILING_ENABLED
+ /* Work out the counter offsets for the core number */
+ u32 counter0_offset = MALI_PROFILING_PP_CORE_COUNTER0_OFFSET(core->core_number);
+ u32 counter1_offset = MALI_PROFILING_PP_CORE_COUNTER1_OFFSET(core->core_number);
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+
+ job200->perf_counter0 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+ job200->perf_counter1 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ /* Report the counter values */
+ _mali_osk_profiling_report_hw_counter(counter0_offset, job200->perf_counter0);
+ _mali_osk_profiling_report_hw_counter(counter1_offset, job200->perf_counter1);
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+ }
+
+#if defined(USING_MALI400_L2_CACHE)
+ if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) )
+ {
+ u32 src0;
+ u32 val0;
+ u32 src1;
+ u32 val1;
+ mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1);
+
+ if (job200->perf_counter_l2_src0 == src0)
+ {
+ job200->perf_counter_l2_val0_raw = val0;
+ job200->perf_counter_l2_val0 = val0 - job200->perf_counter_l2_val0;
+ }
+ else
+ {
+ job200->perf_counter_l2_val0_raw = 0;
+ job200->perf_counter_l2_val0 = 0;
+ }
+
+ if (job200->perf_counter_l2_src1 == src1)
+ {
+ job200->perf_counter_l2_val1_raw = val1;
+ job200->perf_counter_l2_val1 = val1 - job200->perf_counter_l2_val1;
+ }
+ else
+ {
+ job200->perf_counter_l2_val1_raw = 0;
+ job200->perf_counter_l2_val1 = 0;
+ }
+ }
+#endif
+
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number),
+ job200->perf_counter0, job200->perf_counter1,
+ job200->user_input.perf_counter_src0 | (job200->user_input.perf_counter_src1 << 8)
+#if defined(USING_MALI400_L2_CACHE)
+ | (job200->user_input.perf_counter_l2_src0 << 16) | (job200->user_input.perf_counter_l2_src1 << 24),
+ job200->perf_counter_l2_val0_raw, job200->perf_counter_l2_val1_raw
+#else
+ , 0, 0
+#endif
+ );
+#endif
+
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+ return JOB_STATUS_END_SUCCESS; /* reschedule */
+ }
+ /* Overall SW watchdog timeout or (time to do hang checking and progress detected)? */
+ else if (
+ (CORE_WATCHDOG_TIMEOUT == core->state) ||
+ ((CORE_HANG_CHECK_TIMEOUT == core->state) && (current_tile_addr == job200->last_tile_list_addr))
+ )
+ {
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */
+#endif
+ /* no progress detected, killed by the watchdog */
+ MALI_DEBUG_PRINT(2, ("M200: SW-Timeout Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x.\n", irq_readout ,current_tile_addr ,core_status) );
+ /* In this case will the system outside cleanup and reset the core */
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+
+ return JOB_STATUS_END_HANG;
+ }
+ /* HW watchdog triggered or an existing hang check passed? */
+ else if ((CORE_HANG_CHECK_TIMEOUT == core->state) || (irq_readout & job200->active_mask & MALI200_REG_VAL_IRQ_HANG))
+ {
+ /* check interval in ms */
+ u32 timeout = mali_core_hang_check_timeout_get();
+ MALI_DEBUG_PRINT(3, ("M200: HW/SW Watchdog triggered, checking for progress in %d ms\n", timeout));
+ job200->last_tile_list_addr = current_tile_addr;
+ /* hw watchdog triggered, set up a progress checker every HANGCHECK ms */
+ _mali_osk_timer_add(core->timer_hang_detection, _mali_osk_time_mstoticks(timeout));
+ job200->active_mask &= ~MALI200_REG_VAL_IRQ_HANG; /* ignore the hw watchdoig from now on */
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout & ~MALI200_REG_VAL_IRQ_HANG);
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask);
+ return JOB_STATUS_CONTINUE_RUN; /* not finished */
+ }
+ /* No irq pending, core still busy */
+ else if ((0 == (irq_readout & MALI200_REG_VAL_IRQ_MASK_USED)) && ( 0 != (core_status & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)))
+ {
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout);
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask);
+ return JOB_STATUS_CONTINUE_RUN; /* Not finished */
+ }
+ else
+ {
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */
+#endif
+
+ MALI_DEBUG_PRINT(1, ("Mali PP: Job: 0x%08x CRASH? Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n",
+ (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status) ) ;
+
+ if (irq_readout & MALI200_REG_VAL_IRQ_BUS_ERROR)
+ {
+ u32 bus_error = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS);
+
+ MALI_DEBUG_PRINT(1, ("Bus error status: 0x%08X\n", bus_error));
+ MALI_DEBUG_PRINT_IF(1, (bus_error & 0x01), ("Bus write error from id 0x%02x\n", (bus_error>>2) & 0x0F));
+ MALI_DEBUG_PRINT_IF(1, (bus_error & 0x02), ("Bus read error from id 0x%02x\n", (bus_error>>6) & 0x0F));
+ MALI_DEBUG_PRINT_IF(1, (0 == (bus_error & 0x03)), ("Bus error but neither read or write was set as the error reason\n"));
+ (void)bus_error;
+ }
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&job->session->jobs_ended);
+#endif
+ return JOB_STATUS_END_UNKNOWN_ERR; /* reschedule */
+ }
+}
+
+
+/* This function is called from the ioctl function and should return a mali_core_job pointer
+to a created mali_core_job object with the data given from userspace */
+static _mali_osk_errcode_t subsystem_mali200_get_new_job_from_user(struct mali_core_session * session, void * argument)
+{
+ mali200_job *job200;
+ mali_core_job *job = NULL;
+ mali_core_job *previous_replaced_job;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_uk_pp_start_job_s * user_ptr_job_input;
+
+ user_ptr_job_input = (_mali_uk_pp_start_job_s *)argument;
+
+ MALI_CHECK_NON_NULL(job200 = (mali200_job *) _mali_osk_malloc(sizeof(mali200_job)), _MALI_OSK_ERR_NOMEM);
+ _mali_osk_memset(job200, 0 , sizeof(mali200_job) );
+
+ /* We read job data from Userspace pointer */
+ if ( NULL == _mali_osk_memcpy((void*)&job200->user_input, user_ptr_job_input, sizeof(job200->user_input)) )
+ {
+ MALI_PRINT_ERROR( ("Mali PP: Could not copy data from U/K interface.\n")) ;
+ err = _MALI_OSK_ERR_FAULT;
+ goto function_exit;
+ }
+
+ MALI_DEBUG_PRINT(5, ("Mali PP: subsystem_mali200_get_new_job_from_user 0x%x\n", (void*)job200->user_input.user_job_ptr));
+
+ MALI_DEBUG_PRINT(5, ("Mali PP: Frameregs: 0x%x 0x%x 0x%x Writeback[1] 0x%x, Pri:%d; Watchd:%d\n",
+ job200->user_input.frame_registers[0], job200->user_input.frame_registers[1], job200->user_input.frame_registers[2],
+ job200->user_input.wb0_registers[1], job200->user_input.priority,
+ job200->user_input.watchdog_msecs));
+
+ if ( job200->user_input.perf_counter_flag)
+ {
+#if defined(USING_MALI400_L2_CACHE)
+ MALI_DEBUG_PRINT(5, ("Mali PP: Performance counters: flag:0x%x src0:0x%x src1:0x%x l2_src0:0x%x l2_src1:0x%x\n",
+ job200->user_input.perf_counter_flag,
+ job200->user_input.perf_counter_src0,
+ job200->user_input.perf_counter_src1,
+ job200->user_input.perf_counter_l2_src0,
+ job200->user_input.perf_counter_l2_src1));
+#else
+ MALI_DEBUG_PRINT(5, ("Mali PP: Performance counters: flag:0x%x src0:0x%x src1:0x%x\n",
+ job200->user_input.perf_counter_flag,
+ job200->user_input.perf_counter_src0,
+ job200->user_input.perf_counter_src1));
+#endif
+ }
+
+ job = GET_JOB_EMBEDDED_PTR(job200);
+
+ job->session = session;
+ job->flags = user_ptr_job_input->flags;
+ job_priority_set(job, job200->user_input.priority);
+ job_watchdog_set(job, job200->user_input.watchdog_msecs );
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ job200->pid = _mali_osk_get_pid();
+ job200->tid = _mali_osk_get_tid();
+#endif
+
+ job->abort_id = job200->user_input.abort_id;
+ if (mali_job_queue_full(session))
+ {
+ user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
+ goto function_exit;
+ }
+
+ /* We now know that we has a job, and a empty session slot to put it in */
+
+ job200->active_mask = MALI200_REG_VAL_IRQ_MASK_USED;
+
+ /* Allocating User Return Data */
+ job200->notification_obj = _mali_osk_notification_create(
+ _MALI_NOTIFICATION_PP_FINISHED,
+ sizeof(_mali_uk_pp_job_finished_s) );
+
+ if ( NULL == job200->notification_obj )
+ {
+ MALI_PRINT_ERROR( ("Mali PP: Could not get notification_obj.\n")) ;
+ err = _MALI_OSK_ERR_NOMEM;
+ goto function_exit;
+ }
+
+ _MALI_OSK_INIT_LIST_HEAD( &(job->list) ) ;
+
+ MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x INPUT from user.\n", (u32)job200->user_input.user_job_ptr)) ;
+
+ /* This should not happen since we have the checking of priority above */
+ if ( _MALI_OSK_ERR_OK != mali_core_session_add_job(session, job, &previous_replaced_job))
+ {
+ MALI_PRINT_ERROR( ("Mali PP: Internal error\n")) ;
+ user_ptr_job_input->status = _MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE;
+ _mali_osk_notification_delete( job200->notification_obj );
+ goto function_exit;
+ }
+
+ /* If MALI_TRUE: This session had a job with lower priority which were removed.
+ This replaced job is given back to userspace. */
+ if ( NULL != previous_replaced_job )
+ {
+ mali200_job *previous_replaced_job200;
+
+ previous_replaced_job200 = GET_JOB200_PTR(previous_replaced_job);
+
+ MALI_DEBUG_PRINT(4, ("Mali PP: Replacing job: 0x%08x\n", (u32)previous_replaced_job200->user_input.user_job_ptr)) ;
+
+ /* Copy to the input data (which also is output data) the
+ pointer to the job that were replaced, so that the userspace
+ driver can put this job in the front of its job-queue */
+
+ user_ptr_job_input->returned_user_job_ptr = previous_replaced_job200->user_input.user_job_ptr;
+
+ /** @note failure to 'copy to user' at this point must not free job200,
+ * and so no transaction rollback required in the U/K interface */
+
+ /* This does not cause job200 to free: */
+ user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED;
+ MALI_DEBUG_PRINT(5, ("subsystem_mali200_get_new_job_from_user: Job added, prev returned\n")) ;
+ }
+ else
+ {
+ /* This does not cause job200 to free: */
+ user_ptr_job_input->status = _MALI_UK_START_JOB_STARTED;
+ MALI_DEBUG_PRINT(5, ("subsystem_mali200_get_new_job_from_user: Job added\n")) ;
+ }
+
+function_exit:
+ if (_MALI_UK_START_JOB_NOT_STARTED_DO_REQUEUE == user_ptr_job_input->status
+ || _MALI_OSK_ERR_OK != err )
+ {
+ _mali_osk_free(job200);
+ }
+#if MALI_STATE_TRACKING
+ if (_MALI_UK_START_JOB_STARTED==user_ptr_job_input->status)
+ {
+ if(job)
+ {
+ job->job_nr=_mali_osk_atomic_inc_return(&session->jobs_received);
+ }
+ }
+#endif
+
+ MALI_ERROR(err);
+}
+
+/* This function is called from the ioctl function and should write the necessary data
+to userspace telling which job was finished and the status and debuginfo for this job.
+The function must also free and cleanup the input job object. */
+static void subsystem_mali200_return_job_to_user( mali_core_job * job, mali_subsystem_job_end_code end_status)
+{
+ mali200_job *job200;
+ _mali_uk_pp_job_finished_s * job_out;
+ _mali_uk_pp_start_job_s * job_input;
+ mali_core_session *session;
+
+ if (NULL == job)
+ {
+ MALI_DEBUG_PRINT(1, ("subsystem_mali200_return_job_to_user received a NULL ptr\n"));
+ return;
+ }
+
+ job200 = _MALI_OSK_CONTAINER_OF(job, mali200_job, embedded_core_job);
+
+ if (NULL == job200->notification_obj)
+ {
+ MALI_DEBUG_PRINT(1, ("Found job200 with NULL notification object, abandoning userspace sending\n"));
+ return;
+ }
+
+ job_out = job200->notification_obj->result_buffer;
+ job_input= &(job200->user_input);
+ session = job->session;
+
+ MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x OUTPUT to user. Runtime: %dus\n",
+ (u32)job200->user_input.user_job_ptr,
+ job->render_time_usecs)) ;
+
+ _mali_osk_memset(job_out, 0 , sizeof(_mali_uk_pp_job_finished_s));
+
+ job_out->user_job_ptr = job_input->user_job_ptr;
+
+ switch( end_status )
+ {
+ case JOB_STATUS_CONTINUE_RUN:
+ case JOB_STATUS_END_SUCCESS:
+ case JOB_STATUS_END_OOM:
+ case JOB_STATUS_END_ABORT:
+ case JOB_STATUS_END_TIMEOUT_SW:
+ case JOB_STATUS_END_HANG:
+ case JOB_STATUS_END_SEG_FAULT:
+ case JOB_STATUS_END_ILLEGAL_JOB:
+ case JOB_STATUS_END_UNKNOWN_ERR:
+ case JOB_STATUS_END_SHUTDOWN:
+ case JOB_STATUS_END_SYSTEM_UNUSABLE:
+ job_out->status = (mali_subsystem_job_end_code) end_status;
+ break;
+
+ default:
+ job_out->status = JOB_STATUS_END_UNKNOWN_ERR ;
+ }
+ job_out->irq_status = job200->irq_status;
+ job_out->perf_counter0 = job200->perf_counter0;
+ job_out->perf_counter1 = job200->perf_counter1;
+ job_out->render_time = job->render_time_usecs;
+
+#if defined(USING_MALI400_L2_CACHE)
+ job_out->perf_counter_l2_src0 = job200->perf_counter_l2_src0;
+ job_out->perf_counter_l2_src1 = job200->perf_counter_l2_src1;
+ job_out->perf_counter_l2_val0 = job200->perf_counter_l2_val0;
+ job_out->perf_counter_l2_val1 = job200->perf_counter_l2_val1;
+ job_out->perf_counter_l2_val0_raw = job200->perf_counter_l2_val0_raw;
+ job_out->perf_counter_l2_val1_raw = job200->perf_counter_l2_val1_raw;
+#endif
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_inc(&session->jobs_returned);
+#endif
+ _mali_osk_notification_queue_send( session->notification_queue, job200->notification_obj);
+ job200->notification_obj = NULL;
+
+ _mali_osk_free(job200);
+}
+
+static void subsystem_mali200_renderunit_delete(mali_core_renderunit * core)
+{
+ MALI_DEBUG_PRINT(5, ("Mali PP: mali200_renderunit_delete\n"));
+ _mali_osk_free(core);
+}
+
+static void mali200_reset_hard(struct mali_core_renderunit * core)
+{
+ const int reset_finished_loop_count = 15;
+ const u32 reset_wait_target_register = MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW;
+ const u32 reset_invalid_value = 0xC0FFE000;
+ const u32 reset_check_value = 0xC01A0000;
+ const u32 reset_default_value = 0;
+ int i;
+
+ MALI_DEBUG_PRINT(5, ("subsystem_mali200_renderunit_reset_core_hard called for core %s\n", core->description));
+
+ mali_core_renderunit_register_write(core, reset_wait_target_register, reset_invalid_value);
+
+ mali_core_renderunit_register_write(
+ core,
+ MALI200_REG_ADDR_MGMT_CTRL_MGMT,
+ MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);
+
+ for (i = 0; i < reset_finished_loop_count; i++)
+ {
+ mali_core_renderunit_register_write(core, reset_wait_target_register, reset_check_value);
+ if (reset_check_value == mali_core_renderunit_register_read(core, reset_wait_target_register))
+ {
+ MALI_DEBUG_PRINT(5, ("Reset loop exiting after %d iterations\n", i));
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (i == reset_finished_loop_count)
+ {
+ MALI_DEBUG_PRINT(1, ("The reset loop didn't work\n"));
+ }
+
+ mali_core_renderunit_register_write(core, reset_wait_target_register, reset_default_value); /* set it back to the default */
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
+}
+
+static void subsystem_mali200_renderunit_reset_core(struct mali_core_renderunit * core, mali_core_reset_style style)
+{
+ MALI_DEBUG_PRINT(5, ("Mali PP: renderunit_reset_core\n"));
+
+ switch (style)
+ {
+ case MALI_CORE_RESET_STYLE_RUNABLE:
+ mali200_reset(core);
+ break;
+ case MALI_CORE_RESET_STYLE_DISABLE:
+ mali200_raw_reset(core); /* do the raw reset */
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* then disable the IRQs */
+ break;
+ case MALI_CORE_RESET_STYLE_HARD:
+ mali200_reset_hard(core);
+ break;
+ default:
+ MALI_DEBUG_PRINT(1, ("Unknown reset type %d\n", style));
+ }
+}
+
+static void subsystem_mali200_renderunit_probe_core_irq_trigger(struct mali_core_renderunit* core)
+{
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG);
+ _mali_osk_mem_barrier();
+}
+
+static _mali_osk_errcode_t subsystem_mali200_renderunit_probe_core_irq_finished(struct mali_core_renderunit* core)
+{
+ u32 irq_readout;
+
+ irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+
+ if ( MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout )
+ {
+ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG);
+ _mali_osk_mem_barrier();
+ MALI_SUCCESS;
+ }
+
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+}
+
+_mali_osk_errcode_t _mali_ukk_pp_start_job( _mali_uk_pp_start_job_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_start_job(session, args);
+}
+
+_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_number_of_cores_get(session, &args->number_of_cores);
+}
+
+_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args )
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
+ MALI_CHECK_NON_NULL(session, _MALI_OSK_ERR_FAULT);
+ return mali_core_subsystem_ioctl_core_version_get(session, &args->version);
+}
+
+void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_s * args)
+{
+ mali_core_session * session;
+ MALI_DEBUG_ASSERT_POINTER(args);
+ if (NULL == args->ctx) return;
+ session = (mali_core_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_mali200_id);
+ if (NULL == session) return;
+ mali_core_subsystem_ioctl_abort_job(session, args->abort_id);
+
+}
+
+#if USING_MALI_PMM
+
+_mali_osk_errcode_t malipp_signal_power_up( u32 core_num, mali_bool queue_only )
+{
+ MALI_DEBUG_PRINT(4, ("Mali PP: signal power up core: %d - queue_only: %d\n", core_num, queue_only ));
+
+ return( mali_core_subsystem_signal_power_up( &subsystem_mali200, core_num, queue_only ) );
+}
+
+_mali_osk_errcode_t malipp_signal_power_down( u32 core_num, mali_bool immediate_only )
+{
+ MALI_DEBUG_PRINT(4, ("Mali PP: signal power down core: %d - immediate_only: %d\n", core_num, immediate_only ));
+
+ return( mali_core_subsystem_signal_power_down( &subsystem_mali200, core_num, immediate_only ) );
+}
+
+#endif
+
+#if MALI_STATE_TRACKING
+u32 mali200_subsystem_dump_state(char *buf, u32 size)
+{
+ return mali_core_renderunit_dump_state(&subsystem_mali200, buf, size);
+}
+#endif
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_common.h b/drivers/gpu/arm/mali/common/mali_kernel_common.h
new file mode 100644
index 00000000000..d9388ff18a2
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_common.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_COMMON_H__
+#define __MALI_KERNEL_COMMON_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
+extern int mali_debug_level;
+
+#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/mali/common/mali_kernel_core.c b/drivers/gpu/arm/mali/common/mali_kernel_core.c
new file mode 100644
index 00000000000..5e3626dece4
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_core.c
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_subsystem.h"
+#include "mali_kernel_mem.h"
+#include "mali_kernel_session_manager.h"
+#include "mali_kernel_pp.h"
+#include "mali_kernel_gp.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_ukk.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_rendercore.h"
+#if defined USING_MALI400_L2_CACHE
+#include "mali_kernel_l2_cache.h"
+#endif
+#if USING_MALI_PMM
+#include "mali_pmm.h"
+#endif /* USING_MALI_PMM */
+
+/* platform specific set up */
+#include "mali_platform.h"
+
+/* Initialized when this subsystem is initialized. This is determined by the
+ * position in subsystems[], and so the value used to initialize this is
+ * determined at compile time */
+static mali_kernel_subsystem_identifier mali_subsystem_core_id = -1;
+
+/** Pointer to table of resource definitions available to the Mali driver.
+ * _mali_osk_resources_init() sets up the pointer to this table.
+ */
+static _mali_osk_resource_t *arch_configuration = NULL;
+
+/** Number of resources initialized by _mali_osk_resources_init() */
+static u32 num_resources;
+
+static _mali_osk_errcode_t register_resources( _mali_osk_resource_t **arch_configuration, u32 num_resources );
+
+static _mali_osk_errcode_t initialize_subsystems(void);
+static void terminate_subsystems(void);
+
+static _mali_osk_errcode_t mali_kernel_subsystem_core_setup(mali_kernel_subsystem_identifier id);
+static void mali_kernel_subsystem_core_cleanup(mali_kernel_subsystem_identifier id);
+static _mali_osk_errcode_t mali_kernel_subsystem_core_system_info_fill(_mali_system_info* info);
+static _mali_osk_errcode_t mali_kernel_subsystem_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+
+static _mali_osk_errcode_t build_system_info(void);
+static void cleanup_system_info(_mali_system_info *cleanup);
+
+/**
+ * @brief handler for MEM_VALIDATION resources
+ *
+ * This resource handler is common to all memory systems. It provides a default
+ * means for validating requests to map in external memory via
+ * _mali_ukk_map_external_mem. In addition, if _mali_ukk_va_to_pa is
+ * implemented, then _mali_ukk_va_to_pa can make use of this MEM_VALIDATION
+ * resource.
+ *
+ * MEM_VALIDATION also provide a CPU physical to Mali physical address
+ * translation, for use by _mali_ukk_map_external_mem.
+ *
+ * @note MEM_VALIDATION resources are only to handle simple cases where a
+ * certain physical address range is allowed to be mapped in by any process,
+ * e.g. a framebuffer at a fixed location. If the implementor has more complex
+ * mapping requirements, then they must either:
+ * - implement their own memory validation function
+ * - or, integrate with UMP.
+ *
+ * @param resource The resource to handle (type MEM_VALIDATION)
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+static _mali_osk_errcode_t mali_kernel_core_resource_mem_validation(_mali_osk_resource_t * resource);
+
+/* MEM_VALIDATION handler state */
+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 */
+ s32 cpu_usage_adjust; /**< Offset to add to Mali Physical address to obtain CPU physical address */
+} _mali_mem_validation_t;
+
+#define INVALID_MEM 0xffffffff
+
+static _mali_mem_validation_t mem_validator = { INVALID_MEM, INVALID_MEM, -1 };
+
+static struct mali_kernel_subsystem mali_subsystem_core =
+{
+ mali_kernel_subsystem_core_setup, /* startup */
+ mali_kernel_subsystem_core_cleanup, /* shutdown */
+ NULL, /* load_complete */
+ mali_kernel_subsystem_core_system_info_fill, /* system_info_fill */
+ mali_kernel_subsystem_core_session_begin, /* session_begin */
+ NULL, /* session_end */
+ NULL, /* broadcast_notification */
+#if MALI_STATE_TRACKING
+ NULL, /* dump_state */
+#endif
+};
+
+static struct mali_kernel_subsystem * subsystems[] =
+{
+
+#if USING_MALI_PMM
+ /* The PMM must be initialized before any cores - including L2 cache */
+ &mali_subsystem_pmm,
+#endif
+
+ /* always included */
+ &mali_subsystem_memory,
+
+ /* The rendercore subsystem must be initialized before any subsystem based on the
+ * rendercores is started e.g. mali_subsystem_mali200 and mali_subsystem_gp2 */
+ &mali_subsystem_rendercore,
+
+ /* add reference to the subsystem */
+ &mali_subsystem_mali200,
+
+ /* add reference to the subsystem */
+ &mali_subsystem_gp2,
+
+#if defined USING_MALI400_L2_CACHE
+ &mali_subsystem_l2_cache,
+#endif
+
+ /* always included */
+ /* NOTE Keep the core entry at the tail of the list */
+ &mali_subsystem_core
+};
+
+#define SUBSYSTEMS_COUNT ( sizeof(subsystems) / sizeof(subsystems[0]) )
+
+/* Pointers to this type available as incomplete struct in mali_kernel_session_manager.h */
+struct mali_session_data
+{
+ void * subsystem_data[SUBSYSTEMS_COUNT];
+ _mali_osk_notification_queue_t * ioctl_queue;
+};
+
+static mali_kernel_resource_registrator resource_handler[RESOURCE_TYPE_COUNT] = { NULL, };
+
+/* system info variables */
+static _mali_osk_lock_t *system_info_lock = NULL;
+static _mali_system_info * system_info = NULL;
+static u32 system_info_size = 0;
+
+/* is called from OS specific driver entry point */
+_mali_osk_errcode_t mali_kernel_constructor( void )
+{
+ _mali_osk_errcode_t err;
+
+ err = mali_platform_init();
+ if (_MALI_OSK_ERR_OK != err) goto error1;
+
+ err = _mali_osk_init();
+ if (_MALI_OSK_ERR_OK != err) goto error2;
+
+ MALI_DEBUG_PRINT(2, ("\n"));
+ 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, ("Svn revision: %s\n", SVN_REV_STRING));
+
+ err = initialize_subsystems();
+ if (_MALI_OSK_ERR_OK != err) goto error3;
+
+ MALI_PRINT(("Mali device driver %s loaded\n", SVN_REV_STRING));
+
+ MALI_SUCCESS;
+
+error3:
+ MALI_PRINT(("Mali subsystems failed\n"));
+ _mali_osk_term();
+error2:
+ MALI_PRINT(("Mali device driver init failed\n"));
+ if (_MALI_OSK_ERR_OK != mali_platform_deinit())
+ {
+ MALI_PRINT(("Failed to deinit platform\n"));
+ }
+error1:
+ MALI_PRINT(("Failed to init platform\n"));
+ MALI_ERROR(err);
+}
+
+/* is called from OS specific driver exit point */
+void mali_kernel_destructor( void )
+{
+ MALI_DEBUG_PRINT(2, ("\n"));
+ MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION));
+#if USING_MALI_PMM
+ malipmm_force_powerup();
+#endif
+ terminate_subsystems(); /* subsystems are responsible for their registered resources */
+ _mali_osk_term();
+
+ if (_MALI_OSK_ERR_OK != mali_platform_deinit())
+ {
+ MALI_PRINT(("Failed to deinit platform\n"));
+ }
+ MALI_DEBUG_PRINT(2, ("Module unloaded.\n"));
+}
+
+_mali_osk_errcode_t register_resources( _mali_osk_resource_t **arch_configuration, u32 num_resources )
+{
+ _mali_osk_resource_t *arch_resource = *arch_configuration;
+ u32 i;
+#if USING_MALI_PMM
+ u32 is_pmu_first_resource = 1;
+#endif /* USING_MALI_PMM */
+
+ /* loop over arch configuration */
+ for (i = 0; i < num_resources; ++i, arch_resource++)
+ {
+ if ( (arch_resource->type >= RESOURCE_TYPE_FIRST) &&
+ (arch_resource->type < RESOURCE_TYPE_COUNT) &&
+ (NULL != resource_handler[arch_resource->type])
+ )
+ {
+#if USING_MALI_PMM
+ if((arch_resource->type != PMU) && (is_pmu_first_resource == 1))
+ {
+ _mali_osk_resource_t mali_pmu_virtual_resource;
+ mali_pmu_virtual_resource.type = PMU;
+ mali_pmu_virtual_resource.description = "Virtual PMU";
+ mali_pmu_virtual_resource.base = 0x00000000;
+ mali_pmu_virtual_resource.cpu_usage_adjust = 0;
+ mali_pmu_virtual_resource.size = 0;
+ mali_pmu_virtual_resource.irq = 0;
+ mali_pmu_virtual_resource.flags = 0;
+ mali_pmu_virtual_resource.mmu_id = 0;
+ mali_pmu_virtual_resource.alloc_order = 0;
+ MALI_CHECK_NO_ERROR(resource_handler[mali_pmu_virtual_resource.type](&mali_pmu_virtual_resource));
+ }
+ is_pmu_first_resource = 0;
+#endif /* USING_MALI_PMM */
+
+ MALI_CHECK_NO_ERROR(resource_handler[arch_resource->type](arch_resource));
+ /* the subsystem shutdown process will release all the resources already registered */
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ("No handler installed for resource %s, type %d\n", arch_resource->description, arch_resource->type));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t initialize_subsystems(void)
+{
+ int i, j;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; /* default error code */
+
+ MALI_CHECK_NON_NULL(system_info_lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0 ), _MALI_OSK_ERR_FAULT);
+
+ for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ {
+ if (NULL != subsystems[i]->startup)
+ {
+ /* the subsystem has a startup function defined */
+ err = subsystems[i]->startup(i); /* the subsystem identifier is the offset in our subsystems array */
+ if (_MALI_OSK_ERR_OK != err) goto cleanup;
+ }
+ }
+
+ for (j = 0; j < (int)SUBSYSTEMS_COUNT; ++j)
+ {
+ if (NULL != subsystems[j]->load_complete)
+ {
+ /* the subsystem has a load_complete function defined */
+ err = subsystems[j]->load_complete(j);
+ if (_MALI_OSK_ERR_OK != err) goto cleanup;
+ }
+ }
+
+ /* All systems loaded and resources registered */
+ /* Build system info */
+ if (_MALI_OSK_ERR_OK != build_system_info()) goto cleanup;
+
+ MALI_SUCCESS; /* all ok */
+
+cleanup:
+ /* i is index of subsystem which failed to start, all indices before that has to be shut down */
+ for (i = i - 1; i >= 0; --i)
+ {
+ /* the subsystem identifier is the offset in our subsystems array */
+ /* Call possible shutdown notficiation functions */
+ if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i);
+ }
+
+ _mali_osk_lock_term( system_info_lock );
+ MALI_ERROR(err); /* err is what the module which failed its startup returned, or the default */
+}
+
+static void terminate_subsystems(void)
+{
+ int i;
+ /* shut down subsystems in reverse order from startup */
+ for (i = SUBSYSTEMS_COUNT - 1; i >= 0; --i)
+ {
+ /* the subsystem identifier is the offset in our subsystems array */
+ if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i);
+ }
+ if (system_info_lock) _mali_osk_lock_term( system_info_lock );
+
+ /* Free _mali_system_info struct */
+ cleanup_system_info(system_info);
+}
+
+void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data)
+{
+ int i;
+
+ for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ {
+ if (NULL != subsystems[i]->broadcast_notification)
+ {
+ subsystems[i]->broadcast_notification(message, data);
+ }
+ }
+}
+
+static _mali_osk_errcode_t mali_kernel_subsystem_core_setup(mali_kernel_subsystem_identifier id)
+{
+ mali_subsystem_core_id = id;
+
+ /* Register our own resources */
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MEM_VALIDATION, mali_kernel_core_resource_mem_validation));
+
+ /* parse the arch resource definition and tell all the subsystems */
+ /* this is why the core subsystem has to be specified last in the subsystem array */
+ MALI_CHECK_NO_ERROR(_mali_osk_resources_init(&arch_configuration, &num_resources));
+
+ MALI_CHECK_NO_ERROR(register_resources(&arch_configuration, num_resources));
+
+ /* resource parsing succeeded and the subsystem have corretly accepted their resources */
+ MALI_SUCCESS;
+}
+
+static void mali_kernel_subsystem_core_cleanup(mali_kernel_subsystem_identifier id)
+{
+ _mali_osk_resources_term(&arch_configuration, num_resources);
+}
+
+static void cleanup_system_info(_mali_system_info *cleanup)
+{
+ _mali_core_info * current_core;
+ _mali_mem_info * current_mem;
+
+ /* delete all the core info structs */
+ while (NULL != cleanup->core_info)
+ {
+ current_core = cleanup->core_info;
+ cleanup->core_info = cleanup->core_info->next;
+ _mali_osk_free(current_core);
+ }
+
+ /* delete all the mem info struct */
+ while (NULL != cleanup->mem_info)
+ {
+ current_mem = cleanup->mem_info;
+ cleanup->mem_info = cleanup->mem_info->next;
+ _mali_osk_free(current_mem);
+ }
+
+ /* delete the system info struct itself */
+ _mali_osk_free(cleanup);
+}
+
+static _mali_osk_errcode_t build_system_info(void)
+{
+ unsigned int i;
+ int err = _MALI_OSK_ERR_FAULT;
+ _mali_system_info * new_info, * cleanup;
+ _mali_core_info * current_core;
+ _mali_mem_info * current_mem;
+ u32 new_size = 0;
+
+ /* create a new system info struct */
+ MALI_CHECK_NON_NULL(new_info = (_mali_system_info *)_mali_osk_malloc(sizeof(_mali_system_info)), _MALI_OSK_ERR_NOMEM);
+
+ _mali_osk_memset(new_info, 0, sizeof(_mali_system_info));
+
+ /* if an error happens during any of the system_info_fill calls cleanup the new info structs */
+ cleanup = new_info;
+
+ /* ask each subsystems to fill in their info */
+ for (i = 0; i < SUBSYSTEMS_COUNT; ++i)
+ {
+ if (NULL != subsystems[i]->system_info_fill)
+ {
+ err = subsystems[i]->system_info_fill(new_info);
+ if (_MALI_OSK_ERR_OK != err) goto error_exit;
+ }
+ }
+
+ /* building succeeded, calculate the size */
+
+ /* size needed of the system info struct itself */
+ new_size = sizeof(_mali_system_info);
+
+ /* size needed for the cores */
+ for (current_core = new_info->core_info; NULL != current_core; current_core = current_core->next)
+ {
+ new_size += sizeof(_mali_core_info);
+ }
+
+ /* size needed for the memory banks */
+ for (current_mem = new_info->mem_info; NULL != current_mem; current_mem = current_mem->next)
+ {
+ new_size += sizeof(_mali_mem_info);
+ }
+
+ /* lock system info access so a user wont't get a corrupted version */
+ _mali_osk_lock_wait( system_info_lock, _MALI_OSK_LOCKMODE_RW );
+
+ /* cleanup the old one */
+ cleanup = system_info;
+ /* set new info */
+ system_info = new_info;
+ system_info_size = new_size;
+
+ /* we're safe */
+ _mali_osk_lock_signal( system_info_lock, _MALI_OSK_LOCKMODE_RW );
+
+ /* ok result */
+ err = _MALI_OSK_ERR_OK;
+
+ /* we share the cleanup routine with the error case */
+error_exit:
+ if (NULL == cleanup) MALI_ERROR((_mali_osk_errcode_t)err); /* no cleanup needed, return what err contains */
+
+ /* cleanup */
+ cleanup_system_info(cleanup);
+
+ /* return whatever err is, we could end up here in both the error and success cases */
+ MALI_ERROR((_mali_osk_errcode_t)err);
+}
+
+_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_get_system_info_size(_mali_uk_get_system_info_size_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ args->size = system_info_size;
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args )
+{
+ _mali_core_info * current_core;
+ _mali_mem_info * current_mem;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+ void * current_write_pos, ** current_patch_pos;
+ u32 adjust_ptr_base;
+
+ /* check input */
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->system_info, _MALI_OSK_ERR_INVALID_ARGS);
+
+ /* lock the system info */
+ _mali_osk_lock_wait( system_info_lock, _MALI_OSK_LOCKMODE_RW );
+
+ /* first check size */
+ if (args->size < system_info_size) goto exit_when_locked;
+
+ /* we build a copy of system_info in the user space buffer specified by the user and
+ * patch up the pointers. The ukk_private members of _mali_uk_get_system_info_s may
+ * indicate a different base address for patching the pointers (normally the
+ * address of the provided system_info buffer would be used). This is helpful when
+ * the system_info buffer needs to get copied to user space and the pointers need
+ * to be in user space.
+ */
+ if (0 == args->ukk_private)
+ {
+ adjust_ptr_base = (u32)args->system_info;
+ }
+ else
+ {
+ adjust_ptr_base = args->ukk_private;
+ }
+
+ /* copy each struct into the buffer, and update its pointers */
+ current_write_pos = (void *)args->system_info;
+
+ /* first, the master struct */
+ _mali_osk_memcpy(current_write_pos, system_info, sizeof(_mali_system_info));
+
+ /* advance write pointer */
+ current_write_pos = (void *)((u32)current_write_pos + sizeof(_mali_system_info));
+
+ /* first we write the core info structs, patch starts at master's core_info pointer */
+ current_patch_pos = (void **)((u32)args->system_info + offsetof(_mali_system_info, core_info));
+
+ for (current_core = system_info->core_info; NULL != current_core; current_core = current_core->next)
+ {
+
+ /* patch the pointer pointing to this core */
+ *current_patch_pos = (void*)(adjust_ptr_base + ((u32)current_write_pos - (u32)args->system_info));
+
+ /* copy the core info */
+ _mali_osk_memcpy(current_write_pos, current_core, sizeof(_mali_core_info));
+
+ /* update patch pos */
+ current_patch_pos = (void **)((u32)current_write_pos + offsetof(_mali_core_info, next));
+
+ /* advance write pos in memory */
+ current_write_pos = (void *)((u32)current_write_pos + sizeof(_mali_core_info));
+ }
+ /* patching of last patch pos is not needed, since we wrote NULL there in the first place */
+
+ /* then we write the mem info structs, patch starts at master's mem_info pointer */
+ current_patch_pos = (void **)((u32)args->system_info + offsetof(_mali_system_info, mem_info));
+
+ for (current_mem = system_info->mem_info; NULL != current_mem; current_mem = current_mem->next)
+ {
+ /* patch the pointer pointing to this core */
+ *current_patch_pos = (void*)(adjust_ptr_base + ((u32)current_write_pos - (u32)args->system_info));
+
+ /* copy the core info */
+ _mali_osk_memcpy(current_write_pos, current_mem, sizeof(_mali_mem_info));
+
+ /* update patch pos */
+ current_patch_pos = (void **)((u32)current_write_pos + offsetof(_mali_mem_info, next));
+
+ /* advance write pos in memory */
+ current_write_pos = (void *)((u32)current_write_pos + sizeof(_mali_mem_info));
+ }
+ /* patching of last patch pos is not needed, since we wrote NULL there in the first place */
+
+ err = _MALI_OSK_ERR_OK;
+exit_when_locked:
+ _mali_osk_lock_signal( system_info_lock, _MALI_OSK_LOCKMODE_RW );
+ MALI_ERROR(err);
+}
+
+_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 = (_mali_osk_notification_queue_t *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_core_id);
+
+ /* 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 = (_mali_osk_notification_queue_t *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_core_id);
+
+ /* 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 */
+}
+
+static _mali_osk_errcode_t mali_kernel_subsystem_core_system_info_fill(_mali_system_info* info)
+{
+ MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS);
+
+ info->drivermode = _MALI_DRIVER_MODE_NORMAL;
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_kernel_subsystem_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
+{
+ MALI_CHECK_NON_NULL(slot, _MALI_OSK_ERR_INVALID_ARGS);
+ *slot = queue;
+ MALI_SUCCESS;
+}
+
+/* MEM_VALIDATION resource handler */
+static _mali_osk_errcode_t mali_kernel_core_resource_mem_validation(_mali_osk_resource_t * resource)
+{
+ /* Check that no other MEM_VALIDATION resources exist */
+ MALI_CHECK( ((u32)-1) == mem_validator.phys_base, _MALI_OSK_ERR_FAULT );
+
+ /* Check restrictions on page alignment */
+ MALI_CHECK( 0 == (resource->base & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
+ MALI_CHECK( 0 == (resource->size & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
+ MALI_CHECK( 0 == (resource->cpu_usage_adjust & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
+
+ mem_validator.phys_base = resource->base;
+ mem_validator.size = resource->size;
+ mem_validator.cpu_usage_adjust = resource->cpu_usage_adjust;
+ MALI_DEBUG_PRINT( 2, ("Memory Validator '%s' installed for Mali physical address base==0x%08X, size==0x%08X, cpu_adjust==0x%08X\n",
+ resource->description, mem_validator.phys_base, mem_validator.size, mem_validator.cpu_usage_adjust ));
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_kernel_core_translate_cpu_to_mali_phys_range( u32 *phys_base, u32 size )
+{
+ u32 mali_phys_base;
+
+ mali_phys_base = *phys_base - mem_validator.cpu_usage_adjust;
+
+ MALI_CHECK( 0 == ( mali_phys_base & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
+ MALI_CHECK( 0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)), _MALI_OSK_ERR_FAULT );
+
+ MALI_CHECK_NO_ERROR( mali_kernel_core_validate_mali_phys_range( mali_phys_base, size ) );
+
+ *phys_base = mali_phys_base;
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_kernel_core_validate_mali_phys_range( u32 phys_base, u32 size )
+{
+ MALI_CHECK_GOTO( 0 == ( phys_base & (~_MALI_OSK_CPU_PAGE_MASK)), failure );
+ MALI_CHECK_GOTO( 0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK)), failure );
+
+ if ( phys_base >= mem_validator.phys_base
+ && (phys_base + size) >= mem_validator.phys_base
+ && phys_base <= (mem_validator.phys_base + mem_validator.size)
+ && (phys_base + size) <= (mem_validator.phys_base + mem_validator.size) )
+ {
+ MALI_SUCCESS;
+ }
+
+ failure:
+ MALI_PRINTF( ("*******************************************************************************\n") );
+ MALI_PRINTF( ("MALI PHYSICAL RANGE VALIDATION ERROR!\n") );
+ MALI_PRINTF( ("\n") );
+ MALI_PRINTF( ("We failed to validate a Mali-Physical range that the user-side wished to map in\n") );
+ MALI_PRINTF( ("\n") );
+ MALI_PRINTF( ("It is likely that the user-side wished to do Direct Rendering, but a suitable\n") );
+ MALI_PRINTF( ("address range validation mechanism has not been correctly setup\n") );
+ MALI_PRINTF( ("\n") );
+ MALI_PRINTF( ("The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_base, size) );
+ MALI_PRINTF( ("\n") );
+ MALI_PRINTF( ("Please refer to the ARM Mali Software Integration Guide for more information.\n") );
+ MALI_PRINTF( ("\n") );
+ MALI_PRINTF( ("*******************************************************************************\n") );
+
+ MALI_ERROR( _MALI_OSK_ERR_FAULT );
+}
+
+
+_mali_osk_errcode_t _mali_kernel_core_register_resource_handler(_mali_osk_resource_type_t type, mali_kernel_resource_registrator handler)
+{
+ MALI_CHECK(type < RESOURCE_TYPE_COUNT, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_DEBUG_ASSERT(NULL == resource_handler[type]); /* A handler for resource already exists */
+ resource_handler[type] = handler;
+ MALI_SUCCESS;
+}
+
+void * mali_kernel_session_manager_slot_get(struct mali_session_data * session_data, int id)
+{
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+ if(id >= SUBSYSTEMS_COUNT) { MALI_DEBUG_PRINT(3, ("mali_kernel_session_manager_slot_get: id %d out of range\n", id)); return NULL; }
+
+ if (NULL == session_data) { MALI_DEBUG_PRINT(3, ("mali_kernel_session_manager_slot_get: got NULL session data\n")); return NULL; }
+ return session_data->subsystem_data[id];
+}
+
+_mali_osk_errcode_t _mali_ukk_open(void **context)
+{
+ int i;
+ _mali_osk_errcode_t err;
+ struct mali_session_data * session_data;
+
+ /* allocated struct to track this session */
+ session_data = (struct mali_session_data *)_mali_osk_malloc(sizeof(struct mali_session_data));
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_NOMEM);
+
+ _mali_osk_memset(session_data->subsystem_data, 0, sizeof(session_data->subsystem_data));
+
+ /* create a response queue for this session */
+ session_data->ioctl_queue = _mali_osk_notification_queue_init();
+ if (NULL == session_data->ioctl_queue)
+ {
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ MALI_DEBUG_PRINT(3, ("Session starting\n"));
+
+ /* call session_begin on all subsystems */
+ for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ {
+ if (NULL != subsystems[i]->session_begin)
+ {
+ /* subsystem has a session_begin */
+ err = subsystems[i]->session_begin(session_data, &session_data->subsystem_data[i], session_data->ioctl_queue);
+ MALI_CHECK_GOTO(err == _MALI_OSK_ERR_OK, cleanup);
+ }
+ }
+
+ *context = (void*)session_data;
+
+ MALI_DEBUG_PRINT(3, ("Session started\n"));
+ MALI_SUCCESS;
+
+cleanup:
+ MALI_DEBUG_PRINT(2, ("Session startup failed\n"));
+ /* i is index of subsystem which failed session begin, all indices before that has to be ended */
+ /* end subsystem sessions in the reverse order they where started in */
+ for (i = i - 1; i >= 0; --i)
+ {
+ if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]);
+ }
+
+ _mali_osk_notification_queue_term(session_data->ioctl_queue);
+ _mali_osk_free(session_data);
+
+ /* return what the subsystem which failed session start returned */
+ MALI_ERROR(err);
+}
+
+_mali_osk_errcode_t _mali_ukk_close(void **context)
+{
+ int i;
+ struct mali_session_data * session_data;
+
+ MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)*context;
+
+ MALI_DEBUG_PRINT(2, ("Session ending\n"));
+
+ /* end subsystem sessions in the reverse order they where started in */
+ for (i = SUBSYSTEMS_COUNT - 1; i >= 0; --i)
+ {
+ if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]);
+ }
+
+ _mali_osk_notification_queue_term(session_data->ioctl_queue);
+ _mali_osk_free(session_data);
+
+ *context = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Session has ended\n"));
+
+ MALI_SUCCESS;
+}
+
+#if USING_MALI_PMM
+
+_mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool queue_only )
+{
+ switch( core )
+ {
+ case MALI_PMM_CORE_GP:
+ MALI_CHECK_NO_ERROR(maligp_signal_power_up(queue_only));
+ break;
+#if defined USING_MALI400_L2_CACHE
+ case MALI_PMM_CORE_L2:
+ if( !queue_only )
+ {
+ /* Enable L2 cache due to power up */
+ mali_kernel_l2_cache_do_enable();
+
+ /* Invalidate the cache on power up */
+ MALI_DEBUG_PRINT(5, ("L2 Cache: Invalidate all\n"));
+ MALI_CHECK_NO_ERROR(mali_kernel_l2_cache_invalidate_all());
+ }
+ break;
+#endif
+ case MALI_PMM_CORE_PP0:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_up(0, queue_only));
+ break;
+ case MALI_PMM_CORE_PP1:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_up(1, queue_only));
+ break;
+ case MALI_PMM_CORE_PP2:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_up(2, queue_only));
+ break;
+ case MALI_PMM_CORE_PP3:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_up(3, queue_only));
+ break;
+ default:
+ /* Unknown core */
+ MALI_DEBUG_PRINT_ERROR( ("Unknown core signalled with power up: %d\n", core) );
+ MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS );
+ }
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_bool immediate_only )
+{
+ switch( core )
+ {
+ case MALI_PMM_CORE_GP:
+ MALI_CHECK_NO_ERROR(maligp_signal_power_down(immediate_only));
+ break;
+#if defined USING_MALI400_L2_CACHE
+ case MALI_PMM_CORE_L2:
+ /* Nothing to do */
+ break;
+#endif
+ case MALI_PMM_CORE_PP0:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_down(0, immediate_only));
+ break;
+ case MALI_PMM_CORE_PP1:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_down(1, immediate_only));
+ break;
+ case MALI_PMM_CORE_PP2:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_down(2, immediate_only));
+ break;
+ case MALI_PMM_CORE_PP3:
+ MALI_CHECK_NO_ERROR(malipp_signal_power_down(3, immediate_only));
+ break;
+ default:
+ /* Unknown core */
+ MALI_DEBUG_PRINT_ERROR( ("Unknown core signalled with power down: %d\n", core) );
+ MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS );
+ }
+
+ MALI_SUCCESS;
+}
+
+#endif
+
+
+#if MALI_STATE_TRACKING
+u32 _mali_kernel_core_dump_state(char* buf, u32 size)
+{
+ int i, n;
+ char *original_buf = buf;
+ for (i = 0; i < SUBSYSTEMS_COUNT; ++i)
+ {
+ if (NULL != subsystems[i]->dump_state)
+ {
+ n = subsystems[i]->dump_state(buf, size);
+ size -= n;
+ buf += n;
+ }
+ }
+#if USING_MALI_PMM
+ n = mali_pmm_dump_os_thread_state(buf, size);
+ size -= n;
+ buf += n;
+#endif
+ /* Return number of bytes written to buf */
+ return (u32)(buf - original_buf);
+}
+#endif
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_core.h b/drivers/gpu/arm/mali/common/mali_kernel_core.h
new file mode 100644
index 00000000000..b2fc3f0e388
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_core.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_CORE_H__
+#define __MALI_KERNEL_CORE_H__
+
+#include "mali_osk.h"
+
+#if USING_MALI_PMM
+#include "mali_ukk.h"
+#include "mali_pmm.h"
+#include "mali_pmm_system.h"
+#endif
+
+_mali_osk_errcode_t mali_kernel_constructor( void );
+void mali_kernel_destructor( void );
+
+/**
+ * @brief Tranlate CPU physical to Mali physical addresses.
+ *
+ * This function is used to convert CPU physical addresses to Mali Physical
+ * addresses, such that _mali_ukk_map_external_mem may be used to map them
+ * into Mali. This will be used by _mali_ukk_va_to_mali_pa.
+ *
+ * This function only supports physically contiguous regions.
+ *
+ * A default implementation is provided, which uses a registered MEM_VALIDATION
+ * resource to do a static translation. Only an address range which will lie
+ * in the range specified by MEM_VALIDATION will be successfully translated.
+ *
+ * If a more complex, or non-static translation is required, then the
+ * implementor has the following options:
+ * - Rewrite this function to provide such a translation
+ * - Integrate the provider of the memory with UMP.
+ *
+ * @param[in,out] phys_base pointer to the page-aligned base address of the
+ * physical range to be translated
+ *
+ * @param[in] size size of the address range to be translated, which must be a
+ * multiple of the physical page size.
+ *
+ * @return on success, _MALI_OSK_ERR_OK and *phys_base is translated. If the
+ * cpu physical address range is not in the valid range, then a suitable
+ * _mali_osk_errcode_t error.
+ *
+ */
+_mali_osk_errcode_t mali_kernel_core_translate_cpu_to_mali_phys_range( u32 *phys_base, u32 size );
+
+
+/**
+ * @brief Validate a Mali physical address range.
+ *
+ * This function is used to ensure that an address range passed to
+ * _mali_ukk_map_external_mem is allowed to be mapped into Mali.
+ *
+ * This function only supports physically contiguous regions.
+ *
+ * A default implementation is provided, which uses a registered MEM_VALIDATION
+ * resource to do a static translation. Only an address range which will lie
+ * in the range specified by MEM_VALIDATION will be successfully validated.
+ *
+ * If a more complex, or non-static validation is required, then the
+ * implementor has the following options:
+ * - Rewrite this function to provide such a validation
+ * - Integrate the provider of the memory with UMP.
+ *
+ * @param phys_base page-aligned base address of the Mali physical range to be
+ * validated.
+ *
+ * @param size size of the address range to be validated, which must be a
+ * multiple of the physical page size.
+ *
+ * @return _MALI_OSK_ERR_OK if the Mali physical range is valid. Otherwise, a
+ * suitable _mali_osk_errcode_t error.
+ *
+ */
+_mali_osk_errcode_t mali_kernel_core_validate_mali_phys_range( u32 phys_base, u32 size );
+
+#if USING_MALI_PMM
+/**
+ * @brief Signal a power up on a Mali core.
+ *
+ * This function flags a core as powered up.
+ * For PP and GP cores it calls functions that move the core from a power off
+ * queue into the idle queue ready to run jobs. It also tries to schedule any
+ * pending jobs to run on it.
+ *
+ * This function will fail if the core is not powered off - either running or
+ * already idle.
+ *
+ * @param core The PMM core id to power up.
+ * @param queue_only When MALI_TRUE only re-queue the core - do not reset.
+ *
+ * @return _MALI_OSK_ERR_OK if the core has been powered up. Otherwise a
+ * suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool queue_only );
+
+/**
+ * @brief Signal a power down on a Mali core.
+ *
+ * This function flags a core as powered down.
+ * For PP and GP cores it calls functions that move the core from an idle
+ * queue into the power off queue.
+ *
+ * This function will fail if the core is not idle - either running or
+ * already powered down.
+ *
+ * @param core The PMM core id to power up.
+ * @param immediate_only Do not set the core to pending power down if it can't
+ * power down immediately
+ *
+ * @return _MALI_OSK_ERR_OK if the core has been powered up. Otherwise a
+ * suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_bool immediate_only );
+
+#endif
+
+/**
+ * Flag to indicate whether or not mali_benchmark is turned on.
+ */
+extern int mali_benchmark;
+
+
+#endif /* __MALI_KERNEL_CORE_H__ */
+
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.c b/drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.c
new file mode 100644
index 00000000000..2ea2d3d319e
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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)
+ {
+#if !USING_MMU
+ map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 20);
+#else
+ map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 116);
+#endif
+ 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_lock_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_lock_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_lock_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_lock_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_lock_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_lock_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_lock_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_lock_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_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+ MALI_ERROR(result);
+}
+
+void mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor)
+{
+ _mali_osk_lock_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_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+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/mali/common/mali_kernel_descriptor_mapping.h b/drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.h
new file mode 100644
index 00000000000..b02f16fbeb5
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_descriptor_mapping.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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_lock_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
+ */
+void mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor);
+
+#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_gp.h b/drivers/gpu/arm/mali/common/mali_kernel_gp.h
new file mode 100644
index 00000000000..ecd10e84d40
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_gp.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_GP2_H__
+#define __MALI_KERNEL_GP2_H__
+
+extern struct mali_kernel_subsystem mali_subsystem_gp2;
+
+#if USING_MALI_PMM
+_mali_osk_errcode_t maligp_signal_power_up( mali_bool queue_only );
+_mali_osk_errcode_t maligp_signal_power_down( mali_bool immediate_only );
+#endif
+
+#endif /* __MALI_KERNEL_GP2_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c b/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c
new file mode 100644
index 00000000000..7177979ee64
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+
+#include "mali_kernel_core.h"
+#include "mali_kernel_pp.h"
+#include "mali_kernel_subsystem.h"
+#include "regs/mali_200_regs.h"
+#include "mali_kernel_rendercore.h"
+#include "mali_kernel_l2_cache.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_STATUS = 0x0002,
+ /*unused = 0x0003 */
+ MALI400_L2_CACHE_REGISTER_COMMAND = 0x0004, /**< Misc cache commands, e.g. clear */
+ MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0005,
+ MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0006, /**< Limit of outstanding read requests */
+ MALI400_L2_CACHE_REGISTER_ENABLE = 0x0007, /**< Enable misc cache features */
+ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0008,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0009,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x000A,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x000B,
+} 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;
+
+
+/**
+ * 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
+ */
+typedef struct mali_kernel_l2_cache_core
+{
+ unsigned long base; /**< Physical address of the registers */
+ mali_io_address mapped_registers; /**< Virtual mapping of the registers */
+ u32 mapping_size; /**< Size of registers in bytes */
+ _mali_osk_list_t list; /**< Used to link multiple cache cores into a list */
+ _mali_osk_lock_t *lock; /**< Serialize all L2 cache commands */
+} mali_kernel_l2_cache_core;
+
+
+#define MALI400_L2_MAX_READS_DEFAULT 0x1C
+
+int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT;
+
+
+/**
+ * Mali L2 cache subsystem startup function
+ * Called by the driver core when the driver is loaded.
+ *
+ * @param id Identifier assigned by the core to the L2 cache subsystem
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_l2_cache_initialize(mali_kernel_subsystem_identifier id);
+
+/**
+ * Mali L2 cache subsystem shutdown function
+ * Called by the driver core when the driver is unloaded.
+ * Cleans up
+ * @param id Identifier assigned by the core to the L2 cache subsystem
+ */
+static void mali_l2_cache_terminate(mali_kernel_subsystem_identifier id);
+
+/**
+ * L2 cache subsystem complete notification function.
+ * Called by the driver core when all drivers have loaded and all resources has been registered
+ * @param id Identifier assigned by the core to the L2 cache subsystem
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_l2_cache_load_complete(mali_kernel_subsystem_identifier id);
+
+/**
+ * Mali L2 cache subsystem's notification handler for a Mali L2 cache resource instances.
+ * Registered with the core during startup.
+ * Called by the core for each Mali L2 cache described in the active architecture's config.h file.
+ * @param resource The resource to handle (type MALI400L2)
+ * @return 0 if the Mali L2 cache was found and initialized, negative on error
+ */
+static _mali_osk_errcode_t mali_l2_cache_core_create(_mali_osk_resource_t * resource);
+
+/**
+ * Write to a L2 cache register
+ * Writes the given value to the specified register
+ * @param unit The L2 cache to write to
+ * @param reg The register to write to
+ * @param val The value to write to the register
+ */
+static void mali_l2_cache_register_write(mali_kernel_l2_cache_core * unit, mali_l2_cache_register reg, u32 val);
+
+
+
+/**
+ * Invalidate specified L2 cache
+ * @param cache The L2 cache to invalidate
+ * @return 0 if Mali L2 cache was successfully invalidated, otherwise error
+ */
+static _mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all_cache(mali_kernel_l2_cache_core *cache);
+
+
+/*
+ The fixed Mali L2 cache system's mali subsystem interface implementation.
+ We currently handle module and session life-time management.
+*/
+struct mali_kernel_subsystem mali_subsystem_l2_cache =
+{
+ mali_l2_cache_initialize, /**< startup */
+ mali_l2_cache_terminate, /**< shutdown */
+ mali_l2_cache_load_complete, /**< load_complete */
+ NULL, /**< system_info_fill */
+ NULL, /**< session_begin */
+ NULL, /**< session_end */
+ NULL, /**< broadcast_notification */
+#if MALI_STATE_TRACKING
+ NULL, /**< dump_state */
+#endif
+};
+
+
+
+static _MALI_OSK_LIST_HEAD(caches_head);
+
+
+
+
+/* called during module init */
+static _mali_osk_errcode_t mali_l2_cache_initialize(mali_kernel_subsystem_identifier id)
+{
+ _mali_osk_errcode_t err;
+
+ MALI_IGNORE( id );
+
+ MALI_DEBUG_PRINT(2, ( "Mali L2 cache system initializing\n"));
+
+ _MALI_OSK_INIT_LIST_HEAD(&caches_head);
+
+ /* This will register the function for adding Mali L2 cache cores to the subsystem */
+ err = _mali_kernel_core_register_resource_handler(MALI400L2, mali_l2_cache_core_create);
+
+ MALI_ERROR(err);
+}
+
+
+
+/* called if/when our module is unloaded */
+static void mali_l2_cache_terminate(mali_kernel_subsystem_identifier id)
+{
+ mali_kernel_l2_cache_core * cache, *temp_cache;
+
+ MALI_DEBUG_PRINT(2, ( "Mali L2 cache system terminating\n"));
+
+ /* loop over all L2 cache units and shut them down */
+ _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list )
+ {
+ /* reset to defaults */
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT);
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT);
+
+ /* remove from the list of cacges on the system */
+ _mali_osk_list_del( &cache->list );
+
+ /* release resources */
+ _mali_osk_mem_unmapioregion( cache->base, cache->mapping_size, cache->mapped_registers );
+ _mali_osk_mem_unreqregion( cache->base, cache->mapping_size );
+ _mali_osk_lock_term( cache->lock );
+ _mali_osk_free( cache );
+
+ #if USING_MALI_PMM
+ /* Unregister the L2 cache with the PMM */
+ malipmm_core_unregister( MALI_PMM_CORE_L2 );
+ #endif
+ }
+}
+
+static _mali_osk_errcode_t mali_l2_cache_core_create(_mali_osk_resource_t * resource)
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT ;
+ mali_kernel_l2_cache_core * cache = NULL;
+
+ MALI_DEBUG_PRINT(2, ( "Creating Mali L2 cache: %s\n", resource->description));
+
+#if USING_MALI_PMM
+ /* Register the L2 cache with the PMM */
+ err = malipmm_core_register( MALI_PMM_CORE_L2 );
+ if( _MALI_OSK_ERR_OK != err )
+ {
+ MALI_DEBUG_PRINT(1, ( "Failed to register L2 cache unit with PMM"));
+ return err;
+ }
+#endif
+
+ err = _mali_osk_mem_reqregion( resource->base, MALI400_L2_CACHE_REGISTERS_SIZE, resource->description);
+
+ MALI_CHECK_GOTO( _MALI_OSK_ERR_OK == err, err_cleanup_requestmem_failed);
+
+ /* Reset error that might be passed out */
+ err = _MALI_OSK_ERR_FAULT;
+
+ cache = _mali_osk_malloc(sizeof(mali_kernel_l2_cache_core));
+
+ MALI_CHECK_GOTO( NULL != cache, err_cleanup);
+
+ cache->lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 104 );
+
+ MALI_CHECK_GOTO( NULL != cache->lock, err_cleanup);
+
+ /* basic setup */
+ _MALI_OSK_INIT_LIST_HEAD(&cache->list);
+
+ cache->base = resource->base;
+ cache->mapping_size = MALI400_L2_CACHE_REGISTERS_SIZE;
+
+ /* map the registers */
+ cache->mapped_registers = _mali_osk_mem_mapioregion( cache->base, cache->mapping_size, resource->description );
+
+ MALI_CHECK_GOTO( NULL != cache->mapped_registers, err_cleanup);
+
+ /* Invalidate cache (just to keep it in a known state at startup) */
+ err = mali_kernel_l2_cache_invalidate_all_cache(cache);
+
+ MALI_CHECK_GOTO( _MALI_OSK_ERR_OK == err, err_cleanup);
+
+ /* add to our list of L2 caches */
+ _mali_osk_list_add( &cache->list, &caches_head );
+
+ MALI_SUCCESS;
+
+err_cleanup:
+ /* This cleanup used when resources have been requested successfully */
+
+ if ( NULL != cache )
+ {
+ if (NULL != cache->mapped_registers)
+ {
+ _mali_osk_mem_unmapioregion( cache->base, cache->mapping_size, cache->mapped_registers);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ( "Failed to map Mali L2 cache registers at 0x%08lX\n", cache->base));
+ }
+
+ if( NULL != cache->lock )
+ {
+ _mali_osk_lock_term( cache->lock );
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ( "Failed to allocate a lock for handling a L2 cache unit"));
+ }
+
+ _mali_osk_free( cache );
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ( "Failed to allocate memory for handling a L2 cache unit"));
+ }
+
+ /* A call is to request region, so this must always be reversed */
+ _mali_osk_mem_unreqregion( resource->base, MALI400_L2_CACHE_REGISTERS_SIZE);
+#if USING_MALI_PMM
+ malipmm_core_unregister( MALI_PMM_CORE_L2 );
+#endif
+ return err;
+
+err_cleanup_requestmem_failed:
+ MALI_DEBUG_PRINT(1, ("Failed to request Mali L2 cache '%s' register address space at (0x%08X - 0x%08X)\n",
+ resource->description, resource->base, resource->base + MALI400_L2_CACHE_REGISTERS_SIZE - 1) );
+#if USING_MALI_PMM
+ malipmm_core_unregister( MALI_PMM_CORE_L2 );
+#endif
+ return err;
+
+}
+
+
+static void mali_l2_cache_register_write(mali_kernel_l2_cache_core * unit, mali_l2_cache_register reg, u32 val)
+{
+ _mali_osk_mem_iowrite32(unit->mapped_registers, (u32)reg * sizeof(u32), val);
+}
+
+
+static u32 mali_l2_cache_register_read(mali_kernel_l2_cache_core * unit, mali_l2_cache_register reg)
+{
+ return _mali_osk_mem_ioread32(unit->mapped_registers, (u32)reg * sizeof(u32));
+}
+
+void mali_kernel_l2_cache_do_enable(void)
+{
+ mali_kernel_l2_cache_core * cache, *temp_cache;
+
+ /* loop over all L2 cache units and enable them*/
+ _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
+ {
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE);
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads);
+ }
+}
+
+
+static _mali_osk_errcode_t mali_l2_cache_load_complete(mali_kernel_subsystem_identifier id)
+{
+ mali_kernel_l2_cache_do_enable();
+ MALI_DEBUG_PRINT(2, ( "Mali L2 cache system load complete\n"));
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_kernel_l2_cache_send_command(mali_kernel_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_osk_lock_wait(cache->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* First, wait for L2 cache command handler to go idle */
+
+ for (i = 0; i < loop_count; i++)
+ {
+ if (!(_mali_osk_mem_ioread32(cache->mapped_registers , (u32)MALI400_L2_CACHE_REGISTER_STATUS * sizeof(u32)) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY))
+ {
+ break;
+ }
+ }
+
+ if (i == loop_count)
+ {
+ _mali_osk_lock_signal(cache->lock, _MALI_OSK_LOCKMODE_RW);
+ 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_l2_cache_register_write(cache, reg, val);
+
+ _mali_osk_lock_signal(cache->lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_SUCCESS;
+}
+
+
+static _mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all_cache(mali_kernel_l2_cache_core *cache)
+{
+ return mali_kernel_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
+}
+
+_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all(void)
+{
+ mali_kernel_l2_cache_core * cache, *temp_cache;
+
+ /* loop over all L2 cache units and invalidate them */
+
+ _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
+ {
+ MALI_CHECK_NO_ERROR( mali_kernel_l2_cache_invalidate_all_cache(cache) );
+ }
+
+ MALI_SUCCESS;
+}
+
+
+static _mali_osk_errcode_t mali_kernel_l2_cache_invalidate_page_cache(mali_kernel_l2_cache_core *cache, u32 page)
+{
+ return mali_kernel_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, page);
+}
+
+_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_page(u32 page)
+{
+ mali_kernel_l2_cache_core * cache, *temp_cache;
+
+ /* loop over all L2 cache units and invalidate them */
+
+ _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
+ {
+ MALI_CHECK_NO_ERROR( mali_kernel_l2_cache_invalidate_page_cache(cache, page) );
+ }
+
+ MALI_SUCCESS;
+}
+
+
+void mali_kernel_l2_cache_set_perf_counters(u32 src0, u32 src1, int force_reset)
+{
+ mali_kernel_l2_cache_core * cache, *temp_cache;
+ int reset0 = force_reset;
+ int reset1 = force_reset;
+ MALI_DEBUG_CODE(
+ int changed0 = 0;
+ int changed1 = 0;
+ )
+
+ /* loop over all L2 cache units and activate the counters on them */
+ _MALI_OSK_LIST_FOREACHENTRY(cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
+ {
+ u32 cur_src0 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0);
+ u32 cur_src1 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1);
+
+ if (src0 != cur_src0)
+ {
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, src0);
+ MALI_DEBUG_CODE(changed0 = 1;)
+ reset0 = 1;
+ }
+
+ if (src1 != cur_src1)
+ {
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, src1);
+ MALI_DEBUG_CODE(changed1 = 1;)
+ reset1 = 1;
+ }
+
+ if (reset0)
+ {
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0, 0);
+ }
+
+ if (reset1)
+ {
+ mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1, 0);
+ }
+
+ MALI_DEBUG_PRINT(5, ("L2 cache counters set: SRC0=%u, CHANGED0=%d, RESET0=%d, SRC1=%u, CHANGED1=%d, RESET1=%d\n",
+ src0, changed0, reset0,
+ src1, changed1, reset1));
+ }
+}
+
+
+void mali_kernel_l2_cache_get_perf_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1)
+{
+ mali_kernel_l2_cache_core * cache, *temp_cache;
+ int first_time = 1;
+ *src0 = 0;
+ *src1 = 0;
+ *val0 = 0;
+ *val1 = 0;
+
+ /* loop over all L2 cache units and read the counters */
+ _MALI_OSK_LIST_FOREACHENTRY(cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list)
+ {
+ u32 cur_src0 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0);
+ u32 cur_src1 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1);
+ u32 cur_val0 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0);
+ u32 cur_val1 = mali_l2_cache_register_read(cache, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1);
+
+ MALI_DEBUG_PRINT(5, ("L2 cache counters get: SRC0=%u, VAL0=%u, SRC1=%u, VAL1=%u\n", cur_src0, cur_val0, cur_src1, cur_val1));
+
+ /* Only update the counter source once, with the value from the first L2 cache unit. */
+ if (first_time)
+ {
+ *src0 = cur_src0;
+ *src1 = cur_src1;
+ first_time = 0;
+ }
+
+ /* Bail out if the L2 cache units have different counters set. */
+ if (*src0 == cur_src0 && *src1 == cur_src1)
+ {
+ *val0 += cur_val0;
+ *val1 += cur_val1;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ("Warning: Mali L2 caches has different performance counters set, not retrieving data\n"));
+ }
+ }
+}
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.h b/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.h
new file mode 100644
index 00000000000..1588850c1c7
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_L2_CACHE_H__
+#define __MALI_KERNEL_L2_CACHE_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_subsystem.h"
+extern struct mali_kernel_subsystem mali_subsystem_l2_cache;
+
+_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_all(void);
+_mali_osk_errcode_t mali_kernel_l2_cache_invalidate_page(u32 page);
+
+void mali_kernel_l2_cache_do_enable(void);
+void mali_kernel_l2_cache_set_perf_counters(u32 src0, u32 src1, int force_reset);
+void mali_kernel_l2_cache_get_perf_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1);
+
+#endif /* __MALI_KERNEL_L2_CACHE_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem.h b/drivers/gpu/arm/mali/common/mali_kernel_mem.h
new file mode 100644
index 00000000000..dddf1622331
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_mem.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_MEM_H__
+#define __MALI_KERNEL_MEM_H__
+
+#include "mali_kernel_subsystem.h"
+extern struct mali_kernel_subsystem mali_subsystem_memory;
+
+#endif /* __MALI_KERNEL_MEM_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c b/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c
new file mode 100644
index 00000000000..49190db7ada
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c
@@ -0,0 +1,1426 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_core.h"
+#include "mali_kernel_subsystem.h"
+#include "mali_kernel_mem.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_kernel_session_manager.h"
+
+/* kernel side OS functions and user-kernel interface */
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_osk_list.h"
+#include "mali_ukk.h"
+
+#ifdef _MALI_OSK_SPECIFIC_INDIRECT_MMAP
+#include "mali_osk_indir_mmap.h"
+#endif
+
+#error Support for non-MMU builds is no longer supported and is planned for removal.
+
+/**
+ * Minimum memory allocation size
+ */
+#define MIN_BLOCK_SIZE (1024*1024UL)
+
+/**
+ * Per-session memory descriptor mapping table sizes
+ */
+#define MALI_MEM_DESCRIPTORS_INIT 64
+#define MALI_MEM_DESCRIPTORS_MAX 4096
+
+/**
+ * Enum uses to store multiple fields in one u32 to keep the memory block struct small
+ */
+enum MISC_SHIFT { MISC_SHIFT_FREE = 0, MISC_SHIFT_ORDER = 1, MISC_SHIFT_TOPLEVEL = 6 };
+enum MISC_MASK { MISC_MASK_FREE = 0x01, MISC_MASK_ORDER = 0x1F, MISC_MASK_TOPLEVEL = 0x1F };
+
+/* forward declaration of the block struct */
+struct mali_memory_block;
+
+/**
+ * Definition of memory bank type.
+ * Represents a memory bank (separate address space)
+ * Each bank keeps track of its block usage.
+ * A buddy system used to track the usage
+*/
+typedef struct mali_memory_bank
+{
+ _mali_osk_list_t list; /* links multiple banks together */
+ _mali_osk_lock_t *lock;
+ u32 base_addr; /* Mali seen address of bank */
+ u32 cpu_usage_adjust; /* Adjustment factor for what the CPU sees */
+ u32 size; /* the effective size */
+ u32 real_size; /* the real size of the bank, as given by to the subsystem */
+ int min_order;
+ int max_order;
+ struct mali_memory_block * blocklist;
+ _mali_osk_list_t *freelist;
+ _mali_osk_atomic_t num_active_allocations;
+ u32 used_for_flags;
+ u32 alloc_order; /**< Order in which the bank will be used for allocations */
+ const char *name; /**< Descriptive name of the bank */
+} mali_memory_bank;
+
+/**
+ * Definition of the memory block type
+ * Represents a memory block, which is the smallest memory unit operated on.
+ * A block keeps info about its mapping, if in use by a user process
+ */
+typedef struct mali_memory_block
+{
+ _mali_osk_list_t link; /* used for freelist and process usage list*/
+ mali_memory_bank * bank; /* the bank it belongs to */
+ void __user * mapping; /* possible user space mapping of this block */
+ u32 misc; /* used while a block is free to track the number blocks it represents */
+ int descriptor;
+ u32 mmap_cookie; /**< necessary for interaction with _mali_ukk_mem_mmap/munmap */
+} mali_memory_block;
+
+/**
+ * Defintion of the type used to represent memory used by a session.
+ * Containts the head of the list of memory currently in use by a session.
+ */
+typedef struct memory_session
+{
+ _mali_osk_lock_t *lock;
+ _mali_osk_list_t memory_head; /* List of the memory blocks used by this session. */
+ mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
+} memory_session;
+
+/*
+ Subsystem interface implementation
+*/
+/**
+ * Buddy block memory subsystem startup function
+ * Called by the driver core when the driver is loaded.
+ * Registers the memory systems ioctl handler, resource handlers and memory map function with the core.
+ *
+ * @param id Identifier assigned by the core to the memory subsystem
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id);
+
+/**
+ * Buddy block memory subsystem shutdown function
+ * Called by the driver core when the driver is unloaded.
+ * Cleans up
+ * @param id Identifier assigned by the core to the memory subsystem
+ */
+static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id);
+
+/**
+ * Buddy block memory load complete notification function.
+ * Called by the driver core when all drivers have loaded and all resources has been registered
+ * Reports on the memory resources registered
+ * @param id Identifier assigned by the core to the memory subsystem
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id);
+
+
+/**
+ * Buddy block memory subsystem session begin notification
+ * Called by the core when a new session to the driver is started.
+ * Creates a memory session object and sets it as the subsystem slot data for this session
+ * @param slot Pointer to the slot to use for storing per-session data
+ * @param queue The user space event sink
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+
+/**
+ * Buddy block memory subsystem session end notification
+ * Called by the core when a session to the driver has ended.
+ * Cleans up per session data, which includes checking and fixing memory leaks
+ *
+ * @param slot Pointer to the slot to use for storing per-session data
+ */
+static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
+
+/**
+ * Buddy block memory subsystem system info filler
+ * Called by the core when a system info update is needed
+ * We fill in info about all the memory types we have
+ * @param info Pointer to system info struct to update
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info);
+
+/* our registered resource handlers */
+/**
+ * Buddy block memory subsystem's notification handler for MEMORY resource instances.
+ * Registered with the core during startup.
+ * Called by the core for each memory bank described in the active architecture's config.h file.
+ * Requests memory region ownership and calls backend.
+ * @param resource The resource to handle (type MEMORY)
+ * @return 0 if the memory was claimed and accepted, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_resource_memory(_mali_osk_resource_t * resource);
+
+/**
+ * Buddy block memory subsystem's notification handler for MMU resource instances.
+ * Registered with the core during startup.
+ * Called by the core for each mmu described in the active architecture's config.h file.
+ * @param resource The resource to handle (type MMU)
+ * @return 0 if the MMU was found and initialized, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource);
+
+/**
+ * Buddy block memory subsystem's notification handler for FPGA_FRAMEWORK resource instances.
+ * Registered with the core during startup.
+ * Called by the core for each fpga framework described in the active architecture's config.h file.
+ * @param resource The resource to handle (type FPGA_FRAMEWORK)
+ * @return 0 if the FPGA framework was found and initialized, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource);
+
+/* ioctl command implementations */
+/**
+ * Buddy block memory subsystem's handler for MALI_IOC_MEM_GET_BIG_BLOCK ioctl
+ * Called by the generic ioctl handler when the MALI_IOC_MEM_GET_BIG_BLOCK command is received.
+ * Finds an available memory block and maps into the current process' address space.
+ * @param ukk_private private word for use by the User/Kernel interface
+ * @param session_data Pointer to the per-session object which will track the memory usage
+ * @param argument The argument from the user. A pointer to an struct mali_dd_get_big_block in user space
+ * @return Zero if successful, a standard Linux error value value on error (a negative value)
+ */
+_mali_osk_errcode_t _mali_ukk_get_big_block( _mali_uk_get_big_block_s *args );
+
+/**
+ * Buddy block memory subsystem's handler for MALI_IOC_MEM_FREE_BIG_BLOCK ioctl
+ * Called by the generic ioctl handler when the MALI_IOC_MEM_FREE_BIG_BLOCK command is received.
+ * Unmaps the memory from the process' address space and marks the block as free.
+ * @param session_data Pointer to the per-session object which tracks the memory usage
+ * @param argument The argument from the user. A pointer to an struct mali_dd_get_big_block in user space
+ * @return Zero if successful, a standard Linux error value value on error (a negative value)
+ */
+
+/* this static version allows us to make use of it while holding the memory_session lock.
+ * This is required for the session_end code */
+static _mali_osk_errcode_t _mali_ukk_free_big_block_internal( struct mali_session_data * mali_session_data, memory_session * session_data, _mali_uk_free_big_block_s *args);
+
+_mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args );
+
+/**
+ * Buddy block memory subsystem's memory bank registration routine
+ * Called when a MEMORY resource has been found.
+ * The memory region has already been reserved for use by this driver.
+ * Create a bank object to represent this region and initialize its slots.
+ * @note Can only be called in an module atomic scope, i.e. during module init since no locking is performed
+ * @param phys_base Physical base address of this bank
+ * @param cpu_usage_adjust Adjustment factor for CPU seen address
+ * @param size Size of the bank in bytes
+ * @param flags Memory type bits
+ * @param alloc_order Order in which the bank will be used for allocations
+ * @param name descriptive name of the bank
+ * @return Zero on success, negative on error
+ */
+static int mali_memory_bank_register(u32 phys_base, u32 cpu_usage_adjust, u32 size, u32 flags, u32 alloc_order, const char *name);
+
+/**
+ * Get a block of mali memory of at least the given size and of the given type
+ * This is the backend for get_big_block.
+ * @param type_id The type id of memory requested.
+ * @param minimum_size The size requested
+ * @return Pointer to a block on success, NULL on failure
+ */
+static mali_memory_block * mali_memory_block_get(u32 type_id, u32 minimum_size);
+
+/**
+ * Get the mali seen address of the memory described by the block
+ * @param block The memory block to return the address of
+ * @return The mali seen address of the memory block
+ */
+MALI_STATIC_INLINE u32 block_mali_addr_get(mali_memory_block * block);
+
+/**
+ * Get the cpu seen address of the memory described by the block
+ * The cpu_usage_adjust will be used to change the mali seen phys address
+ * @param block The memory block to return the address of
+ * @return The mali seen address of the memory block
+ */
+MALI_STATIC_INLINE u32 block_cpu_addr_get(mali_memory_block * block);
+
+/**
+ * Get the size of the memory described by the given block
+ * @param block The memory block to return the size of
+ * @return The size of the memory block described by the object
+ */
+MALI_STATIC_INLINE u32 block_size_get(mali_memory_block * block);
+
+/**
+ * Get the user space accessible mapping the memory described by the given memory block
+ * Returns a pointer in user space to the memory, if one has been created.
+ * @param block The memory block to return the mapping of
+ * @return User space pointer to cpu accessible memory or NULL if not mapped
+ */
+MALI_STATIC_INLINE void __user * block_mapping_get(mali_memory_block * block);
+
+/**
+ * Set the user space accessible mapping the memory described by the given memory block.
+ * Sets the stored pointer to user space for the memory described by this block.
+ * @param block The memory block to set mapping info for
+ * @param ptr User space pointer to cpu accessible memory or NULL if not mapped
+ */
+MALI_STATIC_INLINE void block_mapping_set(mali_memory_block * block, void __user * ptr);
+
+/**
+ * Get the cookie for use with _mali_ukk_mem_munmap().
+ * @param block The memory block to get the cookie from
+ * @return the cookie. A return of 0 is still a valid cookie.
+ */
+MALI_STATIC_INLINE u32 block_mmap_cookie_get(mali_memory_block * block);
+
+/**
+ * Set the cookie returned via _mali_ukk_mem_mmap().
+ * @param block The memory block to set the cookie for
+ * @param cookie the cookie
+ */
+MALI_STATIC_INLINE void block_mmap_cookie_set(mali_memory_block * block, u32 cookie);
+
+
+/**
+ * Get a memory block's free status
+ * @param block The block to get the state of
+ */
+MALI_STATIC_INLINE u32 get_block_free(mali_memory_block * block);
+
+/**
+ * Set a memory block's free status
+ * @param block The block to set the state for
+ * @param state The state to set
+ */
+MALI_STATIC_INLINE void set_block_free(mali_memory_block * block, int state);
+
+/**
+ * Set a memory block's order
+ * @param block The block to set the order for
+ * @param order The order to set
+ */
+MALI_STATIC_INLINE void set_block_order(mali_memory_block * block, u32 order);
+
+/**
+ * Get a memory block's order
+ * @param block The block to get the order for
+ * @return The order this block exists on
+ */
+MALI_STATIC_INLINE u32 get_block_order(mali_memory_block * block);
+
+/**
+ * Tag a block as being a toplevel block.
+ * A toplevel block has no buddy and no parent
+ * @param block The block to tag as being toplevel
+ */
+MALI_STATIC_INLINE void set_block_toplevel(mali_memory_block * block, u32 level);
+
+/**
+ * Check if a block is a toplevel block
+ * @param block The block to check
+ * @return 1 if toplevel, 0 else
+ */
+MALI_STATIC_INLINE u32 get_block_toplevel(mali_memory_block * block);
+
+/**
+ * Checks if the given block is a buddy at the given order and that it's free
+ * @param block The block to check
+ * @param order The order to check against
+ * @return 0 if not valid, else 1
+ */
+MALI_STATIC_INLINE int block_is_valid_buddy(mali_memory_block * block, int order);
+
+/*
+ The buddy system uses the following rules to quickly find a blocks buddy
+ and parent (block representing this block at a higher order level):
+ - Given a block with index i the blocks buddy is at index i ^ ( 1 << order)
+ - Given a block with index i the blocks parent is at i & ~(1 << order)
+*/
+
+/**
+ * Get a blocks buddy
+ * @param block The block to find the buddy for
+ * @param order The order to operate on
+ * @return Pointer to the buddy block
+ */
+MALI_STATIC_INLINE mali_memory_block * block_get_buddy(mali_memory_block * block, u32 order);
+
+/**
+ * Get a blocks parent
+ * @param block The block to find the parent for
+ * @param order The order to operate on
+ * @return Pointer to the parent block
+ */
+MALI_STATIC_INLINE mali_memory_block * block_get_parent(mali_memory_block * block, u32 order);
+
+/**
+ * Release mali memory
+ * Backend for free_big_block.
+ * Will release the mali memory described by the given block struct.
+ * @param block Memory block to free
+ */
+static void block_release(mali_memory_block * block);
+
+/* end interface implementation */
+
+/**
+ * List of all the memory banks registerd with the subsystem.
+ * Access to this list is NOT synchronized since it's only
+ * written to during module init and termination.
+ */
+static _MALI_OSK_LIST_HEAD(memory_banks_list);
+
+/*
+ The buddy memory system's mali subsystem interface implementation.
+ We currently handle module and session life-time management.
+*/
+struct mali_kernel_subsystem mali_subsystem_memory =
+{
+ mali_memory_core_initialize, /* startup */
+ mali_memory_core_terminate, /* shutdown */
+ mali_memory_core_load_complete, /* load_complete */
+ mali_memory_core_system_info_fill, /* system_info_fill */
+ mali_memory_core_session_begin, /* session_begin */
+ mali_memory_core_session_end, /* session_end */
+ NULL, /* broadcast_notification */
+#if MALI_STATE_TRACKING
+ NULL, /* dump_state */
+#endif
+};
+
+/* Initialized when this subsystem is initialized. This is determined by the
+ * position in subsystems[], and so the value used to initialize this is
+ * determined at compile time */
+static mali_kernel_subsystem_identifier mali_subsystem_memory_id = -1;
+
+/* called during module init */
+static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id)
+{
+ _MALI_OSK_INIT_LIST_HEAD(&memory_banks_list);
+
+ mali_subsystem_memory_id = id;
+
+ /* register our handlers */
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MEMORY, mali_memory_core_resource_memory));
+
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MMU, mali_memory_core_resource_mmu));
+
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(FPGA_FRAMEWORK, mali_memory_core_resource_fpga));
+
+ MALI_SUCCESS;
+}
+
+/* called if/when our module is unloaded */
+static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id)
+{
+ mali_memory_bank * bank, *temp;
+
+ /* loop over all memory banks to free them */
+ /* we use the safe version since we delete the current bank in the body */
+ _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
+ {
+ MALI_DEBUG_CODE(int usage_count = _mali_osk_atomic_read(&bank->num_active_allocations));
+ /*
+ Report leaked memory
+ */
+ MALI_DEBUG_PRINT_IF(1, 0 != usage_count, ("%d allocation(s) from memory bank at 0x%X still in use\n", usage_count, bank->base_addr));
+
+ _mali_osk_atomic_term(&bank->num_active_allocations);
+
+ _mali_osk_lock_term(bank->lock);
+
+ /* unlink from bank list */
+ _mali_osk_list_del(&bank->list);
+
+ /* release kernel resources used by the bank */
+ _mali_osk_mem_unreqregion(bank->base_addr, bank->real_size);
+
+ /* remove all resources used to represent this bank*/
+ _mali_osk_free(bank->freelist);
+ _mali_osk_free(bank->blocklist);
+
+ /* destroy the bank object itself */
+ _mali_osk_free(bank);
+ }
+
+ /* No need to de-initialize mali_subsystem_memory_id - it could only be
+ * re-initialized to the same value */
+}
+
+/* load_complete handler */
+static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id)
+{
+ mali_memory_bank * bank, *temp;
+
+ MALI_DEBUG_PRINT( 1, ("Mali memory allocators will be used in this order of preference (lowest number first) :\n"));
+
+ _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
+ {
+ if ( NULL != bank->name )
+ {
+ MALI_DEBUG_PRINT( 1, ("\t%d: %s\n", bank->alloc_order, bank->name) );
+ }
+ else
+ {
+ MALI_DEBUG_PRINT( 1, ("\t%d: (UNNAMED ALLOCATOR)\n", bank->alloc_order ) );
+ }
+ }
+ MALI_SUCCESS;
+}
+
+MALI_STATIC_INLINE u32 order_needed_for_size(u32 size, struct mali_memory_bank * bank)
+{
+ u32 order = 0;
+
+ if (0 < size)
+ {
+ for ( order = sizeof(u32)*8 - 1; ((1UL<<order) & size) == 0; --order)
+ /* nothing */;
+
+ /* check if size is pow2, if not we need increment order by one */
+ if (0 != (size & ((1UL<<order)-1))) ++order;
+ }
+
+ if ((NULL != bank) && (order < bank->min_order)) order = bank->min_order;
+ /* Not capped to max order, that doesn't make sense */
+
+ return order;
+}
+
+MALI_STATIC_INLINE u32 maximum_order_which_fits(u32 size)
+{
+ u32 order = 0;
+ u32 powsize = 1;
+ while (powsize < size)
+ {
+ powsize <<= 1;
+ if (powsize > size) break;
+ order++;
+ }
+
+ return order;
+}
+
+/* called for new MEMORY resources */
+static _mali_osk_errcode_t mali_memory_bank_register(u32 phys_base, u32 cpu_usage_adjust, u32 size, u32 flags, u32 alloc_order, const char *name)
+{
+ /* no locking performed due to function contract */
+ int i;
+ u32 left, offset;
+ mali_memory_bank * bank;
+ mali_memory_bank * bank_enum, *temp;
+
+ _mali_osk_errcode_t err;
+
+ /* Only a multiple of MIN_BLOCK_SIZE is usable */
+ u32 usable_size = size & ~(MIN_BLOCK_SIZE - 1);
+
+ /* handle zero sized banks and bank smaller than the fixed block size */
+ if (0 == usable_size)
+ {
+ MALI_PRINT(("Usable size == 0\n"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ /* warn for banks not a muliple of the block size */
+ MALI_DEBUG_PRINT_IF(1, usable_size != size, ("Memory bank @ 0x%X not a multiple of minimum block size. %d bytes wasted\n", phys_base, size - usable_size));
+
+ /* check against previous registrations */
+ MALI_DEBUG_CODE(
+ {
+ _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
+ {
+ /* duplicate ? */
+ if (bank->base_addr == phys_base)
+ {
+ MALI_PRINT(("Duplicate registration of a memory bank at 0x%X detected\n", phys_base));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ /* overlapping ? */
+ else if (
+ ( (phys_base > bank->base_addr) && (phys_base < (bank->base_addr + bank->real_size)) ) ||
+ ( (phys_base + size) > bank->base_addr && ((phys_base + size) < (bank->base_addr + bank->real_size)) )
+ )
+ {
+ MALI_PRINT(("Overlapping memory blocks found. Memory at 0x%X overlaps with memory at 0x%X size 0x%X\n", bank->base_addr, phys_base, size));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ }
+ }
+ );
+
+ /* create an object to represent this memory bank */
+ MALI_CHECK_NON_NULL(bank = (mali_memory_bank*)_mali_osk_malloc(sizeof(mali_memory_bank)), _MALI_OSK_ERR_NOMEM);
+
+ /* init the fields */
+ _MALI_OSK_INIT_LIST_HEAD(&bank->list);
+ bank->base_addr = phys_base;
+ bank->cpu_usage_adjust = cpu_usage_adjust;
+ bank->size = usable_size;
+ bank->real_size = size;
+ bank->alloc_order = alloc_order;
+ bank->name = name;
+
+ err = _mali_osk_atomic_init(&bank->num_active_allocations, 0);
+ if (err != _MALI_OSK_ERR_OK)
+ {
+ _mali_osk_free(bank);
+ MALI_ERROR(err);
+ }
+
+ bank->used_for_flags = flags;
+ bank->min_order = order_needed_for_size(MIN_BLOCK_SIZE, NULL);
+ bank->max_order = maximum_order_which_fits(usable_size);
+ bank->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0);
+ if (NULL == bank->lock)
+ {
+ _mali_osk_atomic_term(&bank->num_active_allocations);
+ _mali_osk_free(bank);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ bank->blocklist = _mali_osk_calloc(1, sizeof(struct mali_memory_block) * (usable_size / MIN_BLOCK_SIZE));
+ if (NULL == bank->blocklist)
+ {
+ _mali_osk_lock_term(bank->lock);
+ _mali_osk_atomic_term(&bank->num_active_allocations);
+ _mali_osk_free(bank);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ for (i = 0; i < (usable_size / MIN_BLOCK_SIZE); i++)
+ {
+ bank->blocklist[i].bank = bank;
+ }
+
+ bank->freelist = _mali_osk_calloc(1, sizeof(_mali_osk_list_t) * (bank->max_order - bank->min_order + 1));
+ if (NULL == bank->freelist)
+ {
+ _mali_osk_lock_term(bank->lock);
+ _mali_osk_free(bank->blocklist);
+ _mali_osk_atomic_term(&bank->num_active_allocations);
+ _mali_osk_free(bank);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ for (i = 0; i < (bank->max_order - bank->min_order + 1); i++) _MALI_OSK_INIT_LIST_HEAD(&bank->freelist[i]);
+
+ /* init slot info */
+ for (offset = 0, left = usable_size; offset < (usable_size / MIN_BLOCK_SIZE); /* updated inside the body */)
+ {
+ u32 block_order;
+ mali_memory_block * block;
+
+ /* the maximum order which fits in the remaining area */
+ block_order = maximum_order_which_fits(left);
+
+ /* find the block pointer */
+ block = &bank->blocklist[offset];
+
+ /* tag the block as being toplevel */
+ set_block_toplevel(block, block_order);
+
+ /* tag it as being free */
+ set_block_free(block, 1);
+
+ /* set the order */
+ set_block_order(block, block_order);
+
+ _mali_osk_list_addtail(&block->link, bank->freelist + (block_order - bank->min_order));
+
+ left -= (1 << block_order);
+ offset += ((1 << block_order) / MIN_BLOCK_SIZE);
+ }
+
+ /* add bank to list of banks on the system */
+ _MALI_OSK_LIST_FOREACHENTRY( bank_enum, temp, &memory_banks_list, mali_memory_bank, list )
+ {
+ if ( bank_enum->alloc_order >= alloc_order )
+ {
+ /* Found insertion point - our item must go before this one */
+ break;
+ }
+ }
+ _mali_osk_list_addtail(&bank->list, &bank_enum->list);
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_memory_mmu_register(u32 type, u32 phys_base)
+{
+ /* not supported */
+ return _MALI_OSK_ERR_INVALID_FUNC;
+}
+
+void mali_memory_mmu_unregister(u32 phys_base)
+{
+ /* not supported */
+ return;
+}
+
+static mali_memory_block * mali_memory_block_get(u32 type_id, u32 minimum_size)
+{
+ mali_memory_bank * bank;
+ mali_memory_block * block = NULL;
+ u32 requested_order, current_order;
+
+ /* input validation */
+ if (0 == minimum_size)
+ {
+ /* bad size */
+ MALI_DEBUG_PRINT(2, ("Zero size block requested by mali_memory_block_get\n"));
+ return NULL;
+ }
+
+ bank = (mali_memory_bank*)type_id;
+
+ requested_order = order_needed_for_size(minimum_size, bank);
+
+ MALI_DEBUG_PRINT(4, ("For size %d we need order %d (%d)\n", minimum_size, requested_order, 1 << requested_order));
+
+ _mali_osk_lock_wait(bank->lock, _MALI_OSK_LOCKMODE_RW);
+ /* ! critical section begin */
+
+ MALI_DEBUG_PRINT(7, ("Bank 0x%x locked\n", bank));
+
+ for (current_order = requested_order; current_order <= bank->max_order; ++current_order)
+ {
+ _mali_osk_list_t * list = bank->freelist + (current_order - bank->min_order);
+ MALI_DEBUG_PRINT(7, ("Checking freelist 0x%x for order %d\n", list, current_order));
+ if (0 != _mali_osk_list_empty(list)) continue; /* empty list */
+
+ MALI_DEBUG_PRINT(7, ("Found an entry on the freelist for order %d\n", current_order));
+
+
+ block = _MALI_OSK_LIST_ENTRY(list->next, mali_memory_block, link);
+ _mali_osk_list_delinit(&block->link);
+
+ while (current_order > requested_order)
+ {
+ mali_memory_block * buddy_block;
+ MALI_DEBUG_PRINT(7, ("Splitting block 0x%x\n", block));
+ current_order--;
+ list--;
+ buddy_block = block_get_buddy(block, current_order - bank->min_order);
+ set_block_order(buddy_block, current_order);
+ set_block_free(buddy_block, 1);
+ _mali_osk_list_add(&buddy_block->link, list);
+ }
+
+ set_block_order(block, current_order);
+ set_block_free(block, 0);
+
+ /* update usage count */
+ _mali_osk_atomic_inc(&bank->num_active_allocations);
+
+ break;
+ }
+
+ /* ! critical section end */
+ _mali_osk_lock_signal(bank->lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_DEBUG_PRINT(7, ("Lock released for bank 0x%x\n", bank));
+
+ MALI_DEBUG_PRINT_IF(7, NULL != block, ("Block 0x%x allocated\n", block));
+
+ return block;
+}
+
+
+static void block_release(mali_memory_block * block)
+{
+ mali_memory_bank * bank;
+ u32 current_order;
+
+ if (NULL == block) return;
+
+ bank = block->bank;
+
+ /* we're manipulating the free list, so we need to lock it */
+ _mali_osk_lock_wait(bank->lock, _MALI_OSK_LOCKMODE_RW);
+ /* ! critical section begin */
+
+ set_block_free(block, 1);
+ current_order = get_block_order(block);
+
+ while (current_order <= bank->max_order)
+ {
+ mali_memory_block * buddy_block;
+ buddy_block = block_get_buddy(block, current_order - bank->min_order);
+ if (!block_is_valid_buddy(buddy_block, current_order)) break;
+ _mali_osk_list_delinit(&buddy_block->link); /* remove from free list */
+ /* clear tracked data in both blocks */
+ set_block_order(block, 0);
+ set_block_free(block, 0);
+ set_block_order(buddy_block, 0);
+ set_block_free(buddy_block, 0);
+ /* make the parent control the new state */
+ block = block_get_parent(block, current_order - bank->min_order);
+ set_block_order(block, current_order + 1); /* merged has a higher order */
+ set_block_free(block, 1); /* mark it as free */
+ current_order++;
+ if (get_block_toplevel(block) == current_order) break; /* stop the merge if we've arrived at a toplevel block */
+ }
+
+ _mali_osk_list_add(&block->link, &bank->freelist[current_order - bank->min_order]);
+
+ /* update bank usage statistics */
+ _mali_osk_atomic_dec(&block->bank->num_active_allocations);
+
+ /* !critical section end */
+ _mali_osk_lock_signal(bank->lock, _MALI_OSK_LOCKMODE_RW);
+
+ return;
+}
+
+MALI_STATIC_INLINE u32 block_get_offset(mali_memory_block * block)
+{
+ return block - block->bank->blocklist;
+}
+
+MALI_STATIC_INLINE u32 block_mali_addr_get(mali_memory_block * block)
+{
+ if (NULL != block) return block->bank->base_addr + MIN_BLOCK_SIZE * block_get_offset(block);
+ else return 0;
+}
+
+MALI_STATIC_INLINE u32 block_cpu_addr_get(mali_memory_block * block)
+{
+ if (NULL != block) return (block->bank->base_addr + MIN_BLOCK_SIZE * block_get_offset(block)) + block->bank->cpu_usage_adjust;
+ else return 0;
+}
+
+MALI_STATIC_INLINE u32 block_size_get(mali_memory_block * block)
+{
+ if (NULL != block) return 1 << get_block_order(block);
+ else return 0;
+}
+
+MALI_STATIC_INLINE void __user * block_mapping_get(mali_memory_block * block)
+{
+ if (NULL != block) return block->mapping;
+ else return NULL;
+}
+
+MALI_STATIC_INLINE void block_mapping_set(mali_memory_block * block, void __user * ptr)
+{
+ if (NULL != block) block->mapping = ptr;
+}
+
+MALI_STATIC_INLINE u32 block_mmap_cookie_get(mali_memory_block * block)
+{
+ if (NULL != block) return block->mmap_cookie;
+ else return 0;
+}
+
+/**
+ * Set the cookie returned via _mali_ukk_mem_mmap().
+ * @param block The memory block to set the cookie for
+ * @param cookie the cookie
+ */
+MALI_STATIC_INLINE void block_mmap_cookie_set(mali_memory_block * block, u32 cookie)
+{
+ if (NULL != block) block->mmap_cookie = cookie;
+}
+
+
+static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
+{
+ memory_session * session_data;
+
+ /* validate input */
+ if (NULL == slot)
+ {
+ MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ if (NULL != *slot)
+ {
+ MALI_DEBUG_PRINT(1, ("The slot given to memory session begin already contains data"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ /* create the session data object */
+ MALI_CHECK_NON_NULL(session_data = _mali_osk_malloc(sizeof(memory_session)), _MALI_OSK_ERR_NOMEM);
+
+ /* 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_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _MALI_OSK_INIT_LIST_HEAD(&session_data->memory_head); /* no memory in use */
+ session_data->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, 0);
+ if (NULL == session_data->lock)
+ {
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ *slot = session_data; /* slot will point to our data object */
+
+ MALI_SUCCESS;
+}
+
+static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
+{
+ memory_session * session_data;
+
+ /* validate input */
+ if (NULL == slot)
+ {
+ MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
+ return;
+ }
+
+ if (NULL == *slot)
+ {
+ MALI_DEBUG_PRINT(1, ("NULL memory_session found in current session object"));
+ return;
+ }
+
+ _mali_osk_lock_wait(((memory_session*)*slot)->lock, _MALI_OSK_LOCKMODE_RW);
+ session_data = (memory_session *)*slot;
+ /* clear our slot */
+ *slot = NULL;
+
+ /* First free all memory still being used. This can happen if the
+ * caller has leaked memory or the application has crashed forcing an
+ * auto-session end. */
+ if (0 == _mali_osk_list_empty(&session_data->memory_head))
+ {
+ mali_memory_block * block, * temp;
+ MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n"));
+
+ /* use the _safe version since fre_big_block removes the active block from the list we're iterating */
+ _MALI_OSK_LIST_FOREACHENTRY(block, temp, &session_data->memory_head, mali_memory_block, link)
+ {
+ _mali_osk_errcode_t err;
+ _mali_uk_free_big_block_s uk_args;
+
+ MALI_DEBUG_PRINT(4, ("Freeing block 0x%x with mali address 0x%x size %d mapped in user space at 0x%x\n",
+ block,
+ (void*)block_mali_addr_get(block),
+ block_size_get(block),
+ block_mapping_get(block))
+ );
+
+ /* free the block */
+ /** @note manual type safety check-point */
+ uk_args.ctx = mali_session_data;
+ uk_args.cookie = (u32)block->descriptor;
+ err = _mali_ukk_free_big_block_internal( mali_session_data, session_data, &uk_args );
+
+ if ( _MALI_OSK_ERR_OK != err )
+ {
+ MALI_DEBUG_PRINT_ERROR(("_mali_ukk_free_big_block_internal() failed during session termination on block with cookie==0x%X\n",
+ uk_args.cookie)
+ );
+ }
+ }
+ }
+
+ if (NULL != session_data->descriptor_mapping)
+ {
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ session_data->descriptor_mapping = NULL;
+ }
+
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_lock_term(session_data->lock);
+
+ /* free the session data object */
+ _mali_osk_free(session_data);
+
+ return;
+}
+
+static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info)
+{
+ mali_memory_bank * bank, *temp;
+ _mali_mem_info **mem_info_tail;
+
+ /* check input */
+ MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS);
+
+ /* Make sure we won't leak any memory. It could also be that it's an
+ * uninitialized variable, but the caller should have zeroed the
+ * variable. */
+ MALI_DEBUG_ASSERT(NULL == info->mem_info);
+
+ mem_info_tail = &info->mem_info;
+
+ _MALI_OSK_LIST_FOREACHENTRY(bank, temp, &memory_banks_list, mali_memory_bank, list)
+ {
+ _mali_mem_info * mem_info;
+
+ mem_info = (_mali_mem_info *)_mali_osk_calloc(1, sizeof(_mali_mem_info));
+ if (NULL == mem_info) return _MALI_OSK_ERR_NOMEM; /* memory already allocated will be freed by the caller */
+
+ /* set info */
+ mem_info->size = bank->size;
+ mem_info->flags = (_mali_bus_usage)bank->used_for_flags;
+ mem_info->maximum_order_supported = bank->max_order;
+ mem_info->identifier = (u32)bank;
+
+ /* add to system info linked list */
+ (*mem_info_tail) = mem_info;
+ mem_info_tail = &mem_info->next;
+ }
+
+ /* all OK */
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_memory(_mali_osk_resource_t * resource)
+{
+ _mali_osk_errcode_t err;
+
+ /* Request ownership of the memory */
+ if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description))
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to request memory region %s (0x%08X - 0x%08X)\n", resource->description, resource->base, resource->base + resource->size - 1));
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ /* call backend */
+ err = mali_memory_bank_register(resource->base, resource->cpu_usage_adjust, resource->size, resource->flags, resource->alloc_order, resource->description);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ /* if backend refused the memory we have to release the region again */
+ MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
+ _mali_osk_mem_unreqregion(resource->base, resource->size);
+ MALI_ERROR(err);
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource)
+{
+ /* Not supported by the fixed block memory system */
+ MALI_DEBUG_PRINT(1, ("MMU resource not supported by non-MMU driver!\n"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_FUNC);
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource)
+{
+ mali_io_address mapping;
+
+ MALI_DEBUG_PRINT(5, ("FPGA framework '%s' @ (0x%08X - 0x%08X)\n",
+ resource->description, resource->base, resource->base + sizeof(u32) * 2 - 1
+ ));
+
+ mapping = _mali_osk_mem_mapioregion(resource->base + 0x1000, sizeof(u32) * 2, "fpga framework");
+ if (mapping)
+ {
+ u32 data;
+ data = _mali_osk_mem_ioread32(mapping, 0);
+ MALI_DEBUG_PRINT(2, ("FPGA framwork '%s' @ 0x%08X:\n", resource->description, resource->base));
+ MALI_DEBUG_PRINT(2, ("\tBitfile date: %d%02d%02d_%02d%02d\n",
+ (data >> 20),
+ (data >> 16) & 0xF,
+ (data >> 11) & 0x1F,
+ (data >> 6) & 0x1F,
+ (data >> 0) & 0x3F));
+ data = _mali_osk_mem_ioread32(mapping, sizeof(u32));
+ MALI_DEBUG_PRINT(2, ("\tBitfile SCCS rev: %d\n", data));
+
+ _mali_osk_mem_unmapioregion(resource->base + 0x1000, sizeof(u32) *2, mapping);
+ }
+ else MALI_DEBUG_PRINT(1, ("Failed to access FPGA framwork '%s' @ 0x%08X\n", resource->description, resource->base));
+
+ MALI_SUCCESS;
+}
+
+/* static _mali_osk_errcode_t get_big_block(void * ukk_private, struct mali_session_data * mali_session_data, void __user * argument) */
+_mali_osk_errcode_t _mali_ukk_get_big_block( _mali_uk_get_big_block_s *args )
+{
+ _mali_uk_mem_mmap_s args_mmap = {0, };
+ int md;
+ mali_memory_block * block;
+ _mali_osk_errcode_t err;
+ memory_session * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER( args );
+
+ MALI_DEBUG_ASSERT_POINTER( args->ctx );
+
+ /** @note manual type safety check-point */
+ session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (!args->type_id)
+ {
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* at least min block size */
+ if (MIN_BLOCK_SIZE > args->minimum_size_requested) args->minimum_size_requested = MIN_BLOCK_SIZE;
+
+ /* perform the actual allocation */
+ block = mali_memory_block_get(args->type_id, args->minimum_size_requested);
+ if ( NULL == block )
+ {
+ /* no memory available with requested type_id */
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, block, &md))
+ {
+ block_release(block);
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+ block->descriptor = md;
+
+
+ /* fill in response */
+ args->mali_address = block_mali_addr_get(block);
+ args->block_size = block_size_get(block);
+ args->cookie = (u32)md;
+ args->flags = block->bank->used_for_flags;
+
+ /* map the block into the process' address space */
+
+ /** @note manual type safety check-point */
+ args_mmap.ukk_private = (void *)args->ukk_private;
+ args_mmap.ctx = args->ctx;
+ args_mmap.size = args->block_size;
+ args_mmap.phys_addr = block_cpu_addr_get(block);
+
+#ifndef _MALI_OSK_SPECIFIC_INDIRECT_MMAP
+ err = _mali_ukk_mem_mmap( &args_mmap );
+#else
+ err = _mali_osk_specific_indirect_mmap( &args_mmap );
+#endif
+
+ /* check if the mapping failed */
+ if ( _MALI_OSK_ERR_OK != err )
+ {
+ MALI_DEBUG_PRINT(1, ("Memory mapping failed 0x%x\n", args->cpuptr));
+ /* mapping failed */
+
+ /* remove descriptor entry */
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
+
+ /* free the mali memory */
+ block_release(block);
+
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+ }
+
+ args->cpuptr = args_mmap.mapping;
+ block_mmap_cookie_set(block, args_mmap.cookie);
+ block_mapping_set(block, args->cpuptr);
+
+ MALI_DEBUG_PRINT(2, ("Mali memory 0x%x (size %d) mapped in process memory space at 0x%x\n", (void*)args->mali_address, args->block_size, args->cpuptr));
+
+ /* track memory in use for the session */
+ _mali_osk_list_addtail(&block->link, &session_data->memory_head);
+
+ /* memory assigned to the session, memory mapped into the process' view */
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_SUCCESS;
+}
+
+/* Internal code that assumes the memory session lock is held */
+static _mali_osk_errcode_t _mali_ukk_free_big_block_internal( struct mali_session_data * mali_session_data, memory_session * session_data, _mali_uk_free_big_block_s *args)
+{
+ mali_memory_block * block = NULL;
+ _mali_osk_errcode_t err;
+ _mali_uk_mem_munmap_s args_munmap = {0,};
+
+ MALI_DEBUG_ASSERT_POINTER( mali_session_data );
+ MALI_DEBUG_ASSERT_POINTER( session_data );
+ MALI_DEBUG_ASSERT_POINTER( args );
+
+ err = mali_descriptor_mapping_get(session_data->descriptor_mapping, (int)args->cookie, (void**)&block);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release memory pages\n", (int)args->cookie));
+ MALI_ERROR(err);
+ }
+
+ MALI_DEBUG_ASSERT_POINTER(block);
+
+ MALI_DEBUG_PRINT(4, ("Asked to free block 0x%x with mali address 0x%x size %d mapped in user space at 0x%x\n",
+ block,
+ (void*)block_mali_addr_get(block),
+ block_size_get(block),
+ block_mapping_get(block))
+ );
+
+ /** @note manual type safety check-point */
+ args_munmap.ctx = (void*)mali_session_data;
+ args_munmap.mapping = block_mapping_get( block );
+ args_munmap.size = block_size_get( block );
+ args_munmap.cookie = block_mmap_cookie_get( block );
+
+#ifndef _MALI_OSK_SPECIFIC_INDIRECT_MMAP
+ _mali_ukk_mem_munmap( &args_munmap );
+#else
+ _mali_osk_specific_indirect_munmap( &args_munmap );
+#endif
+
+ MALI_DEBUG_PRINT(6, ("Session data 0x%x, lock 0x%x\n", session_data, &session_data->lock));
+
+ /* unlink from session usage list */
+ MALI_DEBUG_PRINT(5, ("unlink from session usage list\n"));
+ _mali_osk_list_delinit(&block->link);
+
+ /* remove descriptor entry */
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, (int)args->cookie);
+
+ /* free the mali memory */
+ block_release(block);
+ MALI_DEBUG_PRINT(5, ("Block freed\n"));
+
+ MALI_SUCCESS;
+}
+
+/* static _mali_osk_errcode_t free_big_block( struct mali_session_data * mali_session_data, void __user * argument) */
+_mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args )
+{
+ _mali_osk_errcode_t err;
+ struct mali_session_data * mali_session_data;
+ memory_session * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER( args );
+
+ MALI_DEBUG_ASSERT_POINTER( args->ctx );
+
+ /** @note manual type safety check-point */
+ mali_session_data = (struct mali_session_data *)args->ctx;
+
+ /* Must always verify this, since these are provided by the user */
+ MALI_CHECK_NON_NULL(mali_session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
+
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /** @note this has been separated out so that the session_end handler can call this while it has the memory_session lock held */
+ err = _mali_ukk_free_big_block_internal( mali_session_data, session_data, args );
+
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ return err;
+}
+
+MALI_STATIC_INLINE u32 get_block_free(mali_memory_block * block)
+{
+ return (block->misc >> MISC_SHIFT_FREE) & MISC_MASK_FREE;
+}
+
+MALI_STATIC_INLINE void set_block_free(mali_memory_block * block, int state)
+{
+ if (state) block->misc |= (MISC_MASK_FREE << MISC_SHIFT_FREE);
+ else block->misc &= ~(MISC_MASK_FREE << MISC_SHIFT_FREE);
+}
+
+MALI_STATIC_INLINE void set_block_order(mali_memory_block * block, u32 order)
+{
+ block->misc &= ~(MISC_MASK_ORDER << MISC_SHIFT_ORDER);
+ block->misc |= ((order & MISC_MASK_ORDER) << MISC_SHIFT_ORDER);
+}
+
+MALI_STATIC_INLINE u32 get_block_order(mali_memory_block * block)
+{
+ return (block->misc >> MISC_SHIFT_ORDER) & MISC_MASK_ORDER;
+}
+
+MALI_STATIC_INLINE void set_block_toplevel(mali_memory_block * block, u32 level)
+{
+ block->misc |= ((level & MISC_MASK_TOPLEVEL) << MISC_SHIFT_TOPLEVEL);
+}
+
+MALI_STATIC_INLINE u32 get_block_toplevel(mali_memory_block * block)
+{
+ return (block->misc >> MISC_SHIFT_TOPLEVEL) & MISC_MASK_TOPLEVEL;
+}
+
+MALI_STATIC_INLINE int block_is_valid_buddy(mali_memory_block * block, int order)
+{
+ if (get_block_free(block) && (get_block_order(block) == order)) return 1;
+ else return 0;
+}
+
+MALI_STATIC_INLINE mali_memory_block * block_get_buddy(mali_memory_block * block, u32 order)
+{
+ return block + ( (block_get_offset(block) ^ (1 << order)) - block_get_offset(block));
+}
+
+MALI_STATIC_INLINE mali_memory_block * block_get_parent(mali_memory_block * block, u32 order)
+{
+ return block + ((block_get_offset(block) & ~(1 << order)) - block_get_offset(block));
+}
+
+/* This handler registered to mali_mmap for non-MMU builds */
+_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args )
+{
+ _mali_osk_errcode_t ret;
+ struct mali_session_data * mali_session_data;
+ mali_memory_allocation * descriptor;
+ memory_session * session_data;
+
+ /* validate input */
+ if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
+
+ /* Unpack arguments */
+ mali_session_data = (struct mali_session_data *)args->ctx;
+
+ if (NULL == mali_session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: mali_session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
+
+ MALI_DEBUG_ASSERT( mali_subsystem_memory_id >= 0 );
+
+ session_data = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
+ /* validate input */
+ if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); }
+
+ descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) );
+ if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); }
+
+ descriptor->size = args->size;
+ descriptor->mali_address = args->phys_addr;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+ descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */
+ descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE;
+
+ ret = _mali_osk_mem_mapregion_init( descriptor );
+ if ( _MALI_OSK_ERR_OK != ret )
+ {
+ MALI_DEBUG_PRINT(3, ("_mali_osk_mem_mapregion_init() failed\n"));
+ _mali_osk_free(descriptor);
+ MALI_ERROR(ret);
+ }
+
+ ret = _mali_osk_mem_mapregion_map( descriptor, 0, &descriptor->mali_address, descriptor->size );
+ if ( _MALI_OSK_ERR_OK != ret )
+ {
+ MALI_DEBUG_PRINT(3, ("_mali_osk_mem_mapregion_map() failed\n"));
+ _mali_osk_mem_mapregion_term( descriptor );
+ _mali_osk_free(descriptor);
+ MALI_ERROR(ret);
+ }
+
+ args->mapping = descriptor->mapping;
+
+ /**
+ * @note we do not require use of mali_descriptor_mapping here:
+ * the cookie gets stored in the mali_memory_block struct, which itself is
+ * protected by mali_descriptor_mapping, and so this cookie never leaves
+ * kernel space (on any OS).
+ *
+ * In the MMU case, we must use a mali_descriptor_mapping, since on _some_
+ * OSs, the cookie leaves kernel space.
+ */
+ args->cookie = (u32)descriptor;
+ MALI_SUCCESS;
+}
+
+/* This handler registered to mali_munmap for non-MMU builds */
+_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args )
+{
+ mali_memory_allocation * descriptor;
+
+ /** see note in _mali_ukk_mem_mmap() - no need to use descriptor mapping */
+ descriptor = (mali_memory_allocation *)args->cookie;
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /* args->mapping and args->size are also discarded. They are only necessary for certain do_munmap implementations. However, they could be used to check the descriptor at this point. */
+ _mali_osk_mem_mapregion_unmap( descriptor, 0, descriptor->size, (_mali_osk_mem_mapregion_flags_t)0 );
+
+ _mali_osk_mem_mapregion_term( descriptor );
+
+ _mali_osk_free(descriptor);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c b/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c
new file mode 100644
index 00000000000..be0cc6702e8
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c
@@ -0,0 +1,3158 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_subsystem.h"
+#include "mali_kernel_mem.h"
+#include "mali_kernel_ioctl.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_kernel_mem_mmu.h"
+#include "mali_kernel_memory_engine.h"
+#include "mali_block_allocator.h"
+#include "mali_kernel_mem_os.h"
+#include "mali_kernel_session_manager.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_rendercore.h"
+
+#if defined USING_MALI400_L2_CACHE
+#include "mali_kernel_l2_cache.h"
+#endif
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+#include "ump_kernel_interface.h"
+#endif
+
+/* kernel side OS functions and user-kernel interface */
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_ukk.h"
+#include "mali_osk_bitops.h"
+#include "mali_osk_list.h"
+
+/**
+ * Size of the MMU registers in bytes
+ */
+#define MALI_MMU_REGISTERS_SIZE 0x24
+
+/**
+ * Size of an MMU page in bytes
+ */
+#define MALI_MMU_PAGE_SIZE 0x1000
+
+/**
+ * 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)
+
+/**
+ * Calculate memory address from PDE and PTE
+ */
+#define MALI_MMU_ADDRESS(pde, pte) (((pde)<<22) | ((pte)<<12))
+
+/**
+ * Linux kernel version has marked SA_SHIRQ as deprecated, IRQF_SHARED should be used.
+ * This is to handle older kernels which haven't done this swap.
+ */
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif /* IRQF_SHARED */
+
+/**
+ * Per-session memory descriptor mapping table sizes
+ */
+#define MALI_MEM_DESCRIPTORS_INIT 64
+#define MALI_MEM_DESCRIPTORS_MAX 65536
+
+/**
+ * Used to disallow more than one core to run a MMU at the same time
+ *
+ * @note This value is hardwired into some systems' configuration files,
+ * which \em might not be a header file (e.g. some external data configuration
+ * file). Therefore, if this value is modified, its occurance must be
+ * \b manually checked for in the entire driver source tree.
+ */
+#define MALI_MMU_DISALLOW_PARALLELL_WORK_OF_MALI_CORES 1
+
+#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_MASK = 0x07
+} mali_mmu_entry_flags;
+
+/**
+ * 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 = 0x0001, /**< Status of the MMU */
+ MALI_MMU_REGISTER_COMMAND = 0x0002, /**< Command register, used to control the MMU */
+ MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x0003, /**< Logical address of the last page fault */
+ MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x004, /**< Used to invalidate the mapping of a single page from the MMU */
+ MALI_MMU_REGISTER_INT_RAWSTAT = 0x0005, /**< Raw interrupt status, all interrupts visible */
+ MALI_MMU_REGISTER_INT_CLEAR = 0x0006, /**< Indicate to the MMU that the interrupt has been received */
+ MALI_MMU_REGISTER_INT_MASK = 0x0007, /**< Enable/disable types of interrupts */
+ MALI_MMU_REGISTER_INT_STATUS = 0x0008 /**< 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;
+
+/**
+ * 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_SOFT_RESET = 0x06 /**< Reset the MMU back to power-on settings */
+} mali_mmu_command;
+
+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_bits;
+
+/**
+ * Defintion of the type used to represent memory used by a session.
+ * Containts the pointer to the huge user space virtual memory area
+ * used to access the Mali memory.
+ */
+typedef struct memory_session
+{
+ _mali_osk_lock_t *lock; /**< Lock protecting the vm manipulation */
+
+ u32 mali_base_address; /**< Mali virtual memory area used by this session */
+ mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
+
+ 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 */
+
+ _mali_osk_list_t active_mmus; /**< The MMUs in this session, in increasing order of ID (so we can lock them in the correct order when necessary) */
+ _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */
+} memory_session;
+
+typedef struct mali_kernel_memory_mmu_idle_callback
+{
+ _mali_osk_list_t link;
+ void (*callback)(void*);
+ void * callback_argument;
+} mali_kernel_memory_mmu_idle_callback;
+
+/**
+ * Definition of the MMU struct
+ * Used to track a MMU unit in the system.
+ * Contains information about the mapping of the registers
+ */
+typedef struct mali_kernel_memory_mmu
+{
+ int id; /**< ID of the MMU, no duplicate IDs may exist on the system */
+ const char * description; /**< Description text received from the resource manager to help identify the resource for people */
+ int irq_nr; /**< IRQ number */
+ u32 base; /**< Physical address of the registers */
+ mali_io_address mapped_registers; /**< Virtual mapping of the registers */
+ u32 mapping_size; /**< Size of registers in bytes */
+ _mali_osk_list_t list; /**< Used to link multiple MMU's into a list */
+ _mali_osk_irq_t *irq;
+ u32 flags; /**< Used to store if there is something special with this mmu. */
+
+ _mali_osk_lock_t *lock; /**< Lock protecting access to the usage fields */
+ /* usage fields */
+ memory_session * active_session; /**< Active session, NULL if no session is active */
+ u32 usage_count; /**< Number of nested activations of the active session */
+ _mali_osk_list_t callbacks; /**< Callback registered for MMU idle notification */
+ void *core;
+
+ int in_page_fault_handler;
+
+ _mali_osk_list_t session_link;
+} mali_kernel_memory_mmu;
+
+typedef struct dedicated_memory_info
+{
+ u32 base;
+ u32 size;
+ struct dedicated_memory_info * next;
+} dedicated_memory_info;
+
+/* types used for external_memory and ump_memory physical memory allocators, which are using the mali_allocation_engine */
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+typedef struct ump_mem_allocation
+{
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+ u32 initial_offset;
+ u32 size_allocated;
+ ump_dd_handle ump_mem;
+} ump_mem_allocation ;
+#endif
+
+typedef struct external_mem_allocation
+{
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+ u32 initial_offset;
+ u32 size;
+} external_mem_allocation;
+
+/*
+ Subsystem interface implementation
+*/
+/**
+ * Fixed block memory subsystem startup function.
+ * Called by the driver core when the driver is loaded.
+ * Registers the memory systems ioctl handler, resource handlers and memory map function with the core.
+ *
+ * @param id Identifier assigned by the core to the memory subsystem
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id);
+
+/**
+ * Fixed block memory subsystem shutdown function.
+ * Called by the driver core when the driver is unloaded.
+ * Cleans up
+ * @param id Identifier assigned by the core to the memory subsystem
+ */
+static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id);
+
+/**
+ * MMU Memory load complete notification function.
+ * Called by the driver core when all drivers have loaded and all resources has been registered
+ * Builds the memory overall memory list
+ * @param id Identifier assigned by the core to the memory subsystem
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id);
+
+/**
+ * Fixed block memory subsystem session begin notification
+ * Called by the core when a new session to the driver is started.
+ * Creates a memory session object and sets it as the subsystem slot data for this session
+ * @param slot Pointer to the slot to use for storing per-session data
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+
+/**
+ * Fixed block memory subsystem session end notification
+ * Called by the core when a session to the driver has ended.
+ * Cleans up per session data, which includes checking and fixing memory leaks
+ *
+ * @param slot Pointer to the slot to use for storing per-session data
+ */
+static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
+
+/**
+ * Fixed block memory subsystem system info filler
+ * Called by the core when a system info update is needed
+ * We fill in info about all the memory types we have
+ * @param info Pointer to system info struct to update
+ * @return 0 on success, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info);
+
+/* our registered resource handlers */
+
+/**
+ * Fixed block memory subsystem's notification handler for MMU resource instances.
+ * Registered with the core during startup.
+ * Called by the core for each mmu described in the active architecture's config.h file.
+ * @param resource The resource to handle (type MMU)
+ * @return 0 if the MMU was found and initialized, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource);
+
+/**
+ * Fixed block memory subsystem's notification handler for FPGA_FRAMEWORK resource instances.
+ * Registered with the core during startup.
+ * Called by the core for each fpga framework described in the active architecture's config.h file.
+ * @param resource The resource to handle (type FPGA_FRAMEWORK)
+ * @return 0 if the FPGA framework was found and initialized, negative on error
+ */
+static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource);
+
+
+static _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource);
+static _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource);
+
+/**
+ * @brief Internal function for unmapping memory
+ *
+ * Worker function for unmapping memory from a user-process. We assume that the
+ * session/descriptor's lock was obtained before entry. For example, the
+ * wrapper _mali_ukk_mem_munmap() will lock the descriptor, then call this
+ * function to do the actual unmapping. mali_memory_core_session_end() could
+ * also call this directly (depending on compilation options), having locked
+ * the descriptor.
+ *
+ * This function will fail if it is unable to put the MMU in stall mode (which
+ * might be the case if a page fault is also being processed).
+ *
+ * @param args see _mali_uk_mem_munmap_s in "mali_uk_types.h"
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args );
+
+/**
+ * The MMU interrupt handler
+ * Upper half of the MMU interrupt processing.
+ * Called by the kernel when the MMU has triggered an interrupt.
+ * The interrupt function supports IRQ sharing. So it'll probe the MMU in question
+ * @param irq The irq number (not used)
+ * @param dev_id Points to the MMU object being handled
+ * @param regs Registers of interrupted process (not used)
+ * @return Standard Linux interrupt result.
+ * Subset used by the driver is IRQ_HANDLED processed
+ * IRQ_NONE Not processed
+ */
+static _mali_osk_errcode_t mali_kernel_memory_mmu_interrupt_handler_upper_half(void * data);
+
+/**
+ * The MMU reset hander
+ * Bottom half of the MMU interrupt processing for page faults and bus errors
+ * @param work The item to operate on, NULL in our case
+ */
+static void mali_kernel_memory_mmu_interrupt_handler_bottom_half ( void *data );
+
+/**
+ * Read MMU register value
+ * Reads the contents of the specified register.
+ * @param unit The MMU to read from
+ * @param reg The register to read
+ * @return The contents of the register
+ */
+static u32 mali_mmu_register_read(mali_kernel_memory_mmu * unit, mali_mmu_register reg);
+
+/**
+ * Write to a MMU register
+ * Writes the given value to the specified register
+ * @param unit The MMU to write to
+ * @param reg The register to write to
+ * @param val The value to write to the register
+ */
+static void mali_mmu_register_write(mali_kernel_memory_mmu * unit, mali_mmu_register reg, u32 val);
+
+/**
+ * Issues the reset command to the MMU and waits for HW to be ready again
+ * @param mmu The MMU to reset
+ */
+static void mali_mmu_raw_reset(mali_kernel_memory_mmu * mmu);
+
+/**
+ * Issues the enable paging command to the MMU and waits for HW to complete the request
+ * @param mmu The MMU to enable paging for
+ */
+static void mali_mmu_enable_paging(mali_kernel_memory_mmu * mmu);
+
+/**
+ * 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(mali_kernel_memory_mmu * mmu);
+
+/**
+ * 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(mali_kernel_memory_mmu * mmu);
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+static void ump_memory_release(void * ctx, void * handle);
+static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
+#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0*/
+
+
+static void external_memory_release(void * ctx, void * handle);
+static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
+
+
+
+
+/* nop functions */
+
+/* mali address manager needs to allocate page tables on allocate, write to page table(s) on map, write to page table(s) and release page tables on release */
+static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor); /* validates the range, allocates memory for the page tables if needed */
+static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size);
+static void mali_address_manager_release(mali_memory_allocation * descriptor);
+
+static void mali_mmu_activate_address_space(mali_kernel_memory_mmu * mmu, u32 page_directory);
+
+_mali_osk_errcode_t mali_mmu_page_table_cache_create(void);
+void mali_mmu_page_table_cache_destroy(void);
+
+_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping);
+void mali_mmu_release_table_page(u32 pa);
+
+static _mali_osk_errcode_t mali_allocate_empty_page_directory(void);
+
+static void mali_free_empty_page_directory(void);
+
+static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data);
+
+static _mali_osk_errcode_t mali_allocate_fault_flush_pages(void);
+
+static void mali_free_fault_flush_pages(void);
+
+static void mali_mmu_probe_irq_trigger(mali_kernel_memory_mmu * mmu);
+static _mali_osk_errcode_t mali_mmu_probe_irq_acknowledge(mali_kernel_memory_mmu * mmu);
+
+/* MMU variables */
+
+typedef struct mali_mmu_page_table_allocation
+{
+ _mali_osk_list_t list;
+ u32 * usage_map;
+ u32 usage_count;
+ u32 num_pages;
+ mali_page_table_block pages;
+} mali_mmu_page_table_allocation;
+
+typedef struct mali_mmu_page_table_allocations
+{
+ _mali_osk_lock_t *lock;
+ _mali_osk_list_t partial;
+ _mali_osk_list_t full;
+ /* we never hold on to a empty allocation */
+} mali_mmu_page_table_allocations;
+
+/* Head of the list of MMUs */
+static _MALI_OSK_LIST_HEAD(mmu_head);
+
+/* the mmu page table cache */
+static struct mali_mmu_page_table_allocations page_table_cache;
+
+/* 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 = MALI_INVALID_PAGE;
+
+/*
+ The fixed memory system's mali subsystem interface implementation.
+ We currently handle module and session life-time management.
+*/
+struct mali_kernel_subsystem mali_subsystem_memory =
+{
+ mali_memory_core_initialize, /* startup */
+ mali_memory_core_terminate, /* shutdown */
+ mali_memory_core_load_complete, /* load_complete */
+ mali_memory_core_system_info_fill, /* system_info_fill */
+ mali_memory_core_session_begin, /* session_begin */
+ mali_memory_core_session_end, /* session_end */
+ NULL, /* broadcast_notification */
+#if MALI_STATE_TRACKING
+ NULL, /* dump_state */
+#endif
+};
+
+static mali_kernel_mem_address_manager mali_address_manager =
+{
+ mali_address_manager_allocate, /* allocate */
+ mali_address_manager_release, /* release */
+ mali_address_manager_map, /* map_physical */
+ NULL /* unmap_physical not present*/
+};
+
+static mali_kernel_mem_address_manager process_address_manager =
+{
+ _mali_osk_mem_mapregion_init, /* allocate */
+ _mali_osk_mem_mapregion_term, /* release */
+ _mali_osk_mem_mapregion_map, /* map_physical */
+ _mali_osk_mem_mapregion_unmap /* unmap_physical */
+};
+
+static mali_allocation_engine memory_engine = NULL;
+static mali_physical_memory_allocator * physical_memory_allocators = NULL;
+
+static dedicated_memory_info * mem_region_registrations = NULL;
+
+/* Initialized when this subsystem is initialized. This is determined by the
+ * position in subsystems[], and so the value used to initialize this is
+ * determined at compile time */
+static mali_kernel_subsystem_identifier mali_subsystem_memory_id = (mali_kernel_subsystem_identifier)-1;
+
+/* called during module init */
+static _mali_osk_errcode_t mali_memory_core_initialize(mali_kernel_subsystem_identifier id)
+{
+ MALI_DEBUG_PRINT(2, ("MMU memory system initializing\n"));
+
+ /* save our subsystem id for later for use in slot lookup during session activation */
+ mali_subsystem_memory_id = id;
+
+ _MALI_OSK_INIT_LIST_HEAD(&mmu_head);
+
+ MALI_CHECK_NO_ERROR( mali_mmu_page_table_cache_create() );
+
+ /* register our handlers */
+ MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(MMU, mali_memory_core_resource_mmu) );
+
+ MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(FPGA_FRAMEWORK, mali_memory_core_resource_fpga) );
+
+ MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(MEMORY, mali_memory_core_resource_dedicated_memory) );
+
+ MALI_CHECK_NO_ERROR( _mali_kernel_core_register_resource_handler(OS_MEMORY, mali_memory_core_resource_os_memory) );
+
+ memory_engine = mali_allocation_engine_create(&mali_address_manager, &process_address_manager);
+ MALI_CHECK_NON_NULL( memory_engine, _MALI_OSK_ERR_FAULT);
+
+ MALI_SUCCESS;
+}
+
+/* called if/when our module is unloaded */
+static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id)
+{
+ mali_kernel_memory_mmu * mmu, *temp_mmu;
+
+ MALI_DEBUG_PRINT(2, ("MMU memory system terminating\n"));
+
+ /* loop over all MMU units and shut them down */
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list)
+ {
+ /* reset to defaults */
+ mali_mmu_raw_reset(mmu);
+
+ /* unregister the irq */
+ _mali_osk_irq_term(mmu->irq);
+
+ /* remove from the list of MMU's on the system */
+ _mali_osk_list_del(&mmu->list);
+
+ /* release resources */
+ _mali_osk_mem_unmapioregion(mmu->base, mmu->mapping_size, mmu->mapped_registers);
+ _mali_osk_mem_unreqregion(mmu->base, mmu->mapping_size);
+ _mali_osk_lock_term(mmu->lock);
+ _mali_osk_free(mmu);
+ }
+
+ /* free global helper pages */
+ mali_free_empty_page_directory();
+ mali_free_fault_flush_pages();
+
+ /* destroy the page table cache before shutting down backends in case we have a page table leak to report */
+ mali_mmu_page_table_cache_destroy();
+
+ while ( NULL != mem_region_registrations)
+ {
+ dedicated_memory_info * m;
+ m = mem_region_registrations;
+ mem_region_registrations = m->next;
+ _mali_osk_mem_unreqregion(m->base, m->size);
+ _mali_osk_free(m);
+ }
+
+ while ( NULL != physical_memory_allocators)
+ {
+ mali_physical_memory_allocator * m;
+ m = physical_memory_allocators;
+ physical_memory_allocators = m->next;
+ m->destroy(m);
+ }
+
+ if (NULL != memory_engine)
+ {
+ mali_allocation_engine_destroy(memory_engine);
+ memory_engine = NULL;
+ }
+
+}
+
+static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue)
+{
+ memory_session * session_data;
+ _mali_osk_errcode_t err;
+ int i;
+ mali_io_address pd_mapped;
+
+ /* validate input */
+ if (NULL == slot)
+ {
+ MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ if (NULL != *slot)
+ {
+ MALI_DEBUG_PRINT(1, ("The slot given to memory session begin already contains data"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ MALI_DEBUG_PRINT(2, ("MMU session begin\n"));
+
+ /* create the session data object */
+ session_data = _mali_osk_calloc(1, sizeof(memory_session));
+ MALI_CHECK_NON_NULL( session_data, _MALI_OSK_ERR_NOMEM );
+
+ /* 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_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ err = mali_mmu_get_table_page(&session_data->page_directory, &pd_mapped);
+
+ session_data->page_directory_mapped = pd_mapped;
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ _mali_osk_free(session_data);
+ MALI_ERROR(err);
+ }
+ MALI_DEBUG_ASSERT_POINTER( session_data->page_directory_mapped );
+
+ MALI_DEBUG_PRINT(2, ("Page directory for session 0x%x placed at physical address 0x%08X\n", mali_session_data, session_data->page_directory));
+
+ for (i = 0; i < MALI_MMU_PAGE_SIZE/4; i++)
+ {
+ /* mark each page table as not present */
+ _mali_osk_mem_iowrite32_relaxed(session_data->page_directory_mapped, sizeof(u32) * i, 0);
+ }
+ _mali_osk_write_mem_barrier();
+
+ /* page_table_mapped[] is already set to NULL by _mali_osk_calloc call */
+
+ _MALI_OSK_INIT_LIST_HEAD(&session_data->active_mmus);
+ session_data->lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 128);
+ if (NULL == session_data->lock)
+ {
+ mali_mmu_release_table_page(session_data->page_directory);
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Init the session's memory allocation list */
+ _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head );
+
+ *slot = session_data; /* slot will point to our data object */
+ MALI_DEBUG_PRINT(2, ("MMU session begin: success\n"));
+ MALI_SUCCESS;
+}
+
+static void descriptor_table_cleanup_callback(int descriptor_id, void* map_target)
+{
+ mali_memory_allocation * descriptor;
+
+ descriptor = (mali_memory_allocation*)map_target;
+
+ MALI_DEBUG_PRINT(1, ("Cleanup of descriptor %d mapping to 0x%x in descriptor table\n", descriptor_id, map_target));
+ MALI_DEBUG_ASSERT(descriptor);
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+ _mali_osk_free(descriptor);
+}
+
+static void mali_memory_core_session_end(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot)
+{
+ memory_session * session_data;
+ int i;
+ const int num_page_table_entries = sizeof(session_data->page_entries_mapped) / sizeof(session_data->page_entries_mapped[0]);
+
+ MALI_DEBUG_PRINT(2, ("MMU session end\n"));
+
+ /* validate input */
+ if (NULL == slot)
+ {
+ MALI_DEBUG_PRINT(1, ("NULL slot given to memory session begin\n"));
+ return;
+ }
+
+ session_data = (memory_session *)*slot;
+
+ if (NULL == session_data)
+ {
+ 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_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW );
+ /* Noninterruptable spinlock type, so must always have locked. Checking should've been done in OSK function. */
+
+#ifndef MALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP
+#if _MALI_OSK_SPECIFIC_INDIRECT_MMAP
+#error Indirect MMAP specified, but UKK does not have implicit MMAP cleanup. Current implementation does not handle this.
+#else
+
+ /* Free all memory engine allocations */
+ if (0 == _mali_osk_list_empty(&session_data->memory_head))
+ {
+ mali_memory_allocation *descriptor;
+ mali_memory_allocation *temp;
+ _mali_uk_mem_munmap_s unmap_args;
+
+ MALI_DEBUG_PRINT(1, ("Memory found on session usage list during session termination\n"));
+
+ unmap_args.ctx = mali_session_data;
+
+ /* 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->memory_head, mali_memory_allocation, list)
+ {
+ MALI_DEBUG_PRINT(4, ("Freeing block with mali address 0x%x size %d mapped in user space at 0x%x\n",
+ descriptor->mali_address, descriptor->size, descriptor->size, descriptor->mapping)
+ );
+ /* ASSERT that the descriptor's lock references the correct thing */
+ MALI_DEBUG_ASSERT( descriptor->lock == session_data->lock );
+ /* Therefore, we have already locked the descriptor */
+
+ unmap_args.size = descriptor->size;
+ unmap_args.mapping = descriptor->mapping;
+ unmap_args.cookie = (u32)descriptor;
+
+ /*
+ * This removes the descriptor from the list, and frees the descriptor
+ *
+ * Does not handle the _MALI_OSK_SPECIFIC_INDIRECT_MMAP case, since
+ * the only OS we are aware of that requires indirect MMAP also has
+ * implicit mmap cleanup.
+ */
+ _mali_ukk_mem_munmap_internal( &unmap_args );
+ }
+ }
+
+ /* Assert that we really did free everything */
+ MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) );
+#endif /* _MALI_OSK_SPECIFIC_INDIRECT_MMAP */
+#endif /* MALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP */
+
+ if (NULL != session_data->descriptor_mapping)
+ {
+ mali_descriptor_mapping_call_for_each(session_data->descriptor_mapping, descriptor_table_cleanup_callback);
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ session_data->descriptor_mapping = NULL;
+ }
+
+ for (i = 0; i < num_page_table_entries; i++)
+ {
+ /* free PTE memory */
+ if (session_data->page_directory_mapped && (_mali_osk_mem_ioread32(session_data->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT))
+ {
+ mali_mmu_release_table_page( _mali_osk_mem_ioread32(session_data->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+ _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), 0);
+ }
+ }
+
+ if (MALI_INVALID_PAGE != session_data->page_directory)
+ {
+ mali_mmu_release_table_page(session_data->page_directory);
+ session_data->page_directory = MALI_INVALID_PAGE;
+ }
+
+ _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW );
+
+ /**
+ * @note Could the VMA close handler mean that we use the session data after it was freed?
+ * In which case, would need to refcount the session data, and free on VMA close
+ */
+
+ /* Free the lock */
+ _mali_osk_lock_term( session_data->lock );
+ /* free the session data object */
+ _mali_osk_free(session_data);
+
+ /* clear our slot */
+ *slot = NULL;
+
+ return;
+}
+
+static _mali_osk_errcode_t mali_allocate_empty_page_directory(void)
+{
+ _mali_osk_errcode_t err;
+ mali_io_address mapping;
+
+ MALI_CHECK_NO_ERROR(mali_mmu_get_table_page(&mali_empty_page_directory, &mapping));
+
+ MALI_DEBUG_ASSERT_POINTER( mapping );
+
+ err = fill_page(mapping, 0);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ mali_mmu_release_table_page(mali_empty_page_directory);
+ mali_empty_page_directory = MALI_INVALID_PAGE;
+ }
+ return err;
+}
+
+static void mali_free_empty_page_directory(void)
+{
+ if (MALI_INVALID_PAGE != mali_empty_page_directory)
+ {
+ mali_mmu_release_table_page(mali_empty_page_directory);
+ mali_empty_page_directory = MALI_INVALID_PAGE;
+ }
+}
+
+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;
+}
+
+static _mali_osk_errcode_t mali_allocate_fault_flush_pages(void)
+{
+ _mali_osk_errcode_t err;
+
+ err = mali_mmu_get_table_page(&mali_page_fault_flush_data_page, &mali_page_fault_flush_data_page_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ err = mali_mmu_get_table_page(&mali_page_fault_flush_page_table, &mali_page_fault_flush_page_table_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ err = mali_mmu_get_table_page(&mali_page_fault_flush_page_directory, &mali_page_fault_flush_page_directory_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ fill_page(mali_page_fault_flush_data_page_mapping, 0);
+ fill_page(mali_page_fault_flush_page_table_mapping, mali_page_fault_flush_data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
+ fill_page(mali_page_fault_flush_page_directory_mapping, mali_page_fault_flush_page_table | MALI_MMU_FLAGS_PRESENT);
+ MALI_SUCCESS;
+ }
+ mali_mmu_release_table_page(mali_page_fault_flush_page_table);
+ mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
+ mali_page_fault_flush_page_table_mapping = NULL;
+ }
+ mali_mmu_release_table_page(mali_page_fault_flush_data_page);
+ mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
+ mali_page_fault_flush_data_page_mapping = NULL;
+ }
+ MALI_ERROR(err);
+}
+
+static void mali_free_fault_flush_pages(void)
+{
+ if (MALI_INVALID_PAGE != mali_page_fault_flush_page_directory)
+ {
+ mali_mmu_release_table_page(mali_page_fault_flush_page_directory);
+ mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
+ }
+
+ if (MALI_INVALID_PAGE != mali_page_fault_flush_page_table)
+ {
+ mali_mmu_release_table_page(mali_page_fault_flush_page_table);
+ mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
+ }
+
+ if (MALI_INVALID_PAGE != mali_page_fault_flush_data_page)
+ {
+ mali_mmu_release_table_page(mali_page_fault_flush_data_page);
+ mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
+ }
+}
+
+static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_identifier id)
+{
+ mali_kernel_memory_mmu * mmu, * temp_mmu;
+
+ /* Report the allocators */
+ mali_allocation_engine_report_allocators( physical_memory_allocators );
+
+ /* allocate the helper pages */
+ MALI_CHECK_NO_ERROR( mali_allocate_empty_page_directory() );
+ if (_MALI_OSK_ERR_OK != mali_allocate_fault_flush_pages())
+ {
+ mali_free_empty_page_directory();
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* activate the empty page directory on all MMU's */
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list)
+ {
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
+ mali_mmu_enable_paging(mmu);
+ }
+
+ MALI_DEBUG_PRINT(4, ("MMUs activated\n"));
+ /* the MMU system is now active */
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_system_info_fill(_mali_system_info* info)
+{
+ _mali_mem_info * mem_info;
+
+ /* Make sure we won't leak any memory. It could also be that it's an
+ * uninitialized variable, but the caller should have zeroed the
+ * variable. */
+ MALI_DEBUG_ASSERT(NULL == info->mem_info);
+
+ info->has_mmu = 1;
+
+ mem_info = _mali_osk_calloc(1,sizeof(_mali_mem_info));
+ MALI_CHECK_NON_NULL( mem_info, _MALI_OSK_ERR_NOMEM );
+
+ mem_info->size = 2048UL * 1024UL * 1024UL;
+ mem_info->maximum_order_supported = 30;
+ mem_info->flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE;
+ mem_info->identifier = 0;
+
+ info->mem_info = mem_info;
+
+ /* all OK */
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * resource)
+{
+ mali_kernel_memory_mmu * mmu;
+
+ MALI_DEBUG_PRINT(4, ("MMU '%s' @ (0x%08X - 0x%08X)\n",
+ resource->description, resource->base, resource->base + MALI_MMU_REGISTERS_SIZE - 1
+ ));
+
+ if (NULL != mali_memory_core_mmu_lookup(resource->mmu_id))
+ {
+ MALI_DEBUG_PRINT(1, ("Duplicate MMU ids found. The id %d is already in use\n", resource->mmu_id));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, MALI_MMU_REGISTERS_SIZE, resource->description))
+ {
+ /* specified addresses are already in used by another driver / the kernel */
+ MALI_DEBUG_PRINT(
+ 1, ("Failed to request MMU '%s' register address space at (0x%08X - 0x%08X)\n",
+ resource->description, resource->base, resource->base + MALI_MMU_REGISTERS_SIZE - 1
+ ));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ mmu = _mali_osk_calloc(1, sizeof(mali_kernel_memory_mmu));
+
+ if (NULL == mmu)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to allocate memory for handling a MMU unit"));
+ _mali_osk_mem_unreqregion(resource->base, MALI_MMU_REGISTERS_SIZE);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ /* basic setup */
+ _MALI_OSK_INIT_LIST_HEAD(&mmu->list);
+
+ mmu->id = resource->mmu_id;
+ mmu->irq_nr = resource->irq;
+ mmu->flags = resource->flags;
+ mmu->base = resource->base;
+ mmu->mapping_size = MALI_MMU_REGISTERS_SIZE;
+ mmu->description = resource->description; /* no need to copy */
+ _MALI_OSK_INIT_LIST_HEAD(&mmu->callbacks);
+ _MALI_OSK_INIT_LIST_HEAD(&mmu->session_link);
+ mmu->in_page_fault_handler = 0;
+
+ mmu->lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 127-mmu->id);
+ if (NULL == mmu->lock)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to create mmu lock\n"));
+ _mali_osk_mem_unreqregion(mmu->base, mmu->mapping_size);
+ _mali_osk_free(mmu);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* map the registers */
+ mmu->mapped_registers = _mali_osk_mem_mapioregion( mmu->base, mmu->mapping_size, mmu->description );
+ if (NULL == mmu->mapped_registers)
+ {
+ /* failed to map the registers */
+ MALI_DEBUG_PRINT(1, ("Failed to map MMU registers at 0x%08X\n", mmu->base));
+ _mali_osk_lock_term(mmu->lock);
+ _mali_osk_mem_unreqregion(mmu->base, MALI_MMU_REGISTERS_SIZE);
+ _mali_osk_free(mmu);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ MALI_DEBUG_PRINT(4, ("MMU '%s' @ (0x%08X - 0x%08X) mapped to 0x%08X\n",
+ resource->description, resource->base, resource->base + MALI_MMU_REGISTERS_SIZE - 1, mmu->mapped_registers
+ ));
+
+ /* setup MMU interrupt mask */
+ /* set all values to known defaults */
+ mali_mmu_raw_reset(mmu);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ /* setup MMU page directory pointer */
+ /* The mali_page_directory pointer is guaranteed to be 4kb aligned because we've used get_zeroed_page to accquire it */
+ /* convert the kernel virtual address into a physical address and set */
+
+ /* add to our list of MMU's */
+ _mali_osk_list_addtail(&mmu->list, &mmu_head);
+
+ mmu->irq = _mali_osk_irq_init(
+ mmu->irq_nr,
+ mali_kernel_memory_mmu_interrupt_handler_upper_half,
+ mali_kernel_memory_mmu_interrupt_handler_bottom_half,
+ (_mali_osk_irq_trigger_t)mali_mmu_probe_irq_trigger,
+ (_mali_osk_irq_ack_t)mali_mmu_probe_irq_acknowledge,
+ mmu,
+ "mali_mmu_irq_handlers"
+ );
+ if (NULL == mmu->irq)
+ {
+ _mali_osk_list_del(&mmu->list);
+ _mali_osk_lock_term(mmu->lock);
+ _mali_osk_mem_unmapioregion( mmu->base, mmu->mapping_size, mmu->mapped_registers );
+ _mali_osk_mem_unreqregion(resource->base, MALI_MMU_REGISTERS_SIZE);
+ _mali_osk_free(mmu);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* set to a known state */
+ mali_mmu_raw_reset(mmu);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+
+ MALI_DEBUG_PRINT(2, ("MMU registered\n"));
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_fpga(_mali_osk_resource_t * resource)
+{
+ mali_io_address mapping;
+
+ MALI_DEBUG_PRINT(5, ("FPGA framework '%s' @ (0x%08X - 0x%08X)\n",
+ resource->description, resource->base, resource->base + sizeof(u32) * 2 - 1
+ ));
+
+ mapping = _mali_osk_mem_mapioregion(resource->base + 0x1000, sizeof(u32) * 2, "fpga framework");
+ if (mapping)
+ {
+ MALI_DEBUG_CODE(u32 data = )
+ _mali_osk_mem_ioread32(mapping, 0);
+ MALI_DEBUG_PRINT(2, ("FPGA framwork '%s' @ 0x%08X:\n", resource->description, resource->base));
+ MALI_DEBUG_PRINT(2, ("\tBitfile date: %d%02d%02d_%02d%02d\n",
+ (data >> 20),
+ (data >> 16) & 0xF,
+ (data >> 11) & 0x1F,
+ (data >> 6) & 0x1F,
+ (data >> 0) & 0x3F));
+ MALI_DEBUG_CODE(data = )
+ _mali_osk_mem_ioread32(mapping, sizeof(u32));
+ MALI_DEBUG_PRINT(2, ("\tBitfile SCCS rev: %d\n", data));
+
+ _mali_osk_mem_unmapioregion(resource->base + 0x1000, sizeof(u32) *2, mapping);
+ }
+ else MALI_DEBUG_PRINT(1, ("Failed to access FPGA framwork '%s' @ 0x%08X\n", resource->description, resource->base));
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource)
+{
+ mali_physical_memory_allocator * allocator;
+ mali_physical_memory_allocator ** next_allocator_list;
+
+ u32 alloc_order = resource->alloc_order;
+
+ allocator = mali_os_allocator_create(resource->size, resource->cpu_usage_adjust, resource->description);
+ if (NULL == allocator)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to create OS memory allocator\n"));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ allocator->alloc_order = alloc_order;
+
+ /* link in the allocator: insertion into ordered list
+ * resources of the same alloc_order will be Last-in-first */
+ next_allocator_list = &physical_memory_allocators;
+
+ while ( NULL != *next_allocator_list &&
+ (*next_allocator_list)->alloc_order < alloc_order )
+ {
+ next_allocator_list = &((*next_allocator_list)->next);
+ }
+
+ allocator->next = (*next_allocator_list);
+ (*next_allocator_list) = allocator;
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource)
+{
+ mali_physical_memory_allocator * allocator;
+ mali_physical_memory_allocator ** next_allocator_list;
+ dedicated_memory_info * cleanup_data;
+
+ u32 alloc_order = resource->alloc_order;
+
+ /* do the lowlevel linux operation first */
+
+ /* Request ownership of the memory */
+ if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(resource->base, resource->size, resource->description))
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to request memory region %s (0x%08X - 0x%08X)\n", resource->description, resource->base, resource->base + resource->size - 1));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* create generic block allocator object to handle it */
+ allocator = mali_block_allocator_create(resource->base, resource->cpu_usage_adjust, resource->size, resource->description );
+
+ if (NULL == allocator)
+ {
+ MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n"));
+ _mali_osk_mem_unreqregion(resource->base, resource->size);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* save lowlevel cleanup info */
+ allocator->alloc_order = alloc_order;
+
+ cleanup_data = _mali_osk_malloc(sizeof(dedicated_memory_info));
+
+ if (NULL == cleanup_data)
+ {
+ _mali_osk_mem_unreqregion(resource->base, resource->size);
+ allocator->destroy(allocator);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ cleanup_data->base = resource->base;
+ cleanup_data->size = resource->size;
+
+ cleanup_data->next = mem_region_registrations;
+ mem_region_registrations = cleanup_data;
+
+ /* link in the allocator: insertion into ordered list
+ * resources of the same alloc_order will be Last-in-first */
+ next_allocator_list = &physical_memory_allocators;
+
+ while ( NULL != *next_allocator_list &&
+ (*next_allocator_list)->alloc_order < alloc_order )
+ {
+ next_allocator_list = &((*next_allocator_list)->next);
+ }
+
+ allocator->next = (*next_allocator_list);
+ (*next_allocator_list) = allocator;
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t mali_kernel_memory_mmu_interrupt_handler_upper_half(void * data)
+{
+ mali_kernel_memory_mmu * mmu;
+ u32 int_stat;
+ mali_core_renderunit *core;
+
+ if (mali_benchmark) MALI_SUCCESS;
+
+ mmu = (mali_kernel_memory_mmu *)data;
+
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+
+ /* Pointer to core holding this MMU */
+ core = (mali_core_renderunit *)mmu->core;
+
+ if(CORE_OFF == core->state)
+ {
+ MALI_SUCCESS;
+ }
+
+
+ /* check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
+ int_stat = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_STATUS);
+ if (0 == int_stat)
+ {
+ MALI_ERROR(_MALI_OSK_ERR_FAULT); /* no bits set, we are sharing the IRQ line and someone else caused the interrupt */
+ }
+
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, 0);
+
+ mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS);
+
+ if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
+ {
+ _mali_osk_irq_schedulework(mmu->irq);
+ }
+ if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
+ {
+ /* clear interrupt flag */
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ /* reenable it */
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ }
+
+ MALI_SUCCESS;
+}
+
+
+static void mali_kernel_mmu_bus_reset(mali_kernel_memory_mmu * mmu)
+{
+
+#if defined(USING_MALI200)
+ int i;
+ const int replay_buffer_check_interval = 10; /* must be below 1000 */
+ const int replay_buffer_max_number_of_checks = 100;
+#endif
+
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ /* add an extra reference while handling the page fault */
+ mmu->usage_count++;
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_DEBUG_PRINT(4, ("Sending stop bus request to cores\n"));
+ /* request to stop the bus, but don't wait for it to actually stop */
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES, (u32)mmu);
+
+#if defined(USING_MALI200)
+ /* no new request will come from any of the connected cores from now
+ * we must now flush the playback buffer for any requests queued already
+ */
+
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_DEBUG_PRINT(4, ("Switching to the special page fault flush page directory\n"));
+ /* don't use the mali_mmu_activate_address_space function here as we can't stall the MMU */
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_page_fault_flush_page_directory);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+ /* resume the MMU */
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
+ /* the MMU will now play back all the requests, all going to our special page fault flush data page */
+
+ /* just to be safe, check that the playback buffer is empty before continuing */
+ if (!mali_benchmark) {
+ for (i = 0; i < replay_buffer_max_number_of_checks; i++)
+ {
+ if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_REPLAY_BUFFER_EMPTY) break;
+ _mali_osk_time_ubusydelay(replay_buffer_check_interval);
+ }
+
+ MALI_DEBUG_PRINT_IF(1, i == replay_buffer_max_number_of_checks, ("MMU: %s: Failed to flush replay buffer on page fault\n", mmu->description));
+ MALI_DEBUG_PRINT(1, ("Replay playback took %ld usec\n", i * replay_buffer_check_interval));
+ }
+
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+#endif
+ /* notify all subsystems that the core should be reset once the bus is actually stopped */
+ MALI_DEBUG_PRINT(4,("Sending job abort command to subsystems\n"));
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS, (u32)mmu);
+
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* reprogram the MMU */
+ mali_mmu_raw_reset(mmu);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); /* no session is active, so just activate the empty page directory */
+ mali_mmu_enable_paging(mmu);
+
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* release the extra address space reference, will schedule */
+ mali_memory_core_mmu_release_address_space_reference(mmu);
+
+ /* resume normal operation */
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP3_CONTINUE_JOB_HANDLING, (u32)mmu);
+ MALI_DEBUG_PRINT(4, ("Page fault handling complete\n"));
+}
+
+static void mali_mmu_raw_reset(mali_kernel_memory_mmu * mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 1;
+
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET);
+
+ if (!mali_benchmark)
+ {
+ int i;
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_DTE_ADDR) == 0)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Reset request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
+ }
+}
+
+static void mali_mmu_enable_paging(mali_kernel_memory_mmu * mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 1;
+
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
+
+ if (!mali_benchmark)
+ {
+ int i;
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Enable paging request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
+ }
+}
+
+static mali_bool mali_mmu_enable_stall(mali_kernel_memory_mmu * mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 999;
+ int i;
+
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
+
+ if (!mali_benchmark)
+ {
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Enable stall request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
+ if (max_loop_count == i)
+ {
+ return MALI_FALSE;
+ }
+ }
+
+ return MALI_TRUE;
+}
+
+static void mali_mmu_disable_stall(mali_kernel_memory_mmu * mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 1;
+ int i;
+
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
+
+ if (!mali_benchmark)
+ {
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ if ((mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) == 0)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Disable stall request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS)));
+ }
+}
+
+void mali_kernel_mmu_reset(void * input_mmu)
+{
+ mali_kernel_memory_mmu * mmu;
+ MALI_DEBUG_ASSERT_POINTER(input_mmu);
+ mmu = (mali_kernel_memory_mmu *)input_mmu;
+
+ MALI_DEBUG_PRINT(4, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->description));
+
+ if ( 0 != mmu->in_page_fault_handler)
+ {
+ /* This is possible if the bus can never be stopped for some reason */
+ MALI_PRINT_ERROR(("Stopping the Memory bus not possible. Mali reset could not be performed."));
+ return;
+ }
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ mali_mmu_raw_reset(mmu);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); /* no session is active, so just activate the empty page directory */
+ mali_mmu_enable_paging(mmu);
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+}
+
+void mali_kernel_mmu_force_bus_reset(void * input_mmu)
+{
+ mali_kernel_memory_mmu * mmu;
+ MALI_DEBUG_ASSERT_POINTER(input_mmu);
+ mmu = (mali_kernel_memory_mmu *)input_mmu;
+ if ( 0 != mmu->in_page_fault_handler)
+ {
+ /* This is possible if the bus can never be stopped for some reason */
+ MALI_PRINT_ERROR(("Stopping the Memory bus not possible. Mali reset could not be performed."));
+ return;
+ }
+ MALI_DEBUG_PRINT(1, ("Mali MMU: Force_bus_reset.\n"));
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, 0);
+ mali_kernel_mmu_bus_reset(mmu);
+}
+
+
+static void mali_kernel_memory_mmu_interrupt_handler_bottom_half(void * data)
+{
+ mali_kernel_memory_mmu *mmu;
+ u32 raw, fault_address, status;
+ mali_core_renderunit *core;
+
+ MALI_DEBUG_PRINT(1, ("mali_kernel_memory_mmu_interrupt_handler_bottom_half\n"));
+ if (NULL == data)
+ {
+ MALI_PRINT_ERROR(("MMU IRQ work queue: NULL argument"));
+ return; /* Error */
+ }
+ mmu = (mali_kernel_memory_mmu*)data;
+
+
+ MALI_DEBUG_PRINT(4, ("Locking subsystems\n"));
+ /* lock all subsystems */
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP0_LOCK_SUBSYSTEM, (u32)mmu);
+
+ /* Pointer to core holding this MMU */
+ core = (mali_core_renderunit *)mmu->core;
+
+ if(CORE_OFF == core->state)
+ {
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu);
+ return;
+ }
+
+ raw = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_RAWSTAT);
+ status = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS);
+
+ if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) && (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) )
+ {
+ MALI_DEBUG_PRINT(1, ("MMU: Page fault bottom half: No Irq found.\n"));
+ MALI_DEBUG_PRINT(4, ("Unlocking subsystems"));
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu);
+ return;
+ }
+
+ mmu->in_page_fault_handler = 1;
+
+ fault_address = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
+ MALI_PRINT(("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->description)
+ );
+
+ if (NULL == mmu->active_session)
+ {
+ MALI_PRINT(("Spurious memory access detected from MMU %s\n", mmu->description));
+ }
+ else
+ {
+ MALI_PRINT(("Active page directory at 0x%08X\n", mmu->active_session->page_directory));
+ MALI_PRINT(("Info from page table for VA 0x%x:\n", (void*)fault_address));
+ MALI_PRINT(("DTE entry: PTE at 0x%x marked as %s\n",
+ (void*)(_mali_osk_mem_ioread32(mmu->active_session->page_directory_mapped,
+ MALI_MMU_PDE_ENTRY(fault_address) * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK),
+ _mali_osk_mem_ioread32(mmu->active_session->page_directory_mapped,
+ MALI_MMU_PDE_ENTRY(fault_address) * sizeof(u32)) & MALI_MMU_FLAGS_PRESENT ? "present" : "not present"
+ ));
+
+ if (_mali_osk_mem_ioread32(mmu->active_session->page_directory_mapped, MALI_MMU_PDE_ENTRY(fault_address) * sizeof(u32)) & MALI_MMU_FLAGS_PRESENT)
+ {
+ mali_io_address pte;
+ u32 data;
+ pte = mmu->active_session->page_entries_mapped[MALI_MMU_PDE_ENTRY(fault_address)];
+ data = _mali_osk_mem_ioread32(pte, MALI_MMU_PTE_ENTRY(fault_address) * sizeof(u32));
+ MALI_PRINT(("PTE entry: Page at 0x%x, %s %s %s\n",
+ (void*)(data & ~MALI_MMU_FLAGS_MASK),
+ data & MALI_MMU_FLAGS_PRESENT ? "present" : "not present",
+ data & MALI_MMU_FLAGS_READ_PERMISSION ? "readable" : "",
+ data & MALI_MMU_FLAGS_WRITE_PERMISSION ? "writable" : ""
+ ));
+ }
+ else
+ {
+ MALI_PRINT(("PTE entry: Not present\n"));
+ }
+ }
+
+
+ mali_kernel_mmu_bus_reset(mmu);
+
+ mmu->in_page_fault_handler = 0;
+
+ /* unlock all subsystems */
+ MALI_DEBUG_PRINT(4, ("Unlocking subsystems"));
+ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu);
+
+}
+
+
+static u32 mali_mmu_register_read(mali_kernel_memory_mmu * unit, mali_mmu_register reg)
+{
+ u32 val;
+
+ if (mali_benchmark) return 0;
+
+ val = _mali_osk_mem_ioread32(unit->mapped_registers, (u32)reg * sizeof(u32));
+
+ MALI_DEBUG_PRINT(6, ("mali_mmu_register_read addr:0x%04X val:0x%08x\n", (u32)reg * sizeof(u32),val));
+
+ return val;
+}
+
+static void mali_mmu_register_write(mali_kernel_memory_mmu * unit, mali_mmu_register reg, u32 val)
+{
+ if (mali_benchmark) return;
+
+ MALI_DEBUG_PRINT(6, ("mali_mmu_register_write addr:0x%04X val:0x%08x\n", (u32)reg * sizeof(u32), val));
+
+ _mali_osk_mem_iowrite32(unit->mapped_registers, (u32)reg * sizeof(u32), val);
+}
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
+{
+ ump_dd_handle ump_mem;
+ u32 nr_blocks;
+ u32 i;
+ ump_dd_physical_block * ump_blocks;
+ ump_mem_allocation *ret_allocation;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(alloc_info);
+
+ ret_allocation = _mali_osk_malloc( sizeof( ump_mem_allocation ) );
+ if ( NULL==ret_allocation ) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ ump_mem = (ump_dd_handle)ctx;
+
+ MALI_DEBUG_PRINT(4, ("In ump_memory_commit\n"));
+
+ nr_blocks = ump_dd_phys_block_count_get(ump_mem);
+
+ MALI_DEBUG_PRINT(4, ("Have %d blocks\n", nr_blocks));
+
+ if (nr_blocks == 0)
+ {
+ MALI_DEBUG_PRINT(1, ("No block count\n"));
+ _mali_osk_free( ret_allocation );
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ ump_blocks = _mali_osk_malloc(sizeof(*ump_blocks)*nr_blocks );
+ if ( NULL==ump_blocks )
+ {
+ _mali_osk_free( ret_allocation );
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ if (UMP_DD_INVALID == ump_dd_phys_blocks_get(ump_mem, ump_blocks, nr_blocks))
+ {
+ _mali_osk_free(ump_blocks);
+ _mali_osk_free( ret_allocation );
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ /* Store away the initial offset for unmapping purposes */
+ ret_allocation->initial_offset = *offset;
+
+ for(i=0; i<nr_blocks; ++i)
+ {
+ MALI_DEBUG_PRINT(4, ("Mapping in 0x%08x size %d\n", ump_blocks[i].addr , ump_blocks[i].size));
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[i].addr , 0, ump_blocks[i].size ))
+ {
+ u32 size_allocated = *offset - ret_allocation->initial_offset;
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
+
+ /* unmap all previous blocks (if any) */
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
+
+ _mali_osk_free(ump_blocks);
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += ump_blocks[i].size;
+ }
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ /* Map in an extra virtual guard page at the end of the VMA */
+ MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, ump_blocks[0].addr , 0, _MALI_OSK_MALI_PAGE_SIZE ))
+ {
+ u32 size_allocated = *offset - ret_allocation->initial_offset;
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
+
+ /* unmap all previous blocks (if any) */
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
+
+ _mali_osk_free(ump_blocks);
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += _MALI_OSK_MALI_PAGE_SIZE;
+ }
+
+ _mali_osk_free( ump_blocks );
+
+ ret_allocation->engine = engine;
+ ret_allocation->descriptor = descriptor;
+ ret_allocation->ump_mem = ump_mem;
+ ret_allocation->size_allocated = *offset - ret_allocation->initial_offset;
+
+ alloc_info->ctx = NULL;
+ alloc_info->handle = ret_allocation;
+ alloc_info->next = NULL;
+ alloc_info->release = ump_memory_release;
+
+ return MALI_MEM_ALLOC_FINISHED;
+}
+
+static void ump_memory_release(void * ctx, void * handle)
+{
+ ump_dd_handle ump_mem;
+ ump_mem_allocation *allocation;
+
+ allocation = (ump_mem_allocation *)handle;
+
+ MALI_DEBUG_ASSERT_POINTER( allocation );
+
+ ump_mem = allocation->ump_mem;
+
+ MALI_DEBUG_ASSERT(UMP_DD_HANDLE_INVALID!=ump_mem);
+
+ /* At present, this is a no-op. But, it allows the mali_address_manager to
+ * do unmapping of a subrange in future. */
+ mali_allocation_engine_unmap_physical( allocation->engine,
+ allocation->descriptor,
+ allocation->initial_offset,
+ allocation->size_allocated,
+ (_mali_osk_mem_mapregion_flags_t)0
+ );
+ _mali_osk_free( allocation );
+
+
+ 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;
+ mali_physical_memory_allocator external_memory_allocator;
+ memory_session * session_data;
+ mali_memory_allocation * descriptor;
+ int md;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+ MALI_CHECK_NON_NULL(session_data, _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_osk_calloc(1, sizeof(mali_memory_allocation));
+ if (NULL == descriptor)
+ {
+ ump_dd_reference_release(ump_mem);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ descriptor->size = args->size;
+ descriptor->mapping = NULL;
+ descriptor->mali_address = args->mali_address;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+ descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
+ descriptor->lock = session_data->lock;
+ if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE)
+ {
+ descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE;
+ }
+ _mali_osk_list_init( &descriptor->list );
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
+ {
+ ump_dd_reference_release(ump_mem);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ external_memory_allocator.allocate = ump_memory_commit;
+ external_memory_allocator.allocate_page_table_block = NULL;
+ external_memory_allocator.ctx = ump_mem;
+ external_memory_allocator.name = "UMP Memory";
+ external_memory_allocator.next = NULL;
+
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
+ {
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
+ ump_dd_reference_release(ump_mem);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ args->cookie = md;
+
+ MALI_DEBUG_PRINT(5,("Returning from UMP attach\n"));
+
+ /* All OK */
+ MALI_SUCCESS;
+}
+
+
+_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args )
+{
+ mali_memory_allocation * descriptor;
+ memory_session * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->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);
+ }
+
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
+
+ _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW );
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+
+ _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW );
+
+ _mali_osk_free(descriptor);
+
+ MALI_SUCCESS;
+
+}
+#endif /* MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 */
+
+
+static mali_physical_memory_allocation_result external_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
+{
+ u32 * data;
+ external_mem_allocation * ret_allocation;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(alloc_info);
+
+ ret_allocation = _mali_osk_malloc( sizeof(external_mem_allocation) );
+
+ if ( NULL == ret_allocation )
+ {
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+
+ data = (u32*)ctx;
+
+ ret_allocation->engine = engine;
+ ret_allocation->descriptor = descriptor;
+ ret_allocation->initial_offset = *offset;
+
+ alloc_info->ctx = NULL;
+ alloc_info->handle = ret_allocation;
+ alloc_info->next = NULL;
+ alloc_info->release = external_memory_release;
+
+ MALI_DEBUG_PRINT(3, ("External map: mapping phys 0x%08X at mali virtual address 0x%08X staring at offset 0x%08X length 0x%08X\n", data[0], descriptor->mali_address, *offset, data[1]));
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, data[1]))
+ {
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory failed\n"));
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += data[1];
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ /* Map in an extra virtual guard page at the end of the VMA */
+ MALI_DEBUG_PRINT(4, ("Mapping in extra guard page\n"));
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_map_physical(engine, descriptor, *offset, data[0], 0, _MALI_OSK_MALI_PAGE_SIZE))
+ {
+ u32 size_allocated = *offset - ret_allocation->initial_offset;
+ MALI_DEBUG_PRINT(1, ("Mapping of external memory (guard page) failed\n"));
+
+ /* unmap what we previously mapped */
+ mali_allocation_engine_unmap_physical(engine, descriptor, ret_allocation->initial_offset, size_allocated, (_mali_osk_mem_mapregion_flags_t)0 );
+ _mali_osk_free(ret_allocation);
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ }
+ *offset += _MALI_OSK_MALI_PAGE_SIZE;
+ }
+
+ ret_allocation->size = *offset - ret_allocation->initial_offset;
+
+ return MALI_MEM_ALLOC_FINISHED;
+}
+
+static void external_memory_release(void * ctx, void * handle)
+{
+ external_mem_allocation * allocation;
+
+ allocation = (external_mem_allocation *) handle;
+ MALI_DEBUG_ASSERT_POINTER( allocation );
+
+ /* At present, this is a no-op. But, it allows the mali_address_manager to
+ * do unmapping of a subrange in future. */
+
+ mali_allocation_engine_unmap_physical( allocation->engine,
+ allocation->descriptor,
+ allocation->initial_offset,
+ allocation->size,
+ (_mali_osk_mem_mapregion_flags_t)0
+ );
+
+ _mali_osk_free( allocation );
+
+ return;
+}
+
+_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
+{
+ mali_physical_memory_allocator external_memory_allocator;
+ memory_session * session_data;
+ u32 info[2];
+ mali_memory_allocation * descriptor;
+ int md;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ external_memory_allocator.allocate = external_memory_commit;
+ external_memory_allocator.allocate_page_table_block = NULL;
+ external_memory_allocator.ctx = &info[0];
+ external_memory_allocator.name = "External Memory";
+ external_memory_allocator.next = NULL;
+
+ /* 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 */
+ MALI_CHECK_NO_ERROR( mali_kernel_core_validate_mali_phys_range( args->phys_addr, args->size ) );
+
+ info[0] = args->phys_addr;
+ info[1] = args->size;
+
+ descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
+ if (NULL == descriptor) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+ descriptor->size = args->size;
+ descriptor->mapping = NULL;
+ descriptor->mali_address = args->mali_address;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+ descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */
+ descriptor->lock = session_data->lock;
+ if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE)
+ {
+ descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE;
+ }
+ _mali_osk_list_init( &descriptor->list );
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
+ {
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL))
+ {
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, md);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ args->cookie = md;
+
+ MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n"));
+
+ /* All OK */
+ MALI_SUCCESS;
+}
+
+
+_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args )
+{
+ mali_memory_allocation * descriptor;
+ memory_session * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+ MALI_CHECK_NON_NULL(session_data, _MALI_OSK_ERR_INVALID_ARGS);
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session_data->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);
+ }
+
+ mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
+
+ _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW );
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+
+ _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW );
+
+ _mali_osk_free(descriptor);
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args )
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ args->memory_size = 2 * 1024 * 1024 * 1024UL; /* 2GB address space */
+ args->mali_address_base = 1 * 1024 * 1024 * 1024UL; /* staring at 1GB, causing this layout: (0-1GB unused)(1GB-3G usage by Mali)(3G-4G unused) */
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_term_mem( _mali_uk_term_mem_s *args )
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_mmu_page_table_cache_create(void)
+{
+ page_table_cache.lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 110);
+ MALI_CHECK_NON_NULL( page_table_cache.lock, _MALI_OSK_ERR_FAULT );
+ _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.partial);
+ _MALI_OSK_INIT_LIST_HEAD(&page_table_cache.full);
+ MALI_SUCCESS;
+}
+
+void mali_mmu_page_table_cache_destroy(void)
+{
+ mali_mmu_page_table_allocation * alloc, *temp;
+
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
+ {
+ MALI_DEBUG_PRINT_IF(1, 0 != alloc->usage_count, ("Destroying page table cache while pages are tagged as in use. %d allocations still marked as in use.\n", alloc->usage_count));
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+
+ MALI_DEBUG_PRINT_IF(1, 0 == _mali_osk_list_empty(&page_table_cache.full), ("Page table cache full list contains one or more elements \n"));
+
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp, &page_table_cache.full, mali_mmu_page_table_allocation, list)
+ {
+ MALI_DEBUG_PRINT(1, ("Destroy alloc 0x%08X with usage count %d\n", (u32)alloc, alloc->usage_count));
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+
+ _mali_osk_lock_term(page_table_cache.lock);
+}
+
+_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping)
+{
+ _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (0 == _mali_osk_list_empty(&page_table_cache.partial))
+ {
+ mali_mmu_page_table_allocation * alloc = _MALI_OSK_LIST_ENTRY(page_table_cache.partial.next, mali_mmu_page_table_allocation, list);
+ int page_number = _mali_osk_find_first_zero_bit(alloc->usage_map, alloc->num_pages);
+ MALI_DEBUG_PRINT(6, ("Partial page table allocation found, using page offset %d\n", page_number));
+ _mali_osk_set_nonatomic_bit(page_number, alloc->usage_map);
+ alloc->usage_count++;
+ if (alloc->num_pages == alloc->usage_count)
+ {
+ /* full, move alloc to full list*/
+ _mali_osk_list_move(&alloc->list, &page_table_cache.full);
+ }
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+
+ *table_page = (MALI_MMU_PAGE_SIZE * page_number) + alloc->pages.phys_base;
+ *mapping = (mali_io_address)((MALI_MMU_PAGE_SIZE * page_number) + (u32)alloc->pages.mapping);
+ MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
+ MALI_SUCCESS;
+ }
+ else
+ {
+ mali_mmu_page_table_allocation * alloc;
+ /* no free pages, allocate a new one */
+
+ alloc = (mali_mmu_page_table_allocation *)_mali_osk_calloc(1, sizeof(mali_mmu_page_table_allocation));
+ if (NULL == alloc)
+ {
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = MALI_INVALID_PAGE;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _MALI_OSK_INIT_LIST_HEAD(&alloc->list);
+
+ if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_page_tables(memory_engine, &alloc->pages, physical_memory_allocators))
+ {
+ MALI_DEBUG_PRINT(1, ("No more memory for page tables\n"));
+ _mali_osk_free(alloc);
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = MALI_INVALID_PAGE;
+ *mapping = NULL;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ /* create the usage map */
+ alloc->num_pages = alloc->pages.size / MALI_MMU_PAGE_SIZE;
+ alloc->usage_count = 1;
+ MALI_DEBUG_PRINT(3, ("New page table cache expansion, %d pages in new cache allocation\n", alloc->num_pages));
+ alloc->usage_map = _mali_osk_calloc(1, ((alloc->num_pages + BITS_PER_LONG - 1) & ~(BITS_PER_LONG-1) / BITS_PER_LONG) * sizeof(unsigned long));
+ if (NULL == alloc->usage_map)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to allocate memory to describe MMU page table cache usage\n"));
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc);
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = MALI_INVALID_PAGE;
+ *mapping = NULL;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ /* clear memory allocation */
+ fill_page(alloc->pages.mapping, 0);
+
+ _mali_osk_set_nonatomic_bit(0, alloc->usage_map);
+
+ if (alloc->num_pages > 1)
+ {
+ _mali_osk_list_add(&alloc->list, &page_table_cache.partial);
+ }
+ else
+ {
+ _mali_osk_list_add(&alloc->list, &page_table_cache.full);
+ }
+
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ *table_page = alloc->pages.phys_base; /* return the first page */
+ *mapping = alloc->pages.mapping; /* Mapping for first page */
+ MALI_DEBUG_PRINT(4, ("Page table allocated for VA=0x%08X, MaliPA=0x%08X\n", *mapping, *table_page ));
+ MALI_SUCCESS;
+ }
+}
+
+void mali_mmu_release_table_page(u32 pa)
+{
+ mali_mmu_page_table_allocation * alloc, * temp_alloc;
+
+ MALI_DEBUG_PRINT_IF(1, pa & 4095, ("Bad page address 0x%x given to mali_mmu_release_table_page\n", (void*)pa));
+
+ MALI_DEBUG_PRINT(4, ("Releasing table page 0x%08X to the cache\n", pa));
+
+ _mali_osk_lock_wait(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* find the entry this address belongs to */
+ /* first check the partial list */
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.partial, mali_mmu_page_table_allocation, list)
+ {
+ u32 start = alloc->pages.phys_base;
+ u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
+ if (pa >= start && pa <= last)
+ {
+ MALI_DEBUG_ASSERT(0 != _mali_osk_test_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map));
+ _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
+ alloc->usage_count--;
+
+ _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
+
+ if (0 == alloc->usage_count)
+ {
+ /* empty, release whole page alloc */
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_DEBUG_PRINT(4, ("(partial list)Released table page 0x%08X to the cache\n", pa));
+ return;
+ }
+ }
+
+ /* the check the full list */
+ _MALI_OSK_LIST_FOREACHENTRY(alloc, temp_alloc, &page_table_cache.full, mali_mmu_page_table_allocation, list)
+ {
+ u32 start = alloc->pages.phys_base;
+ u32 last = start + (alloc->num_pages - 1) * MALI_MMU_PAGE_SIZE;
+ if (pa >= start && pa <= last)
+ {
+ _mali_osk_clear_nonatomic_bit((pa - start)/MALI_MMU_PAGE_SIZE, alloc->usage_map);
+ alloc->usage_count--;
+
+ _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE);
+
+
+ if (0 == alloc->usage_count)
+ {
+ /* empty, release whole page alloc */
+ _mali_osk_list_del(&alloc->list);
+ alloc->pages.release(&alloc->pages);
+ _mali_osk_free(alloc->usage_map);
+ _mali_osk_free(alloc);
+ }
+ else
+ {
+ /* transfer to partial list */
+ _mali_osk_list_move(&alloc->list, &page_table_cache.partial);
+ }
+
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa));
+ return;
+ }
+ }
+
+ MALI_DEBUG_PRINT(1, ("pa 0x%x not found in the page table cache\n", (void*)pa));
+
+ _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+void* mali_memory_core_mmu_lookup(u32 id)
+{
+ mali_kernel_memory_mmu * mmu, * temp_mmu;
+
+ /* find an MMU with a matching id */
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list)
+ {
+ if (id == mmu->id) return mmu;
+ }
+
+ /* not found */
+ return NULL;
+}
+
+void mali_memory_core_mmu_owner(void *core, void *mmu_ptr)
+{
+ mali_kernel_memory_mmu *mmu;
+
+ MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ mmu = (mali_kernel_memory_mmu *)mmu_ptr;
+ mmu->core = core;
+}
+
+void mali_mmu_activate_address_space(mali_kernel_memory_mmu * mmu, u32 page_directory)
+{
+ mali_mmu_enable_stall(mmu); /* this might fail, but changing the DTE address and ZAP should work anyway... */
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+ mali_mmu_disable_stall(mmu);
+}
+
+_mali_osk_errcode_t mali_memory_core_mmu_activate_page_table(void* mmu_ptr, struct mali_session_data * mali_session_data, void(*callback)(void*), void * callback_argument)
+{
+ memory_session * requested_memory_session;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+ mali_kernel_memory_mmu * mmu;
+
+ MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
+ MALI_DEBUG_ASSERT_POINTER(mali_session_data);
+
+ mmu = (mali_kernel_memory_mmu *)mmu_ptr;
+
+ MALI_DEBUG_PRINT(4, ("Asked to activate page table for session 0x%x on MMU %s\n", mali_session_data, mmu->description));
+ requested_memory_session = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
+ MALI_DEBUG_PRINT(5, ("Session 0x%x looked up as using memory session 0x%x\n", mali_session_data, requested_memory_session));
+
+ MALI_DEBUG_ASSERT_POINTER(requested_memory_session);
+
+ MALI_DEBUG_PRINT(7, ("Taking locks\n"));
+
+ _mali_osk_lock_wait(requested_memory_session->lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ if (0 == mmu->usage_count)
+ {
+ /* no session currently active, activate the requested session */
+ MALI_DEBUG_ASSERT(NULL == mmu->active_session);
+ mmu->active_session = requested_memory_session;
+ mmu->usage_count = 1;
+ MALI_DEBUG_PRINT(4, ("MMU idle, activating page directory 0x%08X on MMU %s\n", requested_memory_session->page_directory, mmu->description));
+ mali_mmu_activate_address_space(mmu, requested_memory_session->page_directory);
+ {
+ /* Insert mmu into the right place in the active_mmus list so that
+ * it is still sorted. The list must be sorted by ID so we can get
+ * the mutexes in the right order in
+ * _mali_ukk_mem_munmap_internal().
+ */
+ _mali_osk_list_t *entry;
+ for (entry = requested_memory_session->active_mmus.next;
+ entry != &requested_memory_session->active_mmus;
+ entry = entry->next)
+ {
+ mali_kernel_memory_mmu *temp = _MALI_OSK_LIST_ENTRY(entry, mali_kernel_memory_mmu, session_link);
+ if (mmu->id < temp->id)
+ break;
+ }
+ /* If we broke out, then 'entry' points to the list node of the
+ * first mmu with a greater ID; otherwise, it points to
+ * active_mmus. We want to add *before* this node.
+ */
+ _mali_osk_list_addtail(&mmu->session_link, entry);
+ }
+ err = _MALI_OSK_ERR_OK;
+ }
+
+ /* Allow two cores to run in parallel if they come from the same session */
+ else if (
+ (mmu->in_page_fault_handler == 0) &&
+ (requested_memory_session == mmu->active_session ) &&
+ (0==(MALI_MMU_DISALLOW_PARALLELL_WORK_OF_MALI_CORES & mmu->flags))
+ )
+ {
+ /* nested activation detected, just update the reference count */
+ MALI_DEBUG_PRINT(4, ("Nested activation detected, %d previous activations found\n", mmu->usage_count));
+ mmu->usage_count++;
+ err = _MALI_OSK_ERR_OK;
+ }
+
+ else if (NULL != callback)
+ {
+ /* can't activate right now, notify caller on idle via callback */
+ mali_kernel_memory_mmu_idle_callback * callback_object, * temp_callback_object;
+ int found = 0;
+
+ MALI_DEBUG_PRINT(3, ("The MMU is busy and is using a different address space, callback given\n"));
+ /* check for existing registration */
+ _MALI_OSK_LIST_FOREACHENTRY(callback_object, temp_callback_object, &mmu->callbacks, mali_kernel_memory_mmu_idle_callback, link)
+ {
+ if (callback_object->callback == callback)
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ MALI_DEBUG_PRINT(5, ("Duplicate callback registration found, ignoring\n"));
+ /* callback already registered */
+ err = _MALI_OSK_ERR_BUSY;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(5,("New callback, registering\n"));
+ /* register the new callback */
+ callback_object = _mali_osk_malloc(sizeof(mali_kernel_memory_mmu_idle_callback));
+ if (NULL != callback_object)
+ {
+ MALI_DEBUG_PRINT(7,("Callback struct setup\n"));
+ callback_object->callback = callback;
+ callback_object->callback_argument = callback_argument;
+ _mali_osk_list_addtail(&callback_object->link, &mmu->callbacks);
+ err = _MALI_OSK_ERR_BUSY;
+ }
+ }
+ }
+
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_lock_signal(requested_memory_session->lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_ERROR(err);
+}
+
+void mali_memory_core_mmu_release_address_space_reference(void* mmu_ptr)
+{
+ mali_kernel_memory_mmu_idle_callback * callback_object, * temp;
+ mali_kernel_memory_mmu * mmu;
+ memory_session * session;
+
+ _MALI_OSK_LIST_HEAD(callbacks);
+
+ MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
+ mmu = (mali_kernel_memory_mmu *)mmu_ptr;
+
+ session = mmu->active_session;
+
+ /* support that we handle spurious page faults */
+ if (NULL != session)
+ {
+ _mali_osk_lock_wait(session->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ MALI_DEBUG_PRINT(4, ("Deactivation of address space on MMU %s, %d references exists\n", mmu->description, mmu->usage_count));
+ MALI_DEBUG_ASSERT(0 != mmu->usage_count);
+ mmu->usage_count--;
+ if (0 != mmu->usage_count)
+ {
+ MALI_DEBUG_PRINT(4, ("MMU still in use by this address space, %d references still exists\n", mmu->usage_count));
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ /* support that we handle spurious page faults */
+ if (NULL != session)
+ {
+ _mali_osk_lock_signal(session->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+ return;
+ }
+
+ MALI_DEBUG_PRINT(4, ("Activating the empty page directory on %s\n", mmu->description));
+
+ /* last reference gone, deactivate current address space */
+ mali_mmu_activate_address_space(mmu, mali_empty_page_directory);
+
+ /* unlink from session */
+ _mali_osk_list_delinit(&mmu->session_link);
+ /* remove the active session pointer */
+ mmu->active_session = NULL;
+
+ /* Notify all registered callbacks.
+ * We have to be clever here:
+ * We must call the callbacks with the spinlock unlocked and
+ * the callback list emptied to allow them to re-register.
+ * So we make a copy of the list, clears the list and then later call the callbacks on the local copy
+ */
+ /* copy list */
+ _MALI_OSK_INIT_LIST_HEAD(&callbacks);
+ _mali_osk_list_splice(&mmu->callbacks, &callbacks);
+ /* clear the original, allowing new registrations during the callback */
+ _MALI_OSK_INIT_LIST_HEAD(&mmu->callbacks);
+
+ /* end of mmu manipulation, so safe to unlock */
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* then finally remove the (possible) session lock, supporting that no session was active (spurious page fault handling) */
+ if (NULL != session)
+ {
+ _mali_osk_lock_signal(session->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+
+ _MALI_OSK_LIST_FOREACHENTRY(callback_object, temp, &callbacks, mali_kernel_memory_mmu_idle_callback, link)
+ {
+ MALI_DEBUG_ASSERT_POINTER(callback_object->callback);
+ (callback_object->callback)(callback_object->callback_argument);
+ _mali_osk_list_del(&callback_object->link);
+ _mali_osk_free(callback_object);
+ }
+}
+
+void mali_memory_core_mmu_unregister_callback(void* mmu_ptr, void(*callback)(void*))
+{
+ mali_kernel_memory_mmu_idle_callback * callback_object, * temp_callback_object;
+ mali_kernel_memory_mmu * mmu;
+ MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
+
+ MALI_DEBUG_ASSERT_POINTER(callback);
+ MALI_DEBUG_ASSERT_POINTER(mmu_ptr);
+
+ mmu = (mali_kernel_memory_mmu *)mmu_ptr;
+
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ _MALI_OSK_LIST_FOREACHENTRY(callback_object, temp_callback_object, &mmu->callbacks, mali_kernel_memory_mmu_idle_callback, link)
+ {
+ MALI_DEBUG_ASSERT_POINTER(callback_object->callback);
+ if (callback_object->callback == callback)
+ {
+ _mali_osk_list_del(&callback_object->link);
+ _mali_osk_free(callback_object);
+ break;
+ }
+ }
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor)
+{
+ /* allocate page tables, if needed */
+ int i;
+ const int first_pde_idx = MALI_MMU_PDE_ENTRY(descriptor->mali_address);
+ int last_pde_idx;
+ memory_session * session_data;
+#if defined USING_MALI400_L2_CACHE
+ int has_active_mmus = 0;
+ int page_dir_updated = 0;
+#endif
+
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ last_pde_idx = MALI_MMU_PDE_ENTRY(descriptor->mali_address + _MALI_OSK_MALI_PAGE_SIZE + descriptor->size - 1);
+ }
+ else
+ {
+ last_pde_idx = MALI_MMU_PDE_ENTRY(descriptor->mali_address + descriptor->size - 1);
+ }
+
+ session_data = (memory_session*)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ MALI_DEBUG_PRINT(4, ("allocating page tables for Mali virtual address space 0x%08X to 0x%08X\n", descriptor->mali_address, descriptor->mali_address + descriptor->size - 1));
+
+#if defined USING_MALI400_L2_CACHE
+ if (0 == _mali_osk_list_empty(&session_data->active_mmus))
+ {
+ /*
+ * We have active MMUs, so we are probably in the process of alocating more memory for a suspended GP job (PLBU heap)
+ * From Mali-400 MP r1p0, MMU page directory/tables are also cached by the Mali L2 cache, thus we need to invalidate the page directory
+ * from the L2 cache if we add new page directory entries (PDEs) to the page directory.
+ * We only need to do this when we have an active MMU, because we otherwise invalidate the entire Mali L2 cache before at job start
+ */
+ has_active_mmus = 1;
+ }
+#endif
+
+ for (i = first_pde_idx; i <= last_pde_idx; i++)
+ {
+ if ( 0 == (_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32)) & MALI_MMU_FLAGS_PRESENT) )
+ {
+ u32 pte_phys;
+ mali_io_address pte_mapped;
+ _mali_osk_errcode_t err;
+
+ /* allocate a new page table */
+ MALI_DEBUG_ASSERT(0 == session_data->page_entries_usage_count[i]);
+ MALI_DEBUG_ASSERT(NULL == session_data->page_entries_mapped[i]);
+
+ err = mali_mmu_get_table_page(&pte_phys, &pte_mapped);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ session_data->page_entries_mapped[i] = pte_mapped;
+ MALI_DEBUG_ASSERT_POINTER( session_data->page_entries_mapped[i] );
+
+ _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), pte_phys | MALI_MMU_FLAGS_PRESENT); /* mark page table as present */
+
+ /* update usage count */
+ session_data->page_entries_usage_count[i]++;
+#if defined USING_MALI400_L2_CACHE
+ page_dir_updated = 1;
+#endif
+ continue; /* continue loop */
+ }
+
+ MALI_DEBUG_PRINT(1, ("Page table alloc failed\n"));
+ break; /* abort loop, failed to allocate one or more page tables */
+ }
+ else
+ {
+ session_data->page_entries_usage_count[i]++;
+ }
+ }
+
+ if (i <= last_pde_idx)
+ {
+ /* one or more pages could not be allocated, release reference count for the ones we added one for */
+ /* adjust for the one which caused the for loop to be aborted */
+ i--;
+
+ while (i >= first_pde_idx)
+ {
+ MALI_DEBUG_ASSERT(0 != session_data->page_entries_usage_count[i]);
+ session_data->page_entries_usage_count[i]--;
+ if (0 == session_data->page_entries_usage_count[i])
+ {
+ /* last reference removed */
+ mali_mmu_release_table_page(MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32))));
+ session_data->page_entries_mapped[i] = NULL;
+ _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), 0); /* mark as not present in the page directory */
+ }
+ i--;
+ }
+
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+#if defined USING_MALI400_L2_CACHE
+ if (1 == has_active_mmus && 1 == page_dir_updated)
+ {
+ /*
+ * We have updated the page directory and have an active MMU using it, so invalidate it in the Mali L2 cache.
+ */
+ mali_kernel_l2_cache_invalidate_page(session_data->page_directory);
+ }
+#endif
+
+ /* all OK */
+ MALI_SUCCESS;
+}
+
+static void mali_address_manager_release(mali_memory_allocation * descriptor)
+{
+ int first_pde_idx;
+ int last_pde_idx;
+ memory_session * session_data;
+ u32 mali_address;
+ u32 mali_address_end;
+ u32 left;
+ int i;
+#if defined USING_MALI400_L2_CACHE
+ int has_active_mmus = 0;
+ int page_dir_updated = 0;
+#endif
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ session_data = (memory_session*)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+ MALI_DEBUG_ASSERT_POINTER(session_data->page_directory_mapped);
+
+ mali_address = descriptor->mali_address;
+ mali_address_end = descriptor->mali_address + descriptor->size;
+ left = descriptor->size;
+
+ first_pde_idx = MALI_MMU_PDE_ENTRY(mali_address);
+ last_pde_idx = MALI_MMU_PDE_ENTRY(mali_address_end - 1);
+
+ MALI_DEBUG_PRINT(3, ("Zapping Mali MMU table for address 0x%08X size 0x%08X\n", mali_address, left));
+ MALI_DEBUG_PRINT(4, ("Zapping PDE %d through %d\n", first_pde_idx, last_pde_idx));
+
+#if defined USING_MALI400_L2_CACHE
+ if (0 == _mali_osk_list_empty(&session_data->active_mmus))
+ {
+ /*
+ * From Mali-400 MP r1p0, MMU page directory/tables are also cached by the Mali L2 cache, thus we need to invalidate the page tables
+ * from the L2 cache to ensure that the memory is unmapped.
+ * We only need to do this when we have an active MMU, because we otherwise invalidate the entire Mali L2 cache before at job start
+ */
+ has_active_mmus = 1;
+ }
+#endif
+
+
+ for (i = first_pde_idx; i <= last_pde_idx; i++)
+ {
+ int size_inside_pte = left < 0x400000 ? left : 0x400000;
+ const int first_pte_idx = MALI_MMU_PTE_ENTRY(mali_address);
+ int last_pte_idx = MALI_MMU_PTE_ENTRY(mali_address + size_inside_pte - 1);
+
+ if (last_pte_idx < first_pte_idx)
+ {
+ /* The last_pte_idx is into the next PTE, crop it to fit into this */
+ last_pte_idx = 1023; /* 1024 PTE entries, so 1023 is the last one */
+ size_inside_pte = MALI_MMU_ADDRESS(i + 1, 0) - mali_address;
+ }
+
+ MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped[i]);
+ MALI_DEBUG_ASSERT(0 != session_data->page_entries_usage_count[i]);
+ MALI_DEBUG_PRINT(4, ("PDE %d: zapping entries %d through %d, address 0x%08X, size 0x%08X, left 0x%08X (page table at 0x%08X)\n",
+ i, first_pte_idx, last_pte_idx, mali_address, size_inside_pte, left,
+ MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32)))));
+
+ session_data->page_entries_usage_count[i]--;
+
+ if (0 == session_data->page_entries_usage_count[i])
+ {
+ MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n"));
+ /* last reference removed, no need to zero out each PTE */
+ mali_mmu_release_table_page(MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32))));
+ session_data->page_entries_mapped[i] = NULL;
+ _mali_osk_mem_iowrite32(session_data->page_directory_mapped, i * sizeof(u32), 0); /* mark as not present in the page directory */
+#if defined USING_MALI400_L2_CACHE
+ page_dir_updated = 1;
+#endif
+ }
+ else
+ {
+ int j;
+
+ for (j = first_pte_idx; j <= last_pte_idx; j++)
+ {
+ _mali_osk_mem_iowrite32(session_data->page_entries_mapped[i], j * sizeof(u32), 0);
+ }
+
+#if defined USING_MALI400_L2_CACHE
+ if (1 == has_active_mmus)
+ {
+ /* Invalidate the page we've just modified */
+ mali_kernel_l2_cache_invalidate_page( _mali_osk_mem_ioread32(session_data->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+ }
+#endif
+ }
+ left -= size_inside_pte;
+ mali_address += size_inside_pte;
+ }
+
+#if defined USING_MALI400_L2_CACHE
+ if ((1 == page_dir_updated) && (1== has_active_mmus))
+ {
+ /* The page directory was also updated */
+ mali_kernel_l2_cache_invalidate_page(session_data->page_directory);
+ }
+#endif
+}
+
+static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size)
+{
+ memory_session * session_data;
+ u32 mali_address;
+ u32 mali_address_end;
+ u32 current_phys_addr;
+#if defined USING_MALI400_L2_CACHE
+ int has_active_mmus = 0;
+#endif
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ MALI_DEBUG_ASSERT_POINTER( phys_addr );
+
+ current_phys_addr = *phys_addr;
+
+ session_data = (memory_session*)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ mali_address = descriptor->mali_address + offset;
+ mali_address_end = descriptor->mali_address + offset + size;
+
+#if defined USING_MALI400_L2_CACHE
+ if (0 == _mali_osk_list_empty(&session_data->active_mmus))
+ {
+ /*
+ * We have active MMUs, so we are probably in the process of alocating more memory for a suspended GP job (PLBU heap)
+ * From Mali-400 MP r1p0, MMU page directory/tables are also cached by the Mali L2 cache, thus we need to invalidate the page tables
+ * from the L2 cache when we have allocated more heap memory.
+ * We only need to do this when we have an active MMU, because we otherwise invalidate the entire Mali L2 cache before at job start
+ */
+ has_active_mmus = 1;
+ }
+#endif
+
+ MALI_DEBUG_PRINT(6, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", current_phys_addr, mali_address, size));
+
+ MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped);
+
+ for ( ; mali_address < mali_address_end; mali_address += MALI_MMU_PAGE_SIZE, current_phys_addr += MALI_MMU_PAGE_SIZE)
+ {
+ MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]);
+ _mali_osk_mem_iowrite32_relaxed(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), current_phys_addr | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
+ }
+ _mali_osk_write_mem_barrier();
+
+#if defined USING_MALI400_L2_CACHE
+ if (1 == has_active_mmus)
+ {
+ int i;
+ const int first_pde_idx = MALI_MMU_PDE_ENTRY(mali_address);
+ const int last_pde_idx = MALI_MMU_PDE_ENTRY(mali_address_end - 1);
+
+ /*
+ * Invalidate the updated page table(s), incase they have been used for something
+ * else since last job start (invalidation of entire Mali L2 cache)
+ */
+ for (i = first_pde_idx; i <= last_pde_idx; i++)
+ {
+ mali_kernel_l2_cache_invalidate_page( _mali_osk_mem_ioread32(session_data->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+ }
+ }
+#endif
+
+ MALI_SUCCESS;
+}
+
+/* This handler registered to mali_mmap for MMU builds */
+_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args )
+{
+ struct mali_session_data * mali_session_data;
+ mali_memory_allocation * descriptor;
+ memory_session * session_data;
+
+ /* validate input */
+ if (NULL == args) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: args was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
+
+ /* Unpack arguments */
+ mali_session_data = (struct mali_session_data *)args->ctx;
+
+ if (NULL == mali_session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: mali_session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); }
+
+ MALI_DEBUG_ASSERT( mali_subsystem_memory_id >= 0 );
+
+ session_data = mali_kernel_session_manager_slot_get(mali_session_data, mali_subsystem_memory_id);
+ /* validate input */
+ if (NULL == session_data) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: session data was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); }
+
+ descriptor = (mali_memory_allocation*) _mali_osk_calloc( 1, sizeof(mali_memory_allocation) );
+ if (NULL == descriptor) { MALI_DEBUG_PRINT(3,("mali_ukk_mem_mmap: descriptor was NULL\n")); MALI_ERROR(_MALI_OSK_ERR_NOMEM); }
+
+ descriptor->size = args->size;
+ descriptor->mali_address = args->phys_addr;
+ descriptor->mali_addr_mapping_info = (void*)session_data;
+
+ descriptor->process_addr_mapping_info = args->ukk_private; /* save to be used during physical manager callback */
+ descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE;
+ descriptor->lock = session_data->lock;
+ _mali_osk_list_init( &descriptor->list );
+
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head))
+ {
+ mali_kernel_memory_mmu * mmu, * temp_mmu;
+
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
+ {
+ /* no need to lock the MMU as we own it already */
+ MALI_DEBUG_PRINT(5, ("Zapping the cache of mmu %s as it's using the page table we have updated\n", mmu->description));
+
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ mali_mmu_enable_stall(mmu); /* this might fail, but ZAP should work anyway... */
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+ mali_mmu_disable_stall(mmu);
+
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* All ok, write out any information generated from this call */
+ args->mapping = descriptor->mapping;
+ args->cookie = (u32)descriptor;
+
+ MALI_DEBUG_PRINT(7, ("MMAP OK\n"));
+ /* All done */
+ MALI_SUCCESS;
+ }
+ else
+ {
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ /* OOM, but not a fatal error */
+ MALI_DEBUG_PRINT(4, ("Memory allocation failure, OOM\n"));
+ _mali_osk_free(descriptor);
+ /* Linux will free the CPU address allocation, userspace client the Mali address allocation */
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+}
+
+static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args )
+{
+ memory_session * session_data;
+ mali_kernel_memory_mmu * mmu, * temp_mmu;
+ mali_memory_allocation * descriptor;
+
+ descriptor = (mali_memory_allocation *)args->cookie;
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /** @note args->context unused; we use the memory_session from the cookie */
+ /* args->mapping and args->size are also discarded. They are only necessary
+ for certain do_munmap implementations. However, they could be used to check the
+ descriptor at this point. */
+
+ session_data = (memory_session*)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ /* Stall the MMU(s) which is using the address space we're operating on.
+ * Note that active_mmus must be sorted in order of ID to avoid a mutex
+ * ordering violation.
+ */
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
+ {
+ u32 status;
+ status = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS);
+ if ( MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE == (status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) {
+ MALI_DEBUG_PRINT(2, ("Stopped stall attempt for mmu with id %d since it is in page fault mode.\n", mmu->id));
+ continue;
+ }
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+
+ /*
+ * If we're unable to stall, then make sure we tell our caller that,
+ * the caller should then release the session lock for a while,
+ * then this function again.
+ * This function will fail if we're in page fault mode, and to get
+ * out of page fault mode, the page fault handler must be able to
+ * take the session lock.
+ */
+ if (!mali_mmu_enable_stall(mmu))
+ {
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ return _MALI_OSK_ERR_BUSY;
+ }
+
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
+ {
+ _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+
+ /* This function also removes the memory from the session's memory list */
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+ _mali_osk_free(descriptor);
+
+ /* any L2 maintenance was done during mali_allocation_engine_release_memory */
+ /* the session is locked, so the active mmu list should be the same */
+ /* zap the TLB and resume operation */
+ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link)
+ {
+ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+ mali_mmu_disable_stall(mmu);
+
+ _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW);
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+/* Handler for unmapping memory for MMU builds */
+_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args )
+{
+ mali_memory_allocation * descriptor;
+ _mali_osk_lock_t *descriptor_lock;
+ _mali_osk_errcode_t err;
+
+ descriptor = (mali_memory_allocation *)args->cookie;
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /** @note args->context unused; we use the memory_session from the cookie */
+ /* args->mapping and args->size are also discarded. They are only necessary
+ for certain do_munmap implementations. However, they could be used to check the
+ descriptor at this point. */
+
+ MALI_DEBUG_ASSERT_POINTER((memory_session*)descriptor->mali_addr_mapping_info);
+
+ descriptor_lock = descriptor->lock; /* should point to the session data lock... */
+
+ err = _MALI_OSK_ERR_BUSY;
+ while (err == _MALI_OSK_ERR_BUSY)
+ {
+ if (descriptor_lock)
+ {
+ _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
+ }
+
+ err = _mali_ukk_mem_munmap_internal( args );
+
+ if (descriptor_lock)
+ {
+ _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW );
+ }
+
+ if (err == _MALI_OSK_ERR_BUSY)
+ {
+ /*
+ * Reason for this;
+ * We where unable to stall the MMU, probably because we are in page fault handling.
+ * Sleep for a while with the session lock released, then try again.
+ * Abnormal termination of programs with running Mali jobs is a normal reason for this.
+ */
+ _mali_osk_time_ubusydelay(10);
+ }
+ }
+
+ return err;
+}
+
+/* Is called when the rendercore wants the mmu to give an interrupt */
+static void mali_mmu_probe_irq_trigger(mali_kernel_memory_mmu * mmu)
+{
+ MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_trigger\n"));
+ mali_mmu_register_write(mmu, 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_irq_acknowledge(mali_kernel_memory_mmu * mmu)
+{
+ u32 int_stat;
+
+ int_stat = mali_mmu_register_read(mmu, 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_mmu_register_write(mmu, 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_mmu_register_write(mmu, 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))
+ {
+ MALI_SUCCESS;
+ }
+
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+}
+
+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, int dump_to_serial)
+{
+ if (dump_to_serial) MALI_DEBUG_PRINT(1, ("writereg %08X %08X # %s\n", where, what, comment));
+
+ 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 dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info, int dump_to_serial)
+{
+ if (dump_to_serial)
+ {
+ int i;
+ for (i = 0; i < 256; i++)
+ {
+ MALI_DEBUG_PRINT(1, ("%08X: %08X %08X %08X %08X\n", phys_addr + 16*i, _mali_osk_mem_ioread32(page, (i*4 + 0) * sizeof(u32)),
+ _mali_osk_mem_ioread32(page, (i*4 + 1) * sizeof(u32)),
+ _mali_osk_mem_ioread32(page, (i*4 + 2) * sizeof(u32)),
+ _mali_osk_mem_ioread32(page, (i*4 + 3) * sizeof(u32))));
+
+ }
+ }
+
+ 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(memory_session * session_data, struct dump_info * info)
+{
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+ MALI_DEBUG_ASSERT_POINTER(info);
+
+ if (NULL != session_data->page_directory_mapped)
+ {
+ int i;
+
+ MALI_CHECK_NO_ERROR(
+ dump_page(session_data->page_directory_mapped, session_data->page_directory, info, 0)
+ );
+
+ for (i = 0; i < 1024; i++)
+ {
+ if (NULL != session_data->page_entries_mapped[i])
+ {
+ MALI_CHECK_NO_ERROR(
+ dump_page(session_data->page_entries_mapped[i], _mali_osk_mem_ioread32(session_data->page_directory_mapped, i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info, 0)
+ );
+ }
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_registers(memory_session * session_data, struct dump_info * info)
+{
+ MALI_CHECK_NO_ERROR(writereg(0x00000000, session_data->page_directory, "set the page directory address", info, 0));
+ MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info, 0));
+ MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info, 0));
+ 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 };
+ memory_session * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+
+ MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data, &info));
+ MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data, &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 };
+ memory_session * 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 = (memory_session *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_memory_id);
+
+ info.buffer_left = args->size;
+ info.buffer = args->buffer;
+
+ args->register_writes = info.buffer;
+ MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data, &info));
+
+ args->page_table_dump = info.buffer;
+ MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data, &info));
+
+ args->register_writes_size = info.register_writes_size;
+ args->page_table_dump_size = info.page_table_dump_size;
+
+ MALI_SUCCESS;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_get_big_block( _mali_uk_get_big_block_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/**
+ * Stub function to satisfy UDD interface exclusion requirement.
+ * This is because the Base code compiles in \b both MMU and non-MMU calls,
+ * so both sets must be declared (but the 'unused' set may be stub)
+ */
+_mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args )
+{
+ MALI_IGNORE( args );
+ return _MALI_OSK_ERR_FAULT;
+}
+
+u32 _mali_ukk_report_memory_usage(void)
+{
+ return mali_allocation_engine_memory_usage(physical_memory_allocators);
+}
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.h b/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.h
new file mode 100644
index 00000000000..0462f660385
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_MEM_MMU_H__
+#define __MALI_KERNEL_MEM_MMU_H__
+
+#include "mali_kernel_session_manager.h"
+
+/**
+ * Lookup a MMU core by ID.
+ * @param id ID of the MMU to find
+ * @return NULL if ID not found or valid, non-NULL if a core was found.
+ */
+void* mali_memory_core_mmu_lookup(u32 id);
+
+/**
+ * Set the core pointer of MMU to core owner of MMU
+ *
+ * @param core Core holding this MMU
+ * @param mmu_ptr The MMU whose core pointer needs set to core holding the MMU
+ *
+ */
+void mali_memory_core_mmu_owner(void *core, void *mmu_ptr);
+
+/**
+ * Activate a user session with its address space on the given MMU.
+ * If the session can't be activated due to that the MMU is busy and
+ * a callback pointer is given, the callback will be called once the MMU becomes idle.
+ * If the same callback pointer is registered multiple time it will only be called once.
+ * Nested activations are supported.
+ * Each call must be matched by a call to @see mali_memory_core_mmu_release_address_space_reference
+ *
+ * @param mmu The MMU to activate the address space on
+ * @param mali_session_data The user session object which address space to activate
+ * @param callback Pointer to the function to call when the MMU becomes idle
+ * @param callback_arg Argument given to the callback
+ * @return 0 if the address space was activated, -EBUSY if the MMU was busy, -EFAULT in all other cases.
+ */
+int mali_memory_core_mmu_activate_page_table(void* mmu_ptr, struct mali_session_data * mali_session_data, void(*callback)(void*), void * callback_argument);
+
+/**
+ * Release a reference to the current active address space.
+ * Once the last reference is released any callback(s) registered will be called before the function returns
+ *
+ * @note Caution must be shown calling this function with locks held due to that callback can be called
+ * @param mmu The mmu to release a reference to the active address space of
+ */
+void mali_memory_core_mmu_release_address_space_reference(void* mmu);
+
+/**
+ * Soft reset of MMU - needed after power up
+ *
+ * @param mmu_ptr The MMU pointer registered with the relevant core
+ */
+void mali_kernel_mmu_reset(void * mmu_ptr);
+
+void mali_kernel_mmu_force_bus_reset(void * mmu_ptr);
+
+/**
+ * Unregister a previously registered callback.
+ * @param mmu The MMU to unregister the callback on
+ * @param callback The function to unregister
+ */
+void mali_memory_core_mmu_unregister_callback(void* mmu, void(*callback)(void*));
+
+
+
+#endif /* __MALI_KERNEL_MEM_MMU_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_os.c b/drivers/gpu/arm/mali/common/mali_kernel_mem_os.c
new file mode 100644
index 00000000000..9ac122d05b8
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_os.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_memory_engine.h"
+#include "mali_osk.h"
+
+typedef struct os_allocation
+{
+ u32 num_pages;
+ u32 offset_start;
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+} os_allocation;
+
+typedef struct os_allocator
+{
+ _mali_osk_lock_t *mutex;
+
+ /**
+ * Maximum number of pages to allocate from the OS
+ */
+ u32 num_pages_max;
+
+ /**
+ * Number of pages allocated from the OS
+ */
+ u32 num_pages_allocated;
+
+ /** CPU Usage adjustment (add to mali physical address to get cpu physical address) */
+ u32 cpu_usage_adjust;
+} os_allocator;
+
+static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
+static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block);
+static void os_allocator_release(void * ctx, void * handle);
+static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block );
+static void os_allocator_destroy(mali_physical_memory_allocator * allocator);
+static u32 os_allocator_stat(mali_physical_memory_allocator * allocator);
+
+mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name)
+{
+ mali_physical_memory_allocator * allocator;
+ os_allocator * info;
+
+ max_allocation = (max_allocation + _MALI_OSK_CPU_PAGE_SIZE-1) & ~(_MALI_OSK_CPU_PAGE_SIZE-1);
+
+ MALI_DEBUG_PRINT(2, ("Mali OS memory allocator created with max allocation size of 0x%X bytes, cpu_usage_adjust 0x%08X\n", max_allocation, cpu_usage_adjust));
+
+ allocator = _mali_osk_malloc(sizeof(mali_physical_memory_allocator));
+ if (NULL != allocator)
+ {
+ info = _mali_osk_malloc(sizeof(os_allocator));
+ if (NULL != info)
+ {
+ info->num_pages_max = max_allocation / _MALI_OSK_CPU_PAGE_SIZE;
+ info->num_pages_allocated = 0;
+ info->cpu_usage_adjust = cpu_usage_adjust;
+
+ info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, 106);
+ if (NULL != info->mutex)
+ {
+ allocator->allocate = os_allocator_allocate;
+ allocator->allocate_page_table_block = os_allocator_allocate_page_table_block;
+ allocator->destroy = os_allocator_destroy;
+ allocator->stat = os_allocator_stat;
+ allocator->ctx = info;
+ allocator->name = name;
+
+ return allocator;
+ }
+ _mali_osk_free(info);
+ }
+ _mali_osk_free(allocator);
+ }
+
+ return NULL;
+}
+
+static u32 os_allocator_stat(mali_physical_memory_allocator * allocator)
+{
+ os_allocator * info;
+ info = (os_allocator*)allocator->ctx;
+ return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE;
+}
+
+static void os_allocator_destroy(mali_physical_memory_allocator * allocator)
+{
+ os_allocator * info;
+ MALI_DEBUG_ASSERT_POINTER(allocator);
+ MALI_DEBUG_ASSERT_POINTER(allocator->ctx);
+ info = (os_allocator*)allocator->ctx;
+ _mali_osk_lock_term(info->mutex);
+ _mali_osk_free(info);
+ _mali_osk_free(allocator);
+}
+
+static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
+{
+ mali_physical_memory_allocation_result result = MALI_MEM_ALLOC_NONE;
+ u32 left;
+ os_allocator * info;
+ os_allocation * allocation;
+ int pages_allocated = 0;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(offset);
+ MALI_DEBUG_ASSERT_POINTER(alloc_info);
+
+ info = (os_allocator*)ctx;
+ left = descriptor->size - *offset;
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ /** @note this code may not work on Linux, or may require a more complex Linux implementation */
+ allocation = _mali_osk_malloc(sizeof(os_allocation));
+ if (NULL != allocation)
+ {
+ u32 os_mem_max_usage = info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE;
+ allocation->offset_start = *offset;
+ allocation->num_pages = ((left + _MALI_OSK_CPU_PAGE_SIZE - 1) & ~(_MALI_OSK_CPU_PAGE_SIZE - 1)) >> _MALI_OSK_CPU_PAGE_ORDER;
+ MALI_DEBUG_PRINT(6, ("Allocating page array of size %d bytes\n", allocation->num_pages * sizeof(struct page*)));
+
+ while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max) && _mali_osk_mem_check_allocated(os_mem_max_usage))
+ {
+ err = mali_allocation_engine_map_physical(engine, descriptor, *offset, MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, info->cpu_usage_adjust, _MALI_OSK_CPU_PAGE_SIZE);
+ if ( _MALI_OSK_ERR_OK != err)
+ {
+ if ( _MALI_OSK_ERR_NOMEM == err)
+ {
+ /* 'Partial' allocation (or, out-of-memory on first page) */
+ break;
+ }
+
+ MALI_DEBUG_PRINT(1, ("Mapping of physical memory failed\n"));
+
+ /* Fatal error, cleanup any previous pages allocated. */
+ if ( pages_allocated > 0 )
+ {
+ mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*pages_allocated, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR );
+ /* (*offset) doesn't need to be restored; it will not be used by the caller on failure */
+ }
+
+ pages_allocated = 0;
+
+ result = MALI_MEM_ALLOC_INTERNAL_FAILURE;
+ break;
+ }
+
+ /* Loop iteration */
+ if (left < _MALI_OSK_CPU_PAGE_SIZE) left = 0;
+ else left -= _MALI_OSK_CPU_PAGE_SIZE;
+
+ pages_allocated++;
+
+ *offset += _MALI_OSK_CPU_PAGE_SIZE;
+ }
+
+ if (left) MALI_PRINT(("Out of memory. Mali memory allocated: %d kB Configured maximum OS memory usage: %d kB\n",
+ (info->num_pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024));
+
+ /* Loop termination; decide on result */
+ if (pages_allocated)
+ {
+ MALI_DEBUG_PRINT(6, ("Allocated %d pages\n", pages_allocated));
+ if (left) result = MALI_MEM_ALLOC_PARTIAL;
+ else result = MALI_MEM_ALLOC_FINISHED;
+
+ /* 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.
+ */
+ _mali_osk_cache_ensure_uncached_range_flushed( (void *)descriptor, allocation->offset_start, pages_allocated *_MALI_OSK_CPU_PAGE_SIZE );
+ allocation->num_pages = pages_allocated;
+ allocation->engine = engine; /* Necessary to make the engine's unmap call */
+ allocation->descriptor = descriptor; /* Necessary to make the engine's unmap call */
+ info->num_pages_allocated += pages_allocated;
+
+ MALI_DEBUG_PRINT(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max));
+
+ alloc_info->ctx = info;
+ alloc_info->handle = allocation;
+ alloc_info->release = os_allocator_release;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(6, ("Releasing pages array due to no pages allocated\n"));
+ _mali_osk_free( allocation );
+ }
+ }
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+
+ return result;
+}
+
+static void os_allocator_release(void * ctx, void * handle)
+{
+ os_allocator * info;
+ os_allocation * allocation;
+ mali_allocation_engine * engine;
+ mali_memory_allocation * descriptor;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ MALI_DEBUG_ASSERT_POINTER(handle);
+
+ info = (os_allocator*)ctx;
+ allocation = (os_allocation*)handle;
+ engine = allocation->engine;
+ descriptor = allocation->descriptor;
+
+ MALI_DEBUG_ASSERT_POINTER( engine );
+ MALI_DEBUG_ASSERT_POINTER( descriptor );
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW))
+ {
+ MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n"));
+ return;
+ }
+
+ MALI_DEBUG_PRINT(6, ("Releasing %d os pages\n", allocation->num_pages));
+
+ MALI_DEBUG_ASSERT( allocation->num_pages <= info->num_pages_allocated);
+ info->num_pages_allocated -= allocation->num_pages;
+
+ mali_allocation_engine_unmap_physical( engine, descriptor, allocation->offset_start, _MALI_OSK_CPU_PAGE_SIZE*allocation->num_pages, _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR );
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+
+ _mali_osk_free(allocation);
+}
+
+static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block)
+{
+ int allocation_order = 6; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */
+ void *virt = NULL;
+ u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order;
+ os_allocator * info;
+
+ u32 cpu_phys_base;
+
+ MALI_DEBUG_ASSERT_POINTER(ctx);
+ info = (os_allocator*)ctx;
+
+ /* Ensure we don't allocate more than we're supposed to from the ctx */
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE;
+
+ /* if the number of pages to be requested lead to exceeding the memory
+ * limit in info->num_pages_max, reduce the size that is to be requested. */
+ while ( (info->num_pages_allocated + (1 << allocation_order) > info->num_pages_max)
+ && _mali_osk_mem_check_allocated(info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE) )
+ {
+ if ( allocation_order > 0 ) {
+ --allocation_order;
+ } else {
+ /* return OOM */
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+ return MALI_MEM_ALLOC_NONE;
+ }
+ }
+
+ /* try to allocate 2^(allocation_order) pages, if that fails, try
+ * allocation_order-1 to allocation_order 0 (inclusive) */
+ while ( allocation_order >= 0 )
+ {
+ size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order;
+ virt = _mali_osk_mem_allocioregion( &cpu_phys_base, size );
+
+ if (NULL != virt) break;
+
+ --allocation_order;
+ }
+
+ if ( NULL == virt )
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to allocate consistent memory. Is CONSISTENT_DMA_SIZE set too low?\n"));
+ /* return OOM */
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+ return MALI_MEM_ALLOC_NONE;
+ }
+
+ MALI_DEBUG_PRINT(5, ("os_allocator_allocate_page_table_block: Allocation of order %i succeeded\n",
+ allocation_order));
+
+ /* we now know the size of the allocation since we know for what
+ * allocation_order the allocation succeeded */
+ size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order;
+
+
+ block->release = os_allocator_page_table_block_release;
+ block->ctx = ctx;
+ block->handle = (void*)allocation_order;
+ block->size = size;
+ block->phys_base = cpu_phys_base - info->cpu_usage_adjust;
+ block->mapping = virt;
+
+ info->num_pages_allocated += (1 << allocation_order);
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+
+ return MALI_MEM_ALLOC_FINISHED;
+}
+
+static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block )
+{
+ os_allocator * info;
+ u32 allocation_order;
+ u32 pages_allocated;
+
+ MALI_DEBUG_ASSERT_POINTER( page_table_block );
+
+ info = (os_allocator*)page_table_block->ctx;
+
+ MALI_DEBUG_ASSERT_POINTER( info );
+
+ allocation_order = (u32)page_table_block->handle;
+
+ pages_allocated = 1 << allocation_order;
+
+ MALI_DEBUG_ASSERT( pages_allocated * _MALI_OSK_CPU_PAGE_SIZE == page_table_block->size );
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW))
+ {
+ MALI_DEBUG_PRINT(1, ("allocator release: Failed to get mutex\n"));
+ return;
+ }
+
+ MALI_DEBUG_ASSERT( pages_allocated <= info->num_pages_allocated);
+ info->num_pages_allocated -= pages_allocated;
+
+ /* Adjust phys_base from mali physical address to CPU physical address */
+ _mali_osk_mem_freeioregion( page_table_block->phys_base + info->cpu_usage_adjust, page_table_block->size, page_table_block->mapping );
+
+ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW);
+}
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_os.h b/drivers/gpu/arm/mali/common/mali_kernel_mem_os.h
new file mode 100644
index 00000000000..59e6494c5eb
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_os.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_MEM_OS_H__
+#define __MALI_KERNEL_MEM_OS_H__
+
+/**
+ * @brief Creates an object that manages allocating OS memory
+ *
+ * Creates an object that provides an interface to allocate OS memory and
+ * have it mapped into the Mali virtual memory space.
+ *
+ * The object exposes pointers to
+ * - allocate OS memory
+ * - allocate Mali page tables in OS memory
+ * - destroy the object
+ *
+ * Allocations from OS memory are of type mali_physical_memory_allocation
+ * which provides a function to release the allocation.
+ *
+ * @param max_allocation max. number of bytes that can be allocated from OS memory
+ * @param cpu_usage_adjust value to add to mali physical addresses to obtain CPU physical addresses
+ * @param name description of the allocator
+ * @return pointer to mali_physical_memory_allocator object. NULL on failure.
+ **/
+mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name);
+
+#endif /* __MALI_KERNEL_MEM_OS_H__ */
+
+
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_memory_engine.c b/drivers/gpu/arm/mali/common/mali_kernel_memory_engine.c
new file mode 100644
index 00000000000..8bb80e63cbf
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_memory_engine.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_memory_engine.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+
+typedef struct memory_engine
+{
+ mali_kernel_mem_address_manager * mali_address;
+ mali_kernel_mem_address_manager * process_address;
+} memory_engine;
+
+mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager)
+{
+ memory_engine * engine;
+
+ /* Mali Address Manager need not support unmap_physical */
+ MALI_DEBUG_ASSERT_POINTER(mali_address_manager);
+ MALI_DEBUG_ASSERT_POINTER(mali_address_manager->allocate);
+ MALI_DEBUG_ASSERT_POINTER(mali_address_manager->release);
+ MALI_DEBUG_ASSERT_POINTER(mali_address_manager->map_physical);
+
+ /* Process Address Manager must support unmap_physical for OS allocation
+ * error path handling */
+ MALI_DEBUG_ASSERT_POINTER(process_address_manager);
+ MALI_DEBUG_ASSERT_POINTER(process_address_manager->allocate);
+ MALI_DEBUG_ASSERT_POINTER(process_address_manager->release);
+ MALI_DEBUG_ASSERT_POINTER(process_address_manager->map_physical);
+ MALI_DEBUG_ASSERT_POINTER(process_address_manager->unmap_physical);
+
+
+ engine = (memory_engine*)_mali_osk_malloc(sizeof(memory_engine));
+ if (NULL == engine) return NULL;
+
+ engine->mali_address = mali_address_manager;
+ engine->process_address = process_address_manager;
+
+ return (mali_allocation_engine)engine;
+}
+
+void mali_allocation_engine_destroy(mali_allocation_engine engine)
+{
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ _mali_osk_free(engine);
+}
+
+_mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_allocators, _mali_osk_list_t *tracking_list )
+{
+ memory_engine * engine = (memory_engine*)mem_engine;
+
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(physical_allocators);
+ /* ASSERT that the list member has been initialized, even if it won't be
+ * used for tracking. We need it to be initialized to see if we need to
+ * delete it from a list in the release function. */
+ MALI_DEBUG_ASSERT( NULL != descriptor->list.next && NULL != descriptor->list.prev );
+
+ if (_MALI_OSK_ERR_OK == engine->mali_address->allocate(descriptor))
+ {
+ _mali_osk_errcode_t res = _MALI_OSK_ERR_OK;
+ if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE )
+ {
+ res = engine->process_address->allocate(descriptor);
+ }
+ if ( _MALI_OSK_ERR_OK == res )
+ {
+ /* address space setup OK, commit physical memory to the allocation */
+ mali_physical_memory_allocator * active_allocator = physical_allocators;
+ struct mali_physical_memory_allocation * active_allocation_tracker = &descriptor->physical_allocation;
+ u32 offset = 0;
+
+ while ( NULL != active_allocator )
+ {
+ switch (active_allocator->allocate(active_allocator->ctx, mem_engine, descriptor, &offset, active_allocation_tracker))
+ {
+ case MALI_MEM_ALLOC_FINISHED:
+ if ( NULL != tracking_list )
+ {
+ /* Insert into the memory session list */
+ /* ASSERT that it is not already part of a list */
+ MALI_DEBUG_ASSERT( _mali_osk_list_empty( &descriptor->list ) );
+ _mali_osk_list_add( &descriptor->list, tracking_list );
+ }
+
+ MALI_SUCCESS; /* all done */
+ case MALI_MEM_ALLOC_NONE:
+ /* reuse current active_allocation_tracker */
+ MALI_DEBUG_PRINT( 4, ("Memory Engine Allocate: No allocation on %s, resorting to %s\n",
+ ( active_allocator->name ) ? active_allocator->name : "UNNAMED",
+ ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") );
+ active_allocator = active_allocator->next;
+ break;
+ case MALI_MEM_ALLOC_PARTIAL:
+ if (NULL != active_allocator->next)
+ {
+ /* need a new allocation tracker */
+ active_allocation_tracker->next = _mali_osk_calloc(1, sizeof(mali_physical_memory_allocation));
+ if (NULL != active_allocation_tracker->next)
+ {
+ active_allocation_tracker = active_allocation_tracker->next;
+ MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate: Partial allocation on %s, resorting to %s\n",
+ ( active_allocator->name ) ? active_allocator->name : "UNNAMED",
+ ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") );
+ active_allocator = active_allocator->next;
+ break;
+ }
+ }
+ /* FALL THROUGH */
+ case MALI_MEM_ALLOC_INTERNAL_FAILURE:
+ active_allocator = NULL; /* end the while loop */
+ break;
+ }
+ }
+
+ MALI_PRINT(("Memory allocate failed, could not allocate size %d kB.\n", descriptor->size/1024));
+
+ /* allocation failure, start cleanup */
+ /* loop over any potential partial allocations */
+ active_allocation_tracker = &descriptor->physical_allocation;
+ while (NULL != active_allocation_tracker)
+ {
+ /* handle blank trackers which will show up during failure */
+ if (NULL != active_allocation_tracker->release)
+ {
+ active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle);
+ }
+ active_allocation_tracker = active_allocation_tracker->next;
+ }
+
+ /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */
+ for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; )
+ {
+ void * buf = active_allocation_tracker;
+ active_allocation_tracker = active_allocation_tracker->next;
+ _mali_osk_free(buf);
+ }
+
+ /* release the address spaces */
+
+ if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE )
+ {
+ engine->process_address->release(descriptor);
+ }
+ }
+ engine->mali_address->release(descriptor);
+ }
+
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+}
+
+void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor)
+{
+ memory_engine * engine = (memory_engine*)mem_engine;
+ mali_physical_memory_allocation * active_allocation_tracker;
+
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /* Determine whether we need to remove this from a tracking list */
+ if ( ! _mali_osk_list_empty( &descriptor->list ) )
+ {
+ _mali_osk_list_del( &descriptor->list );
+ /* Clear the list for debug mode, catch use-after-free */
+ MALI_DEBUG_CODE( descriptor->list.next = descriptor->list.prev = NULL; )
+ }
+
+ engine->mali_address->release(descriptor);
+
+ active_allocation_tracker = &descriptor->physical_allocation;
+ while (NULL != active_allocation_tracker)
+ {
+ MALI_DEBUG_ASSERT_POINTER(active_allocation_tracker->release);
+ active_allocation_tracker->release(active_allocation_tracker->ctx, active_allocation_tracker->handle);
+ active_allocation_tracker = active_allocation_tracker->next;
+ }
+
+ /* free the allocation tracker objects themselves, skipping the tracker stored inside the descriptor itself */
+ for ( active_allocation_tracker = descriptor->physical_allocation.next; active_allocation_tracker != NULL; )
+ {
+ void * buf = active_allocation_tracker;
+ active_allocation_tracker = active_allocation_tracker->next;
+ _mali_osk_free(buf);
+ }
+
+ if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE )
+ {
+ engine->process_address->release(descriptor);
+ }
+}
+
+
+_mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size)
+{
+ _mali_osk_errcode_t err;
+ memory_engine * engine = (memory_engine*)mem_engine;
+ _mali_osk_mem_mapregion_flags_t unmap_flags = (_mali_osk_mem_mapregion_flags_t)0;
+
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ MALI_DEBUG_PRINT(7, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X\n", phys, size, offset));
+
+ MALI_DEBUG_ASSERT_POINTER(engine->mali_address);
+ MALI_DEBUG_ASSERT_POINTER(engine->mali_address->map_physical);
+
+ /* Handle process address manager first, because we may need them to
+ * allocate the physical page */
+ if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE )
+ {
+ /* Handle OS-allocated specially, since an adjustment may be required */
+ if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == phys )
+ {
+ MALI_DEBUG_ASSERT( _MALI_OSK_CPU_PAGE_SIZE == size );
+
+ /* Set flags to use on error path */
+ unmap_flags |= _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR;
+
+ err = engine->process_address->map_physical(descriptor, offset, &phys, size);
+ /* Adjust for cpu physical address to mali physical address */
+ phys -= cpu_usage_adjust;
+ }
+ else
+ {
+ u32 cpu_phys;
+ /* Adjust mali physical address to cpu physical address */
+ cpu_phys = phys + cpu_usage_adjust;
+ err = engine->process_address->map_physical(descriptor, offset, &cpu_phys, size);
+ }
+
+ if ( _MALI_OSK_ERR_OK != err )
+ {
+ MALI_ERROR( err );
+ }
+ }
+
+ MALI_DEBUG_PRINT(4, ("Mapping phys 0x%08X length 0x%08X at offset 0x%08X to CPUVA 0x%08X\n", phys, size, offset, (u32)(descriptor->mapping) + offset));
+
+ /* Mali address manager must use the physical address - no point in asking
+ * it to allocate another one for us */
+ MALI_DEBUG_ASSERT( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC != phys );
+
+ err = engine->mali_address->map_physical(descriptor, offset, &phys, size);
+
+ if ( _MALI_OSK_ERR_OK != err )
+ {
+ if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE )
+ {
+ MALI_DEBUG_PRINT( 2, ("Process address manager succeeded, but Mali Address manager failed for phys=0x%08X size=0x%08X, offset=0x%08X. Will unmap.\n", phys, size, offset));
+ engine->process_address->unmap_physical(descriptor, offset, size, unmap_flags);
+ }
+
+ MALI_ERROR( err );
+ }
+
+ MALI_SUCCESS;
+}
+
+void mali_allocation_engine_unmap_physical(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags )
+{
+ memory_engine * engine = (memory_engine*)mem_engine;
+
+ MALI_DEBUG_ASSERT_POINTER(engine);
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ MALI_DEBUG_PRINT(7, ("UnMapping length 0x%08X at offset 0x%08X\n", size, offset));
+
+ MALI_DEBUG_ASSERT_POINTER(engine->mali_address);
+ MALI_DEBUG_ASSERT_POINTER(engine->process_address);
+
+ if ( descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE )
+ {
+ /* Mandetory for process_address manager to have an unmap function*/
+ engine->process_address->unmap_physical( descriptor, offset, size, unmap_flags );
+ }
+
+ /* Optional for mali_address manager to have an unmap function*/
+ if ( NULL != engine->mali_address->unmap_physical )
+ {
+ engine->mali_address->unmap_physical( descriptor, offset, size, unmap_flags );
+ }
+}
+
+
+_mali_osk_errcode_t mali_allocation_engine_allocate_page_tables(mali_allocation_engine engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider)
+{
+ mali_physical_memory_allocator * active_allocator = physical_provider;
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(physical_provider);
+
+ while ( NULL != active_allocator )
+ {
+ switch (active_allocator->allocate_page_table_block(active_allocator->ctx, descriptor))
+ {
+ case MALI_MEM_ALLOC_FINISHED:
+ MALI_SUCCESS; /* all done */
+ case MALI_MEM_ALLOC_NONE:
+ /* try next */
+ MALI_DEBUG_PRINT( 2, ("Memory Engine Allocate PageTables: No allocation on %s, resorting to %s\n",
+ ( active_allocator->name ) ? active_allocator->name : "UNNAMED",
+ ( active_allocator->next ) ? (( active_allocator->next->name )? active_allocator->next->name : "UNNAMED") : "NONE") );
+ active_allocator = active_allocator->next;
+ break;
+ case MALI_MEM_ALLOC_PARTIAL:
+ MALI_DEBUG_PRINT(1, ("Invalid return value from allocate_page_table_block call: MALI_MEM_ALLOC_PARTIAL\n"));
+ /* FALL THROUGH */
+ case MALI_MEM_ALLOC_INTERNAL_FAILURE:
+ MALI_DEBUG_PRINT(1, ("Aborting due to allocation failure\n"));
+ active_allocator = NULL; /* end the while loop */
+ break;
+ }
+ }
+
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+}
+
+
+void mali_allocation_engine_report_allocators( mali_physical_memory_allocator * physical_provider )
+{
+ mali_physical_memory_allocator * active_allocator = physical_provider;
+ MALI_DEBUG_ASSERT_POINTER(physical_provider);
+
+ MALI_DEBUG_PRINT( 1, ("Mali memory allocators will be used in this order of preference (lowest numbered first) :\n"));
+ while ( NULL != active_allocator )
+ {
+ if ( NULL != active_allocator->name )
+ {
+ MALI_DEBUG_PRINT( 1, ("\t%d: %s\n", active_allocator->alloc_order, active_allocator->name) );
+ }
+ else
+ {
+ MALI_DEBUG_PRINT( 1, ("\t%d: (UNNAMED ALLOCATOR)\n", active_allocator->alloc_order) );
+ }
+ active_allocator = active_allocator->next;
+ }
+
+}
+
+u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator)
+{
+ u32 sum = 0;
+ while(NULL != allocator)
+ {
+ /* Only count allocators that have set up a stat function. */
+ if(allocator->stat)
+ sum += allocator->stat(allocator);
+
+ allocator = allocator->next;
+ }
+
+ return sum;
+}
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_memory_engine.h b/drivers/gpu/arm/mali/common/mali_kernel_memory_engine.h
new file mode 100644
index 00000000000..367219f191d
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_memory_engine.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_MEMORY_ENGINE_H__
+#define __MALI_KERNEL_MEMORY_ENGINE_H__
+
+typedef void * mali_allocation_engine;
+
+typedef enum { MALI_MEM_ALLOC_FINISHED, MALI_MEM_ALLOC_PARTIAL, MALI_MEM_ALLOC_NONE, MALI_MEM_ALLOC_INTERNAL_FAILURE } mali_physical_memory_allocation_result;
+
+typedef struct mali_physical_memory_allocation
+{
+ void (*release)(void * ctx, void * handle); /**< Function to call on to release the physical memory */
+ void * ctx;
+ void * handle;
+ struct mali_physical_memory_allocation * next;
+} mali_physical_memory_allocation;
+
+struct mali_page_table_block;
+
+typedef struct mali_page_table_block
+{
+ void (*release)(struct mali_page_table_block *page_table_block);
+ void * ctx;
+ void * handle;
+ u32 size; /**< In bytes, should be a multiple of MALI_MMU_PAGE_SIZE to avoid internal fragementation */
+ u32 phys_base; /**< Mali physical address */
+ mali_io_address mapping;
+} mali_page_table_block;
+
+
+/** @addtogroup _mali_osk_low_level_memory
+ * @{ */
+
+typedef enum
+{
+ MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE = 0x1,
+ MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE = 0x2,
+} mali_memory_allocation_flag;
+
+/**
+ * Supplying this 'magic' physical address requests that the OS allocate the
+ * physical address at page commit time, rather than committing a specific page
+ */
+#define MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC ((u32)(-1))
+
+typedef struct mali_memory_allocation
+{
+ /* Information about the allocation */
+ void * mapping; /**< CPU virtual address where the memory is mapped at */
+ u32 mali_address; /**< The Mali seen address of the memory allocation */
+ u32 size; /**< Size of the allocation */
+ u32 permission; /**< Permission settings */
+ mali_memory_allocation_flag flags;
+
+ _mali_osk_lock_t * lock;
+
+ /* Manager specific information pointers */
+ void * mali_addr_mapping_info; /**< Mali address allocation specific info */
+ void * process_addr_mapping_info; /**< Mapping manager specific info */
+
+ mali_physical_memory_allocation physical_allocation;
+
+ _mali_osk_list_t list; /**< List for linking together memory allocations into the session's memory head */
+} mali_memory_allocation;
+/** @} */ /* end group _mali_osk_low_level_memory */
+
+
+typedef struct mali_physical_memory_allocator
+{
+ mali_physical_memory_allocation_result (*allocate)(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info);
+ mali_physical_memory_allocation_result (*allocate_page_table_block)(void * ctx, mali_page_table_block * block); /* MALI_MEM_ALLOC_PARTIAL not allowed */
+ void (*destroy)(struct mali_physical_memory_allocator * allocator);
+ u32 (*stat)(struct mali_physical_memory_allocator * allocator);
+ void * ctx;
+ const char * name; /**< Descriptive name for use in mali_allocation_engine_report_allocators, or NULL */
+ u32 alloc_order; /**< Order in which the allocations should happen */
+ struct mali_physical_memory_allocator * next;
+} mali_physical_memory_allocator;
+
+typedef struct mali_kernel_mem_address_manager
+{
+ _mali_osk_errcode_t (*allocate)(mali_memory_allocation *); /**< Function to call to reserve an address */
+ void (*release)(mali_memory_allocation *); /**< Function to call to free the address allocated */
+
+ /**
+ * Function called for each physical sub allocation.
+ * Called for each physical block allocated by the physical memory manager.
+ * @param[in] descriptor The memory descriptor in question
+ * @param[in] off Offset from the start of range
+ * @param[in,out] phys_addr A pointer to the physical address of the start of the
+ * physical block. When *phys_addr == MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC
+ * is used, this requests the function to allocate the physical page
+ * itself, and return it through the pointer provided.
+ * @param[in] size Length in bytes of the physical block
+ * @return _MALI_OSK_ERR_OK on success.
+ * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure.
+ * Specifically, _MALI_OSK_ERR_UNSUPPORTED indicates that the function
+ * does not support allocating physical pages itself.
+ */
+ _mali_osk_errcode_t (*map_physical)(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size);
+
+ /**
+ * Function called to remove a physical sub allocation.
+ * Called on error paths where one of the address managers fails.
+ *
+ * @note this is optional. For address managers where this is not
+ * implemented, the value of this member is NULL. The memory engine
+ * currently does not require the mali address manager to be able to
+ * unmap individual pages, but the process address manager must have this
+ * capability.
+ *
+ * @param[in] descriptor The memory descriptor in question
+ * @param[in] off Offset from the start of range
+ * @param[in] size Length in bytes of the physical block
+ * @param[in] flags flags to use on a per-page basis. For OS-allocated
+ * physical pages, this must include _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR.
+ * @return _MALI_OSK_ERR_OK on success.
+ * A value of type _mali_osk_errcode_t other than _MALI_OSK_ERR_OK indicates failure.
+ */
+ void (*unmap_physical)(mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags);
+
+} mali_kernel_mem_address_manager;
+
+mali_allocation_engine mali_allocation_engine_create(mali_kernel_mem_address_manager * mali_address_manager, mali_kernel_mem_address_manager * process_address_manager);
+
+void mali_allocation_engine_destroy(mali_allocation_engine engine);
+
+int mali_allocation_engine_allocate_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor, mali_physical_memory_allocator * physical_provider, _mali_osk_list_t *tracking_list );
+void mali_allocation_engine_release_memory(mali_allocation_engine engine, mali_memory_allocation * descriptor);
+
+int mali_allocation_engine_map_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 phys, u32 cpu_usage_adjust, u32 size);
+void mali_allocation_engine_unmap_physical(mali_allocation_engine engine, mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t unmap_flags);
+
+int mali_allocation_engine_allocate_page_tables(mali_allocation_engine, mali_page_table_block * descriptor, mali_physical_memory_allocator * physical_provider);
+
+void mali_allocation_engine_report_allocators(mali_physical_memory_allocator * physical_provider);
+
+u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator);
+
+#endif /* __MALI_KERNEL_MEMORY_ENGINE_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_pp.h b/drivers/gpu/arm/mali/common/mali_kernel_pp.h
new file mode 100644
index 00000000000..61721e786fc
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_pp.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_PP_H__
+#define __MALI_KERNEL_PP_H__
+
+extern struct mali_kernel_subsystem mali_subsystem_mali200;
+
+#if USING_MALI_PMM
+_mali_osk_errcode_t malipp_signal_power_up( u32 core_num, mali_bool queue_only );
+_mali_osk_errcode_t malipp_signal_power_down( u32 core_num, mali_bool immediate_only );
+#endif
+
+#endif /* __MALI_KERNEL_PP_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_profiling.h b/drivers/gpu/arm/mali/common/mali_kernel_profiling.h
new file mode 100644
index 00000000000..074b2b3149b
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_profiling.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_PROFILING_H__
+#define __MALI_KERNEL_PROFILING_H__
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+
+#include <../../../include/cinstr/mali_cinstr_profiling_events_m200.h>
+
+#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576
+
+/**
+ * Initialize the profiling module.
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t _mali_profiling_init(mali_bool auto_start);
+
+/*
+ * Terminate the profiling module.
+ */
+void _mali_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_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.
+ */
+_mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4);
+
+/**
+ * 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_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_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_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_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_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_profiling_have_recording(void);
+
+/**
+ * Enable or disable profiling events as default for new sessions (applications)
+ *
+ * @param enable MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE
+ */
+void _mali_profiling_set_default_enable_state(mali_bool enable);
+
+/**
+ * Get current default enable state for new sessions (applications)
+ *
+ * @return MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE
+ */
+mali_bool _mali_profiling_get_default_enable_state(void);
+
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+
+#endif /* __MALI_KERNEL_PROFILING_H__ */
+
+
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c
new file mode 100644
index 00000000000..db5dd5aa35f
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c
@@ -0,0 +1,2021 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#include "mali_osk.h"
+#include "mali_kernel_subsystem.h"
+#include "mali_kernel_rendercore.h"
+#include "mali_osk_list.h"
+#if MALI_GPU_UTILIZATION
+#include "mali_kernel_utilization.h"
+#endif
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.h"
+#endif
+#if USING_MMU
+#include "mali_kernel_mem_mmu.h"
+#endif /* USING_MMU */
+#if defined USING_MALI400_L2_CACHE
+#include "mali_kernel_l2_cache.h"
+#endif /* USING_MALI400_L2_CACHE */
+
+#define HANG_CHECK_MSECS_MIN 100
+#define HANG_CHECK_MSECS_MAX 2000 /* 2 secs */
+#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */
+
+#define WATCHDOG_MSECS_MIN (2*HANG_CHECK_MSECS_MIN)
+#define WATCHDOG_MSECS_MAX 3600000 /* 1 hour */
+#define WATCHDOG_MSECS_DEFAULT 900000 /* 15 mins */
+
+/* max value that will be converted from jiffies to micro seconds and written to job->render_time_usecs */
+#define JOB_MAX_JIFFIES 100000
+
+int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT;
+int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+int mali_boot_profiling = 0;
+#endif
+
+/* Subsystem entrypoints: */
+static _mali_osk_errcode_t rendercore_subsystem_startup(mali_kernel_subsystem_identifier id);
+static void rendercore_subsystem_terminate(mali_kernel_subsystem_identifier id);
+#if USING_MMU
+static void rendercore_subsystem_broadcast_notification(mali_core_notification_message message, u32 data);
+#endif
+
+
+static void mali_core_subsystem_cleanup_all_renderunits(struct mali_core_subsystem* subsys);
+static void mali_core_subsystem_move_core_set_idle(struct mali_core_renderunit *core);
+
+static mali_core_session * mali_core_subsystem_get_waiting_session(mali_core_subsystem *subsystem);
+static mali_core_job * mali_core_subsystem_release_session_get_job(mali_core_subsystem *subsystem, mali_core_session * session);
+
+static void find_and_abort(mali_core_session* session, u32 abort_id);
+
+static void mali_core_job_start_on_core(mali_core_job *job, mali_core_renderunit *core);
+#if USING_MMU
+static void mali_core_subsystem_callback_schedule_wrapper(void* sub);
+#endif
+static void mali_core_subsystem_schedule(mali_core_subsystem*subsystem);
+static void mali_core_renderunit_detach_job_from_core(mali_core_renderunit* core, mali_subsystem_reschedule_option reschedule, mali_subsystem_job_end_code end_status);
+
+static void mali_core_renderunit_irq_handler_remove(struct mali_core_renderunit *core);
+
+static _mali_osk_errcode_t mali_core_irq_handler_upper_half (void * data);
+static void mali_core_irq_handler_bottom_half ( void *data );
+
+#if USING_MMU
+static void lock_subsystem(struct mali_core_subsystem * subsys);
+static void unlock_subsystem(struct mali_core_subsystem * subsys);
+#endif
+
+
+/**
+ * This will be one of the subsystems in the array of subsystems:
+ * static struct mali_kernel_subsystem * subsystems[];
+ * found in file: mali_kernel_core.c
+ *
+ * This subsystem is necessary for operations common to all rendercore
+ * subsystems. For example, mali_subsystem_mali200 and mali_subsystem_gp2 may
+ * share a mutex when RENDERCORES_USE_GLOBAL_MUTEX is non-zero.
+ */
+struct mali_kernel_subsystem mali_subsystem_rendercore=
+{
+ rendercore_subsystem_startup, /* startup */
+ rendercore_subsystem_terminate, /* shutdown */
+ NULL, /* load_complete */
+ NULL, /* system_info_fill */
+ NULL, /* session_begin */
+ NULL, /* session_end */
+#if USING_MMU
+ rendercore_subsystem_broadcast_notification, /* broadcast_notification */
+#else
+ NULL,
+#endif
+#if MALI_STATE_TRACKING
+ NULL, /* dump_state */
+#endif
+} ;
+
+static _mali_osk_lock_t *rendercores_global_mutex = NULL;
+static u32 rendercores_global_mutex_is_held = 0;
+static u32 rendercores_global_mutex_owner = 0;
+
+/** The 'dummy' rendercore subsystem to allow global subsystem mutex to be
+ * locked for all subsystems that extend the ''rendercore'' */
+static mali_core_subsystem rendercore_dummy_subsystem = {0,};
+
+/*
+ * Rendercore Subsystem functions.
+ *
+ * These are exposed by mali_subsystem_rendercore
+ */
+
+/**
+ * @brief Initialize the Rendercore subsystem.
+ *
+ * This must be called before any other subsystem that extends the
+ * ''rendercore'' may be initialized. For example, this must be called before
+ * the following functions:
+ * - mali200_subsystem_startup(), from mali_subsystem_mali200
+ * - maligp_subsystem_startup(), from mali_subsystem_gp2
+ *
+ * @note This function is separate from mali_core_subsystem_init(). They
+ * are related, in that mali_core_subsystem_init() may use the structures
+ * initialized by rendercore_subsystem_startup()
+ */
+static _mali_osk_errcode_t rendercore_subsystem_startup(mali_kernel_subsystem_identifier id)
+{
+ rendercores_global_mutex_is_held = 0;
+ rendercores_global_mutex = _mali_osk_lock_init(
+ (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED),
+ 0, 129);
+
+ if (NULL == rendercores_global_mutex)
+ {
+ MALI_PRINT_ERROR(("Failed: _mali_osk_lock_init\n")) ;
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ rendercore_dummy_subsystem.name = "Rendercore Global Subsystem"; /* On the constant pool, do not free */
+ rendercore_dummy_subsystem.magic_nr = SUBSYSTEM_MAGIC_NR; /* To please the Subsystem Mutex code */
+
+#if MALI_GPU_UTILIZATION
+ if (mali_utilization_init() != _MALI_OSK_ERR_OK)
+ {
+ _mali_osk_lock_term(rendercores_global_mutex);
+ rendercores_global_mutex = NULL;
+ MALI_PRINT_ERROR(("Failed: mali_utilization_init\n")) ;
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#endif
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ if (_mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE) != _MALI_OSK_ERR_OK)
+ {
+ /* No biggie if we wheren't able to initialize the profiling */
+ MALI_PRINT_ERROR(("Rendercore: Failed to initialize profiling, feature will be unavailable\n")) ;
+ }
+#endif
+
+ MALI_DEBUG_PRINT(2, ("Rendercore: subsystem global mutex initialized\n")) ;
+ MALI_SUCCESS;
+}
+
+/**
+ * @brief Terminate the Rendercore subsystem.
+ *
+ * This must only be called \b after any other subsystem that extends the
+ * ''rendercore'' has been terminated. For example, this must be called \b after
+ * the following functions:
+ * - mali200_subsystem_terminate(), from mali_subsystem_mali200
+ * - maligp_subsystem_terminate(), from mali_subsystem_gp2
+ *
+ * @note This function is separate from mali_core_subsystem_cleanup(), though,
+ * the subsystems that extend ''rendercore'' must still call
+ * mali_core_subsystem_cleanup() when they terminate.
+ */
+static void rendercore_subsystem_terminate(mali_kernel_subsystem_identifier id)
+{
+ /* Catch double-terminate */
+ MALI_DEBUG_ASSERT_POINTER( rendercores_global_mutex );
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_term();
+#endif
+
+#if MALI_GPU_UTILIZATION
+ mali_utilization_term();
+#endif
+
+ rendercore_dummy_subsystem.name = NULL; /* The original string was on the constant pool, do not free */
+ rendercore_dummy_subsystem.magic_nr = 0;
+
+ /* ASSERT that no-one's holding this */
+ MALI_DEBUG_PRINT_ASSERT( 0 == rendercores_global_mutex_is_held,
+ ("Rendercores' Global Mutex was held at termination time. Have the subsystems that extend ''rendercore'' been terminated?\n") );
+
+ _mali_osk_lock_term( rendercores_global_mutex );
+ rendercores_global_mutex = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Rendercore: subsystem global mutex terminated\n")) ;
+}
+
+
+#if USING_MMU
+/**
+ * @brief Handle certain Rendercore subsystem broadcast notifications
+ *
+ * When RENDERCORES_USE_GLOBAL_MUTEX is non-zero, this handles the following messages:
+ * - MMU_KILL_STEP0_LOCK_SUBSYSTEM
+ * - MMU_KILL_STEP4_UNLOCK_SUBSYSTEM
+ *
+ * The purpose is to manage the Rendercode Global Mutex, which cannot be
+ * managed by any system that extends the ''rendercore''.
+ *
+ * All other messages must be handled by mali_core_subsystem_broadcast_notification()
+ *
+ *
+ * When RENDERCORES_USE_GLOBAL_MUTEX is 0, this function does nothing.
+ * Instead, the subsystem that extends the ''rendercore' \b must handle its
+ * own mutexes - refer to mali_core_subsystem_broadcast_notification().
+ *
+ * Used currently only for signalling when MMU has a pagefault
+ */
+static void rendercore_subsystem_broadcast_notification(mali_core_notification_message message, u32 data)
+{
+ switch(message)
+ {
+ case MMU_KILL_STEP0_LOCK_SUBSYSTEM:
+ lock_subsystem( &rendercore_dummy_subsystem );
+ break;
+ case MMU_KILL_STEP4_UNLOCK_SUBSYSTEM:
+ unlock_subsystem( &rendercore_dummy_subsystem );
+ break;
+
+ case MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES:
+ /** FALLTHROUGH */
+ case MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS:
+ /** FALLTHROUGH */
+ case MMU_KILL_STEP3_CONTINUE_JOB_HANDLING:
+ break;
+
+ default:
+ MALI_PRINT_ERROR(("Illegal message: 0x%x, data: 0x%x\n", (u32)message, data));
+ break;
+ }
+
+}
+#endif
+
+/*
+ * Functions inherited by the subsystems that extend the ''rendercore''.
+ */
+
+void mali_core_renderunit_timeout_function_hang_detection(void *arg)
+{
+ mali_bool action = MALI_FALSE;
+ mali_core_renderunit * core;
+
+ core = (mali_core_renderunit *) arg;
+ if( !core ) return;
+
+ /* if NOT idle OR NOT powered off OR has TIMED_OUT */
+ if ( !((CORE_WATCHDOG_TIMEOUT == core->state ) || (CORE_IDLE== core->state) || (CORE_OFF == core->state)) )
+ {
+ core->state = CORE_HANG_CHECK_TIMEOUT;
+ action = MALI_TRUE;
+ }
+
+ if(action) _mali_osk_irq_schedulework(core->irq);
+}
+
+
+void mali_core_renderunit_timeout_function(void *arg)
+{
+ mali_core_renderunit * core;
+ mali_bool is_watchdog;
+
+ core = (mali_core_renderunit *)arg;
+ if( !core ) return;
+
+ is_watchdog = MALI_TRUE;
+ if (mali_benchmark)
+ {
+ /* poll based core */
+ mali_core_job *job;
+ job = core->current_job;
+ if ( (NULL != job) &&
+ (0 != _mali_osk_time_after(job->watchdog_jiffies,_mali_osk_time_tickcount()))
+ )
+ {
+ core->state = CORE_POLL;
+ is_watchdog = MALI_FALSE;
+ }
+ }
+
+ if (is_watchdog)
+ {
+ MALI_DEBUG_PRINT(3, ("SW-Watchdog timeout: Core:%s\n", core->description));
+ core->state = CORE_WATCHDOG_TIMEOUT;
+ }
+
+ _mali_osk_irq_schedulework(core->irq);
+}
+
+/* Used by external renderunit_create<> function */
+_mali_osk_errcode_t mali_core_renderunit_init(mali_core_renderunit * core)
+{
+ MALI_DEBUG_PRINT(5, ("Core: renderunit_init: Core:%s\n", core->description));
+
+ _MALI_OSK_INIT_LIST_HEAD(&core->list) ;
+ core->timer = _mali_osk_timer_init();
+ if (NULL == core->timer)
+ {
+ MALI_PRINT_ERROR(("Core: renderunit_init: Core:%s -- cannot init timer\n", core->description));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ _mali_osk_timer_setcallback(core->timer, mali_core_renderunit_timeout_function, (void *)core);
+
+ core->timer_hang_detection = _mali_osk_timer_init();
+ if (NULL == core->timer_hang_detection)
+ {
+ _mali_osk_timer_term(core->timer);
+ MALI_PRINT_ERROR(("Core: renderunit_init: Core:%s -- cannot init hang detection timer\n", core->description));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ _mali_osk_timer_setcallback(core->timer_hang_detection, mali_core_renderunit_timeout_function_hang_detection, (void *)core);
+
+#if USING_MALI_PMM
+ /* Init no pending power downs */
+ core->pend_power_down = MALI_FALSE;
+
+ /* Register the core with the PMM - which powers it up */
+ if (_MALI_OSK_ERR_OK != malipmm_core_register( core->pmm_id ))
+ {
+ _mali_osk_timer_term(core->timer);
+ _mali_osk_timer_term(core->timer_hang_detection);
+ MALI_PRINT_ERROR(("Core: renderunit_init: Core:%s -- cannot register with PMM\n", core->description));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#endif /* USING_MALI_PMM */
+
+ core->error_recovery = MALI_FALSE;
+ core->in_detach_function = MALI_FALSE;
+ core->state = CORE_IDLE;
+ core->current_job = NULL;
+ core->magic_nr = CORE_MAGIC_NR;
+#if USING_MMU
+ core->mmu = NULL;
+#endif /* USING_MMU */
+
+ MALI_SUCCESS;
+}
+
+void mali_core_renderunit_term(mali_core_renderunit * core)
+{
+ MALI_DEBUG_PRINT(5, ("Core: renderunit_term: Core:%s\n", core->description));
+
+ if (NULL != core->timer)
+ {
+ _mali_osk_timer_term(core->timer);
+ core->timer = NULL;
+ }
+ if (NULL != core->timer_hang_detection)
+ {
+ _mali_osk_timer_term(core->timer_hang_detection);
+ core->timer_hang_detection = NULL;
+ }
+
+#if USING_MALI_PMM
+ /* Unregister the core with the PMM */
+ malipmm_core_unregister( core->pmm_id );
+#endif
+}
+
+/* Used by external renderunit_create<> function */
+_mali_osk_errcode_t mali_core_renderunit_map_registers(mali_core_renderunit *core)
+{
+ MALI_DEBUG_PRINT(3, ("Core: renderunit_map_registers: Core:%s\n", core->description)) ;
+ if( (0 == core->registers_base_addr) ||
+ (0 == core->size) ||
+ (NULL == core->description)
+ )
+ {
+ MALI_PRINT_ERROR(("Missing fields in the core structure %u %u 0x%x;\n", core->registers_base_addr, core->size, core->description));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(core->registers_base_addr, core->size, core->description))
+ {
+ MALI_PRINT_ERROR(("Could not request register region (0x%08X - 0x%08X) to core: %s\n",
+ core->registers_base_addr, core->registers_base_addr + core->size - 1, core->description));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(6, ("Success: request_mem_region: (0x%08X - 0x%08X) Core:%s\n",
+ core->registers_base_addr, core->registers_base_addr + core->size - 1, core->description));
+ }
+
+ core->registers_mapped = _mali_osk_mem_mapioregion( core->registers_base_addr, core->size, core->description );
+
+ if ( 0 == core->registers_mapped )
+ {
+ MALI_PRINT_ERROR(("Could not ioremap registers for %s .\n", core->description));
+ _mali_osk_mem_unreqregion(core->registers_base_addr, core->size);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(6, ("Success: ioremap_nocache: Internal ptr: (0x%08X - 0x%08X) Core:%s\n",
+ (u32) core->registers_mapped,
+ ((u32)core->registers_mapped)+ core->size - 1,
+ core->description));
+ }
+
+ MALI_DEBUG_PRINT(4, ("Success: Mapping registers to core: %s\n",core->description));
+
+ MALI_SUCCESS;
+}
+
+/* Used by external renderunit_create<> function + other places */
+void mali_core_renderunit_unmap_registers(mali_core_renderunit *core)
+{
+ MALI_DEBUG_PRINT(3, ("Core: renderunit_unmap_registers: Core:%s\n", core->description));
+ if (0 == core->registers_mapped)
+ {
+ MALI_PRINT_ERROR(("Trying to unmap register-mapping with NULL from core: %s\n", core->description));
+ return;
+ }
+ _mali_osk_mem_unmapioregion(core->registers_base_addr, core->size, core->registers_mapped);
+ core->registers_mapped = 0;
+ _mali_osk_mem_unreqregion(core->registers_base_addr, core->size);
+}
+
+static void mali_core_renderunit_irq_handler_remove(mali_core_renderunit *core)
+{
+ MALI_DEBUG_PRINT(3, ("Core: renderunit_irq_handler_remove: Core:%s\n", core->description));
+ _mali_osk_irq_term(core->irq);
+}
+
+mali_core_renderunit * mali_core_renderunit_get_mali_core_nr(mali_core_subsystem *subsys, u32 mali_core_nr)
+{
+ mali_core_renderunit * core;
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+ if (subsys->number_of_cores <= mali_core_nr)
+ {
+ MALI_PRINT_ERROR(("Trying to get illegal mali_core_nr: 0x%x for %s", mali_core_nr, subsys->name));
+ return NULL;
+ }
+ core = (subsys->mali_core_array)[mali_core_nr];
+ MALI_DEBUG_PRINT(6, ("Core: renderunit_get_mali_core_nr: Core:%s\n", core->description));
+ MALI_CHECK_CORE(core);
+ return core;
+}
+
+/* Is used by external function:
+ subsystem_startup<> */
+_mali_osk_errcode_t mali_core_subsystem_init(mali_core_subsystem* new_subsys)
+{
+ int i;
+
+ /* These function pointers must have been set on before calling this function */
+ if (
+ ( NULL == new_subsys->name ) ||
+ ( NULL == new_subsys->start_job ) ||
+ ( NULL == new_subsys->irq_handler_upper_half ) ||
+ ( NULL == new_subsys->irq_handler_bottom_half ) ||
+ ( NULL == new_subsys->get_new_job_from_user ) ||
+ ( NULL == new_subsys->return_job_to_user )
+ )
+ {
+ MALI_PRINT_ERROR(("Missing functions in subsystem."));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ MALI_DEBUG_PRINT(2, ("Core: subsystem_init: %s\n", new_subsys->name)) ;
+
+ /* Catch use-before-initialize/use-after-terminate */
+ MALI_DEBUG_ASSERT_POINTER( rendercores_global_mutex );
+
+ new_subsys->magic_nr = SUBSYSTEM_MAGIC_NR;
+
+ _MALI_OSK_INIT_LIST_HEAD(&new_subsys->renderunit_idle_head); /* Idle cores of this type */
+ _MALI_OSK_INIT_LIST_HEAD(&new_subsys->renderunit_off_head); /* Powered off cores of this type */
+
+ /* Linked list for each priority of sessions with a job ready for scheduleing */
+ for(i=0; i<PRIORITY_LEVELS; ++i)
+ {
+ _MALI_OSK_INIT_LIST_HEAD(&new_subsys->awaiting_sessions_head[i]);
+ }
+
+ /* Linked list of all sessions connected to this coretype */
+ _MALI_OSK_INIT_LIST_HEAD(&new_subsys->all_sessions_head);
+
+ MALI_SUCCESS;
+}
+
+#if USING_MMU
+void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys)
+{
+ u32 i;
+ mali_core_renderunit * core;
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+
+ for(i=0 ; i < subsys->number_of_cores ; ++i)
+ {
+ core = mali_core_renderunit_get_mali_core_nr(subsys,i);
+ if ( NULL==core ) break;
+ core->mmu = mali_memory_core_mmu_lookup(core->mmu_id);
+ mali_memory_core_mmu_owner(core,core->mmu);
+ MALI_DEBUG_PRINT(2, ("Attach mmu: 0x%x to core: %s in subsystem: %s\n", core->mmu, core->description, subsys->name));
+ }
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+}
+#endif
+
+/* This will register an IRQ handler, and add the core to the list of available cores for this subsystem. */
+_mali_osk_errcode_t mali_core_subsystem_register_renderunit(mali_core_subsystem* subsys, mali_core_renderunit * core)
+{
+ mali_core_renderunit ** mali_core_array;
+ u32 previous_nr;
+ u32 previous_size;
+ u32 new_nr;
+ u32 new_size;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+
+ /* If any of these are 0 there is an error */
+ if(0 == core->subsystem ||
+ 0 == core->registers_base_addr ||
+ 0 == core->size ||
+ 0 == core->description)
+ {
+ MALI_PRINT_ERROR(("Missing fields in the core structure 0x%x 0x%x 0x%x;\n",
+ core->registers_base_addr, core->size, core->description));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ MALI_DEBUG_PRINT(3, ("Core: subsystem_register_renderunit: %s\n", core->description));
+
+ MALI_CHECK_NON_NULL(
+ core->irq = _mali_osk_irq_init(
+ core->irq_nr,
+ mali_core_irq_handler_upper_half,
+ mali_core_irq_handler_bottom_half,
+ (_mali_osk_irq_trigger_t)subsys->probe_core_irq_trigger,
+ (_mali_osk_irq_ack_t)subsys->probe_core_irq_acknowledge,
+ core,
+ "mali_core_irq_handlers"
+ ),
+ _MALI_OSK_ERR_FAULT
+ );
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+
+ /* Update which core number this is */
+ core->core_number = subsys->number_of_cores;
+
+ /* Update the array of cores in the subsystem. */
+ previous_nr = subsys->number_of_cores;
+ previous_size = sizeof(mali_core_renderunit*)*previous_nr;
+ new_nr = previous_nr + 1;
+ new_size = sizeof(mali_core_renderunit*)*new_nr;
+
+ if (0 != previous_nr)
+ {
+ if (NULL == subsys->mali_core_array)
+ {
+ MALI_PRINT_ERROR(("Internal error"));
+ goto exit_function;
+ }
+
+ mali_core_array = (mali_core_renderunit **) _mali_osk_malloc( new_size );
+ if (NULL == mali_core_array )
+ {
+ MALI_PRINT_ERROR(("Out of mem"));
+ err = _MALI_OSK_ERR_NOMEM;
+ goto exit_function;
+ }
+ _mali_osk_memcpy(mali_core_array, subsys->mali_core_array, previous_size);
+ _mali_osk_free( subsys->mali_core_array);
+ MALI_DEBUG_PRINT(5, ("Success: adding a new core to subsystem array %s\n", core->description) ) ;
+ }
+ else
+ {
+ mali_core_array = (mali_core_renderunit **) _mali_osk_malloc( new_size );
+ if (NULL == mali_core_array )
+ {
+ MALI_PRINT_ERROR(("Out of mem"));
+ err = _MALI_OSK_ERR_NOMEM;
+ goto exit_function;
+ }
+ MALI_DEBUG_PRINT(6, ("Success: adding first core to subsystem array %s\n", core->description) ) ;
+ }
+ subsys->mali_core_array = mali_core_array;
+ mali_core_array[previous_nr] = core;
+
+ /* Add the core to the list of available cores on the system */
+ _mali_osk_list_add(&(core->list), &(subsys->renderunit_idle_head));
+
+ /* Update total number of cores */
+ subsys->number_of_cores = new_nr;
+ MALI_DEBUG_PRINT(6, ("Success: mali_core_subsystem_register_renderunit %s\n", core->description));
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_SUCCESS;
+
+exit_function:
+ mali_core_renderunit_irq_handler_remove(core);
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_ERROR(err);
+}
+
+
+/**
+ * Called by the core when a system info update is needed
+ * We fill in info about all the core types available
+ * @param subsys Pointer to the core's @a mali_core_subsystem data structure
+ * @param info Pointer to system info struct to update
+ * @return _MALI_OSK_ERR_OK on success, or another _mali_osk_errcode_t error code on failure
+ */
+_mali_osk_errcode_t mali_core_subsystem_system_info_fill(mali_core_subsystem* subsys, _mali_system_info* info)
+{
+ u32 i;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; /* OK if no cores to update info for */
+ mali_core_renderunit * core;
+ _mali_core_info **core_info_nextp;
+ _mali_core_info * cinfo;
+
+ MALI_DEBUG_PRINT(4, ("mali_core_subsystem_system_info_fill: %s\n", subsys->name) ) ;
+
+ /* check input */
+ MALI_CHECK_NON_NULL(info, _MALI_OSK_ERR_INVALID_ARGS);
+
+ core_info_nextp = &(info->core_info);
+ cinfo = info->core_info;
+
+ while(NULL!=cinfo)
+ {
+ core_info_nextp = &(cinfo->next);
+ cinfo = cinfo->next;
+ }
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+ for(i=0 ; i < subsys->number_of_cores ; ++i)
+ {
+ core = mali_core_renderunit_get_mali_core_nr(subsys,i);
+ if ( NULL==core )
+ {
+ err = _MALI_OSK_ERR_FAULT;
+ goto early_exit;
+ }
+ cinfo = (_mali_core_info *)_mali_osk_calloc(1, sizeof(_mali_core_info));
+ if ( NULL==cinfo )
+ {
+ err = _MALI_OSK_ERR_NOMEM;
+ goto early_exit;
+ }
+ cinfo->version = core->core_version;
+ cinfo->type =subsys->core_type;
+ cinfo->reg_address = core->registers_base_addr;
+ cinfo->core_nr = i;
+ cinfo->next = NULL;
+ /* Writing this address to the previous' *(&next) ptr */
+ *core_info_nextp = cinfo;
+ /* Setting the next_ptr to point to &this->next_ptr */
+ core_info_nextp = &(cinfo->next);
+ }
+early_exit:
+ if ( _MALI_OSK_ERR_OK != err) MALI_PRINT_ERROR(("Error: In mali_core_subsystem_system_info_fill %d\n", err));
+ MALI_DEBUG_CODE(
+ cinfo = info->core_info;
+
+ MALI_DEBUG_PRINT(3, ("Current list of cores\n"));
+ while( NULL != cinfo )
+ {
+ MALI_DEBUG_PRINT(3, ("Type: 0x%x\n", cinfo->type));
+ MALI_DEBUG_PRINT(3, ("Version: 0x%x\n", cinfo->version));
+ MALI_DEBUG_PRINT(3, ("Reg_addr: 0x%x\n", cinfo->reg_address));
+ MALI_DEBUG_PRINT(3, ("Core_nr: 0x%x\n", cinfo->core_nr));
+ MALI_DEBUG_PRINT(3, ("Flags: 0x%x\n", cinfo->flags));
+ MALI_DEBUG_PRINT(3, ("*****\n"));
+ cinfo = cinfo->next;
+ }
+ );
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_ERROR(err);
+}
+
+
+/* Is used by external function:
+ subsystem_terminate<> */
+void mali_core_subsystem_cleanup(mali_core_subsystem* subsys)
+{
+ u32 i;
+ mali_core_renderunit * core;
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+ MALI_DEBUG_PRINT(2, ("Core: subsystem_cleanup: %s\n", subsys->name )) ;
+
+ for(i=0 ; i < subsys->number_of_cores ; ++i)
+ {
+ core = mali_core_renderunit_get_mali_core_nr(subsys,i);
+
+#if USING_MMU
+ if (NULL != core->mmu)
+ {
+ /* the MMU is attached in the load_complete callback, which will never be called if the module fails to load, handle that case */
+ mali_memory_core_mmu_unregister_callback(core->mmu, mali_core_subsystem_callback_schedule_wrapper);
+ }
+#endif
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+
+ mali_core_renderunit_irq_handler_remove(core);
+
+ /* When a process terminates, all cores running jobs from that process is reset and put to idle.
+ That means that when the module is unloading (this code) we are guaranteed that all cores are idle.
+ However: if something (we can't think of) is really wrong, a core may give an interrupt during this
+ unloading, and we may now in the code have a bottom-half-processing pending from the interrupts
+ we deregistered above. To be sure that the bottom halves do not access the structures after they
+ are deallocated we flush the bottom-halves processing here, before the deallocation. */
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+
+#if USING_MALI_PMM
+ /* Only reset when we are using PMM and the core is not off */
+#if MALI_PMM_NO_PMU
+ /* We need to reset when there is no PMU - but this will
+ * cause the register read/write functions to report an
+ * error (hence the if to check for CORE_OFF below) we
+ * change state to allow the reset to happen.
+ */
+ core->state = CORE_IDLE;
+#endif
+ if( core->state != CORE_OFF )
+ {
+ subsys->reset_core( core, MALI_CORE_RESET_STYLE_DISABLE );
+ }
+#else
+ /* Always reset the core */
+ subsys->reset_core( core, MALI_CORE_RESET_STYLE_DISABLE );
+#endif
+
+ mali_core_renderunit_unmap_registers(core);
+
+ _mali_osk_list_delinit(&core->list);
+
+ mali_core_renderunit_term(core);
+
+ subsys->renderunit_delete(core);
+ }
+
+ mali_core_subsystem_cleanup_all_renderunits(subsys);
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_DEBUG_PRINT(6, ("SUCCESS: mali_core_subsystem_cleanup: %s\n", subsys->name )) ;
+}
+
+_mali_osk_errcode_t mali_core_subsystem_ioctl_number_of_cores_get(mali_core_session * session, u32 *number_of_cores)
+{
+ mali_core_subsystem * subsystem;
+
+ subsystem = session->subsystem;
+ if ( NULL != number_of_cores )
+ {
+ *number_of_cores = subsystem->number_of_cores;
+
+ MALI_DEBUG_PRINT(4, ("Core: ioctl_number_of_cores_get: %s: %u\n", subsystem->name, *number_of_cores) ) ;
+ }
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_core_subsystem_ioctl_start_job(mali_core_session * session, void *job_data)
+{
+ mali_core_subsystem * subsystem;
+ _mali_osk_errcode_t err;
+
+ /* need the subsystem to run callback function */
+ subsystem = session->subsystem;
+ MALI_CHECK_NON_NULL(subsystem, _MALI_OSK_ERR_FAULT);
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
+ err = subsystem->get_new_job_from_user(session, job_data);
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
+
+ MALI_ERROR(err);
+}
+
+
+/* We return the version number to the first core in this subsystem */
+_mali_osk_errcode_t mali_core_subsystem_ioctl_core_version_get(mali_core_session * session, _mali_core_version *version)
+{
+ mali_core_subsystem * subsystem;
+ mali_core_renderunit * core0;
+ u32 nr_return;
+
+ subsystem = session->subsystem;
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
+
+ core0 = mali_core_renderunit_get_mali_core_nr(subsystem, 0);
+
+ if( NULL == core0 )
+ {
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ nr_return = core0->core_version;
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
+
+ MALI_DEBUG_PRINT(4, ("Core: ioctl_core_version_get: %s: %u\n", subsystem->name, nr_return )) ;
+
+ *version = nr_return;
+
+ MALI_SUCCESS;
+}
+
+void mali_core_subsystem_ioctl_abort_job(mali_core_session * session, u32 id)
+{
+ find_and_abort(session, id);
+}
+
+static mali_bool job_should_be_aborted(mali_core_job *job, u32 abort_id)
+{
+ if ( job->abort_id == abort_id ) return MALI_TRUE;
+ else return MALI_FALSE;
+}
+
+static void find_and_abort(mali_core_session* session, u32 abort_id)
+{
+ mali_core_subsystem * subsystem;
+ mali_core_renderunit *core;
+ mali_core_renderunit *tmp;
+ mali_core_job *job;
+
+ subsystem = session->subsystem;
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
+
+ job = mali_job_queue_abort_job(session, abort_id);
+ if (NULL != job)
+ {
+ MALI_DEBUG_PRINT(3, ("Core: Aborting %s job, with id nr: %u, from the waiting_to_run slot.\n", subsystem->name, abort_id ));
+ if (mali_job_queue_empty(session))
+ {
+ _mali_osk_list_delinit(&(session->awaiting_sessions_list));
+ }
+ subsystem->awaiting_sessions_sum_all_priorities--;
+ subsystem->return_job_to_user(job , JOB_STATUS_END_ABORT);
+ }
+
+ _MALI_OSK_LIST_FOREACHENTRY( core, tmp, &session->renderunits_working_head, mali_core_renderunit, list )
+ {
+ job = core->current_job;
+ if ( (job!=NULL) && (job_should_be_aborted (job, abort_id) ) )
+ {
+ MALI_DEBUG_PRINT(3, ("Core: Aborting %s job, with id nr: %u, which is currently running on mali.\n", subsystem->name, abort_id ));
+ if ( core->state==CORE_IDLE )
+ {
+ MALI_PRINT_ERROR(("Aborting core with running job which is idle. Must be something very wrong."));
+ goto end_bug;
+ }
+ mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_ABORT);
+ }
+ }
+end_bug:
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem );
+}
+
+
+_mali_osk_errcode_t mali_core_subsystem_ioctl_suspend_response(mali_core_session * session, void *argument)
+{
+ mali_core_subsystem * subsystem;
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+
+ /* need the subsystem to run callback function */
+ subsystem = session->subsystem;
+ MALI_CHECK_NON_NULL(subsystem, _MALI_OSK_ERR_FAULT);
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
+ if ( NULL != subsystem->suspend_response)
+ {
+ MALI_DEBUG_PRINT(4, ("MALI_IOC_CORE_CMD_SUSPEND_RESPONSE start\n"));
+ err = subsystem->suspend_response(session, argument);
+ MALI_DEBUG_PRINT(4, ("MALI_IOC_CORE_CMD_SUSPEND_RESPONSE end\n"));
+ }
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
+
+ return err;
+}
+
+
+/* Is used by internal function:
+ mali_core_subsystem_cleanup<>s */
+/* All cores should be removed before calling this function
+Must hold subsystem_mutex before entering this function */
+static void mali_core_subsystem_cleanup_all_renderunits(mali_core_subsystem* subsys)
+{
+ int i;
+ _mali_osk_free(subsys->mali_core_array);
+ subsys->number_of_cores = 0;
+
+ MALI_DEBUG_PRINT(5, ("Core: subsystem_cleanup_all_renderunits: %s\n", subsys->name) ) ;
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+
+ if ( ! _mali_osk_list_empty(&(subsys->renderunit_idle_head)))
+ {
+ MALI_PRINT_ERROR(("List renderunit_list_idle should be empty."));
+ _MALI_OSK_INIT_LIST_HEAD(&(subsys->renderunit_idle_head)) ;
+ }
+
+ if ( ! _mali_osk_list_empty(&(subsys->renderunit_off_head)))
+ {
+ MALI_PRINT_ERROR(("List renderunit_list_off should be empty."));
+ _MALI_OSK_INIT_LIST_HEAD(&(subsys->renderunit_off_head)) ;
+ }
+
+ for(i=0; i<PRIORITY_LEVELS; ++i)
+ {
+ if ( ! _mali_osk_list_empty(&(subsys->awaiting_sessions_head[i])))
+ {
+ MALI_PRINT_ERROR(("List awaiting_sessions_linkedlist should be empty."));
+ _MALI_OSK_INIT_LIST_HEAD(&(subsys->awaiting_sessions_head[i])) ;
+ subsys->awaiting_sessions_sum_all_priorities = 0;
+ }
+ }
+
+ if ( ! _mali_osk_list_empty(&(subsys->all_sessions_head)))
+ {
+ MALI_PRINT_ERROR(("List all_sessions_linkedlist should be empty."));
+ _MALI_OSK_INIT_LIST_HEAD(&(subsys->all_sessions_head)) ;
+ }
+}
+
+/* Is used by internal functions:
+ mali_core_irq_handler_bottom_half<>;
+ mali_core_subsystem_schedule<>; */
+/* Will release the core.*/
+/* Must hold subsystem_mutex before entering this function */
+static void mali_core_subsystem_move_core_set_idle(mali_core_renderunit *core)
+{
+ mali_core_subsystem *subsystem;
+#if USING_MALI_PMM
+ mali_core_status oldstatus;
+#endif
+ subsystem = core->subsystem;
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+ MALI_CHECK_CORE(core);
+ MALI_CHECK_SUBSYSTEM(subsystem);
+
+ _mali_osk_timer_del(core->timer);
+ _mali_osk_timer_del(core->timer_hang_detection);
+
+ MALI_DEBUG_PRINT(5, ("Core: subsystem_move_core_set_idle: %s\n", core->description) ) ;
+
+ core->current_job = NULL ;
+
+#if USING_MALI_PMM
+
+ oldstatus = core->state;
+
+ if ( !core->pend_power_down )
+ {
+ core->state = CORE_IDLE ;
+ _mali_osk_list_move( &core->list, &subsystem->renderunit_idle_head );
+ }
+
+ if( CORE_OFF != oldstatus )
+ {
+ /* Message that this core is now idle or in fact off */
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ MALI_PMM_EVENT_JOB_FINISHED,
+ 0 };
+ event.data = core->pmm_id;
+ _mali_ukk_pmm_event_message( &event );
+#if USING_MMU
+ /* Only free the reference when entering idle state from
+ * anything other than power off
+ */
+ mali_memory_core_mmu_release_address_space_reference(core->mmu);
+#endif /* USING_MMU */
+ }
+
+ if( core->pend_power_down )
+ {
+ core->state = CORE_OFF ;
+ _mali_osk_list_move( &core->list, &subsystem->renderunit_off_head );
+
+ /* Done the move from the active queues, so the pending power down can be done */
+ core->pend_power_down = MALI_FALSE;
+ malipmm_core_power_down_okay( core->pmm_id );
+ }
+
+#else /* !USING_MALI_PMM */
+
+ core->state = CORE_IDLE ;
+ _mali_osk_list_move( &core->list, &subsystem->renderunit_idle_head );
+
+#if USING_MMU
+ mali_memory_core_mmu_release_address_space_reference(core->mmu);
+#endif
+
+#endif /* USING_MALI_PMM */
+}
+
+/* Must hold subsystem_mutex before entering this function */
+static void mali_core_subsystem_move_set_working(mali_core_renderunit *core, mali_core_job *job)
+{
+ mali_core_subsystem *subsystem;
+ mali_core_session *session;
+ u64 time_now;
+
+ session = job->session;
+ subsystem = core->subsystem;
+
+ MALI_CHECK_CORE(core);
+ MALI_CHECK_JOB(job);
+ MALI_CHECK_SUBSYSTEM(subsystem);
+
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+
+ MALI_DEBUG_PRINT(5, ("Core: subsystem_move_set_working: %s\n", core->description) ) ;
+
+ time_now = _mali_osk_time_get_ns();
+ job->start_time = time_now;
+#if MALI_GPU_UTILIZATION
+ mali_utilization_core_start(time_now);
+#endif
+
+ core->current_job = job ;
+ core->state = CORE_WORKING ;
+ _mali_osk_list_move( &core->list, &session->renderunits_working_head );
+
+}
+
+#if USING_MALI_PMM
+
+/* Must hold subsystem_mutex before entering this function */
+static void mali_core_subsystem_move_core_set_off(mali_core_renderunit *core)
+{
+ mali_core_subsystem *subsystem;
+ subsystem = core->subsystem;
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+ MALI_CHECK_CORE(core);
+ MALI_CHECK_SUBSYSTEM(subsystem);
+
+ /* Cores must be idle before powering off */
+ MALI_DEBUG_ASSERT(core->state == CORE_IDLE);
+
+ MALI_DEBUG_PRINT(5, ("Core: subsystem_move_core_set_off: %s\n", core->description) ) ;
+
+ core->current_job = NULL ;
+ core->state = CORE_OFF ;
+ _mali_osk_list_move( &core->list, &subsystem->renderunit_off_head );
+}
+
+#endif /* USING_MALI_PMM */
+
+/* Is used by internal function:
+ mali_core_subsystem_schedule<>; */
+/* Returns the job with the highest priority for the subsystem. NULL if none*/
+/* Must hold subsystem_mutex before entering this function */
+static mali_core_session * mali_core_subsystem_get_waiting_session(mali_core_subsystem *subsystem)
+{
+ int i;
+
+ MALI_CHECK_SUBSYSTEM(subsystem);
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+
+ if ( 0 == subsystem->awaiting_sessions_sum_all_priorities )
+ {
+ MALI_DEBUG_PRINT(5, ("Core: subsystem_get_waiting_job: No awaiting session found\n"));
+ return NULL;
+ }
+
+ for( i=0; i<PRIORITY_LEVELS ; ++i)
+ {
+ if (!_mali_osk_list_empty(&subsystem->awaiting_sessions_head[i]))
+ {
+ return _MALI_OSK_LIST_ENTRY(subsystem->awaiting_sessions_head[i].next, mali_core_session, awaiting_sessions_list);
+ }
+ }
+
+ return NULL;
+}
+
+static mali_core_job * mali_core_subsystem_release_session_get_job(mali_core_subsystem *subsystem, mali_core_session * session)
+{
+ mali_core_job *job;
+ MALI_CHECK_SUBSYSTEM(subsystem);
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+
+ job = mali_job_queue_get_job(session);
+ subsystem->awaiting_sessions_sum_all_priorities--;
+
+ if(mali_job_queue_empty(session))
+ {
+ /* This is the last job, so remove it from the list */
+ _mali_osk_list_delinit(&session->awaiting_sessions_list);
+ }
+ else
+ {
+ if (0 == (job->flags & MALI_UK_START_JOB_FLAG_MORE_JOBS_FOLLOW))
+ {
+ /* There are more jobs, but the follow flag is not set, so let other sessions run their jobs first */
+ _mali_osk_list_del(&(session->awaiting_sessions_list));
+ _mali_osk_list_addtail(&(session->awaiting_sessions_list), &(subsystem->awaiting_sessions_head[
+ session->queue[session->queue_head]->priority]));
+ }
+ /* else; keep on list, follow flag is set and there are more jobs in queue for this session */
+ }
+
+ MALI_CHECK_JOB(job);
+ return job;
+}
+
+/* Is used by internal functions:
+ mali_core_subsystem_schedule<> */
+/* This will start the job on the core. It will also release the core if it did not start.*/
+/* Must hold subsystem_mutex before entering this function */
+static void mali_core_job_start_on_core(mali_core_job *job, mali_core_renderunit *core)
+{
+ mali_core_session *session;
+ mali_core_subsystem *subsystem;
+ _mali_osk_errcode_t err;
+ session = job->session;
+ subsystem = core->subsystem;
+
+ MALI_CHECK_CORE(core);
+ MALI_CHECK_JOB(job);
+ MALI_CHECK_SUBSYSTEM(subsystem);
+ MALI_CHECK_SESSION(session);
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+
+ MALI_DEBUG_PRINT(4, ("Core: job_start_on_core: job=0x%x, session=0x%x, core=%s\n", job, session, core->description));
+
+ MALI_DEBUG_ASSERT(NULL == core->current_job) ;
+ MALI_DEBUG_ASSERT(CORE_IDLE == core->state );
+
+ mali_core_subsystem_move_set_working(core, job);
+
+#if defined USING_MALI400_L2_CACHE
+ if (0 == (job->flags & MALI_UK_START_JOB_FLAG_NO_FLUSH))
+ {
+ /* Invalidate the L2 cache */
+ if (_MALI_OSK_ERR_OK != mali_kernel_l2_cache_invalidate_all() )
+ {
+ MALI_DEBUG_PRINT(4, ("Core: Clear of L2 failed, return job. System may not be usable for some reason.\n"));
+ mali_core_subsystem_move_core_set_idle(core);
+ subsystem->return_job_to_user(job,JOB_STATUS_END_SYSTEM_UNUSABLE );
+ return;
+ }
+ }
+#endif
+
+ /* Tries to start job on the core. Returns MALI_FALSE if the job could not be started */
+ err = subsystem->start_job(job, core);
+
+ if ( _MALI_OSK_ERR_OK != err )
+ {
+ /* This will happen only if there is something in the job object
+ which make it inpossible to start. Like if it require illegal memory.*/
+ MALI_DEBUG_PRINT(4, ("Core: start_job failed, return job and putting core back into idle list\n"));
+ mali_core_subsystem_move_core_set_idle(core);
+ subsystem->return_job_to_user(job,JOB_STATUS_END_ILLEGAL_JOB );
+ }
+ else
+ {
+ u32 delay = _mali_osk_time_mstoticks(job->watchdog_msecs)+1;
+ job->watchdog_jiffies = _mali_osk_time_tickcount() + delay;
+ if (mali_benchmark)
+ {
+ _mali_osk_timer_add(core->timer, 1);
+ }
+ else
+ {
+ _mali_osk_timer_add(core->timer, delay);
+ }
+ }
+}
+
+#if USING_MMU
+static void mali_core_subsystem_callback_schedule_wrapper(void* sub)
+{
+ mali_core_subsystem * subsystem;
+ subsystem = (mali_core_subsystem *)sub;
+ MALI_DEBUG_PRINT(3, ("MMU: Is schedulling subsystem: %s\n", subsystem->name));
+ mali_core_subsystem_schedule(subsystem);
+}
+#endif
+
+/* Is used by internal function:
+ mali_core_irq_handler_bottom_half
+ mali_core_session_add_job
+*/
+/* Must hold subsystem_mutex before entering this function */
+static void mali_core_subsystem_schedule(mali_core_subsystem * subsystem)
+{
+ mali_core_renderunit *core, *tmp;
+ mali_core_session *session;
+ mali_core_job *job;
+
+ MALI_DEBUG_PRINT(5, ("Core: subsystem_schedule: %s\n", subsystem->name )) ;
+
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+
+ /* First check that there are sessions with jobs waiting to run */
+ if ( 0 == subsystem->awaiting_sessions_sum_all_priorities)
+ {
+ MALI_DEBUG_PRINT(6, ("Core: No jobs available for %s\n", subsystem->name) ) ;
+ return;
+ }
+
+ /* Returns the session with the highest priority job for the subsystem. NULL if none*/
+ session = mali_core_subsystem_get_waiting_session(subsystem);
+
+ if (NULL == session)
+ {
+ MALI_DEBUG_PRINT(6, ("Core: Schedule: No runnable job found\n"));
+ return;
+ }
+
+ _MALI_OSK_LIST_FOREACHENTRY(core, tmp, &subsystem->renderunit_idle_head, mali_core_renderunit, list)
+ {
+#if USING_MMU
+ int err = mali_memory_core_mmu_activate_page_table(core->mmu, session->mmu_session, mali_core_subsystem_callback_schedule_wrapper, subsystem);
+ if (0 == err)
+ {
+ /* core points to a core where the MMU page table activation succeeded */
+#endif
+ /* This will remove the job from queue system */
+ job = mali_core_subsystem_release_session_get_job(subsystem, session);
+ MALI_DEBUG_ASSERT_POINTER(job);
+
+ MALI_DEBUG_PRINT(6, ("Core: Schedule: Got a job 0x%x\n", job));
+
+#if USING_MALI_PMM
+ {
+ /* Message that there is a job scheduled to run
+ * NOTE: mali_core_job_start_on_core() can fail to start
+ * the job for several reasons, but it will move the core
+ * back to idle which will create the FINISHED message
+ * so we can still say that the job is SCHEDULED
+ */
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ MALI_PMM_EVENT_JOB_SCHEDULED,
+ 0 };
+ event.data = core->pmm_id;
+ _mali_ukk_pmm_event_message( &event );
+ }
+#endif
+ /* This will {remove core from freelist AND start the job on the core}*/
+ mali_core_job_start_on_core(job, core);
+
+ MALI_DEBUG_PRINT(6, ("Core: Schedule: Job started, done\n"));
+ return;
+#if USING_MMU
+ }
+#endif
+ }
+ MALI_DEBUG_PRINT(6, ("Core: Schedule: Could not activate MMU. Scheduelling postponed to MMU, checking next.\n"));
+
+#if USING_MALI_PMM
+ {
+ /* Message that there are jobs to run */
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ MALI_PMM_EVENT_JOB_QUEUED,
+ 0 };
+ if( subsystem->core_type == _MALI_GP2 || subsystem->core_type == _MALI_400_GP )
+ {
+ event.data = MALI_PMM_CORE_GP;
+ }
+ else
+ {
+ /* Check the PP is supported by the PMM */
+ MALI_DEBUG_ASSERT( subsystem->core_type == _MALI_200 || subsystem->core_type == _MALI_400_PP );
+ /* We state that all PP cores are scheduled to inform the PMM
+ * that it may need to power something up!
+ */
+ event.data = MALI_PMM_CORE_PP_ALL;
+ }
+ _mali_ukk_pmm_event_message( &event );
+ }
+#endif /* USING_MALI_PMM */
+
+}
+
+/* Is used by external function:
+ session_begin<> */
+void mali_core_session_begin(mali_core_session * session)
+{
+ mali_core_subsystem * subsystem;
+ int i;
+
+ subsystem = session->subsystem;
+ if ( NULL == subsystem )
+ {
+ MALI_PRINT_ERROR(("Missing data in struct\n"));
+ return;
+ }
+ MALI_DEBUG_PRINT(2, ("Core: session_begin: for %s\n", session->subsystem->name )) ;
+
+ session->magic_nr = SESSION_MAGIC_NR;
+
+ _MALI_OSK_INIT_LIST_HEAD(&session->renderunits_working_head);
+
+ for (i = 0; i < MALI_JOB_QUEUE_SIZE; i++)
+ {
+ session->queue[i] = NULL;
+ }
+ session->queue_head = 0;
+ session->queue_tail = 0;
+ _MALI_OSK_INIT_LIST_HEAD(&session->awaiting_sessions_list);
+ _MALI_OSK_INIT_LIST_HEAD(&session->all_sessions_list);
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem);
+ _mali_osk_list_add(&session->all_sessions_list, &session->subsystem->all_sessions_head);
+
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_init(&session->jobs_received, 0);
+ _mali_osk_atomic_init(&session->jobs_returned, 0);
+ session->pid = _mali_osk_get_pid();
+#endif
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
+
+ MALI_DEBUG_PRINT(5, ("Core: session_begin: for %s DONE\n", session->subsystem->name) ) ;
+}
+
+#if USING_MMU
+static void mali_core_renderunit_stop_bus(mali_core_renderunit* core)
+{
+ core->subsystem->stop_bus(core);
+}
+#endif
+
+void mali_core_session_close(mali_core_session * session)
+{
+ mali_core_subsystem * subsystem;
+ mali_core_renderunit *core;
+
+ subsystem = session->subsystem;
+ MALI_DEBUG_ASSERT_POINTER(subsystem);
+
+ MALI_DEBUG_PRINT(2, ("Core: session_close: for %s\n", session->subsystem->name) ) ;
+
+ /* We must grab subsystem mutex since the list this session belongs to
+ is owned by the subsystem */
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
+
+ /* Remove this session from the global sessionlist */
+ _mali_osk_list_delinit(&session->all_sessions_list);
+
+ _mali_osk_list_delinit(&(session->awaiting_sessions_list));
+
+ /* Return the potensial waiting job to user */
+ while ( !mali_job_queue_empty(session) )
+ {
+ /* Queue not empty */
+ mali_core_job *job = mali_job_queue_get_job(session);
+ subsystem->return_job_to_user( job, JOB_STATUS_END_SHUTDOWN );
+ subsystem->awaiting_sessions_sum_all_priorities--;
+ }
+
+ /* Kill active cores working for this session - freeing their jobs
+ Since the handling of one core also could stop jobs from another core, there is a while loop */
+ while ( ! _mali_osk_list_empty(&session->renderunits_working_head) )
+ {
+ core = _MALI_OSK_LIST_ENTRY(session->renderunits_working_head.next, mali_core_renderunit, list);
+ MALI_DEBUG_PRINT(3, ("Core: session_close: Core was working: %s\n", core->description )) ;
+ mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_SHUTDOWN );
+ }
+ _MALI_OSK_INIT_LIST_HEAD(&session->renderunits_working_head); /* Not necessary - we will _mali_osk_free session*/
+
+ MALI_DEBUG_PRINT(5, ("Core: session_close: for %s FINISHED\n", session->subsystem->name )) ;
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem );
+}
+
+/* Must hold subsystem_mutex before entering this function */
+_mali_osk_errcode_t mali_core_session_add_job(mali_core_session * session, mali_core_job *job, mali_core_job **job_return)
+{
+ mali_core_subsystem * subsystem;
+
+ job->magic_nr = JOB_MAGIC_NR;
+ MALI_CHECK_SESSION(session);
+
+ subsystem = session->subsystem;
+ MALI_CHECK_SUBSYSTEM(subsystem);
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsystem);
+
+ MALI_DEBUG_PRINT(5, ("Core: session_add_job: for %s\n", subsystem->name )) ;
+
+ /* Setting the default value; No job to return */
+ MALI_DEBUG_ASSERT_POINTER(job_return);
+ *job_return = NULL;
+
+ if (mali_job_queue_empty(session))
+ {
+ /* Add session to the wait list only if it didn't already have a job waiting. */
+ _mali_osk_list_addtail( &(session->awaiting_sessions_list), &(subsystem->awaiting_sessions_head[job->priority]));
+ }
+
+
+ if (_MALI_OSK_ERR_OK != mali_job_queue_add_job(session, job))
+ {
+ if (mali_job_queue_empty(session))
+ {
+ _mali_osk_list_delinit(&(session->awaiting_sessions_list));
+ }
+ MALI_DEBUG_PRINT(4, ("Core: session_add_job: %s queue is full\n", subsystem->name));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Continue to add the new job as the next job from this session */
+ MALI_DEBUG_PRINT(6, ("Core: session_add_job job=0x%x\n", job));
+
+ subsystem->awaiting_sessions_sum_all_priorities++;
+
+ mali_core_subsystem_schedule(subsystem);
+
+ MALI_DEBUG_PRINT(6, ("Core: session_add_job: for %s FINISHED\n", session->subsystem->name )) ;
+
+ MALI_SUCCESS;
+}
+
+static void mali_core_job_set_run_time(mali_core_job * job, u64 end_time)
+ {
+ u32 time_used_nano_seconds;
+
+ time_used_nano_seconds = end_time - job->start_time;
+ job->render_time_usecs = time_used_nano_seconds / 1000;
+}
+
+static void mali_core_renderunit_detach_job_from_core(mali_core_renderunit* core, mali_subsystem_reschedule_option reschedule, mali_subsystem_job_end_code end_status)
+{
+ mali_core_job * job;
+ mali_core_subsystem * subsystem;
+ mali_bool already_in_detach_function;
+ u64 time_now;
+
+ MALI_DEBUG_ASSERT(CORE_IDLE != core->state);
+ time_now = _mali_osk_time_get_ns();
+ job = core->current_job;
+ subsystem = core->subsystem;
+
+ /* The reset_core() called some lines below might call this detach
+ * funtion again. To protect the core object from being modified by
+ * recursive calls, the in_detach_function would track if it is an recursive call
+ */
+ already_in_detach_function = core->in_detach_function;
+
+
+ if ( MALI_FALSE == already_in_detach_function )
+ {
+ core->in_detach_function = MALI_TRUE;
+ if ( NULL != job )
+ {
+ mali_core_job_set_run_time(job, time_now);
+ core->current_job = NULL;
+ }
+ }
+
+ if (JOB_STATUS_END_SEG_FAULT == end_status)
+ {
+ subsystem->reset_core( core, MALI_CORE_RESET_STYLE_HARD );
+ }
+ else
+ {
+ subsystem->reset_core( core, MALI_CORE_RESET_STYLE_RUNABLE );
+ }
+
+ if ( MALI_FALSE == already_in_detach_function )
+ {
+ if ( CORE_IDLE != core->state )
+ {
+ #if MALI_GPU_UTILIZATION
+ mali_utilization_core_end(time_now);
+ #endif
+ mali_core_subsystem_move_core_set_idle(core);
+ }
+
+ core->in_detach_function = MALI_FALSE;
+
+ if ( SUBSYSTEM_RESCHEDULE == reschedule )
+ {
+ mali_core_subsystem_schedule(subsystem);
+ }
+ if ( NULL != job )
+ {
+ core->subsystem->return_job_to_user(job, end_status);
+ }
+ }
+}
+
+#if USING_MMU
+/* This function intentionally does not release the semaphore. You must run
+ stop_bus_for_all_cores(), reset_all_cores_on_mmu() and continue_job_handling()
+ after calling this function, and then call unlock_subsystem() to release the
+ semaphore. */
+
+static void lock_subsystem(struct mali_core_subsystem * subsys)
+{
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+}
+
+/* You must run lock_subsystem() before entering this function, to ensure that
+ the subsystem mutex is held.
+ Later, unlock_subsystem() can be called to release the mutex.
+
+ This function only stops cores behind the given MMU, unless "mmu" is NULL, in
+ which case all cores are stopped.
+*/
+static void stop_bus_for_all_cores_on_mmu(struct mali_core_subsystem * subsys, void* mmu)
+{
+ u32 i;
+
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+ MALI_DEBUG_PRINT(2,("Handling: bus stop %s\n", subsys->name ));
+ for(i=0 ; i < subsys->number_of_cores ; ++i)
+ {
+ mali_core_renderunit * core;
+ core = mali_core_renderunit_get_mali_core_nr(subsys,i);
+
+ /* We stop only cores behind the given MMU, unless MMU is NULL */
+ if ( (NULL!=mmu) && (core->mmu != mmu) ) continue;
+
+ if ( CORE_IDLE != core->state )
+ {
+ MALI_DEBUG_PRINT(4, ("Stopping bus on core %s\n", core->description));
+ mali_core_renderunit_stop_bus(core);
+ core->error_recovery = MALI_TRUE;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(4,("Core: not active %s\n", core->description ));
+ }
+ }
+ /* Mutex is still being held, to prevent things to happen while we do cleanup */
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+}
+
+/* You must run lock_subsystem() before entering this function, to ensure that
+ the subsystem mutex is held.
+ Later, unlock_subsystem() can be called to release the mutex.
+
+ This function only resets cores behind the given MMU, unless "mmu" is NULL, in
+ which case all cores are reset.
+*/
+static void reset_all_cores_on_mmu(struct mali_core_subsystem * subsys, void* mmu)
+{
+ u32 i;
+
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+ MALI_DEBUG_PRINT(3, ("Handling: reset cores from mmu: 0x%x on %s\n", mmu, subsys->name ));
+ for(i=0 ; i < subsys->number_of_cores ; ++i)
+ {
+ mali_core_renderunit * core;
+ core = mali_core_renderunit_get_mali_core_nr(subsys,i);
+
+ /* We reset only cores behind the given MMU, unless MMU is NULL */
+ if ( (NULL!=mmu) && (core->mmu != mmu) ) continue;
+
+ if ( CORE_IDLE != core->state )
+ {
+ MALI_DEBUG_PRINT(4, ("Abort and reset core: %s\n", core->description ));
+ mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_WAIT, JOB_STATUS_END_SEG_FAULT);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(4, ("Core: not active %s\n", core->description ));
+ }
+ }
+ MALI_DEBUG_PRINT(4, ("Handling: done %s\n", subsys->name ));
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+}
+
+/* You must run lock_subsystem() before entering this function, to ensure that
+ the subsystem mutex is held.
+ Later, unlock_subsystem() can be called to release the mutex. */
+static void continue_job_handling(struct mali_core_subsystem * subsys)
+{
+ u32 i, j;
+
+ MALI_DEBUG_PRINT(3, ("Handling: Continue: %s\n", subsys->name ));
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+
+
+ for(i=0 ; i < subsys->number_of_cores ; ++i)
+ {
+ mali_core_renderunit * core;
+ core = mali_core_renderunit_get_mali_core_nr(subsys,i);
+ core->error_recovery = MALI_FALSE;
+ }
+
+ i = subsys->number_of_cores;
+ j = subsys->awaiting_sessions_sum_all_priorities;
+
+ /* Schedule MIN(nr_waiting_jobs , number of cores) times */
+ while( i-- && j--)
+ {
+ mali_core_subsystem_schedule(subsys);
+ }
+ MALI_DEBUG_PRINT(4, ("Handling: done %s\n", subsys->name ));
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+}
+
+/* Unlock the subsystem. */
+static void unlock_subsystem(struct mali_core_subsystem * subsys)
+{
+ MALI_ASSERT_MUTEX_IS_GRABBED(subsys);
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+}
+
+void mali_core_subsystem_broadcast_notification(struct mali_core_subsystem * subsys, mali_core_notification_message message, u32 data)
+{
+ void * mmu;
+ mmu = (void*) data;
+
+ switch(message)
+ {
+ case MMU_KILL_STEP0_LOCK_SUBSYSTEM:
+ break;
+ case MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES:
+ stop_bus_for_all_cores_on_mmu(subsys, mmu);
+ break;
+ case MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS:
+ reset_all_cores_on_mmu(subsys, mmu );
+ break;
+ case MMU_KILL_STEP3_CONTINUE_JOB_HANDLING:
+ continue_job_handling(subsys);
+ break;
+ case MMU_KILL_STEP4_UNLOCK_SUBSYSTEM:
+ break;
+
+ default:
+ MALI_PRINT_ERROR(("Illegal message: 0x%x, data: 0x%x\n", (u32)message, data));
+ break;
+ }
+}
+#endif /* USING_MMU */
+
+void job_watchdog_set(mali_core_job * job, u32 watchdog_msecs)
+{
+ if (watchdog_msecs == 0) job->watchdog_msecs = mali_max_job_runtime; /* use the default */
+ else if (watchdog_msecs > WATCHDOG_MSECS_MAX) job->watchdog_msecs = WATCHDOG_MSECS_MAX; /* no larger than max */
+ else if (watchdog_msecs < WATCHDOG_MSECS_MIN) job->watchdog_msecs = WATCHDOG_MSECS_MIN; /* not below min */
+ else job->watchdog_msecs = watchdog_msecs;
+}
+
+u32 mali_core_hang_check_timeout_get(void)
+{
+ /* check the value. The user might have set the value outside the allowed range */
+ if (mali_hang_check_interval > HANG_CHECK_MSECS_MAX) mali_hang_check_interval = HANG_CHECK_MSECS_MAX; /* cap to max */
+ else if (mali_hang_check_interval < HANG_CHECK_MSECS_MIN) mali_hang_check_interval = HANG_CHECK_MSECS_MIN; /* cap to min */
+
+ /* return the active value */
+ return mali_hang_check_interval;
+}
+
+static _mali_osk_errcode_t mali_core_irq_handler_upper_half (void * data)
+{
+ mali_core_renderunit *core;
+ u32 has_pending_irq;
+
+ core = (mali_core_renderunit * )data;
+
+ if(core && (CORE_OFF == core->state))
+ {
+ MALI_SUCCESS;
+ }
+
+ if ( (NULL == core) ||
+ (NULL == core->subsystem) ||
+ (NULL == core->subsystem->irq_handler_upper_half) )
+ {
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+ MALI_CHECK_CORE(core);
+ MALI_CHECK_SUBSYSTEM(core->subsystem);
+
+ has_pending_irq = core->subsystem->irq_handler_upper_half(core);
+
+ if ( has_pending_irq )
+ {
+ _mali_osk_irq_schedulework( core->irq ) ;
+ MALI_SUCCESS;
+ }
+
+ if (mali_benchmark) MALI_SUCCESS;
+
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+}
+
+static void mali_core_irq_handler_bottom_half ( void *data )
+{
+ mali_core_renderunit *core;
+ mali_core_subsystem* subsystem;
+
+ mali_subsystem_job_end_code job_status;
+
+ core = (mali_core_renderunit * )data;
+
+ MALI_CHECK_CORE(core);
+ subsystem = core->subsystem;
+ MALI_CHECK_SUBSYSTEM(subsystem);
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
+ if ( CORE_IDLE == core->state || CORE_OFF == core->state ) goto end_function;
+
+ MALI_DEBUG_PRINT(5, ("IRQ: handling irq from core %s\n", core->description )) ;
+
+ _mali_osk_cache_flushall();
+
+ /* This function must also update the job status flag */
+ job_status = subsystem->irq_handler_bottom_half( core );
+
+ /* Retval is nonzero if the job is finished. */
+ if ( JOB_STATUS_CONTINUE_RUN != job_status )
+ {
+ mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, job_status);
+ }
+ else
+ {
+ switch ( core->state )
+ {
+ case CORE_WATCHDOG_TIMEOUT:
+ MALI_DEBUG_PRINT(2, ("Watchdog SW Timeout of job from core: %s\n", core->description ));
+ mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_TIMEOUT_SW );
+ break;
+
+ case CORE_POLL:
+ MALI_DEBUG_PRINT(5, ("Poll core: %s\n", core->description )) ;
+ core->state = CORE_WORKING;
+ _mali_osk_timer_add( core->timer, 1);
+ break;
+
+ default:
+ MALI_DEBUG_PRINT(4, ("IRQ: The job on the core continue to run: %s\n", core->description )) ;
+ break;
+ }
+ }
+end_function:
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem);
+}
+
+void subsystem_flush_mapped_mem_cache(void)
+{
+ _mali_osk_cache_flushall();
+ _mali_osk_mem_barrier();
+}
+
+#if USING_MALI_PMM
+
+_mali_osk_errcode_t mali_core_subsystem_signal_power_down(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool immediate_only)
+{
+ mali_core_renderunit * core = NULL;
+
+ MALI_CHECK_SUBSYSTEM(subsys);
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+
+ /* It is possible that this signal funciton can be called during a driver exit,
+ * and so the requested core may now be destroyed. (This is due to us not having
+ * the subsys lock before signalling power down).
+ * mali_core_renderunit_get_mali_core_nr() will report a Mali ERR because
+ * the core number is out of range (which is a valid error in other cases).
+ * So instead we check here (now that we have the subsys lock) and let the
+ * caller cope with the core get failure and check that the core has
+ * been unregistered in the PMM as part of its destruction.
+ */
+ if ( subsys->number_of_cores > mali_core_nr )
+ {
+ core = mali_core_renderunit_get_mali_core_nr(subsys, mali_core_nr);
+ }
+
+ if ( NULL == core )
+ {
+ /* Couldn't find the core */
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_DEBUG_PRINT( 1, ("Core: Failed to find core to power down\n") );
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ else if ( core->state != CORE_IDLE )
+ {
+ /* When powering down we either set a pending power down flag here so we
+ * can power down cleanly after the job completes or we don't set the
+ * flag if we have been asked to only do a power down right now
+ * In either case, return that the core is busy
+ */
+ if ( !immediate_only ) core->pend_power_down = MALI_TRUE;
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_DEBUG_PRINT( 5, ("Core: No idle core to power down\n") );
+ MALI_ERROR(_MALI_OSK_ERR_BUSY);
+ }
+
+ /* Shouldn't have a pending power down flag set */
+ MALI_DEBUG_ASSERT( !core->pend_power_down );
+
+ /* Move core to off queue */
+ mali_core_subsystem_move_core_set_off(core);
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool queue_only)
+{
+ mali_core_renderunit * core;
+
+ MALI_CHECK_SUBSYSTEM(subsys);
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys);
+
+ core = mali_core_renderunit_get_mali_core_nr(subsys, mali_core_nr);
+
+ if( core == NULL )
+ {
+ /* Couldn't find the core */
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_DEBUG_PRINT( 1, ("Core: Failed to find core to power up\n") );
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+ else if( core->state != CORE_OFF )
+ {
+ /* This will usually happen because we are trying to cancel a pending power down */
+ core->pend_power_down = MALI_FALSE;
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+ MALI_DEBUG_PRINT( 1, ("Core: No powered off core to power up (cancelled power down?)\n") );
+ MALI_ERROR(_MALI_OSK_ERR_BUSY);
+ }
+
+ /* Shouldn't have a pending power down set */
+ MALI_DEBUG_ASSERT( !core->pend_power_down );
+
+ /* Move core to idle queue */
+ mali_core_subsystem_move_core_set_idle(core);
+
+ if( !queue_only )
+ {
+ /* Reset MMU & core - core must be idle to allow this */
+#if USING_MMU
+ if ( NULL!=core->mmu )
+ {
+#if defined(USING_MALI200)
+ if (core->pmm_id != MALI_PMM_CORE_PP0)
+ {
+#endif
+ mali_kernel_mmu_reset(core->mmu);
+#if defined(USING_MALI200)
+ }
+#endif
+
+ }
+#endif /* USING_MMU */
+ subsys->reset_core( core, MALI_CORE_RESET_STYLE_RUNABLE );
+ }
+
+ /* Need to schedule work to start on this core */
+ mali_core_subsystem_schedule(subsys);
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys);
+
+ MALI_SUCCESS;
+}
+
+#endif /* USING_MALI_PMM */
+
+#if MALI_STATE_TRACKING
+u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size)
+{
+ u32 i, len = 0;
+ mali_core_renderunit *core;
+ mali_core_renderunit *tmp_core;
+
+ mali_core_session* session;
+ mali_core_session* tmp_session;
+
+ if (0 >= size)
+ {
+ return 0;
+ }
+
+ MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem );
+
+ len += _mali_osk_snprintf(buf + len, size - len, "Subsystem:\n");
+ len += _mali_osk_snprintf(buf + len, size - len, " Name: %s\n", subsystem->name);
+
+ for (i = 0; i < subsystem->number_of_cores; i++)
+ {
+ len += _mali_osk_snprintf(buf + len, size - len, " Core: #%u\n",
+ subsystem->mali_core_array[i]->core_number);
+ len += _mali_osk_snprintf(buf + len, size - len, " Description: %s\n",
+ subsystem->mali_core_array[i]->description);
+ switch(subsystem->mali_core_array[i]->state)
+ {
+ case CORE_IDLE:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_IDLE\n");
+ break;
+ case CORE_WORKING:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WORKING\n");
+ break;
+ case CORE_WATCHDOG_TIMEOUT:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WATCHDOG_TIMEOUT\n");
+ break;
+ case CORE_POLL:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_POLL\n");
+ break;
+ case CORE_HANG_CHECK_TIMEOUT:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_HANG_CHECK_TIMEOUT\n");
+ break;
+ case CORE_OFF:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_OFF\n");
+ break;
+ default:
+ len += _mali_osk_snprintf(buf + len, size - len, " State: Unknown (0x%X)\n",
+ subsystem->mali_core_array[i]->state);
+ break;
+ }
+ len += _mali_osk_snprintf(buf + len, size - len, " Current job: 0x%X\n",
+ (u32)(subsystem->mali_core_array[i]->current_job));
+ if (subsystem->mali_core_array[i]->current_job)
+ {
+ u64 time_used_nano_seconds;
+ u32 time_used_micro_seconds;
+ u64 time_now = _mali_osk_time_get_ns();
+
+ time_used_nano_seconds = time_now - subsystem->mali_core_array[i]->current_job->start_time;
+ time_used_micro_seconds = ((u32)(time_used_nano_seconds)) / 1000;
+
+ len += _mali_osk_snprintf(buf + len, size - len, " Current job session: 0x%X\n",
+ subsystem->mali_core_array[i]->current_job->session);
+ len += _mali_osk_snprintf(buf + len, size - len, " Current job number: %d\n",
+ subsystem->mali_core_array[i]->current_job->job_nr);
+ len += _mali_osk_snprintf(buf + len, size - len, " Current job render_time micro seconds: %d\n",
+ time_used_micro_seconds );
+ len += _mali_osk_snprintf(buf + len, size - len, " Current job start time micro seconds: %d\n",
+ (u32) (subsystem->mali_core_array[i]->current_job->start_time >>10) );
+ }
+ len += _mali_osk_snprintf(buf + len, size - len, " Core version: 0x%X\n",
+ subsystem->mali_core_array[i]->core_version);
+#if USING_MALI_PMM
+ len += _mali_osk_snprintf(buf + len, size - len, " PMM id: 0x%X\n",
+ subsystem->mali_core_array[i]->pmm_id);
+ len += _mali_osk_snprintf(buf + len, size - len, " Power down requested: %s\n",
+ subsystem->mali_core_array[i]->pend_power_down ? "TRUE" : "FALSE");
+#endif
+ }
+
+ len += _mali_osk_snprintf(buf + len, size - len, " Cores on idle list:\n");
+ _MALI_OSK_LIST_FOREACHENTRY(core, tmp_core, &subsystem->renderunit_idle_head, mali_core_renderunit, list)
+ {
+ len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number);
+ }
+
+ len += _mali_osk_snprintf(buf + len, size - len, " Cores on off list:\n");
+ _MALI_OSK_LIST_FOREACHENTRY(core, tmp_core, &subsystem->renderunit_off_head, mali_core_renderunit, list)
+ {
+ len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number);
+ }
+
+ len += _mali_osk_snprintf(buf + len, size - len, " Connected sessions:\n");
+ _MALI_OSK_LIST_FOREACHENTRY(session, tmp_session, &subsystem->all_sessions_head, mali_core_session, all_sessions_list)
+ {
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " Session 0x%X:\n", (u32)session);
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " Queue depth: %u\n", mali_job_queue_size(session));
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " First waiting job: 0x%p\n", session->queue[session->queue_head]);
+ len += _mali_osk_snprintf(buf + len, size - len, " Notification queue: %s\n",
+ _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY");
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " Jobs received:%4d\n", _mali_osk_atomic_read(&session->jobs_received));
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " Jobs started :%4d\n", _mali_osk_atomic_read(&session->jobs_started));
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " Jobs ended :%4d\n", _mali_osk_atomic_read(&session->jobs_ended));
+ len += _mali_osk_snprintf(buf + len, size - len,
+ " Jobs returned:%4d\n", _mali_osk_atomic_read(&session->jobs_returned));
+ len += _mali_osk_snprintf(buf + len, size - len, " PID: %d\n", session->pid);
+ }
+
+ len += _mali_osk_snprintf(buf + len, size - len, " Waiting sessions sum all priorities: %u\n",
+ subsystem->awaiting_sessions_sum_all_priorities);
+ for (i = 0; i < PRIORITY_LEVELS; i++)
+ {
+ len += _mali_osk_snprintf(buf + len, size - len, " Waiting sessions with priority %u:\n", i);
+ _MALI_OSK_LIST_FOREACHENTRY(session, tmp_session, &subsystem->awaiting_sessions_head[i],
+ mali_core_session, awaiting_sessions_list)
+ {
+ len += _mali_osk_snprintf(buf + len, size - len, " Session 0x%X:\n", (u32)session);
+ len += _mali_osk_snprintf(buf + len, size - len, " Waiting job: 0x%X\n",
+ (u32)session->queue[session->queue_head]);
+ len += _mali_osk_snprintf(buf + len, size - len, " Notification queue: %s\n",
+ _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY");
+ }
+ }
+
+ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem );
+ return len;
+}
+#endif
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h
new file mode 100644
index 00000000000..6d0c11dd188
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_RENDERCORE_H__
+#define __MALI_RENDERCORE_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_subsystem.h"
+
+#define PRIORITY_LEVELS 3
+#define PRIORITY_MAX 0
+#define PRIORITY_MIN (PRIORITY_MAX+PRIORITY_LEVELS-1)
+
+/* This file contains what we need in kernel for all core types. */
+
+typedef enum
+{
+ CORE_IDLE, /**< Core is ready for a new job */
+ CORE_WORKING, /**< Core is working on a job */
+ CORE_WATCHDOG_TIMEOUT, /**< Core is working but it has timed out */
+ CORE_POLL, /**< Poll timer triggered, pending handling */
+ CORE_HANG_CHECK_TIMEOUT,/**< Timeout for hang detection */
+ CORE_OFF /**< Core is powered off */
+} mali_core_status;
+
+typedef enum
+{
+ SUBSYSTEM_RESCHEDULE,
+ SUBSYSTEM_WAIT
+} mali_subsystem_reschedule_option;
+
+typedef enum
+{
+ MALI_CORE_RESET_STYLE_RUNABLE,
+ MALI_CORE_RESET_STYLE_DISABLE,
+ MALI_CORE_RESET_STYLE_HARD
+} mali_core_reset_style;
+
+typedef enum
+{
+ JOB_STATUS_CONTINUE_RUN = 0x01,
+ JOB_STATUS_END_SUCCESS = 1<<(16+0),
+ JOB_STATUS_END_OOM = 1<<(16+1),
+ JOB_STATUS_END_ABORT = 1<<(16+2),
+ JOB_STATUS_END_TIMEOUT_SW = 1<<(16+3),
+ JOB_STATUS_END_HANG = 1<<(16+4),
+ JOB_STATUS_END_SEG_FAULT = 1<<(16+5),
+ JOB_STATUS_END_ILLEGAL_JOB = 1<<(16+6),
+ JOB_STATUS_END_UNKNOWN_ERR = 1<<(16+7),
+ JOB_STATUS_END_SHUTDOWN = 1<<(16+8),
+ JOB_STATUS_END_SYSTEM_UNUSABLE = 1<<(16+9)
+} mali_subsystem_job_end_code;
+
+
+struct mali_core_job;
+struct mali_core_subsystem;
+struct mali_core_renderunit;
+struct mali_core_session;
+
+/* We have one of these subsystems for each core type */
+typedef struct mali_core_subsystem
+{
+ struct mali_core_renderunit ** mali_core_array; /* An array of all cores of this type */
+ u32 number_of_cores; /* Number of cores in this list */
+
+ _mali_core_type core_type;
+
+ u32 magic_nr;
+
+ _mali_osk_list_t renderunit_idle_head; /* Idle cores of this type */
+ _mali_osk_list_t renderunit_off_head; /* Powered off cores of this type */
+
+ /* Linked list for each priority of sessions with a job ready for scheduelling */
+ _mali_osk_list_t awaiting_sessions_head[PRIORITY_LEVELS];
+ u32 awaiting_sessions_sum_all_priorities;
+
+ /* Linked list of all sessions connected to this coretype */
+ _mali_osk_list_t all_sessions_head;
+
+ /* Linked list of all sessions connected to this coretype */
+ struct _mali_osk_notification_queue_t * notification_queue;
+
+ const char * name;
+ mali_kernel_subsystem_identifier id;
+
+ /**** Functions registered for this core type. Set during mali_core_init ******/
+ /* Start this job on this core. Return MALI_TRUE if the job was started. */
+ _mali_osk_errcode_t (*start_job)(struct mali_core_job * job, struct mali_core_renderunit * core);
+
+ /* Check if given core has an interrupt pending. Return MALI_TRUE and set mask to 0 if pending */
+ u32 (*irq_handler_upper_half)(struct mali_core_renderunit * core);
+
+ /* This function should check if the interrupt indicates that job was finished.
+ If so it should update the job-struct, reset the core registers, and return MALI_TRUE, .
+ If the job is still working after this function it should return MALI_FALSE.
+ The function must also enable the bits in the interrupt mask for the core.
+ Called by the bottom half interrupt function. */
+ int (*irq_handler_bottom_half)(struct mali_core_renderunit* core);
+
+ /* This function is called from the ioctl function and should return a mali_core_job pointer
+ to a created mali_core_job object with the data given from userspace */
+ _mali_osk_errcode_t (*get_new_job_from_user)(struct mali_core_session * session, void * argument);
+
+ _mali_osk_errcode_t (*suspend_response)(struct mali_core_session * session, void * argument);
+
+ /* This function is called from the ioctl function and should write the necessary data
+ to userspace telling which job was finished and the status and debuginfo for this job.
+ The function must also free and cleanup the input job object. */
+ void (*return_job_to_user)(struct mali_core_job * job, mali_subsystem_job_end_code end_status);
+
+ /* Is called when a subsystem shuts down. This function needs to
+ release internal pointers in the core struct, and free the
+ core struct before returning.
+ It is not allowed to write to any registers, since this
+ unmapping is already done. */
+ void (*renderunit_delete)(struct mali_core_renderunit * core);
+
+ /* Is called when we want to abort a job that is running on the core.
+ This is done if program exits while core is running */
+ void (*reset_core)(struct mali_core_renderunit * core, mali_core_reset_style style);
+
+ /* Is called when the rendercore wants the core to give an interrupt */
+ void (*probe_core_irq_trigger)(struct mali_core_renderunit* core);
+
+ /* Is called when the irq probe wants the core to acknowledge an interrupt from the hw */
+ _mali_osk_errcode_t (*probe_core_irq_acknowledge)(struct mali_core_renderunit* core);
+
+ /* Called when the rendercore want to issue a bus stop request to a core */
+ void (*stop_bus)(struct mali_core_renderunit* core);
+} mali_core_subsystem;
+
+
+/* Per core data. This must be embedded into each core type internal core info. */
+typedef struct mali_core_renderunit
+{
+ struct mali_core_subsystem * subsystem; /* The core belongs to this subsystem */
+ _mali_osk_list_t list; /* Is always in subsystem->idle_list OR session->renderunits_working */
+ mali_core_status state;
+ mali_bool error_recovery; /* Indicates if the core is waiting for external help to recover (typically the MMU) */
+ mali_bool in_detach_function;
+ struct mali_core_job * current_job; /* Current job being processed on this core ||NULL */
+ u32 magic_nr;
+ _mali_osk_timer_t * timer;
+ _mali_osk_timer_t * timer_hang_detection;
+
+ mali_io_address registers_mapped; /* IO-mapped pointer to registers */
+ u32 registers_base_addr; /* Base addres of the registers */
+ u32 size; /* The size of registers_mapped */
+ const char * description; /* Description of this core. */
+ u32 irq_nr; /* The IRQ nr for this core */
+ u32 core_version;
+#if USING_MMU
+ u32 mmu_id;
+ void * mmu; /* The MMU this rendercore is behind.*/
+#endif
+#if USING_MALI_PMM
+ mali_pmm_core_id pmm_id; /* The PMM core id */
+ mali_bool pend_power_down; /* Power down is requested */
+#endif
+
+ u32 core_number; /* 0 for first detected core of this type, 1 for second and so on */
+
+ _mali_osk_irq_t *irq;
+} mali_core_renderunit;
+
+
+#define MALI_JOB_QUEUE_SIZE 8
+/* Per open FILE data. */
+/* You must held subsystem->mutex before any transactions to this datatype. */
+typedef struct mali_core_session
+{
+ struct mali_core_subsystem * subsystem; /* The session belongs to this subsystem */
+ _mali_osk_list_t renderunits_working_head; /* List of renderunits working for this session */
+ struct mali_core_job *queue[MALI_JOB_QUEUE_SIZE]; /* The next job from this session to run */
+ int queue_head;
+ int queue_tail;
+ int queue_size;
+
+ _mali_osk_list_t awaiting_sessions_list; /* Linked list of sessions with jobs, for each priority */
+ _mali_osk_list_t all_sessions_list; /* Linked list of all sessions on the system. */
+
+ _mali_osk_notification_queue_t * notification_queue; /* Messages back to Base in userspace*/
+#if USING_MMU
+ struct mali_session_data * mmu_session; /* The session associated with the MMU page tables for this core */
+#endif
+ u32 magic_nr;
+#if MALI_STATE_TRACKING
+ _mali_osk_atomic_t jobs_received;
+ _mali_osk_atomic_t jobs_started;
+ _mali_osk_atomic_t jobs_ended;
+ _mali_osk_atomic_t jobs_returned;
+ u32 pid;
+#endif
+} mali_core_session;
+
+/* This must be embedded into a specific mali_core_job struct */
+/* use this macro to get spesific mali_core_job: container_of(ptr, type, member)*/
+typedef struct mali_core_job
+{
+ _mali_osk_list_t list; /* Linked list of jobs. Used by struct mali_core_session */
+ struct mali_core_session *session;
+ u32 magic_nr;
+ u32 priority;
+ u32 watchdog_msecs;
+ u32 render_time_usecs ;
+ u64 start_time;
+ unsigned long watchdog_jiffies;
+ u32 abort_id;
+ u32 job_nr;
+ _mali_uk_start_job_flags flags;
+} mali_core_job;
+
+MALI_STATIC_INLINE mali_bool mali_job_queue_empty(mali_core_session *session)
+{
+ if (0 == session->queue_size)
+ {
+ return MALI_TRUE;
+ }
+ return MALI_FALSE;
+}
+
+MALI_STATIC_INLINE mali_bool mali_job_queue_full(mali_core_session *session)
+{
+ if (MALI_JOB_QUEUE_SIZE == session->queue_size)
+ {
+ return MALI_TRUE;
+ }
+ return MALI_FALSE;
+}
+
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_job_queue_add_job(mali_core_session *session, struct mali_core_job *job)
+{
+ if (mali_job_queue_full(session))
+ {
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ session->queue[session->queue_tail] = job;
+ session->queue_tail = (session->queue_tail + 1) % MALI_JOB_QUEUE_SIZE;
+ session->queue_size++;
+
+ MALI_SUCCESS;
+}
+
+MALI_STATIC_INLINE struct mali_core_job *mali_job_queue_get_job(mali_core_session *session)
+{
+ struct mali_core_job *job;
+ MALI_DEBUG_ASSERT(!mali_job_queue_empty(session));
+
+ job = session->queue[session->queue_head];
+
+ MALI_DEBUG_ASSERT_POINTER(job);
+
+ session->queue[session->queue_head] = NULL;
+ session->queue_head = (session->queue_head + 1) % MALI_JOB_QUEUE_SIZE;
+ session->queue_size--;
+
+ return job;
+}
+
+MALI_STATIC_INLINE u32 mali_job_queue_size(mali_core_session *session)
+{
+ return (u32)(session->queue_size);
+}
+
+MALI_STATIC_INLINE struct mali_core_job *mali_job_queue_abort_job(mali_core_session *session, u32 abort_id)
+{
+ int i;
+ int n;
+ struct mali_core_job *job = NULL;
+
+ for (i = session->queue_head, n = session->queue_size; n > 0; n--, i = (i+1)%MALI_JOB_QUEUE_SIZE)
+ {
+ if (session->queue[i]->abort_id == abort_id)
+ {
+ /* Remove job from queue */
+ job = session->queue[i];
+ session->queue[i] = NULL;
+
+ session->queue_size -= 1;
+ n--;
+ break;
+ }
+ }
+ if (NULL == job)
+ {
+ return NULL;
+ }
+
+ /* Rearrange queue */
+ while (n > 0)
+ {
+ int next = (i + 1) % MALI_JOB_QUEUE_SIZE;
+ session->queue[i] = session->queue[next];
+ i = next;
+ n--;
+ }
+ session->queue_tail = i;
+
+ return job;
+}
+
+
+/*
+ * The rendercode subsystem is included in the subsystems[] array.
+ */
+extern struct mali_kernel_subsystem mali_subsystem_rendercore;
+
+void subsystem_flush_mapped_mem_cache(void);
+
+
+#define SUBSYSTEM_MAGIC_NR 0xdeadbeef
+#define CORE_MAGIC_NR 0xcafebabe
+#define SESSION_MAGIC_NR 0xbabe1234
+#define JOB_MAGIC_NR 0x0123abcd
+
+
+#define MALI_CHECK_SUBSYSTEM(subsystem)\
+ do { \
+ if ( SUBSYSTEM_MAGIC_NR != subsystem->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
+ } while (0)
+
+#define MALI_CHECK_CORE(CORE)\
+ do { \
+ if ( CORE_MAGIC_NR != CORE->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
+} while (0)
+
+#define MALI_CHECK_SESSION(SESSION)\
+ do { \
+ if ( SESSION_MAGIC_NR != SESSION->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
+} while (0)
+
+#define MALI_CHECK_JOB(JOB)\
+ do { \
+ if ( JOB_MAGIC_NR != JOB->magic_nr) MALI_PRINT_ERROR(("Wrong magic number"));\
+} while (0)
+
+
+/* Check if job_a has higher priority than job_b */
+MALI_STATIC_INLINE int job_has_higher_priority(mali_core_job * job_a, mali_core_job * job_b)
+{
+ /* The lowest number has the highest priority */
+ return (int) (job_a->priority < job_b->priority);
+}
+
+MALI_STATIC_INLINE void job_priority_set(mali_core_job * job, u32 priority)
+{
+ if (priority > PRIORITY_MIN) job->priority = PRIORITY_MIN;
+ else job->priority = priority;
+}
+
+void job_watchdog_set(mali_core_job * job, u32 watchdog_msecs);
+
+/* For use by const default register settings (e.g. set these after reset) */
+typedef struct register_address_and_value
+{
+ u32 address;
+ u32 value;
+} register_address_and_value ;
+
+
+/* For use by dynamic default register settings (e.g. set these after reset) */
+typedef struct register_address_and_value_list
+{
+ _mali_osk_list_t list;
+ register_address_and_value item;
+} register_address_and_value_list ;
+
+/* Used if the user wants to set a continious block of registers */
+typedef struct register_array_user
+{
+ u32 entries_in_array;
+ u32 start_address;
+ void __user * reg_array;
+}register_array_user;
+
+
+#define MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys) \
+ do { \
+ MALI_DEBUG_PRINT(5, ("MUTEX: GRAB %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
+ _mali_osk_lock_wait( rendercores_global_mutex, _MALI_OSK_LOCKMODE_RW); \
+ MALI_DEBUG_PRINT(5, ("MUTEX: GRABBED %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
+ if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
+ rendercores_global_mutex_is_held = 1; \
+ rendercores_global_mutex_owner = _mali_osk_get_tid(); \
+ } while (0) ;
+
+#define MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys) \
+ do { \
+ MALI_DEBUG_PRINT(5, ("MUTEX: RELEASE %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
+ rendercores_global_mutex_is_held = 0; \
+ rendercores_global_mutex_owner = 0; \
+ if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
+ _mali_osk_lock_signal( rendercores_global_mutex, _MALI_OSK_LOCKMODE_RW); \
+ MALI_DEBUG_PRINT(5, ("MUTEX: RELEASED %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \
+ if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
+ } while (0) ;
+
+
+#define MALI_ASSERT_MUTEX_IS_GRABBED(input_pointer)\
+ do { \
+ if ( 0 == rendercores_global_mutex_is_held ) MALI_PRINT_ERROR(("ASSERT MUTEX SHOULD BE GRABBED"));\
+ if ( SUBSYSTEM_MAGIC_NR != input_pointer->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\
+ if ( rendercores_global_mutex_owner != _mali_osk_get_tid() ) MALI_PRINT_ERROR(("Owner mismatch"));\
+ } while (0)
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_core_renderunit_register_rw_check(mali_core_renderunit *core,
+ u32 relative_address)
+{
+#if USING_MALI_PMM
+ if( core->state == CORE_OFF )
+ {
+ MALI_PRINT_ERROR(("Core is OFF during access: Core: %s Addr: 0x%04X\n",
+ core->description,relative_address));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+#endif
+
+ MALI_DEBUG_ASSERT((relative_address & 0x03) == 0);
+
+ if (mali_benchmark) MALI_ERROR(_MALI_OSK_ERR_FAULT);
+
+ MALI_DEBUG_CODE(if (relative_address >= core->size)
+ {
+ MALI_PRINT_ERROR(("Trying to access illegal register: 0x%04x in core: %s",
+ relative_address, core->description));
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ })
+
+ MALI_SUCCESS;
+}
+
+
+MALI_STATIC_INLINE u32 mali_core_renderunit_register_read(struct mali_core_renderunit *core, u32 relative_address)
+{
+ u32 read_val;
+
+ if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address))
+ return 0xDEADBEEF;
+
+ read_val = _mali_osk_mem_ioread32(core->registers_mapped, relative_address);
+
+ MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read: Core:%s Addr:0x%04X Val:0x%08x\n",
+ core->description,relative_address, read_val));
+
+ return read_val;
+}
+
+MALI_STATIC_INLINE void mali_core_renderunit_register_read_array(struct mali_core_renderunit *core,
+ u32 relative_address,
+ u32 * result_array,
+ u32 nr_of_regs)
+{
+ /* NOTE Do not use burst reads against the registers */
+ u32 i;
+
+ MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read_array: Core:%s Addr:0x%04X Nr_regs: %u\n",
+ core->description,relative_address, nr_of_regs));
+
+ for(i=0; i<nr_of_regs; ++i)
+ {
+ result_array[i] = mali_core_renderunit_register_read(core, relative_address + i*4);
+ }
+}
+
+/*
+ * Write to a core register, and bypass implied memory barriers.
+ *
+ * On some systems, _mali_osk_mem_iowrite32() implies a memory barrier. This
+ * can be a performance problem when doing many writes in sequence.
+ *
+ * When using this function, ensure proper barriers are put in palce. Most
+ * likely a _mali_osk_mem_barrier() is needed after all related writes are
+ * completed.
+ *
+ */
+MALI_STATIC_INLINE void mali_core_renderunit_register_write_relaxed(mali_core_renderunit *core,
+ u32 relative_address,
+ u32 new_val)
+{
+ if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address))
+ return;
+
+ MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write_relaxed: Core:%s Addr:0x%04X Val:0x%08x\n",
+ core->description,relative_address, new_val));
+
+ _mali_osk_mem_iowrite32_relaxed(core->registers_mapped, relative_address, new_val);
+}
+
+MALI_STATIC_INLINE void mali_core_renderunit_register_write(struct mali_core_renderunit *core,
+ u32 relative_address,
+ u32 new_val)
+{
+ MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write: Core:%s Addr:0x%04X Val:0x%08x\n",
+ core->description,relative_address, new_val));
+
+ if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address))
+ return;
+
+ _mali_osk_mem_iowrite32(core->registers_mapped, relative_address, new_val);
+}
+
+MALI_STATIC_INLINE void mali_core_renderunit_register_write_array(struct mali_core_renderunit *core,
+ u32 relative_address,
+ u32 * write_array,
+ u32 nr_of_regs)
+{
+ u32 i;
+ MALI_DEBUG_PRINT(6, ("Core: renderunit_register_write_array: Core:%s Addr:0x%04X Nr_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_core_renderunit_register_write_relaxed(core, relative_address + i*4, write_array[i]);
+ }
+}
+
+_mali_osk_errcode_t mali_core_renderunit_init(struct mali_core_renderunit * core);
+void mali_core_renderunit_term(struct mali_core_renderunit * core);
+int mali_core_renderunit_map_registers(struct mali_core_renderunit *core);
+void mali_core_renderunit_unmap_registers(struct mali_core_renderunit *core);
+int mali_core_renderunit_irq_handler_add(struct mali_core_renderunit *core);
+mali_core_renderunit * mali_core_renderunit_get_mali_core_nr(mali_core_subsystem *subsys, u32 mali_core_nr);
+
+int mali_core_subsystem_init(struct mali_core_subsystem * new_subsys);
+#if USING_MMU
+void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys);
+#endif
+int mali_core_subsystem_register_renderunit(struct mali_core_subsystem * subsys, struct mali_core_renderunit * core);
+int mali_core_subsystem_system_info_fill(mali_core_subsystem* subsys, _mali_system_info* info);
+void mali_core_subsystem_cleanup(struct mali_core_subsystem * subsys);
+#if USING_MMU
+void mali_core_subsystem_broadcast_notification(struct mali_core_subsystem * subsys, mali_core_notification_message message, u32 data);
+#endif
+void mali_core_session_begin(mali_core_session *session);
+void mali_core_session_close(mali_core_session * session);
+int mali_core_session_add_job(mali_core_session * session, mali_core_job *job, mali_core_job **job_return);
+u32 mali_core_hang_check_timeout_get(void);
+
+_mali_osk_errcode_t mali_core_subsystem_ioctl_start_job(mali_core_session * session, void *job_data);
+_mali_osk_errcode_t mali_core_subsystem_ioctl_number_of_cores_get(mali_core_session * session, u32 *number_of_cores);
+_mali_osk_errcode_t mali_core_subsystem_ioctl_core_version_get(mali_core_session * session, _mali_core_version *version);
+_mali_osk_errcode_t mali_core_subsystem_ioctl_suspend_response(mali_core_session * session, void* argument);
+void mali_core_subsystem_ioctl_abort_job(mali_core_session * session, u32 id);
+
+#if USING_MALI_PMM
+_mali_osk_errcode_t mali_core_subsystem_signal_power_down(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool immediate_only);
+_mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool queue_only);
+#endif
+
+#if MALI_STATE_TRACKING
+u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size);
+#endif
+
+#endif /* __MALI_RENDERCORE_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_session_manager.h b/drivers/gpu/arm/mali/common/mali_kernel_session_manager.h
new file mode 100644
index 00000000000..821f0fd906b
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_session_manager.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_SESSION_MANAGER_H__
+#define __MALI_KERNEL_SESSION_MANAGER_H__
+
+/* Incomplete struct to pass around pointers to it */
+struct mali_session_data;
+
+void * mali_kernel_session_manager_slot_get(struct mali_session_data * session, int id);
+
+#endif /* __MALI_KERNEL_SESSION_MANAGER_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h b/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h
new file mode 100644
index 00000000000..1828913a9d8
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_kernel_subsystem.h
+ */
+
+#ifndef __MALI_KERNEL_SUBSYSTEM_H__
+#define __MALI_KERNEL_SUBSYSTEM_H__
+
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_session_manager.h"
+
+/* typedefs of the datatypes used in the hook functions */
+typedef void * mali_kernel_subsystem_session_slot;
+typedef int mali_kernel_subsystem_identifier;
+typedef _mali_osk_errcode_t (*mali_kernel_resource_registrator)(_mali_osk_resource_t *);
+
+/**
+ * Broadcast notification messages
+ */
+typedef enum mali_core_notification_message
+{
+ MMU_KILL_STEP0_LOCK_SUBSYSTEM, /**< Request to lock subsystem */
+ MMU_KILL_STEP1_STOP_BUS_FOR_ALL_CORES, /**< Request to stop all buses */
+ MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS, /**< Request kill all jobs, and not start more jobs */
+ MMU_KILL_STEP3_CONTINUE_JOB_HANDLING, /**< Request to continue with new jobs on all cores */
+ MMU_KILL_STEP4_UNLOCK_SUBSYSTEM /**< Request to unlock subsystem */
+} mali_core_notification_message;
+
+/**
+ * A function pointer can be NULL if the subsystem isn't interested in the event.
+ */
+typedef struct mali_kernel_subsystem
+{
+ /* subsystem control */
+ _mali_osk_errcode_t (*startup)(mali_kernel_subsystem_identifier id); /**< Called during module load or system startup*/
+ void (*shutdown)(mali_kernel_subsystem_identifier id); /**< Called during module unload or system shutdown */
+
+ /**
+ * Called during module load or system startup.
+ * Called when all subsystems have reported startup OK and all resources where successfully initialized
+ */
+ _mali_osk_errcode_t (*load_complete)(mali_kernel_subsystem_identifier id);
+
+ /* per subsystem handlers */
+ _mali_osk_errcode_t (*system_info_fill)(_mali_system_info* info); /**< Fill info into info struct. MUST allocate memory with kmalloc, since it's kfree'd */
+
+ /* per session handlers */
+ /**
+ * Informs about a new session.
+ * slot can be used to track per-session per-subsystem data.
+ * queue can be used to send events to user space.
+ * _mali_osk_errcode_t error return value.
+ */
+ _mali_osk_errcode_t (*session_begin)(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue);
+ /**
+ * Informs that a session is ending
+ * slot was the same as given during session_begin
+ */
+ void (*session_end)(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot);
+
+ /* Used by subsystems to send messages to each other. This is the receiving end */
+ void (*broadcast_notification)(mali_core_notification_message message, u32 data);
+
+#if MALI_STATE_TRACKING
+ /** Dump the current state of the subsystem */
+ u32 (*dump_state)(char *buf, u32 size);
+#endif
+} mali_kernel_subsystem;
+
+/* functions used by the subsystems to interact with the core */
+/**
+ * Register a resouce handler
+ * @param type The resoruce type to register a handler for
+ * @param handler Pointer to the function handling this resource
+ * @return _MALI_OSK_ERR_OK on success. Otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t _mali_kernel_core_register_resource_handler(_mali_osk_resource_type_t type, mali_kernel_resource_registrator handler);
+
+/* function used to interact with other subsystems */
+/**
+ * Broadcast a message
+ * Sends a message to all subsystems which have registered a broadcast notification handler
+ * @param message The message to send
+ * @param data Message specific extra data
+ */
+void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data);
+
+#if MALI_STATE_TRACKING
+/**
+ * Tell all subsystems to dump their current state
+ */
+u32 _mali_kernel_core_dump_state(char *buf, u32 size);
+#endif
+
+
+#endif /* __MALI_KERNEL_SUBSYSTEM_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_utilization.c b/drivers/gpu/arm/mali/common/mali_kernel_utilization.c
new file mode 100644
index 00000000000..72eb4b0c609
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_utilization.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_utilization.h"
+#include "mali_osk.h"
+#include "mali_platform.h"
+
+/* Define how often to calculate and report GPU utilization, in milliseconds */
+#define MALI_GPU_UTILIZATION_TIMEOUT 1000
+
+static _mali_osk_lock_t *time_data_lock;
+
+static _mali_osk_atomic_t num_running_cores;
+
+static u64 period_start_time = 0;
+static u64 work_start_time = 0;
+static u64 accumulated_work_time = 0;
+
+static _mali_osk_timer_t *utilization_timer = NULL;
+static mali_bool timer_running = MALI_FALSE;
+
+
+static void calculate_gpu_utilization(void* arg)
+{
+ u64 time_now;
+ u64 time_period;
+ u32 leading_zeroes;
+ u32 shift_val;
+ u32 work_normalized;
+ u32 period_normalized;
+ u32 utilization;
+
+ _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (accumulated_work_time == 0 && work_start_time == 0)
+ {
+ /* Don't reschedule timer, this will be started if new work arrives */
+ timer_running = MALI_FALSE;
+
+ _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* No work done for this period, report zero usage */
+ mali_gpu_utilization_handler(0);
+
+ 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 != 0)
+ {
+ accumulated_work_time += (time_now - work_start_time);
+ work_start_time = 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 = (u32)(accumulated_work_time >> 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 <<= 8;
+ }
+
+ utilization = work_normalized / period_normalized;
+
+ accumulated_work_time = 0;
+ period_start_time = time_now; /* starting a new period */
+
+ _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+
+ _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT));
+
+ mali_gpu_utilization_handler(utilization);
+}
+
+
+
+_mali_osk_errcode_t mali_utilization_init(void)
+{
+ time_data_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ|_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0 );
+ if (NULL == time_data_lock)
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ _mali_osk_atomic_init(&num_running_cores, 0);
+
+ utilization_timer = _mali_osk_timer_init();
+ if (NULL == utilization_timer)
+ {
+ _mali_osk_lock_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)
+{
+ if (NULL != utilization_timer)
+ {
+ _mali_osk_timer_del(utilization_timer);
+ timer_running = MALI_FALSE;
+ }
+}
+
+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_atomic_term(&num_running_cores);
+
+ _mali_osk_lock_term(time_data_lock);
+}
+
+
+
+void mali_utilization_core_start(u64 time_now)
+{
+ if (_mali_osk_atomic_inc_return(&num_running_cores) == 1)
+ {
+ /*
+ * We went from zero cores working, to one core working,
+ * we now consider the entire GPU for being busy
+ */
+
+ _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (time_now < period_start_time)
+ {
+ /*
+ * This might happen if the calculate_gpu_utilization() was able
+ * to run between the sampling of time_now and us grabbing the lock above
+ */
+ time_now = period_start_time;
+ }
+
+ work_start_time = time_now;
+ if (timer_running != MALI_TRUE)
+ {
+ timer_running = MALI_TRUE;
+ period_start_time = work_start_time; /* starting a new period */
+
+ _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+
+ _mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT));
+ }
+ else
+ {
+ _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+ }
+ }
+}
+
+
+
+void mali_utilization_core_end(u64 time_now)
+{
+ if (_mali_osk_atomic_dec_return(&num_running_cores) == 0)
+ {
+ /*
+ * No more cores are working, so accumulate the time we was busy.
+ */
+ _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (time_now < work_start_time)
+ {
+ /*
+ * This might happen if the calculate_gpu_utilization() was able
+ * to run between the sampling of time_now and us grabbing the lock above
+ */
+ time_now = work_start_time;
+ }
+
+ accumulated_work_time += (time_now - work_start_time);
+ work_start_time = 0;
+
+ _mali_osk_lock_signal(time_data_lock, _MALI_OSK_LOCKMODE_RW);
+ }
+}
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_utilization.h b/drivers/gpu/arm/mali/common/mali_kernel_utilization.h
new file mode 100644
index 00000000000..1f605179d8f
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_utilization.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_UTILIZATION_H__
+#define __MALI_KERNEL_UTILIZATION_H__
+
+#include "mali_osk.h"
+
+/**
+ * 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);
+
+/**
+ * Should be called when a job is about to execute a job
+ */
+void mali_utilization_core_start(u64 time_now);
+
+/**
+ * Should be called to stop the utilization timer during system suspend
+ */
+void mali_utilization_suspend(void);
+
+/**
+ * Should be called when a job has completed executing a job
+ */
+void mali_utilization_core_end(u64 time_now);
+
+
+#endif /* __MALI_KERNEL_UTILIZATION_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_kernel_vsync.c b/drivers/gpu/arm/mali/common/mali_kernel_vsync.c
new file mode 100644
index 00000000000..686f84c7933
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_kernel_vsync.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_mali.h"
+#include "mali_ukk.h"
+/*#include "mali_timestamp.h"*/
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_kernel_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 */
+/* u64 ts = _mali_timestamp_get();
+ */
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT)
+ {
+ _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SUSPEND |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+ 0, 0, 0, 0, 0);
+ }
+
+ if ( event==_MALI_UK_VSYNC_EVENT_END_WAIT)
+ {
+
+ _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_RESUME |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+ 0, 0, 0, 0, 0);
+ }
+#endif
+ MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));
+ MALI_SUCCESS;
+}
+
diff --git a/drivers/gpu/arm/mali/common/mali_osk.h b/drivers/gpu/arm/mali/common/mali_osk.h
new file mode 100644
index 00000000000..6a6c3e0b76d
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_osk.h
@@ -0,0 +1,1715 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_osk.h
+ * Defines the OS abstraction layer for the kernel device driver (OSK)
+ */
+
+#ifndef __MALI_OSK_H__
+#define __MALI_OSK_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
+
+/**
+ * @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_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_irq_schedulework(). Refer to \ref _mali_osk_irq_schedulework() 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 );
+
+/** @brief IRQ 'bottom-half' handler callback.
+ *
+ * This function is implemented by the common layer to do the deferred handling
+ * of a resource's IRQ. Usually, this work cannot be carried out in IRQ context
+ * by the IRQ upper-half handler.
+ *
+ * The IRQ bottom-half handler maps on to the concept of an IST that may
+ * execute some time after the actual IRQ has fired.
+ *
+ * All OSK-registered IRQ bottom-half handlers will be serialized, across all
+ * CPU-cores in the system.
+ *
+ * Refer to \ref _mali_osk_irq_schedulework() for more information on the
+ * IRQ work-queue, and the calling of the IRQ bottom-half handler.
+ *
+ * @param arg resource-specific data
+ */
+typedef void (*_mali_osk_irq_bhandler_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.
+ *
+ * Even though the structure has space for a u32, the counters will only
+ * represent signed 24-bit integers.
+ *
+ * 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 flags type
+ *
+ * Flags are supplied at the point where the Lock is initialized. Each flag can
+ * be combined with others using bitwise OR, '|'.
+ *
+ * The flags must be sufficiently rich to cope with all our OSs. This means
+ * that on some OSs, certain flags can be completely ignored. We define a
+ * number of terms that are significant across all OSs:
+ *
+ * - Sleeping/non-sleeping mutexs. Sleeping mutexs can block on waiting, and so
+ * schedule out the current thread. This is significant on OSs where there are
+ * situations in which the current thread must not be put to sleep. On OSs
+ * without this restriction, sleeping and non-sleeping mutexes can be treated
+ * as the same (if that is required).
+ * - Interruptable/non-interruptable mutexes. For sleeping mutexes, it may be
+ * possible for the sleep to be interrupted for a reason other than the thread
+ * being able to obtain the lock. OSs behaving in this way may provide a
+ * mechanism to control whether sleeping mutexes can be interrupted. On OSs
+ * that do not support the concept of interruption, \b or they do not support
+ * control of mutex interruption, then interruptable mutexes may be treated
+ * as non-interruptable.
+ *
+ * Some constrains apply to the lock type flags:
+ *
+ * - Spinlocks are by nature, non-interruptable. Hence, they must always be
+ * combined with the NONINTERRUPTABLE flag, because it is meaningless to ask
+ * for a spinlock that is interruptable (and this highlights its
+ * non-interruptable-ness). For example, on certain OSs they should be used when
+ * you must not sleep.
+ * - Reader/writer is an optimization hint, and any type of lock can be
+ * reader/writer. Since this is an optimization hint, the implementation need
+ * not respect this for any/all types of lock. For example, on certain OSs,
+ * there's no interruptable reader/writer mutex. If such a thing were requested
+ * on that OS, the fact that interruptable was requested takes priority over the
+ * reader/writer-ness, because reader/writer-ness is not necessary for correct
+ * operation.
+ * - Any lock can use the order parameter.
+ * - A onelock is an optimization hint specific to certain OSs. It can be
+ * specified when it is known that only one lock will be held by the thread,
+ * and so can provide faster mutual exclusion. This can be safely ignored if
+ * such optimization is not required/present.
+ *
+ * The absence of any flags (the value 0) results in a sleeping-mutex, which is interruptable.
+ */
+typedef enum
+{
+ _MALI_OSK_LOCKFLAG_SPINLOCK = 0x1, /**< Specifically, don't sleep on those architectures that require it */
+ _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE = 0x2, /**< The mutex cannot be interrupted, e.g. delivery of signals on those architectures where this is required */
+ _MALI_OSK_LOCKFLAG_READERWRITER = 0x4, /**< Optimise for readers/writers */
+ _MALI_OSK_LOCKFLAG_ORDERED = 0x8, /**< Use the order parameter; otherwise use automatic ordering */
+ _MALI_OSK_LOCKFLAG_ONELOCK = 0x10, /**< Each thread can only hold one lock at a time */
+ _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ = 0x20, /**< IRQ version of spinlock */
+ /** @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 specified
+ * as _MALI_OSK_LOCKFLAG_READERWRITER. 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
+ * _MALI_OSK_LOCKFLAG_READERWRITER is not supplied.
+ *
+ */
+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 type for Mutual Exclusion lock objects */
+typedef struct _mali_osk_lock_t_struct _mali_osk_lock_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_irq_schedulework() to make use of the IRQ 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;
+
+/** @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 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) ))
+
+/** @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))
+/** @} */ /* end group _mali_osk_list */
+
+
+/** @addtogroup _mali_osk_miscellaneous
+ * @{ */
+
+/** @brief The known resource types
+ *
+ * @note \b IMPORTANT: these must remain fixed, and only be extended. This is
+ * because not all systems use a header file for reading in their resources.
+ * The resources may instead come from a data file where these resources are
+ * 'hard-coded' in, because there's no easy way of transferring the enum values
+ * into such data files. E.g. the C-Pre-processor does \em not process enums.
+ */
+typedef enum _mali_osk_resource_type
+{
+ RESOURCE_TYPE_FIRST =0, /**< Duplicate resource marker for the first resource*/
+ MEMORY =0, /**< Physically contiguous memory block, not managed by the OS */
+ OS_MEMORY =1, /**< Memory managed by and shared with the OS */
+ MALI200 =3, /**< Mali200 Programmable Fragment Shader */
+ MALIGP2 =4, /**< MaliGP2 Programmable Vertex Shader */
+ MMU =5, /**< Mali MMU (Memory Management Unit) */
+ FPGA_FRAMEWORK =6, /**< Mali registers specific to FPGA implementations */
+ MALI400L2 =7, /**< Mali400 L2 Cache */
+ MALI300L2 =7, /**< Mali300 L2 Cache */
+ MALI400GP =8, /**< Mali400 Programmable Vertex Shader Core */
+ MALI300GP =8, /**< Mali300 Programmable Vertex Shader Core */
+ MALI400PP =9, /**< Mali400 Programmable Fragment Shader Core */
+ MALI300PP =9, /**< Mali300 Programmable Fragment Shader Core */
+ MEM_VALIDATION =10, /**< External Memory Validator */
+ PMU =11, /**< Power Manangement Unit */
+ RESOURCE_TYPE_COUNT /**< The total number of known resources */
+} _mali_osk_resource_type_t;
+
+/** @brief resource description struct
+ *
+ * _mali_osk_resources_init() will enumerate objects of this type. Not all
+ * members have a valid meaning across all types.
+ *
+ * The mmu_id is used to group resources to a certain MMU, since there may be
+ * more than one MMU in the system, and each resource may be using a different
+ * MMU:
+ * - For MMU resources, the setting of mmu_id is a uniquely identifying number.
+ * - For Other resources, the setting of mmu_id determines which MMU the
+ * resource uses.
+ */
+typedef struct _mali_osk_resource
+{
+ _mali_osk_resource_type_t type; /**< type of the resource */
+ const char * description; /**< short description of the resource */
+ u32 base; /**< Physical base address of the resource, as seen by Mali resources. */
+ s32 cpu_usage_adjust; /**< Offset added to the base address of the resource to arrive at the CPU physical address of the resource (if different from the Mali physical address) */
+ u32 size; /**< Size in bytes of the resource - either the size of its register range, or the size of the memory block. */
+ u32 irq; /**< IRQ number delivered to the CPU, or -1 to tell the driver to probe for it (if possible) */
+ u32 flags; /**< Resources-specific flags. */
+ u32 mmu_id; /**< Identifier for Mali MMU resources. */
+ u32 alloc_order; /**< Order in which MEMORY/OS_MEMORY resources are used */
+} _mali_osk_resource_t;
+/** @} */ /* end group _mali_osk_miscellaneous */
+
+
+#include "mali_kernel_memory_engine.h" /* include for mali_memory_allocation and mali_physical_memory_allocation type */
+
+/** @addtogroup _mali_osk_irq
+ * @{ */
+
+/** @brief Fake IRQ number for testing purposes
+ */
+#define _MALI_OSK_IRQ_NUMBER_FAKE ((u32)0xFFFFFFF1)
+
+/** @addtogroup _mali_osk_irq
+ * @{ */
+
+/** @brief PMM Virtual IRQ number
+ */
+#define _MALI_OSK_IRQ_NUMBER_PMM ((u32)0xFFFFFFF2)
+
+
+/** @brief Initialize IRQ handling for a resource
+ *
+ * The _mali_osk_irq_t returned must be written into the resource-specific data
+ * pointed to by data. This is so that the upper and lower handlers can call
+ * _mali_osk_irq_schedulework().
+ *
+ * @note The caller must ensure that the resource does not generate an
+ * interrupt after _mali_osk_irq_init() finishes, and before the
+ * _mali_osk_irq_t is written into the resource-specific data. Otherwise,
+ * the upper-half handler will fail to call _mali_osk_irq_schedulework().
+ *
+ * @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 upper-half handler, corresponding to a ISR handler for
+ * the resource
+ * @param bhandler The lower-half handler, corresponding to an IST handler for
+ * the resource
+ * @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 data resource-specific data, which will be passed to uhandler,
+ * bhandler and (if present) trigger_func and ack_funnc
+ * @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, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description );
+
+/** @brief Cause a queued, deferred call of the IRQ bottom-half.
+ *
+ * _mali_osk_irq_schedulework provides a mechanism for enqueuing deferred calls
+ * to the IRQ bottom-half handler. The queue is known as the IRQ work-queue.
+ * After calling _mali_osk_irq_schedulework(), the IRQ bottom-half handler will
+ * be scheduled to run at some point in the future.
+ *
+ * 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_irq_schedulework() 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_irq_schedulework() is guaranteed to not block on:
+ * - enqueuing a deferred call request.
+ * - the completion of the IRQ bottom-half handler.
+ *
+ * This is to prevent deadlock. For example, if _mali_osk_irq_schedulework()
+ * blocked, then it would cause a deadlock when the following two conditions
+ * hold:
+ * - The IRQ bottom-half callback (of type _mali_osk_irq_bhandler_t) locks
+ * a mutex
+ * - And, at the same time, the caller of _mali_osk_irq_schedulework() also
+ * holds the same mutex
+ *
+ * @note care must be taken to not overflow the queue that
+ * _mali_osk_irq_schedulework() operates on. Code must be structured to
+ * ensure that the number of requests made to the queue is bounded. Otherwise,
+ * IRQs will be lost.
+ *
+ * The queue that _mali_osk_irq_schedulework implements is a FIFO of N-writer,
+ * 1-reader type. The writers are the callers of _mali_osk_irq_schedulework
+ * (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 IRQs.
+ *
+ * The consequence of the queue being a 1-reader type is that calling
+ * _mali_osk_irq_schedulework() on different _mali_osk_irq_t objects causes
+ * their IRQ bottom-halves to be serialized, across all CPU-cores in the
+ * system.
+ *
+ * @param irq a pointer to the _mali_osk_irq_t object corresponding to the
+ * resource whose IRQ bottom-half must begin processing.
+ */
+void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq );
+
+/** @brief Terminate IRQ handling on a resource.
+ *
+ * This will disable the interrupt from the device, and then waits for the
+ * IRQ work-queue to finish the work that is currently in the queue. That is,
+ * for every deferred call currently in the IRQ work-queue, it waits for each
+ * of those to be processed by their respective IRQ bottom-half handler.
+ *
+ * This function is used to ensure that the bottom-half handler of the supplied
+ * IRQ object will not be running at the completion of this function call.
+ * However, the caller must ensure that no other sources could call the
+ * _mali_osk_irq_schedulework() on the same IRQ object. For example, the
+ * relevant timers must be stopped.
+ *
+ * @note While this function is being called, other OSK-registered IRQs in the
+ * system may enqueue work for their respective bottom-half handlers. This
+ * function will not wait for those entries in the work-queue to be flushed.
+ *
+ * Since this blocks on the completion of work in the IRQ work-queue, the
+ * caller of this function \b must \b not hold any mutexes that are taken by
+ * any OSK-registered IRQ bottom-half handler. To do so may cause a deadlock.
+ *
+ * @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 );
+
+/** @brief flushing workqueue.
+ *
+ * This will flush the workqueue.
+ *
+ * @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_flush_workqueue( _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
+ *
+ * Although the value returned is a u32, only numbers with signed 24-bit
+ * precision (sign extended to u32) are returned.
+ *
+ * @note It is an error to decrement the counter beyond -(1<<23)
+ *
+ * @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
+ *
+ * Although the value returned is a u32, only numbers with signed 24-bit
+ * precision (sign extended to u32) are returned.
+ *
+ * @note It is an error to increment the counter beyond (1<<23)-1
+ *
+ * @param atom pointer to an atomic counter */
+u32 _mali_osk_atomic_inc_return( _mali_osk_atomic_t *atom );
+
+/** @brief Initialize an atomic counter
+ *
+ * The counters have storage for signed 24-bit integers. Initializing to signed
+ * values requiring more than 24-bits storage will fail.
+ *
+ * @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
+ *
+ * Although the value returned is a u32, only numbers with signed 24-bit
+ * precision (sign extended to u32) are returned.
+ *
+ * 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 );
+/** @} */ /* 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_lock
+ * @{ */
+
+/** @brief Initialize a Mutual Exclusion Lock
+ *
+ * Locks are created in the signalled (unlocked) state.
+ *
+ * initial must be zero, since there is currently no means of expressing
+ * whether a reader/writer lock should be initially locked as a reader or
+ * writer. This would require some encoding to be used.
+ *
+ * 'Automatic' ordering means that locks must be obtained in the order that
+ * they were created. For all locks that can be held at the same time, they must
+ * either all provide the order parameter, or they all must use 'automatic'
+ * ordering - because there is no way of mixing 'automatic' and 'manual'
+ * ordering.
+ *
+ * @param flags flags combined with bitwise OR ('|'), or zero. There are
+ * restrictions on which flags can be combined, @see _mali_osk_lock_flags_t.
+ * @param initial For future expansion into semaphores. SBZ.
+ * @param order The locking order of the mutex. That is, locks obtained by the
+ * same thread must have been created with an increasing order parameter, for
+ * deadlock prevention. Setting to zero causes 'automatic' ordering to be used.
+ * @return On success, a pointer to a _mali_osk_lock_t object. NULL on failure.
+ */
+_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_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.
+ *
+ * In the case of Reader/Writer locks, multiple readers can obtain a lock in
+ * the absence of writers, which is a performance optimization (providing that
+ * the readers never write to the protected resource).
+ *
+ * To prevent deadlock, locks must always be obtained in the same order.
+ *
+ * For locks marked as _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, it is a
+ * programming error for the function to exit without obtaining the lock. This
+ * means that the error code must only be checked for interruptible locks.
+ *
+ * @param lock the lock to wait upon (obtain).
+ * @param mode the mode in which the lock should be obtained. Unless the lock
+ * was created with _MALI_OSK_LOCKFLAG_READERWRITER, this must be
+ * _MALI_OSK_LOCKMODE_RW.
+ * @return On success, _MALI_OSK_ERR_OK. For interruptible locks, a suitable
+ * _mali_osk_errcode_t will be returned on failure, and the lock will not be
+ * obtained. In this case, the error code must be propagated up to the U/K
+ * interface.
+ */
+_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode);
+
+
+/** @brief Signal (release) a lock
+ *
+ * Locks may only be signalled by the thread that originally waited upon the
+ * lock.
+ *
+ * @note In the OSU, a flag exists to allow any thread to signal a
+ * lock. Such functionality is not present in the OSK.
+ *
+ * @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 _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_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 _mali_osk_lock_term( _mali_osk_lock_t *lock );
+/** @} */ /* end group _mali_osk_lock */
+
+
+/** @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 );
+
+#if MALI_STATE_TRACKING
+/** @brief Receive a notification from a queue
+ *
+ * Check if a notification queue is empty.
+ *
+ * @param queue The queue to check.
+ * @return MALI_TRUE if queue is empty, otherwise MALI_FALSE.
+ */
+mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue );
+#endif
+
+/** @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 absolute time at which a timer will expire, and start it if it is
+ * stopped. If \a expiry_tick is in the past (determined by
+ * _mali_osk_time_after() ), 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 absolute time \a expiry_tick, 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 expiry_tick the \em absolute time in ticks at which this timer should
+ * trigger.
+ *
+ */
+void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick);
+
+/** @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 IRQ work-queue by the timer (with
+ * \ref _mali_osk_irq_schedulework()) may still run. The timer callback and IRQ
+ * bottom-half 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 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 );
+/** @} */ /* end group _mali_osk_math */
+
+
+/** @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
+ */
+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 Return a handle to the current task.
+ *
+ * @return An OS-specific handle to the current task.
+ */
+void * _mali_osk_get_task(void);
+
+/** @} */ /* end group _mali_osk_miscellaneous */
+
+/** @} */ /* end group osuapi */
+
+/** @} */ /* end group uddapi */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "mali_osk_specific.h" /* include any per-os specifics */
+
+/* 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/mali/common/mali_osk_bitops.h b/drivers/gpu/arm/mali/common/mali_osk_bitops.h
new file mode 100644
index 00000000000..ada1488eef6
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_osk_bitops.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/mali/common/mali_osk_list.h b/drivers/gpu/arm/mali/common/mali_osk_list.h
new file mode 100644
index 00000000000..5987b0a9149
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_osk_list.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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__
+
+#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
+ * @{ */
+
+/** 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 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 int _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 Join two lists
+ *
+ * The list element must be initialized.
+ *
+ * Allows you to join a list into another list at a specific location
+ *
+ * @param list the new list to add
+ * @param at the location in a list to add the new list into
+ */
+MALI_STATIC_INLINE void _mali_osk_list_splice( _mali_osk_list_t *list, _mali_osk_list_t *at )
+{
+ if (!_mali_osk_list_empty(list))
+ {
+ /* insert all items from 'list' after 'at' */
+ _mali_osk_list_t *first = list->next;
+ _mali_osk_list_t *last = list->prev;
+ _mali_osk_list_t *split = at->next;
+
+ first->prev = at;
+ at->next = first;
+
+ last->next = split;
+ split->prev = last;
+ }
+}
+/** @} */ /* end group _mali_osk_list */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_LIST_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_osk_mali.h b/drivers/gpu/arm/mali/common/mali_osk_mali.h
new file mode 100644
index 00000000000..704a436523b
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_osk_mali.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 <mali_osk.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** @addtogroup _mali_osk_miscellaneous
+ * @{ */
+
+/** @brief Initialize the OSK layer
+ *
+ * This function is used to setup any initialization of OSK functionality, if
+ * required.
+ *
+ * This must be the first function called from the common code, specifically,
+ * from the common code entry-point, mali_kernel_constructor.
+ *
+ * The OS-integration into the OS's kernel must handle calling of
+ * mali_kernel_constructor when the device driver is loaded.
+ *
+ * @return _MALI_OSK_ERR_OK on success, or a suitable _mali_osk_errcode_t on
+ * failure.
+ */
+_mali_osk_errcode_t _mali_osk_init( void );
+
+/** @brief Terminate the OSK layer
+ *
+ * This function is used to terminate any resources initialized by
+ * _mali_osk_init.
+ *
+ * This must be the last function called from the common code, specifically,
+ * from the common code closedown function, mali_kernel_destructor, and the
+ * error path in mali_kernel_constructor.
+ *
+ * The OS-integration into the OS's kernel must handle calling of
+ * mali_kernel_destructor when the device driver is terminated.
+ */
+void _mali_osk_term( void );
+
+/** @brief Read the Mali Resource configuration
+ *
+ * Populates a _mali_arch_resource_t array from configuration settings, which
+ * are stored in an OS-specific way.
+ *
+ * For example, these may be compiled in to a static structure, or read from
+ * the filesystem at startup.
+ *
+ * On failure, do not call _mali_osk_resources_term.
+ *
+ * @param arch_config a pointer to the store the pointer to the resources
+ * @param num_resources the number of resources read
+ * @return _MALI_OSK_ERR_OK on success. _MALI_OSK_ERR_NOMEM on allocation
+ * error. For other failures, a suitable _mali_osk_errcode_t is returned.
+ */
+_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources );
+
+/** @brief Free resources allocated by _mali_osk_resources_init.
+ *
+ * Frees the _mali_arch_resource_t array allocated by _mali_osk_resources_init
+ *
+ * @param arch_config a pointer to the stored the pointer to the resources
+ * @param num_resources the number of resources in the array
+ */
+void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources);
+/** @} */ /* end group _mali_osk_miscellaneous */
+
+/** @addtogroup _mali_osk_low_level_memory
+ * @{ */
+
+/** @brief Initialize a user-space accessible memory range
+ *
+ * This initializes a virtual address range such that it is reserved for the
+ * current process, but does not map any physical pages into this range.
+ *
+ * This function may initialize or adjust any members of the
+ * mali_memory_allocation \a descriptor supplied, before the physical pages are
+ * mapped in with _mali_osk_mem_mapregion_map().
+ *
+ * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE
+ * set in \a descriptor->flags. It is an error to call this function without
+ * setting this flag. Otherwise, \a descriptor->flags bits are reserved for
+ * future expansion
+ *
+ * The \a descriptor's process_addr_mapping_info member can be modified to
+ * allocate OS-specific information. Note that on input, this will be a
+ * ukk_private word from the U/K inteface, as inserted by _mali_ukk_mem_mmap().
+ * This is used to pass information from the U/K interface to the OSK interface,
+ * if necessary. The precise usage of the process_addr_mapping_info member
+ * depends on the U/K implementation of _mali_ukk_mem_mmap().
+ *
+ * Therefore, the U/K implementation of _mali_ukk_mem_mmap() and the OSK
+ * implementation of _mali_osk_mem_mapregion_init() must agree on the meaning and
+ * usage of the ukk_private word and process_addr_mapping_info member.
+ *
+ * Refer to \ref u_k_api for more information on the U/K interface.
+ *
+ * On successful return, \a descriptor's mapping member will be correct for
+ * use with _mali_osk_mem_mapregion_term() and _mali_osk_mem_mapregion_map().
+ *
+ * @param descriptor the mali_memory_allocation to initialize.
+ */
+_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor );
+
+/** @brief Terminate a user-space accessible memory range
+ *
+ * This terminates a virtual address range reserved in the current user process,
+ * where none, some or all of the virtual address ranges have mappings to
+ * physical pages.
+ *
+ * It will unmap any physical pages that had been mapped into a reserved
+ * virtual address range for the current process, and then releases the virtual
+ * address range. Any extra book-keeping information or resources allocated
+ * during _mali_osk_mem_mapregion_init() will also be released.
+ *
+ * The \a descriptor itself is not freed - this must be handled by the caller of
+ * _mali_osk_mem_mapregion_term().
+ *
+ * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE
+ * set in descriptor->flags. It is an error to call this function without
+ * setting this flag. Otherwise, descriptor->flags bits are reserved for
+ * future expansion
+ *
+ * @param descriptor the mali_memory_allocation to terminate.
+ */
+void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor );
+
+/** @brief Map physical pages into a user process's virtual address range
+ *
+ * This is used to map a number of physically contigous pages into a
+ * user-process's virtual address range, which was previously reserved by a
+ * call to _mali_osk_mem_mapregion_init().
+ *
+ * This need not provide a mapping for the entire virtual address range
+ * reserved for \a descriptor - it may be used to map single pages per call.
+ *
+ * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE
+ * set in \a descriptor->flags. It is an error to call this function without
+ * setting this flag. Otherwise, \a descriptor->flags bits are reserved for
+ * future expansion
+ *
+ * The function may supply \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC.
+ * In this case, \a size must be set to \ref _MALI_OSK_CPU_PAGE_SIZE, and the function
+ * will allocate the physical page itself. The physical address of the
+ * allocated page will be returned through \a phys_addr.
+ *
+ * It is an error to set \a size != \ref _MALI_OSK_CPU_PAGE_SIZE while
+ * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC,
+ * since it is not always possible for OSs to support such a setting through this
+ * interface.
+ *
+ * @note \b IMPORTANT: This code must validate the input parameters. If the
+ * range defined by \a offset and \a size is outside the range allocated in
+ * \a descriptor, then this function \b MUST not attempt any mapping, and must
+ * instead return a suitable \ref _mali_osk_errcode_t \b failure code.
+ *
+ * @param[in,out] descriptor the mali_memory_allocation representing the
+ * user-process's virtual address range to map into.
+ *
+ * @param[in] offset the offset into the virtual address range. This is only added
+ * to the mapping member of the \a descriptor, and not the \a phys_addr parameter.
+ * It must be a multiple of \ref _MALI_OSK_CPU_PAGE_SIZE.
+ *
+ * @param[in,out] phys_addr a pointer to the physical base address to begin the
+ * mapping from. If \a size == \ref _MALI_OSK_CPU_PAGE_SIZE and
+ * \a *phys_addr == \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, then this
+ * function will allocate the physical page itself, and return the
+ * physical address of the page through \a phys_addr, which will be aligned to
+ * \ref _MALI_OSK_CPU_PAGE_SIZE. Otherwise, \a *phys_addr must be aligned to
+ * \ref _MALI_OSK_CPU_PAGE_SIZE, and is unmodified after the call.
+ * \a phys_addr is unaffected by the \a offset parameter.
+ *
+ * @param[in] size the number of bytes to map in. This must be a multiple of
+ * \ref _MALI_OSK_CPU_PAGE_SIZE.
+ *
+ * @return _MALI_OSK_ERR_OK on sucess, otherwise a _mali_osk_errcode_t value
+ * on failure
+ *
+ * @note could expand to use _mali_osk_mem_mapregion_flags_t instead of
+ * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, but note that we must
+ * also modify the mali process address manager in the mmu/memory engine code.
+ */
+_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size );
+
+
+/** @brief Unmap physical pages from a user process's virtual address range
+ *
+ * This is used to unmap a number of physically contigous pages from a
+ * user-process's virtual address range, which were previously mapped by a
+ * call to _mali_osk_mem_mapregion_map(). If the range specified was allocated
+ * from OS memory, then that memory will be returned to the OS. Whilst pages
+ * will be mapped out, the Virtual address range remains reserved, and at the
+ * same base address.
+ *
+ * When this function is used to unmap pages from OS memory
+ * (_mali_osk_mem_mapregion_map() was called with *phys_addr ==
+ * \ref MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC), then the \a flags must
+ * include \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR. This is because
+ * it is not always easy for an OS implementation to discover whether the
+ * memory was OS allocated or not (and so, how it should release the memory).
+ *
+ * For this reason, only a range of pages of the same allocation type (all OS
+ * allocated, or none OS allocacted) may be unmapped in one call. Multiple
+ * calls must be made if allocations of these different types exist across the
+ * entire region described by the \a descriptor.
+ *
+ * The function will always be called with MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE
+ * set in \a descriptor->flags. It is an error to call this function without
+ * setting this flag. Otherwise, \a descriptor->flags bits are reserved for
+ * future expansion
+ *
+ * @param[in,out] descriptor the mali_memory_allocation representing the
+ * user-process's virtual address range to map into.
+ *
+ * @param[in] offset the offset into the virtual address range. This is only added
+ * to the mapping member of the \a descriptor. \a offset must be a multiple of
+ * \ref _MALI_OSK_CPU_PAGE_SIZE.
+ *
+ * @param[in] size the number of bytes to unmap. This must be a multiple of
+ * \ref _MALI_OSK_CPU_PAGE_SIZE.
+ *
+ * @param[in] flags specifies how the memory should be unmapped. For a range
+ * of pages that were originally OS allocated, this must have
+ * \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR set.
+ */
+void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags );
+/** @} */ /* end group _mali_osk_low_level_memory */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_MALI_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_osk_profiling.h b/drivers/gpu/arm/mali/common/mali_osk_profiling.h
new file mode 100644
index 00000000000..8c41b0a9fa8
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_osk_profiling.h
@@ -0,0 +1,181 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms of
+ * such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_OSK_PROFILING_H__
+#define __MALI_OSK_PROFILING_H__
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+
+#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#include "mali_linux_trace.h"
+#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */
+
+#include "mali_cinstr_profiling_events_m200.h"
+
+#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576
+
+#define MALI_PROFILING_PP_CORE_COUNTER0_OFFSET(core_number) (((core_number) * 2) + COUNTER_FP0_C0)
+#define MALI_PROFILING_PP_CORE_COUNTER1_OFFSET(core_number) (((core_number) * 2) + COUNTER_FP0_C1)
+
+/** @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.
+ */
+#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+/*
+ * On platforms where we are using Linux tracepoints and we aren't forcing
+ * internal profiling we can call through to the tracepoint directly and
+ * avoid the overhead of the function call.
+ */
+#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) \
+ trace_mali_timeline_event((event_id), (data0), (data1), (u32)_mali_osk_get_task(), (data3), (data4))
+#else
+void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4);
+#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */
+
+/**
+ * Report a hardware counter event.
+ *
+ * @param counter_id The ID of the counter.
+ * @param value The value of the counter.
+ */
+#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+/*
+ * On platforms where we are using Linux tracepoints and we aren't forcing
+ * internal profiling we can call through to the tracepoint directly and
+ * avoid the overhead of the function call.
+ */
+#define _mali_osk_profiling_report_hw_counter trace_mali_hw_counter
+#else
+void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value);
+#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */
+
+/**
+ * Query a hardware counter. Given a counter ID, check which event the
+ * counter should report and update the given pointer with that event
+ * number before returning MALI_TRUE. If the counter has been disabled
+ * by the profiling tool, returns MALI_FALSE and does not update the
+ * pointer.
+ *
+ * MALI_FALSE is also returned if the counter is not a valid hardware
+ * counter ID. In this case the event value is not updated.
+ *
+ * @param counter_id The counter ID.
+ * @param event_id A pointer to a u32 value that will be updated with
+ * the event ID that should be counted, should the counter have been
+ * enabled by the profiling tool.
+ *
+ * @return MALI_TRUE if the counter should be enabled, MALI_FALSE otherwise.
+ */
+mali_bool _mali_osk_profiling_query_hw_counter(u32 counter_id, u32 *event_id);
+
+/**
+ * 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);
+
+/**
+ * Enable or disable profiling events as default for new sessions (applications)
+ *
+ * @param enable MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE
+ */
+void _mali_osk_profiling_set_default_enable_state(mali_bool enable);
+
+/**
+ * Get current default enable state for new sessions (applications)
+ *
+ * @return MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE
+ */
+mali_bool _mali_osk_profiling_get_default_enable_state(void);
+
+/** @} */ /* end group _mali_osk_profiling */
+
+#endif /* MALI_TIMELINE_PROFILING_ENABLED */
+
+#endif /* __MALI_OSK_PROFILING_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_uk_types.h b/drivers/gpu/arm/mali/common/mali_uk_types.h
new file mode 100644
index 00000000000..85bb82d0a90
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_uk_types.h
@@ -0,0 +1,1167 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_uk_types.h
+ * Defines the types and constants used in the user-kernel interface
+ */
+
+#ifndef __MALI_UK_TYPES_H__
+#define __MALI_UK_TYPES_H__
+
+/*
+ * NOTE: Because this file can be included from user-side and kernel-side,
+ * it is up to the includee to ensure certain typedefs (e.g. u32) are already
+ * defined when #including this.
+ */
+#include "regs/mali_200_regs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @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_GET_SYSTEM_INFO_SIZE, /**< _mali_ukk_get_system_info_size() */
+ _MALI_UK_GET_SYSTEM_INFO, /**< _mali_ukk_get_system_info() */
+ _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() */
+
+ /** 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_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() */
+
+ /** Common functions for each core */
+
+ _MALI_UK_START_JOB = 0, /**< Start a Fragment/Vertex Processor Job on a core */
+ _MALI_UK_ABORT_JOB, /**< Abort a job */
+ _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_PP_ABORT_JOB = _MALI_UK_ABORT_JOB, /**< _mali_ukk_pp_abort_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() */
+
+ /** Vertex Processor Functions */
+
+ _MALI_UK_GP_START_JOB = _MALI_UK_START_JOB, /**< _mali_ukk_gp_start_job() */
+ _MALI_UK_GP_ABORT_JOB = _MALI_UK_ABORT_JOB, /**< _mali_ukk_gp_abort_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() */
+
+#if USING_MALI_PMM
+ /** Power Management Module Functions */
+ _MALI_UK_PMM_EVENT_MESSAGE = 0, /**< Raise an event message */
+#endif
+
+ /** 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 Information about each Mali Core
+ *
+ * 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()
+ *
+ * Both Fragment Processor (PP) and Vertex Processor (GP) cores are represented
+ * by this struct.
+ *
+ * The type is reported by the type field, _mali_core_info::_mali_core_type.
+ *
+ * Each core is given a unique Sequence number identifying it, the core_nr
+ * member.
+ *
+ * Flags are taken directly from the resource's flags, and are currently unused.
+ *
+ * Multiple mali_core_info structs are linked in a single linked list using the next field
+ */
+typedef struct _mali_core_info
+{
+ _mali_core_type type; /**< Type of core */
+ _mali_core_version version; /**< Core Version, as reported by the Core's Version Register */
+ u32 reg_address; /**< Address of Registers */
+ u32 core_nr; /**< Sequence number */
+ u32 flags; /**< Flags. Currently Unused. */
+ struct _mali_core_info * next; /**< Next core in Linked List */
+} _mali_core_info;
+
+/** @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_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;
+
+/** @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.
+ *
+ * Each bank is uniquely identified by its identifier member. On Mali-nonMMU
+ * systems, to allocate from this bank, the value of identifier must be passed
+ * as the type_id member of the _mali_uk_get_big_block_s arguments to
+ * _mali_ukk_get_big_block.
+ *
+ * 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; /**< Unique identifier, to be used in allocate calls */
+ struct _mali_mem_info * next; /**< Next List Link */
+} _mali_mem_info;
+
+/** @brief Info about the whole Mali system.
+ *
+ * This Contains a linked list of the cores and memory banks available. Each
+ * list pointer will remain inside the system_info buffer supplied in the
+ * _mali_uk_get_system_info_s arguments to a _mali_ukk_get_system_info call.
+ *
+ * The has_mmu member must be inspected to ensure the correct group of
+ * Memory function calls is obtained - that is, those for either Mali-MMU
+ * or Mali-nonMMU. @see _mali_uk_memory
+ */
+typedef struct _mali_system_info
+{
+ _mali_core_info * core_info; /**< List of _mali_core_info structures */
+ _mali_mem_info * mem_info; /**< List of _mali_mem_info structures */
+ u32 has_mmu; /**< Non-zero if Mali-MMU present. Zero otherwise. */
+ _mali_driver_mode drivermode; /**< Reserved. Must always be _MALI_DRIVER_MODE_NORMAL */
+} _mali_system_info;
+
+/** @brief Arguments to _mali_ukk_get_system_info()
+ *
+ * A buffer of the size returned by _mali_ukk_get_system_info_size() must be
+ * allocated, and the pointer to this buffer must be written into the
+ * system_info member. The buffer must be suitably aligned for storage of
+ * the _mali_system_info structure - for example, one returned by
+ * _mali_osk_malloc(), which will be suitably aligned for any structure.
+ *
+ * The ukk_private member must be set to zero by the user-side. Under an OS
+ * implementation, the U/K interface must write in the user-side base address
+ * into the ukk_private member, so that the common code in
+ * _mali_ukk_get_system_info() can determine how to adjust the pointers such
+ * that they are sensible from user space. Leaving ukk_private as NULL implies
+ * that no pointer adjustment is necessary - which will be the case on a
+ * bare-metal/RTOS system.
+ *
+ * @see _mali_system_info
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 size; /**< [in] size of buffer provided to store system information data */
+ _mali_system_info * system_info; /**< [in,out] pointer to buffer to store system information data. No initialisation of buffer required on input. */
+ u32 ukk_private; /**< [in] Kernel-side private word inserted by certain U/K interface implementations. Caller must set to Zero. */
+} _mali_uk_get_system_info_s;
+/** @} */ /* end group _mali_uk_getsysteminfo */
+
+/** @} */ /* 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_STARTED_LOW_PRI_JOB_RETURNED, /**< Job started and bumped a lower priority job that was pending execution */
+ _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 starting a Vertex or Fragment processor job */
+typedef enum
+{
+ MALI_UK_START_JOB_FLAG_DEFAULT = 0, /**< Default behaviour; Flush L2 caches before start, no following jobs */
+ MALI_UK_START_JOB_FLAG_NO_FLUSH = 1, /**< No need to flush L2 caches before start */
+ MALI_UK_START_JOB_FLAG_MORE_JOBS_FOLLOW = 2, /**< More related jobs follows, try to schedule them as soon as possible after this job */
+} _mali_uk_start_job_flags;
+
+/** @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. If the job had a higher priority than the one currently pending
+ * execution (@c _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED), it will bump
+ * the lower priority job and returns the address of the @c mali_gp_job_info
+ * for that job in @c returned_user_job_ptr. That job should get requeued.
+ *
+ * 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 watchdog_msecs; /**< [in] maximum allowed runtime in milliseconds. The job gets killed if it runs longer than this. A value of 0 selects the default used by the device driver. */
+ 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 returned_user_job_ptr; /**< [out] identifier for the returned job in user space, a @c mali_gp_job_info* */
+ _mali_uk_start_job_status status; /**< [out] indicates job start status (success, previous job returned, requeue) */
+ u32 abort_id; /**< [in] abort id of this job, used to identify this job for later abort requests */
+ u32 perf_counter_l2_src0; /**< [in] soruce id for Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_src1; /**< [in] source id for Mali-400 MP L2 cache performance counter 1 */
+ u32 frame_builder_id; /**< [in] id of the originating frame builder */
+ u32 flush_id; /**< [in] flush id within the originating frame builder */
+} _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_L2_SRC0_ENABLE (1<<2) /**< Enable performance counter L2_SRC0 for a job */
+#define _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE (1<<3) /**< Enable performance counter L2_SRC1 for a job */
+#define _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET (1<<4) /**< Enable performance counter L2_RESET for a job */
+
+/** @} */ /* 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 irq_status; /**< [out] value of the GP interrupt rawstat register (see ARM DDI0415A) */
+ u32 status_reg_on_stop; /**< [out] value of the GP control register */
+ u32 vscl_stop_addr; /**< [out] value of the GP VLSCL start register */
+ u32 plbcl_stop_addr; /**< [out] value of the GP PLBCL start register */
+ u32 heap_current_addr; /**< [out] value of the GP PLB PL heap start address register */
+ u32 perf_counter_src0; /**< [out] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter_src1; /**< [out] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */
+ u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */
+ u32 render_time; /**< [out] number of microseconds it took for the job to render */
+ u32 perf_counter_l2_src0; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_src1; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 1 */
+ u32 perf_counter_l2_val0; /**< [out] Value of the Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_val1; /**< [out] Value of the Mali-400 MP L2 cache performance counter 1 */
+} _mali_uk_gp_job_finished_s;
+
+typedef enum _maligp_job_suspended_reason
+{
+ _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY /**< Polygon list builder unit (PLBU) has run out of memory */
+} _maligp_job_suspended_reason;
+
+typedef struct
+{
+ u32 user_job_ptr; /**< [out] identifier for the job in user space */
+ _maligp_job_suspended_reason reason; /**< [out] reason why the job stalled */
+ 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
+ * @{ */
+
+/** @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. If the job had a higher priority than the one currently pending
+ * execution (@c _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED), it will bump
+ * the lower priority job and returns the address of the @c mali_pp_job
+ * for that job in @c returned_user_job_ptr. That job should get requeued.
+ *
+ * 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 watchdog_msecs; /**< [in] maximum allowed runtime in milliseconds. The job gets killed if it runs longer than this. A value of 0 selects the default used by the device driver. */
+ u32 frame_registers[MALI200_NUM_REGS_FRAME]; /**< [in] core specific registers associated with this job, see ARM DDI0415A */
+ u32 wb0_registers[MALI200_NUM_REGS_WBx];
+ u32 wb1_registers[MALI200_NUM_REGS_WBx];
+ u32 wb2_registers[MALI200_NUM_REGS_WBx];
+ 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 returned_user_job_ptr; /**< [out] identifier for the returned job in user space */
+ _mali_uk_start_job_status status; /**< [out] indicates job start status (success, previous job returned, requeue) */
+ u32 abort_id; /**< [in] abort id of this job, used to identify this job for later abort requests */
+ u32 perf_counter_l2_src0; /**< [in] soruce id for Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_src1; /**< [in] source id for Mali-400 MP L2 cache performance counter 1 */
+ u32 frame_builder_id; /**< [in] id of the originating frame builder */
+ u32 flush_id; /**< [in] flush id within the originating frame builder */
+ _mali_uk_start_job_flags flags; /**< [in] Flags for job, see _mali_uk_start_job_flags for more information */
+} _mali_uk_pp_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 irq_status; /**< [out] value of interrupt rawstat register (see ARM DDI0415A) */
+ u32 last_tile_list_addr; /**< [out] value of renderer list register (see ARM DDI0415A); necessary to restart a stopped job */
+ u32 perf_counter_src0; /**< [out] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter_src1; /**< [out] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter0; /**< [out] value of perfomance counter 0 (see ARM DDI0415A) */
+ u32 perf_counter1; /**< [out] value of perfomance counter 1 (see ARM DDI0415A) */
+ u32 render_time; /**< [out] number of microseconds it took for the job to render */
+ u32 perf_counter_l2_src0; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_src1; /**< [out] soruce id for Mali-400 MP L2 cache performance counter 1 */
+ u32 perf_counter_l2_val0; /**< [out] Value of the Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_val1; /**< [out] Value of the Mali-400 MP L2 cache performance counter 1 */
+ u32 perf_counter_l2_val0_raw; /**< [out] Raw value of the Mali-400 MP L2 cache performance counter 0 */
+ u32 perf_counter_l2_val1_raw; /**< [out] Raw value of the Mali-400 MP L2 cache performance counter 1 */
+} _mali_uk_pp_job_finished_s;
+/** @} */ /* end group _mali_uk_pp */
+
+
+/** @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,
+
+ /** Fragment Processor notifications */
+
+ _MALI_NOTIFICATION_PP_FINISHED = (_MALI_UK_PP_SUBSYSTEM << 16) | 0x10,
+
+ /** 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 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 */
+ } 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))))
+
+/**
+ * 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 10
+#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 */
+
+/** @} */ /* end group _mali_uk_core */
+
+
+/** @defgroup _mali_uk_memory U/K Memory
+ * @{ */
+
+/** @brief Arguments for _mali_ukk_init_mem(). */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 mali_address_base; /**< [out] start of MALI address space */
+ u32 memory_size; /**< [out] total MALI address space available */
+} _mali_uk_init_mem_s;
+
+/** @brief Arguments for _mali_ukk_term_mem(). */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+} _mali_uk_term_mem_s;
+
+/** @brief Arguments for _mali_ukk_get_big_block()
+ *
+ * - type_id should be set to the value of the identifier member of one of the
+ * _mali_mem_info structures returned through _mali_ukk_get_system_info()
+ * - ukk_private must be zero when calling from user-side. 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. Specifically, ukk_private will be placed
+ * into the ukk_private member of the _mali_uk_mem_mmap_s structure. See
+ * _mali_ukk_mem_mmap() for more details.
+ * - minimum_size_requested will be updated if it is too small
+ * - block_size will always be >= minimum_size_requested, because the underlying
+ * allocation mechanism may only be able to divide up memory regions in certain
+ * ways. To avoid wasting memory, block_size should always be taken into account
+ * rather than assuming minimum_size_requested was really allocated.
+ * - to free the memory, the returned cookie member must be stored, and used to
+ * refer to it.
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 type_id; /**< [in] the type id of the memory bank to allocate memory from */
+ u32 minimum_size_requested; /**< [in,out] minimum size of the allocation */
+ u32 ukk_private; /**< [in] Kernel-side private word inserted by certain U/K interface implementations. Caller must set to Zero. */
+ u32 mali_address; /**< [out] address of the allocation in mali address space */
+ void *cpuptr; /**< [out] address of the allocation in the current process address space */
+ u32 block_size; /**< [out] size of the block that got allocated */
+ u32 flags; /**< [out] flags associated with the allocated block, of type _mali_bus_usage */
+ u32 cookie; /**< [out] identifier for the allocated block in kernel space */
+} _mali_uk_get_big_block_s;
+
+/** @brief Arguments for _mali_ukk_free_big_block()
+ *
+ * All that is required is that the cookie member must be set to the value of
+ * the cookie member returned through _mali_ukk_get_big_block()
+ */
+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_free_big_block_s;
+
+/** @note Mali-MMU only */
+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;
+
+/** Flag for _mali_uk_map_external_mem_s and _mali_uk_attach_ump_mem_s */
+#define _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE (1<<0)
+
+/** @note Mali-MMU only */
+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 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;
+
+/** @note Mali-MMU only; will be supported in future version */
+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;
+
+
+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_cores; /**< [out] number of Fragment Processor cores in the system */
+} _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;
+
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 abort_id; /**< [in] ID of job(s) to abort */
+} _mali_uk_pp_abort_job_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 abort_id; /**< [in] ID of job(s) to abort */
+} _mali_uk_gp_abort_job_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;
+
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 enable_events; /**< [out] 1 if user space process should generate events, 0 if not */
+} _mali_uk_profiling_get_config_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_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 */
+
+#if USING_MALI_PMM
+
+/** @defgroup _mali_uk_pmm U/K Power Management Module
+ * @{ */
+
+/** @brief Power management event message identifiers.
+ *
+ * U/K events start after id 200, and can range up to 999
+ * Adding new events will require updates to the PMM mali_pmm_event_id type
+ */
+#define _MALI_PMM_EVENT_UK_EXAMPLE 201
+
+/** @brief Generic PMM message data type, that will be dependent on the event msg
+ */
+typedef u32 mali_pmm_message_data;
+
+
+/** @brief Arguments to _mali_ukk_pmm_event_message()
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 id; /**< [in] event id */
+ mali_pmm_message_data data; /**< [in] specific data associated with the event */
+} _mali_uk_pmm_message_s;
+
+/** @} */ /* end group _mali_uk_pmm */
+#endif /* USING_MALI_PMM */
+
+/** @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 */
+
+/** @} */ /* end group u_k_api */
+
+/** @} */ /* end group uddapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UK_TYPES_H__ */
diff --git a/drivers/gpu/arm/mali/common/mali_ukk.h b/drivers/gpu/arm/mali/common/mali_ukk.h
new file mode 100644
index 00000000000..e95fa30123a
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/mali_ukk.h
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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
+ * - On OS systems (not including direct function call U/K interface
+ * implementations), _mali_ukk_get_big_block() may succeed, but the subsequent
+ * copying to user space may fail.
+ * - A problem scenario exists: some memory has been reserved by
+ * _mali_ukk_get_big_block(), but the user-mode will be unaware of it (it will
+ * never receive any information about this memory). In this case, the U/K
+ * implementation must do everything necessary to 'rollback' the \em atomic
+ * _mali_ukk_get_big_block() transaction.
+ * - 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 Returns the size of the buffer needed for a _mali_ukk_get_system_info call
+ *
+ * This function must be called before a call is made to
+ * _mali_ukk_get_system_info, so that memory of the correct size can be
+ * allocated, and a pointer to this memory written into the system_info member
+ * of _mali_uk_get_system_info_s.
+ *
+ * @param args see _mali_uk_get_system_info_size_s in "mali_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_system_info_size( _mali_uk_get_system_info_size_s *args );
+
+/** @brief Returns information about the system (cores and memory banks)
+ *
+ * A buffer for this needs to be allocated by the caller. The size of the buffer required is returned by
+ * _mali_ukk_get_system_info_size(). The user is responsible for freeing the buffer.
+ *
+ * The _mali_system_info structure will be written to the start of this buffer,
+ * and the core_info and mem_info lists will be written to locations inside
+ * the buffer, and will be suitably aligned.
+ *
+ * Under OS implementations of the U/K interface we need to pack/unpack
+ * pointers across the user/kernel boundary. This has required that we malloc()
+ * an intermediate buffer inside the kernel-side U/K interface, and free it
+ * before returning to user-side. To avoid modifying common code, we do the
+ * following pseudo-code, which we shall call 'pointer switching':
+ *
+ * @code
+ * {
+ * Copy_From_User(kargs, args, ... );
+ * void __user * local_ptr = kargs->system_info;
+ * kargs->system_info = _mali_osk_malloc( ... );
+ * _mali_ukk_get_system_info( kargs );
+ * Copy_To_User( local_ptr, kargs->system_info, ... );
+ * _mali_osk_free( kargs->system_info );
+ * }
+ * @endcode
+ * @note The user-side's args->system_info members was unmodified here.
+ *
+ * However, the current implementation requires an extra ukk_private word so that the common code can work out
+ * how to patch pointers to user-mode for an OS's U/K implementation, this should be set to the user-space
+ * destination address for pointer-patching to occur. When NULL, it is unused, an no pointer-patching occurs in the
+ * common code.
+ *
+ * @param args see _mali_uk_get_system_info_s in "mali_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_system_info( _mali_uk_get_system_info_s *args );
+
+/** @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_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_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_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 );
+/** @} */ /* 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 Initialize the Mali-MMU Memory system
+ *
+ * For Mali-MMU builds of the drivers, this function must be called before any
+ * other functions in the \ref _mali_uk_memory group are called.
+ *
+ * @note This function is for Mali-MMU builds \b only. It should not be called
+ * when the drivers are built without Mali-MMU support.
+ *
+ * @param args see \ref _mali_uk_init_mem_s in mali_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_init_mem( _mali_uk_init_mem_s *args );
+
+/**
+ * @brief Terminate the MMU Memory system
+ *
+ * For Mali-MMU builds of the drivers, this function must be called when
+ * functions in the \ref _mali_uk_memory group will no longer be called. This
+ * function must be called before the application terminates.
+ *
+ * @note This function is for Mali-MMU builds \b only. It should not be called
+ * when the drivers are built without Mali-MMU support.
+ *
+ * @param args see \ref _mali_uk_term_mem_s in mali_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_term_mem( _mali_uk_term_mem_s *args );
+
+/** @brief Map a block of memory into the current user process
+ *
+ * Allocates a minimum of minimum_size_requested bytes of MALI memory and maps it into the current
+ * process space. The number of bytes allocated is returned in args->block_size.
+ *
+ * This is only used for Mali-nonMMU mode.
+ *
+ * @param args see _mali_uk_get_big_block_s in "mali_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_big_block( _mali_uk_get_big_block_s *args );
+
+/** @brief Unmap a block of memory from the current user process
+ *
+ * Frees allocated MALI memory and unmaps it from the current process space. The previously allocated memory
+ * is indicated by the cookie as returned by _mali_ukk_get_big_block().
+ *
+ * This is only used for Mali-nonMMU mode.
+ *
+ * @param args see _mali_uk_free_big_block_s in "mali_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_free_big_block( _mali_uk_free_big_block_s *args );
+
+/** @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. In Mali-nonMMU mode, the function is callable
+ * from the kernel side, and is used to implement _mali_ukk_get_big_block() in this case.
+ *
+ * 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.
+ *
+ * This means that in the first (nonMMU) case, the caller must manage the physical address allocations. The caller
+ * in this case is _mali_ukk_get_big_block(), which does indeed manage the Mali physical address ranges.
+ *
+ * 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_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_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_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_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 Map a physically contiguous range of memory into Mali
+ * @param args see _mali_uk_map_external_mem_s in mali_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_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 MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+/** @brief Map UMP memory into Mali
+ * @param args see _mali_uk_attach_ump_mem_s in mali_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_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 /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
+
+/** @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_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.
+ *
+ * If an existing lower priority job is returned, args->returned_user_job_ptr contains a
+ * pointer to the returned job and the status field args->status is set to
+ * _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED.
+ *
+ * Job completion can be awaited with _mali_ukk_wait_for_notification().
+ *
+ * @param args see _mali_uk_pp_start_job_s in "mali_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_pp_start_job( _mali_uk_pp_start_job_s *args );
+
+/** @brief Returns the number of Fragment Processors in the system
+ *
+ * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_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_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 Abort any PP jobs with the given ID.
+ *
+ * Jobs internally queued or currently running on the hardware is to be stopped/aborted.
+ * Jobs aborted are reported via the normal job completion system.
+ * Any jobs, running or internally queued should be aborted imediately.
+ * Normal notifiction procedures to report on the status of these jobs.
+ *
+ *
+ * @param args see _malu_uk_pp_abort_job_s in "mali_uk_types.h"
+ */
+void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_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.
+ *
+ * If an existing lower priority job is returned, args->returned_user_job_ptr contains a pointer to
+ * the returned job and the status field args->status is set to
+ * _MALI_UK_START_JOB_STARTED_LOW_PRI_JOB_RETURNED.
+ *
+ * Job completion can be awaited with _mali_ukk_wait_for_notification().
+ *
+ * @param args see _mali_uk_gp_start_job_s in "mali_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_start_job( _mali_uk_gp_start_job_s *args );
+
+/** @brief Returns the number of Vertex Processors in the system.
+ *
+ * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_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_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_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 );
+
+/** @brief Abort any GP jobs with the given ID.
+ *
+ * Jobs internally queued or currently running on the hardware is to be stopped/aborted.
+ * Jobs aborted are reported via the normal job completion system.
+ *
+ * Any jobs, running or internally queued should be aborted imediately.
+ * Normal notifiction procedures to report on the status of these jobs.
+ *
+ * @param args see _mali_uk_gp_abort_job_s in "mali_uk_types.h"
+ */
+void _mali_ukk_gp_abort_job( _mali_uk_gp_abort_job_s *args );
+/** @} */ /* end group _mali_uk_gp */
+
+#if USING_MALI_PMM
+/** @addtogroup _mali_uk_pmm U/K Power Management Module
+ * @{ */
+
+/* @brief Power Management Module event message
+ *
+ * @note The event message can fail to be sent due to OOM but this is
+ * stored in the PMM state machine to be handled later
+ *
+ * @param args see _mali_uk_pmm_event_message_s in "mali_uk_types.h"
+ */
+void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args );
+/** @} */ /* end group _mali_uk_pmm */
+#endif /* USING_MALI_PMM */
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+/** @addtogroup _mali_uk_profiling U/K Timeline profiling module
+ * @{ */
+
+/** @brief Start recording profiling events.
+ *
+ * @param args see _mali_uk_profiling_start_s in "mali_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_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_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_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_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args);
+
+/** @brief Get the profiling config applicable for calling process.
+ *
+ * @param args see _mali_uk_profiling_get_config_s in "mali_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_profiling_get_config(_mali_uk_profiling_get_config_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_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args);
+
+/** @} */ /* end group _mali_uk_vsync */
+
+/** @} */ /* end group u_k_api */
+
+/** @} */ /* end group uddapi */
+
+u32 _mali_ukk_report_memory_usage(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UKK_H__ */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm.c
new file mode 100644
index 00000000000..3c015ba26fe
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm.c
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm.c
+ * Implementation of the power management module for the kernel device driver
+ */
+
+#if USING_MALI_PMM
+
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_subsystem.h"
+
+#include "mali_pmm.h"
+#include "mali_pmm_system.h"
+#include "mali_pmm_state.h"
+#include "mali_pmm_policy.h"
+#include "mali_pmm_pmu.h"
+#include "mali_platform.h"
+
+/* Internal PMM subsystem state */
+static _mali_pmm_internal_state_t *pmm_state = NULL;
+/* Mali kernel subsystem id */
+static mali_kernel_subsystem_identifier mali_subsystem_pmm_id = -1;
+
+#define GET_PMM_STATE_PTR (pmm_state)
+
+/* Internal functions */
+static _mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource);
+static void pmm_event_process( void );
+_mali_osk_errcode_t malipmm_irq_uhandler(void *data);
+void malipmm_irq_bhandler(void *data);
+
+/** @brief Start the PMM subsystem
+ *
+ * @param id Subsystem id to uniquely identify this subsystem
+ * @return _MALI_OSK_ERR_OK if the system started successfully, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t malipmm_kernel_subsystem_start( mali_kernel_subsystem_identifier id );
+
+/** @brief Perform post start up of the PMM subsystem
+ *
+ * Post start up includes initializing the current policy, now that the system is
+ * completely started - to stop policies turning off hardware during the start up
+ *
+ * @param id the unique subsystem id
+ * @return _MALI_OSK_ERR_OK if the post startup was successful, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifier id );
+
+/** @brief Terminate the PMM subsystem
+ *
+ * @param id the unique subsystem id
+ */
+void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id );
+
+#if MALI_STATE_TRACKING
+u32 malipmm_subsystem_dump_state( char *buf, u32 size );
+#endif
+
+
+/* This will be one of the subsystems in the array of subsystems:
+ static struct mali_kernel_subsystem * subsystems[];
+ found in file: mali_kernel_core.c
+*/
+struct mali_kernel_subsystem mali_subsystem_pmm=
+{
+ malipmm_kernel_subsystem_start, /* startup */
+ malipmm_kernel_subsystem_terminate, /* shutdown */
+ malipmm_kernel_load_complete, /* loaded all subsystems */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#if MALI_STATE_TRACKING
+ malipmm_subsystem_dump_state, /* dump_state */
+#endif
+};
+
+#if PMM_OS_TEST
+
+u32 power_test_event = 0;
+mali_bool power_test_flag = MALI_FALSE;
+_mali_osk_timer_t *power_test_timer = NULL;
+
+void _mali_osk_pmm_power_up_done(mali_pmm_message_data data)
+{
+ MALI_PRINT(("POWER TEST OS UP DONE\n"));
+}
+
+void _mali_osk_pmm_power_down_done(mali_pmm_message_data data)
+{
+ MALI_PRINT(("POWER TEST OS DOWN DONE\n"));
+}
+
+/**
+ * Symbian OS Power Up call to the driver
+ */
+void power_test_callback( void *arg )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ power_test_flag = MALI_TRUE;
+ _mali_osk_irq_schedulework( pmm->irq );
+}
+
+void power_test_start()
+{
+ power_test_timer = _mali_osk_timer_init();
+ _mali_osk_timer_setcallback( power_test_timer, power_test_callback, NULL );
+
+ /* First event is power down */
+ power_test_event = MALI_PMM_EVENT_OS_POWER_DOWN;
+ _mali_osk_timer_add( power_test_timer, 10000 );
+}
+
+mali_bool power_test_check()
+{
+ if( power_test_flag )
+ {
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ 0,
+ 1 };
+ event.id = power_test_event;
+
+ power_test_flag = MALI_FALSE;
+
+ /* Send event */
+ _mali_ukk_pmm_event_message( &event );
+
+ /* Switch to next event to test */
+ if( power_test_event == MALI_PMM_EVENT_OS_POWER_DOWN )
+ {
+ power_test_event = MALI_PMM_EVENT_OS_POWER_UP;
+ }
+ else
+ {
+ power_test_event = MALI_PMM_EVENT_OS_POWER_DOWN;
+ }
+ _mali_osk_timer_add( power_test_timer, 5000 );
+
+ return MALI_TRUE;
+ }
+
+ return MALI_FALSE;
+}
+
+void power_test_end()
+{
+ _mali_osk_timer_del( power_test_timer );
+ _mali_osk_timer_term( power_test_timer );
+ power_test_timer = NULL;
+}
+
+#endif
+
+void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ _mali_osk_notification_t *msg;
+ mali_pmm_message_t *event;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ MALIPMM_DEBUG_PRINT( ("PMM: sending message\n") );
+
+#if MALI_PMM_TRACE && MALI_PMM_TRACE_SENT_EVENTS
+ _mali_pmm_trace_event_message( args, MALI_FALSE );
+#endif
+
+ msg = _mali_osk_notification_create( MALI_PMM_NOTIFICATION_TYPE, sizeof( mali_pmm_message_t ) );
+
+ if( msg )
+ {
+ event = (mali_pmm_message_t *)msg->result_buffer;
+ event->id = args->id;
+ event->ts = _mali_osk_time_tickcount();
+ event->data = args->data;
+
+ _mali_osk_atomic_inc( &(pmm->messages_queued) );
+
+ if( args->id > MALI_PMM_EVENT_INTERNALS )
+ {
+ /* Internal PMM message */
+ _mali_osk_notification_queue_send( pmm->iqueue, msg );
+ #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
+ pmm->imessages_sent++;
+ #endif
+ }
+ else
+ {
+ /* Real event */
+ _mali_osk_notification_queue_send( pmm->queue, msg );
+ #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
+ pmm->messages_sent++;
+ #endif
+ }
+ }
+ else
+ {
+ MALI_PRINT_ERROR( ("PMM: Could not send message %d", args->id) );
+ /* Make note of this OOM - which has caused a missed event */
+ pmm->missed++;
+ }
+
+ /* Schedule time to look at the event or the fact we couldn't create an event */
+ _mali_osk_irq_schedulework( pmm->irq );
+}
+
+mali_pmm_state _mali_pmm_state( void )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ if( pmm && (mali_subsystem_pmm_id != -1) )
+ {
+ return pmm->state;
+ }
+
+ /* No working subsystem yet */
+ return MALI_PMM_STATE_UNAVAILABLE;
+}
+
+
+mali_pmm_core_mask _mali_pmm_cores_list( void )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ return pmm->cores_registered;
+}
+
+mali_pmm_core_mask _mali_pmm_cores_powered( void )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ return pmm->cores_powered;
+}
+
+
+_mali_osk_errcode_t _mali_pmm_list_policies(
+ u32 policy_list_size,
+ mali_pmm_policy *policy_list,
+ u32 *policies_available )
+{
+ /* TBD - This is currently a stub function for basic power management */
+
+ MALI_ERROR( _MALI_OSK_ERR_UNSUPPORTED );
+}
+
+_mali_osk_errcode_t _mali_pmm_set_policy( mali_pmm_policy policy )
+{
+ /* TBD - This is currently a stub function for basic power management */
+
+/* TBD - When this is not a stub... include tracing...
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_policy_change( old, newpolicy );
+#endif
+*/
+ MALI_ERROR( _MALI_OSK_ERR_UNSUPPORTED );
+}
+
+_mali_osk_errcode_t _mali_pmm_get_policy( mali_pmm_policy *policy )
+{
+ if( policy )
+ {
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ if( pmm )
+ {
+ *policy = pmm->policy;
+ MALI_SUCCESS;
+ }
+ else
+ {
+ *policy = MALI_PMM_POLICY_NONE;
+ MALI_ERROR( _MALI_OSK_ERR_FAULT );
+ }
+ }
+
+ /* No return argument */
+ MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS );
+}
+
+#if ( MALI_PMM_TRACE || MALI_STATE_TRACKING )
+
+/* Event names - order must match mali_pmm_event_id enum */
+static char *pmm_trace_events[] = {
+ "OS_POWER_UP",
+ "OS_POWER_DOWN",
+ "JOB_SCHEDULED",
+ "JOB_QUEUED",
+ "JOB_FINISHED",
+ "TIMEOUT",
+};
+
+/* State names - order must match mali_pmm_state enum */
+static char *pmm_trace_state[] = {
+ "UNAVAILABLE",
+ "SYSTEM ON",
+ "SYSTEM OFF",
+ "SYSTEM TRANSITION",
+};
+
+/* Policy names - order must match mali_pmm_policy enum */
+static char *pmm_trace_policy[] = {
+ "NONE",
+ "ALWAYS ON",
+ "JOB CONTROL",
+};
+
+/* Status names - order must match mali_pmm_status enum */
+static char *pmm_trace_status[] = {
+ "MALI_PMM_STATUS_IDLE", /**< PMM is waiting next event */
+ "MALI_PMM_STATUS_POLICY_POWER_DOWN", /**< Policy initiated power down */
+ "MALI_PMM_STATUS_POLICY_POWER_UP", /**< Policy initiated power down */
+ "MALI_PMM_STATUS_OS_WAITING", /**< PMM is waiting for OS power up */
+ "MALI_PMM_STATUS_OS_POWER_DOWN", /**< OS initiated power down */
+ "MALI_PMM_STATUS_RUNTIME_IDLE_IN_PROGRESS",
+ "MALI_PMM_STATUS_DVFS_PAUSE", /**< PMM DVFS Status Pause */
+ "MALI_PMM_STATUS_OS_POWER_UP", /**< OS initiated power up */
+ "MALI_PMM_STATUS_OFF", /**< PMM is not active */
+};
+
+#endif /* MALI_PMM_TRACE || MALI_STATE_TRACKING */
+#if MALI_PMM_TRACE
+
+/* UK event names - order must match mali_pmm_event_id enum */
+static char *pmm_trace_events_uk[] = {
+ "UKS",
+ "UK_EXAMPLE",
+};
+
+/* Internal event names - order must match mali_pmm_event_id enum */
+static char *pmm_trace_events_internal[] = {
+ "INTERNALS",
+ "INTERNAL_POWER_UP_ACK",
+ "INTERNAL_POWER_DOWN_ACK",
+};
+
+void _mali_pmm_trace_hardware_change( mali_pmm_core_mask old, mali_pmm_core_mask newstate )
+{
+ const char *dname;
+ const char *cname;
+ const char *ename;
+
+ if( old != newstate )
+ {
+ if( newstate == 0 )
+ {
+ dname = "NO cores";
+ }
+ else
+ {
+ dname = pmm_trace_get_core_name( newstate );
+ }
+
+ /* These state checks only work if the assumption that only cores can be
+ * turned on or turned off in seperate actions is true. If core power states can
+ * be toggled (some one, some off) at the same time, this check does not work
+ */
+ if( old > newstate )
+ {
+ /* Cores have turned off */
+ cname = pmm_trace_get_core_name( old - newstate );
+ ename = "OFF";
+ }
+ else
+ {
+ /* Cores have turned on */
+ cname = pmm_trace_get_core_name( newstate - old );
+ ename = "ON";
+ }
+ MALI_PRINT( ("PMM Trace: Hardware %s ON, %s just turned %s. { 0x%08x -> 0x%08x }", dname, cname, ename, old, newstate) );
+ }
+}
+
+void _mali_pmm_trace_state_change( mali_pmm_state old, mali_pmm_state newstate )
+{
+ if( old != newstate )
+ {
+ MALI_PRINT( ("PMM Trace: State changed from %s to %s", pmm_trace_state[old], pmm_trace_state[newstate]) );
+ }
+}
+
+void _mali_pmm_trace_policy_change( mali_pmm_policy old, mali_pmm_policy newpolicy )
+{
+ if( old != newpolicy )
+ {
+ MALI_PRINT( ("PMM Trace: Policy changed from %s to %s", pmm_trace_policy[old], pmm_trace_policy[newpolicy]) );
+ }
+}
+
+void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool received )
+{
+ const char *ename;
+ const char *dname;
+ const char *tname;
+ const char *format = "PMM Trace: Event %s { (%d) %s, %d ticks, (0x%x) %s }";
+
+ MALI_DEBUG_ASSERT_POINTER(event);
+
+ tname = (received) ? "received" : "sent";
+
+ if( event->id >= MALI_PMM_EVENT_INTERNALS )
+ {
+ ename = pmm_trace_events_internal[((int)event->id) - MALI_PMM_EVENT_INTERNALS];
+ }
+ else if( event->id >= MALI_PMM_EVENT_UKS )
+ {
+ ename = pmm_trace_events_uk[((int)event->id) - MALI_PMM_EVENT_UKS];
+ }
+ else
+ {
+ ename = pmm_trace_events[event->id];
+ }
+
+ switch( event->id )
+ {
+ case MALI_PMM_EVENT_OS_POWER_UP:
+ case MALI_PMM_EVENT_OS_POWER_DOWN:
+ dname = "os event";
+ break;
+
+ case MALI_PMM_EVENT_JOB_SCHEDULED:
+ case MALI_PMM_EVENT_JOB_QUEUED:
+ case MALI_PMM_EVENT_JOB_FINISHED:
+ case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
+ case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
+ dname = pmm_trace_get_core_name( (mali_pmm_core_mask)event->data );
+ break;
+
+ case MALI_PMM_EVENT_TIMEOUT:
+ dname = "timeout start";
+ /* Print data with a different format */
+ format = "PMM Trace: Event %s { (%d) %s, %d ticks, %d ticks %s }";
+ break;
+ default:
+ dname = "unknown data";
+ }
+
+ MALI_PRINT( (format, tname, (u32)event->id, ename, event->ts, (u32)event->data, dname) );
+}
+
+#endif /* MALI_PMM_TRACE */
+
+
+/****************** Mali Kernel API *****************/
+
+_mali_osk_errcode_t malipmm_kernel_subsystem_start( mali_kernel_subsystem_identifier id )
+{
+ mali_subsystem_pmm_id = id;
+ MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(PMU, malipmm_create));
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource)
+{
+ /* Create PMM state memory */
+ MALI_DEBUG_ASSERT( pmm_state == NULL );
+ pmm_state = (_mali_pmm_internal_state_t *) _mali_osk_malloc(sizeof(*pmm_state));
+ MALI_CHECK_NON_NULL( pmm_state, _MALI_OSK_ERR_NOMEM );
+
+ /* All values get 0 as default */
+ _mali_osk_memset(pmm_state, 0, sizeof(*pmm_state));
+
+ /* Set up the initial PMM state */
+ pmm_state->waiting = 0;
+ pmm_state->status = MALI_PMM_STATUS_IDLE;
+ pmm_state->state = MALI_PMM_STATE_UNAVAILABLE; /* Until a core registers */
+
+ /* Set up policy via compile time option for the moment */
+#if MALI_PMM_ALWAYS_ON
+ pmm_state->policy = MALI_PMM_POLICY_ALWAYS_ON;
+#else
+ pmm_state->policy = MALI_PMM_POLICY_JOB_CONTROL;
+#endif
+
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_policy_change( MALI_PMM_POLICY_NONE, pmm_state->policy );
+#endif
+
+ /* Set up assumes all values are initialized to NULL or MALI_FALSE, so
+ * we can exit halfway through set up and perform clean up
+ */
+
+#if USING_MALI_PMU
+ if( mali_pmm_pmu_init(resource) != _MALI_OSK_ERR_OK ) goto pmm_fail_cleanup;
+ pmm_state->pmu_initialized = MALI_TRUE;
+#endif
+ pmm_state->queue = _mali_osk_notification_queue_init();
+ if( !pmm_state->queue ) goto pmm_fail_cleanup;
+
+ pmm_state->iqueue = _mali_osk_notification_queue_init();
+ if( !pmm_state->iqueue ) goto pmm_fail_cleanup;
+
+ /* We are creating an IRQ handler just for the worker thread it gives us */
+ pmm_state->irq = _mali_osk_irq_init( _MALI_OSK_IRQ_NUMBER_PMM,
+ malipmm_irq_uhandler,
+ malipmm_irq_bhandler,
+ NULL,
+ NULL,
+ (void *)pmm_state, /* PMM state is passed to IRQ */
+ "PMM handler" );
+
+ if( !pmm_state->irq ) goto pmm_fail_cleanup;
+
+ pmm_state->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 75);
+ if( !pmm_state->lock ) goto pmm_fail_cleanup;
+
+ if( _mali_osk_atomic_init( &(pmm_state->messages_queued), 0 ) != _MALI_OSK_ERR_OK )
+ {
+ goto pmm_fail_cleanup;
+ }
+
+ MALIPMM_DEBUG_PRINT( ("PMM: subsystem created, policy=%d\n", pmm_state->policy) );
+
+ MALI_SUCCESS;
+
+pmm_fail_cleanup:
+ MALI_PRINT_ERROR( ("PMM: subsystem failed to be created\n") );
+ if( pmm_state )
+ {
+ if( pmm_state->lock ) _mali_osk_lock_term( pmm_state->lock );
+ if( pmm_state->irq ) _mali_osk_irq_term( pmm_state->irq );
+ if( pmm_state->queue ) _mali_osk_notification_queue_term( pmm_state->queue );
+ if( pmm_state->iqueue ) _mali_osk_notification_queue_term( pmm_state->iqueue );
+#if USING_MALI_PMU
+ if( pmm_state->pmu_initialized )
+ {
+ _mali_osk_resource_type_t t = PMU;
+ mali_pmm_pmu_deinit(&t);
+ }
+#endif /* USING_MALI_PMU */
+
+ _mali_osk_free(pmm_state);
+ pmm_state = NULL;
+ }
+ MALI_ERROR( _MALI_OSK_ERR_FAULT );
+}
+
+_mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifier id )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ MALIPMM_DEBUG_PRINT( ("PMM: subsystem loaded, policy initializing\n") );
+
+#if PMM_OS_TEST
+ power_test_start();
+#endif
+
+ /* Initialize the profile now the system has loaded - so that cores are
+ * not turned off during start up
+ */
+ return pmm_policy_init( pmm );
+}
+
+void malipmm_force_powerup( void )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_LOCK(pmm);
+ pmm->status = MALI_PMM_STATUS_OFF;
+ MALI_PMM_UNLOCK(pmm);
+
+ /* flush PMM workqueue */
+ _mali_osk_flush_workqueue( pmm->irq );
+
+ if (pmm->cores_powered == 0)
+ {
+ malipmm_powerup(pmm->cores_registered);
+ }
+}
+
+void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id )
+{
+ /* Check this is the right system */
+ MALI_DEBUG_ASSERT( id == mali_subsystem_pmm_id );
+ MALI_DEBUG_ASSERT_POINTER(pmm_state);
+
+ if( pmm_state )
+ {
+#if PMM_OS_TEST
+ power_test_end();
+#endif
+ /* Get the lock so we can shutdown */
+ MALI_PMM_LOCK(pmm_state);
+#if MALI_STATE_TRACKING
+ pmm_state->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+ pmm_state->status = MALI_PMM_STATUS_OFF;
+#if MALI_STATE_TRACKING
+ pmm_state->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+ MALI_PMM_UNLOCK(pmm_state);
+ _mali_osk_pmm_ospmm_cleanup();
+ pmm_policy_term(pmm_state);
+ _mali_osk_irq_term( pmm_state->irq );
+ _mali_osk_notification_queue_term( pmm_state->queue );
+ _mali_osk_notification_queue_term( pmm_state->iqueue );
+ if (pmm_state->cores_registered) malipmm_powerdown(pmm_state->cores_registered,MALI_POWER_MODE_LIGHT_SLEEP);
+#if USING_MALI_PMU
+ if( pmm_state->pmu_initialized )
+ {
+ _mali_osk_resource_type_t t = PMU;
+ mali_pmm_pmu_deinit(&t);
+ }
+#endif /* USING_MALI_PMU */
+
+ _mali_osk_atomic_term( &(pmm_state->messages_queued) );
+ MALI_PMM_LOCK_TERM(pmm_state);
+ _mali_osk_free(pmm_state);
+ pmm_state = NULL;
+ }
+
+ MALIPMM_DEBUG_PRINT( ("PMM: subsystem terminated\n") );
+}
+
+_mali_osk_errcode_t malipmm_powerup( u32 cores )
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+
+ /* If all the cores are powered down, power up the MALI */
+ if (pmm->cores_powered == 0)
+ {
+ mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ /* Initiate the power up */
+ _mali_osk_pmm_dev_activate();
+#endif
+ }
+
+#if USING_MALI_PMU
+ err = mali_pmm_pmu_powerup( cores );
+#endif
+ return err;
+}
+
+_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode )
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+#if USING_MALI_PMU
+ err = mali_pmm_pmu_powerdown( cores );
+#endif
+
+ /* If all cores are powered down, power off the MALI */
+ if (pmm->cores_powered == 0)
+ {
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ /* Initiate the power down */
+ _mali_osk_pmm_dev_idle();
+#endif
+ mali_platform_power_mode_change(power_mode);
+ }
+ return err;
+}
+
+_mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core )
+{
+ _mali_osk_errcode_t err;
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+
+ if( pmm == NULL )
+ {
+ /* PMM state has not been created, this is because the PMU resource has not been
+ * created yet.
+ * This probably means that the PMU resource has not been specfied as the first
+ * resource in the config file
+ */
+ MALI_PRINT_ERROR( ("PMM: Cannot register core %s because the PMU resource has not been\n initialized. Please make sure the PMU resource is the first resource in the\n resource configuration.\n",
+ pmm_trace_get_core_name(core)) );
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ MALI_PMM_LOCK(pmm);
+
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+
+ /* Check if the core is registered more than once in PMM */
+ MALI_DEBUG_ASSERT( (pmm->cores_registered & core) == 0 );
+
+ MALIPMM_DEBUG_PRINT( ("PMM: core registered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) );
+
+#if !MALI_PMM_NO_PMU
+ /* Make sure the core is powered up */
+ err = malipmm_powerup( core );
+#else
+ err = _MALI_OSK_ERR_OK;
+#endif
+ if( _MALI_OSK_ERR_OK == err )
+ {
+#if MALI_PMM_TRACE
+ mali_pmm_core_mask old_power = pmm->cores_powered;
+#endif
+ /* Assume a registered core is now powered up and idle */
+ pmm->cores_registered |= core;
+ pmm->cores_idle |= core;
+ pmm->cores_powered |= core;
+ pmm_update_system_state( pmm );
+
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
+#endif
+ }
+ else
+ {
+ MALI_PRINT_ERROR( ("PMM: Error(%d) powering up registered core: (0x%x) %s\n",
+ err, core, pmm_trace_get_core_name(core)) );
+ }
+
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+
+ return err;
+}
+
+void malipmm_core_unregister( mali_pmm_core_id core )
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ MALI_PMM_LOCK(pmm);
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+
+ /* Check if the core is registered in PMM */
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, core );
+
+ MALIPMM_DEBUG_PRINT( ("PMM: core unregistered: (0x%x) %s\n", core, pmm_trace_get_core_name(core)) );
+
+ {
+#if MALI_PMM_TRACE
+ mali_pmm_core_mask old_power = pmm->cores_powered;
+#endif
+ /* Remove the core from the system */
+ pmm->cores_idle &= (~core);
+ pmm->cores_powered &= (~core);
+ pmm->cores_pend_down &= (~core);
+ pmm->cores_pend_up &= (~core);
+ pmm->cores_ack_down &= (~core);
+ pmm->cores_ack_up &= (~core);
+
+ pmm_update_system_state( pmm );
+
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
+#endif
+ }
+
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+}
+void malipmm_core_power_down_okay( mali_pmm_core_id core )
+{
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK,
+ 0 };
+
+ event.data = core;
+
+ _mali_ukk_pmm_event_message( &event );
+}
+
+void malipmm_set_policy_check()
+{
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ pmm->check_policy = MALI_TRUE;
+
+ /* To check the policy we need to schedule some work */
+ _mali_osk_irq_schedulework( pmm->irq );
+}
+
+_mali_osk_errcode_t malipmm_irq_uhandler(void *data)
+{
+ MALIPMM_DEBUG_PRINT( ("PMM: uhandler - not expected to be used\n") );
+
+ MALI_SUCCESS;
+}
+
+void malipmm_irq_bhandler(void *data)
+{
+ _mali_pmm_internal_state_t *pmm;
+ pmm = (_mali_pmm_internal_state_t *)data;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+#if PMM_OS_TEST
+ if( power_test_check() ) return;
+#endif
+
+ MALI_PMM_LOCK(pmm);
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+ /* Quick out when we are shutting down */
+ if( pmm->status == MALI_PMM_STATUS_OFF )
+ {
+
+ #if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+ #endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+ return;
+ }
+
+ MALIPMM_DEBUG_PRINT( ("PMM: bhandler - Processing event\n") );
+
+ if( pmm->missed > 0 )
+ {
+ MALI_PRINT_ERROR( ("PMM: Failed to send %d events", pmm->missed) );
+ pmm_fatal_reset( pmm );
+ }
+
+ if( pmm->check_policy )
+ {
+ pmm->check_policy = MALI_FALSE;
+ pmm_policy_check_policy(pmm);
+ }
+ else
+ {
+ /* Perform event processing */
+ pmm_event_process();
+ if( pmm->fatal_power_err )
+ {
+ /* Try a reset */
+ pmm_fatal_reset( pmm );
+ }
+ }
+
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+}
+
+static void pmm_event_process( void )
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_osk_notification_t *msg = NULL;
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+ mali_pmm_message_t *event;
+ u32 process_messages;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+
+ /* Max number of messages to process before exiting - as we shouldn't stay
+ * processing the messages for a long time
+ */
+ process_messages = _mali_osk_atomic_read( &(pmm->messages_queued) );
+
+ while( process_messages > 0 )
+ {
+ /* Check internal message queue first */
+ err = _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg );
+
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ if( pmm->status == MALI_PMM_STATUS_IDLE || pmm->status == MALI_PMM_STATUS_OS_WAITING || pmm->status == MALI_PMM_STATUS_DVFS_PAUSE)
+ {
+ if( pmm->waiting > 0 ) pmm->waiting--;
+
+ /* We aren't busy changing state, so look at real events */
+ err = _mali_osk_notification_queue_dequeue( pmm->queue, &msg );
+
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ pmm->no_events++;
+ MALIPMM_DEBUG_PRINT( ("PMM: event_process - No message to process\n") );
+ /* Nothing to do - so return */
+ return;
+ }
+ else
+ {
+ #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
+ pmm->messages_received++;
+ #endif
+ }
+ }
+ else
+ {
+ /* Waiting for an internal message */
+ pmm->waiting++;
+ MALIPMM_DEBUG_PRINT( ("PMM: event_process - Waiting for internal message, messages queued=%d\n", pmm->waiting) );
+ return;
+ }
+ }
+ else
+ {
+ #if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
+ pmm->imessages_received++;
+ #endif
+ }
+
+ MALI_DEBUG_ASSERT_POINTER( msg );
+ /* Check the message type matches */
+ MALI_DEBUG_ASSERT( msg->notification_type == MALI_PMM_NOTIFICATION_TYPE );
+
+ event = msg->result_buffer;
+
+ _mali_osk_atomic_dec( &(pmm->messages_queued) );
+ process_messages--;
+
+ #if MALI_PMM_TRACE
+ /* Trace before we process the event in case we have an error */
+ _mali_pmm_trace_event_message( event, MALI_TRUE );
+ #endif
+ err = pmm_policy_process( pmm, event );
+
+
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ MALI_PRINT_ERROR( ("PMM: Error(%d) in policy %d when processing event message with id: %d",
+ err, pmm->policy, event->id) );
+ }
+
+ /* Delete notification */
+ _mali_osk_notification_delete ( msg );
+
+ if( pmm->fatal_power_err )
+ {
+ /* Nothing good has happened - exit */
+ return;
+ }
+
+
+ #if MALI_PMM_TRACE
+ MALI_PRINT( ("PMM Trace: Event processed, msgs (sent/read) = %d/%d, int msgs (sent/read) = %d/%d, no events = %d, waiting = %d\n",
+ pmm->messages_sent, pmm->messages_received, pmm->imessages_sent, pmm->imessages_received, pmm->no_events, pmm->waiting) );
+ #endif
+ }
+
+ if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->waiting > 0 )
+ {
+ /* For events we ignored whilst we were busy, add a new
+ * scheduled time to look at them */
+ _mali_osk_irq_schedulework( pmm->irq );
+ }
+}
+
+#if MALI_STATE_TRACKING
+u32 malipmm_subsystem_dump_state(char *buf, u32 size)
+{
+ int len = 0;
+ _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
+
+ if( !pmm )
+ {
+ len += _mali_osk_snprintf(buf + len, size + len, "PMM: Null state\n");
+ }
+ else
+ {
+ len += _mali_osk_snprintf(buf+len, size+len, "Locks:\n PMM lock acquired: %s\n",
+ pmm->mali_pmm_lock_acquired ? "true" : "false");
+ len += _mali_osk_snprintf(buf+len, size+len,
+ "PMM state:\n Previous status: %s\n Status: %s\n Current event: %s\n Policy: %s\n Check policy: %s\n State: %s\n",
+ pmm_trace_status[pmm->mali_last_pmm_status], pmm_trace_status[pmm->status],
+ pmm_trace_events[pmm->mali_new_event_status], pmm_trace_policy[pmm->policy],
+ pmm->check_policy ? "true" : "false", pmm_trace_state[pmm->state]);
+ len += _mali_osk_snprintf(buf+len, size+len,
+ "PMM cores:\n Cores registered: %d\n Cores powered: %d\n Cores idle: %d\n"
+ " Cores pending down: %d\n Cores pending up: %d\n Cores ack down: %d\n Cores ack up: %d\n",
+ pmm->cores_registered, pmm->cores_powered, pmm->cores_idle, pmm->cores_pend_down,
+ pmm->cores_pend_up, pmm->cores_ack_down, pmm->cores_ack_up);
+ len += _mali_osk_snprintf(buf+len, size+len, "PMM misc:\n PMU init: %s\n Messages queued: %d\n"
+ " Waiting: %d\n No events: %d\n Missed events: %d\n Fatal power error: %s\n",
+ pmm->pmu_initialized ? "true" : "false", _mali_osk_atomic_read(&(pmm->messages_queued)),
+ pmm->waiting, pmm->no_events, pmm->missed, pmm->fatal_power_err ? "true" : "false");
+ }
+ return len;
+}
+#endif /* MALI_STATE_TRACKING */
+
+#endif /* USING_MALI_PMM */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm.h
new file mode 100644
index 00000000000..4a667bbe5d2
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm.h
+ * Defines the power management module for the kernel device driver
+ */
+
+#ifndef __MALI_PMM_H__
+#define __MALI_PMM_H__
+
+/* For mali_pmm_message_data and MALI_PMM_EVENT_UK_* defines */
+#include "mali_uk_types.h"
+#include "mali_platform.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @defgroup pmmapi Power Management Module APIs
+ *
+ * @{
+ */
+
+/** OS event tester */
+#define PMM_OS_TEST 0
+
+/** @brief Compile option to turn on/off tracing */
+#define MALI_PMM_TRACE 0
+#define MALI_PMM_TRACE_SENT_EVENTS 0
+
+/** @brief Compile option to switch between always on or job control PMM policy */
+#define MALI_PMM_ALWAYS_ON 0
+
+/** @brief Overrides hardware PMU and uses software simulation instead
+ * @note This even stops intialization of PMU and cores being powered on at start up
+ */
+#define MALI_PMM_NO_PMU 0
+
+/** @brief PMM debug print to control debug message level */
+#define MALIPMM_DEBUG_PRINT(args) \
+ MALI_DEBUG_PRINT(3, args)
+
+
+/** @brief power management event message identifiers.
+ */
+/* These must match up with the pmm_trace_events & pmm_trace_events_internal
+ * arrays
+ */
+typedef enum mali_pmm_event_id
+{
+ MALI_PMM_EVENT_OS_POWER_UP = 0, /**< OS power up event */
+ MALI_PMM_EVENT_OS_POWER_DOWN = 1, /**< OS power down event */
+ MALI_PMM_EVENT_JOB_SCHEDULED = 2, /**< Job scheduled to run event */
+ MALI_PMM_EVENT_JOB_QUEUED = 3, /**< Job queued (but not run) event */
+ MALI_PMM_EVENT_JOB_FINISHED = 4, /**< Job finished event */
+ MALI_PMM_EVENT_TIMEOUT = 5, /**< Time out timer has expired */
+ MALI_PMM_EVENT_DVFS_PAUSE = 6, /**< Mali device pause event */
+ MALI_PMM_EVENT_DVFS_RESUME = 7, /**< Mali device resume event */
+
+ MALI_PMM_EVENT_UKS = 200, /**< Events from the user-side start here */
+ MALI_PMM_EVENT_UK_EXAMPLE = _MALI_PMM_EVENT_UK_EXAMPLE,
+
+ MALI_PMM_EVENT_INTERNALS = 1000,
+ MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK = 1001, /**< Internal power up acknowledgement */
+ MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK = 1002, /**< Internal power down acknowledgment */
+} mali_pmm_event_id;
+
+
+/** @brief Use this when the power up/down callbacks do not need any OS data. */
+#define MALI_PMM_NO_OS_DATA 1
+
+
+/* @brief Geometry and pixel processor identifiers for the PMM
+ *
+ * @note these match the ARM Mali 400 PMU hardware definitions, apart from the "SYSTEM"
+ */
+typedef enum mali_pmm_core_id_tag
+{
+ MALI_PMM_CORE_SYSTEM = 0x00000000, /**< All of the Mali hardware */
+ MALI_PMM_CORE_GP = 0x00000001, /**< Mali GP2 */
+ MALI_PMM_CORE_L2 = 0x00000002, /**< Level 2 cache */
+ MALI_PMM_CORE_PP0 = 0x00000004, /**< Mali 200 pixel processor 0 */
+ MALI_PMM_CORE_PP1 = 0x00000008, /**< Mali 200 pixel processor 1 */
+ MALI_PMM_CORE_PP2 = 0x00000010, /**< Mali 200 pixel processor 2 */
+ MALI_PMM_CORE_PP3 = 0x00000020, /**< Mali 200 pixel processor 3 */
+ MALI_PMM_CORE_PP_ALL = 0x0000003C /**< Mali 200 pixel processors 0-3 */
+} mali_pmm_core_id;
+
+
+/* @brief PMM bitmask of mali_pmm_core_ids
+ */
+typedef u32 mali_pmm_core_mask;
+
+/* @brief PMM event timestamp type
+ */
+typedef u32 mali_pmm_timestamp;
+
+/** @brief power management event message struct
+ */
+typedef struct _mali_pmm_message
+{
+ mali_pmm_event_id id; /**< event id */
+ mali_pmm_message_data data; /**< specific data associated with the event */
+ mali_pmm_timestamp ts; /**< timestamp the event was placed in the event queue */
+} mali_pmm_message_t;
+
+
+
+/** @brief the state of the power management module.
+ */
+/* These must match up with the pmm_trace_state array */
+typedef enum mali_pmm_state_tag
+{
+ MALI_PMM_STATE_UNAVAILABLE = 0, /**< PMM is not available */
+ MALI_PMM_STATE_SYSTEM_ON = 1, /**< All of the Mali hardware is on */
+ MALI_PMM_STATE_SYSTEM_OFF = 2, /**< All of the Mali hardware is off */
+ MALI_PMM_STATE_SYSTEM_TRANSITION = 3 /**< System is changing state */
+} mali_pmm_state;
+
+
+/** @brief a power management policy.
+ */
+/* These must match up with the pmm_trace_policy array */
+typedef enum mali_pmm_policy_tag
+{
+ MALI_PMM_POLICY_NONE = 0, /**< No policy */
+ MALI_PMM_POLICY_ALWAYS_ON = 1, /**< Always on policy */
+ MALI_PMM_POLICY_JOB_CONTROL = 2, /**< Job control policy */
+ MALI_PMM_POLICY_RUNTIME_JOB_CONTROL = 3 /**< Run time power management control policy */
+} mali_pmm_policy;
+
+/** @brief Function to power up MALI
+ *
+ * @param cores core mask to power up the cores
+ *
+ * @return error code if MALI fails to power up
+ */
+_mali_osk_errcode_t malipmm_powerup( u32 cores );
+
+/** @brief Function to power down MALI
+ *
+ * @param cores core mask to power down the cores
+ * @param The power mode to which MALI transitions
+ *
+ * @return error code if MALI fails to power down
+ */
+_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode );
+
+/** @brief Function to report to the OS when the power down has finished
+ *
+ * @param data The event message data that initiated the power down
+ */
+void _mali_osk_pmm_power_down_done(mali_pmm_message_data data);
+
+/** @brief Function to report to the OS when the power up has finished
+ *
+ * @param data The event message data that initiated the power up
+ */
+void _mali_osk_pmm_power_up_done(mali_pmm_message_data data);
+
+/** @brief Function to report that DVFS operation done
+ *
+ * @param data The event message data
+ */
+void _mali_osk_pmm_dvfs_operation_done(mali_pmm_message_data data);
+
+#if MALI_POWER_MGMT_TEST_SUITE
+/** @brief Function to notify power management events
+ *
+ * @param data The event message data
+ */
+void _mali_osk_pmm_policy_events_notifications(mali_pmm_event_id event_id);
+
+#endif
+
+/** @brief Function to power up MALI
+ *
+ * @note powers up the MALI during MALI device driver is unloaded
+ */
+void malipmm_force_powerup( void );
+
+/** @brief Function to report the OS that device is idle
+ *
+ * @note inform the OS that device is idle
+ */
+_mali_osk_errcode_t _mali_osk_pmm_dev_idle( void );
+
+/** @brief Function to report the OS to activate device
+ *
+ * @note inform the os that device needs to be activated
+ */
+void _mali_osk_pmm_dev_activate( void );
+
+/** @brief Function to report OS PMM for cleanup
+ *
+ * @note Function to report OS PMM for cleanup
+ */
+void _mali_osk_pmm_ospmm_cleanup( void );
+
+/** @brief Queries the current state of the PMM software
+ *
+ * @note the state of the PMM can change after this call has returned
+ *
+ * @return the current PMM state value
+ */
+mali_pmm_state _mali_pmm_state( void );
+
+/** @brief List of cores that are registered with the PMM
+ *
+ * This will return the cores that have been currently registered with the PMM,
+ * which is a bitwise OR of the mali_pmm_core_id_tags. A value of 0x0 means that
+ * there are no cores registered.
+ *
+ * @note the list of cores can change after this call has returned
+ *
+ * @return a bit mask representing all the cores that have been registered with the PMM
+ */
+mali_pmm_core_mask _mali_pmm_cores_list( void );
+
+/** @brief List of cores that are powered up in the PMM
+ *
+ * This will return the subset of the cores that can be listed using mali_pmm_cores_
+ * list, that have power. It is a bitwise OR of the mali_pmm_core_id_tags. A value of
+ * 0x0 means that none of the cores registered are powered.
+ *
+ * @note the list of cores can change after this call has returned
+ *
+ * @return a bit mask representing all the cores that are powered up
+ */
+mali_pmm_core_mask _mali_pmm_cores_powered( void );
+
+
+/** @brief List of power management policies that are supported by the PMM
+ *
+ * Given an empty array of policies - policy_list - which contains the number
+ * of entries as specified by - policy_list_size, this function will populate
+ * the list with the available policies. If the policy_list is too small for
+ * all the policies then only policy_list_size entries will be returned. If the
+ * policy_list is bigger than the number of available policies then, the extra
+ * entries will be set to MALI_PMM_POLICY_NONE.
+ * The function will also update available_policies with the number of policies
+ * that are available, even if it exceeds the policy_list_size.
+ * The function will succeed if all policies could be returned, else it will
+ * fail if none or only a subset of policies could be returned.
+ * The function will also fail if no policy_list is supplied, though
+ * available_policies is optional.
+ *
+ * @note this is a STUB function and is not yet implemented
+ *
+ * @param policy_list_size is the number of policies that can be returned in
+ * the policy_list argument
+ * @param policy_list is an array of policies that should be populated with
+ * the list of policies that are supported by the PMM
+ * @param policies_available optional argument, if non-NULL will be set to the
+ * number of policies available
+ * @return _MALI_OSK_ERR_OK if the policies could be listed, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t _mali_pmm_list_policies(
+ u32 policy_list_size,
+ mali_pmm_policy *policy_list,
+ u32 *policies_available );
+
+/** @brief Set the power management policy in the PMM
+ *
+ * Given a valid supported policy, this function will change the PMM to use
+ * this new policy
+ * The function will fail if the policy given is invalid or unsupported.
+ *
+ * @note this is a STUB function and is not yet implemented
+ *
+ * @param policy the new policy to be set
+ * @return _MALI_OSK_ERR_OK if the policy could be set, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t _mali_pmm_set_policy( mali_pmm_policy policy );
+
+/** @brief Get the current power management policy in the PMM
+ *
+ * Given a pointer to a policy data type, this function will return the current
+ * policy that is in effect for the PMM. This maybe out of date if there is a
+ * pending set policy call that has not been serviced.
+ * The function will fail if the policy given is NULL.
+ *
+ * @note the policy of the PMM can change after this call has returned
+ *
+ * @param policy a pointer to a policy that can be updated to the current
+ * policy
+ * @return _MALI_OSK_ERR_OK if the policy could be returned, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t _mali_pmm_get_policy( mali_pmm_policy *policy );
+
+#if MALI_PMM_TRACE
+
+/** @brief Indicates when a hardware state change occurs in the PMM
+ *
+ * @param old a mask of the cores indicating the previous state of the cores
+ * @param newstate a mask of the cores indicating the new current state of the cores
+ */
+void _mali_pmm_trace_hardware_change( mali_pmm_core_mask old, mali_pmm_core_mask newstate );
+
+/** @brief Indicates when a state change occurs in the PMM
+ *
+ * @param old the previous state for the PMM
+ * @param newstate the new current state of the PMM
+ */
+void _mali_pmm_trace_state_change( mali_pmm_state old, mali_pmm_state newstate );
+
+/** @brief Indicates when a policy change occurs in the PMM
+ *
+ * @param old the previous policy for the PMM
+ * @param newpolicy the new current policy of the PMM
+ */
+void _mali_pmm_trace_policy_change( mali_pmm_policy old, mali_pmm_policy newpolicy );
+
+/** @brief Records when an event message is read by the event system
+ *
+ * @param event the message details
+ * @param received MALI_TRUE when the message is received by the PMM, else it is being sent
+ */
+void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool received );
+
+#endif /* MALI_PMM_TRACE */
+
+/** @brief Dumps the current state of OS PMM thread
+ */
+#if MALI_STATE_TRACKING
+u32 mali_pmm_dump_os_thread_state( char *buf, u32 size );
+#endif /* MALI_STATE_TRACKING */
+
+/** @} */ /* end group pmmapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PMM_H__ */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.c
new file mode 100644
index 00000000000..da8957724e8
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_pmu.c
+ * Mali driver functions for Mali 400 PMU hardware
+ */
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_platform.h"
+
+#if USING_MALI_PMU
+#if USING_MALI_PMM
+
+#include "mali_pmm.h"
+
+/* Internal test on/off */
+#define PMU_TEST 0
+
+#if MALI_POWER_MGMT_TEST_SUITE
+#include "mali_platform_pmu_internal_testing.h"
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+
+/** @brief PMU hardware info
+ */
+typedef struct platform_pmu
+{
+ u32 reg_base_addr; /**< PMU registers base address */
+ u32 reg_size; /**< PMU registers size */
+ const char *name; /**< PMU name */
+ u32 irq_num; /**< PMU irq number */
+
+ mali_io_address reg_mapped; /**< IO-mapped pointer to registers */
+} platform_pmu_t;
+
+static platform_pmu_t *pmu_info = 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_STAT = 0x14, /*< Interrupt status register */
+ PMU_REG_ADDR_MGMT_INT_CLEAR = 0x18, /*< Interrupt clear register */
+ PMU_REG_ADDR_MGMT_SW_DELAY = 0x1C, /*< Software delay register */
+ PMU_REG_ADDR_MGMT_MASTER_PWR_UP = 0x24, /*< Master power up register */
+ PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x28, /*< Size of register space */
+} pmu_reg_addr_mgmt_addr;
+
+/* Internal functions */
+static u32 pmu_reg_read(platform_pmu_t *pmu, u32 relative_address);
+static void pmu_reg_write(platform_pmu_t *pmu, u32 relative_address, u32 new_val);
+static mali_pmm_core_mask pmu_translate_cores_to_pmu(mali_pmm_core_mask cores);
+#if PMU_TEST
+static void pmm_pmu_dump_regs( platform_pmu_t *pmu );
+static pmm_pmu_test( platform_pmu_t *pmu, u32 cores );
+#endif
+
+_mali_osk_errcode_t mali_pmm_pmu_init(_mali_osk_resource_t *resource)
+{
+
+ if( resource->type == PMU )
+ {
+ if( (resource->base == 0) ||
+ (resource->description == NULL) )
+ {
+ /* NOTE: We currently don't care about any other resource settings */
+ MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Missing PMU set up information\n"));
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+ pmu_info = (platform_pmu_t *)_mali_osk_malloc(sizeof(*pmu_info));
+ MALI_CHECK_NON_NULL( pmu_info, _MALI_OSK_ERR_NOMEM );
+
+ /* All values get 0 as default */
+ _mali_osk_memset(pmu_info, 0, sizeof(*pmu_info));
+
+ pmu_info->reg_base_addr = resource->base;
+ pmu_info->reg_size = (u32)PMU_REGISTER_ADDRESS_SPACE_SIZE;
+ pmu_info->name = resource->description;
+ pmu_info->irq_num = resource->irq;
+
+ if( _MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name) )
+ {
+ MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not request register region (0x%08X - 0x%08X) for %s\n",
+ pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name));
+ goto cleanup;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: request_mem_region: (0x%08X - 0x%08X) for %s\n",
+ pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name));
+ }
+
+ pmu_info->reg_mapped = _mali_osk_mem_mapioregion( pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name );
+
+ if( 0 == pmu_info->reg_mapped )
+ {
+ MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not ioremap registers for %s .\n", pmu_info->name));
+ _mali_osk_mem_unreqregion( pmu_info->reg_base_addr, pmu_info->reg_size );
+ goto cleanup;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: ioremap_nocache: Internal ptr: (0x%08X - 0x%08X) for %s\n",
+ (u32) pmu_info->reg_mapped,
+ ((u32)pmu_info->reg_mapped)+ pmu_info->reg_size - 1,
+ pmu_info->name));
+ }
+
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: Mapping registers to %s\n", pmu_info->name));
+
+#if PMU_TEST
+ pmu_test(pmu_info, (MALI_PMM_CORE_GP));
+ pmu_test(pmu_info, (MALI_PMM_CORE_GP|MALI_PMM_CORE_L2|MALI_PMM_CORE_PP0));
+#endif
+
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Initialized - %s\n", pmu_info->name) );
+ }
+ else
+ {
+ /* Didn't expect a different resource */
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ MALI_SUCCESS;
+
+cleanup:
+ _mali_osk_free(pmu_info);
+ pmu_info = NULL;
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+}
+
+_mali_osk_errcode_t mali_pmm_pmu_deinit(_mali_osk_resource_type_t *type)
+{
+ if (*type == PMU)
+ {
+ if( pmu_info )
+ {
+ _mali_osk_mem_unmapioregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->reg_mapped);
+ _mali_osk_mem_unreqregion(pmu_info->reg_base_addr, pmu_info->reg_size);
+ _mali_osk_free(pmu_info);
+ pmu_info = NULL;
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Terminated PMU\n") );
+ }
+ }
+ else
+ {
+ /* Didn't expect a different resource */
+ MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS);
+ }
+
+ MALI_SUCCESS;
+
+}
+
+_mali_osk_errcode_t mali_pmm_pmu_powerdown(u32 cores)
+{
+ u32 stat;
+ u32 timeout;
+ u32 cores_pmu;
+
+ MALI_DEBUG_ASSERT_POINTER(pmu_info);
+ MALI_DEBUG_ASSERT( cores != 0 ); /* Shouldn't receive zero from PMM */
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: power down (0x%x)\n", cores) );
+
+ cores_pmu = pmu_translate_cores_to_pmu(cores);
+ pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_POWER_DOWN, cores_pmu );
+
+ /* Wait for cores to be powered down */
+ timeout = 10; /* 10ms */
+ do
+ {
+ /* Get status of sleeping cores */
+ stat = pmu_reg_read( pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS );
+ stat &= cores_pmu;
+ if( stat == cores_pmu ) break; /* All cores we wanted are now asleep */
+ _mali_osk_time_ubusydelay(1000); /* 1ms */
+ timeout--;
+ } while( timeout > 0 );
+
+ if( timeout == 0 ) MALI_ERROR(_MALI_OSK_ERR_TIMEOUT);
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_pmm_pmu_powerup(u32 cores)
+{
+ u32 cores_pmu;
+ u32 stat;
+ u32 timeout;
+
+ MALI_DEBUG_ASSERT_POINTER(pmu_info);
+ MALI_DEBUG_ASSERT( cores != 0 ); /* Shouldn't receive zero from PMM */
+ MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: power up (0x%x)\n", cores) );
+
+ /* Don't use interrupts - just poll status */
+ pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_INT_MASK, 0 );
+ cores_pmu = pmu_translate_cores_to_pmu(cores);
+ pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_POWER_UP, cores_pmu );
+
+ timeout = 10; /* 10ms */
+ do
+ {
+ /* Get status of sleeping cores */
+ stat = pmu_reg_read( pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS );
+ stat &= cores_pmu;
+ if( stat == 0 ) break; /* All cores we wanted are now awake */
+ _mali_osk_time_ubusydelay(1000); /* 1ms */
+ timeout--;
+ } while( timeout > 0 );
+
+ if( timeout == 0 ) MALI_ERROR(_MALI_OSK_ERR_TIMEOUT);
+
+ MALI_SUCCESS;
+}
+
+
+/***** INTERNAL *****/
+
+/** @brief Internal PMU function to translate the cores bit mask
+ * into something the hardware PMU understands
+ *
+ * @param cores PMM cores bitmask
+ * @return PMU hardware cores bitmask
+ */
+static u32 pmu_translate_cores_to_pmu(mali_pmm_core_mask cores)
+{
+ /* For Mali 400 PMU the cores mask is already the same as what
+ * the hardware PMU expects.
+ * For other hardware, some translation can be done here, by
+ * translating the MALI_PMM_CORE_* bits into specific hardware
+ * bits
+ */
+ return cores;
+}
+
+/** @brief Internal PMU function to read a PMU register
+ *
+ * @param pmu handle that identifies the PMU hardware
+ * @param relative_address relative PMU hardware address to read from
+ * @return 32-bit value that was read from the address
+ */
+static u32 pmu_reg_read(platform_pmu_t *pmu, u32 relative_address)
+{
+ u32 read_val;
+
+ MALI_DEBUG_ASSERT_POINTER(pmu);
+ MALI_DEBUG_ASSERT((relative_address & 0x03) == 0);
+ MALI_DEBUG_ASSERT(relative_address < pmu->reg_size);
+
+ read_val = _mali_osk_mem_ioread32(pmu->reg_mapped, relative_address);
+
+ MALI_DEBUG_PRINT( 5, ("PMU: reg_read: %s Addr:0x%04X Val:0x%08x\n",
+ pmu->name, relative_address, read_val));
+
+ return read_val;
+}
+
+/** @brief Internal PMU function to write to a PMU register
+ *
+ * @param pmu handle that identifies the PMU hardware
+ * @param relative_address relative PMU hardware address to write to
+ * @param new_val new 32-bit value to write into the address
+ */
+static void pmu_reg_write(platform_pmu_t *pmu, u32 relative_address, u32 new_val)
+{
+ MALI_DEBUG_ASSERT_POINTER(pmu);
+ MALI_DEBUG_ASSERT((relative_address & 0x03) == 0);
+ MALI_DEBUG_ASSERT(relative_address < pmu->reg_size);
+
+ MALI_DEBUG_PRINT( 5, ("PMU: reg_write: %s Addr:0x%04X Val:0x%08x\n",
+ pmu->name, relative_address, new_val));
+
+ _mali_osk_mem_iowrite32(pmu->reg_mapped, relative_address, new_val);
+}
+
+#if PMU_TEST
+
+/***** TEST *****/
+
+static void pmu_dump_regs( platform_pmu_t *pmu )
+{
+ u32 addr;
+ for( addr = 0x0; addr < PMU_REGISTER_ADDRESS_SPACE_SIZE; addr += 0x4 )
+ {
+ MALI_PRINT( ("PMU_REG: 0x%08x: 0x%04x\n", (addr + pmu->reg_base_addr), pmu_reg_read( pmu, addr ) ) );
+ }
+}
+
+/* This function is an internal test for the PMU without any Mali h/w interaction */
+static void pmu_test( platform_pmu_t *pmu, u32 cores )
+{
+ u32 stat;
+ u32 timeout;
+
+ MALI_PRINT( ("PMU_TEST: Start\n") );
+
+ pmu_dump_regs( pmu );
+
+ MALI_PRINT( ("PMU_TEST: Power down cores: 0x%x\n", cores) );
+ _mali_pmm_pmu_power_down( pmu, cores, MALI_TRUE );
+
+ stat = pmu_reg_read( pmu, (u32)PMU_REG_ADDR_MGMT_STATUS );
+ MALI_PRINT( ("PMU_TEST: %s\n", (stat & cores) == cores ? "SUCCESS" : "FAIL" ) );
+
+ pmu_dump_regs( pmu );
+
+ MALI_PRINT( ("PMU_TEST: Power up cores: 0x%x\n", cores) );
+ _mali_pmm_pmu_power_up( pmu, cores, MALI_FALSE );
+
+ MALI_PRINT( ("PMU_TEST: Waiting for power up...\n") );
+ timeout = 1000; /* 1 sec */
+ while( !_mali_pmm_pmu_irq_power_up(pmu) && timeout > 0 )
+ {
+ _mali_osk_time_ubusydelay(1000); /* 1ms */
+ timeout--;
+ }
+
+ MALI_PRINT( ("PMU_TEST: Waited %dms for interrupt\n", (1000-timeout)) );
+ stat = pmu_reg_read( pmu, (u32)PMU_REG_ADDR_MGMT_STATUS );
+ MALI_PRINT( ("PMU_TEST: %s\n", (stat & cores) == 0 ? "SUCCESS" : "FAIL" ) );
+
+ _mali_pmm_pmu_irq_power_up_clear(pmu);
+
+ pmu_dump_regs( pmu );
+
+ MALI_PRINT( ("PMU_TEST: Finish\n") );
+}
+#endif /* PMU_TEST */
+
+#if MALI_POWER_MGMT_TEST_SUITE
+
+u32 pmu_get_power_up_down_info(void)
+{
+ return pmu_reg_read(pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS);
+}
+
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+#endif /* USING_MALI_PMM */
+#endif /* USING_MALI_PMU */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.h
new file mode 100644
index 00000000000..112074b2010
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_pmu.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_platform.h
+ * Platform specific Mali driver functions
+ */
+
+#include "mali_osk.h"
+
+#if !USING_MALI_PMM
+/* @brief System power up/down cores that can be passed into mali_platform_powerdown/up() */
+#define MALI_PLATFORM_SYSTEM 0
+#endif
+
+#if USING_MALI_PMM
+#if USING_MALI_PMU
+#include "mali_pmm.h"
+
+/** @brief Platform specific setup and initialisation of MALI
+ *
+ * This is called from the entrypoint of the driver to initialize the platform
+ * When using PMM, it is also called from the PMM start up to initialise the
+ * system PMU
+ *
+ * @param resource This is NULL when called on first driver start up, else it will
+ * be a pointer to a PMU resource
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmm_pmu_init(_mali_osk_resource_t *resource);
+
+/** @brief Platform specific deinitialisation of MALI
+ *
+ * This is called on the exit of the driver to terminate the platform
+ * When using PMM, it is also called from the PMM termination code to clean up the
+ * system PMU
+ *
+ * @param type This is NULL when called on driver exit, else it will
+ * be a pointer to a PMU resource type (not the full resource)
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmm_pmu_deinit(_mali_osk_resource_type_t *type);
+
+/** @brief Platform specific powerdown sequence of MALI
+ *
+ * Called as part of platform init if there is no PMM support, else the
+ * PMM will call it.
+ *
+ * @param cores This is MALI_PLATFORM_SYSTEM when called without PMM, else it will
+ * be a mask of cores to power down based on the mali_pmm_core_id enum
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmm_pmu_powerdown(u32 cores);
+
+/** @brief Platform specific powerup sequence of MALI
+ *
+ * Called as part of platform deinit if there is no PMM support, else the
+ * PMM will call it.
+ *
+ * @param cores This is MALI_PLATFORM_SYSTEM when called without PMM, else it will
+ * be a mask of cores to power down based on the mali_pmm_core_id enum
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmm_pmu_powerup(u32 cores);
+
+#if MALI_POWER_MGMT_TEST_SUITE
+#if USING_MALI_PMM
+#if USING_MALI_PMU
+/** @brief function to get status of individual cores
+ *
+ * This function is used by power management test suite to get the status of powered up/down the number
+ * of cores
+ * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization.
+ */
+u32 pmu_get_power_up_down_info(void);
+#endif
+#endif
+#endif
+#endif
+#endif
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.c
new file mode 100644
index 00000000000..8958ee8bd8d
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_policy.c
+ * Implementation of the common routines for power management module
+ * policies
+ */
+
+#if USING_MALI_PMM
+
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+
+#include "mali_pmm.h"
+#include "mali_pmm_system.h"
+#include "mali_pmm_state.h"
+#include "mali_pmm_policy.h"
+
+#include "mali_pmm_policy_alwayson.h"
+#include "mali_pmm_policy_jobcontrol.h"
+
+/* Call back function for timer expiration */
+static void pmm_policy_timer_callback( void *arg );
+
+_mali_osk_errcode_t pmm_policy_timer_init( _pmm_policy_timer_t *pptimer, u32 timeout, mali_pmm_event_id id )
+{
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+
+ /* All values get 0 as default */
+ _mali_osk_memset(pptimer, 0, sizeof(*pptimer));
+
+ pptimer->timer = _mali_osk_timer_init();
+ if( pptimer->timer )
+ {
+ _mali_osk_timer_setcallback( pptimer->timer, pmm_policy_timer_callback, (void *)pptimer );
+ pptimer->timeout = timeout;
+ pptimer->event_id = id;
+ MALI_SUCCESS;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+static void pmm_policy_timer_callback( void *arg )
+{
+ _pmm_policy_timer_t *pptimer = (_pmm_policy_timer_t *)arg;
+
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+ MALI_DEBUG_ASSERT( pptimer->set );
+
+ /* Set timer expired and flag there is a policy to check */
+ pptimer->expired = MALI_TRUE;
+ malipmm_set_policy_check();
+}
+
+
+void pmm_policy_timer_term( _pmm_policy_timer_t *pptimer )
+{
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+
+ _mali_osk_timer_del( pptimer->timer );
+ _mali_osk_timer_term( pptimer->timer );
+ pptimer->timer = NULL;
+}
+
+mali_bool pmm_policy_timer_start( _pmm_policy_timer_t *pptimer )
+{
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+ MALI_DEBUG_ASSERT_POINTER(pptimer->timer);
+
+ if( !(pptimer->set) )
+ {
+ pptimer->set = MALI_TRUE;
+ pptimer->expired = MALI_FALSE;
+ pptimer->start = _mali_osk_time_tickcount();
+ _mali_osk_timer_add( pptimer->timer, pptimer->timeout );
+ return MALI_TRUE;
+ }
+
+ return MALI_FALSE;
+}
+
+mali_bool pmm_policy_timer_stop( _pmm_policy_timer_t *pptimer )
+{
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+ MALI_DEBUG_ASSERT_POINTER(pptimer->timer);
+
+ if( pptimer->set )
+ {
+ _mali_osk_timer_del( pptimer->timer );
+ pptimer->set = MALI_FALSE;
+ pptimer->expired = MALI_FALSE;
+ return MALI_TRUE;
+ }
+
+ return MALI_FALSE;
+}
+
+mali_bool pmm_policy_timer_raise_event( _pmm_policy_timer_t *pptimer )
+{
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+
+ if( pptimer->expired )
+ {
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ MALI_PMM_EVENT_TIMEOUT, /* Assume timeout id, but set it below */
+ 0 };
+
+ event.id = pptimer->event_id;
+ event.data = (mali_pmm_message_data)pptimer->start;
+
+ /* Don't need to do any other notification with this timer */
+ pptimer->expired = MALI_FALSE;
+ /* Unset timer so it is free to be set again */
+ pptimer->set = MALI_FALSE;
+
+ _mali_ukk_pmm_event_message( &event );
+
+ return MALI_TRUE;
+ }
+
+ return MALI_FALSE;
+}
+
+mali_bool pmm_policy_timer_valid( u32 timer_start, u32 other_start )
+{
+ return (_mali_osk_time_after( other_start, timer_start ) == 0);
+}
+
+
+_mali_osk_errcode_t pmm_policy_init(_mali_pmm_internal_state_t *pmm)
+{
+ _mali_osk_errcode_t err;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ switch( pmm->policy )
+ {
+ case MALI_PMM_POLICY_ALWAYS_ON:
+ {
+ err = pmm_policy_init_always_on();
+ }
+ break;
+
+ case MALI_PMM_POLICY_JOB_CONTROL:
+ {
+ err = pmm_policy_init_job_control(pmm);
+ }
+ break;
+
+ case MALI_PMM_POLICY_NONE:
+ default:
+ err = _MALI_OSK_ERR_FAULT;
+ }
+
+ return err;
+}
+
+void pmm_policy_term(_mali_pmm_internal_state_t *pmm)
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ switch( pmm->policy )
+ {
+ case MALI_PMM_POLICY_ALWAYS_ON:
+ {
+ pmm_policy_term_always_on();
+ }
+ break;
+
+ case MALI_PMM_POLICY_JOB_CONTROL:
+ {
+ pmm_policy_term_job_control();
+ }
+ break;
+
+ case MALI_PMM_POLICY_NONE:
+ default:
+ MALI_PRINT_ERROR( ("PMM: Invalid policy terminated %d\n", pmm->policy) );
+ }
+}
+
+
+_mali_osk_errcode_t pmm_policy_process(_mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event)
+{
+ _mali_osk_errcode_t err;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(event);
+
+ switch( pmm->policy )
+ {
+ case MALI_PMM_POLICY_ALWAYS_ON:
+ {
+ err = pmm_policy_process_always_on( pmm, event );
+ }
+ break;
+
+ case MALI_PMM_POLICY_JOB_CONTROL:
+ {
+ err = pmm_policy_process_job_control( pmm, event );
+ }
+ break;
+
+ case MALI_PMM_POLICY_NONE:
+ default:
+ err = _MALI_OSK_ERR_FAULT;
+ }
+
+ return err;
+}
+
+
+void pmm_policy_check_policy( _mali_pmm_internal_state_t *pmm )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ switch( pmm->policy )
+ {
+ case MALI_PMM_POLICY_JOB_CONTROL:
+ {
+ pmm_policy_check_job_control();
+ }
+ break;
+
+ default:
+ /* Nothing needs to be done */
+ break;
+ }
+}
+
+
+#endif /* USING_MALI_PMM */
+
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h
new file mode 100644
index 00000000000..b3598fab158
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_policy.h
+ * Defines the power management module policies
+ */
+
+#ifndef __MALI_PMM_POLICY_H__
+#define __MALI_PMM_POLICY_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @addtogroup pmmapi Power Management Module APIs
+ *
+ * @{
+ *
+ * @defgroup pmmapi_policy Power Management Module Policies
+ *
+ * @{
+ */
+
+/** @brief Generic timer for use with policies
+ */
+typedef struct _pmm_policy_timer
+{
+ u32 timeout; /**< Timeout for this timer in ticks */
+ mali_pmm_event_id event_id; /**< Event id that will be raised when timer expires */
+ _mali_osk_timer_t *timer; /**< Timer */
+ mali_bool set; /**< Timer set */
+ mali_bool expired; /**< Timer expired - event needs to be raised */
+ u32 start; /**< Timer start ticks */
+} _pmm_policy_timer_t;
+
+/** @brief Policy timer initialization
+ *
+ * This will create a timer for use in policies, but won't start it
+ *
+ * @param pptimer An empty timer structure to be initialized
+ * @param timeout Timeout in ticks for the timer
+ * @param id Event id that will be raised on timeout
+ * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_timer_init( _pmm_policy_timer_t *pptimer, u32 timeout, mali_pmm_event_id id );
+
+/** @brief Policy timer termination
+ *
+ * This will clean up a timer that was previously used in policies, it
+ * will also stop it if started
+ *
+ * @param pptimer An initialized timer structure to be terminated
+ */
+void pmm_policy_timer_term( _pmm_policy_timer_t *pptimer );
+
+/** @brief Policy timer start
+ *
+ * This will start a previously created timer for use in policies
+ * When the timer expires after the initialized timeout it will raise
+ * a PMM event of the event id given on initialization
+ * As data for the event it will pass the start time of the timer
+ *
+ * @param pptimer A previously initialized policy timer
+ * @return MALI_TRUE if the timer was started, MALI_FALSE if it is already started
+ */
+mali_bool pmm_policy_timer_start( _pmm_policy_timer_t *pptimer );
+
+/** @brief Policy timer stop
+ *
+ * This will stop a previously created timer for use in policies
+ *
+ * @param pptimer A previously started policy timer
+ * @return MALI_TRUE if the timer was stopped, MALI_FALSE if it is already stopped
+ */
+mali_bool pmm_policy_timer_stop( _pmm_policy_timer_t *pptimer );
+
+/** @brief Policy timer stop
+ *
+ * This raise an event for an expired timer
+ *
+ * @param pptimer An expired policy timer
+ * @return MALI_TRUE if an event was raised, else MALI_FALSE
+ */
+mali_bool pmm_policy_timer_raise_event( _pmm_policy_timer_t *pptimer );
+
+/** @brief Policy timer valid checker
+ *
+ * This will check that a timer was started after a given time
+ *
+ * @param timer_start Time the timer was started
+ * @param other_start Time when another event or action occurred
+ * @return MALI_TRUE if the timer was started after the other time, else MALI_FALSE
+ */
+mali_bool pmm_policy_timer_valid( u32 timer_start, u32 other_start );
+
+
+/** @brief Common policy initialization
+ *
+ * This will initialize the current policy
+ *
+ * @note Any previously initialized policy should be terminated first
+ *
+ * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_init( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Common policy termination
+ *
+ * This will terminate the current policy.
+ * @note This can be called when a policy has not been initialized
+ */
+void pmm_policy_term( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Common policy state changer
+ *
+ * Given the next available event message, this routine passes it to
+ * the current policy for processing
+ *
+ * @param pmm internal PMM state
+ * @param event PMM event to process
+ * @return _MALI_OSK_ERR_OK if the policy state completed okay, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_process( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
+
+
+/** @brief Common policy checker
+ *
+ * If a policy timer fires then this function will be called to
+ * allow the policy to take the correct action
+ *
+ * @param pmm internal PMM state
+ */
+void pmm_policy_check_policy( _mali_pmm_internal_state_t *pmm );
+
+/** @} */ /* End group pmmapi_policy */
+/** @} */ /* End group pmmapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PMM_POLICY_H__ */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.c
new file mode 100644
index 00000000000..bca5f8a8b6c
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_policy_alwayson.c
+ * Implementation of the power management module policy - always on
+ */
+
+#if USING_MALI_PMM
+
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+
+#include "mali_pmm.h"
+#include "mali_pmm_system.h"
+#include "mali_pmm_state.h"
+#include "mali_pmm_policy_alwayson.h"
+
+_mali_osk_errcode_t pmm_policy_init_always_on(void)
+{
+ /* Nothing to set up */
+ MALI_SUCCESS;
+}
+
+void pmm_policy_term_always_on(void)
+{
+ /* Nothing to tear down */
+}
+
+_mali_osk_errcode_t pmm_policy_process_always_on( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(event);
+
+ switch( event->id )
+ {
+ case MALI_PMM_EVENT_OS_POWER_DOWN:
+ /* We aren't going to do anything, but signal so we don't block the OS
+ * NOTE: This may adversely affect any jobs Mali is currently running
+ */
+ _mali_osk_pmm_power_down_done( event->data );
+ break;
+
+ case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
+ case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
+ /* Not expected in this policy */
+ MALI_DEBUG_ASSERT( MALI_FALSE );
+ break;
+
+ case MALI_PMM_EVENT_OS_POWER_UP:
+ /* Nothing to do */
+ _mali_osk_pmm_power_up_done( event->data );
+ break;
+
+ case MALI_PMM_EVENT_JOB_SCHEDULED:
+ case MALI_PMM_EVENT_JOB_QUEUED:
+ case MALI_PMM_EVENT_JOB_FINISHED:
+ /* Nothing to do - we are always on */
+ break;
+
+ case MALI_PMM_EVENT_TIMEOUT:
+ /* Not expected in this policy */
+ MALI_DEBUG_ASSERT( MALI_FALSE );
+ break;
+
+ default:
+ MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
+ }
+
+ MALI_SUCCESS;
+}
+
+#endif
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.h
new file mode 100644
index 00000000000..9dc78a46e8a
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_alwayson.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_policy_alwayson.h
+ * Defines the power management module policy for always on
+ */
+
+#ifndef __MALI_PMM_POLICY_ALWAYSON_H__
+#define __MALI_PMM_POLICY_ALWAYSON_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @addtogroup pmmapi_policy Power Management Module Policies
+ *
+ * @{
+ */
+
+/** @brief Always on policy initialization
+ *
+ * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_init_always_on(void);
+
+/** @brief Always on policy termination
+ */
+void pmm_policy_term_always_on(void);
+
+/** @brief Always on policy state changer
+ *
+ * Given the next available event message, this routine processes it
+ * for the policy and changes state as needed.
+ *
+ * Always on policy will ignore all events and keep the Mali cores on
+ * all the time
+ *
+ * @param pmm internal PMM state
+ * @param event PMM event to process
+ * @return _MALI_OSK_ERR_OK if the policy state completed okay, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_process_always_on( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
+
+/** @} */ /* End group pmmapi_policies */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PMM_POLICY_ALWAYSON_H__ */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c
new file mode 100644
index 00000000000..3a194f9672e
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_policy_jobcontrol.c
+ * Implementation of the power management module policy - job control
+ */
+
+#if USING_MALI_PMM
+
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+#include "mali_platform.h"
+
+#include "mali_pmm.h"
+#include "mali_pmm_system.h"
+#include "mali_pmm_state.h"
+#include "mali_pmm_policy.h"
+#include "mali_pmm_policy_jobcontrol.h"
+
+typedef struct _pmm_policy_data_job_control
+{
+ _pmm_policy_timer_t latency; /**< Latency timeout timer for all cores */
+ u32 core_active_start; /**< Last time a core was set to active */
+ u32 timeout; /**< Timeout in ticks for latency timer */
+} _pmm_policy_data_job_control_t;
+
+
+/* @ brief Local data for this policy
+ */
+static _pmm_policy_data_job_control_t *data_job_control = NULL;
+
+/* @brief Set up the timeout if it hasn't already been set and if there are active cores */
+static void job_control_timeout_setup( _mali_pmm_internal_state_t *pmm, _pmm_policy_timer_t *pptimer )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+
+ /* Do we have an inactivity time out and some powered cores? */
+ if( pptimer->timeout > 0 && pmm->cores_powered != 0 )
+ {
+ /* Is the system idle and all the powered cores are idle? */
+ if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->cores_idle == pmm->cores_powered )
+ {
+ if( pmm_policy_timer_start(pptimer) )
+ {
+ MALIPMM_DEBUG_PRINT( ("PMM policy - Job control: Setting in-activity latency timer\n") );
+ }
+ }
+ else
+ {
+ /* We are not idle so there is no need for an inactivity timer
+ */
+ if( pmm_policy_timer_stop(pptimer) )
+ {
+ MALIPMM_DEBUG_PRINT( ("PMM policy - Job control: Removing in-activity latency timer\n") );
+ }
+ }
+ }
+}
+
+/* @brief Check the validity of the timeout - and if there is one set */
+static mali_bool job_control_timeout_valid( _mali_pmm_internal_state_t *pmm, _pmm_policy_timer_t *pptimer, u32 timer_start )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(pptimer);
+
+ /* Not a valid timer! */
+ if( pptimer->timeout == 0 ) return MALI_FALSE;
+
+ /* Are some cores powered and are they all idle? */
+ if( (pmm->cores_powered != 0) && (pmm->cores_idle == pmm->cores_powered) )
+ {
+ /* Has latency timeout started after the last core was active? */
+ if( pmm_policy_timer_valid( timer_start, data_job_control->core_active_start ) )
+ {
+ return MALI_TRUE;
+ }
+ else
+ {
+ MALIPMM_DEBUG_PRINT( ("PMM: In-activity latency time out ignored - out of date\n") );
+ }
+ }
+ else
+ {
+ if( pmm->cores_powered == 0 )
+ {
+ MALIPMM_DEBUG_PRINT( ("PMM: In-activity latency time out ignored - cores already off\n") );
+ }
+ else
+ {
+ MALIPMM_DEBUG_PRINT( ("PMM: In-activity latency time out ignored - cores active\n") );
+ }
+ }
+
+ return MALI_FALSE;
+}
+
+_mali_osk_errcode_t pmm_policy_init_job_control( _mali_pmm_internal_state_t *pmm )
+{
+ _mali_osk_errcode_t err;
+ MALI_DEBUG_ASSERT_POINTER( pmm );
+ MALI_DEBUG_ASSERT( data_job_control == NULL );
+
+ data_job_control = (_pmm_policy_data_job_control_t *) _mali_osk_malloc(sizeof(*data_job_control));
+ MALI_CHECK_NON_NULL( data_job_control, _MALI_OSK_ERR_NOMEM );
+
+ data_job_control->core_active_start = _mali_osk_time_tickcount();
+ data_job_control->timeout = MALI_PMM_POLICY_JOBCONTROL_INACTIVITY_TIMEOUT;
+
+ err = pmm_policy_timer_init( &data_job_control->latency, data_job_control->timeout, MALI_PMM_EVENT_TIMEOUT );
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ _mali_osk_free( data_job_control );
+ data_job_control = NULL;
+ return err;
+ }
+
+ /* Start the latency timeout */
+ job_control_timeout_setup( pmm, &data_job_control->latency );
+
+ MALI_SUCCESS;
+}
+
+void pmm_policy_term_job_control(void)
+{
+ if( data_job_control != NULL )
+ {
+ pmm_policy_timer_term( &data_job_control->latency );
+ _mali_osk_free( data_job_control );
+ data_job_control = NULL;
+ }
+}
+
+static void pmm_policy_job_control_job_queued( _mali_pmm_internal_state_t *pmm )
+{
+ mali_pmm_core_mask cores;
+ mali_pmm_core_mask cores_subset;
+
+ /* Make sure that all cores are powered in this
+ * simple policy
+ */
+ cores = pmm->cores_registered;
+ cores_subset = pmm_cores_to_power_up( pmm, cores );
+ if( cores_subset != 0 )
+ {
+ /* There are some cores that need powering up */
+ if( !pmm_invoke_power_up( pmm ) )
+ {
+ /* Need to wait until finished */
+ pmm->status = MALI_PMM_STATUS_POLICY_POWER_UP;
+ }
+ }
+}
+
+_mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
+{
+ mali_pmm_core_mask cores;
+ mali_pmm_core_mask cores_subset;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(event);
+ MALI_DEBUG_ASSERT_POINTER(data_job_control);
+
+ MALIPMM_DEBUG_PRINT( ("PMM: Job control policy process start - status=%d\n", pmm->status) );
+
+ /* Mainly the data is the cores */
+ cores = pmm_cores_from_event_data( pmm, event );
+
+#if MALI_STATE_TRACKING
+ pmm->mali_last_pmm_status = pmm->status;
+#endif /* MALI_STATE_TRACKING */
+
+ switch( pmm->status )
+ {
+ /**************** IDLE ****************/
+ case MALI_PMM_STATUS_IDLE:
+ switch( event->id )
+ {
+ case MALI_PMM_EVENT_OS_POWER_UP:
+ /* Not expected in this state */
+ break;
+
+ case MALI_PMM_EVENT_JOB_SCHEDULED:
+
+ /* Update idle cores to indicate active - remove these! */
+ pmm_cores_set_active( pmm, cores );
+ /* Remember when this happened */
+ data_job_control->core_active_start = event->ts;
+#if MALI_POWER_MGMT_TEST_SUITE
+ _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_JOB_SCHEDULED);
+#endif
+
+ /*** FALL THROUGH to QUEUED to check POWER UP ***/
+
+ case MALI_PMM_EVENT_JOB_QUEUED:
+
+ pmm_policy_job_control_job_queued( pmm );
+#if MALI_POWER_MGMT_TEST_SUITE
+ _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_JOB_QUEUED);
+#endif
+ break;
+
+ case MALI_PMM_EVENT_DVFS_PAUSE:
+
+ cores_subset = pmm_cores_to_power_down( pmm, cores, MALI_FALSE );
+ if ( cores_subset != 0 )
+ {
+ if ( !pmm_power_down_okay( pmm ) )
+ {
+ pmm->is_dvfs_active = 1;
+ pmm->status = MALI_PMM_STATUS_OS_POWER_DOWN;
+ pmm_save_os_event_data( pmm, event->data );
+ break;
+ }
+ }
+ pmm->status = MALI_PMM_STATUS_DVFS_PAUSE;
+ _mali_osk_pmm_dvfs_operation_done(0);
+ break;
+
+ case MALI_PMM_EVENT_OS_POWER_DOWN:
+
+ /* Need to power down all cores even if we need to wait for them */
+ cores_subset = pmm_cores_to_power_down( pmm, cores, MALI_FALSE );
+ if( cores_subset != 0 )
+ {
+ /* There are some cores that need powering down */
+ if( !pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) )
+ {
+ /* We need to wait until they are idle */
+
+ pmm->status = MALI_PMM_STATUS_OS_POWER_DOWN;
+ /* Save the OS data to respond later */
+ pmm_save_os_event_data( pmm, event->data );
+ /* Exit this case - as we have to wait */
+ break;
+ }
+ }
+ else
+ {
+ mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
+
+ }
+ /* Set waiting status */
+ pmm->status = MALI_PMM_STATUS_OS_WAITING;
+ /* All cores now down - respond to OS power event */
+ _mali_osk_pmm_power_down_done( event->data );
+ break;
+
+ case MALI_PMM_EVENT_JOB_FINISHED:
+
+ /* Update idle cores - add these! */
+ pmm_cores_set_idle( pmm, cores );
+#if MALI_POWER_MGMT_TEST_SUITE
+ _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_JOB_FINISHED);
+#endif
+ if( data_job_control->timeout > 0 )
+ {
+ /* Wait for time out to fire */
+ break;
+ }
+ /* For job control policy - turn off all cores */
+ cores = pmm->cores_powered;
+
+ /*** FALL THROUGH to TIMEOUT TEST as NO TIMEOUT ***/
+
+ case MALI_PMM_EVENT_TIMEOUT:
+
+ /* Main job control policy - turn off cores after inactivity */
+ if( job_control_timeout_valid( pmm, &data_job_control->latency, (u32)event->data ) )
+ {
+ /* Valid timeout of inactivity - so find out if we can power down
+ * immedately - if we can't then this means the cores are still in fact
+ * active
+ */
+ cores_subset = pmm_cores_to_power_down( pmm, cores, MALI_TRUE );
+ if( cores_subset != 0 )
+ {
+ /* Check if we can really power down, if not then we are not
+ * really in-active
+ */
+ if( !pmm_invoke_power_down( pmm, MALI_POWER_MODE_LIGHT_SLEEP ) )
+ {
+ pmm_power_down_cancel( pmm );
+ }
+ }
+ /* else there are no cores powered up! */
+ }
+#if MALI_POWER_MGMT_TEST_SUITE
+ _mali_osk_pmm_policy_events_notifications(MALI_PMM_EVENT_TIMEOUT);
+#endif
+ break;
+
+ default:
+ /* Unexpected event */
+ MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
+ }
+ break;
+
+ /******************DVFS PAUSE**************/
+ case MALI_PMM_STATUS_DVFS_PAUSE:
+ switch ( event->id )
+ {
+ case MALI_PMM_EVENT_DVFS_RESUME:
+
+ if ( pmm->cores_powered != 0 )
+ {
+ pmm->cores_ack_down =0;
+ pmm_power_down_cancel( pmm );
+ pmm->status = MALI_PMM_STATUS_IDLE;
+ }
+ else
+ {
+ pmm_policy_job_control_job_queued( pmm );
+ }
+ _mali_osk_pmm_dvfs_operation_done( 0 );
+ break;
+
+ case MALI_PMM_EVENT_OS_POWER_DOWN:
+ /* Set waiting status */
+ pmm->status = MALI_PMM_STATUS_OS_WAITING;
+ if ( pmm->cores_powered != 0 )
+ {
+ if ( pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) )
+ {
+ _mali_osk_pmm_power_down_done( 0 );
+ break;
+ }
+ }
+ else
+ {
+ mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
+ }
+ _mali_osk_pmm_power_down_done( 0 );
+ break;
+ default:
+ break;
+ }
+ break;
+
+ /**************** POWER UP ****************/
+ case MALI_PMM_STATUS_OS_POWER_UP:
+ case MALI_PMM_STATUS_POLICY_POWER_UP:
+ switch( event->id )
+ {
+ case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
+ /* Make sure cores powered off equal what we expect */
+ MALI_DEBUG_ASSERT( cores == pmm->cores_pend_up );
+ pmm_cores_set_up_ack( pmm, cores );
+
+ if( pmm_invoke_power_up( pmm ) )
+ {
+ if( pmm->status == MALI_PMM_STATUS_OS_POWER_UP )
+ {
+ /* Get the OS data and respond to the power up */
+ _mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) );
+ }
+ pmm->status = MALI_PMM_STATUS_IDLE;
+ }
+ break;
+
+ default:
+ /* Unexpected event */
+ MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
+ }
+ break;
+
+ /**************** POWER DOWN ****************/
+ case MALI_PMM_STATUS_OS_POWER_DOWN:
+ case MALI_PMM_STATUS_POLICY_POWER_DOWN:
+ switch( event->id )
+ {
+
+ case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
+
+ pmm_cores_set_down_ack( pmm, cores );
+
+ if ( pmm->is_dvfs_active == 1 )
+ {
+ if( pmm_power_down_okay( pmm ) )
+ {
+ pmm->is_dvfs_active = 0;
+ pmm->status = MALI_PMM_STATUS_DVFS_PAUSE;
+ _mali_osk_pmm_dvfs_operation_done( pmm_retrieve_os_event_data( pmm ) );
+ }
+ break;
+ }
+
+ /* Now check if we can power down */
+ if( pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) )
+ {
+ if( pmm->status == MALI_PMM_STATUS_OS_POWER_DOWN )
+ {
+ /* Get the OS data and respond to the power down */
+ _mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) );
+ }
+ pmm->status = MALI_PMM_STATUS_OS_WAITING;
+ }
+ break;
+
+ default:
+ /* Unexpected event */
+ MALI_ERROR(_MALI_OSK_ERR_ITEM_NOT_FOUND);
+ }
+ break;
+
+ case MALI_PMM_STATUS_OS_WAITING:
+ switch( event->id )
+ {
+ case MALI_PMM_EVENT_OS_POWER_UP:
+ cores_subset = pmm_cores_to_power_up( pmm, cores );
+ if( cores_subset != 0 )
+ {
+ /* There are some cores that need powering up */
+ if( !pmm_invoke_power_up( pmm ) )
+ {
+ /* Need to wait until power up complete */
+ pmm->status = MALI_PMM_STATUS_OS_POWER_UP;
+ /* Save the OS data to respond later */
+ pmm_save_os_event_data( pmm, event->data );
+ /* Exit this case - as we have to wait */
+ break;
+ }
+ }
+ pmm->status = MALI_PMM_STATUS_IDLE;
+ /* All cores now up - respond to OS power up event */
+ _mali_osk_pmm_power_up_done( event->data );
+ break;
+
+ default:
+ /* All other messages are ignored in this state */
+ break;
+ }
+ break;
+
+ default:
+ /* Unexpected state */
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Set in-activity latency timer - if required */
+ job_control_timeout_setup( pmm, &data_job_control->latency );
+
+ /* Update the PMM state */
+ pmm_update_system_state( pmm );
+#if MALI_STATE_TRACKING
+ pmm->mali_new_event_status = event->id;
+#endif /* MALI_STATE_TRACKING */
+
+ MALIPMM_DEBUG_PRINT( ("PMM: Job control policy process end - status=%d and event=%d\n", pmm->status,event->id) );
+
+ MALI_SUCCESS;
+}
+
+void pmm_policy_check_job_control()
+{
+ MALI_DEBUG_ASSERT_POINTER(data_job_control);
+
+ /* Latency timer must have expired raise the event */
+ pmm_policy_timer_raise_event(&data_job_control->latency);
+}
+
+
+#endif /* USING_MALI_PMM */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h
new file mode 100644
index 00000000000..71af3b15d03
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_policy.h
+ * Defines the power management module policies
+ */
+
+#ifndef __MALI_PMM_POLICY_JOBCONTROL_H__
+#define __MALI_PMM_POLICY_JOBCONTROL_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @addtogroup pmmapi_policy Power Management Module Policies
+ *
+ * @{
+ */
+
+/** @brief The jobcontrol policy inactivity latency timeout (in ticks)
+ * before the hardware is switched off
+ *
+ * @note Setting this low whilst tracing or producing debug output can
+ * cause alot of timeouts to fire which can affect the PMM behaviour
+ */
+#define MALI_PMM_POLICY_JOBCONTROL_INACTIVITY_TIMEOUT 50
+
+/** @brief Job control policy initialization
+ *
+ * @return _MALI_OSK_ERR_OK if the policy could be initialized, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_init_job_control(_mali_pmm_internal_state_t *pmm);
+
+/** @brief Job control policy termination
+ */
+void pmm_policy_term_job_control(void);
+
+/** @brief Job control policy state changer
+ *
+ * Given the next available event message, this routine processes it
+ * for the policy and changes state as needed.
+ *
+ * Job control policy depends on events from the Mali cores, and will
+ * power down all cores after an inactivity latency timeout. It will
+ * power the cores back on again when a job is scheduled to run.
+ *
+ * @param pmm internal PMM state
+ * @param event PMM event to process
+ * @return _MALI_OSK_ERR_OK if the policy state completed okay, or a suitable
+ * _mali_osk_errcode_t otherwise.
+ */
+_mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
+
+/** @brief Job control policy checker
+ *
+ * The latency timer has fired and we need to raise the correct event to
+ * handle it
+ *
+ * @param pmm internal PMM state
+ */
+void pmm_policy_check_job_control(void);
+
+/** @} */ /* End group pmmapi_policy */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PMM_POLICY_JOBCONTROL_H__ */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c
new file mode 100644
index 00000000000..c50a56799ae
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_state.c
+ * Implementation of the power management module internal state
+ */
+
+#if USING_MALI_PMM
+
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_subsystem.h"
+
+#include "mali_pmm.h"
+#include "mali_pmm_state.h"
+#include "mali_pmm_system.h"
+
+#include "mali_kernel_core.h"
+#include "mali_platform.h"
+
+#define SIZEOF_CORES_LIST 6
+
+/* NOTE: L2 *MUST* be first on the list so that it
+ * is correctly powered on first and powered off last
+ */
+static mali_pmm_core_id cores_list[] = { MALI_PMM_CORE_L2,
+ MALI_PMM_CORE_GP,
+ MALI_PMM_CORE_PP0,
+ MALI_PMM_CORE_PP1,
+ MALI_PMM_CORE_PP2,
+ MALI_PMM_CORE_PP3 };
+
+
+
+void pmm_update_system_state( _mali_pmm_internal_state_t *pmm )
+{
+ mali_pmm_state state;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ if( pmm->cores_registered == 0 )
+ {
+ state = MALI_PMM_STATE_UNAVAILABLE;
+ }
+ else if( pmm->cores_powered == 0 )
+ {
+ state = MALI_PMM_STATE_SYSTEM_OFF;
+ }
+ else if( pmm->cores_powered == pmm->cores_registered )
+ {
+ state = MALI_PMM_STATE_SYSTEM_ON;
+ }
+ else
+ {
+ /* Some other state where not everything is on or off */
+ state = MALI_PMM_STATE_SYSTEM_TRANSITION;
+ }
+
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_state_change( pmm->state, state );
+#endif
+ pmm->state = state;
+}
+
+mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event )
+{
+ mali_pmm_core_mask cores;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_DEBUG_ASSERT_POINTER(event);
+
+ switch( event->id )
+ {
+ case MALI_PMM_EVENT_OS_POWER_UP:
+ case MALI_PMM_EVENT_OS_POWER_DOWN:
+ /* All cores - the system */
+ cores = pmm->cores_registered;
+ break;
+
+ case MALI_PMM_EVENT_JOB_SCHEDULED:
+ case MALI_PMM_EVENT_JOB_QUEUED:
+ case MALI_PMM_EVENT_JOB_FINISHED:
+ case MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK:
+ case MALI_PMM_EVENT_INTERNAL_POWER_DOWN_ACK:
+ /* Currently the main event data is only the cores
+ * for these messages
+ */
+ cores = (mali_pmm_core_mask)event->data;
+ if( cores == MALI_PMM_CORE_SYSTEM )
+ {
+ cores = pmm->cores_registered;
+ }
+ else if( cores == MALI_PMM_CORE_PP_ALL )
+ {
+ /* Get the subset of registered PP cores */
+ cores = (pmm->cores_registered & MALI_PMM_CORE_PP_ALL);
+ }
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+ break;
+
+ default:
+ /* Assume timeout messages - report cores still powered */
+ cores = pmm->cores_powered;
+ break;
+ }
+
+ return cores;
+}
+
+mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
+{
+ mali_pmm_core_mask cores_subset;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+
+ /* Check that cores aren't pending power down when asked for power up */
+ MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );
+
+ cores_subset = (~(pmm->cores_powered) & cores);
+ if( cores_subset != 0 )
+ {
+ /* There are some cores that need powering up */
+ pmm->cores_pend_up = cores_subset;
+ }
+
+ return cores_subset;
+}
+
+mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only )
+{
+ mali_pmm_core_mask cores_subset;
+ _mali_osk_errcode_t err;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+
+ /* Check that cores aren't pending power up when asked for power down */
+ MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );
+
+ cores_subset = (pmm->cores_powered & cores);
+ if( cores_subset != 0 )
+ {
+ int n;
+ volatile mali_pmm_core_mask *ppowered = &(pmm->cores_powered);
+
+ /* There are some cores that need powering up, but we may
+ * need to wait until they are idle
+ */
+ for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
+ {
+ if( (cores_list[n] & cores_subset) != 0 )
+ {
+ /* Core is to be powered down */
+ pmm->cores_pend_down |= cores_list[n];
+
+ /* Can't hold the power lock, when acessing subsystem mutex via
+ * the core power call.
+ * Due to terminatation of driver requiring a subsystem mutex
+ * and then power lock held to unregister a core.
+ * This does mean that the following function could fail
+ * as the core is unregistered before we tell it to power
+ * down, but it does not matter as we are terminating
+ */
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+ /* Signal the core to power down
+ * If it is busy (not idle) it will set a pending power down flag
+ * (as long as we don't want to only immediately power down).
+ * If it isn't busy it will move out of the idle queue right
+ * away
+ */
+ err = mali_core_signal_power_down( cores_list[n], immediate_only );
+ MALI_PMM_LOCK(pmm);
+
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+
+ /* Re-read cores_subset in case it has changed */
+ cores_subset = (*ppowered & cores);
+
+ if( err == _MALI_OSK_ERR_OK )
+ {
+ /* We moved an idle core to the power down queue
+ * which means it is now acknowledged (if it is still
+ * registered)
+ */
+ pmm->cores_ack_down |= (cores_list[n] & cores_subset);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1,("PMM: In pmm_cores_to_power_down, the error and cores powered are..%x....%x",err,*ppowered));
+ MALI_DEBUG_ASSERT( err == _MALI_OSK_ERR_BUSY ||
+ (err == _MALI_OSK_ERR_FAULT &&
+ (*ppowered & cores_list[n]) == 0) );
+ /* If we didn't move a core - it must be active, so
+ * leave it pending, so we get an acknowledgement (when
+ * not in immediate only mode)
+ * Alternatively we are shutting down and the core has
+ * been unregistered
+ */
+ }
+ }
+ }
+ }
+
+ return cores_subset;
+}
+
+void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm )
+{
+ int n;
+ mali_pmm_core_mask pd, ad;
+ _mali_osk_errcode_t err;
+ volatile mali_pmm_core_mask *pregistered;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ MALIPMM_DEBUG_PRINT( ("PMM: Cancelling power down\n") );
+
+ pd = pmm->cores_pend_down;
+ ad = pmm->cores_ack_down;
+ /* Clear the pending cores so that they don't move to the off
+ * queue if they haven't already
+ */
+ pmm->cores_pend_down = 0;
+ pmm->cores_ack_down = 0;
+ pregistered = &(pmm->cores_registered);
+
+ /* Power up all the pending power down cores - just so
+ * we make sure the system is in a known state, as a
+ * pending core might have sent an acknowledged message
+ * which hasn't been read yet.
+ */
+ for( n = 0; n < SIZEOF_CORES_LIST; n++ )
+ {
+ if( (cores_list[n] & pd) != 0 )
+ {
+ /* Can't hold the power lock, when acessing subsystem mutex via
+ * the core power call.
+ * Due to terminatation of driver requiring a subsystem mutex
+ * and then power lock held to unregister a core.
+ * This does mean that the following power up function could fail
+ * as the core is unregistered before we tell it to power
+ * up, but it does not matter as we are terminating
+ */
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+ /* As we are cancelling - only move the cores back to the queue -
+ * no reset needed
+ */
+ err = mali_core_signal_power_up( cores_list[n], MALI_TRUE );
+ MALI_PMM_LOCK(pmm);
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+ /* Update pending list with the current registered cores */
+ pd &= (*pregistered);
+
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_BUSY &&
+ ((cores_list[n] & ad) == 0)) ||
+ (err == _MALI_OSK_ERR_FAULT &&
+ (*pregistered & cores_list[n]) == 0) );
+ /* If we didn't power up a core - it must be active and
+ * hasn't actually tried to power down - this is expected
+ * for cores that haven't acknowledged
+ * Alternatively we are shutting down and the core has
+ * been unregistered
+ */
+ }
+ }
+ }
+ /* Only used in debug builds */
+ MALI_IGNORE(ad);
+}
+
+
+mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ return ( pmm->cores_pend_down == pmm->cores_ack_down ? MALI_TRUE : MALI_FALSE );
+}
+
+mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode )
+{
+ _mali_osk_errcode_t err;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ /* Check that cores are pending power down during power down invoke */
+ MALI_DEBUG_ASSERT( pmm->cores_pend_down != 0 );
+ /* Check that cores are not pending power up during power down invoke */
+ MALI_DEBUG_ASSERT( pmm->cores_pend_up == 0 );
+
+ if( !pmm_power_down_okay( pmm ) )
+ {
+ MALIPMM_DEBUG_PRINT( ("PMM: Waiting for cores to go idle for power off - 0x%08x / 0x%08x\n",
+ pmm->cores_pend_down, pmm->cores_ack_down) );
+ return MALI_FALSE;
+ }
+ else
+ {
+ pmm->cores_powered &= ~(pmm->cores_pend_down);
+#if !MALI_PMM_NO_PMU
+ err = malipmm_powerdown( pmm->cores_pend_down, power_mode);
+#else
+ err = _MALI_OSK_ERR_OK;
+#endif
+
+ if( err == _MALI_OSK_ERR_OK )
+ {
+#if MALI_PMM_TRACE
+ mali_pmm_core_mask old_power = pmm->cores_powered;
+#endif
+ /* Remove powered down cores from idle and powered list */
+ pmm->cores_idle &= ~(pmm->cores_pend_down);
+ /* Reset pending/acknowledged status */
+ pmm->cores_pend_down = 0;
+ pmm->cores_ack_down = 0;
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
+#endif
+ }
+ else
+ {
+ pmm->cores_powered |= pmm->cores_pend_down;
+ MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power down cores - (0x%x) %s",
+ pmm->cores_pend_down, pmm_trace_get_core_name(pmm->cores_pend_down)) );
+ pmm->fatal_power_err = MALI_TRUE;
+ }
+ }
+
+ return MALI_TRUE;
+}
+
+
+mali_bool pmm_power_up_okay( _mali_pmm_internal_state_t *pmm )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ return ( pmm->cores_pend_up == pmm->cores_ack_up ? MALI_TRUE : MALI_FALSE );
+}
+
+
+mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm )
+{
+ _mali_osk_errcode_t err;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+
+ /* Check that cores are pending power up during power up invoke */
+ MALI_DEBUG_ASSERT( pmm->cores_pend_up != 0 );
+ /* Check that cores are not pending power down during power up invoke */
+ MALI_DEBUG_ASSERT( pmm->cores_pend_down == 0 );
+
+ if( pmm_power_up_okay( pmm ) )
+ {
+ /* Power up has completed - sort out subsystem core status */
+
+ int n;
+ /* Use volatile to access, so that it is updated if any cores are unregistered */
+ volatile mali_pmm_core_mask *ppendup = &(pmm->cores_pend_up);
+#if MALI_PMM_TRACE
+ mali_pmm_core_mask old_power = pmm->cores_powered;
+#endif
+ /* Move cores into idle queues */
+ for( n = 0; n < SIZEOF_CORES_LIST; n++ )
+ {
+ if( (cores_list[n] & (*ppendup)) != 0 )
+ {
+ /* Can't hold the power lock, when acessing subsystem mutex via
+ * the core power call.
+ * Due to terminatation of driver requiring a subsystem mutex
+ * and then power lock held to unregister a core.
+ * This does mean that the following function could fail
+ * as the core is unregistered before we tell it to power
+ * up, but it does not matter as we are terminating
+ */
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+ err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
+ MALI_PMM_LOCK(pmm);
+
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ MALI_DEBUG_PRINT(1,("In pmm_invoke_power_up:: The error and pending cores to be powered up are...%x...%x",err,*ppendup));
+ MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_FAULT &&
+ (*ppendup & cores_list[n]) == 0) );
+ /* We only expect this to fail when we are shutting down
+ * and the core has been unregistered
+ */
+ }
+ }
+ }
+ /* Finished power up - add cores to idle and powered list */
+ pmm->cores_powered |= (*ppendup);
+ pmm->cores_idle |= (*ppendup);
+ /* Reset pending/acknowledge status */
+ pmm->cores_pend_up = 0;
+ pmm->cores_ack_up = 0;
+
+#if MALI_PMM_TRACE
+ _mali_pmm_trace_hardware_change( old_power, pmm->cores_powered );
+#endif
+ return MALI_TRUE;
+ }
+ else
+ {
+#if !MALI_PMM_NO_PMU
+ /* Power up must now be done */
+ err = malipmm_powerup( pmm->cores_pend_up );
+#else
+ err = _MALI_OSK_ERR_OK;
+#endif
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power up cores - (0x%x) %s",
+ pmm->cores_pend_up, pmm_trace_get_core_name(pmm->cores_pend_up)) );
+ pmm->fatal_power_err = MALI_TRUE;
+ }
+ else
+ {
+ /* TBD - Update core status immediately rather than use event message */
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ MALI_PMM_EVENT_INTERNAL_POWER_UP_ACK,
+ 0 };
+ /* All the cores that were pending power up, have now completed power up */
+ event.data = pmm->cores_pend_up;
+ _mali_ukk_pmm_event_message( &event );
+ MALIPMM_DEBUG_PRINT( ("PMM: Sending ACK to power up") );
+ }
+ }
+
+ /* Always return false, as we need an interrupt to acknowledge
+ * when power up is complete
+ */
+ return MALI_FALSE;
+}
+
+mali_pmm_core_mask pmm_cores_set_active( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+
+ pmm->cores_idle &= (~cores);
+ return pmm->cores_idle;
+}
+
+mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+
+ pmm->cores_idle |= (cores);
+ return pmm->cores_idle;
+}
+
+mali_pmm_core_mask pmm_cores_set_down_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+
+ /* Check core is not pending a power down */
+ MALI_DEBUG_ASSERT( (pmm->cores_pend_down & cores) != 0 );
+ /* Check core has not acknowledged power down more than once */
+ MALI_DEBUG_ASSERT( (pmm->cores_ack_down & cores) == 0 );
+
+ pmm->cores_ack_down |= (cores);
+
+ return pmm->cores_ack_down;
+}
+
+void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm )
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_osk_notification_t *msg = NULL;
+ mali_pmm_status status;
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALIPMM_DEBUG_PRINT( ("PMM: Fatal Reset called") );
+
+ MALI_DEBUG_ASSERT( pmm->status != MALI_PMM_STATUS_OFF );
+
+ /* Reset the common status */
+ pmm->waiting = 0;
+ pmm->missed = 0;
+ pmm->fatal_power_err = MALI_FALSE;
+ pmm->no_events = 0;
+ pmm->check_policy = MALI_FALSE;
+ pmm->cores_pend_down = 0;
+ pmm->cores_pend_up = 0;
+ pmm->cores_ack_down = 0;
+ pmm->cores_ack_up = 0;
+ pmm->is_dvfs_active = 0;
+#if MALI_PMM_TRACE
+ pmm->messages_sent = 0;
+ pmm->messages_received = 0;
+ pmm->imessages_sent = 0;
+ pmm->imessages_received = 0;
+ MALI_PRINT( ("PMM Trace: *** Fatal reset occurred ***") );
+#endif
+
+ /* Set that we are unavailable whilst resetting */
+ pmm->state = MALI_PMM_STATE_UNAVAILABLE;
+ status = pmm->status;
+ pmm->status = MALI_PMM_STATUS_OFF;
+
+ /* We want all cores powered */
+ pmm->cores_powered = pmm->cores_registered;
+ /* The cores may not be idle, but this state will be rectified later */
+ pmm->cores_idle = pmm->cores_registered;
+
+ /* So power on any cores that are registered */
+ if( pmm->cores_registered != 0 )
+ {
+ int n;
+ volatile mali_pmm_core_mask *pregistered = &(pmm->cores_registered);
+#if !MALI_PMM_NO_PMU
+ err = malipmm_powerup( pmm->cores_registered );
+#endif
+ if( err != _MALI_OSK_ERR_OK )
+ {
+ /* This is very bad as we can't even be certain the cores are now
+ * powered up
+ */
+ MALI_PRINT_ERROR( ("PMM: Failed to perform PMM reset!\n") );
+ /* TBD driver exit? */
+ }
+
+ for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- )
+ {
+ if( (cores_list[n] & (*pregistered)) != 0 )
+ {
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 0;
+#endif /* MALI_STATE_TRACKING */
+
+ MALI_PMM_UNLOCK(pmm);
+ /* Core is now active - so try putting it in the idle queue */
+ err = mali_core_signal_power_up( cores_list[n], MALI_FALSE );
+ MALI_PMM_LOCK(pmm);
+#if MALI_STATE_TRACKING
+ pmm->mali_pmm_lock_acquired = 1;
+#endif /* MALI_STATE_TRACKING */
+
+ /* We either succeeded, or we were not off anyway, or we have
+ * just be deregistered
+ */
+ MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_OK) ||
+ (err == _MALI_OSK_ERR_BUSY) ||
+ (err == _MALI_OSK_ERR_FAULT &&
+ (*pregistered & cores_list[n]) == 0) );
+ }
+ }
+ }
+
+ /* Unblock any pending OS event */
+ if( status == MALI_PMM_STATUS_OS_POWER_UP )
+ {
+ /* Get the OS data and respond to the power up */
+ _mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) );
+ }
+ if( status == MALI_PMM_STATUS_OS_POWER_DOWN )
+ {
+ /* Get the OS data and respond to the power down
+ * NOTE: We are not powered down at this point due to power problems,
+ * so we are lying to the system, but something bad has already
+ * happened and we are trying unstick things
+ * TBD - Add busy loop to power down cores?
+ */
+ _mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) );
+ }
+
+ /* Purge the event queues */
+ do
+ {
+ if( _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ) == _MALI_OSK_ERR_OK )
+ {
+ _mali_osk_notification_delete ( msg );
+ break;
+ }
+ } while (MALI_TRUE);
+
+ do
+ {
+ if( _mali_osk_notification_queue_dequeue( pmm->queue, &msg ) == _MALI_OSK_ERR_OK )
+ {
+ _mali_osk_notification_delete ( msg );
+ break;
+ }
+ } while (MALI_TRUE);
+
+ /* Return status/state to normal */
+ pmm->status = MALI_PMM_STATUS_IDLE;
+ pmm_update_system_state(pmm);
+}
+
+mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores )
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, cores );
+
+ /* Check core is not pending a power up */
+ MALI_DEBUG_ASSERT( (pmm->cores_pend_up & cores) != 0 );
+ /* Check core has not acknowledged power up more than once */
+ MALI_DEBUG_ASSERT( (pmm->cores_ack_up & cores) == 0 );
+
+ pmm->cores_ack_up |= (cores);
+
+ return pmm->cores_ack_up;
+}
+
+void pmm_save_os_event_data(_mali_pmm_internal_state_t *pmm, mali_pmm_message_data data)
+{
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ /* Check that there is no saved data */
+ MALI_DEBUG_ASSERT( pmm->os_data == 0 );
+ /* Can't store zero data - as retrieve check will fail */
+ MALI_DEBUG_ASSERT( data != 0 );
+
+ pmm->os_data = data;
+}
+
+mali_pmm_message_data pmm_retrieve_os_event_data(_mali_pmm_internal_state_t *pmm)
+{
+ mali_pmm_message_data data;
+
+ MALI_DEBUG_ASSERT_POINTER(pmm);
+ /* Check that there is saved data */
+ MALI_DEBUG_ASSERT( pmm->os_data != 0 );
+
+ /* Get data, and clear the saved version */
+ data = pmm->os_data;
+ pmm->os_data = 0;
+
+ return data;
+}
+
+/* Create list of core names to look up
+ * We are doing it this way to overcome the need for
+ * either string allocation, or stack space, so we
+ * use constant strings instead
+ */
+typedef struct pmm_trace_corelist
+{
+ mali_pmm_core_mask id;
+ const char *name;
+} pmm_trace_corelist_t;
+
+static pmm_trace_corelist_t pmm_trace_cores[] = {
+ { MALI_PMM_CORE_SYSTEM, "SYSTEM" },
+ { MALI_PMM_CORE_GP, "GP" },
+ { MALI_PMM_CORE_L2, "L2" },
+ { MALI_PMM_CORE_PP0, "PP0" },
+ { MALI_PMM_CORE_PP1, "PP1" },
+ { MALI_PMM_CORE_PP2, "PP2" },
+ { MALI_PMM_CORE_PP3, "PP3" },
+ { MALI_PMM_CORE_PP_ALL, "PP (all)" },
+ { (MALI_PMM_CORE_GP | MALI_PMM_CORE_L2 | MALI_PMM_CORE_PP0),
+ "GP+L2+PP0" },
+ { (MALI_PMM_CORE_GP | MALI_PMM_CORE_PP0),
+ "GP+PP0" },
+ { (MALI_PMM_CORE_GP | MALI_PMM_CORE_L2 | MALI_PMM_CORE_PP0 | MALI_PMM_CORE_PP1),
+ "GP+L2+PP0+PP1" },
+ { (MALI_PMM_CORE_GP | MALI_PMM_CORE_PP0 | MALI_PMM_CORE_PP1),
+ "GP+PP0+PP1" },
+ { 0, NULL } /* Terminator of list */
+};
+
+const char *pmm_trace_get_core_name( mali_pmm_core_mask cores )
+{
+ const char *dname = NULL;
+ int cl;
+
+ /* Look up name in corelist */
+ cl = 0;
+ while( pmm_trace_cores[cl].name != NULL )
+ {
+ if( pmm_trace_cores[cl].id == cores )
+ {
+ dname = pmm_trace_cores[cl].name;
+ break;
+ }
+ cl++;
+ }
+
+ if( dname == NULL )
+ {
+ /* We don't know a good short-hand for the configuration */
+ dname = "[multi-core]";
+ }
+
+ return dname;
+}
+
+#endif /* USING_MALI_PMM */
+
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h
new file mode 100644
index 00000000000..0fb62d2a642
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_state.h
+ * Defines the internal power management module state
+ */
+
+#ifndef __MALI_PMM_STATE_H__
+#define __MALI_PMM_STATE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @addtogroup pmmapi Power Management Module APIs
+ *
+ * @{
+ *
+ * @defgroup pmmapi_state Power Management Module State
+ *
+ * @{
+ */
+
+/* Check that the subset is really a subset of cores */
+#define MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( cores, subset ) \
+ MALI_DEBUG_ASSERT( ((~(cores)) & (subset)) == 0 )
+
+
+/* Locking macros */
+#define MALI_PMM_LOCK(pmm) \
+ _mali_osk_lock_wait( pmm->lock, _MALI_OSK_LOCKMODE_RW )
+#define MALI_PMM_UNLOCK(pmm) \
+ _mali_osk_lock_signal( pmm->lock, _MALI_OSK_LOCKMODE_RW )
+#define MALI_PMM_LOCK_TERM(pmm) \
+ _mali_osk_lock_term( pmm->lock )
+
+/* Notification type for messages */
+#define MALI_PMM_NOTIFICATION_TYPE 0
+
+/** @brief Status of the PMM state machine
+ */
+typedef enum mali_pmm_status_tag
+{
+ MALI_PMM_STATUS_IDLE, /**< PMM is waiting next event */
+ MALI_PMM_STATUS_POLICY_POWER_DOWN, /**< Policy initiated power down */
+ MALI_PMM_STATUS_POLICY_POWER_UP, /**< Policy initiated power down */
+ MALI_PMM_STATUS_OS_WAITING, /**< PMM is waiting for OS power up */
+ MALI_PMM_STATUS_OS_POWER_DOWN, /**< OS initiated power down */
+ MALI_PMM_STATUS_DVFS_PAUSE, /**< PMM DVFS Status Pause */
+ MALI_PMM_STATUS_OS_POWER_UP, /**< OS initiated power up */
+ MALI_PMM_STATUS_OFF, /**< PMM is not active */
+} mali_pmm_status;
+
+
+/** @brief Internal state of the PMM
+ */
+typedef struct _mali_pmm_internal_state
+{
+ mali_pmm_status status; /**< PMM state machine */
+ mali_pmm_policy policy; /**< PMM policy */
+ mali_bool check_policy; /**< PMM policy needs checking */
+ mali_pmm_state state; /**< PMM state */
+ mali_pmm_core_mask cores_registered; /**< Bitmask of cores registered */
+ mali_pmm_core_mask cores_powered; /**< Bitmask of cores powered up */
+ mali_pmm_core_mask cores_idle; /**< Bitmask of cores idle */
+ mali_pmm_core_mask cores_pend_down; /**< Bitmask of cores pending power down */
+ mali_pmm_core_mask cores_pend_up; /**< Bitmask of cores pending power up */
+ mali_pmm_core_mask cores_ack_down; /**< Bitmask of cores acknowledged power down */
+ mali_pmm_core_mask cores_ack_up; /**< Bitmask of cores acknowledged power up */
+
+ _mali_osk_notification_queue_t *queue; /**< PMM event queue */
+ _mali_osk_notification_queue_t *iqueue; /**< PMM internal event queue */
+ _mali_osk_irq_t *irq; /**< PMM irq handler */
+ _mali_osk_lock_t *lock; /**< PMM lock */
+
+ mali_pmm_message_data os_data; /**< OS data sent via the OS events */
+
+ mali_bool pmu_initialized; /**< PMU initialized */
+
+ _mali_osk_atomic_t messages_queued; /**< PMM event messages queued */
+ u32 waiting; /**< PMM waiting events - due to busy */
+ u32 no_events; /**< PMM called to process when no events */
+
+ u32 missed; /**< PMM missed events due to OOM */
+ mali_bool fatal_power_err; /**< PMM has had a fatal power error? */
+ u32 is_dvfs_active; /**< PMM DVFS activity */
+
+#if MALI_STATE_TRACKING
+ mali_pmm_status mali_last_pmm_status; /**< The previous PMM status */
+ mali_pmm_event_id mali_new_event_status;/**< The type of the last PMM event */
+ mali_bool mali_pmm_lock_acquired; /**< Is the PMM lock held somewhere or not */
+#endif
+
+#if (MALI_PMM_TRACE || MALI_STATE_TRACKING)
+ u32 messages_sent; /**< Total event messages sent */
+ u32 messages_received; /**< Total event messages received */
+ u32 imessages_sent; /**< Total event internal messages sent */
+ u32 imessages_received; /**< Total event internal messages received */
+#endif
+} _mali_pmm_internal_state_t;
+
+/** @brief Sets that a policy needs a check before processing events
+ *
+ * A timer or something has expired that needs dealing with
+ */
+void malipmm_set_policy_check(void);
+
+/** @brief Update the PMM externally viewable state depending on the current PMM internal state
+ *
+ * @param pmm internal PMM state
+ * @return MALI_TRUE if the timeout is valid, else MALI_FALSE
+ */
+void pmm_update_system_state( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Returns the core mask from the event data - if applicable
+ *
+ * @param pmm internal PMM state
+ * @param event event message to get the core mask from
+ * @return mask of cores that is relevant to this event message
+ */
+mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, mali_pmm_message_t *event );
+
+/** @brief Sort out which cores need to be powered up from the given core mask
+ *
+ * All cores that can be powered up will be put into a pending state
+ *
+ * @param pmm internal PMM state
+ * @param cores mask of cores to check if they need to be powered up
+ * @return mask of cores that need to be powered up, this can be 0 if all cores
+ * are powered up already
+ */
+mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
+
+/** @brief Sort out which cores need to be powered down from the given core mask
+ *
+ * All cores that can be powered down will be put into a pending state. If they
+ * can be powered down immediately they will also be acknowledged that they can be
+ * powered down. If the immediate_only flag is set, then only those cores that
+ * can be acknowledged for power down will be put into a pending state.
+ *
+ * @param pmm internal PMM state
+ * @param cores mask of cores to check if they need to be powered down
+ * @param immediate_only MALI_TRUE means that only cores that can power down now will
+ * be put into a pending state
+ * @return mask of cores that need to be powered down, this can be 0 if all cores
+ * are powered down already
+ */
+mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only );
+
+/** @brief Cancel an invokation to power down (pmm_invoke_power_down)
+ *
+ * @param pmm internal PMM state
+ */
+void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Check if a call to invoke power down should succeed, or fail
+ *
+ * This will report MALI_FALSE if some of the cores are still active and need
+ * to acknowledge that they are ready to power down
+ *
+ * @param pmm internal PMM state
+ * @return MALI_TRUE if the pending cores to power down have acknowledged they
+ * can power down, else MALI_FALSE
+ */
+mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Try to make all the pending cores power down
+ *
+ * If all the pending cores have acknowledged they can power down, this will call the
+ * PMU power down function to turn them off
+ *
+ * @param pmm internal PMM state
+ * @return MALI_TRUE if the pending cores have been powered down, else MALI_FALSE
+ */
+mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode );
+
+/** @brief Check if all the pending cores to power up have done so
+ *
+ * This will report MALI_FALSE if some of the cores are still powered off
+ * and have not acknowledged that they have powered up
+ *
+ * @param pmm internal PMM state
+ * @return MALI_TRUE if the pending cores to power up have acknowledged they
+ * are now powered up, else MALI_FALSE
+ */
+mali_bool pmm_power_up_okay( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Try to make all the pending cores power up
+ *
+ * If all the pending cores have acknowledged they have powered up, this will
+ * make the cores start processing jobs again, else this will call the PMU
+ * power up function to turn them on, and the PMM is then expected to wait for an
+ * interrupt to acknowledge the power up
+ *
+ * @param pmm internal PMM state
+ * @return MALI_TRUE if the pending cores have been powered up, else MALI_FALSE
+ */
+mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Set the cores that are now active in the system
+ *
+ * Updates which cores are active and returns which cores are still idle
+ *
+ * @param pmm internal PMM state
+ * @param cores mask of cores to set to active
+ * @return mask of all the cores that are idle
+ */
+mali_pmm_core_mask pmm_cores_set_active( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
+
+/** @brief Set the cores that are now idle in the system
+ *
+ * Updates which cores are idle and returns which cores are still idle
+ *
+ * @param pmm internal PMM state
+ * @param cores mask of cores to set to idle
+ * @return mask of all the cores that are idle
+ */
+mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
+
+/** @brief Set the cores that have acknowledged a pending power down
+ *
+ * Updates which cores have acknowledged the pending power down and are now ready
+ * to be turned off
+ *
+ * @param pmm internal PMM state
+ * @param cores mask of cores that have acknowledged the pending power down
+ * @return mask of all the cores that have acknowledged the power down
+ */
+mali_pmm_core_mask pmm_cores_set_down_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
+
+/** @brief Set the cores that have acknowledged a pending power up
+ *
+ * Updates which cores have acknowledged the pending power up and are now
+ * fully powered and ready to run jobs
+ *
+ * @param pmm internal PMM state
+ * @param cores mask of cores that have acknowledged the pending power up
+ * @return mask of all the cores that have acknowledged the power up
+ */
+mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores );
+
+
+/** @brief Tries to reset the PMM and PMU hardware to a known state after any fatal issues
+ *
+ * This will try and make all the cores powered up and reset the PMM state
+ * to its initial state after core registration - all cores powered but not
+ * pending or active.
+ * All events in the event queues will be thrown away.
+ *
+ * @note: Any pending power down will be cancelled including the OS calling for power down
+ */
+void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm );
+
+/** @brief Save the OS specific data for an OS power up/down event
+ *
+ * @param pmm internal PMM state
+ * @param data OS specific event data
+ */
+void pmm_save_os_event_data(_mali_pmm_internal_state_t *pmm, mali_pmm_message_data data);
+
+/** @brief Retrieve the OS specific data for an OS power up/down event
+ *
+ * This will clear the stored OS data, as well as return it.
+ *
+ * @param pmm internal PMM state
+ * @return OS specific event data that was saved previously
+ */
+mali_pmm_message_data pmm_retrieve_os_event_data(_mali_pmm_internal_state_t *pmm);
+
+
+/** @brief Get a human readable name for the cores in a core mask
+ *
+ * @param core the core mask
+ * @return string containing a name relating to the given core mask
+ */
+const char *pmm_trace_get_core_name( mali_pmm_core_mask core );
+
+/** @} */ /* End group pmmapi_state */
+/** @} */ /* End group pmmapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PMM_STATE_H__ */
diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_system.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_system.h
new file mode 100644
index 00000000000..1be5b847c88
--- /dev/null
+++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_system.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_pmm_system.h
+ * Defines the power management module system functions
+ */
+
+#ifndef __MALI_PMM_SYSTEM_H__
+#define __MALI_PMM_SYSTEM_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @addtogroup pmmapi Power Management Module APIs
+ *
+ * @{
+ *
+ * @defgroup pmmapi_system Power Management Module System Functions
+ *
+ * @{
+ */
+
+extern struct mali_kernel_subsystem mali_subsystem_pmm;
+
+/** @brief Register a core with the PMM, which will power up
+ * the core
+ *
+ * @param core the core to register with the PMM
+ * @return error if the core cannot be powered up
+ */
+_mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core );
+
+/** @brief Unregister a core with the PMM
+ *
+ * @param core the core to unregister with the PMM
+ */
+void malipmm_core_unregister( mali_pmm_core_id core );
+
+/** @brief Acknowledge that a power down is okay to happen
+ *
+ * A core should not be running a job, or be in the idle queue when this
+ * is called.
+ *
+ * @param core the core that can now be powered down
+ */
+void malipmm_core_power_down_okay( mali_pmm_core_id core );
+
+/** @} */ /* End group pmmapi_system */
+/** @} */ /* End group pmmapi */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_PMM_H__ */
diff --git a/drivers/gpu/arm/mali/include/cinstr/mali_cinstr_profiling_events_m200.h b/drivers/gpu/arm/mali/include/cinstr/mali_cinstr_profiling_events_m200.h
new file mode 100644
index 00000000000..49d982ec52c
--- /dev/null
+++ b/drivers/gpu/arm/mali/include/cinstr/mali_cinstr_profiling_events_m200.h
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+#ifndef _CINSTR_PROFILING_EVENTS_M200_H_
+#define _CINSTR_PROFILING_EVENTS_M200_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
+} 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
+ */
+typedef enum
+{
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0,
+ MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1,
+} 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,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT= 27,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC= 28,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP = 29,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE = 30,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL = 31,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS = 32,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE= 33,
+} 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,
+} cinstr_profiling_event_reason_single_gpu_t;
+
+#endif /*_CINSTR_PROFILING_EVENTS_M200_H_*/
diff --git a/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h
new file mode 100644
index 00000000000..e9e5e55a082
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/mali/linux/mali_device_pause_resume.c b/drivers/gpu/arm/mali/linux/mali_device_pause_resume.c
new file mode 100644
index 00000000000..da9cdd99d27
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_device_pause_resume.c
@@ -0,0 +1,72 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_device_pause_resume.c
+ * Implementation of the Mali pause/resume functionality
+ */
+#if USING_MALI_PMM
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_platform.h"
+#include "mali_linux_pm.h"
+#include "mali_device_pause_resume.h"
+#include "mali_pmm.h"
+#include "mali_kernel_license.h"
+#ifdef CONFIG_PM
+#if MALI_LICENSE_IS_GPL
+
+/* Mali Pause Resume APIs */
+int mali_dev_pause()
+{
+ int err = 0;
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+ if ((mali_dvfs_device_state == _MALI_DEVICE_SUSPEND)
+ || (mali_device_state == _MALI_DEVICE_SUSPEND) )
+ {
+ err = -EPERM;
+ }
+ if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) && (!err))
+ {
+ mali_device_suspend(MALI_PMM_EVENT_DVFS_PAUSE, &dvfs_pm_thread);
+ mali_dvfs_device_state = _MALI_DEVICE_SUSPEND;
+ }
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+}
+
+EXPORT_SYMBOL(mali_dev_pause);
+
+int mali_dev_resume()
+{
+ int err = 0;
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+ if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME)
+ || (mali_device_state == _MALI_DEVICE_SUSPEND) )
+ {
+ err = -EPERM;
+ }
+ if (!err)
+ {
+ mali_device_resume(MALI_PMM_EVENT_DVFS_RESUME, &dvfs_pm_thread);
+ mali_dvfs_device_state = _MALI_DEVICE_RESUME;
+ }
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+}
+
+EXPORT_SYMBOL(mali_dev_resume);
+
+#endif /* MALI_LICENSE_IS_GPL */
+#endif /* CONFIG_PM */
+#endif /* USING_MALI_PMM */
diff --git a/drivers/gpu/arm/mali/linux/mali_device_pause_resume.h b/drivers/gpu/arm/mali/linux/mali_device_pause_resume.h
new file mode 100644
index 00000000000..c770cb6f532
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_device_pause_resume.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_DEVICE_PAUSE_RESUME_H__
+#define __MALI_DEVICE_PAUSE_RESUME_H__
+
+#if USING_MALI_PMM
+int mali_dev_pause(void);
+int mali_dev_resume(void);
+#endif /* USING_MALI_PMM */
+
+#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h b/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h
new file mode 100644
index 00000000000..5386566010a
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_IOCTL_H__
+#define __MALI_KERNEL_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_GET_SYSTEM_INFO_SIZE _IOR (MALI_IOC_CORE_BASE, _MALI_UK_GET_SYSTEM_INFO_SIZE, _mali_uk_get_system_info_s *)
+#define MALI_IOC_GET_SYSTEM_INFO _IOR (MALI_IOC_CORE_BASE, _MALI_UK_GET_SYSTEM_INFO, _mali_uk_get_system_info_s *)
+#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_POST_NOTIFICATION _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_POST_NOTIFICATION, _mali_uk_post_notification_s *)
+#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, _mali_uk_get_big_block_s *)
+#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, _mali_uk_free_big_block_s *)
+#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _mali_uk_init_mem_s *)
+#define MALI_IOC_MEM_TERM _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_TERM_MEM, _mali_uk_term_mem_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_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_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_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_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_ABORT_JOB _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_ABORT_JOB, _mali_uk_pp_abort_job_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_ABORT_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_ABORT_JOB, _mali_uk_gp_abort_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_profiling_get_config_s *)
+#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_IOCTL_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali/linux/mali_kernel_linux.c
new file mode 100644
index 00000000000..6d108ff7a37
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_linux.c
@@ -0,0 +1,494 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 mananger definitions */
+#include <linux/device.h>
+
+/* the mali kernel subsystem types */
+#include "mali_kernel_subsystem.h"
+
+/* A memory subsystem always exists, so no need to conditionally include it */
+#include "mali_kernel_common.h"
+#include "mali_kernel_session_manager.h"
+#include "mali_kernel_core.h"
+
+#include "mali_osk.h"
+#include "mali_kernel_linux.h"
+#include "mali_ukk.h"
+#include "mali_kernel_ioctl.h"
+#include "mali_ukk_wrappers.h"
+#include "mali_kernel_pm.h"
+
+#include "mali_kernel_sysfs.h"
+
+/* */
+#include "mali_kernel_license.h"
+
+/* Streamline support for the Mali driver */
+#if defined(CONFIG_TRACEPOINTS)
+/* 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");
+
+/* By default the module uses any available major, but it's possible to set it at load time to a specific number */
+int mali_major = 244;
+module_param(mali_major, int, S_IRUGO); /* r--r--r-- */
+MODULE_PARM_DESC(mali_major, "Device major number");
+
+int mali_benchmark = 0;
+module_param(mali_benchmark, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); /* rw-rw-r-- */
+MODULE_PARM_DESC(mali_benchmark, "Bypass Mali hardware when non-zero");
+
+extern int mali_hang_check_interval;
+module_param(mali_hang_check_interval, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mali_hang_check_interval, "Interval at which to check for progress after the hw watchdog has been triggered");
+
+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");
+
+#if defined(USING_MALI400_L2_CACHE)
+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");
+#endif
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+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
+
+static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
+
+/* the mali device */
+static struct mali_dev device;
+
+
+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_mmap(struct file * filp, struct vm_area_struct * vma);
+
+/* Linux char file operations provided by the Mali module */
+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
+};
+
+
+int mali_driver_init(void)
+{
+ int err;
+#if USING_MALI_PMM
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+ err = _mali_dev_platform_register();
+ if (err)
+ {
+ return err;
+ }
+#endif
+#endif
+#endif
+ err = mali_kernel_constructor();
+ if (_MALI_OSK_ERR_OK != err)
+ {
+#if USING_MALI_PMM
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+ _mali_dev_platform_unregister();
+#endif
+#endif
+#endif
+ MALI_PRINT(("Failed to initialize driver (error %d)\n", err));
+ return -EFAULT;
+ }
+
+ /* print build options */
+// MALI_DEBUG_PRINT(2, ("%s\n", __malidrv_build_info()));
+
+ return 0;
+}
+
+void mali_driver_exit(void)
+{
+ mali_kernel_destructor();
+
+#if MALI_LICENSE_IS_GPL
+#if USING_MALI_PMM
+#ifdef CONFIG_PM
+ _mali_dev_platform_unregister();
+#endif
+#endif
+
+ flush_workqueue(mali_wq);
+ destroy_workqueue(mali_wq);
+ mali_wq = NULL;
+#endif
+}
+
+/* called from _mali_osk_init */
+int initialize_kernel_device(void)
+{
+ int err;
+ dev_t dev = 0;
+ if (0 == mali_major)
+ {
+ /* auto select a major */
+ err = alloc_chrdev_region(&dev, 0/*first minor*/, 1/*count*/, mali_dev_name);
+ mali_major = MAJOR(dev);
+ }
+ else
+ {
+ /* use load time defined major number */
+ dev = MKDEV(mali_major, 0);
+ err = register_chrdev_region(dev, 1/*count*/, mali_dev_name);
+ }
+
+ if (err)
+ {
+ goto init_chrdev_err;
+ }
+
+ memset(&device, 0, sizeof(device));
+
+ /* initialize our char dev data */
+ cdev_init(&device.cdev, &mali_fops);
+ device.cdev.owner = THIS_MODULE;
+ device.cdev.ops = &mali_fops;
+
+ /* register char dev with the kernel */
+ err = cdev_add(&device.cdev, dev, 1/*count*/);
+ if (err)
+ {
+ goto init_cdev_err;
+ }
+
+ err = mali_sysfs_register(&device, dev, mali_dev_name);
+ if (err)
+ {
+ goto init_sysfs_err;
+ }
+
+ /* Success! */
+ return 0;
+
+init_sysfs_err:
+ cdev_del(&device.cdev);
+init_cdev_err:
+ unregister_chrdev_region(dev, 1/*count*/);
+init_chrdev_err:
+ return err;
+}
+
+/* called from _mali_osk_term */
+void terminate_kernel_device(void)
+{
+ dev_t dev = MKDEV(mali_major, 0);
+
+ mali_sysfs_unregister(&device, dev, mali_dev_name);
+
+ /* unregister char device */
+ cdev_del(&device.cdev);
+ /* free major */
+ unregister_chrdev_region(dev, 1/*count*/);
+ return;
+}
+
+/** @note munmap handler is done by vma close handler */
+static int mali_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+ struct mali_session_data * session_data;
+ _mali_uk_mem_mmap_s args = {0, };
+
+ session_data = (struct mali_session_data *)filp->private_data;
+ if (NULL == session_data)
+ {
+ MALI_PRINT_ERROR(("mmap called without any session data available\n"));
+ return -EFAULT;
+ }
+
+ MALI_DEBUG_PRINT(3, ("MMap() handler: start=0x%08X, phys=0x%08X, size=0x%08X\n", (unsigned int)vma->vm_start, (unsigned int)(vma->vm_pgoff << PAGE_SHIFT), (unsigned int)(vma->vm_end - vma->vm_start)) );
+
+ /* Re-pack the arguments that mmap() packed for us */
+ args.ctx = session_data;
+ args.phys_addr = vma->vm_pgoff << PAGE_SHIFT;
+ args.size = vma->vm_end - vma->vm_start;
+ args.ukk_private = vma;
+
+ /* Call the common mmap handler */
+ MALI_CHECK(_MALI_OSK_ERR_OK ==_mali_ukk_mem_mmap( &args ), -EFAULT);
+
+ return 0;
+}
+
+static int mali_open(struct inode *inode, struct file *filp)
+{
+ struct mali_session_data * session_data;
+ _mali_osk_errcode_t err;
+
+ /* input validation */
+ if (0 != MINOR(inode->i_rdev)) 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 (0 != MINOR(inode->i_rdev)) 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_GET_SYSTEM_INFO_SIZE:
+ err = get_system_info_size_wrapper(session_data, (_mali_uk_get_system_info_size_s __user *)arg);
+ break;
+
+ case MALI_IOC_GET_SYSTEM_INFO:
+ err = get_system_info_wrapper(session_data, (_mali_uk_get_system_info_s __user *)arg);
+ break;
+
+ 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;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ 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:
+ err = profiling_get_config_wrapper(session_data, (_mali_uk_profiling_get_config_s __user *)arg);
+ break;
+#endif
+
+ case MALI_IOC_MEM_INIT:
+ err = mem_init_wrapper(session_data, (_mali_uk_init_mem_s __user *)arg);
+ break;
+
+ case MALI_IOC_MEM_TERM:
+ err = mem_term_wrapper(session_data, (_mali_uk_term_mem_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;
+
+ case MALI_IOC_MEM_GET_BIG_BLOCK:
+ err = mem_get_big_block_wrapper(filp, (_mali_uk_get_big_block_s __user *)arg);
+ break;
+
+ case MALI_IOC_MEM_FREE_BIG_BLOCK:
+ err = mem_free_big_block_wrapper(session_data, (_mali_uk_free_big_block_s __user *)arg);
+ break;
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+
+ 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
+
+ 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_ABORT_JOB:
+ err = pp_abort_job_wrapper(session_data, (_mali_uk_pp_abort_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_GP2_START_JOB:
+ err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
+ break;
+
+ case MALI_IOC_GP2_ABORT_JOB:
+ err = gp_abort_job_wrapper(session_data, (_mali_uk_gp_abort_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;
+
+ default:
+ MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg));
+ err = -ENOTTY;
+ };
+
+ return err;
+}
+
+
+module_init(mali_driver_init);
+module_exit(mali_driver_exit);
+
+MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
+MODULE_AUTHOR("ARM Ltd.");
+MODULE_VERSION(SVN_REV_STRING);
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_linux.h b/drivers/gpu/arm/mali/linux/mali_kernel_linux.h
new file mode 100644
index 00000000000..b63baa90b7f
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_linux.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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.h"
+
+struct mali_dev
+{
+ struct cdev cdev;
+#if MALI_LICENSE_IS_GPL
+ struct class * mali_class;
+#endif
+};
+
+#if MALI_LICENSE_IS_GPL
+/* Defined in mali_osk_irq.h */
+extern struct workqueue_struct * mali_wq;
+#endif
+
+_mali_osk_errcode_t initialize_kernel_device(void);
+void terminate_kernel_device(void);
+
+void mali_osk_low_level_mem_init(void);
+void mali_osk_low_level_mem_term(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_LINUX_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_pm.c b/drivers/gpu/arm/mali/linux/mali_kernel_pm.c
new file mode 100644
index 00000000000..ea92368ccae
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_pm.c
@@ -0,0 +1,645 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_kernel_pm.c
+ * Implementation of the Linux Power Management for Mali GPU kernel driver
+ */
+
+#include <linux/module.h>
+#if USING_MALI_PMM
+#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 <asm/current.h>
+#include <linux/suspend.h>
+
+#include "mali_platform.h"
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+#include "mali_pmm.h"
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_license.h"
+#include "mali_kernel_pm.h"
+#include "mali_device_pause_resume.h"
+#include "mali_linux_pm.h"
+
+#if MALI_GPU_UTILIZATION
+#include "mali_kernel_utilization.h"
+#endif /* MALI_GPU_UTILIZATION */
+
+#if MALI_POWER_MGMT_TEST_SUITE
+#ifdef CONFIG_PM
+#include "mali_linux_pm_testsuite.h"
+#include "mali_platform_pmu_internal_testing.h"
+unsigned int pwr_mgmt_status_reg = 0;
+#endif /* CONFIG_PM */
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+
+static int is_os_pmm_thread_waiting = 0;
+
+/* kernel should be configured with power management support */
+#ifdef CONFIG_PM
+
+#if MALI_LICENSE_IS_GPL
+
+/* Linux kernel major version */
+#define LINUX_KERNEL_MAJOR_VERSION 2
+
+/* Linux kernel minor version */
+#define LINUX_KERNEL_MINOR_VERSION 6
+
+/* Linux kernel development version */
+#define LINUX_KERNEL_DEVELOPMENT_VERSION 29
+
+#ifdef CONFIG_PM_DEBUG
+static const char* const mali_states[_MALI_MAX_DEBUG_OPERATIONS] = {
+ [_MALI_DEVICE_SUSPEND] = "suspend",
+ [_MALI_DEVICE_RESUME] = "resume",
+ [_MALI_DVFS_PAUSE_EVENT] = "dvfs_pause",
+ [_MALI_DVFS_RESUME_EVENT] = "dvfs_resume",
+};
+
+#endif /* CONFIG_PM_DEBUG */
+
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy);
+
+static struct notifier_block mali_pwr_notif_block = {
+ .notifier_call = mali_pwr_suspend_notifier
+};
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+/* Power management thread pointer */
+struct task_struct *pm_thread;
+
+/* dvfs power management thread */
+struct task_struct *dvfs_pm_thread;
+
+/* is wake up needed */
+short is_wake_up_needed = 0;
+int timeout_fired = 2;
+unsigned int is_mali_pmm_testsuite_enabled = 0;
+
+_mali_device_power_states mali_device_state = _MALI_DEVICE_RESUME;
+_mali_device_power_states mali_dvfs_device_state = _MALI_DEVICE_RESUME;
+_mali_osk_lock_t *lock;
+
+#if MALI_POWER_MGMT_TEST_SUITE
+
+const char* const mali_pmm_recording_events[_MALI_DEVICE_MAX_PMM_EVENTS] = {
+ [_MALI_DEVICE_PMM_TIMEOUT_EVENT] = "timeout",
+ [_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS] = "job_scheduling",
+ [_MALI_DEVICE_PMM_REGISTERED_CORES] = "cores",
+
+};
+
+unsigned int mali_timeout_event_recording_on = 0;
+unsigned int mali_job_scheduling_events_recording_on = 0;
+unsigned int is_mali_pmu_present = 0;
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+
+/* Function prototypes */
+static int mali_pm_probe(struct platform_device *pdev);
+static int mali_pm_remove(struct platform_device *pdev);
+
+/* Mali device suspend function */
+static int mali_pm_suspend(struct device *dev);
+
+/* Mali device resume function */
+static int mali_pm_resume(struct device *dev);
+
+/* Run time suspend and resume functions */
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+static int mali_device_runtime_suspend(struct device *dev);
+static int mali_device_runtime_resume(struct device *dev);
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+/* OS suspend and resume callbacks */
+#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#ifndef CONFIG_PM_RUNTIME
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+static int mali_pm_os_suspend(struct platform_device *pdev, pm_message_t state);
+#else
+static int mali_pm_os_suspend(struct device *dev);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+static int mali_pm_os_resume(struct platform_device *pdev);
+#else
+static int mali_pm_os_resume(struct device *dev);
+#endif
+#endif /* CONFIG_PM_RUNTIME */
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+
+/* OS Hibernation suspend callback */
+static int mali_pm_os_suspend_on_hibernation(struct device *dev);
+
+/* OS Hibernation resume callback */
+static int mali_pm_os_resume_on_hibernation(struct device *dev);
+
+static void _mali_release_pm(struct device* device);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+static const struct dev_pm_ops mali_dev_pm_ops = {
+
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ .runtime_suspend = mali_device_runtime_suspend,
+ .runtime_resume = mali_device_runtime_resume,
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifndef CONFIG_PM_RUNTIME
+#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ .suspend = mali_pm_os_suspend,
+ .resume = mali_pm_os_resume,
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+ .freeze = mali_pm_os_suspend_on_hibernation,
+ .poweroff = mali_pm_os_suspend_on_hibernation,
+ .thaw = mali_pm_os_resume_on_hibernation,
+ .restore = mali_pm_os_resume_on_hibernation,
+};
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+struct pm_ext_ops mali_pm_operations = {
+ .base = {
+ .freeze = mali_pm_os_suspend_on_hibernation,
+ .thaw = mali_pm_os_resume_on_hibernation,
+ .poweroff = mali_pm_os_resume_on_hibernation,
+ .restore = mali_pm_os_resume_on_hibernation,
+ },
+};
+#endif
+
+static struct platform_driver mali_plat_driver = {
+ .probe = mali_pm_probe,
+ .remove = mali_pm_remove,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+#ifndef CONFIG_PM_RUNTIME
+#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ .suspend = mali_pm_os_suspend,
+ .resume = mali_pm_os_resume,
+#endif /* CONFIG_PM_RUNTIME */
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+ .pm = &mali_pm_operations,
+#endif
+
+ .driver = {
+ .name = "mali_dev",
+ .owner = THIS_MODULE,
+ .bus = &platform_bus_type,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+ .pm = &mali_dev_pm_ops,
+#endif
+ },
+};
+
+/* Mali GPU platform device */
+struct platform_device mali_gpu_device = {
+ .name = "mali_dev",
+ .id = 0,
+ .dev.release = _mali_release_pm
+};
+
+/** This function is called when platform device is unregistered. This function
+ * is necessary when the platform device is unregistered.
+ */
+static void _mali_release_pm(struct device *device)
+{
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI Platform device removed\n" ));
+}
+
+#if MALI_POWER_MGMT_TEST_SUITE
+void mali_is_pmu_present(void)
+{
+ int temp = 0;
+ temp = pmu_get_power_up_down_info();
+ if (4095 == temp)
+ {
+ is_mali_pmu_present = 0;
+ }
+ else
+ {
+ is_mali_pmu_present = 1;
+ }
+}
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+#endif /* MALI_LICENSE_IS_GPL */
+
+#if MALI_LICENSE_IS_GPL
+
+static int mali_wait_for_power_management_policy_event(void)
+{
+ int err = 0;
+ for (; ;)
+ {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (signal_pending(current))
+ {
+ err = -EINTR;
+ break;
+ }
+ if (is_wake_up_needed == 1)
+ {
+ break;
+ }
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+ is_wake_up_needed =0;
+ return err;
+}
+
+/** This function is invoked when mali device is suspended
+ */
+int mali_device_suspend(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
+{
+ int err = 0;
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ event_id,
+ timeout_fired};
+ *pwr_mgmt_thread = current;
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being suspended\n" ));
+ _mali_ukk_pmm_event_message(&event);
+ is_os_pmm_thread_waiting = 1;
+ err = mali_wait_for_power_management_policy_event();
+ is_os_pmm_thread_waiting = 0;
+ return err;
+}
+
+/** This function is called when Operating system wants to power down
+ * the mali GPU device.
+ */
+static int mali_pm_suspend(struct device *dev)
+{
+ int err = 0;
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+#if MALI_GPU_UTILIZATION
+ mali_utilization_suspend();
+#endif /* MALI_GPU_UTILIZATION */
+ if ((mali_device_state == _MALI_DEVICE_SUSPEND))
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+ }
+ err = mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread);
+ mali_device_state = _MALI_DEVICE_SUSPEND;
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+}
+
+#ifndef CONFIG_PM_RUNTIME
+#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+static int mali_pm_os_suspend(struct platform_device *pdev, pm_message_t state)
+#else
+static int mali_pm_os_suspend(struct device *dev)
+#endif
+{
+ int err = 0;
+ err = mali_pm_suspend(NULL);
+ return err;
+}
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy)
+{
+ int err = 0;
+ switch (event)
+ {
+ case PM_SUSPEND_PREPARE:
+ err = mali_pm_suspend(NULL);
+ break;
+
+ case PM_POST_SUSPEND:
+ err = mali_pm_resume(NULL);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+/** This function is called when mali GPU device is to be resumed.
+ */
+int mali_device_resume(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
+{
+ int err = 0;
+ _mali_uk_pmm_message_s event = {
+ NULL,
+ event_id,
+ timeout_fired};
+ *pwr_mgmt_thread = current;
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being resumed\n" ));
+ _mali_ukk_pmm_event_message(&event);
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power up event is scheduled\n" ));
+ is_os_pmm_thread_waiting = 1;
+ err = mali_wait_for_power_management_policy_event();
+ is_os_pmm_thread_waiting = 0;
+ return err;
+}
+
+/** This function is called when mali GPU device is to be resumed
+ */
+
+static int mali_pm_resume(struct device *dev)
+{
+ int err = 0;
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+ if (mali_device_state == _MALI_DEVICE_RESUME)
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+ }
+ err = mali_device_resume(MALI_PMM_EVENT_OS_POWER_UP, &pm_thread);
+ mali_device_state = _MALI_DEVICE_RESUME;
+ mali_dvfs_device_state = _MALI_DEVICE_RESUME;
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return err;
+}
+
+#ifndef CONFIG_PM_RUNTIME
+#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+static int mali_pm_os_resume(struct platform_device *pdev)
+#else
+static int mali_pm_os_resume(struct device *dev)
+#endif
+{
+ int err = 0;
+ err = mali_pm_resume(NULL);
+ return err;
+}
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+static int mali_pm_os_suspend_on_hibernation(struct device *dev)
+{
+ int err = 0;
+ err = mali_pm_suspend(NULL);
+ return err;
+}
+
+static int mali_pm_os_resume_on_hibernation(struct device *dev)
+{
+ int err = 0;
+ err = mali_pm_resume(NULL);
+ return err;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+/** This function is called when runtime suspend of mali device is required.
+ */
+static int mali_device_runtime_suspend(struct device *dev)
+{
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time suspended \n" ));
+ return 0;
+}
+
+/** This function is called when runtime resume of mali device is required.
+ */
+static int mali_device_runtime_resume(struct device *dev)
+{
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time Resumed \n" ));
+ return 0;
+}
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_DEBUG
+
+/** This function is used for debugging purposes when the user want to see
+ * which power management operations are supported for
+ * mali device.
+ */
+static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *str = buf;
+#if !MALI_POWER_MGMT_TEST_SUITE
+ int pm_counter = 0;
+ for (pm_counter = 0; pm_counter<_MALI_MAX_DEBUG_OPERATIONS; pm_counter++)
+ {
+ str += sprintf(str, "%s ", mali_states[pm_counter]);
+ }
+#else
+ str += sprintf(str, "%d ",pwr_mgmt_status_reg);
+#endif
+ if (str != buf)
+ {
+ *(str-1) = '\n';
+ }
+ return (str-buf);
+}
+
+/** This function is called when user wants to suspend the mali GPU device in order
+ * to simulate the power up and power down events.
+ */
+static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int err = 0;
+
+#if MALI_POWER_MGMT_TEST_SUITE
+ int test_flag_dvfs = 0;
+ pwr_mgmt_status_reg = 0;
+ mali_is_pmu_present();
+
+#endif
+ if (!strncmp(buf,mali_states[_MALI_DEVICE_SUSPEND],strlen(mali_states[_MALI_DEVICE_SUSPEND])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI suspend Power operation is scheduled\n" ));
+ err = mali_pm_suspend(NULL);
+ }
+
+#if MALI_POWER_MGMT_TEST_SUITE
+ else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_REGISTERED_CORES],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_REGISTERED_CORES])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Device get number of registerd cores\n" ));
+ pwr_mgmt_status_reg = _mali_pmm_cores_list();
+ return count;
+ }
+ else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_TIMEOUT_EVENT],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_TIMEOUT_EVENT])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI timeout event recording is enabled\n" ));
+ mali_timeout_event_recording_on = 1;
+ }
+ else if (!strncmp(buf,mali_pmm_recording_events[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS],strlen(mali_pmm_recording_events[_MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Job scheduling events recording is enabled\n" ));
+ mali_job_scheduling_events_recording_on = 1;
+ }
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+
+ else if (!strncmp(buf,mali_states[_MALI_DEVICE_RESUME],strlen(mali_states[_MALI_DEVICE_RESUME])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" ));
+ err = mali_pm_resume(NULL);
+ }
+ else if (!strncmp(buf,mali_states[_MALI_DVFS_PAUSE_EVENT],strlen(mali_states[_MALI_DVFS_PAUSE_EVENT])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Pause Power operation is scheduled\n" ));
+ err = mali_dev_pause();
+#if MALI_POWER_MGMT_TEST_SUITE
+ test_flag_dvfs = 1;
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+ }
+ else if (!strncmp(buf,mali_states[_MALI_DVFS_RESUME_EVENT],strlen(mali_states[_MALI_DVFS_RESUME_EVENT])))
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Resume Power operation is scheduled\n" ));
+ err = mali_dev_resume();
+#if MALI_POWER_MGMT_TEST_SUITE
+ test_flag_dvfs = 1;
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: Invalid Power Mode Operation selected\n" ));
+ }
+#if MALI_POWER_MGMT_TEST_SUITE
+ if (test_flag_dvfs == 1)
+ {
+ if (err)
+ {
+ pwr_mgmt_status_reg = 2;
+ }
+ else
+ {
+ pwr_mgmt_status_reg = 1;
+ }
+ }
+ else
+ {
+ if (1 == is_mali_pmu_present)
+ {
+ pwr_mgmt_status_reg = pmu_get_power_up_down_info();
+ }
+ }
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+ return count;
+}
+
+/* Device attribute file */
+static DEVICE_ATTR(file, 0644, show_file, store_file);
+#endif /* CONFIG_PM_DEBUG */
+
+static int mali_pm_remove(struct platform_device *pdev)
+{
+#ifdef CONFIG_PM_DEBUG
+ device_remove_file(&mali_gpu_device.dev, &dev_attr_file);
+#endif /* CONFIG_PM_DEBUG */
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ pm_runtime_disable(&pdev->dev);
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+ return 0;
+}
+
+/** This function is called when the device is probed */
+static int mali_pm_probe(struct platform_device *pdev)
+{
+#ifdef CONFIG_PM_DEBUG
+ int err;
+ err = device_create_file(&mali_gpu_device.dev, &dev_attr_file);
+ if (err)
+ {
+ MALI_DEBUG_PRINT(4, ("PMMDEBUG: Error in creating device file\n" ));
+ }
+#endif /* CONFIG_PM_DEBUG */
+ return 0;
+}
+
+/** This function is called when Mali GPU device is initialized
+ */
+int _mali_dev_platform_register(void)
+{
+ int err;
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ set_mali_parent_power_domain((void *)&mali_gpu_device);
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ err = register_pm_notifier(&mali_pwr_notif_block);
+ if (err)
+ {
+ return err;
+ }
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+ err = platform_device_register(&mali_gpu_device);
+ lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)( _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 0);
+ if (!err)
+ {
+ err = platform_driver_register(&mali_plat_driver);
+ if (err)
+ {
+ _mali_osk_lock_term(lock);
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ unregister_pm_notifier(&mali_pwr_notif_block);
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+ platform_device_unregister(&mali_gpu_device);
+ }
+ }
+ return err;
+}
+
+/** This function is called when Mali GPU device is unloaded
+ */
+void _mali_dev_platform_unregister(void)
+{
+ _mali_osk_lock_term(lock);
+
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ unregister_pm_notifier(&mali_pwr_notif_block);
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+
+ platform_driver_unregister(&mali_plat_driver);
+ platform_device_unregister(&mali_gpu_device);
+}
+
+int mali_get_ospmm_thread_state(void)
+{
+ return is_os_pmm_thread_waiting;
+}
+
+#endif /* MALI_LICENSE_IS_GPL */
+#endif /* CONFIG_PM */
+
+#if MALI_STATE_TRACKING
+u32 mali_pmm_dump_os_thread_state( char *buf, u32 size )
+{
+ return snprintf(buf, size, "OSPMM: OS PMM thread is waiting: %s\n", is_os_pmm_thread_waiting ? "true" : "false");
+}
+#endif /* MALI_STATE_TRACKING */
+#endif /* USING_MALI_PMM */
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_pm.h b/drivers/gpu/arm/mali/linux/mali_kernel_pm.h
new file mode 100644
index 00000000000..7ee1572a534
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_pm.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_PM_H__
+#define __MALI_KERNEL_PM_H__
+
+#ifdef USING_MALI_PMM
+int _mali_dev_platform_register(void);
+void _mali_dev_platform_unregister(void);
+#endif /* USING_MALI_PMM */
+
+#endif /* __MALI_KERNEL_PM_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c
new file mode 100644
index 00000000000..2a61a87e6f3
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c
@@ -0,0 +1,402 @@
+/**
+ * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+/**
+ * @file mali_kernel_sysfs.c
+ * Implementation of some sysfs data exports
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include "mali_kernel_license.h"
+#include "mali_kernel_linux.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/slab.h>
+#include "mali_kernel_subsystem.h"
+#include "mali_kernel_sysfs.h"
+#include "mali_osk_profiling.h"
+
+static struct dentry *mali_debugfs_dir = NULL;
+
+#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 MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+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_osk_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_osk_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_osk_profiling_have_recording())
+ {
+ if (_MALI_OSK_ERR_OK != _mali_osk_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_osk_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_osk_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_osk_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_osk_profiling_have_recording())
+ {
+ return NULL;
+ }
+
+ /* check if the next entry actually is avaiable */
+ if (_mali_osk_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_osk_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 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 ssize_t profiling_proc_default_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ char buf[64];
+ int r;
+
+ r = sprintf(buf, "%u\n", _mali_osk_profiling_get_default_enable_state() ? 1 : 0);
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t profiling_proc_default_enable_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;
+ }
+
+ _mali_osk_profiling_set_default_enable_state(val != 0 ? MALI_TRUE : MALI_FALSE);
+
+ *ppos += cnt;
+ return cnt;
+}
+
+static const struct file_operations profiling_proc_default_enable_fops = {
+ .owner = THIS_MODULE,
+ .read = profiling_proc_default_enable_read,
+ .write = profiling_proc_default_enable_write,
+};
+#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,
+};
+
+int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+{
+ int err = 0;
+ struct device * mdev;
+
+ device->mali_class = class_create(THIS_MODULE, mali_dev_name);
+ if (IS_ERR(device->mali_class))
+ {
+ err = PTR_ERR(device->mali_class);
+ goto init_class_err;
+ }
+ mdev = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name);
+ if (IS_ERR(mdev))
+ {
+ err = PTR_ERR(mdev);
+ goto init_mdev_err;
+ }
+
+ 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 */
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ struct dentry *mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
+ if (mali_profiling_dir != NULL)
+ {
+ struct dentry *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, NULL, &profiling_proc_default_enable_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);
+ }
+#endif
+
+#if MALI_STATE_TRACKING
+ debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
+#endif
+
+ debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
+ }
+ }
+
+ /* Success! */
+ return 0;
+
+ /* Error handling */
+init_mdev_err:
+ class_destroy(device->mali_class);
+init_class_err:
+
+ return err;
+}
+
+int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+{
+ if(NULL != mali_debugfs_dir)
+ {
+ debugfs_remove_recursive(mali_debugfs_dir);
+ }
+ device_destroy(device->mali_class, dev);
+ class_destroy(device->mali_class);
+
+ return 0;
+}
+
+#else
+
+/* Dummy implementations for when the sysfs API isn't available. */
+
+int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+{
+ return 0;
+}
+
+int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
+{
+ return 0;
+}
+
+
+#endif
diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h
new file mode 100644
index 00000000000..26a60745ffc
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_KERNEL_SYSFS_H__
+#define __MALI_KERNEL_SYSFS_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define MALI_PROC_DIR "driver/mali"
+
+int mali_sysfs_register(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name);
+
+int mali_sysfs_unregister(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_KERNEL_LINUX_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_linux_pm.h b/drivers/gpu/arm/mali/linux/mali_linux_pm.h
new file mode 100644
index 00000000000..ad69853333e
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_linux_pm.h
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MALI_LINUX_PM_H__
+#define __MALI_LINUX_PM_H__
+
+#if USING_MALI_PMM
+
+#ifdef CONFIG_PM
+/* Number of power states supported for making power up and down */
+typedef enum
+{
+ _MALI_DEVICE_SUSPEND, /* Suspend */
+ _MALI_DEVICE_RESUME, /* Resume */
+ _MALI_DEVICE_MAX_POWER_STATES, /* Maximum power states */
+} _mali_device_power_states;
+
+/* Number of DVFS events */
+typedef enum
+{
+ _MALI_DVFS_PAUSE_EVENT = _MALI_DEVICE_MAX_POWER_STATES, /* DVFS Pause event */
+ _MALI_DVFS_RESUME_EVENT, /* DVFS Resume event */
+ _MALI_MAX_DEBUG_OPERATIONS,
+} _mali_device_dvfs_events;
+
+extern _mali_device_power_states mali_device_state;
+extern _mali_device_power_states mali_dvfs_device_state;
+extern _mali_osk_lock_t *lock;
+extern short is_wake_up_needed;
+extern int timeout_fired;
+extern struct platform_device mali_gpu_device;
+
+/* dvfs pm thread */
+extern struct task_struct *dvfs_pm_thread;
+
+/* Power management thread */
+extern struct task_struct *pm_thread;
+
+int mali_device_suspend(u32 event_id, struct task_struct **pwr_mgmt_thread);
+int mali_device_resume(u32 event_id, struct task_struct **pwr_mgmt_thread);
+int mali_get_ospmm_thread_state(void);
+
+#endif /* CONFIG_PM */
+#endif /* USING_MALI_PMM */
+#endif /* __MALI_LINUX_PM_H___ */
diff --git a/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h b/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h
new file mode 100644
index 00000000000..e88ce94281f
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __MALI_LINUX_PM_TESTSUITE_H__
+#define __MALI_LINUX_PM_TESTSUITE_H__
+
+#if USING_MALI_PMM
+#if MALI_POWER_MGMT_TEST_SUITE
+#ifdef CONFIG_PM
+
+typedef enum
+{
+ _MALI_DEVICE_PMM_TIMEOUT_EVENT,
+ _MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS,
+ _MALI_DEVICE_PMM_REGISTERED_CORES,
+ _MALI_DEVICE_MAX_PMM_EVENTS
+
+} _mali_device_pmm_recording_events;
+
+extern unsigned int mali_timeout_event_recording_on;
+extern unsigned int mali_job_scheduling_events_recording_on;
+extern unsigned int pwr_mgmt_status_reg;
+extern unsigned int is_mali_pmm_testsuite_enabled;
+extern unsigned int is_mali_pmu_present;
+
+#endif /* CONFIG_PM */
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+#endif /* USING_MALI_PMM */
+#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */
+
+
diff --git a/drivers/gpu/arm/mali/linux/mali_linux_trace.h b/drivers/gpu/arm/mali/linux/mali_linux_trace.h
new file mode 100644
index 00000000000..045e6da3d1a
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_linux_trace.h
@@ -0,0 +1,124 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms of
+ * such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ)
+#define MALI_LINUX_TRACE_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;
+ __entry->value = value;
+ ),
+
+ TP_printk("event %d = %d", __entry->counter_id, __entry->value)
+);
+
+/**
+ * Define a tracepoint used to register the value of a software counter.
+ *
+ * @param counter_id The counter ID.
+ * @param value The value of the counter.
+ */
+TRACE_EVENT(mali_sw_counter,
+
+ TP_PROTO(unsigned int counter_id, signed long long value),
+
+ TP_ARGS(counter_id, value),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, counter_id)
+ __field(signed long long, value)
+ ),
+
+ TP_fast_assign(
+ __entry->counter_id = counter_id;
+ __entry->value = value;
+ ),
+
+ TP_printk("event %d = %lld", __entry->counter_id, __entry->value)
+);
+
+#endif /* MALI_LINUX_TRACE_H */
+
+/* This part must exist outside the header guard. */
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_atomics.c b/drivers/gpu/arm/mali/linux/mali_osk_atomics.c
new file mode 100644
index 00000000000..32f8e6bdac7
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_atomics.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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);
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.c b/drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.c
new file mode 100644
index 00000000000..ecb44818a6b
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <linux/version.h>
+
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+
+#include "mali_osk.h"
+#include "mali_ukk.h"
+#include "mali_kernel_common.h"
+
+/**
+ * @file mali_osk_specific.c
+ * Implementation of per-OS Kernel level specifics
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+#define do_mmap do_mmap_pgoff
+#endif
+
+_mali_osk_errcode_t _mali_osk_specific_indirect_mmap( _mali_uk_mem_mmap_s *args )
+{
+ /* args->ctx ignored here; args->ukk_private required instead */
+ /* we need to lock the mmap semaphore before calling the do_mmap function */
+ down_write(&current->mm->mmap_sem);
+
+ args->mapping = (void __user *)do_mmap(
+ (struct file *)args->ukk_private,
+ 0, /* start mapping from any address after NULL */
+ args->size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ args->phys_addr
+ );
+
+ /* and unlock it after the call */
+ up_write(&current->mm->mmap_sem);
+
+ /* No cookie required here */
+ args->cookie = 0;
+ /* uku_private meaningless, so zero */
+ args->uku_private = NULL;
+
+ if ( (NULL == args->mapping) || IS_ERR((void *)args->mapping) )
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* Success */
+ return _MALI_OSK_ERR_OK;
+}
+
+
+_mali_osk_errcode_t _mali_osk_specific_indirect_munmap( _mali_uk_mem_munmap_s *args )
+{
+ /* args->ctx and args->cookie ignored here */
+
+ if ((NULL != current) && (NULL != current->mm))
+ {
+ /* remove mapping of mali memory from the process' view */
+ /* lock mmap semaphore before call */
+ /* lock mmap_sem before calling do_munmap */
+ down_write(&current->mm->mmap_sem);
+ do_munmap(
+ current->mm,
+ (unsigned long)args->mapping,
+ args->size
+ );
+ /* and unlock after call */
+ up_write(&current->mm->mmap_sem);
+ MALI_DEBUG_PRINT(5, ("unmapped\n"));
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(2, ("Freeing of a big block while no user process attached, assuming crash cleanup in progress\n"));
+ }
+
+ return _MALI_OSK_ERR_OK; /* always succeeds */
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.h b/drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.h
new file mode 100644
index 00000000000..5c0b1f0340d
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_indir_mmap.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_osk_specific.h
+ * Defines per-OS Kernel level specifics, such as unusual workarounds for
+ * certain OSs.
+ */
+
+#ifndef __MALI_OSK_INDIR_MMAP_H__
+#define __MALI_OSK_INDIR_MMAP_H__
+
+#include "mali_uk_types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Linux specific means for calling _mali_ukk_mem_mmap/munmap
+ *
+ * The presence of _MALI_OSK_SPECIFIC_INDIRECT_MMAP indicates that
+ * _mali_osk_specific_indirect_mmap and _mali_osk_specific_indirect_munmap
+ * should be used instead of _mali_ukk_mem_mmap/_mali_ukk_mem_munmap.
+ *
+ * The arguments are the same as _mali_ukk_mem_mmap/_mali_ukk_mem_munmap.
+ *
+ * In ALL operating system other than Linux, it is expected that common code
+ * should be able to call _mali_ukk_mem_mmap/_mali_ukk_mem_munmap directly.
+ * Such systems should NOT define _MALI_OSK_SPECIFIC_INDIRECT_MMAP.
+ */
+_mali_osk_errcode_t _mali_osk_specific_indirect_mmap( _mali_uk_mem_mmap_s *args );
+_mali_osk_errcode_t _mali_osk_specific_indirect_munmap( _mali_uk_mem_munmap_s *args );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_OSK_INDIR_MMAP_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_irq.c b/drivers/gpu/arm/mali/linux/mali_osk_irq.c
new file mode 100644
index 00000000000..ed43b4fa0c4
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_irq.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/workqueue.h>
+#include <linux/version.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_core.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_license.h"
+#include "mali_kernel_linux.h"
+#include "linux/interrupt.h"
+
+typedef struct _mali_osk_irq_t_struct
+{
+ u32 irqnum;
+ void *data;
+ _mali_osk_irq_uhandler_t uhandler;
+ _mali_osk_irq_bhandler_t bhandler;
+ struct work_struct work_queue_irq_handle; /* Workqueue for the bottom half of the IRQ-handling. This job is activated when this core gets an IRQ.*/
+} mali_osk_irq_object_t;
+
+#if MALI_LICENSE_IS_GPL
+static struct workqueue_struct *pmm_wq=NULL;
+struct workqueue_struct *mali_wq = NULL;
+#endif
+
+typedef void (*workqueue_func_t)(void *);
+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(INIT_DELAYED_WORK)
+static void irq_handler_bottom_half ( struct work_struct *work );
+#else
+static void irq_handler_bottom_half ( void * input );
+#endif
+
+/**
+ * Linux kernel version has marked SA_SHIRQ as deprecated, IRQF_SHARED should be used.
+ * This is to handle older kernels which haven't done this swap.
+ */
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif /* IRQF_SHARED */
+
+_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, _mali_osk_irq_bhandler_t bhandler, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *data, const char *description )
+{
+ mali_osk_irq_object_t *irq_object;
+
+ irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
+ if (NULL == irq_object) return NULL;
+
+#if MALI_LICENSE_IS_GPL
+ if (NULL == mali_wq)
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+ mali_wq = alloc_workqueue("mali", WQ_UNBOUND, 0);
+#else
+ mali_wq = create_workqueue("mali");
+#endif
+ if(NULL == mali_wq)
+ {
+ MALI_PRINT_ERROR(("Unable to create Mali workqueue\n"));
+ return NULL;
+ }
+ }
+#endif
+
+ /* workqueue API changed in 2.6.20, support both versions: */
+#if defined(INIT_DELAYED_WORK)
+ /* New syntax: INIT_WORK( struct work_struct *work, void (*function)(struct work_struct *)) */
+ INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half);
+#else
+ /* Old syntax: INIT_WORK( struct work_struct *work, void (*function)(void *), void *data) */
+ INIT_WORK( &irq_object->work_queue_irq_handle, irq_handler_bottom_half, irq_object);
+#endif /* defined(INIT_DELAYED_WORK) */
+
+ 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(data);
+
+ _mali_osk_time_ubusydelay(5);
+
+ irq = probe_irq_off(mask);
+ err = ack_func(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->bhandler = bhandler;
+ irq_object->data = data;
+
+ /* Is this a real IRQ handler we need? */
+ if (!mali_benchmark && irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM)
+ {
+ if (-1 == irqnum)
+ {
+ MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
+ kfree(irq_object);
+ return NULL;
+ }
+
+ if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object))
+ {
+ MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
+ kfree(irq_object);
+ return NULL;
+ }
+ }
+
+#if MALI_LICENSE_IS_GPL
+ if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum )
+ {
+ pmm_wq = create_singlethread_workqueue("mali-pmm-wq");
+ }
+#endif
+
+ return irq_object;
+}
+
+void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq )
+{
+ mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
+#if MALI_LICENSE_IS_GPL
+ if ( irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
+ {
+ queue_work( pmm_wq,&irq_object->work_queue_irq_handle );
+ }
+ else
+ {
+ queue_work(mali_wq, &irq_object->work_queue_irq_handle);
+ }
+#else
+ schedule_work(&irq_object->work_queue_irq_handle);
+#endif
+}
+
+void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq )
+{
+#if MALI_LICENSE_IS_GPL
+ mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
+ if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
+ {
+ flush_workqueue(pmm_wq);
+ }
+ else
+ {
+ flush_workqueue(mali_wq);
+ }
+#endif
+}
+
+void _mali_osk_irq_term( _mali_osk_irq_t *irq )
+{
+ mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
+
+#if MALI_LICENSE_IS_GPL
+ if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
+ {
+ flush_workqueue(pmm_wq);
+ destroy_workqueue(pmm_wq);
+ }
+#endif
+ if (!mali_benchmark)
+ {
+ free_irq(irq_object->irqnum, irq_object);
+ }
+ kfree(irq_object);
+ flush_scheduled_work();
+}
+
+
+/** 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*/
+{
+ mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id;
+
+ if (irq_object->uhandler(irq_object->data) == _MALI_OSK_ERR_OK)
+ {
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+/* Is executed when an interrupt occur on one core */
+/* workqueue API changed in 2.6.20, support both versions: */
+#if defined(INIT_DELAYED_WORK)
+static void irq_handler_bottom_half ( struct work_struct *work )
+#else
+static void irq_handler_bottom_half ( void * input )
+#endif
+{
+ mali_osk_irq_object_t *irq_object;
+
+#if defined(INIT_DELAYED_WORK)
+ irq_object = _MALI_OSK_CONTAINER_OF(work, mali_osk_irq_object_t, work_queue_irq_handle);
+#else
+ if ( NULL == input )
+ {
+ MALI_PRINT_ERROR(("IRQ: Null pointer! Illegal!"));
+ return; /* Error */
+ }
+ irq_object = (mali_osk_irq_object_t *) input;
+#endif
+
+ irq_object->bhandler(irq_object->data);
+}
+
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_locks.c b/drivers/gpu/arm/mali/linux/mali_osk_locks.c
new file mode 100644
index 00000000000..30af91deb6f
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_locks.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_osk_locks.c
+ * Implemenation of the OS abstraction layer for the kernel device driver
+ */
+
+/* needed to detect kernel version specific code */
+#include <linux/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/rwsem.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/slab.h>
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+/* These are all the locks we implement: */
+typedef enum
+{
+ _MALI_OSK_INTERNAL_LOCKTYPE_SPIN, /* Mutex, implicitly non-interruptable, use spin_lock/spin_unlock */
+ _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ, /* Mutex, IRQ version of spinlock, use spin_lock_irqsave/spin_unlock_irqrestore */
+ _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use up()/down_interruptable() */
+ _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use up()/down() */
+ _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {up,down}{read,write}() */
+
+ /* Linux supports, but we do not support:
+ * Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off
+ */
+
+ /* Linux does not support:
+ * One-locks, of any sort - no optimization for this fact will be made.
+ */
+
+} _mali_osk_internal_locktype;
+
+struct _mali_osk_lock_t_struct
+{
+ _mali_osk_internal_locktype type;
+ unsigned long flags;
+ union
+ {
+ spinlock_t spinlock;
+ struct semaphore sema;
+ struct rw_semaphore rw_sema;
+ } obj;
+ MALI_DEBUG_CODE(
+ /** original flags for debug checking */
+ _mali_osk_lock_flags_t orig_flags;
+ ); /* MALI_DEBUG_CODE */
+};
+
+_mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial, u32 order )
+{
+ _mali_osk_lock_t *lock = NULL;
+
+ /* Validate parameters: */
+ /* Flags acceptable */
+ MALI_DEBUG_ASSERT( 0 == ( flags & ~(_MALI_OSK_LOCKFLAG_SPINLOCK
+ | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ
+ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE
+ | _MALI_OSK_LOCKFLAG_READERWRITER
+ | _MALI_OSK_LOCKFLAG_ORDERED
+ | _MALI_OSK_LOCKFLAG_ONELOCK )) );
+ /* Spinlocks are always non-interruptable */
+ MALI_DEBUG_ASSERT( (((flags & _MALI_OSK_LOCKFLAG_SPINLOCK) || (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ)) && (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE))
+ || !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK));
+ /* Parameter initial SBZ - for future expansion */
+ MALI_DEBUG_ASSERT( 0 == initial );
+
+ lock = kmalloc(sizeof(_mali_osk_lock_t), GFP_KERNEL);
+
+ if ( NULL == lock )
+ {
+ return lock;
+ }
+
+ /* Determine type of mutex: */
+ /* defaults to interruptable mutex if no flags are specified */
+
+ if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK) )
+ {
+ /* Non-interruptable Spinlocks override all others */
+ lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN;
+ spin_lock_init( &lock->obj.spinlock );
+ }
+ else if ( (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ ) )
+ {
+ lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ;
+ lock->flags = 0;
+ spin_lock_init( &lock->obj.spinlock );
+ }
+ else if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE)
+ && (flags & _MALI_OSK_LOCKFLAG_READERWRITER) )
+ {
+ lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW;
+ init_rwsem( &lock->obj.rw_sema );
+ }
+ else
+ {
+ /* Usual mutex types */
+ if ( (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE) )
+ {
+ lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT;
+ }
+ else
+ {
+ lock->type = _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX;
+ }
+
+ /* Initially unlocked */
+ sema_init( &lock->obj.sema, 1 );
+ }
+
+ MALI_DEBUG_CODE(
+ /* Debug tracking of flags */
+ lock->orig_flags = flags;
+ ); /* MALI_DEBUG_CODE */
+
+ return lock;
+}
+
+_mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode)
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+
+ /* Parameter validation */
+ MALI_DEBUG_ASSERT_POINTER( lock );
+
+ MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
+ || _MALI_OSK_LOCKMODE_RO == mode );
+
+ /* Only allow RO locks when the initial object was a Reader/Writer lock
+ * Since information is lost on the internal locktype, we use the original
+ * information, which is only stored when built for DEBUG */
+ MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
+ || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) );
+
+ switch ( lock->type )
+ {
+ case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN:
+ spin_lock(&lock->obj.spinlock);
+ break;
+ case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ:
+ spin_lock_irqsave(&lock->obj.spinlock, lock->flags);
+ break;
+
+ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX:
+ if ( down_interruptible(&lock->obj.sema) )
+ {
+ err = _MALI_OSK_ERR_RESTARTSYSCALL;
+ }
+ break;
+
+ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT:
+ down(&lock->obj.sema);
+ break;
+
+ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW:
+ if (mode == _MALI_OSK_LOCKMODE_RO)
+ {
+ down_read(&lock->obj.rw_sema);
+ }
+ else
+ {
+ down_write(&lock->obj.rw_sema);
+ }
+ break;
+
+ default:
+ /* Reaching here indicates a programming error, so you will not get here
+ * on non-DEBUG builds */
+ MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) );
+ break;
+ }
+
+ return err;
+}
+
+void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode )
+{
+ /* Parameter validation */
+ MALI_DEBUG_ASSERT_POINTER( lock );
+
+ MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
+ || _MALI_OSK_LOCKMODE_RO == mode );
+
+ /* Only allow RO locks when the initial object was a Reader/Writer lock
+ * Since information is lost on the internal locktype, we use the original
+ * information, which is only stored when built for DEBUG */
+ MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
+ || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) );
+
+ switch ( lock->type )
+ {
+ case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN:
+ spin_unlock(&lock->obj.spinlock);
+ break;
+ case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ:
+ spin_unlock_irqrestore(&lock->obj.spinlock, lock->flags);
+ break;
+
+ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX:
+ /* FALLTHROUGH */
+ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT:
+ up(&lock->obj.sema);
+ break;
+
+ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW:
+ if (mode == _MALI_OSK_LOCKMODE_RO)
+ {
+ up_read(&lock->obj.rw_sema);
+ }
+ else
+ {
+ up_write(&lock->obj.rw_sema);
+ }
+ break;
+
+ default:
+ /* Reaching here indicates a programming error, so you will not get here
+ * on non-DEBUG builds */
+ MALI_DEBUG_PRINT_ERROR( ("Invalid internal lock type: %.8X", lock->type ) );
+ break;
+ }
+}
+
+void _mali_osk_lock_term( _mali_osk_lock_t *lock )
+{
+ /* Parameter validation */
+ MALI_DEBUG_ASSERT_POINTER( lock );
+
+ /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
+ kfree(lock);
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c b/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c
new file mode 100644
index 00000000000..210d8226074
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_osk_low_level_mem.c
+ * Implementation of the OS abstraction layer for the kernel device driver
+ */
+
+/* needed to detect kernel version specific code */
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+
+#include "mali_osk.h"
+#include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */
+#include "mali_kernel_common.h"
+#include "mali_kernel_linux.h"
+
+static void mali_kernel_memory_vma_open(struct vm_area_struct * vma);
+static void mali_kernel_memory_vma_close(struct vm_area_struct * vma);
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf);
+#else
+static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address);
+#endif
+
+
+typedef struct mali_vma_usage_tracker
+{
+ int references;
+ u32 cookie;
+} mali_vma_usage_tracker;
+
+
+/* Linked list structure to hold details of all OS allocations in a particular
+ * mapping
+ */
+struct AllocationList
+{
+ struct AllocationList *next;
+ u32 offset;
+ u32 physaddr;
+};
+
+typedef struct AllocationList AllocationList;
+
+/* Private structure to store details of a mapping region returned
+ * from _mali_osk_mem_mapregion_init
+ */
+struct MappingInfo
+{
+ struct vm_area_struct *vma;
+ struct AllocationList *list;
+};
+
+typedef struct MappingInfo MappingInfo;
+
+
+static u32 _kernel_page_allocate(void);
+static void _kernel_page_release(u32 physical_address);
+static AllocationList * _allocation_list_item_get(void);
+static void _allocation_list_item_release(AllocationList * item);
+
+
+/* Variable declarations */
+static DEFINE_SPINLOCK(allocation_list_spinlock);
+static AllocationList * pre_allocated_memory = (AllocationList*) NULL ;
+static int pre_allocated_memory_size_current = 0;
+#ifdef MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB
+ static int pre_allocated_memory_size_max = MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 1024 * 1024;
+#else
+ static int pre_allocated_memory_size_max = 6 * 1024 * 1024; /* 6 MiB */
+#endif
+
+static struct vm_operations_struct mali_kernel_vm_ops =
+{
+ .open = mali_kernel_memory_vma_open,
+ .close = mali_kernel_memory_vma_close,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+ .fault = mali_kernel_memory_cpu_page_fault_handler
+#else
+ .nopfn = mali_kernel_memory_cpu_page_fault_handler
+#endif
+};
+
+
+void mali_osk_low_level_mem_init(void)
+{
+ pre_allocated_memory = (AllocationList*) NULL ;
+}
+
+void mali_osk_low_level_mem_term(void)
+{
+ while ( NULL != pre_allocated_memory )
+ {
+ AllocationList *item;
+ item = pre_allocated_memory;
+ pre_allocated_memory = item->next;
+ _kernel_page_release(item->physaddr);
+ _mali_osk_free( item );
+ }
+ pre_allocated_memory_size_current = 0;
+}
+
+static u32 _kernel_page_allocate(void)
+{
+ struct page *new_page;
+ u32 linux_phys_addr;
+
+ new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD);
+
+ if ( NULL == new_page )
+ {
+ return 0;
+ }
+
+ /* Ensure page is flushed from CPU caches. */
+ linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+ return linux_phys_addr;
+}
+
+static void _kernel_page_release(u32 physical_address)
+{
+ struct page *unmap_page;
+
+ #if 1
+ dma_unmap_page(NULL, physical_address, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ #endif
+
+ unmap_page = pfn_to_page( physical_address >> PAGE_SHIFT );
+ MALI_DEBUG_ASSERT_POINTER( unmap_page );
+ __free_page( unmap_page );
+}
+
+static AllocationList * _allocation_list_item_get(void)
+{
+ AllocationList *item = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&allocation_list_spinlock,flags);
+ if ( pre_allocated_memory )
+ {
+ item = pre_allocated_memory;
+ pre_allocated_memory = pre_allocated_memory->next;
+ pre_allocated_memory_size_current -= PAGE_SIZE;
+
+ spin_unlock_irqrestore(&allocation_list_spinlock,flags);
+ return item;
+ }
+ spin_unlock_irqrestore(&allocation_list_spinlock,flags);
+
+ item = _mali_osk_malloc( sizeof(AllocationList) );
+ if ( NULL == item)
+ {
+ return NULL;
+ }
+
+ item->physaddr = _kernel_page_allocate();
+ if ( 0 == item->physaddr )
+ {
+ /* Non-fatal error condition, out of memory. Upper levels will handle this. */
+ _mali_osk_free( item );
+ return NULL;
+ }
+ return item;
+}
+
+static void _allocation_list_item_release(AllocationList * item)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&allocation_list_spinlock,flags);
+ if ( pre_allocated_memory_size_current < pre_allocated_memory_size_max)
+ {
+ item->next = pre_allocated_memory;
+ pre_allocated_memory = item;
+ pre_allocated_memory_size_current += PAGE_SIZE;
+ spin_unlock_irqrestore(&allocation_list_spinlock,flags);
+ return;
+ }
+ spin_unlock_irqrestore(&allocation_list_spinlock,flags);
+
+ _kernel_page_release(item->physaddr);
+ _mali_osk_free( item );
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf)
+#else
+static unsigned long mali_kernel_memory_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
+ /*
+ * 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));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+ return VM_FAULT_SIGBUS;
+#else
+ return NOPFN_SIGBUS;
+#endif
+}
+
+static void mali_kernel_memory_vma_open(struct vm_area_struct * vma)
+{
+ mali_vma_usage_tracker * vma_usage_tracker;
+ MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma));
+
+ vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data;
+ vma_usage_tracker->references++;
+
+ return;
+}
+
+static void mali_kernel_memory_vma_close(struct vm_area_struct * vma)
+{
+ _mali_uk_mem_munmap_s args = {0, };
+ mali_memory_allocation * descriptor;
+ mali_vma_usage_tracker * vma_usage_tracker;
+ MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma));
+
+ vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data;
+
+ BUG_ON(!vma_usage_tracker);
+ BUG_ON(0 == vma_usage_tracker->references);
+
+ vma_usage_tracker->references--;
+
+ if (0 != vma_usage_tracker->references)
+ {
+ MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", vma_usage_tracker->references));
+ return;
+ }
+
+ /** @note args->context unused, initialized to 0.
+ * Instead, we use the memory_session from the cookie */
+
+ descriptor = (mali_memory_allocation *)vma_usage_tracker->cookie;
+
+ args.cookie = (u32)descriptor;
+ args.mapping = descriptor->mapping;
+ args.size = descriptor->size;
+
+ _mali_ukk_mem_munmap( &args );
+
+ /* vma_usage_tracker is free()d by _mali_osk_mem_mapregion_term().
+ * In the case of the memory engine, it is called as the release function that has been registered with the engine*/
+}
+
+
+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_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size )
+{
+ void * virt;
+ MALI_DEBUG_ASSERT_POINTER( phys );
+ MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) );
+ MALI_DEBUG_ASSERT( 0 != size );
+
+ /* dma_alloc_* uses a limited region of address space. On most arch/marchs
+ * 2 to 14 MiB is available. This should be enough for the page tables, which
+ * currently is the only user of this function. */
+ virt = dma_alloc_coherent(NULL, size, phys, GFP_KERNEL | GFP_DMA );
+
+ MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys));
+
+ if ( NULL == virt )
+ {
+ MALI_DEBUG_PRINT(5, ("allocioregion: Failed to allocate Pagetable memory, size=0x%.8X\n", size ));
+ return 0;
+ }
+
+ MALI_DEBUG_ASSERT( 0 == (*phys & ~_MALI_OSK_CPU_PAGE_MASK) );
+
+ return (mali_io_address)virt;
+}
+
+void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt )
+{
+ MALI_DEBUG_ASSERT_POINTER( (void*)virt );
+ MALI_DEBUG_ASSERT( 0 != size );
+ MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) );
+
+ dma_free_coherent(NULL, size, virt, phys);
+}
+
+_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description )
+{
+ return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK);
+}
+
+void inline _mali_osk_mem_unreqregion( u32 phys, u32 size )
+{
+ release_mem_region(phys, size);
+}
+
+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();
+}
+
+_mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descriptor )
+{
+ struct vm_area_struct *vma;
+ mali_vma_usage_tracker * vma_usage_tracker;
+ MappingInfo *mappingInfo;
+
+ if (NULL == descriptor) return _MALI_OSK_ERR_FAULT;
+
+ MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
+
+ vma = (struct vm_area_struct*)descriptor->process_addr_mapping_info;
+
+ if (NULL == vma ) return _MALI_OSK_ERR_FAULT;
+
+ /* Re-write the process_addr_mapping_info */
+ mappingInfo = _mali_osk_calloc( 1, sizeof(MappingInfo) );
+
+ if ( NULL == mappingInfo ) return _MALI_OSK_ERR_FAULT;
+
+ vma_usage_tracker = _mali_osk_calloc( 1, sizeof(mali_vma_usage_tracker) );
+
+ if (NULL == vma_usage_tracker)
+ {
+ MALI_DEBUG_PRINT(2, ("Failed to allocate memory to track memory usage\n"));
+ _mali_osk_free( mappingInfo );
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ mappingInfo->vma = vma;
+ descriptor->process_addr_mapping_info = mappingInfo;
+
+ /* 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;
+ /* list member is already NULL */
+
+ /*
+ 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
+ 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_RESERVED;
+ vma->vm_flags |= VM_DONTCOPY;
+
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */
+
+ vma_usage_tracker->references = 1; /* set initial reference count to be 1 as vma_open won't be called for the first mmap call */
+ vma_usage_tracker->cookie = (u32)descriptor; /* cookie for munmap */
+
+ vma->vm_private_data = vma_usage_tracker;
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_mem_mapregion_term( mali_memory_allocation * descriptor )
+{
+ struct vm_area_struct* vma;
+ mali_vma_usage_tracker * vma_usage_tracker;
+ MappingInfo *mappingInfo;
+
+ if (NULL == descriptor) return;
+
+ MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
+
+ mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
+
+ MALI_DEBUG_ASSERT_POINTER( mappingInfo );
+
+ /* 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 = mappingInfo->vma;
+
+ MALI_DEBUG_ASSERT_POINTER( vma );
+
+ /* ASSERT that there are no allocations on the list. Unmap should've been
+ * called on all OS allocations. */
+ MALI_DEBUG_ASSERT( NULL == mappingInfo->list );
+
+ vma_usage_tracker = vma->vm_private_data;
+
+ /* We only get called if mem_mapregion_init succeeded */
+ _mali_osk_free(vma_usage_tracker);
+
+ _mali_osk_free( mappingInfo );
+ return;
+}
+
+_mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size )
+{
+ struct vm_area_struct *vma;
+ MappingInfo *mappingInfo;
+
+ if (NULL == descriptor) return _MALI_OSK_ERR_FAULT;
+
+ MALI_DEBUG_ASSERT_POINTER( phys_addr );
+
+ MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
+
+ MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) );
+
+ MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK));
+
+ if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS;
+
+ if (size > (descriptor->size - offset))
+ {
+ MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n",
+ *phys_addr, size, descriptor->mapping, offset));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
+
+ MALI_DEBUG_ASSERT_POINTER( mappingInfo );
+
+ vma = mappingInfo->vma;
+
+ if (NULL == vma ) return _MALI_OSK_ERR_FAULT;
+
+ MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", *phys_addr, (long unsigned int)(descriptor->mapping + offset), size));
+
+ if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == *phys_addr )
+ {
+ _mali_osk_errcode_t ret;
+ AllocationList *alloc_item;
+ u32 linux_phys_frame_num;
+
+ alloc_item = _allocation_list_item_get();
+ if (NULL == alloc_item)
+ {
+ MALI_DEBUG_PRINT(1, ("Failed to allocate list item\n"));
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ linux_phys_frame_num = alloc_item->physaddr >> PAGE_SHIFT;
+
+ ret = ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, linux_phys_frame_num, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK;
+
+ if ( ret != _MALI_OSK_ERR_OK)
+ {
+ _allocation_list_item_release(alloc_item);
+ return ret;
+ }
+
+ /* Put our alloc_item into the list of allocations on success */
+ alloc_item->next = mappingInfo->list;
+ alloc_item->offset = offset;
+
+ /*alloc_item->physaddr = linux_phys_addr;*/
+ mappingInfo->list = alloc_item;
+
+ /* Write out new physical address on success */
+ *phys_addr = alloc_item->physaddr;
+
+ return ret;
+ }
+
+ /* Otherwise, Use the supplied physical address */
+
+ /* ASSERT that supplied phys_addr is page aligned */
+ MALI_DEBUG_ASSERT( 0 == ((*phys_addr) & ~_MALI_OSK_CPU_PAGE_MASK) );
+
+ return ( 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;
+
+}
+
+void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags )
+{
+ MappingInfo *mappingInfo;
+
+ if (NULL == descriptor) return;
+
+ MALI_DEBUG_ASSERT( 0 != (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_INTO_USERSPACE) );
+
+ MALI_DEBUG_ASSERT( 0 == (size & ~_MALI_OSK_CPU_PAGE_MASK) );
+
+ MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK) );
+
+ if (NULL == descriptor->mapping) return;
+
+ if (size > (descriptor->size - offset))
+ {
+ MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n",
+ size, descriptor->mapping, offset));
+ return;
+ }
+ mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
+
+ MALI_DEBUG_ASSERT_POINTER( mappingInfo );
+
+ if ( 0 != (flags & _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR) )
+ {
+ /* This physical RAM was allocated in _mali_osk_mem_mapregion_map and
+ * so needs to be unmapped
+ */
+ while (size)
+ {
+ /* First find the allocation in the list of allocations */
+ AllocationList *alloc = mappingInfo->list;
+ AllocationList **prev = &(mappingInfo->list);
+ while (NULL != alloc && alloc->offset != offset)
+ {
+ prev = &(alloc->next);
+ alloc = alloc->next;
+ }
+ if (alloc == NULL) {
+ MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n"));
+ size -= _MALI_OSK_CPU_PAGE_SIZE;
+ offset += _MALI_OSK_CPU_PAGE_SIZE;
+ continue;
+ }
+
+ _kernel_page_release(alloc->physaddr);
+
+ /* Remove the allocation from the list */
+ *prev = alloc->next;
+ _mali_osk_free( alloc );
+
+ /* Move onto the next allocation */
+ size -= _MALI_OSK_CPU_PAGE_SIZE;
+ offset += _MALI_OSK_CPU_PAGE_SIZE;
+ }
+ }
+
+ /* Linux does the right thing as part of munmap to remove the mapping */
+
+ return;
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_mali.c b/drivers/gpu/arm/mali/linux/mali_osk_mali.c
new file mode 100644
index 00000000000..591430c123c
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_mali.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 "mali_kernel_common.h" /* MALI_xxx macros */
+#include "mali_osk.h" /* kernel side OS functions */
+#include "mali_uk_types.h"
+#include "mali_kernel_linux.h" /* exports initialize/terminate_kernel_device() definition of mali_osk_low_level_mem_init() and term */
+#include <mach-exynos/irqs.h>
+#include <mach-exynos/mali/config.h> /* contains the configuration of the arch we are compiling for */
+
+/* is called from mali_kernel_constructor in common code */
+_mali_osk_errcode_t _mali_osk_init( void )
+{
+ if (0 != initialize_kernel_device()) MALI_ERROR(_MALI_OSK_ERR_FAULT);
+
+ mali_osk_low_level_mem_init();
+
+ MALI_SUCCESS;
+}
+
+/* is called from mali_kernel_deconstructor in common code */
+void _mali_osk_term( void )
+{
+ mali_osk_low_level_mem_term();
+ terminate_kernel_device();
+}
+
+_mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources )
+{
+ *num_resources = sizeof(arch_configuration) / sizeof(arch_configuration[0]);
+ *arch_config = arch_configuration;
+ return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_resources_term( _mali_osk_resource_t **arch_config, u32 num_resources )
+{
+ /* Nothing to do */
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_math.c b/drivers/gpu/arm/mali/linux/mali_osk_math.c
new file mode 100644
index 00000000000..bb25e7dc7dd
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_math.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 inline _mali_osk_clz( u32 input )
+{
+ return 32-fls(input);
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_memory.c b/drivers/gpu/arm/mali/linux/mali_osk_memory.c
new file mode 100644
index 00000000000..5354e855e8d
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_memory.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/mali/linux/mali_osk_misc.c b/drivers/gpu/arm/mali/linux/mali_osk_misc.c
new file mode 100644
index 00000000000..286e45d0c08
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_misc.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 = vsnprintf(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 */
+ *(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 */
+ return (u32)current->pid;
+}
+
+void * _mali_osk_get_task(void)
+{
+ return current;
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_notification.c b/drivers/gpu/arm/mali/linux/mali_osk_notification.c
new file mode 100644
index 00000000000..fb4907eefce
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_notification.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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"
+
+/* needed to detect kernel version specific code */
+#include <linux/version.h>
+
+#include <linux/sched.h>
+#include <linux/slab.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
+
+/**
+ * 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
+{
+ struct semaphore 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;
+
+ sema_init(&result->mutex, 1);
+ 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 );
+ 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 );
+
+ /* Remove from the list */
+ list_del(&notification->list);
+ /* Free the container */
+ kfree(notification);
+}
+
+void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue )
+{
+ MALI_DEBUG_ASSERT_POINTER( queue );
+
+ /* 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 )
+{
+ _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 );
+
+ /* lock queue access */
+ down(&queue->mutex);
+ /* add to list */
+ list_add_tail(&notification->list, &queue->head);
+ /* unlock the queue */
+ up(&queue->mutex);
+
+ /* and wake up one possible exclusive waiter */
+ wake_up(&queue->receive_queue);
+}
+
+static int _mali_notification_queue_is_empty( _mali_osk_notification_queue_t *queue )
+{
+ int ret;
+
+ down(&queue->mutex);
+ ret = list_empty(&queue->head);
+ up(&queue->mutex);
+ return ret;
+}
+
+#if MALI_STATE_TRACKING
+mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue )
+{
+ return _mali_notification_queue_is_empty(queue) ? MALI_TRUE : MALI_FALSE;
+}
+#endif
+
+_mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result )
+{
+ _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND;
+ _mali_osk_notification_wrapper_t *wrapper_object;
+
+ down(&queue->mutex);
+
+ 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;
+ }
+
+ up(&queue->mutex);
+
+ 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;
+
+ while (_MALI_OSK_ERR_OK != _mali_osk_notification_queue_dequeue(queue, result))
+ {
+ if (wait_event_interruptible(queue->receive_queue, !_mali_notification_queue_is_empty(queue)))
+ {
+ return _MALI_OSK_ERR_RESTARTSYSCALL;
+ }
+ }
+
+ return _MALI_OSK_ERR_OK; /* all ok */
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_pm.c b/drivers/gpu/arm/mali/linux/mali_osk_pm.c
new file mode 100644
index 00000000000..e5b8ea1a78a
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_pm.c
@@ -0,0 +1,208 @@
+/**
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 "mali_platform.h"
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+#include "mali_pmm.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_license.h"
+#include "mali_linux_pm.h"
+#include "mali_linux_pm_testsuite.h"
+
+#if MALI_LICENSE_IS_GPL
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#ifdef CONFIG_PM_RUNTIME
+static int is_runtime =0;
+#endif /* CONFIG_PM_RUNTIME */
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* MALI_LICENSE_IS_GPL */
+
+#if MALI_POWER_MGMT_TEST_SUITE
+
+#ifdef CONFIG_PM
+unsigned int mali_pmm_events_triggered_mask = 0;
+#endif /* CONFIG_PM */
+
+void _mali_osk_pmm_policy_events_notifications(mali_pmm_event_id mali_pmm_event)
+{
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+
+ switch (mali_pmm_event)
+ {
+ case MALI_PMM_EVENT_JOB_QUEUED:
+ if (mali_job_scheduling_events_recording_on == 1)
+ {
+ mali_pmm_events_triggered_mask |= (1<<0);
+ }
+ break;
+
+ case MALI_PMM_EVENT_JOB_SCHEDULED:
+ if (mali_job_scheduling_events_recording_on == 1)
+ {
+ mali_pmm_events_triggered_mask |= (1<<1);
+ }
+ break;
+
+ case MALI_PMM_EVENT_JOB_FINISHED:
+ if (mali_job_scheduling_events_recording_on == 1)
+ {
+ mali_pmm_events_triggered_mask |= (1<<2);
+ mali_job_scheduling_events_recording_on = 0;
+ pwr_mgmt_status_reg = mali_pmm_events_triggered_mask;
+ }
+ break;
+
+ case MALI_PMM_EVENT_TIMEOUT:
+ if (mali_timeout_event_recording_on == 1)
+ {
+ pwr_mgmt_status_reg = (1<<3);
+ mali_timeout_event_recording_on = 0;
+ }
+ break;
+
+ default:
+
+ break;
+
+ }
+#endif /* CONFIG_PM */
+
+#endif /* MALI_LICENSE_IS_GPL */
+}
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+
+/** This function is called when the Mali device has completed power up
+ * operation.
+ */
+void _mali_osk_pmm_power_up_done(mali_pmm_message_data data)
+{
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+ is_wake_up_needed = 1;
+ wake_up_process(pm_thread);
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI OSK Power up Done\n" ));
+ return;
+#endif /* CONFIG_PM */
+#endif /* MALI_LICENSE_IS_GPL */
+}
+
+/** This function is called when the Mali device has completed power down
+ * operation.
+ */
+void _mali_osk_pmm_power_down_done(mali_pmm_message_data data)
+{
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+ is_wake_up_needed = 1;
+#if MALI_POWER_MGMT_TEST_SUITE
+ if (is_mali_pmu_present == 0)
+ {
+ pwr_mgmt_status_reg = _mali_pmm_cores_list();
+ }
+#endif /* MALI_POWER_MGMT_TEST_SUITE */
+ wake_up_process(pm_thread);
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power down Done\n" ));
+ return;
+
+#endif /* CONFIG_PM */
+#endif /* MALI_LICENSE_IS_GPL */
+}
+
+/** This function is invoked when mali device is idle.
+*/
+_mali_osk_errcode_t _mali_osk_pmm_dev_idle(void)
+{
+ _mali_osk_errcode_t err = 0;
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+
+ err = pm_runtime_put_sync(&(mali_gpu_device.dev));
+ if(err)
+ {
+ MALI_DEBUG_PRINT(4, ("OSPMM: Error in _mali_osk_pmm_dev_idle\n" ));
+ }
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+#endif /* MALI_LICENSE_IS_GPL */
+ return err;
+}
+
+/** This funtion is invoked when mali device needs to be activated.
+*/
+void _mali_osk_pmm_dev_activate(void)
+{
+
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM_RUNTIME
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ int err = 0;
+ if(is_runtime == 0)
+ {
+ pm_suspend_ignore_children(&(mali_gpu_device.dev), true);
+ pm_runtime_enable(&(mali_gpu_device.dev));
+ pm_runtime_get_sync(&(mali_gpu_device.dev));
+ is_runtime = 1;
+ }
+ else
+ {
+ err = pm_runtime_get_sync(&(mali_gpu_device.dev));
+ }
+ if(err)
+ {
+ MALI_DEBUG_PRINT(4, ("OSPMM: Error in _mali_osk_pmm_dev_activate\n" ));
+ }
+#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+#endif /* CONFIG_PM_RUNTIME */
+#endif /* MALI_LICENSE_IS_GPL */
+}
+
+void _mali_osk_pmm_ospmm_cleanup( void )
+{
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+ int thread_state;
+ thread_state = mali_get_ospmm_thread_state();
+ if (thread_state)
+ {
+ _mali_osk_pmm_dvfs_operation_done(0);
+ }
+#endif /* CONFIG_PM */
+#endif /* MALI_LICENSE_IS_GPL */
+}
+
+void _mali_osk_pmm_dvfs_operation_done(mali_pmm_message_data data)
+{
+#if MALI_LICENSE_IS_GPL
+#ifdef CONFIG_PM
+ is_wake_up_needed = 1;
+ wake_up_process(dvfs_pm_thread);
+ MALI_DEBUG_PRINT(4, ("OSPMM: MALI OSK DVFS Operation done\n" ));
+ return;
+#endif /* CONFIG_PM */
+#endif /* MALI_LICENSE_IS_GPL */
+}
+
+
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_profiling_gator.c b/drivers/gpu/arm/mali/linux/mali_osk_profiling_gator.c
new file mode 100644
index 00000000000..5c1618c2eb8
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_profiling_gator.c
@@ -0,0 +1,248 @@
+/**
+ * Copyright (C) 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms of
+ * such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained
+ * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#define DONT_USE_L2_CACHE_COUNTERS /* These traces can cause lock-ups so disable them. */
+
+#include <linux/module.h>
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_ukk.h"
+#include "mali_osk_profiling.h"
+#include "mali_linux_trace.h"
+
+#if defined(USING_MALI400_L2_CACHE) && !defined(DONT_USE_L2_CACHE_COUNTERS)
+#include "mali_kernel_l2_cache.h"
+#endif /* USING_MALI400_L2_CACHE */
+
+#define COUNTER_DISABLED (-1)
+
+/**
+ * Since there are only two physical hardware counters per GPU block, we
+ * need to multiplex the range of possible events that can be collected by
+ * each counter. This multiplexing is achieved by means of the following
+ * table, which holds the event ID that should be collected by each hardware
+ * counter.
+ *
+ * Note that this table should be updated with any change to the above
+ * _mali_osk_counter_id enumeration.
+ */
+s32 _mali_osk_hw_counter_table[] = {
+ COUNTER_DISABLED, /* ACTIVITY_VP */
+ COUNTER_DISABLED, /* ACTIVITY_FP0 */
+ COUNTER_DISABLED, /* ACTIVITY_FP1 */
+ COUNTER_DISABLED, /* ACTIVITY_FP2 */
+ COUNTER_DISABLED, /* ACTIVITY_FP3 */
+ COUNTER_DISABLED, /* COUNTER_L2_C0 */
+ COUNTER_DISABLED, /* COUNTER_L2_C1 */
+ COUNTER_DISABLED, /* COUNTER_VP_C0 */
+ COUNTER_DISABLED, /* COUNTER_VP_C1 */
+ COUNTER_DISABLED, /* COUNTER_FP0_C0 */
+ COUNTER_DISABLED, /* COUNTER_FP0_C1 */
+ COUNTER_DISABLED, /* COUNTER_FP1_C0 */
+ COUNTER_DISABLED, /* COUNTER_FP1_C1 */
+ COUNTER_DISABLED, /* COUNTER_FP2_C0 */
+ COUNTER_DISABLED, /* COUNTER_FP2_C1 */
+ COUNTER_DISABLED, /* COUNTER_FP3_C0 */
+ COUNTER_DISABLED, /* COUNTER_FP3_C1 */
+};
+
+mali_bool _mali_osk_profiling_query_hw_counter(u32 counter_id, u32 *event_id)
+{
+ /* Check that the counter is in range... */
+ if (counter_id >= FIRST_HW_COUNTER && counter_id <= LAST_HW_COUNTER)
+ {
+ s32 id = _mali_osk_hw_counter_table[counter_id];
+
+ /* ...and enabled */
+ if (id != COUNTER_DISABLED)
+ {
+ /* Update the pointer to the event ID */
+ *event_id = (u32)id;
+
+ return MALI_TRUE;
+ }
+ }
+
+ /* The counter was disabled or out of range */
+ return MALI_FALSE;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start)
+{
+ /* Nothing to do */
+ 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_set_default_enable_state(mali_bool enable)
+{
+ /* Nothing to do */
+}
+
+mali_bool _mali_osk_profiling_get_default_enable_state(void)
+{
+ return MALI_FALSE;
+}
+
+_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_profiling_get_config(_mali_uk_profiling_get_config_s *args)
+{
+ return _MALI_OSK_ERR_UNSUPPORTED;
+}
+
+/**
+ * Called by gator.ko to populate the _mali_osk_hw_counter_table.
+ *
+ * @param counter_id The counter ID.
+ * @param event_id Event ID that the counter should count.
+ *
+ * @return 1 on success, 0 on failure.
+ */
+int _mali_profiling_set_event(u32 counter_id, s32 event_id)
+{
+#if defined(USING_MALI400_L2_CACHE) && !defined(DONT_USE_L2_CACHE_COUNTERS)
+ /*
+ * The L2 cache counters have special handling in the driver. Since we
+ * receive new event IDs for each counter one at a time, we need to know
+ * what the L2 counters are currently programmed to read. This way we
+ * can supply the current value to the counter we _aren't_ trying to
+ * program; mali_kernel_l2_cache_set_perf_counters will dutifully ignore
+ * that counter.
+ */
+ u32 current_src0, current_src1, current_val0, current_val1;
+
+ mali_kernel_l2_cache_get_perf_counters(&current_src0, &current_val0,
+ &current_src1, &current_val1);
+
+ if (counter_id == COUNTER_L2_C0)
+ {
+ mali_kernel_l2_cache_set_perf_counters(event_id, current_src1, 0);
+
+ return 1;
+ }
+ else if (counter_id == COUNTER_L2_C1)
+ {
+ mali_kernel_l2_cache_set_perf_counters(current_src0, event_id, 0);
+
+ return 1;
+ }
+#endif /* USING_MALI400_L2_CACHE */
+
+ /* Check that the counter is in range */
+ if (counter_id >= FIRST_HW_COUNTER && counter_id <= LAST_HW_COUNTER)
+ {
+ /*
+ * This does not actually update the hardware with the new event ID;
+ * it will query what event ID it should be counting on each frame
+ * via _mali_osk_profiling_query_hw_counter.
+ */
+ _mali_osk_hw_counter_table[counter_id] = event_id;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+#if defined(USING_MALI400_L2_CACHE) && !defined(DONT_USE_L2_CACHE_COUNTERS)
+/**
+ * Called by gator.ko to retrieve the L2 cache counter values. The L2 cache
+ * counters are unique in that they are polled by gator, rather than being
+ * transmitted via the tracepoint mechanism.
+ *
+ * @param src0 First L2 cache counter ID.
+ * @param val0 First L2 cache counter value.
+ * @param src1 Second L2 cache counter ID.
+ * @param val1 Second L2 cache counter value.
+ */
+void _mali_profiling_get_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1)
+{
+ mali_kernel_l2_cache_get_perf_counters(src0, val0, src1, val1);
+}
+
+EXPORT_SYMBOL(_mali_profiling_get_counters);
+#endif /* USING_MALI400_L2_CACHE */
+
+EXPORT_SYMBOL(_mali_profiling_set_event);
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_profiling_internal.c b/drivers/gpu/arm/mali/linux/mali_osk_profiling_internal.c
new file mode 100644
index 00000000000..c162ffd8fd1
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_profiling_internal.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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"
+
+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_lock_t *lock = NULL;
+static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
+static mali_profiling_entry* profile_entries = NULL;
+static u32 profile_entry_count = 0;
+static _mali_osk_atomic_t profile_insert_index;
+static _mali_osk_atomic_t profile_entries_written;
+static mali_bool mali_profiling_default_enable = MALI_FALSE;
+
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start)
+{
+ profile_entries = NULL;
+ profile_entry_count = 0;
+ _mali_osk_atomic_init(&profile_insert_index, 0);
+ _mali_osk_atomic_init(&profile_entries_written, 0);
+
+ lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0 );
+ 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_profiling_default_enable = MALI_TRUE; /* save this so user space can query this on their startup */
+ if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit))
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_profiling_term(void)
+{
+ prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
+
+ /* wait for all elements to be completely inserted into array */
+ while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written))
+ {
+ /* do nothing */;
+ }
+
+ if (NULL != profile_entries)
+ {
+ _mali_osk_vfree(profile_entries);
+ profile_entries = NULL;
+ }
+
+ if (NULL != lock)
+ {
+ _mali_osk_lock_term(lock);
+ lock = NULL;
+ }
+}
+
+inline _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit)
+{
+ _mali_osk_errcode_t ret;
+
+ mali_profiling_entry *new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry));
+
+ if(NULL == new_profile_entries)
+ {
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (prof_state != MALI_PROFILING_STATE_IDLE)
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_vfree(new_profile_entries);
+ return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+ }
+
+ if (*limit > MALI_PROFILING_MAX_BUFFER_ENTRIES)
+ {
+ *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES;
+ }
+
+ profile_entries = new_profile_entries;
+ profile_entry_count = *limit;
+
+ ret = _mali_timestamp_reset();
+
+ if (ret == _MALI_OSK_ERR_OK)
+ {
+ prof_state = MALI_PROFILING_STATE_RUNNING;
+ }
+ else
+ {
+ _mali_osk_vfree(profile_entries);
+ profile_entries = NULL;
+ }
+
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return ret;
+}
+
+inline void _mali_osk_profiling_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;
+
+ if (prof_state != MALI_PROFILING_STATE_RUNNING || cur_index >= profile_entry_count)
+ {
+ /*
+ * Not in recording mode, or buffer is full
+ * Decrement index again, and early out
+ */
+ _mali_osk_atomic_dec(&profile_insert_index);
+ return;
+ }
+
+ 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;
+
+ _mali_osk_atomic_inc(&profile_entries_written);
+}
+
+inline void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value)
+{
+ /* Not implemented */
+}
+
+inline mali_bool _mali_osk_profiling_query_hw_counter(u32 counter_id, u32 *event_id)
+{
+ return _MALI_OSK_ERR_UNSUPPORTED;
+}
+
+inline _mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count)
+{
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (prof_state != MALI_PROFILING_STATE_RUNNING)
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ 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;
+
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* wait for all elements to be completely inserted into array */
+ while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written))
+ {
+ /* do nothing */;
+ }
+
+ *count = _mali_osk_atomic_read(&profile_insert_index);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+inline u32 _mali_osk_profiling_get_count(void)
+{
+ u32 retval = 0;
+
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+ if (prof_state == MALI_PROFILING_STATE_RETURN)
+ {
+ retval = _mali_osk_atomic_read(&profile_entries_written);
+ }
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+
+ return retval;
+}
+
+inline _mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
+{
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (prof_state != MALI_PROFILING_STATE_RETURN)
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+ }
+
+ if (index >= _mali_osk_atomic_read(&profile_entries_written))
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ 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];
+
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return _MALI_OSK_ERR_OK;
+}
+
+inline _mali_osk_errcode_t _mali_osk_profiling_clear(void)
+{
+ _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (prof_state != MALI_PROFILING_STATE_RETURN)
+ {
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
+ }
+
+ prof_state = MALI_PROFILING_STATE_IDLE;
+ profile_entry_count = 0;
+ _mali_osk_atomic_init(&profile_insert_index, 0);
+ _mali_osk_atomic_init(&profile_entries_written, 0);
+ if (NULL != profile_entries)
+ {
+ _mali_osk_vfree(profile_entries);
+ profile_entries = NULL;
+ }
+
+ _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ return _MALI_OSK_ERR_OK;
+}
+
+mali_bool _mali_osk_profiling_is_recording(void)
+{
+ return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE;
+}
+
+mali_bool _mali_osk_profiling_have_recording(void)
+{
+ return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE;
+}
+
+void _mali_osk_profiling_set_default_enable_state(mali_bool enable)
+{
+ mali_profiling_default_enable = enable;
+}
+
+mali_bool _mali_osk_profiling_get_default_enable_state(void)
+{
+ return mali_profiling_default_enable;
+}
+
+_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_profiling_get_config(_mali_uk_profiling_get_config_s *args)
+{
+ args->enable_events = mali_profiling_default_enable;
+ return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_specific.h b/drivers/gpu/arm/mali/linux/mali_osk_specific.h
new file mode 100644
index 00000000000..a7ad2fc0cb3
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_specific.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define MALI_STATIC_INLINE static inline
+#define MALI_NON_STATIC_INLINE inline
+
+#ifdef __cplusplus
+}
+#endif
+
+/** The list of events supported by the Mali DDK. */
+typedef enum
+{
+ /* Vertex processor activity */
+ ACTIVITY_VP = 0,
+
+ /* Fragment processor activity */
+ ACTIVITY_FP0,
+ ACTIVITY_FP1,
+ ACTIVITY_FP2,
+ ACTIVITY_FP3,
+
+ /* L2 cache counters */
+ COUNTER_L2_C0,
+ COUNTER_L2_C1,
+
+ /* Vertex processor counters */
+ COUNTER_VP_C0,
+ COUNTER_VP_C1,
+
+ /* Fragment processor counters */
+ COUNTER_FP0_C0,
+ COUNTER_FP0_C1,
+ COUNTER_FP1_C0,
+ COUNTER_FP1_C1,
+ COUNTER_FP2_C0,
+ COUNTER_FP2_C1,
+ COUNTER_FP3_C0,
+ COUNTER_FP3_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
+#define LAST_ACTIVITY_EVENT ACTIVITY_FP3
+
+#define FIRST_HW_COUNTER COUNTER_L2_C0
+#define LAST_HW_COUNTER COUNTER_FP3_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
+
+#endif /* __MALI_OSK_SPECIFIC_H__ */
diff --git a/drivers/gpu/arm/mali/linux/mali_osk_time.c b/drivers/gpu/arm/mali/linux/mali_osk_time.c
new file mode 100644
index 00000000000..b399b874880
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_time.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/mali/linux/mali_osk_timers.c b/drivers/gpu/arm/mali/linux/mali_osk_timers.c
new file mode 100644
index 00000000000..2353fdb6ecf
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_osk_timers.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 = _mali_osk_time_tickcount() + ticks_to_expire;
+ add_timer(&(tim->timer));
+}
+
+void _mali_osk_timer_mod( _mali_osk_timer_t *tim, u32 expiry_tick)
+{
+ MALI_DEBUG_ASSERT_POINTER(tim);
+ mod_timer(&(tim->timer), expiry_tick);
+}
+
+void _mali_osk_timer_del( _mali_osk_timer_t *tim )
+{
+ MALI_DEBUG_ASSERT_POINTER(tim);
+ del_timer_sync(&(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/mali/linux/mali_ukk_core.c b/drivers/gpu/arm/mali/linux/mali_ukk_core.c
new file mode 100644
index 00000000000..6c7fed5d0b6
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_core.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#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_kernel_session_manager.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;
+}
+
+int get_system_info_size_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_size_s __user *uargs)
+{
+ _mali_uk_get_system_info_size_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_get_system_info_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 get_system_info_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_s __user *uargs)
+{
+ _mali_uk_get_system_info_s kargs;
+ _mali_osk_errcode_t err;
+ _mali_system_info *system_info_user;
+ _mali_system_info *system_info_kernel;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ if (0 != get_user(kargs.system_info, &uargs->system_info)) return -EFAULT;
+ if (0 != get_user(kargs.size, &uargs->size)) return -EFAULT;
+
+ /* A temporary kernel buffer for the system_info datastructure is passed through the system_info
+ * member. The ukk_private member will point to the user space destination of this buffer so
+ * that _mali_ukk_get_system_info() can correct the pointers in the system_info correctly
+ * for user space.
+ */
+ system_info_kernel = kmalloc(kargs.size, GFP_KERNEL);
+ if (NULL == system_info_kernel) return -EFAULT;
+
+ system_info_user = kargs.system_info;
+ kargs.system_info = system_info_kernel;
+ kargs.ukk_private = (u32)system_info_user;
+ kargs.ctx = session_data;
+
+ err = _mali_ukk_get_system_info(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ kfree(system_info_kernel);
+ return map_errcode(err);
+ }
+
+ if (0 != copy_to_user(system_info_user, system_info_kernel, kargs.size))
+ {
+ kfree(system_info_kernel);
+ return -EFAULT;
+ }
+
+ kfree(system_info_kernel);
+ 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;
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_gp.c b/drivers/gpu/arm/mali/linux/mali_ukk_gp.c
new file mode 100644
index 00000000000..13a8e25bc41
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_gp.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#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_kernel_session_manager.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_uk_gp_start_job_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+ MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+ if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_gp_start_job_s)))
+ {
+ return -EFAULT;
+ }
+
+ if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_start_job_s))) return -EFAULT;
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_gp_start_job(&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_gp_start_job_s)))
+ {
+ /*
+ * If this happens, then user space will not know that the job was actually started,
+ * and if we return a queued job, then user space will still think that one is still queued.
+ * This will typically lead to a deadlock in user space.
+ * This could however only happen if user space deliberately passes a user buffer which
+ * passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user().
+ * The official Mali driver will never attempt to do that, and kernel space should not be affected.
+ * That is why we do not bother to do a complex rollback in this very very very rare case.
+ */
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int gp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_abort_job_s __user *uargs)
+{
+ _mali_uk_gp_abort_job_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_gp_abort_job_s))) return -EFAULT;
+
+ kargs.ctx = session_data;
+ _mali_ukk_gp_abort_job(&kargs);
+
+ 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/mali/linux/mali_ukk_mem.c b/drivers/gpu/arm/mali/linux/mali_ukk_mem.c
new file mode 100644
index 00000000000..6ec41a59339
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_mem.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#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_kernel_session_manager.h"
+#include "mali_ukk_wrappers.h"
+
+int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs)
+{
+ _mali_uk_init_mem_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_init_mem(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ return map_errcode(err);
+ }
+
+ if (0 != put_user(kargs.mali_address_base, &uargs->mali_address_base)) goto mem_init_rollback;
+ if (0 != put_user(kargs.memory_size, &uargs->memory_size)) goto mem_init_rollback;
+
+ return 0;
+
+mem_init_rollback:
+ {
+ _mali_uk_term_mem_s kargs;
+ kargs.ctx = session_data;
+ err = _mali_ukk_term_mem(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT(4, ("reverting _mali_ukk_init_mem, as a result of failing put_user(), failed\n"));
+ }
+ }
+ return -EFAULT;
+}
+
+int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs)
+{
+ _mali_uk_term_mem_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_term_mem(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ return map_errcode(err);
+ }
+
+ 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 MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+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 /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
+
+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 */
+ 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;
+}
+
+
+
+int mem_get_big_block_wrapper( struct file * filp, _mali_uk_get_big_block_s __user * argument )
+{
+ _mali_uk_get_big_block_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_get_big_block_s)) )
+ {
+ return -EFAULT;
+ }
+
+ /* This interface inserts something into the ukk_private word */
+ uk_args.ukk_private = (u32)filp;
+ uk_args.ctx = filp->private_data;
+ err_code = _mali_ukk_get_big_block( &uk_args );
+
+ /* Do not leak the private word back into user space */
+ uk_args.ukk_private = 0;
+
+ if ( _MALI_OSK_ERR_OK != err_code )
+ {
+ return map_errcode(err_code);
+ }
+
+ /* From this point on, we must roll-back any failing action to preserve the
+ * meaning of the U/K interface (e.g. when excluded) */
+
+ /* transfer response back to user space */
+ if ( 0 != copy_to_user(argument, &uk_args, sizeof(_mali_uk_get_big_block_s)) )
+ {
+ /* Roll-back - the _mali_uk_get_big_block call succeeded, so all
+ * values in uk_args will be correct */
+ _mali_uk_free_big_block_s uk_args_rollback = {0, };
+
+ uk_args_rollback.ctx = uk_args.ctx;
+ uk_args_rollback.cookie = uk_args.cookie;
+ err_code = _mali_ukk_free_big_block( &uk_args_rollback );
+
+ if ( _MALI_OSK_ERR_OK != err_code )
+ {
+ /* error in DEBUG and RELEASE */
+ MALI_PRINT_ERROR( ("Failed to rollback get_big_block: %.8X\n", (u32)err_code) );
+ }
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int mem_free_big_block_wrapper(struct mali_session_data *session_data, _mali_uk_free_big_block_s __user * argument)
+{
+ _mali_uk_free_big_block_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. get_user returns 0 on success */
+ if ( 0 != get_user(uk_args.cookie, &argument->cookie) )
+ {
+ return -EFAULT;
+ }
+
+ uk_args.ctx = session_data;
+ err_code = _mali_ukk_free_big_block( &uk_args );
+
+ /* Return the error that _mali_ukk_free_big_block produced */
+ return map_errcode(err_code);
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_pp.c b/drivers/gpu/arm/mali/linux/mali_ukk_pp.c
new file mode 100644
index 00000000000..98e01739de3
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_pp.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#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_kernel_session_manager.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_uk_pp_start_job_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+ MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+ if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_pp_start_job_s)))
+ {
+ return -EFAULT;
+ }
+
+ if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_start_job_s))) return -EFAULT;
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_pp_start_job(&kargs);
+ if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
+
+ if (0 != put_user(kargs.returned_user_job_ptr, &uargs->returned_user_job_ptr) ||
+ 0 != put_user(kargs.status, &uargs->status))
+ {
+ /*
+ * If this happens, then user space will not know that the job was actually started,
+ * and if we return a queued job, then user space will still think that one is still queued.
+ * This will typically lead to a deadlock in user space.
+ * This could however only happen if user space deliberately passes a user buffer which
+ * passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user().
+ * The official Mali driver will never attempt to do that, and kernel space should not be affected.
+ * That is why we do not bother to do a complex rollback in this very very very rare case.
+ */
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int pp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_abort_job_s __user *uargs)
+{
+ _mali_uk_pp_abort_job_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_abort_job_s))) return -EFAULT;
+
+ kargs.ctx = session_data;
+ _mali_ukk_pp_abort_job(&kargs);
+
+ 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);
+
+ if (0 != put_user(kargs.number_of_cores, &uargs->number_of_cores)) 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;
+}
diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_profiling.c b/drivers/gpu/arm/mali/linux/mali_ukk_profiling.c
new file mode 100644
index 00000000000..ab71b75ff97
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_profiling.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#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_kernel_session_manager.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_get_config_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_config_s __user *uargs)
+{
+ _mali_uk_profiling_get_config_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_profiling_get_config(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ return map_errcode(err);
+ }
+
+ if (0 != put_user(kargs.enable_events, &uargs->enable_events))
+ {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_vsync.c b/drivers/gpu/arm/mali/linux/mali_ukk_vsync.c
new file mode 100644
index 00000000000..d27fac1dae8
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_vsync.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#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_kernel_session_manager.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/mali/linux/mali_ukk_wrappers.h b/drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h
new file mode 100644
index 00000000000..af56efdde43
--- /dev/null
+++ b/drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 get_system_info_size_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_size_s __user *uargs);
+int get_system_info_wrapper(struct mali_session_data *session_data, _mali_uk_get_system_info_s __user *uargs);
+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 post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs);
+int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs);
+int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_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);
+
+#if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0
+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 /* MALI_USE_UNIFIED_MEMORY_PROVIDER */
+
+int mem_get_big_block_wrapper( struct file * filp, _mali_uk_get_big_block_s __user * argument );
+int mem_free_big_block_wrapper( struct mali_session_data *session_data, _mali_uk_free_big_block_s __user * argument);
+int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs);
+int pp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_abort_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 gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs);
+int gp_abort_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_abort_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_get_config_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_config_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/mali/platform/default/mali_platform.c b/drivers/gpu/arm/mali/platform/default/mali_platform.c
new file mode 100644
index 00000000000..d966f25f6c4
--- /dev/null
+++ b/drivers/gpu/arm/mali/platform/default/mali_platform.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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"
+
+
+_mali_osk_errcode_t mali_platform_init(void)
+{
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_deinit(void)
+{
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode)
+{
+ MALI_SUCCESS;
+}
+
+void mali_gpu_utilization_handler(u32 utilization)
+{
+}
+
+void set_mali_parent_power_domain(void* dev)
+{
+}
+
+
diff --git a/drivers/gpu/arm/mali/platform/mali_platform.h b/drivers/gpu/arm/mali/platform/mali_platform.h
new file mode 100644
index 00000000000..078bcefa11b
--- /dev/null
+++ b/drivers/gpu/arm/mali/platform/mali_platform.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_platform.h
+ * Platform specific Mali driver functions
+ */
+
+#ifndef __MALI_PLATFORM_H__
+#define __MALI_PLATFORM_H__
+
+#include "mali_osk.h"
+
+#if !USING_MALI_PMM
+/* @brief System power up/down cores that can be passed into mali_platform_powerdown/up() */
+#define MALI_PLATFORM_SYSTEM 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief description of power change reasons
+ */
+typedef enum mali_power_mode_tag
+{
+ MALI_POWER_MODE_ON,
+ MALI_POWER_MODE_LIGHT_SLEEP,
+ MALI_POWER_MODE_DEEP_SLEEP,
+} 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
+ *
+ * Call as part of platform init if there is no PMM support, else the
+ * PMM will call it.
+ * There are three power modes defined:
+ * 1) MALI_POWER_MODE_ON
+ * 2) MALI_POWER_MODE_LIGHT_SLEEP
+ * 3) MALI_POWER_MODE_DEEP_SLEEP
+ * MALI power management module transitions to MALI_POWER_MODE_LIGHT_SLEEP mode when MALI is idle
+ * for idle timer (software timer defined in mali_pmm_policy_jobcontrol.h) duration, MALI transitions
+ * to MALI_POWER_MODE_LIGHT_SLEEP mode during timeout if there are no more jobs queued.
+ * MALI power management module transitions to MALI_POWER_MODE_DEEP_SLEEP mode when OS does system power
+ * off.
+ * Customer has to add power down code when MALI transitions to MALI_POWER_MODE_LIGHT_SLEEP or MALI_POWER_MODE_DEEP_SLEEP
+ * mode.
+ * MALI_POWER_MODE_ON mode is entered when the MALI is to powered up. Some customers want to control voltage regulators during
+ * the whole system powers on/off. Customer can track in this function whether the MALI is powered up from
+ * MALI_POWER_MODE_LIGHT_SLEEP or MALI_POWER_MODE_DEEP_SLEEP mode and manage the voltage regulators as well.
+ * @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(u32 utilization);
+
+/** @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/mali/readme.txt b/drivers/gpu/arm/mali/readme.txt
new file mode 100644
index 00000000000..fadafe67a97
--- /dev/null
+++ b/drivers/gpu/arm/mali/readme.txt
@@ -0,0 +1,30 @@
+Building the Mali Device Driver for Linux
+-----------------------------------------
+
+Build the Mali Device Driver for Linux by running the following make command:
+
+KDIR=<kdir_path> USING_UMP=<ump_option> USING_PMM=<pmm_option> BUILD=<build_option> \
+TARGET_PLATFORM=<target_platform> CONFIG=<your_config> make
+
+where
+ kdir_path: Path to your Linux Kernel directory
+ ump_option: 1 = Enable UMP support(*)
+ 0 = disable UMP support
+ pmm_option: 1 = Enable power management
+ 0 = Disable power management
+ build_option: debug = debug build of driver
+ release = release build of driver
+ target_platform: Name of the sub-folder in platform/ that contains the
+ required mali_platform.c file.
+ your_config: Name of the sub-folder to find the required config.h(**) file
+ ("arch-" will be prepended)
+
+(*) For newer Linux Kernels, the Module.symvers file for the UMP device driver
+ must be available. The UMP_SYMVERS_FILE variable in the Makefile should
+ point to this file. This file is generated when the UMP driver is built.
+
+(**) The config.h file contains the configuration parameters needed, like where the
+ Mali GPU is located, interrupts it uses, memory and so on.
+
+The result will be a mali.ko file, which can be loaded into the Linux kernel
+by using the insmod command.
diff --git a/drivers/gpu/arm/mali/regs/mali_200_regs.h b/drivers/gpu/arm/mali/regs/mali_200_regs.h
new file mode 100644
index 00000000000..36981043266
--- /dev/null
+++ b/drivers/gpu/arm/mali/regs/mali_200_regs.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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_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),
+#if defined(USING_MALI200)
+ MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES = (1<<3),
+#endif
+ MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET = (1<<5),
+ MALI200_REG_VAL_CTRL_MGMT_START_RENDERING = (1<<6),
+#if defined(USING_MALI400)
+ MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7),
+#endif
+};
+
+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),
+};
+
+#if defined USING_MALI200
+#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))
+#elif defined USING_MALI400
+#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))
+#else
+#error "No supported mali core defined"
+#endif
+
+#if defined USING_MALI200
+#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\
+ MALI200_REG_VAL_IRQ_END_OF_FRAME |\
+ MALI200_REG_VAL_IRQ_HANG |\
+ MALI200_REG_VAL_IRQ_FORCE_HANG |\
+ MALI200_REG_VAL_IRQ_BUS_ERROR |\
+ MALI200_REG_VAL_IRQ_WRITE_BOUNDARY_ERROR))
+#elif defined USING_MALI400
+#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\
+ MALI200_REG_VAL_IRQ_END_OF_FRAME |\
+ 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_WRITE_BOUNDARY_ERROR |\
+ MALI400PP_REG_VAL_IRQ_INVALID_PLIST_COMMAND |\
+ MALI400PP_REG_VAL_IRQ_CALL_STACK_UNDERFLOW |\
+ MALI400PP_REG_VAL_IRQ_CALL_STACK_OVERFLOW))
+#else
+#error "No supported mali core defined"
+#endif
+
+#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,
+};
+
+#if defined USING_MALI200
+#define MALI200_NUM_REGS_FRAME ((0x04C/4)+1)
+#elif defined USING_MALI400
+#define MALI200_NUM_REGS_FRAME ((0x058/4)+1)
+#else
+#error "No supported mali core defined"
+#endif
+
+enum mali200_wb_unit {
+ MALI200_REG_ADDR_WB0 = 0x0100,
+ MALI200_REG_ADDR_WB1 = 0x0200,
+ MALI200_REG_ADDR_WB2 = 0x0300
+};
+
+/** The number of registers in one single writeback unit */
+#ifndef MALI200_NUM_REGS_WBx
+#define MALI200_NUM_REGS_WBx ((0x02C/4)+1)
+#endif
+
+/* This should be in the top 16 bit of the version register of Mali PP */
+#if defined USING_MALI200
+#define MALI_PP_PRODUCT_ID 0xC807
+#elif defined USING_MALI400
+#define MALI300_PP_PRODUCT_ID 0xCE07
+#define MALI400_PP_PRODUCT_ID 0xCD07
+#define MALI_PP_PRODUCT_ID MALI400_PP_PRODUCT_ID
+#else
+#error "No supported mali core defined"
+#endif
+
+
+#endif /* _MALI200_REGS_H_ */
diff --git a/drivers/gpu/arm/mali/regs/mali_gp_regs.h b/drivers/gpu/arm/mali/regs/mali_gp_regs.h
new file mode 100644
index 00000000000..2b1c021c204
--- /dev/null
+++ b/drivers/gpu/arm/mali/regs/mali_gp_regs.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _MALIGP2_CONROL_REGS_H_
+#define _MALIGP2_CONROL_REGS_H_
+
+/**
+ * These are the different geometry processor controll registers.
+ * Their usage is to control and monitor the operation of the
+ * Vertex Shader and the Polygon List Builer 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),
+#if defined(USING_MALI400)
+ MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10),
+#endif
+} 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)
+#if defined USING_MALI400
+#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)
+#elif !defined USING_MALI200
+#error "No supported mali core defined"
+#endif
+
+/* Mask defining all IRQs in MaliGP2 */
+#if defined USING_MALI200
+#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)
+#elif defined USING_MALI400
+#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)
+#else
+#error "No supported mali core defined"
+#endif
+
+/* Mask defining the IRQs in MaliGP2 which we use*/
+#if defined USING_MALI200
+#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_HANG | \
+ 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)
+#elif defined USING_MALI400
+#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_HANG | \
+ 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)
+#else
+#error "No supported mali core defined"
+#endif
+
+/* 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.*/
+#if defined(USING_MALI200)
+#define MALI_GP_PRODUCT_ID 0xA07
+#elif defined(USING_MALI400)
+#define MALI300_GP_PRODUCT_ID 0xC07
+#define MALI400_GP_PRODUCT_ID 0xB07
+#define MALI_GP_PRODUCT_ID MALI400_GP_PRODUCT_ID
+#else
+#error "No supported mali core defined"
+#endif
+
+/**
+ * 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/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.c
new file mode 100644
index 00000000000..24268534821
--- /dev/null
+++ b/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h
new file mode 100644
index 00000000000..05517260cad
--- /dev/null
+++ b/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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/mali/timestamp-default/mali_timestamp.c b/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.c
new file mode 100644
index 00000000000..24268534821
--- /dev/null
+++ b/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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/mali/timestamp-default/mali_timestamp.h b/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h
new file mode 100644
index 00000000000..e6d3f2aaf51
--- /dev/null
+++ b/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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/ump/Kconfig b/drivers/gpu/arm/ump/Kconfig
new file mode 100644
index 00000000000..62f1cec9311
--- /dev/null
+++ b/drivers/gpu/arm/ump/Kconfig
@@ -0,0 +1,19 @@
+config UMP
+ bool "Enable UMP(Unified Memory Provider)"
+ default n
+ ---help---
+ This enables UMP memory provider
+
+config UMP_MEM_SIZE
+ int "UMP Memory Size"
+ depends on UMP
+ default "64"
+ ---help---
+ This value decide memory size of UMP (unit is MByte).
+
+config UMP_DEBUG
+ bool "Enables debug messages"
+ depends on UMP
+ default n
+ ---help---
+ This enables UMP driver debug messages
diff --git a/drivers/gpu/arm/ump/Makefile b/drivers/gpu/arm/ump/Makefile
new file mode 100755
index 00000000000..a560b160da4
--- /dev/null
+++ b/drivers/gpu/arm/ump/Makefile
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the GNU General Public License version 2
+# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained from Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+ifeq ($(CONFIG_USING_OS_MEMORY),y)
+USING_MEMORY_TYPE=1
+endif
+
+UMP_FILE_PREFIX =
+UDD_FILE_PREFIX := drivers/gpu/arm/ump/
+
+# For each arch check: CROSS_COMPILE , KDIR , CFLAGS += -DARCH
+
+## @note Should allow overriding of building UMP for non-debug:
+
+ifeq (($CONFIG_UMP_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+EXTRA_CFLAGS += -DMALI_STATE_TRACKING=0
+USING_MEMORY_TYPE ?=0 # 0: dedicated memory 1: OS memory
+
+EXTRA_CFLAGS += -I$(UDD_FILE_PREFIX) -I$(UDD_FILE_PREFIX)/common -I$(UDD_FILE_PREFIX)/linux -I$(UDD_FILE_PREFIX)/../mali/common -I$(UDD_FILE_PREFIX)/../mali/linux -I$(UDD_FILE_PREFIX)/include
+
+EXTRA_CFLAGS += -DUMP_MEMORY_TYPE=$(USING_MEMORY_TYPE)
+# 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 $(UDD_FILE_PREFIX)/linux/license/gpl/*),)
+EXTRA_CFLAGS += -I$(UDD_FILE_PREFIX)/linux/license/proprietary
+else
+EXTRA_CFLAGS += -I$(UDD_FILE_PREFIX)/linux/license/gpl
+endif
+
+obj-$(CONFIG_UMP) += ump.o
+
+ump-y:= $(UMP_FILE_PREFIX)common/ump_kernel_common.o \
+ $(UMP_FILE_PREFIX)common/ump_kernel_descriptor_mapping.o \
+ $(UMP_FILE_PREFIX)common/ump_kernel_api.o \
+ $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.o \
+ $(UMP_FILE_PREFIX)linux/ump_kernel_linux.o \
+ $(UMP_FILE_PREFIX)linux/ump_kernel_memory_backend_os.o \
+ $(UMP_FILE_PREFIX)linux/ump_kernel_memory_backend_dedicated.o \
+ $(UMP_FILE_PREFIX)linux/ump_memory_backend.o \
+ $(UMP_FILE_PREFIX)linux/ump_ukk_wrappers.o \
+ $(UMP_FILE_PREFIX)linux/ump_ukk_ref_wrappers.o \
+ $(UMP_FILE_PREFIX)linux/ump_osk_atomics.o \
+ $(UMP_FILE_PREFIX)linux/ump_osk_low_level_mem.o \
+ $(UMP_FILE_PREFIX)linux/ump_osk_misc.o \
+ $(UMP_FILE_PREFIX)../mali/linux/mali_osk_atomics.o \
+ $(UMP_FILE_PREFIX)../mali/linux/mali_osk_locks.o \
+ $(UMP_FILE_PREFIX)../mali/linux/mali_osk_memory.o \
+ $(UMP_FILE_PREFIX)../mali/linux/mali_osk_math.o \
+ $(UMP_FILE_PREFIX)../mali/linux/mali_osk_misc.o
+
+# Get subversion revision number, fall back to 0000 if no svn info is available
+SVN_REV:=$(shell ((svnversion | grep -qvE '(exported|Unversioned)' && 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/ump/arch/config.h b/drivers/gpu/arm/ump/arch/config.h
new file mode 100644
index 00000000000..6efc91e4bc9
--- /dev/null
+++ b/drivers/gpu/arm/ump/arch/config.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT UMP_MEMORY_TYPE
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0xC8000000
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT CONFIG_UMP_MEM_SIZE * 1024UL * 1024UL
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/drivers/gpu/arm/ump/common/ump_kernel_api.c b/drivers/gpu/arm/ump/common/ump_kernel_api.c
new file mode 100644
index 00000000000..c6ea89634b1
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_api.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ 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_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id));
+ return UMP_DD_HANDLE_INVALID;
+ }
+
+ ump_dd_reference_add(mem);
+
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ 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(4, ("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_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ new_ref = _ump_osk_atomic_dec_and_read(&mem->ref_count);
+
+ DBG_MSG(4, ("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_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ mem->release_func(mem->ctx, mem);
+ _mali_osk_free(mem);
+ }
+ else
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ }
+}
+
+
+
+/* --------------- 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_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ _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_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ 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_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ 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_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ 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_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem);
+
+ if (NULL == mem)
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ 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_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* 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_ukk_msync FLUSHING ID: %u Enabled: %d OP: %d Address: 0x%08x Mapping: 0x%08x\n",
+ (ump_secure_id)args->secure_id, mem->is_cached, 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);
+
+msync_release_and_return:
+ ump_dd_reference_release(mem);
+ return;
+}
diff --git a/drivers/gpu/arm/ump/common/ump_kernel_common.c b/drivers/gpu/arm/ump/common/ump_kernel_common.c
new file mode 100644
index 00000000000..946286c83c5
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_common.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0 , 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_lock_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_lock_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_lock_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_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 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_lock_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;
+
+ 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_lock_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_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_list_add( &descriptor->list, &session_data->list_head_session_memory_mappings_list );
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ 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_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_list_del( &descriptor->list );
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ 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/ump/common/ump_kernel_common.h b/drivers/gpu/arm/ump/common/ump_kernel_common.h
new file mode 100644
index 00000000000..3e3636a0401
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_common.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __UMP_KERNEL_H__
+#define __UMP_KERNEL_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_lock_t * lock;
+ ump_descriptor_mapping * cookies_map; /**< Secure mapping of cookies from _ump_ukk_map_mem() */
+} 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_lock_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_H__ */
diff --git a/drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.c b/drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.c
new file mode 100644
index 00000000000..d6b59b74e35
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_READERWRITER, 0 , 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_lock_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_lock_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_lock_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_lock_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_lock_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_lock_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_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RO);
+ return result;
+}
+
+void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor)
+{
+ _mali_osk_lock_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_lock_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/ump/common/ump_kernel_descriptor_mapping.h b/drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.h
new file mode 100644
index 00000000000..05b39827ce3
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_descriptor_mapping.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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_lock_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/ump/common/ump_kernel_memory_backend.h b/drivers/gpu/arm/ump/common/ump_kernel_memory_backend.h
new file mode 100644
index 00000000000..a91ae28672a
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_memory_backend.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/common/ump_kernel_ref_drv.c b/drivers/gpu/arm/ump/common/ump_kernel_ref_drv.c
new file mode 100644
index 00000000000..e98f801cb96
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_ref_drv.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*) mem);
+
+ if (map_id < 0)
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ _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_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ _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;
+
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ 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_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*)new_allocation);
+
+ if (map_id < 0)
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ _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 */
+
+ /* 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_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_free(new_allocation);
+ _mali_osk_free(session_memory_element);
+ return _MALI_OSK_ERR_INVALID_FUNC;
+ }
+
+ new_allocation->ctx = device.backend->ctx;
+ new_allocation->release_func = device.backend->release;
+
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* Initialize the session_memory_element, and add it to the session object */
+ session_memory_element->mem = new_allocation;
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list));
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ 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/ump/common/ump_kernel_types.h b/drivers/gpu/arm/ump/common/ump_kernel_types.h
new file mode 100644
index 00000000000..fa3d9fb8e70
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_kernel_types.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __UMP_KERNEL_TYPES_H__
+#define __UMP_KERNEL_TYPES_H__
+
+#include "ump_kernel_interface.h"
+#include "mali_osk.h"
+
+/*
+ * 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_dd_mem;
+
+
+
+#endif /* __UMP_KERNEL_TYPES_H__ */
diff --git a/drivers/gpu/arm/ump/common/ump_osk.h b/drivers/gpu/arm/ump/common/ump_osk.h
new file mode 100644
index 00000000000..56ec0704831
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_osk.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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"
+
+#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 );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/arm/ump/common/ump_uk_types.h b/drivers/gpu/arm/ump/common/ump_uk_types.h
new file mode 100644
index 00000000000..ac0f1ceef41
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_uk_types.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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_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_uk_alloc_constraints;
+
+typedef enum
+{
+ _UMP_UK_MSYNC_CLEAN = 0,
+ _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1,
+ _UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128,
+} ump_uk_msync_op;
+
+/**
+ * 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] cookie stored with reference to the kernel mapping internals */
+ u32 is_cached; /**< [out] caching of CPU mappings */
+} _ump_uk_msync_s;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_UK_TYPES_H__ */
diff --git a/drivers/gpu/arm/ump/common/ump_ukk.h b/drivers/gpu/arm/ump/common/ump_ukk.h
new file mode 100644
index 00000000000..ff517684198
--- /dev/null
+++ b/drivers/gpu/arm/ump/common/ump_ukk.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 );
+
+u32 _ump_ukk_report_memory_usage( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_UKK_H__ */
diff --git a/drivers/gpu/arm/ump/include/ump_kernel_interface.h b/drivers/gpu/arm/ump/include/ump_kernel_interface.h
new file mode 100644
index 00000000000..042c8b1b45b
--- /dev/null
+++ b/drivers/gpu/arm/ump/include/ump_kernel_interface.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/include/ump_kernel_interface_ref_drv.h b/drivers/gpu/arm/ump/include/ump_kernel_interface_ref_drv.h
new file mode 100644
index 00000000000..c9937461a0f
--- /dev/null
+++ b/drivers/gpu/arm/ump/include/ump_kernel_interface_ref_drv.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/include/ump_kernel_platform.h b/drivers/gpu/arm/ump/include/ump_kernel_platform.h
new file mode 100644
index 00000000000..4349605e859
--- /dev/null
+++ b/drivers/gpu/arm/ump/include/ump_kernel_platform.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/license/gpl/ump_kernel_license.h b/drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h
new file mode 100644
index 00000000000..17b930d2c57
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_ioctl.h b/drivers/gpu/arm/ump/linux/ump_ioctl.h
new file mode 100644
index 00000000000..531de737137
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_ioctl.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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_size_get_s)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMP_IOCTL_H__ */
diff --git a/drivers/gpu/arm/ump/linux/ump_kernel_linux.c b/drivers/gpu/arm/ump/linux/ump_kernel_linux.c
new file mode 100644
index 00000000000..5bc06513b4b
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_kernel_linux.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#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 <mach-exynos/ump/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 "license/gpl/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 = 243;
+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;
+
+ default:
+ DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg));
+ err = -EFAULT;
+ break;
+ }
+
+ return err;
+}
+#ifndef CONFIG_MALI400MP
+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;
+ }
+}
+#endif
+
+/*
+ * 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/ump/linux/ump_kernel_linux.h b/drivers/gpu/arm/ump/linux/ump_kernel_linux.h
new file mode 100644
index 00000000000..4ec5a4760c1
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_kernel_linux.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __UMP_KERNEL_H__
+#define __UMP_KERNEL_H__
+
+int ump_kernel_device_initialize(void);
+void ump_kernel_device_terminate(void);
+
+
+#endif /* __UMP_KERNEL_H__ */
diff --git a/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c
new file mode 100644
index 00000000000..463e6097ead
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/* 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_allocator) * 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/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.h
new file mode 100644
index 00000000000..ca8faae847f
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_kernel_memory_backend_os.c b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c
new file mode 100644
index 00000000000..fc3afa89fd6
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/* 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/ump/linux/ump_kernel_memory_backend_os.h b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.h
new file mode 100644
index 00000000000..6f7e610324f
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_memory_backend.c b/drivers/gpu/arm/ump/linux/ump_memory_backend.c
new file mode 100644
index 00000000000..1e5e3cc9373
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_memory_backend.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h> /* kernel module definitions */
+#include <linux/ioport.h> /* request_mem_region */
+
+#include <mach-exynos/ump/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"
+
+/* 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)
+ {
+ 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/ump/linux/ump_osk_atomics.c b/drivers/gpu/arm/ump/linux/ump_osk_atomics.c
new file mode 100644
index 00000000000..b117d99bd77
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_osk_atomics.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_osk_low_level_mem.c b/drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c
new file mode 100644
index 00000000000..b37fd28721a
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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;
+ vma->vm_flags |= VM_RESERVED;
+
+ 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;
+}
+
+
+void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op )
+{
+ int i;
+ const void *start_v, *end_v;
+
+ DBG_MSG(3, ("Flushing nr of blocks: %u, size: %u. First: paddr: 0x%08x vaddr: 0x%08x offset: 0x%08x size:%uB\n",
+ mem->nr_blocks, mem->size_bytes, mem->block_array[0].addr, virt, offset, size));
+
+ /* 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(access_ok(VERIFY_WRITE, virt, size))
+ {
+ start_v = (void *)virt;
+ end_v = (void *)(start_v + size - 1);
+ /* There is no dmac_clean_range, so the L1 is always flushed,
+ * also for UMP_MSYNC_CLEAN. */
+ dmac_flush_range(start_v, end_v);
+ }
+ else
+ {
+ DBG_MSG(1, ("Attempt to flush %d@%x as part of ID %u rejected: there is no valid mapping.\n",
+ size, virt, mem->secure_id));
+ return;
+ }
+
+ /* 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;
+ default:
+ break;
+ }
+
+ if(0 == size)
+ {
+ /* Nothing left to flush. */
+ break;
+ }
+ }
+
+ return;
+}
diff --git a/drivers/gpu/arm/ump/linux/ump_osk_misc.c b/drivers/gpu/arm/ump/linux/ump_osk_misc.c
new file mode 100644
index 00000000000..3be6fedcb0b
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_osk_misc.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_ukk_ref_wrappers.c b/drivers/gpu/arm/ump/linux/ump_ukk_ref_wrappers.c
new file mode 100644
index 00000000000..6a2791e28c2
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_ukk_ref_wrappers.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_ukk_ref_wrappers.h b/drivers/gpu/arm/ump/linux/ump_ukk_ref_wrappers.h
new file mode 100644
index 00000000000..a3e3cb0c2f6
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_ukk_ref_wrappers.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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/ump/linux/ump_ukk_wrappers.c b/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c
new file mode 100644
index 00000000000..7fa805993b8
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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 */
+}
diff --git a/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.h b/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.h
new file mode 100644
index 00000000000..b04445a2c7a
--- /dev/null
+++ b/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* __UMP_UKK_WRAPPERS_H__ */
diff --git a/drivers/gpu/arm/ump/readme.txt b/drivers/gpu/arm/ump/readme.txt
new file mode 100644
index 00000000000..c238cf0f2b1
--- /dev/null
+++ b/drivers/gpu/arm/ump/readme.txt
@@ -0,0 +1,28 @@
+Building the UMP Device Driver for Linux
+----------------------------------------
+
+Build the UMP Device Driver for Linux by running the following make command:
+
+KDIR=<kdir_path> CONFIG=<your_config> BUILD=<build_option> make
+
+where
+ kdir_path: Path to your Linux Kernel directory
+ your_config: Name of the sub-folder to find the required config.h file
+ ("arch-" will be prepended)
+ build_option: debug or release. Debug is default.
+
+The config.h contains following configuration parameters:
+
+ARCH_UMP_BACKEND_DEFAULT
+ 0 specifies the dedicated memory allocator.
+ 1 specifies the OS memory allocator.
+ARCH_UMP_MEMORY_ADDRESS_DEFAULT
+ This is only required for the dedicated memory allocator, and specifies
+ the physical start address of the memory block reserved for UMP.
+ARCH_UMP_MEMORY_SIZE_DEFAULT
+ This specified the size of the memory block reserved for UMP, or the
+ maximum limit for allocations from the OS.
+
+The result will be a ump.ko file, which can be loaded into the Linux kernel
+by using the insmod command. The driver can also be built as a part of the
+kernel itself.
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 90e28081712..8a6557f3476 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -180,6 +180,13 @@ config DRM_SAVAGE
Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
chipset. If M is selected the module will be called savage.
+config DRM_MALI
+ tristate "Mali-200, Mali-400 GPU"
+ depends on DRM && UMP
+ help
+ Choose this option if you have a Mali-200, Mali-400 or compatible GPU
+ chipset. If M is selected the module will be called mali.
+
source "drivers/gpu/drm/exynos/Kconfig"
source "drivers/gpu/drm/vmwgfx/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f65f65ed0dd..1d34d48468c 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -45,4 +45,5 @@ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
obj-$(CONFIG_DRM_GMA500) += gma500/
obj-$(CONFIG_DRM_UDL) += udl/
obj-$(CONFIG_DRM_AST) += ast/
+obj-$(CONFIG_DRM_MALI) +=mali/
obj-y += i2c/
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index b3cb0a69fbf..7767dfbdd88 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -23,6 +23,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm.h"
#include "exynos_drm.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index d9568198c30..cbcdb6ecf6b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -25,6 +25,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm_crtc_helper.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 84dd099eae3..87cd65734ba 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -26,6 +26,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index abb1e2f8227..29499d8f83c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -26,6 +26,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm_crtc_helper.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index d0707193745..8563335b54e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -25,6 +25,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm.h"
#include "drm_crtc_helper.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 2c037cd7d2d..ba520a50e09 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -26,6 +26,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm_crtc_helper.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 4ccfe4328fa..53a1f06558b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -26,6 +26,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index d5586cc7516..0905466f747 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -26,6 +26,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm_crtc.h"
#include "drm_fb_helper.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index a38051c95ec..17102e1f42d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -23,6 +23,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/module.h>
+
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/gpu/drm/mali/Makefile b/drivers/gpu/drm/mali/Makefile
new file mode 100644
index 00000000000..68ee68c03c5
--- /dev/null
+++ b/drivers/gpu/drm/mali/Makefile
@@ -0,0 +1,20 @@
+#
+# * Copyright (C) 2010 ARM Limited. All rights reserved.
+# *
+# * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+# * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+# *
+# * A copy of the licence is included with the program, and can also be obtained from Free Software
+# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+#
+# Makefile for the Mali drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y = -Iinclude/drm
+mali_drm-y := mali_drv.o
+
+obj-$(CONFIG_DRM_MALI) += mali_drm.o
+
+
diff --git a/drivers/gpu/drm/mali/mali_drv.c b/drivers/gpu/drm/mali/mali_drv.c
new file mode 100644
index 00000000000..ec6fdcacb7d
--- /dev/null
+++ b/drivers/gpu/drm/mali/mali_drv.c
@@ -0,0 +1,177 @@
+/**
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file mali_drv.c
+ * Implementation of the Linux device driver entrypoints for Mali DRM
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/vermagic.h>
+#include "drmP.h"
+#include "mali_drv.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+static struct pci_device_id pciidlist[] = {
+ /*need to fill this with right id lists*/
+};
+
+static struct pci_driver mali_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+};
+#endif
+
+void mali_drm_preclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+}
+
+void mali_drm_lastclose(struct drm_device *dev)
+{
+}
+
+static int mali_drm_suspend(struct drm_device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+static int mali_drm_resume(struct drm_device *dev)
+{
+ return 0;
+}
+
+static int mali_drm_load(struct drm_device *dev, unsigned long chipset)
+{
+ return 0;
+}
+
+static int mali_drm_unload(struct drm_device *dev)
+{
+ return 0;
+}
+
+static const struct file_operations drm_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+ .mmap = drm_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+};
+
+static struct drm_driver driver =
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+ .driver_features = DRIVER_USE_PLATFORM_DEVICE,
+#endif
+ .load = mali_drm_load,
+ .unload = mali_drm_unload,
+ .context_dtor = NULL,
+ .reclaim_buffers = NULL,
+ .reclaim_buffers_idlelocked = NULL,
+ .preclose = mali_drm_preclose,
+ .lastclose = mali_drm_lastclose,
+ .suspend = mali_drm_suspend,
+ .resume = mali_drm_resume,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+#endif
+ .ioctls = NULL,
+ .fops = &drm_fops,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+int mali_drm_init(struct platform_device *dev)
+{
+ printk(KERN_INFO "Mali DRM initialize, driver name: %s, version %d.%d\n", DRIVER_NAME, DRIVER_MAJOR, DRIVER_MINOR);
+ driver.num_ioctls = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+ driver.platform_device = dev;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+ return drm_init(&driver);
+#else
+ return drm_pci_init(&driver, &mali_pci_driver);
+#endif
+}
+
+void mali_drm_exit(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+ drm_exit(&driver);
+#else
+ drm_pci_exit(&driver, &mali_pci_driver);
+#endif
+}
+
+static int __devinit mali_platform_drm_probe(struct platform_device *dev)
+{
+ return mali_drm_init(dev);
+}
+
+static int mali_platform_drm_remove(struct platform_device *dev)
+{
+ mali_drm_exit();
+
+ return 0;
+}
+
+static int mali_platform_drm_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+static int mali_platform_drm_resume(struct platform_device *dev)
+{
+ return 0;
+}
+
+
+static struct platform_driver platform_drm_driver = {
+ .probe = mali_platform_drm_probe,
+ .remove = __devexit_p(mali_platform_drm_remove),
+ .suspend = mali_platform_drm_suspend,
+ .resume = mali_platform_drm_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ },
+};
+
+static int __init mali_platform_drm_init(void)
+{
+ return platform_driver_register( &platform_drm_driver );
+}
+
+static void __exit mali_platform_drm_exit(void)
+{
+ platform_driver_unregister( &platform_drm_driver );
+}
+
+#ifdef MODULE
+module_init(mali_platform_drm_init);
+#else
+late_initcall(mali_platform_drm_init);
+#endif
+module_exit(mali_platform_drm_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE(DRIVER_LICENCE);
+MODULE_ALIAS(DRIVER_ALIAS);
+MODULE_INFO(vermagic, VERMAGIC_STRING);
diff --git a/drivers/gpu/drm/mali/mali_drv.h b/drivers/gpu/drm/mali/mali_drv.h
new file mode 100644
index 00000000000..aed5fd356b7
--- /dev/null
+++ b/drivers/gpu/drm/mali/mali_drv.h
@@ -0,0 +1,25 @@
+/**
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _MALI_DRV_H_
+#define _MALI_DRV_H_
+
+#define DRIVER_AUTHOR "ARM Ltd."
+#define DRIVER_NAME "mali_drm"
+#define DRIVER_DESC "DRM module for Mali-200, Mali-400"
+#define DRIVER_LICENSE "GPLv2"
+#define DRIVER_ALIAS "platform:mali_drm"
+#define DRIVER_DATE "20101111"
+#define DRIVER_VERSION "0.2"
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 1
+#define DRIVER_PATCHLEVEL 1
+
+#endif /* _MALI_DRV_H_ */
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 5099ceebc62..8a89693ff4d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -906,4 +906,11 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_UNIDISPLAY_TS
+ tristate "Pixcir capacitive touchscreen driver"
+ depends on I2C
+ help
+ Say Y here if you have a Pixcir capacitive based touchscreen
+ controller.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index d6bac0bfc3f..8e903cf8e1a 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -74,3 +74,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_UNIDISPLAY_TS) += unidisplay_ts.o
diff --git a/drivers/input/touchscreen/unidisplay_ts.c b/drivers/input/touchscreen/unidisplay_ts.c
new file mode 100644
index 00000000000..fecbbd6b8eb
--- /dev/null
+++ b/drivers/input/touchscreen/unidisplay_ts.c
@@ -0,0 +1,404 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/of_irq.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/gpio.h>
+
+#include <mach/regs-gpio.h>
+
+#include <plat/gpio-cfg.h>
+
+/* 20 ms */
+#define TOUCH_READ_TIME msecs_to_jiffies(20)
+
+#define TOUCH_INT_PIN EXYNOS4_GPX3(1)
+#define TOUCH_INT_PIN_SHIFT 1
+#define TOUCH_RST_PIN EXYNOS4_GPE3(5)
+
+#define TOUCHSCREEN_MINX 0
+#define TOUCHSCREEN_MAXX 3968
+#define TOUCHSCREEN_MINY 0
+#define TOUCHSCREEN_MAXY 2304
+#define TOUCH_DEBUG
+#ifdef TOUCH_DEBUG
+#define DEBUG_PRINT(fmt, args...) printk(fmt, ##args)
+#else
+#define DEBUG_PRINT(fmt, args...)
+#endif
+
+#define INPUT_REPORT(x, y, p, val1, val2) \
+ { \
+ input_report_abs(tsdata->input, ABS_MT_POSITION_X, x); \
+ input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y); \
+ input_report_abs(tsdata->input, ABS_MT_TOUCH_MAJOR, p); \
+ input_report_abs(tsdata->input, ABS_PRESSURE, val1); \
+ input_report_key(tsdata->input, BTN_TOUCH, val2); \
+ input_mt_sync(tsdata->input); \
+ }
+
+struct unidisplay_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct task_struct *kidle_task;
+ wait_queue_head_t idle_wait;
+ struct delayed_work work;
+ int irq;
+ unsigned int irq_pending;
+};
+
+
+static irqreturn_t unidisplay_ts_isr(int irq, void *dev_id);
+
+static void unidisplay_ts_config(void)
+{
+ s3c_gpio_cfgpin(TOUCH_INT_PIN, S3C_GPIO_SFN(0x0F));
+ s3c_gpio_setpull(TOUCH_INT_PIN, S3C_GPIO_PULL_UP);
+
+ if (gpio_request(TOUCH_INT_PIN, "TOUCH_INT_PIN")) {
+ pr_err("%s : gpio request failed.\n", __func__);
+ return;
+ }
+ gpio_direction_input(TOUCH_INT_PIN);
+ gpio_free(TOUCH_INT_PIN);
+
+ s3c_gpio_setpull(TOUCH_RST_PIN, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(TOUCH_RST_PIN, S3C_GPIO_OUTPUT);
+
+ if (gpio_request(TOUCH_RST_PIN, "TOUCH_RST_PIN")) {
+ pr_err("%s : gpio request failed.\n", __func__);
+ return;
+ }
+ gpio_direction_output(TOUCH_RST_PIN, 1);
+ gpio_free(TOUCH_RST_PIN);
+}
+
+static void unidisplay_ts_start(void)
+{
+ if (gpio_request(TOUCH_RST_PIN, "TOUCH_RST_PIN")) {
+ pr_err("%s : gpio request failed.\n", __func__);
+ return;
+ }
+ gpio_set_value(TOUCH_RST_PIN, 0);
+ gpio_free(TOUCH_RST_PIN);
+}
+
+static void unidisplay_ts_stop(void)
+{
+ if (gpio_request(TOUCH_RST_PIN, "TOUCH_RST_PIN")) {
+ pr_err("%s : gpio request failed.\n", __func__);
+ return;
+ }
+ gpio_set_value(TOUCH_RST_PIN, 1);
+ gpio_free(TOUCH_RST_PIN);
+}
+
+static void unidisplay_ts_reset(void)
+{
+ unidisplay_ts_stop();
+ udelay(100);
+ unidisplay_ts_start();
+}
+
+static int unidisplay_ts_pen_up(void)
+{
+ return (gpio_get_value(TOUCH_INT_PIN) & 0x1);
+}
+
+static irqreturn_t unidisplay_ts_isr(int irq, void *dev_id)
+{
+ struct unidisplay_ts_data *tsdata = dev_id;
+ if (irq == tsdata->irq) {
+ disable_irq_nosync(tsdata->irq);
+ tsdata->irq_pending = 1;
+ wake_up(&tsdata->idle_wait);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static int unidisplay_ts_thread(void *kthread)
+{
+ struct unidisplay_ts_data *tsdata = kthread;
+ struct task_struct *tsk = current;
+ int ret = 0;
+ struct sched_param param = { .sched_priority = 1 };
+ sched_setscheduler(tsk, SCHED_FIFO, &param);
+ set_freezable();
+ while (!kthread_should_stop()) {
+ int x1 = 0, y1 = 0;
+ u8 buf[9];
+ u8 type = 0;
+ unsigned int pendown = 0;
+ long timeout = 0;
+ if (tsdata->irq_pending) {
+ tsdata->irq_pending = 0;
+ enable_irq(tsdata->irq);
+ }
+ pendown = !unidisplay_ts_pen_up();
+ if (pendown) {
+ u8 addr = 0x10;
+ memset(buf, 0, sizeof(buf));
+ ret = i2c_master_send(tsdata->client, &addr, 1);
+ if (ret != 1) {
+ dev_err(&tsdata->client->dev,\
+ "Unable to write to i2c touchscreen\n");
+ ret = -EIO;
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ goto wait_event;
+ }
+ ret = i2c_master_recv(tsdata->client, buf, 9);
+ if (ret != 9) {
+ dev_err(&tsdata->client->dev,\
+ "Unable to read to i2c touchscreen!\n");
+ ret = -EIO;
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ goto wait_event;
+ }
+ /* mark everything ok now */
+ ret = 0;
+ type = buf[0];
+ if (type & 0x1) {
+ x1 = buf[2];
+ x1 <<= 8;
+ x1 |= buf[1];
+ y1 = buf[4];
+ y1 <<= 8;
+ y1 |= buf[3];
+ INPUT_REPORT(x1, y1, 1, 255, 1);
+ }
+ if (type & 0x2) {
+ x1 = buf[6];
+ x1 <<= 8;
+ x1 |= buf[5];
+ y1 = buf[8];
+ y1 <<= 8;
+ y1 |= buf[7];
+ INPUT_REPORT(x1, y1, 2, 255, 1);
+ }
+ input_sync(tsdata->input);
+ timeout = msecs_to_jiffies(20);
+ } else {
+ INPUT_REPORT(0, 0, 0, 0 ,0);
+ INPUT_REPORT(0, 0, 0, 0, 0);
+ input_sync(tsdata->input);
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ }
+wait_event:
+ wait_event_freezable_timeout(tsdata->idle_wait, \
+ tsdata->irq_pending || kthread_should_stop(), \
+ timeout);
+ }
+ return ret;
+}
+
+static int unidisplay_ts_open(struct input_dev *dev)
+{
+ struct unidisplay_ts_data *tsdata = input_get_drvdata(dev);
+ int ret = 0;
+ u8 addr = 0x10;
+ BUG_ON(tsdata->kidle_task);
+
+ ret = i2c_master_send(tsdata->client, &addr, 1);
+
+ if (ret != 1) {
+ dev_err(&tsdata->client->dev, "Unable to open touchscreen device\n");
+ return -ENODEV;
+ }
+
+ tsdata->kidle_task = kthread_run(unidisplay_ts_thread, tsdata, \
+ "unidisplay_ts");
+ if (IS_ERR(tsdata->kidle_task)) {
+ ret = PTR_ERR(tsdata->kidle_task);
+ tsdata->kidle_task = NULL;
+ return ret;
+ }
+ enable_irq(tsdata->irq);
+
+ return 0;
+}
+
+static void unidisplay_ts_close(struct input_dev *dev)
+{
+ struct unidisplay_ts_data *tsdata = input_get_drvdata(dev);
+
+ if (tsdata->kidle_task) {
+ kthread_stop(tsdata->kidle_task);
+ tsdata->kidle_task = NULL;
+ }
+
+ disable_irq(tsdata->irq);
+}
+
+static int unidisplay_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct unidisplay_ts_data *tsdata;
+ int err;
+
+ unidisplay_ts_config();
+ unidisplay_ts_reset();
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "i2c func not supported\n");
+ err = -EIO;
+ goto end;
+ }
+
+ tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
+ if (!tsdata) {
+ dev_err(&client->dev, "failed to allocate driver data!\n");
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ dev_set_drvdata(&client->dev, tsdata);
+
+ tsdata->input = input_allocate_device();
+ if (!tsdata->input) {
+ dev_err(&client->dev, "failed to allocate input device!\n");
+ err = -ENOMEM;
+ goto fail2;
+ }
+
+ tsdata->input->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |\
+ BIT_MASK(EV_ABS);
+ set_bit(EV_SYN, tsdata->input->evbit);
+ set_bit(EV_KEY, tsdata->input->evbit);
+ set_bit(EV_ABS, tsdata->input->evbit);
+
+ tsdata->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ set_bit(0, tsdata->input->absbit);
+ set_bit(1, tsdata->input->absbit);
+ set_bit(2, tsdata->input->absbit);
+
+ input_set_abs_params(tsdata->input, ABS_X, TOUCHSCREEN_MINX,\
+ TOUCHSCREEN_MAXX, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_Y, TOUCHSCREEN_MINY,\
+ TOUCHSCREEN_MAXY, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_HAT0X, TOUCHSCREEN_MINX,\
+ TOUCHSCREEN_MAXX, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_HAT0Y, TOUCHSCREEN_MINY,\
+ TOUCHSCREEN_MAXY, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_MT_POSITION_X,\
+ TOUCHSCREEN_MINX, TOUCHSCREEN_MAXX, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_MT_POSITION_Y, \
+ TOUCHSCREEN_MINY, TOUCHSCREEN_MAXY, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(tsdata->input, ABS_MT_WIDTH_MAJOR, 0, 25, 0, 0);
+
+ tsdata->input->name = client->name;
+ tsdata->input->id.bustype = BUS_I2C;
+ tsdata->input->dev.parent = &client->dev;
+
+ tsdata->input->open = unidisplay_ts_open;
+ tsdata->input->close = unidisplay_ts_close;
+
+ input_set_drvdata(tsdata->input, tsdata);
+
+ tsdata->client = client;
+ tsdata->irq = client->irq;
+
+ err = input_register_device(tsdata->input);
+ if (err)
+ goto fail2;
+
+ device_init_wakeup(&client->dev, 1);
+ init_waitqueue_head(&tsdata->idle_wait);
+
+ err = request_irq(tsdata->irq, unidisplay_ts_isr,\
+ IRQF_TRIGGER_FALLING, client->name, tsdata);
+ if (err != 0) {
+ dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+ goto fail3;
+ }
+ /* disable irq for now, will be enabled when device is opened */
+ disable_irq(tsdata->irq);
+ pr_info("Unidisplay touch driver registered successfully\n");
+ return err;
+fail3:
+ input_unregister_device(tsdata->input);
+fail2:
+ input_free_device(tsdata->input);
+ kfree(tsdata);
+fail1:
+ dev_set_drvdata(&client->dev, NULL);
+end:
+ return err;
+}
+
+
+static int unidisplay_ts_remove(struct i2c_client *client)
+{
+ struct unidisplay_ts_data *tsdata = dev_get_drvdata(&client->dev);
+ disable_irq(tsdata->irq);
+ free_irq(tsdata->irq, tsdata);
+ input_unregister_device(tsdata->input);
+ kfree(tsdata);
+ dev_set_drvdata(&client->dev, NULL);
+ return 0;
+}
+#ifdef CONFIG_PM
+static int unidisplay_ts_suspend(struct device *dev)
+{
+ struct unidisplay_ts_data *tsdata = dev_get_drvdata(dev);
+ disable_irq(tsdata->irq);
+ return 0;
+}
+
+static int unidisplay_ts_resume(struct device *dev)
+{
+ struct unidisplay_ts_data *tsdata = dev_get_drvdata(dev);
+ enable_irq(tsdata->irq);
+ return 0;
+}
+static const struct dev_pm_ops unidisplay_ts_pm = {
+ .suspend = unidisplay_ts_suspend,
+ .resume = unidisplay_ts_resume,
+};
+#endif
+
+static const struct i2c_device_id unidisplay_ts_i2c_id[] = {
+ { "unidisplay_ts", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, unidisplay_ts_i2c_id);
+
+static const struct of_device_id unidisplay_ts_of_match[] = {
+ { .compatible = "pixcir,unidisplay-ts", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, unidisplay_ts_of_match);
+
+static struct i2c_driver unidisplay_ts_i2c_driver = {
+ .driver = {
+ .name = "Unidisplay Touch Driver",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &unidisplay_ts_pm,
+#endif
+ .of_match_table = unidisplay_ts_of_match,
+ },
+ .probe = unidisplay_ts_probe,
+ .remove = unidisplay_ts_remove,
+ .id_table = unidisplay_ts_i2c_id,
+};
+
+module_i2c_driver(unidisplay_ts_i2c_driver);
+
+MODULE_AUTHOR("JHKIM");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("unidisplay Touch-screen Driver");
+
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 60ed6492e7c..74483a539df 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -50,6 +50,13 @@ config VIDEOBUF2_CORE
config VIDEOBUF2_MEMOPS
tristate
+config VIDEOBUF2_FB
+ depends on VIDEOBUF2_CORE
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ tristate
+
config VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
@@ -388,6 +395,44 @@ config VIDEO_VPX3220
To compile this driver as a module, choose M here: the
module will be called vpx3220.
+config VIDEO_S5K4ECGX
+ tristate "S5K4ECGX Camera Sensor"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports S5K4ECGX SoC camera module
+
+config VIDEO_S5K4ECGX_FLASHLIGHT
+ bool "S5K4ECGX flashlight support"
+ depends on VIDEO_S5K4ECGX
+ ---help---
+ Enable flash light support in S5K4ECGX camera driver
+
+config VIDEO_S5K4ECGX_DEBUG
+ bool "S5K4ECGX Camera Sensor Debugging"
+ depends on VIDEO_S5K4ECGX
+ ---help---
+ Enable extra debug messages for S5K4ECGX camera driver
+
+config VIDEO_S5K4ECGX_V_1_0
+ bool "S5K4ECGX Camera Sensor Version 1.0 Support"
+ depends on VIDEO_S5K4ECGX
+ ---help---
+ Enabled support for Rev 1.0 sensor
+
+config VIDEO_S5K4ECGX_V_1_1
+ bool "S5K4ECGX Camera Sensor Version 1.1 Support"
+ depends on VIDEO_S5K4ECGX
+ ---help---
+ Enabled support for Rev 1.1 sensor
+
+config VIDEO_S5K4ECGX_SLSI_4EC
+ bool "SLSI-4EC. S5K4ECGX based Camera module from SLSI"
+ depends on VIDEO_S5K4ECGX_V_1_1
+ ---help---
+ This module have sensor rev 1.1.
+ but, init seq. of herring have some problems with this
+ module.
+
comment "Video and audio decoders"
config VIDEO_SAA717X
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index b7da9faa3b0..f6edf8e3cbb 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
obj-$(CONFIG_VIDEO_SMIAPP) += smiapp/
+obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o
@@ -136,6 +137,7 @@ obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o
obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
+obj-$(CONFIG_VIDEOBUF2_FB) += videobuf2-fb.o
obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o
diff --git a/drivers/media/video/s5k4ecgx.c b/drivers/media/video/s5k4ecgx.c
new file mode 100755
index 00000000000..d35af1ad077
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx.c
@@ -0,0 +1,1358 @@
+/* drivers/media/video/s5k4ec.c
+ *
+ * Driver for s5k4ec (5MP Camera) from SEC
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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/i2c.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/vmalloc.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+#include <media/s5k4ecgx.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+
+#include "s5k4ecgx_regset.h"
+
+/* Should include twice to generate regset and data */
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+#include "s5k4ecgx_regs_1_0.h"
+#include "s5k4ecgx_regs_1_0.h"
+#endif /* CONFIG_VIDEO_S5K4ECGX_V_1_0 */
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+#ifndef CONFIG_VIDEO_S5K4ECGX_SLSI_4EC
+#include "s5k4ecgx_regs_1_1.h"
+#include "s5k4ecgx_regs_1_1.h"
+#else
+#include "s5k4ecgx_regs_1_1_slsi-4ec.h"
+#include "s5k4ecgx_regs_1_1_slsi-4ec.h"
+#endif
+#endif /* CONFIG_VIDEO_S5K4ECGX_V_1_1 */
+
+#define FORMAT_FLAGS_COMPRESSED 0x3
+#define SENSOR_JPEG_SNAPSHOT_MEMSIZE 0x410580
+
+#define DEFAULT_PIX_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
+#define DEFAULT_MCLK 24000000
+#define POLL_TIME_MS 10
+#define CAPTURE_POLL_TIME_MS 1000
+
+/* maximum time for one frame at minimum fps (15fps) in normal mode */
+#define NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS 67
+/* maximum time for one frame at minimum fps (4fps) in night mode */
+#define NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS 250
+
+/* time to move lens to target position before last af mode register write */
+#define LENS_MOVE_TIME_MS 100
+
+/* level at or below which we need to enable flash when in auto mode */
+#define LOW_LIGHT_LEVEL 0x1D
+
+/* level at or below which we need to use low light capture mode */
+#define HIGH_LIGHT_LEVEL 0x80
+
+#define FIRST_AF_SEARCH_COUNT 80
+#define SECOND_AF_SEARCH_COUNT 80
+#define AE_STABLE_SEARCH_COUNT 4
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+enum {
+ S5K4ECGX_DEBUG_I2C = 1U << 0,
+ S5K4ECGX_DEBUG_I2C_BURSTS = 1U << 1,
+};
+static uint32_t s5k4ecgx_debug_mask = S5K4ECGX_DEBUG_I2C_BURSTS;
+module_param_named(debug_mask, s5k4ecgx_debug_mask, uint, S_IWUSR | S_IRUGO);
+
+#define s5k4ecgx_debug(mask, x...) \
+ do { \
+ if (s5k4ecgx_debug_mask & mask) \
+ pr_info(x); \
+ } while (0)
+#else
+
+#define s5k4ecgx_debug(mask, x...)
+
+#endif
+
+#define S5K4ECGX_VERSION_1_0 0x00
+#define S5K4ECGX_VERSION_1_1 0x11
+
+enum s5k4ecgx_oprmode {
+ S5K4ECGX_OPRMODE_VIDEO = 0,
+ S5K4ECGX_OPRMODE_IMAGE = 1,
+};
+
+enum s5k4ecgx_preview_frame_size {
+ S5K4ECGX_PREVIEW_QCIF = 0, /* 176x144 */
+ S5K4ECGX_PREVIEW_CIF, /* 352x288 */
+ S5K4ECGX_PREVIEW_VGA, /* 640x480 */
+ S5K4ECGX_PREVIEW_D1, /* 720x480 */
+ S5K4ECGX_PREVIEW_WVGA, /* 800x480 */
+ S5K4ECGX_PREVIEW_SVGA, /* 800x600 */
+ S5K4ECGX_PREVIEW_WSVGA, /* 1024x600*/
+ S5K4ECGX_PREVIEW_MAX,
+};
+
+enum s5k4ecgx_capture_frame_size {
+ S5K4ECGX_CAPTURE_VGA = 0, /* 640x480 */
+ S5K4ECGX_CAPTURE_WVGA, /* 800x480 */
+ S5K4ECGX_CAPTURE_SVGA, /* 800x600 */
+ S5K4ECGX_CAPTURE_WSVGA, /* 1024x600 */
+ S5K4ECGX_CAPTURE_1MP, /* 1280x960 */
+ S5K4ECGX_CAPTURE_W1MP, /* 1600x960 */
+ S5K4ECGX_CAPTURE_2MP, /* UXGA - 1600x1200 */
+ S5K4ECGX_CAPTURE_W2MP, /* 35mm Academy Offset Standard 1.66 */
+ /* 2048x1232, 2.4MP */
+ S5K4ECGX_CAPTURE_3MP, /* QXGA - 2048x1536 */
+ S5K4ECGX_CAPTURE_W4MP, /* WQXGA - 2560x1536 */
+ S5K4ECGX_CAPTURE_5MP, /* 2560x1920 */
+ S5K4ECGX_CAPTURE_MAX,
+};
+
+struct s5k4ecgx_framesize {
+ u32 index;
+ u32 width;
+ u32 height;
+};
+
+static const struct s5k4ecgx_framesize s5k4ecgx_preview_framesize_list[] = {
+ { S5K4ECGX_PREVIEW_QCIF, 176, 144 },
+ { S5K4ECGX_PREVIEW_CIF, 352, 288 },
+ { S5K4ECGX_PREVIEW_VGA, 640, 480 },
+ { S5K4ECGX_PREVIEW_D1, 720, 480 },
+};
+
+static const struct s5k4ecgx_framesize s5k4ecgx_capture_framesize_list[] = {
+ { S5K4ECGX_CAPTURE_VGA, 640, 480 },
+ { S5K4ECGX_CAPTURE_1MP, 1280, 960 },
+ { S5K4ECGX_CAPTURE_2MP, 1600, 1200 },
+ { S5K4ECGX_CAPTURE_3MP, 2048, 1536 },
+ { S5K4ECGX_CAPTURE_5MP, 2560, 1920 },
+};
+
+struct s5k4ecgx_version {
+ u32 major;
+ u32 minor;
+};
+
+struct s5k4ecgx_regset_table {
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ const char *name;
+#endif
+ const struct s5k4ecgx_reg *regset;
+ const u8 *data;
+};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+#define S5K4ECGX_REGSET_TABLE(REGSET) \
+ { \
+ .name = #REGSET, \
+ .regset = REGSET, \
+ .data = REGSET##_data, \
+ }
+#else
+#define S5K4ECGX_REGSET_TABLE(REGSET) \
+ { \
+ .regset = REGSET, \
+ .data = REGSET##_data, \
+ }
+#endif
+
+#define S5K4ECGX_REGSET(IDX, REGSET) \
+ [(IDX)] = S5K4ECGX_REGSET_TABLE(REGSET)
+
+struct s5k4ecgx_regs {
+ struct s5k4ecgx_regset_table ev[EV_MAX];
+ struct s5k4ecgx_regset_table metering[METERING_MAX];
+ struct s5k4ecgx_regset_table iso[ISO_MAX];
+ struct s5k4ecgx_regset_table effect[IMAGE_EFFECT_MAX];
+ struct s5k4ecgx_regset_table white_balance[WHITE_BALANCE_MAX];
+ struct s5k4ecgx_regset_table preview_size[S5K4ECGX_PREVIEW_MAX];
+ struct s5k4ecgx_regset_table capture_size[S5K4ECGX_CAPTURE_MAX];
+ struct s5k4ecgx_regset_table scene_mode[SCENE_MODE_MAX];
+ struct s5k4ecgx_regset_table saturation[SATURATION_MAX];
+ struct s5k4ecgx_regset_table contrast[CONTRAST_MAX];
+ struct s5k4ecgx_regset_table sharpness[SHARPNESS_MAX];
+ struct s5k4ecgx_regset_table fps[FRAME_RATE_MAX];
+ struct s5k4ecgx_regset_table preview_return;
+ struct s5k4ecgx_regset_table capture_start;
+ struct s5k4ecgx_regset_table af_macro_mode;
+ struct s5k4ecgx_regset_table af_normal_mode;
+ struct s5k4ecgx_regset_table dtp_start;
+ struct s5k4ecgx_regset_table dtp_stop;
+ struct s5k4ecgx_regset_table init_reg;
+ struct s5k4ecgx_regset_table flash_init;
+ struct s5k4ecgx_regset_table reset_crop;
+};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+static const struct s5k4ecgx_regs regs_for_fw_version_1_0 = {
+ .ev = {
+ S5K4ECGX_REGSET(EV_MINUS_4, s5k4ecgx_EV_Minus_4_v1),
+ S5K4ECGX_REGSET(EV_MINUS_3, s5k4ecgx_EV_Minus_3_v1),
+ S5K4ECGX_REGSET(EV_MINUS_2, s5k4ecgx_EV_Minus_2_v1),
+ S5K4ECGX_REGSET(EV_MINUS_1, s5k4ecgx_EV_Minus_1_v1),
+ S5K4ECGX_REGSET(EV_DEFAULT, s5k4ecgx_EV_Default_v1),
+ S5K4ECGX_REGSET(EV_PLUS_1, s5k4ecgx_EV_Plus_1_v1),
+ S5K4ECGX_REGSET(EV_PLUS_2, s5k4ecgx_EV_Plus_2_v1),
+ S5K4ECGX_REGSET(EV_PLUS_3, s5k4ecgx_EV_Plus_3_v1),
+ S5K4ECGX_REGSET(EV_PLUS_4, s5k4ecgx_EV_Plus_4_v1),
+ },
+ .metering = {
+ S5K4ECGX_REGSET(METERING_MATRIX, s5k4ecgx_Metering_Matrix_v1),
+ S5K4ECGX_REGSET(METERING_CENTER, s5k4ecgx_Metering_Center_v1),
+ S5K4ECGX_REGSET(METERING_SPOT, s5k4ecgx_Metering_Spot_v1),
+ },
+ .iso = {
+ S5K4ECGX_REGSET(ISO_AUTO, s5k4ecgx_ISO_Auto_v1),
+ S5K4ECGX_REGSET(ISO_50, s5k4ecgx_ISO_100_v1), /* use 100 */
+ S5K4ECGX_REGSET(ISO_100, s5k4ecgx_ISO_100_v1),
+ S5K4ECGX_REGSET(ISO_200, s5k4ecgx_ISO_200_v1),
+ S5K4ECGX_REGSET(ISO_400, s5k4ecgx_ISO_400_v1),
+ S5K4ECGX_REGSET(ISO_800, s5k4ecgx_ISO_400_v1), /* use 400 */
+ S5K4ECGX_REGSET(ISO_1600, s5k4ecgx_ISO_400_v1), /* use 400 */
+ S5K4ECGX_REGSET(ISO_SPORTS, s5k4ecgx_ISO_Auto_v1),/* use auto */
+ S5K4ECGX_REGSET(ISO_NIGHT, s5k4ecgx_ISO_Auto_v1), /* use auto */
+ S5K4ECGX_REGSET(ISO_MOVIE, s5k4ecgx_ISO_Auto_v1), /* use auto */
+ },
+ .effect = {
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NONE, s5k4ecgx_Effect_Normal_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_BNW,
+ s5k4ecgx_Effect_Black_White_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_SEPIA, s5k4ecgx_Effect_Sepia_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NEGATIVE,
+ s5k4ecgx_Effect_Negative_v1),
+ },
+ .white_balance = {
+ S5K4ECGX_REGSET(WHITE_BALANCE_AUTO, s5k4ecgx_WB_Auto_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_SUNNY, s5k4ecgx_WB_Sunny_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_CLOUDY, s5k4ecgx_WB_Cloudy_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_TUNGSTEN,
+ s5k4ecgx_WB_Tungsten_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_FLUORESCENT,
+ s5k4ecgx_WB_Fluorescent_v1),
+ },
+ .preview_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_QCIF, s5k4ecgx_176_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_CIF, s5k4ecgx_352_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_VGA, s5k4ecgx_640_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_D1, s5k4ecgx_720_Preview_v1),
+ },
+ .capture_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_VGA, s5k4ecgx_VGA_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_1MP, s5k4ecgx_1M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_2MP, s5k4ecgx_2M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_3MP, s5k4ecgx_3M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_5MP, s5k4ecgx_5M_Capture_v1),
+ },
+ .scene_mode = {
+ S5K4ECGX_REGSET(SCENE_MODE_NONE, s5k4ecgx_Scene_Default_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_PORTRAIT,
+ s5k4ecgx_Scene_Portrait_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_NIGHTSHOT,
+ s5k4ecgx_Scene_Nightshot_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_LANDSCAPE,
+ s5k4ecgx_Scene_Landscape_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_SPORTS, s5k4ecgx_Scene_Sports_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_PARTY_INDOOR,
+ s5k4ecgx_Scene_Party_Indoor_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_BEACH_SNOW,
+ s5k4ecgx_Scene_Beach_Snow_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_SUNSET, s5k4ecgx_Scene_Sunset_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_FIREWORKS,
+ s5k4ecgx_Scene_Fireworks_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_CANDLE_LIGHT,
+ s5k4ecgx_Scene_Candle_Light_v1),
+ },
+ .saturation = {
+ S5K4ECGX_REGSET(SATURATION_MINUS_2,
+ s5k4ecgx_Saturation_Minus_2_v1),
+ S5K4ECGX_REGSET(SATURATION_MINUS_1,
+ s5k4ecgx_Saturation_Minus_1_v1),
+ S5K4ECGX_REGSET(SATURATION_DEFAULT,
+ s5k4ecgx_Saturation_Default_v1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_1,
+ s5k4ecgx_Saturation_Plus_1_v1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_2,
+ s5k4ecgx_Saturation_Plus_2_v1),
+ },
+ .contrast = {
+ S5K4ECGX_REGSET(CONTRAST_MINUS_2, s5k4ecgx_Contrast_Minus_2_v1),
+ S5K4ECGX_REGSET(CONTRAST_MINUS_1, s5k4ecgx_Contrast_Minus_1_v1),
+ S5K4ECGX_REGSET(CONTRAST_DEFAULT, s5k4ecgx_Contrast_Default_v1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_1, s5k4ecgx_Contrast_Plus_1_v1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_2, s5k4ecgx_Contrast_Plus_2_v1),
+ },
+ .sharpness = {
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_2,
+ s5k4ecgx_Sharpness_Minus_2_v1),
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_1,
+ s5k4ecgx_Sharpness_Minus_1_v1),
+ S5K4ECGX_REGSET(SHARPNESS_DEFAULT,
+ s5k4ecgx_Sharpness_Default_v1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_1, s5k4ecgx_Sharpness_Plus_1_v1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_2, s5k4ecgx_Sharpness_Plus_2_v1),
+ },
+ .preview_return = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Preview_Return_v1),
+ .capture_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Capture_Start_v1),
+ .af_macro_mode = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_v1),
+ .af_normal_mode = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_v1),
+ .dtp_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_init_v1),
+ .dtp_stop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_stop_v1),
+ .init_reg = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg_v1),
+ .flash_init = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_init_v1),
+ .reset_crop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Reset_Crop_v1),
+};
+#endif
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+static const struct s5k4ecgx_regs regs_for_fw_version_1_1 = {
+ .ev = {
+ S5K4ECGX_REGSET(EV_MINUS_4, s5k4ecgx_EV_Minus_4),
+ S5K4ECGX_REGSET(EV_MINUS_3, s5k4ecgx_EV_Minus_3),
+ S5K4ECGX_REGSET(EV_MINUS_2, s5k4ecgx_EV_Minus_2),
+ S5K4ECGX_REGSET(EV_MINUS_1, s5k4ecgx_EV_Minus_1),
+ S5K4ECGX_REGSET(EV_DEFAULT, s5k4ecgx_EV_Default),
+ S5K4ECGX_REGSET(EV_PLUS_1, s5k4ecgx_EV_Plus_1),
+ S5K4ECGX_REGSET(EV_PLUS_2, s5k4ecgx_EV_Plus_2),
+ S5K4ECGX_REGSET(EV_PLUS_3, s5k4ecgx_EV_Plus_3),
+ S5K4ECGX_REGSET(EV_PLUS_4, s5k4ecgx_EV_Plus_4),
+ },
+ .metering = {
+ S5K4ECGX_REGSET(METERING_MATRIX, s5k4ecgx_Metering_Matrix),
+ S5K4ECGX_REGSET(METERING_CENTER, s5k4ecgx_Metering_Center),
+ S5K4ECGX_REGSET(METERING_SPOT, s5k4ecgx_Metering_Spot),
+ },
+ .iso = {
+ S5K4ECGX_REGSET(ISO_AUTO, s5k4ecgx_ISO_Auto),
+ S5K4ECGX_REGSET(ISO_50, s5k4ecgx_ISO_100), /* map to 100 */
+ S5K4ECGX_REGSET(ISO_100, s5k4ecgx_ISO_100),
+ S5K4ECGX_REGSET(ISO_200, s5k4ecgx_ISO_200),
+ S5K4ECGX_REGSET(ISO_400, s5k4ecgx_ISO_400),
+ S5K4ECGX_REGSET(ISO_800, s5k4ecgx_ISO_400), /* map to 400 */
+ S5K4ECGX_REGSET(ISO_1600, s5k4ecgx_ISO_400), /* map to 400 */
+ S5K4ECGX_REGSET(ISO_SPORTS, s5k4ecgx_ISO_Auto),/* map to auto */
+ S5K4ECGX_REGSET(ISO_NIGHT, s5k4ecgx_ISO_Auto), /* map to auto */
+ S5K4ECGX_REGSET(ISO_MOVIE, s5k4ecgx_ISO_Auto), /* map to auto */
+ },
+ .effect = {
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NONE, s5k4ecgx_Effect_Normal),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_BNW, s5k4ecgx_Effect_Black_White),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_SEPIA, s5k4ecgx_Effect_Sepia),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NEGATIVE,
+ s5k4ecgx_Effect_Negative),
+ },
+ .white_balance = {
+ S5K4ECGX_REGSET(WHITE_BALANCE_AUTO, s5k4ecgx_WB_Auto),
+ S5K4ECGX_REGSET(WHITE_BALANCE_SUNNY, s5k4ecgx_WB_Sunny),
+ S5K4ECGX_REGSET(WHITE_BALANCE_CLOUDY, s5k4ecgx_WB_Cloudy),
+ S5K4ECGX_REGSET(WHITE_BALANCE_TUNGSTEN, s5k4ecgx_WB_Tungsten),
+ S5K4ECGX_REGSET(WHITE_BALANCE_FLUORESCENT,
+ s5k4ecgx_WB_Fluorescent),
+ },
+ .preview_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_QCIF, s5k4ecgx_176_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_CIF, s5k4ecgx_352_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_VGA, s5k4ecgx_640_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_D1, s5k4ecgx_720_Preview),
+ },
+ .capture_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_VGA, s5k4ecgx_VGA_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_1MP, s5k4ecgx_1M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_2MP, s5k4ecgx_2M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_3MP, s5k4ecgx_3M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_5MP, s5k4ecgx_5M_Capture),
+ },
+ .scene_mode = {
+ S5K4ECGX_REGSET(SCENE_MODE_NONE, s5k4ecgx_Scene_Default),
+ S5K4ECGX_REGSET(SCENE_MODE_PORTRAIT, s5k4ecgx_Scene_Portrait),
+ S5K4ECGX_REGSET(SCENE_MODE_NIGHTSHOT, s5k4ecgx_Scene_Nightshot),
+ S5K4ECGX_REGSET(SCENE_MODE_LANDSCAPE, s5k4ecgx_Scene_Landscape),
+ S5K4ECGX_REGSET(SCENE_MODE_SPORTS, s5k4ecgx_Scene_Sports),
+ S5K4ECGX_REGSET(SCENE_MODE_PARTY_INDOOR,
+ s5k4ecgx_Scene_Party_Indoor),
+ S5K4ECGX_REGSET(SCENE_MODE_BEACH_SNOW,
+ s5k4ecgx_Scene_Beach_Snow),
+ S5K4ECGX_REGSET(SCENE_MODE_SUNSET, s5k4ecgx_Scene_Sunset),
+ S5K4ECGX_REGSET(SCENE_MODE_FIREWORKS, s5k4ecgx_Scene_Fireworks),
+ S5K4ECGX_REGSET(SCENE_MODE_CANDLE_LIGHT,
+ s5k4ecgx_Scene_Candle_Light),
+ },
+ .saturation = {
+ S5K4ECGX_REGSET(SATURATION_MINUS_2,
+ s5k4ecgx_Saturation_Minus_2),
+ S5K4ECGX_REGSET(SATURATION_MINUS_1,
+ s5k4ecgx_Saturation_Minus_1),
+ S5K4ECGX_REGSET(SATURATION_DEFAULT,
+ s5k4ecgx_Saturation_Default),
+ S5K4ECGX_REGSET(SATURATION_PLUS_1, s5k4ecgx_Saturation_Plus_1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_2, s5k4ecgx_Saturation_Plus_2),
+ },
+ .contrast = {
+ S5K4ECGX_REGSET(CONTRAST_MINUS_2, s5k4ecgx_Contrast_Minus_2),
+ S5K4ECGX_REGSET(CONTRAST_MINUS_1, s5k4ecgx_Contrast_Minus_1),
+ S5K4ECGX_REGSET(CONTRAST_DEFAULT, s5k4ecgx_Contrast_Default),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_1, s5k4ecgx_Contrast_Plus_1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_2, s5k4ecgx_Contrast_Plus_2),
+ },
+ .sharpness = {
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_2, s5k4ecgx_Sharpness_Minus_2),
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_1, s5k4ecgx_Sharpness_Minus_1),
+ S5K4ECGX_REGSET(SHARPNESS_DEFAULT, s5k4ecgx_Sharpness_Default),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_1, s5k4ecgx_Sharpness_Plus_1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_2, s5k4ecgx_Sharpness_Plus_2),
+ },
+ .fps = {
+ S5K4ECGX_REGSET(FRAME_RATE_AUTO, s5k4ecgx_FPS_Auto),
+ S5K4ECGX_REGSET(FRAME_RATE_7, s5k4ecgx_FPS_7),
+ S5K4ECGX_REGSET(FRAME_RATE_15, s5k4ecgx_FPS_15),
+ S5K4ECGX_REGSET(FRAME_RATE_30, s5k4ecgx_FPS_30),
+ },
+ .preview_return = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Preview_Return),
+ .capture_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Capture_Start),
+ .af_macro_mode = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode),
+ .af_normal_mode = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode),
+#if 0
+ .single_af_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Start),
+ .single_af_off_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_1),
+ .single_af_off_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_2),
+#endif
+ .dtp_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_init),
+ .dtp_stop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_stop),
+ .init_reg = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg),
+ .flash_init = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_init),
+ .reset_crop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Reset_Crop),
+};
+#endif
+
+
+struct s5k4ec {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+ struct v4l2_pix_format pix;
+ struct s5k4ecgx_version fw;
+ struct v4l2_streamparm strm;
+ struct mutex ctrl_lock;
+ enum s5k4ecgx_oprmode oprmode;
+ int preview_framesize_index;
+ int capture_framesize_index;
+ int freq; /* MCLK in Hz */
+ int check_dataline;
+ bool initialized;
+ const struct s5k4ecgx_regs *regs;
+ enum s5k4ecgx_reg_type reg_type;
+ u16 reg_addr_high;
+ u16 reg_addr_low;
+ struct clk *clk;
+ struct v4l2_ctrl_handler handler;
+ int (*s_power)(int enable);
+};
+
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+ return &container_of(ctrl->handler, struct s5k4ec, handler)->sd;
+}
+
+static inline struct s5k4ec *to_s5k4ec(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct s5k4ec, sd);
+}
+
+static const struct v4l2_mbus_framefmt capture_fmts[] = {
+ {
+ .code = V4L2_MBUS_FMT_FIXED,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+};
+
+/**
+ * s5k4ecgx_i2c_read_twobyte: Read 2 bytes from sensor
+ */
+static int s5k4ecgx_i2c_read_twobyte(struct i2c_client *client,
+ u16 subaddr, u16 *data)
+{
+ int err;
+ unsigned char buf[2];
+ struct i2c_msg msg[2];
+
+ subaddr = swab16(subaddr);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = (u8 *)&subaddr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 2;
+ msg[1].buf = buf;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (unlikely(err != 2)) {
+ dev_err(&client->dev,
+ "%s: register read fail\n", __func__);
+ return -EIO;
+ }
+
+ *data = ((buf[0] << 8) | buf[1]);
+
+ return 0;
+}
+
+static int s5k4ecgx_i2c_write(struct i2c_client *client,
+ const u8 *data, u16 data_len)
+{
+ int retry_count = 5;
+ struct i2c_msg msg = {client->addr, 0, data_len, (u8 *)data};
+ int ret = 0;
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ dev_err(&client->dev, "%s: I2C err %d, retry %d.\n",
+ __func__, ret, retry_count);
+ printk("%s: I2C err %d, retry %d.\n",
+ __func__, ret, retry_count);
+ } while (retry_count-- > 0);
+ if (ret != 1) {
+ dev_err(&client->dev, "%s: I2C is not working.\n", __func__);
+ printk("%s: I2C is not working.\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
+static int s5k4ecgx_i2c_write_block(struct v4l2_subdev *sd, u8 *buf, int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err;
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ if (s5k4ecgx_debug_mask & S5K4ECGX_DEBUG_I2C_BURSTS) {
+ if ((buf[0] == 0x0F) && (buf[1] == 0x12))
+ pr_info("%s : data[0,1] = 0x%02X%02X,"
+ " total data size = %d\n",
+ __func__, buf[2], buf[3], size-2);
+ else
+ pr_info("%s : 0x%02X%02X%02X%02X\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+ }
+#else
+ msleep(1);
+#endif
+
+ err = s5k4ecgx_i2c_write(client, buf, size);
+ if (err)
+ return err;
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+ {
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+ if (state->fw.minor == 0) {
+ /* v1.0 sensor have problems sometimes if we write
+ * too much data too fast, so add a sleep. I've
+ * tried various combinations of size/delay. Checking
+ * for a larger size doesn't seem to work reliably, and
+ * a delay of 1ms sometimes isn't enough either.
+ */
+ if (size > 16)
+ msleep(2);
+ }
+ }
+#endif
+ return 0;
+}
+
+static int s5k4ecgx_i2c_write_two_word(struct i2c_client *client,
+ u16 addr, u16 w_data)
+{
+ u8 buf[4];
+
+ addr = swab16(addr);
+ w_data = swab16(w_data);
+
+ memcpy(buf, &addr, 2);
+ memcpy(buf + 2, &w_data, 2);
+
+ s5k4ecgx_debug(S5K4ECGX_DEBUG_I2C, "%s : W(0x%02X%02X%02X%02X)\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+
+ return s5k4ecgx_i2c_write(client, buf, 4);
+}
+
+static int s5k4ecgx_burst_write_regs(struct v4l2_subdev *sd,
+ struct s5k4ecgx_reg **start_reg,
+ const u8 *regset_data, int *regset_data_idx)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+ struct s5k4ecgx_reg *curr_reg = *start_reg;
+ u16 addr_high, addr_low;
+
+ u8 *burst_buf;
+ int burst_len = 0;
+
+ int ret = 0;
+
+ addr_high = curr_reg->addr >> 16;
+ addr_low = curr_reg->addr & 0xffff;
+
+ if (state->reg_type != S5K4ECGX_REGTYPE_WRITE) {
+ state->reg_addr_high = 0;
+ state->reg_addr_low = 0;
+ state->reg_type = S5K4ECGX_REGTYPE_WRITE;
+ }
+
+ if (state->reg_addr_high != addr_high) {
+ s5k4ecgx_i2c_write_two_word(client, 0x0028, addr_high);
+ state->reg_addr_high = addr_high;
+ state->reg_addr_low = 0;
+ }
+
+ if (state->reg_addr_low != addr_low) {
+ s5k4ecgx_i2c_write_two_word(client, 0x002A, addr_low);
+ state->reg_addr_low = addr_low;
+ }
+
+ while (curr_reg->type != S5K4ECGX_REGTYPE_END) {
+ burst_len += curr_reg->data_len;
+
+ if (S5K4ECGX_REGTYPE_WRITE != (curr_reg + 1)->type)
+ break;
+
+ if (curr_reg->addr + 2 != (curr_reg + 1)->addr)
+ break;
+
+ curr_reg += 1;
+ }
+
+ burst_buf = vmalloc(burst_len + 2);
+ if (burst_buf == NULL)
+ return -ENOMEM;
+
+ burst_buf[0] = 0x0F;
+ burst_buf[1] = 0x12;
+ memcpy(burst_buf + 2, regset_data + (*regset_data_idx), burst_len);
+
+ ret = s5k4ecgx_i2c_write_block(sd, burst_buf, burst_len + 2);
+
+ vfree(burst_buf);
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ if (s5k4ecgx_debug_mask & S5K4ECGX_DEBUG_I2C_BURSTS) {
+ u32 start_addr = (*start_reg)->addr;
+ u32 end_addr = curr_reg->addr;
+ int reg_count = (end_addr - start_addr) / 2;
+ pr_debug("%s: burst write from 0x%08X to 0x%08X. %d regs.",
+ "burst data starts with 0x0F12 and follow "
+ "%d bytes.\n", __func__,
+ start_addr, end_addr, reg_count, burst_len);
+ }
+#endif
+
+ *start_reg = curr_reg;
+ *regset_data_idx += burst_len;
+ state->reg_addr_low = 0;
+
+ return ret;
+}
+
+static int s5k4ecgx_request_reg_read(struct v4l2_subdev *sd, u32 addr)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+
+ u16 addr_high, addr_low;
+
+ addr_high = (addr >> 16) & 0xffff;
+ addr_low = addr & 0xffff;
+
+
+ if (state->reg_type != S5K4ECGX_REGTYPE_READ) {
+ state->reg_addr_high = 0;
+ state->reg_type = S5K4ECGX_REGTYPE_READ;
+ }
+
+ if (state->reg_addr_high != addr_high) {
+ s5k4ecgx_i2c_write_two_word(client, 0x002C, addr_high);
+ state->reg_addr_high = addr_high;
+ }
+
+ s5k4ecgx_i2c_write_two_word(client, 0x002E, addr_low);
+
+ return 0;
+}
+
+static int s5k4ecgx_reg_read_16(struct i2c_client *client, u16 *value)
+{
+ return s5k4ecgx_i2c_read_twobyte(client, 0x0F12, value);
+}
+
+static int s5k4ecgx_write_regset(struct v4l2_subdev *sd,
+ const struct s5k4ecgx_regset_table *table)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+ struct s5k4ecgx_reg *curr_reg = (struct s5k4ecgx_reg *)table->regset;
+ const u8 *regset_data = table->data;
+ int data_idx = 0;
+ int err = 0;
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ dev_dbg(&client->dev, "%s: writing regset, %s...\n", __func__,
+ table->name);
+#endif
+
+ if (curr_reg == NULL)
+ return -EINVAL;
+
+ while(curr_reg->type != S5K4ECGX_REGTYPE_END && err == 0) {
+ switch(curr_reg->type) {
+ case S5K4ECGX_REGTYPE_WRITE:
+ err = s5k4ecgx_burst_write_regs(sd, &curr_reg,
+ regset_data, &data_idx);
+ break;
+
+ case S5K4ECGX_REGTYPE_CMD:
+ err = s5k4ecgx_i2c_write(client,
+ regset_data + data_idx,
+ curr_reg->data_len);
+ data_idx += curr_reg->data_len;
+ state->reg_type = S5K4ECGX_REGTYPE_CMD;
+ break;
+
+ case S5K4ECGX_REGTYPE_READ:
+ err = s5k4ecgx_request_reg_read(sd, curr_reg->addr);
+ data_idx += curr_reg->data_len;
+ break;
+
+ case S5K4ECGX_REGTYPE_DELAY:
+ msleep(curr_reg->msec);
+ data_idx += curr_reg->data_len;
+ break;
+
+ default:
+ dev_err(&client->dev,
+ "%s: Got unknown reg_type, %d!\n",
+ __func__, curr_reg->type);
+ err = -EINVAL;
+ break;
+ }
+ curr_reg += 1;
+ }
+
+ if (unlikely(curr_reg->type != S5K4ECGX_REGTYPE_END)) {
+ dev_err(&client->dev, "%s: fail to write regset!\n", __func__);
+ return -EIO;
+ }
+
+ return err;
+}
+
+static int s5k4ecgx_enum_mbus_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ pr_debug("%s: index = %d\n", __func__, code->index);
+
+ if (code->index >= ARRAY_SIZE(capture_fmts))
+ return -EINVAL;
+
+ code->code = capture_fmts[code->index].code;
+
+ return 0;
+}
+
+static int s5k4ecgx_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ int i = ARRAY_SIZE(capture_fmts);
+
+ if (fse->index > 0)
+ return -EINVAL;
+
+ while (--i)
+ if (fse->code == capture_fmts[i].code)
+ break;
+
+ fse->code = capture_fmts[i].code;
+ fse->min_width = 640;
+ fse->max_width = 2560;
+ fse->min_height = 480;
+ fse->max_height = 1920;
+
+ return 0;
+}
+
+static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ return 0;
+}
+
+static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ return 0;
+}
+
+static int s5k4ecgx_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ return 0;
+}
+
+static int s5k4ecgx_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_crop *crop)
+{
+ return 0;
+}
+
+static int s5k4ec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+ struct s5k4ec *s5k4ec = to_s5k4ec(sd);
+ struct s5k4ec *state = s5k4ec;
+ struct sec_cam_parm *params =
+ (struct sec_cam_parm *)&s5k4ec->strm.parm.raw_data;
+ int err = 0;
+ /* int idx; */
+
+ mutex_lock(&s5k4ec->ctrl_lock);
+
+ switch(ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ if(params->brightness != ctrl->val) {
+ err = s5k4ecgx_write_regset(sd, state->regs->ev + EV_DEFAULT + ctrl->val);
+ params->brightness = ctrl->val;
+ }
+ break;
+
+ case V4L2_CID_CONTRAST:
+ if(params->contrast != ctrl->val) {
+ err = s5k4ecgx_write_regset(sd, state->regs->contrast + CONTRAST_DEFAULT + ctrl->val);
+ params->contrast = ctrl->val;
+ }
+ break;
+#if 0
+ case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+ if(params->white_balance != ctrl->val) {
+ if(ctrl->val == V4L2_WHITE_BALANCE_AUTO) {
+ idx = WHITE_BALANCE_AUTO;
+ params->white_balance = V4L2_WHITE_BALANCE_AUTO;
+ }
+ else if(ctrl->val == V4L2_WHITE_BALANCE_DAYLIGHT) {
+ idx = WHITE_BALANCE_SUNNY;
+ params->white_balance = V4L2_WHITE_BALANCE_DAYLIGHT;
+ }
+ else if(ctrl->val == V4L2_WHITE_BALANCE_CLOUDY) {
+ idx = WHITE_BALANCE_CLOUDY;
+ params->white_balance = V4L2_WHITE_BALANCE_CLOUDY;
+ }
+ else if(ctrl->val == V4L2_WHITE_BALANCE_INCANDESCENT) {
+ idx = WHITE_BALANCE_TUNGSTEN;
+ params->white_balance = V4L2_WHITE_BALANCE_INCANDESCENT;
+ }
+ else if(ctrl->val == V4L2_WHITE_BALANCE_FLUORESCENT) {
+ idx = WHITE_BALANCE_FLUORESCENT;
+ params->white_balance = V4L2_WHITE_BALANCE_FLUORESCENT;
+ }
+ else {
+ idx = WHITE_BALANCE_AUTO;
+ params->white_balance = V4L2_WHITE_BALANCE_AUTO;
+ }
+
+ err = s5k4ecgx_write_regset(sd, state->regs->white_balance + idx);
+ }
+ break;
+
+ case V4L2_CID_ISO_SENSITIVITY_AUTO:
+ if(params->iso != ctrl->val) {
+ err = s5k4ecgx_write_regset(sd, state->regs->iso + 0);
+ params->iso = ctrl->val;
+ }
+ break;
+
+ case V4L2_CID_EXPOSURE_METERING:
+ if(params->metering != ctrl->val) {
+ if(ctrl->val == V4L2_EXPOSURE_METERING_AVERAGE) {
+ idx = METERING_MATRIX;
+ params->metering = V4L2_EXPOSURE_METERING_AVERAGE;
+ }
+ else if(ctrl->val == V4L2_EXPOSURE_METERING_CENTER_WEIGHTED) {
+ idx = METERING_CENTER;
+ params->metering = V4L2_EXPOSURE_METERING_CENTER_WEIGHTED;
+ }
+ else if(ctrl->val == V4L2_EXPOSURE_METERING_SPOT) {
+ idx = METERING_SPOT;
+ params->metering = V4L2_EXPOSURE_METERING_SPOT;
+ }
+ err = s5k4ecgx_write_regset(sd, state->regs->metering + idx);
+ }
+ break;
+
+ case V4L2_CID_COLORFX:
+ if(params->effects != ctrl->val) {
+ if(ctrl->val == V4L2_COLORFX_NONE) {
+ idx = IMAGE_EFFECT_NONE;
+ params->effects = V4L2_COLORFX_NONE;
+ }
+ else if(ctrl->val == V4L2_COLORFX_BW) {
+ idx = IMAGE_EFFECT_BNW;
+ params->effects = V4L2_COLORFX_BW;
+ }
+ else if(ctrl->val == V4L2_COLORFX_SEPIA) {
+ idx = IMAGE_EFFECT_SEPIA;
+ params->effects = V4L2_COLORFX_SEPIA;
+ }
+ else if(ctrl->val == V4L2_COLORFX_NEGATIVE) {
+ idx = IMAGE_EFFECT_NEGATIVE;
+ params->effects = V4L2_COLORFX_NEGATIVE;
+ }
+ err = s5k4ecgx_write_regset(sd, state->regs->effect + idx);
+ }
+ break;
+
+ case V4L2_CID_SCENE_MODE:
+ if(params->scene_mode != ctrl->val) {
+ if(ctrl->val == V4L2_SCENE_MODE_NONE) {
+ idx = SCENE_MODE_NONE;
+ params->scene_mode = V4L2_SCENE_MODE_NONE;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_PORTRAIT) {
+ idx = SCENE_MODE_PORTRAIT;
+ params->scene_mode = V4L2_SCENE_MODE_PORTRAIT;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_NIGHT) {
+ idx = SCENE_MODE_NIGHTSHOT;
+ params->scene_mode = V4L2_SCENE_MODE_NIGHT;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_LANDSCAPE) {
+ idx = SCENE_MODE_LANDSCAPE;
+ params->scene_mode = V4L2_SCENE_MODE_LANDSCAPE;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_SPORTS) {
+ idx = SCENE_MODE_SPORTS;
+ params->scene_mode = V4L2_SCENE_MODE_SPORTS;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_PARTY_INDOOR) {
+ idx = SCENE_MODE_PARTY_INDOOR;
+ params->scene_mode = V4L2_SCENE_MODE_PARTY_INDOOR;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_BEACH_SNOW) {
+ idx = SCENE_MODE_BEACH_SNOW;
+ params->scene_mode = V4L2_SCENE_MODE_BEACH_SNOW;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_SUNSET) {
+ idx = SCENE_MODE_SUNSET;
+ params->scene_mode = V4L2_SCENE_MODE_SUNSET;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_FIREWORKS) {
+ idx = SCENE_MODE_FIREWORKS;
+ params->scene_mode = V4L2_SCENE_MODE_FIREWORKS;
+ }
+ else if(ctrl->val == V4L2_SCENE_MODE_CANDLE_LIGHT) {
+ idx = SCENE_MODE_CANDLE_LIGHT;
+ params->scene_mode = V4L2_SCENE_MODE_CANDLE_LIGHT;
+ }
+ err = s5k4ecgx_write_regset(sd, state->regs->scene_mode + idx);
+ }
+ break;
+
+ case V4L2_CID_SATURATION:
+ if(params->saturation != ctrl->val) {
+ err = s5k4ecgx_write_regset(sd, state->regs->saturation + ctrl->val + SATURATION_DEFAULT);
+ params->saturation = ctrl->val;
+ }
+ break;
+
+ case V4L2_CID_SHARPNESS:
+ if(params->sharpness != ctrl->val) {
+ err = s5k4ecgx_write_regset(sd, state->regs->sharpness + ctrl->val + SHARPNESS_DEFAULT);
+ params->sharpness = ctrl->val;
+ }
+ break;
+ case V4L2_CID_AUTO_FOCUS_RANGE:
+ if(params->focus_mode != ctrl->val) {
+ msleep(150);
+ if(ctrl->val == V4L2_AUTO_FOCUS_RANGE_AUTO)
+ err = s5k4ecgx_write_regset(sd, &state->regs->af_normal_mode);
+ else if(ctrl->val == V4L2_AUTO_FOCUS_RANGE_MACRO)
+ err = s5k4ecgx_write_regset(sd, &state->regs->af_macro_mode);
+ params->focus_mode = ctrl->val;
+ }
+#endif
+ }
+
+ mutex_unlock(&s5k4ec->ctrl_lock);
+ return err;
+}
+
+
+static const struct v4l2_ctrl_ops s5k4ec_ctrl_ops = {
+ .s_ctrl = s5k4ec_s_ctrl,
+};
+
+static int s5k4ec_initialize_ctrls(struct s5k4ec *s5k4ec)
+{
+ const struct v4l2_ctrl_ops *ops = &s5k4ec_ctrl_ops;
+ struct v4l2_ctrl_handler *hdl = &s5k4ec->handler;
+
+ int ret = v4l2_ctrl_handler_init(hdl, 16);
+ if (ret)
+ return ret;
+
+ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -4, 4, 1, 0);
+
+ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2, 2, 1, 0);
+
+ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -2, 2, 1, 0);
+
+#if 0
+ v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, V4L2_WHITE_BALANCE_SHADE, ~0x14E, V4L2_WHITE_BALANCE_AUTO);
+
+ v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_ISO_SENSITIVITY_AUTO, V4L2_ISO_SENSITIVITY_AUTO, ~0x2, V4L2_ISO_SENSITIVITY_AUTO);
+
+ v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_EXPOSURE_METERING, V4L2_EXPOSURE_METERING_SPOT, 0, V4L2_EXPOSURE_METERING_CENTER_WEIGHTED);
+
+ v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX, V4L2_COLORFX_NEGATIVE, ~0xF, V4L2_COLORFX_NONE);
+
+ v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_SCENE_MODE, V4L2_SCENE_MODE_TEXT, ~0x17CD, V4L2_SCENE_MODE_NONE);
+
+ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -2, 2, 1, 0);
+
+ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -2, 2, 1, 0);
+
+ v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_AUTO_FOCUS_RANGE, V4L2_AUTO_FOCUS_RANGE_MACRO, ~0x5, V4L2_AUTO_FOCUS_RANGE_AUTO);
+#endif
+ if (hdl->error) {
+ ret = hdl->error;
+ v4l2_ctrl_handler_free(hdl);
+ printk("\n %s function failed", __FUNCTION__);
+ return ret;
+ }
+
+ s5k4ec->sd.ctrl_handler = hdl;
+ return 0;
+}
+
+int s5k4ecgx_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ dev_dbg(&client->dev, "%s: stream %s\n", __func__,
+ enable ? "on" : "off");
+
+ /* do nothing here! cause of the sensor streaming on automatically
+ * after finish it's init sequence and can off by power down
+ */
+
+ return 0;
+}
+
+/* returns the real iso currently used by sensor due to lighting
+ * conditions, not the requested iso we sent using s_ctrl.
+ */
+static int s5k4ecgx_init_regs(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+ u16 read_value = 0;
+
+ /* we'd prefer to do this in probe, but the framework hasn't
+ * turned on the camera yet so our i2c operations would fail
+ * if we tried to do it in probe, so we have to do it here
+ * and keep track if we succeeded or not.
+ */
+ s5k4ecgx_request_reg_read(sd, 0x700001A6);
+ s5k4ecgx_reg_read_16(client, &read_value);
+
+ pr_debug("%s : revision %08X\n", __func__, read_value);
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+ if (read_value == S5K4ECGX_VERSION_1_0) {
+ state->regs = &regs_for_fw_version_1_0;
+ state->initialized = true;
+ return 0;
+ }
+#endif
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+ if (read_value == S5K4ECGX_VERSION_1_1) {
+ state->fw.minor = 1;
+ state->regs = &regs_for_fw_version_1_1;
+ state->initialized = true;
+ return 0;
+ }
+#endif
+
+ dev_err(&client->dev, "%s: unknown fw version 0x%x\n",
+ __func__, read_value);
+ return -ENODEV;
+}
+
+static int s5k4ecgx_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ if (s5k4ecgx_init_regs(&state->sd) < 0)
+ return -ENODEV;
+
+ dev_dbg(&client->dev, "%s: state->check_dataline : %d\n",
+ __func__, state->check_dataline);
+
+ if (s5k4ecgx_write_regset(sd, &state->regs->init_reg) < 0)
+ return -EIO;
+
+ if (s5k4ecgx_write_regset(sd, &state->regs->flash_init) < 0)
+ return -EIO;
+
+ if (state->check_dataline
+ && s5k4ecgx_write_regset(sd, &state->regs->dtp_start) < 0)
+ return -EIO;
+
+ dev_dbg(&client->dev, "%s: end\n", __func__);
+
+ return 0;
+}
+
+static int s5k4ec_set_power(struct v4l2_subdev *sd, int on)
+{
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+ if(on == 1 ) {
+ if(state->s_power)
+ state->s_power(1);
+ s5k4ecgx_init(sd, 0);
+ v4l2_ctrl_handler_setup(sd->ctrl_handler);
+ }
+ else {
+ if(state->s_power)
+ state->s_power(0);
+ }
+ return 0;
+}
+
+static int s5k4ec_log_status(struct v4l2_subdev *sd)
+{
+ v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = {
+ .s_power = s5k4ec_set_power,
+ .log_status = s5k4ec_log_status,
+};
+
+static const struct v4l2_subdev_pad_ops s5k4ecgx_pad_ops = {
+ .enum_mbus_code = s5k4ecgx_enum_mbus_fmt,
+ .enum_frame_size = s5k4ecgx_enum_frame_size,
+ .get_fmt = s5k4ecgx_get_fmt,
+ .set_fmt = s5k4ecgx_set_fmt,
+ .get_crop = s5k4ecgx_get_crop,
+ .set_crop = s5k4ecgx_set_crop,
+};
+
+static int s5k4ec_g_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct s5k4ec *s5k4ec = to_s5k4ec(sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&s5k4ec->strm.parm.raw_data;
+
+ fi->interval.denominator = parms->fps;
+ fi->interval.numerator = 1;
+ return 0;
+
+}
+
+static int s5k4ec_s_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct s5k4ec *s5k4ec = to_s5k4ec(sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&s5k4ec->strm.parm.raw_data;
+ int ret;
+
+ unsigned int fps = fi->interval.denominator / fi->interval.numerator;
+
+ if(fps < 10) {
+ ret = s5k4ecgx_write_regset(sd, s5k4ec->regs->fps + 1);
+ parms->fps = 7;
+ }
+ else if(fps < 20) {
+ ret = s5k4ecgx_write_regset(sd, s5k4ec->regs->fps + 2);
+ parms->fps = 15;
+ }
+ else if(fps <= 30) {
+ ret = s5k4ecgx_write_regset(sd, s5k4ec->regs->fps + 3);
+ parms->fps = 30;
+ }
+ else {
+ ret = s5k4ecgx_write_regset(sd, s5k4ec->regs->fps + 0);
+ parms->fps = 15;
+ }
+ return ret;
+}
+
+static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = {
+ .g_frame_interval = s5k4ec_g_frame_interval,
+ .s_frame_interval = s5k4ec_s_frame_interval,
+ .s_stream = s5k4ecgx_s_stream,
+};
+
+static const struct v4l2_subdev_ops s5k4ecgx_ops = {
+ .core = &s5k4ecgx_core_ops,
+ .video = &s5k4ecgx_video_ops,
+ .pad = &s5k4ecgx_pad_ops,
+};
+
+
+/*
+ * s5k4ecgx_probe
+ * Fetching platform data is being done with s_config subdev call.
+ * In probe routine, we just register subdev device
+ */
+
+static int s5k4ecgx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct v4l2_subdev *sd;
+ struct s5k4ec *state;
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+ int ret;
+
+
+ state = kzalloc(sizeof(struct s5k4ec), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+
+ mutex_init(&state->ctrl_lock);
+
+ sd = &state->sd;
+ strcpy(sd->name, S5K4ECGX_DRIVER_NAME);
+
+ /*
+ * Assign default format and resolution
+ * Use configured default information in platform data
+ * or without them, use default information in driver
+ */
+ if (pdata) {
+ state->pix.width = pdata->default_width;
+ state->pix.height = pdata->default_height;
+
+ if (!pdata->pixelformat)
+ state->pix.pixelformat = DEFAULT_PIX_FMT;
+ else
+ state->pix.pixelformat = pdata->pixelformat;
+
+ if (!pdata->freq)
+ state->freq = DEFAULT_MCLK; /* 24MHz default */
+ else
+ state->freq = pdata->freq;
+
+ if(pdata)
+ state->s_power = pdata->set_power;
+ } else {
+ state->pix.width = 640;
+ state->pix.height = 480;
+ state->pix.pixelformat = DEFAULT_PIX_FMT;
+ state->freq = DEFAULT_MCLK; /* 24MHz default */
+ }
+
+ /* Registering subdev */
+ v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops);
+
+ state->pad.flags = MEDIA_PAD_FL_SOURCE;
+ sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+ ret = media_entity_init(&sd->entity, 1, &state->pad, 0);
+ if (ret)
+ goto out_err;
+
+ dev_dbg(&client->dev, "5MP camera S5K4ECGX loaded.\n");
+
+
+ ret = s5k4ec_initialize_ctrls(state);
+ if (ret)
+ goto out_err;
+ return 0;
+
+out_err:
+ media_entity_cleanup(&state->sd.entity);
+ kfree(state);
+ return ret;
+}
+
+static int s5k4ecgx_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct s5k4ec *state =
+ container_of(sd, struct s5k4ec, sd);
+
+ printk("\n At %s file %s fn %d line\n", __FILE__, __FUNCTION__, __LINE__);
+ v4l2_device_unregister_subdev(sd);
+ mutex_destroy(&state->ctrl_lock);
+ kfree(state);
+
+ dev_dbg(&client->dev, "Unloaded camera sensor S5K4ECGX.\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id s5k4ecgx_id[] = {
+ { S5K4ECGX_DRIVER_NAME, 0 },
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+ .driver.name = S5K4ECGX_DRIVER_NAME,
+ .probe = s5k4ecgx_probe,
+ .remove = s5k4ecgx_remove,
+ .id_table = s5k4ecgx_id,
+};
+
+static int __init v4l2_i2c_drv_init(void)
+{
+ return i2c_add_driver(&v4l2_i2c_driver);
+}
+
+static void __exit v4l2_i2c_drv_cleanup(void)
+{
+ i2c_del_driver(&v4l2_i2c_driver);
+}
+
+module_init(v4l2_i2c_drv_init);
+module_exit(v4l2_i2c_drv_cleanup);
+
+MODULE_DESCRIPTION("LSI S5K4ECGX 5MP SOC camera driver");
+MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/s5k4ecgx_regs.h b/drivers/media/video/s5k4ecgx_regs.h
new file mode 100644
index 00000000000..3b17934cc29
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs.h
@@ -0,0 +1,3121 @@
+/*
+ * Samsung S5K4ECGX registers table for default values
+ *
+ * Copyright (C) 2012 Linaro
+ * Copyright (C) 2012 Insignal Co,. Ltd
+ *
+ * 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 __DRIVERS_MEDIA_VIDEO_S5K4ECGX_H__
+#define __DRIVERS_MEDIA_VIDEO_S5K4ECGX_H__
+
+/*
+ * Tokens for register write
+ * Default type about how to write values to registers
+ */
+enum token_type {
+ TOK_TERM = 0, /* terminating token */
+ TOK_CMD, /* Command write */
+ TOK_WRITE, /* token for write operation */
+ TOK_DELAY, /* delay token for reg list */
+ TOK_READ,
+};
+
+struct regval_list {
+ enum token_type type;
+ u32 addr;
+ u16 val;
+};
+
+/*
+ * FIXME:
+ * The tables are default values of a S5K4ECGX sensor EVT1.1
+ * and are provided from Samsung LSI.
+ * It seems that no information is available for these registers
+ * in the datasheet
+ */
+struct regval_list s5k4ecgx_init_regs[] = {
+ {TOK_CMD, 0xFCFC, 0xD000},
+ {TOK_CMD, 0x0010, 0x0001},
+ {TOK_CMD, 0x1030, 0x0000},
+ {TOK_CMD, 0x0014, 0x0001},
+ {TOK_DELAY, 0x0, 0x64},
+ {TOK_WRITE, 0xD0001082, 0x01AA},
+ {TOK_WRITE, 0xD0001084, 0x01AA},
+ {TOK_WRITE, 0xD0001086, 0x0055},
+ {TOK_WRITE, 0xD0001088, 0x01AF},
+ {TOK_WRITE, 0xD000100E, 0x0000},
+ {TOK_WRITE, 0xD000007A, 0x0000},
+ {TOK_WRITE, 0xD000E406, 0x0092},
+ {TOK_WRITE, 0xD000E410, 0x3804},
+ {TOK_WRITE, 0xD000E41A, 0x0010},
+ {TOK_WRITE, 0xD000E420, 0x0003},
+ {TOK_WRITE, 0xD000E422, 0x0060},
+ {TOK_WRITE, 0xD000E42E, 0x0004},
+ {TOK_WRITE, 0xD000F400, 0x5A3C},
+ {TOK_WRITE, 0xD000F402, 0x0023},
+ {TOK_WRITE, 0xD000F404, 0x8080},
+ {TOK_WRITE, 0xD000F406, 0x03AF},
+ {TOK_WRITE, 0xD000F408, 0x000A},
+ {TOK_WRITE, 0xD000F40A, 0xAA54},
+ {TOK_WRITE, 0xD000F40C, 0x0040},
+ {TOK_WRITE, 0xD000F40E, 0x464E},
+ {TOK_WRITE, 0xD000F410, 0x0240},
+ {TOK_WRITE, 0xD000F412, 0x0240},
+ {TOK_WRITE, 0xD000F414, 0x0040},
+ {TOK_WRITE, 0xD000F416, 0x1000},
+ {TOK_WRITE, 0xD000F418, 0x55FF},
+ {TOK_WRITE, 0xD000F41A, 0xD000},
+ {TOK_WRITE, 0xD000F41C, 0x0010},
+ {TOK_WRITE, 0xD000F41E, 0x0202},
+ {TOK_WRITE, 0xD000F420, 0x0401},
+ {TOK_WRITE, 0xD000F422, 0x0022},
+ {TOK_WRITE, 0xD000F424, 0x0088},
+ {TOK_WRITE, 0xD000F426, 0x009F},
+ {TOK_WRITE, 0xD000F428, 0x0000},
+ {TOK_WRITE, 0xD000F42A, 0x1800},
+ {TOK_WRITE, 0xD000F42C, 0x0088},
+ {TOK_WRITE, 0xD000F42E, 0x0000},
+ {TOK_WRITE, 0xD000F430, 0x2428},
+ {TOK_WRITE, 0xD000F432, 0x0000},
+ {TOK_WRITE, 0xD000F434, 0x03EE},
+ {TOK_WRITE, 0xD000F436, 0x0000},
+ {TOK_WRITE, 0xD000F438, 0x0000},
+ {TOK_WRITE, 0xD000F43A, 0x0000},
+ {TOK_WRITE, 0xD000F552, 0x0708},
+ {TOK_WRITE, 0xD000F554, 0x080C},
+ {TOK_WRITE, 0x700018BC, 0x0004},
+ {TOK_WRITE, 0x700018BE, 0x05B6},
+ {TOK_WRITE, 0x700018C0, 0x0000},
+ {TOK_WRITE, 0x700018C2, 0x0000},
+ {TOK_WRITE, 0x700018C4, 0x0001},
+ {TOK_WRITE, 0x700018C6, 0x05BA},
+ {TOK_WRITE, 0x700018C8, 0x0000},
+ {TOK_WRITE, 0x700018CA, 0x0000},
+ {TOK_WRITE, 0x700018CC, 0x0007},
+ {TOK_WRITE, 0x700018CE, 0x05BA},
+ {TOK_WRITE, 0x700018D0, 0x0000},
+ {TOK_WRITE, 0x700018D2, 0x0000},
+ {TOK_WRITE, 0x700018D4, 0x01F4},
+ {TOK_WRITE, 0x700018D6, 0x024E},
+ {TOK_WRITE, 0x700018D8, 0x0000},
+ {TOK_WRITE, 0x700018DA, 0x0000},
+ {TOK_WRITE, 0x700018DC, 0x01F4},
+ {TOK_WRITE, 0x700018DE, 0x05B6},
+ {TOK_WRITE, 0x700018E0, 0x0000},
+ {TOK_WRITE, 0x700018E2, 0x0000},
+ {TOK_WRITE, 0x700018E4, 0x01F4},
+ {TOK_WRITE, 0x700018E6, 0x05BA},
+ {TOK_WRITE, 0x700018E8, 0x0000},
+ {TOK_WRITE, 0x700018EA, 0x0000},
+ {TOK_WRITE, 0x700018EC, 0x01F4},
+ {TOK_WRITE, 0x700018EE, 0x024F},
+ {TOK_WRITE, 0x700018F0, 0x0000},
+ {TOK_WRITE, 0x700018F2, 0x0000},
+ {TOK_WRITE, 0x700018F4, 0x0000},
+ {TOK_WRITE, 0x700018F6, 0x0000},
+ {TOK_WRITE, 0x700018F8, 0x0000},
+ {TOK_WRITE, 0x700018FA, 0x0000},
+ {TOK_WRITE, 0x700018FC, 0x0075},
+ {TOK_WRITE, 0x700018FE, 0x00CF},
+ {TOK_WRITE, 0x70001900, 0x0000},
+ {TOK_WRITE, 0x70001902, 0x0000},
+ {TOK_WRITE, 0x70001904, 0x0075},
+ {TOK_WRITE, 0x70001906, 0x00D6},
+ {TOK_WRITE, 0x70001908, 0x0000},
+ {TOK_WRITE, 0x7000190A, 0x0000},
+ {TOK_WRITE, 0x7000190C, 0x0004},
+ {TOK_WRITE, 0x7000190E, 0x01F4},
+ {TOK_WRITE, 0x70001910, 0x0000},
+ {TOK_WRITE, 0x70001912, 0x0000},
+ {TOK_WRITE, 0x70001914, 0x00F0},
+ {TOK_WRITE, 0x70001916, 0x01F4},
+ {TOK_WRITE, 0x70001918, 0x029E},
+ {TOK_WRITE, 0x7000191A, 0x05B2},
+ {TOK_WRITE, 0x7000191C, 0x0000},
+ {TOK_WRITE, 0x7000191E, 0x0000},
+ {TOK_WRITE, 0x70001920, 0x0000},
+ {TOK_WRITE, 0x70001922, 0x0000},
+ {TOK_WRITE, 0x70001924, 0x01F8},
+ {TOK_WRITE, 0x70001926, 0x0228},
+ {TOK_WRITE, 0x70001928, 0x0000},
+ {TOK_WRITE, 0x7000192A, 0x0000},
+ {TOK_WRITE, 0x7000192C, 0x0000},
+ {TOK_WRITE, 0x7000192E, 0x0000},
+ {TOK_WRITE, 0x70001930, 0x0208},
+ {TOK_WRITE, 0x70001932, 0x0238},
+ {TOK_WRITE, 0x70001934, 0x0000},
+ {TOK_WRITE, 0x70001936, 0x0000},
+ {TOK_WRITE, 0x70001938, 0x0000},
+ {TOK_WRITE, 0x7000193A, 0x0000},
+ {TOK_WRITE, 0x7000193C, 0x0218},
+ {TOK_WRITE, 0x7000193E, 0x0238},
+ {TOK_WRITE, 0x70001940, 0x0000},
+ {TOK_WRITE, 0x70001942, 0x0000},
+ {TOK_WRITE, 0x70001944, 0x0000},
+ {TOK_WRITE, 0x70001946, 0x0000},
+ {TOK_WRITE, 0x70001948, 0x0001},
+ {TOK_WRITE, 0x7000194A, 0x0009},
+ {TOK_WRITE, 0x7000194C, 0x00DE},
+ {TOK_WRITE, 0x7000194E, 0x05C0},
+ {TOK_WRITE, 0x70001950, 0x0000},
+ {TOK_WRITE, 0x70001952, 0x0000},
+ {TOK_WRITE, 0x70001954, 0x00DF},
+ {TOK_WRITE, 0x70001956, 0x00E4},
+ {TOK_WRITE, 0x70001958, 0x01F8},
+ {TOK_WRITE, 0x7000195A, 0x01FD},
+ {TOK_WRITE, 0x7000195C, 0x05B6},
+ {TOK_WRITE, 0x7000195E, 0x05BB},
+ {TOK_WRITE, 0x70001960, 0x0000},
+ {TOK_WRITE, 0x70001962, 0x0000},
+ {TOK_WRITE, 0x70001964, 0x0000},
+ {TOK_WRITE, 0x70001966, 0x0000},
+ {TOK_WRITE, 0x70001968, 0x0000},
+ {TOK_WRITE, 0x7000196A, 0x0000},
+ {TOK_WRITE, 0x7000196C, 0x0000},
+ {TOK_WRITE, 0x7000196E, 0x0000},
+ {TOK_WRITE, 0x70001970, 0x0000},
+ {TOK_WRITE, 0x70001972, 0x0000},
+ {TOK_WRITE, 0x70001974, 0x0000},
+ {TOK_WRITE, 0x70001976, 0x0000},
+ {TOK_WRITE, 0x70001978, 0x01F8},
+ {TOK_WRITE, 0x7000197A, 0x0000},
+ {TOK_WRITE, 0x7000197C, 0x0000},
+ {TOK_WRITE, 0x7000197E, 0x0077},
+ {TOK_WRITE, 0x70001980, 0x007E},
+ {TOK_WRITE, 0x70001982, 0x024F},
+ {TOK_WRITE, 0x70001984, 0x025E},
+ {TOK_WRITE, 0x70001986, 0x0000},
+ {TOK_WRITE, 0x70001988, 0x0000},
+ {TOK_WRITE, 0x7000198A, 0x0000},
+ {TOK_WRITE, 0x7000198C, 0x0000},
+ {TOK_WRITE, 0x7000198E, 0x0004},
+ {TOK_WRITE, 0x70001990, 0x09D1},
+ {TOK_WRITE, 0x70001992, 0x0000},
+ {TOK_WRITE, 0x70001994, 0x0000},
+ {TOK_WRITE, 0x70001996, 0x0001},
+ {TOK_WRITE, 0x70001998, 0x09D5},
+ {TOK_WRITE, 0x7000199A, 0x0000},
+ {TOK_WRITE, 0x7000199C, 0x0000},
+ {TOK_WRITE, 0x7000199E, 0x0008},
+ {TOK_WRITE, 0x700019A0, 0x09D5},
+ {TOK_WRITE, 0x700019A2, 0x0000},
+ {TOK_WRITE, 0x700019A4, 0x0000},
+ {TOK_WRITE, 0x700019A6, 0x02AA},
+ {TOK_WRITE, 0x700019A8, 0x0326},
+ {TOK_WRITE, 0x700019AA, 0x0000},
+ {TOK_WRITE, 0x700019AC, 0x0000},
+ {TOK_WRITE, 0x700019AE, 0x02AA},
+ {TOK_WRITE, 0x700019B0, 0x09D1},
+ {TOK_WRITE, 0x700019B2, 0x0000},
+ {TOK_WRITE, 0x700019B4, 0x0000},
+ {TOK_WRITE, 0x700019B6, 0x02AA},
+ {TOK_WRITE, 0x700019B8, 0x09D5},
+ {TOK_WRITE, 0x700019BA, 0x0000},
+ {TOK_WRITE, 0x700019BC, 0x0000},
+ {TOK_WRITE, 0x700019BE, 0x02AA},
+ {TOK_WRITE, 0x700019C0, 0x0327},
+ {TOK_WRITE, 0x700019C2, 0x0000},
+ {TOK_WRITE, 0x700019C4, 0x0000},
+ {TOK_WRITE, 0x700019C6, 0x0000},
+ {TOK_WRITE, 0x700019C8, 0x0000},
+ {TOK_WRITE, 0x700019CA, 0x0000},
+ {TOK_WRITE, 0x700019CC, 0x0000},
+ {TOK_WRITE, 0x700019CE, 0x0008},
+ {TOK_WRITE, 0x700019D0, 0x0084},
+ {TOK_WRITE, 0x700019D2, 0x0000},
+ {TOK_WRITE, 0x700019D4, 0x0000},
+ {TOK_WRITE, 0x700019D6, 0x0008},
+ {TOK_WRITE, 0x700019D8, 0x008D},
+ {TOK_WRITE, 0x700019DA, 0x0000},
+ {TOK_WRITE, 0x700019DC, 0x0000},
+ {TOK_WRITE, 0x700019DE, 0x0008},
+ {TOK_WRITE, 0x700019E0, 0x02AA},
+ {TOK_WRITE, 0x700019E2, 0x0000},
+ {TOK_WRITE, 0x700019E4, 0x0000},
+ {TOK_WRITE, 0x700019E6, 0x00AA},
+ {TOK_WRITE, 0x700019E8, 0x02AA},
+ {TOK_WRITE, 0x700019EA, 0x03AD},
+ {TOK_WRITE, 0x700019EC, 0x09CD},
+ {TOK_WRITE, 0x700019EE, 0x0000},
+ {TOK_WRITE, 0x700019F0, 0x0000},
+ {TOK_WRITE, 0x700019F2, 0x0000},
+ {TOK_WRITE, 0x700019F4, 0x0000},
+ {TOK_WRITE, 0x700019F6, 0x02AE},
+ {TOK_WRITE, 0x700019F8, 0x02DE},
+ {TOK_WRITE, 0x700019FA, 0x0000},
+ {TOK_WRITE, 0x700019FC, 0x0000},
+ {TOK_WRITE, 0x700019FE, 0x0000},
+ {TOK_WRITE, 0x70001A00, 0x0000},
+ {TOK_WRITE, 0x70001A02, 0x02BE},
+ {TOK_WRITE, 0x70001A04, 0x02EE},
+ {TOK_WRITE, 0x70001A06, 0x0000},
+ {TOK_WRITE, 0x70001A08, 0x0000},
+ {TOK_WRITE, 0x70001A0A, 0x0000},
+ {TOK_WRITE, 0x70001A0C, 0x0000},
+ {TOK_WRITE, 0x70001A0E, 0x02CE},
+ {TOK_WRITE, 0x70001A10, 0x02EE},
+ {TOK_WRITE, 0x70001A12, 0x0000},
+ {TOK_WRITE, 0x70001A14, 0x0000},
+ {TOK_WRITE, 0x70001A16, 0x0000},
+ {TOK_WRITE, 0x70001A18, 0x0000},
+ {TOK_WRITE, 0x70001A1A, 0x0001},
+ {TOK_WRITE, 0x70001A1C, 0x0009},
+ {TOK_WRITE, 0x70001A1E, 0x0095},
+ {TOK_WRITE, 0x70001A20, 0x09DB},
+ {TOK_WRITE, 0x70001A22, 0x0000},
+ {TOK_WRITE, 0x70001A24, 0x0000},
+ {TOK_WRITE, 0x70001A26, 0x0096},
+ {TOK_WRITE, 0x70001A28, 0x009B},
+ {TOK_WRITE, 0x70001A2A, 0x02AE},
+ {TOK_WRITE, 0x70001A2C, 0x02B3},
+ {TOK_WRITE, 0x70001A2E, 0x09D1},
+ {TOK_WRITE, 0x70001A30, 0x09D6},
+ {TOK_WRITE, 0x70001A32, 0x0000},
+ {TOK_WRITE, 0x70001A34, 0x0000},
+ {TOK_WRITE, 0x70001A36, 0x0000},
+ {TOK_WRITE, 0x70001A38, 0x0000},
+ {TOK_WRITE, 0x70001A3A, 0x0000},
+ {TOK_WRITE, 0x70001A3C, 0x0000},
+ {TOK_WRITE, 0x70001A3E, 0x0000},
+ {TOK_WRITE, 0x70001A40, 0x0000},
+ {TOK_WRITE, 0x70001A42, 0x0000},
+ {TOK_WRITE, 0x70001A44, 0x0000},
+ {TOK_WRITE, 0x70001A46, 0x0000},
+ {TOK_WRITE, 0x70001A48, 0x0000},
+ {TOK_WRITE, 0x70001A4A, 0x02AE},
+ {TOK_WRITE, 0x70001A4C, 0x0000},
+ {TOK_WRITE, 0x70001A4E, 0x0000},
+ {TOK_WRITE, 0x70001A50, 0x0009},
+ {TOK_WRITE, 0x70001A52, 0x0010},
+ {TOK_WRITE, 0x70001A54, 0x0327},
+ {TOK_WRITE, 0x70001A56, 0x0336},
+ {TOK_WRITE, 0x70001A58, 0x0000},
+ {TOK_WRITE, 0x70001A5A, 0x0000},
+ {TOK_WRITE, 0x70001A5C, 0x0000},
+ {TOK_WRITE, 0x70001A5E, 0x0000},
+ {TOK_WRITE, 0x70001AF8, 0x5A3C},
+ {TOK_WRITE, 0x70001896, 0x0002},
+ {TOK_WRITE, 0x70001898, 0x0000},
+ {TOK_WRITE, 0x7000189A, 0x0003},
+ {TOK_WRITE, 0x7000189E, 0x0FB0},
+ {TOK_WRITE, 0x700018AC, 0x0060},
+ {TOK_WRITE, 0x700018AE, 0x0060},
+ {TOK_WRITE, 0x700018B0, 0x05C0},
+ {TOK_WRITE, 0x700018B2, 0x05C0},
+ {TOK_WRITE, 0x70001AEA, 0x8080},
+ {TOK_WRITE, 0x70001AEC, 0x0080},
+ {TOK_WRITE, 0x70001AE0, 0x0000},
+ {TOK_WRITE, 0x70001A72, 0x0000},
+ {TOK_WRITE, 0x700018A2, 0x0004},
+ {TOK_WRITE, 0x70001A6A, 0x009A},
+ {TOK_WRITE, 0x7000385E, 0x024C},
+ {TOK_WRITE, 0x70000EE6, 0x0000},
+ {TOK_WRITE, 0x70001B2A, 0x0300},
+ {TOK_WRITE, 0x70001B2C, 0x00D6},
+ {TOK_WRITE, 0x70001B2E, 0x008D},
+ {TOK_WRITE, 0x70001B30, 0x00CF},
+ {TOK_WRITE, 0x70001B32, 0x0084},
+ {TOK_WRITE, 0x70000722, 0x0100},
+ {TOK_WRITE, 0x70000726, 0x0001},
+ {TOK_WRITE, 0x700008D6, 0x0001},
+ {TOK_WRITE, 0x7000146E, 0x0000},
+ {TOK_WRITE, 0x700008DC, 0x0000},
+ {TOK_WRITE, 0x70003AF8, 0xB570},
+ {TOK_WRITE, 0x70003AFA, 0x4B39},
+ {TOK_WRITE, 0x70003AFC, 0x4939},
+ {TOK_WRITE, 0x70003AFE, 0x483A},
+ {TOK_WRITE, 0x70003B00, 0x2200},
+ {TOK_WRITE, 0x70003B02, 0xC008},
+ {TOK_WRITE, 0x70003B04, 0x6001},
+ {TOK_WRITE, 0x70003B06, 0x4939},
+ {TOK_WRITE, 0x70003B08, 0x4839},
+ {TOK_WRITE, 0x70003B0A, 0x2401},
+ {TOK_WRITE, 0x70003B0C, 0xF000},
+ {TOK_WRITE, 0x70003B0E, 0xFBD4},
+ {TOK_WRITE, 0x70003B10, 0x4938},
+ {TOK_WRITE, 0x70003B12, 0x4839},
+ {TOK_WRITE, 0x70003B14, 0x2502},
+ {TOK_WRITE, 0x70003B16, 0x0022},
+ {TOK_WRITE, 0x70003B18, 0xF000},
+ {TOK_WRITE, 0x70003B1A, 0xFBCE},
+ {TOK_WRITE, 0x70003B1C, 0x4837},
+ {TOK_WRITE, 0x70003B1E, 0x0261},
+ {TOK_WRITE, 0x70003B20, 0x8001},
+ {TOK_WRITE, 0x70003B22, 0x2100},
+ {TOK_WRITE, 0x70003B24, 0x8041},
+ {TOK_WRITE, 0x70003B26, 0x4936},
+ {TOK_WRITE, 0x70003B28, 0x4836},
+ {TOK_WRITE, 0x70003B2A, 0x6041},
+ {TOK_WRITE, 0x70003B2C, 0x4936},
+ {TOK_WRITE, 0x70003B2E, 0x4837},
+ {TOK_WRITE, 0x70003B30, 0x2403},
+ {TOK_WRITE, 0x70003B32, 0x002A},
+ {TOK_WRITE, 0x70003B34, 0xF000},
+ {TOK_WRITE, 0x70003B36, 0xFBC0},
+ {TOK_WRITE, 0x70003B38, 0x4832},
+ {TOK_WRITE, 0x70003B3A, 0x4935},
+ {TOK_WRITE, 0x70003B3C, 0x30C0},
+ {TOK_WRITE, 0x70003B3E, 0x63C1},
+ {TOK_WRITE, 0x70003B40, 0x4930},
+ {TOK_WRITE, 0x70003B42, 0x4834},
+ {TOK_WRITE, 0x70003B44, 0x3980},
+ {TOK_WRITE, 0x70003B46, 0x6408},
+ {TOK_WRITE, 0x70003B48, 0x4833},
+ {TOK_WRITE, 0x70003B4A, 0x4934},
+ {TOK_WRITE, 0x70003B4C, 0x6388},
+ {TOK_WRITE, 0x70003B4E, 0x4934},
+ {TOK_WRITE, 0x70003B50, 0x4834},
+ {TOK_WRITE, 0x70003B52, 0x0022},
+ {TOK_WRITE, 0x70003B54, 0x2504},
+ {TOK_WRITE, 0x70003B56, 0xF000},
+ {TOK_WRITE, 0x70003B58, 0xFBAF},
+ {TOK_WRITE, 0x70003B5A, 0x4933},
+ {TOK_WRITE, 0x70003B5C, 0x4833},
+ {TOK_WRITE, 0x70003B5E, 0x2405},
+ {TOK_WRITE, 0x70003B60, 0x002A},
+ {TOK_WRITE, 0x70003B62, 0xF000},
+ {TOK_WRITE, 0x70003B64, 0xF881},
+ {TOK_WRITE, 0x70003B66, 0x491F},
+ {TOK_WRITE, 0x70003B68, 0x4830},
+ {TOK_WRITE, 0x70003B6A, 0x0022},
+ {TOK_WRITE, 0x70003B6C, 0x2506},
+ {TOK_WRITE, 0x70003B6E, 0x39B6},
+ {TOK_WRITE, 0x70003B70, 0x1D80},
+ {TOK_WRITE, 0x70003B72, 0xF000},
+ {TOK_WRITE, 0x70003B74, 0xF879},
+ {TOK_WRITE, 0x70003B76, 0x482D},
+ {TOK_WRITE, 0x70003B78, 0x492D},
+ {TOK_WRITE, 0x70003B7A, 0x2407},
+ {TOK_WRITE, 0x70003B7C, 0x002A},
+ {TOK_WRITE, 0x70003B7E, 0x300C},
+ {TOK_WRITE, 0x70003B80, 0xF000},
+ {TOK_WRITE, 0x70003B82, 0xF872},
+ {TOK_WRITE, 0x70003B84, 0x4829},
+ {TOK_WRITE, 0x70003B86, 0x492B},
+ {TOK_WRITE, 0x70003B88, 0x0022},
+ {TOK_WRITE, 0x70003B8A, 0x2508},
+ {TOK_WRITE, 0x70003B8C, 0x3010},
+ {TOK_WRITE, 0x70003B8E, 0xF000},
+ {TOK_WRITE, 0x70003B90, 0xF86B},
+ {TOK_WRITE, 0x70003B92, 0x4929},
+ {TOK_WRITE, 0x70003B94, 0x4829},
+ {TOK_WRITE, 0x70003B96, 0x2409},
+ {TOK_WRITE, 0x70003B98, 0x002A},
+ {TOK_WRITE, 0x70003B9A, 0xF000},
+ {TOK_WRITE, 0x70003B9C, 0xFB8D},
+ {TOK_WRITE, 0x70003B9E, 0x4928},
+ {TOK_WRITE, 0x70003BA0, 0x4828},
+ {TOK_WRITE, 0x70003BA2, 0x0022},
+ {TOK_WRITE, 0x70003BA4, 0x250A},
+ {TOK_WRITE, 0x70003BA6, 0xF000},
+ {TOK_WRITE, 0x70003BA8, 0xFB87},
+ {TOK_WRITE, 0x70003BAA, 0x4927},
+ {TOK_WRITE, 0x70003BAC, 0x4827},
+ {TOK_WRITE, 0x70003BAE, 0x240B},
+ {TOK_WRITE, 0x70003BB0, 0x002A},
+ {TOK_WRITE, 0x70003BB2, 0xF000},
+ {TOK_WRITE, 0x70003BB4, 0xFB81},
+ {TOK_WRITE, 0x70003BB6, 0x4926},
+ {TOK_WRITE, 0x70003BB8, 0x4826},
+ {TOK_WRITE, 0x70003BBA, 0x0022},
+ {TOK_WRITE, 0x70003BBC, 0x250C},
+ {TOK_WRITE, 0x70003BBE, 0xF000},
+ {TOK_WRITE, 0x70003BC0, 0xFB7B},
+ {TOK_WRITE, 0x70003BC2, 0x4925},
+ {TOK_WRITE, 0x70003BC4, 0x4825},
+ {TOK_WRITE, 0x70003BC6, 0x240D},
+ {TOK_WRITE, 0x70003BC8, 0x002A},
+ {TOK_WRITE, 0x70003BCA, 0xF000},
+ {TOK_WRITE, 0x70003BCC, 0xFB75},
+ {TOK_WRITE, 0x70003BCE, 0x4924},
+ {TOK_WRITE, 0x70003BD0, 0x4824},
+ {TOK_WRITE, 0x70003BD2, 0x0022},
+ {TOK_WRITE, 0x70003BD4, 0xF000},
+ {TOK_WRITE, 0x70003BD6, 0xFB70},
+ {TOK_WRITE, 0x70003BD8, 0xBC70},
+ {TOK_WRITE, 0x70003BDA, 0xBC08},
+ {TOK_WRITE, 0x70003BDC, 0x4718},
+ {TOK_WRITE, 0x70003BDE, 0x0000},
+ {TOK_WRITE, 0x70003BE0, 0x018F},
+ {TOK_WRITE, 0x70003BE2, 0x4EC2},
+ {TOK_WRITE, 0x70003BE4, 0x037F},
+ {TOK_WRITE, 0x70003BE6, 0x0000},
+ {TOK_WRITE, 0x70003BE8, 0x1F90},
+ {TOK_WRITE, 0x70003BEA, 0x7000},
+ {TOK_WRITE, 0x70003BEC, 0x3C81},
+ {TOK_WRITE, 0x70003BEE, 0x7000},
+ {TOK_WRITE, 0x70003BF0, 0xE38B},
+ {TOK_WRITE, 0x70003BF2, 0x0000},
+ {TOK_WRITE, 0x70003BF4, 0x3CB9},
+ {TOK_WRITE, 0x70003BF6, 0x7000},
+ {TOK_WRITE, 0x70003BF8, 0xC3B1},
+ {TOK_WRITE, 0x70003BFA, 0x0000},
+ {TOK_WRITE, 0x70003BFC, 0x4780},
+ {TOK_WRITE, 0x70003BFE, 0x7000},
+ {TOK_WRITE, 0x70003C00, 0x3D17},
+ {TOK_WRITE, 0x70003C02, 0x7000},
+ {TOK_WRITE, 0x70003C04, 0x0080},
+ {TOK_WRITE, 0x70003C06, 0x7000},
+ {TOK_WRITE, 0x70003C08, 0x3D53},
+ {TOK_WRITE, 0x70003C0A, 0x7000},
+ {TOK_WRITE, 0x70003C0C, 0xB49D},
+ {TOK_WRITE, 0x70003C0E, 0x0000},
+ {TOK_WRITE, 0x70003C10, 0x3DFF},
+ {TOK_WRITE, 0x70003C12, 0x7000},
+ {TOK_WRITE, 0x70003C14, 0x3DB3},
+ {TOK_WRITE, 0x70003C16, 0x7000},
+ {TOK_WRITE, 0x70003C18, 0xFFFF},
+ {TOK_WRITE, 0x70003C1A, 0x00FF},
+ {TOK_WRITE, 0x70003C1C, 0x17E0},
+ {TOK_WRITE, 0x70003C1E, 0x7000},
+ {TOK_WRITE, 0x70003C20, 0x3F7B},
+ {TOK_WRITE, 0x70003C22, 0x7000},
+ {TOK_WRITE, 0x70003C24, 0x053D},
+ {TOK_WRITE, 0x70003C26, 0x0000},
+ {TOK_WRITE, 0x70003C28, 0x0000},
+ {TOK_WRITE, 0x70003C2A, 0x0A89},
+ {TOK_WRITE, 0x70003C2C, 0x6CD2},
+ {TOK_WRITE, 0x70003C2E, 0x0000},
+ {TOK_WRITE, 0x70003C30, 0x0000},
+ {TOK_WRITE, 0x70003C32, 0x0A9A},
+ {TOK_WRITE, 0x70003C34, 0x0000},
+ {TOK_WRITE, 0x70003C36, 0x02D2},
+ {TOK_WRITE, 0x70003C38, 0x3FC9},
+ {TOK_WRITE, 0x70003C3A, 0x7000},
+ {TOK_WRITE, 0x70003C3C, 0x9E65},
+ {TOK_WRITE, 0x70003C3E, 0x0000},
+ {TOK_WRITE, 0x70003C40, 0x403D},
+ {TOK_WRITE, 0x70003C42, 0x7000},
+ {TOK_WRITE, 0x70003C44, 0x7C49},
+ {TOK_WRITE, 0x70003C46, 0x0000},
+ {TOK_WRITE, 0x70003C48, 0x40B1},
+ {TOK_WRITE, 0x70003C4A, 0x7000},
+ {TOK_WRITE, 0x70003C4C, 0x7C63},
+ {TOK_WRITE, 0x70003C4E, 0x0000},
+ {TOK_WRITE, 0x70003C50, 0x40CD},
+ {TOK_WRITE, 0x70003C52, 0x7000},
+ {TOK_WRITE, 0x70003C54, 0x8F01},
+ {TOK_WRITE, 0x70003C56, 0x0000},
+ {TOK_WRITE, 0x70003C58, 0x416F},
+ {TOK_WRITE, 0x70003C5A, 0x7000},
+ {TOK_WRITE, 0x70003C5C, 0x7F3F},
+ {TOK_WRITE, 0x70003C5E, 0x0000},
+ {TOK_WRITE, 0x70003C60, 0x41FD},
+ {TOK_WRITE, 0x70003C62, 0x7000},
+ {TOK_WRITE, 0x70003C64, 0x98C5},
+ {TOK_WRITE, 0x70003C66, 0x0000},
+ {TOK_WRITE, 0x70003C68, 0xB570},
+ {TOK_WRITE, 0x70003C6A, 0x000C},
+ {TOK_WRITE, 0x70003C6C, 0x0015},
+ {TOK_WRITE, 0x70003C6E, 0x0029},
+ {TOK_WRITE, 0x70003C70, 0xF000},
+ {TOK_WRITE, 0x70003C72, 0xFB2A},
+ {TOK_WRITE, 0x70003C74, 0x49F8},
+ {TOK_WRITE, 0x70003C76, 0x00A8},
+ {TOK_WRITE, 0x70003C78, 0x500C},
+ {TOK_WRITE, 0x70003C7A, 0xBC70},
+ {TOK_WRITE, 0x70003C7C, 0xBC08},
+ {TOK_WRITE, 0x70003C7E, 0x4718},
+ {TOK_WRITE, 0x70003C80, 0x6808},
+ {TOK_WRITE, 0x70003C82, 0x0400},
+ {TOK_WRITE, 0x70003C84, 0x0C00},
+ {TOK_WRITE, 0x70003C86, 0x6849},
+ {TOK_WRITE, 0x70003C88, 0x0409},
+ {TOK_WRITE, 0x70003C8A, 0x0C09},
+ {TOK_WRITE, 0x70003C8C, 0x4AF3},
+ {TOK_WRITE, 0x70003C8E, 0x8992},
+ {TOK_WRITE, 0x70003C90, 0x2A00},
+ {TOK_WRITE, 0x70003C92, 0xD00D},
+ {TOK_WRITE, 0x70003C94, 0x2300},
+ {TOK_WRITE, 0x70003C96, 0x1A89},
+ {TOK_WRITE, 0x70003C98, 0xD400},
+ {TOK_WRITE, 0x70003C9A, 0x000B},
+ {TOK_WRITE, 0x70003C9C, 0x0419},
+ {TOK_WRITE, 0x70003C9E, 0x0C09},
+ {TOK_WRITE, 0x70003CA0, 0x23FF},
+ {TOK_WRITE, 0x70003CA2, 0x33C1},
+ {TOK_WRITE, 0x70003CA4, 0x1810},
+ {TOK_WRITE, 0x70003CA6, 0x4298},
+ {TOK_WRITE, 0x70003CA8, 0xD800},
+ {TOK_WRITE, 0x70003CAA, 0x0003},
+ {TOK_WRITE, 0x70003CAC, 0x0418},
+ {TOK_WRITE, 0x70003CAE, 0x0C00},
+ {TOK_WRITE, 0x70003CB0, 0x4AEB},
+ {TOK_WRITE, 0x70003CB2, 0x8150},
+ {TOK_WRITE, 0x70003CB4, 0x8191},
+ {TOK_WRITE, 0x70003CB6, 0x4770},
+ {TOK_WRITE, 0x70003CB8, 0xB5F3},
+ {TOK_WRITE, 0x70003CBA, 0x0004},
+ {TOK_WRITE, 0x70003CBC, 0xB081},
+ {TOK_WRITE, 0x70003CBE, 0x9802},
+ {TOK_WRITE, 0x70003CC0, 0x6800},
+ {TOK_WRITE, 0x70003CC2, 0x0600},
+ {TOK_WRITE, 0x70003CC4, 0x0E00},
+ {TOK_WRITE, 0x70003CC6, 0x2201},
+ {TOK_WRITE, 0x70003CC8, 0x0015},
+ {TOK_WRITE, 0x70003CCA, 0x0021},
+ {TOK_WRITE, 0x70003CCC, 0x3910},
+ {TOK_WRITE, 0x70003CCE, 0x408A},
+ {TOK_WRITE, 0x70003CD0, 0x40A5},
+ {TOK_WRITE, 0x70003CD2, 0x4FE4},
+ {TOK_WRITE, 0x70003CD4, 0x0016},
+ {TOK_WRITE, 0x70003CD6, 0x2C10},
+ {TOK_WRITE, 0x70003CD8, 0xDA03},
+ {TOK_WRITE, 0x70003CDA, 0x8839},
+ {TOK_WRITE, 0x70003CDC, 0x43A9},
+ {TOK_WRITE, 0x70003CDE, 0x8039},
+ {TOK_WRITE, 0x70003CE0, 0xE002},
+ {TOK_WRITE, 0x70003CE2, 0x8879},
+ {TOK_WRITE, 0x70003CE4, 0x43B1},
+ {TOK_WRITE, 0x70003CE6, 0x8079},
+ {TOK_WRITE, 0x70003CE8, 0xF000},
+ {TOK_WRITE, 0x70003CEA, 0xFAF6},
+ {TOK_WRITE, 0x70003CEC, 0x2C10},
+ {TOK_WRITE, 0x70003CEE, 0xDA03},
+ {TOK_WRITE, 0x70003CF0, 0x8839},
+ {TOK_WRITE, 0x70003CF2, 0x4329},
+ {TOK_WRITE, 0x70003CF4, 0x8039},
+ {TOK_WRITE, 0x70003CF6, 0xE002},
+ {TOK_WRITE, 0x70003CF8, 0x8879},
+ {TOK_WRITE, 0x70003CFA, 0x4331},
+ {TOK_WRITE, 0x70003CFC, 0x8079},
+ {TOK_WRITE, 0x70003CFE, 0x49DA},
+ {TOK_WRITE, 0x70003D00, 0x8809},
+ {TOK_WRITE, 0x70003D02, 0x2900},
+ {TOK_WRITE, 0x70003D04, 0xD102},
+ {TOK_WRITE, 0x70003D06, 0xF000},
+ {TOK_WRITE, 0x70003D08, 0xFAEF},
+ {TOK_WRITE, 0x70003D0A, 0x2000},
+ {TOK_WRITE, 0x70003D0C, 0x9902},
+ {TOK_WRITE, 0x70003D0E, 0x6008},
+ {TOK_WRITE, 0x70003D10, 0xBCFE},
+ {TOK_WRITE, 0x70003D12, 0xBC08},
+ {TOK_WRITE, 0x70003D14, 0x4718},
+ {TOK_WRITE, 0x70003D16, 0xB538},
+ {TOK_WRITE, 0x70003D18, 0x9C04},
+ {TOK_WRITE, 0x70003D1A, 0x0015},
+ {TOK_WRITE, 0x70003D1C, 0x002A},
+ {TOK_WRITE, 0x70003D1E, 0x9400},
+ {TOK_WRITE, 0x70003D20, 0xF000},
+ {TOK_WRITE, 0x70003D22, 0xFAEA},
+ {TOK_WRITE, 0x70003D24, 0x4AD1},
+ {TOK_WRITE, 0x70003D26, 0x8811},
+ {TOK_WRITE, 0x70003D28, 0x2900},
+ {TOK_WRITE, 0x70003D2A, 0xD00F},
+ {TOK_WRITE, 0x70003D2C, 0x8820},
+ {TOK_WRITE, 0x70003D2E, 0x4281},
+ {TOK_WRITE, 0x70003D30, 0xD20C},
+ {TOK_WRITE, 0x70003D32, 0x8861},
+ {TOK_WRITE, 0x70003D34, 0x8853},
+ {TOK_WRITE, 0x70003D36, 0x4299},
+ {TOK_WRITE, 0x70003D38, 0xD200},
+ {TOK_WRITE, 0x70003D3A, 0x1E40},
+ {TOK_WRITE, 0x70003D3C, 0x0400},
+ {TOK_WRITE, 0x70003D3E, 0x0C00},
+ {TOK_WRITE, 0x70003D40, 0x8020},
+ {TOK_WRITE, 0x70003D42, 0x8851},
+ {TOK_WRITE, 0x70003D44, 0x8061},
+ {TOK_WRITE, 0x70003D46, 0x4368},
+ {TOK_WRITE, 0x70003D48, 0x1840},
+ {TOK_WRITE, 0x70003D4A, 0x6060},
+ {TOK_WRITE, 0x70003D4C, 0xBC38},
+ {TOK_WRITE, 0x70003D4E, 0xBC08},
+ {TOK_WRITE, 0x70003D50, 0x4718},
+ {TOK_WRITE, 0x70003D52, 0xB5F8},
+ {TOK_WRITE, 0x70003D54, 0x0004},
+ {TOK_WRITE, 0x70003D56, 0x6808},
+ {TOK_WRITE, 0x70003D58, 0x0400},
+ {TOK_WRITE, 0x70003D5A, 0x0C00},
+ {TOK_WRITE, 0x70003D5C, 0x2201},
+ {TOK_WRITE, 0x70003D5E, 0x0015},
+ {TOK_WRITE, 0x70003D60, 0x0021},
+ {TOK_WRITE, 0x70003D62, 0x3910},
+ {TOK_WRITE, 0x70003D64, 0x408A},
+ {TOK_WRITE, 0x70003D66, 0x40A5},
+ {TOK_WRITE, 0x70003D68, 0x4FBE},
+ {TOK_WRITE, 0x70003D6A, 0x0016},
+ {TOK_WRITE, 0x70003D6C, 0x2C10},
+ {TOK_WRITE, 0x70003D6E, 0xDA03},
+ {TOK_WRITE, 0x70003D70, 0x8839},
+ {TOK_WRITE, 0x70003D72, 0x43A9},
+ {TOK_WRITE, 0x70003D74, 0x8039},
+ {TOK_WRITE, 0x70003D76, 0xE002},
+ {TOK_WRITE, 0x70003D78, 0x8879},
+ {TOK_WRITE, 0x70003D7A, 0x43B1},
+ {TOK_WRITE, 0x70003D7C, 0x8079},
+ {TOK_WRITE, 0x70003D7E, 0xF000},
+ {TOK_WRITE, 0x70003D80, 0xFAC3},
+ {TOK_WRITE, 0x70003D82, 0x2C10},
+ {TOK_WRITE, 0x70003D84, 0xDA03},
+ {TOK_WRITE, 0x70003D86, 0x8838},
+ {TOK_WRITE, 0x70003D88, 0x4328},
+ {TOK_WRITE, 0x70003D8A, 0x8038},
+ {TOK_WRITE, 0x70003D8C, 0xE002},
+ {TOK_WRITE, 0x70003D8E, 0x8878},
+ {TOK_WRITE, 0x70003D90, 0x4330},
+ {TOK_WRITE, 0x70003D92, 0x8078},
+ {TOK_WRITE, 0x70003D94, 0x48B6},
+ {TOK_WRITE, 0x70003D96, 0x8800},
+ {TOK_WRITE, 0x70003D98, 0x0400},
+ {TOK_WRITE, 0x70003D9A, 0xD507},
+ {TOK_WRITE, 0x70003D9C, 0x4BB5},
+ {TOK_WRITE, 0x70003D9E, 0x7819},
+ {TOK_WRITE, 0x70003DA0, 0x4AB5},
+ {TOK_WRITE, 0x70003DA2, 0x7810},
+ {TOK_WRITE, 0x70003DA4, 0x7018},
+ {TOK_WRITE, 0x70003DA6, 0x7011},
+ {TOK_WRITE, 0x70003DA8, 0x49B4},
+ {TOK_WRITE, 0x70003DAA, 0x8188},
+ {TOK_WRITE, 0x70003DAC, 0xBCF8},
+ {TOK_WRITE, 0x70003DAE, 0xBC08},
+ {TOK_WRITE, 0x70003DB0, 0x4718},
+ {TOK_WRITE, 0x70003DB2, 0xB538},
+ {TOK_WRITE, 0x70003DB4, 0x48B2},
+ {TOK_WRITE, 0x70003DB6, 0x4669},
+ {TOK_WRITE, 0x70003DB8, 0xF000},
+ {TOK_WRITE, 0x70003DBA, 0xFAAE},
+ {TOK_WRITE, 0x70003DBC, 0x48B1},
+ {TOK_WRITE, 0x70003DBE, 0x49B0},
+ {TOK_WRITE, 0x70003DC0, 0x69C2},
+ {TOK_WRITE, 0x70003DC2, 0x2400},
+ {TOK_WRITE, 0x70003DC4, 0x31A8},
+ {TOK_WRITE, 0x70003DC6, 0x2A00},
+ {TOK_WRITE, 0x70003DC8, 0xD008},
+ {TOK_WRITE, 0x70003DCA, 0x61C4},
+ {TOK_WRITE, 0x70003DCC, 0x684A},
+ {TOK_WRITE, 0x70003DCE, 0x6242},
+ {TOK_WRITE, 0x70003DD0, 0x6282},
+ {TOK_WRITE, 0x70003DD2, 0x466B},
+ {TOK_WRITE, 0x70003DD4, 0x881A},
+ {TOK_WRITE, 0x70003DD6, 0x6302},
+ {TOK_WRITE, 0x70003DD8, 0x885A},
+ {TOK_WRITE, 0x70003DDA, 0x6342},
+ {TOK_WRITE, 0x70003DDC, 0x6A02},
+ {TOK_WRITE, 0x70003DDE, 0x2A00},
+ {TOK_WRITE, 0x70003DE0, 0xD00A},
+ {TOK_WRITE, 0x70003DE2, 0x6204},
+ {TOK_WRITE, 0x70003DE4, 0x6849},
+ {TOK_WRITE, 0x70003DE6, 0x6281},
+ {TOK_WRITE, 0x70003DE8, 0x466B},
+ {TOK_WRITE, 0x70003DEA, 0x8819},
+ {TOK_WRITE, 0x70003DEC, 0x6301},
+ {TOK_WRITE, 0x70003DEE, 0x8859},
+ {TOK_WRITE, 0x70003DF0, 0x6341},
+ {TOK_WRITE, 0x70003DF2, 0x49A5},
+ {TOK_WRITE, 0x70003DF4, 0x88C9},
+ {TOK_WRITE, 0x70003DF6, 0x63C1},
+ {TOK_WRITE, 0x70003DF8, 0xF000},
+ {TOK_WRITE, 0x70003DFA, 0xFA96},
+ {TOK_WRITE, 0x70003DFC, 0xE7A6},
+ {TOK_WRITE, 0x70003DFE, 0xB5F0},
+ {TOK_WRITE, 0x70003E00, 0xB08B},
+ {TOK_WRITE, 0x70003E02, 0x20FF},
+ {TOK_WRITE, 0x70003E04, 0x1C40},
+ {TOK_WRITE, 0x70003E06, 0x49A1},
+ {TOK_WRITE, 0x70003E08, 0x89CC},
+ {TOK_WRITE, 0x70003E0A, 0x4E9E},
+ {TOK_WRITE, 0x70003E0C, 0x6AB1},
+ {TOK_WRITE, 0x70003E0E, 0x4284},
+ {TOK_WRITE, 0x70003E10, 0xD101},
+ {TOK_WRITE, 0x70003E12, 0x489F},
+ {TOK_WRITE, 0x70003E14, 0x6081},
+ {TOK_WRITE, 0x70003E16, 0x6A70},
+ {TOK_WRITE, 0x70003E18, 0x0200},
+ {TOK_WRITE, 0x70003E1A, 0xF000},
+ {TOK_WRITE, 0x70003E1C, 0xFA8D},
+ {TOK_WRITE, 0x70003E1E, 0x0400},
+ {TOK_WRITE, 0x70003E20, 0x0C00},
+ {TOK_WRITE, 0x70003E22, 0x4A96},
+ {TOK_WRITE, 0x70003E24, 0x8A11},
+ {TOK_WRITE, 0x70003E26, 0x9109},
+ {TOK_WRITE, 0x70003E28, 0x2101},
+ {TOK_WRITE, 0x70003E2A, 0x0349},
+ {TOK_WRITE, 0x70003E2C, 0x4288},
+ {TOK_WRITE, 0x70003E2E, 0xD200},
+ {TOK_WRITE, 0x70003E30, 0x0001},
+ {TOK_WRITE, 0x70003E32, 0x4A92},
+ {TOK_WRITE, 0x70003E34, 0x8211},
+ {TOK_WRITE, 0x70003E36, 0x4D97},
+ {TOK_WRITE, 0x70003E38, 0x8829},
+ {TOK_WRITE, 0x70003E3A, 0x9108},
+ {TOK_WRITE, 0x70003E3C, 0x4A8B},
+ {TOK_WRITE, 0x70003E3E, 0x2303},
+ {TOK_WRITE, 0x70003E40, 0x3222},
+ {TOK_WRITE, 0x70003E42, 0x1F91},
+ {TOK_WRITE, 0x70003E44, 0xF000},
+ {TOK_WRITE, 0x70003E46, 0xFA7E},
+ {TOK_WRITE, 0x70003E48, 0x8028},
+ {TOK_WRITE, 0x70003E4A, 0x488E},
+ {TOK_WRITE, 0x70003E4C, 0x4987},
+ {TOK_WRITE, 0x70003E4E, 0x6BC2},
+ {TOK_WRITE, 0x70003E50, 0x6AC0},
+ {TOK_WRITE, 0x70003E52, 0x4282},
+ {TOK_WRITE, 0x70003E54, 0xD201},
+ {TOK_WRITE, 0x70003E56, 0x8CC8},
+ {TOK_WRITE, 0x70003E58, 0x8028},
+ {TOK_WRITE, 0x70003E5A, 0x88E8},
+ {TOK_WRITE, 0x70003E5C, 0x9007},
+ {TOK_WRITE, 0x70003E5E, 0x2240},
+ {TOK_WRITE, 0x70003E60, 0x4310},
+ {TOK_WRITE, 0x70003E62, 0x80E8},
+ {TOK_WRITE, 0x70003E64, 0x2000},
+ {TOK_WRITE, 0x70003E66, 0x0041},
+ {TOK_WRITE, 0x70003E68, 0x194B},
+ {TOK_WRITE, 0x70003E6A, 0x001E},
+ {TOK_WRITE, 0x70003E6C, 0x3680},
+ {TOK_WRITE, 0x70003E6E, 0x8BB2},
+ {TOK_WRITE, 0x70003E70, 0xAF04},
+ {TOK_WRITE, 0x70003E72, 0x527A},
+ {TOK_WRITE, 0x70003E74, 0x4A7D},
+ {TOK_WRITE, 0x70003E76, 0x188A},
+ {TOK_WRITE, 0x70003E78, 0x8897},
+ {TOK_WRITE, 0x70003E7A, 0x83B7},
+ {TOK_WRITE, 0x70003E7C, 0x33A0},
+ {TOK_WRITE, 0x70003E7E, 0x891F},
+ {TOK_WRITE, 0x70003E80, 0xAE01},
+ {TOK_WRITE, 0x70003E82, 0x5277},
+ {TOK_WRITE, 0x70003E84, 0x8A11},
+ {TOK_WRITE, 0x70003E86, 0x8119},
+ {TOK_WRITE, 0x70003E88, 0x1C40},
+ {TOK_WRITE, 0x70003E8A, 0x0400},
+ {TOK_WRITE, 0x70003E8C, 0x0C00},
+ {TOK_WRITE, 0x70003E8E, 0x2806},
+ {TOK_WRITE, 0x70003E90, 0xD3E9},
+ {TOK_WRITE, 0x70003E92, 0xF000},
+ {TOK_WRITE, 0x70003E94, 0xFA5F},
+ {TOK_WRITE, 0x70003E96, 0xF000},
+ {TOK_WRITE, 0x70003E98, 0xFA65},
+ {TOK_WRITE, 0x70003E9A, 0x4F79},
+ {TOK_WRITE, 0x70003E9C, 0x37A8},
+ {TOK_WRITE, 0x70003E9E, 0x2800},
+ {TOK_WRITE, 0x70003EA0, 0xD10A},
+ {TOK_WRITE, 0x70003EA2, 0x1FE0},
+ {TOK_WRITE, 0x70003EA4, 0x38FD},
+ {TOK_WRITE, 0x70003EA6, 0xD001},
+ {TOK_WRITE, 0x70003EA8, 0x1CC0},
+ {TOK_WRITE, 0x70003EAA, 0xD105},
+ {TOK_WRITE, 0x70003EAC, 0x4874},
+ {TOK_WRITE, 0x70003EAE, 0x8829},
+ {TOK_WRITE, 0x70003EB0, 0x3818},
+ {TOK_WRITE, 0x70003EB2, 0x6840},
+ {TOK_WRITE, 0x70003EB4, 0x4348},
+ {TOK_WRITE, 0x70003EB6, 0x6078},
+ {TOK_WRITE, 0x70003EB8, 0x4972},
+ {TOK_WRITE, 0x70003EBA, 0x6878},
+ {TOK_WRITE, 0x70003EBC, 0x6B89},
+ {TOK_WRITE, 0x70003EBE, 0x4288},
+ {TOK_WRITE, 0x70003EC0, 0xD300},
+ {TOK_WRITE, 0x70003EC2, 0x0008},
+ {TOK_WRITE, 0x70003EC4, 0x6078},
+ {TOK_WRITE, 0x70003EC6, 0x2000},
+ {TOK_WRITE, 0x70003EC8, 0x0041},
+ {TOK_WRITE, 0x70003ECA, 0xAA04},
+ {TOK_WRITE, 0x70003ECC, 0x5A53},
+ {TOK_WRITE, 0x70003ECE, 0x194A},
+ {TOK_WRITE, 0x70003ED0, 0x269C},
+ {TOK_WRITE, 0x70003ED2, 0x52B3},
+ {TOK_WRITE, 0x70003ED4, 0xAB01},
+ {TOK_WRITE, 0x70003ED6, 0x5A59},
+ {TOK_WRITE, 0x70003ED8, 0x32A0},
+ {TOK_WRITE, 0x70003EDA, 0x8111},
+ {TOK_WRITE, 0x70003EDC, 0x1C40},
+ {TOK_WRITE, 0x70003EDE, 0x0400},
+ {TOK_WRITE, 0x70003EE0, 0x0C00},
+ {TOK_WRITE, 0x70003EE2, 0x2806},
+ {TOK_WRITE, 0x70003EE4, 0xD3F0},
+ {TOK_WRITE, 0x70003EE6, 0x4965},
+ {TOK_WRITE, 0x70003EE8, 0x9809},
+ {TOK_WRITE, 0x70003EEA, 0x8208},
+ {TOK_WRITE, 0x70003EEC, 0x9808},
+ {TOK_WRITE, 0x70003EEE, 0x8028},
+ {TOK_WRITE, 0x70003EF0, 0x9807},
+ {TOK_WRITE, 0x70003EF2, 0x80E8},
+ {TOK_WRITE, 0x70003EF4, 0x1FE0},
+ {TOK_WRITE, 0x70003EF6, 0x38FD},
+ {TOK_WRITE, 0x70003EF8, 0xD13B},
+ {TOK_WRITE, 0x70003EFA, 0x4D64},
+ {TOK_WRITE, 0x70003EFC, 0x89E8},
+ {TOK_WRITE, 0x70003EFE, 0x1FC1},
+ {TOK_WRITE, 0x70003F00, 0x39FF},
+ {TOK_WRITE, 0x70003F02, 0xD136},
+ {TOK_WRITE, 0x70003F04, 0x4C5F},
+ {TOK_WRITE, 0x70003F06, 0x8AE0},
+ {TOK_WRITE, 0x70003F08, 0xF000},
+ {TOK_WRITE, 0x70003F0A, 0xFA34},
+ {TOK_WRITE, 0x70003F0C, 0x0006},
+ {TOK_WRITE, 0x70003F0E, 0x8B20},
+ {TOK_WRITE, 0x70003F10, 0xF000},
+ {TOK_WRITE, 0x70003F12, 0xFA38},
+ {TOK_WRITE, 0x70003F14, 0x9000},
+ {TOK_WRITE, 0x70003F16, 0x6AA1},
+ {TOK_WRITE, 0x70003F18, 0x6878},
+ {TOK_WRITE, 0x70003F1A, 0x1809},
+ {TOK_WRITE, 0x70003F1C, 0x0200},
+ {TOK_WRITE, 0x70003F1E, 0xF000},
+ {TOK_WRITE, 0x70003F20, 0xFA0B},
+ {TOK_WRITE, 0x70003F22, 0x0400},
+ {TOK_WRITE, 0x70003F24, 0x0C00},
+ {TOK_WRITE, 0x70003F26, 0x0022},
+ {TOK_WRITE, 0x70003F28, 0x3246},
+ {TOK_WRITE, 0x70003F2A, 0x0011},
+ {TOK_WRITE, 0x70003F2C, 0x310A},
+ {TOK_WRITE, 0x70003F2E, 0x2305},
+ {TOK_WRITE, 0x70003F30, 0xF000},
+ {TOK_WRITE, 0x70003F32, 0xFA08},
+ {TOK_WRITE, 0x70003F34, 0x66E8},
+ {TOK_WRITE, 0x70003F36, 0x6B23},
+ {TOK_WRITE, 0x70003F38, 0x0002},
+ {TOK_WRITE, 0x70003F3A, 0x0031},
+ {TOK_WRITE, 0x70003F3C, 0x0018},
+ {TOK_WRITE, 0x70003F3E, 0xF000},
+ {TOK_WRITE, 0x70003F40, 0xFA29},
+ {TOK_WRITE, 0x70003F42, 0x466B},
+ {TOK_WRITE, 0x70003F44, 0x8518},
+ {TOK_WRITE, 0x70003F46, 0x6EEA},
+ {TOK_WRITE, 0x70003F48, 0x6B60},
+ {TOK_WRITE, 0x70003F4A, 0x9900},
+ {TOK_WRITE, 0x70003F4C, 0xF000},
+ {TOK_WRITE, 0x70003F4E, 0xFA22},
+ {TOK_WRITE, 0x70003F50, 0x466B},
+ {TOK_WRITE, 0x70003F52, 0x8558},
+ {TOK_WRITE, 0x70003F54, 0x0029},
+ {TOK_WRITE, 0x70003F56, 0x980A},
+ {TOK_WRITE, 0x70003F58, 0x3170},
+ {TOK_WRITE, 0x70003F5A, 0xF000},
+ {TOK_WRITE, 0x70003F5C, 0xFA23},
+ {TOK_WRITE, 0x70003F5E, 0x0028},
+ {TOK_WRITE, 0x70003F60, 0x3060},
+ {TOK_WRITE, 0x70003F62, 0x8A02},
+ {TOK_WRITE, 0x70003F64, 0x4946},
+ {TOK_WRITE, 0x70003F66, 0x3128},
+ {TOK_WRITE, 0x70003F68, 0x808A},
+ {TOK_WRITE, 0x70003F6A, 0x8A42},
+ {TOK_WRITE, 0x70003F6C, 0x80CA},
+ {TOK_WRITE, 0x70003F6E, 0x8A80},
+ {TOK_WRITE, 0x70003F70, 0x8108},
+ {TOK_WRITE, 0x70003F72, 0xB00B},
+ {TOK_WRITE, 0x70003F74, 0xBCF0},
+ {TOK_WRITE, 0x70003F76, 0xBC08},
+ {TOK_WRITE, 0x70003F78, 0x4718},
+ {TOK_WRITE, 0x70003F7A, 0xB570},
+ {TOK_WRITE, 0x70003F7C, 0x2400},
+ {TOK_WRITE, 0x70003F7E, 0x4D46},
+ {TOK_WRITE, 0x70003F80, 0x4846},
+ {TOK_WRITE, 0x70003F82, 0x8881},
+ {TOK_WRITE, 0x70003F84, 0x4846},
+ {TOK_WRITE, 0x70003F86, 0x8041},
+ {TOK_WRITE, 0x70003F88, 0x2101},
+ {TOK_WRITE, 0x70003F8A, 0x8001},
+ {TOK_WRITE, 0x70003F8C, 0xF000},
+ {TOK_WRITE, 0x70003F8E, 0xFA12},
+ {TOK_WRITE, 0x70003F90, 0x4842},
+ {TOK_WRITE, 0x70003F92, 0x3820},
+ {TOK_WRITE, 0x70003F94, 0x8BC0},
+ {TOK_WRITE, 0x70003F96, 0xF000},
+ {TOK_WRITE, 0x70003F98, 0xFA15},
+ {TOK_WRITE, 0x70003F9A, 0x4B42},
+ {TOK_WRITE, 0x70003F9C, 0x220D},
+ {TOK_WRITE, 0x70003F9E, 0x0712},
+ {TOK_WRITE, 0x70003FA0, 0x18A8},
+ {TOK_WRITE, 0x70003FA2, 0x8806},
+ {TOK_WRITE, 0x70003FA4, 0x00E1},
+ {TOK_WRITE, 0x70003FA6, 0x18C9},
+ {TOK_WRITE, 0x70003FA8, 0x81CE},
+ {TOK_WRITE, 0x70003FAA, 0x8846},
+ {TOK_WRITE, 0x70003FAC, 0x818E},
+ {TOK_WRITE, 0x70003FAE, 0x8886},
+ {TOK_WRITE, 0x70003FB0, 0x824E},
+ {TOK_WRITE, 0x70003FB2, 0x88C0},
+ {TOK_WRITE, 0x70003FB4, 0x8208},
+ {TOK_WRITE, 0x70003FB6, 0x3508},
+ {TOK_WRITE, 0x70003FB8, 0x042D},
+ {TOK_WRITE, 0x70003FBA, 0x0C2D},
+ {TOK_WRITE, 0x70003FBC, 0x1C64},
+ {TOK_WRITE, 0x70003FBE, 0x0424},
+ {TOK_WRITE, 0x70003FC0, 0x0C24},
+ {TOK_WRITE, 0x70003FC2, 0x2C07},
+ {TOK_WRITE, 0x70003FC4, 0xD3EC},
+ {TOK_WRITE, 0x70003FC6, 0xE658},
+ {TOK_WRITE, 0x70003FC8, 0xB510},
+ {TOK_WRITE, 0x70003FCA, 0x4834},
+ {TOK_WRITE, 0x70003FCC, 0x4C34},
+ {TOK_WRITE, 0x70003FCE, 0x88C0},
+ {TOK_WRITE, 0x70003FD0, 0x8060},
+ {TOK_WRITE, 0x70003FD2, 0x2001},
+ {TOK_WRITE, 0x70003FD4, 0x8020},
+ {TOK_WRITE, 0x70003FD6, 0x4831},
+ {TOK_WRITE, 0x70003FD8, 0x3820},
+ {TOK_WRITE, 0x70003FDA, 0x8BC0},
+ {TOK_WRITE, 0x70003FDC, 0xF000},
+ {TOK_WRITE, 0x70003FDE, 0xF9F2},
+ {TOK_WRITE, 0x70003FE0, 0x88E0},
+ {TOK_WRITE, 0x70003FE2, 0x4A31},
+ {TOK_WRITE, 0x70003FE4, 0x2800},
+ {TOK_WRITE, 0x70003FE6, 0xD003},
+ {TOK_WRITE, 0x70003FE8, 0x4930},
+ {TOK_WRITE, 0x70003FEA, 0x8849},
+ {TOK_WRITE, 0x70003FEC, 0x2900},
+ {TOK_WRITE, 0x70003FEE, 0xD009},
+ {TOK_WRITE, 0x70003FF0, 0x2001},
+ {TOK_WRITE, 0x70003FF2, 0x03C0},
+ {TOK_WRITE, 0x70003FF4, 0x8050},
+ {TOK_WRITE, 0x70003FF6, 0x80D0},
+ {TOK_WRITE, 0x70003FF8, 0x2000},
+ {TOK_WRITE, 0x70003FFA, 0x8090},
+ {TOK_WRITE, 0x70003FFC, 0x8110},
+ {TOK_WRITE, 0x70003FFE, 0xBC10},
+ {TOK_WRITE, 0x70004000, 0xBC08},
+ {TOK_WRITE, 0x70004002, 0x4718},
+ {TOK_WRITE, 0x70004004, 0x8050},
+ {TOK_WRITE, 0x70004006, 0x8920},
+ {TOK_WRITE, 0x70004008, 0x80D0},
+ {TOK_WRITE, 0x7000400A, 0x8960},
+ {TOK_WRITE, 0x7000400C, 0x0400},
+ {TOK_WRITE, 0x7000400E, 0x1400},
+ {TOK_WRITE, 0x70004010, 0x8090},
+ {TOK_WRITE, 0x70004012, 0x89A1},
+ {TOK_WRITE, 0x70004014, 0x0409},
+ {TOK_WRITE, 0x70004016, 0x1409},
+ {TOK_WRITE, 0x70004018, 0x8111},
+ {TOK_WRITE, 0x7000401A, 0x89E3},
+ {TOK_WRITE, 0x7000401C, 0x8A24},
+ {TOK_WRITE, 0x7000401E, 0x2B00},
+ {TOK_WRITE, 0x70004020, 0xD104},
+ {TOK_WRITE, 0x70004022, 0x17C3},
+ {TOK_WRITE, 0x70004024, 0x0F5B},
+ {TOK_WRITE, 0x70004026, 0x1818},
+ {TOK_WRITE, 0x70004028, 0x10C0},
+ {TOK_WRITE, 0x7000402A, 0x8090},
+ {TOK_WRITE, 0x7000402C, 0x2C00},
+ {TOK_WRITE, 0x7000402E, 0xD1E6},
+ {TOK_WRITE, 0x70004030, 0x17C8},
+ {TOK_WRITE, 0x70004032, 0x0F40},
+ {TOK_WRITE, 0x70004034, 0x1840},
+ {TOK_WRITE, 0x70004036, 0x10C0},
+ {TOK_WRITE, 0x70004038, 0x8110},
+ {TOK_WRITE, 0x7000403A, 0xE7E0},
+ {TOK_WRITE, 0x7000403C, 0xB510},
+ {TOK_WRITE, 0x7000403E, 0x000C},
+ {TOK_WRITE, 0x70004040, 0x4919},
+ {TOK_WRITE, 0x70004042, 0x2204},
+ {TOK_WRITE, 0x70004044, 0x6820},
+ {TOK_WRITE, 0x70004046, 0x5E8A},
+ {TOK_WRITE, 0x70004048, 0x0140},
+ {TOK_WRITE, 0x7000404A, 0x1A80},
+ {TOK_WRITE, 0x7000404C, 0x0280},
+ {TOK_WRITE, 0x7000404E, 0x8849},
+ {TOK_WRITE, 0x70004050, 0xF000},
+ {TOK_WRITE, 0x70004052, 0xF9C0},
+ {TOK_WRITE, 0x70004054, 0x6020},
+ {TOK_WRITE, 0x70004056, 0xE7D2},
+ {TOK_WRITE, 0x70004058, 0x38D4},
+ {TOK_WRITE, 0x7000405A, 0x7000},
+ {TOK_WRITE, 0x7000405C, 0x17D0},
+ {TOK_WRITE, 0x7000405E, 0x7000},
+ {TOK_WRITE, 0x70004060, 0x5000},
+ {TOK_WRITE, 0x70004062, 0xD000},
+ {TOK_WRITE, 0x70004064, 0x1100},
+ {TOK_WRITE, 0x70004066, 0xD000},
+ {TOK_WRITE, 0x70004068, 0x171A},
+ {TOK_WRITE, 0x7000406A, 0x7000},
+ {TOK_WRITE, 0x7000406C, 0x4780},
+ {TOK_WRITE, 0x7000406E, 0x7000},
+ {TOK_WRITE, 0x70004070, 0x2FCA},
+ {TOK_WRITE, 0x70004072, 0x7000},
+ {TOK_WRITE, 0x70004074, 0x2FC5},
+ {TOK_WRITE, 0x70004076, 0x7000},
+ {TOK_WRITE, 0x70004078, 0x2FC6},
+ {TOK_WRITE, 0x7000407A, 0x7000},
+ {TOK_WRITE, 0x7000407C, 0x2ED8},
+ {TOK_WRITE, 0x7000407E, 0x7000},
+ {TOK_WRITE, 0x70004080, 0x2BD0},
+ {TOK_WRITE, 0x70004082, 0x7000},
+ {TOK_WRITE, 0x70004084, 0x17E0},
+ {TOK_WRITE, 0x70004086, 0x7000},
+ {TOK_WRITE, 0x70004088, 0x2DE8},
+ {TOK_WRITE, 0x7000408A, 0x7000},
+ {TOK_WRITE, 0x7000408C, 0x37E0},
+ {TOK_WRITE, 0x7000408E, 0x7000},
+ {TOK_WRITE, 0x70004090, 0x210C},
+ {TOK_WRITE, 0x70004092, 0x7000},
+ {TOK_WRITE, 0x70004094, 0x1484},
+ {TOK_WRITE, 0x70004096, 0x7000},
+ {TOK_WRITE, 0x70004098, 0xA006},
+ {TOK_WRITE, 0x7000409A, 0x0000},
+ {TOK_WRITE, 0x7000409C, 0x0724},
+ {TOK_WRITE, 0x7000409E, 0x7000},
+ {TOK_WRITE, 0x700040A0, 0xA000},
+ {TOK_WRITE, 0x700040A2, 0xD000},
+ {TOK_WRITE, 0x700040A4, 0x2270},
+ {TOK_WRITE, 0x700040A6, 0x7000},
+ {TOK_WRITE, 0x700040A8, 0x2558},
+ {TOK_WRITE, 0x700040AA, 0x7000},
+ {TOK_WRITE, 0x700040AC, 0x146C},
+ {TOK_WRITE, 0x700040AE, 0x7000},
+ {TOK_WRITE, 0x700040B0, 0xB510},
+ {TOK_WRITE, 0x700040B2, 0x000C},
+ {TOK_WRITE, 0x700040B4, 0x4979},
+ {TOK_WRITE, 0x700040B6, 0x2208},
+ {TOK_WRITE, 0x700040B8, 0x6820},
+ {TOK_WRITE, 0x700040BA, 0x5E8A},
+ {TOK_WRITE, 0x700040BC, 0x0140},
+ {TOK_WRITE, 0x700040BE, 0x1A80},
+ {TOK_WRITE, 0x700040C0, 0x0280},
+ {TOK_WRITE, 0x700040C2, 0x88C9},
+ {TOK_WRITE, 0x700040C4, 0xF000},
+ {TOK_WRITE, 0x700040C6, 0xF986},
+ {TOK_WRITE, 0x700040C8, 0x6020},
+ {TOK_WRITE, 0x700040CA, 0xE798},
+ {TOK_WRITE, 0x700040CC, 0xB5FE},
+ {TOK_WRITE, 0x700040CE, 0x000C},
+ {TOK_WRITE, 0x700040D0, 0x6825},
+ {TOK_WRITE, 0x700040D2, 0x6866},
+ {TOK_WRITE, 0x700040D4, 0x68A0},
+ {TOK_WRITE, 0x700040D6, 0x9001},
+ {TOK_WRITE, 0x700040D8, 0x68E7},
+ {TOK_WRITE, 0x700040DA, 0x1BA8},
+ {TOK_WRITE, 0x700040DC, 0x42B5},
+ {TOK_WRITE, 0x700040DE, 0xDA00},
+ {TOK_WRITE, 0x700040E0, 0x1B70},
+ {TOK_WRITE, 0x700040E2, 0x9000},
+ {TOK_WRITE, 0x700040E4, 0x496D},
+ {TOK_WRITE, 0x700040E6, 0x486E},
+ {TOK_WRITE, 0x700040E8, 0x884A},
+ {TOK_WRITE, 0x700040EA, 0x8843},
+ {TOK_WRITE, 0x700040EC, 0x435A},
+ {TOK_WRITE, 0x700040EE, 0x2304},
+ {TOK_WRITE, 0x700040F0, 0x5ECB},
+ {TOK_WRITE, 0x700040F2, 0x0A92},
+ {TOK_WRITE, 0x700040F4, 0x18D2},
+ {TOK_WRITE, 0x700040F6, 0x02D2},
+ {TOK_WRITE, 0x700040F8, 0x0C12},
+ {TOK_WRITE, 0x700040FA, 0x88CB},
+ {TOK_WRITE, 0x700040FC, 0x8880},
+ {TOK_WRITE, 0x700040FE, 0x4343},
+ {TOK_WRITE, 0x70004100, 0x0A98},
+ {TOK_WRITE, 0x70004102, 0x2308},
+ {TOK_WRITE, 0x70004104, 0x5ECB},
+ {TOK_WRITE, 0x70004106, 0x18C0},
+ {TOK_WRITE, 0x70004108, 0x02C0},
+ {TOK_WRITE, 0x7000410A, 0x0C00},
+ {TOK_WRITE, 0x7000410C, 0x0411},
+ {TOK_WRITE, 0x7000410E, 0x0400},
+ {TOK_WRITE, 0x70004110, 0x1409},
+ {TOK_WRITE, 0x70004112, 0x1400},
+ {TOK_WRITE, 0x70004114, 0x1A08},
+ {TOK_WRITE, 0x70004116, 0x4962},
+ {TOK_WRITE, 0x70004118, 0x39E0},
+ {TOK_WRITE, 0x7000411A, 0x6148},
+ {TOK_WRITE, 0x7000411C, 0x9801},
+ {TOK_WRITE, 0x7000411E, 0x3040},
+ {TOK_WRITE, 0x70004120, 0x7880},
+ {TOK_WRITE, 0x70004122, 0x2800},
+ {TOK_WRITE, 0x70004124, 0xD103},
+ {TOK_WRITE, 0x70004126, 0x9801},
+ {TOK_WRITE, 0x70004128, 0x0029},
+ {TOK_WRITE, 0x7000412A, 0xF000},
+ {TOK_WRITE, 0x7000412C, 0xF959},
+ {TOK_WRITE, 0x7000412E, 0x8839},
+ {TOK_WRITE, 0x70004130, 0x9800},
+ {TOK_WRITE, 0x70004132, 0x4281},
+ {TOK_WRITE, 0x70004134, 0xD814},
+ {TOK_WRITE, 0x70004136, 0x8879},
+ {TOK_WRITE, 0x70004138, 0x9800},
+ {TOK_WRITE, 0x7000413A, 0x4281},
+ {TOK_WRITE, 0x7000413C, 0xD20C},
+ {TOK_WRITE, 0x7000413E, 0x9801},
+ {TOK_WRITE, 0x70004140, 0x0029},
+ {TOK_WRITE, 0x70004142, 0xF000},
+ {TOK_WRITE, 0x70004144, 0xF955},
+ {TOK_WRITE, 0x70004146, 0x9801},
+ {TOK_WRITE, 0x70004148, 0x0029},
+ {TOK_WRITE, 0x7000414A, 0xF000},
+ {TOK_WRITE, 0x7000414C, 0xF951},
+ {TOK_WRITE, 0x7000414E, 0x9801},
+ {TOK_WRITE, 0x70004150, 0x0029},
+ {TOK_WRITE, 0x70004152, 0xF000},
+ {TOK_WRITE, 0x70004154, 0xF94D},
+ {TOK_WRITE, 0x70004156, 0xE003},
+ {TOK_WRITE, 0x70004158, 0x9801},
+ {TOK_WRITE, 0x7000415A, 0x0029},
+ {TOK_WRITE, 0x7000415C, 0xF000},
+ {TOK_WRITE, 0x7000415E, 0xF948},
+ {TOK_WRITE, 0x70004160, 0x9801},
+ {TOK_WRITE, 0x70004162, 0x0032},
+ {TOK_WRITE, 0x70004164, 0x0039},
+ {TOK_WRITE, 0x70004166, 0xF000},
+ {TOK_WRITE, 0x70004168, 0xF94B},
+ {TOK_WRITE, 0x7000416A, 0x6020},
+ {TOK_WRITE, 0x7000416C, 0xE5D0},
+ {TOK_WRITE, 0x7000416E, 0xB57C},
+ {TOK_WRITE, 0x70004170, 0x484C},
+ {TOK_WRITE, 0x70004172, 0xA901},
+ {TOK_WRITE, 0x70004174, 0x0004},
+ {TOK_WRITE, 0x70004176, 0xF000},
+ {TOK_WRITE, 0x70004178, 0xF8CF},
+ {TOK_WRITE, 0x7000417A, 0x466B},
+ {TOK_WRITE, 0x7000417C, 0x88D9},
+ {TOK_WRITE, 0x7000417E, 0x8898},
+ {TOK_WRITE, 0x70004180, 0x4B47},
+ {TOK_WRITE, 0x70004182, 0x3346},
+ {TOK_WRITE, 0x70004184, 0x1E9A},
+ {TOK_WRITE, 0x70004186, 0xF000},
+ {TOK_WRITE, 0x70004188, 0xF943},
+ {TOK_WRITE, 0x7000418A, 0x4846},
+ {TOK_WRITE, 0x7000418C, 0x4944},
+ {TOK_WRITE, 0x7000418E, 0x3812},
+ {TOK_WRITE, 0x70004190, 0x3140},
+ {TOK_WRITE, 0x70004192, 0x8A42},
+ {TOK_WRITE, 0x70004194, 0x888B},
+ {TOK_WRITE, 0x70004196, 0x18D2},
+ {TOK_WRITE, 0x70004198, 0x8242},
+ {TOK_WRITE, 0x7000419A, 0x8AC2},
+ {TOK_WRITE, 0x7000419C, 0x88C9},
+ {TOK_WRITE, 0x7000419E, 0x1851},
+ {TOK_WRITE, 0x700041A0, 0x82C1},
+ {TOK_WRITE, 0x700041A2, 0x0020},
+ {TOK_WRITE, 0x700041A4, 0x4669},
+ {TOK_WRITE, 0x700041A6, 0xF000},
+ {TOK_WRITE, 0x700041A8, 0xF8B7},
+ {TOK_WRITE, 0x700041AA, 0x483F},
+ {TOK_WRITE, 0x700041AC, 0x214D},
+ {TOK_WRITE, 0x700041AE, 0x8301},
+ {TOK_WRITE, 0x700041B0, 0x2196},
+ {TOK_WRITE, 0x700041B2, 0x8381},
+ {TOK_WRITE, 0x700041B4, 0x211D},
+ {TOK_WRITE, 0x700041B6, 0x3020},
+ {TOK_WRITE, 0x700041B8, 0x8001},
+ {TOK_WRITE, 0x700041BA, 0xF000},
+ {TOK_WRITE, 0x700041BC, 0xF931},
+ {TOK_WRITE, 0x700041BE, 0xF000},
+ {TOK_WRITE, 0x700041C0, 0xF937},
+ {TOK_WRITE, 0x700041C2, 0x483A},
+ {TOK_WRITE, 0x700041C4, 0x4C3A},
+ {TOK_WRITE, 0x700041C6, 0x6E00},
+ {TOK_WRITE, 0x700041C8, 0x60E0},
+ {TOK_WRITE, 0x700041CA, 0x466B},
+ {TOK_WRITE, 0x700041CC, 0x8818},
+ {TOK_WRITE, 0x700041CE, 0x8859},
+ {TOK_WRITE, 0x700041D0, 0x0025},
+ {TOK_WRITE, 0x700041D2, 0x1A40},
+ {TOK_WRITE, 0x700041D4, 0x3540},
+ {TOK_WRITE, 0x700041D6, 0x61A8},
+ {TOK_WRITE, 0x700041D8, 0x4831},
+ {TOK_WRITE, 0x700041DA, 0x9900},
+ {TOK_WRITE, 0x700041DC, 0x3060},
+ {TOK_WRITE, 0x700041DE, 0xF000},
+ {TOK_WRITE, 0x700041E0, 0xF92F},
+ {TOK_WRITE, 0x700041E2, 0x466B},
+ {TOK_WRITE, 0x700041E4, 0x8819},
+ {TOK_WRITE, 0x700041E6, 0x1DE0},
+ {TOK_WRITE, 0x700041E8, 0x30F9},
+ {TOK_WRITE, 0x700041EA, 0x8741},
+ {TOK_WRITE, 0x700041EC, 0x8859},
+ {TOK_WRITE, 0x700041EE, 0x8781},
+ {TOK_WRITE, 0x700041F0, 0x2000},
+ {TOK_WRITE, 0x700041F2, 0x71A0},
+ {TOK_WRITE, 0x700041F4, 0x74A8},
+ {TOK_WRITE, 0x700041F6, 0xBC7C},
+ {TOK_WRITE, 0x700041F8, 0xBC08},
+ {TOK_WRITE, 0x700041FA, 0x4718},
+ {TOK_WRITE, 0x700041FC, 0xB5F8},
+ {TOK_WRITE, 0x700041FE, 0x0005},
+ {TOK_WRITE, 0x70004200, 0x6808},
+ {TOK_WRITE, 0x70004202, 0x0400},
+ {TOK_WRITE, 0x70004204, 0x0C00},
+ {TOK_WRITE, 0x70004206, 0x684A},
+ {TOK_WRITE, 0x70004208, 0x0412},
+ {TOK_WRITE, 0x7000420A, 0x0C12},
+ {TOK_WRITE, 0x7000420C, 0x688E},
+ {TOK_WRITE, 0x7000420E, 0x68CC},
+ {TOK_WRITE, 0x70004210, 0x4922},
+ {TOK_WRITE, 0x70004212, 0x884B},
+ {TOK_WRITE, 0x70004214, 0x4343},
+ {TOK_WRITE, 0x70004216, 0x0A98},
+ {TOK_WRITE, 0x70004218, 0x2304},
+ {TOK_WRITE, 0x7000421A, 0x5ECB},
+ {TOK_WRITE, 0x7000421C, 0x18C0},
+ {TOK_WRITE, 0x7000421E, 0x02C0},
+ {TOK_WRITE, 0x70004220, 0x0C00},
+ {TOK_WRITE, 0x70004222, 0x88CB},
+ {TOK_WRITE, 0x70004224, 0x4353},
+ {TOK_WRITE, 0x70004226, 0x0A9A},
+ {TOK_WRITE, 0x70004228, 0x2308},
+ {TOK_WRITE, 0x7000422A, 0x5ECB},
+ {TOK_WRITE, 0x7000422C, 0x18D1},
+ {TOK_WRITE, 0x7000422E, 0x02C9},
+ {TOK_WRITE, 0x70004230, 0x0C09},
+ {TOK_WRITE, 0x70004232, 0x2701},
+ {TOK_WRITE, 0x70004234, 0x003A},
+ {TOK_WRITE, 0x70004236, 0x40AA},
+ {TOK_WRITE, 0x70004238, 0x9200},
+ {TOK_WRITE, 0x7000423A, 0x002A},
+ {TOK_WRITE, 0x7000423C, 0x3A10},
+ {TOK_WRITE, 0x7000423E, 0x4097},
+ {TOK_WRITE, 0x70004240, 0x2D10},
+ {TOK_WRITE, 0x70004242, 0xDA06},
+ {TOK_WRITE, 0x70004244, 0x4A1B},
+ {TOK_WRITE, 0x70004246, 0x9B00},
+ {TOK_WRITE, 0x70004248, 0x8812},
+ {TOK_WRITE, 0x7000424A, 0x439A},
+ {TOK_WRITE, 0x7000424C, 0x4B19},
+ {TOK_WRITE, 0x7000424E, 0x801A},
+ {TOK_WRITE, 0x70004250, 0xE003},
+ {TOK_WRITE, 0x70004252, 0x4B18},
+ {TOK_WRITE, 0x70004254, 0x885A},
+ {TOK_WRITE, 0x70004256, 0x43BA},
+ {TOK_WRITE, 0x70004258, 0x805A},
+ {TOK_WRITE, 0x7000425A, 0x0023},
+ {TOK_WRITE, 0x7000425C, 0x0032},
+ {TOK_WRITE, 0x7000425E, 0xF000},
+ {TOK_WRITE, 0x70004260, 0xF8D7},
+ {TOK_WRITE, 0x70004262, 0x2D10},
+ {TOK_WRITE, 0x70004264, 0xDA05},
+ {TOK_WRITE, 0x70004266, 0x4913},
+ {TOK_WRITE, 0x70004268, 0x9A00},
+ {TOK_WRITE, 0x7000426A, 0x8808},
+ {TOK_WRITE, 0x7000426C, 0x4310},
+ {TOK_WRITE, 0x7000426E, 0x8008},
+ {TOK_WRITE, 0x70004270, 0xE003},
+ {TOK_WRITE, 0x70004272, 0x4810},
+ {TOK_WRITE, 0x70004274, 0x8841},
+ {TOK_WRITE, 0x70004276, 0x4339},
+ {TOK_WRITE, 0x70004278, 0x8041},
+ {TOK_WRITE, 0x7000427A, 0x4D0D},
+ {TOK_WRITE, 0x7000427C, 0x2000},
+ {TOK_WRITE, 0x7000427E, 0x3580},
+ {TOK_WRITE, 0x70004280, 0x88AA},
+ {TOK_WRITE, 0x70004282, 0x5E30},
+ {TOK_WRITE, 0x70004284, 0x2100},
+ {TOK_WRITE, 0x70004286, 0xF000},
+ {TOK_WRITE, 0x70004288, 0xF8E3},
+ {TOK_WRITE, 0x7000428A, 0x8030},
+ {TOK_WRITE, 0x7000428C, 0x2000},
+ {TOK_WRITE, 0x7000428E, 0x88AA},
+ {TOK_WRITE, 0x70004290, 0x5E20},
+ {TOK_WRITE, 0x70004292, 0x2100},
+ {TOK_WRITE, 0x70004294, 0xF000},
+ {TOK_WRITE, 0x70004296, 0xF8DC},
+ {TOK_WRITE, 0x70004298, 0x8020},
+ {TOK_WRITE, 0x7000429A, 0xE587},
+ {TOK_WRITE, 0x7000429C, 0x2558},
+ {TOK_WRITE, 0x7000429E, 0x7000},
+ {TOK_WRITE, 0x700042A0, 0x2AB8},
+ {TOK_WRITE, 0x700042A2, 0x7000},
+ {TOK_WRITE, 0x700042A4, 0x145E},
+ {TOK_WRITE, 0x700042A6, 0x7000},
+ {TOK_WRITE, 0x700042A8, 0x2698},
+ {TOK_WRITE, 0x700042AA, 0x7000},
+ {TOK_WRITE, 0x700042AC, 0x2BB8},
+ {TOK_WRITE, 0x700042AE, 0x7000},
+ {TOK_WRITE, 0x700042B0, 0x2998},
+ {TOK_WRITE, 0x700042B2, 0x7000},
+ {TOK_WRITE, 0x700042B4, 0x1100},
+ {TOK_WRITE, 0x700042B6, 0xD000},
+ {TOK_WRITE, 0x700042B8, 0x4778},
+ {TOK_WRITE, 0x700042BA, 0x46C0},
+ {TOK_WRITE, 0x700042BC, 0xC000},
+ {TOK_WRITE, 0x700042BE, 0xE59F},
+ {TOK_WRITE, 0x700042C0, 0xFF1C},
+ {TOK_WRITE, 0x700042C2, 0xE12F},
+ {TOK_WRITE, 0x700042C4, 0x1789},
+ {TOK_WRITE, 0x700042C6, 0x0001},
+ {TOK_WRITE, 0x700042C8, 0x4778},
+ {TOK_WRITE, 0x700042CA, 0x46C0},
+ {TOK_WRITE, 0x700042CC, 0xC000},
+ {TOK_WRITE, 0x700042CE, 0xE59F},
+ {TOK_WRITE, 0x700042D0, 0xFF1C},
+ {TOK_WRITE, 0x700042D2, 0xE12F},
+ {TOK_WRITE, 0x700042D4, 0x16F1},
+ {TOK_WRITE, 0x700042D6, 0x0001},
+ {TOK_WRITE, 0x700042D8, 0x4778},
+ {TOK_WRITE, 0x700042DA, 0x46C0},
+ {TOK_WRITE, 0x700042DC, 0xC000},
+ {TOK_WRITE, 0x700042DE, 0xE59F},
+ {TOK_WRITE, 0x700042E0, 0xFF1C},
+ {TOK_WRITE, 0x700042E2, 0xE12F},
+ {TOK_WRITE, 0x700042E4, 0xC3B1},
+ {TOK_WRITE, 0x700042E6, 0x0000},
+ {TOK_WRITE, 0x700042E8, 0x4778},
+ {TOK_WRITE, 0x700042EA, 0x46C0},
+ {TOK_WRITE, 0x700042EC, 0xC000},
+ {TOK_WRITE, 0x700042EE, 0xE59F},
+ {TOK_WRITE, 0x700042F0, 0xFF1C},
+ {TOK_WRITE, 0x700042F2, 0xE12F},
+ {TOK_WRITE, 0x700042F4, 0xC36D},
+ {TOK_WRITE, 0x700042F6, 0x0000},
+ {TOK_WRITE, 0x700042F8, 0x4778},
+ {TOK_WRITE, 0x700042FA, 0x46C0},
+ {TOK_WRITE, 0x700042FC, 0xC000},
+ {TOK_WRITE, 0x700042FE, 0xE59F},
+ {TOK_WRITE, 0x70004300, 0xFF1C},
+ {TOK_WRITE, 0x70004302, 0xE12F},
+ {TOK_WRITE, 0x70004304, 0xF6D7},
+ {TOK_WRITE, 0x70004306, 0x0000},
+ {TOK_WRITE, 0x70004308, 0x4778},
+ {TOK_WRITE, 0x7000430A, 0x46C0},
+ {TOK_WRITE, 0x7000430C, 0xC000},
+ {TOK_WRITE, 0x7000430E, 0xE59F},
+ {TOK_WRITE, 0x70004310, 0xFF1C},
+ {TOK_WRITE, 0x70004312, 0xE12F},
+ {TOK_WRITE, 0x70004314, 0xB49D},
+ {TOK_WRITE, 0x70004316, 0x0000},
+ {TOK_WRITE, 0x70004318, 0x4778},
+ {TOK_WRITE, 0x7000431A, 0x46C0},
+ {TOK_WRITE, 0x7000431C, 0xC000},
+ {TOK_WRITE, 0x7000431E, 0xE59F},
+ {TOK_WRITE, 0x70004320, 0xFF1C},
+ {TOK_WRITE, 0x70004322, 0xE12F},
+ {TOK_WRITE, 0x70004324, 0x7EDF},
+ {TOK_WRITE, 0x70004326, 0x0000},
+ {TOK_WRITE, 0x70004328, 0x4778},
+ {TOK_WRITE, 0x7000432A, 0x46C0},
+ {TOK_WRITE, 0x7000432C, 0xC000},
+ {TOK_WRITE, 0x7000432E, 0xE59F},
+ {TOK_WRITE, 0x70004330, 0xFF1C},
+ {TOK_WRITE, 0x70004332, 0xE12F},
+ {TOK_WRITE, 0x70004334, 0x448D},
+ {TOK_WRITE, 0x70004336, 0x0000},
+ {TOK_WRITE, 0x70004338, 0x4778},
+ {TOK_WRITE, 0x7000433A, 0x46C0},
+ {TOK_WRITE, 0x7000433C, 0xF004},
+ {TOK_WRITE, 0x7000433E, 0xE51F},
+ {TOK_WRITE, 0x70004340, 0x29EC},
+ {TOK_WRITE, 0x70004342, 0x0001},
+ {TOK_WRITE, 0x70004344, 0x4778},
+ {TOK_WRITE, 0x70004346, 0x46C0},
+ {TOK_WRITE, 0x70004348, 0xC000},
+ {TOK_WRITE, 0x7000434A, 0xE59F},
+ {TOK_WRITE, 0x7000434C, 0xFF1C},
+ {TOK_WRITE, 0x7000434E, 0xE12F},
+ {TOK_WRITE, 0x70004350, 0x2EF1},
+ {TOK_WRITE, 0x70004352, 0x0000},
+ {TOK_WRITE, 0x70004354, 0x4778},
+ {TOK_WRITE, 0x70004356, 0x46C0},
+ {TOK_WRITE, 0x70004358, 0xC000},
+ {TOK_WRITE, 0x7000435A, 0xE59F},
+ {TOK_WRITE, 0x7000435C, 0xFF1C},
+ {TOK_WRITE, 0x7000435E, 0xE12F},
+ {TOK_WRITE, 0x70004360, 0xEE03},
+ {TOK_WRITE, 0x70004362, 0x0000},
+ {TOK_WRITE, 0x70004364, 0x4778},
+ {TOK_WRITE, 0x70004366, 0x46C0},
+ {TOK_WRITE, 0x70004368, 0xC000},
+ {TOK_WRITE, 0x7000436A, 0xE59F},
+ {TOK_WRITE, 0x7000436C, 0xFF1C},
+ {TOK_WRITE, 0x7000436E, 0xE12F},
+ {TOK_WRITE, 0x70004370, 0xA58B},
+ {TOK_WRITE, 0x70004372, 0x0000},
+ {TOK_WRITE, 0x70004374, 0x4778},
+ {TOK_WRITE, 0x70004376, 0x46C0},
+ {TOK_WRITE, 0x70004378, 0xC000},
+ {TOK_WRITE, 0x7000437A, 0xE59F},
+ {TOK_WRITE, 0x7000437C, 0xFF1C},
+ {TOK_WRITE, 0x7000437E, 0xE12F},
+ {TOK_WRITE, 0x70004380, 0x7C49},
+ {TOK_WRITE, 0x70004382, 0x0000},
+ {TOK_WRITE, 0x70004384, 0x4778},
+ {TOK_WRITE, 0x70004386, 0x46C0},
+ {TOK_WRITE, 0x70004388, 0xC000},
+ {TOK_WRITE, 0x7000438A, 0xE59F},
+ {TOK_WRITE, 0x7000438C, 0xFF1C},
+ {TOK_WRITE, 0x7000438E, 0xE12F},
+ {TOK_WRITE, 0x70004390, 0x7C63},
+ {TOK_WRITE, 0x70004392, 0x0000},
+ {TOK_WRITE, 0x70004394, 0x4778},
+ {TOK_WRITE, 0x70004396, 0x46C0},
+ {TOK_WRITE, 0x70004398, 0xC000},
+ {TOK_WRITE, 0x7000439A, 0xE59F},
+ {TOK_WRITE, 0x7000439C, 0xFF1C},
+ {TOK_WRITE, 0x7000439E, 0xE12F},
+ {TOK_WRITE, 0x700043A0, 0x2DB7},
+ {TOK_WRITE, 0x700043A2, 0x0000},
+ {TOK_WRITE, 0x700043A4, 0x4778},
+ {TOK_WRITE, 0x700043A6, 0x46C0},
+ {TOK_WRITE, 0x700043A8, 0xC000},
+ {TOK_WRITE, 0x700043AA, 0xE59F},
+ {TOK_WRITE, 0x700043AC, 0xFF1C},
+ {TOK_WRITE, 0x700043AE, 0xE12F},
+ {TOK_WRITE, 0x700043B0, 0xEB3D},
+ {TOK_WRITE, 0x700043B2, 0x0000},
+ {TOK_WRITE, 0x700043B4, 0x4778},
+ {TOK_WRITE, 0x700043B6, 0x46C0},
+ {TOK_WRITE, 0x700043B8, 0xC000},
+ {TOK_WRITE, 0x700043BA, 0xE59F},
+ {TOK_WRITE, 0x700043BC, 0xFF1C},
+ {TOK_WRITE, 0x700043BE, 0xE12F},
+ {TOK_WRITE, 0x700043C0, 0xF061},
+ {TOK_WRITE, 0x700043C2, 0x0000},
+ {TOK_WRITE, 0x700043C4, 0x4778},
+ {TOK_WRITE, 0x700043C6, 0x46C0},
+ {TOK_WRITE, 0x700043C8, 0xC000},
+ {TOK_WRITE, 0x700043CA, 0xE59F},
+ {TOK_WRITE, 0x700043CC, 0xFF1C},
+ {TOK_WRITE, 0x700043CE, 0xE12F},
+ {TOK_WRITE, 0x700043D0, 0xF0EF},
+ {TOK_WRITE, 0x700043D2, 0x0000},
+ {TOK_WRITE, 0x700043D4, 0x4778},
+ {TOK_WRITE, 0x700043D6, 0x46C0},
+ {TOK_WRITE, 0x700043D8, 0xF004},
+ {TOK_WRITE, 0x700043DA, 0xE51F},
+ {TOK_WRITE, 0x700043DC, 0x2824},
+ {TOK_WRITE, 0x700043DE, 0x0001},
+ {TOK_WRITE, 0x700043E0, 0x4778},
+ {TOK_WRITE, 0x700043E2, 0x46C0},
+ {TOK_WRITE, 0x700043E4, 0xC000},
+ {TOK_WRITE, 0x700043E6, 0xE59F},
+ {TOK_WRITE, 0x700043E8, 0xFF1C},
+ {TOK_WRITE, 0x700043EA, 0xE12F},
+ {TOK_WRITE, 0x700043EC, 0x8EDD},
+ {TOK_WRITE, 0x700043EE, 0x0000},
+ {TOK_WRITE, 0x700043F0, 0x4778},
+ {TOK_WRITE, 0x700043F2, 0x46C0},
+ {TOK_WRITE, 0x700043F4, 0xC000},
+ {TOK_WRITE, 0x700043F6, 0xE59F},
+ {TOK_WRITE, 0x700043F8, 0xFF1C},
+ {TOK_WRITE, 0x700043FA, 0xE12F},
+ {TOK_WRITE, 0x700043FC, 0x8DCB},
+ {TOK_WRITE, 0x700043FE, 0x0000},
+ {TOK_WRITE, 0x70004400, 0x4778},
+ {TOK_WRITE, 0x70004402, 0x46C0},
+ {TOK_WRITE, 0x70004404, 0xC000},
+ {TOK_WRITE, 0x70004406, 0xE59F},
+ {TOK_WRITE, 0x70004408, 0xFF1C},
+ {TOK_WRITE, 0x7000440A, 0xE12F},
+ {TOK_WRITE, 0x7000440C, 0x8E17},
+ {TOK_WRITE, 0x7000440E, 0x0000},
+ {TOK_WRITE, 0x70004410, 0x4778},
+ {TOK_WRITE, 0x70004412, 0x46C0},
+ {TOK_WRITE, 0x70004414, 0xC000},
+ {TOK_WRITE, 0x70004416, 0xE59F},
+ {TOK_WRITE, 0x70004418, 0xFF1C},
+ {TOK_WRITE, 0x7000441A, 0xE12F},
+ {TOK_WRITE, 0x7000441C, 0x98C5},
+ {TOK_WRITE, 0x7000441E, 0x0000},
+ {TOK_WRITE, 0x70004420, 0x4778},
+ {TOK_WRITE, 0x70004422, 0x46C0},
+ {TOK_WRITE, 0x70004424, 0xC000},
+ {TOK_WRITE, 0x70004426, 0xE59F},
+ {TOK_WRITE, 0x70004428, 0xFF1C},
+ {TOK_WRITE, 0x7000442A, 0xE12F},
+ {TOK_WRITE, 0x7000442C, 0x7C7D},
+ {TOK_WRITE, 0x7000442E, 0x0000},
+ {TOK_WRITE, 0x70004430, 0x4778},
+ {TOK_WRITE, 0x70004432, 0x46C0},
+ {TOK_WRITE, 0x70004434, 0xC000},
+ {TOK_WRITE, 0x70004436, 0xE59F},
+ {TOK_WRITE, 0x70004438, 0xFF1C},
+ {TOK_WRITE, 0x7000443A, 0xE12F},
+ {TOK_WRITE, 0x7000443C, 0x7E31},
+ {TOK_WRITE, 0x7000443E, 0x0000},
+ {TOK_WRITE, 0x70004440, 0x4778},
+ {TOK_WRITE, 0x70004442, 0x46C0},
+ {TOK_WRITE, 0x70004444, 0xC000},
+ {TOK_WRITE, 0x70004446, 0xE59F},
+ {TOK_WRITE, 0x70004448, 0xFF1C},
+ {TOK_WRITE, 0x7000444A, 0xE12F},
+ {TOK_WRITE, 0x7000444C, 0x7EAB},
+ {TOK_WRITE, 0x7000444E, 0x0000},
+ {TOK_WRITE, 0x70004450, 0x4778},
+ {TOK_WRITE, 0x70004452, 0x46C0},
+ {TOK_WRITE, 0x70004454, 0xC000},
+ {TOK_WRITE, 0x70004456, 0xE59F},
+ {TOK_WRITE, 0x70004458, 0xFF1C},
+ {TOK_WRITE, 0x7000445A, 0xE12F},
+ {TOK_WRITE, 0x7000445C, 0x7501},
+ {TOK_WRITE, 0x7000445E, 0x0000},
+ {TOK_WRITE, 0xD0001000, 0x0001},
+ {TOK_WRITE, 0x700001FC, 0x0001},
+ {TOK_WRITE, 0x700001FE, 0x0003},
+ {TOK_WRITE, 0x70000200, 0x0000},
+ {TOK_WRITE, 0x70000204, 0x0061},
+ {TOK_WRITE, 0x7000020C, 0x2F0C},
+ {TOK_WRITE, 0x7000020E, 0x0190},
+ {TOK_WRITE, 0x70000294, 0x0100},
+ {TOK_WRITE, 0x70000296, 0x00E3},
+ {TOK_WRITE, 0x70000298, 0x0200},
+ {TOK_WRITE, 0x7000029A, 0x0238},
+ {TOK_WRITE, 0x7000029C, 0x01C6},
+ {TOK_WRITE, 0x7000029E, 0x0166},
+ {TOK_WRITE, 0x700002A0, 0x0074},
+ {TOK_WRITE, 0x700002A2, 0x0132},
+ {TOK_WRITE, 0x700002A4, 0x0001},
+ {TOK_WRITE, 0x7000070E, 0x00FF},
+ {TOK_WRITE, 0x7000071E, 0x0001},
+ {TOK_WRITE, 0x7000163C, 0x0000},
+ {TOK_WRITE, 0x70001648, 0x9002},
+ {TOK_WRITE, 0x70001652, 0x0002},
+ {TOK_WRITE, 0x70001654, 0x0000},
+ {TOK_WRITE, 0x700015E0, 0x0801},
+ {TOK_WRITE, 0x7000164C, 0x0003},
+ {TOK_WRITE, 0x7000163E, 0x00E5},
+ {TOK_WRITE, 0x70001640, 0x00CC},
+ {TOK_WRITE, 0x700015D4, 0x0000},
+ {TOK_WRITE, 0x700015D6, 0xD000},
+ {TOK_WRITE, 0x7000169A, 0xFF95},
+ {TOK_WRITE, 0x7000166A, 0x0280},
+ {TOK_WRITE, 0x70001676, 0x03A0},
+ {TOK_WRITE, 0x70001678, 0x0320},
+ {TOK_WRITE, 0x700016BC, 0x0030},
+ {TOK_WRITE, 0x700016E0, 0x0060},
+ {TOK_WRITE, 0x700016D4, 0x0010},
+ {TOK_WRITE, 0x70001656, 0x0000},
+ {TOK_WRITE, 0x700015E6, 0x003C},
+ {TOK_WRITE, 0x700015E8, 0x0015},
+ {TOK_WRITE, 0x700015EA, 0x0032},
+ {TOK_WRITE, 0x700015EC, 0x0038},
+ {TOK_WRITE, 0x700015EE, 0x003E},
+ {TOK_WRITE, 0x700015F0, 0x0044},
+ {TOK_WRITE, 0x700015F2, 0x004A},
+ {TOK_WRITE, 0x700015F4, 0x0050},
+ {TOK_WRITE, 0x700015F6, 0x0056},
+ {TOK_WRITE, 0x700015F8, 0x005C},
+ {TOK_WRITE, 0x700015FA, 0x0062},
+ {TOK_WRITE, 0x700015FC, 0x0068},
+ {TOK_WRITE, 0x700015FE, 0x006E},
+ {TOK_WRITE, 0x70001600, 0x0074},
+ {TOK_WRITE, 0x70001602, 0x007A},
+ {TOK_WRITE, 0x70001604, 0x0080},
+ {TOK_WRITE, 0x70001606, 0x0086},
+ {TOK_WRITE, 0x70001608, 0x008C},
+ {TOK_WRITE, 0x7000160A, 0x0092},
+ {TOK_WRITE, 0x7000160C, 0x0098},
+ {TOK_WRITE, 0x7000160E, 0x009E},
+ {TOK_WRITE, 0x70001610, 0x00A4},
+ {TOK_WRITE, 0x70001612, 0x00AA},
+ {TOK_WRITE, 0x70001614, 0x00B0},
+ {TOK_WRITE, 0x70001722, 0x8000},
+ {TOK_WRITE, 0x70001724, 0x0006},
+ {TOK_WRITE, 0x70001726, 0x3FF0},
+ {TOK_WRITE, 0x70001728, 0x03E8},
+ {TOK_WRITE, 0x7000172A, 0x0000},
+ {TOK_WRITE, 0x7000172C, 0x0080},
+ {TOK_WRITE, 0x7000172E, 0x0009},
+ {TOK_WRITE, 0x70001730, 0x0020},
+ {TOK_WRITE, 0x70001732, 0x0040},
+ {TOK_WRITE, 0x70001734, 0x0080},
+ {TOK_WRITE, 0x70001736, 0x00C0},
+ {TOK_WRITE, 0x70001738, 0x00E0},
+ {TOK_WRITE, 0x7000028C, 0x0003},
+ {TOK_WRITE, 0x700008B4, 0x0001},
+ {TOK_WRITE, 0x700008BC, 0x00C0},
+ {TOK_WRITE, 0x700008BE, 0x00DF},
+ {TOK_WRITE, 0x700008C0, 0x0100},
+ {TOK_WRITE, 0x700008C2, 0x0125},
+ {TOK_WRITE, 0x700008C4, 0x015F},
+ {TOK_WRITE, 0x700008C6, 0x017C},
+ {TOK_WRITE, 0x700008C8, 0x0194},
+ {TOK_WRITE, 0x700008F6, 0x4000},
+ {TOK_WRITE, 0x700008F8, 0x4000},
+ {TOK_WRITE, 0x700008FA, 0x4000},
+ {TOK_WRITE, 0x700008FC, 0x4000},
+ {TOK_WRITE, 0x700008FE, 0x4000},
+ {TOK_WRITE, 0x70000900, 0x4000},
+ {TOK_WRITE, 0x70000902, 0x4000},
+ {TOK_WRITE, 0x70000904, 0x4000},
+ {TOK_WRITE, 0x70000906, 0x4000},
+ {TOK_WRITE, 0x70000908, 0x4000},
+ {TOK_WRITE, 0x7000090A, 0x4000},
+ {TOK_WRITE, 0x7000090C, 0x4000},
+ {TOK_WRITE, 0x7000090E, 0x3800},
+ {TOK_WRITE, 0x70000910, 0x4000},
+ {TOK_WRITE, 0x70000912, 0x4000},
+ {TOK_WRITE, 0x70000914, 0x4000},
+ {TOK_WRITE, 0x70000916, 0x3B00},
+ {TOK_WRITE, 0x70000918, 0x4000},
+ {TOK_WRITE, 0x7000091A, 0x4000},
+ {TOK_WRITE, 0x7000091C, 0x4000},
+ {TOK_WRITE, 0x7000091E, 0x4300},
+ {TOK_WRITE, 0x70000920, 0x4000},
+ {TOK_WRITE, 0x70000922, 0x4000},
+ {TOK_WRITE, 0x70000924, 0x4000},
+ {TOK_WRITE, 0x70000926, 0x4300},
+ {TOK_WRITE, 0x70000928, 0x4000},
+ {TOK_WRITE, 0x7000092A, 0x4000},
+ {TOK_WRITE, 0x7000092C, 0x4000},
+ {TOK_WRITE, 0x7000092E, 0x4500},
+ {TOK_WRITE, 0x70000930, 0x4000},
+ {TOK_WRITE, 0x70000932, 0x4000},
+ {TOK_WRITE, 0x70000934, 0x4000},
+ {TOK_WRITE, 0x700008F4, 0x0001},
+ {TOK_WRITE, 0x70001492, 0x0100},
+ {TOK_WRITE, 0x70001494, 0x0101},
+ {TOK_WRITE, 0x70001496, 0x0101},
+ {TOK_WRITE, 0x70001498, 0x0001},
+ {TOK_WRITE, 0x7000149A, 0x0101},
+ {TOK_WRITE, 0x7000149C, 0x0201},
+ {TOK_WRITE, 0x7000149E, 0x0102},
+ {TOK_WRITE, 0x700014A0, 0x0101},
+ {TOK_WRITE, 0x700014A2, 0x0101},
+ {TOK_WRITE, 0x700014A4, 0x0202},
+ {TOK_WRITE, 0x700014A6, 0x0202},
+ {TOK_WRITE, 0x700014A8, 0x0101},
+ {TOK_WRITE, 0x700014AA, 0x0201},
+ {TOK_WRITE, 0x700014AC, 0x0302},
+ {TOK_WRITE, 0x700014AE, 0x0203},
+ {TOK_WRITE, 0x700014B0, 0x0102},
+ {TOK_WRITE, 0x700014B2, 0x0201},
+ {TOK_WRITE, 0x700014B4, 0x0302},
+ {TOK_WRITE, 0x700014B6, 0x0203},
+ {TOK_WRITE, 0x700014B8, 0x0102},
+ {TOK_WRITE, 0x700014BA, 0x0201},
+ {TOK_WRITE, 0x700014BC, 0x0202},
+ {TOK_WRITE, 0x700014BE, 0x0202},
+ {TOK_WRITE, 0x700014C0, 0x0102},
+ {TOK_WRITE, 0x700014C2, 0x0101},
+ {TOK_WRITE, 0x700014C4, 0x0202},
+ {TOK_WRITE, 0x700014C6, 0x0202},
+ {TOK_WRITE, 0x700014C8, 0x0101},
+ {TOK_WRITE, 0x700014CA, 0x0101},
+ {TOK_WRITE, 0x700014CC, 0x0101},
+ {TOK_WRITE, 0x700014CE, 0x0101},
+ {TOK_WRITE, 0x700014D0, 0x0101},
+ {TOK_WRITE, 0x70001484, 0x003C},
+ {TOK_WRITE, 0x7000148A, 0x000F},
+ {TOK_WRITE, 0x7000058C, 0x3520},
+ {TOK_WRITE, 0x7000058E, 0x0000},
+ {TOK_WRITE, 0x70000590, 0xC350},
+ {TOK_WRITE, 0x70000592, 0x0000},
+ {TOK_WRITE, 0x70000594, 0x3520},
+ {TOK_WRITE, 0x70000596, 0x0000},
+ {TOK_WRITE, 0x70000598, 0xC350},
+ {TOK_WRITE, 0x7000059A, 0x0000},
+ {TOK_WRITE, 0x7000059C, 0x0470},
+ {TOK_WRITE, 0x7000059E, 0x0C00},
+ {TOK_WRITE, 0x700005A0, 0x0100},
+ {TOK_WRITE, 0x700005A2, 0x1000},
+ {TOK_WRITE, 0x70000544, 0x0111},
+ {TOK_WRITE, 0x70000546, 0x00EF},
+ {TOK_WRITE, 0x70000F2A, 0x0000},
+ {TOK_WRITE, 0x700004E6, 0x077F},
+ {TOK_WRITE, 0x70000F30, 0x0001},
+ {TOK_WRITE, 0x70000608, 0x0001},
+ {TOK_WRITE, 0x7000060A, 0x0001},
+ {TOK_WRITE, 0x7000060C, 0x0800},
+ {TOK_WRITE, 0x7000060E, 0x0100},
+ {TOK_WRITE, 0x70000610, 0x0001},
+ {TOK_WRITE, 0x70000612, 0x0000},
+ {TOK_WRITE, 0x70000614, 0x0A3C},
+ {TOK_WRITE, 0x70000616, 0x0000},
+ {TOK_WRITE, 0x70000618, 0x0D05},
+ {TOK_WRITE, 0x7000061A, 0x0000},
+ {TOK_WRITE, 0x7000061C, 0x4008},
+ {TOK_WRITE, 0x7000061E, 0x0000},
+ {TOK_WRITE, 0x70000620, 0x7000},
+ {TOK_WRITE, 0x70000622, 0x0000},
+ {TOK_WRITE, 0x70000624, 0x9C00},
+ {TOK_WRITE, 0x70000626, 0x0000},
+ {TOK_WRITE, 0x70000628, 0xAD00},
+ {TOK_WRITE, 0x7000062A, 0x0001},
+ {TOK_WRITE, 0x7000062C, 0xF1D4},
+ {TOK_WRITE, 0x7000062E, 0x0002},
+ {TOK_WRITE, 0x70000630, 0xDC00},
+ {TOK_WRITE, 0x70000632, 0x0005},
+ {TOK_WRITE, 0x70000634, 0xDC00},
+ {TOK_WRITE, 0x70000636, 0x0005},
+ {TOK_WRITE, 0x70000638, 0x0001},
+ {TOK_WRITE, 0x7000063A, 0x0000},
+ {TOK_WRITE, 0x7000063C, 0x0A3C},
+ {TOK_WRITE, 0x7000063E, 0x0000},
+ {TOK_WRITE, 0x70000640, 0x0D05},
+ {TOK_WRITE, 0x70000642, 0x0000},
+ {TOK_WRITE, 0x70000644, 0x3408},
+ {TOK_WRITE, 0x70000646, 0x0000},
+ {TOK_WRITE, 0x70000648, 0x3408},
+ {TOK_WRITE, 0x7000064A, 0x0000},
+ {TOK_WRITE, 0x7000064C, 0x6810},
+ {TOK_WRITE, 0x7000064E, 0x0000},
+ {TOK_WRITE, 0x70000650, 0x8214},
+ {TOK_WRITE, 0x70000652, 0x0000},
+ {TOK_WRITE, 0x70000654, 0xC350},
+ {TOK_WRITE, 0x70000656, 0x0000},
+ {TOK_WRITE, 0x70000658, 0xC350},
+ {TOK_WRITE, 0x7000065A, 0x0000},
+ {TOK_WRITE, 0x7000065C, 0xC350},
+ {TOK_WRITE, 0x7000065E, 0x0000},
+ {TOK_WRITE, 0x70000660, 0x0650},
+ {TOK_WRITE, 0x70000662, 0x0100},
+ {TOK_WRITE, 0x700006B8, 0x452C},
+ {TOK_WRITE, 0x700006BA, 0x0005},
+ {TOK_WRITE, 0x700005D0, 0x0000},
+ {TOK_WRITE, 0x7000145E, 0x0580},
+ {TOK_WRITE, 0x70001460, 0x0428},
+ {TOK_WRITE, 0x70001462, 0x07B0},
+ {TOK_WRITE, 0x700011F0, 0x0120},
+ {TOK_WRITE, 0x700011F2, 0x0121},
+ {TOK_WRITE, 0x7000101C, 0x037C},
+ {TOK_WRITE, 0x7000101E, 0x038E},
+ {TOK_WRITE, 0x70001020, 0x033C},
+ {TOK_WRITE, 0x70001022, 0x0384},
+ {TOK_WRITE, 0x70001024, 0x02FE},
+ {TOK_WRITE, 0x70001026, 0x036C},
+ {TOK_WRITE, 0x70001028, 0x02BA},
+ {TOK_WRITE, 0x7000102A, 0x0352},
+ {TOK_WRITE, 0x7000102C, 0x028E},
+ {TOK_WRITE, 0x7000102E, 0x0300},
+ {TOK_WRITE, 0x70001030, 0x026A},
+ {TOK_WRITE, 0x70001032, 0x02C8},
+ {TOK_WRITE, 0x70001034, 0x0254},
+ {TOK_WRITE, 0x70001036, 0x02A8},
+ {TOK_WRITE, 0x70001038, 0x0242},
+ {TOK_WRITE, 0x7000103A, 0x02A0},
+ {TOK_WRITE, 0x7000103C, 0x021A},
+ {TOK_WRITE, 0x7000103E, 0x02A0},
+ {TOK_WRITE, 0x70001040, 0x01F4},
+ {TOK_WRITE, 0x70001042, 0x0298},
+ {TOK_WRITE, 0x70001044, 0x01D4},
+ {TOK_WRITE, 0x70001046, 0x0290},
+ {TOK_WRITE, 0x70001048, 0x01CC},
+ {TOK_WRITE, 0x7000104A, 0x0276},
+ {TOK_WRITE, 0x7000104C, 0x01D2},
+ {TOK_WRITE, 0x7000104E, 0x0260},
+ {TOK_WRITE, 0x70001050, 0x01F6},
+ {TOK_WRITE, 0x70001052, 0x023A},
+ {TOK_WRITE, 0x70001054, 0x0000},
+ {TOK_WRITE, 0x70001056, 0x0000},
+ {TOK_WRITE, 0x70001058, 0x0000},
+ {TOK_WRITE, 0x7000105A, 0x0000},
+ {TOK_WRITE, 0x7000105C, 0x0000},
+ {TOK_WRITE, 0x7000105E, 0x0000},
+ {TOK_WRITE, 0x70001060, 0x0000},
+ {TOK_WRITE, 0x70001062, 0x0000},
+ {TOK_WRITE, 0x70001064, 0x0000},
+ {TOK_WRITE, 0x70001066, 0x0000},
+ {TOK_WRITE, 0x70001068, 0x0000},
+ {TOK_WRITE, 0x7000106A, 0x0000},
+ {TOK_WRITE, 0x7000106C, 0x0005},
+ {TOK_WRITE, 0x70001070, 0x000E},
+ {TOK_WRITE, 0x70001074, 0x0126},
+ {TOK_WRITE, 0x70001078, 0x0272},
+ {TOK_WRITE, 0x7000107A, 0x02A0},
+ {TOK_WRITE, 0x7000107C, 0x025A},
+ {TOK_WRITE, 0x7000107E, 0x02BC},
+ {TOK_WRITE, 0x70001080, 0x024A},
+ {TOK_WRITE, 0x70001082, 0x02C0},
+ {TOK_WRITE, 0x70001084, 0x023C},
+ {TOK_WRITE, 0x70001086, 0x02BE},
+ {TOK_WRITE, 0x70001088, 0x022E},
+ {TOK_WRITE, 0x7000108A, 0x02BC},
+ {TOK_WRITE, 0x7000108C, 0x0224},
+ {TOK_WRITE, 0x7000108E, 0x02B6},
+ {TOK_WRITE, 0x70001090, 0x0218},
+ {TOK_WRITE, 0x70001092, 0x02AA},
+ {TOK_WRITE, 0x70001094, 0x0210},
+ {TOK_WRITE, 0x70001096, 0x02A0},
+ {TOK_WRITE, 0x70001098, 0x020C},
+ {TOK_WRITE, 0x7000109A, 0x0296},
+ {TOK_WRITE, 0x7000109C, 0x020A},
+ {TOK_WRITE, 0x7000109E, 0x028C},
+ {TOK_WRITE, 0x700010A0, 0x0212},
+ {TOK_WRITE, 0x700010A2, 0x027E},
+ {TOK_WRITE, 0x700010A4, 0x0234},
+ {TOK_WRITE, 0x700010A6, 0x0256},
+ {TOK_WRITE, 0x700010A8, 0x0004},
+ {TOK_WRITE, 0x700010AC, 0x000C},
+ {TOK_WRITE, 0x700010B0, 0x01D8},
+ {TOK_WRITE, 0x700010B4, 0x0350},
+ {TOK_WRITE, 0x700010B6, 0x0422},
+ {TOK_WRITE, 0x700010B8, 0x02C4},
+ {TOK_WRITE, 0x700010BA, 0x0452},
+ {TOK_WRITE, 0x700010BC, 0x0278},
+ {TOK_WRITE, 0x700010BE, 0x041C},
+ {TOK_WRITE, 0x700010C0, 0x0230},
+ {TOK_WRITE, 0x700010C2, 0x03EE},
+ {TOK_WRITE, 0x700010C4, 0x01F0},
+ {TOK_WRITE, 0x700010C6, 0x0392},
+ {TOK_WRITE, 0x700010C8, 0x01C0},
+ {TOK_WRITE, 0x700010CA, 0x0340},
+ {TOK_WRITE, 0x700010CC, 0x0194},
+ {TOK_WRITE, 0x700010CE, 0x0302},
+ {TOK_WRITE, 0x700010D0, 0x016E},
+ {TOK_WRITE, 0x700010D2, 0x02C2},
+ {TOK_WRITE, 0x700010D4, 0x0148},
+ {TOK_WRITE, 0x700010D6, 0x0286},
+ {TOK_WRITE, 0x700010D8, 0x018A},
+ {TOK_WRITE, 0x700010DA, 0x0242},
+ {TOK_WRITE, 0x700010DC, 0x0000},
+ {TOK_WRITE, 0x700010DE, 0x0000},
+ {TOK_WRITE, 0x700010E0, 0x0000},
+ {TOK_WRITE, 0x700010E2, 0x0000},
+ {TOK_WRITE, 0x700010E4, 0x0006},
+ {TOK_WRITE, 0x700010E8, 0x000A},
+ {TOK_WRITE, 0x700010EC, 0x0106},
+ {TOK_WRITE, 0x700010F0, 0x0380},
+ {TOK_WRITE, 0x700010F2, 0x0000},
+ {TOK_WRITE, 0x700010F4, 0x0168},
+ {TOK_WRITE, 0x700010F6, 0x0000},
+ {TOK_WRITE, 0x700010F8, 0x2D90},
+ {TOK_WRITE, 0x700010FA, 0x0000},
+ {TOK_WRITE, 0x70001464, 0x0008},
+ {TOK_WRITE, 0x70001466, 0x0190},
+ {TOK_WRITE, 0x70001468, 0x00A0},
+ {TOK_WRITE, 0x70001228, 0x00C0},
+ {TOK_WRITE, 0x7000122C, 0x0010},
+ {TOK_WRITE, 0x7000122A, 0x0010},
+ {TOK_WRITE, 0x7000120A, 0x05D5},
+ {TOK_WRITE, 0x7000120E, 0x0000},
+ {TOK_WRITE, 0x70001210, 0x0771},
+ {TOK_WRITE, 0x70001212, 0x03A4},
+ {TOK_WRITE, 0x70001214, 0x0036},
+ {TOK_WRITE, 0x70001216, 0x002A},
+ {TOK_WRITE, 0x70001278, 0xFEF7},
+ {TOK_WRITE, 0x7000127A, 0x0021},
+ {TOK_WRITE, 0x7000127C, 0x0AF0},
+ {TOK_WRITE, 0x7000127E, 0x0AF0},
+ {TOK_WRITE, 0x70001280, 0x018F},
+ {TOK_WRITE, 0x70001282, 0x0096},
+ {TOK_WRITE, 0x70001284, 0x000E},
+ {TOK_WRITE, 0x70001224, 0x0032},
+ {TOK_WRITE, 0x70001226, 0x001E},
+ {TOK_WRITE, 0x70001228, 0x00C0},
+ {TOK_WRITE, 0x7000122A, 0x0010},
+ {TOK_WRITE, 0x7000122C, 0x0002},
+ {TOK_WRITE, 0x70002BA4, 0x0006},
+ {TOK_WRITE, 0x7000146C, 0x0002},
+ {TOK_WRITE, 0x70001434, 0x02CE},
+ {TOK_WRITE, 0x70001436, 0x0347},
+ {TOK_WRITE, 0x70001438, 0x03C2},
+ {TOK_WRITE, 0x7000143A, 0x10A0},
+ {TOK_WRITE, 0x7000143C, 0x10A1},
+ {TOK_WRITE, 0x7000143E, 0x1185},
+ {TOK_WRITE, 0x70001440, 0x1186},
+ {TOK_WRITE, 0x70001442, 0x11E5},
+ {TOK_WRITE, 0x70001444, 0x11E6},
+ {TOK_WRITE, 0x70001446, 0x00AB},
+ {TOK_WRITE, 0x70001448, 0x00BF},
+ {TOK_WRITE, 0x7000144A, 0x00D2},
+ {TOK_WRITE, 0x7000144C, 0x0093},
+ {TOK_WRITE, 0x700013A4, 0xFFF6},
+ {TOK_WRITE, 0x700013A6, 0xFFD8},
+ {TOK_WRITE, 0x700013A8, 0xFFD8},
+ {TOK_WRITE, 0x700013AA, 0xFFD8},
+ {TOK_WRITE, 0x700013AC, 0xFFD8},
+ {TOK_WRITE, 0x700013AE, 0xFFD0},
+ {TOK_WRITE, 0x700013B0, 0xFFF6},
+ {TOK_WRITE, 0x700013B2, 0xFFD8},
+ {TOK_WRITE, 0x700013B4, 0xFFD8},
+ {TOK_WRITE, 0x700013B6, 0xFFD8},
+ {TOK_WRITE, 0x700013B8, 0xFFD8},
+ {TOK_WRITE, 0x700013BA, 0xFFD0},
+ {TOK_WRITE, 0x700013BC, 0xFFF6},
+ {TOK_WRITE, 0x700013BE, 0xFFD8},
+ {TOK_WRITE, 0x700013C0, 0xFFD8},
+ {TOK_WRITE, 0x700013C2, 0xFFD8},
+ {TOK_WRITE, 0x700013C4, 0xFFD8},
+ {TOK_WRITE, 0x700013C6, 0xFFD0},
+ {TOK_WRITE, 0x700013C8, 0xFFEC},
+ {TOK_WRITE, 0x700013CA, 0x000A},
+ {TOK_WRITE, 0x700013CC, 0x000A},
+ {TOK_WRITE, 0x700013CE, 0x0050},
+ {TOK_WRITE, 0x700013D0, 0x0050},
+ {TOK_WRITE, 0x700013D2, 0x0078},
+ {TOK_WRITE, 0x700013D4, 0xFFEC},
+ {TOK_WRITE, 0x700013D6, 0x000A},
+ {TOK_WRITE, 0x700013D8, 0x000A},
+ {TOK_WRITE, 0x700013DA, 0x0050},
+ {TOK_WRITE, 0x700013DC, 0x0050},
+ {TOK_WRITE, 0x700013DE, 0x0078},
+ {TOK_WRITE, 0x700013E0, 0xFFEC},
+ {TOK_WRITE, 0x700013E2, 0x000A},
+ {TOK_WRITE, 0x700013E4, 0x000A},
+ {TOK_WRITE, 0x700013E6, 0x0050},
+ {TOK_WRITE, 0x700013E8, 0x0050},
+ {TOK_WRITE, 0x700013EA, 0x0078},
+ {TOK_WRITE, 0x700013EC, 0x0000},
+ {TOK_WRITE, 0x700013EE, 0x0000},
+ {TOK_WRITE, 0x700013F0, 0x0000},
+ {TOK_WRITE, 0x700013F2, 0x0000},
+ {TOK_WRITE, 0x700013F4, 0x0000},
+ {TOK_WRITE, 0x700013F6, 0x0000},
+ {TOK_WRITE, 0x700013F8, 0x0000},
+ {TOK_WRITE, 0x700013FA, 0x0000},
+ {TOK_WRITE, 0x700013FC, 0x0000},
+ {TOK_WRITE, 0x700013FE, 0x0000},
+ {TOK_WRITE, 0x70001400, 0x0000},
+ {TOK_WRITE, 0x70001402, 0x0000},
+ {TOK_WRITE, 0x70001404, 0x0000},
+ {TOK_WRITE, 0x70001406, 0x0000},
+ {TOK_WRITE, 0x70001408, 0x0000},
+ {TOK_WRITE, 0x7000140A, 0x0000},
+ {TOK_WRITE, 0x7000140C, 0x0000},
+ {TOK_WRITE, 0x7000140E, 0x0000},
+ {TOK_WRITE, 0x70001410, 0xFFC0},
+ {TOK_WRITE, 0x70001412, 0xFFC0},
+ {TOK_WRITE, 0x70001414, 0xFFC0},
+ {TOK_WRITE, 0x70001416, 0x0000},
+ {TOK_WRITE, 0x70001418, 0x0000},
+ {TOK_WRITE, 0x7000141A, 0x0000},
+ {TOK_WRITE, 0x7000141C, 0xFFC0},
+ {TOK_WRITE, 0x7000141E, 0xFFC0},
+ {TOK_WRITE, 0x70001420, 0xFFC0},
+ {TOK_WRITE, 0x70001422, 0x0000},
+ {TOK_WRITE, 0x70001424, 0x0000},
+ {TOK_WRITE, 0x70001426, 0x0000},
+ {TOK_WRITE, 0x70001428, 0xFFC0},
+ {TOK_WRITE, 0x7000142A, 0xFFC0},
+ {TOK_WRITE, 0x7000142C, 0xFFC0},
+ {TOK_WRITE, 0x7000142E, 0x0000},
+ {TOK_WRITE, 0x70001430, 0x0000},
+ {TOK_WRITE, 0x70001432, 0x0000},
+ {TOK_WRITE, 0x70001208, 0x0020},
+ {TOK_WRITE, 0x7000144E, 0x0000},
+ {TOK_WRITE, 0x70001450, 0xFFE0},
+ {TOK_WRITE, 0x70001452, 0x0000},
+ {TOK_WRITE, 0x70000734, 0x0000},
+ {TOK_WRITE, 0x70000736, 0x000A},
+ {TOK_WRITE, 0x70000738, 0x0016},
+ {TOK_WRITE, 0x7000073A, 0x0030},
+ {TOK_WRITE, 0x7000073C, 0x0066},
+ {TOK_WRITE, 0x7000073E, 0x00D5},
+ {TOK_WRITE, 0x70000740, 0x0138},
+ {TOK_WRITE, 0x70000742, 0x0163},
+ {TOK_WRITE, 0x70000744, 0x0189},
+ {TOK_WRITE, 0x70000746, 0x01C6},
+ {TOK_WRITE, 0x70000748, 0x01F8},
+ {TOK_WRITE, 0x7000074A, 0x0222},
+ {TOK_WRITE, 0x7000074C, 0x0247},
+ {TOK_WRITE, 0x7000074E, 0x0282},
+ {TOK_WRITE, 0x70000750, 0x02B5},
+ {TOK_WRITE, 0x70000752, 0x030F},
+ {TOK_WRITE, 0x70000754, 0x035F},
+ {TOK_WRITE, 0x70000756, 0x03A2},
+ {TOK_WRITE, 0x70000758, 0x03D8},
+ {TOK_WRITE, 0x7000075A, 0x03FF},
+ {TOK_WRITE, 0x7000075C, 0x0000},
+ {TOK_WRITE, 0x7000075E, 0x000A},
+ {TOK_WRITE, 0x70000760, 0x0016},
+ {TOK_WRITE, 0x70000762, 0x0030},
+ {TOK_WRITE, 0x70000764, 0x0066},
+ {TOK_WRITE, 0x70000766, 0x00D5},
+ {TOK_WRITE, 0x70000768, 0x0138},
+ {TOK_WRITE, 0x7000076A, 0x0163},
+ {TOK_WRITE, 0x7000076C, 0x0189},
+ {TOK_WRITE, 0x7000076E, 0x01C6},
+ {TOK_WRITE, 0x70000770, 0x01F8},
+ {TOK_WRITE, 0x70000772, 0x0222},
+ {TOK_WRITE, 0x70000774, 0x0247},
+ {TOK_WRITE, 0x70000776, 0x0282},
+ {TOK_WRITE, 0x70000778, 0x02B5},
+ {TOK_WRITE, 0x7000077A, 0x030F},
+ {TOK_WRITE, 0x7000077C, 0x035F},
+ {TOK_WRITE, 0x7000077E, 0x03A2},
+ {TOK_WRITE, 0x70000780, 0x03D8},
+ {TOK_WRITE, 0x70000782, 0x03FF},
+ {TOK_WRITE, 0x70000784, 0x0000},
+ {TOK_WRITE, 0x70000786, 0x000A},
+ {TOK_WRITE, 0x70000788, 0x0016},
+ {TOK_WRITE, 0x7000078A, 0x0030},
+ {TOK_WRITE, 0x7000078C, 0x0066},
+ {TOK_WRITE, 0x7000078E, 0x00D5},
+ {TOK_WRITE, 0x70000790, 0x0138},
+ {TOK_WRITE, 0x70000792, 0x0163},
+ {TOK_WRITE, 0x70000794, 0x0189},
+ {TOK_WRITE, 0x70000796, 0x01C6},
+ {TOK_WRITE, 0x70000798, 0x01F8},
+ {TOK_WRITE, 0x7000079A, 0x0222},
+ {TOK_WRITE, 0x7000079C, 0x0247},
+ {TOK_WRITE, 0x7000079E, 0x0282},
+ {TOK_WRITE, 0x700007A0, 0x02B5},
+ {TOK_WRITE, 0x700007A2, 0x030F},
+ {TOK_WRITE, 0x700007A4, 0x035F},
+ {TOK_WRITE, 0x700007A6, 0x03A2},
+ {TOK_WRITE, 0x700007A8, 0x03D8},
+ {TOK_WRITE, 0x700007AA, 0x03FF},
+ {TOK_WRITE, 0x700007AC, 0x0000},
+ {TOK_WRITE, 0x700007AE, 0x000B},
+ {TOK_WRITE, 0x700007B0, 0x0019},
+ {TOK_WRITE, 0x700007B2, 0x0036},
+ {TOK_WRITE, 0x700007B4, 0x006F},
+ {TOK_WRITE, 0x700007B6, 0x00D8},
+ {TOK_WRITE, 0x700007B8, 0x0135},
+ {TOK_WRITE, 0x700007BA, 0x015F},
+ {TOK_WRITE, 0x700007BC, 0x0185},
+ {TOK_WRITE, 0x700007BE, 0x01C1},
+ {TOK_WRITE, 0x700007C0, 0x01F3},
+ {TOK_WRITE, 0x700007C2, 0x0220},
+ {TOK_WRITE, 0x700007C4, 0x024A},
+ {TOK_WRITE, 0x700007C6, 0x0291},
+ {TOK_WRITE, 0x700007C8, 0x02D0},
+ {TOK_WRITE, 0x700007CA, 0x032A},
+ {TOK_WRITE, 0x700007CC, 0x036A},
+ {TOK_WRITE, 0x700007CE, 0x039F},
+ {TOK_WRITE, 0x700007D0, 0x03CC},
+ {TOK_WRITE, 0x700007D2, 0x03F9},
+ {TOK_WRITE, 0x700007D4, 0x0000},
+ {TOK_WRITE, 0x700007D6, 0x000B},
+ {TOK_WRITE, 0x700007D8, 0x0019},
+ {TOK_WRITE, 0x700007DA, 0x0036},
+ {TOK_WRITE, 0x700007DC, 0x006F},
+ {TOK_WRITE, 0x700007DE, 0x00D8},
+ {TOK_WRITE, 0x700007E0, 0x0135},
+ {TOK_WRITE, 0x700007E2, 0x015F},
+ {TOK_WRITE, 0x700007E4, 0x0185},
+ {TOK_WRITE, 0x700007E6, 0x01C1},
+ {TOK_WRITE, 0x700007E8, 0x01F3},
+ {TOK_WRITE, 0x700007EA, 0x0220},
+ {TOK_WRITE, 0x700007EC, 0x024A},
+ {TOK_WRITE, 0x700007EE, 0x0291},
+ {TOK_WRITE, 0x700007F0, 0x02D0},
+ {TOK_WRITE, 0x700007F2, 0x032A},
+ {TOK_WRITE, 0x700007F4, 0x036A},
+ {TOK_WRITE, 0x700007F6, 0x039F},
+ {TOK_WRITE, 0x700007F8, 0x03CC},
+ {TOK_WRITE, 0x700007FA, 0x03F9},
+ {TOK_WRITE, 0x700007FC, 0x0000},
+ {TOK_WRITE, 0x700007FE, 0x000B},
+ {TOK_WRITE, 0x70000800, 0x0019},
+ {TOK_WRITE, 0x70000802, 0x0036},
+ {TOK_WRITE, 0x70000804, 0x006F},
+ {TOK_WRITE, 0x70000806, 0x00D8},
+ {TOK_WRITE, 0x70000808, 0x0135},
+ {TOK_WRITE, 0x7000080A, 0x015F},
+ {TOK_WRITE, 0x7000080C, 0x0185},
+ {TOK_WRITE, 0x7000080E, 0x01C1},
+ {TOK_WRITE, 0x70000810, 0x01F3},
+ {TOK_WRITE, 0x70000812, 0x0220},
+ {TOK_WRITE, 0x70000814, 0x024A},
+ {TOK_WRITE, 0x70000816, 0x0291},
+ {TOK_WRITE, 0x70000818, 0x02D0},
+ {TOK_WRITE, 0x7000081A, 0x032A},
+ {TOK_WRITE, 0x7000081C, 0x036A},
+ {TOK_WRITE, 0x7000081E, 0x039F},
+ {TOK_WRITE, 0x70000820, 0x03CC},
+ {TOK_WRITE, 0x70000822, 0x03F9},
+ {TOK_WRITE, 0x700008A6, 0x00C0},
+ {TOK_WRITE, 0x700008A8, 0x0100},
+ {TOK_WRITE, 0x700008AA, 0x0125},
+ {TOK_WRITE, 0x700008AC, 0x015F},
+ {TOK_WRITE, 0x700008AE, 0x017C},
+ {TOK_WRITE, 0x700008B0, 0x0194},
+ {TOK_WRITE, 0x700008B2, 0x0001},
+ {TOK_WRITE, 0x70000898, 0x4800},
+ {TOK_WRITE, 0x7000089A, 0x7000},
+ {TOK_WRITE, 0x700008A0, 0x48D8},
+ {TOK_WRITE, 0x700008A2, 0x7000},
+ {TOK_WRITE, 0x70004800, 0x024C},
+ {TOK_WRITE, 0x70004802, 0xFF5E},
+ {TOK_WRITE, 0x70004804, 0xFF9D},
+ {TOK_WRITE, 0x70004806, 0xFEC9},
+ {TOK_WRITE, 0x70004808, 0x0203},
+ {TOK_WRITE, 0x7000480A, 0xFF08},
+ {TOK_WRITE, 0x7000480C, 0xFFDB},
+ {TOK_WRITE, 0x7000480E, 0xFF8F},
+ {TOK_WRITE, 0x70004810, 0x0206},
+ {TOK_WRITE, 0x70004812, 0x00E0},
+ {TOK_WRITE, 0x70004814, 0x009F},
+ {TOK_WRITE, 0x70004816, 0xFE7B},
+ {TOK_WRITE, 0x70004818, 0x0227},
+ {TOK_WRITE, 0x7000481A, 0xFEFE},
+ {TOK_WRITE, 0x7000481C, 0x0194},
+ {TOK_WRITE, 0x7000481E, 0xFE86},
+ {TOK_WRITE, 0x70004820, 0x01E0},
+ {TOK_WRITE, 0x70004822, 0x0104},
+ {TOK_WRITE, 0x70004824, 0x024C},
+ {TOK_WRITE, 0x70004826, 0xFF5E},
+ {TOK_WRITE, 0x70004828, 0xFF9D},
+ {TOK_WRITE, 0x7000482A, 0xFEC9},
+ {TOK_WRITE, 0x7000482C, 0x0203},
+ {TOK_WRITE, 0x7000482E, 0xFF08},
+ {TOK_WRITE, 0x70004830, 0xFFDB},
+ {TOK_WRITE, 0x70004832, 0xFF8F},
+ {TOK_WRITE, 0x70004834, 0x0206},
+ {TOK_WRITE, 0x70004836, 0x00E0},
+ {TOK_WRITE, 0x70004838, 0x009F},
+ {TOK_WRITE, 0x7000483A, 0xFE7B},
+ {TOK_WRITE, 0x7000483C, 0x0227},
+ {TOK_WRITE, 0x7000483E, 0xFEFE},
+ {TOK_WRITE, 0x70004840, 0x0194},
+ {TOK_WRITE, 0x70004842, 0xFE86},
+ {TOK_WRITE, 0x70004844, 0x01E0},
+ {TOK_WRITE, 0x70004846, 0x0104},
+ {TOK_WRITE, 0x70004848, 0x0208},
+ {TOK_WRITE, 0x7000484A, 0xFFB5},
+ {TOK_WRITE, 0x7000484C, 0xFFE8},
+ {TOK_WRITE, 0x7000484E, 0xFF20},
+ {TOK_WRITE, 0x70004850, 0x01BF},
+ {TOK_WRITE, 0x70004852, 0xFF53},
+ {TOK_WRITE, 0x70004854, 0x0022},
+ {TOK_WRITE, 0x70004856, 0xFFEA},
+ {TOK_WRITE, 0x70004858, 0x01C2},
+ {TOK_WRITE, 0x7000485A, 0x00C6},
+ {TOK_WRITE, 0x7000485C, 0x0095},
+ {TOK_WRITE, 0x7000485E, 0xFEFD},
+ {TOK_WRITE, 0x70004860, 0x0206},
+ {TOK_WRITE, 0x70004862, 0xFF7F},
+ {TOK_WRITE, 0x70004864, 0x0191},
+ {TOK_WRITE, 0x70004866, 0xFF06},
+ {TOK_WRITE, 0x70004868, 0x01BA},
+ {TOK_WRITE, 0x7000486A, 0x0108},
+ {TOK_WRITE, 0x7000486C, 0x0204},
+ {TOK_WRITE, 0x7000486E, 0xFFB2},
+ {TOK_WRITE, 0x70004870, 0xFFF5},
+ {TOK_WRITE, 0x70004872, 0xFEF1},
+ {TOK_WRITE, 0x70004874, 0x014E},
+ {TOK_WRITE, 0x70004876, 0xFF18},
+ {TOK_WRITE, 0x70004878, 0xFFE6},
+ {TOK_WRITE, 0x7000487A, 0xFFDD},
+ {TOK_WRITE, 0x7000487C, 0x01B2},
+ {TOK_WRITE, 0x7000487E, 0x00F2},
+ {TOK_WRITE, 0x70004880, 0x00CA},
+ {TOK_WRITE, 0x70004882, 0xFF48},
+ {TOK_WRITE, 0x70004884, 0x0151},
+ {TOK_WRITE, 0x70004886, 0xFF50},
+ {TOK_WRITE, 0x70004888, 0x0147},
+ {TOK_WRITE, 0x7000488A, 0xFF75},
+ {TOK_WRITE, 0x7000488C, 0x0187},
+ {TOK_WRITE, 0x7000488E, 0x01BF},
+ {TOK_WRITE, 0x70004890, 0x0204},
+ {TOK_WRITE, 0x70004892, 0xFFB2},
+ {TOK_WRITE, 0x70004894, 0xFFF5},
+ {TOK_WRITE, 0x70004896, 0xFEF1},
+ {TOK_WRITE, 0x70004898, 0x014E},
+ {TOK_WRITE, 0x7000489A, 0xFF18},
+ {TOK_WRITE, 0x7000489C, 0xFFE6},
+ {TOK_WRITE, 0x7000489E, 0xFFDD},
+ {TOK_WRITE, 0x700048A0, 0x01B2},
+ {TOK_WRITE, 0x700048A2, 0x00F2},
+ {TOK_WRITE, 0x700048A4, 0x00CA},
+ {TOK_WRITE, 0x700048A6, 0xFF48},
+ {TOK_WRITE, 0x700048A8, 0x0151},
+ {TOK_WRITE, 0x700048AA, 0xFF50},
+ {TOK_WRITE, 0x700048AC, 0x0147},
+ {TOK_WRITE, 0x700048AE, 0xFF75},
+ {TOK_WRITE, 0x700048B0, 0x0187},
+ {TOK_WRITE, 0x700048B2, 0x01BF},
+ {TOK_WRITE, 0x700048B4, 0x0204},
+ {TOK_WRITE, 0x700048B6, 0xFFB2},
+ {TOK_WRITE, 0x700048B8, 0xFFF5},
+ {TOK_WRITE, 0x700048BA, 0xFEF1},
+ {TOK_WRITE, 0x700048BC, 0x014E},
+ {TOK_WRITE, 0x700048BE, 0xFF18},
+ {TOK_WRITE, 0x700048C0, 0xFFE6},
+ {TOK_WRITE, 0x700048C2, 0xFFDD},
+ {TOK_WRITE, 0x700048C4, 0x01B2},
+ {TOK_WRITE, 0x700048C6, 0x00F2},
+ {TOK_WRITE, 0x700048C8, 0x00CA},
+ {TOK_WRITE, 0x700048CA, 0xFF48},
+ {TOK_WRITE, 0x700048CC, 0x0151},
+ {TOK_WRITE, 0x700048CE, 0xFF50},
+ {TOK_WRITE, 0x700048D0, 0x0147},
+ {TOK_WRITE, 0x700048D2, 0xFF75},
+ {TOK_WRITE, 0x700048D4, 0x0187},
+ {TOK_WRITE, 0x700048D6, 0x01BF},
+ {TOK_WRITE, 0x700048D8, 0x01E5},
+ {TOK_WRITE, 0x700048DA, 0xFFA4},
+ {TOK_WRITE, 0x700048DC, 0xFFDC},
+ {TOK_WRITE, 0x700048DE, 0xFE90},
+ {TOK_WRITE, 0x700048E0, 0x013F},
+ {TOK_WRITE, 0x700048E2, 0xFF1B},
+ {TOK_WRITE, 0x700048E4, 0xFFD2},
+ {TOK_WRITE, 0x700048E6, 0xFFDF},
+ {TOK_WRITE, 0x700048E8, 0x0236},
+ {TOK_WRITE, 0x700048EA, 0x00EC},
+ {TOK_WRITE, 0x700048EC, 0x00F8},
+ {TOK_WRITE, 0x700048EE, 0xFF34},
+ {TOK_WRITE, 0x700048F0, 0x01CE},
+ {TOK_WRITE, 0x700048F2, 0xFF83},
+ {TOK_WRITE, 0x700048F4, 0x0195},
+ {TOK_WRITE, 0x700048F6, 0xFEF3},
+ {TOK_WRITE, 0x700048F8, 0x0126},
+ {TOK_WRITE, 0x700048FA, 0x0162},
+ {TOK_WRITE, 0x70000944, 0x0050},
+ {TOK_WRITE, 0x70000946, 0x00B0},
+ {TOK_WRITE, 0x70000948, 0x0196},
+ {TOK_WRITE, 0x7000094A, 0x0245},
+ {TOK_WRITE, 0x7000094C, 0x0300},
+ {TOK_WRITE, 0x7000097A, 0x0000},
+ {TOK_WRITE, 0x7000097C, 0x01CC},
+ {TOK_WRITE, 0x7000097E, 0x01CC},
+ {TOK_WRITE, 0x70000980, 0x01CC},
+ {TOK_WRITE, 0x70000982, 0x01CC},
+ {TOK_WRITE, 0x70000984, 0x01CC},
+ {TOK_WRITE, 0x70000986, 0x0180},
+ {TOK_WRITE, 0x70000988, 0x0196},
+ {TOK_WRITE, 0x70000976, 0x0070},
+ {TOK_WRITE, 0x70000978, 0x0005},
+ {TOK_WRITE, 0x70000938, 0x0000},
+ {TOK_WRITE, 0x7000093A, 0x0014},
+ {TOK_WRITE, 0x7000093C, 0x00D2},
+ {TOK_WRITE, 0x7000093E, 0x0384},
+ {TOK_WRITE, 0x70000940, 0x07D0},
+ {TOK_WRITE, 0x70000942, 0x1388},
+ {TOK_WRITE, 0x7000098C, 0x0000},
+ {TOK_WRITE, 0x7000098E, 0x0000},
+ {TOK_WRITE, 0x70000990, 0x0000},
+ {TOK_WRITE, 0x70000992, 0x0000},
+ {TOK_WRITE, 0x70000994, 0x0000},
+ {TOK_WRITE, 0x70000996, 0x00C0},
+ {TOK_WRITE, 0x70000998, 0x0064},
+ {TOK_WRITE, 0x7000099A, 0x0384},
+ {TOK_WRITE, 0x7000099C, 0x005F},
+ {TOK_WRITE, 0x7000099E, 0x01F4},
+ {TOK_WRITE, 0x700009A0, 0x0070},
+ {TOK_WRITE, 0x700009A2, 0x0040},
+ {TOK_WRITE, 0x700009A4, 0x00A0},
+ {TOK_WRITE, 0x700009A6, 0x0100},
+ {TOK_WRITE, 0x700009A8, 0x0010},
+ {TOK_WRITE, 0x700009AA, 0x0040},
+ {TOK_WRITE, 0x700009AC, 0x00A0},
+ {TOK_WRITE, 0x700009AE, 0x1430},
+ {TOK_WRITE, 0x700009B0, 0x0201},
+ {TOK_WRITE, 0x700009B2, 0x0204},
+ {TOK_WRITE, 0x700009B4, 0x3604},
+ {TOK_WRITE, 0x700009B6, 0x032A},
+ {TOK_WRITE, 0x700009B8, 0x0403},
+ {TOK_WRITE, 0x700009BA, 0x1B06},
+ {TOK_WRITE, 0x700009BC, 0x6015},
+ {TOK_WRITE, 0x700009BE, 0x00C0},
+ {TOK_WRITE, 0x700009C0, 0x6080},
+ {TOK_WRITE, 0x700009C2, 0x4080},
+ {TOK_WRITE, 0x700009C4, 0x0640},
+ {TOK_WRITE, 0x700009C6, 0x0306},
+ {TOK_WRITE, 0x700009C8, 0x2003},
+ {TOK_WRITE, 0x700009CA, 0xFF01},
+ {TOK_WRITE, 0x700009CC, 0x0000},
+ {TOK_WRITE, 0x700009CE, 0x0400},
+ {TOK_WRITE, 0x700009D0, 0x365A},
+ {TOK_WRITE, 0x700009D2, 0x102A},
+ {TOK_WRITE, 0x700009D4, 0x000B},
+ {TOK_WRITE, 0x700009D6, 0x0600},
+ {TOK_WRITE, 0x700009D8, 0x5A0F},
+ {TOK_WRITE, 0x700009DA, 0x0505},
+ {TOK_WRITE, 0x700009DC, 0x1802},
+ {TOK_WRITE, 0x700009DE, 0x0000},
+ {TOK_WRITE, 0x700009E0, 0x2006},
+ {TOK_WRITE, 0x700009E2, 0x3028},
+ {TOK_WRITE, 0x700009E4, 0x0418},
+ {TOK_WRITE, 0x700009E6, 0x0101},
+ {TOK_WRITE, 0x700009E8, 0x0800},
+ {TOK_WRITE, 0x700009EA, 0x1804},
+ {TOK_WRITE, 0x700009EC, 0x4008},
+ {TOK_WRITE, 0x700009EE, 0x0540},
+ {TOK_WRITE, 0x700009F0, 0x8006},
+ {TOK_WRITE, 0x700009F2, 0x0020},
+ {TOK_WRITE, 0x700009F4, 0x0000},
+ {TOK_WRITE, 0x700009F6, 0x1800},
+ {TOK_WRITE, 0x700009F8, 0x0000},
+ {TOK_WRITE, 0x700009FA, 0x1E10},
+ {TOK_WRITE, 0x700009FC, 0x000B},
+ {TOK_WRITE, 0x700009FE, 0x0607},
+ {TOK_WRITE, 0x70000A00, 0x0005},
+ {TOK_WRITE, 0x70000A02, 0x0607},
+ {TOK_WRITE, 0x70000A04, 0x0405},
+ {TOK_WRITE, 0x70000A06, 0x0205},
+ {TOK_WRITE, 0x70000A08, 0x0304},
+ {TOK_WRITE, 0x70000A0A, 0x0409},
+ {TOK_WRITE, 0x70000A0C, 0x0306},
+ {TOK_WRITE, 0x70000A0E, 0x0407},
+ {TOK_WRITE, 0x70000A10, 0x1C04},
+ {TOK_WRITE, 0x70000A12, 0x0214},
+ {TOK_WRITE, 0x70000A14, 0x1002},
+ {TOK_WRITE, 0x70000A16, 0x0610},
+ {TOK_WRITE, 0x70000A18, 0x1A02},
+ {TOK_WRITE, 0x70000A1A, 0x4A18},
+ {TOK_WRITE, 0x70000A1C, 0x0080},
+ {TOK_WRITE, 0x70000A1E, 0x0348},
+ {TOK_WRITE, 0x70000A20, 0x0180},
+ {TOK_WRITE, 0x70000A22, 0x0A0A},
+ {TOK_WRITE, 0x70000A24, 0x0101},
+ {TOK_WRITE, 0x70000A26, 0x2A36},
+ {TOK_WRITE, 0x70000A28, 0x6024},
+ {TOK_WRITE, 0x70000A2A, 0x2A36},
+ {TOK_WRITE, 0x70000A2C, 0xFFFF},
+ {TOK_WRITE, 0x70000A2E, 0x0808},
+ {TOK_WRITE, 0x70000A30, 0x0A01},
+ {TOK_WRITE, 0x70000A32, 0x010A},
+ {TOK_WRITE, 0x70000A34, 0x3601},
+ {TOK_WRITE, 0x70000A36, 0x242A},
+ {TOK_WRITE, 0x70000A38, 0x3660},
+ {TOK_WRITE, 0x70000A3A, 0xFF2A},
+ {TOK_WRITE, 0x70000A3C, 0x08FF},
+ {TOK_WRITE, 0x70000A3E, 0x0008},
+ {TOK_WRITE, 0x70000A40, 0x0001},
+ {TOK_WRITE, 0x70000A42, 0x0000},
+ {TOK_WRITE, 0x70000A44, 0x0000},
+ {TOK_WRITE, 0x70000A46, 0x0010},
+ {TOK_WRITE, 0x70000A48, 0x0000},
+ {TOK_WRITE, 0x70000A4A, 0x0000},
+ {TOK_WRITE, 0x70000A4C, 0x00C0},
+ {TOK_WRITE, 0x70000A4E, 0x0064},
+ {TOK_WRITE, 0x70000A50, 0x0384},
+ {TOK_WRITE, 0x70000A52, 0x0051},
+ {TOK_WRITE, 0x70000A54, 0x01F4},
+ {TOK_WRITE, 0x70000A56, 0x0070},
+ {TOK_WRITE, 0x70000A58, 0x0040},
+ {TOK_WRITE, 0x70000A5A, 0x00A0},
+ {TOK_WRITE, 0x70000A5C, 0x0100},
+ {TOK_WRITE, 0x70000A5E, 0x0010},
+ {TOK_WRITE, 0x70000A60, 0x0060},
+ {TOK_WRITE, 0x70000A62, 0x0100},
+ {TOK_WRITE, 0x70000A64, 0x1430},
+ {TOK_WRITE, 0x70000A66, 0x0201},
+ {TOK_WRITE, 0x70000A68, 0x0204},
+ {TOK_WRITE, 0x70000A6A, 0x2404},
+ {TOK_WRITE, 0x70000A6C, 0x031B},
+ {TOK_WRITE, 0x70000A6E, 0x0103},
+ {TOK_WRITE, 0x70000A70, 0x1205},
+ {TOK_WRITE, 0x70000A72, 0x400D},
+ {TOK_WRITE, 0x70000A74, 0x0080},
+ {TOK_WRITE, 0x70000A76, 0x2080},
+ {TOK_WRITE, 0x70000A78, 0x3040},
+ {TOK_WRITE, 0x70000A7A, 0x0630},
+ {TOK_WRITE, 0x70000A7C, 0x0306},
+ {TOK_WRITE, 0x70000A7E, 0x2003},
+ {TOK_WRITE, 0x70000A80, 0xFF01},
+ {TOK_WRITE, 0x70000A82, 0x0404},
+ {TOK_WRITE, 0x70000A84, 0x0300},
+ {TOK_WRITE, 0x70000A86, 0x245A},
+ {TOK_WRITE, 0x70000A88, 0x1018},
+ {TOK_WRITE, 0x70000A8A, 0x000B},
+ {TOK_WRITE, 0x70000A8C, 0x0B00},
+ {TOK_WRITE, 0x70000A8E, 0x5A0F},
+ {TOK_WRITE, 0x70000A90, 0x0505},
+ {TOK_WRITE, 0x70000A92, 0x1802},
+ {TOK_WRITE, 0x70000A94, 0x0000},
+ {TOK_WRITE, 0x70000A96, 0x2006},
+ {TOK_WRITE, 0x70000A98, 0x3428},
+ {TOK_WRITE, 0x70000A9A, 0x041C},
+ {TOK_WRITE, 0x70000A9C, 0x0101},
+ {TOK_WRITE, 0x70000A9E, 0x0800},
+ {TOK_WRITE, 0x70000AA0, 0x1004},
+ {TOK_WRITE, 0x70000AA2, 0x4008},
+ {TOK_WRITE, 0x70000AA4, 0x0540},
+ {TOK_WRITE, 0x70000AA6, 0x8006},
+ {TOK_WRITE, 0x70000AA8, 0x0020},
+ {TOK_WRITE, 0x70000AAA, 0x0000},
+ {TOK_WRITE, 0x70000AAC, 0x1800},
+ {TOK_WRITE, 0x70000AAE, 0x0000},
+ {TOK_WRITE, 0x70000AB0, 0x1E10},
+ {TOK_WRITE, 0x70000AB2, 0x000B},
+ {TOK_WRITE, 0x70000AB4, 0x0607},
+ {TOK_WRITE, 0x70000AB6, 0x0005},
+ {TOK_WRITE, 0x70000AB8, 0x0607},
+ {TOK_WRITE, 0x70000ABA, 0x0405},
+ {TOK_WRITE, 0x70000ABC, 0x0205},
+ {TOK_WRITE, 0x70000ABE, 0x0304},
+ {TOK_WRITE, 0x70000AC0, 0x0409},
+ {TOK_WRITE, 0x70000AC2, 0x0306},
+ {TOK_WRITE, 0x70000AC4, 0x0407},
+ {TOK_WRITE, 0x70000AC6, 0x1F04},
+ {TOK_WRITE, 0x70000AC8, 0x0218},
+ {TOK_WRITE, 0x70000ACA, 0x1102},
+ {TOK_WRITE, 0x70000ACC, 0x0611},
+ {TOK_WRITE, 0x70000ACE, 0x1A02},
+ {TOK_WRITE, 0x70000AD0, 0x8018},
+ {TOK_WRITE, 0x70000AD2, 0x0080},
+ {TOK_WRITE, 0x70000AD4, 0x0380},
+ {TOK_WRITE, 0x70000AD6, 0x0180},
+ {TOK_WRITE, 0x70000AD8, 0x0A0A},
+ {TOK_WRITE, 0x70000ADA, 0x0101},
+ {TOK_WRITE, 0x70000ADC, 0x1B24},
+ {TOK_WRITE, 0x70000ADE, 0x6024},
+ {TOK_WRITE, 0x70000AE0, 0x1D22},
+ {TOK_WRITE, 0x70000AE2, 0xFFFF},
+ {TOK_WRITE, 0x70000AE4, 0x0808},
+ {TOK_WRITE, 0x70000AE6, 0x0A01},
+ {TOK_WRITE, 0x70000AE8, 0x010A},
+ {TOK_WRITE, 0x70000AEA, 0x2401},
+ {TOK_WRITE, 0x70000AEC, 0x241B},
+ {TOK_WRITE, 0x70000AEE, 0x1E60},
+ {TOK_WRITE, 0x70000AF0, 0xFF18},
+ {TOK_WRITE, 0x70000AF2, 0x08FF},
+ {TOK_WRITE, 0x70000AF4, 0x0008},
+ {TOK_WRITE, 0x70000AF6, 0x0001},
+ {TOK_WRITE, 0x70000AF8, 0x0000},
+ {TOK_WRITE, 0x70000AFA, 0x0000},
+ {TOK_WRITE, 0x70000AFC, 0x0010},
+ {TOK_WRITE, 0x70000AFE, 0x0000},
+ {TOK_WRITE, 0x70000B00, 0x0000},
+ {TOK_WRITE, 0x70000B02, 0x00C0},
+ {TOK_WRITE, 0x70000B04, 0x0064},
+ {TOK_WRITE, 0x70000B06, 0x0384},
+ {TOK_WRITE, 0x70000B08, 0x0043},
+ {TOK_WRITE, 0x70000B0A, 0x01F4},
+ {TOK_WRITE, 0x70000B0C, 0x0070},
+ {TOK_WRITE, 0x70000B0E, 0x0040},
+ {TOK_WRITE, 0x70000B10, 0x00A0},
+ {TOK_WRITE, 0x70000B12, 0x0100},
+ {TOK_WRITE, 0x70000B14, 0x0010},
+ {TOK_WRITE, 0x70000B16, 0x0060},
+ {TOK_WRITE, 0x70000B18, 0x0100},
+ {TOK_WRITE, 0x70000B1A, 0x1430},
+ {TOK_WRITE, 0x70000B1C, 0x0201},
+ {TOK_WRITE, 0x70000B1E, 0x0204},
+ {TOK_WRITE, 0x70000B20, 0x1B04},
+ {TOK_WRITE, 0x70000B22, 0x0312},
+ {TOK_WRITE, 0x70000B24, 0x0003},
+ {TOK_WRITE, 0x70000B26, 0x0C03},
+ {TOK_WRITE, 0x70000B28, 0x2806},
+ {TOK_WRITE, 0x70000B2A, 0x0060},
+ {TOK_WRITE, 0x70000B2C, 0x1580},
+ {TOK_WRITE, 0x70000B2E, 0x2020},
+ {TOK_WRITE, 0x70000B30, 0x0620},
+ {TOK_WRITE, 0x70000B32, 0x0306},
+ {TOK_WRITE, 0x70000B34, 0x2003},
+ {TOK_WRITE, 0x70000B36, 0xFF01},
+ {TOK_WRITE, 0x70000B38, 0x0404},
+ {TOK_WRITE, 0x70000B3A, 0x0300},
+ {TOK_WRITE, 0x70000B3C, 0x145A},
+ {TOK_WRITE, 0x70000B3E, 0x1010},
+ {TOK_WRITE, 0x70000B40, 0x000B},
+ {TOK_WRITE, 0x70000B42, 0x0E00},
+ {TOK_WRITE, 0x70000B44, 0x5A0F},
+ {TOK_WRITE, 0x70000B46, 0x0504},
+ {TOK_WRITE, 0x70000B48, 0x1802},
+ {TOK_WRITE, 0x70000B4A, 0x0000},
+ {TOK_WRITE, 0x70000B4C, 0x2006},
+ {TOK_WRITE, 0x70000B4E, 0x3828},
+ {TOK_WRITE, 0x70000B50, 0x0428},
+ {TOK_WRITE, 0x70000B52, 0x0101},
+ {TOK_WRITE, 0x70000B54, 0x8000},
+ {TOK_WRITE, 0x70000B56, 0x0A04},
+ {TOK_WRITE, 0x70000B58, 0x4008},
+ {TOK_WRITE, 0x70000B5A, 0x0540},
+ {TOK_WRITE, 0x70000B5C, 0x8006},
+ {TOK_WRITE, 0x70000B5E, 0x0020},
+ {TOK_WRITE, 0x70000B60, 0x0000},
+ {TOK_WRITE, 0x70000B62, 0x1800},
+ {TOK_WRITE, 0x70000B64, 0x0000},
+ {TOK_WRITE, 0x70000B66, 0x1E10},
+ {TOK_WRITE, 0x70000B68, 0x000B},
+ {TOK_WRITE, 0x70000B6A, 0x0607},
+ {TOK_WRITE, 0x70000B6C, 0x0005},
+ {TOK_WRITE, 0x70000B6E, 0x0607},
+ {TOK_WRITE, 0x70000B70, 0x0405},
+ {TOK_WRITE, 0x70000B72, 0x0207},
+ {TOK_WRITE, 0x70000B74, 0x0304},
+ {TOK_WRITE, 0x70000B76, 0x0409},
+ {TOK_WRITE, 0x70000B78, 0x0306},
+ {TOK_WRITE, 0x70000B7A, 0x0407},
+ {TOK_WRITE, 0x70000B7C, 0x2404},
+ {TOK_WRITE, 0x70000B7E, 0x0221},
+ {TOK_WRITE, 0x70000B80, 0x1202},
+ {TOK_WRITE, 0x70000B82, 0x0613},
+ {TOK_WRITE, 0x70000B84, 0x1A02},
+ {TOK_WRITE, 0x70000B86, 0x8018},
+ {TOK_WRITE, 0x70000B88, 0x0080},
+ {TOK_WRITE, 0x70000B8A, 0x0080},
+ {TOK_WRITE, 0x70000B8C, 0x0180},
+ {TOK_WRITE, 0x70000B8E, 0x0A0A},
+ {TOK_WRITE, 0x70000B90, 0x0101},
+ {TOK_WRITE, 0x70000B92, 0x141D},
+ {TOK_WRITE, 0x70000B94, 0x6024},
+ {TOK_WRITE, 0x70000B96, 0x0C0C},
+ {TOK_WRITE, 0x70000B98, 0xFFFF},
+ {TOK_WRITE, 0x70000B9A, 0x0808},
+ {TOK_WRITE, 0x70000B9C, 0x0A01},
+ {TOK_WRITE, 0x70000B9E, 0x010A},
+ {TOK_WRITE, 0x70000BA0, 0x1B01},
+ {TOK_WRITE, 0x70000BA2, 0x2412},
+ {TOK_WRITE, 0x70000BA4, 0x0C60},
+ {TOK_WRITE, 0x70000BA6, 0xFF0C},
+ {TOK_WRITE, 0x70000BA8, 0x08FF},
+ {TOK_WRITE, 0x70000BAA, 0x0008},
+ {TOK_WRITE, 0x70000BAC, 0x0001},
+ {TOK_WRITE, 0x70000BAE, 0x0000},
+ {TOK_WRITE, 0x70000BB0, 0x0000},
+ {TOK_WRITE, 0x70000BB2, 0x000A},
+ {TOK_WRITE, 0x70000BB4, 0x0000},
+ {TOK_WRITE, 0x70000BB6, 0x0000},
+ {TOK_WRITE, 0x70000BB8, 0x00C0},
+ {TOK_WRITE, 0x70000BBA, 0x0064},
+ {TOK_WRITE, 0x70000BBC, 0x0384},
+ {TOK_WRITE, 0x70000BBE, 0x0032},
+ {TOK_WRITE, 0x70000BC0, 0x01F4},
+ {TOK_WRITE, 0x70000BC2, 0x0070},
+ {TOK_WRITE, 0x70000BC4, 0x0040},
+ {TOK_WRITE, 0x70000BC6, 0x00A0},
+ {TOK_WRITE, 0x70000BC8, 0x0100},
+ {TOK_WRITE, 0x70000BCA, 0x0010},
+ {TOK_WRITE, 0x70000BCC, 0x0060},
+ {TOK_WRITE, 0x70000BCE, 0x0100},
+ {TOK_WRITE, 0x70000BD0, 0x1430},
+ {TOK_WRITE, 0x70000BD2, 0x0201},
+ {TOK_WRITE, 0x70000BD4, 0x0204},
+ {TOK_WRITE, 0x70000BD6, 0x1504},
+ {TOK_WRITE, 0x70000BD8, 0x030F},
+ {TOK_WRITE, 0x70000BDA, 0x0003},
+ {TOK_WRITE, 0x70000BDC, 0x0902},
+ {TOK_WRITE, 0x70000BDE, 0x2004},
+ {TOK_WRITE, 0x70000BE0, 0x0050},
+ {TOK_WRITE, 0x70000BE2, 0x1140},
+ {TOK_WRITE, 0x70000BE4, 0x201C},
+ {TOK_WRITE, 0x70000BE6, 0x0620},
+ {TOK_WRITE, 0x70000BE8, 0x0306},
+ {TOK_WRITE, 0x70000BEA, 0x2003},
+ {TOK_WRITE, 0x70000BEC, 0xFF01},
+ {TOK_WRITE, 0x70000BEE, 0x0404},
+ {TOK_WRITE, 0x70000BF0, 0x0300},
+ {TOK_WRITE, 0x70000BF2, 0x145A},
+ {TOK_WRITE, 0x70000BF4, 0x1010},
+ {TOK_WRITE, 0x70000BF6, 0x000B},
+ {TOK_WRITE, 0x70000BF8, 0x1000},
+ {TOK_WRITE, 0x70000BFA, 0x5A0F},
+ {TOK_WRITE, 0x70000BFC, 0x0503},
+ {TOK_WRITE, 0x70000BFE, 0x1802},
+ {TOK_WRITE, 0x70000C00, 0x0000},
+ {TOK_WRITE, 0x70000C02, 0x2006},
+ {TOK_WRITE, 0x70000C04, 0x3C28},
+ {TOK_WRITE, 0x70000C06, 0x042C},
+ {TOK_WRITE, 0x70000C08, 0x0101},
+ {TOK_WRITE, 0x70000C0A, 0xFF00},
+ {TOK_WRITE, 0x70000C0C, 0x0904},
+ {TOK_WRITE, 0x70000C0E, 0x4008},
+ {TOK_WRITE, 0x70000C10, 0x0540},
+ {TOK_WRITE, 0x70000C12, 0x8006},
+ {TOK_WRITE, 0x70000C14, 0x0020},
+ {TOK_WRITE, 0x70000C16, 0x0000},
+ {TOK_WRITE, 0x70000C18, 0x1800},
+ {TOK_WRITE, 0x70000C1A, 0x0000},
+ {TOK_WRITE, 0x70000C1C, 0x1E10},
+ {TOK_WRITE, 0x70000C1E, 0x000B},
+ {TOK_WRITE, 0x70000C20, 0x0607},
+ {TOK_WRITE, 0x70000C22, 0x0005},
+ {TOK_WRITE, 0x70000C24, 0x0607},
+ {TOK_WRITE, 0x70000C26, 0x0405},
+ {TOK_WRITE, 0x70000C28, 0x0206},
+ {TOK_WRITE, 0x70000C2A, 0x0304},
+ {TOK_WRITE, 0x70000C2C, 0x0409},
+ {TOK_WRITE, 0x70000C2E, 0x0305},
+ {TOK_WRITE, 0x70000C30, 0x0406},
+ {TOK_WRITE, 0x70000C32, 0x2804},
+ {TOK_WRITE, 0x70000C34, 0x0228},
+ {TOK_WRITE, 0x70000C36, 0x1402},
+ {TOK_WRITE, 0x70000C38, 0x0618},
+ {TOK_WRITE, 0x70000C3A, 0x1A02},
+ {TOK_WRITE, 0x70000C3C, 0x8018},
+ {TOK_WRITE, 0x70000C3E, 0x0080},
+ {TOK_WRITE, 0x70000C40, 0x0080},
+ {TOK_WRITE, 0x70000C42, 0x0180},
+ {TOK_WRITE, 0x70000C44, 0x0A0A},
+ {TOK_WRITE, 0x70000C46, 0x0101},
+ {TOK_WRITE, 0x70000C48, 0x1117},
+ {TOK_WRITE, 0x70000C4A, 0x6024},
+ {TOK_WRITE, 0x70000C4C, 0x0A0A},
+ {TOK_WRITE, 0x70000C4E, 0xFFFF},
+ {TOK_WRITE, 0x70000C50, 0x0808},
+ {TOK_WRITE, 0x70000C52, 0x0A01},
+ {TOK_WRITE, 0x70000C54, 0x010A},
+ {TOK_WRITE, 0x70000C56, 0x1501},
+ {TOK_WRITE, 0x70000C58, 0x240F},
+ {TOK_WRITE, 0x70000C5A, 0x0A60},
+ {TOK_WRITE, 0x70000C5C, 0xFF0A},
+ {TOK_WRITE, 0x70000C5E, 0x08FF},
+ {TOK_WRITE, 0x70000C60, 0x0008},
+ {TOK_WRITE, 0x70000C62, 0x0001},
+ {TOK_WRITE, 0x70000C64, 0x0000},
+ {TOK_WRITE, 0x70000C66, 0x0000},
+ {TOK_WRITE, 0x70000C68, 0x0000},
+ {TOK_WRITE, 0x70000C6A, 0x0000},
+ {TOK_WRITE, 0x70000C6C, 0x0000},
+ {TOK_WRITE, 0x70000C6E, 0x00C0},
+ {TOK_WRITE, 0x70000C70, 0x0064},
+ {TOK_WRITE, 0x70000C72, 0x0384},
+ {TOK_WRITE, 0x70000C74, 0x0032},
+ {TOK_WRITE, 0x70000C76, 0x01F4},
+ {TOK_WRITE, 0x70000C78, 0x0070},
+ {TOK_WRITE, 0x70000C7A, 0x0040},
+ {TOK_WRITE, 0x70000C7C, 0x00A0},
+ {TOK_WRITE, 0x70000C7E, 0x0100},
+ {TOK_WRITE, 0x70000C80, 0x0010},
+ {TOK_WRITE, 0x70000C82, 0x0060},
+ {TOK_WRITE, 0x70000C84, 0x0100},
+ {TOK_WRITE, 0x70000C86, 0x1430},
+ {TOK_WRITE, 0x70000C88, 0x0201},
+ {TOK_WRITE, 0x70000C8A, 0x0204},
+ {TOK_WRITE, 0x70000C8C, 0x0F04},
+ {TOK_WRITE, 0x70000C8E, 0x030C},
+ {TOK_WRITE, 0x70000C90, 0x0003},
+ {TOK_WRITE, 0x70000C92, 0x0602},
+ {TOK_WRITE, 0x70000C94, 0x1803},
+ {TOK_WRITE, 0x70000C96, 0x0040},
+ {TOK_WRITE, 0x70000C98, 0x0E20},
+ {TOK_WRITE, 0x70000C9A, 0x2018},
+ {TOK_WRITE, 0x70000C9C, 0x0620},
+ {TOK_WRITE, 0x70000C9E, 0x0306},
+ {TOK_WRITE, 0x70000CA0, 0x2003},
+ {TOK_WRITE, 0x70000CA2, 0xFF01},
+ {TOK_WRITE, 0x70000CA4, 0x0404},
+ {TOK_WRITE, 0x70000CA6, 0x0200},
+ {TOK_WRITE, 0x70000CA8, 0x145A},
+ {TOK_WRITE, 0x70000CAA, 0x1010},
+ {TOK_WRITE, 0x70000CAC, 0x000B},
+ {TOK_WRITE, 0x70000CAE, 0x1200},
+ {TOK_WRITE, 0x70000CB0, 0x5A0F},
+ {TOK_WRITE, 0x70000CB2, 0x0502},
+ {TOK_WRITE, 0x70000CB4, 0x1802},
+ {TOK_WRITE, 0x70000CB6, 0x0000},
+ {TOK_WRITE, 0x70000CB8, 0x2006},
+ {TOK_WRITE, 0x70000CBA, 0x4028},
+ {TOK_WRITE, 0x70000CBC, 0x0430},
+ {TOK_WRITE, 0x70000CBE, 0x0101},
+ {TOK_WRITE, 0x70000CC0, 0xFF00},
+ {TOK_WRITE, 0x70000CC2, 0x0804},
+ {TOK_WRITE, 0x70000CC4, 0x4008},
+ {TOK_WRITE, 0x70000CC6, 0x0540},
+ {TOK_WRITE, 0x70000CC8, 0x8006},
+ {TOK_WRITE, 0x70000CCA, 0x0020},
+ {TOK_WRITE, 0x70000CCC, 0x0000},
+ {TOK_WRITE, 0x70000CCE, 0x1800},
+ {TOK_WRITE, 0x70000CD0, 0x0000},
+ {TOK_WRITE, 0x70000CD2, 0x1E10},
+ {TOK_WRITE, 0x70000CD4, 0x000B},
+ {TOK_WRITE, 0x70000CD6, 0x0607},
+ {TOK_WRITE, 0x70000CD8, 0x0005},
+ {TOK_WRITE, 0x70000CDA, 0x0607},
+ {TOK_WRITE, 0x70000CDC, 0x0405},
+ {TOK_WRITE, 0x70000CDE, 0x0205},
+ {TOK_WRITE, 0x70000CE0, 0x0304},
+ {TOK_WRITE, 0x70000CE2, 0x0409},
+ {TOK_WRITE, 0x70000CE4, 0x0306},
+ {TOK_WRITE, 0x70000CE6, 0x0407},
+ {TOK_WRITE, 0x70000CE8, 0x2C04},
+ {TOK_WRITE, 0x70000CEA, 0x022C},
+ {TOK_WRITE, 0x70000CEC, 0x1402},
+ {TOK_WRITE, 0x70000CEE, 0x0618},
+ {TOK_WRITE, 0x70000CF0, 0x1A02},
+ {TOK_WRITE, 0x70000CF2, 0x8018},
+ {TOK_WRITE, 0x70000CF4, 0x0080},
+ {TOK_WRITE, 0x70000CF6, 0x0080},
+ {TOK_WRITE, 0x70000CF8, 0x0180},
+ {TOK_WRITE, 0x70000CFA, 0x0A0A},
+ {TOK_WRITE, 0x70000CFC, 0x0101},
+ {TOK_WRITE, 0x70000CFE, 0x0C0F},
+ {TOK_WRITE, 0x70000D00, 0x6024},
+ {TOK_WRITE, 0x70000D02, 0x0808},
+ {TOK_WRITE, 0x70000D04, 0xFFFF},
+ {TOK_WRITE, 0x70000D06, 0x0808},
+ {TOK_WRITE, 0x70000D08, 0x0A01},
+ {TOK_WRITE, 0x70000D0A, 0x010A},
+ {TOK_WRITE, 0x70000D0C, 0x0F01},
+ {TOK_WRITE, 0x70000D0E, 0x240C},
+ {TOK_WRITE, 0x70000D10, 0x0860},
+ {TOK_WRITE, 0x70000D12, 0xFF08},
+ {TOK_WRITE, 0x70000D14, 0x08FF},
+ {TOK_WRITE, 0x70000D16, 0x0008},
+ {TOK_WRITE, 0x70000D18, 0x0001},
+ {TOK_WRITE, 0x70000D1A, 0x23CE},
+ {TOK_WRITE, 0x70000D1C, 0xFDC8},
+ {TOK_WRITE, 0x70000D1E, 0x112E},
+ {TOK_WRITE, 0x70000D20, 0x93A5},
+ {TOK_WRITE, 0x70000D22, 0xFE67},
+ {TOK_WRITE, 0x70000D24, 0x0000},
+ {TOK_WRITE, 0x700001F8, 0x5DC0},
+ {TOK_WRITE, 0x70000212, 0x0002},
+ {TOK_WRITE, 0x70000214, 0x0000},
+ {TOK_WRITE, 0x70000216, 0x0000},
+ {TOK_WRITE, 0x7000021A, 0x3A98},
+ {TOK_WRITE, 0x7000021C, 0x4F1A},
+ {TOK_WRITE, 0x7000021E, 0x4F1A},
+ {TOK_WRITE, 0x70000220, 0x4F1A},
+ {TOK_WRITE, 0x70000222, 0x4F1A},
+ {TOK_WRITE, 0x70000224, 0x4F1A},
+ {TOK_WRITE, 0x7000022C, 0x0001},
+ {TOK_WRITE, 0x70000478, 0x005F},
+ {TOK_WRITE, 0x7000047A, 0x005F},
+ {TOK_WRITE, 0x7000047C, 0x0001},
+ {TOK_WRITE, 0x7000047E, 0x0280},
+ {TOK_WRITE, 0x70000480, 0x01E0},
+ {TOK_WRITE, 0x70000482, 0x0005},
+ {TOK_WRITE, 0x700017DC, 0x0054},
+ {TOK_WRITE, 0x70001AE4, 0x001C},
+ {TOK_WRITE, 0x70000284, 0x0001},
+ {TOK_WRITE, 0x7000028A, 0x0000},
+ {TOK_WRITE, 0x700002A6, 0x0288},
+ {TOK_WRITE, 0x700002A8, 0x01E8},
+ {TOK_WRITE, 0x700002AA, 0x0005},
+ {TOK_WRITE, 0x700002AC, 0x4F1A},
+ {TOK_WRITE, 0x700002AE, 0x4F1A},
+ {TOK_WRITE, 0x700002B0, 0x0100},
+ {TOK_WRITE, 0x700002B2, 0x0300},
+ {TOK_WRITE, 0x700002B4, 0x0042},
+ {TOK_WRITE, 0x700002B6, 0x0000},
+ {TOK_WRITE, 0x700002B8, 0x01E0},
+ {TOK_WRITE, 0x700002BA, 0x0000},
+ {TOK_WRITE, 0x700002BC, 0x0000},
+ {TOK_WRITE, 0x700002BE, 0x0000},
+ {TOK_WRITE, 0x700002C0, 0x0002},
+ {TOK_WRITE, 0x700002C2, 0x03E8},
+ {TOK_WRITE, 0x700002C4, 0x014A},
+ {TOK_WRITE, 0x700002D0, 0x0000},
+ {TOK_WRITE, 0x700002D2, 0x0000},
+ {TOK_WRITE, 0x700002D4, 0x0000},
+ {TOK_WRITE, 0x70000396, 0x0000},
+ {TOK_WRITE, 0x70000398, 0x0A00},
+ {TOK_WRITE, 0x7000039A, 0x0780},
+ {TOK_WRITE, 0x7000039C, 0x0005},
+ {TOK_WRITE, 0x7000039E, 0x4F1A},
+ {TOK_WRITE, 0x700003A0, 0x4F1A},
+ {TOK_WRITE, 0x700003A2, 0x0100},
+ {TOK_WRITE, 0x700003A4, 0x0300},
+ {TOK_WRITE, 0x700003A6, 0x0042},
+ {TOK_WRITE, 0x700003A8, 0x0070},
+ {TOK_WRITE, 0x700003AA, 0x0810},
+ {TOK_WRITE, 0x700003AC, 0x0900},
+ {TOK_WRITE, 0x700003AE, 0x0001},
+ {TOK_WRITE, 0x700003B0, 0x0000},
+ {TOK_WRITE, 0x700003B2, 0x0002},
+ {TOK_WRITE, 0x700003B4, 0x0535},
+ {TOK_WRITE, 0x700003B6, 0x029A},
+ {TOK_WRITE, 0x70000250, 0x0A00},
+ {TOK_WRITE, 0x70000252, 0x0780},
+ {TOK_WRITE, 0x70000254, 0x0010},
+ {TOK_WRITE, 0x70000256, 0x000C},
+ {TOK_WRITE, 0x70000258, 0x0A00},
+ {TOK_WRITE, 0x7000025A, 0x0780},
+ {TOK_WRITE, 0x7000025C, 0x0010},
+ {TOK_WRITE, 0x7000025E, 0x000C},
+ {TOK_WRITE, 0x70000494, 0x0A00},
+ {TOK_WRITE, 0x70000496, 0x0780},
+ {TOK_WRITE, 0x70000498, 0x0000},
+ {TOK_WRITE, 0x7000049A, 0x0000},
+ {TOK_WRITE, 0x7000049C, 0x0A00},
+ {TOK_WRITE, 0x7000049E, 0x0780},
+ {TOK_WRITE, 0x700004A0, 0x0000},
+ {TOK_WRITE, 0x700004A2, 0x0000},
+ {TOK_WRITE, 0x70000262, 0x0001},
+ {TOK_WRITE, 0x70000264, 0x0001},
+ {TOK_WRITE, 0x70001CC2, 0x0100},
+ {TOK_WRITE, 0x70001CC4, 0x0100},
+ {TOK_WRITE, 0x70001CC6, 0x0100},
+ {TOK_WRITE, 0x70001CC8, 0x0100},
+ {TOK_WRITE, 0x700001A8, 0x0A0A},
+ {TOK_WRITE, 0x7000147C, 0x0170},
+ {TOK_WRITE, 0x70001482, 0x01E0},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_WRITE, 0x70000270, 0x0001},
+ {TOK_WRITE, 0x7000023E, 0x0001},
+ {TOK_WRITE, 0x70000240, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+
+/* Configure 30 FPS */
+struct regval_list s5k4ecgx_fps_30[] = {
+ {TOK_WRITE, 0x700002B4, 0x0052},
+ {TOK_WRITE, 0x700002BE, 0x0000},
+ {TOK_WRITE, 0x700002C0, 0x0001},
+ {TOK_WRITE, 0x700002C2, 0x014D},
+ {TOK_WRITE, 0x700002C4, 0x014D},
+ {TOK_WRITE, 0x700002D0, 0x0000},
+ {TOK_WRITE, 0x700002D2, 0x0000},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+struct regval_list s5k4ecgx_effect_normal[] = {
+ {TOK_WRITE, 0x7000023C, 0x0000},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+struct regval_list s5k4ecgx_wb_auto[] = {
+ {TOK_WRITE, 0x700004E6, 0x077F},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+struct regval_list s5k4ecgx_iso_auto[] = {
+ {TOK_WRITE, 0x70000938, 0x0000},
+ {TOK_WRITE, 0x70000F2A, 0x0001},
+ {TOK_WRITE, 0x700004E6, 0x077F},
+ {TOK_WRITE, 0x700004D0, 0x0000},
+ {TOK_WRITE, 0x700004D2, 0x0000},
+ {TOK_WRITE, 0x700004D4, 0x0001},
+ {TOK_WRITE, 0x700006C2, 0x0200},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+struct regval_list s5k4ecgx_contrast_default[] = {
+ {TOK_WRITE, 0x70000232, 0x0000},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+struct regval_list s5k4ecgx_scene_default[] = {
+ {TOK_WRITE, 0x70001492, 0x0000},
+ {TOK_WRITE, 0x70001494, 0x0101},
+ {TOK_WRITE, 0x70001496, 0x0101},
+ {TOK_WRITE, 0x70001498, 0x0000},
+ {TOK_WRITE, 0x7000149A, 0x0101},
+ {TOK_WRITE, 0x7000149C, 0x0101},
+ {TOK_WRITE, 0x7000149E, 0x0101},
+ {TOK_WRITE, 0x700014A0, 0x0101},
+ {TOK_WRITE, 0x700014A2, 0x0201},
+ {TOK_WRITE, 0x700014A4, 0x0303},
+ {TOK_WRITE, 0x700014A6, 0x0303},
+ {TOK_WRITE, 0x700014A8, 0x0102},
+ {TOK_WRITE, 0x700014AA, 0x0201},
+ {TOK_WRITE, 0x700014AC, 0x0403},
+ {TOK_WRITE, 0x700014AE, 0x0304},
+ {TOK_WRITE, 0x700014B0, 0x0102},
+ {TOK_WRITE, 0x700014B2, 0x0201},
+ {TOK_WRITE, 0x700014B4, 0x0403},
+ {TOK_WRITE, 0x700014B6, 0x0304},
+ {TOK_WRITE, 0x700014B8, 0x0102},
+ {TOK_WRITE, 0x700014BA, 0x0201},
+ {TOK_WRITE, 0x700014BC, 0x0403},
+ {TOK_WRITE, 0x700014BE, 0x0304},
+ {TOK_WRITE, 0x700014C0, 0x0102},
+ {TOK_WRITE, 0x700014C2, 0x0201},
+ {TOK_WRITE, 0x700014C4, 0x0303},
+ {TOK_WRITE, 0x700014C6, 0x0303},
+ {TOK_WRITE, 0x700014C8, 0x0102},
+ {TOK_WRITE, 0x700014CA, 0x0201},
+ {TOK_WRITE, 0x700014CC, 0x0202},
+ {TOK_WRITE, 0x700014CE, 0x0202},
+ {TOK_WRITE, 0x700014D0, 0x0102},
+ {TOK_WRITE, 0x70000938, 0x0000},
+ {TOK_WRITE, 0x700006B8, 0x452C},
+ {TOK_WRITE, 0x700006BA, 0x000C},
+ {TOK_WRITE, 0x70000F2A, 0x0001},
+ {TOK_WRITE, 0x70000F30, 0x0001},
+ {TOK_WRITE, 0x700004E6, 0x077F},
+ {TOK_WRITE, 0x700004D0, 0x0000},
+ {TOK_WRITE, 0x700004D2, 0x0000},
+ {TOK_WRITE, 0x700004D4, 0x0001},
+ {TOK_WRITE, 0x700006C2, 0x0200},
+ {TOK_WRITE, 0x70002C66, 0x0001},
+ {TOK_WRITE, 0x70001484, 0x003C},
+ {TOK_WRITE, 0x7000148A, 0x000F},
+ {TOK_WRITE, 0x7000058C, 0x3520},
+ {TOK_WRITE, 0x7000058E, 0x0000},
+ {TOK_WRITE, 0x70000590, 0xC350},
+ {TOK_WRITE, 0x70000592, 0x0000},
+ {TOK_WRITE, 0x70000594, 0x3520},
+ {TOK_WRITE, 0x70000596, 0x0000},
+ {TOK_WRITE, 0x70000598, 0xC350},
+ {TOK_WRITE, 0x7000059A, 0x0000},
+ {TOK_WRITE, 0x7000059C, 0x0470},
+ {TOK_WRITE, 0x7000059E, 0x0C00},
+ {TOK_WRITE, 0x700005A0, 0x0100},
+ {TOK_WRITE, 0x700005A2, 0x1000},
+ {TOK_WRITE, 0x70000544, 0x0111},
+ {TOK_WRITE, 0x70000546, 0x00EF},
+ {TOK_WRITE, 0x70000608, 0x0001},
+ {TOK_WRITE, 0x7000060A, 0x0001},
+ {TOK_WRITE, 0x70000A28, 0x6024},
+ {TOK_WRITE, 0x70000ADE, 0x6024},
+ {TOK_WRITE, 0x70000B94, 0x6024},
+ {TOK_WRITE, 0x70000C4A, 0x6024},
+ {TOK_WRITE, 0x70000D00, 0x6024},
+ {TOK_WRITE, 0x70000234, 0x0000},
+ {TOK_WRITE, 0x70000638, 0x0001},
+ {TOK_WRITE, 0x7000063A, 0x0000},
+ {TOK_WRITE, 0x7000063C, 0x0A3C},
+ {TOK_WRITE, 0x7000063E, 0x0000},
+ {TOK_WRITE, 0x70000640, 0x0D05},
+ {TOK_WRITE, 0x70000642, 0x0000},
+ {TOK_WRITE, 0x70000644, 0x3408},
+ {TOK_WRITE, 0x70000646, 0x0000},
+ {TOK_WRITE, 0x70000648, 0x3408},
+ {TOK_WRITE, 0x7000064A, 0x0000},
+ {TOK_WRITE, 0x7000064C, 0x6810},
+ {TOK_WRITE, 0x7000064E, 0x0000},
+ {TOK_WRITE, 0x70000650, 0x8214},
+ {TOK_WRITE, 0x70000652, 0x0000},
+ {TOK_WRITE, 0x70000654, 0xC350},
+ {TOK_WRITE, 0x70000656, 0x0000},
+ {TOK_WRITE, 0x70000658, 0xC350},
+ {TOK_WRITE, 0x7000065A, 0x0000},
+ {TOK_WRITE, 0x7000065C, 0xC350},
+ {TOK_WRITE, 0x7000065E, 0x0000},
+ {TOK_WRITE, 0x700002C2, 0x029A},
+ /* #REG_0TC_PCFG_usMaxFrTimeMsecMult10 */
+ {TOK_WRITE, 0x700002C4, 0x014A},
+ /* #REG_0TC_PCFG_usMinFrTimeMsecMult10 */
+ {TOK_WRITE, 0x700003B4, 0x0535},
+ {TOK_WRITE, 0x700003B6, 0x029A},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_WRITE, 0x70000270, 0x0001},
+ {TOK_WRITE, 0x7000023E, 0x0001},
+ {TOK_WRITE, 0x70000240, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Configure 720x480 preview size */
+struct regval_list s5k4ecgx_720_preview[] = {
+ {TOK_WRITE, 0x70000250, 0x0A00},
+ {TOK_WRITE, 0x70000252, 0x06A8},
+ {TOK_WRITE, 0x70000254, 0x0010},
+ {TOK_WRITE, 0x70000256, 0x0078},
+ {TOK_WRITE, 0x70000258, 0x0A00},
+ {TOK_WRITE, 0x7000025A, 0x06A8},
+ {TOK_WRITE, 0x7000025C, 0x0010},
+ {TOK_WRITE, 0x7000025E, 0x0078},
+ {TOK_WRITE, 0x70000494, 0x0A00},
+ {TOK_WRITE, 0x70000496, 0x06A8},
+ {TOK_WRITE, 0x70000498, 0x0000},
+ {TOK_WRITE, 0x7000049A, 0x0000},
+ {TOK_WRITE, 0x7000049C, 0x0A00},
+ {TOK_WRITE, 0x7000049E, 0x06A8},
+ {TOK_WRITE, 0x700004A0, 0x0000},
+ {TOK_WRITE, 0x700004A2, 0x0000},
+ {TOK_WRITE, 0x70000262, 0x0001},
+ /* #REG_TC_GP_bUseReqInputInPre */
+ {TOK_WRITE, 0x70000A1E, 0x0028},
+ {TOK_WRITE, 0x70000AD4, 0x003C},
+ {TOK_WRITE, 0x700002A6, 0x02D0},
+ {TOK_WRITE, 0x700002A8, 0x01E0},
+ {TOK_WRITE, 0x700002AA, 0x0005},
+ {TOK_WRITE, 0x700002B4, 0x0052},
+ {TOK_WRITE, 0x700002BE, 0x0000},
+ {TOK_WRITE, 0x700002C0, 0x0001},
+ {TOK_WRITE, 0x700002C2, 0x029A},
+ {TOK_WRITE, 0x700002C4, 0x014D},
+ {TOK_WRITE, 0x700002D0, 0x0000},
+ {TOK_WRITE, 0x700002D2, 0x0000},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Configure 640x480 preview size */
+struct regval_list s5k4ecgx_640_preview[] = {
+ {TOK_WRITE, 0x70000250, 0x0A00},
+ {TOK_WRITE, 0x70000252, 0x0780},
+ {TOK_WRITE, 0x70000254, 0x0010},
+ {TOK_WRITE, 0x70000256, 0x000C},
+ {TOK_WRITE, 0x70000258, 0x0A00},
+ {TOK_WRITE, 0x7000025A, 0x0780},
+ {TOK_WRITE, 0x7000025C, 0x0010},
+ {TOK_WRITE, 0x7000025E, 0x000C},
+ {TOK_WRITE, 0x70000494, 0x0A00},
+ {TOK_WRITE, 0x70000496, 0x0780},
+ {TOK_WRITE, 0x70000498, 0x0000},
+ {TOK_WRITE, 0x7000049A, 0x0000},
+ {TOK_WRITE, 0x7000049C, 0x0A00},
+ {TOK_WRITE, 0x7000049E, 0x0780},
+ {TOK_WRITE, 0x700004A0, 0x0000},
+ {TOK_WRITE, 0x700004A2, 0x0000},
+ {TOK_WRITE, 0x70000262, 0x0001},
+ {TOK_WRITE, 0x70000A1E, 0x0028},
+ {TOK_WRITE, 0x70000AD4, 0x003C},
+ {TOK_WRITE, 0x700002A6, 0x0280},
+ {TOK_WRITE, 0x700002A8, 0x01E0},
+ {TOK_WRITE, 0x700002AA, 0x0005},
+ {TOK_WRITE, 0x700002B4, 0x0052},
+ {TOK_WRITE, 0x700002BE, 0x0000},
+ {TOK_WRITE, 0x700002C0, 0x0001},
+ {TOK_WRITE, 0x700002C2, 0x029A},
+ {TOK_WRITE, 0x700002C4, 0x014A},
+ {TOK_WRITE, 0x700002D0, 0x0000},
+ {TOK_WRITE, 0x700002D2, 0x0000},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Configure 352x288 preview size */
+struct regval_list s5k4ecgx_352_preview[] = {
+ {TOK_WRITE, 0x70000250, 0x0928},
+ {TOK_WRITE, 0x70000252, 0x0780},
+ {TOK_WRITE, 0x70000254, 0x007C},
+ {TOK_WRITE, 0x70000256, 0x000C},
+ {TOK_WRITE, 0x70000258, 0x0928},
+ {TOK_WRITE, 0x7000025A, 0x0780},
+ {TOK_WRITE, 0x7000025C, 0x007C},
+ {TOK_WRITE, 0x7000025E, 0x000C},
+ {TOK_WRITE, 0x70000494, 0x0928},
+ {TOK_WRITE, 0x70000496, 0x0780},
+ {TOK_WRITE, 0x70000498, 0x0000},
+ {TOK_WRITE, 0x7000049A, 0x0000},
+ {TOK_WRITE, 0x7000049C, 0x0928},
+ {TOK_WRITE, 0x7000049E, 0x0780},
+ {TOK_WRITE, 0x700004A0, 0x0000},
+ {TOK_WRITE, 0x700004A2, 0x0000},
+ {TOK_WRITE, 0x70000262, 0x0001},
+ {TOK_WRITE, 0x70000A1E, 0x0028},
+ {TOK_WRITE, 0x70000AD4, 0x003C},
+ {TOK_WRITE, 0x700002A6, 0x0160},
+ {TOK_WRITE, 0x700002A8, 0x0120},
+ {TOK_WRITE, 0x700002AA, 0x0005},
+ {TOK_WRITE, 0x700002B4, 0x0052},
+ {TOK_WRITE, 0x700002BE, 0x0000},
+ {TOK_WRITE, 0x700002C0, 0x0001},
+ {TOK_WRITE, 0x700002C2, 0x029A},
+ {TOK_WRITE, 0x700002C4, 0x014D},
+ {TOK_WRITE, 0x700002D0, 0x0000},
+ {TOK_WRITE, 0x700002D2, 0x0000},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Configure 176x144 preview size */
+struct regval_list s5k4ecgx_176_preview[] = {
+ {TOK_WRITE, 0x70000250, 0x0928},
+ {TOK_WRITE, 0x70000252, 0x0780},
+ {TOK_WRITE, 0x70000254, 0x007C},
+ {TOK_WRITE, 0x70000256, 0x000C},
+ {TOK_WRITE, 0x70000258, 0x0928},
+ {TOK_WRITE, 0x7000025A, 0x0780},
+ {TOK_WRITE, 0x7000025C, 0x007C},
+ {TOK_WRITE, 0x7000025E, 0x000C},
+ {TOK_WRITE, 0x70000494, 0x0928},
+ {TOK_WRITE, 0x70000496, 0x0780},
+ {TOK_WRITE, 0x70000498, 0x0000},
+ {TOK_WRITE, 0x7000049A, 0x0000},
+ {TOK_WRITE, 0x7000049C, 0x0928},
+ {TOK_WRITE, 0x7000049E, 0x0780},
+ {TOK_WRITE, 0x700004A0, 0x0000},
+ {TOK_WRITE, 0x700004A2, 0x0000},
+ {TOK_WRITE, 0x70000262, 0x0001},
+ {TOK_WRITE, 0x70000A1E, 0x0028},
+ {TOK_WRITE, 0x70000AD4, 0x003C},
+ {TOK_WRITE, 0x700002A6, 0x00B0},
+ {TOK_WRITE, 0x700002A8, 0x0090},
+ {TOK_WRITE, 0x700002AA, 0x0005},
+ {TOK_WRITE, 0x700002B4, 0x0052},
+ {TOK_WRITE, 0x700002BE, 0x0000},
+ {TOK_WRITE, 0x700002C0, 0x0001},
+ {TOK_WRITE, 0x700002C2, 0x029A},
+ {TOK_WRITE, 0x700002C4, 0x014D},
+ {TOK_WRITE, 0x700002D0, 0x0000},
+ {TOK_WRITE, 0x700002D2, 0x0000},
+ {TOK_WRITE, 0x70000266, 0x0000},
+ {TOK_WRITE, 0x7000026A, 0x0001},
+ {TOK_WRITE, 0x7000024E, 0x0001},
+ {TOK_WRITE, 0x70000268, 0x0001},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Default value for brightness */
+struct regval_list s5k4ecgx_ev_default[] = {
+ {TOK_WRITE, 0x70000230, 0x0000},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Default value for saturation */
+struct regval_list s5k4ecgx_saturation_default[] = {
+ {TOK_WRITE, 0x70000234, 0x0000},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+/* Default value for sharpness */
+struct regval_list s5k4ecgx_sharpness_default[] = {
+ {TOK_WRITE, 0x70000A28, 0x6024},
+ {TOK_WRITE, 0x70000ADE, 0x6024},
+ {TOK_WRITE, 0x70000B94, 0x6024},
+ {TOK_WRITE, 0x70000C4A, 0x6024},
+ {TOK_WRITE, 0x70000D00, 0x6024},
+ {TOK_TERM, 0xFFFFFFFF, 0x0},
+};
+
+#endif /* __DRIVERS_MEDIA_VIDEO_S5K4ECGX_H__ */
diff --git a/drivers/media/video/s5k4ecgx_regs_1_0.h b/drivers/media/video/s5k4ecgx_regs_1_0.h
new file mode 100755
index 00000000000..8135e672224
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_0.h
@@ -0,0 +1,4460 @@
+/* drivers/media/video/s5k4ecgx_regs_1_0.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.0
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ * Copyright (C) 2012, Insignal Co,. Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5k4ecgx_regset.h"
+
+#if !defined(__S5K4ECGX_V1_0_DEFINE_REGSET__)
+
+#define S5K4ECGX_DEFINE_REGSET(NAME) static const struct s5k4ecgx_reg NAME[]
+#define S5K4ECGX_REGSET_END \
+ { .type = S5K4ECGX_REGTYPE_END, .data_len = 0 }
+#define S5K4ECGX_CMD_WRITE(ADDR, DATA) \
+ { .type = S5K4ECGX_REGTYPE_CMD, .data_len = 4 }
+#define S5K4ECGX_REG_WRITE(ADDR, DATA) \
+ { .type = S5K4ECGX_REGTYPE_WRITE, .data_len = 2, { .addr = ADDR } }
+#define S5K4ECGX_REG_READ(ADDR) \
+ { .type = S5K4ECGX_REGTYPE_READ, .data_len = 1, { .addr = ADDR } }
+#define S5K4ECGX_MDELAY(MSEC) \
+ { .type = S5K4ECGX_REGTYPE_DELAY, .data_len = 1, { .msec = MSEC } }
+
+#elif !defined(__S5K4ECGX_V1_0_DEFINE_REGSET_DATA__)
+
+#define _SWAB16(X) ((X >> 8) & 0xFF), (X & 0xFF)
+#define _DUMMY 0
+#define S5K4ECGX_DEFINE_REGSET(NAME) static const u8 NAME##_data[]
+#define S5K4ECGX_REGSET_END
+#define S5K4ECGX_CMD_WRITE(ADDR, DATA) _SWAB16(ADDR), _SWAB16(DATA)
+#define S5K4ECGX_REG_WRITE(ADDR, DATA) _SWAB16(DATA)
+#define S5K4ECGX_REG_READ(ADDR) _DUMMY
+#define S5K4ECGX_MDELAY(MSEC) _DUMMY
+
+#endif
+
+#if !defined(__S5K4ECGX_V1_0_DEFINE_REGSET__) \
+ || !defined(__S5K4ECGX_V1_0_DEFINE_REGSET_DATA__)
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_init_reg_v1) = {
+ /* direct addressing, hw addresses */
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_CMD_WRITE(0x0004, 0x0000),
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_CMD_WRITE(0x0010, 0x0001),
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_CMD_WRITE(0x1030, 0x0000),
+ S5K4ECGX_CMD_WRITE(0x0014, 0x0001),
+
+ S5K4ECGX_MDELAY(10),
+
+ /* start analog settings, indirect addressing mode */
+
+ S5K4ECGX_REG_WRITE(0xD000007A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0xD000E406, 0x0092),
+
+ S5K4ECGX_REG_WRITE(0xD000E410, 0x3804),
+
+ S5K4ECGX_REG_WRITE(0xD000E420, 0x0003),
+ S5K4ECGX_REG_WRITE(0xD000E422, 0x0060),
+
+ S5K4ECGX_REG_WRITE(0xD000E42E, 0x0004),
+
+ S5K4ECGX_REG_WRITE(0xD000F400, 0x5A3C),
+ S5K4ECGX_REG_WRITE(0xD000F402, 0x0023),
+ S5K4ECGX_REG_WRITE(0xD000F404, 0x8080),
+ S5K4ECGX_REG_WRITE(0xD000F406, 0x03AF),
+ S5K4ECGX_REG_WRITE(0xD000F408, 0x000A),
+ S5K4ECGX_REG_WRITE(0xD000F40A, 0xAA54),
+ S5K4ECGX_REG_WRITE(0xD000F40C, 0x0040),
+ S5K4ECGX_REG_WRITE(0xD000F40E, 0x464E),
+ S5K4ECGX_REG_WRITE(0xD000F410, 0x0240),
+ S5K4ECGX_REG_WRITE(0xD000F412, 0x0240),
+ S5K4ECGX_REG_WRITE(0xD000F414, 0x0040),
+ S5K4ECGX_REG_WRITE(0xD000F416, 0x1000),
+ S5K4ECGX_REG_WRITE(0xD000F418, 0x5558),
+ S5K4ECGX_REG_WRITE(0xD000F41A, 0xD000),
+ S5K4ECGX_REG_WRITE(0xD000F41C, 0x0010),
+ S5K4ECGX_REG_WRITE(0xD000F41E, 0x0202),
+ S5K4ECGX_REG_WRITE(0xD000F420, 0x0401),
+ S5K4ECGX_REG_WRITE(0xD000F422, 0x0022),
+ S5K4ECGX_REG_WRITE(0xD000F424, 0x0088),
+ S5K4ECGX_REG_WRITE(0xD000F426, 0x009F),
+ S5K4ECGX_REG_WRITE(0xD000F428, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F42A, 0x1800),
+ S5K4ECGX_REG_WRITE(0xD000F42C, 0x0088),
+ S5K4ECGX_REG_WRITE(0xD000F42E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F430, 0x2428),
+ S5K4ECGX_REG_WRITE(0xD000F432, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F434, 0x03EE),
+ S5K4ECGX_REG_WRITE(0xD000F436, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F438, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F43A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0xD000F480, 0x0004),
+ S5K4ECGX_REG_WRITE(0xD000F482, 0x05B6),
+ S5K4ECGX_REG_WRITE(0xD000F484, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F486, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F488, 0x0001),
+ S5K4ECGX_REG_WRITE(0xD000F48A, 0x05BA),
+ S5K4ECGX_REG_WRITE(0xD000F48C, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F48E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F490, 0x0007),
+ S5K4ECGX_REG_WRITE(0xD000F492, 0x05BA),
+ S5K4ECGX_REG_WRITE(0xD000F494, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F496, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F498, 0x01F4),
+ S5K4ECGX_REG_WRITE(0xD000F49A, 0x024E),
+ S5K4ECGX_REG_WRITE(0xD000F49C, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F49E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4A0, 0x01F4),
+ S5K4ECGX_REG_WRITE(0xD000F4A2, 0x05B6),
+ S5K4ECGX_REG_WRITE(0xD000F4A4, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4A6, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4A8, 0x01F4),
+ S5K4ECGX_REG_WRITE(0xD000F4AA, 0x05BA),
+ S5K4ECGX_REG_WRITE(0xD000F4AC, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4AE, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4B0, 0x01F4),
+ S5K4ECGX_REG_WRITE(0xD000F4B2, 0x024F),
+ S5K4ECGX_REG_WRITE(0xD000F4B4, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4B6, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4BC, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4C0, 0x0075),
+ S5K4ECGX_REG_WRITE(0xD000F4C2, 0x00CF),
+ S5K4ECGX_REG_WRITE(0xD000F4C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4C8, 0x0075),
+ S5K4ECGX_REG_WRITE(0xD000F4CA, 0x00D6),
+ S5K4ECGX_REG_WRITE(0xD000F4CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4D0, 0x0004),
+ S5K4ECGX_REG_WRITE(0xD000F4D2, 0x01F4),
+ S5K4ECGX_REG_WRITE(0xD000F4D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4D8, 0x00F0),
+ S5K4ECGX_REG_WRITE(0xD000F4DA, 0x01F4),
+ S5K4ECGX_REG_WRITE(0xD000F4DC, 0x029E),
+ S5K4ECGX_REG_WRITE(0xD000F4DE, 0x05B2),
+ S5K4ECGX_REG_WRITE(0xD000F4E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4E4, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4E6, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4E8, 0x01F8),
+ S5K4ECGX_REG_WRITE(0xD000F4EA, 0x0228),
+ S5K4ECGX_REG_WRITE(0xD000F4EC, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4F4, 0x0208),
+ S5K4ECGX_REG_WRITE(0xD000F4F6, 0x0238),
+ S5K4ECGX_REG_WRITE(0xD000F4F8, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F4FC, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0xD000F590, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0xD000F500, 0x0218),
+ S5K4ECGX_REG_WRITE(0xD000F502, 0x0238),
+ S5K4ECGX_REG_WRITE(0xD000F504, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F506, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F508, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F50A, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F50C, 0x0001),
+ S5K4ECGX_REG_WRITE(0xD000F50E, 0x0009),
+ S5K4ECGX_REG_WRITE(0xD000F510, 0x00DE),
+ S5K4ECGX_REG_WRITE(0xD000F512, 0x05C0),
+ S5K4ECGX_REG_WRITE(0xD000F514, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F516, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F518, 0x00DF),
+ S5K4ECGX_REG_WRITE(0xD000F51A, 0x00E4),
+ S5K4ECGX_REG_WRITE(0xD000F51C, 0x01F8),
+ S5K4ECGX_REG_WRITE(0xD000F51E, 0x01FD),
+ S5K4ECGX_REG_WRITE(0xD000F520, 0x05B6),
+ S5K4ECGX_REG_WRITE(0xD000F522, 0x05BB),
+ S5K4ECGX_REG_WRITE(0xD000F524, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F526, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F528, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F52A, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F52C, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F52E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F530, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F532, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F534, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F536, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F538, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F53A, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F53C, 0x01F8),
+ S5K4ECGX_REG_WRITE(0xD000F53E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F540, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F542, 0x0077),
+ S5K4ECGX_REG_WRITE(0xD000F544, 0x007E),
+ S5K4ECGX_REG_WRITE(0xD000F546, 0x024F),
+ S5K4ECGX_REG_WRITE(0xD000F548, 0x025E),
+ S5K4ECGX_REG_WRITE(0xD000F54A, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F54C, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F54E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F550, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F552, 0x0708),
+ S5K4ECGX_REG_WRITE(0xD000F554, 0x080C),
+
+ S5K4ECGX_REG_WRITE(0xD0001082, 0x5555),
+ S5K4ECGX_REG_WRITE(0xD0001084, 0x5555),
+
+ S5K4ECGX_REG_WRITE(0xD0001088, 0x055D),
+
+ S5K4ECGX_REG_WRITE(0xD000100E, 0x0000),
+
+ /* switch to sw address bank */
+
+ S5K4ECGX_REG_WRITE(0x70000716, 0x0100),
+
+ /* Start of Patch Data for firmware */
+ S5K4ECGX_REG_WRITE(0x70003A10, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003A12, 0x4A3E),
+ S5K4ECGX_REG_WRITE(0x70003A14, 0x493E),
+ S5K4ECGX_REG_WRITE(0x70003A16, 0x483F),
+ S5K4ECGX_REG_WRITE(0x70003A18, 0xC004),
+ S5K4ECGX_REG_WRITE(0x70003A1A, 0x6001),
+ S5K4ECGX_REG_WRITE(0x70003A1C, 0x4C3E),
+ S5K4ECGX_REG_WRITE(0x70003A1E, 0x2500),
+ S5K4ECGX_REG_WRITE(0x70003A20, 0x8265),
+ S5K4ECGX_REG_WRITE(0x70003A22, 0x8025),
+ S5K4ECGX_REG_WRITE(0x70003A24, 0x493D),
+ S5K4ECGX_REG_WRITE(0x70003A26, 0x483E),
+ S5K4ECGX_REG_WRITE(0x70003A28, 0x2701),
+ S5K4ECGX_REG_WRITE(0x70003A2A, 0x002A),
+ S5K4ECGX_REG_WRITE(0x70003A2C, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A2E, 0xFC38),
+ S5K4ECGX_REG_WRITE(0x70003A30, 0x493C),
+ S5K4ECGX_REG_WRITE(0x70003A32, 0x483D),
+ S5K4ECGX_REG_WRITE(0x70003A34, 0x2602),
+ S5K4ECGX_REG_WRITE(0x70003A36, 0x003A),
+ S5K4ECGX_REG_WRITE(0x70003A38, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A3A, 0xFC32),
+ S5K4ECGX_REG_WRITE(0x70003A3C, 0x493B),
+ S5K4ECGX_REG_WRITE(0x70003A3E, 0x483C),
+ S5K4ECGX_REG_WRITE(0x70003A40, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70003A42, 0x2703),
+ S5K4ECGX_REG_WRITE(0x70003A44, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A46, 0xFC2C),
+ S5K4ECGX_REG_WRITE(0x70003A48, 0x8225),
+ S5K4ECGX_REG_WRITE(0x70003A4A, 0x493A),
+ S5K4ECGX_REG_WRITE(0x70003A4C, 0x483A),
+ S5K4ECGX_REG_WRITE(0x70003A4E, 0x2604),
+ S5K4ECGX_REG_WRITE(0x70003A50, 0x003A),
+ S5K4ECGX_REG_WRITE(0x70003A52, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A54, 0xFC25),
+ S5K4ECGX_REG_WRITE(0x70003A56, 0x200E),
+ S5K4ECGX_REG_WRITE(0x70003A58, 0x8420),
+ S5K4ECGX_REG_WRITE(0x70003A5A, 0x2701),
+ S5K4ECGX_REG_WRITE(0x70003A5C, 0x83E7),
+ S5K4ECGX_REG_WRITE(0x70003A5E, 0x4937),
+ S5K4ECGX_REG_WRITE(0x70003A60, 0x4837),
+ S5K4ECGX_REG_WRITE(0x70003A62, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70003A64, 0x2405),
+ S5K4ECGX_REG_WRITE(0x70003A66, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A68, 0xFC1B),
+ S5K4ECGX_REG_WRITE(0x70003A6A, 0x4936),
+ S5K4ECGX_REG_WRITE(0x70003A6C, 0x4836),
+ S5K4ECGX_REG_WRITE(0x70003A6E, 0x2606),
+ S5K4ECGX_REG_WRITE(0x70003A70, 0x0022),
+ S5K4ECGX_REG_WRITE(0x70003A72, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A74, 0xFC15),
+ S5K4ECGX_REG_WRITE(0x70003A76, 0x4C28),
+ S5K4ECGX_REG_WRITE(0x70003A78, 0x3460),
+ S5K4ECGX_REG_WRITE(0x70003A7A, 0x81E7),
+ S5K4ECGX_REG_WRITE(0x70003A7C, 0x4825),
+ S5K4ECGX_REG_WRITE(0x70003A7E, 0x3824),
+ S5K4ECGX_REG_WRITE(0x70003A80, 0x86C5),
+ S5K4ECGX_REG_WRITE(0x70003A82, 0x4932),
+ S5K4ECGX_REG_WRITE(0x70003A84, 0x4832),
+ S5K4ECGX_REG_WRITE(0x70003A86, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70003A88, 0x2707),
+ S5K4ECGX_REG_WRITE(0x70003A8A, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A8C, 0xFC09),
+ S5K4ECGX_REG_WRITE(0x70003A8E, 0x4931),
+ S5K4ECGX_REG_WRITE(0x70003A90, 0x4831),
+ S5K4ECGX_REG_WRITE(0x70003A92, 0x2608),
+ S5K4ECGX_REG_WRITE(0x70003A94, 0x003A),
+ S5K4ECGX_REG_WRITE(0x70003A96, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003A98, 0xFC03),
+ S5K4ECGX_REG_WRITE(0x70003A9A, 0x4930),
+ S5K4ECGX_REG_WRITE(0x70003A9C, 0x4830),
+ S5K4ECGX_REG_WRITE(0x70003A9E, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70003AA0, 0x2709),
+ S5K4ECGX_REG_WRITE(0x70003AA2, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003AA4, 0xFBFD),
+ S5K4ECGX_REG_WRITE(0x70003AA6, 0x2005),
+ S5K4ECGX_REG_WRITE(0x70003AA8, 0x8160),
+ S5K4ECGX_REG_WRITE(0x70003AAA, 0x492E),
+ S5K4ECGX_REG_WRITE(0x70003AAC, 0x482E),
+ S5K4ECGX_REG_WRITE(0x70003AAE, 0x6281),
+ S5K4ECGX_REG_WRITE(0x70003AB0, 0x8225),
+ S5K4ECGX_REG_WRITE(0x70003AB2, 0x8265),
+ S5K4ECGX_REG_WRITE(0x70003AB4, 0x482D),
+ S5K4ECGX_REG_WRITE(0x70003AB6, 0x8320),
+ S5K4ECGX_REG_WRITE(0x70003AB8, 0x482D),
+ S5K4ECGX_REG_WRITE(0x70003ABA, 0x8360),
+ S5K4ECGX_REG_WRITE(0x70003ABC, 0x0270),
+ S5K4ECGX_REG_WRITE(0x70003ABE, 0x83A0),
+ S5K4ECGX_REG_WRITE(0x70003AC0, 0x2005),
+ S5K4ECGX_REG_WRITE(0x70003AC2, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70003AC4, 0x83E0),
+ S5K4ECGX_REG_WRITE(0x70003AC6, 0x4828),
+ S5K4ECGX_REG_WRITE(0x70003AC8, 0x492A),
+ S5K4ECGX_REG_WRITE(0x70003ACA, 0x3840),
+ S5K4ECGX_REG_WRITE(0x70003ACC, 0x6001),
+ S5K4ECGX_REG_WRITE(0x70003ACE, 0x492A),
+ S5K4ECGX_REG_WRITE(0x70003AD0, 0x482A),
+ S5K4ECGX_REG_WRITE(0x70003AD2, 0x240A),
+ S5K4ECGX_REG_WRITE(0x70003AD4, 0x003A),
+ S5K4ECGX_REG_WRITE(0x70003AD6, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003AD8, 0xFBE3),
+ S5K4ECGX_REG_WRITE(0x70003ADA, 0x4929),
+ S5K4ECGX_REG_WRITE(0x70003ADC, 0x4829),
+ S5K4ECGX_REG_WRITE(0x70003ADE, 0x0022),
+ S5K4ECGX_REG_WRITE(0x70003AE0, 0x250B),
+ S5K4ECGX_REG_WRITE(0x70003AE2, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003AE4, 0xFBDD),
+ S5K4ECGX_REG_WRITE(0x70003AE6, 0x4820),
+ S5K4ECGX_REG_WRITE(0x70003AE8, 0x4927),
+ S5K4ECGX_REG_WRITE(0x70003AEA, 0x3080),
+ S5K4ECGX_REG_WRITE(0x70003AEC, 0x6381),
+ S5K4ECGX_REG_WRITE(0x70003AEE, 0x4927),
+ S5K4ECGX_REG_WRITE(0x70003AF0, 0x4827),
+ S5K4ECGX_REG_WRITE(0x70003AF2, 0x240C),
+ S5K4ECGX_REG_WRITE(0x70003AF4, 0x002A),
+ S5K4ECGX_REG_WRITE(0x70003AF6, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003AF8, 0xFBD3),
+ S5K4ECGX_REG_WRITE(0x70003AFA, 0x4926),
+ S5K4ECGX_REG_WRITE(0x70003AFC, 0x4826),
+ S5K4ECGX_REG_WRITE(0x70003AFE, 0x0022),
+ S5K4ECGX_REG_WRITE(0x70003B00, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003B02, 0xFBCE),
+ S5K4ECGX_REG_WRITE(0x70003B04, 0xBCF8),
+ S5K4ECGX_REG_WRITE(0x70003B06, 0xBC08),
+ S5K4ECGX_REG_WRITE(0x70003B08, 0x4718),
+ S5K4ECGX_REG_WRITE(0x70003B0A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B0C, 0x0174),
+ S5K4ECGX_REG_WRITE(0x70003B0E, 0x4EC1),
+ S5K4ECGX_REG_WRITE(0x70003B10, 0xFFFE),
+ S5K4ECGX_REG_WRITE(0x70003B12, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B14, 0x1EF0),
+ S5K4ECGX_REG_WRITE(0x70003B16, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B18, 0x4780),
+ S5K4ECGX_REG_WRITE(0x70003B1A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B1C, 0x3BF3),
+ S5K4ECGX_REG_WRITE(0x70003B1E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B20, 0xA1D9),
+ S5K4ECGX_REG_WRITE(0x70003B22, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B24, 0x3B9D),
+ S5K4ECGX_REG_WRITE(0x70003B26, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B28, 0xA0BD),
+ S5K4ECGX_REG_WRITE(0x70003B2A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B2C, 0x3C8D),
+ S5K4ECGX_REG_WRITE(0x70003B2E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B30, 0x217B),
+ S5K4ECGX_REG_WRITE(0x70003B32, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B34, 0x3CE9),
+ S5K4ECGX_REG_WRITE(0x70003B36, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B38, 0xE0DF),
+ S5K4ECGX_REG_WRITE(0x70003B3A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B3C, 0x3E73),
+ S5K4ECGX_REG_WRITE(0x70003B3E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B40, 0x053B),
+ S5K4ECGX_REG_WRITE(0x70003B42, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B44, 0x3D71),
+ S5K4ECGX_REG_WRITE(0x70003B46, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B48, 0x509B),
+ S5K4ECGX_REG_WRITE(0x70003B4A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B4C, 0x3FF9),
+ S5K4ECGX_REG_WRITE(0x70003B4E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B50, 0xD42F),
+ S5K4ECGX_REG_WRITE(0x70003B52, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B54, 0x3EB5),
+ S5K4ECGX_REG_WRITE(0x70003B56, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B58, 0x49D1),
+ S5K4ECGX_REG_WRITE(0x70003B5A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B5C, 0x3F4F),
+ S5K4ECGX_REG_WRITE(0x70003B5E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B60, 0x1E57),
+ S5K4ECGX_REG_WRITE(0x70003B62, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B64, 0x4033),
+ S5K4ECGX_REG_WRITE(0x70003B66, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B68, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70003B6A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B6C, 0x4E34),
+ S5K4ECGX_REG_WRITE(0x70003B6E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B70, 0x7C53),
+ S5K4ECGX_REG_WRITE(0x70003B72, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B74, 0x40BF),
+ S5K4ECGX_REG_WRITE(0x70003B76, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B78, 0x40FB),
+ S5K4ECGX_REG_WRITE(0x70003B7A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B7C, 0xF5D7),
+ S5K4ECGX_REG_WRITE(0x70003B7E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B80, 0x406F),
+ S5K4ECGX_REG_WRITE(0x70003B82, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B84, 0xBAB1),
+ S5K4ECGX_REG_WRITE(0x70003B86, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B88, 0x4187),
+ S5K4ECGX_REG_WRITE(0x70003B8A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B8C, 0x4129),
+ S5K4ECGX_REG_WRITE(0x70003B8E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B90, 0xC10D),
+ S5K4ECGX_REG_WRITE(0x70003B92, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B94, 0x4203),
+ S5K4ECGX_REG_WRITE(0x70003B96, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003B98, 0xB231),
+ S5K4ECGX_REG_WRITE(0x70003B9A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003B9C, 0xB570),
+ S5K4ECGX_REG_WRITE(0x70003B9E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70003BA0, 0x6820),
+ S5K4ECGX_REG_WRITE(0x70003BA2, 0x6865),
+ S5K4ECGX_REG_WRITE(0x70003BA4, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003BA6, 0xFB84),
+ S5K4ECGX_REG_WRITE(0x70003BA8, 0x4BFC),
+ S5K4ECGX_REG_WRITE(0x70003BAA, 0x0402),
+ S5K4ECGX_REG_WRITE(0x70003BAC, 0x0C12),
+ S5K4ECGX_REG_WRITE(0x70003BAE, 0x819A),
+ S5K4ECGX_REG_WRITE(0x70003BB0, 0x48FB),
+ S5K4ECGX_REG_WRITE(0x70003BB2, 0x89C1),
+ S5K4ECGX_REG_WRITE(0x70003BB4, 0x428A),
+ S5K4ECGX_REG_WRITE(0x70003BB6, 0xD305),
+ S5K4ECGX_REG_WRITE(0x70003BB8, 0x4AFA),
+ S5K4ECGX_REG_WRITE(0x70003BBA, 0x8986),
+ S5K4ECGX_REG_WRITE(0x70003BBC, 0x8852),
+ S5K4ECGX_REG_WRITE(0x70003BBE, 0x42B2),
+ S5K4ECGX_REG_WRITE(0x70003BC0, 0xD300),
+ S5K4ECGX_REG_WRITE(0x70003BC2, 0x8199),
+ S5K4ECGX_REG_WRITE(0x70003BC4, 0x8801),
+ S5K4ECGX_REG_WRITE(0x70003BC6, 0x2900),
+ S5K4ECGX_REG_WRITE(0x70003BC8, 0xD008),
+ S5K4ECGX_REG_WRITE(0x70003BCA, 0x49F7),
+ S5K4ECGX_REG_WRITE(0x70003BCC, 0x002B),
+ S5K4ECGX_REG_WRITE(0x70003BCE, 0x6E0A),
+ S5K4ECGX_REG_WRITE(0x70003BD0, 0x2105),
+ S5K4ECGX_REG_WRITE(0x70003BD2, 0x1C80),
+ S5K4ECGX_REG_WRITE(0x70003BD4, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003BD6, 0xFB74),
+ S5K4ECGX_REG_WRITE(0x70003BD8, 0x6020),
+ S5K4ECGX_REG_WRITE(0x70003BDA, 0xE006),
+ S5K4ECGX_REG_WRITE(0x70003BDC, 0x899A),
+ S5K4ECGX_REG_WRITE(0x70003BDE, 0x48F3),
+ S5K4ECGX_REG_WRITE(0x70003BE0, 0x002B),
+ S5K4ECGX_REG_WRITE(0x70003BE2, 0x2105),
+ S5K4ECGX_REG_WRITE(0x70003BE4, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003BE6, 0xFB6C),
+ S5K4ECGX_REG_WRITE(0x70003BE8, 0x6020),
+ S5K4ECGX_REG_WRITE(0x70003BEA, 0x6820),
+ S5K4ECGX_REG_WRITE(0x70003BEC, 0xBC70),
+ S5K4ECGX_REG_WRITE(0x70003BEE, 0xBC08),
+ S5K4ECGX_REG_WRITE(0x70003BF0, 0x4718),
+ S5K4ECGX_REG_WRITE(0x70003BF2, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003BF4, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70003BF6, 0x2000),
+ S5K4ECGX_REG_WRITE(0x70003BF8, 0x9000),
+ S5K4ECGX_REG_WRITE(0x70003BFA, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70003BFC, 0x2501),
+ S5K4ECGX_REG_WRITE(0x70003BFE, 0x3810),
+ S5K4ECGX_REG_WRITE(0x70003C00, 0x2601),
+ S5K4ECGX_REG_WRITE(0x70003C02, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x70003C04, 0x4086),
+ S5K4ECGX_REG_WRITE(0x70003C06, 0x4FEA),
+ S5K4ECGX_REG_WRITE(0x70003C08, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003C0A, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70003C0C, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70003C0E, 0x43A8),
+ S5K4ECGX_REG_WRITE(0x70003C10, 0x8038),
+ S5K4ECGX_REG_WRITE(0x70003C12, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70003C14, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70003C16, 0x43B0),
+ S5K4ECGX_REG_WRITE(0x70003C18, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70003C1A, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003C1C, 0xFB59),
+ S5K4ECGX_REG_WRITE(0x70003C1E, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003C20, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70003C22, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70003C24, 0x4328),
+ S5K4ECGX_REG_WRITE(0x70003C26, 0x8038),
+ S5K4ECGX_REG_WRITE(0x70003C28, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70003C2A, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70003C2C, 0x4330),
+ S5K4ECGX_REG_WRITE(0x70003C2E, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70003C30, 0x48DA),
+ S5K4ECGX_REG_WRITE(0x70003C32, 0x2105),
+ S5K4ECGX_REG_WRITE(0x70003C34, 0x8982),
+ S5K4ECGX_REG_WRITE(0x70003C36, 0x48DD),
+ S5K4ECGX_REG_WRITE(0x70003C38, 0x466B),
+ S5K4ECGX_REG_WRITE(0x70003C3A, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003C3C, 0xFB41),
+ S5K4ECGX_REG_WRITE(0x70003C3E, 0x1C41),
+ S5K4ECGX_REG_WRITE(0x70003C40, 0x4CD7),
+ S5K4ECGX_REG_WRITE(0x70003C42, 0x0049),
+ S5K4ECGX_REG_WRITE(0x70003C44, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70003C46, 0x1909),
+ S5K4ECGX_REG_WRITE(0x70003C48, 0x1900),
+ S5K4ECGX_REG_WRITE(0x70003C4A, 0x466B),
+ S5K4ECGX_REG_WRITE(0x70003C4C, 0x8A89),
+ S5K4ECGX_REG_WRITE(0x70003C4E, 0x8A80),
+ S5K4ECGX_REG_WRITE(0x70003C50, 0x881A),
+ S5K4ECGX_REG_WRITE(0x70003C52, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003C54, 0xFB45),
+ S5K4ECGX_REG_WRITE(0x70003C56, 0x8A61),
+ S5K4ECGX_REG_WRITE(0x70003C58, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70003C5A, 0x02C9),
+ S5K4ECGX_REG_WRITE(0x70003C5C, 0x0D40),
+ S5K4ECGX_REG_WRITE(0x70003C5E, 0x4301),
+ S5K4ECGX_REG_WRITE(0x70003C60, 0x48D4),
+ S5K4ECGX_REG_WRITE(0x70003C62, 0x8081),
+ S5K4ECGX_REG_WRITE(0x70003C64, 0x49D4),
+ S5K4ECGX_REG_WRITE(0x70003C66, 0x48D4),
+ S5K4ECGX_REG_WRITE(0x70003C68, 0x3120),
+ S5K4ECGX_REG_WRITE(0x70003C6A, 0x8BC0),
+ S5K4ECGX_REG_WRITE(0x70003C6C, 0x8809),
+ S5K4ECGX_REG_WRITE(0x70003C6E, 0x1841),
+ S5K4ECGX_REG_WRITE(0x70003C70, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70003C72, 0x3060),
+ S5K4ECGX_REG_WRITE(0x70003C74, 0x8A82),
+ S5K4ECGX_REG_WRITE(0x70003C76, 0x4291),
+ S5K4ECGX_REG_WRITE(0x70003C78, 0xD205),
+ S5K4ECGX_REG_WRITE(0x70003C7A, 0x8AC0),
+ S5K4ECGX_REG_WRITE(0x70003C7C, 0x49CF),
+ S5K4ECGX_REG_WRITE(0x70003C7E, 0x7388),
+ S5K4ECGX_REG_WRITE(0x70003C80, 0x2001),
+ S5K4ECGX_REG_WRITE(0x70003C82, 0x31A0),
+ S5K4ECGX_REG_WRITE(0x70003C84, 0x70C8),
+ S5K4ECGX_REG_WRITE(0x70003C86, 0xBCF8),
+ S5K4ECGX_REG_WRITE(0x70003C88, 0xBC08),
+ S5K4ECGX_REG_WRITE(0x70003C8A, 0x4718),
+ S5K4ECGX_REG_WRITE(0x70003C8C, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003C8E, 0x48C6),
+ S5K4ECGX_REG_WRITE(0x70003C90, 0x2200),
+ S5K4ECGX_REG_WRITE(0x70003C92, 0x30A0),
+ S5K4ECGX_REG_WRITE(0x70003C94, 0x81C2),
+ S5K4ECGX_REG_WRITE(0x70003C96, 0x6808),
+ S5K4ECGX_REG_WRITE(0x70003C98, 0x4669),
+ S5K4ECGX_REG_WRITE(0x70003C9A, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003C9C, 0xFB29),
+ S5K4ECGX_REG_WRITE(0x70003C9E, 0x466B),
+ S5K4ECGX_REG_WRITE(0x70003CA0, 0x8818),
+ S5K4ECGX_REG_WRITE(0x70003CA2, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003CA4, 0xFB2D),
+ S5K4ECGX_REG_WRITE(0x70003CA6, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70003CA8, 0x466B),
+ S5K4ECGX_REG_WRITE(0x70003CAA, 0x8858),
+ S5K4ECGX_REG_WRITE(0x70003CAC, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003CAE, 0xFB30),
+ S5K4ECGX_REG_WRITE(0x70003CB0, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70003CB2, 0x2101),
+ S5K4ECGX_REG_WRITE(0x70003CB4, 0x1928),
+ S5K4ECGX_REG_WRITE(0x70003CB6, 0x02C9),
+ S5K4ECGX_REG_WRITE(0x70003CB8, 0x1A08),
+ S5K4ECGX_REG_WRITE(0x70003CBA, 0x0286),
+ S5K4ECGX_REG_WRITE(0x70003CBC, 0x0029),
+ S5K4ECGX_REG_WRITE(0x70003CBE, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70003CC0, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003CC2, 0xFB2E),
+ S5K4ECGX_REG_WRITE(0x70003CC4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70003CC6, 0x2701),
+ S5K4ECGX_REG_WRITE(0x70003CC8, 0x02BF),
+ S5K4ECGX_REG_WRITE(0x70003CCA, 0x0021),
+ S5K4ECGX_REG_WRITE(0x70003CCC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70003CCE, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003CD0, 0xFB27),
+ S5K4ECGX_REG_WRITE(0x70003CD2, 0x49B5),
+ S5K4ECGX_REG_WRITE(0x70003CD4, 0x4AB8),
+ S5K4ECGX_REG_WRITE(0x70003CD6, 0x3140),
+ S5K4ECGX_REG_WRITE(0x70003CD8, 0x3220),
+ S5K4ECGX_REG_WRITE(0x70003CDA, 0x808D),
+ S5K4ECGX_REG_WRITE(0x70003CDC, 0x8295),
+ S5K4ECGX_REG_WRITE(0x70003CDE, 0x80CF),
+ S5K4ECGX_REG_WRITE(0x70003CE0, 0x82D7),
+ S5K4ECGX_REG_WRITE(0x70003CE2, 0x8108),
+ S5K4ECGX_REG_WRITE(0x70003CE4, 0x8310),
+ S5K4ECGX_REG_WRITE(0x70003CE6, 0xE7CE),
+ S5K4ECGX_REG_WRITE(0x70003CE8, 0x6808),
+ S5K4ECGX_REG_WRITE(0x70003CEA, 0x0400),
+ S5K4ECGX_REG_WRITE(0x70003CEC, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x70003CEE, 0x6849),
+ S5K4ECGX_REG_WRITE(0x70003CF0, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70003CF2, 0x0C09),
+ S5K4ECGX_REG_WRITE(0x70003CF4, 0x4AAA),
+ S5K4ECGX_REG_WRITE(0x70003CF6, 0x8A12),
+ S5K4ECGX_REG_WRITE(0x70003CF8, 0x2A00),
+ S5K4ECGX_REG_WRITE(0x70003CFA, 0xD00D),
+ S5K4ECGX_REG_WRITE(0x70003CFC, 0x2300),
+ S5K4ECGX_REG_WRITE(0x70003CFE, 0x1A89),
+ S5K4ECGX_REG_WRITE(0x70003D00, 0xD400),
+ S5K4ECGX_REG_WRITE(0x70003D02, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70003D04, 0x0419),
+ S5K4ECGX_REG_WRITE(0x70003D06, 0x0C09),
+ S5K4ECGX_REG_WRITE(0x70003D08, 0x23FF),
+ S5K4ECGX_REG_WRITE(0x70003D0A, 0x33C1),
+ S5K4ECGX_REG_WRITE(0x70003D0C, 0x1810),
+ S5K4ECGX_REG_WRITE(0x70003D0E, 0x4298),
+ S5K4ECGX_REG_WRITE(0x70003D10, 0xD800),
+ S5K4ECGX_REG_WRITE(0x70003D12, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70003D14, 0x0418),
+ S5K4ECGX_REG_WRITE(0x70003D16, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x70003D18, 0x4AA9),
+ S5K4ECGX_REG_WRITE(0x70003D1A, 0x8150),
+ S5K4ECGX_REG_WRITE(0x70003D1C, 0x8191),
+ S5K4ECGX_REG_WRITE(0x70003D1E, 0x4770),
+ S5K4ECGX_REG_WRITE(0x70003D20, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003D22, 0x2400),
+ S5K4ECGX_REG_WRITE(0x70003D24, 0x4DA7),
+ S5K4ECGX_REG_WRITE(0x70003D26, 0x4F9E),
+ S5K4ECGX_REG_WRITE(0x70003D28, 0x48A7),
+ S5K4ECGX_REG_WRITE(0x70003D2A, 0x8C39),
+ S5K4ECGX_REG_WRITE(0x70003D2C, 0x8041),
+ S5K4ECGX_REG_WRITE(0x70003D2E, 0x2101),
+ S5K4ECGX_REG_WRITE(0x70003D30, 0x8001),
+ S5K4ECGX_REG_WRITE(0x70003D32, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003D34, 0xFAFB),
+ S5K4ECGX_REG_WRITE(0x70003D36, 0x48A5),
+ S5K4ECGX_REG_WRITE(0x70003D38, 0x8BC0),
+ S5K4ECGX_REG_WRITE(0x70003D3A, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003D3C, 0xFAFF),
+ S5K4ECGX_REG_WRITE(0x70003D3E, 0x260D),
+ S5K4ECGX_REG_WRITE(0x70003D40, 0x0736),
+ S5K4ECGX_REG_WRITE(0x70003D42, 0x2000),
+ S5K4ECGX_REG_WRITE(0x70003D44, 0x00E1),
+ S5K4ECGX_REG_WRITE(0x70003D46, 0x19CA),
+ S5K4ECGX_REG_WRITE(0x70003D48, 0x0041),
+ S5K4ECGX_REG_WRITE(0x70003D4A, 0x194B),
+ S5K4ECGX_REG_WRITE(0x70003D4C, 0x199B),
+ S5K4ECGX_REG_WRITE(0x70003D4E, 0x881B),
+ S5K4ECGX_REG_WRITE(0x70003D50, 0x1851),
+ S5K4ECGX_REG_WRITE(0x70003D52, 0x844B),
+ S5K4ECGX_REG_WRITE(0x70003D54, 0x1C40),
+ S5K4ECGX_REG_WRITE(0x70003D56, 0x0400),
+ S5K4ECGX_REG_WRITE(0x70003D58, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x70003D5A, 0x2804),
+ S5K4ECGX_REG_WRITE(0x70003D5C, 0xD3F4),
+ S5K4ECGX_REG_WRITE(0x70003D5E, 0x3508),
+ S5K4ECGX_REG_WRITE(0x70003D60, 0x042D),
+ S5K4ECGX_REG_WRITE(0x70003D62, 0x0C2D),
+ S5K4ECGX_REG_WRITE(0x70003D64, 0x1C64),
+ S5K4ECGX_REG_WRITE(0x70003D66, 0x0424),
+ S5K4ECGX_REG_WRITE(0x70003D68, 0x0C24),
+ S5K4ECGX_REG_WRITE(0x70003D6A, 0x2C07),
+ S5K4ECGX_REG_WRITE(0x70003D6C, 0xD3E9),
+ S5K4ECGX_REG_WRITE(0x70003D6E, 0xE78A),
+ S5K4ECGX_REG_WRITE(0x70003D70, 0xB5F0),
+ S5K4ECGX_REG_WRITE(0x70003D72, 0xB087),
+ S5K4ECGX_REG_WRITE(0x70003D74, 0x6808),
+ S5K4ECGX_REG_WRITE(0x70003D76, 0x9006),
+ S5K4ECGX_REG_WRITE(0x70003D78, 0x6848),
+ S5K4ECGX_REG_WRITE(0x70003D7A, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70003D7C, 0x0C2D),
+ S5K4ECGX_REG_WRITE(0x70003D7E, 0x6888),
+ S5K4ECGX_REG_WRITE(0x70003D80, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70003D82, 0x0C1B),
+ S5K4ECGX_REG_WRITE(0x70003D84, 0x4892),
+ S5K4ECGX_REG_WRITE(0x70003D86, 0x8B80),
+ S5K4ECGX_REG_WRITE(0x70003D88, 0x2800),
+ S5K4ECGX_REG_WRITE(0x70003D8A, 0xD100),
+ S5K4ECGX_REG_WRITE(0x70003D8C, 0x2300),
+ S5K4ECGX_REG_WRITE(0x70003D8E, 0x001C),
+ S5K4ECGX_REG_WRITE(0x70003D90, 0x4A90),
+ S5K4ECGX_REG_WRITE(0x70003D92, 0x466E),
+ S5K4ECGX_REG_WRITE(0x70003D94, 0x1E91),
+ S5K4ECGX_REG_WRITE(0x70003D96, 0x1E88),
+ S5K4ECGX_REG_WRITE(0x70003D98, 0xC607),
+ S5K4ECGX_REG_WRITE(0x70003D9A, 0x498F),
+ S5K4ECGX_REG_WRITE(0x70003D9C, 0x0023),
+ S5K4ECGX_REG_WRITE(0x70003D9E, 0x2207),
+ S5K4ECGX_REG_WRITE(0x70003DA0, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70003DA2, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003DA4, 0xFAD3),
+ S5K4ECGX_REG_WRITE(0x70003DA6, 0x487E),
+ S5K4ECGX_REG_WRITE(0x70003DA8, 0x8BC1),
+ S5K4ECGX_REG_WRITE(0x70003DAA, 0x2900),
+ S5K4ECGX_REG_WRITE(0x70003DAC, 0xD030),
+ S5K4ECGX_REG_WRITE(0x70003DAE, 0x2100),
+ S5K4ECGX_REG_WRITE(0x70003DB0, 0x4888),
+ S5K4ECGX_REG_WRITE(0x70003DB2, 0x4A7B),
+ S5K4ECGX_REG_WRITE(0x70003DB4, 0x380A),
+ S5K4ECGX_REG_WRITE(0x70003DB6, 0x88C0),
+ S5K4ECGX_REG_WRITE(0x70003DB8, 0x00C3),
+ S5K4ECGX_REG_WRITE(0x70003DBA, 0x189A),
+ S5K4ECGX_REG_WRITE(0x70003DBC, 0x4696),
+ S5K4ECGX_REG_WRITE(0x70003DBE, 0x4A86),
+ S5K4ECGX_REG_WRITE(0x70003DC0, 0x1C40),
+ S5K4ECGX_REG_WRITE(0x70003DC2, 0x189B),
+ S5K4ECGX_REG_WRITE(0x70003DC4, 0x469C),
+ S5K4ECGX_REG_WRITE(0x70003DC6, 0x4B76),
+ S5K4ECGX_REG_WRITE(0x70003DC8, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70003DCA, 0x18C6),
+ S5K4ECGX_REG_WRITE(0x70003DCC, 0x1887),
+ S5K4ECGX_REG_WRITE(0x70003DCE, 0x0048),
+ S5K4ECGX_REG_WRITE(0x70003DD0, 0x4672),
+ S5K4ECGX_REG_WRITE(0x70003DD2, 0x4663),
+ S5K4ECGX_REG_WRITE(0x70003DD4, 0x1812),
+ S5K4ECGX_REG_WRITE(0x70003DD6, 0x181B),
+ S5K4ECGX_REG_WRITE(0x70003DD8, 0x8C52),
+ S5K4ECGX_REG_WRITE(0x70003DDA, 0x8EDB),
+ S5K4ECGX_REG_WRITE(0x70003DDC, 0x435A),
+ S5K4ECGX_REG_WRITE(0x70003DDE, 0x0092),
+ S5K4ECGX_REG_WRITE(0x70003DE0, 0x0C15),
+ S5K4ECGX_REG_WRITE(0x70003DE2, 0x4A6F),
+ S5K4ECGX_REG_WRITE(0x70003DE4, 0x1882),
+ S5K4ECGX_REG_WRITE(0x70003DE6, 0x235A),
+ S5K4ECGX_REG_WRITE(0x70003DE8, 0x529D),
+ S5K4ECGX_REG_WRITE(0x70003DEA, 0x1833),
+ S5K4ECGX_REG_WRITE(0x70003DEC, 0x1838),
+ S5K4ECGX_REG_WRITE(0x70003DEE, 0x8C5B),
+ S5K4ECGX_REG_WRITE(0x70003DF0, 0x8EC0),
+ S5K4ECGX_REG_WRITE(0x70003DF2, 0x4343),
+ S5K4ECGX_REG_WRITE(0x70003DF4, 0x0098),
+ S5K4ECGX_REG_WRITE(0x70003DF6, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x70003DF8, 0x3260),
+ S5K4ECGX_REG_WRITE(0x70003DFA, 0x8050),
+ S5K4ECGX_REG_WRITE(0x70003DFC, 0x1C49),
+ S5K4ECGX_REG_WRITE(0x70003DFE, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70003E00, 0x0C09),
+ S5K4ECGX_REG_WRITE(0x70003E02, 0x2904),
+ S5K4ECGX_REG_WRITE(0x70003E04, 0xD3E3),
+ S5K4ECGX_REG_WRITE(0x70003E06, 0x4A66),
+ S5K4ECGX_REG_WRITE(0x70003E08, 0x325A),
+ S5K4ECGX_REG_WRITE(0x70003E0A, 0x0013),
+ S5K4ECGX_REG_WRITE(0x70003E0C, 0x3308),
+ S5K4ECGX_REG_WRITE(0x70003E0E, 0xE00A),
+ S5K4ECGX_REG_WRITE(0x70003E10, 0x4870),
+ S5K4ECGX_REG_WRITE(0x70003E12, 0x4971),
+ S5K4ECGX_REG_WRITE(0x70003E14, 0x380A),
+ S5K4ECGX_REG_WRITE(0x70003E16, 0x88C0),
+ S5K4ECGX_REG_WRITE(0x70003E18, 0x00C2),
+ S5K4ECGX_REG_WRITE(0x70003E1A, 0x1852),
+ S5K4ECGX_REG_WRITE(0x70003E1C, 0x3236),
+ S5K4ECGX_REG_WRITE(0x70003E1E, 0x1C40),
+ S5K4ECGX_REG_WRITE(0x70003E20, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70003E22, 0x1843),
+ S5K4ECGX_REG_WRITE(0x70003E24, 0x3336),
+ S5K4ECGX_REG_WRITE(0x70003E26, 0x2100),
+ S5K4ECGX_REG_WRITE(0x70003E28, 0x4864),
+ S5K4ECGX_REG_WRITE(0x70003E2A, 0x3020),
+ S5K4ECGX_REG_WRITE(0x70003E2C, 0x4684),
+ S5K4ECGX_REG_WRITE(0x70003E2E, 0x4E69),
+ S5K4ECGX_REG_WRITE(0x70003E30, 0x0048),
+ S5K4ECGX_REG_WRITE(0x70003E32, 0x3E0A),
+ S5K4ECGX_REG_WRITE(0x70003E34, 0x8937),
+ S5K4ECGX_REG_WRITE(0x70003E36, 0x5A15),
+ S5K4ECGX_REG_WRITE(0x70003E38, 0x8976),
+ S5K4ECGX_REG_WRITE(0x70003E3A, 0x437D),
+ S5K4ECGX_REG_WRITE(0x70003E3C, 0x5A1F),
+ S5K4ECGX_REG_WRITE(0x70003E3E, 0x4377),
+ S5K4ECGX_REG_WRITE(0x70003E40, 0x4E65),
+ S5K4ECGX_REG_WRITE(0x70003E42, 0x19ED),
+ S5K4ECGX_REG_WRITE(0x70003E44, 0x1986),
+ S5K4ECGX_REG_WRITE(0x70003E46, 0x3660),
+ S5K4ECGX_REG_WRITE(0x70003E48, 0x89F6),
+ S5K4ECGX_REG_WRITE(0x70003E4A, 0x4366),
+ S5K4ECGX_REG_WRITE(0x70003E4C, 0x19AD),
+ S5K4ECGX_REG_WRITE(0x70003E4E, 0x022D),
+ S5K4ECGX_REG_WRITE(0x70003E50, 0x0C2D),
+ S5K4ECGX_REG_WRITE(0x70003E52, 0xAE04),
+ S5K4ECGX_REG_WRITE(0x70003E54, 0x5235),
+ S5K4ECGX_REG_WRITE(0x70003E56, 0x4666),
+ S5K4ECGX_REG_WRITE(0x70003E58, 0x7C76),
+ S5K4ECGX_REG_WRITE(0x70003E5A, 0x4375),
+ S5K4ECGX_REG_WRITE(0x70003E5C, 0x9E06),
+ S5K4ECGX_REG_WRITE(0x70003E5E, 0x026D),
+ S5K4ECGX_REG_WRITE(0x70003E60, 0x0C2D),
+ S5K4ECGX_REG_WRITE(0x70003E62, 0x5235),
+ S5K4ECGX_REG_WRITE(0x70003E64, 0x1C49),
+ S5K4ECGX_REG_WRITE(0x70003E66, 0x2904),
+ S5K4ECGX_REG_WRITE(0x70003E68, 0xD3E1),
+ S5K4ECGX_REG_WRITE(0x70003E6A, 0xB007),
+ S5K4ECGX_REG_WRITE(0x70003E6C, 0xBCF0),
+ S5K4ECGX_REG_WRITE(0x70003E6E, 0xBC08),
+ S5K4ECGX_REG_WRITE(0x70003E70, 0x4718),
+ S5K4ECGX_REG_WRITE(0x70003E72, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003E74, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70003E76, 0xF7FF),
+ S5K4ECGX_REG_WRITE(0x70003E78, 0xFF53),
+ S5K4ECGX_REG_WRITE(0x70003E7A, 0x2101),
+ S5K4ECGX_REG_WRITE(0x70003E7C, 0x000D),
+ S5K4ECGX_REG_WRITE(0x70003E7E, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70003E80, 0x3810),
+ S5K4ECGX_REG_WRITE(0x70003E82, 0x4081),
+ S5K4ECGX_REG_WRITE(0x70003E84, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x70003E86, 0x4F4A),
+ S5K4ECGX_REG_WRITE(0x70003E88, 0x000E),
+ S5K4ECGX_REG_WRITE(0x70003E8A, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003E8C, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70003E8E, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70003E90, 0x43A8),
+ S5K4ECGX_REG_WRITE(0x70003E92, 0x8038),
+ S5K4ECGX_REG_WRITE(0x70003E94, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70003E96, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70003E98, 0x43B0),
+ S5K4ECGX_REG_WRITE(0x70003E9A, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70003E9C, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003E9E, 0xFA5E),
+ S5K4ECGX_REG_WRITE(0x70003EA0, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003EA2, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70003EA4, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70003EA6, 0x4328),
+ S5K4ECGX_REG_WRITE(0x70003EA8, 0x8038),
+ S5K4ECGX_REG_WRITE(0x70003EAA, 0xE6EC),
+ S5K4ECGX_REG_WRITE(0x70003EAC, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70003EAE, 0x4330),
+ S5K4ECGX_REG_WRITE(0x70003EB0, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70003EB2, 0xE6E8),
+ S5K4ECGX_REG_WRITE(0x70003EB4, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003EB6, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70003EB8, 0x4F48),
+ S5K4ECGX_REG_WRITE(0x70003EBA, 0x4949),
+ S5K4ECGX_REG_WRITE(0x70003EBC, 0x78FA),
+ S5K4ECGX_REG_WRITE(0x70003EBE, 0x2001),
+ S5K4ECGX_REG_WRITE(0x70003EC0, 0x2A00),
+ S5K4ECGX_REG_WRITE(0x70003EC2, 0xD102),
+ S5K4ECGX_REG_WRITE(0x70003EC4, 0x2000),
+ S5K4ECGX_REG_WRITE(0x70003EC6, 0x86C8),
+ S5K4ECGX_REG_WRITE(0x70003EC8, 0xE003),
+ S5K4ECGX_REG_WRITE(0x70003ECA, 0x7AFA),
+ S5K4ECGX_REG_WRITE(0x70003ECC, 0x2A00),
+ S5K4ECGX_REG_WRITE(0x70003ECE, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70003ED0, 0x86C8),
+ S5K4ECGX_REG_WRITE(0x70003ED2, 0x2101),
+ S5K4ECGX_REG_WRITE(0x70003ED4, 0x000D),
+ S5K4ECGX_REG_WRITE(0x70003ED6, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70003ED8, 0x3810),
+ S5K4ECGX_REG_WRITE(0x70003EDA, 0x4081),
+ S5K4ECGX_REG_WRITE(0x70003EDC, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x70003EDE, 0x000E),
+ S5K4ECGX_REG_WRITE(0x70003EE0, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003EE2, 0xDA04),
+ S5K4ECGX_REG_WRITE(0x70003EE4, 0x4932),
+ S5K4ECGX_REG_WRITE(0x70003EE6, 0x8808),
+ S5K4ECGX_REG_WRITE(0x70003EE8, 0x43A8),
+ S5K4ECGX_REG_WRITE(0x70003EEA, 0x8008),
+ S5K4ECGX_REG_WRITE(0x70003EEC, 0xE003),
+ S5K4ECGX_REG_WRITE(0x70003EEE, 0x4930),
+ S5K4ECGX_REG_WRITE(0x70003EF0, 0x8848),
+ S5K4ECGX_REG_WRITE(0x70003EF2, 0x43B0),
+ S5K4ECGX_REG_WRITE(0x70003EF4, 0x8048),
+ S5K4ECGX_REG_WRITE(0x70003EF6, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003EF8, 0xFA39),
+ S5K4ECGX_REG_WRITE(0x70003EFA, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003EFC, 0xDA04),
+ S5K4ECGX_REG_WRITE(0x70003EFE, 0x482C),
+ S5K4ECGX_REG_WRITE(0x70003F00, 0x8801),
+ S5K4ECGX_REG_WRITE(0x70003F02, 0x4329),
+ S5K4ECGX_REG_WRITE(0x70003F04, 0x8001),
+ S5K4ECGX_REG_WRITE(0x70003F06, 0xE003),
+ S5K4ECGX_REG_WRITE(0x70003F08, 0x4829),
+ S5K4ECGX_REG_WRITE(0x70003F0A, 0x8841),
+ S5K4ECGX_REG_WRITE(0x70003F0C, 0x4331),
+ S5K4ECGX_REG_WRITE(0x70003F0E, 0x8041),
+ S5K4ECGX_REG_WRITE(0x70003F10, 0x4934),
+ S5K4ECGX_REG_WRITE(0x70003F12, 0x8B08),
+ S5K4ECGX_REG_WRITE(0x70003F14, 0x06C2),
+ S5K4ECGX_REG_WRITE(0x70003F16, 0xD50A),
+ S5K4ECGX_REG_WRITE(0x70003F18, 0x7ABA),
+ S5K4ECGX_REG_WRITE(0x70003F1A, 0x0652),
+ S5K4ECGX_REG_WRITE(0x70003F1C, 0xD507),
+ S5K4ECGX_REG_WRITE(0x70003F1E, 0x2210),
+ S5K4ECGX_REG_WRITE(0x70003F20, 0x4390),
+ S5K4ECGX_REG_WRITE(0x70003F22, 0x8308),
+ S5K4ECGX_REG_WRITE(0x70003F24, 0x4830),
+ S5K4ECGX_REG_WRITE(0x70003F26, 0x7AF9),
+ S5K4ECGX_REG_WRITE(0x70003F28, 0x6B00),
+ S5K4ECGX_REG_WRITE(0x70003F2A, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003F2C, 0xFA27),
+ S5K4ECGX_REG_WRITE(0x70003F2E, 0x481C),
+ S5K4ECGX_REG_WRITE(0x70003F30, 0x3060),
+ S5K4ECGX_REG_WRITE(0x70003F32, 0x89C0),
+ S5K4ECGX_REG_WRITE(0x70003F34, 0x2800),
+ S5K4ECGX_REG_WRITE(0x70003F36, 0xD009),
+ S5K4ECGX_REG_WRITE(0x70003F38, 0x78F8),
+ S5K4ECGX_REG_WRITE(0x70003F3A, 0x2800),
+ S5K4ECGX_REG_WRITE(0x70003F3C, 0xD006),
+ S5K4ECGX_REG_WRITE(0x70003F3E, 0x7AF8),
+ S5K4ECGX_REG_WRITE(0x70003F40, 0x2800),
+ S5K4ECGX_REG_WRITE(0x70003F42, 0xD003),
+ S5K4ECGX_REG_WRITE(0x70003F44, 0x7AB8),
+ S5K4ECGX_REG_WRITE(0x70003F46, 0x2140),
+ S5K4ECGX_REG_WRITE(0x70003F48, 0x4308),
+ S5K4ECGX_REG_WRITE(0x70003F4A, 0x72B8),
+ S5K4ECGX_REG_WRITE(0x70003F4C, 0xE69B),
+ S5K4ECGX_REG_WRITE(0x70003F4E, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70003F50, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70003F52, 0x4826),
+ S5K4ECGX_REG_WRITE(0x70003F54, 0x8981),
+ S5K4ECGX_REG_WRITE(0x70003F56, 0x2900),
+ S5K4ECGX_REG_WRITE(0x70003F58, 0xD007),
+ S5K4ECGX_REG_WRITE(0x70003F5A, 0x8940),
+ S5K4ECGX_REG_WRITE(0x70003F5C, 0x2800),
+ S5K4ECGX_REG_WRITE(0x70003F5E, 0xD104),
+ S5K4ECGX_REG_WRITE(0x70003F60, 0x481E),
+ S5K4ECGX_REG_WRITE(0x70003F62, 0x22BF),
+ S5K4ECGX_REG_WRITE(0x70003F64, 0x7A81),
+ S5K4ECGX_REG_WRITE(0x70003F66, 0x4011),
+ S5K4ECGX_REG_WRITE(0x70003F68, 0x7281),
+ S5K4ECGX_REG_WRITE(0x70003F6A, 0x2101),
+ S5K4ECGX_REG_WRITE(0x70003F6C, 0x000D),
+ S5K4ECGX_REG_WRITE(0x70003F6E, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70003F70, 0x3810),
+ S5K4ECGX_REG_WRITE(0x70003F72, 0x4081),
+ S5K4ECGX_REG_WRITE(0x70003F74, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x70003F76, 0x4F0E),
+ S5K4ECGX_REG_WRITE(0x70003F78, 0x000E),
+ S5K4ECGX_REG_WRITE(0x70003F7A, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003F7C, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70003F7E, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70003F80, 0x43A8),
+ S5K4ECGX_REG_WRITE(0x70003F82, 0x8038),
+ S5K4ECGX_REG_WRITE(0x70003F84, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70003F86, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70003F88, 0x43B0),
+ S5K4ECGX_REG_WRITE(0x70003F8A, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70003F8C, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70003F8E, 0xF9FE),
+ S5K4ECGX_REG_WRITE(0x70003F90, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70003F92, 0xDA2D),
+ S5K4ECGX_REG_WRITE(0x70003F94, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70003F96, 0x4328),
+ S5K4ECGX_REG_WRITE(0x70003F98, 0x8038),
+ S5K4ECGX_REG_WRITE(0x70003F9A, 0xE674),
+ S5K4ECGX_REG_WRITE(0x70003F9C, 0x21C0),
+ S5K4ECGX_REG_WRITE(0x70003F9E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FA0, 0x4780),
+ S5K4ECGX_REG_WRITE(0x70003FA2, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FA4, 0x2D00),
+ S5K4ECGX_REG_WRITE(0x70003FA6, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FA8, 0x2AD0),
+ S5K4ECGX_REG_WRITE(0x70003FAA, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FAC, 0x0924),
+ S5K4ECGX_REG_WRITE(0x70003FAE, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FB0, 0x1100),
+ S5K4ECGX_REG_WRITE(0x70003FB2, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70003FB4, 0xE300),
+ S5K4ECGX_REG_WRITE(0x70003FB6, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70003FB8, 0x29D0),
+ S5K4ECGX_REG_WRITE(0x70003FBA, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FBC, 0x2C30),
+ S5K4ECGX_REG_WRITE(0x70003FBE, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FC0, 0x5000),
+ S5K4ECGX_REG_WRITE(0x70003FC2, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70003FC4, 0xA006),
+ S5K4ECGX_REG_WRITE(0x70003FC6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70003FC8, 0xA000),
+ S5K4ECGX_REG_WRITE(0x70003FCA, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70003FCC, 0x06F8),
+ S5K4ECGX_REG_WRITE(0x70003FCE, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FD0, 0x0888),
+ S5K4ECGX_REG_WRITE(0x70003FD2, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FD4, 0x21DA),
+ S5K4ECGX_REG_WRITE(0x70003FD6, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FD8, 0x08AC),
+ S5K4ECGX_REG_WRITE(0x70003FDA, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FDC, 0x20BC),
+ S5K4ECGX_REG_WRITE(0x70003FDE, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FE0, 0x1ECC),
+ S5K4ECGX_REG_WRITE(0x70003FE2, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FE4, 0x2FA4),
+ S5K4ECGX_REG_WRITE(0x70003FE6, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FE8, 0x235C),
+ S5K4ECGX_REG_WRITE(0x70003FEA, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FEC, 0x0234),
+ S5K4ECGX_REG_WRITE(0x70003FEE, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70003FF0, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70003FF2, 0x4330),
+ S5K4ECGX_REG_WRITE(0x70003FF4, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70003FF6, 0xE646),
+ S5K4ECGX_REG_WRITE(0x70003FF8, 0xB570),
+ S5K4ECGX_REG_WRITE(0x70003FFA, 0x4D99),
+ S5K4ECGX_REG_WRITE(0x70003FFC, 0x4C99),
+ S5K4ECGX_REG_WRITE(0x70003FFE, 0x8B28),
+ S5K4ECGX_REG_WRITE(0x70004000, 0x0701),
+ S5K4ECGX_REG_WRITE(0x70004002, 0xD507),
+ S5K4ECGX_REG_WRITE(0x70004004, 0x2108),
+ S5K4ECGX_REG_WRITE(0x70004006, 0x4388),
+ S5K4ECGX_REG_WRITE(0x70004008, 0x8328),
+ S5K4ECGX_REG_WRITE(0x7000400A, 0x4997),
+ S5K4ECGX_REG_WRITE(0x7000400C, 0x6B20),
+ S5K4ECGX_REG_WRITE(0x7000400E, 0x68C9),
+ S5K4ECGX_REG_WRITE(0x70004010, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70004012, 0xF9C4),
+ S5K4ECGX_REG_WRITE(0x70004014, 0x8B28),
+ S5K4ECGX_REG_WRITE(0x70004016, 0x06C1),
+ S5K4ECGX_REG_WRITE(0x70004018, 0xD50A),
+ S5K4ECGX_REG_WRITE(0x7000401A, 0x4994),
+ S5K4ECGX_REG_WRITE(0x7000401C, 0x7A8A),
+ S5K4ECGX_REG_WRITE(0x7000401E, 0x0652),
+ S5K4ECGX_REG_WRITE(0x70004020, 0xD406),
+ S5K4ECGX_REG_WRITE(0x70004022, 0x2210),
+ S5K4ECGX_REG_WRITE(0x70004024, 0x4390),
+ S5K4ECGX_REG_WRITE(0x70004026, 0x8328),
+ S5K4ECGX_REG_WRITE(0x70004028, 0x7AC9),
+ S5K4ECGX_REG_WRITE(0x7000402A, 0x6B20),
+ S5K4ECGX_REG_WRITE(0x7000402C, 0xF000),
+ S5K4ECGX_REG_WRITE(0x7000402E, 0xF9A6),
+ S5K4ECGX_REG_WRITE(0x70004030, 0xE5DC),
+ S5K4ECGX_REG_WRITE(0x70004032, 0xB570),
+ S5K4ECGX_REG_WRITE(0x70004034, 0x4D8E),
+ S5K4ECGX_REG_WRITE(0x70004036, 0x4C8F),
+ S5K4ECGX_REG_WRITE(0x70004038, 0x88EA),
+ S5K4ECGX_REG_WRITE(0x7000403A, 0x2A14),
+ S5K4ECGX_REG_WRITE(0x7000403C, 0xD101),
+ S5K4ECGX_REG_WRITE(0x7000403E, 0x2200),
+ S5K4ECGX_REG_WRITE(0x70004040, 0x81A2),
+ S5K4ECGX_REG_WRITE(0x70004042, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70004044, 0xF9B3),
+ S5K4ECGX_REG_WRITE(0x70004046, 0x88E8),
+ S5K4ECGX_REG_WRITE(0x70004048, 0x2821),
+ S5K4ECGX_REG_WRITE(0x7000404A, 0xD10F),
+ S5K4ECGX_REG_WRITE(0x7000404C, 0x8B28),
+ S5K4ECGX_REG_WRITE(0x7000404E, 0x2800),
+ S5K4ECGX_REG_WRITE(0x70004050, 0xD10C),
+ S5K4ECGX_REG_WRITE(0x70004052, 0x200C),
+ S5K4ECGX_REG_WRITE(0x70004054, 0x5E20),
+ S5K4ECGX_REG_WRITE(0x70004056, 0x8961),
+ S5K4ECGX_REG_WRITE(0x70004058, 0x4288),
+ S5K4ECGX_REG_WRITE(0x7000405A, 0xDC07),
+ S5K4ECGX_REG_WRITE(0x7000405C, 0x4882),
+ S5K4ECGX_REG_WRITE(0x7000405E, 0x3880),
+ S5K4ECGX_REG_WRITE(0x70004060, 0x6B80),
+ S5K4ECGX_REG_WRITE(0x70004062, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70004064, 0xF9AB),
+ S5K4ECGX_REG_WRITE(0x70004066, 0x89A0),
+ S5K4ECGX_REG_WRITE(0x70004068, 0x1C40),
+ S5K4ECGX_REG_WRITE(0x7000406A, 0x81A0),
+ S5K4ECGX_REG_WRITE(0x7000406C, 0xE5BE),
+ S5K4ECGX_REG_WRITE(0x7000406E, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70004070, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70004072, 0x2101),
+ S5K4ECGX_REG_WRITE(0x70004074, 0x000D),
+ S5K4ECGX_REG_WRITE(0x70004076, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70004078, 0x3810),
+ S5K4ECGX_REG_WRITE(0x7000407A, 0x4081),
+ S5K4ECGX_REG_WRITE(0x7000407C, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x7000407E, 0x4F7E),
+ S5K4ECGX_REG_WRITE(0x70004080, 0x000E),
+ S5K4ECGX_REG_WRITE(0x70004082, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70004084, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70004086, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70004088, 0x43A8),
+ S5K4ECGX_REG_WRITE(0x7000408A, 0x8038),
+ S5K4ECGX_REG_WRITE(0x7000408C, 0xE002),
+ S5K4ECGX_REG_WRITE(0x7000408E, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70004090, 0x43B0),
+ S5K4ECGX_REG_WRITE(0x70004092, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70004094, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70004096, 0xF99A),
+ S5K4ECGX_REG_WRITE(0x70004098, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x7000409A, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x7000409C, 0x8838),
+ S5K4ECGX_REG_WRITE(0x7000409E, 0x4328),
+ S5K4ECGX_REG_WRITE(0x700040A0, 0x8038),
+ S5K4ECGX_REG_WRITE(0x700040A2, 0xE002),
+ S5K4ECGX_REG_WRITE(0x700040A4, 0x8878),
+ S5K4ECGX_REG_WRITE(0x700040A6, 0x4330),
+ S5K4ECGX_REG_WRITE(0x700040A8, 0x8078),
+ S5K4ECGX_REG_WRITE(0x700040AA, 0x4874),
+ S5K4ECGX_REG_WRITE(0x700040AC, 0x8800),
+ S5K4ECGX_REG_WRITE(0x700040AE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700040B0, 0xD504),
+ S5K4ECGX_REG_WRITE(0x700040B2, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700040B4, 0xF993),
+ S5K4ECGX_REG_WRITE(0x700040B6, 0x496E),
+ S5K4ECGX_REG_WRITE(0x700040B8, 0x2012),
+ S5K4ECGX_REG_WRITE(0x700040BA, 0x80C8),
+ S5K4ECGX_REG_WRITE(0x700040BC, 0xE5E3),
+ S5K4ECGX_REG_WRITE(0x700040BE, 0xB570),
+ S5K4ECGX_REG_WRITE(0x700040C0, 0x4E6A),
+ S5K4ECGX_REG_WRITE(0x700040C2, 0x8881),
+ S5K4ECGX_REG_WRITE(0x700040C4, 0x78F2),
+ S5K4ECGX_REG_WRITE(0x700040C6, 0x4D6E),
+ S5K4ECGX_REG_WRITE(0x700040C8, 0x4C6A),
+ S5K4ECGX_REG_WRITE(0x700040CA, 0x2A00),
+ S5K4ECGX_REG_WRITE(0x700040CC, 0xD005),
+ S5K4ECGX_REG_WRITE(0x700040CE, 0x8A62),
+ S5K4ECGX_REG_WRITE(0x700040D0, 0x1889),
+ S5K4ECGX_REG_WRITE(0x700040D2, 0x8081),
+ S5K4ECGX_REG_WRITE(0x700040D4, 0x8B61),
+ S5K4ECGX_REG_WRITE(0x700040D6, 0x8029),
+ S5K4ECGX_REG_WRITE(0x700040D8, 0xE004),
+ S5K4ECGX_REG_WRITE(0x700040DA, 0x8A22),
+ S5K4ECGX_REG_WRITE(0x700040DC, 0x1889),
+ S5K4ECGX_REG_WRITE(0x700040DE, 0x8081),
+ S5K4ECGX_REG_WRITE(0x700040E0, 0x8B21),
+ S5K4ECGX_REG_WRITE(0x700040E2, 0x8029),
+ S5K4ECGX_REG_WRITE(0x700040E4, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700040E6, 0xF982),
+ S5K4ECGX_REG_WRITE(0x700040E8, 0x78F0),
+ S5K4ECGX_REG_WRITE(0x700040EA, 0x2800),
+ S5K4ECGX_REG_WRITE(0x700040EC, 0xD002),
+ S5K4ECGX_REG_WRITE(0x700040EE, 0x8BE0),
+ S5K4ECGX_REG_WRITE(0x700040F0, 0x82E8),
+ S5K4ECGX_REG_WRITE(0x700040F2, 0xE57B),
+ S5K4ECGX_REG_WRITE(0x700040F4, 0x8BA0),
+ S5K4ECGX_REG_WRITE(0x700040F6, 0x82E8),
+ S5K4ECGX_REG_WRITE(0x700040F8, 0xE578),
+ S5K4ECGX_REG_WRITE(0x700040FA, 0xB430),
+ S5K4ECGX_REG_WRITE(0x700040FC, 0x680B),
+ S5K4ECGX_REG_WRITE(0x700040FE, 0x684D),
+ S5K4ECGX_REG_WRITE(0x70004100, 0x688C),
+ S5K4ECGX_REG_WRITE(0x70004102, 0x68C8),
+ S5K4ECGX_REG_WRITE(0x70004104, 0x4A5F),
+ S5K4ECGX_REG_WRITE(0x70004106, 0x8054),
+ S5K4ECGX_REG_WRITE(0x70004108, 0x4958),
+ S5K4ECGX_REG_WRITE(0x7000410A, 0x78CC),
+ S5K4ECGX_REG_WRITE(0x7000410C, 0x4959),
+ S5K4ECGX_REG_WRITE(0x7000410E, 0x2C00),
+ S5K4ECGX_REG_WRITE(0x70004110, 0xD003),
+ S5K4ECGX_REG_WRITE(0x70004112, 0x8A49),
+ S5K4ECGX_REG_WRITE(0x70004114, 0x1808),
+ S5K4ECGX_REG_WRITE(0x70004116, 0x8090),
+ S5K4ECGX_REG_WRITE(0x70004118, 0xE002),
+ S5K4ECGX_REG_WRITE(0x7000411A, 0x8A09),
+ S5K4ECGX_REG_WRITE(0x7000411C, 0x1808),
+ S5K4ECGX_REG_WRITE(0x7000411E, 0x8090),
+ S5K4ECGX_REG_WRITE(0x70004120, 0x80D3),
+ S5K4ECGX_REG_WRITE(0x70004122, 0x8115),
+ S5K4ECGX_REG_WRITE(0x70004124, 0xBC30),
+ S5K4ECGX_REG_WRITE(0x70004126, 0x4770),
+ S5K4ECGX_REG_WRITE(0x70004128, 0xB5F3),
+ S5K4ECGX_REG_WRITE(0x7000412A, 0x0004),
+ S5K4ECGX_REG_WRITE(0x7000412C, 0xB081),
+ S5K4ECGX_REG_WRITE(0x7000412E, 0x9802),
+ S5K4ECGX_REG_WRITE(0x70004130, 0x6800),
+ S5K4ECGX_REG_WRITE(0x70004132, 0x0600),
+ S5K4ECGX_REG_WRITE(0x70004134, 0x0E00),
+ S5K4ECGX_REG_WRITE(0x70004136, 0x2201),
+ S5K4ECGX_REG_WRITE(0x70004138, 0x0015),
+ S5K4ECGX_REG_WRITE(0x7000413A, 0x0021),
+ S5K4ECGX_REG_WRITE(0x7000413C, 0x3910),
+ S5K4ECGX_REG_WRITE(0x7000413E, 0x408A),
+ S5K4ECGX_REG_WRITE(0x70004140, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x70004142, 0x4F4D),
+ S5K4ECGX_REG_WRITE(0x70004144, 0x0016),
+ S5K4ECGX_REG_WRITE(0x70004146, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70004148, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x7000414A, 0x8839),
+ S5K4ECGX_REG_WRITE(0x7000414C, 0x43A9),
+ S5K4ECGX_REG_WRITE(0x7000414E, 0x8039),
+ S5K4ECGX_REG_WRITE(0x70004150, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70004152, 0x8879),
+ S5K4ECGX_REG_WRITE(0x70004154, 0x43B1),
+ S5K4ECGX_REG_WRITE(0x70004156, 0x8079),
+ S5K4ECGX_REG_WRITE(0x70004158, 0xF000),
+ S5K4ECGX_REG_WRITE(0x7000415A, 0xF950),
+ S5K4ECGX_REG_WRITE(0x7000415C, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x7000415E, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70004160, 0x8839),
+ S5K4ECGX_REG_WRITE(0x70004162, 0x4329),
+ S5K4ECGX_REG_WRITE(0x70004164, 0x8039),
+ S5K4ECGX_REG_WRITE(0x70004166, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70004168, 0x8879),
+ S5K4ECGX_REG_WRITE(0x7000416A, 0x4331),
+ S5K4ECGX_REG_WRITE(0x7000416C, 0x8079),
+ S5K4ECGX_REG_WRITE(0x7000416E, 0x4946),
+ S5K4ECGX_REG_WRITE(0x70004170, 0x8809),
+ S5K4ECGX_REG_WRITE(0x70004172, 0x2900),
+ S5K4ECGX_REG_WRITE(0x70004174, 0xD102),
+ S5K4ECGX_REG_WRITE(0x70004176, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70004178, 0xF949),
+ S5K4ECGX_REG_WRITE(0x7000417A, 0x2000),
+ S5K4ECGX_REG_WRITE(0x7000417C, 0x9902),
+ S5K4ECGX_REG_WRITE(0x7000417E, 0x6008),
+ S5K4ECGX_REG_WRITE(0x70004180, 0xBCFE),
+ S5K4ECGX_REG_WRITE(0x70004182, 0xBC08),
+ S5K4ECGX_REG_WRITE(0x70004184, 0x4718),
+ S5K4ECGX_REG_WRITE(0x70004186, 0xB538),
+ S5K4ECGX_REG_WRITE(0x70004188, 0x4C40),
+ S5K4ECGX_REG_WRITE(0x7000418A, 0x89E5),
+ S5K4ECGX_REG_WRITE(0x7000418C, 0xF000),
+ S5K4ECGX_REG_WRITE(0x7000418E, 0xF946),
+ S5K4ECGX_REG_WRITE(0x70004190, 0x1FE8),
+ S5K4ECGX_REG_WRITE(0x70004192, 0x38FD),
+ S5K4ECGX_REG_WRITE(0x70004194, 0xD132),
+ S5K4ECGX_REG_WRITE(0x70004196, 0x89E0),
+ S5K4ECGX_REG_WRITE(0x70004198, 0x1FC1),
+ S5K4ECGX_REG_WRITE(0x7000419A, 0x39FF),
+ S5K4ECGX_REG_WRITE(0x7000419C, 0xD12E),
+ S5K4ECGX_REG_WRITE(0x7000419E, 0x483C),
+ S5K4ECGX_REG_WRITE(0x700041A0, 0x69E1),
+ S5K4ECGX_REG_WRITE(0x700041A2, 0x6840),
+ S5K4ECGX_REG_WRITE(0x700041A4, 0x1809),
+ S5K4ECGX_REG_WRITE(0x700041A6, 0x0200),
+ S5K4ECGX_REG_WRITE(0x700041A8, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700041AA, 0xF8BA),
+ S5K4ECGX_REG_WRITE(0x700041AC, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700041AE, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x700041B0, 0x4A38),
+ S5K4ECGX_REG_WRITE(0x700041B2, 0x2305),
+ S5K4ECGX_REG_WRITE(0x700041B4, 0x0011),
+ S5K4ECGX_REG_WRITE(0x700041B6, 0x3114),
+ S5K4ECGX_REG_WRITE(0x700041B8, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700041BA, 0xF938),
+ S5K4ECGX_REG_WRITE(0x700041BC, 0x0002),
+ S5K4ECGX_REG_WRITE(0x700041BE, 0x66E0),
+ S5K4ECGX_REG_WRITE(0x700041C0, 0x4D34),
+ S5K4ECGX_REG_WRITE(0x700041C2, 0x8CE0),
+ S5K4ECGX_REG_WRITE(0x700041C4, 0x3D14),
+ S5K4ECGX_REG_WRITE(0x700041C6, 0x89E9),
+ S5K4ECGX_REG_WRITE(0x700041C8, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700041CA, 0xF88A),
+ S5K4ECGX_REG_WRITE(0x700041CC, 0x466B),
+ S5K4ECGX_REG_WRITE(0x700041CE, 0x8018),
+ S5K4ECGX_REG_WRITE(0x700041D0, 0x8A29),
+ S5K4ECGX_REG_WRITE(0x700041D2, 0x8D20),
+ S5K4ECGX_REG_WRITE(0x700041D4, 0x6EE2),
+ S5K4ECGX_REG_WRITE(0x700041D6, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700041D8, 0xF883),
+ S5K4ECGX_REG_WRITE(0x700041DA, 0x466B),
+ S5K4ECGX_REG_WRITE(0x700041DC, 0x8058),
+ S5K4ECGX_REG_WRITE(0x700041DE, 0x0021),
+ S5K4ECGX_REG_WRITE(0x700041E0, 0x9800),
+ S5K4ECGX_REG_WRITE(0x700041E2, 0x3170),
+ S5K4ECGX_REG_WRITE(0x700041E4, 0xF000),
+ S5K4ECGX_REG_WRITE(0x700041E6, 0xF92A),
+ S5K4ECGX_REG_WRITE(0x700041E8, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700041EA, 0x3060),
+ S5K4ECGX_REG_WRITE(0x700041EC, 0x8A02),
+ S5K4ECGX_REG_WRITE(0x700041EE, 0x4928),
+ S5K4ECGX_REG_WRITE(0x700041F0, 0x3980),
+ S5K4ECGX_REG_WRITE(0x700041F2, 0x808A),
+ S5K4ECGX_REG_WRITE(0x700041F4, 0x8A42),
+ S5K4ECGX_REG_WRITE(0x700041F6, 0x80CA),
+ S5K4ECGX_REG_WRITE(0x700041F8, 0x8A80),
+ S5K4ECGX_REG_WRITE(0x700041FA, 0x8108),
+ S5K4ECGX_REG_WRITE(0x700041FC, 0xBC38),
+ S5K4ECGX_REG_WRITE(0x700041FE, 0xBC08),
+ S5K4ECGX_REG_WRITE(0x70004200, 0x4718),
+ S5K4ECGX_REG_WRITE(0x70004202, 0xB5F8),
+ S5K4ECGX_REG_WRITE(0x70004204, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70004206, 0x6808),
+ S5K4ECGX_REG_WRITE(0x70004208, 0x0400),
+ S5K4ECGX_REG_WRITE(0x7000420A, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x7000420C, 0x2201),
+ S5K4ECGX_REG_WRITE(0x7000420E, 0x0015),
+ S5K4ECGX_REG_WRITE(0x70004210, 0x0021),
+ S5K4ECGX_REG_WRITE(0x70004212, 0x3910),
+ S5K4ECGX_REG_WRITE(0x70004214, 0x408A),
+ S5K4ECGX_REG_WRITE(0x70004216, 0x40A5),
+ S5K4ECGX_REG_WRITE(0x70004218, 0x4F17),
+ S5K4ECGX_REG_WRITE(0x7000421A, 0x0016),
+ S5K4ECGX_REG_WRITE(0x7000421C, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x7000421E, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70004220, 0x8839),
+ S5K4ECGX_REG_WRITE(0x70004222, 0x43A9),
+ S5K4ECGX_REG_WRITE(0x70004224, 0x8039),
+ S5K4ECGX_REG_WRITE(0x70004226, 0xE002),
+ S5K4ECGX_REG_WRITE(0x70004228, 0x8879),
+ S5K4ECGX_REG_WRITE(0x7000422A, 0x43B1),
+ S5K4ECGX_REG_WRITE(0x7000422C, 0x8079),
+ S5K4ECGX_REG_WRITE(0x7000422E, 0xF000),
+ S5K4ECGX_REG_WRITE(0x70004230, 0xF90D),
+ S5K4ECGX_REG_WRITE(0x70004232, 0x2C10),
+ S5K4ECGX_REG_WRITE(0x70004234, 0xDA03),
+ S5K4ECGX_REG_WRITE(0x70004236, 0x8838),
+ S5K4ECGX_REG_WRITE(0x70004238, 0x4328),
+ S5K4ECGX_REG_WRITE(0x7000423A, 0x8038),
+ S5K4ECGX_REG_WRITE(0x7000423C, 0xE002),
+ S5K4ECGX_REG_WRITE(0x7000423E, 0x8878),
+ S5K4ECGX_REG_WRITE(0x70004240, 0x4330),
+ S5K4ECGX_REG_WRITE(0x70004242, 0x8078),
+ S5K4ECGX_REG_WRITE(0x70004244, 0x480D),
+ S5K4ECGX_REG_WRITE(0x70004246, 0x8800),
+ S5K4ECGX_REG_WRITE(0x70004248, 0x0400),
+ S5K4ECGX_REG_WRITE(0x7000424A, 0xD507),
+ S5K4ECGX_REG_WRITE(0x7000424C, 0x4B12),
+ S5K4ECGX_REG_WRITE(0x7000424E, 0x7819),
+ S5K4ECGX_REG_WRITE(0x70004250, 0x4A12),
+ S5K4ECGX_REG_WRITE(0x70004252, 0x7810),
+ S5K4ECGX_REG_WRITE(0x70004254, 0x7018),
+ S5K4ECGX_REG_WRITE(0x70004256, 0x7011),
+ S5K4ECGX_REG_WRITE(0x70004258, 0x4905),
+ S5K4ECGX_REG_WRITE(0x7000425A, 0x8188),
+ S5K4ECGX_REG_WRITE(0x7000425C, 0xE513),
+ S5K4ECGX_REG_WRITE(0x7000425E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70004260, 0x2FA4),
+ S5K4ECGX_REG_WRITE(0x70004262, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004264, 0x235C),
+ S5K4ECGX_REG_WRITE(0x70004266, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004268, 0x0140),
+ S5K4ECGX_REG_WRITE(0x7000426A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x7000426C, 0x20BC),
+ S5K4ECGX_REG_WRITE(0x7000426E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004270, 0x2DF0),
+ S5K4ECGX_REG_WRITE(0x70004272, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004274, 0x47E0),
+ S5K4ECGX_REG_WRITE(0x70004276, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004278, 0x1100),
+ S5K4ECGX_REG_WRITE(0x7000427A, 0xD000),
+ S5K4ECGX_REG_WRITE(0x7000427C, 0x2EE2),
+ S5K4ECGX_REG_WRITE(0x7000427E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004280, 0xF400),
+ S5K4ECGX_REG_WRITE(0x70004282, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70004284, 0x3200),
+ S5K4ECGX_REG_WRITE(0x70004286, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70004288, 0x16DE),
+ S5K4ECGX_REG_WRITE(0x7000428A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x7000428C, 0x36F8),
+ S5K4ECGX_REG_WRITE(0x7000428E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004290, 0x2B90),
+ S5K4ECGX_REG_WRITE(0x70004292, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004294, 0x17B4),
+ S5K4ECGX_REG_WRITE(0x70004296, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70004298, 0x2EDD),
+ S5K4ECGX_REG_WRITE(0x7000429A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x7000429C, 0x2EDE),
+ S5K4ECGX_REG_WRITE(0x7000429E, 0x7000),
+ S5K4ECGX_REG_WRITE(0x700042A0, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700042A2, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700042A4, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700042A6, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700042A8, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700042AA, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700042AC, 0x13D5),
+ S5K4ECGX_REG_WRITE(0x700042AE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700042B0, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700042B2, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700042B4, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700042B6, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700042B8, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700042BA, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700042BC, 0xA083),
+ S5K4ECGX_REG_WRITE(0x700042BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700042C0, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700042C2, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700042C4, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700042C6, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700042C8, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700042CA, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700042CC, 0xA035),
+ S5K4ECGX_REG_WRITE(0x700042CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700042D0, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700042D2, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700042D4, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700042D6, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700042D8, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700042DA, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700042DC, 0xA1D9),
+ S5K4ECGX_REG_WRITE(0x700042DE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700042E0, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700042E2, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700042E4, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700042E6, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700042E8, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700042EA, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700042EC, 0x2D27),
+ S5K4ECGX_REG_WRITE(0x700042EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700042F0, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700042F2, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700042F4, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700042F6, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700042F8, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700042FA, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700042FC, 0x7D47),
+ S5K4ECGX_REG_WRITE(0x700042FE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70004300, 0x4778),
+ S5K4ECGX_REG_WRITE(0x70004302, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004304, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004306, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004308, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x7000430A, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x7000430C, 0x7AB1),
+ S5K4ECGX_REG_WRITE(0x7000430E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70004310, 0x4778),
+ S5K4ECGX_REG_WRITE(0x70004312, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004314, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004316, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004318, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x7000431A, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x7000431C, 0x7ACB),
+ S5K4ECGX_REG_WRITE(0x7000431E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70004320, 0x4778),
+ S5K4ECGX_REG_WRITE(0x70004322, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004324, 0xF004),
+ S5K4ECGX_REG_WRITE(0x70004326, 0xE51F),
+ S5K4ECGX_REG_WRITE(0x70004328, 0x2630),
+ S5K4ECGX_REG_WRITE(0x7000432A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000432C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000432E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004330, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004332, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004334, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004336, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004338, 0xED4D),
+ S5K4ECGX_REG_WRITE(0x7000433A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000433C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000433E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004340, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004342, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004344, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004346, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004348, 0xEDDB),
+ S5K4ECGX_REG_WRITE(0x7000434A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000434C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000434E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004350, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004352, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004354, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004356, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004358, 0x4EB5),
+ S5K4ECGX_REG_WRITE(0x7000435A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000435C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000435E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004360, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004362, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004364, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004366, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004368, 0x053B),
+ S5K4ECGX_REG_WRITE(0x7000436A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000436C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000436E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004370, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004372, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004374, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004376, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004378, 0x49D1),
+ S5K4ECGX_REG_WRITE(0x7000437A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000437C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000437E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004380, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004382, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004384, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004386, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004388, 0xD411),
+ S5K4ECGX_REG_WRITE(0x7000438A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000438C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000438E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004390, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004392, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004394, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004396, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004398, 0x1E57),
+ S5K4ECGX_REG_WRITE(0x7000439A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000439C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000439E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700043A0, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700043A2, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700043A4, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700043A6, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700043A8, 0x2603),
+ S5K4ECGX_REG_WRITE(0x700043AA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700043AC, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700043AE, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700043B0, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700043B2, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700043B4, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700043B6, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700043B8, 0xBC3D),
+ S5K4ECGX_REG_WRITE(0x700043BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700043BC, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700043BE, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700043C0, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700043C2, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700043C4, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700043C6, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700043C8, 0x2601),
+ S5K4ECGX_REG_WRITE(0x700043CA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700043CC, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700043CE, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700043D0, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700043D2, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700043D4, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700043D6, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700043D8, 0xBAB1),
+ S5K4ECGX_REG_WRITE(0x700043DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700043DC, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700043DE, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700043E0, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700043E2, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700043E4, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700043E6, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700043E8, 0xB89F),
+ S5K4ECGX_REG_WRITE(0x700043EA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700043EC, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700043EE, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x700043F0, 0xC000),
+ S5K4ECGX_REG_WRITE(0x700043F2, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x700043F4, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x700043F6, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x700043F8, 0xF077),
+ S5K4ECGX_REG_WRITE(0x700043FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700043FC, 0x4778),
+ S5K4ECGX_REG_WRITE(0x700043FE, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004400, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004402, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004404, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004406, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004408, 0xC10D),
+ S5K4ECGX_REG_WRITE(0x7000440A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000440C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000440E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004410, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004412, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004414, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004416, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004418, 0xC0C9),
+ S5K4ECGX_REG_WRITE(0x7000441A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000441C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000441E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004420, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004422, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004424, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004426, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004428, 0xEAF9),
+ S5K4ECGX_REG_WRITE(0x7000442A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000442C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000442E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004430, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004432, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004434, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004436, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004438, 0x2E61),
+ S5K4ECGX_REG_WRITE(0x7000443A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000443C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000443E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004440, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004442, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004444, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004446, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004448, 0xE86B),
+ S5K4ECGX_REG_WRITE(0x7000444A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000444C, 0x4778),
+ S5K4ECGX_REG_WRITE(0x7000444E, 0x46C0),
+ S5K4ECGX_REG_WRITE(0x70004450, 0xC000),
+ S5K4ECGX_REG_WRITE(0x70004452, 0xE59F),
+ S5K4ECGX_REG_WRITE(0x70004454, 0xFF1C),
+ S5K4ECGX_REG_WRITE(0x70004456, 0xE12F),
+ S5K4ECGX_REG_WRITE(0x70004458, 0xB231),
+ S5K4ECGX_REG_WRITE(0x7000445A, 0x0000),
+ /* End of Patch Data */
+
+ /* switch to firmware address bank */
+ S5K4ECGX_REG_WRITE(0xD0001000, 0x0001),
+ /* End of factory settings */
+
+ /* Switch to sw address bank */
+
+ S5K4ECGX_REG_WRITE(0x7000479E, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001432, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700047EE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700047F0, 0x000A),
+ S5K4ECGX_REG_WRITE(0x700047F2, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700047F4, 0x0070),
+ S5K4ECGX_REG_WRITE(0x700047F6, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700047F8, 0x5A3C),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70004782, 0x0014),
+ S5K4ECGX_REG_WRITE(0x70004784, 0x00D2),
+ S5K4ECGX_REG_WRITE(0x70004786, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70004788, 0x07D0),
+ S5K4ECGX_REG_WRITE(0x7000478A, 0x1388),
+ S5K4ECGX_REG_WRITE(0x7000478C, 0x0180),
+ S5K4ECGX_REG_WRITE(0x7000478E, 0x0196),
+ S5K4ECGX_REG_WRITE(0x70004790, 0x0054),
+ S5K4ECGX_REG_WRITE(0x70004792, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70004794, 0x01CC),
+ S5K4ECGX_REG_WRITE(0x70004796, 0x01CC),
+ S5K4ECGX_REG_WRITE(0x70004798, 0x01CC),
+ S5K4ECGX_REG_WRITE(0x7000479A, 0x01CC),
+ S5K4ECGX_REG_WRITE(0x7000479C, 0x01CC),
+
+ S5K4ECGX_REG_WRITE(0x70000EF0, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000EF6, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x70001A84, 0x001C),
+
+ S5K4ECGX_REG_WRITE(0x700001F8, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700016E4, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x700001FA, 0x0003),
+ S5K4ECGX_REG_WRITE(0x700001FC, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000200, 0x0061),
+
+ S5K4ECGX_REG_WRITE(0x70000208, 0x2F0C),
+ S5K4ECGX_REG_WRITE(0x7000020A, 0x0190),
+
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000290, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000292, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0166),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0074),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x0132),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000702, 0x00FF),
+
+ S5K4ECGX_REG_WRITE(0x70001600, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000712, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x9002),
+
+ S5K4ECGX_REG_WRITE(0x70001616, 0x0003),
+
+ S5K4ECGX_REG_WRITE(0x700015A4, 0x0902),
+
+ S5K4ECGX_REG_WRITE(0x70001618, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001610, 0x0003),
+
+ S5K4ECGX_REG_WRITE(0x70001602, 0x00E5),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0098),
+
+ S5K4ECGX_REG_WRITE(0x70001598, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000159A, 0xD000),
+
+ S5K4ECGX_REG_WRITE(0x7000165E, 0xFF95),
+
+ S5K4ECGX_REG_WRITE(0x7000162E, 0x0280),
+
+ S5K4ECGX_REG_WRITE(0x7000163A, 0x03A0),
+ S5K4ECGX_REG_WRITE(0x7000163C, 0x0320),
+
+ S5K4ECGX_REG_WRITE(0x70001680, 0x0030),
+
+ S5K4ECGX_REG_WRITE(0x700016A4, 0x0060),
+
+ S5K4ECGX_REG_WRITE(0x70001698, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x7000161A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700015AA, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015AC, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015AE, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015B0, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015B2, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015B4, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015B6, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015B8, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015BA, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015BC, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015BE, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015C0, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015C2, 0x0066),
+ S5K4ECGX_REG_WRITE(0x700015C4, 0x006C),
+ S5K4ECGX_REG_WRITE(0x700015C6, 0x0072),
+ S5K4ECGX_REG_WRITE(0x700015C8, 0x0078),
+ S5K4ECGX_REG_WRITE(0x700015CA, 0x007E),
+ S5K4ECGX_REG_WRITE(0x700015CC, 0x0084),
+ S5K4ECGX_REG_WRITE(0x700015CE, 0x008A),
+ S5K4ECGX_REG_WRITE(0x700015D0, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700015D2, 0x0096),
+ S5K4ECGX_REG_WRITE(0x700015D4, 0x009C),
+ S5K4ECGX_REG_WRITE(0x700015D6, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x700015D8, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x700015DC, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x700015DE, 0x00BA),
+
+ S5K4ECGX_REG_WRITE(0x700016E6, 0x8000),
+ S5K4ECGX_REG_WRITE(0x700016E8, 0x0006),
+ S5K4ECGX_REG_WRITE(0x700016EA, 0x3FF0),
+ S5K4ECGX_REG_WRITE(0x700016EC, 0x03E8),
+ S5K4ECGX_REG_WRITE(0x700016EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700016F0, 0x0080),
+ S5K4ECGX_REG_WRITE(0x700016F2, 0x0009),
+ S5K4ECGX_REG_WRITE(0x700016F4, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700016F6, 0x0040),
+ S5K4ECGX_REG_WRITE(0x700016F8, 0x0080),
+ S5K4ECGX_REG_WRITE(0x700016FA, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x700016FC, 0x00E0),
+
+ S5K4ECGX_REG_WRITE(0x70000286, 0x0003),
+
+ S5K4ECGX_REG_WRITE(0x700011B4, 0x012C),
+ S5K4ECGX_REG_WRITE(0x700011B6, 0x0121),
+
+ S5K4ECGX_REG_WRITE(0x70001A00, 0x192E),
+ S5K4ECGX_REG_WRITE(0x70001A02, 0x7000),
+
+ S5K4ECGX_REG_WRITE(0x7000185C, 0x0004),
+ S5K4ECGX_REG_WRITE(0x7000185E, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x70001860, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001862, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001864, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70001866, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x70001868, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000186A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000186C, 0x0008),
+ S5K4ECGX_REG_WRITE(0x7000186E, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x70001870, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001872, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001874, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70001876, 0x0326),
+ S5K4ECGX_REG_WRITE(0x70001878, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000187A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000187C, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x7000187E, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x70001880, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001882, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001884, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70001886, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x70001888, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000188A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000188C, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x7000188E, 0x0327),
+ S5K4ECGX_REG_WRITE(0x70001890, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001892, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001894, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001896, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001898, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000189A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000189C, 0x0008),
+ S5K4ECGX_REG_WRITE(0x7000189E, 0x0084),
+ S5K4ECGX_REG_WRITE(0x700018A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018A4, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700018A6, 0x008D),
+ S5K4ECGX_REG_WRITE(0x700018A8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018AC, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700018AE, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700018B0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018B4, 0x00AA),
+ S5K4ECGX_REG_WRITE(0x700018B6, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700018B8, 0x03AD),
+ S5K4ECGX_REG_WRITE(0x700018BA, 0x09CD),
+ S5K4ECGX_REG_WRITE(0x700018BC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C4, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x700018C6, 0x02DE),
+ S5K4ECGX_REG_WRITE(0x700018C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D0, 0x02BE),
+ S5K4ECGX_REG_WRITE(0x700018D2, 0x02EE),
+ S5K4ECGX_REG_WRITE(0x700018D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018DC, 0x02CE),
+ S5K4ECGX_REG_WRITE(0x700018DE, 0x02EE),
+ S5K4ECGX_REG_WRITE(0x700018E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E8, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700018EA, 0x0009),
+ S5K4ECGX_REG_WRITE(0x700018EC, 0x0095),
+ S5K4ECGX_REG_WRITE(0x700018EE, 0x09DB),
+ S5K4ECGX_REG_WRITE(0x700018F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F4, 0x0096),
+ S5K4ECGX_REG_WRITE(0x700018F6, 0x009B),
+ S5K4ECGX_REG_WRITE(0x700018F8, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x700018FA, 0x02B3),
+ S5K4ECGX_REG_WRITE(0x700018FC, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x700018FE, 0x09D6),
+ S5K4ECGX_REG_WRITE(0x70001900, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001902, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001904, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001906, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001908, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001910, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001912, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001914, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001916, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001918, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x7000191A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000191C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000191E, 0x0009),
+ S5K4ECGX_REG_WRITE(0x70001920, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70001922, 0x0327),
+ S5K4ECGX_REG_WRITE(0x70001924, 0x0336),
+ S5K4ECGX_REG_WRITE(0x70001926, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001928, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192E, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70001930, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x70001932, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001934, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001936, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70001938, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x7000193A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000193C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000193E, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70001940, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x70001942, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001944, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001946, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001948, 0x024E),
+ S5K4ECGX_REG_WRITE(0x7000194A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000194C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000194E, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001950, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x70001952, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001954, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001956, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001958, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x7000195A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000195C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000195E, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001960, 0x024F),
+ S5K4ECGX_REG_WRITE(0x70001962, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001964, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001966, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001968, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196E, 0x0075),
+ S5K4ECGX_REG_WRITE(0x70001970, 0x00CF),
+ S5K4ECGX_REG_WRITE(0x70001972, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001974, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001976, 0x0075),
+ S5K4ECGX_REG_WRITE(0x70001978, 0x00D6),
+ S5K4ECGX_REG_WRITE(0x7000197A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000197C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000197E, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70001980, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001982, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001984, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001986, 0x00F0),
+ S5K4ECGX_REG_WRITE(0x70001988, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x7000198A, 0x029E),
+ S5K4ECGX_REG_WRITE(0x7000198C, 0x05B2),
+ S5K4ECGX_REG_WRITE(0x7000198E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001990, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001992, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001994, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001996, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x70001998, 0x0228),
+ S5K4ECGX_REG_WRITE(0x7000199A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000199C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000199E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A2, 0x0208),
+ S5K4ECGX_REG_WRITE(0x700019A4, 0x0238),
+ S5K4ECGX_REG_WRITE(0x700019A6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AE, 0x0218),
+ S5K4ECGX_REG_WRITE(0x700019B0, 0x0238),
+ S5K4ECGX_REG_WRITE(0x700019B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700019BC, 0x0009),
+ S5K4ECGX_REG_WRITE(0x700019BE, 0x00DE),
+ S5K4ECGX_REG_WRITE(0x700019C0, 0x05C0),
+ S5K4ECGX_REG_WRITE(0x700019C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C6, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x700019C8, 0x00E4),
+ S5K4ECGX_REG_WRITE(0x700019CA, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x700019CC, 0x01FD),
+ S5K4ECGX_REG_WRITE(0x700019CE, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x700019D0, 0x05BB),
+ S5K4ECGX_REG_WRITE(0x700019D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019EA, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x700019EC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F0, 0x0077),
+ S5K4ECGX_REG_WRITE(0x700019F2, 0x007E),
+ S5K4ECGX_REG_WRITE(0x700019F4, 0x024F),
+ S5K4ECGX_REG_WRITE(0x700019F6, 0x025E),
+ S5K4ECGX_REG_WRITE(0x700019F8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FE, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001836, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70001838, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000183A, 0x0003),
+
+ S5K4ECGX_REG_WRITE(0x7000183E, 0x0FB0),
+
+ S5K4ECGX_REG_WRITE(0x7000184C, 0x0060),
+ S5K4ECGX_REG_WRITE(0x7000184E, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70001850, 0x05C0),
+ S5K4ECGX_REG_WRITE(0x70001852, 0x05C0),
+
+ S5K4ECGX_REG_WRITE(0x70001A8A, 0x8080),
+ S5K4ECGX_REG_WRITE(0x70001A8C, 0x0080),
+
+ S5K4ECGX_REG_WRITE(0x70001A80, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001A12, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001842, 0x0004),
+
+ S5K4ECGX_REG_WRITE(0x70001A0A, 0x009A),
+
+ S5K4ECGX_REG_WRITE(0x70003776, 0x024C),
+
+ S5K4ECGX_REG_WRITE(0x70000EB2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700008C6, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700008A4, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700008E2, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008E4, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008E6, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008E8, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008EA, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008EC, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008EE, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F0, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F2, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F4, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F6, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F8, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FA, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FC, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FE, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000900, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000902, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000904, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000906, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000908, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090C, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090E, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000910, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000912, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000914, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000916, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000918, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000091A, 0x4500),
+ S5K4ECGX_REG_WRITE(0x7000091C, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000091E, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000920, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x700008E0, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001456, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001458, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000146A, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001470, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70001472, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70001474, 0x0102),
+ S5K4ECGX_REG_WRITE(0x70001476, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001478, 0x0403),
+ S5K4ECGX_REG_WRITE(0x7000147A, 0x0304),
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000147E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001480, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0102),
+ S5K4ECGX_REG_WRITE(0x70001486, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001488, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000148C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000148E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001490, 0x0202),
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0202),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0102),
+
+ S5K4ECGX_REG_WRITE(0x70001448, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x7000144E, 0x000F),
+
+ S5K4ECGX_REG_WRITE(0x70000580, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000582, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000584, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000586, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000588, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000058C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0x0470),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x1000),
+
+ S5K4ECGX_REG_WRITE(0x70000538, 0x0111),
+ S5K4ECGX_REG_WRITE(0x7000053A, 0x00EF),
+
+ S5K4ECGX_REG_WRITE(0x700005FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700005FE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000600, 0x0600),
+ S5K4ECGX_REG_WRITE(0x70000602, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000604, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000606, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0D04),
+ S5K4ECGX_REG_WRITE(0x7000060E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000610, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000612, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000614, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70000616, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000618, 0x9C00),
+ S5K4ECGX_REG_WRITE(0x7000061A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000061C, 0xAD00),
+ S5K4ECGX_REG_WRITE(0x7000061E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000620, 0xF1D4),
+ S5K4ECGX_REG_WRITE(0x70000622, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70000624, 0xDC00),
+ S5K4ECGX_REG_WRITE(0x70000626, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000628, 0xDC00),
+ S5K4ECGX_REG_WRITE(0x7000062A, 0x0005),
+ S5K4ECGX_REG_WRITE(0x7000062C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000062E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000630, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x70000632, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000634, 0x0D05),
+ S5K4ECGX_REG_WRITE(0x70000636, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000638, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x6810),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x8214),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000654, 0x0650),
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x700006AC, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006AE, 0x0004),
+
+ S5K4ECGX_REG_WRITE(0x70000280, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700005C4, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000476, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000478, 0x0280),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x7000047C, 0x0005),
+
+ S5K4ECGX_REG_WRITE(0x700001F4, 0x5DC0),
+
+ S5K4ECGX_REG_WRITE(0x7000020E, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70000210, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000212, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000216, 0x3A98),
+ S5K4ECGX_REG_WRITE(0x70000218, 0x4F1A),
+ S5K4ECGX_REG_WRITE(0x7000021A, 0x4F1A),
+ S5K4ECGX_REG_WRITE(0x7000021C, 0x4F1A),
+ S5K4ECGX_REG_WRITE(0x7000021E, 0x4F1A),
+ S5K4ECGX_REG_WRITE(0x70000220, 0x4F1A),
+
+ S5K4ECGX_REG_WRITE(0x70000228, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0280),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x4F1A),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x4F1A),
+
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x0052),
+
+ S5K4ECGX_REG_WRITE(0x700002B6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x014D),
+
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0080),
+
+ S5K4ECGX_REG_WRITE(0x7000024C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x000C),
+
+ S5K4ECGX_REG_WRITE(0x7000048E, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000490, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000260, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000392, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000394, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0009),
+ S5K4ECGX_REG_WRITE(0x70000398, 0x4F1A),
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x4F1A),
+
+ S5K4ECGX_REG_WRITE(0x700003A0, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x700003A8, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0002),
+ S5K4ECGX_REG_WRITE(0x700003AE, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x029A),
+
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0080),
+
+ S5K4ECGX_REG_WRITE(0x70000476, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000478, 0x0280),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x7000047C, 0x0005),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000023A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000472, 0x005F),
+ S5K4ECGX_REG_WRITE(0x70000474, 0x005F),
+
+ S5K4ECGX_REG_WRITE(0x70000FE0, 0x03B8),
+ S5K4ECGX_REG_WRITE(0x70000FE2, 0x03CE),
+ S5K4ECGX_REG_WRITE(0x70000FE4, 0x0350),
+ S5K4ECGX_REG_WRITE(0x70000FE6, 0x03C4),
+ S5K4ECGX_REG_WRITE(0x70000FE8, 0x02F2),
+ S5K4ECGX_REG_WRITE(0x70000FEA, 0x0394),
+ S5K4ECGX_REG_WRITE(0x70000FEC, 0x02C0),
+ S5K4ECGX_REG_WRITE(0x70000FEE, 0x0364),
+ S5K4ECGX_REG_WRITE(0x70000FF0, 0x029E),
+ S5K4ECGX_REG_WRITE(0x70000FF2, 0x0334),
+ S5K4ECGX_REG_WRITE(0x70000FF4, 0x027C),
+ S5K4ECGX_REG_WRITE(0x70000FF6, 0x0312),
+ S5K4ECGX_REG_WRITE(0x70000FF8, 0x025E),
+ S5K4ECGX_REG_WRITE(0x70000FFA, 0x02F2),
+ S5K4ECGX_REG_WRITE(0x70000FFC, 0x0246),
+ S5K4ECGX_REG_WRITE(0x70000FFE, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x70001000, 0x0230),
+ S5K4ECGX_REG_WRITE(0x70001002, 0x02B0),
+ S5K4ECGX_REG_WRITE(0x70001004, 0x0218),
+ S5K4ECGX_REG_WRITE(0x70001006, 0x029E),
+ S5K4ECGX_REG_WRITE(0x70001008, 0x0208),
+ S5K4ECGX_REG_WRITE(0x7000100A, 0x0290),
+ S5K4ECGX_REG_WRITE(0x7000100C, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000100E, 0x0284),
+ S5K4ECGX_REG_WRITE(0x70001010, 0x01E8),
+ S5K4ECGX_REG_WRITE(0x70001012, 0x0276),
+ S5K4ECGX_REG_WRITE(0x70001014, 0x01DA),
+ S5K4ECGX_REG_WRITE(0x70001016, 0x026A),
+ S5K4ECGX_REG_WRITE(0x70001018, 0x01CE),
+ S5K4ECGX_REG_WRITE(0x7000101A, 0x025E),
+ S5K4ECGX_REG_WRITE(0x7000101C, 0x01EC),
+ S5K4ECGX_REG_WRITE(0x7000101E, 0x022E),
+ S5K4ECGX_REG_WRITE(0x70001020, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001022, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001024, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001026, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001028, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000102A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000102C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000102E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001030, 0x0005),
+
+ S5K4ECGX_REG_WRITE(0x70001034, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x70001038, 0x0126),
+
+ S5K4ECGX_REG_WRITE(0x7000103C, 0x026C),
+ S5K4ECGX_REG_WRITE(0x7000103E, 0x029A),
+ S5K4ECGX_REG_WRITE(0x70001040, 0x025C),
+ S5K4ECGX_REG_WRITE(0x70001042, 0x02B6),
+ S5K4ECGX_REG_WRITE(0x70001044, 0x024E),
+ S5K4ECGX_REG_WRITE(0x70001046, 0x02C0),
+ S5K4ECGX_REG_WRITE(0x70001048, 0x0240),
+ S5K4ECGX_REG_WRITE(0x7000104A, 0x02BE),
+ S5K4ECGX_REG_WRITE(0x7000104C, 0x023A),
+ S5K4ECGX_REG_WRITE(0x7000104E, 0x02B4),
+ S5K4ECGX_REG_WRITE(0x70001050, 0x023A),
+ S5K4ECGX_REG_WRITE(0x70001052, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70001054, 0x0240),
+ S5K4ECGX_REG_WRITE(0x70001056, 0x029E),
+ S5K4ECGX_REG_WRITE(0x70001058, 0x025C),
+ S5K4ECGX_REG_WRITE(0x7000105A, 0x0294),
+ S5K4ECGX_REG_WRITE(0x7000105C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001060, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001062, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001064, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001066, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001068, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000106A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000106C, 0x0004),
+
+ S5K4ECGX_REG_WRITE(0x70001070, 0x0008),
+
+ S5K4ECGX_REG_WRITE(0x70001074, 0x01E2),
+
+ S5K4ECGX_REG_WRITE(0x70001078, 0x0350),
+ S5K4ECGX_REG_WRITE(0x7000107A, 0x0422),
+ S5K4ECGX_REG_WRITE(0x7000107C, 0x02C4),
+ S5K4ECGX_REG_WRITE(0x7000107E, 0x0452),
+ S5K4ECGX_REG_WRITE(0x70001080, 0x0278),
+ S5K4ECGX_REG_WRITE(0x70001082, 0x041C),
+ S5K4ECGX_REG_WRITE(0x70001084, 0x0230),
+ S5K4ECGX_REG_WRITE(0x70001086, 0x03EE),
+ S5K4ECGX_REG_WRITE(0x70001088, 0x01F0),
+ S5K4ECGX_REG_WRITE(0x7000108A, 0x0392),
+ S5K4ECGX_REG_WRITE(0x7000108C, 0x01C0),
+ S5K4ECGX_REG_WRITE(0x7000108E, 0x0340),
+ S5K4ECGX_REG_WRITE(0x70001090, 0x0194),
+ S5K4ECGX_REG_WRITE(0x70001092, 0x0302),
+ S5K4ECGX_REG_WRITE(0x70001094, 0x016E),
+ S5K4ECGX_REG_WRITE(0x70001096, 0x02C2),
+ S5K4ECGX_REG_WRITE(0x70001098, 0x0148),
+ S5K4ECGX_REG_WRITE(0x7000109A, 0x0286),
+ S5K4ECGX_REG_WRITE(0x7000109C, 0x018A),
+ S5K4ECGX_REG_WRITE(0x7000109E, 0x0242),
+ S5K4ECGX_REG_WRITE(0x700010A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A8, 0x0006),
+
+ S5K4ECGX_REG_WRITE(0x700010AC, 0x000A),
+
+ S5K4ECGX_REG_WRITE(0x700010B0, 0x0106),
+
+ S5K4ECGX_REG_WRITE(0x700010B4, 0x0380),
+ S5K4ECGX_REG_WRITE(0x700010B6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010B8, 0x0168),
+ S5K4ECGX_REG_WRITE(0x700010BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010BC, 0x2D90),
+ S5K4ECGX_REG_WRITE(0x700010BE, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001428, 0x0008),
+ S5K4ECGX_REG_WRITE(0x7000142A, 0x0190),
+ S5K4ECGX_REG_WRITE(0x7000142C, 0x00A0),
+
+ S5K4ECGX_REG_WRITE(0x700011EC, 0x00C0),
+
+ S5K4ECGX_REG_WRITE(0x700011F0, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x700011EE, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x700011CE, 0x05D5),
+
+ S5K4ECGX_REG_WRITE(0x700011D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700011D4, 0x0771),
+ S5K4ECGX_REG_WRITE(0x700011D6, 0x03A4),
+ S5K4ECGX_REG_WRITE(0x700011D8, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700011DA, 0x002A),
+
+ S5K4ECGX_REG_WRITE(0x700008AC, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x700008AE, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x700008B0, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700008B2, 0x0125),
+ S5K4ECGX_REG_WRITE(0x700008B4, 0x015F),
+ S5K4ECGX_REG_WRITE(0x700008B6, 0x017C),
+ S5K4ECGX_REG_WRITE(0x700008B8, 0x0194),
+
+ S5K4ECGX_REG_WRITE(0x7000123C, 0xFEF7),
+ S5K4ECGX_REG_WRITE(0x7000123E, 0x0021),
+ S5K4ECGX_REG_WRITE(0x70001240, 0x0E74),
+ S5K4ECGX_REG_WRITE(0x70001242, 0x0E74),
+ S5K4ECGX_REG_WRITE(0x70001244, 0x018F),
+ S5K4ECGX_REG_WRITE(0x70001246, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001248, 0x000E),
+
+ S5K4ECGX_REG_WRITE(0x700011E8, 0x0032),
+ S5K4ECGX_REG_WRITE(0x700011EA, 0x001E),
+
+ S5K4ECGX_REG_WRITE(0x70002ABC, 0x0006),
+
+ S5K4ECGX_REG_WRITE(0x70001430, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x7000140A, 0x00AB),
+ S5K4ECGX_REG_WRITE(0x7000140C, 0x00BF),
+ S5K4ECGX_REG_WRITE(0x7000140E, 0x00D2),
+ S5K4ECGX_REG_WRITE(0x70001410, 0x0093),
+
+ S5K4ECGX_REG_WRITE(0x700013F8, 0x0300),
+ S5K4ECGX_REG_WRITE(0x700013FA, 0x036E),
+ S5K4ECGX_REG_WRITE(0x700013FC, 0x03C2),
+ S5K4ECGX_REG_WRITE(0x700013FE, 0x1015),
+ S5K4ECGX_REG_WRITE(0x70001400, 0x10E1),
+ S5K4ECGX_REG_WRITE(0x70001402, 0x1154),
+ S5K4ECGX_REG_WRITE(0x70001404, 0x11A8),
+ S5K4ECGX_REG_WRITE(0x70001406, 0x11BB),
+ S5K4ECGX_REG_WRITE(0x70001408, 0x123B),
+
+ S5K4ECGX_REG_WRITE(0x70001368, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000136A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000136C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000136E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001370, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70001372, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70001374, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001376, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001378, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000137A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000137C, 0x0008),
+ S5K4ECGX_REG_WRITE(0x7000137E, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70001380, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001382, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001384, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001386, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001388, 0x0008),
+ S5K4ECGX_REG_WRITE(0x7000138A, 0x0030),
+ S5K4ECGX_REG_WRITE(0x7000138C, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x7000138E, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x70001390, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001392, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001394, 0xFFA0),
+ S5K4ECGX_REG_WRITE(0x70001396, 0xFE36),
+ S5K4ECGX_REG_WRITE(0x70001398, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x7000139A, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x7000139C, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x7000139E, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013A0, 0xFFA0),
+ S5K4ECGX_REG_WRITE(0x700013A2, 0xFE36),
+ S5K4ECGX_REG_WRITE(0x700013A4, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013A6, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013A8, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013AA, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013AC, 0xFFA0),
+ S5K4ECGX_REG_WRITE(0x700013AE, 0xFE36),
+ S5K4ECGX_REG_WRITE(0x700013B0, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x700013B2, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x700013B4, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013B6, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013B8, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013BA, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013BC, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x700013BE, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x700013C0, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013C2, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013C4, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013C6, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013C8, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x700013CA, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x700013CC, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013CE, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013D0, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013D2, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700013D4, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013D6, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013D8, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013DA, 0xFDA0),
+ S5K4ECGX_REG_WRITE(0x700013DC, 0xFCF0),
+ S5K4ECGX_REG_WRITE(0x700013DE, 0xFCD0),
+ S5K4ECGX_REG_WRITE(0x700013E0, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013E2, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013E4, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013E6, 0xFDA0),
+ S5K4ECGX_REG_WRITE(0x700013E8, 0xFCF0),
+ S5K4ECGX_REG_WRITE(0x700013EA, 0xFCD0),
+ S5K4ECGX_REG_WRITE(0x700013EC, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013EE, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013F0, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700013F2, 0xFDA0),
+ S5K4ECGX_REG_WRITE(0x700013F4, 0xFCF0),
+ S5K4ECGX_REG_WRITE(0x700013F6, 0xFCD0),
+
+ S5K4ECGX_REG_WRITE(0x700013FE, 0x1015),
+ S5K4ECGX_REG_WRITE(0x70001400, 0x106C),
+ S5K4ECGX_REG_WRITE(0x70001402, 0x10CA),
+ S5K4ECGX_REG_WRITE(0x70001404, 0x1142),
+ S5K4ECGX_REG_WRITE(0x70001406, 0x11BB),
+ S5K4ECGX_REG_WRITE(0x70001408, 0x123B),
+ S5K4ECGX_REG_WRITE(0x7000140A, 0x00AB),
+ S5K4ECGX_REG_WRITE(0x7000140C, 0x00BF),
+ S5K4ECGX_REG_WRITE(0x7000140E, 0x00D2),
+ S5K4ECGX_REG_WRITE(0x70001410, 0x0093),
+
+ S5K4ECGX_REG_WRITE(0x700011CC, 0x0020),
+
+ S5K4ECGX_REG_WRITE(0x70001412, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001414, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001416, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000724, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000726, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000728, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000072A, 0x0028),
+ S5K4ECGX_REG_WRITE(0x7000072C, 0x0062),
+ S5K4ECGX_REG_WRITE(0x7000072E, 0x00D3),
+ S5K4ECGX_REG_WRITE(0x70000730, 0x0130),
+ S5K4ECGX_REG_WRITE(0x70000732, 0x0158),
+ S5K4ECGX_REG_WRITE(0x70000734, 0x017D),
+ S5K4ECGX_REG_WRITE(0x70000736, 0x01BE),
+ S5K4ECGX_REG_WRITE(0x70000738, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000073A, 0x022C),
+ S5K4ECGX_REG_WRITE(0x7000073C, 0x025B),
+ S5K4ECGX_REG_WRITE(0x7000073E, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70000740, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x70000742, 0x034E),
+ S5K4ECGX_REG_WRITE(0x70000744, 0x0396),
+ S5K4ECGX_REG_WRITE(0x70000746, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x70000748, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x7000074A, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x7000074C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000074E, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000750, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000752, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000754, 0x0062),
+ S5K4ECGX_REG_WRITE(0x70000756, 0x00D3),
+ S5K4ECGX_REG_WRITE(0x70000758, 0x0130),
+ S5K4ECGX_REG_WRITE(0x7000075A, 0x0158),
+ S5K4ECGX_REG_WRITE(0x7000075C, 0x017D),
+ S5K4ECGX_REG_WRITE(0x7000075E, 0x01BE),
+ S5K4ECGX_REG_WRITE(0x70000760, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x70000762, 0x022C),
+ S5K4ECGX_REG_WRITE(0x70000764, 0x025B),
+ S5K4ECGX_REG_WRITE(0x70000766, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70000768, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x7000076A, 0x034E),
+ S5K4ECGX_REG_WRITE(0x7000076C, 0x0396),
+ S5K4ECGX_REG_WRITE(0x7000076E, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x70000770, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x70000772, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x70000774, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000776, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000778, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000077A, 0x0028),
+ S5K4ECGX_REG_WRITE(0x7000077C, 0x0062),
+ S5K4ECGX_REG_WRITE(0x7000077E, 0x00D3),
+ S5K4ECGX_REG_WRITE(0x70000780, 0x0130),
+ S5K4ECGX_REG_WRITE(0x70000782, 0x0158),
+ S5K4ECGX_REG_WRITE(0x70000784, 0x017D),
+ S5K4ECGX_REG_WRITE(0x70000786, 0x01BE),
+ S5K4ECGX_REG_WRITE(0x70000788, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000078A, 0x022C),
+ S5K4ECGX_REG_WRITE(0x7000078C, 0x025B),
+ S5K4ECGX_REG_WRITE(0x7000078E, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70000790, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x70000792, 0x034E),
+ S5K4ECGX_REG_WRITE(0x70000794, 0x0396),
+ S5K4ECGX_REG_WRITE(0x70000796, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x70000798, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x7000079A, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x7000079C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000079E, 0x000F),
+ S5K4ECGX_REG_WRITE(0x700007A0, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700007A2, 0x0043),
+ S5K4ECGX_REG_WRITE(0x700007A4, 0x0086),
+ S5K4ECGX_REG_WRITE(0x700007A6, 0x00ED),
+ S5K4ECGX_REG_WRITE(0x700007A8, 0x013E),
+ S5K4ECGX_REG_WRITE(0x700007AA, 0x0163),
+ S5K4ECGX_REG_WRITE(0x700007AC, 0x0185),
+ S5K4ECGX_REG_WRITE(0x700007AE, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x700007B0, 0x01F2),
+ S5K4ECGX_REG_WRITE(0x700007B2, 0x0221),
+ S5K4ECGX_REG_WRITE(0x700007B4, 0x024A),
+ S5K4ECGX_REG_WRITE(0x700007B6, 0x0294),
+ S5K4ECGX_REG_WRITE(0x700007B8, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700007BA, 0x032A),
+ S5K4ECGX_REG_WRITE(0x700007BC, 0x036A),
+ S5K4ECGX_REG_WRITE(0x700007BE, 0x039F),
+ S5K4ECGX_REG_WRITE(0x700007C0, 0x03CC),
+ S5K4ECGX_REG_WRITE(0x700007C2, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x700007C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700007C6, 0x000F),
+ S5K4ECGX_REG_WRITE(0x700007C8, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700007CA, 0x0043),
+ S5K4ECGX_REG_WRITE(0x700007CC, 0x0086),
+ S5K4ECGX_REG_WRITE(0x700007CE, 0x00ED),
+ S5K4ECGX_REG_WRITE(0x700007D0, 0x013E),
+ S5K4ECGX_REG_WRITE(0x700007D2, 0x0163),
+ S5K4ECGX_REG_WRITE(0x700007D4, 0x0185),
+ S5K4ECGX_REG_WRITE(0x700007D6, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x700007D8, 0x01F2),
+ S5K4ECGX_REG_WRITE(0x700007DA, 0x0221),
+ S5K4ECGX_REG_WRITE(0x700007DC, 0x024A),
+ S5K4ECGX_REG_WRITE(0x700007DE, 0x0294),
+ S5K4ECGX_REG_WRITE(0x700007E0, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700007E2, 0x032A),
+ S5K4ECGX_REG_WRITE(0x700007E4, 0x036A),
+ S5K4ECGX_REG_WRITE(0x700007E6, 0x039F),
+ S5K4ECGX_REG_WRITE(0x700007E8, 0x03CC),
+ S5K4ECGX_REG_WRITE(0x700007EA, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x700007EC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700007EE, 0x000F),
+ S5K4ECGX_REG_WRITE(0x700007F0, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700007F2, 0x0043),
+ S5K4ECGX_REG_WRITE(0x700007F4, 0x0086),
+ S5K4ECGX_REG_WRITE(0x700007F6, 0x00ED),
+ S5K4ECGX_REG_WRITE(0x700007F8, 0x013E),
+ S5K4ECGX_REG_WRITE(0x700007FA, 0x0163),
+ S5K4ECGX_REG_WRITE(0x700007FC, 0x0185),
+ S5K4ECGX_REG_WRITE(0x700007FE, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x70000800, 0x01F2),
+ S5K4ECGX_REG_WRITE(0x70000802, 0x0221),
+ S5K4ECGX_REG_WRITE(0x70000804, 0x024A),
+ S5K4ECGX_REG_WRITE(0x70000806, 0x0294),
+ S5K4ECGX_REG_WRITE(0x70000808, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x7000080A, 0x032A),
+ S5K4ECGX_REG_WRITE(0x7000080C, 0x036A),
+ S5K4ECGX_REG_WRITE(0x7000080E, 0x039F),
+ S5K4ECGX_REG_WRITE(0x70000810, 0x03CC),
+ S5K4ECGX_REG_WRITE(0x70000812, 0x03F9),
+
+ S5K4ECGX_REG_WRITE(0x70000896, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000898, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000089A, 0x0125),
+ S5K4ECGX_REG_WRITE(0x7000089C, 0x015F),
+ S5K4ECGX_REG_WRITE(0x7000089E, 0x017C),
+ S5K4ECGX_REG_WRITE(0x700008A0, 0x0194),
+ S5K4ECGX_REG_WRITE(0x700008A2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000888, 0x4800),
+ S5K4ECGX_REG_WRITE(0x7000088A, 0x7000),
+
+ S5K4ECGX_REG_WRITE(0x70004800, 0x016C),
+ S5K4ECGX_REG_WRITE(0x70004802, 0xFF94),
+ S5K4ECGX_REG_WRITE(0x70004804, 0xFFCE),
+ S5K4ECGX_REG_WRITE(0x70004806, 0xFF20),
+ S5K4ECGX_REG_WRITE(0x70004808, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x7000480A, 0xFF53),
+ S5K4ECGX_REG_WRITE(0x7000480C, 0x003F),
+ S5K4ECGX_REG_WRITE(0x7000480E, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70004810, 0x01DF),
+ S5K4ECGX_REG_WRITE(0x70004812, 0x0110),
+ S5K4ECGX_REG_WRITE(0x70004814, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x70004816, 0xFF47),
+ S5K4ECGX_REG_WRITE(0x70004818, 0x0206),
+ S5K4ECGX_REG_WRITE(0x7000481A, 0xFF7F),
+ S5K4ECGX_REG_WRITE(0x7000481C, 0x0191),
+ S5K4ECGX_REG_WRITE(0x7000481E, 0xFF06),
+ S5K4ECGX_REG_WRITE(0x70004820, 0x01BA),
+ S5K4ECGX_REG_WRITE(0x70004822, 0x0108),
+ S5K4ECGX_REG_WRITE(0x70004824, 0x016C),
+ S5K4ECGX_REG_WRITE(0x70004826, 0xFF94),
+ S5K4ECGX_REG_WRITE(0x70004828, 0xFFCE),
+ S5K4ECGX_REG_WRITE(0x7000482A, 0xFF20),
+ S5K4ECGX_REG_WRITE(0x7000482C, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x7000482E, 0xFF53),
+ S5K4ECGX_REG_WRITE(0x70004830, 0x003F),
+ S5K4ECGX_REG_WRITE(0x70004832, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70004834, 0x01DF),
+ S5K4ECGX_REG_WRITE(0x70004836, 0x0110),
+ S5K4ECGX_REG_WRITE(0x70004838, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x7000483A, 0xFF47),
+ S5K4ECGX_REG_WRITE(0x7000483C, 0x0206),
+ S5K4ECGX_REG_WRITE(0x7000483E, 0xFF7F),
+ S5K4ECGX_REG_WRITE(0x70004840, 0x0191),
+ S5K4ECGX_REG_WRITE(0x70004842, 0xFF06),
+ S5K4ECGX_REG_WRITE(0x70004844, 0x01BA),
+ S5K4ECGX_REG_WRITE(0x70004846, 0x0108),
+ S5K4ECGX_REG_WRITE(0x70004848, 0x016C),
+ S5K4ECGX_REG_WRITE(0x7000484A, 0xFF94),
+ S5K4ECGX_REG_WRITE(0x7000484C, 0xFFCE),
+ S5K4ECGX_REG_WRITE(0x7000484E, 0xFF20),
+ S5K4ECGX_REG_WRITE(0x70004850, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x70004852, 0xFF53),
+ S5K4ECGX_REG_WRITE(0x70004854, 0x003F),
+ S5K4ECGX_REG_WRITE(0x70004856, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70004858, 0x01DF),
+ S5K4ECGX_REG_WRITE(0x7000485A, 0x0110),
+ S5K4ECGX_REG_WRITE(0x7000485C, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x7000485E, 0xFF47),
+ S5K4ECGX_REG_WRITE(0x70004860, 0x0206),
+ S5K4ECGX_REG_WRITE(0x70004862, 0xFF7F),
+ S5K4ECGX_REG_WRITE(0x70004864, 0x0191),
+ S5K4ECGX_REG_WRITE(0x70004866, 0xFF06),
+ S5K4ECGX_REG_WRITE(0x70004868, 0x01BA),
+ S5K4ECGX_REG_WRITE(0x7000486A, 0x0108),
+ S5K4ECGX_REG_WRITE(0x7000486C, 0x0208),
+ S5K4ECGX_REG_WRITE(0x7000486E, 0xFFD3),
+ S5K4ECGX_REG_WRITE(0x70004870, 0xFFE9),
+ S5K4ECGX_REG_WRITE(0x70004872, 0xFF5B),
+ S5K4ECGX_REG_WRITE(0x70004874, 0x025A),
+ S5K4ECGX_REG_WRITE(0x70004876, 0xFF80),
+ S5K4ECGX_REG_WRITE(0x70004878, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x7000487A, 0xFFC1),
+ S5K4ECGX_REG_WRITE(0x7000487C, 0x013A),
+ S5K4ECGX_REG_WRITE(0x7000487E, 0x0112),
+ S5K4ECGX_REG_WRITE(0x70004880, 0x00EE),
+ S5K4ECGX_REG_WRITE(0x70004882, 0xFF99),
+ S5K4ECGX_REG_WRITE(0x70004884, 0x009E),
+ S5K4ECGX_REG_WRITE(0x70004886, 0xFF5F),
+ S5K4ECGX_REG_WRITE(0x70004888, 0x01A8),
+ S5K4ECGX_REG_WRITE(0x7000488A, 0xFF75),
+ S5K4ECGX_REG_WRITE(0x7000488C, 0x0187),
+ S5K4ECGX_REG_WRITE(0x7000488E, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x70004890, 0x0208),
+ S5K4ECGX_REG_WRITE(0x70004892, 0xFFD3),
+ S5K4ECGX_REG_WRITE(0x70004894, 0xFFE9),
+ S5K4ECGX_REG_WRITE(0x70004896, 0xFF5B),
+ S5K4ECGX_REG_WRITE(0x70004898, 0x025A),
+ S5K4ECGX_REG_WRITE(0x7000489A, 0xFF80),
+ S5K4ECGX_REG_WRITE(0x7000489C, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x7000489E, 0xFFC1),
+ S5K4ECGX_REG_WRITE(0x700048A0, 0x013A),
+ S5K4ECGX_REG_WRITE(0x700048A2, 0x0112),
+ S5K4ECGX_REG_WRITE(0x700048A4, 0x00EE),
+ S5K4ECGX_REG_WRITE(0x700048A6, 0xFF99),
+ S5K4ECGX_REG_WRITE(0x700048A8, 0x009E),
+ S5K4ECGX_REG_WRITE(0x700048AA, 0xFF5F),
+ S5K4ECGX_REG_WRITE(0x700048AC, 0x01A8),
+ S5K4ECGX_REG_WRITE(0x700048AE, 0xFF75),
+ S5K4ECGX_REG_WRITE(0x700048B0, 0x0187),
+ S5K4ECGX_REG_WRITE(0x700048B2, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x700048B4, 0x0208),
+ S5K4ECGX_REG_WRITE(0x700048B6, 0xFFD3),
+ S5K4ECGX_REG_WRITE(0x700048B8, 0xFFE9),
+ S5K4ECGX_REG_WRITE(0x700048BA, 0xFF5B),
+ S5K4ECGX_REG_WRITE(0x700048BC, 0x025A),
+ S5K4ECGX_REG_WRITE(0x700048BE, 0xFF80),
+ S5K4ECGX_REG_WRITE(0x700048C0, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x700048C2, 0xFFC1),
+ S5K4ECGX_REG_WRITE(0x700048C4, 0x013A),
+ S5K4ECGX_REG_WRITE(0x700048C6, 0x0112),
+ S5K4ECGX_REG_WRITE(0x700048C8, 0x00EE),
+ S5K4ECGX_REG_WRITE(0x700048CA, 0xFF99),
+ S5K4ECGX_REG_WRITE(0x700048CC, 0x009E),
+ S5K4ECGX_REG_WRITE(0x700048CE, 0xFF5F),
+ S5K4ECGX_REG_WRITE(0x700048D0, 0x01A8),
+ S5K4ECGX_REG_WRITE(0x700048D2, 0xFF75),
+ S5K4ECGX_REG_WRITE(0x700048D4, 0x0187),
+ S5K4ECGX_REG_WRITE(0x700048D6, 0x01BF),
+
+ S5K4ECGX_REG_WRITE(0x70000890, 0x48D8),
+ S5K4ECGX_REG_WRITE(0x70000892, 0x7000),
+
+ S5K4ECGX_REG_WRITE(0x700048D8, 0x01AA),
+ S5K4ECGX_REG_WRITE(0x700048DA, 0xFFB6),
+ S5K4ECGX_REG_WRITE(0x700048DC, 0xFFD4),
+ S5K4ECGX_REG_WRITE(0x700048DE, 0xFF6C),
+ S5K4ECGX_REG_WRITE(0x700048E0, 0x01E8),
+ S5K4ECGX_REG_WRITE(0x700048E2, 0xFF79),
+ S5K4ECGX_REG_WRITE(0x700048E4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700048E6, 0xFFF5),
+ S5K4ECGX_REG_WRITE(0x700048E8, 0x023C),
+ S5K4ECGX_REG_WRITE(0x700048EA, 0x00BF),
+ S5K4ECGX_REG_WRITE(0x700048EC, 0x00E0),
+ S5K4ECGX_REG_WRITE(0x700048EE, 0xFF5B),
+ S5K4ECGX_REG_WRITE(0x700048F0, 0x022D),
+ S5K4ECGX_REG_WRITE(0x700048F2, 0xFF9B),
+ S5K4ECGX_REG_WRITE(0x700048F4, 0x01E1),
+ S5K4ECGX_REG_WRITE(0x700048F6, 0xFF34),
+ S5K4ECGX_REG_WRITE(0x700048F8, 0x014B),
+ S5K4ECGX_REG_WRITE(0x700048FA, 0x01B6),
+
+ S5K4ECGX_REG_WRITE(0x70000924, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70000926, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x70000928, 0x0196),
+ S5K4ECGX_REG_WRITE(0x7000092A, 0x0245),
+ S5K4ECGX_REG_WRITE(0x7000092C, 0x0300),
+
+ S5K4ECGX_REG_WRITE(0x70000958, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000095A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000095C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000095E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000960, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000962, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000964, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000966, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000968, 0x0032),
+ S5K4ECGX_REG_WRITE(0x7000096A, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x7000096C, 0x0070),
+ S5K4ECGX_REG_WRITE(0x7000096E, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000970, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000972, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000974, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000976, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000978, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x7000097A, 0x1430),
+ S5K4ECGX_REG_WRITE(0x7000097C, 0x0201),
+ S5K4ECGX_REG_WRITE(0x7000097E, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000980, 0x3604),
+ S5K4ECGX_REG_WRITE(0x70000982, 0x032A),
+ S5K4ECGX_REG_WRITE(0x70000984, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70000986, 0x1B06),
+ S5K4ECGX_REG_WRITE(0x70000988, 0x6015),
+ S5K4ECGX_REG_WRITE(0x7000098A, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000098C, 0x6080),
+ S5K4ECGX_REG_WRITE(0x7000098E, 0x4080),
+ S5K4ECGX_REG_WRITE(0x70000990, 0x0640),
+ S5K4ECGX_REG_WRITE(0x70000992, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000994, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000996, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000998, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000099A, 0x0400),
+ S5K4ECGX_REG_WRITE(0x7000099C, 0x365A),
+ S5K4ECGX_REG_WRITE(0x7000099E, 0x102A),
+ S5K4ECGX_REG_WRITE(0x700009A0, 0x000B),
+ S5K4ECGX_REG_WRITE(0x700009A2, 0x0600),
+ S5K4ECGX_REG_WRITE(0x700009A4, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x700009A6, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700009A8, 0x1802),
+ S5K4ECGX_REG_WRITE(0x700009AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009AC, 0x2006),
+ S5K4ECGX_REG_WRITE(0x700009AE, 0x3028),
+ S5K4ECGX_REG_WRITE(0x700009B0, 0x0418),
+ S5K4ECGX_REG_WRITE(0x700009B2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700009B4, 0x0800),
+ S5K4ECGX_REG_WRITE(0x700009B6, 0x1804),
+ S5K4ECGX_REG_WRITE(0x700009B8, 0x4008),
+ S5K4ECGX_REG_WRITE(0x700009BA, 0x0540),
+ S5K4ECGX_REG_WRITE(0x700009BC, 0x8006),
+ S5K4ECGX_REG_WRITE(0x700009BE, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700009C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009C2, 0x1800),
+ S5K4ECGX_REG_WRITE(0x700009C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009C6, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x700009C8, 0x000B),
+ S5K4ECGX_REG_WRITE(0x700009CA, 0x0607),
+ S5K4ECGX_REG_WRITE(0x700009CC, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700009CE, 0x0607),
+ S5K4ECGX_REG_WRITE(0x700009D0, 0x0405),
+ S5K4ECGX_REG_WRITE(0x700009D2, 0x0205),
+ S5K4ECGX_REG_WRITE(0x700009D4, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700009D6, 0x0409),
+ S5K4ECGX_REG_WRITE(0x700009D8, 0x0306),
+ S5K4ECGX_REG_WRITE(0x700009DA, 0x0407),
+ S5K4ECGX_REG_WRITE(0x700009DC, 0x1C04),
+ S5K4ECGX_REG_WRITE(0x700009DE, 0x0214),
+ S5K4ECGX_REG_WRITE(0x700009E0, 0x1002),
+ S5K4ECGX_REG_WRITE(0x700009E2, 0x0610),
+ S5K4ECGX_REG_WRITE(0x700009E4, 0x0F02),
+ S5K4ECGX_REG_WRITE(0x700009E6, 0x4A18),
+ S5K4ECGX_REG_WRITE(0x700009E8, 0x0080),
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x0040),
+ S5K4ECGX_REG_WRITE(0x700009EC, 0x0180),
+ S5K4ECGX_REG_WRITE(0x700009EE, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x700009F0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700009F2, 0x2A36),
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x6024),
+ S5K4ECGX_REG_WRITE(0x700009F6, 0x2A36),
+ S5K4ECGX_REG_WRITE(0x700009F8, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x700009FA, 0x0808),
+ S5K4ECGX_REG_WRITE(0x700009FC, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x700009FE, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000A00, 0x3601),
+ S5K4ECGX_REG_WRITE(0x70000A02, 0x242A),
+ S5K4ECGX_REG_WRITE(0x70000A04, 0x3660),
+ S5K4ECGX_REG_WRITE(0x70000A06, 0xFF2A),
+ S5K4ECGX_REG_WRITE(0x70000A08, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000A0A, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000A0C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000A0E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A10, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A12, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A14, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A16, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A18, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000A1C, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70000A20, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000A22, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000A24, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000A26, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000A2A, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000A2C, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000A2E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000A30, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000A32, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000A34, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000A36, 0x2404),
+ S5K4ECGX_REG_WRITE(0x70000A38, 0x031B),
+ S5K4ECGX_REG_WRITE(0x70000A3A, 0x0103),
+ S5K4ECGX_REG_WRITE(0x70000A3C, 0x1205),
+ S5K4ECGX_REG_WRITE(0x70000A3E, 0x400D),
+ S5K4ECGX_REG_WRITE(0x70000A40, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000A42, 0x2080),
+ S5K4ECGX_REG_WRITE(0x70000A44, 0x3040),
+ S5K4ECGX_REG_WRITE(0x70000A46, 0x0630),
+ S5K4ECGX_REG_WRITE(0x70000A48, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000A4A, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000A4C, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000A4E, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000A50, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70000A52, 0x245A),
+ S5K4ECGX_REG_WRITE(0x70000A54, 0x1018),
+ S5K4ECGX_REG_WRITE(0x70000A56, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000A58, 0x0B00),
+ S5K4ECGX_REG_WRITE(0x70000A5A, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000A5C, 0x0505),
+ S5K4ECGX_REG_WRITE(0x70000A5E, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000A60, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A62, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000A64, 0x3428),
+ S5K4ECGX_REG_WRITE(0x70000A66, 0x041C),
+ S5K4ECGX_REG_WRITE(0x70000A68, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000A6A, 0x0800),
+ S5K4ECGX_REG_WRITE(0x70000A6C, 0x1004),
+ S5K4ECGX_REG_WRITE(0x70000A6E, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000A70, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000A72, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000A74, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000A76, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A78, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000A7A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A7C, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000A7E, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000A80, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000A82, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000A84, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000A86, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000A88, 0x0205),
+ S5K4ECGX_REG_WRITE(0x70000A8A, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000A8C, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000A8E, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000A90, 0x0407),
+ S5K4ECGX_REG_WRITE(0x70000A92, 0x1F04),
+ S5K4ECGX_REG_WRITE(0x70000A94, 0x0218),
+ S5K4ECGX_REG_WRITE(0x70000A96, 0x1102),
+ S5K4ECGX_REG_WRITE(0x70000A98, 0x0611),
+ S5K4ECGX_REG_WRITE(0x70000A9A, 0x1002),
+ S5K4ECGX_REG_WRITE(0x70000A9C, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000A9E, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000AA0, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000AA2, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000AA4, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000AA6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000AA8, 0x1B24),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000AAC, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000AAE, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000AB0, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000AB2, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000AB4, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000AB6, 0x2401),
+ S5K4ECGX_REG_WRITE(0x70000AB8, 0x241B),
+ S5K4ECGX_REG_WRITE(0x70000ABA, 0x1E60),
+ S5K4ECGX_REG_WRITE(0x70000ABC, 0xFF18),
+ S5K4ECGX_REG_WRITE(0x70000ABE, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000AC0, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000AC2, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000AC4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AC6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AC8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000ACA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000ACC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000ACE, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000AD0, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000AD2, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70000AD6, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000AD8, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000ADA, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000ADC, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000AE0, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000AE2, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000AE4, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000AE6, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000AE8, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000AEA, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000AEC, 0x1B04),
+ S5K4ECGX_REG_WRITE(0x70000AEE, 0x0312),
+ S5K4ECGX_REG_WRITE(0x70000AF0, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000AF2, 0x0C03),
+ S5K4ECGX_REG_WRITE(0x70000AF4, 0x2806),
+ S5K4ECGX_REG_WRITE(0x70000AF6, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000AF8, 0x1580),
+ S5K4ECGX_REG_WRITE(0x70000AFA, 0x2020),
+ S5K4ECGX_REG_WRITE(0x70000AFC, 0x0620),
+ S5K4ECGX_REG_WRITE(0x70000AFE, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000B00, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000B02, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000B04, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000B06, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70000B08, 0x145A),
+ S5K4ECGX_REG_WRITE(0x70000B0A, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000B0C, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000B0E, 0x0E00),
+ S5K4ECGX_REG_WRITE(0x70000B10, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000B12, 0x0504),
+ S5K4ECGX_REG_WRITE(0x70000B14, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000B16, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B18, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000B1A, 0x3828),
+ S5K4ECGX_REG_WRITE(0x70000B1C, 0x0428),
+ S5K4ECGX_REG_WRITE(0x70000B1E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000B20, 0x8000),
+ S5K4ECGX_REG_WRITE(0x70000B22, 0x0A04),
+ S5K4ECGX_REG_WRITE(0x70000B24, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000B26, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000B28, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000B2A, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000B2C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B2E, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000B30, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B32, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000B34, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000B36, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000B38, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000B3A, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000B3C, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000B3E, 0x0207),
+ S5K4ECGX_REG_WRITE(0x70000B40, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000B42, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000B44, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000B46, 0x0407),
+ S5K4ECGX_REG_WRITE(0x70000B48, 0x2404),
+ S5K4ECGX_REG_WRITE(0x70000B4A, 0x0221),
+ S5K4ECGX_REG_WRITE(0x70000B4C, 0x1202),
+ S5K4ECGX_REG_WRITE(0x70000B4E, 0x0613),
+ S5K4ECGX_REG_WRITE(0x70000B50, 0x1202),
+ S5K4ECGX_REG_WRITE(0x70000B52, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000B54, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000B56, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000B58, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000B5A, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000B5C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000B5E, 0x121B),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B62, 0x0C0C),
+ S5K4ECGX_REG_WRITE(0x70000B64, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000B66, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000B68, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000B6A, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000B6C, 0x1B01),
+ S5K4ECGX_REG_WRITE(0x70000B6E, 0x2412),
+ S5K4ECGX_REG_WRITE(0x70000B70, 0x0C60),
+ S5K4ECGX_REG_WRITE(0x70000B72, 0xFF0C),
+ S5K4ECGX_REG_WRITE(0x70000B74, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000B76, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000B78, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000B7A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B7C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B7E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B80, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B82, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B84, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000B86, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000B88, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000B8A, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70000B8C, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000B8E, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000B90, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000B92, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000B96, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000B98, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000B9A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000B9C, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000B9E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000BA0, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000BA2, 0x1504),
+ S5K4ECGX_REG_WRITE(0x70000BA4, 0x030F),
+ S5K4ECGX_REG_WRITE(0x70000BA6, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000BA8, 0x0902),
+ S5K4ECGX_REG_WRITE(0x70000BAA, 0x2004),
+ S5K4ECGX_REG_WRITE(0x70000BAC, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70000BAE, 0x1140),
+ S5K4ECGX_REG_WRITE(0x70000BB0, 0x201C),
+ S5K4ECGX_REG_WRITE(0x70000BB2, 0x0620),
+ S5K4ECGX_REG_WRITE(0x70000BB4, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000BB6, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000BB8, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000BBA, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000BBC, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70000BBE, 0x145A),
+ S5K4ECGX_REG_WRITE(0x70000BC0, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000BC2, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000BC4, 0x1000),
+ S5K4ECGX_REG_WRITE(0x70000BC6, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000BC8, 0x0503),
+ S5K4ECGX_REG_WRITE(0x70000BCA, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000BCC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BCE, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000BD0, 0x3C28),
+ S5K4ECGX_REG_WRITE(0x70000BD2, 0x042C),
+ S5K4ECGX_REG_WRITE(0x70000BD4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000BD6, 0xFF00),
+ S5K4ECGX_REG_WRITE(0x70000BD8, 0x0904),
+ S5K4ECGX_REG_WRITE(0x70000BDA, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000BDC, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000BDE, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000BE0, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000BE2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BE4, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000BE6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BE8, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000BEA, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000BEC, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000BEE, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000BF0, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000BF2, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000BF4, 0x0206),
+ S5K4ECGX_REG_WRITE(0x70000BF6, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000BF8, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000BFA, 0x0305),
+ S5K4ECGX_REG_WRITE(0x70000BFC, 0x0406),
+ S5K4ECGX_REG_WRITE(0x70000BFE, 0x2804),
+ S5K4ECGX_REG_WRITE(0x70000C00, 0x0228),
+ S5K4ECGX_REG_WRITE(0x70000C02, 0x1402),
+ S5K4ECGX_REG_WRITE(0x70000C04, 0x0618),
+ S5K4ECGX_REG_WRITE(0x70000C06, 0x1402),
+ S5K4ECGX_REG_WRITE(0x70000C08, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000C0A, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000C0C, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000C0E, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000C10, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000C12, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000C14, 0x0F15),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C18, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000C1A, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000C1C, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000C1E, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000C20, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000C22, 0x1501),
+ S5K4ECGX_REG_WRITE(0x70000C24, 0x240F),
+ S5K4ECGX_REG_WRITE(0x70000C26, 0x0A60),
+ S5K4ECGX_REG_WRITE(0x70000C28, 0xFF0A),
+ S5K4ECGX_REG_WRITE(0x70000C2A, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000C2C, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000C2E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000C30, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C32, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C34, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C36, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C38, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C3A, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000C3C, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000C3E, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000C40, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70000C42, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000C44, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000C46, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000C48, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000C4C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000C4E, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000C50, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000C52, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000C54, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000C56, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000C58, 0x0F04),
+ S5K4ECGX_REG_WRITE(0x70000C5A, 0x030C),
+ S5K4ECGX_REG_WRITE(0x70000C5C, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000C5E, 0x0602),
+ S5K4ECGX_REG_WRITE(0x70000C60, 0x1803),
+ S5K4ECGX_REG_WRITE(0x70000C62, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000C64, 0x0E20),
+ S5K4ECGX_REG_WRITE(0x70000C66, 0x2018),
+ S5K4ECGX_REG_WRITE(0x70000C68, 0x0620),
+ S5K4ECGX_REG_WRITE(0x70000C6A, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000C6C, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000C6E, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000C70, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000C72, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000C74, 0x145A),
+ S5K4ECGX_REG_WRITE(0x70000C76, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000C78, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000C7A, 0x1200),
+ S5K4ECGX_REG_WRITE(0x70000C7C, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000C7E, 0x0502),
+ S5K4ECGX_REG_WRITE(0x70000C80, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000C82, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C84, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000C86, 0x4028),
+ S5K4ECGX_REG_WRITE(0x70000C88, 0x0430),
+ S5K4ECGX_REG_WRITE(0x70000C8A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000C8C, 0xFF00),
+ S5K4ECGX_REG_WRITE(0x70000C8E, 0x0804),
+ S5K4ECGX_REG_WRITE(0x70000C90, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000C92, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000C94, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000C96, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000C98, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C9A, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000C9C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C9E, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000CA0, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000CA2, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000CA4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000CA6, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000CA8, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000CAA, 0x0205),
+ S5K4ECGX_REG_WRITE(0x70000CAC, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000CAE, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000CB0, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000CB2, 0x0407),
+ S5K4ECGX_REG_WRITE(0x70000CB4, 0x2C04),
+ S5K4ECGX_REG_WRITE(0x70000CB6, 0x022C),
+ S5K4ECGX_REG_WRITE(0x70000CB8, 0x1402),
+ S5K4ECGX_REG_WRITE(0x70000CBA, 0x0618),
+ S5K4ECGX_REG_WRITE(0x70000CBC, 0x1402),
+ S5K4ECGX_REG_WRITE(0x70000CBE, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000CC0, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000CC2, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000CC4, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000CC6, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000CC8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000CCA, 0x0C0F),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000CCE, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000CD0, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000CD2, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000CD4, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000CD6, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000CD8, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x70000CDA, 0x240C),
+ S5K4ECGX_REG_WRITE(0x70000CDC, 0x0860),
+ S5K4ECGX_REG_WRITE(0x70000CDE, 0xFF08),
+ S5K4ECGX_REG_WRITE(0x70000CE0, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000CE2, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000CE4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000CE6, 0x23CE),
+ S5K4ECGX_REG_WRITE(0x70000CE8, 0xFDC8),
+ S5K4ECGX_REG_WRITE(0x70000CEA, 0x112E),
+ S5K4ECGX_REG_WRITE(0x70000CEC, 0x93A5),
+ S5K4ECGX_REG_WRITE(0x70000CEE, 0xFE67),
+ S5K4ECGX_REG_WRITE(0x70000CF0, 0x0000),
+
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_WRITE(0x700001A2, 0x0A0A),
+
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_CMD_WRITE(0x0004, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_DTP_init_v1) = {
+ S5K4ECGX_REG_WRITE(0xD000B054, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_DTP_stop_v1) = {
+ S5K4ECGX_REG_WRITE(0xD000B054, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Normal_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000238, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Negative_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000238, 0x0003),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Sepia_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000238, 0x0004),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Black_White_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000238, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Auto_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x077F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Sunny_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Cloudy_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x0710), /* R */
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001), /* Changed */
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400), /* G */
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0420), /* B 480-reference */
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Tungsten_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x0390),
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0920),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Fluorescent_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0875),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WDR_on_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001B4A, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WDR_off_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001B4A, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_Auto_v1) = {
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000EF0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x077F),
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0200),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_100_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x01A0),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_200_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_400_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x0680),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Matrix_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001456, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001458, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001470, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001472, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001474, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001476, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001478, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000147A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000147E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001480, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001486, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001488, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000148C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000148E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001490, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Center_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001456, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001458, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000146A, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001470, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70001472, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70001474, 0x0102),
+ S5K4ECGX_REG_WRITE(0x70001476, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001478, 0x0403),
+ S5K4ECGX_REG_WRITE(0x7000147A, 0x0304),
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000147E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001480, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0102),
+ S5K4ECGX_REG_WRITE(0x70001486, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001488, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000148C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000148E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001490, 0x0202),
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0202),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0102),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Spot_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001456, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001458, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000145A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000145C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001470, 0x010F),
+ S5K4ECGX_REG_WRITE(0x70001472, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x70001474, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001476, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001478, 0x010F),
+ S5K4ECGX_REG_WRITE(0x7000147A, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000147E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001480, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001486, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001488, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000148C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000148E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001490, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_4_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0xFF30),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_3_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0xFFA0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0xFFC8),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0xFFE0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Default_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x0020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x0038),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_3_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_4_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_4_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0xFF81),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_3_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0xFFA0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0xFFC0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0xFFE0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Default_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0x0020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_3_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_4_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000022E, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_3_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x2010),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x4020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Default_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x6024),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x8040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0xA060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_3_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0xC080),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Minus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFF81),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Minus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFC0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Default_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Plus_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Plus_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_High_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000472, 0x005F),
+ S5K4ECGX_REG_WRITE(0x70000474, 0x005F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_Normal_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000472, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70000474, 0x0050),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_Low_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000472, 0x004B),
+ S5K4ECGX_REG_WRITE(0x70000474, 0x004B),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Default_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001456, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001458, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000146A, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001470, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70001472, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70001474, 0x0102),
+ S5K4ECGX_REG_WRITE(0x70001476, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001478, 0x0403),
+ S5K4ECGX_REG_WRITE(0x7000147A, 0x0304),
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000147E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001480, 0x0403),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0102),
+ S5K4ECGX_REG_WRITE(0x70001486, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001488, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x0303),
+ S5K4ECGX_REG_WRITE(0x7000148C, 0x0102),
+ S5K4ECGX_REG_WRITE(0x7000148E, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70001490, 0x0202),
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0202),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0102),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700006AC, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006AE, 0x0004),
+
+ S5K4ECGX_REG_WRITE(0x70000EF0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000EF6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x077F),
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x70002B7E, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001448, 0x003C),
+ S5K4ECGX_REG_WRITE(0x7000144E, 0x000F),
+ S5K4ECGX_REG_WRITE(0x70000580, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000582, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000584, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000586, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000588, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000058C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0x0470),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x1000),
+
+ S5K4ECGX_REG_WRITE(0x70000538, 0x0111),
+ S5K4ECGX_REG_WRITE(0x7000053A, 0x00EF),
+
+ S5K4ECGX_REG_WRITE(0x700005FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700005FE, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x6024),
+
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000062C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000062E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000630, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x70000632, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000634, 0x0D05),
+ S5K4ECGX_REG_WRITE(0x70000636, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000638, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x6810),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x8214),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700003AE, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x029A),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Portrait_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x4020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Nightshot_v1) = {
+ S5K4ECGX_REG_WRITE(0x700006AC, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x700006AE, 0x00FF),
+
+ S5K4ECGX_REG_WRITE(0x700005FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700005FE, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000580, 0xF424),
+ S5K4ECGX_REG_WRITE(0x70000582, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000584, 0xF424),
+ S5K4ECGX_REG_WRITE(0x70000586, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000588, 0xF424),
+ S5K4ECGX_REG_WRITE(0x7000058A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000058C, 0xF424),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000590, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0700),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x2000),
+
+ S5K4ECGX_REG_WRITE(0x700003AE, 0x1388),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x1388),
+
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x09C4),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x014D),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000023A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x1580),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Landscape_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001456, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001458, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001470, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001472, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001474, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001476, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001478, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000147A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000147E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001480, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001486, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001488, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000148C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000148E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001490, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Sports_v1) = {
+
+ S5K4ECGX_REG_WRITE(0x700005FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700005FE, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000580, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000582, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000584, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000586, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000588, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Party_Indoor_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0031),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Beach_Snow_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004CA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004CC, 0x00D0),
+ S5K4ECGX_REG_WRITE(0x700004CE, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006B6, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70004780, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0031),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Sunset_v1) = {
+ S5K4ECGX_REG_WRITE(0x70002B7E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0520),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Duskdawn_v1) = {
+ S5K4ECGX_REG_WRITE(0x70002B7E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x0575),
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0835),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Fireworks_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000062C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000062E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000630, 0x1478),
+ S5K4ECGX_REG_WRITE(0x70000632, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000634, 0x1A0A),
+ S5K4ECGX_REG_WRITE(0x70000636, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000638, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0xD020),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x0428),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000648, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0006),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0006),
+ S5K4ECGX_REG_WRITE(0x70000650, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0006),
+
+ S5K4ECGX_REG_WRITE(0x700003AE, 0x2710),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x2710),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Candle_Light_v1) = {
+ S5K4ECGX_REG_WRITE(0x700004E0, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004B4, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004B6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004B8, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Night_Capture_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x0AAA),
+ S5K4ECGX_REG_WRITE(0x70000AA0, 0x0AAA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Return_Macro_pos_v1) = {
+ S5K4ECGX_REG_WRITE(0x700015AC, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015AE, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015B0, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015B2, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015B4, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015B6, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015B8, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015BA, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015BC, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015BE, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015C0, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015C2, 0x0066),
+ S5K4ECGX_REG_WRITE(0x700015C4, 0x006C),
+ S5K4ECGX_REG_WRITE(0x700015C6, 0x0072),
+ S5K4ECGX_REG_WRITE(0x700015C8, 0x0078),
+ S5K4ECGX_REG_WRITE(0x700015CA, 0x007E),
+ S5K4ECGX_REG_WRITE(0x700015CC, 0x0084),
+ S5K4ECGX_REG_WRITE(0x700015CE, 0x008A),
+ S5K4ECGX_REG_WRITE(0x700015D0, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700015D2, 0x0096),
+ S5K4ECGX_REG_WRITE(0x700015D4, 0x009C),
+ S5K4ECGX_REG_WRITE(0x700015D6, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x700015D8, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x700015DC, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x700015DE, 0x00BA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Normal_mode_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000288, 0x002A),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0x70000286, 0x0004),
+ S5K4ECGX_MDELAY(200),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x9002),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Macro_mode_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000288, 0x00D0),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0x70000286, 0x0004),
+ S5K4ECGX_MDELAY(200),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x9042),
+ S5K4ECGX_REG_WRITE(0x7000159E, 0x1800),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Low_Light_Mode_On_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001616, 0x0003),
+
+ S5K4ECGX_REG_WRITE(0x700015A4, 0x0902),
+
+ S5K4ECGX_REG_WRITE(0x7000159E, 0x0C00),
+
+ S5K4ECGX_REG_WRITE(0x700015AC, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015AE, 0x0033),
+ S5K4ECGX_REG_WRITE(0x700015B0, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015B2, 0x0045),
+ S5K4ECGX_REG_WRITE(0x700015B4, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015B6, 0x0057),
+ S5K4ECGX_REG_WRITE(0x700015B8, 0x0063),
+ S5K4ECGX_REG_WRITE(0x700015BA, 0x006F),
+ S5K4ECGX_REG_WRITE(0x700015BC, 0x007B),
+ S5K4ECGX_REG_WRITE(0x700015BE, 0x0087),
+ S5K4ECGX_REG_WRITE(0x700015C0, 0x0093),
+ S5K4ECGX_REG_WRITE(0x700015C2, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x700015C4, 0x00B1),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Low_Light_Mode_Off_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001616, 0x0003),
+
+ S5K4ECGX_REG_WRITE(0x700015A4, 0x0902),
+
+ S5K4ECGX_REG_WRITE(0x7000159E, 0x1800),
+
+ S5K4ECGX_REG_WRITE(0x700015AC, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015AE, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015B0, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015B2, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015B4, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015B6, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015B8, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015BA, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015BC, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015BE, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015C0, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015C2, 0x0066),
+ S5K4ECGX_REG_WRITE(0x700015C4, 0x006C),
+ S5K4ECGX_REG_WRITE(0x700015C6, 0x0072),
+ S5K4ECGX_REG_WRITE(0x700015C8, 0x0078),
+ S5K4ECGX_REG_WRITE(0x700015CA, 0x007E),
+ S5K4ECGX_REG_WRITE(0x700015CC, 0x0084),
+ S5K4ECGX_REG_WRITE(0x700015CE, 0x008A),
+ S5K4ECGX_REG_WRITE(0x700015D0, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700015D2, 0x0096),
+ S5K4ECGX_REG_WRITE(0x700015D4, 0x009C),
+ S5K4ECGX_REG_WRITE(0x700015D6, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x700015D8, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x700015DC, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x700015DE, 0x00BA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Start_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000286, 0x0005),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_1_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000288, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_2_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000286, 0x0004),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Face_Detection_On_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000290, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000292, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0166),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0074),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x0132),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Face_Detection_Off_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000290, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000292, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0166),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0074),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x0132),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Low_Cap_On_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x0D58),
+ S5K4ECGX_REG_WRITE(0x70000AA0, 0x0A53),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Low_Cap_Off_v1) = {
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000AA0, 0x0080),
+ S5K4ECGX_REGSET_END
+};
+
+/* restores crop settings to full resolution */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Reset_Crop_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000024C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x000C),
+ S5K4ECGX_REG_WRITE(0x7000048E, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000490, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000260, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Capture_Start_v1) = {
+ S5K4ECGX_REG_WRITE(0x70001A00, 0x185C),
+ S5K4ECGX_REG_WRITE(0x70001A02, 0x7000),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Preview_Return_v1) = {
+ S5K4ECGX_REG_WRITE(0x700005C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A00, 0x192E),
+ S5K4ECGX_REG_WRITE(0x70001A02, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70000952, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_init_v1) = {
+ S5K4ECGX_REG_WRITE(0x700017DC, 0x0001), /* one frame AE */
+
+ S5K4ECGX_REG_WRITE(0x700017AE, 0x0270), /* AWB R point */
+
+ S5K4ECGX_REG_WRITE(0x700017B0, 0x0210), /* AWB B point */
+
+ S5K4ECGX_REG_WRITE(0x700017E2, 0x0001), /* Flash AE tune start */
+ S5K4ECGX_REG_WRITE(0x700017E4, 0x0030), /* 0x100 for Rin output */
+ S5K4ECGX_REG_WRITE(0x700017E6, 0x0040),
+ S5K4ECGX_REG_WRITE(0x700017E8, 0x0050),
+ S5K4ECGX_REG_WRITE(0x700017EA, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700017EC, 0x0070),
+ S5K4ECGX_REG_WRITE(0x700017EE, 0x0080),
+ S5K4ECGX_REG_WRITE(0x700017F0, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700017F2, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x700017F4, 0x0050), /* 0x100 for Rout output-20 */
+ S5K4ECGX_REG_WRITE(0x700017F6, 0x0014),
+ S5K4ECGX_REG_WRITE(0x700017F8, 0x000A),
+ S5K4ECGX_REG_WRITE(0x700017FA, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700017FC, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700017FE, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70001800, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70001802, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001824, 0x0100), /* 0x100 for NB output */
+ S5K4ECGX_REG_WRITE(0x70001826, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001828, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000182A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000182C, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000182E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001830, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001832, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x700017B4, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700017B6, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x700017B8, 0x0080),
+ S5K4ECGX_REG_WRITE(0x700017BA, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700017BC, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700017C8, 0x0025),
+ S5K4ECGX_REG_WRITE(0x700017CA, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700017CC, 0x0050),
+ S5K4ECGX_REG_WRITE(0x700017CE, 0x0070),
+ S5K4ECGX_REG_WRITE(0x700017D0, 0x0080),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Pre_Flash_Start_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000057C, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001F06, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Pre_Flash_End_v1) = {
+ S5K4ECGX_REG_WRITE(0x7000057C, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x70001F08, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_Start_v1) = {
+ S5K4ECGX_REG_WRITE(0x700017A8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000047E, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x70001448, 0x0027),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_End_v1) = {
+ S5K4ECGX_REG_WRITE(0x700017A8, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000047E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001448, 0x003C),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_5M_Capture_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000392, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000394, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0009),
+
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_3M_Capture_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000392, 0x0800),
+ S5K4ECGX_REG_WRITE(0x70000394, 0x0600),
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0009),
+
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_2M_Capture_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000392, 0x0640),
+ S5K4ECGX_REG_WRITE(0x70000394, 0x04B0),
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0009),
+
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_1M_Capture_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000392, 0x0500),
+ S5K4ECGX_REG_WRITE(0x70000394, 0x03C0),
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0009),
+
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_VGA_Capture_v1) = {
+ S5K4ECGX_REG_WRITE(0x70000392, 0x0280),
+ S5K4ECGX_REG_WRITE(0x70000394, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0009),
+
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000026C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_720_Preview_v1) = {
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_640_Preview_v1) = {
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0280),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_352_Preview_v1) = {
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0160),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0120),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_176_Preview_v1) = {
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AE_AWB_Lock_On_v1) = {
+ S5K4ECGX_REG_WRITE(0x70002B76, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70002B7E, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AE_AWB_Lock_Off_v1) = {
+ S5K4ECGX_REG_WRITE(0x70002B76, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70002B7E, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Get_AE_Stable_Status_v1) = {
+ S5K4ECGX_REG_READ(0x70002B8C),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Get_Light_Level_v1) = {
+ S5K4ECGX_REG_READ(0x70002B30),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_1st_af_search_status_v1) = {
+ S5K4ECGX_REG_READ(0x70002E06),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_2nd_af_search_status_v1) = {
+ S5K4ECGX_REG_READ(0x70002167),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_capture_status_v1) = {
+ S5K4ECGX_REG_READ(0x70001F02),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_esd_status_v1) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_READ(0xD0000060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_iso_reg_v1) = {
+ S5K4ECGX_REG_READ(0x70002ADC),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_shutterspeed_reg_v1) = {
+ S5K4ECGX_REG_READ(0x70002AD8),
+ S5K4ECGX_REGSET_END
+};
+
+#undef S5K4ECGX_DEFINE_REGSET
+#undef S5K4ECGX_REGSET_END
+#undef S5K4ECGX_CMD_WRITE
+#undef S5K4ECGX_REG_WRITE
+#undef S5K4ECGX_REG_READ
+#undef S5K4ECGX_MDELAY
+#undef _SWAB16
+#undef _DUMMY
+
+#endif
+
+#if !defined(__S5K4ECGX_V1_0_DEFINE_REGSET__)
+#define __S5K4ECGX_V1_0_DEFINE_REGSET__
+#elif !defined(__S5K4ECGX_V1_0_DEFINE_REGSET_DATA__)
+#define __S5K4ECGX_V1_0_DEFINE_REGSET_DATA__
+#endif
diff --git a/drivers/media/video/s5k4ecgx_regs_1_1.h b/drivers/media/video/s5k4ecgx_regs_1_1.h
new file mode 100755
index 00000000000..ce8cf687b2f
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_1.h
@@ -0,0 +1,4386 @@
+/* drivers/media/video/s5k4ecgx_regs_1_1.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.1
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ * Copyright (C) 2012, Insignal Co,. Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5k4ecgx_regset.h"
+
+#if !defined(__S5K4ECGX_V1_1_DEFINE_REGSET__)
+
+#define S5K4ECGX_DEFINE_REGSET(NAME) static const struct s5k4ecgx_reg NAME[]
+#define S5K4ECGX_REGSET_END \
+ { .type = S5K4ECGX_REGTYPE_END, .data_len = 0 }
+#define S5K4ECGX_CMD_WRITE(ADDR, DATA) \
+ { .type = S5K4ECGX_REGTYPE_CMD, .data_len = 4 }
+#define S5K4ECGX_REG_WRITE(ADDR, DATA) \
+ { .type = S5K4ECGX_REGTYPE_WRITE, .data_len = 2, { .addr = ADDR } }
+#define S5K4ECGX_REG_READ(ADDR) \
+ { .type = S5K4ECGX_REGTYPE_READ, .data_len = 1, { .addr = ADDR } }
+#define S5K4ECGX_MDELAY(MSEC) \
+ { .type = S5K4ECGX_REGTYPE_DELAY, .data_len = 1, { .msec = MSEC } }
+
+#elif !defined(__S5K4ECGX_V1_1_DEFINE_REGSET_DATA__)
+
+#define _SWAB16(X) ((X >> 8) & 0xFF), (X & 0xFF)
+#define _DUMMY 0
+#define S5K4ECGX_DEFINE_REGSET(NAME) static const u8 NAME##_data[]
+#define S5K4ECGX_REGSET_END
+#define S5K4ECGX_CMD_WRITE(ADDR, DATA) _SWAB16(ADDR), _SWAB16(DATA)
+#define S5K4ECGX_REG_WRITE(ADDR, DATA) _SWAB16(DATA)
+#define S5K4ECGX_REG_READ(ADDR) _DUMMY
+#define S5K4ECGX_MDELAY(MSEC) _DUMMY
+
+#endif
+
+#if !defined(__S5K4ECGX_V1_1_DEFINE_REGSET__) \
+ || !defined(__S5K4ECGX_V1_1_DEFINE_REGSET_DATA__)
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_init_reg) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_CMD_WRITE(0x0010, 0x0001),
+ S5K4ECGX_CMD_WRITE(0x1030, 0x0000),
+ S5K4ECGX_CMD_WRITE(0x0014, 0x0001),
+
+ S5K4ECGX_MDELAY(10),
+
+ /* Drive current setting */
+ S5K4ECGX_REG_WRITE(0xD0001082, 0x0155), /* d0_d4_cd10, d0_d4_cd10 9:0 */
+ S5K4ECGX_REG_WRITE(0xD0001084, 0x0155), /* d5_d9_cd10, d5_d9_cd10 9:0 */
+ S5K4ECGX_REG_WRITE(0xD0001086, 0x0055), /* gpio_cd10, gpio_cd10 */
+ S5K4ECGX_REG_WRITE(0xD0001088, 0x0555), /* clks_output_cd10, clks_output_cd10 11:0 */
+ S5K4ECGX_REG_WRITE(0xD000100E, 0x0000), /* pclk_delay_r */
+
+ S5K4ECGX_REG_WRITE(0xD000007A, 0x0000),
+
+ /* ISP FE(ADLC) */
+ S5K4ECGX_REG_WRITE(0xD000E406, 0x0092),
+ S5K4ECGX_REG_WRITE(0xD000E410, 0x3804),
+ S5K4ECGX_REG_WRITE(0xD000E41A, 0x0010), /* 101022 ADD adlcptune_total */
+ S5K4ECGX_REG_WRITE(0xD000E420, 0x0003),
+ S5K4ECGX_REG_WRITE(0xD000E422, 0x0060),
+ S5K4ECGX_REG_WRITE(0xD000E42E, 0x0004),
+ S5K4ECGX_REG_WRITE(0xD000F400, 0x5A3C),
+ S5K4ECGX_REG_WRITE(0xD000F402, 0x0023),
+ S5K4ECGX_REG_WRITE(0xD000F404, 0x8080),
+ S5K4ECGX_REG_WRITE(0xD000F406, 0x03AF),
+ S5K4ECGX_REG_WRITE(0xD000F408, 0x000A),
+ S5K4ECGX_REG_WRITE(0xD000F40A, 0xAA54),
+ S5K4ECGX_REG_WRITE(0xD000F40C, 0x0040),
+ S5K4ECGX_REG_WRITE(0xD000F40E, 0x464E),
+ S5K4ECGX_REG_WRITE(0xD000F410, 0x0240),
+ S5K4ECGX_REG_WRITE(0xD000F412, 0x0240),
+ S5K4ECGX_REG_WRITE(0xD000F414, 0x0040),
+ S5K4ECGX_REG_WRITE(0xD000F416, 0x1000),
+ S5K4ECGX_REG_WRITE(0xD000F418, 0x555C),
+ S5K4ECGX_REG_WRITE(0xD000F41A, 0xD000),
+ S5K4ECGX_REG_WRITE(0xD000F41C, 0x0010),
+ S5K4ECGX_REG_WRITE(0xD000F41E, 0x0202),
+ S5K4ECGX_REG_WRITE(0xD000F420, 0x0401),
+ S5K4ECGX_REG_WRITE(0xD000F422, 0x0022),
+ S5K4ECGX_REG_WRITE(0xD000F424, 0x0088),
+ S5K4ECGX_REG_WRITE(0xD000F426, 0x009F),
+ S5K4ECGX_REG_WRITE(0xD000F428, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F42A, 0x1800),
+ S5K4ECGX_REG_WRITE(0xD000F42C, 0x0088),
+ S5K4ECGX_REG_WRITE(0xD000F42E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F430, 0x2428),
+ S5K4ECGX_REG_WRITE(0xD000F432, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F434, 0x03EE),
+ S5K4ECGX_REG_WRITE(0xD000F436, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F438, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F43A, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F552, 0x0708),
+ S5K4ECGX_REG_WRITE(0xD000F554, 0x080C),
+
+ /* For subsampling Size */
+ S5K4ECGX_REG_WRITE(0x700018BC, 0x0004),
+ S5K4ECGX_REG_WRITE(0x700018BE, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x700018C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700018C6, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x700018C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CC, 0x0007),
+ S5K4ECGX_REG_WRITE(0x700018CE, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x700018D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D4, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018D6, 0x024E),
+ S5K4ECGX_REG_WRITE(0x700018D8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018DC, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018DE, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x700018E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E4, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018E6, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x700018E8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018EA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018EC, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018EE, 0x024F),
+ S5K4ECGX_REG_WRITE(0x700018F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018FC, 0x0075),
+ S5K4ECGX_REG_WRITE(0x700018FE, 0x00CF),
+ S5K4ECGX_REG_WRITE(0x70001900, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001902, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001904, 0x0075),
+ S5K4ECGX_REG_WRITE(0x70001906, 0x00D6),
+ S5K4ECGX_REG_WRITE(0x70001908, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190C, 0x0004),
+ S5K4ECGX_REG_WRITE(0x7000190E, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001910, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001912, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001914, 0x00F0),
+ S5K4ECGX_REG_WRITE(0x70001916, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001918, 0x029E),
+ S5K4ECGX_REG_WRITE(0x7000191A, 0x05B2),
+ S5K4ECGX_REG_WRITE(0x7000191C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000191E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001920, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001922, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001924, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x70001926, 0x0228),
+ S5K4ECGX_REG_WRITE(0x70001928, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001930, 0x0208),
+ S5K4ECGX_REG_WRITE(0x70001932, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70001934, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001936, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001938, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000193A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000193C, 0x0218),
+ S5K4ECGX_REG_WRITE(0x7000193E, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70001940, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001942, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001944, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001946, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001948, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000194A, 0x0009),
+ S5K4ECGX_REG_WRITE(0x7000194C, 0x00DE),
+ S5K4ECGX_REG_WRITE(0x7000194E, 0x05C0),
+ S5K4ECGX_REG_WRITE(0x70001950, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001952, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001954, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x70001956, 0x00E4),
+ S5K4ECGX_REG_WRITE(0x70001958, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000195A, 0x01FD),
+ S5K4ECGX_REG_WRITE(0x7000195C, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x7000195E, 0x05BB),
+ S5K4ECGX_REG_WRITE(0x70001960, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001962, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001964, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001966, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001968, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001970, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001972, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001974, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001976, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001978, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000197A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000197C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000197E, 0x0077),
+ S5K4ECGX_REG_WRITE(0x70001980, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001982, 0x024F),
+ S5K4ECGX_REG_WRITE(0x70001984, 0x025E),
+ S5K4ECGX_REG_WRITE(0x70001986, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001988, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000198A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000198C, 0x0000),
+
+ /* For Capture */
+ S5K4ECGX_REG_WRITE(0x7000198E, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70001990, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x70001992, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001994, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001996, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70001998, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x7000199A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000199C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000199E, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019A0, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x700019A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A6, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019A8, 0x0326),
+ S5K4ECGX_REG_WRITE(0x700019AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AE, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019B0, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x700019B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B6, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019B8, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x700019BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019BC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019BE, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019C0, 0x0327),
+ S5K4ECGX_REG_WRITE(0x700019C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019CE, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019D0, 0x0084),
+ S5K4ECGX_REG_WRITE(0x700019D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D6, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019D8, 0x008D),
+ S5K4ECGX_REG_WRITE(0x700019DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DE, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019E0, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E6, 0x00AA),
+ S5K4ECGX_REG_WRITE(0x700019E8, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019EA, 0x03AD),
+ S5K4ECGX_REG_WRITE(0x700019EC, 0x09CD),
+ S5K4ECGX_REG_WRITE(0x700019EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F6, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x700019F8, 0x02DE),
+ S5K4ECGX_REG_WRITE(0x700019FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A00, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A02, 0x02BE),
+ S5K4ECGX_REG_WRITE(0x70001A04, 0x02EE),
+ S5K4ECGX_REG_WRITE(0x70001A06, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A08, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A0A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A0C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A0E, 0x02CE),
+ S5K4ECGX_REG_WRITE(0x70001A10, 0x02EE),
+ S5K4ECGX_REG_WRITE(0x70001A12, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A14, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A16, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A18, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A1A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70001A1C, 0x0009),
+ S5K4ECGX_REG_WRITE(0x70001A1E, 0x0095),
+ S5K4ECGX_REG_WRITE(0x70001A20, 0x09DB),
+ S5K4ECGX_REG_WRITE(0x70001A22, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A24, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A26, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001A28, 0x009B),
+ S5K4ECGX_REG_WRITE(0x70001A2A, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x70001A2C, 0x02B3),
+ S5K4ECGX_REG_WRITE(0x70001A2E, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x70001A30, 0x09D6),
+ S5K4ECGX_REG_WRITE(0x70001A32, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A34, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A36, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A38, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A3A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A3C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A3E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A40, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A42, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A44, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A46, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A48, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A4A, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x70001A4C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A4E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A50, 0x0009),
+ S5K4ECGX_REG_WRITE(0x70001A52, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70001A54, 0x0327),
+ S5K4ECGX_REG_WRITE(0x70001A56, 0x0336),
+ S5K4ECGX_REG_WRITE(0x70001A58, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A5A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A5C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A5E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001AF8, 0x5A3C), /* #senHal_TuneStr_AngTuneData1_2_D000F400
+ register at subsampling*/
+
+ S5K4ECGX_REG_WRITE(0x70001896, 0x0002), /* #senHal_SamplingType 0002 03EE: PLA setting */
+ S5K4ECGX_REG_WRITE(0x70001898, 0x0000), /* #senHal_SamplingMode 0 : 2 PLA / 1 : 4PLA */
+ S5K4ECGX_REG_WRITE(0x7000189A, 0x0003), /* #senHal_PLAOption
+ [0] VPLA enable , [1] HPLA enable*/
+
+ S5K4ECGX_REG_WRITE(0x7000189E, 0x0FB0), /* #senHal_ExpMinPixels */
+
+ S5K4ECGX_REG_WRITE(0x700018AC, 0x0060), /* #senHal_uAddColsBin */
+ S5K4ECGX_REG_WRITE(0x700018AE, 0x0060), /* #senHal_uAddColsNoBin */
+ S5K4ECGX_REG_WRITE(0x700018B0, 0x05C0), /* #senHal_uMinColsBin */
+ S5K4ECGX_REG_WRITE(0x700018B2, 0x05C0), /* #senHal_uMinColsNoBin */
+
+ S5K4ECGX_REG_WRITE(0x70001AEA, 0x8080), /* #senHal_SubF404Tune */
+ S5K4ECGX_REG_WRITE(0x70001AEC, 0x0080), /* #senHal_FullF404Tune */
+ S5K4ECGX_REG_WRITE(0x70001AE0, 0x0000), /* #senHal_bSenAAC */
+
+ S5K4ECGX_REG_WRITE(0x70001A72, 0x0000), /* #senHal_bSRX SRX off */
+ S5K4ECGX_REG_WRITE(0x700018A2, 0x0004), /* #senHal_NExpLinesCheckFine,
+ extend Forbidden area line*/
+ S5K4ECGX_REG_WRITE(0x70001A6A, 0x009A), /* #senHal_usForbiddenRightOfs,
+ extend right Forbidden area line*/
+ S5K4ECGX_REG_WRITE(0x7000385E, 0x024C), /* #Mon_Sen_uExpPixelsOfs */
+
+ S5K4ECGX_REG_WRITE(0x70000EE6, 0x0000), /* #setot_bUseDigitalHbin */
+ S5K4ECGX_REG_WRITE(0x70001B2A, 0x0300), /* #senHal_TuneStr2_usAngTuneGainTh 2 70001B2A */
+ S5K4ECGX_REG_WRITE(0x70001B2C, 0x00D6), /* #senHal_TuneStr2_AngTuneF4CA_0_ 2 70001B2C */
+ S5K4ECGX_REG_WRITE(0x70001B2E, 0x008D), /* #senHal_TuneStr2_AngTuneF4CA_1_ 2 70001B2E */
+ S5K4ECGX_REG_WRITE(0x70001B30, 0x00CF), /* #senHal_TuneStr2_AngTuneF4C2_0_ 2 70001B30 */
+ S5K4ECGX_REG_WRITE(0x70001B32, 0x0084), /* #senHal_TuneStr2_AngTuneF4C2_1_ 2 70001B32 */
+
+ /* OTP setting */
+
+ S5K4ECGX_REG_WRITE(0x70000722, 0x0100), /* #skl_OTP_usWaitTime,
+ This register should be positioned in
+ front of D0001000*/
+ S5K4ECGX_REG_WRITE(0x70000726, 0x0001), /* #skl_bUseOTPfunc, This is OTP on/off function */
+ S5K4ECGX_REG_WRITE(0x700008D6, 0x0001), /* #ash_bUseOTPData */
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0000), /* #awbb_otp_disable */
+ S5K4ECGX_REG_WRITE(0x700008DC, 0x0001), /* #ash_bUseGasAlphaOTP */
+
+ /* TnP setting */
+ /* Start of Patch data */
+ S5K4ECGX_REG_WRITE(0x70003AF8, 0xB570), /* 70003AF8 */
+ S5K4ECGX_REG_WRITE(0x70003AFA, 0x4B36), /* 70003AFA */
+ S5K4ECGX_REG_WRITE(0x70003AFC, 0x216F), /* 70003AFC */
+ S5K4ECGX_REG_WRITE(0x70003AFE, 0x4836), /* 70003AFE */
+ S5K4ECGX_REG_WRITE(0x70003B00, 0x8C80), /* 70003B00 */
+ S5K4ECGX_REG_WRITE(0x70003B02, 0x2200), /* 70003B02 */
+ S5K4ECGX_REG_WRITE(0x70003B04, 0xC008), /* 70003B04 */
+ S5K4ECGX_REG_WRITE(0x70003B06, 0x6001), /* 70003B06 */
+ S5K4ECGX_REG_WRITE(0x70003B08, 0x4934), /* 70003B08 */
+ S5K4ECGX_REG_WRITE(0x70003B0A, 0x4835), /* 70003B0A */
+ S5K4ECGX_REG_WRITE(0x70003B0C, 0x2501), /* 70003B0C */
+ S5K4ECGX_REG_WRITE(0x70003B0E, 0xF000), /* 70003B0E */
+ S5K4ECGX_REG_WRITE(0x70003B10, 0xFB77), /* 70003B10 */
+ S5K4ECGX_REG_WRITE(0x70003B12, 0x4934), /* 70003B12 */
+ S5K4ECGX_REG_WRITE(0x70003B14, 0x4834), /* 70003B14 */
+ S5K4ECGX_REG_WRITE(0x70003B16, 0x2402), /* 70003B16 */
+ S5K4ECGX_REG_WRITE(0x70003B18, 0x002A), /* 70003B18 */
+ S5K4ECGX_REG_WRITE(0x70003B1A, 0xF000), /* 70003B1A */
+ S5K4ECGX_REG_WRITE(0x70003B1C, 0xFB71), /* 70003B1C */
+ S5K4ECGX_REG_WRITE(0x70003B1E, 0x4833), /* 70003B1E */
+ S5K4ECGX_REG_WRITE(0x70003B20, 0x0221), /* 70003B20 */
+ S5K4ECGX_REG_WRITE(0x70003B22, 0x8001), /* 70003B22 */
+ S5K4ECGX_REG_WRITE(0x70003B24, 0x2100), /* 70003B24 */
+ S5K4ECGX_REG_WRITE(0x70003B26, 0x8041), /* 70003B26 */
+ S5K4ECGX_REG_WRITE(0x70003B28, 0x4931), /* 70003B28 */
+ S5K4ECGX_REG_WRITE(0x70003B2A, 0x4832), /* 70003B2A */
+ S5K4ECGX_REG_WRITE(0x70003B2C, 0x6041), /* 70003B2C */
+ S5K4ECGX_REG_WRITE(0x70003B2E, 0x4932), /* 70003B2E */
+ S5K4ECGX_REG_WRITE(0x70003B30, 0x4832), /* 70003B30 */
+ S5K4ECGX_REG_WRITE(0x70003B32, 0x0022), /* 70003B32 */
+ S5K4ECGX_REG_WRITE(0x70003B34, 0x2503), /* 70003B34 */
+ S5K4ECGX_REG_WRITE(0x70003B36, 0xF000), /* 70003B36 */
+ S5K4ECGX_REG_WRITE(0x70003B38, 0xFB63), /* 70003B38 */
+ S5K4ECGX_REG_WRITE(0x70003B3A, 0x482E), /* 70003B3A */
+ S5K4ECGX_REG_WRITE(0x70003B3C, 0x4930), /* 70003B3C */
+ S5K4ECGX_REG_WRITE(0x70003B3E, 0x30C0), /* 70003B3E */
+ S5K4ECGX_REG_WRITE(0x70003B40, 0x63C1), /* 70003B40 */
+ S5K4ECGX_REG_WRITE(0x70003B42, 0x492C), /* 70003B42 */
+ S5K4ECGX_REG_WRITE(0x70003B44, 0x482F), /* 70003B44 */
+ S5K4ECGX_REG_WRITE(0x70003B46, 0x3980), /* 70003B46 */
+ S5K4ECGX_REG_WRITE(0x70003B48, 0x6408), /* 70003B48 */
+ S5K4ECGX_REG_WRITE(0x70003B4A, 0x482F), /* 70003B4A */
+ S5K4ECGX_REG_WRITE(0x70003B4C, 0x492F), /* 70003B4C */
+ S5K4ECGX_REG_WRITE(0x70003B4E, 0x6388), /* 70003B4E */
+ S5K4ECGX_REG_WRITE(0x70003B50, 0x492F), /* 70003B50 */
+ S5K4ECGX_REG_WRITE(0x70003B52, 0x4830), /* 70003B52 */
+ S5K4ECGX_REG_WRITE(0x70003B54, 0x2404), /* 70003B54 */
+ S5K4ECGX_REG_WRITE(0x70003B56, 0x002A), /* 70003B56 */
+ S5K4ECGX_REG_WRITE(0x70003B58, 0xF000), /* 70003B58 */
+ S5K4ECGX_REG_WRITE(0x70003B5A, 0xFB52), /* 70003B5A */
+ S5K4ECGX_REG_WRITE(0x70003B5C, 0x492E), /* 70003B5C */
+ S5K4ECGX_REG_WRITE(0x70003B5E, 0x482F), /* 70003B5E */
+ S5K4ECGX_REG_WRITE(0x70003B60, 0x0022), /* 70003B60 */
+ S5K4ECGX_REG_WRITE(0x70003B62, 0x2505), /* 70003B62 */
+ S5K4ECGX_REG_WRITE(0x70003B64, 0xF000), /* 70003B64 */
+ S5K4ECGX_REG_WRITE(0x70003B66, 0xF876), /* 70003B66 */
+ S5K4ECGX_REG_WRITE(0x70003B68, 0x482C), /* 70003B68 */
+ S5K4ECGX_REG_WRITE(0x70003B6A, 0x492D), /* 70003B6A */
+ S5K4ECGX_REG_WRITE(0x70003B6C, 0x2406), /* 70003B6C */
+ S5K4ECGX_REG_WRITE(0x70003B6E, 0x002A), /* 70003B6E */
+ S5K4ECGX_REG_WRITE(0x70003B70, 0x1D80), /* 70003B70 */
+ S5K4ECGX_REG_WRITE(0x70003B72, 0xF000), /* 70003B72 */
+ S5K4ECGX_REG_WRITE(0x70003B74, 0xF86F), /* 70003B74 */
+ S5K4ECGX_REG_WRITE(0x70003B76, 0x4829), /* 70003B76 */
+ S5K4ECGX_REG_WRITE(0x70003B78, 0x492A), /* 70003B78 */
+ S5K4ECGX_REG_WRITE(0x70003B7A, 0x0022), /* 70003B7A */
+ S5K4ECGX_REG_WRITE(0x70003B7C, 0x2507), /* 70003B7C */
+ S5K4ECGX_REG_WRITE(0x70003B7E, 0x300C), /* 70003B7E */
+ S5K4ECGX_REG_WRITE(0x70003B80, 0xF000), /* 70003B80 */
+ S5K4ECGX_REG_WRITE(0x70003B82, 0xF868), /* 70003B82 */
+ S5K4ECGX_REG_WRITE(0x70003B84, 0x4825), /* 70003B84 */
+ S5K4ECGX_REG_WRITE(0x70003B86, 0x4928), /* 70003B86 */
+ S5K4ECGX_REG_WRITE(0x70003B88, 0x2408), /* 70003B88 */
+ S5K4ECGX_REG_WRITE(0x70003B8A, 0x002A), /* 70003B8A */
+ S5K4ECGX_REG_WRITE(0x70003B8C, 0x3010), /* 70003B8C */
+ S5K4ECGX_REG_WRITE(0x70003B8E, 0xF000), /* 70003B8E */
+ S5K4ECGX_REG_WRITE(0x70003B90, 0xF861), /* 70003B90 */
+ S5K4ECGX_REG_WRITE(0x70003B92, 0x4926), /* 70003B92 */
+ S5K4ECGX_REG_WRITE(0x70003B94, 0x4826), /* 70003B94 */
+ S5K4ECGX_REG_WRITE(0x70003B96, 0x0022), /* 70003B96 */
+ S5K4ECGX_REG_WRITE(0x70003B98, 0x2509), /* 70003B98 */
+ S5K4ECGX_REG_WRITE(0x70003B9A, 0xF000), /* 70003B9A */
+ S5K4ECGX_REG_WRITE(0x70003B9C, 0xFB31), /* 70003B9C */
+ S5K4ECGX_REG_WRITE(0x70003B9E, 0x4925), /* 70003B9E */
+ S5K4ECGX_REG_WRITE(0x70003BA0, 0x4825), /* 70003BA0 */
+ S5K4ECGX_REG_WRITE(0x70003BA2, 0x240A), /* 70003BA2 */
+ S5K4ECGX_REG_WRITE(0x70003BA4, 0x002A), /* 70003BA4 */
+ S5K4ECGX_REG_WRITE(0x70003BA6, 0xF000), /* 70003BA6 */
+ S5K4ECGX_REG_WRITE(0x70003BA8, 0xFB2B), /* 70003BA8 */
+ S5K4ECGX_REG_WRITE(0x70003BAA, 0x4924), /* 70003BAA */
+ S5K4ECGX_REG_WRITE(0x70003BAC, 0x4824), /* 70003BAC */
+ S5K4ECGX_REG_WRITE(0x70003BAE, 0x250B), /* 70003BAE */
+ S5K4ECGX_REG_WRITE(0x70003BB0, 0x0022), /* 70003BB0 */
+ S5K4ECGX_REG_WRITE(0x70003BB2, 0xF000), /* 70003BB2 */
+ S5K4ECGX_REG_WRITE(0x70003BB4, 0xFB25), /* 70003BB4 */
+ S5K4ECGX_REG_WRITE(0x70003BB6, 0x4923), /* 70003BB6 */
+ S5K4ECGX_REG_WRITE(0x70003BB8, 0x4823), /* 70003BB8 */
+ S5K4ECGX_REG_WRITE(0x70003BBA, 0x002A), /* 70003BBA */
+ S5K4ECGX_REG_WRITE(0x70003BBC, 0x240C), /* 70003BBC */
+ S5K4ECGX_REG_WRITE(0x70003BBE, 0xF000), /* 70003BBE */
+ S5K4ECGX_REG_WRITE(0x70003BC0, 0xFB1F), /* 70003BC0 */
+ S5K4ECGX_REG_WRITE(0x70003BC2, 0x4922), /* 70003BC2 */
+ S5K4ECGX_REG_WRITE(0x70003BC4, 0x4822), /* 70003BC4 */
+ S5K4ECGX_REG_WRITE(0x70003BC6, 0x0022), /* 70003BC6 */
+ S5K4ECGX_REG_WRITE(0x70003BC8, 0xF000), /* 70003BC8 */
+ S5K4ECGX_REG_WRITE(0x70003BCA, 0xFB1A), /* 70003BCA */
+ S5K4ECGX_REG_WRITE(0x70003BCC, 0xBC70), /* 70003BCC */
+ S5K4ECGX_REG_WRITE(0x70003BCE, 0xBC08), /* 70003BCE */
+ S5K4ECGX_REG_WRITE(0x70003BD0, 0x4718), /* 70003BD0 */
+ S5K4ECGX_REG_WRITE(0x70003BD2, 0x0000), /* 70003BD2 */
+ S5K4ECGX_REG_WRITE(0x70003BD4, 0x0185), /* 70003BD4 */
+ S5K4ECGX_REG_WRITE(0x70003BD6, 0x4EC2), /* 70003BD6 */
+ S5K4ECGX_REG_WRITE(0x70003BD8, 0x1F6C), /* 70003BD8 */
+ S5K4ECGX_REG_WRITE(0x70003BDA, 0x7000), /* 70003BDA */
+ S5K4ECGX_REG_WRITE(0x70003BDC, 0x3C6D), /* 70003BDC */
+ S5K4ECGX_REG_WRITE(0x70003BDE, 0x7000), /* 70003BDE */
+ S5K4ECGX_REG_WRITE(0x70003BE0, 0xE38B), /* 70003BE0 */
+ S5K4ECGX_REG_WRITE(0x70003BE2, 0x0000), /* 70003BE2 */
+ S5K4ECGX_REG_WRITE(0x70003BE4, 0x3CA5), /* 70003BE4 */
+ S5K4ECGX_REG_WRITE(0x70003BE6, 0x7000), /* 70003BE6 */
+ S5K4ECGX_REG_WRITE(0x70003BE8, 0xC3B1), /* 70003BE8 */
+ S5K4ECGX_REG_WRITE(0x70003BEA, 0x0000), /* 70003BEA */
+ S5K4ECGX_REG_WRITE(0x70003BEC, 0x4780), /* 70003BEC */
+ S5K4ECGX_REG_WRITE(0x70003BEE, 0x7000), /* 70003BEE */
+ S5K4ECGX_REG_WRITE(0x70003BF0, 0x3D03), /* 70003BF0 */
+ S5K4ECGX_REG_WRITE(0x70003BF2, 0x7000), /* 70003BF2 */
+ S5K4ECGX_REG_WRITE(0x70003BF4, 0x0080), /* 70003BF4 */
+ S5K4ECGX_REG_WRITE(0x70003BF6, 0x7000), /* 70003BF6 */
+ S5K4ECGX_REG_WRITE(0x70003BF8, 0x3D3F), /* 70003BF8 */
+ S5K4ECGX_REG_WRITE(0x70003BFA, 0x7000), /* 70003BFA */
+ S5K4ECGX_REG_WRITE(0x70003BFC, 0xB49D), /* 70003BFC */
+ S5K4ECGX_REG_WRITE(0x70003BFE, 0x0000), /* 70003BFE */
+ S5K4ECGX_REG_WRITE(0x70003C00, 0x3DEB), /* 70003C00 */
+ S5K4ECGX_REG_WRITE(0x70003C02, 0x7000), /* 70003C02 */
+ S5K4ECGX_REG_WRITE(0x70003C04, 0x3D9F), /* 70003C04 */
+ S5K4ECGX_REG_WRITE(0x70003C06, 0x7000), /* 70003C06 */
+ S5K4ECGX_REG_WRITE(0x70003C08, 0xFFFF), /* 70003C08 */
+ S5K4ECGX_REG_WRITE(0x70003C0A, 0x00FF), /* 70003C0A */
+ S5K4ECGX_REG_WRITE(0x70003C0C, 0x17E0), /* 70003C0C */
+ S5K4ECGX_REG_WRITE(0x70003C0E, 0x7000), /* 70003C0E */
+ S5K4ECGX_REG_WRITE(0x70003C10, 0x3F67), /* 70003C10 */
+ S5K4ECGX_REG_WRITE(0x70003C12, 0x7000), /* 70003C12 */
+ S5K4ECGX_REG_WRITE(0x70003C14, 0x053D), /* 70003C14 */
+ S5K4ECGX_REG_WRITE(0x70003C16, 0x0000), /* 70003C16 */
+ S5K4ECGX_REG_WRITE(0x70003C18, 0x0000), /* 70003C18 */
+ S5K4ECGX_REG_WRITE(0x70003C1A, 0x0A89), /* 70003C1A */
+ S5K4ECGX_REG_WRITE(0x70003C1C, 0x6CD2), /* 70003C1C */
+ S5K4ECGX_REG_WRITE(0x70003C1E, 0x0000), /* 70003C1E */
+ S5K4ECGX_REG_WRITE(0x70003C20, 0x02C9), /* 70003C20 */
+ S5K4ECGX_REG_WRITE(0x70003C22, 0x0000), /* 70003C22 */
+ S5K4ECGX_REG_WRITE(0x70003C24, 0x0000), /* 70003C24 */
+ S5K4ECGX_REG_WRITE(0x70003C26, 0x0A9A), /* 70003C26 */
+ S5K4ECGX_REG_WRITE(0x70003C28, 0x0000), /* 70003C28 */
+ S5K4ECGX_REG_WRITE(0x70003C2A, 0x02D2), /* 70003C2A */
+ S5K4ECGX_REG_WRITE(0x70003C2C, 0x3FB5), /* 70003C2C */
+ S5K4ECGX_REG_WRITE(0x70003C2E, 0x7000), /* 70003C2E */
+ S5K4ECGX_REG_WRITE(0x70003C30, 0x9E65), /* 70003C30 */
+ S5K4ECGX_REG_WRITE(0x70003C32, 0x0000), /* 70003C32 */
+ S5K4ECGX_REG_WRITE(0x70003C34, 0x4029), /* 70003C34 */
+ S5K4ECGX_REG_WRITE(0x70003C36, 0x7000), /* 70003C36 */
+ S5K4ECGX_REG_WRITE(0x70003C38, 0x7C49), /* 70003C38 */
+ S5K4ECGX_REG_WRITE(0x70003C3A, 0x0000), /* 70003C3A */
+ S5K4ECGX_REG_WRITE(0x70003C3C, 0x409D), /* 70003C3C */
+ S5K4ECGX_REG_WRITE(0x70003C3E, 0x7000), /* 70003C3E */
+ S5K4ECGX_REG_WRITE(0x70003C40, 0x7C63), /* 70003C40 */
+ S5K4ECGX_REG_WRITE(0x70003C42, 0x0000), /* 70003C42 */
+ S5K4ECGX_REG_WRITE(0x70003C44, 0x40B9), /* 70003C44 */
+ S5K4ECGX_REG_WRITE(0x70003C46, 0x7000), /* 70003C46 */
+ S5K4ECGX_REG_WRITE(0x70003C48, 0x8F01), /* 70003C48 */
+ S5K4ECGX_REG_WRITE(0x70003C4A, 0x0000), /* 70003C4A */
+ S5K4ECGX_REG_WRITE(0x70003C4C, 0x415B), /* 70003C4C */
+ S5K4ECGX_REG_WRITE(0x70003C4E, 0x7000), /* 70003C4E */
+ S5K4ECGX_REG_WRITE(0x70003C50, 0x7F3F), /* 70003C50 */
+ S5K4ECGX_REG_WRITE(0x70003C52, 0x0000), /* 70003C52 */
+ S5K4ECGX_REG_WRITE(0x70003C54, 0xB570), /* 70003C54 */
+ S5K4ECGX_REG_WRITE(0x70003C56, 0x000C), /* 70003C56 */
+ S5K4ECGX_REG_WRITE(0x70003C58, 0x0015), /* 70003C58 */
+ S5K4ECGX_REG_WRITE(0x70003C5A, 0x0029), /* 70003C5A */
+ S5K4ECGX_REG_WRITE(0x70003C5C, 0xF000), /* 70003C5C */
+ S5K4ECGX_REG_WRITE(0x70003C5E, 0xFAD8), /* 70003C5E */
+ S5K4ECGX_REG_WRITE(0x70003C60, 0x49F8), /* 70003C60 */
+ S5K4ECGX_REG_WRITE(0x70003C62, 0x00A8), /* 70003C62 */
+ S5K4ECGX_REG_WRITE(0x70003C64, 0x500C), /* 70003C64 */
+ S5K4ECGX_REG_WRITE(0x70003C66, 0xBC70), /* 70003C66 */
+ S5K4ECGX_REG_WRITE(0x70003C68, 0xBC08), /* 70003C68 */
+ S5K4ECGX_REG_WRITE(0x70003C6A, 0x4718), /* 70003C6A */
+ S5K4ECGX_REG_WRITE(0x70003C6C, 0x6808), /* 70003C6C */
+ S5K4ECGX_REG_WRITE(0x70003C6E, 0x0400), /* 70003C6E */
+ S5K4ECGX_REG_WRITE(0x70003C70, 0x0C00), /* 70003C70 */
+ S5K4ECGX_REG_WRITE(0x70003C72, 0x6849), /* 70003C72 */
+ S5K4ECGX_REG_WRITE(0x70003C74, 0x0409), /* 70003C74 */
+ S5K4ECGX_REG_WRITE(0x70003C76, 0x0C09), /* 70003C76 */
+ S5K4ECGX_REG_WRITE(0x70003C78, 0x4AF3), /* 70003C78 */
+ S5K4ECGX_REG_WRITE(0x70003C7A, 0x8992), /* 70003C7A */
+ S5K4ECGX_REG_WRITE(0x70003C7C, 0x2A00), /* 70003C7C */
+ S5K4ECGX_REG_WRITE(0x70003C7E, 0xD00D), /* 70003C7E */
+ S5K4ECGX_REG_WRITE(0x70003C80, 0x2300), /* 70003C80 */
+ S5K4ECGX_REG_WRITE(0x70003C82, 0x1A89), /* 70003C82 */
+ S5K4ECGX_REG_WRITE(0x70003C84, 0xD400), /* 70003C84 */
+ S5K4ECGX_REG_WRITE(0x70003C86, 0x000B), /* 70003C86 */
+ S5K4ECGX_REG_WRITE(0x70003C88, 0x0419), /* 70003C88 */
+ S5K4ECGX_REG_WRITE(0x70003C8A, 0x0C09), /* 70003C8A */
+ S5K4ECGX_REG_WRITE(0x70003C8C, 0x23FF), /* 70003C8C */
+ S5K4ECGX_REG_WRITE(0x70003C8E, 0x33C1), /* 70003C8E */
+ S5K4ECGX_REG_WRITE(0x70003C90, 0x1810), /* 70003C90 */
+ S5K4ECGX_REG_WRITE(0x70003C92, 0x4298), /* 70003C92 */
+ S5K4ECGX_REG_WRITE(0x70003C94, 0xD800), /* 70003C94 */
+ S5K4ECGX_REG_WRITE(0x70003C96, 0x0003), /* 70003C96 */
+ S5K4ECGX_REG_WRITE(0x70003C98, 0x0418), /* 70003C98 */
+ S5K4ECGX_REG_WRITE(0x70003C9A, 0x0C00), /* 70003C9A */
+ S5K4ECGX_REG_WRITE(0x70003C9C, 0x4AEB), /* 70003C9C */
+ S5K4ECGX_REG_WRITE(0x70003C9E, 0x8150), /* 70003C9E */
+ S5K4ECGX_REG_WRITE(0x70003CA0, 0x8191), /* 70003CA0 */
+ S5K4ECGX_REG_WRITE(0x70003CA2, 0x4770), /* 70003CA2 */
+ S5K4ECGX_REG_WRITE(0x70003CA4, 0xB5F3), /* 70003CA4 */
+ S5K4ECGX_REG_WRITE(0x70003CA6, 0x0004), /* 70003CA6 */
+ S5K4ECGX_REG_WRITE(0x70003CA8, 0xB081), /* 70003CA8 */
+ S5K4ECGX_REG_WRITE(0x70003CAA, 0x9802), /* 70003CAA */
+ S5K4ECGX_REG_WRITE(0x70003CAC, 0x6800), /* 70003CAC */
+ S5K4ECGX_REG_WRITE(0x70003CAE, 0x0600), /* 70003CAE */
+ S5K4ECGX_REG_WRITE(0x70003CB0, 0x0E00), /* 70003CB0 */
+ S5K4ECGX_REG_WRITE(0x70003CB2, 0x2201), /* 70003CB2 */
+ S5K4ECGX_REG_WRITE(0x70003CB4, 0x0015), /* 70003CB4 */
+ S5K4ECGX_REG_WRITE(0x70003CB6, 0x0021), /* 70003CB6 */
+ S5K4ECGX_REG_WRITE(0x70003CB8, 0x3910), /* 70003CB8 */
+ S5K4ECGX_REG_WRITE(0x70003CBA, 0x408A), /* 70003CBA */
+ S5K4ECGX_REG_WRITE(0x70003CBC, 0x40A5), /* 70003CBC */
+ S5K4ECGX_REG_WRITE(0x70003CBE, 0x4FE4), /* 70003CBE */
+ S5K4ECGX_REG_WRITE(0x70003CC0, 0x0016), /* 70003CC0 */
+ S5K4ECGX_REG_WRITE(0x70003CC2, 0x2C10), /* 70003CC2 */
+ S5K4ECGX_REG_WRITE(0x70003CC4, 0xDA03), /* 70003CC4 */
+ S5K4ECGX_REG_WRITE(0x70003CC6, 0x8839), /* 70003CC6 */
+ S5K4ECGX_REG_WRITE(0x70003CC8, 0x43A9), /* 70003CC8 */
+ S5K4ECGX_REG_WRITE(0x70003CCA, 0x8039), /* 70003CCA */
+ S5K4ECGX_REG_WRITE(0x70003CCC, 0xE002), /* 70003CCC */
+ S5K4ECGX_REG_WRITE(0x70003CCE, 0x8879), /* 70003CCE */
+ S5K4ECGX_REG_WRITE(0x70003CD0, 0x43B1), /* 70003CD0 */
+ S5K4ECGX_REG_WRITE(0x70003CD2, 0x8079), /* 70003CD2 */
+ S5K4ECGX_REG_WRITE(0x70003CD4, 0xF000), /* 70003CD4 */
+ S5K4ECGX_REG_WRITE(0x70003CD6, 0xFAA4), /* 70003CD6 */
+ S5K4ECGX_REG_WRITE(0x70003CD8, 0x2C10), /* 70003CD8 */
+ S5K4ECGX_REG_WRITE(0x70003CDA, 0xDA03), /* 70003CDA */
+ S5K4ECGX_REG_WRITE(0x70003CDC, 0x8839), /* 70003CDC */
+ S5K4ECGX_REG_WRITE(0x70003CDE, 0x4329), /* 70003CDE */
+ S5K4ECGX_REG_WRITE(0x70003CE0, 0x8039), /* 70003CE0 */
+ S5K4ECGX_REG_WRITE(0x70003CE2, 0xE002), /* 70003CE2 */
+ S5K4ECGX_REG_WRITE(0x70003CE4, 0x8879), /* 70003CE4 */
+ S5K4ECGX_REG_WRITE(0x70003CE6, 0x4331), /* 70003CE6 */
+ S5K4ECGX_REG_WRITE(0x70003CE8, 0x8079), /* 70003CE8 */
+ S5K4ECGX_REG_WRITE(0x70003CEA, 0x49DA), /* 70003CEA */
+ S5K4ECGX_REG_WRITE(0x70003CEC, 0x8809), /* 70003CEC */
+ S5K4ECGX_REG_WRITE(0x70003CEE, 0x2900), /* 70003CEE */
+ S5K4ECGX_REG_WRITE(0x70003CF0, 0xD102), /* 70003CF0 */
+ S5K4ECGX_REG_WRITE(0x70003CF2, 0xF000), /* 70003CF2 */
+ S5K4ECGX_REG_WRITE(0x70003CF4, 0xFA9D), /* 70003CF4 */
+ S5K4ECGX_REG_WRITE(0x70003CF6, 0x2000), /* 70003CF6 */
+ S5K4ECGX_REG_WRITE(0x70003CF8, 0x9902), /* 70003CF8 */
+ S5K4ECGX_REG_WRITE(0x70003CFA, 0x6008), /* 70003CFA */
+ S5K4ECGX_REG_WRITE(0x70003CFC, 0xBCFE), /* 70003CFC */
+ S5K4ECGX_REG_WRITE(0x70003CFE, 0xBC08), /* 70003CFE */
+ S5K4ECGX_REG_WRITE(0x70003D00, 0x4718), /* 70003D00 */
+ S5K4ECGX_REG_WRITE(0x70003D02, 0xB538), /* 70003D02 */
+ S5K4ECGX_REG_WRITE(0x70003D04, 0x9C04), /* 70003D04 */
+ S5K4ECGX_REG_WRITE(0x70003D06, 0x0015), /* 70003D06 */
+ S5K4ECGX_REG_WRITE(0x70003D08, 0x002A), /* 70003D08 */
+ S5K4ECGX_REG_WRITE(0x70003D0A, 0x9400), /* 70003D0A */
+ S5K4ECGX_REG_WRITE(0x70003D0C, 0xF000), /* 70003D0C */
+ S5K4ECGX_REG_WRITE(0x70003D0E, 0xFA98), /* 70003D0E */
+ S5K4ECGX_REG_WRITE(0x70003D10, 0x4AD1), /* 70003D10 */
+ S5K4ECGX_REG_WRITE(0x70003D12, 0x8811), /* 70003D12 */
+ S5K4ECGX_REG_WRITE(0x70003D14, 0x2900), /* 70003D14 */
+ S5K4ECGX_REG_WRITE(0x70003D16, 0xD00F), /* 70003D16 */
+ S5K4ECGX_REG_WRITE(0x70003D18, 0x8820), /* 70003D18 */
+ S5K4ECGX_REG_WRITE(0x70003D1A, 0x4281), /* 70003D1A */
+ S5K4ECGX_REG_WRITE(0x70003D1C, 0xD20C), /* 70003D1C */
+ S5K4ECGX_REG_WRITE(0x70003D1E, 0x8861), /* 70003D1E */
+ S5K4ECGX_REG_WRITE(0x70003D20, 0x8853), /* 70003D20 */
+ S5K4ECGX_REG_WRITE(0x70003D22, 0x4299), /* 70003D22 */
+ S5K4ECGX_REG_WRITE(0x70003D24, 0xD200), /* 70003D24 */
+ S5K4ECGX_REG_WRITE(0x70003D26, 0x1E40), /* 70003D26 */
+ S5K4ECGX_REG_WRITE(0x70003D28, 0x0400), /* 70003D28 */
+ S5K4ECGX_REG_WRITE(0x70003D2A, 0x0C00), /* 70003D2A */
+ S5K4ECGX_REG_WRITE(0x70003D2C, 0x8020), /* 70003D2C */
+ S5K4ECGX_REG_WRITE(0x70003D2E, 0x8851), /* 70003D2E */
+ S5K4ECGX_REG_WRITE(0x70003D30, 0x8061), /* 70003D30 */
+ S5K4ECGX_REG_WRITE(0x70003D32, 0x4368), /* 70003D32 */
+ S5K4ECGX_REG_WRITE(0x70003D34, 0x1840), /* 70003D34 */
+ S5K4ECGX_REG_WRITE(0x70003D36, 0x6060), /* 70003D36 */
+ S5K4ECGX_REG_WRITE(0x70003D38, 0xBC38), /* 70003D38 */
+ S5K4ECGX_REG_WRITE(0x70003D3A, 0xBC08), /* 70003D3A */
+ S5K4ECGX_REG_WRITE(0x70003D3C, 0x4718), /* 70003D3C */
+ S5K4ECGX_REG_WRITE(0x70003D3E, 0xB5F8), /* 70003D3E */
+ S5K4ECGX_REG_WRITE(0x70003D40, 0x0004), /* 70003D40 */
+ S5K4ECGX_REG_WRITE(0x70003D42, 0x6808), /* 70003D42 */
+ S5K4ECGX_REG_WRITE(0x70003D44, 0x0400), /* 70003D44 */
+ S5K4ECGX_REG_WRITE(0x70003D46, 0x0C00), /* 70003D46 */
+ S5K4ECGX_REG_WRITE(0x70003D48, 0x2201), /* 70003D48 */
+ S5K4ECGX_REG_WRITE(0x70003D4A, 0x0015), /* 70003D4A */
+ S5K4ECGX_REG_WRITE(0x70003D4C, 0x0021), /* 70003D4C */
+ S5K4ECGX_REG_WRITE(0x70003D4E, 0x3910), /* 70003D4E */
+ S5K4ECGX_REG_WRITE(0x70003D50, 0x408A), /* 70003D50 */
+ S5K4ECGX_REG_WRITE(0x70003D52, 0x40A5), /* 70003D52 */
+ S5K4ECGX_REG_WRITE(0x70003D54, 0x4FBE), /* 70003D54 */
+ S5K4ECGX_REG_WRITE(0x70003D56, 0x0016), /* 70003D56 */
+ S5K4ECGX_REG_WRITE(0x70003D58, 0x2C10), /* 70003D58 */
+ S5K4ECGX_REG_WRITE(0x70003D5A, 0xDA03), /* 70003D5A */
+ S5K4ECGX_REG_WRITE(0x70003D5C, 0x8839), /* 70003D5C */
+ S5K4ECGX_REG_WRITE(0x70003D5E, 0x43A9), /* 70003D5E */
+ S5K4ECGX_REG_WRITE(0x70003D60, 0x8039), /* 70003D60 */
+ S5K4ECGX_REG_WRITE(0x70003D62, 0xE002), /* 70003D62 */
+ S5K4ECGX_REG_WRITE(0x70003D64, 0x8879), /* 70003D64 */
+ S5K4ECGX_REG_WRITE(0x70003D66, 0x43B1), /* 70003D66 */
+ S5K4ECGX_REG_WRITE(0x70003D68, 0x8079), /* 70003D68 */
+ S5K4ECGX_REG_WRITE(0x70003D6A, 0xF000), /* 70003D6A */
+ S5K4ECGX_REG_WRITE(0x70003D6C, 0xFA71), /* 70003D6C */
+ S5K4ECGX_REG_WRITE(0x70003D6E, 0x2C10), /* 70003D6E */
+ S5K4ECGX_REG_WRITE(0x70003D70, 0xDA03), /* 70003D70 */
+ S5K4ECGX_REG_WRITE(0x70003D72, 0x8838), /* 70003D72 */
+ S5K4ECGX_REG_WRITE(0x70003D74, 0x4328), /* 70003D74 */
+ S5K4ECGX_REG_WRITE(0x70003D76, 0x8038), /* 70003D76 */
+ S5K4ECGX_REG_WRITE(0x70003D78, 0xE002), /* 70003D78 */
+ S5K4ECGX_REG_WRITE(0x70003D7A, 0x8878), /* 70003D7A */
+ S5K4ECGX_REG_WRITE(0x70003D7C, 0x4330), /* 70003D7C */
+ S5K4ECGX_REG_WRITE(0x70003D7E, 0x8078), /* 70003D7E */
+ S5K4ECGX_REG_WRITE(0x70003D80, 0x48B6), /* 70003D80 */
+ S5K4ECGX_REG_WRITE(0x70003D82, 0x8800), /* 70003D82 */
+ S5K4ECGX_REG_WRITE(0x70003D84, 0x0400), /* 70003D84 */
+ S5K4ECGX_REG_WRITE(0x70003D86, 0xD507), /* 70003D86 */
+ S5K4ECGX_REG_WRITE(0x70003D88, 0x4BB5), /* 70003D88 */
+ S5K4ECGX_REG_WRITE(0x70003D8A, 0x7819), /* 70003D8A */
+ S5K4ECGX_REG_WRITE(0x70003D8C, 0x4AB5), /* 70003D8C */
+ S5K4ECGX_REG_WRITE(0x70003D8E, 0x7810), /* 70003D8E */
+ S5K4ECGX_REG_WRITE(0x70003D90, 0x7018), /* 70003D90 */
+ S5K4ECGX_REG_WRITE(0x70003D92, 0x7011), /* 70003D92 */
+ S5K4ECGX_REG_WRITE(0x70003D94, 0x49B4), /* 70003D94 */
+ S5K4ECGX_REG_WRITE(0x70003D96, 0x8188), /* 70003D96 */
+ S5K4ECGX_REG_WRITE(0x70003D98, 0xBCF8), /* 70003D98 */
+ S5K4ECGX_REG_WRITE(0x70003D9A, 0xBC08), /* 70003D9A */
+ S5K4ECGX_REG_WRITE(0x70003D9C, 0x4718), /* 70003D9C */
+ S5K4ECGX_REG_WRITE(0x70003D9E, 0xB538), /* 70003D9E */
+ S5K4ECGX_REG_WRITE(0x70003DA0, 0x48B2), /* 70003DA0 */
+ S5K4ECGX_REG_WRITE(0x70003DA2, 0x4669), /* 70003DA2 */
+ S5K4ECGX_REG_WRITE(0x70003DA4, 0xF000), /* 70003DA4 */
+ S5K4ECGX_REG_WRITE(0x70003DA6, 0xFA5C), /* 70003DA6 */
+ S5K4ECGX_REG_WRITE(0x70003DA8, 0x48B1), /* 70003DA8 */
+ S5K4ECGX_REG_WRITE(0x70003DAA, 0x49B0), /* 70003DAA */
+ S5K4ECGX_REG_WRITE(0x70003DAC, 0x69C2), /* 70003DAC */
+ S5K4ECGX_REG_WRITE(0x70003DAE, 0x2400), /* 70003DAE */
+ S5K4ECGX_REG_WRITE(0x70003DB0, 0x31A8), /* 70003DB0 */
+ S5K4ECGX_REG_WRITE(0x70003DB2, 0x2A00), /* 70003DB2 */
+ S5K4ECGX_REG_WRITE(0x70003DB4, 0xD008), /* 70003DB4 */
+ S5K4ECGX_REG_WRITE(0x70003DB6, 0x61C4), /* 70003DB6 */
+ S5K4ECGX_REG_WRITE(0x70003DB8, 0x684A), /* 70003DB8 */
+ S5K4ECGX_REG_WRITE(0x70003DBA, 0x6242), /* 70003DBA */
+ S5K4ECGX_REG_WRITE(0x70003DBC, 0x6282), /* 70003DBC */
+ S5K4ECGX_REG_WRITE(0x70003DBE, 0x466B), /* 70003DBE */
+ S5K4ECGX_REG_WRITE(0x70003DC0, 0x881A), /* 70003DC0 */
+ S5K4ECGX_REG_WRITE(0x70003DC2, 0x6302), /* 70003DC2 */
+ S5K4ECGX_REG_WRITE(0x70003DC4, 0x885A), /* 70003DC4 */
+ S5K4ECGX_REG_WRITE(0x70003DC6, 0x6342), /* 70003DC6 */
+ S5K4ECGX_REG_WRITE(0x70003DC8, 0x6A02), /* 70003DC8 */
+ S5K4ECGX_REG_WRITE(0x70003DCA, 0x2A00), /* 70003DCA */
+ S5K4ECGX_REG_WRITE(0x70003DCC, 0xD00A), /* 70003DCC */
+ S5K4ECGX_REG_WRITE(0x70003DCE, 0x6204), /* 70003DCE */
+ S5K4ECGX_REG_WRITE(0x70003DD0, 0x6849), /* 70003DD0 */
+ S5K4ECGX_REG_WRITE(0x70003DD2, 0x6281), /* 70003DD2 */
+ S5K4ECGX_REG_WRITE(0x70003DD4, 0x466B), /* 70003DD4 */
+ S5K4ECGX_REG_WRITE(0x70003DD6, 0x8819), /* 70003DD6 */
+ S5K4ECGX_REG_WRITE(0x70003DD8, 0x6301), /* 70003DD8 */
+ S5K4ECGX_REG_WRITE(0x70003DDA, 0x8859), /* 70003DDA */
+ S5K4ECGX_REG_WRITE(0x70003DDC, 0x6341), /* 70003DDC */
+ S5K4ECGX_REG_WRITE(0x70003DDE, 0x49A5), /* 70003DDE */
+ S5K4ECGX_REG_WRITE(0x70003DE0, 0x88C9), /* 70003DE0 */
+ S5K4ECGX_REG_WRITE(0x70003DE2, 0x63C1), /* 70003DE2 */
+ S5K4ECGX_REG_WRITE(0x70003DE4, 0xF000), /* 70003DE4 */
+ S5K4ECGX_REG_WRITE(0x70003DE6, 0xFA44), /* 70003DE6 */
+ S5K4ECGX_REG_WRITE(0x70003DE8, 0xE7A6), /* 70003DE8 */
+ S5K4ECGX_REG_WRITE(0x70003DEA, 0xB5F0), /* 70003DEA */
+ S5K4ECGX_REG_WRITE(0x70003DEC, 0xB08B), /* 70003DEC */
+ S5K4ECGX_REG_WRITE(0x70003DEE, 0x20FF), /* 70003DEE */
+ S5K4ECGX_REG_WRITE(0x70003DF0, 0x1C40), /* 70003DF0 */
+ S5K4ECGX_REG_WRITE(0x70003DF2, 0x49A1), /* 70003DF2 */
+ S5K4ECGX_REG_WRITE(0x70003DF4, 0x89CC), /* 70003DF4 */
+ S5K4ECGX_REG_WRITE(0x70003DF6, 0x4E9E), /* 70003DF6 */
+ S5K4ECGX_REG_WRITE(0x70003DF8, 0x6AB1), /* 70003DF8 */
+ S5K4ECGX_REG_WRITE(0x70003DFA, 0x4284), /* 70003DFA */
+ S5K4ECGX_REG_WRITE(0x70003DFC, 0xD101), /* 70003DFC */
+ S5K4ECGX_REG_WRITE(0x70003DFE, 0x489F), /* 70003DFE */
+ S5K4ECGX_REG_WRITE(0x70003E00, 0x6081), /* 70003E00 */
+ S5K4ECGX_REG_WRITE(0x70003E02, 0x6A70), /* 70003E02 */
+ S5K4ECGX_REG_WRITE(0x70003E04, 0x0200), /* 70003E04 */
+ S5K4ECGX_REG_WRITE(0x70003E06, 0xF000), /* 70003E06 */
+ S5K4ECGX_REG_WRITE(0x70003E08, 0xFA3B), /* 70003E08 */
+ S5K4ECGX_REG_WRITE(0x70003E0A, 0x0400), /* 70003E0A */
+ S5K4ECGX_REG_WRITE(0x70003E0C, 0x0C00), /* 70003E0C */
+ S5K4ECGX_REG_WRITE(0x70003E0E, 0x4A96), /* 70003E0E */
+ S5K4ECGX_REG_WRITE(0x70003E10, 0x8A11), /* 70003E10 */
+ S5K4ECGX_REG_WRITE(0x70003E12, 0x9109), /* 70003E12 */
+ S5K4ECGX_REG_WRITE(0x70003E14, 0x2101), /* 70003E14 */
+ S5K4ECGX_REG_WRITE(0x70003E16, 0x0349), /* 70003E16 */
+ S5K4ECGX_REG_WRITE(0x70003E18, 0x4288), /* 70003E18 */
+ S5K4ECGX_REG_WRITE(0x70003E1A, 0xD200), /* 70003E1A */
+ S5K4ECGX_REG_WRITE(0x70003E1C, 0x0001), /* 70003E1C */
+ S5K4ECGX_REG_WRITE(0x70003E1E, 0x4A92), /* 70003E1E */
+ S5K4ECGX_REG_WRITE(0x70003E20, 0x8211), /* 70003E20 */
+ S5K4ECGX_REG_WRITE(0x70003E22, 0x4D97), /* 70003E22 */
+ S5K4ECGX_REG_WRITE(0x70003E24, 0x8829), /* 70003E24 */
+ S5K4ECGX_REG_WRITE(0x70003E26, 0x9108), /* 70003E26 */
+ S5K4ECGX_REG_WRITE(0x70003E28, 0x4A8B), /* 70003E28 */
+ S5K4ECGX_REG_WRITE(0x70003E2A, 0x2303), /* 70003E2A */
+ S5K4ECGX_REG_WRITE(0x70003E2C, 0x3222), /* 70003E2C */
+ S5K4ECGX_REG_WRITE(0x70003E2E, 0x1F91), /* 70003E2E */
+ S5K4ECGX_REG_WRITE(0x70003E30, 0xF000), /* 70003E30 */
+ S5K4ECGX_REG_WRITE(0x70003E32, 0xFA2C), /* 70003E32 */
+ S5K4ECGX_REG_WRITE(0x70003E34, 0x8028), /* 70003E34 */
+ S5K4ECGX_REG_WRITE(0x70003E36, 0x488E), /* 70003E36 */
+ S5K4ECGX_REG_WRITE(0x70003E38, 0x4987), /* 70003E38 */
+ S5K4ECGX_REG_WRITE(0x70003E3A, 0x6BC2), /* 70003E3A */
+ S5K4ECGX_REG_WRITE(0x70003E3C, 0x6AC0), /* 70003E3C */
+ S5K4ECGX_REG_WRITE(0x70003E3E, 0x4282), /* 70003E3E */
+ S5K4ECGX_REG_WRITE(0x70003E40, 0xD201), /* 70003E40 */
+ S5K4ECGX_REG_WRITE(0x70003E42, 0x8CC8), /* 70003E42 */
+ S5K4ECGX_REG_WRITE(0x70003E44, 0x8028), /* 70003E44 */
+ S5K4ECGX_REG_WRITE(0x70003E46, 0x88E8), /* 70003E46 */
+ S5K4ECGX_REG_WRITE(0x70003E48, 0x9007), /* 70003E48 */
+ S5K4ECGX_REG_WRITE(0x70003E4A, 0x2240), /* 70003E4A */
+ S5K4ECGX_REG_WRITE(0x70003E4C, 0x4310), /* 70003E4C */
+ S5K4ECGX_REG_WRITE(0x70003E4E, 0x80E8), /* 70003E4E */
+ S5K4ECGX_REG_WRITE(0x70003E50, 0x2000), /* 70003E50 */
+ S5K4ECGX_REG_WRITE(0x70003E52, 0x0041), /* 70003E52 */
+ S5K4ECGX_REG_WRITE(0x70003E54, 0x194B), /* 70003E54 */
+ S5K4ECGX_REG_WRITE(0x70003E56, 0x001E), /* 70003E56 */
+ S5K4ECGX_REG_WRITE(0x70003E58, 0x3680), /* 70003E58 */
+ S5K4ECGX_REG_WRITE(0x70003E5A, 0x8BB2), /* 70003E5A */
+ S5K4ECGX_REG_WRITE(0x70003E5C, 0xAF04), /* 70003E5C */
+ S5K4ECGX_REG_WRITE(0x70003E5E, 0x527A), /* 70003E5E */
+ S5K4ECGX_REG_WRITE(0x70003E60, 0x4A7D), /* 70003E60 */
+ S5K4ECGX_REG_WRITE(0x70003E62, 0x188A), /* 70003E62 */
+ S5K4ECGX_REG_WRITE(0x70003E64, 0x8897), /* 70003E64 */
+ S5K4ECGX_REG_WRITE(0x70003E66, 0x83B7), /* 70003E66 */
+ S5K4ECGX_REG_WRITE(0x70003E68, 0x33A0), /* 70003E68 */
+ S5K4ECGX_REG_WRITE(0x70003E6A, 0x891F), /* 70003E6A */
+ S5K4ECGX_REG_WRITE(0x70003E6C, 0xAE01), /* 70003E6C */
+ S5K4ECGX_REG_WRITE(0x70003E6E, 0x5277), /* 70003E6E */
+ S5K4ECGX_REG_WRITE(0x70003E70, 0x8A11), /* 70003E70 */
+ S5K4ECGX_REG_WRITE(0x70003E72, 0x8119), /* 70003E72 */
+ S5K4ECGX_REG_WRITE(0x70003E74, 0x1C40), /* 70003E74 */
+ S5K4ECGX_REG_WRITE(0x70003E76, 0x0400), /* 70003E76 */
+ S5K4ECGX_REG_WRITE(0x70003E78, 0x0C00), /* 70003E78 */
+ S5K4ECGX_REG_WRITE(0x70003E7A, 0x2806), /* 70003E7A */
+ S5K4ECGX_REG_WRITE(0x70003E7C, 0xD3E9), /* 70003E7C */
+ S5K4ECGX_REG_WRITE(0x70003E7E, 0xF000), /* 70003E7E */
+ S5K4ECGX_REG_WRITE(0x70003E80, 0xFA0D), /* 70003E80 */
+ S5K4ECGX_REG_WRITE(0x70003E82, 0xF000), /* 70003E82 */
+ S5K4ECGX_REG_WRITE(0x70003E84, 0xFA13), /* 70003E84 */
+ S5K4ECGX_REG_WRITE(0x70003E86, 0x4F79), /* 70003E86 */
+ S5K4ECGX_REG_WRITE(0x70003E88, 0x37A8), /* 70003E88 */
+ S5K4ECGX_REG_WRITE(0x70003E8A, 0x2800), /* 70003E8A */
+ S5K4ECGX_REG_WRITE(0x70003E8C, 0xD10A), /* 70003E8C */
+ S5K4ECGX_REG_WRITE(0x70003E8E, 0x1FE0), /* 70003E8E */
+ S5K4ECGX_REG_WRITE(0x70003E90, 0x38FD), /* 70003E90 */
+ S5K4ECGX_REG_WRITE(0x70003E92, 0xD001), /* 70003E92 */
+ S5K4ECGX_REG_WRITE(0x70003E94, 0x1CC0), /* 70003E94 */
+ S5K4ECGX_REG_WRITE(0x70003E96, 0xD105), /* 70003E96 */
+ S5K4ECGX_REG_WRITE(0x70003E98, 0x4874), /* 70003E98 */
+ S5K4ECGX_REG_WRITE(0x70003E9A, 0x8829), /* 70003E9A */
+ S5K4ECGX_REG_WRITE(0x70003E9C, 0x3818), /* 70003E9C */
+ S5K4ECGX_REG_WRITE(0x70003E9E, 0x6840), /* 70003E9E */
+ S5K4ECGX_REG_WRITE(0x70003EA0, 0x4348), /* 70003EA0 */
+ S5K4ECGX_REG_WRITE(0x70003EA2, 0x6078), /* 70003EA2 */
+ S5K4ECGX_REG_WRITE(0x70003EA4, 0x4972), /* 70003EA4 */
+ S5K4ECGX_REG_WRITE(0x70003EA6, 0x6878), /* 70003EA6 */
+ S5K4ECGX_REG_WRITE(0x70003EA8, 0x6B89), /* 70003EA8 */
+ S5K4ECGX_REG_WRITE(0x70003EAA, 0x4288), /* 70003EAA */
+ S5K4ECGX_REG_WRITE(0x70003EAC, 0xD300), /* 70003EAC */
+ S5K4ECGX_REG_WRITE(0x70003EAE, 0x0008), /* 70003EAE */
+ S5K4ECGX_REG_WRITE(0x70003EB0, 0x6078), /* 70003EB0 */
+ S5K4ECGX_REG_WRITE(0x70003EB2, 0x2000), /* 70003EB2 */
+ S5K4ECGX_REG_WRITE(0x70003EB4, 0x0041), /* 70003EB4 */
+ S5K4ECGX_REG_WRITE(0x70003EB6, 0xAA04), /* 70003EB6 */
+ S5K4ECGX_REG_WRITE(0x70003EB8, 0x5A53), /* 70003EB8 */
+ S5K4ECGX_REG_WRITE(0x70003EBA, 0x194A), /* 70003EBA */
+ S5K4ECGX_REG_WRITE(0x70003EBC, 0x269C), /* 70003EBC */
+ S5K4ECGX_REG_WRITE(0x70003EBE, 0x52B3), /* 70003EBE */
+ S5K4ECGX_REG_WRITE(0x70003EC0, 0xAB01), /* 70003EC0 */
+ S5K4ECGX_REG_WRITE(0x70003EC2, 0x5A59), /* 70003EC2 */
+ S5K4ECGX_REG_WRITE(0x70003EC4, 0x32A0), /* 70003EC4 */
+ S5K4ECGX_REG_WRITE(0x70003EC6, 0x8111), /* 70003EC6 */
+ S5K4ECGX_REG_WRITE(0x70003EC8, 0x1C40), /* 70003EC8 */
+ S5K4ECGX_REG_WRITE(0x70003ECA, 0x0400), /* 70003ECA */
+ S5K4ECGX_REG_WRITE(0x70003ECC, 0x0C00), /* 70003ECC */
+ S5K4ECGX_REG_WRITE(0x70003ECE, 0x2806), /* 70003ECE */
+ S5K4ECGX_REG_WRITE(0x70003ED0, 0xD3F0), /* 70003ED0 */
+ S5K4ECGX_REG_WRITE(0x70003ED2, 0x4965), /* 70003ED2 */
+ S5K4ECGX_REG_WRITE(0x70003ED4, 0x9809), /* 70003ED4 */
+ S5K4ECGX_REG_WRITE(0x70003ED6, 0x8208), /* 70003ED6 */
+ S5K4ECGX_REG_WRITE(0x70003ED8, 0x9808), /* 70003ED8 */
+ S5K4ECGX_REG_WRITE(0x70003EDA, 0x8028), /* 70003EDA */
+ S5K4ECGX_REG_WRITE(0x70003EDC, 0x9807), /* 70003EDC */
+ S5K4ECGX_REG_WRITE(0x70003EDE, 0x80E8), /* 70003EDE */
+ S5K4ECGX_REG_WRITE(0x70003EE0, 0x1FE0), /* 70003EE0 */
+ S5K4ECGX_REG_WRITE(0x70003EE2, 0x38FD), /* 70003EE2 */
+ S5K4ECGX_REG_WRITE(0x70003EE4, 0xD13B), /* 70003EE4 */
+ S5K4ECGX_REG_WRITE(0x70003EE6, 0x4D64), /* 70003EE6 */
+ S5K4ECGX_REG_WRITE(0x70003EE8, 0x89E8), /* 70003EE8 */
+ S5K4ECGX_REG_WRITE(0x70003EEA, 0x1FC1), /* 70003EEA */
+ S5K4ECGX_REG_WRITE(0x70003EEC, 0x39FF), /* 70003EEC */
+ S5K4ECGX_REG_WRITE(0x70003EEE, 0xD136), /* 70003EEE */
+ S5K4ECGX_REG_WRITE(0x70003EF0, 0x4C5F), /* 70003EF0 */
+ S5K4ECGX_REG_WRITE(0x70003EF2, 0x8AE0), /* 70003EF2 */
+ S5K4ECGX_REG_WRITE(0x70003EF4, 0xF000), /* 70003EF4 */
+ S5K4ECGX_REG_WRITE(0x70003EF6, 0xF9E2), /* 70003EF6 */
+ S5K4ECGX_REG_WRITE(0x70003EF8, 0x0006), /* 70003EF8 */
+ S5K4ECGX_REG_WRITE(0x70003EFA, 0x8B20), /* 70003EFA */
+ S5K4ECGX_REG_WRITE(0x70003EFC, 0xF000), /* 70003EFC */
+ S5K4ECGX_REG_WRITE(0x70003EFE, 0xF9E6), /* 70003EFE */
+ S5K4ECGX_REG_WRITE(0x70003F00, 0x9000), /* 70003F00 */
+ S5K4ECGX_REG_WRITE(0x70003F02, 0x6AA1), /* 70003F02 */
+ S5K4ECGX_REG_WRITE(0x70003F04, 0x6878), /* 70003F04 */
+ S5K4ECGX_REG_WRITE(0x70003F06, 0x1809), /* 70003F06 */
+ S5K4ECGX_REG_WRITE(0x70003F08, 0x0200), /* 70003F08 */
+ S5K4ECGX_REG_WRITE(0x70003F0A, 0xF000), /* 70003F0A */
+ S5K4ECGX_REG_WRITE(0x70003F0C, 0xF9B9), /* 70003F0C */
+ S5K4ECGX_REG_WRITE(0x70003F0E, 0x0400), /* 70003F0E */
+ S5K4ECGX_REG_WRITE(0x70003F10, 0x0C00), /* 70003F10 */
+ S5K4ECGX_REG_WRITE(0x70003F12, 0x0022), /* 70003F12 */
+ S5K4ECGX_REG_WRITE(0x70003F14, 0x3246), /* 70003F14 */
+ S5K4ECGX_REG_WRITE(0x70003F16, 0x0011), /* 70003F16 */
+ S5K4ECGX_REG_WRITE(0x70003F18, 0x310A), /* 70003F18 */
+ S5K4ECGX_REG_WRITE(0x70003F1A, 0x2305), /* 70003F1A */
+ S5K4ECGX_REG_WRITE(0x70003F1C, 0xF000), /* 70003F1C */
+ S5K4ECGX_REG_WRITE(0x70003F1E, 0xF9B6), /* 70003F1E */
+ S5K4ECGX_REG_WRITE(0x70003F20, 0x66E8), /* 70003F20 */
+ S5K4ECGX_REG_WRITE(0x70003F22, 0x6B23), /* 70003F22 */
+ S5K4ECGX_REG_WRITE(0x70003F24, 0x0002), /* 70003F24 */
+ S5K4ECGX_REG_WRITE(0x70003F26, 0x0031), /* 70003F26 */
+ S5K4ECGX_REG_WRITE(0x70003F28, 0x0018), /* 70003F28 */
+ S5K4ECGX_REG_WRITE(0x70003F2A, 0xF000), /* 70003F2A */
+ S5K4ECGX_REG_WRITE(0x70003F2C, 0xF9D7), /* 70003F2C */
+ S5K4ECGX_REG_WRITE(0x70003F2E, 0x466B), /* 70003F2E */
+ S5K4ECGX_REG_WRITE(0x70003F30, 0x8518), /* 70003F30 */
+ S5K4ECGX_REG_WRITE(0x70003F32, 0x6EEA), /* 70003F32 */
+ S5K4ECGX_REG_WRITE(0x70003F34, 0x6B60), /* 70003F34 */
+ S5K4ECGX_REG_WRITE(0x70003F36, 0x9900), /* 70003F36 */
+ S5K4ECGX_REG_WRITE(0x70003F38, 0xF000), /* 70003F38 */
+ S5K4ECGX_REG_WRITE(0x70003F3A, 0xF9D0), /* 70003F3A */
+ S5K4ECGX_REG_WRITE(0x70003F3C, 0x466B), /* 70003F3C */
+ S5K4ECGX_REG_WRITE(0x70003F3E, 0x8558), /* 70003F3E */
+ S5K4ECGX_REG_WRITE(0x70003F40, 0x0029), /* 70003F40 */
+ S5K4ECGX_REG_WRITE(0x70003F42, 0x980A), /* 70003F42 */
+ S5K4ECGX_REG_WRITE(0x70003F44, 0x3170), /* 70003F44 */
+ S5K4ECGX_REG_WRITE(0x70003F46, 0xF000), /* 70003F46 */
+ S5K4ECGX_REG_WRITE(0x70003F48, 0xF9D1), /* 70003F48 */
+ S5K4ECGX_REG_WRITE(0x70003F4A, 0x0028), /* 70003F4A */
+ S5K4ECGX_REG_WRITE(0x70003F4C, 0x3060), /* 70003F4C */
+ S5K4ECGX_REG_WRITE(0x70003F4E, 0x8A02), /* 70003F4E */
+ S5K4ECGX_REG_WRITE(0x70003F50, 0x4946), /* 70003F50 */
+ S5K4ECGX_REG_WRITE(0x70003F52, 0x3128), /* 70003F52 */
+ S5K4ECGX_REG_WRITE(0x70003F54, 0x808A), /* 70003F54 */
+ S5K4ECGX_REG_WRITE(0x70003F56, 0x8A42), /* 70003F56 */
+ S5K4ECGX_REG_WRITE(0x70003F58, 0x80CA), /* 70003F58 */
+ S5K4ECGX_REG_WRITE(0x70003F5A, 0x8A80), /* 70003F5A */
+ S5K4ECGX_REG_WRITE(0x70003F5C, 0x8108), /* 70003F5C */
+ S5K4ECGX_REG_WRITE(0x70003F5E, 0xB00B), /* 70003F5E */
+ S5K4ECGX_REG_WRITE(0x70003F60, 0xBCF0), /* 70003F60 */
+ S5K4ECGX_REG_WRITE(0x70003F62, 0xBC08), /* 70003F62 */
+ S5K4ECGX_REG_WRITE(0x70003F64, 0x4718), /* 70003F64 */
+ S5K4ECGX_REG_WRITE(0x70003F66, 0xB570), /* 70003F66 */
+ S5K4ECGX_REG_WRITE(0x70003F68, 0x2400), /* 70003F68 */
+ S5K4ECGX_REG_WRITE(0x70003F6A, 0x4D46), /* 70003F6A */
+ S5K4ECGX_REG_WRITE(0x70003F6C, 0x4846), /* 70003F6C */
+ S5K4ECGX_REG_WRITE(0x70003F6E, 0x8881), /* 70003F6E */
+ S5K4ECGX_REG_WRITE(0x70003F70, 0x4846), /* 70003F70 */
+ S5K4ECGX_REG_WRITE(0x70003F72, 0x8041), /* 70003F72 */
+ S5K4ECGX_REG_WRITE(0x70003F74, 0x2101), /* 70003F74 */
+ S5K4ECGX_REG_WRITE(0x70003F76, 0x8001), /* 70003F76 */
+ S5K4ECGX_REG_WRITE(0x70003F78, 0xF000), /* 70003F78 */
+ S5K4ECGX_REG_WRITE(0x70003F7A, 0xF9C0), /* 70003F7A */
+ S5K4ECGX_REG_WRITE(0x70003F7C, 0x4842), /* 70003F7C */
+ S5K4ECGX_REG_WRITE(0x70003F7E, 0x3820), /* 70003F7E */
+ S5K4ECGX_REG_WRITE(0x70003F80, 0x8BC0), /* 70003F80 */
+ S5K4ECGX_REG_WRITE(0x70003F82, 0xF000), /* 70003F82 */
+ S5K4ECGX_REG_WRITE(0x70003F84, 0xF9C3), /* 70003F84 */
+ S5K4ECGX_REG_WRITE(0x70003F86, 0x4B42), /* 70003F86 */
+ S5K4ECGX_REG_WRITE(0x70003F88, 0x220D), /* 70003F88 */
+ S5K4ECGX_REG_WRITE(0x70003F8A, 0x0712), /* 70003F8A */
+ S5K4ECGX_REG_WRITE(0x70003F8C, 0x18A8), /* 70003F8C */
+ S5K4ECGX_REG_WRITE(0x70003F8E, 0x8806), /* 70003F8E */
+ S5K4ECGX_REG_WRITE(0x70003F90, 0x00E1), /* 70003F90 */
+ S5K4ECGX_REG_WRITE(0x70003F92, 0x18C9), /* 70003F92 */
+ S5K4ECGX_REG_WRITE(0x70003F94, 0x81CE), /* 70003F94 */
+ S5K4ECGX_REG_WRITE(0x70003F96, 0x8846), /* 70003F96 */
+ S5K4ECGX_REG_WRITE(0x70003F98, 0x818E), /* 70003F98 */
+ S5K4ECGX_REG_WRITE(0x70003F9A, 0x8886), /* 70003F9A */
+ S5K4ECGX_REG_WRITE(0x70003F9C, 0x824E), /* 70003F9C */
+ S5K4ECGX_REG_WRITE(0x70003F9E, 0x88C0), /* 70003F9E */
+ S5K4ECGX_REG_WRITE(0x70003FA0, 0x8208), /* 70003FA0 */
+ S5K4ECGX_REG_WRITE(0x70003FA2, 0x3508), /* 70003FA2 */
+ S5K4ECGX_REG_WRITE(0x70003FA4, 0x042D), /* 70003FA4 */
+ S5K4ECGX_REG_WRITE(0x70003FA6, 0x0C2D), /* 70003FA6 */
+ S5K4ECGX_REG_WRITE(0x70003FA8, 0x1C64), /* 70003FA8 */
+ S5K4ECGX_REG_WRITE(0x70003FAA, 0x0424), /* 70003FAA */
+ S5K4ECGX_REG_WRITE(0x70003FAC, 0x0C24), /* 70003FAC */
+ S5K4ECGX_REG_WRITE(0x70003FAE, 0x2C07), /* 70003FAE */
+ S5K4ECGX_REG_WRITE(0x70003FB0, 0xD3EC), /* 70003FB0 */
+ S5K4ECGX_REG_WRITE(0x70003FB2, 0xE658), /* 70003FB2 */
+ S5K4ECGX_REG_WRITE(0x70003FB4, 0xB510), /* 70003FB4 */
+ S5K4ECGX_REG_WRITE(0x70003FB6, 0x4834), /* 70003FB6 */
+ S5K4ECGX_REG_WRITE(0x70003FB8, 0x4C34), /* 70003FB8 */
+ S5K4ECGX_REG_WRITE(0x70003FBA, 0x88C0), /* 70003FBA */
+ S5K4ECGX_REG_WRITE(0x70003FBC, 0x8060), /* 70003FBC */
+ S5K4ECGX_REG_WRITE(0x70003FBE, 0x2001), /* 70003FBE */
+ S5K4ECGX_REG_WRITE(0x70003FC0, 0x8020), /* 70003FC0 */
+ S5K4ECGX_REG_WRITE(0x70003FC2, 0x4831), /* 70003FC2 */
+ S5K4ECGX_REG_WRITE(0x70003FC4, 0x3820), /* 70003FC4 */
+ S5K4ECGX_REG_WRITE(0x70003FC6, 0x8BC0), /* 70003FC6 */
+ S5K4ECGX_REG_WRITE(0x70003FC8, 0xF000), /* 70003FC8 */
+ S5K4ECGX_REG_WRITE(0x70003FCA, 0xF9A0), /* 70003FCA */
+ S5K4ECGX_REG_WRITE(0x70003FCC, 0x88E0), /* 70003FCC */
+ S5K4ECGX_REG_WRITE(0x70003FCE, 0x4A31), /* 70003FCE */
+ S5K4ECGX_REG_WRITE(0x70003FD0, 0x2800), /* 70003FD0 */
+ S5K4ECGX_REG_WRITE(0x70003FD2, 0xD003), /* 70003FD2 */
+ S5K4ECGX_REG_WRITE(0x70003FD4, 0x4930), /* 70003FD4 */
+ S5K4ECGX_REG_WRITE(0x70003FD6, 0x8849), /* 70003FD6 */
+ S5K4ECGX_REG_WRITE(0x70003FD8, 0x2900), /* 70003FD8 */
+ S5K4ECGX_REG_WRITE(0x70003FDA, 0xD009), /* 70003FDA */
+ S5K4ECGX_REG_WRITE(0x70003FDC, 0x2001), /* 70003FDC */
+ S5K4ECGX_REG_WRITE(0x70003FDE, 0x03C0), /* 70003FDE */
+ S5K4ECGX_REG_WRITE(0x70003FE0, 0x8050), /* 70003FE0 */
+ S5K4ECGX_REG_WRITE(0x70003FE2, 0x80D0), /* 70003FE2 */
+ S5K4ECGX_REG_WRITE(0x70003FE4, 0x2000), /* 70003FE4 */
+ S5K4ECGX_REG_WRITE(0x70003FE6, 0x8090), /* 70003FE6 */
+ S5K4ECGX_REG_WRITE(0x70003FE8, 0x8110), /* 70003FE8 */
+ S5K4ECGX_REG_WRITE(0x70003FEA, 0xBC10), /* 70003FEA */
+ S5K4ECGX_REG_WRITE(0x70003FEC, 0xBC08), /* 70003FEC */
+ S5K4ECGX_REG_WRITE(0x70003FEE, 0x4718), /* 70003FEE */
+ S5K4ECGX_REG_WRITE(0x70003FF0, 0x8050), /* 70003FF0 */
+ S5K4ECGX_REG_WRITE(0x70003FF2, 0x8920), /* 70003FF2 */
+ S5K4ECGX_REG_WRITE(0x70003FF4, 0x80D0), /* 70003FF4 */
+ S5K4ECGX_REG_WRITE(0x70003FF6, 0x8960), /* 70003FF6 */
+ S5K4ECGX_REG_WRITE(0x70003FF8, 0x0400), /* 70003FF8 */
+ S5K4ECGX_REG_WRITE(0x70003FFA, 0x1400), /* 70003FFA */
+ S5K4ECGX_REG_WRITE(0x70003FFC, 0x8090), /* 70003FFC */
+ S5K4ECGX_REG_WRITE(0x70003FFE, 0x89A1), /* 70003FFE */
+ S5K4ECGX_REG_WRITE(0x70004000, 0x0409), /* 70004000 */
+ S5K4ECGX_REG_WRITE(0x70004002, 0x1409), /* 70004002 */
+ S5K4ECGX_REG_WRITE(0x70004004, 0x8111), /* 70004004 */
+ S5K4ECGX_REG_WRITE(0x70004006, 0x89E3), /* 70004006 */
+ S5K4ECGX_REG_WRITE(0x70004008, 0x8A24), /* 70004008 */
+ S5K4ECGX_REG_WRITE(0x7000400A, 0x2B00), /* 7000400A */
+ S5K4ECGX_REG_WRITE(0x7000400C, 0xD104), /* 7000400C */
+ S5K4ECGX_REG_WRITE(0x7000400E, 0x17C3), /* 7000400E */
+ S5K4ECGX_REG_WRITE(0x70004010, 0x0F5B), /* 70004010 */
+ S5K4ECGX_REG_WRITE(0x70004012, 0x1818), /* 70004012 */
+ S5K4ECGX_REG_WRITE(0x70004014, 0x10C0), /* 70004014 */
+ S5K4ECGX_REG_WRITE(0x70004016, 0x8090), /* 70004016 */
+ S5K4ECGX_REG_WRITE(0x70004018, 0x2C00), /* 70004018 */
+ S5K4ECGX_REG_WRITE(0x7000401A, 0xD1E6), /* 7000401A */
+ S5K4ECGX_REG_WRITE(0x7000401C, 0x17C8), /* 7000401C */
+ S5K4ECGX_REG_WRITE(0x7000401E, 0x0F40), /* 7000401E */
+ S5K4ECGX_REG_WRITE(0x70004020, 0x1840), /* 70004020 */
+ S5K4ECGX_REG_WRITE(0x70004022, 0x10C0), /* 70004022 */
+ S5K4ECGX_REG_WRITE(0x70004024, 0x8110), /* 70004024 */
+ S5K4ECGX_REG_WRITE(0x70004026, 0xE7E0), /* 70004026 */
+ S5K4ECGX_REG_WRITE(0x70004028, 0xB510), /* 70004028 */
+ S5K4ECGX_REG_WRITE(0x7000402A, 0x000C), /* 7000402A */
+ S5K4ECGX_REG_WRITE(0x7000402C, 0x4919), /* 7000402C */
+ S5K4ECGX_REG_WRITE(0x7000402E, 0x2204), /* 7000402E */
+ S5K4ECGX_REG_WRITE(0x70004030, 0x6820), /* 70004030 */
+ S5K4ECGX_REG_WRITE(0x70004032, 0x5E8A), /* 70004032 */
+ S5K4ECGX_REG_WRITE(0x70004034, 0x0140), /* 70004034 */
+ S5K4ECGX_REG_WRITE(0x70004036, 0x1A80), /* 70004036 */
+ S5K4ECGX_REG_WRITE(0x70004038, 0x0280), /* 70004038 */
+ S5K4ECGX_REG_WRITE(0x7000403A, 0x8849), /* 7000403A */
+ S5K4ECGX_REG_WRITE(0x7000403C, 0xF000), /* 7000403C */
+ S5K4ECGX_REG_WRITE(0x7000403E, 0xF96E), /* 7000403E */
+ S5K4ECGX_REG_WRITE(0x70004040, 0x6020), /* 70004040 */
+ S5K4ECGX_REG_WRITE(0x70004042, 0xE7D2), /* 70004042 */
+ S5K4ECGX_REG_WRITE(0x70004044, 0x38D4), /* 70004044 */
+ S5K4ECGX_REG_WRITE(0x70004046, 0x7000), /* 70004046 */
+ S5K4ECGX_REG_WRITE(0x70004048, 0x17D0), /* 70004048 */
+ S5K4ECGX_REG_WRITE(0x7000404A, 0x7000), /* 7000404A */
+ S5K4ECGX_REG_WRITE(0x7000404C, 0x5000), /* 7000404C */
+ S5K4ECGX_REG_WRITE(0x7000404E, 0xD000), /* 7000404E */
+ S5K4ECGX_REG_WRITE(0x70004050, 0x1100), /* 70004050 */
+ S5K4ECGX_REG_WRITE(0x70004052, 0xD000), /* 70004052 */
+ S5K4ECGX_REG_WRITE(0x70004054, 0x171A), /* 70004054 */
+ S5K4ECGX_REG_WRITE(0x70004056, 0x7000), /* 70004056 */
+ S5K4ECGX_REG_WRITE(0x70004058, 0x4780), /* 70004058 */
+ S5K4ECGX_REG_WRITE(0x7000405A, 0x7000), /* 7000405A */
+ S5K4ECGX_REG_WRITE(0x7000405C, 0x2FCA), /* 7000405C */
+ S5K4ECGX_REG_WRITE(0x7000405E, 0x7000), /* 7000405E */
+ S5K4ECGX_REG_WRITE(0x70004060, 0x2FC5), /* 70004060 */
+ S5K4ECGX_REG_WRITE(0x70004062, 0x7000), /* 70004062 */
+ S5K4ECGX_REG_WRITE(0x70004064, 0x2FC6), /* 70004064 */
+ S5K4ECGX_REG_WRITE(0x70004066, 0x7000), /* 70004066 */
+ S5K4ECGX_REG_WRITE(0x70004068, 0x2ED8), /* 70004068 */
+ S5K4ECGX_REG_WRITE(0x7000406A, 0x7000), /* 7000406A */
+ S5K4ECGX_REG_WRITE(0x7000406C, 0x2BD0), /* 7000406C */
+ S5K4ECGX_REG_WRITE(0x7000406E, 0x7000), /* 7000406E */
+ S5K4ECGX_REG_WRITE(0x70004070, 0x17E0), /* 70004070 */
+ S5K4ECGX_REG_WRITE(0x70004072, 0x7000), /* 70004072 */
+ S5K4ECGX_REG_WRITE(0x70004074, 0x2DE8), /* 70004074 */
+ S5K4ECGX_REG_WRITE(0x70004076, 0x7000), /* 70004076 */
+ S5K4ECGX_REG_WRITE(0x70004078, 0x37E0), /* 70004078 */
+ S5K4ECGX_REG_WRITE(0x7000407A, 0x7000), /* 7000407A */
+ S5K4ECGX_REG_WRITE(0x7000407C, 0x210C), /* 7000407C */
+ S5K4ECGX_REG_WRITE(0x7000407E, 0x7000), /* 7000407E */
+ S5K4ECGX_REG_WRITE(0x70004080, 0x1484), /* 70004080 */
+ S5K4ECGX_REG_WRITE(0x70004082, 0x7000), /* 70004082 */
+ S5K4ECGX_REG_WRITE(0x70004084, 0xA006), /* 70004084 */
+ S5K4ECGX_REG_WRITE(0x70004086, 0x0000), /* 70004086 */
+ S5K4ECGX_REG_WRITE(0x70004088, 0x0724), /* 70004088 */
+ S5K4ECGX_REG_WRITE(0x7000408A, 0x7000), /* 7000408A */
+ S5K4ECGX_REG_WRITE(0x7000408C, 0xA000), /* 7000408C */
+ S5K4ECGX_REG_WRITE(0x7000408E, 0xD000), /* 7000408E */
+ S5K4ECGX_REG_WRITE(0x70004090, 0x2270), /* 70004090 */
+ S5K4ECGX_REG_WRITE(0x70004092, 0x7000), /* 70004092 */
+ S5K4ECGX_REG_WRITE(0x70004094, 0x2558), /* 70004094 */
+ S5K4ECGX_REG_WRITE(0x70004096, 0x7000), /* 70004096 */
+ S5K4ECGX_REG_WRITE(0x70004098, 0x146C), /* 70004098 */
+ S5K4ECGX_REG_WRITE(0x7000409A, 0x7000), /* 7000409A */
+ S5K4ECGX_REG_WRITE(0x7000409C, 0xB510), /* 7000409C */
+ S5K4ECGX_REG_WRITE(0x7000409E, 0x000C), /* 7000409E */
+ S5K4ECGX_REG_WRITE(0x700040A0, 0x4951), /* 700040A0 */
+ S5K4ECGX_REG_WRITE(0x700040A2, 0x2208), /* 700040A2 */
+ S5K4ECGX_REG_WRITE(0x700040A4, 0x6820), /* 700040A4 */
+ S5K4ECGX_REG_WRITE(0x700040A6, 0x5E8A), /* 700040A6 */
+ S5K4ECGX_REG_WRITE(0x700040A8, 0x0140), /* 700040A8 */
+ S5K4ECGX_REG_WRITE(0x700040AA, 0x1A80), /* 700040AA */
+ S5K4ECGX_REG_WRITE(0x700040AC, 0x0280), /* 700040AC */
+ S5K4ECGX_REG_WRITE(0x700040AE, 0x88C9), /* 700040AE */
+ S5K4ECGX_REG_WRITE(0x700040B0, 0xF000), /* 700040B0 */
+ S5K4ECGX_REG_WRITE(0x700040B2, 0xF934), /* 700040B2 */
+ S5K4ECGX_REG_WRITE(0x700040B4, 0x6020), /* 700040B4 */
+ S5K4ECGX_REG_WRITE(0x700040B6, 0xE798), /* 700040B6 */
+ S5K4ECGX_REG_WRITE(0x700040B8, 0xB5FE), /* 700040B8 */
+ S5K4ECGX_REG_WRITE(0x700040BA, 0x000C), /* 700040BA */
+ S5K4ECGX_REG_WRITE(0x700040BC, 0x6825), /* 700040BC */
+ S5K4ECGX_REG_WRITE(0x700040BE, 0x6866), /* 700040BE */
+ S5K4ECGX_REG_WRITE(0x700040C0, 0x68A0), /* 700040C0 */
+ S5K4ECGX_REG_WRITE(0x700040C2, 0x9001), /* 700040C2 */
+ S5K4ECGX_REG_WRITE(0x700040C4, 0x68E7), /* 700040C4 */
+ S5K4ECGX_REG_WRITE(0x700040C6, 0x1BA8), /* 700040C6 */
+ S5K4ECGX_REG_WRITE(0x700040C8, 0x42B5), /* 700040C8 */
+ S5K4ECGX_REG_WRITE(0x700040CA, 0xDA00), /* 700040CA */
+ S5K4ECGX_REG_WRITE(0x700040CC, 0x1B70), /* 700040CC */
+ S5K4ECGX_REG_WRITE(0x700040CE, 0x9000), /* 700040CE */
+ S5K4ECGX_REG_WRITE(0x700040D0, 0x4945), /* 700040D0 */
+ S5K4ECGX_REG_WRITE(0x700040D2, 0x4846), /* 700040D2 */
+ S5K4ECGX_REG_WRITE(0x700040D4, 0x884A), /* 700040D4 */
+ S5K4ECGX_REG_WRITE(0x700040D6, 0x8843), /* 700040D6 */
+ S5K4ECGX_REG_WRITE(0x700040D8, 0x435A), /* 700040D8 */
+ S5K4ECGX_REG_WRITE(0x700040DA, 0x2304), /* 700040DA */
+ S5K4ECGX_REG_WRITE(0x700040DC, 0x5ECB), /* 700040DC */
+ S5K4ECGX_REG_WRITE(0x700040DE, 0x0A92), /* 700040DE */
+ S5K4ECGX_REG_WRITE(0x700040E0, 0x18D2), /* 700040E0 */
+ S5K4ECGX_REG_WRITE(0x700040E2, 0x02D2), /* 700040E2 */
+ S5K4ECGX_REG_WRITE(0x700040E4, 0x0C12), /* 700040E4 */
+ S5K4ECGX_REG_WRITE(0x700040E6, 0x88CB), /* 700040E6 */
+ S5K4ECGX_REG_WRITE(0x700040E8, 0x8880), /* 700040E8 */
+ S5K4ECGX_REG_WRITE(0x700040EA, 0x4343), /* 700040EA */
+ S5K4ECGX_REG_WRITE(0x700040EC, 0x0A98), /* 700040EC */
+ S5K4ECGX_REG_WRITE(0x700040EE, 0x2308), /* 700040EE */
+ S5K4ECGX_REG_WRITE(0x700040F0, 0x5ECB), /* 700040F0 */
+ S5K4ECGX_REG_WRITE(0x700040F2, 0x18C0), /* 700040F2 */
+ S5K4ECGX_REG_WRITE(0x700040F4, 0x02C0), /* 700040F4 */
+ S5K4ECGX_REG_WRITE(0x700040F6, 0x0C00), /* 700040F6 */
+ S5K4ECGX_REG_WRITE(0x700040F8, 0x0411), /* 700040F8 */
+ S5K4ECGX_REG_WRITE(0x700040FA, 0x0400), /* 700040FA */
+ S5K4ECGX_REG_WRITE(0x700040FC, 0x1409), /* 700040FC */
+ S5K4ECGX_REG_WRITE(0x700040FE, 0x1400), /* 700040FE */
+ S5K4ECGX_REG_WRITE(0x70004100, 0x1A08), /* 70004100 */
+ S5K4ECGX_REG_WRITE(0x70004102, 0x493A), /* 70004102 */
+ S5K4ECGX_REG_WRITE(0x70004104, 0x39E0), /* 70004104 */
+ S5K4ECGX_REG_WRITE(0x70004106, 0x6148), /* 70004106 */
+ S5K4ECGX_REG_WRITE(0x70004108, 0x9801), /* 70004108 */
+ S5K4ECGX_REG_WRITE(0x7000410A, 0x3040), /* 7000410A */
+ S5K4ECGX_REG_WRITE(0x7000410C, 0x7880), /* 7000410C */
+ S5K4ECGX_REG_WRITE(0x7000410E, 0x2800), /* 7000410E */
+ S5K4ECGX_REG_WRITE(0x70004110, 0xD103), /* 70004110 */
+ S5K4ECGX_REG_WRITE(0x70004112, 0x9801), /* 70004112 */
+ S5K4ECGX_REG_WRITE(0x70004114, 0x0029), /* 70004114 */
+ S5K4ECGX_REG_WRITE(0x70004116, 0xF000), /* 70004116 */
+ S5K4ECGX_REG_WRITE(0x70004118, 0xF907), /* 70004118 */
+ S5K4ECGX_REG_WRITE(0x7000411A, 0x8839), /* 7000411A */
+ S5K4ECGX_REG_WRITE(0x7000411C, 0x9800), /* 7000411C */
+ S5K4ECGX_REG_WRITE(0x7000411E, 0x4281), /* 7000411E */
+ S5K4ECGX_REG_WRITE(0x70004120, 0xD814), /* 70004120 */
+ S5K4ECGX_REG_WRITE(0x70004122, 0x8879), /* 70004122 */
+ S5K4ECGX_REG_WRITE(0x70004124, 0x9800), /* 70004124 */
+ S5K4ECGX_REG_WRITE(0x70004126, 0x4281), /* 70004126 */
+ S5K4ECGX_REG_WRITE(0x70004128, 0xD20C), /* 70004128 */
+ S5K4ECGX_REG_WRITE(0x7000412A, 0x9801), /* 7000412A */
+ S5K4ECGX_REG_WRITE(0x7000412C, 0x0029), /* 7000412C */
+ S5K4ECGX_REG_WRITE(0x7000412E, 0xF000), /* 7000412E */
+ S5K4ECGX_REG_WRITE(0x70004130, 0xF903), /* 70004130 */
+ S5K4ECGX_REG_WRITE(0x70004132, 0x9801), /* 70004132 */
+ S5K4ECGX_REG_WRITE(0x70004134, 0x0029), /* 70004134 */
+ S5K4ECGX_REG_WRITE(0x70004136, 0xF000), /* 70004136 */
+ S5K4ECGX_REG_WRITE(0x70004138, 0xF8FF), /* 70004138 */
+ S5K4ECGX_REG_WRITE(0x7000413A, 0x9801), /* 7000413A */
+ S5K4ECGX_REG_WRITE(0x7000413C, 0x0029), /* 7000413C */
+ S5K4ECGX_REG_WRITE(0x7000413E, 0xF000), /* 7000413E */
+ S5K4ECGX_REG_WRITE(0x70004140, 0xF8FB), /* 70004140 */
+ S5K4ECGX_REG_WRITE(0x70004142, 0xE003), /* 70004142 */
+ S5K4ECGX_REG_WRITE(0x70004144, 0x9801), /* 70004144 */
+ S5K4ECGX_REG_WRITE(0x70004146, 0x0029), /* 70004146 */
+ S5K4ECGX_REG_WRITE(0x70004148, 0xF000), /* 70004148 */
+ S5K4ECGX_REG_WRITE(0x7000414A, 0xF8F6), /* 7000414A */
+ S5K4ECGX_REG_WRITE(0x7000414C, 0x9801), /* 7000414C */
+ S5K4ECGX_REG_WRITE(0x7000414E, 0x0032), /* 7000414E */
+ S5K4ECGX_REG_WRITE(0x70004150, 0x0039), /* 70004150 */
+ S5K4ECGX_REG_WRITE(0x70004152, 0xF000), /* 70004152 */
+ S5K4ECGX_REG_WRITE(0x70004154, 0xF8F9), /* 70004154 */
+ S5K4ECGX_REG_WRITE(0x70004156, 0x6020), /* 70004156 */
+ S5K4ECGX_REG_WRITE(0x70004158, 0xE5D0), /* 70004158 */
+ S5K4ECGX_REG_WRITE(0x7000415A, 0xB57C), /* 7000415A */
+ S5K4ECGX_REG_WRITE(0x7000415C, 0x4824), /* 7000415C */
+ S5K4ECGX_REG_WRITE(0x7000415E, 0xA901), /* 7000415E */
+ S5K4ECGX_REG_WRITE(0x70004160, 0x0004), /* 70004160 */
+ S5K4ECGX_REG_WRITE(0x70004162, 0xF000), /* 70004162 */
+ S5K4ECGX_REG_WRITE(0x70004164, 0xF87D), /* 70004164 */
+ S5K4ECGX_REG_WRITE(0x70004166, 0x466B), /* 70004166 */
+ S5K4ECGX_REG_WRITE(0x70004168, 0x88D9), /* 70004168 */
+ S5K4ECGX_REG_WRITE(0x7000416A, 0x8898), /* 7000416A */
+ S5K4ECGX_REG_WRITE(0x7000416C, 0x4B1F), /* 7000416C */
+ S5K4ECGX_REG_WRITE(0x7000416E, 0x3346), /* 7000416E */
+ S5K4ECGX_REG_WRITE(0x70004170, 0x1E9A), /* 70004170 */
+ S5K4ECGX_REG_WRITE(0x70004172, 0xF000), /* 70004172 */
+ S5K4ECGX_REG_WRITE(0x70004174, 0xF8F1), /* 70004174 */
+ S5K4ECGX_REG_WRITE(0x70004176, 0x481E), /* 70004176 */
+ S5K4ECGX_REG_WRITE(0x70004178, 0x491C), /* 70004178 */
+ S5K4ECGX_REG_WRITE(0x7000417A, 0x3812), /* 7000417A */
+ S5K4ECGX_REG_WRITE(0x7000417C, 0x3140), /* 7000417C */
+ S5K4ECGX_REG_WRITE(0x7000417E, 0x8A42), /* 7000417E */
+ S5K4ECGX_REG_WRITE(0x70004180, 0x888B), /* 70004180 */
+ S5K4ECGX_REG_WRITE(0x70004182, 0x18D2), /* 70004182 */
+ S5K4ECGX_REG_WRITE(0x70004184, 0x8242), /* 70004184 */
+ S5K4ECGX_REG_WRITE(0x70004186, 0x8AC2), /* 70004186 */
+ S5K4ECGX_REG_WRITE(0x70004188, 0x88C9), /* 70004188 */
+ S5K4ECGX_REG_WRITE(0x7000418A, 0x1851), /* 7000418A */
+ S5K4ECGX_REG_WRITE(0x7000418C, 0x82C1), /* 7000418C */
+ S5K4ECGX_REG_WRITE(0x7000418E, 0x0020), /* 7000418E */
+ S5K4ECGX_REG_WRITE(0x70004190, 0x4669), /* 70004190 */
+ S5K4ECGX_REG_WRITE(0x70004192, 0xF000), /* 70004192 */
+ S5K4ECGX_REG_WRITE(0x70004194, 0xF865), /* 70004194 */
+ S5K4ECGX_REG_WRITE(0x70004196, 0x4817), /* 70004196 */
+ S5K4ECGX_REG_WRITE(0x70004198, 0x214D), /* 70004198 */
+ S5K4ECGX_REG_WRITE(0x7000419A, 0x8301), /* 7000419A */
+ S5K4ECGX_REG_WRITE(0x7000419C, 0x2196), /* 7000419C */
+ S5K4ECGX_REG_WRITE(0x7000419E, 0x8381), /* 7000419E */
+ S5K4ECGX_REG_WRITE(0x700041A0, 0x211D), /* 700041A0 */
+ S5K4ECGX_REG_WRITE(0x700041A2, 0x3020), /* 700041A2 */
+ S5K4ECGX_REG_WRITE(0x700041A4, 0x8001), /* 700041A4 */
+ S5K4ECGX_REG_WRITE(0x700041A6, 0xF000), /* 700041A6 */
+ S5K4ECGX_REG_WRITE(0x700041A8, 0xF8DF), /* 700041A8 */
+ S5K4ECGX_REG_WRITE(0x700041AA, 0xF000), /* 700041AA */
+ S5K4ECGX_REG_WRITE(0x700041AC, 0xF8E5), /* 700041AC */
+ S5K4ECGX_REG_WRITE(0x700041AE, 0x4812), /* 700041AE */
+ S5K4ECGX_REG_WRITE(0x700041B0, 0x4C12), /* 700041B0 */
+ S5K4ECGX_REG_WRITE(0x700041B2, 0x6E00), /* 700041B2 */
+ S5K4ECGX_REG_WRITE(0x700041B4, 0x60E0), /* 700041B4 */
+ S5K4ECGX_REG_WRITE(0x700041B6, 0x466B), /* 700041B6 */
+ S5K4ECGX_REG_WRITE(0x700041B8, 0x8818), /* 700041B8 */
+ S5K4ECGX_REG_WRITE(0x700041BA, 0x8859), /* 700041BA */
+ S5K4ECGX_REG_WRITE(0x700041BC, 0x0025), /* 700041BC */
+ S5K4ECGX_REG_WRITE(0x700041BE, 0x1A40), /* 700041BE */
+ S5K4ECGX_REG_WRITE(0x700041C0, 0x3540), /* 700041C0 */
+ S5K4ECGX_REG_WRITE(0x700041C2, 0x61A8), /* 700041C2 */
+ S5K4ECGX_REG_WRITE(0x700041C4, 0x4809), /* 700041C4 */
+ S5K4ECGX_REG_WRITE(0x700041C6, 0x9900), /* 700041C6 */
+ S5K4ECGX_REG_WRITE(0x700041C8, 0x3060), /* 700041C8 */
+ S5K4ECGX_REG_WRITE(0x700041CA, 0xF000), /* 700041CA */
+ S5K4ECGX_REG_WRITE(0x700041CC, 0xF8DD), /* 700041CC */
+ S5K4ECGX_REG_WRITE(0x700041CE, 0x466B), /* 700041CE */
+ S5K4ECGX_REG_WRITE(0x700041D0, 0x8819), /* 700041D0 */
+ S5K4ECGX_REG_WRITE(0x700041D2, 0x1DE0), /* 700041D2 */
+ S5K4ECGX_REG_WRITE(0x700041D4, 0x30F9), /* 700041D4 */
+ S5K4ECGX_REG_WRITE(0x700041D6, 0x8741), /* 700041D6 */
+ S5K4ECGX_REG_WRITE(0x700041D8, 0x8859), /* 700041D8 */
+ S5K4ECGX_REG_WRITE(0x700041DA, 0x8781), /* 700041DA */
+ S5K4ECGX_REG_WRITE(0x700041DC, 0x2000), /* 700041DC */
+ S5K4ECGX_REG_WRITE(0x700041DE, 0x71A0), /* 700041DE */
+ S5K4ECGX_REG_WRITE(0x700041E0, 0x74A8), /* 700041E0 */
+ S5K4ECGX_REG_WRITE(0x700041E2, 0xBC7C), /* 700041E2 */
+ S5K4ECGX_REG_WRITE(0x700041E4, 0xBC08), /* 700041E4 */
+ S5K4ECGX_REG_WRITE(0x700041E6, 0x4718), /* 700041E6 */
+ S5K4ECGX_REG_WRITE(0x700041E8, 0x2558), /* 700041E8 */
+ S5K4ECGX_REG_WRITE(0x700041EA, 0x7000), /* 700041EA */
+ S5K4ECGX_REG_WRITE(0x700041EC, 0x2AB8), /* 700041EC */
+ S5K4ECGX_REG_WRITE(0x700041EE, 0x7000), /* 700041EE */
+ S5K4ECGX_REG_WRITE(0x700041F0, 0x145E), /* 700041F0 */
+ S5K4ECGX_REG_WRITE(0x700041F2, 0x7000), /* 700041F2 */
+ S5K4ECGX_REG_WRITE(0x700041F4, 0x2698), /* 700041F4 */
+ S5K4ECGX_REG_WRITE(0x700041F6, 0x7000), /* 700041F6 */
+ S5K4ECGX_REG_WRITE(0x700041F8, 0x2BB8), /* 700041F8 */
+ S5K4ECGX_REG_WRITE(0x700041FA, 0x7000), /* 700041FA */
+ S5K4ECGX_REG_WRITE(0x700041FC, 0x2998), /* 700041FC */
+ S5K4ECGX_REG_WRITE(0x700041FE, 0x7000), /* 700041FE */
+ S5K4ECGX_REG_WRITE(0x70004200, 0x4778), /* 70004200 */
+ S5K4ECGX_REG_WRITE(0x70004202, 0x46C0), /* 70004202 */
+ S5K4ECGX_REG_WRITE(0x70004204, 0xC000), /* 70004204 */
+ S5K4ECGX_REG_WRITE(0x70004206, 0xE59F), /* 70004206 */
+ S5K4ECGX_REG_WRITE(0x70004208, 0xFF1C), /* 70004208 */
+ S5K4ECGX_REG_WRITE(0x7000420A, 0xE12F), /* 7000420A */
+ S5K4ECGX_REG_WRITE(0x7000420C, 0x1789), /* 7000420C */
+ S5K4ECGX_REG_WRITE(0x7000420E, 0x0001), /* 7000420E */
+ S5K4ECGX_REG_WRITE(0x70004210, 0x4778), /* 70004210 */
+ S5K4ECGX_REG_WRITE(0x70004212, 0x46C0), /* 70004212 */
+ S5K4ECGX_REG_WRITE(0x70004214, 0xC000), /* 70004214 */
+ S5K4ECGX_REG_WRITE(0x70004216, 0xE59F), /* 70004216 */
+ S5K4ECGX_REG_WRITE(0x70004218, 0xFF1C), /* 70004218 */
+ S5K4ECGX_REG_WRITE(0x7000421A, 0xE12F), /* 7000421A */
+ S5K4ECGX_REG_WRITE(0x7000421C, 0x16F1), /* 7000421C */
+ S5K4ECGX_REG_WRITE(0x7000421E, 0x0001), /* 7000421E */
+ S5K4ECGX_REG_WRITE(0x70004220, 0x4778), /* 70004220 */
+ S5K4ECGX_REG_WRITE(0x70004222, 0x46C0), /* 70004222 */
+ S5K4ECGX_REG_WRITE(0x70004224, 0xC000), /* 70004224 */
+ S5K4ECGX_REG_WRITE(0x70004226, 0xE59F), /* 70004226 */
+ S5K4ECGX_REG_WRITE(0x70004228, 0xFF1C), /* 70004228 */
+ S5K4ECGX_REG_WRITE(0x7000422A, 0xE12F), /* 7000422A */
+ S5K4ECGX_REG_WRITE(0x7000422C, 0xC3B1), /* 7000422C */
+ S5K4ECGX_REG_WRITE(0x7000422E, 0x0000), /* 7000422E */
+ S5K4ECGX_REG_WRITE(0x70004230, 0x4778), /* 70004230 */
+ S5K4ECGX_REG_WRITE(0x70004232, 0x46C0), /* 70004232 */
+ S5K4ECGX_REG_WRITE(0x70004234, 0xC000), /* 70004234 */
+ S5K4ECGX_REG_WRITE(0x70004236, 0xE59F), /* 70004236 */
+ S5K4ECGX_REG_WRITE(0x70004238, 0xFF1C), /* 70004238 */
+ S5K4ECGX_REG_WRITE(0x7000423A, 0xE12F), /* 7000423A */
+ S5K4ECGX_REG_WRITE(0x7000423C, 0xC36D), /* 7000423C */
+ S5K4ECGX_REG_WRITE(0x7000423E, 0x0000), /* 7000423E */
+ S5K4ECGX_REG_WRITE(0x70004240, 0x4778), /* 70004240 */
+ S5K4ECGX_REG_WRITE(0x70004242, 0x46C0), /* 70004242 */
+ S5K4ECGX_REG_WRITE(0x70004244, 0xC000), /* 70004244 */
+ S5K4ECGX_REG_WRITE(0x70004246, 0xE59F), /* 70004246 */
+ S5K4ECGX_REG_WRITE(0x70004248, 0xFF1C), /* 70004248 */
+ S5K4ECGX_REG_WRITE(0x7000424A, 0xE12F), /* 7000424A */
+ S5K4ECGX_REG_WRITE(0x7000424C, 0xF6D7), /* 7000424C */
+ S5K4ECGX_REG_WRITE(0x7000424E, 0x0000), /* 7000424E */
+ S5K4ECGX_REG_WRITE(0x70004250, 0x4778), /* 70004250 */
+ S5K4ECGX_REG_WRITE(0x70004252, 0x46C0), /* 70004252 */
+ S5K4ECGX_REG_WRITE(0x70004254, 0xC000), /* 70004254 */
+ S5K4ECGX_REG_WRITE(0x70004256, 0xE59F), /* 70004256 */
+ S5K4ECGX_REG_WRITE(0x70004258, 0xFF1C), /* 70004258 */
+ S5K4ECGX_REG_WRITE(0x7000425A, 0xE12F), /* 7000425A */
+ S5K4ECGX_REG_WRITE(0x7000425C, 0xB49D), /* 7000425C */
+ S5K4ECGX_REG_WRITE(0x7000425E, 0x0000), /* 7000425E */
+ S5K4ECGX_REG_WRITE(0x70004260, 0x4778), /* 70004260 */
+ S5K4ECGX_REG_WRITE(0x70004262, 0x46C0), /* 70004262 */
+ S5K4ECGX_REG_WRITE(0x70004264, 0xC000), /* 70004264 */
+ S5K4ECGX_REG_WRITE(0x70004266, 0xE59F), /* 70004266 */
+ S5K4ECGX_REG_WRITE(0x70004268, 0xFF1C), /* 70004268 */
+ S5K4ECGX_REG_WRITE(0x7000426A, 0xE12F), /* 7000426A */
+ S5K4ECGX_REG_WRITE(0x7000426C, 0x7EDF), /* 7000426C */
+ S5K4ECGX_REG_WRITE(0x7000426E, 0x0000), /* 7000426E */
+ S5K4ECGX_REG_WRITE(0x70004270, 0x4778), /* 70004270 */
+ S5K4ECGX_REG_WRITE(0x70004272, 0x46C0), /* 70004272 */
+ S5K4ECGX_REG_WRITE(0x70004274, 0xC000), /* 70004274 */
+ S5K4ECGX_REG_WRITE(0x70004276, 0xE59F), /* 70004276 */
+ S5K4ECGX_REG_WRITE(0x70004278, 0xFF1C), /* 70004278 */
+ S5K4ECGX_REG_WRITE(0x7000427A, 0xE12F), /* 7000427A */
+ S5K4ECGX_REG_WRITE(0x7000427C, 0x448D), /* 7000427C */
+ S5K4ECGX_REG_WRITE(0x7000427E, 0x0000), /* 7000427E */
+ S5K4ECGX_REG_WRITE(0x70004280, 0x4778), /* 70004280 */
+ S5K4ECGX_REG_WRITE(0x70004282, 0x46C0), /* 70004282 */
+ S5K4ECGX_REG_WRITE(0x70004284, 0xF004), /* 70004284 */
+ S5K4ECGX_REG_WRITE(0x70004286, 0xE51F), /* 70004286 */
+ S5K4ECGX_REG_WRITE(0x70004288, 0x29EC), /* 70004288 */
+ S5K4ECGX_REG_WRITE(0x7000428A, 0x0001), /* 7000428A */
+ S5K4ECGX_REG_WRITE(0x7000428C, 0x4778), /* 7000428C */
+ S5K4ECGX_REG_WRITE(0x7000428E, 0x46C0), /* 7000428E */
+ S5K4ECGX_REG_WRITE(0x70004290, 0xC000), /* 70004290 */
+ S5K4ECGX_REG_WRITE(0x70004292, 0xE59F), /* 70004292 */
+ S5K4ECGX_REG_WRITE(0x70004294, 0xFF1C), /* 70004294 */
+ S5K4ECGX_REG_WRITE(0x70004296, 0xE12F), /* 70004296 */
+ S5K4ECGX_REG_WRITE(0x70004298, 0x2EF1), /* 70004298 */
+ S5K4ECGX_REG_WRITE(0x7000429A, 0x0000), /* 7000429A */
+ S5K4ECGX_REG_WRITE(0x7000429C, 0x4778), /* 7000429C */
+ S5K4ECGX_REG_WRITE(0x7000429E, 0x46C0), /* 7000429E */
+ S5K4ECGX_REG_WRITE(0x700042A0, 0xC000), /* 700042A0 */
+ S5K4ECGX_REG_WRITE(0x700042A2, 0xE59F), /* 700042A2 */
+ S5K4ECGX_REG_WRITE(0x700042A4, 0xFF1C), /* 700042A4 */
+ S5K4ECGX_REG_WRITE(0x700042A6, 0xE12F), /* 700042A6 */
+ S5K4ECGX_REG_WRITE(0x700042A8, 0xEE03), /* 700042A8 */
+ S5K4ECGX_REG_WRITE(0x700042AA, 0x0000), /* 700042AA */
+ S5K4ECGX_REG_WRITE(0x700042AC, 0x4778), /* 700042AC */
+ S5K4ECGX_REG_WRITE(0x700042AE, 0x46C0), /* 700042AE */
+ S5K4ECGX_REG_WRITE(0x700042B0, 0xC000), /* 700042B0 */
+ S5K4ECGX_REG_WRITE(0x700042B2, 0xE59F), /* 700042B2 */
+ S5K4ECGX_REG_WRITE(0x700042B4, 0xFF1C), /* 700042B4 */
+ S5K4ECGX_REG_WRITE(0x700042B6, 0xE12F), /* 700042B6 */
+ S5K4ECGX_REG_WRITE(0x700042B8, 0xA58B), /* 700042B8 */
+ S5K4ECGX_REG_WRITE(0x700042BA, 0x0000), /* 700042BA */
+ S5K4ECGX_REG_WRITE(0x700042BC, 0x4778), /* 700042BC */
+ S5K4ECGX_REG_WRITE(0x700042BE, 0x46C0), /* 700042BE */
+ S5K4ECGX_REG_WRITE(0x700042C0, 0xC000), /* 700042C0 */
+ S5K4ECGX_REG_WRITE(0x700042C2, 0xE59F), /* 700042C2 */
+ S5K4ECGX_REG_WRITE(0x700042C4, 0xFF1C), /* 700042C4 */
+ S5K4ECGX_REG_WRITE(0x700042C6, 0xE12F), /* 700042C6 */
+ S5K4ECGX_REG_WRITE(0x700042C8, 0x7C49), /* 700042C8 */
+ S5K4ECGX_REG_WRITE(0x700042CA, 0x0000), /* 700042CA */
+ S5K4ECGX_REG_WRITE(0x700042CC, 0x4778), /* 700042CC */
+ S5K4ECGX_REG_WRITE(0x700042CE, 0x46C0), /* 700042CE */
+ S5K4ECGX_REG_WRITE(0x700042D0, 0xC000), /* 700042D0 */
+ S5K4ECGX_REG_WRITE(0x700042D2, 0xE59F), /* 700042D2 */
+ S5K4ECGX_REG_WRITE(0x700042D4, 0xFF1C), /* 700042D4 */
+ S5K4ECGX_REG_WRITE(0x700042D6, 0xE12F), /* 700042D6 */
+ S5K4ECGX_REG_WRITE(0x700042D8, 0x7C63), /* 700042D8 */
+ S5K4ECGX_REG_WRITE(0x700042DA, 0x0000), /* 700042DA */
+ S5K4ECGX_REG_WRITE(0x700042DC, 0x4778), /* 700042DC */
+ S5K4ECGX_REG_WRITE(0x700042DE, 0x46C0), /* 700042DE */
+ S5K4ECGX_REG_WRITE(0x700042E0, 0xC000), /* 700042E0 */
+ S5K4ECGX_REG_WRITE(0x700042E2, 0xE59F), /* 700042E2 */
+ S5K4ECGX_REG_WRITE(0x700042E4, 0xFF1C), /* 700042E4 */
+ S5K4ECGX_REG_WRITE(0x700042E6, 0xE12F), /* 700042E6 */
+ S5K4ECGX_REG_WRITE(0x700042E8, 0x2DB7), /* 700042E8 */
+ S5K4ECGX_REG_WRITE(0x700042EA, 0x0000), /* 700042EA */
+ S5K4ECGX_REG_WRITE(0x700042EC, 0x4778), /* 700042EC */
+ S5K4ECGX_REG_WRITE(0x700042EE, 0x46C0), /* 700042EE */
+ S5K4ECGX_REG_WRITE(0x700042F0, 0xC000), /* 700042F0 */
+ S5K4ECGX_REG_WRITE(0x700042F2, 0xE59F), /* 700042F2 */
+ S5K4ECGX_REG_WRITE(0x700042F4, 0xFF1C), /* 700042F4 */
+ S5K4ECGX_REG_WRITE(0x700042F6, 0xE12F), /* 700042F6 */
+ S5K4ECGX_REG_WRITE(0x700042F8, 0xEB3D), /* 700042F8 */
+ S5K4ECGX_REG_WRITE(0x700042FA, 0x0000), /* 700042FA */
+ S5K4ECGX_REG_WRITE(0x700042FC, 0x4778), /* 700042FC */
+ S5K4ECGX_REG_WRITE(0x700042FE, 0x46C0), /* 700042FE */
+ S5K4ECGX_REG_WRITE(0x70004300, 0xC000), /* 70004300 */
+ S5K4ECGX_REG_WRITE(0x70004302, 0xE59F), /* 70004302 */
+ S5K4ECGX_REG_WRITE(0x70004304, 0xFF1C), /* 70004304 */
+ S5K4ECGX_REG_WRITE(0x70004306, 0xE12F), /* 70004306 */
+ S5K4ECGX_REG_WRITE(0x70004308, 0xF061), /* 70004308 */
+ S5K4ECGX_REG_WRITE(0x7000430A, 0x0000), /* 7000430A */
+ S5K4ECGX_REG_WRITE(0x7000430C, 0x4778), /* 7000430C */
+ S5K4ECGX_REG_WRITE(0x7000430E, 0x46C0), /* 7000430E */
+ S5K4ECGX_REG_WRITE(0x70004310, 0xC000), /* 70004310 */
+ S5K4ECGX_REG_WRITE(0x70004312, 0xE59F), /* 70004312 */
+ S5K4ECGX_REG_WRITE(0x70004314, 0xFF1C), /* 70004314 */
+ S5K4ECGX_REG_WRITE(0x70004316, 0xE12F), /* 70004316 */
+ S5K4ECGX_REG_WRITE(0x70004318, 0xF0EF), /* 70004318 */
+ S5K4ECGX_REG_WRITE(0x7000431A, 0x0000), /* 7000431A */
+ S5K4ECGX_REG_WRITE(0x7000431C, 0x4778), /* 7000431C */
+ S5K4ECGX_REG_WRITE(0x7000431E, 0x46C0), /* 7000431E */
+ S5K4ECGX_REG_WRITE(0x70004320, 0xF004), /* 70004320 */
+ S5K4ECGX_REG_WRITE(0x70004322, 0xE51F), /* 70004322 */
+ S5K4ECGX_REG_WRITE(0x70004324, 0x2824), /* 70004324 */
+ S5K4ECGX_REG_WRITE(0x70004326, 0x0001), /* 70004326 */
+ S5K4ECGX_REG_WRITE(0x70004328, 0x4778), /* 70004328 */
+ S5K4ECGX_REG_WRITE(0x7000432A, 0x46C0), /* 7000432A */
+ S5K4ECGX_REG_WRITE(0x7000432C, 0xC000), /* 7000432C */
+ S5K4ECGX_REG_WRITE(0x7000432E, 0xE59F), /* 7000432E */
+ S5K4ECGX_REG_WRITE(0x70004330, 0xFF1C), /* 70004330 */
+ S5K4ECGX_REG_WRITE(0x70004332, 0xE12F), /* 70004332 */
+ S5K4ECGX_REG_WRITE(0x70004334, 0x8EDD), /* 70004334 */
+ S5K4ECGX_REG_WRITE(0x70004336, 0x0000), /* 70004336 */
+ S5K4ECGX_REG_WRITE(0x70004338, 0x4778), /* 70004338 */
+ S5K4ECGX_REG_WRITE(0x7000433A, 0x46C0), /* 7000433A */
+ S5K4ECGX_REG_WRITE(0x7000433C, 0xC000), /* 7000433C */
+ S5K4ECGX_REG_WRITE(0x7000433E, 0xE59F), /* 7000433E */
+ S5K4ECGX_REG_WRITE(0x70004340, 0xFF1C), /* 70004340 */
+ S5K4ECGX_REG_WRITE(0x70004342, 0xE12F), /* 70004342 */
+ S5K4ECGX_REG_WRITE(0x70004344, 0x8DCB), /* 70004344 */
+ S5K4ECGX_REG_WRITE(0x70004346, 0x0000), /* 70004346 */
+ S5K4ECGX_REG_WRITE(0x70004348, 0x4778), /* 70004348 */
+ S5K4ECGX_REG_WRITE(0x7000434A, 0x46C0), /* 7000434A */
+ S5K4ECGX_REG_WRITE(0x7000434C, 0xC000), /* 7000434C */
+ S5K4ECGX_REG_WRITE(0x7000434E, 0xE59F), /* 7000434E */
+ S5K4ECGX_REG_WRITE(0x70004350, 0xFF1C), /* 70004350 */
+ S5K4ECGX_REG_WRITE(0x70004352, 0xE12F), /* 70004352 */
+ S5K4ECGX_REG_WRITE(0x70004354, 0x8E17), /* 70004354 */
+ S5K4ECGX_REG_WRITE(0x70004356, 0x0000), /* 70004356 */
+ S5K4ECGX_REG_WRITE(0x70004358, 0x4778), /* 70004358 */
+ S5K4ECGX_REG_WRITE(0x7000435A, 0x46C0), /* 7000435A */
+ S5K4ECGX_REG_WRITE(0x7000435C, 0xC000), /* 7000435C */
+ S5K4ECGX_REG_WRITE(0x7000435E, 0xE59F), /* 7000435E */
+ S5K4ECGX_REG_WRITE(0x70004360, 0xFF1C), /* 70004360 */
+ S5K4ECGX_REG_WRITE(0x70004362, 0xE12F), /* 70004362 */
+ S5K4ECGX_REG_WRITE(0x70004364, 0x98C5), /* 70004364 */
+ S5K4ECGX_REG_WRITE(0x70004366, 0x0000), /* 70004366 */
+ S5K4ECGX_REG_WRITE(0x70004368, 0x4778), /* 70004368 */
+ S5K4ECGX_REG_WRITE(0x7000436A, 0x46C0), /* 7000436A */
+ S5K4ECGX_REG_WRITE(0x7000436C, 0xC000), /* 7000436C */
+ S5K4ECGX_REG_WRITE(0x7000436E, 0xE59F), /* 7000436E */
+ S5K4ECGX_REG_WRITE(0x70004370, 0xFF1C), /* 70004370 */
+ S5K4ECGX_REG_WRITE(0x70004372, 0xE12F), /* 70004372 */
+ S5K4ECGX_REG_WRITE(0x70004374, 0x7C7D), /* 70004374 */
+ S5K4ECGX_REG_WRITE(0x70004376, 0x0000), /* 70004376 */
+ S5K4ECGX_REG_WRITE(0x70004378, 0x4778), /* 70004378 */
+ S5K4ECGX_REG_WRITE(0x7000437A, 0x46C0), /* 7000437A */
+ S5K4ECGX_REG_WRITE(0x7000437C, 0xC000), /* 7000437C */
+ S5K4ECGX_REG_WRITE(0x7000437E, 0xE59F), /* 7000437E */
+ S5K4ECGX_REG_WRITE(0x70004380, 0xFF1C), /* 70004380 */
+ S5K4ECGX_REG_WRITE(0x70004382, 0xE12F), /* 70004382 */
+ S5K4ECGX_REG_WRITE(0x70004384, 0x7E31), /* 70004384 */
+ S5K4ECGX_REG_WRITE(0x70004386, 0x0000), /* 70004386 */
+ S5K4ECGX_REG_WRITE(0x70004388, 0x4778), /* 70004388 */
+ S5K4ECGX_REG_WRITE(0x7000438A, 0x46C0), /* 7000438A */
+ S5K4ECGX_REG_WRITE(0x7000438C, 0xC000), /* 7000438C */
+ S5K4ECGX_REG_WRITE(0x7000438E, 0xE59F), /* 7000438E */
+ S5K4ECGX_REG_WRITE(0x70004390, 0xFF1C), /* 70004390 */
+ S5K4ECGX_REG_WRITE(0x70004392, 0xE12F), /* 70004392 */
+ S5K4ECGX_REG_WRITE(0x70004394, 0x7EAB), /* 70004394 */
+ S5K4ECGX_REG_WRITE(0x70004396, 0x0000), /* 70004396 */
+ /* End of Patch Data(Last : 70004396h) */
+ /* Total Size 2208 (08A0) */
+ /* Addr : 3AF8 , Size : 2206(89Eh) */
+
+ /* #define TNP_USER_MBCV_CONTROL */
+ /* #define TNP_4EC_MBR_TUNE */
+ /* #define TNP_4EC_FORBIDDEN_TUNE */
+ /* #define TNP_AF_FINESEARCH_DRIVEBACK */
+ /* #define TNP_FLASH_ALG */
+ /* #define TNP_GAS_ALPHA_OTP */
+ /* #define TNP_AWB_MODUL_COMP */
+ /* #define TNP_AWB_INIT_QUEUE */
+
+ /* TNP_Regs_usCintrTh 2 70004780 */
+ /* TNP_Regs_usFixedCintc 2 70004782 */
+ /* TNP_Regs_FlsWeightRIn_0_ 2 70004784 */
+ /* TNP_Regs_FlsWeightRIn_1_ 2 70004786 */
+ /* TNP_Regs_FlsWeightRIn_2_ 2 70004788 */
+ /* TNP_Regs_FlsWeightRIn_3_ 2 7000478A */
+ /* TNP_Regs_FlsWeightRIn_4_ 2 7000478C */
+ /* TNP_Regs_FlsWeightRIn_5_ 2 7000478E */
+ /* TNP_Regs_FlsWeightROut_0_ 2 70004790 */
+ /* TNP_Regs_FlsWeightROut_1_ 2 70004792 */
+ /* TNP_Regs_FlsWeightROut_2_ 2 70004794 */
+ /* TNP_Regs_FlsWeightROut_3_ 2 70004796 */
+ /* TNP_Regs_FlsWeightROut_4_ 2 70004798 */
+ /* TNP_Regs_FlsWeightROut_5_ 2 7000479A */
+
+ /* TNP_Regs_FlBRIn_0_ 2 7000479C */
+ /* TNP_Regs_FlBRIn_1_ 2 7000479E */
+ /* TNP_Regs_FlBRIn_2_ 2 700047A0 */
+ /* TNP_Regs_FlBRInOut_0_ 2 700047A2 */
+ /* TNP_Regs_FlBRInOut_1_ 2 700047A4 */
+ /* TNP_Regs_FlBRInOut_2_ 2 700047A6 */
+
+ S5K4ECGX_REG_WRITE(0xD0001000, 0x0001),
+
+ /* AF setting */
+ S5K4ECGX_REG_WRITE(0x700001FC, 0x0001), /* #REG_TC_IPRM_LedGpio */
+ S5K4ECGX_REG_WRITE(0x70001720, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700001FE, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000200, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000204, 0x0061),
+ S5K4ECGX_REG_WRITE(0x7000020C, 0x2F0C),
+ S5K4ECGX_REG_WRITE(0x7000020E, 0x0190),
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0238),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0074),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0132),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000070E, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000071E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000163C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001648, 0x9002),
+ S5K4ECGX_REG_WRITE(0x70001652, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70001654, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700015E0, 0x0902),
+
+ S5K4ECGX_REG_WRITE(0x7000164C, 0x0003),
+ S5K4ECGX_REG_WRITE(0x7000163E, 0x00D5),
+ S5K4ECGX_REG_WRITE(0x70001640, 0x0098),
+ S5K4ECGX_REG_WRITE(0x700015D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700015D6, 0xD000),
+ S5K4ECGX_REG_WRITE(0x7000169A, 0xFF95),
+ S5K4ECGX_REG_WRITE(0x7000166A, 0x0280),
+ S5K4ECGX_REG_WRITE(0x70001676, 0x03A0),
+ S5K4ECGX_REG_WRITE(0x70001678, 0x0320),
+ S5K4ECGX_REG_WRITE(0x700016BC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700016E0, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700016D4, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70001656, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700015E6, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x0018), /* #af_pos_usTableLastInd */
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0066),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x006C),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x0072),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70001606, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001608, 0x0084),
+ S5K4ECGX_REG_WRITE(0x7000160A, 0x008A),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x0090),
+ S5K4ECGX_REG_WRITE(0x7000160E, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001610, 0x009C),
+ S5K4ECGX_REG_WRITE(0x70001612, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001614, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x70001616, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x70001618, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x7000161A, 0x00BA), /* #af_pos_usTable_24_ */
+
+ S5K4ECGX_REG_WRITE(0x70001722, 0x8000),
+ S5K4ECGX_REG_WRITE(0x70001724, 0x0006),
+ S5K4ECGX_REG_WRITE(0x70001726, 0x3FF0),
+ S5K4ECGX_REG_WRITE(0x70001728, 0x03E8),
+ S5K4ECGX_REG_WRITE(0x7000172A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000172C, 0x0020),
+ S5K4ECGX_REG_WRITE(0x7000172E, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70001730, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70001732, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70001734, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70001736, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70001738, 0x00E0),
+
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0003), /* #REG_TC_AF_AfCmd */
+
+ /* GAS TBL setting */
+ S5K4ECGX_REG_WRITE(0x700008B4, 0x0001), /* #wbt_bUseOutdoorASH */
+
+ /* TVAR_ash_AwbAshCord, Refer Mon_AWB_RotGain */
+ S5K4ECGX_REG_WRITE(0x700008BC, 0x00C0), /* #TVAR_ash_AwbAshCord_0_ 2300K */
+ S5K4ECGX_REG_WRITE(0x700008BE, 0x00DF), /* #TVAR_ash_AwbAshCord_1_ 2750K */
+ S5K4ECGX_REG_WRITE(0x700008C0, 0x0100), /* #TVAR_ash_AwbAshCord_2_ 3300K */
+ S5K4ECGX_REG_WRITE(0x700008C2, 0x0125), /* #TVAR_ash_AwbAshCord_3_ 4150K */
+ S5K4ECGX_REG_WRITE(0x700008C4, 0x015F), /* #TVAR_ash_AwbAshCord_4_ 5250K */
+ S5K4ECGX_REG_WRITE(0x700008C6, 0x017C), /* #TVAR_ash_AwbAshCord_5_ 6400K */
+ S5K4ECGX_REG_WRITE(0x700008C8, 0x0194), /* #TVAR_ash_AwbAshCord_6_ 7500K */
+
+ S5K4ECGX_REG_WRITE(0x700008F6, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F8, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FA, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FC, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x700008FE, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000900, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000902, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000904, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x70000906, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000908, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090C, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x7000090E, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000910, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000912, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000914, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x70000916, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000918, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000091A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000091C, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x7000091E, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000920, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000922, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000924, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x70000926, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000928, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000092A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000092C, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x7000092E, 0x4500),
+ S5K4ECGX_REG_WRITE(0x70000930, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000932, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000934, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x700008F4, 0x0001), /* #ash_bUseGasAlpha */
+
+ /* AE START */
+
+ /* AE WEIGHT */
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0102),
+
+ S5K4ECGX_REG_WRITE(0x70001484, 0x003C), /* #TVAR_ae_BrAve */
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x000F), /* #ae_StatMode */
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000), /* #lt_uMaxExp1 */
+ S5K4ECGX_REG_WRITE(0x70000590, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0000), /* #lt_uMaxExp2 */
+ S5K4ECGX_REG_WRITE(0x70000594, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0000), /* #lt_uCapMaxExp1 */
+ S5K4ECGX_REG_WRITE(0x70000598, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000059A, 0x0000), /* #lt_uCapMaxExp2 */
+ S5K4ECGX_REG_WRITE(0x7000059C, 0x0470), /* #lt_uMaxAnGain1 */
+ S5K4ECGX_REG_WRITE(0x7000059E, 0x0C00), /* #lt_uMaxAnGain2 */
+ S5K4ECGX_REG_WRITE(0x700005A0, 0x0100), /* #lt_uMaxDigGain */
+ S5K4ECGX_REG_WRITE(0x700005A2, 0x1000), /* #lt_uMaxTotGain */
+
+ S5K4ECGX_REG_WRITE(0x70000544, 0x0111), /* #lt_uLimitHigh */
+ S5K4ECGX_REG_WRITE(0x70000546, 0x00EF), /* #lt_uLimitLow */
+
+ S5K4ECGX_REG_WRITE(0x70000F2A, 0x0001), /* #AFC_Default60Hz */
+ S5K4ECGX_REG_WRITE(0x70000F30, 0x0002), /* #AFC_D_ConvAccelerPower */
+
+ S5K4ECGX_REG_WRITE(0x70000588, 0x0000), /* AE Speed-up */
+
+ S5K4ECGX_REG_WRITE(0x70000600, 0xD000),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0C00), /* #lt_ExpGain_ExpCurveGainMaxStr */
+ S5K4ECGX_REG_WRITE(0x7000060E, 0x0100), /* #lt_ExpGain_ExpCurveGainMaxStr_0__uMaxDigGain */
+ S5K4ECGX_REG_WRITE(0x70000610, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000612, 0x0000), /* #lt_ExpGain_ExpCurveGainMaxStr_0__ulExpIn_0_ */
+ S5K4ECGX_REG_WRITE(0x70000614, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x70000616, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000618, 0x0D04),
+ S5K4ECGX_REG_WRITE(0x7000061A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000061C, 0x4008),
+ S5K4ECGX_REG_WRITE(0x7000061E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000620, 0x7000),
+ S5K4ECGX_REG_WRITE(0x70000622, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000624, 0x9C00),
+ S5K4ECGX_REG_WRITE(0x70000626, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000628, 0xAD00),
+ S5K4ECGX_REG_WRITE(0x7000062A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000062C, 0xF1D4),
+ S5K4ECGX_REG_WRITE(0x7000062E, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70000630, 0xDC00),
+ S5K4ECGX_REG_WRITE(0x70000632, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000634, 0xDC00),
+ S5K4ECGX_REG_WRITE(0x70000636, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000638, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000), /* #lt_ExpGain_ExpCurveGainMaxStr_0__ulExpOut_0_ */
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x0D05),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x3408),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0x8214),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000654, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000658, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000660, 0x0650), /* #lt_ExpGain_ExpCurveGainMaxStr_1_ */
+ S5K4ECGX_REG_WRITE(0x70000662, 0x0100), /* #lt_ExpGain_ExpCurveGainMaxStr_1__uMaxDigGain */
+
+ S5K4ECGX_REG_WRITE(0x700006B8, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x000C), /* #lt_uMaxLei */
+
+ S5K4ECGX_REG_WRITE(0x700005D0, 0x0000), /* #lt_mbr_Peak_behind */
+
+ /* AWB init Start point */
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0470), /* 0400 */
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0400), /* 0428 */
+ S5K4ECGX_REG_WRITE(0x70001462, 0x09F0), /* 9B3 */
+
+ /* AWB Init */
+ /* White Locus */
+ S5K4ECGX_REG_WRITE(0x700011F0, 0x012C), /* #awbb_IntcR */
+ S5K4ECGX_REG_WRITE(0x700011F2, 0x0121), /* #awbb_IntcB */
+
+ /* IndoorZone */
+ S5K4ECGX_REG_WRITE(0x7000101C, 0x039A),
+ S5K4ECGX_REG_WRITE(0x7000101E, 0x03E8),
+ S5K4ECGX_REG_WRITE(0x70001020, 0x033C),
+ S5K4ECGX_REG_WRITE(0x70001022, 0x03AE),
+ S5K4ECGX_REG_WRITE(0x70001024, 0x02DE),
+ S5K4ECGX_REG_WRITE(0x70001026, 0x0376),
+ S5K4ECGX_REG_WRITE(0x70001028, 0x029C),
+ S5K4ECGX_REG_WRITE(0x7000102A, 0x033C),
+ S5K4ECGX_REG_WRITE(0x7000102C, 0x027E),
+ S5K4ECGX_REG_WRITE(0x7000102E, 0x0312),
+ S5K4ECGX_REG_WRITE(0x70001030, 0x025E),
+ S5K4ECGX_REG_WRITE(0x70001032, 0x02F6),
+ S5K4ECGX_REG_WRITE(0x70001034, 0x023E),
+ S5K4ECGX_REG_WRITE(0x70001036, 0x02DA),
+ S5K4ECGX_REG_WRITE(0x70001038, 0x022A),
+ S5K4ECGX_REG_WRITE(0x7000103A, 0x02BC),
+ S5K4ECGX_REG_WRITE(0x7000103C, 0x0214),
+ S5K4ECGX_REG_WRITE(0x7000103E, 0x02A2),
+ S5K4ECGX_REG_WRITE(0x70001040, 0x01FE),
+ S5K4ECGX_REG_WRITE(0x70001042, 0x0292),
+ S5K4ECGX_REG_WRITE(0x70001044, 0x01F0),
+ S5K4ECGX_REG_WRITE(0x70001046, 0x0284),
+ S5K4ECGX_REG_WRITE(0x70001048, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x7000104A, 0x0276),
+ S5K4ECGX_REG_WRITE(0x7000104C, 0x01D2),
+ S5K4ECGX_REG_WRITE(0x7000104E, 0x0266),
+ S5K4ECGX_REG_WRITE(0x70001050, 0x01C4),
+ S5K4ECGX_REG_WRITE(0x70001052, 0x0258),
+ S5K4ECGX_REG_WRITE(0x70001054, 0x01D8),
+ S5K4ECGX_REG_WRITE(0x70001056, 0x0216),
+ S5K4ECGX_REG_WRITE(0x70001058, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001060, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001062, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001064, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001066, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001068, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000106A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000106C, 0x0005), /* #awbb_IndoorGrZones_m_GridStep */
+ S5K4ECGX_REG_WRITE(0x70001070, 0x000F), /* #awbb_IndoorGrZones_ZInfo_m_GridSz */
+ S5K4ECGX_REG_WRITE(0x70001074, 0x013C), /* #awbb_IndoorGrZones_m_Boffs */
+
+ /* Outdoor Zone */
+ S5K4ECGX_REG_WRITE(0x70001078, 0x0254),
+ S5K4ECGX_REG_WRITE(0x7000107A, 0x0296),
+ S5K4ECGX_REG_WRITE(0x7000107C, 0x0246),
+ S5K4ECGX_REG_WRITE(0x7000107E, 0x02B4),
+ S5K4ECGX_REG_WRITE(0x70001080, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70001082, 0x02B8),
+ S5K4ECGX_REG_WRITE(0x70001084, 0x022A),
+ S5K4ECGX_REG_WRITE(0x70001086, 0x02B0),
+ S5K4ECGX_REG_WRITE(0x70001088, 0x021C),
+ S5K4ECGX_REG_WRITE(0x7000108A, 0x02A6),
+ S5K4ECGX_REG_WRITE(0x7000108C, 0x021A),
+ S5K4ECGX_REG_WRITE(0x7000108E, 0x029C),
+ S5K4ECGX_REG_WRITE(0x70001090, 0x021A),
+ S5K4ECGX_REG_WRITE(0x70001092, 0x0292),
+ S5K4ECGX_REG_WRITE(0x70001094, 0x0220),
+ S5K4ECGX_REG_WRITE(0x70001096, 0x0288),
+ S5K4ECGX_REG_WRITE(0x70001098, 0x0226),
+ S5K4ECGX_REG_WRITE(0x7000109A, 0x027E),
+ S5K4ECGX_REG_WRITE(0x7000109C, 0x0244),
+ S5K4ECGX_REG_WRITE(0x7000109E, 0x0274),
+ S5K4ECGX_REG_WRITE(0x700010A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010A6, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700010A8, 0x0004), /* #awbb_OutdoorGrZones_m_GridStep */
+ S5K4ECGX_REG_WRITE(0x700010AC, 0x000A), /* #awbb_OutdoorGrZones_ZInfo_m_GridSz */
+ S5K4ECGX_REG_WRITE(0x700010B0, 0x01EE), /* #awbb_OutdoorGrZones_m_Boffs */
+
+ /* LowBR Zone */
+ S5K4ECGX_REG_WRITE(0x700010B4, 0x0350),
+ S5K4ECGX_REG_WRITE(0x700010B6, 0x0422),
+ S5K4ECGX_REG_WRITE(0x700010B8, 0x02C4),
+ S5K4ECGX_REG_WRITE(0x700010BA, 0x0452),
+ S5K4ECGX_REG_WRITE(0x700010BC, 0x0278),
+ S5K4ECGX_REG_WRITE(0x700010BE, 0x041C),
+ S5K4ECGX_REG_WRITE(0x700010C0, 0x0230),
+ S5K4ECGX_REG_WRITE(0x700010C2, 0x03EE),
+ S5K4ECGX_REG_WRITE(0x700010C4, 0x01F0),
+ S5K4ECGX_REG_WRITE(0x700010C6, 0x0392),
+ S5K4ECGX_REG_WRITE(0x700010C8, 0x01C0),
+ S5K4ECGX_REG_WRITE(0x700010CA, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700010CC, 0x0194),
+ S5K4ECGX_REG_WRITE(0x700010CE, 0x0302),
+ S5K4ECGX_REG_WRITE(0x700010D0, 0x016E),
+ S5K4ECGX_REG_WRITE(0x700010D2, 0x02C2),
+ S5K4ECGX_REG_WRITE(0x700010D4, 0x0148),
+ S5K4ECGX_REG_WRITE(0x700010D6, 0x0286),
+ S5K4ECGX_REG_WRITE(0x700010D8, 0x018A),
+ S5K4ECGX_REG_WRITE(0x700010DA, 0x0242),
+ S5K4ECGX_REG_WRITE(0x700010DC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010DE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010E2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700010E4, 0x0006), /* #awbb_LowBrGrZones_m_GridStep */
+ S5K4ECGX_REG_WRITE(0x700010E8, 0x000A), /* #awbb_LowBrGrZones_ZInfo_m_GridSz */
+ S5K4ECGX_REG_WRITE(0x700010EC, 0x0106), /* #awbb_LowBrGrZones_m_Boffs */
+
+ /* LowTemp Zone */
+ S5K4ECGX_REG_WRITE(0x700010F0, 0x0380),
+ S5K4ECGX_REG_WRITE(0x700010F2, 0x0000), /* #awbb_CrclLowT_R_c */
+ S5K4ECGX_REG_WRITE(0x700010F4, 0x0168),
+ S5K4ECGX_REG_WRITE(0x700010F6, 0x0000), /* #awbb_CrclLowT_B_c */
+ S5K4ECGX_REG_WRITE(0x700010F8, 0x2D90),
+ S5K4ECGX_REG_WRITE(0x700010FA, 0x0000), /* #awbb_CrclLowT_Rad_c */
+
+ /* AWB Convergence Speed */
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0190),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x00A0),
+
+ S5K4ECGX_REG_WRITE(0x70001228, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000122C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000122A, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x7000120A, 0x05D5), /* #awbb_MvEq_RBthresh */
+ S5K4ECGX_REG_WRITE(0x7000120E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001210, 0x0771),
+ S5K4ECGX_REG_WRITE(0x70001212, 0x03A4),
+ S5K4ECGX_REG_WRITE(0x70001214, 0x0036),
+ S5K4ECGX_REG_WRITE(0x70001216, 0x002A),
+
+ S5K4ECGX_REG_WRITE(0x70001278, 0xFEF7),
+ S5K4ECGX_REG_WRITE(0x7000127A, 0x0021),
+ S5K4ECGX_REG_WRITE(0x7000127C, 0x0E74),
+ S5K4ECGX_REG_WRITE(0x7000127E, 0x0E74),
+ S5K4ECGX_REG_WRITE(0x70001280, 0x018F),
+ S5K4ECGX_REG_WRITE(0x70001282, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001284, 0x000E),
+ S5K4ECGX_REG_WRITE(0x70001224, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70001226, 0x001E),
+ S5K4ECGX_REG_WRITE(0x70001228, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000122A, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000122C, 0x0002), /* awbb_YThreshLow_Low */
+ S5K4ECGX_REG_WRITE(0x70002BA4, 0x0006), /* #Mon_AWB_ByPassMode */
+
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0002), /* #awbb_GridEnable */
+
+ /* Grid */
+ S5K4ECGX_REG_WRITE(0x70001434, 0x0300), /* awbb_GridConst_1 */
+ S5K4ECGX_REG_WRITE(0x70001436, 0x036E), /* awbb_GridConst_1_1_ */
+ S5K4ECGX_REG_WRITE(0x70001438, 0x03C2), /* awbb_GridConst_1_2_ */
+ S5K4ECGX_REG_WRITE(0x7000143A, 0x1074), /* awbb_GridConst_2 */
+ S5K4ECGX_REG_WRITE(0x7000143C, 0x10C2), /* awbb_GridConst_2_1_ */
+ S5K4ECGX_REG_WRITE(0x7000143E, 0x1104), /* awbb_GridConst_2_2_ */
+ S5K4ECGX_REG_WRITE(0x70001440, 0x1142), /* awbb_GridConst_2_3_ */
+ S5K4ECGX_REG_WRITE(0x70001442, 0x11BB), /* awbb_GridConst_2_4_ */
+ S5K4ECGX_REG_WRITE(0x70001444, 0x123B), /* awbb_GridConst_2_5_ */
+ S5K4ECGX_REG_WRITE(0x70001446, 0x00AB), /* awbb_GridCoeff_R_1 */
+ S5K4ECGX_REG_WRITE(0x70001448, 0x00BF), /* awbb_GridCoeff_B_1 */
+ S5K4ECGX_REG_WRITE(0x7000144A, 0x00D2), /* awbb_GridCoeff_R_2 */
+ S5K4ECGX_REG_WRITE(0x7000144C, 0x0093), /* awbb_GridCoeff_B_2 */
+
+ /* Indoor Grid Offset */
+ S5K4ECGX_REG_WRITE(0x700013A4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013A6, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013A8, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013AC, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700013AE, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700013B0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013B2, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013B4, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013B6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013B8, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700013BA, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700013BC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013BE, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013C0, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013C4, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700013C6, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700013C8, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013CA, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013CC, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013CE, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013D0, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013D2, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013D4, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013D6, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013D8, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013DA, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013DC, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013DE, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013E0, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013E2, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700013E4, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013E6, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x700013E8, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013EA, 0xFFB0),
+
+ /* Outdoor Grid Offset */
+ S5K4ECGX_REG_WRITE(0x700013EC, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013EE, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013F0, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013F2, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013F6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013F8, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x700013FA, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013FC, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x700013FE, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x70001400, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001402, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001404, 0xFFB0),
+ S5K4ECGX_REG_WRITE(0x70001406, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x70001408, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x7000140A, 0xFFD0),
+ S5K4ECGX_REG_WRITE(0x7000140C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000140E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001410, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001412, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x70001414, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001416, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001418, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x7000141A, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x7000141C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000141E, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x70001420, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001422, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001424, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001426, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001428, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000142A, 0xFFC8),
+ S5K4ECGX_REG_WRITE(0x7000142C, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x7000142E, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001430, 0xFFB8),
+ S5K4ECGX_REG_WRITE(0x70001432, 0xFFB8),
+
+ S5K4ECGX_REG_WRITE(0x70001208, 0x0020),
+
+ S5K4ECGX_REG_WRITE(0x7000144E, 0x0000), /* #awbb_RGainOff */
+ S5K4ECGX_REG_WRITE(0x70001450, 0x0000), /* #awbb_BGainOff */
+ S5K4ECGX_REG_WRITE(0x70001452, 0x0000), /* #awbb_GGainOff */
+
+ /* RGB Indoor Gamma */
+ S5K4ECGX_REG_WRITE(0x70000734, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000736, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000738, 0x0011),
+ S5K4ECGX_REG_WRITE(0x7000073A, 0x002D),
+ S5K4ECGX_REG_WRITE(0x7000073C, 0x006B),
+ S5K4ECGX_REG_WRITE(0x7000073E, 0x00DC),
+ S5K4ECGX_REG_WRITE(0x70000740, 0x013B),
+ S5K4ECGX_REG_WRITE(0x70000742, 0x0166),
+ S5K4ECGX_REG_WRITE(0x70000744, 0x018D),
+ S5K4ECGX_REG_WRITE(0x70000746, 0x01CD),
+ S5K4ECGX_REG_WRITE(0x70000748, 0x0204),
+ S5K4ECGX_REG_WRITE(0x7000074A, 0x0235),
+ S5K4ECGX_REG_WRITE(0x7000074C, 0x0260),
+ S5K4ECGX_REG_WRITE(0x7000074E, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70000750, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x70000752, 0x034E),
+ S5K4ECGX_REG_WRITE(0x70000754, 0x0396),
+ S5K4ECGX_REG_WRITE(0x70000756, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x70000758, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x7000075A, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x7000075C, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000075E, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000760, 0x0011),
+ S5K4ECGX_REG_WRITE(0x70000762, 0x002D),
+ S5K4ECGX_REG_WRITE(0x70000764, 0x006B),
+ S5K4ECGX_REG_WRITE(0x70000766, 0x00DC),
+ S5K4ECGX_REG_WRITE(0x70000768, 0x013B),
+ S5K4ECGX_REG_WRITE(0x7000076A, 0x0166),
+ S5K4ECGX_REG_WRITE(0x7000076C, 0x018D),
+ S5K4ECGX_REG_WRITE(0x7000076E, 0x01CD),
+ S5K4ECGX_REG_WRITE(0x70000770, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000772, 0x0235),
+ S5K4ECGX_REG_WRITE(0x70000774, 0x0260),
+ S5K4ECGX_REG_WRITE(0x70000776, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70000778, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x7000077A, 0x034E),
+ S5K4ECGX_REG_WRITE(0x7000077C, 0x0396),
+ S5K4ECGX_REG_WRITE(0x7000077E, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x70000780, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x70000782, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x70000784, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000786, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000788, 0x0011),
+ S5K4ECGX_REG_WRITE(0x7000078A, 0x002D),
+ S5K4ECGX_REG_WRITE(0x7000078C, 0x006B),
+ S5K4ECGX_REG_WRITE(0x7000078E, 0x00DC),
+ S5K4ECGX_REG_WRITE(0x70000790, 0x013B),
+ S5K4ECGX_REG_WRITE(0x70000792, 0x0166),
+ S5K4ECGX_REG_WRITE(0x70000794, 0x018D),
+ S5K4ECGX_REG_WRITE(0x70000796, 0x01CD),
+ S5K4ECGX_REG_WRITE(0x70000798, 0x0204),
+ S5K4ECGX_REG_WRITE(0x7000079A, 0x0235),
+ S5K4ECGX_REG_WRITE(0x7000079C, 0x0260),
+ S5K4ECGX_REG_WRITE(0x7000079E, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700007A0, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x700007A2, 0x034E),
+ S5K4ECGX_REG_WRITE(0x700007A4, 0x0396),
+ S5K4ECGX_REG_WRITE(0x700007A6, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x700007A8, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x700007AA, 0x03F9),
+
+ /* RGB Outdoor Gamma */
+ S5K4ECGX_REG_WRITE(0x700007AC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700007AE, 0x0007),
+ S5K4ECGX_REG_WRITE(0x700007B0, 0x0011),
+ S5K4ECGX_REG_WRITE(0x700007B2, 0x002D),
+ S5K4ECGX_REG_WRITE(0x700007B4, 0x006B),
+ S5K4ECGX_REG_WRITE(0x700007B6, 0x00DC),
+ S5K4ECGX_REG_WRITE(0x700007B8, 0x013B),
+ S5K4ECGX_REG_WRITE(0x700007BA, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700007BC, 0x018D),
+ S5K4ECGX_REG_WRITE(0x700007BE, 0x01CD),
+ S5K4ECGX_REG_WRITE(0x700007C0, 0x0204),
+ S5K4ECGX_REG_WRITE(0x700007C2, 0x0235),
+ S5K4ECGX_REG_WRITE(0x700007C4, 0x0260),
+ S5K4ECGX_REG_WRITE(0x700007C6, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700007C8, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x700007CA, 0x034E),
+ S5K4ECGX_REG_WRITE(0x700007CC, 0x0396),
+ S5K4ECGX_REG_WRITE(0x700007CE, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x700007D0, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x700007D2, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x700007D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700007D6, 0x0007),
+ S5K4ECGX_REG_WRITE(0x700007D8, 0x0011),
+ S5K4ECGX_REG_WRITE(0x700007DA, 0x002D),
+ S5K4ECGX_REG_WRITE(0x700007DC, 0x006B),
+ S5K4ECGX_REG_WRITE(0x700007DE, 0x00DC),
+ S5K4ECGX_REG_WRITE(0x700007E0, 0x013B),
+ S5K4ECGX_REG_WRITE(0x700007E2, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700007E4, 0x018D),
+ S5K4ECGX_REG_WRITE(0x700007E6, 0x01CD),
+ S5K4ECGX_REG_WRITE(0x700007E8, 0x0204),
+ S5K4ECGX_REG_WRITE(0x700007EA, 0x0235),
+ S5K4ECGX_REG_WRITE(0x700007EC, 0x0260),
+ S5K4ECGX_REG_WRITE(0x700007EE, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700007F0, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x700007F2, 0x034E),
+ S5K4ECGX_REG_WRITE(0x700007F4, 0x0396),
+ S5K4ECGX_REG_WRITE(0x700007F6, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x700007F8, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x700007FA, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x700007FC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700007FE, 0x0007),
+ S5K4ECGX_REG_WRITE(0x70000800, 0x0011),
+ S5K4ECGX_REG_WRITE(0x70000802, 0x002D),
+ S5K4ECGX_REG_WRITE(0x70000804, 0x006B),
+ S5K4ECGX_REG_WRITE(0x70000806, 0x00DC),
+ S5K4ECGX_REG_WRITE(0x70000808, 0x013B),
+ S5K4ECGX_REG_WRITE(0x7000080A, 0x0166),
+ S5K4ECGX_REG_WRITE(0x7000080C, 0x018D),
+ S5K4ECGX_REG_WRITE(0x7000080E, 0x01CD),
+ S5K4ECGX_REG_WRITE(0x70000810, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000812, 0x0235),
+ S5K4ECGX_REG_WRITE(0x70000814, 0x0260),
+ S5K4ECGX_REG_WRITE(0x70000816, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70000818, 0x02EC),
+ S5K4ECGX_REG_WRITE(0x7000081A, 0x034E),
+ S5K4ECGX_REG_WRITE(0x7000081C, 0x0396),
+ S5K4ECGX_REG_WRITE(0x7000081E, 0x03C6),
+ S5K4ECGX_REG_WRITE(0x70000820, 0x03E9),
+ S5K4ECGX_REG_WRITE(0x70000822, 0x03F9),
+
+ /* CCM */
+ S5K4ECGX_REG_WRITE(0x700008A6, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x700008A8, 0x00D0),
+ S5K4ECGX_REG_WRITE(0x700008AA, 0x00E0),
+ S5K4ECGX_REG_WRITE(0x700008AC, 0x0110),
+ S5K4ECGX_REG_WRITE(0x700008AE, 0x017C),
+ S5K4ECGX_REG_WRITE(0x700008B0, 0x0194),
+
+ S5K4ECGX_REG_WRITE(0x700008B2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000898, 0x4800),
+ S5K4ECGX_REG_WRITE(0x7000089A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x700008A0, 0x48D8),
+ S5K4ECGX_REG_WRITE(0x700008A2, 0x7000),
+
+ S5K4ECGX_REG_WRITE(0x70004800, 0x010F), /* hor */
+ S5K4ECGX_REG_WRITE(0x70004802, 0xFF90),
+ S5K4ECGX_REG_WRITE(0x70004804, 0xFF7D),
+ S5K4ECGX_REG_WRITE(0x70004806, 0xFEF1),
+ S5K4ECGX_REG_WRITE(0x70004808, 0x0137),
+ S5K4ECGX_REG_WRITE(0x7000480A, 0xFF68),
+ S5K4ECGX_REG_WRITE(0x7000480C, 0xFFEE),
+ S5K4ECGX_REG_WRITE(0x7000480E, 0xFF8A),
+ S5K4ECGX_REG_WRITE(0x70004810, 0x013A),
+ S5K4ECGX_REG_WRITE(0x70004812, 0x006E),
+ S5K4ECGX_REG_WRITE(0x70004814, 0x0089),
+ S5K4ECGX_REG_WRITE(0x70004816, 0xFEFE),
+ S5K4ECGX_REG_WRITE(0x70004818, 0x0175),
+ S5K4ECGX_REG_WRITE(0x7000481A, 0xFF4A),
+ S5K4ECGX_REG_WRITE(0x7000481C, 0x00D6),
+ S5K4ECGX_REG_WRITE(0x7000481E, 0xFEFE),
+ S5K4ECGX_REG_WRITE(0x70004820, 0x0113),
+ S5K4ECGX_REG_WRITE(0x70004822, 0x00E6),
+ S5K4ECGX_REG_WRITE(0x70004824, 0x010F), /* incaA */
+ S5K4ECGX_REG_WRITE(0x70004826, 0xFF90),
+ S5K4ECGX_REG_WRITE(0x70004828, 0xFF7D),
+ S5K4ECGX_REG_WRITE(0x7000482A, 0xFEF1),
+ S5K4ECGX_REG_WRITE(0x7000482C, 0x0137),
+ S5K4ECGX_REG_WRITE(0x7000482E, 0xFF68),
+ S5K4ECGX_REG_WRITE(0x70004830, 0xFFEE),
+ S5K4ECGX_REG_WRITE(0x70004832, 0xFF8A),
+ S5K4ECGX_REG_WRITE(0x70004834, 0x013A),
+ S5K4ECGX_REG_WRITE(0x70004836, 0x006E),
+ S5K4ECGX_REG_WRITE(0x70004838, 0x0089),
+ S5K4ECGX_REG_WRITE(0x7000483A, 0xFEFE),
+ S5K4ECGX_REG_WRITE(0x7000483C, 0x0175),
+ S5K4ECGX_REG_WRITE(0x7000483E, 0xFF4A),
+ S5K4ECGX_REG_WRITE(0x70004840, 0x00D6),
+ S5K4ECGX_REG_WRITE(0x70004842, 0xFEFE),
+ S5K4ECGX_REG_WRITE(0x70004844, 0x0113),
+ S5K4ECGX_REG_WRITE(0x70004846, 0x00E6),
+ S5K4ECGX_REG_WRITE(0x70004848, 0x010F), /* WW */
+ S5K4ECGX_REG_WRITE(0x7000484A, 0xFF90),
+ S5K4ECGX_REG_WRITE(0x7000484C, 0xFF7D),
+ S5K4ECGX_REG_WRITE(0x7000484E, 0xFEF1),
+ S5K4ECGX_REG_WRITE(0x70004850, 0x0137),
+ S5K4ECGX_REG_WRITE(0x70004852, 0xFF68),
+ S5K4ECGX_REG_WRITE(0x70004854, 0xFFEE),
+ S5K4ECGX_REG_WRITE(0x70004856, 0xFF8A),
+ S5K4ECGX_REG_WRITE(0x70004858, 0x013A),
+ S5K4ECGX_REG_WRITE(0x7000485A, 0x006E),
+ S5K4ECGX_REG_WRITE(0x7000485C, 0x0089),
+ S5K4ECGX_REG_WRITE(0x7000485E, 0xFEFE),
+ S5K4ECGX_REG_WRITE(0x70004860, 0x0175),
+ S5K4ECGX_REG_WRITE(0x70004862, 0xFF4A),
+ S5K4ECGX_REG_WRITE(0x70004864, 0x00D6),
+ S5K4ECGX_REG_WRITE(0x70004866, 0xFEFE),
+ S5K4ECGX_REG_WRITE(0x70004868, 0x0113),
+ S5K4ECGX_REG_WRITE(0x7000486A, 0x00E6),
+ S5K4ECGX_REG_WRITE(0x7000486C, 0x017B), /* CW */
+ S5K4ECGX_REG_WRITE(0x7000486E, 0xFFB5),
+ S5K4ECGX_REG_WRITE(0x70004870, 0xFFF9),
+ S5K4ECGX_REG_WRITE(0x70004872, 0xFF5E),
+ S5K4ECGX_REG_WRITE(0x70004874, 0x019D),
+ S5K4ECGX_REG_WRITE(0x70004876, 0xFFA2),
+ S5K4ECGX_REG_WRITE(0x70004878, 0xFFD9),
+ S5K4ECGX_REG_WRITE(0x7000487A, 0xFFCB),
+ S5K4ECGX_REG_WRITE(0x7000487C, 0x012C),
+ S5K4ECGX_REG_WRITE(0x7000487E, 0x00C9),
+ S5K4ECGX_REG_WRITE(0x70004880, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x70004882, 0xFF2F),
+ S5K4ECGX_REG_WRITE(0x70004884, 0x00CA),
+ S5K4ECGX_REG_WRITE(0x70004886, 0xFF91),
+ S5K4ECGX_REG_WRITE(0x70004888, 0x015E),
+ S5K4ECGX_REG_WRITE(0x7000488A, 0xFF47),
+ S5K4ECGX_REG_WRITE(0x7000488C, 0x0129),
+ S5K4ECGX_REG_WRITE(0x7000488E, 0x0125),
+ S5K4ECGX_REG_WRITE(0x70004890, 0x01AF), /* D50 */
+ S5K4ECGX_REG_WRITE(0x70004892, 0xFFBA),
+ S5K4ECGX_REG_WRITE(0x70004894, 0xFFF1),
+ S5K4ECGX_REG_WRITE(0x70004896, 0xFF27),
+ S5K4ECGX_REG_WRITE(0x70004898, 0x01DE),
+ S5K4ECGX_REG_WRITE(0x7000489A, 0xFF77),
+ S5K4ECGX_REG_WRITE(0x7000489C, 0xFFCB),
+ S5K4ECGX_REG_WRITE(0x7000489E, 0xFFC5),
+ S5K4ECGX_REG_WRITE(0x700048A0, 0x0136),
+ S5K4ECGX_REG_WRITE(0x700048A2, 0x0110),
+ S5K4ECGX_REG_WRITE(0x700048A4, 0x00EF),
+ S5K4ECGX_REG_WRITE(0x700048A6, 0xFFA0),
+ S5K4ECGX_REG_WRITE(0x700048A8, 0x00A3),
+ S5K4ECGX_REG_WRITE(0x700048AA, 0xFF7B),
+ S5K4ECGX_REG_WRITE(0x700048AC, 0x018C),
+ S5K4ECGX_REG_WRITE(0x700048AE, 0xFF1D),
+ S5K4ECGX_REG_WRITE(0x700048B0, 0x0138),
+ S5K4ECGX_REG_WRITE(0x700048B2, 0x0138),
+ S5K4ECGX_REG_WRITE(0x700048B4, 0x01AF), /* D65 */
+ S5K4ECGX_REG_WRITE(0x700048B6, 0xFFBA),
+ S5K4ECGX_REG_WRITE(0x700048B8, 0xFFF1),
+ S5K4ECGX_REG_WRITE(0x700048BA, 0xFF27),
+ S5K4ECGX_REG_WRITE(0x700048BC, 0x01DE),
+ S5K4ECGX_REG_WRITE(0x700048BE, 0xFF77),
+ S5K4ECGX_REG_WRITE(0x700048C0, 0xFFCB),
+ S5K4ECGX_REG_WRITE(0x700048C2, 0xFFC5),
+ S5K4ECGX_REG_WRITE(0x700048C4, 0x0136),
+ S5K4ECGX_REG_WRITE(0x700048C6, 0x0110),
+ S5K4ECGX_REG_WRITE(0x700048C8, 0x00EF),
+ S5K4ECGX_REG_WRITE(0x700048CA, 0xFFA0),
+ S5K4ECGX_REG_WRITE(0x700048CC, 0x00A3),
+ S5K4ECGX_REG_WRITE(0x700048CE, 0xFF7B),
+ S5K4ECGX_REG_WRITE(0x700048D0, 0x018C),
+ S5K4ECGX_REG_WRITE(0x700048D2, 0xFF1D),
+ S5K4ECGX_REG_WRITE(0x700048D4, 0x0138),
+ S5K4ECGX_REG_WRITE(0x700048D6, 0x0138),
+
+ S5K4ECGX_REG_WRITE(0x700048D8, 0x019F), /* #TVAR_wbt_pOutdoorCcm[0] */
+ S5K4ECGX_REG_WRITE(0x700048DA, 0xFFBF),
+ S5K4ECGX_REG_WRITE(0x700048DC, 0xFFFD),
+ S5K4ECGX_REG_WRITE(0x700048DE, 0xFF10),
+ S5K4ECGX_REG_WRITE(0x700048E0, 0x01D4),
+ S5K4ECGX_REG_WRITE(0x700048E2, 0xFFA4),
+ S5K4ECGX_REG_WRITE(0x700048E4, 0xFFE8),
+ S5K4ECGX_REG_WRITE(0x700048E6, 0xFFE0),
+ S5K4ECGX_REG_WRITE(0x700048E8, 0x01C2),
+ S5K4ECGX_REG_WRITE(0x700048EA, 0x0087),
+ S5K4ECGX_REG_WRITE(0x700048EC, 0x00A5),
+ S5K4ECGX_REG_WRITE(0x700048EE, 0xFF17),
+ S5K4ECGX_REG_WRITE(0x700048F0, 0x01DD),
+ S5K4ECGX_REG_WRITE(0x700048F2, 0xFF0E),
+ S5K4ECGX_REG_WRITE(0x700048F4, 0x010B),
+ S5K4ECGX_REG_WRITE(0x700048F6, 0xFF24),
+ S5K4ECGX_REG_WRITE(0x700048F8, 0x00F0),
+ S5K4ECGX_REG_WRITE(0x700048FA, 0x01DB),
+
+ /* System Setting */
+ S5K4ECGX_REG_WRITE(0x700001F8, 0x5DC0), /* #REG_TC_IPRM_InClockLSBs, MCLK: 24Mhz */
+ S5K4ECGX_REG_WRITE(0x70000212, 0x0002), /* #REG_TC_IPRM_UseNPviClocks */
+ S5K4ECGX_REG_WRITE(0x70000214, 0x0000), /* #REG_TC_IPRM_UseNMipiClocks */
+ S5K4ECGX_REG_WRITE(0x70000216, 0x0000), /* #REG_TC_IPRM_NumberOfMipiLanes */
+ S5K4ECGX_REG_WRITE(0x7000021A, 0x3A98), /* #REG_TC_IPRM_OpClk4KHz_0, SCLK: 60Mhz */
+ S5K4ECGX_REG_WRITE(0x7000021C, 0x4F1A), /* #REG_TC_IPRM_MinOutRate4KHz_0 PCLK Min : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x7000021E, 0x4F1A), /* #REG_TC_IPRM_MaxOutRate4KHz_0 PCLK Max : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x70000220, 0x4F1A), /* #REG_TC_IPRM_OpClk4KHz_1 SCLK : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x70000222, 0x4F1A), /* #REG_TC_IPRM_MinOutRate4KHz_1 PCLK Min : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x70000224, 0x4F1A), /* #REG_TC_IPRM_MaxOutRate4KHz_1 PCLK Max : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x0001), /* #REG_TC_IPRM_InitParamsUpdated */
+
+ /* ETC.. Setting */
+ S5K4ECGX_REG_WRITE(0x70000478, 0x005F), /* #REG_TC_BRC_usPrevQuality */
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x005F), /* #REG_TC_BRC_usCaptureQuality */
+
+ S5K4ECGX_REG_WRITE(0x7000047C, 0x0001), /* #REG_TC_THUMB_Thumb_bActive */
+ S5K4ECGX_REG_WRITE(0x7000047E, 0x0280), /* #REG_TC_THUMB_Thumb_uWidth */
+ S5K4ECGX_REG_WRITE(0x70000480, 0x01E0), /* #REG_TC_THUMB_Thumb_uHeight */
+ S5K4ECGX_REG_WRITE(0x70000482, 0x0005), /* #REG_TC_THUMB_Thumb_Format */
+
+ S5K4ECGX_REG_WRITE(0x700017DC, 0x0054), /* #jpeg_ManualMBCV */
+ S5K4ECGX_REG_WRITE(0x70001AE4, 0x001C), /* #senHal_bExtraAddLine */
+ S5K4ECGX_REG_WRITE(0x70000284, 0x0001), /* #REG_TC_GP_bBypassScalerJpg */
+ S5K4ECGX_REG_WRITE(0x7000028A, 0x0001), /* #REG_TC_GP_bUse1FrameCaptureMode */
+ /* 0 : Continuous mode,1 : Single frame mode */
+
+ /* Configuration Setting */
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x0280), /* #REG_0TC_PCFG_usWidth : 640 */
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x01E0), /* #REG_0TC_PCFG_usHeight : 480 */
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005), /* #REG_0TC_PCFG_Format 5 : YUV 7 : Raw 9 : JPG */
+ S5K4ECGX_REG_WRITE(0x700002AC, 0x4F1A), /* #REG_0TC_PCFG_usMaxOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x4F1A), /* #REG_0TC_PCFG_usMinOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700002B0, 0x0100), /* #REG_0TC_PCFG_OutClkPerPix88 */
+ S5K4ECGX_REG_WRITE(0x700002B2, 0x0300), /* #REG_0TC_PCFG_uBpp88 */
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052), /* #REG_0TC_PCFG_PVIMask */
+ S5K4ECGX_REG_WRITE(0x700002B6, 0x0000), /* #REG_0TC_PCFG_OIFMask */
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x01E0), /* #REG_0TC_PCFG_usJpegPacketSize */
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0000), /* #REG_0TC_PCFG_usJpegTotalPackets */
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x0000), /* #REG_0TC_PCFG_uClockInd */
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000), /* #REG_0TC_PCFG_usFrTimeType */
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001), /* #REG_0TC_PCFG_FrRateQualityType */
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A), /* #REG_0TC_PCFG_usMaxFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A), /* #REG_0TC_PCFG_usMinFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000), /* #REG_0TC_PCFG_uPrevMirror */
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000), /* #REG_0TC_PCFG_uCaptureMirror */
+ S5K4ECGX_REG_WRITE(0x700002D4, 0x0000), /* #REG_0TC_PCFG_uRotation */
+
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0000), /* #REG_0TC_CCFG_uCaptureMode */
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0A00), /* #REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x0780), /* #REG_0TC_CCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0009), /* #REG_0TC_CCFG_Format */
+ S5K4ECGX_REG_WRITE(0x7000039E, 0x4F1A), /* #REG_0TC_CCFG_usMaxOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700003A0, 0x4F1A), /* #REG_0TC_CCFG_usMinOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700003A2, 0x0100), /* #REG_0TC_CCFG_OutClkPerPix88 */
+ S5K4ECGX_REG_WRITE(0x700003A4, 0x0300), /* #REG_0TC_CCFG_uBpp88 */
+ S5K4ECGX_REG_WRITE(0x700003A6, 0x0042), /* #REG_0TC_CCFG_PVIMask */
+ S5K4ECGX_REG_WRITE(0x700003A8, 0x0000), /* #REG_0TC_CCFG_OIFMask */
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x01E0), /* #REG_0TC_CCFG_usJpegPacketSize */
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0000), /* #REG_0TC_CCFG_usJpegTotalPackets */
+ S5K4ECGX_REG_WRITE(0x700003AE, 0x0001), /* #REG_0TC_CCFG_uClockInd */
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0000), /* #REG_0TC_CCFG_usFrTimeType */
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002), /* #REG_0TC_CCFG_FrRateQualityType */
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x0535), /* #REG_0TC_CCFG_usMaxFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x029A), /* #REG_0TC_CCFG_usMinFrTimeMsecMult10 */
+
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000), /* #REG_TC_GP_ActivePrevConfig */
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001), /* #REG_TC_GP_PrevOpenAfterChange */
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_PrevConfigChanged */
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001), /* #REG_TC_GP_EnablePreview */
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001), /* #REG_TC_GP_EnablePreviewChanged */
+
+ /* AFIT */
+ S5K4ECGX_REG_WRITE(0x70000944, 0x0050), /* #afit_uNoiseIndInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x70000946, 0x0103), /* #afit_uNoiseIndInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x70000948, 0x0196), /* #afit_uNoiseIndInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x7000094A, 0x0245), /* #afit_uNoiseIndInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x7000094C, 0x0300), /* #afit_uNoiseIndInDoor_4_ */
+
+ S5K4ECGX_REG_WRITE(0x7000097A, 0x0001), /* #afit_bUseSenBpr */
+ S5K4ECGX_REG_WRITE(0x7000097C, 0x01CC), /* #afit_usBprThr_0_ */
+ S5K4ECGX_REG_WRITE(0x7000097E, 0x01CC), /* #afit_usBprThr_1_ */
+ S5K4ECGX_REG_WRITE(0x70000980, 0x01CC), /* #afit_usBprThr_2_ */
+ S5K4ECGX_REG_WRITE(0x70000982, 0x01CC), /* #afit_usBprThr_3_ */
+ S5K4ECGX_REG_WRITE(0x70000984, 0x01CC), /* #afit_usBprThr_4_ */
+ S5K4ECGX_REG_WRITE(0x70000986, 0x0180), /* #afit_NIContrastAFITValue */
+ S5K4ECGX_REG_WRITE(0x70000988, 0x0196), /* #afit_NIContrastTh */
+
+ S5K4ECGX_REG_WRITE(0x70000976, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000978, 0x0005),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000093A, 0x0014), /* #SARR_uNormBrInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x7000093C, 0x00D2), /* #SARR_uNormBrInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x7000093E, 0x0384), /* #SARR_uNormBrInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x70000940, 0x07D0), /* #SARR_uNormBrInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x70000942, 0x1388), /* #SARR_uNormBrInDoor_4_ */
+
+ S5K4ECGX_REG_WRITE(0x7000098C, 0x0000), /* AFIT 0 */
+ S5K4ECGX_REG_WRITE(0x7000098E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000990, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000992, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000994, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000996, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000998, 0x0064),
+ S5K4ECGX_REG_WRITE(0x7000099A, 0x0384),
+ S5K4ECGX_REG_WRITE(0x7000099C, 0x005F),
+ S5K4ECGX_REG_WRITE(0x7000099E, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700009A0, 0x0070),
+ S5K4ECGX_REG_WRITE(0x700009A2, 0x0040),
+ S5K4ECGX_REG_WRITE(0x700009A4, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x700009A6, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700009A8, 0x0010),
+ S5K4ECGX_REG_WRITE(0x700009AA, 0x0040),
+ S5K4ECGX_REG_WRITE(0x700009AC, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x700009AE, 0x1430),
+ S5K4ECGX_REG_WRITE(0x700009B0, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700009B2, 0x0204),
+ S5K4ECGX_REG_WRITE(0x700009B4, 0x3604),
+ S5K4ECGX_REG_WRITE(0x700009B6, 0x032A),
+ S5K4ECGX_REG_WRITE(0x700009B8, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700009BA, 0x1B06),
+ S5K4ECGX_REG_WRITE(0x700009BC, 0x6015),
+ S5K4ECGX_REG_WRITE(0x700009BE, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x700009C0, 0x6080),
+ S5K4ECGX_REG_WRITE(0x700009C2, 0x4080),
+ S5K4ECGX_REG_WRITE(0x700009C4, 0x0640),
+ S5K4ECGX_REG_WRITE(0x700009C6, 0x0306),
+ S5K4ECGX_REG_WRITE(0x700009C8, 0x2003),
+ S5K4ECGX_REG_WRITE(0x700009CA, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x700009CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009CE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700009D0, 0x365A),
+ S5K4ECGX_REG_WRITE(0x700009D2, 0x102A),
+ S5K4ECGX_REG_WRITE(0x700009D4, 0x000B),
+ S5K4ECGX_REG_WRITE(0x700009D6, 0x0600),
+ S5K4ECGX_REG_WRITE(0x700009D8, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x700009DA, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700009DC, 0x1802),
+ S5K4ECGX_REG_WRITE(0x700009DE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009E0, 0x2006),
+ S5K4ECGX_REG_WRITE(0x700009E2, 0x3028),
+ S5K4ECGX_REG_WRITE(0x700009E4, 0x0418),
+ S5K4ECGX_REG_WRITE(0x700009E6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700009E8, 0x0800),
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x1804),
+ S5K4ECGX_REG_WRITE(0x700009EC, 0x4008),
+ S5K4ECGX_REG_WRITE(0x700009EE, 0x0540),
+ S5K4ECGX_REG_WRITE(0x700009F0, 0x8006),
+ S5K4ECGX_REG_WRITE(0x700009F2, 0x0020),
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009F6, 0x1800),
+ S5K4ECGX_REG_WRITE(0x700009F8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700009FA, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x700009FC, 0x000B),
+ S5K4ECGX_REG_WRITE(0x700009FE, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000A00, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000A02, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000A04, 0x0705),
+ S5K4ECGX_REG_WRITE(0x70000A06, 0x0206),
+ S5K4ECGX_REG_WRITE(0x70000A08, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000A0A, 0x0309),
+ S5K4ECGX_REG_WRITE(0x70000A0C, 0x0305),
+ S5K4ECGX_REG_WRITE(0x70000A0E, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000A10, 0x1320),
+ S5K4ECGX_REG_WRITE(0x70000A12, 0x1014),
+ S5K4ECGX_REG_WRITE(0x70000A14, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000A16, 0x0C10),
+ S5K4ECGX_REG_WRITE(0x70000A18, 0x1A0C),
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x4A18),
+ S5K4ECGX_REG_WRITE(0x70000A1C, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70000A20, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000A22, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000A24, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000A26, 0x2A36),
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000A2A, 0x2A36),
+ S5K4ECGX_REG_WRITE(0x70000A2C, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000A2E, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000A30, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000A32, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000A34, 0x3601),
+ S5K4ECGX_REG_WRITE(0x70000A36, 0x242A),
+ S5K4ECGX_REG_WRITE(0x70000A38, 0x3660),
+ S5K4ECGX_REG_WRITE(0x70000A3A, 0xFF2A),
+ S5K4ECGX_REG_WRITE(0x70000A3C, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000A3E, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000A40, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000A42, 0x0000), /* AFIT 1 */
+ S5K4ECGX_REG_WRITE(0x70000A44, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A46, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A48, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A4A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A4C, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000A4E, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000A50, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000A52, 0x0051),
+ S5K4ECGX_REG_WRITE(0x70000A54, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000A56, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000A58, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000A5A, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000A5C, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000A5E, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000A60, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000A62, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000A64, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000A66, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000A68, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000A6A, 0x2404),
+ S5K4ECGX_REG_WRITE(0x70000A6C, 0x031B),
+ S5K4ECGX_REG_WRITE(0x70000A6E, 0x0103),
+ S5K4ECGX_REG_WRITE(0x70000A70, 0x1205),
+ S5K4ECGX_REG_WRITE(0x70000A72, 0x400D),
+ S5K4ECGX_REG_WRITE(0x70000A74, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000A76, 0x1980),
+ S5K4ECGX_REG_WRITE(0x70000A78, 0x272E),
+ S5K4ECGX_REG_WRITE(0x70000A7A, 0x0629),
+ S5K4ECGX_REG_WRITE(0x70000A7C, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000A7E, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000A80, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000A82, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000A84, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70000A86, 0x245A),
+ S5K4ECGX_REG_WRITE(0x70000A88, 0x1018),
+ S5K4ECGX_REG_WRITE(0x70000A8A, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000A8C, 0x0B00),
+ S5K4ECGX_REG_WRITE(0x70000A8E, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000A90, 0x0505),
+ S5K4ECGX_REG_WRITE(0x70000A92, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000A94, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000A96, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000A98, 0x3828),
+ S5K4ECGX_REG_WRITE(0x70000A9A, 0x0425),
+ S5K4ECGX_REG_WRITE(0x70000A9C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000A9E, 0x0800),
+ S5K4ECGX_REG_WRITE(0x70000AA0, 0x1004),
+ S5K4ECGX_REG_WRITE(0x70000AA2, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000AA4, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000AA6, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000AA8, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AAC, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000AAE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AB0, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000AB2, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000AB4, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000AB6, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000AB8, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000ABA, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000ABC, 0x0205),
+ S5K4ECGX_REG_WRITE(0x70000ABE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000AC0, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000AC2, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000AC4, 0x0407),
+ S5K4ECGX_REG_WRITE(0x70000AC6, 0x2204),
+ S5K4ECGX_REG_WRITE(0x70000AC8, 0x021C),
+ S5K4ECGX_REG_WRITE(0x70000ACA, 0x1102),
+ S5K4ECGX_REG_WRITE(0x70000ACC, 0x0611),
+ S5K4ECGX_REG_WRITE(0x70000ACE, 0x1A02),
+ S5K4ECGX_REG_WRITE(0x70000AD0, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000AD2, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x0074),
+ S5K4ECGX_REG_WRITE(0x70000AD6, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000AD8, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000ADA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000ADC, 0x141D),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000AE0, 0x1217),
+ S5K4ECGX_REG_WRITE(0x70000AE2, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000AE4, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000AE6, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000AE8, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000AEA, 0x2401),
+ S5K4ECGX_REG_WRITE(0x70000AEC, 0x241B),
+ S5K4ECGX_REG_WRITE(0x70000AEE, 0x1E60),
+ S5K4ECGX_REG_WRITE(0x70000AF0, 0xFF18),
+ S5K4ECGX_REG_WRITE(0x70000AF2, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000AF4, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000AF6, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000AF8, 0x0000), /* AFIT 2 */
+ S5K4ECGX_REG_WRITE(0x70000AFA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AFC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000AFE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B00, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B02, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000B04, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000B06, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000B08, 0x0043),
+ S5K4ECGX_REG_WRITE(0x70000B0A, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000B0C, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000B0E, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000B10, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000B12, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000B14, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000B16, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000B18, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000B1A, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000B1C, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000B1E, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000B20, 0x1B04),
+ S5K4ECGX_REG_WRITE(0x70000B22, 0x0312),
+ S5K4ECGX_REG_WRITE(0x70000B24, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000B26, 0x0C03),
+ S5K4ECGX_REG_WRITE(0x70000B28, 0x2806),
+ S5K4ECGX_REG_WRITE(0x70000B2A, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000B2C, 0x1580),
+ S5K4ECGX_REG_WRITE(0x70000B2E, 0x2020),
+ S5K4ECGX_REG_WRITE(0x70000B30, 0x0620),
+ S5K4ECGX_REG_WRITE(0x70000B32, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000B34, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000B36, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000B38, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000B3A, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70000B3C, 0x145A),
+ S5K4ECGX_REG_WRITE(0x70000B3E, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000B40, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000B42, 0x0E00),
+ S5K4ECGX_REG_WRITE(0x70000B44, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000B46, 0x0504),
+ S5K4ECGX_REG_WRITE(0x70000B48, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000B4A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B4C, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000B4E, 0x3828),
+ S5K4ECGX_REG_WRITE(0x70000B50, 0x0428),
+ S5K4ECGX_REG_WRITE(0x70000B52, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000B54, 0x8000),
+ S5K4ECGX_REG_WRITE(0x70000B56, 0x0A04),
+ S5K4ECGX_REG_WRITE(0x70000B58, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000B5A, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000B5C, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000B5E, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B62, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000B64, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B66, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000B68, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000B6A, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000B6C, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000B6E, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000B70, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000B72, 0x0207),
+ S5K4ECGX_REG_WRITE(0x70000B74, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000B76, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000B78, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000B7A, 0x0407),
+ S5K4ECGX_REG_WRITE(0x70000B7C, 0x2404),
+ S5K4ECGX_REG_WRITE(0x70000B7E, 0x0221),
+ S5K4ECGX_REG_WRITE(0x70000B80, 0x1202),
+ S5K4ECGX_REG_WRITE(0x70000B82, 0x0613),
+ S5K4ECGX_REG_WRITE(0x70000B84, 0x1A02),
+ S5K4ECGX_REG_WRITE(0x70000B86, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000B88, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000B8A, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000B8C, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000B8E, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000B90, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000B92, 0x121B),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B96, 0x0C0C),
+ S5K4ECGX_REG_WRITE(0x70000B98, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000B9A, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000B9C, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000B9E, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000BA0, 0x1B01),
+ S5K4ECGX_REG_WRITE(0x70000BA2, 0x2412),
+ S5K4ECGX_REG_WRITE(0x70000BA4, 0x0C60),
+ S5K4ECGX_REG_WRITE(0x70000BA6, 0xFF0C),
+ S5K4ECGX_REG_WRITE(0x70000BA8, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000BAA, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000BAC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000BAE, 0x0000), /* AFIT 3 */
+ S5K4ECGX_REG_WRITE(0x70000BB0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BB2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BB4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BB6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000BB8, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000BBA, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000BBC, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000BBE, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70000BC0, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000BC2, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000BC4, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000BC6, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000BC8, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000BCA, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000BCC, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000BCE, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000BD0, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000BD2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000BD4, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000BD6, 0x1504),
+ S5K4ECGX_REG_WRITE(0x70000BD8, 0x030F),
+ S5K4ECGX_REG_WRITE(0x70000BDA, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000BDC, 0x0902),
+ S5K4ECGX_REG_WRITE(0x70000BDE, 0x2004),
+ S5K4ECGX_REG_WRITE(0x70000BE0, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70000BE2, 0x1140),
+ S5K4ECGX_REG_WRITE(0x70000BE4, 0x201C),
+ S5K4ECGX_REG_WRITE(0x70000BE6, 0x0620),
+ S5K4ECGX_REG_WRITE(0x70000BE8, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000BEA, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000BEC, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000BEE, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000BF0, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70000BF2, 0x145A),
+ S5K4ECGX_REG_WRITE(0x70000BF4, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000BF6, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000BF8, 0x1000),
+ S5K4ECGX_REG_WRITE(0x70000BFA, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000BFC, 0x0503),
+ S5K4ECGX_REG_WRITE(0x70000BFE, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000C00, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C02, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000C04, 0x3C28),
+ S5K4ECGX_REG_WRITE(0x70000C06, 0x042C),
+ S5K4ECGX_REG_WRITE(0x70000C08, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000C0A, 0xFF00),
+ S5K4ECGX_REG_WRITE(0x70000C0C, 0x0904),
+ S5K4ECGX_REG_WRITE(0x70000C0E, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000C10, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000C12, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000C14, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C18, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000C1A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C1C, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000C1E, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000C20, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000C22, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000C24, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000C26, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000C28, 0x0206),
+ S5K4ECGX_REG_WRITE(0x70000C2A, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000C2C, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000C2E, 0x0305),
+ S5K4ECGX_REG_WRITE(0x70000C30, 0x0406),
+ S5K4ECGX_REG_WRITE(0x70000C32, 0x2804),
+ S5K4ECGX_REG_WRITE(0x70000C34, 0x0228),
+ S5K4ECGX_REG_WRITE(0x70000C36, 0x1402),
+ S5K4ECGX_REG_WRITE(0x70000C38, 0x0618),
+ S5K4ECGX_REG_WRITE(0x70000C3A, 0x1A02),
+ S5K4ECGX_REG_WRITE(0x70000C3C, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000C3E, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000C40, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000C42, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000C44, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000C46, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000C48, 0x0F15),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C4C, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000C4E, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000C50, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000C52, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000C54, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000C56, 0x1501),
+ S5K4ECGX_REG_WRITE(0x70000C58, 0x240F),
+ S5K4ECGX_REG_WRITE(0x70000C5A, 0x0A60),
+ S5K4ECGX_REG_WRITE(0x70000C5C, 0xFF0A),
+ S5K4ECGX_REG_WRITE(0x70000C5E, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000C60, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000C62, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000C64, 0x0000), /* AFIT 4 */
+ S5K4ECGX_REG_WRITE(0x70000C66, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C68, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C6A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C6C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C6E, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70000C70, 0x0064),
+ S5K4ECGX_REG_WRITE(0x70000C72, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70000C74, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70000C76, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70000C78, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000C7A, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000C7C, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70000C7E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000C80, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000C82, 0x0060),
+ S5K4ECGX_REG_WRITE(0x70000C84, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000C86, 0x1430),
+ S5K4ECGX_REG_WRITE(0x70000C88, 0x0201),
+ S5K4ECGX_REG_WRITE(0x70000C8A, 0x0204),
+ S5K4ECGX_REG_WRITE(0x70000C8C, 0x0F04),
+ S5K4ECGX_REG_WRITE(0x70000C8E, 0x030C),
+ S5K4ECGX_REG_WRITE(0x70000C90, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000C92, 0x0602),
+ S5K4ECGX_REG_WRITE(0x70000C94, 0x1803),
+ S5K4ECGX_REG_WRITE(0x70000C96, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70000C98, 0x0E20),
+ S5K4ECGX_REG_WRITE(0x70000C9A, 0x2018),
+ S5K4ECGX_REG_WRITE(0x70000C9C, 0x0620),
+ S5K4ECGX_REG_WRITE(0x70000C9E, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000CA0, 0x2003),
+ S5K4ECGX_REG_WRITE(0x70000CA2, 0xFF01),
+ S5K4ECGX_REG_WRITE(0x70000CA4, 0x0404),
+ S5K4ECGX_REG_WRITE(0x70000CA6, 0x0200),
+ S5K4ECGX_REG_WRITE(0x70000CA8, 0x145A),
+ S5K4ECGX_REG_WRITE(0x70000CAA, 0x1010),
+ S5K4ECGX_REG_WRITE(0x70000CAC, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000CAE, 0x1200),
+ S5K4ECGX_REG_WRITE(0x70000CB0, 0x5A0F),
+ S5K4ECGX_REG_WRITE(0x70000CB2, 0x0502),
+ S5K4ECGX_REG_WRITE(0x70000CB4, 0x1802),
+ S5K4ECGX_REG_WRITE(0x70000CB6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000CB8, 0x2006),
+ S5K4ECGX_REG_WRITE(0x70000CBA, 0x4028),
+ S5K4ECGX_REG_WRITE(0x70000CBC, 0x0430),
+ S5K4ECGX_REG_WRITE(0x70000CBE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000CC0, 0xFF00),
+ S5K4ECGX_REG_WRITE(0x70000CC2, 0x0804),
+ S5K4ECGX_REG_WRITE(0x70000CC4, 0x4008),
+ S5K4ECGX_REG_WRITE(0x70000CC6, 0x0540),
+ S5K4ECGX_REG_WRITE(0x70000CC8, 0x8006),
+ S5K4ECGX_REG_WRITE(0x70000CCA, 0x0020),
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000CCE, 0x1800),
+ S5K4ECGX_REG_WRITE(0x70000CD0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000CD2, 0x1E10),
+ S5K4ECGX_REG_WRITE(0x70000CD4, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000CD6, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000CD8, 0x0005),
+ S5K4ECGX_REG_WRITE(0x70000CDA, 0x0607),
+ S5K4ECGX_REG_WRITE(0x70000CDC, 0x0405),
+ S5K4ECGX_REG_WRITE(0x70000CDE, 0x0205),
+ S5K4ECGX_REG_WRITE(0x70000CE0, 0x0304),
+ S5K4ECGX_REG_WRITE(0x70000CE2, 0x0409),
+ S5K4ECGX_REG_WRITE(0x70000CE4, 0x0306),
+ S5K4ECGX_REG_WRITE(0x70000CE6, 0x0407),
+ S5K4ECGX_REG_WRITE(0x70000CE8, 0x2C04),
+ S5K4ECGX_REG_WRITE(0x70000CEA, 0x022C),
+ S5K4ECGX_REG_WRITE(0x70000CEC, 0x1402),
+ S5K4ECGX_REG_WRITE(0x70000CEE, 0x0618),
+ S5K4ECGX_REG_WRITE(0x70000CF0, 0x1A02),
+ S5K4ECGX_REG_WRITE(0x70000CF2, 0x8018),
+ S5K4ECGX_REG_WRITE(0x70000CF4, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000CF6, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70000CF8, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70000CFA, 0x0A0A),
+ S5K4ECGX_REG_WRITE(0x70000CFC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000CFE, 0x0C0F),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000D02, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000D04, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x70000D06, 0x0808),
+ S5K4ECGX_REG_WRITE(0x70000D08, 0x0A01),
+ S5K4ECGX_REG_WRITE(0x70000D0A, 0x010A),
+ S5K4ECGX_REG_WRITE(0x70000D0C, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x70000D0E, 0x240C),
+ S5K4ECGX_REG_WRITE(0x70000D10, 0x0860),
+ S5K4ECGX_REG_WRITE(0x70000D12, 0xFF08),
+ S5K4ECGX_REG_WRITE(0x70000D14, 0x08FF),
+ S5K4ECGX_REG_WRITE(0x70000D16, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70000D18, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000D1A, 0x23CE),
+ S5K4ECGX_REG_WRITE(0x70000D1C, 0xFDC8),
+ S5K4ECGX_REG_WRITE(0x70000D1E, 0x112E),
+ S5K4ECGX_REG_WRITE(0x70000D20, 0x83A5),
+ S5K4ECGX_REG_WRITE(0x70000D22, 0xFE67),
+ S5K4ECGX_REG_WRITE(0x70000D24, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000588, 0x0002), /* AE Speed Normal */
+
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_DTP_init) = {
+ S5K4ECGX_REG_WRITE(0xD000B054, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_DTP_stop) = {
+ S5K4ECGX_REG_WRITE(0xD000B054, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_Auto) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_7) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_15) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_30) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Normal) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Solarization) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0002),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Negative) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0003),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Sepia) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0004),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Black_White) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Auto) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Sunny) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Cloudy) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0710),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0420),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Tungsten) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0390),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0920),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Fluorescent) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0875),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WDR_on) = {
+ S5K4ECGX_REG_WRITE(0x70001BEA, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WDR_off) = {
+ S5K4ECGX_REG_WRITE(0x70001BEA, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_Auto) = {
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000F2A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0200),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_100) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x01A0),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_200) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_400) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0680),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Matrix) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0101),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Center) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0102),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Spot) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFF30),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFA0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFC8),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFE0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0038),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFF81),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFFA0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFFC0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFFE0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x2010),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x4020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x6024),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x8040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xA060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xC080),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0xFF81),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0xFFC0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_High) = {
+ S5K4ECGX_REG_WRITE(0x70000478, 0x005F),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x005F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_Normal) = {
+ S5K4ECGX_REG_WRITE(0x70000478, 0x005A),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x005A),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_Low) = {
+ S5K4ECGX_REG_WRITE(0x70000478, 0x0054),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x0054),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Default) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0102),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700006B8, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x000C),
+
+ S5K4ECGX_REG_WRITE(0x70000F2A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000F30, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x70002C66, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001484, 0x003C),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x000F),
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000598, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000059A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000059C, 0x0470),
+ S5K4ECGX_REG_WRITE(0x7000059E, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x700005A0, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700005A2, 0x1000),
+
+ S5K4ECGX_REG_WRITE(0x70000544, 0x0111),
+ S5K4ECGX_REG_WRITE(0x70000546, 0x00EF),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x6024),
+
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000638, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x0D05),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x3408),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0x8214),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000654, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000658, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A), /* #REG_0TC_PCFG_usMaxFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A), /* #REG_0TC_PCFG_usMinFrTimeMsecMult10 */
+
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x029A),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Portrait) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x2010),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Nightshot) = {
+ S5K4ECGX_REG_WRITE(0x700006B8, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x00FF),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0900), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000658, 0xD090),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0007),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0xD090),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0007),
+
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x1388),
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x1388),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x09C4),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x1580),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Backlight) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Landscape) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Sports) = {
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000598, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000059A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000059C, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000059E, 0x0200),
+ S5K4ECGX_REG_WRITE(0x700005A0, 0x0200),
+ S5K4ECGX_REG_WRITE(0x700005A2, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Party_Indoor) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Beach_Snow) = {
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0045), /* #TVAR_ae_BrAve */
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x00D0),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Sunset) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Duskdawn) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0875),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Fall_Color) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Fireworks) = {
+ S5K4ECGX_REG_WRITE(0x70000638, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x1478),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x1A0A),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x6810),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0xD020),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0x0428),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000654, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0006),
+ S5K4ECGX_REG_WRITE(0x70000658, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0006),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0006),
+
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x2710),
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x2710),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Text) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xA060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Candle_Light) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Night_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0900), /* #lt_ExpGain_ExpCurveGainMaxStr */
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Return_Macro_pos) = {
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0066),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x006C),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x0072),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70001606, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001608, 0x0084),
+ S5K4ECGX_REG_WRITE(0x7000160A, 0x008A),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x0090),
+ S5K4ECGX_REG_WRITE(0x7000160E, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001610, 0x009C),
+ S5K4ECGX_REG_WRITE(0x70001612, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001614, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x70001616, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x70001618, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x7000161A, 0x00BA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Normal_mode) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0000),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0004),
+ S5K4ECGX_MDELAY(200),
+ S5K4ECGX_REG_WRITE(0x70001648, 0x9002),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Macro_mode) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x00D0),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0004),
+ S5K4ECGX_MDELAY(200),
+ S5K4ECGX_REG_WRITE(0x70001648, 0x9042),
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x1800),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Low_Light_Mode_On) = {
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x0C00),
+
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x000C),
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0033),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x0045),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0057),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x0063),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x006F),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x007B),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0087),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0093),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x00B1),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Low_Light_Mode_Off) = {
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x1800),
+
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0066),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x006C),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x0072),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70001606, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001608, 0x0084),
+ S5K4ECGX_REG_WRITE(0x7000160A, 0x008A),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x0090),
+ S5K4ECGX_REG_WRITE(0x7000160E, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001610, 0x009C),
+ S5K4ECGX_REG_WRITE(0x70001612, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001614, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x70001616, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x70001618, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x7000161A, 0x00BA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Start) = {
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0005),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_1) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_2) = {
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0004),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_3) = {
+
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Face_Detection_On) = {
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0238),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0074),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0132),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Face_Detection_Off) = {
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0238),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0074),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0132),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Low_Cap_On) = {
+ S5K4ECGX_REG_WRITE(0x700006B8, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x00FF), /* #lt_uMaxLei */
+
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x4A18), /* #Gamma linearity */
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0850), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000093A, 0x0012), /* #SARR_uNormBrInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x7000093C, 0x0022), /* #SARR_uNormBrInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x7000093E, 0x0384), /* #SARR_uNormBrInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x70000940, 0x07D0), /* #SARR_uNormBrInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x70000942, 0x1388), /* #SARR_uNormBrInDoor_4_ */
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Low_Cap_Off) = {
+ S5K4ECGX_REG_WRITE(0x700006B8, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x000C), /* #lt_uMaxLei */
+
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x8F18), /* #Gamma linearity */
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0C00), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000093A, 0x0014), /* #SARR_uNormBrInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x7000093C, 0x00D2), /* #SARR_uNormBrInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x7000093E, 0x0384), /* #SARR_uNormBrInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x70000940, 0x07D0), /* #SARR_uNormBrInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x70000942, 0x1388), /* #SARR_uNormBrInDoor_4_ */
+ S5K4ECGX_REGSET_END
+};
+
+ /* restores crop settings to full resolution */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Reset_Crop) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Capture_Start) = {
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0050),
+
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x0074),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0850), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000242, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000244, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Preview_Return) = {
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0C00), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x700005D0, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000972, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000242, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000244, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_init) = {
+ S5K4ECGX_REG_WRITE(0x70000484, 0x0002), /* capture flash on */
+
+ S5K4ECGX_REG_WRITE(0x7000183A, 0x0001), /* one frame AE */
+
+ S5K4ECGX_REG_WRITE(0x700017F6, 0x0258), /* AWB R point */
+ S5K4ECGX_REG_WRITE(0x700017F8, 0x0248), /* AWB B point */
+
+ S5K4ECGX_REG_WRITE(0x70001840, 0x0001), /* Fls AE tune start */
+
+ S5K4ECGX_REG_WRITE(0x70001842, 0x0100), /* fls_afl_FlsAFIn Rin */
+ S5K4ECGX_REG_WRITE(0x70001844, 0x0120),
+ S5K4ECGX_REG_WRITE(0x70001846, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70001848, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000184A, 0x0400),
+ S5K4ECGX_REG_WRITE(0x7000184C, 0x0800),
+ S5K4ECGX_REG_WRITE(0x7000184E, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70001850, 0x1000),
+
+ S5K4ECGX_REG_WRITE(0x70001852, 0x0100), /* fls_afl_FlsAFOut Rout */
+ S5K4ECGX_REG_WRITE(0x70001854, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70001856, 0x0090),
+ S5K4ECGX_REG_WRITE(0x70001858, 0x0080),
+ S5K4ECGX_REG_WRITE(0x7000185A, 0x0070),
+ S5K4ECGX_REG_WRITE(0x7000185C, 0x0045),
+ S5K4ECGX_REG_WRITE(0x7000185E, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70001860, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x70001884, 0x0100), /* fls_afl_FlsNBOut flash NB default */
+ S5K4ECGX_REG_WRITE(0x70001886, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001888, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000188A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000188C, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000188E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001890, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001892, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70001826, 0x0100), /* fls_afl_FlashWP_Weight flash NB default */
+ S5K4ECGX_REG_WRITE(0x70001828, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000182A, 0x0080),
+ S5K4ECGX_REG_WRITE(0x7000182C, 0x000A),
+ S5K4ECGX_REG_WRITE(0x7000182E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001830, 0x0030), /* fls_afl_FlashWP_Weight flash NB default */
+ S5K4ECGX_REG_WRITE(0x70001832, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70001834, 0x0048),
+ S5K4ECGX_REG_WRITE(0x70001836, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70001838, 0x0060),
+
+ S5K4ECGX_REG_WRITE(0x70004784, 0x00A0), /* TNP_Regs_FlsWeightRIn weight tune start in */
+ S5K4ECGX_REG_WRITE(0x70004786, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70004788, 0x00D0),
+ S5K4ECGX_REG_WRITE(0x7000478A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000478C, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000478E, 0x0300),
+
+ S5K4ECGX_REG_WRITE(0x70004790, 0x0088), /* TNP_Regs_FlsWeightROut weight tune start out */
+ S5K4ECGX_REG_WRITE(0x70004792, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x70004794, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70004796, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70004798, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000479A, 0x0300),
+
+ S5K4ECGX_REG_WRITE(0x7000479C, 0x0120), /* Fls BRIn */
+ S5K4ECGX_REG_WRITE(0x7000479E, 0x0150),
+ S5K4ECGX_REG_WRITE(0x700047A0, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x700047A2, 0x003C), /* Fls BROut */
+ S5K4ECGX_REG_WRITE(0x700047A4, 0x003B),
+ S5K4ECGX_REG_WRITE(0x700047A6, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Pre_Flash_Start) = {
+ S5K4ECGX_REG_WRITE(0x70000588, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700017FC, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Pre_Flash_End) = {
+ S5K4ECGX_REG_WRITE(0x70000588, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x70001800, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_Start) = {
+ S5K4ECGX_REG_WRITE(0x700017E8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000180C, 0x0027),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_End) = {
+ S5K4ECGX_REG_WRITE(0x700017E8, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+ /* 2560 x 1920 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_5M_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0A00), /* #REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x0780), /* #REG_0TC_CCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0009),
+
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+ /* 2048 x 1536 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_3M_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0800), /* REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x0600), /* REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0009), /* REG_0TC_CCFG_Format */
+
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002), /* REG_0TC_CCFG_FrRateQualityType */
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0002), /* REG_0TC_CCFG_usFrTimeType */
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001), /* REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 1600 x 1200 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_2M_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0640), /* #REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x04B0), /* #REG_0TC_CCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0009),
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0002),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+ /* 1280 x 960 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_1M_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0500), /* #REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x03C0), /* #REG_0TC_CCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0009),
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0002),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+ /* 640 x 480 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_VGA_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0280), /* #REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x01E0), /* #REG_0TC_CCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0009),
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002),
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0002),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+ /* 720 x 480 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_720_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 640 x 480 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_640_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x0280),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 352 x 288 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_352_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x007C),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x007C),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x0160),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x0120),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 176 x 144 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_176_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x007C),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x007C),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AE_AWB_Lock_On) = {
+ S5K4ECGX_REG_WRITE(0x70002C5E, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AE_AWB_Lock_Off) = {
+ S5K4ECGX_REG_WRITE(0x70002C5E, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Get_AE_Stable_Status) = {
+ S5K4ECGX_REG_READ(0x70002C74),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Get_Light_Level) = {
+ S5K4ECGX_REG_READ(0x70002C18),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_1st_af_search_status) = {
+ S5K4ECGX_REG_READ(0x70002EEE),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_2nd_af_search_status) = {
+ S5K4ECGX_REG_READ(0x70002207),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_capture_status) = {
+ S5K4ECGX_REG_READ(0x70000530),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_esd_status) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_READ(0xD0000060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_iso_reg) = {
+ S5K4ECGX_REG_READ(0x70002BC4),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_shutterspeed_reg) = {
+ S5K4ECGX_REG_READ(0x70002BC0),
+ S5K4ECGX_REGSET_END
+};
+
+#undef S5K4ECGX_DEFINE_REGSET
+#undef S5K4ECGX_REGSET_END
+#undef S5K4ECGX_CMD_WRITE
+#undef S5K4ECGX_REG_WRITE
+#undef S5K4ECGX_REG_READ
+#undef S5K4ECGX_MDELAY
+#undef _SWAB16
+#undef _DUMMY
+
+#endif
+
+#if !defined(__S5K4ECGX_V1_1_DEFINE_REGSET__)
+#define __S5K4ECGX_V1_1_DEFINE_REGSET__
+#elif !defined(__S5K4ECGX_V1_1_DEFINE_REGSET_DATA__)
+#define __S5K4ECGX_V1_1_DEFINE_REGSET_DATA__
+#endif
diff --git a/drivers/media/video/s5k4ecgx_regs_1_1_slsi-4ec.h b/drivers/media/video/s5k4ecgx_regs_1_1_slsi-4ec.h
new file mode 100644
index 00000000000..f7542a5861a
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_1_slsi-4ec.h
@@ -0,0 +1,4474 @@
+/* drivers/media/video/s5k4ecgx_regs_1_1_slsi-4ec.h
+ *
+ * Register-sets for Camera module, SLSI-4EC which have sensor S5K4ECGX rev1.1
+ *
+ * Copyright (C) 2012, Insignal Co,. Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5k4ecgx_regset.h"
+
+#if !defined(__S5K4ECGX_V1_1_DEFINE_REGSET__)
+
+#define S5K4ECGX_DEFINE_REGSET(NAME) static const struct s5k4ecgx_reg NAME[]
+#define S5K4ECGX_REGSET_END \
+ { .type = S5K4ECGX_REGTYPE_END, .data_len = 0 }
+#define S5K4ECGX_CMD_WRITE(ADDR, DATA) \
+ { .type = S5K4ECGX_REGTYPE_CMD, .data_len = 4 }
+#define S5K4ECGX_REG_WRITE(ADDR, DATA) \
+ { .type = S5K4ECGX_REGTYPE_WRITE, .data_len = 2, { .addr = ADDR } }
+#define S5K4ECGX_REG_READ(ADDR) \
+ { .type = S5K4ECGX_REGTYPE_READ, .data_len = 1, { .addr = ADDR } }
+#define S5K4ECGX_MDELAY(MSEC) \
+ { .type = S5K4ECGX_REGTYPE_DELAY, .data_len = 1, { .msec = MSEC } }
+
+#elif !defined(__S5K4ECGX_V1_1_DEFINE_REGSET_DATA__)
+
+#define _SWAB16(X) ((X >> 8) & 0xFF), (X & 0xFF)
+#define _DUMMY 0
+#define S5K4ECGX_DEFINE_REGSET(NAME) static const u8 NAME##_data[]
+#define S5K4ECGX_REGSET_END
+#define S5K4ECGX_CMD_WRITE(ADDR, DATA) _SWAB16(ADDR), _SWAB16(DATA)
+#define S5K4ECGX_REG_WRITE(ADDR, DATA) _SWAB16(DATA)
+#define S5K4ECGX_REG_READ(ADDR) _DUMMY
+#define S5K4ECGX_MDELAY(MSEC) _DUMMY
+
+#endif
+
+#if !defined(__S5K4ECGX_V1_1_DEFINE_REGSET__) \
+ || !defined(__S5K4ECGX_V1_1_DEFINE_REGSET_DATA__)
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_init_reg) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_CMD_WRITE(0x0010, 0x0001),
+ S5K4ECGX_CMD_WRITE(0x1030, 0x0000),
+ S5K4ECGX_CMD_WRITE(0x0014, 0x0001),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0xD0001082, 0x01AA), /* d0_d4_cd10 d0_d4_cd10 9:0 */
+ S5K4ECGX_REG_WRITE(0xD0001084, 0x01AA), /* d5_d9_cd10 d5_d9_cd10 9:0 */
+ S5K4ECGX_REG_WRITE(0xD0001086, 0x0055), /* gpio_cd10 gpio_cd10 */
+ S5K4ECGX_REG_WRITE(0xD0001088, 0x01AF), /* clks_output_cd10 clks_output_cd10 11:0 */
+ S5K4ECGX_REG_WRITE(0xD000100E, 0x0000), /* pclk_delay_r */
+
+ S5K4ECGX_REG_WRITE(0xD000007A, 0x0000),
+
+ /* This register is for FACTORY ONLY. If you change it without prior notification */
+ /* YOU are RESPONSIBLE for the FAILURE that will happen in the future. */
+
+ /* ISP FE(ADLC) */
+ S5K4ECGX_REG_WRITE(0xD000E406, 0x0092),
+ S5K4ECGX_REG_WRITE(0xD000E410, 0x3804),
+ S5K4ECGX_REG_WRITE(0xD000E41A, 0x0010), /* 101022 ADD adlcptune_total */
+ S5K4ECGX_REG_WRITE(0xD000E420, 0x0003),
+ S5K4ECGX_REG_WRITE(0xD000E422, 0x0060),
+ S5K4ECGX_REG_WRITE(0xD000E42E, 0x0004),
+ S5K4ECGX_REG_WRITE(0xD000F400, 0x5A3C),
+ S5K4ECGX_REG_WRITE(0xD000F402, 0x0023),
+ S5K4ECGX_REG_WRITE(0xD000F404, 0x8080),
+ S5K4ECGX_REG_WRITE(0xD000F406, 0x03AF),
+ S5K4ECGX_REG_WRITE(0xD000F408, 0x000A),
+ S5K4ECGX_REG_WRITE(0xD000F40A, 0xAA54),
+ S5K4ECGX_REG_WRITE(0xD000F40C, 0x0040),
+ S5K4ECGX_REG_WRITE(0xD000F40E, 0x464E),
+ S5K4ECGX_REG_WRITE(0xD000F410, 0x0240),
+ S5K4ECGX_REG_WRITE(0xD000F412, 0x0240),
+ S5K4ECGX_REG_WRITE(0xD000F414, 0x0040),
+ S5K4ECGX_REG_WRITE(0xD000F416, 0x1000),
+ S5K4ECGX_REG_WRITE(0xD000F418, 0x55FF), /* 555C -> 55FF */
+ S5K4ECGX_REG_WRITE(0xD000F41A, 0xD000),
+ S5K4ECGX_REG_WRITE(0xD000F41C, 0x0010),
+ S5K4ECGX_REG_WRITE(0xD000F41E, 0x0202),
+ S5K4ECGX_REG_WRITE(0xD000F420, 0x0401),
+ S5K4ECGX_REG_WRITE(0xD000F422, 0x0022),
+ S5K4ECGX_REG_WRITE(0xD000F424, 0x0088),
+ S5K4ECGX_REG_WRITE(0xD000F426, 0x009F),
+ S5K4ECGX_REG_WRITE(0xD000F428, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F42A, 0x1800),
+ S5K4ECGX_REG_WRITE(0xD000F42C, 0x0088),
+ S5K4ECGX_REG_WRITE(0xD000F42E, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F430, 0x2428),
+ S5K4ECGX_REG_WRITE(0xD000F432, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F434, 0x03EE),
+ S5K4ECGX_REG_WRITE(0xD000F436, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F438, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F43A, 0x0000),
+ S5K4ECGX_REG_WRITE(0xD000F552, 0x0708),
+ S5K4ECGX_REG_WRITE(0xD000F554, 0x080C),
+
+ /* For subsampling Size */
+ S5K4ECGX_REG_WRITE(0x700018BC, 0x0004),
+ S5K4ECGX_REG_WRITE(0x700018BE, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x700018C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700018C6, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x700018C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018CC, 0x0007),
+ S5K4ECGX_REG_WRITE(0x700018CE, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x700018D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018D4, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018D6, 0x024E),
+ S5K4ECGX_REG_WRITE(0x700018D8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018DC, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018DE, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x700018E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018E4, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018E6, 0x05BA),
+ S5K4ECGX_REG_WRITE(0x700018E8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018EA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018EC, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x700018EE, 0x024F),
+ S5K4ECGX_REG_WRITE(0x700018F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018F8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700018FC, 0x0075),
+ S5K4ECGX_REG_WRITE(0x700018FE, 0x00CF),
+ S5K4ECGX_REG_WRITE(0x70001900, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001902, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001904, 0x0075),
+ S5K4ECGX_REG_WRITE(0x70001906, 0x00D6),
+ S5K4ECGX_REG_WRITE(0x70001908, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000190C, 0x0004),
+ S5K4ECGX_REG_WRITE(0x7000190E, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001910, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001912, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001914, 0x00F0),
+ S5K4ECGX_REG_WRITE(0x70001916, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001918, 0x029E),
+ S5K4ECGX_REG_WRITE(0x7000191A, 0x05B2),
+ S5K4ECGX_REG_WRITE(0x7000191C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000191E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001920, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001922, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001924, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x70001926, 0x0228),
+ S5K4ECGX_REG_WRITE(0x70001928, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000192E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001930, 0x0208),
+ S5K4ECGX_REG_WRITE(0x70001932, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70001934, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001936, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001938, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000193A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000193C, 0x0218),
+ S5K4ECGX_REG_WRITE(0x7000193E, 0x0238),
+ S5K4ECGX_REG_WRITE(0x70001940, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001942, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001944, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001946, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001948, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000194A, 0x0009),
+ S5K4ECGX_REG_WRITE(0x7000194C, 0x00DE),
+ S5K4ECGX_REG_WRITE(0x7000194E, 0x05C0),
+ S5K4ECGX_REG_WRITE(0x70001950, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001952, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001954, 0x00DF),
+ S5K4ECGX_REG_WRITE(0x70001956, 0x00E4),
+ S5K4ECGX_REG_WRITE(0x70001958, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000195A, 0x01FD),
+ S5K4ECGX_REG_WRITE(0x7000195C, 0x05B6),
+ S5K4ECGX_REG_WRITE(0x7000195E, 0x05BB),
+ S5K4ECGX_REG_WRITE(0x70001960, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001962, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001964, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001966, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001968, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000196E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001970, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001972, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001974, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001976, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001978, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000197A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000197C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000197E, 0x0077),
+ S5K4ECGX_REG_WRITE(0x70001980, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001982, 0x024F),
+ S5K4ECGX_REG_WRITE(0x70001984, 0x025E),
+ S5K4ECGX_REG_WRITE(0x70001986, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001988, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000198A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000198C, 0x0000),
+
+ /* For Capture */
+ S5K4ECGX_REG_WRITE(0x7000198E, 0x0004),
+ S5K4ECGX_REG_WRITE(0x70001990, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x70001992, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001994, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001996, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70001998, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x7000199A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000199C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000199E, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019A0, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x700019A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019A6, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019A8, 0x0326),
+ S5K4ECGX_REG_WRITE(0x700019AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019AE, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019B0, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x700019B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019B6, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019B8, 0x09D5),
+ S5K4ECGX_REG_WRITE(0x700019BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019BC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019BE, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019C0, 0x0327),
+ S5K4ECGX_REG_WRITE(0x700019C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019CE, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019D0, 0x0084),
+ S5K4ECGX_REG_WRITE(0x700019D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019D6, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019D8, 0x008D),
+ S5K4ECGX_REG_WRITE(0x700019DA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019DE, 0x0008),
+ S5K4ECGX_REG_WRITE(0x700019E0, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019E2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019E6, 0x00AA),
+ S5K4ECGX_REG_WRITE(0x700019E8, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x700019EA, 0x03AD),
+ S5K4ECGX_REG_WRITE(0x700019EC, 0x09CD),
+ S5K4ECGX_REG_WRITE(0x700019EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019F6, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x700019F8, 0x02DE),
+ S5K4ECGX_REG_WRITE(0x700019FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700019FE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A00, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A02, 0x02BE),
+ S5K4ECGX_REG_WRITE(0x70001A04, 0x02EE),
+ S5K4ECGX_REG_WRITE(0x70001A06, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A08, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A0A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A0C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A0E, 0x02CE),
+ S5K4ECGX_REG_WRITE(0x70001A10, 0x02EE),
+ S5K4ECGX_REG_WRITE(0x70001A12, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A14, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A16, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A18, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A1A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70001A1C, 0x0009),
+ S5K4ECGX_REG_WRITE(0x70001A1E, 0x0095),
+ S5K4ECGX_REG_WRITE(0x70001A20, 0x09DB),
+ S5K4ECGX_REG_WRITE(0x70001A22, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A24, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A26, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001A28, 0x009B),
+ S5K4ECGX_REG_WRITE(0x70001A2A, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x70001A2C, 0x02B3),
+ S5K4ECGX_REG_WRITE(0x70001A2E, 0x09D1),
+ S5K4ECGX_REG_WRITE(0x70001A30, 0x09D6),
+ S5K4ECGX_REG_WRITE(0x70001A32, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A34, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A36, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A38, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A3A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A3C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A3E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A40, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A42, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A44, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A46, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A48, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A4A, 0x02AE),
+ S5K4ECGX_REG_WRITE(0x70001A4C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A4E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A50, 0x0009),
+ S5K4ECGX_REG_WRITE(0x70001A52, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70001A54, 0x0327),
+ S5K4ECGX_REG_WRITE(0x70001A56, 0x0336),
+ S5K4ECGX_REG_WRITE(0x70001A58, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A5A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A5C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001A5E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001AF8, 0x5A3C), /* senHal_TuneStr_AngTuneData1_2_D000F400 register at subsampling */
+
+ S5K4ECGX_REG_WRITE(0x70001896, 0x0002), /* senHal_SamplingType 0002 03EE: PLA setting */
+ S5K4ECGX_REG_WRITE(0x70001898, 0x0000), /* senHal_SamplingMode 0 : 2 PLA / 1 : 4PLA */
+ S5K4ECGX_REG_WRITE(0x7000189A, 0x0003), /* senHal_PLAOption [0] VPLA enable [1] HPLA enable */
+
+ S5K4ECGX_REG_WRITE(0x7000189E, 0x0FB0), /* senHal_ExpMinPixels */
+
+ S5K4ECGX_REG_WRITE(0x700018AC, 0x0060), /* senHal_uAddColsBin */
+ S5K4ECGX_REG_WRITE(0x700018AE, 0x0060), /* senHal_uAddColsNoBin */
+ S5K4ECGX_REG_WRITE(0x700018B0, 0x05C0), /* senHal_uMinColsBin */
+ S5K4ECGX_REG_WRITE(0x700018B2, 0x05C0), /* senHal_uMinColsNoBin */
+
+ S5K4ECGX_REG_WRITE(0x70001AEA, 0x8080), /* senHal_SubF404Tune */
+ S5K4ECGX_REG_WRITE(0x70001AEC, 0x0080), /* senHal_FullF404Tune */
+ S5K4ECGX_REG_WRITE(0x70001AE0, 0x0000), /* senHal_bSenAAC */
+
+ S5K4ECGX_REG_WRITE(0x70001A72, 0x0000), /* senHal_bSRX SRX off */
+ S5K4ECGX_REG_WRITE(0x700018A2, 0x0004), /* senHal_NExpLinesCheckFine extend Forbidden area line */
+ S5K4ECGX_REG_WRITE(0x70001A6A, 0x009A), /* senHal_usForbiddenRightOfs extend right Forbidden area line */
+ S5K4ECGX_REG_WRITE(0x7000385E, 0x024C), /* Mon_Sen_uExpPixelsOfs */
+
+ S5K4ECGX_REG_WRITE(0x70000EE6, 0x0000), /* setot_bUseDigitalHbin */
+ S5K4ECGX_REG_WRITE(0x70001B2A, 0x0300), /* senHal_TuneStr2_usAngTuneGainTh 2 70001B2A */
+ S5K4ECGX_REG_WRITE(0x70001B2C, 0x00D6), /* senHal_TuneStr2_AngTuneF4CA_0_ 2 70001B2C */
+ S5K4ECGX_REG_WRITE(0x70001B2E, 0x008D), /* senHal_TuneStr2_AngTuneF4CA_1_ 2 70001B2E */
+ S5K4ECGX_REG_WRITE(0x70001B30, 0x00CF), /* senHal_TuneStr2_AngTuneF4C2_0_ 2 70001B30 */
+ S5K4ECGX_REG_WRITE(0x70001B32, 0x0084), /* senHal_TuneStr2_AngTuneF4C2_1_ 2 70001B32 */
+
+ /* OTP setting */
+ S5K4ECGX_REG_WRITE(0x70000722, 0x0100), /* skl_OTP_usWaitTime This register should be positioned in fornt of D0001000 */
+ S5K4ECGX_REG_WRITE(0x70000726, 0x0001), /* 0408 0000 //skl_bUseOTPfunc This is OTP on/off function */
+ S5K4ECGX_REG_WRITE(0x700008D6, 0x0001), /* 0408 0000 //ash_bUseOTPData */
+ S5K4ECGX_REG_WRITE(0x7000146E, 0x0000), /* 0408 0001 //awbb_otp_disable */
+ S5K4ECGX_REG_WRITE(0x700008DC, 0x0000), /* ash_bUseGasAlphaOTP */
+
+ /* TnP setting */
+ /* Start of Patch data */
+ S5K4ECGX_REG_WRITE(0x70003AF8, 0xB570), /* 70003AF8 */
+ S5K4ECGX_REG_WRITE(0x70003AFA, 0x4B39), /* 70003AFA */
+ S5K4ECGX_REG_WRITE(0x70003AFC, 0x4939), /* 70003AFC */
+ S5K4ECGX_REG_WRITE(0x70003AFE, 0x483A), /* 70003AFE */
+ S5K4ECGX_REG_WRITE(0x70003B00, 0x2200), /* 70003B00 */
+ S5K4ECGX_REG_WRITE(0x70003B02, 0xC008), /* 70003B02 */
+ S5K4ECGX_REG_WRITE(0x70003B04, 0x6001), /* 70003B04 */
+ S5K4ECGX_REG_WRITE(0x70003B06, 0x4939), /* 70003B06 */
+ S5K4ECGX_REG_WRITE(0x70003B08, 0x4839), /* 70003B08 */
+ S5K4ECGX_REG_WRITE(0x70003B0A, 0x2401), /* 70003B0A */
+ S5K4ECGX_REG_WRITE(0x70003B0C, 0xF000), /* 70003B0C */
+ S5K4ECGX_REG_WRITE(0x70003B0E, 0xFBD4), /* 70003B0E */
+ S5K4ECGX_REG_WRITE(0x70003B10, 0x4938), /* 70003B10 */
+ S5K4ECGX_REG_WRITE(0x70003B12, 0x4839), /* 70003B12 */
+ S5K4ECGX_REG_WRITE(0x70003B14, 0x2502), /* 70003B14 */
+ S5K4ECGX_REG_WRITE(0x70003B16, 0x0022), /* 70003B16 */
+ S5K4ECGX_REG_WRITE(0x70003B18, 0xF000), /* 70003B18 */
+ S5K4ECGX_REG_WRITE(0x70003B1A, 0xFBCE), /* 70003B1A */
+ S5K4ECGX_REG_WRITE(0x70003B1C, 0x4837), /* 70003B1C */
+ S5K4ECGX_REG_WRITE(0x70003B1E, 0x0261), /* 70003B1E */
+ S5K4ECGX_REG_WRITE(0x70003B20, 0x8001), /* 70003B20 */
+ S5K4ECGX_REG_WRITE(0x70003B22, 0x2100), /* 70003B22 */
+ S5K4ECGX_REG_WRITE(0x70003B24, 0x8041), /* 70003B24 */
+ S5K4ECGX_REG_WRITE(0x70003B26, 0x4936), /* 70003B26 */
+ S5K4ECGX_REG_WRITE(0x70003B28, 0x4836), /* 70003B28 */
+ S5K4ECGX_REG_WRITE(0x70003B2A, 0x6041), /* 70003B2A */
+ S5K4ECGX_REG_WRITE(0x70003B2C, 0x4936), /* 70003B2C */
+ S5K4ECGX_REG_WRITE(0x70003B2E, 0x4837), /* 70003B2E */
+ S5K4ECGX_REG_WRITE(0x70003B30, 0x2403), /* 70003B30 */
+ S5K4ECGX_REG_WRITE(0x70003B32, 0x002A), /* 70003B32 */
+ S5K4ECGX_REG_WRITE(0x70003B34, 0xF000), /* 70003B34 */
+ S5K4ECGX_REG_WRITE(0x70003B36, 0xFBC0), /* 70003B36 */
+ S5K4ECGX_REG_WRITE(0x70003B38, 0x4832), /* 70003B38 */
+ S5K4ECGX_REG_WRITE(0x70003B3A, 0x4935), /* 70003B3A */
+ S5K4ECGX_REG_WRITE(0x70003B3C, 0x30C0), /* 70003B3C */
+ S5K4ECGX_REG_WRITE(0x70003B3E, 0x63C1), /* 70003B3E */
+ S5K4ECGX_REG_WRITE(0x70003B40, 0x4930), /* 70003B40 */
+ S5K4ECGX_REG_WRITE(0x70003B42, 0x4834), /* 70003B42 */
+ S5K4ECGX_REG_WRITE(0x70003B44, 0x3980), /* 70003B44 */
+ S5K4ECGX_REG_WRITE(0x70003B46, 0x6408), /* 70003B46 */
+ S5K4ECGX_REG_WRITE(0x70003B48, 0x4833), /* 70003B48 */
+ S5K4ECGX_REG_WRITE(0x70003B4A, 0x4934), /* 70003B4A */
+ S5K4ECGX_REG_WRITE(0x70003B4C, 0x6388), /* 70003B4C */
+ S5K4ECGX_REG_WRITE(0x70003B4E, 0x4934), /* 70003B4E */
+ S5K4ECGX_REG_WRITE(0x70003B50, 0x4834), /* 70003B50 */
+ S5K4ECGX_REG_WRITE(0x70003B52, 0x0022), /* 70003B52 */
+ S5K4ECGX_REG_WRITE(0x70003B54, 0x2504), /* 70003B54 */
+ S5K4ECGX_REG_WRITE(0x70003B56, 0xF000), /* 70003B56 */
+ S5K4ECGX_REG_WRITE(0x70003B58, 0xFBAF), /* 70003B58 */
+ S5K4ECGX_REG_WRITE(0x70003B5A, 0x4933), /* 70003B5A */
+ S5K4ECGX_REG_WRITE(0x70003B5C, 0x4833), /* 70003B5C */
+ S5K4ECGX_REG_WRITE(0x70003B5E, 0x2405), /* 70003B5E */
+ S5K4ECGX_REG_WRITE(0x70003B60, 0x002A), /* 70003B60 */
+ S5K4ECGX_REG_WRITE(0x70003B62, 0xF000), /* 70003B62 */
+ S5K4ECGX_REG_WRITE(0x70003B64, 0xF881), /* 70003B64 */
+ S5K4ECGX_REG_WRITE(0x70003B66, 0x491F), /* 70003B66 */
+ S5K4ECGX_REG_WRITE(0x70003B68, 0x4830), /* 70003B68 */
+ S5K4ECGX_REG_WRITE(0x70003B6A, 0x0022), /* 70003B6A */
+ S5K4ECGX_REG_WRITE(0x70003B6C, 0x2506), /* 70003B6C */
+ S5K4ECGX_REG_WRITE(0x70003B6E, 0x39B6), /* 70003B6E */
+ S5K4ECGX_REG_WRITE(0x70003B70, 0x1D80), /* 70003B70 */
+ S5K4ECGX_REG_WRITE(0x70003B72, 0xF000), /* 70003B72 */
+ S5K4ECGX_REG_WRITE(0x70003B74, 0xF879), /* 70003B74 */
+ S5K4ECGX_REG_WRITE(0x70003B76, 0x482D), /* 70003B76 */
+ S5K4ECGX_REG_WRITE(0x70003B78, 0x492D), /* 70003B78 */
+ S5K4ECGX_REG_WRITE(0x70003B7A, 0x2407), /* 70003B7A */
+ S5K4ECGX_REG_WRITE(0x70003B7C, 0x002A), /* 70003B7C */
+ S5K4ECGX_REG_WRITE(0x70003B7E, 0x300C), /* 70003B7E */
+ S5K4ECGX_REG_WRITE(0x70003B80, 0xF000), /* 70003B80 */
+ S5K4ECGX_REG_WRITE(0x70003B82, 0xF872), /* 70003B82 */
+ S5K4ECGX_REG_WRITE(0x70003B84, 0x4829), /* 70003B84 */
+ S5K4ECGX_REG_WRITE(0x70003B86, 0x492B), /* 70003B86 */
+ S5K4ECGX_REG_WRITE(0x70003B88, 0x0022), /* 70003B88 */
+ S5K4ECGX_REG_WRITE(0x70003B8A, 0x2508), /* 70003B8A */
+ S5K4ECGX_REG_WRITE(0x70003B8C, 0x3010), /* 70003B8C */
+ S5K4ECGX_REG_WRITE(0x70003B8E, 0xF000), /* 70003B8E */
+ S5K4ECGX_REG_WRITE(0x70003B90, 0xF86B), /* 70003B90 */
+ S5K4ECGX_REG_WRITE(0x70003B92, 0x4929), /* 70003B92 */
+ S5K4ECGX_REG_WRITE(0x70003B94, 0x4829), /* 70003B94 */
+ S5K4ECGX_REG_WRITE(0x70003B96, 0x2409), /* 70003B96 */
+ S5K4ECGX_REG_WRITE(0x70003B98, 0x002A), /* 70003B98 */
+ S5K4ECGX_REG_WRITE(0x70003B9A, 0xF000), /* 70003B9A */
+ S5K4ECGX_REG_WRITE(0x70003B9C, 0xFB8D), /* 70003B9C */
+ S5K4ECGX_REG_WRITE(0x70003B9E, 0x4928), /* 70003B9E */
+ S5K4ECGX_REG_WRITE(0x70003BA0, 0x4828), /* 70003BA0 */
+ S5K4ECGX_REG_WRITE(0x70003BA2, 0x0022), /* 70003BA2 */
+ S5K4ECGX_REG_WRITE(0x70003BA4, 0x250A), /* 70003BA4 */
+ S5K4ECGX_REG_WRITE(0x70003BA6, 0xF000), /* 70003BA6 */
+ S5K4ECGX_REG_WRITE(0x70003BA8, 0xFB87), /* 70003BA8 */
+ S5K4ECGX_REG_WRITE(0x70003BAA, 0x4927), /* 70003BAA */
+ S5K4ECGX_REG_WRITE(0x70003BAC, 0x4827), /* 70003BAC */
+ S5K4ECGX_REG_WRITE(0x70003BAE, 0x240B), /* 70003BAE */
+ S5K4ECGX_REG_WRITE(0x70003BB0, 0x002A), /* 70003BB0 */
+ S5K4ECGX_REG_WRITE(0x70003BB2, 0xF000), /* 70003BB2 */
+ S5K4ECGX_REG_WRITE(0x70003BB4, 0xFB81), /* 70003BB4 */
+ S5K4ECGX_REG_WRITE(0x70003BB6, 0x4926), /* 70003BB6 */
+ S5K4ECGX_REG_WRITE(0x70003BB8, 0x4826), /* 70003BB8 */
+ S5K4ECGX_REG_WRITE(0x70003BBA, 0x0022), /* 70003BBA */
+ S5K4ECGX_REG_WRITE(0x70003BBC, 0x250C), /* 70003BBC */
+ S5K4ECGX_REG_WRITE(0x70003BBE, 0xF000), /* 70003BBE */
+ S5K4ECGX_REG_WRITE(0x70003BC0, 0xFB7B), /* 70003BC0 */
+ S5K4ECGX_REG_WRITE(0x70003BC2, 0x4925), /* 70003BC2 */
+ S5K4ECGX_REG_WRITE(0x70003BC4, 0x4825), /* 70003BC4 */
+ S5K4ECGX_REG_WRITE(0x70003BC6, 0x240D), /* 70003BC6 */
+ S5K4ECGX_REG_WRITE(0x70003BC8, 0x002A), /* 70003BC8 */
+ S5K4ECGX_REG_WRITE(0x70003BCA, 0xF000), /* 70003BCA */
+ S5K4ECGX_REG_WRITE(0x70003BCC, 0xFB75), /* 70003BCC */
+ S5K4ECGX_REG_WRITE(0x70003BCE, 0x4924), /* 70003BCE */
+ S5K4ECGX_REG_WRITE(0x70003BD0, 0x4824), /* 70003BD0 */
+ S5K4ECGX_REG_WRITE(0x70003BD2, 0x0022), /* 70003BD2 */
+ S5K4ECGX_REG_WRITE(0x70003BD4, 0xF000), /* 70003BD4 */
+ S5K4ECGX_REG_WRITE(0x70003BD6, 0xFB70), /* 70003BD6 */
+ S5K4ECGX_REG_WRITE(0x70003BD8, 0xBC70), /* 70003BD8 */
+ S5K4ECGX_REG_WRITE(0x70003BDA, 0xBC08), /* 70003BDA */
+ S5K4ECGX_REG_WRITE(0x70003BDC, 0x4718), /* 70003BDC */
+ S5K4ECGX_REG_WRITE(0x70003BDE, 0x0000), /* 70003BDE */
+ S5K4ECGX_REG_WRITE(0x70003BE0, 0x018F), /* 70003BE0 */
+ S5K4ECGX_REG_WRITE(0x70003BE2, 0x4EC2), /* 70003BE2 */
+ S5K4ECGX_REG_WRITE(0x70003BE4, 0x037F), /* 70003BE4 */
+ S5K4ECGX_REG_WRITE(0x70003BE6, 0x0000), /* 70003BE6 */
+ S5K4ECGX_REG_WRITE(0x70003BE8, 0x1F90), /* 70003BE8 */
+ S5K4ECGX_REG_WRITE(0x70003BEA, 0x7000), /* 70003BEA */
+ S5K4ECGX_REG_WRITE(0x70003BEC, 0x3C81), /* 70003BEC */
+ S5K4ECGX_REG_WRITE(0x70003BEE, 0x7000), /* 70003BEE */
+ S5K4ECGX_REG_WRITE(0x70003BF0, 0xE38B), /* 70003BF0 */
+ S5K4ECGX_REG_WRITE(0x70003BF2, 0x0000), /* 70003BF2 */
+ S5K4ECGX_REG_WRITE(0x70003BF4, 0x3CB9), /* 70003BF4 */
+ S5K4ECGX_REG_WRITE(0x70003BF6, 0x7000), /* 70003BF6 */
+ S5K4ECGX_REG_WRITE(0x70003BF8, 0xC3B1), /* 70003BF8 */
+ S5K4ECGX_REG_WRITE(0x70003BFA, 0x0000), /* 70003BFA */
+ S5K4ECGX_REG_WRITE(0x70003BFC, 0x4780), /* 70003BFC */
+ S5K4ECGX_REG_WRITE(0x70003BFE, 0x7000), /* 70003BFE */
+ S5K4ECGX_REG_WRITE(0x70003C00, 0x3D17), /* 70003C00 */
+ S5K4ECGX_REG_WRITE(0x70003C02, 0x7000), /* 70003C02 */
+ S5K4ECGX_REG_WRITE(0x70003C04, 0x0080), /* 70003C04 */
+ S5K4ECGX_REG_WRITE(0x70003C06, 0x7000), /* 70003C06 */
+ S5K4ECGX_REG_WRITE(0x70003C08, 0x3D53), /* 70003C08 */
+ S5K4ECGX_REG_WRITE(0x70003C0A, 0x7000), /* 70003C0A */
+ S5K4ECGX_REG_WRITE(0x70003C0C, 0xB49D), /* 70003C0C */
+ S5K4ECGX_REG_WRITE(0x70003C0E, 0x0000), /* 70003C0E */
+ S5K4ECGX_REG_WRITE(0x70003C10, 0x3DFF), /* 70003C10 */
+ S5K4ECGX_REG_WRITE(0x70003C12, 0x7000), /* 70003C12 */
+ S5K4ECGX_REG_WRITE(0x70003C14, 0x3DB3), /* 70003C14 */
+ S5K4ECGX_REG_WRITE(0x70003C16, 0x7000), /* 70003C16 */
+ S5K4ECGX_REG_WRITE(0x70003C18, 0xFFFF), /* 70003C18 */
+ S5K4ECGX_REG_WRITE(0x70003C1A, 0x00FF), /* 70003C1A */
+ S5K4ECGX_REG_WRITE(0x70003C1C, 0x17E0), /* 70003C1C */
+ S5K4ECGX_REG_WRITE(0x70003C1E, 0x7000), /* 70003C1E */
+ S5K4ECGX_REG_WRITE(0x70003C20, 0x3F7B), /* 70003C20 */
+ S5K4ECGX_REG_WRITE(0x70003C22, 0x7000), /* 70003C22 */
+ S5K4ECGX_REG_WRITE(0x70003C24, 0x053D), /* 70003C24 */
+ S5K4ECGX_REG_WRITE(0x70003C26, 0x0000), /* 70003C26 */
+ S5K4ECGX_REG_WRITE(0x70003C28, 0x0000), /* 70003C28 */
+ S5K4ECGX_REG_WRITE(0x70003C2A, 0x0A89), /* 70003C2A */
+ S5K4ECGX_REG_WRITE(0x70003C2C, 0x6CD2), /* 70003C2C */
+ S5K4ECGX_REG_WRITE(0x70003C2E, 0x0000), /* 70003C2E */
+ S5K4ECGX_REG_WRITE(0x70003C30, 0x0000), /* 70003C30 */
+ S5K4ECGX_REG_WRITE(0x70003C32, 0x0A9A), /* 70003C32 */
+ S5K4ECGX_REG_WRITE(0x70003C34, 0x0000), /* 70003C34 */
+ S5K4ECGX_REG_WRITE(0x70003C36, 0x02D2), /* 70003C36 */
+ S5K4ECGX_REG_WRITE(0x70003C38, 0x3FC9), /* 70003C38 */
+ S5K4ECGX_REG_WRITE(0x70003C3A, 0x7000), /* 70003C3A */
+ S5K4ECGX_REG_WRITE(0x70003C3C, 0x9E65), /* 70003C3C */
+ S5K4ECGX_REG_WRITE(0x70003C3E, 0x0000), /* 70003C3E */
+ S5K4ECGX_REG_WRITE(0x70003C40, 0x403D), /* 70003C40 */
+ S5K4ECGX_REG_WRITE(0x70003C42, 0x7000), /* 70003C42 */
+ S5K4ECGX_REG_WRITE(0x70003C44, 0x7C49), /* 70003C44 */
+ S5K4ECGX_REG_WRITE(0x70003C46, 0x0000), /* 70003C46 */
+ S5K4ECGX_REG_WRITE(0x70003C48, 0x40B1), /* 70003C48 */
+ S5K4ECGX_REG_WRITE(0x70003C4A, 0x7000), /* 70003C4A */
+ S5K4ECGX_REG_WRITE(0x70003C4C, 0x7C63), /* 70003C4C */
+ S5K4ECGX_REG_WRITE(0x70003C4E, 0x0000), /* 70003C4E */
+ S5K4ECGX_REG_WRITE(0x70003C50, 0x40CD), /* 70003C50 */
+ S5K4ECGX_REG_WRITE(0x70003C52, 0x7000), /* 70003C52 */
+ S5K4ECGX_REG_WRITE(0x70003C54, 0x8F01), /* 70003C54 */
+ S5K4ECGX_REG_WRITE(0x70003C56, 0x0000), /* 70003C56 */
+ S5K4ECGX_REG_WRITE(0x70003C58, 0x416F), /* 70003C58 */
+ S5K4ECGX_REG_WRITE(0x70003C5A, 0x7000), /* 70003C5A */
+ S5K4ECGX_REG_WRITE(0x70003C5C, 0x7F3F), /* 70003C5C */
+ S5K4ECGX_REG_WRITE(0x70003C5E, 0x0000), /* 70003C5E */
+ S5K4ECGX_REG_WRITE(0x70003C60, 0x41FD), /* 70003C60 */
+ S5K4ECGX_REG_WRITE(0x70003C62, 0x7000), /* 70003C62 */
+ S5K4ECGX_REG_WRITE(0x70003C64, 0x98C5), /* 70003C64 */
+ S5K4ECGX_REG_WRITE(0x70003C66, 0x0000), /* 70003C66 */
+ S5K4ECGX_REG_WRITE(0x70003C68, 0xB570), /* 70003C68 */
+ S5K4ECGX_REG_WRITE(0x70003C6A, 0x000C), /* 70003C6A */
+ S5K4ECGX_REG_WRITE(0x70003C6C, 0x0015), /* 70003C6C */
+ S5K4ECGX_REG_WRITE(0x70003C6E, 0x0029), /* 70003C6E */
+ S5K4ECGX_REG_WRITE(0x70003C70, 0xF000), /* 70003C70 */
+ S5K4ECGX_REG_WRITE(0x70003C72, 0xFB2A), /* 70003C72 */
+ S5K4ECGX_REG_WRITE(0x70003C74, 0x49F8), /* 70003C74 */
+ S5K4ECGX_REG_WRITE(0x70003C76, 0x00A8), /* 70003C76 */
+ S5K4ECGX_REG_WRITE(0x70003C78, 0x500C), /* 70003C78 */
+ S5K4ECGX_REG_WRITE(0x70003C7A, 0xBC70), /* 70003C7A */
+ S5K4ECGX_REG_WRITE(0x70003C7C, 0xBC08), /* 70003C7C */
+ S5K4ECGX_REG_WRITE(0x70003C7E, 0x4718), /* 70003C7E */
+ S5K4ECGX_REG_WRITE(0x70003C80, 0x6808), /* 70003C80 */
+ S5K4ECGX_REG_WRITE(0x70003C82, 0x0400), /* 70003C82 */
+ S5K4ECGX_REG_WRITE(0x70003C84, 0x0C00), /* 70003C84 */
+ S5K4ECGX_REG_WRITE(0x70003C86, 0x6849), /* 70003C86 */
+ S5K4ECGX_REG_WRITE(0x70003C88, 0x0409), /* 70003C88 */
+ S5K4ECGX_REG_WRITE(0x70003C8A, 0x0C09), /* 70003C8A */
+ S5K4ECGX_REG_WRITE(0x70003C8C, 0x4AF3), /* 70003C8C */
+ S5K4ECGX_REG_WRITE(0x70003C8E, 0x8992), /* 70003C8E */
+ S5K4ECGX_REG_WRITE(0x70003C90, 0x2A00), /* 70003C90 */
+ S5K4ECGX_REG_WRITE(0x70003C92, 0xD00D), /* 70003C92 */
+ S5K4ECGX_REG_WRITE(0x70003C94, 0x2300), /* 70003C94 */
+ S5K4ECGX_REG_WRITE(0x70003C96, 0x1A89), /* 70003C96 */
+ S5K4ECGX_REG_WRITE(0x70003C98, 0xD400), /* 70003C98 */
+ S5K4ECGX_REG_WRITE(0x70003C9A, 0x000B), /* 70003C9A */
+ S5K4ECGX_REG_WRITE(0x70003C9C, 0x0419), /* 70003C9C */
+ S5K4ECGX_REG_WRITE(0x70003C9E, 0x0C09), /* 70003C9E */
+ S5K4ECGX_REG_WRITE(0x70003CA0, 0x23FF), /* 70003CA0 */
+ S5K4ECGX_REG_WRITE(0x70003CA2, 0x33C1), /* 70003CA2 */
+ S5K4ECGX_REG_WRITE(0x70003CA4, 0x1810), /* 70003CA4 */
+ S5K4ECGX_REG_WRITE(0x70003CA6, 0x4298), /* 70003CA6 */
+ S5K4ECGX_REG_WRITE(0x70003CA8, 0xD800), /* 70003CA8 */
+ S5K4ECGX_REG_WRITE(0x70003CAA, 0x0003), /* 70003CAA */
+ S5K4ECGX_REG_WRITE(0x70003CAC, 0x0418), /* 70003CAC */
+ S5K4ECGX_REG_WRITE(0x70003CAE, 0x0C00), /* 70003CAE */
+ S5K4ECGX_REG_WRITE(0x70003CB0, 0x4AEB), /* 70003CB0 */
+ S5K4ECGX_REG_WRITE(0x70003CB2, 0x8150), /* 70003CB2 */
+ S5K4ECGX_REG_WRITE(0x70003CB4, 0x8191), /* 70003CB4 */
+ S5K4ECGX_REG_WRITE(0x70003CB6, 0x4770), /* 70003CB6 */
+ S5K4ECGX_REG_WRITE(0x70003CB8, 0xB5F3), /* 70003CB8 */
+ S5K4ECGX_REG_WRITE(0x70003CBA, 0x0004), /* 70003CBA */
+ S5K4ECGX_REG_WRITE(0x70003CBC, 0xB081), /* 70003CBC */
+ S5K4ECGX_REG_WRITE(0x70003CBE, 0x9802), /* 70003CBE */
+ S5K4ECGX_REG_WRITE(0x70003CC0, 0x6800), /* 70003CC0 */
+ S5K4ECGX_REG_WRITE(0x70003CC2, 0x0600), /* 70003CC2 */
+ S5K4ECGX_REG_WRITE(0x70003CC4, 0x0E00), /* 70003CC4 */
+ S5K4ECGX_REG_WRITE(0x70003CC6, 0x2201), /* 70003CC6 */
+ S5K4ECGX_REG_WRITE(0x70003CC8, 0x0015), /* 70003CC8 */
+ S5K4ECGX_REG_WRITE(0x70003CCA, 0x0021), /* 70003CCA */
+ S5K4ECGX_REG_WRITE(0x70003CCC, 0x3910), /* 70003CCC */
+ S5K4ECGX_REG_WRITE(0x70003CCE, 0x408A), /* 70003CCE */
+ S5K4ECGX_REG_WRITE(0x70003CD0, 0x40A5), /* 70003CD0 */
+ S5K4ECGX_REG_WRITE(0x70003CD2, 0x4FE4), /* 70003CD2 */
+ S5K4ECGX_REG_WRITE(0x70003CD4, 0x0016), /* 70003CD4 */
+ S5K4ECGX_REG_WRITE(0x70003CD6, 0x2C10), /* 70003CD6 */
+ S5K4ECGX_REG_WRITE(0x70003CD8, 0xDA03), /* 70003CD8 */
+ S5K4ECGX_REG_WRITE(0x70003CDA, 0x8839), /* 70003CDA */
+ S5K4ECGX_REG_WRITE(0x70003CDC, 0x43A9), /* 70003CDC */
+ S5K4ECGX_REG_WRITE(0x70003CDE, 0x8039), /* 70003CDE */
+ S5K4ECGX_REG_WRITE(0x70003CE0, 0xE002), /* 70003CE0 */
+ S5K4ECGX_REG_WRITE(0x70003CE2, 0x8879), /* 70003CE2 */
+ S5K4ECGX_REG_WRITE(0x70003CE4, 0x43B1), /* 70003CE4 */
+ S5K4ECGX_REG_WRITE(0x70003CE6, 0x8079), /* 70003CE6 */
+ S5K4ECGX_REG_WRITE(0x70003CE8, 0xF000), /* 70003CE8 */
+ S5K4ECGX_REG_WRITE(0x70003CEA, 0xFAF6), /* 70003CEA */
+ S5K4ECGX_REG_WRITE(0x70003CEC, 0x2C10), /* 70003CEC */
+ S5K4ECGX_REG_WRITE(0x70003CEE, 0xDA03), /* 70003CEE */
+ S5K4ECGX_REG_WRITE(0x70003CF0, 0x8839), /* 70003CF0 */
+ S5K4ECGX_REG_WRITE(0x70003CF2, 0x4329), /* 70003CF2 */
+ S5K4ECGX_REG_WRITE(0x70003CF4, 0x8039), /* 70003CF4 */
+ S5K4ECGX_REG_WRITE(0x70003CF6, 0xE002), /* 70003CF6 */
+ S5K4ECGX_REG_WRITE(0x70003CF8, 0x8879), /* 70003CF8 */
+ S5K4ECGX_REG_WRITE(0x70003CFA, 0x4331), /* 70003CFA */
+ S5K4ECGX_REG_WRITE(0x70003CFC, 0x8079), /* 70003CFC */
+ S5K4ECGX_REG_WRITE(0x70003CFE, 0x49DA), /* 70003CFE */
+ S5K4ECGX_REG_WRITE(0x70003D00, 0x8809), /* 70003D00 */
+ S5K4ECGX_REG_WRITE(0x70003D02, 0x2900), /* 70003D02 */
+ S5K4ECGX_REG_WRITE(0x70003D04, 0xD102), /* 70003D04 */
+ S5K4ECGX_REG_WRITE(0x70003D06, 0xF000), /* 70003D06 */
+ S5K4ECGX_REG_WRITE(0x70003D08, 0xFAEF), /* 70003D08 */
+ S5K4ECGX_REG_WRITE(0x70003D0A, 0x2000), /* 70003D0A */
+ S5K4ECGX_REG_WRITE(0x70003D0C, 0x9902), /* 70003D0C */
+ S5K4ECGX_REG_WRITE(0x70003D0E, 0x6008), /* 70003D0E */
+ S5K4ECGX_REG_WRITE(0x70003D10, 0xBCFE), /* 70003D10 */
+ S5K4ECGX_REG_WRITE(0x70003D12, 0xBC08), /* 70003D12 */
+ S5K4ECGX_REG_WRITE(0x70003D14, 0x4718), /* 70003D14 */
+ S5K4ECGX_REG_WRITE(0x70003D16, 0xB538), /* 70003D16 */
+ S5K4ECGX_REG_WRITE(0x70003D18, 0x9C04), /* 70003D18 */
+ S5K4ECGX_REG_WRITE(0x70003D1A, 0x0015), /* 70003D1A */
+ S5K4ECGX_REG_WRITE(0x70003D1C, 0x002A), /* 70003D1C */
+ S5K4ECGX_REG_WRITE(0x70003D1E, 0x9400), /* 70003D1E */
+ S5K4ECGX_REG_WRITE(0x70003D20, 0xF000), /* 70003D20 */
+ S5K4ECGX_REG_WRITE(0x70003D22, 0xFAEA), /* 70003D22 */
+ S5K4ECGX_REG_WRITE(0x70003D24, 0x4AD1), /* 70003D24 */
+ S5K4ECGX_REG_WRITE(0x70003D26, 0x8811), /* 70003D26 */
+ S5K4ECGX_REG_WRITE(0x70003D28, 0x2900), /* 70003D28 */
+ S5K4ECGX_REG_WRITE(0x70003D2A, 0xD00F), /* 70003D2A */
+ S5K4ECGX_REG_WRITE(0x70003D2C, 0x8820), /* 70003D2C */
+ S5K4ECGX_REG_WRITE(0x70003D2E, 0x4281), /* 70003D2E */
+ S5K4ECGX_REG_WRITE(0x70003D30, 0xD20C), /* 70003D30 */
+ S5K4ECGX_REG_WRITE(0x70003D32, 0x8861), /* 70003D32 */
+ S5K4ECGX_REG_WRITE(0x70003D34, 0x8853), /* 70003D34 */
+ S5K4ECGX_REG_WRITE(0x70003D36, 0x4299), /* 70003D36 */
+ S5K4ECGX_REG_WRITE(0x70003D38, 0xD200), /* 70003D38 */
+ S5K4ECGX_REG_WRITE(0x70003D3A, 0x1E40), /* 70003D3A */
+ S5K4ECGX_REG_WRITE(0x70003D3C, 0x0400), /* 70003D3C */
+ S5K4ECGX_REG_WRITE(0x70003D3E, 0x0C00), /* 70003D3E */
+ S5K4ECGX_REG_WRITE(0x70003D40, 0x8020), /* 70003D40 */
+ S5K4ECGX_REG_WRITE(0x70003D42, 0x8851), /* 70003D42 */
+ S5K4ECGX_REG_WRITE(0x70003D44, 0x8061), /* 70003D44 */
+ S5K4ECGX_REG_WRITE(0x70003D46, 0x4368), /* 70003D46 */
+ S5K4ECGX_REG_WRITE(0x70003D48, 0x1840), /* 70003D48 */
+ S5K4ECGX_REG_WRITE(0x70003D4A, 0x6060), /* 70003D4A */
+ S5K4ECGX_REG_WRITE(0x70003D4C, 0xBC38), /* 70003D4C */
+ S5K4ECGX_REG_WRITE(0x70003D4E, 0xBC08), /* 70003D4E */
+ S5K4ECGX_REG_WRITE(0x70003D50, 0x4718), /* 70003D50 */
+ S5K4ECGX_REG_WRITE(0x70003D52, 0xB5F8), /* 70003D52 */
+ S5K4ECGX_REG_WRITE(0x70003D54, 0x0004), /* 70003D54 */
+ S5K4ECGX_REG_WRITE(0x70003D56, 0x6808), /* 70003D56 */
+ S5K4ECGX_REG_WRITE(0x70003D58, 0x0400), /* 70003D58 */
+ S5K4ECGX_REG_WRITE(0x70003D5A, 0x0C00), /* 70003D5A */
+ S5K4ECGX_REG_WRITE(0x70003D5C, 0x2201), /* 70003D5C */
+ S5K4ECGX_REG_WRITE(0x70003D5E, 0x0015), /* 70003D5E */
+ S5K4ECGX_REG_WRITE(0x70003D60, 0x0021), /* 70003D60 */
+ S5K4ECGX_REG_WRITE(0x70003D62, 0x3910), /* 70003D62 */
+ S5K4ECGX_REG_WRITE(0x70003D64, 0x408A), /* 70003D64 */
+ S5K4ECGX_REG_WRITE(0x70003D66, 0x40A5), /* 70003D66 */
+ S5K4ECGX_REG_WRITE(0x70003D68, 0x4FBE), /* 70003D68 */
+ S5K4ECGX_REG_WRITE(0x70003D6A, 0x0016), /* 70003D6A */
+ S5K4ECGX_REG_WRITE(0x70003D6C, 0x2C10), /* 70003D6C */
+ S5K4ECGX_REG_WRITE(0x70003D6E, 0xDA03), /* 70003D6E */
+ S5K4ECGX_REG_WRITE(0x70003D70, 0x8839), /* 70003D70 */
+ S5K4ECGX_REG_WRITE(0x70003D72, 0x43A9), /* 70003D72 */
+ S5K4ECGX_REG_WRITE(0x70003D74, 0x8039), /* 70003D74 */
+ S5K4ECGX_REG_WRITE(0x70003D76, 0xE002), /* 70003D76 */
+ S5K4ECGX_REG_WRITE(0x70003D78, 0x8879), /* 70003D78 */
+ S5K4ECGX_REG_WRITE(0x70003D7A, 0x43B1), /* 70003D7A */
+ S5K4ECGX_REG_WRITE(0x70003D7C, 0x8079), /* 70003D7C */
+ S5K4ECGX_REG_WRITE(0x70003D7E, 0xF000), /* 70003D7E */
+ S5K4ECGX_REG_WRITE(0x70003D80, 0xFAC3), /* 70003D80 */
+ S5K4ECGX_REG_WRITE(0x70003D82, 0x2C10), /* 70003D82 */
+ S5K4ECGX_REG_WRITE(0x70003D84, 0xDA03), /* 70003D84 */
+ S5K4ECGX_REG_WRITE(0x70003D86, 0x8838), /* 70003D86 */
+ S5K4ECGX_REG_WRITE(0x70003D88, 0x4328), /* 70003D88 */
+ S5K4ECGX_REG_WRITE(0x70003D8A, 0x8038), /* 70003D8A */
+ S5K4ECGX_REG_WRITE(0x70003D8C, 0xE002), /* 70003D8C */
+ S5K4ECGX_REG_WRITE(0x70003D8E, 0x8878), /* 70003D8E */
+ S5K4ECGX_REG_WRITE(0x70003D90, 0x4330), /* 70003D90 */
+ S5K4ECGX_REG_WRITE(0x70003D92, 0x8078), /* 70003D92 */
+ S5K4ECGX_REG_WRITE(0x70003D94, 0x48B6), /* 70003D94 */
+ S5K4ECGX_REG_WRITE(0x70003D96, 0x8800), /* 70003D96 */
+ S5K4ECGX_REG_WRITE(0x70003D98, 0x0400), /* 70003D98 */
+ S5K4ECGX_REG_WRITE(0x70003D9A, 0xD507), /* 70003D9A */
+ S5K4ECGX_REG_WRITE(0x70003D9C, 0x4BB5), /* 70003D9C */
+ S5K4ECGX_REG_WRITE(0x70003D9E, 0x7819), /* 70003D9E */
+ S5K4ECGX_REG_WRITE(0x70003DA0, 0x4AB5), /* 70003DA0 */
+ S5K4ECGX_REG_WRITE(0x70003DA2, 0x7810), /* 70003DA2 */
+ S5K4ECGX_REG_WRITE(0x70003DA4, 0x7018), /* 70003DA4 */
+ S5K4ECGX_REG_WRITE(0x70003DA6, 0x7011), /* 70003DA6 */
+ S5K4ECGX_REG_WRITE(0x70003DA8, 0x49B4), /* 70003DA8 */
+ S5K4ECGX_REG_WRITE(0x70003DAA, 0x8188), /* 70003DAA */
+ S5K4ECGX_REG_WRITE(0x70003DAC, 0xBCF8), /* 70003DAC */
+ S5K4ECGX_REG_WRITE(0x70003DAE, 0xBC08), /* 70003DAE */
+ S5K4ECGX_REG_WRITE(0x70003DB0, 0x4718), /* 70003DB0 */
+ S5K4ECGX_REG_WRITE(0x70003DB2, 0xB538), /* 70003DB2 */
+ S5K4ECGX_REG_WRITE(0x70003DB4, 0x48B2), /* 70003DB4 */
+ S5K4ECGX_REG_WRITE(0x70003DB6, 0x4669), /* 70003DB6 */
+ S5K4ECGX_REG_WRITE(0x70003DB8, 0xF000), /* 70003DB8 */
+ S5K4ECGX_REG_WRITE(0x70003DBA, 0xFAAE), /* 70003DBA */
+ S5K4ECGX_REG_WRITE(0x70003DBC, 0x48B1), /* 70003DBC */
+ S5K4ECGX_REG_WRITE(0x70003DBE, 0x49B0), /* 70003DBE */
+ S5K4ECGX_REG_WRITE(0x70003DC0, 0x69C2), /* 70003DC0 */
+ S5K4ECGX_REG_WRITE(0x70003DC2, 0x2400), /* 70003DC2 */
+ S5K4ECGX_REG_WRITE(0x70003DC4, 0x31A8), /* 70003DC4 */
+ S5K4ECGX_REG_WRITE(0x70003DC6, 0x2A00), /* 70003DC6 */
+ S5K4ECGX_REG_WRITE(0x70003DC8, 0xD008), /* 70003DC8 */
+ S5K4ECGX_REG_WRITE(0x70003DCA, 0x61C4), /* 70003DCA */
+ S5K4ECGX_REG_WRITE(0x70003DCC, 0x684A), /* 70003DCC */
+ S5K4ECGX_REG_WRITE(0x70003DCE, 0x6242), /* 70003DCE */
+ S5K4ECGX_REG_WRITE(0x70003DD0, 0x6282), /* 70003DD0 */
+ S5K4ECGX_REG_WRITE(0x70003DD2, 0x466B), /* 70003DD2 */
+ S5K4ECGX_REG_WRITE(0x70003DD4, 0x881A), /* 70003DD4 */
+ S5K4ECGX_REG_WRITE(0x70003DD6, 0x6302), /* 70003DD6 */
+ S5K4ECGX_REG_WRITE(0x70003DD8, 0x885A), /* 70003DD8 */
+ S5K4ECGX_REG_WRITE(0x70003DDA, 0x6342), /* 70003DDA */
+ S5K4ECGX_REG_WRITE(0x70003DDC, 0x6A02), /* 70003DDC */
+ S5K4ECGX_REG_WRITE(0x70003DDE, 0x2A00), /* 70003DDE */
+ S5K4ECGX_REG_WRITE(0x70003DE0, 0xD00A), /* 70003DE0 */
+ S5K4ECGX_REG_WRITE(0x70003DE2, 0x6204), /* 70003DE2 */
+ S5K4ECGX_REG_WRITE(0x70003DE4, 0x6849), /* 70003DE4 */
+ S5K4ECGX_REG_WRITE(0x70003DE6, 0x6281), /* 70003DE6 */
+ S5K4ECGX_REG_WRITE(0x70003DE8, 0x466B), /* 70003DE8 */
+ S5K4ECGX_REG_WRITE(0x70003DEA, 0x8819), /* 70003DEA */
+ S5K4ECGX_REG_WRITE(0x70003DEC, 0x6301), /* 70003DEC */
+ S5K4ECGX_REG_WRITE(0x70003DEE, 0x8859), /* 70003DEE */
+ S5K4ECGX_REG_WRITE(0x70003DF0, 0x6341), /* 70003DF0 */
+ S5K4ECGX_REG_WRITE(0x70003DF2, 0x49A5), /* 70003DF2 */
+ S5K4ECGX_REG_WRITE(0x70003DF4, 0x88C9), /* 70003DF4 */
+ S5K4ECGX_REG_WRITE(0x70003DF6, 0x63C1), /* 70003DF6 */
+ S5K4ECGX_REG_WRITE(0x70003DF8, 0xF000), /* 70003DF8 */
+ S5K4ECGX_REG_WRITE(0x70003DFA, 0xFA96), /* 70003DFA */
+ S5K4ECGX_REG_WRITE(0x70003DFC, 0xE7A6), /* 70003DFC */
+ S5K4ECGX_REG_WRITE(0x70003DFE, 0xB5F0), /* 70003DFE */
+ S5K4ECGX_REG_WRITE(0x70003E00, 0xB08B), /* 70003E00 */
+ S5K4ECGX_REG_WRITE(0x70003E02, 0x20FF), /* 70003E02 */
+ S5K4ECGX_REG_WRITE(0x70003E04, 0x1C40), /* 70003E04 */
+ S5K4ECGX_REG_WRITE(0x70003E06, 0x49A1), /* 70003E06 */
+ S5K4ECGX_REG_WRITE(0x70003E08, 0x89CC), /* 70003E08 */
+ S5K4ECGX_REG_WRITE(0x70003E0A, 0x4E9E), /* 70003E0A */
+ S5K4ECGX_REG_WRITE(0x70003E0C, 0x6AB1), /* 70003E0C */
+ S5K4ECGX_REG_WRITE(0x70003E0E, 0x4284), /* 70003E0E */
+ S5K4ECGX_REG_WRITE(0x70003E10, 0xD101), /* 70003E10 */
+ S5K4ECGX_REG_WRITE(0x70003E12, 0x489F), /* 70003E12 */
+ S5K4ECGX_REG_WRITE(0x70003E14, 0x6081), /* 70003E14 */
+ S5K4ECGX_REG_WRITE(0x70003E16, 0x6A70), /* 70003E16 */
+ S5K4ECGX_REG_WRITE(0x70003E18, 0x0200), /* 70003E18 */
+ S5K4ECGX_REG_WRITE(0x70003E1A, 0xF000), /* 70003E1A */
+ S5K4ECGX_REG_WRITE(0x70003E1C, 0xFA8D), /* 70003E1C */
+ S5K4ECGX_REG_WRITE(0x70003E1E, 0x0400), /* 70003E1E */
+ S5K4ECGX_REG_WRITE(0x70003E20, 0x0C00), /* 70003E20 */
+ S5K4ECGX_REG_WRITE(0x70003E22, 0x4A96), /* 70003E22 */
+ S5K4ECGX_REG_WRITE(0x70003E24, 0x8A11), /* 70003E24 */
+ S5K4ECGX_REG_WRITE(0x70003E26, 0x9109), /* 70003E26 */
+ S5K4ECGX_REG_WRITE(0x70003E28, 0x2101), /* 70003E28 */
+ S5K4ECGX_REG_WRITE(0x70003E2A, 0x0349), /* 70003E2A */
+ S5K4ECGX_REG_WRITE(0x70003E2C, 0x4288), /* 70003E2C */
+ S5K4ECGX_REG_WRITE(0x70003E2E, 0xD200), /* 70003E2E */
+ S5K4ECGX_REG_WRITE(0x70003E30, 0x0001), /* 70003E30 */
+ S5K4ECGX_REG_WRITE(0x70003E32, 0x4A92), /* 70003E32 */
+ S5K4ECGX_REG_WRITE(0x70003E34, 0x8211), /* 70003E34 */
+ S5K4ECGX_REG_WRITE(0x70003E36, 0x4D97), /* 70003E36 */
+ S5K4ECGX_REG_WRITE(0x70003E38, 0x8829), /* 70003E38 */
+ S5K4ECGX_REG_WRITE(0x70003E3A, 0x9108), /* 70003E3A */
+ S5K4ECGX_REG_WRITE(0x70003E3C, 0x4A8B), /* 70003E3C */
+ S5K4ECGX_REG_WRITE(0x70003E3E, 0x2303), /* 70003E3E */
+ S5K4ECGX_REG_WRITE(0x70003E40, 0x3222), /* 70003E40 */
+ S5K4ECGX_REG_WRITE(0x70003E42, 0x1F91), /* 70003E42 */
+ S5K4ECGX_REG_WRITE(0x70003E44, 0xF000), /* 70003E44 */
+ S5K4ECGX_REG_WRITE(0x70003E46, 0xFA7E), /* 70003E46 */
+ S5K4ECGX_REG_WRITE(0x70003E48, 0x8028), /* 70003E48 */
+ S5K4ECGX_REG_WRITE(0x70003E4A, 0x488E), /* 70003E4A */
+ S5K4ECGX_REG_WRITE(0x70003E4C, 0x4987), /* 70003E4C */
+ S5K4ECGX_REG_WRITE(0x70003E4E, 0x6BC2), /* 70003E4E */
+ S5K4ECGX_REG_WRITE(0x70003E50, 0x6AC0), /* 70003E50 */
+ S5K4ECGX_REG_WRITE(0x70003E52, 0x4282), /* 70003E52 */
+ S5K4ECGX_REG_WRITE(0x70003E54, 0xD201), /* 70003E54 */
+ S5K4ECGX_REG_WRITE(0x70003E56, 0x8CC8), /* 70003E56 */
+ S5K4ECGX_REG_WRITE(0x70003E58, 0x8028), /* 70003E58 */
+ S5K4ECGX_REG_WRITE(0x70003E5A, 0x88E8), /* 70003E5A */
+ S5K4ECGX_REG_WRITE(0x70003E5C, 0x9007), /* 70003E5C */
+ S5K4ECGX_REG_WRITE(0x70003E5E, 0x2240), /* 70003E5E */
+ S5K4ECGX_REG_WRITE(0x70003E60, 0x4310), /* 70003E60 */
+ S5K4ECGX_REG_WRITE(0x70003E62, 0x80E8), /* 70003E62 */
+ S5K4ECGX_REG_WRITE(0x70003E64, 0x2000), /* 70003E64 */
+ S5K4ECGX_REG_WRITE(0x70003E66, 0x0041), /* 70003E66 */
+ S5K4ECGX_REG_WRITE(0x70003E68, 0x194B), /* 70003E68 */
+ S5K4ECGX_REG_WRITE(0x70003E6A, 0x001E), /* 70003E6A */
+ S5K4ECGX_REG_WRITE(0x70003E6C, 0x3680), /* 70003E6C */
+ S5K4ECGX_REG_WRITE(0x70003E6E, 0x8BB2), /* 70003E6E */
+ S5K4ECGX_REG_WRITE(0x70003E70, 0xAF04), /* 70003E70 */
+ S5K4ECGX_REG_WRITE(0x70003E72, 0x527A), /* 70003E72 */
+ S5K4ECGX_REG_WRITE(0x70003E74, 0x4A7D), /* 70003E74 */
+ S5K4ECGX_REG_WRITE(0x70003E76, 0x188A), /* 70003E76 */
+ S5K4ECGX_REG_WRITE(0x70003E78, 0x8897), /* 70003E78 */
+ S5K4ECGX_REG_WRITE(0x70003E7A, 0x83B7), /* 70003E7A */
+ S5K4ECGX_REG_WRITE(0x70003E7C, 0x33A0), /* 70003E7C */
+ S5K4ECGX_REG_WRITE(0x70003E7E, 0x891F), /* 70003E7E */
+ S5K4ECGX_REG_WRITE(0x70003E80, 0xAE01), /* 70003E80 */
+ S5K4ECGX_REG_WRITE(0x70003E82, 0x5277), /* 70003E82 */
+ S5K4ECGX_REG_WRITE(0x70003E84, 0x8A11), /* 70003E84 */
+ S5K4ECGX_REG_WRITE(0x70003E86, 0x8119), /* 70003E86 */
+ S5K4ECGX_REG_WRITE(0x70003E88, 0x1C40), /* 70003E88 */
+ S5K4ECGX_REG_WRITE(0x70003E8A, 0x0400), /* 70003E8A */
+ S5K4ECGX_REG_WRITE(0x70003E8C, 0x0C00), /* 70003E8C */
+ S5K4ECGX_REG_WRITE(0x70003E8E, 0x2806), /* 70003E8E */
+ S5K4ECGX_REG_WRITE(0x70003E90, 0xD3E9), /* 70003E90 */
+ S5K4ECGX_REG_WRITE(0x70003E92, 0xF000), /* 70003E92 */
+ S5K4ECGX_REG_WRITE(0x70003E94, 0xFA5F), /* 70003E94 */
+ S5K4ECGX_REG_WRITE(0x70003E96, 0xF000), /* 70003E96 */
+ S5K4ECGX_REG_WRITE(0x70003E98, 0xFA65), /* 70003E98 */
+ S5K4ECGX_REG_WRITE(0x70003E9A, 0x4F79), /* 70003E9A */
+ S5K4ECGX_REG_WRITE(0x70003E9C, 0x37A8), /* 70003E9C */
+ S5K4ECGX_REG_WRITE(0x70003E9E, 0x2800), /* 70003E9E */
+ S5K4ECGX_REG_WRITE(0x70003EA0, 0xD10A), /* 70003EA0 */
+ S5K4ECGX_REG_WRITE(0x70003EA2, 0x1FE0), /* 70003EA2 */
+ S5K4ECGX_REG_WRITE(0x70003EA4, 0x38FD), /* 70003EA4 */
+ S5K4ECGX_REG_WRITE(0x70003EA6, 0xD001), /* 70003EA6 */
+ S5K4ECGX_REG_WRITE(0x70003EA8, 0x1CC0), /* 70003EA8 */
+ S5K4ECGX_REG_WRITE(0x70003EAA, 0xD105), /* 70003EAA */
+ S5K4ECGX_REG_WRITE(0x70003EAC, 0x4874), /* 70003EAC */
+ S5K4ECGX_REG_WRITE(0x70003EAE, 0x8829), /* 70003EAE */
+ S5K4ECGX_REG_WRITE(0x70003EB0, 0x3818), /* 70003EB0 */
+ S5K4ECGX_REG_WRITE(0x70003EB2, 0x6840), /* 70003EB2 */
+ S5K4ECGX_REG_WRITE(0x70003EB4, 0x4348), /* 70003EB4 */
+ S5K4ECGX_REG_WRITE(0x70003EB6, 0x6078), /* 70003EB6 */
+ S5K4ECGX_REG_WRITE(0x70003EB8, 0x4972), /* 70003EB8 */
+ S5K4ECGX_REG_WRITE(0x70003EBA, 0x6878), /* 70003EBA */
+ S5K4ECGX_REG_WRITE(0x70003EBC, 0x6B89), /* 70003EBC */
+ S5K4ECGX_REG_WRITE(0x70003EBE, 0x4288), /* 70003EBE */
+ S5K4ECGX_REG_WRITE(0x70003EC0, 0xD300), /* 70003EC0 */
+ S5K4ECGX_REG_WRITE(0x70003EC2, 0x0008), /* 70003EC2 */
+ S5K4ECGX_REG_WRITE(0x70003EC4, 0x6078), /* 70003EC4 */
+ S5K4ECGX_REG_WRITE(0x70003EC6, 0x2000), /* 70003EC6 */
+ S5K4ECGX_REG_WRITE(0x70003EC8, 0x0041), /* 70003EC8 */
+ S5K4ECGX_REG_WRITE(0x70003ECA, 0xAA04), /* 70003ECA */
+ S5K4ECGX_REG_WRITE(0x70003ECC, 0x5A53), /* 70003ECC */
+ S5K4ECGX_REG_WRITE(0x70003ECE, 0x194A), /* 70003ECE */
+ S5K4ECGX_REG_WRITE(0x70003ED0, 0x269C), /* 70003ED0 */
+ S5K4ECGX_REG_WRITE(0x70003ED2, 0x52B3), /* 70003ED2 */
+ S5K4ECGX_REG_WRITE(0x70003ED4, 0xAB01), /* 70003ED4 */
+ S5K4ECGX_REG_WRITE(0x70003ED6, 0x5A59), /* 70003ED6 */
+ S5K4ECGX_REG_WRITE(0x70003ED8, 0x32A0), /* 70003ED8 */
+ S5K4ECGX_REG_WRITE(0x70003EDA, 0x8111), /* 70003EDA */
+ S5K4ECGX_REG_WRITE(0x70003EDC, 0x1C40), /* 70003EDC */
+ S5K4ECGX_REG_WRITE(0x70003EDE, 0x0400), /* 70003EDE */
+ S5K4ECGX_REG_WRITE(0x70003EE0, 0x0C00), /* 70003EE0 */
+ S5K4ECGX_REG_WRITE(0x70003EE2, 0x2806), /* 70003EE2 */
+ S5K4ECGX_REG_WRITE(0x70003EE4, 0xD3F0), /* 70003EE4 */
+ S5K4ECGX_REG_WRITE(0x70003EE6, 0x4965), /* 70003EE6 */
+ S5K4ECGX_REG_WRITE(0x70003EE8, 0x9809), /* 70003EE8 */
+ S5K4ECGX_REG_WRITE(0x70003EEA, 0x8208), /* 70003EEA */
+ S5K4ECGX_REG_WRITE(0x70003EEC, 0x9808), /* 70003EEC */
+ S5K4ECGX_REG_WRITE(0x70003EEE, 0x8028), /* 70003EEE */
+ S5K4ECGX_REG_WRITE(0x70003EF0, 0x9807), /* 70003EF0 */
+ S5K4ECGX_REG_WRITE(0x70003EF2, 0x80E8), /* 70003EF2 */
+ S5K4ECGX_REG_WRITE(0x70003EF4, 0x1FE0), /* 70003EF4 */
+ S5K4ECGX_REG_WRITE(0x70003EF6, 0x38FD), /* 70003EF6 */
+ S5K4ECGX_REG_WRITE(0x70003EF8, 0xD13B), /* 70003EF8 */
+ S5K4ECGX_REG_WRITE(0x70003EFA, 0x4D64), /* 70003EFA */
+ S5K4ECGX_REG_WRITE(0x70003EFC, 0x89E8), /* 70003EFC */
+ S5K4ECGX_REG_WRITE(0x70003EFE, 0x1FC1), /* 70003EFE */
+ S5K4ECGX_REG_WRITE(0x70003F00, 0x39FF), /* 70003F00 */
+ S5K4ECGX_REG_WRITE(0x70003F02, 0xD136), /* 70003F02 */
+ S5K4ECGX_REG_WRITE(0x70003F04, 0x4C5F), /* 70003F04 */
+ S5K4ECGX_REG_WRITE(0x70003F06, 0x8AE0), /* 70003F06 */
+ S5K4ECGX_REG_WRITE(0x70003F08, 0xF000), /* 70003F08 */
+ S5K4ECGX_REG_WRITE(0x70003F0A, 0xFA34), /* 70003F0A */
+ S5K4ECGX_REG_WRITE(0x70003F0C, 0x0006), /* 70003F0C */
+ S5K4ECGX_REG_WRITE(0x70003F0E, 0x8B20), /* 70003F0E */
+ S5K4ECGX_REG_WRITE(0x70003F10, 0xF000), /* 70003F10 */
+ S5K4ECGX_REG_WRITE(0x70003F12, 0xFA38), /* 70003F12 */
+ S5K4ECGX_REG_WRITE(0x70003F14, 0x9000), /* 70003F14 */
+ S5K4ECGX_REG_WRITE(0x70003F16, 0x6AA1), /* 70003F16 */
+ S5K4ECGX_REG_WRITE(0x70003F18, 0x6878), /* 70003F18 */
+ S5K4ECGX_REG_WRITE(0x70003F1A, 0x1809), /* 70003F1A */
+ S5K4ECGX_REG_WRITE(0x70003F1C, 0x0200), /* 70003F1C */
+ S5K4ECGX_REG_WRITE(0x70003F1E, 0xF000), /* 70003F1E */
+ S5K4ECGX_REG_WRITE(0x70003F20, 0xFA0B), /* 70003F20 */
+ S5K4ECGX_REG_WRITE(0x70003F22, 0x0400), /* 70003F22 */
+ S5K4ECGX_REG_WRITE(0x70003F24, 0x0C00), /* 70003F24 */
+ S5K4ECGX_REG_WRITE(0x70003F26, 0x0022), /* 70003F26 */
+ S5K4ECGX_REG_WRITE(0x70003F28, 0x3246), /* 70003F28 */
+ S5K4ECGX_REG_WRITE(0x70003F2A, 0x0011), /* 70003F2A */
+ S5K4ECGX_REG_WRITE(0x70003F2C, 0x310A), /* 70003F2C */
+ S5K4ECGX_REG_WRITE(0x70003F2E, 0x2305), /* 70003F2E */
+ S5K4ECGX_REG_WRITE(0x70003F30, 0xF000), /* 70003F30 */
+ S5K4ECGX_REG_WRITE(0x70003F32, 0xFA08), /* 70003F32 */
+ S5K4ECGX_REG_WRITE(0x70003F34, 0x66E8), /* 70003F34 */
+ S5K4ECGX_REG_WRITE(0x70003F36, 0x6B23), /* 70003F36 */
+ S5K4ECGX_REG_WRITE(0x70003F38, 0x0002), /* 70003F38 */
+ S5K4ECGX_REG_WRITE(0x70003F3A, 0x0031), /* 70003F3A */
+ S5K4ECGX_REG_WRITE(0x70003F3C, 0x0018), /* 70003F3C */
+ S5K4ECGX_REG_WRITE(0x70003F3E, 0xF000), /* 70003F3E */
+ S5K4ECGX_REG_WRITE(0x70003F40, 0xFA29), /* 70003F40 */
+ S5K4ECGX_REG_WRITE(0x70003F42, 0x466B), /* 70003F42 */
+ S5K4ECGX_REG_WRITE(0x70003F44, 0x8518), /* 70003F44 */
+ S5K4ECGX_REG_WRITE(0x70003F46, 0x6EEA), /* 70003F46 */
+ S5K4ECGX_REG_WRITE(0x70003F48, 0x6B60), /* 70003F48 */
+ S5K4ECGX_REG_WRITE(0x70003F4A, 0x9900), /* 70003F4A */
+ S5K4ECGX_REG_WRITE(0x70003F4C, 0xF000), /* 70003F4C */
+ S5K4ECGX_REG_WRITE(0x70003F4E, 0xFA22), /* 70003F4E */
+ S5K4ECGX_REG_WRITE(0x70003F50, 0x466B), /* 70003F50 */
+ S5K4ECGX_REG_WRITE(0x70003F52, 0x8558), /* 70003F52 */
+ S5K4ECGX_REG_WRITE(0x70003F54, 0x0029), /* 70003F54 */
+ S5K4ECGX_REG_WRITE(0x70003F56, 0x980A), /* 70003F56 */
+ S5K4ECGX_REG_WRITE(0x70003F58, 0x3170), /* 70003F58 */
+ S5K4ECGX_REG_WRITE(0x70003F5A, 0xF000), /* 70003F5A */
+ S5K4ECGX_REG_WRITE(0x70003F5C, 0xFA23), /* 70003F5C */
+ S5K4ECGX_REG_WRITE(0x70003F5E, 0x0028), /* 70003F5E */
+ S5K4ECGX_REG_WRITE(0x70003F60, 0x3060), /* 70003F60 */
+ S5K4ECGX_REG_WRITE(0x70003F62, 0x8A02), /* 70003F62 */
+ S5K4ECGX_REG_WRITE(0x70003F64, 0x4946), /* 70003F64 */
+ S5K4ECGX_REG_WRITE(0x70003F66, 0x3128), /* 70003F66 */
+ S5K4ECGX_REG_WRITE(0x70003F68, 0x808A), /* 70003F68 */
+ S5K4ECGX_REG_WRITE(0x70003F6A, 0x8A42), /* 70003F6A */
+ S5K4ECGX_REG_WRITE(0x70003F6C, 0x80CA), /* 70003F6C */
+ S5K4ECGX_REG_WRITE(0x70003F6E, 0x8A80), /* 70003F6E */
+ S5K4ECGX_REG_WRITE(0x70003F70, 0x8108), /* 70003F70 */
+ S5K4ECGX_REG_WRITE(0x70003F72, 0xB00B), /* 70003F72 */
+ S5K4ECGX_REG_WRITE(0x70003F74, 0xBCF0), /* 70003F74 */
+ S5K4ECGX_REG_WRITE(0x70003F76, 0xBC08), /* 70003F76 */
+ S5K4ECGX_REG_WRITE(0x70003F78, 0x4718), /* 70003F78 */
+ S5K4ECGX_REG_WRITE(0x70003F7A, 0xB570), /* 70003F7A */
+ S5K4ECGX_REG_WRITE(0x70003F7C, 0x2400), /* 70003F7C */
+ S5K4ECGX_REG_WRITE(0x70003F7E, 0x4D46), /* 70003F7E */
+ S5K4ECGX_REG_WRITE(0x70003F80, 0x4846), /* 70003F80 */
+ S5K4ECGX_REG_WRITE(0x70003F82, 0x8881), /* 70003F82 */
+ S5K4ECGX_REG_WRITE(0x70003F84, 0x4846), /* 70003F84 */
+ S5K4ECGX_REG_WRITE(0x70003F86, 0x8041), /* 70003F86 */
+ S5K4ECGX_REG_WRITE(0x70003F88, 0x2101), /* 70003F88 */
+ S5K4ECGX_REG_WRITE(0x70003F8A, 0x8001), /* 70003F8A */
+ S5K4ECGX_REG_WRITE(0x70003F8C, 0xF000), /* 70003F8C */
+ S5K4ECGX_REG_WRITE(0x70003F8E, 0xFA12), /* 70003F8E */
+ S5K4ECGX_REG_WRITE(0x70003F90, 0x4842), /* 70003F90 */
+ S5K4ECGX_REG_WRITE(0x70003F92, 0x3820), /* 70003F92 */
+ S5K4ECGX_REG_WRITE(0x70003F94, 0x8BC0), /* 70003F94 */
+ S5K4ECGX_REG_WRITE(0x70003F96, 0xF000), /* 70003F96 */
+ S5K4ECGX_REG_WRITE(0x70003F98, 0xFA15), /* 70003F98 */
+ S5K4ECGX_REG_WRITE(0x70003F9A, 0x4B42), /* 70003F9A */
+ S5K4ECGX_REG_WRITE(0x70003F9C, 0x220D), /* 70003F9C */
+ S5K4ECGX_REG_WRITE(0x70003F9E, 0x0712), /* 70003F9E */
+ S5K4ECGX_REG_WRITE(0x70003FA0, 0x18A8), /* 70003FA0 */
+ S5K4ECGX_REG_WRITE(0x70003FA2, 0x8806), /* 70003FA2 */
+ S5K4ECGX_REG_WRITE(0x70003FA4, 0x00E1), /* 70003FA4 */
+ S5K4ECGX_REG_WRITE(0x70003FA6, 0x18C9), /* 70003FA6 */
+ S5K4ECGX_REG_WRITE(0x70003FA8, 0x81CE), /* 70003FA8 */
+ S5K4ECGX_REG_WRITE(0x70003FAA, 0x8846), /* 70003FAA */
+ S5K4ECGX_REG_WRITE(0x70003FAC, 0x818E), /* 70003FAC */
+ S5K4ECGX_REG_WRITE(0x70003FAE, 0x8886), /* 70003FAE */
+ S5K4ECGX_REG_WRITE(0x70003FB0, 0x824E), /* 70003FB0 */
+ S5K4ECGX_REG_WRITE(0x70003FB2, 0x88C0), /* 70003FB2 */
+ S5K4ECGX_REG_WRITE(0x70003FB4, 0x8208), /* 70003FB4 */
+ S5K4ECGX_REG_WRITE(0x70003FB6, 0x3508), /* 70003FB6 */
+ S5K4ECGX_REG_WRITE(0x70003FB8, 0x042D), /* 70003FB8 */
+ S5K4ECGX_REG_WRITE(0x70003FBA, 0x0C2D), /* 70003FBA */
+ S5K4ECGX_REG_WRITE(0x70003FBC, 0x1C64), /* 70003FBC */
+ S5K4ECGX_REG_WRITE(0x70003FBE, 0x0424), /* 70003FBE */
+ S5K4ECGX_REG_WRITE(0x70003FC0, 0x0C24), /* 70003FC0 */
+ S5K4ECGX_REG_WRITE(0x70003FC2, 0x2C07), /* 70003FC2 */
+ S5K4ECGX_REG_WRITE(0x70003FC4, 0xD3EC), /* 70003FC4 */
+ S5K4ECGX_REG_WRITE(0x70003FC6, 0xE658), /* 70003FC6 */
+ S5K4ECGX_REG_WRITE(0x70003FC8, 0xB510), /* 70003FC8 */
+ S5K4ECGX_REG_WRITE(0x70003FCA, 0x4834), /* 70003FCA */
+ S5K4ECGX_REG_WRITE(0x70003FCC, 0x4C34), /* 70003FCC */
+ S5K4ECGX_REG_WRITE(0x70003FCE, 0x88C0), /* 70003FCE */
+ S5K4ECGX_REG_WRITE(0x70003FD0, 0x8060), /* 70003FD0 */
+ S5K4ECGX_REG_WRITE(0x70003FD2, 0x2001), /* 70003FD2 */
+ S5K4ECGX_REG_WRITE(0x70003FD4, 0x8020), /* 70003FD4 */
+ S5K4ECGX_REG_WRITE(0x70003FD6, 0x4831), /* 70003FD6 */
+ S5K4ECGX_REG_WRITE(0x70003FD8, 0x3820), /* 70003FD8 */
+ S5K4ECGX_REG_WRITE(0x70003FDA, 0x8BC0), /* 70003FDA */
+ S5K4ECGX_REG_WRITE(0x70003FDC, 0xF000), /* 70003FDC */
+ S5K4ECGX_REG_WRITE(0x70003FDE, 0xF9F2), /* 70003FDE */
+ S5K4ECGX_REG_WRITE(0x70003FE0, 0x88E0), /* 70003FE0 */
+ S5K4ECGX_REG_WRITE(0x70003FE2, 0x4A31), /* 70003FE2 */
+ S5K4ECGX_REG_WRITE(0x70003FE4, 0x2800), /* 70003FE4 */
+ S5K4ECGX_REG_WRITE(0x70003FE6, 0xD003), /* 70003FE6 */
+ S5K4ECGX_REG_WRITE(0x70003FE8, 0x4930), /* 70003FE8 */
+ S5K4ECGX_REG_WRITE(0x70003FEA, 0x8849), /* 70003FEA */
+ S5K4ECGX_REG_WRITE(0x70003FEC, 0x2900), /* 70003FEC */
+ S5K4ECGX_REG_WRITE(0x70003FEE, 0xD009), /* 70003FEE */
+ S5K4ECGX_REG_WRITE(0x70003FF0, 0x2001), /* 70003FF0 */
+ S5K4ECGX_REG_WRITE(0x70003FF2, 0x03C0), /* 70003FF2 */
+ S5K4ECGX_REG_WRITE(0x70003FF4, 0x8050), /* 70003FF4 */
+ S5K4ECGX_REG_WRITE(0x70003FF6, 0x80D0), /* 70003FF6 */
+ S5K4ECGX_REG_WRITE(0x70003FF8, 0x2000), /* 70003FF8 */
+ S5K4ECGX_REG_WRITE(0x70003FFA, 0x8090), /* 70003FFA */
+ S5K4ECGX_REG_WRITE(0x70003FFC, 0x8110), /* 70003FFC */
+ S5K4ECGX_REG_WRITE(0x70003FFE, 0xBC10), /* 70003FFE */
+ S5K4ECGX_REG_WRITE(0x70004000, 0xBC08), /* 70004000 */
+ S5K4ECGX_REG_WRITE(0x70004002, 0x4718), /* 70004002 */
+ S5K4ECGX_REG_WRITE(0x70004004, 0x8050), /* 70004004 */
+ S5K4ECGX_REG_WRITE(0x70004006, 0x8920), /* 70004006 */
+ S5K4ECGX_REG_WRITE(0x70004008, 0x80D0), /* 70004008 */
+ S5K4ECGX_REG_WRITE(0x7000400A, 0x8960), /* 7000400A */
+ S5K4ECGX_REG_WRITE(0x7000400C, 0x0400), /* 7000400C */
+ S5K4ECGX_REG_WRITE(0x7000400E, 0x1400), /* 7000400E */
+ S5K4ECGX_REG_WRITE(0x70004010, 0x8090), /* 70004010 */
+ S5K4ECGX_REG_WRITE(0x70004012, 0x89A1), /* 70004012 */
+ S5K4ECGX_REG_WRITE(0x70004014, 0x0409), /* 70004014 */
+ S5K4ECGX_REG_WRITE(0x70004016, 0x1409), /* 70004016 */
+ S5K4ECGX_REG_WRITE(0x70004018, 0x8111), /* 70004018 */
+ S5K4ECGX_REG_WRITE(0x7000401A, 0x89E3), /* 7000401A */
+ S5K4ECGX_REG_WRITE(0x7000401C, 0x8A24), /* 7000401C */
+ S5K4ECGX_REG_WRITE(0x7000401E, 0x2B00), /* 7000401E */
+ S5K4ECGX_REG_WRITE(0x70004020, 0xD104), /* 70004020 */
+ S5K4ECGX_REG_WRITE(0x70004022, 0x17C3), /* 70004022 */
+ S5K4ECGX_REG_WRITE(0x70004024, 0x0F5B), /* 70004024 */
+ S5K4ECGX_REG_WRITE(0x70004026, 0x1818), /* 70004026 */
+ S5K4ECGX_REG_WRITE(0x70004028, 0x10C0), /* 70004028 */
+ S5K4ECGX_REG_WRITE(0x7000402A, 0x8090), /* 7000402A */
+ S5K4ECGX_REG_WRITE(0x7000402C, 0x2C00), /* 7000402C */
+ S5K4ECGX_REG_WRITE(0x7000402E, 0xD1E6), /* 7000402E */
+ S5K4ECGX_REG_WRITE(0x70004030, 0x17C8), /* 70004030 */
+ S5K4ECGX_REG_WRITE(0x70004032, 0x0F40), /* 70004032 */
+ S5K4ECGX_REG_WRITE(0x70004034, 0x1840), /* 70004034 */
+ S5K4ECGX_REG_WRITE(0x70004036, 0x10C0), /* 70004036 */
+ S5K4ECGX_REG_WRITE(0x70004038, 0x8110), /* 70004038 */
+ S5K4ECGX_REG_WRITE(0x7000403A, 0xE7E0), /* 7000403A */
+ S5K4ECGX_REG_WRITE(0x7000403C, 0xB510), /* 7000403C */
+ S5K4ECGX_REG_WRITE(0x7000403E, 0x000C), /* 7000403E */
+ S5K4ECGX_REG_WRITE(0x70004040, 0x4919), /* 70004040 */
+ S5K4ECGX_REG_WRITE(0x70004042, 0x2204), /* 70004042 */
+ S5K4ECGX_REG_WRITE(0x70004044, 0x6820), /* 70004044 */
+ S5K4ECGX_REG_WRITE(0x70004046, 0x5E8A), /* 70004046 */
+ S5K4ECGX_REG_WRITE(0x70004048, 0x0140), /* 70004048 */
+ S5K4ECGX_REG_WRITE(0x7000404A, 0x1A80), /* 7000404A */
+ S5K4ECGX_REG_WRITE(0x7000404C, 0x0280), /* 7000404C */
+ S5K4ECGX_REG_WRITE(0x7000404E, 0x8849), /* 7000404E */
+ S5K4ECGX_REG_WRITE(0x70004050, 0xF000), /* 70004050 */
+ S5K4ECGX_REG_WRITE(0x70004052, 0xF9C0), /* 70004052 */
+ S5K4ECGX_REG_WRITE(0x70004054, 0x6020), /* 70004054 */
+ S5K4ECGX_REG_WRITE(0x70004056, 0xE7D2), /* 70004056 */
+ S5K4ECGX_REG_WRITE(0x70004058, 0x38D4), /* 70004058 */
+ S5K4ECGX_REG_WRITE(0x7000405A, 0x7000), /* 7000405A */
+ S5K4ECGX_REG_WRITE(0x7000405C, 0x17D0), /* 7000405C */
+ S5K4ECGX_REG_WRITE(0x7000405E, 0x7000), /* 7000405E */
+ S5K4ECGX_REG_WRITE(0x70004060, 0x5000), /* 70004060 */
+ S5K4ECGX_REG_WRITE(0x70004062, 0xD000), /* 70004062 */
+ S5K4ECGX_REG_WRITE(0x70004064, 0x1100), /* 70004064 */
+ S5K4ECGX_REG_WRITE(0x70004066, 0xD000), /* 70004066 */
+ S5K4ECGX_REG_WRITE(0x70004068, 0x171A), /* 70004068 */
+ S5K4ECGX_REG_WRITE(0x7000406A, 0x7000), /* 7000406A */
+ S5K4ECGX_REG_WRITE(0x7000406C, 0x4780), /* 7000406C */
+ S5K4ECGX_REG_WRITE(0x7000406E, 0x7000), /* 7000406E */
+ S5K4ECGX_REG_WRITE(0x70004070, 0x2FCA), /* 70004070 */
+ S5K4ECGX_REG_WRITE(0x70004072, 0x7000), /* 70004072 */
+ S5K4ECGX_REG_WRITE(0x70004074, 0x2FC5), /* 70004074 */
+ S5K4ECGX_REG_WRITE(0x70004076, 0x7000), /* 70004076 */
+ S5K4ECGX_REG_WRITE(0x70004078, 0x2FC6), /* 70004078 */
+ S5K4ECGX_REG_WRITE(0x7000407A, 0x7000), /* 7000407A */
+ S5K4ECGX_REG_WRITE(0x7000407C, 0x2ED8), /* 7000407C */
+ S5K4ECGX_REG_WRITE(0x7000407E, 0x7000), /* 7000407E */
+ S5K4ECGX_REG_WRITE(0x70004080, 0x2BD0), /* 70004080 */
+ S5K4ECGX_REG_WRITE(0x70004082, 0x7000), /* 70004082 */
+ S5K4ECGX_REG_WRITE(0x70004084, 0x17E0), /* 70004084 */
+ S5K4ECGX_REG_WRITE(0x70004086, 0x7000), /* 70004086 */
+ S5K4ECGX_REG_WRITE(0x70004088, 0x2DE8), /* 70004088 */
+ S5K4ECGX_REG_WRITE(0x7000408A, 0x7000), /* 7000408A */
+ S5K4ECGX_REG_WRITE(0x7000408C, 0x37E0), /* 7000408C */
+ S5K4ECGX_REG_WRITE(0x7000408E, 0x7000), /* 7000408E */
+ S5K4ECGX_REG_WRITE(0x70004090, 0x210C), /* 70004090 */
+ S5K4ECGX_REG_WRITE(0x70004092, 0x7000), /* 70004092 */
+ S5K4ECGX_REG_WRITE(0x70004094, 0x1484), /* 70004094 */
+ S5K4ECGX_REG_WRITE(0x70004096, 0x7000), /* 70004096 */
+ S5K4ECGX_REG_WRITE(0x70004098, 0xA006), /* 70004098 */
+ S5K4ECGX_REG_WRITE(0x7000409A, 0x0000), /* 7000409A */
+ S5K4ECGX_REG_WRITE(0x7000409C, 0x0724), /* 7000409C */
+ S5K4ECGX_REG_WRITE(0x7000409E, 0x7000), /* 7000409E */
+ S5K4ECGX_REG_WRITE(0x700040A0, 0xA000), /* 700040A0 */
+ S5K4ECGX_REG_WRITE(0x700040A2, 0xD000), /* 700040A2 */
+ S5K4ECGX_REG_WRITE(0x700040A4, 0x2270), /* 700040A4 */
+ S5K4ECGX_REG_WRITE(0x700040A6, 0x7000), /* 700040A6 */
+ S5K4ECGX_REG_WRITE(0x700040A8, 0x2558), /* 700040A8 */
+ S5K4ECGX_REG_WRITE(0x700040AA, 0x7000), /* 700040AA */
+ S5K4ECGX_REG_WRITE(0x700040AC, 0x146C), /* 700040AC */
+ S5K4ECGX_REG_WRITE(0x700040AE, 0x7000), /* 700040AE */
+ S5K4ECGX_REG_WRITE(0x700040B0, 0xB510), /* 700040B0 */
+ S5K4ECGX_REG_WRITE(0x700040B2, 0x000C), /* 700040B2 */
+ S5K4ECGX_REG_WRITE(0x700040B4, 0x4979), /* 700040B4 */
+ S5K4ECGX_REG_WRITE(0x700040B6, 0x2208), /* 700040B6 */
+ S5K4ECGX_REG_WRITE(0x700040B8, 0x6820), /* 700040B8 */
+ S5K4ECGX_REG_WRITE(0x700040BA, 0x5E8A), /* 700040BA */
+ S5K4ECGX_REG_WRITE(0x700040BC, 0x0140), /* 700040BC */
+ S5K4ECGX_REG_WRITE(0x700040BE, 0x1A80), /* 700040BE */
+ S5K4ECGX_REG_WRITE(0x700040C0, 0x0280), /* 700040C0 */
+ S5K4ECGX_REG_WRITE(0x700040C2, 0x88C9), /* 700040C2 */
+ S5K4ECGX_REG_WRITE(0x700040C4, 0xF000), /* 700040C4 */
+ S5K4ECGX_REG_WRITE(0x700040C6, 0xF986), /* 700040C6 */
+ S5K4ECGX_REG_WRITE(0x700040C8, 0x6020), /* 700040C8 */
+ S5K4ECGX_REG_WRITE(0x700040CA, 0xE798), /* 700040CA */
+ S5K4ECGX_REG_WRITE(0x700040CC, 0xB5FE), /* 700040CC */
+ S5K4ECGX_REG_WRITE(0x700040CE, 0x000C), /* 700040CE */
+ S5K4ECGX_REG_WRITE(0x700040D0, 0x6825), /* 700040D0 */
+ S5K4ECGX_REG_WRITE(0x700040D2, 0x6866), /* 700040D2 */
+ S5K4ECGX_REG_WRITE(0x700040D4, 0x68A0), /* 700040D4 */
+ S5K4ECGX_REG_WRITE(0x700040D6, 0x9001), /* 700040D6 */
+ S5K4ECGX_REG_WRITE(0x700040D8, 0x68E7), /* 700040D8 */
+ S5K4ECGX_REG_WRITE(0x700040DA, 0x1BA8), /* 700040DA */
+ S5K4ECGX_REG_WRITE(0x700040DC, 0x42B5), /* 700040DC */
+ S5K4ECGX_REG_WRITE(0x700040DE, 0xDA00), /* 700040DE */
+ S5K4ECGX_REG_WRITE(0x700040E0, 0x1B70), /* 700040E0 */
+ S5K4ECGX_REG_WRITE(0x700040E2, 0x9000), /* 700040E2 */
+ S5K4ECGX_REG_WRITE(0x700040E4, 0x496D), /* 700040E4 */
+ S5K4ECGX_REG_WRITE(0x700040E6, 0x486E), /* 700040E6 */
+ S5K4ECGX_REG_WRITE(0x700040E8, 0x884A), /* 700040E8 */
+ S5K4ECGX_REG_WRITE(0x700040EA, 0x8843), /* 700040EA */
+ S5K4ECGX_REG_WRITE(0x700040EC, 0x435A), /* 700040EC */
+ S5K4ECGX_REG_WRITE(0x700040EE, 0x2304), /* 700040EE */
+ S5K4ECGX_REG_WRITE(0x700040F0, 0x5ECB), /* 700040F0 */
+ S5K4ECGX_REG_WRITE(0x700040F2, 0x0A92), /* 700040F2 */
+ S5K4ECGX_REG_WRITE(0x700040F4, 0x18D2), /* 700040F4 */
+ S5K4ECGX_REG_WRITE(0x700040F6, 0x02D2), /* 700040F6 */
+ S5K4ECGX_REG_WRITE(0x700040F8, 0x0C12), /* 700040F8 */
+ S5K4ECGX_REG_WRITE(0x700040FA, 0x88CB), /* 700040FA */
+ S5K4ECGX_REG_WRITE(0x700040FC, 0x8880), /* 700040FC */
+ S5K4ECGX_REG_WRITE(0x700040FE, 0x4343), /* 700040FE */
+ S5K4ECGX_REG_WRITE(0x70004100, 0x0A98), /* 70004100 */
+ S5K4ECGX_REG_WRITE(0x70004102, 0x2308), /* 70004102 */
+ S5K4ECGX_REG_WRITE(0x70004104, 0x5ECB), /* 70004104 */
+ S5K4ECGX_REG_WRITE(0x70004106, 0x18C0), /* 70004106 */
+ S5K4ECGX_REG_WRITE(0x70004108, 0x02C0), /* 70004108 */
+ S5K4ECGX_REG_WRITE(0x7000410A, 0x0C00), /* 7000410A */
+ S5K4ECGX_REG_WRITE(0x7000410C, 0x0411), /* 7000410C */
+ S5K4ECGX_REG_WRITE(0x7000410E, 0x0400), /* 7000410E */
+ S5K4ECGX_REG_WRITE(0x70004110, 0x1409), /* 70004110 */
+ S5K4ECGX_REG_WRITE(0x70004112, 0x1400), /* 70004112 */
+ S5K4ECGX_REG_WRITE(0x70004114, 0x1A08), /* 70004114 */
+ S5K4ECGX_REG_WRITE(0x70004116, 0x4962), /* 70004116 */
+ S5K4ECGX_REG_WRITE(0x70004118, 0x39E0), /* 70004118 */
+ S5K4ECGX_REG_WRITE(0x7000411A, 0x6148), /* 7000411A */
+ S5K4ECGX_REG_WRITE(0x7000411C, 0x9801), /* 7000411C */
+ S5K4ECGX_REG_WRITE(0x7000411E, 0x3040), /* 7000411E */
+ S5K4ECGX_REG_WRITE(0x70004120, 0x7880), /* 70004120 */
+ S5K4ECGX_REG_WRITE(0x70004122, 0x2800), /* 70004122 */
+ S5K4ECGX_REG_WRITE(0x70004124, 0xD103), /* 70004124 */
+ S5K4ECGX_REG_WRITE(0x70004126, 0x9801), /* 70004126 */
+ S5K4ECGX_REG_WRITE(0x70004128, 0x0029), /* 70004128 */
+ S5K4ECGX_REG_WRITE(0x7000412A, 0xF000), /* 7000412A */
+ S5K4ECGX_REG_WRITE(0x7000412C, 0xF959), /* 7000412C */
+ S5K4ECGX_REG_WRITE(0x7000412E, 0x8839), /* 7000412E */
+ S5K4ECGX_REG_WRITE(0x70004130, 0x9800), /* 70004130 */
+ S5K4ECGX_REG_WRITE(0x70004132, 0x4281), /* 70004132 */
+ S5K4ECGX_REG_WRITE(0x70004134, 0xD814), /* 70004134 */
+ S5K4ECGX_REG_WRITE(0x70004136, 0x8879), /* 70004136 */
+ S5K4ECGX_REG_WRITE(0x70004138, 0x9800), /* 70004138 */
+ S5K4ECGX_REG_WRITE(0x7000413A, 0x4281), /* 7000413A */
+ S5K4ECGX_REG_WRITE(0x7000413C, 0xD20C), /* 7000413C */
+ S5K4ECGX_REG_WRITE(0x7000413E, 0x9801), /* 7000413E */
+ S5K4ECGX_REG_WRITE(0x70004140, 0x0029), /* 70004140 */
+ S5K4ECGX_REG_WRITE(0x70004142, 0xF000), /* 70004142 */
+ S5K4ECGX_REG_WRITE(0x70004144, 0xF955), /* 70004144 */
+ S5K4ECGX_REG_WRITE(0x70004146, 0x9801), /* 70004146 */
+ S5K4ECGX_REG_WRITE(0x70004148, 0x0029), /* 70004148 */
+ S5K4ECGX_REG_WRITE(0x7000414A, 0xF000), /* 7000414A */
+ S5K4ECGX_REG_WRITE(0x7000414C, 0xF951), /* 7000414C */
+ S5K4ECGX_REG_WRITE(0x7000414E, 0x9801), /* 7000414E */
+ S5K4ECGX_REG_WRITE(0x70004150, 0x0029), /* 70004150 */
+ S5K4ECGX_REG_WRITE(0x70004152, 0xF000), /* 70004152 */
+ S5K4ECGX_REG_WRITE(0x70004154, 0xF94D), /* 70004154 */
+ S5K4ECGX_REG_WRITE(0x70004156, 0xE003), /* 70004156 */
+ S5K4ECGX_REG_WRITE(0x70004158, 0x9801), /* 70004158 */
+ S5K4ECGX_REG_WRITE(0x7000415A, 0x0029), /* 7000415A */
+ S5K4ECGX_REG_WRITE(0x7000415C, 0xF000), /* 7000415C */
+ S5K4ECGX_REG_WRITE(0x7000415E, 0xF948), /* 7000415E */
+ S5K4ECGX_REG_WRITE(0x70004160, 0x9801), /* 70004160 */
+ S5K4ECGX_REG_WRITE(0x70004162, 0x0032), /* 70004162 */
+ S5K4ECGX_REG_WRITE(0x70004164, 0x0039), /* 70004164 */
+ S5K4ECGX_REG_WRITE(0x70004166, 0xF000), /* 70004166 */
+ S5K4ECGX_REG_WRITE(0x70004168, 0xF94B), /* 70004168 */
+ S5K4ECGX_REG_WRITE(0x7000416A, 0x6020), /* 7000416A */
+ S5K4ECGX_REG_WRITE(0x7000416C, 0xE5D0), /* 7000416C */
+ S5K4ECGX_REG_WRITE(0x7000416E, 0xB57C), /* 7000416E */
+ S5K4ECGX_REG_WRITE(0x70004170, 0x484C), /* 70004170 */
+ S5K4ECGX_REG_WRITE(0x70004172, 0xA901), /* 70004172 */
+ S5K4ECGX_REG_WRITE(0x70004174, 0x0004), /* 70004174 */
+ S5K4ECGX_REG_WRITE(0x70004176, 0xF000), /* 70004176 */
+ S5K4ECGX_REG_WRITE(0x70004178, 0xF8CF), /* 70004178 */
+ S5K4ECGX_REG_WRITE(0x7000417A, 0x466B), /* 7000417A */
+ S5K4ECGX_REG_WRITE(0x7000417C, 0x88D9), /* 7000417C */
+ S5K4ECGX_REG_WRITE(0x7000417E, 0x8898), /* 7000417E */
+ S5K4ECGX_REG_WRITE(0x70004180, 0x4B47), /* 70004180 */
+ S5K4ECGX_REG_WRITE(0x70004182, 0x3346), /* 70004182 */
+ S5K4ECGX_REG_WRITE(0x70004184, 0x1E9A), /* 70004184 */
+ S5K4ECGX_REG_WRITE(0x70004186, 0xF000), /* 70004186 */
+ S5K4ECGX_REG_WRITE(0x70004188, 0xF943), /* 70004188 */
+ S5K4ECGX_REG_WRITE(0x7000418A, 0x4846), /* 7000418A */
+ S5K4ECGX_REG_WRITE(0x7000418C, 0x4944), /* 7000418C */
+ S5K4ECGX_REG_WRITE(0x7000418E, 0x3812), /* 7000418E */
+ S5K4ECGX_REG_WRITE(0x70004190, 0x3140), /* 70004190 */
+ S5K4ECGX_REG_WRITE(0x70004192, 0x8A42), /* 70004192 */
+ S5K4ECGX_REG_WRITE(0x70004194, 0x888B), /* 70004194 */
+ S5K4ECGX_REG_WRITE(0x70004196, 0x18D2), /* 70004196 */
+ S5K4ECGX_REG_WRITE(0x70004198, 0x8242), /* 70004198 */
+ S5K4ECGX_REG_WRITE(0x7000419A, 0x8AC2), /* 7000419A */
+ S5K4ECGX_REG_WRITE(0x7000419C, 0x88C9), /* 7000419C */
+ S5K4ECGX_REG_WRITE(0x7000419E, 0x1851), /* 7000419E */
+ S5K4ECGX_REG_WRITE(0x700041A0, 0x82C1), /* 700041A0 */
+ S5K4ECGX_REG_WRITE(0x700041A2, 0x0020), /* 700041A2 */
+ S5K4ECGX_REG_WRITE(0x700041A4, 0x4669), /* 700041A4 */
+ S5K4ECGX_REG_WRITE(0x700041A6, 0xF000), /* 700041A6 */
+ S5K4ECGX_REG_WRITE(0x700041A8, 0xF8B7), /* 700041A8 */
+ S5K4ECGX_REG_WRITE(0x700041AA, 0x483F), /* 700041AA */
+ S5K4ECGX_REG_WRITE(0x700041AC, 0x214D), /* 700041AC */
+ S5K4ECGX_REG_WRITE(0x700041AE, 0x8301), /* 700041AE */
+ S5K4ECGX_REG_WRITE(0x700041B0, 0x2196), /* 700041B0 */
+ S5K4ECGX_REG_WRITE(0x700041B2, 0x8381), /* 700041B2 */
+ S5K4ECGX_REG_WRITE(0x700041B4, 0x211D), /* 700041B4 */
+ S5K4ECGX_REG_WRITE(0x700041B6, 0x3020), /* 700041B6 */
+ S5K4ECGX_REG_WRITE(0x700041B8, 0x8001), /* 700041B8 */
+ S5K4ECGX_REG_WRITE(0x700041BA, 0xF000), /* 700041BA */
+ S5K4ECGX_REG_WRITE(0x700041BC, 0xF931), /* 700041BC */
+ S5K4ECGX_REG_WRITE(0x700041BE, 0xF000), /* 700041BE */
+ S5K4ECGX_REG_WRITE(0x700041C0, 0xF937), /* 700041C0 */
+ S5K4ECGX_REG_WRITE(0x700041C2, 0x483A), /* 700041C2 */
+ S5K4ECGX_REG_WRITE(0x700041C4, 0x4C3A), /* 700041C4 */
+ S5K4ECGX_REG_WRITE(0x700041C6, 0x6E00), /* 700041C6 */
+ S5K4ECGX_REG_WRITE(0x700041C8, 0x60E0), /* 700041C8 */
+ S5K4ECGX_REG_WRITE(0x700041CA, 0x466B), /* 700041CA */
+ S5K4ECGX_REG_WRITE(0x700041CC, 0x8818), /* 700041CC */
+ S5K4ECGX_REG_WRITE(0x700041CE, 0x8859), /* 700041CE */
+ S5K4ECGX_REG_WRITE(0x700041D0, 0x0025), /* 700041D0 */
+ S5K4ECGX_REG_WRITE(0x700041D2, 0x1A40), /* 700041D2 */
+ S5K4ECGX_REG_WRITE(0x700041D4, 0x3540), /* 700041D4 */
+ S5K4ECGX_REG_WRITE(0x700041D6, 0x61A8), /* 700041D6 */
+ S5K4ECGX_REG_WRITE(0x700041D8, 0x4831), /* 700041D8 */
+ S5K4ECGX_REG_WRITE(0x700041DA, 0x9900), /* 700041DA */
+ S5K4ECGX_REG_WRITE(0x700041DC, 0x3060), /* 700041DC */
+ S5K4ECGX_REG_WRITE(0x700041DE, 0xF000), /* 700041DE */
+ S5K4ECGX_REG_WRITE(0x700041E0, 0xF92F), /* 700041E0 */
+ S5K4ECGX_REG_WRITE(0x700041E2, 0x466B), /* 700041E2 */
+ S5K4ECGX_REG_WRITE(0x700041E4, 0x8819), /* 700041E4 */
+ S5K4ECGX_REG_WRITE(0x700041E6, 0x1DE0), /* 700041E6 */
+ S5K4ECGX_REG_WRITE(0x700041E8, 0x30F9), /* 700041E8 */
+ S5K4ECGX_REG_WRITE(0x700041EA, 0x8741), /* 700041EA */
+ S5K4ECGX_REG_WRITE(0x700041EC, 0x8859), /* 700041EC */
+ S5K4ECGX_REG_WRITE(0x700041EE, 0x8781), /* 700041EE */
+ S5K4ECGX_REG_WRITE(0x700041F0, 0x2000), /* 700041F0 */
+ S5K4ECGX_REG_WRITE(0x700041F2, 0x71A0), /* 700041F2 */
+ S5K4ECGX_REG_WRITE(0x700041F4, 0x74A8), /* 700041F4 */
+ S5K4ECGX_REG_WRITE(0x700041F6, 0xBC7C), /* 700041F6 */
+ S5K4ECGX_REG_WRITE(0x700041F8, 0xBC08), /* 700041F8 */
+ S5K4ECGX_REG_WRITE(0x700041FA, 0x4718), /* 700041FA */
+ S5K4ECGX_REG_WRITE(0x700041FC, 0xB5F8), /* 700041FC */
+ S5K4ECGX_REG_WRITE(0x700041FE, 0x0005), /* 700041FE */
+ S5K4ECGX_REG_WRITE(0x70004200, 0x6808), /* 70004200 */
+ S5K4ECGX_REG_WRITE(0x70004202, 0x0400), /* 70004202 */
+ S5K4ECGX_REG_WRITE(0x70004204, 0x0C00), /* 70004204 */
+ S5K4ECGX_REG_WRITE(0x70004206, 0x684A), /* 70004206 */
+ S5K4ECGX_REG_WRITE(0x70004208, 0x0412), /* 70004208 */
+ S5K4ECGX_REG_WRITE(0x7000420A, 0x0C12), /* 7000420A */
+ S5K4ECGX_REG_WRITE(0x7000420C, 0x688E), /* 7000420C */
+ S5K4ECGX_REG_WRITE(0x7000420E, 0x68CC), /* 7000420E */
+ S5K4ECGX_REG_WRITE(0x70004210, 0x4922), /* 70004210 */
+ S5K4ECGX_REG_WRITE(0x70004212, 0x884B), /* 70004212 */
+ S5K4ECGX_REG_WRITE(0x70004214, 0x4343), /* 70004214 */
+ S5K4ECGX_REG_WRITE(0x70004216, 0x0A98), /* 70004216 */
+ S5K4ECGX_REG_WRITE(0x70004218, 0x2304), /* 70004218 */
+ S5K4ECGX_REG_WRITE(0x7000421A, 0x5ECB), /* 7000421A */
+ S5K4ECGX_REG_WRITE(0x7000421C, 0x18C0), /* 7000421C */
+ S5K4ECGX_REG_WRITE(0x7000421E, 0x02C0), /* 7000421E */
+ S5K4ECGX_REG_WRITE(0x70004220, 0x0C00), /* 70004220 */
+ S5K4ECGX_REG_WRITE(0x70004222, 0x88CB), /* 70004222 */
+ S5K4ECGX_REG_WRITE(0x70004224, 0x4353), /* 70004224 */
+ S5K4ECGX_REG_WRITE(0x70004226, 0x0A9A), /* 70004226 */
+ S5K4ECGX_REG_WRITE(0x70004228, 0x2308), /* 70004228 */
+ S5K4ECGX_REG_WRITE(0x7000422A, 0x5ECB), /* 7000422A */
+ S5K4ECGX_REG_WRITE(0x7000422C, 0x18D1), /* 7000422C */
+ S5K4ECGX_REG_WRITE(0x7000422E, 0x02C9), /* 7000422E */
+ S5K4ECGX_REG_WRITE(0x70004230, 0x0C09), /* 70004230 */
+ S5K4ECGX_REG_WRITE(0x70004232, 0x2701), /* 70004232 */
+ S5K4ECGX_REG_WRITE(0x70004234, 0x003A), /* 70004234 */
+ S5K4ECGX_REG_WRITE(0x70004236, 0x40AA), /* 70004236 */
+ S5K4ECGX_REG_WRITE(0x70004238, 0x9200), /* 70004238 */
+ S5K4ECGX_REG_WRITE(0x7000423A, 0x002A), /* 7000423A */
+ S5K4ECGX_REG_WRITE(0x7000423C, 0x3A10), /* 7000423C */
+ S5K4ECGX_REG_WRITE(0x7000423E, 0x4097), /* 7000423E */
+ S5K4ECGX_REG_WRITE(0x70004240, 0x2D10), /* 70004240 */
+ S5K4ECGX_REG_WRITE(0x70004242, 0xDA06), /* 70004242 */
+ S5K4ECGX_REG_WRITE(0x70004244, 0x4A1B), /* 70004244 */
+ S5K4ECGX_REG_WRITE(0x70004246, 0x9B00), /* 70004246 */
+ S5K4ECGX_REG_WRITE(0x70004248, 0x8812), /* 70004248 */
+ S5K4ECGX_REG_WRITE(0x7000424A, 0x439A), /* 7000424A */
+ S5K4ECGX_REG_WRITE(0x7000424C, 0x4B19), /* 7000424C */
+ S5K4ECGX_REG_WRITE(0x7000424E, 0x801A), /* 7000424E */
+ S5K4ECGX_REG_WRITE(0x70004250, 0xE003), /* 70004250 */
+ S5K4ECGX_REG_WRITE(0x70004252, 0x4B18), /* 70004252 */
+ S5K4ECGX_REG_WRITE(0x70004254, 0x885A), /* 70004254 */
+ S5K4ECGX_REG_WRITE(0x70004256, 0x43BA), /* 70004256 */
+ S5K4ECGX_REG_WRITE(0x70004258, 0x805A), /* 70004258 */
+ S5K4ECGX_REG_WRITE(0x7000425A, 0x0023), /* 7000425A */
+ S5K4ECGX_REG_WRITE(0x7000425C, 0x0032), /* 7000425C */
+ S5K4ECGX_REG_WRITE(0x7000425E, 0xF000), /* 7000425E */
+ S5K4ECGX_REG_WRITE(0x70004260, 0xF8D7), /* 70004260 */
+ S5K4ECGX_REG_WRITE(0x70004262, 0x2D10), /* 70004262 */
+ S5K4ECGX_REG_WRITE(0x70004264, 0xDA05), /* 70004264 */
+ S5K4ECGX_REG_WRITE(0x70004266, 0x4913), /* 70004266 */
+ S5K4ECGX_REG_WRITE(0x70004268, 0x9A00), /* 70004268 */
+ S5K4ECGX_REG_WRITE(0x7000426A, 0x8808), /* 7000426A */
+ S5K4ECGX_REG_WRITE(0x7000426C, 0x4310), /* 7000426C */
+ S5K4ECGX_REG_WRITE(0x7000426E, 0x8008), /* 7000426E */
+ S5K4ECGX_REG_WRITE(0x70004270, 0xE003), /* 70004270 */
+ S5K4ECGX_REG_WRITE(0x70004272, 0x4810), /* 70004272 */
+ S5K4ECGX_REG_WRITE(0x70004274, 0x8841), /* 70004274 */
+ S5K4ECGX_REG_WRITE(0x70004276, 0x4339), /* 70004276 */
+ S5K4ECGX_REG_WRITE(0x70004278, 0x8041), /* 70004278 */
+ S5K4ECGX_REG_WRITE(0x7000427A, 0x4D0D), /* 7000427A */
+ S5K4ECGX_REG_WRITE(0x7000427C, 0x2000), /* 7000427C */
+ S5K4ECGX_REG_WRITE(0x7000427E, 0x3580), /* 7000427E */
+ S5K4ECGX_REG_WRITE(0x70004280, 0x88AA), /* 70004280 */
+ S5K4ECGX_REG_WRITE(0x70004282, 0x5E30), /* 70004282 */
+ S5K4ECGX_REG_WRITE(0x70004284, 0x2100), /* 70004284 */
+ S5K4ECGX_REG_WRITE(0x70004286, 0xF000), /* 70004286 */
+ S5K4ECGX_REG_WRITE(0x70004288, 0xF8E3), /* 70004288 */
+ S5K4ECGX_REG_WRITE(0x7000428A, 0x8030), /* 7000428A */
+ S5K4ECGX_REG_WRITE(0x7000428C, 0x2000), /* 7000428C */
+ S5K4ECGX_REG_WRITE(0x7000428E, 0x88AA), /* 7000428E */
+ S5K4ECGX_REG_WRITE(0x70004290, 0x5E20), /* 70004290 */
+ S5K4ECGX_REG_WRITE(0x70004292, 0x2100), /* 70004292 */
+ S5K4ECGX_REG_WRITE(0x70004294, 0xF000), /* 70004294 */
+ S5K4ECGX_REG_WRITE(0x70004296, 0xF8DC), /* 70004296 */
+ S5K4ECGX_REG_WRITE(0x70004298, 0x8020), /* 70004298 */
+ S5K4ECGX_REG_WRITE(0x7000429A, 0xE587), /* 7000429A */
+ S5K4ECGX_REG_WRITE(0x7000429C, 0x2558), /* 7000429C */
+ S5K4ECGX_REG_WRITE(0x7000429E, 0x7000), /* 7000429E */
+ S5K4ECGX_REG_WRITE(0x700042A0, 0x2AB8), /* 700042A0 */
+ S5K4ECGX_REG_WRITE(0x700042A2, 0x7000), /* 700042A2 */
+ S5K4ECGX_REG_WRITE(0x700042A4, 0x145E), /* 700042A4 */
+ S5K4ECGX_REG_WRITE(0x700042A6, 0x7000), /* 700042A6 */
+ S5K4ECGX_REG_WRITE(0x700042A8, 0x2698), /* 700042A8 */
+ S5K4ECGX_REG_WRITE(0x700042AA, 0x7000), /* 700042AA */
+ S5K4ECGX_REG_WRITE(0x700042AC, 0x2BB8), /* 700042AC */
+ S5K4ECGX_REG_WRITE(0x700042AE, 0x7000), /* 700042AE */
+ S5K4ECGX_REG_WRITE(0x700042B0, 0x2998), /* 700042B0 */
+ S5K4ECGX_REG_WRITE(0x700042B2, 0x7000), /* 700042B2 */
+ S5K4ECGX_REG_WRITE(0x700042B4, 0x1100), /* 700042B4 */
+ S5K4ECGX_REG_WRITE(0x700042B6, 0xD000), /* 700042B6 */
+ S5K4ECGX_REG_WRITE(0x700042B8, 0x4778), /* 700042B8 */
+ S5K4ECGX_REG_WRITE(0x700042BA, 0x46C0), /* 700042BA */
+ S5K4ECGX_REG_WRITE(0x700042BC, 0xC000), /* 700042BC */
+ S5K4ECGX_REG_WRITE(0x700042BE, 0xE59F), /* 700042BE */
+ S5K4ECGX_REG_WRITE(0x700042C0, 0xFF1C), /* 700042C0 */
+ S5K4ECGX_REG_WRITE(0x700042C2, 0xE12F), /* 700042C2 */
+ S5K4ECGX_REG_WRITE(0x700042C4, 0x1789), /* 700042C4 */
+ S5K4ECGX_REG_WRITE(0x700042C6, 0x0001), /* 700042C6 */
+ S5K4ECGX_REG_WRITE(0x700042C8, 0x4778), /* 700042C8 */
+ S5K4ECGX_REG_WRITE(0x700042CA, 0x46C0), /* 700042CA */
+ S5K4ECGX_REG_WRITE(0x700042CC, 0xC000), /* 700042CC */
+ S5K4ECGX_REG_WRITE(0x700042CE, 0xE59F), /* 700042CE */
+ S5K4ECGX_REG_WRITE(0x700042D0, 0xFF1C), /* 700042D0 */
+ S5K4ECGX_REG_WRITE(0x700042D2, 0xE12F), /* 700042D2 */
+ S5K4ECGX_REG_WRITE(0x700042D4, 0x16F1), /* 700042D4 */
+ S5K4ECGX_REG_WRITE(0x700042D6, 0x0001), /* 700042D6 */
+ S5K4ECGX_REG_WRITE(0x700042D8, 0x4778), /* 700042D8 */
+ S5K4ECGX_REG_WRITE(0x700042DA, 0x46C0), /* 700042DA */
+ S5K4ECGX_REG_WRITE(0x700042DC, 0xC000), /* 700042DC */
+ S5K4ECGX_REG_WRITE(0x700042DE, 0xE59F), /* 700042DE */
+ S5K4ECGX_REG_WRITE(0x700042E0, 0xFF1C), /* 700042E0 */
+ S5K4ECGX_REG_WRITE(0x700042E2, 0xE12F), /* 700042E2 */
+ S5K4ECGX_REG_WRITE(0x700042E4, 0xC3B1), /* 700042E4 */
+ S5K4ECGX_REG_WRITE(0x700042E6, 0x0000), /* 700042E6 */
+ S5K4ECGX_REG_WRITE(0x700042E8, 0x4778), /* 700042E8 */
+ S5K4ECGX_REG_WRITE(0x700042EA, 0x46C0), /* 700042EA */
+ S5K4ECGX_REG_WRITE(0x700042EC, 0xC000), /* 700042EC */
+ S5K4ECGX_REG_WRITE(0x700042EE, 0xE59F), /* 700042EE */
+ S5K4ECGX_REG_WRITE(0x700042F0, 0xFF1C), /* 700042F0 */
+ S5K4ECGX_REG_WRITE(0x700042F2, 0xE12F), /* 700042F2 */
+ S5K4ECGX_REG_WRITE(0x700042F4, 0xC36D), /* 700042F4 */
+ S5K4ECGX_REG_WRITE(0x700042F6, 0x0000), /* 700042F6 */
+ S5K4ECGX_REG_WRITE(0x700042F8, 0x4778), /* 700042F8 */
+ S5K4ECGX_REG_WRITE(0x700042FA, 0x46C0), /* 700042FA */
+ S5K4ECGX_REG_WRITE(0x700042FC, 0xC000), /* 700042FC */
+ S5K4ECGX_REG_WRITE(0x700042FE, 0xE59F), /* 700042FE */
+ S5K4ECGX_REG_WRITE(0x70004300, 0xFF1C), /* 70004300 */
+ S5K4ECGX_REG_WRITE(0x70004302, 0xE12F), /* 70004302 */
+ S5K4ECGX_REG_WRITE(0x70004304, 0xF6D7), /* 70004304 */
+ S5K4ECGX_REG_WRITE(0x70004306, 0x0000), /* 70004306 */
+ S5K4ECGX_REG_WRITE(0x70004308, 0x4778), /* 70004308 */
+ S5K4ECGX_REG_WRITE(0x7000430A, 0x46C0), /* 7000430A */
+ S5K4ECGX_REG_WRITE(0x7000430C, 0xC000), /* 7000430C */
+ S5K4ECGX_REG_WRITE(0x7000430E, 0xE59F), /* 7000430E */
+ S5K4ECGX_REG_WRITE(0x70004310, 0xFF1C), /* 70004310 */
+ S5K4ECGX_REG_WRITE(0x70004312, 0xE12F), /* 70004312 */
+ S5K4ECGX_REG_WRITE(0x70004314, 0xB49D), /* 70004314 */
+ S5K4ECGX_REG_WRITE(0x70004316, 0x0000), /* 70004316 */
+ S5K4ECGX_REG_WRITE(0x70004318, 0x4778), /* 70004318 */
+ S5K4ECGX_REG_WRITE(0x7000431A, 0x46C0), /* 7000431A */
+ S5K4ECGX_REG_WRITE(0x7000431C, 0xC000), /* 7000431C */
+ S5K4ECGX_REG_WRITE(0x7000431E, 0xE59F), /* 7000431E */
+ S5K4ECGX_REG_WRITE(0x70004320, 0xFF1C), /* 70004320 */
+ S5K4ECGX_REG_WRITE(0x70004322, 0xE12F), /* 70004322 */
+ S5K4ECGX_REG_WRITE(0x70004324, 0x7EDF), /* 70004324 */
+ S5K4ECGX_REG_WRITE(0x70004326, 0x0000), /* 70004326 */
+ S5K4ECGX_REG_WRITE(0x70004328, 0x4778), /* 70004328 */
+ S5K4ECGX_REG_WRITE(0x7000432A, 0x46C0), /* 7000432A */
+ S5K4ECGX_REG_WRITE(0x7000432C, 0xC000), /* 7000432C */
+ S5K4ECGX_REG_WRITE(0x7000432E, 0xE59F), /* 7000432E */
+ S5K4ECGX_REG_WRITE(0x70004330, 0xFF1C), /* 70004330 */
+ S5K4ECGX_REG_WRITE(0x70004332, 0xE12F), /* 70004332 */
+ S5K4ECGX_REG_WRITE(0x70004334, 0x448D), /* 70004334 */
+ S5K4ECGX_REG_WRITE(0x70004336, 0x0000), /* 70004336 */
+ S5K4ECGX_REG_WRITE(0x70004338, 0x4778), /* 70004338 */
+ S5K4ECGX_REG_WRITE(0x7000433A, 0x46C0), /* 7000433A */
+ S5K4ECGX_REG_WRITE(0x7000433C, 0xF004), /* 7000433C */
+ S5K4ECGX_REG_WRITE(0x7000433E, 0xE51F), /* 7000433E */
+ S5K4ECGX_REG_WRITE(0x70004340, 0x29EC), /* 70004340 */
+ S5K4ECGX_REG_WRITE(0x70004342, 0x0001), /* 70004342 */
+ S5K4ECGX_REG_WRITE(0x70004344, 0x4778), /* 70004344 */
+ S5K4ECGX_REG_WRITE(0x70004346, 0x46C0), /* 70004346 */
+ S5K4ECGX_REG_WRITE(0x70004348, 0xC000), /* 70004348 */
+ S5K4ECGX_REG_WRITE(0x7000434A, 0xE59F), /* 7000434A */
+ S5K4ECGX_REG_WRITE(0x7000434C, 0xFF1C), /* 7000434C */
+ S5K4ECGX_REG_WRITE(0x7000434E, 0xE12F), /* 7000434E */
+ S5K4ECGX_REG_WRITE(0x70004350, 0x2EF1), /* 70004350 */
+ S5K4ECGX_REG_WRITE(0x70004352, 0x0000), /* 70004352 */
+ S5K4ECGX_REG_WRITE(0x70004354, 0x4778), /* 70004354 */
+ S5K4ECGX_REG_WRITE(0x70004356, 0x46C0), /* 70004356 */
+ S5K4ECGX_REG_WRITE(0x70004358, 0xC000), /* 70004358 */
+ S5K4ECGX_REG_WRITE(0x7000435A, 0xE59F), /* 7000435A */
+ S5K4ECGX_REG_WRITE(0x7000435C, 0xFF1C), /* 7000435C */
+ S5K4ECGX_REG_WRITE(0x7000435E, 0xE12F), /* 7000435E */
+ S5K4ECGX_REG_WRITE(0x70004360, 0xEE03), /* 70004360 */
+ S5K4ECGX_REG_WRITE(0x70004362, 0x0000), /* 70004362 */
+ S5K4ECGX_REG_WRITE(0x70004364, 0x4778), /* 70004364 */
+ S5K4ECGX_REG_WRITE(0x70004366, 0x46C0), /* 70004366 */
+ S5K4ECGX_REG_WRITE(0x70004368, 0xC000), /* 70004368 */
+ S5K4ECGX_REG_WRITE(0x7000436A, 0xE59F), /* 7000436A */
+ S5K4ECGX_REG_WRITE(0x7000436C, 0xFF1C), /* 7000436C */
+ S5K4ECGX_REG_WRITE(0x7000436E, 0xE12F), /* 7000436E */
+ S5K4ECGX_REG_WRITE(0x70004370, 0xA58B), /* 70004370 */
+ S5K4ECGX_REG_WRITE(0x70004372, 0x0000), /* 70004372 */
+ S5K4ECGX_REG_WRITE(0x70004374, 0x4778), /* 70004374 */
+ S5K4ECGX_REG_WRITE(0x70004376, 0x46C0), /* 70004376 */
+ S5K4ECGX_REG_WRITE(0x70004378, 0xC000), /* 70004378 */
+ S5K4ECGX_REG_WRITE(0x7000437A, 0xE59F), /* 7000437A */
+ S5K4ECGX_REG_WRITE(0x7000437C, 0xFF1C), /* 7000437C */
+ S5K4ECGX_REG_WRITE(0x7000437E, 0xE12F), /* 7000437E */
+ S5K4ECGX_REG_WRITE(0x70004380, 0x7C49), /* 70004380 */
+ S5K4ECGX_REG_WRITE(0x70004382, 0x0000), /* 70004382 */
+ S5K4ECGX_REG_WRITE(0x70004384, 0x4778), /* 70004384 */
+ S5K4ECGX_REG_WRITE(0x70004386, 0x46C0), /* 70004386 */
+ S5K4ECGX_REG_WRITE(0x70004388, 0xC000), /* 70004388 */
+ S5K4ECGX_REG_WRITE(0x7000438A, 0xE59F), /* 7000438A */
+ S5K4ECGX_REG_WRITE(0x7000438C, 0xFF1C), /* 7000438C */
+ S5K4ECGX_REG_WRITE(0x7000438E, 0xE12F), /* 7000438E */
+ S5K4ECGX_REG_WRITE(0x70004390, 0x7C63), /* 70004390 */
+ S5K4ECGX_REG_WRITE(0x70004392, 0x0000), /* 70004392 */
+ S5K4ECGX_REG_WRITE(0x70004394, 0x4778), /* 70004394 */
+ S5K4ECGX_REG_WRITE(0x70004396, 0x46C0), /* 70004396 */
+ S5K4ECGX_REG_WRITE(0x70004398, 0xC000), /* 70004398 */
+ S5K4ECGX_REG_WRITE(0x7000439A, 0xE59F), /* 7000439A */
+ S5K4ECGX_REG_WRITE(0x7000439C, 0xFF1C), /* 7000439C */
+ S5K4ECGX_REG_WRITE(0x7000439E, 0xE12F), /* 7000439E */
+ S5K4ECGX_REG_WRITE(0x700043A0, 0x2DB7), /* 700043A0 */
+ S5K4ECGX_REG_WRITE(0x700043A2, 0x0000), /* 700043A2 */
+ S5K4ECGX_REG_WRITE(0x700043A4, 0x4778), /* 700043A4 */
+ S5K4ECGX_REG_WRITE(0x700043A6, 0x46C0), /* 700043A6 */
+ S5K4ECGX_REG_WRITE(0x700043A8, 0xC000), /* 700043A8 */
+ S5K4ECGX_REG_WRITE(0x700043AA, 0xE59F), /* 700043AA */
+ S5K4ECGX_REG_WRITE(0x700043AC, 0xFF1C), /* 700043AC */
+ S5K4ECGX_REG_WRITE(0x700043AE, 0xE12F), /* 700043AE */
+ S5K4ECGX_REG_WRITE(0x700043B0, 0xEB3D), /* 700043B0 */
+ S5K4ECGX_REG_WRITE(0x700043B2, 0x0000), /* 700043B2 */
+ S5K4ECGX_REG_WRITE(0x700043B4, 0x4778), /* 700043B4 */
+ S5K4ECGX_REG_WRITE(0x700043B6, 0x46C0), /* 700043B6 */
+ S5K4ECGX_REG_WRITE(0x700043B8, 0xC000), /* 700043B8 */
+ S5K4ECGX_REG_WRITE(0x700043BA, 0xE59F), /* 700043BA */
+ S5K4ECGX_REG_WRITE(0x700043BC, 0xFF1C), /* 700043BC */
+ S5K4ECGX_REG_WRITE(0x700043BE, 0xE12F), /* 700043BE */
+ S5K4ECGX_REG_WRITE(0x700043C0, 0xF061), /* 700043C0 */
+ S5K4ECGX_REG_WRITE(0x700043C2, 0x0000), /* 700043C2 */
+ S5K4ECGX_REG_WRITE(0x700043C4, 0x4778), /* 700043C4 */
+ S5K4ECGX_REG_WRITE(0x700043C6, 0x46C0), /* 700043C6 */
+ S5K4ECGX_REG_WRITE(0x700043C8, 0xC000), /* 700043C8 */
+ S5K4ECGX_REG_WRITE(0x700043CA, 0xE59F), /* 700043CA */
+ S5K4ECGX_REG_WRITE(0x700043CC, 0xFF1C), /* 700043CC */
+ S5K4ECGX_REG_WRITE(0x700043CE, 0xE12F), /* 700043CE */
+ S5K4ECGX_REG_WRITE(0x700043D0, 0xF0EF), /* 700043D0 */
+ S5K4ECGX_REG_WRITE(0x700043D2, 0x0000), /* 700043D2 */
+ S5K4ECGX_REG_WRITE(0x700043D4, 0x4778), /* 700043D4 */
+ S5K4ECGX_REG_WRITE(0x700043D6, 0x46C0), /* 700043D6 */
+ S5K4ECGX_REG_WRITE(0x700043D8, 0xF004), /* 700043D8 */
+ S5K4ECGX_REG_WRITE(0x700043DA, 0xE51F), /* 700043DA */
+ S5K4ECGX_REG_WRITE(0x700043DC, 0x2824), /* 700043DC */
+ S5K4ECGX_REG_WRITE(0x700043DE, 0x0001), /* 700043DE */
+ S5K4ECGX_REG_WRITE(0x700043E0, 0x4778), /* 700043E0 */
+ S5K4ECGX_REG_WRITE(0x700043E2, 0x46C0), /* 700043E2 */
+ S5K4ECGX_REG_WRITE(0x700043E4, 0xC000), /* 700043E4 */
+ S5K4ECGX_REG_WRITE(0x700043E6, 0xE59F), /* 700043E6 */
+ S5K4ECGX_REG_WRITE(0x700043E8, 0xFF1C), /* 700043E8 */
+ S5K4ECGX_REG_WRITE(0x700043EA, 0xE12F), /* 700043EA */
+ S5K4ECGX_REG_WRITE(0x700043EC, 0x8EDD), /* 700043EC */
+ S5K4ECGX_REG_WRITE(0x700043EE, 0x0000), /* 700043EE */
+ S5K4ECGX_REG_WRITE(0x700043F0, 0x4778), /* 700043F0 */
+ S5K4ECGX_REG_WRITE(0x700043F2, 0x46C0), /* 700043F2 */
+ S5K4ECGX_REG_WRITE(0x700043F4, 0xC000), /* 700043F4 */
+ S5K4ECGX_REG_WRITE(0x700043F6, 0xE59F), /* 700043F6 */
+ S5K4ECGX_REG_WRITE(0x700043F8, 0xFF1C), /* 700043F8 */
+ S5K4ECGX_REG_WRITE(0x700043FA, 0xE12F), /* 700043FA */
+ S5K4ECGX_REG_WRITE(0x700043FC, 0x8DCB), /* 700043FC */
+ S5K4ECGX_REG_WRITE(0x700043FE, 0x0000), /* 700043FE */
+ S5K4ECGX_REG_WRITE(0x70004400, 0x4778), /* 70004400 */
+ S5K4ECGX_REG_WRITE(0x70004402, 0x46C0), /* 70004402 */
+ S5K4ECGX_REG_WRITE(0x70004404, 0xC000), /* 70004404 */
+ S5K4ECGX_REG_WRITE(0x70004406, 0xE59F), /* 70004406 */
+ S5K4ECGX_REG_WRITE(0x70004408, 0xFF1C), /* 70004408 */
+ S5K4ECGX_REG_WRITE(0x7000440A, 0xE12F), /* 7000440A */
+ S5K4ECGX_REG_WRITE(0x7000440C, 0x8E17), /* 7000440C */
+ S5K4ECGX_REG_WRITE(0x7000440E, 0x0000), /* 7000440E */
+ S5K4ECGX_REG_WRITE(0x70004410, 0x4778), /* 70004410 */
+ S5K4ECGX_REG_WRITE(0x70004412, 0x46C0), /* 70004412 */
+ S5K4ECGX_REG_WRITE(0x70004414, 0xC000), /* 70004414 */
+ S5K4ECGX_REG_WRITE(0x70004416, 0xE59F), /* 70004416 */
+ S5K4ECGX_REG_WRITE(0x70004418, 0xFF1C), /* 70004418 */
+ S5K4ECGX_REG_WRITE(0x7000441A, 0xE12F), /* 7000441A */
+ S5K4ECGX_REG_WRITE(0x7000441C, 0x98C5), /* 7000441C */
+ S5K4ECGX_REG_WRITE(0x7000441E, 0x0000), /* 7000441E */
+ S5K4ECGX_REG_WRITE(0x70004420, 0x4778), /* 70004420 */
+ S5K4ECGX_REG_WRITE(0x70004422, 0x46C0), /* 70004422 */
+ S5K4ECGX_REG_WRITE(0x70004424, 0xC000), /* 70004424 */
+ S5K4ECGX_REG_WRITE(0x70004426, 0xE59F), /* 70004426 */
+ S5K4ECGX_REG_WRITE(0x70004428, 0xFF1C), /* 70004428 */
+ S5K4ECGX_REG_WRITE(0x7000442A, 0xE12F), /* 7000442A */
+ S5K4ECGX_REG_WRITE(0x7000442C, 0x7C7D), /* 7000442C */
+ S5K4ECGX_REG_WRITE(0x7000442E, 0x0000), /* 7000442E */
+ S5K4ECGX_REG_WRITE(0x70004430, 0x4778), /* 70004430 */
+ S5K4ECGX_REG_WRITE(0x70004432, 0x46C0), /* 70004432 */
+ S5K4ECGX_REG_WRITE(0x70004434, 0xC000), /* 70004434 */
+ S5K4ECGX_REG_WRITE(0x70004436, 0xE59F), /* 70004436 */
+ S5K4ECGX_REG_WRITE(0x70004438, 0xFF1C), /* 70004438 */
+ S5K4ECGX_REG_WRITE(0x7000443A, 0xE12F), /* 7000443A */
+ S5K4ECGX_REG_WRITE(0x7000443C, 0x7E31), /* 7000443C */
+ S5K4ECGX_REG_WRITE(0x7000443E, 0x0000), /* 7000443E */
+ S5K4ECGX_REG_WRITE(0x70004440, 0x4778), /* 70004440 */
+ S5K4ECGX_REG_WRITE(0x70004442, 0x46C0), /* 70004442 */
+ S5K4ECGX_REG_WRITE(0x70004444, 0xC000), /* 70004444 */
+ S5K4ECGX_REG_WRITE(0x70004446, 0xE59F), /* 70004446 */
+ S5K4ECGX_REG_WRITE(0x70004448, 0xFF1C), /* 70004448 */
+ S5K4ECGX_REG_WRITE(0x7000444A, 0xE12F), /* 7000444A */
+ S5K4ECGX_REG_WRITE(0x7000444C, 0x7EAB), /* 7000444C */
+ S5K4ECGX_REG_WRITE(0x7000444E, 0x0000), /* 7000444E */
+ S5K4ECGX_REG_WRITE(0x70004450, 0x4778), /* 70004450 */
+ S5K4ECGX_REG_WRITE(0x70004452, 0x46C0), /* 70004452 */
+ S5K4ECGX_REG_WRITE(0x70004454, 0xC000), /* 70004454 */
+ S5K4ECGX_REG_WRITE(0x70004456, 0xE59F), /* 70004456 */
+ S5K4ECGX_REG_WRITE(0x70004458, 0xFF1C), /* 70004458 */
+ S5K4ECGX_REG_WRITE(0x7000445A, 0xE12F), /* 7000445A */
+ S5K4ECGX_REG_WRITE(0x7000445C, 0x7501), /* 7000445C */
+ S5K4ECGX_REG_WRITE(0x7000445E, 0x0000), /* 7000445E */
+ /* End of Patch Data(Last : 7000445Eh) */
+ /* Total Size 2408 (0x0968) */
+ /* Addr : 3AF8 , Size : 2406(966h) */
+
+ /* TNP_USER_MBCV_CONTROL */
+ /* TNP_4EC_MBR_TUNE */
+ /* TNP_4EC_FORBIDDEN_TUNE */
+ /* TNP_AF_FINESEARCH_DRIVEBACK */
+ /* TNP_FLASH_ALG */
+ /* TNP_GAS_ALPHA_OTP */
+ /* TNP_AWB_MODUL_COMP */
+ /* TNP_AWB_INIT_QUEUE */
+ /* TNP_AWB_GRID_LOWBR */
+ /* TNP_AWB_GRID_MODULECOMP */
+
+ S5K4ECGX_REG_WRITE(0xD0001000, 0x0001),
+ /* End of FACTORY ONLY. */
+
+ /* AF setting */
+ S5K4ECGX_REG_WRITE(0x700001FC, 0x0001), /* REG_TC_IPRM_LedGpio */
+ /* 70001720 0100 Only STW Use IT */
+ S5K4ECGX_REG_WRITE(0x700001FE, 0x0003),
+ S5K4ECGX_REG_WRITE(0x70000200, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000204, 0x0061),
+ S5K4ECGX_REG_WRITE(0x7000020C, 0x2F0C),
+ S5K4ECGX_REG_WRITE(0x7000020E, 0x0190),
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0238),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0074),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0132),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000070E, 0x00FF),
+ S5K4ECGX_REG_WRITE(0x7000071E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000163C, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001648, 0x9002), /* 2nd search on when 2nd search lens oppsite direction moving */
+ S5K4ECGX_REG_WRITE(0x70001652, 0x0002),
+ S5K4ECGX_REG_WRITE(0x70001654, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700015E0, 0x0801), /* when 2nd search 1code distance 6+1 position move */
+
+ S5K4ECGX_REG_WRITE(0x7000164C, 0x0003),
+ S5K4ECGX_REG_WRITE(0x7000163E, 0x00E5),
+ S5K4ECGX_REG_WRITE(0x70001640, 0x00CC), /* 98(60%) -> CC(80%) */
+ S5K4ECGX_REG_WRITE(0x700015D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700015D6, 0xD000),
+ S5K4ECGX_REG_WRITE(0x7000169A, 0xFF95),
+ S5K4ECGX_REG_WRITE(0x7000166A, 0x0280),
+ S5K4ECGX_REG_WRITE(0x70001676, 0x03A0),
+ S5K4ECGX_REG_WRITE(0x70001678, 0x0320),
+ S5K4ECGX_REG_WRITE(0x700016BC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700016E0, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700016D4, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70001656, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700015E6, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x0015), /* af_pos_usTableLastInd */
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x0032),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0038),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x003E),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x0044),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x004A),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0050),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x0056),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x005C),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x0062),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0068),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x006E),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x0074),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x007A),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70001606, 0x0086),
+ S5K4ECGX_REG_WRITE(0x70001608, 0x008C),
+ S5K4ECGX_REG_WRITE(0x7000160A, 0x0092),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x0098),
+ S5K4ECGX_REG_WRITE(0x7000160E, 0x009E),
+ S5K4ECGX_REG_WRITE(0x70001610, 0x00A4),
+ S5K4ECGX_REG_WRITE(0x70001612, 0x00AA),
+ S5K4ECGX_REG_WRITE(0x70001614, 0x00B0),
+
+ S5K4ECGX_REG_WRITE(0x70001722, 0x8000),
+ S5K4ECGX_REG_WRITE(0x70001724, 0x0006),
+ S5K4ECGX_REG_WRITE(0x70001726, 0x3FF0),
+ S5K4ECGX_REG_WRITE(0x70001728, 0x03E8),
+ S5K4ECGX_REG_WRITE(0x7000172A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000172C, 0x0080), /* delay2 when threshold upper lens moving when moving distance 9 delay 80h 12.8ms delay */
+ S5K4ECGX_REG_WRITE(0x7000172E, 0x0009), /* threshold */
+ S5K4ECGX_REG_WRITE(0x70001730, 0x0020), /* delay1 when threshold lower lens moving when moving lower then 9(1st search position table distance lower then 9) delay 20h 3.2ms delay */
+ S5K4ECGX_REG_WRITE(0x70001732, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70001734, 0x0080),
+ S5K4ECGX_REG_WRITE(0x70001736, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70001738, 0x00E0),
+
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0003), /* REG_TC_AF_AfCmd */
+
+ /* GAS TBL setting */
+ S5K4ECGX_REG_WRITE(0x700008B4, 0x0001), /* wbt_bUseOutdoorASH */
+
+ /* TVAR_ash_AwbAshCord Refer Mon_AWB_RotGain */
+ S5K4ECGX_REG_WRITE(0x700008BC, 0x00C0), /* TVAR_ash_AwbAshCord_0_ 2300K */
+ S5K4ECGX_REG_WRITE(0x700008BE, 0x00DF), /* TVAR_ash_AwbAshCord_1_ 2750K */
+ S5K4ECGX_REG_WRITE(0x700008C0, 0x0100), /* TVAR_ash_AwbAshCord_2_ 3300K */
+ S5K4ECGX_REG_WRITE(0x700008C2, 0x0125), /* TVAR_ash_AwbAshCord_3_ 4150K */
+ S5K4ECGX_REG_WRITE(0x700008C4, 0x015F), /* TVAR_ash_AwbAshCord_4_ 5250K */
+ S5K4ECGX_REG_WRITE(0x700008C6, 0x017C), /* TVAR_ash_AwbAshCord_5_ 6400K */
+ S5K4ECGX_REG_WRITE(0x700008C8, 0x0194), /* TVAR_ash_AwbAshCord_6_ 7500K */
+
+ S5K4ECGX_REG_WRITE(0x700008F6, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008F8, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FA, 0x4000),
+ S5K4ECGX_REG_WRITE(0x700008FC, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x700008FE, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000900, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000902, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000904, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x70000906, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000908, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000090C, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x7000090E, 0x3800), /* 4000 */
+ S5K4ECGX_REG_WRITE(0x70000910, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000912, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000914, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x70000916, 0x3B00), /* 5000 */
+ S5K4ECGX_REG_WRITE(0x70000918, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000091A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000091C, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x7000091E, 0x4300), /* 6500 */
+ S5K4ECGX_REG_WRITE(0x70000920, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000922, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000924, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x70000926, 0x4300), /* 7400 */
+ S5K4ECGX_REG_WRITE(0x70000928, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000092A, 0x4000),
+ S5K4ECGX_REG_WRITE(0x7000092C, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x7000092E, 0x4500), /* 4500 */
+ S5K4ECGX_REG_WRITE(0x70000930, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000932, 0x4000),
+ S5K4ECGX_REG_WRITE(0x70000934, 0x4000),
+
+ S5K4ECGX_REG_WRITE(0x700008F4, 0x0001), /* ash_bUseGasAlpha */
+
+ /* AE START */
+ /* AE WEIGHT */
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0201),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0302),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0203),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0302),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0203),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0101),
+
+ S5K4ECGX_REG_WRITE(0x70001484, 0x003C), /* TVAR_ae_BrAve */
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x000F), /* ae_StatMode */
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000), /* lt_uMaxExp1 */
+ S5K4ECGX_REG_WRITE(0x70000590, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0000), /* lt_uMaxExp2 */
+ S5K4ECGX_REG_WRITE(0x70000594, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0000), /* lt_uCapMaxExp1 */
+ S5K4ECGX_REG_WRITE(0x70000598, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000059A, 0x0000), /* lt_uCapMaxExp2 */
+ S5K4ECGX_REG_WRITE(0x7000059C, 0x0470), /* lt_uMaxAnGain1 */
+ S5K4ECGX_REG_WRITE(0x7000059E, 0x0C00), /* lt_uMaxAnGain2 */
+ S5K4ECGX_REG_WRITE(0x700005A0, 0x0100), /* lt_uMaxDigGain */
+ S5K4ECGX_REG_WRITE(0x700005A2, 0x1000), /* lt_uMaxTotGain */
+
+ S5K4ECGX_REG_WRITE(0x70000544, 0x0111), /* lt_uLimitHigh */
+ S5K4ECGX_REG_WRITE(0x70000546, 0x00EF), /* lt_uLimitLow */
+
+ S5K4ECGX_REG_WRITE(0x70000F2A, 0x0000), /* AFC_Default60Hz 0001:60Hz 0000h:50Hz */
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F), /* REG_TC_DBG */
+
+ S5K4ECGX_REG_WRITE(0x70000F30, 0x0001), /* AFC_D_ConvAccelerPower */
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0800), /* lt_ExpGain_ExpCurveGainMaxStr */
+ S5K4ECGX_REG_WRITE(0x7000060E, 0x0100), /* 0100 //lt_ExpGain_ExpCurveGainMaxStr_0__uMaxDigGain */
+ S5K4ECGX_REG_WRITE(0x70000610, 0x0001), /* 0001 */
+ S5K4ECGX_REG_WRITE(0x70000612, 0x0000), /* 0000 //lt_ExpGain_ExpCurveGainMaxStr_0__ulExpIn_0_ */
+ S5K4ECGX_REG_WRITE(0x70000614, 0x0A3C), /* 0A3C */
+ S5K4ECGX_REG_WRITE(0x70000616, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000618, 0x0D05), /* 0D05 */
+ S5K4ECGX_REG_WRITE(0x7000061A, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x7000061C, 0x4008), /* 4008 */
+ S5K4ECGX_REG_WRITE(0x7000061E, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000620, 0x7000), /* 7400 //?? //700Lux */
+ S5K4ECGX_REG_WRITE(0x70000622, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000624, 0x9C00), /* C000 //?? //9C00->9F->A5 //400Lux */
+ S5K4ECGX_REG_WRITE(0x70000626, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000628, 0xAD00), /* AD00 */
+ S5K4ECGX_REG_WRITE(0x7000062A, 0x0001), /* 0001 */
+ S5K4ECGX_REG_WRITE(0x7000062C, 0xF1D4), /* F1D4 */
+ S5K4ECGX_REG_WRITE(0x7000062E, 0x0002), /* 0002 */
+ S5K4ECGX_REG_WRITE(0x70000630, 0xDC00), /* DC00 */
+ S5K4ECGX_REG_WRITE(0x70000632, 0x0005), /* 0005 */
+ S5K4ECGX_REG_WRITE(0x70000634, 0xDC00), /* DC00 */
+ S5K4ECGX_REG_WRITE(0x70000636, 0x0005), /* 0005 */
+ //
+ S5K4ECGX_REG_WRITE(0x70000638, 0x0001), /* 0001 */
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000), /* 0000 //lt_ExpGain_ExpCurveGainMaxStr_0__ulExpOut_0_ */
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x0A3C), /* 0A3C */
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000640, 0x0D05), /* 0D05 */
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000644, 0x3408), /* 3408 */
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000648, 0x3408), /* 3408 */
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x7000064C, 0x6810), /* 6810 */
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000650, 0x8214), /* 8214 */
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000654, 0xC350), /* C350 */
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x70000658, 0xC350), /* C350 */
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0000), /* 0000 */
+ S5K4ECGX_REG_WRITE(0x7000065C, 0xC350), /* C350 */
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0000), /* 0000 */
+
+ S5K4ECGX_REG_WRITE(0x70000660, 0x0650), /* lt_ExpGain_ExpCurveGainMaxStr_1_ */
+ S5K4ECGX_REG_WRITE(0x70000662, 0x0100), /* lt_ExpGain_ExpCurveGainMaxStr_1__uMaxDigGain */
+
+ S5K4ECGX_REG_WRITE(0x700006B8, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x0005), /* lt_uMaxLei */
+
+ S5K4ECGX_REG_WRITE(0x700005D0, 0x0000), /* lt_mbr_Peak_behind */
+
+ /* AWB init Start point */
+ S5K4ECGX_REG_WRITE(0x7000145E, 0x0580),
+ S5K4ECGX_REG_WRITE(0x70001460, 0x0428),
+ S5K4ECGX_REG_WRITE(0x70001462, 0x07B0),
+
+ /* AWB Init */
+ /* White Locus */
+ S5K4ECGX_REG_WRITE(0x700011F0, 0x0120), /* awbb_IntcR */
+ S5K4ECGX_REG_WRITE(0x700011F2, 0x0121), /* awbb_IntcB */
+
+ /* IndoorZone */
+ S5K4ECGX_REG_WRITE(0x7000101C, 0x037C),
+ S5K4ECGX_REG_WRITE(0x7000101E, 0x038E),
+ S5K4ECGX_REG_WRITE(0x70001020, 0x033C),
+ S5K4ECGX_REG_WRITE(0x70001022, 0x0384),
+ S5K4ECGX_REG_WRITE(0x70001024, 0x02FE),
+ S5K4ECGX_REG_WRITE(0x70001026, 0x036C),
+ S5K4ECGX_REG_WRITE(0x70001028, 0x02BA),
+ S5K4ECGX_REG_WRITE(0x7000102A, 0x0352),
+ S5K4ECGX_REG_WRITE(0x7000102C, 0x028E),
+ S5K4ECGX_REG_WRITE(0x7000102E, 0x0300),
+ S5K4ECGX_REG_WRITE(0x70001030, 0x026A),
+ S5K4ECGX_REG_WRITE(0x70001032, 0x02C8),
+ S5K4ECGX_REG_WRITE(0x70001034, 0x0254),
+ S5K4ECGX_REG_WRITE(0x70001036, 0x02A8),
+ S5K4ECGX_REG_WRITE(0x70001038, 0x0242),
+ S5K4ECGX_REG_WRITE(0x7000103A, 0x02A0),
+ S5K4ECGX_REG_WRITE(0x7000103C, 0x021A),
+ S5K4ECGX_REG_WRITE(0x7000103E, 0x02A0),
+ S5K4ECGX_REG_WRITE(0x70001040, 0x01F4),
+ S5K4ECGX_REG_WRITE(0x70001042, 0x0298),
+ S5K4ECGX_REG_WRITE(0x70001044, 0x01D4),
+ S5K4ECGX_REG_WRITE(0x70001046, 0x0290),
+ S5K4ECGX_REG_WRITE(0x70001048, 0x01CC),
+ S5K4ECGX_REG_WRITE(0x7000104A, 0x0276),
+ S5K4ECGX_REG_WRITE(0x7000104C, 0x01D2),
+ S5K4ECGX_REG_WRITE(0x7000104E, 0x0260),
+ S5K4ECGX_REG_WRITE(0x70001050, 0x01F6),
+ S5K4ECGX_REG_WRITE(0x70001052, 0x023A),
+ S5K4ECGX_REG_WRITE(0x70001054, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001056, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001058, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000105E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001060, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001062, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001064, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001066, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001068, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000106A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000106C, 0x0005), /* awbb_IndoorGrZones_m_GridStep */
+ S5K4ECGX_REG_WRITE(0x70001070, 0x000E), /* awbb_IndoorGrZones_ZInfo_m_GridSz */
+ S5K4ECGX_REG_WRITE(0x70001074, 0x0126), /* awbb_IndoorGrZones_m_Boffs */
+
+ /* Outdoor Zone */
+ S5K4ECGX_REG_WRITE(0x70001078, 0x0272),
+ S5K4ECGX_REG_WRITE(0x7000107A, 0x02A0),
+ S5K4ECGX_REG_WRITE(0x7000107C, 0x025A),
+ S5K4ECGX_REG_WRITE(0x7000107E, 0x02BC),
+ S5K4ECGX_REG_WRITE(0x70001080, 0x024A),
+ S5K4ECGX_REG_WRITE(0x70001082, 0x02C0),
+ S5K4ECGX_REG_WRITE(0x70001084, 0x023C),
+ S5K4ECGX_REG_WRITE(0x70001086, 0x02BE),
+ S5K4ECGX_REG_WRITE(0x70001088, 0x022E),
+ S5K4ECGX_REG_WRITE(0x7000108A, 0x02BC),
+ S5K4ECGX_REG_WRITE(0x7000108C, 0x0224),
+ S5K4ECGX_REG_WRITE(0x7000108E, 0x02B6),
+ S5K4ECGX_REG_WRITE(0x70001090, 0x0218),
+ S5K4ECGX_REG_WRITE(0x70001092, 0x02AA),
+ S5K4ECGX_REG_WRITE(0x70001094, 0x0210),
+ S5K4ECGX_REG_WRITE(0x70001096, 0x02A0),
+ S5K4ECGX_REG_WRITE(0x70001098, 0x020C),
+ S5K4ECGX_REG_WRITE(0x7000109A, 0x0296),
+ S5K4ECGX_REG_WRITE(0x7000109C, 0x020A),
+ S5K4ECGX_REG_WRITE(0x7000109E, 0x028C),
+ S5K4ECGX_REG_WRITE(0x700010A0, 0x0212),
+ S5K4ECGX_REG_WRITE(0x700010A2, 0x027E),
+ S5K4ECGX_REG_WRITE(0x700010A4, 0x0234),
+ S5K4ECGX_REG_WRITE(0x700010A6, 0x0256),
+
+ S5K4ECGX_REG_WRITE(0x700010A8, 0x0004), /* awbb_OutdoorGrZones_m_GridStep */
+ S5K4ECGX_REG_WRITE(0x700010AC, 0x000C), /* awbb_OutdoorGrZones_ZInfo_m_GridSz */
+ S5K4ECGX_REG_WRITE(0x700010B0, 0x01D8), /* awbb_OutdoorGrZones_m_Boffs */
+
+ /* LowBR Zone */
+ S5K4ECGX_REG_WRITE(0x700010B4, 0x0350),
+ S5K4ECGX_REG_WRITE(0x700010B6, 0x0422),
+ S5K4ECGX_REG_WRITE(0x700010B8, 0x02C4),
+ S5K4ECGX_REG_WRITE(0x700010BA, 0x0452),
+ S5K4ECGX_REG_WRITE(0x700010BC, 0x0278),
+ S5K4ECGX_REG_WRITE(0x700010BE, 0x041C),
+ S5K4ECGX_REG_WRITE(0x700010C0, 0x0230),
+ S5K4ECGX_REG_WRITE(0x700010C2, 0x03EE),
+ S5K4ECGX_REG_WRITE(0x700010C4, 0x01F0),
+ S5K4ECGX_REG_WRITE(0x700010C6, 0x0392),
+ S5K4ECGX_REG_WRITE(0x700010C8, 0x01C0),
+ S5K4ECGX_REG_WRITE(0x700010CA, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700010CC, 0x0194),
+ S5K4ECGX_REG_WRITE(0x700010CE, 0x0302),
+ S5K4ECGX_REG_WRITE(0x700010D0, 0x016E),
+ S5K4ECGX_REG_WRITE(0x700010D2, 0x02C2),
+ S5K4ECGX_REG_WRITE(0x700010D4, 0x0148),
+ S5K4ECGX_REG_WRITE(0x700010D6, 0x0286),
+ S5K4ECGX_REG_WRITE(0x700010D8, 0x018A),
+ S5K4ECGX_REG_WRITE(0x700010DA, 0x0242),
+ S5K4ECGX_REG_WRITE(0x700010DC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010DE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010E0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700010E2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700010E4, 0x0006), /* awbb_LowBrGrZones_m_GridStep */
+ S5K4ECGX_REG_WRITE(0x700010E8, 0x000A), /* awbb_LowBrGrZones_ZInfo_m_GridSz */
+ S5K4ECGX_REG_WRITE(0x700010EC, 0x0106), /* awbb_LowBrGrZones_m_Boffs */
+
+ /* LowTemp Zone */
+ S5K4ECGX_REG_WRITE(0x700010F0, 0x0380),
+ S5K4ECGX_REG_WRITE(0x700010F2, 0x0000), /* awbb_CrclLowT_R_c */
+ S5K4ECGX_REG_WRITE(0x700010F4, 0x0168),
+ S5K4ECGX_REG_WRITE(0x700010F6, 0x0000), /* awbb_CrclLowT_B_c */
+ S5K4ECGX_REG_WRITE(0x700010F8, 0x2D90),
+ S5K4ECGX_REG_WRITE(0x700010FA, 0x0000), /* awbb_CrclLowT_Rad_c */
+
+ /* AWB Convergence Speed */
+ S5K4ECGX_REG_WRITE(0x70001464, 0x0008),
+ S5K4ECGX_REG_WRITE(0x70001466, 0x0190),
+ S5K4ECGX_REG_WRITE(0x70001468, 0x00A0),
+
+ S5K4ECGX_REG_WRITE(0x70001228, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000122C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000122A, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x7000120A, 0x05D5), /* awbb_MvEq_RBthresh */
+ S5K4ECGX_REG_WRITE(0x7000120E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001210, 0x0771),
+ S5K4ECGX_REG_WRITE(0x70001212, 0x03A4),
+ S5K4ECGX_REG_WRITE(0x70001214, 0x0036),
+ S5K4ECGX_REG_WRITE(0x70001216, 0x002A),
+
+ S5K4ECGX_REG_WRITE(0x70001278, 0xFEF7),
+ S5K4ECGX_REG_WRITE(0x7000127A, 0x0021),
+ S5K4ECGX_REG_WRITE(0x7000127C, 0x0AF0), /* 0E74 */
+ S5K4ECGX_REG_WRITE(0x7000127E, 0x0AF0), /* 0E74 */
+ S5K4ECGX_REG_WRITE(0x70001280, 0x018F),
+ S5K4ECGX_REG_WRITE(0x70001282, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001284, 0x000E),
+ S5K4ECGX_REG_WRITE(0x70001224, 0x0032),
+ S5K4ECGX_REG_WRITE(0x70001226, 0x001E),
+ S5K4ECGX_REG_WRITE(0x70001228, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000122A, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000122C, 0x0002), /* awbb_YThreshLow_Low */
+ S5K4ECGX_REG_WRITE(0x70002BA4, 0x0006), /* Mon_AWB_ByPassMode */
+
+ S5K4ECGX_REG_WRITE(0x7000146C, 0x0002), /* awbb_GridEnable */
+
+ /* Grid */
+ S5K4ECGX_REG_WRITE(0x70001434, 0x02CE), /* awbb_GridConst_1 */
+ S5K4ECGX_REG_WRITE(0x70001436, 0x0347), /* awbb_GridConst_1_1_ */
+ S5K4ECGX_REG_WRITE(0x70001438, 0x03C2), /* awbb_GridConst_1_2_ */
+ S5K4ECGX_REG_WRITE(0x7000143A, 0x10A0), /* awbb_GridConst_2 */
+ S5K4ECGX_REG_WRITE(0x7000143C, 0x10A1), /* awbb_GridConst_2_1_ */
+ S5K4ECGX_REG_WRITE(0x7000143E, 0x1185), /* awbb_GridConst_2_2_ */
+ S5K4ECGX_REG_WRITE(0x70001440, 0x1186), /* awbb_GridConst_2_3_ */
+ S5K4ECGX_REG_WRITE(0x70001442, 0x11E5), /* awbb_GridConst_2_4_ */
+ S5K4ECGX_REG_WRITE(0x70001444, 0x11E6), /* awbb_GridConst_2_5_ */
+ S5K4ECGX_REG_WRITE(0x70001446, 0x00AB), /* awbb_GridCoeff_R_1 */
+ S5K4ECGX_REG_WRITE(0x70001448, 0x00BF), /* awbb_GridCoeff_B_1 */
+ S5K4ECGX_REG_WRITE(0x7000144A, 0x00D2), /* awbb_GridCoeff_R_2 */
+ S5K4ECGX_REG_WRITE(0x7000144C, 0x0093), /* awbb_GridCoeff_B_2 */
+
+ /* Indoor Grid Offset */
+ S5K4ECGX_REG_WRITE(0x700013A4, 0xFFF6), /* 0426 0000 //0000 */
+ S5K4ECGX_REG_WRITE(0x700013A6, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013A8, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013AA, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013AC, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013AE, 0xFFD0), /* FFF6 B */
+ //
+ S5K4ECGX_REG_WRITE(0x700013B0, 0xFFF6), /* 0426 0000 //0000 */
+ S5K4ECGX_REG_WRITE(0x700013B2, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013B4, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013B6, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013B8, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013BA, 0xFFD0), /* FFF6 */
+ //
+ S5K4ECGX_REG_WRITE(0x700013BC, 0xFFF6), /* 0426 0000 //0000 */
+ S5K4ECGX_REG_WRITE(0x700013BE, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013C0, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013C2, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013C4, 0xFFD8), /* FFD8 */
+ S5K4ECGX_REG_WRITE(0x700013C6, 0xFFD0), /* FFF6 */
+ //
+ S5K4ECGX_REG_WRITE(0x700013C8, 0xFFEC), /* FFEC */
+ S5K4ECGX_REG_WRITE(0x700013CA, 0x000A), /* 000A */
+ S5K4ECGX_REG_WRITE(0x700013CC, 0x000A), /* 000A */
+ S5K4ECGX_REG_WRITE(0x700013CE, 0x0050), /* FFF6 // 0425 FFC4 //FFC4 */
+ S5K4ECGX_REG_WRITE(0x700013D0, 0x0050), /* FFF6 // 0425 FFC4 //FFC4 */
+ S5K4ECGX_REG_WRITE(0x700013D2, 0x0078), /* 0000 // 0425 FF66 //FF56 7 */
+ //
+ S5K4ECGX_REG_WRITE(0x700013D4, 0xFFEC), /* FFEC */
+ S5K4ECGX_REG_WRITE(0x700013D6, 0x000A), /* 000A */
+ S5K4ECGX_REG_WRITE(0x700013D8, 0x000A), /* 000A */
+ S5K4ECGX_REG_WRITE(0x700013DA, 0x0050), /* FFF6 // 0425 FFC4 //FFC4 */
+ S5K4ECGX_REG_WRITE(0x700013DC, 0x0050), /* FFF6 // 0425 FFC4 //FFC4 */
+ S5K4ECGX_REG_WRITE(0x700013DE, 0x0078), /* 0000 // 0425 FF66 //FF56 */
+ //
+ S5K4ECGX_REG_WRITE(0x700013E0, 0xFFEC), /* FFEC */
+ S5K4ECGX_REG_WRITE(0x700013E2, 0x000A), /* 000A */
+ S5K4ECGX_REG_WRITE(0x700013E4, 0x000A), /* 000A */
+ S5K4ECGX_REG_WRITE(0x700013E6, 0x0050), /* FFF6 // 0425 FFC4 //FFC4 */
+ S5K4ECGX_REG_WRITE(0x700013E8, 0x0050), /* FFF6 // 0425 FFC4 //FFC4 */
+ S5K4ECGX_REG_WRITE(0x700013EA, 0x0078), /* 0000 // 0425 FF66 //FF56 */
+
+ /* Outdoor Grid Offset */
+ S5K4ECGX_REG_WRITE(0x700013EC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013EE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013F0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013F2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013F4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013F6, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700013F8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013FA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700013FE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001400, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001402, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001404, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001406, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001408, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000140A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000140C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000140E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001410, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001412, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001414, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001416, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001418, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000141A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000141C, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x7000141E, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001420, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x70001422, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001424, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001426, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001428, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x7000142A, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x7000142C, 0xFFC0),
+ S5K4ECGX_REG_WRITE(0x7000142E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001430, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001432, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001208, 0x0020),
+
+ S5K4ECGX_REG_WRITE(0x7000144E, 0x0000), /* awbb_RGainOff */
+ S5K4ECGX_REG_WRITE(0x70001450, 0xFFE0), /* awbb_BGainOff */
+ S5K4ECGX_REG_WRITE(0x70001452, 0x0000), /* awbb_GGainOff */
+
+ /* RGB Indoor Gamma */
+ S5K4ECGX_REG_WRITE(0x70000734, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000736, 0x000A),
+ S5K4ECGX_REG_WRITE(0x70000738, 0x0016),
+ S5K4ECGX_REG_WRITE(0x7000073A, 0x0030),
+ S5K4ECGX_REG_WRITE(0x7000073C, 0x0066),
+ S5K4ECGX_REG_WRITE(0x7000073E, 0x00D5),
+ S5K4ECGX_REG_WRITE(0x70000740, 0x0138),
+ S5K4ECGX_REG_WRITE(0x70000742, 0x0163),
+ S5K4ECGX_REG_WRITE(0x70000744, 0x0189),
+ S5K4ECGX_REG_WRITE(0x70000746, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x70000748, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000074A, 0x0222),
+ S5K4ECGX_REG_WRITE(0x7000074C, 0x0247),
+ S5K4ECGX_REG_WRITE(0x7000074E, 0x0282),
+ S5K4ECGX_REG_WRITE(0x70000750, 0x02B5),
+ S5K4ECGX_REG_WRITE(0x70000752, 0x030F),
+ S5K4ECGX_REG_WRITE(0x70000754, 0x035F),
+ S5K4ECGX_REG_WRITE(0x70000756, 0x03A2),
+ S5K4ECGX_REG_WRITE(0x70000758, 0x03D8),
+ S5K4ECGX_REG_WRITE(0x7000075A, 0x03FF),
+ S5K4ECGX_REG_WRITE(0x7000075C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000075E, 0x000A),
+ S5K4ECGX_REG_WRITE(0x70000760, 0x0016),
+ S5K4ECGX_REG_WRITE(0x70000762, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70000764, 0x0066),
+ S5K4ECGX_REG_WRITE(0x70000766, 0x00D5),
+ S5K4ECGX_REG_WRITE(0x70000768, 0x0138),
+ S5K4ECGX_REG_WRITE(0x7000076A, 0x0163),
+ S5K4ECGX_REG_WRITE(0x7000076C, 0x0189),
+ S5K4ECGX_REG_WRITE(0x7000076E, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x70000770, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x70000772, 0x0222),
+ S5K4ECGX_REG_WRITE(0x70000774, 0x0247),
+ S5K4ECGX_REG_WRITE(0x70000776, 0x0282),
+ S5K4ECGX_REG_WRITE(0x70000778, 0x02B5),
+ S5K4ECGX_REG_WRITE(0x7000077A, 0x030F),
+ S5K4ECGX_REG_WRITE(0x7000077C, 0x035F),
+ S5K4ECGX_REG_WRITE(0x7000077E, 0x03A2),
+ S5K4ECGX_REG_WRITE(0x70000780, 0x03D8),
+ S5K4ECGX_REG_WRITE(0x70000782, 0x03FF),
+ S5K4ECGX_REG_WRITE(0x70000784, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000786, 0x000A),
+ S5K4ECGX_REG_WRITE(0x70000788, 0x0016),
+ S5K4ECGX_REG_WRITE(0x7000078A, 0x0030),
+ S5K4ECGX_REG_WRITE(0x7000078C, 0x0066),
+ S5K4ECGX_REG_WRITE(0x7000078E, 0x00D5),
+ S5K4ECGX_REG_WRITE(0x70000790, 0x0138),
+ S5K4ECGX_REG_WRITE(0x70000792, 0x0163),
+ S5K4ECGX_REG_WRITE(0x70000794, 0x0189),
+ S5K4ECGX_REG_WRITE(0x70000796, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x70000798, 0x01F8),
+ S5K4ECGX_REG_WRITE(0x7000079A, 0x0222),
+ S5K4ECGX_REG_WRITE(0x7000079C, 0x0247),
+ S5K4ECGX_REG_WRITE(0x7000079E, 0x0282),
+ S5K4ECGX_REG_WRITE(0x700007A0, 0x02B5),
+ S5K4ECGX_REG_WRITE(0x700007A2, 0x030F),
+ S5K4ECGX_REG_WRITE(0x700007A4, 0x035F),
+ S5K4ECGX_REG_WRITE(0x700007A6, 0x03A2),
+ S5K4ECGX_REG_WRITE(0x700007A8, 0x03D8),
+ S5K4ECGX_REG_WRITE(0x700007AA, 0x03FF),
+
+ /* RGB Outdoor Gamma */
+ S5K4ECGX_REG_WRITE(0x700007AC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700007AE, 0x000B),
+ S5K4ECGX_REG_WRITE(0x700007B0, 0x0019),
+ S5K4ECGX_REG_WRITE(0x700007B2, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700007B4, 0x006F),
+ S5K4ECGX_REG_WRITE(0x700007B6, 0x00D8),
+ S5K4ECGX_REG_WRITE(0x700007B8, 0x0135),
+ S5K4ECGX_REG_WRITE(0x700007BA, 0x015F),
+ S5K4ECGX_REG_WRITE(0x700007BC, 0x0185),
+ S5K4ECGX_REG_WRITE(0x700007BE, 0x01C1),
+ S5K4ECGX_REG_WRITE(0x700007C0, 0x01F3),
+ S5K4ECGX_REG_WRITE(0x700007C2, 0x0220),
+ S5K4ECGX_REG_WRITE(0x700007C4, 0x024A),
+ S5K4ECGX_REG_WRITE(0x700007C6, 0x0291),
+ S5K4ECGX_REG_WRITE(0x700007C8, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700007CA, 0x032A),
+ S5K4ECGX_REG_WRITE(0x700007CC, 0x036A),
+ S5K4ECGX_REG_WRITE(0x700007CE, 0x039F),
+ S5K4ECGX_REG_WRITE(0x700007D0, 0x03CC),
+ S5K4ECGX_REG_WRITE(0x700007D2, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x700007D4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700007D6, 0x000B),
+ S5K4ECGX_REG_WRITE(0x700007D8, 0x0019),
+ S5K4ECGX_REG_WRITE(0x700007DA, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700007DC, 0x006F),
+ S5K4ECGX_REG_WRITE(0x700007DE, 0x00D8),
+ S5K4ECGX_REG_WRITE(0x700007E0, 0x0135),
+ S5K4ECGX_REG_WRITE(0x700007E2, 0x015F),
+ S5K4ECGX_REG_WRITE(0x700007E4, 0x0185),
+ S5K4ECGX_REG_WRITE(0x700007E6, 0x01C1),
+ S5K4ECGX_REG_WRITE(0x700007E8, 0x01F3),
+ S5K4ECGX_REG_WRITE(0x700007EA, 0x0220),
+ S5K4ECGX_REG_WRITE(0x700007EC, 0x024A),
+ S5K4ECGX_REG_WRITE(0x700007EE, 0x0291),
+ S5K4ECGX_REG_WRITE(0x700007F0, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700007F2, 0x032A),
+ S5K4ECGX_REG_WRITE(0x700007F4, 0x036A),
+ S5K4ECGX_REG_WRITE(0x700007F6, 0x039F),
+ S5K4ECGX_REG_WRITE(0x700007F8, 0x03CC),
+ S5K4ECGX_REG_WRITE(0x700007FA, 0x03F9),
+ S5K4ECGX_REG_WRITE(0x700007FC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700007FE, 0x000B),
+ S5K4ECGX_REG_WRITE(0x70000800, 0x0019),
+ S5K4ECGX_REG_WRITE(0x70000802, 0x0036),
+ S5K4ECGX_REG_WRITE(0x70000804, 0x006F),
+ S5K4ECGX_REG_WRITE(0x70000806, 0x00D8),
+ S5K4ECGX_REG_WRITE(0x70000808, 0x0135),
+ S5K4ECGX_REG_WRITE(0x7000080A, 0x015F),
+ S5K4ECGX_REG_WRITE(0x7000080C, 0x0185),
+ S5K4ECGX_REG_WRITE(0x7000080E, 0x01C1),
+ S5K4ECGX_REG_WRITE(0x70000810, 0x01F3),
+ S5K4ECGX_REG_WRITE(0x70000812, 0x0220),
+ S5K4ECGX_REG_WRITE(0x70000814, 0x024A),
+ S5K4ECGX_REG_WRITE(0x70000816, 0x0291),
+ S5K4ECGX_REG_WRITE(0x70000818, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x7000081A, 0x032A),
+ S5K4ECGX_REG_WRITE(0x7000081C, 0x036A),
+ S5K4ECGX_REG_WRITE(0x7000081E, 0x039F),
+ S5K4ECGX_REG_WRITE(0x70000820, 0x03CC),
+ S5K4ECGX_REG_WRITE(0x70000822, 0x03F9),
+
+ /* CCM */
+ S5K4ECGX_REG_WRITE(0x700008A6, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x700008A8, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700008AA, 0x0125),
+ S5K4ECGX_REG_WRITE(0x700008AC, 0x015F),
+ S5K4ECGX_REG_WRITE(0x700008AE, 0x017C),
+ S5K4ECGX_REG_WRITE(0x700008B0, 0x0194),
+
+ S5K4ECGX_REG_WRITE(0x700008B2, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000898, 0x4800),
+ S5K4ECGX_REG_WRITE(0x7000089A, 0x7000),
+ S5K4ECGX_REG_WRITE(0x700008A0, 0x48D8),
+ S5K4ECGX_REG_WRITE(0x700008A2, 0x7000),
+
+ S5K4ECGX_REG_WRITE(0x70004800, 0x024C), /* 0426 0208 */
+ S5K4ECGX_REG_WRITE(0x70004802, 0xFF5E), /* 0426 FFB5 */
+ S5K4ECGX_REG_WRITE(0x70004804, 0xFF9D), /* 0426 FFE8 */
+ S5K4ECGX_REG_WRITE(0x70004806, 0xFEC9), /* 0426 FF20 */
+ S5K4ECGX_REG_WRITE(0x70004808, 0x0203), /* 0426 01BF */
+ S5K4ECGX_REG_WRITE(0x7000480A, 0xFF08), /* 0426 FF53 */
+ S5K4ECGX_REG_WRITE(0x7000480C, 0xFFDB), /* 0426 0022 */
+ S5K4ECGX_REG_WRITE(0x7000480E, 0xFF8F), /* 0426 FFEA */
+ S5K4ECGX_REG_WRITE(0x70004810, 0x0206), /* 0426 01C2 */
+ S5K4ECGX_REG_WRITE(0x70004812, 0x00E0), /* 0426 00C6 */
+ S5K4ECGX_REG_WRITE(0x70004814, 0x009F), /* 0426 0095 */
+ S5K4ECGX_REG_WRITE(0x70004816, 0xFE7B), /* 0426 FEFD */
+ S5K4ECGX_REG_WRITE(0x70004818, 0x0227), /* 0426 0206 */
+ S5K4ECGX_REG_WRITE(0x7000481A, 0xFEFE), /* 0426 FF7F */
+ S5K4ECGX_REG_WRITE(0x7000481C, 0x0194), /* 0426 0191 */
+ S5K4ECGX_REG_WRITE(0x7000481E, 0xFE86), /* 0426 FF06 */
+ S5K4ECGX_REG_WRITE(0x70004820, 0x01E0), /* 0426 01BA */
+ S5K4ECGX_REG_WRITE(0x70004822, 0x0104), /* 0426 0108 */
+
+ S5K4ECGX_REG_WRITE(0x70004824, 0x024C), /* 0426 0208 // inca A */
+ S5K4ECGX_REG_WRITE(0x70004826, 0xFF5E), /* 0426 FFB5 */
+ S5K4ECGX_REG_WRITE(0x70004828, 0xFF9D), /* 0426 FFE8 */
+ S5K4ECGX_REG_WRITE(0x7000482A, 0xFEC9), /* 0426 FF20 */
+ S5K4ECGX_REG_WRITE(0x7000482C, 0x0203), /* 0426 01BF */
+ S5K4ECGX_REG_WRITE(0x7000482E, 0xFF08), /* 0426 FF53 */
+ S5K4ECGX_REG_WRITE(0x70004830, 0xFFDB), /* 0426 0022 */
+ S5K4ECGX_REG_WRITE(0x70004832, 0xFF8F), /* 0426 FFEA */
+ S5K4ECGX_REG_WRITE(0x70004834, 0x0206), /* 0426 01C2 */
+ S5K4ECGX_REG_WRITE(0x70004836, 0x00E0), /* 0426 00C6 */
+ S5K4ECGX_REG_WRITE(0x70004838, 0x009F), /* 0426 0095 */
+ S5K4ECGX_REG_WRITE(0x7000483A, 0xFE7B), /* 0426 FEFD */
+ S5K4ECGX_REG_WRITE(0x7000483C, 0x0227), /* 0426 0206 */
+ S5K4ECGX_REG_WRITE(0x7000483E, 0xFEFE), /* 0426 FF7F */
+ S5K4ECGX_REG_WRITE(0x70004840, 0x0194), /* 0426 0191 */
+ S5K4ECGX_REG_WRITE(0x70004842, 0xFE86), /* 0426 FF06 */
+ S5K4ECGX_REG_WRITE(0x70004844, 0x01E0), /* 0426 01BA */
+ S5K4ECGX_REG_WRITE(0x70004846, 0x0104), /* 0426 0108 */
+
+ S5K4ECGX_REG_WRITE(0x70004848, 0x0208), /* WW */
+ S5K4ECGX_REG_WRITE(0x7000484A, 0xFFB5),
+ S5K4ECGX_REG_WRITE(0x7000484C, 0xFFE8),
+ S5K4ECGX_REG_WRITE(0x7000484E, 0xFF20),
+ S5K4ECGX_REG_WRITE(0x70004850, 0x01BF),
+ S5K4ECGX_REG_WRITE(0x70004852, 0xFF53),
+ S5K4ECGX_REG_WRITE(0x70004854, 0x0022),
+ S5K4ECGX_REG_WRITE(0x70004856, 0xFFEA),
+ S5K4ECGX_REG_WRITE(0x70004858, 0x01C2),
+ S5K4ECGX_REG_WRITE(0x7000485A, 0x00C6),
+ S5K4ECGX_REG_WRITE(0x7000485C, 0x0095),
+ S5K4ECGX_REG_WRITE(0x7000485E, 0xFEFD),
+ S5K4ECGX_REG_WRITE(0x70004860, 0x0206),
+ S5K4ECGX_REG_WRITE(0x70004862, 0xFF7F),
+ S5K4ECGX_REG_WRITE(0x70004864, 0x0191),
+ S5K4ECGX_REG_WRITE(0x70004866, 0xFF06),
+ S5K4ECGX_REG_WRITE(0x70004868, 0x01BA),
+ S5K4ECGX_REG_WRITE(0x7000486A, 0x0108),
+
+ S5K4ECGX_REG_WRITE(0x7000486C, 0x0204), /* CW */
+ S5K4ECGX_REG_WRITE(0x7000486E, 0xFFB2),
+ S5K4ECGX_REG_WRITE(0x70004870, 0xFFF5),
+ S5K4ECGX_REG_WRITE(0x70004872, 0xFEF1),
+ S5K4ECGX_REG_WRITE(0x70004874, 0x014E),
+ S5K4ECGX_REG_WRITE(0x70004876, 0xFF18),
+ S5K4ECGX_REG_WRITE(0x70004878, 0xFFE6),
+ S5K4ECGX_REG_WRITE(0x7000487A, 0xFFDD),
+ S5K4ECGX_REG_WRITE(0x7000487C, 0x01B2),
+ S5K4ECGX_REG_WRITE(0x7000487E, 0x00F2),
+ S5K4ECGX_REG_WRITE(0x70004880, 0x00CA),
+ S5K4ECGX_REG_WRITE(0x70004882, 0xFF48),
+ S5K4ECGX_REG_WRITE(0x70004884, 0x0151),
+ S5K4ECGX_REG_WRITE(0x70004886, 0xFF50),
+ S5K4ECGX_REG_WRITE(0x70004888, 0x0147),
+ S5K4ECGX_REG_WRITE(0x7000488A, 0xFF75),
+ S5K4ECGX_REG_WRITE(0x7000488C, 0x0187),
+ S5K4ECGX_REG_WRITE(0x7000488E, 0x01BF),
+
+ S5K4ECGX_REG_WRITE(0x70004890, 0x0204), /* D50 */
+ S5K4ECGX_REG_WRITE(0x70004892, 0xFFB2),
+ S5K4ECGX_REG_WRITE(0x70004894, 0xFFF5),
+ S5K4ECGX_REG_WRITE(0x70004896, 0xFEF1),
+ S5K4ECGX_REG_WRITE(0x70004898, 0x014E),
+ S5K4ECGX_REG_WRITE(0x7000489A, 0xFF18),
+ S5K4ECGX_REG_WRITE(0x7000489C, 0xFFE6),
+ S5K4ECGX_REG_WRITE(0x7000489E, 0xFFDD),
+ S5K4ECGX_REG_WRITE(0x700048A0, 0x01B2),
+ S5K4ECGX_REG_WRITE(0x700048A2, 0x00F2),
+ S5K4ECGX_REG_WRITE(0x700048A4, 0x00CA),
+ S5K4ECGX_REG_WRITE(0x700048A6, 0xFF48),
+ S5K4ECGX_REG_WRITE(0x700048A8, 0x0151),
+ S5K4ECGX_REG_WRITE(0x700048AA, 0xFF50),
+ S5K4ECGX_REG_WRITE(0x700048AC, 0x0147),
+ S5K4ECGX_REG_WRITE(0x700048AE, 0xFF75),
+ S5K4ECGX_REG_WRITE(0x700048B0, 0x0187),
+ S5K4ECGX_REG_WRITE(0x700048B2, 0x01BF),
+
+ S5K4ECGX_REG_WRITE(0x700048B4, 0x0204), /* D65 */
+ S5K4ECGX_REG_WRITE(0x700048B6, 0xFFB2),
+ S5K4ECGX_REG_WRITE(0x700048B8, 0xFFF5),
+ S5K4ECGX_REG_WRITE(0x700048BA, 0xFEF1),
+ S5K4ECGX_REG_WRITE(0x700048BC, 0x014E),
+ S5K4ECGX_REG_WRITE(0x700048BE, 0xFF18),
+ S5K4ECGX_REG_WRITE(0x700048C0, 0xFFE6),
+ S5K4ECGX_REG_WRITE(0x700048C2, 0xFFDD),
+ S5K4ECGX_REG_WRITE(0x700048C4, 0x01B2),
+ S5K4ECGX_REG_WRITE(0x700048C6, 0x00F2),
+ S5K4ECGX_REG_WRITE(0x700048C8, 0x00CA),
+ S5K4ECGX_REG_WRITE(0x700048CA, 0xFF48),
+ S5K4ECGX_REG_WRITE(0x700048CC, 0x0151),
+ S5K4ECGX_REG_WRITE(0x700048CE, 0xFF50),
+ S5K4ECGX_REG_WRITE(0x700048D0, 0x0147),
+ S5K4ECGX_REG_WRITE(0x700048D2, 0xFF75),
+ S5K4ECGX_REG_WRITE(0x700048D4, 0x0187),
+ S5K4ECGX_REG_WRITE(0x700048D6, 0x01BF),
+
+ S5K4ECGX_REG_WRITE(0x700048D8, 0x01E5), /* Y hue-5. TVAR_wbt_pOutdoorCcm[0] */
+ S5K4ECGX_REG_WRITE(0x700048DA, 0xFFA4),
+ S5K4ECGX_REG_WRITE(0x700048DC, 0xFFDC),
+ S5K4ECGX_REG_WRITE(0x700048DE, 0xFE90),
+ S5K4ECGX_REG_WRITE(0x700048E0, 0x013F),
+ S5K4ECGX_REG_WRITE(0x700048E2, 0xFF1B),
+ S5K4ECGX_REG_WRITE(0x700048E4, 0xFFD2),
+ S5K4ECGX_REG_WRITE(0x700048E6, 0xFFDF),
+ S5K4ECGX_REG_WRITE(0x700048E8, 0x0236),
+ S5K4ECGX_REG_WRITE(0x700048EA, 0x00EC),
+ S5K4ECGX_REG_WRITE(0x700048EC, 0x00F8),
+ S5K4ECGX_REG_WRITE(0x700048EE, 0xFF34),
+ S5K4ECGX_REG_WRITE(0x700048F0, 0x01CE),
+ S5K4ECGX_REG_WRITE(0x700048F2, 0xFF83),
+ S5K4ECGX_REG_WRITE(0x700048F4, 0x0195),
+ S5K4ECGX_REG_WRITE(0x700048F6, 0xFEF3),
+ S5K4ECGX_REG_WRITE(0x700048F8, 0x0126),
+ S5K4ECGX_REG_WRITE(0x700048FA, 0x0162),
+
+ /* AFIT */
+ S5K4ECGX_REG_WRITE(0x70000944, 0x0050), /* afit_uNoiseIndInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x70000946, 0x00B0), /* afit_uNoiseIndInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x70000948, 0x0196), /* afit_uNoiseIndInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x7000094A, 0x0245), /* afit_uNoiseIndInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x7000094C, 0x0300), /* afit_uNoiseIndInDoor_4_ */
+
+ S5K4ECGX_REG_WRITE(0x7000097A, 0x0000), /* afit_bUseSenBpr */
+ S5K4ECGX_REG_WRITE(0x7000097C, 0x01CC), /* afit_usBprThr_0_ */
+ S5K4ECGX_REG_WRITE(0x7000097E, 0x01CC), /* afit_usBprThr_1_ */
+ S5K4ECGX_REG_WRITE(0x70000980, 0x01CC), /* afit_usBprThr_2_ */
+ S5K4ECGX_REG_WRITE(0x70000982, 0x01CC), /* afit_usBprThr_3_ */
+ S5K4ECGX_REG_WRITE(0x70000984, 0x01CC), /* afit_usBprThr_4_ */
+ S5K4ECGX_REG_WRITE(0x70000986, 0x0180), /* afit_NIContrastAFITValue */
+ S5K4ECGX_REG_WRITE(0x70000988, 0x0196), /* afit_NIContrastTh */
+
+ S5K4ECGX_REG_WRITE(0x70000976, 0x0070),
+ S5K4ECGX_REG_WRITE(0x70000978, 0x0005),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000093A, 0x0014), /* SARR_uNormBrInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x7000093C, 0x00D2), /* SARR_uNormBrInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x7000093E, 0x0384), /* SARR_uNormBrInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x70000940, 0x07D0), /* SARR_uNormBrInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x70000942, 0x1388), /* SARR_uNormBrInDoor_4_ */
+
+
+ /* AFIT 0 */
+ S5K4ECGX_REG_WRITE(0x7000098C, 0x0000), /* 7000098C AFIT16_BRIGHTNESS */
+ S5K4ECGX_REG_WRITE(0x7000098E, 0x0000), /* 7000098E AFIT16_CONTRAST */
+ S5K4ECGX_REG_WRITE(0x70000990, 0x0000), /* 70000990 AFIT16_SATURATION */
+ S5K4ECGX_REG_WRITE(0x70000992, 0x0000), /* 70000992 AFIT16_SHARP_BLUR */
+ S5K4ECGX_REG_WRITE(0x70000994, 0x0000), /* 70000994 AFIT16_GLAMOUR */
+ S5K4ECGX_REG_WRITE(0x70000996, 0x00C0), /* 70000996 AFIT16_bnr_edge_high */
+ S5K4ECGX_REG_WRITE(0x70000998, 0x0064), /* 70000998 AFIT16_postdmsc_iLowBright */
+ S5K4ECGX_REG_WRITE(0x7000099A, 0x0384), /* 7000099A AFIT16_postdmsc_iHighBright */
+ S5K4ECGX_REG_WRITE(0x7000099C, 0x005F), /* 7000099C AFIT16_postdmsc_iLowSat */
+ S5K4ECGX_REG_WRITE(0x7000099E, 0x01F4), /* 7000099E AFIT16_postdmsc_iHighSat */
+ S5K4ECGX_REG_WRITE(0x700009A0, 0x0070), /* 700009A0 AFIT16_postdmsc_iTune */
+ S5K4ECGX_REG_WRITE(0x700009A2, 0x0040), /* 700009A2 AFIT16_yuvemix_mNegRanges_0 */
+ S5K4ECGX_REG_WRITE(0x700009A4, 0x00A0), /* 700009A4 AFIT16_yuvemix_mNegRanges_1 */
+ S5K4ECGX_REG_WRITE(0x700009A6, 0x0100), /* 700009A6 AFIT16_yuvemix_mNegRanges_2 */
+ S5K4ECGX_REG_WRITE(0x700009A8, 0x0010), /* 700009A8 AFIT16_yuvemix_mPosRanges_0 */
+ S5K4ECGX_REG_WRITE(0x700009AA, 0x0040), /* 700009AA AFIT16_yuvemix_mPosRanges_1 */
+ S5K4ECGX_REG_WRITE(0x700009AC, 0x00A0), /* 700009AC AFIT16_yuvemix_mPosRanges_2 */
+ S5K4ECGX_REG_WRITE(0x700009AE, 0x1430), /* 700009AE AFIT8_bnr_edge_low [7:0] AFIT8_bnr_repl_thresh */
+ S5K4ECGX_REG_WRITE(0x700009B0, 0x0201), /* 700009B0 AFIT8_bnr_repl_force [7:0] AFIT8_bnr_iHotThreshHigh */
+ S5K4ECGX_REG_WRITE(0x700009B2, 0x0204), /* 700009B2 AFIT8_bnr_iHotThreshLow [7:0] AFIT8_bnr_iColdThreshHigh */
+ S5K4ECGX_REG_WRITE(0x700009B4, 0x3604), /* 700009B4 AFIT8_bnr_iColdThreshLow [7:0] AFIT8_bnr_DispTH_Low */
+ S5K4ECGX_REG_WRITE(0x700009B6, 0x032A), /* 700009B6 AFIT8_bnr_DispTH_High [7:0] AFIT8_bnr_DISP_Limit_Low */
+ S5K4ECGX_REG_WRITE(0x700009B8, 0x0403), /* 700009B8 AFIT8_bnr_DISP_Limit_High [7:0] AFIT8_bnr_iDistSigmaMin */
+ S5K4ECGX_REG_WRITE(0x700009BA, 0x1B06), /* 700009BA AFIT8_bnr_iDistSigmaMax [7:0] AFIT8_bnr_iDiffSigmaLow */
+ S5K4ECGX_REG_WRITE(0x700009BC, 0x6015), /* 700009BC AFIT8_bnr_iDiffSigmaHigh [7:0] AFIT8_bnr_iNormalizedSTD_TH */
+ S5K4ECGX_REG_WRITE(0x700009BE, 0x00C0), /* 700009BE AFIT8_bnr_iNormalizedSTD_Limit [7:0] AFIT8_bnr_iDirNRTune */
+ S5K4ECGX_REG_WRITE(0x700009C0, 0x6080), /* 700009C0 AFIT8_bnr_iDirMinThres [7:0] AFIT8_bnr_iDirFltDiffThresHigh */
+ S5K4ECGX_REG_WRITE(0x700009C2, 0x4080), /* 700009C2 AFIT8_bnr_iDirFltDiffThresLow [7:0] AFIT8_bnr_iDirSmoothPowerHigh */
+ S5K4ECGX_REG_WRITE(0x700009C4, 0x0640), /* 700009C4 AFIT8_bnr_iDirSmoothPowerLow [7:0] AFIT8_bnr_iLowMaxSlopeAllowed */
+ S5K4ECGX_REG_WRITE(0x700009C6, 0x0306), /* 700009C6 AFIT8_bnr_iHighMaxSlopeAllowed [7:0] AFIT8_bnr_iLowSlopeThresh */
+ S5K4ECGX_REG_WRITE(0x700009C8, 0x2003), /* 700009C8 AFIT8_bnr_iHighSlopeThresh [7:0] AFIT8_bnr_iSlopenessTH */
+ S5K4ECGX_REG_WRITE(0x700009CA, 0xFF01), /* 700009CA AFIT8_bnr_iSlopeBlurStrength [7:0] AFIT8_bnr_iSlopenessLimit */
+ S5K4ECGX_REG_WRITE(0x700009CC, 0x0000), /* 700009CC AFIT8_bnr_AddNoisePower1 [7:0] AFIT8_bnr_AddNoisePower2 */
+ S5K4ECGX_REG_WRITE(0x700009CE, 0x0400), /* 700009CE AFIT8_bnr_iRadialTune [7:0] AFIT8_bnr_iRadialPower */
+ S5K4ECGX_REG_WRITE(0x700009D0, 0x365A), /* 700009D0 AFIT8_bnr_iRadialLimit [7:0] AFIT8_ee_iFSMagThLow */
+ S5K4ECGX_REG_WRITE(0x700009D2, 0x102A), /* 700009D2 AFIT8_ee_iFSMagThHigh [7:0] AFIT8_ee_iFSVarThLow */
+ S5K4ECGX_REG_WRITE(0x700009D4, 0x000B), /* 700009D4 AFIT8_ee_iFSVarThHigh [7:0] AFIT8_ee_iFSThLow */
+ S5K4ECGX_REG_WRITE(0x700009D6, 0x0600), /* 700009D6 AFIT8_ee_iFSThHigh [7:0] AFIT8_ee_iFSmagPower */
+ S5K4ECGX_REG_WRITE(0x700009D8, 0x5A0F), /* 700009D8 AFIT8_ee_iFSVarCountTh [7:0] AFIT8_ee_iRadialLimit */
+ S5K4ECGX_REG_WRITE(0x700009DA, 0x0505), /* 700009DA AFIT8_ee_iRadialPower [7:0] AFIT8_ee_iSmoothEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x700009DC, 0x1802), /* 700009DC AFIT8_ee_iROADThres [7:0] AFIT8_ee_iROADMaxNR */
+ S5K4ECGX_REG_WRITE(0x700009DE, 0x0000), /* 700009DE AFIT8_ee_iROADSubMaxNR [7:0] AFIT8_ee_iROADSubThres */
+ S5K4ECGX_REG_WRITE(0x700009E0, 0x2006), /* 700009E0 AFIT8_ee_iROADNeiThres [7:0] AFIT8_ee_iROADNeiMaxNR */
+ S5K4ECGX_REG_WRITE(0x700009E2, 0x3028), /* 700009E2 AFIT8_ee_iSmoothEdgeThres [7:0] AFIT8_ee_iMSharpen */
+ S5K4ECGX_REG_WRITE(0x700009E4, 0x0418), /* 700009E4 AFIT8_ee_iWSharpen [7:0] AFIT8_ee_iMShThresh */
+ S5K4ECGX_REG_WRITE(0x700009E6, 0x0101), /* 700009E6 AFIT8_ee_iWShThresh [7:0] AFIT8_ee_iReduceNegative */
+ S5K4ECGX_REG_WRITE(0x700009E8, 0x0800), /* 700009E8 AFIT8_ee_iEmbossCentAdd [7:0] AFIT8_ee_iShDespeckle */
+ S5K4ECGX_REG_WRITE(0x700009EA, 0x1804), /* 700009EA AFIT8_ee_iReduceEdgeThresh [7:0] AFIT8_dmsc_iEnhThresh */
+ S5K4ECGX_REG_WRITE(0x700009EC, 0x4008), /* 700009EC AFIT8_dmsc_iDesatThresh [7:0] AFIT8_dmsc_iDemBlurHigh */
+ S5K4ECGX_REG_WRITE(0x700009EE, 0x0540), /* 700009EE AFIT8_dmsc_iDemBlurLow [7:0] AFIT8_dmsc_iDemBlurRange */
+ S5K4ECGX_REG_WRITE(0x700009F0, 0x8006), /* 700009F0 AFIT8_dmsc_iDecisionThresh [7:0] AFIT8_dmsc_iCentGrad */
+ S5K4ECGX_REG_WRITE(0x700009F2, 0x0020), /* 700009F2 AFIT8_dmsc_iMonochrom [7:0] AFIT8_dmsc_iGBDenoiseVal */
+ S5K4ECGX_REG_WRITE(0x700009F4, 0x0000), /* 700009F4 AFIT8_dmsc_iGRDenoiseVal [7:0] AFIT8_dmsc_iEdgeDesatThrHigh */
+ S5K4ECGX_REG_WRITE(0x700009F6, 0x1800), /* 700009F6 AFIT8_dmsc_iEdgeDesatThrLow [7:0] AFIT8_dmsc_iEdgeDesat */
+ S5K4ECGX_REG_WRITE(0x700009F8, 0x0000), /* 700009F8 AFIT8_dmsc_iNearGrayDesat [7:0] AFIT8_dmsc_iEdgeDesatLimit */
+ S5K4ECGX_REG_WRITE(0x700009FA, 0x1E10), /* 700009FA AFIT8_postdmsc_iBCoeff [7:0] AFIT8_postdmsc_iGCoeff */
+ S5K4ECGX_REG_WRITE(0x700009FC, 0x000B), /* 700009FC AFIT8_postdmsc_iWideMult [7:0] AFIT8_yuvemix_mNegSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x700009FE, 0x0607), /* 700009FE AFIT8_yuvemix_mNegSlopes_1 [7:0] AFIT8_yuvemix_mNegSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000A00, 0x0005), /* 70000A00 AFIT8_yuvemix_mNegSlopes_3 [7:0] AFIT8_yuvemix_mPosSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000A02, 0x0607), /* 70000A02 AFIT8_yuvemix_mPosSlopes_1 [7:0] AFIT8_yuvemix_mPosSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000A04, 0x0405), /* 70000A04 AFIT8_yuvemix_mPosSlopes_3 [7:0] AFIT8_yuviirnr_iXSupportY */
+ S5K4ECGX_REG_WRITE(0x70000A06, 0x0205), /* 70000A06 AFIT8_yuviirnr_iXSupportUV [7:0] AFIT8_yuviirnr_iLowYNorm */
+ S5K4ECGX_REG_WRITE(0x70000A08, 0x0304), /* 70000A08 AFIT8_yuviirnr_iHighYNorm [7:0] AFIT8_yuviirnr_iLowUVNorm */
+ S5K4ECGX_REG_WRITE(0x70000A0A, 0x0409), /* 70000A0A AFIT8_yuviirnr_iHighUVNorm [7:0] AFIT8_yuviirnr_iYNormShift */
+ S5K4ECGX_REG_WRITE(0x70000A0C, 0x0306), /* 70000A0C AFIT8_yuviirnr_iUVNormShift [7:0] AFIT8_yuviirnr_iVertLength_Y */
+ S5K4ECGX_REG_WRITE(0x70000A0E, 0x0407), /* 70000A0E AFIT8_yuviirnr_iVertLength_UV [7:0] AFIT8_yuviirnr_iDiffThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000A10, 0x1C04), /* 70000A10 AFIT8_yuviirnr_iDiffThreshH_Y [7:0] AFIT8_yuviirnr_iDiffThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000A12, 0x0214), /* 70000A12 AFIT8_yuviirnr_iDiffThreshH_UV [7:0] AFIT8_yuviirnr_iMaxThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000A14, 0x1002), /* 70000A14 AFIT8_yuviirnr_iMaxThreshH_Y [7:0] AFIT8_yuviirnr_iMaxThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000A16, 0x0610), /* 70000A16 AFIT8_yuviirnr_iMaxThreshH_UV [7:0] AFIT8_yuviirnr_iYNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000A18, 0x1A02), /* 70000A18 AFIT8_yuviirnr_iYNRStrengthH [7:0] AFIT8_yuviirnr_iUVNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x4A18), /* 70000A1A AFIT8_yuviirnr_iUVNRStrengthH [7:0] AFIT8_byr_gras_iShadingPower */
+ S5K4ECGX_REG_WRITE(0x70000A1C, 0x0080), /* 70000A1C AFIT8_RGBGamma2_iLinearity [7:0] AFIT8_RGBGamma2_iDarkReduce */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0348), /* 70000A1E AFIT8_ccm_oscar_iSaturation [7:0] AFIT8_RGB2YUV_iYOffset */
+ S5K4ECGX_REG_WRITE(0x70000A20, 0x0180), /* 70000A20 AFIT8_RGB2YUV_iRGBGain [7:0] AFIT8_bnr_nClustLevel_H */
+ S5K4ECGX_REG_WRITE(0x70000A22, 0x0A0A), /* 70000A22 AFIT8_bnr_iClustMulT_H [7:0] AFIT8_bnr_iClustMulT_C */
+ S5K4ECGX_REG_WRITE(0x70000A24, 0x0101), /* 70000A24 AFIT8_bnr_iClustThresh_H [7:0] AFIT8_bnr_iClustThresh_C */
+ S5K4ECGX_REG_WRITE(0x70000A26, 0x2A36), /* 70000A26 AFIT8_bnr_iDenThreshLow [7:0] AFIT8_bnr_iDenThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x6024), /* 70000A28 AFIT8_ee_iLowSharpPower [7:0] AFIT8_ee_iHighSharpPower */
+ S5K4ECGX_REG_WRITE(0x70000A2A, 0x2A36), /* 70000A2A AFIT8_ee_iLowShDenoise [7:0] AFIT8_ee_iHighShDenoise */
+ S5K4ECGX_REG_WRITE(0x70000A2C, 0xFFFF), /* 70000A2C AFIT8_ee_iLowSharpClamp [7:0] AFIT8_ee_iHighSharpClamp */
+ S5K4ECGX_REG_WRITE(0x70000A2E, 0x0808), /* 70000A2E AFIT8_ee_iReduceEdgeMinMult [7:0] AFIT8_ee_iReduceEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000A30, 0x0A01), /* 70000A30 AFIT8_bnr_nClustLevel_H_Bin [7:0] AFIT8_bnr_iClustMulT_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A32, 0x010A), /* 70000A32 AFIT8_bnr_iClustMulT_C_Bin [7:0] AFIT8_bnr_iClustThresh_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A34, 0x3601), /* 70000A34 AFIT8_bnr_iClustThresh_C_Bin [7:0] AFIT8_bnr_iDenThreshLow_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A36, 0x242A), /* 70000A36 AFIT8_bnr_iDenThreshHigh_Bin [7:0] AFIT8_ee_iLowSharpPower_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A38, 0x3660), /* 70000A38 AFIT8_ee_iHighSharpPower_Bin [7:0] AFIT8_ee_iLowShDenoise_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A3A, 0xFF2A), /* 70000A3A AFIT8_ee_iHighShDenoise_Bin [7:0] AFIT8_ee_iLowSharpClamp_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A3C, 0x08FF), /* 70000A3C AFIT8_ee_iHighSharpClamp_Bin [7:0] AFIT8_ee_iReduceEdgeMinMult_Bin */
+ S5K4ECGX_REG_WRITE(0x70000A3E, 0x0008), /* 70000A3E AFIT8_ee_iReduceEdgeSlope_Bin [7:0] */
+ S5K4ECGX_REG_WRITE(0x70000A40, 0x0001), /* 70000A40 AFITB_bnr_nClustLevel_C [0] */
+
+ /* AFIT 1 */
+ S5K4ECGX_REG_WRITE(0x70000A42, 0x0000), /* 70000A42 AFIT16_BRIGHTNESS */
+ S5K4ECGX_REG_WRITE(0x70000A44, 0x0000), /* 70000A44 AFIT16_CONTRAST */
+ S5K4ECGX_REG_WRITE(0x70000A46, 0x0010), /* 0426 000A // 0420 0000 //70000A46 AFIT16_SATURATION */
+ S5K4ECGX_REG_WRITE(0x70000A48, 0x0000), /* 70000A48 AFIT16_SHARP_BLUR */
+ S5K4ECGX_REG_WRITE(0x70000A4A, 0x0000), /* 70000A4A AFIT16_GLAMOUR */
+ S5K4ECGX_REG_WRITE(0x70000A4C, 0x00C0), /* 70000A4C AFIT16_bnr_edge_high */
+ S5K4ECGX_REG_WRITE(0x70000A4E, 0x0064), /* 70000A4E AFIT16_postdmsc_iLowBright */
+ S5K4ECGX_REG_WRITE(0x70000A50, 0x0384), /* 70000A50 AFIT16_postdmsc_iHighBright */
+ S5K4ECGX_REG_WRITE(0x70000A52, 0x0051), /* 70000A52 AFIT16_postdmsc_iLowSat */
+ S5K4ECGX_REG_WRITE(0x70000A54, 0x01F4), /* 70000A54 AFIT16_postdmsc_iHighSat */
+ S5K4ECGX_REG_WRITE(0x70000A56, 0x0070), /* 70000A56 AFIT16_postdmsc_iTune */
+ S5K4ECGX_REG_WRITE(0x70000A58, 0x0040), /* 70000A58 AFIT16_yuvemix_mNegRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000A5A, 0x00A0), /* 70000A5A AFIT16_yuvemix_mNegRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000A5C, 0x0100), /* 70000A5C AFIT16_yuvemix_mNegRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000A5E, 0x0010), /* 70000A5E AFIT16_yuvemix_mPosRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000A60, 0x0060), /* 70000A60 AFIT16_yuvemix_mPosRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000A62, 0x0100), /* 70000A62 AFIT16_yuvemix_mPosRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000A64, 0x1430), /* 70000A64 AFIT8_bnr_edge_low [7:0] AFIT8_bnr_repl_thresh */
+ S5K4ECGX_REG_WRITE(0x70000A66, 0x0201), /* 70000A66 AFIT8_bnr_repl_force [7:0] AFIT8_bnr_iHotThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000A68, 0x0204), /* 70000A68 AFIT8_bnr_iHotThreshLow [7:0] AFIT8_bnr_iColdThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000A6A, 0x2404), /* 70000A6A AFIT8_bnr_iColdThreshLow [7:0] AFIT8_bnr_DispTH_Low */
+ S5K4ECGX_REG_WRITE(0x70000A6C, 0x031B), /* 70000A6C AFIT8_bnr_DispTH_High [7:0] AFIT8_bnr_DISP_Limit_Low */
+ S5K4ECGX_REG_WRITE(0x70000A6E, 0x0103), /* 70000A6E AFIT8_bnr_DISP_Limit_High [7:0] AFIT8_bnr_iDistSigmaMin */
+ S5K4ECGX_REG_WRITE(0x70000A70, 0x1205), /* 70000A70 AFIT8_bnr_iDistSigmaMax [7:0] AFIT8_bnr_iDiffSigmaLow */
+ S5K4ECGX_REG_WRITE(0x70000A72, 0x400D), /* 70000A72 AFIT8_bnr_iDiffSigmaHigh [7:0] AFIT8_bnr_iNormalizedSTD_TH */
+ S5K4ECGX_REG_WRITE(0x70000A74, 0x0080), /* 70000A74 AFIT8_bnr_iNormalizedSTD_Limit [7:0] AFIT8_bnr_iDirNRTune */
+ S5K4ECGX_REG_WRITE(0x70000A76, 0x2080), /* 70000A76 AFIT8_bnr_iDirMinThres [7:0] AFIT8_bnr_iDirFltDiffThresHigh */
+ S5K4ECGX_REG_WRITE(0x70000A78, 0x3040), /* 70000A78 AFIT8_bnr_iDirFltDiffThresLow [7:0] AFIT8_bnr_iDirSmoothPowerHigh */
+ S5K4ECGX_REG_WRITE(0x70000A7A, 0x0630), /* 70000A7A AFIT8_bnr_iDirSmoothPowerLow [7:0] AFIT8_bnr_iLowMaxSlopeAllowed */
+ S5K4ECGX_REG_WRITE(0x70000A7C, 0x0306), /* 70000A7C AFIT8_bnr_iHighMaxSlopeAllowed [7:0] AFIT8_bnr_iLowSlopeThresh */
+ S5K4ECGX_REG_WRITE(0x70000A7E, 0x2003), /* 70000A7E AFIT8_bnr_iHighSlopeThresh [7:0] AFIT8_bnr_iSlopenessTH */
+ S5K4ECGX_REG_WRITE(0x70000A80, 0xFF01), /* 70000A80 AFIT8_bnr_iSlopeBlurStrength [7:0] AFIT8_bnr_iSlopenessLimit */
+ S5K4ECGX_REG_WRITE(0x70000A82, 0x0404), /* 70000A82 AFIT8_bnr_AddNoisePower1 [7:0] AFIT8_bnr_AddNoisePower2 */
+ S5K4ECGX_REG_WRITE(0x70000A84, 0x0300), /* 70000A84 AFIT8_bnr_iRadialTune [7:0] AFIT8_bnr_iRadialPower */
+ S5K4ECGX_REG_WRITE(0x70000A86, 0x245A), /* 70000A86 AFIT8_bnr_iRadialLimit [7:0] AFIT8_ee_iFSMagThLow */
+ S5K4ECGX_REG_WRITE(0x70000A88, 0x1018), /* 70000A88 AFIT8_ee_iFSMagThHigh [7:0] AFIT8_ee_iFSVarThLow */
+ S5K4ECGX_REG_WRITE(0x70000A8A, 0x000B), /* 70000A8A AFIT8_ee_iFSVarThHigh [7:0] AFIT8_ee_iFSThLow */
+ S5K4ECGX_REG_WRITE(0x70000A8C, 0x0B00), /* 70000A8C AFIT8_ee_iFSThHigh [7:0] AFIT8_ee_iFSmagPower */
+ S5K4ECGX_REG_WRITE(0x70000A8E, 0x5A0F), /* 70000A8E AFIT8_ee_iFSVarCountTh [7:0] AFIT8_ee_iRadialLimit */
+ S5K4ECGX_REG_WRITE(0x70000A90, 0x0505), /* 70000A90 AFIT8_ee_iRadialPower [7:0] AFIT8_ee_iSmoothEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000A92, 0x1802), /* 70000A92 AFIT8_ee_iROADThres [7:0] AFIT8_ee_iROADMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000A94, 0x0000), /* 70000A94 AFIT8_ee_iROADSubMaxNR [7:0] AFIT8_ee_iROADSubThres */
+ S5K4ECGX_REG_WRITE(0x70000A96, 0x2006), /* 70000A96 AFIT8_ee_iROADNeiThres [7:0] AFIT8_ee_iROADNeiMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000A98, 0x3428), /* 70000A98 AFIT8_ee_iSmoothEdgeThres [7:0] AFIT8_ee_iMSharpen */
+ S5K4ECGX_REG_WRITE(0x70000A9A, 0x041C), /* 70000A9A AFIT8_ee_iWSharpen [7:0] AFIT8_ee_iMShThresh */
+ S5K4ECGX_REG_WRITE(0x70000A9C, 0x0101), /* 70000A9C AFIT8_ee_iWShThresh [7:0] AFIT8_ee_iReduceNegative */
+ S5K4ECGX_REG_WRITE(0x70000A9E, 0x0800), /* 70000A9E AFIT8_ee_iEmbossCentAdd [7:0] AFIT8_ee_iShDespeckle */
+ S5K4ECGX_REG_WRITE(0x70000AA0, 0x1004), /* 70000AA0 AFIT8_ee_iReduceEdgeThresh [7:0] AFIT8_dmsc_iEnhThresh */
+ S5K4ECGX_REG_WRITE(0x70000AA2, 0x4008), /* 70000AA2 AFIT8_dmsc_iDesatThresh [7:0] AFIT8_dmsc_iDemBlurHigh */
+ S5K4ECGX_REG_WRITE(0x70000AA4, 0x0540), /* 70000AA4 AFIT8_dmsc_iDemBlurLow [7:0] AFIT8_dmsc_iDemBlurRange */
+ S5K4ECGX_REG_WRITE(0x70000AA6, 0x8006), /* 70000AA6 AFIT8_dmsc_iDecisionThresh [7:0] AFIT8_dmsc_iCentGrad */
+ S5K4ECGX_REG_WRITE(0x70000AA8, 0x0020), /* 70000AA8 AFIT8_dmsc_iMonochrom [7:0] AFIT8_dmsc_iGBDenoiseVal */
+ S5K4ECGX_REG_WRITE(0x70000AAA, 0x0000), /* 70000AAA AFIT8_dmsc_iGRDenoiseVal [7:0] AFIT8_dmsc_iEdgeDesatThrHigh */
+ S5K4ECGX_REG_WRITE(0x70000AAC, 0x1800), /* 70000AAC AFIT8_dmsc_iEdgeDesatThrLow [7:0] AFIT8_dmsc_iEdgeDesat */
+ S5K4ECGX_REG_WRITE(0x70000AAE, 0x0000), /* 70000AAE AFIT8_dmsc_iNearGrayDesat [7:0] AFIT8_dmsc_iEdgeDesatLimit */
+ S5K4ECGX_REG_WRITE(0x70000AB0, 0x1E10), /* 70000AB0 AFIT8_postdmsc_iBCoeff [7:0] AFIT8_postdmsc_iGCoeff */
+ S5K4ECGX_REG_WRITE(0x70000AB2, 0x000B), /* 70000AB2 AFIT8_postdmsc_iWideMult [7:0] AFIT8_yuvemix_mNegSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000AB4, 0x0607), /* 70000AB4 AFIT8_yuvemix_mNegSlopes_1 [7:0] AFIT8_yuvemix_mNegSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000AB6, 0x0005), /* 70000AB6 AFIT8_yuvemix_mNegSlopes_3 [7:0] AFIT8_yuvemix_mPosSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000AB8, 0x0607), /* 70000AB8 AFIT8_yuvemix_mPosSlopes_1 [7:0] AFIT8_yuvemix_mPosSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000ABA, 0x0405), /* 70000ABA AFIT8_yuvemix_mPosSlopes_3 [7:0] AFIT8_yuviirnr_iXSupportY */
+ S5K4ECGX_REG_WRITE(0x70000ABC, 0x0205), /* 70000ABC AFIT8_yuviirnr_iXSupportUV [7:0] AFIT8_yuviirnr_iLowYNorm */
+ S5K4ECGX_REG_WRITE(0x70000ABE, 0x0304), /* 70000ABE AFIT8_yuviirnr_iHighYNorm [7:0] AFIT8_yuviirnr_iLowUVNorm */
+ S5K4ECGX_REG_WRITE(0x70000AC0, 0x0409), /* 70000AC0 AFIT8_yuviirnr_iHighUVNorm [7:0] AFIT8_yuviirnr_iYNormShift */
+ S5K4ECGX_REG_WRITE(0x70000AC2, 0x0306), /* 70000AC2 AFIT8_yuviirnr_iUVNormShift [7:0] AFIT8_yuviirnr_iVertLength_Y */
+ S5K4ECGX_REG_WRITE(0x70000AC4, 0x0407), /* 70000AC4 AFIT8_yuviirnr_iVertLength_UV [7:0] AFIT8_yuviirnr_iDiffThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000AC6, 0x1F04), /* 70000AC6 AFIT8_yuviirnr_iDiffThreshH_Y [7:0] AFIT8_yuviirnr_iDiffThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000AC8, 0x0218), /* 70000AC8 AFIT8_yuviirnr_iDiffThreshH_UV [7:0] AFIT8_yuviirnr_iMaxThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000ACA, 0x1102), /* 70000ACA AFIT8_yuviirnr_iMaxThreshH_Y [7:0] AFIT8_yuviirnr_iMaxThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000ACC, 0x0611), /* 70000ACC AFIT8_yuviirnr_iMaxThreshH_UV [7:0] AFIT8_yuviirnr_iYNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000ACE, 0x1A02), /* 70000ACE AFIT8_yuviirnr_iYNRStrengthH [7:0] AFIT8_yuviirnr_iUVNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000AD0, 0x8018), /* 70000AD0 AFIT8_yuviirnr_iUVNRStrengthH [7:0] AFIT8_byr_gras_iShadingPower */
+ S5K4ECGX_REG_WRITE(0x70000AD2, 0x0080), /* 70000AD2 AFIT8_RGBGamma2_iLinearity [7:0] AFIT8_RGBGamma2_iDarkReduce */
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x0380), /* 70000AD4 AFIT8_ccm_oscar_iSaturation [7:0] AFIT8_RGB2YUV_iYOffset */
+ S5K4ECGX_REG_WRITE(0x70000AD6, 0x0180), /* 70000AD6 AFIT8_RGB2YUV_iRGBGain [7:0] AFIT8_bnr_nClustLevel_H */
+ S5K4ECGX_REG_WRITE(0x70000AD8, 0x0A0A), /* 70000AD8 AFIT8_bnr_iClustMulT_H [7:0] AFIT8_bnr_iClustMulT_C */
+ S5K4ECGX_REG_WRITE(0x70000ADA, 0x0101), /* 70000ADA AFIT8_bnr_iClustThresh_H [7:0] AFIT8_bnr_iClustThresh_C */
+ S5K4ECGX_REG_WRITE(0x70000ADC, 0x1B24), /* 70000ADC AFIT8_bnr_iDenThreshLow [7:0] AFIT8_bnr_iDenThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x6024), /* 70000ADE AFIT8_ee_iLowSharpPower [7:0] AFIT8_ee_iHighSharpPower */
+ S5K4ECGX_REG_WRITE(0x70000AE0, 0x1D22), /* 70000AE0 AFIT8_ee_iLowShDenoise [7:0] AFIT8_ee_iHighShDenoise */
+ S5K4ECGX_REG_WRITE(0x70000AE2, 0xFFFF), /* 70000AE2 AFIT8_ee_iLowSharpClamp [7:0] AFIT8_ee_iHighSharpClamp */
+ S5K4ECGX_REG_WRITE(0x70000AE4, 0x0808), /* 70000AE4 AFIT8_ee_iReduceEdgeMinMult [7:0] AFIT8_ee_iReduceEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000AE6, 0x0A01), /* 70000AE6 AFIT8_bnr_nClustLevel_H_Bin [7:0] AFIT8_bnr_iClustMulT_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AE8, 0x010A), /* 70000AE8 AFIT8_bnr_iClustMulT_C_Bin [7:0] AFIT8_bnr_iClustThresh_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AEA, 0x2401), /* 70000AEA AFIT8_bnr_iClustThresh_C_Bin [7:0] AFIT8_bnr_iDenThreshLow_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AEC, 0x241B), /* 70000AEC AFIT8_bnr_iDenThreshHigh_Bin [7:0] AFIT8_ee_iLowSharpPower_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AEE, 0x1E60), /* 70000AEE AFIT8_ee_iHighSharpPower_Bin [7:0] AFIT8_ee_iLowShDenoise_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AF0, 0xFF18), /* 70000AF0 AFIT8_ee_iHighShDenoise_Bin [7:0] AFIT8_ee_iLowSharpClamp_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AF2, 0x08FF), /* 70000AF2 AFIT8_ee_iHighSharpClamp_Bin [7:0] AFIT8_ee_iReduceEdgeMinMult_Bin */
+ S5K4ECGX_REG_WRITE(0x70000AF4, 0x0008), /* 70000AF4 AFIT8_ee_iReduceEdgeSlope_Bin [7:0] */
+ S5K4ECGX_REG_WRITE(0x70000AF6, 0x0001), /* 70000AF6 AFITB_bnr_nClustLevel_C [0] */
+
+ /* AFIT 2 */
+ S5K4ECGX_REG_WRITE(0x70000AF8, 0x0000), /* 70000AF8 AFIT16_BRIGHTNESS */
+ S5K4ECGX_REG_WRITE(0x70000AFA, 0x0000), /* 70000AFA AFIT16_CONTRAST */
+ S5K4ECGX_REG_WRITE(0x70000AFC, 0x0010), /* 0426 000A // 04200000 //70000AFC AFIT16_SATURATION */
+ S5K4ECGX_REG_WRITE(0x70000AFE, 0x0000), /* 70000AFE AFIT16_SHARP_BLUR */
+ S5K4ECGX_REG_WRITE(0x70000B00, 0x0000), /* 70000B00 AFIT16_GLAMOUR */
+ S5K4ECGX_REG_WRITE(0x70000B02, 0x00C0), /* 70000B02 AFIT16_bnr_edge_high */
+ S5K4ECGX_REG_WRITE(0x70000B04, 0x0064), /* 70000B04 AFIT16_postdmsc_iLowBright */
+ S5K4ECGX_REG_WRITE(0x70000B06, 0x0384), /* 70000B06 AFIT16_postdmsc_iHighBright */
+ S5K4ECGX_REG_WRITE(0x70000B08, 0x0043), /* 70000B08 AFIT16_postdmsc_iLowSat */
+ S5K4ECGX_REG_WRITE(0x70000B0A, 0x01F4), /* 70000B0A AFIT16_postdmsc_iHighSat */
+ S5K4ECGX_REG_WRITE(0x70000B0C, 0x0070), /* 70000B0C AFIT16_postdmsc_iTune */
+ S5K4ECGX_REG_WRITE(0x70000B0E, 0x0040), /* 70000B0E AFIT16_yuvemix_mNegRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000B10, 0x00A0), /* 70000B10 AFIT16_yuvemix_mNegRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000B12, 0x0100), /* 70000B12 AFIT16_yuvemix_mNegRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000B14, 0x0010), /* 70000B14 AFIT16_yuvemix_mPosRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000B16, 0x0060), /* 70000B16 AFIT16_yuvemix_mPosRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000B18, 0x0100), /* 70000B18 AFIT16_yuvemix_mPosRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000B1A, 0x1430), /* 70000B1A AFIT8_bnr_edge_low [7:0] AFIT8_bnr_repl_thresh */
+ S5K4ECGX_REG_WRITE(0x70000B1C, 0x0201), /* 70000B1C AFIT8_bnr_repl_force [7:0] AFIT8_bnr_iHotThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000B1E, 0x0204), /* 70000B1E AFIT8_bnr_iHotThreshLow [7:0] AFIT8_bnr_iColdThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000B20, 0x1B04), /* 70000B20 AFIT8_bnr_iColdThreshLow [7:0] AFIT8_bnr_DispTH_Low */
+ S5K4ECGX_REG_WRITE(0x70000B22, 0x0312), /* 70000B22 AFIT8_bnr_DispTH_High [7:0] AFIT8_bnr_DISP_Limit_Low */
+ S5K4ECGX_REG_WRITE(0x70000B24, 0x0003), /* 70000B24 AFIT8_bnr_DISP_Limit_High [7:0] AFIT8_bnr_iDistSigmaMin */
+ S5K4ECGX_REG_WRITE(0x70000B26, 0x0C03), /* 70000B26 AFIT8_bnr_iDistSigmaMax [7:0] AFIT8_bnr_iDiffSigmaLow */
+ S5K4ECGX_REG_WRITE(0x70000B28, 0x2806), /* 70000B28 AFIT8_bnr_iDiffSigmaHigh [7:0] AFIT8_bnr_iNormalizedSTD_TH */
+ S5K4ECGX_REG_WRITE(0x70000B2A, 0x0060), /* 70000B2A AFIT8_bnr_iNormalizedSTD_Limit [7:0] AFIT8_bnr_iDirNRTune */
+ S5K4ECGX_REG_WRITE(0x70000B2C, 0x1580), /* 70000B2C AFIT8_bnr_iDirMinThres [7:0] AFIT8_bnr_iDirFltDiffThresHigh */
+ S5K4ECGX_REG_WRITE(0x70000B2E, 0x2020), /* 70000B2E AFIT8_bnr_iDirFltDiffThresLow [7:0] AFIT8_bnr_iDirSmoothPowerHigh */
+ S5K4ECGX_REG_WRITE(0x70000B30, 0x0620), /* 70000B30 AFIT8_bnr_iDirSmoothPowerLow [7:0] AFIT8_bnr_iLowMaxSlopeAllowed */
+ S5K4ECGX_REG_WRITE(0x70000B32, 0x0306), /* 70000B32 AFIT8_bnr_iHighMaxSlopeAllowed [7:0] AFIT8_bnr_iLowSlopeThresh */
+ S5K4ECGX_REG_WRITE(0x70000B34, 0x2003), /* 70000B34 AFIT8_bnr_iHighSlopeThresh [7:0] AFIT8_bnr_iSlopenessTH */
+ S5K4ECGX_REG_WRITE(0x70000B36, 0xFF01), /* 70000B36 AFIT8_bnr_iSlopeBlurStrength [7:0] AFIT8_bnr_iSlopenessLimit */
+ S5K4ECGX_REG_WRITE(0x70000B38, 0x0404), /* 70000B38 AFIT8_bnr_AddNoisePower1 [7:0] AFIT8_bnr_AddNoisePower2 */
+ S5K4ECGX_REG_WRITE(0x70000B3A, 0x0300), /* 70000B3A AFIT8_bnr_iRadialTune [7:0] AFIT8_bnr_iRadialPower */
+ S5K4ECGX_REG_WRITE(0x70000B3C, 0x145A), /* 70000B3C AFIT8_bnr_iRadialLimit [7:0] AFIT8_ee_iFSMagThLow */
+ S5K4ECGX_REG_WRITE(0x70000B3E, 0x1010), /* 70000B3E AFIT8_ee_iFSMagThHigh [7:0] AFIT8_ee_iFSVarThLow */
+ S5K4ECGX_REG_WRITE(0x70000B40, 0x000B), /* 70000B40 AFIT8_ee_iFSVarThHigh [7:0] AFIT8_ee_iFSThLow */
+ S5K4ECGX_REG_WRITE(0x70000B42, 0x0E00), /* 70000B42 AFIT8_ee_iFSThHigh [7:0] AFIT8_ee_iFSmagPower */
+ S5K4ECGX_REG_WRITE(0x70000B44, 0x5A0F), /* 70000B44 AFIT8_ee_iFSVarCountTh [7:0] AFIT8_ee_iRadialLimit */
+ S5K4ECGX_REG_WRITE(0x70000B46, 0x0504), /* 70000B46 AFIT8_ee_iRadialPower [7:0] AFIT8_ee_iSmoothEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000B48, 0x1802), /* 70000B48 AFIT8_ee_iROADThres [7:0] AFIT8_ee_iROADMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000B4A, 0x0000), /* 70000B4A AFIT8_ee_iROADSubMaxNR [7:0] AFIT8_ee_iROADSubThres */
+ S5K4ECGX_REG_WRITE(0x70000B4C, 0x2006), /* 70000B4C AFIT8_ee_iROADNeiThres [7:0] AFIT8_ee_iROADNeiMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000B4E, 0x3828), /* 70000B4E AFIT8_ee_iSmoothEdgeThres [7:0] AFIT8_ee_iMSharpen */
+ S5K4ECGX_REG_WRITE(0x70000B50, 0x0428), /* 70000B50 AFIT8_ee_iWSharpen [7:0] AFIT8_ee_iMShThresh */
+ S5K4ECGX_REG_WRITE(0x70000B52, 0x0101), /* 70000B52 AFIT8_ee_iWShThresh [7:0] AFIT8_ee_iReduceNegative */
+ S5K4ECGX_REG_WRITE(0x70000B54, 0x8000), /* 70000B54 AFIT8_ee_iEmbossCentAdd [7:0] AFIT8_ee_iShDespeckle */
+ S5K4ECGX_REG_WRITE(0x70000B56, 0x0A04), /* 70000B56 AFIT8_ee_iReduceEdgeThresh [7:0] AFIT8_dmsc_iEnhThresh */
+ S5K4ECGX_REG_WRITE(0x70000B58, 0x4008), /* 70000B58 AFIT8_dmsc_iDesatThresh [7:0] AFIT8_dmsc_iDemBlurHigh */
+ S5K4ECGX_REG_WRITE(0x70000B5A, 0x0540), /* 70000B5A AFIT8_dmsc_iDemBlurLow [7:0] AFIT8_dmsc_iDemBlurRange */
+ S5K4ECGX_REG_WRITE(0x70000B5C, 0x8006), /* 70000B5C AFIT8_dmsc_iDecisionThresh [7:0] AFIT8_dmsc_iCentGrad */
+ S5K4ECGX_REG_WRITE(0x70000B5E, 0x0020), /* 70000B5E AFIT8_dmsc_iMonochrom [7:0] AFIT8_dmsc_iGBDenoiseVal */
+ S5K4ECGX_REG_WRITE(0x70000B60, 0x0000), /* 70000B60 AFIT8_dmsc_iGRDenoiseVal [7:0] AFIT8_dmsc_iEdgeDesatThrHigh */
+ S5K4ECGX_REG_WRITE(0x70000B62, 0x1800), /* 70000B62 AFIT8_dmsc_iEdgeDesatThrLow [7:0] AFIT8_dmsc_iEdgeDesat */
+ S5K4ECGX_REG_WRITE(0x70000B64, 0x0000), /* 70000B64 AFIT8_dmsc_iNearGrayDesat [7:0] AFIT8_dmsc_iEdgeDesatLimit */
+ S5K4ECGX_REG_WRITE(0x70000B66, 0x1E10), /* 70000B66 AFIT8_postdmsc_iBCoeff [7:0] AFIT8_postdmsc_iGCoeff */
+ S5K4ECGX_REG_WRITE(0x70000B68, 0x000B), /* 70000B68 AFIT8_postdmsc_iWideMult [7:0] AFIT8_yuvemix_mNegSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000B6A, 0x0607), /* 70000B6A AFIT8_yuvemix_mNegSlopes_1 [7:0] AFIT8_yuvemix_mNegSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000B6C, 0x0005), /* 70000B6C AFIT8_yuvemix_mNegSlopes_3 [7:0] AFIT8_yuvemix_mPosSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000B6E, 0x0607), /* 70000B6E AFIT8_yuvemix_mPosSlopes_1 [7:0] AFIT8_yuvemix_mPosSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000B70, 0x0405), /* 70000B70 AFIT8_yuvemix_mPosSlopes_3 [7:0] AFIT8_yuviirnr_iXSupportY */
+ S5K4ECGX_REG_WRITE(0x70000B72, 0x0207), /* 70000B72 AFIT8_yuviirnr_iXSupportUV [7:0] AFIT8_yuviirnr_iLowYNorm */
+ S5K4ECGX_REG_WRITE(0x70000B74, 0x0304), /* 70000B74 AFIT8_yuviirnr_iHighYNorm [7:0] AFIT8_yuviirnr_iLowUVNorm */
+ S5K4ECGX_REG_WRITE(0x70000B76, 0x0409), /* 70000B76 AFIT8_yuviirnr_iHighUVNorm [7:0] AFIT8_yuviirnr_iYNormShift */
+ S5K4ECGX_REG_WRITE(0x70000B78, 0x0306), /* 70000B78 AFIT8_yuviirnr_iUVNormShift [7:0] AFIT8_yuviirnr_iVertLength_Y */
+ S5K4ECGX_REG_WRITE(0x70000B7A, 0x0407), /* 70000B7A AFIT8_yuviirnr_iVertLength_UV [7:0] AFIT8_yuviirnr_iDiffThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000B7C, 0x2404), /* 70000B7C AFIT8_yuviirnr_iDiffThreshH_Y [7:0] AFIT8_yuviirnr_iDiffThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000B7E, 0x0221), /* 70000B7E AFIT8_yuviirnr_iDiffThreshH_UV [7:0] AFIT8_yuviirnr_iMaxThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000B80, 0x1202), /* 70000B80 AFIT8_yuviirnr_iMaxThreshH_Y [7:0] AFIT8_yuviirnr_iMaxThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000B82, 0x0613), /* 70000B82 AFIT8_yuviirnr_iMaxThreshH_UV [7:0] AFIT8_yuviirnr_iYNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000B84, 0x1A02), /* 70000B84 AFIT8_yuviirnr_iYNRStrengthH [7:0] AFIT8_yuviirnr_iUVNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000B86, 0x8018), /* 70000B86 AFIT8_yuviirnr_iUVNRStrengthH [7:0] AFIT8_byr_gras_iShadingPower */
+ S5K4ECGX_REG_WRITE(0x70000B88, 0x0080), /* 70000B88 AFIT8_RGBGamma2_iLinearity [7:0] AFIT8_RGBGamma2_iDarkReduce */
+ S5K4ECGX_REG_WRITE(0x70000B8A, 0x0080), /* 70000B8A AFIT8_ccm_oscar_iSaturation [7:0] AFIT8_RGB2YUV_iYOffset */
+ S5K4ECGX_REG_WRITE(0x70000B8C, 0x0180), /* 70000B8C AFIT8_RGB2YUV_iRGBGain [7:0] AFIT8_bnr_nClustLevel_H */
+ S5K4ECGX_REG_WRITE(0x70000B8E, 0x0A0A), /* 70000B8E AFIT8_bnr_iClustMulT_H [7:0] AFIT8_bnr_iClustMulT_C */
+ S5K4ECGX_REG_WRITE(0x70000B90, 0x0101), /* 70000B90 AFIT8_bnr_iClustThresh_H [7:0] AFIT8_bnr_iClustThresh_C */
+ S5K4ECGX_REG_WRITE(0x70000B92, 0x141D), /* 70000B92 AFIT8_bnr_iDenThreshLow [7:0] AFIT8_bnr_iDenThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x6024), /* 70000B94 AFIT8_ee_iLowSharpPower [7:0] AFIT8_ee_iHighSharpPower */
+ S5K4ECGX_REG_WRITE(0x70000B96, 0x0C0C), /* 70000B96 AFIT8_ee_iLowShDenoise [7:0] AFIT8_ee_iHighShDenoise */
+ S5K4ECGX_REG_WRITE(0x70000B98, 0xFFFF), /* 70000B98 AFIT8_ee_iLowSharpClamp [7:0] AFIT8_ee_iHighSharpClamp */
+ S5K4ECGX_REG_WRITE(0x70000B9A, 0x0808), /* 70000B9A AFIT8_ee_iReduceEdgeMinMult [7:0] AFIT8_ee_iReduceEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000B9C, 0x0A01), /* 70000B9C AFIT8_bnr_nClustLevel_H_Bin [7:0] AFIT8_bnr_iClustMulT_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000B9E, 0x010A), /* 70000B9E AFIT8_bnr_iClustMulT_C_Bin [7:0] AFIT8_bnr_iClustThresh_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000BA0, 0x1B01), /* 70000BA0 AFIT8_bnr_iClustThresh_C_Bin [7:0] AFIT8_bnr_iDenThreshLow_Bin */
+ S5K4ECGX_REG_WRITE(0x70000BA2, 0x2412), /* 70000BA2 AFIT8_bnr_iDenThreshHigh_Bin [7:0] AFIT8_ee_iLowSharpPower_Bin */
+ S5K4ECGX_REG_WRITE(0x70000BA4, 0x0C60), /* 70000BA4 AFIT8_ee_iHighSharpPower_Bin [7:0] AFIT8_ee_iLowShDenoise_Bin */
+ S5K4ECGX_REG_WRITE(0x70000BA6, 0xFF0C), /* 70000BA6 AFIT8_ee_iHighShDenoise_Bin [7:0] AFIT8_ee_iLowSharpClamp_Bin */
+ S5K4ECGX_REG_WRITE(0x70000BA8, 0x08FF), /* 70000BA8 AFIT8_ee_iHighSharpClamp_Bin [7:0] AFIT8_ee_iReduceEdgeMinMult_Bin */
+ S5K4ECGX_REG_WRITE(0x70000BAA, 0x0008), /* 70000BAA AFIT8_ee_iReduceEdgeSlope_Bin [7:0] */
+ S5K4ECGX_REG_WRITE(0x70000BAC, 0x0001), /* 70000BAC AFITB_bnr_nClustLevel_C [0] */
+
+ /* AFIT 3 */
+ S5K4ECGX_REG_WRITE(0x70000BAE, 0x0000), /* 70000BAE AFIT16_BRIGHTNESS */
+ S5K4ECGX_REG_WRITE(0x70000BB0, 0x0000), /* 70000BB0 AFIT16_CONTRAST */
+ S5K4ECGX_REG_WRITE(0x70000BB2, 0x000A), /* 0420 0000 //70000BB2 AFIT16_SATURATION */
+ S5K4ECGX_REG_WRITE(0x70000BB4, 0x0000), /* 70000BB4 AFIT16_SHARP_BLUR */
+ S5K4ECGX_REG_WRITE(0x70000BB6, 0x0000), /* 70000BB6 AFIT16_GLAMOUR */
+ S5K4ECGX_REG_WRITE(0x70000BB8, 0x00C0), /* 70000BB8 AFIT16_bnr_edge_high */
+ S5K4ECGX_REG_WRITE(0x70000BBA, 0x0064), /* 70000BBA AFIT16_postdmsc_iLowBright */
+ S5K4ECGX_REG_WRITE(0x70000BBC, 0x0384), /* 70000BBC AFIT16_postdmsc_iHighBright */
+ S5K4ECGX_REG_WRITE(0x70000BBE, 0x0032), /* 70000BBE AFIT16_postdmsc_iLowSat */
+ S5K4ECGX_REG_WRITE(0x70000BC0, 0x01F4), /* 70000BC0 AFIT16_postdmsc_iHighSat */
+ S5K4ECGX_REG_WRITE(0x70000BC2, 0x0070), /* 70000BC2 AFIT16_postdmsc_iTune */
+ S5K4ECGX_REG_WRITE(0x70000BC4, 0x0040), /* 70000BC4 AFIT16_yuvemix_mNegRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000BC6, 0x00A0), /* 70000BC6 AFIT16_yuvemix_mNegRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000BC8, 0x0100), /* 70000BC8 AFIT16_yuvemix_mNegRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000BCA, 0x0010), /* 70000BCA AFIT16_yuvemix_mPosRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000BCC, 0x0060), /* 70000BCC AFIT16_yuvemix_mPosRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000BCE, 0x0100), /* 70000BCE AFIT16_yuvemix_mPosRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000BD0, 0x1430), /* 70000BD0 AFIT8_bnr_edge_low [7:0] AFIT8_bnr_repl_thresh */
+ S5K4ECGX_REG_WRITE(0x70000BD2, 0x0201), /* 70000BD2 AFIT8_bnr_repl_force [7:0] AFIT8_bnr_iHotThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000BD4, 0x0204), /* 70000BD4 AFIT8_bnr_iHotThreshLow [7:0] AFIT8_bnr_iColdThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000BD6, 0x1504), /* 70000BD6 AFIT8_bnr_iColdThreshLow [7:0] AFIT8_bnr_DispTH_Low */
+ S5K4ECGX_REG_WRITE(0x70000BD8, 0x030F), /* 70000BD8 AFIT8_bnr_DispTH_High [7:0] AFIT8_bnr_DISP_Limit_Low */
+ S5K4ECGX_REG_WRITE(0x70000BDA, 0x0003), /* 70000BDA AFIT8_bnr_DISP_Limit_High [7:0] AFIT8_bnr_iDistSigmaMin */
+ S5K4ECGX_REG_WRITE(0x70000BDC, 0x0902), /* 70000BDC AFIT8_bnr_iDistSigmaMax [7:0] AFIT8_bnr_iDiffSigmaLow */
+ S5K4ECGX_REG_WRITE(0x70000BDE, 0x2004), /* 70000BDE AFIT8_bnr_iDiffSigmaHigh [7:0] AFIT8_bnr_iNormalizedSTD_TH */
+ S5K4ECGX_REG_WRITE(0x70000BE0, 0x0050), /* 70000BE0 AFIT8_bnr_iNormalizedSTD_Limit [7:0] AFIT8_bnr_iDirNRTune */
+ S5K4ECGX_REG_WRITE(0x70000BE2, 0x1140), /* 70000BE2 AFIT8_bnr_iDirMinThres [7:0] AFIT8_bnr_iDirFltDiffThresHigh */
+ S5K4ECGX_REG_WRITE(0x70000BE4, 0x201C), /* 70000BE4 AFIT8_bnr_iDirFltDiffThresLow [7:0] AFIT8_bnr_iDirSmoothPowerHigh */
+ S5K4ECGX_REG_WRITE(0x70000BE6, 0x0620), /* 70000BE6 AFIT8_bnr_iDirSmoothPowerLow [7:0] AFIT8_bnr_iLowMaxSlopeAllowed */
+ S5K4ECGX_REG_WRITE(0x70000BE8, 0x0306), /* 70000BE8 AFIT8_bnr_iHighMaxSlopeAllowed [7:0] AFIT8_bnr_iLowSlopeThresh */
+ S5K4ECGX_REG_WRITE(0x70000BEA, 0x2003), /* 70000BEA AFIT8_bnr_iHighSlopeThresh [7:0] AFIT8_bnr_iSlopenessTH */
+ S5K4ECGX_REG_WRITE(0x70000BEC, 0xFF01), /* 70000BEC AFIT8_bnr_iSlopeBlurStrength [7:0] AFIT8_bnr_iSlopenessLimit */
+ S5K4ECGX_REG_WRITE(0x70000BEE, 0x0404), /* 70000BEE AFIT8_bnr_AddNoisePower1 [7:0] AFIT8_bnr_AddNoisePower2 */
+ S5K4ECGX_REG_WRITE(0x70000BF0, 0x0300), /* 70000BF0 AFIT8_bnr_iRadialTune [7:0] AFIT8_bnr_iRadialPower */
+ S5K4ECGX_REG_WRITE(0x70000BF2, 0x145A), /* 70000BF2 AFIT8_bnr_iRadialLimit [7:0] AFIT8_ee_iFSMagThLow */
+ S5K4ECGX_REG_WRITE(0x70000BF4, 0x1010), /* 70000BF4 AFIT8_ee_iFSMagThHigh [7:0] AFIT8_ee_iFSVarThLow */
+ S5K4ECGX_REG_WRITE(0x70000BF6, 0x000B), /* 70000BF6 AFIT8_ee_iFSVarThHigh [7:0] AFIT8_ee_iFSThLow */
+ S5K4ECGX_REG_WRITE(0x70000BF8, 0x1000), /* 70000BF8 AFIT8_ee_iFSThHigh [7:0] AFIT8_ee_iFSmagPower */
+ S5K4ECGX_REG_WRITE(0x70000BFA, 0x5A0F), /* 70000BFA AFIT8_ee_iFSVarCountTh [7:0] AFIT8_ee_iRadialLimit */
+ S5K4ECGX_REG_WRITE(0x70000BFC, 0x0503), /* 70000BFC AFIT8_ee_iRadialPower [7:0] AFIT8_ee_iSmoothEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000BFE, 0x1802), /* 70000BFE AFIT8_ee_iROADThres [7:0] AFIT8_ee_iROADMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000C00, 0x0000), /* 70000C00 AFIT8_ee_iROADSubMaxNR [7:0] AFIT8_ee_iROADSubThres */
+ S5K4ECGX_REG_WRITE(0x70000C02, 0x2006), /* 70000C02 AFIT8_ee_iROADNeiThres [7:0] AFIT8_ee_iROADNeiMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000C04, 0x3C28), /* 70000C04 AFIT8_ee_iSmoothEdgeThres [7:0] AFIT8_ee_iMSharpen */
+ S5K4ECGX_REG_WRITE(0x70000C06, 0x042C), /* 70000C06 AFIT8_ee_iWSharpen [7:0] AFIT8_ee_iMShThresh */
+ S5K4ECGX_REG_WRITE(0x70000C08, 0x0101), /* 70000C08 AFIT8_ee_iWShThresh [7:0] AFIT8_ee_iReduceNegative */
+ S5K4ECGX_REG_WRITE(0x70000C0A, 0xFF00), /* 70000C0A AFIT8_ee_iEmbossCentAdd [7:0] AFIT8_ee_iShDespeckle */
+ S5K4ECGX_REG_WRITE(0x70000C0C, 0x0904), /* 70000C0C AFIT8_ee_iReduceEdgeThresh [7:0] AFIT8_dmsc_iEnhThresh */
+ S5K4ECGX_REG_WRITE(0x70000C0E, 0x4008), /* 70000C0E AFIT8_dmsc_iDesatThresh [7:0] AFIT8_dmsc_iDemBlurHigh */
+ S5K4ECGX_REG_WRITE(0x70000C10, 0x0540), /* 70000C10 AFIT8_dmsc_iDemBlurLow [7:0] AFIT8_dmsc_iDemBlurRange */
+ S5K4ECGX_REG_WRITE(0x70000C12, 0x8006), /* 70000C12 AFIT8_dmsc_iDecisionThresh [7:0] AFIT8_dmsc_iCentGrad */
+ S5K4ECGX_REG_WRITE(0x70000C14, 0x0020), /* 70000C14 AFIT8_dmsc_iMonochrom [7:0] AFIT8_dmsc_iGBDenoiseVal */
+ S5K4ECGX_REG_WRITE(0x70000C16, 0x0000), /* 70000C16 AFIT8_dmsc_iGRDenoiseVal [7:0] AFIT8_dmsc_iEdgeDesatThrHigh */
+ S5K4ECGX_REG_WRITE(0x70000C18, 0x1800), /* 70000C18 AFIT8_dmsc_iEdgeDesatThrLow [7:0] AFIT8_dmsc_iEdgeDesat */
+ S5K4ECGX_REG_WRITE(0x70000C1A, 0x0000), /* 70000C1A AFIT8_dmsc_iNearGrayDesat [7:0] AFIT8_dmsc_iEdgeDesatLimit */
+ S5K4ECGX_REG_WRITE(0x70000C1C, 0x1E10), /* 70000C1C AFIT8_postdmsc_iBCoeff [7:0] AFIT8_postdmsc_iGCoeff */
+ S5K4ECGX_REG_WRITE(0x70000C1E, 0x000B), /* 70000C1E AFIT8_postdmsc_iWideMult [7:0] AFIT8_yuvemix_mNegSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000C20, 0x0607), /* 70000C20 AFIT8_yuvemix_mNegSlopes_1 [7:0] AFIT8_yuvemix_mNegSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000C22, 0x0005), /* 70000C22 AFIT8_yuvemix_mNegSlopes_3 [7:0] AFIT8_yuvemix_mPosSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000C24, 0x0607), /* 70000C24 AFIT8_yuvemix_mPosSlopes_1 [7:0] AFIT8_yuvemix_mPosSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000C26, 0x0405), /* 70000C26 AFIT8_yuvemix_mPosSlopes_3 [7:0] AFIT8_yuviirnr_iXSupportY */
+ S5K4ECGX_REG_WRITE(0x70000C28, 0x0206), /* 70000C28 AFIT8_yuviirnr_iXSupportUV [7:0] AFIT8_yuviirnr_iLowYNorm */
+ S5K4ECGX_REG_WRITE(0x70000C2A, 0x0304), /* 70000C2A AFIT8_yuviirnr_iHighYNorm [7:0] AFIT8_yuviirnr_iLowUVNorm */
+ S5K4ECGX_REG_WRITE(0x70000C2C, 0x0409), /* 70000C2C AFIT8_yuviirnr_iHighUVNorm [7:0] AFIT8_yuviirnr_iYNormShift */
+ S5K4ECGX_REG_WRITE(0x70000C2E, 0x0305), /* 70000C2E AFIT8_yuviirnr_iUVNormShift [7:0] AFIT8_yuviirnr_iVertLength_Y */
+ S5K4ECGX_REG_WRITE(0x70000C30, 0x0406), /* 70000C30 AFIT8_yuviirnr_iVertLength_UV [7:0] AFIT8_yuviirnr_iDiffThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000C32, 0x2804), /* 70000C32 AFIT8_yuviirnr_iDiffThreshH_Y [7:0] AFIT8_yuviirnr_iDiffThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000C34, 0x0228), /* 70000C34 AFIT8_yuviirnr_iDiffThreshH_UV [7:0] AFIT8_yuviirnr_iMaxThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000C36, 0x1402), /* 70000C36 AFIT8_yuviirnr_iMaxThreshH_Y [7:0] AFIT8_yuviirnr_iMaxThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000C38, 0x0618), /* 70000C38 AFIT8_yuviirnr_iMaxThreshH_UV [7:0] AFIT8_yuviirnr_iYNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000C3A, 0x1A02), /* 70000C3A AFIT8_yuviirnr_iYNRStrengthH [7:0] AFIT8_yuviirnr_iUVNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000C3C, 0x8018), /* 70000C3C AFIT8_yuviirnr_iUVNRStrengthH [7:0] AFIT8_byr_gras_iShadingPower */
+ S5K4ECGX_REG_WRITE(0x70000C3E, 0x0080), /* 70000C3E AFIT8_RGBGamma2_iLinearity [7:0] AFIT8_RGBGamma2_iDarkReduce */
+ S5K4ECGX_REG_WRITE(0x70000C40, 0x0080), /* 70000C40 AFIT8_ccm_oscar_iSaturation [7:0] AFIT8_RGB2YUV_iYOffset */
+ S5K4ECGX_REG_WRITE(0x70000C42, 0x0180), /* 70000C42 AFIT8_RGB2YUV_iRGBGain [7:0] AFIT8_bnr_nClustLevel_H */
+ S5K4ECGX_REG_WRITE(0x70000C44, 0x0A0A), /* 70000C44 AFIT8_bnr_iClustMulT_H [7:0] AFIT8_bnr_iClustMulT_C */
+ S5K4ECGX_REG_WRITE(0x70000C46, 0x0101), /* 70000C46 AFIT8_bnr_iClustThresh_H [7:0] AFIT8_bnr_iClustThresh_C */
+ S5K4ECGX_REG_WRITE(0x70000C48, 0x1117), /* 70000C48 AFIT8_bnr_iDenThreshLow [7:0] AFIT8_bnr_iDenThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x6024), /* 70000C4A AFIT8_ee_iLowSharpPower [7:0] AFIT8_ee_iHighSharpPower */
+ S5K4ECGX_REG_WRITE(0x70000C4C, 0x0A0A), /* 70000C4C AFIT8_ee_iLowShDenoise [7:0] AFIT8_ee_iHighShDenoise */
+ S5K4ECGX_REG_WRITE(0x70000C4E, 0xFFFF), /* 70000C4E AFIT8_ee_iLowSharpClamp [7:0] AFIT8_ee_iHighSharpClamp */
+ S5K4ECGX_REG_WRITE(0x70000C50, 0x0808), /* 70000C50 AFIT8_ee_iReduceEdgeMinMult [7:0] AFIT8_ee_iReduceEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000C52, 0x0A01), /* 70000C52 AFIT8_bnr_nClustLevel_H_Bin [7:0] AFIT8_bnr_iClustMulT_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C54, 0x010A), /* 70000C54 AFIT8_bnr_iClustMulT_C_Bin [7:0] AFIT8_bnr_iClustThresh_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C56, 0x1501), /* 70000C56 AFIT8_bnr_iClustThresh_C_Bin [7:0] AFIT8_bnr_iDenThreshLow_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C58, 0x240F), /* 70000C58 AFIT8_bnr_iDenThreshHigh_Bin [7:0] AFIT8_ee_iLowSharpPower_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C5A, 0x0A60), /* 70000C5A AFIT8_ee_iHighSharpPower_Bin [7:0] AFIT8_ee_iLowShDenoise_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C5C, 0xFF0A), /* 70000C5C AFIT8_ee_iHighShDenoise_Bin [7:0] AFIT8_ee_iLowSharpClamp_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C5E, 0x08FF), /* 70000C5E AFIT8_ee_iHighSharpClamp_Bin [7:0] AFIT8_ee_iReduceEdgeMinMult_Bin */
+ S5K4ECGX_REG_WRITE(0x70000C60, 0x0008), /* 70000C60 AFIT8_ee_iReduceEdgeSlope_Bin [7:0] */
+ S5K4ECGX_REG_WRITE(0x70000C62, 0x0001), /* 70000C62 AFITB_bnr_nClustLevel_C [0] */
+
+ /* AFIT 4 */
+ S5K4ECGX_REG_WRITE(0x70000C64, 0x0000), /* 70000C64 AFIT16_BRIGHTNESS */
+ S5K4ECGX_REG_WRITE(0x70000C66, 0x0000), /* 70000C66 AFIT16_CONTRAST */
+ S5K4ECGX_REG_WRITE(0x70000C68, 0x0000), /* 70000C68 AFIT16_SATURATION */
+ S5K4ECGX_REG_WRITE(0x70000C6A, 0x0000), /* 70000C6A AFIT16_SHARP_BLUR */
+ S5K4ECGX_REG_WRITE(0x70000C6C, 0x0000), /* 70000C6C AFIT16_GLAMOUR */
+ S5K4ECGX_REG_WRITE(0x70000C6E, 0x00C0), /* 70000C6E AFIT16_bnr_edge_high */
+ S5K4ECGX_REG_WRITE(0x70000C70, 0x0064), /* 70000C70 AFIT16_postdmsc_iLowBright */
+ S5K4ECGX_REG_WRITE(0x70000C72, 0x0384), /* 70000C72 AFIT16_postdmsc_iHighBright */
+ S5K4ECGX_REG_WRITE(0x70000C74, 0x0032), /* 70000C74 AFIT16_postdmsc_iLowSat */
+ S5K4ECGX_REG_WRITE(0x70000C76, 0x01F4), /* 70000C76 AFIT16_postdmsc_iHighSat */
+ S5K4ECGX_REG_WRITE(0x70000C78, 0x0070), /* 70000C78 AFIT16_postdmsc_iTune */
+ S5K4ECGX_REG_WRITE(0x70000C7A, 0x0040), /* 70000C7A AFIT16_yuvemix_mNegRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000C7C, 0x00A0), /* 70000C7C AFIT16_yuvemix_mNegRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000C7E, 0x0100), /* 70000C7E AFIT16_yuvemix_mNegRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000C80, 0x0010), /* 70000C80 AFIT16_yuvemix_mPosRanges_0 */
+ S5K4ECGX_REG_WRITE(0x70000C82, 0x0060), /* 70000C82 AFIT16_yuvemix_mPosRanges_1 */
+ S5K4ECGX_REG_WRITE(0x70000C84, 0x0100), /* 70000C84 AFIT16_yuvemix_mPosRanges_2 */
+ S5K4ECGX_REG_WRITE(0x70000C86, 0x1430), /* 70000C86 AFIT8_bnr_edge_low [7:0] AFIT8_bnr_repl_thresh */
+ S5K4ECGX_REG_WRITE(0x70000C88, 0x0201), /* 70000C88 AFIT8_bnr_repl_force [7:0] AFIT8_bnr_iHotThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000C8A, 0x0204), /* 70000C8A AFIT8_bnr_iHotThreshLow [7:0] AFIT8_bnr_iColdThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000C8C, 0x0F04), /* 70000C8C AFIT8_bnr_iColdThreshLow [7:0] AFIT8_bnr_DispTH_Low */
+ S5K4ECGX_REG_WRITE(0x70000C8E, 0x030C), /* 70000C8E AFIT8_bnr_DispTH_High [7:0] AFIT8_bnr_DISP_Limit_Low */
+ S5K4ECGX_REG_WRITE(0x70000C90, 0x0003), /* 70000C90 AFIT8_bnr_DISP_Limit_High [7:0] AFIT8_bnr_iDistSigmaMin */
+ S5K4ECGX_REG_WRITE(0x70000C92, 0x0602), /* 70000C92 AFIT8_bnr_iDistSigmaMax [7:0] AFIT8_bnr_iDiffSigmaLow */
+ S5K4ECGX_REG_WRITE(0x70000C94, 0x1803), /* 70000C94 AFIT8_bnr_iDiffSigmaHigh [7:0] AFIT8_bnr_iNormalizedSTD_TH */
+ S5K4ECGX_REG_WRITE(0x70000C96, 0x0040), /* 70000C96 AFIT8_bnr_iNormalizedSTD_Limit [7:0] AFIT8_bnr_iDirNRTune */
+ S5K4ECGX_REG_WRITE(0x70000C98, 0x0E20), /* 70000C98 AFIT8_bnr_iDirMinThres [7:0] AFIT8_bnr_iDirFltDiffThresHigh */
+ S5K4ECGX_REG_WRITE(0x70000C9A, 0x2018), /* 70000C9A AFIT8_bnr_iDirFltDiffThresLow [7:0] AFIT8_bnr_iDirSmoothPowerHigh */
+ S5K4ECGX_REG_WRITE(0x70000C9C, 0x0620), /* 70000C9C AFIT8_bnr_iDirSmoothPowerLow [7:0] AFIT8_bnr_iLowMaxSlopeAllowed */
+ S5K4ECGX_REG_WRITE(0x70000C9E, 0x0306), /* 70000C9E AFIT8_bnr_iHighMaxSlopeAllowed [7:0] AFIT8_bnr_iLowSlopeThresh */
+ S5K4ECGX_REG_WRITE(0x70000CA0, 0x2003), /* 70000CA0 AFIT8_bnr_iHighSlopeThresh [7:0] AFIT8_bnr_iSlopenessTH */
+ S5K4ECGX_REG_WRITE(0x70000CA2, 0xFF01), /* 70000CA2 AFIT8_bnr_iSlopeBlurStrength [7:0] AFIT8_bnr_iSlopenessLimit */
+ S5K4ECGX_REG_WRITE(0x70000CA4, 0x0404), /* 70000CA4 AFIT8_bnr_AddNoisePower1 [7:0] AFIT8_bnr_AddNoisePower2 */
+ S5K4ECGX_REG_WRITE(0x70000CA6, 0x0200), /* 70000CA6 AFIT8_bnr_iRadialTune [7:0] AFIT8_bnr_iRadialPower */
+ S5K4ECGX_REG_WRITE(0x70000CA8, 0x145A), /* 70000CA8 AFIT8_bnr_iRadialLimit [7:0] AFIT8_ee_iFSMagThLow */
+ S5K4ECGX_REG_WRITE(0x70000CAA, 0x1010), /* 70000CAA AFIT8_ee_iFSMagThHigh [7:0] AFIT8_ee_iFSVarThLow */
+ S5K4ECGX_REG_WRITE(0x70000CAC, 0x000B), /* 70000CAC AFIT8_ee_iFSVarThHigh [7:0] AFIT8_ee_iFSThLow */
+ S5K4ECGX_REG_WRITE(0x70000CAE, 0x1200), /* 70000CAE AFIT8_ee_iFSThHigh [7:0] AFIT8_ee_iFSmagPower */
+ S5K4ECGX_REG_WRITE(0x70000CB0, 0x5A0F), /* 70000CB0 AFIT8_ee_iFSVarCountTh [7:0] AFIT8_ee_iRadialLimit */
+ S5K4ECGX_REG_WRITE(0x70000CB2, 0x0502), /* 70000CB2 AFIT8_ee_iRadialPower [7:0] AFIT8_ee_iSmoothEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000CB4, 0x1802), /* 70000CB4 AFIT8_ee_iROADThres [7:0] AFIT8_ee_iROADMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000CB6, 0x0000), /* 70000CB6 AFIT8_ee_iROADSubMaxNR [7:0] AFIT8_ee_iROADSubThres */
+ S5K4ECGX_REG_WRITE(0x70000CB8, 0x2006), /* 70000CB8 AFIT8_ee_iROADNeiThres [7:0] AFIT8_ee_iROADNeiMaxNR */
+ S5K4ECGX_REG_WRITE(0x70000CBA, 0x4028), /* 70000CBA AFIT8_ee_iSmoothEdgeThres [7:0] AFIT8_ee_iMSharpen */
+ S5K4ECGX_REG_WRITE(0x70000CBC, 0x0430), /* 70000CBC AFIT8_ee_iWSharpen [7:0] AFIT8_ee_iMShThresh */
+ S5K4ECGX_REG_WRITE(0x70000CBE, 0x0101), /* 70000CBE AFIT8_ee_iWShThresh [7:0] AFIT8_ee_iReduceNegative */
+ S5K4ECGX_REG_WRITE(0x70000CC0, 0xFF00), /* 70000CC0 AFIT8_ee_iEmbossCentAdd [7:0] AFIT8_ee_iShDespeckle */
+ S5K4ECGX_REG_WRITE(0x70000CC2, 0x0804), /* 70000CC2 AFIT8_ee_iReduceEdgeThresh [7:0] AFIT8_dmsc_iEnhThresh */
+ S5K4ECGX_REG_WRITE(0x70000CC4, 0x4008), /* 70000CC4 AFIT8_dmsc_iDesatThresh [7:0] AFIT8_dmsc_iDemBlurHigh */
+ S5K4ECGX_REG_WRITE(0x70000CC6, 0x0540), /* 70000CC6 AFIT8_dmsc_iDemBlurLow [7:0] AFIT8_dmsc_iDemBlurRange */
+ S5K4ECGX_REG_WRITE(0x70000CC8, 0x8006), /* 70000CC8 AFIT8_dmsc_iDecisionThresh [7:0] AFIT8_dmsc_iCentGrad */
+ S5K4ECGX_REG_WRITE(0x70000CCA, 0x0020), /* 70000CCA AFIT8_dmsc_iMonochrom [7:0] AFIT8_dmsc_iGBDenoiseVal */
+ S5K4ECGX_REG_WRITE(0x70000CCC, 0x0000), /* 70000CCC AFIT8_dmsc_iGRDenoiseVal [7:0] AFIT8_dmsc_iEdgeDesatThrHigh */
+ S5K4ECGX_REG_WRITE(0x70000CCE, 0x1800), /* 70000CCE AFIT8_dmsc_iEdgeDesatThrLow [7:0] AFIT8_dmsc_iEdgeDesat */
+ S5K4ECGX_REG_WRITE(0x70000CD0, 0x0000), /* 70000CD0 AFIT8_dmsc_iNearGrayDesat [7:0] AFIT8_dmsc_iEdgeDesatLimit */
+ S5K4ECGX_REG_WRITE(0x70000CD2, 0x1E10), /* 70000CD2 AFIT8_postdmsc_iBCoeff [7:0] AFIT8_postdmsc_iGCoeff */
+ S5K4ECGX_REG_WRITE(0x70000CD4, 0x000B), /* 70000CD4 AFIT8_postdmsc_iWideMult [7:0] AFIT8_yuvemix_mNegSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000CD6, 0x0607), /* 70000CD6 AFIT8_yuvemix_mNegSlopes_1 [7:0] AFIT8_yuvemix_mNegSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000CD8, 0x0005), /* 70000CD8 AFIT8_yuvemix_mNegSlopes_3 [7:0] AFIT8_yuvemix_mPosSlopes_0 */
+ S5K4ECGX_REG_WRITE(0x70000CDA, 0x0607), /* 70000CDA AFIT8_yuvemix_mPosSlopes_1 [7:0] AFIT8_yuvemix_mPosSlopes_2 */
+ S5K4ECGX_REG_WRITE(0x70000CDC, 0x0405), /* 70000CDC AFIT8_yuvemix_mPosSlopes_3 [7:0] AFIT8_yuviirnr_iXSupportY */
+ S5K4ECGX_REG_WRITE(0x70000CDE, 0x0205), /* 70000CDE AFIT8_yuviirnr_iXSupportUV [7:0] AFIT8_yuviirnr_iLowYNorm */
+ S5K4ECGX_REG_WRITE(0x70000CE0, 0x0304), /* 70000CE0 AFIT8_yuviirnr_iHighYNorm [7:0] AFIT8_yuviirnr_iLowUVNorm */
+ S5K4ECGX_REG_WRITE(0x70000CE2, 0x0409), /* 70000CE2 AFIT8_yuviirnr_iHighUVNorm [7:0] AFIT8_yuviirnr_iYNormShift */
+ S5K4ECGX_REG_WRITE(0x70000CE4, 0x0306), /* 70000CE4 AFIT8_yuviirnr_iUVNormShift [7:0] AFIT8_yuviirnr_iVertLength_Y */
+ S5K4ECGX_REG_WRITE(0x70000CE6, 0x0407), /* 70000CE6 AFIT8_yuviirnr_iVertLength_UV [7:0] AFIT8_yuviirnr_iDiffThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000CE8, 0x2C04), /* 70000CE8 AFIT8_yuviirnr_iDiffThreshH_Y [7:0] AFIT8_yuviirnr_iDiffThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000CEA, 0x022C), /* 70000CEA AFIT8_yuviirnr_iDiffThreshH_UV [7:0] AFIT8_yuviirnr_iMaxThreshL_Y */
+ S5K4ECGX_REG_WRITE(0x70000CEC, 0x1402), /* 70000CEC AFIT8_yuviirnr_iMaxThreshH_Y [7:0] AFIT8_yuviirnr_iMaxThreshL_UV */
+ S5K4ECGX_REG_WRITE(0x70000CEE, 0x0618), /* 70000CEE AFIT8_yuviirnr_iMaxThreshH_UV [7:0] AFIT8_yuviirnr_iYNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000CF0, 0x1A02), /* 70000CF0 AFIT8_yuviirnr_iYNRStrengthH [7:0] AFIT8_yuviirnr_iUVNRStrengthL */
+ S5K4ECGX_REG_WRITE(0x70000CF2, 0x8018), /* 70000CF2 AFIT8_yuviirnr_iUVNRStrengthH [7:0] AFIT8_byr_gras_iShadingPower */
+ S5K4ECGX_REG_WRITE(0x70000CF4, 0x0080), /* 70000CF4 AFIT8_RGBGamma2_iLinearity [7:0] AFIT8_RGBGamma2_iDarkReduce */
+ S5K4ECGX_REG_WRITE(0x70000CF6, 0x0080), /* 70000CF6 AFIT8_ccm_oscar_iSaturation [7:0] AFIT8_RGB2YUV_iYOffset */
+ S5K4ECGX_REG_WRITE(0x70000CF8, 0x0180), /* 70000CF8 AFIT8_RGB2YUV_iRGBGain [7:0] AFIT8_bnr_nClustLevel_H */
+ S5K4ECGX_REG_WRITE(0x70000CFA, 0x0A0A), /* 70000CFA AFIT8_bnr_iClustMulT_H [7:0] AFIT8_bnr_iClustMulT_C */
+ S5K4ECGX_REG_WRITE(0x70000CFC, 0x0101), /* 70000CFC AFIT8_bnr_iClustThresh_H [7:0] AFIT8_bnr_iClustThresh_C */
+ S5K4ECGX_REG_WRITE(0x70000CFE, 0x0C0F), /* 70000CFE AFIT8_bnr_iDenThreshLow [7:0] AFIT8_bnr_iDenThreshHigh */
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x6024), /* 70000D00 AFIT8_ee_iLowSharpPower [7:0] AFIT8_ee_iHighSharpPower */
+ S5K4ECGX_REG_WRITE(0x70000D02, 0x0808), /* 70000D02 AFIT8_ee_iLowShDenoise [7:0] AFIT8_ee_iHighShDenoise */
+ S5K4ECGX_REG_WRITE(0x70000D04, 0xFFFF), /* 70000D04 AFIT8_ee_iLowSharpClamp [7:0] AFIT8_ee_iHighSharpClamp */
+ S5K4ECGX_REG_WRITE(0x70000D06, 0x0808), /* 70000D06 AFIT8_ee_iReduceEdgeMinMult [7:0] AFIT8_ee_iReduceEdgeSlope */
+ S5K4ECGX_REG_WRITE(0x70000D08, 0x0A01), /* 70000D08 AFIT8_bnr_nClustLevel_H_Bin [7:0] AFIT8_bnr_iClustMulT_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D0A, 0x010A), /* 70000D0A AFIT8_bnr_iClustMulT_C_Bin [7:0] AFIT8_bnr_iClustThresh_H_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D0C, 0x0F01), /* 70000D0C AFIT8_bnr_iClustThresh_C_Bin [7:0] AFIT8_bnr_iDenThreshLow_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D0E, 0x240C), /* 70000D0E AFIT8_bnr_iDenThreshHigh_Bin [7:0] AFIT8_ee_iLowSharpPower_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D10, 0x0860), /* 70000D10 AFIT8_ee_iHighSharpPower_Bin [7:0] AFIT8_ee_iLowShDenoise_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D12, 0xFF08), /* 70000D12 AFIT8_ee_iHighShDenoise_Bin [7:0] AFIT8_ee_iLowSharpClamp_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D14, 0x08FF), /* 70000D14 AFIT8_ee_iHighSharpClamp_Bin [7:0] AFIT8_ee_iReduceEdgeMinMult_Bin */
+ S5K4ECGX_REG_WRITE(0x70000D16, 0x0008), /* 70000D16 AFIT8_ee_iReduceEdgeSlope_Bin [7:0] */
+ S5K4ECGX_REG_WRITE(0x70000D18, 0x0001), /* 70000D18 AFITB_bnr_nClustLevel_C [0] bWideWide[1] */
+
+ S5K4ECGX_REG_WRITE(0x70000D1A, 0x23CE),
+ S5K4ECGX_REG_WRITE(0x70000D1C, 0xFDC8),
+ S5K4ECGX_REG_WRITE(0x70000D1E, 0x112E),
+ S5K4ECGX_REG_WRITE(0x70000D20, 0x93A5),
+ S5K4ECGX_REG_WRITE(0x70000D22, 0xFE67),
+ S5K4ECGX_REG_WRITE(0x70000D24, 0x0000),
+
+ /* System Setting */
+ S5K4ECGX_REG_WRITE(0x700001F8, 0x5DC0), /* REG_TC_IPRM_InClockLSBs MCLK: 24Mhz */
+ S5K4ECGX_REG_WRITE(0x70000212, 0x0002), /* REG_TC_IPRM_UseNPviClocks */
+ S5K4ECGX_REG_WRITE(0x70000214, 0x0000), /* REG_TC_IPRM_UseNMipiClocks */
+ S5K4ECGX_REG_WRITE(0x70000216, 0x0000), /* REG_TC_IPRM_NumberOfMipiLanes */
+ S5K4ECGX_REG_WRITE(0x7000021A, 0x3A98), /* REG_TC_IPRM_OpClk4KHz_0 SCLK: 60Mhz */
+ S5K4ECGX_REG_WRITE(0x7000021C, 0x4F1A), /* REG_TC_IPRM_MinOutRate4KHz_0 PCLK Min : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x7000021E, 0x4F1A), /* REG_TC_IPRM_MaxOutRate4KHz_0 PCLK Max : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x70000220, 0x4F1A), /* REG_TC_IPRM_OpClk4KHz_1 SCLK : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x70000222, 0x4F1A), /* REG_TC_IPRM_MinOutRate4KHz_1 PCLK Min : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x70000224, 0x4F1A), /* REG_TC_IPRM_MaxOutRate4KHz_1 PCLK Max : 81Mhz */
+ S5K4ECGX_REG_WRITE(0x7000022C, 0x0001), /* REG_TC_IPRM_InitParamsUpdated */
+
+ /* ETC Setting */
+ S5K4ECGX_REG_WRITE(0x70000478, 0x005F), /* REG_TC_BRC_usPrevQuality */
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x005F), /* REG_TC_BRC_usCaptureQuality */
+
+ S5K4ECGX_REG_WRITE(0x7000047C, 0x0001), /* REG_TC_THUMB_Thumb_bActive */
+ S5K4ECGX_REG_WRITE(0x7000047E, 0x0280), /* REG_TC_THUMB_Thumb_uWidth */
+ S5K4ECGX_REG_WRITE(0x70000480, 0x01E0), /* REG_TC_THUMB_Thumb_uHeight */
+ S5K4ECGX_REG_WRITE(0x70000482, 0x0005), /* REG_TC_THUMB_Thumb_Format */
+
+ S5K4ECGX_REG_WRITE(0x700017DC, 0x0054), /* jpeg_ManualMBCV */
+ S5K4ECGX_REG_WRITE(0x70001AE4, 0x001C), /* senHal_bExtraAddLine */
+ S5K4ECGX_REG_WRITE(0x70000284, 0x0001), /* REG_TC_GP_bBypassScalerJpg */
+ S5K4ECGX_REG_WRITE(0x7000028A, 0x0000), /* REG_TC_GP_bUse1FrameCaptureMode 0 Continuous mode 1 Single frame mode */
+
+ /* Configuration Setting */
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x0288), /* REG_0TC_PCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x01E8), /* REG_0TC_PCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005), /* REG_0TC_PCFG_Format 5 YUV 7 Raw 9 JPG */
+ S5K4ECGX_REG_WRITE(0x700002AC, 0x4F1A), /* REG_0TC_PCFG_usMaxOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700002AE, 0x4F1A), /* REG_0TC_PCFG_usMinOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700002B0, 0x0100), /* REG_0TC_PCFG_OutClkPerPix88 */
+ S5K4ECGX_REG_WRITE(0x700002B2, 0x0300), /* REG_0TC_PCFG_uBpp88 */
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0042), /* REG_0TC_PCFG_PVIMask 0407 0x0052->0x0042 */
+ S5K4ECGX_REG_WRITE(0x700002B6, 0x0000), /* REG_0TC_PCFG_OIFMask */
+ S5K4ECGX_REG_WRITE(0x700002B8, 0x01E0), /* REG_0TC_PCFG_usJpegPacketSize */
+ S5K4ECGX_REG_WRITE(0x700002BA, 0x0000), /* REG_0TC_PCFG_usJpegTotalPackets */
+ S5K4ECGX_REG_WRITE(0x700002BC, 0x0000), /* REG_0TC_PCFG_uClockInd */
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000), /* REG_0TC_PCFG_usFrTimeType */
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0002), /* REG_0TC_PCFG_FrRateQualityType */
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x03E8), /* REG_0TC_PCFG_usMaxFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A), /* REG_0TC_PCFG_usMinFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000), /* REG_0TC_PCFG_uPrevMirror */
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000), /* REG_0TC_PCFG_uCaptureMirror */
+ S5K4ECGX_REG_WRITE(0x700002D4, 0x0000), /* REG_0TC_PCFG_uRotation */
+
+ S5K4ECGX_REG_WRITE(0x70000396, 0x0000), /* REG_0TC_CCFG_uCaptureMode */
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0A00), /* REG_0TC_CCFG_usWidth */
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x0780), /* REG_0TC_CCFG_usHeight */
+ S5K4ECGX_REG_WRITE(0x7000039C, 0x0005), /* REG_0TC_CCFG_Format 0407 0x0009->0x0005 */
+ S5K4ECGX_REG_WRITE(0x7000039E, 0x4F1A), /* REG_0TC_CCFG_usMaxOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700003A0, 0x4F1A), /* REG_0TC_CCFG_usMinOut4KHzRate */
+ S5K4ECGX_REG_WRITE(0x700003A2, 0x0100), /* REG_0TC_CCFG_OutClkPerPix88 */
+ S5K4ECGX_REG_WRITE(0x700003A4, 0x0300), /* REG_0TC_CCFG_uBpp88 */
+ S5K4ECGX_REG_WRITE(0x700003A6, 0x0042), /* REG_0TC_CCFG_PVIMask 0407 0x0002->0x0042 */
+ S5K4ECGX_REG_WRITE(0x700003A8, 0x0070), /* REG_0TC_CCFG_OIFMask */
+ S5K4ECGX_REG_WRITE(0x700003AA, 0x0810), /* REG_0TC_CCFG_usJpegPacketSize */
+ S5K4ECGX_REG_WRITE(0x700003AC, 0x0900), /* REG_0TC_CCFG_usJpegTotalPackets */
+ S5K4ECGX_REG_WRITE(0x700003AE, 0x0001), /* REG_0TC_CCFG_uClockInd */
+ S5K4ECGX_REG_WRITE(0x700003B0, 0x0000), /* REG_0TC_CCFG_usFrTimeType */
+ S5K4ECGX_REG_WRITE(0x700003B2, 0x0002), /* REG_0TC_CCFG_FrRateQualityType */
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x0535), /* REG_0TC_CCFG_usMaxFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x029A), /* REG_0TC_CCFG_usMinFrTimeMsecMult10 */
+
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001CC2, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001CC4, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001CC6, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001CC8, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x700001A8, 0x0A0A),
+
+ S5K4ECGX_REG_WRITE(0x7000147C, 0x0170),
+ S5K4ECGX_REG_WRITE(0x70001482, 0x01E0),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000), /* REG_TC_GP_ActivePrevConfig */
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001), /* REG_TC_GP_PrevOpenAfterChange */
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* REG_TC_GP_PrevConfigChanged */
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001), /* REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001), /* REG_TC_GP_EnablePreview */
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001), /* REG_TC_GP_EnablePreviewChanged */
+
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_DTP_init) = {
+ S5K4ECGX_REG_WRITE(0xD000B054, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_DTP_stop) = {
+ S5K4ECGX_REG_WRITE(0xD000B054, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_Auto) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_7) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_15) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_FPS_30) = {
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Normal) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Solarization) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0002),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Negative) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0003),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Sepia) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0004),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Effect_Black_White) = {
+ S5K4ECGX_REG_WRITE(0x7000023C, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Auto) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Sunny) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Cloudy) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0710),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0420),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Tungsten) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0390),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0920),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WB_Fluorescent) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0875),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WDR_on) = {
+ S5K4ECGX_REG_WRITE(0x70001BEA, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_WDR_off) = {
+ S5K4ECGX_REG_WRITE(0x70001BEA, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_Auto) = {
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000F2A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0200),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_100) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x01A0),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_200) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_ISO_400) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0680),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Matrix) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0101),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Center) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0102),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Metering_Spot) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFF30),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFA0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFC8),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0xFFE0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0038),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_EV_Plus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000230, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFF81),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFFA0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFFC0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0xFFE0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Contrast_Plus_4) = {
+ S5K4ECGX_REG_WRITE(0x70000232, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x2010),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x4020),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x4020),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x6024),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x8040),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x8040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xA060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Sharpness_Plus_3) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xC080),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xC080),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Minus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0xFF81),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Minus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0xFFC0),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Default) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Plus_1) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0040),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Saturation_Plus_2) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x007F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_High) = {
+ S5K4ECGX_REG_WRITE(0x70000478, 0x005F),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x005F),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_Normal) = {
+ S5K4ECGX_REG_WRITE(0x70000478, 0x005A),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x005A),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Jpeg_Quality_Low) = {
+ S5K4ECGX_REG_WRITE(0x70000478, 0x0054),
+ S5K4ECGX_REG_WRITE(0x7000047A, 0x0054),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Default) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0403),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0304),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0303),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0102),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0201),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0202),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0102),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700006B8, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x000C),
+
+ S5K4ECGX_REG_WRITE(0x70000F2A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000F30, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x077F),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x70002C66, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70001484, 0x003C),
+ S5K4ECGX_REG_WRITE(0x7000148A, 0x000F),
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000598, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000059A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000059C, 0x0470),
+ S5K4ECGX_REG_WRITE(0x7000059E, 0x0C00),
+ S5K4ECGX_REG_WRITE(0x700005A0, 0x0100),
+ S5K4ECGX_REG_WRITE(0x700005A2, 0x1000),
+
+ S5K4ECGX_REG_WRITE(0x70000544, 0x0111),
+ S5K4ECGX_REG_WRITE(0x70000546, 0x00EF),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x6024),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x6024),
+
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000638, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x0A3C),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x0D05),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x3408),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0x3408),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0x8214),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000654, 0xC350),
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000658, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0xC350),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A), /* #REG_0TC_PCFG_usMaxFrTimeMsecMult10 */
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A), /* #REG_0TC_PCFG_usMinFrTimeMsecMult10 */
+
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x0535),
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x029A),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Portrait) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0x2010),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0x2010),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Nightshot) = {
+ S5K4ECGX_REG_WRITE(0x700006B8, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x00FF),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0900), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000658, 0xD090),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0007),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0xD090),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0007),
+
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x1388),
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x1388),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x09C4),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x1580),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Backlight) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x010F),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0F01),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Landscape) = {
+ S5K4ECGX_REG_WRITE(0x70001492, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001494, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001496, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70001498, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149A, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149C, 0x0101),
+ S5K4ECGX_REG_WRITE(0x7000149E, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014A8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014AE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014B8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014BE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C2, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C4, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C6, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014C8, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CA, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CC, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014CE, 0x0101),
+ S5K4ECGX_REG_WRITE(0x700014D0, 0x0101),
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xE082),
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Sports) = {
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x7000058C, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000058E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000590, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000592, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000594, 0x3520),
+ S5K4ECGX_REG_WRITE(0x70000596, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000598, 0x3520),
+ S5K4ECGX_REG_WRITE(0x7000059A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000059C, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000059E, 0x0200),
+ S5K4ECGX_REG_WRITE(0x700005A0, 0x0200),
+ S5K4ECGX_REG_WRITE(0x700005A2, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Party_Indoor) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x0340),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Beach_Snow) = {
+ S5K4ECGX_REG_WRITE(0x70001484, 0x0045), /* #TVAR_ae_BrAve */
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x065F),
+ S5K4ECGX_REG_WRITE(0x700004D6, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004D8, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004D2, 0x00D0),
+ S5K4ECGX_REG_WRITE(0x700004D4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700006C2, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Sunset) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Duskdawn) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x0505),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0875),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Fall_Color) = {
+ S5K4ECGX_REG_WRITE(0x70000234, 0x0060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Fireworks) = {
+ S5K4ECGX_REG_WRITE(0x70000638, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000063A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000063C, 0x1478),
+ S5K4ECGX_REG_WRITE(0x7000063E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000640, 0x1A0A),
+ S5K4ECGX_REG_WRITE(0x70000642, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000644, 0x6810),
+ S5K4ECGX_REG_WRITE(0x70000646, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000648, 0x6810),
+ S5K4ECGX_REG_WRITE(0x7000064A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000064C, 0xD020),
+ S5K4ECGX_REG_WRITE(0x7000064E, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000650, 0x0428),
+ S5K4ECGX_REG_WRITE(0x70000652, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000654, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x70000656, 0x0006),
+ S5K4ECGX_REG_WRITE(0x70000658, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x7000065A, 0x0006),
+ S5K4ECGX_REG_WRITE(0x7000065C, 0x1A80),
+ S5K4ECGX_REG_WRITE(0x7000065E, 0x0006),
+
+ S5K4ECGX_REG_WRITE(0x700003B4, 0x2710),
+ S5K4ECGX_REG_WRITE(0x700003B6, 0x2710),
+
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000023E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000240, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Text) = {
+ S5K4ECGX_REG_WRITE(0x70000A28, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000ADE, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000B94, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000C4A, 0xA060),
+ S5K4ECGX_REG_WRITE(0x70000D00, 0xA060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Scene_Candle_Light) = {
+ S5K4ECGX_REG_WRITE(0x700004E6, 0x0777),
+ S5K4ECGX_REG_WRITE(0x700004BA, 0x05E0),
+ S5K4ECGX_REG_WRITE(0x700004BC, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004BE, 0x0400),
+ S5K4ECGX_REG_WRITE(0x700004C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C2, 0x0530),
+ S5K4ECGX_REG_WRITE(0x700004C4, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700004C6, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Night_Capture) = {
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0900), /* #lt_ExpGain_ExpCurveGainMaxStr */
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Return_Macro_pos) = {
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0066),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x006C),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x0072),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70001606, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001608, 0x0084),
+ S5K4ECGX_REG_WRITE(0x7000160A, 0x008A),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x0090),
+ S5K4ECGX_REG_WRITE(0x7000160E, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001610, 0x009C),
+ S5K4ECGX_REG_WRITE(0x70001612, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001614, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x70001616, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x70001618, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x7000161A, 0x00BA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Normal_mode) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0000),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0004),
+ S5K4ECGX_MDELAY(200),
+ S5K4ECGX_REG_WRITE(0x70001648, 0x9002),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Macro_mode) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x00D0),
+ S5K4ECGX_MDELAY(100),
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0004),
+ S5K4ECGX_MDELAY(200),
+ S5K4ECGX_REG_WRITE(0x70001648, 0x9042),
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x1800),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Low_Light_Mode_On) = {
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x0C00),
+
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x000C),
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0033),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x0045),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0057),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x0063),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x006F),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x007B),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0087),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0093),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x00B1),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AF_Low_Light_Mode_Off) = {
+ S5K4ECGX_REG_WRITE(0x700015DA, 0x1800),
+
+ S5K4ECGX_REG_WRITE(0x700015E8, 0x0018),
+ S5K4ECGX_REG_WRITE(0x700015EA, 0x002A),
+ S5K4ECGX_REG_WRITE(0x700015EC, 0x0030),
+ S5K4ECGX_REG_WRITE(0x700015EE, 0x0036),
+ S5K4ECGX_REG_WRITE(0x700015F0, 0x003C),
+ S5K4ECGX_REG_WRITE(0x700015F2, 0x0042),
+ S5K4ECGX_REG_WRITE(0x700015F4, 0x0048),
+ S5K4ECGX_REG_WRITE(0x700015F6, 0x004E),
+ S5K4ECGX_REG_WRITE(0x700015F8, 0x0054),
+ S5K4ECGX_REG_WRITE(0x700015FA, 0x005A),
+ S5K4ECGX_REG_WRITE(0x700015FC, 0x0060),
+ S5K4ECGX_REG_WRITE(0x700015FE, 0x0066),
+ S5K4ECGX_REG_WRITE(0x70001600, 0x006C),
+ S5K4ECGX_REG_WRITE(0x70001602, 0x0072),
+ S5K4ECGX_REG_WRITE(0x70001604, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70001606, 0x007E),
+ S5K4ECGX_REG_WRITE(0x70001608, 0x0084),
+ S5K4ECGX_REG_WRITE(0x7000160A, 0x008A),
+ S5K4ECGX_REG_WRITE(0x7000160C, 0x0090),
+ S5K4ECGX_REG_WRITE(0x7000160E, 0x0096),
+ S5K4ECGX_REG_WRITE(0x70001610, 0x009C),
+ S5K4ECGX_REG_WRITE(0x70001612, 0x00A2),
+ S5K4ECGX_REG_WRITE(0x70001614, 0x00A8),
+ S5K4ECGX_REG_WRITE(0x70001616, 0x00AE),
+ S5K4ECGX_REG_WRITE(0x70001618, 0x00B4),
+ S5K4ECGX_REG_WRITE(0x7000161A, 0x00BA),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Start) = {
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0005),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_1) = {
+ S5K4ECGX_REG_WRITE(0x7000028E, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_2) = {
+ S5K4ECGX_REG_WRITE(0x7000028C, 0x0004),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Single_AF_Off_3) = {
+
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Face_Detection_On) = {
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0238),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0074),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0132),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Face_Detection_Off) = {
+ S5K4ECGX_REG_WRITE(0x70000294, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70000296, 0x00E3),
+ S5K4ECGX_REG_WRITE(0x70000298, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000029A, 0x0238),
+ S5K4ECGX_REG_WRITE(0x7000029C, 0x01C6),
+ S5K4ECGX_REG_WRITE(0x7000029E, 0x0166),
+ S5K4ECGX_REG_WRITE(0x700002A0, 0x0074),
+ S5K4ECGX_REG_WRITE(0x700002A2, 0x0132),
+ S5K4ECGX_REG_WRITE(0x700002A4, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Low_Cap_On) = {
+ S5K4ECGX_REG_WRITE(0x700006B8, 0xFFFF),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x00FF), /* #lt_uMaxLei */
+
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x4A18), /* #Gamma linearity */
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0850), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000093A, 0x0012), /* #SARR_uNormBrInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x7000093C, 0x0022), /* #SARR_uNormBrInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x7000093E, 0x0384), /* #SARR_uNormBrInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x70000940, 0x07D0), /* #SARR_uNormBrInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x70000942, 0x1388), /* #SARR_uNormBrInDoor_4_ */
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Low_Cap_Off) = {
+ S5K4ECGX_REG_WRITE(0x700006B8, 0x452C),
+ S5K4ECGX_REG_WRITE(0x700006BA, 0x000C), /* #lt_uMaxLei */
+
+ S5K4ECGX_REG_WRITE(0x70000A1A, 0x8F18), /* #Gamma linearity */
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0C00), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000938, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000093A, 0x0014), /* #SARR_uNormBrInDoor_0_ */
+ S5K4ECGX_REG_WRITE(0x7000093C, 0x00D2), /* #SARR_uNormBrInDoor_1_ */
+ S5K4ECGX_REG_WRITE(0x7000093E, 0x0384), /* #SARR_uNormBrInDoor_2_ */
+ S5K4ECGX_REG_WRITE(0x70000940, 0x07D0), /* #SARR_uNormBrInDoor_3_ */
+ S5K4ECGX_REG_WRITE(0x70000942, 0x1388), /* #SARR_uNormBrInDoor_4_ */
+ S5K4ECGX_REGSET_END
+};
+
+ /* restores crop settings to full resolution */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Reset_Crop) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000264, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Capture_Start) = {
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0050),
+
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x0074),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0850), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x70000242, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000244, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Preview_Return) = {
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x70000608, 0x0001), /* #lt_ExpGain_uSubsamplingmode */
+ S5K4ECGX_REG_WRITE(0x7000060A, 0x0001), /* #lt_ExpGain_uNonSubsampling */
+ S5K4ECGX_REG_WRITE(0x7000060C, 0x0C00), /* #lt_ExpGain_ExpCurveGainMaxStr */
+
+ S5K4ECGX_REG_WRITE(0x700005D0, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000972, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000242, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001),
+ S5K4ECGX_REG_WRITE(0x70000244, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_init) = {
+ S5K4ECGX_REG_WRITE(0x70000484, 0x0002), /* capture flash on */
+
+ S5K4ECGX_REG_WRITE(0x7000183A, 0x0001), /* one frame AE */
+
+ S5K4ECGX_REG_WRITE(0x700017F6, 0x0258), /* AWB R point */
+ S5K4ECGX_REG_WRITE(0x700017F8, 0x0248), /* AWB B point */
+
+ S5K4ECGX_REG_WRITE(0x70001840, 0x0001), /* Fls AE tune start */
+
+ S5K4ECGX_REG_WRITE(0x70001842, 0x0100), /* fls_afl_FlsAFIn Rin */
+ S5K4ECGX_REG_WRITE(0x70001844, 0x0120),
+ S5K4ECGX_REG_WRITE(0x70001846, 0x0180),
+ S5K4ECGX_REG_WRITE(0x70001848, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000184A, 0x0400),
+ S5K4ECGX_REG_WRITE(0x7000184C, 0x0800),
+ S5K4ECGX_REG_WRITE(0x7000184E, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70001850, 0x1000),
+
+ S5K4ECGX_REG_WRITE(0x70001852, 0x0100), /* fls_afl_FlsAFOut Rout */
+ S5K4ECGX_REG_WRITE(0x70001854, 0x00A0),
+ S5K4ECGX_REG_WRITE(0x70001856, 0x0090),
+ S5K4ECGX_REG_WRITE(0x70001858, 0x0080),
+ S5K4ECGX_REG_WRITE(0x7000185A, 0x0070),
+ S5K4ECGX_REG_WRITE(0x7000185C, 0x0045),
+ S5K4ECGX_REG_WRITE(0x7000185E, 0x0030),
+ S5K4ECGX_REG_WRITE(0x70001860, 0x0010),
+
+ S5K4ECGX_REG_WRITE(0x70001884, 0x0100), /* fls_afl_FlsNBOut flash NB default */
+ S5K4ECGX_REG_WRITE(0x70001886, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001888, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000188A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000188C, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000188E, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001890, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70001892, 0x0100),
+
+ S5K4ECGX_REG_WRITE(0x70001826, 0x0100), /* fls_afl_FlashWP_Weight flash NB default */
+ S5K4ECGX_REG_WRITE(0x70001828, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x7000182A, 0x0080),
+ S5K4ECGX_REG_WRITE(0x7000182C, 0x000A),
+ S5K4ECGX_REG_WRITE(0x7000182E, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70001830, 0x0030), /* fls_afl_FlashWP_Weight flash NB default */
+ S5K4ECGX_REG_WRITE(0x70001832, 0x0040),
+ S5K4ECGX_REG_WRITE(0x70001834, 0x0048),
+ S5K4ECGX_REG_WRITE(0x70001836, 0x0050),
+ S5K4ECGX_REG_WRITE(0x70001838, 0x0060),
+
+ S5K4ECGX_REG_WRITE(0x70004784, 0x00A0), /* TNP_Regs_FlsWeightRIn weight tune start in */
+ S5K4ECGX_REG_WRITE(0x70004786, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70004788, 0x00D0),
+ S5K4ECGX_REG_WRITE(0x7000478A, 0x0100),
+ S5K4ECGX_REG_WRITE(0x7000478C, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000478E, 0x0300),
+
+ S5K4ECGX_REG_WRITE(0x70004790, 0x0088), /* TNP_Regs_FlsWeightROut weight tune start out */
+ S5K4ECGX_REG_WRITE(0x70004792, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x70004794, 0x00C0),
+ S5K4ECGX_REG_WRITE(0x70004796, 0x0100),
+ S5K4ECGX_REG_WRITE(0x70004798, 0x0200),
+ S5K4ECGX_REG_WRITE(0x7000479A, 0x0300),
+
+ S5K4ECGX_REG_WRITE(0x7000479C, 0x0120), /* Fls BRIn */
+ S5K4ECGX_REG_WRITE(0x7000479E, 0x0150),
+ S5K4ECGX_REG_WRITE(0x700047A0, 0x0200),
+
+ S5K4ECGX_REG_WRITE(0x700047A2, 0x003C), /* Fls BROut */
+ S5K4ECGX_REG_WRITE(0x700047A4, 0x003B),
+ S5K4ECGX_REG_WRITE(0x700047A6, 0x0030),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Pre_Flash_Start) = {
+ S5K4ECGX_REG_WRITE(0x70000588, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x700017FC, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Pre_Flash_End) = {
+ S5K4ECGX_REG_WRITE(0x70000588, 0x0002),
+
+ S5K4ECGX_REG_WRITE(0x70001800, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_Start) = {
+ S5K4ECGX_REG_WRITE(0x700017E8, 0x0001),
+
+ S5K4ECGX_REG_WRITE(0x7000180C, 0x0027),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Flash_End) = {
+ S5K4ECGX_REG_WRITE(0x700017E8, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+/* Capture QSXGA 2560x1920 YUV */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_5M_Capture) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+/* Capture QXGA 2048x1536 YUV */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_3M_Capture) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0800),
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x0600),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+/* Capture UXGA 1600x1200 YUV */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_2M_Capture) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0640),
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x04B4),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+/* Capture SXGA 1280x960 YUV */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_1M_Capture) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0500),
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x03C0),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+/* Capture VGA 640x480 YUV */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_VGA_Capture) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_WRITE(0x70000398, 0x0280),
+ S5K4ECGX_REG_WRITE(0x7000039A, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x70000270, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+ /* 720 x 480 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_720_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x0078),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x06A8),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x02D0),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 640 x 480 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_640_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x0010),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x0010),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0A00),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x0280),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x01E0),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014A),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 352 x 288 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_352_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x007C),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x007C),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x0160),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x0120),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+ /* 176 x 144 */
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_176_Preview) = {
+ S5K4ECGX_REG_WRITE(0x70000250, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000252, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000254, 0x007C),
+ S5K4ECGX_REG_WRITE(0x70000256, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000258, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000025A, 0x0780),
+ S5K4ECGX_REG_WRITE(0x7000025C, 0x007C),
+ S5K4ECGX_REG_WRITE(0x7000025E, 0x000C),
+ S5K4ECGX_REG_WRITE(0x70000494, 0x0928),
+ S5K4ECGX_REG_WRITE(0x70000496, 0x0780),
+ S5K4ECGX_REG_WRITE(0x70000498, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049A, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000049C, 0x0928),
+ S5K4ECGX_REG_WRITE(0x7000049E, 0x0780),
+ S5K4ECGX_REG_WRITE(0x700004A0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700004A2, 0x0000),
+
+ S5K4ECGX_REG_WRITE(0x70000262, 0x0001), /* #REG_TC_GP_bUseReqInputInPre */
+ S5K4ECGX_REG_WRITE(0x70000A1E, 0x0028),
+ S5K4ECGX_REG_WRITE(0x70000AD4, 0x003C),
+
+ S5K4ECGX_REG_WRITE(0x700002A6, 0x00B0),
+ S5K4ECGX_REG_WRITE(0x700002A8, 0x0090),
+ S5K4ECGX_REG_WRITE(0x700002AA, 0x0005),
+ S5K4ECGX_REG_WRITE(0x700002B4, 0x0052),
+ S5K4ECGX_REG_WRITE(0x700002BE, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002C0, 0x0001),
+ S5K4ECGX_REG_WRITE(0x700002C2, 0x029A),
+ S5K4ECGX_REG_WRITE(0x700002C4, 0x014D),
+ S5K4ECGX_REG_WRITE(0x700002D0, 0x0000),
+ S5K4ECGX_REG_WRITE(0x700002D2, 0x0000),
+ S5K4ECGX_REG_WRITE(0x70000266, 0x0000),
+ S5K4ECGX_REG_WRITE(0x7000026A, 0x0001),
+ S5K4ECGX_REG_WRITE(0x7000024E, 0x0001), /* #REG_TC_GP_NewConfigSync */
+ S5K4ECGX_REG_WRITE(0x70000268, 0x0001), /* #REG_TC_GP_CapConfigChanged */
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AE_AWB_Lock_On) = {
+ S5K4ECGX_REG_WRITE(0x70002C5E, 0x0000),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_AE_AWB_Lock_Off) = {
+ S5K4ECGX_REG_WRITE(0x70002C5E, 0x0001),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Get_AE_Stable_Status) = {
+ S5K4ECGX_REG_READ(0x70002C74),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_Get_Light_Level) = {
+ S5K4ECGX_REG_READ(0x70002C18),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_1st_af_search_status) = {
+ S5K4ECGX_REG_READ(0x70002EEE),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_2nd_af_search_status) = {
+ S5K4ECGX_REG_READ(0x70002207),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_capture_status) = {
+ S5K4ECGX_REG_READ(0x70000530),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_esd_status) = {
+ S5K4ECGX_CMD_WRITE(0xFCFC, 0xD000),
+ S5K4ECGX_REG_READ(0xD0000060),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_iso_reg) = {
+ S5K4ECGX_REG_READ(0x70002BC4),
+ S5K4ECGX_REGSET_END
+};
+
+S5K4ECGX_DEFINE_REGSET(s5k4ecgx_get_shutterspeed_reg) = {
+ S5K4ECGX_REG_READ(0x70002BC0),
+ S5K4ECGX_REGSET_END
+};
+
+#undef S5K4ECGX_DEFINE_REGSET
+#undef S5K4ECGX_REGSET_END
+#undef S5K4ECGX_CMD_WRITE
+#undef S5K4ECGX_REG_WRITE
+#undef S5K4ECGX_REG_READ
+#undef S5K4ECGX_MDELAY
+#undef _SWAB16
+#undef _DUMMY
+
+#endif
+
+#if !defined(__S5K4ECGX_V1_1_DEFINE_REGSET__)
+#define __S5K4ECGX_V1_1_DEFINE_REGSET__
+#elif !defined(__S5K4ECGX_V1_1_DEFINE_REGSET_DATA__)
+#define __S5K4ECGX_V1_1_DEFINE_REGSET_DATA__
+#endif
diff --git a/drivers/media/video/s5k4ecgx_regset.h b/drivers/media/video/s5k4ecgx_regset.h
new file mode 100644
index 00000000000..661b8930795
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regset.h
@@ -0,0 +1,33 @@
+/* drivers/media/video/s5k4ecgx_regset.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.1
+ *
+ * Copyright (C) 2012, Insignal Co,. Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __S5K4ECGX_REGSET_H__
+#define __S5K4ECGX_REGSET_H__
+
+enum s5k4ecgx_reg_type {
+ S5K4ECGX_REGTYPE_END = 0,
+ S5K4ECGX_REGTYPE_CMD,
+ S5K4ECGX_REGTYPE_WRITE,
+ S5K4ECGX_REGTYPE_READ,
+ S5K4ECGX_REGTYPE_DELAY,
+};
+
+struct s5k4ecgx_reg {
+ enum s5k4ecgx_reg_type type;
+ int data_len;
+ union {
+ u32 addr;
+ int msec;
+ };
+};
+
+#endif
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
index bd5706a6bad..31a7def32d6 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
@@ -530,6 +530,7 @@ struct s5p_mfc_ctx {
struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
struct v4l2_ctrl_handler ctrl_handler;
+ unsigned int frame_tag;
};
/*
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index c5d567f87d7..1e140f0d105 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -167,6 +167,16 @@ static struct mfc_control controls[] = {
.default_value = 1,
.is_volatile = 1,
},
+ {
+ .id = V4L2_CID_CODEC_FRAME_TAG,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Frame Tag",
+ .minimum = 0,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ .is_volatile = 1,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(controls)
@@ -644,6 +654,9 @@ static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
ctx->slice_interface = ctrl->val;
break;
+ case V4L2_CID_CODEC_FRAME_TAG:
+ ctx->frame_tag = ctrl->val;
+ break;
default:
mfc_err("Invalid control 0x%08x\n", ctrl->id);
return -EINVAL;
@@ -678,6 +691,9 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
break;
+ case V4L2_CID_CODEC_FRAME_TAG:
+ ctrl->val = s5p_mfc_read_shm(ctx, GET_FRAME_TAG_TOP);
+ break;
}
return 0;
}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
index e6217cbfa4a..d3cf95eaec8 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
@@ -1003,6 +1003,8 @@ int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
mfc_write(dev,
((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
| (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+
+
return 0;
}
@@ -1029,6 +1031,8 @@ int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx,
mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
s5p_mfc_set_shared_buffer(ctx);
s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+
+ s5p_mfc_write_shm(ctx, ctx->frame_tag, S5P_FIMV_SHARED_SET_FRAME_TAG);
/* Issue different commands to instance basing on whether it
* is the last frame or not. */
switch (last_frame) {
diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig
index f248b285672..c3d16c82377 100644
--- a/drivers/media/video/s5p-tv/Kconfig
+++ b/drivers/media/video/s5p-tv/Kconfig
@@ -72,6 +72,7 @@ config VIDEO_SAMSUNG_S5P_MIXER
depends on VIDEO_DEV && VIDEO_V4L2
depends on VIDEO_SAMSUNG_S5P_TV
select VIDEOBUF2_DMA_CONTIG
+ select VIDEOBUF2_FB
help
Say Y here if you want support for the Mixer in Samsung S5P SoCs.
This device produce image data to one of output interfaces.
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c
index 20cb6eef297..da1fd549057 100644
--- a/drivers/media/video/s5p-tv/hdmi_drv.c
+++ b/drivers/media/video/s5p-tv/hdmi_drv.c
@@ -42,7 +42,7 @@ MODULE_DESCRIPTION("Samsung HDMI");
MODULE_LICENSE("GPL");
/* default preset configured on probe */
-#define HDMI_DEFAULT_PRESET V4L2_DV_480P59_94
+#define HDMI_DEFAULT_PRESET V4L2_DV_1080P60
struct hdmi_pulse {
u32 beg;
@@ -174,16 +174,175 @@ static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
return IRQ_HANDLED;
}
+/* Audio related changes */
+static void hdmi_set_acr(u32 freq, u8 *acr)
+{
+ u32 n, cts;
+
+ switch (freq) {
+ case 32000:
+ n = 4096;
+ cts = 27000;
+ break;
+ case 44100:
+ n = 6272;
+ cts = 30000;
+ break;
+ case 88200:
+ n = 12544;
+ cts = 30000;
+ break;
+ case 176400:
+ n = 25088;
+ cts = 30000;
+ break;
+ case 48000:
+ n = 6144;
+ cts = 27000;
+ break;
+ case 96000:
+ n = 12288;
+ cts = 27000;
+ break;
+ case 192000:
+ n = 24576;
+ cts = 27000;
+ break;
+ default:
+ n = 0;
+ cts = 0;
+ break;
+ }
+
+ acr[1] = cts >> 16;
+ acr[2] = cts >> 8 & 0xff;
+ acr[3] = cts & 0xff;
+
+ acr[4] = n >> 16;
+ acr[5] = n >> 8 & 0xff;
+ acr[6] = n & 0xff;
+}
+
+static void hdmi_reg_acr(struct hdmi_device *hdev, u8 *acr)
+{
+ hdmi_writeb(hdev, HDMI_ACR_N0, acr[6]);
+ hdmi_writeb(hdev, HDMI_ACR_N1, acr[5]);
+ hdmi_writeb(hdev, HDMI_ACR_N2, acr[4]);
+ hdmi_writeb(hdev, HDMI_ACR_MCTS0, acr[3]);
+ hdmi_writeb(hdev, HDMI_ACR_MCTS1, acr[2]);
+ hdmi_writeb(hdev, HDMI_ACR_MCTS2, acr[1]);
+ hdmi_writeb(hdev, HDMI_ACR_CTS0, acr[3]);
+ hdmi_writeb(hdev, HDMI_ACR_CTS1, acr[2]);
+ hdmi_writeb(hdev, HDMI_ACR_CTS2, acr[1]);
+
+ hdmi_writeb(hdev, HDMI_ACR_CON, 4);
+}
+
+static void hdmi_audio_init(struct hdmi_device *hdev)
+{
+ u32 sample_rate, bits_per_sample, frame_size_code;
+ u32 data_num, bit_ch, sample_frq;
+ u32 val;
+ u8 acr[7];
+
+ sample_rate = 44100;
+ bits_per_sample = 16;
+ frame_size_code = 0;
+
+ switch (bits_per_sample) {
+ case 20:
+ data_num = 2;
+ bit_ch = 1;
+ break;
+ case 24:
+ data_num = 3;
+ bit_ch = 1;
+ break;
+ default:
+ data_num = 1;
+ bit_ch = 0;
+ break;
+ }
+
+ hdmi_set_acr(sample_rate, acr);
+ hdmi_reg_acr(hdev, acr);
+
+ hdmi_writeb(hdev, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
+ | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
+ | HDMI_I2S_MUX_ENABLE);
+
+ hdmi_writeb(hdev, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
+ | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
+
+ hdmi_writeb(hdev, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
+
+ sample_frq = (sample_rate == 44100) ? 0 :
+ (sample_rate == 48000) ? 2 :
+ (sample_rate == 32000) ? 3 :
+ (sample_rate == 96000) ? 0xa : 0x0;
+
+ hdmi_writeb(hdev, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
+ hdmi_writeb(hdev, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
+
+ val = hdmi_read(hdev, HDMI_I2S_DSD_CON) | 0x01;
+ hdmi_writeb(hdev, HDMI_I2S_DSD_CON, val);
+
+ /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
+ hdmi_writeb(hdev, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
+ | HDMI_I2S_SEL_LRCK(6));
+ hdmi_writeb(hdev, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(3)
+ | HDMI_I2S_SEL_SDATA2(4));
+ hdmi_writeb(hdev, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
+ | HDMI_I2S_SEL_SDATA2(2));
+ hdmi_writeb(hdev, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
+
+ /* I2S_CON_1 & 2 */
+ hdmi_writeb(hdev, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
+ | HDMI_I2S_L_CH_LOW_POL);
+ hdmi_writeb(hdev, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
+ | HDMI_I2S_SET_BIT_CH(bit_ch)
+ | HDMI_I2S_SET_SDATA_BIT(data_num)
+ | HDMI_I2S_BASIC_FORMAT);
+
+ /* Configure register related to CUV information */
+ hdmi_writeb(hdev, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
+ | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
+ | HDMI_I2S_COPYRIGHT
+ | HDMI_I2S_LINEAR_PCM
+ | HDMI_I2S_CONSUMER_FORMAT);
+ hdmi_writeb(hdev, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
+ hdmi_writeb(hdev, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
+ hdmi_writeb(hdev, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
+ | HDMI_I2S_SET_SMP_FREQ(sample_frq));
+ hdmi_writeb(hdev, HDMI_I2S_CH_ST_4,
+ HDMI_I2S_ORG_SMP_FREQ_44_1
+ | HDMI_I2S_WORD_LEN_MAX24_24BITS
+ | HDMI_I2S_WORD_LEN_MAX_24BITS);
+
+ hdmi_writeb(hdev, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
+}
+
+static void hdmi_audio_control(struct hdmi_device *hdev, bool onoff)
+{
+ u32 mod;
+
+ mod = hdmi_read(hdev, HDMI_MODE_SEL);
+ if (mod & HDMI_MODE_DVI_EN)
+ return;
+
+ hdmi_writeb(hdev, HDMI_AUI_CON, onoff ? 2 : 0);
+ hdmi_write_mask(hdev, HDMI_CON_0, onoff ?
+ HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
+}
+
static void hdmi_reg_init(struct hdmi_device *hdev)
{
/* enable HPD interrupts */
hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
- /* choose DVI mode */
+ /* choose HDMI mode */
hdmi_write_mask(hdev, HDMI_MODE_SEL,
- HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
- hdmi_write_mask(hdev, HDMI_CON_2, ~0,
- HDMI_DVI_PERAMBLE_EN | HDMI_DVI_BAND_EN);
+ HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
/* disable bluescreen */
hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
/* choose bluescreen (fecal) color */
@@ -280,9 +439,11 @@ static int hdmi_conf_apply(struct hdmi_device *hdmi_dev)
mdelay(10);
hdmi_reg_init(hdmi_dev);
+ hdmi_audio_init(hdmi_dev);
/* setting core registers */
hdmi_timing_apply(hdmi_dev, conf);
+ hdmi_audio_control(hdmi_dev, true);
hdmi_dev->cur_conf_dirty = 0;
@@ -700,8 +861,15 @@ static int hdmi_runtime_suspend(struct device *dev)
struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
dev_dbg(dev, "%s\n", __func__);
+#if 0
+ /*
+ * Currently we are getting a system-hang during soft-reboot and
+ * suspend-resume here. Commenting temporarily to fix that issue.
+ * Also HDMI is not working after resume.
+ */
v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0);
hdmi_resource_poweroff(&hdev->res);
+#endif
/* flag that device context is lost */
hdev->cur_conf_dirty = 1;
return 0;
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h
index ddb422e2355..f5b772eb5e4 100644
--- a/drivers/media/video/s5p-tv/mixer.h
+++ b/drivers/media/video/s5p-tv/mixer.h
@@ -152,6 +152,8 @@ struct mxr_layer_ops {
struct mxr_layer {
/** parent mixer device */
struct mxr_device *mdev;
+ /** frame buffer emulator */
+ void *fb;
/** layer index (unique identifier) */
int idx;
/** callbacks for layer methods */
diff --git a/drivers/media/video/s5p-tv/mixer_reg.c b/drivers/media/video/s5p-tv/mixer_reg.c
index 3b1670a045f..8991c175c91 100644
--- a/drivers/media/video/s5p-tv/mixer_reg.c
+++ b/drivers/media/video/s5p-tv/mixer_reg.c
@@ -115,7 +115,13 @@ void mxr_reg_reset(struct mxr_device *mdev)
/* setting graphical layers */
val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
+#if 0
+ /*
+ * Without this change, the HDMI display in Android had a green tint.
+ * Yet to find the exact reason for the same.
+ */
val |= MXR_GRP_CFG_BLEND_PRE_MUL; /* premul mode */
+#endif
val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
/* the same configuration for both layers */
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index 6c74b05d1f9..351f95584cc 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -15,6 +15,7 @@
#include <media/v4l2-ioctl.h>
#include <linux/videodev2.h>
+#include <media/videobuf2-fb.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/version.h>
@@ -307,6 +308,8 @@ static int mxr_g_fmt(struct file *file, void *priv,
pix->colorspace = layer->fmt->colorspace;
mxr_mplane_fill(pix->plane_fmt, layer->fmt, pix->width, pix->height);
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = f->fmt.pix.width * f->fmt.pix.height * 2;
+
return 0;
}
@@ -1015,11 +1018,18 @@ int mxr_base_layer_register(struct mxr_layer *layer)
else
mxr_info(mdev, "registered layer %s as /dev/video%d\n",
layer->vfd.name, layer->vfd.num);
+
+ layer->fb = vb2_fb_register(&layer->vb_queue, &layer->vfd);
+ if (PTR_ERR(layer->fb))
+ layer->fb = NULL;
+
return ret;
}
void mxr_base_layer_unregister(struct mxr_layer *layer)
{
+ if (layer->fb)
+ vb2_fb_unregister(layer->fb);
video_unregister_device(&layer->vfd);
}
diff --git a/drivers/media/video/s5p-tv/regs-hdmi.h b/drivers/media/video/s5p-tv/regs-hdmi.h
index a889d1f57f2..5d028368120 100644
--- a/drivers/media/video/s5p-tv/regs-hdmi.h
+++ b/drivers/media/video/s5p-tv/regs-hdmi.h
@@ -19,6 +19,7 @@
#define HDMI_CTRL_BASE(x) ((x) + 0x00000000)
#define HDMI_CORE_BASE(x) ((x) + 0x00010000)
+#define HDMI_I2S_BASE(x) ((x) + 0x00040000)
#define HDMI_TG_BASE(x) ((x) + 0x00050000)
/* Control registers */
@@ -73,6 +74,20 @@
#define HDMI_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x05C4)
#define HDMI_HPD_GEN HDMI_CORE_BASE(0x05C8)
+/* Audio related registers */
+#define HDMI_ACR_CON HDMI_CORE_BASE(0x0180)
+#define HDMI_ACR_MCTS0 HDMI_CORE_BASE(0x0184)
+#define HDMI_ACR_MCTS1 HDMI_CORE_BASE(0x0188)
+#define HDMI_ACR_MCTS2 HDMI_CORE_BASE(0x018C)
+#define HDMI_ACR_CTS0 HDMI_CORE_BASE(0x0190)
+#define HDMI_ACR_CTS1 HDMI_CORE_BASE(0x0194)
+#define HDMI_ACR_CTS2 HDMI_CORE_BASE(0x0198)
+#define HDMI_ACR_N0 HDMI_CORE_BASE(0x01A0)
+#define HDMI_ACR_N1 HDMI_CORE_BASE(0x01A4)
+#define HDMI_ACR_N2 HDMI_CORE_BASE(0x01A8)
+
+#define HDMI_AUI_CON HDMI_CORE_BASE(0x0360)
+
/* Timing generator registers */
#define HDMI_TG_CMD HDMI_TG_BASE(0x0000)
#define HDMI_TG_H_FSZ_L HDMI_TG_BASE(0x0018)
@@ -125,6 +140,9 @@
/* HDMI_CON_0 */
#define HDMI_BLUE_SCR_EN (1 << 5)
+#define HDMI_ASP_EN (1 << 2)
+#define HDMI_ASP_DIS (0 << 2)
+#define HDMI_ASP_MASK (1 << 2)
#define HDMI_EN (1 << 0)
/* HDMI_CON_2 */
@@ -139,6 +157,95 @@
#define HDMI_MODE_DVI_EN (1 << 0)
#define HDMI_MODE_MASK (3 << 0)
+/* HDMI I2S register */
+#define HDMI_I2S_CLK_CON HDMI_I2S_BASE(0x000)
+#define HDMI_I2S_CON_1 HDMI_I2S_BASE(0x004)
+#define HDMI_I2S_CON_2 HDMI_I2S_BASE(0x008)
+#define HDMI_I2S_PIN_SEL_0 HDMI_I2S_BASE(0x00c)
+#define HDMI_I2S_PIN_SEL_1 HDMI_I2S_BASE(0x010)
+#define HDMI_I2S_PIN_SEL_2 HDMI_I2S_BASE(0x014)
+#define HDMI_I2S_PIN_SEL_3 HDMI_I2S_BASE(0x018)
+#define HDMI_I2S_DSD_CON HDMI_I2S_BASE(0x01c)
+#define HDMI_I2S_MUX_CON HDMI_I2S_BASE(0x020)
+#define HDMI_I2S_CH_ST_CON HDMI_I2S_BASE(0x024)
+#define HDMI_I2S_CH_ST_0 HDMI_I2S_BASE(0x028)
+#define HDMI_I2S_CH_ST_1 HDMI_I2S_BASE(0x02c)
+#define HDMI_I2S_CH_ST_2 HDMI_I2S_BASE(0x030)
+#define HDMI_I2S_CH_ST_3 HDMI_I2S_BASE(0x034)
+#define HDMI_I2S_CH_ST_4 HDMI_I2S_BASE(0x038)
+#define HDMI_I2S_MUX_CH HDMI_I2S_BASE(0x054)
+#define HDMI_I2S_MUX_CUV HDMI_I2S_BASE(0x058)
+
+/* I2S bit definition */
+
+/* I2S_CLK_CON */
+#define HDMI_I2S_CLK_DIS (0)
+#define HDMI_I2S_CLK_EN (1)
+
+/* I2S_CON_1 */
+#define HDMI_I2S_SCLK_FALLING_EDGE (0 << 1)
+#define HDMI_I2S_L_CH_LOW_POL (0)
+
+/* I2S_CON_2 */
+#define HDMI_I2S_MSB_FIRST_MODE (0 << 6)
+#define HDMI_I2S_BASIC_FORMAT (0)
+#define HDMI_I2S_SET_BIT_CH(x) (((x) & 0x7) << 4)
+#define HDMI_I2S_SET_SDATA_BIT(x) (((x) & 0x7) << 2)
+
+/* I2S_PIN_SEL_0 */
+#define HDMI_I2S_SEL_SCLK(x) (((x) & 0x7) << 4)
+#define HDMI_I2S_SEL_LRCK(x) ((x) & 0x7)
+
+/* I2S_PIN_SEL_1 */
+#define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4)
+#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7)
+
+/* I2S_PIN_SEL_2 */
+#define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4)
+#define HDMI_I2S_SEL_SDATA4(x) ((x) & 0x7)
+
+/* I2S_PIN_SEL_3 */
+#define HDMI_I2S_SEL_DSD(x) ((x) & 0x7)
+
+/* I2S_MUX_CON */
+#define HDMI_I2S_IN_DISABLE (1 << 4)
+#define HDMI_I2S_AUD_I2S (1 << 2)
+#define HDMI_I2S_CUV_I2S_ENABLE (1 << 1)
+#define HDMI_I2S_MUX_ENABLE (1)
+
+/* I2S_CH_ST_CON */
+#define HDMI_I2S_CH_STATUS_RELOAD (1)
+
+/* I2S_CH_ST_0 / I2S_CH_ST_SH_0 */
+#define HDMI_I2S_CH_STATUS_MODE_0 (0 << 6)
+#define HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH (0 << 3)
+#define HDMI_I2S_COPYRIGHT (0 << 2)
+#define HDMI_I2S_LINEAR_PCM (0 << 1)
+#define HDMI_I2S_CONSUMER_FORMAT (0)
+
+/* I2S_CH_ST_1 / I2S_CH_ST_SH_1 */
+#define HDMI_I2S_CD_PLAYER (0x00)
+
+/* I2S_CH_ST_2 / I2S_CH_ST_SH_2 */
+#define HDMI_I2S_SET_SOURCE_NUM(x) ((x) & (0xF))
+
+/* I2S_CH_ST_3 / I2S_CH_ST_SH_3 */
+#define HDMI_I2S_CLK_ACCUR_LEVEL_2 (0 << 4)
+#define HDMI_I2S_SET_SMP_FREQ(x) ((x) & (0xF))
+
+/* I2S_CH_ST_4 / I2S_CH_ST_SH_4 */
+#define HDMI_I2S_ORG_SMP_FREQ_44_1 (0xF << 4)
+#define HDMI_I2S_WORD_LEN_MAX24_24BITS (0x5 << 1)
+#define HDMI_I2S_WORD_LEN_MAX_24BITS (1)
+
+/* I2S_MUX_CH */
+#define HDMI_I2S_CH2_EN (3 << 4)
+#define HDMI_I2S_CH1_EN (3 << 2)
+#define HDMI_I2S_CH0_EN (3)
+
+/* I2S_MUX_CUV */
+#define HDMI_I2S_CUV_RL_EN (0x03)
+
/* HDMI_TG_CMD */
#define HDMI_TG_FIELD_EN (1 << 1)
#define HDMI_TG_EN (1 << 0)
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index b6a2ee71e5c..0d0785bbd32 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -640,6 +640,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size";
case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS";
case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count";
+ case V4L2_CID_CODEC_FRAME_TAG: return "Video Decoder Frame Tag";
/* CAMERA controls */
/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -865,6 +866,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
/* Max is calculated as RGB888 that is 2^24 */
*max = 0xFFFFFF;
break;
+ case V4L2_CID_CODEC_FRAME_TAG:
+ *type = V4L2_CTRL_TYPE_INTEGER;
+ *step = 1;
+ *min = 0;
+ *max = INT_MAX;
+ break;
case V4L2_CID_FLASH_FAULT:
case V4L2_CID_JPEG_ACTIVE_MARKER:
case V4L2_CID_3A_LOCK:
diff --git a/drivers/media/video/videobuf2-fb.c b/drivers/media/video/videobuf2-fb.c
new file mode 100644
index 00000000000..c48e4507679
--- /dev/null
+++ b/drivers/media/video/videobuf2-fb.c
@@ -0,0 +1,565 @@
+/*
+ * videobuf2-fb.c - FrameBuffer API emulator on top of Videobuf2 framework
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Author: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/fb.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-fb.h>
+
+static int debug = 1;
+module_param(debug, int, 0644);
+
+#define dprintk(level, fmt, arg...) \
+ do { \
+ if (debug >= level) \
+ printk(KERN_DEBUG "vb2: " fmt, ## arg); \
+ } while (0)
+
+struct vb2_fb_data {
+ struct video_device *vfd;
+ struct vb2_queue *q;
+ struct device *dev;
+ struct v4l2_requestbuffers req;
+ struct v4l2_buffer b;
+ struct v4l2_plane p;
+ void *vaddr;
+ unsigned int size;
+ int refcount;
+ int blank;
+ int streaming;
+
+ struct file fake_file;
+ struct dentry fake_dentry;
+ struct inode fake_inode;
+};
+
+static int vb2_fb_stop(struct fb_info *info);
+
+struct fmt_desc {
+ __u32 fourcc;
+ __u32 bits_per_pixel;
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+};
+
+static struct fmt_desc fmt_conv_table[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .bits_per_pixel = 16,
+ .red = { .offset = 11, .length = 5, },
+ .green = { .offset = 5, .length = 6, },
+ .blue = { .offset = 0, .length = 5, },
+ }, {
+ .fourcc = V4L2_PIX_FMT_RGB555,
+ .bits_per_pixel = 16,
+ .red = { .offset = 11, .length = 5, },
+ .green = { .offset = 5, .length = 5, },
+ .blue = { .offset = 0, .length = 5, },
+ }, {
+ .fourcc = V4L2_PIX_FMT_RGB444,
+ .bits_per_pixel = 16,
+ .red = { .offset = 8, .length = 4, },
+ .green = { .offset = 4, .length = 4, },
+ .blue = { .offset = 0, .length = 4, },
+ .transp = { .offset = 12, .length = 4, },
+ }, {
+ .fourcc = V4L2_PIX_FMT_BGR32,
+ .bits_per_pixel = 32,
+ .red = { .offset = 16, .length = 4, },
+ .green = { .offset = 8, .length = 8, },
+ .blue = { .offset = 0, .length = 8, },
+ .transp = { .offset = 24, .length = 8, },
+ },
+ /* TODO: add more format descriptors */
+};
+
+/**
+ * vb2_drv_lock() - a shortcut to call driver specific lock()
+ * @q: videobuf2 queue
+ */
+static inline void vb2_drv_lock(struct vb2_queue *q)
+{
+ q->ops->wait_finish(q);
+}
+
+/**
+ * vb2_drv_unlock() - a shortcut to call driver specific unlock()
+ * @q: videobuf2 queue
+ */
+static inline void vb2_drv_unlock(struct vb2_queue *q)
+{
+ q->ops->wait_prepare(q);
+}
+
+/**
+ * vb2_fb_activate() - activate framebuffer emulator
+ * @info: framebuffer vb2 emulator data
+ * This function activates framebuffer emulator. The pixel format
+ * is acquired from video node, memory is allocated and framebuffer
+ * structures are filled with valid data.
+ */
+static int vb2_fb_activate(struct fb_info *info)
+{
+ struct vb2_fb_data *data = info->par;
+ struct vb2_queue *q = data->q;
+ struct fb_var_screeninfo *var;
+ struct v4l2_format fmt;
+ struct fmt_desc *conv = NULL;
+ int width, height, fourcc, bpl, size;
+ int i, ret = 0;
+ int (*g_fmt)(struct file *file, void *fh, struct v4l2_format *f);
+
+ /*
+ * Check if streaming api has not been already activated.
+ */
+ if (q->streaming || q->num_buffers > 0)
+ return -EBUSY;
+
+ dprintk(3, "setting up framebuffer\n");
+
+ /*
+ * Open video node.
+ */
+ ret = data->vfd->fops->open(&data->fake_file);
+ if (ret)
+ return ret;
+
+ /*
+ * Get format from the video node.
+ */
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = q->type;
+ if (data->vfd->ioctl_ops->vidioc_g_fmt_vid_out) {
+ g_fmt = data->vfd->ioctl_ops->vidioc_g_fmt_vid_out;
+ ret = g_fmt(&data->fake_file, data->fake_file.private_data, &fmt);
+ if (ret)
+ goto err;
+ width = fmt.fmt.pix.width;
+ height = fmt.fmt.pix.height;
+ fourcc = fmt.fmt.pix.pixelformat;
+ bpl = fmt.fmt.pix.bytesperline;
+ size = fmt.fmt.pix.sizeimage;
+ } else if (data->vfd->ioctl_ops->vidioc_g_fmt_vid_out_mplane) {
+ g_fmt = data->vfd->ioctl_ops->vidioc_g_fmt_vid_out_mplane;
+ ret = g_fmt(&data->fake_file, data->fake_file.private_data, &fmt);
+ if (ret)
+ goto err;
+ width = fmt.fmt.pix_mp.width;
+ height = fmt.fmt.pix_mp.height;
+ fourcc = fmt.fmt.pix_mp.pixelformat;
+ bpl = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
+ size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
+ } else {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dprintk(3, "fb emu: width %d height %d fourcc %08x size %d bpl %d\n",
+ width, height, fourcc, size, bpl);
+
+ /*
+ * Find format mapping with fourcc returned by g_fmt().
+ */
+ for (i = 0; i < ARRAY_SIZE(fmt_conv_table); i++) {
+ if (fmt_conv_table[i].fourcc == fourcc) {
+ conv = &fmt_conv_table[i];
+ break;
+ }
+ }
+
+ if (conv == NULL) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ /*
+ * Request buffers and use MMAP type to force driver
+ * to allocate buffers by itself.
+ */
+ data->req.count = 1;
+ data->req.memory = V4L2_MEMORY_MMAP;
+ data->req.type = q->type;
+ ret = vb2_reqbufs(q, &data->req);
+ if (ret)
+ goto err;
+
+ /*
+ * Check if plane_count is correct,
+ * multiplane buffers are not supported.
+ */
+ if (q->bufs[0]->num_planes != 1) {
+ data->req.count = 0;
+ ret = -EBUSY;
+ goto err;
+ }
+
+ /*
+ * Get kernel address of the buffer.
+ */
+ data->vaddr = vb2_plane_vaddr(q->bufs[0], 0);
+ if (data->vaddr == NULL) {
+ ret = -EINVAL;
+ goto err;
+ }
+ data->size = size = vb2_plane_size(q->bufs[0], 0);
+
+ /*
+ * Clear the buffer
+ */
+ memset(data->vaddr, 0, size);
+
+ /*
+ * Setup framebuffer parameters
+ */
+ info->screen_base = data->vaddr;
+ info->screen_size = size;
+ info->fix.line_length = bpl;
+ info->fix.smem_len = info->fix.mmio_len = size;
+
+ var = &info->var;
+ var->xres = var->xres_virtual = var->width = width;
+ var->yres = var->yres_virtual = var->height = height;
+ var->bits_per_pixel = conv->bits_per_pixel;
+ var->red = conv->red;
+ var->green = conv->green;
+ var->blue = conv->blue;
+ var->transp = conv->transp;
+
+ return 0;
+
+err:
+ data->vfd->fops->release(&data->fake_file);
+ return ret;
+}
+
+/**
+ * vb2_fb_deactivate() - deactivate framebuffer emulator
+ * @info: framebuffer vb2 emulator data
+ * Stop displaying video data and close framebuffer emulator.
+ */
+static int vb2_fb_deactivate(struct fb_info *info)
+{
+ struct vb2_fb_data *data = info->par;
+
+ info->screen_base = NULL;
+ info->screen_size = 0;
+ data->blank = 1;
+ data->streaming = 0;
+
+ vb2_fb_stop(info);
+ return data->vfd->fops->release(&data->fake_file);
+}
+
+/**
+ * vb2_fb_start() - start displaying the video buffer
+ * @info: framebuffer vb2 emulator data
+ * This function queues video buffer to the driver and starts streaming.
+ */
+static int vb2_fb_start(struct fb_info *info)
+{
+ struct vb2_fb_data *data = info->par;
+ struct v4l2_buffer *b = &data->b;
+ struct v4l2_plane *p = &data->p;
+ struct vb2_queue *q = data->q;
+ int ret;
+
+ if (data->streaming)
+ return 0;
+
+ /*
+ * Prepare the buffer and queue it.
+ */
+ memset(b, 0, sizeof(*b));
+ b->type = q->type;
+ b->memory = q->memory;
+ b->index = 0;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ b->bytesused = data->size;
+ b->length = data->size;
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ memset(p, 0, sizeof(*p));
+ b->m.planes = p;
+ b->length = 1;
+ p->bytesused = data->size;
+ p->length = data->size;
+ }
+ ret = vb2_qbuf(q, b);
+ if (ret)
+ return ret;
+
+ /*
+ * Start streaming.
+ */
+ ret = vb2_streamon(q, q->type);
+ if (ret == 0) {
+ data->streaming = 1;
+ dprintk(3, "fb emu: enabled streaming\n");
+ }
+ return ret;
+}
+
+/**
+ * vb2_fb_start() - stop displaying video buffer
+ * @info: framebuffer vb2 emulator data
+ * This function stops streaming on the video driver.
+ */
+static int vb2_fb_stop(struct fb_info *info)
+{
+ struct vb2_fb_data *data = info->par;
+ struct vb2_queue *q = data->q;
+ int ret = 0;
+
+ if (data->streaming) {
+ ret = vb2_streamoff(q, q->type);
+ data->streaming = 0;
+ dprintk(3, "fb emu: disabled streaming\n");
+ }
+
+ return ret;
+}
+
+/**
+ * vb2_fb_open() - open method for emulated framebuffer
+ * @info: framebuffer vb2 emulator data
+ * @user: client type (0 means kernel, 1 mean userspace)
+ */
+static int vb2_fb_open(struct fb_info *info, int user)
+{
+ struct vb2_fb_data *data = info->par;
+ int ret = 0;
+ dprintk(3, "fb emu: open()\n");
+
+ /*
+ * Reject open() call from fb console.
+ */
+ if (user == 0)
+ return -ENODEV;
+
+ vb2_drv_lock(data->q);
+
+ /*
+ * Activate emulation on the first open.
+ */
+ if (data->refcount == 0)
+ ret = vb2_fb_activate(info);
+
+ if (ret == 0)
+ data->refcount++;
+
+ vb2_drv_unlock(data->q);
+
+ return ret;
+}
+
+/**
+ * vb2_fb_release() - release method for emulated framebuffer
+ * @info: framebuffer vb2 emulator data
+ * @user: client type (0 means kernel, 1 mean userspace)
+ */
+static int vb2_fb_release(struct fb_info *info, int user)
+{
+ struct vb2_fb_data *data = info->par;
+ int ret = 0;
+
+ dprintk(3, "fb emu: release()\n");
+
+ vb2_drv_lock(data->q);
+
+ if (--data->refcount == 0)
+ ret = vb2_fb_deactivate(info);
+
+ vb2_drv_unlock(data->q);
+
+ return ret;
+}
+
+/**
+ * vb2_fb_mmap() - mmap method for emulated framebuffer
+ * @info: framebuffer vb2 emulator data
+ * @vma: memory area to map
+ */
+static int vb2_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct vb2_fb_data *data = info->par;
+ int ret = 0;
+
+ dprintk(3, "fb emu: mmap offset %ld\n", vma->vm_pgoff);
+
+ /*
+ * Add flags required by v4l2/vb2
+ */
+ vma->vm_flags |= VM_SHARED;
+
+ /*
+ * Only the most common case (mapping the whole framebuffer) is
+ * supported for now.
+ */
+ if (vma->vm_pgoff != 0 || (vma->vm_end - vma->vm_start) < data->size)
+ return -EINVAL;
+
+ vb2_drv_lock(data->q);
+ ret = vb2_mmap(data->q, vma);
+ vb2_drv_unlock(data->q);
+
+ return ret;
+}
+
+/**
+ * vb2_fb_blank() - blank method for emulated framebuffer
+ * @blank_mode: requested blank method
+ * @info: framebuffer vb2 emulator data
+ */
+static int vb2_fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct vb2_fb_data *data = info->par;
+ int ret = -EBUSY;
+
+ dprintk(3, "fb emu: blank mode %d, blank %d, streaming %d\n",
+ blank_mode, data->blank, data->streaming);
+
+ /*
+ * If no blank mode change then return immediately
+ */
+ if ((data->blank && blank_mode != FB_BLANK_UNBLANK) ||
+ (!data->blank && blank_mode == FB_BLANK_UNBLANK))
+ return 0;
+
+ /*
+ * Currently blank works only if device has been opened first.
+ */
+ if (!data->refcount)
+ return -EBUSY;
+
+ vb2_drv_lock(data->q);
+
+ /*
+ * Start emulation if user requested mode == FB_BLANK_UNBLANK.
+ */
+ if (blank_mode == FB_BLANK_UNBLANK && data->blank) {
+ ret = vb2_fb_start(info);
+ if (ret == 0)
+ data->blank = 0;
+ }
+
+ /*
+ * Stop emulation if user requested mode != FB_BLANK_UNBLANK.
+ */
+ if (blank_mode != FB_BLANK_UNBLANK && !data->blank) {
+ ret = vb2_fb_stop(info);
+ if (ret == 0)
+ data->blank = 1;
+ }
+
+ vb2_drv_unlock(data->q);
+
+ return ret;
+}
+
+static struct fb_ops vb2_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = vb2_fb_open,
+ .fb_release = vb2_fb_release,
+ .fb_mmap = vb2_fb_mmap,
+ .fb_blank = vb2_fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+/**
+ * vb2_fb_reqister() - register framebuffer emulation
+ * @q: videobuf2 queue
+ * @vfd: video node
+ * This function registers framebuffer emulation for specified
+ * videobuf2 queue and video node. It returns a pointer to the registered
+ * framebuffer device.
+ */
+void *vb2_fb_register(struct vb2_queue *q, struct video_device *vfd)
+{
+ struct vb2_fb_data *data;
+ struct fb_info *info;
+ int ret;
+
+ BUG_ON(q->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ q->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ BUG_ON(!q->mem_ops->vaddr);
+ BUG_ON(!q->ops->wait_prepare || !q->ops->wait_finish);
+ BUG_ON(!vfd->ioctl_ops || !vfd->fops);
+
+ if (!try_module_get(vfd->fops->owner))
+ return ERR_PTR(-ENODEV);
+
+ info = framebuffer_alloc(sizeof(struct vb2_fb_data), &vfd->dev);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ data = info->par;
+
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.accel = FB_ACCEL_NONE;
+ info->fix.visual = FB_VISUAL_TRUECOLOR,
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+ info->fbops = &vb2_fb_ops;
+ info->flags = FBINFO_FLAG_DEFAULT;
+ info->screen_base = NULL;
+
+ ret = register_framebuffer(info);
+ if (ret)
+ return ERR_PTR(ret);
+
+ printk(KERN_INFO "fb%d: registered frame buffer emulation for /dev/%s\n",
+ info->node, dev_name(&vfd->dev));
+
+ data->blank = 1;
+ data->vfd = vfd;
+ data->q = q;
+ data->fake_file.f_path.dentry = &data->fake_dentry;
+ data->fake_dentry.d_inode = &data->fake_inode;
+ data->fake_inode.i_rdev = vfd->cdev->dev;
+
+ return info;
+}
+EXPORT_SYMBOL_GPL(vb2_fb_register);
+
+/**
+ * vb2_fb_unreqister() - unregister framebuffer emulation
+ * @fb_emu: emulated framebuffer device
+ */
+int vb2_fb_unregister(void *fb_emu)
+{
+ struct fb_info *info = fb_emu;
+ struct vb2_fb_data *data = info->par;
+ struct module *owner = data->vfd->fops->owner;
+
+ unregister_framebuffer(info);
+ module_put(owner);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_fb_unregister);
+
+MODULE_DESCRIPTION("FrameBuffer emulator for Videobuf2 and Video for Linux 2");
+MODULE_AUTHOR("Marek Szyprowski");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index f123517065e..abd5c80c7cf 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -21,8 +21,10 @@
* This driver is based on max8998.c
*/
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -47,6 +49,13 @@ static struct mfd_cell max8997_devs[] = {
{ .name = "max8997-led", .id = 2 },
};
+#ifdef CONFIG_OF
+static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
+ { .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
+ {},
+};
+#endif
+
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
{
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
@@ -123,6 +132,58 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
}
EXPORT_SYMBOL_GPL(max8997_update_reg);
+#ifdef CONFIG_OF
+/*
+ * Only the common platform data elements for max8997 are parsed here from the
+ * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
+ * to parse their own platform data elements from device tree.
+ *
+ * The max8997 platform data structure is instantiated here and the drivers for
+ * the sub-modules need not instantiate another instance while parsing their
+ * platform data.
+ */
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+ struct device *dev)
+{
+ struct max8997_platform_data *pd;
+
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ dev_err(dev, "could not allocate memory for pdata\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pd->ono = irq_of_parse_and_map(dev->of_node, 1);
+
+ /*
+ * ToDo: the 'wakeup' member in the platform data is more of a linux
+ * specfic information. Hence, there is no binding for that yet and
+ * not parsed here.
+ */
+
+ return pd;
+}
+#else
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+ struct device *dev)
+{
+ return 0;
+}
+#endif
+
+static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+#ifdef CONFIG_OF
+ if (i2c->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
+ return (int)match->data;
+ }
+#endif
+ return (int)id->driver_data;
+}
+
static int max8997_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -137,12 +198,21 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, max8997);
max8997->dev = &i2c->dev;
max8997->i2c = i2c;
- max8997->type = id->driver_data;
+ max8997->type = max8997_i2c_get_driver_data(i2c, id);
max8997->irq = i2c->irq;
+ if (max8997->dev->of_node) {
+ pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ goto err;
+ }
+ }
+
if (!pdata)
goto err;
+ max8997->pdata = pdata;
max8997->ono = pdata->ono;
mutex_init(&max8997->iolock);
@@ -434,6 +504,7 @@ static struct i2c_driver max8997_i2c_driver = {
.name = "max8997",
.owner = THIS_MODULE,
.pm = &max8997_pm,
+ .of_match_table = of_match_ptr(max8997_pmic_dt_match),
},
.probe = max8997_i2c_probe,
.remove = max8997_i2c_remove,
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 3d8ceb4084d..6c1e63a7211 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -46,7 +46,7 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
return 1;
}
- ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
+ ret = mmc_io_rw_direct_irq(card, &pending);
if (ret) {
pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",
mmc_card_id(card), ret);
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index d29e20630ee..2fcb53e678c 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -111,6 +111,46 @@ static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,
return 0;
}
+static struct mmc_command sdio_intx_cmd = {
+ .opcode = SD_IO_RW_DIRECT,
+ .arg = SDIO_CCCR_INTx << 9,
+ .flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC,
+};
+
+int mmc_io_rw_direct_irq(struct mmc_card *card, u8 *out)
+{
+ int err;
+ struct mmc_host *host ;
+
+ BUG_ON(!card);
+ host = card->host;
+ BUG_ON(!host);
+
+ err = mmc_wait_for_cmd(host, &sdio_intx_cmd, 0);
+ if (err)
+ return err;
+
+ if (mmc_host_is_spi(host)) {
+ /* host driver already reported errors */
+ } else {
+ if (sdio_intx_cmd.resp[0] & R5_ERROR)
+ return -EIO;
+ if (sdio_intx_cmd.resp[0] & R5_FUNCTION_NUMBER)
+ return -EINVAL;
+ if (sdio_intx_cmd.resp[0] & R5_OUT_OF_RANGE)
+ return -ERANGE;
+ }
+
+ if (out) {
+ if (mmc_host_is_spi(host))
+ *out = (sdio_intx_cmd.resp[0] >> 8) & 0xFF;
+ else
+ *out = sdio_intx_cmd.resp[0] & 0xFF;
+ }
+
+ return 0;
+}
+
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8 *out)
{
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index 12a4d3ab174..5fe8ad66745 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -15,6 +15,7 @@
int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8* out);
+int mmc_io_rw_direct_irq(struct mmc_card *card, u8 *out);
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
int sdio_reset(struct mmc_host *host);
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index ef44fae5f3e..4e46bf799b4 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -34,6 +34,9 @@
#define MAX_BUS_CLK (4)
+/* Number of gpio's used is max data bus width + command and clock lines */
+#define NUM_GPIOS(x) (x + 2)
+
/**
* struct sdhci_s3c - S3C SDHCI instance
* @host: The SDHCI host created
@@ -41,6 +44,7 @@
* @ioarea: The resource created when we claimed the IO area.
* @pdata: The platform data for this controller.
* @cur_clk: The index of the current bus clock.
+ * @gpios: List of gpio numbers parsed from device tree.
* @clk_io: The clock for the internal bus interface.
* @clk_bus: The clocks that are available for the SD/MMC bus clock.
*/
@@ -52,6 +56,7 @@ struct sdhci_s3c {
unsigned int cur_clk;
int ext_cd_irq;
int ext_cd_gpio;
+ int *gpios;
struct clk *clk_io;
struct clk *clk_bus[MAX_BUS_CLK];
@@ -419,9 +424,109 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
}
}
+#ifdef CONFIG_OF
+static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+ struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
+{
+ struct device_node *node = dev->of_node;
+ struct sdhci_s3c *ourhost = to_s3c(host);
+ u32 max_width;
+ int gpio, cnt, ret;
+
+ /* if the bus-width property is not specified, assume width as 1 */
+ if (of_property_read_u32(node, "bus-width", &max_width))
+ max_width = 1;
+ pdata->max_width = max_width;
+
+ ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) *
+ sizeof(int), GFP_KERNEL);
+ if (!ourhost->gpios)
+ return -ENOMEM;
+
+ /* get the card detection method */
+ if (of_get_property(node, "samsung,sdhci-cd-internal", NULL))
+ pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
+ else if (of_get_property(node, "samsung,sdhci-cd-gpio", NULL))
+ pdata->cd_type = S3C_SDHCI_CD_GPIO;
+ else if (of_get_property(node, "samsung,sdhci-cd-none", NULL))
+ pdata->cd_type = S3C_SDHCI_CD_NONE;
+ else if (of_get_property(node, "samsung,sdhci-cd-permanent", NULL))
+ pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
+ else
+ pdata->cd_type = S3C_SDHCI_CD_NONE;
+
+ /* get the gpio used for card detection */
+ if (pdata->cd_type == S3C_SDHCI_CD_GPIO ||
+ pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+ gpio = of_get_named_gpio(node, "cd-gpios", 0);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "invalid card detect gpio specified\n");
+ return -EINVAL;
+ }
+ }
+
+ if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
+ pdata->ext_cd_gpio = gpio;
+ ourhost->ext_cd_gpio = -1;
+ if (of_get_property(node, "cd-inverted", NULL))
+ pdata->ext_cd_gpio_invert = 1;
+ } else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+ ret = gpio_request(gpio, "sdhci-cd");
+ if (ret) {
+ dev_err(dev, "card detect gpio request failed\n");
+ return -EINVAL;
+ }
+ ourhost->ext_cd_gpio = gpio;
+ }
+
+ /* get the gpios for command, clock and data lines */
+ for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
+ gpio = of_get_gpio(node, cnt);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "invalid gpio[%d]\n", cnt);
+ goto err_free_dt_cd_gpio;
+ }
+ ourhost->gpios[cnt] = gpio;
+ }
+
+ for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
+ ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio");
+ if (ret) {
+ dev_err(dev, "gpio[%d] request failed\n", cnt);
+ goto err_free_dt_gpios;
+ }
+ }
+
+ return 0;
+
+ err_free_dt_gpios:
+ while (--cnt >= 0)
+ gpio_free(ourhost->gpios[cnt]);
+ err_free_dt_cd_gpio:
+ if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
+ gpio_free(ourhost->ext_cd_gpio);
+ return -EINVAL;
+}
+#else
+static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+ struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
+{
+ return -EINVAL;
+}
+#endif
+
+static const struct of_device_id sdhci_s3c_dt_match[];
+
static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
struct platform_device *pdev)
{
+#ifdef CONFIG_OF
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node);
+ return (struct sdhci_s3c_drv_data *)match->data;
+ }
+#endif
return (struct sdhci_s3c_drv_data *)
platform_get_device_id(pdev)->driver_data;
}
@@ -436,7 +541,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
struct resource *res;
int ret, irq, ptr, clks;
- if (!pdev->dev.platform_data) {
+ if (!pdev->dev.platform_data && !pdev->dev.of_node) {
dev_err(dev, "no device data specified\n");
return -ENOENT;
}
@@ -452,21 +557,28 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
dev_err(dev, "sdhci_alloc_host() failed\n");
return PTR_ERR(host);
}
+ sc = sdhci_priv(host);
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
ret = -ENOMEM;
- goto err_io_clk;
+ goto err_pdata;
+ }
+
+ if (pdev->dev.of_node) {
+ ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
+ if (ret)
+ goto err_pdata;
+ } else {
+ memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+ sc->ext_cd_gpio = -1; /* invalid gpio number */
}
- memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
drv_data = sdhci_s3c_get_driver_data(pdev);
- sc = sdhci_priv(host);
sc->host = host;
sc->pdev = pdev;
sc->pdata = pdata;
- sc->ext_cd_gpio = -1; /* invalid gpio number */
platform_set_drvdata(pdev, host);
@@ -631,6 +743,12 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
clk_put(sc->clk_io);
err_io_clk:
+ for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
+ gpio_free(sc->gpios[ptr]);
+ if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
+ gpio_free(sc->ext_cd_gpio);
+
+ err_pdata:
sdhci_free_host(host);
return ret;
@@ -638,9 +756,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
{
- struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host);
+ struct s3c_sdhci_platdata *pdata = sc->pdata;
int ptr;
if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
@@ -665,6 +783,11 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
clk_disable(sc->clk_io);
clk_put(sc->clk_io);
+ if (pdev->dev.of_node) {
+ for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
+ gpio_free(sc->gpios[ptr]);
+ }
+
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
@@ -737,6 +860,16 @@ static struct platform_device_id sdhci_s3c_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_s3c_dt_match[] = {
+ { .compatible = "samsung,s3c6410-sdhci", },
+ { .compatible = "samsung,exynos4210-sdhci",
+ .data = &exynos4_sdhci_drv_data },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
+#endif
+
static struct platform_driver sdhci_s3c_driver = {
.probe = sdhci_s3c_probe,
.remove = __devexit_p(sdhci_s3c_remove),
@@ -744,6 +877,7 @@ static struct platform_driver sdhci_s3c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "s3c-sdhci",
+ .of_match_table = of_match_ptr(sdhci_s3c_dt_match),
.pm = SDHCI_S3C_PMOPS,
},
};
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index d2b8cc78b6a..c5d12a8f4b2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2767,7 +2767,11 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+#if defined(CONFIG_MACH_ORIGEN) && defined(CONFIG_ATH6KL_POLL)
+ mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
+#else
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
+#endif
if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
host->flags |= SDHCI_AUTO_CMD12;
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index d716b748e57..fc2851e2b7c 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/
obj-$(CONFIG_ATH9K_HW) += ath9k/
obj-$(CONFIG_CARL9170) += carl9170/
obj-$(CONFIG_ATH6KL) += ath6kl/
-
+obj-$(CONFIG_ATH6KL_PLATFORM_DATA) += platform_data.o
obj-$(CONFIG_ATH_COMMON) += ath.o
ath-objs := main.o \
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index d755a5e7ed2..734a6ef3d08 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,3 +30,15 @@ config ATH6KL_DEBUG
depends on ATH6KL
---help---
Enables debug support
+
+config ATH6KL_PLATFORM_DATA
+ bool "Atheros ath6kl Platform data support"
+ depends on ATH6KL
+ ---help---
+ Enables ath6kl platform data
+
+config ATH6KL_POLL
+ bool "Atheros ath6kl Polling support"
+ depends on ATH6KL
+ ---help---
+ Enables workaround for ar6003 hw2.0
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 8cae8886f17..ef3ba6a58da 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -22,22 +22,22 @@
# Author(s): ="Atheros"
#------------------------------------------------------------------------------
-obj-$(CONFIG_ATH6KL) += ath6kl_core.o
-ath6kl_core-y += debug.o
-ath6kl_core-y += hif.o
-ath6kl_core-y += htc_mbox.o
-ath6kl_core-y += htc_pipe.o
-ath6kl_core-y += bmi.o
-ath6kl_core-y += cfg80211.o
-ath6kl_core-y += init.o
-ath6kl_core-y += main.o
-ath6kl_core-y += txrx.o
-ath6kl_core-y += wmi.o
-ath6kl_core-y += core.o
-ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
+obj-$(CONFIG_ATH6KL) += ath6kl.o
+ath6kl-y += debug.o
+ath6kl-y += hif.o
+ath6kl-y += htc_mbox.o
+ath6kl-y += htc_pipe.o
+ath6kl-y += bmi.o
+ath6kl-y += cfg80211.o
+ath6kl-y += init.o
+ath6kl-y += main.o
+ath6kl-y += txrx.o
+ath6kl-y += wmi.o
+ath6kl-y += core.o
+ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
-ath6kl_sdio-y += sdio.o
+ath6kl-y += sdio.o
obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o
ath6kl_usb-y += usb.o
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 05b95405f7b..0a80af3ba10 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -23,6 +23,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sd.h>
+#include <linux/ath6kl.h>
#include "hif.h"
#include "hif-ops.h"
#include "target.h"
@@ -1423,7 +1424,11 @@ static struct sdio_driver ath6kl_sdio_driver = {
static int __init ath6kl_sdio_init(void)
{
int ret;
+ const struct ath6kl_platform_data *wlan_data;
+ wlan_data = ath6kl_get_platform_data();
+ if (!IS_ERR(wlan_data))
+ wlan_data->setup_power(true);
ret = sdio_register_driver(&ath6kl_sdio_driver);
if (ret)
ath6kl_err("sdio driver registration failed: %d\n", ret);
@@ -1433,7 +1438,13 @@ static int __init ath6kl_sdio_init(void)
static void __exit ath6kl_sdio_exit(void)
{
+ const struct ath6kl_platform_data *wlan_data;
+
sdio_unregister_driver(&ath6kl_sdio_driver);
+
+ wlan_data = ath6kl_get_platform_data();
+ if (!IS_ERR(wlan_data))
+ wlan_data->setup_power(false);
}
module_init(ath6kl_sdio_init);
diff --git a/drivers/net/wireless/ath/platform_data.c b/drivers/net/wireless/ath/platform_data.c
new file mode 100644
index 00000000000..dddffe409b0
--- /dev/null
+++ b/drivers/net/wireless/ath/platform_data.c
@@ -0,0 +1,26 @@
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/ath6kl.h>
+
+static const struct ath6kl_platform_data *platform_data;
+
+int __init ath6kl_set_platform_data(const struct ath6kl_platform_data *data)
+{
+ if (platform_data)
+ return -EBUSY;
+ if (!data)
+ return -EINVAL;
+
+ platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!platform_data)
+ return -ENOMEM;
+ return 0;
+}
+
+const struct ath6kl_platform_data *ath6kl_get_platform_data(void)
+{
+ if (!platform_data)
+ return ERR_PTR(-ENODEV);
+ return platform_data;
+}
+EXPORT_SYMBOL(ath6kl_get_platform_data);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 54e3588bef6..34e94c7f68c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -145,6 +145,15 @@ config PINCTRL_COH901
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
ports of 8 GPIO pins each.
+config PINCTRL_SAMSUNG
+ bool "Samsung pinctrl driver"
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_EXYNOS4
+ bool "Pinctrl driver data for Exynos4 SoC"
+ select PINCTRL_SAMSUNG
+
source "drivers/pinctrl/spear/Kconfig"
endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f40b1f81ff2..6a88113e11d 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -29,5 +29,7 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
+obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
+obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o
obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
new file mode 100644
index 00000000000..447818d9851
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -0,0 +1,560 @@
+/*
+ * Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ * http://www.linaro.org
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * 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 file contains the Samsung Exynos specific information required by the
+ * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+ * external gpio and wakeup interrupt support.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include <asm/mach/irq.h>
+
+#include "pinctrl-samsung.h"
+#include "pinctrl-exynos.h"
+
+/* list of external wakeup controllers supported */
+static const struct of_device_id exynos_wkup_irq_ids[] = {
+ { .compatible = "samsung,exynos4210-wakeup-eint", },
+};
+
+static void exynos_gpio_irq_unmask(struct irq_data *irqd)
+{
+ struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+ struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
+ unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+ unsigned long mask;
+
+ mask = readl(d->virt_base + reg_mask);
+ mask &= ~(1 << edata->pin);
+ writel(mask, d->virt_base + reg_mask);
+}
+
+static void exynos_gpio_irq_mask(struct irq_data *irqd)
+{
+ struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+ struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
+ unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+ unsigned long mask;
+
+ mask = readl(d->virt_base + reg_mask);
+ mask |= ~(1 << edata->pin);
+ writel(mask, d->virt_base + reg_mask);
+}
+
+static void exynos_gpio_irq_ack(struct irq_data *irqd)
+{
+ struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+ struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
+ unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
+
+ writel(1 << edata->pin, d->virt_base + reg_pend);
+}
+
+static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+ struct samsung_pin_ctrl *ctrl = d->ctrl;
+ struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
+ unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
+ unsigned int con, trig_type;
+ unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ trig_type = EXYNOS_EINT_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ trig_type = EXYNOS_EINT_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ trig_type = EXYNOS_EINT_EDGE_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ trig_type = EXYNOS_EINT_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ trig_type = EXYNOS_EINT_LEVEL_LOW;
+ break;
+ default:
+ pr_err("unsupported external interrupt type\n");
+ return -EINVAL;
+ }
+
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ __irq_set_handler_locked(irqd->irq, handle_edge_irq);
+ else
+ __irq_set_handler_locked(irqd->irq, handle_level_irq);
+
+ con = readl(d->virt_base + reg_con);
+ con &= ~(EXYNOS_EINT_CON_MASK << shift);
+ con |= trig_type << shift;
+ writel(con, d->virt_base + reg_con);
+ return 0;
+}
+
+/*
+ * irq_chip for gpio interrupts.
+ */
+static struct irq_chip exynos_gpio_irq_chip = {
+ .name = "exynos_gpio_irq_chip",
+ .irq_unmask = exynos_gpio_irq_unmask,
+ .irq_mask = exynos_gpio_irq_mask,
+ .irq_ack = exynos_gpio_irq_ack,
+ .irq_set_type = exynos_gpio_irq_set_type,
+};
+
+/*
+ * given a controller-local external gpio interrupt number, prepare the handler
+ * data for it.
+ */
+static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
+ struct samsung_pinctrl_drv_data *d)
+{
+ struct samsung_pin_bank *bank = d->ctrl->pin_banks;
+ struct exynos_geint_data *eint_data;
+ unsigned int nr_banks = d->ctrl->nr_banks, idx;
+ unsigned int irq_base = 0, eint_offset = 0;
+
+ if (hw >= d->ctrl->nr_gint) {
+ dev_err(d->dev, "unsupported ext-gpio interrupt\n");
+ return NULL;
+ }
+
+ for (idx = 0; idx < nr_banks; idx++, bank++) {
+ if (bank->eint_type != EINT_TYPE_GPIO)
+ continue;
+ if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
+ break;
+ irq_base += bank->nr_pins;
+ eint_offset += 4;
+ }
+
+ if (idx == nr_banks) {
+ dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
+ return NULL;
+ }
+
+ eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
+ if (!eint_data) {
+ dev_err(d->dev, "no memory for eint-gpio data\n");
+ return NULL;
+ }
+
+ eint_data->bank = bank;
+ eint_data->pin = hw - irq_base;
+ eint_data->eint_offset = eint_offset;
+ return eint_data;
+}
+
+static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct samsung_pinctrl_drv_data *d = h->host_data;
+ struct exynos_geint_data *eint_data;
+
+ eint_data = exynos_get_eint_data(hw, d);
+ if (!eint_data)
+ return -EINVAL;
+
+ irq_set_handler_data(virq, eint_data);
+ irq_set_chip_data(virq, h->host_data);
+ irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
+ handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID);
+ return 0;
+}
+
+static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
+{
+ struct samsung_pinctrl_drv_data *d = h->host_data;
+ struct exynos_geint_data *eint_data;
+
+ eint_data = irq_get_handler_data(virq);
+ devm_kfree(d->dev, eint_data);
+}
+
+/*
+ * irq domain callbacks for external gpio interrupt controller.
+ */
+static const struct irq_domain_ops exynos_gpio_irqd_ops = {
+ .map = exynos_gpio_irq_map,
+ .unmap = exynos_gpio_irq_unmap,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
+{
+ struct samsung_pinctrl_drv_data *d = data;
+ struct samsung_pin_ctrl *ctrl = d->ctrl;
+ struct samsung_pin_bank *bank = ctrl->pin_banks;
+ unsigned int svc, group, pin, virq;
+
+ svc = readl(d->virt_base + ctrl->svc);
+ group = EXYNOS_SVC_GROUP(svc);
+ pin = svc & EXYNOS_SVC_NUM_MASK;
+
+ if (!group)
+ return IRQ_HANDLED;
+ bank += (group - 1);
+
+ virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
+ if (!virq)
+ return IRQ_NONE;
+ generic_handle_irq(virq);
+ return IRQ_HANDLED;
+}
+
+/*
+ * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
+{
+ struct device *dev = d->dev;
+ unsigned int ret;
+
+ if (!d->irq) {
+ dev_err(dev, "irq number not available\n");
+ return -EINVAL;
+ }
+
+ ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
+ 0, dev_name(dev), d);
+ if (ret) {
+ dev_err(dev, "irq request failed\n");
+ return -ENXIO;
+ }
+
+ d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
+ &exynos_gpio_irqd_ops, d);
+ if (!d->gpio_irqd) {
+ dev_err(dev, "gpio irq domain allocation failed\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void exynos_wkup_irq_unmask(struct irq_data *irqd)
+{
+ struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+ unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
+ unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
+ unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+ unsigned long mask;
+
+ mask = readl(d->virt_base + reg_mask);
+ mask &= ~(1 << pin);
+ writel(mask, d->virt_base + reg_mask);
+}
+
+static void exynos_wkup_irq_mask(struct irq_data *irqd)
+{
+ struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+ unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
+ unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
+ unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+ unsigned long mask;
+
+ mask = readl(d->virt_base + reg_mask);
+ mask &= ~(1 << pin);
+ writel(mask, d->virt_base + reg_mask);
+}
+
+static void exynos_wkup_irq_ack(struct irq_data *irqd)
+{
+ struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+ unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
+ unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
+ unsigned long pend = d->ctrl->weint_pend + (bank << 2);
+
+ writel(1 << pin, d->virt_base + pend);
+}
+
+static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+ unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
+ unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
+ unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
+ unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
+ unsigned long con, trig_type;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ trig_type = EXYNOS_EINT_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ trig_type = EXYNOS_EINT_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ trig_type = EXYNOS_EINT_EDGE_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ trig_type = EXYNOS_EINT_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ trig_type = EXYNOS_EINT_LEVEL_LOW;
+ break;
+ default:
+ pr_err("unsupported external interrupt type\n");
+ return -EINVAL;
+ }
+
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ __irq_set_handler_locked(irqd->irq, handle_edge_irq);
+ else
+ __irq_set_handler_locked(irqd->irq, handle_level_irq);
+
+ con = readl(d->virt_base + reg_con);
+ con &= ~(EXYNOS_EINT_CON_MASK << shift);
+ con |= trig_type << shift;
+ writel(con, d->virt_base + reg_con);
+ return 0;
+}
+
+/*
+ * irq_chip for wakeup interrupts
+ */
+static struct irq_chip exynos_wkup_irq_chip = {
+ .name = "exynos_wkup_irq_chip",
+ .irq_unmask = exynos_wkup_irq_unmask,
+ .irq_mask = exynos_wkup_irq_mask,
+ .irq_ack = exynos_wkup_irq_ack,
+ .irq_set_type = exynos_wkup_irq_set_type,
+};
+
+/* interrupt handler for wakeup interrupts 0..15 */
+static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+{
+ struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_get_chip(irq);
+ int eint_irq;
+
+ chained_irq_enter(chip, desc);
+ chip->irq_mask(&desc->irq_data);
+
+ if (chip->irq_ack)
+ chip->irq_ack(&desc->irq_data);
+
+ eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
+ generic_handle_irq(eint_irq);
+ chip->irq_unmask(&desc->irq_data);
+ chained_irq_exit(chip, desc);
+}
+
+static void exynos_irq_demux_eint(int irq_base, unsigned long pend,
+ struct irq_domain *domain)
+{
+ unsigned int irq;
+
+ while (pend) {
+ irq = fls(pend) - 1;
+ generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
+ pend &= ~(1 << irq);
+ }
+}
+
+/* interrupt handler for wakeup interrupt 16 */
+static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_get_chip(irq);
+ struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+ struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
+ unsigned long pend;
+
+ chained_irq_enter(chip, desc);
+ pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
+ exynos_irq_demux_eint(16, pend, eintd->domain);
+ pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
+ exynos_irq_demux_eint(24, pend, eintd->domain);
+ chained_irq_exit(chip, desc);
+}
+
+static int exynos_wkup_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip, handle_level_irq);
+ irq_set_chip_data(virq, h->host_data);
+ set_irq_flags(virq, IRQF_VALID);
+ return 0;
+}
+
+/*
+ * irq domain callbacks for external wakeup interrupt controller.
+ */
+static const struct irq_domain_ops exynos_wkup_irqd_ops = {
+ .map = exynos_wkup_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+/*
+ * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
+{
+ struct device *dev = d->dev;
+ struct device_node *wkup_np;
+ struct exynos_weint_data *weint_data;
+ int idx, irq;
+
+ wkup_np = of_find_matching_node(dev->of_node, exynos_wkup_irq_ids);
+ if (!wkup_np) {
+ dev_err(dev, "wakeup controller node not found\n");
+ return -ENODEV;
+ }
+
+ d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
+ &exynos_wkup_irqd_ops, d);
+ if (!d->gpio_irqd) {
+ dev_err(dev, "wakeup irq domain allocation failed\n");
+ return -ENXIO;
+ }
+
+ weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
+ if (!weint_data) {
+ dev_err(dev, "could not allocate memory for weint_data\n");
+ return -ENOMEM;
+ }
+
+ irq = irq_of_parse_and_map(wkup_np, 16);
+ if (irq) {
+ weint_data[16].domain = d->wkup_irqd;
+ irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
+ irq_set_handler_data(irq, &weint_data[16]);
+ } else {
+ dev_err(dev, "irq number for EINT16-32 not found\n");
+ }
+
+ for (idx = 0; idx < 16; idx++) {
+ weint_data[idx].domain = d->wkup_irqd;
+ weint_data[idx].irq = idx;
+
+ irq = irq_of_parse_and_map(wkup_np, idx);
+ if (irq) {
+ irq_set_handler_data(irq, &weint_data[idx]);
+ irq_set_chained_handler(irq, exynos_irq_eint0_15);
+ } else {
+ dev_err(dev, "irq number for eint-%x not found\n", idx);
+ }
+ }
+ return 0;
+}
+
+/* pin banks of exynos4210 pin-controller 0 */
+static struct samsung_pin_bank exynos4210_pin_banks0[] = {
+ EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"),
+ EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"),
+ EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"),
+ EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"),
+ EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"),
+ EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"),
+ EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"),
+ EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"),
+ EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"),
+ EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"),
+ EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"),
+ EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"),
+ EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"),
+ EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"),
+ EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"),
+ EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"),
+};
+
+/* pin banks of exynos4210 pin-controller 1 */
+static struct samsung_pin_bank exynos4210_pin_banks1[] = {
+ EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"),
+ EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"),
+ EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"),
+ EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"),
+ EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"),
+ EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"),
+ EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"),
+ EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"),
+ EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"),
+ EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"),
+ EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"),
+ EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"),
+ EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"),
+ EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"),
+ EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"),
+ EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"),
+ EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"),
+ EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"),
+ EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"),
+ EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"),
+};
+
+/* pin banks of exynos4210 pin-controller 2 */
+static struct samsung_pin_bank exynos4210_pin_banks2[] = {
+ EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes
+ * three gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
+ {
+ /* pin-controller instance 0 data */
+ .pin_banks = exynos4210_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos4210_pin_banks0),
+ .base = EXYNOS4210_GPIO_A0_START,
+ .nr_pins = EXYNOS4210_GPIOA_NR_PINS,
+ .nr_gint = EXYNOS4210_GPIOA_NR_GINT,
+ .geint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+ .svc = EXYNOS_SVC_OFFSET,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .label = "exynos4210-gpio-ctrl0",
+ }, {
+ /* pin-controller instance 1 data */
+ .pin_banks = exynos4210_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1),
+ .base = EXYNOS4210_GPIOA_NR_PINS,
+ .nr_pins = EXYNOS4210_GPIOB_NR_PINS,
+ .nr_gint = EXYNOS4210_GPIOB_NR_GINT,
+ .nr_wint = 32,
+ .geint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+ .weint_con = EXYNOS_WKUP_ECON_OFFSET,
+ .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
+ .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
+ .svc = EXYNOS_SVC_OFFSET,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .label = "exynos4210-gpio-ctrl1",
+ }, {
+ /* pin-controller instance 2 data */
+ .pin_banks = exynos4210_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos4210_pin_banks2),
+ .base = EXYNOS4210_GPIOA_NR_PINS +
+ EXYNOS4210_GPIOB_NR_PINS,
+ .nr_pins = EXYNOS4210_GPIOC_NR_PINS,
+ .label = "exynos4210-gpio-ctrl2",
+ },
+};
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
new file mode 100644
index 00000000000..5f27ba974a3
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -0,0 +1,217 @@
+/*
+ * Exynos specific definitions for Samsung pinctrl and gpiolib driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ * http://www.linaro.org
+ *
+ * This file contains the Exynos specific definitions for the Samsung
+ * pinctrl/gpiolib interface drivers.
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * 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.
+ */
+
+#define EXYNOS_GPIO_START(__gpio) ((__gpio##_START) + (__gpio##_NR))
+
+#define EXYNOS4210_GPIO_A0_NR (8)
+#define EXYNOS4210_GPIO_A1_NR (6)
+#define EXYNOS4210_GPIO_B_NR (8)
+#define EXYNOS4210_GPIO_C0_NR (5)
+#define EXYNOS4210_GPIO_C1_NR (5)
+#define EXYNOS4210_GPIO_D0_NR (4)
+#define EXYNOS4210_GPIO_D1_NR (4)
+#define EXYNOS4210_GPIO_E0_NR (5)
+#define EXYNOS4210_GPIO_E1_NR (8)
+#define EXYNOS4210_GPIO_E2_NR (6)
+#define EXYNOS4210_GPIO_E3_NR (8)
+#define EXYNOS4210_GPIO_E4_NR (8)
+#define EXYNOS4210_GPIO_F0_NR (8)
+#define EXYNOS4210_GPIO_F1_NR (8)
+#define EXYNOS4210_GPIO_F2_NR (8)
+#define EXYNOS4210_GPIO_F3_NR (6)
+#define EXYNOS4210_GPIO_J0_NR (8)
+#define EXYNOS4210_GPIO_J1_NR (5)
+#define EXYNOS4210_GPIO_K0_NR (7)
+#define EXYNOS4210_GPIO_K1_NR (7)
+#define EXYNOS4210_GPIO_K2_NR (7)
+#define EXYNOS4210_GPIO_K3_NR (7)
+#define EXYNOS4210_GPIO_L0_NR (8)
+#define EXYNOS4210_GPIO_L1_NR (3)
+#define EXYNOS4210_GPIO_L2_NR (8)
+#define EXYNOS4210_GPIO_Y0_NR (6)
+#define EXYNOS4210_GPIO_Y1_NR (4)
+#define EXYNOS4210_GPIO_Y2_NR (6)
+#define EXYNOS4210_GPIO_Y3_NR (8)
+#define EXYNOS4210_GPIO_Y4_NR (8)
+#define EXYNOS4210_GPIO_Y5_NR (8)
+#define EXYNOS4210_GPIO_Y6_NR (8)
+#define EXYNOS4210_GPIO_X0_NR (8)
+#define EXYNOS4210_GPIO_X1_NR (8)
+#define EXYNOS4210_GPIO_X2_NR (8)
+#define EXYNOS4210_GPIO_X3_NR (8)
+#define EXYNOS4210_GPIO_Z_NR (7)
+
+enum exynos4210_gpio_xa_start {
+ EXYNOS4210_GPIO_A0_START = 0,
+ EXYNOS4210_GPIO_A1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0),
+ EXYNOS4210_GPIO_B_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1),
+ EXYNOS4210_GPIO_C0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_B),
+ EXYNOS4210_GPIO_C1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0),
+ EXYNOS4210_GPIO_D0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1),
+ EXYNOS4210_GPIO_D1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0),
+ EXYNOS4210_GPIO_E0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1),
+ EXYNOS4210_GPIO_E1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0),
+ EXYNOS4210_GPIO_E2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1),
+ EXYNOS4210_GPIO_E3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2),
+ EXYNOS4210_GPIO_E4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3),
+ EXYNOS4210_GPIO_F0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4),
+ EXYNOS4210_GPIO_F1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0),
+ EXYNOS4210_GPIO_F2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1),
+ EXYNOS4210_GPIO_F3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2),
+};
+
+enum exynos4210_gpio_xb_start {
+ EXYNOS4210_GPIO_J0_START = 0,
+ EXYNOS4210_GPIO_J1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0),
+ EXYNOS4210_GPIO_K0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1),
+ EXYNOS4210_GPIO_K1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0),
+ EXYNOS4210_GPIO_K2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1),
+ EXYNOS4210_GPIO_K3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2),
+ EXYNOS4210_GPIO_L0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3),
+ EXYNOS4210_GPIO_L1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0),
+ EXYNOS4210_GPIO_L2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1),
+ EXYNOS4210_GPIO_Y0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2),
+ EXYNOS4210_GPIO_Y1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0),
+ EXYNOS4210_GPIO_Y2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1),
+ EXYNOS4210_GPIO_Y3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2),
+ EXYNOS4210_GPIO_Y4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3),
+ EXYNOS4210_GPIO_Y5_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4),
+ EXYNOS4210_GPIO_Y6_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5),
+ EXYNOS4210_GPIO_X0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6),
+ EXYNOS4210_GPIO_X1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0),
+ EXYNOS4210_GPIO_X2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1),
+ EXYNOS4210_GPIO_X3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2),
+};
+
+enum exynos4210_gpio_xc_start {
+ EXYNOS4210_GPIO_Z_START = 0,
+};
+
+#define EXYNOS4210_GPIO_A0_IRQ EXYNOS4210_GPIO_A0_START
+#define EXYNOS4210_GPIO_A1_IRQ EXYNOS4210_GPIO_A1_START
+#define EXYNOS4210_GPIO_B_IRQ EXYNOS4210_GPIO_B_START
+#define EXYNOS4210_GPIO_C0_IRQ EXYNOS4210_GPIO_C0_START
+#define EXYNOS4210_GPIO_C1_IRQ EXYNOS4210_GPIO_C1_START
+#define EXYNOS4210_GPIO_D0_IRQ EXYNOS4210_GPIO_D0_START
+#define EXYNOS4210_GPIO_D1_IRQ EXYNOS4210_GPIO_D1_START
+#define EXYNOS4210_GPIO_E0_IRQ EXYNOS4210_GPIO_E0_START
+#define EXYNOS4210_GPIO_E1_IRQ EXYNOS4210_GPIO_E1_START
+#define EXYNOS4210_GPIO_E2_IRQ EXYNOS4210_GPIO_E2_START
+#define EXYNOS4210_GPIO_E3_IRQ EXYNOS4210_GPIO_E3_START
+#define EXYNOS4210_GPIO_E4_IRQ EXYNOS4210_GPIO_E4_START
+#define EXYNOS4210_GPIO_F0_IRQ EXYNOS4210_GPIO_F0_START
+#define EXYNOS4210_GPIO_F1_IRQ EXYNOS4210_GPIO_F1_START
+#define EXYNOS4210_GPIO_F2_IRQ EXYNOS4210_GPIO_F2_START
+#define EXYNOS4210_GPIO_F3_IRQ EXYNOS4210_GPIO_F3_START
+#define EXYNOS4210_GPIO_J0_IRQ EXYNOS4210_GPIO_J0_START
+#define EXYNOS4210_GPIO_J1_IRQ EXYNOS4210_GPIO_J1_START
+#define EXYNOS4210_GPIO_K0_IRQ EXYNOS4210_GPIO_K0_START
+#define EXYNOS4210_GPIO_K1_IRQ EXYNOS4210_GPIO_K1_START
+#define EXYNOS4210_GPIO_K2_IRQ EXYNOS4210_GPIO_K2_START
+#define EXYNOS4210_GPIO_K3_IRQ EXYNOS4210_GPIO_K3_START
+#define EXYNOS4210_GPIO_L0_IRQ EXYNOS4210_GPIO_L0_START
+#define EXYNOS4210_GPIO_L1_IRQ EXYNOS4210_GPIO_L1_START
+#define EXYNOS4210_GPIO_L2_IRQ EXYNOS4210_GPIO_L2_START
+#define EXYNOS4210_GPIO_Z_IRQ EXYNOS4210_GPIO_Z_START
+
+#define EXYNOS4210_GPIOA_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
+#define EXYNOS4210_GPIOA_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
+#define EXYNOS4210_GPIOB_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
+#define EXYNOS4210_GPIOB_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
+#define EXYNOS4210_GPIOC_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
+
+/* External GPIO and wakeup interrupt related definitions */
+#define EXYNOS_GPIO_ECON_OFFSET 0x700
+#define EXYNOS_GPIO_EMASK_OFFSET 0x900
+#define EXYNOS_GPIO_EPEND_OFFSET 0xA00
+#define EXYNOS_WKUP_ECON_OFFSET 0xE00
+#define EXYNOS_WKUP_EMASK_OFFSET 0xF00
+#define EXYNOS_WKUP_EPEND_OFFSET 0xF40
+#define EXYNOS_SVC_OFFSET 0xB08
+
+/* helpers to access interrupt service register */
+#define EXYNOS_SVC_GROUP_SHIFT 3
+#define EXYNOS_SVC_GROUP_MASK 0x1f
+#define EXYNOS_SVC_NUM_MASK 7
+#define EXYNOS_SVC_GROUP(x) ((x >> EXYNOS_SVC_GROUP_SHIFT) & \
+ EXYNOS_SVC_GROUP_MASK)
+
+/* Exynos specific external interrupt trigger types */
+#define EXYNOS_EINT_LEVEL_LOW 0
+#define EXYNOS_EINT_LEVEL_HIGH 1
+#define EXYNOS_EINT_EDGE_FALLING 2
+#define EXYNOS_EINT_EDGE_RISING 3
+#define EXYNOS_EINT_EDGE_BOTH 4
+#define EXYNOS_EINT_CON_MASK 0xF
+#define EXYNOS_EINT_CON_LEN 4
+
+#define EXYNOS_EINT_MAX_PER_BANK 8
+#define EXYNOS_EINT_NR_WKUP_EINT
+
+#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id) \
+ { \
+ .pctl_offset = reg, \
+ .pin_base = (__gpio##_START), \
+ .nr_pins = (__gpio##_NR), \
+ .func_width = 4, \
+ .pud_width = 2, \
+ .drv_width = 2, \
+ .conpdn_width = 2, \
+ .pudpdn_width = 2, \
+ .eint_type = EINT_TYPE_NONE, \
+ .name = id \
+ }
+
+#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id) \
+ { \
+ .pctl_offset = reg, \
+ .pin_base = (__gpio##_START), \
+ .nr_pins = (__gpio##_NR), \
+ .func_width = 4, \
+ .pud_width = 2, \
+ .drv_width = 2, \
+ .conpdn_width = 2, \
+ .pudpdn_width = 2, \
+ .eint_type = EINT_TYPE_GPIO, \
+ .irq_base = (__gpio##_IRQ), \
+ .name = id \
+ }
+
+/**
+ * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
+ * @bank: pin bank from which this gpio interrupt originates.
+ * @pin: pin number within the bank.
+ * @eint_offset: offset to be added to the con/pend/mask register bank base.
+ */
+struct exynos_geint_data {
+ struct samsung_pin_bank *bank;
+ u32 pin;
+ u32 eint_offset;
+};
+
+/**
+ * struct exynos_weint_data: irq specific data for all the wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @domain: irq domain representing the external wakeup interrupts
+ * @irq: interrupt number within the domain.
+ */
+struct exynos_weint_data {
+ struct irq_domain *domain;
+ u32 irq;
+};
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
new file mode 100644
index 00000000000..8a24223d533
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -0,0 +1,888 @@
+/*
+ * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ * http://www.linaro.org
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * 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 driver implements the Samsung pinctrl driver. It supports setting up of
+ * pinmux and pinconf configurations. The gpiolib interface is also included.
+ * External interrupt (gpio and wakeup) support are not included in this driver
+ * but provides extensions to which platform specific implementation of the gpio
+ * and wakeup interrupts can be hooked to.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+
+#include "core.h"
+#include "pinctrl-samsung.h"
+
+#define GROUP_SUFFIX "-grp"
+#define GSUFFIX_LEN sizeof(GROUP_SUFFIX)
+#define FUNCTION_SUFFIX "-mux"
+#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX)
+
+/* list of all possible config options supported */
+struct pin_config {
+ char *prop_cfg;
+ unsigned int cfg_type;
+} pcfgs[] = {
+ { "samsung,pin-pud", PINCFG_TYPE_PUD },
+ { "samsung,pin-drv", PINCFG_TYPE_DRV },
+ { "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN },
+ { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
+};
+
+/* check if the selector is a valid pin group selector */
+static int samsung_get_group_count(struct pinctrl_dev *pctldev)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ return drvdata->nr_groups;
+}
+
+/* return the name of the group selected by the group selector */
+static const char *samsung_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ return drvdata->pin_groups[selector].name;
+}
+
+/* return the pin numbers associated with the specified group */
+static int samsung_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned selector, const unsigned **pins, unsigned *num_pins)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ *pins = drvdata->pin_groups[selector].pins;
+ *num_pins = drvdata->pin_groups[selector].num_pins;
+ return 0;
+}
+
+/* create pinctrl_map entries by parsing device tree nodes */
+static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np, struct pinctrl_map **maps,
+ unsigned *nmaps)
+{
+ struct device *dev = pctldev->dev;
+ struct pinctrl_map *map;
+ unsigned long *cfg = NULL;
+ char *gname, *fname;
+ int cfg_cnt = 0, map_cnt = 0, idx = 0;
+
+ /* count the number of config options specfied in the node */
+ for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
+ if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
+ cfg_cnt++;
+ }
+
+ /*
+ * Find out the number of map entries to create. All the config options
+ * can be accomadated into a single config map entry.
+ */
+ if (cfg_cnt)
+ map_cnt = 1;
+ if (of_find_property(np, "samsung,pin-function", NULL))
+ map_cnt++;
+ if (!map_cnt) {
+ dev_err(dev, "node %s does not have either config or function "
+ "configurations\n", np->name);
+ return -EINVAL;
+ }
+
+ /* Allocate memory for pin-map entries */
+ map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
+ if (!map) {
+ dev_err(dev, "could not alloc memory for pin-maps\n");
+ return -ENOMEM;
+ }
+ *nmaps = 0;
+
+ /*
+ * Allocate memory for pin group name. The pin group name is derived
+ * from the node name from which these map entries are be created.
+ */
+ gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
+ if (!gname) {
+ dev_err(dev, "failed to alloc memory for group name\n");
+ goto free_map;
+ }
+ sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
+
+ /*
+ * don't have config options? then skip over to creating function
+ * map entries.
+ */
+ if (!cfg_cnt)
+ goto skip_cfgs;
+
+ /* Allocate memory for config entries */
+ cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
+ if (!cfg) {
+ dev_err(dev, "failed to alloc memory for configs\n");
+ goto free_gname;
+ }
+
+ /* Prepare a list of config settings */
+ for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
+ u32 value;
+ if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
+ cfg[cfg_cnt++] =
+ PINCFG_PACK(pcfgs[idx].cfg_type, value);
+ }
+
+ /* create the config map entry */
+ map[*nmaps].data.configs.group_or_pin = gname;
+ map[*nmaps].data.configs.configs = cfg;
+ map[*nmaps].data.configs.num_configs = cfg_cnt;
+ map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ *nmaps += 1;
+
+skip_cfgs:
+ /* create the function map entry */
+ if (of_find_property(np, "samsung,pin-function", NULL)) {
+ fname = kzalloc(strlen(np->name) + FSUFFIX_LEN, GFP_KERNEL);
+ if (!fname) {
+ dev_err(dev, "failed to alloc memory for func name\n");
+ goto free_cfg;
+ }
+ sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
+
+ map[*nmaps].data.mux.group = gname;
+ map[*nmaps].data.mux.function = fname;
+ map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+ *nmaps += 1;
+ }
+
+ *maps = map;
+ return 0;
+
+free_cfg:
+ kfree(cfg);
+free_gname:
+ kfree(gname);
+free_map:
+ kfree(map);
+ return -ENOMEM;
+}
+
+/* free the memory allocated to hold the pin-map table */
+static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ int idx;
+
+ for (idx = 0; idx < num_maps; idx++) {
+ if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
+ kfree(map[idx].data.mux.function);
+ if (!idx)
+ kfree(map[idx].data.mux.group);
+ } else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
+ kfree(map[idx].data.configs.configs);
+ if (!idx)
+ kfree(map[idx].data.configs.group_or_pin);
+ }
+ };
+
+ kfree(map);
+}
+
+/* list of pinctrl callbacks for the pinctrl core */
+static struct pinctrl_ops samsung_pctrl_ops = {
+ .get_groups_count = samsung_get_group_count,
+ .get_group_name = samsung_get_group_name,
+ .get_group_pins = samsung_get_group_pins,
+ .dt_node_to_map = samsung_dt_node_to_map,
+ .dt_free_map = samsung_dt_free_map,
+};
+
+/* check if the selector is a valid pin function selector */
+static int samsung_get_functions_count(struct pinctrl_dev *pctldev)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ return drvdata->nr_functions;
+}
+
+/* return the name of the pin function specified */
+static const char *samsung_pinmux_get_fname(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ return drvdata->pmx_functions[selector].name;
+}
+
+/* return the groups associated for the specified function selector */
+static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
+ unsigned selector, const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ *groups = drvdata->pmx_functions[selector].groups;
+ *num_groups = drvdata->pmx_functions[selector].num_groups;
+ return 0;
+}
+
+/*
+ * given a pin number that is local to a pin controller, find out the pin bank
+ * and the register base of the pin bank.
+ */
+static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin,
+ void __iomem **reg, u32 *offset,
+ struct samsung_pin_bank **bank)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+ struct samsung_pin_bank *b;
+
+ drvdata = dev_get_drvdata(gc->dev);
+ b = drvdata->ctrl->pin_banks;
+
+ while ((pin >= b->pin_base) &&
+ ((b->pin_base + b->nr_pins - 1) < pin))
+ b++;
+
+ *reg = drvdata->virt_base + b->pctl_offset;
+ *offset = pin - b->pin_base;
+ if (bank)
+ *bank = b;
+
+ /* some banks have two config registers in a single bank */
+ if (*offset * b->func_width > BITS_PER_LONG)
+ *reg += 4;
+}
+
+/* enable or disable a pinmux function */
+static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group, bool enable)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+ const unsigned int *pins;
+ struct samsung_pin_bank *bank;
+ void __iomem *reg;
+ u32 mask, shift, data, pin_offset, cnt;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ pins = drvdata->pin_groups[group].pins;
+
+ /*
+ * for each pin in the pin group selected, program the correspoding pin
+ * pin function number in the config register.
+ */
+ for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
+ pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base,
+ &reg, &pin_offset, &bank);
+ mask = (1 << bank->func_width) - 1;
+ shift = pin_offset * bank->func_width;
+
+ data = readl(reg);
+ data &= ~(mask << shift);
+ if (enable)
+ data |= drvdata->pin_groups[group].func << shift;
+ writel(data, reg);
+ }
+}
+
+/* enable a specified pinmux by writing to registers */
+static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ samsung_pinmux_setup(pctldev, selector, group, true);
+ return 0;
+}
+
+/* disable a specified pinmux by writing to registers */
+static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
+ unsigned selector, unsigned group)
+{
+ samsung_pinmux_setup(pctldev, selector, group, false);
+}
+
+/*
+ * The calls to gpio_direction_output() and gpio_direction_input()
+ * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
+ * function called from the gpiolib interface).
+ */
+static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+ struct samsung_pin_bank *bank;
+ void __iomem *reg;
+ u32 data, pin_offset, mask, shift;
+
+ pin_to_reg_bank(range->gc, offset, &reg, &pin_offset, &bank);
+ mask = (1 << bank->func_width) - 1;
+ shift = pin_offset * bank->func_width;
+
+ data = readl(reg);
+ data &= ~(mask << shift);
+ if (!input)
+ data |= FUNC_OUTPUT << shift;
+ writel(data, reg);
+ return 0;
+}
+
+/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
+static struct pinmux_ops samsung_pinmux_ops = {
+ .get_functions_count = samsung_get_functions_count,
+ .get_function_name = samsung_pinmux_get_fname,
+ .get_function_groups = samsung_pinmux_get_groups,
+ .enable = samsung_pinmux_enable,
+ .disable = samsung_pinmux_disable,
+ .gpio_set_direction = samsung_pinmux_gpio_set_direction,
+};
+
+/* set or get the pin config settings for a specified pin */
+static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *config, bool set)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+ struct samsung_pin_bank *bank;
+ void __iomem *reg_base;
+ enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
+ u32 data, width, pin_offset, mask, shift;
+ u32 cfg_value, cfg_reg;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, &reg_base,
+ &pin_offset, &bank);
+
+ switch (cfg_type) {
+ case PINCFG_TYPE_PUD:
+ width = bank->pud_width;
+ cfg_reg = PUD_REG;
+ break;
+ case PINCFG_TYPE_DRV:
+ width = bank->drv_width;
+ cfg_reg = DRV_REG;
+ break;
+ case PINCFG_TYPE_CON_PDN:
+ width = bank->conpdn_width;
+ cfg_reg = CONPDN_REG;
+ break;
+ case PINCFG_TYPE_PUD_PDN:
+ width = bank->pudpdn_width;
+ cfg_reg = PUDPDN_REG;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ mask = (1 << width) - 1;
+ shift = pin_offset * width;
+ data = readl(reg_base + cfg_reg);
+
+ if (set) {
+ cfg_value = PINCFG_UNPACK_VALUE(*config);
+ data &= ~(mask << shift);
+ data |= (cfg_value << shift);
+ writel(data, reg_base + cfg_reg);
+ } else {
+ data >>= shift;
+ data &= mask;
+ *config = PINCFG_PACK(cfg_type, data);
+ }
+ return 0;
+}
+
+/* set the pin config settings for a specified pin */
+static int samsung_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long config)
+{
+ return samsung_pinconf_rw(pctldev, pin, &config, true);
+}
+
+/* get the pin config settings for a specified pin */
+static int samsung_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *config)
+{
+ return samsung_pinconf_rw(pctldev, pin, config, false);
+}
+
+/* set the pin config settings for a specified pin group */
+static int samsung_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned group, unsigned long config)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+ const unsigned int *pins;
+ unsigned int cnt;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ pins = drvdata->pin_groups[group].pins;
+
+ for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++)
+ samsung_pinconf_set(pctldev, pins[cnt], config);
+
+ return 0;
+}
+
+/* get the pin config settings for a specified pin group */
+static int samsung_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *config)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+ const unsigned int *pins;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+ pins = drvdata->pin_groups[group].pins;
+ samsung_pinconf_get(pctldev, pins[0], config);
+ return 0;
+}
+
+/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
+static struct pinconf_ops samsung_pinconf_ops = {
+ .pin_config_get = samsung_pinconf_get,
+ .pin_config_set = samsung_pinconf_set,
+ .pin_config_group_get = samsung_pinconf_group_get,
+ .pin_config_group_set = samsung_pinconf_group_set,
+};
+
+/* gpiolib gpio_set callback function */
+static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+ void __iomem *reg;
+ u32 pin_offset, data;
+
+ pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
+ data = readl(reg + DAT_REG);
+ data &= ~(1 << pin_offset);
+ if (value)
+ data |= 1 << pin_offset;
+ writel(data, reg + DAT_REG);
+}
+
+/* gpiolib gpio_get callback function */
+static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+ void __iomem *reg;
+ u32 pin_offset, data;
+
+ pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
+ data = readl(reg + DAT_REG);
+ data >>= pin_offset;
+ data &= 1;
+ return data;
+}
+
+/*
+ * gpiolib gpio_direction_input callback function. The setting of the pin
+ * mux function as 'gpio input' will be handled by the pinctrl susbsystem
+ * interface.
+ */
+static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ return pinctrl_gpio_direction_input(gc->base + offset);
+}
+
+/*
+ * gpiolib gpio_direction_output callback function. The setting of the pin
+ * mux function as 'gpio output' will be handled by the pinctrl susbsystem
+ * interface.
+ */
+static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+ int value)
+{
+ samsung_gpio_set(gc, offset, value);
+ return pinctrl_gpio_direction_output(gc->base + offset);
+}
+
+/*
+ * Parse the pin names listed in the 'samsung,pins' property and convert it
+ * into a list of gpio numbers are create a pin group from it.
+ */
+static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
+ struct device_node *cfg_np, struct pinctrl_desc *pctl,
+ unsigned int **pin_list, unsigned int *npins)
+{
+ struct device *dev = &pdev->dev;
+ struct property *prop;
+ struct pinctrl_pin_desc const *pdesc = pctl->pins;
+ unsigned int idx = 0, cnt;
+ const char *pin_name;
+
+ *npins = of_property_count_strings(cfg_np, "samsung,pins");
+ if (*npins < 0) {
+ dev_err(dev, "invalid pin list in %s node", cfg_np->name);
+ return -EINVAL;
+ }
+
+ *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
+ if (!*pin_list) {
+ dev_err(dev, "failed to allocate memory for pin list\n");
+ return -ENOMEM;
+ }
+
+ of_property_for_each_string(cfg_np, "samsung,pins", prop, pin_name) {
+ for (cnt = 0; cnt < pctl->npins; cnt++) {
+ if (pdesc[cnt].name) {
+ if (!strcmp(pin_name, pdesc[cnt].name)) {
+ (*pin_list)[idx++] = pdesc[cnt].number;
+ break;
+ }
+ }
+ }
+ if (cnt == pctl->npins) {
+ dev_err(dev, "pin %s not valid in %s node\n",
+ pin_name, cfg_np->name);
+ devm_kfree(dev, *pin_list);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Parse the information about all the available pin groups and pin functions
+ * from device node of the pin-controller. A pin group is formed with all
+ * the pins listed in the "samsung,pins" property.
+ */
+static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,
+ struct samsung_pinctrl_drv_data *drvdata)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *dev_np = dev->of_node;
+ struct device_node *cfg_np;
+ struct samsung_pin_group *groups, *grp;
+ struct samsung_pmx_func *functions, *func;
+ unsigned *pin_list;
+ unsigned int npins, grp_cnt, func_idx = 0;
+ char *gname, *fname;
+ int ret;
+
+ grp_cnt = of_get_child_count(dev_np);
+ if (!grp_cnt)
+ return -EINVAL;
+
+ groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
+ if (!groups) {
+ dev_err(dev, "failed allocate memory for ping group list\n");
+ return -EINVAL;
+ }
+ grp = groups;
+
+ functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
+ if (!functions) {
+ dev_err(dev, "failed to allocate memory for function list\n");
+ return -EINVAL;
+ }
+ func = functions;
+
+ /*
+ * Iterate over all the child nodes of the pin controller node
+ * and create pin groups and pin function lists.
+ */
+ for_each_child_of_node(dev_np, cfg_np) {
+ u32 function;
+ if (of_find_property(cfg_np, "interrupt-controller", NULL))
+ continue;
+
+ ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
+ &drvdata->pctl, &pin_list, &npins);
+ if (ret)
+ return ret;
+
+ /* derive pin group name from the node name */
+ gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
+ GFP_KERNEL);
+ if (!gname) {
+ dev_err(dev, "failed to alloc memory for group name\n");
+ return -ENOMEM;
+ }
+ sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
+
+ grp->name = gname;
+ grp->pins = pin_list;
+ grp->num_pins = npins;
+ of_property_read_u32(cfg_np, "samsung,pin-function", &function);
+ grp->func = function;
+ grp++;
+
+ if (!of_find_property(cfg_np, "samsung,pin-function", NULL))
+ continue;
+
+ /* derive function name from the node name */
+ fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
+ GFP_KERNEL);
+ if (!fname) {
+ dev_err(dev, "failed to alloc memory for func name\n");
+ return -ENOMEM;
+ }
+ sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
+
+ func->name = fname;
+ func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
+ if (!func->groups) {
+ dev_err(dev, "failed to alloc memory for group list "
+ "in pin function");
+ return -ENOMEM;
+ }
+ func->groups[0] = gname;
+ func->num_groups = 1;
+ func++;
+ func_idx++;
+ }
+
+ drvdata->pin_groups = groups;
+ drvdata->nr_groups = grp_cnt;
+ drvdata->pmx_functions = functions;
+ drvdata->nr_functions = func_idx;
+
+ return 0;
+}
+
+/* register the pinctrl interface with the pinctrl subsystem */
+static int __init samsung_pinctrl_register(struct platform_device *pdev,
+ struct samsung_pinctrl_drv_data *drvdata)
+{
+ struct pinctrl_desc *ctrldesc = &drvdata->pctl;
+ struct pinctrl_pin_desc *pindesc, *pdesc;
+ struct samsung_pin_bank *pin_bank;
+ char *pin_names;
+ int pin, bank, ret;
+
+ ctrldesc->name = "samsung-pinctrl";
+ ctrldesc->owner = THIS_MODULE;
+ ctrldesc->pctlops = &samsung_pctrl_ops;
+ ctrldesc->pmxops = &samsung_pinmux_ops;
+ ctrldesc->confops = &samsung_pinconf_ops;
+
+ pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
+ drvdata->ctrl->nr_pins, GFP_KERNEL);
+ if (!pindesc) {
+ dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
+ return -ENOMEM;
+ }
+ ctrldesc->pins = pindesc;
+ ctrldesc->npins = drvdata->ctrl->nr_pins;
+ ctrldesc->npins = drvdata->ctrl->nr_pins;
+
+ /* dynamically populate the pin number and pin name for pindesc */
+ for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++)
+ pdesc->number = pin + drvdata->ctrl->base;
+
+ /*
+ * allocate space for storing the dynamically generated names for all
+ * the pins which belong to this pin-controller.
+ */
+ pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
+ drvdata->ctrl->nr_pins, GFP_KERNEL);
+ if (!pin_names) {
+ dev_err(&pdev->dev, "mem alloc for pin names failed\n");
+ return -ENOMEM;
+ }
+
+ /* for each pin, the name of the pin is pin-bank name + pin number */
+ for (bank = 0; bank < drvdata->ctrl->nr_banks; bank++) {
+ pin_bank = &drvdata->ctrl->pin_banks[bank];
+ for (pin = 0; pin < pin_bank->nr_pins; pin++) {
+ sprintf(pin_names, "%s-%d", pin_bank->name, pin);
+ pdesc = pindesc + pin_bank->pin_base + pin;
+ pdesc->name = pin_names;
+ pin_names += PIN_NAME_LENGTH;
+ }
+ }
+
+ drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata);
+ if (!drvdata->pctl_dev) {
+ dev_err(&pdev->dev, "could not register pinctrl driver\n");
+ return -EINVAL;
+ }
+
+ drvdata->grange.name = "samsung-pctrl-gpio-range";
+ drvdata->grange.id = 0;
+ drvdata->grange.base = drvdata->ctrl->base;
+ drvdata->grange.npins = drvdata->ctrl->nr_pins;
+ drvdata->grange.gc = drvdata->gc;
+ pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange);
+
+ ret = samsung_pinctrl_parse_dt(pdev, drvdata);
+ if (ret) {
+ pinctrl_unregister(drvdata->pctl_dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* register the gpiolib interface with the gpiolib subsystem */
+static int __init samsung_gpiolib_register(struct platform_device *pdev,
+ struct samsung_pinctrl_drv_data *drvdata)
+{
+ struct gpio_chip *gc;
+ int ret;
+
+ gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
+ if (!gc) {
+ dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
+ return -ENOMEM;
+ }
+
+ drvdata->gc = gc;
+ gc->base = drvdata->ctrl->base;
+ gc->ngpio = drvdata->ctrl->nr_pins;
+ gc->dev = &pdev->dev;
+ gc->set = samsung_gpio_set;
+ gc->get = samsung_gpio_get;
+ gc->direction_input = samsung_gpio_direction_input;
+ gc->direction_output = samsung_gpio_direction_output;
+ gc->label = drvdata->ctrl->label;
+ gc->owner = THIS_MODULE;
+ ret = gpiochip_add(gc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
+ "code: %d\n", gc->label, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* unregister the gpiolib interface with the gpiolib subsystem */
+static int __init samsung_gpiolib_unregister(struct platform_device *pdev,
+ struct samsung_pinctrl_drv_data *drvdata)
+{
+ int ret = gpiochip_remove(drvdata->gc);
+ if (ret) {
+ dev_err(&pdev->dev, "gpio chip remove failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static const struct of_device_id samsung_pinctrl_dt_match[];
+
+/* retrieve the soc specific data */
+static inline struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
+ struct platform_device *pdev)
+{
+ int id;
+ const struct of_device_id *match;
+ const struct device_node *node = pdev->dev.of_node;
+
+ id = of_alias_get_id(pdev->dev.of_node, "pinctrl");
+ if (id < 0) {
+ dev_err(&pdev->dev, "failed to get alias id\n");
+ return NULL;
+ }
+ match = of_match_node(samsung_pinctrl_dt_match, node);
+ return (struct samsung_pin_ctrl *)match->data + id;
+}
+
+static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
+{
+ struct samsung_pinctrl_drv_data *drvdata;
+ struct device *dev = &pdev->dev;
+ struct samsung_pin_ctrl *ctrl;
+ struct resource *res;
+ int ret;
+
+ if (!dev->of_node) {
+ dev_err(dev, "device tree node not found\n");
+ return -ENODEV;
+ }
+
+ ctrl = samsung_pinctrl_get_soc_data(pdev);
+ if (!ctrl) {
+ dev_err(&pdev->dev, "driver data not available\n");
+ return -EINVAL;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ dev_err(dev, "failed to allocate memory for driver's "
+ "private data\n");
+ return -ENOMEM;
+ }
+ drvdata->ctrl = ctrl;
+ drvdata->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "cannot find IO resource\n");
+ return -ENOENT;
+ }
+
+ drvdata->virt_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!drvdata->virt_base) {
+ dev_err(dev, "ioremap failed\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res)
+ drvdata->irq = res->start;
+
+ ret = samsung_gpiolib_register(pdev, drvdata);
+ if (ret)
+ return ret;
+
+ ret = samsung_pinctrl_register(pdev, drvdata);
+ if (ret) {
+ samsung_gpiolib_unregister(pdev, drvdata);
+ return ret;
+ }
+
+ if (ctrl->eint_gpio_init)
+ ctrl->eint_gpio_init(drvdata);
+ if (ctrl->eint_wkup_init)
+ ctrl->eint_wkup_init(drvdata);
+
+ platform_set_drvdata(pdev, drvdata);
+ return 0;
+}
+
+static const struct of_device_id samsung_pinctrl_dt_match[] = {
+ { .compatible = "samsung,pinctrl-exynos4210",
+ .data = (void *)exynos4210_pin_ctrl },
+ {},
+};
+MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
+
+static struct platform_driver samsung_pinctrl_driver = {
+ .probe = samsung_pinctrl_probe,
+ .driver = {
+ .name = "samsung-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(samsung_pinctrl_dt_match),
+ },
+};
+
+static int __init samsung_pinctrl_drv_register(void)
+{
+ return platform_driver_register(&samsung_pinctrl_driver);
+}
+postcore_initcall(samsung_pinctrl_drv_register);
+
+static void __exit samsung_pinctrl_drv_unregister(void)
+{
+ platform_driver_unregister(&samsung_pinctrl_driver);
+}
+module_exit(samsung_pinctrl_drv_unregister);
+
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
+MODULE_DESCRIPTION("Samsung pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
new file mode 100644
index 00000000000..b8956934cda
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -0,0 +1,239 @@
+/*
+ * pin-controller/pin-mux/pin-config/gpio-driver for Samsung's SoC's.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2012 Linaro Ltd
+ * http://www.linaro.org
+ *
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef __PINCTRL_SAMSUNG_H
+#define __PINCTRL_SAMSUNG_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+
+/* register offsets within a pin bank */
+#define DAT_REG 0x4
+#define PUD_REG 0x8
+#define DRV_REG 0xC
+#define CONPDN_REG 0x10
+#define PUDPDN_REG 0x14
+
+/* pinmux function number for pin as gpio output line */
+#define FUNC_OUTPUT 0x1
+
+/**
+ * enum pincfg_type - possible pin configuration types supported.
+ * @PINCFG_TYPE_PUD: Pull up/down configuration.
+ * @PINCFG_TYPE_DRV: Drive strength configuration.
+ * @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
+ * @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
+ */
+enum pincfg_type {
+ PINCFG_TYPE_PUD,
+ PINCFG_TYPE_DRV,
+ PINCFG_TYPE_CON_PDN,
+ PINCFG_TYPE_PUD_PDN,
+};
+
+/*
+ * pin configuration (pull up/down and drive strength) type and its value are
+ * packed together into a 16-bits. The upper 8-bits represent the configuration
+ * type and the lower 8-bits hold the value of the configuration type.
+ */
+#define PINCFG_TYPE_MASK 0xFF
+#define PINCFG_VALUE_SHIFT 8
+#define PINCFG_VALUE_MASK (0xFF << PINCFG_VALUE_SHIFT)
+#define PINCFG_PACK(type, value) (((value) << PINCFG_VALUE_SHIFT) | type)
+#define PINCFG_UNPACK_TYPE(cfg) ((cfg) & PINCFG_TYPE_MASK)
+#define PINCFG_UNPACK_VALUE(cfg) (((cfg) & PINCFG_VALUE_MASK) >> \
+ PINCFG_VALUE_SHIFT)
+/**
+ * enum eint_type - possible external interrupt types.
+ * @EINT_TYPE_NONE: bank does not support external interrupts
+ * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
+ * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
+ *
+ * Samsung GPIO controller groups all the available pins into banks. The pins
+ * in a pin bank can support external gpio interrupts or external wakeup
+ * interrupts or no interrupts at all. From a software perspective, the only
+ * difference between external gpio and external wakeup interrupts is that
+ * the wakeup interrupts can additionally wakeup the system if it is in
+ * suspended state.
+ */
+enum eint_type {
+ EINT_TYPE_NONE,
+ EINT_TYPE_GPIO,
+ EINT_TYPE_WKUP,
+};
+
+/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
+#define PIN_NAME_LENGTH 10
+
+#define PIN_GROUP(n, p, f) \
+ { \
+ .name = n, \
+ .pins = p, \
+ .num_pins = ARRAY_SIZE(p), \
+ .func = f \
+ }
+
+#define PMX_FUNC(n, g) \
+ { \
+ .name = n, \
+ .groups = g, \
+ .num_groups = ARRAY_SIZE(g), \
+ }
+
+struct samsung_pinctrl_drv_data;
+
+/**
+ * struct samsung_pin_bank: represent a controller pin-bank.
+ * @reg_offset: starting offset of the pin-bank registers.
+ * @pin_base: starting pin number of the bank.
+ * @nr_pins: number of pins included in this bank.
+ * @func_width: width of the function selector bit field.
+ * @pud_width: width of the pin pull up/down selector bit field.
+ * @drv_width: width of the pin driver strength selector bit field.
+ * @conpdn_width: width of the sleep mode function selector bin field.
+ * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
+ * @eint_type: type of the external interrupt supported by the bank.
+ * @irq_base: starting controller local irq number of the bank.
+ * @name: name to be prefixed for each pin in this pin bank.
+ */
+struct samsung_pin_bank {
+ u32 pctl_offset;
+ u32 pin_base;
+ u8 nr_pins;
+ u8 func_width;
+ u8 pud_width;
+ u8 drv_width;
+ u8 conpdn_width;
+ u8 pudpdn_width;
+ enum eint_type eint_type;
+ u32 irq_base;
+ char *name;
+};
+
+/**
+ * struct samsung_pin_ctrl: represent a pin controller.
+ * @pin_banks: list of pin banks included in this controller.
+ * @nr_banks: number of pin banks.
+ * @base: starting system wide pin number.
+ * @nr_pins: number of pins supported by the controller.
+ * @nr_gint: number of external gpio interrupts supported.
+ * @nr_wint: number of external wakeup interrupts supported.
+ * @geint_con: offset of the ext-gpio controller registers.
+ * @geint_mask: offset of the ext-gpio interrupt mask registers.
+ * @geint_pend: offset of the ext-gpio interrupt pending registers.
+ * @weint_con: offset of the ext-wakeup controller registers.
+ * @weint_mask: offset of the ext-wakeup interrupt mask registers.
+ * @weint_pend: offset of the ext-wakeup interrupt pending registers.
+ * @svc: offset of the interrupt service register.
+ * @eint_gpio_init: platform specific callback to setup the external gpio
+ * interrupts for the controller.
+ * @eint_wkup_init: platform specific callback to setup the external wakeup
+ * interrupts for the controller.
+ * @label: for debug information.
+ */
+struct samsung_pin_ctrl {
+ struct samsung_pin_bank *pin_banks;
+ u32 nr_banks;
+
+ u32 base;
+ u32 nr_pins;
+ u32 nr_gint;
+ u32 nr_wint;
+
+ u32 geint_con;
+ u32 geint_mask;
+ u32 geint_pend;
+
+ u32 weint_con;
+ u32 weint_mask;
+ u32 weint_pend;
+
+ u32 svc;
+
+ int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
+ int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
+ char *label;
+};
+
+/**
+ * struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
+ * @virt_base: register base address of the controller.
+ * @dev: device instance representing the controller.
+ * @irq: interrpt number used by the controller to notify gpio interrupts.
+ * @ctrl: pin controller instance managed by the driver.
+ * @pctl: pin controller descriptor registered with the pinctrl subsystem.
+ * @pctl_dev: cookie representing pinctrl device instance.
+ * @pin_groups: list of pin groups available to the driver.
+ * @nr_groups: number of such pin groups.
+ * @pmx_functions: list of pin functions available to the driver.
+ * @nr_function: number of such pin functions.
+ * @gc: gpio_chip instance registered with gpiolib.
+ * @grange: linux gpio pin range supported by this controller.
+ */
+struct samsung_pinctrl_drv_data {
+ void __iomem *virt_base;
+ struct device *dev;
+ int irq;
+
+ struct samsung_pin_ctrl *ctrl;
+ struct pinctrl_desc pctl;
+ struct pinctrl_dev *pctl_dev;
+
+ const struct samsung_pin_group *pin_groups;
+ unsigned int nr_groups;
+ const struct samsung_pmx_func *pmx_functions;
+ unsigned int nr_functions;
+
+ struct irq_domain *gpio_irqd;
+ struct irq_domain *wkup_irqd;
+
+ struct gpio_chip *gc;
+ struct pinctrl_gpio_range grange;
+};
+
+/**
+ * struct samsung_pin_group: represent group of pins of a pinmux function.
+ * @name: name of the pin group, used to lookup the group.
+ * @pins: the pins included in this group.
+ * @num_pins: number of pins included in this group.
+ * @func: the function number to be programmed when selected.
+ */
+struct samsung_pin_group {
+ const char *name;
+ const unsigned int *pins;
+ u8 num_pins;
+ u8 func;
+};
+
+/**
+ * struct samsung_pmx_func: represent a pin function.
+ * @name: name of the pin function, used to lookup the function.
+ * @groups: one or more names of pin groups that provide this function.
+ * @num_groups: number of groups included in @groups.
+ */
+struct samsung_pmx_func {
+ const char *name;
+ const char **groups;
+ u8 num_groups;
+};
+
+/* list of all exported SoC specific data */
+extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
+
+#endif /* __PINCTRL_SAMSUNG_H */
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 98c8cc30845..b271ea54652 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -26,6 +26,8 @@
#include <plat-samsung/regs-timer.h>
+#define NUM_PWM 4
+
struct s3c_chip {
struct platform_device *pdev;
@@ -37,7 +39,6 @@ struct s3c_chip {
unsigned int duty_ns;
unsigned char tcon_base;
- unsigned char pwm_id;
struct pwm_chip chip;
};
@@ -136,8 +137,8 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* The TCMP and TCNT can be read without a lock, they're not
* shared between the timers. */
- tcmp = __raw_readl(S3C2410_TCMPB(s3c->pwm_id));
- tcnt = __raw_readl(S3C2410_TCNTB(s3c->pwm_id));
+ tcmp = __raw_readl(S3C2410_TCMPB(pwm->hwpwm));
+ tcnt = __raw_readl(S3C2410_TCNTB(pwm->hwpwm));
period = NS_IN_HZ / period_ns;
@@ -180,8 +181,8 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
local_irq_save(flags);
- __raw_writel(tcmp, S3C2410_TCMPB(s3c->pwm_id));
- __raw_writel(tcnt, S3C2410_TCNTB(s3c->pwm_id));
+ __raw_writel(tcmp, S3C2410_TCMPB(pwm->hwpwm));
+ __raw_writel(tcnt, S3C2410_TCNTB(pwm->hwpwm));
tcon = __raw_readl(S3C2410_TCON);
tcon |= pwm_tcon_manulupdate(s3c);
@@ -228,7 +229,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)
s3c->chip.dev = &pdev->dev;
s3c->chip.ops = &s3c_pwm_ops;
s3c->chip.base = -1;
- s3c->chip.npwm = 1;
+ s3c->chip.npwm = NUM_PWM;
s3c->clk = devm_clk_get(dev, "pwm-tin");
if (IS_ERR(s3c->clk)) {
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index 86f655c7f7a..e804846e7f3 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -25,9 +25,34 @@
struct regulator_dev *dummy_regulator_rdev;
-static struct regulator_init_data dummy_initdata;
+static struct regulator_init_data dummy_initdata = {
+ .constraints = {
+ .name = "dummy",
+ .min_uV = 0,
+ .max_uV = 5000000,
+ .apply_uV = 0,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .state_mem = {
+ .disabled = 0,
+ },
+ },
+};
+
+static int dummy_get_voltage(struct regulator_dev *rdev)
+{
+ return 0;
+}
-static struct regulator_ops dummy_ops;
+static int dummy_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ return 0;
+}
+
+static struct regulator_ops dummy_ops = {
+ .get_voltage = dummy_get_voltage,
+ .set_voltage = dummy_set_voltage,
+};
static struct regulator_desc dummy_desc = {
.name = "dummy",
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index e39a0c7260d..a333c4ddadb 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -24,6 +24,7 @@
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -31,6 +32,7 @@
#include <linux/regulator/machine.h>
#include <linux/mfd/max8997.h>
#include <linux/mfd/max8997-private.h>
+#include <linux/regulator/of_regulator.h>
struct max8997_data {
struct device *dev;
@@ -933,10 +935,145 @@ static struct regulator_desc regulators[] = {
max8997_charger_fixedstate_ops),
};
+#ifdef CONFIG_OF
+static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+ struct max8997_platform_data *pdata,
+ struct device_node *pmic_np)
+{
+ int i, gpio;
+
+ for (i = 0; i < 3; i++) {
+ gpio = of_get_named_gpio(pmic_np,
+ "max8997,pmic-buck125-dvs-gpios", i);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+ return -EINVAL;
+ }
+ pdata->buck125_gpios[i] = gpio;
+ }
+ return 0;
+}
+
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+ struct max8997_platform_data *pdata)
+{
+ struct device_node *pmic_np, *regulators_np, *reg_np;
+ struct max8997_regulator_data *rdata;
+ unsigned int i, dvs_voltage_nr = 1, ret;
+
+ pmic_np = iodev->dev->of_node;
+ if (!pmic_np) {
+ dev_err(iodev->dev, "could not find pmic sub-node\n");
+ return -ENODEV;
+ }
+
+ regulators_np = of_find_node_by_name(pmic_np, "regulators");
+ if (!regulators_np) {
+ dev_err(iodev->dev, "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ /* count the number of regulators to be supported in pmic */
+ pdata->num_regulators = 0;
+ for_each_child_of_node(regulators_np, reg_np)
+ pdata->num_regulators++;
+
+ rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+ pdata->num_regulators, GFP_KERNEL);
+ if (!rdata) {
+ dev_err(iodev->dev, "could not allocate memory for "
+ "regulator data\n");
+ return -ENOMEM;
+ }
+
+ pdata->regulators = rdata;
+ for_each_child_of_node(regulators_np, reg_np) {
+ for (i = 0; i < ARRAY_SIZE(regulators); i++)
+ if (!of_node_cmp(reg_np->name, regulators[i].name))
+ break;
+
+ if (i == ARRAY_SIZE(regulators)) {
+ dev_warn(iodev->dev, "don't know how to configure "
+ "regulator %s\n", reg_np->name);
+ continue;
+ }
+
+ rdata->id = i;
+ rdata->initdata = of_get_regulator_init_data(
+ iodev->dev, reg_np);
+ rdata->reg_node = reg_np;
+ rdata++;
+ }
+
+ if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL))
+ pdata->buck1_gpiodvs = true;
+
+ if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL))
+ pdata->buck2_gpiodvs = true;
+
+ if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL))
+ pdata->buck5_gpiodvs = true;
+
+ if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+ pdata->buck5_gpiodvs) {
+ ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+ if (ret)
+ return -EINVAL;
+
+ if (of_property_read_u32(pmic_np,
+ "max8997,pmic-buck125-default-dvs-idx",
+ &pdata->buck125_default_idx)) {
+ pdata->buck125_default_idx = 0;
+ } else {
+ if (pdata->buck125_default_idx >= 8) {
+ pdata->buck125_default_idx = 0;
+ dev_info(iodev->dev, "invalid value for "
+ "default dvs index, using 0 instead\n");
+ }
+ }
+
+ if (of_get_property(pmic_np,
+ "max8997,pmic-ignore-gpiodvs-side-effect", NULL))
+ pdata->ignore_gpiodvs_side_effect = true;
+
+ dvs_voltage_nr = 8;
+ }
+
+ if (of_property_read_u32_array(pmic_np,
+ "max8997,pmic-buck1-dvs-voltage",
+ pdata->buck1_voltage, dvs_voltage_nr)) {
+ dev_err(iodev->dev, "buck1 voltages not specified\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32_array(pmic_np,
+ "max8997,pmic-buck2-dvs-voltage",
+ pdata->buck2_voltage, dvs_voltage_nr)) {
+ dev_err(iodev->dev, "buck2 voltages not specified\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32_array(pmic_np,
+ "max8997,pmic-buck5-dvs-voltage",
+ pdata->buck5_voltage, dvs_voltage_nr)) {
+ dev_err(iodev->dev, "buck5 voltages not specified\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#else
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+ struct max8997_platform_data *pdata)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
static __devinit int max8997_pmic_probe(struct platform_device *pdev)
{
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct max8997_platform_data *pdata = iodev->pdata;
struct regulator_config config = { };
struct regulator_dev **rdev;
struct max8997_data *max8997;
@@ -944,11 +1081,17 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
int i, ret, size;
u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
- if (!pdata) {
+ if (IS_ERR_OR_NULL(pdata)) {
dev_err(pdev->dev.parent, "No platform init data supplied.\n");
return -ENODEV;
}
+ if (iodev->dev->of_node) {
+ ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+ if (ret)
+ return ret;
+ }
+
max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
GFP_KERNEL);
if (!max8997)
@@ -1101,6 +1244,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
config.dev = max8997->dev;
config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8997;
+ config.of_node = pdata->regulators[i].reg_node;
rdev[i] = regulator_register(&regulators[id], &config);
if (IS_ERR(rdev[i])) {
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index e3402d5644d..6c05d217e41 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -136,4 +136,6 @@ source "drivers/staging/csr/Kconfig"
source "drivers/staging/omap-thermal/Kconfig"
+source "drivers/staging/alc5625/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 664eae1a4aa..ed1a42e2c3b 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_USB_G_CCG) += ccg/
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
obj-$(CONFIG_CSR_WIFI) += csr/
obj-$(CONFIG_OMAP_BANDGAP) += omap-thermal/
+obj-$(CONFIG_SND_SOC_ORIGEN_ALC5625) += alc5625/
diff --git a/drivers/staging/alc5625/Kconfig b/drivers/staging/alc5625/Kconfig
new file mode 100644
index 00000000000..b35a4695497
--- /dev/null
+++ b/drivers/staging/alc5625/Kconfig
@@ -0,0 +1,13 @@
+# Staging the origen board audio codec
+config SND_SOC_ALC5625
+ tristate
+
+config SND_SOC_ORIGEN_ALC5625
+ tristate "SoC I2S Audio support for ALC5625 on ORIGEN board"
+ depends on SND_SOC_SAMSUNG && MACH_ORIGEN
+ select SND_SOC_ALC5625
+ select SND_SAMSUNG_I2S
+ select fool
+ help
+ Say Y if you want to add support for SoC audio
+ on origen board using ALC5625 codec
diff --git a/drivers/staging/alc5625/Makefile b/drivers/staging/alc5625/Makefile
new file mode 100644
index 00000000000..ae4d85e7738
--- /dev/null
+++ b/drivers/staging/alc5625/Makefile
@@ -0,0 +1,3 @@
+# Staging the origen board audio codec
+obj-$(CONFIG_SND_SOC_ALC5625) += alc5625.o
+obj-$(CONFIG_SND_SOC_ORIGEN_ALC5625) += origen_alc5625.o
diff --git a/drivers/staging/alc5625/alc5625.c b/drivers/staging/alc5625/alc5625.c
new file mode 100644
index 00000000000..98a874fb573
--- /dev/null
+++ b/drivers/staging/alc5625/alc5625.c
@@ -0,0 +1,2276 @@
+/*
+ * alc5625.c -- ALC5625 ALSA SoC Audio driver
+ *
+ * Copyright (C) 2011 Insignal Co., Ltd.
+ *
+ * Author: Pan<pan@insginal.co.kr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "alc5625.h"
+
+struct alc5625_priv {
+ unsigned int stereo_sysclk;
+ unsigned int voice_sysclk;
+ enum snd_soc_control_type control_type;
+ void *control_data;
+ struct snd_soc_codec *codec;
+ struct regmap *regmap;
+};
+
+struct alc5625_init_reg {
+ u8 reg_index;
+ u16 reg_value;
+};
+
+static struct alc5625_init_reg alc5625_init_list[] = {
+
+ {ALC5625_HP_OUT_VOL, 0x9090}, /* default is -12db */
+ {ALC5625_SPK_OUT_VOL, 0x8080}, /* default is 0db */
+ {ALC5625_DAC_AND_MIC_CTRL, 0xee03}, /* DAC to hpmixer */
+ {ALC5625_OUTPUT_MIXER_CTRL, 0x0748}, /* all output from hpmixer */
+ {ALC5625_MIC_CTRL, 0x0500}, /* mic boost 20db */
+ {ALC5625_ADC_REC_MIXER, 0x3f3f}, /* record source from mic1 */
+ {ALC5625_GEN_CTRL_REG1, 0x0c0a}, /* speaker vdd ratio is 1 */
+
+ /* gain 15db of ADC by default */
+ {ALC5625_ADC_REC_GAIN, 0xd5d5},
+
+ /* Audio Record settings */
+ {ALC5625_LINE_IN_VOL, 0xff1f},
+ {ALC5625_PD_CTRL_STAT, 0x00c0},
+ {ALC5625_PWR_MANAG_ADD3, 0x80c2},
+};
+
+#define ALC5625_INIT_REG_NUM ARRAY_SIZE(alc5625_init_list)
+
+/*
+ * bit[0] for linein playback switch
+ * bit[1] phone
+ * bit[2] mic1
+ * bit[3] mic2
+ * bit[4] vopcm
+ *
+ */
+#define HPL_MIXER 0x80
+#define HPR_MIXER 0x82
+static unsigned int reg80, reg82;
+
+/*
+ * bit[0][1][2] use for aec control
+ * bit[3] for none
+ * bit[4] for SPKL pga
+ * bit[5] for SPKR pga
+ * bit[6] for hpl pga
+ * bit[7] for hpr pga
+ * bit[8] for dump dsp
+ */
+#define virtual_reg_FOR_MISC_FUNC 0x84
+static unsigned int reg84;
+
+static const u16 alc5625_reg[] = {
+ 0x59b4, 0x8080, 0x9090, 0x8080, /* reg00-reg06 */
+ 0xc800, 0xff1f, 0x1010, 0x0808, /* reg08-reg0e */
+ 0xe0ef, 0xd5d5, 0x3f3f, 0x0000, /* reg10-reg16 */
+ 0xe010, 0x0000, 0x0748, 0x2007, /* reg18-reg1e */
+ 0x0000, 0x0500, 0x00c0, 0x00c0, /* reg20-reg26 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* reg28-reg2e */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* reg30-reg36 */
+ 0x0000, 0x0000, 0x0000, 0x80c2, /* reg38-reg3e */
+ 0x0c0a, 0x0000, 0x0000, 0x0000, /* reg40-reg46 */
+ 0x0029, 0x0000, 0xbe3e, 0x3e3e, /* reg48-reg4e */
+ 0x0000, 0x0000, 0x803a, 0x0000, /* reg50-reg56 */
+ 0x0000, 0x0009, 0x0000, 0x3000, /* reg58-reg5e */
+ 0x3075, 0x1010, 0x3110, 0x0000, /* reg60-reg66 */
+ 0x0553, 0x0000, 0x0000, 0x0000, /* reg68-reg6e */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* reg70-reg76 */
+ 0x0000, 0x0000, 0x0000, 0x0000, /* reg78-reg7e */
+};
+
+struct voice_dsp_reg vodsp_aec_init_value[] = {
+ {0x232c, 0x0025},
+ {0x230b, 0x0001},
+ {0x2308, 0x007f},
+ {0x23f8, 0x4003},
+ {0x2301, 0x0002},
+ {0x2328, 0x0001},
+ {0x2304, 0x00fa},
+ {0x2305, 0x0500},
+ {0x2306, 0x4000},
+ {0x230d, 0x0900},
+ {0x230e, 0x0280},
+ {0x2312, 0x00b1},
+ {0x2314, 0xc000},
+ {0x2316, 0x0041},
+ {0x2317, 0x2200},
+ {0x2318, 0x0c00},
+ {0x231d, 0x0050},
+ {0x231f, 0x4000},
+ {0x2330, 0x0008},
+ {0x2335, 0x000a},
+ {0x2336, 0x0004},
+ {0x2337, 0x5000},
+ {0x233a, 0x0300},
+ {0x233b, 0x0030},
+ {0x2341, 0x0008},
+ {0x2343, 0x0800},
+ {0x2352, 0x7fff},
+ {0x237f, 0x0400},
+ {0x23a7, 0x2800},
+ {0x22ce, 0x0400},
+ {0x22d3, 0x1500},
+ {0x22d4, 0x2800},
+ {0x22d5, 0x3000},
+ {0x2399, 0x2800},
+ {0x230c, 0x0000}, /* to enable VODSP AEC function */
+};
+
+#define SET_VODSP_REG_INIT_NUM ARRAY_SIZE(vodsp_aec_init_value)
+
+static inline unsigned int alc5625_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ u16 *cache = codec->reg_cache;
+
+ if (reg > 0x7e)
+ return 0;
+ return cache[reg / 2];
+}
+
+static unsigned int alc5625_read_hw_reg(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned int value = 0x0;
+
+ if (regmap_read(codec->control_data, reg, &value) < 0) {
+ printk(KERN_DEBUG "%s failed\n", __func__);
+ return -EIO;
+ }
+ return value;
+}
+
+
+static unsigned int alc5625_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+ if ((reg == 0x80) || (reg == 0x82) || (reg == 0x84))
+ return (reg == 0x80) ? reg80 :
+ ((reg == 0x82) ? reg82 : reg84);
+
+ return alc5625_read_hw_reg(codec, reg);
+}
+
+static inline void alc5625_write_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg,
+ unsigned int value)
+{
+ u16 *cache = codec->reg_cache;
+ if (reg > 0x7E)
+ return;
+ cache[reg / 2] = value;
+}
+
+static int alc5625_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ unsigned int *regvalue = NULL;
+
+ if ((reg == 0x80) || (reg == 0x82) || (reg == 0x84)) {
+ regvalue = ((reg == 0x80) ? &reg80 :
+ ((reg == 0x82) ? &reg82 : &reg84));
+ *regvalue = value;
+ return 0;
+ }
+ alc5625_write_reg_cache(codec, reg, value);
+
+ if (!regmap_write(codec->control_data, reg, value)) {
+ return 0;
+ } else {
+ printk(KERN_ERR "alc5625_write fail\n");
+ return -EIO;
+ }
+}
+
+#define alc5625_write_mask(c, reg, value, mask) snd_soc_update_bits(c,\
+ reg, mask, value)
+
+#define alc5625_reset(c) alc5625_write(c, ALC5625_RESET, 0)
+
+/* read/write dsp reg */
+static int alc5625_wait_vodsp_i2c_done(struct snd_soc_codec *codec)
+{
+ unsigned int checkcount = 0;
+ unsigned int vodsp_data;
+
+ vodsp_data = alc5625_read(codec, ALC5625_VODSP_REG_CMD);
+ while (vodsp_data & VODSP_BUSY) {
+ if (checkcount > 10)
+ return -EBUSY;
+ vodsp_data = alc5625_read(codec, ALC5625_VODSP_REG_CMD);
+ checkcount++;
+ }
+ return 0;
+}
+
+static int alc5625_write_vodsp_reg(struct snd_soc_codec *codec,
+ unsigned int vodspreg, unsigned int value)
+{
+ if (alc5625_wait_vodsp_i2c_done(codec))
+ return -EBUSY;
+
+ alc5625_write(codec, ALC5625_VODSP_REG_ADDR, vodspreg);
+ alc5625_write(codec, ALC5625_VODSP_REG_DATA, value);
+ alc5625_write(codec, ALC5625_VODSP_REG_CMD,
+ VODSP_WRITE_ENABLE | VODSP_CMD_MW);
+ mdelay(10);
+ return 0;
+
+}
+
+static unsigned int alc5625_read_vodsp_reg(struct snd_soc_codec *codec,
+ unsigned int vodspreg)
+{
+ unsigned int ndata_h, ndata_l;
+ unsigned int value;
+
+ if (alc5625_wait_vodsp_i2c_done(codec))
+ return -EBUSY;
+
+ alc5625_write(codec, ALC5625_VODSP_REG_ADDR, vodspreg);
+ alc5625_write(codec, ALC5625_VODSP_REG_CMD,
+ VODSP_READ_ENABLE | VODSP_CMD_MR);
+
+ if (alc5625_wait_vodsp_i2c_done(codec))
+ return -EBUSY;
+
+ alc5625_write(codec, ALC5625_VODSP_REG_ADDR, 0x26);
+ alc5625_write(codec, ALC5625_VODSP_REG_CMD,
+ VODSP_READ_ENABLE | VODSP_CMD_RR);
+
+ if (alc5625_wait_vodsp_i2c_done(codec))
+ return -EBUSY;
+
+ ndata_h = alc5625_read(codec, ALC5625_VODSP_REG_DATA);
+ alc5625_write(codec, ALC5625_VODSP_REG_ADDR, 0x25);
+ alc5625_write(codec, ALC5625_VODSP_REG_CMD,
+ VODSP_READ_ENABLE | VODSP_CMD_RR);
+
+ if (alc5625_wait_vodsp_i2c_done(codec))
+ return -EBUSY;
+
+ ndata_l = alc5625_read(codec, ALC5625_VODSP_REG_DATA);
+ value = ((ndata_h & 0xff) << 8) | (ndata_l & 0xff);
+
+ return value;
+}
+
+static int alc5625_reg_init(struct snd_soc_codec *codec)
+{
+ int i;
+
+ for (i = 0; i < ALC5625_INIT_REG_NUM; i++)
+ alc5625_write(codec, alc5625_init_list[i].reg_index,
+ alc5625_init_list[i].reg_value);
+
+ return 0;
+}
+
+static const char *const alc5625_aec_path_sel[] = {
+ "aec func disable", "aec func for pcm in/out",
+ "aec func for iis in/out", "aec func for analog in/out"
+}; /* 0 */
+static const char *const alc5625_spk_out_sel[] = {
+ "Class AB", "Class D"
+}; /* 1 */
+static const char *const alc5625_spk_l_source_sel[] = {
+ "LPRN", "LPRP", "LPLN", "MM"
+}; /* 2 */
+static const char *const alc5625_spkmux_source_sel[] = {
+ "VMID", "HP Mixer", "SPK Mixer", "Mono Mixer"
+}; /* 3 */
+static const char *const alc5625_hplmux_source_sel[] = {
+ "VMID", "HPL Mixer"
+}; /* 4 */
+static const char *const alc5625_hprmux_source_sel[] = {
+ "VMID", "HPR Mixer"
+}; /* 5 */
+static const char *const alc5625_auxmux_source_sel[] = {
+ "VMID", "HP Mixer", "SPK Mixer", "Mono Mixer"
+}; /* 6 */
+static const char *const alc5625_spkamp_ratio_sel[] = {
+ "2.25 Vdd", "2.00 Vdd", "1.75 Vdd",
+ "1.50 Vdd", "1.25 Vdd", "1.00 Vdd"
+}; /* 7 */
+static const char *const alc5625_mic1_boost_sel[] = {
+ "Bypass", "+20db", "+30db", "+40db"
+}; /* 8 */
+static const char *const alc5625_mic2_boost_sel[] = {
+ "Bypass", "+20db", "+30db", "+40db"
+}; /* 9 */
+static const char *const alc5625_dmic_boost_sel[] = {
+ "Bypass", "+6db", "+12db", "+18db",
+ "+24db", "+30db", "+36db", "+42db"
+}; /* 10 */
+static const char *const alc5625_adcr_func_sel[] = {
+ "Stereo ADC", "Voice ADC",
+ "VoDSP Interface", "PDM Slave Interface"
+}; /* 11 */
+
+static const struct soc_enum alc5625_enum[] = {
+ SOC_ENUM_SINGLE(virtual_reg_FOR_MISC_FUNC, 0, 4,
+ alc5625_aec_path_sel), /* 0 */
+ SOC_ENUM_SINGLE(ALC5625_OUTPUT_MIXER_CTRL, 13, 2,
+ alc5625_spk_out_sel), /* 1 */
+ SOC_ENUM_SINGLE(ALC5625_OUTPUT_MIXER_CTRL, 14, 4,
+ alc5625_spk_l_source_sel), /* 2 */
+ SOC_ENUM_SINGLE(ALC5625_OUTPUT_MIXER_CTRL, 10, 4,
+ alc5625_spkmux_source_sel), /* 3 */
+ SOC_ENUM_SINGLE(ALC5625_OUTPUT_MIXER_CTRL, 9, 2,
+ alc5625_hplmux_source_sel), /* 4 */
+ SOC_ENUM_SINGLE(ALC5625_OUTPUT_MIXER_CTRL, 8, 2,
+ alc5625_hprmux_source_sel), /* 5 */
+ SOC_ENUM_SINGLE(ALC5625_OUTPUT_MIXER_CTRL, 6, 4,
+ alc5625_auxmux_source_sel), /* 6 */
+ SOC_ENUM_SINGLE(ALC5625_GEN_CTRL_REG1, 1, 6,
+ alc5625_spkamp_ratio_sel), /* 7 */
+ SOC_ENUM_SINGLE(ALC5625_MIC_CTRL, 10, 4,
+ alc5625_mic1_boost_sel), /* 8 */
+ SOC_ENUM_SINGLE(ALC5625_MIC_CTRL, 8, 4,
+ alc5625_mic2_boost_sel), /* 9 */
+ SOC_ENUM_SINGLE(ALC5625_DMIC_CTRL, 0, 8,
+ alc5625_dmic_boost_sel), /* 10 */
+ SOC_ENUM_SINGLE(ALC5625_DAC_ADC_VODAC_FUN_SEL, 4, 4,
+ alc5625_adcr_func_sel), /* 11 */
+};
+
+/* function: Enable the Voice PCM interface Path */
+static int config_pcm_voice_path(struct snd_soc_codec *codec,
+ unsigned int enable_voice_path,
+ unsigned int mode)
+{
+ if (enable_voice_path) {
+ /* Power on DAC reference */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ PWR_DAC_REF | PWR_VOICE_DF2SE,
+ PWR_DAC_REF | PWR_VOICE_DF2SE);
+ /* Power on Voice DAC/ADC */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2,
+ PWR_VOICE_CLOCK,
+ PWR_VOICE_CLOCK);
+ /* routing voice to HPMixer */
+ alc5625_write_mask(codec, ALC5625_VOICE_DAC_OUT_VOL, 0,
+ M_V_DAC_TO_HP_MIXER);
+
+ switch (mode) {
+ case PCM_SLAVE_MODE_B:
+ /*
+ * 8kHz sampling rate,16 bits PCM mode and Slave mode,
+ * PCM mode is B,MCLK=24.576MHz from Oscillator.
+ * CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00000,
+ * PSKEY_FORMAT=0x0060
+ *
+ * Set LRCK voice select divide 32
+ * set voice blck select divide 6 and 8
+ * voice filter clock divide 3 and 16
+ * the register 0x64 value's should is 0x5524
+ */
+ alc5625_write(codec, ALC5625_VOICE_DAC_PCMCLK_CTRL1,
+ 0x5524);
+
+ break;
+
+ case PCM_SLAVE_MODE_A:
+ /*
+ * 8kHz sampling rate,16 bits PCM and Slave mode,
+ * PCM mode is A,MCLK=24.576MHz from Oscillator.
+ * CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08C00004,
+ * PSKEY_FORMAT=0x0060
+ *
+ * Enable GPIO 1,3,4,5 to voice interface
+ * Set I2S to Slave mode
+ * Voice I2S SYSCLK Source select Main SYSCLK
+ * Set voice i2s VBCLK Polarity to Invert
+ * Set Data length to 16 bit
+ * set Data Fomrat to PCM mode A
+ * the register 0x36 value's should is 0xC082
+ */
+ alc5625_write(codec, ALC5625_EXTEND_SDP_CTRL, 0xC082);
+
+ /*
+ * Set LRCK voice select divide 64
+ * set voice blck select divide 6 and 8
+ * voice filter clock divide 3 and 16
+ * the register 0x64 value's should is 0x5524
+ */
+ alc5625_write(codec, ALC5625_VOICE_DAC_PCMCLK_CTRL1,
+ 0x5524);
+
+ break;
+
+ case PCM_MASTER_MODE_B:
+ /*
+ * 8kHz sampling rate,16 bits PCM and Master mode,
+ * PCM mode is B,Clock from PLL OUT
+ * CSR PSKEY_PCM_CONFIG32 (HEX) = 0x08000002,
+ * PSKEY_FORMAT=0x0060
+ * Enable GPIO 1,3,4,5 to voice interface
+ * Set I2S to master mode
+ * Set voice i2s VBCLK Polarity to Invert
+ * Set Data length to 16 bit
+ * set Data Fomrat to PCM mode B
+ * the register 0x36 value's should is 0x8083
+ */
+ alc5625_write(codec, ALC5625_EXTEND_SDP_CTRL, 0x8083);
+
+ /*
+ * Set LRCK voice select divide 64
+ * set voice blck select divide 6 and 8
+ * voice filter clock divide 3 and 16
+ * the register 0x64 value's should is 0x5524
+ */
+ alc5625_write(codec, ALC5625_VOICE_DAC_PCMCLK_CTRL1,
+ 0x5524);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+ } else {
+ /* Power down Voice Different to sing-end power */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1, 0,
+ PWR_VOICE_DF2SE);
+ /* Power down Voice DAC/ADC */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2, 0,
+ PWR_VOICE_CLOCK);
+ /* Disable Voice PCM interface */
+ alc5625_write_mask(codec, ALC5625_EXTEND_SDP_CTRL, 0,
+ EXT_I2S_FUNC_ENABLE);
+ }
+
+ return 0;
+}
+
+static int init_vodsp_aec(struct snd_soc_codec *codec)
+{
+ int i;
+ int ret = 0;
+
+ /* Disable LDO power */
+ alc5625_write_mask(codec, ALC5625_LDO_CTRL, 0, LDO_ENABLE);
+ mdelay(20);
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ VODSP_NO_PD_MODE_ENA, VODSP_NO_PD_MODE_ENA);
+ /* Enable LDO power and set output voltage to 1.2V */
+ alc5625_write_mask(codec, ALC5625_LDO_CTRL,
+ LDO_ENABLE | LDO_OUT_VOL_CTRL_1_20V,
+ LDO_ENABLE | LDO_OUT_VOL_CTRL_MASK);
+ mdelay(20);
+ /* Enable power of VODSP I2C interface */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ PWR_VODSP_INTERFACE | PWR_I2C_FOR_VODSP,
+ PWR_VODSP_INTERFACE | PWR_I2C_FOR_VODSP);
+ mdelay(1);
+ /* Reset VODSP */
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ 0, VODSP_NO_RST_MODE_ENA);
+ mdelay(1);
+ /* Set VODSP to non-reset status */
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ VODSP_NO_RST_MODE_ENA, VODSP_NO_RST_MODE_ENA);
+ mdelay(20);
+
+ /*initize AEC paramter*/
+ for (i = 0; i < SET_VODSP_REG_INIT_NUM; i++) {
+ ret = alc5625_write_vodsp_reg(codec,
+ vodsp_aec_init_value[i].index,
+ vodsp_aec_init_value[i].val);
+ if (ret)
+ return -EIO;
+ }
+
+ schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+
+ return 0;
+}
+
+/*
+ * Enable/Disable the VODSP interface Path
+ *
+ * For system clock only support specific clock, realtek suggests customer to
+ * use 24.576Mhz or 22.5792Mhz clock for MCLK (MCLK=48k*512 or 44.1k*512Mhz)
+ */
+static int set_vodsp_aec_path(struct snd_soc_codec *codec, unsigned int mode)
+{
+ switch (mode) {
+ case PCM_IN_PCM_OUT:
+ /* set PCM format */
+ config_pcm_voice_path(codec, 1, PCM_MASTER_MODE_B);
+ /* set AEC path */
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT,
+ 0x0300, 0x0300);
+ alc5625_write_mask(codec, ALC5625_VODSP_PDM_CTL,
+ VODSP_RXDP_PWR |
+ VODSP_RXDP_S_SEL_VOICE |
+ VOICE_PCM_S_SEL_AEC_TXDP,
+ VODSP_RXDP_PWR |
+ VODSP_RXDP_S_SEL_MASK |
+ VOICE_PCM_S_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_DAC_ADC_VODAC_FUN_SEL,
+ ADCR_FUNC_SEL_PDM |
+ VODAC_SOUR_SEL_VODSP_TXDC,
+ ADCR_FUNC_SEL_MASK |
+ VODAC_SOUR_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ VODSP_LRCK_SEL_8K,
+ VODSP_LRCK_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT,
+ 0x0000, 0x0300);
+
+ /* Set input&output path and power
+ * Power on related bit
+ *
+ * I2S DAI Enable | spk amp enable |
+ * Dac2Mixer pwr on | MICBIAS1 Enable |
+ * MICBIAS2 Enable | Main Bias Pwr |
+ * DAC ref voltage pwr on
+ */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0c8f, 0x0c8f);
+
+ /* Pwr on Pll1 | over temperature sensor pwr on |
+ * pwr voice DAC on | Left and Right ADC on |
+ * Spk mixer pwr on | ADC mixer left/right pwr on
+ */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2,
+ 0xa4cb, 0xa4cb);
+
+ /* power spk left/right vol | pwr vodsp interface |
+ * power on microphone1 boost
+ */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x3302, 0xf302);
+
+ /* Mute DAC to hpmixer */
+ alc5625_write(codec, ALC5625_DAC_AND_MIC_CTRL, 0xee0f);
+
+ /* Set Mic1 to differential mode */
+ alc5625_write(codec, ALC5625_MIC_VOL, 0x8808);
+
+ /* Mic boost 0db */
+ alc5625_write(codec, ALC5625_MIC_CTRL, 0x0000);
+
+ /* ADC_Mixer_R boost 10.5 db */
+ alc5625_write(codec, ALC5625_ADC_REC_GAIN, 0xcbd3);
+
+ /* Mic1->ADCMixer_R */
+ alc5625_write(codec, ALC5625_ADC_REC_MIXER, 0x7f3f);
+
+ /* VoDAC to speakerMixer,0db */
+ alc5625_write(codec, ALC5625_VOICE_DAC_OUT_VOL, 0xa010);
+
+ /* Speaker source from speakermixer */
+ alc5625_write(codec, ALC5625_OUTPUT_MIXER_CTRL, 0x8808);
+
+ /* Unmute speaker */
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL, 0x0000, 0x8080);
+
+ break;
+
+ case ANALOG_IN_ANALOG_OUT:
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT, 0x0300, 0x0300);
+ alc5625_write_mask(codec, ALC5625_VODSP_PDM_CTL,
+ VODSP_RXDP_PWR |
+ VODSP_RXDP_S_SEL_ADCL |
+ VOICE_PCM_S_SEL_AEC_TXDP,
+ VODSP_RXDP_PWR | VODSP_RXDP_S_SEL_MASK |
+ VOICE_PCM_S_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_DAC_ADC_VODAC_FUN_SEL,
+ ADCR_FUNC_SEL_PDM |
+ VODAC_SOUR_SEL_VODSP_TXDC |
+ DAC_FUNC_SEL_VODSP_TXDP|
+ ADCL_FUNC_SEL_VODSP,
+ ADCR_FUNC_SEL_MASK |
+ VODAC_SOUR_SEL_MASK |
+ DAC_FUNC_SEL_MASK |
+ ADCL_FUNC_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ VODSP_LRCK_SEL_16K,
+ VODSP_LRCK_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT, 0x0000, 0x0300);
+
+ /* Set input&output path and power */
+ /* Power on related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0xcc8f, 0xcc8f);
+
+ /* Power on related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2,
+ 0xa7cf, 0xa7cf);
+
+ /* Power on related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0xf312, 0xf312);
+
+ /* Set Mic1 to differential mode */
+ alc5625_write(codec, ALC5625_MIC_VOL, 0x8808);
+
+ /* Set phone in to differential mode */
+ alc5625_write(codec, ALC5625_PHONEIN_VOL, 0xe800);
+
+ /* Mic boost 0db */
+ alc5625_write(codec, ALC5625_MIC_CTRL, 0x0000);
+
+ /* Mic1->ADCMixer_R,phone in-->ADCMixer_L */
+ alc5625_write(codec, ALC5625_ADC_REC_MIXER, 0x773f);
+
+ /* ADC_Mixer_R boost 10.5 db */
+ alc5625_write(codec, ALC5625_ADC_REC_GAIN, 0xCBD3);
+
+ /* Speaker from spkmixer,monoOut from monoMixer */
+ alc5625_write(codec, ALC5625_OUTPUT_MIXER_CTRL, 0x88c8);
+
+ /* Unmute VoDAC to spkmixer */
+ alc5625_write(codec, ALC5625_VOICE_DAC_OUT_VOL, 0xA010);
+
+ /* Unmute DAC to monoMixer */
+ alc5625_write(codec, ALC5625_DAC_AND_MIC_CTRL, 0xee0e);
+ alc5625_write(codec, ALC5625_STEREO_DAC_CLK_CTRL2, 0x2222);
+ alc5625_write(codec, ALC5625_VOICE_DAC_PCMCLK_CTRL1, 0x3122);
+
+ /* Unmute speaker */
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL, 0x0000, 0x8080);
+
+ /* Unmute auxout */
+ alc5625_write_mask(codec, ALC5625_AUX_OUT_VOL, 0x0000, 0x8080);
+ break;
+
+ case DAC_IN_ADC_OUT:
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT, 0x0300, 0x0300);
+ alc5625_write_mask(codec, ALC5625_DAC_ADC_VODAC_FUN_SEL,
+ ADCR_FUNC_SEL_PDM |
+ DAC_FUNC_SEL_VODSP_TXDC,
+ ADCR_FUNC_SEL_MASK |
+ DAC_FUNC_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_VODSP_PDM_CTL,
+ VODSP_SRC1_PWR |
+ VODSP_SRC2_PWR |
+ VODSP_RXDP_PWR |
+ VODSP_RXDP_S_SEL_SRC1 |
+ REC_S_SEL_SRC2,
+ VODSP_SRC1_PWR |
+ VODSP_SRC2_PWR |
+ VODSP_RXDP_PWR |
+ VODSP_RXDP_S_SEL_MASK |
+ REC_S_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ VODSP_LRCK_SEL_16K,
+ VODSP_LRCK_SEL_MASK);
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT, 0x0000, 0x0300);
+
+ /* Set input&output path and power */
+ /* Power on related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0xcc0f, 0xcc0f);
+
+ /* Power on related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2,
+ 0xa7cb, 0xa7cb);
+
+ /* Power on related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x3302, 0x3302);
+
+ /* Set Mic1 to differential mode */
+ alc5625_write(codec, ALC5625_MIC_VOL, 0x8808);
+
+ /*Mic boost 0db */
+ alc5625_write(codec, ALC5625_MIC_CTRL, 0x0000);
+
+ /*Mic1->ADCMixer_R */
+ alc5625_write(codec, ALC5625_ADC_REC_MIXER, 0x7f3f);
+
+ /*ADC_Mixer_R boost 10.5 db */
+ alc5625_write(codec, ALC5625_ADC_REC_GAIN, 0xCBD3);
+
+ /* Speaker out from spkMixer */
+ alc5625_write(codec, ALC5625_OUTPUT_MIXER_CTRL, 0x8808);
+
+ /* Unmute DAC to spkMixer */
+ alc5625_write(codec, ALC5625_DAC_AND_MIC_CTRL, 0xee0d);
+ alc5625_write(codec, ALC5625_STEREO_DAC_CLK_CTRL1, 0x3075);
+ alc5625_write(codec, ALC5625_STEREO_DAC_CLK_CTRL2, 0x1010);
+
+ /* Unmute speaker */
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL, 0x0000, 0x8080);
+
+ break;
+
+ case VODSP_AEC_DISABLE:
+ default:
+ /* Mute speaker out */
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL, 0x8080, 0x8080);
+
+ /* Mute auxout */
+ alc5625_write_mask(codec, ALC5625_AUX_OUT_VOL, 0x8080, 0x8080);
+
+ /* Mic boost 20db by default */
+ alc5625_write(codec, ALC5625_MIC_CTRL, 0x0500);
+
+ /* Record from Mic1 by default */
+ alc5625_write(codec, ALC5625_ADC_REC_MIXER, 0x3f3f);
+
+ /* ADC_Mixer_R boost 15 db by default */
+ alc5625_write(codec, ALC5625_ADC_REC_GAIN, 0xD5D5);
+
+ /* All output from HPmixer by default */
+ alc5625_write(codec, ALC5625_OUTPUT_MIXER_CTRL, 0x0748);
+
+ /* DAC to HPmixer by default */
+ alc5625_write(codec, ALC5625_DAC_AND_MIC_CTRL, 0xee03);
+
+ /* Mute VoDAC to mixer by default */
+ alc5625_write(codec, ALC5625_VOICE_DAC_OUT_VOL, 0xe010);
+
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT, 0x0000, 0x0300);
+
+ /* Set stereo DAC&Voice DAC&Stereo ADC function
+ * select to default
+ */
+ alc5625_write(codec, ALC5625_DAC_ADC_VODAC_FUN_SEL, 0);
+
+ /* Set VODSP&PDM Control to default */
+ alc5625_write(codec, ALC5625_VODSP_PDM_CTL, 0);
+
+ alc5625_write_mask(codec, ALC5625_PD_CTRL_STAT, 0x0000, 0x0300);
+
+ /* Power down related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x0000, 0xf312);
+
+ /* Power down related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0000, 0xcc8d);
+
+ /* Power down related bit */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2,
+ 0x0000, 0x07cf);
+ break;
+ }
+ return 0;
+}
+
+static int enable_vodsp_aec(struct snd_soc_codec *codec,
+ unsigned int enable_vodspAEC,
+ unsigned int aec_mode)
+{
+ int ret = 0;
+
+ if (enable_vodspAEC != 0) {
+ /* enable power of VODSP I2C interface & VODSP interface */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ PWR_VODSP_INTERFACE |
+ PWR_I2C_FOR_VODSP,
+ PWR_VODSP_INTERFACE |
+ PWR_I2C_FOR_VODSP);
+ /* enable power of VODSP I2S interface */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ PWR_I2S_INTERFACE,
+ PWR_I2S_INTERFACE);
+ /* select input/output of VODSP AEC */
+ set_vodsp_aec_path(codec, aec_mode);
+ } else {
+ /* disable VODSP AEC path */
+ set_vodsp_aec_path(codec, VODSP_AEC_DISABLE);
+ /* set VODSP AEC to power down mode */
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL, 0,
+ VODSP_NO_PD_MODE_ENA);
+ /* disable power of VODSP I2C interface & VODSP interface */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3, 0,
+ PWR_VODSP_INTERFACE |
+ PWR_I2C_FOR_VODSP);
+ }
+
+ return ret;
+}
+
+static void alc5625_aec_config(struct snd_soc_codec *codec, unsigned int mode)
+{
+ if (mode == VODSP_AEC_DISABLE) {
+ enable_vodsp_aec(codec, 0, mode);
+ /* disable LDO power */
+ alc5625_write_mask(codec, ALC5625_LDO_CTRL, 0, LDO_ENABLE);
+ } else {
+ init_vodsp_aec(codec);
+ enable_vodsp_aec(codec, 1, mode);
+ }
+}
+
+/* function:disable alc5625's function */
+static int alc5625_func_aec_disable(struct snd_soc_codec *codec, int mode)
+{
+ switch (mode) {
+ case ALC5625_AEC_PCM_IN_OUT:
+ case ALC5625_AEC_IIS_IN_OUT:
+ case ALC5625_AEC_ANALOG_IN_OUT:
+ /* disable AEC function and path */
+ alc5625_aec_config(codec, VODSP_AEC_DISABLE);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int alc5625_get_dsp_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ /* cause we choose bit[0][1] to store the mode type */
+ int mode = (alc5625_read(codec, virtual_reg_FOR_MISC_FUNC)) & 0x03;
+
+ ucontrol->value.integer.value[0] = mode;
+ return 0;
+}
+
+static int alc5625_set_dsp_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ u16 virtual_reg = alc5625_read(codec, virtual_reg_FOR_MISC_FUNC);
+ int alc5625_mode = (virtual_reg) & 0x03;
+
+ if (alc5625_mode == ucontrol->value.integer.value[0])
+ return 0;
+
+ switch (ucontrol->value.integer.value[0]) {
+ case ALC5625_AEC_PCM_IN_OUT:
+ /* enable AEC PCM in/out function and path */
+ alc5625_aec_config(codec, PCM_IN_PCM_OUT);
+ break;
+
+ case ALC5625_AEC_IIS_IN_OUT:
+ /* enable AEC IIS in/out function and path */
+ alc5625_aec_config(codec, DAC_IN_ADC_OUT);
+ break;
+
+ case ALC5625_AEC_ANALOG_IN_OUT:
+ /* enable AEC analog in/out function and path */
+ alc5625_aec_config(codec, ANALOG_IN_ANALOG_OUT);
+ break;
+
+ case ALC5625_AEC_DISABLE:
+ /* disable previous select function */
+ alc5625_func_aec_disable(codec, alc5625_mode);
+ break;
+
+ default:
+ break;
+ }
+
+ virtual_reg &= 0xfffc;
+ virtual_reg |= (ucontrol->value.integer.value[0]);
+ alc5625_write(codec, virtual_reg_FOR_MISC_FUNC, virtual_reg);
+
+ return 0;
+}
+
+static int alc5625_dump_dsp_reg(struct snd_soc_codec *codec)
+{
+ int i;
+
+ alc5625_write_mask(codec, ALC5625_VODSP_CTL,
+ VODSP_NO_PD_MODE_ENA,
+ VODSP_NO_PD_MODE_ENA);
+ for (i = 0; i < SET_VODSP_REG_INIT_NUM; i++)
+ alc5625_read_vodsp_reg(codec,
+ vodsp_aec_init_value[i].index);
+
+ return 0;
+}
+
+static int alc5625_dump_dsp_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int mode = alc5625_read(codec, virtual_reg_FOR_MISC_FUNC);
+
+ mode &= ~(0x01 << 8);
+ mode |= (ucontrol->value.integer.value[0] << 8);
+ alc5625_write(codec, virtual_reg_FOR_MISC_FUNC, mode);
+ alc5625_dump_dsp_reg(codec);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new alc5625_snd_ctrls[] = {
+ SOC_ENUM_EXT("alc5625 aec mode sel", alc5625_enum[0],
+ alc5625_get_dsp_mode, alc5625_set_dsp_mode),
+ SOC_ENUM("SPK Amp Type", alc5625_enum[1]),
+ SOC_ENUM("Left SPK Source", alc5625_enum[2]),
+ SOC_ENUM("SPK Amp Ratio", alc5625_enum[7]),
+ SOC_ENUM("Mic1 Boost", alc5625_enum[8]),
+ SOC_ENUM("Mic2 Boost", alc5625_enum[9]),
+ SOC_ENUM("Dmic Boost", alc5625_enum[10]),
+ SOC_ENUM("ADCR Func", alc5625_enum[11]),
+ SOC_DOUBLE("PCM Playback Volume", ALC5625_STEREO_DAC_VOL, 8, 0, 63, 1),
+ SOC_DOUBLE("LineIn Playback Volume", ALC5625_LINE_IN_VOL, 8, 0, 31, 1),
+ SOC_SINGLE("Phone Playback Volume", ALC5625_PHONEIN_VOL, 8, 31, 1),
+ SOC_SINGLE("Mic1 Playback Volume", ALC5625_MIC_VOL, 8, 31, 1),
+ SOC_SINGLE("Mic2 Playback Volume", ALC5625_MIC_VOL, 0, 31, 1),
+ SOC_DOUBLE("PCM Capture Volume", ALC5625_ADC_REC_GAIN, 8, 0, 31, 1),
+ SOC_DOUBLE("SPKOUT Playback Volume", ALC5625_SPK_OUT_VOL, 8, 0, 31, 1),
+ SOC_DOUBLE("SPKOUT Playback Switch", ALC5625_SPK_OUT_VOL, 15, 7, 1, 1),
+ SOC_DOUBLE("HPOUT Playback Volume", ALC5625_HP_OUT_VOL, 8, 0, 31, 1),
+ SOC_DOUBLE("HPOUT Playback Switch", ALC5625_HP_OUT_VOL, 15, 7, 1, 1),
+ SOC_DOUBLE("AUXOUT Playback Volume", ALC5625_AUX_OUT_VOL, 8, 0, 31, 1),
+ SOC_DOUBLE("AUXOUT Playback Switch", ALC5625_AUX_OUT_VOL, 15, 7, 1, 1),
+ SOC_DOUBLE("ADC Record Gain", ALC5625_ADC_REC_GAIN, 8, 0, 31, 0),
+ SOC_SINGLE_EXT("VoDSP Dump", virtual_reg_FOR_MISC_FUNC, 8, 1, 0,
+ snd_soc_get_volsw, alc5625_dump_dsp_put),
+};
+
+static void hp_depop_mode2(struct snd_soc_codec *codec)
+{
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ PWR_SOFTGEN_EN,
+ PWR_SOFTGEN_EN);
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL,
+ PWR_HP_R_OUT_VOL | PWR_HP_L_OUT_VOL);
+ alc5625_write(codec, ALC5625_MISC_CTRL, HP_DEPOP_MODE2_EN);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(500));
+
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ PWR_HP_OUT_AMP | PWR_HP_OUT_ENH_AMP,
+ PWR_HP_OUT_AMP | PWR_HP_OUT_ENH_AMP);
+
+}
+
+/* enable depop function for mute/unmute */
+static void hp_mute_unmute_depop(struct snd_soc_codec *codec, int mute)
+{
+ if (mute) {
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ PWR_SOFTGEN_EN,
+ PWR_SOFTGEN_EN);
+ alc5625_write(codec, ALC5625_MISC_CTRL,
+ M_UM_DEPOP_EN | HP_R_M_UM_DEPOP_EN |
+ HP_L_M_UM_DEPOP_EN);
+ /* Mute headphone right/left channel */
+ alc5625_write_mask(codec, ALC5625_HP_OUT_VOL,
+ ALC_L_MUTE|ALC_R_MUTE,
+ ALC_L_MUTE|ALC_R_MUTE);
+ mdelay(50);
+ } else {
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ PWR_SOFTGEN_EN,
+ PWR_SOFTGEN_EN);
+ alc5625_write(codec, ALC5625_MISC_CTRL,
+ M_UM_DEPOP_EN | HP_R_M_UM_DEPOP_EN |
+ HP_L_M_UM_DEPOP_EN);
+ /* unMute headphone right/left channel */
+ alc5625_write_mask(codec, ALC5625_HP_OUT_VOL, 0,
+ ALC_L_MUTE|ALC_R_MUTE);
+ mdelay(50);
+ }
+}
+
+/*
+ * _DAPM_ Controls
+ */
+/* Left ADC Rec mixer */
+static const struct snd_kcontrol_new alc5625_ctrl_adc_l[] = {
+ SOC_DAPM_SINGLE("Mic1 Capture Switch",
+ ALC5625_ADC_REC_MIXER, 14, 1, 1),
+ SOC_DAPM_SINGLE("Mic2 Capture Switch",
+ ALC5625_ADC_REC_MIXER, 13, 1, 1),
+ SOC_DAPM_SINGLE("LineIn Capture Switch",
+ ALC5625_ADC_REC_MIXER, 12, 1, 1),
+ SOC_DAPM_SINGLE("Phone Capture Switch",
+ ALC5625_ADC_REC_MIXER, 11, 1, 1),
+ SOC_DAPM_SINGLE("HP Mixer Capture Switch",
+ ALC5625_ADC_REC_MIXER, 10, 1, 1),
+ SOC_DAPM_SINGLE("SPK Mixer Capture Switch",
+ ALC5625_ADC_REC_MIXER, 9, 1, 1),
+ SOC_DAPM_SINGLE("MoNo Mixer Capture Switch",
+ ALC5625_ADC_REC_MIXER, 8, 1, 1),
+};
+
+/* Left ADC Rec mixer */
+static const struct snd_kcontrol_new alc5625_ctrl_adc_r[] = {
+ SOC_DAPM_SINGLE("Mic1 Capture Switch",
+ ALC5625_ADC_REC_MIXER, 6, 1, 1),
+ SOC_DAPM_SINGLE("Mic2 Capture Switch",
+ ALC5625_ADC_REC_MIXER, 5, 1, 1),
+ SOC_DAPM_SINGLE("LineIn Capture Switch",
+ ALC5625_ADC_REC_MIXER, 4, 1, 1),
+ SOC_DAPM_SINGLE("Phone Capture Switch",
+ ALC5625_ADC_REC_MIXER, 3, 1, 1),
+ SOC_DAPM_SINGLE("HP Mixer Capture Switch",
+ ALC5625_ADC_REC_MIXER, 2, 1, 1),
+ SOC_DAPM_SINGLE("SPK Mixer Capture Switch",
+ ALC5625_ADC_REC_MIXER, 1, 1, 1),
+ SOC_DAPM_SINGLE("MoNo Mixer Capture Switch",
+ ALC5625_ADC_REC_MIXER, 0, 1, 1),
+};
+
+/* Left hpmixer mixer */
+static const struct snd_kcontrol_new alc5625_ctrl_hp_l[] = {
+ SOC_DAPM_SINGLE("ADC Playback Switch",
+ ALC5625_ADC_REC_GAIN, 15, 1, 1),
+ SOC_DAPM_SINGLE("LineIn Playback Switch",
+ HPL_MIXER, 0, 1, 0),
+ SOC_DAPM_SINGLE("Phone Playback Switch",
+ HPL_MIXER, 1, 1, 0),
+ SOC_DAPM_SINGLE("Mic1 Playback Switch",
+ HPL_MIXER, 2, 1, 0),
+ SOC_DAPM_SINGLE("Mic2 Playback Switch",
+ HPL_MIXER, 3, 1, 0),
+ SOC_DAPM_SINGLE("Voice DAC Playback Switch",
+ HPL_MIXER, 4, 1, 0),
+ SOC_DAPM_SINGLE("HIFI DAC Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 3, 1, 1),
+};
+
+/* Right hpmixer mixer */
+static const struct snd_kcontrol_new alc5625_ctrl_hp_r[] = {
+ SOC_DAPM_SINGLE("ADC Playback Switch",
+ ALC5625_ADC_REC_GAIN, 7, 1, 1),
+ SOC_DAPM_SINGLE("LineIn Playback Switch",
+ HPR_MIXER, 0, 1, 0),
+ SOC_DAPM_SINGLE("Phone Playback Switch",
+ HPR_MIXER, 1, 1, 0),
+ SOC_DAPM_SINGLE("Mic1 Playback Switch",
+ HPR_MIXER, 2, 1, 0),
+ SOC_DAPM_SINGLE("Mic2 Playback Switch",
+ HPR_MIXER, 3, 1, 0),
+ SOC_DAPM_SINGLE("Voice DAC Playback Switch",
+ HPR_MIXER, 4, 1, 0),
+ SOC_DAPM_SINGLE("HIFI DAC Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 2, 1, 1),
+};
+
+/* mono mixer */
+static const struct snd_kcontrol_new alc5625_ctrl_mono[] = {
+ SOC_DAPM_SINGLE("ADCL Playback Switch",
+ ALC5625_ADC_REC_GAIN, 14, 1, 1),
+ SOC_DAPM_SINGLE("ADCR Playback Switch",
+ ALC5625_ADC_REC_GAIN, 6, 1, 1),
+ SOC_DAPM_SINGLE("Line Mixer Playback Switch",
+ ALC5625_LINE_IN_VOL, 13, 1, 1),
+ SOC_DAPM_SINGLE("Mic1 Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 13, 1, 1),
+ SOC_DAPM_SINGLE("Mic2 Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 9, 1, 1),
+ SOC_DAPM_SINGLE("DAC Mixer Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 0, 1, 1),
+ SOC_DAPM_SINGLE("Voice DAC Playback Switch",
+ ALC5625_VOICE_DAC_OUT_VOL, 13, 1, 1),
+};
+
+/* speaker mixer */
+static const struct snd_kcontrol_new alc5625_ctrl_spk[] = {
+ SOC_DAPM_SINGLE("Line Mixer Playback Switch",
+ ALC5625_LINE_IN_VOL, 14, 1, 1),
+ SOC_DAPM_SINGLE("Phone Playback Switch",
+ ALC5625_PHONEIN_VOL, 14, 1, 1),
+ SOC_DAPM_SINGLE("Mic1 Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 14, 1, 1),
+ SOC_DAPM_SINGLE("Mic2 Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 10, 1, 1),
+ SOC_DAPM_SINGLE("DAC Mixer Playback Switch",
+ ALC5625_DAC_AND_MIC_CTRL, 1, 1, 1),
+ SOC_DAPM_SINGLE("Voice DAC Playback Switch",
+ ALC5625_VOICE_DAC_OUT_VOL, 14, 1, 1),
+};
+
+static int mixer_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int l, r;
+
+ l = alc5625_read(codec, HPL_MIXER);
+ r = alc5625_read(codec, HPR_MIXER);
+
+ /* Mute/Unmute vol output to hp mixer */
+ if ((l & 0x1) || (r & 0x1))
+ alc5625_write_mask(codec, ALC5625_LINE_IN_VOL,
+ 0x0000, 0x8000);
+ else
+ alc5625_write_mask(codec, ALC5625_LINE_IN_VOL,
+ 0x8000, 0x8000);
+
+ /* Mute/Unmute phone input to hp mixer */
+ if ((l & 0x2) || (r & 0x2))
+ alc5625_write_mask(codec, ALC5625_PHONEIN_VOL,
+ 0x0000, 0x8000);
+ else
+ alc5625_write_mask(codec, ALC5625_PHONEIN_VOL,
+ 0x8000, 0x8000);
+
+ /* Mute/Unmute Mic1 vol output to hp mixer */
+ if ((l & 0x4) || (r & 0x4))
+ alc5625_write_mask(codec, ALC5625_DAC_AND_MIC_CTRL,
+ 0x0000, 0x8000);
+ else
+ alc5625_write_mask(codec, ALC5625_DAC_AND_MIC_CTRL,
+ 0x8000, 0x8000);
+
+ /* Mute/Unmute Mic2 vol output to hp mixer */
+ if ((l & 0x8) || (r & 0x8))
+ alc5625_write_mask(codec, ALC5625_DAC_AND_MIC_CTRL,
+ 0x0000, 0x0800);
+ else
+ alc5625_write_mask(codec, ALC5625_DAC_AND_MIC_CTRL,
+ 0x0800, 0x0800);
+
+ /* Mute/Unmute voice DAC vol to hp mixer */
+ if ((l & 0x10) || (r & 0x10))
+ alc5625_write_mask(codec, ALC5625_VOICE_DAC_OUT_VOL,
+ 0x0000, 0x8000);
+ else
+ alc5625_write_mask(codec, ALC5625_VOICE_DAC_OUT_VOL,
+ 0x8000, 0x8000);
+
+ return 0;
+}
+
+/*
+ * bit[0][1] use for aec control
+ * bit[2][3] for ADCR func
+ * bit[4] for SPKL pga
+ * bit[5] for SPKR pga
+ * bit[6] for hpl pga
+ * bit[7] for hpr pga
+ */
+static int spk_pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k,
+ int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int reg;
+
+ reg = alc5625_read(codec, virtual_reg_FOR_MISC_FUNC) & (0x3 << 4);
+ if (reg && (reg >> 4) != 0x3)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x3000, 0x3000);
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL,
+ 0x0000, 0x8080);
+ /* power on spk amp */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0400, 0x0400);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* power off spk amp */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0000, 0x0400);
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL,
+ 0x8080, 0x8080);
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x0000, 0x3000);
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+static int hp_pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int reg;
+
+ reg = alc5625_read(codec, virtual_reg_FOR_MISC_FUNC) & (0x3 << 6);
+ if (reg && (reg >> 6) != 0x3)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMD:
+ printk(KERN_DEBUG "ALC5625: Powering down.\n");
+ hp_mute_unmute_depop(codec, 1); /* mute hp */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0000, 0x0300);
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x0000, 0x0c00);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ printk(KERN_DEBUG "ALC5625: Powering on.\n");
+ hp_depop_mode2(codec);
+ hp_mute_unmute_depop(codec, 0); /* unmute hp */
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int aux_pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ return 0;
+}
+
+/* SPKOUT Mux */
+static const struct snd_kcontrol_new alc5625_ctrl_spkmux =
+ SOC_DAPM_ENUM("Route", alc5625_enum[3]);
+
+/* HPLOUT MUX */
+static const struct snd_kcontrol_new alc5625_ctrl_hplmux =
+ SOC_DAPM_ENUM("Route", alc5625_enum[4]);
+
+/* HPROUT MUX */
+static const struct snd_kcontrol_new alc5625_ctrl_hprmux =
+ SOC_DAPM_ENUM("Route", alc5625_enum[5]);
+/* AUXOUT MUX */
+static const struct snd_kcontrol_new alc5625_ctrl_auxmux =
+ SOC_DAPM_ENUM("Route", alc5625_enum[6]);
+
+static const struct snd_soc_dapm_widget alc5625_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("Left LineIn"),
+ SND_SOC_DAPM_INPUT("Right LineIn"),
+ SND_SOC_DAPM_INPUT("Phone"),
+ SND_SOC_DAPM_INPUT("Mic1"),
+ SND_SOC_DAPM_INPUT("Mic2"),
+
+ SND_SOC_DAPM_PGA("Mic1 Boost",
+ ALC5625_PWR_MANAG_ADD3, 1, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mic2 Boost",
+ ALC5625_PWR_MANAG_ADD3, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback DAC",
+ ALC5625_PWR_MANAG_ADD2, 9, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback DAC",
+ ALC5625_PWR_MANAG_ADD2, 8, 0),
+ SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback DAC",
+ ALC5625_PWR_MANAG_ADD2, 10, 0),
+ SND_SOC_DAPM_PGA("Left LineIn PGA",
+ ALC5625_PWR_MANAG_ADD3,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right LineIn PGA",
+ ALC5625_PWR_MANAG_ADD3, 6, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Phone PGA",
+ ALC5625_PWR_MANAG_ADD3, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mic1 PGA",
+ ALC5625_PWR_MANAG_ADD3, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mic2 PGA",
+ ALC5625_PWR_MANAG_ADD3, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("VoDAC PGA",
+ ALC5625_PWR_MANAG_ADD1, 7, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Left Rec Mixer",
+ ALC5625_PWR_MANAG_ADD2, 1, 0,
+ &alc5625_ctrl_adc_l[0],
+ ARRAY_SIZE(alc5625_ctrl_adc_l)),
+ SND_SOC_DAPM_MIXER("Right Rec Mixer",
+ ALC5625_PWR_MANAG_ADD2, 0, 0,
+ &alc5625_ctrl_adc_r[0],
+ ARRAY_SIZE(alc5625_ctrl_adc_r)),
+ SND_SOC_DAPM_MIXER_E("Left HP Mixer",
+ ALC5625_PWR_MANAG_ADD2, 5, 0,
+ &alc5625_ctrl_hp_l[0],
+ ARRAY_SIZE(alc5625_ctrl_hp_l),
+ mixer_event, SND_SOC_DAPM_POST_REG),
+ SND_SOC_DAPM_MIXER_E("Right HP Mixer",
+ ALC5625_PWR_MANAG_ADD2, 4, 0,
+ &alc5625_ctrl_hp_r[0],
+ ARRAY_SIZE(alc5625_ctrl_hp_r),
+ mixer_event, SND_SOC_DAPM_POST_REG),
+ SND_SOC_DAPM_MIXER("MoNo Mixer",
+ ALC5625_PWR_MANAG_ADD2, 2, 0,
+ &alc5625_ctrl_mono[0],
+ ARRAY_SIZE(alc5625_ctrl_mono)),
+ SND_SOC_DAPM_MIXER("SPK Mixer",
+ ALC5625_PWR_MANAG_ADD2, 3, 0,
+ &alc5625_ctrl_spk[0],
+ ARRAY_SIZE(alc5625_ctrl_spk)),
+ SND_SOC_DAPM_MIXER("HP Mixer",
+ SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("DAC Mixer",
+ SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("Line Mixer",
+ SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("SPKOUT Mux",
+ SND_SOC_NOPM, 0, 0,
+ &alc5625_ctrl_spkmux),
+ SND_SOC_DAPM_MUX("HPLOUT Mux",
+ SND_SOC_NOPM, 0, 0,
+ &alc5625_ctrl_hplmux),
+ SND_SOC_DAPM_MUX("HPROUT Mux",
+ SND_SOC_NOPM, 0, 0,
+ &alc5625_ctrl_hprmux),
+ SND_SOC_DAPM_MUX("AUXOUT Mux",
+ SND_SOC_NOPM, 0, 0,
+ &alc5625_ctrl_auxmux),
+ SND_SOC_DAPM_PGA_E("SPKL Out PGA",
+ virtual_reg_FOR_MISC_FUNC, 4, 0,
+ NULL, 0, spk_pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("SPKR Out PGA",
+ virtual_reg_FOR_MISC_FUNC, 5, 0,
+ NULL, 0, spk_pga_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("HPL Out PGA",
+ virtual_reg_FOR_MISC_FUNC, 6, 0,
+ NULL, 0, hp_pga_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("HPR Out PGA",
+ virtual_reg_FOR_MISC_FUNC, 7, 0,
+ NULL, 0, hp_pga_event,
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("AUX Out PGA",
+ ALC5625_PWR_MANAG_ADD3, 14, 0,
+ NULL, 0, aux_pga_event,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_ADC("Left ADC", "Left ADC HiFi Capture",
+ ALC5625_PWR_MANAG_ADD2, 7, 0),
+ SND_SOC_DAPM_ADC("Right ADC", "Right ADC HiFi Capture",
+ ALC5625_PWR_MANAG_ADD2, 6, 0),
+ SND_SOC_DAPM_OUTPUT("SPKL"),
+ SND_SOC_DAPM_OUTPUT("SPKR"),
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+ SND_SOC_DAPM_OUTPUT("AUX"),
+ SND_SOC_DAPM_MICBIAS("Mic1 Bias",
+ ALC5625_PWR_MANAG_ADD1, 3, 0),
+ SND_SOC_DAPM_MICBIAS("Mic2 Bias",
+ ALC5625_PWR_MANAG_ADD1, 2, 0),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ /* Input PGA */
+ {"Left LineIn PGA", NULL, "Left LineIn"},
+ {"Right LineIn PGA", NULL, "Right LineIn"},
+ {"Phone PGA", NULL, "Phone"},
+ {"Mic1 Boost", NULL, "Mic1"},
+ {"Mic2 Boost", NULL, "Mic2"},
+ {"Mic1 PGA", NULL, "Mic1"},
+ {"Mic2 PGA", NULL, "Mic2"},
+ {"VoDAC PGA", NULL, "Voice DAC"},
+
+ /* Left ADC mixer */
+ {"Left Rec Mixer", "LineIn Capture Switch", "Left LineIn"},
+ {"Left Rec Mixer", "Phone Capture Switch", "Phone"},
+ {"Left Rec Mixer", "Mic1 Capture Switch", "Mic1 Boost"},
+ {"Left Rec Mixer", "Mic2 Capture Switch", "Mic2 Boost"},
+ {"Left Rec Mixer", "HP Mixer Capture Switch", "Left HP Mixer"},
+ {"Left Rec Mixer", "SPK Mixer Capture Switch", "SPK Mixer"},
+ {"Left Rec Mixer", "MoNo Mixer Capture Switch", "MoNo Mixer"},
+
+ /* Right ADC Mixer */
+ {"Right Rec Mixer", "LineIn Capture Switch", "Right LineIn"},
+ {"Right Rec Mixer", "Phone Capture Switch", "Phone"},
+ {"Right Rec Mixer", "Mic1 Capture Switch", "Mic1 Boost"},
+ {"Right Rec Mixer", "Mic2 Capture Switch", "Mic2 Boost"},
+ {"Right Rec Mixer", "HP Mixer Capture Switch", "Right HP Mixer"},
+ {"Right Rec Mixer", "SPK Mixer Capture Switch", "SPK Mixer"},
+ {"Right Rec Mixer", "MoNo Mixer Capture Switch", "MoNo Mixer"},
+
+ /* HPL mixer */
+ {"Left HP Mixer", "ADC Playback Switch", "Left Rec Mixer"},
+ {"Left HP Mixer", "LineIn Playback Switch", "Left LineIn PGA"},
+ {"Left HP Mixer", "Phone Playback Switch", "Phone PGA"},
+ {"Left HP Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+ {"Left HP Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+ {"Left HP Mixer", "HIFI DAC Playback Switch", "Left DAC"},
+ {"Left HP Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+
+ /* HPR mixer */
+ {"Right HP Mixer", "ADC Playback Switch", "Right Rec Mixer"},
+ {"Right HP Mixer", "LineIn Playback Switch", "Right LineIn PGA"},
+ {"Right HP Mixer", "HIFI DAC Playback Switch", "Right DAC"},
+ {"Right HP Mixer", "Phone Playback Switch", "Phone PGA"},
+ {"Right HP Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+ {"Right HP Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+ {"Right HP Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+
+ /* DAC Mixer */
+ {"DAC Mixer", NULL, "Left DAC"},
+ {"DAC Mixer", NULL, "Right DAC"},
+
+ /* line mixer */
+ {"Line Mixer", NULL, "Left LineIn PGA"},
+ {"Line Mixer", NULL, "Right LineIn PGA"},
+
+ /* spk mixer */
+ {"SPK Mixer", "Line Mixer Playback Switch", "Line Mixer"},
+ {"SPK Mixer", "Phone Playback Switch", "Phone PGA"},
+ {"SPK Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+ {"SPK Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+ {"SPK Mixer", "DAC Mixer Playback Switch", "DAC Mixer"},
+ {"SPK Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+
+ /* mono mixer */
+ {"MoNo Mixer", "Line Mixer Playback Switch", "Line Mixer"},
+ {"MoNo Mixer", "ADCL Playback Switch", "Left Rec Mixer"},
+ {"MoNo Mixer", "ADCR Playback Switch", "Right Rec Mixer"},
+ {"MoNo Mixer", "Mic1 Playback Switch", "Mic1 PGA"},
+ {"MoNo Mixer", "Mic2 Playback Switch", "Mic2 PGA"},
+ {"MoNo Mixer", "DAC Mixer Playback Switch", "DAC Mixer"},
+ {"MoNo Mixer", "Voice DAC Playback Switch", "VoDAC PGA"},
+
+ /* hp mixer */
+ {"HP Mixer", NULL, "Left HP Mixer"},
+ {"HP Mixer", NULL, "Right HP Mixer"},
+
+ /* spkout mux */
+ {"SPKOUT Mux", "HP Mixer", "HP Mixer"},
+ {"SPKOUT Mux", "SPK Mixer", "SPK Mixer"},
+ {"SPKOUT Mux", "Mono Mixer", "MoNo Mixer"},
+
+ /* hpl out mux */
+ {"HPLOUT Mux", "HPL Mixer", "Left HP Mixer"},
+
+ /* hpr out mux */
+ {"HPROUT Mux", "HPR Mixer", "Right HP Mixer"},
+
+ /* aux out mux */
+ {"AUXOUT Mux", "HP Mixer", "HP Mixer"},
+ {"AUXOUT Mux", "SPK Mixer", "SPK Mixer"},
+ {"SPKOUT Mux", "Mono Mixer", "MoNo Mixer"},
+
+ /* spkl out pga */
+ {"SPKL Out PGA", NULL, "SPKOUT Mux"},
+
+ /* spkr out pga */
+ {"SPKR Out PGA", NULL, "SPKOUT Mux"},
+
+ /* hpl out pga */
+ {"HPL Out PGA", NULL, "HPLOUT Mux"},
+
+ /* hpr out pga */
+ {"HPR Out PGA", NULL, "HPROUT Mux"},
+
+ /* aux out pga */
+ {"AUX Out PGA", NULL, "AUXOUT Mux"},
+
+ /* left adc */
+ {"Left ADC", NULL, "Left Rec Mixer"},
+
+ /* right adc */
+ {"Right ADC", NULL, "Right Rec Mixer"},
+
+ /* output */
+ {"SPKL", NULL, "SPKL Out PGA"},
+ {"SPKR", NULL, "SPKR Out PGA"},
+ {"HPL", NULL, "HPL Out PGA"},
+ {"HPR", NULL, "HPR Out PGA"},
+ {"AUX", NULL, "AUX Out PGA"},
+};
+
+static int alc5625_add_widgets(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(dapm, alc5625_dapm_widgets,
+ ARRAY_SIZE(alc5625_dapm_widgets));
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct _pll_div {
+ u32 pll_in;
+ u32 pll_out;
+ u16 regvalue;
+};
+
+/*
+ * watch out!
+ * our codec support you to select different source as pll input,
+ * but if you use both of the I2S audio interface and pcm interface
+ * instantially. The two DAI must have the same pll setting params,
+ * so you have to offer the same pll input, and set our codec's sysclk
+ * the same one, we suggest 24576000.
+ */
+static const struct _pll_div codec_master_pll1_div[] = {
+ { 2048000, 8192000, 0x0ea0},
+ { 3686400, 8192000, 0x4e27},
+ {12000000, 8192000, 0x456b},
+ {13000000, 8192000, 0x495f},
+ {13100000, 8192000, 0x0320},
+ { 2048000, 11289600, 0xf637},
+ { 3686400, 11289600, 0x2f22},
+ {12000000, 11289600, 0x3e2f},
+ {13000000, 11289600, 0x4d5b},
+ {13100000, 11289600, 0x363b},
+ { 2048000, 16384000, 0x1ea0},
+ { 3686400, 16384000, 0x9e27},
+ {12000000, 16384000, 0x452b},
+ {13000000, 16384000, 0x542f},
+ {13100000, 16384000, 0x03a0},
+ { 2048000, 16934400, 0xe625},
+ { 3686400, 16934400, 0x9126},
+ {12000000, 16934400, 0x4d2c},
+ {13000000, 16934400, 0x742f},
+ {13100000, 16934400, 0x3c27},
+ { 2048000, 22579200, 0x2aa0},
+ { 3686400, 22579200, 0x2f20},
+ {12000000, 22579200, 0x7e2f},
+ {13000000, 22579200, 0x742f},
+ {13100000, 22579200, 0x3c27},
+ { 2048000, 24576000, 0x2ea0},
+ { 3686400, 24576000, 0xee27},
+ {12000000, 24576000, 0x2915},
+ {13000000, 24576000, 0x772e},
+ {13100000, 24576000, 0x0d20},
+ {26000000, 24576000, 0x2027},
+ {26000000, 22579200, 0x392f},
+ {24576000, 22579200, 0x0921},
+ {24576000, 24576000, 0x02a0},
+};
+
+static const struct _pll_div codec_bclk_pll1_div[] = {
+ { 256000, 4096000, 0x3ea0},
+ { 352800, 5644800, 0x3ea0},
+ { 512000, 8192000, 0x3ea0},
+ { 705600, 11289600, 0x3ea0},
+ {1024000, 16384000, 0x3ea0},
+ {1411200, 22579200, 0x3ea0},
+ {1536000, 24576000, 0x3ea0},
+ {2048000, 16384000, 0x1ea0},
+ {2822400, 22579200, 0x1ea0},
+ {3072000, 24576000, 0x1ea0},
+ { 705600, 11289600, 0x3ea0},
+ { 705600, 8467200, 0x3ab0},
+};
+
+static const struct _pll_div codec_vbclk_pll1_div[] = {
+ { 256000, 4096000, 0x3ea0},
+ { 352800, 5644800, 0x3ea0},
+ { 512000, 8192000, 0x3ea0},
+ { 705600, 11289600, 0x3ea0},
+ {1024000, 16384000, 0x3ea0},
+ {1411200, 22579200, 0x3ea0},
+ {1536000, 24576000, 0x3ea0},
+ {2048000, 16384000, 0x1ea0},
+ {2822400, 22579200, 0x1ea0},
+ {3072000, 24576000, 0x1ea0},
+ { 705600, 11289600, 0x3ea0},
+ { 705600, 8467200, 0x3ab0},
+};
+
+struct _coeff_div_stereo {
+ unsigned int mclk;
+ unsigned int rate;
+ unsigned int reg60;
+ unsigned int reg62;
+};
+
+struct _coeff_div_voice {
+ unsigned int mclk;
+ unsigned int rate;
+ unsigned int reg64;
+};
+
+static const struct _coeff_div_stereo coeff_div_stereo[] = {
+ /*
+ * bclk is config to 32fs, if codec is choose to
+ * be slave mode , input bclk should be 32*fs
+ */
+ {24576000, 48000, 0x3174, 0x1010},
+ {12288000, 48000, 0x1174, 0x0000},
+ {18432000, 48000, 0x2174, 0x1111},
+ {36864000, 48000, 0x2274, 0x2020},
+ {49152000, 48000, 0xf074, 0x3030},
+ {24576000, 48000, 0x3172, 0x1010},
+ {24576000, 8000, 0xB274, 0x2424},
+ {24576000, 16000, 0xB174, 0x2222},
+ {24576000, 32000, 0xB074, 0x2121},
+ {22579200, 11025, 0X3374, 0x1414},
+ {22579200, 22050, 0X3274, 0x1212},
+ {22579200, 44100, 0X3174, 0x1010},
+ {0, 0, 0, 0},
+};
+
+static const struct _coeff_div_voice coeff_div_voice[] = {
+ /*
+ * bclk is config to 32fs, if codec is choose to be slave mode,
+ * input bclk should be 32*fs
+ */
+ {24576000, 16000, 0x2622},
+ {24576000, 8000, 0x2824},
+ {0, 0, 0},
+};
+
+static int get_coeff(unsigned int mclk, unsigned int rate, int mode)
+{
+ int i;
+
+ if (!mode) {
+ for (i = 0; i < ARRAY_SIZE(coeff_div_stereo); i++) {
+ if ((coeff_div_stereo[i].rate == rate) &&
+ (coeff_div_stereo[i].mclk == mclk))
+ return i;
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(coeff_div_voice); i++) {
+ if ((coeff_div_voice[i].rate == rate) &&
+ (coeff_div_voice[i].mclk == mclk))
+ return i;
+ }
+ }
+
+ return -EINVAL;
+ printk(KERN_ERR "can't find a matched mclk and rate in %s\n",
+ (mode ? "coeff_div_voice[]" : "coeff_div_audio[]"));
+}
+
+static int alc5625_codec_set_dai_pll(struct snd_soc_dai *codec_dai,
+ int pll_id, int source,
+ unsigned int freq_in,
+ unsigned int freq_out)
+{
+ int i;
+ int pll_src_regval = 0;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ const struct _pll_div *codec_pll_div = NULL;
+ int pll_div_count = 0;
+
+ if (pll_id < ALC5625_PLL1_FROM_MCLK || pll_id > ALC5625_PLL1_FROM_VBCLK)
+ return -EINVAL;
+
+ if (!freq_in || !freq_out)
+ return 0;
+
+ switch (pll_id) {
+ case ALC5625_PLL1_FROM_MCLK:
+ codec_pll_div = codec_master_pll1_div;
+ pll_div_count = ARRAY_SIZE(codec_master_pll1_div);
+ break;
+ case ALC5625_PLL1_FROM_BCLK:
+ codec_pll_div = codec_bclk_pll1_div;
+ pll_div_count = ARRAY_SIZE(codec_bclk_pll1_div);
+ pll_src_regval = 0x2000;
+ break;
+ case ALC5625_PLL1_FROM_VBCLK:
+ codec_pll_div = codec_vbclk_pll1_div;
+ pll_div_count = ARRAY_SIZE(codec_vbclk_pll1_div);
+ pll_src_regval = 0x3000;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < pll_div_count; i++)
+ if ((freq_in == codec_pll_div[i].pll_in) &&
+ (freq_out == codec_pll_div[i].pll_out)) {
+ alc5625_write(codec,
+ ALC5625_GEN_CTRL_REG2,
+ pll_src_regval);
+
+ /* set pll code */
+ alc5625_write(codec,
+ ALC5625_PLL_CTRL,
+ codec_pll_div[i].regvalue);
+
+ /* enable pll power */
+ alc5625_write_mask(codec,
+ ALC5625_PWR_MANAG_ADD2,
+ 0x8000, 0x8000);
+
+ alc5625_write_mask(codec,
+ ALC5625_GEN_CTRL_REG1,
+ 0x8000, 0x8000);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int alc5625_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq,
+ int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct alc5625_priv *alc5625 = snd_soc_codec_get_drvdata(codec);
+
+ if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+ alc5625->stereo_sysclk = freq;
+ return 0;
+ }
+
+ printk(KERN_ERR "unsupported sysclk freq %u for audio i2s\n", freq);
+ alc5625->stereo_sysclk = DEFAULT_SYSCLK;
+
+ return 0;
+}
+
+static int alc5625_voice_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq,
+ int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct alc5625_priv *alc5625 = snd_soc_codec_get_drvdata(codec);
+
+ if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
+ alc5625->voice_sysclk = freq;
+ return 0;
+ }
+
+ printk(KERN_ERR "unsupported sysclk freq %u for voice pcm\n", freq);
+ alc5625->voice_sysclk = DEFAULT_SYSCLK;
+
+ return 0;
+}
+
+static int alc5625_hifi_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct alc5625_priv *alc5625 = snd_soc_codec_get_drvdata(codec);
+ unsigned int iface;
+
+ int rate = params_rate(params);
+ int coeff = get_coeff(alc5625->stereo_sysclk, rate, 0);
+
+ iface = alc5625_read(codec, ALC5625_MAIN_SDP_CTRL) & 0xfff3;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* Nothing to be done */
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= 0x0004;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= 0x0008;
+ break;
+ case SNDRV_PCM_FORMAT_S8:
+ iface |= 0x000c;
+ }
+
+ alc5625_write(codec, ALC5625_MAIN_SDP_CTRL, iface);
+
+ /* power i2s and dac ref */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0xc801, 0xc801);
+ if (coeff >= 0) {
+ alc5625_write(codec, ALC5625_STEREO_DAC_CLK_CTRL1,
+ coeff_div_stereo[coeff].reg60);
+ alc5625_write(codec, ALC5625_STEREO_DAC_CLK_CTRL2,
+ coeff_div_stereo[coeff].reg62);
+ }
+
+ return 0;
+}
+
+static int alc5625_voice_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct alc5625_priv *alc5625 = snd_soc_codec_get_drvdata(codec);
+ unsigned int iface;
+ int rate = params_rate(params);
+ int coeff = get_coeff(alc5625->voice_sysclk, rate, 1);
+
+ iface = alc5625_read(codec, ALC5625_EXTEND_SDP_CTRL) & 0xfff3;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* Nothing to be done */
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= 0x0004;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= 0x0008;
+ break;
+ case SNDRV_PCM_FORMAT_S8:
+ iface |= 0x000c;
+ }
+
+ /* power i2s and dac ref */
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0801, 0x0801);
+ alc5625_write(codec, ALC5625_EXTEND_SDP_CTRL, iface);
+ if (coeff >= 0)
+ alc5625_write(codec, ALC5625_VOICE_DAC_PCMCLK_CTRL1,
+ coeff_div_voice[coeff].reg64);
+
+ return 0;
+}
+
+static int alc5625_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = 0;
+
+ /* set master/slave interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface = 0x0000;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ iface = 0x8000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ /* Nothing to be done */
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= 0x0001;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= 0x0002;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= 0x0003;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ /* Nothing to be done */
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x0080;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ alc5625_write(codec, ALC5625_MAIN_SDP_CTRL, iface);
+ return 0;
+}
+
+static int alc5625_voice_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int iface;
+
+ /*set slave/master mode*/
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface = 0x0000;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ iface = 0x4000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ /* Nothing to be done */
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= 0x0001;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= 0x0002;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= 0x0003;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*clock inversion*/
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ /* Nothing to be done */
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= 0x0080;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ iface |= 0x8000; /* enable vopcm */
+ alc5625_write(codec, ALC5625_EXTEND_SDP_CTRL, iface);
+ return 0;
+}
+
+static int alc5625_hifi_codec_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (mute)
+ alc5625_write_mask(codec, ALC5625_STEREO_DAC_VOL,
+ 0x8080, 0x8080);
+ else
+ alc5625_write_mask(codec, ALC5625_STEREO_DAC_VOL,
+ 0x0000, 0x8080);
+ return 0;
+}
+
+static int alc5625_voice_codec_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (mute)
+ alc5625_write_mask(codec, ALC5625_VOICE_DAC_OUT_VOL,
+ 0x1000, 0x1000);
+ else
+ alc5625_write_mask(codec, ALC5625_VOICE_DAC_OUT_VOL,
+ 0x0000, 0x1000);
+ return 0;
+}
+
+static int alc5625_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:
+ alc5625_write(codec, ALC5625_PD_CTRL_STAT, 0x0000);
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD2,
+ 0x2000, 0x2000);
+ alc5625_write_mask(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x000e, 0x000e);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ break;
+ case SND_SOC_BIAS_OFF:
+ alc5625_write_mask(codec,
+ ALC5625_HP_OUT_VOL, 0x8080, 0x8080); /* mute hp */
+ alc5625_write_mask(codec, ALC5625_SPK_OUT_VOL,
+ 0x8080, 0x8080); /* mute spk */
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD3,
+ 0x0000); /* power off all bit */
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD1,
+ 0x0000); /* power off all bit */
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD2,
+ 0x0000); /* power off all bit */
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+
+#define ALC5625_STEREO_RATES SNDRV_PCM_RATE_8000_48000
+
+#define ALC5626_VOICE_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_8000)
+
+#define ALC5625_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops alc5625_dai_ops_hifi = {
+
+ .hw_params = alc5625_hifi_pcm_hw_params,
+ .set_fmt = alc5625_hifi_codec_set_dai_fmt,
+ .set_pll = alc5625_codec_set_dai_pll,
+ .set_sysclk = alc5625_hifi_codec_set_dai_sysclk,
+ .digital_mute = alc5625_hifi_codec_mute,
+};
+
+static struct snd_soc_dai_ops alc5625_dai_ops_voice = {
+
+ .hw_params = alc5625_voice_pcm_hw_params,
+ .set_fmt = alc5625_voice_codec_set_dai_fmt,
+ .set_pll = alc5625_codec_set_dai_pll,
+ .set_sysclk = alc5625_voice_codec_set_dai_sysclk,
+ .digital_mute = alc5625_voice_codec_mute,
+};
+
+static struct snd_soc_dai_driver alc5625_dai[] = {
+ {
+ .name = "alc5625-aif1",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = ALC5625_STEREO_RATES,
+ .formats = ALC5625_FORMATS,
+ },
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = ALC5625_STEREO_RATES,
+ .formats = ALC5625_FORMATS,
+ },
+ .ops = &alc5625_dai_ops_hifi,
+ },
+
+ /* voice codec dai */
+ {
+ .name = "ALC5625 Voice",
+ .id = 1,
+ .playback = {
+ .stream_name = "Voice Playback",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = ALC5626_VOICE_RATES,
+ .formats = ALC5625_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Voice Capture",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = ALC5626_VOICE_RATES,
+ .formats = ALC5625_FORMATS,
+ },
+
+ .ops = &alc5625_dai_ops_voice,
+
+ },
+};
+
+static void alc5625_work(struct work_struct *work)
+{
+ struct snd_soc_codec *codec =
+ container_of(work, struct snd_soc_codec,\
+ dapm.delayed_work.work);
+ alc5625_set_bias_level(codec, codec->dapm.bias_level);
+}
+
+
+static int alc5625_codec_init(struct snd_soc_codec *codec)
+{
+
+ int ret = 0;
+
+ codec->read = alc5625_read;
+ codec->write = alc5625_write;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ codec->num_dai = 2;
+ codec->reg_cache = kmemdup(alc5625_reg, sizeof(alc5625_reg),
+ GFP_KERNEL);
+ if (codec->reg_cache == NULL)
+ return -ENOMEM;
+
+ alc5625_reset(codec);
+
+ alc5625_write(codec, ALC5625_PD_CTRL_STAT, 0);
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS);
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD2, PWR_MIXER_VREF);
+ alc5625_reg_init(codec);
+ alc5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+ codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
+ schedule_delayed_work(&codec->dapm.delayed_work, msecs_to_jiffies(80));
+
+ ret = snd_soc_add_codec_controls(codec, alc5625_snd_ctrls,
+ ARRAY_SIZE(alc5625_snd_ctrls));
+ if (ret)
+ return ret;
+ alc5625_add_widgets(codec);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int alc5625_suspend(struct snd_soc_codec *codec)
+{
+ alc5625_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int alc5625_resume(struct snd_soc_codec *codec)
+{
+ alc5625_reset(codec);
+ alc5625_write(codec, ALC5625_PD_CTRL_STAT, 0);
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD1, PWR_MAIN_BIAS);
+ alc5625_write(codec, ALC5625_PWR_MANAG_ADD2, PWR_MIXER_VREF);
+ alc5625_reg_init(codec);
+
+ /* charge alc5625 caps */
+ if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
+ alc5625_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+ codec->dapm.bias_level = SND_SOC_BIAS_ON;
+ schedule_delayed_work(&codec->dapm.delayed_work,
+ msecs_to_jiffies(100));
+ }
+
+ return 0;
+}
+#else
+#define alc5625_suspend NULL
+#define alc5625_resume NULL
+#endif
+
+static int alc5625_probe(struct snd_soc_codec *codec)
+{
+ struct alc5625_priv *alc5625 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ codec->control_data = alc5625->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5625->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ mutex_init(&codec->mutex);
+ INIT_DELAYED_WORK(&codec->dapm.delayed_work, alc5625_work);
+
+ ret = alc5625_codec_init(codec);
+
+ return ret;
+}
+
+static int run_delayed_work(struct delayed_work *dwork)
+{
+ int ret;
+
+ /* cancel any work waiting to be queued. */
+ ret = cancel_delayed_work(dwork);
+
+ /* if there was any work waiting then we run it now and
+ * wait for it's completion */
+ if (ret) {
+ schedule_delayed_work(dwork, 0);
+ flush_scheduled_work();
+ }
+ return ret;
+}
+
+static int alc5625_remove(struct snd_soc_codec *codec)
+{
+ if (codec->control_data)
+ alc5625_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ run_delayed_work(&codec->dapm.delayed_work);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_alc5625 = {
+ .probe = alc5625_probe,
+ .remove = alc5625_remove,
+ .suspend = alc5625_suspend,
+ .resume = alc5625_resume,
+ .read = alc5625_read,
+ .write = alc5625_write,
+ .set_bias_level = alc5625_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(alc5625_reg)*2,
+ .reg_cache_default = alc5625_reg,
+ .reg_word_size = 2,
+};
+
+static const struct regmap_config alc5625_i2c_regmap_config = {
+ .val_bits = 16,
+ .reg_bits = 8,
+};
+
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int alc5625_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct alc5625_priv *alc5625;
+ int ret;
+
+ alc5625 = kzalloc(sizeof(struct alc5625_priv), GFP_KERNEL);
+ if (alc5625 == NULL)
+ return -ENOMEM;
+
+ alc5625->regmap = regmap_init_i2c(i2c, &alc5625_i2c_regmap_config);
+ if (IS_ERR(alc5625->regmap)) {
+ ret = PTR_ERR(alc5625->regmap);
+ goto err_free;
+ }
+
+ i2c_set_clientdata(i2c, alc5625);
+ alc5625->control_data = i2c;
+ alc5625->control_type = SND_SOC_REGMAP;
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_alc5625,
+ alc5625_dai, ARRAY_SIZE(alc5625_dai));
+
+ if (ret < 0)
+ goto err_regmap;
+
+ return ret;
+
+err_regmap:
+ regmap_exit(alc5625->regmap);
+err_free:
+ if (ret < 0)
+ kfree(alc5625);
+ return ret;
+}
+
+static __devexit int alc5625_i2c_remove(struct i2c_client *client)
+{
+ struct alc5625_priv *alc5625 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(alc5625->regmap);
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static const struct i2c_device_id alc5625_i2c_id[] = {
+ { "alc5625", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, alc5625_i2c_id);
+
+static const struct of_device_id alc5625_of_match[] = {
+ { .compatible = "realtek,alc5625", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, alc5625_of_match);
+
+static struct i2c_driver alc5625_i2c_driver = {
+ .driver = {
+ .name = "alc5625-codec",
+ .owner = THIS_MODULE,
+ .of_match_table = alc5625_of_match,
+ },
+ .probe = alc5625_i2c_probe,
+ .remove = __devexit_p(alc5625_i2c_remove),
+ .id_table = alc5625_i2c_id,
+};
+#endif
+
+module_i2c_driver(alc5625_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC ALC5625 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/alc5625/alc5625.h b/drivers/staging/alc5625/alc5625.h
new file mode 100644
index 00000000000..5e02a36d91e
--- /dev/null
+++ b/drivers/staging/alc5625/alc5625.h
@@ -0,0 +1,865 @@
+/*
+ * alc5625.h -- Header file for ALC5625 ALSA SoC Audio driver
+ *
+ * Copyright (C) 2011 Insignal Co., Ltd.
+ *
+ * Author: Pan<pan@insginal.co.kr>
+ *
+ * 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 _ALC5625_H
+#define _ALC5625_H
+
+#define ALC5625_RESET 0X00 /* RESET CODEC TO DEFAULT */
+#define ALC5625_SPK_OUT_VOL 0X02 /* SPEAKER OUT VOLUME */
+#define ALC5625_HP_OUT_VOL 0X04 /* HEADPHONE OUTPUT VOLUME */
+#define ALC5625_AUX_OUT_VOL 0X06 /* AUXOUT VOLUME */
+#define ALC5625_PHONEIN_VOL 0X08 /* PHONE INPUT VOLUME */
+#define ALC5625_LINE_IN_VOL 0X0A /* LINE IN VOLUME */
+#define ALC5625_STEREO_DAC_VOL 0X0C /* STEREO DAC VOLUME */
+#define ALC5625_MIC_VOL 0X0E /* MICROPHONE VOLUME */
+
+/* STEREO DAC AND MIC ROUTING CONTROL */
+#define ALC5625_DAC_AND_MIC_CTRL 0X10
+#define ALC5625_ADC_REC_GAIN 0X12 /* ADC RECORD GAIN */
+#define ALC5625_ADC_REC_MIXER 0X14 /* ADC RECORD MIXER CONTROL */
+#define ALC5625_VOICE_DAC_OUT_VOL 0X18 /* VOICE DAC OUTPUT VOLUME */
+#define ALC5625_VODSP_PDM_CTL 0X1A /* VODSP & PDM CONTROL */
+#define ALC5625_OUTPUT_MIXER_CTRL 0X1C /* OUTPUT MIXER CONTROL */
+#define ALC5625_VODSP_CTL 0X1E /* VODSP CONTROL */
+#define ALC5625_MIC_CTRL 0X22 /* MICROPHONE CONTROL */
+#define ALC5625_DMIC_CTRL 0x24
+#define ALC5625_PD_CTRL_STAT 0X26 /* POWER DOWN CONTROL/STATUS */
+
+/* STEREO DAC,VOICE DAC,STEREO ADC FUNCTION SELECT */
+#define ALC5625_DAC_ADC_VODAC_FUN_SEL 0X2E
+
+/* MAIN SERIAL DATA PORT CONTROL(STEREO I2S) */
+#define ALC5625_MAIN_SDP_CTRL 0X34
+
+/* EXTEND SERIAL DATA PORT CONTROL(VOICE I2S/PCM) */
+#define ALC5625_EXTEND_SDP_CTRL 0X36
+#define ALC5625_PWR_MANAG_ADD1 0X3A /* POWER MANAGMENT ADDITION 1 */
+#define ALC5625_PWR_MANAG_ADD2 0X3C /* POWER MANAGMENT ADDITION 2 */
+#define ALC5625_PWR_MANAG_ADD3 0X3E /* POWER MANAGMENT ADDITION 3 */
+
+/* GENERAL PURPOSE CONTROL REGISTER 1 */
+#define ALC5625_GEN_CTRL_REG1 0X40
+
+/* GENERAL PURPOSE CONTROL REGISTER 2 */
+#define ALC5625_GEN_CTRL_REG2 0X42
+#define ALC5625_PLL_CTRL 0X44 /* PLL1 CONTROL */
+#define ALC5625_PLL2_CTRL 0X46 /* PLL2 CONTROL */
+#define ALC5625_LDO_CTRL 0X48 /* LDO CONTROL */
+#define ALC5625_GPIO_PIN_CONFIG 0X4C /* GPIO PIN CONFIGURATION */
+#define ALC5625_GPIO_PIN_POLARITY 0X4E /* GPIO PIN POLARITY */
+#define ALC5625_GPIO_PIN_STICKY 0X50 /* GPIO PIN STICKY */
+#define ALC5625_GPIO_PIN_WAKEUP 0X52 /* GPIO PIN WAKE UP */
+#define ALC5625_GPIO_PIN_STATUS 0X54 /* GPIO PIN STATUS */
+#define ALC5625_GPIO_PIN_SHARING 0X56 /* GPIO PIN SHARING */
+
+/* OVER TEMPERATURE AND CURRENT STATUS */
+#define ALC5625_OVER_TEMP_CURR_STATUS 0X58
+
+/* SOFT VOLUME CONTROL SETTING */
+#define ALC5625_SOFT_VOL_CTRL 0X5A
+#define ALC5625_GPIO_OUT_CTRL 0X5C /* GPIO OUTPUT PIN CONTRL */
+#define ALC5625_MISC_CTRL 0X5E /* MISC CONTROL */
+#define ALC5625_STEREO_DAC_CLK_CTRL1 0X60 /* STEREO DAC CLOCK CONTROL 1 */
+#define ALC5625_STEREO_DAC_CLK_CTRL2 0X62 /* STEREO DAC CLOCK CONTROL 2 */
+
+/* VOICE/PCM DAC CLOCK CONTROL 1 */
+#define ALC5625_VOICE_DAC_PCMCLK_CTRL1 0X64
+
+/* PSEDUEO STEREO /SPATIAL EFFECT BLOCK CONTROL */
+#define ALC5625_PSEDUEO_SPATIAL_CTRL 0X68
+#define ALC5625_PRIV_ADDR 0X6A /* PRIVATE ADDRESS */
+#define ALC5625_PRIV_DATA 0X6C /* PRIVATE DATA */
+
+/* EQ CONTROL AND STATUS /ADC HPF CONTROL */
+#define ALC5625_EQ_CTRL_ADC_HPF 0X6E
+#define ALC5625_VODSP_REG_ADDR 0x70 /* VODSP REGISTER ADDRESS */
+#define ALC5625_VODSP_REG_DATA 0x72 /* VODSP REGISTER DATA */
+#define ALC5625_VODSP_REG_CMD 0x74 /* VODSP REGISTER COMMAND */
+
+/* Bit define of Codec Register */
+#define ALC_L_MUTE (0x1<<15) /* Mute Left Control */
+
+/* Mute Left Zero-Cross Detector Control */
+#define ALC_L_ZC (0x1<<14)
+#define ALC_R_MUTE (0x1<<7) /* Mute Right Control */
+
+/* Mute Right Zero-Cross Detector Control */
+#define ALC_R_ZC (0x1<<6)
+
+/* Mute source to HP Mixer */
+#define ALC_M_HP_MIXER (0x1<<15)
+
+/* Mute source to Speaker Mixer */
+#define ALC_M_SPK_MIXER (0x1<<14)
+
+/* Mute source to Mono Mixer */
+#define ALC_M_MONO_MIXER (0x1<<13)
+
+/* Phone Input Volume(0x08) */
+/* Mute Phone In volume to HP mixer */
+#define M_PHONEIN_TO_HP_MIXER (0x1<<15)
+
+/* Mute Phone In volume to speaker mixer */
+#define M_PHONEIN_TO_SPK_MIXER (0x1<<14)
+
+/* Mic Routing Control(0x10) */
+/* Mute MIC1 to HP mixer */
+#define M_MIC1_TO_HP_MIXER (0x1<<15)
+
+/* Mute MiC1 to SPK mixer */
+#define M_MIC1_TO_SPK_MIXER (0x1<<14)
+
+/* Mute MIC1 to MONO mixer */
+#define M_MIC1_TO_MONO_MIXER (0x1<<13)
+
+/* Mute MIC2 to HP mixer */
+#define M_MIC2_TO_HP_MIXER (0x1<<11)
+
+/* Mute MiC2 to SPK mixer */
+#define M_MIC2_TO_SPK_MIXER (0x1<<10)
+
+/* Mute MIC2 to MONO mixer */
+#define M_MIC2_TO_MONO_MIXER (0x1<<9)
+
+/* Mute DAC to HP left mixer */
+#define M_DAC_TO_HPL_MIXER (0x1<<3)
+
+/* Mute DAC to HP right mixer */
+#define M_DAC_TO_HPR_MIXER (0x1<<2)
+
+/* Mute DAC to SPK mixer */
+#define M_DAC_TO_SPK_MIXER (0x1<<1)
+
+/* Mute DAC to MONO mixer */
+#define M_DAC_TO_MONO_MIXER (0x1<<0)
+
+/* ADC Record Gain(0x12) */
+/* Mute left of ADC to HP Mixer */
+#define M_ADC_L_TO_HP_MIXER (0x1<<15)
+
+/* Mute left of ADC to MONO Mixer */
+#define M_ADC_L_TO_MONO_MIXER (0x1<<14)
+
+/* ADC Zero-Cross Detector Control */
+#define ADC_L_ZC_DET (0x1<<13)
+
+ /* ADC Record Gain Left channel Mask */
+#define ADC_L_GAIN_MASK (0x1f<<8)
+
+/* Mute right of ADC to HP Mixer */
+#define M_ADC_R_TO_HP_MIXER (0x1<<7)
+
+/* Mute right of ADC to MONO Mixer */
+#define M_ADC_R_TO_MONO_MIXER (0x1<<6)
+
+/* ADC Zero-Cross Detector Control */
+#define ADC_R_ZC_DET (0x1<<5)
+
+/* ADC Record Gain Right channel Mask */
+#define ADC_R_GAIN_MASK (0x1f<<0)
+
+/* Voice DAC Output Volume(0x18) */
+#define M_V_DAC_TO_HP_MIXER (0x1<<15)
+#define M_V_DAC_TO_SPK_MIXER (0x1<<14)
+#define M_V_DAC_TO_MONO_MIXER (0x1<<13)
+
+/* AEC & PDM Control(0x1A) */
+#define VODSP_SRC1_PWR (0x1<<15) /* Enable SRC1 Power */
+#define VODSP_SRC2_PWR (0x1<<13) /* Enable SRC2 Power */
+
+#define VODSP_SRC2_S_SEL_MASK (0x1<<12)
+
+/* SRC2 source select AEC_TXDP */
+#define VODSP_SRC2_S_SEL_TXDP (0x0<<12)
+
+/* SRC2 source select AEC_TXDC */
+#define VODSP_SRC2_S_SEL_TXDC (0x1<<12)
+
+/* Enable AEC RXDP Power */
+#define VODSP_RXDP_PWR (0x1<<11)
+
+#define VODSP_RXDP_S_SEL_MASK (0x3<<9)
+
+/* AEC RxDP source select SRC1 Output */
+#define VODSP_RXDP_S_SEL_SRC1 (0x0<<9)
+
+/* AEC RxDP source select ADC Left to AEC Digital Path */
+#define VODSP_RXDP_S_SEL_ADCL (0x1<<9)
+
+/* AEC RxDP source select Voice to Stereo Digital Path */
+#define VODSP_RXDP_S_SEL_VOICE (0x2<<9)
+
+/* AEC RxDP source select ADC Right to AEC Digital Path */
+#define VODSP_RXDP_S_SEL_ADCR (0x3<<9)
+
+/* Enable AEC RXDC Power */
+#define VODSP_RXDC_PWR (0x1<<8)
+
+#define VOICE_PCM_S_SEL_MASK (0x1<<7)
+
+/* VSADC PCM interface source select ADC R */
+#define VOICE_PCM_S_SEL_ADC_R (0x0<<7)
+
+/* VSADC PCM interface source select AEC_TXDP */
+#define VOICE_PCM_S_SEL_AEC_TXDP (0x1<<7)
+
+#define REC_S_SEL_MASK (0x3<<4)
+
+/* Main Stereo Record I2S source select ADC L/R */
+#define REC_S_SEL_ADC (0x0<<4)
+
+/* Main Stereo Record I2S source select Voice to Stereo Digital Path */
+#define REC_S_SEL_VOICE (0x1<<4)
+
+/* Main Stereo Record I2S source select SRC2 */
+#define REC_S_SEL_SRC2 (0x2<<4)
+
+/*Output Mixer Control(0x1C) */
+#define SPKOUT_N_SOUR_MASK (0x3<<14)
+#define SPKOUT_N_SOUR_LN (0x2<<14)
+#define SPKOUT_N_SOUR_RP (0x1<<14)
+#define SPKOUT_N_SOUR_RN (0x0<<14)
+
+#define SPKOUT_SEL_CLASS_D (0x1<<13)
+#define SPKOUT_SEL_CLASS_AB (0x0<<13)
+
+#define SPK_CLASS_AB_S_AMP (0x0<<12)
+#define SPK_CALSS_AB_W_AMP (0x1<<12)
+
+#define SPKOUT_INPUT_SEL_MASK (0x3<<10)
+#define SPKOUT_INPUT_SEL_MONOMIXER (0x3<<10)
+#define SPKOUT_INPUT_SEL_SPKMIXER (0x2<<10)
+#define SPKOUT_INPUT_SEL_HPMIXER (0x1<<10)
+#define SPKOUT_INPUT_SEL_VMID (0x0<<10)
+
+#define HPL_INPUT_SEL_HPLMIXER (0x1<<9)
+#define HPR_INPUT_SEL_HPRMIXER (0x1<<8)
+
+#define AUXOUT_INPUT_SEL_MASK (0x3<<6)
+#define AUXOUT_INPUT_SEL_MONOMIXER (0x3<<6)
+#define AUXOUT_INPUT_SEL_SPKMIXER (0x2<<6)
+#define AUXOUT_INPUT_SEL_HPMIXER (0x1<<6)
+#define AUXOUT_INPUT_SEL_VMID (0x0<<6)
+
+/* Voice DSP Control(0x1E) */
+#define VODSP_SYSCLK_S_SEL_MASK (0x1<<15)
+#define VODSP_SYSCLK_S_SEL_M_CLK (0x0<<15)
+#define VODSP_SYSCLK_S_SEL_V_CLK (0x1<<15)
+
+#define VODSP_LRCK_SEL_MASK (0x1<<13)
+#define VODSP_LRCK_SEL_8K (0x0<<13)
+#define VODSP_LRCK_SEL_16K (0x1<<13)
+#define VODSP_TEST_MODE_ENA (0x1<<3)
+#define VODSP_NO_BP_MODE_ENA (0x1<<2)
+#define VODSP_NO_PD_MODE_ENA (0x1<<1)
+#define VODSP_NO_RST_MODE_ENA (0x1<<0)
+
+/* Micphone Control define(0x22) */
+#define MIC1 1
+#define MIC2 2
+#define MIC_BIAS_90_PRECNET_AVDD 1
+#define MIC_BIAS_75_PRECNET_AVDD 2
+
+#define MIC1_BOOST_CONTROL_MASK (0x3<<10)
+#define MIC1_BOOST_CONTROL_BYPASS (0x0<<10)
+#define MIC1_BOOST_CONTROL_20DB (0x1<<10)
+#define MIC1_BOOST_CONTROL_30DB (0x2<<10)
+#define MIC1_BOOST_CONTROL_40DB (0x3<<10)
+
+#define MIC2_BOOST_CONTROL_MASK (0x3<<8)
+#define MIC2_BOOST_CONTROL_BYPASS (0x0<<8)
+#define MIC2_BOOST_CONTROL_20DB (0x1<<8)
+#define MIC2_BOOST_CONTROL_30DB (0x2<<8)
+#define MIC2_BOOST_CONTROL_40DB (0x3<<8)
+
+#define MIC1_BIAS_VOLT_CTRL_MASK (0x1<<5)
+#define MIC1_BIAS_VOLT_CTRL_90P (0x0<<5)
+#define MIC1_BIAS_VOLT_CTRL_75P (0x1<<5)
+
+#define MIC2_BIAS_VOLT_CTRL_MASK (0x1<<4)
+#define MIC2_BIAS_VOLT_CTRL_90P (0x0<<4)
+#define MIC2_BIAS_VOLT_CTRL_75P (0x1<<4)
+
+/* PowerDown control of register(0x26) */
+/* power management bits */
+/* write this bit to power down the Speaker Amplifier */
+#define ALC_PWR_PR7 (0x1<<15)
+
+/* write this bit to power down the Headphone Out and MonoOut */
+#define ALC_PWR_PR6 (0x1<<14)
+
+/* write this bit to power down the internal clock(without PLL) */
+#define ALC_PWR_PR5 (0x1<<13)
+
+/* write this bit to power down the mixer(vref/vrefout out off) */
+#define ALC_PWR_PR3 (0x1<<11)
+
+/* write this bit to power down the mixer(vref/vrefout still on) */
+#define ALC_PWR_PR2 (0x1<<10)
+
+/* write this bit to power down the dac */
+#define ALC_PWR_PR1 (0x1<<9)
+
+/* write this bit to power down the adc */
+#define ALC_PWR_PR0 (0x1<<8)
+
+
+#define ALC_PWR_REF (0x1<<3) /* read only */
+#define ALC_PWR_ANL (0x1<<2) /* read only */
+#define ALC_PWR_DAC (0x1<<1) /* read only */
+#define ALC_PWR_ADC (0x1) /* read only */
+
+/* Stereo DAC/Voice DAC/Stereo ADC function(0x2E) */
+#define DAC_FUNC_SEL_MASK (0x3<<12)
+#define DAC_FUNC_SEL_DAC (0x0<<12)
+#define DAC_FUNC_SEL_SRC2 (0x1<<12)
+#define DAC_FUNC_SEL_VODSP_TXDP (0x2<<12)
+#define DAC_FUNC_SEL_VODSP_TXDC (0x3<<12)
+
+#define VODAC_SOUR_SEL_MASK (0x7<<8)
+#define VODAC_SOUR_SEL_VOICE (0x0<<8)
+#define VODAC_SOUR_SEL_SRC2 (0x1<<8)
+#define VODAC_SOUR_SEL_VODSP_TXDP (0x2<<8)
+#define VODAC_SOUR_SEL_VODSP_TXDC (0x3<<8)
+
+#define ADCR_FUNC_SEL_MASK (0x3<<4)
+#define ADCR_FUNC_SEL_ADC (0x0<<4)
+#define ADCR_FUNC_SEL_VOADC (0x1<<4)
+#define ADCR_FUNC_SEL_VODSP (0x2<<4)
+#define ADCR_FUNC_SEL_PDM (0x3<<4)
+
+#define ADCL_FUNC_SEL_MASK (0x3<<0)
+#define ADCL_FUNC_SEL_ADC (0x0<<0)
+#define ADCL_FUNC_SEL_VODSP (0x1<<0)
+
+/*
+ * Main Serial Data Port Control(0x34)
+ * 0:Master mode 1:Slave mode
+ */
+#define MAIN_I2S_MODE_SEL (0x1<<15)
+
+/* 0:Disable,ADC and DAC use the same fs,1:Enable */
+#define MAIN_I2S_SADLRCK_CTRL (0x1<<14)
+
+/* 0:Normal SADLRCK/SDALRCK,1:Invert SADLRCK/SDALRCK */
+#define MAIN_I2S_PCM_MODE (0x1<<6)
+
+/* Data Length Selection */
+/* main i2s Data Length mask */
+#define MAIN_I2S_DL_MASK (0x3<<2)
+#define MAIN_I2S_DL_16 (0x0<<2) /* 16 bits */
+#define MAIN_I2S_DL_20 (0x1<<2) /* 20 bits */
+#define MAIN_I2S_DL_24 (0x2<<2) /* 24 bits */
+#define MAIN_I2S_DL_32 (0x3<<2) /* 8 bits */
+
+/* PCM Data Format Selection */
+/* main i2s Data Format mask */
+#define MAIN_I2S_DF_MASK (0x3)
+
+/* I2S FORMAT */
+#define MAIN_I2S_DF_I2S (0x0)
+
+/* LEFT JUSTIFIED format */
+#define MAIN_I2S_DF_LEFT (0x1)
+
+/* PCM Mode A */
+#define MAIN_I2S_DF_PCM_A (0x2)
+
+/* PCM Mode B */
+#define MAIN_I2S_DF_PCM_B (0x3)
+
+/*
+ * Extend Serial Data Port Control(0x36)
+ * Enable PCM interface on GPIO 1,3,4,5
+ * 0:GPIO function,
+ * 1:Voice PCM interface
+ */
+#define EXT_I2S_FUNC_ENABLE (0x1<<15)
+
+/* 0:Master, 1:Slave */
+#define EXT_I2S_MODE_SEL (0x1<<14)
+
+/* 0:Disable, 1:Enable */
+#define EXT_I2S_AUTO_CLK_CTRL (0x1<<13)
+
+/* 0:Normal 1:Invert */
+#define EXT_I2S_BCLK_POLARITY (0x1<<7)
+
+/* 0:Normal VSLRCK,1:Invert VSLRCK */
+#define EXT_I2S_PCM_MODE (0x1<<6)
+/* Data Length Slection */
+/* Extend i2s Data Length mask */
+#define EXT_I2S_DL_MASK (0x3<<2)
+#define EXT_I2S_DL_32 (0x3<<2) /* 8 bits */
+#define EXT_I2S_DL_24 (0x2<<2) /* 24 bits */
+#define EXT_I2S_DL_20 (0x1<<2) /* 20 bits */
+#define EXT_I2S_DL_16 (0x0<<2) /* 16 bits */
+
+/* Voice Data Format */
+/* Extend i2s Data Format mask */
+#define EXT_I2S_DF_MASK (0x3)
+
+/* I2S FORMAT */
+#define EXT_I2S_DF_I2S (0x0)
+
+/* LEFT JUSTIFIED format */
+#define EXT_I2S_DF_LEFT (0x1)
+
+/* PCM Mode A */
+#define EXT_I2S_DF_PCM_A (0x2)
+
+/* PCM Mode B */
+#define EXT_I2S_DF_PCM_B (0x3)
+
+/* Power managment addition 1 (0x3A),0:Disable,1:Enable */
+#define PWR_DAC_DF2SE_L (0x1<<15)
+#define PWR_DAC_DF2SE_R (0x1<<14)
+#define PWR_ZC_DET_PD (0x1<<13)
+#define PWR_I2S_INTERFACE (0x1<<11)
+#define PWR_AMP_POWER (0x1<<10)
+#define PWR_HP_OUT_AMP (0x1<<9)
+#define PWR_HP_OUT_ENH_AMP (0x1<<8)
+#define PWR_VOICE_DF2SE (0x1<<7)
+#define PWR_SOFTGEN_EN (0x1<<6)
+#define PWR_MIC_BIAS1_DET (0x1<<5)
+#define PWR_MIC_BIAS2_DET (0x1<<4)
+#define PWR_MIC_BIAS1 (0x1<<3)
+#define PWR_MIC_BIAS2 (0x1<<2)
+#define PWR_MAIN_BIAS (0x1<<1)
+#define PWR_DAC_REF (0x1)
+
+/* Power managment addition 2(0x3C),0:Disable,1:Enable */
+#define PWR_PLL1 (0x1<<15)
+#define PWR_PLL2 (0x1<<14)
+#define PWR_MIXER_VREF (0x1<<13)
+#define PWR_TEMP_SENSOR (0x1<<12)
+#define PWR_AUX_ADC (0x1<<11)
+#define PWR_VOICE_CLOCK (0x1<<10)
+#define PWR_L_DAC_CLK (0x1<<9)
+#define PWR_R_DAC_CLK (0x1<<8)
+#define PWR_L_ADC_CLK (0x1<<7)
+#define PWR_R_ADC_CLK (0x1<<6)
+#define PWR_L_HP_MIXER (0x1<<5)
+#define PWR_R_HP_MIXER (0x1<<4)
+#define PWR_SPK_MIXER (0x1<<3)
+#define PWR_MONO_MIXER (0x1<<2)
+#define PWR_L_ADC_REC_MIXER (0x1<<1)
+#define PWR_R_ADC_REC_MIXER (0x1)
+
+/* Power managment addition 3(0x3E),0:Disable,1:Enable */
+#define PWR_OSC_EN (0x1<<15)
+#define PWR_AUXOUT_VOL (0x1<<14)
+#define PWR_SPK_OUT (0x1<<13)
+#define PWR_SPK_OUT_N (0x1<<12)
+#define PWR_HP_L_OUT_VOL (0x1<<11)
+#define PWR_HP_R_OUT_VOL (0x1<<10)
+#define PWR_VODSP_INTERFACE (0x1<<9)
+#define PWR_I2C_FOR_VODSP (0x1<<8)
+#define PWR_LINE_IN_L (0x1<<7)
+#define PWR_LINE_IN_R (0x1<<6)
+#define PWR_PHONE_VOL (0x1<<5)
+#define PWR_PHONE_ADMIXER (0x1<<4)
+#define PWR_MIC1_VOL_CTRL (0x1<<3)
+#define PWR_MIC2_VOL_CTRL (0x1<<2)
+#define PWR_MIC1_BOOST (0x1<<1)
+#define PWR_MIC2_BOOST (0x1)
+
+/* General Purpose Control Register 1(0x40) */
+#define GP_CLK_FROM_PLL (0x1<<15)
+#define GP_CLK_FROM_MCLK (0x0<<15)
+
+/* Enable DAC High Pass Filter */
+#define GP_DAC_HI_PA_ENA (0x1<<10)
+
+#define GP_EXTCLK_S_SEL_PLL2 (0x1<<6)
+#define GP_EXTCLK_S_SEL_PLL1 (0x0<<6)
+
+#define GP_EXTCLK_DIR_SEL_OUTPUT (0x1<<5)
+#define GP_EXTCLK_DIR_SEL_INTPUT (0x0<<5)
+
+#define GP_VOSYS_S_SEL_PLL2 (0x0<<4)
+#define GP_VOSYS_S_SEL_EXTCLK (0x1<<4)
+
+#define GP_SPK_AMP_CTRL_MASK (0x7<<1)
+#define GP_SPK_AMP_CTRL_RATIO_225 (0x0<<1) /* 2.25 Vdd */
+#define GP_SPK_AMP_CTRL_RATIO_200 (0x1<<1) /* 2.00 Vdd */
+#define GP_SPK_AMP_CTRL_RATIO_175 (0x2<<1) /* 1.75 Vdd */
+#define GP_SPK_AMP_CTRL_RATIO_150 (0x3<<1) /* 1.50 Vdd */
+#define GP_SPK_AMP_CTRL_RATIO_125 (0x4<<1) /* 1.25 Vdd */
+#define GP_SPK_AMP_CTRL_RATIO_100 (0x5<<1) /* 1.00 Vdd */
+
+/* General Purpose Control Register 2(0x42) */
+#define GP2_PLL1_SOUR_SEL_MASK (0x3<<12)
+#define GP2_PLL1_SOUR_SEL_MCLK (0x0<<12)
+#define GP2_PLL1_SOUR_SEL_BCLK (0x2<<12)
+#define GP2_PLL1_SOUR_SEL_VBCLK (0x3<<12)
+
+/* PLL Control(0x44) */
+#define PLL_M_CODE_MASK 0xF /* PLL M code mask */
+#define PLL_K_CODE_MASK (0x7<<4) /* PLL K code mask */
+#define PLL_BYPASS_N (0x1<<7) /* bypass PLL N code */
+#define PLL_N_CODE_MASK (0xFF<<8) /* PLL N code mask */
+
+#define PLL_CTRL_M_VAL(m) ((m)&0xf)
+#define PLL_CTRL_K_VAL(k) (((k)&0x7)<<4)
+#define PLL_CTRL_N_VAL(n) (((n)&0xff)<<8)
+
+/* PLL2 CONTROL */
+#define PLL2_ENA (0x1<<15)
+#define PLL_2_RATIO_8X (0x0)
+#define PLL_2_RATIO_16X (0x1)
+
+/* LDO Control(0x48) */
+#define LDO_ENABLE (0x1<<15)
+
+#define LDO_OUT_VOL_CTRL_MASK (0xf<<0)
+#define LDO_OUT_VOL_CTRL_1_55V (0xf<<0)
+#define LDO_OUT_VOL_CTRL_1_50V (0xe<<0)
+#define LDO_OUT_VOL_CTRL_1_45V (0xd<<0)
+#define LDO_OUT_VOL_CTRL_1_40V (0xc<<0)
+#define LDO_OUT_VOL_CTRL_1_35V (0xb<<0)
+#define LDO_OUT_VOL_CTRL_1_30V (0xa<<0)
+#define LDO_OUT_VOL_CTRL_1_25V (0x9<<0)
+#define LDO_OUT_VOL_CTRL_1_20V (0x8<<0)
+#define LDO_OUT_VOL_CTRL_1_15V (0x7<<0)
+#define LDO_OUT_VOL_CTRL_1_05V (0x6<<0)
+#define LDO_OUT_VOL_CTRL_1_00V (0x5<<0)
+#define LDO_OUT_VOL_CTRL_0_95V (0x4<<0)
+#define LDO_OUT_VOL_CTRL_0_90V (0x3<<0)
+#define LDO_OUT_VOL_CTRL_0_85V (0x2<<0)
+#define LDO_OUT_VOL_CTRL_0_80V (0x1<<0)
+#define LDO_OUT_VOL_CTRL_0_75V (0x0<<0)
+
+/* GPIO Pin Configuration(0x4C) */
+#define GPIO_1 (0x1<<1)
+#define GPIO_2 (0x1<<2)
+#define GPIO_3 (0x1<<3)
+#define GPIO_4 (0x1<<4)
+#define GPIO_5 (0x1<<5)
+
+/* INTERRUPT CONTROL(0x5E) */
+#define DISABLE_FAST_VREG (0x1<<15)
+
+#define AVC_TARTGET_SEL_MASK (0x3<<12)
+#define AVC_TARTGET_SEL_NONE (0x0<<12)
+#define AVC_TARTGET_SEL_R (0x1<<12)
+#define AVC_TARTGET_SEL_L (0x2<<12)
+#define AVC_TARTGET_SEL_BOTH (0x3<<12)
+
+#define HP_DEPOP_MODE2_EN (0x1<<8)
+#define HP_DEPOP_MODE1_EN (0x1<<9)
+#define HP_L_M_UM_DEPOP_EN (0x1<<7)
+#define HP_R_M_UM_DEPOP_EN (0x1<<6)
+#define M_UM_DEPOP_EN (0x1<<5)
+
+/* Stereo DAC Clock Control 1(0x60) */
+#define STEREO_BCLK_DIV1_MASK (0xF<<12)
+#define STEREO_BCLK_DIV1_1 (0x0<<12)
+#define STEREO_BCLK_DIV1_2 (0x1<<12)
+#define STEREO_BCLK_DIV1_3 (0x2<<12)
+#define STEREO_BCLK_DIV1_4 (0x3<<12)
+#define STEREO_BCLK_DIV1_5 (0x4<<12)
+#define STEREO_BCLK_DIV1_6 (0x5<<12)
+#define STEREO_BCLK_DIV1_7 (0x6<<12)
+#define STEREO_BCLK_DIV1_8 (0x7<<12)
+#define STEREO_BCLK_DIV1_9 (0x8<<12)
+#define STEREO_BCLK_DIV1_10 (0x9<<12)
+#define STEREO_BCLK_DIV1_11 (0xA<<12)
+#define STEREO_BCLK_DIV1_12 (0xB<<12)
+#define STEREO_BCLK_DIV1_13 (0xC<<12)
+#define STEREO_BCLK_DIV1_14 (0xD<<12)
+#define STEREO_BCLK_DIV1_15 (0xE<<12)
+#define STEREO_BCLK_DIV1_16 (0xF<<12)
+
+#define STEREO_BCLK_DIV2_MASK (0x7<<8)
+#define STEREO_BCLK_DIV2_2 (0x0<<8)
+#define STEREO_BCLK_DIV2_4 (0x1<<8)
+#define STEREO_BCLK_DIV2_8 (0x2<<8)
+#define STEREO_BCLK_DIV2_16 (0x3<<8)
+#define STEREO_BCLK_DIV2_32 (0x4<<8)
+
+#define STEREO_AD_LRCK_DIV1_MASK (0xF<<4)
+#define STEREO_AD_LRCK_DIV1_1 (0x0<<4)
+#define STEREO_AD_LRCK_DIV1_2 (0x1<<4)
+#define STEREO_AD_LRCK_DIV1_3 (0x2<<4)
+#define STEREO_AD_LRCK_DIV1_4 (0x3<<4)
+#define STEREO_AD_LRCK_DIV1_5 (0x4<<4)
+#define STEREO_AD_LRCK_DIV1_6 (0x5<<4)
+#define STEREO_AD_LRCK_DIV1_7 (0x6<<4)
+#define STEREO_AD_LRCK_DIV1_8 (0x7<<4)
+#define STEREO_AD_LRCK_DIV1_9 (0x8<<4)
+#define STEREO_AD_LRCK_DIV1_10 (0x9<<4)
+#define STEREO_AD_LRCK_DIV1_11 (0xA<<4)
+#define STEREO_AD_LRCK_DIV1_12 (0xB<<4)
+#define STEREO_AD_LRCK_DIV1_13 (0xC<<4)
+#define STEREO_AD_LRCK_DIV1_14 (0xD<<4)
+#define STEREO_AD_LRCK_DIV1_15 (0xE<<4)
+#define STEREO_AD_LRCK_DIV1_16 (0xF<<4)
+
+#define STEREO_AD_LRCK_DIV2_MASK (0x7<<1)
+#define STEREO_AD_LRCK_DIV2_2 (0x0<<1)
+#define STEREO_AD_LRCK_DIV2_4 (0x1<<1)
+#define STEREO_AD_LRCK_DIV2_8 (0x2<<1)
+#define STEREO_AD_LRCK_DIV2_16 (0x3<<1)
+#define STEREO_AD_LRCK_DIV2_32 (0x4<<1)
+
+#define STEREO_DA_LRCK_DIV_MASK (1)
+#define STEREO_DA_LRCK_DIV_32 (0)
+#define STEREO_DA_LRCK_DIV_64 (1)
+
+/* Stereo DAC Clock Control 2(0x62) */
+#define STEREO_DA_FILTER_DIV1_MASK (0xF<<12)
+#define STEREO_DA_FILTER_DIV1_1 (0x0<<12)
+#define STEREO_DA_FILTER_DIV1_2 (0x1<<12)
+#define STEREO_DA_FILTER_DIV1_3 (0x2<<12)
+#define STEREO_DA_FILTER_DIV1_4 (0x3<<12)
+#define STEREO_DA_FILTER_DIV1_5 (0x4<<12)
+#define STEREO_DA_FILTER_DIV1_6 (0x5<<12)
+#define STEREO_DA_FILTER_DIV1_7 (0x6<<12)
+#define STEREO_DA_FILTER_DIV1_8 (0x7<<12)
+#define STEREO_DA_FILTER_DIV1_9 (0x8<<12)
+#define STEREO_DA_FILTER_DIV1_10 (0x9<<12)
+#define STEREO_DA_FILTER_DIV1_11 (0xA<<12)
+#define STEREO_DA_FILTER_DIV1_12 (0xB<<12)
+#define STEREO_DA_FILTER_DIV1_13 (0xC<<12)
+#define STEREO_DA_FILTER_DIV1_14 (0xD<<12)
+#define STEREO_DA_FILTER_DIV1_15 (0xE<<12)
+#define STEREO_DA_FILTER_DIV1_16 (0xF<<12)
+
+#define STEREO_DA_FILTER_DIV2_MASK (0x7<<9)
+#define STEREO_DA_FILTER_DIV2_2 (0x0<<9)
+#define STEREO_DA_FILTER_DIV2_4 (0x1<<9)
+#define STEREO_DA_FILTER_DIV2_8 (0x2<<9)
+#define STEREO_DA_FILTER_DIV2_16 (0x3<<9)
+#define STEREO_DA_FILTER_DIV2_32 (0x4<<9)
+
+#define STEREO_AD_FILTER_DIV1_MASK (0xF<<4)
+#define STEREO_AD_FILTER_DIV1_1 (0x0<<4)
+#define STEREO_AD_FILTER_DIV1_2 (0x1<<4)
+#define STEREO_AD_FILTER_DIV1_3 (0x2<<4)
+#define STEREO_AD_FILTER_DIV1_4 (0x3<<4)
+#define STEREO_AD_FILTER_DIV1_5 (0x4<<4)
+#define STEREO_AD_FILTER_DIV1_6 (0x5<<4)
+#define STEREO_AD_FILTER_DIV1_7 (0x6<<4)
+#define STEREO_AD_FILTER_DIV1_8 (0x7<<4)
+#define STEREO_AD_FILTER_DIV1_9 (0x8<<4)
+#define STEREO_AD_FILTER_DIV1_10 (0x9<<4)
+#define STEREO_AD_FILTER_DIV1_11 (0xA<<4)
+#define STEREO_AD_FILTER_DIV1_12 (0xB<<4)
+#define STEREO_AD_FILTER_DIV1_13 (0xC<<4)
+#define STEREO_AD_FILTER_DIV1_14 (0xD<<4)
+#define STEREO_AD_FILTER_DIV1_15 (0xE<<4)
+#define STEREO_AD_FILTER_DIV1_16 (0xF<<4)
+
+#define STEREO_AD_FILTER_DIV2_MASK (0x7<<1)
+#define STEREO_AD_FILTER_DIV2_1 (0x0<<1)
+#define STEREO_AD_FILTER_DIV2_2 (0x1<<1)
+#define STEREO_AD_FILTER_DIV2_4 (0x2<<1)
+#define STEREO_AD_FILTER_DIV2_8 (0x3<<1)
+#define STEREO_AD_FILTER_DIV2_16 (0x4<<1)
+#define STEREO_AD_FILTER_DIV2_32 (0x5<<1)
+
+/* Voice DAC PCM Clock Control 1(0x64) */
+#define VOICE_BCLK_DIV1_MASK (0xF<<12)
+#define VOICE_BCLK_DIV1_1 (0x0<<12)
+#define VOICE_BCLK_DIV1_2 (0x1<<12)
+#define VOICE_BCLK_DIV1_3 (0x2<<12)
+#define VOICE_BCLK_DIV1_4 (0x3<<12)
+#define VOICE_BCLK_DIV1_5 (0x4<<12)
+#define VOICE_BCLK_DIV1_6 (0x5<<12)
+#define VOICE_BCLK_DIV1_7 (0x6<<12)
+#define VOICE_BCLK_DIV1_8 (0x7<<12)
+#define VOICE_BCLK_DIV1_9 (0x8<<12)
+#define VOICE_BCLK_DIV1_10 (0x9<<12)
+#define VOICE_BCLK_DIV1_11 (0xA<<12)
+#define VOICE_BCLK_DIV1_12 (0xB<<12)
+#define VOICE_BCLK_DIV1_13 (0xC<<12)
+#define VOICE_BCLK_DIV1_14 (0xD<<12)
+#define VOICE_BCLK_DIV1_15 (0xE<<12)
+#define VOICE_BCLK_DIV1_16 (0xF<<12)
+
+#define VOICE_BCLK_DIV2_MASK (0x7<<8)
+#define VOICE_BCLK_DIV2_2 (0x0<<8)
+#define VOICE_BCLK_DIV2_4 (0x1<<8)
+#define VOICE_BCLK_DIV2_8 (0x2<<8)
+#define VOICE_BCLK_DIV2_16 (0x3<<8)
+#define VOICE_BCLK_DIV2_32 (0x4<<8)
+
+#define VOICE_AD_LRCK_DIV1_MASK (0xF<<4)
+#define VOICE_AD_LRCK_DIV1_1 (0x0<<4)
+#define VOICE_AD_LRCK_DIV1_2 (0x1<<4)
+#define VOICE_AD_LRCK_DIV1_3 (0x2<<4)
+#define VOICE_AD_LRCK_DIV1_4 (0x3<<4)
+#define VOICE_AD_LRCK_DIV1_5 (0x4<<4)
+#define VOICE_AD_LRCK_DIV1_6 (0x5<<4)
+#define VOICE_AD_LRCK_DIV1_7 (0x6<<4)
+#define VOICE_AD_LRCK_DIV1_8 (0x7<<4)
+#define VOICE_AD_LRCK_DIV1_9 (0x8<<4)
+#define VOICE_AD_LRCK_DIV1_10 (0x9<<4)
+#define VOICE_AD_LRCK_DIV1_11 (0xA<<4)
+#define VOICE_AD_LRCK_DIV1_12 (0xB<<4)
+#define VOICE_AD_LRCK_DIV1_13 (0xC<<4)
+#define VOICE_AD_LRCK_DIV1_14 (0xD<<4)
+#define VOICE_AD_LRCK_DIV1_15 (0xE<<4)
+#define VOICE_AD_LRCK_DIV1_16 (0xF<<4)
+
+#define VOICE_AD_LRCK_DIV2_MASK (0x7<<1)
+#define VOICE_AD_LRCK_DIV2_2 (0x0<<1)
+#define VOICE_AD_LRCK_DIV2_4 (0x1<<1)
+#define VOICE_AD_LRCK_DIV2_8 (0x2<<1)
+#define VOICE_AD_LRCK_DIV2_16 (0x3<<1)
+#define VOICE_AD_LRCK_DIV2_32 (0x4<<1)
+
+#define VOICE_DA_LRCK_DIV_MASK (1)
+#define VOICE_DA_LRCK_DIV_32 (0)
+#define VOICE_DA_LRCK_DIV_64 (1)
+
+
+/* Psedueo Stereo & Spatial Effect Block Control(0x68) */
+#define SPATIAL_CTRL_EN (0x1<<15)
+#define ALL_PASS_FILTER_EN (0x1<<14)
+#define PSEUDO_STEREO_EN (0x1<<13)
+#define STEREO_EXPENSION_EN (0x1<<12)
+
+#define SPATIAL_3D_GAIN1_MASK (0x3<<10)
+#define SPATIAL_3D_GAIN1_1_0 (0x0<<10)
+#define SPATIAL_3D_GAIN1_1_5 (0x1<<10)
+#define SPATIAL_3D_GAIN1_2_0 (0x2<<10)
+
+#define SPATIAL_3D_RATIO1_MASK (0x3<<8)
+#define SPATIAL_3D_RATIO1_0_0 (0x0<<8)
+#define SPATIAL_3D_RATIO1_0_66 (0x1<<8)
+#define SPATIAL_3D_RATIO1_1_0 (0x2<<8)
+
+#define SPATIAL_3D_GAIN2_MASK (0x3<<6)
+#define SPATIAL_3D_GAIN2_1_0 (0x0<<6)
+#define SPATIAL_3D_GAIN2_1_5 (0x1<<6)
+#define SPATIAL_3D_GAIN2_2_0 (0x2<<6)
+
+#define SPATIAL_3D_RATIO2_MASK (0x3<<4)
+#define SPATIAL_3D_RATIO2_0_0 (0x0<<4)
+#define SPATIAL_3D_RATIO2_0_66 (0x1<<4)
+#define SPATIAL_3D_RATIO2_1_0 (0x2<<4)
+
+#define APF_MASK (0x3)
+#define APF_FOR_48K (0x3)
+#define APF_FOR_44_1K (0x2)
+#define APF_FOR_32K (0x1)
+
+/* EQ Control and Status /ADC HPF Control(0x6E) */
+/* HW EQ block control */
+#define EN_HW_EQ_BLK (0x1<<15)
+
+#define EQ_SOUR_SEL_DAC (0x0<<14)
+#define EQ_SOUR_SEL_ADC (0x1<<14)
+
+/* EQ parameter update control */
+#define EQ_CHANGE_EN (0x1<<7)
+
+/* EQ High Pass Filter Control */
+#define EN_HW_EQ_HPF (0x1<<4)
+
+/* EQ Band-3 Control */
+#define EN_HW_EQ_BP3 (0x1<<3)
+
+/* EQ Band-2 Control */
+#define EN_HW_EQ_BP2 (0x1<<2)
+
+/* EQ Band-1 Control */
+#define EN_HW_EQ_BP1 (0x1<<1)
+
+/* EQ Low Pass Filter Control */
+#define EN_HW_EQ_LPF (0x1<<0)
+
+/* AEC register command(0x74) */
+/* VODSP I2C busy flag */
+#define VODSP_BUSY (0x1<<15)
+
+#define VODSP_S_FROM_VODSP_RD (0x0<<14)
+#define VODSP_S_FROM_MX72 (0x1<<14)
+
+/* VODSP CLK select Mask */
+#define VODSP_CLK_SEL_MASK (0x3<<12)
+
+/* VODSP CLK select 12.288Mhz */
+#define VODSP_CLK_SEL_12_288M (0x0<<12)
+
+/* VODSP CLK select 6.144Mhz */
+#define VODSP_CLK_SEL_6_144M (0x1<<12)
+
+/* VODSP CLK select 3.072Mhz */
+#define VODSP_CLK_SEL_3_072M (0x2<<12)
+
+/* VODSP CLK select 2.0488Mhz */
+#define VODSP_CLK_SEL_2_048M (0x3<<12)
+
+/* VODSP Read Enable */
+#define VODSP_READ_ENABLE (0x1<<9)
+
+/* VODSP Write Enable */
+#define VODSP_WRITE_ENABLE (0x1<<8)
+
+#define VODSP_CMD_MASK (0xFF<<0)
+#define VODSP_CMD_MW (0x3B<<0) /* Memory Write */
+#define VODSP_CMD_MR (0x37<<0) /* Memory Read */
+#define VODSP_CMD_RR (0x60<<0) /* Register Read */
+#define VODSP_CMD_RW (0x68<<0) /* Register Write */
+
+/*
+ * Index register of codec
+ * Index(0x20) for Auto Volume Control
+ */
+#define AVC_CH_SEL_MASK (0x1<<7)
+#define AVC_CH_SEL_L_CH (0x0<<7)
+#define AVC_CH_SEL_R_CH (0x1<<7)
+#define ENABLE_AVC_GAIN_CTRL (0x1<<15)
+
+#define DEFAULT_SYSCLK 24576000
+
+enum ALC5625_PLL_SEL {
+ ALC5625_PLL1_FROM_MCLK = 0,
+ ALC5625_PLL1_FROM_BCLK,
+ ALC5625_PLL1_FROM_VBCLK,
+};
+
+enum ALC5625_AEC_MODE {
+ PCM_IN_PCM_OUT = 0,
+ ANALOG_IN_ANALOG_OUT,
+ DAC_IN_ADC_OUT,
+ VODSP_AEC_DISABLE
+};
+
+enum ALC5625_PCM_MODE {
+ PCM_MASTER_MODE_A = 0,
+ PCM_MASTER_MODE_B,
+ PCM_SLAVE_MODE_A,
+ PCM_SLAVE_MODE_B,
+};
+
+enum ALC5625_FUNC_SEL {
+ ALC5625_AEC_DISABLE = 0,
+ ALC5625_AEC_PCM_IN_OUT,
+ ALC5625_AEC_IIS_IN_OUT,
+ ALC5625_AEC_ANALOG_IN_OUT,
+};
+
+struct alc5625_setup_data {
+ int i2c_bus;
+ int i2c_address;
+};
+
+struct voice_dsp_reg {
+ u16 index;
+ u16 val;
+};
+
+#endif
diff --git a/drivers/staging/alc5625/origen_alc5625.c b/drivers/staging/alc5625/origen_alc5625.c
new file mode 100644
index 00000000000..f2b6f3585a0
--- /dev/null
+++ b/drivers/staging/alc5625/origen_alc5625.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2011 Insignal Co., Ltd.
+ *
+ * Author: Pan <pan@insginal.co.kr>
+ *
+ * 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/platform_device.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "../../../sound/soc/samsung/i2s.h"
+
+static int set_epll_rate(unsigned long rate)
+{
+ struct clk *fout_epll;
+
+ fout_epll = clk_get(NULL, "fout_epll");
+ if (IS_ERR(fout_epll)) {
+ printk(KERN_ERR "%s: failed to get fout_epll\n", __func__);
+ return -ENOENT;
+ }
+
+ if (rate == clk_get_rate(fout_epll))
+ goto out;
+
+ clk_set_rate(fout_epll, rate);
+out:
+ clk_put(fout_epll);
+
+ return 0;
+}
+
+static int origen_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 *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int bfs, psr, rfs, ret;
+ unsigned long rclk;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_U24:
+ case SNDRV_PCM_FORMAT_S24:
+ bfs = 48;
+ break;
+ case SNDRV_PCM_FORMAT_U16_LE:
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bfs = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params_rate(params)) {
+ case 16000:
+ case 22050:
+ case 24000:
+ case 32000:
+ case 44100:
+ case 48000:
+ case 88200:
+ case 96000:
+ rfs = (bfs == 48) ? 384 : 256;
+ break;
+ case 64000:
+ rfs = 384;
+ break;
+ case 8000:
+ case 11025:
+ case 12000:
+ rfs = (bfs == 48) ? 768 : 512;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rclk = params_rate(params) * rfs;
+
+ switch (rclk) {
+ case 4096000:
+ case 5644800:
+ case 6144000:
+ case 8467200:
+ case 9216000:
+ psr = 8;
+ break;
+ case 8192000:
+ case 11289600:
+ case 12288000:
+ case 16934400:
+ case 18432000:
+ psr = 4;
+ break;
+ case 22579200:
+ case 24576000:
+ case 33868800:
+ case 36864000:
+ psr = 2;
+ break;
+ case 67737600:
+ case 73728000:
+ psr = 1;
+ break;
+ default:
+ printk(KERN_ERR "Not yet supported!\n");
+ return -EINVAL;
+ }
+
+ set_epll_rate(rclk * psr);
+
+ /* Set the Codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* Set the AP DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, rfs,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, SAMSUNG_I2S_DIV_BCLK, bfs);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops origen_ops = {
+ .hw_params = origen_hw_params,
+};
+
+static int origen_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link origen_dai[] = {
+ { /* Primary DAI i/f */
+ .name = "ALC5625 PAIF",
+ .stream_name = "Pri_Dai",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "alc5625-aif1",
+ .platform_name = "samsung-audio",
+ .codec_name = "alc5625-codec.1-001e",
+ .init = origen_wm8994_init_paiftx,
+ .ops = &origen_ops,
+ },
+};
+
+static struct snd_soc_card snd_soc_origen_audio = {
+ .name = "ORIGEN-I2S",
+ .dai_link = origen_dai,
+ .num_links = ARRAY_SIZE(origen_dai),
+};
+
+static int __devinit origen_audio_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct snd_soc_card *card = &snd_soc_origen_audio;
+
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+
+ return ret;
+}
+
+static int __devexit origen_audio_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static const struct of_device_id origen_audio_of_match[] = {
+ { .compatible = "samsung,origen_audio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, origen_audio_of_match);
+
+static struct platform_driver origen_audio_driver = {
+ .driver = {
+ .name = "origen-audio",
+ .owner = THIS_MODULE,
+ .of_match_table = origen_audio_of_match,
+ },
+ .probe = origen_audio_probe,
+ .remove = __devexit_p(origen_audio_remove),
+};
+
+static int __init origen_audio_init(void)
+{
+ return platform_driver_register(&origen_audio_driver);
+}
+late_initcall(origen_audio_init);
+
+static void __exit origen_audio_exit(void)
+{
+ platform_driver_unregister(&origen_audio_driver);
+}
+module_exit(origen_audio_exit);
+
+MODULE_AUTHOR("Pan, <pan@insignal.co.kr>");
+MODULE_DESCRIPTION("ALSA SoC ORIGEN+ALC5625");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:origen-audio");
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index b179dbab93b..921e25ee911 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -577,7 +577,7 @@ static int FlashSectorErase(struct bcm_mini_adapter *Adapter,
* the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms
* won't hamper performance in any case.
*/
- udelay(10000);
+ mdelay(10);
} while ((uiStatus & 0x1) && (iRetries < 400));
if (uiStatus & 0x1) {
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 207c8adfcce..5873f56ed29 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -988,6 +988,9 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+ wr_regl(port, S3C64XX_UINTP, 0xf);
+
/* some delay is required after fifo reset */
udelay(1);
}
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9d5cee9a871..5b8ae76e42d 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -834,6 +834,13 @@ config USB_G_ANDROID
Each function can be configured and enabled/disabled
dynamically from userspace through a sysfs interface.
+config USB_G_RNDIS_DWORD_ALIGNED
+ bool "RNDIS Dword Aligned support"
+ depends on USB_G_ANDROID
+ default y
+ help
+ Provides dword aligned for DMA controller.
+
config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
depends on NET
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 0bb617e1dda..edd3388346d 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -28,6 +28,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/ch9.h>
@@ -3485,6 +3486,8 @@ static void s3c_hsotg_release(struct device *dev)
kfree(hsotg);
}
+static u64 s3c_hsotg_dma_mask = DMA_BIT_MASK(32);
+
/**
* s3c_hsotg_probe - probe function for hsotg driver
* @pdev: The platform information for the driver
@@ -3507,6 +3510,14 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
return -EINVAL;
}
+ /*
+ * Right now device-tree probed devices don't get dma_mask set.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &s3c_hsotg_dma_mask;
+ if (!pdev->dev.coherent_dma_mask)
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
if (!hsotg) {
dev_err(dev, "cannot get memory\n");
@@ -3704,10 +3715,19 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
#define s3c_hsotg_resume NULL
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_hsotg_match[] = {
+ { .compatible = "samsung,exynos-hsotg" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_hsotg_match);
+#endif
+
static struct platform_driver s3c_hsotg_driver = {
.driver = {
.name = "s3c-hsotg",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(exynos_hsotg_match),
},
.probe = s3c_hsotg_probe,
.remove = __devexit_p(s3c_hsotg_remove),
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 0e523092615..cef635a9516 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -240,13 +240,15 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
DBG(dev, "no rx skb\n");
goto enomem;
}
-
+#ifndef USB_G_RNDIS_DWORD_ALIGNED
/* Some platforms perform better when IP packets are aligned,
* but on at least one, checksumming fails otherwise. Note:
* RNDIS headers involve variable numbers of LE32 values.
*/
skb_reserve(skb, NET_IP_ALIGN);
+#endif
+
req->buf = skb->data;
req->length = size;
req->complete = rx_complete;
@@ -476,6 +478,10 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req)
spin_unlock(&dev->req_lock);
dev_kfree_skb_any(skb);
+#ifdef USB_G_RNDIS_DWORD_ALIGNED
+ if (req->buf != skb->data)
+ kfree(req->buf);
+#endif
atomic_dec(&dev->tx_qlen);
if (netif_carrier_ok(dev->net))
netif_wake_queue(dev->net);
@@ -569,7 +575,18 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
length = skb->len;
}
+#ifdef USB_G_RNDIS_DWORD_ALIGNED
+if ((int)skb->data & 3) {
+ req->buf = kmalloc(skb->len, GFP_ATOMIC);
+ if (!req->buf)
+ goto drop;
+ memcpy((void *)req->buf, (void *)skb->data, skb->len);
+ } else {
+ req->buf = skb->data;
+ }
+#else
req->buf = skb->data;
+#endif
req->context = skb;
req->complete = tx_complete;
@@ -611,6 +628,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
dev_kfree_skb_any(skb);
drop:
dev->net->stats.tx_dropped++;
+#ifdef USB_G_RNDIS_DWORD_ALIGNED
+ if (req->buf != skb->data)
+ kfree(req->buf);
+#endif
spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs))
netif_start_queue(net);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d55a33aa94c..727fa16536a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -25,6 +25,8 @@ source "drivers/gpu/stub/Kconfig"
source "drivers/gpu/ion/Kconfig"
+source "drivers/gpu/arm/Kconfig"
+
config VGASTATE
tristate
default n
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index cf282763a8d..09fa1d4d848 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -86,6 +86,13 @@ config LCD_PLATFORM
This driver provides a platform-device registered LCD power
control interface.
+config LCD_PWRCTRL
+ tristate "LCD panel power control"
+ help
+ Say y here, if you have a lcd panel that allows reset and vcc to be
+ controlled by the host system, and which does not use a serial command
+ interface (such as i2c or spi) or memory-mapped-io interface.
+
config LCD_TOSA
tristate "Sharp SL-6000 LCD Driver"
depends on I2C && SPI && MACH_TOSA
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index a2ac9cfbaf6..915650e0103 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
obj-$(CONFIG_LCD_ILI9320) += ili9320.o
obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
+obj-$(CONFIG_LCD_PWRCTRL) += lcd_pwrctrl.o
obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
diff --git a/drivers/video/backlight/lcd_pwrctrl.c b/drivers/video/backlight/lcd_pwrctrl.c
new file mode 100644
index 00000000000..917d842523c
--- /dev/null
+++ b/drivers/video/backlight/lcd_pwrctrl.c
@@ -0,0 +1,226 @@
+/*
+ * Simple lcd panel power control driver.
+ *
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2012 Linaro Ltd.
+ *
+ * This driver is for controlling power for raster type lcd panels that requires
+ * its nRESET interface line to be connected and controlled by a GPIO of the
+ * host system and the Vcc line controlled by a voltage regulator. This
+ * excludes support for lcd panels that use a serial command interface or direct
+ * memory mapped IO interface.
+ *
+ * The nRESET interface line of the panel should be connected to a gpio of the
+ * host system. The Vcc pin is controlled using a external volatage regulator.
+ * Panel backlight is not controlled by this driver.
+ *
+ * This driver is derived from platform-lcd.c which was written by
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/lcd.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <video/lcd_pwrctrl.h>
+
+struct lcd_pwrctrl {
+ struct device *dev;
+ struct lcd_device *lcd;
+ struct lcd_pwrctrl_data *pdata;
+ struct regulator *regulator;
+ unsigned int power;
+ bool suspended;
+ bool pwr_en;
+};
+
+static int lcd_pwrctrl_get_power(struct lcd_device *lcd)
+{
+ struct lcd_pwrctrl *lp = lcd_get_data(lcd);
+ return lp->power;
+}
+
+static int lcd_pwrctrl_set_power(struct lcd_device *lcd, int power)
+{
+ struct lcd_pwrctrl *lp = lcd_get_data(lcd);
+ struct lcd_pwrctrl_data *pd = lp->pdata;
+ bool lcd_enable;
+ int lcd_reset, ret = 0;
+
+ lcd_enable = (power == FB_BLANK_POWERDOWN || lp->suspended) ? 0 : 1;
+ lcd_reset = (pd->invert) ? !lcd_enable : lcd_enable;
+
+ if (lp->pwr_en == lcd_enable)
+ return 0;
+
+ if (!IS_ERR_OR_NULL(lp->regulator)) {
+ if (lcd_enable) {
+ if (regulator_enable(lp->regulator)) {
+ dev_info(lp->dev, "regulator enable failed\n");
+ ret = -EPERM;
+ }
+ } else {
+ if (regulator_disable(lp->regulator)) {
+ dev_info(lp->dev, "regulator disable failed\n");
+ ret = -EPERM;
+ }
+ }
+ }
+
+ gpio_direction_output(lp->pdata->gpio, lcd_reset);
+ lp->power = power;
+ lp->pwr_en = lcd_enable;
+ return ret;
+}
+
+static int lcd_pwrctrl_check_fb(struct lcd_device *lcd, struct fb_info *info)
+{
+ struct lcd_pwrctrl *lp = lcd_get_data(lcd);
+ return lp->dev->parent == info->device;
+}
+
+static struct lcd_ops lcd_pwrctrl_ops = {
+ .get_power = lcd_pwrctrl_get_power,
+ .set_power = lcd_pwrctrl_set_power,
+ .check_fb = lcd_pwrctrl_check_fb,
+};
+
+#ifdef CONFIG_OF
+static void __devinit lcd_pwrctrl_parse_dt(struct device *dev,
+ struct lcd_pwrctrl_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+
+ pdata->gpio = of_get_named_gpio(np, "lcd-reset-gpio", 0);
+ if (of_get_property(np, "lcd-reset-active-high", NULL))
+ pdata->invert = true;
+}
+#endif
+
+static int __devinit lcd_pwrctrl_probe(struct platform_device *pdev)
+{
+ struct lcd_pwrctrl *lp;
+ struct lcd_pwrctrl_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ int err;
+
+#ifdef CONFIG_OF
+ if (dev->of_node) {
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "memory allocation for pdata failed\n");
+ return -ENOMEM;
+ }
+ lcd_pwrctrl_parse_dt(dev, pdata);
+ }
+#endif
+
+ if (!pdata) {
+ dev_err(dev, "platform data not available\n");
+ return -EINVAL;
+ }
+
+ lp = devm_kzalloc(dev, sizeof(struct lcd_pwrctrl), GFP_KERNEL);
+ if (!lp) {
+ dev_err(dev, "memory allocation failed for private data\n");
+ return -ENOMEM;
+ }
+
+ err = gpio_request(pdata->gpio, "LCD-nRESET");
+ if (err) {
+ dev_err(dev, "gpio [%d] request failed\n", pdata->gpio);
+ return err;
+ }
+
+ /*
+ * If power to lcd and/or lcd interface is controlled using a regulator,
+ * get the handle to the regulator for later use during power switching.
+ */
+ lp->regulator = devm_regulator_get(dev, "vcc-lcd");
+ if (IS_ERR(lp->regulator))
+ dev_info(dev, "could not find regulator\n");
+
+ lp->dev = dev;
+ lp->pdata = pdata;
+ lp->lcd = lcd_device_register(dev_name(dev), dev, lp, &lcd_pwrctrl_ops);
+ if (IS_ERR(lp->lcd)) {
+ dev_err(dev, "cannot register lcd device\n");
+ gpio_free(pdata->gpio);
+ return PTR_ERR(lp->lcd);
+ }
+
+ platform_set_drvdata(pdev, lp);
+ lcd_pwrctrl_set_power(lp->lcd, FB_BLANK_NORMAL);
+ return 0;
+}
+
+static int __devexit lcd_pwrctrl_remove(struct platform_device *pdev)
+{
+ struct lcd_pwrctrl *lp = platform_get_drvdata(pdev);
+ lcd_device_unregister(lp->lcd);
+ gpio_free(lp->pdata->gpio);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int lcd_pwrctrl_suspend(struct device *dev)
+{
+ struct lcd_pwrctrl *lp = dev_get_drvdata(dev);
+
+ lp->suspended = true;
+ lcd_pwrctrl_set_power(lp->lcd, FB_BLANK_POWERDOWN);
+ return 0;
+}
+
+static int lcd_pwrctrl_resume(struct device *dev)
+{
+ struct lcd_pwrctrl *lp = dev_get_drvdata(dev);
+
+ lp->suspended = false;
+ lcd_pwrctrl_set_power(lp->lcd, FB_BLANK_UNBLANK);
+ return 0;
+}
+
+static const struct dev_pm_ops lcd_pwrctrl_dev_pm_ops = {
+ .suspend = lcd_pwrctrl_suspend,
+ .resume = lcd_pwrctrl_resume,
+};
+
+#define LCD_PWRCTRL_DEV_PM_OPS (&lcd_pwrctrl_dev_pm_ops)
+#else
+#define LCD_PWRCTRL_DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_OF
+static const struct of_device_id lcd_pwrctrl_match[] = {
+ { .compatible = "lcd-powercontrol", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, lcd_pwrctrl_match);
+#endif
+
+static struct platform_driver lcd_pwrctrl_driver = {
+ .driver = {
+ .name = "lcd-pwrctrl",
+ .owner = THIS_MODULE,
+ .pm = LCD_PWRCTRL_DEV_PM_OPS,
+ .of_match_table = of_match_ptr(lcd_pwrctrl_match),
+ },
+ .probe = lcd_pwrctrl_probe,
+ .remove = lcd_pwrctrl_remove,
+};
+
+module_platform_driver(lcd_pwrctrl_driver);
+
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:lcd-pwrctrl");
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 995f0164c9b..35893050d66 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -277,6 +277,15 @@ static int pwm_backlight_remove(struct platform_device *pdev)
return 0;
}
+static void pwm_backlight_shutdown(struct platform_device *pdev)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
+
+ pwm_config(pb->pwm, 0, pb->period);
+ pwm_disable(pb->pwm);
+}
+
#ifdef CONFIG_PM
static int pwm_backlight_suspend(struct device *dev)
{
@@ -316,6 +325,7 @@ static struct platform_driver pwm_backlight_driver = {
},
.probe = pwm_backlight_probe,
.remove = pwm_backlight_remove,
+ .shutdown = pwm_backlight_shutdown,
};
module_platform_driver(pwm_backlight_driver);
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index f175240b225..63e97b130f3 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -24,6 +24,8 @@
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <mach/map.h>
#include <plat-samsung/regs-fb-v4.h>
@@ -67,6 +69,8 @@ struct s3c_fb;
#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
+#define S3CFB_WIN_SET_PIXEL_ALPHA _IOW('F', 204, __u32)
+
/**
* struct s3c_fb_variant - fb variant information
* @is_2443: Set if S3C2443/S3C2416 style hardware.
@@ -220,6 +224,7 @@ struct s3c_fb {
int irq_no;
unsigned long irq_flags;
struct s3c_fb_vsync vsync_info;
+ int *gpios;
};
/**
@@ -1013,6 +1018,33 @@ static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
return 0;
}
+int s3cfb_set_alpha_blending(struct s3c_fb *ctrl, int id)
+{
+ u32 avalue = 0, cfg;
+
+ if (id == 0) {
+ dev_err(ctrl->dev, "[fb%d] does not support alpha blending\n",
+ id);
+ return -EINVAL;
+ }
+
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+ cfg |= (1 << 0);
+ writel(cfg, ctrl->regs + S3C_WINCON(id));
+ cfg = readl(ctrl->regs + S3C_WINSHMAP);
+ cfg |= S3C_WINSHMAP_CH_ENABLE(id);
+ writel(cfg, ctrl->regs + S3C_WINSHMAP);
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+ cfg &= ~(S3C_WINCON_BLD_MASK | S3C_WINCON_ALPHA_SEL_MASK);
+
+ cfg |= (S3C_WINCON_BLD_PIXEL | S3C_WINCON_ALPHA1_SEL);
+ writel(cfg, ctrl->regs + S3C_WINCON(id));
+ writel(avalue, ctrl->regs + S3C_VIDOSD_C(id));
+
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+ return 0;
+}
+
static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
@@ -1030,6 +1062,9 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
ret = s3c_fb_wait_for_vsync(sfb, crtc);
break;
+ case S3CFB_WIN_SET_PIXEL_ALPHA:
+ ret = s3cfb_set_alpha_blending(sfb, win->index);
+ break;
default:
ret = -ENOTTY;
}
@@ -1037,8 +1072,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
return ret;
}
+int s3c_fb_open(struct fb_info *info, int user)
+{
+ s3c_fb_set_par(info);
+ return 0;
+}
+
+int s3c_fb_release(struct fb_info *info, int user)
+{
+ struct s3c_fb_win *win = info->par;
+ struct s3c_fb *sfb = win->parent;
+ void __iomem *regs = sfb->regs;
+ int win_no = win->index;
+
+ if (win_no != 2) {
+ printk(KERN_DEBUG"Releasing window %d\n", win_no);
+ writel(0, regs + WINCON(win_no));
+ }
+ return 0;
+}
+
static struct fb_ops s3c_fb_ops = {
.owner = THIS_MODULE,
+ .fb_open = s3c_fb_open,
+ .fb_release = s3c_fb_release,
.fb_check_var = s3c_fb_check_var,
.fb_set_par = s3c_fb_set_par,
.fb_blank = s3c_fb_blank,
@@ -1268,8 +1325,6 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
else
dev_err(sfb->dev, "failed to allocate fb cmap\n");
- s3c_fb_set_par(fbinfo);
-
dev_dbg(sfb->dev, "about to register framebuffer\n");
/* run the check_var and set_par on our configuration. */
@@ -1358,27 +1413,215 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
}
}
+#ifdef CONFIG_OF
+static int s3c_fb_dt_parse_gpios(struct device *dev, struct s3c_fb *sfb,
+ bool request)
+{
+ int nr_gpios, idx, gpio, ret;
+
+ nr_gpios = sfb->pdata->win[0]->max_bpp + 4;
+ sfb->gpios = devm_kzalloc(dev, sizeof(int) * nr_gpios, GFP_KERNEL);
+ if (!sfb->gpios) {
+ dev_err(dev, "unable to allocate private data for gpio\n");
+ return -ENOMEM;
+ }
+
+ for (idx = 0; idx < nr_gpios; idx++) {
+ gpio = of_get_gpio(dev->of_node, idx);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio);
+ return -EINVAL;
+ }
+
+ if (!request)
+ continue;
+
+ ret = gpio_request(gpio, "fimd");
+ if (ret) {
+ dev_err(dev, "gpio [%d] request failed\n", gpio);
+ goto gpio_free;
+ }
+ sfb->gpios[idx] = gpio;
+ }
+ return 0;
+
+gpio_free:
+ while (--idx >= 0)
+ gpio_free(sfb->gpios[idx]);
+ return ret;
+}
+
+static void s3c_fb_dt_free_gpios(struct s3c_fb *sfb)
+{
+ unsigned int idx, nr_gpio;
+
+ nr_gpio = sfb->pdata->win[0]->max_bpp + 4;
+ for (idx = 0; idx < nr_gpio; idx++)
+ gpio_free(sfb->gpios[idx]);
+}
+
+static struct s3c_fb_platdata *s3c_fb_dt_parse_pdata(struct device *dev)
+{
+ struct device_node *np = dev->of_node, *win_np;
+ struct device_node *disp_np;
+ struct s3c_fb_platdata *pd;
+ struct s3c_fb_pd_win *win;
+ u32 wnum = 0, data[4];
+
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ dev_err(dev, "memory allocation for pdata failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pd->vtiming = devm_kzalloc(dev, sizeof(*pd->vtiming), GFP_KERNEL);
+ if (!pd->vtiming) {
+ dev_err(dev, "memory allocation for vtiming failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (of_get_property(np, "samsung,fimd-vidout-rgb", NULL))
+ pd->vidcon0 |= VIDCON0_VIDOUT_RGB;
+ if (of_get_property(np, "samsung,fimd-vidout-tv", NULL))
+ pd->vidcon0 |= VIDCON0_VIDOUT_TV;
+ if (of_get_property(np, "samsung,fimd-inv-hsync", NULL))
+ pd->vidcon1 |= VIDCON1_INV_HSYNC;
+ if (of_get_property(np, "samsung,fimd-inv-vsync", NULL))
+ pd->vidcon1 |= VIDCON1_INV_VSYNC;
+ if (of_get_property(np, "samsung,fimd-inv-vclk", NULL))
+ pd->vidcon1 |= VIDCON1_INV_VCLK;
+ if (of_get_property(np, "samsung,fimd-inv-vden", NULL))
+ pd->vidcon1 |= VIDCON1_INV_VDEN;
+
+ disp_np = of_parse_phandle(np, "samsung,fimd-display", 0);
+ if (!disp_np) {
+ dev_err(dev, "unable to find display panel info\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32_array(disp_np, "lcd-htiming", data, 4)) {
+ dev_err(dev, "invalid horizontal timing\n");
+ return ERR_PTR(-EINVAL);
+ }
+ pd->vtiming->left_margin = data[0];
+ pd->vtiming->right_margin = data[1];
+ pd->vtiming->hsync_len = data[2];
+ pd->vtiming->xres = data[3];
+
+ if (of_property_read_u32_array(disp_np, "lcd-vtiming", data, 4)) {
+ dev_err(dev, "invalid vertical timing\n");
+ return ERR_PTR(-EINVAL);
+ }
+ pd->vtiming->upper_margin = data[0];
+ pd->vtiming->lower_margin = data[1];
+ pd->vtiming->vsync_len = data[2];
+ pd->vtiming->yres = data[3];
+
+ of_property_read_u32_array(np, "samsung,fimd-frame-rate",
+ &pd->vtiming->refresh, 1);
+
+ for_each_child_of_node(np, win_np) {
+ if (of_property_read_u32_array(win_np, "samsung,fimd-win-id",
+ &wnum, 1)) {
+ dev_err(dev, "window id not specified\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ win = devm_kzalloc(dev, sizeof(*win), GFP_KERNEL);
+ if (!win) {
+ dev_err(dev, "no memory for window[%d] data\n", wnum);
+ return ERR_PTR(-ENOMEM);
+ }
+ pd->win[wnum] = win;
+
+ if (of_property_read_u32_array(win_np, "samsung,fimd-win-bpp",
+ data, 2)) {
+ dev_err(dev, "invalid window bpp\n");
+ return ERR_PTR(-EINVAL);
+ }
+ win->default_bpp = data[0];
+ win->max_bpp = data[1];
+
+ if (of_property_read_u32_array(win_np, "samsung,fimd-win-res",
+ data, 2)) {
+ dev_info(dev, "window [%d] resolution not specified. "
+ "Using lcd resolution X[%d] and Y[%d]", wnum,
+ pd->vtiming->xres, pd->vtiming->yres);
+ win->xres = pd->vtiming->xres;
+ win->yres = pd->vtiming->yres;
+ } else {
+ win->xres = data[0];
+ win->yres = data[1];
+ }
+
+ if (!of_property_read_u32_array(win_np,
+ "samsung,fimd-win-virtres", data, 2)) {
+ win->virtual_x = data[0];
+ win->virtual_y = data[1];
+ }
+ }
+
+ return pd;
+}
+#else
+static int s3c_fb_dt_parse_gpios(struct device *dev, struct s3c_fb *sfb,
+ bool request)
+{
+ return 0;
+}
+
+static void s3c_fb_dt_free_gpios(struct s3c_fb *sfb)
+{
+ return 0;
+}
+
+static int s3c_fb_dt_parse_pdata(struct device *dev,
+ struct s3c_fb_platdata **pdata)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+static const struct of_device_id s3c_fb_dt_match[];
+
+static inline struct s3c_fb_driverdata *s3c_fb_get_driver_data(
+ struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(s3c_fb_dt_match, pdev->dev.of_node);
+ return (struct s3c_fb_driverdata *)match->data;
+ }
+#endif
+ return (struct s3c_fb_driverdata *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
static int __devinit s3c_fb_probe(struct platform_device *pdev)
{
- const struct platform_device_id *platid;
struct s3c_fb_driverdata *fbdrv;
struct device *dev = &pdev->dev;
- struct s3c_fb_platdata *pd;
+ struct s3c_fb_platdata *pd = pdev->dev.platform_data;
struct s3c_fb *sfb;
struct resource *res;
int win;
int ret = 0;
u32 reg;
- platid = platform_get_device_id(pdev);
- fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
+ fbdrv = s3c_fb_get_driver_data(pdev);
if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
dev_err(dev, "too many windows, cannot attach\n");
return -EINVAL;
}
- pd = pdev->dev.platform_data;
+ if (pdev->dev.of_node) {
+ pd = s3c_fb_dt_parse_pdata(&pdev->dev);
+ if (IS_ERR(pd))
+ return PTR_ERR(pd);
+ }
+
if (!pd) {
dev_err(dev, "no platform data specified\n");
return -EINVAL;
@@ -1455,7 +1698,12 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
/* setup gpio and output polarity controls */
- pd->setup_gpio();
+ if (dev->of_node) {
+ if (s3c_fb_dt_parse_gpios(dev, sfb, true))
+ goto err_lcd_clk;
+ } else {
+ pd->setup_gpio();
+ }
writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1505,6 +1753,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
return 0;
err_pm_runtime:
+ s3c_fb_dt_free_gpios(sfb);
pm_runtime_put_sync(sfb->dev);
err_lcd_clk:
@@ -1551,6 +1800,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
pm_runtime_put_sync(sfb->dev);
pm_runtime_disable(sfb->dev);
+ s3c_fb_dt_free_gpios(sfb);
return 0;
}
@@ -1601,7 +1851,10 @@ static int s3c_fb_resume(struct device *dev)
clk_enable(sfb->lcd_clk);
/* setup gpio and output polarity controls */
- pd->setup_gpio();
+ if (dev->of_node)
+ s3c_fb_dt_parse_gpios(dev, sfb, false);
+ else
+ pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
/* set video clock running at under-run */
@@ -1673,7 +1926,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
clk_enable(sfb->lcd_clk);
/* setup gpio and output polarity controls */
- pd->setup_gpio();
+ if (dev->of_node)
+ s3c_fb_dt_parse_gpios(dev, sfb, false);
+ else
+ pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
return 0;
@@ -2043,6 +2299,15 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
+#ifdef CONFIG_OF
+static const struct of_device_id s3c_fb_dt_match[] = {
+ { .compatible = "samsung,exynos4210-fimd",
+ .data = (void *)&s3c_fb_data_exynos4 },
+ {},
+};
+MODULE_DEVICE_TABLE(of, s3c_fb_dt_match);
+#endif
+
static const struct dev_pm_ops s3cfb_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
@@ -2057,6 +2322,7 @@ static struct platform_driver s3c_fb_driver = {
.name = "s3c-fb",
.owner = THIS_MODULE,
.pm = &s3cfb_pm_ops,
+ .of_match_table = of_match_ptr(s3c_fb_dt_match),
},
};
diff --git a/include/linux/ath6kl.h b/include/linux/ath6kl.h
new file mode 100644
index 00000000000..0e0ff495481
--- /dev/null
+++ b/include/linux/ath6kl.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_ATH6KL_PLATFORM_H
+#define _LINUX_ATH6KL_PLATFORM_H
+
+struct ath6kl_platform_data {
+ int (*setup_power)(bool);
+};
+
+#ifdef CONFIG_ATH6KL_PLATFORM_DATA
+int ath6kl_set_platform_data(const struct ath6kl_platform_data *data);
+#else
+static inline
+int ath6kl_set_platform_data(const struct ath6kl_platform_data *data)
+{
+ return -ENOSYS;
+}
+#endif
+
+const struct ath6kl_platform_data *ath6kl_get_platform_data(void);
+
+#endif /* _LINUX_ATH6KL_PLATFORM_H */
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index 830152cfae3..6ae21bf47d6 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -316,6 +316,7 @@ enum max8997_irq {
#define MAX8997_NUM_GPIO 12
struct max8997_dev {
struct device *dev;
+ struct max8997_platform_data *pdata;
struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
struct i2c_client *rtc; /* slave addr 0x0c */
struct i2c_client *haptic; /* slave addr 0x90 */
diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h
index 328d8e24b53..1d4a4fe6ac3 100644
--- a/include/linux/mfd/max8997.h
+++ b/include/linux/mfd/max8997.h
@@ -75,6 +75,7 @@ enum max8998_regulators {
struct max8997_regulator_data {
int id;
struct regulator_init_data *initdata;
+ struct device_node *reg_node;
};
enum max8997_muic_usb_type {
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 9afc01e5a0a..a2560f6391e 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -6,6 +6,7 @@
extern const char linux_banner[];
extern const char linux_proc_banner[];
+extern const char linux_scm_version_banner[];
static inline int printk_get_level(const char *buffer)
{
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 21d076c5089..87e7f45f663 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -124,6 +124,7 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
struct pwm_device *pwm_get(struct device *dev, const char *consumer);
void pwm_put(struct pwm_device *pwm);
+#endif
struct pwm_lookup {
struct list_head list;
@@ -141,8 +142,10 @@ struct pwm_lookup {
.con_id = _con_id, \
}
+#ifdef CONFIG_PWM
void pwm_add_table(struct pwm_lookup *table, size_t num);
-
+#else
+static void pwm_add_table(struct pwm_lookup *table, size_t num) {}
#endif
#endif /* __LINUX_PWM_H */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 7a147c8299a..07ac797f09b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1388,8 +1388,10 @@ enum v4l2_colorfx {
#define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41)
#define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
+#define V4L2_CID_CODEC_FRAME_TAG (V4L2_CID_BASE+43)
/* last CID + 1 */
-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+43)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
+
/* MPEG-class control IDs defined by V4L2 */
#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
diff --git a/include/linux/videodev2_samsung.h b/include/linux/videodev2_samsung.h
new file mode 100644
index 00000000000..dbb24d11fe9
--- /dev/null
+++ b/include/linux/videodev2_samsung.h
@@ -0,0 +1,656 @@
+/*
+ * Video for Linux Two header file for samsung
+ *
+ * Copyright (C) 2009, Dongsoo Nathaniel Kim<dongsoo45.kim@samsung.com>
+ *
+ * This header file contains several v4l2 APIs to be proposed to v4l2
+ * community and until bein accepted, will be used restrictly in Samsung's
+ * camera interface driver FIMC.
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_VIDEODEV2_SAMSUNG_H
+#define __LINUX_VIDEODEV2_SAMSUNG_H
+
+/* Values for 'capabilities' field */
+/* Object detection device */
+#define V4L2_CAP_OBJ_RECOGNITION 0x10000000
+/* strobe control */
+#define V4L2_CAP_STROBE 0x20000000
+
+
+#define V4L2_CID_FOCUS_MODE (V4L2_CID_CAMERA_CLASS_BASE+17)
+/* Focus Methods */
+enum v4l2_focus_mode {
+ V4L2_FOCUS_MODE_AUTO = 0,
+ V4L2_FOCUS_MODE_MACRO = 1,
+ V4L2_FOCUS_MODE_MANUAL = 2,
+ V4L2_FOCUS_MODE_LASTP = 2,
+};
+
+#define V4L2_CID_ZOOM_MODE (V4L2_CID_CAMERA_CLASS_BASE+18)
+/* Zoom Methods */
+enum v4l2_zoom_mode {
+ V4L2_ZOOM_MODE_CONTINUOUS = 0,
+ V4L2_ZOOM_MODE_OPTICAL = 1,
+ V4L2_ZOOM_MODE_DIGITAL = 2,
+ V4L2_ZOOM_MODE_LASTP = 2,
+};
+
+/* Exposure Methods */
+#define V4L2_CID_PHOTOMETRY (V4L2_CID_CAMERA_CLASS_BASE+19)
+enum v4l2_photometry_mode {
+ V4L2_PHOTOMETRY_MULTISEG = 0, /*Multi Segment*/
+ V4L2_PHOTOMETRY_CWA = 1, /*Centre Weighted Average*/
+ V4L2_PHOTOMETRY_SPOT = 2,
+ V4L2_PHOTOMETRY_AFSPOT = 3, /*Spot metering on focused point*/
+ V4L2_PHOTOMETRY_LASTP = V4L2_PHOTOMETRY_AFSPOT,
+};
+
+/* Manual exposure control items menu type: iris, shutter, iso */
+#define V4L2_CID_CAM_APERTURE (V4L2_CID_CAMERA_CLASS_BASE+20)
+#define V4L2_CID_CAM_SHUTTER (V4L2_CID_CAMERA_CLASS_BASE+21)
+#define V4L2_CID_CAM_ISO (V4L2_CID_CAMERA_CLASS_BASE+22)
+
+/* Following CIDs are menu type */
+#define V4L2_CID_SCENEMODE (V4L2_CID_CAMERA_CLASS_BASE+23)
+#define V4L2_CID_CAM_STABILIZE (V4L2_CID_CAMERA_CLASS_BASE+24)
+#define V4L2_CID_CAM_MULTISHOT (V4L2_CID_CAMERA_CLASS_BASE+25)
+
+/* Control dynamic range */
+#define V4L2_CID_CAM_DR (V4L2_CID_CAMERA_CLASS_BASE+26)
+
+/* White balance preset control */
+#define V4L2_CID_WHITE_BALANCE_PRESET (V4L2_CID_CAMERA_CLASS_BASE+27)
+
+/* CID extensions */
+#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_OVERLAY_AUTO (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_OVERLAY_VADDR0 (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_OVERLAY_VADDR1 (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_OVERLAY_VADDR2 (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_DST_INFO (V4L2_CID_PRIVATE_BASE + 10)
+
+/* UMP secure id control */
+#define V4L2_CID_GET_UMP_SECURE_ID (V4L2_CID_PRIVATE_BASE + 11)
+#define V4L2_CID_GET_PHY_SRC_YADDR (V4L2_CID_PRIVATE_BASE + 12)
+#define V4L2_CID_GET_PHY_SRC_CADDR (V4L2_CID_PRIVATE_BASE + 13)
+#define V4L2_CID_IMAGE_EFFECT_FN (V4L2_CID_PRIVATE_BASE + 16)
+#define V4L2_CID_IMAGE_EFFECT_APPLY (V4L2_CID_PRIVATE_BASE + 17)
+#define V4L2_CID_IMAGE_EFFECT_CB (V4L2_CID_PRIVATE_BASE + 18)
+#define V4L2_CID_IMAGE_EFFECT_CR (V4L2_CID_PRIVATE_BASE + 19)
+#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20)
+#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21)
+
+#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53)
+
+/* CID Extensions for camera sensor operations */
+#define V4L2_CID_CAM_PREVIEW_ONOFF (V4L2_CID_PRIVATE_BASE + 64)
+#define V4L2_CID_CAM_CAPTURE (V4L2_CID_PRIVATE_BASE + 65)
+
+#define V4L2_CID_CAM_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 14)
+#define V4L2_CID_CAM_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 15)
+#define V4L2_CID_CAM_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 22)
+#define V4L2_CID_CAM_SENSOR_VER (V4L2_CID_PRIVATE_BASE + 23)
+#define V4L2_CID_CAM_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 24)
+#define V4L2_CID_CAM_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 25)
+#define V4L2_CID_CAM_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 26)
+#define V4L2_CID_CAM_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 27)
+#define V4L2_CID_CAM_FW_VER (V4L2_CID_PRIVATE_BASE + 28)
+#define V4L2_CID_CAM_SET_FW_ADDR (V4L2_CID_PRIVATE_BASE + 29)
+#define V4L2_CID_CAM_SET_FW_SIZE (V4L2_CID_PRIVATE_BASE + 30)
+#define V4L2_CID_CAM_UPDATE_FW (V4L2_CID_PRIVATE_BASE + 31)
+#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32)
+#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33)
+#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34)
+#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35)
+#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36)
+#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37)
+#define V4L2_CID_CAM_SENSOR_MAKER (V4L2_CID_PRIVATE_BASE + 38)
+#define V4L2_CID_CAM_SENSOR_OPTICAL (V4L2_CID_PRIVATE_BASE + 39)
+#define V4L2_CID_CAM_AF_VER_LOW (V4L2_CID_PRIVATE_BASE + 40)
+#define V4L2_CID_CAM_AF_VER_HIGH (V4L2_CID_PRIVATE_BASE + 41)
+#define V4L2_CID_CAM_GAMMA_RG_LOW (V4L2_CID_PRIVATE_BASE + 42)
+#define V4L2_CID_CAM_GAMMA_RG_HIGH (V4L2_CID_PRIVATE_BASE + 43)
+#define V4L2_CID_CAM_GAMMA_BG_LOW (V4L2_CID_PRIVATE_BASE + 44)
+#define V4L2_CID_CAM_GAMMA_BG_HIGH (V4L2_CID_PRIVATE_BASE + 45)
+#define V4L2_CID_CAM_DUMP_FW (V4L2_CID_PRIVATE_BASE + 46)
+#define V4L2_CID_CAM_GET_DUMP_SIZE (V4L2_CID_PRIVATE_BASE + 47)
+#define V4L2_CID_CAMERA_VT_MODE (V4L2_CID_PRIVATE_BASE + 48)
+#define V4L2_CID_CAMERA_VGA_BLUR (V4L2_CID_PRIVATE_BASE + 49)
+#define V4L2_CID_CAMERA_CAPTURE (V4L2_CID_PRIVATE_BASE + 50)
+
+#define V4L2_CID_MAIN_SW_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 54)
+#define V4L2_CID_MAIN_SW_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 55)
+#define V4L2_CID_MAIN_SW_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 56)
+#define V4L2_CID_MAIN_SW_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 57)
+#define V4L2_CID_MAIN_SW_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 58)
+#define V4L2_CID_MAIN_SW_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 59)
+#define V4L2_CID_MAIN_SW_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 60)
+
+enum v4l2_blur {
+ BLUR_LEVEL_0 = 0,
+ BLUR_LEVEL_1,
+ BLUR_LEVEL_2,
+ BLUR_LEVEL_3,
+ BLUR_LEVEL_MAX,
+};
+
+#define V4L2_CID_CAMERA_SCENE_MODE (V4L2_CID_PRIVATE_BASE + 70)
+enum v4l2_scene_mode_samsung {
+ SCENE_MODE_BASE,
+ SCENE_MODE_NONE,
+ SCENE_MODE_PORTRAIT,
+ SCENE_MODE_NIGHTSHOT,
+ SCENE_MODE_BACK_LIGHT,
+ SCENE_MODE_LANDSCAPE,
+ SCENE_MODE_SPORTS,
+ SCENE_MODE_PARTY_INDOOR,
+ SCENE_MODE_BEACH_SNOW,
+ SCENE_MODE_SUNSET,
+ SCENE_MODE_DUST_DAWN,
+ SCENE_MODE_FALL_COLOR,
+ SCENE_MODE_FIREWORKS,
+ SCENE_MODE_TEXT,
+ SCENE_MODE_CANDLE_LIGHT,
+ SCENE_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_FLASH_MODE (V4L2_CID_PRIVATE_BASE + 71)
+enum v4l2_flash_mode {
+ FLASH_MODE_BASE,
+ FLASH_MODE_OFF,
+ FLASH_MODE_AUTO,
+ FLASH_MODE_ON,
+ FLASH_MODE_TORCH,
+ FLASH_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_BRIGHTNESS (V4L2_CID_PRIVATE_BASE + 72)
+enum v4l2_ev_mode {
+ EV_MINUS_4 = 0,
+ EV_MINUS_3,
+ EV_MINUS_2,
+ EV_MINUS_1,
+ EV_DEFAULT,
+ EV_PLUS_1,
+ EV_PLUS_2,
+ EV_PLUS_3,
+ EV_PLUS_4,
+ EV_MAX,
+};
+
+#define V4L2_CID_CAMERA_WHITE_BALANCE (V4L2_CID_PRIVATE_BASE + 73)
+enum v4l2_wb_mode {
+ WHITE_BALANCE_BASE = 0,
+ WHITE_BALANCE_AUTO,
+ WHITE_BALANCE_SUNNY,
+ WHITE_BALANCE_CLOUDY,
+ WHITE_BALANCE_TUNGSTEN,
+ WHITE_BALANCE_FLUORESCENT,
+ WHITE_BALANCE_MAX,
+};
+
+#define V4L2_CID_CAMERA_EFFECT (V4L2_CID_PRIVATE_BASE + 74)
+enum v4l2_effect_mode {
+ IMAGE_EFFECT_BASE = 0,
+ IMAGE_EFFECT_NONE,
+ IMAGE_EFFECT_BNW,
+ IMAGE_EFFECT_SEPIA,
+ IMAGE_EFFECT_AQUA,
+ IMAGE_EFFECT_ANTIQUE,
+ IMAGE_EFFECT_NEGATIVE,
+ IMAGE_EFFECT_SHARPEN,
+ IMAGE_EFFECT_MAX,
+};
+
+#define V4L2_CID_CAMERA_ISO (V4L2_CID_PRIVATE_BASE + 75)
+enum v4l2_iso_mode {
+ ISO_AUTO = 0,
+ ISO_50,
+ ISO_100,
+ ISO_200,
+ ISO_400,
+ ISO_800,
+ ISO_1600,
+ ISO_SPORTS,
+ ISO_NIGHT,
+ ISO_MOVIE,
+ ISO_MAX,
+};
+
+#define V4L2_CID_CAMERA_METERING (V4L2_CID_PRIVATE_BASE + 76)
+enum v4l2_metering_mode {
+ METERING_BASE = 0,
+ METERING_MATRIX,
+ METERING_CENTER,
+ METERING_SPOT,
+ METERING_MAX,
+};
+
+#define V4L2_CID_CAMERA_CONTRAST (V4L2_CID_PRIVATE_BASE + 77)
+enum v4l2_contrast_mode {
+ CONTRAST_MINUS_2 = 0,
+ CONTRAST_MINUS_1,
+ CONTRAST_DEFAULT,
+ CONTRAST_PLUS_1,
+ CONTRAST_PLUS_2,
+ CONTRAST_MAX,
+};
+
+#define V4L2_CID_CAMERA_SATURATION (V4L2_CID_PRIVATE_BASE + 78)
+enum v4l2_saturation_mode {
+ SATURATION_MINUS_2 = 0,
+ SATURATION_MINUS_1,
+ SATURATION_DEFAULT,
+ SATURATION_PLUS_1,
+ SATURATION_PLUS_2,
+ SATURATION_MAX,
+};
+
+#define V4L2_CID_CAMERA_SHARPNESS (V4L2_CID_PRIVATE_BASE + 79)
+enum v4l2_sharpness_mode {
+ SHARPNESS_MINUS_2 = 0,
+ SHARPNESS_MINUS_1,
+ SHARPNESS_DEFAULT,
+ SHARPNESS_PLUS_1,
+ SHARPNESS_PLUS_2,
+ SHARPNESS_MAX,
+};
+
+#define V4L2_CID_CAMERA_WDR (V4L2_CID_PRIVATE_BASE + 80)
+enum v4l2_wdr_mode {
+ WDR_OFF,
+ WDR_ON,
+ WDR_MAX,
+};
+
+#define V4L2_CID_CAMERA_ANTI_SHAKE (V4L2_CID_PRIVATE_BASE + 81)
+enum v4l2_anti_shake_mode {
+ ANTI_SHAKE_OFF,
+ ANTI_SHAKE_STILL_ON,
+ ANTI_SHAKE_MOVIE_ON,
+ ANTI_SHAKE_MAX,
+};
+
+#define V4L2_CID_CAMERA_TOUCH_AF_START_STOP (V4L2_CID_PRIVATE_BASE + 82)
+enum v4l2_touch_af {
+ TOUCH_AF_STOP = 0,
+ TOUCH_AF_START,
+ TOUCH_AF_MAX,
+};
+
+#define V4L2_CID_CAMERA_SMART_AUTO (V4L2_CID_PRIVATE_BASE + 83)
+enum v4l2_smart_auto {
+ SMART_AUTO_OFF = 0,
+ SMART_AUTO_ON,
+ SMART_AUTO_MAX,
+};
+
+#define V4L2_CID_CAMERA_VINTAGE_MODE (V4L2_CID_PRIVATE_BASE + 84)
+enum v4l2_vintage_mode {
+ VINTAGE_MODE_BASE,
+ VINTAGE_MODE_OFF,
+ VINTAGE_MODE_NORMAL,
+ VINTAGE_MODE_WARM,
+ VINTAGE_MODE_COOL,
+ VINTAGE_MODE_BNW,
+ VINTAGE_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 85)
+#define V4L2_CID_CAMERA_GPS_LATITUDE (V4L2_CID_CAMERA_CLASS_BASE + 30)
+#define V4L2_CID_CAMERA_GPS_LONGITUDE (V4L2_CID_CAMERA_CLASS_BASE + 31)
+#define V4L2_CID_CAMERA_GPS_TIMESTAMP (V4L2_CID_CAMERA_CLASS_BASE + 32)
+#define V4L2_CID_CAMERA_GPS_ALTITUDE (V4L2_CID_CAMERA_CLASS_BASE + 33)
+#define V4L2_CID_CAMERA_EXIF_TIME_INFO (V4L2_CID_CAMERA_CLASS_BASE + 34)
+#define V4L2_CID_CAMERA_ZOOM (V4L2_CID_PRIVATE_BASE + 90)
+enum v4l2_zoom_level {
+ ZOOM_LEVEL_0 = 0,
+ ZOOM_LEVEL_1,
+ ZOOM_LEVEL_2,
+ ZOOM_LEVEL_3,
+ ZOOM_LEVEL_4,
+ ZOOM_LEVEL_5,
+ ZOOM_LEVEL_6,
+ ZOOM_LEVEL_7,
+ ZOOM_LEVEL_8,
+ ZOOM_LEVEL_9,
+ ZOOM_LEVEL_10,
+ ZOOM_LEVEL_11,
+ ZOOM_LEVEL_12,
+ ZOOM_LEVEL_MAX,
+};
+
+#define V4L2_CID_CAMERA_FACE_DETECTION (V4L2_CID_PRIVATE_BASE + 91)
+enum v4l2_face_detection {
+ FACE_DETECTION_OFF = 0,
+ FACE_DETECTION_ON,
+ FACE_DETECTION_NOLINE,
+ FACE_DETECTION_ON_BEAUTY,
+ FACE_DETECTION_MAX,
+};
+
+#define V4L2_CID_CAMERA_SMART_AUTO_STATUS (V4L2_CID_PRIVATE_BASE + 92)
+enum v4l2_smart_auto_status {
+ SMART_AUTO_STATUS_AUTO = 0,
+ SMART_AUTO_STATUS_LANDSCAPE,
+ SMART_AUTO_STATUS_PORTRAIT,
+ SMART_AUTO_STATUS_MACRO,
+ SMART_AUTO_STATUS_NIGHT,
+ SMART_AUTO_STATUS_PORTRAIT_NIGHT,
+ SMART_AUTO_STATUS_BACKLIT,
+ SMART_AUTO_STATUS_PORTRAIT_BACKLIT,
+ SMART_AUTO_STATUS_ANTISHAKE,
+ SMART_AUTO_STATUS_PORTRAIT_ANTISHAKE,
+ SMART_AUTO_STATUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_SET_AUTO_FOCUS (V4L2_CID_PRIVATE_BASE + 93)
+enum v4l2_auto_focus {
+ AUTO_FOCUS_OFF = 0,
+ AUTO_FOCUS_ON,
+ AUTO_FOCUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_BEAUTY_SHOT (V4L2_CID_PRIVATE_BASE + 94)
+enum v4l2_beauty_shot {
+ BEAUTY_SHOT_OFF = 0,
+ BEAUTY_SHOT_ON,
+ BEAUTY_SHOT_MAX,
+};
+
+#define V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK (V4L2_CID_PRIVATE_BASE + 95)
+enum v4l2_ae_awb_lockunlock {
+ AE_UNLOCK_AWB_UNLOCK = 0,
+ AE_LOCK_AWB_UNLOCK,
+ AE_UNLOCK_AWB_LOCK,
+ AE_LOCK_AWB_LOCK,
+ AE_AWB_MAX
+};
+
+#define V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK (V4L2_CID_PRIVATE_BASE + 96)
+enum v4l2_face_lock {
+ FACE_LOCK_OFF = 0,
+ FACE_LOCK_ON,
+ FIRST_FACE_TRACKING,
+ FACE_LOCK_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJECT_POSITION_X (V4L2_CID_PRIVATE_BASE + 97)
+#define V4L2_CID_CAMERA_OBJECT_POSITION_Y (V4L2_CID_PRIVATE_BASE + 98)
+#define V4L2_CID_CAMERA_FOCUS_MODE (V4L2_CID_PRIVATE_BASE + 99)
+enum v4l2_focusmode {
+ FOCUS_MODE_AUTO = 0,
+ FOCUS_MODE_MACRO,
+ FOCUS_MODE_FACEDETECT,
+ FOCUS_MODE_AUTO_DEFAULT,
+ FOCUS_MODE_MACRO_DEFAULT,
+ FOCUS_MODE_FACEDETECT_DEFAULT,
+ FOCUS_MODE_INFINITY,
+ FOCUS_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJ_TRACKING_STATUS (V4L2_CID_PRIVATE_BASE + 100)
+enum v4l2_obj_tracking_status {
+ OBJECT_TRACKING_STATUS_BASE,
+ OBJECT_TRACKING_STATUS_PROGRESSING,
+ OBJECT_TRACKING_STATUS_SUCCESS,
+ OBJECT_TRACKING_STATUS_FAIL,
+ OBJECT_TRACKING_STATUS_MISSING,
+ OBJECT_TRACKING_STATUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP (V4L2_CID_PRIVATE_BASE + 101)
+enum v4l2_ot_start_stop {
+ OT_STOP = 0,
+ OT_START,
+ OT_MAX,
+};
+
+#define V4L2_CID_CAMERA_CAF_START_STOP (V4L2_CID_PRIVATE_BASE + 102)
+enum v4l2_caf_start_stop {
+ CAF_STOP = 0,
+ CAF_START,
+ CAF_MAX,
+};
+
+#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_FIRST (V4L2_CID_PRIVATE_BASE + 103)
+#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_SECOND (V4L2_CID_PRIVATE_BASE + 120)
+#define V4L2_CID_CAMERA_FINISH_AUTO_FOCUS (V4L2_CID_PRIVATE_BASE + 121)
+#define V4L2_CID_CAMERA_FRAME_RATE (V4L2_CID_PRIVATE_BASE + 104)
+enum v4l2_frame_rate {
+ FRAME_RATE_AUTO = 0,
+ FRAME_RATE_7 = 7,
+ FRAME_RATE_15 = 15,
+ FRAME_RATE_30 = 30,
+ FRAME_RATE_60 = 60,
+ FRAME_RATE_120 = 120,
+ FRAME_RATE_MAX
+};
+
+#define V4L2_CID_CAMERA_ANTI_BANDING (V4L2_CID_PRIVATE_BASE + 105)
+enum v4l2_anti_banding {
+ ANTI_BANDING_AUTO = 0,
+ ANTI_BANDING_50HZ = 1,
+ ANTI_BANDING_60HZ = 2,
+ ANTI_BANDING_OFF = 3,
+};
+
+#define V4L2_CID_CAMERA_SET_GAMMA (V4L2_CID_PRIVATE_BASE + 106)
+enum v4l2_gamma_mode {
+ GAMMA_OFF = 0,
+ GAMMA_ON = 1,
+ GAMMA_MAX,
+};
+
+#define V4L2_CID_CAMERA_SET_SLOW_AE (V4L2_CID_PRIVATE_BASE + 107)
+enum v4l2_slow_ae_mode {
+ SLOW_AE_OFF,
+ SLOW_AE_ON,
+ SLOW_AE_MAX,
+};
+
+#define V4L2_CID_CAMERA_BATCH_REFLECTION (V4L2_CID_PRIVATE_BASE + 108)
+#define V4L2_CID_CAMERA_EXIF_ORIENTATION (V4L2_CID_PRIVATE_BASE + 109)
+
+#define V4L2_CID_CAMERA_RESET (V4L2_CID_PRIVATE_BASE + 111)
+#define V4L2_CID_CAMERA_CHECK_DATALINE (V4L2_CID_PRIVATE_BASE + 112)
+#define V4L2_CID_CAMERA_CHECK_DATALINE_STOP (V4L2_CID_PRIVATE_BASE + 113)
+#define V4L2_CID_CAMERA_GET_ISO (V4L2_CID_PRIVATE_BASE + 114)
+#define V4L2_CID_CAMERA_GET_SHT_TIME (V4L2_CID_PRIVATE_BASE + 115)
+#define V4L2_CID_CAMERA_SENSOR_MODE (V4L2_CID_PRIVATE_BASE + 116)
+#define V4L2_CID_ESD_INT (V4L2_CID_PRIVATE_BASE + 117)
+#define V4L2_CID_CAMERA_GET_FLASH_ONOFF (V4L2_CID_PRIVATE_BASE + 118)
+#define V4L2_CID_CAMERA_RETURN_FOCUS (V4L2_CID_PRIVATE_BASE + 119)
+
+#define V4L2_CID_FIMC_IS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x1000)
+
+#define V4L2_CID_IS_LOAD_FW (V4L2_CID_FIMC_IS_BASE + 10)
+#define V4L2_CID_IS_RESET (V4L2_CID_FIMC_IS_BASE + 12)
+#define V4L2_CID_IS_S_POWER (V4L2_CID_FIMC_IS_BASE + 13)
+
+#define V4L2_CID_IS_S_STREAM (V4L2_CID_FIMC_IS_BASE + 14)
+
+#define V4L2_CID_IS_GET_SENSOR_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 480)
+#define V4L2_CID_IS_GET_SENSOR_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 481)
+#define V4L2_CID_IS_GET_SENSOR_WIDTH (V4L2_CID_FIMC_IS_BASE + 482)
+#define V4L2_CID_IS_GET_SENSOR_HEIGHT (V4L2_CID_FIMC_IS_BASE + 483)
+
+#define V4L2_CID_IS_GET_FRAME_VALID (V4L2_CID_FIMC_IS_BASE + 484)
+#define V4L2_CID_IS_SET_FRAME_VALID (V4L2_CID_FIMC_IS_BASE + 485)
+#define V4L2_CID_IS_GET_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 491)
+#define V4L2_CID_IS_CLEAR_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 492)
+#define V4L2_CID_IS_GET_LOSTED_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 493)
+#define V4L2_CID_IS_ZOOM_STATE (V4L2_CID_FIMC_IS_BASE + 660)
+#define V4L2_CID_IS_ZOOM (V4L2_CID_FIMC_IS_BASE + 662)
+/* Pixel format FOURCC depth Description */
+enum v4l2_pix_format_mode {
+ V4L2_PIX_FMT_MODE_PREVIEW,
+ V4L2_PIX_FMT_MODE_CAPTURE,
+ V4L2_PIX_FMT_MODE_HDR,
+ V4L2_PIX_FMT_MODE_VT_MIRROR,
+ V4L2_PIX_FMT_MODE_VT_NONMIRROR,
+};
+/* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2')
+
+
+/*
+ * * V4L2 extention for digital camera
+ * */
+/* Strobe flash light */
+enum v4l2_strobe_control {
+ /* turn off the flash light */
+ V4L2_STROBE_CONTROL_OFF = 0,
+ /* turn on the flash light */
+ V4L2_STROBE_CONTROL_ON = 1,
+ /* act guide light before splash */
+ V4L2_STROBE_CONTROL_AFGUIDE = 2,
+ /* charge the flash light */
+ V4L2_STROBE_CONTROL_CHARGE = 3,
+};
+
+enum v4l2_strobe_conf {
+ V4L2_STROBE_OFF = 0, /* Always off */
+ V4L2_STROBE_ON = 1, /* Always splashes */
+ /* Auto control presets */
+ V4L2_STROBE_AUTO = 2,
+ V4L2_STROBE_REDEYE_REDUCTION = 3,
+ V4L2_STROBE_SLOW_SYNC = 4,
+ V4L2_STROBE_FRONT_CURTAIN = 5,
+ V4L2_STROBE_REAR_CURTAIN = 6,
+ /* Extra manual control presets */
+ /* keep turned on until turning off */
+ V4L2_STROBE_PERMANENT = 7,
+ V4L2_STROBE_EXTERNAL = 8,
+};
+
+enum v4l2_strobe_status {
+ V4L2_STROBE_STATUS_OFF = 0,
+ /* while processing configurations */
+ V4L2_STROBE_STATUS_BUSY = 1,
+ V4L2_STROBE_STATUS_ERR = 2,
+ V4L2_STROBE_STATUS_CHARGING = 3,
+ V4L2_STROBE_STATUS_CHARGED = 4,
+};
+
+/* capabilities field */
+/* No strobe supported */
+#define V4L2_STROBE_CAP_NONE 0x0000
+/* Always flash off mode */
+#define V4L2_STROBE_CAP_OFF 0x0001
+/* Always use flash light mode */
+#define V4L2_STROBE_CAP_ON 0x0002
+/* Flashlight works automatic */
+#define V4L2_STROBE_CAP_AUTO 0x0004
+/* Red-eye reduction */
+#define V4L2_STROBE_CAP_REDEYE 0x0008
+/* Slow sync */
+#define V4L2_STROBE_CAP_SLOWSYNC 0x0010
+/* Front curtain */
+#define V4L2_STROBE_CAP_FRONT_CURTAIN 0x0020
+/* Rear curtain */
+#define V4L2_STROBE_CAP_REAR_CURTAIN 0x0040
+/* keep turned on until turning off */
+#define V4L2_STROBE_CAP_PERMANENT 0x0080
+/* use external strobe */
+#define V4L2_STROBE_CAP_EXTERNAL 0x0100
+
+/* Set mode and Get status */
+struct v4l2_strobe {
+ /* off/on/charge:0/1/2 */
+ enum v4l2_strobe_control control;
+ /* supported strobe capabilities */
+ __u32 capabilities;
+ enum v4l2_strobe_conf mode;
+ enum v4l2_strobe_status status; /* read only */
+ /* default is 0 and range of value varies from each models */
+ __u32 flash_ev;
+ __u32 reserved[4];
+};
+
+#define VIDIOC_S_STROBE _IOWR('V', 83, struct v4l2_strobe)
+#define VIDIOC_G_STROBE _IOR('V', 84, struct v4l2_strobe)
+
+/* Object recognition and collateral actions */
+enum v4l2_recog_mode {
+ V4L2_RECOGNITION_MODE_OFF = 0,
+ V4L2_RECOGNITION_MODE_ON = 1,
+ V4L2_RECOGNITION_MODE_LOCK = 2,
+};
+
+enum v4l2_recog_action {
+ V4L2_RECOGNITION_ACTION_NONE = 0, /* only recognition */
+ V4L2_RECOGNITION_ACTION_BLINK = 1, /* Capture on blinking */
+ V4L2_RECOGNITION_ACTION_SMILE = 2, /* Capture on smiling */
+};
+
+enum v4l2_recog_pattern {
+ V4L2_RECOG_PATTERN_FACE = 0, /* Face */
+ V4L2_RECOG_PATTERN_HUMAN = 1, /* Human */
+ V4L2_RECOG_PATTERN_CHAR = 2, /* Character */
+};
+
+struct v4l2_recog_rect {
+ enum v4l2_recog_pattern p; /* detected pattern */
+ struct v4l2_rect o; /* detected area */
+ __u32 reserved[4];
+};
+
+struct v4l2_recog_data {
+ __u8 detect_cnt; /* detected object counter */
+ struct v4l2_rect o; /* detected area */
+ __u32 reserved[4];
+};
+
+struct v4l2_recognition {
+ enum v4l2_recog_mode mode;
+
+ /* Which pattern to detect */
+ enum v4l2_recog_pattern pattern;
+
+ /* How many object to detect */
+ __u8 obj_num;
+
+ /* select detected object */
+ __u32 detect_idx;
+
+ /* read only :Get object coordination */
+ struct v4l2_recog_data data;
+
+ enum v4l2_recog_action action;
+ __u32 reserved[4];
+};
+
+#define VIDIOC_S_RECOGNITION _IOWR('V', 85, struct v4l2_recognition)
+#define VIDIOC_G_RECOGNITION _IOR('V', 86, struct v4l2_recognition)
+
+/* We use this struct as the v4l2_streamparm raw_data for
+ * VIDIOC_G_PARM and VIDIOC_S_PARM
+ */
+struct sec_cam_parm {
+ struct v4l2_captureparm capture;
+ int contrast;
+ int effects;
+ int brightness;
+ int flash_mode;
+ int focus_mode;
+ int iso;
+ int metering;
+ int saturation;
+ int scene_mode;
+ int sharpness;
+ int white_balance;
+ int fps;
+};
+#endif /* __LINUX_VIDEODEV2_SAMSUNG_H */
diff --git a/include/media/s5k4ecgx.h b/include/media/s5k4ecgx.h
new file mode 100644
index 00000000000..747acdd45df
--- /dev/null
+++ b/include/media/s5k4ecgx.h
@@ -0,0 +1,26 @@
+/* include/media/s5k4ecgx.h
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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.
+ */
+
+#define S5K4ECGX_DRIVER_NAME "S5K4ECGX"
+
+struct s5k4ecgx_platform_data {
+ unsigned int default_width;
+ unsigned int default_height;
+ unsigned int pixelformat;
+ int freq; /* MCLK in Hz */
+ int (*set_power)(int enable);
+#ifdef CONFIG_VIDEO_S5K4ECGX_FLASHLIGHT
+ int (*flash_onoff)(int);
+ int (*af_assist_onoff)(int);
+ int (*torch_onoff)(int);
+#endif
+};
+
+
diff --git a/include/media/videobuf2-fb.h b/include/media/videobuf2-fb.h
new file mode 100644
index 00000000000..fea16b655a9
--- /dev/null
+++ b/include/media/videobuf2-fb.h
@@ -0,0 +1,22 @@
+/*
+ * videobuf2-fb.h - FrameBuffer API emulator on top of Videobuf2 framework
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Author: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _MEDIA_VIDEOBUF2_FB_H
+#define _MEDIA_VIDEOBUF2_FB_H
+
+#include <media/v4l2-dev.h>
+#include <media/videobuf2-core.h>
+
+void *vb2_fb_register(struct vb2_queue *q, struct video_device *vfd);
+int vb2_fb_unregister(void *fb_emu);
+
+#endif
diff --git a/include/video/lcd_pwrctrl.h b/include/video/lcd_pwrctrl.h
new file mode 100644
index 00000000000..924bfd22234
--- /dev/null
+++ b/include/video/lcd_pwrctrl.h
@@ -0,0 +1,24 @@
+/*
+ * Simple lcd panel power control driver.
+ *
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2012 Linaro Ltd.
+ *
+ * This driver is derived from platform-lcd.h which was written by
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ *
+*/
+
+/**
+ * struct lcd_pwrctrl_data - platform data for lcd_pwrctrl driver.
+ * @gpio: GPIO number of the host system that connects to nRESET line.
+ * @invert: True, if output of gpio connected to nRESET should be inverted.
+ */
+struct lcd_pwrctrl_data {
+ int gpio;
+ bool invert;
+};
diff --git a/init/Kconfig b/init/Kconfig
index 1340707e294..2d10853180b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1514,7 +1514,7 @@ config PROFILING
# dynamically changed for a probe function.
#
config TRACEPOINTS
- bool
+ bool "Tracepoints support"
source "arch/Kconfig"
diff --git a/init/main.c b/init/main.c
index d7309335481..0117a06f103 100644
--- a/init/main.c
+++ b/init/main.c
@@ -513,6 +513,9 @@ asmlinkage void __init start_kernel(void)
boot_cpu_init();
page_address_init();
printk(KERN_NOTICE "%s", linux_banner);
+#if !IS_ENABLED(CONFIG_LOCALVERSION_AUTO)
+ printk(KERN_NOTICE "%s", linux_scm_version_banner);
+#endif
setup_arch(&command_line);
mm_init_owner(&init_mm, &init_task);
mm_init_cpumask(&init_mm);
diff --git a/init/version.c b/init/version.c
index 3a9433a39d2..fc94762eb3a 100644
--- a/init/version.c
+++ b/init/version.c
@@ -50,3 +50,6 @@ const char linux_proc_banner[] =
"%s version %s"
" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
" (" LINUX_COMPILER ") %s\n";
+
+const char linux_scm_version_banner [] =
+ "Detailed version Linux "UTS_RELEASE "" KERNEL_VERSION_LOCAL "\n";
diff --git a/linaro/configs/origen.conf b/linaro/configs/origen.conf
new file mode 100644
index 00000000000..413aeda9aa4
--- /dev/null
+++ b/linaro/configs/origen.conf
@@ -0,0 +1,126 @@
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_ARMLEX4210=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_NR_CPUS=2
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/mmcblk0p1 rw rootwait console=ttySAC2,115200"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CFG80211=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=y
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_SENSORS_EXYNOS4_TMU=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_VIDEO_S5P_FIMC=y
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+CONFIG_VIDEO_SAMSUNG_S5P_SDO=y
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_DBGP_PRINTK=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_STAGING=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_DEBUG_S3C_UART2=y
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index bd6dca8a0ab..b65e8a93df0 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -47,7 +47,7 @@ scm_version()
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
# it, because this version is defined in the top level Makefile.
- if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+ if [ -z "`git describe --exact-match --match v[2-9].* 2>/dev/null`" ]; then
# If only the short version is requested, don't bother
# running further git commands
@@ -57,7 +57,8 @@ scm_version()
fi
# If we are past a tagged commit (like
# "v2.6.30-rc5-302-g72357d5"), we pretty print it.
- if atag="`git describe 2>/dev/null`"; then
+ # Also match linux tags pattern to discard private tags
+ if atag="`git describe --match v[2-9].* 2>/dev/null`"; then
echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
# If we don't have a tag at all we print -g{commitish}.
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index b70964ea448..62a37adf20a 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -168,6 +168,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
req.cap = (samsung_dma_has_circular() ?
DMA_CYCLIC : DMA_SLAVE);
req.client = prtd->params->client;
+ req.dt_dmach_prop = prtd->params->dma_prop;
config.direction =
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
@@ -432,8 +433,17 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
.pcm_free = dma_free_dma_buffers,
};
+static u64 asoc_dma_mask = DMA_BIT_MASK(32);
+
static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev)
{
+ int ret;
+
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &asoc_dma_mask;
+ if (!pdev->dev.coherent_dma_mask)
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
return snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);
}
@@ -443,10 +453,17 @@ static int __devexit samsung_asoc_platform_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id asoc_dma_of_match[] = {
+ { .compatible = "samsung,audio-dma", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, asoc_dma_of_match);
+
static struct platform_driver asoc_dma_driver = {
.driver = {
.name = "samsung-audio",
.owner = THIS_MODULE,
+ .of_match_table = asoc_dma_of_match,
},
.probe = samsung_asoc_platform_probe,
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 7d1ead77ef2..2e60415244a 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -19,6 +19,7 @@ struct s3c_dma_params {
int dma_size; /* Size of the DMA transfer */
unsigned ch;
struct samsung_dma_ops *ops;
+ struct property *dma_prop;
};
#endif
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index cdc6cea62ed..04b8ec8cc9d 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -15,12 +15,15 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <plat-samsung/audio.h>
+#include <plat-samsung/dma-pl330.h>
#include "dma.h"
#include "idma.h"
@@ -49,8 +52,6 @@ struct i2s_dai {
struct clk *clk;
/* Clock for generating I2S signals */
struct clk *op_clk;
- /* Array of clock names for op_clk */
- const char **src_clk;
/* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */
struct i2s_dai *pri_dai;
/* Pointer to the Secondary_Fifo if it has one, NULL otherwise */
@@ -68,6 +69,8 @@ struct i2s_dai {
u32 suspend_i2smod;
u32 suspend_i2scon;
u32 suspend_i2spsr;
+ unsigned long gpios[7]; /* i2s gpio line numbers */
+ int dev_id; /* i2s dev id */
};
/* Lock for cross i/f checks */
@@ -385,6 +388,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
struct i2s_dai *i2s = to_info(dai);
struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai;
u32 mod = readl(i2s->addr + I2SMOD);
+ char clk_name[16];
switch (clk_id) {
case SAMSUNG_I2S_CDCLK:
@@ -432,8 +436,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
}
}
+ sprintf(clk_name, "i2s_opclk%d", clk_id);
i2s->op_clk = clk_get(&i2s->pdev->dev,
- i2s->src_clk[clk_id]);
+ clk_name);
clk_enable(i2s->op_clk);
i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
@@ -851,6 +856,8 @@ static int i2s_resume(struct snd_soc_dai *dai)
writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
+ } else {
+ writel(CON_RSTCLR, i2s->addr + I2SCON);
}
return 0;
@@ -980,8 +987,9 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
} else { /* Create a new platform_device for Secondary */
i2s->pdev = platform_device_register_resndata(NULL,
- pdev->name, pdev->id + SAMSUNG_I2S_SECOFF,
- NULL, 0, NULL, 0);
+ "samsung-i2s",
+ i2s->dev_id + SAMSUNG_I2S_SECOFF, NULL, 0,
+ NULL, 0);
if (IS_ERR(i2s->pdev))
return NULL;
}
@@ -992,49 +1000,149 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
return i2s;
}
+#ifdef CONFIG_OF
+static int samsung_i2s_parse_dt_gpio(struct i2s_dai *i2s)
+{
+ struct device *dev = &i2s->pdev->dev;
+ int index, gpio, ret;
+
+ for (index = 0; index < 7; index++) {
+ gpio = of_get_gpio(dev->of_node, index);
+ if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "invalid gpio[%d]: %d\n", index, gpio);
+ goto free_gpio;
+ }
+
+ ret = gpio_request(gpio, dev_name(dev));
+ if (ret) {
+ dev_err(dev, "gpio [%d] request failed\n", gpio);
+ goto free_gpio;
+ }
+ i2s->gpios[index] = gpio;
+ }
+ return 0;
+
+free_gpio:
+ while (--index >= 0)
+ gpio_free(i2s->gpios[index]);
+ return -EINVAL;
+}
+
+static void samsung_i2s_dt_gpio_free(struct i2s_dai *i2s)
+{
+ unsigned int index;
+ for (index = 0; index < 7; index++)
+ gpio_free(i2s->gpios[index]);
+}
+#else
+static int samsung_i2s_parse_dt_gpio(struct i2s_dai *dai)
+{
+ return -EINVAL;
+}
+
+static void samsung_i2s_dt_gpio_free(struct i2s_dai *dai)
+{
+}
+
+#endif
+
static __devinit int samsung_i2s_probe(struct platform_device *pdev)
{
- u32 dma_pl_chan, dma_cp_chan, dma_pl_sec_chan;
+ u32 dma_pl_chan, dma_cp_chan;
+ u32 dma_pl_sec_chan = 0;
struct i2s_dai *pri_dai, *sec_dai = NULL;
- struct s3c_audio_pdata *i2s_pdata;
- struct samsung_i2s *i2s_cfg;
+ struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data;
+ struct samsung_i2s *i2s_cfg = NULL;
struct resource *res;
- u32 regs_base, quirks;
- int ret = 0;
+ u32 regs_base, quirks = 0, idma_addr = 0;
+ struct property *prop;
+ struct device_node *np = pdev->dev.of_node;
+ int ret = 0, id;
/* Call during Seconday interface registration */
- if (pdev->id >= SAMSUNG_I2S_SECOFF) {
+ if (np) {
+ id = of_alias_get_id(np, "i2s");
+ if (id < 0) {
+ dev_err(&pdev->dev, "failed to get alias id:%d\n", id);
+ return id;
+ }
+ } else {
+ id = pdev->id;
+ }
+
+ if (id >= SAMSUNG_I2S_SECOFF) {
sec_dai = dev_get_drvdata(&pdev->dev);
snd_soc_register_dai(&sec_dai->pdev->dev,
&sec_dai->i2s_dai_drv);
return 0;
}
- i2s_pdata = pdev->dev.platform_data;
- if (i2s_pdata == NULL) {
- dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n");
- return -EINVAL;
+ pri_dai = i2s_alloc_dai(pdev, false);
+ if (!pri_dai) {
+ dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
+ return -ENOMEM;
}
- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!res) {
- dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
- return -ENXIO;
- }
- dma_pl_chan = res->start;
+ if (!np) {
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Unable to get I2S-TX dma resource\n");
+ return -ENXIO;
+ }
+ dma_pl_chan = res->start;
- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!res) {
- dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
- return -ENXIO;
- }
- dma_cp_chan = res->start;
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Unable to get I2S-RX dma resource\n");
+ return -ENXIO;
+ }
+ dma_cp_chan = res->start;
- res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
- if (res)
- dma_pl_sec_chan = res->start;
- else
- dma_pl_sec_chan = 0;
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
+ if (res)
+ dma_pl_sec_chan = res->start;
+
+ i2s_cfg = &i2s_pdata->type.i2s;
+ quirks = i2s_cfg->quirks;
+ idma_addr = i2s_cfg->idma_addr;
+ } else {
+ prop = of_find_property(np, "tx-dma-channel", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "tx dma channel property not"\
+ "specified\n");
+ return -ENXIO;
+ }
+ dma_pl_chan = DMACH_DT_PROP;
+ pri_dai->dma_playback.dma_prop = prop;
+
+ prop = of_find_property(np, "rx-dma-channel", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "tx dma channel property not"\
+ "specified\n");
+ return -ENXIO;
+ }
+ dma_cp_chan = DMACH_DT_PROP;
+ pri_dai->dma_capture.dma_prop = prop;
+
+ if (of_find_property(np, "supports-6ch", NULL))
+ quirks |= QUIRK_PRI_6CHAN;
+
+ if (of_find_property(np, "supports-secdai", NULL))
+ quirks |= QUIRK_SEC_DAI;
+
+ if (of_find_property(np, "supports-rstclr", NULL))
+ quirks |= QUIRK_NEED_RSTCLR;
+
+ if (of_property_read_u32(np, "idma-addr", &idma_addr)) {
+ if (quirks & QUIRK_SEC_DAI) {
+ dev_err(&pdev->dev, "idma address is not"\
+ "specified");
+ return -EINVAL;
+ }
+ }
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -1049,16 +1157,6 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
}
regs_base = res->start;
- i2s_cfg = &i2s_pdata->type.i2s;
- quirks = i2s_cfg->quirks;
-
- pri_dai = i2s_alloc_dai(pdev, false);
- if (!pri_dai) {
- dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
- ret = -ENOMEM;
- goto err;
- }
-
pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
pri_dai->dma_playback.client =
@@ -1067,11 +1165,11 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
(struct s3c2410_dma_client *)&pri_dai->dma_capture;
pri_dai->dma_playback.channel = dma_pl_chan;
pri_dai->dma_capture.channel = dma_cp_chan;
- pri_dai->src_clk = i2s_cfg->src_clk;
pri_dai->dma_playback.dma_size = 4;
pri_dai->dma_capture.dma_size = 4;
pri_dai->base = regs_base;
pri_dai->quirks = quirks;
+ pri_dai->dev_id = id;
if (quirks & QUIRK_PRI_6CHAN)
pri_dai->i2s_dai_drv.playback.channels_max = 6;
@@ -1086,21 +1184,42 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
sec_dai->dma_playback.client =
(struct s3c2410_dma_client *)&sec_dai->dma_playback;
+
+ if (np) {
+ prop = of_find_property(np, "tx-dma-channel-secondary",
+ NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "tx dma channel property"\
+ "not specified\n");
+ ret = -ENXIO;
+ goto err;
+ }
+ sec_dai->dma_playback.dma_prop = prop;
+ }
+
/* Use iDMA always if SysDMA not provided */
sec_dai->dma_playback.channel = dma_pl_sec_chan ? : -1;
- sec_dai->src_clk = i2s_cfg->src_clk;
sec_dai->dma_playback.dma_size = 4;
sec_dai->base = regs_base;
sec_dai->quirks = quirks;
- sec_dai->idma_playback.dma_addr = i2s_cfg->idma_addr;
+ sec_dai->dev_id = id;
+ sec_dai->idma_playback.dma_addr = idma_addr;
sec_dai->pri_dai = pri_dai;
pri_dai->sec_dai = sec_dai;
}
- if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
- dev_err(&pdev->dev, "Unable to configure gpio\n");
- ret = -EINVAL;
- goto err;
+ if (np) {
+ if (samsung_i2s_parse_dt_gpio(pri_dai)) {
+ dev_err(&pdev->dev, "Unable to configure gpio\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
+ dev_err(&pdev->dev, "Unable to configure gpio\n");
+ ret = -EINVAL;
+ goto err;
+ }
}
snd_soc_register_dai(&pri_dai->pdev->dev, &pri_dai->i2s_dai_drv);
@@ -1118,10 +1237,14 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
{
struct i2s_dai *i2s, *other;
struct resource *res;
+ struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data;
i2s = dev_get_drvdata(&pdev->dev);
other = i2s->pri_dai ? : i2s->sec_dai;
+ if (!i2s_pdata->cfg_gpio && pdev->dev.of_node)
+ samsung_i2s_dt_gpio_free(i2s->pri_dai);
+
if (other) {
other->pri_dai = NULL;
other->sec_dai = NULL;
@@ -1140,12 +1263,21 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_i2s_match[] = {
+ { .compatible = "samsung,samsung-i2s" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_i2s_match);
+#endif
+
static struct platform_driver samsung_i2s_driver = {
.probe = samsung_i2s_probe,
.remove = __devexit_p(samsung_i2s_remove),
.driver = {
.name = "samsung-i2s",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(exynos_i2s_match),
},
};
diff --git a/ubuntu/dm-raid4-5/dm-raid4-5.c b/ubuntu/dm-raid4-5/dm-raid4-5.c
index e05b0e14e34..9f55f582588 100644
--- a/ubuntu/dm-raid4-5/dm-raid4-5.c
+++ b/ubuntu/dm-raid4-5/dm-raid4-5.c
@@ -4073,7 +4073,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
* Make sure that dm core only hands maximum io size
* length down and pays attention to io boundaries.
*/
- ti->split_io = rs->set.io_size;
+ ti->max_io_len = rs->set.io_size;
ti->private = rs;
/* Initialize work queue to handle this RAID set's io. */
@@ -4246,7 +4246,7 @@ static void raid_devel_stats(struct dm_target *ti, char *result,
}
static int raid_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
unsigned p, sz = 0;
char buf[BDEVNAME_SIZE];