rk fb: add rk_fb_trsm_ops
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rk_fb.c
1 /*
2  * drivers/video/rockchip/rk_fb.c
3  *
4  * Copyright (C) ROCKCHIP, Inc.
5  *Author:yxj<yxj@rock-chips.com>
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
20 #include <linux/mm.h>
21 #include <linux/slab.h>
22 #include <linux/delay.h>
23 #include <linux/device.h>
24 #include <linux/kthread.h>
25 #include <linux/fb.h>
26 #include <linux/init.h>
27 #include <asm/div64.h>
28 #include <linux/uaccess.h>
29 #include <linux/rk_fb.h>
30 #include <linux/linux_logo.h>
31 #include <linux/dma-mapping.h>
32
33
34 #if defined(CONFIG_RK_HDMI)
35 #include "hdmi/rk_hdmi.h"
36 #endif
37
38 #ifdef CONFIG_OF
39 #include <linux/of.h>
40 #include <linux/of_gpio.h>
41 #include <video/of_display_timing.h>
42 #include <video/display_timing.h>
43 #include <dt-bindings/rkfb/rk_fb.h>
44 #endif
45
46 #if defined(CONFIG_ION_ROCKCHIP)
47 #include <linux/rockchip_ion.h>
48 #endif
49
50
51 static int hdmi_switch_complete;
52 static struct platform_device *fb_pdev;
53 struct list_head saved_list;
54
55 #if defined(CONFIG_FB_MIRRORING)
56 int (*video_data_to_mirroring)(struct fb_info *info, u32 yuv_phy[2]);
57 EXPORT_SYMBOL(video_data_to_mirroring);
58 #endif
59
60
61 static struct rk_fb_trsm_ops *trsm_lvds_ops;
62 static struct rk_fb_trsm_ops *trsm_edp_ops;
63 static struct rk_fb_trsm_ops *trsm_mipi_ops;
64
65 int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
66 {
67         switch (type) {
68         case SCREEN_RGB:
69         case SCREEN_LVDS:
70         case SCREEN_DUAL_LVDS:
71                 trsm_lvds_ops = ops;
72                 break;
73         case SCREEN_EDP:
74                 trsm_edp_ops = ops;
75                 break;
76         case SCREEN_MIPI:
77         case SCREEN_DUAL_MIPI:
78                 trsm_mipi_ops = ops;
79                 break;
80         default:
81                 printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
82                         __func__, type);
83                 break;
84         }
85         return 0;
86 }
87
88 struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
89 {
90         struct rk_fb_trsm_ops *ops;
91         switch (type) {
92         case SCREEN_RGB:
93         case SCREEN_LVDS:
94         case SCREEN_DUAL_LVDS:
95                 ops = trsm_lvds_ops;
96                 break;
97         case SCREEN_EDP:
98                 ops = trsm_edp_ops;
99                 break;
100         case SCREEN_MIPI:
101         case SCREEN_DUAL_MIPI:
102                 ops = trsm_mipi_ops;
103                 break;
104         default:
105                 ops = NULL;
106                 printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
107                         __func__, type);
108                 break;
109         }
110         return ops;
111 }
112
113 int rk_fb_pixel_width(int data_format)
114 {
115         int pixel_width;
116         switch(data_format){
117         case XBGR888:
118         case ABGR888:
119         case ARGB888:
120                 pixel_width = 4*8;
121                 break;
122         case RGB888:
123                 pixel_width = 3*8;
124                 break;
125         case RGB565:
126                 pixel_width = 2*8;
127                 break;
128         case YUV422:
129         case YUV420:
130         case YUV444:
131                 pixel_width = 1*8;
132                 break;
133         default:
134                 return -EINVAL;
135         }
136         return pixel_width;
137 }
138
139 static int rk_fb_data_fmt(int data_format,int bits_per_pixel)
140 {
141         int fb_data_fmt;
142         if(data_format){
143                 switch(data_format){
144                 case HAL_PIXEL_FORMAT_RGBX_8888: 
145                         fb_data_fmt = XBGR888;
146                         break;
147                 case HAL_PIXEL_FORMAT_RGBA_8888:
148                         fb_data_fmt = ABGR888;
149                         break;
150                 case HAL_PIXEL_FORMAT_BGRA_8888: 
151                         fb_data_fmt = ARGB888;
152                         break;
153                 case HAL_PIXEL_FORMAT_RGB_888:
154                         fb_data_fmt = RGB888;
155                         break;
156                 case HAL_PIXEL_FORMAT_RGB_565:
157                         fb_data_fmt = RGB565;
158                         break;
159                 case HAL_PIXEL_FORMAT_YCbCr_422_SP: // yuv422
160                         fb_data_fmt = YUV422;
161                         break;
162                 case HAL_PIXEL_FORMAT_YCrCb_NV12: // YUV420---uvuvuv
163                         fb_data_fmt = YUV420;
164                         break;
165                 case HAL_PIXEL_FORMAT_YCrCb_444: // yuv444
166                         fb_data_fmt = YUV444;
167                         break;
168                 default:
169                         printk("%s:un supported format:0x%x\n",__func__,data_format);
170                     return -EINVAL;
171                 }
172         }else{
173                 switch(bits_per_pixel){
174                 case 32:
175                         fb_data_fmt = ARGB888;
176                         break;
177                 case 16:
178                         fb_data_fmt = RGB565;
179                         break;
180                 default:
181                         break;
182                 }
183         }
184         return fb_data_fmt;
185 }
186
187 /* rk display power control parse from dts
188  *
189 */
190 int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
191 {
192         struct device_node *root  = of_parse_phandle(dev_drv->dev->of_node,
193                                 "power_ctr", 0);
194         struct device_node *child;
195         struct rk_disp_pwr_ctr_list *pwr_ctr;
196         struct list_head *pos;
197         enum of_gpio_flags flags;
198         u32 val = 0;
199         u32 debug = 0;
200         int ret;
201
202         INIT_LIST_HEAD(&dev_drv->pwrlist_head);
203         if (!root) {
204                 dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",dev_drv->id);
205                 return -ENODEV;
206         }
207
208         for_each_child_of_node(root, child) {
209                 pwr_ctr = kmalloc(sizeof(struct rk_disp_pwr_ctr_list), GFP_KERNEL);
210                 strcpy(pwr_ctr->pwr_ctr.name, child->name);
211                 if (!of_property_read_u32(child, "rockchip,power_type", &val)) {
212                         if (val == GPIO) {
213                                 pwr_ctr->pwr_ctr.type = GPIO;
214                                 pwr_ctr->pwr_ctr.gpio = of_get_gpio_flags(child, 0, &flags);
215                                 if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
216                                         dev_err(dev_drv->dev, "%s ivalid gpio\n", child->name);
217                                         return -EINVAL;
218                                 }
219                                 pwr_ctr->pwr_ctr.atv_val = !(flags & OF_GPIO_ACTIVE_LOW);
220                                 ret = gpio_request(pwr_ctr->pwr_ctr.gpio,child->name);
221                                 if (ret) {
222                                         dev_err(dev_drv->dev, "request %s gpio fail:%d\n",
223                                                 child->name,ret);
224                                 }
225
226                         } else {
227                                 pwr_ctr->pwr_ctr.type = REGULATOR;
228
229                         }
230                 };
231                 of_property_read_u32(child, "rockchip,delay", &val);
232                 pwr_ctr->pwr_ctr.delay = val;
233                 list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
234         }
235
236         of_property_read_u32(root, "rockchip,debug", &debug);
237
238         if (debug) {
239                 list_for_each(pos, &dev_drv->pwrlist_head) {
240                         pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list, list);
241                         printk(KERN_INFO "pwr_ctr_name:%s\n"
242                                          "pwr_type:%s\n"
243                                          "gpio:%d\n"
244                                          "atv_val:%d\n"
245                                          "delay:%d\n\n",
246                                          pwr_ctr->pwr_ctr.name,
247                                          (pwr_ctr->pwr_ctr.type == GPIO) ? "gpio" : "regulator",
248                                          pwr_ctr->pwr_ctr.gpio,
249                                          pwr_ctr->pwr_ctr.atv_val,
250                                          pwr_ctr->pwr_ctr.delay);
251                 }
252         }
253
254         return 0;
255
256 }
257
258 int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv)
259 {
260         struct list_head *pos;
261         struct rk_disp_pwr_ctr_list *pwr_ctr_list;
262         struct pwr_ctr *pwr_ctr;
263         if (list_empty(&dev_drv->pwrlist_head))
264                 return 0;
265         list_for_each(pos, &dev_drv->pwrlist_head) {
266                 pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list, list);
267                 pwr_ctr = &pwr_ctr_list->pwr_ctr;
268                 if (pwr_ctr->type == GPIO) {
269                         gpio_direction_output(pwr_ctr->gpio,pwr_ctr->atv_val);
270                         mdelay(pwr_ctr->delay);
271                 }
272         }
273
274         return 0;
275 }
276
277 int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv)
278 {
279         struct list_head *pos;
280         struct rk_disp_pwr_ctr_list *pwr_ctr_list;
281         struct pwr_ctr *pwr_ctr;
282         if (list_empty(&dev_drv->pwrlist_head))
283                 return 0;
284         list_for_each(pos, &dev_drv->pwrlist_head) {
285                 pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list, list);
286                 pwr_ctr = &pwr_ctr_list->pwr_ctr;
287                 if (pwr_ctr->type == GPIO) {
288                         gpio_set_value(pwr_ctr->gpio,pwr_ctr->atv_val);
289                 }
290         }
291
292         return 0;
293 }
294
295 int rk_fb_video_mode_from_timing(const struct display_timing *dt, 
296                                 struct rk_screen *screen)
297 {
298         screen->mode.pixclock = dt->pixelclock.typ;
299         screen->mode.left_margin = dt->hback_porch.typ;
300         screen->mode.right_margin = dt->hfront_porch.typ;
301         screen->mode.xres = dt->hactive.typ;
302         screen->mode.hsync_len = dt->hsync_len.typ;
303         screen->mode.upper_margin = dt->vback_porch.typ;
304         screen->mode.lower_margin = dt->vfront_porch.typ;
305         screen->mode.yres = dt->vactive.typ;
306         screen->mode.vsync_len = dt->vsync_len.typ;
307         screen->type = dt->screen_type;
308         screen->lvds_format = dt->lvds_format;
309         screen->face = dt->face;
310
311         if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
312                 screen->pin_dclk = 1;
313         else
314                 screen->pin_dclk = 0;
315         if(dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
316                 screen->pin_hsync = 1;
317         else
318                 screen->pin_hsync = 0;
319         if(dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
320                 screen->pin_vsync = 1;
321         else
322                 screen->pin_vsync = 0;
323         if(dt->flags & DISPLAY_FLAGS_DE_HIGH)
324                 screen->pin_den = 1;
325         else
326                 screen->pin_den = 0;
327         
328         return 0;
329         
330 }
331
332 int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
333 {
334         struct display_timings *disp_timing;
335         struct display_timing *dt;
336         disp_timing = of_get_display_timings(np);
337         if (!disp_timing) {
338                 pr_err("parse display timing err\n");
339                 return -EINVAL;
340         }
341         dt = display_timings_get(disp_timing, 0);
342         rk_fb_video_mode_from_timing(dt, screen);
343         printk(KERN_DEBUG "dclk:%d\n"
344                          "hactive:%d\n"
345                          "hback_porch:%d\n"
346                          "hfront_porch:%d\n"
347                          "hsync_len:%d\n"
348                          "vactive:%d\n"
349                          "vback_porch:%d\n"
350                          "vfront_porch:%d\n"
351                          "vsync_len:%d\n"
352                          "screen_type:%d\n"
353                          "lvds_format:%d\n"
354                          "face:%d\n",
355                         dt->pixelclock.typ,
356                         dt->hactive.typ,
357                         dt->hback_porch.typ,
358                         dt->hfront_porch.typ,
359                         dt->hsync_len.typ,
360                         dt->vactive.typ,
361                         dt->vback_porch.typ,
362                         dt->vfront_porch.typ,
363                         dt->vsync_len.typ,
364                         dt->screen_type,
365                         dt->lvds_format,
366                         dt->face);
367         return 0;
368
369 }
370
371 int  rk_fb_calc_fps(struct rk_screen * screen, u32 pixclock)
372 {
373         int x, y;
374         unsigned long long hz;
375         if (!screen) {
376                 printk(KERN_ERR "%s:null screen!\n", __func__);
377                 return 0;
378         }
379         x = screen->mode.xres + screen->mode.left_margin + screen->mode.right_margin +
380             screen->mode.hsync_len;
381         y = screen->mode.yres + screen->mode.upper_margin + screen->mode.lower_margin +
382             screen->mode.vsync_len;
383
384         hz = 1000000000000ULL;  /* 1e12 picoseconds per second */
385
386         hz += (x * y) / 2;
387         do_div(hz, x * y);      /* divide by x * y with rounding */
388
389         hz += pixclock / 2;
390         do_div(hz, pixclock);   /* divide by pixclock with rounding */
391
392         return hz;
393 }
394
395 char *get_format_string(enum data_format format, char *fmt)
396 {
397         if (!fmt)
398                 return NULL;
399         switch (format) {
400         case ARGB888:
401                 strcpy(fmt, "ARGB888");
402                 break;
403         case RGB888:
404                 strcpy(fmt, "RGB888");
405                 break;
406         case RGB565:
407                 strcpy(fmt, "RGB565");
408                 break;
409         case YUV420:
410                 strcpy(fmt, "YUV420");
411                 break;
412         case YUV422:
413                 strcpy(fmt, "YUV422");
414                 break;
415         case YUV444:
416                 strcpy(fmt, "YUV444");
417                 break;
418         case XRGB888:
419                 strcpy(fmt, "XRGB888");
420                 break;
421         case XBGR888:
422                 strcpy(fmt, "XBGR888");
423                 break;
424         case ABGR888:
425                 strcpy(fmt, "XBGR888");
426                 break;
427         default:
428                 strcpy(fmt, "invalid");
429                 break;
430         }
431
432         return fmt;
433
434 }
435
436
437
438 /**********************************************************************
439 this is for hdmi
440 name: lcdc device name ,lcdc0 , lcdc1
441 ***********************************************************************/
442 struct rk_lcdc_driver *rk_get_lcdc_drv(char *name)
443 {
444         struct rk_fb *inf =  platform_get_drvdata(fb_pdev);
445         int i = 0;
446         for (i = 0; i < inf->num_lcdc; i++) {
447                 if (!strcmp(inf->lcdc_dev_drv[i]->name, name))
448                         break;
449         }
450         return inf->lcdc_dev_drv[i];
451
452 }
453
454 static struct rk_lcdc_driver *rk_get_prmry_lcdc_drv(void)
455 {
456         struct rk_fb *inf = NULL;
457         struct rk_lcdc_driver *dev_drv = NULL;
458         int i = 0;
459
460         if (likely(fb_pdev))
461                 inf = platform_get_drvdata(fb_pdev);
462         else
463                 return NULL;
464
465         for (i = 0; i < inf->num_lcdc; i++) {
466                 if (inf->lcdc_dev_drv[i]->prop ==  PRMRY) {
467                         dev_drv = inf->lcdc_dev_drv[i];
468                         break;
469                 }
470         }
471
472         return dev_drv;
473 }
474
475
476 int rk_fb_get_prmry_screen_ft(void)
477 {
478         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
479         uint32_t htotal, vtotal, pix_total, ft_us, dclk_mhz;
480
481         if (unlikely(!dev_drv))
482                 return 0;
483
484         dclk_mhz = dev_drv->pixclock/(1000*1000);
485
486         htotal = (dev_drv->cur_screen->mode.upper_margin + dev_drv->cur_screen->mode.lower_margin +
487                 dev_drv->cur_screen->mode.yres + dev_drv->cur_screen->mode.vsync_len);
488         vtotal = (dev_drv->cur_screen->mode.left_margin + dev_drv->cur_screen->mode.right_margin +
489                 dev_drv->cur_screen->mode.xres + dev_drv->cur_screen->mode.hsync_len);
490         pix_total = htotal*vtotal;
491         ft_us = pix_total / dclk_mhz;
492
493         return ft_us;
494 }
495
496 static struct rk_lcdc_driver  *rk_get_extend_lcdc_drv(void)
497 {
498         struct rk_fb *inf = NULL;
499         struct rk_lcdc_driver *dev_drv = NULL;
500         int i = 0;
501
502         if (likely(fb_pdev))
503                 inf = platform_get_drvdata(fb_pdev);
504         else
505                 return NULL;
506
507         for (i = 0; i < inf->num_lcdc; i++) {
508                 if (inf->lcdc_dev_drv[i]->prop == EXTEND) {
509                         dev_drv = inf->lcdc_dev_drv[i];
510                         break;
511                 }
512         }
513
514         return dev_drv;
515 }
516
517
518 u32 rk_fb_get_prmry_screen_pixclock(void)
519 {
520         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
521         return dev_drv->pixclock;
522 }
523
524 int rk_fb_poll_prmry_screen_vblank(void)
525 {
526         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
527         if (likely(dev_drv)) {
528                 if (dev_drv->ops->poll_vblank)
529                         return dev_drv->ops->poll_vblank(dev_drv);
530                 else
531                         return RK_LF_STATUS_NC;
532         } else
533                 return RK_LF_STATUS_NC;
534 }
535
536 bool rk_fb_poll_wait_frame_complete(void)
537 {
538         uint32_t timeout = RK_LF_MAX_TIMEOUT;
539         if (rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_NC)
540                 return false;
541
542         while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FR)  &&  --timeout);
543         while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FC)  &&  --timeout);
544
545         return true;
546 }
547 static int rk_fb_open(struct fb_info *info, int user)
548 {
549         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
550         int win_id;
551
552         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
553         if (dev_drv->win[win_id]->state)
554                 return 0;    /* if this win aready opened ,no need to reopen*/
555         else
556                 dev_drv->ops->open(dev_drv, win_id, 1);
557         return 0;
558 }
559
560 static int  get_extend_fb_id(struct fb_info *info)
561 {
562         int fb_id = 0;
563         char *id = info->fix.id;
564         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
565         if (!strcmp(id, "fb0"))
566                 fb_id = 0;
567         else if (!strcmp(id, "fb1"))
568                 fb_id = 1;
569         else if (!strcmp(id, "fb2") && (dev_drv->lcdc_win_num > 2))
570                 fb_id = 2;
571         return fb_id;
572 }
573
574 static int rk_fb_close(struct fb_info *info, int user)
575 {
576         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
577         struct rk_lcdc_win *win = NULL;
578         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
579         if (win_id >= 0) {
580                 win = dev_drv->win[win_id];
581                 info->fix.smem_start = win->reserved;
582
583                 info->var.xres = dev_drv->screen0->mode.xres;
584                 info->var.yres = dev_drv->screen0->mode.yres;
585                 info->var.grayscale |= (info->var.xres<<8) + (info->var.yres<<20);
586 #if defined(CONFIG_LOGO_LINUX_BMP)
587                 info->var.bits_per_pixel = 32;
588 #else
589                 info->var.bits_per_pixel = 16;
590 #endif
591                 info->fix.line_length  = (info->var.xres)*(info->var.bits_per_pixel>>3);
592                 info->var.xres_virtual = info->var.xres;
593                 info->var.yres_virtual = info->var.yres;
594                 info->var.width =  dev_drv->screen0->width;
595                 info->var.height = dev_drv->screen0->height;
596                 info->var.pixclock = dev_drv->pixclock;
597                 info->var.left_margin = dev_drv->screen0->mode.left_margin;
598                 info->var.right_margin = dev_drv->screen0->mode.right_margin;
599                 info->var.upper_margin = dev_drv->screen0->mode.upper_margin;
600                 info->var.lower_margin = dev_drv->screen0->mode.lower_margin;
601                 info->var.vsync_len = dev_drv->screen0->mode.vsync_len;
602                 info->var.hsync_len = dev_drv->screen0->mode.hsync_len;
603         }
604
605         return 0;
606 }
607
608
609 #if defined(CONFIG_RK29_IPP)
610 static int get_ipp_format(int fmt)
611 {
612         int ipp_fmt = IPP_XRGB_8888;
613         switch (fmt) {
614         case HAL_PIXEL_FORMAT_RGBX_8888:
615         case HAL_PIXEL_FORMAT_RGBA_8888:
616         case HAL_PIXEL_FORMAT_BGRA_8888:
617         case HAL_PIXEL_FORMAT_RGB_888:
618                 ipp_fmt = IPP_XRGB_8888;
619                 break;
620         case HAL_PIXEL_FORMAT_RGB_565:
621                 ipp_fmt = IPP_RGB_565;
622                 break;
623         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
624                 ipp_fmt = IPP_Y_CBCR_H2V1;
625                 break;
626         case HAL_PIXEL_FORMAT_YCrCb_NV12:
627                 ipp_fmt = IPP_Y_CBCR_H2V2;
628                 break;
629         case HAL_PIXEL_FORMAT_YCrCb_444:
630                 ipp_fmt = IPP_Y_CBCR_H1V1;
631                 break;
632         default:
633                 ipp_fmt = IPP_IMGTYPE_LIMIT;
634                 break;
635         }
636
637         return ipp_fmt;
638 }
639
640 static void ipp_win_check(int *dst_w, int *dst_h, int *dst_vir_w,
641                                 int rotation, int fmt)
642 {
643         int align16 = 2;
644         int align64 = 8;
645
646
647         if (fmt == IPP_XRGB_8888) {
648                 align16 = 1;
649                 align64 = 2;
650         } else if (fmt == IPP_RGB_565) {
651                 align16 = 1;
652                 align64 = 4;
653         } else {
654                 align16 = 2;
655                 align64 = 8;
656         }
657         align16 -= 1;  /*for YUV, 1*/
658         align64 -= 1;  /*for YUV, 7*/
659
660         if (rotation == IPP_ROT_0) {
661                 if (fmt > IPP_RGB_565) {
662                         if ((*dst_w & 1) != 0)
663                                 *dst_w = *dst_w+1;
664                         if ((*dst_h & 1) != 0)
665                                 *dst_h = *dst_h+1;
666                         if (*dst_vir_w < *dst_w)
667                                 *dst_vir_w = *dst_w;
668                 }
669         } else {
670
671                 if ((*dst_w & align64) != 0)
672                         *dst_w = (*dst_w+align64)&(~align64);
673                 if ((fmt > IPP_RGB_565) && ((*dst_h & 1) == 1))
674                         *dst_h = *dst_h+1;
675                 if (*dst_vir_w < *dst_w)
676                         *dst_vir_w = *dst_w;
677         }
678
679 }
680
681 static void fb_copy_by_ipp(struct fb_info *dst_info,
682                 struct fb_info *src_info, int offset)
683 {
684         struct rk29_ipp_req ipp_req;
685         uint32_t  rotation = 0;
686         int dst_w, dst_h, dst_vir_w;
687         int ipp_fmt;
688         u8 data_format = (dst_info->var.nonstd)&0xff;
689
690         memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
691 #if defined(CONFIG_FB_ROTATE)
692         int orientation = 270 - CONFIG_ROTATE_ORIENTATION;
693         switch (orientation) {
694         case 0:
695                 rotation = IPP_ROT_0;
696                 break;
697         case 90:
698                 rotation = IPP_ROT_90;
699                 break;
700         case 180:
701                 rotation = IPP_ROT_180;
702                 break;
703         case 270:
704                 rotation = IPP_ROT_270;
705                 break;
706         default:
707                 rotation = IPP_ROT_270;
708                 break;
709
710         }
711 #endif
712
713         dst_w = dst_info->var.xres;
714         dst_h = dst_info->var.yres;
715         dst_vir_w = dst_info->var.xres_virtual;
716         ipp_fmt = get_ipp_format(data_format);
717         ipp_win_check(&dst_w, &dst_h, &dst_vir_w, rotation, ipp_fmt);
718         ipp_req.src0.YrgbMst = src_info->fix.smem_start + offset;
719         ipp_req.src0.w = src_info->var.xres;
720         ipp_req.src0.h = src_info->var.yres;
721         ipp_req.src_vir_w = src_info->var.xres_virtual;
722         ipp_req.src0.fmt = ipp_fmt;
723
724         ipp_req.dst0.YrgbMst = dst_info->fix.smem_start + offset;
725         ipp_req.dst0.w = dst_w;
726         ipp_req.dst0.h = dst_h;
727         ipp_req.dst_vir_w = dst_vir_w;
728         ipp_req.dst0.fmt = ipp_fmt;
729
730
731         ipp_req.timeout = 100;
732         ipp_req.flag = rotation;
733         ipp_blit_sync(&ipp_req);
734
735 }
736
737 #endif
738
739
740 static int rk_fb_rotate(struct fb_info *dst_info,
741                                 struct fb_info *src_info, int offset)
742 {
743         #if defined(CONFIG_RK29_IPP)
744                 fb_copy_by_ipp(dst_info, src_info, offset);
745         #else
746                 return -1;
747         #endif
748                 return 0;
749 }
750 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
751 {
752         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
753         struct rk_lcdc_driver *dev_drv  = (struct rk_lcdc_driver *)info->par;
754         struct fb_fix_screeninfo *fix = &info->fix;
755         struct fb_info *extend_info = NULL;
756         struct rk_lcdc_driver *extend_dev_drv = NULL;
757         int win_id = 0, extend_win_id = 0;
758         struct rk_lcdc_win *extend_win = NULL;
759         struct rk_lcdc_win *win = NULL;
760         int fb_id = 0;
761
762
763         u32 xoffset = var->xoffset;
764         u32 yoffset = var->yoffset;
765         u32 xvir = var->xres_virtual;
766         u32 yvir = var->yres_virtual;
767         /*u8 data_format = var->nonstd&0xff;*/
768
769         u8  pixel_width;
770         u32 vir_width_bit;
771         u32 stride,uv_stride;
772         u32 stride_32bit_1;
773         u32 stride_32bit_2;
774         u32 stride_128bit_1;
775         u32 stride_128bit_2;
776         u16 uv_x_off,uv_y_off;
777         u8  is_pic_yuv=0;
778
779         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
780         if (win_id < 0)
781                 return  -ENODEV;
782         else
783                 win = dev_drv->win[win_id];
784
785         if (rk_fb->disp_mode == DUAL) {
786                 fb_id = get_extend_fb_id(info);
787                 extend_info = rk_fb->fb[(rk_fb->num_fb>>1) + fb_id];
788                 extend_dev_drv  = (struct rk_lcdc_driver *)extend_info->par;
789                 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
790                                                 extend_info->fix.id);
791                 extend_win = extend_dev_drv->win[extend_win_id];
792         }
793         pixel_width = rk_fb_pixel_width(win->format);
794         vir_width_bit = pixel_width * xvir;
795         stride_128bit_1 = ((vir_width_bit   + 127) & (~127))/8; //pixel_width = byte_num *8
796         stride_128bit_2 = ((vir_width_bit*2 + 127) & (~127))/8; //pixel_width = byte_num *8
797         stride_32bit_1  = ((vir_width_bit   + 31 ) & (~31 ))/8; //pixel_width = byte_num *8
798         stride_32bit_2  = ((vir_width_bit*2 + 31 ) & (~31 ))/8; //pixel_width = byte_num *8
799
800         stride    = stride_32bit_1;//default rgb
801         fix->line_length = stride;
802
803         switch (win->format){
804         case YUV422:
805                 is_pic_yuv = 1;
806                 stride     = stride_32bit_1;
807                 uv_stride  = stride_32bit_1>> 1 ;//
808                 uv_x_off   = xoffset >> 1 ;//
809                 uv_y_off   = yoffset;//0
810                 fix->line_length = stride;
811                 break;
812         case YUV420://420sp
813                 is_pic_yuv = 1;
814                 stride     = stride_32bit_1;
815                 uv_stride  = stride_32bit_1;
816                 uv_x_off   = xoffset;
817                 uv_y_off   = yoffset >> 1;
818                 fix->line_length = stride;
819                 break;
820         case YUV444:
821                 is_pic_yuv = 1;
822                 stride     = stride_32bit_1;
823                 uv_stride  = stride_32bit_2;
824                 uv_x_off   = xoffset*2;
825                 uv_y_off   = yoffset;
826                 fix->line_length = stride<<2;
827                 break;
828         default:
829                 break;
830         }
831
832         // x y mirror ,jump line
833         win->area[0].y_offset = yoffset*stride+xoffset*pixel_width/8;
834         if(is_pic_yuv == 1){
835                 win->area[0].c_offset = uv_y_off*uv_stride+uv_x_off*pixel_width/8;
836         }
837
838         switch (win->format) {
839         case XBGR888:
840         case ARGB888:
841         case ABGR888:
842                 win->area[0].y_offset=(yoffset*xvir + xoffset)*4;//win->y_offset = (yoffset*xvir + xoffset)*4;
843                 break;
844         case  RGB888:
845                 win->area[0].y_offset = (yoffset*xvir + xoffset)*3;
846                 break;
847         case RGB565:
848                 win->area[0].y_offset = (yoffset*xvir + xoffset)*2;
849                 break;
850         case  YUV422:
851                 win->area[0].y_offset = yoffset*xvir + xoffset;
852                 win->area[0].c_offset = win->area[0].y_offset;
853                 break;
854         case  YUV420:
855                 win->area[0].y_offset = yoffset*xvir + xoffset;
856                 win->area[0].c_offset = (yoffset>>1)*xvir + xoffset;
857                 break;
858         case  YUV444:
859                 win->area[0].y_offset = yoffset*xvir + xoffset;
860                 win->area[0].c_offset = yoffset*2*xvir + (xoffset<<1);
861                 break;
862         default:
863                 break;
864         }
865         win->area[0].smem_start = fix->smem_start;
866         win->area[0].cbr_start = fix->smem_start + xvir * yvir;
867         win->state=1;
868         win->area[0].state=1;
869         win->area_num = 1;
870         
871         dev_drv->ops->pan_display(dev_drv, win_id);
872         if (rk_fb->disp_mode == DUAL) {
873                 if (extend_win->state && (hdmi_switch_complete)) {
874                         extend_win->area[0].y_offset = win->area[0].y_offset;
875                 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
876                         rk_fb_rotate(extend_info, info, win->area[0].y_offset);
877                 #endif
878                         extend_dev_drv->ops->pan_display(extend_dev_drv, extend_win_id);
879                 }
880         }
881
882         #ifdef  CONFIG_FB_MIRRORING
883         if (video_data_to_mirroring)
884                 video_data_to_mirroring(info, NULL);
885         #endif
886         return 0;
887 }
888
889 static int rk_fb_get_list_stat(struct rk_lcdc_driver *dev_drv)
890 {
891         int i,j;
892         i = list_empty(&dev_drv->update_regs_list);
893         j = list_empty(&saved_list);
894         return i==j?0:1;
895
896 }
897
898 void rk_fd_fence_wait(struct rk_lcdc_driver *dev_drv,
899         struct sync_fence *fence)
900 {
901         int err = sync_fence_wait(fence, 1000);
902         
903         if (err >= 0)
904                 return;
905
906         if (err == -ETIME)
907                 err = sync_fence_wait(fence, 10 * MSEC_PER_SEC);
908
909         if (err < 0)
910                 printk("error waiting on fence\n");
911 }
912
913
914 void rk_fb_free_dma_buf(struct rk_fb_reg_win_data *reg_win_data)
915 {
916 #ifdef H_USE_FENCE
917         int i;
918         for(i=0;i<RK_WIN_MAX_AREA;i++){
919                 if(reg_win_data->reg_area_data[i].acq_fence)
920                         sync_fence_put(reg_win_data->reg_area_data[i].acq_fence);
921         }
922 #endif
923         memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data));
924 }
925
926 static void rk_fb_update_driver(struct rk_lcdc_win *win,struct rk_fb_reg_win_data *reg_win_data)
927 {
928         int i=0;
929         //struct rk_lcdc_win *win;      
930         //win = dev_drv->win[reg_win_data->win_id];
931         win->area_num = reg_win_data->area_num;
932         win->format = reg_win_data->data_format;
933         win->id = reg_win_data->win_id;
934         win->z_order = reg_win_data->z_order;
935         
936         #if 0
937         for(i=0;i<win->area_num;i++)
938         {
939                 printk("i=%d:area[%d]=%x,reg_area_data[%d]=%x,mem_start=%x\n",
940                         i,i,&win->area[i],i,&reg_win_data->reg_area_data[i],reg_win_data->reg_area_data[i].smem_start);
941                 
942                 win->area[i].smem_start = reg_win_data->reg_area_data[i].smem_start;
943                 win->area[i].cbr_start  = reg_win_data->reg_area_data[i].cbr_start;
944                 win->area[i].xpos          = reg_win_data->reg_area_data[i].xpos;
945                 win->area[i].ypos          = reg_win_data->reg_area_data[i].ypos;
946                 win->area[i].xsize         = reg_win_data->reg_area_data[i].xsize;
947                 win->area[i].ysize         = reg_win_data->reg_area_data[i].ysize;
948                 win->area[i].xact          = reg_win_data->reg_area_data[i].xact;
949                 win->area[i].yact          = reg_win_data->reg_area_data[i].yact;
950                 win->area[i].xvir          = reg_win_data->reg_area_data[i].xvir;
951                 win->area[i].yvir          = reg_win_data->reg_area_data[i].yvir;
952                 win->area[i].y_offset      = reg_win_data->reg_area_data[i].y_offset;
953                 win->area[i].c_offset      = reg_win_data->reg_area_data[i].c_offset;
954                 win->area[i].state = 1;
955         }       
956         #else
957         if(reg_win_data->reg_area_data[0].smem_start > 0){
958                 win->state = 1;
959                 win->area_num = reg_win_data->area_num;
960                 win->format = reg_win_data->data_format;
961                 win->id = reg_win_data->win_id;
962                 win->z_order = reg_win_data->z_order;
963                 win->area[0].uv_vir_stride = reg_win_data->reg_area_data[0].uv_vir_stride;
964                 win->area[0].cbr_start = reg_win_data->reg_area_data[0].cbr_start;
965                 win->area[0].c_offset = reg_win_data->reg_area_data[0].c_offset;
966                 win->alpha_en = reg_win_data->alpha_en;
967                 win->alpha_mode = reg_win_data->alpha_mode;
968                 win->g_alpha_val = reg_win_data->g_alpha_val;
969                 for(i=0;i<RK_WIN_MAX_AREA;i++)
970                 {
971                         if(reg_win_data->reg_area_data[i].smem_start > 0){
972                                 win->area[i].smem_start = reg_win_data->reg_area_data[i].smem_start;
973                                 win->area[i].xpos          = reg_win_data->reg_area_data[i].xpos;
974                                 win->area[i].ypos          = reg_win_data->reg_area_data[i].ypos;
975                                 win->area[i].xsize         = reg_win_data->reg_area_data[i].xsize;
976                                 win->area[i].ysize         = reg_win_data->reg_area_data[i].ysize;
977                                 win->area[i].xact          = reg_win_data->reg_area_data[i].xact;
978                                 win->area[i].yact          = reg_win_data->reg_area_data[i].yact;
979                                 win->area[i].xvir          = reg_win_data->reg_area_data[i].xvir;
980                                 win->area[i].yvir          = reg_win_data->reg_area_data[i].yvir;
981                                 win->area[i].y_offset      = reg_win_data->reg_area_data[i].y_offset;
982                                 win->area[i].y_vir_stride  = reg_win_data->reg_area_data[i].y_vir_stride;
983                                 win->area[i].state = 1;
984                         }else{
985                                 win->area[i].state = 0;
986                         }
987                 }
988         }else{
989                 win->state = 0;
990         }
991         #endif
992
993 }
994
995
996 static void rk_fb_update_reg(struct rk_lcdc_driver * dev_drv,struct rk_fb_reg_data *regs)
997 {
998         int i,j,ret=0;
999         struct rk_lcdc_win *win;
1000         ktime_t timestamp = dev_drv->vsync_info.timestamp;
1001         //struct rk_fb_reg_win_data old_reg_win_data[RK30_MAX_LAYER_SUPPORT];
1002
1003         for(i=0;i<dev_drv->lcdc_win_num;i++){ 
1004                 //old_reg_win_data[i]= regs->reg_win_data[i];
1005                 win = dev_drv->win[i];
1006                 for(j=0;j<regs->win_num;j++){
1007                         if(i == regs->reg_win_data[j].win_id)
1008                                 break;
1009                 }
1010                 if(j<regs->win_num){
1011                         rk_fb_update_driver(win,&regs->reg_win_data[j]);
1012                         win->state = 1;
1013                 }else{
1014                         win->state = 0;
1015                 }
1016         }
1017 #if 0
1018         for(i=0;i<2;i++){
1019                 printk("win[%d]:drv_win_state=%d\n",i,dev_drv->win[i]->state);
1020                 for(j=0;j<4;j++){
1021                         printk("area[%d]:state=%d,mem_addr=%x\n",
1022                                 i,dev_drv->win[i]->area[j].state,dev_drv->win[i]->area[j].smem_start);
1023                 }
1024         }
1025 #endif  
1026         dev_drv->atv_layer_cnt = regs->win_num;
1027         dev_drv->cur_screen->post_xsize = regs->post_cfg.xsize;
1028         dev_drv->cur_screen->post_ysize = regs->post_cfg.ysize;
1029         dev_drv->cur_screen->post_dsp_stx = regs->post_cfg.xpos;
1030         dev_drv->cur_screen->post_dsp_sty = regs->post_cfg.ypos;
1031         dev_drv->ops->set_par(dev_drv,0);
1032
1033         ret = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
1034                         !ktime_equal(timestamp, dev_drv->vsync_info.timestamp),msecs_to_jiffies(dev_drv->cur_screen->ft+5));
1035
1036         sw_sync_timeline_inc(dev_drv->timeline, 1);
1037
1038         for(i=0;i<regs->win_num;i++){
1039                 rk_fb_free_dma_buf(&regs->reg_win_data[i]);
1040         }
1041 }
1042
1043 static void rk_fb_update_regs_handler(struct kthread_work *work)
1044 {
1045         struct rk_lcdc_driver * dev_drv =
1046                         container_of(work, struct rk_lcdc_driver, update_regs_work);
1047         struct rk_fb_reg_data *data, *next;
1048         //struct list_head saved_list;
1049         mutex_lock(&dev_drv->update_regs_list_lock);
1050         saved_list = dev_drv->update_regs_list;
1051         list_replace_init(&dev_drv->update_regs_list, &saved_list);
1052         mutex_unlock(&dev_drv->update_regs_list_lock);
1053         
1054         list_for_each_entry_safe(data, next, &saved_list, list) {
1055                 rk_fb_update_reg(dev_drv,data);
1056                 list_del(&data->list);
1057                 kfree(data);
1058         }
1059 }
1060
1061 static int rk_fb_set_win_buffer(struct fb_info *info,
1062         struct rk_fb_win_par *win_par,struct rk_fb_reg_win_data *reg_win_data)
1063 {
1064         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1065         //struct fb_var_screeninfo *var = &info->var;
1066         struct fb_fix_screeninfo *fix = &info->fix;
1067         //struct rk_lcdc_driver * dev_drv = (struct rk_lcdc_driver * )info->par;
1068
1069         int i,j,ion_fd,acq_fence_fd;
1070         u32 xvir,yvir;
1071         u32 xoffset,yoffset;
1072
1073         struct ion_handle *hdl;
1074         ion_phys_addr_t phy_addr;
1075         size_t len;
1076         int index_buf;
1077         u8  fb_data_fmt;
1078         u8  pixel_width;
1079         u32 vir_width_bit;
1080         u32 stride,uv_stride;
1081         u32 stride_32bit_1;
1082         u32 stride_32bit_2;
1083         u32 stride_128bit_1;
1084         u32 stride_128bit_2;
1085         u16 uv_x_off,uv_y_off;
1086         u8  is_pic_yuv=0;
1087         u8  ppixel_a=0,global_a=0;
1088         reg_win_data->area_num = 0;
1089         if(win_par->area_par[0].phy_addr == 0){
1090                 for(i=0;i<RK_WIN_MAX_AREA;i++){ 
1091                         ion_fd = win_par->area_par[i].ion_fd;
1092                         if(ion_fd > 0){
1093                                 reg_win_data->area_num++;
1094                                 for(j=0;j<i;j++){
1095                                         if(ion_fd == win_par->area_par[j].ion_fd){
1096                                                 printk("region[%d] fd is same to region[%d]:fd=%d",
1097                                                         i,j,ion_fd);
1098                                                 break;
1099                                         }       
1100                                 }
1101                                 if(j == i){
1102                                         hdl = ion_import_dma_buf(rk_fb->ion_client, ion_fd);
1103                                         ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
1104                                         reg_win_data->reg_area_data[i].smem_start = phy_addr;
1105                                         reg_win_data->area_buf_num++;
1106                                         reg_win_data->reg_area_data[i].index_buf = 1;
1107                                 }else{
1108                                         reg_win_data->reg_area_data[i].smem_start = 
1109                                                 reg_win_data->reg_area_data[j].smem_start;                      
1110                                 }
1111                         }
1112                         #if 0
1113                         printk("i=%d,ion_fd=%d,addr=0x%x,area_num=%d,area_buf_num=%d\n",
1114                                 i,ion_fd,reg_win_data->reg_area_data[i].smem_start,
1115                                 reg_win_data->area_num,reg_win_data->area_buf_num);
1116                         #endif
1117                 }
1118         }else{
1119                 reg_win_data->reg_area_data[0].smem_start = 
1120                 win_par->area_par[0].phy_addr;
1121                 reg_win_data->area_num = 1;
1122         }       
1123
1124         if(reg_win_data->area_num == 0){
1125                 return 0;
1126         }
1127
1128         for(i=0;i<reg_win_data->area_num;i++){
1129                 acq_fence_fd = win_par->area_par[i].acq_fence_fd;
1130                 index_buf = reg_win_data->reg_area_data[i].index_buf;
1131                 if((acq_fence_fd > 0)&&(index_buf == 1)){
1132                         reg_win_data->reg_area_data[i].acq_fence = 
1133                                 sync_fence_fdget(win_par->area_par[i].acq_fence_fd);
1134                 }
1135         }
1136         fb_data_fmt = rk_fb_data_fmt(win_par->data_format,0);
1137         reg_win_data->data_format = fb_data_fmt;
1138         pixel_width = rk_fb_pixel_width(fb_data_fmt);
1139         
1140         ppixel_a = ((fb_data_fmt == ARGB888)||(fb_data_fmt == ABGR888)) ? 1:0;
1141         global_a = (win_par->g_alpha_val == 0) ? 0:1;
1142         reg_win_data->alpha_en = ppixel_a | global_a;
1143         
1144         reg_win_data->z_order = win_par->z_order;
1145         reg_win_data->win_id  = win_par->win_id;        
1146         
1147         for(i=0;i<reg_win_data->area_num;i++){  
1148                 reg_win_data->reg_area_data[i].xpos = win_par->area_par[i].xpos;//visiable pos in panel
1149                 reg_win_data->reg_area_data[i].ypos = win_par->area_par[i].ypos;
1150
1151                 reg_win_data->reg_area_data[i].xsize= win_par->area_par[i].xsize;//realy size in panel
1152                 reg_win_data->reg_area_data[i].ysize= win_par->area_par[i].ysize;
1153
1154                 reg_win_data->reg_area_data[i].xact= win_par->area_par[i].xact;//realy size in panel
1155                 reg_win_data->reg_area_data[i].yact= win_par->area_par[i].yact; 
1156
1157                 xoffset = win_par->area_par[i].x_offset;//buf offset
1158                 yoffset = win_par->area_par[i].y_offset;
1159                 xvir = win_par->area_par[i].xvir;
1160                 reg_win_data->reg_area_data[i].xvir = xvir;
1161                 yvir = win_par->area_par[i].yvir;
1162                 reg_win_data->reg_area_data[i].yvir = yvir;
1163                 #if 0
1164                 printk("i=%d,xpos=%d,ypos=%d,xsize=%d,ysize=%d,xact=%d,yact=%d,x_off=%d,y_off=%d,xvir=%d,yvir=%d\n",
1165                 i,reg_win_data->reg_area_data[i].xpos,reg_win_data->reg_area_data[i].ypos,reg_win_data->reg_area_data[i].xsize,reg_win_data->reg_area_data[i].ysize,
1166                 reg_win_data->reg_area_data[i].xact,reg_win_data->reg_area_data[i].yact,xoffset,yoffset,xvir,yvir);
1167                 #endif
1168
1169                 vir_width_bit = pixel_width * xvir;
1170                 stride_128bit_1 = ((vir_width_bit   + 127) & (~127))/8; //pixel_width = byte_num *8
1171                 stride_128bit_2 = ((vir_width_bit*2 + 127) & (~127))/8; //pixel_width = byte_num *8
1172                 stride_32bit_1  = ((vir_width_bit   + 31 ) & (~31 ))/8; //pixel_width = byte_num *8
1173                 stride_32bit_2  = ((vir_width_bit*2 + 31 ) & (~31 ))/8; //pixel_width = byte_num *8
1174
1175                 stride    = stride_32bit_1;//default rgb
1176                 fix->line_length = stride;
1177                 reg_win_data->reg_area_data[i].y_vir_stride = stride >> 2;
1178                 // x y mirror ,jump line
1179                 reg_win_data->reg_area_data[i].y_offset = yoffset*stride+xoffset*pixel_width/8;
1180         }
1181         switch (fb_data_fmt){
1182         case YUV422:
1183                 is_pic_yuv = 1;
1184                 stride     = stride_32bit_1;
1185                 uv_stride  = stride_32bit_1>> 1 ;//
1186                 uv_x_off   = xoffset >> 1 ;//
1187                 uv_y_off   = yoffset;//0
1188                 fix->line_length = stride;
1189                 break;
1190         case YUV420://420sp
1191                 is_pic_yuv = 1;
1192                 stride     = stride_32bit_1;
1193                 uv_stride  = stride_32bit_1;
1194                 uv_x_off   = xoffset;
1195                 uv_y_off   = yoffset >> 1;
1196                 fix->line_length = stride;
1197                 break;
1198         case YUV444:
1199                 is_pic_yuv = 1;
1200                 stride     = stride_32bit_1;
1201                 uv_stride  = stride_32bit_2;
1202                 uv_x_off   = xoffset*2;
1203                 uv_y_off   = yoffset;
1204                 fix->line_length = stride<<2;
1205                 break;
1206         default:
1207                 break;
1208         }
1209         if(is_pic_yuv == 1){
1210                 reg_win_data->reg_area_data[0].cbr_start = 
1211                         reg_win_data->reg_area_data[0].smem_start + xvir*yvir;          
1212                 reg_win_data->reg_area_data[0].c_offset = 
1213                         uv_y_off*uv_stride+uv_x_off*pixel_width/8;
1214                 reg_win_data->reg_area_data[0].uv_vir_stride = 
1215                         uv_stride >> 2;
1216         }       
1217         return 0;
1218 }
1219
1220 static int rk_fb_set_win_config(struct fb_info *info,
1221                 struct rk_fb_win_cfg_data *win_data)
1222 {
1223         //struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1224         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1225         struct rk_fb_reg_data *regs;
1226         struct rk_fb_reg_win_data *reg_win_data;
1227         struct sync_fence *release_fence[RK_MAX_BUF_NUM];
1228         struct sync_fence *retire_fence;
1229         struct sync_pt *release_sync_pt[RK_MAX_BUF_NUM];
1230         struct sync_pt *retire_sync_pt;
1231         int ret,i,j=0,fence_fd;
1232         char fence_name[20];
1233
1234         //mutex_lock(&dev_drv->output_lock);
1235         regs = kzalloc(sizeof(struct rk_fb_reg_data), GFP_KERNEL);
1236         if (!regs) {
1237                 printk("could not allocate rk_fb_reg_data\n");
1238                 ret = -ENOMEM;
1239                 return ret;
1240         }
1241         
1242         regs->post_cfg.xpos = win_data->post_cfg.xpos;
1243         regs->post_cfg.ypos = win_data->post_cfg.ypos;
1244         regs->post_cfg.xsize = win_data->post_cfg.xsize;
1245         regs->post_cfg.ysize = win_data->post_cfg.xsize;
1246         for (i=0; i<dev_drv->lcdc_win_num; i++) {
1247                 if(win_data->win_par[i].win_id < dev_drv->lcdc_win_num){
1248                         rk_fb_set_win_buffer(info,&win_data->win_par[i],&regs->reg_win_data[j]);
1249                         if(regs->reg_win_data[j].area_num > 0){
1250                                 regs->win_num++;
1251                                 regs->buf_num += regs->reg_win_data[j].area_buf_num;
1252                         }
1253                         j++;
1254                 }else{
1255                         printk("error:win_id bigger than lcdc_win_num\n");
1256                         printk("i=%d,win_id=%d\n",i,win_data->win_par[i].win_id);
1257                 }
1258         }       
1259         for(i=0; i<regs->win_num; i++){
1260                 reg_win_data = &regs->reg_win_data[i];
1261                 for(j=0;j<RK_WIN_MAX_AREA;j++){
1262                         if(reg_win_data->reg_area_data[j].acq_fence){
1263                                 printk("acq_fence wait!!!!!\n");
1264                                 rk_fd_fence_wait(dev_drv,
1265                                 reg_win_data->reg_area_data[j].acq_fence);
1266                         }
1267                 }
1268         }
1269
1270         mutex_lock(&dev_drv->output_lock);
1271         if(!(dev_drv->suspend_flag == 0)){
1272                 rk_fb_update_reg(dev_drv,regs);
1273                 printk("suspend_flag == 0\n");
1274                 goto err;
1275         }
1276         mutex_lock(&dev_drv->update_regs_list_lock);
1277         dev_drv->timeline_max++;
1278 #ifdef H_USE_FENCE
1279         for(i=0;i<RK_MAX_BUF_NUM;i++){
1280                 if(i<regs->buf_num){
1281                         sprintf(fence_name,"fence%d",i);
1282                         win_data->rel_fence_fd[i] =  get_unused_fd();
1283                         if (win_data->rel_fence_fd[i] < 0){
1284                                 printk("rel_fence_fd=%d\n",win_data->rel_fence_fd[i]);
1285                                 return -EFAULT;
1286                         }
1287                         release_sync_pt[i] = sw_sync_pt_create(dev_drv->timeline,
1288                                 dev_drv->timeline_max);
1289                         release_fence[i] = sync_fence_create(fence_name, release_sync_pt[i]);
1290                         sync_fence_install(release_fence[i], win_data->rel_fence_fd[i]);        
1291                 }else{
1292                         win_data->rel_fence_fd[i] = -1;
1293                 }
1294         }
1295         
1296         win_data->ret_fence_fd =  get_unused_fd();
1297         if (win_data->ret_fence_fd < 0){
1298                 printk("ret_fence_fd=%d\n",win_data->ret_fence_fd);
1299                 return -EFAULT;
1300         }
1301         retire_sync_pt = sw_sync_pt_create(dev_drv->timeline, dev_drv->timeline_max);
1302         retire_fence = sync_fence_create("ret_fence", retire_sync_pt);
1303         sync_fence_install(retire_fence, win_data->ret_fence_fd);
1304 #else
1305         for(i=0;i<RK_MAX_BUF_NUM;i++){
1306                 win_data->rel_fence_fd[i] = -1;
1307         }
1308         win_data->ret_fence_fd = -1;    
1309 #endif  
1310         if(dev_drv->wait_fs == 0){
1311                 list_add_tail(&regs->list,&dev_drv->update_regs_list);  
1312                 mutex_unlock(&dev_drv->update_regs_list_lock);
1313                 queue_kthread_work(&dev_drv->update_regs_worker,
1314                                 &dev_drv->update_regs_work);
1315         }else{
1316                 mutex_unlock(&dev_drv->update_regs_list_lock);
1317                 rk_fb_update_reg(dev_drv,regs);
1318         }
1319
1320 err:
1321         mutex_unlock(&dev_drv->output_lock);
1322         return ret;
1323 }
1324
1325 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
1326 {
1327         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1328         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1329         struct fb_fix_screeninfo *fix = &info->fix;
1330         int fb_id = 0, extend_win_id = 0;
1331         struct fb_info *extend_info = NULL;
1332         struct rk_lcdc_driver *extend_dev_drv = NULL;
1333         struct rk_lcdc_win *extend_win = NULL;
1334         struct rk_lcdc_win *win;
1335         int enable; /* enable fb:1 enable;0 disable*/
1336         int ovl;   /*overlay:0 win1 on the top of win0;1,win0 on the top of win1*/
1337         int num_buf; /*buffer_number*/
1338         int ret;
1339         struct rk_fb_win_cfg_data win_data;
1340         unsigned int dsp_addr[4];
1341         int list_stat;
1342
1343         int  win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1344         
1345         void __user *argp = (void __user *)arg;
1346         win = dev_drv->win[win_id];
1347         if (rk_fb->disp_mode == DUAL) {
1348                 fb_id = get_extend_fb_id(info);
1349                 extend_info = rk_fb->fb[(rk_fb->num_fb>>1) + fb_id];
1350                 extend_dev_drv  = (struct rk_lcdc_driver *)extend_info->par;
1351                 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
1352                                                 extend_info->fix.id);
1353                 extend_win = extend_dev_drv->win[extend_win_id];
1354         }
1355
1356         switch (cmd) {
1357         case RK_FBIOSET_YUV_ADDR:
1358         {
1359                 u32 yuv_phy[2];
1360                 if (copy_from_user(yuv_phy, argp, 8))
1361                         return -EFAULT;
1362                 fix->smem_start = yuv_phy[0];
1363                 fix->mmio_start = yuv_phy[1];
1364                 break;
1365         }
1366         case RK_FBIOSET_ENABLE:
1367                 if (copy_from_user(&enable, argp, sizeof(enable)))
1368                         return -EFAULT;
1369                 dev_drv->ops->open(dev_drv, win_id, enable);
1370                 break;
1371         case RK_FBIOGET_ENABLE:
1372                 enable = dev_drv->ops->get_win_state(dev_drv, win_id);
1373                 if (copy_to_user(argp, &enable, sizeof(enable)))
1374                         return -EFAULT;
1375                 break;
1376         case RK_FBIOSET_OVERLAY_STATE:
1377                 if (copy_from_user(&ovl, argp, sizeof(ovl)))
1378                         return -EFAULT;
1379                 dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
1380                 break;
1381         case RK_FBIOGET_OVERLAY_STATE:
1382                 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
1383                 if (copy_to_user(argp, &ovl, sizeof(ovl)))
1384                         return -EFAULT;
1385                 break;
1386         case RK_FBIOPUT_NUM_BUFFERS:
1387                 if (copy_from_user(&num_buf, argp, sizeof(num_buf)))
1388                         return -EFAULT;
1389                 dev_drv->num_buf = num_buf;
1390                 break;
1391         case RK_FBIOSET_VSYNC_ENABLE:
1392                 if (copy_from_user(&enable, argp, sizeof(enable)))
1393                         return -EFAULT;
1394                 dev_drv->vsync_info.active = enable;
1395                 break;
1396
1397         case RK_FBIOGET_DSP_ADDR:
1398                 dev_drv->ops->get_dsp_addr(dev_drv,dsp_addr);
1399                 if (copy_to_user(argp, &dsp_addr, sizeof(dsp_addr)))
1400                         return -EFAULT;
1401                 break;
1402         case RK_FBIOGET_LIST_STAT:
1403                 list_stat = rk_fb_get_list_stat(dev_drv);
1404                 if (copy_to_user(argp, &list_stat, sizeof(list_stat)))
1405                         return -EFAULT;
1406
1407                 break;
1408
1409 #if defined(CONFIG_ION_ROCKCHIP)
1410         case RK_FBIOSET_DMABUF_FD:
1411         {
1412                 int usr_fd;
1413                 struct ion_handle *hdl;
1414                 ion_phys_addr_t phy_addr;
1415                 size_t len;
1416                 if (copy_from_user(&usr_fd, argp, sizeof(usr_fd)))
1417                         return -EFAULT;
1418                 hdl = ion_import_dma_buf(rk_fb->ion_client, usr_fd);
1419                 ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
1420                 fix->smem_start = phy_addr;
1421                 break;
1422         }
1423         case RK_FBIOGET_DMABUF_FD:
1424         {
1425                 int fd = ion_share_dma_buf_fd(rk_fb->ion_client, win->area[0].ion_hdl);
1426                 if (fd < 0) {
1427                         dev_err(info->dev, "ion_share_dma_buf_fd failed\n");
1428                         return fd;
1429                 }
1430                 if (copy_to_user(argp, &fd, sizeof(fd)))
1431                         return -EFAULT;
1432                 break;
1433         }
1434 #endif
1435         case RK_FBIOSET_CONFIG_DONE:
1436                 if(copy_from_user(&win_data,
1437                         (struct rk_fb_win_cfg_data __user *)argp,
1438                         sizeof(win_data))){
1439                         ret = -EFAULT;
1440                         break;
1441                 };
1442
1443                 dev_drv->wait_fs = win_data.wait_fs;
1444                 rk_fb_set_win_config(info,&win_data);   
1445
1446                 if (copy_to_user((struct rk_fb_win_cfg_data __user *)arg,
1447                          &win_data,
1448                         sizeof(win_data))) {
1449                         ret = -EFAULT;
1450                         break;
1451                 }       
1452                 memset(&win_data, 0, sizeof(struct rk_fb_win_cfg_data));
1453
1454                 if (rk_fb->disp_mode == DUAL) {
1455                         if (extend_win->state && (hdmi_switch_complete)) {
1456                                 if (rk_fb->num_fb >= 2) {
1457                                         if (extend_dev_drv->ops->lcdc_reg_update)
1458                                                 extend_dev_drv->ops->lcdc_reg_update(extend_dev_drv);
1459                                 }
1460                         }
1461                 }
1462                 break;
1463         default:
1464                 dev_drv->ops->ioctl(dev_drv, cmd, arg, win_id);
1465                 break;
1466         }
1467         
1468         return 0;       
1469 }
1470
1471 static int rk_fb_blank(int blank_mode, struct fb_info *info)
1472 {
1473         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1474         struct fb_fix_screeninfo *fix = &info->fix;
1475         int win_id;
1476 #if defined(CONFIG_RK_HDMI)
1477         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1478 #endif
1479
1480         win_id = dev_drv->ops->fb_get_win_id(dev_drv, fix->id);
1481         if (win_id < 0)
1482                 return  -ENODEV;
1483 #if defined(CONFIG_RK_HDMI)     
1484         if ((rk_fb->disp_mode == ONE_DUAL) && (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)) {
1485                 printk(KERN_INFO "hdmi is connect , not blank lcdc\n");
1486         } else
1487 #endif
1488         {
1489                 dev_drv->ops->blank(dev_drv, win_id, blank_mode);
1490         }
1491         return 0;
1492 }
1493
1494 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1495 {
1496
1497         if ((0 == var->xres_virtual) || (0 == var->yres_virtual) ||
1498                 (0 == var->xres) || (0 == var->yres) || (var->xres < 16) ||
1499                 ((16 != var->bits_per_pixel) && (32 != var->bits_per_pixel))) {
1500                 dev_err(info->dev, "%s check var fail 1:\n"
1501                                 "xres_vir:%d>>yres_vir:%d\n"
1502                                 "xres:%d>>yres:%d\n"
1503                                 "bits_per_pixel:%d\n",
1504                                 info->fix.id,
1505                                 var->xres_virtual,
1506                                 var->yres_virtual,
1507                                 var->xres,
1508                                 var->yres,
1509                                 var->bits_per_pixel);
1510                 return -EINVAL;
1511         }
1512
1513         if (((var->xoffset+var->xres) > var->xres_virtual) ||
1514                 ((var->yoffset+var->yres) > (var->yres_virtual))) {
1515                 dev_err(info->dev, "%s check_var fail 2:\n"
1516                                 "xoffset:%d>>xres:%d>>xres_vir:%d\n"
1517                                 "yoffset:%d>>yres:%d>>yres_vir:%d\n",
1518                                 info->fix.id,
1519                                 var->xoffset,
1520                                 var->xres,
1521                                 var->xres_virtual,
1522                                 var->yoffset,
1523                                 var->yres,
1524                                 var->yres_virtual);
1525                 return -EINVAL;
1526         }
1527
1528         return 0;
1529 }
1530
1531 static ssize_t rk_fb_read(struct fb_info *info, char __user *buf,
1532                            size_t count, loff_t *ppos)
1533 {
1534         unsigned long p = *ppos;
1535         u8 *buffer, *dst;
1536         u8 __iomem *src;
1537         int c, cnt = 0, err = 0;
1538         unsigned long total_size;
1539         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1540         struct rk_lcdc_win *win = NULL;
1541         int win_id = 0;
1542         int list_empty=0;
1543
1544         list_empty = rk_fb_get_list_stat(dev_drv);
1545         printk("list_empty=%d\n",list_empty);
1546
1547         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1548         if (win_id < 0)
1549                 return  -ENODEV;
1550         else
1551                 win = dev_drv->win[win_id];
1552
1553         if (win->format == RGB565)
1554                 total_size = win->area[0].xact*win->area[0].yact<<1; /*only read the current frame buffer*/
1555         else
1556                 total_size = win->area[0].xact*win->area[0].yact<<2;
1557
1558
1559         if (p >= total_size)
1560                 return 0;
1561
1562         if (count >= total_size)
1563                 count = total_size;
1564
1565         if (count + p > total_size)
1566                 count = total_size - p;
1567
1568         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
1569                          GFP_KERNEL);
1570         if (!buffer)
1571                 return -ENOMEM;
1572
1573         src = (u8 __iomem *) (info->screen_base + p + win->area[0].y_offset);
1574
1575         while (count) {
1576                 c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1577                 dst = buffer;
1578                 fb_memcpy_fromfb(dst, src, c);
1579                 dst += c;
1580                 src += c;
1581
1582                 if (copy_to_user(buf, buffer, c)) {
1583                         err = -EFAULT;
1584                         break;
1585                 }
1586                 *ppos += c;
1587                 buf += c;
1588                 cnt += c;
1589                 count -= c;
1590         }
1591
1592         kfree(buffer);
1593
1594         return (err) ? err : cnt;
1595 }
1596
1597 static ssize_t rk_fb_write(struct fb_info *info, const char __user *buf,
1598                             size_t count, loff_t *ppos)
1599 {
1600         unsigned long p = *ppos;
1601         u8 *buffer, *src;
1602         u8 __iomem *dst;
1603         int c, cnt = 0, err = 0;
1604         unsigned long total_size;
1605         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1606         struct rk_lcdc_win *win = NULL;
1607         int win_id = 0;
1608
1609         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1610         if (win_id < 0)
1611                 return  -ENODEV;
1612         else
1613                 win = dev_drv->win[win_id];
1614
1615         if (win->format == RGB565)
1616                 total_size = win->area[0].xact*win->area[0].yact<<1; /*write the current frame buffer*/
1617         else
1618                 total_size = win->area[0].xact*win->area[0].yact<<2;
1619
1620         if (p > total_size)
1621                 return -EFBIG;
1622
1623         if (count > total_size) {
1624                 err = -EFBIG;
1625                 count = total_size;
1626         }
1627
1628         if (count + p > total_size) {
1629                 if (!err)
1630                         err = -ENOSPC;
1631
1632                 count = total_size - p;
1633         }
1634
1635         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
1636                          GFP_KERNEL);
1637         if (!buffer)
1638                 return -ENOMEM;
1639
1640         dst = (u8 __iomem *) (info->screen_base + p + win->area[0].y_offset);
1641
1642         while (count) {
1643                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1644                 src = buffer;
1645
1646                 if (copy_from_user(src, buf, c)) {
1647                         err = -EFAULT;
1648                         break;
1649                 }
1650
1651                 fb_memcpy_tofb(dst, src, c);
1652                 dst += c;
1653                 src += c;
1654                 *ppos += c;
1655                 buf += c;
1656                 cnt += c;
1657                 count -= c;
1658         }
1659
1660         kfree(buffer);
1661
1662         return (cnt) ? cnt : err;
1663
1664 }
1665
1666 static int rk_fb_set_par(struct fb_info *info)
1667 {
1668         struct fb_var_screeninfo *var = &info->var;
1669         struct fb_fix_screeninfo *fix = &info->fix;
1670         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1671         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1672         int fb_id, extend_win_id = 0;
1673         struct fb_info *extend_info = NULL;
1674         struct rk_lcdc_driver *extend_dev_drv = NULL;
1675         struct rk_lcdc_win *extend_win = NULL;
1676         struct rk_lcdc_win *win = NULL;
1677         struct rk_screen *screen = dev_drv->cur_screen;
1678         int win_id = 0;
1679         u32 cblen = 0, crlen = 0;
1680         u16 xsize = 0, ysize = 0;                 /*winx display window height/width --->LCDC_WINx_DSP_INFO*/
1681         u32 xoffset = var->xoffset;             /* offset from virtual to visible*/
1682         u32 yoffset = var->yoffset;
1683         u16 xpos = (var->nonstd>>8) & 0xfff;   /*visiable pos in panel*/
1684         u16 ypos = (var->nonstd>>20) & 0xfff;
1685         u32 xvir = var->xres_virtual;
1686         u32 yvir = var->yres_virtual;
1687         u8  data_format = var->nonstd&0xff;
1688         u8  fb_data_fmt;
1689         u8  pixel_width;
1690         u32 vir_width_bit;
1691         u32 stride,uv_stride;
1692         u32 stride_32bit_1;
1693         u32 stride_32bit_2;
1694         u32 stride_128bit_1;
1695         u32 stride_128bit_2;
1696         u16 uv_x_off,uv_y_off;
1697         u8  is_pic_yuv=0;
1698
1699         var->pixclock = dev_drv->pixclock;
1700         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1701         if (win_id < 0)
1702                 return  -ENODEV;
1703         else
1704                 win = dev_drv->win[win_id];
1705         if (rk_fb->disp_mode == DUAL) {
1706                 fb_id = get_extend_fb_id(info);
1707                 extend_info = rk_fb->fb[(rk_fb->num_fb>>1) + fb_id];
1708                 extend_dev_drv  = (struct rk_lcdc_driver *)extend_info->par;
1709                 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
1710                                         extend_info->fix.id);
1711                 extend_win = extend_dev_drv->win[extend_win_id];
1712         }
1713         if (var->grayscale>>8) { /*if the application has specific the horizontal and vertical display size*/
1714                 xsize = (var->grayscale>>8) & 0xfff;
1715                 ysize = (var->grayscale>>20) & 0xfff;
1716         } else  { /*ohterwise  full  screen display*/
1717                 xsize = screen->mode.xres;
1718                 ysize = screen->mode.yres;
1719         }
1720
1721 /*this is for device like rk2928 ,whic have one lcdc but two display outputs*/
1722 /*save winameter set by android*/
1723 if (rk_fb->disp_mode != DUAL) {
1724         if (screen->screen_id == 0) {
1725
1726                 dev_drv->screen0->xsize = xsize;
1727                 dev_drv->screen0->ysize = ysize;
1728                 dev_drv->screen0->xpos  = xpos;
1729                 dev_drv->screen0->ypos = ypos;
1730         } else {
1731                 xsize = dev_drv->screen1->xsize;
1732                 ysize = dev_drv->screen1->ysize;
1733                 xpos = dev_drv->screen1->xpos;
1734                 ypos = dev_drv->screen1->ypos;
1735         }
1736 }
1737
1738         fb_data_fmt = rk_fb_data_fmt(data_format,var->bits_per_pixel);
1739         pixel_width = rk_fb_pixel_width(fb_data_fmt);
1740         vir_width_bit = pixel_width * xvir;
1741         stride_128bit_1 = ((vir_width_bit   + 127) & (~127))/8; //pixel_width = byte_num *8
1742         stride_128bit_2 = ((vir_width_bit*2 + 127) & (~127))/8; //pixel_width = byte_num *8
1743         stride_32bit_1  = ((vir_width_bit   + 31 ) & (~31 ))/8; //pixel_width = byte_num *8
1744         stride_32bit_2  = ((vir_width_bit*2 + 31 ) & (~31 ))/8; //pixel_width = byte_num *8
1745
1746         stride    = stride_32bit_1;//default rgb
1747         fix->line_length = stride;
1748
1749         switch (fb_data_fmt){
1750         case YUV422:
1751                 is_pic_yuv = 1;
1752                 stride     = stride_32bit_1;
1753                 uv_stride  = stride_32bit_1>> 1 ;//
1754                 uv_x_off   = xoffset >> 1 ;//
1755                 uv_y_off   = yoffset;//0
1756                 fix->line_length = stride;
1757                 cblen = crlen = (xvir*yvir)>>1;
1758                 break;
1759         case YUV420://420sp
1760                 is_pic_yuv = 1;
1761                 stride     = stride_32bit_1;
1762                 uv_stride  = stride_32bit_1;
1763                 uv_x_off   = xoffset;
1764                 uv_y_off   = yoffset >> 1;
1765                 fix->line_length = stride;
1766                 cblen = crlen = (xvir*yvir)>>2;
1767                 break;
1768         case YUV444:
1769                 is_pic_yuv = 1;
1770                 stride     = stride_32bit_1;
1771                 uv_stride  = stride_32bit_2;
1772                 uv_x_off   = xoffset*2;
1773                 uv_y_off   = yoffset;
1774                 fix->line_length = stride<<2;
1775                 cblen = crlen = (xvir*yvir);
1776                 break;
1777         default:
1778                 break;
1779         }
1780
1781         // x y mirror ,jump line
1782         win->area[0].y_offset = yoffset*stride+xoffset*pixel_width/8;
1783         if(is_pic_yuv == 1){
1784                 win->area[0].c_offset = uv_y_off*uv_stride+uv_x_off*pixel_width/8;
1785         }
1786         win->format = fb_data_fmt;
1787         win->area[0].y_vir_stride = stride>>2;
1788         win->area[0].uv_vir_stride = uv_stride>>2;
1789         win->area[0].xpos = xpos;
1790         win->area[0].ypos = ypos;
1791         win->area[0].xsize = xsize;
1792         win->area[0].ysize = ysize;
1793
1794         win->area[0].smem_start = fix->smem_start;
1795         win->area[0].cbr_start = fix->smem_start+stride*yvir;//fix->mmio_start;
1796         win->area[0].xact = var->xres;              /*winx active window height,is a wint of vir*/
1797         win->area[0].yact = var->yres;
1798         win->area[0].xvir =  var->xres_virtual;    /*virtual resolution  stride --->LCDC_WINx_VIR*/
1799         win->area[0].yvir =  var->yres_virtual;
1800         win->state=1;
1801         win->area[0].state=1;
1802         win->area_num = 1;
1803
1804         if (rk_fb->disp_mode == DUAL) {
1805                 if (extend_win->state && (hdmi_switch_complete)) {
1806                         if (info != extend_info) {
1807                                 if (win->area[0].xact < win->area[0].yact) {
1808                                         //extend_win->xact = win->area[0].yact;
1809                                         extend_win->area[0].xact = win->area[0].yact;
1810                                         extend_win->area[0].yact = win->area[0].xact;
1811                                         extend_win->area[0].xvir = win->area[0].yact;
1812                                         extend_info->var.xres = var->yres;
1813                                         extend_info->var.yres = var->xres;
1814                                         extend_info->var.xres_virtual = var->yres;
1815                                 } else {
1816                                         extend_win->area[0].xact = win->area[0].xact;
1817                                         extend_win->area[0].yact = win->area[0].yact;
1818                                         extend_win->area[0].xvir = win->area[0].xvir;
1819                                         extend_info->var.xres = var->xres;
1820                                         extend_info->var.yres = var->yres;
1821                                         extend_info->var.xres_virtual = var->xres_virtual;
1822                                 }
1823                                 extend_win->format = win->format;
1824                                 extend_info->var.nonstd &= 0xffffff00;
1825                                 extend_info->var.nonstd |= data_format;
1826                                 extend_dev_drv->ops->set_par(extend_dev_drv, extend_win_id);
1827                         }
1828                 }
1829         }
1830         dev_drv->ops->set_par(dev_drv, win_id);
1831
1832         return 0;
1833 }
1834
1835 static inline unsigned int chan_to_field(unsigned int chan,
1836                                          struct fb_bitfield *bf)
1837 {
1838         chan &= 0xffff;
1839         chan >>= 16 - bf->length;
1840         return chan << bf->offset;
1841 }
1842
1843 static int fb_setcolreg(unsigned regno,
1844                                unsigned red, unsigned green, unsigned blue,
1845                                unsigned transp, struct fb_info *info)
1846 {
1847         unsigned int val;
1848
1849         switch (info->fix.visual) {
1850         case FB_VISUAL_TRUECOLOR:
1851                 /* true-colour, use pseudo-palette */
1852                 if (regno < 16) {
1853                         u32 *pal = info->pseudo_palette;
1854                         val  = chan_to_field(red,   &info->var.red);
1855                         val |= chan_to_field(green, &info->var.green);
1856                         val |= chan_to_field(blue,  &info->var.blue);
1857                         pal[regno] = val;
1858                 }
1859                 break;
1860         default:
1861                 return -1;      /* unknown type */
1862         }
1863
1864         return 0;
1865 }
1866
1867 static struct fb_ops fb_ops = {
1868         .owner          = THIS_MODULE,
1869         .fb_open        = rk_fb_open,
1870         .fb_release     = rk_fb_close,
1871         .fb_check_var   = rk_fb_check_var,
1872         .fb_set_par     = rk_fb_set_par,
1873         .fb_blank       = rk_fb_blank,
1874         .fb_ioctl       = rk_fb_ioctl,
1875         .fb_pan_display = rk_pan_display,
1876         .fb_read        = rk_fb_read,
1877         .fb_write       = rk_fb_write,
1878         .fb_setcolreg   = fb_setcolreg,
1879         .fb_fillrect    = cfb_fillrect,
1880         .fb_copyarea    = cfb_copyarea,
1881         .fb_imageblit   = cfb_imageblit,
1882 };
1883
1884
1885
1886 static struct fb_var_screeninfo def_var = {
1887 #if defined(CONFIG_LOGO_LINUX_BMP)
1888         .red            = {16, 8, 0},
1889         .green          = {8, 8, 0},
1890         .blue           = {0, 8, 0},
1891         .transp         = {0, 0, 0},
1892         .nonstd         = HAL_PIXEL_FORMAT_BGRA_8888,
1893 #else
1894         .red            = {11, 5, 0},
1895         .green          = {5, 6, 0},
1896         .blue           = {0, 5, 0},
1897         .transp         = {0, 0, 0},
1898         .nonstd         = HAL_PIXEL_FORMAT_RGB_565,   /*(ypos<<20+xpos<<8+format) format*/
1899 #endif
1900         .grayscale      = 0,  /*(ysize<<20+xsize<<8)*/
1901         .activate       = FB_ACTIVATE_NOW,
1902         .accel_flags    = 0,
1903         .vmode          = FB_VMODE_NONINTERLACED,
1904 };
1905
1906 static struct fb_fix_screeninfo def_fix = {
1907         .type            = FB_TYPE_PACKED_PIXELS,
1908         .type_aux        = 0,
1909         .xpanstep        = 1,
1910         .ypanstep        = 1,
1911         .ywrapstep       = 0,
1912         .accel           = FB_ACCEL_NONE,
1913         .visual          = FB_VISUAL_TRUECOLOR,
1914
1915 };
1916
1917
1918 static int rk_fb_wait_for_vsync_thread(void *data)
1919 {
1920         struct rk_lcdc_driver  *dev_drv = data;
1921         struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
1922         struct fb_info *fbi = rk_fb->fb[0];
1923
1924         while (!kthread_should_stop()) {
1925                 ktime_t timestamp = dev_drv->vsync_info.timestamp;
1926                 int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
1927                         !ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
1928                         (dev_drv->vsync_info.active || dev_drv->vsync_info.irq_stop));
1929
1930                 if (!ret)
1931                         sysfs_notify(&fbi->dev->kobj, NULL, "vsync");
1932         }
1933
1934         return 0;
1935 }
1936
1937 static ssize_t rk_fb_vsync_show(struct device *dev,
1938                 struct device_attribute *attr, char *buf)
1939 {
1940         struct fb_info *fbi = dev_get_drvdata(dev);
1941         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
1942         return scnprintf(buf, PAGE_SIZE, "%llu\n",
1943                         ktime_to_ns(dev_drv->vsync_info.timestamp));
1944 }
1945
1946 static DEVICE_ATTR(vsync, S_IRUGO, rk_fb_vsync_show, NULL);
1947
1948
1949 /*****************************************************************
1950 this two function is for other module that in the kernel which
1951 need show image directly through fb
1952 fb_id:we have 4 fb here,default we use fb0 for ui display
1953 *******************************************************************/
1954 struct fb_info *rk_get_fb(int fb_id)
1955 {
1956         struct rk_fb *inf =  platform_get_drvdata(fb_pdev);
1957         struct fb_info *fb = inf->fb[fb_id];
1958         return fb;
1959 }
1960 EXPORT_SYMBOL(rk_get_fb);
1961
1962 void rk_direct_fb_show(struct fb_info *fbi)
1963 {
1964         rk_fb_set_par(fbi);
1965         rk_pan_display(&fbi->var, fbi);
1966 }
1967 EXPORT_SYMBOL(rk_direct_fb_show);
1968
1969
1970 static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var,
1971                                         struct fb_var_screeninfo *hdmi_var)
1972 {
1973         if (pmy_var->xres < pmy_var->yres) {  /*vertical  lcd screen*/
1974                 hdmi_var->xres = pmy_var->yres;
1975                 hdmi_var->yres = pmy_var->xres;
1976                 hdmi_var->xres_virtual = pmy_var->yres;
1977         } else {
1978                 hdmi_var->xres = pmy_var->xres;
1979                 hdmi_var->yres = pmy_var->yres;
1980                 hdmi_var->xres_virtual = pmy_var->xres_virtual;
1981         }
1982
1983         return 0;
1984
1985 }
1986 int rk_fb_dpi_open(bool open)
1987 {
1988         struct rk_lcdc_driver *dev_drv = NULL;
1989         dev_drv = rk_get_prmry_lcdc_drv();
1990         dev_drv->ops->dpi_open(dev_drv, open);
1991
1992         return 0;
1993 }
1994 int rk_fb_dpi_win_sel(int win_id)
1995 {
1996         struct rk_lcdc_driver *dev_drv = NULL;
1997         dev_drv = rk_get_prmry_lcdc_drv();
1998         dev_drv->ops->dpi_win_sel(dev_drv, win_id);
1999
2000         return 0;
2001 }
2002 int rk_fb_dpi_status(void)
2003 {
2004         int ret;
2005         struct rk_lcdc_driver *dev_drv = NULL;
2006         dev_drv = rk_get_prmry_lcdc_drv();
2007         ret = dev_drv->ops->dpi_status(dev_drv);
2008
2009         return ret;
2010 }
2011
2012 /******************************************
2013 *function:this function will be called by hdmi,when
2014 *             hdmi plug in/out
2015 *screen: the screen attached to hdmi
2016 *enable: 1,hdmi plug in,0,hdmi plug out
2017 *lcdc_id: the lcdc id the hdmi attached ,0 or 1
2018 ******************************************/
2019 int rk_fb_switch_screen(struct rk_screen *screen , int enable, int lcdc_id)
2020 {
2021         struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
2022         struct fb_info *info = NULL;
2023         struct rk_lcdc_driver *dev_drv = NULL;
2024         struct fb_var_screeninfo *hdmi_var    = NULL;
2025         struct fb_var_screeninfo *pmy_var = NULL;      /*var for primary screen*/
2026         struct fb_info *pmy_info = NULL;
2027         struct fb_fix_screeninfo *pmy_fix = NULL;
2028         int i;
2029         struct fb_fix_screeninfo *hdmi_fix    = NULL;
2030         char name[6];
2031         int ret;
2032         int win_id;
2033
2034         //if (rk_fb->disp_mode != DUAL)
2035         //      rk29_backlight_set(0);
2036
2037         sprintf(name, "lcdc%d", lcdc_id);
2038
2039         if (rk_fb->disp_mode != DUAL) {
2040                 dev_drv = rk_fb->lcdc_dev_drv[0];
2041         } else {
2042
2043                 for (i = 0; i < rk_fb->num_lcdc; i++) {
2044                         if (rk_fb->lcdc_dev_drv[i]->prop == EXTEND) {
2045                                 dev_drv = rk_fb->lcdc_dev_drv[i];
2046                                 break;
2047                         }
2048                 }
2049
2050                 if (i == rk_fb->num_lcdc) {
2051                         printk(KERN_ERR "%s driver not found!", name);
2052                         return -ENODEV;
2053                 }
2054         }
2055         printk("hdmi %s lcdc%d\n", enable ? "connect to" : "remove from", dev_drv->id);
2056
2057         if (rk_fb->num_lcdc == 1)
2058                 info = rk_fb->fb[0];
2059         else if (rk_fb->num_lcdc == 2)
2060                 info = rk_fb->fb[dev_drv->lcdc_win_num]; /*the main fb of lcdc1*/
2061
2062         if (dev_drv->screen1) { /*device like rk2928 ,have only one lcdc but two outputs*/
2063                 if (enable) {
2064                         memcpy(dev_drv->screen1, screen, sizeof(struct rk_screen));
2065                         dev_drv->screen1->lcdc_id = 0; /*connect screen1 to output interface 0*/
2066                         dev_drv->screen1->screen_id = 1;
2067                         dev_drv->screen0->lcdc_id = 1; /*connect screen0 to output interface 1*/
2068                         dev_drv->cur_screen = dev_drv->screen1;
2069                         dev_drv->screen0->ext_screen = dev_drv->screen1;
2070                         if (dev_drv->screen0->sscreen_get) {
2071                                 dev_drv->screen0->sscreen_get(dev_drv->screen0,
2072                                         dev_drv->cur_screen->hdmi_resolution);
2073                         }
2074
2075
2076                 } else {
2077                         dev_drv->screen1->lcdc_id = 1; /*connect screen1 to output interface 1*/
2078                         dev_drv->screen0->lcdc_id = 0; /*connect screen0 to output interface 0*/
2079                         dev_drv->cur_screen = dev_drv->screen0;
2080                         dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen,
2081                                         dev_drv->screen_ctr_info->lcd_info);
2082                 }
2083         } else{
2084                 if (enable)
2085                         memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
2086         }
2087
2088
2089         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
2090
2091         if (!enable && !dev_drv->screen1) { /*only double lcdc device need to close*/
2092                 if (dev_drv->win[win_id]->state)
2093                         dev_drv->ops->open(dev_drv, win_id, enable); /*disable the win which attached to this fb*/
2094                 hdmi_switch_complete = 0;
2095
2096                 return 0;
2097         }
2098
2099         hdmi_var = &info->var;
2100         hdmi_fix = &info->fix;
2101         if (rk_fb->disp_mode  == DUAL) {
2102                 if (likely(rk_fb->num_lcdc == 2)) {
2103                         pmy_var = &rk_fb->fb[0]->var;
2104                         pmy_fix = &rk_fb->fb[0]->fix;
2105                         set_xact_yact_for_hdmi(pmy_var, hdmi_var);
2106                         hdmi_var->nonstd &= 0xffffff00;
2107                         hdmi_var->nonstd |= (pmy_var->nonstd & 0xff); /*use the same format as primary screen*/
2108                 } else {
2109                         printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!", __func__);
2110                 }
2111         }
2112         hdmi_var->grayscale &= 0xff;
2113         hdmi_var->grayscale |= (dev_drv->cur_screen->mode.xres<<8) + (dev_drv->cur_screen->mode.yres<<20);
2114         if (dev_drv->screen1) { /*device like rk2928,whic have one lcdc but two outputs*/
2115         /*      info->var.nonstd &= 0xff;
2116                 info->var.nonstd |= (dev_drv->cur_screen->mode.xpos<<8) + (dev_drv->cur_screen->mode.ypos<<20);
2117                 info->var.grayscale &= 0xff;
2118                 info->var.grayscale |= (dev_drv->cur_screen->mode.x_res<<8) + (dev_drv->cur_screen->mode.y_res<<20);*/
2119                 dev_drv->screen1->xsize = dev_drv->cur_screen->mode.xres;
2120                 dev_drv->screen1->ysize = dev_drv->cur_screen->mode.yres;
2121                 dev_drv->screen1->xpos = 0;
2122                 dev_drv->screen1->ypos = 0;
2123         }
2124
2125         ret = info->fbops->fb_open(info, 1);
2126         dev_drv->ops->load_screen(dev_drv, 1);
2127         ret = info->fbops->fb_set_par(info);
2128         if (dev_drv->ops->lcdc_hdmi_process)
2129                 dev_drv->ops->lcdc_hdmi_process(dev_drv, enable);
2130
2131         if (rk_fb->disp_mode == DUAL) {
2132                 if (likely(rk_fb->num_lcdc == 2)) {
2133                         pmy_info = rk_fb->fb[0];
2134                         pmy_info->fbops->fb_pan_display(pmy_var, pmy_info);
2135                 } else {
2136                         printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!", __func__);
2137                 }
2138         } else {
2139                 info->fbops->fb_pan_display(hdmi_var, info);
2140         }
2141         info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0);
2142         if (dev_drv->screen1) {
2143                 if (dev_drv->screen0->sscreen_set) {
2144                         dev_drv->ops->blank(dev_drv, 0, FB_BLANK_NORMAL);
2145                         msleep(100);
2146                         dev_drv->screen0->sscreen_set(dev_drv->screen0, enable);
2147                         dev_drv->ops->blank(dev_drv, 0, FB_BLANK_UNBLANK);
2148                 }
2149         }
2150
2151         //if (rk_fb->disp_mode != DUAL)
2152         //      rk29_backlight_set(1);
2153         hdmi_switch_complete = enable;
2154         return 0;
2155
2156 }
2157
2158
2159
2160
2161 /******************************************
2162 function:this function current only called by hdmi for
2163         scale the display
2164 scale_x: scale rate of x resolution
2165 scale_y: scale rate of y resolution
2166 lcdc_id: the lcdc id the hdmi attached ,0 or 1
2167 ******************************************/
2168
2169 int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
2170 {
2171         struct rk_fb *inf =  platform_get_drvdata(fb_pdev);
2172         struct fb_info *info = NULL;
2173         struct fb_var_screeninfo *var = NULL;
2174         struct rk_lcdc_driver *dev_drv = NULL;
2175         u16 screen_x, screen_y;
2176         u16 xpos, ypos;
2177         u16 xsize, ysize;
2178         char name[6];
2179         int i = 0;
2180         sprintf(name, "lcdc%d", lcdc_id);
2181
2182 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
2183         dev_drv = inf->lcdc_dev_drv[0];
2184 #else
2185         for (i = 0; i < inf->num_lcdc; i++) {
2186                 if (inf->lcdc_dev_drv[i]->prop == EXTEND) {
2187                         dev_drv = inf->lcdc_dev_drv[i];
2188                         break;
2189                 }
2190         }
2191
2192         if (i == inf->num_lcdc) {
2193                 printk(KERN_ERR "%s driver not found!", name);
2194                 return -ENODEV;
2195
2196         }
2197 #endif
2198         if (inf->num_lcdc == 1)
2199                 info = inf->fb[0];
2200         else if (inf->num_lcdc == 2)
2201                 info = inf->fb[dev_drv->lcdc_win_num];
2202
2203         var = &info->var;
2204         screen_x = dev_drv->cur_screen->mode.xres;
2205         screen_y = dev_drv->cur_screen->mode.yres;
2206
2207 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP)
2208         if (dev_drv->cur_screen->screen_id == 1) {
2209                 dev_drv->cur_screen->xpos = (screen_x-screen_x*scale_x/100)>>1;
2210                 dev_drv->cur_screen->ypos = (screen_y-screen_y*scale_y/100)>>1;
2211                 dev_drv->cur_screen->xsize = screen_x*scale_x/100;
2212                 dev_drv->cur_screen->ysize = screen_y*scale_y/100;
2213         } else
2214 #endif
2215         {
2216                 xpos = (screen_x-screen_x*scale_x/100)>>1;
2217                 ypos = (screen_y-screen_y*scale_y/100)>>1;
2218                 xsize = screen_x*scale_x/100;
2219                 ysize = screen_y*scale_y/100;
2220                 var->nonstd &= 0xff;
2221                 var->nonstd |= (xpos<<8) + (ypos<<20);
2222                 var->grayscale &= 0xff;
2223                 var->grayscale |= (xsize<<8) + (ysize<<20);
2224         }
2225
2226         info->fbops->fb_set_par(info);
2227         info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0);
2228         return 0;
2229
2230
2231 }
2232
2233 static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
2234 {
2235         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
2236         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
2237         struct rk_lcdc_win *win = NULL;
2238         int win_id;
2239         int ret = 0;
2240         unsigned long fb_mem_size;
2241 #if defined(CONFIG_ION_ROCKCHIP)
2242         struct ion_handle *handle;
2243         ion_phys_addr_t phy_addr;
2244         size_t len;
2245 #else
2246         dma_addr_t fb_mem_phys;
2247         void *fb_mem_virt;
2248 #endif
2249         win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
2250         if (win_id < 0)
2251                 return  -ENODEV;
2252         else
2253                 win = dev_drv->win[win_id];
2254
2255         if (!strcmp(fbi->fix.id, "fb0")) {
2256                 fb_mem_size = 3 * (fbi->var.xres * fbi->var.yres) << 2;
2257                 fb_mem_size = ALIGN(fb_mem_size, SZ_1M);
2258 #if defined(CONFIG_ION_ROCKCHIP)
2259                 handle = ion_alloc(rk_fb->ion_client, (size_t)fb_mem_size, 0, ION_HEAP(ION_CMA_HEAP_ID), 0);
2260                 if (IS_ERR(handle)) {
2261                         dev_err(fbi->device, "failed to ion_alloc:%ld\n",PTR_ERR(handle));
2262                         return -ENOMEM;
2263                 }
2264                 win->area[0].ion_hdl = handle;
2265                 fbi->screen_base = ion_map_kernel(rk_fb->ion_client, handle);
2266                 ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
2267                 fbi->fix.smem_start = phy_addr;
2268                 fbi->fix.smem_len = len;
2269                 printk("alloc_buffer:smem_start=0x%x\n",phy_addr);
2270 #else
2271
2272                 fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size, &fb_mem_phys,
2273                         GFP_KERNEL);
2274                 if (!fb_mem_virt) {
2275                         pr_err("%s: Failed to allocate framebuffer\n", __func__);
2276                         return -ENOMEM;
2277                 }
2278                 fbi->fix.smem_len = fb_mem_size;
2279                 fbi->fix.smem_start = fb_mem_phys;
2280                 fbi->screen_base = fb_mem_virt;
2281 #endif
2282                 memset(fbi->screen_base, 0, fbi->fix.smem_len);
2283                 printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
2284                 fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
2285         } else {
2286 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
2287                 res = platform_get_resource_byname(fb_pdev,
2288                         IORESOURCE_MEM, "fb2 buf");
2289                 if (res == NULL) {
2290                         dev_err(&fb_pdev->dev, "failed to get win0 memory \n");
2291                         ret = -ENOENT;
2292                 }
2293                 fbi->fix.smem_start = res->start;
2294                 fbi->fix.smem_len = res->end - res->start + 1;
2295                 mem = request_mem_region(res->start, resource_size(res),
2296                         fb_pdev->name);
2297                 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
2298                 memset(fbi->screen_base, 0, fbi->fix.smem_len);
2299 #else    /*three buffer no need to copy*/
2300                 fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start;
2301                 fbi->fix.smem_len   = rk_fb->fb[0]->fix.smem_len;
2302                 fbi->screen_base    = rk_fb->fb[0]->screen_base;
2303 #endif
2304                 printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
2305                         fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
2306         }
2307
2308         fbi->screen_size = fbi->fix.smem_len;
2309         win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
2310         if (win_id >= 0) {
2311                 win = dev_drv->win[win_id];
2312                 win->reserved = fbi->fix.smem_start;
2313         }
2314
2315         return ret;
2316 }
2317
2318 static int rk_release_fb_buffer(struct fb_info *fbi)
2319 {
2320         if (!strcmp(fbi->fix.id, "fb1") || !strcmp(fbi->fix.id, "fb3"))  /*buffer for fb1 and fb3 are alloc by android*/
2321                 return 0;
2322         iounmap(fbi->screen_base);
2323         release_mem_region(fbi->fix.smem_start, fbi->fix.smem_len);
2324         return 0;
2325
2326 }
2327 static int init_lcdc_win(struct rk_lcdc_driver *dev_drv, struct rk_lcdc_win *def_win)
2328 {
2329         int i;
2330         int lcdc_win_num = dev_drv->lcdc_win_num;
2331         for (i = 0; i < lcdc_win_num; i++) {
2332                 struct rk_lcdc_win *win = NULL;
2333                 win =  kzalloc(sizeof(struct rk_lcdc_win), GFP_KERNEL);
2334                 if (!win) {
2335                         dev_err(dev_drv->dev, "kzmalloc for win fail!");
2336                         return   -ENOMEM;
2337                 }
2338
2339                 strcpy(win->name, def_win->name);
2340                 win->id = def_win->id;
2341                 win->support_3d = def_win->support_3d;
2342                 dev_drv->win[i] = win;
2343         }
2344
2345         return 0;
2346 }
2347
2348
2349 static int init_lcdc_device_driver(struct rk_fb *rk_fb,
2350                                         struct rk_lcdc_win *def_win, int index)
2351 {
2352         struct rk_lcdc_driver *dev_drv = rk_fb->lcdc_dev_drv[index];
2353         struct rk_screen *screen = devm_kzalloc(dev_drv->dev,
2354                                 sizeof(struct rk_screen), GFP_KERNEL);
2355         if (!screen) {
2356                 dev_err(dev_drv->dev, "malloc screen for lcdc%d fail!",
2357                                         dev_drv->id);
2358                 return -ENOMEM;
2359         }
2360         
2361         screen->screen_id = 0;
2362         screen->lcdc_id = dev_drv->id;
2363         dev_drv->screen0 = screen;
2364         dev_drv->cur_screen = screen;
2365         /* devie use one lcdc + rk61x scaler for dual display*/
2366         if (rk_fb->disp_mode == ONE_DUAL) {
2367                 struct rk_screen *screen1 = devm_kzalloc(dev_drv->dev,
2368                                                 sizeof(struct rk_screen), GFP_KERNEL);
2369                 if (screen1) {
2370                         dev_err(dev_drv->dev, "malloc screen1 for lcdc%d fail!",
2371                                                 dev_drv->id);
2372                         return -ENOMEM;
2373                 }
2374                 screen1->screen_id = 1;
2375                 screen1->lcdc_id = 1;
2376                 dev_drv->screen1 = screen1;
2377         }
2378         sprintf(dev_drv->name, "lcdc%d", dev_drv->id);
2379         init_lcdc_win(dev_drv, def_win);
2380         init_completion(&dev_drv->frame_done);
2381         spin_lock_init(&dev_drv->cpl_lock);
2382         mutex_init(&dev_drv->fb_win_id_mutex);
2383         dev_drv->ops->fb_win_remap(dev_drv, FB_DEFAULT_ORDER);
2384         dev_drv->first_frame = 1;
2385         rk_disp_pwr_ctr_parse_dt(dev_drv);
2386         if (dev_drv->prop == PRMRY)
2387                 rk_fb_get_prmry_screen(screen);
2388         dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
2389
2390         return 0;
2391 }
2392
2393 #ifdef CONFIG_LOGO_LINUX_BMP
2394 static struct linux_logo *bmp_logo;
2395 static int fb_prewine_bmp_logo(struct fb_info *info, int rotate)
2396 {
2397         bmp_logo = fb_find_logo(24);
2398         if (bmp_logo == NULL) {
2399                 printk(KERN_INFO "%s error\n", __func__);
2400                 return 0;
2401         }
2402         return 1;
2403 }
2404
2405 static void fb_show_bmp_logo(struct fb_info *info, int rotate)
2406 {
2407         unsigned char *src = bmp_logo->data;
2408         unsigned char *dst = info->screen_base;
2409         int i;
2410         unsigned int Needwidth = (*(src-24)<<8) | (*(src-23));
2411         unsigned int Needheight = (*(src-22)<<8) | (*(src-21));
2412
2413         for (i = 0; i < Needheight; i++)
2414                 memcpy(dst+info->var.xres*i*4,
2415                         src+bmp_logo->width*i*4, Needwidth*4);
2416
2417 }
2418 #endif
2419
2420 /********************************
2421 *check if the primary lcdc has registerd,
2422 the primary lcdc mas register first
2423 *********************************/
2424 bool is_prmry_rk_lcdc_registered(void)
2425 {
2426         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
2427         if (rk_fb->lcdc_dev_drv[0])
2428                 return  true;
2429         else
2430                 return false;
2431
2432
2433 }
2434 int rk_fb_register(struct rk_lcdc_driver *dev_drv,
2435                                 struct rk_lcdc_win *win, int id)
2436 {
2437         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
2438         struct fb_info *fbi;
2439         int i = 0, ret = 0, index = 0;
2440
2441         if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
2442                 return -ENXIO;
2443
2444         for (i = 0; i < RK30_MAX_LCDC_SUPPORT; i++) {
2445                 if (!rk_fb->lcdc_dev_drv[i]) {
2446                         rk_fb->lcdc_dev_drv[i] = dev_drv;
2447                         rk_fb->lcdc_dev_drv[i]->id = id;
2448                         rk_fb->num_lcdc++;
2449                         break;
2450                 }
2451         }
2452
2453         index = i;
2454         init_lcdc_device_driver(rk_fb, win, index);
2455         dev_drv->fb_index_base = rk_fb->num_fb;
2456         for (i = 0; i < dev_drv->lcdc_win_num; i++) {
2457                 fbi = framebuffer_alloc(0, &fb_pdev->dev);
2458                 if (!fbi) {
2459                         dev_err(&fb_pdev->dev, "fb framebuffer_alloc fail!");
2460                         ret = -ENOMEM;
2461                 }
2462                 fbi->par = dev_drv;
2463                 fbi->var = def_var;
2464                 fbi->fix = def_fix;
2465                 sprintf(fbi->fix.id, "fb%d", rk_fb->num_fb);
2466                 fb_videomode_to_var(&fbi->var, &dev_drv->cur_screen->mode);
2467                 fbi->var.grayscale |= (fbi->var.xres<<8) + (fbi->var.yres<<20);
2468 #if defined(CONFIG_LOGO_LINUX_BMP)
2469                 fbi->var.bits_per_pixel = 32;
2470 #else
2471                 fbi->var.bits_per_pixel = 16;
2472 #endif
2473                 fbi->fix.line_length  = (fbi->var.xres)*(fbi->var.bits_per_pixel>>3);
2474                 fbi->var.width = dev_drv->cur_screen->width;
2475                 fbi->var.height = dev_drv->cur_screen->height;
2476                 fbi->var.pixclock = dev_drv->pixclock;
2477                 fbi->fbops = &fb_ops;
2478                 fbi->flags = FBINFO_FLAG_DEFAULT;
2479                 fbi->pseudo_palette = dev_drv->win[i]->pseudo_pal;
2480                 if (i == 0) /* only alloc memory for main fb*/
2481                         rk_fb_alloc_buffer(fbi, rk_fb->num_fb);
2482                 ret = register_framebuffer(fbi);
2483                 if (ret < 0) {
2484                         dev_err(&fb_pdev->dev, "%s fb%d register_framebuffer fail!\n",
2485                                         __func__, rk_fb->num_fb);
2486                         return ret;
2487                 }
2488                 rkfb_create_sysfs(fbi);
2489                 rk_fb->fb[rk_fb->num_fb] = fbi;
2490                 dev_info(&fb_pdev->dev, "rockchip framebuffer registerd:%s\n",
2491                                         fbi->fix.id);
2492                 rk_fb->num_fb++;
2493
2494                 if (i == 0) {
2495                         init_waitqueue_head(&dev_drv->vsync_info.wait);
2496                         ret = device_create_file(fbi->dev, &dev_attr_vsync);
2497                         if (ret)
2498                                 dev_err(fbi->dev, "failed to create vsync file\n");
2499                         dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
2500                                                                 dev_drv, "fb-vsync");
2501                         if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM)) {
2502                                 dev_err(fbi->dev, "failed to run vsync thread\n");
2503                                 dev_drv->vsync_info.thread = NULL;
2504                         }
2505                         dev_drv->vsync_info.active = 1;
2506
2507                         mutex_init(&dev_drv->output_lock);
2508
2509                         INIT_LIST_HEAD(&dev_drv->update_regs_list);
2510                         mutex_init(&dev_drv->update_regs_list_lock);
2511                         init_kthread_worker(&dev_drv->update_regs_worker);
2512
2513                         dev_drv->update_regs_thread = kthread_run(kthread_worker_fn,
2514                                         &dev_drv->update_regs_worker, "rk-fb");
2515                         if (IS_ERR(dev_drv->update_regs_thread)) {
2516                                 int err = PTR_ERR(dev_drv->update_regs_thread);
2517                                 dev_drv->update_regs_thread = NULL;
2518
2519                                 printk("failed to run update_regs thread\n");
2520                                 return err;
2521                         }
2522                         init_kthread_work(&dev_drv->update_regs_work, rk_fb_update_regs_handler);
2523
2524                         dev_drv->timeline = sw_sync_timeline_create("fb-timeline");                     dev_drv->timeline_max = 1;
2525                 }
2526
2527         }
2528
2529  /*show logo for primary display device*/
2530 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
2531 if (dev_drv->prop == PRMRY) {
2532         struct fb_info *main_fbi = rk_fb->fb[0];
2533         main_fbi->fbops->fb_open(main_fbi, 1);
2534         main_fbi->fbops->fb_set_par(main_fbi);
2535 #if  defined(CONFIG_LOGO_LINUX_BMP)
2536         if (fb_prewine_bmp_logo(main_fbi, FB_ROTATE_UR)) {
2537                 fb_set_cmap(&main_fbi->cmap, main_fbi);
2538                 fb_show_bmp_logo(main_fbi, FB_ROTATE_UR);
2539                 main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
2540         }
2541 #else
2542         if (fb_prepare_logo(main_fbi, FB_ROTATE_UR)) {
2543                 fb_set_cmap(&main_fbi->cmap, main_fbi);
2544                 fb_show_logo(main_fbi, FB_ROTATE_UR);
2545                 main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
2546         }
2547 #endif
2548         //main_fbi->fbops->fb_ioctl(main_fbi, RK_FBIOSET_CONFIG_DONE, 0);
2549         main_fbi->fbops->fb_set_par(main_fbi);
2550
2551 }
2552 #endif
2553         return 0;
2554
2555
2556 }
2557
2558 int rk_fb_unregister(struct rk_lcdc_driver *dev_drv)
2559 {
2560
2561         struct rk_fb *fb_inf = platform_get_drvdata(fb_pdev);
2562         struct fb_info *fbi;
2563         int fb_index_base = dev_drv->fb_index_base;
2564         int fb_num = dev_drv->lcdc_win_num;
2565         int i = 0;
2566
2567         if (fb_inf->lcdc_dev_drv[i]->vsync_info.thread) {
2568                 fb_inf->lcdc_dev_drv[i]->vsync_info.irq_stop = 1;
2569                 kthread_stop(fb_inf->lcdc_dev_drv[i]->vsync_info.thread);
2570         }
2571
2572         for (i = 0; i < fb_num; i++)
2573                 kfree(dev_drv->win[i]);
2574
2575         for (i = fb_index_base; i < (fb_index_base+fb_num); i++) {
2576                 fbi = fb_inf->fb[i];
2577                 unregister_framebuffer(fbi);
2578                 /*rk_release_fb_buffer(fbi);*/
2579                 framebuffer_release(fbi);
2580         }
2581         fb_inf->lcdc_dev_drv[dev_drv->id] = NULL;
2582         fb_inf->num_lcdc--;
2583
2584         return 0;
2585 }
2586
2587
2588
2589 #if defined(CONFIG_HAS_EARLYSUSPEND)
2590 struct suspend_info {
2591         struct early_suspend early_suspend;
2592         struct rk_fb *inf;
2593 };
2594
2595 static void rkfb_early_suspend(struct early_suspend *h)
2596 {
2597         struct suspend_info *info = container_of(h, struct suspend_info,
2598                                                 early_suspend);
2599         struct rk_fb *inf = info->inf;
2600         int i;
2601         for (i = 0; i < inf->num_lcdc; i++) {
2602                 if (!inf->lcdc_dev_drv[i])
2603                         continue;
2604                 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
2605         }
2606 }
2607 static void rkfb_early_resume(struct early_suspend *h)
2608 {
2609         struct suspend_info *info = container_of(h, struct suspend_info,
2610                                                 early_suspend);
2611         struct rk_fb *inf = info->inf;
2612         int i;
2613         for (i = 0; i < inf->num_lcdc; i++) {
2614                 if (!inf->lcdc_dev_drv[i])
2615                         continue;
2616                 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);
2617         }
2618
2619 }
2620
2621
2622
2623 static struct suspend_info suspend_info = {
2624         .early_suspend.suspend = rkfb_early_suspend,
2625         .early_suspend.resume = rkfb_early_resume,
2626         .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
2627 };
2628 #endif
2629
2630 static int rk_fb_probe(struct platform_device *pdev)
2631 {
2632         struct rk_fb *rk_fb = NULL;
2633         struct device_node *np = pdev->dev.of_node;
2634         u32 mode;
2635
2636         if (!np) {
2637                 dev_err(&pdev->dev, "Missing device tree node.\n");
2638                 return -EINVAL;
2639         }
2640
2641         rk_fb = devm_kzalloc(&pdev->dev, sizeof(struct rk_fb), GFP_KERNEL);
2642         if (!rk_fb) {
2643                 dev_err(&pdev->dev, "kmalloc for rk fb fail!");
2644                 return  -ENOMEM;
2645         }
2646         platform_set_drvdata(pdev, rk_fb);
2647
2648         if (!of_property_read_u32(np, "rockchip,disp-mode", &mode)) {
2649                 rk_fb->disp_mode = mode;
2650
2651         } else {
2652                 dev_err(&pdev->dev, "no disp-mode node found!");
2653                 return -ENODEV;
2654         }
2655         dev_set_name(&pdev->dev, "rockchip-fb");
2656 #if defined(CONFIG_ION_ROCKCHIP)
2657         rk_fb->ion_client = rockchip_ion_client_create("rk_fb");
2658         if (IS_ERR(rk_fb->ion_client)) {
2659                 dev_err(&pdev->dev, "failed to create ion client for rk fb");
2660                 return PTR_ERR(rk_fb->ion_client);
2661         } else {
2662                 dev_info(&pdev->dev, "rk fb ion client create success!\n");
2663         }
2664 #endif
2665
2666 #if defined(CONFIG_HAS_EARLYSUSPEND)
2667         suspend_info.inf = rk_fb;
2668         register_early_suspend(&suspend_info.early_suspend);
2669 #endif
2670         fb_pdev = pdev;
2671         dev_info(&pdev->dev, "rockchip framebuffer driver probe\n");
2672         return 0;
2673 }
2674
2675 static int rk_fb_remove(struct platform_device *pdev)
2676 {
2677         struct rk_fb *rk_fb = platform_get_drvdata(pdev);
2678         kfree(rk_fb);
2679         platform_set_drvdata(pdev, NULL);
2680         return 0;
2681 }
2682
2683 static void rk_fb_shutdown(struct platform_device *pdev)
2684 {
2685         struct rk_fb *rk_fb = platform_get_drvdata(pdev);
2686         int i;
2687         for (i = 0; i < rk_fb->num_lcdc; i++) {
2688                 if (!rk_fb->lcdc_dev_drv[i])
2689                         continue;
2690
2691         }
2692
2693 #if     defined(CONFIG_HAS_EARLYSUSPEND)
2694         unregister_early_suspend(&suspend_info.early_suspend);
2695 #endif
2696 }
2697
2698
2699 static const struct of_device_id rkfb_dt_ids[] = {
2700         { .compatible = "rockchip,rk-fb", },
2701         {}
2702 };
2703
2704 static struct platform_driver rk_fb_driver = {
2705         .probe          = rk_fb_probe,
2706         .remove         = rk_fb_remove,
2707         .driver         = {
2708                 .name   = "rk-fb",
2709                 .owner  = THIS_MODULE,
2710                 .of_match_table = of_match_ptr(rkfb_dt_ids),
2711         },
2712         .shutdown   = rk_fb_shutdown,
2713 };
2714
2715 static int __init rk_fb_init(void)
2716 {
2717         return platform_driver_register(&rk_fb_driver);
2718 }
2719
2720 static void __exit rk_fb_exit(void)
2721 {
2722         platform_driver_unregister(&rk_fb_driver);
2723 }
2724
2725 subsys_initcall_sync(rk_fb_init);
2726 module_exit(rk_fb_exit);