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