~thopiekar/arm-mali/mali-400-kernel-drivers-sunxi

« back to all changes in this revision

Viewing changes to driver/src/devicedrv/mali/common/mali_pm.c

  • Committer: Dmitriy Beykun
  • Date: 2012-10-21 16:12:55 UTC
  • Revision ID: git-v1:23debc5a26ce858ef020405dbf91b2f268a72f44
added r3p0-04rel0 kernel drivers

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
 
3
 * 
 
4
 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
 
5
 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
 
6
 * 
 
7
 * A copy of the licence is included with the program, and can also be obtained from Free Software
 
8
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
9
 */
 
10
 
 
11
#include "mali_pm.h"
 
12
#include "mali_kernel_common.h"
 
13
#include "mali_osk.h"
 
14
#include "mali_gp_scheduler.h"
 
15
#include "mali_pp_scheduler.h"
 
16
#include "mali_platform.h"
 
17
#include "mali_kernel_utilization.h"
 
18
#include "mali_kernel_core.h"
 
19
#include "mali_group.h"
 
20
 
 
21
#define MALI_PM_LIGHT_SLEEP_TIMEOUT 1000
 
22
 
 
23
enum mali_pm_scheme
 
24
{
 
25
        MALI_PM_SCHEME_DYNAMIC,
 
26
        MALI_PM_SCHEME_OS_SUSPENDED,
 
27
        MALI_PM_SCHEME_ALWAYS_ON
 
28
};
 
29
 
 
30
enum mali_pm_level
 
31
{
 
32
        MALI_PM_LEVEL_1_ON,
 
33
        MALI_PM_LEVEL_2_STANDBY,
 
34
        MALI_PM_LEVEL_3_LIGHT_SLEEP,
 
35
        MALI_PM_LEVEL_4_DEEP_SLEEP
 
36
};
 
37
static _mali_osk_lock_t *mali_pm_lock_set_next_state;
 
38
static _mali_osk_lock_t *mali_pm_lock_set_core_states;
 
39
static _mali_osk_lock_t *mali_pm_lock_execute_state_change;
 
40
static _mali_osk_irq_t *wq_irq;
 
41
 
 
42
static _mali_osk_timer_t *idle_timer = NULL;
 
43
static mali_bool idle_timer_running = MALI_FALSE;
 
44
static u32 mali_pm_event_number     = 0;
 
45
 
 
46
static u32 num_active_gps = 0;
 
47
static u32 num_active_pps = 0;
 
48
 
 
49
static enum mali_pm_scheme current_scheme = MALI_PM_SCHEME_DYNAMIC;
 
50
static enum mali_pm_level current_level = MALI_PM_LEVEL_1_ON;
 
51
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 */
 
52
 
 
53
 
 
54
 
 
55
static _mali_osk_errcode_t mali_pm_upper_half(void *data);
 
56
static void mali_pm_bottom_half(void *data);
 
57
static void mali_pm_powerup(void);
 
58
static void mali_pm_powerdown(mali_power_mode power_mode);
 
59
 
 
60
static void timeout_light_sleep(void* arg);
 
61
#if 0
 
62
/* Deep sleep timout not supported */
 
63
static void timeout_deep_sleep(void* arg);
 
64
#endif
 
65
static u32 mali_pm_event_number_get(void);
 
66
static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time );
 
67
 
 
68
_mali_osk_errcode_t mali_pm_initialize(void)
 
69
{
 
70
        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);
 
71
 
 
72
        if (NULL != mali_pm_lock_execute_state_change )
 
73
        {
 
74
                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);
 
75
 
 
76
                if (NULL != mali_pm_lock_set_next_state)
 
77
                {
 
78
                        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);
 
79
 
 
80
                        if (NULL != mali_pm_lock_set_core_states)
 
