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_screen *screen = lcdc_dev->driver.cur_screen;
286 u32 h_pw_bp = screen->mode.hsync_len + screen->mode.left_margin;
287 u32 v_pw_bp = screen->mode.vsync_len + screen->mode.upper_margin;
289 struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
291 spin_lock(&lcdc_dev->reg_lock);
292 for (reg = 0; reg < FRC_LOWER11_1; reg += 4) {
293 val = lcdc_readl(lcdc_dev, reg);
297 (val & m_WIN0_ACT_WIDTH) + 1;
299 ((val & m_WIN0_ACT_HEIGHT) >> 16) + 1;
302 win0->area[0].xsize =
303 (val & m_WIN0_DSP_WIDTH) + 1;
304 win0->area[0].ysize =
305 ((val & m_WIN0_DSP_HEIGHT) >> 16) + 1;
308 st_x = val & m_WIN0_DSP_XST;
309 st_y = (val & m_WIN0_DSP_YST) >> 16;
310 win0->area[0].xpos = st_x - h_pw_bp;
311 win0->area[0].ypos = st_y - v_pw_bp;
314 win0->state = val & m_WIN0_EN;
315 win0->area[0].fmt_cfg =
316 (val & m_WIN0_DATA_FMT) >> 1;
317 win0->fmt_10 = (val & m_WIN0_FMT_10) >> 4;
318 win0->area[0].format = win0->area[0].fmt_cfg;
321 win0->area[0].y_vir_stride =
322 val & m_WIN0_VIR_STRIDE;
323 win0->area[0].uv_vir_stride =
324 (val & m_WIN0_VIR_STRIDE_UV) >> 16;
325 if (win0->area[0].format == ARGB888)
327 win0->area[0].y_vir_stride;
328 else if (win0->area[0].format == RGB888)
330 win0->area[0].y_vir_stride * 4 / 3;
331 else if (win0->area[0].format == RGB565)
333 2 * win0->area[0].y_vir_stride;
336 4 * win0->area[0].y_vir_stride;
339 win0->area[0].smem_start = val;
342 win0->area[0].cbr_start = val;
348 spin_unlock(&lcdc_dev->reg_lock);
352 /********do basic init*********/
353 static int rk3288_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
357 struct lcdc_device *lcdc_dev = container_of(dev_drv,
361 if (lcdc_dev->pre_init)
364 lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
365 lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
366 lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
367 lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
369 if (IS_ERR(lcdc_dev->pd) || (IS_ERR(lcdc_dev->aclk)) ||
370 (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
371 dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
374 if (!support_uboot_display())
375 rk_disp_pwr_enable(dev_drv);
376 rk3288_lcdc_clk_enable(lcdc_dev);
378 /*backup reg config at uboot*/
379 lcdc_read_reg_defalut_cfg(lcdc_dev);
381 #ifndef CONFIG_RK_FPGA
382 if (lcdc_dev->pwr18 == true) {
383 v = 0x00010001; /*bit14: 1,1.8v;0,3.3v*/
384 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
387 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
390 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_0,0x15110903);
391 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_1,0x00030911);
392 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_0,0x1a150b04);
393 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_1,0x00040b15);
394 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_0,0x15110903);
395 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_1,0x00030911);
397 lcdc_writel(lcdc_dev,FRC_LOWER01_0,0x12844821);
398 lcdc_writel(lcdc_dev,FRC_LOWER01_1,0x21488412);
399 lcdc_writel(lcdc_dev,FRC_LOWER10_0,0xa55a9696);
400 lcdc_writel(lcdc_dev,FRC_LOWER10_1,0x5aa56969);
401 lcdc_writel(lcdc_dev,FRC_LOWER11_0,0xdeb77deb);
402 lcdc_writel(lcdc_dev,FRC_LOWER11_1,0xed7bb7de);
404 mask = m_AUTO_GATING_EN;
405 val = v_AUTO_GATING_EN(0);
406 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val);
407 lcdc_cfg_done(lcdc_dev);
408 /*disable win0 to workaround iommu pagefault */
409 /*if (dev_drv->iommu_enabled) */
410 /* win0_enable(lcdc_dev, 0); */
411 lcdc_dev->pre_init = true;
417 static void rk3288_lcdc_deint(struct lcdc_device *lcdc_dev)
421 rk3288_lcdc_disable_irq(lcdc_dev);
422 spin_lock(&lcdc_dev->reg_lock);
423 if (likely(lcdc_dev->clk_on)) {
424 lcdc_dev->clk_on = 0;
425 lcdc_set_bit(lcdc_dev, SYS_CTRL, m_STANDBY_EN);
426 lcdc_cfg_done(lcdc_dev);
427 spin_unlock(&lcdc_dev->reg_lock);
429 spin_unlock(&lcdc_dev->reg_lock);
433 static int rk3288_lcdc_post_cfg(struct rk_lcdc_driver *dev_drv)
435 struct lcdc_device *lcdc_dev =
436 container_of(dev_drv, struct lcdc_device, driver);
437 struct rk_screen *screen = dev_drv->cur_screen;
438 u16 x_res = screen->mode.xres;
439 u16 y_res = screen->mode.yres;
442 u16 post_hsd_en,post_vsd_en;
443 u16 post_dsp_hact_st,post_dsp_hact_end;
444 u16 post_dsp_vact_st,post_dsp_vact_end;
445 u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
446 u16 post_h_fac,post_v_fac;
448 screen->post_dsp_stx = x_res * (100 - dev_drv->overscan.left) / 200;
449 screen->post_dsp_sty = y_res * (100 - dev_drv->overscan.top) / 200;
450 screen->post_xsize = x_res *
451 (dev_drv->overscan.left + dev_drv->overscan.right) / 200;
452 screen->post_ysize = y_res *
453 (dev_drv->overscan.top + dev_drv->overscan.bottom) / 200;
454 h_total = screen->mode.hsync_len+screen->mode.left_margin +
455 x_res + screen->mode.right_margin;
456 v_total = screen->mode.vsync_len+screen->mode.upper_margin +
457 y_res + screen->mode.lower_margin;
459 if(screen->post_dsp_stx + screen->post_xsize > x_res){
460 dev_warn(lcdc_dev->dev, "post:stx[%d] + xsize[%d] > x_res[%d]\n",
461 screen->post_dsp_stx,screen->post_xsize,x_res);
462 screen->post_dsp_stx = x_res - screen->post_xsize;
464 if(screen->x_mirror == 0){
465 post_dsp_hact_st=screen->post_dsp_stx +
466 screen->mode.hsync_len+screen->mode.left_margin;
467 post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize;
469 post_dsp_hact_end = h_total - screen->mode.right_margin -
470 screen->post_dsp_stx;
471 post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize;
473 if((screen->post_xsize < x_res)&&(screen->post_xsize != 0)){
476 GET_SCALE_FACTOR_BILI_DN(x_res , screen->post_xsize);
483 if(screen->post_dsp_sty + screen->post_ysize > y_res){
484 dev_warn(lcdc_dev->dev, "post:sty[%d] + ysize[%d] > y_res[%d]\n",
485 screen->post_dsp_sty,screen->post_ysize,y_res);
486 screen->post_dsp_sty = y_res - screen->post_ysize;
489 if(screen->y_mirror == 0){
490 post_dsp_vact_st = screen->post_dsp_sty +
491 screen->mode.vsync_len+screen->mode.upper_margin;
492 post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
494 post_dsp_vact_end = v_total - screen->mode.lower_margin -
495 - screen->post_dsp_sty;
496 post_dsp_vact_st = post_dsp_vact_end - screen->post_ysize;
498 if((screen->post_ysize < y_res)&&(screen->post_ysize != 0)){
500 post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res, screen->post_ysize);
506 if(screen->interlace == 1){
507 post_dsp_vact_st_f1 = v_total + post_dsp_vact_st;
508 post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
510 post_dsp_vact_st_f1 = 0;
511 post_dsp_vact_end_f1 = 0;
513 DBG(1,"post:xsize=%d,ysize=%d,xpos=%d,ypos=%d,"
514 "hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n",
515 screen->post_xsize,screen->post_ysize,screen->xpos,screen->ypos,
516 post_hsd_en,post_h_fac,post_vsd_en,post_v_fac);
517 mask = m_DSP_HACT_END_POST | m_DSP_HACT_ST_POST;
518 val = v_DSP_HACT_END_POST(post_dsp_hact_end) |
519 v_DSP_HACT_ST_POST(post_dsp_hact_st);
520 lcdc_msk_reg(lcdc_dev, POST_DSP_HACT_INFO, mask, val);
522 mask = m_DSP_VACT_END_POST | m_DSP_VACT_ST_POST;
523 val = v_DSP_VACT_END_POST(post_dsp_vact_end) |
524 v_DSP_VACT_ST_POST(post_dsp_vact_st);
525 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO, mask, val);
527 mask = m_POST_HS_FACTOR_YRGB | m_POST_VS_FACTOR_YRGB;
528 val = v_POST_HS_FACTOR_YRGB(post_h_fac) |
529 v_POST_VS_FACTOR_YRGB(post_v_fac);
530 lcdc_msk_reg(lcdc_dev, POST_SCL_FACTOR_YRGB, mask, val);
532 mask = m_DSP_VACT_END_POST_F1 | m_DSP_VACT_ST_POST_F1;
533 val = v_DSP_VACT_END_POST_F1(post_dsp_vact_end_f1) |
534 v_DSP_VACT_ST_POST_F1(post_dsp_vact_st_f1);
535 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO_F1, mask, val);
537 mask = m_POST_HOR_SD_EN | m_POST_VER_SD_EN;
538 val = v_POST_HOR_SD_EN(post_hsd_en) | v_POST_VER_SD_EN(post_vsd_en);
539 lcdc_msk_reg(lcdc_dev, POST_SCL_CTRL, mask, val);
543 static int rk3288_lcdc_clr_key_cfg(struct rk_lcdc_driver *dev_drv)
545 struct lcdc_device *lcdc_dev = container_of(dev_drv,
549 struct rk_lcdc_win *win;
550 u32 colorkey_r,colorkey_g,colorkey_b;
553 win = dev_drv->win[i];
554 key_val = win->color_key_val;
555 colorkey_r = (key_val & 0xff)<<2;
556 colorkey_g = ((key_val>>8)&0xff)<<12;
557 colorkey_b = ((key_val>>16)&0xff)<<22;
558 /*color key dither 565/888->aaa*/
559 key_val = colorkey_r | colorkey_g | colorkey_b;
562 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY, key_val);
565 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY, key_val);
568 lcdc_writel(lcdc_dev, WIN2_COLOR_KEY, key_val);
571 lcdc_writel(lcdc_dev, WIN3_COLOR_KEY, key_val);
574 printk(KERN_WARNING "%s:un support win num:%d\n",
582 static int rk3288_lcdc_alpha_cfg(struct rk_lcdc_driver *dev_drv,int win_id)
584 struct lcdc_device *lcdc_dev =
585 container_of(dev_drv, struct lcdc_device, driver);
586 struct rk_lcdc_win *win = dev_drv->win[win_id];
587 struct alpha_config alpha_config;
590 int ppixel_alpha,global_alpha;
591 u32 src_alpha_ctl,dst_alpha_ctl;
592 ppixel_alpha = ((win->area[0].format == ARGB888) ||
593 (win->area[0].format == ABGR888)) ? 1 : 0;
594 global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
595 alpha_config.src_global_alpha_val = win->g_alpha_val;
596 win->alpha_mode = AB_SRC_OVER;
597 /*printk("%s,alpha_mode=%d,alpha_en=%d,ppixel_a=%d,gla_a=%d\n",
598 __func__,win->alpha_mode,win->alpha_en,ppixel_alpha,global_alpha);*/
599 switch(win->alpha_mode){
603 alpha_config.src_factor_mode=AA_ZERO;
604 alpha_config.dst_factor_mode=AA_ZERO;
607 alpha_config.src_factor_mode=AA_ONE;
608 alpha_config.dst_factor_mode=AA_ZERO;
611 alpha_config.src_factor_mode=AA_ZERO;
612 alpha_config.dst_factor_mode=AA_ONE;
615 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
617 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
619 alpha_config.src_factor_mode=AA_ONE;
620 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
623 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
624 alpha_config.src_factor_mode=AA_SRC_INVERSE;
625 alpha_config.dst_factor_mode=AA_ONE;
628 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
629 alpha_config.src_factor_mode=AA_SRC;
630 alpha_config.dst_factor_mode=AA_ZERO;
633 alpha_config.src_factor_mode=AA_ZERO;
634 alpha_config.dst_factor_mode=AA_SRC;
637 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
638 alpha_config.src_factor_mode=AA_SRC_INVERSE;
639 alpha_config.dst_factor_mode=AA_ZERO;
642 alpha_config.src_factor_mode=AA_ZERO;
643 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
646 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
647 alpha_config.src_factor_mode=AA_SRC;
648 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
651 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
652 alpha_config.src_factor_mode=AA_SRC_INVERSE;
653 alpha_config.dst_factor_mode=AA_SRC;
656 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
657 alpha_config.src_factor_mode=AA_SRC_INVERSE;
658 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
660 case AB_SRC_OVER_GLOBAL:
661 alpha_config.src_global_alpha_mode=AA_PER_PIX_GLOBAL;
662 alpha_config.src_color_mode=AA_SRC_NO_PRE_MUL;
663 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
664 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
667 pr_err("alpha mode error\n");
670 if((ppixel_alpha == 1)&&(global_alpha == 1)){
671 alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL;
672 }else if(ppixel_alpha == 1){
673 alpha_config.src_global_alpha_mode = AA_PER_PIX;
674 }else if(global_alpha == 1){
675 alpha_config.src_global_alpha_mode = AA_GLOBAL;
677 dev_warn(lcdc_dev->dev,"alpha_en should be 0\n");
679 alpha_config.src_alpha_mode = AA_STRAIGHT;
680 alpha_config.src_alpha_cal_m0 = AA_NO_SAT;
684 src_alpha_ctl = 0x60;
685 dst_alpha_ctl = 0x64;
688 src_alpha_ctl = 0xa0;
689 dst_alpha_ctl = 0xa4;
692 src_alpha_ctl = 0xdc;
693 dst_alpha_ctl = 0xec;
696 src_alpha_ctl = 0x12c;
697 dst_alpha_ctl = 0x13c;
700 mask = m_WIN0_DST_FACTOR_M0;
701 val = v_WIN0_DST_FACTOR_M0(alpha_config.dst_factor_mode);
702 lcdc_msk_reg(lcdc_dev, dst_alpha_ctl, mask, val);
703 mask = m_WIN0_SRC_ALPHA_EN | m_WIN0_SRC_COLOR_M0 |
704 m_WIN0_SRC_ALPHA_M0 | m_WIN0_SRC_BLEND_M0 |
705 m_WIN0_SRC_ALPHA_CAL_M0 | m_WIN0_SRC_FACTOR_M0|
706 m_WIN0_SRC_GLOBAL_ALPHA;
707 val = v_WIN0_SRC_ALPHA_EN(1) |
708 v_WIN0_SRC_COLOR_M0(alpha_config.src_color_mode) |
709 v_WIN0_SRC_ALPHA_M0(alpha_config.src_alpha_mode) |
710 v_WIN0_SRC_BLEND_M0(alpha_config.src_global_alpha_mode) |
711 v_WIN0_SRC_ALPHA_CAL_M0(alpha_config.src_alpha_cal_m0) |
712 v_WIN0_SRC_FACTOR_M0(alpha_config.src_factor_mode) |
713 v_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val);
714 lcdc_msk_reg(lcdc_dev, src_alpha_ctl, mask, val);
718 static int rk3288_lcdc_area_swap(struct rk_lcdc_win *win,int area_num)
720 struct rk_lcdc_win_area area_temp;
723 area_temp = win->area[0];
724 win->area[0] = win->area[1];
725 win->area[1] = area_temp;
728 area_temp = win->area[0];
729 win->area[0] = win->area[2];
730 win->area[2] = area_temp;
733 area_temp = win->area[0];
734 win->area[0] = win->area[3];
735 win->area[3] = area_temp;
737 area_temp = win->area[1];
738 win->area[1] = win->area[2];
739 win->area[2] = area_temp;
742 printk(KERN_WARNING "un supported area num!\n");
748 static int rk3288_win_area_check_var(int win_id,int area_num,struct rk_lcdc_win_area *area_pre,
749 struct rk_lcdc_win_area *area_now)
751 if((area_pre->ypos >= area_now->ypos) ||
752 (area_pre->ypos+area_pre->ysize > area_now->ypos)){
755 "area_pre[%d]:ypos[%d],ysize[%d]\n"
756 "area_now[%d]:ypos[%d],ysize[%d]\n",
758 area_num-1,area_pre->ypos,area_pre->ysize,
759 area_num, area_now->ypos,area_now->ysize);
765 static int rk3288_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
767 struct lcdc_device *lcdc_dev =
768 container_of(dev_drv, struct lcdc_device, driver);
769 struct rk_lcdc_win *win = dev_drv->win[win_id];
770 unsigned int mask, val, off;
772 if(win->win_lb_mode == 5)
773 win->win_lb_mode = 4;
776 mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
777 m_WIN0_LB_MODE | m_WIN0_RB_SWAP | m_WIN0_UV_SWAP;
778 val = v_WIN0_EN(win->state) |
779 v_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
780 v_WIN0_FMT_10(win->fmt_10) |
781 v_WIN0_LB_MODE(win->win_lb_mode) |
782 v_WIN0_RB_SWAP(win->area[0].swap_rb) |
783 v_WIN0_UV_SWAP(win->area[0].swap_uv);
784 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
786 mask = m_WIN0_BIC_COE_SEL |
787 m_WIN0_VSD_YRGB_GT4 | m_WIN0_VSD_YRGB_GT2 |
788 m_WIN0_VSD_CBR_GT4 | m_WIN0_VSD_CBR_GT2 |
789 m_WIN0_YRGB_HOR_SCL_MODE | m_WIN0_YRGB_VER_SCL_MODE |
790 m_WIN0_YRGB_HSD_MODE | m_WIN0_YRGB_VSU_MODE |
791 m_WIN0_YRGB_VSD_MODE | m_WIN0_CBR_HOR_SCL_MODE |
792 m_WIN0_CBR_VER_SCL_MODE | m_WIN0_CBR_HSD_MODE |
793 m_WIN0_CBR_VSU_MODE | m_WIN0_CBR_VSD_MODE;
794 val = v_WIN0_BIC_COE_SEL(win->bic_coe_el) |
795 v_WIN0_VSD_YRGB_GT4(win->vsd_yrgb_gt4) |
796 v_WIN0_VSD_YRGB_GT2(win->vsd_yrgb_gt2) |
797 v_WIN0_VSD_CBR_GT4(win->vsd_cbr_gt4) |
798 v_WIN0_VSD_CBR_GT2(win->vsd_cbr_gt2) |
799 v_WIN0_YRGB_HOR_SCL_MODE(win->yrgb_hor_scl_mode) |
800 v_WIN0_YRGB_VER_SCL_MODE(win->yrgb_ver_scl_mode) |
801 v_WIN0_YRGB_HSD_MODE(win->yrgb_hsd_mode) |
802 v_WIN0_YRGB_VSU_MODE(win->yrgb_vsu_mode) |
803 v_WIN0_YRGB_VSD_MODE(win->yrgb_vsd_mode) |
804 v_WIN0_CBR_HOR_SCL_MODE(win->cbr_hor_scl_mode) |
805 v_WIN0_CBR_VER_SCL_MODE(win->cbr_ver_scl_mode) |
806 v_WIN0_CBR_HSD_MODE(win->cbr_hsd_mode) |
807 v_WIN0_CBR_VSU_MODE(win->cbr_vsu_mode) |
808 v_WIN0_CBR_VSD_MODE(win->cbr_vsd_mode);
809 lcdc_msk_reg(lcdc_dev, WIN0_CTRL1+off, mask,val);
811 val = v_WIN0_VIR_STRIDE(win->area[0].y_vir_stride) |
812 v_WIN0_VIR_STRIDE_UV(win->area[0].uv_vir_stride);
813 lcdc_writel(lcdc_dev, WIN0_VIR+off, val);
814 /*lcdc_writel(lcdc_dev, WIN0_YRGB_MST+off, win->area[0].y_addr);
815 lcdc_writel(lcdc_dev, WIN0_CBR_MST+off, win->area[0].uv_addr);*/
816 val = v_WIN0_ACT_WIDTH(win->area[0].xact) |
817 v_WIN0_ACT_HEIGHT(win->area[0].yact);
818 lcdc_writel(lcdc_dev, WIN0_ACT_INFO+off, val);
820 val = v_WIN0_DSP_WIDTH(win->area[0].xsize) |
821 v_WIN0_DSP_HEIGHT(win->area[0].ysize);
822 lcdc_writel(lcdc_dev, WIN0_DSP_INFO+off, val);
824 val = v_WIN0_DSP_XST(win->area[0].dsp_stx) |
825 v_WIN0_DSP_YST(win->area[0].dsp_sty);
826 lcdc_writel(lcdc_dev, WIN0_DSP_ST+off, val);
828 val = v_WIN0_HS_FACTOR_YRGB(win->scale_yrgb_x) |
829 v_WIN0_VS_FACTOR_YRGB(win->scale_yrgb_y);
830 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB+off, val);
832 val = v_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) |
833 v_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y);
834 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR+off, val);
835 if(win->alpha_en == 1)
836 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
838 mask = m_WIN0_SRC_ALPHA_EN;
839 val = v_WIN0_SRC_ALPHA_EN(0);
840 lcdc_msk_reg(lcdc_dev,WIN0_SRC_ALPHA_CTRL+off,mask,val);
845 val = v_WIN0_EN(win->state);
846 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
851 static int rk3288_win_2_3_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
853 struct lcdc_device *lcdc_dev =
854 container_of(dev_drv, struct lcdc_device, driver);
855 struct rk_lcdc_win *win = dev_drv->win[win_id];
856 struct rk_screen *screen = dev_drv->cur_screen;
857 unsigned int mask, val, off;
858 off = (win_id-2) * 0x50;
859 if((screen->y_mirror == 1)&&(win->area_num > 1)){
860 rk3288_lcdc_area_swap(win,win->area_num);
864 mask = m_WIN2_EN | m_WIN2_DATA_FMT | m_WIN2_RB_SWAP;
866 v_WIN2_DATA_FMT(win->area[0].fmt_cfg) |
867 v_WIN2_RB_SWAP(win->area[0].swap_rb);
868 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
870 if(win->area[0].state == 1){
871 mask = m_WIN2_MST0_EN;
872 val = v_WIN2_MST0_EN(win->area[0].state);
873 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
875 mask = m_WIN2_VIR_STRIDE0;
876 val = v_WIN2_VIR_STRIDE0(win->area[0].y_vir_stride);
877 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
879 /*lcdc_writel(lcdc_dev,WIN2_MST0+off,win->area[0].y_addr);*/
880 val = v_WIN2_DSP_WIDTH0(win->area[0].xsize) |
881 v_WIN2_DSP_HEIGHT0(win->area[0].ysize);
882 lcdc_writel(lcdc_dev,WIN2_DSP_INFO0+off,val);
883 val = v_WIN2_DSP_XST0(win->area[0].dsp_stx) |
884 v_WIN2_DSP_YST0(win->area[0].dsp_sty);
885 lcdc_writel(lcdc_dev,WIN2_DSP_ST0+off,val);
887 mask = m_WIN2_MST0_EN;
888 val = v_WIN2_MST0_EN(0);
889 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
892 if(win->area[1].state == 1){
893 rk3288_win_area_check_var(win_id,1,&win->area[0],&win->area[1]);
895 mask = m_WIN2_MST1_EN;
896 val = v_WIN2_MST1_EN(win->area[1].state);
897 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
899 mask = m_WIN2_VIR_STRIDE1;
900 val = v_WIN2_VIR_STRIDE1(win->area[1].y_vir_stride);
901 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
903 /*lcdc_writel(lcdc_dev,WIN2_MST1+off,win->area[1].y_addr);*/
904 val = v_WIN2_DSP_WIDTH1(win->area[1].xsize) |
905 v_WIN2_DSP_HEIGHT1(win->area[1].ysize);
906 lcdc_writel(lcdc_dev,WIN2_DSP_INFO1+off,val);
907 val = v_WIN2_DSP_XST1(win->area[1].dsp_stx) |
908 v_WIN2_DSP_YST1(win->area[1].dsp_sty);
909 lcdc_writel(lcdc_dev,WIN2_DSP_ST1+off,val);
911 mask = m_WIN2_MST1_EN;
912 val = v_WIN2_MST1_EN(0);
913 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
916 if(win->area[2].state == 1){
917 rk3288_win_area_check_var(win_id,2,&win->area[1],&win->area[2]);
919 mask = m_WIN2_MST2_EN;
920 val = v_WIN2_MST2_EN(win->area[2].state);
921 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
923 mask = m_WIN2_VIR_STRIDE2;
924 val = v_WIN2_VIR_STRIDE2(win->area[2].y_vir_stride);
925 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
927 /*lcdc_writel(lcdc_dev,WIN2_MST2+off,win->area[2].y_addr);*/
928 val = v_WIN2_DSP_WIDTH2(win->area[2].xsize) |
929 v_WIN2_DSP_HEIGHT2(win->area[2].ysize);
930 lcdc_writel(lcdc_dev,WIN2_DSP_INFO2+off,val);
931 val = v_WIN2_DSP_XST2(win->area[2].dsp_stx) |
932 v_WIN2_DSP_YST2(win->area[2].dsp_sty);
933 lcdc_writel(lcdc_dev,WIN2_DSP_ST2+off,val);
935 mask = m_WIN2_MST2_EN;
936 val = v_WIN2_MST2_EN(0);
937 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
940 if(win->area[3].state == 1){
941 rk3288_win_area_check_var(win_id,3,&win->area[2],&win->area[3]);
943 mask = m_WIN2_MST3_EN;
944 val = v_WIN2_MST3_EN(win->area[3].state);
945 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
947 mask = m_WIN2_VIR_STRIDE3;
948 val = v_WIN2_VIR_STRIDE3(win->area[3].y_vir_stride);
949 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
951 /*lcdc_writel(lcdc_dev,WIN2_MST3+off,win->area[3].y_addr);*/
952 val = v_WIN2_DSP_WIDTH3(win->area[3].xsize) |
953 v_WIN2_DSP_HEIGHT3(win->area[3].ysize);
954 lcdc_writel(lcdc_dev,WIN2_DSP_INFO3+off,val);
955 val = v_WIN2_DSP_XST3(win->area[3].dsp_stx) |
956 v_WIN2_DSP_YST3(win->area[3].dsp_sty);
957 lcdc_writel(lcdc_dev,WIN2_DSP_ST3+off,val);
959 mask = m_WIN2_MST3_EN;
960 val = v_WIN2_MST3_EN(0);
961 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
964 if(win->alpha_en == 1)
965 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
967 mask = m_WIN2_SRC_ALPHA_EN;
968 val = v_WIN2_SRC_ALPHA_EN(0);
969 lcdc_msk_reg(lcdc_dev,WIN2_SRC_ALPHA_CTRL+off,mask,val);
972 mask = m_WIN2_EN | m_WIN2_MST0_EN |
973 m_WIN2_MST0_EN | m_WIN2_MST2_EN |
975 val = v_WIN2_EN(win->state) | v_WIN2_MST0_EN(0) |
976 v_WIN2_MST1_EN(0) | v_WIN2_MST2_EN(0) |
978 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0+off, mask,val);
983 static int rk3288_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
985 struct lcdc_device *lcdc_dev =
986 container_of(dev_drv, struct lcdc_device, driver);
990 spin_lock(&lcdc_dev->reg_lock);
991 if(likely(lcdc_dev->clk_on))
993 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
994 v_STANDBY_EN(lcdc_dev->standby));
995 rk3288_win_0_1_reg_update(dev_drv,0);
996 rk3288_win_0_1_reg_update(dev_drv,1);
997 rk3288_win_2_3_reg_update(dev_drv,2);
998 rk3288_win_2_3_reg_update(dev_drv,3);
999 /*rk3288_lcdc_post_cfg(dev_drv);*/
1000 lcdc_cfg_done(lcdc_dev);
1002 spin_unlock(&lcdc_dev->reg_lock);
1004 /*if (dev_drv->wait_fs) {*/
1006 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
1007 init_completion(&dev_drv->frame_done);
1008 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
1009 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
1011 (dev_drv->cur_screen->ft +
1013 if (!timeout && (!dev_drv->frame_done.done)) {
1014 dev_warn(lcdc_dev->dev, "wait for new frame start time out!\n");
1018 DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
1023 static int rk3288_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
1025 memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
1028 static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
1031 struct lcdc_device *lcdc_dev =
1032 container_of(dev_drv, struct lcdc_device, driver);
1034 if (unlikely(!lcdc_dev->clk_on)) {
1035 pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
1038 #if defined(CONFIG_ROCKCHIP_IOMMU)
1039 if (dev_drv->iommu_enabled) {
1040 if (!lcdc_dev->iommu_status && dev_drv->mmu_dev) {
1042 if (likely(lcdc_dev->clk_on)) {
1043 spin_lock(&lcdc_dev->reg_lock);
1046 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
1047 mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
1048 val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
1049 lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
1050 spin_unlock(&lcdc_dev->reg_lock);
1052 lcdc_dev->iommu_status = 1;
1053 rockchip_iovmm_activate(dev_drv->dev);
1060 static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv, int reset_rate)
1062 #ifdef CONFIG_RK_FPGA
1066 struct lcdc_device *lcdc_dev =
1067 container_of(dev_drv, struct lcdc_device, driver);
1068 struct rk_screen *screen = dev_drv->cur_screen;
1071 ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);/*set pll */
1073 dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
1074 lcdc_dev->pixclock =
1075 div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
1076 lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
1078 fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
1079 screen->ft = 1000 / fps;
1080 dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
1081 lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
1086 static int rk3288_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
1087 u16 *yact, int *format, u32 *dsp_addr)
1089 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1090 struct lcdc_device, driver);
1093 spin_lock(&lcdc_dev->reg_lock);
1095 val = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
1096 *xact = (val & m_WIN0_ACT_WIDTH) + 1;
1097 *yact = ((val & m_WIN0_ACT_HEIGHT)>>16) + 1;
1099 val = lcdc_readl(lcdc_dev, WIN0_CTRL0);
1100 *format = (val & m_WIN0_DATA_FMT) >> 1;
1101 *dsp_addr = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
1103 spin_unlock(&lcdc_dev->reg_lock);
1108 static int rk3288_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
1109 int format, u16 xact, u16 yact, u16 xvir)
1111 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1112 struct lcdc_device, driver);
1114 int swap = (format == RGB888) ? 1 : 0;
1116 mask = m_WIN0_DATA_FMT | m_WIN0_RB_SWAP;
1117 val = v_WIN0_DATA_FMT(format) | v_WIN0_RB_SWAP(swap);
1118 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask, val);
1120 lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_WIN0_VIR_STRIDE,
1121 v_WIN0_VIR_STRIDE(xvir));
1122 lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_WIN0_ACT_WIDTH(xact) |
1123 v_WIN0_ACT_HEIGHT(yact));
1125 lcdc_writel(lcdc_dev, WIN0_YRGB_MST, rgb_mst);
1127 lcdc_cfg_done(lcdc_dev);
1132 static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
1136 struct lcdc_device *lcdc_dev =
1137 container_of(dev_drv, struct lcdc_device, driver);
1138 struct rk_screen *screen = dev_drv->cur_screen;
1139 u16 hsync_len = screen->mode.hsync_len;
1140 u16 left_margin = screen->mode.left_margin;
1141 u16 right_margin = screen->mode.right_margin;
1142 u16 vsync_len = screen->mode.vsync_len;
1143 u16 upper_margin = screen->mode.upper_margin;
1144 u16 lower_margin = screen->mode.lower_margin;
1145 u16 x_res = screen->mode.xres;
1146 u16 y_res = screen->mode.yres;
1148 u16 h_total,v_total;
1149 if (unlikely(!lcdc_dev->clk_on)) {
1150 pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
1154 h_total = hsync_len + left_margin + x_res + right_margin;
1155 v_total = vsync_len + upper_margin + y_res + lower_margin;
1157 screen->post_dsp_stx = x_res * (100 - screen->overscan.left) / 200;
1158 screen->post_dsp_sty = y_res * (100 - screen->overscan.top) / 200;
1159 screen->post_xsize = x_res * (screen->overscan.left + screen->overscan.right) / 200;
1160 screen->post_ysize = y_res * (screen->overscan.top + screen->overscan.bottom) / 200;
1162 spin_lock(&lcdc_dev->reg_lock);
1163 if (likely(lcdc_dev->clk_on)) {
1164 switch (screen->face) {
1167 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1168 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1169 m_PRE_DITHER_DOWN_EN;
1170 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1171 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1172 v_PRE_DITHER_DOWN_EN(1);
1173 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1177 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1178 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1179 m_PRE_DITHER_DOWN_EN;
1180 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1181 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1182 v_PRE_DITHER_DOWN_EN(1);
1183 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1187 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1188 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1189 m_PRE_DITHER_DOWN_EN;
1190 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1191 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1192 v_PRE_DITHER_DOWN_EN(1);
1193 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1197 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1198 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1199 m_PRE_DITHER_DOWN_EN;
1200 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1201 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1202 v_PRE_DITHER_DOWN_EN(1);
1203 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1207 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
1208 m_PRE_DITHER_DOWN_EN;
1209 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
1210 v_PRE_DITHER_DOWN_EN(1);
1211 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1215 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
1216 m_PRE_DITHER_DOWN_EN;
1217 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
1218 v_PRE_DITHER_DOWN_EN(0);
1219 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1222 dev_err(lcdc_dev->dev,"un supported interface!\n");
1225 switch(screen->type){
1228 case SCREEN_DUAL_LVDS:
1229 case SCREEN_LVDS_10BIT:
1230 case SCREEN_DUAL_LVDS_10BIT:
1231 mask = m_RGB_OUT_EN;
1232 val = v_RGB_OUT_EN(1);
1234 v |= (lcdc_dev->id << 3);
1237 face = OUT_P101010;/*RGB 101010 output*/
1238 mask = m_HDMI_OUT_EN;
1239 val = v_HDMI_OUT_EN(1);
1242 mask = m_MIPI_OUT_EN;
1243 val = v_MIPI_OUT_EN(1);
1245 case SCREEN_DUAL_MIPI:
1246 mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
1247 val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
1250 face = OUT_P101010; /*RGB 101010 output*/
1251 mask = m_EDP_OUT_EN;
1252 val = v_EDP_OUT_EN(1);
1255 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
1256 #ifndef CONFIG_RK_FPGA
1257 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
1259 mask = m_DSP_OUT_MODE | m_DSP_HSYNC_POL | m_DSP_VSYNC_POL |
1260 m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP |
1261 m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
1262 m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN |
1263 m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN;
1264 val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
1265 v_DSP_VSYNC_POL(screen->pin_vsync) |
1266 v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
1267 v_DSP_BG_SWAP(screen->swap_gb) | v_DSP_RB_SWAP(screen->swap_rb) |
1268 v_DSP_RG_SWAP(screen->swap_rg) |
1269 v_DSP_DELTA_SWAP(screen->swap_delta) |
1270 v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) |
1271 v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
1272 v_DSP_X_MIR_EN(screen->x_mirror) | v_DSP_Y_MIR_EN(screen->y_mirror);
1273 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
1275 mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
1276 val = v_DSP_BG_BLUE(0) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
1277 lcdc_msk_reg(lcdc_dev, DSP_BG, mask, val);
1279 mask = m_DSP_HS_PW | m_DSP_HTOTAL;
1280 val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
1281 lcdc_msk_reg(lcdc_dev, DSP_HTOTAL_HS_END, mask, val);
1283 mask = m_DSP_HACT_END | m_DSP_HACT_ST;
1284 val = v_DSP_HACT_END(hsync_len + left_margin + x_res) |
1285 v_DSP_HACT_ST(hsync_len + left_margin);
1286 lcdc_msk_reg(lcdc_dev, DSP_HACT_ST_END, mask, val);
1288 mask = m_DSP_VS_PW | m_DSP_VTOTAL;
1289 val = v_DSP_VS_PW(vsync_len) | v_DSP_VTOTAL(v_total);
1290 lcdc_msk_reg(lcdc_dev, DSP_VTOTAL_VS_END, mask, val);
1292 mask = m_DSP_VACT_END | m_DSP_VACT_ST;
1293 val = v_DSP_VACT_END(vsync_len + upper_margin + y_res) |
1294 v_DSP_VACT_ST(vsync_len + upper_margin);
1295 lcdc_msk_reg(lcdc_dev, DSP_VACT_ST_END, mask, val);
1297 rk3288_lcdc_post_cfg(dev_drv);
1298 mask = m_DSP_LINE_FLAG_NUM;
1299 val = v_DSP_LINE_FLAG_NUM(vsync_len + upper_margin + y_res);
1300 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
1302 spin_unlock(&lcdc_dev->reg_lock);
1303 rk3288_lcdc_set_dclk(dev_drv, 1);
1304 if (screen->type != SCREEN_HDMI && dev_drv->trsm_ops &&
1305 dev_drv->trsm_ops->enable)
1306 dev_drv->trsm_ops->enable();
1313 /*enable layer,open:1,enable;0 disable*/
1314 static int win0_open(struct lcdc_device *lcdc_dev, bool open)
1316 spin_lock(&lcdc_dev->reg_lock);
1317 if (likely(lcdc_dev->clk_on)) {
1319 if (!lcdc_dev->atv_layer_cnt) {
1320 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1321 lcdc_dev->standby = 0;
1323 lcdc_dev->atv_layer_cnt++;
1324 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1325 lcdc_dev->atv_layer_cnt--;
1327 lcdc_dev->driver.win[0]->state = open;
1328 if (!lcdc_dev->atv_layer_cnt) {
1329 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1330 lcdc_dev->standby = 1;
1333 spin_unlock(&lcdc_dev->reg_lock);
1338 static int win1_open(struct lcdc_device *lcdc_dev, bool open)
1340 spin_lock(&lcdc_dev->reg_lock);
1341 if (likely(lcdc_dev->clk_on)) {
1343 if (!lcdc_dev->atv_layer_cnt) {
1344 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1345 lcdc_dev->standby = 0;
1347 lcdc_dev->atv_layer_cnt++;
1348 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1349 lcdc_dev->atv_layer_cnt--;
1351 lcdc_dev->driver.win[1]->state = open;
1353 /*if no layer used,disable lcdc*/
1354 if (!lcdc_dev->atv_layer_cnt) {
1355 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1356 lcdc_dev->standby = 1;
1359 spin_unlock(&lcdc_dev->reg_lock);
1364 static int win2_open(struct lcdc_device *lcdc_dev, bool open)
1366 spin_lock(&lcdc_dev->reg_lock);
1367 if (likely(lcdc_dev->clk_on)) {
1369 if (!lcdc_dev->atv_layer_cnt) {
1370 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1371 lcdc_dev->standby = 0;
1373 lcdc_dev->atv_layer_cnt++;
1374 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1375 lcdc_dev->atv_layer_cnt--;
1377 lcdc_dev->driver.win[2]->state = open;
1379 /*if no layer used,disable lcdc*/
1380 if (!lcdc_dev->atv_layer_cnt) {
1381 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1382 lcdc_dev->standby = 1;
1385 spin_unlock(&lcdc_dev->reg_lock);
1390 static int win3_open(struct lcdc_device *lcdc_dev, bool open)
1392 spin_lock(&lcdc_dev->reg_lock);
1393 if (likely(lcdc_dev->clk_on)) {
1395 if (!lcdc_dev->atv_layer_cnt) {
1396 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1397 lcdc_dev->standby = 0;
1399 lcdc_dev->atv_layer_cnt++;
1400 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1401 lcdc_dev->atv_layer_cnt--;
1403 lcdc_dev->driver.win[3]->state = open;
1405 /*if no layer used,disable lcdc*/
1406 if (!lcdc_dev->atv_layer_cnt) {
1407 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1408 lcdc_dev->standby = 1;
1411 spin_unlock(&lcdc_dev->reg_lock);
1415 static int rk3288_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
1417 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1418 struct lcdc_device, driver);
1421 mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
1422 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR |
1423 m_BUS_ERROR_INTR_EN;
1424 val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(1) |
1425 v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0);
1426 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
1427 #ifdef LCDC_IRQ_EMPTY_DEBUG
1428 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN | m_WIN2_EMPTY_INTR_EN |
1429 m_WIN3_EMPTY_INTR_EN |m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
1431 val = v_WIN0_EMPTY_INTR_EN(1) | v_WIN1_EMPTY_INTR_EN(1) | v_WIN2_EMPTY_INTR_EN(1) |
1432 v_WIN3_EMPTY_INTR_EN(1)| v_HWC_EMPTY_INTR_EN(1) | v_POST_BUF_EMPTY_INTR_EN(1) |
1433 v_PWM_GEN_INTR_EN(1);
1434 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
1439 static int rk3288_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
1442 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1443 struct lcdc_device, driver);
1444 int sys_status = (dev_drv->id == 0) ?
1445 SYS_STATUS_LCDC0 : SYS_STATUS_LCDC1;
1447 /*enable clk,when first layer open */
1448 if ((open) && (!lcdc_dev->atv_layer_cnt)) {
1449 rockchip_set_system_status(sys_status);
1450 rk3288_lcdc_pre_init(dev_drv);
1451 rk3288_lcdc_clk_enable(lcdc_dev);
1452 rk3288_lcdc_enable_irq(dev_drv);
1453 #if defined(CONFIG_ROCKCHIP_IOMMU)
1454 if (dev_drv->iommu_enabled) {
1455 if (!dev_drv->mmu_dev) {
1457 rk_fb_get_sysmmu_device_by_compatible(dev_drv->mmu_dts_name);
1458 if (dev_drv->mmu_dev) {
1459 rk_fb_platform_set_sysmmu(dev_drv->mmu_dev,
1462 dev_err(dev_drv->dev,
1463 "failed to get rockchip iommu device\n");
1469 rk3288_lcdc_reg_restore(lcdc_dev);
1470 /*if (dev_drv->iommu_enabled)
1471 rk3368_lcdc_mmu_en(dev_drv); */
1472 if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
1473 rk3288_lcdc_set_dclk(dev_drv, 0);
1474 /* rk3288_lcdc_enable_irq(dev_drv); */
1476 rk3288_load_screen(dev_drv, 1);
1478 if (dev_drv->bcsh.enable)
1479 rk3288_lcdc_set_bcsh(dev_drv, 1);
1480 spin_lock(&lcdc_dev->reg_lock);
1481 if (dev_drv->cur_screen->dsp_lut)
1482 rk3288_lcdc_set_lut(dev_drv);
1483 spin_unlock(&lcdc_dev->reg_lock);
1487 win0_open(lcdc_dev, open);
1488 else if (win_id == 1)
1489 win1_open(lcdc_dev, open);
1490 else if (win_id == 2)
1491 win2_open(lcdc_dev, open);
1492 else if (win_id == 3)
1493 win3_open(lcdc_dev, open);
1495 dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
1497 /* when all layer closed,disable clk */
1498 if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
1499 rk3288_lcdc_disable_irq(lcdc_dev);
1500 rk3288_lcdc_reg_update(dev_drv);
1501 #if defined(CONFIG_ROCKCHIP_IOMMU)
1502 if (dev_drv->iommu_enabled) {
1503 if (dev_drv->mmu_dev)
1504 rockchip_iovmm_deactivate(dev_drv->dev);
1507 rk3288_lcdc_clk_disable(lcdc_dev);
1508 rockchip_clear_system_status(sys_status);
1514 static int win0_display(struct lcdc_device *lcdc_dev,
1515 struct rk_lcdc_win *win)
1519 y_addr = win->area[0].smem_start+win->area[0].y_offset;/*win->smem_start + win->y_offset;*/
1520 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1521 DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
1522 lcdc_dev->id, __func__, y_addr, uv_addr,win->area[0].y_offset);
1523 spin_lock(&lcdc_dev->reg_lock);
1524 if (likely(lcdc_dev->clk_on)) {
1525 win->area[0].y_addr = y_addr;
1526 win->area[0].uv_addr = uv_addr;
1527 lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr);
1528 lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr);
1529 /*lcdc_cfg_done(lcdc_dev);*/
1531 spin_unlock(&lcdc_dev->reg_lock);
1537 static int win1_display(struct lcdc_device *lcdc_dev,
1538 struct rk_lcdc_win *win)
1542 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1543 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1544 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>uv_addr:0x%x\n",
1545 lcdc_dev->id, __func__, y_addr, uv_addr);
1547 spin_lock(&lcdc_dev->reg_lock);
1548 if (likely(lcdc_dev->clk_on)) {
1549 win->area[0].y_addr = y_addr;
1550 win->area[0].uv_addr = uv_addr;
1551 lcdc_writel(lcdc_dev, WIN1_YRGB_MST, win->area[0].y_addr);
1552 lcdc_writel(lcdc_dev, WIN1_CBR_MST, win->area[0].uv_addr);
1554 spin_unlock(&lcdc_dev->reg_lock);
1560 static int win2_display(struct lcdc_device *lcdc_dev,
1561 struct rk_lcdc_win *win)
1564 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1565 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1566 lcdc_dev->id, __func__, y_addr);
1568 spin_lock(&lcdc_dev->reg_lock);
1569 if (likely(lcdc_dev->clk_on)){
1570 for(i=0;i<win->area_num;i++)
1571 win->area[i].y_addr =
1572 win->area[i].smem_start + win->area[i].y_offset;
1573 lcdc_writel(lcdc_dev,WIN2_MST0,win->area[0].y_addr);
1574 lcdc_writel(lcdc_dev,WIN2_MST1,win->area[1].y_addr);
1575 lcdc_writel(lcdc_dev,WIN2_MST2,win->area[2].y_addr);
1576 lcdc_writel(lcdc_dev,WIN2_MST3,win->area[3].y_addr);
1578 spin_unlock(&lcdc_dev->reg_lock);
1582 static int win3_display(struct lcdc_device *lcdc_dev,
1583 struct rk_lcdc_win *win)
1586 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1587 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1588 lcdc_dev->id, __func__, y_addr);
1590 spin_lock(&lcdc_dev->reg_lock);
1591 if (likely(lcdc_dev->clk_on)){
1592 for(i=0;i<win->area_num;i++)
1593 win->area[i].y_addr =
1594 win->area[i].smem_start + win->area[i].y_offset;
1595 lcdc_writel(lcdc_dev,WIN3_MST0,win->area[0].y_addr);
1596 lcdc_writel(lcdc_dev,WIN3_MST1,win->area[1].y_addr);
1597 lcdc_writel(lcdc_dev,WIN3_MST2,win->area[2].y_addr);
1598 lcdc_writel(lcdc_dev,WIN3_MST3,win->area[3].y_addr);
1600 spin_unlock(&lcdc_dev->reg_lock);
1604 static int rk3288_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
1606 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1607 struct lcdc_device, driver);
1608 struct rk_lcdc_win *win = NULL;
1609 struct rk_screen *screen = dev_drv->cur_screen;
1611 #if defined(WAIT_FOR_SYNC)
1613 unsigned long flags;
1615 win = dev_drv->win[win_id];
1617 dev_err(dev_drv->dev, "screen is null!\n");
1621 win0_display(lcdc_dev, win);
1622 }else if(win_id == 1){
1623 win1_display(lcdc_dev, win);
1624 }else if(win_id == 2){
1625 win2_display(lcdc_dev, win);
1626 }else if(win_id == 3){
1627 win3_display(lcdc_dev, win);
1629 dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
1633 /*this is the first frame of the system ,enable frame start interrupt */
1634 if ((dev_drv->first_frame)) {
1635 dev_drv->first_frame = 0;
1636 rk3288_lcdc_enable_irq(dev_drv);
1638 #if defined(WAIT_FOR_SYNC)
1639 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
1640 init_completion(&dev_drv->frame_done);
1641 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
1642 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
1643 msecs_to_jiffies(dev_drv->
1646 if (!timeout && (!dev_drv->frame_done.done)) {
1647 dev_info(dev_drv->dev, "wait for new frame start time out!\n");
1654 static int rk3288_lcdc_cal_scl_fac(struct rk_lcdc_win *win)
1664 u32 yrgb_vScaleDnMult;
1665 u32 yrgb_xscl_factor;
1666 u32 yrgb_yscl_factor;
1667 u8 yrgb_vsd_bil_gt2=0;
1668 u8 yrgb_vsd_bil_gt4=0;
1674 u32 cbcr_vScaleDnMult;
1675 u32 cbcr_xscl_factor;
1676 u32 cbcr_yscl_factor;
1677 u8 cbcr_vsd_bil_gt2=0;
1678 u8 cbcr_vsd_bil_gt4=0;
1682 srcW = win->area[0].xact;
1683 srcH = win->area[0].yact;
1684 dstW = win->area[0].xsize;
1685 dstH = win->area[0].ysize;
1692 if ((yrgb_dstW*8 <= yrgb_srcW) || (yrgb_dstH*8 <= yrgb_srcH)) {
1693 pr_err("ERROR: yrgb scale exceed 8,"
1694 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1695 yrgb_srcW,yrgb_srcH,yrgb_dstW,yrgb_dstH);
1697 if(yrgb_srcW < yrgb_dstW){
1698 win->yrgb_hor_scl_mode = SCALE_UP;
1699 }else if(yrgb_srcW > yrgb_dstW){
1700 win->yrgb_hor_scl_mode = SCALE_DOWN;
1702 win->yrgb_hor_scl_mode = SCALE_NONE;
1705 if(yrgb_srcH < yrgb_dstH){
1706 win->yrgb_ver_scl_mode = SCALE_UP;
1707 }else if (yrgb_srcH > yrgb_dstH){
1708 win->yrgb_ver_scl_mode = SCALE_DOWN;
1710 win->yrgb_ver_scl_mode = SCALE_NONE;
1714 switch (win->area[0].format) {
1748 if ((cbcr_dstW*8 <= cbcr_srcW) || (cbcr_dstH*8 <= cbcr_srcH)) {
1749 pr_err("ERROR: cbcr scale exceed 8,"
1750 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1751 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH);
1755 if(cbcr_srcW < cbcr_dstW){
1756 win->cbr_hor_scl_mode = SCALE_UP;
1757 }else if(cbcr_srcW > cbcr_dstW){
1758 win->cbr_hor_scl_mode = SCALE_DOWN;
1760 win->cbr_hor_scl_mode = SCALE_NONE;
1763 if(cbcr_srcH < cbcr_dstH){
1764 win->cbr_ver_scl_mode = SCALE_UP;
1765 }else if(cbcr_srcH > cbcr_dstH){
1766 win->cbr_ver_scl_mode = SCALE_DOWN;
1768 win->cbr_ver_scl_mode = SCALE_NONE;
1770 DBG(1, "srcW:%d>>srcH:%d>>dstW:%d>>dstH:%d>>\n"
1771 "yrgb:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1772 "cbcr:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1773 ,srcW,srcH,dstW,dstH,yrgb_srcW,yrgb_srcH,yrgb_dstW,
1774 yrgb_dstH,win->yrgb_hor_scl_mode,win->yrgb_ver_scl_mode,
1775 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH,
1776 win->cbr_hor_scl_mode,win->cbr_ver_scl_mode);
1778 /*line buffer mode*/
1779 if ((win->area[0].format == YUV422) ||
1780 (win->area[0].format == YUV420) ||
1781 (win->area[0].format == YUV422_A) ||
1782 (win->area[0].format == YUV420_A)) {
1783 if (win->cbr_hor_scl_mode == SCALE_DOWN) {
1784 if ((cbcr_dstW > 3840) || (cbcr_dstW == 0)) {
1785 pr_err("ERROR cbcr_dstW = %d\n",cbcr_dstW);
1786 } else if (cbcr_dstW > 2560) {
1787 win->win_lb_mode = LB_RGB_3840X2;
1788 } else if (cbcr_dstW > 1920) {
1789 if (win->yrgb_hor_scl_mode == SCALE_DOWN) {
1790 if(yrgb_dstW > 3840){
1791 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1792 }else if(yrgb_dstW > 2560){
1793 win->win_lb_mode = LB_RGB_3840X2;
1794 }else if(yrgb_dstW > 1920){
1795 win->win_lb_mode = LB_RGB_2560X4;
1797 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1800 } else if (cbcr_dstW > 1280) {
1801 win->win_lb_mode = LB_YUV_3840X5;
1803 win->win_lb_mode = LB_YUV_2560X8;
1805 } else { /*SCALE_UP or SCALE_NONE*/
1806 if ((cbcr_srcW > 3840) || (cbcr_srcW == 0)) {
1807 pr_err("ERROR cbcr_srcW = %d\n",cbcr_srcW);
1808 }else if(cbcr_srcW > 2560){
1809 win->win_lb_mode = LB_RGB_3840X2;
1810 }else if(cbcr_srcW > 1920){
1811 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1812 if(yrgb_dstW > 3840){
1813 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1814 }else if(yrgb_dstW > 2560){
1815 win->win_lb_mode = LB_RGB_3840X2;
1816 }else if(yrgb_dstW > 1920){
1817 win->win_lb_mode = LB_RGB_2560X4;
1819 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1822 }else if(cbcr_srcW > 1280){
1823 win->win_lb_mode = LB_YUV_3840X5;
1825 win->win_lb_mode = LB_YUV_2560X8;
1829 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1830 if ((yrgb_dstW > 3840) || (yrgb_dstW == 0)) {
1831 pr_err("ERROR yrgb_dstW = %d\n",yrgb_dstW);
1832 }else if(yrgb_dstW > 2560){
1833 win->win_lb_mode = LB_RGB_3840X2;
1834 }else if(yrgb_dstW > 1920){
1835 win->win_lb_mode = LB_RGB_2560X4;
1836 }else if(yrgb_dstW > 1280){
1837 win->win_lb_mode = LB_RGB_1920X5;
1839 win->win_lb_mode = LB_RGB_1280X8;
1841 }else{ /*SCALE_UP or SCALE_NONE*/
1842 if ((yrgb_srcW > 3840) || (yrgb_srcW == 0)) {
1843 pr_err("ERROR yrgb_srcW = %d\n",yrgb_srcW);
1844 }else if(yrgb_srcW > 2560){
1845 win->win_lb_mode = LB_RGB_3840X2;
1846 }else if(yrgb_srcW > 1920){
1847 win->win_lb_mode = LB_RGB_2560X4;
1848 }else if(yrgb_srcW > 1280){
1849 win->win_lb_mode = LB_RGB_1920X5;
1851 win->win_lb_mode = LB_RGB_1280X8;
1855 DBG(1,"win->win_lb_mode = %d;\n",win->win_lb_mode);
1857 /*vsd/vsu scale ALGORITHM*/
1858 win->yrgb_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1859 win->cbr_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1860 win->yrgb_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1861 win->cbr_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1862 switch(win->win_lb_mode){
1867 win->yrgb_vsu_mode = SCALE_UP_BIC;
1868 win->cbr_vsu_mode = SCALE_UP_BIC;
1871 if(win->yrgb_ver_scl_mode != SCALE_NONE) {
1872 pr_err("ERROR : not allow yrgb ver scale\n");
1874 if(win->cbr_ver_scl_mode != SCALE_NONE) {
1875 pr_err("ERROR : not allow cbcr ver scale\n");
1879 win->yrgb_vsu_mode = SCALE_UP_BIL;
1880 win->cbr_vsu_mode = SCALE_UP_BIL;
1883 printk(KERN_WARNING "%s:un supported win_lb_mode:%d\n",
1884 __func__,win->win_lb_mode);
1887 DBG(1,"yrgb:hsd=%d,vsd=%d,vsu=%d;cbcr:hsd=%d,vsd=%d,vsu=%d\n",
1888 win->yrgb_hsd_mode,win->yrgb_vsd_mode,win->yrgb_vsu_mode,
1889 win->cbr_hsd_mode,win->cbr_vsd_mode,win->cbr_vsu_mode);
1893 /*(1.1)YRGB HOR SCALE FACTOR*/
1894 switch(win->yrgb_hor_scl_mode){
1896 yrgb_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1899 yrgb_xscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcW, yrgb_dstW);
1902 switch(win->yrgb_hsd_mode)
1904 case SCALE_DOWN_BIL:
1905 yrgb_xscl_factor = GET_SCALE_FACTOR_BILI_DN(yrgb_srcW, yrgb_dstW);
1907 case SCALE_DOWN_AVG:
1908 yrgb_xscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcW, yrgb_dstW);
1911 printk(KERN_WARNING "%s:un supported yrgb_hsd_mode:%d\n",
1912 __func__,win->yrgb_hsd_mode);
1917 printk(KERN_WARNING "%s:un supported yrgb_hor_scl_mode:%d\n",
1918 __func__,win->yrgb_hor_scl_mode);
1920 } /*win->yrgb_hor_scl_mode*/
1922 /*(1.2)YRGB VER SCALE FACTOR*/
1923 switch(win->yrgb_ver_scl_mode)
1926 yrgb_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1929 switch(win->yrgb_vsu_mode)
1932 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_UP(yrgb_srcH, yrgb_dstH);
1936 pr_err("yrgb_srcH should be greater than 3 !!!\n");
1938 yrgb_yscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcH, yrgb_dstH);
1941 printk(KERN_WARNING "%s:un supported yrgb_vsu_mode:%d\n",
1942 __func__,win->yrgb_vsu_mode);
1947 switch(win->yrgb_vsd_mode)
1949 case SCALE_DOWN_BIL:
1950 yrgb_vScaleDnMult = getHardWareVSkipLines(yrgb_srcH, yrgb_dstH);
1951 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(yrgb_srcH, yrgb_dstH, yrgb_vScaleDnMult);
1952 if(yrgb_vScaleDnMult == 4){
1953 yrgb_vsd_bil_gt4 = 1;
1954 yrgb_vsd_bil_gt2 = 0;
1955 }else if(yrgb_vScaleDnMult == 2){
1956 yrgb_vsd_bil_gt4 = 0;
1957 yrgb_vsd_bil_gt2 = 1;
1959 yrgb_vsd_bil_gt4 = 0;
1960 yrgb_vsd_bil_gt2 = 0;
1963 case SCALE_DOWN_AVG:
1964 yrgb_yscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcH, yrgb_dstH);
1967 printk(KERN_WARNING "%s:un supported yrgb_vsd_mode:%d\n",
1968 __func__,win->yrgb_vsd_mode);
1970 } /*win->yrgb_vsd_mode*/
1973 printk(KERN_WARNING "%s:un supported yrgb_ver_scl_mode:%d\n",
1974 __func__,win->yrgb_ver_scl_mode);
1977 win->scale_yrgb_x = yrgb_xscl_factor;
1978 win->scale_yrgb_y = yrgb_yscl_factor;
1979 win->vsd_yrgb_gt4 = yrgb_vsd_bil_gt4;
1980 win->vsd_yrgb_gt2 = yrgb_vsd_bil_gt2;
1981 DBG(1,"yrgb:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",yrgb_xscl_factor,
1982 yrgb_yscl_factor,yrgb_vsd_bil_gt4,yrgb_vsd_bil_gt2);
1984 /*(2.1)CBCR HOR SCALE FACTOR*/
1985 switch(win->cbr_hor_scl_mode)
1988 cbcr_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
1991 cbcr_xscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcW, cbcr_dstW);
1994 switch(win->cbr_hsd_mode)
1996 case SCALE_DOWN_BIL:
1997 cbcr_xscl_factor = GET_SCALE_FACTOR_BILI_DN(cbcr_srcW, cbcr_dstW);
1999 case SCALE_DOWN_AVG:
2000 cbcr_xscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcW, cbcr_dstW);
2003 printk(KERN_WARNING "%s:un supported cbr_hsd_mode:%d\n",
2004 __func__,win->cbr_hsd_mode);
2009 printk(KERN_WARNING "%s:un supported cbr_hor_scl_mode:%d\n",
2010 __func__,win->cbr_hor_scl_mode);
2012 } /*win->cbr_hor_scl_mode*/
2014 /*(2.2)CBCR VER SCALE FACTOR*/
2015 switch(win->cbr_ver_scl_mode)
2018 cbcr_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
2021 switch(win->cbr_vsu_mode)
2024 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_UP(cbcr_srcH, cbcr_dstH);
2028 pr_err("cbcr_srcH should be greater than 3 !!!\n");
2030 cbcr_yscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcH, cbcr_dstH);
2033 printk(KERN_WARNING "%s:un supported cbr_vsu_mode:%d\n",
2034 __func__,win->cbr_vsu_mode);
2039 switch(win->cbr_vsd_mode)
2041 case SCALE_DOWN_BIL:
2042 cbcr_vScaleDnMult = getHardWareVSkipLines(cbcr_srcH, cbcr_dstH);
2043 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(cbcr_srcH, cbcr_dstH, cbcr_vScaleDnMult);
2044 if(cbcr_vScaleDnMult == 4){
2045 cbcr_vsd_bil_gt4 = 1;
2046 cbcr_vsd_bil_gt2 = 0;
2047 }else if(cbcr_vScaleDnMult == 2){
2048 cbcr_vsd_bil_gt4 = 0;
2049 cbcr_vsd_bil_gt2 = 1;
2051 cbcr_vsd_bil_gt4 = 0;
2052 cbcr_vsd_bil_gt2 = 0;
2055 case SCALE_DOWN_AVG:
2056 cbcr_yscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcH, cbcr_dstH);
2059 printk(KERN_WARNING "%s:un supported cbr_vsd_mode:%d\n",
2060 __func__,win->cbr_vsd_mode);
2065 printk(KERN_WARNING "%s:un supported cbr_ver_scl_mode:%d\n",
2066 __func__,win->cbr_ver_scl_mode);
2069 win->scale_cbcr_x = cbcr_xscl_factor;
2070 win->scale_cbcr_y = cbcr_yscl_factor;
2071 win->vsd_cbr_gt4 = cbcr_vsd_bil_gt4;
2072 win->vsd_cbr_gt2 = cbcr_vsd_bil_gt2;
2074 DBG(1,"cbcr:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",cbcr_xscl_factor,
2075 cbcr_yscl_factor,cbcr_vsd_bil_gt4,cbcr_vsd_bil_gt2);
2081 static int win0_set_par(struct lcdc_device *lcdc_dev,
2082 struct rk_screen *screen, struct rk_lcdc_win *win)
2084 u32 xact,yact,xvir, yvir,xpos, ypos;
2085 u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
2086 char fmt[9] = "NULL";
2088 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
2089 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
2091 spin_lock(&lcdc_dev->reg_lock);
2092 if(likely(lcdc_dev->clk_on)){
2093 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
2094 switch (win->area[0].format) {
2152 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2156 win->area[0].fmt_cfg = fmt_cfg;
2157 win->area[0].swap_rb = swap_rb;
2158 win->area[0].dsp_stx = xpos;
2159 win->area[0].dsp_sty = ypos;
2160 win->area[0].swap_uv = swap_uv;
2161 xact = win->area[0].xact;
2162 yact = win->area[0].yact;
2163 xvir = win->area[0].xvir;
2164 yvir = win->area[0].yvir;
2166 rk3288_win_0_1_reg_update(&lcdc_dev->driver,0);
2167 spin_unlock(&lcdc_dev->reg_lock);
2169 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2170 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2171 __func__, get_format_string(win->area[0].format, fmt), xact,
2172 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2177 static int win1_set_par(struct lcdc_device *lcdc_dev,
2178 struct rk_screen *screen, struct rk_lcdc_win *win)
2180 u32 xact, yact, xvir, yvir, xpos, ypos;
2181 u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
2182 char fmt[9] = "NULL";
2184 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
2185 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
2187 spin_lock(&lcdc_dev->reg_lock);
2188 if (likely(lcdc_dev->clk_on)) {
2189 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
2190 switch (win->area[0].format) {
2249 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2253 win->area[0].fmt_cfg = fmt_cfg;
2254 win->area[0].swap_rb = swap_rb;
2255 win->area[0].dsp_stx = xpos;
2256 win->area[0].dsp_sty = ypos;
2257 win->area[0].swap_uv = swap_uv;
2258 xact = win->area[0].xact;
2259 yact = win->area[0].yact;
2260 xvir = win->area[0].xvir;
2261 yvir = win->area[0].yvir;
2263 rk3288_win_0_1_reg_update(&lcdc_dev->driver,1);
2264 spin_unlock(&lcdc_dev->reg_lock);
2266 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2267 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2268 __func__, get_format_string(win->area[0].format, fmt), xact,
2269 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2274 static int win2_set_par(struct lcdc_device *lcdc_dev,
2275 struct rk_screen *screen, struct rk_lcdc_win *win)
2278 u8 fmt_cfg, swap_rb;
2280 spin_lock(&lcdc_dev->reg_lock);
2281 if (likely(lcdc_dev->clk_on)) {
2282 for (i = 0; i < win->area_num; i++) {
2283 switch (win->area[i].format) {
2302 dev_err(lcdc_dev->driver.dev,
2303 "%s:un supported format!\n",
2307 win->area[i].fmt_cfg = fmt_cfg;
2308 win->area[i].swap_rb = swap_rb;
2309 win->area[i].dsp_stx = win->area[i].xpos +
2310 screen->mode.left_margin +
2311 screen->mode.hsync_len;
2312 if (screen->y_mirror == 1) {
2313 win->area[i].dsp_sty = screen->mode.yres -
2315 win->area[i].ysize +
2316 screen->mode.upper_margin +
2317 screen->mode.vsync_len;
2319 win->area[i].dsp_sty = win->area[i].ypos +
2320 screen->mode.upper_margin +
2321 screen->mode.vsync_len;
2323 if ((win->area[i].xact != win->area[i].xsize) ||
2324 (win->area[i].yact != win->area[i].ysize)) {
2325 pr_err("win[%d]->area[%d],not support scale\n",
2327 pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
2328 win->area[i].xact,win->area[i].yact,
2329 win->area[i].xsize,win->area[i].ysize);
2330 win->area[i].xsize = win->area[i].xact;
2331 win->area[i].ysize = win->area[i].yact;
2335 rk3288_win_2_3_reg_update(&lcdc_dev->driver,2);
2336 spin_unlock(&lcdc_dev->reg_lock);
2340 static int win3_set_par(struct lcdc_device *lcdc_dev,
2341 struct rk_screen *screen, struct rk_lcdc_win *win)
2345 u8 fmt_cfg, swap_rb;
2347 spin_lock(&lcdc_dev->reg_lock);
2348 if (likely(lcdc_dev->clk_on)) {
2349 for (i = 0; i < win->area_num; i++) {
2350 switch (win->area[i].format) {
2369 dev_err(lcdc_dev->driver.dev,
2370 "%s:un supported format!\n",
2374 win->area[i].fmt_cfg = fmt_cfg;
2375 win->area[i].swap_rb = swap_rb;
2376 win->area[i].dsp_stx = win->area[i].xpos +
2377 screen->mode.left_margin +
2378 screen->mode.hsync_len;
2379 if (screen->y_mirror == 1) {
2380 win->area[i].dsp_sty = screen->mode.yres -
2382 win->area[i].ysize +
2383 screen->mode.upper_margin +
2384 screen->mode.vsync_len;
2386 win->area[i].dsp_sty = win->area[i].ypos +
2387 screen->mode.upper_margin +
2388 screen->mode.vsync_len;
2391 if ((win->area[i].xact != win->area[i].xsize) ||
2392 (win->area[i].yact != win->area[i].ysize)) {
2393 pr_err("win[%d]->area[%d],not support scale\n",
2395 pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
2396 win->area[i].xact,win->area[i].yact,
2397 win->area[i].xsize,win->area[i].ysize);
2398 win->area[i].xsize = win->area[i].xact;
2399 win->area[i].ysize = win->area[i].yact;
2402 rk3288_win_2_3_reg_update(&lcdc_dev->driver,3);
2403 spin_unlock(&lcdc_dev->reg_lock);
2407 static int rk3288_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id)
2409 struct lcdc_device *lcdc_dev =
2410 container_of(dev_drv, struct lcdc_device, driver);
2411 struct rk_lcdc_win *win = NULL;
2412 struct rk_screen *screen = dev_drv->cur_screen;
2413 win = dev_drv->win[win_id];
2418 win0_set_par(lcdc_dev, screen, win);
2421 win1_set_par(lcdc_dev, screen, win);
2424 win2_set_par(lcdc_dev, screen, win);
2427 win3_set_par(lcdc_dev, screen, win);
2430 dev_err(dev_drv->dev, "unsupported win number:%d\n", win_id);
2436 static int rk3288_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
2437 unsigned long arg, int win_id)
2439 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2444 void __user *argp = (void __user *)arg;
2445 struct color_key_cfg clr_key_cfg;
2448 case RK_FBIOGET_PANEL_SIZE:
2449 panel_size[0] = lcdc_dev->screen->mode.xres;
2450 panel_size[1] = lcdc_dev->screen->mode.yres;
2451 if (copy_to_user(argp, panel_size, 8))
2454 case RK_FBIOPUT_COLOR_KEY_CFG:
2455 if (copy_from_user(&clr_key_cfg, argp,
2456 sizeof(struct color_key_cfg)))
2458 rk3288_lcdc_clr_key_cfg(dev_drv);
2459 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
2460 clr_key_cfg.win0_color_key_cfg);
2461 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
2462 clr_key_cfg.win1_color_key_cfg);
2471 static int rk3288_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
2474 struct lcdc_device *lcdc_dev =
2475 container_of(dev_drv, struct lcdc_device, driver);
2476 if (dev_drv->suspend_flag)
2479 dev_drv->suspend_flag = 1;
2480 flush_kthread_worker(&dev_drv->update_regs_worker);
2482 for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4)
2483 lcdc_readl(lcdc_dev, reg);
2484 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
2485 dev_drv->trsm_ops->disable();
2487 spin_lock(&lcdc_dev->reg_lock);
2488 if (likely(lcdc_dev->clk_on)) {
2489 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2491 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR | m_LINE_FLAG_INTR_CLR,
2492 v_FS_INTR_CLR(1) | v_LINE_FLAG_INTR_CLR(1));
2493 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2495 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2497 lcdc_cfg_done(lcdc_dev);
2499 if (dev_drv->iommu_enabled) {
2500 if (dev_drv->mmu_dev)
2501 rockchip_iovmm_deactivate(dev_drv->dev);
2504 spin_unlock(&lcdc_dev->reg_lock);
2506 spin_unlock(&lcdc_dev->reg_lock);
2509 rk3288_lcdc_clk_disable(lcdc_dev);
2510 rk_disp_pwr_disable(dev_drv);
2514 static int rk3288_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
2516 struct lcdc_device *lcdc_dev =
2517 container_of(dev_drv, struct lcdc_device, driver);
2522 if (!dev_drv->suspend_flag)
2524 rk_disp_pwr_enable(dev_drv);
2525 dev_drv->suspend_flag = 0;
2527 if (lcdc_dev->atv_layer_cnt) {
2528 rk3288_lcdc_clk_enable(lcdc_dev);
2529 rk3288_lcdc_reg_restore(lcdc_dev);
2531 spin_lock(&lcdc_dev->reg_lock);
2532 if (dev_drv->cur_screen->dsp_lut) {
2533 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
2535 lcdc_cfg_done(lcdc_dev);
2537 for (i = 0; i < 256; i++) {
2538 v = dev_drv->cur_screen->dsp_lut[i];
2539 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
2540 b = (v & 0xff) << 2;
2541 g = (v & 0xff00) << 4;
2542 r = (v & 0xff0000) << 6;
2544 for (j = 0; j < 4; j++) {
2545 writel_relaxed(v, c);
2546 v += (1 + (1 << 10) + (1 << 20)) ;
2550 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
2554 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2556 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2558 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2560 lcdc_cfg_done(lcdc_dev);
2562 if (dev_drv->iommu_enabled) {
2563 if (dev_drv->mmu_dev)
2564 rockchip_iovmm_activate(dev_drv->dev);
2567 spin_unlock(&lcdc_dev->reg_lock);
2570 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
2571 dev_drv->trsm_ops->enable();
2576 static int rk3288_lcdc_blank(struct rk_lcdc_driver *dev_drv,
2577 int win_id, int blank_mode)
2579 switch (blank_mode) {
2580 case FB_BLANK_UNBLANK:
2581 rk3288_lcdc_early_resume(dev_drv);
2583 case FB_BLANK_NORMAL:
2584 rk3288_lcdc_early_suspend(dev_drv);
2587 rk3288_lcdc_early_suspend(dev_drv);
2591 dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
2596 static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
2597 int win_id, int area_id)
2599 struct lcdc_device *lcdc_dev =
2600 container_of(dev_drv, struct lcdc_device, driver);
2602 u32 area_status = 0;
2606 win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
2607 area_status = win_ctrl & m_WIN0_EN;
2610 win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
2611 area_status = win_ctrl & m_WIN1_EN;
2614 win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
2616 area_status = win_ctrl & m_WIN2_MST0_EN;
2618 area_status = win_ctrl & m_WIN2_MST1_EN;
2620 area_status = win_ctrl & m_WIN2_MST2_EN;
2622 area_status = win_ctrl & m_WIN2_MST3_EN;
2625 win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
2627 area_status = win_ctrl & m_WIN3_MST0_EN;
2629 area_status = win_ctrl & m_WIN3_MST1_EN;
2631 area_status = win_ctrl & m_WIN3_MST2_EN;
2633 area_status = win_ctrl & m_WIN3_MST3_EN;
2636 win_ctrl = lcdc_readl(lcdc_dev, HWC_CTRL0);
2637 area_status = win_ctrl & m_HWC_EN;
2640 pr_err("!!!%s,win[%d]area[%d],unsupport!!!\n",__func__,win_id,area_id);
2646 static int rk3288_lcdc_get_area_num(struct rk_lcdc_driver *dev_drv,
2647 unsigned int *area_support)
2649 area_support[0] = 1;
2650 area_support[1] = 1;
2651 area_support[2] = 4;
2652 area_support[3] = 4;
2657 /*overlay will be do at regupdate*/
2658 static int rk3288_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
2661 struct lcdc_device *lcdc_dev =
2662 container_of(dev_drv, struct lcdc_device, driver);
2663 struct rk_lcdc_win *win = NULL;
2665 unsigned int mask, val;
2667 int layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2670 win = dev_drv->win[i];
2671 if(win->state == 1){
2676 win = dev_drv->win[i];
2678 win->z_order = z_order_num++;
2679 switch(win->z_order){
2681 layer0_sel = win->id;
2684 layer1_sel = win->id;
2687 layer2_sel = win->id;
2690 layer3_sel = win->id;
2697 layer0_sel = swap %10;;
2698 layer1_sel = swap /10 % 10;
2699 layer2_sel = swap / 100 %10;
2700 layer3_sel = swap / 1000;
2703 spin_lock(&lcdc_dev->reg_lock);
2704 if(lcdc_dev->clk_on){
2706 mask = m_DSP_LAYER0_SEL | m_DSP_LAYER1_SEL |
2707 m_DSP_LAYER2_SEL | m_DSP_LAYER3_SEL;
2708 val = v_DSP_LAYER0_SEL(layer0_sel) |
2709 v_DSP_LAYER1_SEL(layer1_sel) |
2710 v_DSP_LAYER2_SEL(layer2_sel) |
2711 v_DSP_LAYER3_SEL(layer3_sel);
2712 lcdc_msk_reg(lcdc_dev,DSP_CTRL1,mask,val);
2714 layer0_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER0_SEL);
2715 layer1_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER1_SEL);
2716 layer2_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER2_SEL);
2717 layer3_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER3_SEL);
2718 ovl = layer3_sel*1000 + layer2_sel*100 + layer1_sel *10 + layer0_sel;
2723 spin_unlock(&lcdc_dev->reg_lock);
2728 static ssize_t rk3288_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
2729 char *buf, int win_id)
2731 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2735 struct rk_screen *screen = dev_drv->cur_screen;
2736 u16 hsync_len = screen->mode.hsync_len;
2737 u16 left_margin = screen->mode.left_margin;
2738 u16 vsync_len = screen->mode.vsync_len;
2739 u16 upper_margin = screen->mode.upper_margin;
2740 u32 h_pw_bp = hsync_len + left_margin;
2741 u32 v_pw_bp = vsync_len + upper_margin;
2743 char format_w0[9] = "NULL";
2744 char format_w1[9] = "NULL";
2745 char format_w2[9] = "NULL";
2746 char format_w3[9] = "NULL";
2747 u32 win_ctrl,zorder,vir_info,act_info,dsp_info,dsp_st,y_factor,uv_factor;
2748 u8 layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2749 u8 w0_state,w1_state,w2_state,w3_state;
2750 u8 w2_0_state,w2_1_state,w2_2_state,w2_3_state;
2751 u8 w3_0_state,w3_1_state,w3_2_state,w3_3_state;
2753 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;
2754 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;
2755 u32 w0_y_h_fac,w0_y_v_fac,w0_uv_h_fac,w0_uv_v_fac;
2756 u32 w1_y_h_fac,w1_y_v_fac,w1_uv_h_fac,w1_uv_v_fac;
2758 u32 w2_0_vir_y,w2_1_vir_y,w2_2_vir_y,w2_3_vir_y;
2759 u32 w2_0_dsp_x,w2_1_dsp_x,w2_2_dsp_x,w2_3_dsp_x;
2760 u32 w2_0_dsp_y,w2_1_dsp_y,w2_2_dsp_y,w2_3_dsp_y;
2761 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;
2762 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;
2764 u32 w3_0_vir_y,w3_1_vir_y,w3_2_vir_y,w3_3_vir_y;
2765 u32 w3_0_dsp_x,w3_1_dsp_x,w3_2_dsp_x,w3_3_dsp_x;
2766 u32 w3_0_dsp_y,w3_1_dsp_y,w3_2_dsp_y,w3_3_dsp_y;
2767 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;
2768 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;
2771 dclk_freq = screen->mode.pixclock;
2772 /*rk3288_lcdc_reg_dump(dev_drv);*/
2774 spin_lock(&lcdc_dev->reg_lock);
2775 if (lcdc_dev->clk_on) {
2776 zorder = lcdc_readl(lcdc_dev, DSP_CTRL1);
2777 layer0_sel = (zorder & m_DSP_LAYER0_SEL)>>8;
2778 layer1_sel = (zorder & m_DSP_LAYER1_SEL)>>10;
2779 layer2_sel = (zorder & m_DSP_LAYER2_SEL)>>12;
2780 layer3_sel = (zorder & m_DSP_LAYER3_SEL)>>14;
2782 win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
2783 w0_state = win_ctrl & m_WIN0_EN;
2784 fmt_id = (win_ctrl & m_WIN0_DATA_FMT)>>1;
2787 strcpy(format_w0, "ARGB888");
2790 strcpy(format_w0, "RGB888");
2793 strcpy(format_w0, "RGB565");
2796 strcpy(format_w0, "YCbCr420");
2799 strcpy(format_w0, "YCbCr422");
2802 strcpy(format_w0, "YCbCr444");
2805 strcpy(format_w0, "invalid\n");
2808 vir_info = lcdc_readl(lcdc_dev,WIN0_VIR);
2809 act_info = lcdc_readl(lcdc_dev,WIN0_ACT_INFO);
2810 dsp_info = lcdc_readl(lcdc_dev,WIN0_DSP_INFO);
2811 dsp_st = lcdc_readl(lcdc_dev,WIN0_DSP_ST);
2812 y_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_YRGB);
2813 uv_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_CBR);
2814 w0_vir_y = vir_info & m_WIN0_VIR_STRIDE;
2815 w0_vir_uv = (vir_info & m_WIN0_VIR_STRIDE_UV)>>16;
2816 w0_act_x = (act_info & m_WIN0_ACT_WIDTH)+1;
2817 w0_act_y = ((act_info & m_WIN0_ACT_HEIGHT)>>16)+1;
2818 w0_dsp_x = (dsp_info & m_WIN0_DSP_WIDTH)+1;
2819 w0_dsp_y = ((dsp_info & m_WIN0_DSP_HEIGHT)>>16)+1;
2821 w0_st_x = dsp_st & m_WIN0_DSP_XST;
2822 w0_st_y = (dsp_st & m_WIN0_DSP_YST)>>16;
2824 w0_y_h_fac = y_factor & m_WIN0_HS_FACTOR_YRGB;
2825 w0_y_v_fac = (y_factor & m_WIN0_VS_FACTOR_YRGB)>>16;
2826 w0_uv_h_fac = uv_factor & m_WIN0_HS_FACTOR_CBR;
2827 w0_uv_v_fac = (uv_factor & m_WIN0_VS_FACTOR_CBR)>>16;
2830 win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
2831 w1_state = win_ctrl & m_WIN1_EN;
2832 fmt_id = (win_ctrl & m_WIN1_DATA_FMT)>>1;
2835 strcpy(format_w1, "ARGB888");
2838 strcpy(format_w1, "RGB888");
2841 strcpy(format_w1, "RGB565");
2844 strcpy(format_w1, "YCbCr420");
2847 strcpy(format_w1, "YCbCr422");
2850 strcpy(format_w1, "YCbCr444");
2853 strcpy(format_w1, "invalid\n");
2856 vir_info = lcdc_readl(lcdc_dev,WIN1_VIR);
2857 act_info = lcdc_readl(lcdc_dev,WIN1_ACT_INFO);
2858 dsp_info = lcdc_readl(lcdc_dev,WIN1_DSP_INFO);
2859 dsp_st = lcdc_readl(lcdc_dev,WIN1_DSP_ST);
2860 y_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_YRGB);
2861 uv_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_CBR);
2862 w1_vir_y = vir_info & m_WIN1_VIR_STRIDE;
2863 w1_vir_uv = (vir_info & m_WIN1_VIR_STRIDE_UV)>>16;
2864 w1_act_x = (act_info & m_WIN1_ACT_WIDTH)+1;
2865 w1_act_y = ((act_info & m_WIN1_ACT_HEIGHT)>>16)+1;
2866 w1_dsp_x = (dsp_info & m_WIN1_DSP_WIDTH)+1;
2867 w1_dsp_y =((dsp_info & m_WIN1_DSP_HEIGHT)>>16)+1;
2869 w1_st_x = dsp_st & m_WIN1_DSP_XST;
2870 w1_st_y = (dsp_st & m_WIN1_DSP_YST)>>16;
2872 w1_y_h_fac = y_factor & m_WIN1_HS_FACTOR_YRGB;
2873 w1_y_v_fac = (y_factor & m_WIN1_VS_FACTOR_YRGB)>>16;
2874 w1_uv_h_fac = uv_factor & m_WIN1_HS_FACTOR_CBR;
2875 w1_uv_v_fac = (uv_factor & m_WIN1_VS_FACTOR_CBR)>>16;
2877 win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
2878 w2_state = win_ctrl & m_WIN2_EN;
2879 w2_0_state = (win_ctrl & m_WIN2_MST0_EN)>>4;
2880 w2_1_state = (win_ctrl & m_WIN2_MST1_EN)>>5;
2881 w2_2_state = (win_ctrl & m_WIN2_MST2_EN)>>6;
2882 w2_3_state = (win_ctrl & m_WIN2_MST3_EN)>>7;
2883 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR0_1);
2884 w2_0_vir_y = vir_info & m_WIN2_VIR_STRIDE0;
2885 w2_1_vir_y = (vir_info & m_WIN2_VIR_STRIDE1)>>16;
2886 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR2_3);
2887 w2_2_vir_y = vir_info & m_WIN2_VIR_STRIDE2;
2888 w2_3_vir_y = (vir_info & m_WIN2_VIR_STRIDE3)>>16;
2889 fmt_id = (win_ctrl & m_WIN2_DATA_FMT)>>1;
2892 strcpy(format_w2, "ARGB888");
2895 strcpy(format_w2, "RGB888");
2898 strcpy(format_w2, "RGB565");
2901 strcpy(format_w2,"8bpp");
2904 strcpy(format_w2,"4bpp");
2907 strcpy(format_w2,"2bpp");
2910 strcpy(format_w2,"1bpp");
2913 strcpy(format_w2, "invalid\n");
2916 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO0);
2917 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST0);
2918 w2_0_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH0)+1;
2919 w2_0_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT0)>>16)+1;
2921 w2_0_st_x = dsp_st & m_WIN2_DSP_XST0;
2922 w2_0_st_y = (dsp_st & m_WIN2_DSP_YST0)>>16;
2924 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO1);
2925 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST1);
2926 w2_1_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH1)+1;
2927 w2_1_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT1)>>16)+1;
2929 w2_1_st_x = dsp_st & m_WIN2_DSP_XST1;
2930 w2_1_st_y = (dsp_st & m_WIN2_DSP_YST1)>>16;
2932 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO2);
2933 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST2);
2934 w2_2_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH2)+1;
2935 w2_2_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT2)>>16)+1;
2937 w2_2_st_x = dsp_st & m_WIN2_DSP_XST2;
2938 w2_2_st_y = (dsp_st & m_WIN2_DSP_YST2)>>16;
2940 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO3);
2941 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST3);
2942 w2_3_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH3)+1;
2943 w2_3_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT3)>>16)+1;
2945 w2_3_st_x = dsp_st & m_WIN2_DSP_XST3;
2946 w2_3_st_y = (dsp_st & m_WIN2_DSP_YST3)>>16;
2950 win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
2951 w3_state = win_ctrl & m_WIN3_EN;
2952 w3_0_state = (win_ctrl & m_WIN3_MST0_EN)>>4;
2953 w3_1_state = (win_ctrl & m_WIN3_MST1_EN)>>5;
2954 w3_2_state = (win_ctrl & m_WIN3_MST2_EN)>>6;
2955 w3_3_state = (win_ctrl & m_WIN3_MST3_EN)>>7;
2956 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR0_1);
2957 w3_0_vir_y = vir_info & m_WIN3_VIR_STRIDE0;
2958 w3_1_vir_y = (vir_info & m_WIN3_VIR_STRIDE1)>>16;
2959 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR2_3);
2960 w3_2_vir_y = vir_info & m_WIN3_VIR_STRIDE2;
2961 w3_3_vir_y = (vir_info & m_WIN3_VIR_STRIDE3)>>16;
2962 fmt_id = (win_ctrl & m_WIN3_DATA_FMT)>>1;
2965 strcpy(format_w3, "ARGB888");
2968 strcpy(format_w3, "RGB888");
2971 strcpy(format_w3, "RGB565");
2974 strcpy(format_w3,"8bpp");
2977 strcpy(format_w3,"4bpp");
2980 strcpy(format_w3,"2bpp");
2983 strcpy(format_w3,"1bpp");
2986 strcpy(format_w3, "invalid");
2989 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO0);
2990 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST0);
2991 w3_0_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH0)+1;
2992 w3_0_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT0)>>16)+1;
2994 w3_0_st_x = dsp_st & m_WIN3_DSP_XST0;
2995 w3_0_st_y = (dsp_st & m_WIN3_DSP_YST0)>>16;
2998 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO1);
2999 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST1);
3000 w3_1_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH1)+1;
3001 w3_1_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT1)>>16)+1;
3003 w3_1_st_x = dsp_st & m_WIN3_DSP_XST1;
3004 w3_1_st_y = (dsp_st & m_WIN3_DSP_YST1)>>16;
3007 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO2);
3008 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST2);
3009 w3_2_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH2)+1;
3010 w3_2_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT2)>>16)+1;
3012 w3_2_st_x = dsp_st & m_WIN3_DSP_XST2;
3013 w3_2_st_y = (dsp_st & m_WIN3_DSP_YST2)>>16;
3016 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO3);
3017 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST3);
3018 w3_3_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH3)+1;
3019 w3_3_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT3)>>16)+1;
3021 w3_3_st_x = dsp_st & m_WIN3_DSP_XST3;
3022 w3_3_st_y = (dsp_st & m_WIN3_DSP_YST3)>>16;
3026 spin_unlock(&lcdc_dev->reg_lock);
3029 spin_unlock(&lcdc_dev->reg_lock);
3030 return snprintf(buf, PAGE_SIZE,
3032 " layer3_sel_win[%d]\n"
3033 " layer2_sel_win[%d]\n"
3034 " layer1_sel_win[%d]\n"
3035 " layer0_sel_win[%d]\n"
3140 layer3_sel,layer2_sel,layer1_sel,layer0_sel,
3141 w0_state,format_w0,w0_vir_y,w0_vir_uv,w0_act_x,w0_act_y,
3142 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,
3143 w0_uv_v_fac,lcdc_readl(lcdc_dev, WIN0_YRGB_MST),
3144 lcdc_readl(lcdc_dev, WIN0_CBR_MST),
3146 w1_state,format_w1,w1_vir_y,w1_vir_uv,w1_act_x,w1_act_y,
3147 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,
3148 w1_uv_v_fac,lcdc_readl(lcdc_dev, WIN1_YRGB_MST),
3149 lcdc_readl(lcdc_dev, WIN1_CBR_MST),
3152 w2_0_state,w2_0_vir_y,w2_0_dsp_x,w2_0_dsp_y,
3153 w2_0_st_x-h_pw_bp,w2_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST0),
3155 w2_1_state,w2_1_vir_y,w2_1_dsp_x,w2_1_dsp_y,
3156 w2_1_st_x-h_pw_bp,w2_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST1),
3158 w2_2_state,w2_2_vir_y,w2_2_dsp_x,w2_2_dsp_y,
3159 w2_2_st_x-h_pw_bp,w2_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST2),
3161 w2_3_state,w2_3_vir_y,w2_3_dsp_x,w2_3_dsp_y,
3162 w2_3_st_x-h_pw_bp,w2_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST3),
3165 w3_0_state,w3_0_vir_y,w3_0_dsp_x,w3_0_dsp_y,
3166 w3_0_st_x-h_pw_bp,w3_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST0),
3168 w3_1_state,w3_1_vir_y,w3_1_dsp_x,w3_1_dsp_y,
3169 w3_1_st_x-h_pw_bp,w3_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST1),
3171 w3_2_state,w3_2_vir_y,w3_2_dsp_x,w3_2_dsp_y,
3172 w3_2_st_x-h_pw_bp,w3_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST2),
3174 w3_3_state,w3_3_vir_y,w3_3_dsp_x,w3_3_dsp_y,
3175 w3_3_st_x-h_pw_bp,w3_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST3)
3180 static int rk3288_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
3183 struct lcdc_device *lcdc_dev =
3184 container_of(dev_drv, struct lcdc_device, driver);
3185 struct rk_screen *screen = dev_drv->cur_screen;
3190 u32 x_total, y_total;
3193 dev_info(dev_drv->dev, "unsupport set fps=0\n");
3196 ft = div_u64(1000000000000llu, fps);
3198 screen->mode.upper_margin + screen->mode.lower_margin +
3199 screen->mode.yres + screen->mode.vsync_len;
3201 screen->mode.left_margin + screen->mode.right_margin +
3202 screen->mode.xres + screen->mode.hsync_len;
3203 dev_drv->pixclock = div_u64(ft, x_total * y_total);
3204 dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
3205 ret = clk_set_rate(lcdc_dev->dclk, dotclk);
3208 pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
3209 dev_drv->pixclock = lcdc_dev->pixclock = pixclock;
3210 fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
3211 screen->ft = 1000 / fps; /*one frame time in ms */
3214 dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
3215 clk_get_rate(lcdc_dev->dclk), fps);
3220 static int rk3288_fb_win_remap(struct rk_lcdc_driver *dev_drv, u16 order)
3222 mutex_lock(&dev_drv->fb_win_id_mutex);
3223 if (order == FB_DEFAULT_ORDER)
3224 order = FB0_WIN0_FB1_WIN1_FB2_WIN2_FB3_WIN3;
3225 dev_drv->fb3_win_id = order / 1000;
3226 dev_drv->fb2_win_id = (order / 100) % 10;
3227 dev_drv->fb1_win_id = (order / 10) % 10;
3228 dev_drv->fb0_win_id = order % 10;
3229 mutex_unlock(&dev_drv->fb_win_id_mutex);
3234 static int rk3288_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
3238 mutex_lock(&dev_drv->fb_win_id_mutex);
3239 if (!strcmp(id, "fb0") || !strcmp(id, "fb4"))
3240 win_id = dev_drv->fb0_win_id;
3241 else if (!strcmp(id, "fb1") || !strcmp(id, "fb5"))
3242 win_id = dev_drv->fb1_win_id;
3243 else if (!strcmp(id, "fb2") || !strcmp(id, "fb6"))
3244 win_id = dev_drv->fb2_win_id;
3245 else if (!strcmp(id, "fb3") || !strcmp(id, "fb7"))
3246 win_id = dev_drv->fb3_win_id;
3247 mutex_unlock(&dev_drv->fb_win_id_mutex);
3252 static int rk3288_set_dsp_lut(struct rk_lcdc_driver *dev_drv, int *lut)
3259 struct lcdc_device *lcdc_dev =
3260 container_of(dev_drv, struct lcdc_device, driver);
3261 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
3262 lcdc_cfg_done(lcdc_dev);
3264 if (dev_drv->cur_screen->dsp_lut) {
3265 for (i = 0; i < 256; i++) {
3266 v = dev_drv->cur_screen->dsp_lut[i] = lut[i];
3267 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
3268 b = (v & 0xff) << 2;
3269 g = (v & 0xff00) << 4;
3270 r = (v & 0xff0000) << 6;
3272 for (j = 0; j < 4; j++) {
3273 writel_relaxed(v, c);
3274 v += (1 + (1 << 10) + (1 << 20)) ;
3279 dev_err(dev_drv->dev, "no buffer to backup lut data!\n");
3284 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
3285 lcdc_cfg_done(lcdc_dev);
3286 }while(!lcdc_read_bit(lcdc_dev,DSP_CTRL1,m_DSP_LUT_EN));
3290 static int rk3288_lcdc_config_done(struct rk_lcdc_driver *dev_drv)
3292 struct lcdc_device *lcdc_dev =
3293 container_of(dev_drv, struct lcdc_device, driver);
3295 unsigned int mask, val;
3296 struct rk_lcdc_win *win = NULL;
3297 spin_lock(&lcdc_dev->reg_lock);
3298 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
3299 v_STANDBY_EN(lcdc_dev->standby));
3301 win = dev_drv->win[i];
3302 if ((win->state == 0)&&(win->last_state == 1)) {
3305 lcdc_writel(lcdc_dev,WIN0_CTRL1,0x0);
3308 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask,val);
3311 lcdc_writel(lcdc_dev,WIN1_CTRL1,0x0);
3314 lcdc_msk_reg(lcdc_dev, WIN1_CTRL0, mask,val);
3317 mask = m_WIN2_EN | m_WIN2_MST0_EN | m_WIN2_MST1_EN |
3318 m_WIN2_MST2_EN | m_WIN2_MST3_EN;
3319 val = v_WIN2_EN(0) | v_WIN2_MST0_EN(0) | v_WIN2_MST1_EN(0) |
3320 v_WIN2_MST2_EN(0) | v_WIN2_MST3_EN(0);
3321 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0, mask,val);
3324 mask = m_WIN3_EN | m_WIN3_MST0_EN | m_WIN3_MST1_EN |
3325 m_WIN3_MST2_EN | m_WIN3_MST3_EN;
3326 val = v_WIN3_EN(0) | v_WIN3_MST0_EN(0) | v_WIN3_MST1_EN(0) |
3327 v_WIN3_MST2_EN(0) | v_WIN3_MST3_EN(0);
3328 lcdc_msk_reg(lcdc_dev, WIN3_CTRL0, mask,val);
3334 win->last_state = win->state;
3336 lcdc_cfg_done(lcdc_dev);
3337 spin_unlock(&lcdc_dev->reg_lock);
3342 static int rk3288_lcdc_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
3344 struct lcdc_device *lcdc_dev =
3345 container_of(dev_drv, struct lcdc_device, driver);
3346 spin_lock(&lcdc_dev->reg_lock);
3347 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN,
3348 v_DIRECT_PATH_EN(open));
3349 lcdc_cfg_done(lcdc_dev);
3350 spin_unlock(&lcdc_dev->reg_lock);
3354 static int rk3288_lcdc_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id)
3356 struct lcdc_device *lcdc_dev = container_of(dev_drv,
3357 struct lcdc_device, driver);
3358 spin_lock(&lcdc_dev->reg_lock);
3359 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATCH_SEL,
3360 v_DIRECT_PATCH_SEL(win_id));
3361 lcdc_cfg_done(lcdc_dev);
3362 spin_unlock(&lcdc_dev->reg_lock);
3367 static int rk3288_lcdc_dpi_status(struct rk_lcdc_driver *dev_drv)
3369 struct lcdc_device *lcdc_dev =
3370 container_of(dev_drv, struct lcdc_device, driver);
3372 spin_lock(&lcdc_dev->reg_lock);
3373 ovl = lcdc_read_bit(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN);
3374 spin_unlock(&lcdc_dev->reg_lock);
3377 static int rk3288_lcdc_set_irq_to_cpu(struct rk_lcdc_driver * dev_drv,int enable)
3379 struct lcdc_device *lcdc_dev =
3380 container_of(dev_drv,struct lcdc_device,driver);
3382 enable_irq(lcdc_dev->irq);
3384 disable_irq(lcdc_dev->irq);
3388 int rk3288_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
3390 struct lcdc_device *lcdc_dev =
3391 container_of(dev_drv, struct lcdc_device, driver);
3395 if (lcdc_dev->clk_on &&(!dev_drv->suspend_flag)){
3396 int_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3397 if (int_reg & m_LINE_FLAG_INTR_STS) {
3398 lcdc_dev->driver.frame_time.last_framedone_t =
3399 lcdc_dev->driver.frame_time.framedone_t;
3400 lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
3401 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3402 v_LINE_FLAG_INTR_CLR(1));
3403 ret = RK_LF_STATUS_FC;
3405 ret = RK_LF_STATUS_FR;
3407 ret = RK_LF_STATUS_NC;
3413 static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
3414 unsigned int dsp_addr[][4])
3416 struct lcdc_device *lcdc_dev =
3417 container_of(dev_drv, struct lcdc_device, driver);
3418 spin_lock(&lcdc_dev->reg_lock);
3419 if (lcdc_dev->clk_on) {
3420 dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
3421 dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
3422 dsp_addr[2][0] = lcdc_readl(lcdc_dev, WIN2_MST0);
3423 dsp_addr[2][1] = lcdc_readl(lcdc_dev, WIN2_MST1);
3424 dsp_addr[2][2] = lcdc_readl(lcdc_dev, WIN2_MST2);
3425 dsp_addr[2][3] = lcdc_readl(lcdc_dev, WIN2_MST3);
3426 dsp_addr[3][0] = lcdc_readl(lcdc_dev, WIN3_MST0);
3427 dsp_addr[3][1] = lcdc_readl(lcdc_dev, WIN3_MST1);
3428 dsp_addr[3][2] = lcdc_readl(lcdc_dev, WIN3_MST2);
3429 dsp_addr[3][3] = lcdc_readl(lcdc_dev, WIN3_MST3);
3431 spin_unlock(&lcdc_dev->reg_lock);
3435 static struct lcdc_cabc_mode cabc_mode[4] = {
3436 /* pixel_num, stage_up, stage_down */
3437 {5, 128, 0}, /*mode 1*/
3438 {10, 128, 0}, /*mode 2*/
3439 {15, 128, 0}, /*mode 3*/
3440 {20, 128, 0}, /*mode 4*/
3443 static int __maybe_unused
3444 rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode)
3446 struct lcdc_device *lcdc_dev =
3447 container_of(dev_drv, struct lcdc_device, driver);
3448 struct rk_screen *screen = dev_drv->cur_screen;
3449 u32 total_pixel, calc_pixel, stage_up, stage_down, pixel_num;
3450 u32 mask = 0, val = 0, cabc_en = 0;
3451 u32 max_mode_num = sizeof(cabc_mode) / sizeof(struct lcdc_cabc_mode);
3453 dev_drv->cabc_mode = mode;
3455 /* iomux connect to vop or pwm */
3457 DBG(3, "close cabc and select rk pwm\n");
3459 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3461 } else if (mode > 0 && mode <= max_mode_num) {
3462 DBG(3, "open cabc and select vop pwm\n");
3463 val = (dev_drv->id == 0) ? 0x30002 : 0x30003;
3464 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3466 } else if (mode > 0x10 && mode <= (max_mode_num + 0x10)) {
3467 DBG(3, "open cabc and select rk pwm\n");
3469 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3472 } else if (mode == 0xff) {
3473 DBG(3, "close cabc and select vop pwm\n");
3474 val = (dev_drv->id == 0) ? 0x30002 : 0x30003;
3475 writel_relaxed(val, RK_GRF_VIRT + RK3288_GRF_GPIO7A_IOMUX);
3478 dev_err(lcdc_dev->dev, "invalid cabc mode value:%d", mode);
3483 spin_lock(&lcdc_dev->reg_lock);
3484 if(lcdc_dev->clk_on) {
3485 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, m_CABC_EN, v_CABC_EN(0));
3486 lcdc_cfg_done(lcdc_dev);
3488 spin_unlock(&lcdc_dev->reg_lock);
3492 total_pixel = screen->mode.xres * screen->mode.yres;
3493 pixel_num = 1000 - (cabc_mode[mode - 1].pixel_num);
3494 calc_pixel = (total_pixel * pixel_num) / 1000;
3495 stage_up = cabc_mode[mode - 1].stage_up;
3496 stage_down = cabc_mode[mode - 1].stage_down;
3498 spin_lock(&lcdc_dev->reg_lock);
3499 if(lcdc_dev->clk_on) {
3500 mask = m_CABC_TOTAL_NUM | m_CABC_STAGE_DOWN;
3501 val = v_CABC_TOTAL_NUM(total_pixel) | v_CABC_STAGE_DOWN(stage_down);
3502 lcdc_msk_reg(lcdc_dev, CABC_CTRL1, mask, val);
3504 mask = m_CABC_EN | m_CABC_CALC_PIXEL_NUM |
3506 val = v_CABC_EN(1) | v_CABC_CALC_PIXEL_NUM(calc_pixel) |
3507 v_CABC_STAGE_UP(stage_up);
3508 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
3509 lcdc_cfg_done(lcdc_dev);
3511 spin_unlock(&lcdc_dev->reg_lock);
3517 sin_hue = sin(a)*256 +0x100;
3518 cos_hue = cos(a)*256;
3520 sin_hue = sin(a)*256;
3521 cos_hue = cos(a)*256;
3523 static int rk3288_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode)
3526 struct lcdc_device *lcdc_dev =
3527 container_of(dev_drv, struct lcdc_device, driver);
3530 spin_lock(&lcdc_dev->reg_lock);
3531 if (lcdc_dev->clk_on) {
3532 val = lcdc_readl(lcdc_dev, BCSH_H);
3535 val &= m_BCSH_SIN_HUE;
3538 val &= m_BCSH_COS_HUE;
3545 spin_unlock(&lcdc_dev->reg_lock);
3551 static int rk3288_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue)
3554 struct lcdc_device *lcdc_dev =
3555 container_of(dev_drv, struct lcdc_device, driver);
3558 spin_lock(&lcdc_dev->reg_lock);
3559 if (lcdc_dev->clk_on) {
3560 mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
3561 val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
3562 lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
3563 lcdc_cfg_done(lcdc_dev);
3565 spin_unlock(&lcdc_dev->reg_lock);
3570 static int rk3288_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value)
3572 struct lcdc_device *lcdc_dev =
3573 container_of(dev_drv, struct lcdc_device, driver);
3576 spin_lock(&lcdc_dev->reg_lock);
3577 if(lcdc_dev->clk_on) {
3580 /*from 0 to 255,typical is 128*/
3583 else if (value >= 0x80)
3584 value = value - 0x80;
3585 mask = m_BCSH_BRIGHTNESS;
3586 val = v_BCSH_BRIGHTNESS(value);
3589 /*from 0 to 510,typical is 256*/
3590 mask = m_BCSH_CONTRAST;
3591 val = v_BCSH_CONTRAST(value);
3594 /*from 0 to 1015,typical is 256*/
3595 mask = m_BCSH_SAT_CON;
3596 val = v_BCSH_SAT_CON(value);
3601 lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
3602 lcdc_cfg_done(lcdc_dev);
3604 spin_unlock(&lcdc_dev->reg_lock);
3608 static int rk3288_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode)
3610 struct lcdc_device *lcdc_dev =
3611 container_of(dev_drv, struct lcdc_device, driver);
3614 spin_lock(&lcdc_dev->reg_lock);
3615 if(lcdc_dev->clk_on) {
3616 val = lcdc_readl(lcdc_dev, BCSH_BCS);
3619 val &= m_BCSH_BRIGHTNESS;
3626 val &= m_BCSH_CONTRAST;
3630 val &= m_BCSH_SAT_CON;
3637 spin_unlock(&lcdc_dev->reg_lock);
3642 static int rk3288_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
3644 struct lcdc_device *lcdc_dev =
3645 container_of(dev_drv, struct lcdc_device, driver);
3648 spin_lock(&lcdc_dev->reg_lock);
3649 if (lcdc_dev->clk_on) {
3651 lcdc_writel(lcdc_dev,BCSH_COLOR_BAR,0x1);
3652 lcdc_writel(lcdc_dev,BCSH_BCS,0xd0010000);
3653 lcdc_writel(lcdc_dev,BCSH_H,0x01000000);
3657 lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
3659 lcdc_cfg_done(lcdc_dev);
3661 spin_unlock(&lcdc_dev->reg_lock);
3665 static int rk3288_lcdc_set_bcsh(struct rk_lcdc_driver *dev_drv,
3668 if (!enable || !dev_drv->bcsh.enable) {
3669 rk3288_lcdc_open_bcsh(dev_drv, false);
3673 if (dev_drv->bcsh.brightness <= 255 ||
3674 dev_drv->bcsh.contrast <= 510 ||
3675 dev_drv->bcsh.sat_con <= 1015 ||
3676 (dev_drv->bcsh.sin_hue <= 511 && dev_drv->bcsh.cos_hue <= 511)) {
3677 rk3288_lcdc_open_bcsh(dev_drv, true);
3678 if (dev_drv->bcsh.brightness <= 255)
3679 rk3288_lcdc_set_bcsh_bcs(dev_drv, BRIGHTNESS,
3680 dev_drv->bcsh.brightness);
3681 if (dev_drv->bcsh.contrast <= 510)
3682 rk3288_lcdc_set_bcsh_bcs(dev_drv, CONTRAST,
3683 dev_drv->bcsh.contrast);
3684 if (dev_drv->bcsh.sat_con <= 1015)
3685 rk3288_lcdc_set_bcsh_bcs(dev_drv, SAT_CON,
3686 dev_drv->bcsh.sat_con);
3687 if (dev_drv->bcsh.sin_hue <= 511 &&
3688 dev_drv->bcsh.cos_hue <= 511)
3689 rk3288_lcdc_set_bcsh_hue(dev_drv,
3690 dev_drv->bcsh.sin_hue,
3691 dev_drv->bcsh.cos_hue);
3696 static int rk3288_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
3697 struct overscan *overscan)
3699 struct lcdc_device *lcdc_dev =
3700 container_of(dev_drv, struct lcdc_device, driver);
3702 if (unlikely(!lcdc_dev->clk_on)) {
3703 pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
3706 rk3288_lcdc_post_cfg(dev_drv);
3711 static struct rk_lcdc_win lcdc_win[] = {
3715 .support_3d = false,
3720 .support_3d = false,
3725 .support_3d = false,
3730 .support_3d = false,
3734 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
3735 .open = rk3288_lcdc_open,
3736 .win_direct_en = rk3288_lcdc_win_direct_en,
3737 .load_screen = rk3288_load_screen,
3738 .get_dspbuf_info = rk3288_get_dspbuf_info,
3739 .post_dspbuf = rk3288_post_dspbuf,
3740 .set_par = rk3288_lcdc_set_par,
3741 .pan_display = rk3288_lcdc_pan_display,
3742 .direct_set_addr = rk3288_lcdc_direct_set_win_addr,
3743 .lcdc_reg_update = rk3288_lcdc_reg_update,
3744 .blank = rk3288_lcdc_blank,
3745 .ioctl = rk3288_lcdc_ioctl,
3746 .suspend = rk3288_lcdc_early_suspend,
3747 .resume = rk3288_lcdc_early_resume,
3748 .get_win_state = rk3288_lcdc_get_win_state,
3749 .area_support_num = rk3288_lcdc_get_area_num,
3750 .ovl_mgr = rk3288_lcdc_ovl_mgr,
3751 .get_disp_info = rk3288_lcdc_get_disp_info,
3752 .fps_mgr = rk3288_lcdc_fps_mgr,
3753 .fb_get_win_id = rk3288_lcdc_get_win_id,
3754 .fb_win_remap = rk3288_fb_win_remap,
3755 .set_dsp_lut = rk3288_set_dsp_lut,
3756 .poll_vblank = rk3288_lcdc_poll_vblank,
3757 .dpi_open = rk3288_lcdc_dpi_open,
3758 .dpi_win_sel = rk3288_lcdc_dpi_win_sel,
3759 .dpi_status = rk3288_lcdc_dpi_status,
3760 .get_dsp_addr = rk3288_lcdc_get_dsp_addr,
3761 /*.set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,*/
3762 .set_dsp_bcsh_hue = rk3288_lcdc_set_bcsh_hue,
3763 .set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
3764 .get_dsp_bcsh_hue = rk3288_lcdc_get_bcsh_hue,
3765 .get_dsp_bcsh_bcs = rk3288_lcdc_get_bcsh_bcs,
3766 .open_bcsh = rk3288_lcdc_open_bcsh,
3767 .dump_reg = rk3288_lcdc_reg_dump,
3768 .cfg_done = rk3288_lcdc_config_done,
3769 .set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,
3770 .mmu_en = rk3288_lcdc_mmu_en,
3771 .set_overscan = rk3288_lcdc_set_overscan,
3775 #ifdef LCDC_IRQ_DEBUG
3776 static int rk3288_lcdc_parse_irq(struct lcdc_device *lcdc_dev,unsigned int reg_val)
3778 if (reg_val & m_WIN0_EMPTY_INTR_STS) {
3779 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN0_EMPTY_INTR_CLR,
3780 v_WIN0_EMPTY_INTR_CLR(1));
3781 dev_warn(lcdc_dev->dev,"win0 empty irq!");
3782 }else if (reg_val & m_WIN1_EMPTY_INTR_STS) {
3783 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN1_EMPTY_INTR_CLR,
3784 v_WIN1_EMPTY_INTR_CLR(1));
3785 dev_warn(lcdc_dev->dev,"win1 empty irq!");
3786 }else if (reg_val & m_WIN2_EMPTY_INTR_STS) {
3787 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN2_EMPTY_INTR_CLR,
3788 v_WIN2_EMPTY_INTR_CLR(1));
3789 dev_warn(lcdc_dev->dev,"win2 empty irq!");
3790 }else if (reg_val & m_WIN3_EMPTY_INTR_STS) {
3791 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN3_EMPTY_INTR_CLR,
3792 v_WIN3_EMPTY_INTR_CLR(1));
3793 dev_warn(lcdc_dev->dev,"win3 empty irq!");
3794 }else if (reg_val & m_HWC_EMPTY_INTR_STS) {
3795 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_HWC_EMPTY_INTR_CLR,
3796 v_HWC_EMPTY_INTR_CLR(1));
3797 dev_warn(lcdc_dev->dev,"HWC empty irq!");
3798 }else if (reg_val & m_POST_BUF_EMPTY_INTR_STS) {
3799 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_POST_BUF_EMPTY_INTR_CLR,
3800 v_POST_BUF_EMPTY_INTR_CLR(1));
3801 dev_warn(lcdc_dev->dev,"post buf empty irq!");
3802 }else if (reg_val & m_PWM_GEN_INTR_STS) {
3803 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_PWM_GEN_INTR_CLR,
3804 v_PWM_GEN_INTR_CLR(1));
3805 dev_warn(lcdc_dev->dev,"PWM gen irq!");
3812 static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
3814 struct lcdc_device *lcdc_dev =
3815 (struct lcdc_device *)dev_id;
3816 ktime_t timestamp = ktime_get();
3819 intr0_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3821 if(intr0_reg & m_FS_INTR_STS){
3822 timestamp = ktime_get();
3823 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR,
3825 /*if(lcdc_dev->driver.wait_fs){ */
3827 spin_lock(&(lcdc_dev->driver.cpl_lock));
3828 complete(&(lcdc_dev->driver.frame_done));
3829 spin_unlock(&(lcdc_dev->driver.cpl_lock));
3831 #ifdef CONFIG_DRM_ROCKCHIP
3832 lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
3834 lcdc_dev->driver.vsync_info.timestamp = timestamp;
3835 wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
3837 }else if(intr0_reg & m_LINE_FLAG_INTR_STS){
3838 lcdc_dev->driver.frame_time.last_framedone_t =
3839 lcdc_dev->driver.frame_time.framedone_t;
3840 lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
3841 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3842 v_LINE_FLAG_INTR_CLR(1));
3843 }else if(intr0_reg & m_BUS_ERROR_INTR_STS){
3844 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_BUS_ERROR_INTR_CLR,
3845 v_BUS_ERROR_INTR_CLR(1));
3846 dev_warn(lcdc_dev->dev,"buf_error_int!");
3849 /* for win empty debug */
3850 #ifdef LCDC_IRQ_EMPTY_DEBUG
3851 intr1_reg = lcdc_readl(lcdc_dev, INTR_CTRL1);
3852 if (intr1_reg != 0) {
3853 rk3288_lcdc_parse_irq(lcdc_dev,intr1_reg);
3859 #if defined(CONFIG_PM)
3860 static int rk3288_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
3865 static int rk3288_lcdc_resume(struct platform_device *pdev)
3870 #define rk3288_lcdc_suspend NULL
3871 #define rk3288_lcdc_resume NULL
3874 static int rk3288_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
3876 struct device_node *np = lcdc_dev->dev->of_node;
3877 struct rk_lcdc_driver *dev_drv = &lcdc_dev->driver;
3880 if (of_property_read_u32(np, "rockchip,prop", &val))
3881 lcdc_dev->prop = PRMRY; /*default set it as primary */
3883 lcdc_dev->prop = val;
3885 if (of_property_read_u32(np, "rockchip,mirror", &val))
3886 dev_drv->rotate_mode = NO_MIRROR;
3888 dev_drv->rotate_mode = val;
3890 if (of_property_read_u32(np, "rockchip,cabc_mode", &val))
3891 dev_drv->cabc_mode = 0; /* default set close cabc */
3893 dev_drv->cabc_mode = val;
3895 if (of_property_read_u32(np, "rockchip,pwr18", &val))
3896 lcdc_dev->pwr18 = false; /*default set it as 3.xv power supply */
3898 lcdc_dev->pwr18 = (val ? true : false);
3900 if (of_property_read_u32(np, "rockchip,fb-win-map", &val))
3901 dev_drv->fb_win_map = FB_DEFAULT_ORDER;
3903 dev_drv->fb_win_map = val;
3905 if (of_property_read_u32(np, "rockchip,bcsh-en", &val))
3906 dev_drv->bcsh.enable = false;
3908 dev_drv->bcsh.enable = (val ? true : false);
3910 if (of_property_read_u32(np, "rockchip,brightness", &val))
3911 dev_drv->bcsh.brightness = 0xffff;
3913 dev_drv->bcsh.brightness = val;
3915 if (of_property_read_u32(np, "rockchip,contrast", &val))
3916 dev_drv->bcsh.contrast = 0xffff;
3918 dev_drv->bcsh.contrast = val;
3920 if (of_property_read_u32(np, "rockchip,sat-con", &val))
3921 dev_drv->bcsh.sat_con = 0xffff;
3923 dev_drv->bcsh.sat_con = val;
3925 if (of_property_read_u32(np, "rockchip,hue", &val)) {
3926 dev_drv->bcsh.sin_hue = 0xffff;
3927 dev_drv->bcsh.cos_hue = 0xffff;
3929 dev_drv->bcsh.sin_hue = val & 0xff;
3930 dev_drv->bcsh.cos_hue = (val >> 8) & 0xff;
3933 #if defined(CONFIG_ROCKCHIP_IOMMU)
3934 if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
3935 dev_drv->iommu_enabled = 0;
3937 dev_drv->iommu_enabled = val;
3939 dev_drv->iommu_enabled = 0;
3944 static int rk3288_lcdc_probe(struct platform_device *pdev)
3946 struct lcdc_device *lcdc_dev = NULL;
3947 struct rk_lcdc_driver *dev_drv;
3948 struct device *dev = &pdev->dev;
3949 struct resource *res;
3950 struct device_node *np = pdev->dev.of_node;
3954 /*if the primary lcdc has not registered ,the extend
3955 lcdc register later */
3956 of_property_read_u32(np, "rockchip,prop", &prop);
3957 if (prop == EXTEND) {
3958 if (!is_prmry_rk_lcdc_registered())
3959 return -EPROBE_DEFER;
3961 lcdc_dev = devm_kzalloc(dev,
3962 sizeof(struct lcdc_device), GFP_KERNEL);
3964 dev_err(&pdev->dev, "rk3288 lcdc device kmalloc fail!");
3967 platform_set_drvdata(pdev, lcdc_dev);
3968 lcdc_dev->dev = dev;
3969 rk3288_lcdc_parse_dt(lcdc_dev);
3970 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3971 lcdc_dev->reg_phy_base = res->start;
3972 lcdc_dev->len = resource_size(res);
3973 lcdc_dev->regs = devm_ioremap_resource(dev, res);
3974 if (IS_ERR(lcdc_dev->regs))
3975 return PTR_ERR(lcdc_dev->regs);
3977 lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
3978 if (IS_ERR(lcdc_dev->regsbak))
3979 return PTR_ERR(lcdc_dev->regsbak);
3980 lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs + GAMMA_LUT_ADDR);
3981 lcdc_dev->id = rk3288_lcdc_get_id(lcdc_dev->reg_phy_base);
3982 if (lcdc_dev->id < 0) {
3983 dev_err(&pdev->dev, "no such lcdc device!\n");
3986 dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
3987 dev_drv = &lcdc_dev->driver;
3989 dev_drv->prop = prop;
3990 dev_drv->id = lcdc_dev->id;
3991 dev_drv->ops = &lcdc_drv_ops;
3992 dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
3993 spin_lock_init(&lcdc_dev->reg_lock);
3995 lcdc_dev->irq = platform_get_irq(pdev, 0);
3996 if (lcdc_dev->irq < 0) {
3997 dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
4002 ret = devm_request_irq(dev, lcdc_dev->irq, rk3288_lcdc_isr,
4003 IRQF_DISABLED | IRQF_SHARED, dev_name(dev), lcdc_dev);
4005 dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
4006 lcdc_dev->irq, ret);
4010 if (dev_drv->iommu_enabled) {
4011 if(lcdc_dev->id == 0){
4012 strcpy(dev_drv->mmu_dts_name, VOPB_IOMMU_COMPATIBLE_NAME);
4014 strcpy(dev_drv->mmu_dts_name, VOPL_IOMMU_COMPATIBLE_NAME);
4018 ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
4020 dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
4023 lcdc_dev->screen = dev_drv->screen0;
4024 dev_info(dev, "lcdc%d probe ok, iommu %s\n",
4025 lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
4030 static int rk3288_lcdc_remove(struct platform_device *pdev)
4036 static void rk3288_lcdc_shutdown(struct platform_device *pdev)
4038 struct lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
4040 rk3288_lcdc_deint(lcdc_dev);
4041 rk_disp_pwr_disable(&lcdc_dev->driver);
4044 #if defined(CONFIG_OF)
4045 static const struct of_device_id rk3288_lcdc_dt_ids[] = {
4046 {.compatible = "rockchip,rk3288-lcdc",},
4051 static struct platform_driver rk3288_lcdc_driver = {
4052 .probe = rk3288_lcdc_probe,
4053 .remove = rk3288_lcdc_remove,
4055 .name = "rk3288-lcdc",
4056 .owner = THIS_MODULE,
4057 .of_match_table = of_match_ptr(rk3288_lcdc_dt_ids),
4059 .suspend = rk3288_lcdc_suspend,
4060 .resume = rk3288_lcdc_resume,
4061 .shutdown = rk3288_lcdc_shutdown,
4064 static int __init rk3288_lcdc_module_init(void)
4066 return platform_driver_register(&rk3288_lcdc_driver);
4069 static void __exit rk3288_lcdc_module_exit(void)
4071 platform_driver_unregister(&rk3288_lcdc_driver);
4074 fs_initcall(rk3288_lcdc_module_init);
4075 module_exit(rk3288_lcdc_module_exit);