aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/mali/platform/orion-m400
diff options
context:
space:
mode:
authorDorian Snyder <dastin1015@gmail.com>2014-06-15 01:24:33 -0700
committerDorian Snyder <dastin1015@gmail.com>2014-08-04 18:46:06 +0000
commitd90b43b963027b4d1559cec14e97117827a6458d (patch)
tree00d1334c383628e7d6f38a4f7ca0c575a4916d91 /drivers/media/video/samsung/mali/platform/orion-m400
parent89e6992285b4274996b39cd953c0adb5e95a3236 (diff)
downloadkernel_samsung_smdk4412-d90b43b963027b4d1559cec14e97117827a6458d.zip
kernel_samsung_smdk4412-d90b43b963027b4d1559cec14e97117827a6458d.tar.gz
kernel_samsung_smdk4412-d90b43b963027b4d1559cec14e97117827a6458d.tar.bz2
mali: add r3p1 for devices that need it
d710 needs to use old mali drivers due to new ones causing signal to be completely killed Change-Id: I450c356b50e3f3521a63717a1c241e3b818b936f
Diffstat (limited to 'drivers/media/video/samsung/mali/platform/orion-m400')
-rw-r--r--drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c656
-rw-r--r--drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c448
2 files changed, 1104 insertions, 0 deletions
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
new file mode 100644
index 0000000..119831d
--- /dev/null
+++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c
@@ -0,0 +1,656 @@
+/*
+ * 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 <linux/version.h>
+#include "mali_kernel_common.h"
+#include "mali_osk.h"
+#include "mali_platform.h"
+#include "mali_linux_pm.h"
+
+#if USING_MALI_PMM
+#include "mali_pm.h"
+#endif
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#include <plat/pd.h>
+#endif
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+#include "mali_kernel_profiling.h"
+#endif
+
+#include <asm/io.h>
+#include <mach/regs-pmu.h>
+
+#define EXTXTALCLK_NAME "ext_xtal"
+#define VPLLSRCCLK_NAME "vpll_src"
+#define FOUTVPLLCLK_NAME "fout_vpll"
+#define SCLVPLLCLK_NAME "sclk_vpll"
+#define GPUMOUT1CLK_NAME "mout_g3d1"
+
+#define MPLLCLK_NAME "mout_mpll"
+#define GPUMOUT0CLK_NAME "mout_g3d0"
+#define GPUCLK_NAME "sclk_g3d"
+#define CLK_DIV_STAT_G3D 0x1003C62C
+#define CLK_DESC "clk-divider-status"
+
+static struct clk *ext_xtal_clock = 0;
+static struct clk *vpll_src_clock = 0;
+static struct clk *fout_vpll_clock = 0;
+static struct clk *sclk_vpll_clock = 0;
+
+static struct clk *mpll_clock = 0;
+static struct clk *mali_parent_clock = 0;
+static struct clk *mali_clock = 0;
+
+int mali_gpu_clk = 160;
+static unsigned int GPU_MHZ = 1000000;
+#ifdef CONFIG_S5PV310_ASV
+int mali_gpu_vol = 1100000; /* 1.10V for ASV */
+#else
+int mali_gpu_vol = 1100000; /* 1.10V */
+#endif
+
+#if MALI_DVFS_ENABLED
+#define MALI_DVFS_DEFAULT_STEP 0 // 134Mhz default
+#endif
+
+int gpu_power_state;
+static int bPoweroff;
+
+#ifdef CONFIG_REGULATOR
+struct regulator {
+ struct device *dev;
+ struct list_head list;
+ int uA_load;
+ int min_uV;
+ int max_uV;
+ char *supply_name;
+ struct device_attribute dev_attr;
+ struct regulator_dev *rdev;
+};
+
+struct regulator *g3d_regulator=NULL;
+#endif
+
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36)
+extern struct platform_device s5pv310_device_pd[];
+#else
+extern struct platform_device exynos4_device_pd[];
+#endif
+#endif
+
+mali_io_address clk_register_map=0;
+
+#if MALI_GPU_BOTTOM_LOCK
+_mali_osk_lock_t *mali_dvfs_lock;
+#else
+static _mali_osk_lock_t *mali_dvfs_lock;
+#endif
+
+#ifdef CONFIG_REGULATOR
+int mali_regulator_get_usecount(void)
+{
+ struct regulator_dev *rdev;
+
+ if( IS_ERR_OR_NULL(g3d_regulator) )
+ {
+ MALI_DEBUG_PRINT(1, ("error on mali_regulator_get_usecount : g3d_regulator is null\n"));
+ return 0;
+ }
+ rdev = g3d_regulator->rdev;
+ return rdev->use_count;
+}
+
+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"));
+ return;
+ }
+ regulator_disable(g3d_regulator);
+ MALI_DEBUG_PRINT(1, ("regulator_disable -> use cnt: %d \n",mali_regulator_get_usecount()));
+}
+
+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"));
+ return;
+ }
+ regulator_enable(g3d_regulator);
+ MALI_DEBUG_PRINT(1, ("regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount()));
+}
+
+void mali_regulator_set_voltage(int min_uV, int max_uV)
+{
+ int voltage;
+
+ _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if( IS_ERR_OR_NULL(g3d_regulator) )
+ {
+ MALI_DEBUG_PRINT(1, ("error on mali_regulator_set_voltage : g3d_regulator is null\n"));
+ return;
+ }
+ 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 |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS,
+ min_uV, max_uV, 0, 0, 0);
+#endif
+
+ 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 |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS,
+ voltage, 0, 1, 0, 0);
+#endif
+ mali_gpu_vol = voltage;
+ MALI_DEBUG_PRINT(1, ("= regulator_get_voltage: %d \n",mali_gpu_vol));
+
+ _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
+}
+#endif
+
+unsigned long mali_clk_get_rate(void)
+{
+ return clk_get_rate(mali_clock);
+}
+
+mali_bool mali_clk_get(mali_bool bis_vpll)
+{
+ if (bis_vpll == MALI_TRUE)
+ {
+ if (ext_xtal_clock == NULL)
+ {
+ ext_xtal_clock = clk_get(NULL,EXTXTALCLK_NAME);
+ if (IS_ERR(ext_xtal_clock)) {
+ MALI_PRINT( ("MALI Error : failed to get source ext_xtal_clock\n"));
+ return MALI_FALSE;
+ }
+ }
+
+ if (vpll_src_clock == NULL)
+ {
+ vpll_src_clock = clk_get(NULL,VPLLSRCCLK_NAME);
+ if (IS_ERR(vpll_src_clock)) {
+ MALI_PRINT( ("MALI Error : failed to get source vpll_src_clock\n"));
+ return MALI_FALSE;
+ }
+ }
+
+ if (fout_vpll_clock == NULL)
+ {
+ fout_vpll_clock = clk_get(NULL,FOUTVPLLCLK_NAME);
+ if (IS_ERR(fout_vpll_clock)) {
+ MALI_PRINT( ("MALI Error : failed to get source fout_vpll_clock\n"));
+ return MALI_FALSE;
+ }
+ }
+
+ if (sclk_vpll_clock == NULL)
+ {
+ sclk_vpll_clock = clk_get(NULL,SCLVPLLCLK_NAME);
+ if (IS_ERR(sclk_vpll_clock)) {
+ MALI_PRINT( ("MALI Error : failed to get source sclk_vpll_clock\n"));
+ return MALI_FALSE;
+ }
+ }
+
+ if (mali_parent_clock == NULL)
+ {
+ mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME);
+
+ if (IS_ERR(mali_parent_clock)) {
+ MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n"));
+ return MALI_FALSE;
+ }
+ }
+ }
+ else // mpll
+ {
+ if (mpll_clock == NULL)
+ {
+ mpll_clock = clk_get(NULL,MPLLCLK_NAME);
+
+ if (IS_ERR(mpll_clock)) {
+ MALI_PRINT( ("MALI Error : failed to get source mpll clock\n"));
+ return MALI_FALSE;
+ }
+ }
+
+ if (mali_parent_clock == NULL)
+ {
+ mali_parent_clock = clk_get(NULL, GPUMOUT0CLK_NAME);
+
+ if (IS_ERR(mali_parent_clock)) {
+ MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n"));
+ return MALI_FALSE;
+ }
+ }
+ }
+
+ // mali clock get always.
+ if (mali_clock == NULL)
+ {
+ mali_clock = clk_get(NULL, GPUCLK_NAME);
+
+ if (IS_ERR(mali_clock)) {
+ MALI_PRINT( ("MALI Error : failed to get source mali clock\n"));
+ return MALI_FALSE;
+ }
+ }
+
+ return MALI_TRUE;
+}
+
+void mali_clk_put(mali_bool binc_mali_clock)
+{
+ if (mali_parent_clock)
+ {
+ clk_put(mali_parent_clock);
+ mali_parent_clock = 0;
+ }
+
+ if (mpll_clock)
+ {
+ clk_put(mpll_clock);
+ mpll_clock = 0;
+ }
+
+ if (sclk_vpll_clock)
+ {
+ clk_put(sclk_vpll_clock);
+ sclk_vpll_clock = 0;
+ }
+
+ if (fout_vpll_clock)
+ {
+ clk_put(fout_vpll_clock);
+ fout_vpll_clock = 0;
+ }
+
+ if (vpll_src_clock)
+ {
+ clk_put(vpll_src_clock);
+ vpll_src_clock = 0;
+ }
+
+ if (ext_xtal_clock)
+ {
+ clk_put(ext_xtal_clock);
+ ext_xtal_clock = 0;
+ }
+
+ if (binc_mali_clock == MALI_TRUE && mali_clock)
+ {
+ clk_put(mali_clock);
+ mali_clock = 0;
+ }
+
+}
+
+
+mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz)
+{
+ unsigned long rate = 0;
+ mali_bool bis_vpll = MALI_FALSE;
+
+#ifdef CONFIG_VPLL_USE_FOR_TVENC
+ bis_vpll = MALI_TRUE;
+#endif
+
+ _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
+
+ if (mali_clk_get(bis_vpll) == MALI_FALSE)
+ return MALI_FALSE;
+
+ rate = (unsigned long)clk * (unsigned long)mhz;
+ MALI_DEBUG_PRINT(3,("= clk_set_rate : %d , %d \n",clk, mhz ));
+
+ if (bis_vpll)
+ {
+ clk_set_rate(fout_vpll_clock, (unsigned int)clk * GPU_MHZ);
+ clk_set_parent(vpll_src_clock, ext_xtal_clock);
+ clk_set_parent(sclk_vpll_clock, fout_vpll_clock);
+
+ clk_set_parent(mali_parent_clock, sclk_vpll_clock);
+ clk_set_parent(mali_clock, mali_parent_clock);
+ }
+ else
+ {
+ clk_set_parent(mali_parent_clock, mpll_clock);
+ clk_set_parent(mali_clock, mali_parent_clock);
+ }
+
+ if (clk_enable(mali_clock) < 0)
+ return MALI_FALSE;
+
+#if MALI_TIMELINE_PROFILING_ENABLED
+ _mali_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);
+#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 |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ,
+ rate, 0, 0, 0, 0);
+#endif
+
+ if (bis_vpll)
+ mali_gpu_clk = (int)(rate / mhz);
+ else
+ mali_gpu_clk = (int)((rate + 500000) / mhz);
+
+ GPU_MHZ = mhz;
+ MALI_DEBUG_PRINT(3,("= clk_get_rate: %d \n",mali_gpu_clk));
+
+ mali_clk_put(MALI_FALSE);
+
+ _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW);
+
+ return MALI_TRUE;
+}
+
+static mali_bool init_mali_clock(void)
+{
+ mali_bool ret = MALI_TRUE;
+
+ gpu_power_state = 0;
+
+ if (mali_clock != 0)
+ return ret; // already initialized
+
+ mali_dvfs_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE
+ | _MALI_OSK_LOCKFLAG_ONELOCK, 0, 0);
+ if (mali_dvfs_lock == NULL)
+ return _MALI_OSK_ERR_FAULT;
+
+ if (mali_clk_set_rate(mali_gpu_clk, GPU_MHZ) == MALI_FALSE)
+ {
+ ret = MALI_FALSE;
+ goto err_clock_get;
+ }
+
+ MALI_PRINT(("init_mali_clock mali_clock %p \n", mali_clock));
+
+
+#ifdef CONFIG_REGULATOR
+#if USING_MALI_PMM
+ g3d_regulator = regulator_get(&mali_gpu_device.dev, "vdd_g3d");
+#else
+ g3d_regulator = regulator_get(NULL, "vdd_g3d");
+#endif
+
+ if (IS_ERR(g3d_regulator))
+ {
+ MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n"));
+ ret = MALI_FALSE;
+ goto err_regulator;
+ }
+
+ regulator_enable(g3d_regulator);
+ MALI_DEBUG_PRINT(1, ("= regulator_enable -> use cnt: %d \n",mali_regulator_get_usecount()));
+ mali_regulator_set_voltage(mali_gpu_vol, mali_gpu_vol);
+#endif
+
+ 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;
+
+
+#ifdef CONFIG_REGULATOR
+err_regulator:
+ regulator_put(g3d_regulator);
+#endif
+
+err_clock_get:
+ mali_clk_put(MALI_TRUE);
+
+ return ret;
+}
+
+static mali_bool deinit_mali_clock(void)
+{
+ if (mali_clock == 0)
+ return MALI_TRUE;
+
+#ifdef CONFIG_REGULATOR
+ if (g3d_regulator)
+ {
+ regulator_put(g3d_regulator);
+ g3d_regulator=NULL;
+ }
+#endif
+
+ mali_clk_put(MALI_TRUE);
+
+ return MALI_TRUE;
+}
+
+
+static _mali_osk_errcode_t enable_mali_clocks(void)
+{
+ int err;
+ err = clk_enable(mali_clock);
+ MALI_DEBUG_PRINT(3,("enable_mali_clocks mali_clock %p error %d \n", mali_clock, err));
+
+ // set clock rate
+ mali_clk_set_rate(mali_gpu_clk, GPU_MHZ);
+
+ MALI_SUCCESS;
+}
+
+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));
+
+ MALI_SUCCESS;
+}
+
+void set_mali_parent_power_domain(struct platform_device* dev)
+{
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36)
+ dev->dev.parent = &s5pv310_device_pd[PD_G3D].dev;
+#else
+ dev->dev.parent = &exynos4_device_pd[PD_G3D].dev;
+#endif
+
+#endif
+}
+
+_mali_osk_errcode_t g3d_power_domain_control(int bpower_on)
+{
+ if (bpower_on)
+ {
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ MALI_DEBUG_PRINT(3,("_mali_osk_pm_dev_activate \n"));
+ _mali_osk_pm_dev_activate();
+#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ void __iomem *status;
+ u32 timeout;
+ __raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_G3D_CONF);
+ status = S5P_PMU_G3D_CONF + 0x4;
+
+ timeout = 10;
+ while ((__raw_readl(status) & S5P_INT_LOCAL_PWR_EN)
+ != S5P_INT_LOCAL_PWR_EN) {
+ if (timeout == 0) {
+ MALI_PRINTF(("Power domain enable failed.\n"));
+ return -ETIMEDOUT;
+ }
+ timeout--;
+ _mali_osk_time_ubusydelay(100);
+ }
+#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ }
+ else
+ {
+#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ MALI_DEBUG_PRINT( 4,("_mali_osk_pm_dev_idle\n"));
+ _mali_osk_pm_dev_idle();
+
+#else //MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ void __iomem *status;
+ u32 timeout;
+ __raw_writel(0, S5P_PMU_G3D_CONF);
+
+ status = S5P_PMU_G3D_CONF + 0x4;
+ /* Wait max 1ms */
+ timeout = 10;
+ while (__raw_readl(status) & S5P_INT_LOCAL_PWR_EN)
+ {
+ if (timeout == 0) {
+ MALI_PRINTF(("Power domain disable failed.\n" ));
+ return -ETIMEDOUT;
+ }
+ timeout--;
+ _mali_osk_time_ubusydelay( 100);
+ }
+#endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON
+ }
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_init()
+{
+ MALI_CHECK(init_mali_clock(), _MALI_OSK_ERR_FAULT);
+#if MALI_DVFS_ENABLED
+ if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC );
+ if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP))
+ MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n"));
+#endif
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_deinit()
+{
+ deinit_mali_clock();
+
+#if MALI_DVFS_ENABLED
+ deinit_mali_dvfs_status();
+ if (clk_register_map )
+ {
+ _mali_osk_mem_unmapioregion(CLK_DIV_STAT_G3D, 0x20, clk_register_map);
+ clk_register_map=0;
+ }
+#endif
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_powerdown(u32 cores)
+{
+ MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores));
+
+ if (gpu_power_state != 0) // power down after state is 0
+ {
+ gpu_power_state = gpu_power_state & (~cores);
+ if (gpu_power_state == 0)
+ {
+ MALI_DEBUG_PRINT( 3,("disable clock\n"));
+ disable_mali_clocks();
+ }
+ }
+ else
+ {
+ MALI_PRINT(("mali_platform_powerdown gpu_power_state == 0 and cores %x \n", cores));
+ }
+
+ bPoweroff=1;
+
+
+
+ MALI_SUCCESS;
+}
+
+_mali_osk_errcode_t mali_platform_powerup(u32 cores)
+{
+ MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores));
+
+ if (gpu_power_state == 0) // power up only before state is 0
+ {
+ gpu_power_state = gpu_power_state | cores;
+
+ if (gpu_power_state != 0)
+ {
+ MALI_DEBUG_PRINT(4,("enable clock \n"));
+ enable_mali_clocks();
+ }
+ }
+ else
+ {
+ gpu_power_state = gpu_power_state | cores;
+ }
+
+ bPoweroff=0;
+
+
+ MALI_SUCCESS;
+}
+
+void mali_gpu_utilization_handler(u32 utilization)
+{
+ if (bPoweroff==0)
+ {
+#if MALI_DVFS_ENABLED
+ if(!mali_dvfs_handler(utilization))
+ MALI_DEBUG_PRINT(1,( "error on mali dvfs status in utilization\n"));
+#endif
+ }
+}
+
+#if MALI_POWER_MGMT_TEST_SUITE
+u32 pmu_get_power_up_down_info(void)
+{
+ return 4095;
+}
+
+#endif
+_mali_osk_errcode_t mali_platform_power_mode_change(mali_power_mode power_mode)
+{
+ MALI_SUCCESS;
+}
+
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
new file mode 100644
index 0000000..4efa759
--- /dev/null
+++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform_dvfs.c
@@ -0,0 +1,448 @@
+/* * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @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},
+ /*step 2*/{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*85)/100))},
+ /*step 2*/{((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]={
+#ifdef CONFIG_EXYNOS4210_1400MHZ_SUPPORT
+ /*step 0*/{134 ,1000000 , 950000},
+#else
+ /*step 0*/{100 ,1000000 , 950000},
+#endif
+ /*step 1*/{160 ,1000000 , 950000},
+ /*step 2*/{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 (100/134MHz) L2(160MHz), L1(267MHz) */
+ {1000000, 1000000, 1100000}, /* S */
+ {1000000, 1000000, 1100000}, /* A */
+ { 950000, 950000, 1000000}, /* B */
+ { 950000, 950000, 1000000}, /* C */
+ { 950000, 950000, 950000}, /* D */
+};
+
+static unsigned int asv_3d_volt_8_table[ASV_8_LEVEL][MALI_DVFS_STEPS] = {
+ /* L3 (100/134MHz) L2(160MHz), L1(267MHz) */
+ {1000000, 1000000, 1100000}, /* SS */
+ {1000000, 1000000, 1100000}, /* A1 */
+ {1000000, 1000000, 1100000}, /* A2 */
+ { 950000, 950000, 1000000}, /* B1 */
+ { 950000, 950000, 1000000}, /* B2 */
+ { 950000, 950000, 1000000}, /* C1 */
+ { 950000, 950000, 1000000}, /* C2 */
+ { 950000, 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
+#endif
+ switch(maliDvfsStatus.currentStep)
+ {
+ case 0:
+ if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold)
+ level=1;
+ else
+ level = maliDvfsStatus.currentStep;
+ break;
+ case 1:
+ if( utilization > mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold)
+ level=2;
+ else if( utilization <
+ (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/
+ mali_dvfs[maliDvfsStatus.currentStep].clock)
+ level=0;
+ else
+ level = maliDvfsStatus.currentStep;
+ break;
+ case 2:
+ if( utilization <
+ (mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold*mali_dvfs[maliDvfsStatus.currentStep-1].clock)/
+ mali_dvfs[maliDvfsStatus.currentStep].clock)
+ level=1;
+ else
+ level = maliDvfsStatus.currentStep;
+ break;
+ }
+ }
+ else
+ {
+ if((mali_dvfs_control == 1)||(( mali_dvfs_control > 3) && (mali_dvfs_control < mali_dvfs[0].clock+1)))
+ {
+ level=0;
+ }
+ else if((mali_dvfs_control == 2)||(( mali_dvfs_control > mali_dvfs[0].clock) && (mali_dvfs_control < mali_dvfs[1].clock+1)))
+ {
+ level=1;
+ }
+ else
+ {
+ level=2;
+ }
+ }
+
+ 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