3 * MediaTek <www.MediaTek.com>
5 * MTK GPU Extension Device
9 #include <linux/cdev.h>
10 #include <linux/delay.h>
11 #include <linux/device.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>
23 //#include <mach/system.h>
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 <mt-plat/aee.h>
31 #include "ged_debugFS.h"
34 #include "ged_bridge.h"
35 #include "ged_profile_dvfs.h"
36 #include "ged_monitor_3D_fence.h"
37 #include "ged_notify_sw_vsync.h"
41 #define GED_DRIVER_DEVICE_NAME "ged"
43 #define GED_IOCTL_PARAM_BUF_SIZE 0x3000 //12KB
46 #define GED_LOG_BUF_COMMON_GLES "GLES"
47 static GED_LOG_BUF_HANDLE ghLogBuf_GLES
= 0;
48 GED_LOG_BUF_HANDLE ghLogBuf_GED
= 0;
51 #define GED_LOG_BUF_COMMON_HWC "HWC"
52 static GED_LOG_BUF_HANDLE ghLogBuf_HWC
= 0;
53 #define GED_LOG_BUF_COMMON_FENCE "FENCE"
54 static GED_LOG_BUF_HANDLE ghLogBuf_FENCE
= 0;
56 GED_LOG_BUF_HANDLE ghLogBuf_DVFS
= 0;
57 GED_LOG_BUF_HANDLE ghLogBuf_ged_srv
= 0;
61 static void* gvIOCTLParamBuf
= NULL
;
63 /******************************************************************************
65 *****************************************************************************/
66 static int ged_open(struct inode
*inode
, struct file
*filp
)
68 GED_LOGE("%s:%d:%d\n", __func__
, MAJOR(inode
->i_rdev
), MINOR(inode
->i_rdev
));
72 static int ged_release(struct inode
*inode
, struct file
*filp
)
74 GED_LOGE("%s:%d:%d\n", __func__
, MAJOR(inode
->i_rdev
), MINOR(inode
->i_rdev
));
78 static unsigned int ged_poll(struct file
*file
, struct poll_table_struct
*ptable
)
83 static ssize_t
ged_read(struct file
*filp
, char __user
*buf
, size_t count
, loff_t
*f_pos
)
88 static ssize_t
ged_write(struct file
*filp
, const char __user
*buf
, size_t count
, loff_t
*f_pos
)
93 static long ged_dispatch(GED_BRIDGE_PACKAGE
*psBridgePackageKM
)
97 typedef int (ged_bridge_func_type
)(void*, void*);
98 ged_bridge_func_type
* pFunc
= NULL
;
100 if ((psBridgePackageKM
->i32InBufferSize
>=0) && (psBridgePackageKM
->i32OutBufferSize
>=0) &&
101 (psBridgePackageKM
->i32InBufferSize
+ psBridgePackageKM
->i32OutBufferSize
< GED_IOCTL_PARAM_BUF_SIZE
))
103 pvInt
= gvIOCTLParamBuf
;
104 pvOut
= (void*)((char*)pvInt
+ (uintptr_t)psBridgePackageKM
->i32InBufferSize
);
105 if (psBridgePackageKM
->i32InBufferSize
> 0)
107 if (0 != ged_copy_from_user(pvInt
, psBridgePackageKM
->pvParamIn
, psBridgePackageKM
->i32InBufferSize
))
109 GED_LOGE("ged_copy_from_user fail\n");
114 // we will change the below switch into a function pointer mapping table in the future
115 switch(GED_GET_BRIDGE_ID(psBridgePackageKM
->ui32FunctionID
))
117 case GED_BRIDGE_COMMAND_LOG_BUF_GET
:
118 pFunc
= (ged_bridge_func_type
*)ged_bridge_log_buf_get
;
120 case GED_BRIDGE_COMMAND_LOG_BUF_WRITE
:
121 pFunc
= (ged_bridge_func_type
*)ged_bridge_log_buf_write
;
123 case GED_BRIDGE_COMMAND_LOG_BUF_RESET
:
124 pFunc
= (ged_bridge_func_type
*)ged_bridge_log_buf_reset
;
126 case GED_BRIDGE_COMMAND_BOOST_GPU_FREQ
:
127 pFunc
= (ged_bridge_func_type
*)ged_bridge_boost_gpu_freq
;
129 case GED_BRIDGE_COMMAND_MONITOR_3D_FENCE
:
130 pFunc
= (ged_bridge_func_type
*)ged_bridge_monitor_3D_fence
;
132 case GED_BRIDGE_COMMAND_QUERY_INFO
:
133 pFunc
= (ged_bridge_func_type
*)ged_bridge_query_info
;
135 case GED_BRIDGE_COMMAND_NOTIFY_VSYNC
:
136 pFunc
= (ged_bridge_func_type
*)ged_bridge_notify_vsync
;
138 case GED_BRIDGE_COMMAND_DVFS_PROBE
:
139 pFunc
= (ged_bridge_func_type
*)ged_bridge_dvfs_probe
;
141 case GED_BRIDGE_COMMAND_DVFS_UM_RETURN
:
142 pFunc
= (ged_bridge_func_type
*)ged_bridge_dvfs_um_retrun
;
145 GED_LOGE("Unknown Bridge ID: %u\n", GED_GET_BRIDGE_ID(psBridgePackageKM
->ui32FunctionID
));
151 ret
= pFunc(pvInt
, pvOut
);
154 if (psBridgePackageKM
->i32OutBufferSize
> 0)
156 if (0 != ged_copy_to_user(psBridgePackageKM
->pvParamOut
, pvOut
, psBridgePackageKM
->i32OutBufferSize
))
166 DEFINE_SEMAPHORE(ged_dal_sem
);
168 static long ged_ioctl(struct file
*pFile
, unsigned int ioctlCmd
, unsigned long arg
)
171 GED_BRIDGE_PACKAGE
*psBridgePackageKM
, *psBridgePackageUM
= (GED_BRIDGE_PACKAGE
*)arg
;
172 GED_BRIDGE_PACKAGE sBridgePackageKM
;
174 if (down_interruptible(&ged_dal_sem
) < 0)
176 GED_LOGE("Fail to down ged_dal_sem\n");
180 psBridgePackageKM
= &sBridgePackageKM
;
181 if (0 != ged_copy_from_user(psBridgePackageKM
, psBridgePackageUM
, sizeof(GED_BRIDGE_PACKAGE
)))
183 GED_LOGE("Fail to ged_copy_from_user\n");
184 goto unlock_and_return
;
187 ret
= ged_dispatch(psBridgePackageKM
);
196 static long ged_ioctl_compat(struct file
*pFile
, unsigned int ioctlCmd
, unsigned long arg
)
198 typedef struct GED_BRIDGE_PACKAGE_32_TAG
200 unsigned int ui32FunctionID
;
202 unsigned int ui32ParamIn
;
204 unsigned int ui32ParamOut
;
205 int i32OutBufferSize
;
206 } GED_BRIDGE_PACKAGE_32
;
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
;
214 if (down_interruptible(&ged_dal_sem
) < 0)
216 GED_LOGE("Fail to down ged_dal_sem\n");
220 if (0 != ged_copy_from_user(psBridgePackageKM32
, psBridgePackageUM32
, sizeof(GED_BRIDGE_PACKAGE_32
)))
222 GED_LOGE("Fail to ged_copy_from_user\n");
223 goto unlock_and_return
;
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
;
233 ret
= ged_dispatch(&sBridgePackageKM64
);
242 /******************************************************************************
244 *****************************************************************************/
246 static struct file_operations ged_fops
= {
247 .owner
= THIS_MODULE
,
249 .release
= ged_release
,
253 .unlocked_ioctl
= ged_ioctl
,
255 .compat_ioctl
= ged_ioctl_compat
,
260 static struct miscdevice ged_dev
= {
261 .minor
= MISC_DYNAMIC_MINOR
,
267 static void ged_exit(void)
269 #ifdef GED_DVFS_DEBUG_BUF
270 ged_log_buf_free(ghLogBuf_DVFS
);
271 ged_log_buf_free(ghLogBuf_ged_srv
);
273 ghLogBuf_ged_srv
= 0;
276 ged_log_buf_free(ghLogBuf_GED
);
278 ged_log_buf_free(ghLogBuf_GLES
);
281 ged_log_buf_free(ghLogBuf_FENCE
);
283 ged_log_buf_free(ghLogBuf_HWC
);
286 ged_dvfs_system_exit();
288 ged_profile_dvfs_exit();
290 //ged_notify_vsync_system_exit();
292 ged_notify_sw_vsync_system_exit();
296 ged_log_system_exit();
300 remove_proc_entry(GED_DRIVER_DEVICE_NAME
, NULL
);
304 vfree(gvIOCTLParamBuf
);
305 gvIOCTLParamBuf
= NULL
;
309 static int ged_init(void)
311 GED_ERROR err
= GED_ERROR_FAIL
;
313 gvIOCTLParamBuf
= vmalloc(GED_IOCTL_PARAM_BUF_SIZE
);
314 if (NULL
== gvIOCTLParamBuf
)
320 if (NULL
== proc_create(GED_DRIVER_DEVICE_NAME
, 0644, NULL
, &ged_fops
))
322 err
= GED_ERROR_FAIL
;
323 GED_LOGE("ged: failed to register ged proc entry!\n");
327 err
= ged_debugFS_init();
328 if (unlikely(err
!= GED_OK
))
330 GED_LOGE("ged: failed to init debug FS!\n");
334 err
= ged_log_system_init();
335 if (unlikely(err
!= GED_OK
))
337 GED_LOGE("ged: failed to create gedlog entry!\n");
341 err
= ged_hal_init();
342 if (unlikely(err
!= GED_OK
))
344 GED_LOGE("ged: failed to create hal entry!\n");
348 err
= ged_notify_sw_vsync_system_init();
349 if (unlikely(err
!= GED_OK
))
351 GED_LOGE("ged: failed to init notify sw vsync!\n");
355 err
= ged_profile_dvfs_init();
356 if (unlikely(err
!= GED_OK
))
358 GED_LOGE("ged: failed to init profile dvfs!\n");
363 err
= ged_dvfs_system_init();
364 if (unlikely(err
!= GED_OK
))
366 GED_LOGE("ged: failed to init common dvfs!\n");
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
);
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
);
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");
382 ghLogBuf_DVFS
= ged_log_buf_alloc(20*60*10, 20*60*10*80, GED_LOG_BUF_TYPE_RINGBUFFER
, "DVFS_Log", "ged_dvfs_debug");
384 ghLogBuf_ged_srv
= ged_log_buf_alloc(32, 32*80, GED_LOG_BUF_TYPE_RINGBUFFER
, "ged_srv_Log", "ged_srv_debug");
395 module_init(ged_init
);
396 module_exit(ged_exit
);
398 MODULE_LICENSE("GPL");
399 MODULE_DESCRIPTION("MediaTek GED Driver");
400 MODULE_AUTHOR("MediaTek Inc.");