diff options
Diffstat (limited to 'drivers/media/video/samsung/mali/common/mali_pm.c')
-rw-r--r-- | drivers/media/video/samsung/mali/common/mali_pm.c | 552 |
1 files changed, 0 insertions, 552 deletions
diff --git a/drivers/media/video/samsung/mali/common/mali_pm.c b/drivers/media/video/samsung/mali/common/mali_pm.c deleted file mode 100644 index 933e54e..0000000 --- a/drivers/media/video/samsung/mali/common/mali_pm.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * 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) -{ -#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON - 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); -#else - /* Aquire our reference */ - _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(); - } - -#if !MALI_PMM_RUNTIME_JOB_CONTROL_ON - mali_platform_power_mode_change(power_mode); -#else - _mali_osk_pm_dev_idle(); - - if (MALI_POWER_MODE_DEEP_SLEEP == power_mode) - { - mali_platform_power_mode_change(power_mode); - } -#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")); - mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP); -} - -void mali_pm_runtime_resume(void) -{ - MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime resumed\n")); - mali_platform_power_mode_change(MALI_POWER_MODE_ON); -} |