81
                        {
 
82
                                idle_timer = _mali_osk_timer_init();
 
83
                                if (NULL != idle_timer)
 
84
                                {
 
85
                                        wq_irq = _mali_osk_irq_init(_MALI_OSK_IRQ_NUMBER_PMM,
 
86
                                                                                                mali_pm_upper_half,
 
87
                                                                                                mali_pm_bottom_half,
 
88
                                                                                                NULL,
 
89
                                                                                                NULL,
 
90
                                                                                                (void *)NULL,
 
91
                                                                                                "Mali PM deferred work");
 
92
                                        if (NULL != wq_irq)
 
93
                                        {
 
94
                                                if (_MALI_OSK_ERR_OK == mali_platform_init())
 
95
                                                {
 
96
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
 
97
                                                        _mali_osk_pm_dev_enable();
 
98
                                                        mali_pm_powerup();
 
99
#endif
 
100
                                                        return _MALI_OSK_ERR_OK;
 
101
                                                }
 
102
 
 
103
                                                _mali_osk_irq_term(wq_irq);
 
104
                                        }
 
105
 
 
106
                                        _mali_osk_timer_del(idle_timer);
 
107
                                        _mali_osk_timer_term(idle_timer);
 
108
                                }
 
109
                                _mali_osk_lock_term(mali_pm_lock_set_core_states);
 
110
                        }
 
111
                        _mali_osk_lock_term(mali_pm_lock_set_next_state);
 
112
                }
 
113
                _mali_osk_lock_term(mali_pm_lock_execute_state_change);
 
114
        }
 
115
 
 
116
        return _MALI_OSK_ERR_FAULT;
 
117
}
 
118
 
 
119
void mali_pm_terminate(void)
 
120
{
 
121
        mali_platform_deinit();
 
122
        _mali_osk_irq_term(wq_irq);
 
123
        _mali_osk_timer_del(idle_timer);
 
124
        _mali_osk_timer_term(idle_timer);
 
125
        _mali_osk_lock_term(mali_pm_lock_execute_state_change);
 
126
        _mali_osk_lock_term(mali_pm_lock_set_next_state);
 
127
        _mali_osk_lock_term(mali_pm_lock_set_core_states);
 
128
}
 
129
 
 
130
 
 
131
inline void mali_pm_lock(void)
 
132
{
 
133
        _mali_osk_lock_wait(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW);
 
134
}
 
135
 
 
136
inline void mali_pm_unlock(void)
 
137
{
 
138
        _mali_osk_lock_signal(mali_pm_lock_set_next_state, _MALI_OSK_LOCKMODE_RW);
 
139
}
 
140
 
 
141
inline void mali_pm_execute_state_change_lock(void)
 
142
{
 
143
        _mali_osk_lock_wait(mali_pm_lock_execute_state_change,_MALI_OSK_LOCKMODE_RW);
 
144
}
 
145
 
 
146
inline void mali_pm_execute_state_change_unlock(void)
 
147
{
 
148
        _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
 
149
}
 
150
 
 
151
static void mali_pm_powerup(void)
 
