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