rk fb: define data format for fbdc
[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 <linux/vmalloc.h>
28 #include <asm/div64.h>
29 #include <linux/uaccess.h>
30 #include <linux/rk_fb.h>
31 #include <linux/linux_logo.h>
32 #include <linux/dma-mapping.h>
33 #include <linux/regulator/consumer.h>
34
35 #include "bmp_helper.h"
36
37 #if defined(CONFIG_RK_HDMI)
38 #include "hdmi/rk_hdmi.h"
39 #endif
40
41 #if defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
42 #include "rga/rga.h"
43 #endif
44
45 #ifdef CONFIG_OF
46 #include <linux/of.h>
47 #include <linux/of_platform.h>
48 #include <linux/of_gpio.h>
49 #include <video/of_display_timing.h>
50 #include <video/display_timing.h>
51 #include <dt-bindings/rkfb/rk_fb.h>
52 #endif
53
54 #if defined(CONFIG_ION_ROCKCHIP)
55 #include <linux/rockchip_ion.h>
56 #include <linux/rockchip-iovmm.h>
57 #include <linux/dma-buf.h>
58 #include <linux/highmem.h>
59 #endif
60
61 #define H_USE_FENCE 1
62 static int hdmi_switch_complete;
63 static struct platform_device *fb_pdev;
64 struct list_head saved_list;
65
66 #if defined(CONFIG_FB_MIRRORING)
67 int (*video_data_to_mirroring) (struct fb_info *info, u32 yuv_phy[2]);
68 EXPORT_SYMBOL(video_data_to_mirroring);
69 #endif
70
71 extern phys_addr_t uboot_logo_base;
72 extern phys_addr_t uboot_logo_size;
73 extern phys_addr_t uboot_logo_offset;
74 static struct rk_fb_trsm_ops *trsm_lvds_ops;
75 static struct rk_fb_trsm_ops *trsm_edp_ops;
76 static struct rk_fb_trsm_ops *trsm_mipi_ops;
77 static int uboot_logo_on;
78 int support_uboot_display(void)
79 {
80         return uboot_logo_on;
81 }
82
83 int rk_fb_get_display_policy(void)
84 {
85         struct rk_fb *rk_fb;
86
87         if (fb_pdev) {
88                 rk_fb = platform_get_drvdata(fb_pdev);
89                 return rk_fb->disp_policy;
90         } else {
91                 return DISPLAY_POLICY_SDK;
92         }
93 }
94
95 int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
96 {
97         switch (type) {
98         case SCREEN_RGB:
99         case SCREEN_LVDS:
100         case SCREEN_DUAL_LVDS:
101                 trsm_lvds_ops = ops;
102                 break;
103         case SCREEN_EDP:
104                 trsm_edp_ops = ops;
105                 break;
106         case SCREEN_MIPI:
107         case SCREEN_DUAL_MIPI:
108                 trsm_mipi_ops = ops;
109                 break;
110         default:
111                 printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
112                        __func__, type);
113                 break;
114         }
115         return 0;
116 }
117
118 struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
119 {
120         struct rk_fb_trsm_ops *ops;
121         switch (type) {
122         case SCREEN_RGB:
123         case SCREEN_LVDS:
124         case SCREEN_DUAL_LVDS:
125                 ops = trsm_lvds_ops;
126                 break;
127         case SCREEN_EDP:
128                 ops = trsm_edp_ops;
129                 break;
130         case SCREEN_MIPI:
131         case SCREEN_DUAL_MIPI:
132                 ops = trsm_mipi_ops;
133                 break;
134         default:
135                 ops = NULL;
136                 printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
137                        __func__, type);
138                 break;
139         }
140         return ops;
141 }
142
143 int rk_fb_pixel_width(int data_format)
144 {
145         int pixel_width;
146         switch (data_format) {
147         case XBGR888:
148         case ABGR888:
149         case ARGB888:
150         case FBDC_ARGB_888:
151         case FBDC_RGBX_888:
152                 pixel_width = 4 * 8;
153                 break;
154         case RGB888:
155                 pixel_width = 3 * 8;
156                 break;
157         case RGB565:
158         case FBDC_RGB_565:
159                 pixel_width = 2 * 8;
160                 break;
161         case YUV422:
162         case YUV420:
163         case YUV444:
164                 pixel_width = 1 * 8;
165                 break;
166         case YUV422_A:
167         case YUV420_A:
168         case YUV444_A:
169                 pixel_width = 8;
170                 break;
171         default:
172                 printk(KERN_WARNING "%s:un supported format:0x%x\n",
173                        __func__, data_format);
174                 return -EINVAL;
175         }
176         return pixel_width;
177 }
178
179 static int rk_fb_data_fmt(int data_format, int bits_per_pixel)
180 {
181         int fb_data_fmt;
182         if (data_format) {
183                 switch (data_format) {
184                 case HAL_PIXEL_FORMAT_RGBX_8888:
185                         fb_data_fmt = XBGR888;
186                         break;
187                 case HAL_PIXEL_FORMAT_RGBA_8888:
188                         fb_data_fmt = ABGR888;
189                         break;
190                 case HAL_PIXEL_FORMAT_BGRA_8888:
191                         fb_data_fmt = ARGB888;
192                         break;
193                 case HAL_PIXEL_FORMAT_RGB_888:
194                         fb_data_fmt = RGB888;
195                         break;
196                 case HAL_PIXEL_FORMAT_RGB_565:
197                         fb_data_fmt = RGB565;
198                         break;
199                 case HAL_PIXEL_FORMAT_YCbCr_422_SP:     /* yuv422 */
200                         fb_data_fmt = YUV422;
201                         break;
202                 case HAL_PIXEL_FORMAT_YCrCb_NV12:       /* YUV420---uvuvuv */
203                         fb_data_fmt = YUV420;
204                         break;
205                 case HAL_PIXEL_FORMAT_YCrCb_444:        /* yuv444 */
206                         fb_data_fmt = YUV444;
207                         break;
208                 case HAL_PIXEL_FORMAT_YCrCb_NV12_10:    /* yuv444 */
209                         fb_data_fmt = YUV420_A;
210                         break;
211                 case HAL_PIXEL_FORMAT_YCbCr_422_SP_10:  /* yuv444 */
212                         fb_data_fmt = YUV422_A;
213                         break;
214                 case HAL_PIXEL_FORMAT_YCrCb_420_SP_10:  /* yuv444 */
215                         fb_data_fmt = YUV444_A;
216                         break;
217                 case HAL_PIXEL_FORMAT_FBDC_RGB565:      /* fbdc rgb565*/
218                         fb_data_fmt = FBDC_RGB_565;
219                         break;
220                 case HAL_PIXEL_FORMAT_FBDC_U8U8U8U8:    /* fbdc argb888 */
221                         fb_data_fmt = FBDC_ARGB_888;
222                         break;
223                 case HAL_PIXEL_FORMAT_FBDC_U8U8U8:      /* fbdc rgb888 */
224                         fb_data_fmt = FBDC_RGBX_888;
225                         break;
226                 default:
227                         printk(KERN_WARNING "%s:un supported format:0x%x\n",
228                                __func__, data_format);
229                         return -EINVAL;
230                 }
231         } else {
232                 switch (bits_per_pixel) {
233                 case 32:
234                         fb_data_fmt = ARGB888;
235                         break;
236                 case 24:
237                         fb_data_fmt = RGB888;
238                         break;
239                 case 16:
240                         fb_data_fmt = RGB565;
241                         break;
242                 default:
243                         printk(KERN_WARNING
244                                "%s:un supported bits_per_pixel:%d\n", __func__,
245                                bits_per_pixel);
246                         break;
247                 }
248         }
249         return fb_data_fmt;
250 }
251
252 /*
253  * rk display power control parse from dts
254  */
255 int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
256 {
257         struct device_node *root = of_get_child_by_name(dev_drv->dev->of_node,
258                                                         "power_ctr");
259         struct device_node *child;
260         struct rk_disp_pwr_ctr_list *pwr_ctr;
261         struct list_head *pos;
262         enum of_gpio_flags flags;
263         u32 val = 0;
264         u32 debug = 0;
265         int ret;
266
267         INIT_LIST_HEAD(&dev_drv->pwrlist_head);
268         if (!root) {
269                 dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",
270                         dev_drv->id);
271                 return -ENODEV;
272         }
273
274         for_each_child_of_node(root, child) {
275                 pwr_ctr = kmalloc(sizeof(struct rk_disp_pwr_ctr_list),
276                                   GFP_KERNEL);
277                 strcpy(pwr_ctr->pwr_ctr.name, child->name);
278                 if (!of_property_read_u32(child, "rockchip,power_type", &val)) {
279                         if (val == GPIO) {
280                                 pwr_ctr->pwr_ctr.type = GPIO;
281                                 pwr_ctr->pwr_ctr.gpio = of_get_gpio_flags(child, 0, &flags);
282                                 if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
283                                         dev_err(dev_drv->dev, "%s ivalid gpio\n",
284                                                 child->name);
285                                         return -EINVAL;
286                                 }
287                                 pwr_ctr->pwr_ctr.atv_val = !(flags & OF_GPIO_ACTIVE_LOW);
288                                 ret = gpio_request(pwr_ctr->pwr_ctr.gpio,
289                                                    child->name);
290                                 if (ret) {
291                                         dev_err(dev_drv->dev,
292                                                 "request %s gpio fail:%d\n",
293                                                 child->name, ret);
294                                 }
295
296                         } else {
297                                 pwr_ctr->pwr_ctr.type = REGULATOR;
298                                 pwr_ctr->pwr_ctr.rgl_name = NULL;
299                                 ret = of_property_read_string(child, "rockchip,regulator_name",
300                                                              &(pwr_ctr->pwr_ctr.rgl_name));
301                                 if (ret || IS_ERR_OR_NULL(pwr_ctr->pwr_ctr.rgl_name))
302                                         dev_err(dev_drv->dev, "get regulator name failed!\n");
303                                 if (!of_property_read_u32(child, "rockchip,regulator_voltage", &val))
304                                         pwr_ctr->pwr_ctr.volt = val;
305                                 else
306                                         pwr_ctr->pwr_ctr.volt = 0;
307                         }
308                 };
309
310                 if (!of_property_read_u32(child, "rockchip,delay", &val))
311                         pwr_ctr->pwr_ctr.delay = val;
312                 else
313                         pwr_ctr->pwr_ctr.delay = 0;
314                 list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
315         }
316
317         of_property_read_u32(root, "rockchip,debug", &debug);
318
319         if (debug) {
320                 list_for_each(pos, &dev_drv->pwrlist_head) {
321                         pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list,
322                                              list);
323                         printk(KERN_INFO "pwr_ctr_name:%s\n"
324                                "pwr_type:%s\n"
325                                "gpio:%d\n"
326                                "atv_val:%d\n"
327                                "delay:%d\n\n",
328                                pwr_ctr->pwr_ctr.name,
329                                (pwr_ctr->pwr_ctr.type == GPIO) ? "gpio" : "regulator",
330                                pwr_ctr->pwr_ctr.gpio,
331                                pwr_ctr->pwr_ctr.atv_val,
332                                pwr_ctr->pwr_ctr.delay);
333                 }
334         }
335
336         return 0;
337
338 }
339
340 int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv)
341 {
342         struct list_head *pos;
343         struct rk_disp_pwr_ctr_list *pwr_ctr_list;
344         struct pwr_ctr *pwr_ctr;
345         struct regulator *regulator_lcd = NULL;
346         int count = 10;
347
348         if (list_empty(&dev_drv->pwrlist_head))
349                 return 0;
350         list_for_each(pos, &dev_drv->pwrlist_head) {
351                 pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
352                                           list);
353                 pwr_ctr = &pwr_ctr_list->pwr_ctr;
354                 if (pwr_ctr->type == GPIO) {
355                         gpio_direction_output(pwr_ctr->gpio, pwr_ctr->atv_val);
356                         mdelay(pwr_ctr->delay);
357                 } else if (pwr_ctr->type == REGULATOR) {
358                         if (pwr_ctr->rgl_name)
359                                 regulator_lcd = regulator_get(NULL, pwr_ctr->rgl_name);
360                         if (regulator_lcd == NULL) {
361                                 dev_err(dev_drv->dev,
362                                         "%s: regulator get failed,regulator name:%s\n",
363                                         __func__, pwr_ctr->rgl_name);
364                                 continue;
365                         }
366                         regulator_set_voltage(regulator_lcd, pwr_ctr->volt, pwr_ctr->volt);
367                         while (!regulator_is_enabled(regulator_lcd)) {
368                                 if (regulator_enable(regulator_lcd) == 0 || count == 0)
369                                         break;
370                                 else
371                                         dev_err(dev_drv->dev,
372                                                 "regulator_enable failed,count=%d\n",
373                                                 count);
374                                 count--;
375                         }
376                         regulator_put(regulator_lcd);
377                         msleep(pwr_ctr->delay);
378                 }
379         }
380
381         return 0;
382 }
383
384 int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv)
385 {
386         struct list_head *pos;
387         struct rk_disp_pwr_ctr_list *pwr_ctr_list;
388         struct pwr_ctr *pwr_ctr;
389         struct regulator *regulator_lcd = NULL;
390         int count = 10;
391
392         if (list_empty(&dev_drv->pwrlist_head))
393                 return 0;
394         list_for_each(pos, &dev_drv->pwrlist_head) {
395                 pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
396                                           list);
397                 pwr_ctr = &pwr_ctr_list->pwr_ctr;
398                 if (pwr_ctr->type == GPIO) {
399                         gpio_set_value(pwr_ctr->gpio, !pwr_ctr->atv_val);
400                 } else if (pwr_ctr->type == REGULATOR) {
401                         if (pwr_ctr->rgl_name)
402                                 regulator_lcd = regulator_get(NULL, pwr_ctr->rgl_name);
403                         if (regulator_lcd == NULL) {
404                                 dev_err(dev_drv->dev,
405                                         "%s: regulator get failed,regulator name:%s\n",
406                                         __func__, pwr_ctr->rgl_name);
407                                 continue;
408                         }
409                         while (regulator_is_enabled(regulator_lcd) > 0) {
410                                 if (regulator_disable(regulator_lcd) == 0 || count == 0)
411                                         break;
412                                 else
413                                         dev_err(dev_drv->dev,
414                                                 "regulator_disable failed,count=%d\n",
415                                                 count);
416                                 count--;
417                         }
418                         regulator_put(regulator_lcd);
419                 }
420         }
421         return 0;
422 }
423
424 int rk_fb_video_mode_from_timing(const struct display_timing *dt,
425                                  struct rk_screen *screen)
426 {
427         screen->mode.pixclock = dt->pixelclock.typ;
428         screen->mode.left_margin = dt->hback_porch.typ;
429         screen->mode.right_margin = dt->hfront_porch.typ;
430         screen->mode.xres = dt->hactive.typ;
431         screen->mode.hsync_len = dt->hsync_len.typ;
432         screen->mode.upper_margin = dt->vback_porch.typ;
433         screen->mode.lower_margin = dt->vfront_porch.typ;
434         screen->mode.yres = dt->vactive.typ;
435         screen->mode.vsync_len = dt->vsync_len.typ;
436         screen->type = dt->screen_type;
437         screen->lvds_format = dt->lvds_format;
438         screen->face = dt->face;
439         screen->color_mode = dt->color_mode;
440         screen->dsp_lut = dt->dsp_lut;
441
442         if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
443                 screen->pin_dclk = 1;
444         else
445                 screen->pin_dclk = 0;
446         if (dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
447                 screen->pin_hsync = 1;
448         else
449                 screen->pin_hsync = 0;
450         if (dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
451                 screen->pin_vsync = 1;
452         else
453                 screen->pin_vsync = 0;
454         if (dt->flags & DISPLAY_FLAGS_DE_HIGH)
455                 screen->pin_den = 1;
456         else
457                 screen->pin_den = 0;
458
459         return 0;
460
461 }
462
463 int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
464 {
465         struct display_timings *disp_timing;
466         struct display_timing *dt;
467         disp_timing = of_get_display_timings(np);
468         if (!disp_timing) {
469                 pr_err("parse display timing err\n");
470                 return -EINVAL;
471         }
472         dt = display_timings_get(disp_timing, disp_timing->native_mode);
473         rk_fb_video_mode_from_timing(dt, screen);
474         return 0;
475
476 }
477
478 int rk_fb_calc_fps(struct rk_screen *screen, u32 pixclock)
479 {
480         int x, y;
481         unsigned long long hz;
482         if (!screen) {
483                 printk(KERN_ERR "%s:null screen!\n", __func__);
484                 return 0;
485         }
486         x = screen->mode.xres + screen->mode.left_margin +
487             screen->mode.right_margin + screen->mode.hsync_len;
488         y = screen->mode.yres + screen->mode.upper_margin +
489             screen->mode.lower_margin + screen->mode.vsync_len;
490
491         hz = 1000000000000ULL;  /* 1e12 picoseconds per second */
492
493         hz += (x * y) / 2;
494         do_div(hz, x * y);      /* divide by x * y with rounding */
495
496         hz += pixclock / 2;
497         do_div(hz, pixclock);   /* divide by pixclock with rounding */
498
499         return hz;
500 }
501
502 char *get_format_string(enum data_format format, char *fmt)
503 {
504         if (!fmt)
505                 return NULL;
506         switch (format) {
507         case ARGB888:
508                 strcpy(fmt, "ARGB888");
509                 break;
510         case RGB888:
511                 strcpy(fmt, "RGB888");
512                 break;
513         case RGB565:
514                 strcpy(fmt, "RGB565");
515                 break;
516         case YUV420:
517                 strcpy(fmt, "YUV420");
518                 break;
519         case YUV422:
520                 strcpy(fmt, "YUV422");
521                 break;
522         case YUV444:
523                 strcpy(fmt, "YUV444");
524                 break;
525         case YUV420_A:
526                 strcpy(fmt, "YUV420_A");
527                 break;
528         case YUV422_A:
529                 strcpy(fmt, "YUV422_A");
530                 break;
531         case YUV444_A:
532                 strcpy(fmt, "YUV444_A");
533                 break;
534         case XRGB888:
535                 strcpy(fmt, "XRGB888");
536                 break;
537         case XBGR888:
538                 strcpy(fmt, "XBGR888");
539                 break;
540         case ABGR888:
541                 strcpy(fmt, "ABGR888");
542                 break;
543         case FBDC_RGB_565:
544                 strcpy(fmt, "FBDC_RGB_565");
545                 break;
546         case FBDC_ARGB_888:
547                 strcpy(fmt, "FBDC_ARGB_888");
548                 break;
549         case FBDC_RGBX_888:
550                 strcpy(fmt, "FBDC_RGBX_888");
551                 break;
552         default:
553                 strcpy(fmt, "invalid");
554                 break;
555         }
556
557         return fmt;
558
559 }
560
561 /*
562  * this is for hdmi
563  * name: lcdc device name ,lcdc0 , lcdc1
564  */
565 struct rk_lcdc_driver *rk_get_lcdc_drv(char *name)
566 {
567         struct rk_fb *inf = NULL;
568         struct rk_lcdc_driver *dev_drv = NULL;
569         int i = 0;
570
571         if (likely(fb_pdev))
572                 inf = platform_get_drvdata(fb_pdev);
573         else
574                 return NULL;
575
576         for (i = 0; i < inf->num_lcdc; i++) {
577                 if (!strcmp(inf->lcdc_dev_drv[i]->name, name)) {
578                         dev_drv = inf->lcdc_dev_drv[i];
579                         break;
580                 }
581         }
582
583         return dev_drv;
584 }
585
586 static struct rk_lcdc_driver *rk_get_prmry_lcdc_drv(void)
587 {
588         struct rk_fb *inf = NULL;
589         struct rk_lcdc_driver *dev_drv = NULL;
590         int i = 0;
591
592         if (likely(fb_pdev))
593                 inf = platform_get_drvdata(fb_pdev);
594         else
595                 return NULL;
596
597         for (i = 0; i < inf->num_lcdc; i++) {
598                 if (inf->lcdc_dev_drv[i]->prop == PRMRY) {
599                         dev_drv = inf->lcdc_dev_drv[i];
600                         break;
601                 }
602         }
603
604         return dev_drv;
605 }
606
607 /*
608  * get one frame time of the prmry screen, unit: us
609  */
610 u32 rk_fb_get_prmry_screen_ft(void)
611 {
612         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
613         uint32_t htotal, vtotal, pixclock_ps;
614         u64 pix_total, ft_us;
615
616         if (unlikely(!dev_drv))
617                 return 0;
618
619         pixclock_ps = dev_drv->pixclock;
620
621         vtotal = (dev_drv->cur_screen->mode.upper_margin +
622                  dev_drv->cur_screen->mode.lower_margin +
623                  dev_drv->cur_screen->mode.yres +
624                  dev_drv->cur_screen->mode.vsync_len);
625         htotal = (dev_drv->cur_screen->mode.left_margin +
626                  dev_drv->cur_screen->mode.right_margin +
627                  dev_drv->cur_screen->mode.xres +
628                  dev_drv->cur_screen->mode.hsync_len);
629         pix_total = htotal * vtotal;
630         ft_us = pix_total * pixclock_ps;
631         do_div(ft_us, 1000000);
632         if (dev_drv->frame_time.ft == 0)
633                 dev_drv->frame_time.ft = ft_us;
634
635         ft_us = dev_drv->frame_time.framedone_t - dev_drv->frame_time.last_framedone_t;
636         do_div(ft_us, 1000);
637         ft_us = min(dev_drv->frame_time.ft, (u32)ft_us);
638         if (ft_us != 0)
639                 dev_drv->frame_time.ft = ft_us;
640
641         return dev_drv->frame_time.ft;
642 }
643
644 /*
645  * get the vblanking time of the prmry screen, unit: us
646  */
647 u32 rk_fb_get_prmry_screen_vbt(void)
648 {
649         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
650         uint32_t htotal, vblank, pixclock_ps;
651         u64 pix_blank, vbt_us;
652
653         if (unlikely(!dev_drv))
654                 return 0;
655
656         pixclock_ps = dev_drv->pixclock;
657
658         htotal = (dev_drv->cur_screen->mode.left_margin +
659                  dev_drv->cur_screen->mode.right_margin +
660                  dev_drv->cur_screen->mode.xres +
661                  dev_drv->cur_screen->mode.hsync_len);
662         vblank = (dev_drv->cur_screen->mode.upper_margin +
663                  dev_drv->cur_screen->mode.lower_margin +
664                  dev_drv->cur_screen->mode.vsync_len);
665         pix_blank = htotal * vblank;
666         vbt_us = pix_blank * pixclock_ps;
667         do_div(vbt_us, 1000000);
668         return (u32)vbt_us;
669 }
670
671 /*
672  * get the frame done time of the prmry screen, unit: us
673  */
674 u64 rk_fb_get_prmry_screen_framedone_t(void)
675 {
676         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
677
678         if (unlikely(!dev_drv))
679                 return 0;
680         else
681                 return dev_drv->frame_time.framedone_t;
682 }
683
684 /*
685  * set prmry screen status
686  */
687 int rk_fb_set_prmry_screen_status(int status)
688 {
689         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
690         struct rk_screen *screen;
691
692         if (unlikely(!dev_drv))
693                 return 0;
694
695         screen = dev_drv->cur_screen;
696         switch (status) {
697         case SCREEN_PREPARE_DDR_CHANGE:
698                 if (screen->type == SCREEN_MIPI
699                         || screen->type == SCREEN_DUAL_MIPI) {
700                         if (dev_drv->trsm_ops->dsp_pwr_off)
701                                 dev_drv->trsm_ops->dsp_pwr_off();
702                 }
703                 break;
704         case SCREEN_UNPREPARE_DDR_CHANGE:
705                 if (screen->type == SCREEN_MIPI
706                         || screen->type == SCREEN_DUAL_MIPI) {
707                         if (dev_drv->trsm_ops->dsp_pwr_on)
708                                 dev_drv->trsm_ops->dsp_pwr_on();
709                 }
710                 break;
711         default:
712                 break;
713         }
714
715         return 0;
716 }
717
718 static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
719 {
720         struct rk_fb *inf = NULL;
721         struct rk_lcdc_driver *dev_drv = NULL;
722         int i = 0;
723
724         if (likely(fb_pdev))
725                 inf = platform_get_drvdata(fb_pdev);
726         else
727                 return NULL;
728
729         for (i = 0; i < inf->num_lcdc; i++) {
730                 if (inf->lcdc_dev_drv[i]->prop == EXTEND) {
731                         dev_drv = inf->lcdc_dev_drv[i];
732                         break;
733                 }
734         }
735
736         return dev_drv;
737 }
738
739 u32 rk_fb_get_prmry_screen_pixclock(void)
740 {
741         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
742
743         if (unlikely(!dev_drv))
744                 return 0;
745         else
746                 return dev_drv->pixclock;
747 }
748
749 int rk_fb_poll_prmry_screen_vblank(void)
750 {
751         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
752
753         if (likely(dev_drv)) {
754                 if (dev_drv->ops->poll_vblank)
755                         return dev_drv->ops->poll_vblank(dev_drv);
756                 else
757                         return RK_LF_STATUS_NC;
758         } else {
759                 return RK_LF_STATUS_NC;
760         }
761 }
762
763 bool rk_fb_poll_wait_frame_complete(void)
764 {
765         uint32_t timeout = RK_LF_MAX_TIMEOUT;
766         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
767
768         if (likely(dev_drv)) {
769                 if (dev_drv->ops->set_irq_to_cpu)
770                         dev_drv->ops->set_irq_to_cpu(dev_drv, 0);
771         }
772
773         if (rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_NC) {
774                 if (likely(dev_drv)) {
775                         if (dev_drv->ops->set_irq_to_cpu)
776                                 dev_drv->ops->set_irq_to_cpu(dev_drv, 1);
777                 }
778                 return false;
779         }
780         while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FR) && --timeout)
781                 ;
782         while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FC) && --timeout)
783                 ;
784         if (likely(dev_drv)) {
785                 if (dev_drv->ops->set_irq_to_cpu)
786                         dev_drv->ops->set_irq_to_cpu(dev_drv, 1);
787         }
788
789         return true;
790 }
791
792
793 /* rk_fb_get_sysmmu_device_by_compatible()
794  * @compt: dts device compatible name
795  * return value: success: pointer to the device inside of platform device
796  *               fail: NULL
797  */
798 struct device *rk_fb_get_sysmmu_device_by_compatible(const char *compt)
799 {
800         struct device_node *dn = NULL;
801         struct platform_device *pd = NULL;
802         struct device *ret = NULL ;
803
804         dn = of_find_compatible_node(NULL, NULL, compt);
805         if (!dn) {
806                 printk("can't find device node %s \r\n", compt);
807                 return NULL;
808         }
809
810         pd = of_find_device_by_node(dn);
811         if (!pd) {
812                 printk("can't find platform device in device node %s \r\n", compt);
813                 return  NULL;
814         }
815         ret = &pd->dev;
816
817         return ret;
818 }
819
820 #ifdef CONFIG_IOMMU_API
821 void rk_fb_platform_set_sysmmu(struct device *sysmmu, struct device *dev)
822 {
823         dev->archdata.iommu = sysmmu;
824 }
825 #else
826 void rk_fb_platform_set_sysmmu(struct device *sysmmu, struct device *dev)
827 {
828
829 }
830 #endif
831
832 static int rk_fb_open(struct fb_info *info, int user)
833 {
834         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
835         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
836         int win_id;
837
838         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
839         fb_par->state++;
840         /* if this win aready opened ,no need to reopen */
841         if (dev_drv->win[win_id]->state)
842                 return 0;
843         else
844                 dev_drv->ops->open(dev_drv, win_id, 1);
845         return 0;
846 }
847
848 static int get_extend_fb_id(struct fb_info *info)
849 {
850         int fb_id = 0;
851         char *id = info->fix.id;
852         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
853         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
854
855         if (!strcmp(id, "fb0"))
856                 fb_id = 0;
857         else if (!strcmp(id, "fb1"))
858                 fb_id = 1;
859         else if (!strcmp(id, "fb2") && (dev_drv->lcdc_win_num > 2))
860                 fb_id = 2;
861         else if (!strcmp(id, "fb3") && (dev_drv->lcdc_win_num > 3))
862                 fb_id = 3;
863         else if (!strcmp(id, "fb4") && (dev_drv->lcdc_win_num > 4))
864                 fb_id = 4;
865         return fb_id;
866 }
867
868 static int rk_fb_close(struct fb_info *info, int user)
869 {
870         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
871         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
872         struct rk_lcdc_win *win = NULL;
873         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
874
875         if (win_id >= 0) {
876                 win = dev_drv->win[win_id];
877                 fb_par->state--;
878                 if (!fb_par->state) {
879                         if (fb_par->fb_phy_base > 0)
880                                 info->fix.smem_start = fb_par->fb_phy_base;
881                         info->var.xres = dev_drv->screen0->mode.xres;
882                         info->var.yres = dev_drv->screen0->mode.yres;
883                         /*
884                         info->var.grayscale |=
885                             (info->var.xres << 8) + (info->var.yres << 20);
886                         */
887                         info->var.xres_virtual = info->var.xres;
888                         info->var.yres_virtual = info->var.yres;
889 #if defined(CONFIG_LOGO_LINUX_BMP)
890                         info->var.bits_per_pixel = 32;
891 #else
892                         info->var.bits_per_pixel = 16;
893 #endif
894                         info->fix.line_length =
895                             (info->var.xres_virtual) * (info->var.bits_per_pixel >> 3);
896                         info->var.width = dev_drv->screen0->width;
897                         info->var.height = dev_drv->screen0->height;
898                         info->var.pixclock = dev_drv->pixclock;
899                         info->var.left_margin = dev_drv->screen0->mode.left_margin;
900                         info->var.right_margin = dev_drv->screen0->mode.right_margin;
901                         info->var.upper_margin = dev_drv->screen0->mode.upper_margin;
902                         info->var.lower_margin = dev_drv->screen0->mode.lower_margin;
903                         info->var.vsync_len = dev_drv->screen0->mode.vsync_len;
904                         info->var.hsync_len = dev_drv->screen0->mode.hsync_len;
905                 }
906         }
907
908         return 0;
909 }
910
911
912 #if defined(CONFIG_RK29_IPP)
913 static int get_ipp_format(int fmt)
914 {
915         int ipp_fmt = IPP_XRGB_8888;
916         switch (fmt) {
917         case HAL_PIXEL_FORMAT_RGBX_8888:
918         case HAL_PIXEL_FORMAT_RGBA_8888:
919         case HAL_PIXEL_FORMAT_BGRA_8888:
920         case HAL_PIXEL_FORMAT_RGB_888:
921                 ipp_fmt = IPP_XRGB_8888;
922                 break;
923         case HAL_PIXEL_FORMAT_RGB_565:
924                 ipp_fmt = IPP_RGB_565;
925                 break;
926         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
927                 ipp_fmt = IPP_Y_CBCR_H2V1;
928                 break;
929         case HAL_PIXEL_FORMAT_YCrCb_NV12:
930                 ipp_fmt = IPP_Y_CBCR_H2V2;
931                 break;
932         case HAL_PIXEL_FORMAT_YCrCb_444:
933                 ipp_fmt = IPP_Y_CBCR_H1V1;
934                 break;
935         default:
936                 ipp_fmt = IPP_IMGTYPE_LIMIT;
937                 break;
938         }
939
940         return ipp_fmt;
941 }
942
943 static void ipp_win_check(int *dst_w, int *dst_h, int *dst_vir_w,
944                           int rotation, int fmt)
945 {
946         int align16 = 2;
947         int align64 = 8;
948
949         if (fmt == IPP_XRGB_8888) {
950                 align16 = 1;
951                 align64 = 2;
952         } else if (fmt == IPP_RGB_565) {
953                 align16 = 1;
954                 align64 = 4;
955         } else {
956                 align16 = 2;
957                 align64 = 8;
958         }
959         align16 -= 1;           /*for YUV, 1 */
960         align64 -= 1;           /*for YUV, 7 */
961
962         if (rotation == IPP_ROT_0) {
963                 if (fmt > IPP_RGB_565) {
964                         if ((*dst_w & 1) != 0)
965                                 *dst_w = *dst_w + 1;
966                         if ((*dst_h & 1) != 0)
967                                 *dst_h = *dst_h + 1;
968                         if (*dst_vir_w < *dst_w)
969                                 *dst_vir_w = *dst_w;
970                 }
971         } else {
972                 if ((*dst_w & align64) != 0)
973                         *dst_w = (*dst_w + align64) & (~align64);
974                 if ((fmt > IPP_RGB_565) && ((*dst_h & 1) == 1))
975                         *dst_h = *dst_h + 1;
976                 if (*dst_vir_w < *dst_w)
977                         *dst_vir_w = *dst_w;
978         }
979 }
980
981 static void fb_copy_by_ipp(struct fb_info *dst_info,
982                                 struct fb_info *src_info)
983 {
984         struct rk29_ipp_req ipp_req;
985         uint32_t rotation = 0;
986         int dst_w, dst_h, dst_vir_w;
987         int ipp_fmt;
988         u8 data_format = (dst_info->var.nonstd) & 0xff;
989         struct rk_fb_par *fb_par = (struct rk_fb_par *)dst_info->par;
990         struct rk_lcdc_driver *ext_dev_drv = fb_par->lcdc_drv;
991         u16 orientation = ext_dev_drv->rotate_mode;
992
993         memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
994
995         switch (orientation) {
996         case 0:
997                 rotation = IPP_ROT_0;
998                 break;
999         case ROTATE_90:
1000                 rotation = IPP_ROT_90;
1001                 break;
1002         case ROTATE_180:
1003                 rotation = IPP_ROT_180;
1004                 break;
1005         case ROTATE_270:
1006                 rotation = IPP_ROT_270;
1007                 break;
1008         default:
1009                 rotation = IPP_ROT_270;
1010                 break;
1011         }
1012
1013         dst_w = dst_info->var.xres;
1014         dst_h = dst_info->var.yres;
1015         dst_vir_w = dst_info->var.xres_virtual;
1016         ipp_fmt = get_ipp_format(data_format);
1017         ipp_win_check(&dst_w, &dst_h, &dst_vir_w, rotation, ipp_fmt);
1018         ipp_req.src0.YrgbMst = src_info->fix.smem_start + offset;
1019         ipp_req.src0.w = src_info->var.xres;
1020         ipp_req.src0.h = src_info->var.yres;
1021         ipp_req.src_vir_w = src_info->var.xres_virtual;
1022         ipp_req.src0.fmt = ipp_fmt;
1023
1024         ipp_req.dst0.YrgbMst = dst_info->fix.smem_start + offset;
1025         ipp_req.dst0.w = dst_w;
1026         ipp_req.dst0.h = dst_h;
1027         ipp_req.dst_vir_w = dst_vir_w;
1028         ipp_req.dst0.fmt = ipp_fmt;
1029
1030         ipp_req.timeout = 100;
1031         ipp_req.flag = rotation;
1032         ipp_blit_sync(&ipp_req);
1033 }
1034
1035 #endif
1036
1037 #if defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
1038 static int get_rga_format(int fmt)
1039 {
1040         int rga_fmt = 0;
1041
1042         switch (fmt) {
1043         case XBGR888:
1044                 rga_fmt = RK_FORMAT_RGBX_8888;
1045                 break;
1046         case ABGR888:
1047                 rga_fmt = RK_FORMAT_RGBA_8888;
1048                 break;
1049         case ARGB888:
1050                 rga_fmt = RK_FORMAT_BGRA_8888;
1051                 break;
1052         case RGB888:
1053                 rga_fmt = RK_FORMAT_RGB_888;
1054                 break;
1055         case RGB565:
1056                 rga_fmt = RK_FORMAT_RGB_565;
1057                 break;
1058         case YUV422:
1059                 rga_fmt = RK_FORMAT_YCbCr_422_SP;
1060                 break;
1061         case YUV420:
1062                 rga_fmt = RK_FORMAT_YCbCr_420_SP;
1063                 break;
1064         default:
1065                 rga_fmt = RK_FORMAT_RGBA_8888;
1066                 break;
1067         }
1068
1069         return rga_fmt;
1070 }
1071
1072 static void rga_win_check(struct rk_lcdc_win *dst_win,
1073                           struct rk_lcdc_win *src_win)
1074 {
1075         int format = 0;
1076
1077         format = get_rga_format(src_win->area[0].format);
1078         /* width and height must be even number */
1079         if (format >= RK_FORMAT_YCbCr_422_SP &&
1080             format <= RK_FORMAT_YCrCb_420_P) {
1081                 if ((src_win->area[0].xact % 2) != 0)
1082                         src_win->area[0].xact += 1;
1083                 if ((src_win->area[0].yact % 2) != 0)
1084                         src_win->area[0].yact += 1;
1085         }
1086         if (src_win->area[0].xvir < src_win->area[0].xact)
1087                 src_win->area[0].xvir = src_win->area[0].xact;
1088         if (src_win->area[0].yvir < src_win->area[0].yact)
1089                 src_win->area[0].yvir = src_win->area[0].yact;
1090
1091         format = get_rga_format(dst_win->area[0].format);
1092         if (format >= RK_FORMAT_YCbCr_422_SP &&
1093             format <= RK_FORMAT_YCrCb_420_P) {
1094                 if ((dst_win->area[0].xact % 2) != 0)
1095                         dst_win->area[0].xact += 1;
1096                 if ((dst_win->area[0].yact % 2) != 0)
1097                         dst_win->area[0].yact += 1;
1098         }
1099         if (dst_win->area[0].xvir < dst_win->area[0].xact)
1100                 dst_win->area[0].xvir = dst_win->area[0].xact;
1101         if (dst_win->area[0].yvir < dst_win->area[0].yact)
1102                 dst_win->area[0].yvir = dst_win->area[0].yact;
1103 }
1104
1105 static void win_copy_by_rga(struct rk_lcdc_win *dst_win,
1106                             struct rk_lcdc_win *src_win,
1107                             u16 orientation, int iommu_en)
1108 {
1109         struct rga_req Rga_Request;
1110         long ret = 0;
1111         /* int fd = 0; */
1112
1113         memset(&Rga_Request, 0, sizeof(Rga_Request));
1114         rga_win_check(dst_win, src_win);
1115
1116         switch (orientation) {
1117         case ROTATE_90:
1118                 Rga_Request.rotate_mode = 1;
1119                 Rga_Request.sina = 65536;
1120                 Rga_Request.cosa = 0;
1121                 Rga_Request.dst.act_w = dst_win->area[0].yact;
1122                 Rga_Request.dst.act_h = dst_win->area[0].xact;
1123                 Rga_Request.dst.x_offset = dst_win->area[0].xact - 1;
1124                 Rga_Request.dst.y_offset = 0;
1125                 break;
1126         case ROTATE_180:
1127                 Rga_Request.rotate_mode = 1;
1128                 Rga_Request.sina = 0;
1129                 Rga_Request.cosa = -65536;
1130                 Rga_Request.dst.act_w = dst_win->area[0].xact;
1131                 Rga_Request.dst.act_h = dst_win->area[0].yact;
1132                 Rga_Request.dst.x_offset = dst_win->area[0].xact - 1;
1133                 Rga_Request.dst.y_offset = dst_win->area[0].yact - 1;
1134                 break;
1135         case ROTATE_270:
1136                 Rga_Request.rotate_mode = 1;
1137                 Rga_Request.sina = -65536;
1138                 Rga_Request.cosa = 0;
1139                 Rga_Request.dst.act_w = dst_win->area[0].yact;
1140                 Rga_Request.dst.act_h = dst_win->area[0].xact;
1141                 Rga_Request.dst.x_offset = 0;
1142                 Rga_Request.dst.y_offset = dst_win->area[0].yact - 1;
1143                 break;
1144         default:
1145                 Rga_Request.rotate_mode = 0;
1146                 Rga_Request.dst.act_w = dst_win->area[0].xact;
1147                 Rga_Request.dst.act_h = dst_win->area[0].yact;
1148                 Rga_Request.dst.x_offset = dst_win->area[0].xact - 1;
1149                 Rga_Request.dst.y_offset = dst_win->area[0].yact - 1;
1150                 break;
1151         }
1152
1153 /*
1154         fd = ion_share_dma_buf_fd(rk_fb->ion_client, src_win->area[0].ion_hdl);
1155         Rga_Request.src.yrgb_addr = fd;
1156         fd = ion_share_dma_buf_fd(rk_fb->ion_client, dst_win->area[0].ion_hdl);
1157         Rga_Request.dst.yrgb_addr = fd;
1158 */
1159         Rga_Request.src.yrgb_addr = 0;
1160         Rga_Request.src.uv_addr =
1161             src_win->area[0].smem_start + src_win->area[0].y_offset;
1162         Rga_Request.src.v_addr = 0;
1163
1164         Rga_Request.dst.yrgb_addr = 0;
1165         Rga_Request.dst.uv_addr =
1166             dst_win->area[0].smem_start + dst_win->area[0].y_offset;
1167         Rga_Request.dst.v_addr = 0;
1168
1169         Rga_Request.src.vir_w = src_win->area[0].xvir;
1170         Rga_Request.src.vir_h = src_win->area[0].yvir;
1171         Rga_Request.src.format = get_rga_format(src_win->area[0].format);
1172         Rga_Request.src.act_w = src_win->area[0].xact;
1173         Rga_Request.src.act_h = src_win->area[0].yact;
1174         Rga_Request.src.x_offset = 0;
1175         Rga_Request.src.y_offset = 0;
1176
1177         Rga_Request.dst.vir_w = dst_win->area[0].xvir;
1178         Rga_Request.dst.vir_h = dst_win->area[0].yvir;
1179         Rga_Request.dst.format = get_rga_format(dst_win->area[0].format);
1180
1181         Rga_Request.clip.xmin = 0;
1182         Rga_Request.clip.xmax = dst_win->area[0].xact - 1;
1183         Rga_Request.clip.ymin = 0;
1184         Rga_Request.clip.ymax = dst_win->area[0].yact - 1;
1185         Rga_Request.scale_mode = 0;
1186 #if defined(CONFIG_ROCKCHIP_IOMMU)
1187         if (iommu_en) {
1188                 Rga_Request.mmu_info.mmu_en = 1;
1189                 Rga_Request.mmu_info.mmu_flag = 1;
1190         } else {
1191                 Rga_Request.mmu_info.mmu_en = 0;
1192                 Rga_Request.mmu_info.mmu_flag = 0;
1193         }
1194 #else
1195         Rga_Request.mmu_info.mmu_en = 0;
1196         Rga_Request.mmu_info.mmu_flag = 0;
1197 #endif
1198
1199         ret = rga_ioctl_kernel(&Rga_Request);
1200 }
1201
1202 /*
1203  * This function is used for copying fb by RGA Module
1204  * RGA only support copy RGB to RGB
1205  * RGA2 support copy RGB to RGB and YUV to YUV
1206  */
1207 static void fb_copy_by_rga(struct fb_info *dst_info,
1208                                 struct fb_info *src_info)
1209 {
1210         struct rk_fb_par *src_fb_par = (struct rk_fb_par *)src_info->par;
1211         struct rk_fb_par *dst_fb_par = (struct rk_fb_par *)dst_info->par;
1212         struct rk_lcdc_driver *dev_drv = src_fb_par->lcdc_drv;
1213         struct rk_lcdc_driver *ext_dev_drv = dst_fb_par->lcdc_drv;
1214         int win_id = 0, ext_win_id;
1215         struct rk_lcdc_win *src_win, *dst_win;
1216
1217         win_id = dev_drv->ops->fb_get_win_id(dev_drv, src_info->fix.id);
1218         src_win = dev_drv->win[win_id];
1219
1220         ext_win_id =
1221             ext_dev_drv->ops->fb_get_win_id(ext_dev_drv, dst_info->fix.id);
1222         dst_win = ext_dev_drv->win[ext_win_id];
1223
1224         win_copy_by_rga(dst_win, src_win, ext_dev_drv->rotate_mode,
1225                         ext_dev_drv->iommu_enabled);
1226 }
1227
1228 #endif
1229
1230 static int rk_fb_rotate(struct fb_info *dst_info,
1231                           struct fb_info *src_info)
1232 {
1233
1234 #if defined(CONFIG_RK29_IPP)
1235         fb_copy_by_ipp(dst_info, src_info);
1236 #elif defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
1237         fb_copy_by_rga(dst_info, src_info);
1238 #else
1239         return -1;
1240 #endif
1241         return 0;
1242 }
1243
1244 static int __maybe_unused rk_fb_win_rotate(struct rk_lcdc_win *dst_win,
1245                                             struct rk_lcdc_win *src_win,
1246                                             u16 rotate, int iommu_en)
1247 {
1248 #if defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
1249         win_copy_by_rga(dst_win, src_win, rotate, iommu_en);
1250 #else
1251         return -1;
1252 #endif
1253         return 0;
1254 }
1255
1256 static int rk_fb_set_ext_win_buffer(struct rk_lcdc_win *ext_win,
1257                                          struct rk_lcdc_win *win,
1258                                          u16 rotate, int iommu_en)
1259 {
1260         struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
1261         struct fb_info *ext_info = rk_fb->fb[(rk_fb->num_fb >> 1)];
1262         struct rk_fb_par *ext_fb_par = (struct rk_fb_par *)ext_info->par;
1263         struct rk_lcdc_driver *ext_dev_drv = rk_get_extend_lcdc_drv();
1264         struct rk_lcdc_win *last_win;
1265         static u8 fb_index = 0;
1266         ion_phys_addr_t phy_addr;
1267         size_t len = 0;
1268         int ret = 0;
1269         bool is_yuv = false;
1270
1271         if (unlikely(!ext_win) || unlikely(!win))
1272                 return -1;
1273
1274         if (rk_fb->disp_mode != DUAL || ext_info == NULL)
1275                 return 0;
1276
1277         switch (ext_win->area[0].format) {
1278         case YUV422:
1279         case YUV420:
1280         case YUV444:
1281         case YUV422_A:
1282         case YUV420_A:
1283         case YUV444_A:
1284                 is_yuv = true;
1285                 break;
1286         default:
1287                 is_yuv = false;
1288                 break;
1289         }
1290
1291         /* no rotate mode */
1292         if (rotate <= X_Y_MIRROR) {
1293                 if (iommu_en) {
1294                         ret = ion_map_iommu(ext_dev_drv->dev,
1295                                             rk_fb->ion_client,
1296                                             win->area[0].ion_hdl,
1297                                             (unsigned long *)&phy_addr,
1298                                             (unsigned long *)&len);
1299                         if (ret < 0) {
1300                                 dev_err(ext_dev_drv->dev, "ion map to get phy addr failed\n");
1301                                 ion_free(rk_fb->ion_client, win->area[0].ion_hdl);
1302                                 return -ENOMEM;
1303                         }
1304                         ext_win->area[0].smem_start = phy_addr;
1305                         ext_win->area[0].y_offset = win->area[0].y_offset;
1306                         if (is_yuv) {
1307                                 ext_win->area[0].cbr_start = win->area[0].cbr_start;
1308                                 ext_win->area[0].c_offset = win->area[0].c_offset;
1309                         } else {
1310                                 ext_win->area[0].cbr_start = 0;
1311                                 ext_win->area[0].c_offset = 0;
1312                         }
1313                 } else {
1314                         ext_win->area[0].smem_start = win->area[0].smem_start;
1315                         ext_win->area[0].y_offset = win->area[0].y_offset;
1316                         if (is_yuv) {
1317                                 ext_win->area[0].cbr_start = win->area[0].cbr_start;
1318                                 ext_win->area[0].c_offset = win->area[0].c_offset;
1319                         } else {
1320                                 ext_win->area[0].cbr_start = 0;
1321                                 ext_win->area[0].c_offset = 0;
1322                         }
1323                 }
1324
1325                 return 0;
1326         }
1327
1328         /* rotate mode */
1329         if (!iommu_en) {
1330                 if (ext_win->id == 0) {
1331                         ext_win->area[0].smem_start = ext_fb_par->fb_phy_base;
1332                         ext_win->area[0].y_offset = (get_rotate_fb_size() >> 1) * fb_index;
1333                         if ((++fb_index) > 1)
1334                                 fb_index = 0;
1335                 } else {
1336                         ext_win->area[0].y_offset = 0;
1337                         last_win = ext_dev_drv->win[ext_win->id - 1];
1338                         if (last_win->area[0].cbr_start)
1339                                 ext_win->area[0].smem_start =
1340                                         last_win->area[0].cbr_start +
1341                                         last_win->area[0].c_offset +
1342                                         last_win->area[0].xvir * last_win->area[0].yvir;
1343                         else
1344                                 ext_win->area[0].smem_start =
1345                                         last_win->area[0].smem_start +
1346                                         last_win->area[0].y_offset +
1347                                         last_win->area[0].xvir * last_win->area[0].yvir;
1348                 }
1349
1350                 if (is_yuv) {
1351                         ext_win->area[0].cbr_start =
1352                                 ext_win->area[0].smem_start +
1353                                 ext_win->area[0].y_offset +
1354                                 ext_win->area[0].xvir * ext_win->area[0].yvir;
1355                         ext_win->area[0].c_offset = win->area[0].c_offset;
1356                 } else {
1357                         ext_win->area[0].cbr_start = 0;
1358                         ext_win->area[0].c_offset = 0;
1359                 }
1360         }
1361
1362         return 0;
1363 }
1364
1365 static int rk_fb_pan_display(struct fb_var_screeninfo *var,
1366                              struct fb_info *info)
1367 {
1368         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1369         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
1370         struct rk_fb_par *extend_fb_par = NULL;
1371         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1372         struct fb_fix_screeninfo *fix = &info->fix;
1373         struct fb_info *extend_info = NULL;
1374         struct rk_lcdc_driver *extend_dev_drv = NULL;
1375         int win_id = 0, extend_win_id = 0;
1376         struct rk_lcdc_win *extend_win = NULL;
1377         struct rk_lcdc_win *win = NULL;
1378         struct rk_screen *screen = dev_drv->cur_screen;
1379         int fb_id = 0;
1380
1381         u32 xoffset = var->xoffset;
1382         u32 yoffset = var->yoffset;
1383         u32 xvir = var->xres_virtual;
1384         /* u32 yvir = var->yres_virtual; */
1385         /* u8 data_format = var->nonstd&0xff; */
1386
1387         u8 pixel_width;
1388         u32 vir_width_bit;
1389         u32 stride, uv_stride;
1390         u32 stride_32bit_1;
1391         u32 stride_32bit_2;
1392         u16 uv_x_off, uv_y_off, uv_y_act;
1393         u8 is_pic_yuv = 0;
1394
1395         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1396         if (win_id < 0)
1397                 return -ENODEV;
1398         else
1399                 win = dev_drv->win[win_id];
1400
1401         if (rk_fb->disp_mode == DUAL) {
1402                 fb_id = get_extend_fb_id(info);
1403                 extend_info = rk_fb->fb[(rk_fb->num_fb >> 1) + fb_id];
1404                 extend_fb_par = (struct rk_fb_par *)extend_info->par;
1405                 extend_dev_drv = extend_fb_par->lcdc_drv;
1406                 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
1407                                                            extend_info->fix.id);
1408                 extend_win = extend_dev_drv->win[extend_win_id];
1409         }
1410
1411         pixel_width = rk_fb_pixel_width(win->area[0].format);
1412         vir_width_bit = pixel_width * xvir;
1413         /* pixel_width = byte_num * 8 */
1414         stride_32bit_1 = ALIGN_N_TIMES(vir_width_bit, 32) / 8;
1415         stride_32bit_2 = ALIGN_N_TIMES(vir_width_bit * 2, 32) / 8;
1416
1417         switch (win->area[0].format) {
1418         case YUV422:
1419         case YUV422_A:
1420                 is_pic_yuv = 1;
1421                 stride = stride_32bit_1;
1422                 uv_stride = stride_32bit_1 >> 1;
1423                 uv_x_off = xoffset >> 1;
1424                 uv_y_off = yoffset;
1425                 fix->line_length = stride;
1426                 uv_y_act = win->area[0].yact >> 1;
1427                 break;
1428         case YUV420:            /* 420sp */
1429         case YUV420_A:
1430                 is_pic_yuv = 1;
1431                 stride = stride_32bit_1;
1432                 uv_stride = stride_32bit_1;
1433                 uv_x_off = xoffset;
1434                 uv_y_off = yoffset >> 1;
1435                 fix->line_length = stride;
1436                 uv_y_act = win->area[0].yact >> 1;
1437                 break;
1438         case YUV444:
1439         case YUV444_A:
1440                 is_pic_yuv = 1;
1441                 stride = stride_32bit_1;
1442                 uv_stride = stride_32bit_2;
1443                 uv_x_off = xoffset * 2;
1444                 uv_y_off = yoffset;
1445                 fix->line_length = stride << 2;
1446                 uv_y_act = win->area[0].yact;
1447                 break;
1448         default:
1449                 stride = stride_32bit_1;        /* default rgb */
1450                 fix->line_length = stride;
1451                 break;
1452         }
1453
1454         /* x y mirror ,jump line */
1455         if ((screen->y_mirror == 1) ||
1456             (win->mirror_en == 1)) {
1457                 if (screen->interlace == 1) {
1458                         win->area[0].y_offset = yoffset * stride * 2 +
1459                             ((win->area[0].yact - 1) * 2 + 1) * stride +
1460                             xoffset * pixel_width / 8;
1461                 } else {
1462                         win->area[0].y_offset = yoffset * stride +
1463                             (win->area[0].yact - 1) * stride +
1464                             xoffset * pixel_width / 8;
1465                 }
1466         } else {
1467                 if (screen->interlace == 1) {
1468                         win->area[0].y_offset =
1469                             yoffset * stride * 2 + xoffset * pixel_width / 8;
1470                 } else {
1471                         win->area[0].y_offset =
1472                             yoffset * stride + xoffset * pixel_width / 8;
1473                 }
1474         }
1475         if (is_pic_yuv == 1) {
1476                 if ((screen->y_mirror == 1) ||
1477                     (win->mirror_en == 1)) {
1478                         if (screen->interlace == 1) {
1479                                 win->area[0].c_offset =
1480                                     uv_y_off * uv_stride * 2 +
1481                                     ((uv_y_act - 1) * 2 + 1) * uv_stride +
1482                                     uv_x_off * pixel_width / 8;
1483                         } else {
1484                                 win->area[0].c_offset = uv_y_off * uv_stride +
1485                                     (uv_y_act - 1) * uv_stride +
1486                                     uv_x_off * pixel_width / 8;
1487                         }
1488                 } else {
1489                         if (screen->interlace == 1) {
1490                                 win->area[0].c_offset =
1491                                     uv_y_off * uv_stride * 2 +
1492                                     uv_x_off * pixel_width / 8;
1493                         } else {
1494                                 win->area[0].c_offset =
1495                                     uv_y_off * uv_stride +
1496                                     uv_x_off * pixel_width / 8;
1497                         }
1498                 }
1499         }
1500
1501         win->area[0].smem_start = fix->smem_start;
1502         win->area[0].cbr_start = fix->mmio_start;
1503         win->area[0].state = 1;
1504         win->area_num = 1;
1505
1506         dev_drv->ops->pan_display(dev_drv, win_id);
1507
1508         if (rk_fb->disp_mode == DUAL) {
1509                 if (extend_info != info && extend_win->state &&
1510                     hdmi_switch_complete) {
1511                         rk_fb_set_ext_win_buffer(extend_win, win,
1512                                                  extend_dev_drv->rotate_mode,
1513                                                  extend_dev_drv->iommu_enabled);
1514                         if (extend_dev_drv->rotate_mode > X_Y_MIRROR)
1515                                 rk_fb_rotate(extend_info, info);
1516
1517                         extend_dev_drv->ops->pan_display(extend_dev_drv,
1518                                                          extend_win_id);
1519                         extend_dev_drv->ops->cfg_done(extend_dev_drv);
1520                 }
1521         }
1522 #ifdef  CONFIG_FB_MIRRORING
1523         if (video_data_to_mirroring)
1524                 video_data_to_mirroring(info, NULL);
1525 #endif
1526         dev_drv->ops->cfg_done(dev_drv);
1527         /*msleep(1000);
1528         dev_drv->ops->dump_reg(dev_drv);
1529         while(1);*/
1530         return 0;
1531 }
1532
1533 static int rk_fb_get_list_stat(struct rk_lcdc_driver *dev_drv)
1534 {
1535         int i, j;
1536
1537         i = list_empty(&dev_drv->update_regs_list);
1538         j = list_empty(&saved_list);
1539         return i == j ? 0 : 1;
1540 }
1541
1542 void rk_fd_fence_wait(struct rk_lcdc_driver *dev_drv, struct sync_fence *fence)
1543 {
1544         int err = sync_fence_wait(fence, 1000);
1545
1546         if (err >= 0)
1547                 return;
1548
1549         if (err == -ETIME)
1550                 err = sync_fence_wait(fence, 10 * MSEC_PER_SEC);
1551
1552         if (err < 0)
1553                 printk("error waiting on fence\n");
1554 }
1555 #if 0
1556 static int rk_fb_copy_from_loader(struct fb_info *info)
1557 {
1558         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
1559         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1560         void *dst = info->screen_base;
1561         u32 dsp_addr[4];
1562         u32 src;
1563         u32 i,size;
1564         int win_id;
1565         struct rk_lcdc_win *win;
1566         
1567         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1568         win = dev_drv->win[win_id];
1569         size = (win->area[0].xact) * (win->area[0].yact) << 2;
1570         dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
1571         src = dsp_addr[win_id];
1572         dev_info(info->dev, "copy fb data %d x %d  from  dst_addr:%08x\n",
1573                  win->area[0].xact, win->area[0].yact, src);
1574         for (i = 0; i < size; i += PAGE_SIZE) {
1575                 void *page = phys_to_page(i + src);
1576                 void *from_virt = kmap(page);
1577                 void *to_virt = dst + i;
1578                 memcpy(to_virt, from_virt, PAGE_SIZE);
1579         }
1580         dev_drv->ops->direct_set_addr(dev_drv, win_id,
1581                                       info->fix.smem_start);
1582         return 0;
1583 }
1584 #endif
1585 #ifdef CONFIG_ROCKCHIP_IOMMU
1586 static int g_last_addr[4];
1587 int g_last_timeout;
1588 u32 freed_addr[10];
1589 u32 freed_index;
1590
1591 #define DUMP_CHUNK 256
1592 char buf[PAGE_SIZE];
1593
1594 int rk_fb_sysmmu_fault_handler(struct device *dev,
1595                                enum rk_iommu_inttype itype,
1596                                unsigned long pgtable_base,
1597                                unsigned long fault_addr, unsigned int status)
1598 {
1599         struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
1600         int i = 0;
1601         static int page_fault_cnt;
1602         if ((page_fault_cnt++) >= 10)
1603                 return 0;
1604         pr_err
1605             ("PAGE FAULT occurred at 0x%lx (Page table base: 0x%lx),status=%d\n",
1606              fault_addr, pgtable_base, status);
1607         printk("last config addr:\n" "win0:0x%08x\n" "win1:0x%08x\n"
1608                "win2:0x%08x\n" "win3:0x%08x\n", g_last_addr[0], g_last_addr[1],
1609                g_last_addr[2], g_last_addr[3]);
1610         printk("last freed buffer:\n");
1611         for (i = 0; (freed_addr[i] != 0xfefefefe) && freed_addr[i]; i++)
1612                 printk("%d:0x%08x\n", i, freed_addr[i]);
1613         printk("last timeout:%d\n", g_last_timeout);
1614         dev_drv->ops->get_disp_info(dev_drv, buf, 0);
1615         for (i = 0; i < PAGE_SIZE; i += DUMP_CHUNK) {
1616                 if ((PAGE_SIZE - i) > DUMP_CHUNK) {
1617                         char c = buf[i + DUMP_CHUNK];
1618                         buf[i + DUMP_CHUNK] = 0;
1619                         pr_cont("%s", buf + i);
1620                         buf[i + DUMP_CHUNK] = c;
1621                 } else {
1622                         buf[PAGE_SIZE - 1] = 0;
1623                         pr_cont("%s", buf + i);
1624                 }
1625         }
1626
1627         return 0;
1628 }
1629 #endif
1630
1631 void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
1632                         struct rk_fb_reg_win_data *reg_win_data)
1633 {
1634         int i, index_buf;
1635         struct rk_fb_reg_area_data *area_data;
1636         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1637 #if defined(CONFIG_ROCKCHIP_IOMMU)
1638         struct rk_lcdc_driver *ext_dev_drv = rk_get_extend_lcdc_drv();
1639 #endif
1640
1641         for (i = 0; i < reg_win_data->area_num; i++) {
1642                 area_data = &reg_win_data->reg_area_data[i];
1643                 index_buf = area_data->index_buf;
1644 #if defined(CONFIG_ROCKCHIP_IOMMU)
1645                 if (dev_drv->iommu_enabled) {
1646                         if (rk_fb->disp_policy != DISPLAY_POLICY_BOX)
1647                         ion_unmap_iommu(dev_drv->dev, rk_fb->ion_client,
1648                                         area_data->ion_handle);
1649                         freed_addr[freed_index++] = area_data->smem_start;
1650                 }
1651                 if (rk_fb->disp_mode == DUAL && hdmi_switch_complete) {
1652                         if (ext_dev_drv->iommu_enabled)
1653                                 ion_unmap_iommu(ext_dev_drv->dev,
1654                                                 rk_fb->ion_client,
1655                                                 area_data->ion_handle);
1656                 }
1657 #endif
1658                 if (area_data->ion_handle != NULL) {
1659                         ion_unmap_kernel(rk_fb->ion_client,
1660                                          area_data->ion_handle);
1661                         ion_free(rk_fb->ion_client, area_data->ion_handle);
1662                 }
1663                 if (area_data->acq_fence)
1664                         sync_fence_put(area_data->acq_fence);
1665         }
1666         memset(reg_win_data, 0, sizeof(struct rk_fb_reg_win_data));
1667 }
1668
1669 /*
1670  * function: update extend win info acorrding to primary win info,
1671         the function is only used for dual display mode
1672  * @ext_dev_drv: the extend lcdc driver
1673  * @dev_drv: the primary lcdc driver
1674  * @ext_win: the lcdc win info of extend screen
1675  * @win: the lcdc win info of primary screen
1676  */
1677 static int rk_fb_update_ext_win(struct rk_lcdc_driver *ext_dev_drv,
1678                                      struct rk_lcdc_driver *dev_drv,
1679                                      struct rk_lcdc_win *ext_win,
1680                                      struct rk_lcdc_win *win)
1681 {
1682         struct rk_screen *screen = dev_drv->cur_screen;
1683         struct rk_screen *ext_screen = ext_dev_drv->cur_screen;
1684         int hdmi_xsize = ext_screen->xsize;
1685         int hdmi_ysize = ext_screen->ysize;
1686         int pixel_width, vir_width_bit, y_stride;
1687         bool is_yuv = false;
1688         int rotate_mode = 0;
1689
1690         if (unlikely(!dev_drv) || unlikely(!ext_dev_drv) ||
1691             unlikely(!ext_win) || unlikely(!win))
1692                 return -1;
1693
1694         rotate_mode = ext_dev_drv->rotate_mode;
1695
1696         if (ext_win->state == 0) {
1697                 dev_info(ext_dev_drv->dev, "extend lcdc win is closed\n");
1698                 return 0;
1699         }
1700
1701         ext_win->area[0].state = win->area[0].state;
1702         ext_win->area[0].format = win->area[0].format;
1703         ext_win->area_num = win->area_num;
1704         ext_win->fmt_10 = win->fmt_10;
1705         ext_win->z_order = win->z_order;
1706         ext_win->alpha_en = win->alpha_en;
1707         ext_win->alpha_mode = win->alpha_mode;
1708         ext_win->g_alpha_val = win->g_alpha_val;
1709         ext_win->mirror_en = win->mirror_en;
1710         ext_win->area[0].fbdc_en = win->area[0].fbdc_en;
1711         ext_win->area[0].fbdc_cor_en = win->area[0].fbdc_cor_en;
1712         ext_win->area[0].fbdc_data_format = win->area[0].fbdc_data_format;
1713
1714         switch (ext_win->area[0].format) {
1715         case YUV422:
1716         case YUV420:
1717         case YUV444:
1718         case YUV422_A:
1719         case YUV420_A:
1720         case YUV444_A:
1721                 is_yuv = true;
1722                 break;
1723         default:
1724                 is_yuv = false;
1725                 break;
1726         }
1727
1728         if (rotate_mode == ROTATE_90 || rotate_mode == ROTATE_270) {
1729                 ext_win->area[0].xact = win->area[0].yact;
1730                 ext_win->area[0].yact = win->area[0].xact;
1731                 ext_win->area[0].xvir = win->area[0].yact;
1732                 ext_win->area[0].yvir = win->area[0].xact;
1733
1734                 pixel_width = rk_fb_pixel_width(ext_win->area[0].format);
1735                 vir_width_bit = pixel_width * ext_win->area[0].xvir;
1736                 y_stride = ALIGN_N_TIMES(vir_width_bit, 32) / 8;
1737                 ext_win->area[0].y_vir_stride = y_stride >> 2;
1738                 if (is_yuv)
1739                         ext_win->area[0].uv_vir_stride = ext_win->area[0].y_vir_stride;
1740                 else
1741                         ext_win->area[0].uv_vir_stride = 0;
1742         } else {
1743                 ext_win->area[0].xact = win->area[0].xact;
1744                 ext_win->area[0].yact = win->area[0].yact;
1745                 if (win->area[0].xvir == 0)
1746                         ext_win->area[0].xvir = win->area[0].xact;
1747                 else
1748                         ext_win->area[0].xvir = win->area[0].xvir;
1749                 if (win->area[0].yvir == 0)
1750                         ext_win->area[0].yvir = win->area[0].yact;
1751                 else
1752                         ext_win->area[0].yvir = win->area[0].yvir;
1753                 ext_win->area[0].y_vir_stride = win->area[0].y_vir_stride;
1754                 if (is_yuv)
1755                         ext_win->area[0].uv_vir_stride = win->area[0].uv_vir_stride;
1756                 else
1757                         ext_win->area[0].uv_vir_stride = 0;
1758         }
1759
1760         if (win->area[0].xpos != 0 || win->area[0].ypos != 0) {
1761                 if (rotate_mode == ROTATE_270) {
1762                         int xbom_pos = 0, ybom_pos = 0;
1763                         int xtop_pos = 0, ytop_pos = 0;
1764
1765                         ext_win->area[0].xsize =
1766                                 hdmi_xsize * win->area[0].ysize / screen->mode.yres;
1767                         ext_win->area[0].ysize =
1768                                 hdmi_ysize * win->area[0].xsize / screen->mode.xres;
1769                         xbom_pos =
1770                                 hdmi_xsize * win->area[0].ypos / screen->mode.yres;
1771                         ybom_pos = hdmi_ysize * win->area[0].xpos / screen->mode.xres;
1772                         xtop_pos = hdmi_xsize - ext_win->area[0].xsize - xbom_pos;
1773                         ytop_pos = hdmi_ysize - ext_win->area[0].ysize - ybom_pos;
1774                         ext_win->area[0].xpos =
1775                                 ((ext_screen->mode.xres - hdmi_xsize) >> 1) + xtop_pos;
1776                         ext_win->area[0].ypos =
1777                                 ((ext_screen->mode.yres - hdmi_ysize) >> 1) + ytop_pos;
1778                 } else if (rotate_mode == ROTATE_90) {
1779                         ext_win->area[0].xsize =
1780                                 hdmi_xsize * win->area[0].ysize / screen->mode.yres;
1781                         ext_win->area[0].ysize =
1782                                 hdmi_ysize * win->area[0].xsize / screen->mode.xres;
1783                         ext_win->area[0].xpos =
1784                                 ((ext_screen->mode.xres - hdmi_xsize) >> 1) +
1785                                 hdmi_xsize * win->area[0].ypos / screen->mode.yres;
1786                         ext_win->area[0].ypos =
1787                                 ((ext_screen->mode.yres - hdmi_ysize) >> 1) +
1788                                 hdmi_ysize * win->area[0].xpos / screen->mode.xres;
1789                 } else {
1790                         ext_win->area[0].xsize =
1791                                 hdmi_xsize * win->area[0].xsize / screen->mode.xres;
1792                         ext_win->area[0].ysize =
1793                                 hdmi_ysize * win->area[0].ysize / screen->mode.yres;
1794                         ext_win->area[0].xpos =
1795                                 ((ext_screen->mode.xres - hdmi_xsize) >> 1) +
1796                                 hdmi_xsize * win->area[0].xpos / screen->mode.xres;
1797                         ext_win->area[0].ypos =
1798                                 ((ext_screen->mode.yres - hdmi_ysize) >> 1) +
1799                                 hdmi_ysize * win->area[0].ypos / screen->mode.yres;
1800                 }
1801         } else {
1802                 ext_win->area[0].xsize = hdmi_xsize;
1803                 ext_win->area[0].ysize = hdmi_ysize;
1804                 ext_win->area[0].xpos =
1805                         (ext_screen->mode.xres - hdmi_xsize) >> 1;
1806                 ext_win->area[0].ypos =
1807                         (ext_screen->mode.yres - hdmi_ysize) >> 1;
1808         }
1809
1810         return 0;
1811 }
1812
1813 static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
1814                                 struct rk_lcdc_win *win,
1815                                 struct rk_fb_reg_win_data *reg_win_data)
1816 {
1817         int i = 0;
1818         struct rk_fb *inf = platform_get_drvdata(fb_pdev);
1819         struct rk_screen *cur_screen;
1820         struct rk_screen primary_screen;
1821
1822         if (unlikely(!inf) || unlikely(!dev_drv) ||
1823             unlikely(!win) || unlikely(!reg_win_data))
1824                 return;
1825
1826         cur_screen = dev_drv->cur_screen;
1827         rk_fb_get_prmry_screen(&primary_screen);
1828
1829         win->area_num = reg_win_data->area_num;
1830         win->id = reg_win_data->win_id;
1831         win->z_order = reg_win_data->z_order;
1832
1833         if (reg_win_data->reg_area_data[0].smem_start > 0) {
1834                 win->state = 1;
1835                 win->area_num = reg_win_data->area_num;
1836                 win->id = reg_win_data->win_id;
1837                 win->z_order = reg_win_data->z_order;
1838                 win->area[0].uv_vir_stride =
1839                     reg_win_data->reg_area_data[0].uv_vir_stride;
1840                 win->area[0].cbr_start =
1841                     reg_win_data->reg_area_data[0].cbr_start;
1842                 win->area[0].c_offset = reg_win_data->reg_area_data[0].c_offset;
1843                 win->alpha_en = reg_win_data->alpha_en;
1844                 win->alpha_mode = reg_win_data->alpha_mode;
1845                 win->g_alpha_val = reg_win_data->g_alpha_val;
1846                 win->mirror_en = reg_win_data->mirror_en;
1847                 win->area[0].fbdc_en =
1848                         reg_win_data->reg_area_data[0].fbdc_en;
1849                 win->area[0].fbdc_cor_en =
1850                         reg_win_data->reg_area_data[0].fbdc_cor_en;
1851                 win->area[0].fbdc_data_format =
1852                         reg_win_data->reg_area_data[0].fbdc_data_format;
1853                 for (i = 0; i < RK_WIN_MAX_AREA; i++) {
1854                         if (reg_win_data->reg_area_data[i].smem_start > 0) {
1855                                 win->area[i].format =
1856                                         reg_win_data->reg_area_data[i].data_format;
1857                                 if (inf->disp_policy != DISPLAY_POLICY_BOX)
1858                                         win->area[i].ion_hdl =
1859                                         reg_win_data->reg_area_data[i].ion_handle;
1860                                 win->area[i].smem_start =
1861                                         reg_win_data->reg_area_data[i].smem_start;
1862                                 if (inf->disp_mode == DUAL ||
1863                                     inf->disp_policy == DISPLAY_POLICY_BOX) {
1864                                         win->area[i].xpos =
1865                                                 reg_win_data->reg_area_data[i].xpos;
1866                                         win->area[i].ypos =
1867                                                 reg_win_data->reg_area_data[i].ypos;
1868                                         win->area[i].xsize =
1869                                                 reg_win_data->reg_area_data[i].xsize;
1870                                         win->area[i].ysize =
1871                                                 reg_win_data->reg_area_data[i].ysize;
1872                                 } else {
1873                                         win->area[i].xpos =
1874                                                 reg_win_data->reg_area_data[i].xpos *
1875                                                 cur_screen->mode.xres /
1876                                                 primary_screen.mode.xres;
1877                                         win->area[i].ypos =
1878                                                 reg_win_data->reg_area_data[i].ypos *
1879                                                 cur_screen->mode.yres /
1880                                                 primary_screen.mode.yres;
1881                                         win->area[i].xsize =
1882                                                 reg_win_data->reg_area_data[i].xsize *
1883                                                 cur_screen->mode.xres /
1884                                                 primary_screen.mode.xres;
1885                                         win->area[i].ysize =
1886                                                 reg_win_data->reg_area_data[i].ysize *
1887                                                 cur_screen->mode.yres /
1888                                                 primary_screen.mode.yres;
1889
1890                                         /* recalc display size if set hdmi scaler when at ONE_DUAL mode */
1891                                         if (inf->disp_mode == ONE_DUAL && hdmi_switch_complete) {
1892                                                 if (cur_screen->xsize > 0 &&
1893                                                     cur_screen->xsize <= cur_screen->mode.xres) {
1894                                                         win->area[i].xpos =
1895                                                                 ((cur_screen->mode.xres - cur_screen->xsize) >> 1) +
1896                                                                 cur_screen->xsize * win->area[i].xpos / cur_screen->mode.xres;
1897                                                         win->area[i].xsize =
1898                                                                 win->area[i].xsize * cur_screen->xsize / cur_screen->mode.xres;
1899                                                 }
1900                                                 if (cur_screen->ysize > 0 && cur_screen->ysize <= cur_screen->mode.yres) {
1901                                                         win->area[i].ypos =
1902                                                                 ((cur_screen->mode.yres - cur_screen->ysize) >> 1) +
1903                                                                 cur_screen->ysize * win->area[i].ypos / cur_screen->mode.yres;
1904                                                         win->area[i].ysize =
1905                                                                 win->area[i].ysize * cur_screen->ysize / cur_screen->mode.yres;
1906                                                 }
1907                                         }
1908                                 }
1909                                 win->area[i].xact =
1910                                     reg_win_data->reg_area_data[i].xact;
1911                                 win->area[i].yact =
1912                                     reg_win_data->reg_area_data[i].yact;
1913                                 win->area[i].xvir =
1914                                     reg_win_data->reg_area_data[i].xvir;
1915                                 win->area[i].yvir =
1916                                     reg_win_data->reg_area_data[i].yvir;
1917                                 win->area[i].xoff =
1918                                     reg_win_data->reg_area_data[i].xoff;
1919                                 win->area[i].yoff =
1920                                     reg_win_data->reg_area_data[i].yoff;
1921                                 win->area[i].y_offset =
1922                                     reg_win_data->reg_area_data[i].y_offset;
1923                                 win->area[i].y_vir_stride =
1924                                     reg_win_data->reg_area_data[i].y_vir_stride;
1925                                 win->area[i].state = 1;
1926                         } else {
1927                                 win->area[i].state = 0;
1928                         }
1929                 }
1930         } else {
1931         /*
1932                 win->state = 0;
1933                 win->z_order = -1;
1934         */
1935         }
1936 }
1937
1938 static struct rk_fb_reg_win_data *rk_fb_get_win_data(struct rk_fb_reg_data
1939                                                      *regs, int win_id)
1940 {
1941         int i;
1942         struct rk_fb_reg_win_data *win_data = NULL;
1943         for (i = 0; i < regs->win_num; i++) {
1944                 if (regs->reg_win_data[i].win_id == win_id) {
1945                         win_data = &(regs->reg_win_data[i]);
1946                         break;
1947                 }
1948         }
1949
1950         return win_data;
1951 }
1952
1953 static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
1954                              struct rk_fb_reg_data *regs)
1955 {
1956         int i, j;
1957         struct rk_lcdc_win *win;
1958         ktime_t timestamp = dev_drv->vsync_info.timestamp;
1959         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1960 #if defined(CONFIG_RK_HDMI)
1961         struct rk_lcdc_driver *ext_dev_drv;
1962         struct rk_lcdc_win *ext_win;
1963 #endif
1964         struct rk_fb_reg_win_data *win_data;
1965         bool wait_for_vsync;
1966         int count = 100;
1967         unsigned int dsp_addr[4];
1968         long timeout;
1969
1970         /* acq_fence wait */
1971         for (i = 0; i < regs->win_num; i++) {
1972                 win_data = &regs->reg_win_data[i];
1973                 for (j = 0; j < RK_WIN_MAX_AREA; j++) {
1974                         if (win_data->reg_area_data[j].acq_fence) {
1975                                 /* printk("acq_fence wait!!!!!\n"); */
1976                                 rk_fd_fence_wait(dev_drv, win_data->reg_area_data[j].acq_fence);
1977                         }
1978                 }
1979         }
1980
1981         for (i = 0; i < dev_drv->lcdc_win_num; i++) {
1982                 win = dev_drv->win[i];
1983                 win_data = rk_fb_get_win_data(regs, i);
1984                 if (win_data) {
1985                         if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
1986                             (win_data->reg_area_data[0].data_format == YUV420 ||
1987                              win_data->reg_area_data[0].data_format == YUV420_A))
1988                                 continue;
1989                         mutex_lock(&dev_drv->win_config);
1990                         rk_fb_update_win(dev_drv, win, win_data);
1991                         win->state = 1;
1992                         dev_drv->ops->set_par(dev_drv, i);
1993                         dev_drv->ops->pan_display(dev_drv, i);
1994                         mutex_unlock(&dev_drv->win_config);
1995 #if defined(CONFIG_ROCKCHIP_IOMMU)
1996                         if (dev_drv->iommu_enabled) {
1997                                 g_last_addr[i] = win_data->reg_area_data[0].smem_start +
1998                                         win_data->reg_area_data[0].y_offset;
1999                         }
2000 #endif
2001                 } else {
2002                         win->z_order = -1;
2003                         win->state = 0;
2004                 }
2005         }
2006         dev_drv->ops->ovl_mgr(dev_drv, 0, 1);
2007         if (rk_fb->disp_policy == DISPLAY_POLICY_BOX)
2008                 dev_drv->ops->cfg_done(dev_drv);
2009 #if defined(CONFIG_RK_HDMI)
2010         if ((rk_fb->disp_mode == DUAL)
2011             && (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
2012             && hdmi_switch_complete) {
2013                 ext_dev_drv = rk_get_extend_lcdc_drv();
2014                 if (!ext_dev_drv) {
2015                         printk(KERN_ERR "hdmi lcdc driver not found!\n");
2016                         goto ext_win_exit;
2017                 }
2018
2019                 /*
2020                   * For RK3288: win0 and win1 have only one area and support scale
2021                   * but win2 and win3 don't support scale
2022                   * so hdmi only use win0 or win1
2023                   */
2024                 for (i = 0; i < 2; i++) {
2025                         win = dev_drv->win[i];
2026                         ext_win = ext_dev_drv->win[i];
2027                         ext_win->state = win->state;
2028                         ext_win->id = win->id;
2029                         if (!ext_win->state)
2030                                 continue;
2031                         rk_fb_update_ext_win(ext_dev_drv, dev_drv, ext_win, win);
2032                         rk_fb_set_ext_win_buffer(ext_win, win,
2033                                                  ext_dev_drv->rotate_mode,
2034                                                  ext_dev_drv->iommu_enabled);
2035
2036                         if (ext_dev_drv->rotate_mode > X_Y_MIRROR)
2037                                 rk_fb_win_rotate(ext_win, win,
2038                                                  ext_dev_drv->rotate_mode,
2039                                                  ext_dev_drv->iommu_enabled);
2040
2041                         ext_dev_drv->ops->set_par(ext_dev_drv, i);
2042                         ext_dev_drv->ops->pan_display(ext_dev_drv, i);
2043                 }
2044
2045                 ext_dev_drv->ops->cfg_done(ext_dev_drv);
2046         }
2047 ext_win_exit:
2048 #endif
2049         dev_drv->ops->cfg_done(dev_drv);
2050
2051         do {
2052                 timestamp = dev_drv->vsync_info.timestamp;
2053                 timeout = wait_event_interruptible_timeout(dev_drv->vsync_info.wait,
2054                                 ktime_compare(dev_drv->vsync_info.timestamp, timestamp) > 0,
2055                                 msecs_to_jiffies(25));
2056 #if defined(CONFIG_RK_HDMI)
2057                 if ((rk_fb->disp_mode == DUAL) &&
2058                     (hdmi_get_hotplug() == HDMI_HPD_ACTIVED) &&
2059                     hdmi_switch_complete) {
2060                         /*
2061                          * If dual output, we need make sure the extend display
2062                          * cfg take effect before release fence.
2063                          */
2064                         ext_dev_drv = rk_get_extend_lcdc_drv();
2065                         timeout = wait_event_interruptible_timeout(ext_dev_drv->vsync_info.wait,
2066                                         ktime_compare(ext_dev_drv->vsync_info.timestamp, timestamp) > 0,
2067                                         msecs_to_jiffies(25));
2068                 }
2069 #endif
2070                 dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
2071                 wait_for_vsync = false;
2072                 for (i = 0; i < dev_drv->lcdc_win_num; i++) {
2073                         if (dev_drv->win[i]->state == 1) {
2074                                 if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
2075                                     (dev_drv->win[i]->area[0].format == YUV420 ||
2076                                      dev_drv->win[i]->area[0].format == YUV420_A ||
2077                                      !strcmp(dev_drv->win[i]->name, "hwc"))) {
2078                                         continue;
2079                                 } else {
2080                                         u32 new_start =
2081                                             dev_drv->win[i]->area[0].smem_start +
2082                                             dev_drv->win[i]->area[0].y_offset;
2083                                         u32 reg_start = dsp_addr[i];
2084
2085                                         if ((rk_fb->disp_policy ==
2086                                              DISPLAY_POLICY_BOX) &&
2087                                             (new_start == 0x0 ||
2088                                              dev_drv->suspend_flag))
2089                                                 continue;
2090                                         if (unlikely(new_start != reg_start)) {
2091                                                 wait_for_vsync = true;
2092                                                 dev_info(dev_drv->dev,
2093                                                        "win%d:new_addr:0x%08x cur_addr:0x%08x--%d\n",
2094                                                        i, new_start, reg_start, 101 - count);
2095                                                 break;
2096                                         }
2097                                 }
2098                         }
2099                 }
2100         } while (wait_for_vsync && count--);
2101 #ifdef H_USE_FENCE
2102         sw_sync_timeline_inc(dev_drv->timeline, 1);
2103 #endif
2104         if (dev_drv->front_regs) {
2105 #if defined(CONFIG_ROCKCHIP_IOMMU)
2106                 if (dev_drv->iommu_enabled) {
2107                         if (dev_drv->ops->mmu_en)
2108                                 dev_drv->ops->mmu_en(dev_drv);
2109                         freed_index = 0;
2110                         g_last_timeout = timeout;
2111                 }
2112 #endif
2113
2114                 mutex_lock(&dev_drv->front_lock);
2115
2116                 for (i = 0; i < dev_drv->front_regs->win_num; i++) {
2117                         win_data = &dev_drv->front_regs->reg_win_data[i];
2118                         rk_fb_free_dma_buf(dev_drv, win_data);
2119                 }
2120                 kfree(dev_drv->front_regs);
2121
2122                 mutex_unlock(&dev_drv->front_lock);
2123
2124 #if defined(CONFIG_ROCKCHIP_IOMMU)
2125                 if (dev_drv->iommu_enabled)
2126                         freed_addr[freed_index] = 0xfefefefe;
2127 #endif
2128         }
2129
2130         mutex_lock(&dev_drv->front_lock);
2131
2132         dev_drv->front_regs = regs;
2133
2134         mutex_unlock(&dev_drv->front_lock);
2135 }
2136
2137 static void rk_fb_update_regs_handler(struct kthread_work *work)
2138 {
2139         struct rk_lcdc_driver *dev_drv =
2140             container_of(work, struct rk_lcdc_driver, update_regs_work);
2141         struct rk_fb_reg_data *data, *next;
2142         /* struct list_head saved_list; */
2143
2144         mutex_lock(&dev_drv->update_regs_list_lock);
2145         saved_list = dev_drv->update_regs_list;
2146         list_replace_init(&dev_drv->update_regs_list, &saved_list);
2147         mutex_unlock(&dev_drv->update_regs_list_lock);
2148
2149         list_for_each_entry_safe(data, next, &saved_list, list) {
2150                 rk_fb_update_reg(dev_drv, data);
2151                 list_del(&data->list);
2152         }
2153
2154         if (dev_drv->wait_fs && list_empty(&dev_drv->update_regs_list))
2155                 wake_up(&dev_drv->update_regs_wait);
2156 }
2157
2158 static int rk_fb_check_config_var(struct rk_fb_area_par *area_par,
2159                                   struct rk_screen *screen)
2160 {
2161         if ((area_par->x_offset + area_par->xact > area_par->xvir) ||
2162             (area_par->xact <= 0) || (area_par->yact <= 0) ||
2163             (area_par->xvir <= 0) || (area_par->yvir <= 0)) {
2164                 pr_err("check config var fail 0:\n"
2165                        "x_offset=%d,xact=%d,xvir=%d\n",
2166                        area_par->x_offset, area_par->xact, area_par->xvir);
2167                 return -EINVAL;
2168         }
2169
2170         if ((area_par->xpos + area_par->xsize > screen->mode.xres) ||
2171             (area_par->ypos + area_par->ysize > screen->mode.yres) ||
2172             (area_par->xsize <= 0) || (area_par->ysize <= 0)) {
2173                 pr_err("check config var fail 1:\n"
2174                        "xpos=%d,xsize=%d,xres=%d\n"
2175                        "ypos=%d,ysize=%d,yres=%d\n",
2176                        area_par->xpos, area_par->xsize, screen->mode.xres,
2177                        area_par->ypos, area_par->ysize, screen->mode.yres);
2178                 return -EINVAL;
2179         }
2180         return 0;
2181 }
2182
2183 static int rk_fb_set_win_buffer(struct fb_info *info,
2184                                 struct rk_fb_win_par *win_par,
2185                                 struct rk_fb_reg_win_data *reg_win_data)
2186 {
2187         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
2188         struct fb_fix_screeninfo *fix = &info->fix;
2189         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
2190         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
2191         struct rk_screen *screen = dev_drv->cur_screen;
2192         struct rk_screen primary_screen;
2193         struct fb_info *fbi;
2194         int i, ion_fd, acq_fence_fd;
2195         u32 xvir, yvir;
2196         u32 xoffset, yoffset;
2197
2198         struct ion_handle *hdl;
2199         size_t len;
2200         int index_buf;
2201         u8 fb_data_fmt;
2202         u8 pixel_width;
2203         u32 vir_width_bit;
2204         u32 stride, uv_stride;
2205         u32 stride_32bit_1;
2206         u32 stride_32bit_2;
2207         u16 uv_x_off, uv_y_off, uv_y_act;
2208         u8 is_pic_yuv = 0;
2209         u8 ppixel_a = 0, global_a = 0;
2210         ion_phys_addr_t phy_addr;
2211         int ret = 0;
2212
2213         reg_win_data->reg_area_data[0].smem_start = -1;
2214         reg_win_data->area_num = 0;
2215         fbi = rk_fb->fb[reg_win_data->win_id];
2216         if (win_par->area_par[0].phy_addr == 0) {
2217                 for (i = 0; i < RK_WIN_MAX_AREA; i++) {
2218                         ion_fd = win_par->area_par[i].ion_fd;
2219                         if (ion_fd > 0) {
2220                                 hdl =
2221                                     ion_import_dma_buf(rk_fb->ion_client,
2222                                                        ion_fd);
2223                                 if (IS_ERR(hdl)) {
2224                                         pr_info("%s: Could not import handle:"
2225                                                 " %ld\n", __func__, (long)hdl);
2226                                         /*return -EINVAL; */
2227                                         break;
2228                                 }
2229                                 fbi->screen_base =
2230                                     ion_map_kernel(rk_fb->ion_client, hdl);
2231                                 reg_win_data->area_num++;
2232                                 reg_win_data->reg_area_data[i].ion_handle = hdl;
2233 #ifndef CONFIG_ROCKCHIP_IOMMU
2234                                 ret = ion_phys(rk_fb->ion_client, hdl, &phy_addr,
2235                                                 &len);
2236 #else
2237                                 if (dev_drv->iommu_enabled)
2238                                         ret = ion_map_iommu(dev_drv->dev,
2239                                                                 rk_fb->ion_client,
2240                                                                 hdl,
2241                                                                 (unsigned long *)&phy_addr,
2242                                                                 (unsigned long *)&len);
2243                                 else
2244                                         ret = ion_phys(rk_fb->ion_client, hdl,
2245                                                         &phy_addr, &len);
2246 #endif
2247                                 if (ret < 0) {
2248                                         dev_err(fbi->dev, "ion map to get phy addr failed\n");
2249                                         ion_free(rk_fb->ion_client, hdl);
2250                                         return -ENOMEM;
2251                                 }
2252                                 reg_win_data->reg_area_data[i].smem_start = phy_addr;
2253                                 reg_win_data->area_buf_num++;
2254                                 reg_win_data->reg_area_data[i].index_buf = 1;
2255                         }
2256                 }
2257         } else {
2258                 reg_win_data->reg_area_data[0].smem_start =
2259                     win_par->area_par[0].phy_addr;
2260                 reg_win_data->area_num = 1;
2261                 fbi->screen_base = phys_to_virt(win_par->area_par[0].phy_addr);
2262         }
2263
2264         if (reg_win_data->area_num == 0)
2265                 return 0;
2266
2267         for (i = 0; i < reg_win_data->area_num; i++) {
2268                 acq_fence_fd = win_par->area_par[i].acq_fence_fd;
2269                 index_buf = reg_win_data->reg_area_data[i].index_buf;
2270                 if ((acq_fence_fd > 0) && (index_buf == 1)) {
2271                         reg_win_data->reg_area_data[i].acq_fence =
2272                             sync_fence_fdget(win_par->area_par[i].acq_fence_fd);
2273                 }
2274         }
2275         if (reg_win_data->reg_area_data[0].smem_start > 0) {
2276                 reg_win_data->z_order = win_par->z_order;
2277                 reg_win_data->win_id = win_par->win_id;
2278         } else {
2279                 reg_win_data->z_order = -1;
2280                 reg_win_data->win_id = -1;
2281         }
2282
2283         rk_fb_get_prmry_screen(&primary_screen);
2284         reg_win_data->mirror_en = win_par->mirror_en;
2285         for (i = 0; i < reg_win_data->area_num; i++) {
2286                 if (rk_fb->disp_policy == DISPLAY_POLICY_BOX)
2287                         rk_fb_check_config_var(&win_par->area_par[i], screen);
2288                 else
2289                         rk_fb_check_config_var(&win_par->area_par[i], &primary_screen);
2290
2291                 fb_data_fmt = rk_fb_data_fmt(win_par->area_par[i].data_format, 0);
2292                 reg_win_data->reg_area_data[i].data_format = fb_data_fmt;
2293                 if (fb_data_fmt >= FBDC_RGB_565) {
2294                         reg_win_data->reg_area_data[i].fbdc_en = 1;
2295                         reg_win_data->reg_area_data[i].fbdc_cor_en = 1;
2296                 } else {
2297                         reg_win_data->reg_area_data[i].fbdc_en = 0;
2298                         reg_win_data->reg_area_data[i].fbdc_cor_en = 0;
2299                 }
2300                 pixel_width = rk_fb_pixel_width(fb_data_fmt);
2301
2302                 ppixel_a |= ((fb_data_fmt == ARGB888) ||
2303                              (fb_data_fmt == FBDC_ARGB_888) ||
2304                              (fb_data_fmt == ABGR888)) ? 1 : 0;
2305                 /* visiable pos in panel */
2306                 reg_win_data->reg_area_data[i].xpos = win_par->area_par[i].xpos;
2307                 reg_win_data->reg_area_data[i].ypos = win_par->area_par[i].ypos;
2308
2309                 /* realy size in panel */
2310                 reg_win_data->reg_area_data[i].xsize = win_par->area_par[i].xsize;
2311                 reg_win_data->reg_area_data[i].ysize = win_par->area_par[i].ysize;
2312
2313                 /* realy size in panel */
2314                 reg_win_data->reg_area_data[i].xact = win_par->area_par[i].xact;
2315                 reg_win_data->reg_area_data[i].yact = win_par->area_par[i].yact;
2316
2317                 xoffset = win_par->area_par[i].x_offset;        /* buf offset */
2318                 yoffset = win_par->area_par[i].y_offset;
2319                 reg_win_data->reg_area_data[i].xoff = xoffset;
2320                 reg_win_data->reg_area_data[i].yoff = yoffset;
2321
2322                 xvir = win_par->area_par[i].xvir;
2323                 reg_win_data->reg_area_data[i].xvir = xvir;
2324                 yvir = win_par->area_par[i].yvir;
2325                 reg_win_data->reg_area_data[i].yvir = yvir;
2326
2327                 vir_width_bit = pixel_width * xvir;
2328                 /* pixel_width = byte_num*8 */
2329                 stride_32bit_1 = ((vir_width_bit + 31) & (~31)) / 8;
2330                 stride_32bit_2 = ((vir_width_bit * 2 + 31) & (~31)) / 8;
2331
2332                 stride = stride_32bit_1;        /* default rgb */
2333                 fix->line_length = stride;
2334                 reg_win_data->reg_area_data[i].y_vir_stride = stride >> 2;
2335
2336                 /* x y mirror ,jump line
2337                  * reg_win_data->reg_area_data[i].y_offset =
2338                  *              yoffset*stride+xoffset*pixel_width/8;
2339                  */
2340                 if ((screen->y_mirror == 1) || (reg_win_data->mirror_en)) {
2341                         if (screen->interlace == 1) {
2342                                 reg_win_data->reg_area_data[i].y_offset =
2343                                     yoffset * stride * 2 +
2344                                     ((reg_win_data->reg_area_data[i].yact - 1) * 2 + 1) * stride +
2345                                     xoffset * pixel_width / 8;
2346                         } else {
2347                                 reg_win_data->reg_area_data[i].y_offset =
2348                                     yoffset * stride +
2349                                     (reg_win_data->reg_area_data[i].yact - 1) * stride +
2350                                     xoffset * pixel_width / 8;
2351                         }
2352                 } else {
2353                         if (screen->interlace == 1) {
2354                                 reg_win_data->reg_area_data[i].y_offset =
2355                                     yoffset * stride * 2 +
2356                                     xoffset * pixel_width / 8;
2357                         } else {
2358                                 reg_win_data->reg_area_data[i].y_offset =
2359                                     yoffset * stride +
2360                                     xoffset * pixel_width / 8;
2361                         }
2362                 }
2363         }
2364
2365         global_a = (win_par->g_alpha_val == 0) ? 0 : 1;
2366         reg_win_data->alpha_en = ppixel_a | global_a;
2367         reg_win_data->g_alpha_val = win_par->g_alpha_val;
2368         reg_win_data->alpha_mode = win_par->alpha_mode;
2369
2370         switch (fb_data_fmt) {
2371         case YUV422:
2372         case YUV422_A:
2373                 is_pic_yuv = 1;
2374                 stride = stride_32bit_1;
2375                 uv_stride = stride_32bit_1 >> 1;
2376                 uv_x_off = xoffset >> 1;
2377                 uv_y_off = yoffset;
2378                 fix->line_length = stride;
2379                 uv_y_act = win_par->area_par[0].yact >> 1;
2380                 break;
2381         case YUV420:            /* 420sp */
2382         case YUV420_A:
2383                 is_pic_yuv = 1;
2384                 stride = stride_32bit_1;
2385                 uv_stride = stride_32bit_1;
2386                 uv_x_off = xoffset;
2387                 uv_y_off = yoffset >> 1;
2388                 fix->line_length = stride;
2389                 uv_y_act = win_par->area_par[0].yact >> 1;
2390                 break;
2391         case YUV444:
2392         case YUV444_A:
2393                 is_pic_yuv = 1;
2394                 stride = stride_32bit_1;
2395                 uv_stride = stride_32bit_2;
2396                 uv_x_off = xoffset * 2;
2397                 uv_y_off = yoffset;
2398                 fix->line_length = stride << 2;
2399                 uv_y_act = win_par->area_par[0].yact;
2400                 break;
2401         default:
2402                 break;
2403         }
2404         if (is_pic_yuv == 1) {
2405                 reg_win_data->reg_area_data[0].cbr_start =
2406                     reg_win_data->reg_area_data[0].smem_start + xvir * yvir;
2407                 reg_win_data->reg_area_data[0].uv_vir_stride = uv_stride >> 2;
2408                 if ((screen->y_mirror == 1) || (reg_win_data->mirror_en)) {
2409                         if (screen->interlace == 1) {
2410                                 reg_win_data->reg_area_data[0].c_offset =
2411                                     uv_y_off * uv_stride * 2 +
2412                                     ((uv_y_act - 1) * 2 + 1) * uv_stride +
2413                                     uv_x_off * pixel_width / 8;
2414                         } else {
2415                                 reg_win_data->reg_area_data[0].c_offset =
2416                                     uv_y_off * uv_stride +
2417                                     (uv_y_act - 1) * uv_stride +
2418                                     uv_x_off * pixel_width / 8;
2419                         }
2420                 } else {
2421                         if (screen->interlace == 1) {
2422                                 reg_win_data->reg_area_data[0].c_offset =
2423                                     uv_y_off * uv_stride * 2 +
2424                                     uv_x_off * pixel_width / 8;
2425                         } else {
2426                                 reg_win_data->reg_area_data[0].c_offset =
2427                                     uv_y_off * uv_stride +
2428                                     uv_x_off * pixel_width / 8;
2429                         }
2430                 }
2431         }
2432
2433         /* record buffer information for rk_fb_disp_scale to prevent fence timeout
2434          * because rk_fb_disp_scale will call function info->fbops->fb_set_par(info);
2435          */
2436         info->var.yoffset = yoffset;
2437         info->var.xoffset = xoffset;
2438         return 0;
2439 }
2440
2441 static int rk_fb_set_win_config(struct fb_info *info,
2442                                 struct rk_fb_win_cfg_data *win_data)
2443 {
2444         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
2445         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
2446         struct rk_fb_reg_data *regs;
2447 #ifdef H_USE_FENCE
2448         struct sync_fence *release_fence[RK_MAX_BUF_NUM];
2449         struct sync_fence *retire_fence;
2450         struct sync_pt *release_sync_pt[RK_MAX_BUF_NUM];
2451         struct sync_pt *retire_sync_pt;
2452         char fence_name[20];
2453 #endif
2454         int ret = 0, i, j = 0;
2455         int list_is_empty = 0;
2456
2457         regs = kzalloc(sizeof(struct rk_fb_reg_data), GFP_KERNEL);
2458         if (!regs) {
2459                 printk(KERN_INFO "could not allocate rk_fb_reg_data\n");
2460                 ret = -ENOMEM;
2461                 return ret;
2462         }
2463
2464 /*
2465         regs->post_cfg.xpos = win_data->post_cfg.xpos;
2466         regs->post_cfg.ypos = win_data->post_cfg.ypos;
2467         regs->post_cfg.xsize = win_data->post_cfg.xsize;
2468         regs->post_cfg.ysize = win_data->post_cfg.xsize;
2469 */
2470
2471         for (i = 0; i < dev_drv->lcdc_win_num; i++) {
2472                 if (win_data->win_par[i].win_id < dev_drv->lcdc_win_num) {
2473                         if (rk_fb_set_win_buffer(info, &win_data->win_par[i],
2474                                                         &regs->reg_win_data[j]))
2475                                 return -ENOMEM;
2476                         if (regs->reg_win_data[j].area_num > 0) {
2477                                 regs->win_num++;
2478                                 regs->buf_num +=
2479                                     regs->reg_win_data[j].area_buf_num;
2480                         }
2481                         j++;
2482                 } else {
2483                         printk(KERN_INFO "error:win_id bigger than lcdc_win_num\n");
2484                         printk(KERN_INFO "i=%d,win_id=%d\n", i,
2485                                win_data->win_par[i].win_id);
2486                 }
2487         }
2488
2489         mutex_lock(&dev_drv->output_lock);
2490         if (!(dev_drv->suspend_flag == 0)) {
2491                 rk_fb_update_reg(dev_drv, regs);
2492                 printk(KERN_INFO "suspend_flag = 1\n");
2493                 goto err;
2494         }
2495
2496         dev_drv->timeline_max++;
2497 #ifdef H_USE_FENCE
2498         for (i = 0; i < RK_MAX_BUF_NUM; i++) {
2499                 if (i < regs->buf_num) {
2500                         sprintf(fence_name, "fence%d", i);
2501                         win_data->rel_fence_fd[i] = get_unused_fd();
2502                         if (win_data->rel_fence_fd[i] < 0) {
2503                                 printk(KERN_INFO "rel_fence_fd=%d\n",
2504                                        win_data->rel_fence_fd[i]);
2505                                 ret = -EFAULT;
2506                                 goto err;
2507                         }
2508                         release_sync_pt[i] =
2509                             sw_sync_pt_create(dev_drv->timeline,
2510                                               dev_drv->timeline_max);
2511                         release_fence[i] =
2512                             sync_fence_create(fence_name, release_sync_pt[i]);
2513                         sync_fence_install(release_fence[i],
2514                                            win_data->rel_fence_fd[i]);
2515                 } else {
2516                         win_data->rel_fence_fd[i] = -1;
2517                 }
2518         }
2519
2520         win_data->ret_fence_fd = get_unused_fd();
2521         if (win_data->ret_fence_fd < 0) {
2522                 printk("ret_fence_fd=%d\n", win_data->ret_fence_fd);
2523                 ret = -EFAULT;
2524                 goto err;
2525         }
2526         retire_sync_pt =
2527             sw_sync_pt_create(dev_drv->timeline, dev_drv->timeline_max);
2528         retire_fence = sync_fence_create("ret_fence", retire_sync_pt);
2529         sync_fence_install(retire_fence, win_data->ret_fence_fd);
2530 #else
2531         for (i = 0; i < RK_MAX_BUF_NUM; i++)
2532                 win_data->rel_fence_fd[i] = -1;
2533
2534         win_data->ret_fence_fd = -1;
2535 #endif
2536         if (dev_drv->wait_fs == 0) {
2537                 mutex_lock(&dev_drv->update_regs_list_lock);
2538                 list_add_tail(&regs->list, &dev_drv->update_regs_list);
2539                 mutex_unlock(&dev_drv->update_regs_list_lock);
2540                 queue_kthread_work(&dev_drv->update_regs_worker,
2541                                    &dev_drv->update_regs_work);
2542         } else {
2543                 mutex_lock(&dev_drv->update_regs_list_lock);
2544                 list_is_empty = list_empty(&dev_drv->update_regs_list) &&
2545                                         list_empty(&saved_list);
2546                 mutex_unlock(&dev_drv->update_regs_list_lock);
2547                 if (!list_is_empty) {
2548                         ret = wait_event_timeout(dev_drv->update_regs_wait,
2549                                 list_empty(&dev_drv->update_regs_list) && list_empty(&saved_list),
2550                                 msecs_to_jiffies(60));
2551                         if (ret > 0)
2552                                 rk_fb_update_reg(dev_drv, regs);
2553                         else
2554                                 printk("%s: wait update_regs_wait timeout\n", __func__);
2555                 } else if (ret == 0) {
2556                         rk_fb_update_reg(dev_drv, regs);
2557                 }
2558         }
2559
2560 err:
2561         mutex_unlock(&dev_drv->output_lock);
2562         return ret;
2563 }
2564
2565 #if 1
2566 static int cfgdone_distlist[10] = { 0 };
2567
2568 static int cfgdone_index;
2569 static int cfgdone_lasttime;
2570
2571 int rk_get_real_fps(int before)
2572 {
2573         struct timespec now;
2574         int dist_curr;
2575         int dist_total = 0;
2576         int dist_count = 0;
2577         int dist_first = 0;
2578
2579         int index = cfgdone_index;
2580         int i = 0, fps = 0;
2581         int total;
2582
2583         if (before > 100)
2584                 before = 100;
2585         if (before < 0)
2586                 before = 0;
2587
2588         getnstimeofday(&now);
2589         dist_curr = (now.tv_sec * 1000000 + now.tv_nsec / 1000) -
2590                         cfgdone_lasttime;
2591         total = dist_curr;
2592         /*
2593            printk("fps: ");
2594          */
2595         for (i = 0; i < 10; i++) {
2596                 if (--index < 0)
2597                         index = 9;
2598                 total += cfgdone_distlist[index];
2599                 if (i == 0)
2600                         dist_first = cfgdone_distlist[index];
2601                 if (total < (before * 1000)) {
2602                         /*
2603                            printk("[%d:%d] ", dist_count, cfgdone_distlist[index]);
2604                          */
2605                         dist_total += cfgdone_distlist[index];
2606                         dist_count++;
2607                 } else {
2608                         break;
2609                 }
2610         }
2611
2612         /*
2613            printk("total %d, count %d, curr %d, ", dist_total, dist_count, dist_curr);
2614          */
2615         dist_curr = (dist_curr > dist_first) ? dist_curr : dist_first;
2616         dist_total += dist_curr;
2617         dist_count++;
2618
2619         if (dist_total > 0)
2620                 fps = (1000000 * dist_count) / dist_total;
2621         else
2622                 fps = 60;
2623
2624         /*
2625            printk("curr2 %d, fps=%d\n", dist_curr, fps);
2626          */
2627         return fps;
2628 }
2629 EXPORT_SYMBOL(rk_get_real_fps);
2630
2631 #endif
2632 #ifdef CONFIG_ROCKCHIP_IOMMU
2633 #define ION_MAX 10
2634 static struct ion_handle *ion_hanle[ION_MAX];
2635 static struct ion_handle *ion_hwc[1];
2636 #endif
2637 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,
2638                        unsigned long arg)
2639 {
2640         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
2641         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
2642         struct rk_fb_par *extend_fb_par = NULL;
2643         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
2644         struct fb_fix_screeninfo *fix = &info->fix;
2645         int fb_id = 0, extend_win_id = 0;
2646         struct fb_info *extend_info = NULL;
2647         struct rk_lcdc_driver *extend_dev_drv = NULL;
2648         struct rk_lcdc_win *extend_win = NULL;
2649         struct rk_lcdc_win *win;
2650         int enable;     /* enable fb:1 enable;0 disable */
2651         int ovl;        /* overlay:0 win1 on the top of win0;1,win0 on the top of win1 */
2652         int num_buf;    /* buffer_number */
2653         int ret;
2654         struct rk_fb_win_cfg_data win_data;
2655         unsigned int dsp_addr[4];
2656         int list_stat;
2657
2658         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
2659
2660         void __user *argp = (void __user *)arg;
2661         win = dev_drv->win[win_id];
2662         if (rk_fb->disp_mode == DUAL) {
2663                 fb_id = get_extend_fb_id(info);
2664                 extend_info = rk_fb->fb[(rk_fb->num_fb >> 1) + fb_id];
2665                 extend_fb_par = (struct rk_fb_par *)extend_info->par;
2666                 extend_dev_drv = extend_fb_par->lcdc_drv;
2667                 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
2668                                                             extend_info->fix.id);
2669                 extend_win = extend_dev_drv->win[extend_win_id];
2670         }
2671
2672         switch (cmd) {
2673         case RK_FBIOSET_HWC_ADDR:
2674         {
2675                 u32 hwc_phy[1];
2676                 if (copy_from_user(hwc_phy, argp, 4))
2677                         return -EFAULT;
2678 #ifdef CONFIG_ROCKCHIP_IOMMU
2679                 if (!dev_drv->iommu_enabled) {
2680 #endif
2681                         fix->smem_start = hwc_phy[0];
2682 #ifdef CONFIG_ROCKCHIP_IOMMU
2683                 } else {
2684                         int usr_fd;
2685                         struct ion_handle *hdl;
2686                         ion_phys_addr_t phy_addr;
2687                         size_t len;
2688
2689                         usr_fd = hwc_phy[0];
2690                         if (!usr_fd) {
2691                                 fix->smem_start = 0;
2692                                 fix->mmio_start = 0;
2693                                 break;
2694                         }
2695
2696                         if (ion_hwc[0] != 0) {
2697                                 ion_free(rk_fb->ion_client, ion_hwc[0]);
2698                                 ion_hwc[0] = 0;
2699                         }
2700
2701                         hdl = ion_import_dma_buf(rk_fb->ion_client, usr_fd);
2702                         if (IS_ERR(hdl)) {
2703                                 dev_err(info->dev, "failed to get hwc ion handle:%ld\n",
2704                                         PTR_ERR(hdl));
2705                                 return -EFAULT;
2706                         }
2707
2708                         ret = ion_map_iommu(dev_drv->dev, rk_fb->ion_client, hdl,
2709                                                 (unsigned long *)&phy_addr,
2710                                                 (unsigned long *)&len);
2711                         if (ret < 0) {
2712                                 dev_err(info->dev, "ion map to get hwc phy addr failed");
2713                                 ion_free(rk_fb->ion_client, hdl);
2714                                 return -ENOMEM;
2715                         }
2716                         fix->smem_start = phy_addr;
2717                         ion_hwc[0] = hdl;
2718                 }
2719 #endif
2720                 break;
2721         }
2722         case RK_FBIOSET_YUV_ADDR:
2723                 {
2724                         u32 yuv_phy[2];
2725
2726                         if (copy_from_user(yuv_phy, argp, 8))
2727                                 return -EFAULT;
2728                         #ifdef CONFIG_ROCKCHIP_IOMMU
2729                         if (!dev_drv->iommu_enabled || !strcmp(info->fix.id, "fb0")) {
2730                         #endif
2731                                 fix->smem_start = yuv_phy[0];
2732                                 fix->mmio_start = yuv_phy[1];
2733                         #ifdef CONFIG_ROCKCHIP_IOMMU
2734                         } else {
2735                                 int usr_fd, offset, tmp;
2736                                 struct ion_handle *hdl;
2737                                 ion_phys_addr_t phy_addr;
2738                                 size_t len;
2739
2740                                 usr_fd = yuv_phy[0];
2741                                 offset = yuv_phy[1] - yuv_phy[0];
2742
2743                                 if (!usr_fd) {
2744                                         fix->smem_start = 0;
2745                                         fix->mmio_start = 0;
2746                                         break;
2747                                 }
2748
2749                                 if (ion_hanle[ION_MAX - 1] != 0) {
2750                                         /*ion_unmap_kernel(rk_fb->ion_client, ion_hanle[ION_MAX - 1]);*/
2751                                         /*ion_unmap_iommu(dev_drv->dev, rk_fb->ion_client, ion_hanle[ION_MAX - 1]);*/
2752                                         ion_free(rk_fb->ion_client, ion_hanle[ION_MAX - 1]);
2753                                         ion_hanle[ION_MAX - 1] = 0;
2754                                 }
2755
2756                                 hdl = ion_import_dma_buf(rk_fb->ion_client, usr_fd);
2757                                 if (IS_ERR(hdl)) {
2758                                         dev_err(info->dev, "failed to get ion handle:%ld\n",
2759                                                 PTR_ERR(hdl));
2760                                         return -EFAULT;
2761                                 }
2762
2763                                 ret = ion_map_iommu(dev_drv->dev, rk_fb->ion_client, hdl,
2764                                                         (unsigned long *)&phy_addr,
2765                                                         (unsigned long *)&len);
2766                                 if (ret < 0) {
2767                                         dev_err(info->dev, "ion map to get phy addr failed");
2768                                         ion_free(rk_fb->ion_client, hdl);
2769                                         return -ENOMEM;
2770                                 }
2771                                 fix->smem_start = phy_addr;
2772                                 fix->mmio_start = phy_addr + offset;
2773                                 fix->smem_len = len;
2774                                 /*info->screen_base = ion_map_kernel(rk_fb->ion_client, hdl);*/
2775
2776                                 ion_hanle[0] = hdl;
2777                                 for (tmp = ION_MAX - 1; tmp > 0; tmp--)
2778                                         ion_hanle[tmp] = ion_hanle[tmp - 1];
2779                                 ion_hanle[0] = 0;
2780                         }
2781                         #endif
2782                         break;
2783                 }
2784         case RK_FBIOSET_ENABLE:
2785                 if (copy_from_user(&enable, argp, sizeof(enable)))
2786                         return -EFAULT;
2787                                 if (enable)
2788                                         fb_par->state++;
2789                                 else
2790                                         fb_par->state--;
2791                 dev_drv->ops->open(dev_drv, win_id, enable);
2792                 break;
2793         case RK_FBIOGET_ENABLE:
2794                 enable = dev_drv->ops->get_win_state(dev_drv, win_id);
2795                 if (copy_to_user(argp, &enable, sizeof(enable)))
2796                         return -EFAULT;
2797                 break;
2798         case RK_FBIOSET_OVERLAY_STA:
2799                 if (copy_from_user(&ovl, argp, sizeof(ovl)))
2800                         return -EFAULT;
2801                 dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
2802                 break;
2803         case RK_FBIOGET_OVERLAY_STA:
2804                 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
2805                 if (copy_to_user(argp, &ovl, sizeof(ovl)))
2806                         return -EFAULT;
2807                 break;
2808         case RK_FBIOPUT_NUM_BUFFERS:
2809                 if (copy_from_user(&num_buf, argp, sizeof(num_buf)))
2810                         return -EFAULT;
2811                 dev_drv->num_buf = num_buf;
2812                 break;
2813         case RK_FBIOSET_VSYNC_ENABLE:
2814                 if (copy_from_user(&enable, argp, sizeof(enable)))
2815                         return -EFAULT;
2816                 dev_drv->vsync_info.active = enable;
2817                 break;
2818
2819         case RK_FBIOGET_DSP_ADDR:
2820                 dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
2821                 if (copy_to_user(argp, &dsp_addr, sizeof(dsp_addr)))
2822                         return -EFAULT;
2823                 break;
2824         case RK_FBIOGET_LIST_STA:
2825                 list_stat = rk_fb_get_list_stat(dev_drv);
2826                 if (copy_to_user(argp, &list_stat, sizeof(list_stat)))
2827                         return -EFAULT;
2828
2829                 break;
2830         case RK_FBIOGET_IOMMU_STA:
2831                 if (copy_to_user(argp, &dev_drv->iommu_enabled,
2832                                  sizeof(dev_drv->iommu_enabled)))
2833                         return -EFAULT;
2834                 break;
2835 #if defined(CONFIG_ION_ROCKCHIP)
2836         case RK_FBIOSET_DMABUF_FD:
2837                 {
2838                         int usr_fd;
2839                         struct ion_handle *hdl;
2840                         ion_phys_addr_t phy_addr;
2841                         size_t len;
2842                         if (copy_from_user(&usr_fd, argp, sizeof(usr_fd)))
2843                                 return -EFAULT;
2844                         hdl = ion_import_dma_buf(rk_fb->ion_client, usr_fd);
2845                         ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
2846                         fix->smem_start = phy_addr;
2847                         break;
2848                 }
2849         case RK_FBIOGET_DMABUF_FD:
2850                 {
2851                         int fd = -1;
2852
2853                         if (IS_ERR_OR_NULL(fb_par->ion_hdl)) {
2854                                 dev_err(info->dev,
2855                                         "get dma_buf fd failed,ion handle is err\n");
2856                                 return PTR_ERR(fb_par->ion_hdl);
2857                         }
2858                         fd = ion_share_dma_buf_fd(rk_fb->ion_client,
2859                                                   fb_par->ion_hdl);
2860                         if (fd < 0) {
2861                                 dev_err(info->dev,
2862                                         "ion_share_dma_buf_fd failed\n");
2863                                 return fd;
2864                         }
2865                         if (copy_to_user(argp, &fd, sizeof(fd)))
2866                                 return -EFAULT;
2867                         break;
2868                 }
2869 #endif
2870         case RK_FBIOSET_CLEAR_FB:
2871                 memset(fb_par->fb_virt_base, 0, fb_par->fb_size);
2872                 break;
2873         case RK_FBIOSET_CONFIG_DONE:
2874                 {
2875                         int curr = 0;
2876                         struct timespec now;
2877
2878                         getnstimeofday(&now);
2879                         curr = now.tv_sec * 1000000 + now.tv_nsec / 1000;
2880                         cfgdone_distlist[cfgdone_index++] =
2881                             curr - cfgdone_lasttime;
2882                         /*
2883                            printk("%d ", curr - cfgdone_lasttime);
2884                          */
2885                         cfgdone_lasttime = curr;
2886                         if (cfgdone_index >= 10)
2887                                 cfgdone_index = 0;
2888                 }
2889                 if (copy_from_user(&win_data,
2890                                    (struct rk_fb_win_cfg_data __user *)argp,
2891                                    sizeof(win_data))) {
2892                         ret = -EFAULT;
2893                         break;
2894                 };
2895
2896                 dev_drv->wait_fs = win_data.wait_fs;
2897                 rk_fb_set_win_config(info, &win_data);
2898
2899                 if (copy_to_user((struct rk_fb_win_cfg_data __user *)arg,
2900                                  &win_data, sizeof(win_data))) {
2901                         ret = -EFAULT;
2902                         break;
2903                 }
2904                 memset(&win_data, 0, sizeof(struct rk_fb_win_cfg_data));
2905                 break;
2906         default:
2907                 dev_drv->ops->ioctl(dev_drv, cmd, arg, win_id);
2908                 break;
2909         }
2910
2911         return 0;
2912 }
2913
2914 static int rk_fb_blank(int blank_mode, struct fb_info *info)
2915 {
2916         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
2917         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
2918         struct fb_fix_screeninfo *fix = &info->fix;
2919         int win_id;
2920 #if defined(CONFIG_RK_HDMI)
2921         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
2922 #endif
2923
2924         win_id = dev_drv->ops->fb_get_win_id(dev_drv, fix->id);
2925         if (win_id < 0)
2926                 return -ENODEV;
2927 #if defined(CONFIG_RK_HDMI)
2928         if ((rk_fb->disp_mode == ONE_DUAL) &&
2929             (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)) {
2930                 printk(KERN_INFO "hdmi is connect , not blank lcdc\n");
2931         } else
2932 #endif
2933         {
2934                 dev_drv->ops->blank(dev_drv, win_id, blank_mode);
2935         }
2936         return 0;
2937 }
2938
2939 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2940 {
2941         if ((0 == var->xres_virtual) || (0 == var->yres_virtual) ||
2942             (0 == var->xres) || (0 == var->yres) || (var->xres < 16) ||
2943             ((16 != var->bits_per_pixel) &&
2944             (32 != var->bits_per_pixel) &&
2945             (24 != var->bits_per_pixel))) {
2946                 dev_err(info->dev, "%s check var fail 1:\n"
2947                         "xres_vir:%d>>yres_vir:%d\n"
2948                         "xres:%d>>yres:%d\n"
2949                         "bits_per_pixel:%d\n",
2950                         info->fix.id,
2951                         var->xres_virtual,
2952                         var->yres_virtual,
2953                         var->xres, var->yres, var->bits_per_pixel);
2954                 return -EINVAL;
2955         }
2956
2957         if (((var->xoffset + var->xres) > var->xres_virtual) ||
2958             ((var->yoffset + var->yres) > (var->yres_virtual))) {
2959                 dev_err(info->dev, "%s check_var fail 2:\n"
2960                         "xoffset:%d>>xres:%d>>xres_vir:%d\n"
2961                         "yoffset:%d>>yres:%d>>yres_vir:%d\n",
2962                         info->fix.id,
2963                         var->xoffset,
2964                         var->xres,
2965                         var->xres_virtual,
2966                         var->yoffset, var->yres, var->yres_virtual);
2967                 return -EINVAL;
2968         }
2969
2970         return 0;
2971 }
2972
2973 static ssize_t rk_fb_read(struct fb_info *info, char __user *buf,
2974                           size_t count, loff_t *ppos)
2975 {
2976         unsigned long p = *ppos;
2977         u8 *buffer, *dst;
2978         u8 __iomem *src;
2979         int c, cnt = 0, err = 0;
2980         unsigned long total_size;
2981         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
2982         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
2983         struct rk_lcdc_win *win = NULL;
2984         int win_id = 0;
2985
2986         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
2987         if (win_id < 0)
2988                 return -ENODEV;
2989         else
2990                 win = dev_drv->win[win_id];
2991
2992         /* only read the current frame buffer */
2993         if (win->area[0].format == RGB565) {
2994                 total_size = win->area[0].y_vir_stride * win->area[0].yact << 1;
2995         } else if (win->area[0].format == YUV420) {
2996                 total_size =
2997                     (win->area[0].y_vir_stride * win->area[0].yact * 6);
2998         } else {
2999                 total_size = win->area[0].y_vir_stride * win->area[0].yact << 2;
3000         }
3001         if (p >= total_size)
3002                 return 0;
3003
3004         if (count >= total_size)
3005                 count = total_size;
3006
3007         if (count + p > total_size)
3008                 count = total_size - p;
3009
3010         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
3011         if (!buffer)
3012                 return -ENOMEM;
3013
3014         src = (u8 __iomem *)(info->screen_base + p + win->area[0].y_offset);
3015
3016         while (count) {
3017                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
3018                 dst = buffer;
3019                 fb_memcpy_fromfb(dst, src, c);
3020                 dst += c;
3021                 src += c;
3022
3023                 if (copy_to_user(buf, buffer, c)) {
3024                         err = -EFAULT;
3025                         break;
3026                 }
3027                 *ppos += c;
3028                 buf += c;
3029                 cnt += c;
3030                 count -= c;
3031         }
3032
3033         kfree(buffer);
3034
3035         return (err) ? err : cnt;
3036 }
3037
3038 static ssize_t rk_fb_write(struct fb_info *info, const char __user *buf,
3039                            size_t count, loff_t *ppos)
3040 {
3041         unsigned long p = *ppos;
3042         u8 *buffer, *src;
3043         u8 __iomem *dst;
3044         int c, cnt = 0, err = 0;
3045         unsigned long total_size;
3046         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
3047         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
3048         struct rk_lcdc_win *win = NULL;
3049         int win_id = 0;
3050
3051         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
3052         if (win_id < 0)
3053                 return -ENODEV;
3054         else
3055                 win = dev_drv->win[win_id];
3056
3057         /* write the current frame buffer */
3058         if (win->area[0].format == RGB565)
3059                 total_size = win->area[0].xact * win->area[0].yact << 1;
3060         else
3061                 total_size = win->area[0].xact * win->area[0].yact << 2;
3062
3063         if (p > total_size)
3064                 return -EFBIG;
3065
3066         if (count > total_size) {
3067                 err = -EFBIG;
3068                 count = total_size;
3069         }
3070
3071         if (count + p > total_size) {
3072                 if (!err)
3073                         err = -ENOSPC;
3074
3075                 count = total_size - p;
3076         }
3077
3078         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
3079         if (!buffer)
3080                 return -ENOMEM;
3081
3082         dst = (u8 __iomem *)(info->screen_base + p + win->area[0].y_offset);
3083
3084         while (count) {
3085                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
3086                 src = buffer;
3087
3088                 if (copy_from_user(src, buf, c)) {
3089                         err = -EFAULT;
3090                         break;
3091                 }
3092
3093                 fb_memcpy_tofb(dst, src, c);
3094                 dst += c;
3095                 src += c;
3096                 *ppos += c;
3097                 buf += c;
3098                 cnt += c;
3099                 count -= c;
3100         }
3101
3102         kfree(buffer);
3103
3104         return (cnt) ? cnt : err;
3105 }
3106
3107 /*
3108  * function: update extend info acorrding to primary info that only used for dual display mode
3109  * @ext_info: the fb_info of extend screen
3110  * @info: the fb_info of primary screen
3111  * @update_buffer: whether to update extend info buffer, 0: no;1: yes
3112  */
3113 static int rk_fb_update_ext_info(struct fb_info *ext_info,
3114                                         struct fb_info *info, int update_buffer)
3115 {
3116         struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
3117         struct rk_fb_par *fb_par = NULL;
3118         struct rk_fb_par *ext_fb_par = NULL;
3119         struct rk_lcdc_driver *dev_drv = NULL;
3120         struct rk_lcdc_driver *ext_dev_drv = NULL;
3121         struct rk_lcdc_win *win = NULL;
3122         struct rk_lcdc_win *ext_win = NULL;
3123         int win_id = 0, ext_win_id = 0;
3124
3125         if (rk_fb->disp_mode != DUAL || info == ext_info)
3126                 return 0;
3127         if (unlikely(!info) || unlikely(!ext_info))
3128                 return -1;
3129
3130         fb_par = (struct rk_fb_par *)info->par;
3131         ext_fb_par = (struct rk_fb_par *)ext_info->par;
3132         dev_drv = fb_par->lcdc_drv;
3133         ext_dev_drv = ext_fb_par->lcdc_drv;
3134         if (unlikely(!dev_drv) || unlikely(!ext_dev_drv))
3135                 return -1;
3136
3137         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
3138         win = dev_drv->win[win_id];
3139         ext_win_id = ext_dev_drv->ops->fb_get_win_id(ext_dev_drv,
3140                                                      ext_info->fix.id);
3141         ext_win = ext_dev_drv->win[ext_win_id];
3142
3143         rk_fb_update_ext_win(ext_dev_drv, dev_drv, ext_win, win);
3144         if (update_buffer) {
3145                 rk_fb_set_ext_win_buffer(ext_win, win, ext_dev_drv->rotate_mode,
3146                                          ext_dev_drv->iommu_enabled);
3147
3148                 /* update extend info display address */
3149                 ext_info->fix.smem_start = ext_win->area[0].smem_start;
3150                 ext_info->fix.mmio_start = ext_win->area[0].cbr_start;
3151
3152                 if (ext_dev_drv->rotate_mode > X_Y_MIRROR)
3153                         rk_fb_rotate(ext_info, info);
3154         }
3155
3156         /* update extend info */
3157         ext_info->var.xres = ext_win->area[0].xact;
3158         ext_info->var.yres = ext_win->area[0].yact;
3159         ext_info->var.xres_virtual = ext_win->area[0].xvir;
3160         ext_info->var.yres_virtual = ext_win->area[0].yvir;
3161
3162         /* config same data format */
3163         ext_info->var.nonstd &= 0xffffff00;
3164         ext_info->var.nonstd |= (info->var.nonstd & 0xff);
3165
3166         ext_info->var.nonstd &= 0xff;
3167         ext_info->var.nonstd |=
3168                 (ext_win->area[0].xpos << 8) + (ext_win->area[0].ypos << 20);
3169
3170         ext_info->var.grayscale &= 0xff;
3171         ext_info->var.grayscale |=
3172                 (ext_win->area[0].xsize << 8) + (ext_win->area[0].ysize << 20);
3173
3174         return 0;
3175 }
3176
3177 static int rk_fb_set_par(struct fb_info *info)
3178 {
3179         struct fb_var_screeninfo *var = &info->var;
3180         struct fb_fix_screeninfo *fix = &info->fix;
3181         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
3182         struct rk_fb_par *extend_fb_par = NULL;
3183         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
3184         struct rk_fb *rk_fb = dev_get_drvdata(info->device);
3185         int fb_id, extend_win_id = 0;
3186         struct fb_info *extend_info = NULL;
3187         struct rk_lcdc_driver *extend_dev_drv = NULL;
3188         struct rk_lcdc_win *extend_win = NULL;
3189         struct rk_lcdc_win *win = NULL;
3190         struct rk_screen *screen = dev_drv->cur_screen;
3191         int win_id = 0;
3192         u32 cblen = 0, crlen = 0;
3193         u16 xsize = 0, ysize = 0;       /* winx display window height/width --->LCDC_WINx_DSP_INFO */
3194         u32 xoffset = var->xoffset;     /* offset from virtual to visible */
3195         u32 yoffset = var->yoffset;
3196         u16 xpos = (var->nonstd >> 8) & 0xfff;  /*visiable pos in panel */
3197         u16 ypos = (var->nonstd >> 20) & 0xfff;
3198         u32 xvir = var->xres_virtual;
3199         u32 yvir = var->yres_virtual;
3200         u8 data_format = var->nonstd & 0xff;
3201         u8 fb_data_fmt;
3202         u8 pixel_width;
3203         u32 vir_width_bit;
3204         u32 stride, uv_stride;
3205         u32 stride_32bit_1;
3206         u32 stride_32bit_2;
3207         u16 uv_x_off, uv_y_off, uv_y_act;
3208         u8 is_pic_yuv = 0;
3209
3210         var->pixclock = dev_drv->pixclock;
3211         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
3212         if (win_id < 0)
3213                 return -ENODEV;
3214         else
3215                 win = dev_drv->win[win_id];
3216
3217         if (rk_fb->disp_mode == DUAL) {
3218                 fb_id = get_extend_fb_id(info);
3219                 extend_info = rk_fb->fb[(rk_fb->num_fb >> 1) + fb_id];
3220                 extend_fb_par = (struct rk_fb_par *)extend_info->par;
3221                 extend_dev_drv = extend_fb_par->lcdc_drv;
3222                 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
3223                                                             extend_info->fix.id);
3224                 extend_win = extend_dev_drv->win[extend_win_id];
3225         }
3226
3227         /* if the application has specific the horizontal and vertical display size */
3228         if (var->grayscale >> 8) {
3229                 xsize = (var->grayscale >> 8) & 0xfff;
3230                 ysize = (var->grayscale >> 20) & 0xfff;
3231                 if (xsize > screen->mode.xres)
3232                         xsize = screen->mode.xres;
3233                 if (ysize > screen->mode.yres)
3234                         ysize = screen->mode.yres;
3235         } else {                /*ohterwise  full  screen display */
3236                 xsize = screen->mode.xres;
3237                 ysize = screen->mode.yres;
3238         }
3239
3240         fb_data_fmt = rk_fb_data_fmt(data_format, var->bits_per_pixel);
3241         if (fb_data_fmt >= FBDC_RGB_565) {
3242                 win->area[0].fbdc_en = 1;
3243                 win->area[0].fbdc_cor_en = 1;
3244         } else {
3245                 win->area[0].fbdc_en = 0;
3246                 win->area[0].fbdc_cor_en = 0;
3247         }
3248         pixel_width = rk_fb_pixel_width(fb_data_fmt);
3249         vir_width_bit = pixel_width * xvir;
3250         /* pixel_width = byte_num * 8 */
3251         stride_32bit_1 = ALIGN_N_TIMES(vir_width_bit, 32) / 8;
3252         stride_32bit_2 = ALIGN_N_TIMES(vir_width_bit * 2, 32) / 8;
3253
3254         switch (fb_data_fmt) {
3255         case YUV422:
3256         case YUV422_A:
3257                 is_pic_yuv = 1;
3258                 stride = stride_32bit_1;
3259                 uv_stride = stride_32bit_1 >> 1;
3260                 uv_x_off = xoffset >> 1;
3261                 uv_y_off = yoffset;
3262                 fix->line_length = stride;
3263                 cblen = crlen = (xvir * yvir) >> 1;
3264                 uv_y_act = win->area[0].yact >> 1;
3265                 break;
3266         case YUV420:            /* 420sp */
3267         case YUV420_A:
3268                 is_pic_yuv = 1;
3269                 stride = stride_32bit_1;
3270                 uv_stride = stride_32bit_1;
3271                 uv_x_off = xoffset;
3272                 uv_y_off = yoffset >> 1;
3273                 fix->line_length = stride;
3274                 cblen = crlen = (xvir * yvir) >> 2;
3275                 uv_y_act = win->area[0].yact >> 1;
3276                 break;
3277         case YUV444:
3278         case YUV444_A:
3279                 is_pic_yuv = 1;
3280                 stride = stride_32bit_1;
3281                 uv_stride = stride_32bit_2;
3282                 uv_x_off = xoffset * 2;
3283                 uv_y_off = yoffset;
3284                 fix->line_length = stride << 2;
3285                 cblen = crlen = (xvir * yvir);
3286                 uv_y_act = win->area[0].yact;
3287                 break;
3288         default:
3289                 stride = stride_32bit_1;        /* default rgb */
3290                 fix->line_length = stride;
3291                 break;
3292         }
3293
3294         win->area[0].format = fb_data_fmt;
3295         win->area[0].y_vir_stride = stride >> 2;
3296         win->area[0].uv_vir_stride = uv_stride >> 2;
3297         win->area[0].xpos = xpos;
3298         win->area[0].ypos = ypos;
3299         win->area[0].xsize = xsize;
3300         win->area[0].ysize = ysize;
3301         win->area[0].xact = var->xres;  /* winx active window height,is a wint of vir */
3302         win->area[0].yact = var->yres;
3303         win->area[0].xvir = var->xres_virtual;  /* virtual resolution  stride --->LCDC_WINx_VIR */
3304         win->area[0].yvir = var->yres_virtual;
3305         win->area[0].xoff = xoffset;
3306         win->area[0].yoff = yoffset;
3307
3308         win->area_num = 1;
3309         win->alpha_mode = 4;    /* AB_SRC_OVER; */
3310         win->alpha_en = ((win->area[0].format == ARGB888) ||
3311                          (win->area[0].format == FBDC_ARGB_888) ||
3312                          (win->area[0].format == ABGR888)) ? 1 : 0;
3313         win->g_alpha_val = 0;
3314
3315         if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
3316             (win->area[0].format == YUV420 || win->area[0].format == YUV420_A))
3317             win->state = 1;
3318         if (rk_fb->disp_mode == DUAL) {
3319                 if (extend_win->state && hdmi_switch_complete) {
3320                         if (info != extend_info) {
3321                                 rk_fb_update_ext_win(extend_dev_drv, dev_drv,
3322                                                      extend_win, win);
3323                                 extend_dev_drv->ops->set_par(extend_dev_drv,
3324                                                              extend_win_id);
3325                         }
3326                 }
3327         }
3328         dev_drv->ops->set_par(dev_drv, win_id);
3329
3330         return 0;
3331 }
3332
3333 static inline unsigned int chan_to_field(unsigned int chan,
3334                                          struct fb_bitfield *bf)
3335 {
3336         chan &= 0xffff;
3337         chan >>= 16 - bf->length;
3338         return chan << bf->offset;
3339 }
3340
3341 static int fb_setcolreg(unsigned regno,
3342                         unsigned red, unsigned green, unsigned blue,
3343                         unsigned transp, struct fb_info *info)
3344 {
3345         unsigned int val;
3346
3347         switch (info->fix.visual) {
3348         case FB_VISUAL_TRUECOLOR:
3349                 /* true-colour, use pseudo-palette */
3350                 if (regno < 16) {
3351                         u32 *pal = info->pseudo_palette;
3352                         val = chan_to_field(red, &info->var.red);
3353                         val |= chan_to_field(green, &info->var.green);
3354                         val |= chan_to_field(blue, &info->var.blue);
3355                         pal[regno] = val;
3356                 }
3357                 break;
3358         default:
3359                 return -1;      /* unknown type */
3360         }
3361
3362         return 0;
3363 }
3364
3365 static int rk_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
3366 {
3367         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
3368         struct rk_fb_par *fb_par = (struct rk_fb_par *)info->par;
3369         struct ion_handle *handle = fb_par->ion_hdl;
3370         struct dma_buf *dma_buf = NULL;
3371
3372         if (IS_ERR_OR_NULL(handle)) {
3373                 dev_err(info->dev, "failed to get ion handle:%ld\n",
3374                         PTR_ERR(handle));
3375                 return -ENOMEM;
3376         }
3377         dma_buf = ion_share_dma_buf(rk_fb->ion_client, handle);
3378         if (IS_ERR_OR_NULL(dma_buf)) {
3379                 printk("get ion share dma buf failed\n");
3380                 return -ENOMEM;
3381         }
3382
3383         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
3384
3385         return dma_buf_mmap(dma_buf, vma, 0);
3386 }
3387
3388 static struct fb_ops fb_ops = {
3389         .owner = THIS_MODULE,
3390         .fb_open = rk_fb_open,
3391         .fb_release = rk_fb_close,
3392         .fb_check_var = rk_fb_check_var,
3393         .fb_set_par = rk_fb_set_par,
3394         .fb_blank = rk_fb_blank,
3395         .fb_ioctl = rk_fb_ioctl,
3396         .fb_compat_ioctl = rk_fb_ioctl,
3397         .fb_pan_display = rk_fb_pan_display,
3398         .fb_read = rk_fb_read,
3399         .fb_write = rk_fb_write,
3400         .fb_setcolreg = fb_setcolreg,
3401         .fb_fillrect = cfb_fillrect,
3402         .fb_copyarea = cfb_copyarea,
3403         .fb_imageblit = cfb_imageblit,
3404 };
3405
3406 static struct fb_var_screeninfo def_var = {
3407 #if defined(CONFIG_LOGO_LINUX_BMP)
3408         .red = {16, 8, 0},
3409         .green = {8, 8, 0},
3410         .blue = {0, 8, 0},
3411         .transp = {0, 0, 0},
3412         .nonstd = HAL_PIXEL_FORMAT_BGRA_8888,
3413 #else
3414         .red = {11, 5, 0},
3415         .green = {5, 6, 0},
3416         .blue = {0, 5, 0},
3417         .transp = {0, 0, 0},
3418         .nonstd = HAL_PIXEL_FORMAT_RGB_565,     /* (ypos<<20+xpos<<8+format) format */
3419 #endif
3420         .grayscale = 0,         /* (ysize<<20+xsize<<8) */
3421         .activate = FB_ACTIVATE_NOW,
3422         .accel_flags = 0,
3423         .vmode = FB_VMODE_NONINTERLACED,
3424 };
3425
3426 static struct fb_fix_screeninfo def_fix = {
3427         .type = FB_TYPE_PACKED_PIXELS,
3428         .type_aux = 0,
3429         .xpanstep = 1,
3430         .ypanstep = 1,
3431         .ywrapstep = 0,
3432         .accel = FB_ACCEL_NONE,
3433         .visual = FB_VISUAL_TRUECOLOR,
3434
3435 };
3436
3437 static int rk_fb_wait_for_vsync_thread(void *data)
3438 {
3439         struct rk_lcdc_driver *dev_drv = data;
3440         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
3441         struct fb_info *fbi = rk_fb->fb[0];
3442
3443         while (!kthread_should_stop()) {
3444                 ktime_t timestamp = dev_drv->vsync_info.timestamp;
3445                 int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
3446                                 !ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
3447                                 (dev_drv->vsync_info.active || dev_drv->vsync_info.irq_stop));
3448
3449                 if (!ret)
3450                         sysfs_notify(&fbi->dev->kobj, NULL, "vsync");
3451         }
3452
3453         return 0;
3454 }
3455
3456 static ssize_t rk_fb_vsync_show(struct device *dev,
3457                                 struct device_attribute *attr, char *buf)
3458 {
3459         struct fb_info *fbi = dev_get_drvdata(dev);
3460         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
3461         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
3462         return scnprintf(buf, PAGE_SIZE, "%llu\n",
3463                          ktime_to_ns(dev_drv->vsync_info.timestamp));
3464 }
3465
3466 static DEVICE_ATTR(vsync, S_IRUGO, rk_fb_vsync_show, NULL);
3467
3468 /*
3469  * this two function is for other module that in the kernel which
3470  * need show image directly through fb
3471  * fb_id:we have 4 fb here,default we use fb0 for ui display
3472  */
3473 struct fb_info *rk_get_fb(int fb_id)
3474 {
3475         struct rk_fb *inf = platform_get_drvdata(fb_pdev);
3476         struct fb_info *fb = inf->fb[fb_id];
3477         return fb;
3478 }
3479 EXPORT_SYMBOL(rk_get_fb);
3480
3481 void rk_direct_fb_show(struct fb_info *fbi)
3482 {
3483         rk_fb_set_par(fbi);
3484         rk_fb_pan_display(&fbi->var, fbi);
3485 }
3486 EXPORT_SYMBOL(rk_direct_fb_show);
3487
3488 int rk_fb_dpi_open(bool open)
3489 {
3490         struct rk_lcdc_driver *dev_drv = NULL;
3491         dev_drv = rk_get_prmry_lcdc_drv();
3492
3493         if (dev_drv->ops->dpi_open)
3494                 dev_drv->ops->dpi_open(dev_drv, open);
3495         return 0;
3496 }
3497
3498 int rk_fb_dpi_win_sel(int win_id)
3499 {
3500         struct rk_lcdc_driver *dev_drv = NULL;
3501         dev_drv = rk_get_prmry_lcdc_drv();
3502
3503         if (dev_drv->ops->dpi_win_sel)
3504                 dev_drv->ops->dpi_win_sel(dev_drv, win_id);
3505         return 0;
3506 }
3507
3508 int rk_fb_dpi_status(void)
3509 {
3510         int ret = 0;
3511         struct rk_lcdc_driver *dev_drv = NULL;
3512
3513         dev_drv = rk_get_prmry_lcdc_drv();
3514         if (dev_drv->ops->dpi_status)
3515                 ret = dev_drv->ops->dpi_status(dev_drv);
3516
3517         return ret;
3518 }
3519
3520 /*
3521  * function: this function will be called by display device, enable/disable lcdc
3522  * @screen: screen timing to be set to lcdc
3523  * @enable: 0 disable lcdc; 1 enable change lcdc timing; 2 just enable dclk
3524  * @lcdc_id: the lcdc id the display device attached ,0 or 1
3525  */
3526 int rk_fb_switch_screen(struct rk_screen *screen, int enable, int lcdc_id)
3527 {
3528         struct rk_fb *rk_fb =  platform_get_drvdata(fb_pdev);
3529         struct fb_info *info = NULL;
3530         struct fb_info *pmy_info = NULL;
3531         struct rk_fb_par *fb_par = NULL;
3532         struct rk_fb_par *pmy_fb_par = NULL;
3533         struct rk_lcdc_driver *dev_drv = NULL;
3534         char name[6] = {0};
3535         int i, win_id, load_screen = 0;
3536
3537         if (unlikely(!rk_fb) || unlikely(!screen))
3538                 return -ENODEV;
3539
3540         hdmi_switch_complete = 0;
3541         /* get lcdc driver */
3542         sprintf(name, "lcdc%d", lcdc_id);
3543         if (rk_fb->disp_mode != DUAL)
3544                 dev_drv = rk_fb->lcdc_dev_drv[0];
3545         else
3546                 dev_drv = rk_get_lcdc_drv(name);
3547
3548         if (dev_drv == NULL) {
3549                 printk(KERN_ERR "%s driver not found!", name);
3550                 return -ENODEV;
3551         }
3552         if (screen->type == SCREEN_HDMI)
3553                 printk("hdmi %s lcdc%d\n", enable ? "connect to" : "remove from",
3554                         dev_drv->id);
3555         else if (screen->type == SCREEN_TVOUT ||
3556                      screen->type == SCREEN_TVOUT_TEST )
3557                 printk("cvbs %s lcdc%d\n", enable ? "connect to" : "remove from",
3558                         dev_drv->id);
3559         if (enable == 2 /*&& dev_drv->enable*/)
3560                 return 0;
3561
3562         if ((rk_fb->disp_mode == ONE_DUAL) ||
3563             (rk_fb->disp_mode == NO_DUAL)) {
3564                 if ((dev_drv->ops->backlight_close) &&
3565                     (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
3566                         dev_drv->ops->backlight_close(dev_drv, 1);
3567                 if (dev_drv->ops->dsp_black)
3568                         dev_drv->ops->dsp_black(dev_drv, 1);
3569                 if ((dev_drv->ops->set_screen_scaler) &&
3570                     (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
3571                         dev_drv->ops->set_screen_scaler(dev_drv,
3572                                                         dev_drv->screen0, 0);
3573         }
3574
3575         if (!enable) {
3576                 /* if screen type is different, we do not disable lcdc. */
3577                 if (dev_drv->cur_screen->type != screen->type)
3578                         return 0;
3579
3580                 /* if used one lcdc to dual disp, no need to close win */
3581                 if ((rk_fb->disp_mode == ONE_DUAL) ||
3582                     (rk_fb->disp_mode == NO_DUAL)) {
3583                         dev_drv->cur_screen = dev_drv->screen0;
3584                         dev_drv->ops->load_screen(dev_drv, 1);
3585
3586                         /* force modify dsp size */
3587                         info = rk_fb->fb[dev_drv->fb_index_base];
3588                         info->var.grayscale &= 0xff;
3589                         info->var.grayscale |=
3590                                 (dev_drv->cur_screen->mode.xres << 8) +
3591                                 (dev_drv->cur_screen->mode.yres << 20);
3592                         mutex_lock(&dev_drv->win_config);
3593                         info->fbops->fb_set_par(info);
3594                         info->fbops->fb_pan_display(&info->var, info);
3595                         mutex_unlock(&dev_drv->win_config);
3596
3597                         if (dev_drv->ops->dsp_black)
3598                                 dev_drv->ops->dsp_black(dev_drv, 0);
3599                         if ((dev_drv->ops->backlight_close) &&
3600                             (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
3601                                 dev_drv->ops->backlight_close(dev_drv, 0);
3602                 } else if (rk_fb->num_lcdc > 1) {
3603                         /* If there is more than one lcdc device, we disable
3604                            the layer which attached to this device */
3605                         for (i = 0; i < dev_drv->lcdc_win_num; i++) {
3606                                 if (dev_drv->win[i] && dev_drv->win[i]->state)
3607                                         dev_drv->ops->open(dev_drv, i, 0);
3608                         }
3609                 }
3610
3611                 hdmi_switch_complete = 0;
3612                 return 0;
3613         } else {
3614                 if (dev_drv->screen1)
3615                         dev_drv->cur_screen = dev_drv->screen1;
3616                 memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
3617                 dev_drv->cur_screen->xsize = dev_drv->cur_screen->mode.xres;
3618                 dev_drv->cur_screen->ysize = dev_drv->cur_screen->mode.yres;
3619                 dev_drv->cur_screen->x_mirror = dev_drv->rotate_mode & X_MIRROR;
3620                 dev_drv->cur_screen->y_mirror = dev_drv->rotate_mode & Y_MIRROR;
3621         }
3622         if ((!dev_drv->uboot_logo) ||
3623             (rk_fb->disp_policy != DISPLAY_POLICY_BOX)) {
3624                 for (i = 0; i < dev_drv->lcdc_win_num; i++) {
3625                         info = rk_fb->fb[dev_drv->fb_index_base + i];
3626                         fb_par = (struct rk_fb_par *)info->par;
3627                         win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
3628                         if (dev_drv->win[win_id]) {
3629                                 if (rk_fb->disp_mode == DUAL) {
3630                                         pmy_info = rk_fb->fb[i];
3631                                         if (pmy_info != info) {
3632                                                 pmy_fb_par =
3633                                                         (struct rk_fb_par *)pmy_info->par;
3634                                                 fb_par->state = pmy_fb_par->state;
3635                                         }
3636                                 }
3637                                 if (fb_par->state) {
3638                                         if (!dev_drv->win[win_id]->state)
3639                                                 dev_drv->ops->open(dev_drv, win_id, 1);
3640                                         if (!load_screen) {
3641                                                 dev_drv->ops->load_screen(dev_drv, 1);
3642                                                 load_screen = 1;
3643                                         }
3644                                         info->var.activate |= FB_ACTIVATE_FORCE;
3645                                         if (rk_fb->disp_mode == DUAL) {
3646                                                 rk_fb_update_ext_info(info, pmy_info, 1);
3647                                         } else if (rk_fb->disp_mode == ONE_DUAL) {
3648                                                 info->var.grayscale &= 0xff;
3649                                                 info->var.grayscale |=
3650                                                         (dev_drv->cur_screen->xsize << 8) +
3651                                                         (dev_drv->cur_screen->ysize << 20);
3652                                         }
3653
3654                                         mutex_lock(&dev_drv->win_config);
3655                                         info->fbops->fb_set_par(info);
3656                                         info->fbops->fb_pan_display(&info->var, info);
3657                                         mutex_unlock(&dev_drv->win_config);
3658                                 }
3659                         }
3660                 }
3661         }else {
3662                 dev_drv->uboot_logo = 0;
3663         }
3664         hdmi_switch_complete = 1;
3665         if ((rk_fb->disp_mode == ONE_DUAL) || (rk_fb->disp_mode == NO_DUAL)) {
3666                 if ((dev_drv->ops->set_screen_scaler) &&
3667                     (rk_fb->disp_policy != DISPLAY_POLICY_BOX))
3668                         dev_drv->ops->set_screen_scaler(dev_drv, dev_drv->screen0, 1);
3669                 if (dev_drv->ops->dsp_black)
3670                         dev_drv->ops->dsp_black(dev_drv, 0);
3671                 if ((dev_drv->ops->backlight_close) &&
3672                     (rk_fb->disp_policy != DISPLAY_POLICY_BOX) &&
3673                     (rk_fb->disp_mode == ONE_DUAL))
3674                         dev_drv->ops->backlight_close(dev_drv, 0);
3675         }
3676         return 0;
3677 }
3678
3679 /*
3680  * function:this function current only called by hdmi for
3681  *      scale the display
3682  * scale_x: scale rate of x resolution
3683  * scale_y: scale rate of y resolution
3684  * lcdc_id: the lcdc id the hdmi attached ,0 or 1
3685  */
3686 int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
3687 {
3688         struct rk_fb *inf = platform_get_drvdata(fb_pdev);
3689         struct fb_info *info = NULL;
3690         struct fb_info *pmy_info = NULL;
3691         struct fb_var_screeninfo *var = NULL;
3692         struct rk_lcdc_driver *dev_drv = NULL;
3693         u16 screen_x, screen_y;
3694         u16 xpos, ypos;
3695         char name[6];
3696         struct rk_screen primary_screen;
3697         rk_fb_get_prmry_screen(&primary_screen);
3698         if (primary_screen.type == SCREEN_HDMI) {
3699                 return 0;
3700         }
3701
3702         sprintf(name, "lcdc%d", lcdc_id);
3703
3704         if (inf->disp_mode == DUAL) {
3705                 dev_drv = rk_get_lcdc_drv(name);
3706                 if (dev_drv == NULL) {
3707                         printk(KERN_ERR "%s driver not found!", name);
3708                         return -ENODEV;
3709                 }
3710         } else {
3711                 dev_drv = inf->lcdc_dev_drv[0];
3712         }
3713
3714         if (inf->num_lcdc == 1) {
3715                 info = inf->fb[0];
3716         } else if (inf->num_lcdc == 2) {
3717                 info = inf->fb[dev_drv->lcdc_win_num];
3718                 pmy_info = inf->fb[0];
3719         }
3720
3721         var = &info->var;
3722         screen_x = dev_drv->cur_screen->mode.xres;
3723         screen_y = dev_drv->cur_screen->mode.yres;
3724
3725         if (inf->disp_mode != DUAL && dev_drv->screen1) {
3726                 dev_drv->cur_screen->xpos =
3727                     (screen_x - screen_x * scale_x / 100) >> 1;
3728                 dev_drv->cur_screen->ypos =
3729                     (screen_y - screen_y * scale_y / 100) >> 1;
3730                 dev_drv->cur_screen->xsize = screen_x * scale_x / 100;
3731                 dev_drv->cur_screen->ysize = screen_y * scale_y / 100;
3732         } else {
3733                 xpos = (screen_x - screen_x * scale_x / 100) >> 1;
3734                 ypos = (screen_y - screen_y * scale_y / 100) >> 1;
3735                 dev_drv->cur_screen->xsize = screen_x * scale_x / 100;
3736                 dev_drv->cur_screen->ysize = screen_y * scale_y / 100;
3737                 if (inf->disp_mode == DUAL) {
3738                         rk_fb_update_ext_info(info, pmy_info, 0);
3739                 } else {
3740                         var->nonstd &= 0xff;
3741                         var->nonstd |= (xpos << 8) + (ypos << 20);
3742                         var->grayscale &= 0xff;
3743                         var->grayscale |=
3744                                 (dev_drv->cur_screen->xsize << 8) +
3745                                 (dev_drv->cur_screen->ysize << 20);
3746                 }
3747         }
3748
3749         mutex_lock(&dev_drv->win_config);
3750         info->fbops->fb_set_par(info);
3751         dev_drv->ops->cfg_done(dev_drv);
3752         mutex_unlock(&dev_drv->win_config);
3753
3754         return 0;
3755 }
3756
3757 #if defined(CONFIG_ION_ROCKCHIP)
3758 static int rk_fb_alloc_buffer_by_ion(struct fb_info *fbi,
3759                                      struct rk_lcdc_win *win,
3760                                      unsigned long fb_mem_size)
3761 {
3762         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
3763         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
3764         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
3765         struct ion_handle *handle;
3766         ion_phys_addr_t phy_addr;
3767         size_t len;
3768         int ret = 0;
3769
3770         if (dev_drv->iommu_enabled)
3771                 handle = ion_alloc(rk_fb->ion_client, (size_t) fb_mem_size, 0,
3772                                    ION_HEAP(ION_VMALLOC_HEAP_ID), 0);
3773         else
3774                 handle = ion_alloc(rk_fb->ion_client, (size_t) fb_mem_size, 0,
3775                                    ION_HEAP(ION_CMA_HEAP_ID), 0);
3776         if (IS_ERR(handle)) {
3777                 dev_err(fbi->device, "failed to ion_alloc:%ld\n",
3778                         PTR_ERR(handle));
3779                 return -ENOMEM;
3780         }
3781
3782         fb_par->ion_hdl = handle;
3783         win->area[0].dma_buf = ion_share_dma_buf(rk_fb->ion_client, handle);
3784         if (IS_ERR_OR_NULL(win->area[0].dma_buf)) {
3785                 printk("ion_share_dma_buf() failed\n");
3786                 goto err_share_dma_buf;
3787         }
3788         win->area[0].ion_hdl = handle;
3789         if (dev_drv->prop == PRMRY)
3790                 fbi->screen_base = ion_map_kernel(rk_fb->ion_client, handle);
3791 #ifdef CONFIG_ROCKCHIP_IOMMU
3792         if (dev_drv->iommu_enabled && dev_drv->mmu_dev)
3793                 ret = ion_map_iommu(dev_drv->dev, rk_fb->ion_client, handle,
3794                                         (unsigned long *)&phy_addr,
3795                                         (unsigned long *)&len);
3796         else
3797                 ret = ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
3798 #else
3799         ret = ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
3800 #endif
3801         if (ret < 0) {
3802                 dev_err(fbi->dev, "ion map to get phy addr failed\n");
3803                 goto err_share_dma_buf;
3804         }
3805         fbi->fix.smem_start = phy_addr;
3806         fbi->fix.smem_len = len;
3807         printk(KERN_INFO "alloc_buffer:ion_phy_addr=0x%lx\n", phy_addr);
3808         return 0;
3809
3810 err_share_dma_buf:
3811         ion_free(rk_fb->ion_client, handle);
3812         return -ENOMEM;
3813 }
3814 #endif
3815
3816 static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
3817 {
3818         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
3819         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
3820         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
3821         struct rk_lcdc_win *win = NULL;
3822         int win_id;
3823         int ret = 0;
3824         unsigned long fb_mem_size;
3825 #if !defined(CONFIG_ION_ROCKCHIP)
3826         dma_addr_t fb_mem_phys;
3827         void *fb_mem_virt;
3828 #endif
3829
3830         win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
3831         if (win_id < 0)
3832                 return -ENODEV;
3833         else
3834                 win = dev_drv->win[win_id];
3835
3836         if (!strcmp(fbi->fix.id, "fb0")) {
3837                 fb_mem_size = get_fb_size();
3838 #if defined(CONFIG_ION_ROCKCHIP)
3839                 if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
3840                         return -ENOMEM;
3841 #else
3842                 fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size,
3843                                                      &fb_mem_phys, GFP_KERNEL);
3844                 if (!fb_mem_virt) {
3845                         pr_err("%s: Failed to allocate framebuffer\n",
3846                                __func__);
3847                         return -ENOMEM;
3848                 }
3849                 fbi->fix.smem_len = fb_mem_size;
3850                 fbi->fix.smem_start = fb_mem_phys;
3851                 fbi->screen_base = fb_mem_virt;
3852 #endif
3853                 memset(fbi->screen_base, 0, fbi->fix.smem_len);
3854                 printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
3855                        fbi->fix.smem_start, fbi->screen_base,
3856                        fbi->fix.smem_len);
3857         } else {
3858                 if (dev_drv->rotate_mode > X_Y_MIRROR) {
3859                         fb_mem_size = get_rotate_fb_size();
3860 #if defined(CONFIG_ION_ROCKCHIP)
3861                         if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
3862                                 return -ENOMEM;
3863 #else
3864                         fb_mem_virt =
3865                                 dma_alloc_writecombine(fbi->dev,
3866                                                        fb_mem_size,
3867                                                        &fb_mem_phys,
3868                                                        GFP_KERNEL);
3869                         if (!fb_mem_virt) {
3870                                 pr_err("%s: Failed to allocate framebuffer\n",
3871                                         __func__);
3872                                 return -ENOMEM;
3873                         }
3874                         fbi->fix.smem_len = fb_mem_size;
3875                         fbi->fix.smem_start = fb_mem_phys;
3876                         fbi->screen_base = fb_mem_virt;
3877 #endif
3878                 } else {
3879                         fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start;
3880                         fbi->fix.smem_len = rk_fb->fb[0]->fix.smem_len;
3881                         fbi->screen_base = rk_fb->fb[0]->screen_base;
3882                 }
3883
3884                 printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
3885                        fbi->fix.smem_start, fbi->screen_base,
3886                        fbi->fix.smem_len);
3887         }
3888
3889         fbi->screen_size = fbi->fix.smem_len;
3890         fb_par->fb_phy_base = fbi->fix.smem_start;
3891         fb_par->fb_virt_base = fbi->screen_base;
3892         fb_par->fb_size = fbi->fix.smem_len;
3893
3894         return ret;
3895 }
3896
3897 #if 0
3898 static int rk_release_fb_buffer(struct fb_info *fbi)
3899 {
3900         /* buffer for fb1 and fb3 are alloc by android */
3901         if (!strcmp(fbi->fix.id, "fb1") || !strcmp(fbi->fix.id, "fb3"))
3902                 return 0;
3903         iounmap(fbi->screen_base);
3904         release_mem_region(fbi->fix.smem_start, fbi->fix.smem_len);
3905         return 0;
3906 }
3907 #endif
3908
3909 static int init_lcdc_win(struct rk_lcdc_driver *dev_drv,
3910                          struct rk_lcdc_win *def_win)
3911 {
3912         int i;
3913         int lcdc_win_num = dev_drv->lcdc_win_num;
3914
3915         for (i = 0; i < lcdc_win_num; i++) {
3916                 struct rk_lcdc_win *win = NULL;
3917                 win = kzalloc(sizeof(struct rk_lcdc_win), GFP_KERNEL);
3918                 if (!win) {
3919                         dev_err(dev_drv->dev, "kzmalloc for win fail!");
3920                         return -ENOMEM;
3921                 }
3922
3923                 strcpy(win->name, def_win[i].name);
3924                 win->id = def_win[i].id;
3925                 win->support_3d = def_win[i].support_3d;
3926                 dev_drv->win[i] = win;
3927         }
3928
3929         return 0;
3930 }
3931
3932 static int init_lcdc_device_driver(struct rk_fb *rk_fb,
3933                                    struct rk_lcdc_win *def_win, int index)
3934 {
3935         struct rk_lcdc_driver *dev_drv = rk_fb->lcdc_dev_drv[index];
3936         struct rk_screen *screen = devm_kzalloc(dev_drv->dev,
3937                                                 sizeof(struct rk_screen),
3938                                                 GFP_KERNEL);
3939
3940         if (!screen) {
3941                 dev_err(dev_drv->dev, "malloc screen for lcdc%d fail!",
3942                         dev_drv->id);
3943                 return -ENOMEM;
3944         }
3945
3946         screen->screen_id = 0;
3947         screen->lcdc_id = dev_drv->id;
3948         screen->overscan.left = 100;
3949         screen->overscan.top = 100;
3950         screen->overscan.right = 100;
3951         screen->overscan.bottom = 100;
3952
3953         screen->x_mirror = dev_drv->rotate_mode & X_MIRROR;
3954         screen->y_mirror = dev_drv->rotate_mode & Y_MIRROR;
3955
3956         dev_drv->screen0 = screen;
3957         dev_drv->cur_screen = screen;
3958         /* devie use one lcdc + rk61x scaler for dual display */
3959         if (rk_fb->disp_mode == ONE_DUAL) {
3960                 struct rk_screen *screen1 =
3961                                 devm_kzalloc(dev_drv->dev,
3962                                              sizeof(struct rk_screen),
3963                                              GFP_KERNEL);
3964                 if (!screen1) {
3965                         dev_err(dev_drv->dev, "malloc screen1 for lcdc%d fail!",
3966                                 dev_drv->id);
3967                         return -ENOMEM;
3968                 }
3969                 screen1->screen_id = 1;
3970                 screen1->lcdc_id = 1;
3971                 dev_drv->screen1 = screen1;
3972         }
3973         sprintf(dev_drv->name, "lcdc%d", dev_drv->id);
3974         init_lcdc_win(dev_drv, def_win);
3975         init_completion(&dev_drv->frame_done);
3976         spin_lock_init(&dev_drv->cpl_lock);
3977         mutex_init(&dev_drv->fb_win_id_mutex);
3978         mutex_init(&dev_drv->win_config);
3979         mutex_init(&dev_drv->front_lock);
3980         dev_drv->ops->fb_win_remap(dev_drv, dev_drv->fb_win_map);
3981         dev_drv->first_frame = 1;
3982         dev_drv->overscan.left = 100;
3983         dev_drv->overscan.top = 100;
3984         dev_drv->overscan.right = 100;
3985         dev_drv->overscan.bottom = 100;
3986         rk_disp_pwr_ctr_parse_dt(dev_drv);
3987         if (dev_drv->prop == PRMRY) {
3988                 if (dev_drv->ops->set_dsp_cabc)
3989                         dev_drv->ops->set_dsp_cabc(dev_drv, dev_drv->cabc_mode);
3990                 rk_fb_set_prmry_screen(screen);
3991                 rk_fb_get_prmry_screen(screen);
3992         }
3993         dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
3994         if (dev_drv->prop != PRMRY)
3995                 rk_fb_get_prmry_screen(screen);
3996         dev_drv->output_color = screen->color_mode;
3997
3998         return 0;
3999 }
4000
4001 #ifdef CONFIG_LOGO_LINUX_BMP
4002 static struct linux_logo *bmp_logo;
4003 static int fb_prewine_bmp_logo(struct fb_info *info, int rotate)
4004 {
4005         bmp_logo = fb_find_logo(24);
4006         if (bmp_logo == NULL) {
4007                 printk(KERN_INFO "%s error\n", __func__);
4008                 return 0;
4009         }
4010         return 1;
4011 }
4012
4013 static void fb_show_bmp_logo(struct fb_info *info, int rotate)
4014 {
4015         unsigned char *src = bmp_logo->data;
4016         unsigned char *dst = info->screen_base;
4017         int i;
4018         unsigned int Needwidth = (*(src - 24) << 8) | (*(src - 23));
4019         unsigned int Needheight = (*(src - 22) << 8) | (*(src - 21));
4020
4021         for (i = 0; i < Needheight; i++)
4022                 memcpy(dst + info->var.xres * i * 4,
4023                        src + bmp_logo->width * i * 4, Needwidth * 4);
4024 }
4025 #endif
4026
4027 /*
4028  * check if the primary lcdc has registerd,
4029  * the primary lcdc mas register first
4030  */
4031 bool is_prmry_rk_lcdc_registered(void)
4032 {
4033         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
4034
4035         if (rk_fb->lcdc_dev_drv[0])
4036                 return true;
4037         else
4038                 return false;
4039 }
4040
4041 int rk_fb_register(struct rk_lcdc_driver *dev_drv,
4042                    struct rk_lcdc_win *win, int id)
4043 {
4044         struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
4045         struct fb_info *fbi;
4046         struct rk_fb_par *fb_par = NULL;
4047         int i = 0, ret = 0, index = 0;
4048
4049         if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
4050                 return -ENXIO;
4051
4052         for (i = 0; i < RK30_MAX_LCDC_SUPPORT; i++) {
4053                 if (!rk_fb->lcdc_dev_drv[i]) {
4054                         rk_fb->lcdc_dev_drv[i] = dev_drv;
4055                         rk_fb->lcdc_dev_drv[i]->id = id;
4056                         rk_fb->num_lcdc++;
4057                         break;
4058                 }
4059         }
4060
4061         index = i;
4062         init_lcdc_device_driver(rk_fb, win, index);
4063         dev_drv->fb_index_base = rk_fb->num_fb;
4064         for (i = 0; i < dev_drv->lcdc_win_num; i++) {
4065                 fbi = framebuffer_alloc(0, &fb_pdev->dev);
4066                 if (!fbi) {
4067                         dev_err(&fb_pdev->dev, "fb framebuffer_alloc fail!");
4068                         ret = -ENOMEM;
4069                 }
4070                 fb_par = devm_kzalloc(&fb_pdev->dev, sizeof(struct rk_fb_par),
4071                                       GFP_KERNEL);
4072                 if (!fb_par) {
4073                         dev_err(&fb_pdev->dev, "malloc fb_par for fb%d fail!",
4074                                 rk_fb->num_fb);
4075                         return -ENOMEM;
4076                 }
4077                 fb_par->id = rk_fb->num_fb;
4078                 fb_par->lcdc_drv = dev_drv;
4079                 fbi->par = (void *)fb_par;
4080                 fbi->var = def_var;
4081                 fbi->fix = def_fix;
4082                 sprintf(fbi->fix.id, "fb%d", rk_fb->num_fb);
4083                 fb_videomode_to_var(&fbi->var, &dev_drv->cur_screen->mode);
4084                 fbi->var.grayscale |=
4085                     (fbi->var.xres << 8) + (fbi->var.yres << 20);
4086 #if defined(CONFIG_LOGO_LINUX_BMP)
4087                 fbi->var.bits_per_pixel = 32;
4088 #else
4089                 fbi->var.bits_per_pixel = 16;
4090 #endif
4091                 fbi->fix.line_length =
4092                     (fbi->var.xres_virtual) * (fbi->var.bits_per_pixel >> 3);
4093                 fbi->var.width = dev_drv->cur_screen->width;
4094                 fbi->var.height = dev_drv->cur_screen->height;
4095                 fbi->var.pixclock = dev_drv->pixclock;
4096                 if (dev_drv->iommu_enabled)
4097                         fb_ops.fb_mmap = rk_fb_mmap;
4098                 fbi->fbops = &fb_ops;
4099                 fbi->flags = FBINFO_FLAG_DEFAULT;
4100                 fbi->pseudo_palette = dev_drv->win[i]->pseudo_pal;
4101                 ret = register_framebuffer(fbi);
4102                 if (ret < 0) {
4103                         dev_err(&fb_pdev->dev,
4104                                 "%s fb%d register_framebuffer fail!\n",
4105                                 __func__, rk_fb->num_fb);
4106                         return ret;
4107                 }
4108                 rkfb_create_sysfs(fbi);
4109                 rk_fb->fb[rk_fb->num_fb] = fbi;
4110                 dev_info(fbi->dev, "rockchip framebuffer registerd:%s\n",
4111                          fbi->fix.id);
4112                 rk_fb->num_fb++;
4113
4114                 if (i == 0) {
4115                         init_waitqueue_head(&dev_drv->vsync_info.wait);
4116                         init_waitqueue_head(&dev_drv->update_regs_wait);
4117                         ret = device_create_file(fbi->dev, &dev_attr_vsync);
4118                         if (ret)
4119                                 dev_err(fbi->dev,
4120                                         "failed to create vsync file\n");
4121                         dev_drv->vsync_info.thread =
4122                             kthread_run(rk_fb_wait_for_vsync_thread, dev_drv,
4123                                         "fb-vsync");
4124                         if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM)) {
4125                                 dev_err(fbi->dev,
4126                                         "failed to run vsync thread\n");
4127                                 dev_drv->vsync_info.thread = NULL;
4128                         }
4129                         dev_drv->vsync_info.active = 1;
4130
4131                         mutex_init(&dev_drv->output_lock);
4132
4133                         INIT_LIST_HEAD(&dev_drv->update_regs_list);
4134                         mutex_init(&dev_drv->update_regs_list_lock);
4135                         init_kthread_worker(&dev_drv->update_regs_worker);
4136
4137                         dev_drv->update_regs_thread =
4138                             kthread_run(kthread_worker_fn,
4139                                         &dev_drv->update_regs_worker, "rk-fb");
4140                         if (IS_ERR(dev_drv->update_regs_thread)) {
4141                                 int err = PTR_ERR(dev_drv->update_regs_thread);
4142                                 dev_drv->update_regs_thread = NULL;
4143
4144                                 printk("failed to run update_regs thread\n");
4145                                 return err;
4146                         }
4147                         init_kthread_work(&dev_drv->update_regs_work,
4148                                           rk_fb_update_regs_handler);
4149
4150                         dev_drv->timeline =
4151                             sw_sync_timeline_create("fb-timeline");
4152                         dev_drv->timeline_max = 1;
4153                 }
4154         }
4155
4156         /* show logo for primary display device */
4157 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE)
4158         if (dev_drv->prop == PRMRY) {
4159                 struct fb_info *main_fbi = rk_fb->fb[0];
4160                 main_fbi->fbops->fb_open(main_fbi, 1);
4161
4162 #if defined(CONFIG_ROCKCHIP_IOMMU)
4163                 if (dev_drv->iommu_enabled) {
4164                         if (dev_drv->mmu_dev)
4165                                 rockchip_iovmm_set_fault_handler(dev_drv->dev,
4166                                                 rk_fb_sysmmu_fault_handler);
4167                 }
4168 #endif
4169
4170                 rk_fb_alloc_buffer(main_fbi, 0);        /* only alloc memory for main fb */
4171                 dev_drv->uboot_logo = support_uboot_display();
4172
4173                 if (uboot_logo_offset && uboot_logo_base) {
4174                         struct rk_lcdc_win *win = dev_drv->win[0];
4175                         int width, height, bits;
4176                         phys_addr_t start = uboot_logo_base + uboot_logo_offset;
4177                         unsigned int size = uboot_logo_size - uboot_logo_offset;
4178                         unsigned int nr_pages;
4179                         struct page **pages;
4180                         char *vaddr;
4181                         int i = 0;
4182
4183                         nr_pages = size >> PAGE_SHIFT;
4184                         pages = kzalloc(sizeof(struct page) * nr_pages,
4185                                         GFP_KERNEL);
4186                         while (i < nr_pages) {
4187                                 pages[i] = phys_to_page(start);
4188                                 start += PAGE_SIZE;
4189                                 i++;
4190                         }
4191                         vaddr = vmap(pages, nr_pages, VM_MAP,
4192                                         pgprot_writecombine(PAGE_KERNEL));
4193                         if (!vaddr) {
4194                                 pr_err("failed to vmap phy addr 0x%lx\n",
4195                                        (long)(uboot_logo_base +
4196                                        uboot_logo_offset));
4197                                 return -1;
4198                         }
4199
4200                         if(bmpdecoder(vaddr, main_fbi->screen_base, &width,
4201                                       &height, &bits)) {
4202                                 kfree(pages);
4203                                 vunmap(vaddr);
4204                                 return 0;
4205                         }
4206                         kfree(pages);
4207                         vunmap(vaddr);
4208                         if (width > main_fbi->var.xres ||
4209                             height > main_fbi->var.yres) {
4210                                 pr_err("ERROR: logo size out of screen range");
4211                                 return 0;
4212                         }
4213
4214                         win->area[0].format = rk_fb_data_fmt(0, bits);
4215                         win->area[0].y_vir_stride = width * bits >> 5;
4216                         win->area[0].xpos = (main_fbi->var.xres - width) >> 1;
4217                         win->area[0].ypos = (main_fbi->var.yres - height) >> 1;
4218                         win->area[0].xsize = width;
4219                         win->area[0].ysize = height;
4220                         win->area[0].xact = width;
4221                         win->area[0].yact = height;
4222                         win->area[0].xvir = win->area[0].y_vir_stride;
4223                         win->area[0].yvir = height;
4224                         win->area[0].smem_start = main_fbi->fix.smem_start;
4225                         win->area[0].y_offset = 0;
4226
4227                         win->area_num = 1;
4228                         win->alpha_mode = 4;
4229                         win->alpha_en = 0;
4230                         win->g_alpha_val = 0;
4231
4232                         win->state = 1;
4233                         dev_drv->ops->set_par(dev_drv, 0);
4234                         dev_drv->ops->pan_display(dev_drv, 0);
4235                         dev_drv->ops->cfg_done(dev_drv);
4236
4237                         return 0;
4238                 }
4239 #if defined(CONFIG_LOGO)
4240                 main_fbi->fbops->fb_set_par(main_fbi);
4241 #if  defined(CONFIG_LOGO_LINUX_BMP)
4242                 if (fb_prewine_bmp_logo(main_fbi, FB_ROTATE_UR)) {
4243                         fb_set_cmap(&main_fbi->cmap, main_fbi);
4244                         fb_show_bmp_logo(main_fbi, FB_ROTATE_UR);
4245                 }
4246 #else
4247                 if (fb_prepare_logo(main_fbi, FB_ROTATE_UR)) {
4248                         fb_set_cmap(&main_fbi->cmap, main_fbi);
4249                         fb_show_logo(main_fbi, FB_ROTATE_UR);
4250                 }
4251 #endif
4252                 main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
4253 #endif
4254         } else {
4255                 struct fb_info *extend_fbi = rk_fb->fb[rk_fb->num_fb >> 1];
4256                 int extend_fb_id = get_extend_fb_id(extend_fbi);
4257
4258                 rk_fb_alloc_buffer(extend_fbi, extend_fb_id);
4259         }
4260 #endif
4261         return 0;
4262 }
4263
4264 int rk_fb_unregister(struct rk_lcdc_driver *dev_drv)
4265 {
4266         struct rk_fb *fb_inf = platform_get_drvdata(fb_pdev);
4267         struct fb_info *fbi;
4268         int fb_index_base = dev_drv->fb_index_base;
4269         int fb_num = dev_drv->lcdc_win_num;
4270         int i = 0;
4271
4272         if (fb_inf->lcdc_dev_drv[i]->vsync_info.thread) {
4273                 fb_inf->lcdc_dev_drv[i]->vsync_info.irq_stop = 1;
4274                 kthread_stop(fb_inf->lcdc_dev_drv[i]->vsync_info.thread);
4275         }
4276
4277         for (i = 0; i < fb_num; i++)
4278                 kfree(dev_drv->win[i]);
4279
4280         for (i = fb_index_base; i < (fb_index_base + fb_num); i++) {
4281                 fbi = fb_inf->fb[i];
4282                 unregister_framebuffer(fbi);
4283                 /* rk_release_fb_buffer(fbi); */
4284                 framebuffer_release(fbi);
4285         }
4286         fb_inf->lcdc_dev_drv[dev_drv->id] = NULL;
4287         fb_inf->num_lcdc--;
4288
4289         return 0;
4290 }
4291
4292 static int rk_fb_probe(struct platform_device *pdev)
4293 {
4294         struct rk_fb *rk_fb = NULL;
4295         struct device_node *np = pdev->dev.of_node;
4296         u32 mode;
4297
4298         if (!np) {
4299                 dev_err(&pdev->dev, "Missing device tree node.\n");
4300                 return -EINVAL;
4301         }
4302
4303         rk_fb = devm_kzalloc(&pdev->dev, sizeof(struct rk_fb), GFP_KERNEL);
4304         if (!rk_fb) {
4305                 dev_err(&pdev->dev, "kmalloc for rk fb fail!");
4306                 return -ENOMEM;
4307         }
4308         platform_set_drvdata(pdev, rk_fb);
4309
4310         if (!of_property_read_u32(np, "rockchip,disp-mode", &mode)) {
4311                 rk_fb->disp_mode = mode;
4312
4313         } else {
4314                 dev_err(&pdev->dev, "no disp-mode node found!");
4315                 return -ENODEV;
4316         }
4317         
4318         if (!of_property_read_u32(np, "rockchip,disp-policy", &mode)) {
4319                 rk_fb->disp_policy = mode;
4320                 pr_info("fb disp policy is %s\n", rk_fb->disp_policy ? "box":"sdk");
4321         }
4322
4323         if (!of_property_read_u32(np, "rockchip,uboot-logo-on", &uboot_logo_on))
4324                 printk(KERN_DEBUG "uboot-logo-on:%d\n", uboot_logo_on);
4325
4326         dev_set_name(&pdev->dev, "rockchip-fb");
4327 #if defined(CONFIG_ION_ROCKCHIP)
4328         rk_fb->ion_client = rockchip_ion_client_create("rk_fb");
4329         if (IS_ERR(rk_fb->ion_client)) {
4330                 dev_err(&pdev->dev, "failed to create ion client for rk fb");
4331                 return PTR_ERR(rk_fb->ion_client);
4332         } else {
4333                 dev_info(&pdev->dev, "rk fb ion client create success!\n");
4334         }
4335 #endif
4336
4337         fb_pdev = pdev;
4338         dev_info(&pdev->dev, "rockchip framebuffer driver probe\n");
4339         return 0;
4340 }
4341
4342 static int rk_fb_remove(struct platform_device *pdev)
4343 {
4344         struct rk_fb *rk_fb = platform_get_drvdata(pdev);
4345
4346         kfree(rk_fb);
4347         platform_set_drvdata(pdev, NULL);
4348         return 0;
4349 }
4350
4351 static void rk_fb_shutdown(struct platform_device *pdev)
4352 {
4353         struct rk_fb *rk_fb = platform_get_drvdata(pdev);
4354         int i;
4355
4356         for (i = 0; i < rk_fb->num_lcdc; i++) {
4357                 if (!rk_fb->lcdc_dev_drv[i])
4358                         continue;
4359         }
4360 }
4361
4362 static const struct of_device_id rkfb_dt_ids[] = {
4363         {.compatible = "rockchip,rk-fb",},
4364         {}
4365 };
4366
4367 static struct platform_driver rk_fb_driver = {
4368         .probe = rk_fb_probe,
4369         .remove = rk_fb_remove,
4370         .driver = {
4371                    .name = "rk-fb",
4372                    .owner = THIS_MODULE,
4373                    .of_match_table = of_match_ptr(rkfb_dt_ids),
4374                    },
4375         .shutdown = rk_fb_shutdown,
4376 };
4377
4378 static int __init rk_fb_init(void)
4379 {
4380         return platform_driver_register(&rk_fb_driver);
4381 }
4382
4383 static void __exit rk_fb_exit(void)
4384 {
4385         platform_driver_unregister(&rk_fb_driver);
4386 }
4387
4388 fs_initcall(rk_fb_init);
4389 module_exit(rk_fb_exit);