152
{
 
153
        MALI_DEBUG_PRINT(3, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n"));
 
154
        mali_platform_power_mode_change(MALI_POWER_MODE_ON);
 
155
 
 
156
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
 
157
 
 
158
        /* Aquire our reference */
 
159
        MALI_DEBUG_PRINT(4, ("Mali PM: Getting device PM reference (=> requesting MALI_POWER_MODE_ON)\n"));
 
160
        _mali_osk_pm_dev_activate();
 
161
#endif
 
162
 
 
163
        mali_group_power_on();
 
164
}
 
165
 
 
166
static void mali_pm_powerdown(mali_power_mode power_mode)
 
167
{
 
168
        if ( (MALI_PM_LEVEL_1_ON == current_level) || (MALI_PM_LEVEL_2_STANDBY == current_level) )
 
169
        {
 
170
                mali_group_power_off();
 
171
        }
 
172
        mali_platform_power_mode_change(power_mode);
 
173
 
 
174
#if MALI_PMM_RUNTIME_JOB_CONTROL_ON
 
175
        _mali_osk_pm_dev_idle();
 
176
#endif
 
177
}
 
178
 
 
179
mali_bool mali_pm_is_powered_on(void)
 
180
{
 
181
        mali_bool is_on = MALI_TRUE;
 
182
 
 
183
        if( ! (MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme) )
 
184
        {
 
185
                is_on = MALI_FALSE;
 
186
        }
 
187
        else if ( ! (MALI_PM_LEVEL_1_ON == current_level || MALI_PM_LEVEL_2_STANDBY == current_level))
 
188
        {
 
189
                is_on = MALI_FALSE;
 
190
        }
 
191
        else if ( ! (MALI_PM_LEVEL_1_ON == next_level_dynamic || MALI_PM_LEVEL_2_STANDBY == next_level_dynamic))
 
192
        {
 
193
                is_on = MALI_FALSE;
 
194
        }
 
195
 
 
196
        return is_on;
 
197
}
 
198
 
 
199
MALI_DEBUG_CODE(
 
200
static const char *state_as_string(enum mali_pm_level level)
 
201
{
 
202
        switch(level)
 
203
        {
 
204
                case MALI_PM_LEVEL_1_ON:
 
205
                        return "MALI_PM_LEVEL_1_ON";
 
206
                case MALI_PM_LEVEL_2_STANDBY:
 
207
                        return "MALI_PM_LEVEL_2_STANDBY";
 
208
                case MALI_PM_LEVEL_3_LIGHT_SLEEP:
 
209
                        return "MALI_PM_LEVEL_3_LIGHT_SLEEP";
 
210
                case MALI_PM_LEVEL_4_DEEP_SLEEP:
 
211
                        return "MALI_PM_LEVEL_4_DEEP_SLEEP";
 
212
                default:
 
213
                        return "UNKNOWN LEVEL";
 
214
        }
 
215
});
 
216
 
 
217
/* This could be used from another thread (work queue), if we need that */
 
218
static void mali_pm_process_next(void)
 
219
{
 
220
        enum mali_pm_level pm_level_to_set;
 
221
 
 
222
        _mali_osk_lock_wait(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
 
223
 
 
224
        pm_level_to_set = current_level;
 
225
 
 
226
        if (MALI_PM_SCHEME_DYNAMIC == current_scheme)
 
227
        {
 
228
                pm_level_to_set = next_level_dynamic;
 
229
 
 
230
                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)));
 
231
 
 
232
                if (current_level == pm_level_to_set)
 
233
                {
 
234
                        goto end_function; /* early out, no change in power level */
 
235
                }
 
236
 
 
237
                /* Start timers according to new state, so we get STANDBY -> LIGHT_SLEEP -> DEEP_SLEEP */
 
238
 
 
239
                if (MALI_TRUE == idle_timer_running)
 
240
                {
 
241
                        /* There is an existing timeout, so delete it */
 
242
                        _mali_osk_timer_del(idle_timer);
 
243
                        idle_timer_running = MALI_FALSE;
 
244
                }
 
245
 
 
246
                /* Making sure that we turn on through the platform file
 
247
                   Since it was turned OFF directly through the platform file.
 
248
                   This might lead to double turn-on, but the plaform file supports that.*/
 
249
                if ( current_level == MALI_PM_LEVEL_4_DEEP_SLEEP)
 
250
                {
 
251
                        mali_pm_powerup();
 
252
                        mali_kernel_core_wakeup();
 
253
 
 
254
                }
 
255
                if (MALI_PM_LEVEL_1_ON == pm_level_to_set)
 
256
                {
 
257
                        if (MALI_PM_LEVEL_2_STANDBY != current_level)
 
258
                        {
 
259
                                /* We only need to do anything if we came from one of the sleeping states */
 
260
                                mali_pm_powerup();
 
261
 
 
262
                                /* Wake up Mali cores since we came from a sleep state */
 
263
                                mali_kernel_core_wakeup();
 
264
                        }
 
265
                }
 
266
                else if (MALI_PM_LEVEL_2_STANDBY == pm_level_to_set)
 
267
                {
 
268
                        /* This is just an internal state, so we don't bother to report it to the platform file */
 
269
                        idle_timer_running = MALI_TRUE;
 
270
                        _mali_osk_timer_setcallback(idle_timer, timeout_light_sleep, (void*) mali_pm_event_number_get());
 
271
                        _mali_osk_timer_add(idle_timer, _mali_osk_time_mstoticks(MALI_PM_LIGHT_SLEEP_TIMEOUT));
 
272
                }
 
273
                else if (MALI_PM_LEVEL_3_LIGHT_SLEEP == pm_level_to_set)
 
274
                {
 
275
                        mali_pm_powerdown(MALI_POWER_MODE_LIGHT_SLEEP);
 
276
                }
 
277
                else if (MALI_PM_LEVEL_4_DEEP_SLEEP == pm_level_to_set)
 
278
                {
 
279
                        MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n"));
 
280
                        mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP);
 
281
                }
 
