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 static int num_cores_total;
27 static int num_cores_enabled;
28 static void mali_platform_device_release(struct device *device);
29 static int mali_os_suspend(struct device *device);
30 static int mali_os_resume(struct device *device);
31 static int mali_os_freeze(struct device *device);
32 static int mali_os_thaw(struct device *device);
33 #ifdef CONFIG_PM_RUNTIME
34 static int mali_runtime_suspend(struct device *device);
35 static int mali_runtime_resume(struct device *device);
36 static int mali_runtime_idle(struct device *device);
37 #endif
38
39 /*#include "arm_core_scaling.h"*/
40 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data);
41
42 static struct work_struct wq_work;
43
44 static struct dev_pm_ops mali_gpu_device_type_pm_ops =
45 {
46         .suspend = mali_os_suspend,
47         .resume = mali_os_resume,
48         .freeze = mali_os_freeze,
49         .thaw = mali_os_thaw,
50 #ifdef CONFIG_PM_RUNTIME
51         .runtime_suspend = mali_runtime_suspend,
52         .runtime_resume = mali_runtime_resume,
53         .runtime_idle = mali_runtime_idle,
54 #endif
55 };
56
57 static struct device_type mali_gpu_device_device_type =
58 {
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 {
66         .shared_mem_size = 1024* 1024 * 1024, /* 1GB */
67         .fb_start = 0x40000000,
68         .fb_size = 0xb1000000,
69         .utilization_interval = 0, /* 0ms */
70         .utilization_callback = mali_gpu_utilization_handler,
71 };
72 static void mali_platform_device_add_config(struct platform_device *pdev)
73 {
74         pdev->dev.id = 0;
75         pdev->dev.release = mali_platform_device_release;
76         pdev->dev.type = &mali_gpu_device_device_type;
77         pdev->dev.dma_mask = &dma_dmamask;
78         pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
79 }
80 static void set_num_cores(struct work_struct *work)
81 {
82         int err = mali_perf_set_num_pp_cores(num_cores_enabled);
83         MALI_DEBUG_ASSERT(0 == err);
84         MALI_IGNORE(err);
85 }
86 static void enable_one_core(void)
87 {
88         if (num_cores_enabled < num_cores_total)
89         {
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         {
102                 --num_cores_enabled;
103                 schedule_work(&wq_work);
104                 MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
105         }
106
107         MALI_DEBUG_ASSERT(              1 <= num_cores_enabled);
108         MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
109 }
110 static void enable_max_num_cores(void)
111 {
112         if (num_cores_enabled < num_cores_total)
113         {
114                 num_cores_enabled = num_cores_total;
115                 schedule_work(&wq_work);
116                 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
117         }
118
119         MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
120 }
121 void mali_core_scaling_init(int num_pp_cores)
122 {
123         INIT_WORK(&wq_work, set_num_cores);
124
125         num_cores_total   = num_pp_cores;
126         num_cores_enabled = num_pp_cores;
127
128         /* NOTE: Mali is not fully initialized at this point. */
129 }
130 void mali_core_scaling_term(void)
131 {
132         flush_scheduled_work();
133 }
134 #define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
135 void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
136 {
137         /*
138          * This function implements a very trivial PP core scaling algorithm.
139          *
140          * It is _NOT_ of production quality.
141          * The only intention behind this algorithm is to exercise and test the
142          * core scaling functionality of the driver.
143          * It is _NOT_ tuned for neither power saving nor performance!
144          *
145          * Other metrics than PP utilization need to be considered as well
146          * in order to make a good core scaling algorithm.
147          */
148
149         MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, 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         {
156                 enable_max_num_cores();
157         }
158         else if (PERCENT_OF(50, 256) < data->utilization_pp)
159         {
160                 enable_one_core();
161         }
162         else if (PERCENT_OF(40, 256) < data->utilization_pp)
163         {
164                 /* do nothing */
165         }
166         else if (PERCENT_OF( 0, 256) < data->utilization_pp)
167         {
168                 disable_one_core();
169         }
170         else
171         {
172                 /* do nothing */
173         }
174 }
175 int mali_platform_device_register(struct platform_device *pdev)
176 {
177         int err = 0;
178         int num_pp_cores = 0;
179         MALI_PRINT(("mali_platform_device_register() called\n"));
180         
181         num_pp_cores = 1;
182         
183         mali_platform_device_add_config(pdev);
184
185         err = platform_device_add_data(pdev, &mali_gpu_data, sizeof(mali_gpu_data));
186         
187         if (0 == err)
188         {
189                 err = mali_platform_init();
190                 if(0 == err)
191                 {
192 #ifdef CONFIG_PM_RUNTIME
193 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
194                         pm_runtime_set_autosuspend_delay(&(pdev->dev), 1000);
195                         pm_runtime_use_autosuspend(&(pdev->dev));
196 #endif
197                         pm_runtime_enable(&(pdev->dev));
198 #endif
199                         mali_core_scaling_init(num_pp_cores);
200                         return 0;
201                 }
202         }
203         return err;
204 }
205 void mali_platform_device_unregister(struct platform_device *pdev)
206 {
207         MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));
208
209         mali_platform_deinit();
210         mali_core_scaling_term();
211 }
212
213 static void mali_platform_device_release(struct device *device)
214 {
215         MALI_DEBUG_PRINT(4, ("mali_platform_device_release() called\n"));
216 }
217 static int mali_os_suspend(struct device *device)
218 {
219         int ret = 0;
220
221         MALI_DEBUG_PRINT(2, ("mali_os_suspend() called\n"));
222         
223         if (NULL != device->driver &&
224             NULL != device->driver->pm &&
225             NULL != device->driver->pm->suspend)
226         {
227                 /* Need to notify Mali driver about this event */
228                 ret = device->driver->pm->suspend(device);
229         }
230
231         mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
232
233         return ret;
234 }
235
236 static int mali_os_resume(struct device *device)
237 {
238         int ret = 0;
239
240         MALI_DEBUG_PRINT(2, ("mali_os_resume() called\n"));
241
242         mali_platform_power_mode_change(MALI_POWER_MODE_ON);
243
244         if (NULL != device->driver &&
245             NULL != device->driver->pm &&
246             NULL != device->driver->pm->resume)
247         {
248                 /* Need to notify Mali driver about this event */
249                 ret = device->driver->pm->resume(device);
250         }
251
252         return ret;
253 }
254
255 static int mali_os_freeze(struct device *device)
256 {
257         int ret = 0;
258
259         MALI_DEBUG_PRINT(4, ("mali_os_freeze() called\n"));
260
261         if (NULL != device->driver &&
262             NULL != device->driver->pm &&
263             NULL != device->driver->pm->freeze)
264         {
265                 /* Need to notify Mali driver about this event */
266                 ret = device->driver->pm->freeze(device);
267         }
268
269         return ret;
270 }
271
272 static int mali_os_thaw(struct device *device)
273 {
274         int ret = 0;
275
276         MALI_DEBUG_PRINT(4, ("mali_os_thaw() called\n"));
277
278         if (NULL != device->driver &&
279             NULL != device->driver->pm &&
280             NULL != device->driver->pm->thaw)
281         {
282                 /* Need to notify Mali driver about this event */
283                 ret = device->driver->pm->thaw(device);
284         }
285
286         return ret;
287 }
288
289 #ifdef CONFIG_PM_RUNTIME
290 static int mali_runtime_suspend(struct device *device)
291 {
292         int ret = 0;
293         MALI_DEBUG_PRINT(4, ("mali_runtime_suspend() called\n"));
294
295         if (NULL != device->driver &&
296             NULL != device->driver->pm &&
297             NULL != device->driver->pm->runtime_suspend)
298         {
299                 /* Need to notify Mali driver about this event */
300                 ret = device->driver->pm->runtime_suspend(device);
301         }
302
303         mali_platform_power_mode_change(MALI_POWER_MODE_LIGHT_SLEEP);
304
305         return ret;
306 }
307
308 static int mali_runtime_resume(struct device *device)
309 {
310         int ret = 0;
311         MALI_DEBUG_PRINT(4, ("mali_runtime_resume() called\n"));
312
313         mali_platform_power_mode_change(MALI_POWER_MODE_ON);
314
315         if (NULL != device->driver &&
316             NULL != device->driver->pm &&
317             NULL != device->driver->pm->runtime_resume)
318         {
319                 /* Need to notify Mali driver about this event */
320                 ret = device->driver->pm->runtime_resume(device);
321         }
322
323         return ret;
324 }
325
326 static int mali_runtime_idle(struct device *device)
327 {
328         int ret = 0;
329         MALI_DEBUG_PRINT(4, ("mali_runtime_idle() called\n"));
330
331         if (NULL != device->driver &&
332             NULL != device->driver->pm &&
333             NULL != device->driver->pm->runtime_idle)
334         {
335                 /* Need to notify Mali driver about this event */
336                 ret = device->driver->pm->runtime_idle(device);
337                 if (0 != ret)
338                 {
339                         return ret;
340                 }
341         }
342
343         pm_runtime_suspend(device);
344
345         return 0;
346 }
347 #endif
348 void mali_gpu_utilization_callback(struct mali_gpu_utilization_data *data)
349 {
350         mali_core_scaling_update(data);
351 }
352