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 struct fb_info *rk_get_fb(int fb_id);
55 /*#define WAIT_FOR_SYNC 1*/
57 static int rk3288_lcdc_get_id(u32 phy_base)
59 if (cpu_is_rk3288()) {
60 if (phy_base == 0xff930000)/*vop big*/
62 else if (phy_base == 0xff940000)/*vop lit*/
67 pr_err("un supported platform \n");
72 static int rk3288_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
77 struct lcdc_device *lcdc_dev = container_of(dev_drv,
78 struct lcdc_device,driver);
79 if (dev_drv->cur_screen->dsp_lut)
80 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
82 if ((dev_drv->cur_screen->cabc_lut) &&
83 (dev_drv->version == VOP_FULL_RK3288_V1_1))
84 lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN,
86 lcdc_cfg_done(lcdc_dev);
88 if (dev_drv->cur_screen->dsp_lut) {
89 for (i = 0; i < 256; i++) {
90 v = dev_drv->cur_screen->dsp_lut[i];
91 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
93 g = (v & 0xff00) << 4;
94 r = (v & 0xff0000) << 6;
96 for (j = 0; j < 4; j++) {
98 v += (1 + (1 << 10) + (1 << 20));
102 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
105 if ((dev_drv->cur_screen->cabc_lut) &&
106 (dev_drv->version == VOP_FULL_RK3288_V1_1)) {
107 for (i = 0; i < 128; i++) {
108 v = dev_drv->cur_screen->cabc_lut[i];
109 lcdc_writel(lcdc_dev, i * 4 + CABC_LUT_ADDR, v);
111 lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN,
119 static int rk3288_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
121 #ifdef CONFIG_RK_FPGA
122 lcdc_dev->clk_on = 1;
125 if (!lcdc_dev->clk_on) {
126 clk_prepare_enable(lcdc_dev->hclk);
127 clk_prepare_enable(lcdc_dev->dclk);
128 clk_prepare_enable(lcdc_dev->aclk);
129 clk_prepare_enable(lcdc_dev->pd);
130 spin_lock(&lcdc_dev->reg_lock);
131 lcdc_dev->clk_on = 1;
132 spin_unlock(&lcdc_dev->reg_lock);
138 static int rk3288_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
140 #ifdef CONFIG_RK_FPGA
141 lcdc_dev->clk_on = 0;
144 if (lcdc_dev->clk_on) {
145 spin_lock(&lcdc_dev->reg_lock);
146 lcdc_dev->clk_on = 0;
147 spin_unlock(&lcdc_dev->reg_lock);
149 clk_disable_unprepare(lcdc_dev->dclk);
150 clk_disable_unprepare(lcdc_dev->hclk);
151 clk_disable_unprepare(lcdc_dev->aclk);
152 clk_disable_unprepare(lcdc_dev->pd);
158 static int rk3288_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
161 spin_lock(&lcdc_dev->reg_lock);
162 if (likely(lcdc_dev->clk_on)) {
163 mask = m_DSP_HOLD_VALID_INTR_EN | m_FS_INTR_EN |
164 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_EN;
165 val = v_DSP_HOLD_VALID_INTR_EN(0) | v_FS_INTR_EN(0) |
166 v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_EN(0);
167 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
169 mask = m_DSP_HOLD_VALID_INTR_CLR | m_FS_INTR_CLR |
170 m_LINE_FLAG_INTR_CLR | m_LINE_FLAG_INTR_CLR;
171 val = v_DSP_HOLD_VALID_INTR_CLR(0) | v_FS_INTR_CLR(0) |
172 v_LINE_FLAG_INTR_CLR(0) | v_BUS_ERROR_INTR_CLR(0);
173 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
175 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN |
176 m_WIN2_EMPTY_INTR_EN | m_WIN3_EMPTY_INTR_EN |
177 m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
178 m_POST_BUF_EMPTY_INTR_EN;
179 val = v_WIN0_EMPTY_INTR_EN(0) | v_WIN1_EMPTY_INTR_EN(0) |
180 v_WIN2_EMPTY_INTR_EN(0) | v_WIN3_EMPTY_INTR_EN(0) |
181 v_HWC_EMPTY_INTR_EN(0) | v_POST_BUF_EMPTY_INTR_EN(0) |
182 v_PWM_GEN_INTR_EN(0);
183 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
185 mask = m_WIN0_EMPTY_INTR_CLR | m_WIN1_EMPTY_INTR_CLR |
186 m_WIN2_EMPTY_INTR_CLR | m_WIN3_EMPTY_INTR_CLR |
187 m_HWC_EMPTY_INTR_CLR | m_POST_BUF_EMPTY_INTR_CLR |
188 m_POST_BUF_EMPTY_INTR_CLR;
189 val = v_WIN0_EMPTY_INTR_CLR(0) | v_WIN1_EMPTY_INTR_CLR(0) |
190 v_WIN2_EMPTY_INTR_CLR(0) | v_WIN3_EMPTY_INTR_CLR(0) |
191 v_HWC_EMPTY_INTR_CLR(0) | v_POST_BUF_EMPTY_INTR_CLR(0) |
192 v_PWM_GEN_INTR_CLR(0);
193 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
194 lcdc_cfg_done(lcdc_dev);
195 spin_unlock(&lcdc_dev->reg_lock);
197 spin_unlock(&lcdc_dev->reg_lock);
202 static int rk3288_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
204 struct lcdc_device *lcdc_dev = container_of(dev_drv,
207 int *cbase = (int *)lcdc_dev->regs;
208 int *regsbak = (int *)lcdc_dev->regsbak;
211 printk("back up reg:\n");
212 for (i = 0; i <= (0x200 >> 4); i++) {
213 printk("0x%04x: ",i*16);
214 for (j = 0; j < 4; j++)
215 printk("%08x ", *(regsbak + i * 4 + j));
219 printk("lcdc reg:\n");
220 for (i = 0; i <= (0x200 >> 4); i++) {
221 printk("0x%04x: ",i*16);
222 for (j = 0; j < 4; j++)
223 printk("%08x ", readl_relaxed(cbase + i * 4 + j));
231 static int win##id##_enable(struct lcdc_device *lcdc_dev, int en) \
234 spin_lock(&lcdc_dev->reg_lock); \
235 msk = m_WIN##id##_EN; \
236 val = v_WIN##id##_EN(en); \
237 lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk, val); \
238 lcdc_cfg_done(lcdc_dev); \
239 /*val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
240 while (val != (!!en)) { \
241 val = lcdc_read_bit(lcdc_dev, WIN##id##_CTRL0, msk); \
243 spin_unlock(&lcdc_dev->reg_lock); \
251 /*enable/disable win directly*/
252 static int rk3288_lcdc_win_direct_en
253 (struct rk_lcdc_driver *drv, int win_id , int en)
255 struct lcdc_device *lcdc_dev = container_of(drv,
256 struct lcdc_device, driver);
258 win0_enable(lcdc_dev, en);
259 else if (win_id == 1)
260 win1_enable(lcdc_dev, en);
261 else if (win_id == 2)
262 win2_enable(lcdc_dev, en);
263 else if (win_id == 3)
264 win3_enable(lcdc_dev, en);
266 dev_err(lcdc_dev->dev, "invalid win number:%d\n", win_id);
271 #define SET_WIN_ADDR(id) \
272 static int set_win##id##_addr(struct lcdc_device *lcdc_dev, u32 addr) \
275 spin_lock(&lcdc_dev->reg_lock); \
276 lcdc_writel(lcdc_dev,WIN##id##_YRGB_MST,addr); \
277 msk = m_WIN##id##_EN; \
278 val = v_WIN0_EN(1); \
279 lcdc_msk_reg(lcdc_dev, WIN##id##_CTRL0, msk,val); \
280 lcdc_cfg_done(lcdc_dev); \
281 spin_unlock(&lcdc_dev->reg_lock); \
287 int rk3288_lcdc_direct_set_win_addr
288 (struct rk_lcdc_driver *dev_drv, int win_id, u32 addr)
290 struct lcdc_device *lcdc_dev = container_of(dev_drv,
291 struct lcdc_device, driver);
293 set_win0_addr(lcdc_dev, addr);
295 set_win1_addr(lcdc_dev, addr);
300 static void lcdc_read_reg_defalut_cfg(struct lcdc_device *lcdc_dev)
304 struct rk_screen *screen = lcdc_dev->driver.cur_screen;
305 u32 h_pw_bp = screen->mode.hsync_len + screen->mode.left_margin;
306 u32 v_pw_bp = screen->mode.vsync_len + screen->mode.upper_margin;
308 struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
310 spin_lock(&lcdc_dev->reg_lock);
311 memcpy(lcdc_dev->regsbak, lcdc_dev->regs, FRC_LOWER11_1);
312 for (reg = 0; reg < FRC_LOWER11_1; reg += 4) {
313 val = lcdc_readl(lcdc_dev, reg);
316 lcdc_dev->driver.version = val;
320 (val & m_WIN0_ACT_WIDTH) + 1;
322 ((val & m_WIN0_ACT_HEIGHT) >> 16) + 1;
325 win0->area[0].xsize =
326 (val & m_WIN0_DSP_WIDTH) + 1;
327 win0->area[0].ysize =
328 ((val & m_WIN0_DSP_HEIGHT) >> 16) + 1;
331 st_x = val & m_WIN0_DSP_XST;
332 st_y = (val & m_WIN0_DSP_YST) >> 16;
333 win0->area[0].xpos = st_x - h_pw_bp;
334 win0->area[0].ypos = st_y - v_pw_bp;
337 win0->state = val & m_WIN0_EN;
338 win0->area[0].fmt_cfg =
339 (val & m_WIN0_DATA_FMT) >> 1;
340 win0->fmt_10 = (val & m_WIN0_FMT_10) >> 4;
341 win0->area[0].format = win0->area[0].fmt_cfg;
344 win0->area[0].y_vir_stride =
345 val & m_WIN0_VIR_STRIDE;
346 win0->area[0].uv_vir_stride =
347 (val & m_WIN0_VIR_STRIDE_UV) >> 16;
348 if (win0->area[0].format == ARGB888)
350 win0->area[0].y_vir_stride;
351 else if (win0->area[0].format == RGB888)
353 win0->area[0].y_vir_stride * 4 / 3;
354 else if (win0->area[0].format == RGB565)
356 2 * win0->area[0].y_vir_stride;
359 4 * win0->area[0].y_vir_stride;
362 win0->area[0].smem_start = val;
365 win0->area[0].cbr_start = val;
367 case DSP_VACT_ST_END:
368 if (support_uboot_display()) {
370 (val & 0x1fff) - ((val >> 16) & 0x1fff);
372 st_y - ((val >> 16) & 0x1fff);
375 case DSP_HACT_ST_END:
376 if (support_uboot_display()) {
378 (val & 0x1fff) - ((val >> 16) & 0x1fff);
380 st_x - ((val >> 16) & 0x1fff);
387 spin_unlock(&lcdc_dev->reg_lock);
391 /********do basic init*********/
392 static int rk3288_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
396 struct lcdc_device *lcdc_dev = container_of(dev_drv,
400 if (lcdc_dev->pre_init)
403 lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
404 lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
405 lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
406 lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
408 if (IS_ERR(lcdc_dev->pd) || (IS_ERR(lcdc_dev->aclk)) ||
409 (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
410 dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
413 if (!support_uboot_display())
414 rk_disp_pwr_enable(dev_drv);
415 rk3288_lcdc_clk_enable(lcdc_dev);
417 /*backup reg config at uboot*/
418 lcdc_read_reg_defalut_cfg(lcdc_dev);
420 #ifndef CONFIG_RK_FPGA
421 if (lcdc_dev->pwr18 == true) {
422 v = 0x00010001; /*bit14: 1,1.8v;0,3.3v*/
423 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
426 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_IO_VSEL);
429 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_0,0x15110903);
430 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE0_1,0x00030911);
431 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_0,0x1a150b04);
432 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE1_1,0x00040b15);
433 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_0,0x15110903);
434 lcdc_writel(lcdc_dev,CABC_GAUSS_LINE2_1,0x00030911);
436 lcdc_writel(lcdc_dev,FRC_LOWER01_0,0x12844821);
437 lcdc_writel(lcdc_dev,FRC_LOWER01_1,0x21488412);
438 lcdc_writel(lcdc_dev,FRC_LOWER10_0,0xa55a9696);
439 lcdc_writel(lcdc_dev,FRC_LOWER10_1,0x5aa56969);
440 lcdc_writel(lcdc_dev,FRC_LOWER11_0,0xdeb77deb);
441 lcdc_writel(lcdc_dev,FRC_LOWER11_1,0xed7bb7de);
443 mask = m_AUTO_GATING_EN;
444 val = v_AUTO_GATING_EN(0);
445 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask,val);
446 lcdc_cfg_done(lcdc_dev);
447 /*disable win0 to workaround iommu pagefault */
448 /*if (dev_drv->iommu_enabled) */
449 /* win0_enable(lcdc_dev, 0); */
450 lcdc_dev->pre_init = true;
456 static void rk3288_lcdc_deint(struct lcdc_device *lcdc_dev)
460 rk3288_lcdc_disable_irq(lcdc_dev);
461 spin_lock(&lcdc_dev->reg_lock);
462 if (likely(lcdc_dev->clk_on)) {
463 lcdc_dev->clk_on = 0;
464 lcdc_set_bit(lcdc_dev, SYS_CTRL, m_STANDBY_EN);
465 lcdc_cfg_done(lcdc_dev);
466 spin_unlock(&lcdc_dev->reg_lock);
468 spin_unlock(&lcdc_dev->reg_lock);
472 static int rk3288_lcdc_post_cfg(struct rk_lcdc_driver *dev_drv)
474 struct lcdc_device *lcdc_dev =
475 container_of(dev_drv, struct lcdc_device, driver);
476 struct rk_screen *screen = dev_drv->cur_screen;
477 u16 x_res = screen->mode.xres;
478 u16 y_res = screen->mode.yres;
481 u16 post_hsd_en,post_vsd_en;
482 u16 post_dsp_hact_st,post_dsp_hact_end;
483 u16 post_dsp_vact_st,post_dsp_vact_end;
484 u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
485 u16 post_h_fac,post_v_fac;
487 screen->post_dsp_stx = x_res * (100 - dev_drv->overscan.left) / 200;
488 screen->post_dsp_sty = y_res * (100 - dev_drv->overscan.top) / 200;
489 screen->post_xsize = x_res *
490 (dev_drv->overscan.left + dev_drv->overscan.right) / 200;
491 screen->post_ysize = y_res *
492 (dev_drv->overscan.top + dev_drv->overscan.bottom) / 200;
493 h_total = screen->mode.hsync_len+screen->mode.left_margin +
494 x_res + screen->mode.right_margin;
495 v_total = screen->mode.vsync_len+screen->mode.upper_margin +
496 y_res + screen->mode.lower_margin;
498 if(screen->post_dsp_stx + screen->post_xsize > x_res){
499 dev_warn(lcdc_dev->dev, "post:stx[%d] + xsize[%d] > x_res[%d]\n",
500 screen->post_dsp_stx,screen->post_xsize,x_res);
501 screen->post_dsp_stx = x_res - screen->post_xsize;
503 if(screen->x_mirror == 0){
504 post_dsp_hact_st=screen->post_dsp_stx +
505 screen->mode.hsync_len+screen->mode.left_margin;
506 post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize;
508 post_dsp_hact_end = h_total - screen->mode.right_margin -
509 screen->post_dsp_stx;
510 post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize;
512 if((screen->post_xsize < x_res)&&(screen->post_xsize != 0)){
515 GET_SCALE_FACTOR_BILI_DN(x_res , screen->post_xsize);
522 if(screen->post_dsp_sty + screen->post_ysize > y_res){
523 dev_warn(lcdc_dev->dev, "post:sty[%d] + ysize[%d] > y_res[%d]\n",
524 screen->post_dsp_sty,screen->post_ysize,y_res);
525 screen->post_dsp_sty = y_res - screen->post_ysize;
528 if(screen->y_mirror == 0){
529 post_dsp_vact_st = screen->post_dsp_sty +
530 screen->mode.vsync_len+screen->mode.upper_margin;
531 post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
533 post_dsp_vact_end = v_total - screen->mode.lower_margin -
534 - screen->post_dsp_sty;
535 post_dsp_vact_st = post_dsp_vact_end - screen->post_ysize;
537 if((screen->post_ysize < y_res)&&(screen->post_ysize != 0)){
539 post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res, screen->post_ysize);
545 if(screen->interlace == 1){
546 post_dsp_vact_st_f1 = v_total + post_dsp_vact_st;
547 post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
549 post_dsp_vact_st_f1 = 0;
550 post_dsp_vact_end_f1 = 0;
552 DBG(1,"post:xsize=%d,ysize=%d,xpos=%d,ypos=%d,"
553 "hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n",
554 screen->post_xsize,screen->post_ysize,screen->xpos,screen->ypos,
555 post_hsd_en,post_h_fac,post_vsd_en,post_v_fac);
556 mask = m_DSP_HACT_END_POST | m_DSP_HACT_ST_POST;
557 val = v_DSP_HACT_END_POST(post_dsp_hact_end) |
558 v_DSP_HACT_ST_POST(post_dsp_hact_st);
559 lcdc_msk_reg(lcdc_dev, POST_DSP_HACT_INFO, mask, val);
561 mask = m_DSP_VACT_END_POST | m_DSP_VACT_ST_POST;
562 val = v_DSP_VACT_END_POST(post_dsp_vact_end) |
563 v_DSP_VACT_ST_POST(post_dsp_vact_st);
564 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO, mask, val);
566 mask = m_POST_HS_FACTOR_YRGB | m_POST_VS_FACTOR_YRGB;
567 val = v_POST_HS_FACTOR_YRGB(post_h_fac) |
568 v_POST_VS_FACTOR_YRGB(post_v_fac);
569 lcdc_msk_reg(lcdc_dev, POST_SCL_FACTOR_YRGB, mask, val);
571 mask = m_DSP_VACT_END_POST_F1 | m_DSP_VACT_ST_POST_F1;
572 val = v_DSP_VACT_END_POST_F1(post_dsp_vact_end_f1) |
573 v_DSP_VACT_ST_POST_F1(post_dsp_vact_st_f1);
574 lcdc_msk_reg(lcdc_dev, POST_DSP_VACT_INFO_F1, mask, val);
576 mask = m_POST_HOR_SD_EN | m_POST_VER_SD_EN;
577 val = v_POST_HOR_SD_EN(post_hsd_en) | v_POST_VER_SD_EN(post_vsd_en);
578 lcdc_msk_reg(lcdc_dev, POST_SCL_CTRL, mask, val);
582 static int rk3288_lcdc_clr_key_cfg(struct rk_lcdc_driver *dev_drv)
584 struct lcdc_device *lcdc_dev = container_of(dev_drv,
588 struct rk_lcdc_win *win;
589 u32 colorkey_r,colorkey_g,colorkey_b;
592 win = dev_drv->win[i];
593 key_val = win->color_key_val;
594 colorkey_r = (key_val & 0xff)<<2;
595 colorkey_g = ((key_val>>8)&0xff)<<12;
596 colorkey_b = ((key_val>>16)&0xff)<<22;
597 /*color key dither 565/888->aaa*/
598 key_val = colorkey_r | colorkey_g | colorkey_b;
601 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY, key_val);
604 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY, key_val);
607 lcdc_writel(lcdc_dev, WIN2_COLOR_KEY, key_val);
610 lcdc_writel(lcdc_dev, WIN3_COLOR_KEY, key_val);
613 printk(KERN_WARNING "%s:un support win num:%d\n",
621 static int rk3288_lcdc_alpha_cfg(struct rk_lcdc_driver *dev_drv,int win_id)
623 struct lcdc_device *lcdc_dev =
624 container_of(dev_drv, struct lcdc_device, driver);
625 struct rk_lcdc_win *win = dev_drv->win[win_id];
626 struct alpha_config alpha_config;
629 int ppixel_alpha,global_alpha;
630 u32 src_alpha_ctl,dst_alpha_ctl;
631 ppixel_alpha = ((win->area[0].format == ARGB888) ||
632 (win->area[0].format == ABGR888)) ? 1 : 0;
633 global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
634 alpha_config.src_global_alpha_val = win->g_alpha_val;
635 win->alpha_mode = AB_SRC_OVER;
636 /*printk("%s,alpha_mode=%d,alpha_en=%d,ppixel_a=%d,gla_a=%d\n",
637 __func__,win->alpha_mode,win->alpha_en,ppixel_alpha,global_alpha);*/
638 switch(win->alpha_mode){
642 alpha_config.src_factor_mode=AA_ZERO;
643 alpha_config.dst_factor_mode=AA_ZERO;
646 alpha_config.src_factor_mode=AA_ONE;
647 alpha_config.dst_factor_mode=AA_ZERO;
650 alpha_config.src_factor_mode=AA_ZERO;
651 alpha_config.dst_factor_mode=AA_ONE;
654 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
656 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
658 alpha_config.src_factor_mode=AA_ONE;
659 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
662 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
663 alpha_config.src_factor_mode=AA_SRC_INVERSE;
664 alpha_config.dst_factor_mode=AA_ONE;
667 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
668 alpha_config.src_factor_mode=AA_SRC;
669 alpha_config.dst_factor_mode=AA_ZERO;
672 alpha_config.src_factor_mode=AA_ZERO;
673 alpha_config.dst_factor_mode=AA_SRC;
676 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
677 alpha_config.src_factor_mode=AA_SRC_INVERSE;
678 alpha_config.dst_factor_mode=AA_ZERO;
681 alpha_config.src_factor_mode=AA_ZERO;
682 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
685 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
686 alpha_config.src_factor_mode=AA_SRC;
687 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
690 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
691 alpha_config.src_factor_mode=AA_SRC_INVERSE;
692 alpha_config.dst_factor_mode=AA_SRC;
695 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
696 alpha_config.src_factor_mode=AA_SRC_INVERSE;
697 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
699 case AB_SRC_OVER_GLOBAL:
700 alpha_config.src_global_alpha_mode=AA_PER_PIX_GLOBAL;
701 alpha_config.src_color_mode=AA_SRC_NO_PRE_MUL;
702 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
703 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
706 pr_err("alpha mode error\n");
709 if((ppixel_alpha == 1)&&(global_alpha == 1)){
710 alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL;
711 }else if(ppixel_alpha == 1){
712 alpha_config.src_global_alpha_mode = AA_PER_PIX;
713 }else if(global_alpha == 1){
714 alpha_config.src_global_alpha_mode = AA_GLOBAL;
716 dev_warn(lcdc_dev->dev,"alpha_en should be 0\n");
718 alpha_config.src_alpha_mode = AA_STRAIGHT;
719 alpha_config.src_alpha_cal_m0 = AA_NO_SAT;
723 src_alpha_ctl = 0x60;
724 dst_alpha_ctl = 0x64;
727 src_alpha_ctl = 0xa0;
728 dst_alpha_ctl = 0xa4;
731 src_alpha_ctl = 0xdc;
732 dst_alpha_ctl = 0xec;
735 src_alpha_ctl = 0x12c;
736 dst_alpha_ctl = 0x13c;
739 mask = m_WIN0_DST_FACTOR_M0;
740 val = v_WIN0_DST_FACTOR_M0(alpha_config.dst_factor_mode);
741 lcdc_msk_reg(lcdc_dev, dst_alpha_ctl, mask, val);
742 mask = m_WIN0_SRC_ALPHA_EN | m_WIN0_SRC_COLOR_M0 |
743 m_WIN0_SRC_ALPHA_M0 | m_WIN0_SRC_BLEND_M0 |
744 m_WIN0_SRC_ALPHA_CAL_M0 | m_WIN0_SRC_FACTOR_M0|
745 m_WIN0_SRC_GLOBAL_ALPHA;
746 val = v_WIN0_SRC_ALPHA_EN(1) |
747 v_WIN0_SRC_COLOR_M0(alpha_config.src_color_mode) |
748 v_WIN0_SRC_ALPHA_M0(alpha_config.src_alpha_mode) |
749 v_WIN0_SRC_BLEND_M0(alpha_config.src_global_alpha_mode) |
750 v_WIN0_SRC_ALPHA_CAL_M0(alpha_config.src_alpha_cal_m0) |
751 v_WIN0_SRC_FACTOR_M0(alpha_config.src_factor_mode) |
752 v_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val);
753 lcdc_msk_reg(lcdc_dev, src_alpha_ctl, mask, val);
757 static int rk3288_lcdc_area_swap(struct rk_lcdc_win *win,int area_num)
759 struct rk_lcdc_win_area area_temp;
762 area_temp = win->area[0];
763 win->area[0] = win->area[1];
764 win->area[1] = area_temp;
767 area_temp = win->area[0];
768 win->area[0] = win->area[2];
769 win->area[2] = area_temp;
772 area_temp = win->area[0];
773 win->area[0] = win->area[3];
774 win->area[3] = area_temp;
776 area_temp = win->area[1];
777 win->area[1] = win->area[2];
778 win->area[2] = area_temp;
781 printk(KERN_WARNING "un supported area num!\n");
787 static int rk3288_win_area_check_var(int win_id,int area_num,struct rk_lcdc_win_area *area_pre,
788 struct rk_lcdc_win_area *area_now)
790 if((area_pre->ypos >= area_now->ypos) ||
791 (area_pre->ypos+area_pre->ysize > area_now->ypos)){
794 "area_pre[%d]:ypos[%d],ysize[%d]\n"
795 "area_now[%d]:ypos[%d],ysize[%d]\n",
797 area_num-1,area_pre->ypos,area_pre->ysize,
798 area_num, area_now->ypos,area_now->ysize);
804 static int rk3288_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
806 struct lcdc_device *lcdc_dev =
807 container_of(dev_drv, struct lcdc_device, driver);
808 struct rk_lcdc_win *win = dev_drv->win[win_id];
809 unsigned int mask, val, off;
811 if((win->win_lb_mode == 5) &&
812 (dev_drv->version == VOP_FULL_RK3288_V1_0))
813 win->win_lb_mode = 4;
816 mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
817 m_WIN0_LB_MODE | m_WIN0_RB_SWAP | m_WIN0_UV_SWAP;
818 val = v_WIN0_EN(win->state) |
819 v_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
820 v_WIN0_FMT_10(win->fmt_10) |
821 v_WIN0_LB_MODE(win->win_lb_mode) |
822 v_WIN0_RB_SWAP(win->area[0].swap_rb) |
823 v_WIN0_UV_SWAP(win->area[0].swap_uv);
824 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
826 mask = m_WIN0_BIC_COE_SEL |
827 m_WIN0_VSD_YRGB_GT4 | m_WIN0_VSD_YRGB_GT2 |
828 m_WIN0_VSD_CBR_GT4 | m_WIN0_VSD_CBR_GT2 |
829 m_WIN0_YRGB_HOR_SCL_MODE | m_WIN0_YRGB_VER_SCL_MODE |
830 m_WIN0_YRGB_HSD_MODE | m_WIN0_YRGB_VSU_MODE |
831 m_WIN0_YRGB_VSD_MODE | m_WIN0_CBR_HOR_SCL_MODE |
832 m_WIN0_CBR_VER_SCL_MODE | m_WIN0_CBR_HSD_MODE |
833 m_WIN0_CBR_VSU_MODE | m_WIN0_CBR_VSD_MODE;
834 val = v_WIN0_BIC_COE_SEL(win->bic_coe_el) |
835 v_WIN0_VSD_YRGB_GT4(win->vsd_yrgb_gt4) |
836 v_WIN0_VSD_YRGB_GT2(win->vsd_yrgb_gt2) |
837 v_WIN0_VSD_CBR_GT4(win->vsd_cbr_gt4) |
838 v_WIN0_VSD_CBR_GT2(win->vsd_cbr_gt2) |
839 v_WIN0_YRGB_HOR_SCL_MODE(win->yrgb_hor_scl_mode) |
840 v_WIN0_YRGB_VER_SCL_MODE(win->yrgb_ver_scl_mode) |
841 v_WIN0_YRGB_HSD_MODE(win->yrgb_hsd_mode) |
842 v_WIN0_YRGB_VSU_MODE(win->yrgb_vsu_mode) |
843 v_WIN0_YRGB_VSD_MODE(win->yrgb_vsd_mode) |
844 v_WIN0_CBR_HOR_SCL_MODE(win->cbr_hor_scl_mode) |
845 v_WIN0_CBR_VER_SCL_MODE(win->cbr_ver_scl_mode) |
846 v_WIN0_CBR_HSD_MODE(win->cbr_hsd_mode) |
847 v_WIN0_CBR_VSU_MODE(win->cbr_vsu_mode) |
848 v_WIN0_CBR_VSD_MODE(win->cbr_vsd_mode);
849 lcdc_msk_reg(lcdc_dev, WIN0_CTRL1+off, mask,val);
851 val = v_WIN0_VIR_STRIDE(win->area[0].y_vir_stride) |
852 v_WIN0_VIR_STRIDE_UV(win->area[0].uv_vir_stride);
853 lcdc_writel(lcdc_dev, WIN0_VIR+off, val);
854 /*lcdc_writel(lcdc_dev, WIN0_YRGB_MST+off, win->area[0].y_addr);
855 lcdc_writel(lcdc_dev, WIN0_CBR_MST+off, win->area[0].uv_addr);*/
856 val = v_WIN0_ACT_WIDTH(win->area[0].xact) |
857 v_WIN0_ACT_HEIGHT(win->area[0].yact);
858 lcdc_writel(lcdc_dev, WIN0_ACT_INFO+off, val);
860 val = v_WIN0_DSP_WIDTH(win->area[0].xsize) |
861 v_WIN0_DSP_HEIGHT(win->area[0].ysize);
862 lcdc_writel(lcdc_dev, WIN0_DSP_INFO+off, val);
864 val = v_WIN0_DSP_XST(win->area[0].dsp_stx) |
865 v_WIN0_DSP_YST(win->area[0].dsp_sty);
866 lcdc_writel(lcdc_dev, WIN0_DSP_ST+off, val);
868 val = v_WIN0_HS_FACTOR_YRGB(win->scale_yrgb_x) |
869 v_WIN0_VS_FACTOR_YRGB(win->scale_yrgb_y);
870 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB+off, val);
872 val = v_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) |
873 v_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y);
874 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR+off, val);
875 if(win->alpha_en == 1)
876 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
878 mask = m_WIN0_SRC_ALPHA_EN;
879 val = v_WIN0_SRC_ALPHA_EN(0);
880 lcdc_msk_reg(lcdc_dev,WIN0_SRC_ALPHA_CTRL+off,mask,val);
885 val = v_WIN0_EN(win->state);
886 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);
891 static int rk3288_win_2_3_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
893 struct lcdc_device *lcdc_dev =
894 container_of(dev_drv, struct lcdc_device, driver);
895 struct rk_lcdc_win *win = dev_drv->win[win_id];
896 struct rk_screen *screen = dev_drv->cur_screen;
897 unsigned int mask, val, off;
898 struct fb_info *fb0 = rk_get_fb(0);
900 off = (win_id-2) * 0x50;
901 if((screen->y_mirror == 1)&&(win->area_num > 1)){
902 rk3288_lcdc_area_swap(win,win->area_num);
906 mask = m_WIN2_EN | m_WIN2_DATA_FMT | m_WIN2_RB_SWAP;
908 v_WIN2_DATA_FMT(win->area[0].fmt_cfg) |
909 v_WIN2_RB_SWAP(win->area[0].swap_rb);
910 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
912 if(win->area[0].state == 1){
913 mask = m_WIN2_MST0_EN;
914 val = v_WIN2_MST0_EN(win->area[0].state);
915 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
917 mask = m_WIN2_VIR_STRIDE0;
918 val = v_WIN2_VIR_STRIDE0(win->area[0].y_vir_stride);
919 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
921 /*lcdc_writel(lcdc_dev,WIN2_MST0+off,win->area[0].y_addr);*/
922 val = v_WIN2_DSP_WIDTH0(win->area[0].xsize) |
923 v_WIN2_DSP_HEIGHT0(win->area[0].ysize);
924 lcdc_writel(lcdc_dev,WIN2_DSP_INFO0+off,val);
925 val = v_WIN2_DSP_XST0(win->area[0].dsp_stx) |
926 v_WIN2_DSP_YST0(win->area[0].dsp_sty);
927 lcdc_writel(lcdc_dev,WIN2_DSP_ST0+off,val);
929 mask = m_WIN2_MST0_EN;
930 val = v_WIN2_MST0_EN(0);
931 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
932 lcdc_writel(lcdc_dev, WIN2_MST0 + off,
933 fb0->fix.smem_start);
936 if(win->area[1].state == 1){
937 rk3288_win_area_check_var(win_id,1,&win->area[0],&win->area[1]);
939 mask = m_WIN2_MST1_EN;
940 val = v_WIN2_MST1_EN(win->area[1].state);
941 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
943 mask = m_WIN2_VIR_STRIDE1;
944 val = v_WIN2_VIR_STRIDE1(win->area[1].y_vir_stride);
945 lcdc_msk_reg(lcdc_dev,WIN2_VIR0_1+off,mask,val);
947 /*lcdc_writel(lcdc_dev,WIN2_MST1+off,win->area[1].y_addr);*/
948 val = v_WIN2_DSP_WIDTH1(win->area[1].xsize) |
949 v_WIN2_DSP_HEIGHT1(win->area[1].ysize);
950 lcdc_writel(lcdc_dev,WIN2_DSP_INFO1+off,val);
951 val = v_WIN2_DSP_XST1(win->area[1].dsp_stx) |
952 v_WIN2_DSP_YST1(win->area[1].dsp_sty);
953 lcdc_writel(lcdc_dev,WIN2_DSP_ST1+off,val);
955 mask = m_WIN2_MST1_EN;
956 val = v_WIN2_MST1_EN(0);
957 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
958 lcdc_writel(lcdc_dev, WIN2_MST1 + off,
959 fb0->fix.smem_start);
962 if(win->area[2].state == 1){
963 rk3288_win_area_check_var(win_id,2,&win->area[1],&win->area[2]);
965 mask = m_WIN2_MST2_EN;
966 val = v_WIN2_MST2_EN(win->area[2].state);
967 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
969 mask = m_WIN2_VIR_STRIDE2;
970 val = v_WIN2_VIR_STRIDE2(win->area[2].y_vir_stride);
971 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
973 /*lcdc_writel(lcdc_dev,WIN2_MST2+off,win->area[2].y_addr);*/
974 val = v_WIN2_DSP_WIDTH2(win->area[2].xsize) |
975 v_WIN2_DSP_HEIGHT2(win->area[2].ysize);
976 lcdc_writel(lcdc_dev,WIN2_DSP_INFO2+off,val);
977 val = v_WIN2_DSP_XST2(win->area[2].dsp_stx) |
978 v_WIN2_DSP_YST2(win->area[2].dsp_sty);
979 lcdc_writel(lcdc_dev,WIN2_DSP_ST2+off,val);
981 mask = m_WIN2_MST2_EN;
982 val = v_WIN2_MST2_EN(0);
983 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
984 lcdc_writel(lcdc_dev, WIN2_MST2 + off,
985 fb0->fix.smem_start);
988 if(win->area[3].state == 1){
989 rk3288_win_area_check_var(win_id,3,&win->area[2],&win->area[3]);
991 mask = m_WIN2_MST3_EN;
992 val = v_WIN2_MST3_EN(win->area[3].state);
993 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
995 mask = m_WIN2_VIR_STRIDE3;
996 val = v_WIN2_VIR_STRIDE3(win->area[3].y_vir_stride);
997 lcdc_msk_reg(lcdc_dev,WIN2_VIR2_3+off,mask,val);
999 /*lcdc_writel(lcdc_dev,WIN2_MST3+off,win->area[3].y_addr);*/
1000 val = v_WIN2_DSP_WIDTH3(win->area[3].xsize) |
1001 v_WIN2_DSP_HEIGHT3(win->area[3].ysize);
1002 lcdc_writel(lcdc_dev,WIN2_DSP_INFO3+off,val);
1003 val = v_WIN2_DSP_XST3(win->area[3].dsp_stx) |
1004 v_WIN2_DSP_YST3(win->area[3].dsp_sty);
1005 lcdc_writel(lcdc_dev,WIN2_DSP_ST3+off,val);
1007 mask = m_WIN2_MST3_EN;
1008 val = v_WIN2_MST3_EN(0);
1009 lcdc_msk_reg(lcdc_dev,WIN2_CTRL0+off,mask,val);
1010 lcdc_writel(lcdc_dev, WIN2_MST3 + off,
1011 fb0->fix.smem_start);
1014 if(win->alpha_en == 1)
1015 rk3288_lcdc_alpha_cfg(dev_drv,win_id);
1017 mask = m_WIN2_SRC_ALPHA_EN;
1018 val = v_WIN2_SRC_ALPHA_EN(0);
1019 lcdc_msk_reg(lcdc_dev,WIN2_SRC_ALPHA_CTRL+off,mask,val);
1022 mask = m_WIN2_EN | m_WIN2_MST0_EN |
1023 m_WIN2_MST0_EN | m_WIN2_MST2_EN |
1025 val = v_WIN2_EN(win->state) | v_WIN2_MST0_EN(0) |
1026 v_WIN2_MST1_EN(0) | v_WIN2_MST2_EN(0) |
1028 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0+off, mask,val);
1033 static int rk3288_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
1035 struct lcdc_device *lcdc_dev =
1036 container_of(dev_drv, struct lcdc_device, driver);
1038 unsigned long flags;
1040 spin_lock(&lcdc_dev->reg_lock);
1041 if(likely(lcdc_dev->clk_on))
1043 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
1044 v_STANDBY_EN(lcdc_dev->standby));
1045 rk3288_win_0_1_reg_update(dev_drv,0);
1046 rk3288_win_0_1_reg_update(dev_drv,1);
1047 rk3288_win_2_3_reg_update(dev_drv,2);
1048 rk3288_win_2_3_reg_update(dev_drv,3);
1049 /*rk3288_lcdc_post_cfg(dev_drv);*/
1050 lcdc_cfg_done(lcdc_dev);
1052 spin_unlock(&lcdc_dev->reg_lock);
1054 /*if (dev_drv->wait_fs) {*/
1056 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
1057 init_completion(&dev_drv->frame_done);
1058 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
1059 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
1061 (dev_drv->cur_screen->ft +
1063 if (!timeout && (!dev_drv->frame_done.done)) {
1064 dev_warn(lcdc_dev->dev, "wait for new frame start time out!\n");
1068 DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
1073 static int rk3288_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
1075 memcpy((u8 *) lcdc_dev->regs, (u8 *) lcdc_dev->regsbak, 0x1fc);
1078 static int rk3288_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
1081 struct lcdc_device *lcdc_dev =
1082 container_of(dev_drv, struct lcdc_device, driver);
1084 if (unlikely(!lcdc_dev->clk_on)) {
1085 pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
1088 #if defined(CONFIG_ROCKCHIP_IOMMU)
1089 if (dev_drv->iommu_enabled) {
1090 if (!lcdc_dev->iommu_status && dev_drv->mmu_dev) {
1092 if (likely(lcdc_dev->clk_on)) {
1093 spin_lock(&lcdc_dev->reg_lock);
1096 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
1097 mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
1098 val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
1099 lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
1100 spin_unlock(&lcdc_dev->reg_lock);
1102 lcdc_dev->iommu_status = 1;
1103 rockchip_iovmm_activate(dev_drv->dev);
1110 static int rk3288_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv, int reset_rate)
1112 #ifdef CONFIG_RK_FPGA
1116 struct lcdc_device *lcdc_dev =
1117 container_of(dev_drv, struct lcdc_device, driver);
1118 struct rk_screen *screen = dev_drv->cur_screen;
1121 ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);/*set pll */
1123 dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
1124 lcdc_dev->pixclock =
1125 div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
1126 lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
1128 fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
1129 screen->ft = 1000 / fps;
1130 dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
1131 lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
1136 static void rk3288_lcdc_bcsh_path_sel(struct rk_lcdc_driver *dev_drv)
1138 struct lcdc_device *lcdc_dev =
1139 container_of(dev_drv, struct lcdc_device, driver);
1142 if (dev_drv->output_color == COLOR_RGB) {
1143 bcsh_color_bar = lcdc_readl(lcdc_dev, BCSH_COLOR_BAR);
1144 if (((bcsh_color_bar & m_BCSH_EN) == 1) ||
1145 (dev_drv->bcsh.enable == 1))/*bcsh enabled */
1146 lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
1147 m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
1148 v_BCSH_R2Y_EN(1) | v_BCSH_Y2R_EN(1));
1150 lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
1151 m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
1152 v_BCSH_R2Y_EN(0) | v_BCSH_Y2R_EN(0));
1153 } else { /* RGB2YUV */
1154 lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
1155 m_BCSH_R2Y_EN | m_BCSH_Y2R_EN,
1156 v_BCSH_R2Y_EN(1) | v_BCSH_Y2R_EN(0));
1160 static int rk3288_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
1161 u16 *yact, int *format, u32 *dsp_addr)
1163 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1164 struct lcdc_device, driver);
1167 spin_lock(&lcdc_dev->reg_lock);
1169 val = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
1170 *xact = (val & m_WIN0_ACT_WIDTH) + 1;
1171 *yact = ((val & m_WIN0_ACT_HEIGHT)>>16) + 1;
1173 val = lcdc_readl(lcdc_dev, WIN0_CTRL0);
1174 *format = (val & m_WIN0_DATA_FMT) >> 1;
1175 *dsp_addr = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
1177 spin_unlock(&lcdc_dev->reg_lock);
1182 static int rk3288_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
1183 int format, u16 xact, u16 yact, u16 xvir)
1185 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1186 struct lcdc_device, driver);
1188 int swap = (format == RGB888) ? 1 : 0;
1190 mask = m_WIN0_DATA_FMT | m_WIN0_RB_SWAP;
1191 val = v_WIN0_DATA_FMT(format) | v_WIN0_RB_SWAP(swap);
1192 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask, val);
1194 lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_WIN0_VIR_STRIDE,
1195 v_WIN0_VIR_STRIDE(xvir));
1196 lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_WIN0_ACT_WIDTH(xact) |
1197 v_WIN0_ACT_HEIGHT(yact));
1199 lcdc_writel(lcdc_dev, WIN0_YRGB_MST, rgb_mst);
1201 lcdc_cfg_done(lcdc_dev);
1206 static int rk3288_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
1211 struct lcdc_device *lcdc_dev =
1212 container_of(dev_drv, struct lcdc_device, driver);
1213 struct rk_screen *screen = dev_drv->cur_screen;
1214 u16 hsync_len = screen->mode.hsync_len;
1215 u16 left_margin = screen->mode.left_margin;
1216 u16 right_margin = screen->mode.right_margin;
1217 u16 vsync_len = screen->mode.vsync_len;
1218 u16 upper_margin = screen->mode.upper_margin;
1219 u16 lower_margin = screen->mode.lower_margin;
1220 u16 x_res = screen->mode.xres;
1221 u16 y_res = screen->mode.yres;
1223 u16 h_total,v_total;
1225 int hdmi_dclk_out_en = 0;
1227 if (unlikely(!lcdc_dev->clk_on)) {
1228 pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
1232 h_total = hsync_len + left_margin + x_res + right_margin;
1233 v_total = vsync_len + upper_margin + y_res + lower_margin;
1235 screen->post_dsp_stx = x_res * (100 - screen->overscan.left) / 200;
1236 screen->post_dsp_sty = y_res * (100 - screen->overscan.top) / 200;
1237 screen->post_xsize = x_res * (screen->overscan.left + screen->overscan.right) / 200;
1238 screen->post_ysize = y_res * (screen->overscan.top + screen->overscan.bottom) / 200;
1240 spin_lock(&lcdc_dev->reg_lock);
1241 if (likely(lcdc_dev->clk_on)) {
1242 switch (screen->face) {
1245 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1246 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1247 m_PRE_DITHER_DOWN_EN;
1248 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1249 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1250 v_PRE_DITHER_DOWN_EN(1);
1251 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1255 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1256 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1257 m_PRE_DITHER_DOWN_EN;
1258 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1259 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1260 v_PRE_DITHER_DOWN_EN(1);
1261 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1265 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1266 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1267 m_PRE_DITHER_DOWN_EN;
1268 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
1269 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1270 v_PRE_DITHER_DOWN_EN(1);
1271 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1275 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
1276 m_DITHER_DOWN_SEL | m_DITHER_UP_EN |
1277 m_PRE_DITHER_DOWN_EN;
1278 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
1279 v_DITHER_DOWN_SEL(1) | v_DITHER_UP_EN(1) |
1280 v_PRE_DITHER_DOWN_EN(1);
1281 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1285 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
1286 m_PRE_DITHER_DOWN_EN;
1287 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
1288 v_PRE_DITHER_DOWN_EN(1);
1289 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1292 hdmi_dclk_out_en = 1;
1295 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
1296 m_PRE_DITHER_DOWN_EN;
1297 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
1298 v_PRE_DITHER_DOWN_EN(1);
1299 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1301 case OUT_YUV_420_10BIT:
1302 hdmi_dclk_out_en = 1;
1305 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
1306 m_PRE_DITHER_DOWN_EN;
1307 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
1308 v_PRE_DITHER_DOWN_EN(0);
1309 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1313 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN |
1314 m_PRE_DITHER_DOWN_EN;
1315 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(1) |
1316 v_PRE_DITHER_DOWN_EN(0);
1317 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
1320 dev_err(lcdc_dev->dev,"un supported interface!\n");
1323 switch(screen->type){
1326 case SCREEN_DUAL_LVDS:
1327 case SCREEN_LVDS_10BIT:
1328 case SCREEN_DUAL_LVDS_10BIT:
1329 mask = m_RGB_OUT_EN;
1330 val = v_RGB_OUT_EN(1);
1332 v |= (lcdc_dev->id << 3);
1335 if ((screen->face == OUT_P888) ||
1336 (screen->face == OUT_P101010))
1337 face = OUT_P101010;/*RGB 101010 output*/
1338 mask = m_HDMI_OUT_EN;
1339 val = v_HDMI_OUT_EN(1);
1342 mask = m_MIPI_OUT_EN;
1343 val = v_MIPI_OUT_EN(1);
1345 case SCREEN_DUAL_MIPI:
1346 mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
1347 val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
1350 face = OUT_P101010; /*RGB 101010 output*/
1351 mask = m_EDP_OUT_EN;
1352 val = v_EDP_OUT_EN(1);
1355 if (dev_drv->version == VOP_FULL_RK3288_V1_1) {
1356 mask |= m_HDMI_DCLK_OUT_EN;
1357 val |= v_HDMI_DCLK_OUT_EN(hdmi_dclk_out_en);
1359 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
1360 #ifndef CONFIG_RK_FPGA
1361 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
1363 mask = m_DSP_OUT_MODE | m_DSP_HSYNC_POL | m_DSP_VSYNC_POL |
1364 m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP |
1365 m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
1366 m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN |
1367 m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN |
1369 val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
1370 v_DSP_VSYNC_POL(screen->pin_vsync) |
1371 v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
1372 v_DSP_BG_SWAP(screen->swap_gb) | v_DSP_RB_SWAP(screen->swap_rb) |
1373 v_DSP_RG_SWAP(screen->swap_rg) |
1374 v_DSP_DELTA_SWAP(screen->swap_delta) |
1375 v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) |
1376 v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
1377 v_DSP_X_MIR_EN(screen->x_mirror) |
1378 v_DSP_Y_MIR_EN(screen->y_mirror) |
1379 v_DSP_DCLK_DDR(dclk_ddr);
1380 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
1382 mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
1383 val = v_DSP_BG_BLUE(0) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
1384 lcdc_msk_reg(lcdc_dev, DSP_BG, mask, val);
1386 mask = m_DSP_HS_PW | m_DSP_HTOTAL;
1387 val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
1388 lcdc_msk_reg(lcdc_dev, DSP_HTOTAL_HS_END, mask, val);
1390 mask = m_DSP_HACT_END | m_DSP_HACT_ST;
1391 val = v_DSP_HACT_END(hsync_len + left_margin + x_res) |
1392 v_DSP_HACT_ST(hsync_len + left_margin);
1393 lcdc_msk_reg(lcdc_dev, DSP_HACT_ST_END, mask, val);
1395 mask = m_DSP_VS_PW | m_DSP_VTOTAL;
1396 val = v_DSP_VS_PW(vsync_len) | v_DSP_VTOTAL(v_total);
1397 lcdc_msk_reg(lcdc_dev, DSP_VTOTAL_VS_END, mask, val);
1399 mask = m_DSP_VACT_END | m_DSP_VACT_ST;
1400 val = v_DSP_VACT_END(vsync_len + upper_margin + y_res) |
1401 v_DSP_VACT_ST(vsync_len + upper_margin);
1402 lcdc_msk_reg(lcdc_dev, DSP_VACT_ST_END, mask, val);
1404 rk3288_lcdc_post_cfg(dev_drv);
1405 mask = m_DSP_LINE_FLAG_NUM;
1406 val = v_DSP_LINE_FLAG_NUM(vsync_len + upper_margin + y_res);
1407 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
1408 dev_drv->output_color = screen->color_mode;
1409 if (dev_drv->version == VOP_FULL_RK3288_V1_1) {
1410 rk3288_lcdc_bcsh_path_sel(dev_drv);
1412 if (dev_drv->output_color != COLOR_RGB) {
1413 pr_err("vop ver:%x,unsupport output color:%d\n",
1414 dev_drv->version, dev_drv->output_color);
1419 spin_unlock(&lcdc_dev->reg_lock);
1420 rk3288_lcdc_set_dclk(dev_drv, 1);
1421 if (screen->type != SCREEN_HDMI && dev_drv->trsm_ops &&
1422 dev_drv->trsm_ops->enable)
1423 dev_drv->trsm_ops->enable();
1430 /*enable layer,open:1,enable;0 disable*/
1431 static int win0_open(struct lcdc_device *lcdc_dev, bool open)
1433 spin_lock(&lcdc_dev->reg_lock);
1434 if (likely(lcdc_dev->clk_on)) {
1436 if (!lcdc_dev->atv_layer_cnt) {
1437 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1438 lcdc_dev->standby = 0;
1440 lcdc_dev->atv_layer_cnt++;
1441 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1442 lcdc_dev->atv_layer_cnt--;
1444 lcdc_dev->driver.win[0]->state = open;
1445 if (!lcdc_dev->atv_layer_cnt) {
1446 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1447 lcdc_dev->standby = 1;
1450 spin_unlock(&lcdc_dev->reg_lock);
1455 static int win1_open(struct lcdc_device *lcdc_dev, bool open)
1457 spin_lock(&lcdc_dev->reg_lock);
1458 if (likely(lcdc_dev->clk_on)) {
1460 if (!lcdc_dev->atv_layer_cnt) {
1461 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1462 lcdc_dev->standby = 0;
1464 lcdc_dev->atv_layer_cnt++;
1465 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1466 lcdc_dev->atv_layer_cnt--;
1468 lcdc_dev->driver.win[1]->state = open;
1470 /*if no layer used,disable lcdc*/
1471 if (!lcdc_dev->atv_layer_cnt) {
1472 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1473 lcdc_dev->standby = 1;
1476 spin_unlock(&lcdc_dev->reg_lock);
1481 static int win2_open(struct lcdc_device *lcdc_dev, bool open)
1483 spin_lock(&lcdc_dev->reg_lock);
1484 if (likely(lcdc_dev->clk_on)) {
1486 if (!lcdc_dev->atv_layer_cnt) {
1487 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1488 lcdc_dev->standby = 0;
1490 lcdc_dev->atv_layer_cnt++;
1491 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1492 lcdc_dev->atv_layer_cnt--;
1494 lcdc_dev->driver.win[2]->state = open;
1496 /*if no layer used,disable lcdc*/
1497 if (!lcdc_dev->atv_layer_cnt) {
1498 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1499 lcdc_dev->standby = 1;
1502 spin_unlock(&lcdc_dev->reg_lock);
1507 static int win3_open(struct lcdc_device *lcdc_dev, bool open)
1509 spin_lock(&lcdc_dev->reg_lock);
1510 if (likely(lcdc_dev->clk_on)) {
1512 if (!lcdc_dev->atv_layer_cnt) {
1513 dev_info(lcdc_dev->dev, "wakeup from standby!\n");
1514 lcdc_dev->standby = 0;
1516 lcdc_dev->atv_layer_cnt++;
1517 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
1518 lcdc_dev->atv_layer_cnt--;
1520 lcdc_dev->driver.win[3]->state = open;
1522 /*if no layer used,disable lcdc*/
1523 if (!lcdc_dev->atv_layer_cnt) {
1524 dev_info(lcdc_dev->dev, "no layer is used,go to standby!\n");
1525 lcdc_dev->standby = 1;
1528 spin_unlock(&lcdc_dev->reg_lock);
1532 static int rk3288_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
1534 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1535 struct lcdc_device, driver);
1538 mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
1539 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR |
1540 m_BUS_ERROR_INTR_EN;
1541 val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(1) |
1542 v_LINE_FLAG_INTR_EN(1) | v_BUS_ERROR_INTR_CLR(1) | v_BUS_ERROR_INTR_EN(0);
1543 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, mask, val);
1544 #ifdef LCDC_IRQ_EMPTY_DEBUG
1545 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN | m_WIN2_EMPTY_INTR_EN |
1546 m_WIN3_EMPTY_INTR_EN |m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
1548 val = v_WIN0_EMPTY_INTR_EN(1) | v_WIN1_EMPTY_INTR_EN(1) | v_WIN2_EMPTY_INTR_EN(1) |
1549 v_WIN3_EMPTY_INTR_EN(1)| v_HWC_EMPTY_INTR_EN(1) | v_POST_BUF_EMPTY_INTR_EN(1) |
1550 v_PWM_GEN_INTR_EN(1);
1551 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, mask, val);
1556 static int rk3288_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
1559 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1560 struct lcdc_device, driver);
1561 int sys_status = (dev_drv->id == 0) ?
1562 SYS_STATUS_LCDC0 : SYS_STATUS_LCDC1;
1564 /*enable clk,when first layer open */
1565 if ((open) && (!lcdc_dev->atv_layer_cnt)) {
1566 rockchip_set_system_status(sys_status);
1567 rk3288_lcdc_pre_init(dev_drv);
1568 rk3288_lcdc_clk_enable(lcdc_dev);
1569 rk3288_lcdc_enable_irq(dev_drv);
1570 #if defined(CONFIG_ROCKCHIP_IOMMU)
1571 if (dev_drv->iommu_enabled) {
1572 if (!dev_drv->mmu_dev) {
1574 rk_fb_get_sysmmu_device_by_compatible(dev_drv->mmu_dts_name);
1575 if (dev_drv->mmu_dev) {
1576 rk_fb_platform_set_sysmmu(dev_drv->mmu_dev,
1579 dev_err(dev_drv->dev,
1580 "failed to get rockchip iommu device\n");
1586 rk3288_lcdc_reg_restore(lcdc_dev);
1587 /*if (dev_drv->iommu_enabled)
1588 rk3368_lcdc_mmu_en(dev_drv); */
1589 if ((support_uboot_display()&&(lcdc_dev->prop == PRMRY))) {
1590 rk3288_lcdc_set_dclk(dev_drv, 0);
1591 /* rk3288_lcdc_enable_irq(dev_drv); */
1593 rk3288_load_screen(dev_drv, 1);
1595 if (dev_drv->bcsh.enable)
1596 rk3288_lcdc_set_bcsh(dev_drv, 1);
1597 spin_lock(&lcdc_dev->reg_lock);
1598 rk3288_lcdc_set_lut(dev_drv);
1599 spin_unlock(&lcdc_dev->reg_lock);
1603 win0_open(lcdc_dev, open);
1604 else if (win_id == 1)
1605 win1_open(lcdc_dev, open);
1606 else if (win_id == 2)
1607 win2_open(lcdc_dev, open);
1608 else if (win_id == 3)
1609 win3_open(lcdc_dev, open);
1611 dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
1613 /* when all layer closed,disable clk */
1614 if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
1615 rk3288_lcdc_disable_irq(lcdc_dev);
1616 rk3288_lcdc_reg_update(dev_drv);
1617 #if defined(CONFIG_ROCKCHIP_IOMMU)
1618 if (dev_drv->iommu_enabled) {
1619 if (dev_drv->mmu_dev) {
1620 rockchip_iovmm_deactivate(dev_drv->dev);
1621 lcdc_dev->iommu_status = 0;
1625 rk3288_lcdc_clk_disable(lcdc_dev);
1626 rockchip_clear_system_status(sys_status);
1632 static int win0_display(struct lcdc_device *lcdc_dev,
1633 struct rk_lcdc_win *win)
1637 y_addr = win->area[0].smem_start+win->area[0].y_offset;/*win->smem_start + win->y_offset;*/
1638 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1639 DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
1640 lcdc_dev->id, __func__, y_addr, uv_addr,win->area[0].y_offset);
1641 spin_lock(&lcdc_dev->reg_lock);
1642 if (likely(lcdc_dev->clk_on)) {
1643 win->area[0].y_addr = y_addr;
1644 win->area[0].uv_addr = uv_addr;
1645 lcdc_writel(lcdc_dev, WIN0_YRGB_MST, win->area[0].y_addr);
1646 lcdc_writel(lcdc_dev, WIN0_CBR_MST, win->area[0].uv_addr);
1647 /*lcdc_cfg_done(lcdc_dev);*/
1649 spin_unlock(&lcdc_dev->reg_lock);
1655 static int win1_display(struct lcdc_device *lcdc_dev,
1656 struct rk_lcdc_win *win)
1660 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1661 uv_addr = win->area[0].cbr_start + win->area[0].c_offset;
1662 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>uv_addr:0x%x\n",
1663 lcdc_dev->id, __func__, y_addr, uv_addr);
1665 spin_lock(&lcdc_dev->reg_lock);
1666 if (likely(lcdc_dev->clk_on)) {
1667 win->area[0].y_addr = y_addr;
1668 win->area[0].uv_addr = uv_addr;
1669 lcdc_writel(lcdc_dev, WIN1_YRGB_MST, win->area[0].y_addr);
1670 lcdc_writel(lcdc_dev, WIN1_CBR_MST, win->area[0].uv_addr);
1672 spin_unlock(&lcdc_dev->reg_lock);
1678 static int win2_display(struct lcdc_device *lcdc_dev,
1679 struct rk_lcdc_win *win)
1682 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1683 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1684 lcdc_dev->id, __func__, y_addr);
1686 spin_lock(&lcdc_dev->reg_lock);
1687 if (likely(lcdc_dev->clk_on)){
1688 for(i=0;i<win->area_num;i++)
1689 win->area[i].y_addr =
1690 win->area[i].smem_start + win->area[i].y_offset;
1691 if (win->area[0].state)
1692 lcdc_writel(lcdc_dev, WIN2_MST0,
1693 win->area[0].y_addr);
1694 if (win->area[1].state)
1695 lcdc_writel(lcdc_dev, WIN2_MST1,
1696 win->area[1].y_addr);
1697 if (win->area[2].state)
1698 lcdc_writel(lcdc_dev, WIN2_MST2,
1699 win->area[2].y_addr);
1700 if (win->area[3].state)
1701 lcdc_writel(lcdc_dev, WIN2_MST3,
1702 win->area[3].y_addr);
1704 spin_unlock(&lcdc_dev->reg_lock);
1708 static int win3_display(struct lcdc_device *lcdc_dev,
1709 struct rk_lcdc_win *win)
1712 y_addr = win->area[0].smem_start + win->area[0].y_offset;
1713 DBG(2, "lcdc%d>>%s>>y_addr:0x%x>>\n",
1714 lcdc_dev->id, __func__, y_addr);
1716 spin_lock(&lcdc_dev->reg_lock);
1717 if (likely(lcdc_dev->clk_on)){
1718 for(i=0;i<win->area_num;i++)
1719 win->area[i].y_addr =
1720 win->area[i].smem_start + win->area[i].y_offset;
1721 if (win->area[0].state)
1722 lcdc_writel(lcdc_dev, WIN3_MST0,
1723 win->area[0].y_addr);
1724 if (win->area[1].state)
1725 lcdc_writel(lcdc_dev, WIN3_MST1,
1726 win->area[1].y_addr);
1727 if (win->area[2].state)
1728 lcdc_writel(lcdc_dev, WIN3_MST2,
1729 win->area[2].y_addr);
1730 if (win->area[3].state)
1731 lcdc_writel(lcdc_dev, WIN3_MST3,
1732 win->area[3].y_addr);
1734 spin_unlock(&lcdc_dev->reg_lock);
1738 static int rk3288_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
1740 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1741 struct lcdc_device, driver);
1742 struct rk_lcdc_win *win = NULL;
1743 struct rk_screen *screen = dev_drv->cur_screen;
1745 #if defined(WAIT_FOR_SYNC)
1747 unsigned long flags;
1749 win = dev_drv->win[win_id];
1751 dev_err(dev_drv->dev, "screen is null!\n");
1755 win0_display(lcdc_dev, win);
1756 }else if(win_id == 1){
1757 win1_display(lcdc_dev, win);
1758 }else if(win_id == 2){
1759 win2_display(lcdc_dev, win);
1760 }else if(win_id == 3){
1761 win3_display(lcdc_dev, win);
1763 dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
1767 /*this is the first frame of the system ,enable frame start interrupt */
1768 if ((dev_drv->first_frame)) {
1769 dev_drv->first_frame = 0;
1770 rk3288_lcdc_enable_irq(dev_drv);
1772 #if defined(WAIT_FOR_SYNC)
1773 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
1774 init_completion(&dev_drv->frame_done);
1775 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
1776 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
1777 msecs_to_jiffies(dev_drv->
1780 if (!timeout && (!dev_drv->frame_done.done)) {
1781 dev_info(dev_drv->dev, "wait for new frame start time out!\n");
1788 static int rk3288_lcdc_cal_scl_fac(struct rk_lcdc_win *win)
1798 u32 yrgb_vScaleDnMult;
1799 u32 yrgb_xscl_factor;
1800 u32 yrgb_yscl_factor;
1801 u8 yrgb_vsd_bil_gt2=0;
1802 u8 yrgb_vsd_bil_gt4=0;
1808 u32 cbcr_vScaleDnMult;
1809 u32 cbcr_xscl_factor;
1810 u32 cbcr_yscl_factor;
1811 u8 cbcr_vsd_bil_gt2=0;
1812 u8 cbcr_vsd_bil_gt4=0;
1816 srcW = win->area[0].xact;
1817 srcH = win->area[0].yact;
1818 dstW = win->area[0].xsize;
1819 dstH = win->area[0].ysize;
1826 if ((yrgb_dstW*8 <= yrgb_srcW) || (yrgb_dstH*8 <= yrgb_srcH)) {
1827 pr_err("ERROR: yrgb scale exceed 8,"
1828 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1829 yrgb_srcW,yrgb_srcH,yrgb_dstW,yrgb_dstH);
1831 if(yrgb_srcW < yrgb_dstW){
1832 win->yrgb_hor_scl_mode = SCALE_UP;
1833 }else if(yrgb_srcW > yrgb_dstW){
1834 win->yrgb_hor_scl_mode = SCALE_DOWN;
1836 win->yrgb_hor_scl_mode = SCALE_NONE;
1839 if(yrgb_srcH < yrgb_dstH){
1840 win->yrgb_ver_scl_mode = SCALE_UP;
1841 }else if (yrgb_srcH > yrgb_dstH){
1842 win->yrgb_ver_scl_mode = SCALE_DOWN;
1844 win->yrgb_ver_scl_mode = SCALE_NONE;
1848 switch (win->area[0].format) {
1882 if ((cbcr_dstW*8 <= cbcr_srcW) || (cbcr_dstH*8 <= cbcr_srcH)) {
1883 pr_err("ERROR: cbcr scale exceed 8,"
1884 "srcW=%d,srcH=%d,dstW=%d,dstH=%d\n",
1885 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH);
1889 if(cbcr_srcW < cbcr_dstW){
1890 win->cbr_hor_scl_mode = SCALE_UP;
1891 }else if(cbcr_srcW > cbcr_dstW){
1892 win->cbr_hor_scl_mode = SCALE_DOWN;
1894 win->cbr_hor_scl_mode = SCALE_NONE;
1897 if(cbcr_srcH < cbcr_dstH){
1898 win->cbr_ver_scl_mode = SCALE_UP;
1899 }else if(cbcr_srcH > cbcr_dstH){
1900 win->cbr_ver_scl_mode = SCALE_DOWN;
1902 win->cbr_ver_scl_mode = SCALE_NONE;
1904 DBG(1, "srcW:%d>>srcH:%d>>dstW:%d>>dstH:%d>>\n"
1905 "yrgb:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1906 "cbcr:src:W=%d>>H=%d,dst:W=%d>>H=%d,H_mode=%d,V_mode=%d\n"
1907 ,srcW,srcH,dstW,dstH,yrgb_srcW,yrgb_srcH,yrgb_dstW,
1908 yrgb_dstH,win->yrgb_hor_scl_mode,win->yrgb_ver_scl_mode,
1909 cbcr_srcW,cbcr_srcH,cbcr_dstW,cbcr_dstH,
1910 win->cbr_hor_scl_mode,win->cbr_ver_scl_mode);
1912 /*line buffer mode*/
1913 if ((win->area[0].format == YUV422) ||
1914 (win->area[0].format == YUV420) ||
1915 (win->area[0].format == YUV422_A) ||
1916 (win->area[0].format == YUV420_A)) {
1917 if (win->cbr_hor_scl_mode == SCALE_DOWN) {
1918 if ((cbcr_dstW > 3840) || (cbcr_dstW == 0)) {
1919 pr_err("ERROR cbcr_dstW = %d\n",cbcr_dstW);
1920 } else if (cbcr_dstW > 2560) {
1921 win->win_lb_mode = LB_RGB_3840X2;
1922 } else if (cbcr_dstW > 1920) {
1923 if (win->yrgb_hor_scl_mode == SCALE_DOWN) {
1924 if(yrgb_dstW > 3840){
1925 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1926 }else if(yrgb_dstW > 2560){
1927 win->win_lb_mode = LB_RGB_3840X2;
1928 }else if(yrgb_dstW > 1920){
1929 win->win_lb_mode = LB_RGB_2560X4;
1931 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1934 } else if (cbcr_dstW > 1280) {
1935 win->win_lb_mode = LB_YUV_3840X5;
1937 win->win_lb_mode = LB_YUV_2560X8;
1939 } else { /*SCALE_UP or SCALE_NONE*/
1940 if ((cbcr_srcW > 3840) || (cbcr_srcW == 0)) {
1941 pr_err("ERROR cbcr_srcW = %d\n",cbcr_srcW);
1942 }else if(cbcr_srcW > 2560){
1943 win->win_lb_mode = LB_RGB_3840X2;
1944 }else if(cbcr_srcW > 1920){
1945 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1946 if(yrgb_dstW > 3840){
1947 pr_err("ERROR yrgb_dst_width exceeds 3840\n");
1948 }else if(yrgb_dstW > 2560){
1949 win->win_lb_mode = LB_RGB_3840X2;
1950 }else if(yrgb_dstW > 1920){
1951 win->win_lb_mode = LB_RGB_2560X4;
1953 pr_err("ERROR never run here!yrgb_dstW<1920 ==> cbcr_dstW>1920\n");
1956 }else if(cbcr_srcW > 1280){
1957 win->win_lb_mode = LB_YUV_3840X5;
1959 win->win_lb_mode = LB_YUV_2560X8;
1963 if(win->yrgb_hor_scl_mode == SCALE_DOWN){
1964 if ((yrgb_dstW > 3840) || (yrgb_dstW == 0)) {
1965 pr_err("ERROR yrgb_dstW = %d\n",yrgb_dstW);
1966 }else if(yrgb_dstW > 2560){
1967 win->win_lb_mode = LB_RGB_3840X2;
1968 }else if(yrgb_dstW > 1920){
1969 win->win_lb_mode = LB_RGB_2560X4;
1970 }else if(yrgb_dstW > 1280){
1971 win->win_lb_mode = LB_RGB_1920X5;
1973 win->win_lb_mode = LB_RGB_1280X8;
1975 }else{ /*SCALE_UP or SCALE_NONE*/
1976 if ((yrgb_srcW > 3840) || (yrgb_srcW == 0)) {
1977 pr_err("ERROR yrgb_srcW = %d\n",yrgb_srcW);
1978 }else if(yrgb_srcW > 2560){
1979 win->win_lb_mode = LB_RGB_3840X2;
1980 }else if(yrgb_srcW > 1920){
1981 win->win_lb_mode = LB_RGB_2560X4;
1982 }else if(yrgb_srcW > 1280){
1983 win->win_lb_mode = LB_RGB_1920X5;
1985 win->win_lb_mode = LB_RGB_1280X8;
1989 DBG(1,"win->win_lb_mode = %d;\n",win->win_lb_mode);
1991 /*vsd/vsu scale ALGORITHM*/
1992 win->yrgb_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1993 win->cbr_hsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1994 win->yrgb_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1995 win->cbr_vsd_mode = SCALE_DOWN_BIL;/*not to specify*/
1996 switch(win->win_lb_mode){
2001 win->yrgb_vsu_mode = SCALE_UP_BIC;
2002 win->cbr_vsu_mode = SCALE_UP_BIC;
2005 if(win->yrgb_ver_scl_mode != SCALE_NONE) {
2006 pr_err("ERROR : not allow yrgb ver scale\n");
2008 if(win->cbr_ver_scl_mode != SCALE_NONE) {
2009 pr_err("ERROR : not allow cbcr ver scale\n");
2013 win->yrgb_vsu_mode = SCALE_UP_BIL;
2014 win->cbr_vsu_mode = SCALE_UP_BIL;
2017 printk(KERN_WARNING "%s:un supported win_lb_mode:%d\n",
2018 __func__,win->win_lb_mode);
2021 DBG(1,"yrgb:hsd=%d,vsd=%d,vsu=%d;cbcr:hsd=%d,vsd=%d,vsu=%d\n",
2022 win->yrgb_hsd_mode,win->yrgb_vsd_mode,win->yrgb_vsu_mode,
2023 win->cbr_hsd_mode,win->cbr_vsd_mode,win->cbr_vsu_mode);
2027 /*(1.1)YRGB HOR SCALE FACTOR*/
2028 switch(win->yrgb_hor_scl_mode){
2030 yrgb_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
2033 yrgb_xscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcW, yrgb_dstW);
2036 switch(win->yrgb_hsd_mode)
2038 case SCALE_DOWN_BIL:
2039 yrgb_xscl_factor = GET_SCALE_FACTOR_BILI_DN(yrgb_srcW, yrgb_dstW);
2041 case SCALE_DOWN_AVG:
2042 yrgb_xscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcW, yrgb_dstW);
2045 printk(KERN_WARNING "%s:un supported yrgb_hsd_mode:%d\n",
2046 __func__,win->yrgb_hsd_mode);
2051 printk(KERN_WARNING "%s:un supported yrgb_hor_scl_mode:%d\n",
2052 __func__,win->yrgb_hor_scl_mode);
2054 } /*win->yrgb_hor_scl_mode*/
2056 /*(1.2)YRGB VER SCALE FACTOR*/
2057 switch(win->yrgb_ver_scl_mode)
2060 yrgb_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
2063 switch(win->yrgb_vsu_mode)
2066 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_UP(yrgb_srcH, yrgb_dstH);
2070 pr_err("yrgb_srcH should be greater than 3 !!!\n");
2072 yrgb_yscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcH, yrgb_dstH);
2075 printk(KERN_WARNING "%s:un supported yrgb_vsu_mode:%d\n",
2076 __func__,win->yrgb_vsu_mode);
2081 switch(win->yrgb_vsd_mode)
2083 case SCALE_DOWN_BIL:
2084 yrgb_vScaleDnMult = getHardWareVSkipLines(yrgb_srcH, yrgb_dstH);
2085 yrgb_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(yrgb_srcH, yrgb_dstH, yrgb_vScaleDnMult);
2086 if(yrgb_vScaleDnMult == 4){
2087 yrgb_vsd_bil_gt4 = 1;
2088 yrgb_vsd_bil_gt2 = 0;
2089 }else if(yrgb_vScaleDnMult == 2){
2090 yrgb_vsd_bil_gt4 = 0;
2091 yrgb_vsd_bil_gt2 = 1;
2093 yrgb_vsd_bil_gt4 = 0;
2094 yrgb_vsd_bil_gt2 = 0;
2097 case SCALE_DOWN_AVG:
2098 yrgb_yscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcH, yrgb_dstH);
2101 printk(KERN_WARNING "%s:un supported yrgb_vsd_mode:%d\n",
2102 __func__,win->yrgb_vsd_mode);
2104 } /*win->yrgb_vsd_mode*/
2107 printk(KERN_WARNING "%s:un supported yrgb_ver_scl_mode:%d\n",
2108 __func__,win->yrgb_ver_scl_mode);
2111 win->scale_yrgb_x = yrgb_xscl_factor;
2112 win->scale_yrgb_y = yrgb_yscl_factor;
2113 win->vsd_yrgb_gt4 = yrgb_vsd_bil_gt4;
2114 win->vsd_yrgb_gt2 = yrgb_vsd_bil_gt2;
2115 DBG(1,"yrgb:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",yrgb_xscl_factor,
2116 yrgb_yscl_factor,yrgb_vsd_bil_gt4,yrgb_vsd_bil_gt2);
2118 /*(2.1)CBCR HOR SCALE FACTOR*/
2119 switch(win->cbr_hor_scl_mode)
2122 cbcr_xscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
2125 cbcr_xscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcW, cbcr_dstW);
2128 switch(win->cbr_hsd_mode)
2130 case SCALE_DOWN_BIL:
2131 cbcr_xscl_factor = GET_SCALE_FACTOR_BILI_DN(cbcr_srcW, cbcr_dstW);
2133 case SCALE_DOWN_AVG:
2134 cbcr_xscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcW, cbcr_dstW);
2137 printk(KERN_WARNING "%s:un supported cbr_hsd_mode:%d\n",
2138 __func__,win->cbr_hsd_mode);
2143 printk(KERN_WARNING "%s:un supported cbr_hor_scl_mode:%d\n",
2144 __func__,win->cbr_hor_scl_mode);
2146 } /*win->cbr_hor_scl_mode*/
2148 /*(2.2)CBCR VER SCALE FACTOR*/
2149 switch(win->cbr_ver_scl_mode)
2152 cbcr_yscl_factor = (1<<SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT);
2155 switch(win->cbr_vsu_mode)
2158 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_UP(cbcr_srcH, cbcr_dstH);
2162 pr_err("cbcr_srcH should be greater than 3 !!!\n");
2164 cbcr_yscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcH, cbcr_dstH);
2167 printk(KERN_WARNING "%s:un supported cbr_vsu_mode:%d\n",
2168 __func__,win->cbr_vsu_mode);
2173 switch(win->cbr_vsd_mode)
2175 case SCALE_DOWN_BIL:
2176 cbcr_vScaleDnMult = getHardWareVSkipLines(cbcr_srcH, cbcr_dstH);
2177 cbcr_yscl_factor = GET_SCALE_FACTOR_BILI_DN_VSKIP(cbcr_srcH, cbcr_dstH, cbcr_vScaleDnMult);
2178 if(cbcr_vScaleDnMult == 4){
2179 cbcr_vsd_bil_gt4 = 1;
2180 cbcr_vsd_bil_gt2 = 0;
2181 }else if(cbcr_vScaleDnMult == 2){
2182 cbcr_vsd_bil_gt4 = 0;
2183 cbcr_vsd_bil_gt2 = 1;
2185 cbcr_vsd_bil_gt4 = 0;
2186 cbcr_vsd_bil_gt2 = 0;
2189 case SCALE_DOWN_AVG:
2190 cbcr_yscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcH, cbcr_dstH);
2193 printk(KERN_WARNING "%s:un supported cbr_vsd_mode:%d\n",
2194 __func__,win->cbr_vsd_mode);
2199 printk(KERN_WARNING "%s:un supported cbr_ver_scl_mode:%d\n",
2200 __func__,win->cbr_ver_scl_mode);
2203 win->scale_cbcr_x = cbcr_xscl_factor;
2204 win->scale_cbcr_y = cbcr_yscl_factor;
2205 win->vsd_cbr_gt4 = cbcr_vsd_bil_gt4;
2206 win->vsd_cbr_gt2 = cbcr_vsd_bil_gt2;
2208 DBG(1,"cbcr:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n",cbcr_xscl_factor,
2209 cbcr_yscl_factor,cbcr_vsd_bil_gt4,cbcr_vsd_bil_gt2);
2215 static int win0_set_par(struct lcdc_device *lcdc_dev,
2216 struct rk_screen *screen, struct rk_lcdc_win *win)
2218 u32 xact,yact,xvir, yvir,xpos, ypos;
2219 u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
2220 char fmt[9] = "NULL";
2222 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
2223 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
2225 spin_lock(&lcdc_dev->reg_lock);
2226 if(likely(lcdc_dev->clk_on)){
2227 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
2228 switch (win->area[0].format) {
2286 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2290 win->area[0].fmt_cfg = fmt_cfg;
2291 win->area[0].swap_rb = swap_rb;
2292 win->area[0].dsp_stx = xpos;
2293 win->area[0].dsp_sty = ypos;
2294 win->area[0].swap_uv = swap_uv;
2295 xact = win->area[0].xact;
2296 yact = win->area[0].yact;
2297 xvir = win->area[0].xvir;
2298 yvir = win->area[0].yvir;
2300 rk3288_win_0_1_reg_update(&lcdc_dev->driver,0);
2301 spin_unlock(&lcdc_dev->reg_lock);
2303 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2304 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2305 __func__, get_format_string(win->area[0].format, fmt), xact,
2306 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2311 static int win1_set_par(struct lcdc_device *lcdc_dev,
2312 struct rk_screen *screen, struct rk_lcdc_win *win)
2314 u32 xact, yact, xvir, yvir, xpos, ypos;
2315 u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
2316 char fmt[9] = "NULL";
2318 xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
2319 ypos = win->area[0].ypos + screen->mode.upper_margin + screen->mode.vsync_len;
2321 spin_lock(&lcdc_dev->reg_lock);
2322 if (likely(lcdc_dev->clk_on)) {
2323 rk3288_lcdc_cal_scl_fac(win);/*fac,lb,gt2,gt4*/
2324 switch (win->area[0].format) {
2383 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
2387 win->area[0].fmt_cfg = fmt_cfg;
2388 win->area[0].swap_rb = swap_rb;
2389 win->area[0].dsp_stx = xpos;
2390 win->area[0].dsp_sty = ypos;
2391 win->area[0].swap_uv = swap_uv;
2392 xact = win->area[0].xact;
2393 yact = win->area[0].yact;
2394 xvir = win->area[0].xvir;
2395 yvir = win->area[0].yvir;
2397 rk3288_win_0_1_reg_update(&lcdc_dev->driver,1);
2398 spin_unlock(&lcdc_dev->reg_lock);
2400 DBG(1, "lcdc%d>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
2401 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
2402 __func__, get_format_string(win->area[0].format, fmt), xact,
2403 yact, win->area[0].xsize, win->area[0].ysize, xvir, yvir, xpos, ypos);
2408 static int win2_set_par(struct lcdc_device *lcdc_dev,
2409 struct rk_screen *screen, struct rk_lcdc_win *win)
2412 u8 fmt_cfg, swap_rb;
2414 spin_lock(&lcdc_dev->reg_lock);
2415 if (likely(lcdc_dev->clk_on)) {
2416 for (i = 0; i < win->area_num; i++) {
2417 switch (win->area[i].format) {
2436 dev_err(lcdc_dev->driver.dev,
2437 "%s:un supported format!\n",
2441 win->area[i].fmt_cfg = fmt_cfg;
2442 win->area[i].swap_rb = swap_rb;
2443 win->area[i].dsp_stx = win->area[i].xpos +
2444 screen->mode.left_margin +
2445 screen->mode.hsync_len;
2446 if (screen->y_mirror == 1) {
2447 win->area[i].dsp_sty = screen->mode.yres -
2449 win->area[i].ysize +
2450 screen->mode.upper_margin +
2451 screen->mode.vsync_len;
2453 win->area[i].dsp_sty = win->area[i].ypos +
2454 screen->mode.upper_margin +
2455 screen->mode.vsync_len;
2457 if ((win->area[i].xact != win->area[i].xsize) ||
2458 (win->area[i].yact != win->area[i].ysize)) {
2459 pr_err("win[%d]->area[%d],not support scale\n",
2461 pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
2462 win->area[i].xact,win->area[i].yact,
2463 win->area[i].xsize,win->area[i].ysize);
2464 win->area[i].xsize = win->area[i].xact;
2465 win->area[i].ysize = win->area[i].yact;
2469 rk3288_win_2_3_reg_update(&lcdc_dev->driver,2);
2470 spin_unlock(&lcdc_dev->reg_lock);
2474 static int win3_set_par(struct lcdc_device *lcdc_dev,
2475 struct rk_screen *screen, struct rk_lcdc_win *win)
2479 u8 fmt_cfg, swap_rb;
2481 spin_lock(&lcdc_dev->reg_lock);
2482 if (likely(lcdc_dev->clk_on)) {
2483 for (i = 0; i < win->area_num; i++) {
2484 switch (win->area[i].format) {
2503 dev_err(lcdc_dev->driver.dev,
2504 "%s:un supported format!\n",
2508 win->area[i].fmt_cfg = fmt_cfg;
2509 win->area[i].swap_rb = swap_rb;
2510 win->area[i].dsp_stx = win->area[i].xpos +
2511 screen->mode.left_margin +
2512 screen->mode.hsync_len;
2513 if (screen->y_mirror == 1) {
2514 win->area[i].dsp_sty = screen->mode.yres -
2516 win->area[i].ysize +
2517 screen->mode.upper_margin +
2518 screen->mode.vsync_len;
2520 win->area[i].dsp_sty = win->area[i].ypos +
2521 screen->mode.upper_margin +
2522 screen->mode.vsync_len;
2524 if ((win->area[i].xact != win->area[i].xsize) ||
2525 (win->area[i].yact != win->area[i].ysize)) {
2526 pr_err("win[%d]->area[%d],not support scale\n",
2528 pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
2529 win->area[i].xact, win->area[i].yact,
2530 win->area[i].xsize, win->area[i].ysize);
2531 win->area[i].xsize = win->area[i].xact;
2532 win->area[i].ysize = win->area[i].yact;
2536 rk3288_win_2_3_reg_update(&lcdc_dev->driver,3);
2537 spin_unlock(&lcdc_dev->reg_lock);
2541 static int rk3288_lcdc_set_par(struct rk_lcdc_driver *dev_drv,int win_id)
2543 struct lcdc_device *lcdc_dev =
2544 container_of(dev_drv, struct lcdc_device, driver);
2545 struct rk_lcdc_win *win = NULL;
2546 struct rk_screen *screen = dev_drv->cur_screen;
2547 win = dev_drv->win[win_id];
2552 win0_set_par(lcdc_dev, screen, win);
2555 win1_set_par(lcdc_dev, screen, win);
2558 win2_set_par(lcdc_dev, screen, win);
2561 win3_set_par(lcdc_dev, screen, win);
2564 dev_err(dev_drv->dev, "unsupported win number:%d\n", win_id);
2570 static int rk3288_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
2571 unsigned long arg, int win_id)
2573 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2578 void __user *argp = (void __user *)arg;
2579 struct color_key_cfg clr_key_cfg;
2582 case RK_FBIOGET_PANEL_SIZE:
2583 panel_size[0] = lcdc_dev->screen->mode.xres;
2584 panel_size[1] = lcdc_dev->screen->mode.yres;
2585 if (copy_to_user(argp, panel_size, 8))
2588 case RK_FBIOPUT_COLOR_KEY_CFG:
2589 if (copy_from_user(&clr_key_cfg, argp,
2590 sizeof(struct color_key_cfg)))
2592 rk3288_lcdc_clr_key_cfg(dev_drv);
2593 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
2594 clr_key_cfg.win0_color_key_cfg);
2595 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
2596 clr_key_cfg.win1_color_key_cfg);
2605 static int rk3288_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
2608 struct lcdc_device *lcdc_dev =
2609 container_of(dev_drv, struct lcdc_device, driver);
2610 if (dev_drv->suspend_flag)
2613 dev_drv->suspend_flag = 1;
2614 flush_kthread_worker(&dev_drv->update_regs_worker);
2616 for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg +=4)
2617 lcdc_readl(lcdc_dev, reg);
2618 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
2619 dev_drv->trsm_ops->disable();
2621 spin_lock(&lcdc_dev->reg_lock);
2622 if (likely(lcdc_dev->clk_on)) {
2623 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2625 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR | m_LINE_FLAG_INTR_CLR,
2626 v_FS_INTR_CLR(1) | v_LINE_FLAG_INTR_CLR(1));
2627 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2629 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2631 lcdc_cfg_done(lcdc_dev);
2633 if (dev_drv->iommu_enabled) {
2634 if (dev_drv->mmu_dev)
2635 rockchip_iovmm_deactivate(dev_drv->dev);
2638 spin_unlock(&lcdc_dev->reg_lock);
2640 spin_unlock(&lcdc_dev->reg_lock);
2643 rk3288_lcdc_clk_disable(lcdc_dev);
2644 rk_disp_pwr_disable(dev_drv);
2648 static int rk3288_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
2650 struct lcdc_device *lcdc_dev =
2651 container_of(dev_drv, struct lcdc_device, driver);
2653 if (!dev_drv->suspend_flag)
2655 rk_disp_pwr_enable(dev_drv);
2656 dev_drv->suspend_flag = 0;
2658 if (lcdc_dev->atv_layer_cnt) {
2659 rk3288_lcdc_clk_enable(lcdc_dev);
2660 rk3288_lcdc_reg_restore(lcdc_dev);
2662 spin_lock(&lcdc_dev->reg_lock);
2663 rk3288_lcdc_set_lut(dev_drv);
2665 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO,
2667 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
2669 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLANK_EN,
2671 lcdc_cfg_done(lcdc_dev);
2673 if (dev_drv->iommu_enabled) {
2674 if (dev_drv->mmu_dev)
2675 rockchip_iovmm_activate(dev_drv->dev);
2678 spin_unlock(&lcdc_dev->reg_lock);
2681 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
2682 dev_drv->trsm_ops->enable();
2687 static int rk3288_lcdc_blank(struct rk_lcdc_driver *dev_drv,
2688 int win_id, int blank_mode)
2690 switch (blank_mode) {
2691 case FB_BLANK_UNBLANK:
2692 rk3288_lcdc_early_resume(dev_drv);
2694 case FB_BLANK_NORMAL:
2695 rk3288_lcdc_early_suspend(dev_drv);
2698 rk3288_lcdc_early_suspend(dev_drv);
2702 dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
2707 static int rk3288_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
2708 int win_id, int area_id)
2710 struct lcdc_device *lcdc_dev =
2711 container_of(dev_drv, struct lcdc_device, driver);
2713 u32 area_status = 0;
2717 win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
2718 area_status = win_ctrl & m_WIN0_EN;
2721 win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
2722 area_status = win_ctrl & m_WIN1_EN;
2725 win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
2727 area_status = win_ctrl & m_WIN2_MST0_EN;
2729 area_status = win_ctrl & m_WIN2_MST1_EN;
2731 area_status = win_ctrl & m_WIN2_MST2_EN;
2733 area_status = win_ctrl & m_WIN2_MST3_EN;
2736 win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
2738 area_status = win_ctrl & m_WIN3_MST0_EN;
2740 area_status = win_ctrl & m_WIN3_MST1_EN;
2742 area_status = win_ctrl & m_WIN3_MST2_EN;
2744 area_status = win_ctrl & m_WIN3_MST3_EN;
2747 win_ctrl = lcdc_readl(lcdc_dev, HWC_CTRL0);
2748 area_status = win_ctrl & m_HWC_EN;
2751 pr_err("!!!%s,win[%d]area[%d],unsupport!!!\n",__func__,win_id,area_id);
2757 static int rk3288_lcdc_get_area_num(struct rk_lcdc_driver *dev_drv,
2758 unsigned int *area_support)
2760 area_support[0] = 1;
2761 area_support[1] = 1;
2762 area_support[2] = 4;
2763 area_support[3] = 4;
2768 /*overlay will be do at regupdate*/
2769 static int rk3288_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
2772 struct lcdc_device *lcdc_dev =
2773 container_of(dev_drv, struct lcdc_device, driver);
2774 struct rk_lcdc_win *win = NULL;
2776 unsigned int mask, val;
2778 int layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2781 win = dev_drv->win[i];
2782 if(win->state == 1){
2787 win = dev_drv->win[i];
2789 win->z_order = z_order_num++;
2790 switch(win->z_order){
2792 layer0_sel = win->id;
2795 layer1_sel = win->id;
2798 layer2_sel = win->id;
2801 layer3_sel = win->id;
2808 layer0_sel = swap %10;;
2809 layer1_sel = swap /10 % 10;
2810 layer2_sel = swap / 100 %10;
2811 layer3_sel = swap / 1000;
2814 spin_lock(&lcdc_dev->reg_lock);
2815 if(lcdc_dev->clk_on){
2817 mask = m_DSP_LAYER0_SEL | m_DSP_LAYER1_SEL |
2818 m_DSP_LAYER2_SEL | m_DSP_LAYER3_SEL;
2819 val = v_DSP_LAYER0_SEL(layer0_sel) |
2820 v_DSP_LAYER1_SEL(layer1_sel) |
2821 v_DSP_LAYER2_SEL(layer2_sel) |
2822 v_DSP_LAYER3_SEL(layer3_sel);
2823 lcdc_msk_reg(lcdc_dev,DSP_CTRL1,mask,val);
2825 layer0_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER0_SEL);
2826 layer1_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER1_SEL);
2827 layer2_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER2_SEL);
2828 layer3_sel = lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LAYER3_SEL);
2829 ovl = layer3_sel*1000 + layer2_sel*100 + layer1_sel *10 + layer0_sel;
2834 spin_unlock(&lcdc_dev->reg_lock);
2839 static ssize_t rk3288_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
2840 char *buf, int win_id)
2842 struct lcdc_device *lcdc_dev = container_of(dev_drv,
2846 struct rk_screen *screen = dev_drv->cur_screen;
2847 u16 hsync_len = screen->mode.hsync_len;
2848 u16 left_margin = screen->mode.left_margin;
2849 u16 vsync_len = screen->mode.vsync_len;
2850 u16 upper_margin = screen->mode.upper_margin;
2851 u32 h_pw_bp = hsync_len + left_margin;
2852 u32 v_pw_bp = vsync_len + upper_margin;
2854 char format_w0[9] = "NULL";
2855 char format_w1[9] = "NULL";
2856 char format_w2[9] = "NULL";
2857 char format_w3[9] = "NULL";
2858 u32 win_ctrl,zorder,vir_info,act_info,dsp_info,dsp_st,y_factor,uv_factor;
2859 u8 layer0_sel,layer1_sel,layer2_sel,layer3_sel;
2860 u8 w0_state,w1_state,w2_state,w3_state;
2861 u8 w2_0_state,w2_1_state,w2_2_state,w2_3_state;
2862 u8 w3_0_state,w3_1_state,w3_2_state,w3_3_state;
2864 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;
2865 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;
2866 u32 w0_y_h_fac,w0_y_v_fac,w0_uv_h_fac,w0_uv_v_fac;
2867 u32 w1_y_h_fac,w1_y_v_fac,w1_uv_h_fac,w1_uv_v_fac;
2869 u32 w2_0_vir_y,w2_1_vir_y,w2_2_vir_y,w2_3_vir_y;
2870 u32 w2_0_dsp_x,w2_1_dsp_x,w2_2_dsp_x,w2_3_dsp_x;
2871 u32 w2_0_dsp_y,w2_1_dsp_y,w2_2_dsp_y,w2_3_dsp_y;
2872 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;
2873 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;
2875 u32 w3_0_vir_y,w3_1_vir_y,w3_2_vir_y,w3_3_vir_y;
2876 u32 w3_0_dsp_x,w3_1_dsp_x,w3_2_dsp_x,w3_3_dsp_x;
2877 u32 w3_0_dsp_y,w3_1_dsp_y,w3_2_dsp_y,w3_3_dsp_y;
2878 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;
2879 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;
2882 dclk_freq = screen->mode.pixclock;
2883 /*rk3288_lcdc_reg_dump(dev_drv);*/
2885 spin_lock(&lcdc_dev->reg_lock);
2886 if (lcdc_dev->clk_on) {
2887 zorder = lcdc_readl(lcdc_dev, DSP_CTRL1);
2888 layer0_sel = (zorder & m_DSP_LAYER0_SEL)>>8;
2889 layer1_sel = (zorder & m_DSP_LAYER1_SEL)>>10;
2890 layer2_sel = (zorder & m_DSP_LAYER2_SEL)>>12;
2891 layer3_sel = (zorder & m_DSP_LAYER3_SEL)>>14;
2893 win_ctrl = lcdc_readl(lcdc_dev, WIN0_CTRL0);
2894 w0_state = win_ctrl & m_WIN0_EN;
2895 fmt_id = (win_ctrl & m_WIN0_DATA_FMT)>>1;
2898 strcpy(format_w0, "ARGB888");
2901 strcpy(format_w0, "RGB888");
2904 strcpy(format_w0, "RGB565");
2907 strcpy(format_w0, "YCbCr420");
2910 strcpy(format_w0, "YCbCr422");
2913 strcpy(format_w0, "YCbCr444");
2916 strcpy(format_w0, "invalid\n");
2919 vir_info = lcdc_readl(lcdc_dev,WIN0_VIR);
2920 act_info = lcdc_readl(lcdc_dev,WIN0_ACT_INFO);
2921 dsp_info = lcdc_readl(lcdc_dev,WIN0_DSP_INFO);
2922 dsp_st = lcdc_readl(lcdc_dev,WIN0_DSP_ST);
2923 y_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_YRGB);
2924 uv_factor = lcdc_readl(lcdc_dev,WIN0_SCL_FACTOR_CBR);
2925 w0_vir_y = vir_info & m_WIN0_VIR_STRIDE;
2926 w0_vir_uv = (vir_info & m_WIN0_VIR_STRIDE_UV)>>16;
2927 w0_act_x = (act_info & m_WIN0_ACT_WIDTH)+1;
2928 w0_act_y = ((act_info & m_WIN0_ACT_HEIGHT)>>16)+1;
2929 w0_dsp_x = (dsp_info & m_WIN0_DSP_WIDTH)+1;
2930 w0_dsp_y = ((dsp_info & m_WIN0_DSP_HEIGHT)>>16)+1;
2932 w0_st_x = dsp_st & m_WIN0_DSP_XST;
2933 w0_st_y = (dsp_st & m_WIN0_DSP_YST)>>16;
2935 w0_y_h_fac = y_factor & m_WIN0_HS_FACTOR_YRGB;
2936 w0_y_v_fac = (y_factor & m_WIN0_VS_FACTOR_YRGB)>>16;
2937 w0_uv_h_fac = uv_factor & m_WIN0_HS_FACTOR_CBR;
2938 w0_uv_v_fac = (uv_factor & m_WIN0_VS_FACTOR_CBR)>>16;
2941 win_ctrl = lcdc_readl(lcdc_dev, WIN1_CTRL0);
2942 w1_state = win_ctrl & m_WIN1_EN;
2943 fmt_id = (win_ctrl & m_WIN1_DATA_FMT)>>1;
2946 strcpy(format_w1, "ARGB888");
2949 strcpy(format_w1, "RGB888");
2952 strcpy(format_w1, "RGB565");
2955 strcpy(format_w1, "YCbCr420");
2958 strcpy(format_w1, "YCbCr422");
2961 strcpy(format_w1, "YCbCr444");
2964 strcpy(format_w1, "invalid\n");
2967 vir_info = lcdc_readl(lcdc_dev,WIN1_VIR);
2968 act_info = lcdc_readl(lcdc_dev,WIN1_ACT_INFO);
2969 dsp_info = lcdc_readl(lcdc_dev,WIN1_DSP_INFO);
2970 dsp_st = lcdc_readl(lcdc_dev,WIN1_DSP_ST);
2971 y_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_YRGB);
2972 uv_factor = lcdc_readl(lcdc_dev,WIN1_SCL_FACTOR_CBR);
2973 w1_vir_y = vir_info & m_WIN1_VIR_STRIDE;
2974 w1_vir_uv = (vir_info & m_WIN1_VIR_STRIDE_UV)>>16;
2975 w1_act_x = (act_info & m_WIN1_ACT_WIDTH)+1;
2976 w1_act_y = ((act_info & m_WIN1_ACT_HEIGHT)>>16)+1;
2977 w1_dsp_x = (dsp_info & m_WIN1_DSP_WIDTH)+1;
2978 w1_dsp_y =((dsp_info & m_WIN1_DSP_HEIGHT)>>16)+1;
2980 w1_st_x = dsp_st & m_WIN1_DSP_XST;
2981 w1_st_y = (dsp_st & m_WIN1_DSP_YST)>>16;
2983 w1_y_h_fac = y_factor & m_WIN1_HS_FACTOR_YRGB;
2984 w1_y_v_fac = (y_factor & m_WIN1_VS_FACTOR_YRGB)>>16;
2985 w1_uv_h_fac = uv_factor & m_WIN1_HS_FACTOR_CBR;
2986 w1_uv_v_fac = (uv_factor & m_WIN1_VS_FACTOR_CBR)>>16;
2988 win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
2989 w2_state = win_ctrl & m_WIN2_EN;
2990 w2_0_state = (win_ctrl & m_WIN2_MST0_EN)>>4;
2991 w2_1_state = (win_ctrl & m_WIN2_MST1_EN)>>5;
2992 w2_2_state = (win_ctrl & m_WIN2_MST2_EN)>>6;
2993 w2_3_state = (win_ctrl & m_WIN2_MST3_EN)>>7;
2994 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR0_1);
2995 w2_0_vir_y = vir_info & m_WIN2_VIR_STRIDE0;
2996 w2_1_vir_y = (vir_info & m_WIN2_VIR_STRIDE1)>>16;
2997 vir_info = lcdc_readl(lcdc_dev,WIN2_VIR2_3);
2998 w2_2_vir_y = vir_info & m_WIN2_VIR_STRIDE2;
2999 w2_3_vir_y = (vir_info & m_WIN2_VIR_STRIDE3)>>16;
3000 fmt_id = (win_ctrl & m_WIN2_DATA_FMT)>>1;
3003 strcpy(format_w2, "ARGB888");
3006 strcpy(format_w2, "RGB888");
3009 strcpy(format_w2, "RGB565");
3012 strcpy(format_w2,"8bpp");
3015 strcpy(format_w2,"4bpp");
3018 strcpy(format_w2,"2bpp");
3021 strcpy(format_w2,"1bpp");
3024 strcpy(format_w2, "invalid\n");
3027 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO0);
3028 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST0);
3029 w2_0_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH0)+1;
3030 w2_0_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT0)>>16)+1;
3032 w2_0_st_x = dsp_st & m_WIN2_DSP_XST0;
3033 w2_0_st_y = (dsp_st & m_WIN2_DSP_YST0)>>16;
3035 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO1);
3036 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST1);
3037 w2_1_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH1)+1;
3038 w2_1_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT1)>>16)+1;
3040 w2_1_st_x = dsp_st & m_WIN2_DSP_XST1;
3041 w2_1_st_y = (dsp_st & m_WIN2_DSP_YST1)>>16;
3043 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO2);
3044 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST2);
3045 w2_2_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH2)+1;
3046 w2_2_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT2)>>16)+1;
3048 w2_2_st_x = dsp_st & m_WIN2_DSP_XST2;
3049 w2_2_st_y = (dsp_st & m_WIN2_DSP_YST2)>>16;
3051 dsp_info = lcdc_readl(lcdc_dev,WIN2_DSP_INFO3);
3052 dsp_st = lcdc_readl(lcdc_dev,WIN2_DSP_ST3);
3053 w2_3_dsp_x = (dsp_info & m_WIN2_DSP_WIDTH3)+1;
3054 w2_3_dsp_y = ((dsp_info & m_WIN2_DSP_HEIGHT3)>>16)+1;
3056 w2_3_st_x = dsp_st & m_WIN2_DSP_XST3;
3057 w2_3_st_y = (dsp_st & m_WIN2_DSP_YST3)>>16;
3061 win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
3062 w3_state = win_ctrl & m_WIN3_EN;
3063 w3_0_state = (win_ctrl & m_WIN3_MST0_EN)>>4;
3064 w3_1_state = (win_ctrl & m_WIN3_MST1_EN)>>5;
3065 w3_2_state = (win_ctrl & m_WIN3_MST2_EN)>>6;
3066 w3_3_state = (win_ctrl & m_WIN3_MST3_EN)>>7;
3067 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR0_1);
3068 w3_0_vir_y = vir_info & m_WIN3_VIR_STRIDE0;
3069 w3_1_vir_y = (vir_info & m_WIN3_VIR_STRIDE1)>>16;
3070 vir_info = lcdc_readl(lcdc_dev,WIN3_VIR2_3);
3071 w3_2_vir_y = vir_info & m_WIN3_VIR_STRIDE2;
3072 w3_3_vir_y = (vir_info & m_WIN3_VIR_STRIDE3)>>16;
3073 fmt_id = (win_ctrl & m_WIN3_DATA_FMT)>>1;
3076 strcpy(format_w3, "ARGB888");
3079 strcpy(format_w3, "RGB888");
3082 strcpy(format_w3, "RGB565");
3085 strcpy(format_w3,"8bpp");
3088 strcpy(format_w3,"4bpp");
3091 strcpy(format_w3,"2bpp");
3094 strcpy(format_w3,"1bpp");
3097 strcpy(format_w3, "invalid");
3100 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO0);
3101 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST0);
3102 w3_0_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH0)+1;
3103 w3_0_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT0)>>16)+1;
3105 w3_0_st_x = dsp_st & m_WIN3_DSP_XST0;
3106 w3_0_st_y = (dsp_st & m_WIN3_DSP_YST0)>>16;
3109 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO1);
3110 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST1);
3111 w3_1_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH1)+1;
3112 w3_1_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT1)>>16)+1;
3114 w3_1_st_x = dsp_st & m_WIN3_DSP_XST1;
3115 w3_1_st_y = (dsp_st & m_WIN3_DSP_YST1)>>16;
3118 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO2);
3119 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST2);
3120 w3_2_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH2)+1;
3121 w3_2_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT2)>>16)+1;
3123 w3_2_st_x = dsp_st & m_WIN3_DSP_XST2;
3124 w3_2_st_y = (dsp_st & m_WIN3_DSP_YST2)>>16;
3127 dsp_info = lcdc_readl(lcdc_dev,WIN3_DSP_INFO3);
3128 dsp_st = lcdc_readl(lcdc_dev,WIN3_DSP_ST3);
3129 w3_3_dsp_x = (dsp_info & m_WIN3_DSP_WIDTH3)+1;
3130 w3_3_dsp_y = ((dsp_info & m_WIN3_DSP_HEIGHT3)>>16)+1;
3132 w3_3_st_x = dsp_st & m_WIN3_DSP_XST3;
3133 w3_3_st_y = (dsp_st & m_WIN3_DSP_YST3)>>16;
3137 spin_unlock(&lcdc_dev->reg_lock);
3140 spin_unlock(&lcdc_dev->reg_lock);
3141 return snprintf(buf, PAGE_SIZE,
3143 " layer3_sel_win[%d]\n"
3144 " layer2_sel_win[%d]\n"
3145 " layer1_sel_win[%d]\n"
3146 " layer0_sel_win[%d]\n"
3251 layer3_sel,layer2_sel,layer1_sel,layer0_sel,
3252 w0_state,format_w0,w0_vir_y,w0_vir_uv,w0_act_x,w0_act_y,
3253 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,
3254 w0_uv_v_fac,lcdc_readl(lcdc_dev, WIN0_YRGB_MST),
3255 lcdc_readl(lcdc_dev, WIN0_CBR_MST),
3257 w1_state,format_w1,w1_vir_y,w1_vir_uv,w1_act_x,w1_act_y,
3258 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,
3259 w1_uv_v_fac,lcdc_readl(lcdc_dev, WIN1_YRGB_MST),
3260 lcdc_readl(lcdc_dev, WIN1_CBR_MST),
3263 w2_0_state,w2_0_vir_y,w2_0_dsp_x,w2_0_dsp_y,
3264 w2_0_st_x-h_pw_bp,w2_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST0),
3266 w2_1_state,w2_1_vir_y,w2_1_dsp_x,w2_1_dsp_y,
3267 w2_1_st_x-h_pw_bp,w2_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST1),
3269 w2_2_state,w2_2_vir_y,w2_2_dsp_x,w2_2_dsp_y,
3270 w2_2_st_x-h_pw_bp,w2_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST2),
3272 w2_3_state,w2_3_vir_y,w2_3_dsp_x,w2_3_dsp_y,
3273 w2_3_st_x-h_pw_bp,w2_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN2_MST3),
3276 w3_0_state,w3_0_vir_y,w3_0_dsp_x,w3_0_dsp_y,
3277 w3_0_st_x-h_pw_bp,w3_0_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST0),
3279 w3_1_state,w3_1_vir_y,w3_1_dsp_x,w3_1_dsp_y,
3280 w3_1_st_x-h_pw_bp,w3_1_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST1),
3282 w3_2_state,w3_2_vir_y,w3_2_dsp_x,w3_2_dsp_y,
3283 w3_2_st_x-h_pw_bp,w3_2_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST2),
3285 w3_3_state,w3_3_vir_y,w3_3_dsp_x,w3_3_dsp_y,
3286 w3_3_st_x-h_pw_bp,w3_3_st_y-v_pw_bp,lcdc_readl(lcdc_dev, WIN3_MST3)
3291 static int rk3288_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
3294 struct lcdc_device *lcdc_dev =
3295 container_of(dev_drv, struct lcdc_device, driver);
3296 struct rk_screen *screen = dev_drv->cur_screen;
3301 u32 x_total, y_total;
3304 dev_info(dev_drv->dev, "unsupport set fps=0\n");
3307 ft = div_u64(1000000000000llu, fps);
3309 screen->mode.upper_margin + screen->mode.lower_margin +
3310 screen->mode.yres + screen->mode.vsync_len;
3312 screen->mode.left_margin + screen->mode.right_margin +
3313 screen->mode.xres + screen->mode.hsync_len;
3314 dev_drv->pixclock = div_u64(ft, x_total * y_total);
3315 dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
3316 ret = clk_set_rate(lcdc_dev->dclk, dotclk);
3319 pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
3320 dev_drv->pixclock = lcdc_dev->pixclock = pixclock;
3321 fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
3322 screen->ft = 1000 / fps; /*one frame time in ms */
3325 dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
3326 clk_get_rate(lcdc_dev->dclk), fps);
3331 static int rk3288_fb_win_remap(struct rk_lcdc_driver *dev_drv, u16 order)
3333 mutex_lock(&dev_drv->fb_win_id_mutex);
3334 if (order == FB_DEFAULT_ORDER)
3335 order = FB0_WIN0_FB1_WIN1_FB2_WIN2_FB3_WIN3;
3336 dev_drv->fb3_win_id = order / 1000;
3337 dev_drv->fb2_win_id = (order / 100) % 10;
3338 dev_drv->fb1_win_id = (order / 10) % 10;
3339 dev_drv->fb0_win_id = order % 10;
3340 mutex_unlock(&dev_drv->fb_win_id_mutex);
3345 static int rk3288_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
3349 mutex_lock(&dev_drv->fb_win_id_mutex);
3350 if (!strcmp(id, "fb0") || !strcmp(id, "fb4"))
3351 win_id = dev_drv->fb0_win_id;
3352 else if (!strcmp(id, "fb1") || !strcmp(id, "fb5"))
3353 win_id = dev_drv->fb1_win_id;
3354 else if (!strcmp(id, "fb2") || !strcmp(id, "fb6"))
3355 win_id = dev_drv->fb2_win_id;
3356 else if (!strcmp(id, "fb3") || !strcmp(id, "fb7"))
3357 win_id = dev_drv->fb3_win_id;
3358 mutex_unlock(&dev_drv->fb_win_id_mutex);
3363 static int rk3288_set_dsp_lut(struct rk_lcdc_driver *dev_drv, int *lut)
3370 struct lcdc_device *lcdc_dev =
3371 container_of(dev_drv, struct lcdc_device, driver);
3372 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0));
3373 lcdc_cfg_done(lcdc_dev);
3375 if (dev_drv->cur_screen->dsp_lut) {
3376 for (i = 0; i < 256; i++) {
3377 v = dev_drv->cur_screen->dsp_lut[i] = lut[i];
3378 c = lcdc_dev->dsp_lut_addr_base + (i << 2);
3379 b = (v & 0xff) << 2;
3380 g = (v & 0xff00) << 4;
3381 r = (v & 0xff0000) << 6;
3383 for (j = 0; j < 4; j++) {
3384 writel_relaxed(v, c);
3385 v += (1 + (1 << 10) + (1 << 20)) ;
3390 dev_err(dev_drv->dev, "no buffer to backup lut data!\n");
3395 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1));
3396 lcdc_cfg_done(lcdc_dev);
3397 }while(!lcdc_read_bit(lcdc_dev,DSP_CTRL1,m_DSP_LUT_EN));
3401 static int rk3288_lcdc_config_done(struct rk_lcdc_driver *dev_drv)
3403 struct lcdc_device *lcdc_dev =
3404 container_of(dev_drv, struct lcdc_device, driver);
3406 unsigned int mask, val;
3407 struct rk_lcdc_win *win = NULL;
3408 struct fb_info *fb0 = rk_get_fb(0);
3410 spin_lock(&lcdc_dev->reg_lock);
3411 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_STANDBY_EN,
3412 v_STANDBY_EN(lcdc_dev->standby));
3414 win = dev_drv->win[i];
3415 if ((win->state == 0)&&(win->last_state == 1)) {
3418 if (dev_drv->version == VOP_FULL_RK3288_V1_0)
3419 lcdc_writel(lcdc_dev, WIN0_CTRL1, 0x0);
3422 lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask,val);
3425 if (dev_drv->version == VOP_FULL_RK3288_V1_0)
3426 lcdc_writel(lcdc_dev, WIN1_CTRL1, 0x0);
3429 lcdc_msk_reg(lcdc_dev, WIN1_CTRL0, mask,val);
3432 mask = m_WIN2_EN | m_WIN2_MST0_EN | m_WIN2_MST1_EN |
3433 m_WIN2_MST2_EN | m_WIN2_MST3_EN;
3434 val = v_WIN2_EN(0) | v_WIN2_MST0_EN(0) | v_WIN2_MST1_EN(0) |
3435 v_WIN2_MST2_EN(0) | v_WIN2_MST3_EN(0);
3436 lcdc_msk_reg(lcdc_dev, WIN2_CTRL0, mask,val);
3437 lcdc_writel(lcdc_dev,WIN2_DSP_INFO0,0);
3438 lcdc_writel(lcdc_dev,WIN2_DSP_INFO1,0);
3439 lcdc_writel(lcdc_dev,WIN2_DSP_INFO2,0);
3440 lcdc_writel(lcdc_dev,WIN2_DSP_INFO3,0);
3441 lcdc_writel(lcdc_dev,WIN2_MST0, fb0->fix.smem_start);
3442 lcdc_writel(lcdc_dev,WIN2_MST1, fb0->fix.smem_start);
3443 lcdc_writel(lcdc_dev,WIN2_MST2, fb0->fix.smem_start);
3444 lcdc_writel(lcdc_dev,WIN2_MST3, fb0->fix.smem_start);
3447 mask = m_WIN3_EN | m_WIN3_MST0_EN | m_WIN3_MST1_EN |
3448 m_WIN3_MST2_EN | m_WIN3_MST3_EN;
3449 val = v_WIN3_EN(0) | v_WIN3_MST0_EN(0) | v_WIN3_MST1_EN(0) |
3450 v_WIN3_MST2_EN(0) | v_WIN3_MST3_EN(0);
3451 lcdc_msk_reg(lcdc_dev, WIN3_CTRL0, mask,val);
3452 lcdc_writel(lcdc_dev,WIN3_DSP_INFO0,0);
3453 lcdc_writel(lcdc_dev,WIN3_DSP_INFO1,0);
3454 lcdc_writel(lcdc_dev,WIN3_DSP_INFO2,0);
3455 lcdc_writel(lcdc_dev,WIN3_DSP_INFO3,0);
3456 lcdc_writel(lcdc_dev,WIN3_MST0, fb0->fix.smem_start);
3457 lcdc_writel(lcdc_dev,WIN3_MST1, fb0->fix.smem_start);
3458 lcdc_writel(lcdc_dev,WIN3_MST2, fb0->fix.smem_start);
3459 lcdc_writel(lcdc_dev,WIN3_MST3, fb0->fix.smem_start);
3465 win->last_state = win->state;
3467 lcdc_cfg_done(lcdc_dev);
3468 spin_unlock(&lcdc_dev->reg_lock);
3473 static int rk3288_lcdc_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
3475 struct lcdc_device *lcdc_dev =
3476 container_of(dev_drv, struct lcdc_device, driver);
3477 spin_lock(&lcdc_dev->reg_lock);
3478 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN,
3479 v_DIRECT_PATH_EN(open));
3480 lcdc_cfg_done(lcdc_dev);
3481 spin_unlock(&lcdc_dev->reg_lock);
3485 static int rk3288_lcdc_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id)
3487 struct lcdc_device *lcdc_dev = container_of(dev_drv,
3488 struct lcdc_device, driver);
3489 spin_lock(&lcdc_dev->reg_lock);
3490 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_DIRECT_PATCH_SEL,
3491 v_DIRECT_PATCH_SEL(win_id));
3492 lcdc_cfg_done(lcdc_dev);
3493 spin_unlock(&lcdc_dev->reg_lock);
3498 static int rk3288_lcdc_dpi_status(struct rk_lcdc_driver *dev_drv)
3500 struct lcdc_device *lcdc_dev =
3501 container_of(dev_drv, struct lcdc_device, driver);
3503 spin_lock(&lcdc_dev->reg_lock);
3504 ovl = lcdc_read_bit(lcdc_dev, SYS_CTRL, m_DIRECT_PATH_EN);
3505 spin_unlock(&lcdc_dev->reg_lock);
3508 static int rk3288_lcdc_set_irq_to_cpu(struct rk_lcdc_driver * dev_drv,int enable)
3510 struct lcdc_device *lcdc_dev =
3511 container_of(dev_drv,struct lcdc_device,driver);
3513 enable_irq(lcdc_dev->irq);
3515 disable_irq(lcdc_dev->irq);
3519 int rk3288_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
3521 struct lcdc_device *lcdc_dev =
3522 container_of(dev_drv, struct lcdc_device, driver);
3526 if (lcdc_dev->clk_on &&(!dev_drv->suspend_flag)){
3527 int_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3528 if (int_reg & m_LINE_FLAG_INTR_STS) {
3529 lcdc_dev->driver.frame_time.last_framedone_t =
3530 lcdc_dev->driver.frame_time.framedone_t;
3531 lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
3532 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3533 v_LINE_FLAG_INTR_CLR(1));
3534 ret = RK_LF_STATUS_FC;
3536 ret = RK_LF_STATUS_FR;
3538 ret = RK_LF_STATUS_NC;
3544 static int rk3288_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
3545 unsigned int dsp_addr[][4])
3547 struct lcdc_device *lcdc_dev =
3548 container_of(dev_drv, struct lcdc_device, driver);
3549 spin_lock(&lcdc_dev->reg_lock);
3550 if (lcdc_dev->clk_on) {
3551 dsp_addr[0][0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
3552 dsp_addr[1][0] = lcdc_readl(lcdc_dev, WIN1_YRGB_MST);
3553 dsp_addr[2][0] = lcdc_readl(lcdc_dev, WIN2_MST0);
3554 dsp_addr[2][1] = lcdc_readl(lcdc_dev, WIN2_MST1);
3555 dsp_addr[2][2] = lcdc_readl(lcdc_dev, WIN2_MST2);
3556 dsp_addr[2][3] = lcdc_readl(lcdc_dev, WIN2_MST3);
3557 dsp_addr[3][0] = lcdc_readl(lcdc_dev, WIN3_MST0);
3558 dsp_addr[3][1] = lcdc_readl(lcdc_dev, WIN3_MST1);
3559 dsp_addr[3][2] = lcdc_readl(lcdc_dev, WIN3_MST2);
3560 dsp_addr[3][3] = lcdc_readl(lcdc_dev, WIN3_MST3);
3562 spin_unlock(&lcdc_dev->reg_lock);
3566 static int rk3288_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv,
3567 int mode, int calc, int up,
3568 int down, int global)
3570 struct lcdc_device *lcdc_dev =
3571 container_of(dev_drv, struct lcdc_device, driver);
3572 struct rk_screen *screen = dev_drv->cur_screen;
3573 u32 total_pixel, calc_pixel, stage_up, stage_down;
3574 u32 pixel_num, global_dn;
3575 u32 mask = 0, val = 0;
3577 if (dev_drv->version != VOP_FULL_RK3288_V1_1) {
3578 pr_err("vop version:%x, not supoort cabc\n", dev_drv->version);
3581 if (!screen->cabc_lut) {
3582 pr_err("screen cabc lut not config, so not open cabc\n");
3585 dev_drv->cabc_mode = mode;
3586 if (!dev_drv->cabc_mode) {
3587 spin_lock(&lcdc_dev->reg_lock);
3588 if (lcdc_dev->clk_on) {
3589 lcdc_msk_reg(lcdc_dev, CABC_CTRL0,
3590 m_CABC_HANDLE_EN | m_CABC_EN,
3591 v_CABC_EN(0) | v_CABC_HANDLE_EN(0));
3592 lcdc_cfg_done(lcdc_dev);
3594 pr_info("mode = 0, close cabc\n");
3595 spin_unlock(&lcdc_dev->reg_lock);
3599 total_pixel = screen->mode.xres * screen->mode.yres;
3600 pixel_num = 1000 - calc;
3601 calc_pixel = (total_pixel * pixel_num) / 1000;
3605 pr_info("enable cabc:mode=%d, calc=%d, up=%d, down=%d, global=%d\n",
3606 mode, calc, stage_up, stage_down, global_dn);
3608 spin_lock(&lcdc_dev->reg_lock);
3609 if (lcdc_dev->clk_on) {
3610 mask = m_CABC_EN | m_CABC_HANDLE_EN | m_PWM_CONFIG_MODE |
3611 m_CABC_CALC_PIXEL_NUM;
3612 val = v_CABC_EN(1) | v_CABC_HANDLE_EN(1) |
3613 v_PWM_CONFIG_MODE(STAGE_BY_STAGE) |
3614 v_CABC_CALC_PIXEL_NUM(calc_pixel);
3615 lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
3617 mask = m_CABC_LUT_EN | m_CABC_TOTAL_PIXEL_NUM;
3618 val = v_CABC_LUT_EN(1) | v_CABC_TOTAL_PIXEL_NUM(total_pixel);
3619 lcdc_msk_reg(lcdc_dev, CABC_CTRL1, mask, val);
3621 mask = m_CABC_STAGE_DOWN | m_CABC_STAGE_UP |
3622 m_CABC_STAGE_MODE | m_MAX_SCALE_CFG_VALUE |
3623 m_MAX_SCALE_CFG_ENABLE;
3624 val = v_CABC_STAGE_DOWN(stage_down) |
3625 v_CABC_STAGE_UP(stage_up) |
3626 v_CABC_STAGE_MODE(0) | v_MAX_SCALE_CFG_VALUE(1) |
3627 v_MAX_SCALE_CFG_ENABLE(0);
3628 lcdc_msk_reg(lcdc_dev, CABC_CTRL2, mask, val);
3630 mask = m_CABC_GLOBAL_DN | m_CABC_GLOBAL_DN_LIMIT_EN;
3631 val = v_CABC_GLOBAL_DN(global_dn) |
3632 v_CABC_GLOBAL_DN_LIMIT_EN(1);
3633 lcdc_msk_reg(lcdc_dev, CABC_CTRL3, mask, val);
3634 lcdc_cfg_done(lcdc_dev);
3636 spin_unlock(&lcdc_dev->reg_lock);
3643 sin_hue = sin(a)*256 +0x100;
3644 cos_hue = cos(a)*256;
3646 sin_hue = sin(a)*256;
3647 cos_hue = cos(a)*256;
3649 static int rk3288_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,bcsh_hue_mode mode)
3652 struct lcdc_device *lcdc_dev =
3653 container_of(dev_drv, struct lcdc_device, driver);
3656 spin_lock(&lcdc_dev->reg_lock);
3657 if (lcdc_dev->clk_on) {
3658 val = lcdc_readl(lcdc_dev, BCSH_H);
3661 val &= m_BCSH_SIN_HUE;
3664 val &= m_BCSH_COS_HUE;
3671 spin_unlock(&lcdc_dev->reg_lock);
3677 static int rk3288_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,int sin_hue, int cos_hue)
3680 struct lcdc_device *lcdc_dev =
3681 container_of(dev_drv, struct lcdc_device, driver);
3684 spin_lock(&lcdc_dev->reg_lock);
3685 if (lcdc_dev->clk_on) {
3686 mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
3687 val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
3688 lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
3689 lcdc_cfg_done(lcdc_dev);
3691 spin_unlock(&lcdc_dev->reg_lock);
3696 static int rk3288_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode,int value)
3698 struct lcdc_device *lcdc_dev =
3699 container_of(dev_drv, struct lcdc_device, driver);
3702 spin_lock(&lcdc_dev->reg_lock);
3703 if(lcdc_dev->clk_on) {
3706 /*from 0 to 255,typical is 128*/
3709 else if (value >= 0x80)
3710 value = value - 0x80;
3711 mask = m_BCSH_BRIGHTNESS;
3712 val = v_BCSH_BRIGHTNESS(value);
3715 /*from 0 to 510,typical is 256*/
3716 mask = m_BCSH_CONTRAST;
3717 val = v_BCSH_CONTRAST(value);
3720 /*from 0 to 1015,typical is 256*/
3721 mask = m_BCSH_SAT_CON;
3722 val = v_BCSH_SAT_CON(value);
3727 lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
3728 lcdc_cfg_done(lcdc_dev);
3730 spin_unlock(&lcdc_dev->reg_lock);
3734 static int rk3288_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,bcsh_bcs_mode mode)
3736 struct lcdc_device *lcdc_dev =
3737 container_of(dev_drv, struct lcdc_device, driver);
3740 spin_lock(&lcdc_dev->reg_lock);
3741 if(lcdc_dev->clk_on) {
3742 val = lcdc_readl(lcdc_dev, BCSH_BCS);
3745 val &= m_BCSH_BRIGHTNESS;
3752 val &= m_BCSH_CONTRAST;
3756 val &= m_BCSH_SAT_CON;
3763 spin_unlock(&lcdc_dev->reg_lock);
3768 static int rk3288_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
3770 struct lcdc_device *lcdc_dev =
3771 container_of(dev_drv, struct lcdc_device, driver);
3774 spin_lock(&lcdc_dev->reg_lock);
3775 if (lcdc_dev->clk_on) {
3777 lcdc_writel(lcdc_dev,BCSH_COLOR_BAR,0x1);
3778 lcdc_writel(lcdc_dev,BCSH_BCS,0xd0010000);
3779 lcdc_writel(lcdc_dev,BCSH_H,0x01000000);
3780 dev_drv->bcsh.enable = 1;
3784 lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
3785 dev_drv->bcsh.enable = 0;
3787 if (dev_drv->version == VOP_FULL_RK3288_V1_1)
3788 rk3288_lcdc_bcsh_path_sel(dev_drv);
3789 lcdc_cfg_done(lcdc_dev);
3791 spin_unlock(&lcdc_dev->reg_lock);
3795 static int rk3288_lcdc_set_bcsh(struct rk_lcdc_driver *dev_drv,
3798 if (!enable || !dev_drv->bcsh.enable) {
3799 rk3288_lcdc_open_bcsh(dev_drv, false);
3803 if (dev_drv->bcsh.brightness <= 255 ||
3804 dev_drv->bcsh.contrast <= 510 ||
3805 dev_drv->bcsh.sat_con <= 1015 ||
3806 (dev_drv->bcsh.sin_hue <= 511 && dev_drv->bcsh.cos_hue <= 511)) {
3807 rk3288_lcdc_open_bcsh(dev_drv, true);
3808 if (dev_drv->bcsh.brightness <= 255)
3809 rk3288_lcdc_set_bcsh_bcs(dev_drv, BRIGHTNESS,
3810 dev_drv->bcsh.brightness);
3811 if (dev_drv->bcsh.contrast <= 510)
3812 rk3288_lcdc_set_bcsh_bcs(dev_drv, CONTRAST,
3813 dev_drv->bcsh.contrast);
3814 if (dev_drv->bcsh.sat_con <= 1015)
3815 rk3288_lcdc_set_bcsh_bcs(dev_drv, SAT_CON,
3816 dev_drv->bcsh.sat_con);
3817 if (dev_drv->bcsh.sin_hue <= 511 &&
3818 dev_drv->bcsh.cos_hue <= 511)
3819 rk3288_lcdc_set_bcsh_hue(dev_drv,
3820 dev_drv->bcsh.sin_hue,
3821 dev_drv->bcsh.cos_hue);
3826 static int rk3288_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
3827 struct overscan *overscan)
3829 struct lcdc_device *lcdc_dev =
3830 container_of(dev_drv, struct lcdc_device, driver);
3832 if (unlikely(!lcdc_dev->clk_on)) {
3833 pr_info("%s,clk_on = %d\n", __func__, lcdc_dev->clk_on);
3836 rk3288_lcdc_post_cfg(dev_drv);
3841 static struct rk_lcdc_win lcdc_win[] = {
3845 .support_3d = false,
3850 .support_3d = false,
3855 .support_3d = false,
3860 .support_3d = false,
3864 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
3865 .open = rk3288_lcdc_open,
3866 .win_direct_en = rk3288_lcdc_win_direct_en,
3867 .load_screen = rk3288_load_screen,
3868 .get_dspbuf_info = rk3288_get_dspbuf_info,
3869 .post_dspbuf = rk3288_post_dspbuf,
3870 .set_par = rk3288_lcdc_set_par,
3871 .pan_display = rk3288_lcdc_pan_display,
3872 .direct_set_addr = rk3288_lcdc_direct_set_win_addr,
3873 .lcdc_reg_update = rk3288_lcdc_reg_update,
3874 .blank = rk3288_lcdc_blank,
3875 .ioctl = rk3288_lcdc_ioctl,
3876 .suspend = rk3288_lcdc_early_suspend,
3877 .resume = rk3288_lcdc_early_resume,
3878 .get_win_state = rk3288_lcdc_get_win_state,
3879 .area_support_num = rk3288_lcdc_get_area_num,
3880 .ovl_mgr = rk3288_lcdc_ovl_mgr,
3881 .get_disp_info = rk3288_lcdc_get_disp_info,
3882 .fps_mgr = rk3288_lcdc_fps_mgr,
3883 .fb_get_win_id = rk3288_lcdc_get_win_id,
3884 .fb_win_remap = rk3288_fb_win_remap,
3885 .set_dsp_lut = rk3288_set_dsp_lut,
3886 .poll_vblank = rk3288_lcdc_poll_vblank,
3887 .dpi_open = rk3288_lcdc_dpi_open,
3888 .dpi_win_sel = rk3288_lcdc_dpi_win_sel,
3889 .dpi_status = rk3288_lcdc_dpi_status,
3890 .get_dsp_addr = rk3288_lcdc_get_dsp_addr,
3891 .set_dsp_cabc = rk3288_lcdc_set_dsp_cabc,
3892 .set_dsp_bcsh_hue = rk3288_lcdc_set_bcsh_hue,
3893 .set_dsp_bcsh_bcs = rk3288_lcdc_set_bcsh_bcs,
3894 .get_dsp_bcsh_hue = rk3288_lcdc_get_bcsh_hue,
3895 .get_dsp_bcsh_bcs = rk3288_lcdc_get_bcsh_bcs,
3896 .open_bcsh = rk3288_lcdc_open_bcsh,
3897 .dump_reg = rk3288_lcdc_reg_dump,
3898 .cfg_done = rk3288_lcdc_config_done,
3899 .set_irq_to_cpu = rk3288_lcdc_set_irq_to_cpu,
3900 .mmu_en = rk3288_lcdc_mmu_en,
3901 .set_overscan = rk3288_lcdc_set_overscan,
3905 #ifdef LCDC_IRQ_DEBUG
3906 static int rk3288_lcdc_parse_irq(struct lcdc_device *lcdc_dev,unsigned int reg_val)
3908 if (reg_val & m_WIN0_EMPTY_INTR_STS) {
3909 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN0_EMPTY_INTR_CLR,
3910 v_WIN0_EMPTY_INTR_CLR(1));
3911 dev_warn(lcdc_dev->dev,"win0 empty irq!");
3912 }else if (reg_val & m_WIN1_EMPTY_INTR_STS) {
3913 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN1_EMPTY_INTR_CLR,
3914 v_WIN1_EMPTY_INTR_CLR(1));
3915 dev_warn(lcdc_dev->dev,"win1 empty irq!");
3916 }else if (reg_val & m_WIN2_EMPTY_INTR_STS) {
3917 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN2_EMPTY_INTR_CLR,
3918 v_WIN2_EMPTY_INTR_CLR(1));
3919 dev_warn(lcdc_dev->dev,"win2 empty irq!");
3920 }else if (reg_val & m_WIN3_EMPTY_INTR_STS) {
3921 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_WIN3_EMPTY_INTR_CLR,
3922 v_WIN3_EMPTY_INTR_CLR(1));
3923 dev_warn(lcdc_dev->dev,"win3 empty irq!");
3924 }else if (reg_val & m_HWC_EMPTY_INTR_STS) {
3925 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_HWC_EMPTY_INTR_CLR,
3926 v_HWC_EMPTY_INTR_CLR(1));
3927 dev_warn(lcdc_dev->dev,"HWC empty irq!");
3928 }else if (reg_val & m_POST_BUF_EMPTY_INTR_STS) {
3929 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_POST_BUF_EMPTY_INTR_CLR,
3930 v_POST_BUF_EMPTY_INTR_CLR(1));
3931 dev_warn(lcdc_dev->dev,"post buf empty irq!");
3932 }else if (reg_val & m_PWM_GEN_INTR_STS) {
3933 lcdc_msk_reg(lcdc_dev, INTR_CTRL1, m_PWM_GEN_INTR_CLR,
3934 v_PWM_GEN_INTR_CLR(1));
3935 dev_warn(lcdc_dev->dev,"PWM gen irq!");
3942 static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
3944 struct lcdc_device *lcdc_dev =
3945 (struct lcdc_device *)dev_id;
3946 ktime_t timestamp = ktime_get();
3949 intr0_reg = lcdc_readl(lcdc_dev, INTR_CTRL0);
3951 if(intr0_reg & m_FS_INTR_STS){
3952 timestamp = ktime_get();
3953 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_FS_INTR_CLR,
3955 /*if(lcdc_dev->driver.wait_fs){ */
3957 spin_lock(&(lcdc_dev->driver.cpl_lock));
3958 complete(&(lcdc_dev->driver.frame_done));
3959 spin_unlock(&(lcdc_dev->driver.cpl_lock));
3961 #ifdef CONFIG_DRM_ROCKCHIP
3962 lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
3964 lcdc_dev->driver.vsync_info.timestamp = timestamp;
3965 wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
3967 }else if(intr0_reg & m_LINE_FLAG_INTR_STS){
3968 lcdc_dev->driver.frame_time.last_framedone_t =
3969 lcdc_dev->driver.frame_time.framedone_t;
3970 lcdc_dev->driver.frame_time.framedone_t = cpu_clock(0);
3971 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_LINE_FLAG_INTR_CLR,
3972 v_LINE_FLAG_INTR_CLR(1));
3973 }else if(intr0_reg & m_BUS_ERROR_INTR_STS){
3974 lcdc_msk_reg(lcdc_dev, INTR_CTRL0, m_BUS_ERROR_INTR_CLR,
3975 v_BUS_ERROR_INTR_CLR(1));
3976 dev_warn(lcdc_dev->dev,"buf_error_int!");
3979 /* for win empty debug */
3980 #ifdef LCDC_IRQ_EMPTY_DEBUG
3981 intr1_reg = lcdc_readl(lcdc_dev, INTR_CTRL1);
3982 if (intr1_reg != 0) {
3983 rk3288_lcdc_parse_irq(lcdc_dev,intr1_reg);
3989 #if defined(CONFIG_PM)
3990 static int rk3288_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
3995 static int rk3288_lcdc_resume(struct platform_device *pdev)
4000 #define rk3288_lcdc_suspend NULL
4001 #define rk3288_lcdc_resume NULL
4004 static int rk3288_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
4006 struct device_node *np = lcdc_dev->dev->of_node;
4007 struct rk_lcdc_driver *dev_drv = &lcdc_dev->driver;
4010 if (of_property_read_u32(np, "rockchip,prop", &val))
4011 lcdc_dev->prop = PRMRY; /*default set it as primary */
4013 lcdc_dev->prop = val;
4015 if (of_property_read_u32(np, "rockchip,mirror", &val))
4016 dev_drv->rotate_mode = NO_MIRROR;
4018 dev_drv->rotate_mode = val;
4020 if (of_property_read_u32(np, "rockchip,cabc_mode", &val))
4021 dev_drv->cabc_mode = 0; /* default set close cabc */
4023 dev_drv->cabc_mode = val;
4025 if (of_property_read_u32(np, "rockchip,pwr18", &val))
4026 lcdc_dev->pwr18 = false; /*default set it as 3.xv power supply */
4028 lcdc_dev->pwr18 = (val ? true : false);
4030 if (of_property_read_u32(np, "rockchip,fb-win-map", &val))
4031 dev_drv->fb_win_map = FB_DEFAULT_ORDER;
4033 dev_drv->fb_win_map = val;
4035 if (of_property_read_u32(np, "rockchip,bcsh-en", &val))
4036 dev_drv->bcsh.enable = false;
4038 dev_drv->bcsh.enable = (val ? true : false);
4040 if (of_property_read_u32(np, "rockchip,brightness", &val))
4041 dev_drv->bcsh.brightness = 0xffff;
4043 dev_drv->bcsh.brightness = val;
4045 if (of_property_read_u32(np, "rockchip,contrast", &val))
4046 dev_drv->bcsh.contrast = 0xffff;
4048 dev_drv->bcsh.contrast = val;
4050 if (of_property_read_u32(np, "rockchip,sat-con", &val))
4051 dev_drv->bcsh.sat_con = 0xffff;
4053 dev_drv->bcsh.sat_con = val;
4055 if (of_property_read_u32(np, "rockchip,hue", &val)) {
4056 dev_drv->bcsh.sin_hue = 0xffff;
4057 dev_drv->bcsh.cos_hue = 0xffff;
4059 dev_drv->bcsh.sin_hue = val & 0xff;
4060 dev_drv->bcsh.cos_hue = (val >> 8) & 0xff;
4063 #if defined(CONFIG_ROCKCHIP_IOMMU)
4064 if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
4065 dev_drv->iommu_enabled = 0;
4067 dev_drv->iommu_enabled = val;
4069 dev_drv->iommu_enabled = 0;
4074 static int rk3288_lcdc_probe(struct platform_device *pdev)
4076 struct lcdc_device *lcdc_dev = NULL;
4077 struct rk_lcdc_driver *dev_drv;
4078 struct device *dev = &pdev->dev;
4079 struct resource *res;
4080 struct device_node *np = pdev->dev.of_node;
4084 /*if the primary lcdc has not registered ,the extend
4085 lcdc register later */
4086 of_property_read_u32(np, "rockchip,prop", &prop);
4087 if (prop == EXTEND) {
4088 if (!is_prmry_rk_lcdc_registered())
4089 return -EPROBE_DEFER;
4091 lcdc_dev = devm_kzalloc(dev,
4092 sizeof(struct lcdc_device), GFP_KERNEL);
4094 dev_err(&pdev->dev, "rk3288 lcdc device kmalloc fail!");
4097 platform_set_drvdata(pdev, lcdc_dev);
4098 lcdc_dev->dev = dev;
4099 rk3288_lcdc_parse_dt(lcdc_dev);
4100 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4101 lcdc_dev->reg_phy_base = res->start;
4102 lcdc_dev->len = resource_size(res);
4103 lcdc_dev->regs = devm_ioremap_resource(dev, res);
4104 if (IS_ERR(lcdc_dev->regs))
4105 return PTR_ERR(lcdc_dev->regs);
4107 lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
4108 if (IS_ERR(lcdc_dev->regsbak))
4109 return PTR_ERR(lcdc_dev->regsbak);
4110 lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs + GAMMA_LUT_ADDR);
4111 lcdc_dev->id = rk3288_lcdc_get_id(lcdc_dev->reg_phy_base);
4112 if (lcdc_dev->id < 0) {
4113 dev_err(&pdev->dev, "no such lcdc device!\n");
4116 dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
4117 dev_drv = &lcdc_dev->driver;
4119 dev_drv->prop = prop;
4120 dev_drv->id = lcdc_dev->id;
4121 dev_drv->ops = &lcdc_drv_ops;
4122 dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
4123 spin_lock_init(&lcdc_dev->reg_lock);
4125 lcdc_dev->irq = platform_get_irq(pdev, 0);
4126 if (lcdc_dev->irq < 0) {
4127 dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
4132 ret = devm_request_irq(dev, lcdc_dev->irq, rk3288_lcdc_isr,
4133 IRQF_DISABLED | IRQF_SHARED, dev_name(dev), lcdc_dev);
4135 dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
4136 lcdc_dev->irq, ret);
4140 if (dev_drv->iommu_enabled) {
4141 if(lcdc_dev->id == 0){
4142 strcpy(dev_drv->mmu_dts_name, VOPB_IOMMU_COMPATIBLE_NAME);
4144 strcpy(dev_drv->mmu_dts_name, VOPL_IOMMU_COMPATIBLE_NAME);
4148 ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
4150 dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
4153 lcdc_dev->screen = dev_drv->screen0;
4154 dev_info(dev, "lcdc%d probe ok, iommu %s\n",
4155 lcdc_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
4160 static int rk3288_lcdc_remove(struct platform_device *pdev)
4166 static void rk3288_lcdc_shutdown(struct platform_device *pdev)
4168 struct lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
4170 rk3288_lcdc_deint(lcdc_dev);
4171 rk_disp_pwr_disable(&lcdc_dev->driver);
4174 #if defined(CONFIG_OF)
4175 static const struct of_device_id rk3288_lcdc_dt_ids[] = {
4176 {.compatible = "rockchip,rk3288-lcdc",},
4181 static struct platform_driver rk3288_lcdc_driver = {
4182 .probe = rk3288_lcdc_probe,
4183 .remove = rk3288_lcdc_remove,
4185 .name = "rk3288-lcdc",
4186 .owner = THIS_MODULE,
4187 .of_match_table = of_match_ptr(rk3288_lcdc_dt_ids),
4189 .suspend = rk3288_lcdc_suspend,
4190 .resume = rk3288_lcdc_resume,
4191 .shutdown = rk3288_lcdc_shutdown,
4194 static int __init rk3288_lcdc_module_init(void)
4196 return platform_driver_register(&rk3288_lcdc_driver);
4199 static void __exit rk3288_lcdc_module_exit(void)
4201 platform_driver_unregister(&rk3288_lcdc_driver);
4204 fs_initcall(rk3288_lcdc_module_init);
4205 module_exit(rk3288_lcdc_module_exit);