282
        }
 
283
        else if (MALI_PM_SCHEME_OS_SUSPENDED == current_scheme)
 
284
        {
 
285
                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)));
 
286
 
 
287
                pm_level_to_set = MALI_PM_LEVEL_4_DEEP_SLEEP;
 
288
 
 
289
                if (current_level == pm_level_to_set)
 
290
                {
 
291
                        goto end_function; /* early out, no change in power level */
 
292
                }
 
293
 
 
294
                /* Cancel any timers */
 
295
                if (MALI_TRUE == idle_timer_running)
 
296
                {
 
297
                        /* There is an existing timeout, so delete it */
 
298
                        _mali_osk_timer_del(idle_timer);
 
299
                        idle_timer_running = MALI_FALSE;
 
300
                }
 
301
 
 
302
                MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_DEEP_SLEEP\n"));
 
303
                mali_pm_powerdown(MALI_POWER_MODE_DEEP_SLEEP);
 
304
                next_level_dynamic = current_level;
 
305
        }
 
306
        else if (MALI_PM_SCHEME_ALWAYS_ON == current_scheme)
 
307
        {
 
308
                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)));
 
309
 
 
310
                pm_level_to_set = MALI_PM_LEVEL_1_ON;
 
311
                if (current_level == pm_level_to_set)
 
312
                {
 
313
                        goto end_function; /* early out, no change in power level */
 
314
                }
 
315
 
 
316
                MALI_DEBUG_PRINT(2, ("Mali PM: Setting GPU power mode to MALI_POWER_MODE_ON\n"));
 
317
                mali_pm_powerup();
 
318
                if (MALI_PM_LEVEL_2_STANDBY != current_level)
 
319
                {
 
320
                        /* Wake up Mali cores since we came from a sleep state */
 
321
                        mali_kernel_core_wakeup();
 
322
                }
 
323
        }
 
324
        else
 
325
        {
 
326
                MALI_PRINT_ERROR(("MALI PM: Illegal scheme"));
 
327
        }
 
328
 
 
329
        current_level = pm_level_to_set;
 
330
 
 
331
end_function:
 
332
        _mali_osk_lock_signal(mali_pm_lock_execute_state_change, _MALI_OSK_LOCKMODE_RW);
 
333
 
 
334
}
 
335
 
 
336
void mali_pm_always_on(mali_bool enable)
 
337
{
 
338
        if (MALI_TRUE == enable)
 
339
        {
 
340
                /* The event is processed in current thread synchronously */
 
341
                mali_pm_event(MALI_PM_EVENT_SCHEME_ALWAYS_ON, MALI_FALSE, 0 );
 
342
        }
 
343
        else
 
344
        {
 
345
                /* The event is processed in current thread synchronously */
 
346
                mali_pm_event(MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL, MALI_FALSE, 0 );
 
347
        }
 
348
}
 
349
 
 
350
static _mali_osk_errcode_t mali_pm_upper_half(void *data)
 
351
{
 
352
        /* not used */
 
353
        return _MALI_OSK_ERR_OK;
 
354
}
 
355
 
 
356
static void mali_pm_bottom_half(void *data)
 
357
{
 
358
        mali_pm_process_next();
 
359
}
 
360
 
 
361
static u32 mali_pm_event_number_get(void)
 
362
{
 
363
        u32 retval;
 
364
 
 
365
        mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */
 
366
        retval = ++mali_pm_event_number;
 
367
        if (0==retval ) retval = ++mali_pm_event_number;
 
368
        mali_pm_unlock();
 
369
 
 
370
        return retval;
 
371
}
 
372
 
 
373
static void mali_pm_event(enum mali_pm_event pm_event, mali_bool schedule_work, u32 timer_time )
 
