mali mess
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / ged / src / ged_main.c
CommitLineData
6fa3eb70
S
1/*
2 * (C) Copyright 2010
3 * MediaTek <www.MediaTek.com>
4 *
5 * MTK GPU Extension Device
6 *
7 */
8
9#include <linux/cdev.h>
10#include <linux/delay.h>
11#include <linux/device.h>
12#include <linux/fs.h>
13#include <linux/hardirq.h>
14#include <linux/init.h>
15#include <linux/kallsyms.h>
16#include <linux/miscdevice.h>
17#include <linux/module.h>
18#include <linux/poll.h>
19#include <linux/proc_fs.h>
20#include <linux/wait.h>
21#include <linux/sched.h>
22#include <linux/vmalloc.h>
02af6beb 23//#include <mach/system.h>
6fa3eb70
S
24#include <linux/slab.h>
25#include <linux/spinlock.h>
26#include <linux/semaphore.h>
27#include <linux/workqueue.h>
28#include <linux/kthread.h>
29#include <linux/aee.h>
30
31#include "ged_debugFS.h"
32#include "ged_log.h"
02af6beb 33#include "ged_hal.h"
6fa3eb70
S
34#include "ged_bridge.h"
35#include "ged_profile_dvfs.h"
36#include "ged_monitor_3D_fence.h"
02af6beb
S
37#include "ged_notify_sw_vsync.h"
38#include "ged_dvfs.h"
39
6fa3eb70
S
40
41#define GED_DRIVER_DEVICE_NAME "ged"
42
43#define GED_IOCTL_PARAM_BUF_SIZE 0x3000 //12KB
44
45#ifdef GED_DEBUG
46#define GED_LOG_BUF_COMMON_GLES "GLES"
47static GED_LOG_BUF_HANDLE ghLogBuf_GLES = 0;
48GED_LOG_BUF_HANDLE ghLogBuf_GED = 0;
49#endif
50
02af6beb
S
51#define GED_LOG_BUF_COMMON_HWC "HWC"
52static GED_LOG_BUF_HANDLE ghLogBuf_HWC = 0;
53#define GED_LOG_BUF_COMMON_FENCE "FENCE"
54static GED_LOG_BUF_HANDLE ghLogBuf_FENCE = 0;
55
56GED_LOG_BUF_HANDLE ghLogBuf_DVFS = 0;
57GED_LOG_BUF_HANDLE ghLogBuf_ged_srv = 0;
58
59
60
6fa3eb70
S
61static void* gvIOCTLParamBuf = NULL;
62
63/******************************************************************************
64 * GED File operations
65 *****************************************************************************/
66static int ged_open(struct inode *inode, struct file *filp)
67{
02af6beb
S
68 GED_LOGE("%s:%d:%d\n", __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
69 return 0;
6fa3eb70
S
70}
71
72static int ged_release(struct inode *inode, struct file *filp)
73{
02af6beb
S
74 GED_LOGE("%s:%d:%d\n", __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
75 return 0;
6fa3eb70
S
76}
77
78static unsigned int ged_poll(struct file *file, struct poll_table_struct *ptable)
79{
02af6beb 80 return 0;
6fa3eb70
S
81}
82
83static ssize_t ged_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
84{
02af6beb 85 return 0;
6fa3eb70
S
86}
87
88static ssize_t ged_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
89{
02af6beb 90 return 0;
6fa3eb70
S
91}
92
93static long ged_dispatch(GED_BRIDGE_PACKAGE *psBridgePackageKM)
94{
02af6beb
S
95 int ret = -EFAULT;
96 void *pvInt, *pvOut;
97 typedef int (ged_bridge_func_type)(void*, void*);
98 ged_bridge_func_type* pFunc = NULL;
99
100 if ((psBridgePackageKM->i32InBufferSize >=0) && (psBridgePackageKM->i32OutBufferSize >=0) &&
101 (psBridgePackageKM->i32InBufferSize + psBridgePackageKM->i32OutBufferSize < GED_IOCTL_PARAM_BUF_SIZE))
102 {
103 pvInt = gvIOCTLParamBuf;
104 pvOut = (void*)((char*)pvInt + (uintptr_t)psBridgePackageKM->i32InBufferSize);
105 if (psBridgePackageKM->i32InBufferSize > 0)
106 {
107 if (0 != ged_copy_from_user(pvInt, psBridgePackageKM->pvParamIn, psBridgePackageKM->i32InBufferSize))
108 {
109 GED_LOGE("ged_copy_from_user fail\n");
110 return ret;
111 }
112 }
113
114 // we will change the below switch into a function pointer mapping table in the future
115 switch(GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID))
116 {
117 case GED_BRIDGE_COMMAND_LOG_BUF_GET:
118 pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_get;
119 break;
120 case GED_BRIDGE_COMMAND_LOG_BUF_WRITE:
121 pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_write;
122 break;
123 case GED_BRIDGE_COMMAND_LOG_BUF_RESET:
124 pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_reset;
125 break;
126 case GED_BRIDGE_COMMAND_BOOST_GPU_FREQ:
127 pFunc = (ged_bridge_func_type*)ged_bridge_boost_gpu_freq;
128 break;
129 case GED_BRIDGE_COMMAND_MONITOR_3D_FENCE:
130 pFunc = (ged_bridge_func_type*)ged_bridge_monitor_3D_fence;
131 break;
132 case GED_BRIDGE_COMMAND_QUERY_INFO:
133 pFunc = (ged_bridge_func_type*)ged_bridge_query_info;
134 break;
135 case GED_BRIDGE_COMMAND_NOTIFY_VSYNC:
136 pFunc = (ged_bridge_func_type*)ged_bridge_notify_vsync;
137 break;
138 case GED_BRIDGE_COMMAND_DVFS_PROBE:
139 pFunc = (ged_bridge_func_type*)ged_bridge_dvfs_probe;
140 break;
141 case GED_BRIDGE_COMMAND_DVFS_UM_RETURN:
142 pFunc = (ged_bridge_func_type*)ged_bridge_dvfs_um_retrun;
143 break;
144 default:
145 GED_LOGE("Unknown Bridge ID: %u\n", GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID));
146 break;
147 }
148
149 if (pFunc)
150 {
151 ret = pFunc(pvInt, pvOut);
152 }
153
154 if (psBridgePackageKM->i32OutBufferSize > 0)
155 {
156 if (0 != ged_copy_to_user(psBridgePackageKM->pvParamOut, pvOut, psBridgePackageKM->i32OutBufferSize))
157 {
158 return ret;
159 }
160 }
161 }
162
163 return ret;
6fa3eb70
S
164}
165
166DEFINE_SEMAPHORE(ged_dal_sem);
167
168static long ged_ioctl(struct file *pFile, unsigned int ioctlCmd, unsigned long arg)
169{
02af6beb 170 int ret = -EFAULT;
6fa3eb70
S
171 GED_BRIDGE_PACKAGE *psBridgePackageKM, *psBridgePackageUM = (GED_BRIDGE_PACKAGE*)arg;
172 GED_BRIDGE_PACKAGE sBridgePackageKM;
173
02af6beb
S
174 if (down_interruptible(&ged_dal_sem) < 0)
175 {
176 GED_LOGE("Fail to down ged_dal_sem\n");
177 return -ERESTARTSYS;
178 }
6fa3eb70
S
179
180 psBridgePackageKM = &sBridgePackageKM;
02af6beb
S
181 if (0 != ged_copy_from_user(psBridgePackageKM, psBridgePackageUM, sizeof(GED_BRIDGE_PACKAGE)))
182 {
183 GED_LOGE("Fail to ged_copy_from_user\n");
184 goto unlock_and_return;
185 }
6fa3eb70 186
02af6beb 187 ret = ged_dispatch(psBridgePackageKM);
6fa3eb70
S
188
189unlock_and_return:
02af6beb 190 up(&ged_dal_sem);
6fa3eb70 191
02af6beb 192 return ret;
6fa3eb70
S
193}
194
195#ifdef CONFIG_COMPAT
196static long ged_ioctl_compat(struct file *pFile, unsigned int ioctlCmd, unsigned long arg)
197{
02af6beb
S
198 typedef struct GED_BRIDGE_PACKAGE_32_TAG
199 {
200 unsigned int ui32FunctionID;
201 int i32Size;
202 unsigned int ui32ParamIn;
203 int i32InBufferSize;
204 unsigned int ui32ParamOut;
205 int i32OutBufferSize;
206 } GED_BRIDGE_PACKAGE_32;
207
208 int ret = -EFAULT;
209 GED_BRIDGE_PACKAGE sBridgePackageKM64;
210 GED_BRIDGE_PACKAGE_32 sBridgePackageKM32;
211 GED_BRIDGE_PACKAGE_32 *psBridgePackageKM32 = &sBridgePackageKM32;
212 GED_BRIDGE_PACKAGE_32 *psBridgePackageUM32 = (GED_BRIDGE_PACKAGE_32*)arg;
213
214 if (down_interruptible(&ged_dal_sem) < 0)
215 {
216 GED_LOGE("Fail to down ged_dal_sem\n");
217 return -ERESTARTSYS;
218 }
219
220 if (0 != ged_copy_from_user(psBridgePackageKM32, psBridgePackageUM32, sizeof(GED_BRIDGE_PACKAGE_32)))
221 {
222 GED_LOGE("Fail to ged_copy_from_user\n");
223 goto unlock_and_return;
224 }
225
226 sBridgePackageKM64.ui32FunctionID = psBridgePackageKM32->ui32FunctionID;
227 sBridgePackageKM64.i32Size = sizeof(GED_BRIDGE_PACKAGE);
228 sBridgePackageKM64.pvParamIn = (void*) ((size_t) psBridgePackageKM32->ui32ParamIn);
229 sBridgePackageKM64.pvParamOut = (void*) ((size_t) psBridgePackageKM32->ui32ParamOut);
230 sBridgePackageKM64.i32InBufferSize = psBridgePackageKM32->i32InBufferSize;
231 sBridgePackageKM64.i32OutBufferSize = psBridgePackageKM32->i32OutBufferSize;
232
233 ret = ged_dispatch(&sBridgePackageKM64);
234
6fa3eb70 235unlock_and_return:
02af6beb
S
236 up(&ged_dal_sem);
237
238 return ret;
6fa3eb70
S
239}
240#endif
241
242/******************************************************************************
243 * Module related
244 *****************************************************************************/
245
246static struct file_operations ged_fops = {
02af6beb
S
247 .owner = THIS_MODULE,
248 .open = ged_open,
249 .release = ged_release,
250 .poll = ged_poll,
251 .read = ged_read,
252 .write = ged_write,
253 .unlocked_ioctl = ged_ioctl,
6fa3eb70 254#ifdef CONFIG_COMPAT
02af6beb 255 .compat_ioctl = ged_ioctl_compat,
6fa3eb70
S
256#endif
257};
258
259#if 0
260static struct miscdevice ged_dev = {
02af6beb
S
261 .minor = MISC_DYNAMIC_MINOR,
262 .name = "ged",
263 .fops = &ged_fops,
6fa3eb70
S
264};
265#endif
266
267static void ged_exit(void)
268{
02af6beb
S
269#ifdef GED_DVFS_DEBUG_BUF
270 ged_log_buf_free(ghLogBuf_DVFS);
271 ged_log_buf_free(ghLogBuf_ged_srv);
272 ghLogBuf_DVFS = 0;
273 ghLogBuf_ged_srv = 0;
274#endif
6fa3eb70 275#ifdef GED_DEBUG
02af6beb
S
276 ged_log_buf_free(ghLogBuf_GED);
277 ghLogBuf_GED = 0;
278 ged_log_buf_free(ghLogBuf_GLES);
279 ghLogBuf_GLES = 0;
6fa3eb70 280#endif
02af6beb
S
281 ged_log_buf_free(ghLogBuf_FENCE);
282 ghLogBuf_FENCE = 0;
283 ged_log_buf_free(ghLogBuf_HWC);
284 ghLogBuf_HWC = 0;
285
286 ged_dvfs_system_exit();
287
288 ged_profile_dvfs_exit();
289
290 //ged_notify_vsync_system_exit();
6fa3eb70 291
02af6beb 292 ged_notify_sw_vsync_system_exit();
6fa3eb70 293
02af6beb 294 ged_hal_exit();
6fa3eb70 295
02af6beb 296 ged_log_system_exit();
6fa3eb70 297
02af6beb 298 ged_debugFS_exit();
6fa3eb70 299
02af6beb
S
300 remove_proc_entry(GED_DRIVER_DEVICE_NAME, NULL);
301
302 if (gvIOCTLParamBuf)
303 {
304 vfree(gvIOCTLParamBuf);
305 gvIOCTLParamBuf = NULL;
306 }
6fa3eb70
S
307}
308
309static int ged_init(void)
310{
02af6beb
S
311 GED_ERROR err = GED_ERROR_FAIL;
312
313 gvIOCTLParamBuf = vmalloc(GED_IOCTL_PARAM_BUF_SIZE);
314 if (NULL == gvIOCTLParamBuf)
315 {
316 err = GED_ERROR_OOM;
317 goto ERROR;
318 }
319
320 if (NULL == proc_create(GED_DRIVER_DEVICE_NAME, 0644, NULL, &ged_fops))
321 {
322 err = GED_ERROR_FAIL;
323 GED_LOGE("ged: failed to register ged proc entry!\n");
324 goto ERROR;
325 }
326
327 err = ged_debugFS_init();
328 if (unlikely(err != GED_OK))
329 {
330 GED_LOGE("ged: failed to init debug FS!\n");
331 goto ERROR;
332 }
333
334 err = ged_log_system_init();
335 if (unlikely(err != GED_OK))
336 {
337 GED_LOGE("ged: failed to create gedlog entry!\n");
338 goto ERROR;
339 }
340
341 err = ged_hal_init();
342 if (unlikely(err != GED_OK))
343 {
344 GED_LOGE("ged: failed to create hal entry!\n");
345 goto ERROR;
346 }
347
348 err = ged_notify_sw_vsync_system_init();
349 if (unlikely(err != GED_OK))
350 {
351 GED_LOGE("ged: failed to init notify sw vsync!\n");
352 goto ERROR;
353 }
354
355 err = ged_profile_dvfs_init();
356 if (unlikely(err != GED_OK))
357 {
358 GED_LOGE("ged: failed to init profile dvfs!\n");
359 goto ERROR;
360 }
361
362
363 err = ged_dvfs_system_init();
364 if (unlikely(err != GED_OK))
365 {
366 GED_LOGE("ged: failed to init common dvfs!\n");
367 goto ERROR;
368 }
369
6fa3eb70
S
370
371#ifdef GED_DEBUG
02af6beb
S
372 ghLogBuf_GLES = ged_log_buf_alloc(160, 128 * 160, GED_LOG_BUF_TYPE_RINGBUFFER, GED_LOG_BUF_COMMON_GLES, NULL);
373 ghLogBuf_GED = ged_log_buf_alloc(32, 64 * 32, GED_LOG_BUF_TYPE_RINGBUFFER, "GED internal", NULL);
374#endif
375 ghLogBuf_HWC = ged_log_buf_alloc(4096, 128 * 4096, GED_LOG_BUF_TYPE_RINGBUFFER, GED_LOG_BUF_COMMON_HWC, NULL);
376 ghLogBuf_FENCE = ged_log_buf_alloc(256, 128 * 256, GED_LOG_BUF_TYPE_RINGBUFFER, GED_LOG_BUF_COMMON_FENCE, NULL);
377
378#ifdef GED_DVFS_DEBUG_BUF
379#ifdef GED_LOG_SIZE_LIMITED
380 ghLogBuf_DVFS = ged_log_buf_alloc(20*60, 20*60*80, GED_LOG_BUF_TYPE_RINGBUFFER, "DVFS_Log", "ged_dvfs_debug_limited");
381#else
382 ghLogBuf_DVFS = ged_log_buf_alloc(20*60*10, 20*60*10*80, GED_LOG_BUF_TYPE_RINGBUFFER, "DVFS_Log", "ged_dvfs_debug");
6fa3eb70 383#endif
02af6beb
S
384 ghLogBuf_ged_srv = ged_log_buf_alloc(32, 32*80, GED_LOG_BUF_TYPE_RINGBUFFER, "ged_srv_Log", "ged_srv_debug");
385#endif
6fa3eb70 386
02af6beb 387 return 0;
6fa3eb70
S
388
389ERROR:
02af6beb 390 ged_exit();
6fa3eb70 391
02af6beb 392 return -EFAULT;
6fa3eb70
S
393}
394
395module_init(ged_init);
396module_exit(ged_exit);
397
398MODULE_LICENSE("GPL");
399MODULE_DESCRIPTION("MediaTek GED Driver");
400MODULE_AUTHOR("MediaTek Inc.");