Merge remote-tracking branch 'origin/develop-3.10' into develop-3.10-next
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / platform / rk30 / rk3066.c
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2009-2010, 2012 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10
11 /*author by xxm  2012-12-1*/
12
13 #include <linux/platform_device.h>
14 #include <linux/version.h>
15 #include <linux/pm.h>
16 #ifdef CONFIG_PM_RUNTIME
17 #include <linux/pm_runtime.h>
18 #endif
19 #include <linux/mali/mali_utgard.h>
20 #include "mali_kernel_common.h"
21
22 #include "mali_platform.h"
23
24 #include <linux/workqueue.h>
25 #include <linux/dma-mapping.h>
26 #include <linux/rockchip/cpu.h>
27
28 static int num_cores_total;
29 static int num_cores_enabled;
30 static void mali_platform_device_release(struct device *device);
31 static int mali_os_suspend(struct device *device);
32 static int mali_os_resume(struct device *device);
33 static int mali_os_freeze(struct device *device);
34 static int mali_os_thaw(struct device *device);
35 #ifdef CONFIG_PM_RUNTIME
36 static int mali_runtime_suspend(struct device *device);
37 static int mali_runtime_resume(struct device *device);
38 static int mali_runtime_idle(struct device *device);
39 #endif
40
41 /*#include "arm_core_scaling.h"*/
42 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
43
44 static struct work_struct wq_work;
45
46 static struct dev_pm_ops mali_gpu_device_type_pm_ops = {
47         .suspend = mali_os_suspend,
48         .resume = mali_os_resume,
49         .freeze = mali_os_freeze,
50         .thaw = mali_os_thaw,
51 #ifdef CONFIG_PM_RUNTIME
52         .runtime_suspend = mali_runtime_suspend,
53         .runtime_resume = mali_runtime_resume,
54         .runtime_idle = mali_runtime_idle,
55 #endif
56 };
57
58 static struct device_type mali_gpu_device_device_type = {
59         .pm = &mali_gpu_device_type_pm_ops,
60 };
61
62 static u64 dma_dmamask = DMA_BIT_MASK(32);
63
64 static struct mali_gpu_device_data mali_gpu_data = {
65         .shared_mem_size = 1024* 1024 * 1024, /* 1GB */
66         .fb_start = 0x40000000,
67         .fb_size = 0xb1000000,
68         .utilization_interval = 0, /* 0ms */
69         .utilization_callback = mali_gpu_utilization_handler,
70 };
71 static void mali_platform_device_add_config(struct platform_device *pdev)
72 {
73         if (cpu_is_rk3036())
74                 mali_gpu_device_device_type.pm = NULL;
75         pdev->dev.id = 0;
76         pdev->dev.release = mali_platform_device_release;
77         pdev->dev.type = &mali_gpu_device_device_type;
78         pdev->dev.dma_mask = &dma_dmamask;
79         pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
80 }
81 static void set_num_cores(struct work_struct *work)
82 {
83         int err = mali_perf_set_num_pp_cores(num_cores_enabled);
84         MALI_DEBUG_ASSERT(0 == err);
85         MALI_IGNORE(err);
86 }
87 static void enable_one_core(void)
88 {
89         if (num_cores_enabled < num_cores_total) {
90                 ++num_cores_enabled;
91                 schedule_work(&wq_work);
92                 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
93         }
94
95         MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
96         MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
97 }
98 static void disable_one_core(void)
99 {
100         if (1 < num_cores_enabled) {
101                 --num_cores_enabled;
102                 schedule_work(&wq_work);
103                 MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
104         }
105
106         MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
107         MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
108 }
109 static void enable_max_num_cores(void)
110 {
111         if (num_cores_enabled < num_cores_total) {
112                 num_cores_enabled = num_cores_total;
113                 schedule_work(&wq_work);
114                 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
115         }
116
117         MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
118 }
119 void mali_core_scaling_init(int num_pp_cores)
120 {
121         INIT_WORK(&wq_work, set_num_cores);
122
123         num_cores_total   = num_pp_cores;
124         num_cores_enabled = num_pp_cores;
125
126         /* NOTE: Mali is not fully initialized at this point. */
127 }
128 void mali_core_scaling_term(void)
129 {
130         flush_scheduled_work();
131 }
132 #define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
133 void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
134 {
135         /*
136          * This function implements a very trivial PP core scaling algorithm.
137          *
138          * It is _NOT_ of production quality.
139          * The only intention behind this algorithm is to exercise and test the
140          * core scaling functionality of the driver.
141          * It is _NOT_ tuned for neither power saving nor performance!
142          *
143          * Other metrics than PP utilization need to be considered as well
144          * in order to make a good core scaling algorithm.
145          */
146
147         MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", 
148                          data->utilization_gpu, data->utilization_gp,
149                          data->utilization_pp, num_cores_enabled, num_cores_total));
150
151         /* NOTE: this function is normally called directly from the utilization callback which is in
152          * timer context. */
153
154         if (PERCENT_OF(90, 256) < data->utilization_pp) {
155                 enable_max_num_cores();
156         } else if (PERCENT_OF(50, 256) < data->utilization_pp) {
157                 enable_one_core();
158         } else if (PERCENT_OF(40, 256) < data->utilization_pp) {
159                 /* do nothing */
160         } else if (PERCENT_OF( 0, 256) < data->utilization_pp) {
161                 disable_one_core();
162         } else {
163                 /* do nothing */
164         }
165 }
166 int mali_platform_device_register(struct platform_device *pdev)
167 {
168         int err = 0;
169         int num_pp_cores = 0;
170         MALI_PRINT(("mali_platform_device_register() called\n"));
171         
172         num_pp_cores = 1;
173         
174         mali_platform_device_add_config(pdev);
175
176         err = platform_device_add_data(pdev, &mali_gpu_data, sizeof(mali_gpu_data));
177         
178         if (0 == err) {
179                 err = mali_platform_init();
180                 if(0 == err) {
181 #ifdef CONFIG_PM_RUNTIME
182 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
183                         pm_runtime_set_autosuspend_delay(&(pdev->dev), 1000);
184                         pm_runtime_use_autosuspend(&(pdev->dev));
185 #endif
186                         pm_runtime_enable(&(pdev->dev));
187 #endif
188                         mali_core_scaling_init(num_pp_cores);
189                         return 0;
190                 }
191         }
192         return err;
193 }
194 void mali_platform_device_unregister(struct platform_device *pdev)
195 {
196         MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
197
198         mali_platform_deinit();
199         mali_core_scaling_term();
200 }
201
202 static void mali_platform_device_release(struct device *device)
203 {
204         MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
205 }
206 static int mali_os_suspend(struct device *device)
207 {
208         int ret = 0;
209
210         MALI_DEBUG_PRINT(2, ("mali_os_suspend() called\n"));
211         
212         if (NULL != device->driver &&
213             NULL != device->driver->pm &&
214             NULL != device->driver->pm->suspend) {
215                 /* Need to notify Mali driver about this event */
216                 ret = device->driver->pm->suspend(device);
217         }
218
219         mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
220
221         return ret;
222 }
223
224 static int mali_os_resume(struct device *device)
225 {
226         int ret = 0;
227
228         MALI_DEBUG_PRINT(2, ("mali_os_resume() called\n"));
229
230         mali_platform_power_mode_change(MALI_POWER_MODE_ON);
231
232         if (NULL != device->driver &&
233             NULL != device->driver->pm &&
234             NULL != device->driver->pm->resume) {
235                 /* Need to notify Mali driver about this event */
236                 ret = device->driver->pm->resume(device);
237         }
238
239         return ret;
240 }
241
242 static int mali_os_freeze(struct device *device)
243 {
244         int ret = 0;
245
246         MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
247
248         if (NULL != device->driver &&
249             NULL != device->driver->pm &&
250             NULL != device->driver->pm->freeze) {
251                 /* Need to notify Mali driver about this event */
252                 ret = device->driver->pm->freeze(device);
253         }
254
255         return ret;
256 }
257
258 static int mali_os_thaw(struct device *device)
259 {
260         int ret = 0;
261
262         MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
263
264         if (NULL != device->driver &&
265             NULL != device->driver->pm &&
266             NULL != device->driver->pm->thaw) {
267                 /* Need to notify Mali driver about this event */
268                 ret = device->driver->pm->thaw(device);
269         }
270
271         return ret;
272 }
273
274 #ifdef CONFIG_PM_RUNTIME
275 static int mali_runtime_suspend(struct device *device)
276 {
277         int ret = 0;
278         MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
279
280         if (NULL != device->driver &&
281             NULL != device->driver->pm &&
282             NULL != device->driver->pm->runtime_suspend) {
283                 /* Need to notify Mali driver about this event */
284                 ret = device->driver->pm->runtime_suspend(device);
285         }
286
287         mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
288
289         return ret;
290 }
291
292 static int mali_runtime_resume(struct device *device)
293 {
294         int ret = 0;
295         MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
296
297         mali_platform_power_mode_change(MALI_POWER_MODE_ON);
298
299         if (NULL != device->driver &&
300             NULL != device->driver->pm &&
301             NULL != device->driver->pm->runtime_resume) {
302                 /* Need to notify Mali driver about this event */
303                 ret = device->driver->pm->runtime_resume(device);
304         }
305
306         return ret;
307 }
308
309 static int mali_runtime_idle(struct device *device)
310 {
311         int ret = 0;
312         MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
313
314         if (NULL != device->driver &&
315             NULL != device->driver->pm &&
316             NULL != device->driver->pm->runtime_idle) {
317                 /* Need to notify Mali driver about this event */
318                 ret = device->driver->pm->runtime_idle(device);
319                 if (0 != ret)
320                         return ret;
321         }
322
323         pm_runtime_suspend(device);
324
325         return 0;
326 }
327 #endif
328 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
329 {
330         mali_core_scaling_update(data);
331 }
332