374
{
 
375
        mali_pm_lock(); /* spinlock: mali_pm_lock_set_next_state */
 
376
        /* Only timer events should set this variable, all other events must set it to zero. */
 
377
        if ( 0 != timer_time )
 
378
        {
 
379
                MALI_DEBUG_ASSERT( (pm_event==MALI_PM_EVENT_TIMER_LIGHT_SLEEP) || (pm_event==MALI_PM_EVENT_TIMER_DEEP_SLEEP) );
 
380
                if ( mali_pm_event_number != timer_time )
 
381
                {
 
382
                        /* In this case there have been processed newer events since the timer event was set up.
 
383
                           If so we always ignore the timing event */
 
384
                        mali_pm_unlock();
 
385
                        return;
 
386
                }
 
387
        }
 
388
        else
 
389
        {
 
390
                /* Delete possible ongoing timers
 
391
                if (  (MALI_PM_LEVEL_2_STANDBY==current_level) || (MALI_PM_LEVEL_3_LIGHT_SLEEP==current_level) )
 
392
                {
 
393
                        _mali_osk_timer_del(idle_timer);
 
394
                }
 
395
                */
 
396
        }
 
397
        mali_pm_event_number++;
 
398
        switch (pm_event)
 
399
        {
 
400
                case MALI_PM_EVENT_CORES_WORKING:
 
401
                        next_level_dynamic = MALI_PM_LEVEL_1_ON;
 
402
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED    != current_scheme );
 
403
                        break;
 
404
                case MALI_PM_EVENT_CORES_IDLE:
 
405
                        next_level_dynamic = MALI_PM_LEVEL_2_STANDBY;
 
406
                        /*MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED    != current_scheme );*/
 
407
                        break;
 
408
                case MALI_PM_EVENT_TIMER_LIGHT_SLEEP:
 
409
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme );
 
410
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED    != current_scheme );
 
411
                        next_level_dynamic = MALI_PM_LEVEL_3_LIGHT_SLEEP;
 
412
                        break;
 
413
                case MALI_PM_EVENT_TIMER_DEEP_SLEEP:
 
414
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme );
 
415
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED    != current_scheme );
 
416
                        next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP;
 
417
                        break;
 
418
                case MALI_PM_EVENT_OS_SUSPEND:
 
419
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON != current_scheme );
 
420
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED    != current_scheme );
 
421
                        current_scheme = MALI_PM_SCHEME_OS_SUSPENDED;
 
422
                        next_level_dynamic = MALI_PM_LEVEL_4_DEEP_SLEEP; /* Dynamic scheme will go into level when we are resumed */
 
423
                        break;
 
424
                case MALI_PM_EVENT_OS_RESUME:
 
425
                        MALI_DEBUG_ASSERT(MALI_PM_SCHEME_OS_SUSPENDED == current_scheme );
 
426
                        current_scheme = MALI_PM_SCHEME_DYNAMIC;
 
427
                        break;
 
428
                case MALI_PM_EVENT_SCHEME_ALWAYS_ON:
 
429
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_OS_SUSPENDED != current_scheme );
 
430
                        current_scheme = MALI_PM_SCHEME_ALWAYS_ON;
 
431
                        break;
 
432
                case MALI_PM_EVENT_SCHEME_DYNAMIC_CONTROLL:
 
433
                        MALI_DEBUG_ASSERT( MALI_PM_SCHEME_ALWAYS_ON == current_scheme || MALI_PM_SCHEME_DYNAMIC == current_scheme );
 
434
                        current_scheme = MALI_PM_SCHEME_DYNAMIC;
 
435
                        break;
 
436
                default:
 
437
                        MALI_DEBUG_PRINT_ERROR(("Unknown next state."));
 
438
                        mali_pm_unlock();
 
439
                        return;
 
440
        }
 
441
        mali_pm_unlock();
 
442
 
 
443
        if (MALI_TRUE == schedule_work)
 
444
        {
 
445
                _mali_osk_irq_schedulework(wq_irq);
 
446
        }
 
447
        else
 
448
        {
 
449
                mali_pm_process_next();
 
450
        }
 
451
}
 
452
 
 
453
static void timeout_light_sleep(void* arg)
 
454
{
 
455
        /* State change only if no newer power events have happend from the time in arg.
 
456
            Actual work will be scheduled on worker thread. */
 
457
        mali_pm_event(MALI_PM_EVENT_TIMER_LIGHT_SLEEP, MALI_TRUE, (u32) arg);
 
458
}
 
