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 <asm/div64.h>
30 #include <asm/uaccess.h>
31 #include <linux/rockchip/cpu.h>
32 #include <linux/rockchip/iomap.h>
33 #include <linux/rockchip/grf.h>
35 #include "rk3288_lcdc.h"
37 #if defined(CONFIG_HAS_EARLYSUSPEND)
38 #include <linux/earlysuspend.h>
41 static int dbg_thresd;
42 module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
44 #define DBG(level, x...) do { \
45 if (unlikely(dbg_thresd >= level)) \
46 printk(KERN_INFO x); } while (0)
48 /*#define WAIT_FOR_SYNC 1*/
50 static int rk3288_lcdc_get_id(u32 phy_base)
52 if (cpu_is_rk3288()) {
53 if (phy_base == 0xff930000)/*vop big*/
55 else if (phy_base == 0xff940000)/*vop lit*/
60 pr_err("un supported platform \n");
65 static int rk3288_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
70 struct lcdc_device *lcdc_dev = container_of(dev_drv,
74 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
75 lcdc_cfg_done(lcdc_dev);
77 for (i = 0; i < 256; i++) {
78 v = dev_drv->cur_screen->dsp_lut[i];
79 c = lcdc_dev->dsp_lut_addr_base + i;
83 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
89 static int rk3288_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
95 if (!lcdc_dev->clk_on) {
96 clk_prepare_enable(lcdc_dev->hclk);
97 clk_prepare_enable(lcdc_dev->dclk);
98 clk_prepare_enable(lcdc_dev->aclk);
99 clk_prepare_enable(lcdc_dev->pd);
100 spin_lock(&lcdc_dev->reg_lock);
101 lcdc_dev->clk_on = 1;
102 spin_unlock(&lcdc_dev->reg_lock);
108 static int rk3288_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
110 #ifdef CONFIG_RK_FPGA
111 lcdc_dev->clk_on = 0;
114 if (lcdc_dev->clk_on) {
115 spin_lock(&lcdc_dev->reg_lock);
116 lcdc_dev->clk_on = 0;
117 spin_unlock(&lcdc_dev->reg_lock);
119 clk_disable_unprepare(lcdc_dev->dclk);
120 clk_disable_unprepare(lcdc_dev->hclk);
121 clk_disable_unprepare(lcdc_dev->aclk);
122 clk_disable_unprepare(lcdc_dev->pd);
128 static int rk3288_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
131 spin_lock(&lcdc_dev->reg_lock);
132 if (likely(lcdc_dev->clk_on)) {
133 mask = m_DSP_HOLD_VALID_INTR_EN | m_FS_INTR_EN |
134 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_EN;
135 val = v_DSP_HOLD_VALID_INTR_EN(0) | v_FS_INTR_EN(0) |
136 v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_EN(0);
137 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
139 mask = m_DSP_HOLD_VALID_INTR_CLR | m_FS_INTR_CLR |
140 m_LINE_FLAG_INTR_CLR | m_LINE_FLAG_INTR_CLR;
141 val = v_DSP_HOLD_VALID_INTR_CLR(0) | v_FS_INTR_CLR(0) |
142 v_LINE_FLAG_INTR_CLR(0) | v_BUS_ERROR_INTR_CLR(0);
143 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
145 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN |
146 m_WIN2_EMPTY_INTR_EN | m_WIN3_EMPTY_INTR_EN |
147 m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
148 m_POST_BUF_EMPTY_INTR_EN;
149 val = v_WIN0_EMPTY_INTR_EN(0) | v_WIN1_EMPTY_INTR_EN(0) |
150 v_WIN2_EMPTY_INTR_EN(0) | v_WIN3_EMPTY_INTR_EN(0) |
151 v_HWC_EMPTY_INTR_EN(0) | v_POST_BUF_EMPTY_INTR_EN(0) |
152 v_PWM_GEN_INTR_EN(0);
153 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
155 mask = m_WIN0_EMPTY_INTR_CLR | m_WIN1_EMPTY_INTR_CLR |
156 m_WIN2_EMPTY_INTR_CLR | m_WIN3_EMPTY_INTR_CLR |
157 m_HWC_EMPTY_INTR_CLR | m_POST_BUF_EMPTY_INTR_CLR |
158 m_POST_BUF_EMPTY_INTR_CLR;
159 val = v_WIN0_EMPTY_INTR_CLR(0) | v_WIN1_EMPTY_INTR_CLR(0) |
160 v_WIN2_EMPTY_INTR_CLR(0) | v_WIN3_EMPTY_INTR_CLR(0) |
161 v_HWC_EMPTY_INTR_CLR(0) | v_POST_BUF_EMPTY_INTR_CLR(0) |
162 v_PWM_GEN_INTR_CLR(0);
163 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
164 lcdc_cfg_done(lcdc_dev);
165 spin_unlock(&lcdc_dev->reg_lock);
167 spin_unlock(&lcdc_dev->reg_lock);
172 static int rk3288_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
174 struct lcdc_device *lcdc_dev = container_of(dev_drv,
177 int *cbase = (int *)lcdc_dev->regs;
178 int *regsbak = (int *)lcdc_dev->regsbak;
181 printk("back up reg:\n");
182 for (i = 0; i <= (0x200 >> 4); i++) {
183 printk("0x%04x: ",i*16);
184 for (j = 0; j < 4; j++)
185 printk("%08x ", *(regsbak + i * 4 + j));
189 printk("lcdc reg:\n");
190 for (i = 0; i <= (0x200 >> 4); i++) {
191 printk("0x%04x: ",i*16);
192 for (j = 0; j < 4; j++)
193 printk("%08x ", readl_relaxed(cbase + i * 4 + j));
201 static int win##id##_enable(struct lcdc_device *lcdc_dev, int en) \
204 spin_lock(&lcdc_dev->reg_lock); \
205 msk = m_WIN##id##_EN; \
206 val = v_WIN##id##_EN(en); \
207 lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk, val); \
208 lcdc_cfg_done(lcdc_dev); \
209 val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
210 while (val != (!!en)) { \
211 val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
213 spin_unlock(&lcdc_dev->reg_lock); \
221 /*enable/disable win directly*/
222 static int rk3288_lcdc_win_direct_en
223 (struct rk_lcdc_driver *drv, int win_id , int en)
225 struct lcdc_device *lcdc_dev = container_of(drv,
226 struct lcdc_device, driver);
228 win0_enable(lcdc_dev, en);
229 else if (win_id == 1)
230 win1_enable(lcdc_dev, en);
231 else if (win_id == 2)
232 win2_enable(lcdc_dev, en);
233 else if (win_id == 3)
234 win3_enable(lcdc_dev, en);
236 dev_err(lcdc_dev->dev, "invalid win number:%d\n", win_id);
241 #define SET_WIN_ADDR(id) \
242 static int set_win##id##_addr(struct lcdc_device *lcdc_dev, u32 addr) \
245 spin_lock(&lcdc_dev->reg_lock); \
246 lcdc_writel(lcdc_dev,WIN##id##_YRGB_MST,addr); \
247 msk = m_WIN##id##_EN; \
248 val = v_WIN0_EN(1); \
249 lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk,val); \
250 lcdc_cfg_done(lcdc_dev); \
251 spin_unlock(&lcdc_dev->reg_lock); \
257 int rk3288_lcdc_direct_set_win_addr
258 (struct rk_lcdc_driver *dev_drv, int win_id, u32 addr)
260 struct lcdc_device *lcdc_dev = container_of(dev_drv,
261 struct lcdc_device, driver);
263 set_win0_addr(lcdc_dev, addr);
265 set_win1_addr(lcdc_dev, addr);
270 static void lcdc_read_reg_defalut_cfg(struct lcdc_device *lcdc_dev)
274 struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
276 spin_lock(&lcdc_dev->reg_lock);
277 for (reg = 0; reg < 0x1a0; reg+= 4) {
278 val = lcdc_readl(lcdc_dev, reg);
281 win0->area[0].xact = (val & m_WIN0_ACT_WIDTH)+1;
282 win0->area[0].yact = ((val & m_WIN0_ACT_HEIGHT)>>16)+1;
287 spin_unlock(&lcdc_dev->reg_lock);
291 /********do basic init*********/
292 static int rk3288_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
296 struct lcdc_device *lcdc_dev = container_of(dev_drv,
300 if (lcdc_dev->pre_init)
303 lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
304 lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
305 lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
306 lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
308 if (IS_ERR(lcdc_dev->pd) || (IS_ERR(lcdc_dev->aclk)) ||
309 (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
310 dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
314 rk_disp_pwr_enable(dev_drv);
315 rk3288_lcdc_clk_enable(lcdc_dev);
317 /*backup reg config at uboot*/
318 lcdc_read_reg_defalut_cfg(lcdc_dev);
319 #ifndef CONFIG_RK_FPGA
320 if (lcdc_dev->pwr18 == true) {
321 v = 0x00010001; /*bit14: 1,1.8v;0,3.3v*/
322 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
325 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
328 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_0,0x15110903);
329 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_1,0x00030911);
330 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_0,0x1a150b04);
331 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_1,0x00040b15);
332 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_0,0x15110903);
333 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_1,0x00030911);
335 lcdc_writel(lcdc_dev,FRC_LOWER01_0,0x12844821);
336 lcdc_writel(lcdc_dev,FRC_LOWER01_1,0x21488412);
337 lcdc_writel(lcdc_dev,FRC_LOWER10_0,0xa55a9696);
338 lcdc_writel(lcdc_dev,FRC_LOWER10_1,0x5aa56969);
339 lcdc_writel(lcdc_dev,FRC_LOWER11_0,0xdeb77deb);
340 lcdc_writel(lcdc_dev,FRC_LOWER11_1,0xed7bb7de);
342 mask = m_AUTO_GATING_EN;
343 val = v_AUTO_GATING_EN(0);
344 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val);
345 lcdc_cfg_done(lcdc_dev);
346 if (dev_drv->iommu_enabled) /*disable win0 to workaround iommu pagefault*/
347 win0_enable(lcdc_dev, 0);
348 lcdc_dev->pre_init = true;
354 static void rk3288_lcdc_deint(struct lcdc_device *lcdc_dev)
358 rk3288_lcdc_disable_irq(lcdc_dev);
359 spin_lock(&lcdc_dev->reg_lock);
360 if (likely(lcdc_dev->clk_on)) {
361 lcdc_dev->clk_on = 0;
362 lcdc_set_bit(lcdc_dev, SYS_CTRL, m_STANDBY_EN);
363 lcdc_cfg_done(lcdc_dev);
364 spin_unlock(&lcdc_dev->reg_lock);
366 spin_unlock(&lcdc_dev->reg_lock);
370 static int rk3288_lcdc_post_cfg(struct rk_lcdc_driver *dev_drv)
372 struct lcdc_device *lcdc_dev =
373 container_of(dev_drv, struct lcdc_device, driver);
374 struct rk_screen *screen = dev_drv->cur_screen;
375 u16 x_res = screen->mode.xres;
376 u16 y_res = screen->mode.yres;
379 u16 post_hsd_en,post_vsd_en;
380 u16 post_dsp_hact_st,post_dsp_hact_end;
381 u16 post_dsp_vact_st,post_dsp_vact_end;
382 u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
383 u16 post_h_fac,post_v_fac;
385 h_total = screen->mode.hsync_len+screen->mode.left_margin +
386 x_res + screen->mode.right_margin;
387 v_total = screen->mode.vsync_len+screen->mode.upper_margin +
388 y_res + screen->mode.lower_margin;
390 if(screen->post_dsp_stx + screen->post_xsize > x_res){
391 dev_warn(lcdc_dev->dev, "post:stx[%d] + xsize[%d] > x_res[%d]\n",
392 screen->post_dsp_stx,screen->post_xsize,x_res);
393 screen->post_dsp_stx = x_res - screen->post_xsize;
395 if(screen->x_mirror == 0){
396 post_dsp_hact_st=screen->post_dsp_stx +
397 screen->mode.hsync_len+screen->mode.left_margin;
398 post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize;
400 post_dsp_hact_end = h_total - screen->mode.right_margin -
401 screen->post_dsp_stx;
402 post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize;
404 if((screen->post_xsize < x_res)&&(screen->post_xsize != 0)){
407 GET_SCALE_FACTOR_BILI_DN(x_res , screen->post_xsize);
414 if(screen->post_dsp_sty + screen->post_ysize > y_res){
415 dev_warn(lcdc_dev->dev, "post:sty[%d] + ysize[%d] > y_res[%d]\n",
416 screen->post_dsp_sty,screen->post_ysize,y_res);
417 screen->post_dsp_sty = y_res - screen->post_ysize;
420 if(screen->y_mirror == 0){
421 post_dsp_vact_st = screen->post_dsp_sty +
422 screen->mode.vsync_len+screen->mode.upper_margin;
423 post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
425 post_dsp_vact_end = v_total - screen->mode.lower_margin -
426 - screen->post_dsp_sty;
427 post_dsp_vact_st = post_dsp_vact_end - screen->post_ysize;
429 if((screen->post_ysize < y_res)&&(screen->post_ysize != 0)){
431 post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res, screen->post_ysize);
437 if(screen->interlace == 1){
438 post_dsp_vact_st_f1 = v_total + post_dsp_vact_st;
439 post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
441 post_dsp_vact_st_f1 = 0;
442 post_dsp_vact_end_f1 = 0;
444 DBG(1,"post:xsize=%d,ysize=%d,xpos=%d,ypos=%d,"
445 "hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n",
446 screen->post_xsize,screen->post_ysize,screen->xpos,screen->ypos,
447 post_hsd_en,post_h_fac,post_vsd_en,post_v_fac);
448 mask = m_DSP_HACT_END_POST | m_DSP_HACT_ST_POST;
449 val = v_DSP_HACT_END_POST(post_dsp_hact_end) |
450 v_DSP_HACT_ST_POST(post_dsp_hact_st);
451 lcdc_msk_reg(lcdc_dev, POST_DSP_HACT_INFO, mask, val);
453 mask = m_DSP_VACT_END_POST | m_DSP_VACT_ST_POST;
454 val = v_DSP_VACT_END_POST(post_dsp_vact_end) |
455 v_DSP_VACT_ST_POST(post_dsp_vact_st);
456 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO, mask, val);
458 mask = m_POST_HS_FACTOR_YRGB | m_POST_VS_FACTOR_YRGB;
459 val = v_POST_HS_FACTOR_YRGB(post_h_fac) |
460 v_POST_VS_FACTOR_YRGB(post_v_fac);
461 lcdc_msk_reg(lcdc_dev, POST_SCL_FACTOR_YRGB, mask, val);
463 mask = m_DSP_VACT_END_POST_F1 | m_DSP_VACT_ST_POST_F1;
464 val = v_DSP_VACT_END_POST_F1(post_dsp_vact_end_f1) |
465 v_DSP_VACT_ST_POST_F1(post_dsp_vact_st_f1);
466 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO_F1, mask, val);
468 mask = m_POST_HOR_SD_EN | m_POST_VER_SD_EN;
469 val = v_POST_HOR_SD_EN(post_hsd_en) | v_POST_VER_SD_EN(post_vsd_en);
470 lcdc_msk_reg(lcdc_dev, POST_SCL_CTRL, mask, val);
474 static int rk3288_lcdc_clr_key_cfg(struct rk_lcdc_driver *dev_drv)
476 struct lcdc_device *lcdc_dev = container_of(dev_drv,
480 struct rk_lcdc_win *win;
481 u32 colorkey_r,colorkey_g,colorkey_b;
484 win = dev_drv->win[i];
485 key_val = win->color_key_val;
486 colorkey_r = (key_val & 0xff)<<2;
487 colorkey_g = ((key_val>>8)&0xff)<<12;
488 colorkey_b = ((key_val>>16)&0xff)<<22;
489 /*color key dither 565/888->aaa*/
490 key_val = colorkey_r | colorkey_g | colorkey_b;
493 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY, key_val);
496 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY, key_val);
499 lcdc_writel(lcdc_dev, WIN2_COLOR_KEY, key_val);
502 lcdc_writel(lcdc_dev, WIN3_COLOR_KEY, key_val);
505 printk(KERN_WARNING "%s:un support win num:%d\n",
513 static int rk3288_lcdc_alpha_cfg(struct rk_lcdc_driver *dev_drv,int win_id)
515 struct lcdc_device *lcdc_dev =
516 container_of(dev_drv, struct lcdc_device, driver);
517 struct rk_lcdc_win *win = dev_drv->win[win_id];
518 struct alpha_config alpha_config;
521 int ppixel_alpha,global_alpha;
522 u32 src_alpha_ctl,dst_alpha_ctl;
523 ppixel_alpha = ((win->format == ARGB888)||(win->format == ABGR888)) ? 1 : 0;
524 global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
525 alpha_config.src_global_alpha_val = win->g_alpha_val;
526 win->alpha_mode = AB_SRC_OVER;
527 /*printk("%s,alpha_mode=%d,alpha_en=%d,ppixel_a=%d,gla_a=%d\n",
528 __func__,win->alpha_mode,win->alpha_en,ppixel_alpha,global_alpha);*/
529 switch(win->alpha_mode){
533 alpha_config.src_factor_mode=AA_ZERO;
534 alpha_config.dst_factor_mode=AA_ZERO;
537 alpha_config.src_factor_mode=AA_ONE;
538 alpha_config.dst_factor_mode=AA_ZERO;
541 alpha_config.src_factor_mode=AA_ZERO;
542 alpha_config.dst_factor_mode=AA_ONE;
545 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
547 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
549 alpha_config.src_factor_mode=AA_ONE;
550 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
553 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
554 alpha_config.src_factor_mode=AA_SRC_INVERSE;
555 alpha_config.dst_factor_mode=AA_ONE;
558 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
559 alpha_config.src_factor_mode=AA_SRC;
560 alpha_config.dst_factor_mode=AA_ZERO;
563 alpha_config.src_factor_mode=AA_ZERO;
564 alpha_config.dst_factor_mode=AA_SRC;
567 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
568 alpha_config.src_factor_mode=AA_SRC_INVERSE;
569 alpha_config.dst_factor_mode=AA_ZERO;
572 alpha_config.src_factor_mode=AA_ZERO;
573 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
576 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
577 alpha_config.src_factor_mode=AA_SRC;
578 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
581 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
582 alpha_config.src_factor_mode=AA_SRC_INVERSE;
583 alpha_config.dst_factor_mode=AA_SRC;
586 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
587 alpha_config.src_factor_mode=AA_SRC_INVERSE;
588 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
590 case AB_SRC_OVER_GLOBAL:
591 alpha_config.src_global_alpha_mode=AA_PER_PIX_GLOBAL;
592 alpha_config.src_color_mode=AA_SRC_NO_PRE_MUL;
593 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
594 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
597 pr_err("alpha mode error\n");
600 if((ppixel_alpha == 1)&&(global_alpha == 1)){
601 alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL;
602 }else if(ppixel_alpha == 1){
603 alpha_config.src_global_alpha_mode = AA_PER_PIX;
604 }else if(global_alpha == 1){
605 alpha_config.src_global_alpha_mode = AA_GLOBAL;
607 dev_warn(lcdc_dev->dev,"alpha_en should be 0\n");
609 alpha_config.src_alpha_mode = AA_STRAIGHT;
610 alpha_config.src_alpha_cal_m0 = AA_NO_SAT;
614 src_alpha_ctl = 0x60;
615 dst_alpha_ctl = 0x64;
618 src_alpha_ctl = 0xa0;
619 dst_alpha_ctl = 0xa4;
622 src_alpha_ctl = 0xdc;
623 dst_alpha_ctl = 0xec;
626 src_alpha_ctl = 0x12c;
627 dst_alpha_ctl = 0x13c;
630 mask = m_WIN0_DST_FACTOR_M0;
631 val = v_WIN0_DST_FACTOR_M0(alpha_config.dst_factor_mode);
632 lcdc_msk_reg(lcdc_dev, dst_alpha_ctl, mask, val);
633 mask = m_WIN0_SRC_ALPHA_EN | m_WIN0_SRC_COLOR_M0 |
634 m_WIN0_SRC_ALPHA_M0 | m_WIN0_SRC_BLEND_M0 |
635 m_WIN0_SRC_ALPHA_CAL_M0 | m_WIN0_SRC_FACTOR_M0|
636 m_WIN0_SRC_GLOBAL_ALPHA;
637 val = v_WIN0_SRC_ALPHA_EN(1) |
638 v_WIN0_SRC_COLOR_M0(alpha_config.src_color_mode) |
639 v_WIN0_SRC_ALPHA_M0(alpha_config.src_alpha_mode) |
640 v_WIN0_SRC_BLEND_M0(alpha_config.src_global_alpha_mode) |
641 v_WIN0_SRC_ALPHA_CAL_M0(alpha_config.src_alpha_cal_m0) |
642 v_WIN0_SRC_FACTOR_M0(alpha_config.src_factor_mode) |
643 v_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val);
644 lcdc_msk_reg(lcdc_dev, src_alpha_ctl, mask, val);
648 static int rk3288_lcdc_area_swap(struct rk_lcdc_win *win,int area_num)
650 struct rk_lcdc_win_area area_temp;
653 area_temp = win->area[0];
654 win->area[0] = win->area[1];
655 win->area[1] = area_temp;
658 area_temp = win->area[0];
659 win->area[0] = win->area[2];
660 win->area[2] = area_temp;
663 area_temp = win->area[0];
664 win->area[0] = win->area[3];
665 win->area[3] = area_temp;
667 area_temp = win->area[1];
668 win->area[1] = win->area[2];
669 win->area[2] = area_temp;
672 printk(KERN_WARNING "un supported area num!\n");
678 static int rk3288_win_area_check_var(int win_id,int area_num,struct rk_lcdc_win_area *area_pre,
679 struct rk_lcdc_win_area *area_now)
681 if((area_pre->ypos >= area_now->ypos) ||
682 (area_pre->ypos+area_pre->ysize > area_now->ypos)){
685 "area_pre[%d]:ypos[%d],ysize[%d]\n"
686 "area_now[%d]:ypos[%d],ysize[%d]\n",
688 area_num-1,area_pre->ypos,area_pre->ysize,
689 area_num, area_now->ypos,area_now->ysize);
695 static int rk3288_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
697 struct lcdc_device *lcdc_dev =
698 container_of(dev_drv, struct lcdc_device, driver);
699 struct rk_lcdc_win *win = dev_drv->win[win_id];
700 unsigned int mask, val, off;
702 if(win->win_lb_mode == 5)
703 win->win_lb_mode = 4;
706 mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
707 m_WIN0_LB_MODE | m_WIN0_RB_SWAP;
708 val = v_WIN0_EN(win->state) | v_WIN0_DATA_FMT(win->fmt_cfg) |
709 v_WIN0_FMT_10(win->fmt_10) |
710 v_WIN0_LB_MODE(win->win_lb_mode) |
711 v_WIN0_RB_SWAP(win->swap_rb);
712 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
714 mask = m_WIN0_BIC_COE_SEL |
715 m_WIN0_VSD_YRGB_GT4 | m_WIN0_VSD_YRGB_GT2 |
716 m_WIN0_VSD_CBR_GT4 | m_WIN0_VSD_CBR_GT2 |
717 m_WIN0_YRGB_HOR_SCL_MODE | m_WIN0_YRGB_VER_SCL_MODE |
718 m_WIN0_YRGB_HSD_MODE | m_WIN0_YRGB_VSU_MODE |
719 m_WIN0_YRGB_VSD_MODE | m_WIN0_CBR_HOR_SCL_MODE |
720 m_WIN0_CBR_VER_SCL_MODE | m_WIN0_CBR_HSD_MODE |
721 m_WIN0_CBR_VSU_MODE | m_WIN0_CBR_VSD_MODE;
722 val = v_WIN0_BIC_COE_SEL(win->bic_coe_el) |
723 v_WIN0_VSD_YRGB_GT4(win->vsd_yrgb_gt4) |
724 v_WIN0_VSD_YRGB_GT2(win->vsd_yrgb_gt2) |
725 v_WIN0_VSD_CBR_GT4(win->vsd_cbr_gt4) |
726 v_WIN0_VSD_CBR_GT2(win->vsd_cbr_gt2) |
727 v_WIN0_YRGB_HOR_SCL_MODE(win->yrgb_hor_scl_mode) |
728 v_WIN0_YRGB_VER_SCL_MODE(win->yrgb_ver_scl_mode) |
729 v_WIN0_YRGB_HSD_MODE(win->yrgb_hsd_mode) |
730 v_WIN0_YRGB_VSU_MODE(win->yrgb_vsu_mode) |
731 v_WIN0_YRGB_VSD_MODE(win->yrgb_vsd_mode) |
732 v_WIN0_CBR_HOR_SCL_MODE(win->cbr_hor_scl_mode) |
733 v_WIN0_CBR_VER_SCL_MODE(win->cbr_ver_scl_mode) |
734 v_WIN0_CBR_HSD_MODE(win->cbr_hsd_mode) |
735 v_WIN0_CBR_VSU_MODE(win->cbr_vsu_mode) |
736 v_WIN0_CBR_VSD_MODE(win->cbr_vsd_mode);
737 lcdc_msk_reg(lcdc_dev, WIN0_CTRL1+off, mask,val);
739 val = v_WIN0_VIR_STRIDE(win->area[0].y_vir_stride) |
740 v_WIN0_VIR_STRIDE_UV(win->area[0].uv_vir_stride);
741 lcdc_writel(lcdc_dev, WIN0_VIR+off, val);
742 /*lcdc_writel(lcdc_dev, WIN0_YRGB_MST+off, win->area[0].y_addr);
743 lcdc_writel(lcdc_dev, WIN0_CBR_MST+off, win->area[0].uv_addr);*/
744 val = v_WIN0_ACT_WIDTH(win->area[0].xact) |
745 v_WIN0_ACT_HEIGHT(win->area[0].yact);
746 lcdc_writel(lcdc_dev, WIN0_ACT_INFO+off, val);
748 val = v_WIN0_DSP_WIDTH(win->area[0].xsize) |
749 v_WIN0_DSP_HEIGHT(win->area[0].ysize);
750 lcdc_writel(lcdc_dev, WIN0_DSP_INFO+off, val);
752 val = v_WIN0_DSP_XST(win->area[0].dsp_stx) |
753 v_WIN0_DSP_YST(win->area[0].dsp_sty);
754 lcdc_writel(lcdc_dev, WIN0_DSP_ST+off, val);
756 val = v_WIN0_HS_FACTOR_YRGB(win->scale_yrgb_x) |
757 v_WIN0_VS_FACTOR_YRGB(win->scale_yrgb_y);
758 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB+off, val);
760 val = v_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) |
761 v_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y);
762 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR+off, val);
763 if(win->alpha_en == 1)
764 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
766 mask = m_WIN0_SRC_ALPHA_EN;
767 val = v_WIN0_SRC_ALPHA_EN(0);
768 lcdc_msk_reg(lcdc_dev,WIN0_SRC_ALPHA_CTRL+off,mask,val);
773 val = v_WIN0_EN(win->state);
774 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
779 static int rk3288_win_2_3_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
781 struct lcdc_device *lcdc_dev =
782 container_of(dev_drv, struct lcdc_device, driver);
783 struct rk_lcdc_win *win = dev_drv->win[win_id];
784 struct rk_screen *screen = dev_drv->cur_screen;
785 unsigned int mask, val, off;
786 off = (win_id-2) * 0x50;
787 if((screen->y_mirror == 1)&&(win->area_num > 1)){
788 rk3288_lcdc_area_swap(win,win->area_num);
792 mask = m_WIN2_EN | m_WIN2_DATA_FMT | m_WIN2_RB_SWAP;
793 val = v_WIN2_EN(1) | v_WIN2_DATA_FMT(win->fmt_cfg) |
794 v_WIN2_RB_SWAP(win->swap_rb);
795 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
797 if(win->area[0].state == 1){
798 mask = m_WIN2_MST0_EN;
799 val = v_WIN2_MST0_EN(win->area[0].state);
800 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
802 mask = m_WIN2_VIR_STRIDE0;
803 val = v_WIN2_VIR_STRIDE0(win->area[0].y_vir_stride);
804 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
806 /*lcdc_writel(lcdc_dev,WIN2_MST0+off,win->area[0].y_addr);*/
807 val = v_WIN2_DSP_WIDTH0(win->area[0].xsize) |
808 v_WIN2_DSP_HEIGHT0(win->area[0].ysize);
809 lcdc_writel(lcdc_dev,WIN2_DSP_INFO0+off,val);
810 val = v_WIN2_DSP_XST0(win->area[0].dsp_stx) |
811 v_WIN2_DSP_YST0(win->area[0].dsp_sty);
812 lcdc_writel(lcdc_dev,WIN2_DSP_ST0+off,val);
814 mask = m_WIN2_MST0_EN;
815 val = v_WIN2_MST0_EN(0);
816 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
819 if(win->area[1].state == 1){
820 rk3288_win_area_check_var(win_id,1,&win->area[0],&win->area[1]);
822 mask = m_WIN2_MST1_EN;
823 val = v_WIN2_MST1_EN(win->area[1].state);
824 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
826 mask = m_WIN2_VIR_STRIDE1;
827 val = v_WIN2_VIR_STRIDE1(win->area[1].y_vir_stride);
828 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
830 /*lcdc_writel(lcdc_dev,WIN2_MST1+off,win->area[1].y_addr);*/
831 val = v_WIN2_DSP_WIDTH1(win->area[1].xsize) |
832 v_WIN2_DSP_HEIGHT1(win->area[1].ysize);
833 lcdc_writel(lcdc_dev,WIN2_DSP_INFO1+off,val);
834 val = v_WIN2_DSP_XST1(win->area[1].dsp_stx) |
835 v_WIN2_DSP_YST1(win->area[1].dsp_sty);
836 lcdc_writel(lcdc_dev,WIN2_DSP_ST1+off,val);
838 mask = m_WIN2_MST1_EN;
839 val = v_WIN2_MST1_EN(0);
840 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
843 if(win->area[2].state == 1){
844 rk3288_win_area_check_var(win_id,2,&win->area[1],&win->area[2]);
846 mask = m_WIN2_MST2_EN;
847 val = v_WIN2_MST2_EN(win->area[2].state);
848 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
850 mask = m_WIN2_VIR_STRIDE2;
851 val = v_WIN2_VIR_STRIDE2(win->area[2].y_vir_stride);
852 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
854 /*lcdc_writel(lcdc_dev,WIN2_MST2+off,win->area[2].y_addr);*/
855 val = v_WIN2_DSP_WIDTH2(win->area[2].xsize) |
856 v_WIN2_DSP_HEIGHT2(win->area[2].ysize);
857 lcdc_writel(lcdc_dev,WIN2_DSP_INFO2+off,val);
858 val = v_WIN2_DSP_XST2(win->area[2].dsp_stx) |
859 v_WIN2_DSP_YST2(win->area[2].dsp_sty);
860 lcdc_writel(lcdc_dev,WIN2_DSP_ST2+off,val);
862 mask = m_WIN2_MST2_EN;
863 val = v_WIN2_MST2_EN(0);
864 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
867 if(win->area[3].state == 1){
868 rk3288_win_area_check_var(win_id,3,&win->area[2],&win->area[3]);
870 mask = m_WIN2_MST3_EN;
871 val = v_WIN2_MST3_EN(win->area[3].state);
872 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
874 mask = m_WIN2_VIR_STRIDE3;
875 val = v_WIN2_VIR_STRIDE3(win->area[3].y_vir_stride);
876 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
878 /*lcdc_writel(lcdc_dev,WIN2_MST3+off,win->area[3].y_addr);*/
879 val = v_WIN2_DSP_WIDTH3(win->area[3].xsize) |
880 v_WIN2_DSP_HEIGHT3(win->area[3].ysize);
881 lcdc_writel(lcdc_dev,WIN2_DSP_INFO3+off,val);
882 val = v_WIN2_DSP_XST3(win->area[3].dsp_stx) |
883 v_WIN2_DSP_YST3(win->area[3].dsp_sty);
884 lcdc_writel(lcdc_dev,WIN2_DSP_ST3+off,val);
886 mask = m_WIN2_MST3_EN;
887 val = v_WIN2_MST3_EN(0);
888 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
891 if(win->alpha_en == 1)
892 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
894 mask = m_WIN2_SRC_ALPHA_EN;
895 val = v_WIN2_SRC_ALPHA_EN(0);
896 lcdc_msk_reg(lcdc_dev,WIN2_SRC_ALPHA_CTRL+off,mask,val);
899 mask = m_WIN2_EN | m_WIN2_MST0_EN |
900 m_WIN2_MST0_EN | m_WIN2_MST2_EN |
902 val = v_WIN2_EN(win->state) | v_WIN2_MST0_EN(0) |
903 v_WIN2_MST1_EN(0) | v_WIN2_MST2_EN(0) |
905 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0+off, mask,val);
910 static int rk3288_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
912 struct lcdc_device *lcdc_dev =
913 container_of(dev_drv, struct lcdc_device, driver);
917 spin_lock(&lcdc_dev->reg_lock);
918 if(likely(lcdc_dev->clk_on))
920 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
921 v_STANDBY_EN(lcdc_dev->standby));
922 rk3288_win_0_1_reg_update(dev_drv,0);
923 rk3288_win_0_1_reg_update(dev_drv,1);
924 rk3288_win_2_3_reg_update(dev_drv,2);
925 rk3288_win_2_3_reg_update(dev_drv,3);
926 /*rk3288_lcdc_post_cfg(dev_drv);*/
927 lcdc_cfg_done(lcdc_dev);
929 spin_unlock(&lcdc_dev->reg_lock);
931 /*if (dev_drv->wait_fs) {*/
933 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
934 init_completion(&dev_drv->frame_done);
935 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
936 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
938 (dev_drv->cur_screen->ft +
940 if (!timeout && (!dev_drv->frame_done.done)) {
941 dev_warn(lcdc_dev->dev, "wait for new frame start time out!\n");
945 DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
950 static int rk3288_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
952 if (lcdc_dev->driver.iommu_enabled)
953 memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x330);
955 memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
958 static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
961 struct lcdc_device *lcdc_dev =
962 container_of(dev_drv, struct lcdc_device, driver);
963 spin_lock(&lcdc_dev->reg_lock);
964 if (likely(lcdc_dev->clk_on)) {
967 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
968 mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
969 val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
970 lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
972 spin_unlock(&lcdc_dev->reg_lock);
976 static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
978 #ifdef CONFIG_RK_FPGA
982 struct lcdc_device *lcdc_dev =
983 container_of(dev_drv, struct lcdc_device, driver);
984 struct rk_screen *screen = dev_drv->cur_screen;
986 ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
988 dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
990 div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
991 lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
993 fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
994 screen->ft = 1000 / fps;
995 dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
996 lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
1001 static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
1005 struct lcdc_device *lcdc_dev =
1006 container_of(dev_drv, struct lcdc_device, driver);
1007 struct rk_screen *screen = dev_drv->cur_screen;
1008 u16 hsync_len = screen->mode.hsync_len;
1009 u16 left_margin = screen->mode.left_margin;
1010 u16 right_margin = screen->mode.right_margin;
1011 u16 vsync_len = screen->mode.vsync_len;
1012 u16 upper_margin = screen->mode.upper_margin;
1013 u16 lower_margin = screen->mode.lower_margin;
1014 u16 x_res = screen->mode.xres;
1015 u16 y_res = screen->mode.yres;
1017 u16 h_total,v_total;
1019 h_total = hsync_len + left_margin + x_res + right_margin;
1020 v_total = vsync_len + upper_margin + y_res + lower_margin;
1022 screen->post_dsp_stx = x_res * (100 - screen->overscan.left) / 200;
1023 screen->post_dsp_sty = y_res * (100 - screen->overscan.top) / 200;
1024 screen->post_xsize = x_res * (screen->overscan.left + screen->overscan.right) / 200;
1025 screen->post_ysize = y_res * (screen->overscan.top + screen->overscan.bottom) / 200;
1027 spin_lock(&lcdc_dev->reg_lock);
1028 if (likely(lcdc_dev->clk_on)) {
1029 switch (screen->face) {
1032 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1034 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1035 v_DITHER_DOWN_SEL(1);
1036 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1040 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1042 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1043 v_DITHER_DOWN_SEL(1);
1044 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1048 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1050 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1051 v_DITHER_DOWN_SEL(1);
1052 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1056 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1058 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1059 v_DITHER_DOWN_SEL(1);
1060 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1064 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
1065 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
1066 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1069 dev_err(lcdc_dev->dev,"un supported interface!\n");
1072 switch(screen->type){
1075 case SCREEN_DUAL_LVDS:
1076 mask = m_RGB_OUT_EN;
1077 val = v_RGB_OUT_EN(1);
1079 v |= (lcdc_dev->id << 3);
1083 mask = m_HDMI_OUT_EN;
1084 val = v_HDMI_OUT_EN(1);
1087 mask = m_MIPI_OUT_EN;
1088 val = v_MIPI_OUT_EN(1);
1090 case SCREEN_DUAL_MIPI:
1091 mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
1092 val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
1095 face = OUT_RGB_AAA; /*RGB AAA output*/
1096 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
1097 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
1098 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1099 mask = m_EDP_OUT_EN;
1100 val = v_EDP_OUT_EN(1);
1103 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
1104 #ifndef CONFIG_RK_FPGA
1105 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
1107 mask = m_DSP_OUT_MODE | m_DSP_HSYNC_POL | m_DSP_VSYNC_POL |
1108 m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP |
1109 m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
1110 m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN |
1111 m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN;
1112 val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
1113 v_DSP_VSYNC_POL(screen->pin_vsync) |
1114 v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
1115 v_DSP_BG_SWAP(screen->swap_gb) | v_DSP_RB_SWAP(screen->swap_rb) |
1116 v_DSP_RG_SWAP(screen->swap_rg) |
1117 v_DSP_DELTA_SWAP(screen->swap_delta) |
1118 v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) |
1119 v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
1120 v_DSP_X_MIR_EN(screen->x_mirror) | v_DSP_Y_MIR_EN(screen->y_mirror);
1121 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
1123 mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
1124 val = v_DSP_BG_BLUE(0) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
1125 lcdc_msk_reg(lcdc_dev, DSP_BG, mask, val);
1127 mask = m_DSP_HS_PW | m_DSP_HTOTAL;
1128 val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
1129 lcdc_msk_reg(lcdc_dev, DSP_HTOTAL_HS_END, mask, val);
1131 mask = m_DSP_HACT_END | m_DSP_HACT_ST;
1132 val = v_DSP_HACT_END(hsync_len + left_margin + x_res) |
1133 v_DSP_HACT_ST(hsync_len + left_margin);
1134 lcdc_msk_reg(lcdc_dev, DSP_HACT_ST_END, mask, val);
1136 mask = m_DSP_VS_PW | m_DSP_VTOTAL;
1137 val = v_DSP_VS_PW(vsync_len) | v_DSP_VTOTAL(v_total);
1138 lcdc_msk_reg(lcdc_dev, DSP_VTOTAL_VS_END, mask, val);
1140 mask = m_DSP_VACT_END | m_DSP_VACT_ST;
1141 val = v_DSP_VACT_END(vsync_len + upper_margin + y_res) |
1142 v_DSP_VACT_ST(vsync_len + upper_margin);
1143 lcdc_msk_reg(lcdc_dev, DSP_VACT_ST_END, mask, val);
1145 rk3288_lcdc_post_cfg(dev_drv);
1147 spin_unlock(&lcdc_dev->reg_lock);
1148 rk3288_lcdc_set_dclk(dev_drv);
1149 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
1150 dev_drv->trsm_ops->enable();
1157 /*enable layer,open:1,enable;0 disable*/
1158 static int win0_open(struct lcdc_device *lcdc_dev, bool open)
1160 spin_lock(&lcdc_dev->reg_lock);
1161 if (likely(lcdc_dev->clk_on)) {
1163 if (!lcdc_dev->atv_layer_cnt) {
1164 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1165 lcdc_dev->standby = 0;
1167 lcdc_dev->atv_layer_cnt++;
1168 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1169 lcdc_dev->atv_layer_cnt--;
1171 lcdc_dev->driver.win[0]->state = open;
1172 if (!lcdc_dev->atv_layer_cnt) {
1173 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1174 lcdc_dev->standby = 1;
1177 spin_unlock(&lcdc_dev->reg_lock);
1182 static int win1_open(struct lcdc_device *lcdc_dev, bool open)
1184 spin_lock(&lcdc_dev->reg_lock);
1185 if (likely(lcdc_dev->clk_on)) {
1187 if (!lcdc_dev->atv_layer_cnt) {
1188 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1189 lcdc_dev->standby = 0;
1191 lcdc_dev->atv_layer_cnt++;
1192 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1193 lcdc_dev->atv_layer_cnt--;
1195 lcdc_dev->driver.win[1]->state = open;
1197 /*if no layer used,disable lcdc*/
1198 if (!lcdc_dev->atv_layer_cnt) {
1199 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1200 lcdc_dev->standby = 1;
1203 spin_unlock(&lcdc_dev->reg_lock);
1208 static int win2_open(struct lcdc_device *lcdc_dev, bool open)
1210 spin_lock(&lcdc_dev->reg_lock);
1211 if (likely(lcdc_dev->clk_on)) {
1213 if (!lcdc_dev->atv_layer_cnt) {
1214 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1215 lcdc_dev->standby = 0;
1217 lcdc_dev->atv_layer_cnt++;
1218 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1219 lcdc_dev->atv_layer_cnt--;
1221 lcdc_dev->driver.win[2]->state = open;
1223 /*if no layer used,disable lcdc*/
1224 if (!lcdc_dev->atv_layer_cnt) {
1225 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1226 lcdc_dev->standby = 1;
1229 spin_unlock(&lcdc_dev->reg_lock);
1234 static int win3_open(struct lcdc_device *lcdc_dev, bool open)
1236 spin_lock(&lcdc_dev->reg_lock);
1237 if (likely(lcdc_dev->clk_on)) {
1239 if (!lcdc_dev->atv_layer_cnt) {
1240 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1241 lcdc_dev->standby = 0;
1243 lcdc_dev->atv_layer_cnt++;
1244 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1245 lcdc_dev->atv_layer_cnt--;
1247 lcdc_dev->driver.win[3]->state = open;
1249 /*if no layer used,disable lcdc*/
1250 if (!lcdc_dev->atv_layer_cnt) {
1251 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1252 lcdc_dev->standby = 1;
1255 spin_unlock(&lcdc_dev->reg_lock);
1259 static int rk3288_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
1261 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1262 struct lcdc_device, driver);
1264 struct rk_screen *screen = dev_drv->cur_screen;
1266 mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
1267 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR |
1268 m_BUS_ERROR_INTR_EN | m_DSP_LINE_FLAG_NUM;
1269 val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(1) |
1270 v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0) |
1271 v_DSP_LINE_FLAG_NUM(screen->mode.vsync_len + screen->mode.upper_margin +
1272 screen->mode.yres -1);
1273 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
1275 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN | m_WIN2_EMPTY_INTR_EN |
1276 m_WIN3_EMPTY_INTR_EN |m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
1278 val = v_WIN0_EMPTY_INTR_EN(1) | v_WIN1_EMPTY_INTR_EN(1) | v_WIN2_EMPTY_INTR_EN(1) |
1279 v_WIN3_EMPTY_INTR_EN(1)| v_HWC_EMPTY_INTR_EN(1) | v_POST_BUF_EMPTY_INTR_EN(1) |
1280 v_PWM_GEN_INTR_EN(1);
1281 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
1286 static int rk3288_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
1289 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1290 struct lcdc_device, driver);
1292 /*enable clk,when first layer open */
1293 if ((open) && (!lcdc_dev->atv_layer_cnt)) {
1294 rk3288_lcdc_pre_init(dev_drv);
1295 rk3288_lcdc_clk_enable(lcdc_dev);
1296 rk3288_lcdc_reg_restore(lcdc_dev);
1297 if (dev_drv->iommu_enabled)
1298 rk3288_lcdc_mmu_en(dev_drv);
1299 if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
1300 rk3288_lcdc_set_dclk(dev_drv);
1301 rk3288_lcdc_enable_irq(dev_drv);
1303 rk3288_load_screen(dev_drv, 1);
1305 spin_lock(&lcdc_dev->reg_lock);
1306 if (dev_drv->cur_screen->dsp_lut)
1307 rk3288_lcdc_set_lut(dev_drv);
1308 spin_unlock(&lcdc_dev->reg_lock);
1312 win0_open(lcdc_dev, open);
1313 else if (win_id == 1)
1314 win1_open(lcdc_dev, open);
1315 else if (win_id == 2)
1316 win2_open(lcdc_dev, open);
1317 else if (win_id == 3)
1318 win3_open(lcdc_dev, open);
1320 dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
1322 /*when all layer closed,disable clk */
1323 if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
1324 rk3288_lcdc_disable_irq(lcdc_dev);
1325 rk3288_lcdc_reg_update(dev_drv);
1326 rk3288_lcdc_clk_disable(lcdc_dev);
1332 static int win0_display(struct lcdc_device *lcdc_dev,
1333 struct rk_lcdc_win *win)
1337 y_addr = win->area[0].smem_start+win->area[0].y_offset;/*win->smem_start + win->y_offset;*/
1338 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1339 DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
1340 lcdc_dev->id, __func__, y_addr, uv_addr,win->area[0].y_offset);
1341 spin_lock(&lcdc_dev->reg_lock);
1342 if (likely(lcdc_dev->clk_on)) {
1343 win->area[0].y_addr = y_addr;
1344 win->area[0].uv_addr = uv_addr;
1345 lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr);
1346 lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr);
1347 /*lcdc_cfg_done(lcdc_dev);*/
1349 spin_unlock(&lcdc_dev->reg_lock);
1355 static int win1_display(struct lcdc_device *lcdc_dev,
1356 struct rk_lcdc_win *win)
1360 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1361 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1362 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>uv_addr:0x%x\n",
1363 lcdc_dev->id, __func__, y_addr, uv_addr);
1365 spin_lock(&lcdc_dev->reg_lock);
1366 if (likely(lcdc_dev->clk_on)) {
1367 win->area[0].y_addr = y_addr;
1368 win->area[0].uv_addr = uv_addr;
1369 lcdc_writel(lcdc_dev, WIN1_YRGB_MST, win->area[0].y_addr);
1370 lcdc_writel(lcdc_dev, WIN1_CBR_MST, win->area[0].uv_addr);
1372 spin_unlock(&lcdc_dev->reg_lock);
1378 static int win2_display(struct lcdc_device *lcdc_dev,
1379 struct rk_lcdc_win *win)
1382 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1383 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1384 lcdc_dev->id, __func__, y_addr);
1386 spin_lock(&lcdc_dev->reg_lock);
1387 if (likely(lcdc_dev->clk_on)){
1388 for(i=0;i<win->area_num;i++)
1389 win->area[i].y_addr =
1390 win->area[i].smem_start + win->area[i].y_offset;
1391 lcdc_writel(lcdc_dev,WIN2_MST0,win->area[0].y_addr);
1392 lcdc_writel(lcdc_dev,WIN2_MST1,win->area[1].y_addr);
1393 lcdc_writel(lcdc_dev,WIN2_MST2,win->area[2].y_addr);
1394 lcdc_writel(lcdc_dev,WIN2_MST3,win->area[3].y_addr);
1396 spin_unlock(&lcdc_dev->reg_lock);
1400 static int win3_display(struct lcdc_device *lcdc_dev,
1401 struct rk_lcdc_win *win)
1404 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1405 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1406 lcdc_dev->id, __func__, y_addr);
1408 spin_lock(&lcdc_dev->reg_lock);
1409 if (likely(lcdc_dev->clk_on)){
1410 for(i=0;i<win->area_num;i++)
1411 win->area[i].y_addr =
1412 win->area[i].smem_start + win->area[i].y_offset;
1413 lcdc_writel(lcdc_dev,WIN3_MST0,win->area[0].y_addr);
1414 lcdc_writel(lcdc_dev,WIN3_MST1,win->area[1].y_addr);
1415 lcdc_writel(lcdc_dev,WIN3_MST2,win->area[2].y_addr);
1416 lcdc_writel(lcdc_dev,WIN3_MST3,win->area[3].y_addr);
1418 spin_unlock(&lcdc_dev->reg_lock);
1422 static int rk3288_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
1424 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1425 struct lcdc_device, driver);
1426 struct rk_lcdc_win *win = NULL;
1427 struct rk_screen *screen = dev_drv->cur_screen;
1429 #if defined(WAIT_FOR_SYNC)
1431 unsigned long flags;
1433 win = dev_drv->win[win_id];
1435 dev_err(dev_drv->dev, "screen is null!\n");
1439 win0_display(lcdc_dev, win);
1440 }else if(win_id == 1){
1441 win1_display(lcdc_dev, win);
1442 }else if(win_id == 2){
1443 win2_display(lcdc_dev, win);
1444 }else if(win_id == 3){
1445 win3_display(lcdc_dev, win);
1447 dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
1451 /*this is the first frame of the system ,enable frame start interrupt */
1452 if ((dev_drv->first_frame)) {
1453 dev_drv->first_frame = 0;
1454 rk3288_lcdc_enable_irq(dev_drv);
1456 #if defined(WAIT_FOR_SYNC)
1457 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
1458 init_completion(&dev_drv->frame_done);
1459 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
1460 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
1461 msecs_to_jiffies(dev_drv->
1464 if (!timeout && (!dev_drv->frame_done.done)) {
1465 dev_info(dev_drv->dev, "wait for new frame start time out!\n");
1472 static int rk3288_lcdc_cal_scl_fac(struct rk_lcdc_win *win)
1482 u32 yrgb_vScaleDnMult;
1483 u32 yrgb_xscl_factor;
1484 u32 yrgb_yscl_factor;
1485 u8 yrgb_vsd_bil_gt2=0;
1486 u8 yrgb_vsd_bil_gt4=0;
1492 u32 cbcr_vScaleDnMult;
1493 u32 cbcr_xscl_factor;
1494 u32 cbcr_yscl_factor;
1495 u8 cbcr_vsd_bil_gt2=0;
1496 u8 cbcr_vsd_bil_gt4=0;
1500 srcW = win->area[0].xact;
1501 srcH = win->area[0].yact;
1502 dstW = win->area[0].xsize;
1503 dstH = win->area[0].ysize;
1510 if ((yrgb_dstW >= yrgb_srcW*8) || (yrgb_dstH >= yrgb_srcH*8) ||
1511 (yrgb_dstW*8 <= yrgb_srcW) || (yrgb_dstH*8 <= yrgb_srcH)) {
1512 pr_err("ERROR: yrgb scale exceed 8,"
1513 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1514 yrgb_srcW,yrgb_srcH,yrgb_dstW,yrgb_dstH);
1516 if(yrgb_srcW < yrgb_dstW){
1517 win->yrgb_hor_scl_mode = SCALE_UP;
1518 }else if(yrgb_srcW > yrgb_dstW){
1519 win->yrgb_hor_scl_mode = SCALE_DOWN;
1521 win->yrgb_hor_scl_mode = SCALE_NONE;
1524 if(yrgb_srcH < yrgb_dstH){
1525 win->yrgb_ver_scl_mode = SCALE_UP;
1526 }else if (yrgb_srcH > yrgb_dstH){
1527 win->yrgb_ver_scl_mode = SCALE_DOWN;
1529 win->yrgb_ver_scl_mode = SCALE_NONE;
1533 switch (win->format) {
1567 if ((cbcr_dstW >= cbcr_srcW*8) || (cbcr_dstH >= cbcr_srcH*8) ||
1568 (cbcr_dstW*8 <= cbcr_srcW)||(cbcr_dstH*8 <= cbcr_srcH)) {
1569 pr_err("ERROR: cbcr scale exceed 8,"
1570 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1571 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH);
1575 if(cbcr_srcW < cbcr_dstW){
1576 win->cbr_hor_scl_mode = SCALE_UP;
1577 }else if(cbcr_srcW > cbcr_dstW){
1578 win->cbr_hor_scl_mode = SCALE_DOWN;
1580 win->cbr_hor_scl_mode = SCALE_NONE;
1583 if(cbcr_srcH < cbcr_dstH){
1584 win->cbr_ver_scl_mode = SCALE_UP;
1585 }else if(cbcr_srcH > cbcr_dstH){
1586 win->cbr_ver_scl_mode = SCALE_DOWN;
1588 win->cbr_ver_scl_mode = SCALE_NONE;
1590 DBG(1, "srcW:%d>>srcH:%d>>dstW:%d>>dstH:%d>>\n"
1591 "yrgb:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1592 "cbcr:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1593 ,srcW,srcH,dstW,dstH,yrgb_srcW,yrgb_srcH,yrgb_dstW,
1594 yrgb_dstH,win->yrgb_hor_scl_mode,win->yrgb_ver_scl_mode,
1595 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH,
1596 win->cbr_hor_scl_mode,win->cbr_ver_scl_mode);
1598 /*line buffer mode*/
1599 if((win->format == YUV422) || (win->format == YUV420) || (win->format == YUV422_A) || (win->format == YUV420_A)){
1600 if(win->cbr_hor_scl_mode == SCALE_DOWN){
1601 if ((cbcr_dstW > 3840) || (cbcr_dstW == 0)) {
1602 pr_err("ERROR cbcr_dstW = %d\n",cbcr_dstW);
1603 }else if(cbcr_dstW > 2560){
1604 win->win_lb_mode = LB_RGB_3840X2;
1605 }else if(cbcr_dstW > 1920){
1606 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1607 if(yrgb_dstW > 3840){
1608 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1609 }else if(yrgb_dstW > 2560){
1610 win->win_lb_mode = LB_RGB_3840X2;
1611 }else if(yrgb_dstW > 1920){
1612 win->win_lb_mode = LB_RGB_2560X4;
1614 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1617 }else if(cbcr_dstW > 1280){
1618 win->win_lb_mode = LB_YUV_3840X5;
1620 win->win_lb_mode = LB_YUV_2560X8;
1622 } else { /*SCALE_UP or SCALE_NONE*/
1623 if ((cbcr_srcW > 3840) || (cbcr_srcW == 0)) {
1624 pr_err("ERROR cbcr_srcW = %d\n",cbcr_srcW);
1625 }else if(cbcr_srcW > 2560){
1626 win->win_lb_mode = LB_RGB_3840X2;
1627 }else if(cbcr_srcW > 1920){
1628 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1629 if(yrgb_dstW > 3840){
1630 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1631 }else if(yrgb_dstW > 2560){
1632 win->win_lb_mode = LB_RGB_3840X2;
1633 }else if(yrgb_dstW > 1920){
1634 win->win_lb_mode = LB_RGB_2560X4;
1636 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1639 }else if(cbcr_srcW > 1280){
1640 win->win_lb_mode = LB_YUV_3840X5;
1642 win->win_lb_mode = LB_YUV_2560X8;
1646 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1647 if ((yrgb_dstW > 3840) || (yrgb_dstW == 0)) {
1648 pr_err("ERROR yrgb_dstW = %d\n",yrgb_dstW);
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;
1653 }else if(yrgb_dstW > 1280){
1654 win->win_lb_mode = LB_RGB_1920X5;
1656 win->win_lb_mode = LB_RGB_1280X8;
1658 }else{ /*SCALE_UP or SCALE_NONE*/
1659 if ((yrgb_srcW > 3840) || (yrgb_srcW == 0)) {
1660 pr_err("ERROR yrgb_srcW = %d\n",yrgb_srcW);
1661 }else if(yrgb_srcW > 2560){
1662 win->win_lb_mode = LB_RGB_3840X2;
1663 }else if(yrgb_srcW > 1920){
1664 win->win_lb_mode = LB_RGB_2560X4;
1665 }else if(yrgb_srcW > 1280){
1666 win->win_lb_mode = LB_RGB_1920X5;
1668 win->win_lb_mode = LB_RGB_1280X8;
1672 DBG(1,"win->win_lb_mode = %d;\n",win->win_lb_mode);
1674 /*vsd/vsu scale ALGORITHM*/
1675 win->yrgb_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1676 win->cbr_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1677 win->yrgb_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1678 win->cbr_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1679 switch(win->win_lb_mode){
1684 win->yrgb_vsu_mode = SCALE_UP_BIC;
1685 win->cbr_vsu_mode = SCALE_UP_BIC;
1688 if(win->yrgb_ver_scl_mode != SCALE_NONE) {
1689 pr_err("ERROR : not allow yrgb ver scale\n");
1691 if(win->cbr_ver_scl_mode != SCALE_NONE) {
1692 pr_err("ERROR : not allow cbcr ver scale\n");
1696 win->yrgb_vsu_mode = SCALE_UP_BIL;
1697 win->cbr_vsu_mode = SCALE_UP_BIL;
1700 printk(KERN_WARNING "%s:un supported win_lb_mode:%d\n",
1701 __func__,win->win_lb_mode);
1704 DBG(1,"yrgb:hsd=%d,vsd=%d,vsu=%d;cbcr:hsd=%d,vsd=%d,vsu=%d\n",
1705 win->yrgb_hsd_mode,win->yrgb_vsd_mode,win->yrgb_vsu_mode,
1706 win->cbr_hsd_mode,win->cbr_vsd_mode,win->cbr_vsu_mode);
1710 /*(1.1)YRGB HOR SCALE FACTOR*/
1711 switch(win->yrgb_hor_scl_mode){
1713 yrgb_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1716 yrgb_xscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcW, yrgb_dstW);
1719 switch(win->yrgb_hsd_mode)
1721 case SCALE_DOWN_BIL:
1722 yrgb_xscl_factor = GET_SCALE_FACTOR_BILI_DN(yrgb_srcW, yrgb_dstW);
1724 case SCALE_DOWN_AVG:
1725 yrgb_xscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcW, yrgb_dstW);
1728 printk(KERN_WARNING "%s:un supported yrgb_hsd_mode:%d\n",
1729 __func__,win->yrgb_hsd_mode);
1734 printk(KERN_WARNING "%s:un supported yrgb_hor_scl_mode:%d\n",
1735 __func__,win->yrgb_hor_scl_mode);
1737 } /*win->yrgb_hor_scl_mode*/
1739 /*(1.2)YRGB VER SCALE FACTOR*/
1740 switch(win->yrgb_ver_scl_mode)
1743 yrgb_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1746 switch(win->yrgb_vsu_mode)
1749 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_UP(yrgb_srcH, yrgb_dstH);
1753 pr_err("yrgb_srcH should be greater than 3 !!!\n");
1755 yrgb_yscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcH, yrgb_dstH);
1758 printk(KERN_WARNING "%s:un supported yrgb_vsu_mode:%d\n",
1759 __func__,win->yrgb_vsu_mode);
1764 switch(win->yrgb_vsd_mode)
1766 case SCALE_DOWN_BIL:
1767 yrgb_vScaleDnMult = getHardWareVSkipLines(yrgb_srcH, yrgb_dstH);
1768 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(yrgb_srcH, yrgb_dstH, yrgb_vScaleDnMult);
1769 if(yrgb_vScaleDnMult == 4){
1770 yrgb_vsd_bil_gt4 = 1;
1771 yrgb_vsd_bil_gt2 = 0;
1772 }else if(yrgb_vScaleDnMult == 2){
1773 yrgb_vsd_bil_gt4 = 0;
1774 yrgb_vsd_bil_gt2 = 1;
1776 yrgb_vsd_bil_gt4 = 0;
1777 yrgb_vsd_bil_gt2 = 0;
1780 case SCALE_DOWN_AVG:
1781 yrgb_yscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcH, yrgb_dstH);
1784 printk(KERN_WARNING "%s:un supported yrgb_vsd_mode:%d\n",
1785 __func__,win->yrgb_vsd_mode);
1787 } /*win->yrgb_vsd_mode*/
1790 printk(KERN_WARNING "%s:un supported yrgb_ver_scl_mode:%d\n",
1791 __func__,win->yrgb_ver_scl_mode);
1794 win->scale_yrgb_x = yrgb_xscl_factor;
1795 win->scale_yrgb_y = yrgb_yscl_factor;
1796 win->vsd_yrgb_gt4 = yrgb_vsd_bil_gt4;
1797 win->vsd_yrgb_gt2 = yrgb_vsd_bil_gt2;
1798 DBG(1,"yrgb:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",yrgb_xscl_factor,
1799 yrgb_yscl_factor,yrgb_vsd_bil_gt4,yrgb_vsd_bil_gt2);
1801 /*(2.1)CBCR HOR SCALE FACTOR*/
1802 switch(win->cbr_hor_scl_mode)
1805 cbcr_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1808 cbcr_xscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcW, cbcr_dstW);
1811 switch(win->cbr_hsd_mode)
1813 case SCALE_DOWN_BIL:
1814 cbcr_xscl_factor = GET_SCALE_FACTOR_BILI_DN(cbcr_srcW, cbcr_dstW);
1816 case SCALE_DOWN_AVG:
1817 cbcr_xscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcW, cbcr_dstW);
1820 printk(KERN_WARNING "%s:un supported cbr_hsd_mode:%d\n",
1821 __func__,win->cbr_hsd_mode);
1826 printk(KERN_WARNING "%s:un supported cbr_hor_scl_mode:%d\n",
1827 __func__,win->cbr_hor_scl_mode);
1829 } /*win->cbr_hor_scl_mode*/
1831 /*(2.2)CBCR VER SCALE FACTOR*/
1832 switch(win->cbr_ver_scl_mode)
1835 cbcr_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1838 switch(win->cbr_vsu_mode)
1841 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_UP(cbcr_srcH, cbcr_dstH);
1845 pr_err("cbcr_srcH should be greater than 3 !!!\n");
1847 cbcr_yscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcH, cbcr_dstH);
1850 printk(KERN_WARNING "%s:un supported cbr_vsu_mode:%d\n",
1851 __func__,win->cbr_vsu_mode);
1856 switch(win->cbr_vsd_mode)
1858 case SCALE_DOWN_BIL:
1859 cbcr_vScaleDnMult = getHardWareVSkipLines(cbcr_srcH, cbcr_dstH);
1860 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(cbcr_srcH, cbcr_dstH, cbcr_vScaleDnMult);
1861 if(cbcr_vScaleDnMult == 4){
1862 cbcr_vsd_bil_gt4 = 1;
1863 cbcr_vsd_bil_gt2 = 0;
1864 }else if(cbcr_vScaleDnMult == 2){
1865 cbcr_vsd_bil_gt4 = 0;
1866 cbcr_vsd_bil_gt2 = 1;
1868 cbcr_vsd_bil_gt4 = 0;
1869 cbcr_vsd_bil_gt2 = 0;
1872 case SCALE_DOWN_AVG:
1873 cbcr_yscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcH, cbcr_dstH);
1876 printk(KERN_WARNING "%s:un supported cbr_vsd_mode:%d\n",
1877 __func__,win->cbr_vsd_mode);
1882 printk(KERN_WARNING "%s:un supported cbr_ver_scl_mode:%d\n",
1883 __func__,win->cbr_ver_scl_mode);
1886 win->scale_cbcr_x = cbcr_xscl_factor;
1887 win->scale_cbcr_y = cbcr_yscl_factor;
1888 win->vsd_cbr_gt4 = cbcr_vsd_bil_gt4;
1889 win->vsd_cbr_gt2 = cbcr_vsd_bil_gt2;
1891 DBG(1,"cbcr:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",cbcr_xscl_factor,
1892 cbcr_yscl_factor,cbcr_vsd_bil_gt4,cbcr_vsd_bil_gt2);
1898 static int win0_set_par(struct lcdc_device *lcdc_dev,
1899 struct rk_screen *screen, struct rk_lcdc_win *win)
1901 u32 xact,yact,xvir, yvir,xpos, ypos;
1903 char fmt[9] = "NULL";
1905 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
1906 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
1908 spin_lock(&lcdc_dev->reg_lock);
1909 if(likely(lcdc_dev->clk_on)){
1910 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
1911 switch (win->format){
1963 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
1967 win->fmt_cfg = fmt_cfg;
1968 win->area[0].dsp_stx = xpos;
1969 win->area[0].dsp_sty = ypos;
1970 xact = win->area[0].xact;
1971 yact = win->area[0].yact;
1972 xvir = win->area[0].xvir;
1973 yvir = win->area[0].yvir;
1975 rk3288_win_0_1_reg_update(&lcdc_dev->driver,0);
1976 spin_unlock(&lcdc_dev->reg_lock);
1978 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
1979 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
1980 __func__, get_format_string(win->format, fmt), xact,
1981 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
1986 static int win1_set_par(struct lcdc_device *lcdc_dev,
1987 struct rk_screen *screen, struct rk_lcdc_win *win)
1989 u32 xact,yact,xvir, yvir,xpos, ypos;
1991 char fmt[9] = "NULL";
1993 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
1994 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
1996 spin_lock(&lcdc_dev->reg_lock);
1997 if(likely(lcdc_dev->clk_on)){
1998 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
1999 switch (win->format){
2052 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2056 win->fmt_cfg = fmt_cfg;
2057 win->area[0].dsp_stx = xpos;
2058 win->area[0].dsp_sty = ypos;
2059 xact = win->area[0].xact;
2060 yact = win->area[0].yact;
2061 xvir = win->area[0].xvir;
2062 yvir = win->area[0].yvir;
2064 rk3288_win_0_1_reg_update(&lcdc_dev->driver,1);
2065 spin_unlock(&lcdc_dev->reg_lock);
2067 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2068 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2069 __func__, get_format_string(win->format, fmt), xact,
2070 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2075 static int win2_set_par(struct lcdc_device *lcdc_dev,
2076 struct rk_screen *screen, struct rk_lcdc_win *win)
2081 spin_lock(&lcdc_dev->reg_lock);
2082 if(likely(lcdc_dev->clk_on)){
2083 for(i=0;i<win->area_num;i++){
2084 switch (win->format){
2103 dev_err(lcdc_dev->driver.dev,
2104 "%s:un supported format!\n",
2108 win->fmt_cfg = fmt_cfg;
2109 win->area[i].dsp_stx = win->area[i].xpos +
2110 screen->mode.left_margin +
2111 screen->mode.hsync_len;
2112 if (screen->y_mirror == 1) {
2113 win->area[i].dsp_sty = screen->mode.yres -
2115 win->area[i].ysize +
2116 screen->mode.upper_margin +
2117 screen->mode.vsync_len;
2119 win->area[i].dsp_sty = win->area[i].ypos +
2120 screen->mode.upper_margin +
2121 screen->mode.vsync_len;
2125 rk3288_win_2_3_reg_update(&lcdc_dev->driver,2);
2126 spin_unlock(&lcdc_dev->reg_lock);
2130 static int win3_set_par(struct lcdc_device *lcdc_dev,
2131 struct rk_screen *screen, struct rk_lcdc_win *win)
2137 spin_lock(&lcdc_dev->reg_lock);
2138 if(likely(lcdc_dev->clk_on)){
2139 for(i=0;i<win->area_num;i++){
2140 switch (win->format){
2159 dev_err(lcdc_dev->driver.dev,
2160 "%s:un supported format!\n",
2164 win->fmt_cfg = fmt_cfg;
2165 win->area[i].dsp_stx = win->area[i].xpos +
2166 screen->mode.left_margin +
2167 screen->mode.hsync_len;
2168 if (screen->y_mirror == 1) {
2169 win->area[i].dsp_sty = screen->mode.yres -
2171 win->area[i].ysize +
2172 screen->mode.upper_margin +
2173 screen->mode.vsync_len;
2175 win->area[i].dsp_sty = win->area[i].ypos +
2176 screen->mode.upper_margin +
2177 screen->mode.vsync_len;
2181 rk3288_win_2_3_reg_update(&lcdc_dev->driver,3);
2182 spin_unlock(&lcdc_dev->reg_lock);
2186 static int rk3288_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id)
2188 struct lcdc_device *lcdc_dev =
2189 container_of(dev_drv, struct lcdc_device, driver);
2190 struct rk_lcdc_win *win = NULL;
2191 struct rk_screen *screen = dev_drv->cur_screen;
2192 win = dev_drv->win[win_id];
2197 win0_set_par(lcdc_dev, screen, win);
2200 win1_set_par(lcdc_dev, screen, win);
2203 win2_set_par(lcdc_dev, screen, win);
2206 win3_set_par(lcdc_dev, screen, win);
2209 dev_err(dev_drv->dev, "unsupported win number:%d\n", win_id);
2215 static int rk3288_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
2216 unsigned long arg, int win_id)
2218 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2223 void __user *argp = (void __user *)arg;
2224 struct color_key_cfg clr_key_cfg;
2227 case RK_FBIOGET_PANEL_SIZE:
2228 panel_size[0] = lcdc_dev->screen->mode.xres;
2229 panel_size[1] = lcdc_dev->screen->mode.yres;
2230 if (copy_to_user(argp, panel_size, 8))
2233 case RK_FBIOPUT_COLOR_KEY_CFG:
2234 if (copy_from_user(&clr_key_cfg, argp,
2235 sizeof(struct color_key_cfg)))
2237 rk3288_lcdc_clr_key_cfg(dev_drv);
2238 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
2239 clr_key_cfg.win0_color_key_cfg);
2240 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
2241 clr_key_cfg.win1_color_key_cfg);
2250 static int rk3288_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
2253 struct lcdc_device *lcdc_dev =
2254 container_of(dev_drv, struct lcdc_device, driver);
2255 if (dev_drv->suspend_flag)
2258 dev_drv->suspend_flag = 1;
2259 flush_kthread_worker(&dev_drv->update_regs_worker);
2261 for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4)
2262 lcdc_readl(lcdc_dev, reg);
2263 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
2264 dev_drv->trsm_ops->disable();
2266 spin_lock(&lcdc_dev->reg_lock);
2267 if (likely(lcdc_dev->clk_on)) {
2268 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2270 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR | m_LINE_FLAG_INTR_CLR,
2271 v_FS_INTR_CLR(1) | v_LINE_FLAG_INTR_CLR(1));
2272 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2274 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2276 lcdc_cfg_done(lcdc_dev);
2277 spin_unlock(&lcdc_dev->reg_lock);
2279 spin_unlock(&lcdc_dev->reg_lock);
2282 rk3288_lcdc_clk_disable(lcdc_dev);
2283 rk_disp_pwr_disable(dev_drv);
2287 static int rk3288_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
2289 struct lcdc_device *lcdc_dev =
2290 container_of(dev_drv, struct lcdc_device, driver);
2295 if (!dev_drv->suspend_flag)
2297 rk_disp_pwr_enable(dev_drv);
2298 dev_drv->suspend_flag = 0;
2300 if (lcdc_dev->atv_layer_cnt) {
2301 rk3288_lcdc_clk_enable(lcdc_dev);
2302 rk3288_lcdc_reg_restore(lcdc_dev);
2304 spin_lock(&lcdc_dev->reg_lock);
2305 if (dev_drv->cur_screen->dsp_lut) {
2306 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
2308 lcdc_cfg_done(lcdc_dev);
2310 for (i = 0; i < 256; i++) {
2311 v = dev_drv->cur_screen->dsp_lut[i];
2312 c = lcdc_dev->dsp_lut_addr_base + i;
2313 writel_relaxed(v, c);
2315 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
2319 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2321 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2323 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2325 lcdc_cfg_done(lcdc_dev);
2327 spin_unlock(&lcdc_dev->reg_lock);
2330 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
2331 dev_drv->trsm_ops->enable();
2336 static int rk3288_lcdc_blank(struct rk_lcdc_driver *dev_drv,
2337 int win_id, int blank_mode)
2339 switch (blank_mode) {
2340 case FB_BLANK_UNBLANK:
2341 rk3288_lcdc_early_resume(dev_drv);
2343 case FB_BLANK_NORMAL:
2344 rk3288_lcdc_early_suspend(dev_drv);
2347 rk3288_lcdc_early_suspend(dev_drv);
2351 dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
2356 static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
2361 /*overlay will be do at regupdate*/
2362 static int rk3288_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
2365 struct lcdc_device *lcdc_dev =
2366 container_of(dev_drv, struct lcdc_device, driver);
2367 struct rk_lcdc_win *win = NULL;
2369 unsigned int mask, val;
2371 int layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2374 win = dev_drv->win[i];
2375 if(win->state == 1){
2380 win = dev_drv->win[i];
2382 win->z_order = z_order_num++;
2383 switch(win->z_order){
2385 layer0_sel = win->id;
2388 layer1_sel = win->id;
2391 layer2_sel = win->id;
2394 layer3_sel = win->id;
2401 layer0_sel = swap %10;;
2402 layer1_sel = swap /10 % 10;
2403 layer2_sel = swap / 100 %10;
2404 layer3_sel = swap / 1000;
2407 spin_lock(&lcdc_dev->reg_lock);
2408 if(lcdc_dev->clk_on){
2410 mask = m_DSP_LAYER0_SEL | m_DSP_LAYER1_SEL |
2411 m_DSP_LAYER2_SEL | m_DSP_LAYER3_SEL;
2412 val = v_DSP_LAYER0_SEL(layer0_sel) |
2413 v_DSP_LAYER1_SEL(layer1_sel) |
2414 v_DSP_LAYER2_SEL(layer2_sel) |
2415 v_DSP_LAYER3_SEL(layer3_sel);
2416 lcdc_msk_reg(lcdc_dev,DSP_CTRL1,mask,val);
2418 layer0_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER0_SEL);
2419 layer1_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER1_SEL);
2420 layer2_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER2_SEL);
2421 layer3_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER3_SEL);
2422 ovl = layer3_sel*1000 + layer2_sel*100 + layer1_sel *10 + layer0_sel;
2427 spin_unlock(&lcdc_dev->reg_lock);
2432 static ssize_t rk3288_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
2433 char *buf, int win_id)
2435 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2439 struct rk_screen *screen = dev_drv->cur_screen;
2440 u16 hsync_len = screen->mode.hsync_len;
2441 u16 left_margin = screen->mode.left_margin;
2442 u16 vsync_len = screen->mode.vsync_len;
2443 u16 upper_margin = screen->mode.upper_margin;
2444 u32 fmt_id,h_pw_bp,v_pw_bp;
2445 char format_w0[9] = "NULL";
2446 char format_w1[9] = "NULL";
2447 char format_w2[9] = "NULL";
2448 char format_w3[9] = "NULL";
2449 u32 win_ctrl,zorder,vir_info,act_info,dsp_info,dsp_st,y_factor,uv_factor;
2450 u8 layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2451 u8 w0_state,w1_state,w2_state,w3_state;
2452 u8 w2_0_state,w2_1_state,w2_2_state,w2_3_state;
2453 u8 w3_0_state,w3_1_state,w3_2_state,w3_3_state;
2454 h_pw_bp = hsync_len + left_margin;
2455 v_pw_bp = vsync_len + upper_margin;
2457 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;
2458 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;
2459 u32 w0_y_h_fac,w0_y_v_fac,w0_uv_h_fac,w0_uv_v_fac;
2460 u32 w1_y_h_fac,w1_y_v_fac,w1_uv_h_fac,w1_uv_v_fac;
2462 u32 w2_0_vir_y,w2_1_vir_y,w2_2_vir_y,w2_3_vir_y;
2463 u32 w2_0_dsp_x,w2_1_dsp_x,w2_2_dsp_x,w2_3_dsp_x;
2464 u32 w2_0_dsp_y,w2_1_dsp_y,w2_2_dsp_y,w2_3_dsp_y;
2465 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;
2466 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;
2468 u32 w3_0_vir_y,w3_1_vir_y,w3_2_vir_y,w3_3_vir_y;
2469 u32 w3_0_dsp_x,w3_1_dsp_x,w3_2_dsp_x,w3_3_dsp_x;
2470 u32 w3_0_dsp_y,w3_1_dsp_y,w3_2_dsp_y,w3_3_dsp_y;
2471 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;
2472 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;
2475 dclk_freq = screen->mode.pixclock;
2476 /*rk3288_lcdc_reg_dump(dev_drv);*/
2478 spin_lock(&lcdc_dev->reg_lock);
2479 if (lcdc_dev->clk_on) {
2480 zorder = lcdc_readl(lcdc_dev, DSP_CTRL1);
2481 layer0_sel = (zorder & m_DSP_LAYER0_SEL)>>8;
2482 layer1_sel = (zorder & m_DSP_LAYER1_SEL)>>10;
2483 layer2_sel = (zorder & m_DSP_LAYER2_SEL)>>12;
2484 layer3_sel = (zorder & m_DSP_LAYER3_SEL)>>14;
2486 win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
2487 w0_state = win_ctrl & m_WIN0_EN;
2488 fmt_id = (win_ctrl & m_WIN0_DATA_FMT)>>1;
2491 strcpy(format_w0, "ARGB888");
2494 strcpy(format_w0, "RGB888");
2497 strcpy(format_w0, "RGB565");
2500 strcpy(format_w0, "YCbCr420");
2503 strcpy(format_w0, "YCbCr422");
2506 strcpy(format_w0, "YCbCr444");
2509 strcpy(format_w0, "invalid\n");
2512 vir_info = lcdc_readl(lcdc_dev,WIN0_VIR);
2513 act_info = lcdc_readl(lcdc_dev,WIN0_ACT_INFO);
2514 dsp_info = lcdc_readl(lcdc_dev,WIN0_DSP_INFO);
2515 dsp_st = lcdc_readl(lcdc_dev,WIN0_DSP_ST);
2516 y_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_YRGB);
2517 uv_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_CBR);
2518 w0_vir_y = vir_info & m_WIN0_VIR_STRIDE;
2519 w0_vir_uv = (vir_info & m_WIN0_VIR_STRIDE_UV)>>16;
2520 w0_act_x = (act_info & m_WIN0_ACT_WIDTH)+1;
2521 w0_act_y = ((act_info & m_WIN0_ACT_HEIGHT)>>16)+1;
2522 w0_dsp_x = (dsp_info & m_WIN0_DSP_WIDTH)+1;
2523 w0_dsp_y = ((dsp_info & m_WIN0_DSP_HEIGHT)>>16)+1;
2525 w0_st_x = dsp_st & m_WIN0_DSP_XST;
2526 w0_st_y = (dsp_st & m_WIN0_DSP_YST)>>16;
2528 w0_y_h_fac = y_factor & m_WIN0_HS_FACTOR_YRGB;
2529 w0_y_v_fac = (y_factor & m_WIN0_VS_FACTOR_YRGB)>>16;
2530 w0_uv_h_fac = uv_factor & m_WIN0_HS_FACTOR_CBR;
2531 w0_uv_v_fac = (uv_factor & m_WIN0_VS_FACTOR_CBR)>>16;
2534 win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
2535 w1_state = win_ctrl & m_WIN1_EN;
2536 fmt_id = (win_ctrl & m_WIN1_DATA_FMT)>>1;
2539 strcpy(format_w1, "ARGB888");
2542 strcpy(format_w1, "RGB888");
2545 strcpy(format_w1, "RGB565");
2548 strcpy(format_w1, "YCbCr420");
2551 strcpy(format_w1, "YCbCr422");
2554 strcpy(format_w1, "YCbCr444");
2557 strcpy(format_w1, "invalid\n");
2560 vir_info = lcdc_readl(lcdc_dev,WIN1_VIR);
2561 act_info = lcdc_readl(lcdc_dev,WIN1_ACT_INFO);
2562 dsp_info = lcdc_readl(lcdc_dev,WIN1_DSP_INFO);
2563 dsp_st = lcdc_readl(lcdc_dev,WIN1_DSP_ST);
2564 y_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_YRGB);
2565 uv_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_CBR);
2566 w1_vir_y = vir_info & m_WIN1_VIR_STRIDE;
2567 w1_vir_uv = (vir_info & m_WIN1_VIR_STRIDE_UV)>>16;
2568 w1_act_x = (act_info & m_WIN1_ACT_WIDTH)+1;
2569 w1_act_y = ((act_info & m_WIN1_ACT_HEIGHT)>>16)+1;
2570 w1_dsp_x = (dsp_info & m_WIN1_DSP_WIDTH)+1;
2571 w1_dsp_y =((dsp_info & m_WIN1_DSP_HEIGHT)>>16)+1;
2573 w1_st_x = dsp_st & m_WIN1_DSP_XST;
2574 w1_st_y = (dsp_st & m_WIN1_DSP_YST)>>16;
2576 w1_y_h_fac = y_factor & m_WIN1_HS_FACTOR_YRGB;
2577 w1_y_v_fac = (y_factor & m_WIN1_VS_FACTOR_YRGB)>>16;
2578 w1_uv_h_fac = uv_factor & m_WIN1_HS_FACTOR_CBR;
2579 w1_uv_v_fac = (uv_factor & m_WIN1_VS_FACTOR_CBR)>>16;
2581 win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
2582 w2_state = win_ctrl & m_WIN2_EN;
2583 w2_0_state = (win_ctrl & m_WIN2_MST0_EN)>>4;
2584 w2_1_state = (win_ctrl & m_WIN2_MST1_EN)>>5;
2585 w2_2_state = (win_ctrl & m_WIN2_MST2_EN)>>6;
2586 w2_3_state = (win_ctrl & m_WIN2_MST3_EN)>>7;
2587 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR0_1);
2588 w2_0_vir_y = vir_info & m_WIN2_VIR_STRIDE0;
2589 w2_1_vir_y = (vir_info & m_WIN2_VIR_STRIDE1)>>16;
2590 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR2_3);
2591 w2_2_vir_y = vir_info & m_WIN2_VIR_STRIDE2;
2592 w2_3_vir_y = (vir_info & m_WIN2_VIR_STRIDE3)>>16;
2593 fmt_id = (win_ctrl & m_WIN2_DATA_FMT)>>1;
2596 strcpy(format_w2, "ARGB888");
2599 strcpy(format_w2, "RGB888");
2602 strcpy(format_w2, "RGB565");
2605 strcpy(format_w2,"8bpp");
2608 strcpy(format_w2,"4bpp");
2611 strcpy(format_w2,"2bpp");
2614 strcpy(format_w2,"1bpp");
2617 strcpy(format_w2, "invalid\n");
2620 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO0);
2621 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST0);
2622 w2_0_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH0)+1;
2623 w2_0_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT0)>>16)+1;
2625 w2_0_st_x = dsp_st & m_WIN2_DSP_XST0;
2626 w2_0_st_y = (dsp_st & m_WIN2_DSP_YST0)>>16;
2628 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO1);
2629 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST1);
2630 w2_1_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH1)+1;
2631 w2_1_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT1)>>16)+1;
2633 w2_1_st_x = dsp_st & m_WIN2_DSP_XST1;
2634 w2_1_st_y = (dsp_st & m_WIN2_DSP_YST1)>>16;
2636 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO2);
2637 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST2);
2638 w2_2_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH2)+1;
2639 w2_2_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT2)>>16)+1;
2641 w2_2_st_x = dsp_st & m_WIN2_DSP_XST2;
2642 w2_2_st_y = (dsp_st & m_WIN2_DSP_YST2)>>16;
2644 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO3);
2645 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST3);
2646 w2_3_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH3)+1;
2647 w2_3_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT3)>>16)+1;
2649 w2_3_st_x = dsp_st & m_WIN2_DSP_XST3;
2650 w2_3_st_y = (dsp_st & m_WIN2_DSP_YST3)>>16;
2654 win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
2655 w3_state = win_ctrl & m_WIN3_EN;
2656 w3_0_state = (win_ctrl & m_WIN3_MST0_EN)>>4;
2657 w3_1_state = (win_ctrl & m_WIN3_MST1_EN)>>5;
2658 w3_2_state = (win_ctrl & m_WIN3_MST2_EN)>>6;
2659 w3_3_state = (win_ctrl & m_WIN3_MST3_EN)>>7;
2660 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR0_1);
2661 w3_0_vir_y = vir_info & m_WIN3_VIR_STRIDE0;
2662 w3_1_vir_y = (vir_info & m_WIN3_VIR_STRIDE1)>>16;
2663 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR2_3);
2664 w3_2_vir_y = vir_info & m_WIN3_VIR_STRIDE2;
2665 w3_3_vir_y = (vir_info & m_WIN3_VIR_STRIDE3)>>16;
2666 fmt_id = (win_ctrl & m_WIN3_DATA_FMT)>>1;
2669 strcpy(format_w3, "ARGB888");
2672 strcpy(format_w3, "RGB888");
2675 strcpy(format_w3, "RGB565");
2678 strcpy(format_w3,"8bpp");
2681 strcpy(format_w3,"4bpp");
2684 strcpy(format_w3,"2bpp");
2687 strcpy(format_w3,"1bpp");
2690 strcpy(format_w3, "invalid");
2693 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO0);
2694 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST0);
2695 w3_0_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH0)+1;
2696 w3_0_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT0)>>16)+1;
2698 w3_0_st_x = dsp_st & m_WIN3_DSP_XST0;
2699 w3_0_st_y = (dsp_st & m_WIN3_DSP_YST0)>>16;
2702 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO1);
2703 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST1);
2704 w3_1_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH1)+1;
2705 w3_1_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT1)>>16)+1;
2707 w3_1_st_x = dsp_st & m_WIN3_DSP_XST1;
2708 w3_1_st_y = (dsp_st & m_WIN3_DSP_YST1)>>16;
2711 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO2);
2712 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST2);
2713 w3_2_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH2)+1;
2714 w3_2_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT2)>>16)+1;
2716 w3_2_st_x = dsp_st & m_WIN3_DSP_XST2;
2717 w3_2_st_y = (dsp_st & m_WIN3_DSP_YST2)>>16;
2720 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO3);
2721 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST3);
2722 w3_3_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH3)+1;
2723 w3_3_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT3)>>16)+1;
2725 w3_3_st_x = dsp_st & m_WIN3_DSP_XST3;
2726 w3_3_st_y = (dsp_st & m_WIN3_DSP_YST3)>>16;
2730 spin_unlock(&lcdc_dev->reg_lock);
2733 spin_unlock(&lcdc_dev->reg_lock);
2734 return snprintf(buf, PAGE_SIZE,
2736 " layer3_sel_win[%d]\n"
2737 " layer2_sel_win[%d]\n"
2738 " layer1_sel_win[%d]\n"
2739 " layer0_sel_win[%d]\n"
2844 layer3_sel,layer2_sel,layer1_sel,layer0_sel,
2845 w0_state,format_w0,w0_vir_y,w0_vir_uv,w0_act_x,w0_act_y,
2846 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,
2847 w0_uv_v_fac,lcdc_readl(lcdc_dev, WIN0_YRGB_MST),
2848 lcdc_readl(lcdc_dev, WIN0_CBR_MST),
2850 w1_state,format_w1,w1_vir_y,w1_vir_uv,w1_act_x,w1_act_y,
2851 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,
2852 w1_uv_v_fac,lcdc_readl(lcdc_dev, WIN1_YRGB_MST),
2853 lcdc_readl(lcdc_dev, WIN1_CBR_MST),
2856 w2_0_state,w2_0_vir_y,w2_0_dsp_x,w2_0_dsp_y,
2857 w2_0_st_x-h_pw_bp,w2_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST0),
2859 w2_1_state,w2_1_vir_y,w2_1_dsp_x,w2_1_dsp_y,
2860 w2_1_st_x-h_pw_bp,w2_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST1),
2862 w2_2_state,w2_2_vir_y,w2_2_dsp_x,w2_2_dsp_y,
2863 w2_2_st_x-h_pw_bp,w2_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST2),
2865 w2_3_state,w2_3_vir_y,w2_3_dsp_x,w2_3_dsp_y,
2866 w2_3_st_x-h_pw_bp,w2_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST3),
2869 w3_0_state,w3_0_vir_y,w3_0_dsp_x,w3_0_dsp_y,
2870 w3_0_st_x-h_pw_bp,w3_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST0),
2872 w3_1_state,w3_1_vir_y,w3_1_dsp_x,w3_1_dsp_y,
2873 w3_1_st_x-h_pw_bp,w3_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST1),
2875 w3_2_state,w3_2_vir_y,w3_2_dsp_x,w3_2_dsp_y,
2876 w3_2_st_x-h_pw_bp,w3_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST2),
2878 w3_3_state,w3_3_vir_y,w3_3_dsp_x,w3_3_dsp_y,
2879 w3_3_st_x-h_pw_bp,w3_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST3)
2884 static int rk3288_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
2887 struct lcdc_device *lcdc_dev =
2888 container_of(dev_drv, struct lcdc_device, driver);
2889 struct rk_screen *screen = dev_drv->cur_screen;
2894 u32 x_total, y_total;
2896 ft = div_u64(1000000000000llu, fps);
2898 screen->mode.upper_margin + screen->mode.lower_margin +
2899 screen->mode.yres + screen->mode.vsync_len;
2901 screen->mode.left_margin + screen->mode.right_margin +
2902 screen->mode.xres + screen->mode.hsync_len;
2903 dev_drv->pixclock = div_u64(ft, x_total * y_total);
2904 dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
2905 ret = clk_set_rate(lcdc_dev->dclk, dotclk);
2908 pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
2909 dev_drv->pixclock = lcdc_dev->pixclock = pixclock;
2910 fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
2911 screen->ft = 1000 / fps; /*one frame time in ms */
2914 dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
2915 clk_get_rate(lcdc_dev->dclk), fps);
2920 static int rk3288_fb_win_remap(struct rk_lcdc_driver *dev_drv,
2921 enum fb_win_map_order order)
2923 mutex_lock(&dev_drv->fb_win_id_mutex);
2924 if (order == FB_DEFAULT_ORDER)
2925 order = FB0_WIN0_FB1_WIN1_FB2_WIN2_FB3_WIN3;
2926 dev_drv->fb3_win_id = order / 1000;
2927 dev_drv->fb2_win_id = (order / 100) % 10;
2928 dev_drv->fb1_win_id = (order / 10) % 10;
2929 dev_drv->fb0_win_id = order % 10;
2930 mutex_unlock(&dev_drv->fb_win_id_mutex);
2935 static int rk3288_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
2939 mutex_lock(&dev_drv->fb_win_id_mutex);
2940 if (!strcmp(id, "fb0") || !strcmp(id, "fb4"))
2941 win_id = dev_drv->fb0_win_id;
2942 else if (!strcmp(id, "fb1") || !strcmp(id, "fb5"))
2943 win_id = dev_drv->fb1_win_id;
2944 else if (!strcmp(id, "fb2") || !strcmp(id, "fb6"))
2945 win_id = dev_drv->fb2_win_id;
2946 else if (!strcmp(id, "fb3") || !strcmp(id, "fb7"))
2947 win_id = dev_drv->fb3_win_id;
2948 mutex_unlock(&dev_drv->fb_win_id_mutex);
2953 static int rk3288_set_dsp_lut(struct rk_lcdc_driver *dev_drv, int *lut)
2960 struct lcdc_device *lcdc_dev =
2961 container_of(dev_drv, struct lcdc_device, driver);
2962 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
2963 lcdc_cfg_done(lcdc_dev);
2965 if (dev_drv->cur_screen->dsp_lut) {
2966 for (i = 0; i < 256; i++) {
2967 v = dev_drv->cur_screen->dsp_lut[i] = lut[i];
2968 c = lcdc_dev->dsp_lut_addr_base + i;
2969 writel_relaxed(v, c);
2973 dev_err(dev_drv->dev, "no buffer to backup lut data!\n");
2976 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
2977 lcdc_cfg_done(lcdc_dev);
2982 static int rk3288_lcdc_config_done(struct rk_lcdc_driver *dev_drv)
2984 struct lcdc_device *lcdc_dev =
2985 container_of(dev_drv, struct lcdc_device, driver);
2987 unsigned int mask, val;
2988 struct rk_lcdc_win *win = NULL;
2989 spin_lock(&lcdc_dev->reg_lock);
2990 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2991 v_STANDBY_EN(lcdc_dev->standby));
2993 win = dev_drv->win[i];
2994 if ((win->state == 0)&&(win->last_state == 1)) {
2997 lcdc_writel(lcdc_dev,WIN0_CTRL1,0x0);
3000 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask,val);
3003 lcdc_writel(lcdc_dev,WIN1_CTRL1,0x0);
3006 lcdc_msk_reg(lcdc_dev, WIN1_CTRL0, mask,val);
3009 mask = m_WIN2_EN | m_WIN2_MST0_EN | m_WIN2_MST1_EN |
3010 m_WIN2_MST2_EN | m_WIN2_MST3_EN;
3011 val = v_WIN2_EN(0) | v_WIN2_MST0_EN(0) | v_WIN2_MST1_EN(0) |
3012 v_WIN2_MST2_EN(0) | v_WIN2_MST3_EN(0);
3013 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0, mask,val);
3016 mask = m_WIN3_EN | m_WIN3_MST0_EN | m_WIN3_MST1_EN |
3017 m_WIN3_MST2_EN | m_WIN3_MST3_EN;
3018 val = v_WIN3_EN(0) | v_WIN3_MST0_EN(0) | v_WIN3_MST1_EN(0) |
3019 v_WIN3_MST2_EN(0) | v_WIN3_MST3_EN(0);
3020 lcdc_msk_reg(lcdc_dev, WIN3_CTRL0, mask,val);
3026 win->last_state = win->state;
3028 lcdc_cfg_done(lcdc_dev);
3029 spin_unlock(&lcdc_dev->reg_lock);
3034 static int rk3288_lcdc_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
3036 struct lcdc_device *lcdc_dev =
3037 container_of(dev_drv, struct lcdc_device, driver);
3038 spin_lock(&lcdc_dev->reg_lock);
3039 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN,
3040 v_DIRECT_PATH_EN(open));
3041 lcdc_cfg_done(lcdc_dev);
3042 spin_unlock(&lcdc_dev->reg_lock);
3046 static int rk3288_lcdc_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id)
3048 struct lcdc_device *lcdc_dev = container_of(dev_drv,
3049 struct lcdc_device, driver);
3050 spin_lock(&lcdc_dev->reg_lock);
3051 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATCH_SEL,
3052 v_DIRECT_PATCH_SEL(win_id));
3053 lcdc_cfg_done(lcdc_dev);
3054 spin_unlock(&lcdc_dev->reg_lock);
3059 static int rk3288_lcdc_dpi_status(struct rk_lcdc_driver *dev_drv)
3061 struct lcdc_device *lcdc_dev =
3062 container_of(dev_drv, struct lcdc_device, driver);
3064 spin_lock(&lcdc_dev->reg_lock);
3065 ovl = lcdc_read_bit(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN);
3066 spin_unlock(&lcdc_dev->reg_lock);
3069 static int rk3288_lcdc_set_irq_to_cpu(struct rk_lcdc_driver * dev_drv,int enable)
3071 struct lcdc_device *lcdc_dev =
3072 container_of(dev_drv,struct lcdc_device,driver);
3074 enable_irq(lcdc_dev->irq);
3076 disable_irq(lcdc_dev->irq);
3080 int rk3288_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
3082 struct lcdc_device *lcdc_dev =
3083 container_of(dev_drv, struct lcdc_device, driver);
3087 if (lcdc_dev->clk_on &&(!dev_drv->suspend_flag)){
3088 int_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3089 if (int_reg & m_LINE_FLAG_INTR_STS) {
3090 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3091 v_LINE_FLAG_INTR_CLR(1));
3092 ret = RK_LF_STATUS_FC;
3094 ret = RK_LF_STATUS_FR;
3096 ret = RK_LF_STATUS_NC;
3101 static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,unsigned int *dsp_addr)
3103 struct lcdc_device *lcdc_dev =
3104 container_of(dev_drv, struct lcdc_device, driver);
3105 spin_lock(&lcdc_dev->reg_lock);
3106 if(lcdc_dev->clk_on){
3107 dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
3108 dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
3109 dsp_addr[2] = lcdc_readl(lcdc_dev, WIN2_MST0);
3110 dsp_addr[3] = lcdc_readl(lcdc_dev, WIN3_MST0);
3112 spin_unlock(&lcdc_dev->reg_lock);
3116 static int rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv,int mode)
3118 struct lcdc_device *lcdc_dev =
3119 container_of(dev_drv, struct lcdc_device, driver);
3120 struct rk_screen *screen = dev_drv->cur_screen;
3121 int total_pixel,calc_pixel,stage_up,stage_down;
3124 u32 cabc_mode[5][3]={
3126 {2, 10, 10}, /*mode 1*/
3127 {4, 10, 10}, /*mode 2*/
3128 {6, 10, 10}, /*mode 3*/
3129 {8, 10, 10}, /*mode 4*/
3130 {10, 10, 10}, /*mode 5*/
3132 /*iomux connect to vop or pwm*/
3134 DBG(3,"close cabc\n");
3136 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);/*pwm sel*/
3137 lcdc_set_bit(lcdc_dev, SYS_CTRL, 0<<23);/*disable auto gating*/
3140 lcdc_set_bit(lcdc_dev, SYS_CTRL, m_AUTO_GATING_EN);
3141 /*lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);*/
3144 total_pixel = screen->mode.xres * screen->mode.yres;
3145 calc_pixel = total_pixel * (100 - cabc_mode[mode-1][0])/100;
3146 stage_up = cabc_mode[mode-1][1];
3147 stage_down = cabc_mode[mode-1][2];
3149 spin_lock(&lcdc_dev->reg_lock);
3150 if(lcdc_dev->clk_on){
3151 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
3152 mask = m_CABC_TOTAL_NUM | m_CABC_STAGE_DOWN;
3153 val = v_CABC_TOTAL_NUM(total_pixel) | v_CABC_STAGE_DOWN(stage_down);
3154 lcdc_msk_reg(lcdc_dev, CABC_CTRL1, mask, val);
3156 mask = m_CABC_EN | m_CABC_CALC_PIXEL_NUM |
3158 val = v_CABC_EN(1) | v_CABC_CALC_PIXEL_NUM(calc_pixel) |
3159 v_CABC_STAGE_UP(stage_up);
3160 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
3161 lcdc_cfg_done(lcdc_dev);
3163 spin_unlock(&lcdc_dev->reg_lock);
3165 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);/*pwm sel*/
3169 Sin0=*0.000???????? Cos0=*1.000
3170 Sin5=*0.087???????C Cos5=*0.996
3171 Sin10=*0.174 Cos10=*0.985
3172 Sin15=*0.259 ???????CCos15=*0.966
3173 Sin20=*0.342????????Cos20=*0.940
3174 Sin25=*0.422????????Cos25=*0.906
3175 Sin30=*0.500????????Cos30=*0.866
3177 static int rk3288_lcdc_set_hue(struct rk_lcdc_driver *dev_drv,int hue)
3180 struct lcdc_device *lcdc_dev =
3181 container_of(dev_drv, struct lcdc_device, driver);
3182 int sin_hue_val,cos_hue_val;
3185 int sin_hue[7]={0,22, 44, 66, 87, 108, 128};
3186 int cos_hue[7]={256,254,252,247,240,231,221};
3188 if((hue > 0)&&(hue <= 30)){
3189 /*sin_hue_val = (int)sin_hue[hue] * 256;
3190 cos_hue_val = (int)cos_hue[hue] * 256;*/
3192 sin_hue_val = sin_hue[hue];
3193 cos_hue_val = cos_hue[hue];
3194 }else if((hue > 30)&&(hue <= 60)){
3197 /*sin_hue_val = (int)sin_hue[hue] * 256 + 0x100;
3198 cos_hue_val = (int)cos_hue[hue] * 256 + 0x100;*/
3199 sin_hue_val = sin_hue[hue] + 0x100;
3200 cos_hue_val = cos_hue[hue] + 0x100;
3202 dev_warn(lcdc_dev->dev,"hue=%d should be [0:60]\n",hue);
3205 spin_lock(&lcdc_dev->reg_lock);
3206 if(lcdc_dev->clk_on){
3208 mask = m_BCSH_OUT_MODE;
3209 val = v_BCSH_OUT_MODE(3);
3210 lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
3212 mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
3213 val = v_BCSH_SIN_HUE(sin_hue_val) | v_BCSH_COS_HUE(cos_hue_val);
3214 lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
3218 lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
3219 lcdc_cfg_done(lcdc_dev);
3221 spin_unlock(&lcdc_dev->reg_lock);
3226 static int rk3288_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,int bri,int con,int sat)
3228 struct lcdc_device *lcdc_dev =
3229 container_of(dev_drv, struct lcdc_device, driver);
3232 spin_lock(&lcdc_dev->reg_lock);
3233 if(lcdc_dev->clk_on){
3234 mask = m_BCSH_OUT_MODE | m_BCSH_BRIGHTNESS |
3235 m_BCSH_CONTRAST | m_BCSH_SAT_CON;
3236 val = v_BCSH_OUT_MODE(3) | v_BCSH_BRIGHTNESS(bri) |
3237 v_BCSH_CONTRAST(con) | v_BCSH_SAT_CON(sat);
3238 lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
3242 lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
3243 lcdc_cfg_done(lcdc_dev);
3245 spin_unlock(&lcdc_dev->reg_lock);
3250 static struct rk_lcdc_win lcdc_win[] = {
3254 .support_3d = false,
3259 .support_3d = false,
3264 .support_3d = false,
3269 .support_3d = false,
3273 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
3274 .open = rk3288_lcdc_open,
3275 .win_direct_en = rk3288_lcdc_win_direct_en,
3276 .load_screen = rk3288_load_screen,
3277 .set_par = rk3288_lcdc_set_par,
3278 .pan_display = rk3288_lcdc_pan_display,
3279 .direct_set_addr = rk3288_lcdc_direct_set_win_addr,
3280 .lcdc_reg_update = rk3288_lcdc_reg_update,
3281 .blank = rk3288_lcdc_blank,
3282 .ioctl = rk3288_lcdc_ioctl,
3283 .suspend = rk3288_lcdc_early_suspend,
3284 .resume = rk3288_lcdc_early_resume,
3285 .get_win_state = rk3288_lcdc_get_win_state,
3286 .ovl_mgr = rk3288_lcdc_ovl_mgr,
3287 .get_disp_info = rk3288_lcdc_get_disp_info,
3288 .fps_mgr = rk3288_lcdc_fps_mgr,
3289 .fb_get_win_id = rk3288_lcdc_get_win_id,
3290 .fb_win_remap = rk3288_fb_win_remap,
3291 .set_dsp_lut = rk3288_set_dsp_lut,
3292 .poll_vblank = rk3288_lcdc_poll_vblank,
3293 .dpi_open = rk3288_lcdc_dpi_open,
3294 .dpi_win_sel = rk3288_lcdc_dpi_win_sel,
3295 .dpi_status = rk3288_lcdc_dpi_status,
3296 .get_dsp_addr = rk3288_lcdc_get_dsp_addr,
3297 .set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
3298 .set_dsp_hue = rk3288_lcdc_set_hue,
3299 .set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
3300 .dump_reg = rk3288_lcdc_reg_dump,
3301 .cfg_done = rk3288_lcdc_config_done,
3302 .set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,
3304 static int rk3288_lcdc_parse_irq(struct lcdc_device *lcdc_dev,unsigned int reg_val)
3306 if (reg_val & m_WIN0_EMPTY_INTR_STS) {
3307 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN0_EMPTY_INTR_CLR,
3308 v_WIN0_EMPTY_INTR_CLR(1));
3309 dev_warn(lcdc_dev->dev,"win0 empty irq!");
3310 }else if (reg_val & m_WIN1_EMPTY_INTR_STS) {
3311 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN1_EMPTY_INTR_CLR,
3312 v_WIN1_EMPTY_INTR_CLR(1));
3313 dev_warn(lcdc_dev->dev,"win1 empty irq!");
3314 }else if (reg_val & m_WIN2_EMPTY_INTR_STS) {
3315 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN2_EMPTY_INTR_CLR,
3316 v_WIN2_EMPTY_INTR_CLR(1));
3317 dev_warn(lcdc_dev->dev,"win2 empty irq!");
3318 }else if (reg_val & m_WIN3_EMPTY_INTR_STS) {
3319 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN3_EMPTY_INTR_CLR,
3320 v_WIN3_EMPTY_INTR_CLR(1));
3321 dev_warn(lcdc_dev->dev,"win3 empty irq!");
3322 }else if (reg_val & m_HWC_EMPTY_INTR_STS) {
3323 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_HWC_EMPTY_INTR_CLR,
3324 v_HWC_EMPTY_INTR_CLR(1));
3325 dev_warn(lcdc_dev->dev,"HWC empty irq!");
3326 }else if (reg_val & m_POST_BUF_EMPTY_INTR_STS) {
3327 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_POST_BUF_EMPTY_INTR_CLR,
3328 v_POST_BUF_EMPTY_INTR_CLR(1));
3329 dev_warn(lcdc_dev->dev,"post buf empty irq!");
3330 }else if (reg_val & m_PWM_GEN_INTR_STS) {
3331 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_PWM_GEN_INTR_CLR,
3332 v_PWM_GEN_INTR_CLR(1));
3333 dev_warn(lcdc_dev->dev,"PWM gen irq!");
3338 static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
3340 struct lcdc_device *lcdc_dev =
3341 (struct lcdc_device *)dev_id;
3342 ktime_t timestamp = ktime_get();
3344 intr0_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3346 if(intr0_reg & m_FS_INTR_STS){
3347 timestamp = ktime_get();
3348 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR,
3350 /*if(lcdc_dev->driver.wait_fs){ */
3352 spin_lock(&(lcdc_dev->driver.cpl_lock));
3353 complete(&(lcdc_dev->driver.frame_done));
3354 spin_unlock(&(lcdc_dev->driver.cpl_lock));
3356 #ifdef CONFIG_DRM_ROCKCHIP
3357 lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
3359 lcdc_dev->driver.vsync_info.timestamp = timestamp;
3360 wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
3362 }else if(intr0_reg & m_LINE_FLAG_INTR_STS){
3363 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3364 v_LINE_FLAG_INTR_CLR(1));
3365 }else if(intr0_reg & m_BUS_ERROR_INTR_STS){
3366 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_BUS_ERROR_INTR_CLR,
3367 v_BUS_ERROR_INTR_CLR(1));
3368 dev_warn(lcdc_dev->dev,"buf_error_int!");
3373 intr1_reg = lcdc_readl(lcdc_dev, INTR_CTRL1);
3375 rk3288_lcdc_parse_irq(lcdc_dev,intr1_reg);
3381 #if defined(CONFIG_PM)
3382 static int rk3288_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
3387 static int rk3288_lcdc_resume(struct platform_device *pdev)
3392 #define rk3288_lcdc_suspend NULL
3393 #define rk3288_lcdc_resume NULL
3396 static int rk3288_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
3398 struct device_node *np = lcdc_dev->dev->of_node;
3400 if (of_property_read_u32(np, "rockchip,prop", &val))
3401 lcdc_dev->prop = PRMRY; /*default set it as primary */
3403 lcdc_dev->prop = val;
3405 if (of_property_read_u32(np, "rockchip,pwr18", &val))
3406 lcdc_dev->pwr18 = false; /*default set it as 3.xv power supply */
3408 lcdc_dev->pwr18 = (val ? true : false);
3409 #if defined(CONFIG_ROCKCHIP_IOMMU)
3410 if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
3411 lcdc_dev->driver.iommu_enabled = 0;
3413 lcdc_dev->driver.iommu_enabled = val;
3415 lcdc_dev->driver.iommu_enabled = 0;
3420 static int rk3288_lcdc_probe(struct platform_device *pdev)
3422 struct lcdc_device *lcdc_dev = NULL;
3423 struct rk_lcdc_driver *dev_drv;
3424 struct device *dev = &pdev->dev;
3425 struct resource *res;
3426 struct device_node *np = pdev->dev.of_node;
3430 /*if the primary lcdc has not registered ,the extend
3431 lcdc register later */
3432 of_property_read_u32(np, "rockchip,prop", &prop);
3433 if (prop == EXTEND) {
3434 if (!is_prmry_rk_lcdc_registered())
3435 return -EPROBE_DEFER;
3437 lcdc_dev = devm_kzalloc(dev,
3438 sizeof(struct lcdc_device), GFP_KERNEL);
3440 dev_err(&pdev->dev, "rk3288 lcdc device kmalloc fail!");
3443 platform_set_drvdata(pdev, lcdc_dev);
3444 lcdc_dev->dev = dev;
3445 rk3288_lcdc_parse_dt(lcdc_dev);
3446 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3447 lcdc_dev->reg_phy_base = res->start;
3448 lcdc_dev->len = resource_size(res);
3449 lcdc_dev->regs = devm_ioremap_resource(dev, res);
3450 if (IS_ERR(lcdc_dev->regs))
3451 return PTR_ERR(lcdc_dev->regs);
3453 lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
3454 if (IS_ERR(lcdc_dev->regsbak))
3455 return PTR_ERR(lcdc_dev->regsbak);
3456 lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs + GAMMA_LUT_ADDR);
3457 lcdc_dev->id = rk3288_lcdc_get_id(lcdc_dev->reg_phy_base);
3458 if (lcdc_dev->id < 0) {
3459 dev_err(&pdev->dev, "no such lcdc device!\n");
3462 dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
3463 dev_drv = &lcdc_dev->driver;
3465 dev_drv->prop = prop;
3466 dev_drv->id = lcdc_dev->id;
3467 dev_drv->ops = &lcdc_drv_ops;
3468 dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
3469 spin_lock_init(&lcdc_dev->reg_lock);
3471 lcdc_dev->irq = platform_get_irq(pdev, 0);
3472 if (lcdc_dev->irq < 0) {
3473 dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
3478 ret = devm_request_irq(dev, lcdc_dev->irq, rk3288_lcdc_isr,
3479 IRQF_DISABLED | IRQF_SHARED, dev_name(dev), lcdc_dev);
3481 dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
3482 lcdc_dev->irq, ret);
3486 if (dev_drv->iommu_enabled) {
3487 if(lcdc_dev->id == 0){
3488 strcpy(dev_drv->mmu_dts_name, "iommu,vopb_mmu");
3490 strcpy(dev_drv->mmu_dts_name, "iommu,vopl_mmu");
3494 ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
3496 dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
3499 lcdc_dev->screen = dev_drv->screen0;
3501 dev_info(dev, "lcdc%d probe ok, iommu %s\n",
3502 lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
3507 static int rk3288_lcdc_remove(struct platform_device *pdev)
3513 static void rk3288_lcdc_shutdown(struct platform_device *pdev)
3515 struct lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
3517 rk3288_lcdc_deint(lcdc_dev);
3518 rk_disp_pwr_disable(&lcdc_dev->driver);
3521 #if defined(CONFIG_OF)
3522 static const struct of_device_id rk3288_lcdc_dt_ids[] = {
3523 {.compatible = "rockchip,rk3288-lcdc",},
3528 static struct platform_driver rk3288_lcdc_driver = {
3529 .probe = rk3288_lcdc_probe,
3530 .remove = rk3288_lcdc_remove,
3532 .name = "rk3288-lcdc",
3533 .owner = THIS_MODULE,
3534 .of_match_table = of_match_ptr(rk3288_lcdc_dt_ids),
3536 .suspend = rk3288_lcdc_suspend,
3537 .resume = rk3288_lcdc_resume,
3538 .shutdown = rk3288_lcdc_shutdown,
3541 static int __init rk3288_lcdc_module_init(void)
3543 return platform_driver_register(&rk3288_lcdc_driver);
3546 static void __exit rk3288_lcdc_module_exit(void)
3548 platform_driver_unregister(&rk3288_lcdc_driver);
3551 fs_initcall(rk3288_lcdc_module_init);
3552 module_exit(rk3288_lcdc_module_exit);