Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include <generated/autoconf.h> |
2 | #include <linux/module.h> | |
3 | #include <linux/mm.h> | |
4 | #include <linux/init.h> | |
5 | #include <linux/fb.h> | |
6 | #include <linux/delay.h> | |
7 | #include <linux/device.h> | |
8 | #include <linux/platform_device.h> | |
9 | #include <linux/dma-mapping.h> | |
10 | #include <linux/earlysuspend.h> | |
11 | #include <linux/kthread.h> | |
12 | #include <linux/rtpm_prio.h> | |
13 | #include <linux/vmalloc.h> | |
14 | #include <linux/disp_assert_layer.h> | |
15 | #include <linux/semaphore.h> | |
16 | #include <linux/xlog.h> | |
17 | #include <linux/mutex.h> | |
18 | #include <linux/leds-mt65xx.h> | |
19 | #include <linux/file.h> | |
20 | #include <linux/ion_drv.h> | |
21 | #include <linux/list.h> | |
22 | ||
23 | ||
24 | #include <asm/uaccess.h> | |
25 | #include <asm/atomic.h> | |
26 | #include <asm/mach-types.h> | |
27 | #include <asm/cacheflush.h> | |
28 | #include <asm/io.h> | |
29 | ||
30 | #include <mach/dma.h> | |
31 | #include <mach/irqs.h> | |
32 | #include <mach/m4u_port.h> | |
33 | #include <linux/dma-mapping.h> | |
34 | ||
35 | #include "mach/mt_boot.h" | |
36 | ||
37 | #include "debug.h" | |
38 | #include "disp_drv.h" | |
39 | #include "ddp_hal.h" | |
40 | #include "disp_drv_log.h" | |
41 | #include "disp_hal.h" | |
42 | ||
43 | #include "mtkfb.h" | |
44 | #include "mtkfb_console.h" | |
45 | #include "mtkfb_info.h" | |
46 | #include "ddp_ovl.h" | |
47 | #include "mtkfb_priv.h" | |
48 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
49 | #include "disp_ovl_engine_api.h" | |
50 | #include "disp_ovl_engine_hw.h" | |
51 | #include "disp_ovl_engine_core.h" | |
52 | #endif | |
53 | ||
54 | // for MTK_HDMI_MAIN_PATH | |
55 | #include "disp_drv_platform.h" | |
56 | ||
57 | #define NONFLUSH | |
58 | ||
59 | ||
60 | #define MTK_FB_ALIGNMENT 16 | |
61 | #define ALIGN_TO(x, n) \ | |
62 | (((x) + ((n) - 1)) & ~((n) - 1)) | |
63 | ||
64 | //#undef pr_info | |
65 | //#define pr_info printk | |
66 | ||
67 | unsigned int EnableVSyncLog = 0; | |
68 | ||
69 | static u32 MTK_FB_XRES = 0; | |
70 | static u32 MTK_FB_YRES = 0; | |
71 | static u32 MTK_FB_BPP = 0; | |
72 | static u32 MTK_FB_PAGES = 0; | |
73 | static u32 fb_xres_update = 0; | |
74 | static u32 fb_yres_update = 0; | |
75 | ||
76 | #define MTK_FB_XRESV (ALIGN_TO(MTK_FB_XRES, disphal_get_fb_alignment())) | |
77 | #define MTK_FB_YRESV (ALIGN_TO(MTK_FB_YRES, disphal_get_fb_alignment()) * MTK_FB_PAGES) /* For page flipping */ | |
78 | #define MTK_FB_BYPP ((MTK_FB_BPP + 7) >> 3) | |
79 | #define MTK_FB_LINE (ALIGN_TO(MTK_FB_XRES, disphal_get_fb_alignment()) * MTK_FB_BYPP) | |
80 | #define MTK_FB_SIZE (MTK_FB_LINE * ALIGN_TO(MTK_FB_YRES, disphal_get_fb_alignment())) | |
81 | ||
82 | #define MTK_FB_SIZEV (MTK_FB_LINE * ALIGN_TO(MTK_FB_YRES, disphal_get_fb_alignment()) * MTK_FB_PAGES) | |
83 | ||
84 | #define CHECK_RET(expr) \ | |
85 | do { \ | |
86 | int ret = (expr); \ | |
87 | ASSERT(0 == ret); \ | |
88 | } while (0) | |
89 | ||
90 | ||
91 | static size_t mtkfb_log_on = false; | |
92 | #define MTKFB_LOG(fmt, arg...) \ | |
93 | do { \ | |
94 | if (mtkfb_log_on) DISP_LOG_PRINT(ANDROID_LOG_WARN, "MTKFB", fmt, ##arg); \ | |
95 | }while (0) | |
96 | ||
97 | #define MTKFB_FUNC() \ | |
98 | do { \ | |
99 | if(mtkfb_log_on) DISP_LOG_PRINT(ANDROID_LOG_INFO, "MTKFB", "[Func]%s\n", __func__); \ | |
100 | }while (0) | |
101 | ||
102 | ||
103 | #define MTKFB_MSG(fmt, arg...) \ | |
104 | do { \ | |
105 | pr_err("[MTKFB] mt8127 "fmt, ##arg); \ | |
106 | }while (0) | |
107 | #define PRNERR(fmt, args...) DISP_LOG_PRINT(ANDROID_LOG_INFO, "MTKFB", fmt, ## args); | |
108 | /* [PLATFORM]-Add-BEGIN by TCTSZ.yaohui.zeng, 2015/04/15,MTK patch,fix FB suspend/resume DSI issue*/ | |
109 | extern BOOL _IsEngineBusy(void); | |
110 | extern wait_queue_head_t _dsi_wait_vm_done_queue; | |
111 | /* [PLATFORM]-Add-END by TCTSZ.yaohui.zeng, 2015/04/15*/ | |
112 | ||
113 | void mtkfb_log_enable(int enable) | |
114 | { | |
115 | mtkfb_log_on = enable; | |
116 | MTKFB_LOG("mtkfb log %s\n", enable?"enabled":"disabled"); | |
117 | } | |
118 | ||
119 | void mtkfb_clear_lcm(void); | |
120 | ||
121 | //int ion_handle_note[1024] = {0}; //mtk02420 | |
122 | ||
123 | // --------------------------------------------------------------------------- | |
124 | // local variables | |
125 | // --------------------------------------------------------------------------- | |
126 | ||
127 | unsigned int fb_pa = 0; | |
128 | static BOOL mtkfb_enable_mmu = TRUE; | |
129 | ||
130 | static const struct timeval FRAME_INTERVAL = {0, 30000}; // 33ms | |
131 | ||
132 | atomic_t has_pending_update = ATOMIC_INIT(0); | |
133 | struct fb_overlay_layer video_layerInfo; | |
134 | UINT32 dbr_backup = 0; | |
135 | UINT32 dbg_backup = 0; | |
136 | UINT32 dbb_backup = 0; | |
137 | bool fblayer_dither_needed = false; | |
138 | static unsigned int video_rotation = 0; | |
139 | static UINT32 mtkfb_using_layer_type = LAYER_2D; | |
140 | static bool hwc_force_fb_enabled = true; | |
141 | bool is_ipoh_bootup = false; | |
142 | struct fb_info *mtkfb_fbi; | |
143 | struct fb_overlay_layer fb_layer_context; | |
144 | ||
145 | unsigned int decouple_addr = 0; // It's PA = MVA after m4u mapping | |
146 | unsigned int decouple_size = 0; | |
147 | ||
148 | extern unsigned int g_fb_pattern_en; | |
149 | extern int fb_pattern(struct mtkfb_device *fbdev, struct fb_overlay_config *fb_config); | |
150 | extern wait_queue_head_t _dsi_wait_vm_done_queue; | |
151 | extern BOOL _IsEngineBusy(void); | |
152 | /* This mutex is used to prevent tearing due to page flipping when adbd is | |
153 | reading the front buffer | |
154 | */ | |
155 | DEFINE_SEMAPHORE(sem_flipping); | |
156 | DEFINE_SEMAPHORE(sem_early_suspend); | |
157 | DEFINE_SEMAPHORE(sem_overlay_buffer); | |
158 | ||
159 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
160 | extern OVL_CONFIG_STRUCT cached_layer_config[DDP_OVL_LAYER_MUN]; | |
161 | #endif | |
162 | DEFINE_MUTEX(OverlaySettingMutex); | |
163 | atomic_t OverlaySettingDirtyFlag = ATOMIC_INIT(0); | |
164 | atomic_t OverlaySettingApplied = ATOMIC_INIT(0); | |
165 | unsigned int PanDispSettingPending = 0; | |
166 | unsigned int PanDispSettingDirty = 0; | |
167 | unsigned int PanDispSettingApplied = 0; | |
168 | ||
169 | DECLARE_WAIT_QUEUE_HEAD(reg_update_wq); | |
170 | ||
171 | unsigned int need_esd_check = 0; | |
172 | DECLARE_WAIT_QUEUE_HEAD(esd_check_wq); | |
173 | ||
174 | extern unsigned int disp_running; | |
175 | extern wait_queue_head_t disp_done_wq; | |
176 | ||
177 | DEFINE_MUTEX(ScreenCaptureMutex); | |
178 | ||
179 | BOOL is_early_suspended = FALSE; | |
180 | static int sem_flipping_cnt = 1; | |
181 | static int sem_early_suspend_cnt = 1; | |
182 | static int sem_overlay_buffer_cnt = 1; | |
183 | static int vsync_cnt = 0; | |
184 | ||
185 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
186 | DISP_OVL_ENGINE_INSTANCE_HANDLE mtkfb_instance = 0xff; | |
187 | #endif | |
188 | extern BOOL is_engine_in_suspend_mode; | |
189 | extern BOOL is_lcm_in_suspend_mode; | |
190 | ||
191 | // --------------------------------------------------------------------------- | |
192 | // local function declarations | |
193 | // --------------------------------------------------------------------------- | |
194 | ||
195 | static int init_framebuffer(struct fb_info *info); | |
196 | //static int mtkfb_set_overlay_config(struct mtkfb_device *fbdev, | |
197 | // struct fb_overlay_config* config, struct sync_fence* fences[]); | |
198 | int mtkfb_queue_overlay_config(struct mtkfb_device *fbdev, | |
199 | struct fb_overlay_config* config); | |
200 | static int mtkfb_set_overlay_layer(struct mtkfb_device *fbdev, | |
201 | struct fb_overlay_layer* layerInfo); | |
202 | static int mtkfb_get_overlay_layer_info(struct fb_overlay_layer_info* layerInfo); | |
203 | static int mtkfb_update_screen(struct fb_info *info); | |
204 | static void mtkfb_update_screen_impl(void); | |
205 | ||
206 | #if defined(MTK_HDMI_SUPPORT) | |
207 | extern void hdmi_setorientation(int orientation); | |
208 | extern void MTK_HDMI_Set_Security_Output(int enable); | |
209 | /* temporary solution for hdmi svp p1, always mute hdmi for svp */ | |
210 | void MTK_HDMI_Set_Security_Output_SVP_P1(int enable); | |
211 | #endif | |
212 | ||
213 | // --------------------------------------------------------------------------- | |
214 | // Timer Routines | |
215 | // --------------------------------------------------------------------------- | |
216 | static struct task_struct *screen_update_task = NULL; | |
217 | static struct task_struct *esd_recovery_task = NULL; | |
218 | unsigned int lcd_fps = 6000; | |
219 | wait_queue_head_t screen_update_wq; | |
220 | extern BOOL dal_shown; | |
221 | ||
222 | /* Grallc extra bit type */ | |
223 | enum { | |
224 | GRALLOC_EXTRA_BIT_TYPE_CPU = 0x00000000, | |
225 | GRALLOC_EXTRA_BIT_TYPE_GPU = 0x00000001, | |
226 | GRALLOC_EXTRA_BIT_TYPE_VIDEO = 0x00000002, | |
227 | GRALLOC_EXTRA_BIT_TYPE_CAMERA = 0x00000003, | |
228 | GRALLOC_EXTRA_MASK_TYPE = 0x00000003, | |
229 | }; | |
230 | ||
231 | ||
232 | #if defined(DFO_USE_NEW_API) | |
233 | #if 1 | |
234 | extern int dfo_query(const char *s, unsigned long *v); | |
235 | #endif | |
236 | #else | |
237 | #include <mach/dfo_boot.h> | |
238 | static disp_dfo_item_t disp_dfo_setting[] = | |
239 | { | |
240 | {"LCM_FAKE_WIDTH", 0}, | |
241 | {"LCM_FAKE_HEIGHT", 0}, | |
242 | {"DISP_DEBUG_SWITCH", 0} | |
243 | }; | |
244 | ||
245 | #define MT_DISP_DFO_DEBUG | |
246 | #ifdef MT_DISP_DFO_DEBUG | |
247 | #define disp_dfo_printf(string, args...) printk("[DISP/DFO]"string, ##args) | |
248 | #else | |
249 | #define disp_dfo_printf(string, args...) () | |
250 | #endif | |
251 | ||
252 | // this function will be called in mt_fixup()@mt_devs.c. which will send DFO information organized as tag_dfo_boot struct. | |
253 | // because lcm_params isn't inited here, so we will change lcm_params later in mtkfb_probe. | |
254 | unsigned int mtkfb_parse_dfo_setting(void *dfo_tbl, int num) | |
255 | { | |
256 | char *disp_name = NULL; | |
257 | //int *disp_value; | |
258 | char *tag_name; | |
259 | int tag_value; | |
260 | int i, j; | |
261 | tag_dfo_boot *dfo_data; | |
262 | ||
263 | disp_dfo_printf("enter mtkfb_parse_dfo_setting\n"); | |
264 | ||
265 | if(dfo_tbl == NULL) | |
266 | return -1; | |
267 | ||
268 | dfo_data = (tag_dfo_boot *)dfo_tbl; | |
269 | for (i=0; i<(sizeof(disp_dfo_setting)/sizeof(disp_dfo_item_t)); i++) | |
270 | { | |
271 | disp_name = disp_dfo_setting[i].name; | |
272 | ||
273 | for (j=0; j<num; j++) | |
274 | { | |
275 | tag_name = dfo_data->name[j]; | |
276 | tag_value = dfo_data->value[j]; | |
277 | if(!strcmp(disp_name, tag_name)) | |
278 | { | |
279 | disp_dfo_setting[i].value = tag_value; | |
280 | disp_dfo_printf("%s = [DEC]%d [HEX]0x%08x\n", disp_dfo_setting[i].name, disp_dfo_setting[i].value, disp_dfo_setting[i].value); | |
281 | } | |
282 | } | |
283 | } | |
284 | ||
285 | disp_dfo_printf("leave mtkfb_parse_dfo_setting\n"); | |
286 | ||
287 | return 0; | |
288 | } | |
289 | ||
290 | int mtkfb_get_dfo_setting(const char *string, unsigned int *value) | |
291 | { | |
292 | char *disp_name; | |
293 | int disp_value; | |
294 | int i; | |
295 | ||
296 | if(string == NULL) | |
297 | return -1; | |
298 | ||
299 | for (i=0; i<(sizeof(disp_dfo_setting)/sizeof(disp_dfo_item_t)); i++) | |
300 | { | |
301 | disp_name = disp_dfo_setting[i].name; | |
302 | disp_value = disp_dfo_setting[i].value; | |
303 | if(!strcmp(disp_name, string)) | |
304 | { | |
305 | *value = disp_value; | |
306 | disp_dfo_printf("%s = [DEC]%d [HEX]0x%08x\n", disp_name, disp_value, disp_value); | |
307 | return 0; | |
308 | } | |
309 | } | |
310 | ||
311 | return 0; | |
312 | } | |
313 | #endif | |
314 | ||
315 | ||
316 | void mtkfb_pan_disp_test(void) | |
317 | { | |
318 | MTKFB_FUNC(); | |
319 | if (down_interruptible(&sem_flipping)) { | |
320 | pr_info("[fb driver] can't get semaphore:%d\n", __LINE__); | |
321 | return; | |
322 | } | |
323 | sem_flipping_cnt--; | |
324 | DISP_LOG_PRINT(ANDROID_LOG_WARN, "MTKFB", "wait sem_flipping\n"); | |
325 | if (down_interruptible(&sem_early_suspend)) { | |
326 | pr_info("[fb driver] can't get semaphore:%d\n", __LINE__); | |
327 | sem_flipping_cnt++; | |
328 | up(&sem_flipping); | |
329 | return; | |
330 | } | |
331 | sem_early_suspend_cnt--; | |
332 | ||
333 | DISP_LOG_PRINT(ANDROID_LOG_WARN, "MTKFB", "wait sem_early_suspend\n"); | |
334 | if (down_interruptible(&sem_overlay_buffer)) { | |
335 | pr_info("[fb driver] can't get semaphore,%d\n", __LINE__); | |
336 | sem_early_suspend_cnt++; | |
337 | up(&sem_early_suspend); | |
338 | ||
339 | sem_flipping_cnt++; | |
340 | up(&sem_flipping); | |
341 | return; | |
342 | } | |
343 | sem_overlay_buffer_cnt--; | |
344 | DISP_LOG_PRINT(ANDROID_LOG_WARN, "MTKFB", "wait sem_overlay_buffer\n"); | |
345 | if (is_early_suspended) goto end; | |
346 | ||
347 | end: | |
348 | sem_overlay_buffer_cnt++; | |
349 | sem_early_suspend_cnt++; | |
350 | sem_flipping_cnt++; | |
351 | up(&sem_overlay_buffer); | |
352 | up(&sem_early_suspend); | |
353 | up(&sem_flipping); | |
354 | } | |
355 | ||
356 | void mtkfb_show_sem_cnt(void) | |
357 | { | |
358 | pr_info("[FB driver: sem cnt = %d, %d, %d. fps = %d, vsync_cnt = %d\n", sem_overlay_buffer_cnt, sem_early_suspend_cnt, sem_flipping_cnt, lcd_fps, vsync_cnt); | |
359 | pr_info("[FB driver: sem cnt = %d, %d, %d\n", sem_overlay_buffer.count, sem_early_suspend.count, sem_flipping.count); | |
360 | } | |
361 | ||
362 | void mtkfb_hang_test(bool en) | |
363 | { | |
364 | MTKFB_FUNC(); | |
365 | if(en){ | |
366 | if (down_interruptible(&sem_flipping)) { | |
367 | pr_info("[fb driver] can't get semaphore:%d\n", __LINE__); | |
368 | return; | |
369 | } | |
370 | sem_flipping_cnt--; | |
371 | } | |
372 | else{ | |
373 | sem_flipping_cnt++; | |
374 | up(&sem_flipping); | |
375 | } | |
376 | } | |
377 | ||
378 | BOOL esd_kthread_pause = TRUE; | |
379 | ||
380 | void esd_recovery_pause(BOOL en) | |
381 | { | |
382 | esd_kthread_pause = en; | |
383 | } | |
384 | ||
385 | static int esd_recovery_kthread(void *data) | |
386 | { | |
387 | //struct sched_param param = { .sched_priority = RTPM_PRIO_SCRN_UPDATE }; | |
388 | //sched_setscheduler(current, SCHED_RR, ¶m); | |
389 | MTKFB_LOG("enter esd_recovery_kthread()\n"); | |
390 | for( ;; ) { | |
391 | ||
392 | if (kthread_should_stop()) | |
393 | break; | |
394 | ||
395 | MTKFB_LOG("sleep start in esd_recovery_kthread()\n"); | |
396 | msleep(2000); //2s | |
397 | MTKFB_LOG("sleep ends in esd_recovery_kthread()\n"); | |
398 | ||
399 | if(!esd_kthread_pause) | |
400 | { | |
401 | if(is_early_suspended) | |
402 | { | |
403 | MTKFB_LOG("is_early_suspended in esd_recovery_kthread()\n"); | |
404 | continue; | |
405 | } | |
406 | ///execute ESD check and recover flow | |
407 | MTKFB_LOG("DISP_EsdCheck starts\n"); | |
408 | need_esd_check = 1; | |
409 | wait_event_interruptible(esd_check_wq, !need_esd_check); | |
410 | MTKFB_LOG("DISP_EsdCheck ends\n"); | |
411 | } | |
412 | } | |
413 | ||
414 | ||
415 | MTKFB_LOG("exit esd_recovery_kthread()\n"); | |
416 | return 0; | |
417 | } | |
418 | ||
419 | ||
420 | /* | |
421 | * --------------------------------------------------------------------------- | |
422 | * mtkfb_set_lcm_inited() will be called in mt6516_board_init() | |
423 | * --------------------------------------------------------------------------- | |
424 | */ | |
425 | static BOOL is_lcm_inited = FALSE; | |
426 | void mtkfb_set_lcm_inited(BOOL inited) | |
427 | { | |
428 | is_lcm_inited = inited; | |
429 | } | |
430 | ||
431 | /* | |
432 | * --------------------------------------------------------------------------- | |
433 | * fbdev framework callbacks and the ioctl interface | |
434 | * --------------------------------------------------------------------------- | |
435 | */ | |
436 | /* Called each time the mtkfb device is opened */ | |
437 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) | |
438 | static int mtkfb_open(struct file *file, struct fb_info *info, int user) | |
439 | #else | |
440 | static int mtkfb_open(struct fb_info *info, int user) | |
441 | #endif | |
442 | { | |
443 | NOT_REFERENCED(info); | |
444 | NOT_REFERENCED(user); | |
445 | ||
446 | MTKFB_FUNC(); | |
447 | ||
448 | MSG_FUNC_ENTER(); | |
449 | MSG_FUNC_LEAVE(); | |
450 | return 0; | |
451 | } | |
452 | ||
453 | /* Called when the mtkfb device is closed. We make sure that any pending | |
454 | * gfx DMA operations are ended, before we return. */ | |
455 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) | |
456 | static int mtkfb_release(struct file *file, struct fb_info *info, int user) | |
457 | #else | |
458 | static int mtkfb_release(struct fb_info *info, int user) | |
459 | #endif | |
460 | ||
461 | { | |
462 | ||
463 | NOT_REFERENCED(info); | |
464 | NOT_REFERENCED(user); | |
465 | ||
466 | MTKFB_FUNC(); | |
467 | ||
468 | MSG_FUNC_ENTER(); | |
469 | MSG_FUNC_LEAVE(); | |
470 | return 0; | |
471 | } | |
472 | ||
473 | /* Store a single color palette entry into a pseudo palette or the hardware | |
474 | * palette if one is available. For now we support only 16bpp and thus store | |
475 | * the entry only to the pseudo palette. | |
476 | */ | |
477 | static int mtkfb_setcolreg(u_int regno, u_int red, u_int green, | |
478 | u_int blue, u_int transp, | |
479 | struct fb_info *info) | |
480 | { | |
481 | int r = 0; | |
482 | unsigned bpp, m; | |
483 | ||
484 | NOT_REFERENCED(transp); | |
485 | ||
486 | MSG_FUNC_ENTER(); | |
487 | ||
488 | bpp = info->var.bits_per_pixel; | |
489 | m = 1 << bpp; | |
490 | if (regno >= m) | |
491 | { | |
492 | r = -EINVAL; | |
493 | goto exit; | |
494 | } | |
495 | ||
496 | switch (bpp) | |
497 | { | |
498 | case 16: | |
499 | /* RGB 565 */ | |
500 | ((u32 *)(info->pseudo_palette))[regno] = | |
501 | ((red & 0xF800) | | |
502 | ((green & 0xFC00) >> 5) | | |
503 | ((blue & 0xF800) >> 11)); | |
504 | break; | |
505 | case 32: | |
506 | /* ARGB8888 */ | |
507 | ((u32 *)(info->pseudo_palette))[regno] = | |
508 | (0xff000000) | | |
509 | ((red & 0xFF00) << 8) | | |
510 | ((green & 0xFF00) ) | | |
511 | ((blue & 0xFF00) >> 8); | |
512 | break; | |
513 | ||
514 | // TODO: RGB888, BGR888, ABGR8888 | |
515 | ||
516 | default: | |
517 | ASSERT(0); | |
518 | } | |
519 | ||
520 | exit: | |
521 | MSG_FUNC_LEAVE(); | |
522 | return r; | |
523 | } | |
524 | ||
525 | static void mtkfb_update_screen_impl(void) | |
526 | { | |
527 | BOOL down_sem = FALSE; | |
528 | MTKFB_FUNC(); | |
529 | MMProfileLog(MTKFB_MMP_Events.UpdateScreenImpl, MMProfileFlagStart); | |
530 | if (down_interruptible(&sem_overlay_buffer)) { | |
531 | pr_info("[FB Driver] can't get semaphore in mtkfb_update_screen_impl()\n"); | |
532 | } | |
533 | else{ | |
534 | down_sem = TRUE; | |
535 | sem_overlay_buffer_cnt--; | |
536 | } | |
537 | ||
538 | DISP_CHECK_RET(DISP_UpdateScreen(0, 0, fb_xres_update, fb_yres_update)); | |
539 | ||
540 | if(down_sem){ | |
541 | sem_overlay_buffer_cnt++; | |
542 | up(&sem_overlay_buffer); | |
543 | } | |
544 | MMProfileLog(MTKFB_MMP_Events.UpdateScreenImpl, MMProfileFlagEnd); | |
545 | } | |
546 | ||
547 | ||
548 | static int mtkfb_update_screen(struct fb_info *info) | |
549 | { | |
550 | MTKFB_FUNC(); | |
551 | if (down_interruptible(&sem_early_suspend)) { | |
552 | pr_info("[FB Driver] can't get semaphore in mtkfb_update_screen()\n"); | |
553 | return -ERESTARTSYS; | |
554 | } | |
555 | sem_early_suspend_cnt--; | |
556 | if (is_early_suspended) goto End; | |
557 | mtkfb_update_screen_impl(); | |
558 | ||
559 | End: | |
560 | sem_early_suspend_cnt++; | |
561 | up(&sem_early_suspend); | |
562 | return 0; | |
563 | } | |
564 | static unsigned int BL_level = 0; | |
565 | static BOOL BL_set_level_resume = FALSE; | |
566 | int mtkfb_set_backlight_level(unsigned int level) | |
567 | { | |
568 | MTKFB_FUNC(); | |
569 | pr_info("mtkfb_set_backlight_level:%d\n", level); | |
570 | if (down_interruptible(&sem_flipping)) { | |
571 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
572 | return -ERESTARTSYS; | |
573 | } | |
574 | sem_flipping_cnt--; | |
575 | if (down_interruptible(&sem_early_suspend)) { | |
576 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
577 | sem_flipping_cnt++; | |
578 | up(&sem_flipping); | |
579 | return -ERESTARTSYS; | |
580 | } | |
581 | ||
582 | sem_early_suspend_cnt--; | |
583 | if (is_early_suspended){ | |
584 | BL_level = level; | |
585 | BL_set_level_resume = TRUE; | |
586 | pr_info("[FB driver] set backlight level but FB has been suspended\n"); | |
587 | goto End; | |
588 | } | |
589 | DISP_SetBacklight(level); | |
590 | BL_set_level_resume = FALSE; | |
591 | End: | |
592 | sem_flipping_cnt++; | |
593 | sem_early_suspend_cnt++; | |
594 | up(&sem_early_suspend); | |
595 | up(&sem_flipping); | |
596 | return 0; | |
597 | } | |
598 | ||
599 | EXPORT_SYMBOL(mtkfb_set_backlight_level); | |
600 | ||
601 | int mtkfb_set_backlight_mode(unsigned int mode) | |
602 | { | |
603 | MTKFB_FUNC(); | |
604 | if (down_interruptible(&sem_flipping)) { | |
605 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
606 | return -ERESTARTSYS; | |
607 | } | |
608 | sem_flipping_cnt--; | |
609 | if (down_interruptible(&sem_early_suspend)) { | |
610 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
611 | sem_flipping_cnt++; | |
612 | up(&sem_flipping); | |
613 | return -ERESTARTSYS; | |
614 | } | |
615 | ||
616 | sem_early_suspend_cnt--; | |
617 | if (is_early_suspended) goto End; | |
618 | ||
619 | DISP_SetBacklight_mode(mode); | |
620 | End: | |
621 | sem_flipping_cnt++; | |
622 | sem_early_suspend_cnt++; | |
623 | up(&sem_early_suspend); | |
624 | up(&sem_flipping); | |
625 | return 0; | |
626 | } | |
627 | ||
628 | EXPORT_SYMBOL(mtkfb_set_backlight_mode); | |
629 | ||
630 | ||
631 | int mtkfb_set_backlight_pwm(int div) | |
632 | { | |
633 | MTKFB_FUNC(); | |
634 | if (down_interruptible(&sem_flipping)) { | |
635 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
636 | return -ERESTARTSYS; | |
637 | } | |
638 | sem_flipping_cnt--; | |
639 | if (down_interruptible(&sem_early_suspend)) { | |
640 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
641 | sem_flipping_cnt++; | |
642 | up(&sem_flipping); | |
643 | return -ERESTARTSYS; | |
644 | } | |
645 | sem_early_suspend_cnt--; | |
646 | if (is_early_suspended) goto End; | |
647 | DISP_SetPWM(div); | |
648 | End: | |
649 | sem_flipping_cnt++; | |
650 | sem_early_suspend_cnt++; | |
651 | up(&sem_early_suspend); | |
652 | up(&sem_flipping); | |
653 | return 0; | |
654 | } | |
655 | ||
656 | EXPORT_SYMBOL(mtkfb_set_backlight_pwm); | |
657 | ||
658 | int mtkfb_get_backlight_pwm(int div, unsigned int *freq) | |
659 | { | |
660 | DISP_GetPWM(div, freq); | |
661 | return 0; | |
662 | } | |
663 | ||
664 | EXPORT_SYMBOL(mtkfb_get_backlight_pwm); | |
665 | ||
666 | void mtkfb_waitVsync(void) | |
667 | { | |
668 | if(is_early_suspended){ | |
669 | pr_info("[MTKFB_VSYNC]:mtkfb has suspend, return directly\n"); | |
670 | msleep(20); | |
671 | return; | |
672 | } | |
673 | vsync_cnt++; | |
674 | DISP_WaitVSYNC(); | |
675 | vsync_cnt--; | |
676 | return; | |
677 | } | |
678 | ||
679 | EXPORT_SYMBOL(mtkfb_waitVsync); | |
680 | /* Used for HQA test */ | |
681 | /*------------------------------------------------------------- | |
682 | Note: The using scenario must be | |
683 | 1. switch normal mode to factory mode when LCD screen is on | |
684 | 2. switch factory mode to normal mode(optional) | |
685 | -------------------------------------------------------------*/ | |
686 | static struct fb_var_screeninfo fbi_var_backup; | |
687 | static struct fb_fix_screeninfo fbi_fix_backup; | |
688 | static BOOL need_restore = FALSE; | |
689 | static int mtkfb_set_par(struct fb_info *fbi); | |
690 | void mtkfb_switch_normal_to_factory(void) | |
691 | { | |
692 | if (down_interruptible(&sem_flipping)) { | |
693 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
694 | return; | |
695 | } | |
696 | sem_flipping_cnt--; | |
697 | if (down_interruptible(&sem_early_suspend)) { | |
698 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
699 | sem_flipping_cnt++; | |
700 | up(&sem_flipping); | |
701 | return; | |
702 | } | |
703 | sem_early_suspend_cnt--; | |
704 | if (is_early_suspended) { | |
705 | goto EXIT; | |
706 | } | |
707 | ||
708 | if (mtkfb_fbi) | |
709 | { | |
710 | memcpy(&fbi_var_backup, &mtkfb_fbi->var, sizeof(fbi_var_backup)); | |
711 | memcpy(&fbi_fix_backup, &mtkfb_fbi->fix, sizeof(fbi_fix_backup)); | |
712 | need_restore = TRUE; | |
713 | } | |
714 | ||
715 | EXIT: | |
716 | sem_early_suspend_cnt++; | |
717 | sem_flipping_cnt++; | |
718 | up(&sem_early_suspend); | |
719 | up(&sem_flipping); | |
720 | } | |
721 | ||
722 | /* Used for HQA test */ | |
723 | void mtkfb_switch_factory_to_normal(void) | |
724 | { | |
725 | BOOL need_set_par = FALSE; | |
726 | if (down_interruptible(&sem_flipping)) { | |
727 | pr_info("[FB Driver] can't get semaphore in mtkfb_switch_factory_to_normal()\n"); | |
728 | return; | |
729 | } | |
730 | sem_flipping_cnt--; | |
731 | if (down_interruptible(&sem_early_suspend)) { | |
732 | pr_info("[FB Driver] can't get semaphore in mtkfb_switch_factory_to_normal()\n"); | |
733 | sem_flipping_cnt++; | |
734 | up(&sem_flipping); | |
735 | return; | |
736 | } | |
737 | ||
738 | sem_early_suspend_cnt--; | |
739 | if (is_early_suspended) { | |
740 | goto EXIT; | |
741 | } | |
742 | ||
743 | if ((mtkfb_fbi) && (need_restore)) | |
744 | { | |
745 | memcpy(&mtkfb_fbi->var, &fbi_var_backup, sizeof(fbi_var_backup)); | |
746 | memcpy(&mtkfb_fbi->fix, &fbi_fix_backup, sizeof(fbi_fix_backup)); | |
747 | need_restore = FALSE; | |
748 | need_set_par = TRUE; | |
749 | } | |
750 | ||
751 | EXIT: | |
752 | sem_early_suspend_cnt++; | |
753 | sem_flipping_cnt++; | |
754 | up(&sem_early_suspend); | |
755 | up(&sem_flipping); | |
756 | if (need_set_par) | |
757 | { | |
758 | int ret; | |
759 | ret = mtkfb_set_par(mtkfb_fbi); | |
760 | if (ret != 0) | |
761 | PRNERR("failed to mtkfb_set_par\n"); | |
762 | } | |
763 | } | |
764 | ||
765 | static bool first_update = true; | |
766 | static bool first_enable_esd = true; | |
767 | static bool no_update = false; | |
768 | static int cnt=3; | |
769 | static int mtkfb_pan_display_impl(struct fb_var_screeninfo *var, struct fb_info *info) | |
770 | { | |
771 | UINT32 offset; | |
772 | UINT32 paStart; | |
773 | char *vaStart, *vaEnd; | |
774 | int ret = 0; | |
775 | int wait_ret = 0; | |
776 | if(first_update && no_update){ | |
777 | first_update = false; | |
778 | return ret; | |
779 | } | |
780 | MMProfileLogStructure(MTKFB_MMP_Events.PanDisplay, MMProfileFlagStart, var, struct fb_var_screeninfo); | |
781 | if(0!=cnt){ | |
782 | pr_info("LCD:%dx%d\n",MTK_FB_XRES,MTK_FB_YRES); | |
783 | cnt--; | |
784 | } | |
785 | MTKFB_FUNC(); | |
786 | ||
787 | MSG_FUNC_ENTER(); | |
788 | ||
789 | MSG(ARGU, "xoffset=%u, yoffset=%u, xres=%u, yres=%u, xresv=%u, yresv=%u\n", | |
790 | var->xoffset, var->yoffset, | |
791 | info->var.xres, info->var.yres, | |
792 | info->var.xres_virtual, | |
793 | info->var.yres_virtual); | |
794 | ||
795 | if (down_interruptible(&sem_flipping)) { | |
796 | pr_info("[FB Driver] can't get semaphore in mtkfb_pan_display_impl()\n"); | |
797 | MMProfileLogMetaString(MTKFB_MMP_Events.PanDisplay, MMProfileFlagEnd, "Can't get semaphore in mtkfb_pan_display_impl()"); | |
798 | return -ERESTARTSYS; | |
799 | } | |
800 | sem_flipping_cnt--; | |
801 | ||
802 | info->var.yoffset = var->yoffset; | |
803 | ||
804 | offset = var->yoffset * info->fix.line_length; | |
805 | paStart = fb_pa + offset; | |
806 | vaStart = info->screen_base + offset; | |
807 | vaEnd = vaStart + info->var.yres * info->fix.line_length; | |
808 | ||
809 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
810 | { | |
811 | struct fb_overlay_layer layerInfo = {0}; | |
812 | layerInfo.layer_id = 0;//FB_LAYER; | |
813 | layerInfo.layer_enable = TRUE; | |
814 | layerInfo.src_base_addr = (void *)((unsigned int)vaStart); | |
815 | layerInfo.src_phy_addr = (void *)paStart; | |
816 | layerInfo.src_direct_link = 0; | |
817 | switch(var->bits_per_pixel) | |
818 | { | |
819 | case 16: | |
820 | layerInfo.src_fmt = MTK_FB_FORMAT_RGB565; | |
821 | break; | |
822 | case 24: | |
823 | layerInfo.src_fmt = MTK_FB_FORMAT_RGB888; | |
824 | break; | |
825 | case 32: | |
826 | layerInfo.src_fmt = MTK_FB_FORMAT_ARGB8888; | |
827 | break; | |
828 | default: | |
829 | PRNERR("Invalid color format bpp: 0x%d\n", var->bits_per_pixel); | |
830 | return -1; | |
831 | } | |
832 | layerInfo.src_use_color_key = 0; | |
833 | layerInfo.src_color_key = 0xFF; | |
834 | layerInfo.src_pitch = ALIGN_TO(var->xres, disphal_get_fb_alignment()); | |
835 | layerInfo.src_offset_x = 0; | |
836 | layerInfo.src_offset_y = 0; | |
837 | layerInfo.src_width = var->xres; | |
838 | layerInfo.src_height = var->yres; | |
839 | layerInfo.tgt_offset_x = 0; | |
840 | layerInfo.tgt_offset_y = 0; | |
841 | layerInfo.tgt_width = var->xres; | |
842 | layerInfo.tgt_height = var->yres; | |
843 | layerInfo.layer_rotation = MTK_FB_ORIENTATION_0; | |
844 | layerInfo.layer_type = LAYER_2D; | |
845 | layerInfo.video_rotation = MTK_FB_ORIENTATION_0; | |
846 | layerInfo.isTdshp = TRUE; // set to 1, will go through tdshp first, then layer blending, then to color | |
847 | layerInfo.next_buff_idx = -1; | |
848 | layerInfo.identity = 0; | |
849 | layerInfo.connected_type = 0; | |
850 | layerInfo.security = 0; | |
851 | pr_info("[mtkfb] pan display set va=0x%x, pa=0x%x \n",(unsigned int)vaStart,paStart); | |
852 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layerInfo); | |
853 | ||
4b9e9796 S |
854 | if(get_boot_mode() != FACTORY_BOOT) |
855 | { | |
856 | layerInfo.layer_id = 1; | |
857 | layerInfo.layer_enable = FALSE; | |
858 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layerInfo); | |
859 | layerInfo.layer_id = 2; | |
860 | layerInfo.layer_enable = FALSE; | |
861 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layerInfo); | |
862 | layerInfo.layer_id = 3; | |
863 | layerInfo.layer_enable = FALSE; | |
864 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layerInfo); | |
865 | } | |
6fa3eb70 S |
866 | } |
867 | #else | |
868 | mutex_lock(&OverlaySettingMutex); | |
869 | DISP_CHECK_RET(DISP_SetFrameBufferAddr(paStart)); | |
870 | cached_layer_config[FB_LAYER].vaddr = (unsigned int)vaStart; | |
871 | cached_layer_config[FB_LAYER].layer_en = 1; | |
872 | cached_layer_config[FB_LAYER].src_x = 0; | |
873 | cached_layer_config[FB_LAYER].src_y = 0; | |
874 | cached_layer_config[FB_LAYER].src_w = var->xres; | |
875 | cached_layer_config[FB_LAYER].src_h = var->yres; | |
876 | cached_layer_config[FB_LAYER].dst_x = 0; | |
877 | cached_layer_config[FB_LAYER].dst_y = 0; | |
878 | cached_layer_config[FB_LAYER].dst_w = var->xres; | |
879 | cached_layer_config[FB_LAYER].dst_h = var->yres; | |
880 | { | |
881 | unsigned int layerpitch; | |
882 | unsigned int src_pitch = ALIGN_TO(var->xres, disphal_get_fb_alignment()); | |
883 | switch(var->bits_per_pixel) | |
884 | { | |
885 | case 16: | |
886 | cached_layer_config[FB_LAYER].fmt = eRGB565; | |
887 | layerpitch = 2; | |
888 | cached_layer_config[FB_LAYER].aen = FALSE; | |
889 | break; | |
890 | case 24: | |
891 | cached_layer_config[FB_LAYER].fmt = eRGB888; | |
892 | layerpitch = 3; | |
893 | cached_layer_config[FB_LAYER].aen = FALSE; | |
894 | break; | |
895 | case 32: | |
896 | cached_layer_config[FB_LAYER].fmt = ePARGB8888; | |
897 | layerpitch = 4; | |
898 | cached_layer_config[FB_LAYER].aen = TRUE; | |
899 | break; | |
900 | default: | |
901 | PRNERR("Invalid color format bpp: 0x%d\n", var->bits_per_pixel); | |
902 | return -1; | |
903 | } | |
904 | cached_layer_config[FB_LAYER].alpha = 0xFF; | |
905 | cached_layer_config[FB_LAYER].buff_idx = -1; | |
906 | cached_layer_config[FB_LAYER].src_pitch = src_pitch * layerpitch; | |
907 | } | |
908 | ||
909 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
910 | atomic_set(&OverlaySettingApplied, 0); | |
911 | #endif | |
912 | PanDispSettingPending = 1; | |
913 | PanDispSettingDirty = 1; | |
914 | PanDispSettingApplied = 0; | |
915 | is_ipoh_bootup = false; | |
916 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
917 | mutex_unlock(&OverlaySettingMutex); | |
918 | #endif | |
919 | ||
920 | ret = mtkfb_update_screen(info); | |
921 | //#if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
922 | //Disp_Ovl_Engine_Trigger_Overlay(mtkfb_instance); | |
923 | //#endif | |
924 | // NOTICE: un-interruptible wait here for m4u callback | |
925 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
926 | Disp_Ovl_Engine_Wait_Overlay_Complete(mtkfb_instance, 1000); | |
927 | #else | |
928 | wait_ret = wait_event_timeout(reg_update_wq, PanDispSettingApplied, HZ/10); | |
929 | MTKFB_LOG("[WaitQ] wait_event_interruptible() ret = %d, %d\n", wait_ret, __LINE__); | |
930 | #endif | |
931 | ||
932 | sem_flipping_cnt++; | |
933 | up(&sem_flipping); | |
934 | if(first_enable_esd) | |
935 | { | |
936 | esd_recovery_pause(FALSE); | |
937 | first_enable_esd = false; | |
938 | } | |
939 | MMProfileLog(MTKFB_MMP_Events.PanDisplay, MMProfileFlagEnd); | |
940 | ||
941 | return ret; | |
942 | } | |
943 | ||
944 | ||
945 | static int mtkfb_pan_display_proxy(struct fb_var_screeninfo *var, struct fb_info *info) | |
946 | { | |
947 | #ifdef CONFIG_MTPROF_APPLAUNCH // eng enable, user disable | |
948 | LOG_PRINT(ANDROID_LOG_INFO, "AppLaunch", "mtkfb_pan_display_proxy.\n"); | |
949 | #endif | |
950 | return mtkfb_pan_display_impl(var, info); | |
951 | } | |
952 | ||
953 | ||
954 | /* Set fb_info.fix fields and also updates fbdev. | |
955 | * When calling this fb_info.var must be set up already. | |
956 | */ | |
957 | static void set_fb_fix(struct mtkfb_device *fbdev) | |
958 | { | |
959 | struct fb_info *fbi = fbdev->fb_info; | |
960 | struct fb_fix_screeninfo *fix = &fbi->fix; | |
961 | struct fb_var_screeninfo *var = &fbi->var; | |
962 | struct fb_ops *fbops = fbi->fbops; | |
963 | ||
964 | strncpy(fix->id, MTKFB_DRIVER, sizeof(fix->id)); | |
965 | fix->type = FB_TYPE_PACKED_PIXELS; | |
966 | ||
967 | switch (var->bits_per_pixel) | |
968 | { | |
969 | case 16: | |
970 | case 24: | |
971 | case 32: | |
972 | fix->visual = FB_VISUAL_TRUECOLOR; | |
973 | break; | |
974 | case 1: | |
975 | case 2: | |
976 | case 4: | |
977 | case 8: | |
978 | fix->visual = FB_VISUAL_PSEUDOCOLOR; | |
979 | break; | |
980 | default: | |
981 | ASSERT(0); | |
982 | } | |
983 | ||
984 | fix->accel = FB_ACCEL_NONE; | |
985 | fix->line_length = ALIGN_TO(var->xres_virtual, disphal_get_fb_alignment()) * var->bits_per_pixel / 8; | |
986 | fix->smem_len = fbdev->fb_size_in_byte; | |
987 | fix->smem_start = fbdev->fb_pa_base; | |
988 | ||
989 | fix->xpanstep = 0; | |
990 | fix->ypanstep = 1; | |
991 | ||
992 | fbops->fb_fillrect = cfb_fillrect; | |
993 | fbops->fb_copyarea = cfb_copyarea; | |
994 | fbops->fb_imageblit = cfb_imageblit; | |
995 | } | |
996 | ||
997 | ||
998 | /* Check values in var, try to adjust them in case of out of bound values if | |
999 | * possible, or return error. | |
1000 | */ | |
1001 | static int mtkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | |
1002 | { | |
1003 | unsigned int bpp; | |
1004 | unsigned long max_frame_size; | |
1005 | unsigned long line_size; | |
1006 | ||
1007 | struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par; | |
1008 | ||
1009 | MSG_FUNC_ENTER(); | |
1010 | ||
1011 | MSG(ARGU, "xres=%u, yres=%u, xres_virtual=%u, yres_virtual=%u, " | |
1012 | "xoffset=%u, yoffset=%u, bits_per_pixel=%u)\n", | |
1013 | var->xres, var->yres, var->xres_virtual, var->yres_virtual, | |
1014 | var->xoffset, var->yoffset, var->bits_per_pixel); | |
1015 | ||
1016 | bpp = var->bits_per_pixel; | |
1017 | ||
1018 | if (bpp != 16 && bpp != 24 && bpp != 32) { | |
1019 | MTKFB_LOG("[%s]unsupported bpp: %d", __func__, bpp); | |
1020 | return -1; | |
1021 | } | |
1022 | ||
1023 | switch (var->rotate) { | |
1024 | case 0: | |
1025 | case 180: | |
1026 | var->xres = MTK_FB_XRES; | |
1027 | var->yres = MTK_FB_YRES; | |
1028 | break; | |
1029 | case 90: | |
1030 | case 270: | |
1031 | var->xres = MTK_FB_YRES; | |
1032 | var->yres = MTK_FB_XRES; | |
1033 | break; | |
1034 | default: | |
1035 | return -1; | |
1036 | } | |
1037 | ||
1038 | if (var->xres_virtual < var->xres) | |
1039 | var->xres_virtual = var->xres; | |
1040 | if (var->yres_virtual < var->yres) | |
1041 | var->yres_virtual = var->yres; | |
1042 | ||
1043 | max_frame_size = fbdev->fb_size_in_byte; | |
1044 | line_size = var->xres_virtual * bpp / 8; | |
1045 | ||
1046 | if (line_size * var->yres_virtual > max_frame_size) { | |
1047 | /* Try to keep yres_virtual first */ | |
1048 | line_size = max_frame_size / var->yres_virtual; | |
1049 | var->xres_virtual = line_size * 8 / bpp; | |
1050 | if (var->xres_virtual < var->xres) { | |
1051 | /* Still doesn't fit. Shrink yres_virtual too */ | |
1052 | var->xres_virtual = var->xres; | |
1053 | line_size = var->xres * bpp / 8; | |
1054 | var->yres_virtual = max_frame_size / line_size; | |
1055 | } | |
1056 | } | |
1057 | if (var->xres + var->xoffset > var->xres_virtual) | |
1058 | var->xoffset = var->xres_virtual - var->xres; | |
1059 | if (var->yres + var->yoffset > var->yres_virtual) | |
1060 | var->yoffset = var->yres_virtual - var->yres; | |
1061 | ||
1062 | if (16 == bpp) { | |
1063 | var->red.offset = 11; var->red.length = 5; | |
1064 | var->green.offset = 5; var->green.length = 6; | |
1065 | var->blue.offset = 0; var->blue.length = 5; | |
1066 | var->transp.offset = 0; var->transp.length = 0; | |
1067 | } | |
1068 | else if (24 == bpp) | |
1069 | { | |
1070 | var->red.length = var->green.length = var->blue.length = 8; | |
1071 | var->transp.length = 0; | |
1072 | ||
1073 | // Check if format is RGB565 or BGR565 | |
1074 | ||
1075 | ASSERT(8 == var->green.offset); | |
1076 | ASSERT(16 == var->red.offset + var->blue.offset); | |
1077 | ASSERT(16 == var->red.offset || 0 == var->red.offset); | |
1078 | } | |
1079 | else if (32 == bpp) | |
1080 | { | |
1081 | var->red.length = var->green.length = | |
1082 | var->blue.length = var->transp.length = 8; | |
1083 | ||
1084 | // Check if format is ARGB565 or ABGR565 | |
1085 | ||
1086 | ASSERT(8 == var->green.offset && 24 == var->transp.offset); | |
1087 | ASSERT(16 == var->red.offset + var->blue.offset); | |
1088 | ASSERT(16 == var->red.offset || 0 == var->red.offset); | |
1089 | } | |
1090 | ||
1091 | var->red.msb_right = var->green.msb_right = | |
1092 | var->blue.msb_right = var->transp.msb_right = 0; | |
1093 | ||
1094 | if(var->activate & FB_ACTIVATE_NO_UPDATE) | |
1095 | no_update = true; | |
1096 | else | |
1097 | no_update = false; | |
1098 | ||
1099 | var->activate = FB_ACTIVATE_NOW; | |
1100 | ||
1101 | var->height = UINT_MAX; | |
1102 | var->width = UINT_MAX; | |
1103 | var->grayscale = 0; | |
1104 | var->nonstd = 0; | |
1105 | ||
1106 | var->pixclock = UINT_MAX; | |
1107 | var->left_margin = UINT_MAX; | |
1108 | var->right_margin = UINT_MAX; | |
1109 | var->upper_margin = UINT_MAX; | |
1110 | var->lower_margin = UINT_MAX; | |
1111 | var->hsync_len = UINT_MAX; | |
1112 | var->vsync_len = UINT_MAX; | |
1113 | ||
1114 | var->vmode = FB_VMODE_NONINTERLACED; | |
1115 | var->sync = 0; | |
1116 | ||
1117 | MSG_FUNC_LEAVE(); | |
1118 | return 0; | |
1119 | } | |
1120 | ||
1121 | ||
1122 | /* Switch to a new mode. The parameters for it has been check already by | |
1123 | * mtkfb_check_var. | |
1124 | */ | |
1125 | static int mtkfb_set_par(struct fb_info *fbi) | |
1126 | { | |
1127 | struct fb_var_screeninfo *var = &fbi->var; | |
1128 | struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par; | |
1129 | struct fb_overlay_layer fb_layer; | |
1130 | u32 bpp = var->bits_per_pixel; | |
1131 | ||
1132 | MSG_FUNC_ENTER(); | |
1133 | memset(&fb_layer, 0, sizeof(struct fb_overlay_layer)); | |
1134 | switch(bpp) | |
1135 | { | |
1136 | case 16 : | |
1137 | fb_layer.src_fmt = MTK_FB_FORMAT_RGB565; | |
1138 | fb_layer.src_use_color_key = 1; | |
1139 | fb_layer.src_color_key = 0xFF000000; | |
1140 | break; | |
1141 | ||
1142 | case 24 : | |
1143 | fb_layer.src_use_color_key = 1; | |
1144 | fb_layer.src_fmt = (0 == var->blue.offset) ? | |
1145 | MTK_FB_FORMAT_RGB888 : | |
1146 | MTK_FB_FORMAT_BGR888; | |
1147 | fb_layer.src_color_key = 0xFF000000; | |
1148 | break; | |
1149 | ||
1150 | case 32 : | |
1151 | fb_layer.src_use_color_key = 0; | |
1152 | fb_layer.src_fmt = (0 == var->blue.offset) ? | |
1153 | MTK_FB_FORMAT_ARGB8888 : | |
1154 | MTK_FB_FORMAT_ABGR8888; | |
1155 | fb_layer.src_color_key = 0; | |
1156 | break; | |
1157 | ||
1158 | default : | |
1159 | fb_layer.src_fmt = MTK_FB_FORMAT_UNKNOWN; | |
1160 | MTKFB_LOG("[%s]unsupported bpp: %d", __func__, bpp); | |
1161 | return -1; | |
1162 | } | |
1163 | ||
1164 | // If the framebuffer format is NOT changed, nothing to do | |
1165 | // | |
1166 | if (fb_layer.src_fmt == fbdev->layer_format[0]) { | |
1167 | goto Done; | |
1168 | } | |
1169 | ||
1170 | // else, begin change display mode | |
1171 | // | |
1172 | set_fb_fix(fbdev); | |
1173 | ||
1174 | //fb_layer.layer_id = FB_LAYER; //fix batterary disappearing | |
1175 | fb_layer.layer_id = 0; | |
1176 | fb_layer.layer_enable = 1; | |
1177 | fb_layer.src_base_addr = (void *)((unsigned long)fbdev->fb_va_base + var->yoffset * fbi->fix.line_length); | |
1178 | fb_layer.src_phy_addr = (void *)(fb_pa + var->yoffset * fbi->fix.line_length); | |
1179 | fb_layer.src_direct_link = 0; | |
1180 | fb_layer.src_offset_x = fb_layer.src_offset_y = 0; | |
1181 | // fb_layer.src_width = fb_layer.tgt_width = fb_layer.src_pitch = var->xres; | |
1182 | #if defined(HWGPU_SUPPORT) | |
1183 | fb_layer.src_pitch = ALIGN_TO(var->xres, MTK_FB_ALIGNMENT); | |
1184 | #else | |
1185 | if(get_boot_mode() == META_BOOT || get_boot_mode() == FACTORY_BOOT | |
1186 | || get_boot_mode() == ADVMETA_BOOT || get_boot_mode() == RECOVERY_BOOT) | |
1187 | fb_layer.src_pitch = ALIGN_TO(var->xres, MTK_FB_ALIGNMENT); | |
1188 | else | |
1189 | fb_layer.src_pitch = var->xres; | |
1190 | #endif | |
1191 | fb_layer.src_width = fb_layer.tgt_width = var->xres; | |
1192 | fb_layer.src_height = fb_layer.tgt_height = var->yres; | |
1193 | fb_layer.tgt_offset_x = fb_layer.tgt_offset_y = 0; | |
1194 | ||
1195 | // fb_layer.src_color_key = 0; | |
1196 | fb_layer.layer_rotation = MTK_FB_ORIENTATION_0; | |
1197 | fb_layer.layer_type = LAYER_2D; | |
1198 | ||
1199 | mutex_lock(&OverlaySettingMutex); | |
1200 | mtkfb_set_overlay_layer((struct mtkfb_device *)fbi->par, &fb_layer); | |
1201 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
1202 | atomic_set(&OverlaySettingApplied, 0); | |
1203 | mutex_unlock(&OverlaySettingMutex); | |
1204 | ||
1205 | // backup fb_layer information. | |
1206 | memcpy(&fb_layer_context, &fb_layer, sizeof(fb_layer)); | |
1207 | ||
1208 | Done: | |
1209 | MSG_FUNC_LEAVE(); | |
1210 | return 0; | |
1211 | } | |
1212 | ||
1213 | ||
1214 | static int mtkfb_soft_cursor(struct fb_info *info, struct fb_cursor *cursor) | |
1215 | { | |
1216 | NOT_REFERENCED(info); | |
1217 | NOT_REFERENCED(cursor); | |
1218 | ||
1219 | return 0; | |
1220 | } | |
1221 | void mtkfb_ion_cpu_cache_flush(struct ion_client *client, struct ion_handle *handle) | |
1222 | { | |
1223 | struct ion_sys_data sys_data; | |
1224 | ||
1225 | sys_data.sys_cmd = ION_SYS_CACHE_SYNC; | |
1226 | sys_data.cache_sync_param.kernel_handle = handle; | |
1227 | sys_data.cache_sync_param.sync_type = ION_CACHE_FLUSH_BY_RANGE; | |
1228 | ||
1229 | if (ion_kernel_ioctl(client, ION_CMD_SYSTEM, (unsigned long)&sys_data)) { | |
1230 | pr_err("ion cache flush failed!\n"); | |
1231 | } | |
1232 | } | |
1233 | static void mtkfb_update_ovls_handler(struct work_struct* _work) | |
1234 | { | |
1235 | /* Wait for a whole second for config to apply so it's obvious when something's wrong */ | |
1236 | #ifdef MTK_OVERLAY_ENGINE_SUPPORT | |
1237 | const unsigned long wait_time = 1000; | |
1238 | #else | |
1239 | const unsigned long wait_time = msecs_to_jiffies(1000); | |
1240 | #endif | |
1241 | ||
1242 | update_ovls_work_t *work = (update_ovls_work_t *) _work; | |
1243 | struct mtkfb_device *fbdev = (struct mtkfb_device *)work->dev; | |
1244 | struct fb_overlay_config *config = &work->config; | |
1245 | struct sync_fence **fences = work->fences; | |
1246 | struct ion_handle **ion_handles = work->ion_handles; | |
1247 | int ret, i, suspended = 0; | |
1248 | ||
1249 | update_ovls_work_t *curr, *tmp; | |
1250 | struct list_head tmp_list; | |
1251 | u32 inc = 0; | |
1252 | ||
1253 | MMProfileLog(MTKFB_MMP_Events.WrokHandler, MMProfileFlagStart); | |
1254 | ||
1255 | /* ion handle to mva */ | |
1256 | for (i = 0; i < HW_OVERLAY_COUNT; i++) { | |
1257 | ion_mm_data_t data; | |
1258 | size_t _unused; | |
1259 | ion_phys_addr_t mva; | |
1260 | ||
1261 | if (!ion_handles[i]) | |
1262 | continue; /* Use mva from userspace */ | |
1263 | ||
1264 | /* configure buffer */ | |
1265 | memset(&data, 0, sizeof(ion_mm_data_t)); | |
1266 | data.mm_cmd = ION_MM_CONFIG_BUFFER; | |
1267 | data.config_buffer_param.kernel_handle = ion_handles[i]; | |
1268 | data.config_buffer_param.eModuleID = DISP_OVL_0; | |
1269 | ion_kernel_ioctl(fbdev->ion_client, ION_CMD_MULTIMEDIA, (unsigned long)&data); | |
1270 | ||
1271 | /* Get "physical" address (mva) */ | |
1272 | if (ion_phys(fbdev->ion_client, ion_handles[i], &mva, &_unused)) { | |
1273 | dev_err(fbdev->dev, "ion_phys failed, disable ovl %d\n", i); | |
1274 | config->layers[i].layer_enable = 0; | |
1275 | config->layers[i].src_phy_addr = 0; | |
1276 | ion_free(fbdev->ion_client, ion_handles[i]); | |
1277 | ion_handles[i] = NULL; | |
1278 | continue; | |
1279 | } | |
1280 | ||
1281 | if (!g_fb_pattern_en) | |
1282 | config->layers[i].src_phy_addr = (void *)mva; | |
1283 | //pr_err("[02420] update_ovls_handler[%d] ion_handle=%x src_phy_addr = %x \n", i,data.config_buffer_param.handle, mva); | |
1284 | } | |
1285 | ||
1286 | /* Wait on input fences, unref when done */ | |
1287 | if (down_interruptible(&sem_early_suspend)) { | |
1288 | dev_err(fbdev->dev, "semaphore down failed in %s\n", __func__); | |
1289 | goto out; | |
1290 | } | |
1291 | for (i = 0; i < HW_OVERLAY_COUNT; i++) { | |
1292 | if (!fences[i]) | |
1293 | continue; /* Nothing to wait on */ | |
1294 | ||
1295 | #ifndef NONFLUSH | |
1296 | if (is_early_suspended) | |
1297 | continue; /* Don't wait if suspended */ | |
1298 | /* Wait for the fence to signal */ | |
1299 | up(&sem_early_suspend); | |
1300 | if (sync_fence_wait(fences[i], 1000) < 0) | |
1301 | { | |
1302 | config->layers[i].layer_enable = 0; | |
1303 | config->layers[i].src_phy_addr = 0; | |
1304 | //ion_free(fbdev->ion_client, ion_handles[i]); | |
1305 | //ion_handles[i] = NULL; | |
1306 | pr_err(" error waiting for fence to signal fences[%d]= 0x%x\n",i,(unsigned int)fences[i]); | |
1307 | } | |
1308 | if (down_interruptible(&sem_early_suspend)) { | |
1309 | dev_err(fbdev->dev, "semaphore down failed in %s\n", __func__); | |
1310 | goto out; | |
1311 | } | |
1312 | #else | |
1313 | /* Don't wait if suspended */ | |
1314 | if (!is_early_suspended) { /* Wait for the fence to signal */ | |
1315 | up(&sem_early_suspend); | |
1316 | if (sync_fence_wait(fences[i], 1000) < 0){ | |
1317 | config->layers[i].layer_enable = 0; | |
1318 | config->layers[i].src_phy_addr = 0; | |
1319 | //ion_free(fbdev->ion_client, ion_handles[i]); | |
1320 | //ion_handles[i] = NULL; | |
1321 | pr_err(" error waiting for fence to signal fences[%d]= 0x%x\n",i,(unsigned int)fences[i]); | |
1322 | goto out; | |
1323 | } | |
1324 | if (down_interruptible(&sem_early_suspend)) { | |
1325 | dev_err(fbdev->dev, "semaphore down failed in %s\n", __func__); | |
1326 | goto out; | |
1327 | } | |
1328 | } | |
1329 | #endif | |
1330 | MMProfileLogEx(MTKFB_MMP_Events.HWCFence[i], MMProfileFlagEnd, 0, (unsigned int)fences[i]); | |
1331 | /* Unref the fence */ | |
1332 | sync_fence_put(fences[i]); | |
1333 | fences[i] = NULL; | |
1334 | } | |
1335 | suspended = is_early_suspended; | |
1336 | up(&sem_early_suspend); | |
1337 | ||
1338 | /* if suspended, skip application */ | |
1339 | //if (suspended) | |
1340 | // goto out; | |
1341 | ||
1342 | /* Flush CPU cache */ | |
1343 | for (i = 0; i < HW_OVERLAY_COUNT; i++) { | |
1344 | ion_mm_data_t data; | |
1345 | ||
1346 | if (!work->ion_handles[i]) | |
1347 | continue; | |
1348 | ||
1349 | /* configure buffer */ | |
1350 | memset(&data, 0, sizeof(ion_mm_data_t)); | |
1351 | data.mm_cmd = ION_MM_GET_DEBUG_INFO; | |
1352 | data.config_buffer_param.kernel_handle = ion_handles[i]; | |
1353 | ion_kernel_ioctl(fbdev->ion_client, ION_CMD_MULTIMEDIA, (unsigned long)&data); | |
1354 | ||
1355 | if ((data.buf_debug_info_param.value4 & GRALLOC_EXTRA_MASK_TYPE) != | |
1356 | GRALLOC_EXTRA_BIT_TYPE_CPU) | |
1357 | continue; | |
1358 | ||
1359 | mtkfb_ion_cpu_cache_flush(fbdev->ion_client, work->ion_handles[i]); | |
1360 | } | |
1361 | /* By locking OverlaySettingMutex here we prevent the update thread from commiting the | |
1362 | * frame configuration, even though we make several calls to mtkfb_set_overlay_layer */ | |
1363 | mutex_lock(&OverlaySettingMutex); | |
1364 | ||
1365 | for (i = 0; i < HW_OVERLAY_COUNT; i++) { | |
1366 | //pr_err("[02420]go config ovl[%d] src_phy_addr = %x \n", i,config->layers[i].src_phy_addr); | |
1367 | if (!isAEEEnabled || (i < (HW_OVERLAY_COUNT - 1))) | |
1368 | mtkfb_set_overlay_layer(fbdev, &config->layers[i]); | |
1369 | } | |
1370 | ||
1371 | #ifndef MTK_OVERLAY_ENGINE_SUPPORT | |
1372 | /* These flags should flip back when config is applied */ | |
1373 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
1374 | atomic_set(&OverlaySettingApplied, 0); | |
1375 | #endif | |
1376 | ||
1377 | mutex_unlock(&OverlaySettingMutex); | |
1378 | ||
1379 | /* Trigger an update */ | |
1380 | DISP_StartConfigUpdate(); | |
1381 | ||
1382 | /* We can't really recover from wait errors so just log and soldier on */ | |
1383 | #ifdef MTK_OVERLAY_ENGINE_SUPPORT | |
1384 | ret = Disp_Ovl_Engine_Wait_Overlay_Complete(mtkfb_instance, wait_time); | |
1385 | if (ret < 0) { | |
1386 | pr_warn(" Disp_Ovl_Engine_Wait_Overlay_Complete timed out, tearing risk\n"); | |
1387 | } | |
1388 | #else | |
1389 | /* We can't *really* rely on just OverlaySettingApplied | |
1390 | * since it's triggered not only by us but by AAL and others. */ | |
1391 | ret = wait_event_interruptible_timeout(reg_update_wq, atomic_read(&OverlaySettingApplied) | |
1392 | && !atomic_read(&OverlaySettingDirtyFlag), | |
1393 | wait_time); | |
1394 | ||
1395 | if (ret < 0) { | |
1396 | pr_warn(" wait for OverlaySettingApplied interrupted, tearing risk\n"); | |
1397 | } else if (ret == 0) { | |
1398 | pr_warn(" wait for OverlaySettingApplied timed out, tearing risk\n"); | |
1399 | } | |
1400 | #endif | |
1401 | ||
1402 | out: | |
1403 | /* Free old configs & inc timeline */ | |
1404 | #if 0 | |
1405 | tmp_list = fbdev->pending_configs; | |
1406 | list_replace_init(&fbdev->pending_configs, &tmp_list); | |
1407 | list_for_each_entry_safe(curr, tmp, &tmp_list, list) | |
1408 | { | |
1409 | //pr_err("[02420][0] free ion handle = %x signal fence = %x \n", curr->ion_handles[0], curr->fences[0], curr->ion_handles[1], curr->fences[1], curr->ion_handles[2], curr->fences[2], curr->ion_handles[3], curr->fences[3]); | |
1410 | for (i = 0; i < HW_OVERLAY_COUNT; i++) | |
1411 | { | |
1412 | /* ion handles */ | |
1413 | if (curr->ion_handles[i]) { | |
1414 | ion_free(fbdev->ion_client, curr->ion_handles[i]); | |
1415 | curr->ion_handles[i] = NULL; | |
1416 | } | |
1417 | /* fences */ | |
1418 | if (curr->fences[i]) { | |
1419 | MMProfileLogEx(MTKFB_MMP_Events.HWCFence[i], MMProfileFlagPulse, 1, (unsigned int)curr->fences[i]); | |
1420 | sync_fence_put(curr->fences[i]); | |
1421 | curr->fences[i] = NULL; | |
1422 | } | |
1423 | } | |
1424 | list_del(&curr->list); | |
1425 | kfree(curr); | |
1426 | inc++; | |
1427 | } | |
1428 | ||
1429 | /* This work, and (possibly) its ion handles can't be freed | |
1430 | until next config is applied */ | |
1431 | list_add_tail(&work->list, &fbdev->pending_configs); | |
1432 | ||
1433 | mutex_lock(&fbdev->timeline_lock); | |
1434 | sw_sync_timeline_inc(fbdev->timeline, inc); | |
1435 | MMProfileLogEx(MTKFB_MMP_Events.FBTimeline, MMProfileFlagEnd, fbdev->timeline->value, inc); | |
1436 | //pr_err("[02420]step into out label in update_ovls_handler inc=%d fbdev->timeline->value = %d", inc, fbdev->timeline->value); | |
1437 | mutex_unlock(&fbdev->timeline_lock); | |
1438 | ||
1439 | #else | |
1440 | ||
1441 | for (i = 0; i < HW_OVERLAY_COUNT; i++) | |
1442 | { | |
1443 | /* ion handles */ | |
1444 | if (ion_handles[i]) { | |
1445 | ion_free(fbdev->ion_client, ion_handles[i]); | |
1446 | ion_handles[i] = NULL; | |
1447 | } | |
1448 | /* fences */ | |
1449 | if (fences[i]) { | |
1450 | MMProfileLogEx(MTKFB_MMP_Events.HWCFence[i], MMProfileFlagPulse, 1, (unsigned int)fences[i]); | |
1451 | sync_fence_put(fences[i]); | |
1452 | fences[i] = NULL; | |
1453 | } | |
1454 | } | |
1455 | ||
1456 | kfree(work); | |
1457 | ||
1458 | mutex_lock(&fbdev->timeline_lock); | |
1459 | sw_sync_timeline_inc(fbdev->timeline, 1); | |
1460 | MMProfileLogEx(MTKFB_MMP_Events.FBTimeline, MMProfileFlagEnd, fbdev->timeline->value, 1); | |
1461 | //pr_err("[02420]step into out label in update_ovls_handler inc=%d fbdev->timeline->value = %d", inc, fbdev->timeline->value); | |
1462 | mutex_unlock(&fbdev->timeline_lock); | |
1463 | ||
1464 | #endif | |
1465 | ||
1466 | MMProfileLog(MTKFB_MMP_Events.WrokHandler, MMProfileFlagEnd); | |
1467 | } | |
1468 | ||
1469 | int mtkfb_queue_overlay_config(struct mtkfb_device *fbdev, struct fb_overlay_config* config) | |
1470 | { | |
1471 | update_ovls_work_t *work; | |
1472 | struct sync_fence *fence; | |
1473 | struct sync_pt *pt; | |
1474 | int i, fd = -1, ret = 0; | |
1475 | ||
1476 | if (down_interruptible(&sem_early_suspend)) { | |
1477 | dev_err(fbdev->dev, "semaphore down failed in %s\n", __func__); | |
1478 | return -ERESTARTSYS; | |
1479 | } | |
1480 | ||
1481 | MMProfileLogStructure(MTKFB_MMP_Events.QueueWork, MMProfileFlagStart, config, struct fb_overlay_config); | |
1482 | ||
1483 | fd = get_unused_fd(); | |
1484 | if (fd < 0) { | |
1485 | dev_err(fbdev->dev, "could not get a file descriptor\n"); | |
1486 | ret = -ENOMEM; | |
1487 | goto err; | |
1488 | } | |
1489 | ||
1490 | #if 0 | |
1491 | if (is_early_suspended) { | |
1492 | MTKFB_LOG("[FB]: is_early_suspended\n"); | |
1493 | ||
1494 | /* Create fake sync point and inc timeline */ | |
1495 | mutex_lock(&fbdev->timeline_lock); | |
1496 | fbdev->timeline_max++; | |
1497 | pt = sw_sync_pt_create(fbdev->timeline, fbdev->timeline_max); | |
1498 | fence = sync_fence_create("display", pt); | |
1499 | sync_fence_install(fence, fd); | |
1500 | config->fence = fd; | |
1501 | sw_sync_timeline_inc(fbdev->timeline, 1); | |
1502 | mutex_unlock(&fbdev->timeline_lock); | |
1503 | ||
1504 | goto out; | |
1505 | } | |
1506 | #endif | |
1507 | ||
1508 | work = kzalloc(sizeof(update_ovls_work_t), GFP_KERNEL); | |
1509 | if (!work) { | |
1510 | dev_err(fbdev->dev, "could not allocate update_ovls_work_t\n"); | |
1511 | ret = -ENOMEM; | |
1512 | goto err; | |
1513 | } | |
1514 | INIT_WORK((struct work_struct*)work, mtkfb_update_ovls_handler); | |
1515 | work->dev = (void*)fbdev; | |
1516 | ||
1517 | /* Copy configs */ | |
1518 | memcpy(&work->config, config, sizeof(struct fb_overlay_config)); | |
1519 | ||
1520 | /* Import fences so userspace can close (deref) them after ioctl */ | |
1521 | for (i = 0; i < HW_OVERLAY_COUNT; i++) { | |
1522 | struct fb_overlay_layer* layer = &config->layers[i]; | |
1523 | ||
1524 | if (layer->fence_fd < 0) { | |
1525 | work->fences[i] = NULL; | |
1526 | continue; /* Nothing to wait on */ | |
1527 | } | |
1528 | work->fences[i] = sync_fence_fdget(layer->fence_fd); | |
1529 | MMProfileLogEx(MTKFB_MMP_Events.HWCFence[i], MMProfileFlagStart, layer->fence_fd, (unsigned int)work->fences[i]); | |
1530 | //pr_err("[02420] mtkfb (ion_import_dma_buf) layer[%d]->fence_fd=%d fences=%x layer->ion_fd=%x",i,layer->fence_fd, work->fences[i], layer->ion_fd); | |
1531 | if (!work->fences[i]) { | |
1532 | /* This is bad, but we just log an error and continue */ | |
1533 | pr_err(" failed to import sync fence\n"); | |
1534 | work->fences[i] = NULL; | |
1535 | continue; | |
1536 | } | |
1537 | } | |
1538 | /* Import ion handles so userspace (hwc) doesn't need to have a ref to them */ | |
1539 | for (i = 0; i < HW_OVERLAY_COUNT; i++) { | |
1540 | struct fb_overlay_layer *layer = &config->layers[i]; | |
1541 | if (layer->ion_fd < 0||layer->layer_enable == 0) { //[02420] if (!work->fences[i] || layer->ion_fd <= 0) { | |
1542 | work->ion_handles[i] = NULL; | |
1543 | continue; /* worker will use mva from userspace */ | |
1544 | } | |
1545 | work->ion_handles[i] = ion_import_dma_buf(fbdev->ion_client, layer->ion_fd); | |
1546 | ||
1547 | #if 0/*monica debug use start*/ | |
1548 | ||
1549 | int counter = 0; | |
1550 | int counter_1 = 0; | |
1551 | int statistics = 0; | |
1552 | for(counter_1=0; counter_1 < 1024 ; counter_1++){ | |
1553 | if(ion_handle_note[counter_1] == 0){ | |
1554 | ion_handle_note[counter_1] = work->ion_handles[i]; | |
1555 | break; | |
1556 | } | |
1557 | } | |
1558 | if(counter_1 >= 1023){ | |
1559 | pr_err("[02420] Queue full"); | |
1560 | } | |
1561 | ||
1562 | for(counter=0; counter < 1024 ; counter++){ | |
1563 | if(ion_handle_note[counter] != 0) | |
1564 | statistics++; | |
1565 | } | |
1566 | pr_err("[02420] import[%d] put at [%d] layer->ion_fd = %x tablet_entry_cnt = %d\n", i, counter_1, work->ion_handles[i], statistics); | |
1567 | ||
1568 | #endif/*monica debug use end*/ | |
1569 | ||
1570 | if (IS_ERR(work->ion_handles[i])) { | |
1571 | dev_err(fbdev->dev, "failed to import ion fd, disable ovl %d\n", i); | |
1572 | work->ion_handles[i] = NULL; | |
1573 | layer->layer_enable = 0; | |
1574 | continue; | |
1575 | } | |
1576 | } | |
1577 | /* Create sync point */ | |
1578 | mutex_lock(&fbdev->timeline_lock); | |
1579 | fbdev->timeline_max++; | |
1580 | pt = sw_sync_pt_create(fbdev->timeline, fbdev->timeline_max); | |
1581 | if(pt == NULL) { | |
1582 | pr_err(" sw_sync_pt_create NULL\n"); | |
1583 | goto err; | |
1584 | } | |
1585 | fence = sync_fence_create("display", pt); | |
1586 | if(fence == NULL) { | |
1587 | sync_pt_free(pt); | |
1588 | pr_err(" sync_fence_create NULL\n"); | |
1589 | goto err; | |
1590 | } | |
1591 | ||
1592 | sync_fence_install(fence, fd); | |
1593 | config->fence = fd; | |
1594 | MMProfileLogEx(MTKFB_MMP_Events.FBFence, MMProfileFlagPulse, config->fence, fbdev->timeline->value); | |
1595 | MMProfileLogEx(MTKFB_MMP_Events.FBTimeline, MMProfileFlagStart, fbdev->timeline->value, fbdev->timeline_max); | |
1596 | //pr_err("[02420]output fence=%x fbdev->timeline_max=%d",fd, fbdev->timeline_max); | |
1597 | mutex_unlock(&fbdev->timeline_lock); | |
1598 | ||
1599 | /* Queue work */ | |
1600 | queue_work(fbdev->update_ovls_wq, (struct work_struct*)work); | |
1601 | goto out; | |
1602 | ||
1603 | err: | |
1604 | pr_warn("mtkfb_queue_overlay_config fd=%d failed\n", fd); | |
1605 | config->fence = -1; | |
1606 | if (fd >=0) | |
1607 | put_unused_fd(fd); | |
1608 | kfree(work); | |
1609 | ||
1610 | out: | |
1611 | up(&sem_early_suspend); | |
1612 | MMProfileLog(MTKFB_MMP_Events.QueueWork, MMProfileFlagEnd); | |
1613 | ||
1614 | return ret; | |
1615 | } | |
1616 | ||
1617 | static int mtkfb_set_overlay_layer(struct mtkfb_device *fbdev, struct fb_overlay_layer* layerInfo) | |
1618 | { | |
1619 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1620 | unsigned int layerpitch; | |
1621 | unsigned int layerbpp; | |
1622 | #endif | |
1623 | unsigned int id = layerInfo->layer_id; | |
1624 | int enable = layerInfo->layer_enable ? 1 : 0; | |
1625 | int ret = 0; | |
1626 | ||
1627 | MTKFB_FUNC(); | |
1628 | MSG_FUNC_ENTER(); | |
1629 | MMProfileLogEx(MTKFB_MMP_Events.SetOverlayLayer, MMProfileFlagStart, (id<<16)|enable, (unsigned int)layerInfo->src_phy_addr); | |
1630 | ||
4b9e9796 S |
1631 | // Check id is valid |
1632 | if ((id < 0) || (id >= DDP_OVL_LAYER_MUN)) | |
1633 | { | |
1634 | MTKFB_LOG("Invalid layer id:%d\n", id); | |
1635 | ret = -EFAULT; | |
1636 | goto LeaveOverlayMode; | |
1637 | } | |
1638 | ||
6fa3eb70 S |
1639 | //BUG: check layer 3 format |
1640 | if((layerInfo->layer_id == 3) && (layerInfo->src_fmt != MTK_FB_FORMAT_ARGB8888)) | |
1641 | { | |
1642 | //pr_info("ERROR!!!Layer 3 format error!!!\n"); | |
1643 | } | |
1644 | ||
1645 | MTKFB_LOG("[FB Driver] mtkfb_set_overlay_layer():id=%u, en=%u, next_idx=%u, vaddr=0x%x, paddr=0x%x, fmt=%u, d-link=%u, pitch=%u, xoff=%u, yoff=%u, w=%u, h=%u\n", | |
1646 | layerInfo->layer_id, | |
1647 | layerInfo->layer_enable, | |
1648 | layerInfo->next_buff_idx, | |
1649 | (unsigned int)(layerInfo->src_base_addr), | |
1650 | (unsigned int)(layerInfo->src_phy_addr), | |
1651 | layerInfo->src_fmt, | |
1652 | (unsigned int)(layerInfo->src_direct_link), | |
1653 | layerInfo->src_pitch, | |
1654 | layerInfo->src_offset_x, | |
1655 | layerInfo->src_offset_y, | |
1656 | layerInfo->src_width, | |
1657 | layerInfo->src_height); | |
1658 | MTKFB_LOG("[FB Driver] mtkfb_set_overlay_layer():target xoff=%u, target yoff=%u, target w=%u, target h=%u\n", | |
1659 | layerInfo->tgt_offset_x, | |
1660 | layerInfo->tgt_offset_y, | |
1661 | layerInfo->tgt_width, | |
1662 | layerInfo->tgt_height); | |
1663 | ||
1664 | // Update Layer Enable Bits and Layer Config Dirty Bits | |
1665 | if ((((fbdev->layer_enable >> id) & 1) ^ enable)) { | |
1666 | fbdev->layer_enable ^= (1 << id); | |
1667 | fbdev->layer_config_dirty |= MTKFB_LAYER_ENABLE_DIRTY; | |
1668 | } | |
1669 | ||
1670 | // Update Layer Format and Layer Config Dirty Bits | |
1671 | if (fbdev->layer_format[id] != layerInfo->src_fmt) { | |
1672 | fbdev->layer_format[id] = layerInfo->src_fmt; | |
1673 | fbdev->layer_config_dirty |= MTKFB_LAYER_FORMAT_DIRTY; | |
1674 | } | |
1675 | ||
1676 | // Enter Overlay Mode if any layer is enabled except the FB layer | |
1677 | ||
1678 | if(fbdev->layer_enable & ((1 << VIDEO_LAYER_COUNT)-1)){ | |
1679 | if (DISP_STATUS_OK == DISP_EnterOverlayMode()) { | |
1680 | MTKFB_LOG("mtkfb_ioctl(MTKFB_ENABLE_OVERLAY)\n"); | |
1681 | } | |
1682 | } | |
1683 | ||
1684 | if (!enable) | |
1685 | { | |
1686 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1687 | { | |
1688 | struct fb_overlay_layer layer = {0}; | |
1689 | layer.layer_id = layerInfo->layer_id; | |
1690 | Disp_Ovl_Engine_Get_layer_info(mtkfb_instance,&layer); | |
1691 | layer.layer_enable = enable; | |
1692 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance,&layer); | |
1693 | } | |
1694 | #else | |
1695 | cached_layer_config[id].layer_en = enable; | |
1696 | cached_layer_config[id].isDirty = true; | |
1697 | cached_layer_config[id].security = false; | |
1698 | #endif | |
1699 | ret = 0; | |
1700 | goto LeaveOverlayMode; | |
1701 | } | |
1702 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1703 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, layerInfo); | |
1704 | #endif | |
1705 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1706 | ||
1707 | switch (layerInfo->src_fmt) | |
1708 | { | |
1709 | case MTK_FB_FORMAT_YUV422: | |
1710 | cached_layer_config[id].fmt = eYUY2; | |
1711 | layerpitch = 2; | |
1712 | layerbpp = 24; | |
1713 | break; | |
1714 | ||
1715 | case MTK_FB_FORMAT_RGB565: | |
1716 | cached_layer_config[id].fmt = eRGB565; | |
1717 | layerpitch = 2; | |
1718 | layerbpp = 16; | |
1719 | break; | |
1720 | ||
1721 | case MTK_FB_FORMAT_RGB888: | |
1722 | cached_layer_config[id].fmt = eRGB888; | |
1723 | layerpitch = 3; | |
1724 | layerbpp = 24; | |
1725 | break; | |
1726 | case MTK_FB_FORMAT_BGR888: | |
1727 | cached_layer_config[id].fmt = eBGR888; | |
1728 | layerpitch = 3; | |
1729 | layerbpp = 24; | |
1730 | break; | |
1731 | ||
1732 | case MTK_FB_FORMAT_ARGB8888: | |
1733 | cached_layer_config[id].fmt = ePARGB8888; | |
1734 | layerpitch = 4; | |
1735 | layerbpp = 32; | |
1736 | break; | |
1737 | case MTK_FB_FORMAT_ABGR8888: | |
1738 | cached_layer_config[id].fmt = ePABGR8888; | |
1739 | layerpitch = 4; | |
1740 | layerbpp = 32; | |
1741 | break; | |
1742 | case MTK_FB_FORMAT_XRGB8888: | |
1743 | cached_layer_config[id].fmt = eARGB8888; | |
1744 | layerpitch = 4; | |
1745 | layerbpp = 32; | |
1746 | break; | |
1747 | case MTK_FB_FORMAT_XBGR8888: | |
1748 | cached_layer_config[id].fmt = eABGR8888; | |
1749 | layerpitch = 4; | |
1750 | layerbpp = 32; | |
1751 | break; | |
1752 | default: | |
1753 | PRNERR("Invalid color format: 0x%x\n", layerInfo->src_fmt); | |
1754 | ret = -EFAULT; | |
1755 | goto LeaveOverlayMode; | |
1756 | } | |
1757 | cached_layer_config[id].vaddr = (unsigned int)layerInfo->src_base_addr; | |
1758 | cached_layer_config[id].security = layerInfo->security; | |
1759 | cached_layer_config[id].addr = (unsigned int)layerInfo->src_phy_addr; | |
1760 | cached_layer_config[id].isTdshp = layerInfo->isTdshp; | |
1761 | cached_layer_config[id].buff_idx = layerInfo->next_buff_idx; | |
1762 | #endif | |
1763 | ||
1764 | { | |
1765 | #if defined(MTK_HDMI_SUPPORT) | |
1766 | ||
1767 | #define SUPPORT_HMDI_SVP_P1 1 | |
1768 | ||
1769 | #if SUPPORT_HMDI_SVP_P1 | |
1770 | /* temporary solution for hdmi svp p1, always mute hdmi for svp */ | |
1771 | int tl = 0; | |
1772 | int has_prot_layer = 0; | |
1773 | int has_sec_layer = 0; | |
1774 | ||
1775 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1776 | ||
1777 | OVL_CONFIG_STRUCT cached_layer[DDP_OVL_LAYER_MUN] = {{0}, {0}, {0}, {0}}; | |
1778 | Disp_Ovl_Engine_Dump_layer_info(mtkfb_instance, &cached_layer[0], NULL, NULL); | |
1779 | ||
1780 | for(tl=0;tl<HW_OVERLAY_COUNT;tl++) | |
1781 | { | |
1782 | if( OVL_LAYER_SECURE_BUFFER == cached_layer[tl].security ) | |
1783 | { | |
1784 | has_sec_layer = 1; | |
1785 | break; | |
1786 | } | |
1787 | ||
1788 | if( OVL_LAYER_PROTECTED_BUFFER == cached_layer[tl].security ) | |
1789 | { | |
1790 | has_prot_layer = 1; | |
1791 | break; | |
1792 | } | |
1793 | } | |
1794 | #else | |
1795 | ||
1796 | for(tl=0;tl<HW_OVERLAY_COUNT;tl++) | |
1797 | { | |
1798 | if( OVL_LAYER_SECURE_BUFFER == cached_layer_config[tl].security ) | |
1799 | { | |
1800 | has_sec_layer = 1; | |
1801 | break; | |
1802 | } | |
1803 | ||
1804 | if( OVL_LAYER_PROTECTED_BUFFER == cached_layer_config[tl].security ) | |
1805 | { | |
1806 | has_prot_layer = 1; | |
1807 | break; | |
1808 | } | |
1809 | } | |
1810 | #endif | |
1811 | ||
1812 | /*if( 1 == has_sec_layer ) | |
1813 | { | |
1814 | MTKFB_LOG("Mute hdmi video for secure video buffer\n"); | |
1815 | MTK_HDMI_Set_Security_Output_SVP_P1(1); | |
1816 | } | |
1817 | else if( 1 == has_prot_layer ) | |
1818 | { | |
1819 | MTKFB_LOG("Mute hdmi video for protected video buffer\n"); | |
1820 | MTK_HDMI_Set_Security_Output(1); | |
1821 | } | |
1822 | else | |
1823 | { | |
1824 | MTKFB_LOG("Un-mute hdmi video for secure video buffer\n"); | |
1825 | MTK_HDMI_Set_Security_Output(0); | |
1826 | MTK_HDMI_Set_Security_Output_SVP_P1(0); | |
1827 | }*/ | |
1828 | #else | |
1829 | int tl = 0; | |
1830 | int cnt_security_layer = 0; | |
1831 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1832 | for(tl=0;tl<HW_OVERLAY_COUNT;tl++) | |
1833 | { | |
1834 | cnt_security_layer += cached_layer_config[tl].security; | |
1835 | } | |
1836 | #endif | |
1837 | MTKFB_LOG("Totally %d security layer is set now\n", cnt_security_layer); | |
1838 | //MTK_HDMI_Set_Security_Output(!!cnt_security_layer); | |
1839 | #endif /* SUPPORT_HMDI_SVP_P1 */ | |
1840 | #endif | |
1841 | } | |
1842 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1843 | cached_layer_config[id].identity = layerInfo->identity; | |
1844 | cached_layer_config[id].connected_type = layerInfo->connected_type; | |
1845 | ||
1846 | //set Alpha blending | |
1847 | cached_layer_config[id].alpha = 0xFF; | |
1848 | if (layerInfo->alpha_enable) { | |
1849 | cached_layer_config[id].aen = TRUE; | |
1850 | cached_layer_config[id].alpha = layerInfo->alpha; | |
1851 | } else { | |
1852 | cached_layer_config[id].aen = FALSE; | |
1853 | } | |
1854 | if (MTK_FB_FORMAT_ARGB8888 == layerInfo->src_fmt || | |
1855 | MTK_FB_FORMAT_ABGR8888 == layerInfo->src_fmt) { | |
1856 | cached_layer_config[id].aen = TRUE; | |
1857 | } | |
1858 | ||
1859 | //set src width, src height | |
1860 | cached_layer_config[id].src_x = layerInfo->src_offset_x; | |
1861 | cached_layer_config[id].src_y = layerInfo->src_offset_y; | |
1862 | cached_layer_config[id].src_w = layerInfo->src_width; | |
1863 | cached_layer_config[id].src_h = layerInfo->src_height; | |
1864 | cached_layer_config[id].dst_x = layerInfo->tgt_offset_x; | |
1865 | cached_layer_config[id].dst_y = layerInfo->tgt_offset_y; | |
1866 | cached_layer_config[id].dst_w = layerInfo->tgt_width; | |
1867 | cached_layer_config[id].dst_h = layerInfo->tgt_height; | |
1868 | if (cached_layer_config[id].dst_w > cached_layer_config[id].src_w) | |
1869 | cached_layer_config[id].dst_w = cached_layer_config[id].src_w; | |
1870 | if (cached_layer_config[id].dst_h > cached_layer_config[id].src_h) | |
1871 | cached_layer_config[id].dst_h = cached_layer_config[id].src_h; | |
1872 | ||
1873 | cached_layer_config[id].src_pitch = layerInfo->src_pitch*layerpitch; | |
1874 | #endif | |
1875 | ||
1876 | #if 0 //defined(DITHERING_SUPPORT) // for build warning temp fix!! | |
1877 | { | |
1878 | bool ditherenabled = false; | |
1879 | UINT32 ditherbpp = DISP_GetOutputBPPforDithering(); | |
1880 | UINT32 dbr = 0; | |
1881 | UINT32 dbg = 0; | |
1882 | UINT32 dbb = 0; | |
1883 | ||
1884 | if(ditherbpp < layerbpp) | |
1885 | { | |
1886 | if(ditherbpp == 16) | |
1887 | { | |
1888 | if(layerbpp == 18) | |
1889 | { | |
1890 | dbr = 1; | |
1891 | dbg = 0; | |
1892 | dbb = 1; | |
1893 | ditherenabled = true; | |
1894 | } | |
1895 | else if(layerbpp == 24 || layerbpp == 32) | |
1896 | { | |
1897 | dbr = 2; | |
1898 | dbg = 1; | |
1899 | dbb = 2; | |
1900 | ditherenabled = true; | |
1901 | } | |
1902 | else | |
1903 | { | |
1904 | MTKFB_LOG("ERROR, error dithring bpp settings\n"); | |
1905 | } | |
1906 | } | |
1907 | else if(ditherbpp == 18) | |
1908 | { | |
1909 | if(layerbpp == 24 || layerbpp == 32) | |
1910 | { | |
1911 | dbr = 1; | |
1912 | dbg = 1; | |
1913 | dbb = 1; | |
1914 | ditherenabled = true; | |
1915 | } | |
1916 | else | |
1917 | { | |
1918 | MTKFB_LOG("ERROR, error dithring bpp settings\n"); | |
1919 | ASSERT(0); | |
1920 | } | |
1921 | } | |
1922 | else if(ditherbpp == 24) | |
1923 | { | |
1924 | // do nothing here. | |
1925 | } | |
1926 | else | |
1927 | { | |
1928 | MTKFB_LOG("ERROR, error dithering bpp settings, diterbpp = %d\n",ditherbpp); | |
1929 | ASSERT(0); | |
1930 | } | |
1931 | ||
1932 | if(ditherenabled) | |
1933 | { | |
1934 | //LCD_CHECK_RET(LCD_LayerEnableDither(id, true)); | |
1935 | DISP_ConfigDither(14, 14, 14, dbr, dbg, dbb); | |
1936 | if(FB_LAYER == id){ | |
1937 | dbr_backup = dbr;dbg_backup = dbg;dbb_backup = dbb; | |
1938 | fblayer_dither_needed = ditherenabled; | |
1939 | MTKFB_LOG("[FB driver] dither enabled:%d, dither bit(%d,%d,%d)\n", fblayer_dither_needed, dbr_backup, dbg_backup, dbb_backup); | |
1940 | } | |
1941 | } | |
1942 | } | |
1943 | else | |
1944 | { | |
1945 | // no dithering needed. | |
1946 | } | |
1947 | ||
1948 | } | |
1949 | #endif | |
1950 | ||
1951 | #if defined(MTK_LCM_PHYSICAL_ROTATION) | |
1952 | if(0 == strncmp(MTK_LCM_PHYSICAL_ROTATION, "180", 3)) | |
1953 | { | |
1954 | layerInfo->layer_rotation = (layerInfo->layer_rotation + MTK_FB_ORIENTATION_180) % 4; | |
1955 | layerInfo->tgt_offset_x = MTK_FB_XRES - (layerInfo->tgt_offset_x + layerInfo->tgt_width); | |
1956 | layerInfo->tgt_offset_y = MTK_FB_YRES - (layerInfo->tgt_offset_y + layerInfo->tgt_height); | |
1957 | } | |
1958 | #endif | |
1959 | ||
1960 | video_rotation = layerInfo->video_rotation; | |
1961 | ||
1962 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
1963 | //set color key | |
1964 | cached_layer_config[id].key = layerInfo->src_color_key; | |
1965 | cached_layer_config[id].keyEn = layerInfo->src_use_color_key; | |
1966 | ||
1967 | //data transferring is triggerred in MTKFB_TRIG_OVERLAY_OUT | |
1968 | cached_layer_config[id].layer_en= enable; | |
1969 | cached_layer_config[id].isDirty = true; | |
1970 | ||
1971 | #endif | |
1972 | LeaveOverlayMode: | |
1973 | ||
1974 | // Leave Overlay Mode if only FB layer is enabled | |
1975 | if ((fbdev->layer_enable & ((1 << VIDEO_LAYER_COUNT)-1)) == 0) | |
1976 | { | |
1977 | if (DISP_STATUS_OK == DISP_LeaveOverlayMode()) | |
1978 | { | |
1979 | MTKFB_LOG("mtkfb_ioctl(MTKFB_DISABLE_OVERLAY)\n"); | |
1980 | if(fblayer_dither_needed) | |
1981 | { | |
1982 | DISP_ConfigDither(14, 14, 14, dbr_backup, dbg_backup, dbb_backup); | |
1983 | } | |
1984 | } | |
1985 | } | |
1986 | ||
1987 | MSG_FUNC_LEAVE(); | |
1988 | MMProfileLog(MTKFB_MMP_Events.SetOverlayLayer, MMProfileFlagEnd); | |
1989 | ||
1990 | return ret; | |
1991 | } | |
1992 | ||
1993 | static int mtkfb_get_overlay_layer_info(struct fb_overlay_layer_info* layerInfo) | |
1994 | { | |
1995 | DISP_LAYER_INFO layer; | |
4b9e9796 | 1996 | if ((layerInfo->layer_id < 0) || (layerInfo->layer_id >= DDP_OVL_LAYER_MUN)) |
6fa3eb70 S |
1997 | { |
1998 | return 0; | |
1999 | } | |
2000 | layer.id = layerInfo->layer_id; | |
2001 | DISP_GetLayerInfo(&layer); | |
2002 | layerInfo->layer_enabled = layer.hw_en; | |
2003 | layerInfo->curr_en = layer.curr_en; | |
2004 | layerInfo->next_en = layer.next_en; | |
2005 | layerInfo->hw_en = layer.hw_en; | |
2006 | layerInfo->curr_idx = layer.curr_idx; | |
2007 | layerInfo->next_idx = layer.next_idx; | |
2008 | layerInfo->hw_idx = layer.hw_idx; | |
2009 | layerInfo->curr_identity = layer.curr_identity; | |
2010 | layerInfo->next_identity = layer.next_identity; | |
2011 | layerInfo->hw_identity = layer.hw_identity; | |
2012 | layerInfo->curr_conn_type = layer.curr_conn_type; | |
2013 | layerInfo->next_conn_type = layer.next_conn_type; | |
2014 | layerInfo->hw_conn_type = layer.hw_conn_type; | |
2015 | ||
2016 | MTKFB_LOG("[FB Driver] mtkfb_get_overlay_layer_info():id=%u, layer en=%u, next_en=%u, curr_en=%u, hw_en=%u, next_idx=%u, curr_idx=%u, hw_idx=%u \n", | |
2017 | layerInfo->layer_id, | |
2018 | layerInfo->layer_enabled, | |
2019 | layerInfo->next_en, | |
2020 | layerInfo->curr_en, | |
2021 | layerInfo->hw_en, | |
2022 | layerInfo->next_idx, | |
2023 | layerInfo->curr_idx, | |
2024 | layerInfo->hw_idx); | |
2025 | ||
2026 | MMProfileLogEx(MTKFB_MMP_Events.LayerInfo[layerInfo->layer_id], MMProfileFlagPulse, (layerInfo->next_idx<<16)+((layerInfo->curr_idx)&0xFFFF), (layerInfo->hw_idx<<16)+(layerInfo->next_en<<8)+(layerInfo->curr_en<<4)+layerInfo->hw_en); | |
2027 | return 0; | |
2028 | } | |
2029 | ||
2030 | ||
2031 | static atomic_t capture_ui_layer_only = ATOMIC_INIT(0); /* when capturing framebuffer ,whether capture ui layer only */ | |
2032 | void mtkfb_capture_fb_only(bool enable) | |
2033 | { | |
2034 | atomic_set(&capture_ui_layer_only, enable); | |
2035 | } | |
2036 | ||
2037 | static int mtkfb_capture_framebuffer(struct fb_info *info, unsigned int pvbuf) | |
2038 | { | |
2039 | int ret = 0; | |
2040 | MMProfileLogEx(MTKFB_MMP_Events.CaptureFramebuffer, MMProfileFlagStart, pvbuf, 0); | |
2041 | MTKFB_FUNC(); | |
2042 | if (down_interruptible(&sem_flipping)) { | |
2043 | pr_info("[FB Driver] can't get semaphore:%d\n", __LINE__); | |
2044 | MMProfileLogEx(MTKFB_MMP_Events.CaptureFramebuffer, MMProfileFlagEnd, 0, 1); | |
2045 | return -ERESTARTSYS; | |
2046 | } | |
2047 | sem_flipping_cnt--; | |
2048 | mutex_lock(&ScreenCaptureMutex); | |
2049 | ||
2050 | /** LCD registers can't be R/W when its clock is gated in early suspend | |
2051 | mode; power on/off LCD to modify register values before/after func. | |
2052 | */ | |
2053 | if (is_early_suspended) | |
2054 | { | |
2055 | // Turn on engine clock. | |
2056 | disp_path_clock_on("mtkfb"); | |
2057 | } | |
2058 | ||
2059 | if (atomic_read(&capture_ui_layer_only)) | |
2060 | { | |
2061 | unsigned int w_xres = (unsigned short)fb_layer_context.src_width; | |
2062 | unsigned int h_yres = (unsigned short)fb_layer_context.src_height; | |
2063 | unsigned int pixel_bpp = info->var.bits_per_pixel / 8; // bpp is either 32 or 16, can not be other value | |
2064 | unsigned int w_fb = (unsigned int)fb_layer_context.src_pitch; | |
2065 | unsigned int fbsize = w_fb * h_yres * pixel_bpp; // frame buffer size | |
2066 | unsigned int fbaddress = info->fix.smem_start + info->var.yoffset * info->fix.line_length; //physical address | |
2067 | unsigned int mem_off_x = (unsigned short)fb_layer_context.src_offset_x; | |
2068 | unsigned int mem_off_y = (unsigned short)fb_layer_context.src_offset_y; | |
2069 | unsigned int fbv = 0; | |
2070 | fbaddress += (mem_off_y * w_fb + mem_off_x) * pixel_bpp; | |
2071 | fbv = (unsigned int)ioremap_nocache(fbaddress, fbsize); | |
2072 | MTKFB_LOG("[FB Driver], w_xres = %d, h_yres = %d, w_fb = %d, pixel_bpp = %d, fbsize = %d, fbaddress = 0x%08x\n", w_xres, h_yres, w_fb, pixel_bpp, fbsize, fbaddress); | |
2073 | if (!fbv) | |
2074 | { | |
2075 | MTKFB_LOG("[FB Driver], Unable to allocate memory for frame buffer: address=0x%08x, size=0x%08x\n", \ | |
2076 | fbaddress, fbsize); | |
2077 | goto EXIT; | |
2078 | } | |
2079 | { | |
2080 | unsigned int i; | |
2081 | for(i = 0;i < h_yres; i++) | |
2082 | { | |
2083 | memcpy((void *)(pvbuf + i * w_xres * pixel_bpp), (void *)(fbv + i * w_fb * pixel_bpp), w_xres * pixel_bpp); | |
2084 | } | |
2085 | } | |
2086 | iounmap((void *)fbv); | |
2087 | } | |
2088 | else | |
2089 | DISP_Capture_Framebuffer(pvbuf, info->var.bits_per_pixel, is_early_suspended); | |
2090 | ||
2091 | ||
2092 | EXIT: | |
2093 | if (is_early_suspended) | |
2094 | { | |
2095 | // Turn off engine clock. | |
2096 | //DISP_CHECK_RET(DISP_PowerEnable(FALSE)); | |
2097 | disp_path_clock_off("mtkfb"); | |
2098 | } | |
2099 | ||
2100 | mutex_unlock(&ScreenCaptureMutex); | |
2101 | sem_flipping_cnt++; | |
2102 | up(&sem_flipping); | |
2103 | MSG_FUNC_LEAVE(); | |
2104 | MMProfileLogEx(MTKFB_MMP_Events.CaptureFramebuffer, MMProfileFlagEnd, 0, 0); | |
2105 | ||
2106 | return ret; | |
2107 | } | |
2108 | ||
2109 | ||
2110 | #include <linux/aee.h> | |
2111 | extern OVL_CONFIG_STRUCT* captured_layer_config; | |
2112 | extern OVL_CONFIG_STRUCT* realtime_layer_config; | |
2113 | #define mtkfb_aee_print(string, args...) do{\ | |
2114 | aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_MMPROFILE_BUFFER, "sf-mtkfb blocked", string, ##args); \ | |
2115 | }while(0) | |
2116 | ||
2117 | void mtkfb_dump_layer_info(void) | |
2118 | { | |
2119 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2120 | unsigned int i; | |
2121 | OVL_CONFIG_STRUCT cached_layer[DDP_OVL_LAYER_MUN] = {{0}, {0}, {0}, {0}}; | |
2122 | OVL_CONFIG_STRUCT captured_layer[DDP_OVL_LAYER_MUN] = {{0}, {0}, {0}, {0}}; | |
2123 | OVL_CONFIG_STRUCT realtime_layer[DDP_OVL_LAYER_MUN] = {{0}, {0}, {0}, {0}}; | |
2124 | Disp_Ovl_Engine_Dump_layer_info(mtkfb_instance, &cached_layer[0], &captured_layer[0], &realtime_layer[0]); | |
2125 | pr_info("[mtkfb] start dump layer info, early_suspend=%d \n", is_early_suspended); | |
2126 | pr_info("[mtkfb] cache(next): \n"); | |
2127 | for(i=0;i<DDP_OVL_LAYER_MUN;i++) | |
2128 | { | |
2129 | pr_info("[mtkfb] layer=%d, layer_en=%d, idx=%d, fmt=%d, addr=0x%x, %d, %d, %d \n ", | |
2130 | cached_layer[i].layer, // layer | |
2131 | cached_layer[i].layer_en, | |
2132 | cached_layer[i].buff_idx, | |
2133 | cached_layer[i].fmt, | |
2134 | cached_layer[i].addr, // addr | |
2135 | cached_layer[i].identity, | |
2136 | cached_layer[i].connected_type, | |
2137 | cached_layer[i].security); | |
2138 | } | |
2139 | pr_info("[mtkfb] captured(current): \n"); | |
2140 | for(i=0;i<DDP_OVL_LAYER_MUN;i++) | |
2141 | { | |
2142 | pr_info("[mtkfb] layer=%d, layer_en=%d, idx=%d, fmt=%d, addr=0x%x, %d, %d, %d \n ", | |
2143 | captured_layer[i].layer, // layer | |
2144 | captured_layer[i].layer_en, | |
2145 | captured_layer[i].buff_idx, | |
2146 | captured_layer[i].fmt, | |
2147 | captured_layer[i].addr, // addr | |
2148 | captured_layer[i].identity, | |
2149 | captured_layer[i].connected_type, | |
2150 | captured_layer[i].security); | |
2151 | } | |
2152 | pr_info("[mtkfb] realtime(hw): \n"); | |
2153 | for(i=0;i<DDP_OVL_LAYER_MUN;i++) | |
2154 | { | |
2155 | pr_info("[mtkfb] layer=%d, layer_en=%d, idx=%d, fmt=%d, addr=0x%x, %d, %d, %d \n ", | |
2156 | realtime_layer[i].layer, // layer | |
2157 | realtime_layer[i].layer_en, | |
2158 | realtime_layer[i].buff_idx, | |
2159 | realtime_layer[i].fmt, | |
2160 | realtime_layer[i].addr, // addr | |
2161 | realtime_layer[i].identity, | |
2162 | realtime_layer[i].connected_type, | |
2163 | realtime_layer[i].security); | |
2164 | } | |
2165 | #else | |
2166 | unsigned int i; | |
2167 | pr_info("[mtkfb] start dump layer info, early_suspend=%d \n", is_early_suspended); | |
2168 | pr_info("[mtkfb] cache(next): \n"); | |
2169 | for(i=0;i<4;i++) | |
2170 | { | |
2171 | pr_info("[mtkfb] layer=%d, layer_en=%d, idx=%d, fmt=%d, addr=0x%x, %d, %d, %d \n ", | |
2172 | cached_layer_config[i].layer, // layer | |
2173 | cached_layer_config[i].layer_en, | |
2174 | cached_layer_config[i].buff_idx, | |
2175 | cached_layer_config[i].fmt, | |
2176 | cached_layer_config[i].addr, // addr | |
2177 | cached_layer_config[i].identity, | |
2178 | cached_layer_config[i].connected_type, | |
2179 | cached_layer_config[i].security); | |
2180 | } | |
2181 | ||
2182 | pr_info("[mtkfb] captured(current): \n"); | |
2183 | for(i=0;i<4;i++) | |
2184 | { | |
2185 | pr_info("[mtkfb] layer=%d, layer_en=%d, idx=%d, fmt=%d, addr=0x%x, %d, %d, %d \n ", | |
2186 | captured_layer_config[i].layer, // layer | |
2187 | captured_layer_config[i].layer_en, | |
2188 | captured_layer_config[i].buff_idx, | |
2189 | captured_layer_config[i].fmt, | |
2190 | captured_layer_config[i].addr, // addr | |
2191 | captured_layer_config[i].identity, | |
2192 | captured_layer_config[i].connected_type, | |
2193 | captured_layer_config[i].security); | |
2194 | } | |
2195 | pr_info("[mtkfb] realtime(hw): \n"); | |
2196 | for(i=0;i<4;i++) | |
2197 | { | |
2198 | pr_info("[mtkfb] layer=%d, layer_en=%d, idx=%d, fmt=%d, addr=0x%x, %d, %d, %d \n ", | |
2199 | realtime_layer_config[i].layer, // layer | |
2200 | realtime_layer_config[i].layer_en, | |
2201 | realtime_layer_config[i].buff_idx, | |
2202 | realtime_layer_config[i].fmt, | |
2203 | realtime_layer_config[i].addr, // addr | |
2204 | realtime_layer_config[i].identity, | |
2205 | realtime_layer_config[i].connected_type, | |
2206 | realtime_layer_config[i].security); | |
2207 | } | |
2208 | #endif | |
2209 | // dump mmp data | |
2210 | //mtkfb_aee_print("surfaceflinger-mtkfb blocked"); | |
2211 | ||
2212 | } | |
2213 | ||
2214 | static char *_mtkfb_ioctl_spy(unsigned int cmd) | |
2215 | { | |
2216 | switch(cmd) | |
2217 | { | |
2218 | case MTKFB_SET_OVERLAY_LAYER: | |
2219 | return "MTKFB_SET_OVERLAY_LAYER"; | |
2220 | case MTKFB_TRIG_OVERLAY_OUT: | |
2221 | return "MTKFB_TRIG_OVERLAY_OUT"; | |
2222 | case MTKFB_SET_VIDEO_LAYERS: | |
2223 | return "MTKFB_SET_VIDEO_LAYERS"; | |
2224 | case MTKFB_CAPTURE_FRAMEBUFFER: | |
2225 | return "MTKFB_CAPTURE_FRAMEBUFFER"; | |
2226 | case MTKFB_CONFIG_IMMEDIATE_UPDATE: | |
2227 | return "MTKFB_CONFIG_IMMEDIATE_UPDATE"; | |
2228 | case MTKFB_SET_MULTIPLE_LAYERS: | |
2229 | return "MTKFB_SET_MULTIPLE_LAYERS"; | |
2230 | case MTKFB_REGISTER_OVERLAYBUFFER: | |
2231 | return "MTKFB_REGISTER_OVERLAYBUFFER"; | |
2232 | case MTKFB_UNREGISTER_OVERLAYBUFFER: | |
2233 | return "MTKFB_UNREGISTER_OVERLAYBUFFER"; | |
2234 | case MTKFB_SET_ORIENTATION: | |
2235 | return "MTKFB_SET_ORIENTATION"; | |
2236 | case MTKFB_FBLAYER_ENABLE: | |
2237 | return "MTKFB_FBLAYER_ENABLE"; | |
2238 | case MTKFB_LOCK_FRONT_BUFFER: | |
2239 | return "MTKFB_LOCK_FRONT_BUFFER"; | |
2240 | case MTKFB_UNLOCK_FRONT_BUFFER: | |
2241 | return "MTKFB_UNLOCK_FRONT_BUFFER"; | |
2242 | case MTKFB_POWERON: | |
2243 | return "MTKFB_POWERON"; | |
2244 | case MTKFB_POWEROFF: | |
2245 | return "MTKFB_POWEROFF"; | |
2246 | case MTKFB_PREPARE_OVERLAY_BUFFER: | |
2247 | return "MTKFB_PREPARE_OVERLAY_BUFFER"; | |
2248 | case MTKFB_SET_COMPOSING3D: | |
2249 | return "MTKFB_SET_COMPOSING3D"; | |
2250 | case MTKFB_SET_S3D_FTM: | |
2251 | return "MTKFB_SET_S3D_FTM"; | |
2252 | case MTKFB_GET_DEFAULT_UPDATESPEED: | |
2253 | return "MTKFB_GET_DEFAULT_UPDATESPEED"; | |
2254 | case MTKFB_GET_CURR_UPDATESPEED: | |
2255 | return "MTKFB_GET_CURR_UPDATESPEED"; | |
2256 | case MTKFB_CHANGE_UPDATESPEED: | |
2257 | return "MTKFB_CHANGE_UPDATESPEED"; | |
2258 | case MTKFB_GET_INTERFACE_TYPE: | |
2259 | return "MTKFB_GET_INTERFACE_TYPE"; | |
2260 | case MTKFB_GET_POWERSTATE: | |
2261 | return "MTKFB_GET_POWERSTATE"; | |
2262 | case MTKFB_GET_DISPLAY_IF_INFORMATION: | |
2263 | return "MTKFB_GET_DISPLAY_IF_INFORMATION"; | |
2264 | case MTKFB_AEE_LAYER_EXIST: | |
2265 | return "MTKFB_AEE_LAYER_EXIST"; | |
2266 | case MTKFB_GET_OVERLAY_LAYER_INFO: | |
2267 | return "MTKFB_GET_OVERLAY_LAYER_INFO"; | |
2268 | case MTKFB_FACTORY_AUTO_TEST: | |
2269 | return "MTKFB_FACTORY_AUTO_TEST"; | |
2270 | case MTKFB_GET_FRAMEBUFFER_MVA: | |
2271 | return "MTKFB_GET_FRAMEBUFFER_MVA"; | |
2272 | case MTKFB_SLT_AUTO_CAPTURE: | |
2273 | return "MTKFB_SLT_AUTO_CAPTURE"; | |
2274 | case MTKFB_GETVFRAMEPHYSICAL: | |
2275 | return "MTKFB_GETVFRAMEPHYSICAL"; | |
2276 | case MTKFB_WAIT_OVERLAY_READY: | |
2277 | return "MTKFB_WAIT_OVERLAY_READY"; | |
2278 | case MTKFB_GET_OVERLAY_LAYER_COUNT: | |
2279 | return "MTKFB_GET_OVERLAY_LAYER_COUNT"; | |
2280 | case MTKFB_GET_VIDEOLAYER_SIZE: | |
2281 | return "MTKFB_GET_VIDEOLAYER_SIZE"; | |
2282 | case MTKFB_CAPTURE_VIDEOBUFFER: | |
2283 | return "MTKFB_CAPTURE_VIDEOBUFFER"; | |
2284 | case MTKFB_TV_POST_VIDEO_BUFFER: | |
2285 | return "MTKFB_TV_POST_VIDEO_BUFFER"; | |
2286 | case MTKFB_TV_LEAVE_VIDEO_PLAYBACK_MODE: | |
2287 | return "MTKFB_TV_LEAVE_VIDEO_PLAYBACK_MODE"; | |
2288 | case MTKFB_IS_TV_CABLE_PLUG_IN: | |
2289 | return "MTKFB_IS_TV_CABLE_PLUG_IN"; | |
2290 | case MTKFB_BOOTANIMATION: | |
2291 | return "MTKFB_BOOTANIMATION"; | |
2292 | case MTKFB_GETFPS: | |
2293 | return "MTKFB_GETFPS"; | |
2294 | case MTKFB_VSYNC: | |
2295 | return "MTKFB_VSYNC"; | |
2296 | case MTKFB_FM_NOTIFY_FREQ: | |
2297 | return "MTKFB_FM_NOTIFY_FREQ"; | |
2298 | case MTKFB_RESET_UPDATESPEED: | |
2299 | return "MTKFB_RESET_UPDATESPEED"; | |
2300 | case MTKFB_SET_UI_LAYER_ALPHA: | |
2301 | return "MTKFB_SET_UI_LAYER_ALPHA"; | |
2302 | case MTKFB_SET_UI_LAYER_SRCKEY: | |
2303 | return "MTKFB_SET_UI_LAYER_SRCKEY"; | |
2304 | case MTKFB_GET_MAX_DISPLAY_COUNT: | |
2305 | return "MTKFB_GET_MAX_DISPLAY_COUNT"; | |
2306 | case MTKFB_SET_FB_LAYER_SECURE: | |
2307 | return "MTKFB_SET_FB_LAYER_SECURE"; | |
2308 | case MTKFB_META_RESTORE_SCREEN: | |
2309 | return "MTKFB_META_RESTORE_SCREEN"; | |
2310 | case MTKFB_ERROR_INDEX_UPDATE_TIMEOUT: | |
2311 | return "MTKFB_ERROR_INDEX_UPDATE_TIMEOUT"; | |
2312 | case MTKFB_ERROR_INDEX_UPDATE_TIMEOUT_AEE: | |
2313 | return "MTKFB_ERROR_INDEX_UPDATE_TIMEOUT_AEE"; | |
2314 | case MTKFB_QUEUE_OVERLAY_CONFIG: | |
2315 | return "MTKFB_QUEUE_OVERLAY_CONFIG"; | |
2316 | default: | |
2317 | return "Invalid"; | |
2318 | } | |
2319 | } | |
2320 | ||
2321 | ||
2322 | mtk_dispif_info_t dispif_info[MTKFB_MAX_DISPLAY_COUNT]; | |
2323 | extern unsigned int isAEEEnabled; | |
2324 | ||
2325 | #if LINUX_VERSION_CODE > KERNEL_VERSION(3,7,0) | |
2326 | static int mtkfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | |
2327 | #else | |
2328 | static int mtkfb_ioctl(struct file *file, struct fb_info *info, unsigned int cmd, unsigned long arg) | |
2329 | #endif | |
2330 | { | |
2331 | void __user *argp = (void __user *)arg; | |
2332 | DISP_STATUS ret = 0; | |
2333 | int r = 0, i; | |
2334 | ||
2335 | MTKFB_FUNC(); | |
2336 | /// M: dump debug mmprofile log info | |
2337 | MMProfileLogEx(MTKFB_MMP_Events.IOCtrl, MMProfileFlagPulse, _IOC_NR(cmd), arg); | |
2338 | pr_info("mtkfb_ioctl, info=0x%08x, cmd=0x%08x(%s), arg=0x%08x\n", (unsigned int)info, | |
2339 | (unsigned int)cmd, _mtkfb_ioctl_spy(cmd), (unsigned int)arg); | |
2340 | ||
2341 | switch (cmd) | |
2342 | { | |
2343 | case MTKFB_QUEUE_OVERLAY_CONFIG: | |
2344 | { | |
2345 | struct fb_overlay_config config; | |
2346 | if (copy_from_user(&config, (void __user *)arg, sizeof(config))) { | |
2347 | MTKFB_LOG("[FB]: copy_from_user failed! line: %d \n", __LINE__); | |
2348 | return -EFAULT; | |
2349 | } | |
2350 | ||
2351 | for (i = 0; i < HW_OVERLAY_COUNT; i++) | |
2352 | { | |
2353 | MTKFB_LOG("MTKFB_QUEUE_OVERLAY_CONFIG: fence:%d, time: 0x%x, layer%d en%d, next_idx=0x%x, vaddr=0x%x, paddr=0x%x, fmt=%u," | |
2354 | " d-link=%u, pitch=%u, xoff=%u, yoff=%u, w=%u, h=%u, alpha_en=%d, alpha=%d, fence_fd=%d, ion_fd=%d, security=%d\n", | |
2355 | config.fence, | |
2356 | config.time, | |
2357 | config.layers[i].layer_id, | |
2358 | config.layers[i].layer_enable, | |
2359 | config.layers[i].next_buff_idx, | |
2360 | (unsigned int)(config.layers[i].src_base_addr), | |
2361 | (unsigned int)(config.layers[i].src_phy_addr), | |
2362 | config.layers[i].src_fmt, | |
2363 | (unsigned int)(config.layers[i].src_direct_link), | |
2364 | config.layers[i].src_pitch, | |
2365 | config.layers[i].src_offset_x, | |
2366 | config.layers[i].src_offset_y, | |
2367 | config.layers[i].src_width, | |
2368 | config.layers[i].src_height, | |
2369 | config.layers[i].alpha_enable, | |
2370 | config.layers[i].alpha, | |
2371 | config.layers[i].fence_fd, | |
2372 | config.layers[i].ion_fd, | |
2373 | config.layers[i].security); | |
2374 | } | |
2375 | ||
2376 | if (!g_fb_pattern_en) | |
2377 | r = mtkfb_queue_overlay_config((struct mtkfb_device *)info->par, &config); | |
2378 | else | |
2379 | r = fb_pattern((struct mtkfb_device *)info->par, &config); | |
2380 | ||
2381 | if (copy_to_user((void __user *)arg, &config, sizeof(config))) { | |
2382 | MTKFB_LOG("[FB]: copy_to_user failed! line:%d \n", __LINE__); | |
2383 | r = -EFAULT; | |
2384 | } | |
2385 | return (r); | |
2386 | } | |
2387 | case MTKFB_SET_OVERLAY_LAYER: | |
2388 | { | |
2389 | struct fb_overlay_layer layerInfo; | |
2390 | MTKFB_LOG(" mtkfb_ioctl():MTKFB_SET_OVERLAY_LAYER\n"); | |
2391 | ||
2392 | if (copy_from_user(&layerInfo, (void __user *)arg, sizeof(layerInfo))) { | |
2393 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2394 | r = -EFAULT; | |
2395 | } | |
2396 | else | |
2397 | { | |
2398 | //in early suspend mode ,will not update buffer index, info SF by return value | |
2399 | if(is_early_suspended == TRUE) | |
2400 | { | |
2401 | pr_info("[FB] error, set overlay in early suspend ,skip! \n"); | |
2402 | return MTKFB_ERROR_IS_EARLY_SUSPEND; | |
2403 | } | |
2404 | ||
2405 | mutex_lock(&OverlaySettingMutex); | |
2406 | mtkfb_set_overlay_layer((struct mtkfb_device *)info->par, &layerInfo); | |
2407 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2408 | if (is_ipoh_bootup) | |
2409 | { | |
2410 | int i; | |
2411 | for (i=0; i<DDP_OVL_LAYER_MUN; i++) | |
2412 | cached_layer_config[i].isDirty = 1; | |
2413 | is_ipoh_bootup = false; | |
2414 | } | |
2415 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
2416 | atomic_set(&OverlaySettingApplied, 0); | |
2417 | #endif | |
2418 | mutex_unlock(&OverlaySettingMutex); | |
2419 | } | |
2420 | return (r); | |
2421 | } | |
2422 | case MTKFB_GET_FRAMEBUFFER_MVA: | |
2423 | if (copy_to_user(argp, &fb_pa, sizeof(fb_pa))) { | |
2424 | MTKFB_LOG("[FB]: copy_to_user failed! line:%d \n", __LINE__); | |
2425 | r = -EFAULT; | |
2426 | } | |
2427 | return (r); | |
2428 | case MTKFB_GET_DISPLAY_IF_INFORMATION: | |
2429 | { | |
2430 | int displayid = 0; | |
2431 | if (copy_from_user(&displayid, (void __user *)arg, sizeof(displayid))) { | |
2432 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2433 | return -EFAULT; | |
2434 | } | |
2435 | MTKFB_LOG("MTKFB_GET_DISPLAY_IF_INFORMATION display_id=%d\n", displayid); | |
4b9e9796 | 2436 | if ((displayid < 0) || (displayid >= MTKFB_MAX_DISPLAY_COUNT)) { |
6fa3eb70 S |
2437 | MTKFB_LOG("[FB]: invalid display id:%d \n", displayid); |
2438 | return -EFAULT; | |
2439 | } | |
2440 | dispif_info[displayid].physicalHeight = DISP_GetActiveHeight(); | |
2441 | dispif_info[displayid].physicalWidth = DISP_GetActiveWidth() ; | |
2442 | if (copy_to_user((void __user *)arg, &(dispif_info[displayid]), sizeof(mtk_dispif_info_t))) { | |
2443 | MTKFB_LOG("[FB]: copy_to_user failed! line:%d \n", __LINE__); | |
2444 | r = -EFAULT; | |
2445 | } | |
2446 | return (r); | |
2447 | } | |
2448 | case MTKFB_POWEROFF: | |
2449 | { | |
2450 | MTKFB_FUNC(); | |
2451 | ||
2452 | mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, LED_OFF); | |
2453 | ||
2454 | if (!lcd_fps) | |
2455 | msleep(30); | |
2456 | else | |
2457 | msleep(2*100000/lcd_fps); // Delay 2 frames. | |
2458 | ||
2459 | if(is_early_suspended) | |
2460 | { | |
2461 | MTKFB_LOG("[FB driver] MTKFB_POWEROFF ioctl,device had been suspended\n"); | |
2462 | return r; | |
2463 | } | |
2464 | if (down_interruptible(&sem_early_suspend)) | |
2465 | { | |
2466 | pr_info("[FB Driver] can't get semaphore in mtkfb_early_suspend()\n"); | |
2467 | return -ERESTARTSYS; | |
2468 | } | |
2469 | ||
2470 | is_early_suspended = TRUE; | |
2471 | up(&sem_early_suspend); | |
2472 | #ifndef NONFLUSH | |
2473 | /* Wait until queued compositions are applied */ | |
2474 | flush_workqueue(((struct mtkfb_device *)info->par)->update_ovls_wq); | |
2475 | #else | |
2476 | /* Do not flush work queue, becuase this will cause fence disorder */ | |
2477 | /* disable all layer */ | |
2478 | { | |
2479 | struct fb_overlay_config config; | |
2480 | struct sync_fence *fence; | |
2481 | ||
2482 | config.layers[0].layer_id = 0; | |
2483 | config.layers[0].layer_enable = 0; | |
2484 | config.layers[0].fence_fd = -1; | |
2485 | config.layers[0].ion_fd = -1; | |
2486 | config.layers[1].layer_id = 1; | |
2487 | config.layers[1].layer_enable = 0; | |
2488 | config.layers[1].fence_fd = -1; | |
2489 | config.layers[1].ion_fd = -1; | |
2490 | config.layers[2].layer_id = 2; | |
2491 | config.layers[2].layer_enable = 0; | |
2492 | config.layers[2].fence_fd = -1; | |
2493 | config.layers[2].ion_fd = -1; | |
2494 | config.layers[3].layer_id = 3; | |
2495 | config.layers[3].layer_enable = 0; | |
2496 | config.layers[3].fence_fd = -1; | |
2497 | config.layers[3].ion_fd = -1; | |
2498 | ||
2499 | mtkfb_queue_overlay_config((struct mtkfb_device *)info->par, &config); | |
2500 | ||
2501 | if (config.fence != -1) { | |
2502 | fence = sync_fence_fdget(config.fence); | |
2503 | if (sync_fence_wait(fence, 1000) < 0) | |
2504 | pr_err("MTKFB_POWEROFF error waiting for fence to signal\n"); | |
2505 | sync_fence_put(fence); | |
2506 | put_unused_fd(config.fence); | |
2507 | } | |
2508 | } | |
2509 | #endif | |
2510 | if (down_interruptible(&sem_early_suspend)) | |
2511 | { | |
2512 | pr_info("[FB Driver] can't get semaphore in mtkfb_early_suspend()\n"); | |
2513 | return -ERESTARTSYS; | |
2514 | } | |
2515 | ||
2516 | DISP_PrepareSuspend(); | |
2517 | // Wait for disp finished. | |
2518 | /* [PLATFORM]-Mod-BEGIN by TCTSZ.yaohui.zeng, 2015/04/15,MTK patch,fix FB suspend/resume DSI issue*/ | |
2519 | if(wait_event_interruptible_timeout(_dsi_wait_vm_done_queue, !_IsEngineBusy(), HZ/10)==0 ) | |
2520 | { | |
2521 | pr_info("[FB Driver] Wait disp finished timeout in early_suspend\n"); | |
2522 | } | |
2523 | /* [PLATFORM]-Mod-END by TCTSZ.yaohui.zeng, 2015/04/15*/ | |
2524 | DISP_CHECK_RET(DISP_PauseVsync(TRUE)); | |
2525 | DISP_CHECK_RET(DISP_PanelEnable(FALSE)); | |
2526 | DISP_CHECK_RET(DISP_PowerEnable(FALSE)); | |
2527 | disp_path_clock_off("mtkfb"); | |
2528 | ||
2529 | MMProfileLog(MTKFB_MMP_Events.EarlySuspend, MMProfileFlagStart); | |
2530 | ||
2531 | up(&sem_early_suspend); | |
2532 | ||
2533 | return r; | |
2534 | } | |
2535 | ||
2536 | case MTKFB_POWERON: | |
2537 | { | |
2538 | MTKFB_FUNC(); | |
2539 | if(!is_early_suspended) return r; | |
2540 | if (down_interruptible(&sem_early_suspend)) | |
2541 | { | |
2542 | pr_info("[FB Driver] can't get semaphore in mtkfb_late_resume()\n"); | |
2543 | return -ERESTARTSYS; | |
2544 | } | |
2545 | disp_path_clock_on("mtkfb"); | |
2546 | DISP_CHECK_RET(DISP_PauseVsync(FALSE)); | |
2547 | DISP_CHECK_RET(DISP_PowerEnable(TRUE)); | |
2548 | DISP_CHECK_RET(DISP_PanelEnable(TRUE)); | |
2549 | ||
2550 | is_early_suspended = FALSE; | |
2551 | ||
2552 | if (is_ipoh_bootup) { //ALPS01279263 CL2317283 | |
2553 | DISP_StartConfigUpdate(); | |
2554 | } else { | |
2555 | mtkfb_clear_lcm(); | |
2556 | } | |
2557 | ||
2558 | MMProfileLog(MTKFB_MMP_Events.EarlySuspend, MMProfileFlagEnd); | |
2559 | up(&sem_early_suspend); | |
2560 | ||
2561 | return r; | |
2562 | } | |
2563 | case MTKFB_GET_POWERSTATE: | |
2564 | { | |
2565 | unsigned long power_state; | |
2566 | ||
2567 | if(is_early_suspended == TRUE) | |
2568 | power_state = 0; | |
2569 | else | |
2570 | power_state = 1; | |
2571 | ||
2572 | return copy_to_user(argp, &power_state, sizeof(power_state)) ? -EFAULT : 0; | |
2573 | } | |
2574 | ||
2575 | case MTKFB_CONFIG_IMMEDIATE_UPDATE: | |
2576 | { | |
2577 | MTKFB_LOG("[%s] MTKFB_CONFIG_IMMEDIATE_UPDATE, enable = %lu\n", | |
2578 | __func__, arg); | |
2579 | if (down_interruptible(&sem_early_suspend)) { | |
2580 | MTKFB_LOG("[mtkfb_ioctl] can't get semaphore:%d\n", __LINE__); | |
2581 | return -ERESTARTSYS; | |
2582 | } | |
2583 | sem_early_suspend_cnt--; | |
2584 | DISP_WaitForLCDNotBusy(); | |
2585 | ret = DISP_ConfigImmediateUpdate((BOOL)arg); | |
2586 | sem_early_suspend_cnt++; | |
2587 | up(&sem_early_suspend); | |
2588 | return (r); | |
2589 | } | |
2590 | ||
2591 | case MTKFB_CAPTURE_FRAMEBUFFER: | |
2592 | { | |
2593 | unsigned int pbuf = 0; | |
2594 | if (copy_from_user(&pbuf, (void __user *)arg, sizeof(pbuf))) | |
2595 | { | |
2596 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2597 | r = -EFAULT; | |
2598 | } | |
2599 | else | |
2600 | { | |
2601 | mtkfb_capture_framebuffer(info, pbuf); | |
2602 | } | |
2603 | ||
2604 | return (r); | |
2605 | } | |
2606 | ||
2607 | case MTKFB_GET_OVERLAY_LAYER_INFO: | |
2608 | { | |
2609 | struct fb_overlay_layer_info layerInfo; | |
2610 | MTKFB_LOG(" mtkfb_ioctl():MTKFB_GET_OVERLAY_LAYER_INFO\n"); | |
2611 | ||
2612 | if (copy_from_user(&layerInfo, (void __user *)arg, sizeof(layerInfo))) { | |
2613 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2614 | return -EFAULT; | |
2615 | } | |
2616 | if (mtkfb_get_overlay_layer_info(&layerInfo) < 0) | |
2617 | { | |
2618 | MTKFB_LOG("[FB]: Failed to get overlay layer info\n"); | |
2619 | return -EFAULT; | |
2620 | } | |
2621 | if (copy_to_user((void __user *)arg, &layerInfo, sizeof(layerInfo))) { | |
2622 | MTKFB_LOG("[FB]: copy_to_user failed! line:%d \n", __LINE__); | |
2623 | r = -EFAULT; | |
2624 | } | |
2625 | return (r); | |
2626 | } | |
2627 | ||
2628 | case MTKFB_ERROR_INDEX_UPDATE_TIMEOUT: | |
2629 | { | |
2630 | pr_info("[DDP] mtkfb_ioctl():MTKFB_ERROR_INDEX_UPDATE_TIMEOUT \n"); | |
2631 | // call info dump function here | |
2632 | mtkfb_dump_layer_info(); | |
2633 | return (r); | |
2634 | } | |
2635 | ||
2636 | case MTKFB_ERROR_INDEX_UPDATE_TIMEOUT_AEE: | |
2637 | { | |
2638 | pr_info("[DDP] mtkfb_ioctl():MTKFB_ERROR_INDEX_UPDATE_TIMEOUT \n"); | |
2639 | // call info dump function here | |
2640 | mtkfb_dump_layer_info(); | |
2641 | mtkfb_aee_print("surfaceflinger-mtkfb blocked"); | |
2642 | return (r); | |
2643 | } | |
2644 | ||
2645 | case MTKFB_SET_VIDEO_LAYERS: | |
2646 | { | |
2647 | struct mmp_fb_overlay_layers | |
2648 | { | |
2649 | struct fb_overlay_layer Layer0; | |
2650 | struct fb_overlay_layer Layer1; | |
2651 | struct fb_overlay_layer Layer2; | |
2652 | struct fb_overlay_layer Layer3; | |
2653 | }; | |
2654 | struct fb_overlay_layer layerInfo[VIDEO_LAYER_COUNT]; | |
2655 | MTKFB_LOG(" mtkfb_ioctl():MTKFB_SET_VIDEO_LAYERS\n"); | |
2656 | MMProfileLog(MTKFB_MMP_Events.SetOverlayLayers, MMProfileFlagStart); | |
2657 | if (copy_from_user(&layerInfo, (void __user *)arg, sizeof(layerInfo))) { | |
2658 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2659 | MMProfileLogMetaString(MTKFB_MMP_Events.SetOverlayLayers, MMProfileFlagEnd, "Copy_from_user failed!"); | |
2660 | r = -EFAULT; | |
2661 | } else { | |
2662 | int32_t i; | |
2663 | mutex_lock(&OverlaySettingMutex); | |
2664 | for (i = 0; i < VIDEO_LAYER_COUNT; ++i) { | |
2665 | mtkfb_set_overlay_layer((struct mtkfb_device *)info->par, &layerInfo[i]); | |
2666 | } | |
2667 | is_ipoh_bootup = false; | |
2668 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2669 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
2670 | atomic_set(&OverlaySettingApplied, 0); | |
2671 | #endif | |
2672 | mutex_unlock(&OverlaySettingMutex); | |
2673 | MMProfileLogStructure(MTKFB_MMP_Events.SetOverlayLayers, MMProfileFlagEnd, layerInfo, struct mmp_fb_overlay_layers); | |
2674 | } | |
2675 | ||
2676 | return (r); | |
2677 | } | |
2678 | ||
2679 | case MTKFB_TRIG_OVERLAY_OUT: | |
2680 | { | |
2681 | MTKFB_LOG(" mtkfb_ioctl():MTKFB_TRIG_OVERLAY_OUT\n"); | |
2682 | MMProfileLog(MTKFB_MMP_Events.TrigOverlayOut, MMProfileFlagPulse); | |
2683 | return mtkfb_update_screen(info); | |
2684 | } | |
2685 | ||
2686 | //#endif // MTK_FB_OVERLAY_SUPPORT | |
2687 | ||
2688 | case MTKFB_SET_ORIENTATION: | |
2689 | { | |
2690 | MTKFB_LOG("[MTKFB] Set Orientation: %lu\n", arg); | |
2691 | // surface flinger orientation definition of 90 and 270 | |
2692 | // is different than DISP_TV_ROT | |
2693 | if (arg & 0x1) arg ^= 0x2; | |
2694 | arg *=90; | |
2695 | #if defined(MTK_HDMI_SUPPORT) | |
2696 | //for MT6589, the orientation of DDPK is changed from 0123 to 0/90/180/270 | |
2697 | hdmi_setorientation((int)arg); | |
2698 | #endif | |
2699 | return 0; | |
2700 | } | |
2701 | case MTKFB_META_RESTORE_SCREEN: | |
2702 | { | |
2703 | struct fb_var_screeninfo var; | |
2704 | ||
2705 | if (copy_from_user(&var, argp, sizeof(var))) | |
2706 | return -EFAULT; | |
2707 | ||
2708 | info->var.yoffset = var.yoffset; | |
2709 | init_framebuffer(info); | |
2710 | ||
2711 | return mtkfb_pan_display_impl(&var, info); | |
2712 | } | |
2713 | ||
2714 | case MTKFB_GET_INTERFACE_TYPE: | |
2715 | { | |
2716 | extern LCM_PARAMS *lcm_params; | |
2717 | unsigned long lcm_type = lcm_params->type; | |
2718 | ||
2719 | MTKFB_LOG("[MTKFB] MTKFB_GET_INTERFACE_TYPE\n"); | |
2720 | ||
2721 | pr_info("[MTKFB EM]MTKFB_GET_INTERFACE_TYPE is %ld\n", lcm_type); | |
2722 | ||
2723 | return copy_to_user(argp, &lcm_type, sizeof(lcm_type)) ? -EFAULT : 0; | |
2724 | } | |
2725 | case MTKFB_GET_DEFAULT_UPDATESPEED: | |
2726 | { | |
2727 | unsigned int speed; | |
2728 | MTKFB_LOG("[MTKFB] get default update speed\n"); | |
2729 | DISP_Get_Default_UpdateSpeed(&speed); | |
2730 | ||
2731 | pr_info("[MTKFB EM]MTKFB_GET_DEFAULT_UPDATESPEED is %d\n", speed); | |
2732 | return copy_to_user(argp, &speed, | |
2733 | sizeof(speed)) ? -EFAULT : 0; | |
2734 | } | |
2735 | ||
2736 | case MTKFB_GET_CURR_UPDATESPEED: | |
2737 | { | |
2738 | unsigned int speed; | |
2739 | MTKFB_LOG("[MTKFB] get current update speed\n"); | |
2740 | DISP_Get_Current_UpdateSpeed(&speed); | |
2741 | ||
2742 | pr_info("[MTKFB EM]MTKFB_GET_CURR_UPDATESPEED is %d\n", speed); | |
2743 | return copy_to_user(argp, &speed, | |
2744 | sizeof(speed)) ? -EFAULT : 0; | |
2745 | } | |
2746 | ||
2747 | case MTKFB_CHANGE_UPDATESPEED: | |
2748 | { | |
2749 | unsigned int speed; | |
2750 | MTKFB_LOG("[MTKFB] change update speed\n"); | |
2751 | ||
2752 | if (copy_from_user(&speed, (void __user *)arg, sizeof(speed))) { | |
2753 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2754 | r = -EFAULT; | |
2755 | } else { | |
2756 | DISP_Change_Update(speed); | |
2757 | ||
2758 | pr_info("[MTKFB EM]MTKFB_CHANGE_UPDATESPEED is %d\n", speed); | |
2759 | ||
2760 | } | |
2761 | return (r); | |
2762 | } | |
2763 | ||
2764 | case MTKFB_FBLAYER_ENABLE: | |
2765 | { | |
2766 | BOOL enable; | |
2767 | if(copy_from_user(&enable,(void __user*)argp,sizeof(BOOL))){ | |
2768 | MTKFB_LOG("[FB]: copy_from_user failed! line:%d \n", __LINE__); | |
2769 | r = -EFAULT; | |
2770 | } | |
2771 | else{ | |
2772 | MTKFB_LOG("[FB]: FDLAYER_ENABLE:%d \n",enable); | |
2773 | ||
2774 | hwc_force_fb_enabled = (enable ? true : false); | |
2775 | ||
2776 | mutex_lock(&OverlaySettingMutex); | |
2777 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2778 | { | |
2779 | struct fb_overlay_layer layer = {0}; | |
2780 | layer.layer_id = 0; | |
2781 | Disp_Ovl_Engine_Get_layer_info(mtkfb_instance, &layer); | |
2782 | layer.layer_enable = enable; | |
2783 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layer); | |
2784 | } | |
2785 | #else | |
2786 | cached_layer_config[FB_LAYER].layer_en = enable; | |
2787 | #endif | |
2788 | if (mtkfb_using_layer_type != LAYER_2D) | |
2789 | { | |
2790 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2791 | { | |
2792 | struct fb_overlay_layer layer = {0}; | |
2793 | layer.layer_id = FB_LAYER+1; | |
2794 | Disp_Ovl_Engine_Get_layer_info(mtkfb_instance, &layer); | |
2795 | layer.layer_enable = enable; | |
2796 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layer); | |
2797 | } | |
2798 | #else | |
2799 | cached_layer_config[FB_LAYER+1].layer_en = enable; | |
2800 | #endif | |
2801 | } | |
2802 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2803 | cached_layer_config[FB_LAYER].isDirty= true; | |
2804 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
2805 | atomic_set(&OverlaySettingApplied, 0); | |
2806 | #endif | |
2807 | mutex_unlock(&OverlaySettingMutex); | |
2808 | ||
2809 | ||
2810 | } | |
2811 | ||
2812 | return (r); | |
2813 | } | |
2814 | case MTKFB_AEE_LAYER_EXIST: | |
2815 | { | |
2816 | //pr_info("[MTKFB] isAEEEnabled=%d \n", isAEEEnabled); | |
2817 | return copy_to_user(argp, &isAEEEnabled, | |
2818 | sizeof(isAEEEnabled)) ? -EFAULT : 0; | |
2819 | } | |
2820 | case MTKFB_LOCK_FRONT_BUFFER: | |
2821 | return 0; | |
2822 | case MTKFB_UNLOCK_FRONT_BUFFER: | |
2823 | return 0; | |
2824 | //////////////////////////////////////////////// | |
2825 | default: | |
2826 | pr_info("mtkfb_ioctl 0x%08x(%s) Not support", (unsigned int)cmd, _mtkfb_ioctl_spy(cmd)); | |
2827 | //pr_info("mtkfb_ioctl Not support,MTKFB_QUEUE_OVERLAY_CONFIG=0x%08x info=0x%08x, cmd=0x%08x, arg=0x%08x\n",MTKFB_QUEUE_OVERLAY_CONFIG, (unsigned int)info, (unsigned int)cmd, (unsigned int)arg); | |
2828 | return -EINVAL; | |
2829 | } | |
2830 | } | |
2831 | ||
2832 | ||
2833 | /* Callback table for the frame buffer framework. Some of these pointers | |
2834 | * will be changed according to the current setting of fb_info->accel_flags. | |
2835 | */ | |
2836 | static struct fb_ops mtkfb_ops = { | |
2837 | .owner = THIS_MODULE, | |
2838 | .fb_open = mtkfb_open, | |
2839 | .fb_release = mtkfb_release, | |
2840 | .fb_setcolreg = mtkfb_setcolreg, | |
2841 | .fb_pan_display = mtkfb_pan_display_proxy, | |
2842 | .fb_fillrect = cfb_fillrect, | |
2843 | .fb_copyarea = cfb_copyarea, | |
2844 | .fb_imageblit = cfb_imageblit, | |
2845 | .fb_cursor = mtkfb_soft_cursor, | |
2846 | .fb_check_var = mtkfb_check_var, | |
2847 | .fb_set_par = mtkfb_set_par, | |
2848 | .fb_ioctl = mtkfb_ioctl, | |
2849 | }; | |
2850 | ||
2851 | /* | |
2852 | * --------------------------------------------------------------------------- | |
2853 | * Sysfs interface | |
2854 | * --------------------------------------------------------------------------- | |
2855 | */ | |
2856 | ||
2857 | static int mtkfb_register_sysfs(struct mtkfb_device *fbdev) | |
2858 | { | |
2859 | NOT_REFERENCED(fbdev); | |
2860 | ||
2861 | return 0; | |
2862 | } | |
2863 | ||
2864 | static void mtkfb_unregister_sysfs(struct mtkfb_device *fbdev) | |
2865 | { | |
2866 | NOT_REFERENCED(fbdev); | |
2867 | } | |
2868 | ||
2869 | /* | |
2870 | * --------------------------------------------------------------------------- | |
2871 | * LDM callbacks | |
2872 | * --------------------------------------------------------------------------- | |
2873 | */ | |
2874 | /* Initialize system fb_info object and set the default video mode. | |
2875 | * The frame buffer memory already allocated by lcddma_init | |
2876 | */ | |
2877 | static int mtkfb_fbinfo_init(struct fb_info *info) | |
2878 | { | |
2879 | struct mtkfb_device *fbdev = (struct mtkfb_device *)info->par; | |
2880 | struct fb_var_screeninfo var; | |
2881 | int r = 0; | |
2882 | ||
2883 | MSG_FUNC_ENTER(); | |
2884 | ||
2885 | BUG_ON(!fbdev->fb_va_base); | |
2886 | info->fbops = &mtkfb_ops; | |
2887 | info->flags = FBINFO_FLAG_DEFAULT; | |
2888 | info->screen_base = (char *) fbdev->fb_va_base; | |
2889 | info->screen_size = fbdev->fb_size_in_byte; | |
2890 | info->pseudo_palette = fbdev->pseudo_palette; | |
2891 | ||
2892 | r = fb_alloc_cmap(&info->cmap, 16, 0); | |
2893 | if (r != 0) | |
2894 | PRNERR("unable to allocate color map memory\n"); | |
2895 | ||
2896 | // setup the initial video mode (RGB565) | |
2897 | ||
2898 | memset(&var, 0, sizeof(var)); | |
2899 | ||
2900 | var.xres = MTK_FB_XRES; | |
2901 | var.yres = MTK_FB_YRES; | |
2902 | var.xres_virtual = MTK_FB_XRESV; | |
2903 | var.yres_virtual = MTK_FB_YRESV; | |
2904 | ||
2905 | var.bits_per_pixel = 16; | |
2906 | ||
2907 | var.red.offset = 11; var.red.length = 5; | |
2908 | var.green.offset = 5; var.green.length = 6; | |
2909 | var.blue.offset = 0; var.blue.length = 5; | |
2910 | ||
2911 | var.width = DISP_GetActiveWidth(); | |
2912 | var.height = DISP_GetActiveHeight(); | |
2913 | ||
2914 | var.activate = FB_ACTIVATE_NOW; | |
2915 | ||
2916 | r = mtkfb_check_var(&var, info); | |
2917 | if (r != 0) | |
2918 | PRNERR("failed to mtkfb_check_var\n"); | |
2919 | ||
2920 | info->var = var; | |
2921 | ||
2922 | r = mtkfb_set_par(info); | |
2923 | if (r != 0) | |
2924 | PRNERR("failed to mtkfb_set_par\n"); | |
2925 | ||
2926 | MSG_FUNC_LEAVE(); | |
2927 | return r; | |
2928 | } | |
2929 | ||
2930 | /* Release the fb_info object */ | |
2931 | static void mtkfb_fbinfo_cleanup(struct mtkfb_device *fbdev) | |
2932 | { | |
2933 | MSG_FUNC_ENTER(); | |
2934 | ||
2935 | fb_dealloc_cmap(&fbdev->fb_info->cmap); | |
2936 | ||
2937 | MSG_FUNC_LEAVE(); | |
2938 | } | |
2939 | ||
2940 | void mtkfb_disable_non_fb_layer(void) | |
2941 | { | |
2942 | int id; | |
2943 | unsigned int dirty = 0; | |
2944 | for (id = 0; id < DDP_OVL_LAYER_MUN; id++) | |
2945 | { | |
2946 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2947 | { | |
2948 | struct fb_overlay_layer layer = {0}; | |
2949 | layer.layer_id = id; | |
2950 | Disp_Ovl_Engine_Get_layer_info(mtkfb_instance, &layer); | |
2951 | layer.layer_enable = 0; | |
2952 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layer); | |
2953 | } | |
2954 | #else | |
2955 | if (cached_layer_config[id].layer_en == 0) | |
2956 | continue; | |
2957 | ||
2958 | if (cached_layer_config[id].addr >= fb_pa && | |
2959 | cached_layer_config[id].addr < (fb_pa+DISP_GetVRamSize())) | |
2960 | continue; | |
2961 | ||
2962 | DISP_LOG_PRINT(ANDROID_LOG_INFO, "LCD", " disable(%d)\n", id); | |
2963 | cached_layer_config[id].layer_en = 0; | |
2964 | cached_layer_config[id].isDirty = true; | |
2965 | #endif | |
2966 | dirty = 1; | |
2967 | } | |
2968 | if (dirty) | |
2969 | { | |
2970 | memset(mtkfb_fbi->screen_base, 0, DISP_GetVRamSize()); | |
2971 | mtkfb_pan_display_impl(&mtkfb_fbi->var, mtkfb_fbi); | |
2972 | } | |
2973 | } | |
2974 | ||
2975 | int m4u_reclaim_mva_callback_ovl(int moduleID, unsigned int va, unsigned int size, unsigned int mva) | |
2976 | { | |
2977 | int id; | |
2978 | unsigned int dirty = 0; | |
2979 | MMProfileLogEx(MTKFB_MMP_Events.Debug, MMProfileFlagStart, mva, size); | |
2980 | for (id = 0; id < DDP_OVL_LAYER_MUN; id++) | |
2981 | { | |
2982 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
2983 | if (cached_layer_config[id].layer_en == 0) | |
2984 | continue; | |
2985 | ||
2986 | if (cached_layer_config[id].addr >= mva && | |
2987 | cached_layer_config[id].addr < (mva+size)) | |
2988 | { | |
2989 | pr_info("Warning: m4u required to disable layer id=%d\n", id); | |
2990 | cached_layer_config[id].layer_en = 0; | |
2991 | cached_layer_config[id].isDirty = 1; | |
2992 | dirty = 1; | |
2993 | } | |
2994 | #endif | |
2995 | } | |
2996 | pr_info("Warning: m4u_reclaim_mva_callback_ovl. mva=0x%08X size=0x%X dirty=%d\n", mva, size, dirty); | |
2997 | if (dirty) | |
2998 | { | |
2999 | memset(mtkfb_fbi->screen_base, 0, DISP_GetVRamSize()); | |
3000 | mtkfb_pan_display_impl(&mtkfb_fbi->var, mtkfb_fbi); | |
3001 | } | |
3002 | MMProfileLogEx(MTKFB_MMP_Events.Debug, MMProfileFlagEnd, dirty, 0); | |
3003 | return 0; | |
3004 | } | |
3005 | ||
3006 | #define RGB565_TO_ARGB8888(x) \ | |
3007 | ((((x) & 0x1F) << 3) | \ | |
3008 | (((x) & 0x7E0) << 5) | \ | |
3009 | (((x) & 0xF800) << 8) | \ | |
3010 | (0xFF << 24)) // opaque | |
3011 | ||
3012 | /* Init frame buffer content as 3 R/G/B color bars for debug */ | |
3013 | static int init_framebuffer(struct fb_info *info) | |
3014 | { | |
3015 | void *buffer = info->screen_base + | |
3016 | info->var.yoffset * info->fix.line_length; | |
3017 | ||
3018 | // clean whole frame buffer as black | |
3019 | memset(buffer, 0, info->screen_size); | |
3020 | ||
3021 | return 0; | |
3022 | } | |
3023 | ||
3024 | ||
3025 | /* Free driver resources. Can be called to rollback an aborted initialization | |
3026 | * sequence. | |
3027 | */ | |
3028 | static void mtkfb_free_resources(struct mtkfb_device *fbdev, int state) | |
3029 | { | |
3030 | int r = 0; | |
3031 | ||
3032 | switch (state) { | |
3033 | case MTKFB_ACTIVE: | |
3034 | r = unregister_framebuffer(fbdev->fb_info); | |
3035 | ASSERT(0 == r); | |
3036 | //lint -fallthrough | |
3037 | case 5: | |
3038 | mtkfb_unregister_sysfs(fbdev); | |
3039 | //lint -fallthrough | |
3040 | case 4: | |
3041 | mtkfb_fbinfo_cleanup(fbdev); | |
3042 | //lint -fallthrough | |
3043 | case 3: | |
3044 | DISP_CHECK_RET(DISP_Deinit()); | |
3045 | //lint -fallthrough | |
3046 | case 2: | |
3047 | dma_free_coherent(0, fbdev->fb_size_in_byte, | |
3048 | fbdev->fb_va_base, fbdev->fb_pa_base); | |
3049 | //lint -fallthrough | |
3050 | case 1: | |
3051 | dev_set_drvdata(fbdev->dev, NULL); | |
3052 | framebuffer_release(fbdev->fb_info); | |
3053 | //lint -fallthrough | |
3054 | case 0: | |
3055 | /* nothing to free */ | |
3056 | break; | |
3057 | default: | |
3058 | BUG(); | |
3059 | } | |
3060 | } | |
3061 | ||
3062 | extern char* saved_command_line; | |
3063 | char mtkfb_lcm_name[256] = {0}; | |
3064 | BOOL mtkfb_find_lcm_driver(void) | |
3065 | { | |
3066 | BOOL ret = FALSE; | |
3067 | char *p, *q; | |
3068 | ||
3069 | p = strstr(saved_command_line, "lcm="); | |
3070 | if(p == NULL) | |
3071 | { | |
3072 | // we can't find lcm string in the command line, the uboot should be old version | |
3073 | return DISP_SelectDevice(NULL); | |
3074 | } | |
3075 | ||
3076 | p += 4; | |
3077 | if((p - saved_command_line) > strlen(saved_command_line+1)) | |
3078 | { | |
3079 | ret = FALSE; | |
3080 | goto done; | |
3081 | } | |
3082 | ||
3083 | pr_info("%s, %s\n", __func__, p); | |
3084 | q = p; | |
3085 | while(*q != ' ' && *q != '\0') | |
3086 | q++; | |
3087 | ||
3088 | memset((void*)mtkfb_lcm_name, 0, sizeof(mtkfb_lcm_name)); | |
3089 | strncpy((char*)mtkfb_lcm_name, (const char*)p, (int)(q-p)); | |
3090 | ||
3091 | pr_info("%s, %s\n", __func__, mtkfb_lcm_name); | |
3092 | if(DISP_SelectDevice(mtkfb_lcm_name)) | |
3093 | ret = TRUE; | |
3094 | ||
3095 | done: | |
3096 | return ret; | |
3097 | } | |
3098 | ||
3099 | void disp_get_fb_address(UINT32 *fbVirAddr, UINT32 *fbPhysAddr) | |
3100 | { | |
3101 | struct mtkfb_device *fbdev = (struct mtkfb_device *)mtkfb_fbi->par; | |
3102 | ||
3103 | *fbVirAddr = (UINT32)fbdev->fb_va_base + mtkfb_fbi->var.yoffset * mtkfb_fbi->fix.line_length; | |
3104 | *fbPhysAddr =(UINT32)fbdev->fb_pa_base + mtkfb_fbi->var.yoffset * mtkfb_fbi->fix.line_length; | |
3105 | } | |
3106 | ||
3107 | static int mtkfb_fbinfo_modify(struct fb_info *info) | |
3108 | { | |
3109 | struct fb_var_screeninfo var; | |
3110 | int r = 0; | |
3111 | ||
3112 | memcpy(&var, &(info->var), sizeof(var)); | |
3113 | var.activate = FB_ACTIVATE_NOW; | |
3114 | var.bits_per_pixel = 32; | |
3115 | var.transp.offset = 24; | |
3116 | var.transp.length = 8; | |
3117 | var.red.offset = 16; var.red.length = 8; | |
3118 | var.green.offset = 8; var.green.length = 8; | |
3119 | var.blue.offset = 0; var.blue.length = 8; | |
3120 | var.yoffset = var.yres; | |
3121 | ||
3122 | r = mtkfb_check_var(&var, info); | |
3123 | if (r != 0) | |
3124 | PRNERR("failed to mtkfb_check_var\n"); | |
3125 | ||
3126 | info->var = var; | |
3127 | ||
3128 | r = mtkfb_set_par(info); | |
3129 | if (r != 0) | |
3130 | PRNERR("failed to mtkfb_set_par\n"); | |
3131 | ||
3132 | return r; | |
3133 | } | |
3134 | ||
3135 | static void mtkfb_fb_565_to_8888(struct fb_info *fb_info) | |
3136 | { | |
3137 | unsigned int xres = fb_info->var.xres; | |
3138 | unsigned int yres = fb_info->var.yres; | |
3139 | unsigned int x_virtual = ALIGN_TO(xres,disphal_get_fb_alignment()); | |
3140 | ||
3141 | unsigned int fbsize = x_virtual * yres * 2; | |
3142 | ||
3143 | unsigned short *s = (unsigned short*) fb_info->screen_base; | |
3144 | unsigned int *d = (unsigned int*) (fb_info->screen_base + fbsize * 2); | |
3145 | unsigned short src_rgb565 = 0; | |
3146 | int j = 0; | |
3147 | int k = 0; | |
3148 | int wait_ret = 0; | |
3149 | ||
3150 | // return; //fix battery disappearing | |
3151 | ||
3152 | PRNERR("mtkfb_fb_565_to_8888 xres=%d yres=%d fbsize=0x%X x_virtual=%d s=0x%08X d=0x%08X\n", | |
3153 | xres, yres, fbsize, x_virtual, s, d); | |
3154 | //printf("[boot_logo_updater]normal\n"); | |
3155 | for (j = 0; j < yres; ++ j){ | |
3156 | for(k = 0; k < xres; ++ k) | |
3157 | { | |
3158 | src_rgb565 = *s++; | |
3159 | *d++ = RGB565_TO_ARGB8888(src_rgb565); | |
3160 | } | |
3161 | d += (ALIGN_TO(xres, MTK_FB_ALIGNMENT)-xres); | |
3162 | #if 0 | |
3163 | for(k = xres; k < x_virtual; ++ k){ | |
3164 | *d++ = 0xFFFFFFFF; | |
3165 | *s++; | |
3166 | } | |
3167 | #endif | |
3168 | s += (ALIGN_TO(xres, disphal_get_fb_alignment()) - xres); | |
3169 | } | |
3170 | //printf("[boot_logo_updater] loop copy color over\n"); | |
3171 | ||
3172 | mtkfb_fbinfo_modify(fb_info); | |
3173 | wait_ret = wait_event_interruptible_timeout(reg_update_wq, atomic_read(&OverlaySettingApplied), HZ/10); | |
3174 | MTKFB_LOG("[WaitQ] wait_event_interruptible() ret = %d, %d\n", wait_ret, __LINE__); | |
3175 | ||
3176 | s = (unsigned short *)fb_info->screen_base; | |
3177 | d = (unsigned int *) (fb_info->screen_base + fbsize * 2); | |
3178 | memcpy(s,d,fbsize*2); | |
3179 | } | |
3180 | ||
3181 | ||
3182 | /* Called by LDM binding to probe and attach a new device. | |
3183 | * Initialization sequence: | |
3184 | * 1. allocate system fb_info structure | |
3185 | * select panel type according to machine type | |
3186 | * 2. init LCD panel | |
3187 | * 3. init LCD controller and LCD DMA | |
3188 | * 4. init system fb_info structure | |
3189 | * 5. init gfx DMA | |
3190 | * 6. enable LCD panel | |
3191 | * start LCD frame transfer | |
3192 | * 7. register system fb_info structure | |
3193 | */ | |
3194 | static int mtkfb_probe(struct device *dev) | |
3195 | { | |
3196 | struct platform_device *pdev; | |
3197 | struct mtkfb_device *fbdev = NULL; | |
3198 | struct fb_info *fbi; | |
3199 | int init_state; | |
3200 | int r = 0; | |
3201 | char *p = NULL; | |
3202 | MSG_FUNC_ENTER(); | |
3203 | ||
3204 | ||
3205 | if(get_boot_mode() == META_BOOT || get_boot_mode() == FACTORY_BOOT | |
3206 | || get_boot_mode() == ADVMETA_BOOT || get_boot_mode() == RECOVERY_BOOT) | |
3207 | first_update = false; | |
3208 | ||
3209 | MTKFB_MSG("%s, %s\n", __func__, saved_command_line); | |
3210 | p = strstr(saved_command_line, "fps="); | |
3211 | if(p == NULL){ | |
3212 | lcd_fps = 6000; | |
3213 | pr_info("[FB driver]can not get fps from uboot\n"); | |
3214 | } | |
3215 | else{ | |
3216 | p += 4; | |
3217 | lcd_fps = simple_strtol(p, NULL, 10); | |
3218 | if(0 == lcd_fps) lcd_fps = 6000; | |
3219 | } | |
3220 | ||
3221 | if(DISP_IsContextInited() == FALSE) | |
3222 | { | |
3223 | if(mtkfb_find_lcm_driver()) | |
3224 | { | |
3225 | pr_info("%s, we have found the lcm - %s\n", __func__, mtkfb_lcm_name); | |
3226 | ||
3227 | is_lcm_inited = TRUE; | |
3228 | } | |
3229 | else if(DISP_DetectDevice() != DISP_STATUS_OK) | |
3230 | { | |
3231 | pr_info("[mtkfb] detect device fail, maybe caused by the two reasons below:\n"); | |
3232 | pr_info("\t\t1.no lcm connected\n"); | |
3233 | pr_info("\t\t2.we can't support this lcm\n"); | |
3234 | } | |
3235 | } | |
3236 | ||
3237 | MTK_FB_XRES = DISP_GetScreenWidth(); | |
3238 | MTK_FB_YRES = DISP_GetScreenHeight(); | |
3239 | fb_xres_update = MTK_FB_XRES; | |
3240 | fb_yres_update = MTK_FB_YRES; | |
3241 | ||
3242 | MTKFB_MSG("[MTKFB] XRES=%d, YRES=%d\n", MTK_FB_XRES, MTK_FB_YRES); | |
3243 | ||
3244 | MTK_FB_BPP = DISP_GetScreenBpp(); | |
3245 | MTK_FB_PAGES = DISP_GetPages(); | |
3246 | ||
3247 | ||
3248 | init_waitqueue_head(&screen_update_wq); | |
3249 | ||
3250 | if(DISP_EsdRecoverCapbility()) | |
3251 | { | |
3252 | esd_recovery_task = kthread_create( | |
3253 | esd_recovery_kthread, NULL, "esd_recovery_kthread"); | |
3254 | ||
3255 | if (IS_ERR(esd_recovery_task)) { | |
3256 | MTKFB_LOG("ESD recovery task create fail\n"); | |
3257 | } | |
3258 | else { | |
3259 | wake_up_process(esd_recovery_task); | |
3260 | } | |
3261 | } | |
3262 | init_state = 0; | |
3263 | ||
3264 | pdev = to_platform_device(dev); | |
3265 | if (pdev->num_resources != 1) { | |
3266 | PRNERR("probed for an unknown device\n"); | |
3267 | r = -ENODEV; | |
3268 | goto cleanup; | |
3269 | } | |
3270 | ||
3271 | fbi = framebuffer_alloc(sizeof(struct mtkfb_device), dev); | |
3272 | if (!fbi) { | |
3273 | PRNERR("unable to allocate memory for device info\n"); | |
3274 | r = -ENOMEM; | |
3275 | goto cleanup; | |
3276 | } | |
3277 | mtkfb_fbi = fbi; | |
3278 | ||
3279 | fbdev = (struct mtkfb_device *)fbi->par; | |
3280 | fbdev->fb_info = fbi; | |
3281 | fbdev->dev = dev; | |
3282 | ||
3283 | fbdev->layer_format = (MTK_FB_FORMAT*)vmalloc(sizeof(MTK_FB_FORMAT) * HW_OVERLAY_COUNT); | |
3284 | if(!fbdev->layer_format){ | |
3285 | printk("[mtkfb.c FB driver] vmalloc failed, %d\n", __LINE__); | |
3286 | r = -ENOMEM; | |
3287 | goto cleanup; | |
3288 | } | |
3289 | memset(fbdev->layer_format, 0, sizeof(MTK_FB_FORMAT) * HW_OVERLAY_COUNT); | |
3290 | ||
3291 | dev_set_drvdata(dev, fbdev); | |
3292 | ||
3293 | init_state++; // 1 | |
3294 | ||
3295 | /* Allocate and initialize video frame buffer */ | |
3296 | ||
3297 | fbdev->fb_size_in_byte = MTK_FB_SIZEV; | |
3298 | { | |
3299 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
3300 | ASSERT(DISP_GetVRamSize() <= (res->end - res->start + 1)); | |
3301 | disphal_enable_mmu(mtkfb_enable_mmu); | |
3302 | disphal_allocate_fb(res, &fbdev->fb_pa_base, (unsigned int*)&fbdev->fb_va_base, &fb_pa); | |
3303 | } | |
3304 | ||
3305 | MTKFB_MSG("[FB Driver] fbdev->fb_pa_base = %x, fbdev->fb_va_base = %x\n", fbdev->fb_pa_base, (unsigned int)(fbdev->fb_va_base)); | |
3306 | ||
3307 | if (!fbdev->fb_va_base) { | |
3308 | PRNERR("unable to allocate memory for frame buffer\n"); | |
3309 | r = -ENOMEM; | |
3310 | goto cleanup; | |
3311 | } | |
3312 | init_state++; // 2 | |
3313 | ||
3314 | /* Initialize Display Driver PDD Layer */ | |
3315 | if (DISP_STATUS_OK != DISP_Init((DWORD)fbdev->fb_va_base, | |
3316 | (DWORD)fb_pa, | |
3317 | is_lcm_inited)) | |
3318 | { | |
3319 | r = -1; | |
3320 | goto cleanup; | |
3321 | } | |
3322 | ||
3323 | init_state++; // 3 | |
3324 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3325 | disp_ovl_engine_init(); | |
3326 | ||
3327 | Disp_Ovl_Engine_GetInstance(&mtkfb_instance,COUPLE_MODE); | |
3328 | if (0xFF == mtkfb_instance) | |
3329 | { | |
3330 | PRNERR("allocate overlay engine fail \n"); | |
3331 | goto cleanup; | |
3332 | } | |
3333 | ||
3334 | disp_ovl_engine_indirect_link_overlay(fbdev->fb_va_base, fbdev->fb_pa_base); | |
3335 | #endif //defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3336 | ||
3337 | /* Android native fence support */ | |
3338 | fbdev->update_ovls_wq = alloc_workqueue("mtkfb_ovls_wq", | |
3339 | WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | |
3340 | ||
3341 | if (!fbdev->update_ovls_wq) { | |
3342 | dev_err(dev, "failed to create update_ovls_wq\n"); | |
3343 | return -ENODEV; | |
3344 | } | |
3345 | mutex_init(&fbdev->timeline_lock); | |
3346 | fbdev->timeline = sw_sync_timeline_create("mtkfb"); | |
3347 | fbdev->timeline_max = 0; | |
3348 | INIT_LIST_HEAD(&fbdev->pending_configs); | |
3349 | fbdev->ion_client = ion_client_create(g_ion_device, "mtkfb"); | |
3350 | if (IS_ERR(fbdev->ion_client)) { | |
3351 | dev_err(dev, "failed to create ion client\n"); | |
3352 | return -ENODEV; | |
3353 | } | |
3354 | ||
3355 | /* Register to system */ | |
3356 | ||
3357 | r = mtkfb_fbinfo_init(fbi); | |
3358 | if (r) | |
3359 | goto cleanup; | |
3360 | init_state++; // 4 | |
3361 | ||
3362 | r = mtkfb_register_sysfs(fbdev); | |
3363 | if (r) | |
3364 | goto cleanup; | |
3365 | init_state++; // 5 | |
3366 | ||
3367 | r = register_framebuffer(fbi); | |
3368 | if (r != 0) { | |
3369 | PRNERR("register_framebuffer failed\n"); | |
3370 | goto cleanup; | |
3371 | } | |
3372 | ||
3373 | fbdev->state = MTKFB_ACTIVE; | |
3374 | ||
3375 | /********************************************/ | |
3376 | ||
3377 | mtkfb_fb_565_to_8888(fbi); | |
3378 | ||
3379 | /********************************************/ | |
3380 | MSG(INFO, "MTK framebuffer initialized vram=%lu\n", fbdev->fb_size_in_byte); | |
3381 | ||
3382 | MSG_FUNC_LEAVE(); | |
3383 | return 0; | |
3384 | ||
3385 | cleanup: | |
3386 | mtkfb_free_resources(fbdev, init_state); | |
3387 | ||
3388 | MSG_FUNC_LEAVE(); | |
3389 | return r; | |
3390 | } | |
3391 | ||
3392 | /* Called when the device is being detached from the driver */ | |
3393 | static int mtkfb_remove(struct device *dev) | |
3394 | { | |
3395 | struct mtkfb_device *fbdev = dev_get_drvdata(dev); | |
3396 | enum mtkfb_state saved_state = fbdev->state; | |
3397 | ||
3398 | MSG_FUNC_ENTER(); | |
3399 | /* FIXME: wait till completion of pending events */ | |
3400 | ||
3401 | fbdev->state = MTKFB_DISABLED; | |
3402 | mtkfb_free_resources(fbdev, saved_state); | |
3403 | ||
3404 | MSG_FUNC_LEAVE(); | |
3405 | return 0; | |
3406 | } | |
3407 | ||
3408 | /* PM suspend */ | |
3409 | static int mtkfb_suspend(struct device *pdev, pm_message_t mesg) | |
3410 | { | |
3411 | NOT_REFERENCED(pdev); | |
3412 | MSG_FUNC_ENTER(); | |
3413 | MTKFB_LOG("[FB Driver] mtkfb_suspend(): 0x%x\n", mesg.event); | |
3414 | MSG_FUNC_LEAVE(); | |
3415 | return 0; | |
3416 | } | |
3417 | bool mtkfb_is_suspend(void) | |
3418 | { | |
3419 | return is_early_suspended; | |
3420 | } | |
3421 | ||
3422 | EXPORT_SYMBOL(mtkfb_is_suspend); | |
3423 | ||
3424 | static void mtkfb_shutdown(struct device *pdev) | |
3425 | { | |
3426 | MTKFB_LOG("[FB Driver] mtkfb_shutdown()\n"); | |
3427 | mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, LED_OFF); | |
3428 | if (!lcd_fps) | |
3429 | msleep(30); | |
3430 | else | |
3431 | msleep(2*100000/lcd_fps); // Delay 2 frames. | |
3432 | ||
3433 | if(is_early_suspended){ | |
3434 | MTKFB_LOG("mtkfb has been power off\n"); | |
3435 | return; | |
3436 | } | |
3437 | ||
3438 | if (down_interruptible(&sem_early_suspend)) { | |
3439 | pr_info("[FB Driver] can't get semaphore in mtkfb_shutdown()\n"); | |
3440 | return; | |
3441 | } | |
3442 | sem_early_suspend_cnt--; | |
3443 | ||
3444 | is_early_suspended = TRUE; | |
4b9e9796 S |
3445 | |
3446 | /* [FIXBUG]-Mod-BEGIN by TCTSZ.leo.guo, PR#1000254 2015/05/18, Fix FB suspend/resume DSI cause recovery reboot failed issue*/ | |
6fa3eb70 | 3447 | DISP_PrepareSuspend(); |
4b9e9796 S |
3448 | if(wait_event_interruptible_timeout(_dsi_wait_vm_done_queue, !_IsEngineBusy(), HZ/10) == 0) |
3449 | pr_err("[FB Driver] Wait disp finished timeout in early_suspend\n"); | |
3450 | /* [FIXBUG]-Mod-END by TCTSZ.leo.guo, 2015/05/18*/ | |
6fa3eb70 | 3451 | |
6fa3eb70 S |
3452 | DISP_CHECK_RET(DISP_PanelEnable(FALSE)); |
3453 | DISP_CHECK_RET(DISP_PowerEnable(FALSE)); | |
3454 | ||
3455 | DISP_CHECK_RET(DISP_PauseVsync(TRUE)); | |
3456 | sem_early_suspend_cnt++; | |
3457 | up(&sem_early_suspend); | |
3458 | ||
3459 | MTKFB_LOG("[FB Driver] leave mtkfb_shutdown\n"); | |
3460 | } | |
3461 | ||
3462 | void mtkfb_clear_lcm(void) | |
3463 | { | |
3464 | int i; | |
3465 | unsigned int layer_status[DDP_OVL_LAYER_MUN]={0}; | |
3466 | mutex_lock(&OverlaySettingMutex); | |
3467 | for(i=0;i<DDP_OVL_LAYER_MUN;i++) | |
3468 | { | |
3469 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3470 | // TODO save status | |
3471 | { | |
3472 | struct fb_overlay_layer layer= {0}; | |
3473 | ||
3474 | layer_status[i] = disp_ovl_engine.Instance[mtkfb_instance].cached_layer_config[i].layer_en; | |
3475 | layer.layer_id = i; | |
3476 | Disp_Ovl_Engine_Get_layer_info(mtkfb_instance, &layer); | |
3477 | layer.layer_enable = 0; | |
3478 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layer); | |
3479 | ||
3480 | } | |
3481 | #else | |
3482 | layer_status[i] = cached_layer_config[i].layer_en; | |
3483 | cached_layer_config[i].layer_en = 0; | |
3484 | cached_layer_config[i].isDirty = 1; | |
3485 | #endif | |
3486 | } | |
3487 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3488 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
3489 | atomic_set(&OverlaySettingApplied, 0); | |
3490 | #endif | |
3491 | mutex_unlock(&OverlaySettingMutex); | |
3492 | ||
3493 | DISP_CHECK_RET(DISP_UpdateScreen(0, 0, fb_xres_update, fb_yres_update)); | |
3494 | DISP_CHECK_RET(DISP_UpdateScreen(0, 0, fb_xres_update, fb_yres_update)); | |
3495 | ||
3496 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3497 | Disp_Ovl_Engine_Wait_Overlay_Complete(mtkfb_instance, 1000); | |
3498 | #endif | |
3499 | if (!lcd_fps) | |
3500 | msleep(60); | |
3501 | else | |
3502 | msleep(400000/lcd_fps); | |
3503 | DISP_WaitForLCDNotBusy(); | |
3504 | ||
3505 | mutex_lock(&OverlaySettingMutex); | |
3506 | for(i=0;i<DDP_OVL_LAYER_MUN;i++) | |
3507 | { | |
3508 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3509 | { | |
3510 | struct fb_overlay_layer layer= {0}; | |
3511 | layer.layer_id = i; | |
3512 | Disp_Ovl_Engine_Get_layer_info(mtkfb_instance, &layer); | |
3513 | layer.layer_enable = layer_status[i]; | |
3514 | Disp_Ovl_Engine_Set_layer_info(mtkfb_instance, &layer); | |
3515 | } | |
3516 | #else | |
3517 | cached_layer_config[i].layer_en = layer_status[i]; | |
3518 | cached_layer_config[i].isDirty = 1; | |
3519 | #endif | |
3520 | } | |
3521 | #if !defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3522 | atomic_set(&OverlaySettingDirtyFlag, 1); | |
3523 | atomic_set(&OverlaySettingApplied, 0); | |
3524 | #endif | |
3525 | mutex_unlock(&OverlaySettingMutex); | |
3526 | } | |
3527 | ||
3528 | ||
3529 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
3530 | static void mtkfb_early_suspend(struct early_suspend *h) | |
3531 | { | |
3532 | MSG_FUNC_ENTER(); | |
3533 | ||
3534 | pr_info("[FB Driver] enter early_suspend\n"); | |
3535 | ||
3536 | ||
3537 | mutex_lock(&ScreenCaptureMutex); | |
3538 | ||
3539 | ||
3540 | mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, LED_OFF); | |
3541 | if (down_interruptible(&sem_early_suspend)) { | |
3542 | pr_info("[FB Driver] can't get semaphore in mtkfb_early_suspend()\n"); | |
3543 | mutex_unlock(&ScreenCaptureMutex); | |
3544 | return; | |
3545 | } | |
3546 | ||
3547 | sem_early_suspend_cnt--; | |
3548 | ||
3549 | if(is_early_suspended){ | |
3550 | is_early_suspended = TRUE; | |
3551 | sem_early_suspend_cnt++; | |
3552 | up(&sem_early_suspend); | |
3553 | MTKFB_LOG("[FB driver] has been suspended\n"); | |
3554 | mutex_unlock(&ScreenCaptureMutex); | |
3555 | return; | |
3556 | } | |
3557 | ||
3558 | MMProfileLog(MTKFB_MMP_Events.EarlySuspend, MMProfileFlagStart); | |
3559 | is_early_suspended = TRUE; | |
3560 | ||
3561 | if (!lcd_fps) | |
3562 | msleep(30); | |
3563 | else | |
3564 | msleep(2*100000/lcd_fps); // Delay 2 frames. | |
3565 | ||
3566 | DISP_PrepareSuspend(); | |
3567 | ||
3568 | // Wait for disp finished. | |
3569 | if (wait_event_interruptible_timeout(_dsi_wait_vm_done_queue, !_IsEngineBusy(), HZ/10) == 0) | |
3570 | { | |
3571 | pr_info("[FB Driver] Wait disp finished timeout in early_suspend\n"); | |
3572 | } | |
3573 | DISP_CHECK_RET(DISP_PanelEnable(FALSE)); | |
3574 | DISP_CHECK_RET(DISP_PowerEnable(FALSE)); | |
3575 | DISP_CHECK_RET(DISP_PauseVsync(TRUE)); | |
3576 | ||
3577 | disp_path_clock_off("mtkfb"); | |
3578 | ||
3579 | sem_early_suspend_cnt++; | |
3580 | up(&sem_early_suspend); | |
3581 | mutex_unlock(&ScreenCaptureMutex); | |
3582 | ||
3583 | /* Here we should flush composition workqueue but there's no | |
3584 | * clean and easy way to get the device handle. Because early suspend | |
3585 | * struct is not a member of fbdev, and global variables are used instead, | |
3586 | * we can't just use container_of ... | |
3587 | * As we flush in blank/POWEROFF IOCTL from HWC, this is not a practical issue. | |
3588 | * | |
3589 | * flush_workqueue(((struct mtkfb_device *)dev)->update_ovls_wq); | |
3590 | */ | |
3591 | ||
3592 | pr_info("[FB Driver] leave early_suspend\n"); | |
3593 | ||
3594 | MSG_FUNC_LEAVE(); | |
3595 | } | |
3596 | #endif | |
3597 | ||
3598 | /* PM resume */ | |
3599 | static int mtkfb_resume(struct device *pdev) | |
3600 | { | |
3601 | NOT_REFERENCED(pdev); | |
3602 | MSG_FUNC_ENTER(); | |
3603 | MTKFB_LOG("[FB Driver] mtkfb_resume()\n"); | |
3604 | MSG_FUNC_LEAVE(); | |
3605 | return 0; | |
3606 | } | |
3607 | ||
3608 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
3609 | static void mtkfb_late_resume(struct early_suspend *h) | |
3610 | { | |
3611 | MSG_FUNC_ENTER(); | |
3612 | ||
3613 | pr_info("[FB Driver] enter late_resume\n"); | |
3614 | ||
3615 | mutex_lock(&ScreenCaptureMutex); | |
3616 | if (down_interruptible(&sem_early_suspend)) { | |
3617 | pr_info("[FB Driver] can't get semaphore in mtkfb_late_resume()\n"); | |
3618 | mutex_unlock(&ScreenCaptureMutex); | |
3619 | return; | |
3620 | } | |
3621 | sem_early_suspend_cnt--; | |
3622 | if(!is_early_suspended){ | |
3623 | is_early_suspended = false; | |
3624 | sem_early_suspend_cnt++; | |
3625 | up(&sem_early_suspend); | |
3626 | MTKFB_LOG("[FB driver] has been resumed\n"); | |
3627 | mutex_unlock(&ScreenCaptureMutex); | |
3628 | return; | |
3629 | } | |
3630 | ||
3631 | MMProfileLog(MTKFB_MMP_Events.EarlySuspend, MMProfileFlagEnd); | |
3632 | if (is_ipoh_bootup) | |
3633 | { | |
3634 | atomic_set(&OverlaySettingDirtyFlag, 0); | |
3635 | disp_path_clock_on("ipoh_mtkfb"); | |
3636 | } | |
3637 | else | |
3638 | disp_path_clock_on("mtkfb"); | |
3639 | pr_info("[FB LR] 1\n"); | |
3640 | DISP_CHECK_RET(DISP_PauseVsync(FALSE)); | |
3641 | pr_info("[FB LR] 2\n"); | |
3642 | DISP_CHECK_RET(DISP_PowerEnable(TRUE)); | |
3643 | pr_info("[FB LR] 3\n"); | |
3644 | DISP_CHECK_RET(DISP_PanelEnable(TRUE)); | |
3645 | pr_info("[FB LR] 4\n"); | |
3646 | ||
3647 | is_early_suspended = FALSE; | |
3648 | ||
3649 | if (is_ipoh_bootup) | |
3650 | { | |
3651 | DISP_StartConfigUpdate(); | |
3652 | is_ipoh_bootup =false; | |
3653 | } | |
3654 | else | |
3655 | { | |
3656 | mtkfb_clear_lcm(); | |
3657 | } | |
3658 | ||
3659 | sem_early_suspend_cnt++; | |
3660 | up(&sem_early_suspend); | |
3661 | mutex_unlock(&ScreenCaptureMutex); | |
3662 | ||
3663 | if(BL_set_level_resume){ | |
3664 | mtkfb_set_backlight_level(BL_level); | |
3665 | BL_set_level_resume = FALSE; | |
3666 | } | |
3667 | #if defined(MTK_OVERLAY_ENGINE_SUPPORT) | |
3668 | #ifdef CONFIG_MTK_LEDS | |
3669 | if (!disp_ovl_engine.bCouple) | |
3670 | mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, LED_HALF); | |
3671 | #endif | |
3672 | #endif | |
3673 | pr_info("[FB Driver] leave late_resume\n"); | |
3674 | ||
3675 | MSG_FUNC_LEAVE(); | |
3676 | } | |
3677 | #endif | |
3678 | ||
3679 | /*---------------------------------------------------------------------------*/ | |
3680 | #ifdef CONFIG_PM | |
3681 | /*---------------------------------------------------------------------------*/ | |
3682 | int mtkfb_pm_suspend(struct device *device) | |
3683 | { | |
3684 | //pr_debug("calling %s()\n", __func__); | |
3685 | ||
3686 | struct platform_device *pdev = to_platform_device(device); | |
3687 | BUG_ON(pdev == NULL); | |
3688 | ||
3689 | return mtkfb_suspend((struct device *)pdev, PMSG_SUSPEND); | |
3690 | } | |
3691 | ||
3692 | int mtkfb_pm_resume(struct device *device) | |
3693 | { | |
3694 | //pr_debug("calling %s()\n", __func__); | |
3695 | ||
3696 | struct platform_device *pdev = to_platform_device(device); | |
3697 | BUG_ON(pdev == NULL); | |
3698 | ||
3699 | return mtkfb_resume((struct device *)pdev); | |
3700 | } | |
3701 | ||
3702 | #ifdef DEFAULT_MMP_ENABLE | |
3703 | void MMProfileStart(int start); | |
3704 | #endif | |
3705 | int mtkfb_pm_restore_noirq(struct device *device) | |
3706 | { | |
3707 | ||
3708 | #ifdef DEFAULT_MMP_ENABLE | |
3709 | MMProfileStart(0); | |
3710 | MMProfileStart(1); | |
3711 | #endif | |
3712 | ||
3713 | disphal_pm_restore_noirq(device); | |
3714 | ||
3715 | is_ipoh_bootup = true; | |
3716 | return 0; | |
3717 | ||
3718 | } | |
3719 | /*---------------------------------------------------------------------------*/ | |
3720 | #else /*CONFIG_PM*/ | |
3721 | /*---------------------------------------------------------------------------*/ | |
3722 | #define mtkfb_pm_suspend NULL | |
3723 | #define mtkfb_pm_resume NULL | |
3724 | #define mtkfb_pm_restore_noirq NULL | |
3725 | /*---------------------------------------------------------------------------*/ | |
3726 | #endif /*CONFIG_PM*/ | |
3727 | /*---------------------------------------------------------------------------*/ | |
3728 | struct dev_pm_ops mtkfb_pm_ops = { | |
3729 | .suspend = mtkfb_pm_suspend, | |
3730 | .resume = mtkfb_pm_resume, | |
3731 | .freeze = mtkfb_pm_suspend, | |
3732 | .thaw = mtkfb_pm_resume, | |
3733 | .poweroff = mtkfb_pm_suspend, | |
3734 | .restore = mtkfb_pm_resume, | |
3735 | .restore_noirq = mtkfb_pm_restore_noirq, | |
3736 | }; | |
3737 | ||
3738 | static struct platform_driver mtkfb_driver = | |
3739 | { | |
3740 | .driver = { | |
3741 | .name = MTKFB_DRIVER, | |
3742 | #ifdef CONFIG_PM | |
3743 | .pm = &mtkfb_pm_ops, | |
3744 | #endif | |
3745 | .bus = &platform_bus_type, | |
3746 | .probe = mtkfb_probe, | |
3747 | .remove = mtkfb_remove, | |
3748 | .suspend = mtkfb_suspend, | |
3749 | .resume = mtkfb_resume, | |
3750 | .shutdown = mtkfb_shutdown, | |
3751 | }, | |
3752 | }; | |
3753 | ||
3754 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
3755 | static struct early_suspend mtkfb_early_suspend_handler = | |
3756 | { | |
3757 | .level = EARLY_SUSPEND_LEVEL_DISABLE_FB, | |
3758 | .suspend = mtkfb_early_suspend, | |
3759 | .resume = mtkfb_late_resume, | |
3760 | }; | |
3761 | #endif | |
3762 | ||
3763 | #ifdef DEFAULT_MMP_ENABLE | |
3764 | void MMProfileEnable(int enable); | |
3765 | void MMProfileStart(int start); | |
3766 | void init_mtkfb_mmp_events(void); | |
3767 | void init_ddp_mmp_events(void); | |
3768 | #endif | |
3769 | ||
3770 | /* Register both the driver and the device */ | |
3771 | int __init mtkfb_init(void) | |
3772 | { | |
3773 | int r = 0; | |
3774 | ||
3775 | MSG_FUNC_ENTER(); | |
3776 | ||
3777 | #ifdef DEFAULT_MMP_ENABLE | |
3778 | MMProfileEnable(1); | |
3779 | init_mtkfb_mmp_events(); | |
3780 | init_ddp_mmp_events(); | |
3781 | MMProfileStart(0); | |
3782 | MMProfileStart(1); | |
3783 | #endif | |
3784 | ||
3785 | /* Register the driver with LDM */ | |
3786 | ||
3787 | if (platform_driver_register(&mtkfb_driver)) { | |
3788 | PRNERR("failed to register mtkfb driver\n"); | |
3789 | r = -ENODEV; | |
3790 | goto exit; | |
3791 | } | |
3792 | ||
3793 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
3794 | register_early_suspend(&mtkfb_early_suspend_handler); | |
3795 | #endif | |
3796 | ||
3797 | DBG_Init(); | |
3798 | ||
3799 | exit: | |
3800 | MSG_FUNC_LEAVE(); | |
3801 | return r; | |
3802 | } | |
3803 | ||
3804 | ||
3805 | static void __exit mtkfb_cleanup(void) | |
3806 | { | |
3807 | MSG_FUNC_ENTER(); | |
3808 | ||
3809 | platform_driver_unregister(&mtkfb_driver); | |
3810 | ||
3811 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
3812 | unregister_early_suspend(&mtkfb_early_suspend_handler); | |
3813 | #endif | |
3814 | ||
3815 | kthread_stop(screen_update_task); | |
3816 | if(esd_recovery_task) | |
3817 | kthread_stop(esd_recovery_task); | |
3818 | ||
3819 | DBG_Deinit(); | |
3820 | ||
3821 | MSG_FUNC_LEAVE(); | |
3822 | } | |
3823 | ||
3824 | late_initcall(mtkfb_init); | |
3825 | module_exit(mtkfb_cleanup); | |
3826 | ||
3827 | MODULE_DESCRIPTION("MEDIATEK framebuffer driver"); | |
3828 | MODULE_AUTHOR("Zaikuo Wang <zaikuo.wang@mediatek.com>"); | |
3829 | MODULE_LICENSE("GPL"); |