459
 
 
460
void mali_pm_core_event(enum mali_core_event core_event)
 
461
{
 
462
        mali_bool transition_working = MALI_FALSE;
 
463
        mali_bool transition_idle = MALI_FALSE;
 
464
 
 
465
        _mali_osk_lock_wait(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW);
 
466
 
 
467
        switch (core_event)
 
468
        {
 
469
                case MALI_CORE_EVENT_GP_START:
 
470
                        if (num_active_pps + num_active_gps == 0)
 
471
                        {
 
472
                                transition_working = MALI_TRUE;
 
473
                        }
 
474
                        num_active_gps++;
 
475
                        break;
 
476
                case MALI_CORE_EVENT_GP_STOP:
 
477
                        if (num_active_pps + num_active_gps == 1)
 
478
                        {
 
479
                                transition_idle = MALI_TRUE;
 
480
                        }
 
481
                        num_active_gps--;
 
482
                        break;
 
483
                case MALI_CORE_EVENT_PP_START:
 
484
                        if (num_active_pps + num_active_gps == 0)
 
485
                        {
 
486
                                transition_working = MALI_TRUE;
 
487
                        }
 
488
                        num_active_pps++;
 
489
                        break;
 
490
                case MALI_CORE_EVENT_PP_STOP:
 
491
                        if (num_active_pps + num_active_gps == 1)
 
492
                        {
 
493
                                transition_idle = MALI_TRUE;
 
494
                        }
 
495
                        num_active_pps--;
 
496
                        break;
 
497
        }
 
498
 
 
499
        if (transition_working == MALI_TRUE)
 
500
        {
 
501
#ifdef CONFIG_MALI400_GPU_UTILIZATION
 
502
                mali_utilization_core_start(_mali_osk_time_get_ns());
 
503
#endif
 
504
                mali_pm_event(MALI_PM_EVENT_CORES_WORKING, MALI_FALSE, 0); /* process event in same thread */
 
505
        }
 
506
        else if (transition_idle == MALI_TRUE)
 
507
        {
 
508
#ifdef CONFIG_MALI400_GPU_UTILIZATION
 
509
                mali_utilization_core_end(_mali_osk_time_get_ns());
 
510
#endif
 
511
                mali_pm_event(MALI_PM_EVENT_CORES_IDLE, MALI_FALSE, 0); /* process event in same thread */
 
512
        }
 
513
 
 
514
        _mali_osk_lock_signal(mali_pm_lock_set_core_states, _MALI_OSK_LOCKMODE_RW);
 
515
}
 
516
 
 
517
void mali_pm_os_suspend(void)
 
518
{
 
519
        MALI_DEBUG_PRINT(2, ("Mali PM: OS suspending...\n"));
 
520
 
 
521
        mali_gp_scheduler_suspend();
 
522
        mali_pp_scheduler_suspend();
 
523
        mali_pm_event(MALI_PM_EVENT_OS_SUSPEND, MALI_FALSE, 0); /* process event in same thread */
 
524
 
 
525
        MALI_DEBUG_PRINT(2, ("Mali PM: OS suspend completed\n"));
 
526
}
 
527
 
 
528
void mali_pm_os_resume(void)
 
529
{
 
530
        MALI_DEBUG_PRINT(2, ("Mali PM: OS resuming...\n"));
 
531
 
 
532
        mali_pm_event(MALI_PM_EVENT_OS_RESUME, MALI_FALSE, 0); /* process event in same thread */
 
533
        mali_gp_scheduler_resume();
 
534
        mali_pp_scheduler_resume();
 
535
 
 
536
        MALI_DEBUG_PRINT(2, ("Mali PM: OS resume completed\n"));
 
537
}
 
538
 
 
539
void mali_pm_runtime_suspend(void)
 
540
{
 
541
        MALI_DEBUG_PRINT(2, ("Mali PM: OS runtime suspended\n"));
 
542
}
 
543
 
 
544
void mali_pm_runtime_resume(void)
 
545
{
 
546
        MALI_DEBUG_PRINT(3, ("Mali PM: OS runtime resumed\n"));
 
547
}