2 * drivers/video/rockchip/lcdc/rk3288_lcdc.c
4 * Copyright (C) 2014 ROCKCHIP, Inc.
5 *Author:hjc<hjc@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.
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.
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
22 #include <linux/slab.h>
23 #include <linux/device.h>
24 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/platform_device.h>
28 #include <linux/clk.h>
29 #include <linux/rockchip-iovmm.h>
30 #include <asm/div64.h>
31 #include <asm/uaccess.h>
32 #include <linux/rockchip/cpu.h>
33 #include <linux/rockchip/iomap.h>
34 #include <linux/rockchip/grf.h>
35 #include <linux/rockchip/common.h>
36 #include <dt-bindings/clock/rk_system_status.h>
38 #include "rk3288_lcdc.h"
40 #if defined(CONFIG_HAS_EARLYSUSPEND)
41 #include <linux/earlysuspend.h>
44 static int dbg_thresd;
45 module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
47 #define DBG(level, x...) do { \
48 if (unlikely(dbg_thresd >= level)) \
49 printk(KERN_INFO x); } while (0)
51 static int rk3288_lcdc_set_bcsh(struct rk_lcdc_driver *dev_drv,
54 /*#define WAIT_FOR_SYNC 1*/
56 static int rk3288_lcdc_get_id(u32 phy_base)
58 if (cpu_is_rk3288()) {
59 if (phy_base == 0xff930000)/*vop big*/
61 else if (phy_base == 0xff940000)/*vop lit*/
66 pr_err("un supported platform \n");
71 static int rk3288_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
76 struct lcdc_device *lcdc_dev = container_of(dev_drv,
77 struct lcdc_device,driver);
78 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
79 lcdc_cfg_done(lcdc_dev);
81 for (i = 0; i < 256; i++) {
82 v = dev_drv->cur_screen->dsp_lut[i];
83 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
85 g = (v & 0xff00) << 4;
86 r = (v & 0xff0000) << 6;
88 for (j = 0; j < 4; j++) {
90 v += (1 + (1 << 10) + (1 << 20)) ;
94 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
100 static int rk3288_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
102 #ifdef CONFIG_RK_FPGA
103 lcdc_dev->clk_on = 1;
106 if (!lcdc_dev->clk_on) {
107 clk_prepare_enable(lcdc_dev->hclk);
108 clk_prepare_enable(lcdc_dev->dclk);
109 clk_prepare_enable(lcdc_dev->aclk);
110 clk_prepare_enable(lcdc_dev->pd);
111 spin_lock(&lcdc_dev->reg_lock);
112 lcdc_dev->clk_on = 1;
113 spin_unlock(&lcdc_dev->reg_lock);
119 static int rk3288_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
121 #ifdef CONFIG_RK_FPGA
122 lcdc_dev->clk_on = 0;
125 if (lcdc_dev->clk_on) {
126 spin_lock(&lcdc_dev->reg_lock);
127 lcdc_dev->clk_on = 0;
128 spin_unlock(&lcdc_dev->reg_lock);
130 clk_disable_unprepare(lcdc_dev->dclk);
131 clk_disable_unprepare(lcdc_dev->hclk);
132 clk_disable_unprepare(lcdc_dev->aclk);
133 clk_disable_unprepare(lcdc_dev->pd);
139 static int rk3288_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
142 spin_lock(&lcdc_dev->reg_lock);
143 if (likely(lcdc_dev->clk_on)) {
144 mask = m_DSP_HOLD_VALID_INTR_EN | m_FS_INTR_EN |
145 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_EN;
146 val = v_DSP_HOLD_VALID_INTR_EN(0) | v_FS_INTR_EN(0) |
147 v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_EN(0);
148 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
150 mask = m_DSP_HOLD_VALID_INTR_CLR | m_FS_INTR_CLR |
151 m_LINE_FLAG_INTR_CLR | m_LINE_FLAG_INTR_CLR;
152 val = v_DSP_HOLD_VALID_INTR_CLR(0) | v_FS_INTR_CLR(0) |
153 v_LINE_FLAG_INTR_CLR(0) | v_BUS_ERROR_INTR_CLR(0);
154 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
156 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN |
157 m_WIN2_EMPTY_INTR_EN | m_WIN3_EMPTY_INTR_EN |
158 m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
159 m_POST_BUF_EMPTY_INTR_EN;
160 val = v_WIN0_EMPTY_INTR_EN(0) | v_WIN1_EMPTY_INTR_EN(0) |
161 v_WIN2_EMPTY_INTR_EN(0) | v_WIN3_EMPTY_INTR_EN(0) |
162 v_HWC_EMPTY_INTR_EN(0) | v_POST_BUF_EMPTY_INTR_EN(0) |
163 v_PWM_GEN_INTR_EN(0);
164 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
166 mask = m_WIN0_EMPTY_INTR_CLR | m_WIN1_EMPTY_INTR_CLR |
167 m_WIN2_EMPTY_INTR_CLR | m_WIN3_EMPTY_INTR_CLR |
168 m_HWC_EMPTY_INTR_CLR | m_POST_BUF_EMPTY_INTR_CLR |
169 m_POST_BUF_EMPTY_INTR_CLR;
170 val = v_WIN0_EMPTY_INTR_CLR(0) | v_WIN1_EMPTY_INTR_CLR(0) |
171 v_WIN2_EMPTY_INTR_CLR(0) | v_WIN3_EMPTY_INTR_CLR(0) |
172 v_HWC_EMPTY_INTR_CLR(0) | v_POST_BUF_EMPTY_INTR_CLR(0) |
173 v_PWM_GEN_INTR_CLR(0);
174 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
175 lcdc_cfg_done(lcdc_dev);
176 spin_unlock(&lcdc_dev->reg_lock);
178 spin_unlock(&lcdc_dev->reg_lock);
183 static int rk3288_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
185 struct lcdc_device *lcdc_dev = container_of(dev_drv,
188 int *cbase = (int *)lcdc_dev->regs;
189 int *regsbak = (int *)lcdc_dev->regsbak;
192 printk("back up reg:\n");
193 for (i = 0; i <= (0x200 >> 4); i++) {
194 printk("0x%04x: ",i*16);
195 for (j = 0; j < 4; j++)
196 printk("%08x ", *(regsbak + i * 4 + j));
200 printk("lcdc reg:\n");
201 for (i = 0; i <= (0x200 >> 4); i++) {
202 printk("0x%04x: ",i*16);
203 for (j = 0; j < 4; j++)
204 printk("%08x ", readl_relaxed(cbase + i * 4 + j));
212 static int win##id##_enable(struct lcdc_device *lcdc_dev, int en) \
215 spin_lock(&lcdc_dev->reg_lock); \
216 msk = m_WIN##id##_EN; \
217 val = v_WIN##id##_EN(en); \
218 lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk, val); \
219 lcdc_cfg_done(lcdc_dev); \
220 val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
221 while (val != (!!en)) { \
222 val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
224 spin_unlock(&lcdc_dev->reg_lock); \
232 /*enable/disable win directly*/
233 static int rk3288_lcdc_win_direct_en
234 (struct rk_lcdc_driver *drv, int win_id , int en)
236 struct lcdc_device *lcdc_dev = container_of(drv,
237 struct lcdc_device, driver);
239 win0_enable(lcdc_dev, en);
240 else if (win_id == 1)
241 win1_enable(lcdc_dev, en);
242 else if (win_id == 2)
243 win2_enable(lcdc_dev, en);
244 else if (win_id == 3)
245 win3_enable(lcdc_dev, en);
247 dev_err(lcdc_dev->dev, "invalid win number:%d\n", win_id);
252 #define SET_WIN_ADDR(id) \
253 static int set_win##id##_addr(struct lcdc_device *lcdc_dev, u32 addr) \
256 spin_lock(&lcdc_dev->reg_lock); \
257 lcdc_writel(lcdc_dev,WIN##id##_YRGB_MST,addr); \
258 msk = m_WIN##id##_EN; \
259 val = v_WIN0_EN(1); \
260 lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk,val); \
261 lcdc_cfg_done(lcdc_dev); \
262 spin_unlock(&lcdc_dev->reg_lock); \
268 int rk3288_lcdc_direct_set_win_addr
269 (struct rk_lcdc_driver *dev_drv, int win_id, u32 addr)
271 struct lcdc_device *lcdc_dev = container_of(dev_drv,
272 struct lcdc_device, driver);
274 set_win0_addr(lcdc_dev, addr);
276 set_win1_addr(lcdc_dev, addr);
281 static void lcdc_read_reg_defalut_cfg(struct lcdc_device *lcdc_dev)
285 struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
287 spin_lock(&lcdc_dev->reg_lock);
288 for (reg = 0; reg < 0x1a0; reg+= 4) {
289 val = lcdc_readl(lcdc_dev, reg);
292 win0->area[0].xact = (val & m_WIN0_ACT_WIDTH)+1;
293 win0->area[0].yact = ((val & m_WIN0_ACT_HEIGHT)>>16)+1;
298 spin_unlock(&lcdc_dev->reg_lock);
302 /********do basic init*********/
303 static int rk3288_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
307 struct lcdc_device *lcdc_dev = container_of(dev_drv,
311 if (lcdc_dev->pre_init)
314 lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
315 lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
316 lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
317 lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
319 if (IS_ERR(lcdc_dev->pd) || (IS_ERR(lcdc_dev->aclk)) ||
320 (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
321 dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
325 rk_disp_pwr_enable(dev_drv);
326 rk3288_lcdc_clk_enable(lcdc_dev);
328 /*backup reg config at uboot*/
329 lcdc_read_reg_defalut_cfg(lcdc_dev);
330 #ifndef CONFIG_RK_FPGA
331 if (lcdc_dev->pwr18 == true) {
332 v = 0x00010001; /*bit14: 1,1.8v;0,3.3v*/
333 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
336 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
339 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_0,0x15110903);
340 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_1,0x00030911);
341 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_0,0x1a150b04);
342 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_1,0x00040b15);
343 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_0,0x15110903);
344 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_1,0x00030911);
346 lcdc_writel(lcdc_dev,FRC_LOWER01_0,0x12844821);
347 lcdc_writel(lcdc_dev,FRC_LOWER01_1,0x21488412);
348 lcdc_writel(lcdc_dev,FRC_LOWER10_0,0xa55a9696);
349 lcdc_writel(lcdc_dev,FRC_LOWER10_1,0x5aa56969);
350 lcdc_writel(lcdc_dev,FRC_LOWER11_0,0xdeb77deb);
351 lcdc_writel(lcdc_dev,FRC_LOWER11_1,0xed7bb7de);
353 mask = m_AUTO_GATING_EN;
354 val = v_AUTO_GATING_EN(0);
355 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val);
356 lcdc_cfg_done(lcdc_dev);
357 if (dev_drv->iommu_enabled) /*disable win0 to workaround iommu pagefault*/
358 win0_enable(lcdc_dev, 0);
359 lcdc_dev->pre_init = true;
365 static void rk3288_lcdc_deint(struct lcdc_device *lcdc_dev)
369 rk3288_lcdc_disable_irq(lcdc_dev);
370 spin_lock(&lcdc_dev->reg_lock);
371 if (likely(lcdc_dev->clk_on)) {
372 lcdc_dev->clk_on = 0;
373 lcdc_set_bit(lcdc_dev, SYS_CTRL, m_STANDBY_EN);
374 lcdc_cfg_done(lcdc_dev);
375 spin_unlock(&lcdc_dev->reg_lock);
377 spin_unlock(&lcdc_dev->reg_lock);
381 static int rk3288_lcdc_post_cfg(struct rk_lcdc_driver *dev_drv)
383 struct lcdc_device *lcdc_dev =
384 container_of(dev_drv, struct lcdc_device, driver);
385 struct rk_screen *screen = dev_drv->cur_screen;
386 u16 x_res = screen->mode.xres;
387 u16 y_res = screen->mode.yres;
390 u16 post_hsd_en,post_vsd_en;
391 u16 post_dsp_hact_st,post_dsp_hact_end;
392 u16 post_dsp_vact_st,post_dsp_vact_end;
393 u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
394 u16 post_h_fac,post_v_fac;
396 h_total = screen->mode.hsync_len+screen->mode.left_margin +
397 x_res + screen->mode.right_margin;
398 v_total = screen->mode.vsync_len+screen->mode.upper_margin +
399 y_res + screen->mode.lower_margin;
401 if(screen->post_dsp_stx + screen->post_xsize > x_res){
402 dev_warn(lcdc_dev->dev, "post:stx[%d] + xsize[%d] > x_res[%d]\n",
403 screen->post_dsp_stx,screen->post_xsize,x_res);
404 screen->post_dsp_stx = x_res - screen->post_xsize;
406 if(screen->x_mirror == 0){
407 post_dsp_hact_st=screen->post_dsp_stx +
408 screen->mode.hsync_len+screen->mode.left_margin;
409 post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize;
411 post_dsp_hact_end = h_total - screen->mode.right_margin -
412 screen->post_dsp_stx;
413 post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize;
415 if((screen->post_xsize < x_res)&&(screen->post_xsize != 0)){
418 GET_SCALE_FACTOR_BILI_DN(x_res , screen->post_xsize);
425 if(screen->post_dsp_sty + screen->post_ysize > y_res){
426 dev_warn(lcdc_dev->dev, "post:sty[%d] + ysize[%d] > y_res[%d]\n",
427 screen->post_dsp_sty,screen->post_ysize,y_res);
428 screen->post_dsp_sty = y_res - screen->post_ysize;
431 if(screen->y_mirror == 0){
432 post_dsp_vact_st = screen->post_dsp_sty +
433 screen->mode.vsync_len+screen->mode.upper_margin;
434 post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
436 post_dsp_vact_end = v_total - screen->mode.lower_margin -
437 - screen->post_dsp_sty;
438 post_dsp_vact_st = post_dsp_vact_end - screen->post_ysize;
440 if((screen->post_ysize < y_res)&&(screen->post_ysize != 0)){
442 post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res, screen->post_ysize);
448 if(screen->interlace == 1){
449 post_dsp_vact_st_f1 = v_total + post_dsp_vact_st;
450 post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
452 post_dsp_vact_st_f1 = 0;
453 post_dsp_vact_end_f1 = 0;
455 DBG(1,"post:xsize=%d,ysize=%d,xpos=%d,ypos=%d,"
456 "hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n",
457 screen->post_xsize,screen->post_ysize,screen->xpos,screen->ypos,
458 post_hsd_en,post_h_fac,post_vsd_en,post_v_fac);
459 mask = m_DSP_HACT_END_POST | m_DSP_HACT_ST_POST;
460 val = v_DSP_HACT_END_POST(post_dsp_hact_end) |
461 v_DSP_HACT_ST_POST(post_dsp_hact_st);
462 lcdc_msk_reg(lcdc_dev, POST_DSP_HACT_INFO, mask, val);
464 mask = m_DSP_VACT_END_POST | m_DSP_VACT_ST_POST;
465 val = v_DSP_VACT_END_POST(post_dsp_vact_end) |
466 v_DSP_VACT_ST_POST(post_dsp_vact_st);
467 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO, mask, val);
469 mask = m_POST_HS_FACTOR_YRGB | m_POST_VS_FACTOR_YRGB;
470 val = v_POST_HS_FACTOR_YRGB(post_h_fac) |
471 v_POST_VS_FACTOR_YRGB(post_v_fac);
472 lcdc_msk_reg(lcdc_dev, POST_SCL_FACTOR_YRGB, mask, val);
474 mask = m_DSP_VACT_END_POST_F1 | m_DSP_VACT_ST_POST_F1;
475 val = v_DSP_VACT_END_POST_F1(post_dsp_vact_end_f1) |
476 v_DSP_VACT_ST_POST_F1(post_dsp_vact_st_f1);
477 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO_F1, mask, val);
479 mask = m_POST_HOR_SD_EN | m_POST_VER_SD_EN;
480 val = v_POST_HOR_SD_EN(post_hsd_en) | v_POST_VER_SD_EN(post_vsd_en);
481 lcdc_msk_reg(lcdc_dev, POST_SCL_CTRL, mask, val);
485 static int rk3288_lcdc_clr_key_cfg(struct rk_lcdc_driver *dev_drv)
487 struct lcdc_device *lcdc_dev = container_of(dev_drv,
491 struct rk_lcdc_win *win;
492 u32 colorkey_r,colorkey_g,colorkey_b;
495 win = dev_drv->win[i];
496 key_val = win->color_key_val;
497 colorkey_r = (key_val & 0xff)<<2;
498 colorkey_g = ((key_val>>8)&0xff)<<12;
499 colorkey_b = ((key_val>>16)&0xff)<<22;
500 /*color key dither 565/888->aaa*/
501 key_val = colorkey_r | colorkey_g | colorkey_b;
504 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY, key_val);
507 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY, key_val);
510 lcdc_writel(lcdc_dev, WIN2_COLOR_KEY, key_val);
513 lcdc_writel(lcdc_dev, WIN3_COLOR_KEY, key_val);
516 printk(KERN_WARNING "%s:un support win num:%d\n",
524 static int rk3288_lcdc_alpha_cfg(struct rk_lcdc_driver *dev_drv,int win_id)
526 struct lcdc_device *lcdc_dev =
527 container_of(dev_drv, struct lcdc_device, driver);
528 struct rk_lcdc_win *win = dev_drv->win[win_id];
529 struct alpha_config alpha_config;
532 int ppixel_alpha,global_alpha;
533 u32 src_alpha_ctl,dst_alpha_ctl;
534 ppixel_alpha = ((win->format == ARGB888)||(win->format == ABGR888)) ? 1 : 0;
535 global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
536 alpha_config.src_global_alpha_val = win->g_alpha_val;
537 win->alpha_mode = AB_SRC_OVER;
538 /*printk("%s,alpha_mode=%d,alpha_en=%d,ppixel_a=%d,gla_a=%d\n",
539 __func__,win->alpha_mode,win->alpha_en,ppixel_alpha,global_alpha);*/
540 switch(win->alpha_mode){
544 alpha_config.src_factor_mode=AA_ZERO;
545 alpha_config.dst_factor_mode=AA_ZERO;
548 alpha_config.src_factor_mode=AA_ONE;
549 alpha_config.dst_factor_mode=AA_ZERO;
552 alpha_config.src_factor_mode=AA_ZERO;
553 alpha_config.dst_factor_mode=AA_ONE;
556 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
558 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
560 alpha_config.src_factor_mode=AA_ONE;
561 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
564 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
565 alpha_config.src_factor_mode=AA_SRC_INVERSE;
566 alpha_config.dst_factor_mode=AA_ONE;
569 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
570 alpha_config.src_factor_mode=AA_SRC;
571 alpha_config.dst_factor_mode=AA_ZERO;
574 alpha_config.src_factor_mode=AA_ZERO;
575 alpha_config.dst_factor_mode=AA_SRC;
578 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
579 alpha_config.src_factor_mode=AA_SRC_INVERSE;
580 alpha_config.dst_factor_mode=AA_ZERO;
583 alpha_config.src_factor_mode=AA_ZERO;
584 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
587 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
588 alpha_config.src_factor_mode=AA_SRC;
589 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
592 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
593 alpha_config.src_factor_mode=AA_SRC_INVERSE;
594 alpha_config.dst_factor_mode=AA_SRC;
597 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
598 alpha_config.src_factor_mode=AA_SRC_INVERSE;
599 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
601 case AB_SRC_OVER_GLOBAL:
602 alpha_config.src_global_alpha_mode=AA_PER_PIX_GLOBAL;
603 alpha_config.src_color_mode=AA_SRC_NO_PRE_MUL;
604 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
605 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
608 pr_err("alpha mode error\n");
611 if((ppixel_alpha == 1)&&(global_alpha == 1)){
612 alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL;
613 }else if(ppixel_alpha == 1){
614 alpha_config.src_global_alpha_mode = AA_PER_PIX;
615 }else if(global_alpha == 1){
616 alpha_config.src_global_alpha_mode = AA_GLOBAL;
618 dev_warn(lcdc_dev->dev,"alpha_en should be 0\n");
620 alpha_config.src_alpha_mode = AA_STRAIGHT;
621 alpha_config.src_alpha_cal_m0 = AA_NO_SAT;
625 src_alpha_ctl = 0x60;
626 dst_alpha_ctl = 0x64;
629 src_alpha_ctl = 0xa0;
630 dst_alpha_ctl = 0xa4;
633 src_alpha_ctl = 0xdc;
634 dst_alpha_ctl = 0xec;
637 src_alpha_ctl = 0x12c;
638 dst_alpha_ctl = 0x13c;
641 mask = m_WIN0_DST_FACTOR_M0;
642 val = v_WIN0_DST_FACTOR_M0(alpha_config.dst_factor_mode);
643 lcdc_msk_reg(lcdc_dev, dst_alpha_ctl, mask, val);
644 mask = m_WIN0_SRC_ALPHA_EN | m_WIN0_SRC_COLOR_M0 |
645 m_WIN0_SRC_ALPHA_M0 | m_WIN0_SRC_BLEND_M0 |
646 m_WIN0_SRC_ALPHA_CAL_M0 | m_WIN0_SRC_FACTOR_M0|
647 m_WIN0_SRC_GLOBAL_ALPHA;
648 val = v_WIN0_SRC_ALPHA_EN(1) |
649 v_WIN0_SRC_COLOR_M0(alpha_config.src_color_mode) |
650 v_WIN0_SRC_ALPHA_M0(alpha_config.src_alpha_mode) |
651 v_WIN0_SRC_BLEND_M0(alpha_config.src_global_alpha_mode) |
652 v_WIN0_SRC_ALPHA_CAL_M0(alpha_config.src_alpha_cal_m0) |
653 v_WIN0_SRC_FACTOR_M0(alpha_config.src_factor_mode) |
654 v_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val);
655 lcdc_msk_reg(lcdc_dev, src_alpha_ctl, mask, val);
659 static int rk3288_lcdc_area_swap(struct rk_lcdc_win *win,int area_num)
661 struct rk_lcdc_win_area area_temp;
664 area_temp = win->area[0];
665 win->area[0] = win->area[1];
666 win->area[1] = area_temp;
669 area_temp = win->area[0];
670 win->area[0] = win->area[2];
671 win->area[2] = area_temp;
674 area_temp = win->area[0];
675 win->area[0] = win->area[3];
676 win->area[3] = area_temp;
678 area_temp = win->area[1];
679 win->area[1] = win->area[2];
680 win->area[2] = area_temp;
683 printk(KERN_WARNING "un supported area num!\n");
689 static int rk3288_win_area_check_var(int win_id,int area_num,struct rk_lcdc_win_area *area_pre,
690 struct rk_lcdc_win_area *area_now)
692 if((area_pre->ypos >= area_now->ypos) ||
693 (area_pre->ypos+area_pre->ysize > area_now->ypos)){
696 "area_pre[%d]:ypos[%d],ysize[%d]\n"
697 "area_now[%d]:ypos[%d],ysize[%d]\n",
699 area_num-1,area_pre->ypos,area_pre->ysize,
700 area_num, area_now->ypos,area_now->ysize);
706 static int rk3288_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
708 struct lcdc_device *lcdc_dev =
709 container_of(dev_drv, struct lcdc_device, driver);
710 struct rk_lcdc_win *win = dev_drv->win[win_id];
711 unsigned int mask, val, off;
713 if(win->win_lb_mode == 5)
714 win->win_lb_mode = 4;
717 mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
718 m_WIN0_LB_MODE | m_WIN0_RB_SWAP;
719 val = v_WIN0_EN(win->state) | v_WIN0_DATA_FMT(win->fmt_cfg) |
720 v_WIN0_FMT_10(win->fmt_10) |
721 v_WIN0_LB_MODE(win->win_lb_mode) |
722 v_WIN0_RB_SWAP(win->swap_rb);
723 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
725 mask = m_WIN0_BIC_COE_SEL |
726 m_WIN0_VSD_YRGB_GT4 | m_WIN0_VSD_YRGB_GT2 |
727 m_WIN0_VSD_CBR_GT4 | m_WIN0_VSD_CBR_GT2 |
728 m_WIN0_YRGB_HOR_SCL_MODE | m_WIN0_YRGB_VER_SCL_MODE |
729 m_WIN0_YRGB_HSD_MODE | m_WIN0_YRGB_VSU_MODE |
730 m_WIN0_YRGB_VSD_MODE | m_WIN0_CBR_HOR_SCL_MODE |
731 m_WIN0_CBR_VER_SCL_MODE | m_WIN0_CBR_HSD_MODE |
732 m_WIN0_CBR_VSU_MODE | m_WIN0_CBR_VSD_MODE;
733 val = v_WIN0_BIC_COE_SEL(win->bic_coe_el) |
734 v_WIN0_VSD_YRGB_GT4(win->vsd_yrgb_gt4) |
735 v_WIN0_VSD_YRGB_GT2(win->vsd_yrgb_gt2) |
736 v_WIN0_VSD_CBR_GT4(win->vsd_cbr_gt4) |
737 v_WIN0_VSD_CBR_GT2(win->vsd_cbr_gt2) |
738 v_WIN0_YRGB_HOR_SCL_MODE(win->yrgb_hor_scl_mode) |
739 v_WIN0_YRGB_VER_SCL_MODE(win->yrgb_ver_scl_mode) |
740 v_WIN0_YRGB_HSD_MODE(win->yrgb_hsd_mode) |
741 v_WIN0_YRGB_VSU_MODE(win->yrgb_vsu_mode) |
742 v_WIN0_YRGB_VSD_MODE(win->yrgb_vsd_mode) |
743 v_WIN0_CBR_HOR_SCL_MODE(win->cbr_hor_scl_mode) |
744 v_WIN0_CBR_VER_SCL_MODE(win->cbr_ver_scl_mode) |
745 v_WIN0_CBR_HSD_MODE(win->cbr_hsd_mode) |
746 v_WIN0_CBR_VSU_MODE(win->cbr_vsu_mode) |
747 v_WIN0_CBR_VSD_MODE(win->cbr_vsd_mode);
748 lcdc_msk_reg(lcdc_dev, WIN0_CTRL1+off, mask,val);
750 val = v_WIN0_VIR_STRIDE(win->area[0].y_vir_stride) |
751 v_WIN0_VIR_STRIDE_UV(win->area[0].uv_vir_stride);
752 lcdc_writel(lcdc_dev, WIN0_VIR+off, val);
753 /*lcdc_writel(lcdc_dev, WIN0_YRGB_MST+off, win->area[0].y_addr);
754 lcdc_writel(lcdc_dev, WIN0_CBR_MST+off, win->area[0].uv_addr);*/
755 val = v_WIN0_ACT_WIDTH(win->area[0].xact) |
756 v_WIN0_ACT_HEIGHT(win->area[0].yact);
757 lcdc_writel(lcdc_dev, WIN0_ACT_INFO+off, val);
759 val = v_WIN0_DSP_WIDTH(win->area[0].xsize) |
760 v_WIN0_DSP_HEIGHT(win->area[0].ysize);
761 lcdc_writel(lcdc_dev, WIN0_DSP_INFO+off, val);
763 val = v_WIN0_DSP_XST(win->area[0].dsp_stx) |
764 v_WIN0_DSP_YST(win->area[0].dsp_sty);
765 lcdc_writel(lcdc_dev, WIN0_DSP_ST+off, val);
767 val = v_WIN0_HS_FACTOR_YRGB(win->scale_yrgb_x) |
768 v_WIN0_VS_FACTOR_YRGB(win->scale_yrgb_y);
769 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB+off, val);
771 val = v_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) |
772 v_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y);
773 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR+off, val);
774 if(win->alpha_en == 1)
775 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
777 mask = m_WIN0_SRC_ALPHA_EN;
778 val = v_WIN0_SRC_ALPHA_EN(0);
779 lcdc_msk_reg(lcdc_dev,WIN0_SRC_ALPHA_CTRL+off,mask,val);
784 val = v_WIN0_EN(win->state);
785 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
790 static int rk3288_win_2_3_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
792 struct lcdc_device *lcdc_dev =
793 container_of(dev_drv, struct lcdc_device, driver);
794 struct rk_lcdc_win *win = dev_drv->win[win_id];
795 struct rk_screen *screen = dev_drv->cur_screen;
796 unsigned int mask, val, off;
797 off = (win_id-2) * 0x50;
798 if((screen->y_mirror == 1)&&(win->area_num > 1)){
799 rk3288_lcdc_area_swap(win,win->area_num);
803 mask = m_WIN2_EN | m_WIN2_DATA_FMT | m_WIN2_RB_SWAP;
804 val = v_WIN2_EN(1) | v_WIN2_DATA_FMT(win->fmt_cfg) |
805 v_WIN2_RB_SWAP(win->swap_rb);
806 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
808 if(win->area[0].state == 1){
809 mask = m_WIN2_MST0_EN;
810 val = v_WIN2_MST0_EN(win->area[0].state);
811 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
813 mask = m_WIN2_VIR_STRIDE0;
814 val = v_WIN2_VIR_STRIDE0(win->area[0].y_vir_stride);
815 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
817 /*lcdc_writel(lcdc_dev,WIN2_MST0+off,win->area[0].y_addr);*/
818 val = v_WIN2_DSP_WIDTH0(win->area[0].xsize) |
819 v_WIN2_DSP_HEIGHT0(win->area[0].ysize);
820 lcdc_writel(lcdc_dev,WIN2_DSP_INFO0+off,val);
821 val = v_WIN2_DSP_XST0(win->area[0].dsp_stx) |
822 v_WIN2_DSP_YST0(win->area[0].dsp_sty);
823 lcdc_writel(lcdc_dev,WIN2_DSP_ST0+off,val);
825 mask = m_WIN2_MST0_EN;
826 val = v_WIN2_MST0_EN(0);
827 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
830 if(win->area[1].state == 1){
831 rk3288_win_area_check_var(win_id,1,&win->area[0],&win->area[1]);
833 mask = m_WIN2_MST1_EN;
834 val = v_WIN2_MST1_EN(win->area[1].state);
835 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
837 mask = m_WIN2_VIR_STRIDE1;
838 val = v_WIN2_VIR_STRIDE1(win->area[1].y_vir_stride);
839 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
841 /*lcdc_writel(lcdc_dev,WIN2_MST1+off,win->area[1].y_addr);*/
842 val = v_WIN2_DSP_WIDTH1(win->area[1].xsize) |
843 v_WIN2_DSP_HEIGHT1(win->area[1].ysize);
844 lcdc_writel(lcdc_dev,WIN2_DSP_INFO1+off,val);
845 val = v_WIN2_DSP_XST1(win->area[1].dsp_stx) |
846 v_WIN2_DSP_YST1(win->area[1].dsp_sty);
847 lcdc_writel(lcdc_dev,WIN2_DSP_ST1+off,val);
849 mask = m_WIN2_MST1_EN;
850 val = v_WIN2_MST1_EN(0);
851 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
854 if(win->area[2].state == 1){
855 rk3288_win_area_check_var(win_id,2,&win->area[1],&win->area[2]);
857 mask = m_WIN2_MST2_EN;
858 val = v_WIN2_MST2_EN(win->area[2].state);
859 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
861 mask = m_WIN2_VIR_STRIDE2;
862 val = v_WIN2_VIR_STRIDE2(win->area[2].y_vir_stride);
863 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
865 /*lcdc_writel(lcdc_dev,WIN2_MST2+off,win->area[2].y_addr);*/
866 val = v_WIN2_DSP_WIDTH2(win->area[2].xsize) |
867 v_WIN2_DSP_HEIGHT2(win->area[2].ysize);
868 lcdc_writel(lcdc_dev,WIN2_DSP_INFO2+off,val);
869 val = v_WIN2_DSP_XST2(win->area[2].dsp_stx) |
870 v_WIN2_DSP_YST2(win->area[2].dsp_sty);
871 lcdc_writel(lcdc_dev,WIN2_DSP_ST2+off,val);
873 mask = m_WIN2_MST2_EN;
874 val = v_WIN2_MST2_EN(0);
875 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
878 if(win->area[3].state == 1){
879 rk3288_win_area_check_var(win_id,3,&win->area[2],&win->area[3]);
881 mask = m_WIN2_MST3_EN;
882 val = v_WIN2_MST3_EN(win->area[3].state);
883 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
885 mask = m_WIN2_VIR_STRIDE3;
886 val = v_WIN2_VIR_STRIDE3(win->area[3].y_vir_stride);
887 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
889 /*lcdc_writel(lcdc_dev,WIN2_MST3+off,win->area[3].y_addr);*/
890 val = v_WIN2_DSP_WIDTH3(win->area[3].xsize) |
891 v_WIN2_DSP_HEIGHT3(win->area[3].ysize);
892 lcdc_writel(lcdc_dev,WIN2_DSP_INFO3+off,val);
893 val = v_WIN2_DSP_XST3(win->area[3].dsp_stx) |
894 v_WIN2_DSP_YST3(win->area[3].dsp_sty);
895 lcdc_writel(lcdc_dev,WIN2_DSP_ST3+off,val);
897 mask = m_WIN2_MST3_EN;
898 val = v_WIN2_MST3_EN(0);
899 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
902 if(win->alpha_en == 1)
903 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
905 mask = m_WIN2_SRC_ALPHA_EN;
906 val = v_WIN2_SRC_ALPHA_EN(0);
907 lcdc_msk_reg(lcdc_dev,WIN2_SRC_ALPHA_CTRL+off,mask,val);
910 mask = m_WIN2_EN | m_WIN2_MST0_EN |
911 m_WIN2_MST0_EN | m_WIN2_MST2_EN |
913 val = v_WIN2_EN(win->state) | v_WIN2_MST0_EN(0) |
914 v_WIN2_MST1_EN(0) | v_WIN2_MST2_EN(0) |
916 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0+off, mask,val);
921 static int rk3288_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
923 struct lcdc_device *lcdc_dev =
924 container_of(dev_drv, struct lcdc_device, driver);
928 spin_lock(&lcdc_dev->reg_lock);
929 if(likely(lcdc_dev->clk_on))
931 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
932 v_STANDBY_EN(lcdc_dev->standby));
933 rk3288_win_0_1_reg_update(dev_drv,0);
934 rk3288_win_0_1_reg_update(dev_drv,1);
935 rk3288_win_2_3_reg_update(dev_drv,2);
936 rk3288_win_2_3_reg_update(dev_drv,3);
937 /*rk3288_lcdc_post_cfg(dev_drv);*/
938 lcdc_cfg_done(lcdc_dev);
940 spin_unlock(&lcdc_dev->reg_lock);
942 /*if (dev_drv->wait_fs) {*/
944 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
945 init_completion(&dev_drv->frame_done);
946 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
947 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
949 (dev_drv->cur_screen->ft +
951 if (!timeout && (!dev_drv->frame_done.done)) {
952 dev_warn(lcdc_dev->dev, "wait for new frame start time out!\n");
956 DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
961 static int rk3288_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
963 if (lcdc_dev->driver.iommu_enabled)
964 memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x330);
966 memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
969 static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
972 struct lcdc_device *lcdc_dev =
973 container_of(dev_drv, struct lcdc_device, driver);
974 spin_lock(&lcdc_dev->reg_lock);
975 if (likely(lcdc_dev->clk_on)) {
978 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
979 mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
980 val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
981 lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
983 spin_unlock(&lcdc_dev->reg_lock);
987 static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
989 #ifdef CONFIG_RK_FPGA
993 struct lcdc_device *lcdc_dev =
994 container_of(dev_drv, struct lcdc_device, driver);
995 struct rk_screen *screen = dev_drv->cur_screen;
997 ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
999 dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
1000 lcdc_dev->pixclock =
1001 div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
1002 lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
1004 fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
1005 screen->ft = 1000 / fps;
1006 dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
1007 lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
1012 static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
1016 struct lcdc_device *lcdc_dev =
1017 container_of(dev_drv, struct lcdc_device, driver);
1018 struct rk_screen *screen = dev_drv->cur_screen;
1019 u16 hsync_len = screen->mode.hsync_len;
1020 u16 left_margin = screen->mode.left_margin;
1021 u16 right_margin = screen->mode.right_margin;
1022 u16 vsync_len = screen->mode.vsync_len;
1023 u16 upper_margin = screen->mode.upper_margin;
1024 u16 lower_margin = screen->mode.lower_margin;
1025 u16 x_res = screen->mode.xres;
1026 u16 y_res = screen->mode.yres;
1028 u16 h_total,v_total;
1030 h_total = hsync_len + left_margin + x_res + right_margin;
1031 v_total = vsync_len + upper_margin + y_res + lower_margin;
1033 screen->post_dsp_stx = x_res * (100 - screen->overscan.left) / 200;
1034 screen->post_dsp_sty = y_res * (100 - screen->overscan.top) / 200;
1035 screen->post_xsize = x_res * (screen->overscan.left + screen->overscan.right) / 200;
1036 screen->post_ysize = y_res * (screen->overscan.top + screen->overscan.bottom) / 200;
1038 spin_lock(&lcdc_dev->reg_lock);
1039 if (likely(lcdc_dev->clk_on)) {
1040 switch (screen->face) {
1043 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1045 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1046 v_DITHER_DOWN_SEL(1);
1047 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1051 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1053 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1054 v_DITHER_DOWN_SEL(1);
1055 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1059 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1061 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1062 v_DITHER_DOWN_SEL(1);
1063 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1067 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1069 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1070 v_DITHER_DOWN_SEL(1);
1071 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1075 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
1076 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
1077 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1080 dev_err(lcdc_dev->dev,"un supported interface!\n");
1083 switch(screen->type){
1086 case SCREEN_DUAL_LVDS:
1087 mask = m_RGB_OUT_EN;
1088 val = v_RGB_OUT_EN(1);
1090 v |= (lcdc_dev->id << 3);
1094 mask = m_HDMI_OUT_EN;
1095 val = v_HDMI_OUT_EN(1);
1098 mask = m_MIPI_OUT_EN;
1099 val = v_MIPI_OUT_EN(1);
1101 case SCREEN_DUAL_MIPI:
1102 mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
1103 val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
1106 face = OUT_RGB_AAA; /*RGB AAA output*/
1107 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
1108 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
1109 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1110 mask = m_EDP_OUT_EN;
1111 val = v_EDP_OUT_EN(1);
1114 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
1115 #ifndef CONFIG_RK_FPGA
1116 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
1118 mask = m_DSP_OUT_MODE | m_DSP_HSYNC_POL | m_DSP_VSYNC_POL |
1119 m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP |
1120 m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
1121 m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN |
1122 m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN;
1123 val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
1124 v_DSP_VSYNC_POL(screen->pin_vsync) |
1125 v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
1126 v_DSP_BG_SWAP(screen->swap_gb) | v_DSP_RB_SWAP(screen->swap_rb) |
1127 v_DSP_RG_SWAP(screen->swap_rg) |
1128 v_DSP_DELTA_SWAP(screen->swap_delta) |
1129 v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) |
1130 v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
1131 v_DSP_X_MIR_EN(screen->x_mirror) | v_DSP_Y_MIR_EN(screen->y_mirror);
1132 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
1134 mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
1135 val = v_DSP_BG_BLUE(0) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
1136 lcdc_msk_reg(lcdc_dev, DSP_BG, mask, val);
1138 mask = m_DSP_HS_PW | m_DSP_HTOTAL;
1139 val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
1140 lcdc_msk_reg(lcdc_dev, DSP_HTOTAL_HS_END, mask, val);
1142 mask = m_DSP_HACT_END | m_DSP_HACT_ST;
1143 val = v_DSP_HACT_END(hsync_len + left_margin + x_res) |
1144 v_DSP_HACT_ST(hsync_len + left_margin);
1145 lcdc_msk_reg(lcdc_dev, DSP_HACT_ST_END, mask, val);
1147 mask = m_DSP_VS_PW | m_DSP_VTOTAL;
1148 val = v_DSP_VS_PW(vsync_len) | v_DSP_VTOTAL(v_total);
1149 lcdc_msk_reg(lcdc_dev, DSP_VTOTAL_VS_END, mask, val);
1151 mask = m_DSP_VACT_END | m_DSP_VACT_ST;
1152 val = v_DSP_VACT_END(vsync_len + upper_margin + y_res) |
1153 v_DSP_VACT_ST(vsync_len + upper_margin);
1154 lcdc_msk_reg(lcdc_dev, DSP_VACT_ST_END, mask, val);
1156 rk3288_lcdc_post_cfg(dev_drv);
1158 spin_unlock(&lcdc_dev->reg_lock);
1159 rk3288_lcdc_set_dclk(dev_drv);
1160 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
1161 dev_drv->trsm_ops->enable();
1168 /*enable layer,open:1,enable;0 disable*/
1169 static int win0_open(struct lcdc_device *lcdc_dev, bool open)
1171 spin_lock(&lcdc_dev->reg_lock);
1172 if (likely(lcdc_dev->clk_on)) {
1174 if (!lcdc_dev->atv_layer_cnt) {
1175 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1176 lcdc_dev->standby = 0;
1178 lcdc_dev->atv_layer_cnt++;
1179 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1180 lcdc_dev->atv_layer_cnt--;
1182 lcdc_dev->driver.win[0]->state = open;
1183 if (!lcdc_dev->atv_layer_cnt) {
1184 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1185 lcdc_dev->standby = 1;
1188 spin_unlock(&lcdc_dev->reg_lock);
1193 static int win1_open(struct lcdc_device *lcdc_dev, bool open)
1195 spin_lock(&lcdc_dev->reg_lock);
1196 if (likely(lcdc_dev->clk_on)) {
1198 if (!lcdc_dev->atv_layer_cnt) {
1199 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1200 lcdc_dev->standby = 0;
1202 lcdc_dev->atv_layer_cnt++;
1203 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1204 lcdc_dev->atv_layer_cnt--;
1206 lcdc_dev->driver.win[1]->state = open;
1208 /*if no layer used,disable lcdc*/
1209 if (!lcdc_dev->atv_layer_cnt) {
1210 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1211 lcdc_dev->standby = 1;
1214 spin_unlock(&lcdc_dev->reg_lock);
1219 static int win2_open(struct lcdc_device *lcdc_dev, bool open)
1221 spin_lock(&lcdc_dev->reg_lock);
1222 if (likely(lcdc_dev->clk_on)) {
1224 if (!lcdc_dev->atv_layer_cnt) {
1225 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1226 lcdc_dev->standby = 0;
1228 lcdc_dev->atv_layer_cnt++;
1229 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1230 lcdc_dev->atv_layer_cnt--;
1232 lcdc_dev->driver.win[2]->state = open;
1234 /*if no layer used,disable lcdc*/
1235 if (!lcdc_dev->atv_layer_cnt) {
1236 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1237 lcdc_dev->standby = 1;
1240 spin_unlock(&lcdc_dev->reg_lock);
1245 static int win3_open(struct lcdc_device *lcdc_dev, bool open)
1247 spin_lock(&lcdc_dev->reg_lock);
1248 if (likely(lcdc_dev->clk_on)) {
1250 if (!lcdc_dev->atv_layer_cnt) {
1251 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1252 lcdc_dev->standby = 0;
1254 lcdc_dev->atv_layer_cnt++;
1255 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1256 lcdc_dev->atv_layer_cnt--;
1258 lcdc_dev->driver.win[3]->state = open;
1260 /*if no layer used,disable lcdc*/
1261 if (!lcdc_dev->atv_layer_cnt) {
1262 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1263 lcdc_dev->standby = 1;
1266 spin_unlock(&lcdc_dev->reg_lock);
1270 static int rk3288_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
1272 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1273 struct lcdc_device, driver);
1275 struct rk_screen *screen = dev_drv->cur_screen;
1277 mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
1278 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR |
1279 m_BUS_ERROR_INTR_EN | m_DSP_LINE_FLAG_NUM;
1280 val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(1) |
1281 v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0) |
1282 v_DSP_LINE_FLAG_NUM(screen->mode.vsync_len + screen->mode.upper_margin +
1284 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
1285 #ifdef LCDC_IRQ_EMPTY_DEBUG
1286 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN | m_WIN2_EMPTY_INTR_EN |
1287 m_WIN3_EMPTY_INTR_EN |m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
1289 val = v_WIN0_EMPTY_INTR_EN(1) | v_WIN1_EMPTY_INTR_EN(1) | v_WIN2_EMPTY_INTR_EN(1) |
1290 v_WIN3_EMPTY_INTR_EN(1)| v_HWC_EMPTY_INTR_EN(1) | v_POST_BUF_EMPTY_INTR_EN(1) |
1291 v_PWM_GEN_INTR_EN(1);
1292 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
1297 static int rk3288_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
1300 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1301 struct lcdc_device, driver);
1302 int sys_status = (dev_drv->id == 0) ?
1303 SYS_STATUS_LCDC0 : SYS_STATUS_LCDC1;
1305 /*enable clk,when first layer open */
1306 if ((open) && (!lcdc_dev->atv_layer_cnt)) {
1307 rockchip_set_system_status(sys_status);
1308 rk3288_lcdc_pre_init(dev_drv);
1309 #if defined(CONFIG_ROCKCHIP_IOMMU)
1310 if (dev_drv->iommu_enabled) {
1311 if (!dev_drv->mmu_dev) {
1313 rk_fb_get_sysmmu_device_by_compatible(dev_drv->mmu_dts_name);
1314 if (dev_drv->mmu_dev) {
1315 rk_fb_platform_set_sysmmu(dev_drv->mmu_dev,
1317 rockchip_iovmm_activate(dev_drv->dev);
1319 dev_err(dev_drv->dev,
1320 "failed to get rockchip iommu device\n");
1326 rk3288_lcdc_clk_enable(lcdc_dev);
1327 rk3288_lcdc_reg_restore(lcdc_dev);
1328 if (dev_drv->iommu_enabled)
1329 rk3288_lcdc_mmu_en(dev_drv);
1330 if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
1331 rk3288_lcdc_set_dclk(dev_drv);
1332 rk3288_lcdc_enable_irq(dev_drv);
1334 rk3288_load_screen(dev_drv, 1);
1336 if (dev_drv->bcsh.enable)
1337 rk3288_lcdc_set_bcsh(dev_drv, 1);
1338 spin_lock(&lcdc_dev->reg_lock);
1339 if (dev_drv->cur_screen->dsp_lut)
1340 rk3288_lcdc_set_lut(dev_drv);
1341 spin_unlock(&lcdc_dev->reg_lock);
1345 win0_open(lcdc_dev, open);
1346 else if (win_id == 1)
1347 win1_open(lcdc_dev, open);
1348 else if (win_id == 2)
1349 win2_open(lcdc_dev, open);
1350 else if (win_id == 3)
1351 win3_open(lcdc_dev, open);
1353 dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
1355 /* when all layer closed,disable clk */
1356 if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
1357 rk3288_lcdc_disable_irq(lcdc_dev);
1358 rk3288_lcdc_reg_update(dev_drv);
1359 #if defined(CONFIG_ROCKCHIP_IOMMU)
1360 if (dev_drv->iommu_enabled) {
1361 if (dev_drv->mmu_dev)
1362 rockchip_iovmm_deactivate(dev_drv->dev);
1365 rk3288_lcdc_clk_disable(lcdc_dev);
1366 rockchip_clear_system_status(sys_status);
1372 static int win0_display(struct lcdc_device *lcdc_dev,
1373 struct rk_lcdc_win *win)
1377 y_addr = win->area[0].smem_start+win->area[0].y_offset;/*win->smem_start + win->y_offset;*/
1378 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1379 DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
1380 lcdc_dev->id, __func__, y_addr, uv_addr,win->area[0].y_offset);
1381 spin_lock(&lcdc_dev->reg_lock);
1382 if (likely(lcdc_dev->clk_on)) {
1383 win->area[0].y_addr = y_addr;
1384 win->area[0].uv_addr = uv_addr;
1385 lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr);
1386 lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr);
1387 /*lcdc_cfg_done(lcdc_dev);*/
1389 spin_unlock(&lcdc_dev->reg_lock);
1395 static int win1_display(struct lcdc_device *lcdc_dev,
1396 struct rk_lcdc_win *win)
1400 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1401 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1402 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>uv_addr:0x%x\n",
1403 lcdc_dev->id, __func__, y_addr, uv_addr);
1405 spin_lock(&lcdc_dev->reg_lock);
1406 if (likely(lcdc_dev->clk_on)) {
1407 win->area[0].y_addr = y_addr;
1408 win->area[0].uv_addr = uv_addr;
1409 lcdc_writel(lcdc_dev, WIN1_YRGB_MST, win->area[0].y_addr);
1410 lcdc_writel(lcdc_dev, WIN1_CBR_MST, win->area[0].uv_addr);
1412 spin_unlock(&lcdc_dev->reg_lock);
1418 static int win2_display(struct lcdc_device *lcdc_dev,
1419 struct rk_lcdc_win *win)
1422 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1423 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1424 lcdc_dev->id, __func__, y_addr);
1426 spin_lock(&lcdc_dev->reg_lock);
1427 if (likely(lcdc_dev->clk_on)){
1428 for(i=0;i<win->area_num;i++)
1429 win->area[i].y_addr =
1430 win->area[i].smem_start + win->area[i].y_offset;
1431 lcdc_writel(lcdc_dev,WIN2_MST0,win->area[0].y_addr);
1432 lcdc_writel(lcdc_dev,WIN2_MST1,win->area[1].y_addr);
1433 lcdc_writel(lcdc_dev,WIN2_MST2,win->area[2].y_addr);
1434 lcdc_writel(lcdc_dev,WIN2_MST3,win->area[3].y_addr);
1436 spin_unlock(&lcdc_dev->reg_lock);
1440 static int win3_display(struct lcdc_device *lcdc_dev,
1441 struct rk_lcdc_win *win)
1444 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1445 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1446 lcdc_dev->id, __func__, y_addr);
1448 spin_lock(&lcdc_dev->reg_lock);
1449 if (likely(lcdc_dev->clk_on)){
1450 for(i=0;i<win->area_num;i++)
1451 win->area[i].y_addr =
1452 win->area[i].smem_start + win->area[i].y_offset;
1453 lcdc_writel(lcdc_dev,WIN3_MST0,win->area[0].y_addr);
1454 lcdc_writel(lcdc_dev,WIN3_MST1,win->area[1].y_addr);
1455 lcdc_writel(lcdc_dev,WIN3_MST2,win->area[2].y_addr);
1456 lcdc_writel(lcdc_dev,WIN3_MST3,win->area[3].y_addr);
1458 spin_unlock(&lcdc_dev->reg_lock);
1462 static int rk3288_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
1464 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1465 struct lcdc_device, driver);
1466 struct rk_lcdc_win *win = NULL;
1467 struct rk_screen *screen = dev_drv->cur_screen;
1469 #if defined(WAIT_FOR_SYNC)
1471 unsigned long flags;
1473 win = dev_drv->win[win_id];
1475 dev_err(dev_drv->dev, "screen is null!\n");
1479 win0_display(lcdc_dev, win);
1480 }else if(win_id == 1){
1481 win1_display(lcdc_dev, win);
1482 }else if(win_id == 2){
1483 win2_display(lcdc_dev, win);
1484 }else if(win_id == 3){
1485 win3_display(lcdc_dev, win);
1487 dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
1491 /*this is the first frame of the system ,enable frame start interrupt */
1492 if ((dev_drv->first_frame)) {
1493 dev_drv->first_frame = 0;
1494 rk3288_lcdc_enable_irq(dev_drv);
1496 #if defined(WAIT_FOR_SYNC)
1497 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
1498 init_completion(&dev_drv->frame_done);
1499 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
1500 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
1501 msecs_to_jiffies(dev_drv->
1504 if (!timeout && (!dev_drv->frame_done.done)) {
1505 dev_info(dev_drv->dev, "wait for new frame start time out!\n");
1512 static int rk3288_lcdc_cal_scl_fac(struct rk_lcdc_win *win)
1522 u32 yrgb_vScaleDnMult;
1523 u32 yrgb_xscl_factor;
1524 u32 yrgb_yscl_factor;
1525 u8 yrgb_vsd_bil_gt2=0;
1526 u8 yrgb_vsd_bil_gt4=0;
1532 u32 cbcr_vScaleDnMult;
1533 u32 cbcr_xscl_factor;
1534 u32 cbcr_yscl_factor;
1535 u8 cbcr_vsd_bil_gt2=0;
1536 u8 cbcr_vsd_bil_gt4=0;
1540 srcW = win->area[0].xact;
1541 srcH = win->area[0].yact;
1542 dstW = win->area[0].xsize;
1543 dstH = win->area[0].ysize;
1550 if ((yrgb_dstW >= yrgb_srcW*8) || (yrgb_dstH >= yrgb_srcH*8) ||
1551 (yrgb_dstW*8 <= yrgb_srcW) || (yrgb_dstH*8 <= yrgb_srcH)) {
1552 pr_err("ERROR: yrgb scale exceed 8,"
1553 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1554 yrgb_srcW,yrgb_srcH,yrgb_dstW,yrgb_dstH);
1556 if(yrgb_srcW < yrgb_dstW){
1557 win->yrgb_hor_scl_mode = SCALE_UP;
1558 }else if(yrgb_srcW > yrgb_dstW){
1559 win->yrgb_hor_scl_mode = SCALE_DOWN;
1561 win->yrgb_hor_scl_mode = SCALE_NONE;
1564 if(yrgb_srcH < yrgb_dstH){
1565 win->yrgb_ver_scl_mode = SCALE_UP;
1566 }else if (yrgb_srcH > yrgb_dstH){
1567 win->yrgb_ver_scl_mode = SCALE_DOWN;
1569 win->yrgb_ver_scl_mode = SCALE_NONE;
1573 switch (win->format) {
1607 if ((cbcr_dstW >= cbcr_srcW*8) || (cbcr_dstH >= cbcr_srcH*8) ||
1608 (cbcr_dstW*8 <= cbcr_srcW)||(cbcr_dstH*8 <= cbcr_srcH)) {
1609 pr_err("ERROR: cbcr scale exceed 8,"
1610 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1611 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH);
1615 if(cbcr_srcW < cbcr_dstW){
1616 win->cbr_hor_scl_mode = SCALE_UP;
1617 }else if(cbcr_srcW > cbcr_dstW){
1618 win->cbr_hor_scl_mode = SCALE_DOWN;
1620 win->cbr_hor_scl_mode = SCALE_NONE;
1623 if(cbcr_srcH < cbcr_dstH){
1624 win->cbr_ver_scl_mode = SCALE_UP;
1625 }else if(cbcr_srcH > cbcr_dstH){
1626 win->cbr_ver_scl_mode = SCALE_DOWN;
1628 win->cbr_ver_scl_mode = SCALE_NONE;
1630 DBG(1, "srcW:%d>>srcH:%d>>dstW:%d>>dstH:%d>>\n"
1631 "yrgb:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1632 "cbcr:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1633 ,srcW,srcH,dstW,dstH,yrgb_srcW,yrgb_srcH,yrgb_dstW,
1634 yrgb_dstH,win->yrgb_hor_scl_mode,win->yrgb_ver_scl_mode,
1635 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH,
1636 win->cbr_hor_scl_mode,win->cbr_ver_scl_mode);
1638 /*line buffer mode*/
1639 if((win->format == YUV422) || (win->format == YUV420) || (win->format == YUV422_A) || (win->format == YUV420_A)){
1640 if(win->cbr_hor_scl_mode == SCALE_DOWN){
1641 if ((cbcr_dstW > 3840) || (cbcr_dstW == 0)) {
1642 pr_err("ERROR cbcr_dstW = %d\n",cbcr_dstW);
1643 }else if(cbcr_dstW > 2560){
1644 win->win_lb_mode = LB_RGB_3840X2;
1645 }else if(cbcr_dstW > 1920){
1646 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1647 if(yrgb_dstW > 3840){
1648 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1649 }else if(yrgb_dstW > 2560){
1650 win->win_lb_mode = LB_RGB_3840X2;
1651 }else if(yrgb_dstW > 1920){
1652 win->win_lb_mode = LB_RGB_2560X4;
1654 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1657 }else if(cbcr_dstW > 1280){
1658 win->win_lb_mode = LB_YUV_3840X5;
1660 win->win_lb_mode = LB_YUV_2560X8;
1662 } else { /*SCALE_UP or SCALE_NONE*/
1663 if ((cbcr_srcW > 3840) || (cbcr_srcW == 0)) {
1664 pr_err("ERROR cbcr_srcW = %d\n",cbcr_srcW);
1665 }else if(cbcr_srcW > 2560){
1666 win->win_lb_mode = LB_RGB_3840X2;
1667 }else if(cbcr_srcW > 1920){
1668 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1669 if(yrgb_dstW > 3840){
1670 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1671 }else if(yrgb_dstW > 2560){
1672 win->win_lb_mode = LB_RGB_3840X2;
1673 }else if(yrgb_dstW > 1920){
1674 win->win_lb_mode = LB_RGB_2560X4;
1676 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1679 }else if(cbcr_srcW > 1280){
1680 win->win_lb_mode = LB_YUV_3840X5;
1682 win->win_lb_mode = LB_YUV_2560X8;
1686 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1687 if ((yrgb_dstW > 3840) || (yrgb_dstW == 0)) {
1688 pr_err("ERROR yrgb_dstW = %d\n",yrgb_dstW);
1689 }else if(yrgb_dstW > 2560){
1690 win->win_lb_mode = LB_RGB_3840X2;
1691 }else if(yrgb_dstW > 1920){
1692 win->win_lb_mode = LB_RGB_2560X4;
1693 }else if(yrgb_dstW > 1280){
1694 win->win_lb_mode = LB_RGB_1920X5;
1696 win->win_lb_mode = LB_RGB_1280X8;
1698 }else{ /*SCALE_UP or SCALE_NONE*/
1699 if ((yrgb_srcW > 3840) || (yrgb_srcW == 0)) {
1700 pr_err("ERROR yrgb_srcW = %d\n",yrgb_srcW);
1701 }else if(yrgb_srcW > 2560){
1702 win->win_lb_mode = LB_RGB_3840X2;
1703 }else if(yrgb_srcW > 1920){
1704 win->win_lb_mode = LB_RGB_2560X4;
1705 }else if(yrgb_srcW > 1280){
1706 win->win_lb_mode = LB_RGB_1920X5;
1708 win->win_lb_mode = LB_RGB_1280X8;
1712 DBG(1,"win->win_lb_mode = %d;\n",win->win_lb_mode);
1714 /*vsd/vsu scale ALGORITHM*/
1715 win->yrgb_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1716 win->cbr_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1717 win->yrgb_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1718 win->cbr_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1719 switch(win->win_lb_mode){
1724 win->yrgb_vsu_mode = SCALE_UP_BIC;
1725 win->cbr_vsu_mode = SCALE_UP_BIC;
1728 if(win->yrgb_ver_scl_mode != SCALE_NONE) {
1729 pr_err("ERROR : not allow yrgb ver scale\n");
1731 if(win->cbr_ver_scl_mode != SCALE_NONE) {
1732 pr_err("ERROR : not allow cbcr ver scale\n");
1736 win->yrgb_vsu_mode = SCALE_UP_BIL;
1737 win->cbr_vsu_mode = SCALE_UP_BIL;
1740 printk(KERN_WARNING "%s:un supported win_lb_mode:%d\n",
1741 __func__,win->win_lb_mode);
1744 DBG(1,"yrgb:hsd=%d,vsd=%d,vsu=%d;cbcr:hsd=%d,vsd=%d,vsu=%d\n",
1745 win->yrgb_hsd_mode,win->yrgb_vsd_mode,win->yrgb_vsu_mode,
1746 win->cbr_hsd_mode,win->cbr_vsd_mode,win->cbr_vsu_mode);
1750 /*(1.1)YRGB HOR SCALE FACTOR*/
1751 switch(win->yrgb_hor_scl_mode){
1753 yrgb_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1756 yrgb_xscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcW, yrgb_dstW);
1759 switch(win->yrgb_hsd_mode)
1761 case SCALE_DOWN_BIL:
1762 yrgb_xscl_factor = GET_SCALE_FACTOR_BILI_DN(yrgb_srcW, yrgb_dstW);
1764 case SCALE_DOWN_AVG:
1765 yrgb_xscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcW, yrgb_dstW);
1768 printk(KERN_WARNING "%s:un supported yrgb_hsd_mode:%d\n",
1769 __func__,win->yrgb_hsd_mode);
1774 printk(KERN_WARNING "%s:un supported yrgb_hor_scl_mode:%d\n",
1775 __func__,win->yrgb_hor_scl_mode);
1777 } /*win->yrgb_hor_scl_mode*/
1779 /*(1.2)YRGB VER SCALE FACTOR*/
1780 switch(win->yrgb_ver_scl_mode)
1783 yrgb_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1786 switch(win->yrgb_vsu_mode)
1789 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_UP(yrgb_srcH, yrgb_dstH);
1793 pr_err("yrgb_srcH should be greater than 3 !!!\n");
1795 yrgb_yscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcH, yrgb_dstH);
1798 printk(KERN_WARNING "%s:un supported yrgb_vsu_mode:%d\n",
1799 __func__,win->yrgb_vsu_mode);
1804 switch(win->yrgb_vsd_mode)
1806 case SCALE_DOWN_BIL:
1807 yrgb_vScaleDnMult = getHardWareVSkipLines(yrgb_srcH, yrgb_dstH);
1808 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(yrgb_srcH, yrgb_dstH, yrgb_vScaleDnMult);
1809 if(yrgb_vScaleDnMult == 4){
1810 yrgb_vsd_bil_gt4 = 1;
1811 yrgb_vsd_bil_gt2 = 0;
1812 }else if(yrgb_vScaleDnMult == 2){
1813 yrgb_vsd_bil_gt4 = 0;
1814 yrgb_vsd_bil_gt2 = 1;
1816 yrgb_vsd_bil_gt4 = 0;
1817 yrgb_vsd_bil_gt2 = 0;
1820 case SCALE_DOWN_AVG:
1821 yrgb_yscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcH, yrgb_dstH);
1824 printk(KERN_WARNING "%s:un supported yrgb_vsd_mode:%d\n",
1825 __func__,win->yrgb_vsd_mode);
1827 } /*win->yrgb_vsd_mode*/
1830 printk(KERN_WARNING "%s:un supported yrgb_ver_scl_mode:%d\n",
1831 __func__,win->yrgb_ver_scl_mode);
1834 win->scale_yrgb_x = yrgb_xscl_factor;
1835 win->scale_yrgb_y = yrgb_yscl_factor;
1836 win->vsd_yrgb_gt4 = yrgb_vsd_bil_gt4;
1837 win->vsd_yrgb_gt2 = yrgb_vsd_bil_gt2;
1838 DBG(1,"yrgb:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",yrgb_xscl_factor,
1839 yrgb_yscl_factor,yrgb_vsd_bil_gt4,yrgb_vsd_bil_gt2);
1841 /*(2.1)CBCR HOR SCALE FACTOR*/
1842 switch(win->cbr_hor_scl_mode)
1845 cbcr_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1848 cbcr_xscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcW, cbcr_dstW);
1851 switch(win->cbr_hsd_mode)
1853 case SCALE_DOWN_BIL:
1854 cbcr_xscl_factor = GET_SCALE_FACTOR_BILI_DN(cbcr_srcW, cbcr_dstW);
1856 case SCALE_DOWN_AVG:
1857 cbcr_xscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcW, cbcr_dstW);
1860 printk(KERN_WARNING "%s:un supported cbr_hsd_mode:%d\n",
1861 __func__,win->cbr_hsd_mode);
1866 printk(KERN_WARNING "%s:un supported cbr_hor_scl_mode:%d\n",
1867 __func__,win->cbr_hor_scl_mode);
1869 } /*win->cbr_hor_scl_mode*/
1871 /*(2.2)CBCR VER SCALE FACTOR*/
1872 switch(win->cbr_ver_scl_mode)
1875 cbcr_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1878 switch(win->cbr_vsu_mode)
1881 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_UP(cbcr_srcH, cbcr_dstH);
1885 pr_err("cbcr_srcH should be greater than 3 !!!\n");
1887 cbcr_yscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcH, cbcr_dstH);
1890 printk(KERN_WARNING "%s:un supported cbr_vsu_mode:%d\n",
1891 __func__,win->cbr_vsu_mode);
1896 switch(win->cbr_vsd_mode)
1898 case SCALE_DOWN_BIL:
1899 cbcr_vScaleDnMult = getHardWareVSkipLines(cbcr_srcH, cbcr_dstH);
1900 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(cbcr_srcH, cbcr_dstH, cbcr_vScaleDnMult);
1901 if(cbcr_vScaleDnMult == 4){
1902 cbcr_vsd_bil_gt4 = 1;
1903 cbcr_vsd_bil_gt2 = 0;
1904 }else if(cbcr_vScaleDnMult == 2){
1905 cbcr_vsd_bil_gt4 = 0;
1906 cbcr_vsd_bil_gt2 = 1;
1908 cbcr_vsd_bil_gt4 = 0;
1909 cbcr_vsd_bil_gt2 = 0;
1912 case SCALE_DOWN_AVG:
1913 cbcr_yscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcH, cbcr_dstH);
1916 printk(KERN_WARNING "%s:un supported cbr_vsd_mode:%d\n",
1917 __func__,win->cbr_vsd_mode);
1922 printk(KERN_WARNING "%s:un supported cbr_ver_scl_mode:%d\n",
1923 __func__,win->cbr_ver_scl_mode);
1926 win->scale_cbcr_x = cbcr_xscl_factor;
1927 win->scale_cbcr_y = cbcr_yscl_factor;
1928 win->vsd_cbr_gt4 = cbcr_vsd_bil_gt4;
1929 win->vsd_cbr_gt2 = cbcr_vsd_bil_gt2;
1931 DBG(1,"cbcr:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",cbcr_xscl_factor,
1932 cbcr_yscl_factor,cbcr_vsd_bil_gt4,cbcr_vsd_bil_gt2);
1938 static int win0_set_par(struct lcdc_device *lcdc_dev,
1939 struct rk_screen *screen, struct rk_lcdc_win *win)
1941 u32 xact,yact,xvir, yvir,xpos, ypos;
1943 char fmt[9] = "NULL";
1945 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
1946 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
1948 spin_lock(&lcdc_dev->reg_lock);
1949 if(likely(lcdc_dev->clk_on)){
1950 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
1951 switch (win->format){
2003 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2007 win->fmt_cfg = fmt_cfg;
2008 win->area[0].dsp_stx = xpos;
2009 win->area[0].dsp_sty = ypos;
2010 xact = win->area[0].xact;
2011 yact = win->area[0].yact;
2012 xvir = win->area[0].xvir;
2013 yvir = win->area[0].yvir;
2015 rk3288_win_0_1_reg_update(&lcdc_dev->driver,0);
2016 spin_unlock(&lcdc_dev->reg_lock);
2018 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2019 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2020 __func__, get_format_string(win->format, fmt), xact,
2021 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2026 static int win1_set_par(struct lcdc_device *lcdc_dev,
2027 struct rk_screen *screen, struct rk_lcdc_win *win)
2029 u32 xact,yact,xvir, yvir,xpos, ypos;
2031 char fmt[9] = "NULL";
2033 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
2034 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
2036 spin_lock(&lcdc_dev->reg_lock);
2037 if(likely(lcdc_dev->clk_on)){
2038 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
2039 switch (win->format){
2092 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2096 win->fmt_cfg = fmt_cfg;
2097 win->area[0].dsp_stx = xpos;
2098 win->area[0].dsp_sty = ypos;
2099 xact = win->area[0].xact;
2100 yact = win->area[0].yact;
2101 xvir = win->area[0].xvir;
2102 yvir = win->area[0].yvir;
2104 rk3288_win_0_1_reg_update(&lcdc_dev->driver,1);
2105 spin_unlock(&lcdc_dev->reg_lock);
2107 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2108 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2109 __func__, get_format_string(win->format, fmt), xact,
2110 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2115 static int win2_set_par(struct lcdc_device *lcdc_dev,
2116 struct rk_screen *screen, struct rk_lcdc_win *win)
2121 spin_lock(&lcdc_dev->reg_lock);
2122 if(likely(lcdc_dev->clk_on)){
2123 for(i=0;i<win->area_num;i++){
2124 switch (win->format){
2143 dev_err(lcdc_dev->driver.dev,
2144 "%s:un supported format!\n",
2148 win->fmt_cfg = fmt_cfg;
2149 win->area[i].dsp_stx = win->area[i].xpos +
2150 screen->mode.left_margin +
2151 screen->mode.hsync_len;
2152 if (screen->y_mirror == 1) {
2153 win->area[i].dsp_sty = screen->mode.yres -
2155 win->area[i].ysize +
2156 screen->mode.upper_margin +
2157 screen->mode.vsync_len;
2159 win->area[i].dsp_sty = win->area[i].ypos +
2160 screen->mode.upper_margin +
2161 screen->mode.vsync_len;
2165 rk3288_win_2_3_reg_update(&lcdc_dev->driver,2);
2166 spin_unlock(&lcdc_dev->reg_lock);
2170 static int win3_set_par(struct lcdc_device *lcdc_dev,
2171 struct rk_screen *screen, struct rk_lcdc_win *win)
2177 spin_lock(&lcdc_dev->reg_lock);
2178 if(likely(lcdc_dev->clk_on)){
2179 for(i=0;i<win->area_num;i++){
2180 switch (win->format){
2199 dev_err(lcdc_dev->driver.dev,
2200 "%s:un supported format!\n",
2204 win->fmt_cfg = fmt_cfg;
2205 win->area[i].dsp_stx = win->area[i].xpos +
2206 screen->mode.left_margin +
2207 screen->mode.hsync_len;
2208 if (screen->y_mirror == 1) {
2209 win->area[i].dsp_sty = screen->mode.yres -
2211 win->area[i].ysize +
2212 screen->mode.upper_margin +
2213 screen->mode.vsync_len;
2215 win->area[i].dsp_sty = win->area[i].ypos +
2216 screen->mode.upper_margin +
2217 screen->mode.vsync_len;
2221 rk3288_win_2_3_reg_update(&lcdc_dev->driver,3);
2222 spin_unlock(&lcdc_dev->reg_lock);
2226 static int rk3288_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id)
2228 struct lcdc_device *lcdc_dev =
2229 container_of(dev_drv, struct lcdc_device, driver);
2230 struct rk_lcdc_win *win = NULL;
2231 struct rk_screen *screen = dev_drv->cur_screen;
2232 win = dev_drv->win[win_id];
2237 win0_set_par(lcdc_dev, screen, win);
2240 win1_set_par(lcdc_dev, screen, win);
2243 win2_set_par(lcdc_dev, screen, win);
2246 win3_set_par(lcdc_dev, screen, win);
2249 dev_err(dev_drv->dev, "unsupported win number:%d\n", win_id);
2255 static int rk3288_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
2256 unsigned long arg, int win_id)
2258 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2263 void __user *argp = (void __user *)arg;
2264 struct color_key_cfg clr_key_cfg;
2267 case RK_FBIOGET_PANEL_SIZE:
2268 panel_size[0] = lcdc_dev->screen->mode.xres;
2269 panel_size[1] = lcdc_dev->screen->mode.yres;
2270 if (copy_to_user(argp, panel_size, 8))
2273 case RK_FBIOPUT_COLOR_KEY_CFG:
2274 if (copy_from_user(&clr_key_cfg, argp,
2275 sizeof(struct color_key_cfg)))
2277 rk3288_lcdc_clr_key_cfg(dev_drv);
2278 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
2279 clr_key_cfg.win0_color_key_cfg);
2280 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
2281 clr_key_cfg.win1_color_key_cfg);
2290 static int rk3288_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
2293 struct lcdc_device *lcdc_dev =
2294 container_of(dev_drv, struct lcdc_device, driver);
2295 if (dev_drv->suspend_flag)
2298 dev_drv->suspend_flag = 1;
2299 flush_kthread_worker(&dev_drv->update_regs_worker);
2301 for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4)
2302 lcdc_readl(lcdc_dev, reg);
2303 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
2304 dev_drv->trsm_ops->disable();
2306 spin_lock(&lcdc_dev->reg_lock);
2307 if (likely(lcdc_dev->clk_on)) {
2308 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2310 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR | m_LINE_FLAG_INTR_CLR,
2311 v_FS_INTR_CLR(1) | v_LINE_FLAG_INTR_CLR(1));
2312 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2314 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2316 lcdc_cfg_done(lcdc_dev);
2318 if (dev_drv->iommu_enabled) {
2319 if (dev_drv->mmu_dev)
2320 rockchip_iovmm_deactivate(dev_drv->dev);
2323 spin_unlock(&lcdc_dev->reg_lock);
2325 spin_unlock(&lcdc_dev->reg_lock);
2328 rk3288_lcdc_clk_disable(lcdc_dev);
2329 rk_disp_pwr_disable(dev_drv);
2333 static int rk3288_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
2335 struct lcdc_device *lcdc_dev =
2336 container_of(dev_drv, struct lcdc_device, driver);
2341 if (!dev_drv->suspend_flag)
2343 rk_disp_pwr_enable(dev_drv);
2344 dev_drv->suspend_flag = 0;
2346 if (lcdc_dev->atv_layer_cnt) {
2347 rk3288_lcdc_clk_enable(lcdc_dev);
2348 rk3288_lcdc_reg_restore(lcdc_dev);
2350 spin_lock(&lcdc_dev->reg_lock);
2351 if (dev_drv->cur_screen->dsp_lut) {
2352 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
2354 lcdc_cfg_done(lcdc_dev);
2356 for (i = 0; i < 256; i++) {
2357 v = dev_drv->cur_screen->dsp_lut[i];
2358 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
2359 b = (v & 0xff) << 2;
2360 g = (v & 0xff00) << 4;
2361 r = (v & 0xff0000) << 6;
2363 for (j = 0; j < 4; j++) {
2364 writel_relaxed(v, c);
2365 v += (1 + (1 << 10) + (1 << 20)) ;
2369 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
2373 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2375 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2377 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2379 lcdc_cfg_done(lcdc_dev);
2381 if (dev_drv->iommu_enabled) {
2382 if (dev_drv->mmu_dev)
2383 rockchip_iovmm_activate(dev_drv->dev);
2386 spin_unlock(&lcdc_dev->reg_lock);
2389 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
2390 dev_drv->trsm_ops->enable();
2395 static int rk3288_lcdc_blank(struct rk_lcdc_driver *dev_drv,
2396 int win_id, int blank_mode)
2398 switch (blank_mode) {
2399 case FB_BLANK_UNBLANK:
2400 rk3288_lcdc_early_resume(dev_drv);
2402 case FB_BLANK_NORMAL:
2403 rk3288_lcdc_early_suspend(dev_drv);
2406 rk3288_lcdc_early_suspend(dev_drv);
2410 dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
2415 static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
2420 /*overlay will be do at regupdate*/
2421 static int rk3288_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
2424 struct lcdc_device *lcdc_dev =
2425 container_of(dev_drv, struct lcdc_device, driver);
2426 struct rk_lcdc_win *win = NULL;
2428 unsigned int mask, val;
2430 int layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2433 win = dev_drv->win[i];
2434 if(win->state == 1){
2439 win = dev_drv->win[i];
2441 win->z_order = z_order_num++;
2442 switch(win->z_order){
2444 layer0_sel = win->id;
2447 layer1_sel = win->id;
2450 layer2_sel = win->id;
2453 layer3_sel = win->id;
2460 layer0_sel = swap %10;;
2461 layer1_sel = swap /10 % 10;
2462 layer2_sel = swap / 100 %10;
2463 layer3_sel = swap / 1000;
2466 spin_lock(&lcdc_dev->reg_lock);
2467 if(lcdc_dev->clk_on){
2469 mask = m_DSP_LAYER0_SEL | m_DSP_LAYER1_SEL |
2470 m_DSP_LAYER2_SEL | m_DSP_LAYER3_SEL;
2471 val = v_DSP_LAYER0_SEL(layer0_sel) |
2472 v_DSP_LAYER1_SEL(layer1_sel) |
2473 v_DSP_LAYER2_SEL(layer2_sel) |
2474 v_DSP_LAYER3_SEL(layer3_sel);
2475 lcdc_msk_reg(lcdc_dev,DSP_CTRL1,mask,val);
2477 layer0_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER0_SEL);
2478 layer1_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER1_SEL);
2479 layer2_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER2_SEL);
2480 layer3_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER3_SEL);
2481 ovl = layer3_sel*1000 + layer2_sel*100 + layer1_sel *10 + layer0_sel;
2486 spin_unlock(&lcdc_dev->reg_lock);
2491 static ssize_t rk3288_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
2492 char *buf, int win_id)
2494 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2498 struct rk_screen *screen = dev_drv->cur_screen;
2499 u16 hsync_len = screen->mode.hsync_len;
2500 u16 left_margin = screen->mode.left_margin;
2501 u16 vsync_len = screen->mode.vsync_len;
2502 u16 upper_margin = screen->mode.upper_margin;
2503 u32 h_pw_bp = hsync_len + left_margin;
2504 u32 v_pw_bp = vsync_len + upper_margin;
2506 char format_w0[9] = "NULL";
2507 char format_w1[9] = "NULL";
2508 char format_w2[9] = "NULL";
2509 char format_w3[9] = "NULL";
2510 u32 win_ctrl,zorder,vir_info,act_info,dsp_info,dsp_st,y_factor,uv_factor;
2511 u8 layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2512 u8 w0_state,w1_state,w2_state,w3_state;
2513 u8 w2_0_state,w2_1_state,w2_2_state,w2_3_state;
2514 u8 w3_0_state,w3_1_state,w3_2_state,w3_3_state;
2516 u32 w0_vir_y,w0_vir_uv,w0_act_x,w0_act_y,w0_dsp_x,w0_dsp_y,w0_st_x=h_pw_bp,w0_st_y=v_pw_bp;
2517 u32 w1_vir_y,w1_vir_uv,w1_act_x,w1_act_y,w1_dsp_x,w1_dsp_y,w1_st_x=h_pw_bp,w1_st_y=v_pw_bp;
2518 u32 w0_y_h_fac,w0_y_v_fac,w0_uv_h_fac,w0_uv_v_fac;
2519 u32 w1_y_h_fac,w1_y_v_fac,w1_uv_h_fac,w1_uv_v_fac;
2521 u32 w2_0_vir_y,w2_1_vir_y,w2_2_vir_y,w2_3_vir_y;
2522 u32 w2_0_dsp_x,w2_1_dsp_x,w2_2_dsp_x,w2_3_dsp_x;
2523 u32 w2_0_dsp_y,w2_1_dsp_y,w2_2_dsp_y,w2_3_dsp_y;
2524 u32 w2_0_st_x=h_pw_bp,w2_1_st_x=h_pw_bp,w2_2_st_x=h_pw_bp,w2_3_st_x=h_pw_bp;
2525 u32 w2_0_st_y=v_pw_bp,w2_1_st_y=v_pw_bp,w2_2_st_y=v_pw_bp,w2_3_st_y=v_pw_bp;
2527 u32 w3_0_vir_y,w3_1_vir_y,w3_2_vir_y,w3_3_vir_y;
2528 u32 w3_0_dsp_x,w3_1_dsp_x,w3_2_dsp_x,w3_3_dsp_x;
2529 u32 w3_0_dsp_y,w3_1_dsp_y,w3_2_dsp_y,w3_3_dsp_y;
2530 u32 w3_0_st_x=h_pw_bp,w3_1_st_x=h_pw_bp,w3_2_st_x=h_pw_bp,w3_3_st_x=h_pw_bp;
2531 u32 w3_0_st_y=v_pw_bp,w3_1_st_y=v_pw_bp,w3_2_st_y=v_pw_bp,w3_3_st_y=v_pw_bp;
2534 dclk_freq = screen->mode.pixclock;
2535 /*rk3288_lcdc_reg_dump(dev_drv);*/
2537 spin_lock(&lcdc_dev->reg_lock);
2538 if (lcdc_dev->clk_on) {
2539 zorder = lcdc_readl(lcdc_dev, DSP_CTRL1);
2540 layer0_sel = (zorder & m_DSP_LAYER0_SEL)>>8;
2541 layer1_sel = (zorder & m_DSP_LAYER1_SEL)>>10;
2542 layer2_sel = (zorder & m_DSP_LAYER2_SEL)>>12;
2543 layer3_sel = (zorder & m_DSP_LAYER3_SEL)>>14;
2545 win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
2546 w0_state = win_ctrl & m_WIN0_EN;
2547 fmt_id = (win_ctrl & m_WIN0_DATA_FMT)>>1;
2550 strcpy(format_w0, "ARGB888");
2553 strcpy(format_w0, "RGB888");
2556 strcpy(format_w0, "RGB565");
2559 strcpy(format_w0, "YCbCr420");
2562 strcpy(format_w0, "YCbCr422");
2565 strcpy(format_w0, "YCbCr444");
2568 strcpy(format_w0, "invalid\n");
2571 vir_info = lcdc_readl(lcdc_dev,WIN0_VIR);
2572 act_info = lcdc_readl(lcdc_dev,WIN0_ACT_INFO);
2573 dsp_info = lcdc_readl(lcdc_dev,WIN0_DSP_INFO);
2574 dsp_st = lcdc_readl(lcdc_dev,WIN0_DSP_ST);
2575 y_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_YRGB);
2576 uv_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_CBR);
2577 w0_vir_y = vir_info & m_WIN0_VIR_STRIDE;
2578 w0_vir_uv = (vir_info & m_WIN0_VIR_STRIDE_UV)>>16;
2579 w0_act_x = (act_info & m_WIN0_ACT_WIDTH)+1;
2580 w0_act_y = ((act_info & m_WIN0_ACT_HEIGHT)>>16)+1;
2581 w0_dsp_x = (dsp_info & m_WIN0_DSP_WIDTH)+1;
2582 w0_dsp_y = ((dsp_info & m_WIN0_DSP_HEIGHT)>>16)+1;
2584 w0_st_x = dsp_st & m_WIN0_DSP_XST;
2585 w0_st_y = (dsp_st & m_WIN0_DSP_YST)>>16;
2587 w0_y_h_fac = y_factor & m_WIN0_HS_FACTOR_YRGB;
2588 w0_y_v_fac = (y_factor & m_WIN0_VS_FACTOR_YRGB)>>16;
2589 w0_uv_h_fac = uv_factor & m_WIN0_HS_FACTOR_CBR;
2590 w0_uv_v_fac = (uv_factor & m_WIN0_VS_FACTOR_CBR)>>16;
2593 win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
2594 w1_state = win_ctrl & m_WIN1_EN;
2595 fmt_id = (win_ctrl & m_WIN1_DATA_FMT)>>1;
2598 strcpy(format_w1, "ARGB888");
2601 strcpy(format_w1, "RGB888");
2604 strcpy(format_w1, "RGB565");
2607 strcpy(format_w1, "YCbCr420");
2610 strcpy(format_w1, "YCbCr422");
2613 strcpy(format_w1, "YCbCr444");
2616 strcpy(format_w1, "invalid\n");
2619 vir_info = lcdc_readl(lcdc_dev,WIN1_VIR);
2620 act_info = lcdc_readl(lcdc_dev,WIN1_ACT_INFO);
2621 dsp_info = lcdc_readl(lcdc_dev,WIN1_DSP_INFO);
2622 dsp_st = lcdc_readl(lcdc_dev,WIN1_DSP_ST);
2623 y_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_YRGB);
2624 uv_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_CBR);
2625 w1_vir_y = vir_info & m_WIN1_VIR_STRIDE;
2626 w1_vir_uv = (vir_info & m_WIN1_VIR_STRIDE_UV)>>16;
2627 w1_act_x = (act_info & m_WIN1_ACT_WIDTH)+1;
2628 w1_act_y = ((act_info & m_WIN1_ACT_HEIGHT)>>16)+1;
2629 w1_dsp_x = (dsp_info & m_WIN1_DSP_WIDTH)+1;
2630 w1_dsp_y =((dsp_info & m_WIN1_DSP_HEIGHT)>>16)+1;
2632 w1_st_x = dsp_st & m_WIN1_DSP_XST;
2633 w1_st_y = (dsp_st & m_WIN1_DSP_YST)>>16;
2635 w1_y_h_fac = y_factor & m_WIN1_HS_FACTOR_YRGB;
2636 w1_y_v_fac = (y_factor & m_WIN1_VS_FACTOR_YRGB)>>16;
2637 w1_uv_h_fac = uv_factor & m_WIN1_HS_FACTOR_CBR;
2638 w1_uv_v_fac = (uv_factor & m_WIN1_VS_FACTOR_CBR)>>16;
2640 win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
2641 w2_state = win_ctrl & m_WIN2_EN;
2642 w2_0_state = (win_ctrl & m_WIN2_MST0_EN)>>4;
2643 w2_1_state = (win_ctrl & m_WIN2_MST1_EN)>>5;
2644 w2_2_state = (win_ctrl & m_WIN2_MST2_EN)>>6;
2645 w2_3_state = (win_ctrl & m_WIN2_MST3_EN)>>7;
2646 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR0_1);
2647 w2_0_vir_y = vir_info & m_WIN2_VIR_STRIDE0;
2648 w2_1_vir_y = (vir_info & m_WIN2_VIR_STRIDE1)>>16;
2649 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR2_3);
2650 w2_2_vir_y = vir_info & m_WIN2_VIR_STRIDE2;
2651 w2_3_vir_y = (vir_info & m_WIN2_VIR_STRIDE3)>>16;
2652 fmt_id = (win_ctrl & m_WIN2_DATA_FMT)>>1;
2655 strcpy(format_w2, "ARGB888");
2658 strcpy(format_w2, "RGB888");
2661 strcpy(format_w2, "RGB565");
2664 strcpy(format_w2,"8bpp");
2667 strcpy(format_w2,"4bpp");
2670 strcpy(format_w2,"2bpp");
2673 strcpy(format_w2,"1bpp");
2676 strcpy(format_w2, "invalid\n");
2679 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO0);
2680 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST0);
2681 w2_0_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH0)+1;
2682 w2_0_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT0)>>16)+1;
2684 w2_0_st_x = dsp_st & m_WIN2_DSP_XST0;
2685 w2_0_st_y = (dsp_st & m_WIN2_DSP_YST0)>>16;
2687 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO1);
2688 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST1);
2689 w2_1_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH1)+1;
2690 w2_1_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT1)>>16)+1;
2692 w2_1_st_x = dsp_st & m_WIN2_DSP_XST1;
2693 w2_1_st_y = (dsp_st & m_WIN2_DSP_YST1)>>16;
2695 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO2);
2696 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST2);
2697 w2_2_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH2)+1;
2698 w2_2_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT2)>>16)+1;
2700 w2_2_st_x = dsp_st & m_WIN2_DSP_XST2;
2701 w2_2_st_y = (dsp_st & m_WIN2_DSP_YST2)>>16;
2703 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO3);
2704 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST3);
2705 w2_3_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH3)+1;
2706 w2_3_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT3)>>16)+1;
2708 w2_3_st_x = dsp_st & m_WIN2_DSP_XST3;
2709 w2_3_st_y = (dsp_st & m_WIN2_DSP_YST3)>>16;
2713 win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
2714 w3_state = win_ctrl & m_WIN3_EN;
2715 w3_0_state = (win_ctrl & m_WIN3_MST0_EN)>>4;
2716 w3_1_state = (win_ctrl & m_WIN3_MST1_EN)>>5;
2717 w3_2_state = (win_ctrl & m_WIN3_MST2_EN)>>6;
2718 w3_3_state = (win_ctrl & m_WIN3_MST3_EN)>>7;
2719 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR0_1);
2720 w3_0_vir_y = vir_info & m_WIN3_VIR_STRIDE0;
2721 w3_1_vir_y = (vir_info & m_WIN3_VIR_STRIDE1)>>16;
2722 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR2_3);
2723 w3_2_vir_y = vir_info & m_WIN3_VIR_STRIDE2;
2724 w3_3_vir_y = (vir_info & m_WIN3_VIR_STRIDE3)>>16;
2725 fmt_id = (win_ctrl & m_WIN3_DATA_FMT)>>1;
2728 strcpy(format_w3, "ARGB888");
2731 strcpy(format_w3, "RGB888");
2734 strcpy(format_w3, "RGB565");
2737 strcpy(format_w3,"8bpp");
2740 strcpy(format_w3,"4bpp");
2743 strcpy(format_w3,"2bpp");
2746 strcpy(format_w3,"1bpp");
2749 strcpy(format_w3, "invalid");
2752 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO0);
2753 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST0);
2754 w3_0_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH0)+1;
2755 w3_0_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT0)>>16)+1;
2757 w3_0_st_x = dsp_st & m_WIN3_DSP_XST0;
2758 w3_0_st_y = (dsp_st & m_WIN3_DSP_YST0)>>16;
2761 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO1);
2762 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST1);
2763 w3_1_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH1)+1;
2764 w3_1_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT1)>>16)+1;
2766 w3_1_st_x = dsp_st & m_WIN3_DSP_XST1;
2767 w3_1_st_y = (dsp_st & m_WIN3_DSP_YST1)>>16;
2770 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO2);
2771 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST2);
2772 w3_2_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH2)+1;
2773 w3_2_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT2)>>16)+1;
2775 w3_2_st_x = dsp_st & m_WIN3_DSP_XST2;
2776 w3_2_st_y = (dsp_st & m_WIN3_DSP_YST2)>>16;
2779 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO3);
2780 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST3);
2781 w3_3_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH3)+1;
2782 w3_3_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT3)>>16)+1;
2784 w3_3_st_x = dsp_st & m_WIN3_DSP_XST3;
2785 w3_3_st_y = (dsp_st & m_WIN3_DSP_YST3)>>16;
2789 spin_unlock(&lcdc_dev->reg_lock);
2792 spin_unlock(&lcdc_dev->reg_lock);
2793 return snprintf(buf, PAGE_SIZE,
2795 " layer3_sel_win[%d]\n"
2796 " layer2_sel_win[%d]\n"
2797 " layer1_sel_win[%d]\n"
2798 " layer0_sel_win[%d]\n"
2903 layer3_sel,layer2_sel,layer1_sel,layer0_sel,
2904 w0_state,format_w0,w0_vir_y,w0_vir_uv,w0_act_x,w0_act_y,
2905 w0_dsp_x,w0_dsp_y,w0_st_x-h_pw_bp,w0_st_y-v_pw_bp,w0_y_h_fac,w0_y_v_fac,w0_uv_h_fac,
2906 w0_uv_v_fac,lcdc_readl(lcdc_dev, WIN0_YRGB_MST),
2907 lcdc_readl(lcdc_dev, WIN0_CBR_MST),
2909 w1_state,format_w1,w1_vir_y,w1_vir_uv,w1_act_x,w1_act_y,
2910 w1_dsp_x,w1_dsp_y,w1_st_x-h_pw_bp,w1_st_y-v_pw_bp,w1_y_h_fac,w1_y_v_fac,w1_uv_h_fac,
2911 w1_uv_v_fac,lcdc_readl(lcdc_dev, WIN1_YRGB_MST),
2912 lcdc_readl(lcdc_dev, WIN1_CBR_MST),
2915 w2_0_state,w2_0_vir_y,w2_0_dsp_x,w2_0_dsp_y,
2916 w2_0_st_x-h_pw_bp,w2_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST0),
2918 w2_1_state,w2_1_vir_y,w2_1_dsp_x,w2_1_dsp_y,
2919 w2_1_st_x-h_pw_bp,w2_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST1),
2921 w2_2_state,w2_2_vir_y,w2_2_dsp_x,w2_2_dsp_y,
2922 w2_2_st_x-h_pw_bp,w2_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST2),
2924 w2_3_state,w2_3_vir_y,w2_3_dsp_x,w2_3_dsp_y,
2925 w2_3_st_x-h_pw_bp,w2_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST3),
2928 w3_0_state,w3_0_vir_y,w3_0_dsp_x,w3_0_dsp_y,
2929 w3_0_st_x-h_pw_bp,w3_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST0),
2931 w3_1_state,w3_1_vir_y,w3_1_dsp_x,w3_1_dsp_y,
2932 w3_1_st_x-h_pw_bp,w3_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST1),
2934 w3_2_state,w3_2_vir_y,w3_2_dsp_x,w3_2_dsp_y,
2935 w3_2_st_x-h_pw_bp,w3_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST2),
2937 w3_3_state,w3_3_vir_y,w3_3_dsp_x,w3_3_dsp_y,
2938 w3_3_st_x-h_pw_bp,w3_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST3)
2943 static int rk3288_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
2946 struct lcdc_device *lcdc_dev =
2947 container_of(dev_drv, struct lcdc_device, driver);
2948 struct rk_screen *screen = dev_drv->cur_screen;
2953 u32 x_total, y_total;
2955 ft = div_u64(1000000000000llu, fps);
2957 screen->mode.upper_margin + screen->mode.lower_margin +
2958 screen->mode.yres + screen->mode.vsync_len;
2960 screen->mode.left_margin + screen->mode.right_margin +
2961 screen->mode.xres + screen->mode.hsync_len;
2962 dev_drv->pixclock = div_u64(ft, x_total * y_total);
2963 dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
2964 ret = clk_set_rate(lcdc_dev->dclk, dotclk);
2967 pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
2968 dev_drv->pixclock = lcdc_dev->pixclock = pixclock;
2969 fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
2970 screen->ft = 1000 / fps; /*one frame time in ms */
2973 dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
2974 clk_get_rate(lcdc_dev->dclk), fps);
2979 static int rk3288_fb_win_remap(struct rk_lcdc_driver *dev_drv, u16 order)
2981 mutex_lock(&dev_drv->fb_win_id_mutex);
2982 if (order == FB_DEFAULT_ORDER)
2983 order = FB0_WIN0_FB1_WIN1_FB2_WIN2_FB3_WIN3;
2984 dev_drv->fb3_win_id = order / 1000;
2985 dev_drv->fb2_win_id = (order / 100) % 10;
2986 dev_drv->fb1_win_id = (order / 10) % 10;
2987 dev_drv->fb0_win_id = order % 10;
2988 mutex_unlock(&dev_drv->fb_win_id_mutex);
2993 static int rk3288_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
2997 mutex_lock(&dev_drv->fb_win_id_mutex);
2998 if (!strcmp(id, "fb0") || !strcmp(id, "fb4"))
2999 win_id = dev_drv->fb0_win_id;
3000 else if (!strcmp(id, "fb1") || !strcmp(id, "fb5"))
3001 win_id = dev_drv->fb1_win_id;
3002 else if (!strcmp(id, "fb2") || !strcmp(id, "fb6"))
3003 win_id = dev_drv->fb2_win_id;
3004 else if (!strcmp(id, "fb3") || !strcmp(id, "fb7"))
3005 win_id = dev_drv->fb3_win_id;
3006 mutex_unlock(&dev_drv->fb_win_id_mutex);
3011 static int rk3288_set_dsp_lut(struct rk_lcdc_driver *dev_drv, int *lut)
3018 struct lcdc_device *lcdc_dev =
3019 container_of(dev_drv, struct lcdc_device, driver);
3020 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
3021 lcdc_cfg_done(lcdc_dev);
3023 if (dev_drv->cur_screen->dsp_lut) {
3024 for (i = 0; i < 256; i++) {
3025 v = dev_drv->cur_screen->dsp_lut[i] = lut[i];
3026 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
3027 b = (v & 0xff) << 2;
3028 g = (v & 0xff00) << 4;
3029 r = (v & 0xff0000) << 6;
3031 for (j = 0; j < 4; j++) {
3032 writel_relaxed(v, c);
3033 v += (1 + (1 << 10) + (1 << 20)) ;
3038 dev_err(dev_drv->dev, "no buffer to backup lut data!\n");
3043 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
3044 lcdc_cfg_done(lcdc_dev);
3045 }while(!lcdc_read_bit(lcdc_dev,DSP_CTRL1,m_DSP_LUT_EN));
3049 static int rk3288_lcdc_config_done(struct rk_lcdc_driver *dev_drv)
3051 struct lcdc_device *lcdc_dev =
3052 container_of(dev_drv, struct lcdc_device, driver);
3054 unsigned int mask, val;
3055 struct rk_lcdc_win *win = NULL;
3056 spin_lock(&lcdc_dev->reg_lock);
3057 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
3058 v_STANDBY_EN(lcdc_dev->standby));
3060 win = dev_drv->win[i];
3061 if ((win->state == 0)&&(win->last_state == 1)) {
3064 lcdc_writel(lcdc_dev,WIN0_CTRL1,0x0);
3067 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask,val);
3070 lcdc_writel(lcdc_dev,WIN1_CTRL1,0x0);
3073 lcdc_msk_reg(lcdc_dev, WIN1_CTRL0, mask,val);
3076 mask = m_WIN2_EN | m_WIN2_MST0_EN | m_WIN2_MST1_EN |
3077 m_WIN2_MST2_EN | m_WIN2_MST3_EN;
3078 val = v_WIN2_EN(0) | v_WIN2_MST0_EN(0) | v_WIN2_MST1_EN(0) |
3079 v_WIN2_MST2_EN(0) | v_WIN2_MST3_EN(0);
3080 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0, mask,val);
3083 mask = m_WIN3_EN | m_WIN3_MST0_EN | m_WIN3_MST1_EN |
3084 m_WIN3_MST2_EN | m_WIN3_MST3_EN;
3085 val = v_WIN3_EN(0) | v_WIN3_MST0_EN(0) | v_WIN3_MST1_EN(0) |
3086 v_WIN3_MST2_EN(0) | v_WIN3_MST3_EN(0);
3087 lcdc_msk_reg(lcdc_dev, WIN3_CTRL0, mask,val);
3093 win->last_state = win->state;
3095 lcdc_cfg_done(lcdc_dev);
3096 spin_unlock(&lcdc_dev->reg_lock);
3101 static int rk3288_lcdc_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
3103 struct lcdc_device *lcdc_dev =
3104 container_of(dev_drv, struct lcdc_device, driver);
3105 spin_lock(&lcdc_dev->reg_lock);
3106 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN,
3107 v_DIRECT_PATH_EN(open));
3108 lcdc_cfg_done(lcdc_dev);
3109 spin_unlock(&lcdc_dev->reg_lock);
3113 static int rk3288_lcdc_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id)
3115 struct lcdc_device *lcdc_dev = container_of(dev_drv,
3116 struct lcdc_device, driver);
3117 spin_lock(&lcdc_dev->reg_lock);
3118 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATCH_SEL,
3119 v_DIRECT_PATCH_SEL(win_id));
3120 lcdc_cfg_done(lcdc_dev);
3121 spin_unlock(&lcdc_dev->reg_lock);
3126 static int rk3288_lcdc_dpi_status(struct rk_lcdc_driver *dev_drv)
3128 struct lcdc_device *lcdc_dev =
3129 container_of(dev_drv, struct lcdc_device, driver);
3131 spin_lock(&lcdc_dev->reg_lock);
3132 ovl = lcdc_read_bit(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN);
3133 spin_unlock(&lcdc_dev->reg_lock);
3136 static int rk3288_lcdc_set_irq_to_cpu(struct rk_lcdc_driver * dev_drv,int enable)
3138 struct lcdc_device *lcdc_dev =
3139 container_of(dev_drv,struct lcdc_device,driver);
3141 enable_irq(lcdc_dev->irq);
3143 disable_irq(lcdc_dev->irq);
3147 int rk3288_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
3149 struct lcdc_device *lcdc_dev =
3150 container_of(dev_drv, struct lcdc_device, driver);
3154 if (lcdc_dev->clk_on &&(!dev_drv->suspend_flag)){
3155 int_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3156 if (int_reg & m_LINE_FLAG_INTR_STS) {
3157 lcdc_dev->driver.frame_time.last_framedone_t =
3158 lcdc_dev->driver.frame_time.framedone_t;
3159 lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
3160 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3161 v_LINE_FLAG_INTR_CLR(1));
3162 ret = RK_LF_STATUS_FC;
3164 ret = RK_LF_STATUS_FR;
3166 ret = RK_LF_STATUS_NC;
3171 static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr)
3173 struct lcdc_device *lcdc_dev =
3174 container_of(dev_drv, struct lcdc_device, driver);
3175 spin_lock(&lcdc_dev->reg_lock);
3176 if(lcdc_dev->clk_on){
3177 dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
3178 dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
3179 dsp_addr[2] = lcdc_readl(lcdc_dev, WIN2_MST0);
3180 dsp_addr[3] = lcdc_readl(lcdc_dev, WIN3_MST0);
3182 spin_unlock(&lcdc_dev->reg_lock);
3186 static struct lcdc_cabc_mode cabc_mode[4] = {
3187 /* pixel_num, stage_up, stage_down */
3188 {5, 128, 0}, /*mode 1*/
3189 {10, 128, 0}, /*mode 2*/
3190 {15, 128, 0}, /*mode 3*/
3191 {20, 128, 0}, /*mode 4*/
3194 static int rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode)
3196 struct lcdc_device *lcdc_dev =
3197 container_of(dev_drv, struct lcdc_device, driver);
3198 struct rk_screen *screen = dev_drv->cur_screen;
3199 u32 total_pixel, calc_pixel, stage_up, stage_down, pixel_num;
3200 u32 mask = 0, val = 0, cabc_en = 0;
3201 u32 max_mode_num = sizeof(cabc_mode) / sizeof(struct lcdc_cabc_mode);
3203 dev_drv->cabc_mode = mode;
3205 /* iomux connect to vop or pwm */
3207 DBG(3, "close cabc and select rk pwm\n");
3209 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3211 } else if (mode > 0 && mode <= max_mode_num) {
3212 DBG(3, "open cabc and select vop pwm\n");
3213 val = (dev_drv->id == 0) ? 0x30002 : 0x30003;
3214 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3216 } else if (mode > 0x10 && mode <= (max_mode_num + 0x10)) {
3217 DBG(3, "open cabc and select rk pwm\n");
3219 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3222 } else if (mode == 0xff) {
3223 DBG(3, "close cabc and select vop pwm\n");
3224 val = (dev_drv->id == 0) ? 0x30002 : 0x30003;
3225 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3228 dev_err(lcdc_dev->dev, "invalid cabc mode value:%d", mode);
3233 spin_lock(&lcdc_dev->reg_lock);
3234 if(lcdc_dev->clk_on) {
3235 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, m_CABC_EN, v_CABC_EN(0));
3236 lcdc_cfg_done(lcdc_dev);
3238 spin_unlock(&lcdc_dev->reg_lock);
3242 total_pixel = screen->mode.xres * screen->mode.yres;
3243 pixel_num = 1000 - (cabc_mode[mode - 1].pixel_num);
3244 calc_pixel = (total_pixel * pixel_num) / 1000;
3245 stage_up = cabc_mode[mode - 1].stage_up;
3246 stage_down = cabc_mode[mode - 1].stage_down;
3248 spin_lock(&lcdc_dev->reg_lock);
3249 if(lcdc_dev->clk_on) {
3250 mask = m_CABC_TOTAL_NUM | m_CABC_STAGE_DOWN;
3251 val = v_CABC_TOTAL_NUM(total_pixel) | v_CABC_STAGE_DOWN(stage_down);
3252 lcdc_msk_reg(lcdc_dev, CABC_CTRL1, mask, val);
3254 mask = m_CABC_EN | m_CABC_CALC_PIXEL_NUM |
3256 val = v_CABC_EN(1) | v_CABC_CALC_PIXEL_NUM(calc_pixel) |
3257 v_CABC_STAGE_UP(stage_up);
3258 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
3259 lcdc_cfg_done(lcdc_dev);
3261 spin_unlock(&lcdc_dev->reg_lock);
3267 sin_hue = sin(a)*256 +0x100;
3268 cos_hue = cos(a)*256;
3270 sin_hue = sin(a)*256;
3271 cos_hue = cos(a)*256;
3273 static int rk3288_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode)
3276 struct lcdc_device *lcdc_dev =
3277 container_of(dev_drv, struct lcdc_device, driver);
3280 spin_lock(&lcdc_dev->reg_lock);
3281 if (lcdc_dev->clk_on) {
3282 val = lcdc_readl(lcdc_dev, BCSH_H);
3285 val &= m_BCSH_SIN_HUE;
3288 val &= m_BCSH_COS_HUE;
3295 spin_unlock(&lcdc_dev->reg_lock);
3301 static int rk3288_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue)
3304 struct lcdc_device *lcdc_dev =
3305 container_of(dev_drv, struct lcdc_device, driver);
3308 spin_lock(&lcdc_dev->reg_lock);
3309 if (lcdc_dev->clk_on) {
3310 mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
3311 val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
3312 lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
3313 lcdc_cfg_done(lcdc_dev);
3315 spin_unlock(&lcdc_dev->reg_lock);
3320 static int rk3288_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value)
3322 struct lcdc_device *lcdc_dev =
3323 container_of(dev_drv, struct lcdc_device, driver);
3326 spin_lock(&lcdc_dev->reg_lock);
3327 if(lcdc_dev->clk_on) {
3330 /*from 0 to 255,typical is 128*/
3333 else if (value >= 0x80)
3334 value = value - 0x80;
3335 mask = m_BCSH_BRIGHTNESS;
3336 val = v_BCSH_BRIGHTNESS(value);
3339 /*from 0 to 510,typical is 256*/
3340 mask = m_BCSH_CONTRAST;
3341 val = v_BCSH_CONTRAST(value);
3344 /*from 0 to 1015,typical is 256*/
3345 mask = m_BCSH_SAT_CON;
3346 val = v_BCSH_SAT_CON(value);
3351 lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
3352 lcdc_cfg_done(lcdc_dev);
3354 spin_unlock(&lcdc_dev->reg_lock);
3358 static int rk3288_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode)
3360 struct lcdc_device *lcdc_dev =
3361 container_of(dev_drv, struct lcdc_device, driver);
3364 spin_lock(&lcdc_dev->reg_lock);
3365 if(lcdc_dev->clk_on) {
3366 val = lcdc_readl(lcdc_dev, BCSH_BCS);
3369 val &= m_BCSH_BRIGHTNESS;
3376 val &= m_BCSH_CONTRAST;
3380 val &= m_BCSH_SAT_CON;
3387 spin_unlock(&lcdc_dev->reg_lock);
3392 static int rk3288_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
3394 struct lcdc_device *lcdc_dev =
3395 container_of(dev_drv, struct lcdc_device, driver);
3398 spin_lock(&lcdc_dev->reg_lock);
3399 if (lcdc_dev->clk_on) {
3401 lcdc_writel(lcdc_dev,BCSH_COLOR_BAR,0x1);
3402 lcdc_writel(lcdc_dev,BCSH_BCS,0xd0010000);
3403 lcdc_writel(lcdc_dev,BCSH_H,0x01000000);
3407 lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
3409 lcdc_cfg_done(lcdc_dev);
3411 spin_unlock(&lcdc_dev->reg_lock);
3415 static int rk3288_lcdc_set_bcsh(struct rk_lcdc_driver *dev_drv,
3418 if (!enable || !dev_drv->bcsh.enable) {
3419 rk3288_lcdc_open_bcsh(dev_drv, false);
3423 if (dev_drv->bcsh.brightness <= 255 ||
3424 dev_drv->bcsh.contrast <= 510 ||
3425 dev_drv->bcsh.sat_con <= 1015 ||
3426 (dev_drv->bcsh.sin_hue <= 511 && dev_drv->bcsh.cos_hue <= 511)) {
3427 rk3288_lcdc_open_bcsh(dev_drv, true);
3428 if (dev_drv->bcsh.brightness <= 255)
3429 rk3288_lcdc_set_bcsh_bcs(dev_drv, BRIGHTNESS,
3430 dev_drv->bcsh.brightness);
3431 if (dev_drv->bcsh.contrast <= 510)
3432 rk3288_lcdc_set_bcsh_bcs(dev_drv, CONTRAST,
3433 dev_drv->bcsh.contrast);
3434 if (dev_drv->bcsh.sat_con <= 1015)
3435 rk3288_lcdc_set_bcsh_bcs(dev_drv, SAT_CON,
3436 dev_drv->bcsh.sat_con);
3437 if (dev_drv->bcsh.sin_hue <= 511 &&
3438 dev_drv->bcsh.cos_hue <= 511)
3439 rk3288_lcdc_set_bcsh_hue(dev_drv,
3440 dev_drv->bcsh.sin_hue,
3441 dev_drv->bcsh.cos_hue);
3446 static struct rk_lcdc_win lcdc_win[] = {
3450 .support_3d = false,
3455 .support_3d = false,
3460 .support_3d = false,
3465 .support_3d = false,
3469 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
3470 .open = rk3288_lcdc_open,
3471 .win_direct_en = rk3288_lcdc_win_direct_en,
3472 .load_screen = rk3288_load_screen,
3473 .set_par = rk3288_lcdc_set_par,
3474 .pan_display = rk3288_lcdc_pan_display,
3475 .direct_set_addr = rk3288_lcdc_direct_set_win_addr,
3476 .lcdc_reg_update = rk3288_lcdc_reg_update,
3477 .blank = rk3288_lcdc_blank,
3478 .ioctl = rk3288_lcdc_ioctl,
3479 .suspend = rk3288_lcdc_early_suspend,
3480 .resume = rk3288_lcdc_early_resume,
3481 .get_win_state = rk3288_lcdc_get_win_state,
3482 .ovl_mgr = rk3288_lcdc_ovl_mgr,
3483 .get_disp_info = rk3288_lcdc_get_disp_info,
3484 .fps_mgr = rk3288_lcdc_fps_mgr,
3485 .fb_get_win_id = rk3288_lcdc_get_win_id,
3486 .fb_win_remap = rk3288_fb_win_remap,
3487 .set_dsp_lut = rk3288_set_dsp_lut,
3488 .poll_vblank = rk3288_lcdc_poll_vblank,
3489 .dpi_open = rk3288_lcdc_dpi_open,
3490 .dpi_win_sel = rk3288_lcdc_dpi_win_sel,
3491 .dpi_status = rk3288_lcdc_dpi_status,
3492 .get_dsp_addr = rk3288_lcdc_get_dsp_addr,
3493 .set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
3494 .set_dsp_bcsh_hue = rk3288_lcdc_set_bcsh_hue,
3495 .set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
3496 .get_dsp_bcsh_hue = rk3288_lcdc_get_bcsh_hue,
3497 .get_dsp_bcsh_bcs = rk3288_lcdc_get_bcsh_bcs,
3498 .open_bcsh = rk3288_lcdc_open_bcsh,
3499 .dump_reg = rk3288_lcdc_reg_dump,
3500 .cfg_done = rk3288_lcdc_config_done,
3501 .set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,
3504 #ifdef LCDC_IRQ_DEBUG
3505 static int rk3288_lcdc_parse_irq(struct lcdc_device *lcdc_dev,unsigned int reg_val)
3507 if (reg_val & m_WIN0_EMPTY_INTR_STS) {
3508 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN0_EMPTY_INTR_CLR,
3509 v_WIN0_EMPTY_INTR_CLR(1));
3510 dev_warn(lcdc_dev->dev,"win0 empty irq!");
3511 }else if (reg_val & m_WIN1_EMPTY_INTR_STS) {
3512 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN1_EMPTY_INTR_CLR,
3513 v_WIN1_EMPTY_INTR_CLR(1));
3514 dev_warn(lcdc_dev->dev,"win1 empty irq!");
3515 }else if (reg_val & m_WIN2_EMPTY_INTR_STS) {
3516 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN2_EMPTY_INTR_CLR,
3517 v_WIN2_EMPTY_INTR_CLR(1));
3518 dev_warn(lcdc_dev->dev,"win2 empty irq!");
3519 }else if (reg_val & m_WIN3_EMPTY_INTR_STS) {
3520 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN3_EMPTY_INTR_CLR,
3521 v_WIN3_EMPTY_INTR_CLR(1));
3522 dev_warn(lcdc_dev->dev,"win3 empty irq!");
3523 }else if (reg_val & m_HWC_EMPTY_INTR_STS) {
3524 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_HWC_EMPTY_INTR_CLR,
3525 v_HWC_EMPTY_INTR_CLR(1));
3526 dev_warn(lcdc_dev->dev,"HWC empty irq!");
3527 }else if (reg_val & m_POST_BUF_EMPTY_INTR_STS) {
3528 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_POST_BUF_EMPTY_INTR_CLR,
3529 v_POST_BUF_EMPTY_INTR_CLR(1));
3530 dev_warn(lcdc_dev->dev,"post buf empty irq!");
3531 }else if (reg_val & m_PWM_GEN_INTR_STS) {
3532 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_PWM_GEN_INTR_CLR,
3533 v_PWM_GEN_INTR_CLR(1));
3534 dev_warn(lcdc_dev->dev,"PWM gen irq!");
3541 static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
3543 struct lcdc_device *lcdc_dev =
3544 (struct lcdc_device *)dev_id;
3545 ktime_t timestamp = ktime_get();
3548 intr0_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3550 if(intr0_reg & m_FS_INTR_STS){
3551 timestamp = ktime_get();
3552 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR,
3554 /*if(lcdc_dev->driver.wait_fs){ */
3556 spin_lock(&(lcdc_dev->driver.cpl_lock));
3557 complete(&(lcdc_dev->driver.frame_done));
3558 spin_unlock(&(lcdc_dev->driver.cpl_lock));
3560 #ifdef CONFIG_DRM_ROCKCHIP
3561 lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
3563 lcdc_dev->driver.vsync_info.timestamp = timestamp;
3564 wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
3566 }else if(intr0_reg & m_LINE_FLAG_INTR_STS){
3567 lcdc_dev->driver.frame_time.last_framedone_t =
3568 lcdc_dev->driver.frame_time.framedone_t;
3569 lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
3570 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3571 v_LINE_FLAG_INTR_CLR(1));
3572 }else if(intr0_reg & m_BUS_ERROR_INTR_STS){
3573 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_BUS_ERROR_INTR_CLR,
3574 v_BUS_ERROR_INTR_CLR(1));
3575 dev_warn(lcdc_dev->dev,"buf_error_int!");
3578 /* for win empty debug */
3579 #ifdef LCDC_IRQ_EMPTY_DEBUG
3580 intr1_reg = lcdc_readl(lcdc_dev, INTR_CTRL1);
3581 if (intr1_reg != 0) {
3582 rk3288_lcdc_parse_irq(lcdc_dev,intr1_reg);
3588 #if defined(CONFIG_PM)
3589 static int rk3288_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
3594 static int rk3288_lcdc_resume(struct platform_device *pdev)
3599 #define rk3288_lcdc_suspend NULL
3600 #define rk3288_lcdc_resume NULL
3603 static int rk3288_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
3605 struct device_node *np = lcdc_dev->dev->of_node;
3606 struct rk_lcdc_driver *dev_drv = &lcdc_dev->driver;
3609 if (of_property_read_u32(np, "rockchip,prop", &val))
3610 lcdc_dev->prop = PRMRY; /*default set it as primary */
3612 lcdc_dev->prop = val;
3614 if (of_property_read_u32(np, "rockchip,mirror", &val))
3615 dev_drv->rotate_mode = NO_MIRROR;
3617 dev_drv->rotate_mode = val;
3619 if (of_property_read_u32(np, "rockchip,cabc_mode", &val))
3620 dev_drv->cabc_mode = 0; /* default set close cabc */
3622 dev_drv->cabc_mode = val;
3624 if (of_property_read_u32(np, "rockchip,pwr18", &val))
3625 lcdc_dev->pwr18 = false; /*default set it as 3.xv power supply */
3627 lcdc_dev->pwr18 = (val ? true : false);
3629 if (of_property_read_u32(np, "rockchip,fb-win-map", &val))
3630 dev_drv->fb_win_map = FB_DEFAULT_ORDER;
3632 dev_drv->fb_win_map = val;
3634 if (of_property_read_u32(np, "rockchip,bcsh-en", &val))
3635 dev_drv->bcsh.enable = false;
3637 dev_drv->bcsh.enable = (val ? true : false);
3639 if (of_property_read_u32(np, "rockchip,brightness", &val))
3640 dev_drv->bcsh.brightness = 0xffff;
3642 dev_drv->bcsh.brightness = val;
3644 if (of_property_read_u32(np, "rockchip,contrast", &val))
3645 dev_drv->bcsh.contrast = 0xffff;
3647 dev_drv->bcsh.contrast = val;
3649 if (of_property_read_u32(np, "rockchip,sat-con", &val))
3650 dev_drv->bcsh.sat_con = 0xffff;
3652 dev_drv->bcsh.sat_con = val;
3654 if (of_property_read_u32(np, "rockchip,hue", &val)) {
3655 dev_drv->bcsh.sin_hue = 0xffff;
3656 dev_drv->bcsh.cos_hue = 0xffff;
3658 dev_drv->bcsh.sin_hue = val & 0xff;
3659 dev_drv->bcsh.cos_hue = (val >> 8) & 0xff;
3662 #if defined(CONFIG_ROCKCHIP_IOMMU)
3663 if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
3664 dev_drv->iommu_enabled = 0;
3666 dev_drv->iommu_enabled = val;
3668 dev_drv->iommu_enabled = 0;
3673 static int rk3288_lcdc_probe(struct platform_device *pdev)
3675 struct lcdc_device *lcdc_dev = NULL;
3676 struct rk_lcdc_driver *dev_drv;
3677 struct device *dev = &pdev->dev;
3678 struct resource *res;
3679 struct device_node *np = pdev->dev.of_node;
3683 /*if the primary lcdc has not registered ,the extend
3684 lcdc register later */
3685 of_property_read_u32(np, "rockchip,prop", &prop);
3686 if (prop == EXTEND) {
3687 if (!is_prmry_rk_lcdc_registered())
3688 return -EPROBE_DEFER;
3690 lcdc_dev = devm_kzalloc(dev,
3691 sizeof(struct lcdc_device), GFP_KERNEL);
3693 dev_err(&pdev->dev, "rk3288 lcdc device kmalloc fail!");
3696 platform_set_drvdata(pdev, lcdc_dev);
3697 lcdc_dev->dev = dev;
3698 rk3288_lcdc_parse_dt(lcdc_dev);
3699 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3700 lcdc_dev->reg_phy_base = res->start;
3701 lcdc_dev->len = resource_size(res);
3702 lcdc_dev->regs = devm_ioremap_resource(dev, res);
3703 if (IS_ERR(lcdc_dev->regs))
3704 return PTR_ERR(lcdc_dev->regs);
3706 lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
3707 if (IS_ERR(lcdc_dev->regsbak))
3708 return PTR_ERR(lcdc_dev->regsbak);
3709 lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs + GAMMA_LUT_ADDR);
3710 lcdc_dev->id = rk3288_lcdc_get_id(lcdc_dev->reg_phy_base);
3711 if (lcdc_dev->id < 0) {
3712 dev_err(&pdev->dev, "no such lcdc device!\n");
3715 dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
3716 dev_drv = &lcdc_dev->driver;
3718 dev_drv->prop = prop;
3719 dev_drv->id = lcdc_dev->id;
3720 dev_drv->ops = &lcdc_drv_ops;
3721 dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
3722 spin_lock_init(&lcdc_dev->reg_lock);
3724 lcdc_dev->irq = platform_get_irq(pdev, 0);
3725 if (lcdc_dev->irq < 0) {
3726 dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
3731 ret = devm_request_irq(dev, lcdc_dev->irq, rk3288_lcdc_isr,
3732 IRQF_DISABLED | IRQF_SHARED, dev_name(dev), lcdc_dev);
3734 dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
3735 lcdc_dev->irq, ret);
3739 if (dev_drv->iommu_enabled) {
3740 if(lcdc_dev->id == 0){
3741 strcpy(dev_drv->mmu_dts_name, VOPB_IOMMU_COMPATIBLE_NAME);
3743 strcpy(dev_drv->mmu_dts_name, VOPL_IOMMU_COMPATIBLE_NAME);
3747 ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
3749 dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
3752 lcdc_dev->screen = dev_drv->screen0;
3753 dev_info(dev, "lcdc%d probe ok, iommu %s\n",
3754 lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
3759 static int rk3288_lcdc_remove(struct platform_device *pdev)
3765 static void rk3288_lcdc_shutdown(struct platform_device *pdev)
3767 struct lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
3769 rk3288_lcdc_deint(lcdc_dev);
3770 rk_disp_pwr_disable(&lcdc_dev->driver);
3773 #if defined(CONFIG_OF)
3774 static const struct of_device_id rk3288_lcdc_dt_ids[] = {
3775 {.compatible = "rockchip,rk3288-lcdc",},
3780 static struct platform_driver rk3288_lcdc_driver = {
3781 .probe = rk3288_lcdc_probe,
3782 .remove = rk3288_lcdc_remove,
3784 .name = "rk3288-lcdc",
3785 .owner = THIS_MODULE,
3786 .of_match_table = of_match_ptr(rk3288_lcdc_dt_ids),
3788 .suspend = rk3288_lcdc_suspend,
3789 .resume = rk3288_lcdc_resume,
3790 .shutdown = rk3288_lcdc_shutdown,
3793 static int __init rk3288_lcdc_module_init(void)
3795 return platform_driver_register(&rk3288_lcdc_driver);
3798 static void __exit rk3288_lcdc_module_exit(void)
3800 platform_driver_unregister(&rk3288_lcdc_driver);
3803 fs_initcall(rk3288_lcdc_module_init);
3804 module_exit(rk3288_lcdc_module_exit);