rk3288-tb: adjust core dvfs table
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / rockchip / rk3288_drm_fimd.c
1 /*
2  * rk3288_drm_fimd.c
3  *
4  * Copyright (C) ROCKCHIP, Inc.
5  * Author:yzq<yzq@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 #include <drm/drmP.h>
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/clk.h>
21 #include <linux/of_device.h>
22 #include <linux/pm_runtime.h>
23
24 #include <video/of_display_timing.h>
25 #include <drm/rockchip_drm.h>
26 #include <linux/rockchip/cpu.h>
27 #include <linux/rockchip/iomap.h>
28 #include <linux/rk_fb.h>
29 #include <video/display_timing.h>
30 #include <linux/rockchip/cpu.h>
31 #include <linux/rockchip/iomap.h>
32 #include <linux/rockchip/grf.h>
33 #include "rockchip_drm_drv.h"
34 #include "rockchip_drm_fbdev.h"
35 #include "rockchip_drm_crtc.h"
36 #include "rockchip_drm_iommu.h"
37
38 /*
39  * FIMD is stand for Fully Interactive Mobile Display and
40  * as a display controller, it transfers contents drawn on memory
41  * to a LCD Panel through Display Interfaces such as RGB or
42  * CPU Interface.
43  */
44
45 /* position control register for hardware window 0, 2 ~ 4.*/
46 #define VIDOSD_A(win)           (VIDOSD_BASE + 0x00 + (win) * 16)
47 #define VIDOSD_B(win)           (VIDOSD_BASE + 0x04 + (win) * 16)
48 /*
49  * size control register for hardware windows 0 and alpha control register
50  * for hardware windows 1 ~ 4
51  */
52 #define VIDOSD_C(win)           (VIDOSD_BASE + 0x08 + (win) * 16)
53 /* size control register for hardware windows 1 ~ 2. */
54 #define VIDOSD_D(win)           (VIDOSD_BASE + 0x0C + (win) * 16)
55
56 #define VIDWx_BUF_START(win, buf)       (VIDW_BUF_START(buf) + (win) * 8)
57 #define VIDWx_BUF_END(win, buf)         (VIDW_BUF_END(buf) + (win) * 8)
58 #define VIDWx_BUF_SIZE(win, buf)        (VIDW_BUF_SIZE(buf) + (win) * 4)
59
60 /* color key control register for hardware window 1 ~ 4. */
61 #define WKEYCON0_BASE(x)                ((WKEYCON0 + 0x140) + ((x - 1) * 8))
62 /* color key value register for hardware window 1 ~ 4. */
63 #define WKEYCON1_BASE(x)                ((WKEYCON1 + 0x140) + ((x - 1) * 8))
64
65 /* FIMD has totally five hardware windows. */
66 #define WINDOWS_NR      4
67 /*****************************************************************************************************/
68 #define SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT   12   /* 4.12*/
69 #define SCALE_FACTOR_BILI_DN_FIXPOINT(x)      ((INT32)((x)*(1 << SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT)))
70
71 #define SCALE_FACTOR_BILI_UP_FIXPOINT_SHIFT   16   /* 0.16*/
72
73 #define SCALE_FACTOR_AVRG_FIXPOINT_SHIFT   16   /*0.16*/
74 #define SCALE_FACTOR_AVRG_FIXPOINT(x)      ((INT32)((x)*(1 << SCALE_FACTOR_AVRG_FIXPOINT_SHIFT)))
75
76 #define SCALE_FACTOR_BIC_FIXPOINT_SHIFT    16   /* 0.16*/
77 #define SCALE_FACTOR_BIC_FIXPOINT(x)       ((INT32)((x)*(1 << SCALE_FACTOR_BIC_FIXPOINT_SHIFT)))
78
79 #define SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT    12  /*NONE SCALE,vsd_bil*/
80 #define SCALE_FACTOR_VSDBIL_FIXPOINT_SHIFT     12  /*VER SCALE DOWN BIL*/
81
82 /*****************************************************************************************************/
83
84 /*#define GET_SCALE_FACTOR_BILI(src, dst) ((((src) - 1) << SCALE_FACTOR_BILI_FIXPOINT_SHIFT) / ((dst) - 1))*/
85 /*#define GET_SCALE_FACTOR_BIC(src, dst)  ((((src) - 1) << SCALE_FACTOR_BIC_FIXPOINT_SHIFT) / ((dst) - 1))*/
86 /*modified by hpz*/
87 #define GET_SCALE_FACTOR_BILI_DN(src, dst)  ((((src)*2 - 3) << (SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT-1)) / ((dst) - 1))
88 #define GET_SCALE_FACTOR_BILI_UP(src, dst)  ((((src)*2 - 3) << (SCALE_FACTOR_BILI_UP_FIXPOINT_SHIFT-1)) / ((dst) - 1))
89 #define GET_SCALE_FACTOR_BIC(src, dst)      ((((src)*2 - 3) << (SCALE_FACTOR_BIC_FIXPOINT_SHIFT-1)) / ((dst) - 1))
90
91 #define get_fimd_context(dev)   platform_get_drvdata(to_platform_device(dev))
92
93 static struct rk_fb_trsm_ops *trsm_lvds_ops;
94 static struct rk_fb_trsm_ops *trsm_edp_ops;
95 static struct rk_fb_trsm_ops *trsm_mipi_ops;
96
97 int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
98 {
99         switch (type) {
100         case SCREEN_RGB:
101         case SCREEN_LVDS:
102         case SCREEN_DUAL_LVDS:
103                 trsm_lvds_ops = ops;
104                 break;
105         case SCREEN_EDP:
106                 trsm_edp_ops = ops;
107                 break;
108         case SCREEN_MIPI:
109         case SCREEN_DUAL_MIPI:
110                 trsm_mipi_ops = ops;
111                 break;
112         default:
113                 printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
114                         __func__, type);
115                 break;
116         }
117         return 0;
118 }
119 struct fimd_driver_data {
120         unsigned int timing_base;
121 };
122
123 static struct fimd_driver_data rockchip4_fimd_driver_data = {
124         .timing_base = 0x0,
125 };
126
127 static struct fimd_driver_data rockchip5_fimd_driver_data = {
128         .timing_base = 0x20000,
129 };
130
131 struct fimd_win_data {
132         unsigned int            offset_x;
133         unsigned int            offset_y;
134         unsigned int            ovl_width;
135         unsigned int            ovl_height;
136         unsigned int            fb_width;
137         unsigned int            fb_height;
138         unsigned int            bpp;
139         dma_addr_t              dma_addr;
140         unsigned int            buf_offsize;
141         unsigned int            line_size;      /* bytes */
142         bool                    enabled;
143         bool                    resume;
144 };
145
146 struct fimd_context {
147         struct rockchip_drm_subdrv      subdrv;
148         int                             irq;
149         struct drm_crtc                 *crtc;
150         struct clk                      *pd;                            //lcdc power domain
151         struct clk                      *hclk;                          //lcdc AHP clk
152         struct clk                      *dclk;                          //lcdc dclk
153         struct clk                      *aclk;                          //lcdc share memory frequency
154         void __iomem                    *regs;
155         struct fimd_win_data            win_data[WINDOWS_NR];
156         unsigned int                    clkdiv;
157         unsigned int                    default_win;
158         unsigned long                   irq_flags;
159         u32                             vidcon0;
160         u32                             vidcon1;
161         int                             lcdc_id;
162         bool                            suspended;
163         struct mutex                    lock;
164         wait_queue_head_t               wait_vsync_queue;
165         atomic_t                        wait_vsync_event;
166
167         int clkon;
168         void *regsbak;                  //back up reg
169         struct rockchip_drm_panel_info *panel;
170         struct rk_screen *screen;
171 };
172
173 #include "rk3288_drm_fimd.h"
174 static int rk3288_lcdc_get_id(u32 phy_base)
175 {
176         if (cpu_is_rk3288()) {
177                 if (phy_base == 0xff930000)/*vop big*/
178                         return 0;
179                 else if (phy_base == 0xff940000)/*vop lit*/     
180                         return 1;
181                 else
182                         return -EINVAL;
183         } else {
184                 pr_err("un supported platform \n");
185                 return -EINVAL;
186         }
187 }
188
189
190 static bool fimd_display_is_connected(struct device *dev)
191 {
192         DRM_DEBUG_KMS("%s\n", __FILE__);
193
194         /* TODO. */
195
196         return true;
197 }
198
199 static void *fimd_get_panel(struct device *dev)
200 {
201         struct fimd_context *ctx = get_fimd_context(dev);
202
203         DRM_DEBUG_KMS("%s\n", __FILE__);
204
205         return ctx->panel;
206 }
207
208 static int fimd_check_timing(struct device *dev, void *timing)
209 {
210         DRM_DEBUG_KMS("%s\n", __FILE__);
211
212         /* TODO. */
213
214         return 0;
215 }
216
217 static int fimd_display_power_on(struct device *dev, int mode)
218 {
219         DRM_DEBUG_KMS("%s\n", __FILE__);
220
221         /* TODO */
222
223         return 0;
224 }
225
226 static struct rockchip_drm_display_ops fimd_display_ops = {
227         .type = ROCKCHIP_DISPLAY_TYPE_LCD,
228         .is_connected = fimd_display_is_connected,
229         .get_panel = fimd_get_panel,
230         .check_timing = fimd_check_timing,
231         .power_on = fimd_display_power_on,
232 };
233
234 static void fimd_dpms(struct device *subdrv_dev, int mode)
235 {
236         struct fimd_context *ctx = get_fimd_context(subdrv_dev);
237
238         DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
239
240         mutex_lock(&ctx->lock);
241
242         switch (mode) {
243         case DRM_MODE_DPMS_ON:
244                 /*
245                  * enable fimd hardware only if suspended status.
246                  *
247                  * P.S. fimd_dpms function would be called at booting time so
248                  * clk_enable could be called double time.
249                  */
250
251                 if(trsm_lvds_ops != NULL){
252                         printk(KERN_ERR"------>yzq enable lvds\n");     
253                         trsm_lvds_ops->enable();
254                 }
255                 if (ctx->suspended)
256                         pm_runtime_get_sync(subdrv_dev);
257                 break;
258         case DRM_MODE_DPMS_STANDBY:
259         case DRM_MODE_DPMS_SUSPEND:
260         case DRM_MODE_DPMS_OFF:
261                 if (!ctx->suspended)
262                         pm_runtime_put_sync(subdrv_dev);
263                 break;
264         default:
265                 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
266                 break;
267         }
268
269         mutex_unlock(&ctx->lock);
270 }
271
272 static void fimd_apply(struct device *subdrv_dev)
273 {
274         struct fimd_context *ctx = get_fimd_context(subdrv_dev);
275         struct rockchip_drm_manager *mgr = ctx->subdrv.manager;
276         struct rockchip_drm_manager_ops *mgr_ops = mgr->ops;
277         struct rockchip_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
278         struct fimd_win_data *win_data;
279         int i;
280
281         DRM_DEBUG_KMS("%s\n", __FILE__);
282
283         for (i = 0; i < WINDOWS_NR; i++) {
284                 win_data = &ctx->win_data[i];
285                 if (win_data->enabled && (ovl_ops && ovl_ops->commit))
286                         ovl_ops->commit(subdrv_dev, i);
287         }
288
289         if (mgr_ops && mgr_ops->commit)
290                 mgr_ops->commit(subdrv_dev);
291 }
292
293 static int rk3288_lcdc_alpha_cfg(struct fimd_context *ctx,int win_id)
294 {
295         struct alpha_config alpha_config;
296         struct fimd_win_data *win_data;
297         enum alpha_mode alpha_mode;
298         u32 mask, val;
299         int ppixel_alpha,global_alpha;
300         u32 src_alpha_ctl,dst_alpha_ctl;
301         int g_alpha_val=0;
302
303         win_data = &ctx->win_data[win_id];
304         ppixel_alpha = (win_data->bpp==32) ? 1 : 0;
305         global_alpha = 1; 
306         alpha_config.src_global_alpha_val = 1;
307         alpha_mode = AB_SRC_OVER;
308         global_alpha = (g_alpha_val == 0) ? 0 : 1; 
309         alpha_config.src_global_alpha_val = g_alpha_val;
310         /*printk("%s,alpha_mode=%d,alpha_en=%d,ppixel_a=%d,gla_a=%d\n",
311                 __func__,win->alpha_mode,win->alpha_en,ppixel_alpha,global_alpha);*/
312         switch(alpha_mode){
313         case AB_USER_DEFINE:
314                 break;
315         case AB_CLEAR:
316                 alpha_config.src_factor_mode=AA_ZERO;
317                 alpha_config.dst_factor_mode=AA_ZERO;           
318                 break;
319         case AB_SRC:
320                 alpha_config.src_factor_mode=AA_ONE;
321                 alpha_config.dst_factor_mode=AA_ZERO;
322                 break;
323         case AB_DST:
324                 alpha_config.src_factor_mode=AA_ZERO;
325                 alpha_config.dst_factor_mode=AA_ONE;
326                 break;
327         case AB_SRC_OVER:
328                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
329                 alpha_config.src_factor_mode=AA_ONE;
330                 alpha_config.dst_factor_mode=AA_SRC_INVERSE;            
331                 break;
332         case AB_DST_OVER:
333                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
334                 alpha_config.src_factor_mode=AA_SRC_INVERSE;
335                 alpha_config.dst_factor_mode=AA_ONE;
336                 break;
337         case AB_SRC_IN:
338                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
339                 alpha_config.src_factor_mode=AA_SRC;
340                 alpha_config.dst_factor_mode=AA_ZERO;
341                 break;
342         case AB_DST_IN:
343                 alpha_config.src_factor_mode=AA_ZERO;
344                 alpha_config.dst_factor_mode=AA_SRC;
345                 break;
346         case AB_SRC_OUT:
347                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
348                 alpha_config.src_factor_mode=AA_SRC_INVERSE;
349                 alpha_config.dst_factor_mode=AA_ZERO;           
350                 break;
351         case AB_DST_OUT:
352                 alpha_config.src_factor_mode=AA_ZERO;
353                 alpha_config.dst_factor_mode=AA_SRC_INVERSE;    
354                 break;
355         case AB_SRC_ATOP:
356                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
357                 alpha_config.src_factor_mode=AA_SRC;
358                 alpha_config.dst_factor_mode=AA_SRC_INVERSE;            
359                 break;
360         case AB_DST_ATOP:
361                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
362                 alpha_config.src_factor_mode=AA_SRC_INVERSE;
363                 alpha_config.dst_factor_mode=AA_SRC;            
364                 break;
365         case XOR:
366                 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
367                 alpha_config.src_factor_mode=AA_SRC_INVERSE;
368                 alpha_config.dst_factor_mode=AA_SRC_INVERSE;                    
369                 break;  
370         case AB_SRC_OVER_GLOBAL:        
371                 alpha_config.src_global_alpha_mode=AA_PER_PIX_GLOBAL;
372                 alpha_config.src_color_mode=AA_SRC_NO_PRE_MUL;
373                 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
374                 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
375                 break;
376         default:
377                 pr_err("alpha mode error\n");
378                 break;          
379         }
380         if((ppixel_alpha == 1)&&(global_alpha == 1)){
381                 alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL;
382         }else if(ppixel_alpha == 1){
383                 alpha_config.src_global_alpha_mode = AA_PER_PIX;
384         }else if(global_alpha == 1){
385                 alpha_config.src_global_alpha_mode = AA_GLOBAL;
386         }else{
387                 pr_err("alpha_en should be 0\n");
388         }
389         alpha_config.src_alpha_mode = AA_STRAIGHT;
390         alpha_config.src_alpha_cal_m0 = AA_NO_SAT;
391
392         switch(win_id){
393         case 0:
394                 src_alpha_ctl = 0x60;
395                 dst_alpha_ctl = 0x64;
396                 break;
397         case 1:
398                 src_alpha_ctl = 0xa0;
399                 dst_alpha_ctl = 0xa4;
400                 break;
401         case 2:
402                 src_alpha_ctl = 0xdc;
403                 dst_alpha_ctl = 0xec;
404                 break;
405         case 3:
406                 src_alpha_ctl = 0x12c;
407                 dst_alpha_ctl = 0x13c;
408                 break;
409         }
410         mask = m_WIN0_DST_FACTOR_M0;
411         val  = v_WIN0_DST_FACTOR_M0(alpha_config.dst_factor_mode);
412         lcdc_msk_reg(ctx, dst_alpha_ctl, mask, val);
413         mask = m_WIN0_SRC_ALPHA_EN | m_WIN0_SRC_COLOR_M0 |
414                 m_WIN0_SRC_ALPHA_M0 | m_WIN0_SRC_BLEND_M0 |
415                 m_WIN0_SRC_ALPHA_CAL_M0 | m_WIN0_SRC_FACTOR_M0|
416                 m_WIN0_SRC_GLOBAL_ALPHA;
417         val = v_WIN0_SRC_ALPHA_EN(1) | 
418                 v_WIN0_SRC_COLOR_M0(alpha_config.src_color_mode) |
419                 v_WIN0_SRC_ALPHA_M0(alpha_config.src_alpha_mode) |
420                 v_WIN0_SRC_BLEND_M0(alpha_config.src_global_alpha_mode) |
421                 v_WIN0_SRC_ALPHA_CAL_M0(alpha_config.src_alpha_cal_m0) |
422                 v_WIN0_SRC_FACTOR_M0(alpha_config.src_factor_mode) |
423                 v_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val);
424         lcdc_msk_reg(ctx, src_alpha_ctl, mask, val);
425
426         return 0;
427 }
428 static int rk3288_win_0_1_reg_update(struct fimd_context *ctx,int win_id)
429 {
430         struct fimd_win_data *win_data;
431         unsigned int mask, val, off;
432         struct rk_screen *screen = ctx->screen;
433         u8 fmt_cfg = 0;
434         u32 xpos, ypos;
435         off = win_id * 0x40;
436         win_data = &ctx->win_data[win_id];
437         switch(win_data->bpp){
438                 case 32:
439                         fmt_cfg = 0;
440                         break;
441                 case 24:
442                         fmt_cfg = 1;
443                         break;
444                 case 16:
445                         fmt_cfg = 2;
446                         break;
447                 default:
448                         printk("not support format %d\n",win_data->bpp);
449                         break;
450         }
451
452         xpos = win_data->offset_x + screen->mode.left_margin + screen->mode.hsync_len;
453         ypos = win_data->offset_y + screen->mode.upper_margin + screen->mode.vsync_len;
454         mask =  m_WIN0_EN | m_WIN0_DATA_FMT ;
455         val  =  v_WIN0_EN(1) | v_WIN0_DATA_FMT(fmt_cfg);
456         lcdc_msk_reg(ctx, WIN0_CTRL0+off, mask,val);    
457
458         val =   v_WIN0_VIR_STRIDE(win_data->fb_width);
459         lcdc_writel(ctx, WIN0_VIR+off, val);    
460         val =   v_WIN0_ACT_WIDTH(win_data->fb_width) |
461                 v_WIN0_ACT_HEIGHT(win_data->fb_height);
462         lcdc_writel(ctx, WIN0_ACT_INFO+off, val); 
463
464         val =   v_WIN0_DSP_WIDTH(win_data->ovl_width) |
465                 v_WIN0_DSP_HEIGHT(win_data->ovl_height);
466         lcdc_writel(ctx, WIN0_DSP_INFO+off, val); 
467
468         val =   v_WIN0_DSP_XST(xpos) |
469                 v_WIN0_DSP_YST(ypos);
470         lcdc_writel(ctx, WIN0_DSP_ST+off, val); 
471         lcdc_writel(ctx, WIN0_YRGB_MST+off, win_data->dma_addr );
472
473         if(win_id == 1)
474                 rk3288_lcdc_alpha_cfg(ctx,win_id);
475         lcdc_cfg_done(ctx);
476         return 0;
477 }
478
479 static int rk3288_lcdc_post_cfg(struct fimd_context *ctx)
480 {
481         struct rk_screen *screen = ctx->screen;
482         u16 x_res = screen->mode.xres;
483         u16 y_res = screen->mode.yres;
484         u32 mask, val;
485         u16 h_total,v_total;
486         u16 post_hsd_en,post_vsd_en;
487         u16 post_dsp_hact_st,post_dsp_hact_end; 
488         u16 post_dsp_vact_st,post_dsp_vact_end;
489         u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
490         u16 post_h_fac,post_v_fac;
491
492         h_total = screen->mode.hsync_len+screen->mode.left_margin +
493                   x_res + screen->mode.right_margin;
494         v_total = screen->mode.vsync_len+screen->mode.upper_margin +
495                   y_res + screen->mode.lower_margin;
496
497         if(screen->post_dsp_stx + screen->post_xsize > x_res){          
498                 printk(KERN_ERR"post:stx[%d] + xsize[%d] > x_res[%d]\n",
499                         screen->post_dsp_stx,screen->post_xsize,x_res);
500                 screen->post_dsp_stx = x_res - screen->post_xsize;
501         }
502         if(screen->x_mirror == 0){
503                 post_dsp_hact_st=screen->post_dsp_stx + 
504                         screen->mode.hsync_len+screen->mode.left_margin;
505                 post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize;
506         }else{
507                 post_dsp_hact_end = h_total - screen->mode.right_margin -
508                                         screen->post_dsp_stx;
509                 post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize;
510         }       
511         if((screen->post_xsize < x_res)&&(screen->post_xsize != 0)){
512                 post_hsd_en = 1;
513                 post_h_fac = 
514                         GET_SCALE_FACTOR_BILI_DN(x_res , screen->post_xsize); 
515         }else{
516                 post_hsd_en = 0;
517                 post_h_fac = 0x1000;
518         }
519
520
521         if(screen->post_dsp_sty + screen->post_ysize > y_res){
522                 printk(KERN_ERR "post:sty[%d] + ysize[%d] > y_res[%d]\n",
523                         screen->post_dsp_sty,screen->post_ysize,y_res);
524                 screen->post_dsp_sty = y_res - screen->post_ysize;      
525         }
526         
527         if(screen->y_mirror == 0){
528                 post_dsp_vact_st = screen->post_dsp_sty + 
529                         screen->mode.vsync_len+screen->mode.upper_margin;
530                 post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
531         }else{
532                 post_dsp_vact_end = v_total - screen->mode.lower_margin -
533                                         - screen->post_dsp_sty;
534                 post_dsp_hact_st = post_dsp_vact_end - screen->post_ysize;
535         }
536         if((screen->post_ysize < y_res)&&(screen->post_ysize != 0)){
537                 post_vsd_en = 1;
538                 post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res, screen->post_ysize);               
539         }else{
540                 post_vsd_en = 0;
541                 post_v_fac = 0x1000;
542         }
543
544         if(screen->interlace == 1){
545                 post_dsp_vact_st_f1  = v_total + post_dsp_vact_st;
546                 post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
547         }else{
548                 post_dsp_vact_st_f1  = 0;
549                 post_dsp_vact_end_f1 = 0;
550         }
551         printk(KERN_ERR"post:xsize=%d,ysize=%d,xpos=%d,ypos=%d,"
552               "hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n",
553                 screen->post_xsize,screen->post_ysize,screen->xpos,screen->ypos,
554                 post_hsd_en,post_h_fac,post_vsd_en,post_v_fac);
555         mask = m_DSP_HACT_END_POST | m_DSP_HACT_ST_POST;
556         val = v_DSP_HACT_END_POST(post_dsp_hact_end) | 
557               v_DSP_HACT_ST_POST(post_dsp_hact_st);
558         lcdc_msk_reg(ctx, POST_DSP_HACT_INFO, mask, val);
559
560         mask = m_DSP_VACT_END_POST | m_DSP_VACT_ST_POST;
561         val = v_DSP_VACT_END_POST(post_dsp_vact_end) | 
562               v_DSP_VACT_ST_POST(post_dsp_vact_st);
563         lcdc_msk_reg(ctx, POST_DSP_VACT_INFO, mask, val);
564
565         mask = m_POST_HS_FACTOR_YRGB | m_POST_VS_FACTOR_YRGB;
566         val = v_POST_HS_FACTOR_YRGB(post_h_fac) |
567                 v_POST_VS_FACTOR_YRGB(post_v_fac);
568         lcdc_msk_reg(ctx, POST_SCL_FACTOR_YRGB, mask, val);
569
570         mask = m_DSP_VACT_END_POST_F1 | m_DSP_VACT_ST_POST_F1;
571         val = v_DSP_VACT_END_POST_F1(post_dsp_vact_end_f1) |
572                 v_DSP_VACT_ST_POST_F1(post_dsp_vact_st_f1);
573         lcdc_msk_reg(ctx, POST_DSP_VACT_INFO_F1, mask, val);
574
575         mask = m_POST_HOR_SD_EN | m_POST_VER_SD_EN;
576         val = v_POST_HOR_SD_EN(post_hsd_en) | v_POST_VER_SD_EN(post_vsd_en);
577         lcdc_msk_reg(ctx, POST_SCL_CTRL, mask, val);
578         return 0;
579 }
580 static void fimd_commit(struct device *dev)
581 {
582         struct fimd_context *ctx = get_fimd_context(dev);
583         struct rockchip_drm_panel_info *panel = ctx->panel;
584         struct rk_screen *screen = ctx->screen;
585         u16 hsync_len = screen->mode.hsync_len;
586         u16 left_margin = screen->mode.left_margin;
587         u16 right_margin = screen->mode.right_margin;
588         u16 vsync_len = screen->mode.vsync_len;
589         u16 upper_margin = screen->mode.upper_margin;
590         u16 lower_margin = screen->mode.lower_margin;
591         u16 x_res = screen->mode.xres;
592         u16 y_res = screen->mode.yres;
593         u32 mask, val;
594         int face;
595         u32 v=0;
596         u16 h_total,v_total;
597         h_total = hsync_len + left_margin  + x_res + right_margin;
598         v_total = vsync_len + upper_margin + y_res + lower_margin;
599         screen->post_dsp_stx=0;
600         screen->post_dsp_sty=0;
601         screen->post_xsize =x_res;
602         screen->post_ysize = y_res;
603
604         printk(KERN_ERR"%s %d\n", __func__,__LINE__);
605         if (ctx->suspended)
606                 return;
607
608         printk(KERN_ERR"%s %d\n", __func__,__LINE__);
609         if(!ctx->clkon)
610                 return;
611 #if 1
612         switch (screen->face) {
613                 case OUT_P565:
614                         face = OUT_P565;
615                         mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
616                                 m_DITHER_DOWN_SEL;
617                         val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
618                                 v_DITHER_DOWN_SEL(1);
619                         lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
620                         break;
621                 case OUT_P666:
622                         face = OUT_P666;
623                         mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
624                                 m_DITHER_DOWN_SEL;
625                         val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
626                                 v_DITHER_DOWN_SEL(1);
627                         lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
628                         break;
629                 case OUT_D888_P565:
630                         face = OUT_P888;
631                         mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
632                                 m_DITHER_DOWN_SEL;
633                         val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
634                                 v_DITHER_DOWN_SEL(1);
635                         lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
636                         break;
637                 case OUT_D888_P666:
638                         face = OUT_P888;
639                         mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
640                                 m_DITHER_DOWN_SEL;
641                         val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
642                                 v_DITHER_DOWN_SEL(1);
643                         lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
644                         break;
645                 case OUT_P888:
646                         face = OUT_P888;
647                         mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
648                         val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
649                         lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
650                         break;
651                 default:
652                         printk("un supported interface!\n");
653                         break;
654         }
655         switch(screen->type){
656                 case SCREEN_RGB:
657                 case SCREEN_LVDS:
658                 case SCREEN_DUAL_LVDS:                  
659                         mask = m_RGB_OUT_EN;
660                         val = v_RGB_OUT_EN(1);
661                         v = 1 << (3+16);
662                         v |= (ctx->lcdc_id << 3);
663                         break;
664                 case SCREEN_HDMI:
665                         mask = m_HDMI_OUT_EN;
666                         val = v_HDMI_OUT_EN(1);
667                         /*v = 1 << (4+16);
668                           v |= (ctx->id << 4);*/        
669                         break;
670                 case SCREEN_MIPI:
671                         mask = m_MIPI_OUT_EN;
672                         val = v_MIPI_OUT_EN(1);
673                         /*v = (1 << (6+16))||(1 << (9+16));
674                           v |= (ctx->id << 6);
675                           v |= (ctx->id << 9);*/                
676                         break;
677                 case SCREEN_DUAL_MIPI:
678                         mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
679                         val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
680                         /*v = (1 << (6+16))||(1 << (9+16));
681                           v |= (ctx->id << 6);
682                           v |= (ctx->id << 9);*/        
683                         break;
684                 case SCREEN_EDP:
685                         face = OUT_RGB_AAA;  /*RGB AAA output*/
686                         mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
687                         val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
688                         lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
689                         mask = m_EDP_OUT_EN;
690                         val = v_EDP_OUT_EN(1);
691                         /*v = 1 << (5+16);
692                           v |= (ctx->id << 5);*/                
693                         break;
694         }
695         lcdc_msk_reg(ctx, SYS_CTRL, mask, val);
696 #ifdef USE_ION_MMU
697         mask = m_MMU_EN;
698         val = v_MMU_EN(1);
699         lcdc_msk_reg(ctx, SYS_CTRL, mask, val);
700         mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
701         val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
702         lcdc_msk_reg(ctx, SYS_CTRL1, mask, val);                
703 #endif  
704         writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
705         mask = m_DSP_OUT_MODE | m_DSP_HSYNC_POL | m_DSP_VSYNC_POL |
706                 m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP | 
707                 m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
708                 m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN | 
709                 m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN;
710         val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
711                 v_DSP_VSYNC_POL(screen->pin_vsync) | 
712                 v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
713                 v_DSP_BG_SWAP(screen->swap_gb) | v_DSP_RB_SWAP(screen->swap_rb) | 
714                 v_DSP_RG_SWAP(screen->swap_rg) | 
715                 v_DSP_DELTA_SWAP(screen->swap_delta) |
716                 v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) | 
717                 v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
718                 v_DSP_X_MIR_EN(screen->x_mirror) | v_DSP_Y_MIR_EN(screen->y_mirror);
719         lcdc_msk_reg(ctx, DSP_CTRL0, mask, val);
720
721         mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
722         val  = v_DSP_BG_BLUE(0x3ff) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
723         lcdc_msk_reg(ctx, DSP_BG, mask, val);
724
725         mask = m_DSP_HS_PW | m_DSP_HTOTAL;
726         val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
727         lcdc_msk_reg(ctx, DSP_HTOTAL_HS_END, mask, val);
728
729         mask = m_DSP_HACT_END | m_DSP_HACT_ST;
730         val = v_DSP_HACT_END(hsync_len + left_margin + x_res) |
731                 v_DSP_HACT_ST(hsync_len + left_margin);
732         lcdc_msk_reg(ctx, DSP_HACT_ST_END, mask, val);
733
734         mask = m_DSP_VS_PW | m_DSP_VTOTAL;
735         val = v_DSP_VS_PW(vsync_len) | v_DSP_VTOTAL(v_total);
736         lcdc_msk_reg(ctx, DSP_VTOTAL_VS_END, mask, val);
737
738         mask = m_DSP_VACT_END | m_DSP_VACT_ST;
739         val = v_DSP_VACT_END(vsync_len + upper_margin + y_res) |
740                 v_DSP_VACT_ST(vsync_len + upper_margin);
741         lcdc_msk_reg(ctx, DSP_VACT_ST_END, mask, val);
742
743         rk3288_lcdc_post_cfg(ctx);
744 #endif
745 }
746
747 static int fimd_enable_vblank(struct device *dev)
748 {
749         struct fimd_context *ctx = get_fimd_context(dev);
750         u32 val,mask;
751
752         DRM_DEBUG_KMS("%s\n", __FILE__);
753
754         if (ctx->suspended)
755                 return -EPERM;
756
757         if (!test_and_set_bit(0, &ctx->irq_flags)) {
758                 mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
759                     m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR | 
760                     m_BUS_ERROR_INTR_EN | m_DSP_LINE_FLAG_NUM;
761                 val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(0) |
762                     v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_CLR(0) | v_BUS_ERROR_INTR_EN(0) ;
763                 lcdc_msk_reg(ctx, INTR_CTRL0, mask, val);
764                 lcdc_cfg_done(ctx);
765         }
766
767         return 0;
768 }
769
770 static void fimd_disable_vblank(struct device *dev)
771 {
772         struct fimd_context *ctx = get_fimd_context(dev);
773         u32 val,mask;
774
775         DRM_DEBUG_KMS("%s\n", __FILE__);
776
777         if (ctx->suspended)
778                 return;
779
780         if (test_and_clear_bit(0, &ctx->irq_flags)) {
781                 mask = m_DSP_HOLD_VALID_INTR_EN | m_FS_INTR_EN |
782                         m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_EN;
783                 val = v_DSP_HOLD_VALID_INTR_EN(0) | v_FS_INTR_EN(0) |
784                         v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_EN(0);
785                 lcdc_msk_reg(ctx, INTR_CTRL0, mask, val);
786
787                 mask = m_DSP_HOLD_VALID_INTR_CLR | m_FS_INTR_CLR |
788                         m_LINE_FLAG_INTR_CLR | m_LINE_FLAG_INTR_CLR;
789                 val = v_DSP_HOLD_VALID_INTR_CLR(0) | v_FS_INTR_CLR(0) |
790                         v_LINE_FLAG_INTR_CLR(0) | v_BUS_ERROR_INTR_CLR(0);
791                 lcdc_msk_reg(ctx, INTR_CTRL0, mask, val);
792
793                 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN |
794                         m_WIN2_EMPTY_INTR_EN | m_WIN3_EMPTY_INTR_EN |
795                         m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
796                         m_POST_BUF_EMPTY_INTR_EN;
797                 val = v_WIN0_EMPTY_INTR_EN(0) | v_WIN1_EMPTY_INTR_EN(0) |
798                         v_WIN2_EMPTY_INTR_EN(0) | v_WIN3_EMPTY_INTR_EN(0) |
799                         v_HWC_EMPTY_INTR_EN(0) | v_POST_BUF_EMPTY_INTR_EN(0) |
800                         v_PWM_GEN_INTR_EN(0);
801                 lcdc_msk_reg(ctx, INTR_CTRL1, mask, val);
802
803                 mask = m_WIN0_EMPTY_INTR_CLR | m_WIN1_EMPTY_INTR_CLR |
804                         m_WIN2_EMPTY_INTR_CLR | m_WIN3_EMPTY_INTR_CLR |
805                         m_HWC_EMPTY_INTR_CLR | m_POST_BUF_EMPTY_INTR_CLR |
806                         m_POST_BUF_EMPTY_INTR_CLR;
807                 val = v_WIN0_EMPTY_INTR_CLR(0) | v_WIN1_EMPTY_INTR_CLR(0) |
808                         v_WIN2_EMPTY_INTR_CLR(0) | v_WIN3_EMPTY_INTR_CLR(0) |
809                         v_HWC_EMPTY_INTR_CLR(0) | v_POST_BUF_EMPTY_INTR_CLR(0) |
810                         v_PWM_GEN_INTR_CLR(0);
811                 lcdc_msk_reg(ctx, INTR_CTRL1, mask, val);               
812                 lcdc_cfg_done(ctx);
813
814
815         }
816 }
817
818 static void fimd_wait_for_vblank(struct device *dev)
819 {
820         struct fimd_context *ctx = get_fimd_context(dev);
821
822         if (ctx->suspended)
823                 return;
824
825         atomic_set(&ctx->wait_vsync_event, 1);
826
827         /*
828          * wait for FIMD to signal VSYNC interrupt or return after
829          * timeout which is set to 50ms (refresh rate of 20).
830          */
831         if (!wait_event_timeout(ctx->wait_vsync_queue,
832                                 !atomic_read(&ctx->wait_vsync_event),
833                                 DRM_HZ/20))
834                 DRM_DEBUG_KMS("vblank wait timed out.\n");
835 }
836
837 static struct rockchip_drm_manager_ops fimd_manager_ops = {
838         .dpms = fimd_dpms,
839         .apply = fimd_apply,
840         .commit = fimd_commit,
841         .enable_vblank = fimd_enable_vblank,
842         .disable_vblank = fimd_disable_vblank,
843         .wait_for_vblank = fimd_wait_for_vblank,
844 };
845
846 static void fimd_win_mode_set(struct device *dev,
847                               struct rockchip_drm_overlay *overlay)
848 {
849         struct fimd_context *ctx = get_fimd_context(dev);
850         struct fimd_win_data *win_data;
851         int win;
852         unsigned long offset;
853
854         DRM_DEBUG_KMS("%s\n", __FILE__);
855
856         if (!overlay) {
857                 dev_err(dev, "overlay is NULL\n");
858                 return;
859         }
860
861         win = overlay->zpos;
862         if (win == DEFAULT_ZPOS)
863                 win = ctx->default_win;
864
865         if (win < 0 || win > WINDOWS_NR)
866                 return;
867
868         offset = overlay->fb_x * (overlay->bpp >> 3);
869         offset += overlay->fb_y * overlay->pitch;
870
871         DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
872
873         win_data = &ctx->win_data[win];
874
875         win_data->offset_x = overlay->crtc_x;
876         win_data->offset_y = overlay->crtc_y;
877         win_data->ovl_width = overlay->crtc_width;
878         win_data->ovl_height = overlay->crtc_height;
879         win_data->fb_width = overlay->fb_width;
880         win_data->fb_height = overlay->fb_height;
881         win_data->dma_addr = overlay->dma_addr[0] + offset;
882         win_data->bpp = overlay->bpp;
883         win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
884                                 (overlay->bpp >> 3);
885         win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
886
887         DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
888                         win_data->offset_x, win_data->offset_y);
889         DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
890                         win_data->ovl_width, win_data->ovl_height);
891         DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
892         DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
893                         overlay->fb_width, overlay->crtc_width);
894 }
895
896 static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
897 {
898         struct fimd_context *ctx = get_fimd_context(dev);
899         struct fimd_win_data *win_data = &ctx->win_data[win];
900         u8 fmt_cfg = 0;
901
902 #if 0
903         DRM_DEBUG_KMS("%s\n", __FILE__);
904         switch(win_data->bpp){
905                 case 32:
906                         fmt_cfg = 0;
907                         break;
908                 case 24:
909                         fmt_cfg = 1;
910                         break;
911                 case 16:
912                         fmt_cfg = 2;
913                         break;
914                 default:
915                         printk("not support format %d\n",win_data->bpp);
916                         break;
917         }
918
919
920         printk(KERN_ERR"------>yzq %d  SYS_CTRL=%x \n",__LINE__,lcdc_readl(ctx,SYS_CTRL));
921         lcdc_msk_reg(ctx , SYS_CTRL, m_WIN0_FORMAT, v_WIN0_FORMAT(fmt_cfg));
922         printk(KERN_ERR"------>yzq %d  SYS_CTRL=%x \n",__LINE__,lcdc_readl(ctx,SYS_CTRL));
923 #endif
924 }
925
926 static void fimd_win_set_colkey(struct device *dev, unsigned int win)
927 {
928 //      struct fimd_context *ctx = get_fimd_context(dev);
929
930         DRM_DEBUG_KMS("%s\n", __FILE__);
931
932 }
933
934 static void fimd_win_commit(struct device *dev, int zpos)
935 {
936         struct fimd_context *ctx = get_fimd_context(dev);
937         struct fimd_win_data *win_data;
938         struct rk_screen *screen = ctx->screen;
939         int win = zpos;
940         unsigned long val,  size;
941         u32 xpos, ypos;
942
943 //      printk(KERN_ERR"%s %d\n", __func__,__LINE__);
944
945         if (ctx->suspended)
946                 return;
947
948         if (!ctx->clkon)
949                 return;
950 //      printk(KERN_ERR"%s %d\n", __func__,__LINE__);
951         if (win == DEFAULT_ZPOS)
952                 win = ctx->default_win;
953
954         if (win < 0 || win > WINDOWS_NR)
955                 return;
956
957         win_data = &ctx->win_data[win];
958         switch(win){
959                 case 0:
960                         rk3288_win_0_1_reg_update(ctx,0);
961                         break;
962                 case 1:
963 //      printk(KERN_ERR"-->yzq dma_addr=%x buf_offsize=%x win_data->fb_width=%d \nwin_data->fb_height=%d win_data->ovl_height=%d  win_data->ovl_width=%d \n win_data->offset_x=%d win_data->offset_y=%d win_data->line_size=%d\n win_data->bpp=%d ",win_data->dma_addr,win_data->buf_offsize,win_data->fb_width,win_data->fb_height,win_data->ovl_height, win_data->ovl_width,win_data->offset_x,win_data->offset_y,win_data->line_size,win_data->bpp);
964                         rk3288_win_0_1_reg_update(ctx,1);
965                         break;
966                 case 2:
967                         printk("----->yzq not support now win_id=%d\n",win);
968                 //      rk3288_win_2_3_reg_update(ctx,2);
969                         break;
970                 case 3:
971                         printk("----->yzq not support now win_id=%d\n",win);
972                 //      rk3288_win_2_3_reg_update(ctx,3);
973                         break;
974                 default:
975                         printk("----->yzq not support now win_id=%d\n",win);
976                         break;
977         }
978 //      printk("----->yzq now win_id=%d\n",win);
979
980         //rk3288_lcdc_post_cfg(screen);
981         win_data->enabled = true;
982
983 }
984
985 static void fimd_win_disable(struct device *dev, int zpos)
986 {
987         struct fimd_context *ctx = get_fimd_context(dev);
988         struct fimd_win_data *win_data;
989         int win = zpos;
990
991         DRM_DEBUG_KMS("%s\n", __FILE__);
992
993         if (win == DEFAULT_ZPOS)
994                 win = ctx->default_win;
995
996         if (win < 0 || win > WINDOWS_NR)
997                 return;
998
999         win_data = &ctx->win_data[win];
1000
1001         if (ctx->suspended) {
1002                 /* do not resume this window*/
1003                 win_data->resume = false;
1004                 return;
1005         }
1006
1007         win_data->enabled = false;
1008 }
1009
1010 static struct rockchip_drm_overlay_ops fimd_overlay_ops = {
1011         .mode_set = fimd_win_mode_set,
1012         .commit = fimd_win_commit,
1013         .disable = fimd_win_disable,
1014 };
1015
1016 static struct rockchip_drm_manager fimd_manager = {
1017         .pipe           = -1,
1018         .ops            = &fimd_manager_ops,
1019         .overlay_ops    = &fimd_overlay_ops,
1020         .display_ops    = &fimd_display_ops,
1021 };
1022
1023 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
1024 {
1025         struct fimd_context *ctx = (struct fimd_context *)dev_id;
1026         struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
1027         struct drm_device *drm_dev = subdrv->drm_dev;
1028         struct rockchip_drm_manager *manager = subdrv->manager;
1029         u32 intr0_reg;
1030
1031         intr0_reg = lcdc_readl(ctx, INTR_CTRL0);
1032
1033         if(intr0_reg & m_FS_INTR_STS){
1034                 lcdc_msk_reg(ctx, INTR_CTRL0, m_FS_INTR_CLR,
1035                              v_FS_INTR_CLR(1));
1036
1037         }
1038
1039         /* check the crtc is detached already from encoder */
1040         if (manager->pipe < 0)
1041                 goto out;
1042
1043         drm_handle_vblank(drm_dev, manager->pipe);
1044         rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
1045
1046         /* set wait vsync event to zero and wake up queue. */
1047         if (atomic_read(&ctx->wait_vsync_event)) {
1048                 atomic_set(&ctx->wait_vsync_event, 0);
1049                 DRM_WAKEUP(&ctx->wait_vsync_queue);
1050         }
1051 out:
1052         return IRQ_HANDLED;
1053 }
1054
1055 static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
1056 {
1057         DRM_DEBUG_KMS("%s\n", __FILE__);
1058
1059         /*
1060          * enable drm irq mode.
1061          * - with irq_enabled = 1, we can use the vblank feature.
1062          *
1063          * P.S. note that we wouldn't use drm irq handler but
1064          *      just specific driver own one instead because
1065          *      drm framework supports only one irq handler.
1066          */
1067         drm_dev->irq_enabled = 1;
1068
1069         /*
1070          * with vblank_disable_allowed = 1, vblank interrupt will be disabled
1071          * by drm timer once a current process gives up ownership of
1072          * vblank event.(after drm_vblank_put function is called)
1073          */
1074         drm_dev->vblank_disable_allowed = 1;
1075
1076         /* attach this sub driver to iommu mapping if supported. */
1077         if (is_drm_iommu_supported(drm_dev))
1078                 drm_iommu_attach_device(drm_dev, dev);
1079
1080         return 0;
1081 }
1082
1083 static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
1084 {
1085         DRM_DEBUG_KMS("%s\n", __FILE__);
1086
1087         /* detach this sub driver from iommu mapping if supported. */
1088         if (is_drm_iommu_supported(drm_dev))
1089                 drm_iommu_detach_device(drm_dev, dev);
1090 }
1091
1092
1093 static void fimd_clear_win(struct fimd_context *ctx, int win)
1094 {
1095         u32 val;
1096
1097         DRM_DEBUG_KMS("%s\n", __FILE__);
1098
1099 }
1100
1101 static int fimd_clock(struct fimd_context *ctx, bool enable)
1102 {
1103         DRM_DEBUG_KMS("%s\n", __FILE__);
1104 printk(KERN_ERR"---->yzq %s %d \n",__func__,__LINE__);
1105         if (enable) {
1106                 if(ctx->clkon)
1107                         return 0;
1108                 int ret;
1109
1110                 ret = clk_prepare_enable(ctx->hclk);
1111                 if (ret < 0)
1112                         return ret;
1113
1114                 ret = clk_prepare_enable(ctx->dclk);
1115                 if (ret < 0)
1116                         return ret;
1117                 
1118                 ret = clk_prepare_enable(ctx->aclk);
1119                 if (ret < 0)
1120                         return ret;
1121                 ctx->clkon=1;
1122         } else {
1123                 if(!ctx->clkon)
1124                         return 0;
1125                 clk_disable_unprepare(ctx->aclk);
1126                 clk_disable_unprepare(ctx->dclk);
1127                 clk_disable_unprepare(ctx->hclk);
1128                 ctx->clkon=0;
1129         }
1130
1131         return 0;
1132 }
1133
1134 static void fimd_window_suspend(struct device *dev)
1135 {
1136         struct fimd_context *ctx = get_fimd_context(dev);
1137         struct fimd_win_data *win_data;
1138         int i;
1139
1140         for (i = 0; i < WINDOWS_NR; i++) {
1141                 win_data = &ctx->win_data[i];
1142                 win_data->resume = win_data->enabled;
1143                 fimd_win_disable(dev, i);
1144         }
1145         fimd_wait_for_vblank(dev);
1146 }
1147
1148 static void fimd_window_resume(struct device *dev)
1149 {
1150         struct fimd_context *ctx = get_fimd_context(dev);
1151         struct fimd_win_data *win_data;
1152         int i;
1153
1154         for (i = 0; i < WINDOWS_NR; i++) {
1155                 win_data = &ctx->win_data[i];
1156                 win_data->enabled = win_data->resume;
1157                 win_data->resume = false;
1158         }
1159 }
1160
1161 static int fimd_activate(struct fimd_context *ctx, bool enable)
1162 {
1163         struct device *dev = ctx->subdrv.dev;
1164         if (enable) {
1165                 int ret;
1166
1167                 ret = fimd_clock(ctx, true);
1168                 if (ret < 0)
1169                         return ret;
1170
1171                 ctx->suspended = false;
1172
1173                 /* if vblank was enabled status, enable it again. */
1174                 if (test_and_clear_bit(0, &ctx->irq_flags))
1175                         fimd_enable_vblank(dev);
1176
1177                 fimd_window_resume(dev);
1178         } else {
1179                 fimd_window_suspend(dev);
1180
1181                 fimd_clock(ctx, false);
1182                 ctx->suspended = true;
1183         }
1184
1185         return 0;
1186 }
1187
1188 int rk_fb_video_mode_from_timing(const struct display_timing *dt, 
1189                                 struct rk_screen *screen)
1190 {
1191         screen->mode.pixclock = dt->pixelclock.typ;
1192         screen->mode.left_margin = dt->hback_porch.typ;
1193         screen->mode.right_margin = dt->hfront_porch.typ;
1194         screen->mode.xres = dt->hactive.typ;
1195         screen->mode.hsync_len = dt->hsync_len.typ;
1196         screen->mode.upper_margin = dt->vback_porch.typ;
1197         screen->mode.lower_margin = dt->vfront_porch.typ;
1198         screen->mode.yres = dt->vactive.typ;
1199         screen->mode.vsync_len = dt->vsync_len.typ;
1200         screen->type = SCREEN_LVDS;
1201         screen->lvds_format = LVDS_8BIT_2;
1202         screen->face = OUT_D888_P666;
1203
1204         if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
1205                 screen->pin_dclk = 1;
1206         else
1207                 screen->pin_dclk = 0;
1208         if(dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
1209                 screen->pin_hsync = 1;
1210         else
1211                 screen->pin_hsync = 0;
1212         if(dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
1213                 screen->pin_vsync = 1;
1214         else
1215                 screen->pin_vsync = 0;
1216         if(dt->flags & DISPLAY_FLAGS_DE_HIGH)
1217                 screen->pin_den = 1;
1218         else
1219                 screen->pin_den = 0;
1220         
1221         return 0;
1222         
1223 }
1224
1225 int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
1226 {
1227         struct display_timings *disp_timing;
1228         struct display_timing *dt;
1229         disp_timing = of_get_display_timings(np);
1230         if (!disp_timing) {
1231                 pr_err("parse display timing err\n");
1232                 return -EINVAL;
1233         }
1234         dt = display_timings_get(disp_timing, 0);
1235         rk_fb_video_mode_from_timing(dt, screen);
1236         printk(KERN_ERR "dclk:%d\n"
1237                          "hactive:%d\n"
1238                          "hback_porch:%d\n"
1239                          "hfront_porch:%d\n"
1240                          "hsync_len:%d\n"
1241                          "vactive:%d\n"
1242                          "vback_porch:%d\n"
1243                          "vfront_porch:%d\n"
1244                          "vsync_len:%d\n"
1245                          "screen_type:%d\n"
1246                          "lvds_format:%d\n"
1247                          "face:%d\n",
1248                         dt->pixelclock.typ,
1249                         dt->hactive.typ,
1250                         dt->hback_porch.typ,
1251                         dt->hfront_porch.typ,
1252                         dt->hsync_len.typ,
1253                         dt->vactive.typ,
1254                         dt->vback_porch.typ,
1255                         dt->vfront_porch.typ,
1256                         dt->vsync_len.typ,
1257                         dt->screen_type,
1258                         dt->lvds_format,
1259                         dt->face);
1260         return 0;
1261
1262 }
1263
1264 static int fimd_probe(struct platform_device *pdev)
1265 {
1266         struct device *dev = &pdev->dev;
1267         struct fimd_context *ctx;
1268         struct rockchip_drm_subdrv *subdrv;
1269         struct rockchip_drm_fimd_pdata *pdata;
1270         struct rockchip_drm_panel_info *panel;
1271         struct device_node *np = pdev->dev.of_node;
1272         struct rk_screen *screen;
1273         int prop;
1274         int reg_len;
1275         struct resource *res;
1276         int win;
1277         int val;
1278         int ret = -EINVAL;
1279
1280         DRM_DEBUG_KMS("%s\n", __FILE__);
1281         of_property_read_u32(np, "rockchip,prop", &prop);
1282         if (prop == EXTEND) {
1283                 printk("---->%s not support lcdc EXTEND now\n",__func__);
1284                         return 0;
1285         }
1286         if (of_property_read_u32(np, "rockchip,pwr18", &val))
1287         {
1288                 printk("----->%s default set it as 3.xv power supply",__func__);
1289         }
1290         else{
1291                 if(val){
1292                         printk("----->%s lcdc pwr is 1.8, not supply now",__func__);
1293                 }else{
1294                         printk("----->%s lcdc pwr is 3.3v",__func__);
1295                 }
1296         }
1297
1298         if (dev->of_node) {
1299                 panel = devm_kzalloc(dev, sizeof(struct rockchip_drm_panel_info), GFP_KERNEL);
1300                 screen = devm_kzalloc(dev, sizeof(struct rk_screen), GFP_KERNEL);
1301                 rk_fb_get_prmry_screen(screen);
1302                 memcpy(&panel->timing,&screen->mode,sizeof(struct fb_videomode)); 
1303         } else {
1304                 DRM_ERROR("no platform data specified\n");
1305                 return -EINVAL;
1306         }
1307
1308         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1309         if (!ctx)
1310                 return -ENOMEM;
1311
1312         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1313
1314         ctx->regs = devm_ioremap_resource(dev, res);
1315         if (IS_ERR(ctx->regs))
1316                 return PTR_ERR(ctx->regs);
1317         reg_len = resource_size(res);
1318         ctx->regsbak = devm_kzalloc(dev,reg_len,GFP_KERNEL);
1319         ctx->lcdc_id = rk3288_lcdc_get_id(res->start);  
1320         ctx->screen = screen;
1321         ctx->hclk = devm_clk_get(dev, "hclk_lcdc");
1322         ctx->aclk = devm_clk_get(dev, "aclk_lcdc");
1323         ctx->dclk = devm_clk_get(dev, "dclk_lcdc");
1324
1325         ctx->irq = platform_get_irq(pdev, 0);
1326         if (ctx->irq < 0) {
1327                 dev_err(dev, "cannot find IRQ for lcdc%d\n",
1328                         ctx->lcdc_id);
1329                 return -ENXIO;
1330         }
1331         ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler,
1332                                                         0, "drm_fimd", ctx);
1333         if (ret) {
1334                 dev_err(dev, "irq request failed.\n");
1335                 return ret;
1336         }
1337
1338         ctx->default_win = 0;// pdata->default_win;
1339         ctx->panel = panel;
1340         DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
1341         atomic_set(&ctx->wait_vsync_event, 0);
1342
1343         subdrv = &ctx->subdrv;
1344
1345         subdrv->dev = dev;
1346         subdrv->manager = &fimd_manager;
1347         subdrv->probe = fimd_subdrv_probe;
1348         subdrv->remove = fimd_subdrv_remove;
1349
1350         mutex_init(&ctx->lock);
1351
1352         platform_set_drvdata(pdev, ctx);
1353
1354         pm_runtime_enable(dev);
1355         pm_runtime_get_sync(dev);
1356         
1357         ret = clk_set_rate(ctx->dclk, ctx->screen->mode.pixclock);
1358         if (ret)
1359                 printk( "set lcdc%d dclk failed\n", ctx->lcdc_id);
1360         
1361         fimd_activate(ctx, true);
1362
1363         if(trsm_lvds_ops != NULL){
1364                 printk(KERN_ERR"------>yzq enable lvds\n");     
1365                 trsm_lvds_ops->enable();
1366         }
1367         memcpy(ctx->regsbak,ctx->regs,reg_len);
1368         rockchip_drm_subdrv_register(subdrv);
1369
1370         return 0;
1371 }
1372
1373 static int fimd_remove(struct platform_device *pdev)
1374 {
1375         struct device *dev = &pdev->dev;
1376         struct fimd_context *ctx = platform_get_drvdata(pdev);
1377
1378         DRM_DEBUG_KMS("%s\n", __FILE__);
1379
1380         rockchip_drm_subdrv_unregister(&ctx->subdrv);
1381
1382         if (ctx->suspended)
1383                 goto out;
1384
1385         pm_runtime_set_suspended(dev);
1386         pm_runtime_put_sync(dev);
1387
1388 out:
1389         pm_runtime_disable(dev);
1390
1391         return 0;
1392 }
1393
1394 #ifdef CONFIG_PM_SLEEP
1395 static int fimd_suspend(struct device *dev)
1396 {
1397         struct fimd_context *ctx = get_fimd_context(dev);
1398
1399         /*
1400          * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
1401          * called here, an error would be returned by that interface
1402          * because the usage_count of pm runtime is more than 1.
1403          */
1404         if (!pm_runtime_suspended(dev))
1405                 return fimd_activate(ctx, false);
1406
1407         return 0;
1408 }
1409
1410 static int fimd_resume(struct device *dev)
1411 {
1412         struct fimd_context *ctx = get_fimd_context(dev);
1413
1414         /*
1415          * if entered to sleep when lcd panel was on, the usage_count
1416          * of pm runtime would still be 1 so in this case, fimd driver
1417          * should be on directly not drawing on pm runtime interface.
1418          */
1419         if (!pm_runtime_suspended(dev)) {
1420                 int ret;
1421
1422                 ret = fimd_activate(ctx, true);
1423                 if (ret < 0)
1424                         return ret;
1425
1426                 /*
1427                  * in case of dpms on(standby), fimd_apply function will
1428                  * be called by encoder's dpms callback to update fimd's
1429                  * registers but in case of sleep wakeup, it's not.
1430                  * so fimd_apply function should be called at here.
1431                  */
1432                 fimd_apply(dev);
1433         }
1434
1435         return 0;
1436 }
1437 #endif
1438
1439 #ifdef CONFIG_PM_RUNTIME
1440 static int fimd_runtime_suspend(struct device *dev)
1441 {
1442         struct fimd_context *ctx = get_fimd_context(dev);
1443
1444         DRM_DEBUG_KMS("%s\n", __FILE__);
1445
1446         return fimd_activate(ctx, false);
1447 }
1448
1449 static int fimd_runtime_resume(struct device *dev)
1450 {
1451         struct fimd_context *ctx = get_fimd_context(dev);
1452
1453         DRM_DEBUG_KMS("%s\n", __FILE__);
1454
1455         return fimd_activate(ctx, true);
1456 }
1457 #endif
1458 #if defined(CONFIG_OF)
1459 static const struct of_device_id rk3288_lcdc_dt_ids[] = {
1460         {.compatible = "rockchip,rk3288-lcdc",},
1461         {}
1462 };
1463 #endif
1464
1465 static const struct dev_pm_ops fimd_pm_ops = {
1466         SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1467         SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1468 };
1469
1470 struct platform_driver fimd_driver = {
1471         .probe          = fimd_probe,
1472         .remove         = fimd_remove,
1473         .id_table       = rk3288_lcdc_dt_ids,
1474         .driver         = {
1475                 .name   = "rk3288-lcdc",
1476                 .owner  = THIS_MODULE,
1477                 .pm     = &fimd_pm_ops,
1478                 .of_match_table = of_match_ptr(rk3288_lcdc_dt_ids),
1479         },
1480 };