aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung
diff options
context:
space:
mode:
authorcodeworkx <codeworkx@cyanogenmod.com>2012-09-17 17:53:57 +0200
committercodeworkx <codeworkx@cyanogenmod.com>2012-09-18 16:31:59 +0200
commitc28265764ec6ad9995eb0c761a376ffc9f141fcd (patch)
tree3ad899757480d47deb2be6011509a4243e8e0dc2 /drivers/media/video/samsung
parent0ddbcb39c0dc0318f68d858f25a96a074142af2f (diff)
downloadkernel_samsung_smdk4412-c28265764ec6ad9995eb0c761a376ffc9f141fcd.zip
kernel_samsung_smdk4412-c28265764ec6ad9995eb0c761a376ffc9f141fcd.tar.gz
kernel_samsung_smdk4412-c28265764ec6ad9995eb0c761a376ffc9f141fcd.tar.bz2
applied patches from i9305 jb sources, updated mali to r3p0
Change-Id: Iec4bc4e2fb59e2cf5b4d25568a644d4e3719565e
Diffstat (limited to 'drivers/media/video/samsung')
-rw-r--r--drivers/media/video/samsung/Makefile19
-rw-r--r--drivers/media/video/samsung/fimc/Kconfig9
-rw-r--r--drivers/media/video/samsung/fimc/fimc.h42
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture.c376
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture_u1.c45
-rw-r--r--drivers/media/video/samsung/fimc/fimc_dev.c334
-rw-r--r--drivers/media/video/samsung/fimc/fimc_dev_u1.c26
-rw-r--r--drivers/media/video/samsung/fimc/fimc_output.c92
-rw-r--r--drivers/media/video/samsung/fimc/fimc_regs.c7
-rw-r--r--drivers/media/video/samsung/fimc/fimc_v4l2.c130
-rw-r--r--drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_dev.c35
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h12
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c9
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c17
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.c87
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.h10
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c64
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c64
-rw-r--r--drivers/media/video/samsung/jpeg_v2x/jpeg_conf.h44
-rw-r--r--drivers/media/video/samsung/jpeg_v2x/jpeg_dev.c29
-rw-r--r--drivers/media/video/samsung/jpeg_v2x/jpeg_mem.h5
-rw-r--r--drivers/media/video/samsung/jpeg_v2x/jpeg_regs.c103
-rw-r--r--drivers/media/video/samsung/jpeg_v2x/jpeg_regs.h2
-rw-r--r--drivers/media/video/samsung/mali/Kconfig10
-rw-r--r--drivers/media/video/samsung/mali/Makefile207
-rw-r--r--drivers/media/video/samsung/mali/Makefile.common59
-rw-r--r--drivers/media/video/samsung/mali/Makefile_module89
l---------drivers/media/video/samsung/mali/arch1
-rw-r--r--drivers/media/video/samsung/mali/arch-debug/config.h (renamed from drivers/media/video/samsung/mali/arch-orion-m400/config.h)2
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h85
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h92
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h85
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h77
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h91
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h105
-rw-r--r--drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h119
-rw-r--r--drivers/media/video/samsung/mali/arch-pegasus-m400/config.h154
-rw-r--r--drivers/media/video/samsung/mali/arch-release/config.h154
-rw-r--r--drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h168
-rw-r--r--drivers/media/video/samsung/mali/arch/config.h154
-rw-r--r--drivers/media/video/samsung/mali/common/mali_block_allocator.c6
-rw-r--r--drivers/media/video/samsung/mali/common/mali_cluster.c218
-rw-r--r--drivers/media/video/samsung/mali/common/mali_cluster.h44
-rw-r--r--drivers/media/video/samsung/mali/common/mali_device_pause_resume.c46
-rw-r--r--drivers/media/video/samsung/mali/common/mali_device_pause_resume.h31
-rw-r--r--drivers/media/video/samsung/mali/common/mali_dlbu.c285
-rw-r--r--drivers/media/video/samsung/mali/common/mali_dlbu.h45
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp.c693
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp.h46
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_job.c49
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_job.h131
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_scheduler.c438
-rw-r--r--drivers/media/video/samsung/mali/common/mali_gp_scheduler.h30
-rw-r--r--drivers/media/video/samsung/mali/common/mali_group.c841
-rw-r--r--drivers/media/video/samsung/mali/common/mali_group.h146
-rw-r--r--drivers/media/video/samsung/mali/common/mali_hw_core.c46
-rw-r--r--drivers/media/video/samsung/mali/common/mali_hw_core.h71
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_GP2.c1493
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c1304
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_common.h5
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_core.c1359
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_core.h127
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c15
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h6
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c517
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h25
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c1427
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c3157
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h75
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c26
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c26
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h5
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c2031
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h565
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h107
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_utilization.c56
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_utilization.h2
-rw-r--r--drivers/media/video/samsung/mali/common/mali_kernel_vsync.c32
-rw-r--r--drivers/media/video/samsung/mali/common/mali_l2_cache.c398
-rw-r--r--drivers/media/video/samsung/mali/common/mali_l2_cache.h43
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mem_validation.c71
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mem_validation.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_session_manager.h)14
-rw-r--r--drivers/media/video/samsung/mali/common/mali_memory.c1321
-rw-r--r--drivers/media/video/samsung/mali/common/mali_memory.h80
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu.c619
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu.h55
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c459
-rw-r--r--drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h83
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk.h158
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk_list.h2
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk_mali.h32
-rw-r--r--drivers/media/video/samsung/mali/common/mali_osk_profiling.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_profiling.h)88
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pm.c547
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pm.h56
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pmu.c199
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pmu.h70
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp.c710
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp.h47
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_job.c92
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_job.h255
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_scheduler.c542
-rw-r--r--drivers/media/video/samsung/mali/common/mali_pp_scheduler.h38
-rw-r--r--drivers/media/video/samsung/mali/common/mali_scheduler.c36
-rw-r--r--drivers/media/video/samsung/mali/common/mali_scheduler.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_mem.h)16
-rw-r--r--drivers/media/video/samsung/mali/common/mali_session.c47
-rw-r--r--drivers/media/video/samsung/mali/common/mali_session.h65
-rw-r--r--drivers/media/video/samsung/mali/common/mali_ukk.h184
-rw-r--r--drivers/media/video/samsung/mali/common/mali_user_settings_db.c88
-rw-r--r--drivers/media/video/samsung/mali/common/mali_user_settings_db.h40
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm.c1024
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm.h348
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c350
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h86
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c243
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h155
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c80
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h62
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c470
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h80
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c716
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h290
-rw-r--r--drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h61
-rw-r--r--drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_gp.h)25
-rw-r--r--drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h264
-rw-r--r--drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h80
-rw-r--r--drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h121
-rw-r--r--drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h (renamed from drivers/media/video/samsung/mali/common/mali_uk_types.h)341
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_device_pause_resume.c72
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_ioctl.h13
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_linux.c227
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_linux.h8
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_pm.c681
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_pm.h5
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c977
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h2
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_linux_pm.h7
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h13
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_linux_trace.h132
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_indir_mmap.h2
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_irq.c84
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_locks.c109
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c31
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_mali.c21
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_memory.c2
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_misc.c5
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_notification.c25
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_pm.c204
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_profiling.c47
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c262
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c (renamed from drivers/media/video/samsung/mali/common/mali_kernel_profiling.c)122
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_specific.h102
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_timers.c4
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c73
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c65
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_profiling_events.h (renamed from drivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h)13
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_uk_types.h (renamed from drivers/media/video/samsung/mali/linux/mali_device_pause_resume.h)16
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_core.c24
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_gp.c21
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_mem.c81
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_pp.c49
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c63
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c4
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h14
-rw-r--r--drivers/media/video/samsung/mali/platform/default/mali_platform.c4
-rw-r--r--drivers/media/video/samsung/mali/platform/mali_platform.h36
-rw-r--r--drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c66
-rw-r--r--drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c2
-rw-r--r--drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c415
-rw-r--r--drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c118
-rw-r--r--drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c175
-rw-r--r--drivers/media/video/samsung/mali/readme.txt28
-rw-r--r--drivers/media/video/samsung/mali/regs/mali_200_regs.h32
-rw-r--r--drivers/media/video/samsung/mali/regs/mali_gp_regs.h27
-rw-r--r--drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c2
-rw-r--r--drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h2
-rw-r--r--drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c2
-rw-r--r--drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h2
-rw-r--r--drivers/media/video/samsung/tvout/Kconfig10
-rw-r--r--drivers/media/video/samsung/tvout/hw_if/hdcp.c20
-rw-r--r--drivers/media/video/samsung/tvout/hw_if/hdmi.c56
-rw-r--r--drivers/media/video/samsung/tvout/hw_if/hw_if.h26
-rw-r--r--drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c76
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c89
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout.c38
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h10
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h4
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_fb.c16
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_hpd.c80
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c115
-rw-r--r--drivers/media/video/samsung/tvout/s5p_vp_ctrl.c20
-rw-r--r--drivers/media/video/samsung/ump/Kconfig5
-rw-r--r--drivers/media/video/samsung/ump/Makefile18
-rw-r--r--drivers/media/video/samsung/ump/Makefile.common19
-rw-r--r--drivers/media/video/samsung/ump/Makefile_backup80
-rw-r--r--drivers/media/video/samsung/ump/Makefile_module119
l---------drivers/media/video/samsung/ump/arch1
-rw-r--r--drivers/media/video/samsung/ump/arch-debug/config.h (renamed from drivers/media/video/samsung/mali/common/mali_kernel_pp.h)23
-rwxr-xr-xdrivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h.org87
-rw-r--r--drivers/media/video/samsung/ump/arch-orion-m400/config.h14
-rw-r--r--drivers/media/video/samsung/ump/arch-pb-virtex5/config.h4
-rw-r--r--drivers/media/video/samsung/ump/arch-pegasus-m400/config.h22
-rw-r--r--drivers/media/video/samsung/ump/arch-release/config.h22
-rw-r--r--drivers/media/video/samsung/ump/arch/config.h22
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_api.c229
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_common.c15
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_common.h14
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c35
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h6
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h7
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c13
-rw-r--r--drivers/media/video/samsung/ump/common/ump_kernel_types.h24
-rw-r--r--drivers/media/video/samsung/ump/common/ump_osk.h11
-rw-r--r--drivers/media/video/samsung/ump/common/ump_uk_types.h75
-rw-r--r--drivers/media/video/samsung/ump/common/ump_ukk.h14
-rw-r--r--drivers/media/video/samsung/ump/include/ump_kernel_interface.h6
-rw-r--r--drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h6
-rw-r--r--drivers/media/video/samsung/ump/include/ump_kernel_interface_vcm.h6
-rw-r--r--drivers/media/video/samsung/ump/include/ump_kernel_platform.h6
-rw-r--r--drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h6
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_ioctl.h16
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_linux.c36
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_linux.h12
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c19
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h7
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c16
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h7
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c24
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h6
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_memory_backend.c7
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_osk_atomics.c6
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c213
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_osk_misc.c6
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c6
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h6
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c143
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h10
236 files changed, 17734 insertions, 18756 deletions
diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile
index 301cd9a..639d3bc 100644
--- a/drivers/media/video/samsung/Makefile
+++ b/drivers/media/video/samsung/Makefile
@@ -11,8 +11,27 @@ else
obj-$(CONFIG_VIDEO_FIMG2D3X) += fimg2d3x/
obj-$(CONFIG_VIDEO_FIMG2D4X) += fimg2d4x/
endif
+
+ifeq ($(CONFIG_MACH_U1), y)
+obj-$(CONFIG_VIDEO_UMP) += ump/
+else ifeq ($(CONFIG_MACH_SMDKC210), y)
obj-$(CONFIG_VIDEO_UMP) += ump/
+else ifeq ($(CONFIG_MACH_SMDKV310), y)
+obj-$(CONFIG_VIDEO_UMP) += ump/
+else
+obj-$(CONFIG_VIDEO_UMP) += ump/
+endif
+
obj-$(CONFIG_VIDEO_TSI) += tsi/
+
+ifeq ($(CONFIG_MACH_U1), y)
+obj-$(CONFIG_VIDEO_MALI400MP) += mali/
+else ifeq ($(CONFIG_MACH_SMDKC210), y)
+obj-$(CONFIG_VIDEO_MALI400MP) += mali/
+else ifeq ($(CONFIG_MACH_SMDKV310), y)
obj-$(CONFIG_VIDEO_MALI400MP) += mali/
+else
+obj-$(CONFIG_VIDEO_MALI400MP) += mali/
+endif
EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/samsung/fimc/Kconfig b/drivers/media/video/samsung/fimc/Kconfig
index 68f0b14..2fc4c86 100644
--- a/drivers/media/video/samsung/fimc/Kconfig
+++ b/drivers/media/video/samsung/fimc/Kconfig
@@ -6,6 +6,15 @@ config VIDEO_FIMC
help
This is a video4linux driver for Samsung FIMC device.
+config USE_FIMC_CMA
+ bool "Use CMA for FIMC0/1 region (EXPERIMENTAL)"
+ depends on DMA_CMA
+ default n
+ help
+ This enables the Contiguous Memory Allocator for MFC SECURE region.
+
+ If unsure, say "n".
+
choice
depends on VIDEO_FIMC
prompt "Select CSC Range config"
diff --git a/drivers/media/video/samsung/fimc/fimc.h b/drivers/media/video/samsung/fimc/fimc.h
index 9527f52..b648965 100644
--- a/drivers/media/video/samsung/fimc/fimc.h
+++ b/drivers/media/video/samsung/fimc/fimc.h
@@ -25,6 +25,9 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf-core.h>
+#ifdef CONFIG_SLP_DMABUF
+#include <media/videobuf2-core.h>
+#endif
#include <media/v4l2-mediabus.h>
#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
#include <mach/dev.h>
@@ -42,7 +45,9 @@
#define FIMC_CMA_NAME "fimc"
#define FIMC_CORE_CLK "sclk_fimc"
-#define FIMC_CLK_RATE 166750000
+
+extern int fimc_clk_rate(void);
+
#define EXYNOS_BUSFREQ_NAME "exynos-busfreq"
#if defined(CONFIG_ARCH_EXYNOS4)
@@ -58,7 +63,11 @@
#define FIMC_SUBDEVS 3
#define FIMC_OUTBUFS 3
#define FIMC_INQUEUES 10
+#if defined(CONFIG_SLP)
+#define FIMC_MAX_CTXS 8
+#else
#define FIMC_MAX_CTXS 4
+#endif
#define FIMC_TPID 3
#define FIMC_CAPBUFS 32
#define FIMC_ONESHOT_TIMEOUT 200
@@ -205,12 +214,22 @@ enum cam_mclk_status {
CAM_MCLK_ON,
};
+enum fimc_plane_num {
+ PLANE_1 = 0x1,
+ PLANE_2 = 0x2,
+ PLANE_3 = 0x3,
+ PLANE_4 = 0x4,
+};
+
/*
* STRUCTURES
*/
/* for reserved memory */
struct fimc_meminfo {
+#ifdef CONFIG_USE_FIMC_CMA
+ void *cpu_addr;
+#endif
dma_addr_t base; /* buffer base */
size_t size; /* total length */
dma_addr_t curr; /* current addr */
@@ -263,6 +282,9 @@ struct fimc_capinfo {
/* using c210 */
struct list_head outgoing_q;
int nr_bufs;
+#ifdef CONFIG_SLP_DMABUF
+ int nr_plane;
+#endif
int irq;
int lastirq;
@@ -326,6 +348,9 @@ struct fimc_ctx {
struct fimc_overlay overlay;
u32 buf_num;
+#ifdef CONFIG_SLP_DMABUF
+ int nr_plane;
+#endif
u32 is_requested;
struct fimc_buf_set src[FIMC_OUTBUFS];
struct fimc_buf_set dst[FIMC_OUTBUFS];
@@ -477,6 +502,10 @@ struct fimc_control {
struct timeval before_time;
char cma_name[16];
bool restart;
+#ifdef CONFIG_SLP_DMABUF
+ struct vb2_buffer *out_bufs[VIDEO_MAX_FRAME];
+ struct vb2_buffer *cap_bufs[VIDEO_MAX_FRAME];
+#endif
};
/* global */
@@ -766,5 +795,16 @@ static inline struct fimc_control *get_fimc_ctrl(int id)
{
return &fimc_dev->ctrl[id];
}
+#ifdef CONFIG_SLP_DMABUF
+extern void _fimc_queue_free(struct fimc_control *ctrl,
+ enum v4l2_buf_type type);
+extern int fimc_queue_alloc(struct fimc_control *ctrl, enum v4l2_buf_type type,
+ enum v4l2_memory memory, unsigned int num_buffers,
+ unsigned int num_planes);
+extern int _qbuf_dmabuf(struct fimc_control *ctrl, struct vb2_buffer *vb,
+ struct v4l2_buffer *b);
+extern int _dqbuf_dmabuf(struct fimc_control *ctrl, struct vb2_buffer *vb,
+ struct v4l2_buffer *b);
+#endif
#endif /* __FIMC_H */
diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c
index fe0878a..7d00c8b 100644
--- a/drivers/media/video/samsung/fimc/fimc_capture.c
+++ b/drivers/media/video/samsung/fimc/fimc_capture.c
@@ -203,6 +203,9 @@ static const struct v4l2_queryctrl fimc_controls[] = {
.default_value = 0,
},
};
+#ifdef CONFIG_MACH_GC1
+static bool leave_power;
+#endif
#ifndef CONFIG_VIDEO_FIMC_MIPI
void s3c_csis_start(int csis_id, int lanes, int settle, \
@@ -268,7 +271,12 @@ static int fimc_init_camera(struct fimc_control *ctrl)
retry:
/* set rate for mclk */
+#ifndef CONFIG_MACH_GC1
if ((clk_get_rate(cam->clk)) && (fimc->mclk_status == CAM_MCLK_OFF)) {
+#else
+ if ((clk_get_rate(cam->clk)) && (fimc->mclk_status == CAM_MCLK_OFF)
+ && !leave_power) {
+#endif
clk_set_rate(cam->clk, cam->clk_rate);
clk_enable(cam->clk);
fimc->mclk_status = CAM_MCLK_ON;
@@ -277,7 +285,14 @@ retry:
/* enable camera power if needed */
if (cam->cam_power) {
+#ifndef CONFIG_MACH_GC1
ret = cam->cam_power(1);
+#else
+ if (!leave_power)
+ ret = cam->cam_power(1);
+
+ leave_power = false;
+#endif
if (unlikely(ret < 0)) {
fimc_err("\nfail to power on\n");
if (fimc->mclk_status == CAM_MCLK_ON) {
@@ -720,11 +735,19 @@ int fimc_release_subdev(struct fimc_control *ctrl)
client = v4l2_get_subdevdata(ctrl->cam->sd);
i2c_unregister_device(client);
ctrl->cam->sd = NULL;
+#ifndef CONFIG_MACH_GC1
if (ctrl->cam->cam_power)
+#else
+ if (ctrl->cam->cam_power && !leave_power)
+#endif
ctrl->cam->cam_power(0);
/* shutdown the MCLK */
+#ifndef CONFIG_MACH_GC1
if (fimc->mclk_status == CAM_MCLK_ON) {
+#else
+ if (fimc->mclk_status == CAM_MCLK_ON && !leave_power) {
+#endif
clk_disable(ctrl->cam->clk);
fimc->mclk_status = CAM_MCLK_OFF;
}
@@ -801,9 +824,13 @@ static int fimc_configure_subdev(struct fimc_control *ctrl)
ret = fimc_init_camera(ctrl);
if (ret < 0) {
fimc_err("%s: fail to initialize subdev\n", __func__);
+
+#ifndef CONFIG_MACH_GC1
client = v4l2_get_subdevdata(sd);
i2c_unregister_device(client);
ctrl->cam->sd = NULL;
+#endif
+
return ret;
}
}
@@ -1052,9 +1079,6 @@ int fimc_s_input(struct file *file, void *fh, unsigned int i)
}
#else
ctrl->cam = NULL;
-#ifdef CONFIG_MACH_P4NOTE
- fimc_release_subdev(ctrl);
-#endif /* CONFIG_MACH_P4NOTE */
mutex_unlock(&ctrl->v4l2_lock);
fimc_err("%s: Could not register camera" \
" sensor with V4L2.\n", __func__);
@@ -1117,20 +1141,43 @@ int fimc_s_input(struct file *file, void *fh, unsigned int i)
}
ret = v4l2_subdev_call(ctrl->is.sd, core, s_power, 1);
if (ret < 0) {
- fimc_dbg("FIMC-IS init failed");
+ fimc_err("FIMC-IS init s_power failed");
mutex_unlock(&ctrl->v4l2_lock);
return -ENODEV;
}
ret = v4l2_subdev_call(ctrl->is.sd, core, load_fw);
if (ret < 0) {
- fimc_dbg("FIMC-IS init failed");
+ fimc_err("FIMC-IS init load_fw failed");
mutex_unlock(&ctrl->v4l2_lock);
+ if (!cap) {
+ cap = kzalloc(sizeof(*cap), GFP_KERNEL);
+ if (!cap) {
+ fimc_err("%s: no memory for "
+ "capture device info\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* assign to ctrl */
+ ctrl->cap = cap;
+ }
return -ENODEV;
}
ret = v4l2_subdev_call(ctrl->is.sd, core, init, ctrl->cam->sensor_index);
if (ret < 0) {
- fimc_dbg("FIMC-IS init failed");
+ fimc_err("FIMC-IS init failed");
mutex_unlock(&ctrl->v4l2_lock);
+ if (!cap) {
+ cap = kzalloc(sizeof(*cap), GFP_KERNEL);
+ if (!cap) {
+ fimc_err("%s: no memory for "
+ "capture device info\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* assign to ctrl */
+ ctrl->cap = cap;
+ }
+
return -ENODEV;
}
}
@@ -1188,6 +1235,81 @@ int fimc_enum_fmt_vid_capture(struct file *file, void *fh,
return 0;
}
+#ifdef CONFIG_SLP_DMABUF
+/*
+ * figures out the depth of requested format
+ */
+static int fimc_fmt_depth_mplane(struct fimc_control *ctrl,
+ struct v4l2_format *f, int depth[])
+{
+ int ret = 0;
+
+ /* handles only supported pixelformats */
+ switch (f->fmt.pix_mp.pixelformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ f->fmt.pix_mp.num_planes = 2;
+ depth[0] = 8;
+ depth[1] = 4;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ f->fmt.pix_mp.num_planes = 3;
+ depth[0] = 8;
+ depth[1] = 2;
+ depth[2] = 2;
+ break;
+ case V4L2_PIX_FMT_JPEG:
+ case V4L2_PIX_FMT_INTERLEAVED:
+ f->fmt.pix_mp.num_planes = 1;
+ depth[0] = -1;
+ fimc_dbg("Compressed format.\n");
+ break;
+ default:
+ fimc_dbg("why am I here?\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+static int fimc_g_fmt_vid_capture_mplane(struct fimc_control *ctrl,
+ struct v4l2_format *f)
+{
+ int depth[VIDEO_MAX_PLANES];
+ int ret;
+ int i;
+
+ /*
+ * Note that expecting format only can be with
+ * available output format from FIMC
+ * Following items should be handled in driver
+ * bytesperline = width * depth / 8
+ * sizeimage = bytesperline * height
+ */
+
+ f->fmt.pix_mp.pixelformat = ctrl->cap->fmt.pixelformat;
+ f->fmt.pix_mp.width = ctrl->cap->fmt.width;
+ f->fmt.pix_mp.height = ctrl->cap->fmt.height;
+
+ ret = fimc_fmt_depth_mplane(ctrl, f, depth);
+ if (ret < 0) {
+ fimc_err("Invaild format\n");
+ return ret;
+ }
+ for (i = 0; i < f->fmt.pix_mp.num_planes; ++i) {
+ f->fmt.pix_mp.plane_fmt[i].bytesperline = (f->fmt.pix_mp.width *
+ depth[i]) >> 3;
+ f->fmt.pix_mp.plane_fmt[i].sizeimage =
+ (f->fmt.pix_mp.plane_fmt[i].bytesperline *
+ f->fmt.pix_mp.width);
+ }
+
+ return 0;
+}
+#endif
+
int fimc_g_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
{
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
@@ -1201,8 +1323,20 @@ int fimc_g_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
mutex_lock(&ctrl->v4l2_lock);
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_MULTIPLANAR(f->type))
+ if (fimc_g_fmt_vid_capture_mplane(ctrl, f) < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -EINVAL;
+ }
+ else {
+ memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
+ memcpy(&f->fmt.pix, &ctrl->cap->fmt, sizeof(f->fmt.pix));
+ }
+#else
memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
memcpy(&f->fmt.pix, &ctrl->cap->fmt, sizeof(f->fmt.pix));
+#endif
mutex_unlock(&ctrl->v4l2_lock);
@@ -1308,7 +1442,7 @@ int fimc_s_fmt_vid_private(struct file *file, void *fh, struct v4l2_format *f)
*/
mbus_fmt->field = pix->field;
#endif
-#if (defined(CONFIG_MACH_S2PLUS) || defined(CONFIG_MACH_GC1))
+#if defined(CONFIG_MACH_GC1)
mbus_fmt->field = pix->priv;
#endif
printk(KERN_INFO "%s mbus_fmt->width = %d, height = %d,\n",
@@ -1392,7 +1526,17 @@ int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
mutex_lock(&ctrl->v4l2_lock);
memset(&cap->fmt, 0, sizeof(cap->fmt));
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+ cap->fmt.pixelformat = f->fmt.pix_mp.pixelformat;
+ cap->fmt.width = f->fmt.pix_mp.width;
+ cap->fmt.height = f->fmt.pix_mp.height;
+ cap->fmt.pixelformat = f->fmt.pix_mp.pixelformat;
+ } else
+ memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
+#else
memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
+#endif
/*
* Note that expecting format only can be with
@@ -1434,7 +1578,11 @@ int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
Fimc scaler input Hsize is restricted to 4224 pixels.
So, GC1 has to bypass fimc scaler to use more than 12M YUV.
*/
- ctrl->sc.bypass = 1;
+ if (cap->fmt.width > ctrl->limit->pre_dst_w)
+ ctrl->sc.bypass = 1;
+ else
+ ctrl->sc.bypass = 0;
+
#else
ctrl->sc.bypass = 0;
#endif
@@ -1636,6 +1784,43 @@ static void fimc_free_buffers(struct fimc_control *ctrl)
ctrl->mem.curr = ctrl->mem.base;
}
+#ifdef CONFIG_SLP_DMABUF
+static int fimc_set_cap_num_plane(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+
+ switch (cap->fmt.pixelformat) {
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_JPEG:
+ case V4L2_PIX_FMT_INTERLEAVED:
+ return PLANE_1;
+
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ return PLANE_2;
+
+ case V4L2_PIX_FMT_YUV422P: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ return PLANE_3;
+
+ default:
+ fimc_err("%s: Undefined format\n", __func__);
+ break;
+ }
+
+ return 0;
+}
+#endif
+
int fimc_reqbufs_capture_mmap(void *fh, struct v4l2_requestbuffers *b)
{
struct fimc_control *ctrl = fh;
@@ -1825,7 +2010,10 @@ int fimc_reqbufs_capture_userptr(void *fh, struct v4l2_requestbuffers *b)
fimc_streamoff_capture(fh);
fimc_free_buffers(ctrl);
-
+#ifdef CONFIG_SLP_DMABUF
+ if (b->memory == V4L2_MEMORY_DMABUF)
+ _fimc_queue_free(ctrl, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+#endif
mutex_unlock(&ctrl->v4l2_lock);
return 0;
}
@@ -1837,6 +2025,19 @@ int fimc_reqbufs_capture_userptr(void *fh, struct v4l2_requestbuffers *b)
}
cap->nr_bufs = b->count;
+#ifdef CONFIG_SLP_DMABUF
+ if (b->memory == V4L2_MEMORY_DMABUF) {
+ int num_planes;
+
+ num_planes = fimc_set_cap_num_plane(ctrl);
+ if (!num_planes) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ return 0;
+ }
+ fimc_queue_alloc(ctrl, b->type, b->memory,
+ cap->nr_bufs, num_planes);
+ }
+#endif
#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME))
if (ctrl->power_status == FIMC_POWER_OFF) {
@@ -1996,33 +2197,45 @@ int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c)
switch (c->id) {
#ifdef CONFIG_MACH_GC1
- case V4L2_CID_CAM_UPDATE_FW:
- if (fimc->mclk_status == CAM_MCLK_ON) {
- if (ctrl->cam->cam_power)
- ctrl->cam->cam_power(0);
+ case V4L2_CID_CAMERA_HOLD_LENS:
+ leave_power = true;
+ ret = v4l2_subdev_call(ctrl->cam->sd, core, s_ctrl, c);
+ break;
- /* shutdown the MCLK */
- clk_disable(ctrl->cam->clk);
- fimc->mclk_status = CAM_MCLK_OFF;
+ case V4L2_CID_CAM_UPDATE_FW:
+ if (c->value == FW_MODE_UPDATE || c->value == FW_MODE_DUMP) {
+ if (fimc->mclk_status == CAM_MCLK_ON) {
+ if (ctrl->cam->cam_power)
+ ctrl->cam->cam_power(0);
- mdelay(5);
- }
+ /* shutdown the MCLK */
+ clk_disable(ctrl->cam->clk);
+ fimc->mclk_status = CAM_MCLK_OFF;
- if ((clk_get_rate(ctrl->cam->clk)) && (fimc->mclk_status == CAM_MCLK_OFF)) {
- clk_set_rate(ctrl->cam->clk, ctrl->cam->clk_rate);
- clk_enable(ctrl->cam->clk);
- fimc->mclk_status = CAM_MCLK_ON;
- fimc_info1("clock for camera: %d\n", ctrl->cam->clk_rate);
+ mdelay(5);
+ }
- if (ctrl->cam->cam_power)
- ctrl->cam->cam_power(1);
- }
+ if ((clk_get_rate(ctrl->cam->clk)) &&
+ (fimc->mclk_status == CAM_MCLK_OFF)) {
+ clk_set_rate(ctrl->cam->clk,
+ ctrl->cam->clk_rate);
+ clk_enable(ctrl->cam->clk);
+ fimc->mclk_status = CAM_MCLK_ON;
+ fimc_info1("clock for camera: %d\n",
+ ctrl->cam->clk_rate);
+
+ if (ctrl->cam->cam_power)
+ ctrl->cam->cam_power(1);
+ }
- if (c->value == FW_MODE_UPDATE)
- ret = v4l2_subdev_call(ctrl->cam->sd, core, load_fw);
+ if (c->value == FW_MODE_UPDATE)
+ ret = v4l2_subdev_call(ctrl->cam->sd, core, load_fw);
+ else
+ ret = v4l2_subdev_call(ctrl->cam->sd, core, s_ctrl, c);
- else
+ } else {
ret = v4l2_subdev_call(ctrl->cam->sd, core, s_ctrl, c);
+ }
break;
#endif
case V4L2_CID_CAMERA_RESET:
@@ -2206,6 +2419,12 @@ int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c)
break;
#endif
+ case V4L2_CID_CAMERA_SET_DUAL_CAPTURE:
+ case V4L2_CID_CAMERA_DUAL_CAPTURE:
+ case V4L2_CID_CAMERA_DUAL_POSTVIEW:
+ ret = v4l2_subdev_call(ctrl->cam->sd, core, s_ctrl, c);
+ break;
+
case V4L2_CID_IS_CAMERA_FLASH_MODE:
case V4L2_CID_CAMERA_SCENE_MODE:
default:
@@ -2445,6 +2664,9 @@ int fimc_streamon_capture(void *fh)
struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
printk(KERN_INFO "%s++ fimc%d\n", __func__, ctrl->id);
+#ifdef CONFIG_SLP
+ cam_frmsize.index = -1;
+#endif
cam_frmsize.discrete.width = 0;
cam_frmsize.discrete.height = 0;
is_ctrl.id = 0;
@@ -2617,7 +2839,7 @@ int fimc_streamon_capture(void *fh)
if (!ctrl->is.sd && cap->movie_mode &&
!((cam->width == 880 && cam->height == 720))) {
printk(KERN_INFO "\n\n\n%s pm_qos_req is called..\n", __func__ );
- dev_lock(ctrl->bus_dev, ctrl->dev, (unsigned long)400200);
+ /*dev_lock(ctrl->bus_dev, ctrl->dev, (unsigned long)400200);*/
pm_qos_add_request(&bus_qos_pm_qos_req, PM_QOS_BUS_QOS, 1);
/* ioremap for register block */
@@ -2746,6 +2968,15 @@ int fimc_streamoff_capture(void *fh)
v4l2_subdev_call(ctrl->cam->sd, video, s_stream, 0);
#endif
+ /* Set FIMD to write back */
+ if ((ctrl->cam->id == CAMERA_WB) || (ctrl->cam->id == CAMERA_WB_B)) {
+ ret = s3cfb_direct_ioctl(0, S3CFB_SET_WRITEBACK, 0);
+ if (ret) {
+ fimc_err("failed set writeback\n");
+ return ret;
+ }
+ }
+
/* wait for stop hardware */
fimc_wait_disable_capture(ctrl);
@@ -2783,7 +3014,7 @@ int fimc_streamoff_capture(void *fh)
!(ctrl->cam->width == 880 && ctrl->cam->height == 720)) {
printk(KERN_INFO "\n\n\n%s pm_qos_req is removed..\n", __func__ );
pm_qos_remove_request(&bus_qos_pm_qos_req);
- dev_unlock(ctrl->bus_dev, ctrl->dev);
+ /*dev_unlock(ctrl->bus_dev, ctrl->dev);*/
/* ioremap for register block */
qos_regs = ioremap(0x11a00400, 0x10);
@@ -2798,14 +3029,6 @@ int fimc_streamoff_capture(void *fh)
iounmap(qos_regs);
}
- /* Set FIMD to write back */
- if ((ctrl->cam->id == CAMERA_WB) || (ctrl->cam->id == CAMERA_WB_B)) {
- ret = s3cfb_direct_ioctl(0, S3CFB_SET_WRITEBACK, 0);
- if (ret) {
- fimc_err("failed set writeback\n");
- return ret;
- }
- }
/* disable camera power */
/* cam power off should call in the subdev release function */
if (fimc_cam_use) {
@@ -2904,7 +3127,7 @@ static void fimc_buf2bs(struct fimc_buf_set *bs, struct fimc_buf *buf)
int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b)
{
struct fimc_control *ctrl = fh;
- struct fimc_buf *buf = (struct fimc_buf *)b->m.userptr;
+ struct fimc_buf *buf;
struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
struct fimc_capinfo *cap = ctrl->cap;
int idx = b->index;
@@ -2926,8 +3149,58 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b)
return -EINVAL;
} else {
if (b->memory == V4L2_MEMORY_USERPTR) {
+ buf = (struct fimc_buf *)b->m.userptr;
fimc_buf2bs(&cap->bufs[idx], buf);
fimc_hwset_output_address(ctrl, &cap->bufs[idx], idx);
+#ifdef CONFIG_SLP_DMABUF
+ } else if (b->memory == V4L2_MEMORY_DMABUF) {
+ struct vb2_buffer *vb;
+ struct sg_table *sg;
+ struct dma_buf_attachment *dba;
+ struct fimc_buf fimc_buf;
+ int ret;
+ unsigned int size;
+
+ vb = ctrl->cap_bufs[b->index];
+
+ ret = _qbuf_dmabuf(ctrl, vb, b);
+ if (ret < 0) {
+ fimc_err("%s: _qbuf_dmabuf error.\n",
+ __func__);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -ENODEV;
+ }
+ for (i = 0; i < vb->num_planes; i++) {
+ dba = vb->planes[i].mem_priv;
+ sg = dba->priv;
+ if (sg) {
+ fimc_buf.base[i] =
+ sg_dma_address(sg->sgl);
+ fimc_buf.length[i] =
+ sg_dma_len(sg->sgl);
+ } else {
+ fimc_err("%s: Wrong sg value.\n",
+ __func__);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -ENODEV;
+ }
+ }
+ fimc_buf2bs(&cap->bufs[idx], &fimc_buf);
+ fimc_hwset_output_address(ctrl, &cap->bufs[idx],
+ idx);
+ if (cap->pktdata_enable) {
+ size =
+ fimc_buf.length[vb->num_planes-1];
+ cap->bufs[b->index].vaddr_pktdata =
+ phys_to_virt(
+ cap->bufs[b->index].base
+ [vb->num_planes-1] + size);
+ cap->pktdata_plane = vb->num_planes;
+
+ /* Size of packet data is fixed */
+ cap->pktdata_size = 0x1000;
+ }
+#endif
}
fimc_hwset_output_buf_sequence(ctrl, idx, FIMC_FRAMECNT_SEQ_ENABLE);
@@ -3040,8 +3313,23 @@ int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b)
b->index = bs->id;
bs->state = VIDEOBUF_IDLE;
- if (b->memory == V4L2_MEMORY_USERPTR)
+ if (b->memory == V4L2_MEMORY_USERPTR) {
fimc_bs2buf(buf, bs);
+#ifdef CONFIG_SLP_DMABUF
+ } else if (b->memory == V4L2_MEMORY_DMABUF) {
+ struct vb2_buffer *vb;
+
+ vb = ctrl->cap_bufs[b->index];
+ ret = _dqbuf_dmabuf(ctrl, vb, b);
+ if (ret < 0) {
+ fimc_err("%s: _qbuf_dmabuf error.\n",
+ __func__);
+ spin_unlock_irqrestore(&ctrl->outq_lock,
+ spin_flags);
+ return -ENODEV;
+ }
+#endif
+ }
list_del(&bs->list);
}
@@ -3123,6 +3411,12 @@ int fimc_enum_framesizes(struct file *filp, void *fh, struct v4l2_frmsizeenum *f
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int i;
u32 index = 0;
+
+#ifdef CONFIG_SLP
+ if (ctrl->cam && ctrl->cam->sd)
+ return v4l2_subdev_call(ctrl->cam->sd, video,
+ enum_framesizes, fsize);
+#endif
for (i = 0; i < ARRAY_SIZE(capture_fmts); i++) {
if (fsize->pixel_format != capture_fmts[i].pixelformat)
continue;
diff --git a/drivers/media/video/samsung/fimc/fimc_capture_u1.c b/drivers/media/video/samsung/fimc/fimc_capture_u1.c
index d21d877..1855abf 100644
--- a/drivers/media/video/samsung/fimc/fimc_capture_u1.c
+++ b/drivers/media/video/samsung/fimc/fimc_capture_u1.c
@@ -454,11 +454,7 @@ int fimc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
return 0;
mutex_lock(&ctrl->v4l2_lock);
-#ifdef CONFIG_MACH_S2PLUS
- if (ctrl->id == FIMC0)
-#else
if (ctrl->id != FIMC2)
-#endif
ret = subdev_call(ctrl, video, s_parm, a);
mutex_unlock(&ctrl->v4l2_lock);
@@ -654,11 +650,7 @@ int fimc_s_input(struct file *file, void *fh, unsigned int i)
if (!fimc->camera_isvalid[i])
return -EINVAL;
-#ifdef CONFIG_MACH_S2PLUS
- if (fimc->camera[i]->sd && ctrl->id == FIMC0) {
-#else
if (fimc->camera[i]->sd && ctrl->id != FIMC2) {
-#endif
fimc_err("%s: Camera already in use.\n", __func__);
return -EBUSY;
}
@@ -685,18 +677,6 @@ int fimc_s_input(struct file *file, void *fh, unsigned int i)
printk(KERN_INFO "fimc_s_input activated subdev = %d\n", i);
}
-#ifdef CONFIG_MACH_S2PLUS
- if (ctrl->id == FIMC1) {
- if (i == fimc->active_camera) {
- ctrl->cam = fimc->camera[i];
- fimc_info2("fimc_s_input activating subdev FIMC1 %d\n",
- ctrl->cam->initialized);
- } else {
- mutex_unlock(&ctrl->v4l2_lock);
- return -EINVAL;
- }
- }
-#else
if (ctrl->id == FIMC2) {
if (i == fimc->active_camera) {
ctrl->cam = fimc->camera[i];
@@ -707,7 +687,6 @@ int fimc_s_input(struct file *file, void *fh, unsigned int i)
return -EINVAL;
}
}
-#endif
/*
* The first time alloc for struct cap_info, and will be
@@ -973,11 +952,7 @@ int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
mbus_fmt = &cap->mbus_fmt;
-#ifdef CONFIG_MACH_S2PLUS
- if (ctrl->id == FIMC0) {
-#else
if (ctrl->id != FIMC2) {
-#endif
if (cap->movie_mode || cap->vt_mode ||
cap->fmt.priv == V4L2_PIX_FMT_MODE_HDR) {
#if defined(CONFIG_MACH_PX) && defined(CONFIG_VIDEO_HD_SUPPORT)
@@ -1053,11 +1028,7 @@ int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
return 0;
}
-#ifdef CONFIG_MACH_S2PLUS
- if (ctrl->id == FIMC0)
-#else
if (ctrl->id != FIMC2)
-#endif
ret = subdev_call(ctrl, video, s_mbus_fmt, mbus_fmt);
mutex_unlock(&ctrl->v4l2_lock);
@@ -1637,11 +1608,7 @@ int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c)
if ((ctrl->cam->id == CAMERA_WB) || \
(ctrl->cam->id == CAMERA_WB_B))
break;
-#ifdef CONFIG_MACH_S2PLUS
- if (FIMC0 == ctrl->id)
-#else
if (FIMC2 != ctrl->id)
-#endif
ret = subdev_call(ctrl, core, s_ctrl, c);
else
ret = 0;
@@ -1844,11 +1811,7 @@ int fimc_streamon_capture(void *fh)
cam = ctrl->cam;
if ((ctrl->cam->id != CAMERA_WB) && (ctrl->cam->id != CAMERA_WB_B)) {
-#ifdef CONFIG_MACH_S2PLUS
- if (ctrl->id == FIMC0) {
-#else
if (ctrl->id != FIMC2) {
-#endif
ret = subdev_call(ctrl, video, enum_framesizes, &cam_frmsize);
if (ret < 0) {
dev_err(ctrl->dev, "%s: enum_framesizes failed\n", __func__);
@@ -2067,11 +2030,7 @@ int fimc_streamoff_capture(void *fh)
#if defined(CONFIG_MACH_PX)
#ifdef CONFIG_VIDEO_IMPROVE_STREAMOFF
-#ifdef CONFIG_MACH_S2PLUS
- if ((ctrl->id == FIMC0) && (ctrl->cam->type == CAM_TYPE_MIPI))
-#else
if ((ctrl->id != FIMC2) && (ctrl->cam->type == CAM_TYPE_MIPI))
-#endif
v4l2_subdev_call(ctrl->cam->sd, video, s_stream,
STREAM_MODE_CAM_OFF);
#endif /* CONFIG_VIDEO_IMPROVE_STREAMOFF */
@@ -2090,11 +2049,7 @@ int fimc_streamoff_capture(void *fh)
INIT_LIST_HEAD(&cap->inq);
ctrl->status = FIMC_STREAMOFF;
-#ifdef CONFIG_MACH_S2PLUS
- if (ctrl->id == FIMC0) {
-#else
if (ctrl->id != FIMC2) {
-#endif
if (ctrl->cam->type == CAM_TYPE_MIPI) {
if (ctrl->cam->id == CAMERA_CSI_C)
s3c_csis_stop(CSI_CH_0);
diff --git a/drivers/media/video/samsung/fimc/fimc_dev.c b/drivers/media/video/samsung/fimc/fimc_dev.c
index a0a91cd..1ed79dd 100644
--- a/drivers/media/video/samsung/fimc/fimc_dev.c
+++ b/drivers/media/video/samsung/fimc/fimc_dev.c
@@ -32,9 +32,12 @@
#include <linux/videodev2_exynos_camera.h>
#include <linux/delay.h>
#include <linux/cma.h>
+#include <linux/dma-mapping.h>
#include <plat/fimc.h>
#include <plat/clock.h>
#include <mach/regs-pmu.h>
+#include <linux/cpufreq.h>
+#include <mach/cpufreq.h>
#include "fimc.h"
@@ -711,20 +714,32 @@ static struct fimc_control *fimc_register_controller(struct platform_device *pde
/* In Midas project, FIMC2 reserve memory is used by ION driver. */
if (id != 2) {
#endif
- sprintf(ctrl->cma_name, "%s%d", FIMC_CMA_NAME, ctrl->id);
- err = cma_info(&mem_info, ctrl->dev, 0);
- fimc_info1("%s : [cma_info] start_addr : 0x%x, end_addr : 0x%x, "
- "total_size : 0x%x, free_size : 0x%x\n",
- __func__, mem_info.lower_bound, mem_info.upper_bound,
- mem_info.total_size, mem_info.free_size);
- if (err) {
- fimc_err("%s: get cma info failed\n", __func__);
- ctrl->mem.size = 0;
+#ifdef CONFIG_USE_FIMC_CMA
+ if (id == 1) {
+ ctrl->mem.size =
+ CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMC1 * SZ_1K;
ctrl->mem.base = 0;
- } else {
- ctrl->mem.size = mem_info.total_size;
- ctrl->mem.base = (dma_addr_t)cma_alloc
- (ctrl->dev, ctrl->cma_name, (size_t)ctrl->mem.size, 0);
+ } else
+#endif
+ {
+ sprintf(ctrl->cma_name, "%s%d",
+ FIMC_CMA_NAME, ctrl->id);
+ err = cma_info(&mem_info, ctrl->dev, 0);
+ fimc_info1("%s : [cma_info] start_addr : 0x%x, "
+ " end_addr : 0x%x, total_size : 0x%x, "
+ "free_size : 0x%x\n", __func__,
+ mem_info.lower_bound, mem_info.upper_bound,
+ mem_info.total_size, mem_info.free_size);
+ if (err) {
+ fimc_err("%s: get cma info failed\n", __func__);
+ ctrl->mem.size = 0;
+ ctrl->mem.base = 0;
+ } else {
+ ctrl->mem.size = mem_info.total_size;
+ ctrl->mem.base = (dma_addr_t)cma_alloc
+ (ctrl->dev, ctrl->cma_name,
+ (size_t)ctrl->mem.size, 0);
+ }
}
#ifdef CONFIG_ION_EXYNOS
}
@@ -813,7 +828,7 @@ static struct fimc_control *fimc_register_controller(struct platform_device *pde
clk_put(fimc_src_clk);
return NULL;
}
- clk_set_rate(sclk_fimc_lclk, FIMC_CLK_RATE);
+ clk_set_rate(sclk_fimc_lclk, fimc_clk_rate());
clk_put(sclk_fimc_lclk);
clk_put(fimc_src_clk);
@@ -1021,6 +1036,255 @@ static int fimc_mmap(struct file *filp, struct vm_area_struct *vma)
return ret;
}
+#ifdef CONFIG_SLP_DMABUF
+/**
+ * _fimc_dmabuf_put() - release memory associated with
+ * a DMABUF shared buffer
+ */
+static void _fimc_dmabuf_put(struct vb2_buffer *vb)
+{
+ unsigned int plane;
+
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ void *mem_priv = vb->planes[plane].mem_priv;
+
+ if (mem_priv) {
+ dma_buf_detach(vb->planes[plane].dbuf,
+ vb->planes[plane].mem_priv);
+ dma_buf_put(vb->planes[plane].dbuf);
+ vb->planes[plane].dbuf = NULL;
+ vb->planes[plane].mem_priv = NULL;
+ }
+ }
+}
+
+void _fimc_queue_free(struct fimc_control *ctrl, enum v4l2_buf_type type)
+{
+ unsigned int buffer;
+ struct vb2_buffer *vb;
+
+ for (buffer = 0; buffer < VIDEO_MAX_FRAME; ++buffer) {
+ if (V4L2_TYPE_IS_OUTPUT(type))
+ vb = ctrl->out_bufs[buffer];
+ else
+ vb = ctrl->cap_bufs[buffer];
+
+ if (!vb)
+ continue;
+ _fimc_dmabuf_put(vb);
+ kfree(vb);
+ vb = NULL;
+ }
+}
+
+int fimc_queue_alloc(struct fimc_control *ctrl, enum v4l2_buf_type type,
+ enum v4l2_memory memory, unsigned int num_buffers,
+ unsigned int num_planes)
+{
+ unsigned int buffer;
+ struct vb2_buffer *vb;
+
+ for (buffer = 0; buffer < num_buffers; ++buffer) {
+ vb = kzalloc(sizeof(struct vb2_buffer), GFP_KERNEL);
+ if (!vb) {
+ fimc_err("%s: Memory alloc for buffer struct failed\n",
+ __func__);
+ break;
+ }
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(type))
+ vb->v4l2_buf.length = num_planes;
+
+ vb->num_planes = num_planes;
+ vb->v4l2_buf.index = buffer;
+ vb->v4l2_buf.type = type;
+ vb->v4l2_buf.memory = memory;
+
+ if (V4L2_TYPE_IS_OUTPUT(type))
+ ctrl->out_bufs[buffer] = vb;
+ else
+ ctrl->cap_bufs[buffer] = vb;
+ }
+
+ for (buffer = num_buffers; buffer < VIDEO_MAX_FRAME; ++buffer) {
+ ctrl->out_bufs[buffer] = NULL;
+ ctrl->cap_bufs[buffer] = NULL;
+ }
+
+ return buffer;
+}
+
+static inline int _verify_planes_array(struct vb2_buffer *vb,
+ const struct v4l2_buffer *b)
+{
+ if (NULL == b->m.planes) {
+ printk(KERN_ERR "%s: Multi-planar buffer passwd but planes"
+ " array not provided\n", __func__);
+ return -EINVAL;
+ }
+ if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
+ printk(KERN_ERR "%s: Incorrect planes array length, "
+ "expected %d, got %d\n", __func__,
+ vb->num_planes, b->length);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
+ struct v4l2_plane *v4l2_planes)
+{
+ int plane;
+ int ret;
+
+ memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
+ b->input = vb->v4l2_buf.input;
+ b->reserved = vb->v4l2_buf.reserved;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ ret = _verify_planes_array(vb, b);
+ if (ret)
+ return ret;
+
+ memcpy(b->m.planes, vb->v4l2_planes,
+ b->length * sizeof(struct v4l2_plane));
+
+ for (plane = 0; plane < vb->num_planes; ++plane)
+ b->m.planes[plane].m.fd =
+ vb->v4l2_planes[plane].m.fd;
+ } else {
+ b->length = vb->v4l2_planes[0].length;
+ b->bytesused = vb->v4l2_planes[0].bytesused;
+ b->m.fd = vb->v4l2_planes[0].m.fd;
+ }
+
+ return ret;
+}
+
+static int _fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
+ struct v4l2_plane *v4l2_planes)
+{
+ unsigned int plane;
+ int ret;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+ ret = _verify_planes_array(vb, b);
+ if (ret)
+ return ret;
+
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ v4l2_planes[plane].bytesused =
+ b->m.planes[plane].bytesused;
+ v4l2_planes[plane].data_offset =
+ b->m.planes[plane].data_offset;
+ }
+ }
+ for (plane = 0; plane < vb->num_planes; ++plane)
+ v4l2_planes[plane].m.fd =
+ b->m.planes[plane].m.fd;
+
+ } else {
+ if (V4L2_TYPE_IS_OUTPUT(b->type))
+ v4l2_planes[0].bytesused =
+ b->bytesused;
+ v4l2_planes[0].m.fd = b->m.fd;
+ }
+
+ vb->v4l2_buf.field = b->field;
+ vb->v4l2_buf.timestamp = b->timestamp;
+ vb->v4l2_buf.input = b->input;
+
+ return 0;
+}
+
+int _qbuf_dmabuf(struct fimc_control *ctrl, struct vb2_buffer *vb,
+ struct v4l2_buffer *b)
+{
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ unsigned int plane;
+ struct sg_table *sg;
+ struct dma_buf_attachment *dba;
+ int ret;
+
+ ret = _fill_vb2_buffer(vb, b, planes);
+ if (ret)
+ return ret;
+
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
+
+ if (IS_ERR_OR_NULL(dbuf)) {
+ fimc_err("dmabuf get error!!! %x\n", plane);
+ ret = PTR_ERR(dbuf);
+ goto err;
+ }
+ planes[plane].length = dbuf->size;
+
+ /* Skip the plane if already verified */
+ if (dbuf == vb->planes[plane].dbuf) {
+ dma_buf_put(dbuf);
+ continue;
+ }
+
+ vb->planes[plane].mem_priv = NULL;
+
+ dba = dma_buf_attach(dbuf, ctrl->dev);
+ if (IS_ERR(dba)) {
+ fimc_err("failed to attach dmabuf\n");
+ dma_buf_put(dbuf);
+ ret = PTR_ERR(dba);
+ goto err;
+ }
+
+ sg = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL);
+ if (IS_ERR(sg)) {
+ fimc_err("qbuf: failed acquiring dmabuf "
+ "memory for plane\n");
+ ret = PTR_ERR(sg);
+ goto err;
+ }
+ dba->priv = sg;
+
+ vb->planes[plane].dbuf = dbuf;
+ vb->planes[plane].mem_priv = dba;
+
+ vb->v4l2_planes[plane] = planes[plane];
+ }
+
+ return 0;
+
+err:
+ _fimc_dmabuf_put(vb);
+
+ return ret;
+}
+
+int _dqbuf_dmabuf(struct fimc_control *ctrl, struct vb2_buffer *vb,
+ struct v4l2_buffer *b)
+{
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ struct sg_table *sg[VIDEO_MAX_PLANES];
+ struct dma_buf_attachment *dba[VIDEO_MAX_PLANES];
+ unsigned int plane;
+ int ret;
+
+ ret = _fill_v4l2_buffer(vb, b, planes);
+ if (ret)
+ return ret;
+
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ dba[plane] = vb->planes[plane].mem_priv;
+ sg[plane] = dba[plane]->priv;
+ dma_buf_unmap_attachment(dba[plane],
+ sg[plane], DMA_FROM_DEVICE);
+ }
+
+ return 0;
+}
+#endif
+
static u32 fimc_poll(struct file *filp, poll_table *wait)
{
struct fimc_prv_data *prv_data =
@@ -1226,6 +1490,19 @@ static int fimc_open(struct file *filp)
goto kzalloc_err;
}
+#ifdef CONFIG_USE_FIMC_CMA
+ if (ctrl->id == 1) {
+ ctrl->mem.cpu_addr = dma_alloc_coherent(ctrl->dev,
+ ctrl->mem.size, &(ctrl->mem.base), 0);
+ if (!ctrl->mem.cpu_addr) {
+ printk(KERN_INFO "FIMC%d: dma_alloc_coherent failed\n",
+ ctrl->id);
+ ret = -ENOMEM;
+ goto dma_alloc_err;
+ }
+ }
+#endif
+
if (in_use == 1) {
#if (!defined(CONFIG_EXYNOS_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
if (pdata->clk_on)
@@ -1276,6 +1553,11 @@ static int fimc_open(struct file *filp)
return 0;
+#ifdef CONFIG_USE_FIMC_CMA
+dma_alloc_err:
+ kfree(prv_data);
+#endif
+
kzalloc_err:
atomic_dec(&ctrl->in_use);
@@ -1425,6 +1707,9 @@ static int fimc_release(struct file *filp)
} else {
ctrl->out->ctx_used[ctx_id] = false;
}
+#ifdef CONFIG_SLP_DMABUF
+ _fimc_queue_free(ctrl, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+#endif
}
if (ctrl->cap) {
@@ -1445,6 +1730,9 @@ static int fimc_release(struct file *filp)
}
kfree(ctrl->cap);
ctrl->cap = NULL;
+#ifdef CONFIG_SLP_DMABUF
+ _fimc_queue_free(ctrl, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+#endif
}
/*
@@ -1462,6 +1750,14 @@ static int fimc_release(struct file *filp)
ctrl->fb.is_enable = 0;
}
+#ifdef CONFIG_USE_FIMC_CMA
+ if (ctrl->id == 1) {
+ dma_free_coherent(ctrl->dev, ctrl->mem.size, ctrl->mem.cpu_addr,
+ ctrl->mem.base);
+ ctrl->mem.base = 0;
+ ctrl->mem.cpu_addr = NULL;
+ }
+#endif
fimc_warn("FIMC%d %d released.\n",
ctrl->id, atomic_read(&ctrl->in_use));
@@ -1840,7 +2136,7 @@ static int __devinit fimc_probe(struct platform_device *pdev)
ret = device_create_file(&(pdev->dev), &dev_attr_range_mode);
if (ret < 0) {
fimc_err("failed to add sysfs entries for range mode\n");
- goto err_global;
+ goto err_create_file;
}
printk(KERN_INFO "FIMC%d registered successfully\n", ctrl->id);
#if (defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME))
@@ -1848,7 +2144,7 @@ static int __devinit fimc_probe(struct platform_device *pdev)
ctrl->fimc_irq_wq = create_workqueue(buf);
if (ctrl->fimc_irq_wq == NULL) {
fimc_err("failed to create_workqueue\n");
- goto err_global;
+ goto err_wq;
}
INIT_WORK(&ctrl->work_struct, s3c_fimc_irq_work);
@@ -1869,6 +2165,12 @@ static int __devinit fimc_probe(struct platform_device *pdev)
return 0;
+err_wq:
+ device_remove_file(&(pdev->dev), &dev_attr_range_mode);
+
+err_create_file:
+ device_remove_file(&(pdev->dev), &dev_attr_log_level);
+
err_global:
video_unregister_device(ctrl->vd);
diff --git a/drivers/media/video/samsung/fimc/fimc_dev_u1.c b/drivers/media/video/samsung/fimc/fimc_dev_u1.c
index f36db5d..762256b 100644
--- a/drivers/media/video/samsung/fimc/fimc_dev_u1.c
+++ b/drivers/media/video/samsung/fimc/fimc_dev_u1.c
@@ -682,7 +682,7 @@ struct fimc_control *fimc_register_controller(struct platform_device *pdev)
clk_put(fimc_src_clk);
return NULL;
}
- clk_set_rate(sclk_fimc_lclk, FIMC_CLK_RATE);
+ clk_set_rate(sclk_fimc_lclk, fimc_clk_rate());
clk_put(sclk_fimc_lclk);
clk_put(fimc_src_clk);
@@ -1419,6 +1419,30 @@ static int fimc_init_global(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_DRM_EXYNOS_FIMD_WB
+static BLOCKING_NOTIFIER_HEAD(fimc_notifier_client_list);
+
+int fimc_register_client(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(
+ &fimc_notifier_client_list, nb);
+}
+EXPORT_SYMBOL(fimc_register_client);
+
+int fimc_unregister_client(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(
+ &fimc_notifier_client_list, nb);
+}
+EXPORT_SYMBOL(fimc_unregister_client);
+
+int fimc_send_event(unsigned long val, void *v)
+{
+ return blocking_notifier_call_chain(
+ &fimc_notifier_client_list, val, v);
+}
+#endif
+
static int fimc_show_log_level(struct device *dev,
struct device_attribute *attr, char *buf)
{
diff --git a/drivers/media/video/samsung/fimc/fimc_output.c b/drivers/media/video/samsung/fimc/fimc_output.c
index 895cb7f..57611e5 100644
--- a/drivers/media/video/samsung/fimc/fimc_output.c
+++ b/drivers/media/video/samsung/fimc/fimc_output.c
@@ -25,6 +25,9 @@
#include <plat/media.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#ifdef CONFIG_SLP_DMABUF
+#include <linux/dma-buf.h>
+#endif
#include "fimc.h"
#include "fimc-ipc.h"
@@ -287,6 +290,33 @@ static void fimc_init_out_buf(struct fimc_ctx *ctx)
}
}
+#ifdef CONFIG_SLP_DMABUF
+static int fimc_set_out_num_plane(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ u32 format = ctx->pix.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YUYV:
+ return PLANE_1;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ return PLANE_2;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ return PLANE_3;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+
static int fimc_outdev_set_src_buf(struct fimc_control *ctrl,
struct fimc_ctx *ctx)
{
@@ -1690,6 +1720,10 @@ int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b)
default:
break;
}
+#ifdef CONFIG_SLP_DMABUF
+ if (b->memory == V4L2_MEMORY_DMABUF)
+ _fimc_queue_free(ctrl, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+#endif
} else {
/* initialize source buffers */
if (b->memory == V4L2_MEMORY_MMAP) {
@@ -1701,6 +1735,14 @@ int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b)
if (mode == FIMC_OVLY_DMA_AUTO ||
mode == FIMC_OVLY_NOT_FIXED)
ctx->overlay.req_idx = FIMC_USERPTR_IDX;
+#ifdef CONFIG_SLP_DMABUF
+ } else if (b->memory == V4L2_MEMORY_DMABUF) {
+ int num_planes;
+
+ num_planes = fimc_set_out_num_plane(ctrl, ctx);
+ fimc_queue_alloc(ctrl, b->type, b->memory, b->count,
+ num_planes);
+#endif
}
ctx->is_requested = 1;
@@ -2365,6 +2407,7 @@ static int fimc_outdev_start_operation(struct fimc_control *ctrl,
ret = fimc_outdev_start_camif(ctrl);
if (ret < 0) {
fimc_err("Fail: fimc_start_camif\n");
+ spin_unlock_irqrestore(&ctrl->out->slock, spin_flags);
return -EINVAL;
}
@@ -2399,6 +2442,7 @@ static int fimc_qbuf_output_single_buf(struct fimc_control *ctrl,
case V4L2_PIX_FMT_RGB32:
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
buf_set.base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
break;
case V4L2_PIX_FMT_YUV420:
@@ -2465,9 +2509,11 @@ static int fimc_qbuf_output_multi_buf(struct fimc_control *ctrl,
case V4L2_PIX_FMT_RGB32:
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
break;
case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420: /* fall through */
buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
buf_set.base[FIMC_ADDR_CB] = ctx->dst[idx].base[FIMC_ADDR_CB];
buf_set.base[FIMC_ADDR_CR] = ctx->dst[idx].base[FIMC_ADDR_CR];
@@ -2680,7 +2726,7 @@ static int fimc_update_in_queue_addr(struct fimc_control *ctrl,
int fimc_qbuf_output(void *fh, struct v4l2_buffer *b)
{
- struct fimc_buf *buf = (struct fimc_buf *)b->m.userptr;
+ struct fimc_buf *buf;
struct fimc_ctx *ctx;
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
@@ -2716,9 +2762,40 @@ int fimc_qbuf_output(void *fh, struct v4l2_buffer *b)
(ctrl->status == FIMC_STREAMON) ||
(ctrl->status == FIMC_STREAMON_IDLE)) {
if (b->memory == V4L2_MEMORY_USERPTR) {
+ buf = (struct fimc_buf *)b->m.userptr;
ret = fimc_update_in_queue_addr(ctrl, ctx, b->index, buf->base);
if (ret < 0)
return ret;
+#ifdef CONFIG_SLP_DMABUF
+ } else if (b->memory == V4L2_MEMORY_DMABUF) {
+ struct vb2_buffer *vb;
+ dma_addr_t addr[3];
+ struct sg_table *sg;
+ struct dma_buf_attachment *dba;
+ int i;
+
+ vb = ctrl->out_bufs[b->index];
+ ret = _qbuf_dmabuf(ctrl, vb, b);
+ if (ret < 0) {
+ fimc_err("_qbuf_dmabuf failed ret = %d\n", ret);
+ return ret;
+ }
+ for (i = 0; i < vb->num_planes; i++) {
+ dba = vb->planes[i].mem_priv;
+ sg = dba->priv;
+ if (sg)
+ addr[i] = sg_dma_address(sg->sgl);
+ else {
+ fimc_err("%s: Wrong sg value.\n",
+ __func__);
+ return -ENODEV;
+ }
+ }
+ ret = fimc_update_in_queue_addr(ctrl, ctx, b->index,
+ addr);
+ if (ret < 0)
+ return ret;
+#endif
}
#if defined(CONFIG_EXYNOS_DEV_PD) && defined(CONFIG_PM_RUNTIME)
@@ -2831,6 +2908,7 @@ int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
int idx = -1, ret = -1;
ctx = &ctrl->out->ctx[ctx_id];
+
ret = fimc_pop_outq(ctrl, ctx, &idx);
if (ret < 0) {
ret = wait_event_timeout(ctrl->wq, (ctx->outq[0] != -1),
@@ -2838,7 +2916,6 @@ int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
if (ret == 0) {
fimc_dump_context(ctrl, ctx);
fimc_recover_output(ctrl, ctx);
- pm_runtime_put_sync(ctrl->dev);
fimc_err("[0] out_queue is empty\n");
return -EAGAIN;
} else if (ret == -ERESTARTSYS) {
@@ -2854,7 +2931,18 @@ int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
}
}
}
+#ifdef CONFIG_SLP_DMABUF
+ if (b->memory == V4L2_MEMORY_DMABUF) {
+ struct vb2_buffer *vb;
+ vb = ctrl->out_bufs[idx];
+ ret = _dqbuf_dmabuf(ctrl, vb, b);
+ if (ret < 0) {
+ fimc_err("%s: _qbuf_dmabuf error.\n", __func__);
+ return -ENODEV;
+ }
+ }
+#endif
b->index = idx;
fimc_info2("ctx(%d) dqueued idx = %d\n", ctx->ctx_num, b->index);
diff --git a/drivers/media/video/samsung/fimc/fimc_regs.c b/drivers/media/video/samsung/fimc/fimc_regs.c
index 332e5db..20888c7 100644
--- a/drivers/media/video/samsung/fimc/fimc_regs.c
+++ b/drivers/media/video/samsung/fimc/fimc_regs.c
@@ -258,6 +258,9 @@ static void fimc_reset_cfg(struct fimc_control *ctrl)
{
int i;
u32 cfg[][2] = {
+#ifdef CONFIG_SLP
+ { 0x008, 0x20010480 },
+#endif
{ 0x018, 0x00000000 }, { 0x01c, 0x00000000 },
{ 0x020, 0x00000000 }, { 0x024, 0x00000000 },
{ 0x028, 0x00000000 }, { 0x02c, 0x00000000 },
@@ -1253,7 +1256,11 @@ int fimc_hwset_disable_capture(struct fimc_control *ctrl)
void fimc_wait_disable_capture(struct fimc_control *ctrl)
{
+#ifdef CONFIG_VIDEO_S5K5BBGX
+ unsigned long timeo = jiffies + 60; /* more 40 ms */
+#else
unsigned long timeo = jiffies + 40; /* timeout of 200 ms */
+#endif
u32 cfg;
if (!ctrl || !ctrl->cap)
return;
diff --git a/drivers/media/video/samsung/fimc/fimc_v4l2.c b/drivers/media/video/samsung/fimc/fimc_v4l2.c
index 510e2f1..becd16c 100644
--- a/drivers/media/video/samsung/fimc/fimc_v4l2.c
+++ b/drivers/media/video/samsung/fimc/fimc_v4l2.c
@@ -35,8 +35,15 @@ static int fimc_querycap(struct file *filp, void *fh,
sprintf(cap->bus_info, "FIMC AHB-bus");
cap->version = 0;
+#ifdef CONFIG_SLP_DMABUF
+ cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+ V4L2_CAP_VIDEO_CAPTURE_MPLANE);
+#else
cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING);
+#endif
return 0;
}
@@ -47,6 +54,18 @@ static int fimc_reqbufs(struct file *filp, void *fh,
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ ret = fimc_reqbufs_output(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_reqbufs_capture(ctrl, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_reqbufs_capture(ctrl, b);
} else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -56,6 +75,7 @@ static int fimc_reqbufs(struct file *filp, void *fh,
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -65,6 +85,18 @@ static int fimc_querybuf(struct file *filp, void *fh, struct v4l2_buffer *b)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ ret = fimc_querybuf_output(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_querybuf_capture(ctrl, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_querybuf_capture(ctrl, b);
} else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -74,6 +106,7 @@ static int fimc_querybuf(struct file *filp, void *fh, struct v4l2_buffer *b)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -148,6 +181,18 @@ static int fimc_cropcap(struct file *filp, void *fh, struct v4l2_cropcap *a)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(a->type)) {
+ ret = fimc_cropcap_output(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_cropcap_capture(ctrl, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_cropcap_capture(ctrl, a);
} else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -157,6 +202,7 @@ static int fimc_cropcap(struct file *filp, void *fh, struct v4l2_cropcap *a)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -166,6 +212,18 @@ static int fimc_g_crop(struct file *filp, void *fh, struct v4l2_crop *a)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(a->type)) {
+ ret = fimc_g_crop_output(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_g_crop_capture(ctrl, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_g_crop_capture(ctrl, a);
} else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -175,6 +233,7 @@ static int fimc_g_crop(struct file *filp, void *fh, struct v4l2_crop *a)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -184,6 +243,18 @@ static int fimc_s_crop(struct file *filp, void *fh, struct v4l2_crop *a)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(a->type)) {
+ ret = fimc_s_crop_output(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_s_crop_capture(ctrl, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_s_crop_capture(ctrl, a);
} else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -193,6 +264,7 @@ static int fimc_s_crop(struct file *filp, void *fh, struct v4l2_crop *a)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -202,6 +274,18 @@ static int fimc_streamon(struct file *filp, void *fh, enum v4l2_buf_type i)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(i)) {
+ ret = fimc_streamon_output(fh);
+ } else if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || i == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_streamon_capture(ctrl);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_streamon_capture(ctrl);
} else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -211,6 +295,7 @@ static int fimc_streamon(struct file *filp, void *fh, enum v4l2_buf_type i)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -220,6 +305,18 @@ static int fimc_streamoff(struct file *filp, void *fh, enum v4l2_buf_type i)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(i)) {
+ ret = fimc_streamoff_output(fh);
+ } else if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || i == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_streamoff_capture(ctrl);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_streamoff_capture(ctrl);
} else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -229,6 +326,7 @@ static int fimc_streamoff(struct file *filp, void *fh, enum v4l2_buf_type i)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -238,6 +336,18 @@ static int fimc_qbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ ret = fimc_qbuf_output(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_qbuf_capture(ctrl, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_qbuf_capture(ctrl, b);
} else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -247,6 +357,7 @@ static int fimc_qbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -256,6 +367,18 @@ static int fimc_dqbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
int ret = -1;
+#ifdef CONFIG_SLP_DMABUF
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ ret = fimc_dqbuf_output(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+ || b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = fimc_dqbuf_capture(ctrl, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+#else
if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
ret = fimc_dqbuf_capture(ctrl, b);
} else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
@@ -265,6 +388,7 @@ static int fimc_dqbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
"V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
ret = -EINVAL;
}
+#endif
return ret;
}
@@ -315,6 +439,12 @@ const struct v4l2_ioctl_ops fimc_v4l2_ops = {
.vidioc_querymenu = fimc_querymenu,
.vidioc_g_fmt_vid_out = fimc_g_fmt_vid_out,
.vidioc_s_fmt_vid_out = fimc_s_fmt_vid_out,
+#ifdef CONFIG_SLP_DMABUF
+ .vidioc_g_fmt_vid_cap_mplane = fimc_g_fmt_vid_capture,
+ .vidioc_s_fmt_vid_cap_mplane = fimc_s_fmt_vid_capture,
+ .vidioc_g_fmt_vid_out_mplane = fimc_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out_mplane = fimc_s_fmt_vid_out,
+#endif
.vidioc_try_fmt_vid_out = fimc_try_fmt_vid_out,
.vidioc_g_fbuf = fimc_g_fbuf,
.vidioc_s_fbuf = fimc_s_fbuf,
diff --git a/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_dev.c b/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_dev.c
index 5ccde4a..e0d7d4e 100644
--- a/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_dev.c
+++ b/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_dev.c
@@ -477,16 +477,27 @@ static int g2d_remove(struct platform_device *dev)
#if defined(CONFIG_HAS_EARLYSUSPEND)
void g2d_early_suspend(struct early_suspend *h)
{
+ int i = 0;
+
atomic_set(&g2d_dev->ready_to_run, 0);
/* wait until G2D running is finished */
while(1) {
if (!atomic_read(&g2d_dev->in_use))
break;
-
+
msleep_interruptible(2);
+
+ i++;
+ /* Timeout 1sec */
+ if (i > 500) {
+ g2d_clk_enable(g2d_dev);
+ g2d_reset(g2d_dev);
+ g2d_clk_disable(g2d_dev);
+ break;
+ }
}
-
+
g2d_sysmmu_off(g2d_dev);
#if defined(CONFIG_EXYNOS_DEV_PD)
@@ -513,25 +524,37 @@ void g2d_late_resume(struct early_suspend *h)
#if !defined(CONFIG_HAS_EARLYSUSPEND)
static int g2d_suspend(struct platform_device *dev, pm_message_t state)
{
+ int i = 0;
+
atomic_set(&g2d_dev->ready_to_run, 0);
/* wait until G2D running is finished */
while(1) {
if (!atomic_read(&g2d_dev->in_use))
break;
-
+
msleep_interruptible(2);
+
+ i++;
+ /* Timeout 1sec */
+ if (i > 500) {
+ g2d_clk_enable(g2d_dev);
+ g2d_reset(g2d_dev);
+ g2d_clk_disable(g2d_dev);
+ break;
+ }
}
-
+
g2d_sysmmu_off(g2d_dev);
-
+
#if defined(CONFIG_EXYNOS_DEV_PD)
/* disable the power domain */
pm_runtime_put(g2d_dev->dev);
-#endif
+#endif
return 0;
}
+
static int g2d_resume(struct platform_device *pdev)
{
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h
index 2d8f3b7..3bbb194 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h
@@ -41,6 +41,15 @@
#define FIMG2D_BITBLT_SYNC _IOW(FIMG2D_IOCTL_MAGIC, 1, int)
#define FIMG2D_BITBLT_VERSION _IOR(FIMG2D_IOCTL_MAGIC, 2, struct fimg2d_version)
#define FIMG2D_BITBLT_SECURE _IOW(FIMG2D_IOCTL_MAGIC, 3, unsigned int)
+#define FIMG2D_BITBLT_DBUFFER _IOW(FIMG2D_IOCTL_MAGIC, 4, unsigned long)
+
+#define SEQ_NO_BLT_SKIA 0x00000001
+#define SEQ_NO_BLT_HWC_SEC 0x00000012
+#define SEQ_NO_BLT_HWC_NOSEC 0x00000002
+#define SEQ_NO_BLT_HDMI 0x00000003
+#define SEQ_NO_CMD_SECURE_ON 0x10000001
+#define SEQ_NO_CMD_SECURE_OFF 0x10000002
+#define SEQ_NO_CMD_SET_DBUFFER 0x10000003
struct fimg2d_version {
unsigned int hw;
@@ -429,6 +438,7 @@ struct fimg2d_context {
atomic_t ncmd;
wait_queue_head_t wait_q;
struct fimg2d_perf perf[MAX_PERF_DESCS];
+ unsigned long *pgd_clone;
};
/**
@@ -486,6 +496,8 @@ struct fimg2d_control {
int irq;
unsigned int secure;
+ unsigned int dbuffer_addr;
+ unsigned long fault_addr;
atomic_t nctx;
atomic_t busy;
atomic_t active;
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c
index fc6016c..1eb8d63 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c
@@ -83,7 +83,12 @@ void fimg2d4x_bitblt(struct fimg2d_control *info)
goto blitend;
if (cmd->image[IDST].addr.type != ADDR_PHYS) {
- pgd = (unsigned long *)ctx->mm->pgd;
+ if ((cmd->image[IDST].addr.type == ADDR_USER_CONTIG) ||
+ (cmd->image[ISRC].addr.type == ADDR_USER_CONTIG))
+ pgd = (unsigned long *)ctx->pgd_clone;
+ else
+ pgd = (unsigned long *)ctx->mm->pgd;
+
s5p_sysmmu_enable(info->dev, (unsigned long)virt_to_phys(pgd));
fimg2d_debug("sysmmu enable: pgd %p ctx %p seq_no(%u)\n",
pgd, ctx, cmd->seq_no);
@@ -98,6 +103,8 @@ void fimg2d4x_bitblt(struct fimg2d_control *info)
info->run(info);
fimg2d4x_blit_wait(info, cmd);
+ if (info->fault_addr)
+ fimg2d_mmutable_value_replace(cmd, info->fault_addr, 0);
#ifdef PERF_PROFILE
perf_end(cmd->ctx, PERF_BLIT);
#endif
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c
index 4eb4d04..7835dee 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c
@@ -16,6 +16,7 @@
#include "fimg2d.h"
#include "fimg2d4x.h"
#include "fimg2d_clk.h"
+#include "fimg2d_cache.h"
#define wr(d, a) writel((d), info->regs + (a))
#define rd(a) readl(info->regs + (a))
@@ -124,7 +125,13 @@ void fimg2d4x_set_src_image(struct fimg2d_control *info, struct fimg2d_image *s)
{
unsigned long cfg;
- wr(FIMG2D_ADDR(s->addr.start), FIMG2D_SRC_BASE_ADDR_REG);
+ if ((s->addr.type == ADDR_USER_CONTIG) && (s->order < ARGB_ORDER_END)) {
+ wr(FIMG2D_ADDR(GET_MVA(s->addr.start, s->plane2.start)),
+ FIMG2D_SRC_BASE_ADDR_REG);
+ } else {
+ wr(FIMG2D_ADDR(s->addr.start), FIMG2D_SRC_BASE_ADDR_REG);
+ }
+
wr(FIMG2D_STRIDE(s->stride), FIMG2D_SRC_STRIDE_REG);
if (s->order < ARGB_ORDER_END) { /* argb */
@@ -173,7 +180,13 @@ void fimg2d4x_set_dst_image(struct fimg2d_control *info, struct fimg2d_image *d)
{
unsigned long cfg;
- wr(FIMG2D_ADDR(d->addr.start), FIMG2D_DST_BASE_ADDR_REG);
+ if ((d->addr.type == ADDR_USER_CONTIG) && (d->order < ARGB_ORDER_END)) {
+ wr(FIMG2D_ADDR(GET_MVA(d->addr.start, d->plane2.start)),
+ FIMG2D_DST_BASE_ADDR_REG);
+ } else {
+ wr(FIMG2D_ADDR(d->addr.start), FIMG2D_DST_BASE_ADDR_REG);
+ }
+
wr(FIMG2D_STRIDE(d->stride), FIMG2D_DST_STRIDE_REG);
if (d->order < ARGB_ORDER_END) {
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.c
index 43489e4..f5486b1 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.c
@@ -114,8 +114,48 @@ void fimg2d_clean_outer_pagetable(struct mm_struct *mm, unsigned long vaddr,
lv1++;
} while (lv1 != lv1end);
}
+
+void fimg2d_clean_outer_pagetable_clone(unsigned long *pgd_clone,
+ unsigned long vaddr, size_t size)
+{
+ unsigned long *pgd;
+ unsigned long *lv1, *lv1end;
+ unsigned long lv2pa;
+
+ pgd = (unsigned long *)pgd_clone;
+
+ lv1 = pgd + (vaddr >> LV1_SHIFT);
+ lv1end = pgd + ((vaddr + size + LV1_PT_SIZE-1) >> LV1_SHIFT);
+
+ /* clean level1 page table */
+ outer_clean_range(virt_to_phys(lv1), virt_to_phys(lv1end));
+
+ do {
+ /* if page size is 4KB, clean level2 page table entry */
+ if ((*lv1 & 0x3) == 0x1) {
+ lv2pa = *lv1 & ~LV2_BASE_MASK; /* lv2 pt base */
+ /* clean level2 page table */
+ outer_clean_range(lv2pa, lv2pa + LV2_PT_SIZE);
+ }
+ lv1++;
+ } while (lv1 != lv1end);
+}
#endif /* CONFIG_OUTER_CACHE */
+void fimg2d_clean_inner_pagetable_clone(unsigned long *pgd_clone,
+ unsigned long vaddr, size_t size)
+{
+ unsigned long *pgd;
+ unsigned long *lv1, *lv1end;
+
+ pgd = (unsigned long *)pgd_clone;
+
+ lv1 = pgd + (vaddr >> LV1_SHIFT);
+ lv1end = pgd + ((vaddr + size + LV1_PT_SIZE-1) >> LV1_SHIFT);
+ fimg2d_dma_sync_inner((unsigned long)lv1,
+ (unsigned int)lv1end - (unsigned int)lv1, DMA_TO_DEVICE);
+}
+
enum pt_status fimg2d_check_pagetable(struct mm_struct *mm, unsigned long vaddr,
size_t size)
{
@@ -166,3 +206,50 @@ enum pt_status fimg2d_check_pagetable(struct mm_struct *mm, unsigned long vaddr,
return PT_NORMAL;
}
+
+#define PT_NS 0x0 // Non Secure
+#define PT_AP 0x8c00 // Access permission
+#define PT_ENTRY 0x2 // 1MB Page
+
+enum pt_status fimg2d_migrate_pagetable(unsigned long *pgd_clone,
+ unsigned long vaddr, unsigned long paddr, size_t size)
+{
+ unsigned long *pgd;
+ unsigned long *lv1d;
+
+ pgd = (unsigned long *)pgd_clone;
+
+ size += vaddr & (SZ_1M - 1);
+ size = ALIGN(size, SZ_1M);
+
+ while ((long)size > 0) {
+ lv1d = pgd + (vaddr >> LV1_SHIFT);
+
+ *lv1d = (paddr & 0xfff00000) | PT_NS | PT_AP | PT_ENTRY;
+
+ vaddr += SZ_1M;
+ paddr += SZ_1M;
+ size -= SZ_1M;
+ }
+ return PT_NORMAL;
+}
+
+void fimg2d_mmutable_value_replace(struct fimg2d_bltcmd *cmd,
+ unsigned long fault_addr, unsigned long l2d_value)
+{
+ unsigned long *pgd;
+ unsigned long *lv1d, *lv2d;
+
+ pgd = (unsigned long *)cmd->ctx->mm->pgd;
+ lv1d = pgd + (fault_addr >> LV1_SHIFT);
+
+ lv2d = (unsigned long *)phys_to_virt(*lv1d & ~LV2_BASE_MASK) +
+ ((fault_addr & LV2_PT_MASK) >> LV2_SHIFT);
+
+ *lv2d = l2d_value;
+
+ flush_all_cpu_caches();
+ fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4);
+
+ printk(KERN_INFO "MMU Level2 value replaced [0x%lx]", l2d_value);
+}
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.h b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.h
index f337ea5..7699a37 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.h
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_cache.h
@@ -18,6 +18,10 @@
#define L1_CACHE_SIZE SZ_64K
#define L2_CACHE_SIZE SZ_1M
#define LINE_FLUSH_THRESHOLD SZ_1K
+#define L1_DESCRIPTOR_SIZE SZ_16K
+
+/* Get Modified virtual address to use 1MB page */
+#define GET_MVA(V, P) ((V & 0xfff00000) | (P & 0x000fffff))
/**
* cache_opr - [kernel] cache operation mode
@@ -92,5 +96,11 @@ static inline void fimg2d_dma_unsync_inner(unsigned long addr, size_t size, int
}
void fimg2d_clean_outer_pagetable(struct mm_struct *mm, unsigned long addr, size_t size);
+void fimg2d_clean_outer_pagetable_clone(unsigned long *pgd_clone, unsigned long addr, size_t size);
+void fimg2d_clean_inner_pagetable_clone(unsigned long *pgd_clone, unsigned long addr, size_t size);
void fimg2d_dma_sync_outer(struct mm_struct *mm, unsigned long addr, size_t size, enum cache_opr opr);
enum pt_status fimg2d_check_pagetable(struct mm_struct *mm, unsigned long addr, size_t size);
+enum pt_status fimg2d_migrate_pagetable(unsigned long *pgd_clone,
+ unsigned long vaddr, unsigned long paddr, size_t size);
+void fimg2d_mmutable_value_replace(struct fimg2d_bltcmd *cmd,
+ unsigned long fault_addr, unsigned long l2d_value);
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
index eaa722c..0c6c590 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
@@ -130,6 +130,7 @@ static int fimg2d_check_dma_sync(struct fimg2d_bltcmd *cmd)
enum pt_status pt;
int clip_x, clip_w, clip_h, y, dir, i;
unsigned long clip_start;
+ unsigned long modified_addr;
clp = &p->clipping;
@@ -155,6 +156,13 @@ static int fimg2d_check_dma_sync(struct fimg2d_bltcmd *cmd)
pt = fimg2d_check_pagetable(mm, c->addr, c->size);
if (pt == PT_FAULT)
return -1;
+ } else if (img->addr.type == ADDR_USER_CONTIG) {
+ modified_addr = GET_MVA(img->addr.start, img->plane2.start);
+ pt = fimg2d_migrate_pagetable(cmd->ctx->pgd_clone,
+ modified_addr, img->plane2.start, img->height * img->stride);
+ if (pt != PT_NORMAL) {
+ return -1;
+ }
}
if (img->need_cacheopr && i != IMAGE_TMP) {
@@ -175,7 +183,25 @@ static int fimg2d_check_dma_sync(struct fimg2d_bltcmd *cmd)
c = &cmd->dma[i];
r = &img->rect;
- if (!img->addr.type || !c->cached)
+ if (!img->addr.type)
+ continue;
+
+ if ((cmd->image[IMAGE_SRC].addr.type == ADDR_USER_CONTIG) ||
+ (cmd->image[IMAGE_DST].addr.type == ADDR_USER_CONTIG)) {
+ if (img->addr.type == ADDR_USER_CONTIG) {
+ if (i == IMAGE_DST && clp->enable)
+ modified_addr = GET_MVA(img->addr.start, img->plane2.start) +
+ (img->stride * clp->y1);
+ else
+ modified_addr = GET_MVA(img->addr.start, img->plane2.start) +
+ (img->stride * r->y1);
+ } else {
+ modified_addr = c->addr;
+ }
+ fimg2d_clean_inner_pagetable_clone(cmd->ctx->pgd_clone, modified_addr, c->size);
+ }
+
+ if ( !c->cached)
continue;
if (i == IMAGE_DST)
@@ -226,8 +252,22 @@ static int fimg2d_check_dma_sync(struct fimg2d_bltcmd *cmd)
continue;
/* clean pagetable */
- if (img->addr.type == ADDR_USER)
+ if ((cmd->image[IMAGE_SRC].addr.type == ADDR_USER_CONTIG) ||
+ (cmd->image[IMAGE_DST].addr.type == ADDR_USER_CONTIG)) {
+ if (img->addr.type == ADDR_USER_CONTIG) {
+ if (i == IMAGE_DST && clp->enable)
+ modified_addr = GET_MVA(img->addr.start, img->plane2.start) +
+ (img->stride * clp->y1);
+ else
+ modified_addr = GET_MVA(img->addr.start, img->plane2.start) +
+ (img->stride * r->y1);
+ } else {
+ modified_addr = c->addr;
+ }
+ fimg2d_clean_outer_pagetable_clone(cmd->ctx->pgd_clone, modified_addr, c->size);
+ } else {
fimg2d_clean_outer_pagetable(mm, c->addr, c->size);
+ }
if (!c->cached)
continue;
@@ -275,14 +315,17 @@ int fimg2d_add_command(struct fimg2d_control *info, struct fimg2d_context *ctx,
int i, ret;
struct fimg2d_image *buf[MAX_IMAGES] = image_table(blit);
struct fimg2d_bltcmd *cmd;
+ struct fimg2d_image *img;
- if ((blit->dst) && (type == ADDR_USER))
+ if ((blit->dst) && (type == ADDR_USER)
+ && (blit->seq_no == SEQ_NO_BLT_SKIA))
up_write(&page_alloc_slow_rwsem);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) {
- if ((blit->dst) && (type == ADDR_USER))
+ if ((blit->dst) && (type == ADDR_USER)
+ && (blit->seq_no == SEQ_NO_BLT_SKIA))
if (!down_write_trylock(&page_alloc_slow_rwsem))
return -EAGAIN;
return -ENOMEM;
@@ -294,7 +337,8 @@ int fimg2d_add_command(struct fimg2d_control *info, struct fimg2d_context *ctx,
if (copy_from_user(&cmd->image[i], buf[i],
sizeof(struct fimg2d_image))) {
- if ((blit->dst) && (type == ADDR_USER))
+ if ((blit->dst) && (type == ADDR_USER)
+ && (blit->seq_no == SEQ_NO_BLT_SKIA))
if (!down_write_trylock(&page_alloc_slow_rwsem)) {
ret = -EAGAIN;
goto err_user;
@@ -304,7 +348,8 @@ int fimg2d_add_command(struct fimg2d_control *info, struct fimg2d_context *ctx,
}
}
- if ((blit->dst) && (type == ADDR_USER))
+ if ((blit->dst) && (type == ADDR_USER)
+ && (blit->seq_no == SEQ_NO_BLT_SKIA))
if (!down_write_trylock(&page_alloc_slow_rwsem)) {
ret = -EAGAIN;
goto err_user;
@@ -329,6 +374,13 @@ int fimg2d_add_command(struct fimg2d_control *info, struct fimg2d_context *ctx,
fimg2d_fixup_params(cmd);
+ for (i = 0; i < MAX_IMAGES; i++) {
+ img = &cmd->image[i];
+ if (img->addr.type == ADDR_USER_CONTIG) {
+ memcpy(cmd->ctx->pgd_clone, cmd->ctx->mm->pgd, L1_DESCRIPTOR_SIZE);
+ }
+ }
+
if (fimg2d_check_dma_sync(cmd)) {
ret = -EFAULT;
goto err_user;
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c
index ed14901..84c7db5 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c
@@ -46,6 +46,8 @@
#define LV2_PT_MASK 0xff000
#define LV2_SHIFT 12
#define LV1_DESC_MASK 0x3
+#define LV2_VALUE_META 0xc7f
+#define LV2_VALUE_BASE_MASK 0xfff
static struct fimg2d_control *info;
@@ -116,7 +118,12 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
lv2d = (unsigned long *)phys_to_virt(*lv1d & ~LV2_BASE_MASK) +
((fault_addr & LV2_PT_MASK) >> LV2_SHIFT);
printk(KERN_ERR " Level 2 descriptor(0x%lx)\n", *lv2d);
- fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4);
+ if (*lv2d == 0) {
+ fimg2d_mmutable_value_replace(cmd, fault_addr,
+ (info->dbuffer_addr & ~LV2_VALUE_BASE_MASK) | LV2_VALUE_META);
+ info->fault_addr = fault_addr;
+ } else
+ fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4);
next:
return 0;
@@ -161,6 +168,8 @@ static int fimg2d_open(struct inode *inode, struct file *file)
ctx, (unsigned long *)ctx->mm->pgd,
(unsigned long *)init_mm.pgd);
+ ctx->pgd_clone = kzalloc(L1_DESCRIPTOR_SIZE, GFP_KERNEL);
+
fimg2d_add_context(info, ctx);
return 0;
}
@@ -178,6 +187,7 @@ static int fimg2d_release(struct inode *inode, struct file *file)
}
fimg2d_del_context(info, ctx);
+ kfree(ctx->pgd_clone);
kfree(ctx);
return 0;
}
@@ -223,7 +233,8 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dev_lock(info->bus_dev, info->dev, 160160);
#endif
#endif
- if ((blit.dst) && (dst.addr.type == ADDR_USER))
+ if ((blit.dst) && (dst.addr.type == ADDR_USER)
+ && (blit.seq_no == SEQ_NO_BLT_SKIA))
if (!down_write_trylock(&page_alloc_slow_rwsem))
ret = -EAGAIN;
@@ -238,7 +249,9 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
perf_print(ctx, blit.seq_no);
perf_clear(ctx);
#endif
- if ((blit.dst) && (dst.addr.type == ADDR_USER) && ret != -EAGAIN)
+ if ((blit.dst) && (dst.addr.type == ADDR_USER)
+ && (blit.seq_no == SEQ_NO_BLT_SKIA)
+ && ret != -EAGAIN)
up_write(&page_alloc_slow_rwsem);
#ifdef CONFIG_BUSFREQ_OPP
@@ -246,6 +259,13 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dev_unlock(info->bus_dev, info->dev);
#endif
#endif
+
+ if (info->fault_addr) {
+ printk(KERN_INFO "Return by G2D fault handler");
+ info->fault_addr = 0;
+ ret = -EFAULT;
+ }
+
break;
case FIMG2D_BITBLT_SYNC:
@@ -281,6 +301,17 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
+ case FIMG2D_BITBLT_DBUFFER:
+ if (copy_from_user(&info->dbuffer_addr,
+ (unsigned long *)arg,
+ sizeof(unsigned long))) {
+ printk(KERN_ERR
+ "[%s] failed to FIMG2D_BITBLT_DBUFFER: copy_from_user error\n\n",
+ __func__);
+ return -EFAULT;
+ }
+ break;
+
default:
printk(KERN_ERR "[%s] unknown ioctl\n", __func__);
ret = -EFAULT;
@@ -315,6 +346,7 @@ static int fimg2d_setup_controller(struct fimg2d_control *info)
atomic_set(&info->nctx, 0);
atomic_set(&info->active, 0);
info->secure = 0;
+ info->fault_addr = 0;
spin_lock_init(&info->bltlock);
@@ -384,12 +416,20 @@ static int fimg2d_probe(struct platform_device *pdev)
fimg2d_debug("device name: %s base address: 0x%lx\n",
pdev->name, (unsigned long)res->start);
+ /* Clock setup */
+ ret = fimg2d_clk_setup(info);
+ if (ret) {
+ printk(KERN_ERR "FIMG2D failed to setup clk\n");
+ ret = -ENOENT;
+ goto err_clk;
+ }
+
/* irq */
info->irq = platform_get_irq(pdev, 0);
if (!info->irq) {
printk(KERN_ERR "FIMG2D failed to get irq resource\n");
ret = -ENOENT;
- goto err_map;
+ goto err_irq;
}
fimg2d_debug("irq: %d\n", info->irq);
@@ -400,13 +440,6 @@ static int fimg2d_probe(struct platform_device *pdev)
goto err_irq;
}
- ret = fimg2d_clk_setup(info);
- if (ret) {
- printk(KERN_ERR "FIMG2D failed to setup clk\n");
- ret = -ENOENT;
- goto err_clk;
- }
-
#ifdef CONFIG_PM_RUNTIME
pm_runtime_enable(info->dev);
fimg2d_debug("enable runtime pm\n");
@@ -432,19 +465,20 @@ static int fimg2d_probe(struct platform_device *pdev)
return 0;
err_reg:
- fimg2d_clk_release(info);
-
-err_clk:
free_irq(info->irq, NULL);
err_irq:
+ fimg2d_clk_release(info);
+
+err_clk:
iounmap(info->regs);
err_map:
+ release_mem_region(res->start, resource_size(res));
kfree(info->mem);
err_region:
- release_resource(info->mem);
+ release_resource(res);
err_res:
destroy_workqueue(info->work_q);
diff --git a/drivers/media/video/samsung/jpeg_v2x/jpeg_conf.h b/drivers/media/video/samsung/jpeg_v2x/jpeg_conf.h
index 6fcc276..086c20a 100644
--- a/drivers/media/video/samsung/jpeg_v2x/jpeg_conf.h
+++ b/drivers/media/video/samsung/jpeg_v2x/jpeg_conf.h
@@ -15,27 +15,37 @@
/* Q-table for JPEG */
/* ITU standard Q-table */
-const unsigned int ITU_Q_tbl[4][16] = {
+const unsigned int ITU_Q_tbl[6][16] = {
{
- 0x01010101, 0x01020303, 0x01010101, 0x01030303, /* Y */
- 0x01010101, 0x02030303, 0x01010101, 0x03040403,
- 0x01010203, 0x03050504, 0x01020303, 0x04050605,
- 0x02030404, 0x05060605, 0x04050505, 0x06050505
+ 0x06030303, 0x07070706, 0x03030303, 0x08080804, /* Y QF:97 */
+ 0x01010101, 0x03040303, 0x03010101, 0x04050503,
+ 0x03030101, 0x05060704, 0x04030301, 0x06070605,
+ 0x05050403, 0x06070706, 0x06060604, 0x06070707
} , {
- 0x01010102, 0x05050505, 0x01010103, 0x05050505, /* CbCr */
- 0x01010503, 0x05050505, 0x02030505, 0x05050505,
- 0x05050505, 0x05050505, 0x05050505, 0x05050505,
- 0x05050505, 0x05050505, 0x05050505, 0x05050505
+ 0x06030303, 0x07070706, 0x04030303, 0x08080806, /* CbCr QF:97 */
+ 0x06030301, 0x06060606, 0x06060403, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606,
+ 0x06060606, 0x06060606, 0x06060606, 0x06060606
} , {
- 0x05020205, 0x0a161e25, 0x02020307, 0x0c232521, /* Y */
- 0x0302050a, 0x16222b22, 0x0305090e, 0x1e393326,
- 0x06091422, 0x2a384431, 0x0a122118, 0x34454b3c,
- 0x1d283238, 0x44525142, 0x2d3c3e40, 0x4a424441
+ 0x06030303, 0x0a080706, 0x03030303, 0x090a0904, /* Y QF:92 */
+ 0x04030303, 0x090b0906, 0x05040303, 0x0a0d0e08,
+ 0x09060403, 0x0c10110d, 0x0a090604, 0x0f12110d,
+ 0x0e0c0a08, 0x10131310, 0x100f0f0c, 0x10101012
} , {
- 0x05020205, 0x251e160a, 0x07030202, 0x2125230c, /* CbCr */
- 0x0a050203, 0x222b2216, 0x0e090503, 0x2633391e,
- 0x22140906, 0x3144382a, 0x1821120a, 0x3c4b4534,
- 0x3832281d, 0x42515244, 0x403e3c2d, 0x4144424a
+ 0x08040303, 0x10101010, 0x0b040303, 0x10101010, /* CbCr QF:92 */
+ 0x10090404, 0x10101010, 0x10100b08, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010
+ } , {
+ 0x06030304, 0x0e0c0a06, 0x05030303, 0x0d0e0e06, /* Y QF:88 */
+ 0x06040303, 0x0d110e0a, 0x07050403, 0x0f13150c,
+ 0x0d090504, 0x12191a10, 0x0f0d0806, 0x161b1913,
+ 0x15130f0c, 0x181d1d19, 0x18171611, 0x1819181b
+ } , {
+ 0x0b060404, 0x18181818, 0x10060504, 0x18181818, /* CbCr QF:88 */
+ 0x180d0606, 0x18181818, 0x1818100b, 0x18181818,
+ 0x18181818, 0x18181818, 0x18181818, 0x18181818,
+ 0x18181818, 0x18181818, 0x18181818, 0x18181818
}
};
diff --git a/drivers/media/video/samsung/jpeg_v2x/jpeg_dev.c b/drivers/media/video/samsung/jpeg_v2x/jpeg_dev.c
index 1e6b085..eb026ab 100644
--- a/drivers/media/video/samsung/jpeg_v2x/jpeg_dev.c
+++ b/drivers/media/video/samsung/jpeg_v2x/jpeg_dev.c
@@ -504,7 +504,7 @@ static void jpeg_device_enc_run(void *priv)
jpeg_sw_reset(dev->reg_base);
jpeg_set_interrupt(dev->reg_base);
jpeg_set_huf_table_enable(dev->reg_base, 1);
- jpeg_set_enc_tbl(dev->reg_base);
+ jpeg_set_enc_tbl(dev->reg_base, enc_param.quality);
jpeg_set_encode_tbl_select(dev->reg_base, enc_param.quality);
jpeg_set_stream_size(dev->reg_base,
enc_param.in_width, enc_param.in_height);
@@ -893,12 +893,16 @@ static int jpeg_probe(struct platform_device *pdev)
#endif
#ifdef CONFIG_JPEG_V2_1
- dev->watchdog_workqueue = create_singlethread_workqueue(JPEG_NAME);
- INIT_WORK(&dev->watchdog_work, jpeg_watchdog_worker);
- atomic_set(&dev->watchdog_cnt, 0);
- init_timer(&dev->watchdog_timer);
- dev->watchdog_timer.data = (unsigned long)dev;
- dev->watchdog_timer.function = jpeg_watchdog;
+ dev->watchdog_workqueue = create_singlethread_workqueue(JPEG_NAME);
+ if (!dev->watchdog_workqueue) {
+ ret = -ENOMEM;
+ goto err_video_reg;
+ }
+ INIT_WORK(&dev->watchdog_work, jpeg_watchdog_worker);
+ atomic_set(&dev->watchdog_cnt, 0);
+ init_timer(&dev->watchdog_timer);
+ dev->watchdog_timer.data = (unsigned long)dev;
+ dev->watchdog_timer.function = jpeg_watchdog;
#endif
/* clock disable */
clk_disable(dev->clk);
@@ -1043,7 +1047,8 @@ static int jpeg_runtime_suspend(struct device *dev)
struct jpeg_dev *jpeg_drv = platform_get_drvdata(pdev);
#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
/* lock bus frequency */
- dev_unlock(jpeg_drv->bus_dev, dev);
+ if (samsung_rev() < EXYNOS4412_REV_2_0)
+ dev_unlock(jpeg_drv->bus_dev, dev);
#endif
jpeg_drv->vb2->suspend(jpeg_drv->alloc_ctx);
/* clock disable */
@@ -1057,7 +1062,9 @@ static int jpeg_runtime_resume(struct device *dev)
struct jpeg_dev *jpeg_drv = platform_get_drvdata(pdev);
#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
/* lock bus frequency */
- dev_lock(jpeg_drv->bus_dev, &jpeg_drv->plat_dev->dev, BUSFREQ_400MHZ);
+ if (samsung_rev() < EXYNOS4412_REV_2_0)
+ dev_lock(jpeg_drv->bus_dev,
+ &jpeg_drv->plat_dev->dev, BUSFREQ_400MHZ);
#endif
clk_enable(jpeg_drv->clk);
jpeg_drv->vb2->resume(jpeg_drv->alloc_ctx);
@@ -1104,9 +1111,7 @@ static int __init jpeg_init(void)
{
printk(KERN_CRIT "Initialize JPEG driver\n");
- platform_driver_register(&jpeg_driver);
-
- return 0;
+ return platform_driver_register(&jpeg_driver);
}
static void __exit jpeg_exit(void)
diff --git a/drivers/media/video/samsung/jpeg_v2x/jpeg_mem.h b/drivers/media/video/samsung/jpeg_v2x/jpeg_mem.h
index d912628..9336bb8 100644
--- a/drivers/media/video/samsung/jpeg_v2x/jpeg_mem.h
+++ b/drivers/media/video/samsung/jpeg_v2x/jpeg_mem.h
@@ -33,7 +33,12 @@ extern const struct jpeg_vb2 jpeg_vb2_cma;
extern const struct jpeg_vb2 jpeg_vb2_ion;
#endif
+#if defined(CONFIG_MACH_GC1)
+#define MAX_JPEG_WIDTH 4608
+#define MAX_JPEG_HEIGHT 3456
+#else
#define MAX_JPEG_WIDTH 3264
#define MAX_JPEG_HEIGHT 2448
+#endif
#endif /* __JPEG_MEM_H__ */
diff --git a/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.c b/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.c
index e3300cc..0c9bc4b 100644
--- a/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.c
+++ b/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.c
@@ -341,28 +341,99 @@ void jpeg_set_enc_out_fmt(void __iomem *base,
writel(reg, base + S5P_JPEG_IMG_FMT_REG);
}
-void jpeg_set_enc_tbl(void __iomem *base)
+void jpeg_set_enc_tbl(void __iomem *base,
+ enum jpeg_img_quality_level level)
{
int i;
- for (i = 0; i < 16; i++) {
- writel((unsigned int)ITU_Q_tbl[0][i],
- base + S5P_JPEG_QUAN_TBL_ENTRY_REG + (i*0x04));
- }
+ switch (level) {
+ case QUALITY_LEVEL_1:
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[0][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + (i*0x04));
+ }
- for (i = 0; i < 16; i++) {
- writel((unsigned int)ITU_Q_tbl[1][i],
- base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x40 + (i*0x04));
- }
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[1][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x40 + (i*0x04));
+ }
- for (i = 0; i < 16; i++) {
- writel((unsigned int)ITU_Q_tbl[2][i],
- base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x80 + (i*0x04));
- }
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[0][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x80 + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[1][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0xc0 + (i*0x04));
+ }
+ break;
+
+ case QUALITY_LEVEL_2:
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[2][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[3][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x40 + (i*0x04));
+ }
- for (i = 0; i < 16; i++) {
- writel((unsigned int)ITU_Q_tbl[3][i],
- base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0xc0 + (i*0x04));
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[2][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x80 + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[3][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0xc0 + (i*0x04));
+ }
+ break;
+
+ case QUALITY_LEVEL_3:
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[4][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[5][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x40 + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[4][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x80 + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[5][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0xc0 + (i*0x04));
+ }
+ break;
+
+ default:
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[0][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[1][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x40 + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[0][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0x80 + (i*0x04));
+ }
+
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)ITU_Q_tbl[1][i],
+ base + S5P_JPEG_QUAN_TBL_ENTRY_REG + 0xc0 + (i*0x04));
+ }
+ break;
}
for (i = 0; i < 4; i++) {
diff --git a/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.h b/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.h
index 535a3f9..1dee4b2 100644
--- a/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.h
+++ b/drivers/media/video/samsung/jpeg_v2x/jpeg_regs.h
@@ -23,7 +23,7 @@ void jpeg_set_enc_in_fmt(void __iomem *base,
enum jpeg_frame_format in_fmt);
void jpeg_set_enc_out_fmt(void __iomem *base,
enum jpeg_stream_format out_fmt);
-void jpeg_set_enc_tbl(void __iomem *base);
+void jpeg_set_enc_tbl(void __iomem *base, enum jpeg_img_quality_level level);
void jpeg_set_interrupt(void __iomem *base);
void jpeg_clean_interrupt(void __iomem *base);
unsigned int jpeg_get_int_status(void __iomem *base);
diff --git a/drivers/media/video/samsung/mali/Kconfig b/drivers/media/video/samsung/mali/Kconfig
index b93bccf..ae9bd7d 100644
--- a/drivers/media/video/samsung/mali/Kconfig
+++ b/drivers/media/video/samsung/mali/Kconfig
@@ -6,7 +6,7 @@
config VIDEO_MALI400MP
bool "Enable MALI integration"
depends on VIDEO_SAMSUNG
- default n
+ default y
---help---
This enables MALI integration in the multimedia device driver
@@ -39,7 +39,6 @@ int "Dedicated Memory Size"
---help---
This value is dedicated memory size of Mali GPU(unit is MByte).
-
# For DEBUG
config VIDEO_MALI400MP_DEBUG
bool "Enables debug messages"
@@ -48,13 +47,6 @@ config VIDEO_MALI400MP_DEBUG
help
This enables Mali driver debug messages.
-config VIDEO_MALI400MP_STREAMLINE_PROFILING
- bool "Enables mali streamline profiling"
- depends on VIDEO_MALI400MP
- default n
- help
- This enables Mali streamline profiling.
-
config VIDEO_MALI400MP_DVFS
bool "Enables DVFS"
depends on VIDEO_MALI400MP && PM
diff --git a/drivers/media/video/samsung/mali/Makefile b/drivers/media/video/samsung/mali/Makefile
index 0ce60a3..db5ce6a 100644
--- a/drivers/media/video/samsung/mali/Makefile
+++ b/drivers/media/video/samsung/mali/Makefile
@@ -10,7 +10,7 @@
OSKOS :=linux
FILES_PREFIX=
-MALI_FILE_PREFIX := drivers/media/video/samsung/mali
+MALI_INCLUDE_PREFIX := drivers/media/video/samsung/mali/
KBUILDROOT =
ifeq ($(CONFIG_MALI_DED_ONLY),y)
@@ -54,12 +54,8 @@ ifeq ($(CONFIG_VIDEO_MALI400MP_DEBUG),y)
BUILD=debug
endif
-ifeq ($(CONFIG_VIDEO_MALI400MP_STREAMLINE_PROFILING),y)
-USING_PROFILING=1
-USING_TRACEPOINTS=1
-endif
-
# set up defaults if not defined by the user
+USE_UMPV2 ?= 0
PANIC_ON_WATCHDOG_TIMEOUT ?= 1
USING_MALI400 ?= 1
USING_MMU ?= 1
@@ -75,21 +71,47 @@ USING_MALI_PMU ?= 0
USING_GPU_UTILIZATION ?= 0
OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 6
USING_PROFILING ?= 0
+USING_INTERNAL_PROFILING ?= 0
USING_TRACEPOINTS ?= 0
USING_MALI_MAJOR_PREDEFINE = 1
-USING_MALI_DVFS_ENABLED ?= 0
+USING_MALI_DVFS_ENABLED ?= 1
TIMESTAMP ?= default
BUILD ?= release
USING_MALI_PMM_EARLYSUSPEND ?= 0
#USING_KERNEL_WITH_DMA_ALLOC_PHYS_PAGE ?= 0
-CONFIG_MALI_MEM_SIZE ?= 64
+CONFIG_MALI_MEM_SIZE ?= 512
+DISABLE_PP0 ?= 0
+DISABLE_PP1 ?= 0
+DISABLE_PP2 ?= 0
+DISABLE_PP3 ?= 0
+MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0
+MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0
+MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0
+
+# Get path to driver source from Linux build system
+ifeq ($(USING_PROFILING),1)
+ifeq ($(USING_INTERNAL_PROFILING),0)
+ifndef CONFIG_TRACEPOINTS
+# Should default to gator profiling, but we dont have the kernel feature required, so disable profiling
+USING_PROFILING = 0
+endif
+endif
+endif
+
+ifeq ($(USING_PROFILING),0)
+# make sure user hasnt selected incompatible flags
+USING_INTERNAL_PROFILING = 0
+endif
+
+USING_MALI_SLP_GLOBAL_LOCK ?= 0
#config validtion check
ifeq ($(USING_OS_MEMORY),1)
USING_MMU = 1
endif
+
# Check if a Mali Core sub module should be enabled, true or false returned
-#submodule_enabled = $(shell gcc $(DEFINES) -E $(MALI_FILE_PREFIX)/arch/config.h | grep type | grep -c $(2))
+#submodule_enabled = $(shell gcc $(DEFINES) -E $(FILES_PREFIX)/arch/config.h | grep type | grep -c $(2))
# Inside the kernel build system
@@ -111,14 +133,21 @@ DEFINES += -DMALI_GPU_UTILIZATION=$(USING_GPU_UTILIZATION)
DEFINES += -DCONFIG_MALI_MEM_SIZE=$(CONFIG_MALI_MEM_SIZE)
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_MAJOR_PREDEFINE=$(USING_MALI_MAJOR_PREDEFINE)
DEFINES += -DMALI_DVFS_ENABLED=$(USING_MALI_DVFS_ENABLED)
DEFINES += -DUSING_MALI_PMM_EARLYSUSPEND=$(USING_MALI_PMM_EARLYSUSPEND)
-DEFINES += -DMALI_STATE_TRACKING=1
+DEFINES += -DMALI_STATE_TRACKING=0
DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB)
DEFINES += -DMALI_TRACEPOINTS_ENABLED=$(USING_TRACEPOINTS)
-DEFINES += -DMALI_REBOOTNOTIFIER
+DEFINES += -DDISABLE_PP0=$(DISABLE_PP0)
+DEFINES += -DDISABLE_PP1=$(DISABLE_PP1)
+DEFINES += -DDISABLE_PP2=$(DISABLE_PP2)
+DEFINES += -DDISABLE_PP3=$(DISABLE_PP3)
+DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP)
+DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED)
+DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS)
ifeq ($(BUILD),debug)
DEFINES += -DDEBUG
@@ -130,7 +159,7 @@ DEFINES += -DMALI_UKK_HAS_IMPLICIT_MMAP_CLEANUP
# UMP
ifeq ($(CONFIG_VIDEO_UMP),y)
DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=1 -DHAVE_UNLOCKED_IOCTL
- EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/../ump/include
+ EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)../ump/include
else
DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER=0
endif
@@ -141,17 +170,23 @@ obj-$(CONFIG_VIDEO_MALI400MP) += mali.o
# Use our defines when compiling
# MALI
INCLUDES = \
- -I$(MALI_FILE_PREFIX)\
- -I$(MALI_FILE_PREFIX)/platform\
- -I$(MALI_FILE_PREFIX)/common \
- -I$(MALI_FILE_PREFIX)/linux
+ -I$(MALI_INCLUDE_PREFIX)\
+ -I$(MALI_INCLUDE_PREFIX)include \
+ -I$(MALI_INCLUDE_PREFIX)platform\
+ -I$(MALI_INCLUDE_PREFIX)common \
+ -I$(MALI_INCLUDE_PREFIX)linux \
+ -I$(MALI_INCLUDE_PREFIX)regs
+
+ifeq ($(USING_PROFILING),1)
+INCLUDES += \
+ -I$(MALI_INCLUDE_PREFIX)include
+endif
EXTRA_CFLAGS += $(INCLUDES)\
$(DEFINES)
-
-EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/linux/license/gpl
-EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/common/pmm
+EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)linux/license/gpl
+EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)common/pmm
# Source files which always are included in a build
ifeq ($(CONFIG_VIDEO_UMP),y)
@@ -178,11 +213,12 @@ OSKFILES=\
endif #($(CONFIG_VIDEO_UMP),y)
ifeq ($(CONFIG_CPU_EXYNOS4210),y)
- MALI_PLATFORM_FILE = platform/orion-m400/mali_platform.o
+ MALI_PLATFORM_DIR = platform/orion-m400
else
- MALI_PLATFORM_FILE = platform/pegasus-m400/mali_platform.o
+ MALI_PLATFORM_DIR = platform/pegasus-m400
endif #($(CONFIG_CPU_EXYNOS4210),y)
+MALI_PLATFORM_FILE=$(MALI_PLATFORM_DIR)/mali_platform.o
UKKFILES=\
$(FILES_PREFIX)$(OSKOS)/mali_ukk_mem.o \
$(FILES_PREFIX)$(OSKOS)/mali_ukk_gp.o \
@@ -190,85 +226,94 @@ UKKFILES=\
$(FILES_PREFIX)$(OSKOS)/mali_ukk_core.o \
$(FILES_PREFIX)$(OSKOS)/mali_ukk_vsync.o
-mali-y := \
- $(KBUILDROOT)common/mali_kernel_core.o \
- $(KBUILDROOT)linux/mali_kernel_linux.o \
- $(KBUILDROOT)linux/mali_osk_indir_mmap.o \
- $(KBUILDROOT)common/mali_kernel_rendercore.o \
- $(KBUILDROOT)common/mali_kernel_descriptor_mapping.o \
- $(KBUILDROOT)common/mali_kernel_vsync.o \
- $(KBUILDROOT)linux/mali_kernel_sysfs.o \
- $(KBUILDROOT)$(MALI_PLATFORM_FILE) \
- $(KBUILDROOT)$(OSKFILES) \
- $(KBUILDROOT)$(UKKFILES)
- #__malidrv_build_info.o
-
ifeq ($(USING_PROFILING),1)
-EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/timestamp-default
-EXTRA_CFLAGS += -I$(MALI_FILE_PREFIX)/profiling/include
-mali-y += \
- common/mali_kernel_profiling.o \
- timestamp-$(TIMESTAMP)/mali_timestamp.o \
- linux/mali_ukk_profiling.o
-
-EXTRA_CFLAGS += -I$(KBUILD_EXTMOD)/timestamp-$(TIMESTAMP)
+UKKFILES += \
+ $(FILES_PREFIX)$(OSKOS)/mali_ukk_profiling.o
endif
-ifeq ($(USING_TRACEPOINTS),1)
-mali-y += \
- linux/mali_osk_profiling.o
-endif
+mali-y := \
+ common/mali_kernel_core.o \
+ linux/mali_kernel_linux.o \
+ $(OSKOS)/mali_osk_indir_mmap.o \
+ common/mali_kernel_descriptor_mapping.o \
+ common/mali_session.o \
+ common/mali_device_pause_resume.o \
+ common/mali_kernel_vsync.o \
+ linux/mali_ukk_vsync.o \
+ linux/mali_kernel_sysfs.o \
+ common/mali_mmu.o \
+ common/mali_mmu_page_directory.o \
+ common/mali_memory.o \
+ common/mali_kernel_memory_engine.o \
+ common/mali_block_allocator.o \
+ common/mali_kernel_mem_os.o \
+ common/mali_mem_validation.o \
+ common/mali_hw_core.o \
+ common/mali_gp.o \
+ common/mali_pp.o \
+ common/mali_pp_job.o \
+ common/mali_gp_job.o \
+ common/mali_scheduler.o \
+ common/mali_gp_scheduler.o \
+ common/mali_pp_scheduler.o \
+ common/mali_cluster.o \
+ common/mali_group.o \
+ common/mali_dlbu.o \
+ common/mali_pm.o \
+ common/mali_pmu.o \
+ common/mali_user_settings_db.o \
+ $(OSKOS)/mali_osk_pm.o \
+ linux/mali_kernel_pm.o \
+ $(OSKOS)/mali_osk_wait_queue.o \
+ $(MALI_PLATFORM_FILE) \
+ $(OSKFILES) \
+ $(UKKFILES)
+# __malidrv_build_info.c
# 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
+ifeq ($(USING_INTERNAL_PROFILING),1)
+PROFILING_BACKEND_SOURCES = \
+ linux/mali_osk_profiling_internal.o \
+ timestamp-$(TIMESTAMP)/mali_timestamp.o
+EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)timestamp-$(TIMESTAMP)
+else
+ifeq ($(USING_PROFILING),1)
+PROFILING_BACKEND_SOURCES = \
+ linux/mali_osk_profiling_gator.o
endif
-ifeq ($(USING_MALI_PMU),1)
-mali-y += \
- common/pmm/mali_pmm_pmu.o
+endif
+
+# Add the profiling sources
+mali-y += $(PROFILING_BACKEND_SOURCES)
+
+# Mali-400 PP in use
+ifeq ($(USING_MALI_PMM_TESTSUITE),1)
+EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)platform/mali_pmu_testing
endif
ifeq ($(USING_GPU_UTILIZATION),1)
+EXTRA_CFLAGS += -DCONFIG_MALI400_GPU_UTILIZATION=1
+
mali-y += \
common/mali_kernel_utilization.o
endif
-# Mali-400 PP in use
-EXTRA_CFLAGS += -DUSING_MALI400
-mali-y += common/mali_kernel_MALI200.o
-
-# Mali-400 GP in use
-mali-y += common/mali_kernel_GP2.o
+ifeq ($(USING_MALI_DVFS_ENABLED),1)
+mali-y += $(MALI_PLATFORM_DIR)/mali_platform_dvfs.o
+endif #($(USING_MALI_DVFS_ENABLED),1)
-# 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
+EXTRA_CFLAGS += -DUSING_MALI400
# Mali Level2 cache in use
EXTRA_CFLAGS += -DUSING_MALI400_L2_CACHE
-mali-y += common/mali_kernel_l2_cache.o
-
-ifeq ($(USING_MALI_DVFS_ENABLED),1)
-ifeq ($(CONFIG_CPU_EXYNOS4210),y)
+mali-y += common/mali_l2_cache.o
+# Mali SLP Global lock feature
+ifeq ($(USING_MALI_SLP_GLOBAL_LOCK),1)
mali-y += \
- platform/orion-m400/mali_platform_dvfs.o
-else
-mali-y += \
- platform/pegasus-m400/mali_platform_dvfs.o
-endif #($(CONFIG_CPU_EXYNOS4210),y)
-endif #($(USING_MALI_DVFS_ENABLED),1)
+ linux/mali_slp_global_lock.o
+endif
+
ifeq ($(PANIC_ON_WATCHDOG_TIMEOUT),1)
EXTRA_CFLAGS += -DUSING_KERNEL_PANIC
diff --git a/drivers/media/video/samsung/mali/Makefile.common b/drivers/media/video/samsung/mali/Makefile.common
deleted file mode 100644
index 53d4e5b..0000000
--- a/drivers/media/video/samsung/mali/Makefile.common
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# 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.
-#
-
-# Check if a Mali Core sub module should be enabled, true or false returned
-submodule_enabled = $(shell gcc $(DEFINES) -E $1/arch/config.h | grep type | grep -c $(2))
-
-OSKFILES=\
- $(FILES_PREFIX)$(OSKOS)/mali_osk_atomics.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_irq.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_locks.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_low_level_mem.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_math.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_memory.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_misc.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_mali.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_notification.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_time.c \
- $(FILES_PREFIX)$(OSKOS)/mali_osk_timers.c
-
-UKKFILES=\
- $(FILES_PREFIX)$(OSKOS)/mali_ukk_mem.c \
- $(FILES_PREFIX)$(OSKOS)/mali_ukk_gp.c \
- $(FILES_PREFIX)$(OSKOS)/mali_ukk_pp.c \
- $(FILES_PREFIX)$(OSKOS)/mali_ukk_core.c
-
-ifeq ($(USING_PROFILING),1)
-UKKFILES+=\
- $(FILES_PREFIX)$(OSKOS)/mali_ukk_profiling.c
-endif
-
-ifeq ($(MALI_PLATFORM_FILE),)
-MALI_PLATFORM_FILE=platform/default/mali_platform.c
-endif
-
-# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available
-SVN_REV := $(shell (cd $(DRIVER_DIR); (svnversion | grep -qv exported && svnversion) || git svn info | grep '^Revision: '| sed -e 's/^Revision: //' ) 2>/dev/null )
-ifeq ($(SVN_REV),)
-SVN_REV := $(MALI_RELEASE_NAME)
-else
-SVN_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV)
-endif
-
-# Common version-string, will be extended by OS-specifc sections
-VERSION_STRINGS :=
-VERSION_STRINGS += CONFIG=$(CONFIG)
-VERSION_STRINGS += USING_OS_MEMORY=$(USING_OS_MEMORY)
-VERSION_STRINGS += API_VERSION=$(shell cd $(DRIVER_DIR); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)common\/mali_uk_types.h | cut -d' ' -f 3 )
-VERSION_STRINGS += REPO_URL=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'URL: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^URL: ' | cut -d: -f2- | cut -b2-)
-VERSION_STRINGS += REVISION=$(SVN_REV)
-VERSION_STRINGS += CHANGED_REVISION=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Rev: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-)
-VERSION_STRINGS += CHANGE_DATE=$(shell cd $(DRIVER_DIR); (svn info || git svn info || echo 'Last Changed Date: $(MALI_RELEASE_NAME)') 2>/dev/null | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-)
-VERSION_STRINGS += BUILD_DATE=$(shell date)
diff --git a/drivers/media/video/samsung/mali/Makefile_module b/drivers/media/video/samsung/mali/Makefile_module
new file mode 100644
index 0000000..4fb0226
--- /dev/null
+++ b/drivers/media/video/samsung/mali/Makefile_module
@@ -0,0 +1,89 @@
+#
+# 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
+
+# The Makefile sets up "arch" based on the CONFIG, creates the version info
+# string and the __malidrv_build_info.c file, and then call the Linux build
+# system to actually build the driver. After that point the Kbuild file takes
+# over.
+
+# set up defaults if not defined by the user
+ARCH ?= arm
+
+OSKOS=linux
+FILES_PREFIX=
+
+# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak
+-include ../../../arm_internal.mak
+
+# Check that required parameters are supplied.
+ifeq ($(CONFIG),)
+$(error "CONFIG must be specified.")
+endif
+ifeq ($(CPU)$(KDIR),)
+$(error "KDIR or CPU must be specified.")
+endif
+
+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 = $(realpath $(UMP_SYMVERS_FILE))
+$(warning $(KBUILD_EXTRA_SYMBOLS))
+endif
+
+# Get any user defined KDIR-<names> or maybe even a hardcoded KDIR
+-include KDIR_CONFIGURATION
+
+# Define host system directory
+KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build
+
+ifeq ($(ARCH), arm)
+ # when compiling for ARM we're cross compiling
+ export CROSS_COMPILE ?= arm-none-linux-gnueabi-
+endif
+
+# look up KDIR based om CPU selection
+KDIR ?= $(KDIR-$(CPU))
+
+# validate lookup result
+ifeq ($(KDIR),)
+$(error No KDIR found for platform $(CPU))
+endif
+
+# report detected/selected settings
+ifdef ARM_INTERNAL_BUILD
+$(warning Config $(CONFIG))
+$(warning Host CPU $(CPU))
+$(warning OS_MEMORY $(USING_OS_MEMORY))
+endif
+
+# Set up build config
+export CONFIG_MALI400=m
+
+ifeq ($(USING_GPU_UTILIZATION),1)
+export EXTRA_DEFINES += -DCONFIG_MALI400_GPU_UTILIZATION=1
+export CONFIG_MALI400_GPU_UTILIZATION := y
+endif
+
+all: $(UMP_SYMVERS_FILE)
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules
+ @rm $(FILES_PREFIX)__malidrv_build_info.c $(FILES_PREFIX)__malidrv_build_info.o
+
+clean:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
+
+kernelrelease:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease
+
+export CONFIG KBUILD_EXTRA_SYMBOLS
diff --git a/drivers/media/video/samsung/mali/arch b/drivers/media/video/samsung/mali/arch
deleted file mode 120000
index 6154ca4..0000000
--- a/drivers/media/video/samsung/mali/arch
+++ /dev/null
@@ -1 +0,0 @@
-arch-orion-m400 \ No newline at end of file
diff --git a/drivers/media/video/samsung/mali/arch-orion-m400/config.h b/drivers/media/video/samsung/mali/arch-debug/config.h
index 5c4d79d..d5196c3 100644
--- a/drivers/media/video/samsung/mali/arch-orion-m400/config.h
+++ b/drivers/media/video/samsung/mali/arch-debug/config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h
new file mode 100644
index 0000000..e579526
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m300/config.h
@@ -0,0 +1,85 @@
+/*
+ * 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 __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the PB platform with ZBT memory enabled */
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+ {
+ .type = PMU,
+ .description = "Mali-300 PMU",
+ .base = 0xC0002000,
+ .irq = -1,
+ .mmu_id = 0
+
+ },
+ {
+ .type = MALI300GP,
+ .description = "Mali-300 GP",
+ .base = 0xC0000000,
+ .irq = -1,
+ .mmu_id = 1
+ },
+ {
+ .type = MALI300PP,
+ .base = 0xc0008000,
+ .irq = -1,
+ .description = "Mali-300 PP",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = 0xC0003000,
+ .irq = -1,
+ .description = "Mali-300 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = 0xC0004000,
+ .irq = -1,
+ .description = "Mali-300 MMU for PP",
+ .mmu_id = 2
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xD0000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEM_VALIDATION,
+ .description = "Framebuffer",
+ .base = 0xe0000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE
+ },
+ {
+ .type = MALI300L2,
+ .base = 0xC0001000,
+ .description = "Mali-300 L2 cache"
+ },
+};
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h
new file mode 100644
index 0000000..3893d72
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-direct/config.h
@@ -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.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the PB platform with ZBT memory enabled */
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+
+ {
+ .type = PMU,
+ .description = "Mali-400 PMU",
+ .base = 0xC0002000,
+ .irq = -1,
+ .mmu_id = 0
+ },
+ {
+ .type = MALI400GP,
+ .description = "Mali-400 GP",
+ .base = 0xC0000000,
+ .irq = -1,
+ .mmu_id = 1
+ },
+ {
+ .type = MALI400PP,
+ .base = 0xc0008000,
+ .irq = -1,
+ .description = "Mali-400 PP",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = 0xC0003000,
+ .irq = -1,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = 0xC0004000,
+ .irq = -1,
+ .description = "Mali-400 MMU for PP",
+ .mmu_id = 2
+ },
+ {
+ .type = OS_MEMORY,
+ .description = "OS Memory",
+ .alloc_order = 10, /* Lowest preference for this memory */
+ .size = 96 * 1024 * 1024, /* 96 MB */
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = 0,
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0x80000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .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/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h
new file mode 100644
index 0000000..d85c090
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1-pmu/config.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the PB platform with ZBT memory enabled */
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+ {
+ .type = PMU,
+ .description = "Mali-400 PMU",
+ .base = 0xC0002000,
+ .irq = -1,
+ .mmu_id = 0
+
+ },
+ {
+ .type = MALI400GP,
+ .description = "Mali-400 GP",
+ .base = 0xC0000000,
+ .irq = -1,
+ .mmu_id = 1
+ },
+ {
+ .type = MALI400PP,
+ .base = 0xc0008000,
+ .irq = -1,
+ .description = "Mali-400 PP",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = 0xC0003000,
+ .irq = -1,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = 0xC0004000,
+ .irq = -1,
+ .description = "Mali-400 MMU for PP",
+ .mmu_id = 2
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xD0000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .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/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h
new file mode 100644
index 0000000..568ac0a
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-1/config.h
@@ -0,0 +1,77 @@
+/*
+ * 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 __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the PB platform with ZBT memory enabled */
+
+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",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = 0xC0003000,
+ .irq = -1,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = 0xC0004000,
+ .irq = -1,
+ .description = "Mali-400 MMU for PP",
+ .mmu_id = 2
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xD0000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .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/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.h
new file mode 100644
index 0000000..98b8059
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-2/config.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.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the PB platform with ZBT memory enabled */
+
+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 = MMU,
+ .base = 0xC0003000,
+ .irq = -1,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = 0xC0004000,
+ .irq = -1,
+ .description = "Mali-400 MMU for PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = 0xC0005000,
+ .irq = -1,
+ .description = "Mali-400 MMU for PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xD0000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .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/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h
new file mode 100644
index 0000000..7b10925
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-3/config.h
@@ -0,0 +1,105 @@
+/*
+ * 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 __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the PB platform with ZBT memory enabled */
+
+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 = 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 = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xD0000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .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/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h
new file mode 100644
index 0000000..a15a6bd
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pb-virtex5-m400-4/config.h
@@ -0,0 +1,119 @@
+/*
+ * 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 __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the EB platform with ZBT memory enabled */
+
+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
+ },
+ {
+ .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
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali SDRAM remapped to baseboard",
+ .cpu_usage_adjust = -0x50000000,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0xD0000000,
+ .size = 0x10000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEMORY,
+ .description = "Mali ZBT",
+ .alloc_order = 5, /* Medium preference for this memory */
+ .base = 0xe1000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .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/media/video/samsung/mali/arch-pegasus-m400/config.h b/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h
new file mode 100644
index 0000000..d5196c3
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-pegasus-m400/config.h
@@ -0,0 +1,154 @@
+/*
+ * 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 __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 0x40000000
+
+/*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 0x80000000 - MEM_MALI_SIZE
+
+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/drivers/media/video/samsung/mali/arch-release/config.h b/drivers/media/video/samsung/mali/arch-release/config.h
new file mode 100644
index 0000000..d5196c3
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-release/config.h
@@ -0,0 +1,154 @@
+/*
+ * 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 __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 0x40000000
+
+/*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 0x80000000 - MEM_MALI_SIZE
+
+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/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h b/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h
new file mode 100644
index 0000000..9b38f35
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch-ve-virtex6-m450-8/config.h
@@ -0,0 +1,168 @@
+/*
+ * 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 __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the Versatile Express platform */
+
+#define MALI_BASE_ADDRESS 0xFC040000
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+ /* GP cluster */
+ {
+ .type = MALI400L2,
+ .base = MALI_BASE_ADDRESS + 0x10000,
+ .description = "Mali-450 L2 cache for GP"
+ },
+ {
+ .type = MALI400GP,
+ .description = "Mali-450 GP",
+ .base = MALI_BASE_ADDRESS,
+ .irq = -1,
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x3000,
+ .irq = 70,
+ .description = "Mali-450 MMU for GP",
+ },
+
+ /* PP0-3 cluster */
+ {
+ .type = MALI400L2,
+ .base = MALI_BASE_ADDRESS + 0x1000,
+ .description = "Mali-450 L2 cache for PP0-3"
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0x8000,
+ .irq = 70,
+ .description = "Mali-450 PP0",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x4000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP0",
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0xA000,
+ .irq = 70,
+ .description = "Mali-450 PP1",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x5000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP1",
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0xC000,
+ .irq = 70,
+ .description = "Mali-450 PP2",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x6000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP2",
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0xE000,
+ .irq = 70,
+ .description = "Mali-450 PP3",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x7000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP3",
+ },
+
+ /* PP4-7 cluster */
+ {
+ .type = MALI400L2,
+ .base = MALI_BASE_ADDRESS + 0x11000,
+ .description = "Mali-450 L2 cache for PP4-7"
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0x28000,
+ .irq = 70,
+ .description = "Mali-450 PP4",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x1C000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP4",
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0x2A000,
+ .irq = 70,
+ .description = "Mali-450 PP5",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x1D000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP5",
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0x2C000,
+ .irq = 70,
+ .description = "Mali-450 PP6",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x1E000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP6",
+ },
+ {
+ .type = MALI400PP,
+ .base = MALI_BASE_ADDRESS + 0x2E000,
+ .irq = 70,
+ .description = "Mali-450 PP7",
+ },
+ {
+ .type = MMU,
+ .base = MALI_BASE_ADDRESS + 0x1F000,
+ .irq = 70,
+ .description = "Mali-450 MMU for PP7",
+ },
+
+ /* Memory */
+ {
+ .type = OS_MEMORY,
+ .description = "Mali OS memory",
+ .cpu_usage_adjust = 0,
+ .alloc_order = 0, /* Highest preference for this memory */
+ .base = 0x0,
+ .size = 256 * 1024 * 1024,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE |_MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+ {
+ .type = MEM_VALIDATION,
+ .description = "Framebuffer",
+ .base = 0xe0000000,
+ .size = 0x01000000,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_WRITEABLE | _MALI_PP_READABLE
+ },
+};
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/drivers/media/video/samsung/mali/arch/config.h b/drivers/media/video/samsung/mali/arch/config.h
new file mode 100644
index 0000000..d5196c3
--- /dev/null
+++ b/drivers/media/video/samsung/mali/arch/config.h
@@ -0,0 +1,154 @@
+/*
+ * 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 __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 0x40000000
+
+/*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 0x80000000 - MEM_MALI_SIZE
+
+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/drivers/media/video/samsung/mali/common/mali_block_allocator.c b/drivers/media/video/samsung/mali/common/mali_block_allocator.c
index 5f421f0..269e662 100644
--- a/drivers/media/video/samsung/mali/common/mali_block_allocator.c
+++ b/drivers/media/video/samsung/mali/common/mali_block_allocator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -76,7 +76,7 @@ mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u
info = _mali_osk_malloc(sizeof(block_allocator));
if (NULL != info)
{
- info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, 105);
+ info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO);
if (NULL != info->mutex)
{
info->all_blocks = _mali_osk_malloc(sizeof(block_info) * num_blocks);
@@ -355,7 +355,7 @@ static void block_allocator_release_page_table_block( mali_page_table_block *pag
_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. */
+ * Probably unnecessary for page table block releasing. */
while (block)
{
next = block->next;
diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.c b/drivers/media/video/samsung/mali/common/mali_cluster.c
new file mode 100644
index 0000000..f0fb2b6
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_cluster.c
@@ -0,0 +1,218 @@
+/*
+ * 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_cluster.h"
+#include "mali_osk.h"
+#include "mali_group.h"
+#include "mali_l2_cache.h"
+#include "mali_scheduler.h"
+
+static struct mali_cluster *mali_global_clusters[MALI_MAX_NUMBER_OF_CLUSTERS] = { NULL, NULL, NULL };
+static u32 mali_global_num_clusters = 0;
+
+/**
+ * The structure represents a render cluster
+ * A render cluster is defined by all the cores that share the same Mali L2 cache
+ */
+struct mali_cluster
+{
+ struct mali_l2_cache_core *l2;
+ u32 number_of_groups;
+ struct mali_group* groups[MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER];
+ u32 last_invalidated_id;
+ mali_bool power_is_enabled;
+};
+
+struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache)
+{
+ struct mali_cluster *cluster = NULL;
+
+ if (mali_global_num_clusters >= MALI_MAX_NUMBER_OF_CLUSTERS)
+ {
+ MALI_PRINT_ERROR(("Mali cluster: Too many cluster objects created\n"));
+ return NULL;
+ }
+
+ cluster = _mali_osk_malloc(sizeof(struct mali_cluster));
+ if (NULL != cluster)
+ {
+ _mali_osk_memset(cluster, 0, sizeof(struct mali_cluster));
+ cluster->l2 = l2_cache; /* This cluster now owns this L2 cache object */
+ cluster->last_invalidated_id = 0;
+ cluster->power_is_enabled = MALI_TRUE;
+
+ mali_global_clusters[mali_global_num_clusters] = cluster;
+ mali_global_num_clusters++;
+
+ return cluster;
+ }
+
+ return NULL;
+}
+
+void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled)
+{
+ cluster->power_is_enabled = power_is_enabled;
+}
+
+mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster)
+{
+ return cluster->power_is_enabled;
+}
+
+
+void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group)
+{
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+
+ if (cluster->number_of_groups < MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER)
+ {
+ /* This cluster now owns the group object */
+ cluster->groups[cluster->number_of_groups] = group;
+ cluster->number_of_groups++;
+ }
+}
+
+void mali_cluster_delete(struct mali_cluster *cluster)
+{
+ u32 i;
+
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+
+ /* Free all the resources we own */
+ for (i = 0; i < cluster->number_of_groups; i++)
+ {
+ mali_group_delete(cluster->groups[i]);
+ }
+
+ if (NULL != cluster->l2)
+ {
+ mali_l2_cache_delete(cluster->l2);
+ }
+
+ for (i = 0; i < mali_global_num_clusters; i++)
+ {
+ if (mali_global_clusters[i] == cluster)
+ {
+ mali_global_clusters[i] = NULL;
+ mali_global_num_clusters--;
+ break;
+ }
+ }
+
+ _mali_osk_free(cluster);
+}
+
+void mali_cluster_reset(struct mali_cluster *cluster)
+{
+ u32 i;
+
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+
+ /* Free all the resources we own */
+ for (i = 0; i < cluster->number_of_groups; i++)
+ {
+ struct mali_group *group = cluster->groups[i];
+
+ mali_group_reset(group);
+ }
+
+ if (NULL != cluster->l2)
+ {
+ mali_l2_cache_reset(cluster->l2);
+ }
+}
+
+struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster)
+{
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+ return cluster->l2;
+}
+
+struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index)
+{
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+
+ if (index < cluster->number_of_groups)
+ {
+ return cluster->groups[index];
+ }
+
+ return NULL;
+}
+
+struct mali_cluster *mali_cluster_get_global_cluster(u32 index)
+{
+ if (MALI_MAX_NUMBER_OF_CLUSTERS > index)
+ {
+ return mali_global_clusters[index];
+ }
+
+ return NULL;
+}
+
+u32 mali_cluster_get_glob_num_clusters(void)
+{
+ return mali_global_num_clusters;
+}
+
+mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id)
+{
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+
+ if (NULL != cluster->l2)
+ {
+ /* If the last cache invalidation was done by a job with a higher id we
+ * don't have to flush. Since user space will store jobs w/ their
+ * corresponding memory in sequence (first job #0, then job #1, ...),
+ * we don't have to flush for job n-1 if job n has already invalidated
+ * the cache since we know for sure that job n-1's memory was already
+ * written when job n was started. */
+ if (((s32)id) <= ((s32)cluster->last_invalidated_id))
+ {
+ return MALI_FALSE;
+ }
+ else
+ {
+ cluster->last_invalidated_id = mali_scheduler_get_new_id();
+ }
+
+ mali_l2_cache_invalidate_all(cluster->l2);
+ }
+ return MALI_TRUE;
+}
+
+void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster)
+{
+ MALI_DEBUG_ASSERT_POINTER(cluster);
+
+ if (NULL != cluster->l2)
+ {
+ cluster->last_invalidated_id = mali_scheduler_get_new_id();
+ mali_l2_cache_invalidate_all(cluster->l2);
+ }
+}
+
+void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages)
+{
+ u32 i;
+
+ for (i = 0; i < mali_global_num_clusters; i++)
+ {
+ /*additional check for cluster*/
+ if (MALI_TRUE == mali_l2_cache_lock_power_state(mali_global_clusters[i]->l2))
+ {
+ mali_l2_cache_invalidate_pages(mali_global_clusters[i]->l2, pages, num_pages);
+ }
+ mali_l2_cache_unlock_power_state(mali_global_clusters[i]->l2);
+ /*check for failed power locking???*/
+ }
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_cluster.h b/drivers/media/video/samsung/mali/common/mali_cluster.h
new file mode 100644
index 0000000..33debdb
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_cluster.h
@@ -0,0 +1,44 @@
+/*
+ * 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_CLUSTER_H__
+#define __MALI_CLUSTER_H__
+
+#include "mali_osk.h"
+#include "mali_l2_cache.h"
+
+/* Maximum 1 GP and 4 PP for a cluster (Mali-400 Quad-core) */
+#define MALI_MAX_NUMBER_OF_GROUPS_PER_CLUSTER 5
+#define MALI_MAX_NUMBER_OF_CLUSTERS 3
+
+struct mali_cluster;
+struct mali_group;
+
+struct mali_cluster *mali_cluster_create(struct mali_l2_cache_core *l2_cache);
+void mali_cluster_add_group(struct mali_cluster *cluster, struct mali_group *group);
+void mali_cluster_delete(struct mali_cluster *cluster);
+
+void mali_cluster_power_is_enabled_set(struct mali_cluster * cluster, mali_bool power_is_enabled);
+mali_bool mali_cluster_power_is_enabled_get(struct mali_cluster * cluster);
+
+void mali_cluster_reset(struct mali_cluster *cluster);
+
+struct mali_l2_cache_core* mali_cluster_get_l2_cache_core(struct mali_cluster *cluster);
+struct mali_group *mali_cluster_get_group(struct mali_cluster *cluster, u32 index);
+
+struct mali_cluster *mali_cluster_get_global_cluster(u32 index);
+u32 mali_cluster_get_glob_num_clusters(void);
+
+/* Returns MALI_TRUE if it did the flush */
+mali_bool mali_cluster_l2_cache_invalidate_all(struct mali_cluster *cluster, u32 id);
+void mali_cluster_l2_cache_invalidate_all_force(struct mali_cluster *cluster);
+void mali_cluster_invalidate_pages(u32 *pages, u32 num_pages);
+
+#endif /* __MALI_CLUSTER_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c
new file mode 100644
index 0000000..6af1279
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.c
@@ -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.
+ */
+
+/**
+ * @file mali_device_pause_resume.c
+ * Implementation of the Mali pause/resume functionality
+ */
+
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_pm.h"
+
+void mali_dev_pause(mali_bool *power_is_on)
+{
+ mali_gp_scheduler_suspend();
+ mali_pp_scheduler_suspend();
+
+ /*
+ * Take and hold the PM lock to be sure we don't change power state as well.
+ * (it might be unsafe to for instance change frequency if Mali GPU is powered off)
+ */
+ mali_pm_execute_state_change_lock();
+ if (NULL != power_is_on)
+ {
+ *power_is_on = mali_pm_is_powered_on();
+ }
+}
+
+void mali_dev_resume(void)
+{
+ mali_pm_execute_state_change_unlock();
+ mali_gp_scheduler_resume();
+ mali_pp_scheduler_resume();
+}
+
+/*
+EXPORT_SYMBOL(mali_dev_pause);
+EXPORT_SYMBOL(mali_dev_resume);
+*/
diff --git a/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.h
new file mode 100644
index 0000000..6be75b0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_device_pause_resume.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.
+ */
+
+#ifndef __MALI_DEVICE_PAUSE_RESUME_H__
+#define __MALI_DEVICE_PAUSE_RESUME_H__
+
+#include "mali_osk.h"
+
+/**
+ * Pause the scheduling and power state changes of Mali device driver.
+ * mali_dev_resume() must always be called as soon as possible after this function
+ * in order to resume normal operation of the Mali driver.
+ *
+ * @param power_is_on Receives the power current status of Mali GPU. MALI_TRUE if GPU is powered on
+ */
+void mali_dev_pause(mali_bool *power_is_on);
+
+/**
+ * Resume scheduling and allow power changes in Mali device driver.
+ * This must always be called after mali_dev_pause().
+ */
+void mali_dev_resume(void);
+
+#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.c b/drivers/media/video/samsung/mali/common/mali_dlbu.c
new file mode 100644
index 0000000..fcc51fa
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_dlbu.c
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ */
+
+#include "mali_dlbu.h"
+#include "mali_memory.h"
+#include "mali_pp.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "mali_hw_core.h"
+
+/**
+ * Size of DLBU registers in bytes
+ */
+#define MALI_DLBU_SIZE 0x400
+
+u32 mali_dlbu_phys_addr = 0;
+static mali_io_address mali_dlbu_cpu_addr = 0;
+
+static u32 mali_dlbu_tile_position;
+
+/**
+ * DLBU register numbers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_dlbu_register {
+ MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR = 0x0000, /**< Master tile list physical base address;
+ 31:12 Physical address to the page used for the DLBU
+ 0 DLBU enable - set this bit to 1 enables the AXI bus
+ between PPs and L2s, setting to 0 disables the router and
+ no further transactions are sent to DLBU */
+ MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR = 0x0004, /**< Master tile list virtual base address;
+ 31:12 Virtual address to the page used for the DLBU */
+ MALI_DLBU_REGISTER_TLLIST_VBASEADDR = 0x0008, /**< Tile list virtual base address;
+ 31:12 Virtual address to the tile list. This address is used when
+ calculating the call address sent to PP.*/
+ MALI_DLBU_REGISTER_FB_DIM = 0x000C, /**< Framebuffer dimension;
+ 23:16 Number of tiles in Y direction-1
+ 7:0 Number of tiles in X direction-1 */
+ MALI_DLBU_REGISTER_TLLIST_CONF = 0x0010, /**< Tile list configuration;
+ 29:28 select the size of each allocated block: 0=128 bytes, 1=256, 2=512, 3=1024
+ 21:16 2^n number of tiles to be binned to one tile list in Y direction
+ 5:0 2^n number of tiles to be binned to one tile list in X direction */
+ MALI_DLBU_REGISTER_START_TILE_POS = 0x0014, /**< Start tile positions;
+ 31:24 start position in Y direction for group 1
+ 23:16 start position in X direction for group 1
+ 15:8 start position in Y direction for group 0
+ 7:0 start position in X direction for group 0 */
+ MALI_DLBU_REGISTER_PP_ENABLE_MASK = 0x0018, /**< PP enable mask;
+ 7 enable PP7 for load balancing
+ 6 enable PP6 for load balancing
+ 5 enable PP5 for load balancing
+ 4 enable PP4 for load balancing
+ 3 enable PP3 for load balancing
+ 2 enable PP2 for load balancing
+ 1 enable PP1 for load balancing
+ 0 enable PP0 for load balancing */
+} mali_dlbu_register;
+
+typedef enum
+{
+ PP0ENABLE = 0,
+ PP1ENABLE,
+ PP2ENABLE,
+ PP3ENABLE,
+ PP4ENABLE,
+ PP5ENABLE,
+ PP6ENABLE,
+ PP7ENABLE
+} mali_dlbu_pp_enable;
+
+struct mali_dlbu_core
+{
+ struct mali_hw_core hw_core; /**< Common for all HW cores */
+ u32 pp_cores_mask; /**< This is a mask for the PP cores whose operation will be controlled by LBU
+ see MALI_DLBU_REGISTER_PP_ENABLE_MASK register */
+};
+
+_mali_osk_errcode_t mali_dlbu_initialize(void)
+{
+
+ MALI_DEBUG_PRINT(2, ("Dynamic Load Balancing Unit initializing\n"));
+
+ if (_MALI_OSK_ERR_OK == mali_mmu_get_table_page(&mali_dlbu_phys_addr, &mali_dlbu_cpu_addr))
+ {
+ MALI_SUCCESS;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_dlbu_terminate(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali DLBU: terminating\n"));
+
+ mali_mmu_release_table_page(mali_dlbu_phys_addr);
+}
+
+struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource)
+{
+ struct mali_dlbu_core *core = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Mali DLBU: Creating Mali dynamic load balancing unit: %s\n", resource->description));
+
+ core = _mali_osk_malloc(sizeof(struct mali_dlbu_core));
+ if (NULL != core)
+ {
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI_DLBU_SIZE))
+ {
+ if (_MALI_OSK_ERR_OK == mali_dlbu_reset(core))
+ {
+ mali_hw_core_register_write(&core->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_VADDR, MALI_DLB_VIRT_ADDR);
+
+ return core;
+ }
+ MALI_PRINT_ERROR(("Failed to reset DLBU %s\n", core->hw_core.description));
+ mali_hw_core_delete(&core->hw_core);
+ }
+
+ _mali_osk_free(core);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali DLBU: Failed to allocate memory for DLBU core\n"));
+ }
+
+ return NULL;
+}
+
+void mali_dlbu_delete(struct mali_dlbu_core *dlbu)
+{
+ mali_dlbu_reset(dlbu);
+ mali_hw_core_delete(&dlbu->hw_core);
+ _mali_osk_free(dlbu);
+}
+
+void mali_dlbu_enable(struct mali_dlbu_core *dlbu)
+{
+ u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR);
+
+ wval |= 0x1;
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval);
+}
+
+void mali_dlbu_disable(struct mali_dlbu_core *dlbu)
+{
+ u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR);
+
+ wval |= (wval & 0xFFFFFFFE);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, wval);
+}
+
+_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val)
+{
+ u32 wval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK);
+
+ if((pp_core_enable < mali_pp_get_glob_num_pp_cores()) && ((0 == val) || (1 == val))) /* check for valid input parameters */
+ {
+ if (val == 1)
+ {
+ val = (wval | (pp_core_enable <<= 0x1));
+ }
+ if (val == 0)
+ {
+ val = (wval & ~(pp_core_enable << 0x1));
+ }
+ wval |= val;
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, wval);
+ dlbu->pp_cores_mask = wval;
+
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu)
+{
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
+}
+
+void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu)
+{
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, 0x0);
+}
+
+void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1)
+{
+ u32 wval = 0x0;
+
+ /* write the framebuffer dimensions */
+ wval = (16 << (u32)fb_ydim) | (u32)fb_xdim;
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, wval);
+
+ /* write the tile list configuration */
+ wval = 0x0;
+ wval = (28 << (u32)blocksize) | (16 << (u32)ytilesize) | ((u32)xtilesize);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, wval);
+
+ /* write the start tile position */
+ wval = 0x0;
+ wval = (24 << (u32)ygr1 | (16 << (u32)xgr1) | 8 << (u32)ygr0) | (u32)xgr0;
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, wval);
+}
+
+_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu)
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+ MALI_DEBUG_ASSERT_POINTER(dlbu);
+
+ MALI_DEBUG_PRINT(4, ("Mali DLBU: mali_dlbu_reset: %s\n", dlbu->hw_core.description));
+
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_MASTER_TLLIST_PHYS_ADDR, mali_dlbu_phys_addr);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, 0x00);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_FB_DIM, 0x00);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_CONF, 0x00);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, 0x00);
+
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
+
+ err = _MALI_OSK_ERR_OK;
+
+ return err;
+}
+
+_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+ u32 wval, rval;
+ struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+
+ /* find the core id and set the mask */
+
+ if (NULL != pp_core)
+ {
+ wval = mali_pp_core_get_id(pp_core);
+ rval = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK);
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, (wval << 0x1) | rval);
+ err = _MALI_OSK_ERR_OK;
+ }
+
+ return err;
+}
+
+void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val)
+{
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, val);
+}
+
+void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu)
+{
+ /* this function to implement (see documentation):
+ * 1) clear all bits in the enable register
+ * 2) wait until all PPs have finished - mali_pp_scheduler.c code - this done in interrupts call?
+ * 3) read the current tile position registers to get current tile positions -
+ * note that current tile position register is the same as start tile position - perhaps the name should be changed!!! */
+
+ /* 1) */
+ mali_dlbu_disable_all_pp_cores(dlbu);
+
+ /* 3) */
+ mali_dlbu_tile_position = mali_hw_core_register_read(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS);
+}
+
+void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu)
+{
+ /* this function to implement (see the document):
+ * 1) configure the dynamic load balancing unit as normal
+ * 2) set the current tile position registers as read when stopping the job
+ * 3) configure the PPs to start the job as normal - done by another part of the system - scheduler */
+
+ /* 1) */
+ mali_dlbu_reset(dlbu);
+ /* ++ setup the needed values - see this */
+
+ /* 2) */
+ mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_START_TILE_POS, mali_dlbu_tile_position);
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_dlbu.h b/drivers/media/video/samsung/mali/common/mali_dlbu.h
new file mode 100644
index 0000000..e3c3b9d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_dlbu.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef __MALI_DLBU_H__
+#define __MALI_DLBU_H__
+
+#include "mali_osk.h"
+#include "mali_group.h"
+
+#define MALI_DLB_VIRT_ADDR 0xFFF00000 /* master tile virtual address fixed at this value and mapped into every session */
+
+extern u32 mali_dlbu_phys_addr;
+
+struct mali_dlbu_core;
+
+_mali_osk_errcode_t mali_dlbu_initialize(void);
+void mali_dlbu_terminate(void);
+
+struct mali_dlbu_core *mali_dlbu_create(const _mali_osk_resource_t * resource);
+void mali_dlbu_delete(struct mali_dlbu_core *dlbu);
+
+void mali_dlbu_enable(struct mali_dlbu_core *dlbu);
+void mali_dlbu_disable(struct mali_dlbu_core *dlbu);
+
+_mali_osk_errcode_t mali_dlbu_enable_pp_core(struct mali_dlbu_core *dlbu, u32 pp_core_enable, u32 val);
+void mali_dlbu_enable_all_pp_cores(struct mali_dlbu_core *dlbu);
+void mali_dlbu_disable_all_pp_cores(struct mali_dlbu_core *dlbu);
+
+_mali_osk_errcode_t mali_dlbu_reset(struct mali_dlbu_core *dlbu);
+void mali_dlbu_setup(struct mali_dlbu_core *dlbu, u8 fb_xdim, u8 fb_ydim, u8 xtilesize, u8 ytilesize, u8 blocksize, u8 xgr0, u8 ygr0, u8 xgr1, u8 ygr1);
+
+_mali_osk_errcode_t mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group);
+void mali_dlbu_set_tllist_base_address(struct mali_dlbu_core *dlbu, u32 val);
+
+void mali_dlbu_pp_jobs_stop(struct mali_dlbu_core *dlbu);
+void mali_dlbu_pp_jobs_restart(struct mali_dlbu_core *dlbu);
+
+#endif /* __MALI_DLBU_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_gp.c b/drivers/media/video/samsung/mali/common/mali_gp.c
new file mode 100644
index 0000000..d03721c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp.c
@@ -0,0 +1,693 @@
+/*
+ * 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_gp.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "regs/mali_gp_regs.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.h"
+#endif
+
+/**
+ * Definition of the GP core struct
+ * Used to track a GP core in the system.
+ */
+struct mali_gp_core
+{
+ struct mali_hw_core hw_core; /**< Common for all HW cores */
+ struct mali_group *group; /**< Parent group for this core */
+ _mali_osk_irq_t *irq; /**< IRQ handler */
+ struct mali_gp_job *running_job; /**< Current running job */
+ _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */
+ u32 timeout_job_id; /**< job id for the timed out job - relevant only if gp_core_timed_out == MALI_TRUE */
+ mali_bool core_timed_out; /**< if MALI_TRUE, this gp core has timed out; if MALI_FALSE, no timeout on this gp core */
+ u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+ u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+ u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */
+ u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */
+};
+
+static struct mali_gp_core *mali_global_gp_core = NULL;
+
+/* Interrupt handlers */
+static _mali_osk_errcode_t mali_gp_upper_half(void *data);
+static void mali_gp_bottom_half(void *data);
+static void mali_gp_irq_probe_trigger(void *data);
+static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data);
+static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend);
+static void mali_gp_timeout(void *data);
+
+struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group)
+{
+ struct mali_gp_core* core = NULL;
+
+ MALI_DEBUG_ASSERT(NULL == mali_global_gp_core);
+ MALI_DEBUG_PRINT(2, ("Mali GP: Creating Mali GP core: %s\n", resource->description));
+
+ core = _mali_osk_malloc(sizeof(struct mali_gp_core));
+ if (NULL != core)
+ {
+ core->group = group;
+ core->running_job = NULL;
+ core->counter_src0 = MALI_HW_CORE_NO_COUNTER;
+ core->counter_src1 = MALI_HW_CORE_NO_COUNTER;
+ core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
+ core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALIGP2_REGISTER_ADDRESS_SPACE_SIZE))
+ {
+ _mali_osk_errcode_t ret;
+
+ mali_group_lock(group);
+ ret = mali_gp_reset(core);
+ mali_group_unlock(group);
+
+ if (_MALI_OSK_ERR_OK == ret)
+ {
+ /* Setup IRQ handlers (which will do IRQ probing if needed) */
+ core->irq = _mali_osk_irq_init(resource->irq,
+ mali_gp_upper_half,
+ mali_gp_bottom_half,
+ mali_gp_irq_probe_trigger,
+ mali_gp_irq_probe_ack,
+ core,
+ "mali_gp_irq_handlers");
+ if (NULL != core->irq)
+ {
+ /* Initialise the timeout timer */
+ core->timeout_timer = _mali_osk_timer_init();
+ if(NULL != core->timeout_timer)
+ {
+ _mali_osk_timer_setcallback(core->timeout_timer, mali_gp_timeout, (void *)core);
+ MALI_DEBUG_PRINT(4, ("Mali GP: set global gp core from 0x%08X to 0x%08X\n", mali_global_gp_core, core));
+ mali_global_gp_core = core;
+
+ return core;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to setup timeout timer for GP core %s\n", core->hw_core.description));
+ /* Release IRQ handlers */
+ _mali_osk_irq_term(core->irq);
+ }
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to setup interrupt handlers for GP core %s\n", core->hw_core.description));
+ }
+ }
+ mali_hw_core_delete(&core->hw_core);
+ }
+
+ _mali_osk_free(core);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to allocate memory for GP core\n"));
+ }
+
+ return NULL;
+}
+
+void mali_gp_delete(struct mali_gp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ _mali_osk_timer_term(core->timeout_timer);
+ _mali_osk_irq_term(core->irq);
+ mali_hw_core_delete(&core->hw_core);
+ mali_global_gp_core = NULL;
+ _mali_osk_free(core);
+}
+
+void mali_gp_stop_bus(struct mali_gp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
+}
+
+_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core)
+{
+ int i;
+ const int request_loop_count = 20;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ /* Send the stop bus command. */
+ mali_gp_stop_bus(core);
+
+ /* Wait for bus to be stopped */
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Mali GP: Failed to stop bus on %s\n", core->hw_core.description));
+ return _MALI_OSK_ERR_FAULT;
+ }
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_gp_hard_reset(struct mali_gp_core *core)
+{
+ const 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_DEBUG_ASSERT_POINTER(core);
+ MALI_DEBUG_PRINT(4, ("Mali GP: Hard reset of core %s\n", core->hw_core.description));
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ mali_gp_post_process_job(core, MALI_FALSE);
+
+ mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_invalid_value);
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_RESET);
+
+ for (i = 0; i < reset_finished_loop_count; i++)
+ {
+ mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_check_value);
+ if (reset_check_value == mali_hw_core_register_read(&core->hw_core, reset_wait_target_register))
+ {
+ break;
+ }
+ }
+
+ if (i == reset_finished_loop_count)
+ {
+ MALI_PRINT_ERROR(("Mali GP: The hard reset loop didn't work, unable to recover\n"));
+ }
+
+ mali_hw_core_register_write(&core->hw_core, reset_wait_target_register, reset_default_value); /* set it back to the default */
+ /* Re-enable interrupts */
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+
+}
+
+_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core)
+{
+ int i;
+ const int request_loop_count = 20;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_DEBUG_PRINT(4, ("Mali GP: Reset of core %s\n", core->hw_core.description));
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ mali_gp_post_process_job(core, MALI_FALSE);
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+
+#if defined(USING_MALI200)
+
+ /* On Mali-200, stop the bus, then do a hard reset of the core */
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_STOP_BUS);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) & MALIGP2_REG_VAL_STATUS_BUS_STOPPED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Mali GP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* the bus was stopped OK, do the hard reset */
+ mali_gp_hard_reset(core);
+
+#elif defined(USING_MALI400)
+
+ /* Mali-300 and Mali-400 have a safe reset command which we use */
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALI400GP_REG_VAL_IRQ_RESET_COMPLETED);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALI400GP_REG_VAL_CMD_SOFT_RESET);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400GP_REG_VAL_IRQ_RESET_COMPLETED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Mali GP: Failed to reset core %s, unable to recover\n", core->hw_core.description));
+ return _MALI_OSK_ERR_FAULT;
+ }
+#else
+#error "no supported mali core defined"
+#endif
+
+ /* Re-enable interrupts */
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job)
+{
+ u32 startcmd = 0;
+ u32 *frame_registers = mali_gp_job_get_frame_registers(job);
+ core->counter_src0_used = core->counter_src0;
+ core->counter_src1_used = core->counter_src1;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ if (mali_gp_job_has_vs_job(job))
+ {
+ startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_VS;
+ }
+
+ if (mali_gp_job_has_plbu_job(job))
+ {
+ startcmd |= (u32) MALIGP2_REG_VAL_CMD_START_PLBU;
+ }
+
+ MALI_DEBUG_ASSERT(0 != startcmd);
+
+ mali_hw_core_register_write_array_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VSCL_START_ADDR, frame_registers, MALIGP2_NUM_REGS_FRAME);
+
+ /* This selects which performance counters we are reading */
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+ {
+ /* global_config has enabled HW counters, this will override anything specified by user space */
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+ }
+ else
+ {
+ /* Use HW counters from job object, if any */
+ u32 perf_counter_flag = mali_gp_job_get_perf_counter_flag(job);
+ if (0 != perf_counter_flag)
+ {
+ if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
+ {
+ core->counter_src0_used = mali_gp_job_get_perf_counter_src0(job);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+
+ if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
+ {
+ core->counter_src1_used = mali_gp_job_get_perf_counter_src1(job);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE);
+ }
+ }
+ }
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: Starting job (0x%08x) on core %s with command 0x%08X\n", job, core->hw_core.description, startcmd));
+
+ /* Barrier to make sure the previous register write is finished */
+ _mali_osk_write_mem_barrier();
+
+ /* This is the command that starts the core. */
+ mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, startcmd);
+
+ /* Barrier to make sure the previous register write is finished */
+ _mali_osk_write_mem_barrier();
+
+ /* Setup the timeout timer value and save the job id for the job running on the gp core */
+
+ _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
+ core->timeout_job_id = mali_gp_job_get_id(job);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
+ job->frame_builder_id, job->flush_id, 0, 0, 0);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), job->pid, job->tid, 0, 0, 0);
+#endif
+
+ core->running_job = job;
+}
+
+void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr)
+{
+ u32 irq_readout;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT);
+
+ if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG));
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* re-enable interrupts */
+ mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, start_addr);
+ mali_hw_core_register_write_relaxed(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, end_addr);
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: Resuming job\n"));
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC);
+ _mali_osk_write_mem_barrier();
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0);
+#endif
+ }
+ /*
+ * else: core has been reset between PLBU_OUT_OF_MEM interrupt and this new heap response.
+ * A timeout or a page fault on Mali-200 PP core can cause this behaviour.
+ */
+}
+
+void mali_gp_abort_job(struct mali_gp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ if (_MALI_OSK_ERR_FAULT != mali_gp_reset(core))
+ {
+ _mali_osk_timer_del(core->timeout_timer);
+ }
+}
+
+u32 mali_gp_core_get_version(struct mali_gp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_VERSION);
+}
+
+mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ core->counter_src0 = counter;
+ return MALI_TRUE;
+}
+
+mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ core->counter_src1 = counter;
+ return MALI_TRUE;
+}
+
+u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return core->counter_src0;
+}
+
+u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return core->counter_src1;
+}
+
+struct mali_gp_core *mali_gp_get_global_gp_core(void)
+{
+ return mali_global_gp_core;
+}
+
+/* ------------- interrupt handling below ------------------ */
+static _mali_osk_errcode_t mali_gp_upper_half(void *data)
+{
+ struct mali_gp_core *core = (struct mali_gp_core *)data;
+ u32 irq_readout;
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+ if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout)
+ {
+ /* Mask out all IRQs from this core until IRQ is handled */
+ mali_hw_core_register_write(&core->hw_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(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
+#endif
+
+ /* We do need to handle this in a bottom half */
+ _mali_osk_irq_schedulework(core->irq);
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+static void mali_gp_bottom_half(void *data)
+{
+ struct mali_gp_core *core = (struct mali_gp_core *)data;
+ u32 irq_readout;
+ u32 irq_errors;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+#if 0 /* Bottom half TLP logging is currently not supported */
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0);
+#endif
+#endif
+
+ mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */
+
+ if ( MALI_FALSE == mali_group_power_is_on(core->group) )
+ {
+ MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description));
+ mali_group_unlock(core->group);
+ return;
+ }
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT) & MALIGP2_REG_VAL_IRQ_MASK_USED;
+ MALI_DEBUG_PRINT(4, ("Mali GP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description));
+
+ if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST))
+ {
+ u32 core_status = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS);
+ if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
+ {
+ mali_gp_post_process_job(core, MALI_FALSE);
+ MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n"));
+ mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); /* Will release group lock */
+ return;
+ }
+ }
+
+ /*
+ * Now lets look at the possible error cases (IRQ indicating error or timeout)
+ * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error.
+ */
+ irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM);
+ if (0 != irq_errors)
+ {
+ mali_gp_post_process_job(core, MALI_FALSE);
+ MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description));
+ mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); /* Will release group lock */
+ return;
+ }
+ else if (MALI_TRUE == core->core_timed_out) /* SW timeout */
+ {
+ if (core->timeout_job_id == mali_gp_job_get_id(core->running_job))
+ {
+ mali_gp_post_process_job(core, MALI_FALSE);
+ MALI_DEBUG_PRINT(2, ("Mali GP: Job %d timed out\n", mali_gp_job_get_id(core->running_job)));
+ mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT);
+ }
+ core->core_timed_out = MALI_FALSE;
+ return;
+ }
+ else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
+ {
+ /* GP wants more memory in order to continue.
+ *
+ * This must be handled prior to HANG because this actually can
+ * generate a HANG while waiting for more memory.
+ * And it must be handled before the completion interrupts,
+ * since the PLBU can run out of memory after VS is complete;
+ * in which case the OOM must be handled before to complete the
+ * PLBU work.
+ */
+ mali_gp_post_process_job(core, MALI_TRUE);
+ MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n"));
+ mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); /* Will release group lock */
+ return;
+ }
+ else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG)
+ {
+ /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG);
+ }
+
+ /*
+ * The only way to get here is if we got a HANG interrupt, which we ignore, or only one of two needed END_CMD_LST interrupts.
+ * Re-enable interrupts and let core continue to run.
+ */
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED);
+ mali_group_unlock(core->group);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+#if 0 /* Bottom half TLP logging is currently not supported */
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0);
+#endif
+#endif
+}
+
+static void mali_gp_irq_probe_trigger(void *data)
+{
+ struct mali_gp_core *core = (struct mali_gp_core *)data;
+
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_RAWSTAT, MALIGP2_REG_VAL_CMD_FORCE_HANG);
+ _mali_osk_mem_barrier();
+}
+
+static _mali_osk_errcode_t mali_gp_irq_probe_ack(void *data)
+{
+ struct mali_gp_core *core = (struct mali_gp_core *)data;
+ u32 irq_readout;
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_STAT);
+ if (MALIGP2_REG_VAL_IRQ_FORCE_HANG & irq_readout)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_FORCE_HANG);
+ _mali_osk_mem_barrier();
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+/* ------ local helper functions below --------- */
+
+static void mali_gp_post_process_job(struct mali_gp_core *core, mali_bool suspend)
+{
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ if (NULL != core->running_job)
+ {
+ u32 val0 = 0;
+ u32 val1 = 0;
+#if MALI_TIMELINE_PROFILING_ENABLED
+ u32 event_id;
+#endif
+
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+ {
+ val0 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+ if (mali_gp_job_get_perf_counter_flag(core->running_job) &&
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_gp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used)
+ {
+ /* We retrieved the counter that user space asked for, so return the value through the job object */
+ mali_gp_job_set_perf_counter_value0(core->running_job, val0);
+ }
+ else
+ {
+ /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */
+ mali_gp_job_set_perf_counter_value0(core->running_job, MALI_HW_CORE_INVALID_VALUE);
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, val0);
+#endif
+
+ }
+
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+ {
+ val1 = mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+ if (mali_gp_job_get_perf_counter_flag(core->running_job) &&
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_gp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used)
+ {
+ /* We retrieved the counter that user space asked for, so return the value through the job object */
+ mali_gp_job_set_perf_counter_value1(core->running_job, val1);
+ }
+ else
+ {
+ /* User space asked for a counter, but this is not what we retrieved (overridden by counter src set on core) */
+ mali_gp_job_set_perf_counter_value1(core->running_job, MALI_HW_CORE_INVALID_VALUE);
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, val1);
+#endif
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ if (MALI_TRUE == suspend)
+ {
+ event_id = MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0);
+ }
+ else
+ {
+ event_id = MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0);
+ }
+ _mali_osk_profiling_add_event(event_id, val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0);
+#endif
+
+ mali_gp_job_set_current_heap_addr(core->running_job,
+ mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR));
+
+ if (MALI_TRUE != suspend)
+ {
+ /* We are no longer running a job... */
+ core->running_job = NULL;
+ _mali_osk_timer_del(core->timeout_timer);
+ }
+ }
+}
+
+/* callback function for gp core timeout */
+static void mali_gp_timeout(void *data)
+{
+ struct mali_gp_core * core = ((struct mali_gp_core *)data);
+
+ MALI_DEBUG_PRINT(3, ("Mali GP: TIMEOUT callback \n"));
+ core->core_timed_out = MALI_TRUE;
+ _mali_osk_irq_schedulework(core->irq);
+}
+
+#if 0
+void mali_gp_print_state(struct mali_gp_core *core)
+{
+ MALI_DEBUG_PRINT(2, ("Mali GP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALIGP2_REG_ADDR_MGMT_STATUS) ));
+}
+#endif
+
+#if MALI_STATE_TRACKING
+u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size)
+{
+ int n = 0;
+
+ n += _mali_osk_snprintf(buf + n, size - n, "\tGP: %s\n", core->hw_core.description);
+
+ return n;
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_gp.h b/drivers/media/video/samsung/mali/common/mali_gp.h
new file mode 100644
index 0000000..3175b75
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp.h
@@ -0,0 +1,46 @@
+/*
+ * 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_GP_H__
+#define __MALI_GP_H__
+
+#include "mali_osk.h"
+#include "mali_gp_job.h"
+
+struct mali_gp_core;
+struct mali_group;
+
+_mali_osk_errcode_t mali_gp_initialize(void);
+void mali_gp_terminate(void);
+
+struct mali_gp_core *mali_gp_create(const _mali_osk_resource_t * resource, struct mali_group *group);
+void mali_gp_delete(struct mali_gp_core *core);
+
+void mali_gp_stop_bus(struct mali_gp_core *core);
+_mali_osk_errcode_t mali_gp_stop_bus_wait(struct mali_gp_core *core);
+void mali_gp_hard_reset(struct mali_gp_core *core);
+_mali_osk_errcode_t mali_gp_reset(struct mali_gp_core *core);
+
+void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job);
+void mali_gp_resume_with_new_heap(struct mali_gp_core *core, u32 start_addr, u32 end_addr);
+
+void mali_gp_abort_job(struct mali_gp_core *core);
+
+u32 mali_gp_core_get_version(struct mali_gp_core *core);
+
+mali_bool mali_gp_core_set_counter_src0(struct mali_gp_core *core, u32 counter);
+mali_bool mali_gp_core_set_counter_src1(struct mali_gp_core *core, u32 counter);
+u32 mali_gp_core_get_counter_src0(struct mali_gp_core *core);
+u32 mali_gp_core_get_counter_src1(struct mali_gp_core *core);
+struct mali_gp_core *mali_gp_get_global_gp_core(void);
+
+u32 mali_gp_dump_state(struct mali_gp_core *core, char *buf, u32 size);
+
+#endif /* __MALI_GP_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.c b/drivers/media/video/samsung/mali/common/mali_gp_job.c
new file mode 100644
index 0000000..abe1d93
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_job.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_gp_job.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+
+struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id)
+{
+ struct mali_gp_job *job;
+
+ job = _mali_osk_malloc(sizeof(struct mali_gp_job));
+ if (NULL != job)
+ {
+ _mali_osk_list_init(&job->list);
+ job->session = session;
+ job->id = id;
+ job->user_id = args->user_job_ptr;
+ _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers));
+ job->heap_current_addr = args->frame_registers[4];
+ job->perf_counter_flag = args->perf_counter_flag;
+ job->perf_counter_src0 = args->perf_counter_src0;
+ job->perf_counter_src1 = args->perf_counter_src1;
+ job->perf_counter_value0 = 0;
+ job->perf_counter_value1 = 0;
+
+ job->pid = _mali_osk_get_pid();
+ job->tid = _mali_osk_get_tid();
+ job->frame_builder_id = args->frame_builder_id;
+ job->flush_id = args->flush_id;
+
+ return job;
+ }
+
+ return NULL;
+}
+
+void mali_gp_job_delete(struct mali_gp_job *job)
+{
+ _mali_osk_free(job);
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.h b/drivers/media/video/samsung/mali/common/mali_gp_job.h
new file mode 100644
index 0000000..9c29f1c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_job.h
@@ -0,0 +1,131 @@
+/*
+ * 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_GP_JOB_H__
+#define __MALI_GP_JOB_H__
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+#include "mali_session.h"
+
+/**
+ * The structure represends a GP job, including all sub-jobs
+ * (This struct unfortunatly needs to be public because of how the _mali_osk_list_*
+ * mechanism works)
+ */
+struct mali_gp_job
+{
+ _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */
+ struct mali_session_data *session; /**< Session which submitted this job */
+ u32 id; /**< identifier for this job in kernel space (sequential numbering) */
+ u32 user_id; /**< identifier for the job in user space */
+ u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< core specific registers associated with this job, see ARM DDI0415A */
+ u32 heap_current_addr; /**< Holds the current HEAP address when the job has completed */
+ u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */
+ u32 perf_counter_src0; /**< source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter_src1; /**< source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter_value0; /**< Value of performance counter 0 (to be returned to user space) */
+ u32 perf_counter_value1; /**< Value of performance counter 1 (to be returned to user space) */
+ u32 pid; /**< Process ID of submitting process */
+ u32 tid; /**< Thread ID of submitting thread */
+ u32 frame_builder_id; /**< id of the originating frame builder */
+ u32 flush_id; /**< flush id within the originating frame builder */
+};
+
+struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id);
+void mali_gp_job_delete(struct mali_gp_job *job);
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job)
+{
+ return (NULL == job) ? 0 : job->id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job)
+{
+ return job->user_id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job)
+{
+ return job->frame_builder_id;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job)
+{
+ return job->flush_id;
+}
+
+MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job)
+{
+ return job->frame_registers;
+}
+
+MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job)
+{
+ return job->session;
+}
+
+MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job)
+{
+ return (job->frame_registers[0] != job->frame_registers[1]) ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job)
+{
+ return (job->frame_registers[2] != job->frame_registers[3]) ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job)
+{
+ return job->heap_current_addr;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *job, u32 heap_addr)
+{
+ job->heap_current_addr = heap_addr;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job)
+{
+ return job->perf_counter_flag;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job)
+{
+ return job->perf_counter_src0;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job)
+{
+ return job->perf_counter_src1;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job)
+{
+ return job->perf_counter_value0;
+}
+
+MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value1(struct mali_gp_job *job)
+{
+ return job->perf_counter_value1;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value0(struct mali_gp_job *job, u32 value)
+{
+ job->perf_counter_value0 = value;
+}
+
+MALI_STATIC_INLINE void mali_gp_job_set_perf_counter_value1(struct mali_gp_job *job, u32 value)
+{
+ job->perf_counter_value1 = value;
+}
+
+#endif /* __MALI_GP_JOB_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c
new file mode 100644
index 0000000..05f00fc
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+#include "mali_gp_scheduler.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_scheduler.h"
+#include "mali_gp.h"
+#include "mali_gp_job.h"
+#include "mali_group.h"
+#include "mali_cluster.h"
+
+enum mali_gp_slot_state
+{
+ MALI_GP_SLOT_STATE_IDLE,
+ MALI_GP_SLOT_STATE_WORKING,
+};
+
+/* A render slot is an entity which jobs can be scheduled onto */
+struct mali_gp_slot
+{
+ struct mali_group *group;
+ /*
+ * We keep track of the state here as well as in the group object
+ * so we don't need to take the group lock so often (and also avoid clutter with the working lock)
+ */
+ enum mali_gp_slot_state state;
+ u32 returned_cookie;
+};
+
+static u32 gp_version = 0;
+static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */
+static struct mali_gp_slot slot;
+
+/* Variables to allow safe pausing of the scheduler */
+static _mali_osk_wait_queue_t *gp_scheduler_working_wait_queue = NULL;
+static u32 pause_count = 0;
+
+static mali_bool mali_gp_scheduler_is_suspended(void);
+
+static _mali_osk_lock_t *gp_scheduler_lock = NULL;
+/* Contains tid of thread that locked the scheduler or 0, if not locked */
+
+_mali_osk_errcode_t mali_gp_scheduler_initialize(void)
+{
+ u32 i;
+
+ _MALI_OSK_INIT_LIST_HEAD(&job_queue);
+
+ gp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+ gp_scheduler_working_wait_queue = _mali_osk_wait_queue_init();
+
+ if (NULL == gp_scheduler_lock)
+ {
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ if (NULL == gp_scheduler_working_wait_queue)
+ {
+ _mali_osk_lock_term(gp_scheduler_lock);
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ /* Find all the available GP cores */
+ for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++)
+ {
+ u32 group_id = 0;
+ struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i);
+ struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id);
+ while (NULL != group)
+ {
+ struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+ if (NULL != gp_core)
+ {
+ if (0 == gp_version)
+ {
+ /* Retrieve GP version */
+ gp_version = mali_gp_core_get_version(gp_core);
+ }
+ slot.group = group;
+ slot.state = MALI_GP_SLOT_STATE_IDLE;
+ break; /* There are only one GP, no point in looking for more */
+ }
+ group_id++;
+ group = mali_cluster_get_group(curr_cluster, group_id);
+ }
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_gp_scheduler_terminate(void)
+{
+ _mali_osk_wait_queue_term(gp_scheduler_working_wait_queue);
+ _mali_osk_lock_term(gp_scheduler_lock);
+}
+
+MALI_STATIC_INLINE void mali_gp_scheduler_lock(void)
+{
+ if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW))
+ {
+ /* Non-interruptable lock failed: this should never happen. */
+ MALI_DEBUG_ASSERT(0);
+ }
+ MALI_DEBUG_PRINT(5, ("Mali GP scheduler: GP scheduler lock taken\n"));
+}
+
+MALI_STATIC_INLINE void mali_gp_scheduler_unlock(void)
+{
+ MALI_DEBUG_PRINT(5, ("Mali GP scheduler: Releasing GP scheduler lock\n"));
+ _mali_osk_lock_signal(gp_scheduler_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+#ifdef DEBUG
+MALI_STATIC_INLINE void mali_gp_scheduler_assert_locked(void)
+{
+ MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock);
+}
+#define MALI_ASSERT_GP_SCHEDULER_LOCKED() mali_gp_scheduler_assert_locked()
+#else
+#define MALI_ASSERT_GP_SCHEDULER_LOCKED()
+#endif
+
+static void mali_gp_scheduler_schedule(void)
+{
+ struct mali_gp_job *job;
+
+ MALI_ASSERT_GP_SCHEDULER_LOCKED();
+
+ if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue))
+ {
+ MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
+ pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0));
+ return; /* Nothing to do, so early out */
+ }
+
+ job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list);
+
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job));
+ if (_MALI_OSK_ERR_OK == mali_group_start_gp_job(slot.group, job))
+ {
+ /* Mark slot as busy */
+ slot.state = MALI_GP_SLOT_STATE_WORKING;
+
+ /* Remove from queue of unscheduled jobs */
+ _mali_osk_list_del(&job->list);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n"));
+ }
+}
+
+static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success)
+{
+ _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s));
+ if (NULL != notobj)
+ {
+ _mali_uk_gp_job_finished_s *jobres = notobj->result_buffer;
+ _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */
+ jobres->user_job_ptr = mali_gp_job_get_user_id(job);
+ if (MALI_TRUE == success)
+ {
+ jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS;
+ }
+ else
+ {
+ jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR;
+ }
+
+ jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job);
+ jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job);
+ jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job);
+
+ mali_session_send_notification(mali_gp_job_get_session(job), notobj);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali GP scheduler: Unable to allocate notification object\n"));
+ }
+
+ mali_gp_job_delete(job);
+}
+
+
+void mali_gp_scheduler_do_schedule(void)
+{
+ mali_gp_scheduler_lock();
+
+ mali_gp_scheduler_schedule();
+
+ mali_gp_scheduler_unlock();
+}
+
+void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success)
+{
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure"));
+
+ mali_gp_scheduler_lock();
+
+ /* Mark slot as idle again */
+ slot.state = MALI_GP_SLOT_STATE_IDLE;
+
+ /* If paused, then this was the last job, so wake up sleeping workers */
+ if (pause_count > 0)
+ {
+ _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue);
+ }
+ else
+ {
+ mali_gp_scheduler_schedule();
+ }
+
+ mali_gp_scheduler_unlock();
+
+ mali_gp_scheduler_return_job_to_user(job, success);
+}
+
+void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job)
+{
+ _mali_osk_notification_t *notobj;
+
+ notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s));
+
+ if (NULL != notobj)
+ {
+ _mali_uk_gp_job_suspended_s * jobres;
+
+ mali_gp_scheduler_lock();
+
+ jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer;
+
+ jobres->user_job_ptr = mali_gp_job_get_user_id(job);
+ jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY;
+ jobres->cookie = mali_gp_job_get_id(job);
+ slot.returned_cookie = jobres->cookie;
+
+ mali_session_send_notification(mali_gp_job_get_session(job), notobj);
+
+ mali_gp_scheduler_unlock();
+ }
+
+ /*
+ * If this function failed, then we could return the job to user space right away,
+ * but there is a job timer anyway that will do that eventually.
+ * This is not exactly a common case anyway.
+ */
+}
+
+void mali_gp_scheduler_suspend(void)
+{
+ mali_gp_scheduler_lock();
+ pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */
+ mali_gp_scheduler_unlock();
+
+ _mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended);
+}
+
+void mali_gp_scheduler_resume(void)
+{
+ mali_gp_scheduler_lock();
+ pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
+ if (0 == pause_count)
+ {
+ mali_gp_scheduler_schedule();
+ }
+ mali_gp_scheduler_unlock();
+}
+
+_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args)
+{
+ struct mali_session_data *session;
+ struct mali_gp_job *job;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ if (NULL == args->ctx)
+ {
+ return _MALI_OSK_ERR_INVALID_ARGS;
+ }
+
+ session = (struct mali_session_data*)args->ctx;
+ if (NULL == session)
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ job = mali_gp_job_create(session, args, mali_scheduler_get_new_id());
+ if (NULL == job)
+ {
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ mali_gp_scheduler_lock();
+
+ _mali_osk_list_addtail(&job->list, &job_queue);
+
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job));
+
+ mali_gp_scheduler_schedule();
+
+ mali_gp_scheduler_unlock();
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores(_mali_uk_get_gp_number_of_cores_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ args->number_of_cores = 1;
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_gp_core_version(_mali_uk_get_gp_core_version_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ args->version = gp_version;
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args)
+{
+ struct mali_session_data *session;
+ _mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ if (NULL == args->ctx)
+ {
+ return _MALI_OSK_ERR_INVALID_ARGS;
+ }
+
+ session = (struct mali_session_data*)args->ctx;
+ if (NULL == session)
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ mali_gp_scheduler_lock();
+
+ /* Make sure that the cookie returned by user space is the same as we provided in the first place */
+ if (args->cookie != slot.returned_cookie)
+ {
+ MALI_DEBUG_PRINT(2, ("Mali GP scheduler: Got an illegal cookie from user space, expected %u but got %u (job id)\n", slot.returned_cookie, args->cookie)) ;
+ mali_gp_scheduler_unlock();
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ mali_gp_scheduler_unlock();
+
+ switch (args->code)
+ {
+ case _MALIGP_JOB_RESUME_WITH_NEW_HEAP:
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1]));
+ mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]);
+ ret = _MALI_OSK_ERR_OK;
+ break;
+
+ case _MALIGP_JOB_ABORT:
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie));
+ mali_group_abort_gp_job(slot.group, args->cookie);
+ ret = _MALI_OSK_ERR_OK;
+ break;
+
+ default:
+ MALI_PRINT_ERROR(("Mali GP scheduler: Wrong suspend response from user space\n"));
+ ret = _MALI_OSK_ERR_FAULT;
+ break;
+ }
+
+ return ret;
+
+}
+
+void mali_gp_scheduler_abort_session(struct mali_session_data *session)
+{
+ struct mali_gp_job *job, *tmp;
+
+ mali_gp_scheduler_lock();
+ MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session));
+
+ /* Check queue for jobs and remove */
+ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list)
+ {
+ if (mali_gp_job_get_session(job) == session)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job));
+ _mali_osk_list_del(&(job->list));
+ mali_gp_job_delete(job);
+ }
+ }
+
+ mali_gp_scheduler_unlock();
+
+ /* Abort running jobs from this session. It is safe to do this outside
+ * the scheduler lock as there is only one GP core, and the queue has
+ * already been emptied, as long as there are no new jobs coming in
+ * from user space. */
+ mali_group_abort_session(slot.group, session);
+}
+
+static mali_bool mali_gp_scheduler_is_suspended(void)
+{
+ mali_bool ret;
+
+ mali_gp_scheduler_lock();
+ ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE;
+ mali_gp_scheduler_unlock();
+
+ return ret;
+}
+
+
+#if MALI_STATE_TRACKING
+u32 mali_gp_scheduler_dump_state(char *buf, u32 size)
+{
+ int n = 0;
+
+ n += _mali_osk_snprintf(buf + n, size - n, "GP\n");
+ n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty");
+
+ n += mali_group_dump_state(slot.group, buf + n, size - n);
+ n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", mali_group_gp_state(slot.group));
+ n += _mali_osk_snprintf(buf + n, size - n, "\n");
+
+ return n;
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h
new file mode 100644
index 0000000..ef58509
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef __MALI_GP_SCHEDULER_H__
+#define __MALI_GP_SCHEDULER_H__
+
+#include "mali_osk.h"
+#include "mali_cluster.h"
+#include "mali_gp_job.h"
+
+_mali_osk_errcode_t mali_gp_scheduler_initialize(void);
+void mali_gp_scheduler_terminate(void);
+
+void mali_gp_scheduler_do_schedule(void);
+void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success);
+void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job);
+void mali_gp_scheduler_abort_session(struct mali_session_data *session);
+u32 mali_gp_scheduler_dump_state(char *buf, u32 size);
+
+void mali_gp_scheduler_suspend(void);
+void mali_gp_scheduler_resume(void);
+
+#endif /* __MALI_GP_SCHEDULER_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_group.c b/drivers/media/video/samsung/mali/common/mali_group.c
new file mode 100644
index 0000000..9202bc1
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_group.c
@@ -0,0 +1,841 @@
+/*
+ * 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_group.h"
+#include "mali_osk.h"
+#include "mali_cluster.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_mmu.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_pm.h"
+
+/*
+ * The group object is the most important object in the device driver,
+ * and acts as the center of many HW operations.
+ * The reason for this is that operations on the MMU will affect all
+ * cores connected to this MMU (a group is defined by the MMU and the
+ * cores which are connected to this).
+ * The group lock is thus the most important lock, followed by the
+ * GP and PP scheduler locks. They must be taken in the following
+ * order:
+ * GP/PP lock first, then group lock(s).
+ */
+
+/**
+ * The structure represents a render group
+ * A render group is defined by all the cores that share the same Mali MMU
+ */
+
+struct mali_group
+{
+ struct mali_cluster *cluster;
+
+ struct mali_mmu_core *mmu;
+ struct mali_session_data *session;
+ int page_dir_ref_count;
+ mali_bool power_is_on;
+#if defined(USING_MALI200)
+ mali_bool pagedir_activation_failed;
+#endif
+
+ struct mali_gp_core *gp_core;
+ enum mali_group_core_state gp_state;
+ struct mali_gp_job *gp_running_job;
+
+ struct mali_pp_core *pp_core;
+ enum mali_group_core_state pp_state;
+ struct mali_pp_job *pp_running_job;
+ u32 pp_running_sub_job;
+
+ _mali_osk_lock_t *lock;
+};
+
+static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS];
+static u32 mali_global_num_groups = 0;
+
+enum mali_group_activate_pd_status
+{
+ MALI_GROUP_ACTIVATE_PD_STATUS_FAILED,
+ MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD,
+ MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD,
+};
+
+/* local helper functions */
+static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session);
+static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session);
+static void mali_group_recovery_reset(struct mali_group *group);
+static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success);
+
+void mali_group_lock(struct mali_group *group)
+{
+ if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW))
+ {
+ /* Non-interruptable lock failed: this should never happen. */
+ MALI_DEBUG_ASSERT(0);
+ }
+ MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group));
+}
+
+void mali_group_unlock(struct mali_group *group)
+{
+ MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group));
+ _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+#ifdef DEBUG
+void mali_group_assert_locked(struct mali_group *group)
+{
+ MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
+}
+#endif
+
+
+struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu)
+{
+ struct mali_group *group = NULL;
+
+ if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS)
+ {
+ MALI_PRINT_ERROR(("Mali group: Too many group objects created\n"));
+ return NULL;
+ }
+
+ group = _mali_osk_malloc(sizeof(struct mali_group));
+ if (NULL != group)
+ {
+ _mali_osk_memset(group, 0, sizeof(struct mali_group));
+ group->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_GROUP);
+ if (NULL != group->lock)
+ {
+ group->cluster = cluster;
+ group->mmu = mmu; /* This group object now owns the MMU object */
+ group->session = NULL;
+ group->page_dir_ref_count = 0;
+ group->power_is_on = MALI_TRUE;
+
+ group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
+ group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
+#if defined(USING_MALI200)
+ group->pagedir_activation_failed = MALI_FALSE;
+#endif
+ mali_global_groups[mali_global_num_groups] = group;
+ mali_global_num_groups++;
+
+ return group;
+ }
+ _mali_osk_free(group);
+ }
+
+ return NULL;
+}
+
+void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core)
+{
+ /* This group object now owns the GP core object */
+ group->gp_core = gp_core;
+}
+
+void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core)
+{
+ /* This group object now owns the PP core object */
+ group->pp_core = pp_core;
+}
+
+void mali_group_delete(struct mali_group *group)
+{
+ u32 i;
+
+ /* Delete the resources that this group owns */
+ if (NULL != group->gp_core)
+ {
+ mali_gp_delete(group->gp_core);
+ }
+
+ if (NULL != group->pp_core)
+ {
+ mali_pp_delete(group->pp_core);
+ }
+
+ if (NULL != group->mmu)
+ {
+ mali_mmu_delete(group->mmu);
+ }
+
+ for (i = 0; i < mali_global_num_groups; i++)
+ {
+ if (mali_global_groups[i] == group)
+ {
+ mali_global_groups[i] = NULL;
+ mali_global_num_groups--;
+ break;
+ }
+ }
+
+ _mali_osk_lock_term(group->lock);
+
+ _mali_osk_free(group);
+}
+
+/* Called from mali_cluster_reset() when the system is re-turned on */
+void mali_group_reset(struct mali_group *group)
+{
+ mali_group_lock(group);
+
+ group->session = NULL;
+
+ if (NULL != group->mmu)
+ {
+ mali_mmu_reset(group->mmu);
+ }
+
+ if (NULL != group->gp_core)
+ {
+ mali_gp_reset(group->gp_core);
+ }
+
+ if (NULL != group->pp_core)
+ {
+ mali_pp_reset(group->pp_core);
+ }
+
+ mali_group_unlock(group);
+}
+
+struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group)
+{
+ return group->gp_core;
+}
+
+struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group)
+{
+ return group->pp_core;
+}
+
+_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job)
+{
+ struct mali_session_data *session;
+ enum mali_group_activate_pd_status activate_status;
+
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
+
+ mali_pm_core_event(MALI_CORE_EVENT_GP_START);
+
+ session = mali_gp_job_get_session(job);
+
+ mali_group_lock(group);
+
+ mali_cluster_l2_cache_invalidate_all(group->cluster, mali_gp_job_get_id(job));
+
+ activate_status = mali_group_activate_page_directory(group, session);
+ if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
+ {
+ /* if session is NOT kept Zapping is done as part of session switch */
+ if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status)
+ {
+ mali_mmu_zap_tlb_without_stall(group->mmu);
+ }
+ mali_gp_job_start(group->gp_core, job);
+ group->gp_running_job = job;
+ group->gp_state = MALI_GROUP_CORE_STATE_WORKING;
+
+ mali_group_unlock(group);
+
+ return _MALI_OSK_ERR_OK;
+ }
+
+#if defined(USING_MALI200)
+ group->pagedir_activation_failed = MALI_TRUE;
+#endif
+
+ mali_group_unlock(group);
+
+ mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_GP_START */
+ return _MALI_OSK_ERR_FAULT;
+}
+
+_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job)
+{
+ struct mali_session_data *session;
+ enum mali_group_activate_pd_status activate_status;
+
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
+
+ mali_pm_core_event(MALI_CORE_EVENT_PP_START);
+
+ session = mali_pp_job_get_session(job);
+
+ mali_group_lock(group);
+
+ mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job));
+
+ activate_status = mali_group_activate_page_directory(group, session);
+ if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
+ {
+ /* if session is NOT kept Zapping is done as part of session switch */
+ if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status)
+ {
+ MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n"));
+ mali_mmu_zap_tlb_without_stall(group->mmu);
+ }
+ mali_pp_job_start(group->pp_core, job, sub_job);
+ group->pp_running_job = job;
+ group->pp_running_sub_job = sub_job;
+ group->pp_state = MALI_GROUP_CORE_STATE_WORKING;
+
+ mali_group_unlock(group);
+
+ return _MALI_OSK_ERR_OK;
+ }
+
+#if defined(USING_MALI200)
+ group->pagedir_activation_failed = MALI_TRUE;
+#endif
+
+ mali_group_unlock(group);
+
+ mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_PP_START */
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr)
+{
+ mali_group_lock(group);
+
+ if (group->gp_state != MALI_GROUP_CORE_STATE_OOM ||
+ mali_gp_job_get_id(group->gp_running_job) != job_id)
+ {
+ mali_group_unlock(group);
+ return; /* Illegal request or job has already been aborted */
+ }
+
+ mali_cluster_l2_cache_invalidate_all_force(group->cluster);
+ mali_mmu_zap_tlb_without_stall(group->mmu);
+
+ mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr);
+ group->gp_state = MALI_GROUP_CORE_STATE_WORKING;
+
+ mali_group_unlock(group);
+}
+
+void mali_group_abort_gp_job(struct mali_group *group, u32 job_id)
+{
+ mali_group_lock(group);
+
+ if (group->gp_state == MALI_GROUP_CORE_STATE_IDLE ||
+ mali_gp_job_get_id(group->gp_running_job) != job_id)
+ {
+ mali_group_unlock(group);
+ return; /* No need to cancel or job has already been aborted or completed */
+ }
+
+ mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* Will release group lock */
+}
+
+void mali_group_abort_pp_job(struct mali_group *group, u32 job_id)
+{
+ mali_group_lock(group);
+
+ if (group->pp_state == MALI_GROUP_CORE_STATE_IDLE ||
+ mali_pp_job_get_id(group->pp_running_job) != job_id)
+ {
+ mali_group_unlock(group);
+ return; /* No need to cancel or job has already been aborted or completed */
+ }
+
+ mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* Will release group lock */
+}
+
+void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session)
+{
+ struct mali_gp_job *gp_job;
+ struct mali_pp_job *pp_job;
+ u32 gp_job_id = 0;
+ u32 pp_job_id = 0;
+ mali_bool abort_pp = MALI_FALSE;
+ mali_bool abort_gp = MALI_FALSE;
+
+ mali_group_lock(group);
+
+ gp_job = group->gp_running_job;
+ pp_job = group->pp_running_job;
+
+ if (gp_job && mali_gp_job_get_session(gp_job) == session)
+ {
+ MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session));
+
+ gp_job_id = mali_gp_job_get_id(gp_job);
+ abort_gp = MALI_TRUE;
+ }
+
+ if (pp_job && mali_pp_job_get_session(pp_job) == session)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session));
+
+ pp_job_id = mali_pp_job_get_id(pp_job);
+ abort_pp = MALI_TRUE;
+ }
+
+ mali_group_unlock(group);
+
+ /* These functions takes and releases the group lock */
+ if (0 != abort_gp)
+ {
+ mali_group_abort_gp_job(group, gp_job_id);
+ }
+ if (0 != abort_pp)
+ {
+ mali_group_abort_pp_job(group, pp_job_id);
+ }
+
+ mali_group_lock(group);
+ mali_group_remove_session_if_unused(group, session);
+ mali_group_unlock(group);
+}
+
+enum mali_group_core_state mali_group_gp_state(struct mali_group *group)
+{
+ return group->gp_state;
+}
+
+enum mali_group_core_state mali_group_pp_state(struct mali_group *group)
+{
+ return group->pp_state;
+}
+
+/* group lock need to be taken before calling mali_group_bottom_half */
+void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event)
+{
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+ switch (event)
+ {
+ case GROUP_EVENT_PP_JOB_COMPLETED:
+ mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_TRUE); /* PP job SUCCESS */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ case GROUP_EVENT_PP_JOB_FAILED:
+ mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job FAIL */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ case GROUP_EVENT_PP_JOB_TIMED_OUT:
+ mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job TIMEOUT */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ case GROUP_EVENT_GP_JOB_COMPLETED:
+ mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_TRUE); /* GP job SUCCESS */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ case GROUP_EVENT_GP_JOB_FAILED:
+ mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job FAIL */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ case GROUP_EVENT_GP_JOB_TIMED_OUT:
+ mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job TIMEOUT */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ case GROUP_EVENT_GP_OOM:
+ group->gp_state = MALI_GROUP_CORE_STATE_OOM;
+ mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */
+ mali_gp_scheduler_oom(group, group->gp_running_job);
+ break;
+ case GROUP_EVENT_MMU_PAGE_FAULT:
+ mali_group_complete_jobs(group, MALI_TRUE, MALI_TRUE, MALI_FALSE); /* GP and PP job FAIL */
+ /* group lock is released by mali_group_complete_jobs() call above */
+ break;
+ default:
+ break;
+ }
+}
+
+struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group)
+{
+ return group->mmu;
+}
+
+struct mali_session_data *mali_group_get_session(struct mali_group *group)
+{
+ return group->session;
+}
+
+struct mali_group *mali_group_get_glob_group(u32 index)
+{
+ if(mali_global_num_groups > index)
+ {
+ return mali_global_groups[index];
+ }
+
+ return NULL;
+}
+
+u32 mali_group_get_glob_num_groups(void)
+{
+ return mali_global_num_groups;
+}
+
+/* Used to check if scheduler for the other core type needs to be called on job completion.
+ *
+ * Used only for Mali-200, where job start may fail if the only MMU is busy
+ * with another session's address space.
+ */
+static inline mali_bool mali_group_other_reschedule_needed(struct mali_group *group)
+{
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+#if defined(USING_MALI200)
+ if (group->pagedir_activation_failed)
+ {
+ group->pagedir_activation_failed = MALI_FALSE;
+ return MALI_TRUE;
+ }
+ else
+#endif
+ {
+ return MALI_FALSE;
+ }
+}
+
+static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session)
+{
+ enum mali_group_activate_pd_status retval;
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+ MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group));
+ MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count);
+
+ if (0 != group->page_dir_ref_count)
+ {
+ if (group->session != session)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session));
+ return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count));
+ retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD;
+
+ }
+ }
+ else
+ {
+ /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */
+ if (group->session != session)
+ {
+ mali_bool activate_success;
+ MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count));
+
+ activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session));
+ MALI_DEBUG_ASSERT(activate_success);
+ if ( MALI_FALSE== activate_success ) return MALI_FALSE;
+ group->session = session;
+ retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD;
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count));
+ retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD;
+ }
+ }
+
+ group->page_dir_ref_count++;
+ return retval;
+}
+
+static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session)
+{
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+ MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count);
+ MALI_DEBUG_ASSERT(session == group->session);
+
+ group->page_dir_ref_count--;
+
+ /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count),
+ and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */
+ MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count);
+}
+
+void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session)
+{
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+ if (0 == group->page_dir_ref_count)
+ {
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
+
+ if (group->session == session)
+ {
+ MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on);
+ MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group));
+ mali_mmu_activate_empty_page_directory(group->mmu);
+ group->session = NULL;
+ }
+ }
+}
+
+void mali_group_power_on(void)
+{
+ int i;
+ for (i = 0; i < mali_global_num_groups; i++)
+ {
+ struct mali_group *group = mali_global_groups[i];
+ mali_group_lock(group);
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
+ MALI_DEBUG_ASSERT_POINTER(group->cluster);
+ group->power_is_on = MALI_TRUE;
+ mali_cluster_power_is_enabled_set(group->cluster, MALI_TRUE);
+ mali_group_unlock(group);
+ }
+ MALI_DEBUG_PRINT(3,("group: POWER ON\n"));
+}
+
+mali_bool mali_group_power_is_on(struct mali_group *group)
+{
+ MALI_ASSERT_GROUP_LOCKED(group);
+ return group->power_is_on;
+}
+
+void mali_group_power_off(void)
+{
+ int i;
+ /* It is necessary to set group->session = NULL; so that the powered off MMU is not written to on map /unmap */
+ /* It is necessary to set group->power_is_on=MALI_FALSE so that pending bottom_halves does not access powered off cores. */
+ for (i = 0; i < mali_global_num_groups; i++)
+ {
+ struct mali_group *group = mali_global_groups[i];
+ mali_group_lock(group);
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
+ MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
+ MALI_DEBUG_ASSERT_POINTER(group->cluster);
+ group->session = NULL;
+ MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on);
+ group->power_is_on = MALI_FALSE;
+ mali_cluster_power_is_enabled_set(group->cluster, MALI_FALSE);
+ mali_group_unlock(group);
+ }
+ MALI_DEBUG_PRINT(3,("group: POWER OFF\n"));
+}
+
+
+static void mali_group_recovery_reset(struct mali_group *group)
+{
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+ /* Stop cores, bus stop */
+ if (NULL != group->pp_core)
+ {
+ mali_pp_stop_bus(group->pp_core);
+ }
+ if (NULL != group->gp_core)
+ {
+ mali_gp_stop_bus(group->gp_core);
+ }
+
+ /* Flush MMU */
+ mali_mmu_activate_fault_flush_page_directory(group->mmu);
+ mali_mmu_page_fault_done(group->mmu);
+
+ /* Wait for cores to stop bus */
+ if (NULL != group->pp_core)
+ {
+ mali_pp_stop_bus_wait(group->pp_core);
+ }
+ if (NULL != group->gp_core)
+ {
+ mali_gp_stop_bus_wait(group->gp_core);
+ }
+
+ /* Reset cores */
+ if (NULL != group->pp_core)
+ {
+ mali_pp_hard_reset(group->pp_core);
+ }
+ if (NULL != group->gp_core)
+ {
+ mali_gp_hard_reset(group->gp_core);
+ }
+
+ /* Reset MMU */
+ mali_mmu_reset(group->mmu);
+ group->session = NULL;
+}
+
+/* Group lock need to be taken before calling mali_group_complete_jobs. Will release the lock here. */
+static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success)
+{
+ mali_bool need_group_reset = MALI_FALSE;
+ mali_bool gp_success = success;
+ mali_bool pp_success = success;
+
+ MALI_ASSERT_GROUP_LOCKED(group);
+
+ if (complete_gp && !complete_pp)
+ {
+ MALI_DEBUG_ASSERT_POINTER(group->gp_core);
+ if (_MALI_OSK_ERR_OK == mali_gp_reset(group->gp_core))
+ {
+ struct mali_gp_job *gp_job_to_return = group->gp_running_job;
+ group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
+ group->gp_running_job = NULL;
+
+ MALI_DEBUG_ASSERT_POINTER(gp_job_to_return);
+
+ mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return));
+
+ if(mali_group_other_reschedule_needed(group))
+ {
+ mali_group_unlock(group);
+ mali_pp_scheduler_do_schedule();
+ }
+ else
+ {
+ mali_group_unlock(group);
+ }
+
+ mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success);
+ mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
+
+ return;
+ }
+ else
+ {
+ need_group_reset = MALI_TRUE;
+ MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n"));
+ pp_success = MALI_FALSE; /* This might kill PP as well, so this should fail */
+ }
+ }
+ if (complete_pp && !complete_gp)
+ {
+ MALI_DEBUG_ASSERT_POINTER(group->pp_core);
+ if (_MALI_OSK_ERR_OK == mali_pp_reset(group->pp_core))
+ {
+ struct mali_pp_job *pp_job_to_return = group->pp_running_job;
+ u32 pp_sub_job_to_return = group->pp_running_sub_job;
+ group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
+ group->pp_running_job = NULL;
+
+ MALI_DEBUG_ASSERT_POINTER(pp_job_to_return);
+
+ mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return));
+
+ if(mali_group_other_reschedule_needed(group))
+ {
+ mali_group_unlock(group);
+ mali_gp_scheduler_do_schedule();
+ }
+ else
+ {
+ mali_group_unlock(group);
+ }
+
+ mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success);
+ mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
+
+ return;
+ }
+ else
+ {
+ need_group_reset = MALI_TRUE;
+ MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n"));
+ gp_success = MALI_FALSE; /* This might kill GP as well, so this should fail */
+ }
+ }
+ else if (complete_gp && complete_pp)
+ {
+ need_group_reset = MALI_TRUE;
+ }
+
+ if (MALI_TRUE == need_group_reset)
+ {
+ struct mali_gp_job *gp_job_to_return = group->gp_running_job;
+ struct mali_pp_job *pp_job_to_return = group->pp_running_job;
+ u32 pp_sub_job_to_return = group->pp_running_sub_job;
+ mali_bool schedule_other = MALI_FALSE;
+
+ MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n"));
+
+ group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
+ group->gp_running_job = NULL;
+ if (NULL != gp_job_to_return)
+ {
+ mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return));
+ }
+
+ group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
+ group->pp_running_job = NULL;
+ if (NULL != pp_job_to_return)
+ {
+ mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return));
+ }
+
+ /* The reset has to be done after mali_group_deactivate_page_directory() */
+ mali_group_recovery_reset(group);
+
+ if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return))
+ {
+ schedule_other = MALI_TRUE;
+ }
+
+ mali_group_unlock(group);
+
+ if (NULL != gp_job_to_return)
+ {
+ mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success);
+ mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
+ }
+ else if (schedule_other)
+ {
+ mali_pp_scheduler_do_schedule();
+ }
+
+ if (NULL != pp_job_to_return)
+ {
+ mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success);
+ mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
+ }
+ else if (schedule_other)
+ {
+ mali_gp_scheduler_do_schedule();
+ }
+
+ return;
+ }
+
+ mali_group_unlock(group);
+}
+
+#if MALI_STATE_TRACKING
+u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size)
+{
+ int n = 0;
+
+ n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group);
+ if (group->gp_core)
+ {
+ n += mali_gp_dump_state(group->gp_core, buf + n, size - n);
+ n += _mali_osk_snprintf(buf + n, size - n, "\tGP state: %d\n", group->gp_state);
+ n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job);
+ }
+ if (group->pp_core)
+ {
+ n += mali_pp_dump_state(group->pp_core, buf + n, size - n);
+ n += _mali_osk_snprintf(buf + n, size - n, "\tPP state: %d\n", group->pp_state);
+ n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n",
+ group->pp_running_job, group->pp_running_sub_job);
+ }
+
+ return n;
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_group.h b/drivers/media/video/samsung/mali/common/mali_group.h
new file mode 100644
index 0000000..3533d13
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_group.h
@@ -0,0 +1,146 @@
+/*
+ * 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_GROUP_H__
+#define __MALI_GROUP_H__
+
+#include "linux/jiffies.h"
+#include "mali_osk.h"
+#include "mali_cluster.h"
+#include "mali_mmu.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_session.h"
+
+/* max runtime [ms] for a core job - used by timeout timers */
+#define MAX_RUNTIME 5000
+/** @brief A mali group object represents a MMU and a PP and/or a GP core.
+ *
+ */
+#define MALI_MAX_NUMBER_OF_GROUPS 9
+
+struct mali_group;
+
+enum mali_group_event_t
+{
+ GROUP_EVENT_PP_JOB_COMPLETED, /**< PP job completed successfully */
+ GROUP_EVENT_PP_JOB_FAILED, /**< PP job completed with failure */
+ GROUP_EVENT_PP_JOB_TIMED_OUT, /**< PP job reached max runtime */
+ GROUP_EVENT_GP_JOB_COMPLETED, /**< GP job completed successfully */
+ GROUP_EVENT_GP_JOB_FAILED, /**< GP job completed with failure */
+ GROUP_EVENT_GP_JOB_TIMED_OUT, /**< GP job reached max runtime */
+ GROUP_EVENT_GP_OOM, /**< GP job ran out of heap memory */
+ GROUP_EVENT_MMU_PAGE_FAULT, /**< MMU page fault */
+};
+
+enum mali_group_core_state
+{
+ MALI_GROUP_CORE_STATE_IDLE,
+ MALI_GROUP_CORE_STATE_WORKING,
+ MALI_GROUP_CORE_STATE_OOM
+};
+
+/** @brief Create a new Mali group object
+ *
+ * @param cluster Pointer to the cluster to which the group is connected.
+ * @param mmu Pointer to the MMU that defines this group
+ * @return A pointer to a new group object
+ */
+struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu);
+void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core);
+void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core);
+void mali_group_delete(struct mali_group *group);
+
+/** @brief Reset group
+ *
+ * This function will reset the entire group, including all the cores present in the group.
+ *
+ * @param group Pointer to the group to reset
+ */
+void mali_group_reset(struct mali_group *group);
+
+/** @brief Get pointer to GP core object
+ */
+struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group);
+
+/** @brief Get pointer to PP core object
+ */
+struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group);
+
+/** @brief Lock group object
+ *
+ * Most group functions will lock the group object themselves. The expection is
+ * the group_bottom_half which requires the group to be locked on entry.
+ *
+ * @param group Pointer to group to lock
+ */
+void mali_group_lock(struct mali_group *group);
+
+/** @brief Unlock group object
+ *
+ * @param group Pointer to group to unlock
+ */
+void mali_group_unlock(struct mali_group *group);
+#ifdef DEBUG
+void mali_group_assert_locked(struct mali_group *group);
+#define MALI_ASSERT_GROUP_LOCKED(group) mali_group_assert_locked(group)
+#else
+#define MALI_ASSERT_GROUP_LOCKED(group)
+#endif
+
+/** @brief Start GP job
+ */
+_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job);
+/** @brief Start fragment of PP job
+ */
+_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job);
+
+/** @brief Resume GP job that suspended waiting for more heap memory
+ */
+void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr);
+/** @brief Abort GP job
+ *
+ * Used to abort suspended OOM jobs when user space failed to allocte more memory.
+ */
+void mali_group_abort_gp_job(struct mali_group *group, u32 job_id);
+/** @brief Abort all GP jobs from \a session
+ *
+ * Used on session close when terminating all running and queued jobs from \a session.
+ */
+void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session);
+
+enum mali_group_core_state mali_group_gp_state(struct mali_group *group);
+enum mali_group_core_state mali_group_pp_state(struct mali_group *group);
+
+/** @brief The common group bottom half interrupt handler
+ *
+ * This is only called from the GP and PP bottom halves.
+ *
+ * The action taken is dictated by the \a event.
+ *
+ * @param event The event code
+ */
+void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event);
+
+struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group);
+struct mali_session_data *mali_group_get_session(struct mali_group *group);
+
+void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session_data);
+
+void mali_group_power_on(void);
+void mali_group_power_off(void);
+mali_bool mali_group_power_is_on(struct mali_group *group);
+
+struct mali_group *mali_group_get_glob_group(u32 index);
+u32 mali_group_get_glob_num_groups(void);
+
+u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size);
+
+#endif /* __MALI_GROUP_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.c b/drivers/media/video/samsung/mali/common/mali_hw_core.c
new file mode 100644
index 0000000..0b08622
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_hw_core.c
@@ -0,0 +1,46 @@
+/*
+ * 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_hw_core.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size)
+{
+ core->phys_addr = resource->base;
+ core->description = resource->description;
+ core->size = reg_size;
+ if (_MALI_OSK_ERR_OK == _mali_osk_mem_reqregion(core->phys_addr, core->size, core->description))
+ {
+ core->mapped_registers = _mali_osk_mem_mapioregion(core->phys_addr, core->size, core->description);
+ if (NULL != core->mapped_registers)
+ {
+ return _MALI_OSK_ERR_OK;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to map memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr));
+ }
+ _mali_osk_mem_unreqregion(core->phys_addr, core->size);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to request memory region for core %s at phys_addr 0x%08X\n", core->description, core->phys_addr));
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_hw_core_delete(struct mali_hw_core *core)
+{
+ _mali_osk_mem_unmapioregion(core->phys_addr, core->size, core->mapped_registers);
+ core->mapped_registers = NULL;
+ _mali_osk_mem_unreqregion(core->phys_addr, core->size);
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.h b/drivers/media/video/samsung/mali/common/mali_hw_core.h
new file mode 100644
index 0000000..c797804
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_hw_core.h
@@ -0,0 +1,71 @@
+/*
+ * 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_HW_CORE_H__
+#define __MALI_HW_CORE_H__
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+/**
+ * The common parts for all Mali HW cores (GP, PP, MMU, L2 and PMU)
+ * This struct is embedded inside all core specific structs.
+ */
+struct mali_hw_core
+{
+ u32 phys_addr; /**< Physical address of the registers */
+ u32 size; /**< Size of registers */
+ mali_io_address mapped_registers; /**< Virtual mapping of the registers */
+ const char* description; /**< Name of unit (as specified in device configuration) */
+};
+
+#define MALI_HW_CORE_NO_COUNTER ((u32)-1)
+#define MALI_HW_CORE_INVALID_VALUE ((u32)-1)
+
+_mali_osk_errcode_t mali_hw_core_create(struct mali_hw_core *core, const _mali_osk_resource_t *resource, u32 reg_size);
+void mali_hw_core_delete(struct mali_hw_core *core);
+
+MALI_STATIC_INLINE u32 mali_hw_core_register_read(struct mali_hw_core *core, u32 relative_address)
+{
+ u32 read_val;
+ read_val = _mali_osk_mem_ioread32(core->mapped_registers, relative_address);
+ MALI_DEBUG_PRINT(6, ("register_read for core %s, relative addr=0x%04X, val=0x%08X\n",
+ core->description, relative_address, read_val));
+ return read_val;
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core *core, u32 relative_address, u32 new_val)
+{
+ MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n",
+ core->description, relative_address, new_val));
+ _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val);
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val)
+{
+ MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n",
+ core->description, relative_address, new_val));
+ _mali_osk_mem_iowrite32(core->mapped_registers, relative_address, new_val);
+}
+
+MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs)
+{
+ u32 i;
+ MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n",
+ core->description,relative_address, nr_of_regs));
+
+ /* Do not use burst writes against the registers */
+ for (i = 0; i< nr_of_regs; i++)
+ {
+ mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]);
+ }
+}
+
+#endif /* __MALI_HW_CORE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_GP2.c b/drivers/media/video/samsung/mali/common/mali_kernel_GP2.c
deleted file mode 100644
index cfd70f4..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_GP2.c
+++ /dev/null
@@ -1,1493 +0,0 @@
-/*
- * 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.
- */
-//added for SPI
-#include <linux/kernel.h>
-
-#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_kernel_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 */
- NULL, /*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_TRACEPOINTS_ENABLED
- jobgp->user_input.perf_counter_flag = 0;
-
- if( counter_table[7] != 0xFFFFFFFF ) {
- jobgp->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE;
- jobgp->user_input.perf_counter_src0 = counter_table[7];
- }
- if( counter_table[8] != 0xFFFFFFFF ) {
- jobgp->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE;
- jobgp->user_input.perf_counter_src1 = counter_table[8];
- }
-#endif
-
- /* 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();
-
- pr_debug("SPI_GPU_GP Start\n");
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_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_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);
-
- MALI_DEBUG_PRINT(5, ("Mali GP: IRQ: %04x\n", irq_readout)) ;
-
- 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_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_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- _mali_profiling_add_counter(7, jobgp->perf_counter0);
- _mali_profiling_add_counter(8, jobgp->perf_counter1);
-#endif
- }
-
-#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_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_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- _mali_profiling_add_counter(7, jobgp->perf_counter0);
- _mali_profiling_add_counter(8, jobgp->perf_counter1);
-#endif
- }
-
-#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_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
- pr_debug("SPI_GPU_GP Idle\n");
- 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_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_PRINT( ("Mali GP: SW-Timeout.\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
- MALI_PANIC("%s Watchdog timeout\n", MALI_GP_SUBSYSTEM_NAME);
- 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_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_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_PRINT( ("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_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/media/video/samsung/mali/common/mali_kernel_MALI200.c b/drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c
deleted file mode 100644
index 0f5ebd0..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_MALI200.c
+++ /dev/null
@@ -1,1304 +0,0 @@
-/*
- * 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.
- */
-
-//added for SPI
-#include <linux/kernel.h>
-
-#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_kernel_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 */
- NULL, /*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_TRACEPOINTS_ENABLED
- {
- int counter = ((core->core_number)*2)+9; /* magic numbers for FP0 are 9 & 10 */
-
- //printk("FP core->number = %d\n", core->core_number);
- //TODO we are using magic numbers again... these are from gator_events_mali.c
- job200->user_input.perf_counter_flag = 0;
-
- if( counter>=9 && counter<=16) {
-
- if( counter_table[counter] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE;
- job200->user_input.perf_counter_src0 = counter_table[counter];
- }
- if( counter_table[counter+1] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE;
- job200->user_input.perf_counter_src1 = counter_table[counter+1];
- }
-
- } else {
- MALI_DEBUG_PRINT(2, ("core->core_number out of the range (0-3) (%d)\n", core->core_number));
- }
- }
-#if defined(USING_MALI400_L2_CACHE)
- if( counter_table[5] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE | _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET;
- job200->user_input.perf_counter_l2_src0 = counter_table[5];
- }
- if( counter_table[6] != 0xFFFFFFFF ) {
- job200->user_input.perf_counter_flag |= _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE | _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET;
- job200->user_input.perf_counter_l2_src1 = counter_table[6];
- }
-#endif
-#endif
-
- /* 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();
-
-
- pr_debug("SPI_GPU_PP%u Start\n", core->core_number);
-#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 */
- }
-
- MALI_DEBUG_PRINT(5, ("Mali PP: subsystem_mali200_irq_handler_upper_half: %s\n", core->description)) ;
- 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_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_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- unsigned int counter = (core->core_number * 2) + 9;
-#endif
-
- 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_TRACEPOINTS_ENABLED
- _mali_profiling_add_counter(counter, job200->perf_counter0);
- _mali_profiling_add_counter(counter + 1, job200->perf_counter1);
-#endif
-
- }
-
-#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;
- }
-
-#if MALI_TRACEPOINTS_ENABLED
- //TODO magic numbers should come from mali_linux_trace.h instead
- _mali_profiling_add_counter(5, val0);
- _mali_profiling_add_counter(6, val1);
-#endif
- }
-#endif
-
- }
-
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_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, job200->perf_counter_l2_val1
-#else
- , 0, 0
-#endif
- );
-#endif
-
-
-#if MALI_STATE_TRACKING
- _mali_osk_atomic_inc(&job->session->jobs_ended);
-#endif
-
- pr_debug("SPI_GPU_PP%u Idle\n", core->core_number);
-
- 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_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_PRINT( ("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 */
-
- MALI_PANIC("%s Watchdog timeout (rawstat: 0x%x tile_addr: 0x%x status: 0x%x)\n", MALI_PP_SUBSYSTEM_NAME, irq_readout, current_tile_addr, core_status);
-
-#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_PRINT( ("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_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_PRINT( ("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_PRINT(("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/media/video/samsung/mali/common/mali_kernel_common.h b/drivers/media/video/samsung/mali/common/mali_kernel_common.h
index ab6f143..b354f92 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_common.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -28,7 +28,6 @@
#define MALI_PANIC(fmt, args...)
#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.
@@ -129,7 +128,9 @@
} while (0)
#ifdef DEBUG
+#ifndef mali_debug_level
extern int mali_debug_level;
+#endif
#define MALI_DEBUG_CODE(code) code
#define MALI_DEBUG_PRINT(level, args) do { \
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.c b/drivers/media/video/samsung/mali/common/mali_kernel_core.c
index be1889d..0155dfc 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_core.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,344 +8,805 @@
* 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_kernel_common.h"
+#include "mali_session.h"
#include "mali_osk.h"
#include "mali_osk_mali.h"
#include "mali_ukk.h"
#include "mali_kernel_core.h"
-#include "mali_kernel_rendercore.h"
-#if defined USING_MALI400_L2_CACHE
-#include "mali_kernel_l2_cache.h"
+#include "mali_memory.h"
+#include "mali_mem_validation.h"
+#include "mali_mmu.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_dlbu.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_cluster.h"
+#include "mali_group.h"
+#include "mali_pm.h"
+#include "mali_pmu.h"
+#include "mali_scheduler.h"
+#ifdef CONFIG_MALI400_GPU_UTILIZATION
+#include "mali_kernel_utilization.h"
+#endif
+#include "mali_l2_cache.h"
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.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;
+/** Start profiling from module load? */
+int mali_boot_profiling = 0;
+
/** 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_product_id_t global_product_id = _MALI_PRODUCT_ID_UNKNOWN;
+static u32 global_gpu_base_address = 0;
+static u32 global_gpu_major_version = 0;
+static u32 global_gpu_minor_version = 0;
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;
+/* 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;
+static u32 first_pp_offset = 0;
-#define INVALID_MEM 0xffffffff
+#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */
+#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */
-static _mali_mem_validation_t mem_validator = { INVALID_MEM, INVALID_MEM, -1 };
+/* timer related */
+int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
+int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT;
-static struct mali_kernel_subsystem mali_subsystem_core =
+static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset)
{
- 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
-};
+ int i;
+ u32 addr = global_gpu_base_address + offset;
-static struct mali_kernel_subsystem * subsystems[] =
-{
+ for (i = 0; i < num_resources; i++)
+ {
+ if (type == arch_configuration[i].type && arch_configuration[i].base == addr)
+ {
+ return &(arch_configuration[i]);
+ }
+ }
-#if USING_MALI_PMM
- /* The PMM must be initialized before any cores - including L2 cache */
- &mali_subsystem_pmm,
-#endif
+ return NULL;
+}
- /* always included */
- &mali_subsystem_memory,
+static u32 mali_count_resources(_mali_osk_resource_type_t type)
+{
+ int i;
+ u32 retval = 0;
- /* 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,
+ for (i = 0; i < num_resources; i++)
+ {
+ if (type == arch_configuration[i].type)
+ {
+ retval++;
+ }
+ }
- /* add reference to the subsystem */
- &mali_subsystem_mali200,
+ return retval;
+}
- /* add reference to the subsystem */
- &mali_subsystem_gp2,
-#if defined USING_MALI400_L2_CACHE
- &mali_subsystem_l2_cache,
-#endif
+static _mali_osk_errcode_t mali_parse_gpu_base_and_first_pp_offset_address(void)
+{
+ int i;
+ _mali_osk_resource_t *first_gp_resource = NULL;
+ _mali_osk_resource_t *first_pp_resource = NULL;
+
+ for (i = 0; i < num_resources; i++)
+ {
+ if (MALI_GP == arch_configuration[i].type)
+ {
+ if (NULL == first_gp_resource || first_gp_resource->base > arch_configuration[i].base)
+ {
+ first_gp_resource = &(arch_configuration[i]);
+ }
+ }
+ if (MALI_PP == arch_configuration[i].type)
+ {
+ if (NULL == first_pp_resource || first_pp_resource->base > arch_configuration[i].base)
+ {
+ first_pp_resource = &(arch_configuration[i]);
+ }
+ }
+ }
- /* always included */
- /* NOTE Keep the core entry at the tail of the list */
- &mali_subsystem_core
-};
+ if (NULL == first_gp_resource || NULL == first_pp_resource)
+ {
+ MALI_PRINT_ERROR(("No GP+PP core specified in config file\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
-#define SUBSYSTEMS_COUNT ( sizeof(subsystems) / sizeof(subsystems[0]) )
+ if (first_gp_resource->base < first_pp_resource->base)
+ {
+ /* GP is first, so we are dealing with Mali-300, Mali-400 or Mali-450 */
+ global_gpu_base_address = first_gp_resource->base;
+ first_pp_offset = 0x8000;
+ }
+ else
+ {
+ /* PP is first, so we are dealing with Mali-200 */
+ global_gpu_base_address = first_pp_resource->base;
+ first_pp_offset = 0x0;
+ }
+ MALI_SUCCESS;
+}
-/* Pointers to this type available as incomplete struct in mali_kernel_session_manager.h */
-struct mali_session_data
+static _mali_osk_errcode_t mali_parse_product_info(void)
{
- void * subsystem_data[SUBSYSTEMS_COUNT];
- _mali_osk_notification_queue_t * ioctl_queue;
-};
+ _mali_osk_resource_t *first_pp_resource = NULL;
-static mali_kernel_resource_registrator resource_handler[RESOURCE_TYPE_COUNT] = { NULL, };
+ /* Find the first PP core */
+ first_pp_resource = mali_find_resource(MALI_PP, first_pp_offset);
+ if (NULL != first_pp_resource)
+ {
+ /* Create a dummy PP object for this core so that we can read the version register */
+ struct mali_group *group = mali_group_create(NULL, NULL);
+ if (NULL != group)
+ {
+ /*struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group, 0);*/
+ struct mali_pp_core *pp_core = mali_pp_create(first_pp_resource, group);
+ if (NULL != pp_core)
+ {
+ u32 pp_version = mali_pp_core_get_version(pp_core);
+ mali_pp_delete(pp_core);
+ mali_group_delete(group);
+
+ global_gpu_major_version = (pp_version >> 8) & 0xFF;
+ global_gpu_minor_version = pp_version & 0xFF;
+
+ switch (pp_version >> 16)
+ {
+ case MALI200_PP_PRODUCT_ID:
+ global_product_id = _MALI_PRODUCT_ID_MALI200;
+ MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-200 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+ break;
+ case MALI300_PP_PRODUCT_ID:
+ global_product_id = _MALI_PRODUCT_ID_MALI300;
+ MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-300 r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+ break;
+ case MALI400_PP_PRODUCT_ID:
+ global_product_id = _MALI_PRODUCT_ID_MALI400;
+ MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-400 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+ break;
+ case MALI450_PP_PRODUCT_ID:
+ global_product_id = _MALI_PRODUCT_ID_MALI450;
+ MALI_DEBUG_PRINT(2, ("Found Mali GPU Mali-450 MP r%up%u\n", global_gpu_major_version, global_gpu_minor_version));
+ break;
+ default:
+ MALI_DEBUG_PRINT(2, ("Found unknown Mali GPU GPU (r%up%u)\n", global_gpu_major_version, global_gpu_minor_version));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to create initial PP object\n"));
+ }
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to create initial group object\n"));
+ }
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("First PP core not specified in config file\n"));
+ }
-/* 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;
+ return _MALI_OSK_ERR_FAULT;
+}
-/* is called from OS specific driver entry point */
-_mali_osk_errcode_t mali_kernel_constructor( void )
+static void mali_delete_clusters(void)
{
- _mali_osk_errcode_t err;
-
- err = mali_platform_init();
- if (_MALI_OSK_ERR_OK != err) goto error1;
+ u32 i;
+ u32 number_of_clusters = mali_cluster_get_glob_num_clusters();
- err = _mali_osk_init();
- if (_MALI_OSK_ERR_OK != err) goto error2;
+ for (i = 0; i < number_of_clusters; i++)
+ {
+ mali_cluster_delete(mali_cluster_get_global_cluster(i));
+ }
+}
- 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));
+static _mali_osk_errcode_t mali_create_cluster(_mali_osk_resource_t *resource)
+{
+ if (NULL != resource)
+ {
+ struct mali_l2_cache_core *l2_cache;
- err = initialize_subsystems();
- if (_MALI_OSK_ERR_OK != err) goto error3;
+ if (mali_l2_cache_core_get_glob_num_l2_cores() >= mali_l2_cache_core_get_max_num_l2_cores())
+ {
+ MALI_PRINT_ERROR(("Found too many L2 cache core objects, max %u is supported\n", mali_l2_cache_core_get_max_num_l2_cores()));
+ return _MALI_OSK_ERR_FAULT;
+ }
- MALI_PRINT(("Mali device driver %s loaded\n", SVN_REV_STRING));
+ MALI_DEBUG_PRINT(3, ("Found L2 cache %s, starting new cluster\n", resource->description));
- MALI_SUCCESS;
+ /*l2_cache = mali_l2_cache_create(resource, global_num_l2_cache_cores);*/
+ l2_cache = mali_l2_cache_create(resource);
+ if (NULL == l2_cache)
+ {
+ MALI_PRINT_ERROR(("Failed to create L2 cache object\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
-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())
+ if (NULL == mali_cluster_create(l2_cache))
+ {
+ MALI_PRINT_ERROR(("Failed to create cluster object\n"));
+ mali_l2_cache_delete(l2_cache);
+ return _MALI_OSK_ERR_FAULT;
+ }
+ }
+ else
{
- MALI_PRINT(("Failed to deinit platform\n"));
+ mali_cluster_create(NULL);
+ if (NULL == mali_cluster_get_global_cluster(0))
+ {
+ MALI_PRINT_ERROR(("Failed to create cluster object\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
}
-error1:
- MALI_PRINT(("Failed to init platform\n"));
- MALI_ERROR(err);
+
+ MALI_DEBUG_PRINT(3, ("Created cluster object\n"));
+ return _MALI_OSK_ERR_OK;
}
-/* is called from OS specific driver exit point */
-void mali_kernel_destructor( void )
+static _mali_osk_errcode_t mali_parse_config_cluster(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())
+ if (_MALI_PRODUCT_ID_MALI200 == global_product_id)
{
- MALI_PRINT(("Failed to deinit platform\n"));
+ /* Create dummy cluster without L2 cache */
+ return mali_create_cluster(NULL);
}
- MALI_DEBUG_PRINT(2, ("Module unloaded.\n"));
-}
+ else if (_MALI_PRODUCT_ID_MALI300 == global_product_id || _MALI_PRODUCT_ID_MALI400 == global_product_id)
+ {
+ _mali_osk_resource_t *l2_resource = mali_find_resource(MALI_L2, 0x1000);
+ if (NULL == l2_resource)
+ {
+ MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache in config file\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
-_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))
+ return mali_create_cluster(l2_resource);
+ }
+ else if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
+ {
+ /*
+ * L2 for GP at 0x10000
+ * L2 for PP0-3 at 0x01000
+ * L2 for PP4-7 at 0x11000 (optional)
+ */
+
+ _mali_osk_resource_t *l2_gp_resource;
+ _mali_osk_resource_t *l2_pp_grp0_resource;
+ _mali_osk_resource_t *l2_pp_grp1_resource;
+
+ /* Make cluster for GP's L2 */
+ l2_gp_resource = mali_find_resource(MALI_L2, 0x10000);
+ if (NULL != l2_gp_resource)
+ {
+ _mali_osk_errcode_t ret;
+ MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for GP\n"));
+ ret = mali_create_cluster(l2_gp_resource);
+ if (_MALI_OSK_ERR_OK != ret)
{
- _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));
+ return ret;
}
- is_pmu_first_resource = 0;
-#endif /* USING_MALI_PMM */
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for GP in config file\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
- MALI_CHECK_NO_ERROR(resource_handler[arch_resource->type](arch_resource));
- /* the subsystem shutdown process will release all the resources already registered */
+ /* Make cluster for first PP core group */
+ l2_pp_grp0_resource = mali_find_resource(MALI_L2, 0x1000);
+ if (NULL != l2_pp_grp0_resource)
+ {
+ _mali_osk_errcode_t ret;
+ MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n"));
+ ret = mali_create_cluster(l2_pp_grp0_resource);
+ if (_MALI_OSK_ERR_OK != ret)
+ {
+ return ret;
+ }
}
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_DEBUG_PRINT(3, ("Did not find required Mali L2 cache for PP group 0 in config file\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* Second PP core group is optional, don't fail if we don't find it */
+ l2_pp_grp1_resource = mali_find_resource(MALI_L2, 0x11000);
+ if (NULL != l2_pp_grp1_resource)
+ {
+ _mali_osk_errcode_t ret;
+ MALI_DEBUG_PRINT(3, ("Creating Mali-450 cluster for PP group 0\n"));
+ ret = mali_create_cluster(l2_pp_grp1_resource);
+ if (_MALI_OSK_ERR_OK != ret)
+ {
+ return ret;
+ }
}
}
- MALI_SUCCESS;
+ return _MALI_OSK_ERR_OK;
}
-static _mali_osk_errcode_t initialize_subsystems(void)
+static _mali_osk_errcode_t mali_create_group(struct mali_cluster *cluster,
+ _mali_osk_resource_t *resource_mmu,
+ _mali_osk_resource_t *resource_gp,
+ _mali_osk_resource_t *resource_pp)
{
- int i, j;
- _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT; /* default error code */
+ struct mali_mmu_core *mmu;
+ struct mali_group *group;
+ struct mali_pp_core *pp;
- 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);
+ MALI_DEBUG_PRINT(3, ("Starting new group for MMU %s\n", resource_mmu->description));
- for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ /* Create the MMU object */
+ mmu = mali_mmu_create(resource_mmu);
+ if (NULL == mmu)
{
- if (NULL != subsystems[i]->startup)
+ MALI_PRINT_ERROR(("Failed to create MMU object\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* Create the group object */
+ group = mali_group_create(cluster, mmu);
+ if (NULL == group)
+ {
+ MALI_PRINT_ERROR(("Failed to create group object for MMU %s\n", resource_mmu->description));
+ mali_mmu_delete(mmu);
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* Set pointer back to group in mmu.*/
+ mali_mmu_set_group(mmu, group);
+
+ /* Add this group to current cluster */
+ mali_cluster_add_group(cluster, group);
+
+ if (NULL != resource_gp)
+ {
+ /* Create the GP core object inside this group */
+ /* global_gp_core = mali_gp_create(resource_gp, group); */
+ if (NULL == mali_gp_create(resource_gp, group))
{
- /* 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;
+ /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
+ MALI_PRINT_ERROR(("Failed to create GP object\n"));
+ return _MALI_OSK_ERR_FAULT;
}
+
+ /* Add GP object to this group */
+ MALI_DEBUG_PRINT(3, ("Adding GP %s to group\n", resource_gp->description));
+ mali_group_add_gp_core(group, mali_gp_get_global_gp_core());
}
- for (j = 0; j < (int)SUBSYSTEMS_COUNT; ++j)
+ if (NULL != resource_pp)
{
- if (NULL != subsystems[j]->load_complete)
+ /* Create the PP core object inside this group */
+ pp = mali_pp_create(resource_pp, group);
+
+ if (NULL == pp)
{
- /* the subsystem has a load_complete function defined */
- err = subsystems[j]->load_complete(j);
- if (_MALI_OSK_ERR_OK != err) goto cleanup;
+ /* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
+ MALI_PRINT_ERROR(("Failed to create PP object\n"));
+ return _MALI_OSK_ERR_FAULT;
}
+
+ /* Add PP object to this group */
+ MALI_DEBUG_PRINT(3, ("Adding PP %s to group\n", resource_pp->description));
+ mali_group_add_pp_core(group, pp);
}
- /* All systems loaded and resources registered */
- /* Build system info */
- if (_MALI_OSK_ERR_OK != build_system_info()) goto cleanup;
+ return _MALI_OSK_ERR_OK;
+}
+
+static _mali_osk_errcode_t mali_parse_config_groups(void)
+{
+ if (_MALI_PRODUCT_ID_MALI200 == global_product_id)
+ {
+ _mali_osk_resource_t *resource_gp;
+ _mali_osk_resource_t *resource_pp;
+ _mali_osk_resource_t *resource_mmu;
+
+ MALI_DEBUG_ASSERT(1 == mali_cluster_get_glob_num_clusters());
- MALI_SUCCESS; /* all ok */
+ resource_gp = mali_find_resource(MALI_GP, 0x02000);
+ resource_pp = mali_find_resource(MALI_PP, 0x00000);
+ resource_mmu = mali_find_resource(MMU, 0x03000);
-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)
+ if (NULL == resource_mmu || NULL == resource_gp || NULL == resource_pp)
+ {
+ /* Missing mandatory core(s) */
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /*return mali_create_group(global_clusters[0], resource_mmu, resource_gp, resource_pp);*/
+ return mali_create_group(mali_cluster_get_global_cluster(0), resource_mmu, resource_gp, resource_pp);
+ }
+ else if (_MALI_PRODUCT_ID_MALI300 == global_product_id ||
+ _MALI_PRODUCT_ID_MALI400 == global_product_id ||
+ _MALI_PRODUCT_ID_MALI450 == global_product_id)
{
- /* 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_errcode_t err;
+ int cluster_id_gp = 0;
+ int cluster_id_pp_grp0 = 0;
+ int cluster_id_pp_grp1 = 0;
+ int i;
+ _mali_osk_resource_t *resource_gp;
+ _mali_osk_resource_t *resource_gp_mmu;
+ _mali_osk_resource_t *resource_pp[mali_pp_get_max_num_pp_cores()];
+ _mali_osk_resource_t *resource_pp_mmu[mali_pp_get_max_num_pp_cores()];
+ u32 max_num_pp_cores = mali_pp_get_max_num_pp_cores();
+
+ if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
+ {
+ /* Mali-450 has separate L2s for GP, and PP core group(s) */
+ cluster_id_pp_grp0 = 1;
+ cluster_id_pp_grp1 = 2;
+ }
+
+ resource_gp = mali_find_resource(MALI_GP, 0x00000);
+ resource_gp_mmu = mali_find_resource(MMU, 0x03000);
+ resource_pp[0] = mali_find_resource(MALI_PP, 0x08000);
+ resource_pp[1] = mali_find_resource(MALI_PP, 0x0A000);
+ resource_pp[2] = mali_find_resource(MALI_PP, 0x0C000);
+ resource_pp[3] = mali_find_resource(MALI_PP, 0x0E000);
+ resource_pp[4] = mali_find_resource(MALI_PP, 0x28000);
+ resource_pp[5] = mali_find_resource(MALI_PP, 0x2A000);
+ resource_pp[6] = mali_find_resource(MALI_PP, 0x2C000);
+ resource_pp[7] = mali_find_resource(MALI_PP, 0x2E000);
+ resource_pp_mmu[0] = mali_find_resource(MMU, 0x04000);
+ resource_pp_mmu[1] = mali_find_resource(MMU, 0x05000);
+ resource_pp_mmu[2] = mali_find_resource(MMU, 0x06000);
+ resource_pp_mmu[3] = mali_find_resource(MMU, 0x07000);
+ resource_pp_mmu[4] = mali_find_resource(MMU, 0x1C000);
+ resource_pp_mmu[5] = mali_find_resource(MMU, 0x1D000);
+ resource_pp_mmu[6] = mali_find_resource(MMU, 0x1E000);
+ resource_pp_mmu[7] = mali_find_resource(MMU, 0x1F000);
+
+ if (NULL == resource_gp || NULL == resource_gp_mmu || NULL == resource_pp[0] || NULL == resource_pp_mmu[0])
+ {
+ /* Missing mandatory core(s) */
+ MALI_DEBUG_PRINT(2, ("Missing mandatory resource, need at least one GP and one PP, both with a separate MMU (0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
+ resource_gp, resource_gp_mmu, resource_pp[0], resource_pp_mmu[0]));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ MALI_DEBUG_ASSERT(1 <= mali_cluster_get_glob_num_clusters());
+ err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_gp), resource_gp_mmu, resource_gp, NULL);
+ if (err != _MALI_OSK_ERR_OK)
+ {
+ return err;
+ }
+
+ /* Create group for first (and mandatory) PP core */
+ MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= (cluster_id_pp_grp0 + 1)); /* >= 1 on Mali-300 and Mali-400, >= 2 on Mali-450 */
+ err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[0], NULL, resource_pp[0]);
+ if (err != _MALI_OSK_ERR_OK)
+ {
+ return err;
+ }
+
+ /* Create groups for rest of the cores in the first PP core group */
+ for (i = 1; i < 4; i++) /* First half of the PP cores belong to first core group */
+ {
+ if (NULL != resource_pp[i])
+ {
+ err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp0), resource_pp_mmu[i], NULL, resource_pp[i]);
+ if (err != _MALI_OSK_ERR_OK)
+ {
+ return err;
+ }
+ }
+ }
+
+ /* Create groups for cores in the second PP core group */
+ for (i = 4; i < max_num_pp_cores; i++) /* Second half of the PP cores belong to second core group */
+ {
+ if (NULL != resource_pp[i])
+ {
+ MALI_DEBUG_ASSERT(mali_cluster_get_glob_num_clusters() >= 2); /* Only Mali-450 have more than 4 PPs, and these cores belong to second core group */
+ err = mali_create_group(mali_cluster_get_global_cluster(cluster_id_pp_grp1), resource_pp_mmu[i], NULL, resource_pp[i]);
+ if (err != _MALI_OSK_ERR_OK)
+ {
+ return err;
+ }
+ }
+ }
}
- _mali_osk_lock_term( system_info_lock );
- MALI_ERROR(err); /* err is what the module which failed its startup returned, or the default */
+ return _MALI_OSK_ERR_OK;
}
-static void terminate_subsystems(void)
+static _mali_osk_errcode_t mali_parse_config_pmu(void)
{
- int i;
- /* shut down subsystems in reverse order from startup */
- for (i = SUBSYSTEMS_COUNT - 1; i >= 0; --i)
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
+ _mali_osk_resource_t *resource_pmu;
+ u32 number_of_pp_cores;
+ u32 number_of_l2_caches;
+
+ resource_pmu = mali_find_resource(PMU, 0x02000);
+ number_of_pp_cores = mali_count_resources(MALI_PP);
+ number_of_l2_caches = mali_count_resources(MALI_L2);
+
+ if (NULL != resource_pmu)
{
- /* the subsystem identifier is the offset in our subsystems array */
- if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i);
+ if (NULL == mali_pmu_create(resource_pmu, number_of_pp_cores, number_of_l2_caches))
+ {
+ err = _MALI_OSK_ERR_FAULT;
+ }
}
- if (system_info_lock) _mali_osk_lock_term( system_info_lock );
-
- /* Free _mali_system_info struct */
- cleanup_system_info(system_info);
+ return err;
}
-void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data)
+static _mali_osk_errcode_t mali_parse_config_memory(void)
{
int i;
+ _mali_osk_errcode_t ret;
- for (i = 0; i < (int)SUBSYSTEMS_COUNT; ++i)
+ for(i = 0; i < num_resources; i++)
{
- if (NULL != subsystems[i]->broadcast_notification)
+ switch(arch_configuration[i].type)
{
- subsystems[i]->broadcast_notification(message, data);
+ case OS_MEMORY:
+ ret = mali_memory_core_resource_os_memory(&arch_configuration[i]);
+ if (_MALI_OSK_ERR_OK != ret)
+ {
+ MALI_PRINT_ERROR(("Failed to register OS_MEMORY\n"));
+ mali_memory_terminate();
+ return ret;
+ }
+ break;
+ case MEMORY:
+ ret = mali_memory_core_resource_dedicated_memory(&arch_configuration[i]);
+ if (_MALI_OSK_ERR_OK != ret)
+ {
+ MALI_PRINT_ERROR(("Failed to register MEMORY\n"));
+ mali_memory_terminate();
+ return ret;
+ }
+ break;
+ case MEM_VALIDATION:
+ ret = mali_mem_validation_add_range(&arch_configuration[i]);
+ if (_MALI_OSK_ERR_OK != ret)
+ {
+ MALI_PRINT_ERROR(("Failed to register MEM_VALIDATION\n"));
+ mali_memory_terminate();
+ return ret;
+ }
+ break;
+ default:
+ break;
}
}
+ return _MALI_OSK_ERR_OK;
}
-static _mali_osk_errcode_t mali_kernel_subsystem_core_setup(mali_kernel_subsystem_identifier id)
+_mali_osk_errcode_t mali_initialize_subsystems(void)
{
- mali_subsystem_core_id = id;
+ _mali_osk_errcode_t err;
+ mali_bool is_pmu_enabled;
- /* Register our own resources */
- MALI_CHECK_NO_ERROR(_mali_kernel_core_register_resource_handler(MEM_VALIDATION, mali_kernel_core_resource_mem_validation));
+ 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);
- /* 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));
+ err = mali_session_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto session_init_failed;
- MALI_CHECK_NO_ERROR(register_resources(&arch_configuration, num_resources));
+#if MALI_TIMELINE_PROFILING_ENABLED
+ err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ /* No biggie if we wheren't able to initialize the profiling */
+ MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
+ }
+#endif
- /* resource parsing succeeded and the subsystem have corretly accepted their resources */
- MALI_SUCCESS;
+ /* Build dummy system info. Will be removed in the future. */
+ err = build_system_info();
+ if (_MALI_OSK_ERR_OK != err) goto build_system_info_failed;
+
+ /* Get data from config.h */
+ err = _mali_osk_resources_init(&arch_configuration, &num_resources);
+ if (_MALI_OSK_ERR_OK != err) goto osk_resources_init_failed;
+
+ /* Initialize driver subsystems */
+ err = mali_memory_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto memory_init_failed;
+
+ /* Configure memory early. Memory allocation needed for mali_mmu_initialize. */
+ err = mali_parse_config_memory();
+ if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed;
+
+ /* Parsing the GPU base address and first pp offset */
+ err = mali_parse_gpu_base_and_first_pp_offset_address();
+ if (_MALI_OSK_ERR_OK != err) goto parse_gpu_base_address_failed;
+
+ /* Initialize the MALI PMU */
+ err = mali_parse_config_pmu();
+ if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed;
+
+ is_pmu_enabled = mali_pmu_get_global_pmu_core() != NULL ? MALI_TRUE : MALI_FALSE;
+
+ /* Initialize the power management module */
+ err = mali_pm_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto pm_init_failed;
+
+ /* Make sure the power stays on for the rest of this function */
+ mali_pm_always_on(MALI_TRUE);
+
+ /* Detect which Mali GPU we are dealing with */
+ err = mali_parse_product_info();
+ if (_MALI_OSK_ERR_OK != err) goto product_info_parsing_failed;
+
+ /* The global_product_id is now populated with the correct Mali GPU */
+
+ /* Initialize MMU module */
+ err = mali_mmu_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto mmu_init_failed;
+
+ /* Initialize the DLBU module for Mali-450 */
+ if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
+ {
+ err = mali_dlbu_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto dlbu_init_failed;
+ }
+
+ /* Start configuring the actual Mali hardware. */
+ err = mali_parse_config_cluster();
+ if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
+ err = mali_parse_config_groups();
+ if (_MALI_OSK_ERR_OK != err) goto config_parsing_failed;
+
+ /* Initialize the schedulers */
+ err = mali_scheduler_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto scheduler_init_failed;
+ err = mali_gp_scheduler_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto gp_scheduler_init_failed;
+ err = mali_pp_scheduler_initialize();
+ if (_MALI_OSK_ERR_OK != err) goto pp_scheduler_init_failed;
+
+#ifdef CONFIG_MALI400_GPU_UTILIZATION
+ /* Initialize the GPU utilization tracking */
+ err = mali_utilization_init();
+ if (_MALI_OSK_ERR_OK != err) goto utilization_init_failed;
+#endif
+
+ /* We no longer need to stay */
+ mali_pm_always_on(MALI_FALSE);
+ MALI_SUCCESS; /* all ok */
+
+ /* Error handling */
+#ifdef CONFIG_MALI400_GPU_UTILIZATION
+utilization_init_failed:
+ mali_pp_scheduler_terminate();
+#endif
+pp_scheduler_init_failed:
+ mali_gp_scheduler_terminate();
+gp_scheduler_init_failed:
+ mali_scheduler_terminate();
+scheduler_init_failed:
+config_parsing_failed:
+ mali_delete_clusters(); /* Delete clusters even if config parsing failed. */
+ if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
+ {
+ mali_dlbu_terminate();
+ }
+dlbu_init_failed:
+ mali_mmu_terminate();
+mmu_init_failed:
+ /* Nothing to roll back */
+product_info_parsing_failed:
+ mali_pm_terminate();
+pm_init_failed:
+ if (is_pmu_enabled)
+ {
+ mali_pmu_delete(mali_pmu_get_global_pmu_core());
+ }
+parse_pmu_config_failed:
+parse_gpu_base_address_failed:
+parse_memory_config_failed:
+ mali_memory_terminate();
+memory_init_failed:
+ _mali_osk_resources_term(&arch_configuration, num_resources);
+osk_resources_init_failed:
+ cleanup_system_info(system_info);
+build_system_info_failed:
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_term();
+#endif
+ mali_session_terminate();
+session_init_failed:
+ return err;
+}
+
+void mali_terminate_subsystems(void)
+{
+ struct mali_pmu_core *pmu;
+ MALI_DEBUG_PRINT(2, ("terminate_subsystems() called\n"));
+
+ /* shut down subsystems in reverse order from startup */
+
+ mali_pm_always_on(MALI_TRUE); /* Mali will be powered off once PM subsystem terminates */
+
+#ifdef CONFIG_MALI400_GPU_UTILIZATION
+ mali_utilization_term();
+#endif
+
+ mali_pp_scheduler_terminate();
+ mali_gp_scheduler_terminate();
+ mali_scheduler_terminate();
+
+ mali_delete_clusters(); /* Delete clusters even if config parsing failed. */
+
+ if (_MALI_PRODUCT_ID_MALI450 == global_product_id)
+ {
+ mali_dlbu_terminate();
+ }
+
+ mali_mmu_terminate();
+
+ pmu = mali_pmu_get_global_pmu_core();
+ if (NULL != pmu)
+ {
+ mali_pmu_delete(pmu);
+ }
+
+ mali_pm_terminate();
+
+ mali_memory_terminate();
+
+ _mali_osk_resources_term(&arch_configuration, num_resources);
+
+ cleanup_system_info(system_info);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_term();
+#endif
+
+ mali_session_terminate();
+
+ if (NULL != system_info_lock)
+ {
+ _mali_osk_lock_term( system_info_lock );
+ }
+}
+
+_mali_product_id_t mali_kernel_core_get_product_id(void)
+{
+ return global_product_id;
}
-static void mali_kernel_subsystem_core_cleanup(mali_kernel_subsystem_identifier id)
+void mali_kernel_core_wakeup(void)
{
- _mali_osk_resources_term(&arch_configuration, num_resources);
+ u32 i;
+ u32 glob_num_clusters = mali_cluster_get_glob_num_clusters();
+ struct mali_cluster *cluster;
+
+ for (i = 0; i < glob_num_clusters; i++)
+ {
+ cluster = mali_cluster_get_global_cluster(i);
+ mali_cluster_reset(cluster);
+ }
}
static void cleanup_system_info(_mali_system_info *cleanup)
@@ -373,11 +834,10 @@ static void cleanup_system_info(_mali_system_info *cleanup)
_mali_osk_free(cleanup);
}
+/* Build a dummy system info struct. User space still need this. */
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_system_info * new_info;
_mali_core_info * current_core;
_mali_mem_info * current_mem;
u32 new_size = 0;
@@ -387,19 +847,25 @@ static _mali_osk_errcode_t build_system_info(void)
_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;
+ /* fill in the info */
+ new_info->has_mmu = 1;
+ new_info->drivermode = _MALI_DRIVER_MODE_NORMAL;
- /* ask each subsystems to fill in their info */
- for (i = 0; i < SUBSYSTEMS_COUNT; ++i)
+ new_info->core_info = NULL; /* Not used by user space */
+
+ new_info->mem_info = _mali_osk_calloc(1, sizeof(_mali_mem_info));
+ if(NULL == new_info->mem_info)
{
- if (NULL != subsystems[i]->system_info_fill)
- {
- err = subsystems[i]->system_info_fill(new_info);
- if (_MALI_OSK_ERR_OK != err) goto error_exit;
- }
+ _mali_osk_free(new_info);
+ return _MALI_OSK_ERR_NOMEM;
}
+ new_info->mem_info->size = 1024 * 1024 * 1024; /* 1GiB */
+ new_info->mem_info->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;
+ new_info->mem_info->maximum_order_supported = 30;
+ new_info->mem_info->identifier = 0;
+ new_info->mem_info->next = NULL;
+
/* building succeeded, calculate the size */
/* size needed of the system info struct itself */
@@ -420,8 +886,6 @@ static _mali_osk_errcode_t build_system_info(void)
/* 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;
@@ -430,25 +894,15 @@ static _mali_osk_errcode_t build_system_info(void)
_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);
+ return _MALI_OSK_ERR_OK;
}
_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);
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
- /* check compatability */
+ /* check compatability */
if ( args->version == _MALI_UK_API_VERSION )
{
args->compatible = 1;
@@ -461,14 +915,14 @@ _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args
args->version = _MALI_UK_API_VERSION; /* report our version */
/* success regardless of being compatible or not */
- MALI_SUCCESS;
+ 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_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 )
@@ -477,12 +931,12 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
_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;
+ 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);
+ 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 );
@@ -491,20 +945,20 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
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;
- }
+ * 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;
@@ -557,56 +1011,56 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
err = _MALI_OSK_ERR_OK;
exit_when_locked:
_mali_osk_lock_signal( system_info_lock, _MALI_OSK_LOCKMODE_RW );
- MALI_ERROR(err);
+ 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;
+ _mali_osk_notification_t *notification;
+ _mali_osk_notification_queue_t *queue;
- /* check input */
+ /* check input */
MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_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);
+ queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
/* if the queue does not exist we're currently shutting down */
if (NULL == queue)
{
MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n"));
- args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
+ args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS;
MALI_SUCCESS;
}
- /* receive a notification, might sleep */
+ /* 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 */
- }
+ 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);
+ 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_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;
+ _mali_osk_notification_queue_t *queue;
- /* check input */
+ /* check input */
MALI_DEBUG_ASSERT_POINTER(args);
- MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_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);
+ queue = ((struct mali_session_data *)args->ctx)->ioctl_queue;
/* if the queue does not exist we're currently shutting down */
if (NULL == queue)
@@ -618,294 +1072,115 @@ _mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *a
notification = _mali_osk_notification_create(args->type, 0);
if ( NULL == notification)
{
- MALI_PRINT_ERROR( ("Failed to create notification object\n")) ;
+ 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_SUCCESS; /* all ok */
}
_mali_osk_errcode_t _mali_ukk_open(void **context)
{
- int i;
- _mali_osk_errcode_t err;
- struct mali_session_data * session_data;
+ 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);
+ session_data = (struct mali_session_data *)_mali_osk_calloc(1, 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));
+ MALI_DEBUG_PRINT(2, ("Session starting\n"));
/* 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_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)
+ session_data->page_directory = mali_mmu_pagedir_alloc();
+ if (NULL == session_data->page_directory)
{
- 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);
- }
+ _mali_osk_notification_queue_term(session_data->ioctl_queue);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
}
- *context = (void*)session_data;
+ if (_MALI_OSK_ERR_OK != mali_mmu_pagedir_map(session_data->page_directory, MALI_DLB_VIRT_ADDR, _MALI_OSK_MALI_PAGE_SIZE))
+ {
+ MALI_PRINT_ERROR(("Failed to map DLB page into session\n"));
+ _mali_osk_notification_queue_term(session_data->ioctl_queue);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
- MALI_DEBUG_PRINT(3, ("Session started\n"));
- MALI_SUCCESS;
+ if (0 != mali_dlbu_phys_addr)
+ {
+ mali_mmu_pagedir_update(session_data->page_directory, MALI_DLB_VIRT_ADDR, mali_dlbu_phys_addr, _MALI_OSK_MALI_PAGE_SIZE);
+ }
-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 (_MALI_OSK_ERR_OK != mali_memory_session_begin(session_data))
{
- if (NULL != subsystems[i]->session_end) subsystems[i]->session_end(session_data, &session_data->subsystem_data[i]);
+ mali_mmu_pagedir_free(session_data->page_directory);
+ _mali_osk_notification_queue_term(session_data->ioctl_queue);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
}
- _mali_osk_notification_queue_term(session_data->ioctl_queue);
- _mali_osk_free(session_data);
+ *context = (void*)session_data;
- /* return what the subsystem which failed session start returned */
- MALI_ERROR(err);
+ /* Add session to the list of all sessions. */
+ mali_session_add(session_data);
+
+ MALI_DEBUG_PRINT(3, ("Session started\n"));
+ MALI_SUCCESS;
}
_mali_osk_errcode_t _mali_ukk_close(void **context)
{
- int i;
- struct mali_session_data * session_data;
+ struct mali_session_data *session;
+ MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
+ session = (struct mali_session_data *)*context;
- MALI_CHECK_NON_NULL(context, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_DEBUG_PRINT(3, ("Session ending\n"));
- session_data = (struct mali_session_data *)*context;
+ /* Remove session from list of all sessions. */
+ mali_session_remove(session);
- MALI_DEBUG_PRINT(2, ("Session ending\n"));
+ /* Abort queued and running jobs */
+ mali_gp_scheduler_abort_session(session);
+ mali_pp_scheduler_abort_session(session);
- /* 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]);
- }
+ /* Flush pending work.
+ * Needed to make sure all bottom half processing related to this
+ * session has been completed, before we free internal data structures.
+ */
+ _mali_osk_flush_workqueue(NULL);
- _mali_osk_notification_queue_term(session_data->ioctl_queue);
- _mali_osk_free(session_data);
+ /* Free remaining memory allocated to this session */
+ mali_memory_session_end(session);
- *context = NULL;
+ /* Free session data structures */
+ mali_mmu_pagedir_free(session->page_directory);
+ _mali_osk_notification_queue_term(session->ioctl_queue);
+ _mali_osk_free(session);
- MALI_DEBUG_PRINT(2, ("Session has ended\n"));
-
- MALI_SUCCESS;
-}
+ *context = NULL;
-#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();
+ MALI_DEBUG_PRINT(2, ("Session has ended\n"));
- /* 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);
+ int n = 0; /* Number of bytes written to buf */
+
+ n += mali_gp_scheduler_dump_state(buf + n, size - n);
+ n += mali_pp_scheduler_dump_state(buf + n, size - n);
+
+ return n;
}
#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.h b/drivers/media/video/samsung/mali/common/mali_kernel_core.h
index 715c1cd..d424c48 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_core.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,122 +13,27 @@
#include "mali_osk.h"
-#if USING_MALI_PMM
-#include "mali_ukk.h"
-#include "mali_pmm.h"
-#include "mali_pmm_system.h"
-#endif
+extern int mali_hang_check_interval;
+extern int mali_max_job_runtime;
-_mali_osk_errcode_t mali_kernel_constructor( void );
-void mali_kernel_destructor( void );
+typedef enum
+{
+ _MALI_PRODUCT_ID_UNKNOWN,
+ _MALI_PRODUCT_ID_MALI200,
+ _MALI_PRODUCT_ID_MALI300,
+ _MALI_PRODUCT_ID_MALI400,
+ _MALI_PRODUCT_ID_MALI450,
+} _mali_product_id_t;
-/**
- * @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 );
+_mali_osk_errcode_t mali_initialize_subsystems(void);
-#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 );
+void mali_terminate_subsystems(void);
-#endif
+void mali_kernel_core_wakeup(void);
-/**
- * Flag to indicate whether or not mali_benchmark is turned on.
- */
-extern int mali_benchmark;
+_mali_product_id_t mali_kernel_core_get_product_id(void);
+u32 _mali_kernel_core_dump_state(char* buf, u32 size);
#endif /* __MALI_KERNEL_CORE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c
index 8b2a97d..b9f05ca 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -40,11 +40,7 @@ mali_descriptor_mapping * mali_descriptor_mapping_create(int init_entries, int m
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
+ map->lock = _mali_osk_lock_init( (_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE), 0, _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP);
if (NULL != map->lock)
{
_mali_osk_set_nonatomic_bit(0, map->table->usage); /* reserve bit 0 to prevent NULL/zero logic to kick in */
@@ -151,15 +147,20 @@ _mali_osk_errcode_t mali_descriptor_mapping_set(mali_descriptor_mapping * map, i
MALI_ERROR(result);
}
-void mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor)
+void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor)
{
+ void *old_value = NULL;
+
_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) )
{
+ old_value = map->table->mappings[descriptor];
map->table->mappings[descriptor] = NULL;
_mali_osk_clear_nonatomic_bit(descriptor, map->table->usage);
}
_mali_osk_lock_signal(map->lock, _MALI_OSK_LOCKMODE_RW);
+
+ return old_value;
}
static mali_descriptor_table * descriptor_table_alloc(int count)
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h
index 745be92..82ed94d 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_descriptor_mapping.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -93,7 +93,9 @@ void mali_descriptor_mapping_call_for_each(mali_descriptor_mapping * map, void (
* For the descriptor to be reused it has to be freed
* @param map The map to free the descriptor from
* @param descriptor The descriptor ID to free
+ *
+ * @return old value of descriptor mapping
*/
-void mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor);
+void *mali_descriptor_mapping_free(mali_descriptor_mapping * map, int descriptor);
#endif /* __MALI_KERNEL_DESCRIPTOR_MAPPING_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c b/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c
deleted file mode 100644
index e4d4ab1..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * 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.
- */
-#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 */
- NULL, /*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/media/video/samsung/mali/common/mali_kernel_l2_cache.h b/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h
deleted file mode 100644
index 8c12b50..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_l2_cache.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/mali_kernel_mem_buddy.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c
deleted file mode 100644
index e378f03..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_buddy.c
+++ /dev/null
@@ -1,1427 +0,0 @@
-/*
- * 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.
- */
-
-#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 */
- NULL, /*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
- If this happens we have a bug in our session cleanup code.
- */
- 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 that would be a bug in the caller */
- 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/media/video/samsung/mali/common/mali_kernel_mem_mmu.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c
deleted file mode 100644
index c993ad5..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.c
+++ /dev/null
@@ -1,3157 +0,0 @@
-/*
- * 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.
- */
-
-#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 */
- NULL, /*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 && (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/media/video/samsung/mali/common/mali_kernel_mem_mmu.h b/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h
deleted file mode 100644
index 6a110d0..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_mmu.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c
index 324fcab..7462a6d 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -65,19 +65,19 @@ mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u3
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;
+ info->mutex = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_MEM_INFO);
+ 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->ctx = info;
allocator->name = name;
- return allocator;
- }
- _mali_osk_free(info);
+ return allocator;
+ }
+ _mali_osk_free(info);
}
_mali_osk_free(allocator);
}
@@ -132,7 +132,7 @@ static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, m
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))
+ while (left > 0)
{
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)
@@ -243,7 +243,7 @@ static void os_allocator_release(void * ctx, void * handle)
static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block)
{
- int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */
+ int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 11 */
void *virt = NULL;
u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order;
os_allocator * info;
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c
index ff105a4..1377560 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -161,13 +161,28 @@ _mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engin
void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor)
{
+ mali_allocation_engine_release_pt1_mali_pagetables_unmap(mem_engine, descriptor);
+ mali_allocation_engine_release_pt2_physical_memory_free(mem_engine, descriptor);
+}
+
+void mali_allocation_engine_release_pt1_mali_pagetables_unmap(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 */
+ /* Calling: mali_address_manager_release() */
+ /* This function is allowed to be called several times, and it only does the release on the first call. */
+ engine->mali_address->release(descriptor);
+}
+
+void mali_allocation_engine_release_pt2_physical_memory_free(mali_allocation_engine mem_engine, mali_memory_allocation * descriptor)
+{
+ memory_engine * engine = (memory_engine*)mem_engine;
+ mali_physical_memory_allocation * active_allocation_tracker;
+
+ /* Remove this from a tracking list in session_data->memory_head */
if ( ! _mali_osk_list_empty( &descriptor->list ) )
{
_mali_osk_list_del( &descriptor->list );
@@ -175,8 +190,6 @@ void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, ma
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)
{
@@ -199,7 +212,6 @@ void mali_allocation_engine_release_memory(mali_allocation_engine mem_engine, ma
}
}
-
_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;
@@ -244,7 +256,7 @@ _mali_osk_errcode_t mali_allocation_engine_map_physical(mali_allocation_engine m
}
}
- 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_DEBUG_PRINT(7, ("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 */
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h
index 0173c78..cda74c3 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_memory_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -136,6 +136,9 @@ 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);
+void mali_allocation_engine_release_pt1_mali_pagetables_unmap(mali_allocation_engine engine, mali_memory_allocation * descriptor);
+void mali_allocation_engine_release_pt2_physical_memory_free(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);
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c b/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c
deleted file mode 100644
index cfc5ec1..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.c
+++ /dev/null
@@ -1,2031 +0,0 @@
-/*
- * 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.
- */
-
-#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_kernel_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 (10*HANG_CHECK_MSECS_MIN)
-#define WATCHDOG_MSECS_MAX 3600000 /* 1 hour */
-#define WATCHDOG_MSECS_DEFAULT 4000 /* 4 secs */
-
-/* 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
-
-#ifdef MALI_REBOOTNOTIFIER
-extern _mali_osk_atomic_t mali_shutdown_state;
-#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 */
- NULL, /*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_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_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;
-#ifdef MALI_REBOOTNOTIFIER
- if (_mali_osk_atomic_read(&mali_shutdown_state) > 0) {
- MALI_DEBUG_PRINT(3, ("Core: mali already under shutdown process!!")) ;
- return;
- }
-#endif
-
- 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/media/video/samsung/mali/common/mali_kernel_rendercore.h b/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h
deleted file mode 100644
index 5fbe686..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_rendercore.h
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/mali_kernel_subsystem.h b/drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h
deleted file mode 100644
index 8f05216..0000000
--- a/drivers/media/video/samsung/mali/common/mali_kernel_subsystem.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/mali_kernel_utilization.c b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c
index b43b872..a374dbf 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -27,7 +27,7 @@ static _mali_osk_timer_t *utilization_timer = NULL;
static mali_bool timer_running = MALI_FALSE;
-static void calculate_gpu_utilization(void *arg)
+static void calculate_gpu_utilization(void* arg)
{
u64 time_now;
u64 time_period;
@@ -39,7 +39,8 @@ static void calculate_gpu_utilization(void *arg)
_mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW);
- if (accumulated_work_time == 0 && work_start_time == 0) {
+ 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;
@@ -55,7 +56,8 @@ static void calculate_gpu_utilization(void *arg)
time_period = time_now - period_start_time;
/* If we are currently busy, update working period up to now */
- if (work_start_time != 0) {
+ if (work_start_time != 0)
+ {
accumulated_work_time += (time_now - work_start_time);
work_start_time = time_now;
}
@@ -79,10 +81,13 @@ static void calculate_gpu_utilization(void *arg)
* (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) {
+ if (period_normalized > 0x00FFFFFF)
+ {
/* The divisor is so big that it is safe to shift it down */
period_normalized >>= 8;
- } else {
+ }
+ else
+ {
/*
* The divisor is so small that we can shift up the dividend, without loosing any data.
* (dividend is always smaller than the divisor)
@@ -99,22 +104,25 @@ static void calculate_gpu_utilization(void *arg)
_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 );
+ time_data_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |
+ _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_UTILIZATION);
+
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) {
+ if (NULL == utilization_timer)
+ {
_mali_osk_lock_term(time_data_lock);
return _MALI_OSK_ERR_FAULT;
}
@@ -125,7 +133,8 @@ _mali_osk_errcode_t mali_utilization_init(void)
void mali_utilization_suspend(void)
{
- if (NULL != utilization_timer) {
+ if (NULL != utilization_timer)
+ {
_mali_osk_timer_del(utilization_timer);
timer_running = MALI_FALSE;
}
@@ -133,7 +142,8 @@ void mali_utilization_suspend(void)
void mali_utilization_term(void)
{
- if (NULL != utilization_timer) {
+ if (NULL != utilization_timer)
+ {
_mali_osk_timer_del(utilization_timer);
timer_running = MALI_FALSE;
_mali_osk_timer_term(utilization_timer);
@@ -145,11 +155,10 @@ void mali_utilization_term(void)
_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) {
+ 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
@@ -167,27 +176,26 @@ void mali_utilization_core_start(u64 time_now)
}
work_start_time = time_now;
-
- if (timer_running != MALI_TRUE) {
+ 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_del(utilization_timer);
-
_mali_osk_timer_add(utilization_timer, _mali_osk_time_mstoticks(MALI_GPU_UTILIZATION_TIMEOUT));
- } else {
+ }
+ 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) {
+ if (_mali_osk_atomic_dec_return(&num_running_cores) == 0)
+ {
/*
* No more cores are working, so accumulate the time we was busy.
*/
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h
index c779978..1f60517 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_utilization.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c
index dc39e01..63c9f5b 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c
+++ b/drivers/media/video/samsung/mali/common/mali_kernel_vsync.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -10,39 +10,41 @@
#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"
+#include "mali_osk_profiling.h"
#endif
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args)
{
_mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event;
MALI_IGNORE(event); /* event is not used for release code, and that is OK */
-/* u64 ts = _mali_timestamp_get();
- */
#if MALI_TIMELINE_PROFILING_ENABLED
+ /*
+ * Manually generate user space events in kernel space.
+ * This saves user space from calling kernel space twice in this case.
+ * We just need to remember to add pid and tid manually.
+ */
if ( event==_MALI_UK_VSYNC_EVENT_BEGIN_WAIT)
{
- _mali_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);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+ _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
}
- if ( event==_MALI_UK_VSYNC_EVENT_END_WAIT)
+ 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);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC,
+ _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
}
#endif
+
MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event));
MALI_SUCCESS;
}
diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.c b/drivers/media/video/samsung/mali/common/mali_l2_cache.c
new file mode 100644
index 0000000..aa5cc54
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_l2_cache.c
@@ -0,0 +1,398 @@
+/*
+ * 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_l2_cache.h"
+#include "mali_hw_core.h"
+#include "mali_pm.h"
+
+/**
+ * Size of the Mali L2 cache registers in bytes
+ */
+#define MALI400_L2_CACHE_REGISTERS_SIZE 0x30
+
+#define MALI_MAX_NUMBER_OF_L2_CACHE_CORES 3
+
+/**
+ * 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 = 0x0008,
+ /*unused = 0x000C */
+ MALI400_L2_CACHE_REGISTER_COMMAND = 0x0010, /**< Misc cache commands, e.g. clear */
+ MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0014,
+ MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0018, /**< Limit of outstanding read requests */
+ MALI400_L2_CACHE_REGISTER_ENABLE = 0x001C, /**< Enable misc cache features */
+ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0020,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0024,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1 = 0x0028,
+ MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1 = 0x002C,
+} mali_l2_cache_register;
+
+/**
+ * Mali L2 cache commands
+ * These are the commands that can be sent to the Mali L2 cache unit
+ */
+typedef enum mali_l2_cache_command
+{
+ MALI400_L2_CACHE_COMMAND_CLEAR_ALL = 0x01, /**< Clear the entire cache */
+ /* Read HW TRM carefully before adding/using other commands than the clear above */
+} mali_l2_cache_command;
+
+/**
+ * Mali L2 cache commands
+ * These are the commands that can be sent to the Mali L2 cache unit
+ */
+typedef enum mali_l2_cache_enable
+{
+ MALI400_L2_CACHE_ENABLE_DEFAULT = 0x0, /**< Default state of enable register */
+ MALI400_L2_CACHE_ENABLE_ACCESS = 0x01, /**< Permit cacheable accesses */
+ MALI400_L2_CACHE_ENABLE_READ_ALLOCATE = 0x02, /**< Permit cache read allocate */
+} mali_l2_cache_enable;
+
+/**
+ * Mali L2 cache status bits
+ */
+typedef enum mali_l2_cache_status
+{
+ MALI400_L2_CACHE_STATUS_COMMAND_BUSY = 0x01, /**< Command handler of L2 cache is busy */
+ MALI400_L2_CACHE_STATUS_DATA_BUSY = 0x02, /**< L2 cache is busy handling data requests */
+} mali_l2_cache_status;
+
+/**
+ * Definition of the L2 cache core struct
+ * Used to track a L2 cache unit in the system.
+ * Contains information about the mapping of the registers
+ */
+struct mali_l2_cache_core
+{
+ struct mali_hw_core hw_core; /**< Common for all HW cores */
+ u32 core_id; /**< Unique core ID */
+ _mali_osk_lock_t *command_lock; /**< Serialize all L2 cache commands */
+ _mali_osk_lock_t *counter_lock; /**< Synchronize L2 cache counter access */
+ u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+ u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+};
+
+#define MALI400_L2_MAX_READS_DEFAULT 0x1C
+
+static struct mali_l2_cache_core *mali_global_l2_cache_cores[MALI_MAX_NUMBER_OF_L2_CACHE_CORES];
+static u32 mali_global_num_l2_cache_cores = 0;
+
+int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT;
+
+/* Local helper functions */
+static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val);
+
+
+struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t *resource)
+{
+ struct mali_l2_cache_core *cache = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Mali L2 cache: Creating Mali L2 cache: %s\n", resource->description));
+
+ if (mali_global_num_l2_cache_cores >= MALI_MAX_NUMBER_OF_L2_CACHE_CORES)
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Too many L2 cache core objects created\n"));
+ return NULL;
+ }
+
+ cache = _mali_osk_malloc(sizeof(struct mali_l2_cache_core));
+ if (NULL != cache)
+ {
+ cache->core_id = mali_global_num_l2_cache_cores;
+ cache->counter_src0 = MALI_HW_CORE_NO_COUNTER;
+ cache->counter_src1 = MALI_HW_CORE_NO_COUNTER;
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&cache->hw_core, resource, MALI400_L2_CACHE_REGISTERS_SIZE))
+ {
+ cache->command_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE,
+ 0, _MALI_OSK_LOCK_ORDER_L2_COMMAND);
+ if (NULL != cache->command_lock)
+ {
+ cache->counter_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE,
+ 0, _MALI_OSK_LOCK_ORDER_L2_COUNTER);
+ if (NULL != cache->counter_lock)
+ {
+ if (_MALI_OSK_ERR_OK == mali_l2_cache_reset(cache))
+ {
+ mali_global_l2_cache_cores[mali_global_num_l2_cache_cores] = cache;
+ mali_global_num_l2_cache_cores++;
+
+ return cache;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to reset L2 cache core %s\n", cache->hw_core.description));
+ }
+
+ _mali_osk_lock_term(cache->counter_lock);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to create counter lock for L2 cache core %s\n", cache->hw_core.description));
+ }
+
+ _mali_osk_lock_term(cache->command_lock);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to create command lock for L2 cache core %s\n", cache->hw_core.description));
+ }
+
+ mali_hw_core_delete(&cache->hw_core);
+ }
+
+ _mali_osk_free(cache);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali L2 cache: Failed to allocate memory for L2 cache core\n"));
+ }
+
+ return NULL;
+}
+
+void mali_l2_cache_delete(struct mali_l2_cache_core *cache)
+{
+ u32 i;
+
+ /* reset to defaults */
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT);
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT);
+
+ _mali_osk_lock_term(cache->counter_lock);
+ _mali_osk_lock_term(cache->command_lock);
+ mali_hw_core_delete(&cache->hw_core);
+
+ for (i = 0; i < mali_global_num_l2_cache_cores; i++)
+ {
+ if (mali_global_l2_cache_cores[i] == cache)
+ {
+ mali_global_l2_cache_cores[i] = NULL;
+ mali_global_num_l2_cache_cores--;
+ }
+ }
+
+ _mali_osk_free(cache);
+}
+
+u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache)
+{
+ return cache->core_id;
+}
+
+mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter)
+{
+ u32 value = 0; /* disabled src */
+
+ MALI_DEBUG_ASSERT_POINTER(cache);
+ MALI_DEBUG_ASSERT(counter < (1 << 7)); /* the possible values are 0-127 */
+
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ cache->counter_src0 = counter;
+
+ if (counter != MALI_HW_CORE_NO_COUNTER)
+ {
+ value = counter;
+ }
+
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, value);
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+ return MALI_TRUE;
+}
+
+mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter)
+{
+ u32 value = 0; /* disabled src */
+
+ MALI_DEBUG_ASSERT_POINTER(cache);
+ MALI_DEBUG_ASSERT(counter < (1 << 7)); /* the possible values are 0-127 */
+
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ cache->counter_src1 = counter;
+
+ if (counter != MALI_HW_CORE_NO_COUNTER)
+ {
+ value = counter;
+ }
+
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, value);
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+ return MALI_TRUE;
+}
+
+u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache)
+{
+ return cache->counter_src0;
+}
+
+u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache)
+{
+ return cache->counter_src1;
+}
+
+void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1)
+{
+ MALI_DEBUG_ASSERT(NULL != src0);
+ MALI_DEBUG_ASSERT(NULL != value0);
+ MALI_DEBUG_ASSERT(NULL != src1);
+ MALI_DEBUG_ASSERT(NULL != value1);
+
+ /* Caller must hold the PM lock and know that we are powered on */
+
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ *src0 = cache->counter_src0;
+ *src1 = cache->counter_src1;
+
+ if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
+ {
+ *value0 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0);
+ }
+
+ if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
+ {
+ *value1 = mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL1);
+ }
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index)
+{
+ if (MALI_MAX_NUMBER_OF_L2_CACHE_CORES > index)
+ {
+ return mali_global_l2_cache_cores[index];
+ }
+
+ return NULL;
+}
+
+u32 mali_l2_cache_core_get_glob_num_l2_cores(void)
+{
+ return mali_global_num_l2_cache_cores;
+}
+
+u32 mali_l2_cache_core_get_max_num_l2_cores(void)
+{
+ return MALI_MAX_NUMBER_OF_L2_CACHE_CORES;
+}
+
+_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache)
+{
+ /* Invalidate cache (just to keep it in a known state at startup) */
+ mali_l2_cache_invalidate_all(cache);
+
+ /* Enable cache */
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE);
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads);
+
+ /* Restart any performance counters (if enabled) */
+ _mali_osk_lock_wait(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (cache->counter_src0 != MALI_HW_CORE_NO_COUNTER)
+ {
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0, cache->counter_src0);
+ }
+
+ if (cache->counter_src1 != MALI_HW_CORE_NO_COUNTER)
+ {
+ mali_hw_core_register_write(&cache->hw_core, MALI400_L2_CACHE_REGISTER_PERFCNT_SRC1, cache->counter_src1);
+ }
+
+ _mali_osk_lock_signal(cache->counter_lock, _MALI_OSK_LOCKMODE_RW);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache)
+{
+ return mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_COMMAND, MALI400_L2_CACHE_COMMAND_CLEAR_ALL);
+}
+
+_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages)
+{
+ u32 i;
+ _mali_osk_errcode_t ret1, ret = _MALI_OSK_ERR_OK;
+
+ for (i = 0; i < num_pages; i++)
+ {
+ ret1 = mali_l2_cache_send_command(cache, MALI400_L2_CACHE_REGISTER_CLEAR_PAGE, pages[i]);
+ if (_MALI_OSK_ERR_OK != ret1)
+ {
+ ret = ret1;
+ }
+ }
+
+ return ret;
+}
+
+mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache)
+{
+ /*
+ * Take PM lock and check power state.
+ * Returns MALI_TRUE if module is powered on.
+ * Power state will not change until mali_l2_cache_unlock_power_state() is called.
+ */
+ mali_pm_lock();
+ return mali_pm_is_powered_on();
+}
+
+void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache)
+{
+ /* Release PM lock */
+ mali_pm_unlock();
+}
+
+/* -------- local helper functions below -------- */
+
+
+static _mali_osk_errcode_t mali_l2_cache_send_command(struct mali_l2_cache_core *cache, u32 reg, u32 val)
+{
+ int i = 0;
+ const int loop_count = 100000;
+
+ /*
+ * Grab lock in order to send commands to the L2 cache in a serialized fashion.
+ * The L2 cache will ignore commands if it is busy.
+ */
+ _mali_osk_lock_wait(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* First, wait for L2 cache command handler to go idle */
+
+ for (i = 0; i < loop_count; i++)
+ {
+ if (!(mali_hw_core_register_read(&cache->hw_core, MALI400_L2_CACHE_REGISTER_STATUS) & (u32)MALI400_L2_CACHE_STATUS_COMMAND_BUSY))
+ {
+ break;
+ }
+ }
+
+ if (i == loop_count)
+ {
+ _mali_osk_lock_signal(cache->command_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_hw_core_register_write(&cache->hw_core, reg, val);
+
+ _mali_osk_lock_signal(cache->command_lock, _MALI_OSK_LOCKMODE_RW);
+
+ MALI_SUCCESS;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_l2_cache.h b/drivers/media/video/samsung/mali/common/mali_l2_cache.h
new file mode 100644
index 0000000..5a8e4da
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_l2_cache.h
@@ -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.
+ */
+
+#ifndef __MALI_KERNEL_L2_CACHE_H__
+#define __MALI_KERNEL_L2_CACHE_H__
+
+#include "mali_osk.h"
+
+struct mali_l2_cache_core;
+
+_mali_osk_errcode_t mali_l2_cache_initialize(void);
+void mali_l2_cache_terminate(void);
+
+struct mali_l2_cache_core *mali_l2_cache_create(_mali_osk_resource_t * resource);
+void mali_l2_cache_delete(struct mali_l2_cache_core *cache);
+
+u32 mali_l2_cache_get_id(struct mali_l2_cache_core *cache);
+
+mali_bool mali_l2_cache_core_set_counter_src0(struct mali_l2_cache_core *cache, u32 counter);
+mali_bool mali_l2_cache_core_set_counter_src1(struct mali_l2_cache_core *cache, u32 counter);
+u32 mali_l2_cache_core_get_counter_src0(struct mali_l2_cache_core *cache);
+u32 mali_l2_cache_core_get_counter_src1(struct mali_l2_cache_core *cache);
+void mali_l2_cache_core_get_counter_values(struct mali_l2_cache_core *cache, u32 *src0, u32 *value0, u32 *src1, u32 *value1);
+struct mali_l2_cache_core *mali_l2_cache_core_get_glob_l2_core(u32 index);
+u32 mali_l2_cache_core_get_glob_num_l2_cores(void);
+u32 mali_l2_cache_core_get_max_num_l2_cores(void);
+
+_mali_osk_errcode_t mali_l2_cache_reset(struct mali_l2_cache_core *cache);
+
+_mali_osk_errcode_t mali_l2_cache_invalidate_all(struct mali_l2_cache_core *cache);
+_mali_osk_errcode_t mali_l2_cache_invalidate_pages(struct mali_l2_cache_core *cache, u32 *pages, u32 num_pages);
+
+mali_bool mali_l2_cache_lock_power_state(struct mali_l2_cache_core *cache);
+void mali_l2_cache_unlock_power_state(struct mali_l2_cache_core *cache);
+
+#endif /* __MALI_KERNEL_L2_CACHE_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_mem_validation.c b/drivers/media/video/samsung/mali/common/mali_mem_validation.c
new file mode 100644
index 0000000..ea9c428
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mem_validation.c
@@ -0,0 +1,71 @@
+/*
+ * 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_mem_validation.h"
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+#define MALI_INVALID_MEM_ADDR 0xFFFFFFFF
+
+typedef struct
+{
+ u32 phys_base; /**< Mali physical base of the memory, page aligned */
+ u32 size; /**< size in bytes of the memory, multiple of page size */
+} _mali_mem_validation_t;
+
+static _mali_mem_validation_t mali_mem_validator = { MALI_INVALID_MEM_ADDR, MALI_INVALID_MEM_ADDR };
+
+_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t *resource)
+{
+ /* Check that no other MEM_VALIDATION resources exist */
+ if (MALI_INVALID_MEM_ADDR != mali_mem_validator.phys_base)
+ {
+ MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; another range is already specified\n", resource->description));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ /* Check restrictions on page alignment */
+ if ((0 != (resource->base & (~_MALI_OSK_CPU_PAGE_MASK))) ||
+ (0 != (resource->size & (~_MALI_OSK_CPU_PAGE_MASK))))
+ {
+ MALI_PRINT_ERROR(("Failed to add MEM_VALIDATION resource %s; incorrect alignment\n", resource->description));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ mali_mem_validator.phys_base = resource->base;
+ mali_mem_validator.size = resource->size;
+ MALI_DEBUG_PRINT(2, ("Memory Validator '%s' installed for Mali physical address base=0x%08X, size=0x%08X\n",
+ resource->description, mali_mem_validator.phys_base, mali_mem_validator.size));
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size)
+{
+ if (phys_addr < (phys_addr + size)) /* Don't allow overflow (or zero size) */
+ {
+ if ((0 == ( phys_addr & (~_MALI_OSK_CPU_PAGE_MASK))) &&
+ (0 == ( size & (~_MALI_OSK_CPU_PAGE_MASK))))
+ {
+ if ((phys_addr >= mali_mem_validator.phys_base) &&
+ ((phys_addr + (size - 1)) >= mali_mem_validator.phys_base) &&
+ (phys_addr <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) &&
+ ((phys_addr + (size - 1)) <= (mali_mem_validator.phys_base + (mali_mem_validator.size - 1))) )
+ {
+ MALI_DEBUG_PRINT(3, ("Accepted range 0x%08X + size 0x%08X (= 0x%08X)\n", phys_addr, size, (phys_addr + size - 1)));
+ return _MALI_OSK_ERR_OK;
+ }
+ }
+ }
+
+ MALI_PRINT_ERROR(("MALI PHYSICAL RANGE VALIDATION ERROR: The range supplied was: phys_base=0x%08X, size=0x%08X\n", phys_addr, size));
+
+ return _MALI_OSK_ERR_FAULT;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_session_manager.h b/drivers/media/video/samsung/mali/common/mali_mem_validation.h
index 8cc41d7..2043b44 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_session_manager.h
+++ b/drivers/media/video/samsung/mali/common/mali_mem_validation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,12 +8,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_SESSION_MANAGER_H__
-#define __MALI_KERNEL_SESSION_MANAGER_H__
+#ifndef __MALI_MEM_VALIDATION_H__
+#define __MALI_MEM_VALIDATION_H__
-/* Incomplete struct to pass around pointers to it */
-struct mali_session_data;
+#include "mali_osk.h"
-void * mali_kernel_session_manager_slot_get(struct mali_session_data * session, int id);
+_mali_osk_errcode_t mali_mem_validation_add_range(const _mali_osk_resource_t * resource);
+_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size);
-#endif /* __MALI_KERNEL_SESSION_MANAGER_H__ */
+#endif /* __MALI_MEM_VALIDATION_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_memory.c b/drivers/media/video/samsung/mali/common/mali_memory.c
new file mode 100644
index 0000000..7a11d1a
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_memory.c
@@ -0,0 +1,1321 @@
+/*
+ * 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_mem_validation.h"
+#include "mali_memory.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_kernel_memory_engine.h"
+#include "mali_block_allocator.h"
+#include "mali_kernel_mem_os.h"
+#include "mali_session.h"
+#include "mali_l2_cache.h"
+#include "mali_cluster.h"
+#include "mali_group.h"
+#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_list.h"
+#include "mali_osk_bitops.h"
+
+/**
+ * Per-session memory descriptor mapping table sizes
+ */
+#define MALI_MEM_DESCRIPTORS_INIT 64
+#define MALI_MEM_DESCRIPTORS_MAX 65536
+
+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;
+
+/**
+ * @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_utgard_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 );
+
+#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);
+
+/* 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;
+
+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*/
+};
+
+/* the mmu page table cache */
+static struct mali_mmu_page_table_allocations page_table_cache;
+
+
+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_osk_errcode_t mali_mmu_page_table_cache_create(void);
+static void mali_mmu_page_table_cache_destroy(void);
+
+static mali_allocation_engine memory_engine = NULL;
+static mali_physical_memory_allocator * physical_memory_allocators = NULL;
+
+static dedicated_memory_info * mem_region_registrations = NULL;
+
+/* called during module init */
+_mali_osk_errcode_t mali_memory_initialize(void)
+{
+ _mali_osk_errcode_t err;
+
+ MALI_DEBUG_PRINT(2, ("Memory system initializing\n"));
+
+ err = mali_mmu_page_table_cache_create();
+ if(_MALI_OSK_ERR_OK != err)
+ {
+ MALI_ERROR(err);
+ }
+
+ 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 */
+void mali_memory_terminate(void)
+{
+ MALI_DEBUG_PRINT(2, ("Memory system terminating\n"));
+
+ 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;
+ }
+}
+
+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data * session_data)
+{
+ MALI_DEBUG_PRINT(5, ("Memory session begin\n"));
+
+ /* create descriptor mapping table */
+ session_data->descriptor_mapping = mali_descriptor_mapping_create(MALI_MEM_DESCRIPTORS_INIT, MALI_MEM_DESCRIPTORS_MAX);
+
+ if (NULL == session_data->descriptor_mapping)
+ {
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ session_data->memory_lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ONELOCK
+ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_MEM_SESSION);
+ if (NULL == session_data->memory_lock)
+ {
+ mali_descriptor_mapping_destroy(session_data->descriptor_mapping);
+ _mali_osk_free(session_data);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ /* Init the session's memory allocation list */
+ _MALI_OSK_INIT_LIST_HEAD( &session_data->memory_head );
+
+ MALI_DEBUG_PRINT(5, ("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(3, ("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);
+}
+
+void mali_memory_session_end(struct mali_session_data *session_data)
+{
+ MALI_DEBUG_PRINT(3, ("MMU session end\n"));
+
+ if (NULL == session_data)
+ {
+ MALI_DEBUG_PRINT(1, ("No session data found during session end\n"));
+ return;
+ }
+
+#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
+ {
+ _mali_osk_errcode_t err;
+ err = _MALI_OSK_ERR_BUSY;
+ while (err == _MALI_OSK_ERR_BUSY)
+ {
+ /* Lock the session so we can modify the memory list */
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+ err = _MALI_OSK_ERR_OK;
+
+ /* 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 = 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->memory_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.
+ */
+ err = _mali_ukk_mem_munmap_internal( &unmap_args );
+
+ if (err == _MALI_OSK_ERR_BUSY)
+ {
+ _mali_osk_lock_signal( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+ /*
+ * 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);
+ break; /* Will jump back into: "while (err == _MALI_OSK_ERR_BUSY)" */
+ }
+ }
+ }
+ }
+ /* Assert that we really did free everything */
+ MALI_DEBUG_ASSERT( _mali_osk_list_empty(&session_data->memory_head) );
+ }
+#endif /* _MALI_OSK_SPECIFIC_INDIRECT_MMAP */
+#else
+ /* Lock the session so we can modify the memory list */
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+#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;
+ }
+
+ _mali_osk_lock_signal( session_data->memory_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->memory_lock );
+
+ return;
+}
+
+_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;
+}
+
+_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 low level 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 low level 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;
+}
+
+#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;
+ struct mali_session_data *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 = (struct mali_session_data *)args->ctx;
+ 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->memory_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->memory_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->memory_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->memory_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;
+ struct mali_session_data *session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)args->ctx;
+ MALI_CHECK_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);
+ }
+
+ descriptor = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
+
+ if (NULL != descriptor)
+ {
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+
+ _mali_osk_lock_signal( session_data->memory_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(5, ("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;
+ struct mali_session_data *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 = (struct mali_session_data *)args->ctx;
+ 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 */
+ if (_MALI_OSK_ERR_OK != mali_mem_validation_check(args->phys_addr, args->size))
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ 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->memory_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 );
+
+ _mali_osk_lock_wait(session_data->memory_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->memory_lock, _MALI_OSK_LOCKMODE_RW);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+ }
+
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session_data->descriptor_mapping, descriptor, &md))
+ {
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+ _mali_osk_free(descriptor);
+ MALI_ERROR(_MALI_OSK_ERR_FAULT);
+ }
+
+ 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;
+ void* old_value;
+ struct mali_session_data *session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)args->ctx;
+ MALI_CHECK_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);
+ }
+
+ old_value = mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie);
+
+ if (NULL != old_value)
+ {
+ _mali_osk_lock_wait( session_data->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ mali_allocation_engine_release_memory(memory_engine, descriptor);
+
+ _mali_osk_lock_signal( session_data->memory_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;
+}
+
+static _mali_osk_errcode_t mali_address_manager_allocate(mali_memory_allocation * descriptor)
+{
+ struct mali_session_data *session_data;
+ u32 actual_size;
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+
+ actual_size = descriptor->size;
+
+ if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ actual_size += _MALI_OSK_MALI_PAGE_SIZE;
+ }
+
+ return mali_mmu_pagedir_map(session_data->page_directory, descriptor->mali_address, actual_size);
+}
+
+static void mali_address_manager_release(mali_memory_allocation * descriptor)
+{
+ const u32 illegal_mali_address = 0xffffffff;
+ struct mali_session_data *session_data;
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+
+ /* It is allowed to call this function several times on the same descriptor.
+ When memory is released we set the illegal_mali_address so we can early out here. */
+ if ( illegal_mali_address == descriptor->mali_address) return;
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+ mali_mmu_pagedir_unmap(session_data->page_directory, descriptor->mali_address, descriptor->size);
+
+ descriptor->mali_address = illegal_mali_address ;
+}
+
+static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * descriptor, u32 offset, u32 *phys_addr, u32 size)
+{
+ struct mali_session_data *session_data;
+ u32 mali_address;
+
+ MALI_DEBUG_ASSERT_POINTER(descriptor);
+ MALI_DEBUG_ASSERT_POINTER(phys_addr);
+
+ session_data = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ mali_address = descriptor->mali_address + offset;
+
+ MALI_DEBUG_PRINT(7, ("Mali map: mapping 0x%08X to Mali address 0x%08X length 0x%08X\n", *phys_addr, mali_address, size));
+
+ mali_mmu_pagedir_update(session_data->page_directory, mali_address, *phys_addr, size);
+
+ 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 *session_data;
+ mali_memory_allocation * descriptor;
+
+ /* 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 */
+ session_data = (struct mali_session_data *)args->ctx;
+
+ /* 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->memory_lock;
+ _mali_osk_list_init( &descriptor->list );
+
+ _mali_osk_lock_wait(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head))
+ {
+ /* We do not FLUSH nor TLB_ZAP on MMAP, since we do both of those on job start*/
+ _mali_osk_lock_signal(session_data->memory_lock, _MALI_OSK_LOCKMODE_RW);
+
+ args->mapping = descriptor->mapping;
+ args->cookie = (u32)descriptor;
+
+ MALI_DEBUG_PRINT(7, ("MMAP OK\n"));
+ MALI_SUCCESS;
+ }
+ else
+ {
+ _mali_osk_lock_signal(session_data->memory_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 )
+{
+ struct mali_session_data *session_data;
+ mali_memory_allocation * descriptor;
+
+ u32 num_groups = mali_group_get_glob_num_groups();
+ struct mali_group *group;
+ u32 i;
+
+ 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 = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
+ MALI_DEBUG_ASSERT_POINTER(session_data);
+
+ /* Unmapping the memory from the mali virtual address space.
+ It is allowed to call this function severeal times, which might happen if zapping below fails. */
+ mali_allocation_engine_release_pt1_mali_pagetables_unmap(memory_engine, descriptor);
+
+#ifdef MALI_UNMAP_FLUSH_ALL_MALI_L2
+ {
+ u32 number_of_clusters = mali_cluster_get_glob_num_clusters();
+ for (i = 0; i < number_of_clusters; i++)
+ {
+ struct mali_cluster *cluster;
+ cluster = mali_cluster_get_global_cluster(i);
+ if( mali_cluster_power_is_enabled_get(cluster) )
+ {
+ mali_cluster_l2_cache_invalidate_all_force(cluster);
+ }
+ }
+ }
+#endif
+
+ for (i = 0; i < num_groups; i++)
+ {
+ group = mali_group_get_glob_group(i);
+ mali_group_lock(group);
+ mali_group_remove_session_if_unused(group, session_data);
+ if (mali_group_get_session(group) == session_data)
+ {
+ /* The Zap also does the stall and disable_stall */
+ mali_bool zap_success = mali_mmu_zap_tlb(mali_group_get_mmu(group));
+ if (MALI_TRUE != zap_success)
+ {
+ MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n"));
+ mali_group_bottom_half(group, GROUP_EVENT_MMU_PAGE_FAULT);
+ /* The bottom half will also do the unlock */
+ continue;
+ }
+ }
+ mali_group_unlock(group);
+ }
+
+ /* Removes the descriptor from the session's memory list, releases physical memory, releases descriptor */
+ mali_allocation_engine_release_pt2_physical_memory_free(memory_engine, descriptor);
+
+ _mali_osk_free(descriptor);
+
+ 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((struct mali_session_data *)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;
+}
+
+u32 _mali_ukk_report_memory_usage(void)
+{
+ return mali_allocation_engine_memory_usage(physical_memory_allocators);
+}
+
+_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);
+ }
+
+ _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: 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);
+}
+
+static _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, _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE);
+ 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;
+}
+
+static 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);
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_memory.h b/drivers/media/video/samsung/mali/common/mali_memory.h
new file mode 100644
index 0000000..53a994c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_memory.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.
+ */
+
+#ifndef __MALI_MEMORY_H__
+#define __MALI_MEMORY_H__
+
+#include "mali_osk.h"
+#include "mali_session.h"
+
+struct mali_cluster;
+struct mali_group;
+
+/** @brief Initialize Mali memory subsystem
+ *
+ * Allocate and initialize internal data structures. Must be called before
+ * allocating Mali memory.
+ *
+ * @return On success _MALI_OSK_ERR_OK, othervise some error code describing the error.
+ */
+_mali_osk_errcode_t mali_memory_initialize(void);
+
+/** @brief Terminate Mali memory system
+ *
+ * Clean up and release internal data structures.
+ */
+void mali_memory_terminate(void);
+
+/** @brief Start new Mali memory session
+ *
+ * Allocate and prepare session specific memory allocation data data. The
+ * session page directory, lock, and descriptor map is set up.
+ *
+ * @param mali_session_data pointer to the session data structure
+ */
+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *mali_session_data);
+
+/** @brief Close a Mali memory session
+ *
+ * Release session specific memory allocation related data.
+ *
+ * @param mali_session_data pointer to the session data structure
+ */
+void mali_memory_session_end(struct mali_session_data *mali_session_data);
+
+/** @brief Allocate a page table page
+ *
+ * Allocate a page for use as a page directory or page table. The page is
+ * mapped into kernel space.
+ *
+ * @return _MALI_OSK_ERR_OK on success, othervise an error code
+ * @param table_page GPU pointer to the allocated page
+ * @param mapping CPU pointer to the mapping of the allocated page
+ */
+_mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping);
+
+/** @brief Release a page table page
+ *
+ * Release a page table page allocated through \a mali_mmu_get_table_page
+ *
+ * @param pa the GPU address of the page to release
+ */
+void mali_mmu_release_table_page(u32 pa);
+
+
+/** @brief Parse resource and prepare the OS memory allocator
+ */
+_mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resource_t * resource);
+
+/** @brief Parse resource and prepare the dedicated memory allocator
+ */
+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(_mali_osk_resource_t * resource);
+
+#endif /* __MALI_MEMORY_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.c b/drivers/media/video/samsung/mali/common/mali_mmu.c
new file mode 100644
index 0000000..2f2fa4d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu.c
@@ -0,0 +1,619 @@
+/*
+ * 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 "mali_ukk.h"
+
+#include "mali_mmu.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "mali_mmu_page_directory.h"
+
+/**
+ * Size of the MMU registers in bytes
+ */
+#define MALI_MMU_REGISTERS_SIZE 0x24
+
+/**
+ * MMU register numbers
+ * Used in the register read/write routines.
+ * See the hardware documentation for more information about each register
+ */
+typedef enum mali_mmu_register {
+ MALI_MMU_REGISTER_DTE_ADDR = 0x0000, /**< Current Page Directory Pointer */
+ MALI_MMU_REGISTER_STATUS = 0x0004, /**< Status of the MMU */
+ MALI_MMU_REGISTER_COMMAND = 0x0008, /**< Command register, used to control the MMU */
+ MALI_MMU_REGISTER_PAGE_FAULT_ADDR = 0x000C, /**< Logical address of the last page fault */
+ MALI_MMU_REGISTER_ZAP_ONE_LINE = 0x010, /**< Used to invalidate the mapping of a single page from the MMU */
+ MALI_MMU_REGISTER_INT_RAWSTAT = 0x0014, /**< Raw interrupt status, all interrupts visible */
+ MALI_MMU_REGISTER_INT_CLEAR = 0x0018, /**< Indicate to the MMU that the interrupt has been received */
+ MALI_MMU_REGISTER_INT_MASK = 0x001C, /**< Enable/disable types of interrupts */
+ MALI_MMU_REGISTER_INT_STATUS = 0x0020 /**< Interrupt status based on the mask */
+} mali_mmu_register;
+
+/**
+ * MMU interrupt register bits
+ * Each cause of the interrupt is reported
+ * through the (raw) interrupt status registers.
+ * Multiple interrupts can be pending, so multiple bits
+ * can be set at once.
+ */
+typedef enum mali_mmu_interrupt
+{
+ MALI_MMU_INTERRUPT_PAGE_FAULT = 0x01, /**< A page fault occured */
+ MALI_MMU_INTERRUPT_READ_BUS_ERROR = 0x02 /**< A bus read error occured */
+} mali_mmu_interrupt;
+
+/**
+ * MMU commands
+ * These are the commands that can be sent
+ * to the MMU unit.
+ */
+typedef enum mali_mmu_command
+{
+ MALI_MMU_COMMAND_ENABLE_PAGING = 0x00, /**< Enable paging (memory translation) */
+ MALI_MMU_COMMAND_DISABLE_PAGING = 0x01, /**< Disable paging (memory translation) */
+ MALI_MMU_COMMAND_ENABLE_STALL = 0x02, /**< Enable stall on page fault */
+ MALI_MMU_COMMAND_DISABLE_STALL = 0x03, /**< Disable stall on page fault */
+ MALI_MMU_COMMAND_ZAP_CACHE = 0x04, /**< Zap the entire page table cache */
+ MALI_MMU_COMMAND_PAGE_FAULT_DONE = 0x05, /**< Page fault processed */
+ MALI_MMU_COMMAND_HARD_RESET = 0x06 /**< Reset the MMU back to power-on settings */
+} mali_mmu_command;
+
+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;
+
+/**
+ * Definition of the MMU struct
+ * Used to track a MMU unit in the system.
+ * Contains information about the mapping of the registers
+ */
+struct mali_mmu_core
+{
+ struct mali_hw_core hw_core; /**< Common for all HW cores */
+ struct mali_group *group; /**< Parent core group */
+ _mali_osk_irq_t *irq; /**< IRQ handler */
+};
+
+/**
+ * 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_mmu_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_mmu_bottom_half(void *data);
+
+static void mali_mmu_probe_trigger(void *data);
+static _mali_osk_errcode_t mali_mmu_probe_ack(void *data);
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu);
+
+/* page fault queue flush helper pages
+ * note that the mapping pointers are currently unused outside of the initialization functions */
+static u32 mali_page_fault_flush_page_directory = MALI_INVALID_PAGE;
+static u32 mali_page_fault_flush_page_table = MALI_INVALID_PAGE;
+static u32 mali_page_fault_flush_data_page = MALI_INVALID_PAGE;
+
+/* 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;
+
+_mali_osk_errcode_t mali_mmu_initialize(void)
+{
+ /* allocate the helper pages */
+ mali_empty_page_directory = mali_allocate_empty_page();
+ if(0 == mali_empty_page_directory)
+ {
+ mali_empty_page_directory = MALI_INVALID_PAGE;
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_create_fault_flush_pages(&mali_page_fault_flush_page_directory,
+ &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page))
+ {
+ mali_free_empty_page(mali_empty_page_directory);
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_mmu_terminate(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali MMU: terminating\n"));
+
+ /* Free global helper pages */
+ mali_free_empty_page(mali_empty_page_directory);
+
+ /* Free the page fault flush pages */
+ mali_destroy_fault_flush_pages(&mali_page_fault_flush_page_directory,
+ &mali_page_fault_flush_page_table, &mali_page_fault_flush_data_page);
+}
+
+struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource)
+{
+ struct mali_mmu_core* mmu = NULL;
+
+ MALI_DEBUG_ASSERT_POINTER(resource);
+
+ MALI_DEBUG_PRINT(2, ("Mali MMU: Creating Mali MMU: %s\n", resource->description));
+
+ mmu = _mali_osk_calloc(1,sizeof(struct mali_mmu_core));
+ if (NULL != mmu)
+ {
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&mmu->hw_core, resource, MALI_MMU_REGISTERS_SIZE))
+ {
+ if (_MALI_OSK_ERR_OK == mali_mmu_reset(mmu))
+ {
+ /* Setup IRQ handlers (which will do IRQ probing if needed) */
+ mmu->irq = _mali_osk_irq_init(resource->irq,
+ mali_mmu_upper_half,
+ mali_mmu_bottom_half,
+ mali_mmu_probe_trigger,
+ mali_mmu_probe_ack,
+ mmu,
+ "mali_mmu_irq_handlers");
+ if (NULL != mmu->irq)
+ {
+ return mmu;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to setup interrupt handlers for MMU %s\n", mmu->hw_core.description));
+ }
+ }
+ mali_hw_core_delete(&mmu->hw_core);
+ }
+
+ _mali_osk_free(mmu);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to allocate memory for MMU\n"));
+ }
+
+ return NULL;
+}
+
+void mali_mmu_delete(struct mali_mmu_core *mmu)
+{
+ _mali_osk_irq_term(mmu->irq);
+ mali_hw_core_delete(&mmu->hw_core);
+ _mali_osk_free(mmu);
+}
+
+void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group)
+{
+ mmu->group = group;
+}
+
+static void mali_mmu_enable_paging(struct mali_mmu_core *mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 1;
+ int i;
+
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING);
+
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ if (max_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Enable paging request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+ }
+}
+
+mali_bool mali_mmu_enable_stall(struct mali_mmu_core *mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 999;
+ int i;
+ u32 mmu_status;
+
+ /* There are no group when it is called from mali_mmu_create */
+ if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group);
+
+ mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+
+ if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED) )
+ {
+ MALI_DEBUG_PRINT(4, ("MMU stall is implicit when Paging is not enebled.\n"));
+ return MALI_TRUE;
+ }
+
+ if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
+ {
+ MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it is in pagefault state.\n"));
+ return MALI_FALSE;
+ }
+
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL);
+
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+ if ( mmu_status & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE))
+ {
+ break;
+ }
+ if ( 0 == (mmu_status & ( MALI_MMU_STATUS_BIT_PAGING_ENABLED )))
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ if (max_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Enable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+ return MALI_FALSE;
+ }
+
+ if ( mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
+ {
+ MALI_DEBUG_PRINT(3, ("Aborting MMU stall request since it has a pagefault.\n"));
+ return MALI_FALSE;
+ }
+
+ return MALI_TRUE;
+}
+
+void mali_mmu_disable_stall(struct mali_mmu_core *mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 1;
+ int i;
+ u32 mmu_status;
+ /* There are no group when it is called from mali_mmu_create */
+ if ( mmu->group ) MALI_ASSERT_GROUP_LOCKED(mmu->group);
+
+ mmu_status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+
+ if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
+ {
+ MALI_DEBUG_PRINT(3, ("MMU disable skipped since it was not enabled.\n"));
+ return;
+ }
+ if (mmu_status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)
+ {
+ MALI_DEBUG_PRINT(2, ("Aborting MMU disable stall request since it is in pagefault state.\n"));
+ return;
+ }
+
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL);
+
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ u32 status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+ if ( 0 == (status & MALI_MMU_STATUS_BIT_STALL_ACTIVE) )
+ {
+ break;
+ }
+ if ( status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE )
+ {
+ break;
+ }
+ if ( 0 == (mmu_status & MALI_MMU_STATUS_BIT_PAGING_ENABLED ))
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ if (max_loop_count == i) MALI_DEBUG_PRINT(1,("Disable stall request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+}
+
+void mali_mmu_page_fault_done(struct mali_mmu_core *mmu)
+{
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+ MALI_DEBUG_PRINT(4, ("Mali MMU: %s: Leaving page fault mode\n", mmu->hw_core.description));
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_PAGE_FAULT_DONE);
+}
+
+MALI_STATIC_INLINE _mali_osk_errcode_t mali_mmu_raw_reset(struct mali_mmu_core *mmu)
+{
+ const int max_loop_count = 100;
+ const int delay_in_usecs = 1;
+ int i;
+ /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */
+ if (mmu->group)MALI_ASSERT_GROUP_LOCKED(mmu->group);
+
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE);
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_HARD_RESET);
+
+ for (i = 0; i < max_loop_count; ++i)
+ {
+ if (mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR) == 0)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(delay_in_usecs);
+ }
+ if (max_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Reset request failed, MMU status is 0x%08X\n", mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu)
+{
+ _mali_osk_errcode_t err = _MALI_OSK_ERR_FAULT;
+ mali_bool stall_success;
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+ /* The _if_ is neccessary when called from mali_mmu_create and NULL==group */
+ if (mmu->group)
+ {
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+ }
+
+ stall_success = mali_mmu_enable_stall(mmu);
+
+ /* The stall can not fail in current hw-state */
+ MALI_DEBUG_ASSERT(stall_success);
+
+ MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
+
+ if (_MALI_OSK_ERR_OK == mali_mmu_raw_reset(mmu))
+ {
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ /* no session is active, so just activate the empty page directory */
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory);
+ mali_mmu_enable_paging(mmu);
+ err = _MALI_OSK_ERR_OK;
+ }
+ mali_mmu_disable_stall(mmu);
+
+ return err;
+}
+
+
+/* ------------- interrupt handling below ------------------ */
+
+static _mali_osk_errcode_t mali_mmu_upper_half(void * data)
+{
+ struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+ u32 int_stat;
+
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+
+ /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
+ int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
+ if (0 != int_stat)
+ {
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK, 0);
+ mali_hw_core_register_read(&mmu->hw_core, 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_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ /* reenable it */
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK,
+ mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_MASK) | MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ MALI_PRINT_ERROR(("Mali MMU: Read bus error\n"));
+ }
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+static void mali_mmu_bottom_half(void * data)
+{
+ struct mali_mmu_core *mmu = (struct mali_mmu_core*)data;
+ u32 raw, status, fault_address;
+
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+
+ MALI_DEBUG_PRINT(3, ("Mali MMU: Page fault bottom half: Locking subsystems\n"));
+
+ mali_group_lock(mmu->group); /* Unlocked in mali_group_bottom_half */
+
+ if ( MALI_FALSE == mali_group_power_is_on(mmu->group) )
+ {
+ MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.",mmu->hw_core.description));
+ mali_group_unlock(mmu->group);
+ return;
+ }
+
+ raw = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT);
+ status = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS);
+
+ if ( (0==(raw & MALI_MMU_INTERRUPT_PAGE_FAULT)) && (0==(status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE)) )
+ {
+ MALI_DEBUG_PRINT(2, ("Mali MMU: Page fault bottom half: No Irq found.\n"));
+ mali_group_unlock(mmu->group);
+ /* MALI_DEBUG_ASSERT(0); */
+ return;
+ }
+
+ /* An actual page fault has occurred. */
+
+ fault_address = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_PAGE_FAULT_ADDR);
+
+ MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n",
+ (void*)fault_address,
+ (status >> 6) & 0x1F,
+ (status & 32) ? "write" : "read",
+ mmu->hw_core.description));
+
+ mali_group_bottom_half(mmu->group, GROUP_EVENT_MMU_PAGE_FAULT); /* Unlocks the group lock */
+}
+
+mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu)
+{
+ mali_bool stall_success;
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+
+ stall_success = mali_mmu_enable_stall(mmu);
+
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+
+ if (MALI_FALSE == stall_success)
+ {
+ /* False means that it is in Pagefault state. Not possible to disable_stall then */
+ return MALI_FALSE;
+ }
+
+ mali_mmu_disable_stall(mmu);
+ return MALI_TRUE;
+}
+
+void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu)
+{
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+}
+
+
+void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address)
+{
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_ZAP_ONE_LINE, MALI_MMU_PDE_ENTRY(mali_address));
+}
+
+static void mali_mmu_activate_address_space(struct mali_mmu_core *mmu, u32 page_directory)
+{
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+ /* The MMU must be in stalled or page fault mode, for this writing to work */
+ MALI_DEBUG_ASSERT( 0 != ( mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)
+ & (MALI_MMU_STATUS_BIT_STALL_ACTIVE|MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) );
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_DTE_ADDR, page_directory);
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE);
+
+}
+
+mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core *mmu, struct mali_page_directory *pagedir)
+{
+ mali_bool stall_success;
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+
+ MALI_DEBUG_PRINT(5, ("Asked to activate page directory 0x%x on MMU %s\n", pagedir, mmu->hw_core.description));
+ stall_success = mali_mmu_enable_stall(mmu);
+
+ if ( MALI_FALSE==stall_success ) return MALI_FALSE;
+ mali_mmu_activate_address_space(mmu, pagedir->page_directory);
+ mali_mmu_disable_stall(mmu);
+ return MALI_TRUE;
+}
+
+void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu)
+{
+ mali_bool stall_success;
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+ MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
+
+ stall_success = mali_mmu_enable_stall(mmu);
+ /* This function can only be called when the core is idle, so it could not fail. */
+ MALI_DEBUG_ASSERT( stall_success );
+ mali_mmu_activate_address_space(mmu, mali_empty_page_directory);
+ mali_mmu_disable_stall(mmu);
+}
+
+void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu)
+{
+ mali_bool stall_success;
+ MALI_DEBUG_ASSERT_POINTER(mmu);
+ MALI_ASSERT_GROUP_LOCKED(mmu->group);
+
+ MALI_DEBUG_PRINT(3, ("Activating the page fault flush page directory on MMU %s\n", mmu->hw_core.description));
+ stall_success = mali_mmu_enable_stall(mmu);
+ /* This function is expect to fail the stalling, since it might be in PageFault mode when it is called */
+ mali_mmu_activate_address_space(mmu, mali_page_fault_flush_page_directory);
+ if ( MALI_TRUE==stall_success ) mali_mmu_disable_stall(mmu);
+}
+
+/* Is called when we want the mmu to give an interrupt */
+static void mali_mmu_probe_trigger(void *data)
+{
+ struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_RAWSTAT, MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+}
+
+/* Is called when the irq probe wants the mmu to acknowledge an interrupt from the hw */
+static _mali_osk_errcode_t mali_mmu_probe_ack(void *data)
+{
+ struct mali_mmu_core *mmu = (struct mali_mmu_core *)data;
+ u32 int_stat;
+
+ int_stat = mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_INT_STATUS);
+
+ MALI_DEBUG_PRINT(2, ("mali_mmu_probe_irq_acknowledge: intstat 0x%x\n", int_stat));
+ if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT)
+ {
+ MALI_DEBUG_PRINT(2, ("Probe: Page fault detect: PASSED\n"));
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_PAGE_FAULT);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ("Probe: Page fault detect: FAILED\n"));
+ }
+
+ if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR)
+ {
+ MALI_DEBUG_PRINT(2, ("Probe: Bus read error detect: PASSED\n"));
+ mali_hw_core_register_write(&mmu->hw_core, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR);
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(1, ("Probe: Bus read error detect: FAILED\n"));
+ }
+
+ if ( (int_stat & (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR)) ==
+ (MALI_MMU_INTERRUPT_PAGE_FAULT|MALI_MMU_INTERRUPT_READ_BUS_ERROR))
+ {
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+#if 0
+void mali_mmu_print_state(struct mali_mmu_core *mmu)
+{
+ MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS)));
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu.h b/drivers/media/video/samsung/mali/common/mali_mmu.h
new file mode 100644
index 0000000..c7274b8
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu.h
@@ -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.
+ */
+
+#ifndef __MALI_MMU_H__
+#define __MALI_MMU_H__
+
+#include "mali_osk.h"
+#include "mali_mmu_page_directory.h"
+
+/* Forward declaration from mali_group.h */
+struct mali_group;
+
+struct mali_mmu_core;
+
+_mali_osk_errcode_t mali_mmu_initialize(void);
+
+void mali_mmu_terminate(void);
+
+struct mali_mmu_core *mali_mmu_create(_mali_osk_resource_t *resource);
+void mali_mmu_set_group(struct mali_mmu_core *mmu, struct mali_group *group);
+void mali_mmu_delete(struct mali_mmu_core *mmu);
+
+_mali_osk_errcode_t mali_mmu_reset(struct mali_mmu_core *mmu);
+mali_bool mali_mmu_zap_tlb(struct mali_mmu_core *mmu);
+void mali_mmu_zap_tlb_without_stall(struct mali_mmu_core *mmu);
+void mali_mmu_invalidate_page(struct mali_mmu_core *mmu, u32 mali_address);
+
+mali_bool mali_mmu_activate_page_directory(struct mali_mmu_core* mmu, struct mali_page_directory *pagedir);
+void mali_mmu_activate_empty_page_directory(struct mali_mmu_core* mmu);
+void mali_mmu_activate_fault_flush_page_directory(struct mali_mmu_core* mmu);
+
+/**
+ * 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)
+ */
+mali_bool mali_mmu_enable_stall(struct mali_mmu_core *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
+ */
+void mali_mmu_disable_stall(struct mali_mmu_core *mmu);
+
+void mali_mmu_page_fault_done(struct mali_mmu_core *mmu);
+
+
+#endif /* __MALI_MMU_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c
new file mode 100644
index 0000000..43a4cf4
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.c
@@ -0,0 +1,459 @@
+/*
+ * 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_kernel_core.h"
+#include "mali_osk.h"
+#include "mali_uk_types.h"
+#include "mali_mmu_page_directory.h"
+#include "mali_memory.h"
+
+#include "mali_cluster.h"
+#include "mali_group.h"
+
+static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data);
+
+u32 mali_allocate_empty_page(void)
+{
+ _mali_osk_errcode_t err;
+ mali_io_address mapping;
+ u32 address;
+
+ if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&address, &mapping))
+ {
+ /* Allocation failed */
+ return 0;
+ }
+
+ MALI_DEBUG_ASSERT_POINTER( mapping );
+
+ err = fill_page(mapping, 0);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ mali_mmu_release_table_page(address);
+ }
+ return address;
+}
+
+void mali_free_empty_page(u32 address)
+{
+ if (MALI_INVALID_PAGE != address)
+ {
+ mali_mmu_release_table_page(address);
+ }
+}
+
+_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page)
+{
+ _mali_osk_errcode_t err;
+ mali_io_address page_directory_mapping;
+ mali_io_address page_table_mapping;
+ mali_io_address data_page_mapping;
+
+ err = mali_mmu_get_table_page(data_page, &data_page_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ err = mali_mmu_get_table_page(page_table, &page_table_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ err = mali_mmu_get_table_page(page_directory, &page_directory_mapping);
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ fill_page(data_page_mapping, 0);
+ fill_page(page_table_mapping, *data_page | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
+ fill_page(page_directory_mapping, *page_table | MALI_MMU_FLAGS_PRESENT);
+ MALI_SUCCESS;
+ }
+ mali_mmu_release_table_page(*page_table);
+ *page_table = MALI_INVALID_PAGE;
+ }
+ mali_mmu_release_table_page(*data_page);
+ *data_page = MALI_INVALID_PAGE;
+ }
+ return err;
+}
+
+void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page)
+{
+ if (MALI_INVALID_PAGE != *page_directory)
+ {
+ mali_mmu_release_table_page(*page_directory);
+ *page_directory = MALI_INVALID_PAGE;
+ }
+
+ if (MALI_INVALID_PAGE != *page_table)
+ {
+ mali_mmu_release_table_page(*page_table);
+ *page_table = MALI_INVALID_PAGE;
+ }
+
+ if (MALI_INVALID_PAGE != *data_page)
+ {
+ mali_mmu_release_table_page(*data_page);
+ *data_page = 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;
+}
+
+_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size)
+{
+ const int first_pde = MALI_MMU_PDE_ENTRY(mali_address);
+ const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1);
+ _mali_osk_errcode_t err;
+ mali_io_address pde_mapping;
+ u32 pde_phys;
+ int i;
+
+ for(i = first_pde; i <= last_pde; i++)
+ {
+ if(0 == (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & MALI_MMU_FLAGS_PRESENT))
+ {
+ /* Page table not present */
+ MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]);
+ MALI_DEBUG_ASSERT(NULL == pagedir->page_entries_mapped[i]);
+
+ err = mali_mmu_get_table_page(&pde_phys, &pde_mapping);
+ if(_MALI_OSK_ERR_OK != err)
+ {
+ MALI_PRINT_ERROR(("Failed to allocate page table page.\n"));
+ return err;
+ }
+ pagedir->page_entries_mapped[i] = pde_mapping;
+
+ /* Update PDE, mark as present */
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32),
+ pde_phys | MALI_MMU_FLAGS_PRESENT);
+
+ MALI_DEBUG_ASSERT(0 == pagedir->page_entries_usage_count[i]);
+ pagedir->page_entries_usage_count[i] = 1;
+ }
+ else
+ {
+ pagedir->page_entries_usage_count[i]++;
+ }
+ }
+ _mali_osk_write_mem_barrier();
+
+ MALI_SUCCESS;
+}
+
+MALI_STATIC_INLINE void mali_mmu_zero_pte(mali_io_address page_table, u32 mali_address, u32 size)
+{
+ int i;
+ const int first_pte = MALI_MMU_PTE_ENTRY(mali_address);
+ const int last_pte = MALI_MMU_PTE_ENTRY(mali_address + size - 1);
+
+ for (i = first_pte; i <= last_pte; i++)
+ {
+ _mali_osk_mem_iowrite32_relaxed(page_table, i * sizeof(u32), 0);
+ }
+}
+
+_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size)
+{
+ const int first_pde = MALI_MMU_PDE_ENTRY(mali_address);
+ const int last_pde = MALI_MMU_PDE_ENTRY(mali_address + size - 1);
+ u32 left = size;
+ int i;
+#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2
+ mali_bool pd_changed = MALI_FALSE;
+ u32 pages_to_invalidate[3]; /* hard-coded to 3: max two pages from the PT level plus max one page from PD level */
+ u32 num_pages_inv = 0;
+#endif
+
+ /* For all page directory entries in range. */
+ for (i = first_pde; i <= last_pde; i++)
+ {
+ u32 size_in_pde, offset;
+
+ MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[i]);
+ MALI_DEBUG_ASSERT(0 != pagedir->page_entries_usage_count[i]);
+
+ /* Offset into page table, 0 if mali_address is 4MiB aligned */
+ offset = (mali_address & (MALI_MMU_VIRTUAL_PAGE_SIZE - 1));
+ if (left < MALI_MMU_VIRTUAL_PAGE_SIZE - offset)
+ {
+ size_in_pde = left;
+ }
+ else
+ {
+ size_in_pde = MALI_MMU_VIRTUAL_PAGE_SIZE - offset;
+ }
+
+ pagedir->page_entries_usage_count[i]--;
+
+ /* If entire page table is unused, free it */
+ if (0 == pagedir->page_entries_usage_count[i])
+ {
+ u32 page_address;
+ MALI_DEBUG_PRINT(4, ("Releasing page table as this is the last reference\n"));
+ /* last reference removed, no need to zero out each PTE */
+
+ page_address = MALI_MMU_ENTRY_ADDRESS(_mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)));
+ pagedir->page_entries_mapped[i] = NULL;
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i*sizeof(u32), 0);
+
+ mali_mmu_release_table_page(page_address);
+#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2
+ pd_changed = MALI_TRUE;
+#endif
+ }
+ else
+ {
+#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2
+ pages_to_invalidate[num_pages_inv] = mali_page_directory_get_phys_address(pagedir, i);
+ num_pages_inv++;
+ MALI_DEBUG_ASSERT(num_pages_inv<3);
+#endif
+
+ /* If part of the page table is still in use, zero the relevant PTEs */
+ mali_mmu_zero_pte(pagedir->page_entries_mapped[i], mali_address, size_in_pde);
+ }
+
+ left -= size_in_pde;
+ mali_address += size_in_pde;
+ }
+ _mali_osk_write_mem_barrier();
+
+#ifndef MALI_UNMAP_FLUSH_ALL_MALI_L2
+ /* L2 pages invalidation */
+ if (MALI_TRUE == pd_changed)
+ {
+ pages_to_invalidate[num_pages_inv] = pagedir->page_directory;
+ num_pages_inv++;
+ MALI_DEBUG_ASSERT(num_pages_inv<3);
+ }
+
+ if (_MALI_PRODUCT_ID_MALI200 != mali_kernel_core_get_product_id())
+ {
+ mali_cluster_invalidate_pages(pages_to_invalidate, num_pages_inv);
+ }
+#endif
+
+ MALI_SUCCESS;
+}
+
+struct mali_page_directory *mali_mmu_pagedir_alloc(void)
+{
+ struct mali_page_directory *pagedir;
+
+ pagedir = _mali_osk_calloc(1, sizeof(struct mali_page_directory));
+ if(NULL == pagedir)
+ {
+ return NULL;
+ }
+
+ if(_MALI_OSK_ERR_OK != mali_mmu_get_table_page(&pagedir->page_directory, &pagedir->page_directory_mapped))
+ {
+ _mali_osk_free(pagedir);
+ return NULL;
+ }
+
+ /* Zero page directory */
+ fill_page(pagedir->page_directory_mapped, 0);
+
+ return pagedir;
+}
+
+void mali_mmu_pagedir_free(struct mali_page_directory *pagedir)
+{
+ const int num_page_table_entries = sizeof(pagedir->page_entries_mapped) / sizeof(pagedir->page_entries_mapped[0]);
+ int i;
+
+ /* Free referenced page tables and zero PDEs. */
+ for (i = 0; i < num_page_table_entries; i++)
+ {
+ if (pagedir->page_directory_mapped && (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, sizeof(u32)*i) & MALI_MMU_FLAGS_PRESENT))
+ {
+ mali_mmu_release_table_page( _mali_osk_mem_ioread32(pagedir->page_directory_mapped, i*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_directory_mapped, i * sizeof(u32), 0);
+ }
+ }
+ _mali_osk_write_mem_barrier();
+
+ /* Free the page directory page. */
+ mali_mmu_release_table_page(pagedir->page_directory);
+
+ _mali_osk_free(pagedir);
+}
+
+
+void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size)
+{
+ u32 end_address = mali_address + size;
+
+ /* Map physical pages into MMU page tables */
+ for ( ; mali_address < end_address; mali_address += MALI_MMU_PAGE_SIZE, phys_address += MALI_MMU_PAGE_SIZE)
+ {
+ MALI_DEBUG_ASSERT_POINTER(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]);
+ _mali_osk_mem_iowrite32_relaxed(pagedir->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)],
+ MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32),
+ phys_address | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT);
+ }
+ _mali_osk_write_mem_barrier();
+}
+
+u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index)
+{
+ return (_mali_osk_mem_ioread32(pagedir->page_directory_mapped, index*sizeof(u32)) & ~MALI_MMU_FLAGS_MASK);
+}
+
+/* For instrumented */
+struct dump_info
+{
+ u32 buffer_left;
+ u32 register_writes_size;
+ u32 page_table_dump_size;
+ u32 *buffer;
+};
+
+static _mali_osk_errcode_t writereg(u32 where, u32 what, const char *comment, struct dump_info *info)
+{
+ if (NULL != info)
+ {
+ info->register_writes_size += sizeof(u32)*2; /* two 32-bit words */
+
+ if (NULL != info->buffer)
+ {
+ /* check that we have enough space */
+ if (info->buffer_left < sizeof(u32)*2) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+ *info->buffer = where;
+ info->buffer++;
+
+ *info->buffer = what;
+ info->buffer++;
+
+ info->buffer_left -= sizeof(u32)*2;
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_page(mali_io_address page, u32 phys_addr, struct dump_info * info)
+{
+ if (NULL != info)
+ {
+ /* 4096 for the page and 4 bytes for the address */
+ const u32 page_size_in_elements = MALI_MMU_PAGE_SIZE / 4;
+ const u32 page_size_in_bytes = MALI_MMU_PAGE_SIZE;
+ const u32 dump_size_in_bytes = MALI_MMU_PAGE_SIZE + 4;
+
+ info->page_table_dump_size += dump_size_in_bytes;
+
+ if (NULL != info->buffer)
+ {
+ if (info->buffer_left < dump_size_in_bytes) MALI_ERROR(_MALI_OSK_ERR_NOMEM);
+
+ *info->buffer = phys_addr;
+ info->buffer++;
+
+ _mali_osk_memcpy(info->buffer, page, page_size_in_bytes);
+ info->buffer += page_size_in_elements;
+
+ info->buffer_left -= dump_size_in_bytes;
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_page_table(struct mali_page_directory *pagedir, struct dump_info * info)
+{
+ MALI_DEBUG_ASSERT_POINTER(pagedir);
+ MALI_DEBUG_ASSERT_POINTER(info);
+
+ if (NULL != pagedir->page_directory_mapped)
+ {
+ int i;
+
+ MALI_CHECK_NO_ERROR(
+ dump_page(pagedir->page_directory_mapped, pagedir->page_directory, info)
+ );
+
+ for (i = 0; i < 1024; i++)
+ {
+ if (NULL != pagedir->page_entries_mapped[i])
+ {
+ MALI_CHECK_NO_ERROR(
+ dump_page(pagedir->page_entries_mapped[i],
+ _mali_osk_mem_ioread32(pagedir->page_directory_mapped,
+ i * sizeof(u32)) & ~MALI_MMU_FLAGS_MASK, info)
+ );
+ }
+ }
+ }
+
+ MALI_SUCCESS;
+}
+
+static _mali_osk_errcode_t dump_mmu_registers(struct mali_page_directory *pagedir, struct dump_info * info)
+{
+ MALI_CHECK_NO_ERROR(writereg(0x00000000, pagedir->page_directory,
+ "set the page directory address", info));
+ MALI_CHECK_NO_ERROR(writereg(0x00000008, 4, "zap???", info));
+ MALI_CHECK_NO_ERROR(writereg(0x00000008, 0, "enable paging", info));
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args )
+{
+ struct dump_info info = { 0, 0, 0, NULL };
+ struct mali_session_data * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)(args->ctx);
+
+ MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info));
+ MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info));
+ args->size = info.register_writes_size + info.page_table_dump_size;
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args )
+{
+ struct dump_info info = { 0, 0, 0, NULL };
+ struct mali_session_data * session_data;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS);
+ MALI_CHECK_NON_NULL(args->buffer, _MALI_OSK_ERR_INVALID_ARGS);
+
+ session_data = (struct mali_session_data *)(args->ctx);
+
+ info.buffer_left = args->size;
+ info.buffer = args->buffer;
+
+ args->register_writes = info.buffer;
+ MALI_CHECK_NO_ERROR(dump_mmu_registers(session_data->page_directory, &info));
+
+ args->page_table_dump = info.buffer;
+ MALI_CHECK_NO_ERROR(dump_mmu_page_table(session_data->page_directory, &info));
+
+ args->register_writes_size = info.register_writes_size;
+ args->page_table_dump_size = info.page_table_dump_size;
+
+ MALI_SUCCESS;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h
new file mode 100644
index 0000000..8aababe
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_mmu_page_directory.h
@@ -0,0 +1,83 @@
+/*
+ * 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_MMU_PAGE_DIRECTORY_H__
+#define __MALI_MMU_PAGE_DIRECTORY_H__
+
+#include "mali_osk.h"
+
+/**
+ * Size of an MMU page in bytes
+ */
+#define MALI_MMU_PAGE_SIZE 0x1000
+
+/*
+ * Size of the address space referenced by a page table page
+ */
+#define MALI_MMU_VIRTUAL_PAGE_SIZE 0x400000 /* 4 MiB */
+
+/**
+ * Page directory index from address
+ * Calculates the page directory index from the given address
+ */
+#define MALI_MMU_PDE_ENTRY(address) (((address)>>22) & 0x03FF)
+
+/**
+ * Page table index from address
+ * Calculates the page table index from the given address
+ */
+#define MALI_MMU_PTE_ENTRY(address) (((address)>>12) & 0x03FF)
+
+/**
+ * Extract the memory address from an PDE/PTE entry
+ */
+#define MALI_MMU_ENTRY_ADDRESS(value) ((value) & 0xFFFFFC00)
+
+#define MALI_INVALID_PAGE ((u32)(~0))
+
+/**
+ *
+ */
+typedef enum mali_mmu_entry_flags
+{
+ MALI_MMU_FLAGS_PRESENT = 0x01,
+ MALI_MMU_FLAGS_READ_PERMISSION = 0x02,
+ MALI_MMU_FLAGS_WRITE_PERMISSION = 0x04,
+ MALI_MMU_FLAGS_MASK = 0x07
+} mali_mmu_entry_flags;
+
+
+struct mali_page_directory
+{
+ u32 page_directory; /**< Physical address of the memory session's page directory */
+ mali_io_address page_directory_mapped; /**< Pointer to the mapped version of the page directory into the kernel's address space */
+
+ mali_io_address page_entries_mapped[1024]; /**< Pointers to the page tables which exists in the page directory mapped into the kernel's address space */
+ u32 page_entries_usage_count[1024]; /**< Tracks usage count of the page table pages, so they can be releases on the last reference */
+};
+
+/* Map Mali virtual address space (i.e. ensure page tables exist for the virtual range) */
+_mali_osk_errcode_t mali_mmu_pagedir_map(struct mali_page_directory *pagedir, u32 mali_address, u32 size);
+_mali_osk_errcode_t mali_mmu_pagedir_unmap(struct mali_page_directory *pagedir, u32 mali_address, u32 size);
+
+/* Back virtual address space with actual pages. Assumes input is contiguous and 4k aligned. */
+void mali_mmu_pagedir_update(struct mali_page_directory *pagedir, u32 mali_address, u32 phys_address, u32 size);
+
+u32 mali_page_directory_get_phys_address(struct mali_page_directory *pagedir, u32 index);
+
+u32 mali_allocate_empty_page(void);
+void mali_free_empty_page(u32 address);
+_mali_osk_errcode_t mali_create_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page);
+void mali_destroy_fault_flush_pages(u32 *page_directory, u32 *page_table, u32 *data_page);
+
+struct mali_page_directory *mali_mmu_pagedir_alloc(void);
+void mali_mmu_pagedir_free(struct mali_page_directory *pagedir);
+
+#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_osk.h b/drivers/media/video/samsung/mali/common/mali_osk.h
index 72d851d..e32d15d 100644
--- a/drivers/media/video/samsung/mali/common/mali_osk.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -165,9 +165,6 @@ typedef void (*_mali_osk_irq_bhandler_t)( void * arg );
* 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.
@@ -186,6 +183,40 @@ typedef struct
/** @defgroup _mali_osk_lock OSK Mutual Exclusion Locks
* @{ */
+
+/** @brief OSK Mutual Exclusion Lock ordered list
+ *
+ * This lists the various types of locks in the system and is used to check
+ * that locks are taken in the correct order.
+ *
+ * Holding more than one lock of the same order at the same time is not
+ * allowed.
+ *
+ */
+typedef enum
+{
+ _MALI_OSK_LOCK_ORDER_LAST = 0,
+
+ _MALI_OSK_LOCK_ORDER_PM_EXECUTE,
+ _MALI_OSK_LOCK_ORDER_UTILIZATION,
+ _MALI_OSK_LOCK_ORDER_L2_COUNTER,
+ _MALI_OSK_LOCK_ORDER_PROFILING,
+ _MALI_OSK_LOCK_ORDER_L2_COMMAND,
+ _MALI_OSK_LOCK_ORDER_PM_CORE_STATE,
+ _MALI_OSK_LOCK_ORDER_GROUP,
+ _MALI_OSK_LOCK_ORDER_SCHEDULER,
+
+ _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP,
+ _MALI_OSK_LOCK_ORDER_MEM_PT_CACHE,
+ _MALI_OSK_LOCK_ORDER_MEM_INFO,
+ _MALI_OSK_LOCK_ORDER_MEM_SESSION,
+
+ _MALI_OSK_LOCK_ORDER_SESSIONS,
+
+ _MALI_OSK_LOCK_ORDER_FIRST
+} _mali_osk_lock_order_t;
+
+
/** @brief OSK Mutual Exclusion Lock flags type
*
* Flags are supplied at the point where the Lock is initialized. Each flag can
@@ -271,6 +302,17 @@ typedef enum
/** @brief Private type for Mutual Exclusion lock objects */
typedef struct _mali_osk_lock_t_struct _mali_osk_lock_t;
+
+#ifdef DEBUG
+/** @brief Macro for asserting that the current thread holds a given lock
+ */
+#define MALI_DEBUG_ASSERT_LOCK_HELD(l) MALI_DEBUG_ASSERT(_mali_osk_lock_get_owner(l) == _mali_osk_get_tid());
+
+/** @brief returns a lock's owner (thread id) if debugging is enabled
+ */
+u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock );
+#endif
+
/** @} */ /* end group _mali_osk_lock */
/** @defgroup _mali_osk_low_level_memory OSK Low-level Memory Operations
@@ -368,7 +410,6 @@ typedef struct _mali_osk_notification_queue_t_struct _mali_osk_notification_queu
/** @brief Public notification data object type */
typedef struct _mali_osk_notification_t_struct
{
- u32 magic_code;
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 */
@@ -527,20 +568,35 @@ typedef struct _mali_osk_list_s
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 */
+
+ MALI_PP =2, /**< Mali Pixel Processor core */
+ MALI450PP =2, /**< Compatibility option */
+ MALI400PP =2, /**< Compatibility option */
+ MALI300PP =2, /**< Compatibility option */
+ MALI200 =2, /**< Compatibility option */
+
+ MALI_GP =3, /**< Mali Geometry Processor core */
+ MALI450GP =3, /**< Compatibility option */
+ MALI400GP =3, /**< Compatibility option */
+ MALI300GP =3, /**< Compatibility option */
+ MALIGP2 =3, /**< Compatibility option */
+
+ MMU =4, /**< Mali MMU (Memory Management Unit) */
+
+ FPGA_FRAMEWORK =5, /**< Mali registers specific to FPGA implementations */
+
+ MALI_L2 =6, /**< Mali Level 2 cache core */
+ MALI450L2 =6, /**< Compatibility option */
+ MALI400L2 =6, /**< Compatibility option */
+ MALI300L2 =6, /**< Compatibility option */
+
+ MEM_VALIDATION =7, /**< External Memory Validator */
+
+ PMU =8, /**< Power Manangement Unit */
+
RESOURCE_TYPE_COUNT /**< The total number of known resources */
} _mali_osk_resource_type_t;
@@ -726,11 +782,6 @@ 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 );
@@ -744,19 +795,11 @@ 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.
*
@@ -769,9 +812,6 @@ _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.
@@ -1624,6 +1664,41 @@ u64 _mali_osk_time_get_ns( void );
u32 _mali_osk_clz( u32 val );
/** @} */ /* end group _mali_osk_math */
+/** @defgroup _mali_osk_wait_queue OSK Wait Queue functionality
+ * @{ */
+/** @brief Private type for wait queue objects */
+typedef struct _mali_osk_wait_queue_t_struct _mali_osk_wait_queue_t;
+
+/** @brief Initialize an empty Wait Queue */
+_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void );
+
+/** @brief Sleep if condition is false
+ *
+ * @param queue the queue to use
+ * @param condition function pointer to a boolean function
+ *
+ * Put thread to sleep if the given \a codition function returns false. When
+ * being asked to wake up again, the condition will be re-checked and the
+ * thread only woken up if the condition is now true.
+ */
+void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) );
+
+/** @brief Wake up all threads in wait queue if their respective conditions are
+ * true
+ *
+ * @param queue the queue whose threads should be woken up
+ *
+ * Wake up all threads in wait queue \a queue whose condition is now true.
+ */
+void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue );
+
+/** @brief terminate a wait queue
+ *
+ * @param queue the queue to terminate.
+ */
+void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue );
+/** @} */ /* end group _mali_osk_wait_queue */
+
/** @addtogroup _mali_osk_miscellaneous
* @{ */
@@ -1647,6 +1722,7 @@ void _mali_osk_dbgmsg( const char *fmt, ... );
* @param size the total number of bytes allowed to write to \a buf
* @param fmt a _mali_osu_vsnprintf() style format string
* @param ... a variable-number of parameters suitable for \a fmt
+ * @return The number of bytes written to \a buf
*/
u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... );
@@ -1685,13 +1761,19 @@ u32 _mali_osk_get_pid(void);
*/
u32 _mali_osk_get_tid(void);
-void _mali_osk_profiling_add_event(u32 event_id, u32 data0);
-void _mali_osk_profiling_add_counter(u32 event_id, u32 data0);
-int _mali_osk_counter_event(u32 counter, u32 event);
-extern u32 counter_table[];
+/** @brief Enable OS controlled runtime power management
+ */
+void _mali_osk_pm_dev_enable(void);
-/** @} */ /* end group _mali_osk_miscellaneous */
+/** @brief Tells the OS that device is now idle
+ */
+_mali_osk_errcode_t _mali_osk_pm_dev_idle(void);
+/** @brief Tells the OS that the device is about to become active
+ */
+_mali_osk_errcode_t _mali_osk_pm_dev_activate(void);
+
+/** @} */ /* end group _mali_osk_miscellaneous */
/** @} */ /* end group osuapi */
diff --git a/drivers/media/video/samsung/mali/common/mali_osk_list.h b/drivers/media/video/samsung/mali/common/mali_osk_list.h
index 3a562bb..a8d15f2 100644
--- a/drivers/media/video/samsung/mali/common/mali_osk_list.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk_list.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/common/mali_osk_mali.h b/drivers/media/video/samsung/mali/common/mali_osk_mali.h
index 0b1d13a..427fcc8 100644
--- a/drivers/media/video/samsung/mali/common/mali_osk_mali.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk_mali.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -26,36 +26,6 @@ extern "C"
/** @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
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.h b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h
index eb1e6c2..fd9a8fb 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.h
+++ b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,31 +8,34 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_PROFILING_H__
-#define __MALI_KERNEL_PROFILING_H__
+#ifndef __MALI_OSK_PROFILING_H__
+#define __MALI_OSK_PROFILING_H__
#if MALI_TIMELINE_PROFILING_ENABLED
-#include "cinstr/mali_cinstr_profiling_events_m200.h"
+#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#include "mali_linux_trace.h"
+#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */
+
+#include "mali_profiling_events.h"
#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576
+#define MALI_PROFILING_NO_HW_COUNTER = ((u32)-1)
+
+/** @defgroup _mali_osk_profiling External profiling connectivity
+ * @{ */
+
/**
* Initialize the profiling module.
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_init(mali_bool auto_start);
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start);
/*
* Terminate the profiling module.
*/
-void _mali_profiling_term(void);
-
-/** Add a counter event
- * @param event_id - Magic counter id
- * @param data0 - Value of counter
- */
-void _mali_profiling_add_counter(u32 event_id, u32 data0);
+void _mali_osk_profiling_term(void);
/**
* Start recording profiling data
@@ -43,7 +46,7 @@ void _mali_profiling_add_counter(u32 event_id, u32 data0);
* @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);
+_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit);
/**
* Add an profiling event
@@ -56,7 +59,35 @@ _mali_osk_errcode_t _mali_profiling_start(u32 * limit);
* @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);
+#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+/* Call Linux tracepoint directly */
+#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4))
+#else
+/* Internal profiling is handled like a plain function call */
+void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4);
+#endif
+
+/**
+ * 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
+/* Call Linux tracepoint directly */
+#define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value)
+#else
+/* Internal profiling is handled like a plain function call */
+void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value);
+#endif
+
+/**
+ * Report SW counters
+ *
+ * @param counters array of counter values
+ */
+void _mali_osk_profiling_report_sw_counters(u32 *counters);
/**
* Stop recording profiling data
@@ -64,14 +95,14 @@ _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1
* @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);
+_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_profiling_get_count(void);
+u32 _mali_osk_profiling_get_count(void);
/**
* Retrieve an event
@@ -81,7 +112,8 @@ u32 _mali_profiling_get_count(void);
* @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]);
+ */
+_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]);
/**
* Clear the recorded buffer.
@@ -90,38 +122,26 @@ u32 _mali_profiling_get_count(void);
*
* @return _MALI_OSK_ERR_OK on success, otherwise failure.
*/
-_mali_osk_errcode_t _mali_profiling_clear(void);
+_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_profiling_is_recording(void);
+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_profiling_have_recording(void);
+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_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);
+/** @} */ /* end group _mali_osk_profiling */
#endif /* MALI_TIMELINE_PROFILING_ENABLED */
-#endif /* __MALI_KERNEL_PROFILING_H__ */
+#endif /* __MALI_OSK_PROFILING_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pm.c b/drivers/media/video/samsung/mali/common/mali_pm.c
new file mode 100644
index 0000000..1ef3807
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pm.c
@@ -0,0 +1,547 @@
+/*
+ * 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_pm.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_gp_scheduler.h"
+#include "mali_pp_scheduler.h"
+#include "mali_platform.h"
+#include "mali_kernel_utilization.h"
+#include "mali_kernel_core.h"
+#include "mali_group.h"
+
+#define MALI_PM_LIGHT_SLEEP_TIMEOUT 1000
+
+enum mali_pm_scheme
+{
+ MALI_PM_SCHEME_DYNAMIC,
+ MALI_PM_SCHEME_OS_SUSPENDED,
+ MALI_PM_SCHEME_ALWAYS_ON
+};
+
+enum mali_pm_level
+{
+ MALI_PM_LEVEL_1_ON,
+ MALI_PM_LEVEL_2_STANDBY,
+ MALI_PM_LEVEL_3_LIGHT_SLEEP,
+ MALI_PM_LEVEL_4_DEEP_SLEEP
+};
+static _mali_osk_lock_t *mali_pm_lock_set_next_state;
+static _mali_osk_lock_t *mali_pm_lock_set_core_states;
+static _mali_osk_lock_t *mali_pm_lock_execute_state_change;
+static _mali_osk_irq_t *wq_irq;
+
+static _mali_osk_timer_t *idle_timer = NULL;
+static mali_bool idle_timer_running = MALI_FALSE;
+static u32 mali_pm_event_number = 0;
+
+static u32 num_active_gps = 0;
+static u32 num_active_pps = 0;
+
+static enum mali_pm_scheme current_scheme = MALI_PM_SCHEME_DYNAMIC;
+static enum mali_pm_level current_level = MALI_PM_LEVEL_1_ON;
+static enum mali_pm_level next_level_dynamic = MALI_PM_LEVEL_2_STANDBY; /* Should be the state we go to when we go out of MALI_PM_SCHEME_ALWAYS_ON during init */
+
+
+
+static _mali_osk_errcode_t mali_pm_upper_half(void *data);
+static void mali_pm_bottom_half(void *data);
+static void mali_pm_powerup(void);
+static void mali_pm_powerdown(mali_power_mode power_mode);
+
+static void timeout_light_sleep(void* arg);
+#if 0
+/* Deep sleep timout not supported */
+static void timeout_deep_sleep(void* arg);
+#endif
+static u32 mali_pm_event_number_get(void);
+static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time );
+
+_mali_osk_errcode_t mali_pm_initialize(void)
+{
+ mali_pm_lock_execute_state_change = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_EXECUTE);
+
+ if (NULL != mali_pm_lock_execute_state_change )
+ {
+ mali_pm_lock_set_next_state = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ONELOCK| _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_LAST);
+
+ if (NULL != mali_pm_lock_set_next_state)
+ {
+ mali_pm_lock_set_core_states = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PM_CORE_STATE);
+
+ if (NULL != mali_pm_lock_set_core_states)
+ {
+ idle_timer = _mali_osk_timer_init();
+ if (NULL != idle_timer)
+ {
+ wq_irq = _mali_osk_irq_init(_MALI_OSK_IRQ_NUMBER_PMM,
+ mali_pm_upper_half,
+ mali_pm_bottom_half,
+ NULL,
+ NULL,
+ (void *)NULL,
+ "Mali PM deferred work");
+ if (NULL != wq_irq)
+ {
+ if (_MALI_OSK_ERR_OK == mali_platform_init())
+ {
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ _mali_osk_pm_dev_enable();
+ mali_pm_powerup();
+#endif
+ return _MALI_OSK_ERR_OK;
+ }
+
+ _mali_osk_irq_term(wq_irq);
+ }
+
+ _mali_osk_timer_del(idle_timer);
+ _mali_osk_timer_term(idle_timer);
+ }
+ _mali_osk_lock_term(mali_pm_lock_set_core_states);
+ }
+ _mali_osk_lock_term(mali_pm_lock_set_next_state);
+ }
+ _mali_osk_lock_term(mali_pm_lock_execute_state_change);
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+void mali_pm_terminate(void)
+{
+ mali_platform_deinit();
+ _mali_osk_irq_term(wq_irq);
+ _mali_osk_timer_del(idle_timer);
+ _mali_osk_timer_term(idle_timer);
+ _mali_osk_lock_term(mali_pm_lock_execute_state_change);
+ _mali_osk_lock_term(mali_pm_lock_set_next_state);
+ _mali_osk_lock_term(mali_pm_lock_set_core_states);
+}
+
+
+inline void mali_pm_lock(void)
+{
+ _mali_osk_lock_wait(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW);
+}
+
+inline void mali_pm_unlock(void)
+{
+ _mali_osk_lock_signal(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW);
+}
+
+inline void mali_pm_execute_state_change_lock(void)
+{
+ _mali_osk_lock_wait(mali_pm_lock_execute_state_change,_MALI_OSK_LOCKMODE_RW);
+}
+
+inline void mali_pm_execute_state_change_unlock(void)
+{
+ _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
+}
+
+static void mali_pm_powerup(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n"));
+ mali_platform_power_mode_change(MALI_POWER_MODE_ON);
+
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+
+ /* Aquire our reference */
+ MALI_DEBUG_PRINT(4, ("Mali PM: Getting device PM reference (=> requesting MALI_POWER_MODE_ON)\n"));
+ _mali_osk_pm_dev_activate();
+#endif
+
+ mali_group_power_on();
+}
+
+static void mali_pm_powerdown(mali_power_mode power_mode)
+{
+ if ( (MALI_PM_LEVEL_1_ON == current_level) || (MALI_PM_LEVEL_2_STANDBY == current_level) )
+ {
+ mali_group_power_off();
+ }
+ mali_platform_power_mode_change(power_mode);
+
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ _mali_osk_pm_dev_idle();
+#endif
+}
+
+mali_bool mali_pm_is_powered_on(void)
+{
+ mali_bool is_on = MALI_TRUE;
+
+ if( ! (MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme) )
+ {
+ is_on = MALI_FALSE;
+ }
+ else if ( ! (MALI_PM_LEVEL_1_ON == current_level || MALI_PM_LEVEL_2_STANDBY == current_level))
+ {
+ is_on = MALI_FALSE;
+ }
+ else if ( ! (MALI_PM_LEVEL_1_ON == next_level_dynamic || MALI_PM_LEVEL_2_STANDBY == next_level_dynamic))
+ {
+ is_on = MALI_FALSE;
+ }
+
+ return is_on;
+}
+
+MALI_DEBUG_CODE(
+static const char *state_as_string(enum mali_pm_level level)
+{
+ switch(level)
+ {
+ case MALI_PM_LEVEL_1_ON:
+ return "MALI_PM_LEVEL_1_ON";
+ case MALI_PM_LEVEL_2_STANDBY:
+ return "MALI_PM_LEVEL_2_STANDBY";
+ case MALI_PM_LEVEL_3_LIGHT_SLEEP:
+ return "MALI_PM_LEVEL_3_LIGHT_SLEEP";
+ case MALI_PM_LEVEL_4_DEEP_SLEEP:
+ return "MALI_PM_LEVEL_4_DEEP_SLEEP";
+ default:
+ return "UNKNOWN LEVEL";
+ }
+});
+
+/* This could be used from another thread (work queue), if we need that */
+static void mali_pm_process_next(void)
+{
+ enum mali_pm_level pm_level_to_set;
+
+ _mali_osk_lock_wait(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
+
+ pm_level_to_set = current_level;
+
+ if (MALI_PM_SCHEME_DYNAMIC == current_scheme)
+ {
+ pm_level_to_set = next_level_dynamic;
+
+ MALI_DEBUG_PRINT(4, ("Mali PM: Dynamic scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(pm_level_to_set)));
+
+ if (current_level == pm_level_to_set)
+ {
+ goto end_function; /* early out, no change in power level */
+ }
+
+ /* Start timers according to new state, so we get STANDBY -> LIGHT_SLEEP -> DEEP_SLEEP */
+
+ if (MALI_TRUE == idle_timer_running)
+ {
+ /* There is an existing timeout, so delete it */
+ _mali_osk_timer_del(idle_timer);
+ idle_timer_running = MALI_FALSE;
+ }
+
+ /* Making sure that we turn on through the platform file
+ Since it was turned OFF directly through the platform file.
+ This might lead to double turn-on, but the plaform file supports that.*/
+ if ( current_level == MALI_PM_LEVEL_4_DEEP_SLEEP)
+ {
+ mali_pm_powerup();
+ mali_kernel_core_wakeup();
+
+ }
+ if (MALI_PM_LEVEL_1_ON == pm_level_to_set)
+ {
+ if (MALI_PM_LEVEL_2_STANDBY != current_level)
+ {
+ /* We only need to do anything if we came from one of the sleeping states */
+ mali_pm_powerup();
+
+ /* Wake up Mali cores since we came from a sleep state */
+ mali_kernel_core_wakeup();
+ }
+ }
+ else if (MALI_PM_LEVEL_2_STANDBY == pm_level_to_set)
+ {
+ /* This is just an internal state, so we don't bother to report it to the platform file */
+ idle_timer_running = MALI_TRUE;
+ _mali_osk_timer_setcallback(idle_timer, timeout_light_sleep, (void*) mali_pm_event_number_get());
+ _mali_osk_timer_add(idle_timer, _mali_osk_time_mstoticks(MALI_PM_LIGHT_SLEEP_TIMEOUT));
+ }
+ else if (MALI_PM_LEVEL_3_LIGHT_SLEEP == pm_level_to_set)
+ {
+ mali_pm_powerdown(MALI_POWER_MODE_LIGHT_SLEEP);
+ }
+ else if (MALI_PM_LEVEL_4_DEEP_SLEEP == pm_level_to_set)
+ {
+ MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n"));
+ mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP);
+ }
+ }
+ else if (MALI_PM_SCHEME_OS_SUSPENDED == current_scheme)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PM: OS scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_4_DEEP_SLEEP)));
+
+ pm_level_to_set = MALI_PM_LEVEL_4_DEEP_SLEEP;
+
+ if (current_level == pm_level_to_set)
+ {
+ goto end_function; /* early out, no change in power level */
+ }
+
+ /* Cancel any timers */
+ if (MALI_TRUE == idle_timer_running)
+ {
+ /* There is an existing timeout, so delete it */
+ _mali_osk_timer_del(idle_timer);
+ idle_timer_running = MALI_FALSE;
+ }
+
+ MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n"));
+ mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP);
+ next_level_dynamic = current_level;
+ }
+ else if (MALI_PM_SCHEME_ALWAYS_ON == current_scheme)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PM: Always on scheme; Changing Mali GPU power state from %s to: %s\n", state_as_string(current_level), state_as_string(MALI_PM_LEVEL_1_ON)));
+
+ pm_level_to_set = MALI_PM_LEVEL_1_ON;
+ if (current_level == pm_level_to_set)
+ {
+ goto end_function; /* early out, no change in power level */
+ }
+
+ MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n"));
+ mali_pm_powerup();
+ if (MALI_PM_LEVEL_2_STANDBY != current_level)
+ {
+ /* Wake up Mali cores since we came from a sleep state */
+ mali_kernel_core_wakeup();
+ }
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("MALI PM: Illegal scheme"));
+ }
+
+ current_level = pm_level_to_set;
+
+end_function:
+ _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
+
+}
+
+void mali_pm_always_on(mali_bool enable)
+{
+ if (MALI_TRUE == enable)
+ {
+ /* The event is processed in current thread synchronously */
+ mali_pm_event(MALI_PM_EVENT_SCHEME_ALWAYS_ON, MALI_FALSE, 0 );
+ }
+ else
+ {
+ /* The event is processed in current thread synchronously */
+ mali_pm_event(MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, MALI_FALSE, 0 );
+ }
+}
+
+static _mali_osk_errcode_t mali_pm_upper_half(void *data)
+{
+ /* not used */
+ return _MALI_OSK_ERR_OK;
+}
+
+static void mali_pm_bottom_half(void *data)
+{
+ mali_pm_process_next();
+}
+
+static u32 mali_pm_event_number_get(void)
+{
+ u32 retval;
+
+ mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */
+ retval = ++mali_pm_event_number;
+ if (0==retval ) retval = ++mali_pm_event_number;
+ mali_pm_unlock();
+
+ return retval;
+}
+
+static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time )
+{
+ mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */
+ /* Only timer events should set this variable, all other events must set it to zero. */
+ if ( 0 != timer_time )
+ {
+ MALI_DEBUG_ASSERT( (pm_event==MALI_PM_EVENT_TIMER_LIGHT_SLEEP) || (pm_event==MALI_PM_EVENT_TIMER_DEEP_SLEEP) );
+ if ( mali_pm_event_number != timer_time )
+ {
+ /* In this case there have been processed newer events since the timer event was set up.
+ If so we always ignore the timing event */
+ mali_pm_unlock();
+ return;
+ }
+ }
+ else
+ {
+ /* Delete possible ongoing timers
+ if ( (MALI_PM_LEVEL_2_STANDBY==current_level) || (MALI_PM_LEVEL_3_LIGHT_SLEEP==current_level) )
+ {
+ _mali_osk_timer_del(idle_timer);
+ }
+ */
+ }
+ mali_pm_event_number++;
+ switch (pm_event)
+ {
+ case MALI_PM_EVENT_CORES_WORKING:
+ next_level_dynamic = MALI_PM_LEVEL_1_ON;
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );
+ break;
+ case MALI_PM_EVENT_CORES_IDLE:
+ next_level_dynamic = MALI_PM_LEVEL_2_STANDBY;
+ /*MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );*/
+ break;
+ case MALI_PM_EVENT_TIMER_LIGHT_SLEEP:
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme );
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );
+ next_level_dynamic = MALI_PM_LEVEL_3_LIGHT_SLEEP;
+ break;
+ case MALI_PM_EVENT_TIMER_DEEP_SLEEP:
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme );
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );
+ next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP;
+ break;
+ case MALI_PM_EVENT_OS_SUSPEND:
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme );
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );
+ current_scheme = MALI_PM_SCHEME_OS_SUSPENDED;
+ next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; /* Dynamic scheme will go into level when we are resumed */
+ break;
+ case MALI_PM_EVENT_OS_RESUME:
+ MALI_DEBUG_ASSERT(MALI_PM_SCHEME_OS_SUSPENDED == current_scheme );
+ current_scheme = MALI_PM_SCHEME_DYNAMIC;
+ break;
+ case MALI_PM_EVENT_SCHEME_ALWAYS_ON:
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );
+ current_scheme = MALI_PM_SCHEME_ALWAYS_ON;
+ break;
+ case MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL:
+ MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme );
+ current_scheme = MALI_PM_SCHEME_DYNAMIC;
+ break;
+ default:
+ MALI_DEBUG_PRINT_ERROR(("Unknown next state."));
+ mali_pm_unlock();
+ return;
+ }
+ mali_pm_unlock();
+
+ if (MALI_TRUE == schedule_work)
+ {
+ _mali_osk_irq_schedulework(wq_irq);
+ }
+ else
+ {
+ mali_pm_process_next();
+ }
+}
+
+static void timeout_light_sleep(void* arg)
+{
+ /* State change only if no newer power events have happend from the time in arg.
+ Actual work will be scheduled on worker thread. */
+ mali_pm_event(MALI_PM_EVENT_TIMER_LIGHT_SLEEP, MALI_TRUE, (u32) arg);
+}
+
+void mali_pm_core_event(enum mali_core_event core_event)
+{
+ mali_bool transition_working = MALI_FALSE;
+ mali_bool transition_idle = MALI_FALSE;
+
+ _mali_osk_lock_wait(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW);
+
+ switch (core_event)
+ {
+ case MALI_CORE_EVENT_GP_START:
+ if (num_active_pps + num_active_gps == 0)
+ {
+ transition_working = MALI_TRUE;
+ }
+ num_active_gps++;
+ break;
+ case MALI_CORE_EVENT_GP_STOP:
+ if (num_active_pps + num_active_gps == 1)
+ {
+ transition_idle = MALI_TRUE;
+ }
+ num_active_gps--;
+ break;
+ case MALI_CORE_EVENT_PP_START:
+ if (num_active_pps + num_active_gps == 0)
+ {
+ transition_working = MALI_TRUE;
+ }
+ num_active_pps++;
+ break;
+ case MALI_CORE_EVENT_PP_STOP:
+ if (num_active_pps + num_active_gps == 1)
+ {
+ transition_idle = MALI_TRUE;
+ }
+ num_active_pps--;
+ break;
+ }
+
+ if (transition_working == MALI_TRUE)
+ {
+#ifdef CONFIG_MALI400_GPU_UTILIZATION
+ mali_utilization_core_start(_mali_osk_time_get_ns());
+#endif
+ mali_pm_event(MALI_PM_EVENT_CORES_WORKING, MALI_FALSE, 0); /* process event in same thread */
+ }
+ else if (transition_idle == MALI_TRUE)
+ {
+#ifdef CONFIG_MALI400_GPU_UTILIZATION
+ mali_utilization_core_end(_mali_osk_time_get_ns());
+#endif
+ mali_pm_event(MALI_PM_EVENT_CORES_IDLE, MALI_FALSE, 0); /* process event in same thread */
+ }
+
+ _mali_osk_lock_signal(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW);
+}
+
+void mali_pm_os_suspend(void)
+{
+ MALI_DEBUG_PRINT(2, ("Mali PM: OS suspending...\n"));
+
+ mali_gp_scheduler_suspend();
+ mali_pp_scheduler_suspend();
+ mali_pm_event(MALI_PM_EVENT_OS_SUSPEND, MALI_FALSE, 0); /* process event in same thread */
+
+ MALI_DEBUG_PRINT(2, ("Mali PM: OS suspend completed\n"));
+}
+
+void mali_pm_os_resume(void)
+{
+ MALI_DEBUG_PRINT(2, ("Mali PM: OS resuming...\n"));
+
+ mali_pm_event(MALI_PM_EVENT_OS_RESUME, MALI_FALSE, 0); /* process event in same thread */
+ mali_gp_scheduler_resume();
+ mali_pp_scheduler_resume();
+
+ MALI_DEBUG_PRINT(2, ("Mali PM: OS resume completed\n"));
+}
+
+void mali_pm_runtime_suspend(void)
+{
+ MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime suspended\n"));
+}
+
+void mali_pm_runtime_resume(void)
+{
+ MALI_DEBUG_PRINT(3, ("Mali PM: OS runtime resumed\n"));
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_pm.h b/drivers/media/video/samsung/mali/common/mali_pm.h
new file mode 100644
index 0000000..d4ccfde
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pm.h
@@ -0,0 +1,56 @@
+/*
+ * 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_PM_H__
+#define __MALI_PM_H__
+
+#include "mali_osk.h"
+
+enum mali_core_event
+{
+ MALI_CORE_EVENT_GP_START,
+ MALI_CORE_EVENT_GP_STOP,
+ MALI_CORE_EVENT_PP_START,
+ MALI_CORE_EVENT_PP_STOP
+};
+
+enum mali_pm_event
+{
+ MALI_PM_EVENT_CORES_WORKING,
+ MALI_PM_EVENT_CORES_IDLE,
+ MALI_PM_EVENT_TIMER_LIGHT_SLEEP,
+ MALI_PM_EVENT_TIMER_DEEP_SLEEP,
+ MALI_PM_EVENT_OS_SUSPEND,
+ MALI_PM_EVENT_OS_RESUME,
+ MALI_PM_EVENT_SCHEME_ALWAYS_ON,
+ MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL,
+};
+
+_mali_osk_errcode_t mali_pm_initialize(void);
+void mali_pm_terminate(void);
+void mali_pm_always_on(mali_bool enable);
+
+void mali_pm_lock(void);
+void mali_pm_unlock(void);
+void mali_pm_execute_state_change_lock(void);
+
+void mali_pm_execute_state_change_unlock(void);
+
+mali_bool mali_pm_is_powered_on(void);
+
+void mali_pm_core_event(enum mali_core_event core_event);
+
+void mali_pm_os_suspend(void);
+void mali_pm_os_resume(void);
+void mali_pm_runtime_suspend(void);
+void mali_pm_runtime_resume(void);
+
+
+#endif /* __MALI_PM_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.c b/drivers/media/video/samsung/mali/common/mali_pmu.c
new file mode 100644
index 0000000..348b5dc
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pmu.c
@@ -0,0 +1,199 @@
+/*
+ * 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_pmu.c
+ * Mali driver functions for Mali 400 PMU hardware
+ */
+#include "mali_hw_core.h"
+#include "mali_pmu.h"
+#include "mali_pp.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches);
+
+/** @brief MALI inbuilt PMU hardware info and PMU hardware has knowledge of cores power mask
+ */
+struct mali_pmu_core
+{
+ struct mali_hw_core hw_core;
+ u32 mali_registered_cores_power_mask;
+};
+
+static struct mali_pmu_core *mali_global_pmu_core = NULL;
+
+/** @brief Register layout for hardware PMU
+ */
+typedef enum {
+ PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */
+ PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */
+ PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */
+ PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */
+ PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x10, /*< Size of register space */
+} pmu_reg_addr_mgmt_addr;
+
+struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches)
+{
+ struct mali_pmu_core* pmu;
+
+ MALI_DEBUG_ASSERT(NULL == mali_global_pmu_core);
+ MALI_DEBUG_PRINT(2, ("Mali PMU: Creating Mali PMU core\n"));
+
+ pmu = (struct mali_pmu_core *)_mali_osk_malloc(sizeof(struct mali_pmu_core));
+ if (NULL != pmu)
+ {
+ pmu->mali_registered_cores_power_mask = mali_pmu_detect_mask(number_of_pp_cores, number_of_l2_caches);
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&pmu->hw_core, resource, PMU_REGISTER_ADDRESS_SPACE_SIZE))
+ {
+ if (_MALI_OSK_ERR_OK == mali_pmu_reset(pmu))
+ {
+ mali_global_pmu_core = pmu;
+ return pmu;
+ }
+ mali_hw_core_delete(&pmu->hw_core);
+ }
+ _mali_osk_free(pmu);
+ }
+
+ return NULL;
+}
+
+void mali_pmu_delete(struct mali_pmu_core *pmu)
+{
+ MALI_DEBUG_ASSERT_POINTER(pmu);
+
+ mali_hw_core_delete(&pmu->hw_core);
+ _mali_osk_free(pmu);
+ pmu = NULL;
+}
+
+_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu)
+{
+ /* Don't use interrupts - just poll status */
+ mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_INT_MASK, 0);
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu)
+{
+ u32 stat;
+ u32 timeout;
+
+ MALI_DEBUG_ASSERT_POINTER(pmu);
+ MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 );
+ MALI_DEBUG_PRINT( 4, ("Mali PMU: power down (0x%08X)\n", pmu->mali_registered_cores_power_mask) );
+
+ mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_DOWN, pmu->mali_registered_cores_power_mask);
+
+ /* Wait for cores to be powered down (100 x 100us = 100ms) */
+ timeout = 100;
+ do
+ {
+ /* Get status of sleeping cores */
+ stat = mali_hw_core_register_read(&pmu->hw_core, PMU_REG_ADDR_MGMT_STATUS);
+ stat &= pmu->mali_registered_cores_power_mask;
+ if( stat == pmu->mali_registered_cores_power_mask ) break; /* All cores we wanted are now asleep */
+ _mali_osk_time_ubusydelay(100);
+ timeout--;
+ } while( timeout > 0 );
+
+ if( timeout == 0 )
+ {
+ return _MALI_OSK_ERR_TIMEOUT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu)
+{
+ u32 stat;
+ u32 timeout;
+
+ MALI_DEBUG_ASSERT_POINTER(pmu);
+ MALI_DEBUG_ASSERT( pmu->mali_registered_cores_power_mask != 0 ); /* Shouldn't be zero */
+ MALI_DEBUG_PRINT( 4, ("Mali PMU: power up (0x%08X)\n", pmu->mali_registered_cores_power_mask) );
+
+ mali_hw_core_register_write(&pmu->hw_core, PMU_REG_ADDR_MGMT_POWER_UP, pmu->mali_registered_cores_power_mask);
+
+ /* Wait for cores to be powered up (100 x 100us = 100ms) */
+ timeout = 100;
+ do
+ {
+ /* Get status of sleeping cores */
+ stat = mali_hw_core_register_read(&pmu->hw_core,PMU_REG_ADDR_MGMT_STATUS);
+ stat &= pmu->mali_registered_cores_power_mask;
+ if( stat == 0 ) break; /* All cores we wanted are now awake */
+ _mali_osk_time_ubusydelay(100);
+ timeout--;
+ } while( timeout > 0 );
+
+ if( timeout == 0 )
+ {
+ return _MALI_OSK_ERR_TIMEOUT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+struct mali_pmu_core *mali_pmu_get_global_pmu_core(void)
+{
+ return mali_global_pmu_core;
+}
+
+static u32 mali_pmu_detect_mask(u32 number_of_pp_cores, u32 number_of_l2_caches)
+{
+ u32 mask = 0;
+
+ if (number_of_l2_caches == 1)
+ {
+ /* Mali-300 or Mali-400 */
+ u32 i;
+
+ /* GP */
+ mask = 0x01;
+
+ /* L2 cache */
+ mask |= 0x01<<1;
+
+ /* Set bit for each PP core */
+ for (i = 0; i < number_of_pp_cores; i++)
+ {
+ mask |= 0x01<<(i+2);
+ }
+ }
+ else if (number_of_l2_caches > 1)
+ {
+ /* Mali-450 */
+
+ /* GP (including its L2 cache) */
+ mask = 0x01;
+
+ /* There is always at least one PP (including its L2 cache) */
+ mask |= 0x01<<1;
+
+ /* Additional PP cores in same L2 cache */
+ if (number_of_pp_cores >= 2)
+ {
+ mask |= 0x01<<2;
+ }
+
+ /* Additional PP cores in a third L2 cache */
+ if (number_of_pp_cores >= 5)
+ {
+ mask |= 0x01<<3;
+ }
+ }
+
+ MALI_DEBUG_PRINT(4, ("Mali PMU: Power mask is 0x%08X (%u + %u)\n", mask, number_of_pp_cores, number_of_l2_caches));
+
+ return mask;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_pmu.h b/drivers/media/video/samsung/mali/common/mali_pmu.h
new file mode 100644
index 0000000..fd10c08
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pmu.h
@@ -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.
+ */
+
+/**
+ * @file mali_platform.h
+ * Platform specific Mali driver functions
+ */
+
+#include "mali_osk.h"
+
+struct mali_pmu_core;
+
+/** @brief Initialisation of MALI PMU
+ *
+ * This is called from entry point of the driver in order to create and intialize the PMU resource
+ *
+ * @param resource it will be a pointer to a PMU resource
+ * @param number_of_pp_cores Number of found PP resources in configuration
+ * @param number_of_l2_caches Number of found L2 cache resources in configuration
+ * @return The created PMU object, or NULL in case of failure.
+ */
+struct mali_pmu_core *mali_pmu_create(_mali_osk_resource_t *resource, u32 number_of_pp_cores, u32 number_of_l2_caches);
+
+/** @brief It deallocates the PMU resource
+ *
+ * This is called on the exit of the driver to terminate the PMU resource
+ *
+ * @param pmu Pointer to PMU core object to delete
+ */
+void mali_pmu_delete(struct mali_pmu_core *pmu);
+
+/** @brief Reset PMU core
+ *
+ * @param pmu Pointer to PMU core object to reset
+ * @return _MALI_OSK_ERR_OK on success, otherwise failure.
+ */
+_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu);
+
+/** @brief MALI GPU power down using MALI in-built PMU
+ *
+ * called to power down all cores
+ *
+ * @param pmu Pointer to PMU core object to power down
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmu_powerdown_all(struct mali_pmu_core *pmu);
+
+
+/** @brief MALI GPU power up using MALI in-built PMU
+ *
+ * called to power up all cores
+ *
+ * @param pmu Pointer to PMU core object to power up
+ * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
+ */
+_mali_osk_errcode_t mali_pmu_powerup_all(struct mali_pmu_core *pmu);
+
+
+/** @brief Retrieves the Mali PMU core object (if any)
+ *
+ * @return The Mali PMU object, or NULL if no PMU exists.
+ */
+struct mali_pmu_core *mali_pmu_get_global_pmu_core(void);
diff --git a/drivers/media/video/samsung/mali/common/mali_pp.c b/drivers/media/video/samsung/mali/common/mali_pp.c
new file mode 100644
index 0000000..5549f82
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp.c
@@ -0,0 +1,710 @@
+/*
+ * 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_pp.h"
+#include "mali_hw_core.h"
+#include "mali_group.h"
+#include "mali_osk.h"
+#include "regs/mali_200_regs.h"
+#include "mali_kernel_common.h"
+#include "mali_kernel_core.h"
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.h"
+#endif
+
+/* See mali_gp.c file for description on how to handle the interrupt mask.
+ * This is how to do it on PP: mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+ */
+
+#define MALI_MAX_NUMBER_OF_PP_CORES 8
+
+/**
+ * Definition of the PP core struct
+ * Used to track a PP core in the system.
+ */
+struct mali_pp_core
+{
+ struct mali_hw_core hw_core; /**< Common for all HW cores */
+ struct mali_group *group; /**< Parent group for this core */
+ _mali_osk_irq_t *irq; /**< IRQ handler */
+ u32 core_id; /**< Unique core ID */
+ struct mali_pp_job *running_job; /**< Current running (super) job */
+ u32 running_sub_job; /**< Current running sub job */
+ _mali_osk_timer_t *timeout_timer; /**< timeout timer for this core */
+ u32 timeout_job_id; /**< job id for the timed out job - relevant only if pp_core_timed_out == MALI_TRUE */
+ mali_bool core_timed_out; /**< if MALI_TRUE, this pp core has timed out; if MALI_FALSE, no timeout on this pp core */
+ u32 counter_src0; /**< Performance counter 0, MALI_HW_CORE_NO_COUNTER for disabled */
+ u32 counter_src1; /**< Performance counter 1, MALI_HW_CORE_NO_COUNTER for disabled */
+ u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */
+ u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */
+};
+
+static struct mali_pp_core* mali_global_pp_cores[MALI_MAX_NUMBER_OF_PP_CORES];
+static u32 mali_global_num_pp_cores = 0;
+
+/* Interrupt handlers */
+static _mali_osk_errcode_t mali_pp_upper_half(void *data);
+static void mali_pp_bottom_half(void *data);
+static void mali_pp_irq_probe_trigger(void *data);
+static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data);
+static void mali_pp_post_process_job(struct mali_pp_core *core);
+static void mali_pp_timeout(void *data);
+
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group)
+{
+ struct mali_pp_core* core = NULL;
+
+ MALI_DEBUG_PRINT(2, ("Mali PP: Creating Mali PP core: %s\n", resource->description));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Base address of PP core: 0x%x\n", resource->base));
+
+ if (mali_global_num_pp_cores >= MALI_MAX_NUMBER_OF_PP_CORES)
+ {
+ MALI_PRINT_ERROR(("Mali PP: Too many PP core objects created\n"));
+ return NULL;
+ }
+
+ core = _mali_osk_malloc(sizeof(struct mali_pp_core));
+ if (NULL != core)
+ {
+ core->group = group;
+ core->core_id = mali_global_num_pp_cores;
+ core->running_job = NULL;
+ core->counter_src0 = MALI_HW_CORE_NO_COUNTER;
+ core->counter_src1 = MALI_HW_CORE_NO_COUNTER;
+ core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
+ core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
+ if (_MALI_OSK_ERR_OK == mali_hw_core_create(&core->hw_core, resource, MALI200_REG_SIZEOF_REGISTER_BANK))
+ {
+ _mali_osk_errcode_t ret;
+
+ mali_group_lock(group);
+ ret = mali_pp_reset(core);
+ mali_group_unlock(group);
+
+ if (_MALI_OSK_ERR_OK == ret)
+ {
+ /* Setup IRQ handlers (which will do IRQ probing if needed) */
+ core->irq = _mali_osk_irq_init(resource->irq,
+ mali_pp_upper_half,
+ mali_pp_bottom_half,
+ mali_pp_irq_probe_trigger,
+ mali_pp_irq_probe_ack,
+ core,
+ "mali_pp_irq_handlers");
+ if (NULL != core->irq)
+ {
+ /* Initialise the timeout timer */
+ core->timeout_timer = _mali_osk_timer_init();
+ if(NULL != core->timeout_timer)
+ {
+ _mali_osk_timer_setcallback(core->timeout_timer, mali_pp_timeout, (void *)core);
+
+ mali_global_pp_cores[mali_global_num_pp_cores] = core;
+ mali_global_num_pp_cores++;
+
+ return core;
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Failed to setup timeout timer for PP core %s\n", core->hw_core.description));
+ /* Release IRQ handlers */
+ _mali_osk_irq_term(core->irq);
+ }
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali PP: Failed to setup interrupt handlers for PP core %s\n", core->hw_core.description));
+ }
+ }
+ mali_hw_core_delete(&core->hw_core);
+ }
+
+ _mali_osk_free(core);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali PP: Failed to allocate memory for PP core\n"));
+ }
+
+ return NULL;
+}
+
+void mali_pp_delete(struct mali_pp_core *core)
+{
+ u32 i;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ _mali_osk_timer_term(core->timeout_timer);
+ _mali_osk_irq_term(core->irq);
+ mali_hw_core_delete(&core->hw_core);
+
+ /* Remove core from global list */
+ for (i = 0; i < mali_global_num_pp_cores; i++)
+ {
+ if (mali_global_pp_cores[i] == core)
+ {
+ mali_global_pp_cores[i] = NULL;
+ mali_global_num_pp_cores--;
+ break;
+ }
+ }
+
+ _mali_osk_free(core);
+}
+
+void mali_pp_stop_bus(struct mali_pp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ /* Will only send the stop bus command, and not wait for it to complete */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
+}
+
+_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core)
+{
+ int i;
+ const int request_loop_count = 20;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ /* Send the stop bus command. */
+ mali_pp_stop_bus(core);
+
+ /* Wait for bus to be stopped */
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED)
+ break;
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Mali PP: Failed to stop bus on %s. Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
+ return _MALI_OSK_ERR_FAULT;
+ }
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core)
+{
+ /* Bus must be stopped before calling this function */
+ const int reset_finished_loop_count = 15;
+ const u32 reset_invalid_value = 0xC0FFE000;
+ const u32 reset_check_value = 0xC01A0000;
+ int i;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description));
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */
+
+ /* Set register to a bogus value. The register will be used to detect when reset is complete */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value);
+
+ /* Force core to reset */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET);
+
+ /* Wait for reset to be complete */
+ for (i = 0; i < reset_finished_loop_count; i++)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_check_value);
+ if (reset_check_value == mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW))
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (i == reset_finished_loop_count)
+ {
+ MALI_PRINT_ERROR(("Mali PP: The hard reset loop didn't work, unable to recover\n"));
+ }
+
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, 0x00000000); /* set it back to the default */
+ /* Re-enable interrupts */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core)
+{
+ int i;
+ const int request_loop_count = 20;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description));
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */
+
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */
+
+#if defined(USING_MALI200)
+
+ /* On Mali-200, stop the bus, then do a hard reset of the core */
+
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_STOP_BUS);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) & MALI200_REG_VAL_STATUS_BUS_STOPPED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count == i)
+ {
+ MALI_PRINT_ERROR(("Mali PP: Failed to stop bus for core %s, unable to recover\n", core->hw_core.description));
+ return _MALI_OSK_ERR_FAULT ;
+ }
+
+ /* the bus was stopped OK, do the hard reset */
+ mali_pp_hard_reset(core);
+
+#elif defined(USING_MALI400)
+
+ /* Mali-300 and Mali-400 have a safe reset command which we use */
+
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI400PP_REG_VAL_IRQ_RESET_COMPLETED);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET);
+
+ for (i = 0; i < request_loop_count; i++)
+ {
+ if (mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)
+ {
+ break;
+ }
+ _mali_osk_time_ubusydelay(10);
+ }
+
+ if (request_loop_count == i)
+ {
+ MALI_DEBUG_PRINT(2, ("Mali PP: Failed to reset core %s, Status: 0x%08x\n", core->hw_core.description, mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
+ return _MALI_OSK_ERR_FAULT;
+ }
+#else
+#error "no supported mali core defined"
+#endif
+
+ /* Re-enable interrupts */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_MASK_ALL);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job)
+{
+ u32 *frame_registers = mali_pp_job_get_frame_registers(job);
+ u32 *wb0_registers = mali_pp_job_get_wb0_registers(job);
+ u32 *wb1_registers = mali_pp_job_get_wb1_registers(job);
+ u32 *wb2_registers = mali_pp_job_get_wb2_registers(job);
+ core->counter_src0_used = core->counter_src0;
+ core->counter_src1_used = core->counter_src1;
+
+ MALI_DEBUG_ASSERT_POINTER(core);
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME);
+ if (0 != sub_job)
+ {
+ /*
+ * There are two frame registers which are different for each sub job.
+ * For the first sub job, these are correctly represented in the frame register array,
+ * but we need to patch these for all other sub jobs
+ */
+ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job));
+ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job));
+ }
+
+ if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */
+ {
+ mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx);
+ }
+
+ if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */
+ {
+ mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx);
+ }
+
+ if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */
+ {
+ mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx);
+ }
+
+ /* This selects which performance counters we are reading */
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+ {
+ /* global_config has enabled HW counters, this will override anything specified by user space */
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE);
+ }
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE);
+ }
+ }
+ else
+ {
+ /* Use HW counters from job object, if any */
+ u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);
+ if (0 != perf_counter_flag)
+ {
+ if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE)
+ {
+ core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE);
+ }
+
+ if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE)
+ {
+ core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used);
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE);
+ }
+ }
+ }
+
+ MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description));
+
+ /* Adding barrier to make sure all rester writes are finished */
+ _mali_osk_write_mem_barrier();
+
+ /* This is the command that starts the core. */
+ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING);
+
+ /* Adding barrier to make sure previous rester writes is finished */
+ _mali_osk_write_mem_barrier();
+
+ /* Setup the timeout timer value and save the job id for the job running on the pp core */
+ _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
+ core->timeout_job_id = mali_pp_job_get_id(job);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), job->pid, job->tid, 0, 0, 0);
+#endif
+
+ core->running_job = job;
+ core->running_sub_job = sub_job;
+}
+
+u32 mali_pp_core_get_version(struct mali_pp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION);
+}
+
+u32 mali_pp_core_get_id(struct mali_pp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return core->core_id;
+}
+
+mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ core->counter_src0 = counter;
+ return MALI_TRUE;
+}
+
+mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+
+ core->counter_src1 = counter;
+ return MALI_TRUE;
+}
+
+u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return core->counter_src0;
+}
+
+u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return core->counter_src1;
+}
+
+struct mali_pp_core* mali_pp_get_global_pp_core(u32 index)
+{
+ if (MALI_MAX_NUMBER_OF_PP_CORES > index)
+ {
+ return mali_global_pp_cores[index];
+ }
+
+ return NULL;
+}
+
+u32 mali_pp_get_glob_num_pp_cores(void)
+{
+ return mali_global_num_pp_cores;
+}
+
+u32 mali_pp_get_max_num_pp_cores(void)
+{
+ return MALI_MAX_NUMBER_OF_PP_CORES;
+}
+
+/* ------------- interrupt handling below ------------------ */
+static _mali_osk_errcode_t mali_pp_upper_half(void *data)
+{
+ struct mali_pp_core *core = (struct mali_pp_core *)data;
+ u32 irq_readout;
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+ if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout)
+ {
+ /* Mask out all IRQs from this core until IRQ is handled */
+ mali_hw_core_register_write(&core->hw_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_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
+#endif
+
+ /* We do need to handle this in a bottom half */
+ _mali_osk_irq_schedulework(core->irq);
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+static void mali_pp_bottom_half(void *data)
+{
+ struct mali_pp_core *core = (struct mali_pp_core *)data;
+ u32 irq_readout;
+ u32 irq_errors;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+#if 0 /* Bottom half TLP logging is currently not supported */
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
+#endif
+#endif
+
+ mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */
+
+ if ( MALI_FALSE == mali_group_power_is_on(core->group) )
+ {
+ MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description));
+ mali_group_unlock(core->group);
+ return;
+ }
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
+
+ MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, core->hw_core.description));
+
+ if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
+ {
+ mali_pp_post_process_job(core);
+ MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n"));
+ mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */
+ return;
+ }
+
+ /*
+ * Now lets look at the possible error cases (IRQ indicating error or timeout)
+ * END_OF_FRAME and HANG interrupts are not considered error.
+ */
+ irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG);
+ if (0 != irq_errors)
+ {
+ mali_pp_post_process_job(core);
+ MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n",
+ irq_readout, core->hw_core.description));
+ mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */
+ return;
+ }
+ else if (MALI_TRUE == core->core_timed_out) /* SW timeout */
+ {
+ if (core->timeout_job_id == mali_pp_job_get_id(core->running_job))
+ {
+ mali_pp_post_process_job(core);
+ MALI_DEBUG_PRINT(2, ("Mali PP: Job %d timed out on core %s\n",
+ mali_pp_job_get_id(core->running_job), core->hw_core.description));
+ mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_TIMED_OUT); /* Will release group lock */
+ }
+ else
+ {
+ mali_group_unlock(core->group);
+ }
+ core->core_timed_out = MALI_FALSE;
+ return;
+ }
+ else if (irq_readout & MALI200_REG_VAL_IRQ_HANG)
+ {
+ /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_HANG);
+ }
+
+ /*
+ * The only way to get here is if we got a HANG interrupt, which we ignore.
+ * Re-enable interrupts and let core continue to run
+ */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED);
+ mali_group_unlock(core->group);
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+#if 0 /* Bottom half TLP logging is currently not supported */
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0);
+#endif
+#endif
+}
+
+static void mali_pp_irq_probe_trigger(void *data)
+{
+ struct mali_pp_core *core = (struct mali_pp_core *)data;
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_USED); /* @@@@ This should not be needed */
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT, MALI200_REG_VAL_IRQ_FORCE_HANG);
+ _mali_osk_mem_barrier();
+}
+
+static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data)
+{
+ struct mali_pp_core *core = (struct mali_pp_core *)data;
+ u32 irq_readout;
+
+ irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS);
+ if (MALI200_REG_VAL_IRQ_FORCE_HANG & irq_readout)
+ {
+ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_CLEAR, MALI200_REG_VAL_IRQ_FORCE_HANG);
+ _mali_osk_mem_barrier();
+ return _MALI_OSK_ERR_OK;
+ }
+
+ return _MALI_OSK_ERR_FAULT;
+}
+
+
+/* ------ local helper functions below --------- */
+static void mali_pp_post_process_job(struct mali_pp_core *core)
+{
+ MALI_ASSERT_GROUP_LOCKED(core->group);
+
+ if (NULL != core->running_job)
+ {
+ u32 val0 = 0;
+ u32 val1 = 0;
+#if MALI_TIMELINE_PROFILING_ENABLED
+ int counter_index = COUNTER_FP0_C0 + (2 * core->core_id);
+#endif
+
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+ {
+ val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
+ if (mali_pp_job_get_perf_counter_flag(core->running_job) &&
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used)
+ {
+ /* We retrieved the counter that user space asked for, so return the value through the job object */
+ mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0);
+ }
+ else
+ {
+ /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */
+ mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE);
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_report_hw_counter(counter_index, val0);
+#endif
+ }
+
+ if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+ {
+ val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+ if (mali_pp_job_get_perf_counter_flag(core->running_job) &&
+ _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used)
+ {
+ /* We retrieved the counter that user space asked for, so return the value through the job object */
+ mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1);
+ }
+ else
+ {
+ /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */
+ mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE);
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_report_hw_counter(counter_index + 1, val1);
+#endif
+ }
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id),
+ val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0);
+#endif
+
+ /* We are no longer running a job... */
+ core->running_job = NULL;
+ _mali_osk_timer_del(core->timeout_timer);
+ }
+}
+
+/* callback function for pp core timeout */
+static void mali_pp_timeout(void *data)
+{
+ struct mali_pp_core * core = ((struct mali_pp_core *)data);
+
+ MALI_DEBUG_PRINT(3, ("Mali PP: TIMEOUT callback \n"));
+ core->core_timed_out = MALI_TRUE;
+ _mali_osk_irq_schedulework(core->irq);
+}
+
+#if 0
+static void mali_pp_print_registers(struct mali_pp_core *core)
+{
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_VERSION = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_VERSION)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_RAWSTAT = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_MASK = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_INT_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC)));
+ MALI_DEBUG_PRINT(2, ("Mali PP: Register MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE = 0x%08X\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE)));
+}
+#endif
+
+#if 0
+void mali_pp_print_state(struct mali_pp_core *core)
+{
+ MALI_DEBUG_PRINT(2, ("Mali PP: State: 0x%08x\n", mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS) ));
+}
+#endif
+
+#if MALI_STATE_TRACKING
+u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size)
+{
+ int n = 0;
+
+ n += _mali_osk_snprintf(buf + n, size - n, "\tPP #%d: %s\n", core->core_id, core->hw_core.description);
+
+ return n;
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_pp.h b/drivers/media/video/samsung/mali/common/mali_pp.h
new file mode 100644
index 0000000..9b425a0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp.h
@@ -0,0 +1,47 @@
+/*
+ * 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_PP_H__
+#define __MALI_PP_H__
+
+#include "mali_osk.h"
+#include "mali_pp_job.h"
+
+struct mali_pp_core;
+struct mali_group;
+
+_mali_osk_errcode_t mali_pp_initialize(void);
+void mali_pp_terminate(void);
+
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group);
+void mali_pp_delete(struct mali_pp_core *core);
+
+void mali_pp_stop_bus(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core);
+_mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core);
+
+void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job);
+
+u32 mali_pp_core_get_version(struct mali_pp_core *core);
+
+u32 mali_pp_core_get_id(struct mali_pp_core *core);
+
+mali_bool mali_pp_core_set_counter_src0(struct mali_pp_core *core, u32 counter);
+mali_bool mali_pp_core_set_counter_src1(struct mali_pp_core *core, u32 counter);
+u32 mali_pp_core_get_counter_src0(struct mali_pp_core *core);
+u32 mali_pp_core_get_counter_src1(struct mali_pp_core *core);
+struct mali_pp_core* mali_pp_get_global_pp_core(u32 index);
+u32 mali_pp_get_glob_num_pp_cores(void);
+u32 mali_pp_get_max_num_pp_cores(void);
+/* Debug */
+u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size);
+
+#endif /* __MALI_PP_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.c b/drivers/media/video/samsung/mali/common/mali_pp_job.c
new file mode 100644
index 0000000..1efcfda
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_job.c
@@ -0,0 +1,92 @@
+/*
+ * 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_pp_job.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_kernel_common.h"
+#include "mali_uk_types.h"
+
+struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id)
+{
+ struct mali_pp_job *job;
+
+ if (args->num_cores > _MALI_PP_MAX_SUB_JOBS)
+ {
+ MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
+ return NULL;
+ }
+
+ job = _mali_osk_malloc(sizeof(struct mali_pp_job));
+ if (NULL != job)
+ {
+ u32 i;
+ _mali_osk_list_init(&job->list);
+ job->session = session;
+ job->id = id;
+ job->user_id = args->user_job_ptr;
+ _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers));
+ _mali_osk_memcpy(job->frame_registers_addr_frame, args->frame_registers_addr_frame, sizeof(job->frame_registers_addr_frame));
+ _mali_osk_memcpy(job->frame_registers_addr_stack, args->frame_registers_addr_stack, sizeof(job->frame_registers_addr_stack));
+
+ /* Only copy write back registers for the units that are enabled */
+ job->wb0_registers[0] = 0;
+ job->wb1_registers[0] = 0;
+ job->wb2_registers[0] = 0;
+ if (args->wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */
+ {
+ _mali_osk_memcpy(job->wb0_registers, args->wb0_registers, sizeof(job->wb0_registers));
+ }
+ if (args->wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */
+ {
+ _mali_osk_memcpy(job->wb1_registers, args->wb1_registers, sizeof(job->wb1_registers));
+ }
+ if (args->wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */
+ {
+ _mali_osk_memcpy(job->wb2_registers, args->wb2_registers, sizeof(job->wb2_registers));
+ }
+
+ job->perf_counter_flag = args->perf_counter_flag;
+ job->perf_counter_src0 = args->perf_counter_src0;
+ job->perf_counter_src1 = args->perf_counter_src1;
+ for (i = 0; i < args->num_cores; i++)
+ {
+ job->perf_counter_value0[i] = 0;
+ job->perf_counter_value1[i] = 0;
+ }
+ job->sub_job_count = args->num_cores;
+ job->sub_jobs_started = 0;
+ job->sub_jobs_completed = 0;
+ job->sub_job_errors = 0;
+
+ job->pid = _mali_osk_get_pid();
+ job->tid = _mali_osk_get_tid();
+ job->frame_builder_id = args->frame_builder_id;
+ job->flush_id = args->flush_id;
+
+ return job;
+ }
+
+ return NULL;
+}
+
+void mali_pp_job_delete(struct mali_pp_job *job)
+{
+ _mali_osk_free(job);
+}
+
+_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job)
+{
+ if ((0 == job->frame_registers[0]) || (0 == job->frame_registers[1]))
+ {
+ return _MALI_OSK_ERR_FAULT;
+ }
+ return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.h b/drivers/media/video/samsung/mali/common/mali_pp_job.h
new file mode 100644
index 0000000..7fe87f8
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_job.h
@@ -0,0 +1,255 @@
+/*
+ * 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_PP_JOB_H__
+#define __MALI_PP_JOB_H__
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_uk_types.h"
+#include "mali_session.h"
+#include "mali_kernel_common.h"
+#include "regs/mali_200_regs.h"
+
+/**
+ * The structure represends a PP job, including all sub-jobs
+ * (This struct unfortunatly needs to be public because of how the _mali_osk_list_*
+ * mechanism works)
+ */
+struct mali_pp_job
+{
+ _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */
+ struct mali_session_data *session; /**< Session which submitted this job */
+ u32 id; /**< identifier for this job in kernel space (sequencial numbering) */
+ u32 user_id; /**< identifier for the job in user space */
+ u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< core specific registers associated with this job, see ARM DDI0415A */
+ u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_FRAME registers for sub job 1-7 */
+ u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_STACK registers for sub job 1-7 */
+ u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 0 registers */
+ u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 1 registers */
+ u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 2 registers */
+ u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */
+ u32 perf_counter_src0; /**< Source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter_src1; /**< Source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
+ u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 0 (to be returned to user space), one for each sub job */
+ u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */
+ u32 sub_job_count; /**< Total number of sub-jobs in this superjob */
+ u32 sub_jobs_started; /**< Total number of sub-jobs started (always started in ascending order) */
+ u32 sub_jobs_completed; /**< Number of completed sub-jobs in this superjob */
+ u32 sub_job_errors; /**< Bitfield with errors (errors for each single sub-job is or'ed together) */
+ u32 pid; /**< Process ID of submitting process */
+ u32 tid; /**< Thread ID of submitting thread */
+ u32 frame_builder_id; /**< id of the originating frame builder */
+ u32 flush_id; /**< flush id within the originating frame builder */
+};
+
+struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id);
+void mali_pp_job_delete(struct mali_pp_job *job);
+
+_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job);
+
+/******************************************************
+ * simple utility functions for dealing with pp jobs:
+ *****************************************************/
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job)
+{
+ return (NULL == job) ? 0 : job->id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job)
+{
+ return job->user_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job)
+{
+ return job->frame_builder_id;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job)
+{
+ return job->flush_id;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job)
+{
+ return job->frame_registers;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job)
+{
+ if (sub_job == 0)
+ {
+ return job->frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)];
+ }
+ else if (sub_job < _MALI_PP_MAX_SUB_JOBS)
+ {
+ return job->frame_registers_addr_frame[sub_job - 1];
+ }
+
+ return 0;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job)
+{
+ if (sub_job == 0)
+ {
+ return job->frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)];
+ }
+ else if (sub_job < _MALI_PP_MAX_SUB_JOBS)
+ {
+ return job->frame_registers_addr_stack[sub_job - 1];
+ }
+
+ return 0;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job)
+{
+ return job->wb0_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job)
+{
+ return job->wb1_registers;
+}
+
+MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job)
+{
+ return job->wb2_registers;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job)
+{
+ job->wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job)
+{
+ job->wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job)
+{
+ job->wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
+}
+
+MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job)
+{
+ return job->session;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job)
+{
+ return (job->sub_jobs_started < job->sub_job_count) ? MALI_TRUE : MALI_FALSE;
+}
+
+/* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job.
+ Makes sure that no new subjobs is started. */
+MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(struct mali_pp_job *job)
+{
+ /* All can not be started, since then it would not be in the job queue */
+ MALI_DEBUG_ASSERT( job->sub_jobs_started != job->sub_job_count );
+
+ /* If at least one job is started */
+ if ( (job->sub_jobs_started > 0) )
+ {
+ /* If at least one job is currently being rendered, and thus assigned to a group and core */
+ if (job->sub_jobs_started > job->sub_jobs_completed )
+ {
+ u32 jobs_remaining = job->sub_job_count - job->sub_jobs_started;
+ job->sub_jobs_started += jobs_remaining;
+ job->sub_jobs_completed += jobs_remaining;
+ job->sub_job_errors += jobs_remaining;
+ /* Returning TRUE indicating that we can not delete this job which is being redered */
+ return MALI_TRUE;
+ }
+ }
+ /* The job is not being rendered to at the moment and can then safely be deleted */
+ return MALI_FALSE;
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job)
+{
+ return (job->sub_job_count == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job)
+{
+ return job->sub_jobs_started;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job)
+{
+ return job->sub_job_count;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job)
+{
+ /* Assert that we are marking the "first unstarted sub job" as started */
+ MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job);
+ job->sub_jobs_started++;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success)
+{
+ job->sub_jobs_completed++;
+ if ( MALI_FALSE == success )
+ {
+ job->sub_job_errors++;
+ }
+}
+
+MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job)
+{
+ if ( 0 == job->sub_job_errors )
+ {
+ return MALI_TRUE;
+ }
+ return MALI_FALSE;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job)
+{
+ return job->perf_counter_flag;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job)
+{
+ return job->perf_counter_src0;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job)
+{
+ return job->perf_counter_src1;
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job)
+{
+ return job->perf_counter_value0[sub_job];
+}
+
+MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job)
+{
+ return job->perf_counter_value1[sub_job];
+}
+
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value)
+{
+ job->perf_counter_value0[sub_job] = value;
+}
+
+MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value)
+{
+ job->perf_counter_value1[sub_job] = value;
+}
+
+#endif /* __MALI_PP_JOB_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c
new file mode 100644
index 0000000..ce07a76
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c
@@ -0,0 +1,542 @@
+/*
+ * 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.
+ */
+
+#include "mali_pp_scheduler.h"
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_scheduler.h"
+#include "mali_pp.h"
+#include "mali_pp_job.h"
+#include "mali_group.h"
+#include "mali_cluster.h"
+
+/* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */
+#define MALI_MAX_NUMBER_OF_PP_GROUPS 8
+
+static mali_bool mali_pp_scheduler_is_suspended(void);
+
+enum mali_pp_slot_state
+{
+ MALI_PP_SLOT_STATE_IDLE,
+ MALI_PP_SLOT_STATE_WORKING,
+};
+
+/* A render slot is an entity which jobs can be scheduled onto */
+struct mali_pp_slot
+{
+ struct mali_group *group;
+ /*
+ * We keep track of the state here as well as in the group object
+ * so we don't need to take the group lock so often (and also avoid clutter with the working lock)
+ */
+ enum mali_pp_slot_state state;
+};
+
+static u32 pp_version = 0;
+static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */
+static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS];
+static u32 num_slots = 0;
+static u32 num_slots_idle = 0;
+
+/* Variables to allow safe pausing of the scheduler */
+static _mali_osk_wait_queue_t *pp_scheduler_working_wait_queue = NULL;
+static u32 pause_count = 0;
+
+static _mali_osk_lock_t *pp_scheduler_lock = NULL;
+/* Contains tid of thread that locked the scheduler or 0, if not locked */
+MALI_DEBUG_CODE(static u32 pp_scheduler_lock_owner = 0);
+
+_mali_osk_errcode_t mali_pp_scheduler_initialize(void)
+{
+ u32 i;
+
+ _MALI_OSK_INIT_LIST_HEAD(&job_queue);
+
+ pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER);
+ if (NULL == pp_scheduler_lock)
+ {
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ pp_scheduler_working_wait_queue = _mali_osk_wait_queue_init();
+ if (NULL == pp_scheduler_working_wait_queue)
+ {
+ _mali_osk_lock_term(pp_scheduler_lock);
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ /* Find all the available PP cores */
+ for (i = 0; i < mali_cluster_get_glob_num_clusters(); i++)
+ {
+ u32 group_id = 0;
+ struct mali_cluster *curr_cluster = mali_cluster_get_global_cluster(i);
+ struct mali_group *group = mali_cluster_get_group(curr_cluster, group_id);
+ while (NULL != group)
+ {
+ struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+ if (NULL != pp_core)
+ {
+ if (0 == pp_version)
+ {
+ /* Retrieve PP version from first avaiable PP core */
+ pp_version = mali_pp_core_get_version(pp_core);
+ }
+ slots[num_slots].group = group;
+ slots[num_slots].state = MALI_PP_SLOT_STATE_IDLE;
+ num_slots++;
+ num_slots_idle++;
+ }
+ group_id++;
+ group = mali_cluster_get_group(curr_cluster, group_id);
+ }
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_pp_scheduler_terminate(void)
+{
+ _mali_osk_wait_queue_term(pp_scheduler_working_wait_queue);
+ _mali_osk_lock_term(pp_scheduler_lock);
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_lock(void)
+{
+ if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW))
+ {
+ /* Non-interruptable lock failed: this should never happen. */
+ MALI_DEBUG_ASSERT(0);
+ }
+ MALI_DEBUG_PRINT(5, ("Mali PP scheduler: PP scheduler lock taken\n"));
+ MALI_DEBUG_ASSERT(0 == pp_scheduler_lock_owner);
+ MALI_DEBUG_CODE(pp_scheduler_lock_owner = _mali_osk_get_tid());
+}
+
+MALI_STATIC_INLINE void mali_pp_scheduler_unlock(void)
+{
+ MALI_DEBUG_PRINT(5, ("Mali PP scheduler: Releasing PP scheduler lock\n"));
+ MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner);
+ MALI_DEBUG_CODE(pp_scheduler_lock_owner = 0);
+ _mali_osk_lock_signal(pp_scheduler_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+#ifdef DEBUG
+MALI_STATIC_INLINE void mali_pp_scheduler_assert_locked(void)
+{
+ MALI_DEBUG_ASSERT(_mali_osk_get_tid() == pp_scheduler_lock_owner);
+}
+#define MALI_ASSERT_PP_SCHEDULER_LOCKED() mali_pp_scheduler_assert_locked()
+#else
+#define MALI_ASSERT_PP_SCHEDULER_LOCKED()
+#endif
+
+static void mali_pp_scheduler_schedule(void)
+{
+ u32 i;
+ struct mali_pp_job *job;
+#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS
+ struct mali_session_data * session;
+#endif
+
+ MALI_ASSERT_PP_SCHEDULER_LOCKED();
+
+ if (0 < pause_count || 0 == num_slots_idle || _mali_osk_list_empty(&job_queue))
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
+ pause_count, num_slots_idle));
+ return; /* Nothing to do, so early out */
+ }
+
+
+#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP
+ if ( num_slots_idle < num_slots )
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started, since only %d/%d cores are available\n", num_slots_idle,num_slots));
+ return;
+ }
+#endif
+
+#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS
+ /* Finding initial session for the PP cores */
+ job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list);
+ session = job->session;
+ if ( num_slots != num_slots_idle )
+ {
+ for (i = 0; (i < num_slots) ; i++)
+ {
+ if ( slots[i].state == MALI_PP_SLOT_STATE_IDLE )
+ {
+ continue;
+ }
+ session = mali_group_get_session(slots[i].group);
+ break;
+ }
+ }
+#endif
+
+ for (i = 0; (i < num_slots) && (0 < num_slots_idle); i++)
+ {
+ u32 sub_job;
+
+ if (_mali_osk_list_empty(&job_queue)) /* move this check down to where we know we have started all sub jobs for this job??? */
+ {
+ break; /* No more jobs to schedule, so early out */
+ }
+
+ if (MALI_PP_SLOT_STATE_IDLE != slots[i].state)
+ {
+ continue;
+ }
+
+ job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list);
+ MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); /* All jobs on the job_queue should have unstarted sub jobs */
+
+ #if MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED
+ if ( (0==job->sub_jobs_started) && (num_slots_idle < num_slots) && (job->sub_job_count > num_slots_idle))
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job with %d subjobs not started, since only %d/%d cores are available\n", job->sub_job_count, num_slots_idle,num_slots));
+ return;
+ }
+ #endif
+
+ #if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS
+ if ( job->session != session )
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started since existing job is from another application\n"));
+ return;
+ }
+ #endif
+
+ sub_job = mali_pp_job_get_first_unstarted_sub_job(job);
+
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Starting job %u (0x%08X) part %u/%u\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job)));
+ if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slots[i].group, job, sub_job))
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job)));
+
+ /* Mark this sub job as started */
+ mali_pp_job_mark_sub_job_started(job, sub_job);
+
+ /* Mark slot as busy */
+ slots[i].state = MALI_PP_SLOT_STATE_WORKING;
+ num_slots_idle--;
+
+ if (!mali_pp_job_has_unstarted_sub_jobs(job))
+ {
+ /*
+ * All sub jobs have now started for this job, remove this job from the job queue.
+ * The job will now only be referred to by the slots which are running it.
+ * The last slot to complete will make sure it is returned to user space.
+ */
+ _mali_osk_list_del(&job->list);
+#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP
+ MALI_DEBUG_PRINT(6, ("Mali PP scheduler: Skip scheduling more jobs when MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP is set.\n"));
+ return;
+#endif
+ }
+ }
+ else
+ {
+ MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n"));
+ return;
+ }
+ }
+}
+
+static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job)
+{
+ _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
+ if (NULL != notobj)
+ {
+ u32 i;
+ u32 sub_jobs = mali_pp_job_get_sub_job_count(job);
+ mali_bool success = mali_pp_job_was_success(job);
+
+ _mali_uk_pp_job_finished_s *jobres = notobj->result_buffer;
+ _mali_osk_memset(jobres, 0, sizeof(_mali_uk_pp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */
+ jobres->user_job_ptr = mali_pp_job_get_user_id(job);
+ if (MALI_TRUE == success)
+ {
+ jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS;
+ }
+ else
+ {
+ jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR;
+ }
+
+ for (i = 0; i < sub_jobs; i++)
+ {
+ jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i);
+ jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i);
+ }
+
+ mali_session_send_notification(mali_pp_job_get_session(job), notobj);
+ }
+ else
+ {
+ MALI_PRINT_ERROR(("Mali PP scheduler: Unable to allocate notification object\n"));
+ }
+
+ mali_pp_job_delete(job);
+}
+
+void mali_pp_scheduler_do_schedule(void)
+{
+ mali_pp_scheduler_lock();
+
+ mali_pp_scheduler_schedule();
+
+ mali_pp_scheduler_unlock();
+}
+
+void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success)
+{
+ u32 i;
+ mali_bool job_is_done;
+
+ MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job), success ? "success" : "failure"));
+
+ mali_pp_scheduler_lock();
+
+ /* Find slot which was running this job */
+ for (i = 0; i < num_slots; i++)
+ {
+ if (slots[i].group == group)
+ {
+ MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slots[i].state);
+ slots[i].state = MALI_PP_SLOT_STATE_IDLE;
+ num_slots_idle++;
+ mali_pp_job_mark_sub_job_completed(job, success);
+ }
+ }
+
+ /* If paused, then this was the last job, so wake up sleeping workers */
+ if (pause_count > 0)
+ {
+ /* Wake up sleeping workers. Their wake-up condition is that
+ * num_slots == num_slots_idle, so unless we are done working, no
+ * threads will actually be woken up.
+ */
+ _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue);
+ }
+ else
+ {
+ mali_pp_scheduler_schedule();
+ }
+
+ job_is_done = mali_pp_job_is_complete(job);
+
+ mali_pp_scheduler_unlock();
+
+ if (job_is_done)
+ {
+ /* Send notification back to user space */
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for job %u (0x%08X)\n", mali_pp_job_get_id(job), job));
+ mali_pp_scheduler_return_job_to_user(job);
+ }
+}
+
+void mali_pp_scheduler_suspend(void)
+{
+ mali_pp_scheduler_lock();
+ pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */
+ mali_pp_scheduler_unlock();
+
+ /*mali_pp_scheduler_working_lock();*/
+ /* We have now aquired the working lock, which means that we have successfully paused the scheduler */
+ /*mali_pp_scheduler_working_unlock();*/
+
+ /* go to sleep. When woken up again (in mali_pp_scheduler_job_done), the
+ * mali_pp_scheduler_suspended() function will be called. This will return true
+ * iff state is idle and pause_count > 0, so if the core is active this
+ * will not do anything.
+ */
+ _mali_osk_wait_queue_wait_event(pp_scheduler_working_wait_queue, mali_pp_scheduler_is_suspended);
+}
+
+void mali_pp_scheduler_resume(void)
+{
+ mali_pp_scheduler_lock();
+ pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
+ if (0 == pause_count)
+ {
+ mali_pp_scheduler_schedule();
+ }
+ mali_pp_scheduler_unlock();
+}
+
+_mali_osk_errcode_t _mali_ukk_pp_start_job(_mali_uk_pp_start_job_s *args)
+{
+ struct mali_session_data *session;
+ struct mali_pp_job *job;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_DEBUG_ASSERT_POINTER(args->ctx);
+
+ session = (struct mali_session_data*)args->ctx;
+
+ job = mali_pp_job_create(session, args, mali_scheduler_get_new_id());
+ if (NULL == job)
+ {
+ return _MALI_OSK_ERR_NOMEM;
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_pp_job_check(job))
+ {
+ /* Not a valid job, return to user immediately */
+ mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+ mali_pp_scheduler_return_job_to_user(job); /* This will also delete the job object */
+ return _MALI_OSK_ERR_OK; /* User is notified via a notification, so this call is ok */
+ }
+
+ mali_pp_scheduler_lock();
+
+ _mali_osk_list_addtail(&job->list, &job_queue);
+
+ MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job)));
+
+ mali_pp_scheduler_schedule();
+
+ mali_pp_scheduler_unlock();
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores(_mali_uk_get_pp_number_of_cores_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_DEBUG_ASSERT_POINTER(args->ctx);
+ args->number_of_cores = num_slots;
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_get_pp_core_version(_mali_uk_get_pp_core_version_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_DEBUG_ASSERT_POINTER(args->ctx);
+ args->version = pp_version;
+ return _MALI_OSK_ERR_OK;
+}
+
+void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args)
+{
+ struct mali_session_data *session;
+ struct mali_pp_job *job;
+ struct mali_pp_job *tmp;
+
+ MALI_DEBUG_ASSERT_POINTER(args);
+ MALI_DEBUG_ASSERT_POINTER(args->ctx);
+
+ session = (struct mali_session_data*)args->ctx;
+
+ mali_pp_scheduler_lock();
+
+ /* Check queue for jobs that match */
+ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list)
+ {
+ if (mali_pp_job_get_session(job) == session &&
+ mali_pp_job_get_frame_builder_id(job) == (u32)args->fb_id &&
+ mali_pp_job_get_flush_id(job) == (u32)args->flush_id)
+ {
+ if (args->wbx & _MALI_UK_PP_JOB_WB0)
+ {
+ mali_pp_job_disable_wb0(job);
+ }
+ if (args->wbx & _MALI_UK_PP_JOB_WB1)
+ {
+ mali_pp_job_disable_wb1(job);
+ }
+ if (args->wbx & _MALI_UK_PP_JOB_WB2)
+ {
+ mali_pp_job_disable_wb2(job);
+ }
+ break;
+ }
+ }
+
+ mali_pp_scheduler_unlock();
+}
+
+void mali_pp_scheduler_abort_session(struct mali_session_data *session)
+{
+ struct mali_pp_job *job, *tmp;
+ int i;
+
+ mali_pp_scheduler_lock();
+ MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Aborting all jobs from session 0x%08x\n", session));
+
+ /* Check queue for jobs and remove */
+ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list)
+ {
+ if (mali_pp_job_get_session(job) == session)
+ {
+ _mali_osk_list_del(&(job->list));
+
+ if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) )
+ {
+ /* The job is in the render pipeline, we can not delete it yet. */
+ /* It will be deleted in the mali_group_abort_session() call below */
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Keeping partially started PP job 0x%08x in queue\n", job));
+ continue;
+ }
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Removing PP job 0x%08x from queue\n", job));
+ mali_pp_job_delete(job);
+ }
+ }
+
+ mali_pp_scheduler_unlock();
+
+ /* Abort running jobs from this session */
+ for (i = 0; i < num_slots; i++)
+ {
+ struct mali_group *group = slots[i].group;
+
+ MALI_DEBUG_PRINT(5, ("PP sched abort: Looking at group 0x%08x\n", group));
+
+ if (MALI_PP_SLOT_STATE_WORKING == slots[i].state)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborting session 0x%08x from group 0x%08x\n", session, group));
+
+ mali_group_abort_session(group, session);
+ }
+ }
+}
+
+static mali_bool mali_pp_scheduler_is_suspended(void)
+{
+ mali_bool ret;
+
+ mali_pp_scheduler_lock();
+ ret = pause_count > 0 && num_slots == num_slots_idle;
+ mali_pp_scheduler_unlock();
+
+ return ret;
+}
+
+#if MALI_STATE_TRACKING
+u32 mali_pp_scheduler_dump_state(char *buf, u32 size)
+{
+ int n = 0;
+ int i;
+
+ n += _mali_osk_snprintf(buf + n, size - n, "PP:\n");
+ n += _mali_osk_snprintf(buf + n, size - n, "\tQueue is %s\n", _mali_osk_list_empty(&job_queue) ? "empty" : "not empty");
+ n += _mali_osk_snprintf(buf + n, size - n, "\n");
+
+ for (i = 0; i < num_slots; i++)
+ {
+ n += mali_group_dump_state(slots[i].group, buf + n, size - n);
+ n += _mali_osk_snprintf(buf + n, size - n, "\t\tState: %d\n", slots[i].state);
+ }
+
+ return n;
+}
+#endif
diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h
new file mode 100644
index 0000000..48eb3bd
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef __MALI_PP_SCHEDULER_H__
+#define __MALI_PP_SCHEDULER_H__
+
+#include "mali_osk.h"
+#include "mali_cluster.h"
+#include "mali_pp_job.h"
+
+_mali_osk_errcode_t mali_pp_scheduler_initialize(void);
+void mali_pp_scheduler_terminate(void);
+
+void mali_pp_scheduler_do_schedule(void);
+void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success);
+
+void mali_pp_scheduler_suspend(void);
+void mali_pp_scheduler_resume(void);
+
+/** @brief Abort all PP jobs from session running or queued
+ *
+ * This functions aborts all PP jobs from the specified session. Queued jobs are removed from the queue and jobs
+ * currently running on a core will be aborted.
+ *
+ * @param session Pointer to session whose jobs should be aborted
+ */
+void mali_pp_scheduler_abort_session(struct mali_session_data *session);
+
+u32 mali_pp_scheduler_dump_state(char *buf, u32 size);
+
+#endif /* __MALI_PP_SCHEDULER_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_scheduler.c b/drivers/media/video/samsung/mali/common/mali_scheduler.c
new file mode 100644
index 0000000..52159a0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_scheduler.c
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+
+static _mali_osk_atomic_t mali_job_autonumber;
+
+_mali_osk_errcode_t mali_scheduler_initialize(void)
+{
+ if ( _MALI_OSK_ERR_OK != _mali_osk_atomic_init(&mali_job_autonumber, 0))
+ {
+ MALI_DEBUG_PRINT(1, ("Initialization of atomic job id counter failed.\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_scheduler_terminate(void)
+{
+ _mali_osk_atomic_term(&mali_job_autonumber);
+}
+
+u32 mali_scheduler_get_new_id(void)
+{
+ u32 job_id = _mali_osk_atomic_inc_return(&mali_job_autonumber);
+ return job_id;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem.h b/drivers/media/video/samsung/mali/common/mali_scheduler.h
index 8caafe3..74f0947 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_mem.h
+++ b/drivers/media/video/samsung/mali/common/mali_scheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,10 +8,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_MEM_H__
-#define __MALI_KERNEL_MEM_H__
+#ifndef __MALI_SCHEDULER_H__
+#define __MALI_SCHEDULER_H__
-#include "mali_kernel_subsystem.h"
-extern struct mali_kernel_subsystem mali_subsystem_memory;
+#include "mali_osk.h"
-#endif /* __MALI_KERNEL_MEM_H__ */
+_mali_osk_errcode_t mali_scheduler_initialize(void);
+void mali_scheduler_terminate(void);
+
+u32 mali_scheduler_get_new_id(void);
+
+#endif /* __MALI_SCHEDULER_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_session.c b/drivers/media/video/samsung/mali/common/mali_session.c
new file mode 100644
index 0000000..2394bb9
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_session.c
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+#include "mali_session.h"
+
+_MALI_OSK_LIST_HEAD(mali_sessions);
+
+_mali_osk_lock_t *mali_sessions_lock;
+
+_mali_osk_errcode_t mali_session_initialize(void)
+{
+ _MALI_OSK_INIT_LIST_HEAD(&mali_sessions);
+
+ mali_sessions_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED, 0, _MALI_OSK_LOCK_ORDER_SESSIONS);
+
+ if (NULL == mali_sessions_lock) return _MALI_OSK_ERR_NOMEM;
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void mali_session_terminate(void)
+{
+ _mali_osk_lock_term(mali_sessions_lock);
+}
+
+void mali_session_add(struct mali_session_data *session)
+{
+ mali_session_lock();
+ _mali_osk_list_add(&session->link, &mali_sessions);
+ mali_session_unlock();
+}
+
+void mali_session_remove(struct mali_session_data *session)
+{
+ mali_session_lock();
+ _mali_osk_list_delinit(&session->link);
+ mali_session_unlock();
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_session.h b/drivers/media/video/samsung/mali/common/mali_session.h
new file mode 100644
index 0000000..b47c340
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_session.h
@@ -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.
+ */
+
+#ifndef __MALI_SESSION_H__
+#define __MALI_SESSION_H__
+
+#include "mali_mmu_page_directory.h"
+#include "mali_kernel_descriptor_mapping.h"
+#include "mali_osk.h"
+#include "mali_osk_list.h"
+
+struct mali_session_data
+{
+ _mali_osk_notification_queue_t * ioctl_queue;
+
+ _mali_osk_lock_t *memory_lock; /**< Lock protecting the vm manipulation */
+ mali_descriptor_mapping * descriptor_mapping; /**< Mapping between userspace descriptors and our pointers */
+ _mali_osk_list_t memory_head; /**< Track all the memory allocated in this session, for freeing on abnormal termination */
+
+ struct mali_page_directory *page_directory; /**< MMU page directory for this session */
+
+ _MALI_OSK_LIST_HEAD(link); /**< Link for list of all sessions */
+};
+
+_mali_osk_errcode_t mali_session_initialize(void);
+void mali_session_terminate(void);
+
+/* List of all sessions. Actual list head in mali_kernel_core.c */
+extern _mali_osk_list_t mali_sessions;
+/* Lock to protect modification and access to the mali_sessions list */
+extern _mali_osk_lock_t *mali_sessions_lock;
+
+MALI_STATIC_INLINE void mali_session_lock(void)
+{
+ _mali_osk_lock_wait(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+MALI_STATIC_INLINE void mali_session_unlock(void)
+{
+ _mali_osk_lock_signal(mali_sessions_lock, _MALI_OSK_LOCKMODE_RW);
+}
+
+void mali_session_add(struct mali_session_data *session);
+void mali_session_remove(struct mali_session_data *session);
+#define MALI_SESSION_FOREACH(session, tmp, link) \
+ _MALI_OSK_LIST_FOREACHENTRY(session, tmp, &mali_sessions, struct mali_session_data, link)
+
+MALI_STATIC_INLINE struct mali_page_directory *mali_session_get_page_directory(struct mali_session_data *session)
+{
+ return session->page_directory;
+}
+
+MALI_STATIC_INLINE void mali_session_send_notification(struct mali_session_data *session, _mali_osk_notification_t *object)
+{
+ _mali_osk_notification_queue_send(session->ioctl_queue, object);
+}
+
+#endif /* __MALI_SESSION_H__ */
diff --git a/drivers/media/video/samsung/mali/common/mali_ukk.h b/drivers/media/video/samsung/mali/common/mali_ukk.h
index 94efdf5..8ff2002 100644
--- a/drivers/media/video/samsung/mali/common/mali_ukk.h
+++ b/drivers/media/video/samsung/mali/common/mali_ukk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -17,7 +17,7 @@
#define __MALI_UKK_H__
#include "mali_osk.h"
-#include "mali_uk_types.h"
+#include "../linux/mali_uk_types.h"
#ifdef __cplusplus
extern "C"
@@ -139,14 +139,6 @@ extern "C"
* (_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.
@@ -233,7 +225,7 @@ _mali_osk_errcode_t _mali_ukk_close( void **context );
* 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"
+ * @param args see _mali_uk_get_system_info_size_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_system_info_size( _mali_uk_get_system_info_size_s *args );
@@ -270,7 +262,7 @@ _mali_osk_errcode_t _mali_ukk_get_system_info_size( _mali_uk_get_system_info_siz
* 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"
+ * @param args see _mali_uk_get_system_info_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args );
@@ -279,24 +271,37 @@ _mali_osk_errcode_t _mali_ukk_get_system_info( _mali_uk_get_system_info_s *args
*
* 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"
+ * @param args see _mali_uk_wait_for_notification_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args );
/** @brief Post a notification to the notification queue of this application.
*
- * @param args see _mali_uk_post_notification_s in "mali_uk_types.h"
+ * @param args see _mali_uk_post_notification_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_post_notification( _mali_uk_post_notification_s *args );
/** @brief Verifies if the user and kernel side of this API are compatible.
*
- * @param args see _mali_uk_get_api_version_s in "mali_uk_types.h"
+ * @param args see _mali_uk_get_api_version_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args );
+
+/** @brief Get the user space settings applicable for calling process.
+ *
+ * @param args see _mali_uk_get_user_settings_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args);
+
+/** @brief Get a user space setting applicable for calling process.
+ *
+ * @param args see _mali_uk_get_user_setting_s in "mali_utgard_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args);
+
/** @} */ /* end group _mali_uk_core */
@@ -324,7 +329,7 @@ _mali_osk_errcode_t _mali_ukk_get_api_version( _mali_uk_get_api_version_s *args
* @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
+ * @param args see \ref _mali_uk_init_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable
* _mali_osk_errcode_t on failure.
*/
@@ -340,43 +345,18 @@ _mali_osk_errcode_t _mali_ukk_init_mem( _mali_uk_init_mem_s *args );
* @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
+ * @param args see \ref _mali_uk_term_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable
* _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_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.
+ * but should not be called by a user process in Mali-nonMMU mode.
*
* The implementation and operation of _mali_ukk_mem_mmap() is dependant on whether the driver is built for Mali-MMU
* or Mali-nonMMU:
@@ -392,9 +372,6 @@ _mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args );
* 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.
@@ -403,7 +380,7 @@ _mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args );
* 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"
+ * @param args see _mali_uk_mem_mmap_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args );
@@ -413,42 +390,42 @@ _mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args );
* 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"
+ * @param args see _mali_uk_mem_munmap_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args );
/** @brief Determine the buffer size necessary for an MMU page table dump.
- * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_uk_types.h
+ * @param args see _mali_uk_query_mmu_page_table_dump_size_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_query_mmu_page_table_dump_size( _mali_uk_query_mmu_page_table_dump_size_s *args );
/** @brief Dump MMU Page tables.
- * @param args see _mali_uk_dump_mmu_page_table_s in mali_uk_types.h
+ * @param args see _mali_uk_dump_mmu_page_table_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args );
/** @brief Map a physically contiguous range of memory into Mali
- * @param args see _mali_uk_map_external_mem_s in mali_uk_types.h
+ * @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args );
/** @brief Unmap a physically contiguous range of memory from Mali
- * @param args see _mali_uk_unmap_external_mem_s in mali_uk_types.h
+ * @param args see _mali_uk_unmap_external_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s *args );
#if 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
+ * @param args see _mali_uk_attach_ump_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args );
/** @brief Unmap UMP memory from Mali
- * @param args see _mali_uk_release_ump_mem_s in mali_uk_types.h
+ * @param args see _mali_uk_release_ump_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args );
@@ -492,7 +469,7 @@ _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args
* @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"
+ * @param args see _mali_uk_va_to_mali_pa_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args );
@@ -519,20 +496,16 @@ _mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args );
* 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"
+ * @param args see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_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"
+ * @param args see _mali_uk_get_pp_number_of_cores_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_cores_s *args );
@@ -542,22 +515,18 @@ _mali_osk_errcode_t _mali_ukk_get_pp_number_of_cores( _mali_uk_get_pp_number_of_
* 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"
+ * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_pp_core_version( _mali_uk_get_pp_core_version_s *args );
-/** @brief Abort any PP jobs with the given ID.
+/** @brief Disable Write-back unit(s) on specified job
*
- * 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"
+ * @param args see _mali_uk_get_pp_core_version_s in "mali_utgard_uk_types.h"
*/
-void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_s *args );
+void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args);
+
+
/** @} */ /* end group _mali_uk_pp */
@@ -580,20 +549,16 @@ void _mali_ukk_pp_abort_job( _mali_uk_pp_abort_job_s *args );
* 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"
+ * @param args see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_gp_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"
+ * @param args see _mali_uk_get_gp_number_of_cores_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_cores_s *args );
@@ -603,7 +568,7 @@ _mali_osk_errcode_t _mali_ukk_get_gp_number_of_cores( _mali_uk_get_gp_number_of_
* 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"
+ * @param args see _mali_uk_get_gp_core_version_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_s *args );
@@ -613,85 +578,47 @@ _mali_osk_errcode_t _mali_ukk_get_gp_core_version( _mali_uk_get_gp_core_version_
* 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"
+ * @param args see _mali_uk_gp_suspend_response_s in "mali_utgard_uk_types.h"
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
*/
_mali_osk_errcode_t _mali_ukk_gp_suspend_response( _mali_uk_gp_suspend_response_s *args );
-/** @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"
+ * @param args see _mali_uk_profiling_start_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args);
/** @brief Add event to profiling buffer.
*
- * @param args see _mali_uk_profiling_add_event_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_add_event_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args);
/** @brief Stop recording profiling events.
*
- * @param args see _mali_uk_profiling_stop_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_stop_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args);
/** @brief Retrieve a recorded profiling event.
*
- * @param args see _mali_uk_profiling_get_event_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_get_event_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args);
/** @brief Clear recorded profiling events.
*
- * @param args see _mali_uk_profiling_clear_s in "mali_uk_types.h"
+ * @param args see _mali_uk_profiling_clear_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args);
-/** @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);
-
-/** @brief Transfer software counters from user to kernel space
- *
- * @param args see _mali_uk_transfer_sw_counters_s in "mali_uk_types.h"
- */
-_mali_osk_errcode_t _mali_ukk_transfer_sw_counters(_mali_uk_sw_counters_s *args);
-
/** @} */ /* end group _mali_uk_profiling */
#endif
@@ -704,12 +631,23 @@ _mali_osk_errcode_t _mali_ukk_transfer_sw_counters(_mali_uk_sw_counters_s *args)
* 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"
+ * @param args see _mali_uk_vsync_event_report_s in "mali_utgard_uk_types.h"
*/
_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args);
/** @} */ /* end group _mali_uk_vsync */
+/** @addtogroup _mali_sw_counters_report U/K Software counter reporting
+ * @{ */
+
+/** @brief Report software counters.
+ *
+ * @param args see _mali_uk_sw_counters_report_s in "mali_uk_types.h"
+ */
+_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args);
+
+/** @} */ /* end group _mali_sw_counters_report */
+
/** @} */ /* end group u_k_api */
/** @} */ /* end group uddapi */
diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.c b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c
new file mode 100644
index 0000000..681c2b0
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_user_settings_db.c
@@ -0,0 +1,88 @@
+/**
+ * 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.
+ */
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_uk_types.h"
+#include "mali_user_settings_db.h"
+#include "mali_session.h"
+
+static u32 mali_user_settings[_MALI_UK_USER_SETTING_MAX];
+const char *_mali_uk_user_setting_descriptions[] = _MALI_UK_USER_SETTING_DESCRIPTIONS;
+
+static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value)
+{
+ struct mali_session_data *session, *tmp;
+
+ mali_session_lock();
+ MALI_SESSION_FOREACH(session, tmp, link)
+ {
+ _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED, sizeof(_mali_uk_settings_changed_s));
+ _mali_uk_settings_changed_s *data = notobj->result_buffer;
+ data->setting = setting;
+ data->value = value;
+
+ mali_session_send_notification(session, notobj);
+ }
+ mali_session_unlock();
+}
+
+void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value)
+{
+ mali_bool notify = MALI_FALSE;
+
+ MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0);
+
+ if (mali_user_settings[setting] != value)
+ {
+ notify = MALI_TRUE;
+ }
+
+ mali_user_settings[setting] = value;
+
+ if (notify)
+ {
+ mali_user_settings_notify(setting, value);
+ }
+}
+
+u32 mali_get_user_setting(_mali_uk_user_setting_t setting)
+{
+ MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0);
+
+ return mali_user_settings[setting];
+}
+
+_mali_osk_errcode_t _mali_ukk_get_user_setting(_mali_uk_get_user_setting_s *args)
+{
+ _mali_uk_user_setting_t setting;
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ setting = args->setting;
+
+ if (0 <= setting && _MALI_UK_USER_SETTING_MAX > setting)
+ {
+ args->value = mali_user_settings[setting];
+ return _MALI_OSK_ERR_OK;
+ }
+ else
+ {
+ return _MALI_OSK_ERR_INVALID_ARGS;
+ }
+}
+
+_mali_osk_errcode_t _mali_ukk_get_user_settings(_mali_uk_get_user_settings_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ _mali_osk_memcpy(args->settings, mali_user_settings, (sizeof(u32) * _MALI_UK_USER_SETTING_MAX));
+
+ return _MALI_OSK_ERR_OK;
+}
diff --git a/drivers/media/video/samsung/mali/common/mali_user_settings_db.h b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h
new file mode 100644
index 0000000..fbb9415
--- /dev/null
+++ b/drivers/media/video/samsung/mali/common/mali_user_settings_db.h
@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+
+#ifndef __MALI_USER_SETTINGS_DB_H__
+#define __MALI_USER_SETTINGS_DB_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "mali_uk_types.h"
+
+/** @brief Set Mali user setting in DB
+ *
+ * Update the DB with a new value for \a setting. If the value is different from theprevious set value running sessions will be notified of the change.
+ *
+ * @param setting the setting to be changed
+ * @param value the new value to set
+ */
+void mali_set_user_setting(_mali_uk_user_setting_t setting, u32 value);
+
+/** @brief Get current Mali user setting value from DB
+ *
+ * @param setting the setting to extract
+ * @return the value of the selected setting
+ */
+u32 mali_get_user_setting(_mali_uk_user_setting_t setting);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MALI_KERNEL_USER_SETTING__ */
diff --git a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c
deleted file mode 100644
index 7041391..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * 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_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"
-#include "mali_kernel_pm.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 */
- NULL, /*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 */
- if (_mali_osk_pmm_dev_activate() < 0) {
- MALI_PRINT(("PMM: Try again PD_G3D enable\n"));
- if (mali_pd_enable() < 0) {
- MALI_PRINT(("PMM: Mali PMM device activate failed\n"));
- err = _MALI_OSK_ERR_FAULT;
- return err;
- }
- }
-#endif
- }
-
-#if USING_MALI_PMU
- err = mali_pmm_pmu_powerup( cores );
-#endif
-
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
- mali_platform_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 MALI_PMM_RUNTIME_JOB_CONTROL_ON
- mali_platform_powerdown(cores);
-#endif
-
-#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/media/video/samsung/mali/common/pmm/mali_pmm.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm.h
deleted file mode 100644
index 5170650..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * 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_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
- */
-int _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/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c
deleted file mode 100644
index a8160ac..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h
deleted file mode 100644
index 7525cac..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_pmu.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_policy.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c
deleted file mode 100644
index 87b6ec2..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_policy.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h
deleted file mode 100644
index 75ac8c8..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c
deleted file mode 100644
index 0a6b471..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h
deleted file mode 100644
index da13224..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_alwayson.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c
deleted file mode 100644
index 237d702..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h
deleted file mode 100644
index dcfa438..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_policy_jobcontrol.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_state.c b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c
deleted file mode 100644
index d529b9a..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * 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.
- */
-
-#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/media/video/samsung/mali/common/pmm/mali_pmm_state.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h
deleted file mode 100644
index 4768344..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_state.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/pmm/mali_pmm_system.h b/drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h
deleted file mode 100644
index eccd35b..0000000
--- a/drivers/media/video/samsung/mali/common/pmm/mali_pmm_system.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/common/mali_kernel_gp.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h
index efd3b43..7c78947 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_gp.h
+++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,14 +8,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_KERNEL_GP2_H__
-#define __MALI_KERNEL_GP2_H__
+#ifndef __MALI_UTGARD_H__
+#define __MALI_UTGARD_H__
-extern struct mali_kernel_subsystem mali_subsystem_gp2;
+/** @brief MALI GPU power down using MALI in-built PMU
+ *
+ * called to power down all cores
+ */
+int mali_pmu_powerdown(void);
+
+
+/** @brief MALI GPU power up using MALI in-built PMU
+ *
+ * called to power up all cores
+ */
+int mali_pmu_powerup(void);
-#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_UTGARD_H__ */
-#endif /* __MALI_KERNEL_GP2_H__ */
diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h
new file mode 100644
index 0000000..40822f7
--- /dev/null
+++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_counters.h
@@ -0,0 +1,264 @@
+/*
+ * 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_UTGARD_COUNTERS_H_
+#define _MALI_UTGARD_COUNTERS_H_
+
+typedef struct
+{
+ void *unused;
+} mali_cinstr_counter_info;
+
+typedef enum
+{
+ MALI_CINSTR_COUNTER_SOURCE_EGL = 0,
+ MALI_CINSTR_COUNTER_SOURCE_OPENGLES = 1000,
+ MALI_CINSTR_COUNTER_SOURCE_OPENVG = 2000,
+ MALI_CINSTR_COUNTER_SOURCE_GP = 3000,
+ MALI_CINSTR_COUNTER_SOURCE_PP = 4000,
+} cinstr_counter_source;
+
+#define MALI_CINSTR_EGL_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_EGL
+#define MALI_CINSTR_EGL_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_EGL + 999)
+
+#define MALI_CINSTR_GLES_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENGLES
+#define MALI_CINSTR_GLES_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 999)
+
+#define MALI_CINSTR_VG_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_OPENVG
+#define MALI_CINSTR_VG_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_OPENVG + 999)
+
+#define MALI_CINSTR_GP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_GP
+#define MALI_CINSTR_GP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_GP + 999)
+
+#define MALI_CINSTR_PP_FIRST_COUNTER MALI_CINSTR_COUNTER_SOURCE_PP
+#define MALI_CINSTR_PP_LAST_COUNTER (MALI_CINSTR_COUNTER_SOURCE_PP + 999)
+
+
+typedef enum
+{
+ /* EGL counters */
+
+ MALI_CINSTR_EGL_BLIT_TIME = MALI_CINSTR_COUNTER_SOURCE_EGL + 0,
+
+ /* Last counter in the EGL set */
+ MALI_CINSTR_EGL_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_EGL + 1,
+
+ /* GLES counters */
+
+ MALI_CINSTR_GLES_DRAW_ELEMENTS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 0,
+ MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_INDICES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 1,
+ MALI_CINSTR_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 2,
+ MALI_CINSTR_GLES_DRAW_ARRAYS_CALLS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 3,
+ MALI_CINSTR_GLES_DRAW_ARRAYS_NUM_TRANSFORMED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 4,
+ MALI_CINSTR_GLES_DRAW_POINTS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 5,
+ MALI_CINSTR_GLES_DRAW_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 6,
+ MALI_CINSTR_GLES_DRAW_LINE_LOOP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 7,
+ MALI_CINSTR_GLES_DRAW_LINE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 8,
+ MALI_CINSTR_GLES_DRAW_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 9,
+ MALI_CINSTR_GLES_DRAW_TRIANGLE_STRIP = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 10,
+ MALI_CINSTR_GLES_DRAW_TRIANGLE_FAN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 11,
+ MALI_CINSTR_GLES_NON_VBO_DATA_COPY_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 12,
+ MALI_CINSTR_GLES_UNIFORM_BYTES_COPIED_TO_MALI = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 13,
+ MALI_CINSTR_GLES_UPLOAD_TEXTURE_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 14,
+ MALI_CINSTR_GLES_UPLOAD_VBO_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 15,
+ MALI_CINSTR_GLES_NUM_FLUSHES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 16,
+ MALI_CINSTR_GLES_NUM_VSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 17,
+ MALI_CINSTR_GLES_NUM_FSHADERS_GENERATED = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 18,
+ MALI_CINSTR_GLES_VSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 19,
+ MALI_CINSTR_GLES_FSHADER_GEN_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 20,
+ MALI_CINSTR_GLES_INPUT_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 21,
+ MALI_CINSTR_GLES_VXCACHE_HIT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 22,
+ MALI_CINSTR_GLES_VXCACHE_MISS = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 23,
+ MALI_CINSTR_GLES_VXCACHE_COLLISION = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 24,
+ MALI_CINSTR_GLES_CULLED_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 25,
+ MALI_CINSTR_GLES_CULLED_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 26,
+ MALI_CINSTR_GLES_BACKFACE_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 27,
+ MALI_CINSTR_GLES_GBCLIP_TRIANGLES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 28,
+ MALI_CINSTR_GLES_GBCLIP_LINES = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 29,
+ MALI_CINSTR_GLES_TRIANGLES_DRAWN = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 30,
+ MALI_CINSTR_GLES_DRAWCALL_TIME = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 31,
+ MALI_CINSTR_GLES_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 32,
+ MALI_CINSTR_GLES_INDEPENDENT_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 33,
+ MALI_CINSTR_GLES_STRIP_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 34,
+ MALI_CINSTR_GLES_FAN_TRIANGLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 35,
+ MALI_CINSTR_GLES_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 36,
+ MALI_CINSTR_GLES_INDEPENDENT_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 37,
+ MALI_CINSTR_GLES_STRIP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 38,
+ MALI_CINSTR_GLES_LOOP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 39,
+ MALI_CINSTR_GLES_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 40,
+
+ /* Last counter in the GLES set */
+ MALI_CINSTR_GLES_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENGLES + 41,
+
+ /* OpenVG counters */
+
+ MALI_CINSTR_VG_MASK_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 0,
+ MALI_CINSTR_VG_CLEAR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 1,
+ MALI_CINSTR_VG_APPEND_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 2,
+ MALI_CINSTR_VG_APPEND_PATH_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 3,
+ MALI_CINSTR_VG_MODIFY_PATH_COORDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 4,
+ MALI_CINSTR_VG_TRANSFORM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 5,
+ MALI_CINSTR_VG_INTERPOLATE_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 6,
+ MALI_CINSTR_VG_PATH_LENGTH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 7,
+ MALI_CINSTR_VG_POINT_ALONG_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 8,
+ MALI_CINSTR_VG_PATH_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 9,
+ MALI_CINSTR_VG_PATH_TRANSFORMED_BOUNDS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 10,
+ MALI_CINSTR_VG_DRAW_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 11,
+ MALI_CINSTR_VG_CLEAR_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 12,
+ MALI_CINSTR_VG_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 13,
+ MALI_CINSTR_VG_GET_IMAGE_SUB_DATA_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 14,
+ MALI_CINSTR_VG_COPY_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 15,
+ MALI_CINSTR_VG_DRAW_IMAGE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 16,
+ MALI_CINSTR_VG_SET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 17,
+ MALI_CINSTR_VG_WRITE_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 18,
+ MALI_CINSTR_VG_GET_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 19,
+ MALI_CINSTR_VG_READ_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 20,
+ MALI_CINSTR_VG_COPY_PIXELS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 21,
+ MALI_CINSTR_VG_COLOR_MATRIX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 22,
+ MALI_CINSTR_VG_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 23,
+ MALI_CINSTR_VG_SEPARABLE_CONVOLVE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 24,
+ MALI_CINSTR_VG_GAUSSIAN_BLUR_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 25,
+ MALI_CINSTR_VG_LOOKUP_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 26,
+ MALI_CINSTR_VG_LOOKUP_SINGLE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 27,
+ MALI_CINSTR_VG_CONTEXT_CREATE_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 28,
+ MALI_CINSTR_VG_STROKED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 29,
+ MALI_CINSTR_VG_STROKED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 30,
+ MALI_CINSTR_VG_STROKED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 31,
+ MALI_CINSTR_VG_STROKED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 32,
+ MALI_CINSTR_VG_FILLED_CUBICS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 33,
+ MALI_CINSTR_VG_FILLED_QUADS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 34,
+ MALI_CINSTR_VG_FILLED_ARCS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 35,
+ MALI_CINSTR_VG_FILLED_LINES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 36,
+ MALI_CINSTR_VG_DRAW_PATH_CALLS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 37,
+ MALI_CINSTR_VG_TRIANGLES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 38,
+ MALI_CINSTR_VG_VERTICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 39,
+ MALI_CINSTR_VG_INDICES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 40,
+ MALI_CINSTR_VG_FILLED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 41,
+ MALI_CINSTR_VG_STROKED_PATHS_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 42,
+ MALI_CINSTR_VG_FILL_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 43,
+ MALI_CINSTR_VG_DRAW_FILLED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 44,
+ MALI_CINSTR_VG_STROKE_EXTRACT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 45,
+ MALI_CINSTR_VG_DRAW_STROKED_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 46,
+ MALI_CINSTR_VG_DRAW_PAINT_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 47,
+ MALI_CINSTR_VG_DATA_STRUCTURES_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 48,
+ MALI_CINSTR_VG_MEM_PATH_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 49,
+ MALI_CINSTR_VG_RSW_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 50,
+
+ /* Last counter in the VG set */
+ MALI_CINSTR_VG_MAX_COUNTER = MALI_CINSTR_COUNTER_SOURCE_OPENVG + 51,
+
+ /* Mali GP counters */
+
+ MALI_CINSTR_GP_DEPRECATED_0 = MALI_CINSTR_COUNTER_SOURCE_GP + 0,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_GP = MALI_CINSTR_COUNTER_SOURCE_GP + 1,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 2,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_STORER = MALI_CINSTR_COUNTER_SOURCE_GP + 3,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_LOADER = MALI_CINSTR_COUNTER_SOURCE_GP + 4,
+ MALI_CINSTR_GP_CYCLES_VERTEX_LOADER_WAITING_FOR_VERTEX_SHADER = MALI_CINSTR_COUNTER_SOURCE_GP + 5,
+ MALI_CINSTR_GP_NUMBER_OF_WORDS_READ = MALI_CINSTR_COUNTER_SOURCE_GP + 6,
+ MALI_CINSTR_GP_NUMBER_OF_WORDS_WRITTEN = MALI_CINSTR_COUNTER_SOURCE_GP + 7,
+ MALI_CINSTR_GP_NUMBER_OF_READ_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 8,
+ MALI_CINSTR_GP_NUMBER_OF_WRITE_BURSTS = MALI_CINSTR_COUNTER_SOURCE_GP + 9,
+ MALI_CINSTR_GP_NUMBER_OF_VERTICES_PROCESSED = MALI_CINSTR_COUNTER_SOURCE_GP + 10,
+ MALI_CINSTR_GP_NUMBER_OF_VERTICES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 11,
+ MALI_CINSTR_GP_NUMBER_OF_PRIMITIVES_FETCHED = MALI_CINSTR_COUNTER_SOURCE_GP + 12,
+ MALI_CINSTR_GP_RESERVED_13 = MALI_CINSTR_COUNTER_SOURCE_GP + 13,
+ MALI_CINSTR_GP_NUMBER_OF_BACKFACE_CULLINGS_DONE = MALI_CINSTR_COUNTER_SOURCE_GP + 14,
+ MALI_CINSTR_GP_NUMBER_OF_COMMANDS_WRITTEN_TO_TILES = MALI_CINSTR_COUNTER_SOURCE_GP + 15,
+ MALI_CINSTR_GP_NUMBER_OF_MEMORY_BLOCKS_ALLOCATED = MALI_CINSTR_COUNTER_SOURCE_GP + 16,
+ MALI_CINSTR_GP_RESERVED_17 = MALI_CINSTR_COUNTER_SOURCE_GP + 17,
+ MALI_CINSTR_GP_RESERVED_18 = MALI_CINSTR_COUNTER_SOURCE_GP + 18,
+ MALI_CINSTR_GP_NUMBER_OF_VERTEX_LOADER_CACHE_MISSES = MALI_CINSTR_COUNTER_SOURCE_GP + 19,
+ MALI_CINSTR_GP_RESERVED_20 = MALI_CINSTR_COUNTER_SOURCE_GP + 20,
+ MALI_CINSTR_GP_RESERVED_21 = MALI_CINSTR_COUNTER_SOURCE_GP + 21,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_VERTEX_SHADER_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 22,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_COMMAND_PROCESSOR = MALI_CINSTR_COUNTER_SOURCE_GP + 23,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_LIST_WRITER = MALI_CINSTR_COUNTER_SOURCE_GP + 24,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_THROUGH_THE_PREPARE_LIST_COMMANDS = MALI_CINSTR_COUNTER_SOURCE_GP + 25,
+ MALI_CINSTR_GP_RESERVED_26 = MALI_CINSTR_COUNTER_SOURCE_GP + 26,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_PRIMITIVE_ASSEMBLY = MALI_CINSTR_COUNTER_SOURCE_GP + 27,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_VERTEX_FETCHER = MALI_CINSTR_COUNTER_SOURCE_GP + 28,
+ MALI_CINSTR_GP_RESERVED_29 = MALI_CINSTR_COUNTER_SOURCE_GP + 29,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_BOUNDINGBOX_AND_COMMAND_GENERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 30,
+ MALI_CINSTR_GP_RESERVED_31 = MALI_CINSTR_COUNTER_SOURCE_GP + 31,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_SCISSOR_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 32,
+ MALI_CINSTR_GP_ACTIVE_CYCLES_PLBU_TILE_ITERATOR = MALI_CINSTR_COUNTER_SOURCE_GP + 33,
+ MALI_CINSTR_GP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_GP + 900,
+
+ /* Mali PP counters */
+
+ MALI_CINSTR_PP_ACTIVE_CLOCK_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 0,
+ MALI_CINSTR_PP_TOTAL_CLOCK_CYCLES_COUNT_REMOVED = MALI_CINSTR_COUNTER_SOURCE_PP + 1,
+ MALI_CINSTR_PP_TOTAL_BUS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 2,
+ MALI_CINSTR_PP_TOTAL_BUS_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 3,
+ MALI_CINSTR_PP_BUS_READ_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 4,
+ MALI_CINSTR_PP_BUS_WRITE_REQUEST_CYCLES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 5,
+ MALI_CINSTR_PP_BUS_READ_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 6,
+ MALI_CINSTR_PP_BUS_WRITE_TRANSACTIONS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 7,
+ MALI_CINSTR_PP_RESERVED_08 = MALI_CINSTR_COUNTER_SOURCE_PP + 8,
+ MALI_CINSTR_PP_TILE_WRITEBACK_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 9,
+ MALI_CINSTR_PP_STORE_UNIT_WRITES = MALI_CINSTR_COUNTER_SOURCE_PP + 10,
+ MALI_CINSTR_PP_RESERVED_11 = MALI_CINSTR_COUNTER_SOURCE_PP + 11,
+ MALI_CINSTR_PP_PALETTE_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 12,
+ MALI_CINSTR_PP_TEXTURE_CACHE_UNCOMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 13,
+ MALI_CINSTR_PP_POLYGON_LIST_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 14,
+ MALI_CINSTR_PP_RSW_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 15,
+ MALI_CINSTR_PP_VERTEX_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 16,
+ MALI_CINSTR_PP_UNIFORM_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 17,
+ MALI_CINSTR_PP_PROGRAM_CACHE_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19,
+ MALI_CINSTR_PP_VARYING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 19,
+ MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 20,
+ MALI_CINSTR_PP_TEXTURE_DESCRIPTORS_REMAPPING_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 21,
+ MALI_CINSTR_PP_TEXTURE_CACHE_COMPRESSED_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 22,
+ MALI_CINSTR_PP_LOAD_UNIT_READS = MALI_CINSTR_COUNTER_SOURCE_PP + 23,
+ MALI_CINSTR_PP_POLYGON_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 24,
+ MALI_CINSTR_PP_PIXEL_RECTANGLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 25,
+ MALI_CINSTR_PP_LINES_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 26,
+ MALI_CINSTR_PP_POINTS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 27,
+ MALI_CINSTR_PP_STALL_CYCLES_POLYGON_LIST_READER = MALI_CINSTR_COUNTER_SOURCE_PP + 28,
+ MALI_CINSTR_PP_STALL_CYCLES_TRIANGLE_SETUP = MALI_CINSTR_COUNTER_SOURCE_PP + 29,
+ MALI_CINSTR_PP_QUAD_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 30,
+ MALI_CINSTR_PP_FRAGMENT_RASTERIZED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 31,
+ MALI_CINSTR_PP_FRAGMENT_REJECTED_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 32,
+ MALI_CINSTR_PP_FRAGMENT_REJECTED_FWD_FRAGMENT_KILL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 33,
+ MALI_CINSTR_PP_FRAGMENT_PASSED_ZSTENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 34,
+ MALI_CINSTR_PP_PATCHES_REJECTED_EARLY_Z_STENCIL_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 35,
+ MALI_CINSTR_PP_PATCHES_EVALUATED = MALI_CINSTR_COUNTER_SOURCE_PP + 36,
+ MALI_CINSTR_PP_INSTRUCTION_COMPLETED_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 37,
+ MALI_CINSTR_PP_INSTRUCTION_FAILED_RENDEZVOUS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 38,
+ MALI_CINSTR_PP_INSTRUCTION_FAILED_VARYING_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 39,
+ MALI_CINSTR_PP_INSTRUCTION_FAILED_TEXTURE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 40,
+ MALI_CINSTR_PP_INSTRUCTION_FAILED_LOAD_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 41,
+ MALI_CINSTR_PP_INSTRUCTION_FAILED_TILE_READ_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 42,
+ MALI_CINSTR_PP_INSTRUCTION_FAILED_STORE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 43,
+ MALI_CINSTR_PP_RENDEZVOUS_BREAKAGE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 44,
+ MALI_CINSTR_PP_PIPELINE_BUBBLES_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 45,
+ MALI_CINSTR_PP_TEXTURE_MAPPER_MULTIPASS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 46,
+ MALI_CINSTR_PP_TEXTURE_MAPPER_CYCLE_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 47,
+ MALI_CINSTR_PP_VERTEX_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 48,
+ MALI_CINSTR_PP_VERTEX_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 49,
+ MALI_CINSTR_PP_VARYING_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 50,
+ MALI_CINSTR_PP_VARYING_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 51,
+ MALI_CINSTR_PP_VARYING_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 52,
+ MALI_CINSTR_PP_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 53,
+ MALI_CINSTR_PP_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 54,
+ MALI_CINSTR_PP_TEXTURE_CACHE_CONFLICT_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 55,
+ MALI_CINSTR_PP_PALETTE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 200 only */
+ MALI_CINSTR_PP_PALETTE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 200 only */
+ MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 56, /* Mali 400 class only */
+ MALI_CINSTR_PP_COMPRESSED_TEXTURE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 57, /* Mali 400 class only */
+ MALI_CINSTR_PP_LOAD_STORE_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 58,
+ MALI_CINSTR_PP_LOAD_STORE_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 59,
+ MALI_CINSTR_PP_PROGRAM_CACHE_HIT_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 60,
+ MALI_CINSTR_PP_PROGRAM_CACHE_MISS_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 61,
+ MALI_CINSTR_PP_JOB_COUNT = MALI_CINSTR_COUNTER_SOURCE_PP + 900,
+} cinstr_counters_m200_t;
+
+#endif /*_MALI_UTGARD_COUNTERS_H_*/
diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.h
new file mode 100644
index 0000000..31af4cf
--- /dev/null
+++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_ioctl.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.
+ */
+
+#ifndef __MALI_UTGARD_IOCTL_H__
+#define __MALI_UTGARD_IOCTL_H__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h> /* file system operations */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file mali_kernel_ioctl.h
+ * Interface to the Linux device driver.
+ * This file describes the interface needed to use the Linux device driver.
+ * Its interface is designed to used by the HAL implementation through a thin arch layer.
+ */
+
+/**
+ * ioctl commands
+ */
+
+#define MALI_IOC_BASE 0x82
+#define MALI_IOC_CORE_BASE (_MALI_UK_CORE_SUBSYSTEM + MALI_IOC_BASE)
+#define MALI_IOC_MEMORY_BASE (_MALI_UK_MEMORY_SUBSYSTEM + MALI_IOC_BASE)
+#define MALI_IOC_PP_BASE (_MALI_UK_PP_SUBSYSTEM + MALI_IOC_BASE)
+#define MALI_IOC_GP_BASE (_MALI_UK_GP_SUBSYSTEM + MALI_IOC_BASE)
+#define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE)
+#define MALI_IOC_VSYNC_BASE (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE)
+
+#define MALI_IOC_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_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *)
+#define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *)
+#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *)
+#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *)
+#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _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_DISABLE_WB _IOW (MALI_IOC_PP_BASE, _MALI_UK_PP_DISABLE_WB, _mali_uk_pp_disable_wb_s * )
+#define MALI_IOC_GP2_START_JOB _IOWR(MALI_IOC_GP_BASE, _MALI_UK_GP_START_JOB, _mali_uk_gp_start_job_s *)
+#define MALI_IOC_GP2_NUMBER_OF_CORES_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_NUMBER_OF_CORES, _mali_uk_get_gp_number_of_cores_s *)
+#define MALI_IOC_GP2_CORE_VERSION_GET _IOR (MALI_IOC_GP_BASE, _MALI_UK_GET_GP_CORE_VERSION, _mali_uk_get_gp_core_version_s *)
+#define MALI_IOC_GP2_SUSPEND_RESPONSE _IOW (MALI_IOC_GP_BASE, _MALI_UK_GP_SUSPEND_RESPONSE,_mali_uk_gp_suspend_response_s *)
+#define MALI_IOC_PROFILING_START _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_START, _mali_uk_profiling_start_s *)
+#define MALI_IOC_PROFILING_ADD_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_ADD_EVENT, _mali_uk_profiling_add_event_s*)
+#define MALI_IOC_PROFILING_STOP _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *)
+#define MALI_IOC_PROFILING_GET_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *)
+#define MALI_IOC_PROFILING_CLEAR _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *)
+#define MALI_IOC_PROFILING_GET_CONFIG _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_CONFIG, _mali_uk_get_user_settings_s *)
+#define MALI_IOC_PROFILING_REPORT_SW_COUNTERS _IOW (MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_REPORT_SW_COUNTERS, _mali_uk_sw_counters_report_s *)
+#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MALI_UTGARD_IOCTL_H__ */
diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h
new file mode 100644
index 0000000..129526f
--- /dev/null
+++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.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_UTGARD_PROFILING_EVENTS_H_
+#define _MALI_UTGARD_PROFILING_EVENTS_H_
+
+/*
+ * The event ID is a 32 bit value consisting of different fields
+ * reserved, 4 bits, for future use
+ * event type, 4 bits, cinstr_profiling_event_type_t
+ * event channel, 8 bits, the source of the event.
+ * event data, 16 bit field, data depending on event type
+ */
+
+/**
+ * Specifies what kind of event this is
+ */
+typedef enum
+{
+ MALI_PROFILING_EVENT_TYPE_SINGLE = 0 << 24,
+ MALI_PROFILING_EVENT_TYPE_START = 1 << 24,
+ MALI_PROFILING_EVENT_TYPE_STOP = 2 << 24,
+ MALI_PROFILING_EVENT_TYPE_SUSPEND = 3 << 24,
+ MALI_PROFILING_EVENT_TYPE_RESUME = 4 << 24,
+} cinstr_profiling_event_type_t;
+
+
+/**
+ * Secifies the channel/source of the event
+ */
+typedef enum
+{
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE = 0 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_GP0 = 1 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP0 = 5 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP1 = 6 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP2 = 7 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP3 = 8 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP4 = 9 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP5 = 10 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP6 = 11 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_PP7 = 12 << 16,
+ MALI_PROFILING_EVENT_CHANNEL_GPU = 21 << 16,
+} cinstr_profiling_event_channel_t;
+
+
+#define MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(num) (((MALI_PROFILING_EVENT_CHANNEL_GP0 >> 16) + (num)) << 16)
+#define MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(num) (((MALI_PROFILING_EVENT_CHANNEL_PP0 >> 16) + (num)) << 16)
+
+/**
+ * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from software channel
+ */
+typedef enum
+{
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_NONE = 0,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_NEW_FRAME = 1,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_FLUSH = 2,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SWAP_BUFFERS = 3,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC = 10,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC = 11,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55,
+} 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,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_QUEUE_BUFFER = 34,
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_ICS_DEQUEUE_BUFFER = 35,
+} 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 /*_MALI_UTGARD_PROFILING_EVENTS_H_*/
diff --git a/drivers/media/video/samsung/mali/common/mali_uk_types.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h
index e114fa8..512b1e2 100644
--- a/drivers/media/video/samsung/mali/common/mali_uk_types.h
+++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_uk_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,15 +13,8 @@
* 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"
+#ifndef __MALI_UTGARD_UK_TYPES_H__
+#define __MALI_UTGARD_UK_TYPES_H__
#ifdef __cplusplus
extern "C"
@@ -75,6 +68,8 @@ typedef enum
_MALI_UK_WAIT_FOR_NOTIFICATION, /**< _mali_ukk_wait_for_notification() */
_MALI_UK_GET_API_VERSION, /**< _mali_ukk_get_api_version() */
_MALI_UK_POST_NOTIFICATION, /**< _mali_ukk_post_notification() */
+ _MALI_UK_GET_USER_SETTING, /**< _mali_ukk_get_user_setting() *//**< [out] */
+ _MALI_UK_GET_USER_SETTINGS, /**< _mali_ukk_get_user_settings() *//**< [out] */
/** Memory functions */
@@ -95,21 +90,19 @@ typedef enum
/** 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() */
+ _MALI_UK_PP_DISABLE_WB, /**< _mali_ukk_pp_job_disable_wb() */
/** 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() */
@@ -122,12 +115,7 @@ typedef enum
_MALI_UK_PROFILING_GET_EVENT, /**< __mali_uku_profiling_get_event() */
_MALI_UK_PROFILING_CLEAR, /**< __mali_uku_profiling_clear() */
_MALI_UK_PROFILING_GET_CONFIG, /**< __mali_uku_profiling_get_config() */
- _MALI_UK_TRANSFER_SW_COUNTERS,
-
-#if USING_MALI_PMM
- /** Power Management Module Functions */
- _MALI_UK_PMM_EVENT_MESSAGE = 0, /**< Raise an event message */
-#endif
+ _MALI_UK_PROFILING_REPORT_SW_COUNTERS,/**< __mali_uku_profiling_report_sw_counters() */
/** VSYNC reporting fuctions */
_MALI_UK_VSYNC_EVENT_REPORT = 0, /**< _mali_ukk_vsync_event_report() */
@@ -370,18 +358,9 @@ typedef struct
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
@@ -421,10 +400,7 @@ typedef enum
* 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.
+ * tried again.
*
* After the job has started, @c _mali_wait_for_notification() will be notified
* that the job finished or got suspended. It may get suspended due to
@@ -461,25 +437,16 @@ 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 */
+ 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 */
@@ -487,20 +454,9 @@ 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
@@ -521,6 +477,12 @@ typedef struct
/** @defgroup _mali_uk_pp U/K Fragment Processor
* @{ */
+#define _MALI_PP_MAX_SUB_JOBS 8
+
+#define _MALI_PP_MAX_FRAME_REGISTERS ((0x058/4)+1)
+
+#define _MALI_PP_MAX_WB_REGISTERS ((0x02C/4)+1)
+
/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job
* @{ */
@@ -546,10 +508,7 @@ typedef struct
* 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.
+ * tried again.
*
* After the job has started, _mali_wait_for_notification() will be notified
* when the job finished. The notification will contain a
@@ -573,43 +532,48 @@ 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 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< [in] core specific registers associated with first sub job, see ARM DDI0415A */
+ u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_FRAME registers for sub job 1-7 */
+ u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< [in] ADDR_STACK registers for sub job 1-7 */
+ u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS];
+ u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS];
+ u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS];
+ u32 num_cores; /**< [in] Number of cores to set up (valid range: 1-4) */
u32 perf_counter_flag; /**< [in] bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */
u32 perf_counter_src0; /**< [in] source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */
u32 perf_counter_src1; /**< [in] source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */
- u32 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 */
+ u32 frame_builder_id; /**< [in] id of the originating frame builder */
+ u32 flush_id; /**< [in] flush id within the originating frame builder */
} _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 */
+ u32 user_job_ptr; /**< [out] identifier for the job in user space */
+ _mali_uk_job_status status; /**< [out] status of finished job */
+ u32 perf_counter0[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 0 (see ARM DDI0415A), one for each sub job */
+ u32 perf_counter1[_MALI_PP_MAX_SUB_JOBS]; /**< [out] value of perfomance counter 1 (see ARM DDI0415A), one for each sub job */
} _mali_uk_pp_job_finished_s;
+
+/**
+ * Flags to indicate write-back units
+ */
+typedef enum
+{
+ _MALI_UK_PP_JOB_WB0 = 1,
+ _MALI_UK_PP_JOB_WB1 = 2,
+ _MALI_UK_PP_JOB_WB2 = 4,
+} _mali_uk_pp_job_wbx_flag;
+
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 fb_id; /**< [in] Frame builder ID of job to disable WB units for */
+ u32 flush_id; /**< [in] Flush ID of job to disable WB units for */
+ _mali_uk_pp_job_wbx_flag wbx; /**< [in] write-back units to disable */
+} _mali_uk_pp_disable_wb_s;
+
+
/** @} */ /* end group _mali_uk_pp */
@@ -635,6 +599,7 @@ typedef enum
_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20,
_MALI_NOTIFICATION_APPLICATION_QUIT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40,
+ _MALI_NOTIFICATION_SETTINGS_CHANGED = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x80,
/** Fragment Processor notifications */
@@ -644,6 +609,7 @@ typedef enum
_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 */
@@ -653,6 +619,51 @@ typedef enum
#define _MALI_NOTIFICATION_ID_SHIFT 0
+/** @brief Enumeration of possible settings which match mali_setting_t in user space
+ *
+ *
+ */
+typedef enum
+{
+ _MALI_UK_USER_SETTING_SW_EVENTS_ENABLE = 0,
+ _MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED,
+ _MALI_UK_USER_SETTING_DEPTHBUFFER_CAPTURE_ENABLED,
+ _MALI_UK_USER_SETTING_STENCILBUFFER_CAPTURE_ENABLED,
+ _MALI_UK_USER_SETTING_PER_TILE_COUNTERS_CAPTURE_ENABLED,
+ _MALI_UK_USER_SETTING_BUFFER_CAPTURE_COMPOSITOR,
+ _MALI_UK_USER_SETTING_BUFFER_CAPTURE_WINDOW,
+ _MALI_UK_USER_SETTING_BUFFER_CAPTURE_OTHER,
+ _MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES,
+ _MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR,
+ _MALI_UK_USER_SETTING_SW_COUNTER_ENABLED,
+ _MALI_UK_USER_SETTING_MAX,
+} _mali_uk_user_setting_t;
+
+/* See mali_user_settings_db.c */
+extern const char *_mali_uk_user_setting_descriptions[];
+#define _MALI_UK_USER_SETTING_DESCRIPTIONS \
+{ \
+ "sw_events_enable", \
+ "colorbuffer_capture_enable", \
+ "depthbuffer_capture_enable", \
+ "stencilbuffer_capture_enable", \
+ "per_tile_counters_enable", \
+ "buffer_capture_compositor", \
+ "buffer_capture_window", \
+ "buffer_capture_other", \
+ "buffer_capture_n_frames", \
+ "buffer_capture_resize_factor", \
+ "sw_counters_enable", \
+};
+
+/** @brief struct to hold the value to a particular setting as seen in the kernel space
+ */
+typedef struct
+{
+ _mali_uk_user_setting_t setting;
+ u32 value;
+} _mali_uk_settings_changed_s;
+
/** @brief Arguments for _mali_ukk_wait_for_notification()
*
* On successful return from _mali_ukk_wait_for_notification(), the members of
@@ -698,14 +709,15 @@ typedef enum
*/
typedef struct
{
- void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ 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;
+ union
+ {
+ _mali_uk_gp_job_suspended_s gp_job_suspended;/**< [out] Notification data for _MALI_NOTIFICATION_GP_STALLED notification type */
+ _mali_uk_gp_job_finished_s gp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_GP_FINISHED notification type */
+ _mali_uk_pp_job_finished_s pp_job_finished; /**< [out] Notification data for _MALI_NOTIFICATION_PP_FINISHED notification type */
+ _mali_uk_settings_changed_s setting_changed;/**< [out] Notification data for _MALI_NOTIFICAATION_SETTINGS_CHANGED notification type */
+ } data;
} _mali_uk_wait_for_notification_s;
/** @brief Arguments for _mali_ukk_post_notification()
@@ -718,6 +730,7 @@ 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
@@ -748,7 +761,7 @@ typedef struct
* 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_API_VERSION 14
#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION)
/**
@@ -780,6 +793,31 @@ typedef struct
} _mali_uk_get_api_version_s;
/** @} */ /* end group _mali_uk_getapiversion_s */
+/** @defgroup _mali_uk_get_user_settings_s Get user space settings */
+
+/** @brief struct to keep the matching values of the user space settings within certain context
+ *
+ * Each member of the settings array corresponds to a matching setting in the user space and its value is the value
+ * of that particular setting.
+ *
+ * All settings are given reference to the context pointed to by the ctx pointer.
+ *
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 settings[_MALI_UK_USER_SETTING_MAX]; /**< [out] The values for all settings */
+} _mali_uk_get_user_settings_s;
+
+/** @brief struct to hold the value of a particular setting from the user space within a given context
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ _mali_uk_user_setting_t setting; /**< [in] setting to get */
+ u32 value; /**< [out] value of setting */
+} _mali_uk_get_user_setting_s;
+
/** @} */ /* end group _mali_uk_core */
@@ -800,47 +838,6 @@ 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
{
@@ -959,12 +956,6 @@ typedef struct
_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 */
@@ -997,12 +988,6 @@ typedef struct
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;
@@ -1031,24 +1016,9 @@ typedef struct
typedef struct
{
- void *ctx;
-
- u32 id;
- s64 value;
-} _mali_uk_sw_counters_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 */
@@ -1111,35 +1081,6 @@ typedef struct
} _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
* @{ */
@@ -1165,6 +1106,22 @@ typedef struct
/** @} */ /* end group _mali_uk_vsync */
+/** @defgroup _mali_uk_sw_counters_report U/K Software Counter Reporting
+ * @{ */
+
+/** @brief Software counter values
+ *
+ * Values recorded for each of the software counters during a single renderpass.
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32* counters; /**< [in] The array of counter values */
+ u32 num_counters; /**< [in] The number of elements in counters array */
+} _mali_uk_sw_counters_report_s;
+
+/** @} */ /* end group _mali_uk_sw_counters_report */
+
/** @} */ /* end group u_k_api */
/** @} */ /* end group uddapi */
@@ -1173,4 +1130,4 @@ typedef struct
}
#endif
-#endif /* __MALI_UK_TYPES_H__ */
+#endif /* __MALI_UTGARD_UK_TYPES_H__ */
diff --git a/drivers/media/video/samsung/mali/linux/mali_device_pause_resume.c b/drivers/media/video/samsung/mali/linux/mali_device_pause_resume.c
deleted file mode 100644
index 04f57d9..0000000
--- a/drivers/media/video/samsung/mali/linux/mali_device_pause_resume.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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_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/media/video/samsung/mali/linux/mali_kernel_ioctl.h b/drivers/media/video/samsung/mali/linux/mali_kernel_ioctl.h
index 7e3a216..6fc59a7 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_ioctl.h
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_ioctl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -44,8 +44,10 @@ extern "C"
#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_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *)
+#define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *)
+#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *)
+#define MALI_IOC_MEM_FREE_BIG_BLOCK _IOW (MALI_IOC_MEMORY_BASE, _MALI_UK_FREE_BIG_BLOCK, void *)
#define MALI_IOC_MEM_INIT _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_INIT_MEM, _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 *)
@@ -57,9 +59,7 @@ extern "C"
#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 *)
@@ -68,8 +68,7 @@ extern "C"
#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_TRANSFER_SW_COUNTERS _IOW (MALI_IOC_PROFILING_BASE, _MALI_UK_TRANSFER_SW_COUNTERS, _mali_uk_sw_counters_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_PROFILING_GET_CONFIG _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_CONFIG, _mali_uk_get_user_settings_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
diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c
index 05762ca..3de368e 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+/**
+ * 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.
@@ -15,31 +15,31 @@
#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 <linux/mm.h> /* memory mananger definitions */
+#include <linux/mali/mali_utgard_ioctl.h>
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_kernel_core.h"
-
#include "mali_osk.h"
#include "mali_kernel_linux.h"
#include "mali_ukk.h"
-#include "mali_kernel_ioctl.h"
#include "mali_ukk_wrappers.h"
#include "mali_kernel_pm.h"
-#include "mali_linux_pm.h"
-
#include "mali_kernel_sysfs.h"
-
-/* */
+#include "mali_platform.h"
#include "mali_kernel_license.h"
-#include "mali_platform.h"
+/* Streamline support for the Mali driver */
+#if defined(CONFIG_TRACEPOINTS) && MALI_TIMELINE_PROFILING_ENABLED
+/* Ask Linux to create the tracepoints */
+#define CREATE_TRACE_POINTS
+#include "mali_linux_trace.h"
+#endif /* CONFIG_TRACEPOINTS */
+
+static _mali_osk_errcode_t initialize_kernel_device(void);
+static int initialize_sysfs(void);
+static void terminate_kernel_device(void);
+
/* from the __malidrv_build_info.c file that is generated during build */
extern const char *__malidrv_build_info(void);
@@ -58,23 +58,15 @@ int mali_major = 0;
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;
@@ -82,6 +74,10 @@ 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
+/* Export symbols from common code: mali_user_settings.c */
+#include "mali_user_settings_db.h"
+EXPORT_SYMBOL(mali_set_user_setting);
+EXPORT_SYMBOL(mali_get_user_setting);
#if MALI_DVFS_ENABLED
extern int mali_dvfs_control;
module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */
@@ -154,7 +150,6 @@ MODULE_PARM_DESC(step3_vol, "Mali Current step3_vol");
#endif
#endif
#endif
-#endif
extern int mali_gpu_clk;
module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */
@@ -167,7 +162,8 @@ MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage");
extern int gpu_power_state;
module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */
MODULE_PARM_DESC(gpu_power_state, "Mali Power State");
-extern _mali_device_power_states mali_dvfs_device_state;
+#endif
+
static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */
@@ -202,53 +198,74 @@ struct file_operations mali_fops =
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;
- }
+ int ret = 0;
- /* print build options */
- MALI_DEBUG_PRINT(2, ("%s\n", __malidrv_build_info()));
+ 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, ("Driver revision: %s\n", SVN_REV_STRING));
- return 0;
+ ret = _mali_dev_platform_register();
+ if (0 != ret) goto platform_register_failed;
+ ret = map_errcode(initialize_kernel_device());
+ if (0 != ret) goto initialize_kernel_device_failed;
+
+ ret = map_errcode(mali_platform_init());
+ if (0 != ret) goto platform_init_failed;
+
+ mali_osk_low_level_mem_init();
+
+ ret = map_errcode(mali_initialize_subsystems());
+ if (0 != ret) goto initialize_subsystems_failed;
+
+ ret = initialize_sysfs();
+ if (0 != ret) goto initialize_sysfs_failed;
+
+ MALI_PRINT(("Mali device driver loaded\n"));
+
+ return 0; /* Success */
+
+ /* Error handling */
+initialize_sysfs_failed:
+ mali_terminate_subsystems();
+initialize_subsystems_failed:
+ mali_osk_low_level_mem_term();
+ mali_platform_deinit();
+platform_init_failed:
+ terminate_kernel_device();
+initialize_kernel_device_failed:
+ _mali_dev_platform_unregister();
+platform_register_failed:
+ return ret;
}
void mali_driver_exit(void)
{
- mali_kernel_destructor();
+ MALI_DEBUG_PRINT(2, ("\n"));
+ MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION));
-#if USING_MALI_PMM
-#if MALI_LICENSE_IS_GPL
-#ifdef CONFIG_PM
+ /* No need to terminate sysfs, this will be done automatically along with device termination */
+
+ mali_terminate_subsystems();
+
+ mali_osk_low_level_mem_term();
+
+ mali_platform_deinit();
+
+ terminate_kernel_device();
_mali_dev_platform_unregister();
+
+#if MALI_LICENSE_IS_GPL
+ /* @@@@ clean up the work queues! This should not be terminated here, since it isn't inited in the function above! */
+ flush_workqueue(mali_wq);
+ destroy_workqueue(mali_wq);
+ mali_wq = NULL;
#endif
-#endif
-#endif
+
+ MALI_PRINT(("Mali device driver unloaded\n"));
}
-/* called from _mali_osk_init */
-int initialize_kernel_device(void)
+static int initialize_kernel_device(void)
{
int err;
dev_t dev = 0;
@@ -284,28 +301,25 @@ int initialize_kernel_device(void)
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)
+static int initialize_sysfs(void)
{
dev_t dev = MKDEV(mali_major, 0);
-
+ return mali_sysfs_register(&device, dev, mali_dev_name);
+}
+
+static void terminate_kernel_device(void)
+{
+ dev_t dev = MKDEV(mali_major, 0);
+
mali_sysfs_unregister(&device, dev, mali_dev_name);
/* unregister char device */
@@ -421,12 +435,6 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return -ENOTTY;
}
- if (_MALI_DEVICE_SHUTDOWN == mali_dvfs_device_state)
- {
- MALI_DEBUG_PRINT(7, ("system is shutdown \n"));
- return 0;
- }
-
switch(cmd)
{
case MALI_IOC_GET_SYSTEM_INFO_SIZE:
@@ -449,6 +457,10 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
err = post_notification_wrapper(session_data, (_mali_uk_post_notification_s __user *)arg);
break;
+ case MALI_IOC_GET_USER_SETTINGS:
+ err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
+ break;
+
#if MALI_TIMELINE_PROFILING_ENABLED
case MALI_IOC_PROFILING_START:
err = profiling_start_wrapper(session_data, (_mali_uk_profiling_start_s __user *)arg);
@@ -471,8 +483,26 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
break;
case MALI_IOC_PROFILING_GET_CONFIG:
- err = profiling_get_config_wrapper(session_data, (_mali_uk_profiling_get_config_s __user *)arg);
+ /* Deprecated: still compatible with get_user_settings */
+ err = get_user_settings_wrapper(session_data, (_mali_uk_get_user_settings_s __user *)arg);
+ break;
+
+ case MALI_IOC_PROFILING_REPORT_SW_COUNTERS:
+ err = profiling_report_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_report_s __user *)arg);
+ break;
+#else
+
+ case MALI_IOC_PROFILING_START: /* FALL-THROUGH */
+ case MALI_IOC_PROFILING_ADD_EVENT: /* FALL-THROUGH */
+ case MALI_IOC_PROFILING_STOP: /* FALL-THROUGH */
+ case MALI_IOC_PROFILING_GET_EVENT: /* FALL-THROUGH */
+ case MALI_IOC_PROFILING_CLEAR: /* FALL-THROUGH */
+ case MALI_IOC_PROFILING_GET_CONFIG: /* FALL-THROUGH */
+ case MALI_IOC_PROFILING_REPORT_SW_COUNTERS: /* FALL-THROUGH */
+ MALI_DEBUG_PRINT(2, ("Profiling not supported\n"));
+ err = -ENOTTY;
break;
+
#endif
case MALI_IOC_MEM_INIT:
@@ -499,14 +529,6 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
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:
@@ -530,10 +552,6 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
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;
@@ -542,12 +560,12 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
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);
+ case MALI_IOC_PP_DISABLE_WB:
+ err = pp_disable_wb_wrapper(session_data, (_mali_uk_pp_disable_wb_s __user *)arg);
break;
- case MALI_IOC_GP2_ABORT_JOB:
- err = gp_abort_job_wrapper(session_data, (_mali_uk_gp_abort_job_s __user *)arg);
+ case MALI_IOC_GP2_START_JOB:
+ err = gp_start_job_wrapper(session_data, (_mali_uk_gp_start_job_s __user *)arg);
break;
case MALI_IOC_GP2_NUMBER_OF_CORES_GET:
@@ -565,10 +583,11 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
case MALI_IOC_VSYNC_EVENT_REPORT:
err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg);
break;
-#if MALI_TRACEPOINTS_ENABLED
- case MALI_IOC_TRANSFER_SW_COUNTERS:
- err = transfer_sw_counters_wrapper(session_data, (_mali_uk_sw_counters_s __user *)arg);
-#endif
+
+ case MALI_IOC_MEM_GET_BIG_BLOCK: /* Fallthrough */
+ case MALI_IOC_MEM_FREE_BIG_BLOCK:
+ MALI_PRINT_ERROR(("Non-MMU mode is no longer supported.\n"));
+ err = -ENOTTY;
break;
default:
@@ -586,9 +605,3 @@ module_exit(mali_driver_exit);
MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE);
MODULE_AUTHOR("ARM Ltd.");
MODULE_VERSION(SVN_REV_STRING);
-
-#if MALI_TRACEPOINTS_ENABLED
-/* Create the trace points (otherwise we just get code to call a tracepoint) */
-#define CREATE_TRACE_POINTS
-#include "mali_linux_trace.h"
-#endif
diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h
index 9c7668c..22dc9a4 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -28,8 +28,10 @@ struct mali_dev
#endif
};
-_mali_osk_errcode_t initialize_kernel_device(void);
-void terminate_kernel_device(void);
+#if MALI_LICENSE_IS_GPL
+/* Defined in mali_osk_irq.h */
+extern struct workqueue_struct * mali_wq;
+#endif
void mali_osk_low_level_mem_init(void);
void mali_osk_low_level_mem_term(void);
diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c
index f06ea4b..1d861f5 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+/**
+ * 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.
@@ -10,615 +10,211 @@
/**
* @file mali_kernel_pm.c
- * Implementation of the Linux Power Management for Mali GPU kernel driver
+ * Linux Power Management integration
*/
-#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 <plat/cpu.h>
-#include <plat/pd.h>
-#include <plat/devs.h>
-
-#include "mali_platform.h"
+#include <linux/module.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
#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"
+#include "mali_pm.h"
+#include "mali_platform.h"
-#ifdef MALI_REBOOTNOTIFIER
-_mali_osk_atomic_t mali_shutdown_state;
-#include <linux/reboot.h>
+#if ! MALI_LICENSE_IS_GPL
+#undef CONFIG_PM_RUNTIME
#endif
-#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
-
-/* License should be GPL */
-#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 */
-
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
extern void set_mali_parent_power_domain(struct platform_device* dev);
#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
+static int mali_probe(struct platform_device *pdev);
+static int mali_remove(struct platform_device *pdev);
#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);
-static void mali_pm_shutdown(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);
+static int mali_runtime_suspend(struct device *dev);
+static int mali_runtime_resume(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);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+static int mali_os_suspend(struct platform_device *pdev, pm_message_t state);
+static int mali_os_resume(struct platform_device *pdev);
#else
-static int mali_pm_os_resume(struct device *dev);
+static int mali_os_suspend(struct device *dev);
+static int mali_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 = {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+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,
-};
+ .runtime_suspend = mali_runtime_suspend,
+ .runtime_resume = mali_runtime_resume,
+ .runtime_idle = NULL,
+#else
+ .suspend = mali_os_suspend,
+ .resume = mali_os_resume,
#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,
+ .freeze = mali_os_suspend,
+ .poweroff = mali_os_suspend,
+ .thaw = mali_os_resume,
+ .restore = mali_os_resume,
+};
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+struct pm_ext_ops mali_ext_pm_operations =
+{
+ .base =
+ {
+ .freeze = mali_os_suspend,
+ .thaw = mali_os_resume,
+ .poweroff = mali_os_suspend,
+ .restore = mali_os_resume,
},
};
#endif
-static struct platform_driver mali_plat_driver = {
- .probe = mali_pm_probe,
- .remove = mali_pm_remove,
- .shutdown = mali_pm_shutdown,
-#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,
+
+static struct platform_driver mali_plat_driver =
+{
+ .probe = mali_probe,
+ .remove = mali_remove,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
+ .suspend = mali_os_suspend,
+ .resume = mali_os_resume,
+ .pm = &mali_ext_pm_operations,
#endif
- .driver = {
+ .driver =
+ {
.name = "mali_dev",
.owner = THIS_MODULE,
+#if MALI_LICENSE_IS_GPL
.bus = &platform_bus_type,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(LINUX_KERNEL_MAJOR_VERSION,LINUX_KERNEL_MINOR_VERSION,LINUX_KERNEL_DEVELOPMENT_VERSION))
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
.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
+#ifdef CONFIG_PM_RUNTIME
+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
/** 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)
+struct platform_device mali_gpu_device =
{
- 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;
-}
+ .name = "mali_dev",
+ .id = 0,
+ .dev.release = _mali_release_pm
+};
-/** This function is invoked when mali device is suspended
- */
-int mali_device_suspend(unsigned int event_id, struct task_struct **pwr_mgmt_thread)
+/** This function is called when the device is probed */
+static int mali_probe(struct platform_device *pdev)
{
- 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;
+ return 0;
}
-/** This function is called when Operating system wants to power down
- * the mali GPU device.
- */
-static int mali_pm_suspend(struct device *dev)
+static int mali_remove(struct platform_device *pdev)
{
- int err = 0;
- _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
- if ((mali_device_state == _MALI_DEVICE_SUSPEND))
- {
- _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
- return err;
- }
-#if MALI_DVFS_ENABLED
- mali_utilization_suspend();
-#endif
- 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)
+#ifdef CONFIG_PM_RUNTIME
+ pm_runtime_disable(&pdev->dev);
#endif
-{
- int err = 0;
- err = mali_pm_suspend(NULL);
- return err;
+ return 0;
}
-#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;
-
+ MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n"));
+ mali_pm_os_suspend();
+ break;
case PM_POST_SUSPEND:
- err = mali_pm_resume(NULL);
- break;
+ MALI_DEBUG_PRINT(2, ("mali_pwr_suspend_notifier(PM_SUSPEND_PREPARE) called\n"));
+ mali_pm_os_resume();
+ break;
default:
- break;
+ 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);
-
-#ifdef CONFIG_REGULATOR
- mali_regulator_enable();
-#endif
-
- 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)
+static int mali_runtime_suspend(struct device *dev)
{
- MALI_DEBUG_PRINT(4, ("PMMDEBUG: Mali device Run time Resumed \n" ));
- return 0;
+ MALI_DEBUG_PRINT(3, ("mali_runtime_suspend() called\n"));
+ mali_pm_runtime_suspend();
+ return 0; /* all ok */
}
-#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)
+static int mali_runtime_resume(struct device *dev)
{
- 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);
+ MALI_DEBUG_PRINT(3, ("mali_runtime_resume() called\n"));
+ mali_pm_runtime_resume();
+ return 0; /* all ok */
}
-/** 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 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
- 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)
+static int mali_os_suspend(struct platform_device *pdev, pm_message_t state)
{
-#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;
+ MALI_DEBUG_PRINT(3, ("mali_os_suspend(old) called\n"));
+ mali_pm_os_suspend();
+ return 0; /* all ok */
}
-int mali_pd_enable(void)
+static int mali_os_resume(struct platform_device *pdev)
{
- return exynos_pd_enable(&exynos4_device_pd[PD_G3D].dev);
+ MALI_DEBUG_PRINT(3, ("mali_os_resume(old) called\n"));
+ mali_pm_os_resume();
+ return 0; /* all ok */
}
-static void mali_pm_shutdown(struct platform_device *pdev)
-{
- MALI_PRINT(("Mali shutdown!!\n"));
- mali_dvfs_device_state =_MALI_DEVICE_SHUTDOWN;
- exynos_pd_enable(&exynos4_device_pd[PD_G3D].dev);
- return;
-}
+#else
-/** This function is called when the device is probed */
-static int mali_pm_probe(struct platform_device *pdev)
+static int mali_os_suspend(struct device *dev)
{
-#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;
+ MALI_DEBUG_PRINT(3, ("mali_os_suspend(new) called\n"));
+ mali_pm_os_suspend();
+ return 0; /* all ok */
}
-#ifdef MALI_REBOOTNOTIFIER
-static int mali_reboot_notify(struct notifier_block *this,
- unsigned long code, void *unused)
+
+static int mali_os_resume(struct device *dev)
{
- _mali_osk_atomic_inc_return(&mali_shutdown_state);
- mali_dvfs_device_state = _MALI_DEVICE_SHUTDOWN;
- MALI_PRINT(("REBOOT Notifier for mali\n"));
- return NOTIFY_DONE;
+ MALI_DEBUG_PRINT(3, ("mali_os_resume(new) called\n"));
+ mali_pm_os_resume();
+ return 0; /* all ok */
}
-static struct notifier_block mali_reboot_notifier = {
- .notifier_call = mali_reboot_notify,
-};
+
#endif
/** This function is called when Mali GPU device is initialized
@@ -626,50 +222,34 @@ static struct notifier_block mali_reboot_notifier = {
int _mali_dev_platform_register(void)
{
int err;
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+
+#ifdef CONFIG_PM_RUNTIME
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 */
-
-#ifdef MALI_REBOOTNOTIFIER
- _mali_osk_atomic_init(&mali_shutdown_state, 0);
- err = register_reboot_notifier(&mali_reboot_notifier);
- if (err) {
- MALI_PRINT(("Failed to setup reboot notifier\n"));
- return err;
- }
#endif
+#if MALI_LICENSE_IS_GPL
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 */
-
-#ifdef MALI_REBOOTNOTIFIER
- unregister_reboot_notifier(&mali_reboot_notifier);
#endif
-
platform_device_unregister(&mali_gpu_device);
}
}
+#endif
+
return err;
}
@@ -677,33 +257,12 @@ int _mali_dev_platform_register(void)
*/
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 */
-
-#ifdef MALI_REBOOTNOTIFIER
- unregister_reboot_notifier(&mali_reboot_notifier);
#endif
+
+#if MALI_LICENSE_IS_GPL
platform_driver_unregister(&mali_plat_driver);
platform_device_unregister(&mali_gpu_device);
+#endif
}
-
-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/media/video/samsung/mali/linux/mali_kernel_pm.h b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h
index 1c44439..6ef7270 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_pm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -11,10 +11,7 @@
#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 */
-int mali_pd_enable(void);
#endif /* __MALI_KERNEL_PM_H__ */
diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c
index 6dcf052..64853d7 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+/**
+ * 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.
@@ -14,9 +14,14 @@
* Implementation of some sysfs data exports
*/
+#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
#include "mali_kernel_license.h"
+#include "mali_kernel_common.h"
#include "mali_kernel_linux.h"
#include "mali_ukk.h"
@@ -25,13 +30,721 @@
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <asm/uaccess.h>
-#include <linux/slab.h>
-#include "mali_kernel_subsystem.h"
+#include <linux/module.h>
#include "mali_kernel_sysfs.h"
-#include "mali_kernel_profiling.h"
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#include <linux/slab.h>
+#include "mali_osk_profiling.h"
+#endif
+#include "mali_pm.h"
+#include "mali_cluster.h"
+#include "mali_group.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_l2_cache.h"
+#include "mali_hw_core.h"
+#include "mali_kernel_core.h"
+#include "mali_user_settings_db.h"
+#include "mali_device_pause_resume.h"
+
+#define POWER_BUFFER_SIZE 3
static struct dentry *mali_debugfs_dir = NULL;
+typedef enum
+{
+ _MALI_DEVICE_SUSPEND,
+ _MALI_DEVICE_RESUME,
+ _MALI_DEVICE_DVFS_PAUSE,
+ _MALI_DEVICE_DVFS_RESUME,
+ _MALI_MAX_EVENTS
+} _mali_device_debug_power_events;
+
+static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
+ [_MALI_DEVICE_SUSPEND] = "suspend",
+ [_MALI_DEVICE_RESUME] = "resume",
+ [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
+ [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
+};
+
+static u32 virtual_power_status_register=0;
+static char pwr_buf[POWER_BUFFER_SIZE];
+
+static int open_copy_private_data(struct inode *inode, struct file *filp)
+{
+ filp->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
+{
+ char buf[64];
+ int r;
+ u32 val;
+ struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
+
+ if (0 == src_id)
+ {
+ val = mali_gp_core_get_counter_src0(gp_core);
+ }
+ else
+ {
+ val = mali_gp_core_get_counter_src1(gp_core);
+ }
+
+ if (MALI_HW_CORE_NO_COUNTER == val)
+ {
+ r = sprintf(buf, "-1\n");
+ }
+ else
+ {
+ r = sprintf(buf, "%u\n", val);
+ }
+ return simple_read_from_buffer(ubuf, cnt, gpos, buf, r);
+}
+
+static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
+{
+ struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
+ char buf[64];
+ long val;
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ {
+ return -EFAULT;
+ }
+
+ buf[cnt] = 0;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (val < 0)
+ {
+ /* any negative input will disable counter */
+ val = MALI_HW_CORE_NO_COUNTER;
+ }
+
+ if (0 == src_id)
+ {
+ if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+
+ *gpos += cnt;
+ return cnt;
+}
+
+static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
+{
+ char buf[64];
+ long val;
+ int ret;
+ u32 ci;
+ struct mali_cluster *cluster;
+
+ if (cnt >= sizeof(buf))
+ {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ {
+ return -EFAULT;
+ }
+
+ buf[cnt] = 0;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (val < 0)
+ {
+ /* any negative input will disable counter */
+ val = MALI_HW_CORE_NO_COUNTER;
+ }
+
+ ci = 0;
+ cluster = mali_cluster_get_global_cluster(ci);
+ while (NULL != cluster)
+ {
+ u32 gi = 0;
+ struct mali_group *group = mali_cluster_get_group(cluster, gi);
+ while (NULL != group)
+ {
+ struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+ if (NULL != gp_core)
+ {
+ if (0 == src_id)
+ {
+ if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ }
+
+ /* try next group */
+ gi++;
+ group = mali_cluster_get_group(cluster, gi);
+ }
+
+ /* try next cluster */
+ ci++;
+ cluster = mali_cluster_get_global_cluster(ci);
+ }
+
+ *gpos += cnt;
+ return cnt;
+}
+
+static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
+{
+ return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0);
+}
+
+static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
+{
+ return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1);
+}
+
+static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
+{
+ return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
+}
+
+static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
+{
+ return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
+}
+
+static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
+{
+ return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
+}
+
+static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
+{
+ return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
+}
+
+static const struct file_operations gp_gpx_counter_src0_fops = {
+ .owner = THIS_MODULE,
+ .open = open_copy_private_data,
+ .read = gp_gpx_counter_src0_read,
+ .write = gp_gpx_counter_src0_write,
+};
+
+static const struct file_operations gp_gpx_counter_src1_fops = {
+ .owner = THIS_MODULE,
+ .open = open_copy_private_data,
+ .read = gp_gpx_counter_src1_read,
+ .write = gp_gpx_counter_src1_write,
+};
+
+static const struct file_operations gp_all_counter_src0_fops = {
+ .owner = THIS_MODULE,
+ .write = gp_all_counter_src0_write,
+};
+
+static const struct file_operations gp_all_counter_src1_fops = {
+ .owner = THIS_MODULE,
+ .write = gp_all_counter_src1_write,
+};
+
+static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+ char buf[64];
+ int r;
+ u32 val;
+ struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
+
+ if (0 == src_id)
+ {
+ val = mali_pp_core_get_counter_src0(pp_core);
+ }
+ else
+ {
+ val = mali_pp_core_get_counter_src1(pp_core);
+ }
+
+ if (MALI_HW_CORE_NO_COUNTER == val)
+ {
+ r = sprintf(buf, "-1\n");
+ }
+ else
+ {
+ r = sprintf(buf, "%u\n", val);
+ }
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+ struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
+ char buf[64];
+ long val;
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ {
+ return -EFAULT;
+ }
+
+ buf[cnt] = 0;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (val < 0)
+ {
+ /* any negative input will disable counter */
+ val = MALI_HW_CORE_NO_COUNTER;
+ }
+
+ if (0 == src_id)
+ {
+ if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+
+ *ppos += cnt;
+ return cnt;
+}
+
+static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+ char buf[64];
+ long val;
+ int ret;
+ u32 ci;
+ struct mali_cluster *cluster;
+
+ if (cnt >= sizeof(buf))
+ {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ {
+ return -EFAULT;
+ }
+
+ buf[cnt] = 0;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (val < 0)
+ {
+ /* any negative input will disable counter */
+ val = MALI_HW_CORE_NO_COUNTER;
+ }
+
+ ci = 0;
+ cluster = mali_cluster_get_global_cluster(ci);
+ while (NULL != cluster)
+ {
+ u32 gi = 0;
+ struct mali_group *group = mali_cluster_get_group(cluster, gi);
+ while (NULL != group)
+ {
+ struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+ if (NULL != pp_core)
+ {
+ if (0 == src_id)
+ {
+ if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ }
+
+ /* try next group */
+ gi++;
+ group = mali_cluster_get_group(cluster, gi);
+ }
+
+ /* try next cluster */
+ ci++;
+ cluster = mali_cluster_get_global_cluster(ci);
+ }
+
+ *ppos += cnt;
+ return cnt;
+}
+
+static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
+}
+
+static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
+}
+
+static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
+}
+
+static const struct file_operations pp_ppx_counter_src0_fops = {
+ .owner = THIS_MODULE,
+ .open = open_copy_private_data,
+ .read = pp_ppx_counter_src0_read,
+ .write = pp_ppx_counter_src0_write,
+};
+
+static const struct file_operations pp_ppx_counter_src1_fops = {
+ .owner = THIS_MODULE,
+ .open = open_copy_private_data,
+ .read = pp_ppx_counter_src1_read,
+ .write = pp_ppx_counter_src1_write,
+};
+
+static const struct file_operations pp_all_counter_src0_fops = {
+ .owner = THIS_MODULE,
+ .write = pp_all_counter_src0_write,
+};
+
+static const struct file_operations pp_all_counter_src1_fops = {
+ .owner = THIS_MODULE,
+ .write = pp_all_counter_src1_write,
+};
+
+
+
+
+
+
+static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+ char buf[64];
+ int r;
+ u32 val;
+ struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
+
+ if (0 == src_id)
+ {
+ val = mali_l2_cache_core_get_counter_src0(l2_core);
+ }
+ else
+ {
+ val = mali_l2_cache_core_get_counter_src1(l2_core);
+ }
+
+ if (MALI_HW_CORE_NO_COUNTER == val)
+ {
+ r = sprintf(buf, "-1\n");
+ }
+ else
+ {
+ r = sprintf(buf, "%u\n", val);
+ }
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+}
+
+static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+ struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
+ char buf[64];
+ long val;
+ int ret;
+
+ if (cnt >= sizeof(buf))
+ {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ {
+ return -EFAULT;
+ }
+
+ buf[cnt] = 0;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (val < 0)
+ {
+ /* any negative input will disable counter */
+ val = MALI_HW_CORE_NO_COUNTER;
+ }
+
+ if (0 == src_id)
+ {
+ if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val))
+ {
+ return 0;
+ }
+ }
+
+ *ppos += cnt;
+ return cnt;
+}
+
+static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
+{
+ char buf[64];
+ long val;
+ int ret;
+ u32 l2_id;
+ struct mali_l2_cache_core *l2_cache;
+
+ if (cnt >= sizeof(buf))
+ {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&buf, ubuf, cnt))
+ {
+ return -EFAULT;
+ }
+
+ buf[cnt] = 0;
+
+ ret = strict_strtol(buf, 10, &val);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ if (val < 0)
+ {
+ /* any negative input will disable counter */
+ val = MALI_HW_CORE_NO_COUNTER;
+ }
+
+ l2_id = 0;
+ l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+ while (NULL != l2_cache)
+ {
+ if (0 == src_id)
+ {
+ if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val))
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val))
+ {
+ return 0;
+ }
+ }
+
+ /* try next L2 */
+ l2_id++;
+ l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+ }
+
+ *ppos += cnt;
+ return cnt;
+}
+
+static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
+}
+
+static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
+}
+
+static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
+}
+
+static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
+}
+
+static const struct file_operations l2_l2x_counter_src0_fops = {
+ .owner = THIS_MODULE,
+ .open = open_copy_private_data,
+ .read = l2_l2x_counter_src0_read,
+ .write = l2_l2x_counter_src0_write,
+};
+
+static const struct file_operations l2_l2x_counter_src1_fops = {
+ .owner = THIS_MODULE,
+ .open = open_copy_private_data,
+ .read = l2_l2x_counter_src1_read,
+ .write = l2_l2x_counter_src1_write,
+};
+
+static const struct file_operations l2_all_counter_src0_fops = {
+ .owner = THIS_MODULE,
+ .write = l2_all_counter_src0_write,
+};
+
+static const struct file_operations l2_all_counter_src1_fops = {
+ .owner = THIS_MODULE,
+ .write = l2_all_counter_src1_write,
+};
+
+static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+
+ memset(pwr_buf,0,POWER_BUFFER_SIZE);
+ virtual_power_status_register = 0;
+ if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND])))
+ {
+ mali_pm_os_suspend();
+ /* @@@@ assuming currently suspend is successful later on to tune as per previous*/
+ virtual_power_status_register =1;
+
+ }
+ else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME])))
+ {
+ mali_pm_os_resume();
+
+ /* @@@@ assuming currently resume is successful later on to tune as per previous */
+ virtual_power_status_register = 1;
+ }
+ else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])))
+ {
+ mali_bool power_on;
+ mali_dev_pause(&power_on);
+ if (!power_on)
+ {
+ virtual_power_status_register = 2;
+ mali_dev_resume();
+ }
+ else
+ {
+ /* @@@@ assuming currently resume is successful later on to tune as per previous */
+ virtual_power_status_register =1;
+ }
+ }
+ else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])))
+ {
+ mali_dev_resume();
+ /* @@@@ assuming currently resume is successful later on to tune as per previous */
+ virtual_power_status_register = 1;
+
+ }
+ *ppos += cnt;
+ sprintf(pwr_buf, "%d",virtual_power_status_register);
+ return cnt;
+}
+
+static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE);
+}
+
+static loff_t power_events_seek(struct file *file, loff_t offset, int orig)
+{
+ file->f_pos = offset;
+ return 0;
+}
+
+static const struct file_operations power_events_fops = {
+ .owner = THIS_MODULE,
+ .read = power_events_read,
+ .write = power_events_write,
+ .llseek = power_events_seek,
+};
+
+
#if MALI_STATE_TRACKING
static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
{
@@ -72,13 +785,13 @@ static const struct file_operations mali_seq_internal_state_fops = {
#endif /* MALI_STATE_TRACKING */
-#if MALI_TIMELINE_PROFILING_ENABLED
+#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_profiling_is_recording() ? 1 : 0);
+ r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0);
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
@@ -111,16 +824,16 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf
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_profiling_is_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_profiling_have_recording())
+ if (MALI_TRUE == _mali_osk_profiling_have_recording())
{
- if (_MALI_OSK_ERR_OK != _mali_profiling_clear())
+ if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear())
{
MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
return -EFAULT;
@@ -128,7 +841,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf
}
/* start recording profiling data */
- if (_MALI_OSK_ERR_OK != _mali_profiling_start(&limit))
+ if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit))
{
MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
return -EFAULT;
@@ -140,7 +853,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf
{
/* stop recording profiling data */
u32 count = 0;
- if (_MALI_OSK_ERR_OK != _mali_profiling_stop(&count))
+ if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count))
{
MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
return -EFAULT;
@@ -164,7 +877,7 @@ 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_profiling_have_recording())
+ if (MALI_TRUE != _mali_osk_profiling_have_recording())
{
return NULL;
}
@@ -184,13 +897,13 @@ 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_profiling_have_recording())
+ if (MALI_TRUE != _mali_osk_profiling_have_recording())
{
return NULL;
}
/* check if the next entry actually is avaiable */
- if (_mali_profiling_get_count() <= (u32)(*spos + 1))
+ if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1))
{
return NULL;
}
@@ -215,7 +928,7 @@ static int profiling_events_show(struct seq_file *seq_file, void *v)
index = (u32)*spos;
/* Retrieve all events */
- if (_MALI_OSK_ERR_OK == _mali_profiling_get_event(index, &timestamp, &event_id, data))
+ 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;
@@ -243,68 +956,89 @@ static const struct file_operations profiling_events_fops = {
.llseek = seq_lseek,
.release = seq_release,
};
+#endif
-static ssize_t profiling_proc_default_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
{
char buf[64];
- int r;
+ size_t r;
+ u32 mem = _mali_ukk_report_memory_usage();
- r = sprintf(buf, "%u\n", _mali_profiling_get_default_enable_state() ? 1 : 0);
+ r = snprintf(buf, 64, "%u\n", mem);
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)
+static const struct file_operations memory_usage_fops = {
+ .owner = THIS_MODULE,
+ .read = memory_used_read,
+};
+
+
+static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
{
- char buf[64];
unsigned long val;
int ret;
+ _mali_uk_user_setting_t setting;
+ char buf[32];
- if (cnt >= sizeof(buf))
- {
- return -EINVAL;
- }
-
- if (copy_from_user(&buf, ubuf, cnt))
+ cnt = min(cnt, sizeof(buf) - 1);
+ if (copy_from_user(buf, ubuf, cnt))
{
return -EFAULT;
}
-
- buf[cnt] = 0;
+ buf[cnt] = '\0';
ret = strict_strtoul(buf, 10, &val);
- if (ret < 0)
+ if (0 != ret)
{
return ret;
}
- _mali_profiling_set_default_enable_state(val != 0 ? MALI_TRUE : MALI_FALSE);
+ /* Update setting */
+ setting = (_mali_uk_user_setting_t)(filp->private_data);
+ mali_set_user_setting(setting, val);
*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)
+static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
{
char buf[64];
size_t r;
- u32 mem = _mali_ukk_report_memory_usage();
+ u32 value;
+ _mali_uk_user_setting_t setting;
- r = snprintf(buf, 64, "%u\n", mem);
+ setting = (_mali_uk_user_setting_t)(filp->private_data);
+ value = mali_get_user_setting(setting);
+
+ r = snprintf(buf, 64, "%u\n", value);
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
-static const struct file_operations memory_usage_fops = {
+static const struct file_operations user_settings_fops = {
.owner = THIS_MODULE,
- .read = memory_used_read,
+ .open = open_copy_private_data,
+ .read = user_settings_read,
+ .write = user_settings_write,
};
+static int mali_sysfs_user_settings_register(void)
+{
+ struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
+
+ if (mali_user_settings_dir != NULL)
+ {
+ int i;
+ for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++)
+ {
+ debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops);
+ }
+ }
+
+ return 0;
+}
+
int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
{
int err = 0;
@@ -334,8 +1068,151 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
if(NULL != mali_debugfs_dir)
{
/* Debugfs directory created successfully; create files now */
-#if MALI_TIMELINE_PROFILING_ENABLED
- struct dentry *mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
+ struct dentry *mali_power_dir;
+ struct dentry *mali_gp_dir;
+ struct dentry *mali_pp_dir;
+ struct dentry *mali_l2_dir;
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ struct dentry *mali_profiling_dir;
+#endif
+
+ mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
+ if (mali_power_dir != NULL)
+ {
+ debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops);
+ }
+
+ mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
+ if (mali_gp_dir != NULL)
+ {
+ struct dentry *mali_gp_all_dir;
+ u32 ci;
+ struct mali_cluster *cluster;
+
+ mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir);
+ if (mali_gp_all_dir != NULL)
+ {
+ debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops);
+ debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops);
+ }
+
+ ci = 0;
+ cluster = mali_cluster_get_global_cluster(ci);
+ while (NULL != cluster)
+ {
+ u32 gi = 0;
+ struct mali_group *group = mali_cluster_get_group(cluster, gi);
+ while (NULL != group)
+ {
+ struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
+ if (NULL != gp_core)
+ {
+ struct dentry *mali_gp_gpx_dir;
+ mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
+ if (NULL != mali_gp_gpx_dir)
+ {
+ debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops);
+ debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops);
+ }
+ break; /* no need to look for any other GP cores */
+ }
+
+ /* try next group */
+ gi++;
+ group = mali_cluster_get_group(cluster, gi);
+ }
+
+ /* try next cluster */
+ ci++;
+ cluster = mali_cluster_get_global_cluster(ci);
+ }
+ }
+
+ mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
+ if (mali_pp_dir != NULL)
+ {
+ struct dentry *mali_pp_all_dir;
+ u32 ci;
+ struct mali_cluster *cluster;
+
+ mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir);
+ if (mali_pp_all_dir != NULL)
+ {
+ debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops);
+ debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops);
+ }
+
+ ci = 0;
+ cluster = mali_cluster_get_global_cluster(ci);
+ while (NULL != cluster)
+ {
+ u32 gi = 0;
+ struct mali_group *group = mali_cluster_get_group(cluster, gi);
+ while (NULL != group)
+ {
+ struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
+ if (NULL != pp_core)
+ {
+ char buf[16];
+ struct dentry *mali_pp_ppx_dir;
+ _mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
+ mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
+ if (NULL != mali_pp_ppx_dir)
+ {
+ debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops);
+ debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops);
+ }
+ }
+
+ /* try next group */
+ gi++;
+ group = mali_cluster_get_group(cluster, gi);
+ }
+
+ /* try next cluster */
+ ci++;
+ cluster = mali_cluster_get_global_cluster(ci);
+ }
+ }
+
+ mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
+ if (mali_l2_dir != NULL)
+ {
+ struct dentry *mali_l2_all_dir;
+ u32 l2_id;
+ struct mali_l2_cache_core *l2_cache;
+
+ mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
+ if (mali_l2_all_dir != NULL)
+ {
+ debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
+ debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
+ }
+
+ l2_id = 0;
+ l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+ while (NULL != l2_cache)
+ {
+ char buf[16];
+ struct dentry *mali_l2_l2x_dir;
+ _mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
+ mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
+ if (NULL != mali_l2_l2x_dir)
+ {
+ debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
+ debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
+ }
+
+ /* try next L2 */
+ l2_id++;
+ l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
+ }
+ }
+
+ debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
+
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ 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);
@@ -344,7 +1221,7 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
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("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
}
}
debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
@@ -356,7 +1233,11 @@ int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev
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);
+ if (mali_sysfs_user_settings_register())
+ {
+ /* Failed to create the debugfs entries for the user settings DB. */
+ MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
+ }
}
}
@@ -385,7 +1266,7 @@ int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_d
#else
-/* Dummy implementations for when the sysfs API isn't available. */
+/* Dummy implementations for non-GPL */
int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
{
diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h
index f68b4e1..d79a886 100644
--- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h
+++ b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 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.
diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm.h
index a8c0c52..10f633e 100644
--- a/drivers/media/video/samsung/mali/linux/mali_linux_pm.h
+++ b/drivers/media/video/samsung/mali/linux/mali_linux_pm.h
@@ -1,5 +1,6 @@
+
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -11,8 +12,6 @@
#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
@@ -20,7 +19,6 @@ typedef enum
_MALI_DEVICE_SUSPEND, /* Suspend */
_MALI_DEVICE_RESUME, /* Resume */
_MALI_DEVICE_MAX_POWER_STATES, /* Maximum power states */
- _MALI_DEVICE_SHUTDOWN, /* Power off states*/
} _mali_device_power_states;
/* Number of DVFS events */
@@ -49,5 +47,4 @@ 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/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h b/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h
index 7b1bff9..7d811bd 100644
--- a/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h
+++ b/drivers/media/video/samsung/mali/linux/mali_linux_pm_testsuite.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -10,9 +10,7 @@
#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
+#if MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM)
typedef enum
{
@@ -29,9 +27,6 @@ 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__ */
-
+#endif /* MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) */
+#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */
diff --git a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h b/drivers/media/video/samsung/mali/linux/mali_linux_trace.h
index 3ce1e50..09afcb3 100644
--- a/drivers/media/video/samsung/mali/linux/mali_linux_trace.h
+++ b/drivers/media/video/samsung/mali/linux/mali_linux_trace.h
@@ -1,93 +1,125 @@
-#if !defined(_TRACE_MALI_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_MALI_H
+/*
+ * 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.
+ */
+
+#if !defined (MALI_LINUX_TRACE_H) || defined (TRACE_HEADER_MULTI_READ)
+#define MALI_LINUX_TRACE_H
+#include <linux/types.h>
#include <linux/stringify.h>
#include <linux/tracepoint.h>
-#undef TRACE_SYSTEM
+#undef TRACE_SYSTEM
#define TRACE_SYSTEM mali
-#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
+#define TRACE_SYSTEM_STRING __stringfy(TRACE_SYSTEM)
+
+#define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE mali_linux_trace
/**
- * mali_timeline_event - called from the central collection point (_mali_profiling_add_event)
- * @event_id: ORed together bitfields representing a type of event
- * In the future we might add
- * @timestamp
- * @data[5] - this currently includes thread and process id's - we should have EGLConfig or similar too
+ * 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.
*
- * Just make a record of the event_id, we'll decode it elsewhere
+ * @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),
+ 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),
+ TP_ARGS(event_id, d0, d1, d2, d3, d4),
- TP_STRUCT__entry(
- __field( int, event_id )
- ),
+ 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;
- ),
+ 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)
+ TP_printk("event=%d", __entry->event_id)
);
/**
- * mali_hw_counter - called from the ????
- * @event_id: event being counted
- * In the future we might add
- * @timestamp ??
+ * 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.
*
- * Just make a record of the event_id and value
+ * @param counter_id The counter ID.
+ * @param value The value of the counter.
*/
-TRACE_EVENT(mali_hw_counter,
+TRACE_EVENT(mali_hw_counter,
- TP_PROTO(unsigned int event_id, unsigned int value),
+ TP_PROTO(unsigned int counter_id, unsigned int value),
- TP_ARGS(event_id, value),
+ TP_ARGS(counter_id, value),
- TP_STRUCT__entry(
- __field( int, event_id )
- __field( int, value )
- ),
+ TP_STRUCT__entry(
+ __field(unsigned int, counter_id)
+ __field(unsigned int, value)
+ ),
- TP_fast_assign(
- __entry->event_id = event_id;
- ),
+ TP_fast_assign(
+ __entry->counter_id = counter_id;
+ ),
- TP_printk("event %d = %d", __entry->event_id, __entry->value)
+ TP_printk("event %d = %d", __entry->counter_id, __entry->value)
);
/**
- * mali_sw_counter
- * @event_id: counter id
+ * Define a tracepoint used to send a bundle of software counters.
+ *
+ * @param counters The bundle of counters.
*/
-TRACE_EVENT(mali_sw_counter,
+TRACE_EVENT(mali_sw_counters,
- TP_PROTO(unsigned int event_id, signed long long value),
+ TP_PROTO(pid_t pid, pid_t tid, void * surface_id, unsigned int * counters),
- TP_ARGS(event_id, value),
+ TP_ARGS(pid, tid, surface_id, counters),
TP_STRUCT__entry(
- __field( int, event_id )
- __field( long long, value )
+ __field(pid_t, pid)
+ __field(pid_t, tid)
+ __field(void *, surface_id)
+ __field(unsigned int *, counters)
),
TP_fast_assign(
- __entry->event_id = event_id;
+ __entry->pid = pid;
+ __entry->tid = tid;
+ __entry->surface_id = surface_id;
+ __entry->counters = counters;
),
- TP_printk("event %d = %lld", __entry->event_id, __entry->value)
+ TP_printk("counters were %s", __entry->counters == NULL? "NULL" : "not NULL")
);
-#endif /* _TRACE_MALI_H */
-
-#undef TRACE_INCLUDE_PATH
-#undef linux
-#define TRACE_INCLUDE_PATH .
+#endif /* MALI_LINUX_TRACE_H */
-/* This part must be outside protection */
+/* This part must exist outside the header guard. */
#include <trace/define_trace.h>
+
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_indir_mmap.h b/drivers/media/video/samsung/mali/linux/mali_osk_indir_mmap.h
index 41cb462..f87739b 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_indir_mmap.h
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_indir_mmap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c b/drivers/media/video/samsung/mali/linux/mali_osk_irq.c
index c597b9e..ddfe564 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_irq.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -15,11 +15,12 @@
#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
@@ -31,7 +32,10 @@ typedef struct _mali_osk_irq_t_struct
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;
-static struct workqueue_struct *mali_irq_wq=NULL;
+#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 *);
@@ -58,6 +62,23 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
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"));
+ kfree(irq_object);
+ 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 *)) */
@@ -107,14 +128,14 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
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 (irqnum != _MALI_OSK_IRQ_NUMBER_FAKE && irqnum != _MALI_OSK_IRQ_NUMBER_PMM)
{
if (-1 == irqnum)
{
@@ -131,10 +152,12 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
}
}
- if (mali_irq_wq == NULL)
+#if MALI_LICENSE_IS_GPL
+ if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum )
{
- mali_irq_wq = create_singlethread_workqueue("mali-pmm-wq");
+ pmm_wq = create_singlethread_workqueue("mali-pmm-wq");
}
+#endif
return irq_object;
}
@@ -142,29 +165,54 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl
void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq )
{
mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;
- queue_work_on(0, mali_irq_wq,&irq_object->work_queue_irq_handle);
+#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 )
{
- flush_workqueue(mali_irq_wq );
+#if MALI_LICENSE_IS_GPL
+ if (NULL != irq)
+ {
+ 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);
+ }
+ }
+ 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_irq_wq != NULL)
- {
- flush_workqueue(mali_irq_wq);
- destroy_workqueue(mali_irq_wq);
- mali_irq_wq = NULL;
- }
-
- if (!mali_benchmark)
+#if MALI_LICENSE_IS_GPL
+ if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM )
{
- free_irq(irq_object->irqnum, irq_object);
+ flush_workqueue(pmm_wq);
+ destroy_workqueue(pmm_wq);
}
+#endif
+ free_irq(irq_object->irqnum, irq_object);
kfree(irq_object);
flush_scheduled_work();
}
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c
index aad6fc6..0297c77 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -51,7 +51,7 @@ typedef enum
struct _mali_osk_lock_t_struct
{
_mali_osk_internal_locktype type;
- unsigned long flags;
+ unsigned long flags;
union
{
spinlock_t spinlock;
@@ -61,6 +61,15 @@ struct _mali_osk_lock_t_struct
MALI_DEBUG_CODE(
/** original flags for debug checking */
_mali_osk_lock_flags_t orig_flags;
+
+ /* id of the thread currently holding this lock, 0 if no
+ * threads hold it. */
+ u32 owner;
+ /* number of owners this lock currently has (can be > 1 if
+ * taken in R/O mode. */
+ u32 nOwners;
+ /* what mode the lock was taken in */
+ _mali_osk_lock_mode_t mode;
); /* MALI_DEBUG_CODE */
};
@@ -71,11 +80,11 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial
/* 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 )) );
+ | _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));
@@ -126,14 +135,35 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial
sema_init( &lock->obj.sema, 1 );
}
- MALI_DEBUG_CODE(
- /* Debug tracking of flags */
- lock->orig_flags = flags;
- ); /* MALI_DEBUG_CODE */
+#ifdef DEBUG
+ /* Debug tracking of flags */
+ lock->orig_flags = flags;
+
+ /* Debug tracking of lock owner */
+ lock->owner = 0;
+ lock->nOwners = 0;
+#endif /* DEBUG */
return lock;
}
+#ifdef DEBUG
+u32 _mali_osk_lock_get_owner( _mali_osk_lock_t *lock )
+{
+ return lock->owner;
+}
+
+u32 _mali_osk_lock_get_number_owners( _mali_osk_lock_t *lock )
+{
+ return lock->nOwners;
+}
+
+u32 _mali_osk_lock_get_mode( _mali_osk_lock_t *lock )
+{
+ return lock->mode;
+}
+#endif /* DEBUG */
+
_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;
@@ -162,6 +192,7 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_
case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX:
if ( down_interruptible(&lock->obj.sema) )
{
+ MALI_PRINT_ERROR(("Can not lock mutex\n"));
err = _MALI_OSK_ERR_RESTARTSYSCALL;
}
break;
@@ -188,6 +219,31 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_
break;
}
+#ifdef DEBUG
+ /* This thread is now the owner of this lock */
+ if (_MALI_OSK_ERR_OK == err)
+ {
+ if (mode == _MALI_OSK_LOCKMODE_RW)
+ {
+ /*MALI_DEBUG_ASSERT(0 == lock->owner);*/
+ if (0 != lock->owner)
+ {
+ printk(KERN_ERR "%d: ERROR: Lock %p already has owner %d\n", _mali_osk_get_tid(), lock, lock->owner);
+ dump_stack();
+ }
+ lock->owner = _mali_osk_get_tid();
+ lock->mode = mode;
+ ++lock->nOwners;
+ }
+ else /* mode == _MALI_OSK_LOCKMODE_RO */
+ {
+ lock->owner |= _mali_osk_get_tid();
+ lock->mode = mode;
+ ++lock->nOwners;
+ }
+ }
+#endif
+
return err;
}
@@ -205,6 +261,37 @@ void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode )
MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode
|| (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) );
+#ifdef DEBUG
+ /* make sure the thread releasing the lock actually was the owner */
+ if (mode == _MALI_OSK_LOCKMODE_RW)
+ {
+ /*MALI_DEBUG_ASSERT(_mali_osk_get_tid() == lock->owner);*/
+ if (_mali_osk_get_tid() != lock->owner)
+ {
+ printk(KERN_ERR "%d: ERROR: Lock %p owner was %d\n", _mali_osk_get_tid(), lock, lock->owner);
+ dump_stack();
+ }
+ /* This lock now has no owner */
+ lock->owner = 0;
+ --lock->nOwners;
+ }
+ else /* mode == _MALI_OSK_LOCKMODE_RO */
+ {
+ if ((_mali_osk_get_tid() & lock->owner) != _mali_osk_get_tid())
+ {
+ printk(KERN_ERR "%d: ERROR: Not an owner of %p lock.\n", _mali_osk_get_tid(), lock);
+ dump_stack();
+ }
+
+ /* if this is the last thread holding this lock in R/O mode, set owner
+ * back to 0 */
+ if (0 == --lock->nOwners)
+ {
+ lock->owner = 0;
+ }
+ }
+#endif /* DEBUG */
+
switch ( lock->type )
{
case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN:
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c b/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c
index c0aecb8..5767912 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_low_level_mem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -76,12 +76,7 @@ static void _allocation_list_item_release(AllocationList * item);
/* Variable declarations */
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36)
-spinlock_t allocation_list_spinlock = SPIN_LOCK_UNLOCKED;
-#else
-DEFINE_SPINLOCK(allocation_list_spinlock);
-#endif
-
+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
@@ -124,9 +119,9 @@ 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;
@@ -145,7 +140,7 @@ static void _kernel_page_release(u32 physical_address)
#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 );
@@ -155,19 +150,19 @@ 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)
{
@@ -197,7 +192,7 @@ static void _allocation_list_item_release(AllocationList * item)
return;
}
spin_unlock_irqrestore(&allocation_list_spinlock,flags);
-
+
_kernel_page_release(item->physaddr);
_mali_osk_free( item );
}
@@ -244,7 +239,6 @@ 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;
- MappingInfo *mappingInfo;
MALI_DEBUG_PRINT(3, ("Close called on vma %p\n", vma));
vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data;
@@ -254,11 +248,6 @@ static void mali_kernel_memory_vma_close(struct vm_area_struct * vma)
vma_usage_tracker->references--;
- descriptor = (mali_memory_allocation *)vma_usage_tracker->cookie;
-
- mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info;
- mappingInfo->vma = vma;
-
if (0 != vma_usage_tracker->references)
{
MALI_DEBUG_PRINT(3, ("Ignoring this close, %d references still exists\n", vma_usage_tracker->references));
@@ -268,6 +257,8 @@ static void mali_kernel_memory_vma_close(struct vm_area_struct * vma)
/** @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;
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c
index ab571c1..3def446 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -18,27 +18,10 @@
#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 "mali_kernel_linux.h"
#include <mach/irqs.h>
#include "arch/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]);
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c b/drivers/media/video/samsung/mali/linux/mali_osk_memory.c
index 871505a..7bb470f 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_memory.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c b/drivers/media/video/samsung/mali/linux/mali_osk_misc.c
index e37e8c0..ad486db 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_misc.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_misc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -33,7 +33,7 @@ u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... )
va_list args;
va_start(args, fmt);
- res = vsnprintf(buf, (size_t)size, fmt, args);
+ res = vscnprintf(buf, (size_t)size, fmt, args);
va_end(args);
return res;
@@ -42,6 +42,7 @@ u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... )
void _mali_osk_abort(void)
{
/* make a simple fault by dereferencing a NULL pointer */
+ dump_stack();
*(int *)0 = 0;
}
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c
index eef839f..c14c0d5 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -15,8 +15,6 @@
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_pmm.h"
-#include "mali_pmm_state.h"
/* needed to detect kernel version specific code */
#include <linux/version.h>
@@ -67,12 +65,8 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
/* OPT Recycling of notification objects */
_mali_osk_notification_wrapper_t *notification;
- if (MALI_PMM_NOTIFICATION_TYPE == type) {
- if (size != sizeof(mali_pmm_message_t))
- return NULL;
- }
-
- notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, GFP_KERNEL );
+ notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size,
+ GFP_KERNEL | __GFP_HIGH | __GFP_REPEAT);
if (NULL == notification)
{
MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n"));
@@ -92,7 +86,6 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
}
/* set up the non-allocating fields */
- notification->data.magic_code = 0x31415926;
notification->data.notification_type = type;
notification->data.result_buffer_size = size;
@@ -107,8 +100,6 @@ void _mali_osk_notification_delete( _mali_osk_notification_t *object )
notification = container_of( object, _mali_osk_notification_wrapper_t, data );
- /* Remove from the list */
- list_del(&notification->list);
/* Free the container */
kfree(notification);
}
@@ -169,15 +160,7 @@ _mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification
wrapper_object = list_entry(queue->head.next, _mali_osk_notification_wrapper_t, list);
*result = &(wrapper_object->data);
list_del_init(&wrapper_object->list);
-
- if (wrapper_object->data.magic_code != 0x31415926) {
- MALI_PRINT(("SEC WARNING : list entry magic_code not match : %x\n", wrapper_object->data.magic_code));
- MALI_PRINT(("SEC WARNING : list entry notification type : %x\n", wrapper_object->data.notification_type));
- MALI_PRINT(("SEC WARNING : list entry result buffer size : %x\n", wrapper_object->data.result_buffer_size));
- MALI_PRINT(("SEC WARNING : list entry result buffer : %x\n", wrapper_object->data.result_buffer));
- } else {
- ret = _MALI_OSK_ERR_OK;
- }
+ ret = _MALI_OSK_ERR_OK;
}
up(&queue->mutex);
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c b/drivers/media/video/samsung/mali/linux/mali_osk_pm.c
index 2438cbc..20fb7b4 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_pm.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_pm.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+/**
+ * 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.
@@ -18,193 +18,67 @@
#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:
+#include "mali_kernel_license.h"
- break;
+#if ! MALI_LICENSE_IS_GPL
+#undef CONFIG_PM_RUNTIME
+#endif
- }
-#endif /* CONFIG_PM */
+extern struct platform_device mali_gpu_device;
-#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 */
-}
+#ifdef CONFIG_PM_RUNTIME
+static mali_bool have_runtime_reference = MALI_FALSE;
+#endif
-/** 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)
+void _mali_osk_pm_dev_enable(void)
{
-#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 */
+#ifdef CONFIG_PM_RUNTIME
+ pm_runtime_enable(&(mali_gpu_device.dev));
+#endif
}
-/** This function is invoked when mali device is idle.
-*/
-_mali_osk_errcode_t _mali_osk_pmm_dev_idle(void)
+/* NB: Function is not thread safe */
+_mali_osk_errcode_t _mali_osk_pm_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)
+ if (MALI_TRUE == have_runtime_reference)
{
- MALI_DEBUG_PRINT(4, ("OSPMM: Error in _mali_osk_pmm_dev_idle\n" ));
+ int err;
+ err = pm_runtime_put_sync(&(mali_gpu_device.dev));
+ if (0 > err)
+ {
+ MALI_PRINT_ERROR(("OSK PM: pm_runtime_put_sync() returned error code %d\n", err));
+ return _MALI_OSK_ERR_FAULT;
+ }
+ have_runtime_reference = MALI_FALSE;
}
-#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
-#endif /* CONFIG_PM_RUNTIME */
-#endif /* MALI_LICENSE_IS_GPL */
- return err;
+#endif
+ return _MALI_OSK_ERR_OK;
}
-/** This funtion is invoked when mali device needs to be activated.
-*/
-int _mali_osk_pmm_dev_activate(void)
+/* NB: Function is not thread safe */
+_mali_osk_errcode_t _mali_osk_pm_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)
+ if (MALI_TRUE != have_runtime_reference)
{
- pm_suspend_ignore_children(&(mali_gpu_device.dev), true);
- pm_runtime_enable(&(mali_gpu_device.dev));
+ int err;
err = pm_runtime_get_sync(&(mali_gpu_device.dev));
- is_runtime = 1;
- }
- else
- {
- err = pm_runtime_get_sync(&(mali_gpu_device.dev));
- }
- if(err < 0)
- {
- MALI_PRINT(("OSPMM: Error in _mali_osk_pmm_dev_activate, err : %d\n",err ));
- }
-#endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */
-#endif /* CONFIG_PM_RUNTIME */
-#endif /* MALI_LICENSE_IS_GPL */
-
- return err;
-}
-
-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);
+ if (0 > err)
+ {
+ MALI_PRINT_ERROR(("OSK PM: pm_runtime_get_sync() returned error code %d\n", err));
+ return _MALI_OSK_ERR_FAULT;
+ }
+ have_runtime_reference = MALI_TRUE;
}
-#endif /* CONFIG_PM */
-#endif /* MALI_LICENSE_IS_GPL */
+#endif
+ return _MALI_OSK_ERR_OK;
}
-
-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/media/video/samsung/mali/linux/mali_osk_profiling.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling.c
deleted file mode 100644
index 98d3937..0000000
--- a/drivers/media/video/samsung/mali/linux/mali_osk_profiling.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <linux/module.h>
-#include "mali_linux_trace.h"
-#include "mali_osk.h"
-
-/* The Linux trace point for hardware activity (idle vs running) */
-void _mali_osk_profiling_add_event(u32 event_id, u32 data0)
-{
- trace_mali_timeline_event(event_id);
-}
-
-/* The Linux trace point for hardware counters */
-void _mali_osk_profiling_add_counter(u32 event_id, u32 data0)
-{
- trace_mali_hw_counter(event_id, data0);
-}
-
-/* This table stores the event to be counted by each counter
- * 0xFFFFFFFF is a special value which means disable counter
- */
-//TODO at the moment this table is indexed by the magic numbers
-//listed in gator_events_mali.c. In future these numbers should
-//be shared through the mali_linux_trace.h header
-u32 counter_table[17] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
- 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
- 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
- 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
- 0xFFFFFFFF};
-
-/* Called by gator.ko to populate the table above */
-int _mali_osk_counter_event(u32 counter, u32 event)
-{
- /* Remember what has been set, and that a change has occured
- * When a job actually starts the code will program the registers
- */
- //TODO as above these magic numbers need to be moved to a header file
- if( counter >=5 && counter < 17 ) {
- counter_table[counter] = event;
-
- return 1;
- } else {
- printk("mali rjc: counter out of range (%d,%d)\n", counter, event);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(_mali_osk_counter_event);
-
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c
new file mode 100644
index 0000000..75c888d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+#include <linux/module.h>
+
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_ukk.h"
+#include "mali_uk_types.h"
+#include "mali_osk_profiling.h"
+#include "mali_linux_trace.h"
+#include "mali_gp.h"
+#include "mali_pp.h"
+#include "mali_l2_cache.h"
+#include "mali_user_settings_db.h"
+
+_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start)
+{
+ if (MALI_TRUE == auto_start)
+ {
+ mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE);
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+void _mali_osk_profiling_term(void)
+{
+ /* Nothing to do */
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit)
+{
+ /* Nothing to do */
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count)
+{
+ /* Nothing to do */
+ return _MALI_OSK_ERR_OK;
+}
+
+u32 _mali_osk_profiling_get_count(void)
+{
+ return 0;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
+{
+ /* Nothing to do */
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_osk_profiling_clear(void)
+{
+ /* Nothing to do */
+ return _MALI_OSK_ERR_OK;
+}
+
+mali_bool _mali_osk_profiling_is_recording(void)
+{
+ return MALI_FALSE;
+}
+
+mali_bool _mali_osk_profiling_have_recording(void)
+{
+ return MALI_FALSE;
+}
+
+void _mali_osk_profiling_report_sw_counters(u32 *counters)
+{
+ trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters);
+}
+
+
+_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args)
+{
+ return _mali_osk_profiling_start(&args->limit);
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args)
+{
+ /* Always add process and thread identificator in the first two data elements for events from user space */
+ _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]);
+
+ return _MALI_OSK_ERR_OK;
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args)
+{
+ return _mali_osk_profiling_stop(&args->count);
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args)
+{
+ return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data);
+}
+
+_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args)
+{
+ return _mali_osk_profiling_clear();
+}
+
+_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args)
+{
+ _mali_osk_profiling_report_sw_counters(args->counters);
+ return _MALI_OSK_ERR_OK;
+}
+
+/**
+ * Called by gator.ko to set HW counters
+ *
+ * @param counter_id The counter ID.
+ * @param event_id Event ID that the counter should count (HW counter value from TRM).
+ *
+ * @return 1 on success, 0 on failure.
+ */
+int _mali_profiling_set_event(u32 counter_id, s32 event_id)
+{
+
+ if (counter_id == COUNTER_VP_C0)
+ {
+ struct mali_gp_core* gp_core = mali_gp_get_global_gp_core();
+ if (NULL != gp_core)
+ {
+ if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id))
+ {
+ return 1;
+ }
+ }
+ }
+ else if (counter_id == COUNTER_VP_C1)
+ {
+ struct mali_gp_core* gp_core = mali_gp_get_global_gp_core();
+ if (NULL != gp_core)
+ {
+ if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id))
+ {
+ return 1;
+ }
+ }
+ }
+ else if (counter_id >= COUNTER_FP0_C0 && counter_id <= COUNTER_FP3_C1)
+ {
+ u32 core_id = (counter_id - COUNTER_FP0_C0) >> 1;
+ struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id);
+ if (NULL != pp_core)
+ {
+ u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1;
+ if (0 == counter_src)
+ {
+ if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id))
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id))
+ {
+ return 1;
+ }
+ }
+ }
+ }
+ else if (counter_id >= COUNTER_L2_C0 && counter_id <= COUNTER_L2_C1)
+ {
+ u32 core_id = (counter_id - COUNTER_L2_C0) >> 1;
+ struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id);
+ if (NULL != l2_cache_core)
+ {
+ u32 counter_src = (counter_id - COUNTER_L2_C0) & 1;
+ if (0 == counter_src)
+ {
+ if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id))
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id))
+ {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Called by gator.ko to retrieve the L2 cache counter values for the first L2 cache.
+ * 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)
+{
+ struct mali_l2_cache_core *l2_cache = mali_l2_cache_core_get_glob_l2_core(0); /* @@@@ TODO: Fix hardcoded limit of maximum 1 L2 cache */
+ if (NULL != l2_cache)
+ {
+ if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache))
+ {
+ /* It is now safe to access the L2 cache core in order to retrieve the counters */
+ mali_l2_cache_core_get_counter_values(l2_cache, src0, val0, src1, val1);
+ /* @@@@ TODO: add error checking, if needed; src == MALI_HW_CORE_NO_COUNTER if not able to get value */
+ }
+ mali_l2_cache_unlock_power_state(l2_cache);
+ }
+}
+
+/*
+ * List of possible actions to be controlled by Streamline.
+ * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting.
+ * We cannot use the enums in mali_uk_types.h because they are unknown inside gator.
+ */
+#define FBDUMP_CONTROL_ENABLE (1)
+#define FBDUMP_CONTROL_RATE (2)
+#define SW_COUNTER_ENABLE (3)
+#define FBDUMP_CONTROL_RESIZE_FACTOR (4)
+
+/**
+ * Called by gator to control the production of profiling information at runtime.
+ */
+void _mali_profiling_control(u32 action, u32 value)
+{
+ switch(action)
+ {
+ case FBDUMP_CONTROL_ENABLE:
+ mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE));
+ break;
+ case FBDUMP_CONTROL_RATE:
+ mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value);
+ break;
+ case SW_COUNTER_ENABLE:
+ mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value);
+ break;
+ case FBDUMP_CONTROL_RESIZE_FACTOR:
+ mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value);
+ break;
+ default:
+ break; /* Ignore unimplemented actions */
+ }
+}
+
+EXPORT_SYMBOL(_mali_profiling_set_event);
+EXPORT_SYMBOL(_mali_profiling_get_counters);
+EXPORT_SYMBOL(_mali_profiling_control);
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c
index ca04b5f..9a423d2 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_profiling.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,8 +13,8 @@
#include "mali_osk_mali.h"
#include "mali_ukk.h"
#include "mali_timestamp.h"
-#include "mali_kernel_profiling.h"
-#include "mali_linux_trace.h"
+#include "mali_osk_profiling.h"
+#include "mali_user_settings_db.h"
typedef struct mali_profiling_entry
{
@@ -39,16 +39,15 @@ 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_profiling_init(mali_bool auto_start)
+_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 );
+ lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING);
if (NULL == lock)
{
return _MALI_OSK_ERR_FAULT;
@@ -59,9 +58,9 @@ _mali_osk_errcode_t _mali_profiling_init(mali_bool auto_start)
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_profiling_start(&limit))
+
+ mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE);
+ if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit))
{
return _MALI_OSK_ERR_FAULT;
}
@@ -70,7 +69,7 @@ _mali_osk_errcode_t _mali_profiling_init(mali_bool auto_start)
return _MALI_OSK_ERR_OK;
}
-void _mali_profiling_term(void)
+void _mali_osk_profiling_term(void)
{
prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
@@ -93,7 +92,7 @@ void _mali_profiling_term(void)
}
}
-inline _mali_osk_errcode_t _mali_profiling_start(u32 * limit)
+inline _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit)
{
_mali_osk_errcode_t ret;
@@ -137,21 +136,10 @@ inline _mali_osk_errcode_t _mali_profiling_start(u32 * limit)
return ret;
}
-inline void _mali_profiling_add_counter(u32 event_id, u32 data0)
-{
-#if MALI_TRACEPOINTS_ENABLED
- _mali_osk_profiling_add_counter(event_id, data0);
-#endif
-}
-
-inline _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4)
+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 MALI_TRACEPOINTS_ENABLED
- _mali_osk_profiling_add_event(event_id, data0);
-#endif
-
if (prof_state != MALI_PROFILING_STATE_RUNNING || cur_index >= profile_entry_count)
{
/*
@@ -159,7 +147,7 @@ inline _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u3
* Decrement index again, and early out
*/
_mali_osk_atomic_dec(&profile_insert_index);
- return _MALI_OSK_ERR_FAULT;
+ return;
}
profile_entries[cur_index].timestamp = _mali_timestamp_get();
@@ -171,55 +159,19 @@ inline _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u3
profile_entries[cur_index].data[4] = data4;
_mali_osk_atomic_inc(&profile_entries_written);
-
- return _MALI_OSK_ERR_OK;
}
-#if MALI_TRACEPOINTS_ENABLED
-/*
- * The following code uses a bunch of magic numbers taken from the userspace
- * side of the DDK; they are re-used here verbatim. They are taken from the
- * file mali_instrumented_counter_types.h.
- */
-#define MALI_GLES_COUNTER_OFFSET 1000
-#define MALI_VG_COUNTER_OFFSET 2000
-#define MALI_EGL_COUNTER_OFFSET 3000
-#define MALI_SHARED_COUNTER_OFFSET 4000
-
-/* These offsets are derived from the gator driver; see gator_events_mali.c. */
-#define GATOR_EGL_COUNTER_OFFSET 17
-#define GATOR_GLES_COUNTER_OFFSET 18
-
-_mali_osk_errcode_t _mali_ukk_transfer_sw_counters(_mali_uk_sw_counters_s *args)
+inline void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value)
{
- /* Convert the DDK counter ID to what gator expects */
- unsigned int gator_counter_value = 0;
-
- _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
-
- if (args->id >= MALI_EGL_COUNTER_OFFSET && args->id <= MALI_SHARED_COUNTER_OFFSET)
- {
- gator_counter_value = (args->id - MALI_EGL_COUNTER_OFFSET) + GATOR_EGL_COUNTER_OFFSET;
- }
- else if (args->id >= MALI_GLES_COUNTER_OFFSET && args->id <= MALI_VG_COUNTER_OFFSET)
- {
- gator_counter_value = (args->id - MALI_GLES_COUNTER_OFFSET) + GATOR_GLES_COUNTER_OFFSET;
- }
- else
- {
- /* Pass it straight through; gator will ignore it anyway. */
- gator_counter_value = args->id;
- }
-
- trace_mali_sw_counter(gator_counter_value, args->value);
-
- _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
+ /* Not implemented */
+}
- return _MALI_OSK_ERR_OK;
+void _mali_osk_profiling_report_sw_counters(u32 *counters)
+{
+ /* Not implemented */
}
-#endif
-inline _mali_osk_errcode_t _mali_profiling_stop(u32 * count)
+inline _mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count)
{
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
@@ -245,7 +197,7 @@ inline _mali_osk_errcode_t _mali_profiling_stop(u32 * count)
return _MALI_OSK_ERR_OK;
}
-inline u32 _mali_profiling_get_count(void)
+inline u32 _mali_osk_profiling_get_count(void)
{
u32 retval = 0;
@@ -259,7 +211,7 @@ inline u32 _mali_profiling_get_count(void)
return retval;
}
-inline _mali_osk_errcode_t _mali_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
+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);
@@ -287,7 +239,7 @@ inline _mali_osk_errcode_t _mali_profiling_get_event(u32 index, u64* timestamp,
return _MALI_OSK_ERR_OK;
}
-inline _mali_osk_errcode_t _mali_profiling_clear(void)
+inline _mali_osk_errcode_t _mali_osk_profiling_clear(void)
{
_mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
@@ -311,54 +263,46 @@ inline _mali_osk_errcode_t _mali_profiling_clear(void)
return _MALI_OSK_ERR_OK;
}
-mali_bool _mali_profiling_is_recording(void)
+mali_bool _mali_osk_profiling_is_recording(void)
{
return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE;
}
-mali_bool _mali_profiling_have_recording(void)
+mali_bool _mali_osk_profiling_have_recording(void)
{
return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE;
}
-void _mali_profiling_set_default_enable_state(mali_bool enable)
-{
- mali_profiling_default_enable = enable;
-}
-
-mali_bool _mali_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_profiling_start(&args->limit);
+ 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 */
- return _mali_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]);
+ _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_profiling_stop(&args->count);
+ 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_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data);
+ 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_profiling_clear();
+ return _mali_osk_profiling_clear();
}
-_mali_osk_errcode_t _mali_ukk_profiling_get_config(_mali_uk_profiling_get_config_s *args)
+_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args)
{
- args->enable_events = mali_profiling_default_enable;
+ _mali_osk_profiling_report_sw_counters(args->counters);
return _MALI_OSK_ERR_OK;
}
+
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h
index 6aacf17..83ee906 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -22,11 +22,109 @@ extern "C"
{
#endif
-#define MALI_STATIC_INLINE static inline
+#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/media/video/samsung/mali/linux/mali_osk_timers.c b/drivers/media/video/samsung/mali/linux/mali_osk_timers.c
index 0454756..e5829a3 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_timers.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_timers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -34,7 +34,7 @@ _mali_osk_timer_t *_mali_osk_timer_init(void)
void _mali_osk_timer_add( _mali_osk_timer_t *tim, u32 ticks_to_expire )
{
- MALI_DEBUG_ASSERT_POINTER(tim);
+ MALI_DEBUG_ASSERT_POINTER(tim);
tim->timer.expires = _mali_osk_time_tickcount() + ticks_to_expire;
add_timer(&(tim->timer));
}
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c b/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c
new file mode 100644
index 0000000..ce0561d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_wait_queue.c
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file mali_osk_wait_queue.c
+ * Implemenation of the OS abstraction layer for the kernel device driver
+ */
+
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+
+struct _mali_osk_wait_queue_t_struct
+{
+ wait_queue_head_t wait_queue;
+};
+
+_mali_osk_wait_queue_t* _mali_osk_wait_queue_init( void )
+{
+ _mali_osk_wait_queue_t* ret = NULL;
+
+ ret = kmalloc(sizeof(_mali_osk_wait_queue_t), GFP_KERNEL);
+
+ if (NULL == ret)
+ {
+ return ret;
+ }
+
+ init_waitqueue_head(&ret->wait_queue);
+ MALI_DEBUG_ASSERT(!waitqueue_active(&ret->wait_queue));
+
+ return ret;
+}
+
+void _mali_osk_wait_queue_wait_event( _mali_osk_wait_queue_t *queue, mali_bool (*condition)(void) )
+{
+ MALI_DEBUG_ASSERT_POINTER( queue );
+ MALI_DEBUG_PRINT(6, ("Adding to wait queue %p\n", queue));
+ wait_event(queue->wait_queue, condition());
+}
+
+void _mali_osk_wait_queue_wake_up( _mali_osk_wait_queue_t *queue )
+{
+ MALI_DEBUG_ASSERT_POINTER( queue );
+
+ /* if queue is empty, don't attempt to wake up its elements */
+ if (!waitqueue_active(&queue->wait_queue)) return;
+
+ MALI_DEBUG_PRINT(6, ("Waking up elements in wait queue %p ....\n", queue));
+
+ wake_up_all(&queue->wait_queue);
+
+ MALI_DEBUG_PRINT(6, ("... elements in wait queue %p woken up\n", queue));
+}
+
+void _mali_osk_wait_queue_term( _mali_osk_wait_queue_t *queue )
+{
+ /* Parameter validation */
+ MALI_DEBUG_ASSERT_POINTER( queue );
+
+ /* Linux requires no explicit termination of wait queues */
+ kfree(queue);
+}
diff --git a/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c b/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.c
new file mode 100644
index 0000000..f3b0a2c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/linux/mali_pmu_power_up_down.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_pmu_power_up_down.c
+ */
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include "mali_osk.h"
+#include "mali_kernel_common.h"
+#include "mali_pmu.h"
+#include "linux/mali/mali_utgard.h"
+
+/* Mali PMU power up/down APIs */
+
+int mali_pmu_powerup(void)
+{
+ struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+
+ MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n"));
+
+ if (NULL == pmu)
+ {
+ return -ENXIO;
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_pmu_powerup_all(pmu))
+ {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(mali_pmu_powerup);
+
+int mali_pmu_powerdown(void)
+{
+ struct mali_pmu_core *pmu = mali_pmu_get_global_pmu_core();
+
+ MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n"));
+
+ if (NULL == pmu)
+ {
+ return -ENXIO;
+ }
+
+ if (_MALI_OSK_ERR_OK != mali_pmu_powerdown_all(pmu))
+ {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(mali_pmu_powerdown);
diff --git a/drivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h b/drivers/media/video/samsung/mali/linux/mali_profiling_events.h
index 014c4bb..2639a40 100644
--- a/drivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h
+++ b/drivers/media/video/samsung/mali/linux/mali_profiling_events.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,11 +8,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __ARCH_CONFIG_H__
-#define __ARCH_CONFIG_H__
+#ifndef __MALI_PROFILING_EVENTS_H__
+#define __MALI_PROFILING_EVENTS_H__
-#define ARCH_UMP_BACKEND_DEFAULT 0
-#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
-#define ARCH_UMP_MEMORY_SIZE_DEFAULT 0x04000000
+/* Simple wrapper in order to find the OS specific location of this file */
+#include <linux/mali/mali_utgard_profiling_events.h>
-#endif /* __ARCH_CONFIG_H__ */
+#endif /* __MALI_PROFILING_EVENTS_H__ */
diff --git a/drivers/media/video/samsung/mali/linux/mali_device_pause_resume.h b/drivers/media/video/samsung/mali/linux/mali_uk_types.h
index 155a3e6..b535e6c 100644
--- a/drivers/media/video/samsung/mali/linux/mali_device_pause_resume.h
+++ b/drivers/media/video/samsung/mali/linux/mali_uk_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -8,12 +8,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __MALI_DEVICE_PAUSE_RESUME_H__
-#define __MALI_DEVICE_PAUSE_RESUME_H__
+#ifndef __MALI_UK_TYPES_H__
+#define __MALI_UK_TYPES_H__
-#if USING_MALI_PMM
-int mali_dev_pause(void);
-int mali_dev_resume(void);
-#endif /* USING_MALI_PMM */
+#include "regs/mali_200_regs.h"
-#endif /* __MALI_DEVICE_PAUSE_RESUME_H__ */
+/* Simple wrapper in order to find the OS specific location of this file */
+#include "../include/linux/mali/mali_utgard_uk_types.h"
+
+#endif /* __MALI_UK_TYPES_H__ */
diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c b/drivers/media/video/samsung/mali/linux/mali_ukk_core.c
index 59eafe2..6eb2df3 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_core.c
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -14,7 +14,7 @@
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_ukk_wrappers.h"
int get_api_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_api_version_s __user *uargs)
@@ -140,3 +140,23 @@ int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_p
return 0;
}
+
+int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs)
+{
+ _mali_uk_get_user_settings_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ kargs.ctx = session_data;
+ err = _mali_ukk_get_user_settings(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ return map_errcode(err);
+ }
+
+ kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+ if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_get_user_settings_s))) return -EFAULT;
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c
index 58ff1de..7070016 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,7 +13,7 @@
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_ukk_wrappers.h"
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs)
@@ -36,6 +36,7 @@ int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_sta
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)))
{
/*
@@ -53,22 +54,6 @@ int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_sta
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;
diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c b/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c
index 0b98e41..260f257 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_mem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,7 +13,7 @@
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_ukk_wrappers.h"
int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs)
@@ -257,80 +257,3 @@ 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/media/video/samsung/mali/linux/mali_ukk_pp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c
index 31e2a6a..c11c61b 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,7 +13,7 @@
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_ukk_wrappers.h"
int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs)
@@ -35,36 +35,6 @@ int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_sta
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;
}
@@ -101,3 +71,18 @@ int pp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk
return 0;
}
+
+int pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs)
+{
+ _mali_uk_pp_disable_wb_s kargs;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+ MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+ if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_disable_wb_s))) return -EFAULT;
+
+ kargs.ctx = session_data;
+ _mali_ukk_pp_job_disable_wb(&kargs);
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c b/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c
index 17366be..7324d9d 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_profiling.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -9,11 +9,12 @@
*/
#include <linux/fs.h> /* file system operations */
#include <asm/uaccess.h> /* user space access */
+#include <linux/slab.h>
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_ukk_wrappers.h"
int profiling_start_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_start_s __user *uargs)
@@ -133,51 +134,49 @@ int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_pro
return 0;
}
-int profiling_get_config_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_config_s __user *uargs)
+int profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs)
{
- _mali_uk_profiling_get_config_s kargs;
+ _mali_uk_sw_counters_report_s kargs;
_mali_osk_errcode_t err;
+ u32 *counter_buffer;
MALI_CHECK_NON_NULL(uargs, -EINVAL);
- kargs.ctx = session_data;
- err = _mali_ukk_profiling_get_config(&kargs);
- if (_MALI_OSK_ERR_OK != err)
+ if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_sw_counters_report_s)))
{
- return map_errcode(err);
+ return -EFAULT;
}
- if (0 != put_user(kargs.enable_events, &uargs->enable_events))
- {
- return -EFAULT;
+ /* make sure that kargs.num_counters is [at least somewhat] sane */
+ if (kargs.num_counters > 10000) {
+ MALI_DEBUG_PRINT(1, ("User space attempted to allocate too many counters.\n"));
+ return -EINVAL;
}
- return 0;
-}
+ counter_buffer = (u32*)kmalloc(sizeof(u32) * kargs.num_counters, GFP_KERNEL);
+ if (NULL == counter_buffer)
+ {
+ return -ENOMEM;
+ }
-#if MALI_TRACEPOINTS_ENABLED
-int transfer_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_s __user *uargs)
-{
- _mali_uk_sw_counters_s kargs;
- _mali_osk_errcode_t err;
+ if (0 != copy_from_user(counter_buffer, kargs.counters, sizeof(u32) * kargs.num_counters))
+ {
+ kfree(counter_buffer);
+ return -EFAULT;
+ }
- MALI_CHECK_NON_NULL(uargs, -EINVAL);
-
- kargs.ctx = session_data;
+ kargs.ctx = session_data;
+ kargs.counters = counter_buffer;
- if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_sw_counters_s)))
- {
- return -EFAULT;
- }
+ err = _mali_ukk_sw_counters_report(&kargs);
- err = _mali_ukk_transfer_sw_counters(&kargs);
+ kfree(counter_buffer);
- if (_MALI_OSK_ERR_OK != err)
- {
- return map_errcode(err);
- }
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ return map_errcode(err);
+ }
- return 0;
+ return 0;
}
-#endif
diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c b/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c
index 80a6afd..f9b5a3e 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_vsync.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -13,7 +13,7 @@
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_common.h"
-#include "mali_kernel_session_manager.h"
+#include "mali_session.h"
#include "mali_ukk_wrappers.h"
diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h b/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h
index 184ce8d..b568ce7 100644
--- a/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h
+++ b/drivers/media/video/samsung/mali/linux/mali_ukk_wrappers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -28,6 +28,7 @@ int get_system_info_size_wrapper(struct mali_session_data *session_data, _mali_u
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 get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs);
int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs);
int 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);
@@ -41,14 +42,11 @@ int mem_attach_ump_wrapper(struct mali_session_data *session_data, _mali_uk_atta
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 pp_disable_wb_wrapper(struct mali_session_data *session_data, _mali_uk_pp_disable_wb_s __user *uargs);
int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs);
-int gp_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);
@@ -58,14 +56,10 @@ int profiling_add_event_wrapper(struct mali_session_data *session_data, _mali_uk
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 profiling_report_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_report_s __user *uargs);
int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs);
-#if MALI_TRACEPOINTS_ENABLED
-int transfer_sw_counters_wrapper(struct mali_session_data *session_data, _mali_uk_sw_counters_s __user *uargs);
-#endif
-
int map_errcode( _mali_osk_errcode_t err );
#ifdef __cplusplus
diff --git a/drivers/media/video/samsung/mali/platform/default/mali_platform.c b/drivers/media/video/samsung/mali/platform/default/mali_platform.c
index 44f877e..9e64ce7 100644
--- a/drivers/media/video/samsung/mali/platform/default/mali_platform.c
+++ b/drivers/media/video/samsung/mali/platform/default/mali_platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -39,3 +39,5 @@ void mali_gpu_utilization_handler(u32 utilization)
void set_mali_parent_power_domain(void* dev)
{
}
+
+
diff --git a/drivers/media/video/samsung/mali/platform/mali_platform.h b/drivers/media/video/samsung/mali/platform/mali_platform.h
index 70cfa14..6e55dee 100644
--- a/drivers/media/video/samsung/mali/platform/mali_platform.h
+++ b/drivers/media/video/samsung/mali/platform/mali_platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -21,12 +21,7 @@
#ifdef CONFIG_CPU_EXYNOS4210
#define MALI_DVFS_STEPS 2
#else
-#define MALI_DVFS_STEPS 4
-#endif
-
-#if !USING_MALI_PMM
-/* @brief System power up/down cores that can be passed into mali_platform_powerdown/up() */
-#define MALI_PLATFORM_SYSTEM 0
+#define MALI_DVFS_STEPS 5
#endif
/* @Enable or Disable Mali GPU Bottom Lock feature */
@@ -34,6 +29,9 @@
#define MALI_VOLTAGE_LOCK 1
+/* @Enable or Disable the CPU frequency lock when the GPU clock is 440 Mhz */
+#define CPUFREQ_LOCK_DURING_440 0
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -42,9 +40,9 @@ extern "C" {
*/
typedef enum mali_power_mode_tag
{
- MALI_POWER_MODE_ON,
- MALI_POWER_MODE_LIGHT_SLEEP,
- MALI_POWER_MODE_DEEP_SLEEP,
+ MALI_POWER_MODE_ON, /**< Power Mali on */
+ MALI_POWER_MODE_LIGHT_SLEEP, /**< Mali has been idle for a short time, or runtime PM suspend */
+ MALI_POWER_MODE_DEEP_SLEEP, /**< Mali has been idle for a long time, or OS suspend */
} mali_power_mode;
/** @brief Platform specific setup and initialisation of MALI
@@ -65,22 +63,8 @@ _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.
+ * Notification from the Mali device driver stating the new desired power mode.
+ * MALI_POWER_MODE_ON must be obeyed, while the other modes are optional.
* @param power_mode defines the power modes
* @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error.
*/
diff --git a/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c b/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c
new file mode 100644
index 0000000..cb95dc6
--- /dev/null
+++ b/drivers/media/video/samsung/mali/platform/mali_platform_pmu_testing/mali_platform.c
@@ -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_platform.c
+ * Platform specific Mali driver functions for a default platform
+ */
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_platform.h"
+#include "mali_pmu.h"
+#include "linux/mali/mali_utgard.h"
+
+static u32 bPowerOff = 1;
+
+_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)
+{
+ switch (power_mode)
+ {
+ case MALI_POWER_MODE_ON:
+ if (bPowerOff == 1)
+ {
+ mali_pmu_powerup();
+ bPowerOff = 0;
+ }
+ break;
+ case MALI_POWER_MODE_LIGHT_SLEEP:
+ case MALI_POWER_MODE_DEEP_SLEEP:
+
+ if (bPowerOff == 0)
+ {
+ mali_pmu_powerdown();
+ bPowerOff = 1;
+ }
+
+ break;
+ }
+ MALI_SUCCESS;
+}
+
+void mali_gpu_utilization_handler(u32 utilization)
+{
+}
+
+void set_mali_parent_power_domain(void* dev)
+{
+}
+
+
diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c
index 0fc4503..792b9a9 100644
--- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c
+++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c
index 9e6edba..f8d76dc 100644
--- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c
+++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c
@@ -1,414 +1 @@
-/*
- * 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_platform_dvfs.c
- * Platform specific Mali driver dvfs functions
- */
-
-#include "mali_kernel_common.h"
-#include "mali_osk.h"
-#include "mali_platform.h"
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/regulator/consumer.h>
-#include <linux/regulator/driver.h>
-
-#include <asm/io.h>
-
-#ifdef CONFIG_CPU_FREQ
-#include <mach/asv.h>
-#include <mach/regs-pmu.h>
-#define EXYNOS4_ASV_ENABLED
-#endif
-
-#include "mali_device_pause_resume.h"
-#include <linux/workqueue.h>
-
-#define MALI_DVFS_WATING 10 // msec
-
-static int bMaliDvfsRun=0;
-
-#if MALI_GPU_BOTTOM_LOCK
-static _mali_osk_atomic_t bottomlock_status;
-#endif
-
-typedef struct mali_dvfs_tableTag{
- unsigned int clock;
- unsigned int freq;
- unsigned int vol;
-}mali_dvfs_table;
-
-typedef struct mali_dvfs_statusTag{
- unsigned int currentStep;
- mali_dvfs_table * pCurrentDvfs;
-
-}mali_dvfs_currentstatus;
-
-typedef struct mali_dvfs_thresholdTag{
- unsigned int downthreshold;
- unsigned int upthreshold;
-}mali_dvfs_threshold_table;
-
-typedef struct mali_dvfs_staycount{
- unsigned int staycount;
-}mali_dvfs_staycount_table;
-
-mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={
- /*step 0*/{1},
- /*step 1*/{1},};
-
-/*dvfs threshold*/
-mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={
- /*step 0*/{((int)((255*0)/100)), ((int)((255*85)/100))},
- /*step 1*/{((int)((255*75)/100)), ((int)((255*100)/100))} };
-
-/*dvfs status*/
-mali_dvfs_currentstatus maliDvfsStatus;
-int mali_dvfs_control=0;
-
-/*dvfs table*/
-mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
- /*step 0*/{160 ,1000000 , 950000},
- /*step 1*/{267 ,1000000 ,1000000} };
-
-#ifdef EXYNOS4_ASV_ENABLED
-
-#define ASV_8_LEVEL 8
-#define ASV_5_LEVEL 5
-
-static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = {
- /* L3(160MHz), L2(266MHz) */
- {1000000, 1100000}, /* S */
- {1000000, 1100000}, /* A */
- { 950000, 1000000}, /* B */
- { 950000, 1000000}, /* C */
- { 950000, 950000}, /* D */
-};
-
-static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = {
- /* L3(160MHz), L2(266MHz)) */
- {1000000, 1100000}, /* SS */
- {1000000, 1100000}, /* A1 */
- {1000000, 1100000}, /* A2 */
- { 950000, 1000000}, /* B1 */
- { 950000, 1000000}, /* B2 */
- { 950000, 1000000}, /* C1 */
- { 950000, 1000000}, /* C2 */
- { 950000, 950000}, /* D1 */
-};
-#endif
-
-static u32 mali_dvfs_utilization = 255;
-
-static void mali_dvfs_work_handler(struct work_struct *w);
-
-static struct workqueue_struct *mali_dvfs_wq = 0;
-extern mali_io_address clk_register_map;
-
-#if MALI_GPU_BOTTOM_LOCK
-extern _mali_osk_lock_t *mali_dvfs_lock;
-#endif
-
-static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler);
-
-static unsigned int get_mali_dvfs_status(void)
-{
- return maliDvfsStatus.currentStep;
-}
-
-#if MALI_GPU_BOTTOM_LOCK
-#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
-int get_mali_dvfs_control_status(void)
-{
- return mali_dvfs_control;
-}
-
-mali_bool set_mali_dvfs_current_step(unsigned int step)
-{
- _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
- maliDvfsStatus.currentStep = step;
- _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
- return MALI_TRUE;
-}
-#endif
-#endif
-
-static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
-{
- u32 validatedStep=step;
-
-#ifdef CONFIG_REGULATOR
- if (mali_regulator_get_usecount()==0) {
- MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n"));
- return MALI_FALSE;
- }
-#endif
-
- if (boostup) {
-#ifdef CONFIG_REGULATOR
- /*change the voltage*/
- mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
-#endif
- /*change the clock*/
- mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
- } else {
- /*change the clock*/
- mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
-#ifdef CONFIG_REGULATOR
- /*change the voltage*/
- mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol);
-#endif
- }
-
- maliDvfsStatus.currentStep = validatedStep;
- /*for future use*/
- maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep];
-
- return MALI_TRUE;
-}
-
-static void mali_platform_wating(u32 msec)
-{
- /*sample wating
- change this in the future with proper check routine.
- */
- unsigned int read_val;
- while(1) {
- read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00);
- if ((read_val & 0x8000)==0x0000) break;
-
- _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218
- }
- /* _mali_osk_time_ubusydelay(msec*1000);*/
-}
-
-static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup )
-{
-
- MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup));
-
- if (!set_mali_dvfs_status(step, boostup)) {
- MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup));
- return MALI_FALSE;
- }
-
- /*wait until clock and voltage is stablized*/
- mali_platform_wating(MALI_DVFS_WATING); /*msec*/
-
- return MALI_TRUE;
-}
-
-static unsigned int decideNextStatus(unsigned int utilization)
-{
- unsigned int level=0; // 0:stay, 1:up
-
- if (!mali_dvfs_control) {
-#if MALI_GPU_BOTTOM_LOCK
- if (_mali_osk_atomic_read(&bottomlock_status) > 0)
- level = 1; /* or bigger */
- else if (utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold)
-#else
- if (utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold)
-#endif
- level=1;
- else if (utilization < mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold)
- level=0;
- else
- level = maliDvfsStatus.currentStep;
- } else {
- if ((mali_dvfs_control > 0) && (mali_dvfs_control < mali_dvfs[1].clock))
- level=0;
- else
- level=1;
- }
-
- return level;
-}
-
-#ifdef EXYNOS4_ASV_ENABLED
-static mali_bool mali_dvfs_table_update(void)
-{
- unsigned int exynos_result_of_asv_group;
- unsigned int target_asv;
- unsigned int i;
- exynos_result_of_asv_group = exynos_result_of_asv & 0xf;
- target_asv = exynos_result_of_asv >> 28;
- MALI_PRINT(("exynos_result_of_asv_group = 0x%x, target_asv = 0x%x\n", exynos_result_of_asv_group, target_asv));
-
- if (target_asv == 0x8) { //SUPPORT_1400MHZ
- for (i = 0; i < MALI_DVFS_STEPS; i++) {
- mali_dvfs[i].vol = asv_3d_volt_5_table[exynos_result_of_asv_group][i];
- MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol));
- }
- } else if (target_asv == 0x4){ //SUPPORT_1200MHZ
- for (i = 0; i < MALI_DVFS_STEPS; i++) {
- mali_dvfs[i].vol = asv_3d_volt_8_table[exynos_result_of_asv_group][i];
- MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol));
- }
- }
-
- return MALI_TRUE;
-
-}
-#endif
-
-static mali_bool mali_dvfs_status(u32 utilization)
-{
- unsigned int nextStatus = 0;
- unsigned int curStatus = 0;
- mali_bool boostup = MALI_FALSE;
-#ifdef EXYNOS4_ASV_ENABLED
- static mali_bool asv_applied = MALI_FALSE;
-#endif
- static int stay_count = 0; // to prevent frequent switch
-
- MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization));
-#ifdef EXYNOS4_ASV_ENABLED
- if (asv_applied == MALI_FALSE) {
- mali_dvfs_table_update();
- change_mali_dvfs_status(0,0);
- asv_applied = MALI_TRUE;
-
- return MALI_TRUE;
- }
-#endif
-
- /*decide next step*/
- curStatus = get_mali_dvfs_status();
- nextStatus = decideNextStatus(utilization);
-
- MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep));
-
- /*if next status is same with current status, don't change anything*/
- if ((curStatus!=nextStatus && stay_count==0)) {
- /*check if boost up or not*/
- if (nextStatus > maliDvfsStatus.currentStep)
- boostup = 1;
-
- /*change mali dvfs status*/
- if (!change_mali_dvfs_status(nextStatus,boostup)) {
- MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n"));
- return MALI_FALSE;
- }
- stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount;
- } else {
- if (stay_count>0)
- stay_count--;
- }
-
- return MALI_TRUE;
-}
-
-
-
-int mali_dvfs_is_running(void)
-{
- return bMaliDvfsRun;
-}
-
-
-
-void mali_dvfs_late_resume(void)
-{
- // set the init clock as low when resume
- set_mali_dvfs_status(0,0);
-}
-
-
-static void mali_dvfs_work_handler(struct work_struct *w)
-{
- bMaliDvfsRun=1;
-
- MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
-
- if (!mali_dvfs_status(mali_dvfs_utilization))
- MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler"));
-
- bMaliDvfsRun=0;
-}
-
-
-mali_bool init_mali_dvfs_status(int step)
-{
- /*default status
- add here with the right function to get initilization value.
- */
- if (!mali_dvfs_wq)
- mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs");
-
-#if MALI_GPU_BOTTOM_LOCK
- _mali_osk_atomic_init(&bottomlock_status, 0);
-#endif
-
- /*add a error handling here*/
- maliDvfsStatus.currentStep = step;
-
- return MALI_TRUE;
-}
-
-void deinit_mali_dvfs_status(void)
-{
-#if MALI_GPU_BOTTOM_LOCK
- _mali_osk_atomic_term(&bottomlock_status);
-#endif
-
- if (mali_dvfs_wq)
- destroy_workqueue(mali_dvfs_wq);
- mali_dvfs_wq = NULL;
-}
-
-mali_bool mali_dvfs_handler(u32 utilization)
-{
- mali_dvfs_utilization = utilization;
- queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work);
-
- /*add error handle here*/
- return MALI_TRUE;
-}
-
-void mali_default_step_set(int step, mali_bool boostup)
-{
- mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq);
-
- if (maliDvfsStatus.currentStep == 1)
- set_mali_dvfs_status(step, boostup);
-}
-
-#if MALI_GPU_BOTTOM_LOCK
-int mali_dvfs_bottom_lock_push(void)
-{
- int prev_status = _mali_osk_atomic_read(&bottomlock_status);
-
- if (prev_status < 0) {
- MALI_PRINT(("gpu bottom lock status is not valid for push"));
- return -1;
- }
-
- if (prev_status == 0) {
- mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol);
- mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq);
- set_mali_dvfs_current_step(1);
- }
-
- return _mali_osk_atomic_inc_return(&bottomlock_status);
-}
-
-int mali_dvfs_bottom_lock_pop(void)
-{
- if (_mali_osk_atomic_read(&bottomlock_status) <= 0) {
- MALI_PRINT(("gpu bottom lock status is not valid for pop"));
- return -1;
- }
-
- return _mali_osk_atomic_dec_return(&bottomlock_status);
-}
-#endif
+/* * 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_dvfs.c * Platform specific Mali driver dvfs functions */ #include "mali_kernel_common.h" #include "mali_osk.h" #include "mali_platform.h" #include <linux/clk.h> #include <linux/err.h> #include <linux/regulator/consumer.h> #include <linux/regulator/driver.h> #include <asm/io.h> #ifdef CONFIG_CPU_FREQ #include <mach/asv.h> #include <mach/regs-pmu.h> #define EXYNOS4_ASV_ENABLED #endif #include "mali_device_pause_resume.h" #include <linux/workqueue.h> #define MALI_DVFS_WATING 10 // msec static int bMaliDvfsRun=0; #if MALI_GPU_BOTTOM_LOCK static _mali_osk_atomic_t bottomlock_status; #endif typedef struct mali_dvfs_tableTag{ unsigned int clock; unsigned int freq; unsigned int vol; }mali_dvfs_table; typedef struct mali_dvfs_statusTag{ unsigned int currentStep; mali_dvfs_table * pCurrentDvfs; }mali_dvfs_currentstatus; typedef struct mali_dvfs_thresholdTag{ unsigned int downthreshold; unsigned int upthreshold; }mali_dvfs_threshold_table; typedef struct mali_dvfs_staycount{ unsigned int staycount; }mali_dvfs_staycount_table; mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={ /*step 0*/{1}, /*step 1*/{1},}; /*dvfs threshold*/ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ /*step 0*/{((int)((255*0)/100)), ((int)((255*85)/100))}, /*step 1*/{((int)((255*75)/100)), ((int)((255*100)/100))} }; /*dvfs status*/ mali_dvfs_currentstatus maliDvfsStatus; int mali_dvfs_control=0; /*dvfs table*/ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={ /*step 0*/{160 ,1000000 , 950000}, /*step 1*/{267 ,1000000 ,1000000} }; #ifdef EXYNOS4_ASV_ENABLED #define ASV_8_LEVEL 8 #define ASV_5_LEVEL 5 #define ASV_LEVEL_SUPPORT 0 static unsigned int asv_3d_volt_5_table[ASV_5_LEVEL][MALI_DVFS_STEPS] = { /* L3(160MHz), L2(266MHz) */ {1000000, 1100000}, /* S */ {1000000, 1100000}, /* A */ { 950000, 1000000}, /* B */ { 950000, 1000000}, /* C */ { 950000, 950000}, /* D */ }; static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = { /* L3(160MHz), L2(266MHz)) */ {1000000, 1100000}, /* SS */ {1000000, 1100000}, /* A1 */ {1000000, 1100000}, /* A2 */ { 950000, 1000000}, /* B1 */ { 950000, 1000000}, /* B2 */ { 950000, 1000000}, /* C1 */ { 950000, 1000000}, /* C2 */ { 950000, 950000}, /* D1 */ }; #endif static u32 mali_dvfs_utilization = 255; static void mali_dvfs_work_handler(struct work_struct *w); static struct workqueue_struct *mali_dvfs_wq = 0; extern mali_io_address clk_register_map; #if MALI_GPU_BOTTOM_LOCK extern _mali_osk_lock_t *mali_dvfs_lock; #endif static DECLARE_WORK(mali_dvfs_work, mali_dvfs_work_handler); static unsigned int get_mali_dvfs_status(void) { return maliDvfsStatus.currentStep; } #if MALI_GPU_BOTTOM_LOCK #if MALI_PMM_RUNTIME_JOB_CONTROL_ON int get_mali_dvfs_control_status(void) { return mali_dvfs_control; } mali_bool set_mali_dvfs_current_step(unsigned int step) { _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); maliDvfsStatus.currentStep = step; _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); return MALI_TRUE; } #endif #endif static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) { u32 validatedStep=step; #ifdef CONFIG_REGULATOR if (mali_regulator_get_usecount()==0) { MALI_DEBUG_PRINT(1, ("regulator use_count is 0 \n")); return MALI_FALSE; } #endif if (boostup) { #ifdef CONFIG_REGULATOR /*change the voltage*/ mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); #endif /*change the clock*/ mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); } else { /*change the clock*/ mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); #ifdef CONFIG_REGULATOR /*change the voltage*/ mali_regulator_set_voltage(mali_dvfs[step].vol, mali_dvfs[step].vol); #endif } maliDvfsStatus.currentStep = validatedStep; /*for future use*/ maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep]; return MALI_TRUE; } static void mali_platform_wating(u32 msec) { /*sample wating change this in the future with proper check routine. */ unsigned int read_val; while(1) { read_val = _mali_osk_mem_ioread32(clk_register_map, 0x00); if ((read_val & 0x8000)==0x0000) break; _mali_osk_time_ubusydelay(100); // 1000 -> 100 : 20101218 } /* _mali_osk_time_ubusydelay(msec*1000);*/ } static mali_bool change_mali_dvfs_status(u32 step, mali_bool boostup ) { MALI_DEBUG_PRINT(1, ("> change_mali_dvfs_status: %d, %d \n",step, boostup)); if (!set_mali_dvfs_status(step, boostup)) { MALI_DEBUG_PRINT(1, ("error on set_mali_dvfs_status: %d, %d \n",step, boostup)); return MALI_FALSE; } /*wait until clock and voltage is stablized*/ mali_platform_wating(MALI_DVFS_WATING); /*msec*/ return MALI_TRUE; } static unsigned int decideNextStatus(unsigned int utilization) { unsigned int level=0; // 0:stay, 1:up if (!mali_dvfs_control) { #if MALI_GPU_BOTTOM_LOCK if (_mali_osk_atomic_read(&bottomlock_status) > 0) level = 1; /* or bigger */ else if (utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) #else if (utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold) #endif level=1; else if (utilization < mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold) level=0; else level = maliDvfsStatus.currentStep; } else { if ((mali_dvfs_control > 0) && (mali_dvfs_control < mali_dvfs[1].clock)) level=0; else level=1; } return level; } #ifdef EXYNOS4_ASV_ENABLED static mali_bool mali_dvfs_table_update(void) { unsigned int exynos_result_of_asv_group; unsigned int i; exynos_result_of_asv_group = exynos_result_of_asv & 0xf; MALI_PRINT(("exynos_result_of_asv_group = 0x%x\n", exynos_result_of_asv_group)); if (ASV_LEVEL_SUPPORT) { //asv level information will be added. for (i = 0; i < MALI_DVFS_STEPS; i++) { mali_dvfs[i].vol = asv_3d_volt_5_table[exynos_result_of_asv_group][i]; MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); } } else { for (i = 0; i < MALI_DVFS_STEPS; i++) { mali_dvfs[i].vol = asv_3d_volt_8_table[exynos_result_of_asv_group][i]; MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol)); } } return MALI_TRUE; } #endif static mali_bool mali_dvfs_status(u32 utilization) { unsigned int nextStatus = 0; unsigned int curStatus = 0; mali_bool boostup = MALI_FALSE; #ifdef EXYNOS4_ASV_ENABLED static mali_bool asv_applied = MALI_FALSE; #endif static int stay_count = 0; // to prevent frequent switch MALI_DEBUG_PRINT(1, ("> mali_dvfs_status: %d \n",utilization)); #ifdef EXYNOS4_ASV_ENABLED if (asv_applied == MALI_FALSE) { mali_dvfs_table_update(); change_mali_dvfs_status(0,0); asv_applied = MALI_TRUE; return MALI_TRUE; } #endif /*decide next step*/ curStatus = get_mali_dvfs_status(); nextStatus = decideNextStatus(utilization); MALI_DEBUG_PRINT(1, ("= curStatus %d, nextStatus %d, maliDvfsStatus.currentStep %d \n", curStatus, nextStatus, maliDvfsStatus.currentStep)); /*if next status is same with current status, don't change anything*/ if ((curStatus!=nextStatus && stay_count==0)) { /*check if boost up or not*/ if (nextStatus > maliDvfsStatus.currentStep) boostup = 1; /*change mali dvfs status*/ if (!change_mali_dvfs_status(nextStatus,boostup)) { MALI_DEBUG_PRINT(1, ("error on change_mali_dvfs_status \n")); return MALI_FALSE; } stay_count = mali_dvfs_staycount[maliDvfsStatus.currentStep].staycount; } else { if (stay_count>0) stay_count--; } return MALI_TRUE; } int mali_dvfs_is_running(void) { return bMaliDvfsRun; } void mali_dvfs_late_resume(void) { // set the init clock as low when resume set_mali_dvfs_status(0,0); } static void mali_dvfs_work_handler(struct work_struct *w) { bMaliDvfsRun=1; MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n")); if (!mali_dvfs_status(mali_dvfs_utilization)) MALI_DEBUG_PRINT(1,( "error on mali dvfs status in mali_dvfs_work_handler")); bMaliDvfsRun=0; } mali_bool init_mali_dvfs_status(int step) { /*default status add here with the right function to get initilization value. */ if (!mali_dvfs_wq) mali_dvfs_wq = create_singlethread_workqueue("mali_dvfs"); #if MALI_GPU_BOTTOM_LOCK _mali_osk_atomic_init(&bottomlock_status, 0); #endif /*add a error handling here*/ maliDvfsStatus.currentStep = step; return MALI_TRUE; } void deinit_mali_dvfs_status(void) { #if MALI_GPU_BOTTOM_LOCK _mali_osk_atomic_term(&bottomlock_status); #endif if (mali_dvfs_wq) destroy_workqueue(mali_dvfs_wq); mali_dvfs_wq = NULL; } mali_bool mali_dvfs_handler(u32 utilization) { mali_dvfs_utilization = utilization; queue_work_on(0, mali_dvfs_wq,&mali_dvfs_work); /*add error handle here*/ return MALI_TRUE; } void mali_default_step_set(int step, mali_bool boostup) { mali_clk_set_rate(mali_dvfs[step].clock, mali_dvfs[step].freq); if (maliDvfsStatus.currentStep == 1) set_mali_dvfs_status(step, boostup); } #if MALI_GPU_BOTTOM_LOCK int mali_dvfs_bottom_lock_push(void) { int prev_status = _mali_osk_atomic_read(&bottomlock_status); if (prev_status < 0) { MALI_PRINT(("gpu bottom lock status is not valid for push")); return -1; } if (prev_status == 0) { mali_regulator_set_voltage(mali_dvfs[1].vol, mali_dvfs[1].vol); mali_clk_set_rate(mali_dvfs[1].clock, mali_dvfs[1].freq); set_mali_dvfs_current_step(1); } return _mali_osk_atomic_inc_return(&bottomlock_status); } int mali_dvfs_bottom_lock_pop(void) { if (_mali_osk_atomic_read(&bottomlock_status) <= 0) { MALI_PRINT(("gpu bottom lock status is not valid for pop")); return -1; } return _mali_osk_atomic_dec_return(&bottomlock_status); } #endif \ No newline at end of file
diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c
index 397ba942..e8e5129 100644
--- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c
+++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c
@@ -1,5 +1,4 @@
-/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+/* 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.
@@ -19,7 +18,7 @@
#include "mali_linux_pm.h"
#if USING_MALI_PMM
-#include "mali_pmm.h"
+#include "mali_pm.h"
#endif
#include <linux/clk.h>
@@ -32,8 +31,9 @@
#include <plat/pd.h>
#endif
-#if MALI_TIMELINE_PROFILING_ENABLED
-#include "mali_kernel_profiling.h"
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+#include "mali_osk_profiling.h"
+#include "cinstr/mali_cinstr_profiling_events_m200.h"
#endif
#include <asm/io.h>
@@ -58,12 +58,20 @@ typedef struct mali_runtime_resumeTag{
int vol;
}mali_runtime_resume_table;
-mali_runtime_resume_table mali_runtime_resume = {266, 900000};
+mali_runtime_resume_table mali_runtime_resume = {350, 950000};
/* lock/unlock CPU freq by Mali */
extern int cpufreq_lock_by_mali(unsigned int freq);
extern void cpufreq_unlock_by_mali(void);
+/* start of modification by skkim */
+extern mali_bool init_mali_dvfs_status(int step);
+extern void deinit_mali_dvfs_status(void);
+extern mali_bool mali_dvfs_handler(u32 utilization);
+extern int get_mali_dvfs_control_status(void);
+extern mali_bool set_mali_dvfs_current_step(unsigned int step);
+/* end of modification by skkim */
+
static struct clk *ext_xtal_clock = 0;
static struct clk *vpll_src_clock = 0;
static struct clk *fout_vpll_clock = 0;
@@ -76,11 +84,11 @@ static struct clk *mali_clock = 0;
static unsigned int GPU_MHZ = 1000000;
-int mali_gpu_clk = 266;
-int mali_gpu_vol = 900000;
+int mali_gpu_clk = 350;
+int mali_gpu_vol = 950000;
#if MALI_DVFS_ENABLED
-#define MALI_DVFS_DEFAULT_STEP 0
+#define MALI_DVFS_DEFAULT_STEP 2
#endif
#if MALI_VOLTAGE_LOCK
int mali_lock_vol = 0;
@@ -134,7 +142,6 @@ int mali_regulator_get_usecount(void)
void mali_regulator_disable(void)
{
- bPoweroff = 1;
if( IS_ERR_OR_NULL(g3d_regulator) )
{
MALI_DEBUG_PRINT(1, ("error on mali_regulator_disable : g3d_regulator is null\n"));
@@ -142,11 +149,11 @@ void mali_regulator_disable(void)
}
regulator_disable(g3d_regulator);
MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount()));
+ bPoweroff = 1;
}
void mali_regulator_enable(void)
{
- bPoweroff = 0;
if( IS_ERR_OR_NULL(g3d_regulator) )
{
MALI_DEBUG_PRINT(1, ("error on mali_regulator_enable : g3d_regulator is null\n"));
@@ -154,6 +161,7 @@ void mali_regulator_enable(void)
}
regulator_enable(g3d_regulator);
MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount()));
+ bPoweroff = 0;
}
void mali_regulator_set_voltage(int min_uV, int max_uV)
@@ -196,8 +204,8 @@ void mali_regulator_set_voltage(int min_uV, int max_uV)
MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV));
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS,
min_uV, max_uV, 1, 0, 0);
@@ -206,8 +214,8 @@ void mali_regulator_set_voltage(int min_uV, int max_uV)
regulator_set_voltage(g3d_regulator,min_uV,max_uV);
voltage = regulator_get_voltage(g3d_regulator);
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS,
voltage, 0, 2, 0, 0);
@@ -398,18 +406,20 @@ mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz)
if (clk_enable(mali_clock) < 0)
return MALI_FALSE;
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ unsigned long previous_rate = 0;
+ previous_rate = clk_get_rate(mali_clock);
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ,
- rate, 0, 0, 0, 0);
+ previous_rate, 0, 0, 0, 0);
#endif
clk_set_rate(mali_clock, rate);
rate = clk_get_rate(mali_clock);
-#if MALI_TIMELINE_PROFILING_ENABLED
- _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE |
MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ,
rate, 1, 0, 0, 0);
@@ -434,8 +444,6 @@ static mali_bool init_mali_clock(void)
{
mali_bool ret = MALI_TRUE;
- gpu_power_state = 0;
-
if (mali_clock != 0)
return ret; // already initialized
@@ -475,15 +483,15 @@ static mali_bool init_mali_clock(void)
MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n"));
-
MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__));
MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__));
mali_clk_put(MALI_FALSE);
- return MALI_TRUE;
-
+ gpu_power_state=0;
+ bPoweroff=1;
+ return MALI_TRUE;
#ifdef CONFIG_REGULATOR
err_regulator:
regulator_put(g3d_regulator);
@@ -526,12 +534,13 @@ static _mali_osk_errcode_t enable_mali_clocks(void)
else {
mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol);
mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ);
+ set_mali_dvfs_current_step(MALI_DVFS_DEFAULT_STEP);
}
- if (mali_gpu_clk <= mali_runtime_resume.clk)
- set_mali_dvfs_current_step(5);
+#if CPUFREQ_LOCK_DURING_440
/* lock/unlock CPU freq by Mali */
if (mali_gpu_clk == 440)
err = cpufreq_lock_by_mali(1200);
+#endif
#else
mali_regulator_set_voltage(mali_runtime_resume.vol, mali_runtime_resume.vol);
mali_clk_set_rate(mali_runtime_resume.clk, GPU_MHZ);
@@ -547,8 +556,10 @@ static _mali_osk_errcode_t disable_mali_clocks(void)
clk_disable(mali_clock);
MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock));
+#if MALI_DVFS_ENABLED
/* lock/unlock CPU freq by Mali */
cpufreq_unlock_by_mali();
+#endif
MALI_SUCCESS;
}
@@ -569,7 +580,7 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on)
{
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
MALI_DEBUG_PRINT(3,("_mali_osk_pmm_dev_activate \n"));
- _mali_osk_pmm_dev_activate();
+ _mali_osk_pm_dev_activate();
#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON
void __iomem *status;
u32 timeout;
@@ -586,14 +597,14 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on)
timeout--;
_mali_osk_time_ubusydelay(100);
}
+ MALI_PRINTF(("MALI Power domain enabled"));
#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON
}
else
{
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
MALI_DEBUG_PRINT( 4,("_mali_osk_pmm_dev_idle\n"));
- _mali_osk_pmm_dev_idle();
-
+ _mali_osk_pm_dev_idle();
#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON
void __iomem *status;
u32 timeout;
@@ -611,6 +622,7 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on)
timeout--;
_mali_osk_time_ubusydelay( 100);
}
+ MALI_PRINTF(("MALI Power domain disabled"));
#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON
}
@@ -714,7 +726,51 @@ u32 pmu_get_power_up_down_info(void)
_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode)
{
- MALI_SUCCESS;
+ switch (power_mode)
+ {
+ case MALI_POWER_MODE_ON:
+ MALI_DEBUG_PRINT(1, ("Mali platform: Got MALI_POWER_MODE_ON event, %s\n", bPoweroff ? "powering on" : "already on"));
+ if (bPoweroff == 1)
+ {
+ /** If run time power management is used, donot call this function */
+#ifndef CONFIG_PM_RUNTIME
+ g3d_power_domain_control(1);
+#endif
+
+ MALI_DEBUG_PRINT(4,("enable clock \n"));
+ enable_mali_clocks();
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, mali_gpu_clk, mali_gpu_vol/1000, 0, 0, 0);
+#endif
+ //MALI_PRINTF(("Mali Platform powered up"));
+ gpu_power_state=1;
+ bPoweroff=0;
+ }
+ break;
+ case MALI_POWER_MODE_LIGHT_SLEEP:
+ case MALI_POWER_MODE_DEEP_SLEEP:
+ MALI_DEBUG_PRINT(1, ("Mali platform: Got %s event, %s\n",
+ power_mode == MALI_POWER_MODE_LIGHT_SLEEP ? "MALI_POWER_MODE_LIGHT_SLEEP" : "MALI_POWER_MODE_DEEP_SLEEP",
+ bPoweroff ? "already off" : "powering off"));
+ if (bPoweroff == 0)
+ {
+ disable_mali_clocks();
+#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE| MALI_PROFILING_EVENT_CHANNEL_GPU|MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, 0, 0, 0, 0, 0);
+#endif
+
+#ifndef CONFIG_PM_RUNTIME
+ g3d_power_domain_control(0);
+#endif
+
+ //MALI_PRINTF(("Mali Platform powered down"));
+ gpu_power_state=0;
+ bPoweroff=1;
+ }
+
+ break;
+ }
+ MALI_SUCCESS;
}
#if MALI_VOLTAGE_LOCK
diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
index 8293d6e..2d47dba 100644
--- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
+++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -27,7 +27,7 @@
#include "mali_device_pause_resume.h"
#include <linux/workqueue.h>
-#define MAX_MALI_DVFS_STEPS 4
+#define MAX_MALI_DVFS_STEPS 5
#define MALI_DVFS_WATING 10 // msec
#ifdef CONFIG_CPU_FREQ
@@ -35,10 +35,12 @@
#define EXYNOS4_ASV_ENABLED
#endif
+#include <plat/cpu.h>
+
static int bMaliDvfsRun=0;
static _mali_osk_atomic_t bottomlock_status;
-static int bottom_lock_step;
+int bottom_lock_step = 0;
typedef struct mali_dvfs_tableTag{
unsigned int clock;
@@ -73,7 +75,10 @@ mali_dvfs_step step[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
/*step 2 clk*/ {350, 950000},
#if (MALI_DVFS_STEPS > 3)
- /*step 3 clk*/ {440, 1025000}
+ /*step 3 clk*/ {440, 1025000},
+#if (MALI_DVFS_STEPS > 4)
+ /*step 4 clk*/ {533, 1075000}
+#endif
#endif
#endif
#endif
@@ -86,17 +91,21 @@ mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
/*step 2*/{0},
#if (MALI_DVFS_STEPS > 3)
- /*step 3*/{0}
+ /*step 3*/{0},
+#if (MALI_DVFS_STEPS > 4)
+ /*step 4*/{0}
+#endif
#endif
#endif
#endif
};
/* dvfs information */
-// L0 = 440Mhz, 1.025V
-// L1 = 350Mhz, 0.95V
-// L2 = 266Mhz, 0.90V
-// L3 = 160Mhz, 0.875V
+// L0 = 533Mhz, 1.075V
+// L1 = 440Mhz, 1.025V
+// L2 = 350Mhz, 0.95V
+// L3 = 266Mhz, 0.90V
+// L4 = 160Mhz, 0.875V
int step0_clk = 160;
int step0_vol = 875000;
@@ -114,7 +123,13 @@ int step2_down = 85;
int step3_clk = 440;
int step3_vol = 1025000;
int step2_up = 90;
-int step3_down = 90;
+int step3_down = 85;
+#if (MALI_DVFS_STEPS > 4)
+int step4_clk = 533;
+int step4_vol = 1075000;
+int step3_up = 90;
+int step4_down = 95;
+#endif
#endif
#endif
#endif
@@ -123,7 +138,8 @@ mali_dvfs_table mali_dvfs_all[MAX_MALI_DVFS_STEPS]={
{160 ,1000000 , 875000},
{266 ,1000000 , 900000},
{350 ,1000000 , 950000},
- {440 ,1000000 , 1025000} };
+ {440 ,1000000 , 1025000},
+ {533 ,1000000 , 1075000} };
mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
{160 ,1000000 , 875000},
@@ -132,7 +148,10 @@ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
{350 ,1000000 , 950000},
#if (MALI_DVFS_STEPS > 3)
- {440 ,1000000 ,1025000}
+ {440 ,1000000 ,1025000},
+#if (MALI_DVFS_STEPS > 4)
+ {533 ,1000000 ,1075000}
+#endif
#endif
#endif
#endif
@@ -145,7 +164,10 @@ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
{85 , 90},
#if (MALI_DVFS_STEPS > 3)
- {90 ,100}
+ {85 ,90},
+#if (MALI_DVFS_STEPS > 4)
+ {95 ,100}
+#endif
#endif
#endif
#endif
@@ -154,19 +176,48 @@ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={
#ifdef EXYNOS4_ASV_ENABLED
#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */
-static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS][ASV_LEVEL] = {
+static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = {
+ { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */
+#if (MALI_DVFS_STEPS > 1)
+ { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */
+#if (MALI_DVFS_STEPS > 2)
+ { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */
+#if (MALI_DVFS_STEPS > 3)
+ { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */
+#endif
+#endif
+#endif
+};
+
+static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = {
{ 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */
#if (MALI_DVFS_STEPS > 1)
- { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */
+ { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */
#if (MALI_DVFS_STEPS > 2)
- { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */
+ { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */
#if (MALI_DVFS_STEPS > 3)
- { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */
+ { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */
#endif
#endif
#endif
};
+
+static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL] = {
+ { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000}, /* L4(160Mhz) */
+#if (MALI_DVFS_STEPS > 1)
+ { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 862500}, /* L3(266Mhz) */
+#if (MALI_DVFS_STEPS > 2)
+ { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500}, /* L2(350Mhz) */
+#if (MALI_DVFS_STEPS > 3)
+ { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000}, /* L1(440Mhz) */
+#if (MALI_DVFS_STEPS > 4)
+ { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(533Mhz) */
+#endif
#endif
+#endif
+#endif
+};
+#endif /* ASV_LEVEL */
/*dvfs status*/
mali_dvfs_currentstatus maliDvfsStatus;
@@ -279,10 +330,12 @@ static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
}
#ifdef EXYNOS4_ASV_ENABLED
- if (mali_dvfs[step].clock == 160)
- exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
- else
- exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
+ if (samsung_rev() < EXYNOS4412_REV_2_0) {
+ if (mali_dvfs[step].clock == 160)
+ exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
+ else
+ exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
+ }
#endif
@@ -290,11 +343,13 @@ static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
/*for future use*/
maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep];
+#if CPUFREQ_LOCK_DURING_440
/* lock/unlock CPU freq by Mali */
if (mali_dvfs[step].clock == 440)
err = cpufreq_lock_by_mali(1200);
else
cpufreq_unlock_by_mali();
+#endif
return MALI_TRUE;
}
@@ -335,11 +390,30 @@ extern unsigned int exynos_result_of_asv;
static mali_bool mali_dvfs_table_update(void)
{
unsigned int i;
-
- for (i = 0; i < MALI_DVFS_STEPS; i++) {
- MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
- mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv];
- MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol));
+ unsigned int step_num = MALI_DVFS_STEPS;
+
+ if(soc_is_exynos4412()) {
+ if (exynos_armclk_max == 1000000) {
+ step_num = MALI_DVFS_STEPS - 1;
+ for (i = 0; i < step_num; i++) {
+ MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
+ mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv];
+ MALI_PRINT(("mali_dvfs[%d].vol = %d 1ghz_type\n", i, mali_dvfs[i].vol));
+ }
+ } else if (samsung_rev() >= EXYNOS4412_REV_2_0) {
+ for (i = 0; i < step_num; i++) {
+ MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
+ mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv];
+ MALI_PRINT(("mali_dvfs[%d].vol = %d 1.6ghz_type\n", i, mali_dvfs[i].vol));
+ }
+ } else {
+ step_num = MALI_DVFS_STEPS - 1;
+ for (i = 0; i < step_num; i++) {
+ MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
+ mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv];
+ MALI_PRINT(("mali_dvfs[%d].vol = %d 1.4ghz_type\n", i, mali_dvfs[i].vol));
+ }
+ }
}
return MALI_TRUE;
@@ -354,7 +428,6 @@ static unsigned int decideNextStatus(unsigned int utilization)
if (mali_runtime_resumed >= 0) {
level = mali_runtime_resumed;
mali_runtime_resumed = -1;
- return level;
}
if (mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold
@@ -369,6 +442,9 @@ static unsigned int decideNextStatus(unsigned int utilization)
if (utilization > (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold / 100) &&
level < MALI_DVFS_STEPS - 1) {
level++;
+ if ((samsung_rev() < EXYNOS4412_REV_2_0) && (maliDvfsStatus.currentStep == 3)) {
+ level=get_mali_dvfs_status();
+ }
}
if (utilization < (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold / 100) &&
level > 0) {
@@ -400,6 +476,10 @@ static unsigned int decideNextStatus(unsigned int utilization)
#if (MALI_DVFS_STEPS > 3)
step3_clk = step[3].clk;
change_dvfs_tableset(step3_clk, 3);
+#if (MALI_DVFS_STEPS > 4)
+ step4_clk = step[4].clk;
+ change_dvfs_tableset(step4_clk, 4);
+#endif
#endif
#endif
#endif
@@ -422,12 +502,18 @@ static unsigned int decideNextStatus(unsigned int utilization)
step[i].clk = mali_dvfs_all[2].clock;
}
maliDvfsStatus.currentStep = 2;
- } else {
+ } else if (mali_dvfs_control < mali_dvfs_all[4].clock && mali_dvfs_control >= mali_dvfs_all[3].clock) {
int i = 0;
for (i = 0; i < MALI_DVFS_STEPS; i++) {
step[i].clk = mali_dvfs_all[3].clock;
}
maliDvfsStatus.currentStep = 3;
+ } else {
+ int i = 0;
+ for (i = 0; i < MALI_DVFS_STEPS; i++) {
+ step[i].clk = mali_dvfs_all[4].clock;
+ }
+ maliDvfsStatus.currentStep = 4;
}
step0_clk = step[0].clk;
change_dvfs_tableset(step0_clk, 0);
@@ -440,6 +526,10 @@ static unsigned int decideNextStatus(unsigned int utilization)
#if (MALI_DVFS_STEPS > 3)
step3_clk = step[3].clk;
change_dvfs_tableset(step3_clk, 3);
+#if (MALI_DVFS_STEPS > 4)
+ step4_clk = step[4].clk;
+ change_dvfs_tableset(step4_clk, 4);
+#endif
#endif
#endif
#endif
@@ -577,6 +667,22 @@ static void mali_dvfs_work_handler(struct work_struct *w)
MALI_PRINT((":::step3_down change to %d %\n", step3_down));
mali_dvfs_threshold[3].downthreshold = step3_down;
}
+#if (MALI_DVFS_STEPS > 4)
+ if (step4_clk != mali_dvfs[4].clock) {
+ MALI_PRINT(("::: step4_clk change to %d Mhz\n", step4_clk));
+ change_clk = step4_clk;
+ change_step = 4;
+ step4_clk = change_dvfs_tableset(change_clk, change_step);
+ }
+ if (step3_up != mali_dvfs_threshold[3].upthreshold) {
+ MALI_PRINT((":::step3_up change to %d %\n", step3_up));
+ mali_dvfs_threshold[3].upthreshold = step3_up;
+ }
+ if (step4_down != mali_dvfs_threshold[4].downthreshold) {
+ MALI_PRINT((":::step4_down change to %d %\n", step4_down));
+ mali_dvfs_threshold[4].downthreshold = step4_down;
+ }
+#endif
#endif
#endif
#endif
@@ -587,6 +693,7 @@ static void mali_dvfs_work_handler(struct work_struct *w)
mali_dvfs[1].vol = step1_vol;
mali_dvfs[2].vol = step2_vol;
mali_dvfs[3].vol = step3_vol;
+ mali_dvfs[4].vol = step4_vol;
#endif
MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
@@ -641,8 +748,10 @@ int change_dvfs_tableset(int change_clk, int change_step)
mali_dvfs[change_step].clock = mali_dvfs_all[1].clock;
} else if (change_clk < mali_dvfs_all[3].clock && change_clk >= mali_dvfs_all[2].clock) {
mali_dvfs[change_step].clock = mali_dvfs_all[2].clock;
- } else {
+ } else if (change_clk < mali_dvfs_all[4].clock && change_clk >= mali_dvfs_all[3].clock) {
mali_dvfs[change_step].clock = mali_dvfs_all[3].clock;
+ } else {
+ mali_dvfs[change_step].clock = mali_dvfs_all[4].clock;
}
MALI_PRINT((":::mali dvfs step %d clock and voltage = %d Mhz, %d V\n",change_step, mali_dvfs[change_step].clock, mali_dvfs[change_step].vol));
@@ -655,11 +764,13 @@ int change_dvfs_tableset(int change_clk, int change_step)
/*change the clock*/
mali_clk_set_rate(mali_dvfs[change_step].clock, mali_dvfs[change_step].freq);
+#if CPUFREQ_LOCK_DURING_440
/* lock/unlock CPU freq by Mali */
if (mali_dvfs[change_step].clock == 440)
err = cpufreq_lock_by_mali(1200);
else
cpufreq_unlock_by_mali();
+#endif
}
return mali_dvfs[change_step].clock;
@@ -684,10 +795,8 @@ int mali_dvfs_bottom_lock_push(int lock_step)
if (bottom_lock_step < lock_step) {
bottom_lock_step = lock_step;
if (get_mali_dvfs_status() < lock_step) {
- mali_regulator_set_voltage(mali_dvfs[lock_step].vol,
- mali_dvfs[lock_step].vol);
- mali_clk_set_rate(mali_dvfs[lock_step].clock,
- mali_dvfs[lock_step].freq);
+ mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol);
+ mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq);
set_mali_dvfs_current_step(lock_step);
}
}
diff --git a/drivers/media/video/samsung/mali/readme.txt b/drivers/media/video/samsung/mali/readme.txt
new file mode 100644
index 0000000..3acc51c
--- /dev/null
+++ b/drivers/media/video/samsung/mali/readme.txt
@@ -0,0 +1,28 @@
+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> 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
+ 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/media/video/samsung/mali/regs/mali_200_regs.h b/drivers/media/video/samsung/mali/regs/mali_200_regs.h
index e9da7ab..59e92c8 100644
--- a/drivers/media/video/samsung/mali/regs/mali_200_regs.h
+++ b/drivers/media/video/samsung/mali/regs/mali_200_regs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -51,7 +51,7 @@ enum mali200_mgmt_ctrl_mgmt {
#endif
MALI200_REG_VAL_CTRL_MGMT_FORCE_RESET = (1<<5),
MALI200_REG_VAL_CTRL_MGMT_START_RENDERING = (1<<6),
-#if defined(USING_MALI400)
+#if defined(USING_MALI400) || defined(USING_MALI450)
MALI400PP_REG_VAL_CTRL_MGMT_SOFT_RESET = (1<<7),
#endif
};
@@ -72,7 +72,7 @@ enum mali200_mgmt_irq {
MALI400PP_REG_VAL_IRQ_RESET_COMPLETED = (1<<12),
};
-#if defined USING_MALI200
+#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 |\
@@ -83,7 +83,7 @@ enum mali200_mgmt_irq {
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
+#elif defined(USING_MALI400) || defined(USING_MALI450)
#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 |\
@@ -102,14 +102,14 @@ enum mali200_mgmt_irq {
#error "No supported mali core defined"
#endif
-#if defined USING_MALI200
+#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
+#elif defined(USING_MALI400) || defined(USING_MALI450)
#define MALI200_REG_VAL_IRQ_MASK_USED ((enum mali200_mgmt_irq) (\
MALI200_REG_VAL_IRQ_END_OF_FRAME |\
MALI200_REG_VAL_IRQ_HANG |\
@@ -134,11 +134,14 @@ enum mali200_mgmt_status {
enum mali200_render_unit
{
MALI200_REG_ADDR_FRAME = 0x0000,
+ MALI200_REG_ADDR_STACK = 0x0030
};
-#if defined USING_MALI200
+#if defined(USING_MALI200)
#define MALI200_NUM_REGS_FRAME ((0x04C/4)+1)
-#elif defined USING_MALI400
+#elif defined(USING_MALI400)
+#define MALI200_NUM_REGS_FRAME ((0x058/4)+1)
+#elif defined(USING_MALI450)
#define MALI200_NUM_REGS_FRAME ((0x058/4)+1)
#else
#error "No supported mali core defined"
@@ -150,21 +153,20 @@ enum mali200_wb_unit {
MALI200_REG_ADDR_WB2 = 0x0300
};
+enum mali200_wb_unit_regs {
+ MALI200_REG_ADDR_WB_SOURCE_SELECT = 0x0000,
+};
+
/** 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 MALI200_PP_PRODUCT_ID 0xC807
#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
+#define MALI450_PP_PRODUCT_ID 0xCF07
#endif /* _MALI200_REGS_H_ */
diff --git a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h
index 14719a3..21c83c0 100644
--- a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h
+++ b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -12,9 +12,9 @@
#define _MALIGP2_CONROL_REGS_H_
/**
- * These are the different geometry processor controll registers.
+ * These are the different geometry processor control registers.
* Their usage is to control and monitor the operation of the
- * Vertex Shader and the Polygon List Builer in the geometry processor.
+ * Vertex Shader and the Polygon List Builder in the geometry processor.
* Addresses are in 32-bit word relative sizes.
* @see [P0081] "Geometry Processor Data Structures" for details
*/
@@ -60,7 +60,7 @@ typedef enum
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)
+#if defined(USING_MALI400) || defined(USING_MALI450)
MALI400GP_REG_VAL_CMD_SOFT_RESET = (1<<10),
#endif
} mgp_contr_reg_val_cmd;
@@ -84,7 +84,7 @@ typedef enum
#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
+#if defined(USING_MALI400) || defined(USING_MALI450)
#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)
@@ -97,7 +97,7 @@ typedef enum
#endif
/* Mask defining all IRQs in MaliGP2 */
-#if defined USING_MALI200
+#if defined(USING_MALI200)
#define MALIGP2_REG_VAL_IRQ_MASK_ALL \
(\
MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \
@@ -112,7 +112,7 @@ typedef enum
MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \
MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \
MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR)
-#elif defined USING_MALI400
+#elif defined(USING_MALI400) || defined(USING_MALI450)
#define MALIGP2_REG_VAL_IRQ_MASK_ALL \
(\
MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \
@@ -139,7 +139,7 @@ typedef enum
#endif
/* Mask defining the IRQs in MaliGP2 which we use*/
-#if defined USING_MALI200
+#if defined(USING_MALI200)
#define MALIGP2_REG_VAL_IRQ_MASK_USED \
(\
MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \
@@ -150,7 +150,7 @@ typedef enum
MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \
MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \
MALIGP2_REG_VAL_IRQ_AXI_BUS_ERROR)
-#elif defined USING_MALI400
+#elif defined(USING_MALI400) || defined(USING_MALI450)
#define MALIGP2_REG_VAL_IRQ_MASK_USED \
(\
MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \
@@ -197,15 +197,10 @@ typedef enum
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 MALI200_GP_PRODUCT_ID 0xA07
#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
+#define MALI450_GP_PRODUCT_ID 0xD07
/**
* The different sources for instrumented on the geometry processor.
diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c
index cddfa58..a6b1d76 100644
--- a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c
+++ b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h
index 442c6e0..3279dae 100644
--- a/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h
+++ b/drivers/media/video/samsung/mali/timestamp-arm11-cc/mali_timestamp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c
index cddfa58..a6b1d76 100644
--- a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c
+++ b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h
index 470eac9..94b842a 100644
--- a/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h
+++ b/drivers/media/video/samsung/mali/timestamp-default/mali_timestamp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
diff --git a/drivers/media/video/samsung/tvout/Kconfig b/drivers/media/video/samsung/tvout/Kconfig
index 176efeb..da7bda7 100644
--- a/drivers/media/video/samsung/tvout/Kconfig
+++ b/drivers/media/video/samsung/tvout/Kconfig
@@ -62,6 +62,16 @@ config HDMI_CONTROLLED_BY_EXT_IC
For example, the H/W has HDMI level shifter then it should be turned
on when HPD interrupt comes.
+config HDMI_TX_STRENGTH
+ bool "Tuning TX amplitude"
+ depends on VIDEO_TVOUT && ARCH_EXYNOS4
+ default n
+ ---help---
+ Say y here if the H/W needs to be tuned for TX amplitude.
+ HDMI driver will take the values registered at board file
+ and apply them through HDMI phy i2c according to the requested
+ channel number.
+
config HDMI_SWITCH_HPD
bool "HDMI HPD switch uevent driver support"
depends on HDMI_HPD
diff --git a/drivers/media/video/samsung/tvout/hw_if/hdcp.c b/drivers/media/video/samsung/tvout/hw_if/hdcp.c
index 569de28..41caf19 100644
--- a/drivers/media/video/samsung/tvout/hw_if/hdcp.c
+++ b/drivers/media/video/samsung/tvout/hw_if/hdcp.c
@@ -379,7 +379,9 @@ static int s5p_hdcp_read_bcaps(void)
if (s5p_ddc_read(HDCP_Bcaps, BCAPS_SIZE, &bcaps) < 0)
goto bcaps_read_err;
- if (s5p_hdmi_ctrl_status() == false || !s5p_hdmi_reg_get_hpd_status() || on_stop_process)
+ if (s5p_hdmi_ctrl_status() == false ||
+ !s5p_hdmi_reg_get_hpd_status() ||
+ on_stop_process)
goto bcaps_read_err;
writeb(bcaps, hdmi_base + S5P_HDMI_HDCP_BCAPS);
@@ -532,7 +534,8 @@ static void s5p_hdcp_reset_auth(void)
unsigned long spin_flags;
if (s5p_hdmi_ctrl_status() == false ||
- !s5p_hdmi_reg_get_hpd_status() || on_stop_process)
+ !s5p_hdmi_reg_get_hpd_status() ||
+ on_stop_process)
return;
spin_lock_irqsave(&hdcp_info.reset_lock, spin_flags);
@@ -956,9 +959,12 @@ check_ri_err:
static void s5p_hdcp_work(void *arg)
{
+ s5p_tvout_mutex_lock();
if (!hdcp_info.hdcp_enable || s5p_hdmi_ctrl_status() == false ||
- !s5p_hdmi_reg_get_hpd_status() || on_stop_process)
+ !s5p_hdmi_reg_get_hpd_status() || on_stop_process) {
+ s5p_tvout_mutex_unlock();
return;
+ }
if (hdcp_info.event & HDCP_EVENT_READ_BKSV_START) {
if (s5p_hdcp_bksv() < 0)
@@ -987,13 +993,16 @@ static void s5p_hdcp_work(void *arg)
else
hdcp_info.event &= ~HDCP_EVENT_CHECK_RI_START;
}
+ s5p_tvout_mutex_unlock();
return;
work_err:
if (!hdcp_info.hdcp_enable || s5p_hdmi_ctrl_status() == false ||
!s5p_hdmi_reg_get_hpd_status() || on_stop_process) {
+ s5p_tvout_mutex_unlock();
return;
}
s5p_hdcp_reset_auth();
+ s5p_tvout_mutex_unlock();
}
irqreturn_t s5p_hdcp_irq_handler(int irq, void *dev_id)
@@ -1121,3 +1130,8 @@ int s5p_hdcp_encrypt_stop(bool on)
return 0;
}
+
+void s5p_hdcp_flush_work(void)
+{
+ flush_workqueue(hdcp_wq);
+}
diff --git a/drivers/media/video/samsung/tvout/hw_if/hdmi.c b/drivers/media/video/samsung/tvout/hw_if/hdmi.c
index dfb3152..67099af 100644
--- a/drivers/media/video/samsung/tvout/hw_if/hdmi.c
+++ b/drivers/media/video/samsung/tvout/hw_if/hdmi.c
@@ -871,10 +871,10 @@ static void s5p_hdmi_print_phy_config(void)
printk(KERN_WARNING "read buffer :\n");
- for (i = 1; i < size; i++) {
+ for (i = 0; i < size; i++) {
printk("0x%02x", read_buffer[i]);
- if (i % 8)
+ if ((i+1) % 8)
printk(" ");
else
printk("\n");
@@ -1146,6 +1146,58 @@ void s5p_hdmi_reg_sw_reset(void)
s5p_hdmi_ctrl_clock(0);
}
+#ifdef CONFIG_HDMI_TX_STRENGTH
+int s5p_hdmi_phy_set_tx_strength(u8 ch, u8 *value)
+{
+ u8 buff[2];
+
+ if (ch & TX_EMP_LVL) { /* REG10 BIT7:4 */
+ buff[0] = HDMI_PHY_I2C_REG10;
+ buff[1] = (value[TX_EMP_LVL_VAL] & 0x0f) << 4;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_AMP_LVL) { /* REG10 BIT3:0, REG0F BIT7 */
+ buff[0] = HDMI_PHY_I2C_REG10;
+ buff[1] = (value[TX_AMP_LVL_VAL] & 0x0e) >> 1;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ buff[0] = HDMI_PHY_I2C_REG0F;
+ buff[1] = (value[TX_AMP_LVL_VAL] & 0x01) << 7;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_LVL_CH0) { /* REG04 BIT7:6 */
+ buff[0] = HDMI_PHY_I2C_REG04;
+ buff[1] = (value[TX_LVL_CH0_VAL] & 0x3) << 6;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_LVL_CH1) { /* REG13 BIT1:0 */
+ buff[0] = HDMI_PHY_I2C_REG13;
+ buff[1] = (value[TX_LVL_CH1_VAL] & 0x3);
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_LVL_CH2) { /* REG17 BIT1:0 */
+ buff[0] = HDMI_PHY_I2C_REG17;
+ buff[1] = (value[TX_LVL_CH2_VAL] & 0x3);
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ return 0;
+
+err_exit:
+ pr_err("%s: failed to set tx strength\n", __func__);
+ return -1;
+}
+#endif
+
int s5p_hdmi_phy_power(bool on)
{
u32 size;
diff --git a/drivers/media/video/samsung/tvout/hw_if/hw_if.h b/drivers/media/video/samsung/tvout/hw_if/hw_if.h
index 11bda99..e437b0a 100644
--- a/drivers/media/video/samsung/tvout/hw_if/hw_if.h
+++ b/drivers/media/video/samsung/tvout/hw_if/hw_if.h
@@ -364,6 +364,27 @@ struct s5p_hdmi_v_format {
u8 mhl_vsync;
};
+#ifdef CONFIG_HDMI_TX_STRENGTH
+#define HDMI_PHY_I2C_REG10 0x10
+#define HDMI_PHY_I2C_REG0F 0x0F
+#define HDMI_PHY_I2C_REG04 0x04
+#define HDMI_PHY_I2C_REG13 0x13
+#define HDMI_PHY_I2C_REG17 0x17
+
+#define TX_EMP_LVL 0x10
+#define TX_AMP_LVL 0x08
+#define TX_LVL_CH0 0x04
+#define TX_LVL_CH1 0x02
+#define TX_LVL_CH2 0x01
+
+#define TX_EMP_LVL_VAL 0
+#define TX_AMP_LVL_VAL 1
+#define TX_LVL_CH0_VAL 2
+#define TX_LVL_CH1_VAL 3
+#define TX_LVL_CH2_VAL 4
+
+extern int s5p_hdmi_phy_set_tx_strength(u8 ch, u8 *value);
+#endif
extern int s5p_hdmi_phy_power(bool on);
extern s32 s5p_hdmi_phy_config(
enum phy_freq freq, enum s5p_hdmi_color_depth cd);
@@ -750,6 +771,7 @@ extern int s5p_hdcp_encrypt_stop(bool on);
extern int __init s5p_hdcp_init(void);
extern int s5p_hdcp_start(void);
extern int s5p_hdcp_stop(void);
+extern void s5p_hdcp_flush_work(void);
/****************************************
* Definitions for sdo ctrl class
@@ -1000,6 +1022,10 @@ struct s5p_tvif_ctrl_private_data {
struct device *bus_dev; /* for BusFreq with Opp */
#endif
struct device *dev; /* hpd device pointer */
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ u8 tx_ch;
+ u8 *tx_val;
+#endif
};
#endif /* _SAMSUNG_TVOUT_HW_IF_H_ */
diff --git a/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c b/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c
index a0169cb..5e78a3c 100644
--- a/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c
+++ b/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c
@@ -241,7 +241,7 @@ static void s5p_mixer_ctrl_clock(bool on)
clk_enable(s5p_mixer_ctrl_private.clk[ACLK].ptr);
- // Restore mixer_base address
+ /* Restore mixer_base address */
s5p_mixer_init(s5p_mixer_ctrl_private.reg_mem.base);
} else {
clk_disable(s5p_mixer_ctrl_private.clk[ACLK].ptr);
@@ -252,7 +252,7 @@ static void s5p_mixer_ctrl_clock(bool on)
clk_disable(s5p_mixer_ctrl_private.clk[MUX].ptr);
- // Set mixer_base address to NULL
+ /* Set mixer_base address to NULL */
s5p_mixer_init(NULL);
}
}
@@ -267,7 +267,7 @@ void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer)
{
struct s5ptvfb_user_scaling scaling;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -278,12 +278,16 @@ void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer)
s5p_mixer_set_priority(layer,
s5p_mixer_ctrl_private.layer[layer].priority);
s5p_mixer_set_pre_mul_mode(layer,
- s5p_mixer_ctrl_private.layer[layer].pre_mul_mode);
+ s5p_mixer_ctrl_private.layer[layer].
+ pre_mul_mode);
s5p_mixer_set_chroma_key(layer,
- s5p_mixer_ctrl_private.layer[layer].chroma_enable,
- s5p_mixer_ctrl_private.layer[layer].chroma_key);
+ s5p_mixer_ctrl_private.layer[layer].
+ chroma_enable,
+ s5p_mixer_ctrl_private.layer[layer].
+ chroma_key);
s5p_mixer_set_layer_blend(layer,
- s5p_mixer_ctrl_private.layer[layer].layer_blend);
+ s5p_mixer_ctrl_private.layer[layer].
+ layer_blend);
s5p_mixer_set_alpha(layer,
s5p_mixer_ctrl_private.layer[layer].alpha);
s5p_mixer_set_grp_layer_dst_pos(layer,
@@ -299,7 +303,8 @@ void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer)
}
}
-int s5p_mixer_ctrl_set_pixel_format(enum s5p_mixer_layer layer, u32 bpp, u32 trans_len)
+int s5p_mixer_ctrl_set_pixel_format(
+ enum s5p_mixer_layer layer, u32 bpp, u32 trans_len)
{
enum s5p_mixer_color_fmt format;
@@ -322,7 +327,7 @@ int s5p_mixer_ctrl_set_pixel_format(enum s5p_mixer_layer layer, u32 bpp, u32 tra
s5p_mixer_ctrl_private.layer[layer].format = format;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -351,7 +356,7 @@ int s5p_mixer_ctrl_enable_layer(enum s5p_mixer_layer layer)
tvout_err("invalid layer\n");
return -1;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -384,7 +389,7 @@ int s5p_mixer_ctrl_disable_layer(enum s5p_mixer_layer layer)
return -1;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -523,7 +528,7 @@ int s5p_mixer_ctrl_set_dst_win_pos(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].dst_x = (u32)dst_x;
s5p_mixer_ctrl_private.layer[layer].dst_y = (u32)dst_y;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -551,7 +556,7 @@ int s5p_mixer_ctrl_set_src_win_pos(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].width = w;
s5p_mixer_ctrl_private.layer[layer].height = h;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -559,7 +564,8 @@ int s5p_mixer_ctrl_set_src_win_pos(enum s5p_mixer_layer layer,
#endif
{
if (s5p_mixer_ctrl_private.running)
- s5p_mixer_set_grp_layer_src_pos(layer, src_x, src_y, w, w, h);
+ s5p_mixer_set_grp_layer_src_pos(
+ layer, src_x, src_y, w, w, h);
}
return 0;
@@ -577,7 +583,7 @@ int s5p_mixer_ctrl_set_buffer_address(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].fb_addr = start_addr;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -602,7 +608,7 @@ int s5p_mixer_ctrl_set_chroma_key(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].chroma_enable = enabled;
s5p_mixer_ctrl_private.layer[layer].chroma_key = chroma.key;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -709,7 +715,7 @@ int s5p_mixer_ctrl_set_alpha_blending(enum s5p_mixer_layer layer,
case PIXEL_BLENDING:
tvout_dbg("pixel blending\n");
s5p_mixer_ctrl_private.layer[layer].pixel_blend = true;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -723,7 +729,7 @@ int s5p_mixer_ctrl_set_alpha_blending(enum s5p_mixer_layer layer,
tvout_dbg("layer blending : alpha value = 0x%x\n", alpha);
s5p_mixer_ctrl_private.layer[layer].layer_blend = true;
s5p_mixer_ctrl_private.layer[layer].alpha = alpha;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -739,7 +745,7 @@ int s5p_mixer_ctrl_set_alpha_blending(enum s5p_mixer_layer layer,
tvout_dbg("alpha blending off\n");
s5p_mixer_ctrl_private.layer[layer].pixel_blend = false;
s5p_mixer_ctrl_private.layer[layer].layer_blend = false;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -780,7 +786,7 @@ int s5p_mixer_ctrl_scaling(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].ver = scaling.ver;
s5p_mixer_ctrl_private.layer[layer].hor = scaling.hor;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -796,7 +802,8 @@ int s5p_mixer_ctrl_mux_clk(struct clk *ptr)
{
if (clk_set_parent(s5p_mixer_ctrl_private.clk[MUX].ptr, ptr)) {
tvout_err("unable to set parent %s of clock %s.\n",
- ptr->name, s5p_mixer_ctrl_private.clk[MUX].ptr->name);
+ ptr->name,
+ s5p_mixer_ctrl_private.clk[MUX].ptr->name);
return -1;
}
@@ -828,6 +835,12 @@ bool s5p_mixer_ctrl_get_vsync_interrupt()
return s5p_mixer_ctrl_private.vsync_interrupt_enable;
}
+void s5p_mixer_ctrl_disable_vsync_interrupt()
+{
+ if (s5p_mixer_ctrl_private.running)
+ s5p_mixer_set_vsync_interrupt(false);
+}
+
void s5p_mixer_ctrl_clear_pend_all(void)
{
if (s5p_mixer_ctrl_private.running)
@@ -840,7 +853,7 @@ void s5p_mixer_ctrl_stop(void)
tvout_dbg("running(%d)\n", s5p_mixer_ctrl_private.running);
if (s5p_mixer_ctrl_private.running) {
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -848,11 +861,12 @@ void s5p_mixer_ctrl_stop(void)
{
s5p_mixer_set_vsync_interrupt(false);
- for (i = 0; i < S5PTV_VP_BUFF_CNT -1; i++)
+ for (i = 0; i < S5PTV_VP_BUFF_CNT-1; i++)
s5ptv_vp_buff.copy_buff_idxs[i] = i;
s5ptv_vp_buff.curr_copy_idx = 0;
- s5ptv_vp_buff.vp_access_buff_idx = S5PTV_VP_BUFF_CNT - 1;
+ s5ptv_vp_buff.vp_access_buff_idx =
+ S5PTV_VP_BUFF_CNT - 1;
s5p_mixer_stop();
s5p_mixer_ctrl_clock(0);
@@ -1006,10 +1020,24 @@ int s5p_mixer_ctrl_start(
s5p_mixer_init_csc_coef_default(csc_for_coeff);
s5p_mixer_init_display_mode(disp, out, csc);
+#ifndef __CONFIG_HDMI_SUPPORT_FULL_RANGE__
if (!s5p_tvif_get_q_range() || out == TVOUT_HDMI_RGB)
mixer_video_limiter = true;
else
mixer_video_limiter = false;
+#else
+ /* full range */
+ if ((out == TVOUT_HDMI_RGB && disp == TVOUT_480P_60_4_3) ||
+ (out != TVOUT_HDMI_RGB && s5p_tvif_get_q_range())) {
+ mixer_video_limiter = false;
+ for (i = MIXER_BG_COLOR_0; i <= MIXER_BG_COLOR_2; i++)
+ s5p_mixer_ctrl_private.bg_color[i].color_y = 0;
+ } else { /* limited range */
+ mixer_video_limiter = true;
+ for (i = MIXER_BG_COLOR_0; i <= MIXER_BG_COLOR_2; i++)
+ s5p_mixer_ctrl_private.bg_color[i].color_y = 16;
+ }
+#endif
s5p_mixer_set_video_limiter(s5p_mixer_ctrl_private.v_layer.y_min,
s5p_mixer_ctrl_private.v_layer.y_max,
diff --git a/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c b/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
index 93cb640..43e7a1f 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
@@ -49,6 +49,12 @@
#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
#include <mach/dev.h>
#endif
+#include <mach/regs-hdmi.h>
+
+#ifdef CONFIG_HDMI_TX_STRENGTH
+#include <plat/tvout.h>
+#endif
+
#include "s5p_tvout_common_lib.h"
#include "hw_if/hw_if.h"
@@ -1758,7 +1764,7 @@ static void s5p_sdo_ctrl_clock(bool on)
#ifdef CONFIG_ARCH_EXYNOS4
s5p_tvout_pm_runtime_get();
#endif
- // Restore sdo_base address
+ /* Restore sdo_base address */
s5p_sdo_init(s5p_sdo_ctrl_private.reg_mem.base);
clk_enable(s5p_sdo_ctrl_private.clk[SDO_PCLK].ptr);
@@ -1771,7 +1777,7 @@ static void s5p_sdo_ctrl_clock(bool on)
clk_disable(s5p_sdo_ctrl_private.clk[SDO_MUX].ptr);
- // Set sdo_base address to NULL
+ /* Set sdo_base address to NULL */
s5p_sdo_init(NULL);
}
@@ -2362,8 +2368,10 @@ static void s5p_hdmi_ctrl_internal_stop(void)
#ifdef CONFIG_HDMI_HPD
s5p_hpd_set_eint();
#endif
- if (ctrl->hdcp_en)
+ if (ctrl->hdcp_en) {
s5p_hdcp_stop();
+ s5p_hdcp_flush_work();
+ }
s5p_hdmi_reg_enable(false);
@@ -2376,10 +2384,16 @@ int s5p_hdmi_ctrl_phy_power(bool on)
if (on) {
/* on */
clk_enable(s5ptv_status.i2c_phy_clk);
- // Restore i2c_hdmi_phy_base address
+ /* Restore i2c_hdmi_phy_base address */
s5p_hdmi_phy_init(s5p_hdmi_ctrl_private.reg_mem[HDMI_PHY].base);
s5p_hdmi_phy_power(true);
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ if (s5p_tvif_ctrl_private.tx_val)
+ s5p_hdmi_phy_set_tx_strength(
+ s5p_tvif_ctrl_private.tx_ch,
+ s5p_tvif_ctrl_private.tx_val);
+#endif
} else {
/*
@@ -2398,7 +2412,7 @@ int s5p_hdmi_ctrl_phy_power(bool on)
s5p_hdmi_phy_power(false);
clk_disable(s5ptv_status.i2c_phy_clk);
- // Set i2c_hdmi_phy_base to NULL
+ /* Set i2c_hdmi_phy_base to NULL */
s5p_hdmi_phy_init(NULL);
}
@@ -2419,7 +2433,7 @@ void s5p_hdmi_ctrl_clock(bool on)
#endif
clk_enable(clk[HDMI_PCLK].ptr);
- // Restore hdmi_base address
+ /* Restore hdmi_base address */
s5p_hdmi_init(s5p_hdmi_ctrl_private.reg_mem[HDMI].base);
} else {
clk_disable(clk[HDMI_PCLK].ptr);
@@ -2430,7 +2444,7 @@ void s5p_hdmi_ctrl_clock(bool on)
clk_disable(clk[HDMI_MUX].ptr);
- // Set hdmi_base to NULL
+ /* Set hdmi_base to NULL */
s5p_hdmi_init(NULL);
}
}
@@ -2447,7 +2461,7 @@ void s5p_hdmi_ctrl_stop(void)
tvout_dbg("running(%d)\n", ctrl->running);
if (ctrl->running) {
ctrl->running = false;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -2681,7 +2695,7 @@ static int s5p_tvif_ctrl_internal_stop(void)
case TVOUT_HDMI:
case TVOUT_HDMI_RGB:
s5p_hdmi_ctrl_stop();
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -2705,6 +2719,10 @@ static void s5p_tvif_ctrl_internal_start(
enum s5p_tvout_o_mode inf)
{
tvout_dbg("\n");
+#ifdef __CONFIG_HDMI_SUPPORT_FULL_RANGE__
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+#endif
s5p_mixer_ctrl_set_int_enable(false);
/* Clear All Interrupt Pending */
@@ -2724,6 +2742,47 @@ static void s5p_tvif_ctrl_internal_start(
case TVOUT_HDMI:
case TVOUT_HDMI_RGB:
case TVOUT_DVI:
+#ifdef __CONFIG_HDMI_SUPPORT_FULL_RANGE__
+ switch (std) {
+ case TVOUT_480P_60_4_3:
+ if (inf == TVOUT_HDMI_RGB) /* full range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+ else if (s5p_tvif_get_q_range()) /* full range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+ else /* limited range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_YPBPR;
+ break;
+ case TVOUT_480P_60_16_9:
+ case TVOUT_480P_59:
+ case TVOUT_576P_50_16_9:
+ case TVOUT_576P_50_4_3:
+ case TVOUT_720P_60:
+ case TVOUT_720P_50:
+ case TVOUT_720P_59:
+ case TVOUT_1080I_60:
+ case TVOUT_1080I_59:
+ case TVOUT_1080I_50:
+ case TVOUT_1080P_60:
+ case TVOUT_1080P_30:
+ case TVOUT_1080P_59:
+ case TVOUT_1080P_50:
+ if (inf == TVOUT_HDMI_RGB) /* limited range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_RGB;
+ else if (s5p_tvif_get_q_range()) /* full range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+ else /* limited range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_YPBPR;
+ break;
+ default:
+ break;
+ }
+#endif
s5p_hdmi_ctrl_phy_power(1);
if (s5p_mixer_ctrl_start(std, inf) < 0)
@@ -2854,7 +2913,7 @@ int s5p_tvif_ctrl_start(
goto cannot_change;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -2889,6 +2948,16 @@ void s5p_tvif_ctrl_stop(void)
int s5p_tvif_ctrl_constructor(struct platform_device *pdev)
{
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ struct s5p_platform_tvout *pdata = to_tvout_plat(&pdev->dev);
+ s5p_tvif_ctrl_private.tx_ch = 0x00;
+ s5p_tvif_ctrl_private.tx_val = NULL;
+ if ((pdata) && (pdata->tx_tune)) {
+ s5p_tvif_ctrl_private.tx_ch = pdata->tx_tune->tx_ch;
+ s5p_tvif_ctrl_private.tx_val = pdata->tx_tune->tx_val;
+ }
+#endif
+
#ifdef CONFIG_ANALOG_TVENC
if (s5p_sdo_ctrl_constructor(pdev))
goto err;
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout.c b/drivers/media/video/samsung/tvout/s5p_tvout.c
index 7407670..5f00ebc 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
+#include <linux/delay.h>
#if defined(CONFIG_S5P_SYSMMU_TV)
#include <plat/sysmmu.h>
@@ -25,6 +26,10 @@
#include <mach/media.h>
#endif
+#if defined(CONFIG_HDMI_TX_STRENGTH) && !defined(CONFIG_USER_ALLOC_TVOUT)
+#include <plat/tvout.h>
+#endif
+
#include "s5p_tvout_common_lib.h"
#include "s5p_tvout_ctrl.h"
#include "s5p_tvout_fb.h"
@@ -291,6 +296,12 @@ static int __devinit s5p_tvout_probe(struct platform_device *pdev)
struct device *hdmi_audio_dev;
#endif
+#if defined(CONFIG_HDMI_TX_STRENGTH) && !defined(CONFIG_USER_ALLOC_TVOUT)
+ struct s5p_platform_tvout *pdata;
+ u8 tx_ch;
+ u8 *tx_val;
+#endif
+
#ifdef CONFIG_TVOUT_DEBUG
struct class *sec_tvout;
tvout_dbg_flag = 1 << DBG_FLAG_HPD;
@@ -339,6 +350,15 @@ static int __devinit s5p_tvout_probe(struct platform_device *pdev)
s5p_hdmi_phy_power(true);
if (s5p_tvif_ctrl_start(TVOUT_720P_60, TVOUT_HDMI) < 0)
goto err_tvif_start;
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ pdata = to_tvout_plat(&pdev->dev);
+ if (pdata && pdata->tx_tune) {
+ tx_ch = pdata->tx_tune->tx_ch;
+ tx_val = pdata->tx_tune->tx_val;
+ }
+ if (tx_ch && tx_val)
+ s5p_hdmi_phy_set_tx_strength(tx_ch, tx_val);
+#endif
#endif
/* prepare memory */
@@ -495,14 +515,19 @@ static int s5p_tvout_remove(struct platform_device *pdev)
static void s5p_tvout_early_suspend(struct early_suspend *h)
{
tvout_dbg("\n");
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
mutex_lock(&s5p_tvout_mutex);
- s5p_mixer_ctrl_set_vsync_interrupt(false);
+ /* disable vsync interrupt during early suspend */
+ s5p_mixer_ctrl_disable_vsync_interrupt();
s5p_vp_ctrl_suspend();
s5p_mixer_ctrl_suspend();
s5p_tvif_ctrl_suspend();
suspend_status = 1;
tvout_dbg("suspend_status is true\n");
mutex_unlock(&s5p_tvout_mutex);
+#else
+ suspend_status = 1;
+#endif
return;
}
@@ -511,6 +536,7 @@ static void s5p_tvout_late_resume(struct early_suspend *h)
{
tvout_dbg("\n");
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
mutex_lock(&s5p_tvout_mutex);
#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412)
@@ -521,11 +547,17 @@ static void s5p_tvout_late_resume(struct early_suspend *h)
#endif
suspend_status = 0;
tvout_dbg("suspend_status is false\n");
+
s5p_tvif_ctrl_resume();
s5p_mixer_ctrl_resume();
s5p_vp_ctrl_resume();
- s5p_mixer_ctrl_set_vsync_interrupt(s5p_mixer_ctrl_get_vsync_interrupt());
+ /* restore vsync interrupt setting */
+ s5p_mixer_ctrl_set_vsync_interrupt(
+ s5p_mixer_ctrl_get_vsync_interrupt());
mutex_unlock(&s5p_tvout_mutex);
+#else
+ suspend_status = 0;
+#endif
return;
}
@@ -562,8 +594,10 @@ static int s5p_tvout_suspend(struct device *dev)
static int s5p_tvout_resume(struct device *dev)
{
tvout_dbg("\n");
+#if defined(CLOCK_GATING_ON_EARLY_SUSPEND)
#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412)
flag_after_resume = true;
+#endif
#else
queue_work_on(0, tvout_resume_wq, &tvout_resume_work);
#endif
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h b/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h
index e43b9c7..467ab1d 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h
@@ -45,6 +45,12 @@ do { \
#endif
#endif
+/*
+#if defined(CONFIG_MACH_T0) || defined(CONFIG_MACH_M3)
+#define __CONFIG_HDMI_SUPPORT_FULL_RANGE__
+#endif
+*/
+
#define S5PTV_FB_CNT 2
#define S5PTV_VP_BUFF_CNT 4
#define S5PTV_VP_BUFF_SIZE (4*1024*1024)
@@ -53,6 +59,10 @@ do { \
#define HDMI_START_NUM 0x1000
+#ifdef CONFIG_CPU_EXYNOS4210
+#define CLOCK_GATING_ON_EARLY_SUSPEND
+#endif
+
enum s5p_tvout_disp_mode {
TVOUT_NTSC_M = 0,
TVOUT_PAL_BDGHI,
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h b/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h
index 43043b4..b330a95 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h
@@ -29,7 +29,8 @@
extern void s5p_mixer_ctrl_init_fb_addr_phy(enum s5p_mixer_layer layer,
dma_addr_t fb_addr);
extern void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer);
-extern int s5p_mixer_ctrl_set_pixel_format(enum s5p_mixer_layer layer, u32 bpp, u32 trans_len);
+extern int s5p_mixer_ctrl_set_pixel_format(
+ enum s5p_mixer_layer layer, u32 bpp, u32 trans_len);
extern int s5p_mixer_ctrl_enable_layer(enum s5p_mixer_layer layer);
extern int s5p_mixer_ctrl_disable_layer(enum s5p_mixer_layer layer);
extern int s5p_mixer_ctrl_set_priority(enum s5p_mixer_layer layer, u32 prio);
@@ -52,6 +53,7 @@ extern int s5p_mixer_ctrl_mux_clk(struct clk *ptr);
extern void s5p_mixer_ctrl_set_int_enable(bool en);
extern void s5p_mixer_ctrl_set_vsync_interrupt(bool en);
extern bool s5p_mixer_ctrl_get_vsync_interrupt(void);
+extern void s5p_mixer_ctrl_disable_vsync_interrupt(void);
extern void s5p_mixer_ctrl_clear_pend_all(void);
extern void s5p_mixer_ctrl_stop(void);
extern void s5p_mixer_ctrl_internal_start(void);
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_fb.c b/drivers/media/video/samsung/tvout/s5p_tvout_fb.c
index 5a2ce5a..c0a3508 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_fb.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_fb.c
@@ -303,7 +303,7 @@ static int s5p_tvout_fb_blank(int blank_mode, struct fb_info *fb)
tvout_dbg("change blank mode\n");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
switch (fb->node) {
@@ -336,12 +336,12 @@ static int s5p_tvout_fb_blank(int blank_mode, struct fb_info *fb)
goto err_fb_blank;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 1;
err_fb_blank:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
@@ -356,7 +356,7 @@ static int s5p_tvout_fb_set_par(struct fb_info *fb)
tvout_dbg("[fb%d] set_par\n", win->id);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
if (!fb->fix.smem_start) {
@@ -390,7 +390,7 @@ static int s5p_tvout_fb_set_par(struct fb_info *fb)
s5p_mixer_ctrl_set_src_win_pos(layer, src_x, src_y, w, h);
s5p_mixer_ctrl_set_alpha_blending(layer, win->alpha.mode,
win->alpha.value);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -472,7 +472,7 @@ static int s5p_tvout_fb_ioctl(struct fb_info *fb, unsigned int cmd,
} p;
tvout_dbg("\n");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
switch (fb->node) {
@@ -552,13 +552,13 @@ static int s5p_tvout_fb_ioctl(struct fb_info *fb, unsigned int cmd,
s5p_mixer_ctrl_scaling(layer, p.user_scaling);
break;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
err_fb_ioctl:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c b/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c
index 4f35a91..1c98453 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c
@@ -67,6 +67,12 @@ struct hpd_struct {
#endif
};
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+static work_func_t ext_ic_control_func(void) ;
+static DECLARE_DELAYED_WORK(ext_ic_control_dwork,
+ (work_func_t)ext_ic_control_func);
+#endif
+
static struct hpd_struct hpd_struct;
static int last_hpd_state;
@@ -81,6 +87,10 @@ static ssize_t s5p_hpd_read(struct file *file, char __user *buffer,
static unsigned int s5p_hpd_poll(struct file *file, poll_table *wait);
static long s5p_hpd_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
+void mhl_hpd_handler(bool onoff);
+bool (*is_mhl_power_state_on)(void);
+#endif
static const struct file_operations hpd_fops = {
.owner = THIS_MODULE,
@@ -139,6 +149,7 @@ static void s5p_hpd_kobject_uevent(void)
if (hpd_state) {
if (last_uevent_state == -1 || last_uevent_state == HPD_LO) {
#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ HPDPRINTK("ext_ic power ON\n");
hpd_struct.ext_ic_control(true);
msleep(20);
#endif
@@ -154,9 +165,13 @@ static void s5p_hpd_kobject_uevent(void)
KOBJ_CHANGE, envp);
#endif
HPDPRINTK("[HDMI] HPD event -connect!!!\n");
- on_start_process = true;
+ if (atomic_read(&hdmi_status) == HDMI_OFF) {
+ on_start_process = true;
+ } else {
+ on_start_process = false;
+ }
HPDIFPRINTK("%s() on_start_process(%d)\n",
- __func__, on_start_process);
+ __func__, on_start_process);
}
last_uevent_state = HPD_HI;
} else {
@@ -176,10 +191,14 @@ static void s5p_hpd_kobject_uevent(void)
KOBJ_CHANGE, envp);
#endif
HPDPRINTK("[HDMI] HPD event -disconnet!!!\n");
- on_stop_process = true;
-#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
- hpd_struct.ext_ic_control(false);
-#endif
+ if (atomic_read(&hdmi_status) == HDMI_ON) {
+ on_stop_process = true;
+ } else {
+ on_stop_process = false;
+ }
+ HPDIFPRINTK("%s() on_stop_process(%d)\n",
+ __func__, on_stop_process);
+
}
last_uevent_state = HPD_LO;
}
@@ -233,9 +252,16 @@ static unsigned int s5p_hpd_poll(struct file *file, poll_table * wait)
void hdmi_send_audio_ch_num(
int supported_ch_num, struct switch_dev *p_audio_ch_switch)
{
- printk(KERN_INFO "%s() hdmi_send_audio_ch_num :: "
- "HDMI Audio supported ch = %d",
- __func__, supported_ch_num);
+ if (last_uevent_state == HPD_LO) {
+ printk(KERN_INFO "[WARNING] %s() "
+ "HDMI Audio ch = %d but not send\n",
+ __func__, supported_ch_num);
+ return;
+ } else
+ printk(KERN_INFO "%s() "
+ "HDMI Audio ch = %d\n",
+ __func__, supported_ch_num);
+
p_audio_ch_switch->state = 0;
switch_set_state(p_audio_ch_switch, (int)supported_ch_num);
}
@@ -366,7 +392,16 @@ static int s5p_hpd_irq_eint(int irq)
atomic_set(&poll_state, 1);
last_hpd_state = HPD_LO;
+#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
+ if (is_mhl_power_state_on != NULL)
+ if (!is_mhl_power_state_on())
+ mhl_hpd_handler(false);
+#endif
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ schedule_delayed_work(&ext_ic_control_dwork ,
+ msecs_to_jiffies(1000));
+#endif
wake_up_interruptible(&hpd_struct.waitq);
}
schedule_work(&hpd_work);
@@ -438,6 +473,15 @@ static int s5p_hpd_irq_hdmi(int irq)
atomic_set(&poll_state, 1);
last_hpd_state = HPD_LO;
+#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
+ if (is_mhl_power_state_on != NULL)
+ if (!is_mhl_power_state_on())
+ mhl_hpd_handler(false);
+#endif
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ schedule_delayed_work(&ext_ic_control_dwork ,
+ msecs_to_jiffies(1000));
+#endif
wake_up_interruptible(&hpd_struct.waitq);
}
@@ -474,6 +518,20 @@ static irqreturn_t s5p_hpd_irq_handler(int irq, void *dev_id)
return ret;
}
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+static work_func_t ext_ic_control_func(void)
+{
+ if (!hpd_struct.read_gpio()) {
+ hpd_struct.ext_ic_control(false);
+ HPDPRINTK("HDMI_EXT_IC Power Off\n");
+ } else {
+ HPDPRINTK("HDMI_EXT_IC Delay work do nothing\n");
+ }
+ return 0;
+}
+#endif
+
+
#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
static irqreturn_t s5p_hpd_irq_default_handler(int irq, void *dev_id)
{
@@ -566,6 +624,9 @@ static int __devinit s5p_hpd_probe(struct platform_device *pdev)
if (hpd_struct.read_gpio()) {
atomic_set(&hpd_struct.state, HPD_HI);
last_hpd_state = HPD_HI;
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ hpd_struct.ext_ic_control(true);
+#endif
} else {
atomic_set(&hpd_struct.state, HPD_LO);
last_hpd_state = HPD_LO;
@@ -575,6 +636,7 @@ static int __devinit s5p_hpd_probe(struct platform_device *pdev)
hpd_struct.hpd_switch.name = "hdmi";
switch_dev_register(&hpd_struct.hpd_switch);
#endif
+ switch_set_state(&hpd_struct.hpd_switch, last_hpd_state);
irq_set_irq_type(hpd_struct.irq_n, IRQ_TYPE_EDGE_BOTH);
ret = request_irq(hpd_struct.irq_n, (irq_handler_t) s5p_hpd_irq_handler,
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
index 68508e7..3fa6e55 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
@@ -369,7 +369,7 @@ static int s5p_tvout_tvif_s_std(
int i;
v4l2_std_id std_id = *norm;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
for (i = 0; i < S5P_TVOUT_TVIF_NO_OF_STANDARD; i++) {
@@ -379,7 +379,8 @@ static int s5p_tvout_tvif_s_std(
if (i == S5P_TVOUT_TVIF_NO_OF_STANDARD) {
tvout_err("There is no TV standard(0x%08Lx)\n", std_id);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -EINVAL;
@@ -390,7 +391,7 @@ static int s5p_tvout_tvif_s_std(
tvout_dbg("standard id=0x%X, name=\"%s\"\n",
(u32) std_id, s5p_tvout_tvif_standard[i].name);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
@@ -437,7 +438,7 @@ static int s5p_tvout_tvif_s_output(
return -EINVAL;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND)
s5p_tvout_mutex_lock();
#endif
on_start_process = true;
@@ -582,12 +583,12 @@ static int s5p_tvout_tvif_s_output(
s5p_tvif_ctrl_start(tv_std, tv_if);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
error_on_tvif_s_output:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
@@ -749,7 +750,7 @@ long s5p_tvout_tvif_ioctl(
void *argp = (void *) arg;
int i = 0;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
@@ -916,13 +917,13 @@ long s5p_tvout_tvif_ioctl(
break;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return video_ioctl2(file, cmd, arg);
end_tvif_ioctl:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return ret;
@@ -1035,7 +1036,7 @@ static int s5p_tvout_vo_s_fmt_type_private(
(u32) vparam.base_y, (u32) vparam.base_c,
pix_fmt->field);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
/* check progressive or not */
@@ -1133,52 +1134,72 @@ static int s5p_tvout_vo_s_fmt_type_private(
pix_fmt->height, color, field);
#else
if (pix_fmt->priv) {
- copy_buff_idx = s5ptv_vp_buff.copy_buff_idxs[s5ptv_vp_buff.curr_copy_idx];
-
- if ((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base == NULL) {
- s5p_vp_ctrl_set_src_plane((u32) vparam.base_y, (u32) vparam.base_c,
- pix_fmt->width, pix_fmt->height, color, field);
+ copy_buff_idx =
+ s5ptv_vp_buff.
+ copy_buff_idxs[s5ptv_vp_buff.curr_copy_idx];
+
+ if ((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base
+ == NULL) {
+ s5p_vp_ctrl_set_src_plane(
+ (u32) vparam.base_y, (u32) vparam.base_c,
+ pix_fmt->width, pix_fmt->height, color, field);
} else {
- if (pix_fmt->pixelformat == V4L2_PIX_FMT_NV12T
- || pix_fmt->pixelformat == V4L2_PIX_FMT_NV21T) {
- y_size = ALIGN(ALIGN(pix_fmt->width, 128) * ALIGN(pix_fmt->height, 32), SZ_8K);
- cbcr_size = ALIGN(ALIGN(pix_fmt->width, 128) * ALIGN(pix_fmt->height >> 1, 32), SZ_8K);
+ if (pix_fmt->pixelformat ==
+ V4L2_PIX_FMT_NV12T
+ || pix_fmt->pixelformat == V4L2_PIX_FMT_NV21T) {
+ y_size = ALIGN(ALIGN(pix_fmt->width, 128) *
+ ALIGN(pix_fmt->height, 32), SZ_8K);
+ cbcr_size = ALIGN(ALIGN(pix_fmt->width, 128) *
+ ALIGN(pix_fmt->height >> 1, 32), SZ_8K);
} else {
y_size = pix_fmt->width * pix_fmt->height;
- cbcr_size = pix_fmt->width * (pix_fmt->height >> 1);
+ cbcr_size =
+ pix_fmt->width * (pix_fmt->height >> 1);
}
- src_vir_y_addr = (unsigned int)phys_to_virt((unsigned long)vparam.base_y);
- src_vir_cb_addr = (unsigned int)phys_to_virt((unsigned long)vparam.base_c);
+ src_vir_y_addr = (unsigned int)phys_to_virt(
+ (unsigned long)vparam.base_y);
+ src_vir_cb_addr = (unsigned int)phys_to_virt(
+ (unsigned long)vparam.base_c);
- memcpy((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base,
- (void *)src_vir_y_addr, y_size);
- memcpy((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base + y_size,
- (void *)src_vir_cb_addr, cbcr_size);
+ memcpy(
+ (void *)
+ s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base,
+ (void *)src_vir_y_addr, y_size);
+ memcpy(
+ (void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].
+ vir_base + y_size,
+ (void *)src_vir_cb_addr, cbcr_size);
flush_all_cpu_caches();
outer_flush_all();
- s5p_vp_ctrl_set_src_plane((u32) s5ptv_vp_buff.vp_buffs[copy_buff_idx].phy_base,
- (u32) s5ptv_vp_buff.vp_buffs[copy_buff_idx].phy_base + y_size,
- pix_fmt->width, pix_fmt->height, color, field);
+ s5p_vp_ctrl_set_src_plane(
+ (u32) s5ptv_vp_buff.
+ vp_buffs[copy_buff_idx].phy_base,
+ (u32) s5ptv_vp_buff.
+ vp_buffs[copy_buff_idx].phy_base
+ + y_size,
+ pix_fmt->width, pix_fmt->height, color, field);
s5ptv_vp_buff.curr_copy_idx++;
- if (s5ptv_vp_buff.curr_copy_idx >= S5PTV_VP_BUFF_CNT - 1)
+ if (s5ptv_vp_buff.curr_copy_idx >=
+ S5PTV_VP_BUFF_CNT - 1)
s5ptv_vp_buff.curr_copy_idx = 0;
}
} else {
- s5p_vp_ctrl_set_src_plane((u32) vparam.base_y, (u32) vparam.base_c,
- pix_fmt->width, pix_fmt->height, color, field);
+ s5p_vp_ctrl_set_src_plane(
+ (u32) vparam.base_y, (u32) vparam.base_c,
+ pix_fmt->width, pix_fmt->height, color, field);
}
#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
error_on_s_fmt_type_private:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
@@ -1201,7 +1222,7 @@ static int s5p_tvout_vo_s_fmt_vid_overlay(
rect->left, rect->top, rect->width, rect->height,
a->fmt.win.global_alpha);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
s5p_tvout_v4l2_private.vo_dst_fmt = a->fmt.win;
@@ -1211,7 +1232,7 @@ static int s5p_tvout_vo_s_fmt_vid_overlay(
rect->left, rect->top,
rect->width, rect->height);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -1237,7 +1258,7 @@ static int s5p_tvout_vo_s_crop(
struct file *file, void *fh, struct v4l2_crop *a)
{
tvout_dbg("\n");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
switch (a->type) {
@@ -1260,7 +1281,7 @@ static int s5p_tvout_vo_s_crop(
tvout_err("Invalid buf type(0x%08x)\n", a->type);
break;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -1285,7 +1306,7 @@ static int s5p_tvout_vo_s_fbuf(
(a->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) ? 1 : 0,
a->fmt.priv);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
@@ -1294,7 +1315,7 @@ static int s5p_tvout_vo_s_fbuf(
s5p_vp_ctrl_set_dest_win_priority(a->fmt.priv);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -1305,15 +1326,21 @@ static int s5p_tvout_vo_overlay(
{
tvout_dbg("%s\n", (i) ? "start" : "stop");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
- if (i)
+ if (i) {
s5p_vp_ctrl_start();
- else
+ /* restore vsync interrupt setting */
+ s5p_mixer_set_vsync_interrupt(
+ s5p_mixer_ctrl_get_vsync_interrupt());
+ } else {
+ /* disable vsync interrupt when VP is disabled */
+ s5p_mixer_ctrl_disable_vsync_interrupt();
s5p_vp_ctrl_stop();
+ }
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
diff --git a/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c b/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c
index d074da3..148e3e9 100644
--- a/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c
+++ b/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c
@@ -279,7 +279,7 @@ static int s5p_vp_ctrl_set_reg(void)
struct s5p_vp_ctrl_pp_param *pp_param = &s5p_vp_ctrl_private.pp_param;
struct s5p_vp_ctrl_op_mode *op_mode = &s5p_vp_ctrl_private.op_mode;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -362,7 +362,7 @@ static int s5p_vp_ctrl_set_reg(void)
static void s5p_vp_ctrl_internal_stop(void)
{
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -409,7 +409,7 @@ void s5p_vp_ctrl_set_src_plane(
src_plane->w = width;
src_plane->h = height;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -434,7 +434,7 @@ void s5p_vp_ctrl_set_src_win(u32 left, u32 top, u32 width, u32 height)
src_win->w = width;
src_win->h = height;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -466,7 +466,7 @@ void s5p_vp_ctrl_set_dest_win(u32 left, u32 top, u32 width, u32 height)
dst_win->y = top;
dst_win->w = width;
dst_win->h = height;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -493,7 +493,7 @@ void s5p_vp_ctrl_set_dest_win(u32 left, u32 top, u32 width, u32 height)
void s5p_vp_ctrl_set_dest_win_alpha_val(u32 alpha)
{
s5p_vp_ctrl_private.mixer_param.alpha = alpha;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -505,7 +505,7 @@ void s5p_vp_ctrl_set_dest_win_alpha_val(u32 alpha)
void s5p_vp_ctrl_set_dest_win_blend(bool enable)
{
s5p_vp_ctrl_private.mixer_param.blend = enable;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -518,7 +518,7 @@ void s5p_vp_ctrl_set_dest_win_blend(bool enable)
void s5p_vp_ctrl_set_dest_win_priority(u32 prio)
{
s5p_vp_ctrl_private.mixer_param.prio = prio;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -531,7 +531,7 @@ void s5p_vp_ctrl_stop(void)
{
if (s5p_vp_ctrl_private.running) {
s5p_vp_ctrl_internal_stop();
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -647,7 +647,7 @@ int s5p_vp_ctrl_start(void)
if (s5p_vp_ctrl_private.running)
s5p_vp_ctrl_internal_stop();
else {
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
diff --git a/drivers/media/video/samsung/ump/Kconfig b/drivers/media/video/samsung/ump/Kconfig
index aaae26e..6304825 100644
--- a/drivers/media/video/samsung/ump/Kconfig
+++ b/drivers/media/video/samsung/ump/Kconfig
@@ -20,7 +20,7 @@ config UMP_VCM_ALLOC
choice
depends on VIDEO_UMP
prompt "UMP MEMEMORY OPTION"
-default UMP_OSMEM_ONLY
+default UMP_OSMEM_ONLY
config UMP_DED_ONLY
bool "ump dedicated memory only"
---help---
@@ -37,7 +37,7 @@ config UMP_VCM_ONLY
endchoice
config UMP_MEM_SIZE
int "UMP Memory Size"
- depends on VIDEO_UMP
+ depends on VIDEO_UMP
default "512"
---help---
This value is dedicated memory size of UMP (unit is MByte).
@@ -48,4 +48,3 @@ config VIDEO_UMP_DEBUG
default n
help
This enables UMP driver debug messages.
-
diff --git a/drivers/media/video/samsung/ump/Makefile b/drivers/media/video/samsung/ump/Makefile
index f429c40..b3157a3 100644
--- a/drivers/media/video/samsung/ump/Makefile
+++ b/drivers/media/video/samsung/ump/Makefile
@@ -1,9 +1,9 @@
#
# 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.
#
@@ -30,14 +30,13 @@ DEFINES += -DDEBUG
endif
# Set up our defines, which will be passed to gcc
-DEFINES += -DKERNEL_BUILTIN=1
DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER
DEFINES += -DUSING_MEMORY=$(USING_MEMORY)
DEFINES += -DUMP_MEM_SIZE=$(UMP_MEM_SIZE)
DEFINES += -DMALI_STATE_TRACKING=1
UDD_FILE_PREFIX := drivers/media/video/samsung/ump/
-KBUILDROOT =
+KBUILDROOT =
# linux build system integration
@@ -61,7 +60,7 @@ OSKFILES+=\
$(KBUILDROOT)../mali/linux/mali_osk_locks.o \
$(KBUILDROOT)../mali/linux/mali_osk_math.o \
$(KBUILDROOT)../mali/linux/mali_osk_memory.o \
- $(KBUILDROOT)../mali/linux/mali_osk_misc.o
+ $(KBUILDROOT)../mali/linux/mali_osk_misc.o
ump-y := \
$(KBUILDROOT)linux/ump_kernel_linux.o \
@@ -83,12 +82,11 @@ ump-$(CONFIG_UMP_VCM_ALLOC) += \
$(KBUILDROOT)linux/ump_kernel_memory_backend_vcm.o \
EXTRA_CFLAGS += $(INCLUDES) \
- $(DEFINES)
-
-
+ $(DEFINES)
+
+
# Get subversion revision number, fall back to 0000 if no svn info is available
SVN_REV:=$(shell ((svnversion | grep -qv exported && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //')
-
+
EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV)
EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\"
-
diff --git a/drivers/media/video/samsung/ump/Makefile.common b/drivers/media/video/samsung/ump/Makefile.common
index 4b5db24..35527a2 100644
--- a/drivers/media/video/samsung/ump/Makefile.common
+++ b/drivers/media/video/samsung/ump/Makefile.common
@@ -1,17 +1,20 @@
#
-# Copyright (C) 2010 ARM Limited. All rights reserved.
-#
+# 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.
#
-UMP_FILE_PREFIX = ./drivers/video/samsung/ump
+SRC = $(UMP_FILE_PREFIX)common/ump_kernel_common.c \
+ $(UMP_FILE_PREFIX)common/ump_kernel_descriptor_mapping.c \
+ $(UMP_FILE_PREFIX)common/ump_kernel_api.c \
+ $(UMP_FILE_PREFIX)common/ump_kernel_ref_drv.c
-SRC = $(UMP_FILE_PREFIX)/common/ump_kernel_common.c \
- $(UMP_FILE_PREFIX)/common/ump_kernel_descriptor_mapping.c \
- $(UMP_FILE_PREFIX)/common/ump_kernel_api.c \
- $(UMP_FILE_PREFIX)/common/ump_kernel_ref_drv.c
+# Get subversion revision number, fall back to 0000 if no svn info is available
+SVN_REV:=$(shell ((svnversion | grep -qv exported && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //')
+EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV)
+EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\"
diff --git a/drivers/media/video/samsung/ump/Makefile_backup b/drivers/media/video/samsung/ump/Makefile_backup
deleted file mode 100644
index 632cb0c..0000000
--- a/drivers/media/video/samsung/ump/Makefile_backup
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# 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.
-#
-BUILD ?= debug
-USING_MALI400 ?= 1
-USING_ZBT ?= 0
-USING_MMU ?= 1
-USING_UMP ?= 1
-CPU ?= vega1
-CONFIG ?= marcopolo-vega1-m400
-
-
-# Set up our defines, which will be passed to gcc
-DEFINES += -DUSING_MALI400=$(USING_MALI400)
-DEFINES += -DUSING_ZBT=$(USING_ZBT)
-DEFINES += -DUSING_MMU=$(USING_MMU)
-DEFINES += -DUSING_UMP=$(USING_UMP)
-DEFINES += -DMALI_USE_UNIFIED_MEMORY_PROVIDER
-ifeq ($(BUILD), debug)
-DEFINES += -DDEBUG
-endif
-
-
-UMP_FILE_PREFIX := drivers/video/samsung/ump
-UDD_FILE_PREFIX := drivers/video/samsung/mali
-KBUILDROOT =
-
-# linux build system integration
-
-obj-y += ump.o
-
-# 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
-
-INCLUDES = \
- -I$(UMP_FILE_PREFIX)\
- -I$(UMP_FILE_PREFIX)/common\
- -I$(UMP_FILE_PREFIX)/linux\
- -I$(UMP_FILE_PREFIX)/include\
- -I$(UMP_FILE_PREFIX)/linux/license/proprietary/\
- -I$(UDD_FILE_PREFIX)/common\
- -I$(UDD_FILE_PREFIX)/linux
-
-ump-y := \
- $(KBUILDROOT)linux/ump_kernel_linux.o \
- $(KBUILDROOT)linux/ump_kernel_memory_backend_os.o \
- $(KBUILDROOT)linux/ump_kernel_memory_backend_dedicated.o \
- $(KBUILDROOT)linux/ump_memory_backend.o \
- $(KBUILDROOT)linux/ump_ukk_wrappers.o \
- $(KBUILDROOT)linux/ump_ukk_ref_wrappers.o \
- $(KBUILDROOT)linux/ump_osk_atomics.o \
- $(KBUILDROOT)linux/ump_osk_low_level_mem.o \
- $(KBUILDROOT)linux/ump_osk_misc.o \
- $(KBUILDROOT)../mali/linux/mali_osk_atomics.o \
- $(KBUILDROOT)../mali/linux/mali_osk_locks.o \
- $(KBUILDROOT)../mali/linux/mali_osk_memory.o \
- $(KBUILDROOT)../mali/linux/mali_osk_math.o \
- $(KBUILDROOT)../mali/linux/mali_osk_misc.o \
- $(KBUILDROOT)common/ump_kernel_common.o \
- $(KBUILDROOT)common/ump_kernel_descriptor_mapping.o \
- $(KBUILDROOT)common/ump_kernel_api.o \
- $(KBUILDROOT)common/ump_kernel_ref_drv.o
-
-EXTRA_CFLAGS += $(INCLUDES) \
- $(DEFINES)
-
-
-# Get subversion revision number, fall back to 0000 if no svn info is available
-SVN_REV:=$(shell ((svnversion | grep -qv exported && echo -n 'Revision: ' && svnversion) || git svn info | sed -e 's/$$$$/M/' | grep '^Revision: ' || echo ${MALI_RELEASE_NAME}) 2>/dev/null | sed -e 's/^Revision: //')
-
-EXTRA_CFLAGS += -DSVN_REV=$(SVN_REV)
-EXTRA_CFLAGS += -DSVN_REV_STRING=\"$(SVN_REV)\"
-
diff --git a/drivers/media/video/samsung/ump/Makefile_module b/drivers/media/video/samsung/ump/Makefile_module
new file mode 100644
index 0000000..f0c3829
--- /dev/null
+++ b/drivers/media/video/samsung/ump/Makefile_module
@@ -0,0 +1,119 @@
+#
+# 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.
+#
+
+UMP_FILE_PREFIX =
+UDD_FILE_PREFIX = ../mali/
+
+ifneq ($(KBUILD_EXTMOD),)
+include $(KBUILD_EXTMOD)/Makefile.common
+else
+include ./Makefile.common
+endif
+
+# For each arch check: CROSS_COMPILE , KDIR , CFLAGS += -DARCH
+
+ARCH ?= arm
+BUILD ?= debug
+
+EXTRA_CFLAGS += -DDEBUG -DMALI_STATE_TRACKING=0
+ifeq ($(BUILD), debug)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+# linux build system integration
+
+ifneq ($(KERNELRELEASE),)
+# Inside the kernel build system
+
+EXTRA_CFLAGS += -I$(KBUILD_EXTMOD) -I$(KBUILD_EXTMOD)/common -I$(KBUILD_EXTMOD)/linux -I$(KBUILD_EXTMOD)/../mali/common -I$(KBUILD_EXTMOD)/../mali/linux -I$(KBUILD_EXTMOD)/../../ump/include/ump
+
+# 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 $(KBUILD_EXTMOD)/linux/license/gpl/*),)
+EXTRA_CFLAGS += -I$(KBUILD_EXTMOD)/linux/license/proprietary
+else
+EXTRA_CFLAGS += -I$(KBUILD_EXTMOD)/linux/license/gpl
+endif
+
+SRC += $(UMP_FILE_PREFIX)linux/ump_kernel_linux.c \
+ $(UMP_FILE_PREFIX)linux/ump_kernel_memory_backend_os.c \
+ $(UMP_FILE_PREFIX)linux/ump_kernel_memory_backend_dedicated.c \
+ $(UMP_FILE_PREFIX)linux/ump_memory_backend.c \
+ $(UMP_FILE_PREFIX)linux/ump_ukk_wrappers.c \
+ $(UMP_FILE_PREFIX)linux/ump_ukk_ref_wrappers.c \
+ $(UMP_FILE_PREFIX)linux/ump_osk_atomics.c \
+ $(UMP_FILE_PREFIX)linux/ump_osk_low_level_mem.c \
+ $(UMP_FILE_PREFIX)linux/ump_osk_misc.c \
+ $(UDD_FILE_PREFIX)linux/mali_osk_atomics.c \
+ $(UDD_FILE_PREFIX)linux/mali_osk_locks.c \
+ $(UDD_FILE_PREFIX)linux/mali_osk_memory.c \
+ $(UDD_FILE_PREFIX)linux/mali_osk_math.c \
+ $(UDD_FILE_PREFIX)linux/mali_osk_misc.c
+
+# Selecting files to compile by parsing the config file
+
+MODULE:=ump.ko
+
+obj-m := $(MODULE:.ko=.o)
+$(MODULE:.ko=-y) := $(SRC:.c=.o)
+
+else
+# Outside the kernel build system
+
+# Check that required parameters are supplied.
+ifeq ($(CONFIG),)
+$(error "CONFIG must be specified.")
+endif
+ifeq ($(CPU)$(KDIR),)
+$(error "KDIR or CPU must be specified.")
+endif
+
+# Get any user defined KDIR-<names> or maybe even a hardcoded KDIR
+-include KDIR_CONFIGURATION
+
+# Define host system directory
+KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build
+
+ifeq ($(ARCH), arm)
+ # when compiling for ARM we're cross compiling
+ export CROSS_COMPILE ?= arm-none-linux-gnueabi-
+endif
+
+# look up KDIR based om CPU selection
+KDIR ?= $(KDIR-$(CPU))
+
+ifeq ($(KDIR),)
+$(error No KDIR found for platform $(CPU))
+endif
+
+# Validate selected config
+ifneq ($(shell [ -d arch-$(CONFIG) ] && [ -f arch-$(CONFIG)/config.h ] && echo "OK"), OK)
+$(warning Current directory is $(shell pwd))
+$(error No configuration found for config $(CONFIG). Check that arch-$(CONFIG)/config.h exists)
+else
+# Link arch to the selected arch-config directory
+$(shell [ -L arch ] && rm arch)
+$(shell ln -sf arch-$(CONFIG) arch)
+$(shell touch arch/config.h)
+endif
+
+all:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules
+
+kernelrelease:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease
+
+clean:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR)/../mali clean
+
+endif
diff --git a/drivers/media/video/samsung/ump/arch b/drivers/media/video/samsung/ump/arch
deleted file mode 120000
index a65a3fc..0000000
--- a/drivers/media/video/samsung/ump/arch
+++ /dev/null
@@ -1 +0,0 @@
-./arch-orion-m400 \ No newline at end of file
diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_pp.h b/drivers/media/video/samsung/ump/arch-debug/config.h
index 8cf7bf7..688edc9 100644
--- a/drivers/media/video/samsung/mali/common/mali_kernel_pp.h
+++ b/drivers/media/video/samsung/ump/arch-debug/config.h
@@ -1,21 +1,22 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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__
+#ifndef __ARCH_CONFIG_UMP_H__
+#define __ARCH_CONFIG_UMP_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 );
+#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY
+#if (USING_MEMORY == 0) /* Dedicated Memory */
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
+#else
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
#endif
-#endif /* __MALI_KERNEL_PP_H__ */
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024
+#endif /* __ARCH_CONFIG_UMP_H__ */
diff --git a/drivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h.org b/drivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h.org
deleted file mode 100755
index c92a32a..0000000
--- a/drivers/media/video/samsung/ump/arch-marcopolo-vega1-m400/config.h.org
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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 MALI_BASE_ADDR 0xf0000000
-#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 PP_MMU_ADDR MALI_BASE_ADDR+0x4000
-#define PP_ADDR MALI_BASE_ADDR+0x8000
-
-// See 3-11 page in trm. It describes control register address map. cglee
-
-static _mali_osk_resource_t arch_configuration [] =
-{
- {
- .type = MALI400GP,
- .description = "Mali-400 GP",
- .base = GP_ADDR,
- .irq = 18+32,
- .mmu_id = 1
- },
- {
- .type = MALI400PP,
- .base = PP_ADDR,
- .irq = 16+32,
- .description = "Mali-400 PP 0",
- .mmu_id = 2
- },
-#if USING_MMU
- {
- .type = MMU,
- .base = GP_MMU_ADDR,
- .irq = 19+32,
- .description = "Mali-400 MMU for GP",
- .mmu_id = 1
- },
- {
- .type = MMU,
- .base = PP_MMU_ADDR,
- .irq = 17+32,
- .description = "Mali-400 MMU for PP 0",
- .mmu_id = 2
- },
- {
- .type = OS_MEMORY,
- .description = "System Memory",
- .size = 0x06000000,
- .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE
- },
- {
- .type = MEM_VALIDATION,
- .description = "memory validation",
- .base = 0x204e0000,
- .size = 0x7B20000,
- .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
- {
- .type = MEMORY,
- .description = "Dedicated Memory",
- .base = 0x2E000000,
- .size = 0x02000000,
- .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/drivers/media/video/samsung/ump/arch-orion-m400/config.h b/drivers/media/video/samsung/ump/arch-orion-m400/config.h
index 117cc6e..688edc9 100644
--- a/drivers/media/video/samsung/ump/arch-orion-m400/config.h
+++ b/drivers/media/video/samsung/ump/arch-orion-m400/config.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -11,12 +11,12 @@
#ifndef __ARCH_CONFIG_UMP_H__
#define __ARCH_CONFIG_UMP_H__
-#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY
+#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY
#if (USING_MEMORY == 0) /* Dedicated Memory */
-#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
#else
-#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
#endif
-#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024
#endif /* __ARCH_CONFIG_UMP_H__ */
diff --git a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h b/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h
index 560eda9..38ae1ee 100644
--- a/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h
+++ b/drivers/media/video/samsung/ump/arch-pb-virtex5/config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -12,7 +12,7 @@
#define __ARCH_CONFIG_H__
#define ARCH_UMP_BACKEND_DEFAULT 0
-#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0xC8000000
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0xCE000000
#define ARCH_UMP_MEMORY_SIZE_DEFAULT 32UL * 1024UL * 1024UL
#endif /* __ARCH_CONFIG_H__ */
diff --git a/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h b/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h
new file mode 100644
index 0000000..688edc9
--- /dev/null
+++ b/drivers/media/video/samsung/ump/arch-pegasus-m400/config.h
@@ -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.
+ */
+
+#ifndef __ARCH_CONFIG_UMP_H__
+#define __ARCH_CONFIG_UMP_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY
+#if (USING_MEMORY == 0) /* Dedicated Memory */
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
+#else
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
+#endif
+
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024
+#endif /* __ARCH_CONFIG_UMP_H__ */
diff --git a/drivers/media/video/samsung/ump/arch-release/config.h b/drivers/media/video/samsung/ump/arch-release/config.h
new file mode 100644
index 0000000..688edc9
--- /dev/null
+++ b/drivers/media/video/samsung/ump/arch-release/config.h
@@ -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.
+ */
+
+#ifndef __ARCH_CONFIG_UMP_H__
+#define __ARCH_CONFIG_UMP_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY
+#if (USING_MEMORY == 0) /* Dedicated Memory */
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
+#else
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
+#endif
+
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024
+#endif /* __ARCH_CONFIG_UMP_H__ */
diff --git a/drivers/media/video/samsung/ump/arch/config.h b/drivers/media/video/samsung/ump/arch/config.h
new file mode 100644
index 0000000..688edc9
--- /dev/null
+++ b/drivers/media/video/samsung/ump/arch/config.h
@@ -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.
+ */
+
+#ifndef __ARCH_CONFIG_UMP_H__
+#define __ARCH_CONFIG_UMP_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT USING_MEMORY
+#if (USING_MEMORY == 0) /* Dedicated Memory */
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0x2C000000
+#else
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
+#endif
+
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT UMP_MEM_SIZE*1024*1024
+#endif /* __ARCH_CONFIG_UMP_H__ */
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_api.c b/drivers/media/video/samsung/ump/common/ump_kernel_api.c
index ddc9ef7..83f0d30 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_api.c
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_api.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -161,7 +161,7 @@ UMP_KERNEL_API_EXPORT void ump_dd_reference_add(ump_dd_handle memh)
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));
+ DBG_MSG(5, ("Memory reference incremented. ID: %u, new value: %d\n", mem->secure_id, new_ref));
}
@@ -181,7 +181,7 @@ UMP_KERNEL_API_EXPORT void ump_dd_reference_release(ump_dd_handle memh)
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));
+ DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n", mem->secure_id, new_ref));
if (0 == new_ref)
{
@@ -277,7 +277,7 @@ _mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info )
}
_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_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;
@@ -313,15 +313,22 @@ _mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction )
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);
- _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
- if (NULL==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;
@@ -330,17 +337,215 @@ void _ump_ukk_msync( _ump_uk_msync_s *args )
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));
- return;
+ 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));
- return ;
+ goto msync_release_and_return;
+ }
+ DBG_MSG(3, ("UMP[%02u] _ump_ukk_msync Flush OP: %d Address: 0x%08x Mapping: 0x%08x\n",
+ (ump_secure_id)args->secure_id, args->op, args->address, args->mapping));
+
+ if ( args->address )
+ {
+ virtual = (void *)((u32)args->address);
+ offset = (u32)((args->address) - (args->mapping));
+ } else {
+ /* Flush entire mapping when no address is specified. */
+ virtual = args->mapping;
+ }
+ if ( args->size )
+ {
+ size = args->size;
+ } else {
+ /* Flush entire mapping when no size is specified. */
+ size = mem->size_bytes - offset;
+ }
+
+ if ( (offset + size) > mem->size_bytes )
+ {
+ DBG_MSG(1, ("Trying to flush more than the entire UMP allocation: offset: %u + size: %u > %u\n", offset, size, mem->size_bytes));
+ goto msync_release_and_return;
}
- DBG_MSG(3, ("_ump_ukk_msync FLUSHING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op));
/* The actual cache flush - Implemented for each OS*/
- _ump_osk_msync( mem , args->op, (u32)args->mapping, (u32)args->address, args->size);
+ _ump_osk_msync( mem, virtual, offset, size, args->op, NULL);
+
+msync_release_and_return:
+ ump_dd_reference_release(mem);
+ return;
+}
+
+void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args)
+{
+ ump_session_data * session_data;
+ ump_uk_cache_op_control op;
+
+ DEBUG_ASSERT_POINTER( args );
+ DEBUG_ASSERT_POINTER( args->ctx );
+
+ op = args->op;
+ session_data = (ump_session_data *)args->ctx;
+
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ if ( op== _UMP_UK_CACHE_OP_START )
+ {
+ session_data->cache_operations_ongoing++;
+ DBG_MSG(4, ("Cache ops start\n" ));
+ if ( session_data->cache_operations_ongoing != 1 )
+ {
+ DBG_MSG(2, ("UMP: Number of simultanious cache control ops: %d\n", session_data->cache_operations_ongoing) );
+ }
+ }
+ else if ( op== _UMP_UK_CACHE_OP_FINISH )
+ {
+ DBG_MSG(4, ("Cache ops finish\n"));
+ session_data->cache_operations_ongoing--;
+ #if 0
+ if ( session_data->has_pending_level1_cache_flush)
+ {
+ /* This function will set has_pending_level1_cache_flush=0 */
+ _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data);
+ }
+ #endif
+
+ /* to be on the safe side: always flush l1 cache when cache operations are done */
+ _ump_osk_msync( NULL, NULL, 0, 0, _UMP_UK_MSYNC_FLUSH_L1, session_data);
+ DBG_MSG(4, ("Cache ops finish end\n" ));
+ }
+ else
+ {
+ DBG_MSG(1, ("Illegal call to %s at line %d\n", __FUNCTION__, __LINE__));
+ }
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+}
+
+void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args )
+{
+ ump_dd_mem * mem = NULL;
+ ump_uk_user old_user;
+ ump_uk_msync_op cache_op = _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE;
+ ump_session_data *session_data;
+
+ DEBUG_ASSERT_POINTER( args );
+ DEBUG_ASSERT_POINTER( args->ctx );
+
+ session_data = (ump_session_data *)args->ctx;
+
+ _mali_osk_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_switch_hw_usage(). ID: %u\n", (ump_secure_id)args->secure_id));
+ return;
+ }
+
+ old_user = mem->hw_device;
+ mem->hw_device = args->new_user;
+
+ DBG_MSG(3, ("UMP[%02u] Switch usage Start New: %s Prev: %s.\n", (ump_secure_id)args->secure_id, args->new_user?"MALI":"CPU",old_user?"MALI":"CPU"));
+
+ if ( ! mem->is_cached )
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ DBG_MSG(3, ("UMP[%02u] Changing owner of uncached memory. Cache flushing not needed.\n", (ump_secure_id)args->secure_id));
+ return;
+ }
+
+ if ( old_user == args->new_user)
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ DBG_MSG(4, ("UMP[%02u] Setting the new_user equal to previous for. Cache flushing not needed.\n", (ump_secure_id)args->secure_id));
+ return;
+ }
+ if (
+ /* Previous AND new is both different from CPU */
+ (old_user != _UMP_UK_USED_BY_CPU) && (args->new_user != _UMP_UK_USED_BY_CPU )
+ )
+ {
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ DBG_MSG(4, ("UMP[%02u] Previous and new user is not CPU. Cache flushing not needed.\n", (ump_secure_id)args->secure_id));
+ return;
+ }
+
+ if ( (old_user != _UMP_UK_USED_BY_CPU ) && (args->new_user==_UMP_UK_USED_BY_CPU) )
+ {
+ cache_op =_UMP_UK_MSYNC_INVALIDATE;
+ DBG_MSG(4, ("UMP[%02u] Cache invalidation needed\n", (ump_secure_id)args->secure_id));
+#ifdef UMP_SKIP_INVALIDATION
+#error
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+ DBG_MSG(4, ("UMP[%02u] Performing Cache invalidation SKIPPED\n", (ump_secure_id)args->secure_id));
+ return;
+#endif
+ }
+ /* Ensure the memory doesn't dissapear when we are flushing it. */
+ ump_dd_reference_add(mem);
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ /* Take lock to protect: session->cache_operations_ongoing and session->has_pending_level1_cache_flush */
+ _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+ /* Actual cache flush */
+ _ump_osk_msync( mem, NULL, 0, mem->size_bytes, cache_op, session_data);
+ _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
+
+ ump_dd_reference_release(mem);
+ DBG_MSG(4, ("UMP[%02u] Switch usage Finish\n", (ump_secure_id)args->secure_id));
+ return;
+}
+
+void _ump_ukk_lock(_ump_uk_lock_s *args )
+{
+ ump_dd_mem * mem = NULL;
+
+ _mali_osk_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, ("UMP[%02u] Failed to look up mapping in _ump_ukk_lock(). ID: %u\n", (ump_secure_id)args->secure_id));
+ return;
+ }
+ ump_dd_reference_add(mem);
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ DBG_MSG(1, ("UMP[%02u] Lock. New lock flag: %d. Old Lock flag:\n", (u32)args->secure_id, (u32)args->lock_usage, (u32) mem->lock_usage ));
+
+ mem->lock_usage = (ump_lock_usage) args->lock_usage;
+
+ /** TODO: TAKE LOCK HERE */
+
+ ump_dd_reference_release(mem);
+}
+
+void _ump_ukk_unlock(_ump_uk_unlock_s *args )
+{
+ ump_dd_mem * mem = NULL;
+
+ _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_unlock(). ID: %u\n", (ump_secure_id)args->secure_id));
+ return;
+ }
+ ump_dd_reference_add(mem);
+ _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
+
+ DBG_MSG(1, ("UMP[%02u] Unlocking. Old Lock flag:\n", (u32)args->secure_id, (u32) mem->lock_usage ));
+
+ mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED;
+
+ /** TODO: RELEASE LOCK HERE */
+
+ ump_dd_reference_release(mem);
}
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.c b/drivers/media/video/samsung/ump/common/ump_kernel_common.c
index e5ff198..1fa7c8a 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_common.c
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_common.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -147,6 +147,9 @@ _mali_osk_errcode_t _ump_ukk_open( void** context )
*context = (void*)session_data;
+ session_data->cache_operations_ongoing = 0 ;
+ session_data->has_pending_level1_cache_flush = 0;
+
DBG_MSG(2, ("New session opened\n"));
return _MALI_OSK_ERR_OK;
@@ -225,19 +228,17 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args )
int map_id;
session_data = (ump_session_data *)args->ctx;
- if (NULL == session_data)
+ if(NULL == session_data)
{
MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
return _MALI_OSK_ERR_INVALID_ARGS;
}
-
/* SEC kernel stability 2012-02-17 */
if (NULL == session_data->cookies_map)
{
MSG_ERR(("session_data->cookies_map 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)
{
@@ -370,14 +371,12 @@ void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args )
MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n"));
return;
}
-
/* SEC kernel stability 2012-02-17 */
if (NULL == session_data->cookies_map)
{
MSG_ERR(("session_data->cookies_map 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 ));
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.h b/drivers/media/video/samsung/ump/common/ump_kernel_common.h
index c8b5541..03d213d 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_common.h
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_common.h
@@ -1,15 +1,15 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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__
+#ifndef __UMP_KERNEL_COMMON_H__
+#define __UMP_KERNEL_COMMON_H__
#include "ump_kernel_types.h"
#include "ump_kernel_interface.h"
@@ -77,6 +77,8 @@ typedef struct ump_session_data
int api_version;
_mali_osk_lock_t * lock;
ump_descriptor_mapping * cookies_map; /**< Secure mapping of cookies from _ump_ukk_map_mem() */
+ int cache_operations_ongoing;
+ int has_pending_level1_cache_flush;
} ump_session_data;
@@ -123,4 +125,4 @@ int map_errcode( _mali_osk_errcode_t err );
#define __user
#endif
-#endif /* __UMP_KERNEL_H__ */
+#endif /* __UMP_KERNEL_COMMON_H__ */
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c
index 5174839..cc7b8be 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -65,9 +65,9 @@ void ump_descriptor_mapping_destroy(ump_descriptor_mapping * 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);
+ 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;
@@ -89,8 +89,8 @@ int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void *
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*));
+ _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);
@@ -107,10 +107,10 @@ unlock_and_exit:
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) )
+ 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;
@@ -122,9 +122,9 @@ int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, voi
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) )
+ 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;
@@ -135,8 +135,8 @@ int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, voi
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) )
+ _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);
@@ -163,4 +163,3 @@ static void descriptor_table_free(ump_descriptor_table * table)
{
_mali_osk_free(table);
}
-
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h
index 319cc3b..881d3d8 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h
index d329bb5..73915ee 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -49,4 +49,3 @@ ump_memory_backend * ump_memory_backend_create ( void );
void ump_memory_backend_destroy( void );
#endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */
-
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c
index 4dcbe21..a5ccfeb 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -95,6 +95,8 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd
mem->release_func = phys_blocks_release;
/* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */
mem->is_cached = 0;
+ mem->hw_device = _UMP_UK_USED_BY_CPU;
+ mem->lock_usage = UMP_NOT_LOCKED;
_mali_osk_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));
@@ -165,6 +167,7 @@ _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction )
}
new_allocation->size_bytes = UMP_SIZE_ALIGN(user_interaction->size); /* Page align the size */
+ new_allocation->lock_usage = UMP_NOT_LOCKED;
/* Now, ask the active memory backend to do the actual memory allocation */
if (!device.backend->allocate( device.backend->ctx, new_allocation ) )
@@ -176,7 +179,7 @@ _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction )
_mali_osk_free(session_memory_element);
return _MALI_OSK_ERR_INVALID_FUNC;
}
-
+ new_allocation->hw_device = _UMP_UK_USED_BY_CPU;
new_allocation->ctx = device.backend->ctx;
new_allocation->release_func = device.backend->release;
@@ -195,6 +198,7 @@ _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction )
return _MALI_OSK_ERR_OK;
}
+
UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args)
{
ump_dd_mem * mem;
@@ -255,4 +259,3 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long v
return (ump_dd_handle)mem;
}
-
diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_types.h b/drivers/media/video/samsung/ump/common/ump_kernel_types.h
index ca03dec..fdacd86 100644
--- a/drivers/media/video/samsung/ump/common/ump_kernel_types.h
+++ b/drivers/media/video/samsung/ump/common/ump_kernel_types.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -14,6 +14,22 @@
#include "ump_kernel_interface.h"
#include "mali_osk.h"
+
+typedef enum
+{
+ UMP_USED_BY_CPU = 0,
+ UMP_USED_BY_MALI = 1,
+ UMP_USED_BY_UNKNOWN_DEVICE= 100,
+} ump_hw_usage;
+
+typedef enum
+{
+ UMP_NOT_LOCKED = 0,
+ UMP_READ = 1,
+ UMP_READ_WRITE = 3,
+} ump_lock_usage;
+
+
/*
* This struct is what is "behind" a ump_dd_handle
*/
@@ -28,6 +44,8 @@ typedef struct ump_dd_mem
void * ctx;
void * backend_info;
int is_cached;
+ ump_hw_usage hw_device;
+ ump_lock_usage lock_usage;
} ump_dd_mem;
diff --git a/drivers/media/video/samsung/ump/common/ump_osk.h b/drivers/media/video/samsung/ump/common/ump_osk.h
index bd9254b..dabdc7f 100644
--- a/drivers/media/video/samsung/ump/common/ump_osk.h
+++ b/drivers/media/video/samsung/ump/common/ump_osk.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -18,7 +18,8 @@
#include <mali_osk.h>
#include <ump_kernel_memory_backend.h>
-#include <ump_uk_types.h>
+#include "ump_uk_types.h"
+#include "ump_kernel_common.h"
#ifdef __cplusplus
extern "C"
@@ -39,7 +40,7 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descript
void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor );
-void _ump_osk_msync( ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size);
+void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data );
void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr);
diff --git a/drivers/media/video/samsung/ump/common/ump_uk_types.h b/drivers/media/video/samsung/ump/common/ump_uk_types.h
index 2bac454..4fd1ef7 100644
--- a/drivers/media/video/samsung/ump/common/ump_uk_types.h
+++ b/drivers/media/video/samsung/ump/common/ump_uk_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * 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.
@@ -45,12 +45,11 @@ typedef enum
_UMP_IOC_MAP_MEM, /* not used in Linux */
_UMP_IOC_UNMAP_MEM, /* not used in Linux */
_UMP_IOC_MSYNC,
-#ifdef CONFIG_ION_EXYNOS
+ _UMP_IOC_CACHE_OPERATIONS_CONTROL,
+ _UMP_IOC_SWITCH_HW_USAGE,
+ _UMP_IOC_LOCK,
+ _UMP_IOC_UNLOCK,
_UMP_IOC_ION_IMPORT,
-#endif
-#ifdef CONFIG_DMA_SHARED_BUFFER
- _UMP_IOC_DMABUF_IMPORT,
-#endif
}_ump_uk_functions;
typedef enum
@@ -64,9 +63,30 @@ typedef enum
{
_UMP_UK_MSYNC_CLEAN = 0,
_UMP_UK_MSYNC_CLEAN_AND_INVALIDATE = 1,
+ _UMP_UK_MSYNC_INVALIDATE = 2,
+ _UMP_UK_MSYNC_FLUSH_L1 = 3,
_UMP_UK_MSYNC_READOUT_CACHE_ENABLED = 128,
} ump_uk_msync_op;
+typedef enum
+{
+ _UMP_UK_CACHE_OP_START = 0,
+ _UMP_UK_CACHE_OP_FINISH = 1,
+} ump_uk_cache_op_control;
+
+typedef enum
+{
+ _UMP_UK_READ = 1,
+ _UMP_UK_READ_WRITE = 3,
+} ump_uk_lock_usage;
+
+typedef enum
+{
+ _UMP_UK_USED_BY_CPU = 0,
+ _UMP_UK_USED_BY_MALI = 1,
+ _UMP_UK_USED_BY_UNKNOWN_DEVICE= 100,
+} ump_uk_user;
+
/**
* Get API version ([in,out] u32 api_version, [out] u32 compatible)
*/
@@ -88,25 +108,14 @@ typedef struct _ump_uk_allocate_s
ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */
} _ump_uk_allocate_s;
-#ifdef CONFIG_ION_EXYNOS
typedef struct _ump_uk_ion_import_s
{
void *ctx; /**< [in,out] user-kernel context (trashed on output) */
- int ion_fd;
+ int ion_fd; /**< ion_fd */
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_ion_import_s;
-#endif
-
-#ifdef CONFIG_DMA_SHARED_BUFFER
-struct ump_uk_dmabuf {
- void *ctx;
- int fd;
- size_t size;
- uint32_t ump_handle;
-};
-#endif
/**
* SIZE_GET ([in] u32 secure_id, [out]size )
@@ -156,10 +165,38 @@ typedef struct _ump_uk_msync_s
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 secure_id; /**< [in] secure_id that identifies the ump buffer */
u32 is_cached; /**< [out] caching of CPU mappings */
} _ump_uk_msync_s;
+typedef struct _ump_uk_cache_operations_control_s
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ ump_uk_cache_op_control op; /**< [in] cache operations start/stop */
+} _ump_uk_cache_operations_control_s;
+
+
+typedef struct _ump_uk_switch_hw_usage_s
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 secure_id; /**< [in] secure_id that identifies the ump buffer */
+ ump_uk_user new_user; /**< [in] cookie stored with reference to the kernel mapping internals */
+
+} _ump_uk_switch_hw_usage_s;
+
+typedef struct _ump_uk_lock_s
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 secure_id; /**< [in] secure_id that identifies the ump buffer */
+ ump_uk_lock_usage lock_usage;
+} _ump_uk_lock_s;
+
+typedef struct _ump_uk_unlock_s
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ u32 secure_id; /**< [in] secure_id that identifies the ump buffer */
+} _ump_uk_unlock_s;
+
#ifdef __cplusplus
}
#endif
diff --git a/drivers/media/video/samsung/ump/common/ump_ukk.h b/drivers/media/video/samsung/ump/common/ump_ukk.h
index db48cd6..4e6bb86 100644
--- a/drivers/media/video/samsung/ump/common/ump_ukk.h
+++ b/drivers/media/video/samsung/ump/common/ump_ukk.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -44,6 +44,14 @@ void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args );
void _ump_ukk_msync( _ump_uk_msync_s *args );
+void _ump_ukk_cache_operations_control(_ump_uk_cache_operations_control_s* args);
+
+void _ump_ukk_switch_hw_usage(_ump_uk_switch_hw_usage_s *args );
+
+void _ump_ukk_lock(_ump_uk_lock_s *args );
+
+void _ump_ukk_unlock(_ump_uk_unlock_s *args );
+
u32 _ump_ukk_report_memory_usage( void );
#ifdef __cplusplus
diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface.h
index ba81a07..f84d237 100644
--- a/drivers/media/video/samsung/ump/include/ump_kernel_interface.h
+++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h
index 3efe165..36c5c9d 100644
--- a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h
+++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_vcm.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface_vcm.h
index a784241..5ff4155 100644
--- a/drivers/media/video/samsung/ump/include/ump_kernel_interface_vcm.h
+++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface_vcm.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h b/drivers/media/video/samsung/ump/include/ump_kernel_platform.h
index 1b5af40..339e967 100644
--- a/drivers/media/video/samsung/ump/include/ump_kernel_platform.h
+++ b/drivers/media/video/samsung/ump/include/ump_kernel_platform.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h b/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h
index 17b930d..50a021c 100644
--- a/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h
+++ b/drivers/media/video/samsung/ump/linux/license/gpl/ump_kernel_license.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/ump_ioctl.h b/drivers/media/video/samsung/ump/linux/ump_ioctl.h
index 50ef9df..1d49b4d 100644
--- a/drivers/media/video/samsung/ump/linux/ump_ioctl.h
+++ b/drivers/media/video/samsung/ump/linux/ump_ioctl.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -19,7 +19,7 @@ extern "C"
#include <linux/types.h>
#include <linux/ioctl.h>
-#include "../common/ump_uk_types.h"
+#include <ump_uk_types.h>
#ifndef __user
#define __user
@@ -39,16 +39,20 @@ extern "C"
#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)
+#define UMP_IOC_MSYNC _IOW(UMP_IOCTL_NR, _UMP_IOC_MSYNC, _ump_uk_msync_s)
#ifdef CONFIG_ION_EXYNOS
#define UMP_IOC_ION_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_ION_IMPORT, _ump_uk_ion_import_s)
#endif
-
#ifdef CONFIG_DMA_SHARED_BUFFER
#define UMP_IOC_DMABUF_IMPORT _IOW(UMP_IOCTL_NR, _UMP_IOC_DMABUF_IMPORT,\
struct ump_uk_dmabuf)
#endif
+#define UMP_IOC_CACHE_OPERATIONS_CONTROL _IOW(UMP_IOCTL_NR, _UMP_IOC_CACHE_OPERATIONS_CONTROL, _ump_uk_cache_operations_control_s)
+#define UMP_IOC_SWITCH_HW_USAGE _IOW(UMP_IOCTL_NR, _UMP_IOC_SWITCH_HW_USAGE, _ump_uk_switch_hw_usage_s)
+#define UMP_IOC_LOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_LOCK, _ump_uk_lock_s)
+#define UMP_IOC_UNLOCK _IOW(UMP_IOCTL_NR, _UMP_IOC_UNLOCK, _ump_uk_unlock_s)
+
#ifdef __cplusplus
}
#endif
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c
index 69f55c5..58cef54 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -42,7 +42,7 @@ struct ion_client *ion_client_ump = NULL;
#endif
/* Module parameter to control log level */
-int ump_debug_level = 3;
+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");
@@ -55,7 +55,9 @@ MODULE_PARM_DESC(ump_major, "Device major number");
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.
@@ -90,7 +92,7 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c
#endif
static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma);
-#ifdef CONFIG_VIDEO_MALI400MP_R2P3
+#if defined(CONFIG_VIDEO_MALI400MP) || defined(CONFIG_VIDEO_MALI400MP_R3P0) || defined(CONFIG_VIDEO_MALI400MP_R2P3)
extern int map_errcode( _mali_osk_errcode_t err );
#endif
@@ -171,6 +173,7 @@ 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)
{
@@ -180,6 +183,7 @@ int ump_kernel_device_initialize(void)
{
debugfs_create_file("memory_usage", 0400, ump_debugfs_dir, NULL, &ump_memory_usage_fops);
}
+#endif
if (0 == ump_major)
{
@@ -257,8 +261,10 @@ void ump_kernel_device_terminate(void)
/* free major */
unregister_chrdev_region(dev, 1);
+#if UMP_LICENSE_IS_GPL
if(ump_debugfs_dir)
debugfs_remove_recursive(ump_debugfs_dir);
+#endif
}
/*
@@ -369,6 +375,22 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c
err = ump_msync_wrapper((u32 __user *)argument, session_data);
break;
+ case UMP_IOC_CACHE_OPERATIONS_CONTROL:
+ err = ump_cache_operations_control_wrapper((u32 __user *)argument, session_data);
+ break;
+
+ case UMP_IOC_SWITCH_HW_USAGE:
+ err = ump_switch_hw_usage_wrapper((u32 __user *)argument, session_data);
+ break;
+
+ case UMP_IOC_LOCK:
+ err = ump_lock_wrapper((u32 __user *)argument, session_data);
+ break;
+
+ case UMP_IOC_UNLOCK:
+ err = ump_unlock_wrapper((u32 __user *)argument, session_data);
+ break;
+
default:
DBG_MSG(1, ("No handler for IOCTL. cmd: 0x%08x, arg: 0x%08lx\n", cmd, arg));
err = -EFAULT;
@@ -377,7 +399,6 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c
return err;
}
-
#ifndef CONFIG_VIDEO_MALI400MP_R2P3
#ifndef CONFIG_VIDEO_MALI400MP
#ifndef CONFIG_VIDEO_MALI400MP_R3P0
@@ -399,7 +420,6 @@ int map_errcode( _mali_osk_errcode_t err )
#endif
#endif
#endif
-
/*
* Handle from OS to map specified virtual memory to specified UMP memory.
*/
@@ -431,6 +451,8 @@ static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma)
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 ));
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h
index b93c814e..ef68040 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.h
@@ -1,18 +1,18 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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__
+#ifndef __UMP_KERNEL_LINUX_H__
+#define __UMP_KERNEL_LINUX_H__
int ump_kernel_device_initialize(void);
void ump_kernel_device_terminate(void);
-#endif /* __UMP_KERNEL_H__ */
+#endif /* __UMP_KERNEL_LINUX_H__ */
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c
index 4e6c9b5..82c16cc 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -52,6 +52,7 @@ 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);
@@ -104,6 +105,7 @@ ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size)
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;
backend->get = NULL;
@@ -220,6 +222,7 @@ static int block_allocator_allocate(void* ctx, ump_dd_mem * mem)
mem->backend_info = last_allocated;
up(&allocator->mutex);
+ mem->is_cached=0;
return 1;
}
@@ -272,3 +275,13 @@ 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/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h
index fa4bdcc..4f7180e 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -20,4 +20,3 @@
ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size);
#endif /* __UMP_KERNEL_MEMORY_BACKEND_DEDICATED_H__ */
-
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c
index 07fbd3f..2d81546 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -136,16 +136,16 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor)
return 0; /* failure */
}
- while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max))
+ while (left > 0)
{
struct page * new_page;
if (is_cached)
{
- new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN );
+ new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN);
} else
{
- new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_COLD);
+ new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD);
}
if (NULL == new_page)
{
@@ -182,9 +182,7 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor)
if (left)
{
- MSG_ERR(("Failed to allocate needed pages\n"));
- MSG_ERR(("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n",
- (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024));
+ DBG_MSG(1, ("Failed to allocate needed pages\n"));
while(pages_allocated)
{
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h
index f924705..b638562d 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -20,4 +20,3 @@
ump_memory_backend * ump_os_memory_backend_create(const int max_allocation);
#endif /* __UMP_KERNEL_MEMORY_BACKEND_OS_H__ */
-
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c
index de7f212..46797ea 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -66,9 +66,9 @@ ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation)
{
return NULL;
}
-
+
info->num_vcm_blocks = 0;
-
+
sema_init(&info->mutex, 1);
@@ -85,7 +85,7 @@ ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation)
backend->shutdown = vcm_memory_backend_destroy;
backend->pre_allocate_physical_check = NULL;
backend->adjust_to_mali_phys = NULL;
-
+
backend->get = vcm_res_get;
backend->set = vcm_attr_set;
@@ -128,8 +128,8 @@ static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor)
ump_vcm->dev_id = (int)descriptor->backend_info & ~UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE;
- if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */
- ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */
+ if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */
+ ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */
}
else if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR) { /* Physical Linear */
return 0;
@@ -137,7 +137,7 @@ static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor)
else { /* Other VCM */
ump_vcm->dev_id -= 2;
}
-
+
DBG_MSG(5, ("Device ID for VCM : %d\n", ump_vcm->dev_id));
ump_vcm->vcm = vcm_find_vcm(ump_vcm->dev_id);
@@ -146,7 +146,7 @@ static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor)
return 0;
}
descriptor->backend_info = (void*)ump_vcm;
-
+
if (down_interruptible(&info->mutex)) {
DBG_MSG(1, ("Failed to get mutex in ump_vcm_allocate\n"));
return 0; /* failure */
@@ -168,7 +168,7 @@ static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor)
struct ump_vcm *ump_vcm;
ump_vcm = (struct ump_vcm*)descriptor->backend_info;
-
+
ump_vcm->vcm_res =
vcm_make_binding(ump_vcm->vcm, descriptor->size_bytes,
ump_vcm->dev_id, 0);
@@ -288,5 +288,3 @@ static void vcm_attr_set(ump_dd_mem *mem, void *args)
return;
}
-
-
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h
index 62f6d12..c1ead0d 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c
index f2a6bd6..821ac27 100644
--- a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c
+++ b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -17,7 +17,6 @@
#include "ump_kernel_common.h"
#include "ump_kernel_memory_backend_os.h"
#include "ump_kernel_memory_backend_dedicated.h"
-#include "ump_kernel_memory_backend_vcm.h"
/* Configure which dynamic memory allocator to use */
int ump_backend = ARCH_UMP_BACKEND_DEFAULT;
diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c b/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c
index ef1902e..77be0c9 100644
--- a/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c
+++ b/drivers/media/video/samsung/ump/linux/ump_osk_atomics.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c
index 17af2bd..b38c714 100644
--- a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c
+++ b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -27,6 +27,7 @@
#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>
@@ -301,108 +302,140 @@ static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 s
return;
}
-void _ump_osk_msync( ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size)
+static void level1_cache_flush_all(void)
+{
+ DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n"));
+ __cpuc_flush_kern_all();
+}
+
+void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data )
{
int i;
- u32 start_p, end_p;
- ump_dd_physical_block *block;
+ const void *start_v, *end_v;
- DBG_MSG(3,
- ("Flushing nr of blocks: %u. First: paddr: 0x%08x vaddr: 0x%08x size:%dB\n",
- mem->nr_blocks, mem->block_array[0].addr,
- phys_to_virt(mem->block_array[0].addr),
- mem->block_array[0].size));
-
-#ifndef USING_DMA_FLUSH
- if (address) {
- if ((address >= start)
- && ((address + size) <= start + mem->size_bytes)) {
- if (size >= SZ_64K) {
- flush_all_cpu_caches();
- } else if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)
- dmac_flush_range((void *)address,
- (void *)(address + size - 1));
- else
- dmac_map_area((void *)address, size,
- DMA_TO_DEVICE);
-#ifdef CONFIG_CACHE_L2X0
- if (size >= SZ_1M)
- outer_clean_all();
+ /* Flush L1 using virtual address, the entire range in one go.
+ * Only flush if user space process has a valid write mapping on given address. */
+ if( (mem) && (virt!=NULL) && (access_ok(VERIFY_WRITE, virt, size)) )
+ {
+ 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);
+ DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v));
+ }
+ else
+ {
+ if (session_data)
+ {
+ if (op == _UMP_UK_MSYNC_FLUSH_L1 )
+ {
+ DBG_MSG(4, ("UMP Pending L1 cache flushes: %d\n", session_data->has_pending_level1_cache_flush));
+ session_data->has_pending_level1_cache_flush = 0;
+ level1_cache_flush_all();
+ return;
+ }
else
- _ump_osk_msync_with_virt(mem, op, start, address, size);
-#endif
- return;
+ {
+ if (session_data->cache_operations_ongoing)
+ {
+ session_data->has_pending_level1_cache_flush++;
+ DBG_MSG(4, ("UMP[%02u] Defering the L1 flush. Nr pending:%d\n", mem->secure_id, session_data->has_pending_level1_cache_flush) );
+ }
+ else
+ {
+ /* Flushing the L1 cache for each switch_user() if ump_cache_operations_control(START) is not called */
+ level1_cache_flush_all();
+ }
+ }
+ }
+ else
+ {
+ DBG_MSG(4, ("Unkown state %s %d\n", __FUNCTION__, __LINE__));
+ level1_cache_flush_all();
}
}
- if ((op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) {
- if ((mem->size_bytes >= SZ_1M)) {
- flush_all_cpu_caches();
-#ifdef CONFIG_CACHE_L2X0
- outer_flush_all();
-#endif
- return;
- } else if ((mem->size_bytes >= SZ_64K)) {
- flush_all_cpu_caches();
-#ifdef CONFIG_CACHE_L2X0
- for (i = 0; i < mem->nr_blocks; i++) {
- block = &mem->block_array[i];
- start_p = (u32) block->addr;
- end_p = start_p + block->size - 1;
- outer_flush_range(start_p, end_p);
- }
-#endif
- return;
+ if ( NULL == mem ) return;
+
+ if ( mem->size_bytes==size)
+ {
+ DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache\n",mem->secure_id));
+ }
+ else
+ {
+ DBG_MSG(3, ("UMP[%02u] Flushing CPU L2 Cache. Blocks:%u, TotalSize:%u. FlushSize:%u Offset:0x%x FirstPaddr:0x%08x\n",
+ mem->secure_id, mem->nr_blocks, mem->size_bytes, size, offset, mem->block_array[0].addr));
+ }
+
+
+ /* Flush L2 using physical addresses, block for block. */
+ for (i=0 ; i < mem->nr_blocks; i++)
+ {
+ u32 start_p, end_p;
+ ump_dd_physical_block *block;
+ block = &mem->block_array[i];
+
+ if(offset >= block->size)
+ {
+ offset -= block->size;
+ continue;
}
- } else {
- if ((mem->size_bytes >= SZ_1M)) {
- flush_all_cpu_caches();
-#ifdef CONFIG_CACHE_L2X0
- outer_clean_all();
-#endif
- return;
- } else if ((mem->size_bytes >= SZ_64K)) {
- flush_all_cpu_caches();
-#ifdef CONFIG_CACHE_L2X0
- for (i = 0; i < mem->nr_blocks; i++) {
- block = &mem->block_array[i];
- start_p = (u32) block->addr;
+
+ 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;
- outer_clean_range(start_p, end_p);
+ size -= block->size;
}
-#endif
- return;
}
- }
-#endif
- for (i = 0; i < mem->nr_blocks; i++) {
- /* TODO: Find out which flush method is best of 1)Dma OR 2)Normal flush functions */
- /*#define USING_DMA_FLUSH */
-#ifdef USING_DMA_FLUSH
- DEBUG_ASSERT((PAGE_SIZE == mem->block_array[i].size));
- dma_map_page(NULL,
- pfn_to_page(mem->block_array[i].
- addr >> PAGE_SHIFT), 0, PAGE_SIZE,
- DMA_BIDIRECTIONAL);
- /*dma_unmap_page(NULL, mem->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL); */
-#else
- block = &mem->block_array[i];
- start_p = (u32) block->addr;
- end_p = start_p + block->size - 1;
- if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) {
- dmac_flush_range(phys_to_virt(start_p),
- phys_to_virt(end_p));
- outer_flush_range(start_p, end_p);
- } else {
- dmac_map_area(phys_to_virt(start_p), block->size,
- DMA_TO_DEVICE);
- outer_clean_range(start_p, end_p);
+ switch(op)
+ {
+ case _UMP_UK_MSYNC_CLEAN:
+ outer_clean_range(start_p, end_p);
+ break;
+ case _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE:
+ outer_flush_range(start_p, end_p);
+ break;
+ case _UMP_UK_MSYNC_INVALIDATE:
+ outer_inv_range(start_p, end_p);
+ break;
+ default:
+ break;
+ }
+
+ if(0 == size)
+ {
+ /* Nothing left to flush. */
+ break;
}
-#endif
}
-}
+ return;
+}
void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr)
{
diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c b/drivers/media/video/samsung/ump/linux/ump_osk_misc.c
index 12066eb..1f1118e 100644
--- a/drivers/media/video/samsung/ump/linux/ump_osk_misc.c
+++ b/drivers/media/video/samsung/ump/linux/ump_osk_misc.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c
index 3e355c0..405bdca 100644
--- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c
+++ b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h
index 7bd4660..8e3c0fc 100644
--- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h
+++ b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c
index 8b73ca8..e5c5903 100644
--- a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c
+++ b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.c
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -138,9 +138,9 @@ int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * sessi
}
/*
- * IOCTL operation; Return size for specified UMP memory.
+ * IOCTL operation; Do cache maintenance on specified UMP memory.
*/
- int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data)
+int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data)
{
_ump_uk_msync_s user_interaction;
@@ -171,3 +171,136 @@ int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * sessi
return 0; /* success */
}
+int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data)
+{
+ _ump_uk_cache_operations_control_s user_interaction;
+
+ /* Sanity check input parameters */
+ if (NULL == argument || NULL == session_data)
+ {
+ MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+ return -ENOTTY;
+ }
+
+ if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_from_user() in ump_ioctl_cache_operations_control()\n"));
+ return -EFAULT;
+ }
+
+ user_interaction.ctx = (void *) session_data;
+
+ _ump_ukk_cache_operations_control((_ump_uk_cache_operations_control_s*) &user_interaction );
+
+ user_interaction.ctx = NULL;
+
+#if 0 /* No data to copy back */
+ if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_to_user() failed in ump_ioctl_cache_operations_control()\n"));
+ return -EFAULT;
+ }
+#endif
+ return 0; /* success */
+}
+
+int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data)
+{
+ _ump_uk_switch_hw_usage_s user_interaction;
+
+ /* Sanity check input parameters */
+ if (NULL == argument || NULL == session_data)
+ {
+ MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+ return -ENOTTY;
+ }
+
+ if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n"));
+ return -EFAULT;
+ }
+
+ user_interaction.ctx = (void *) session_data;
+
+ _ump_ukk_switch_hw_usage( &user_interaction );
+
+ user_interaction.ctx = NULL;
+
+#if 0 /* No data to copy back */
+ if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n"));
+ return -EFAULT;
+ }
+#endif
+ return 0; /* success */
+}
+
+int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data)
+{
+ _ump_uk_lock_s user_interaction;
+
+ /* Sanity check input parameters */
+ if (NULL == argument || NULL == session_data)
+ {
+ MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+ return -ENOTTY;
+ }
+
+ if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n"));
+ return -EFAULT;
+ }
+
+ user_interaction.ctx = (void *) session_data;
+
+ _ump_ukk_lock( &user_interaction );
+
+ user_interaction.ctx = NULL;
+
+#if 0 /* No data to copy back */
+ if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n"));
+ return -EFAULT;
+ }
+#endif
+
+ return 0; /* success */
+}
+
+int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data)
+{
+ _ump_uk_unlock_s user_interaction;
+
+ /* Sanity check input parameters */
+ if (NULL == argument || NULL == session_data)
+ {
+ MSG_ERR(("NULL parameter in ump_ioctl_size_get()\n"));
+ return -ENOTTY;
+ }
+
+ if (0 != copy_from_user(&user_interaction, argument, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_from_user() in ump_ioctl_switch_hw_usage()\n"));
+ return -EFAULT;
+ }
+
+ user_interaction.ctx = (void *) session_data;
+
+ _ump_ukk_unlock( &user_interaction );
+
+ user_interaction.ctx = NULL;
+
+#if 0 /* No data to copy back */
+ if (0 != copy_to_user(argument, &user_interaction, sizeof(user_interaction)))
+ {
+ MSG_ERR(("copy_to_user() failed in ump_ioctl_switch_hw_usage()\n"));
+ return -EFAULT;
+ }
+#endif
+
+ return 0; /* success */
+}
diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h
index 4892c31..99b790d 100644
--- a/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h
+++ b/drivers/media/video/samsung/ump/linux/ump_ukk_wrappers.h
@@ -1,9 +1,9 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
- *
+ * 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.
*/
@@ -30,6 +30,10 @@ int ump_get_api_version_wrapper(u32 __user * argument, struct ump_session_data *
int ump_release_wrapper(u32 __user * argument, struct ump_session_data * session_data);
int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * session_data);
int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data);
+int ump_cache_operations_control_wrapper(u32 __user * argument, struct ump_session_data * session_data);
+int ump_switch_hw_usage_wrapper(u32 __user * argument, struct ump_session_data * session_data);
+int ump_lock_wrapper(u32 __user * argument, struct ump_session_data * session_data);
+int ump_unlock_wrapper(u32 __user * argument, struct ump_session_data * session_data);
#ifdef __cplusplus