2 * rockchip VOP(Video Output Processer) hardware driver.
4 * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
5 * Author: WenLong Zhuang <daisen.zhuang@rock-chips.com>
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/string.h>
23 #include <linux/slab.h>
24 #include <linux/device.h>
25 #include <linux/delay.h>
26 #include <linux/init.h>
27 #include <linux/interrupt.h>
28 #include <linux/platform_device.h>
29 #include <linux/clk.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/rockchip-iovmm.h>
32 #include <asm/div64.h>
33 #include <linux/uaccess.h>
34 #include <linux/rockchip/cpu.h>
35 #include <linux/rockchip/iomap.h>
36 #include <linux/rockchip/grf.h>
37 #include <linux/rockchip/common.h>
38 #include <dt-bindings/clock/rk_system_status.h>
40 #include "rk_vop_lite.h"
42 static int dbg_thresd;
43 module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
45 #define DBG(level, x...) do { \
46 if (unlikely(dbg_thresd >= level)) \
50 #define to_vop_dev(drv) container_of(drv, struct vop_device, driver)
52 static struct rk_lcdc_win vop_win[] = {
53 { .name = "win0", .id = 0},
54 { .name = "win1", .id = 1},
55 { .name = "hwc", .id = 2}
58 static int vop_set_bcsh(struct rk_lcdc_driver *dev_drv, bool enable);
60 static int vop_clk_enable(struct vop_device *vop_dev)
62 if (!vop_dev->clk_on) {
63 pm_runtime_get_sync(vop_dev->dev);
65 clk_enable(vop_dev->hclk);
66 clk_enable(vop_dev->aclk);
67 clk_enable(vop_dev->dclk);
68 spin_lock(&vop_dev->reg_lock);
70 spin_unlock(&vop_dev->reg_lock);
76 static int vop_clk_disable(struct vop_device *vop_dev)
78 if (vop_dev->clk_on) {
79 spin_lock(&vop_dev->reg_lock);
81 spin_unlock(&vop_dev->reg_lock);
82 clk_disable(vop_dev->dclk);
83 clk_disable(vop_dev->aclk);
84 clk_disable(vop_dev->hclk);
86 pm_runtime_put(vop_dev->dev);
92 static int vop_irq_enable(struct vop_device *vop_dev)
96 spin_lock(&vop_dev->reg_lock);
97 if (likely(vop_dev->clk_on)) {
98 vop_mask_writel(vop_dev, INTR_CLEAR, INTR_MASK, INTR_MASK);
100 val = INTR_FS0 | INTR_FS1 | INTR_LINE_FLAG0 | INTR_LINE_FLAG1 |
101 INTR_BUS_ERROR | INTR_WIN0_EMPTY | INTR_WIN1_EMPTY |
103 vop_mask_writel(vop_dev, INTR_EN, INTR_MASK, val);
105 spin_unlock(&vop_dev->reg_lock);
110 static int vop_irq_disable(struct vop_device *vop_dev)
112 spin_lock(&vop_dev->reg_lock);
113 if (likely(vop_dev->clk_on)) {
114 vop_writel(vop_dev, INTR_EN, 0xffff0000);
115 vop_writel(vop_dev, INTR_CLEAR, 0xffffffff);
116 vop_cfg_done(vop_dev);
118 spin_unlock(&vop_dev->reg_lock);
123 static int vop_standby_enable(struct vop_device *vop_dev)
128 spin_lock(&vop_dev->reg_lock);
129 if (likely(vop_dev->clk_on)) {
130 vop_dev->sync.stdbyfin.done = 0;
132 vop_msk_reg(vop_dev, DSP_CTRL2, V_DSP_BLANK_EN(1));
133 /*vop_mask_writel(vop_dev, INTR_CLEAR0, INTR_MASK, INTR_MASK);*/
134 val = V_IMD_VOP_STANDBY_EN(1) | V_IMD_VOP_DMA_STOP(1) |
135 V_IMD_DSP_OUT_ZERO(1);
136 vop_msk_reg(vop_dev, SYS_CTRL2, val);
137 vop_cfg_done(vop_dev);
138 spin_unlock(&vop_dev->reg_lock);
140 /* wait for standby hold valid */
141 ret = vop_completion_timeout_ms(&vop_dev->sync.stdbyfin,
142 vop_dev->sync.stdbyfin_to);
144 dev_err(vop_dev->dev,
145 "wait standby hold valid timeout %dms\n",
146 vop_dev->sync.stdbyfin_to);
150 spin_unlock(&vop_dev->reg_lock);
156 static int vop_standby_disable(struct vop_device *vop_dev)
161 spin_lock(&vop_dev->reg_lock);
162 if (likely(vop_dev->clk_on)) {
163 vop_dev->sync.frmst.done = 0;
164 val = V_IMD_VOP_STANDBY_EN(0) | V_IMD_VOP_DMA_STOP(0) |
165 V_IMD_DSP_OUT_ZERO(0);
166 vop_msk_reg(vop_dev, SYS_CTRL2, val);
167 vop_msk_reg(vop_dev, DSP_CTRL2, V_DSP_BLANK_EN(0));
168 vop_cfg_done(vop_dev);
169 spin_unlock(&vop_dev->reg_lock);
171 /* win address maybe effect after next frame start,
172 * but mmu maybe effect right now, so need wait frame start
174 ret = vop_completion_timeout_ms(&vop_dev->sync.frmst,
175 vop_dev->sync.frmst_to);
177 dev_err(vop_dev->dev, "wait frame start timeout %dms\n",
178 vop_dev->sync.frmst_to);
182 spin_unlock(&vop_dev->reg_lock);
188 static int vop_mmu_enable(struct rk_lcdc_driver *dev_drv)
190 struct vop_device *vop_dev = to_vop_dev(dev_drv);
192 if (!dev_drv->iommu_enabled || !dev_drv->mmu_dev) {
193 pr_debug("%s: VOP iommu is disabled or not find mmu dev\n",
198 spin_lock(&vop_dev->reg_lock);
199 if (likely(vop_dev->clk_on)) {
200 if (!vop_dev->iommu_status) {
201 vop_dev->iommu_status = 1;
202 rockchip_iovmm_activate(dev_drv->dev);
205 spin_unlock(&vop_dev->reg_lock);
210 static int vop_mmu_disable(struct rk_lcdc_driver *dev_drv)
212 struct vop_device *vop_dev = to_vop_dev(dev_drv);
214 if (!dev_drv->iommu_enabled || !dev_drv->mmu_dev) {
215 pr_debug("%s: VOP iommu is disabled or not find mmu dev\n",
220 spin_lock(&vop_dev->reg_lock);
221 if (likely(vop_dev->clk_on)) {
222 if (vop_dev->iommu_status) {
223 vop_dev->iommu_status = 0;
224 rockchip_iovmm_deactivate(dev_drv->dev);
227 spin_unlock(&vop_dev->reg_lock);
232 static int vop_reg_dump(struct rk_lcdc_driver *dev_drv)
234 struct vop_device *vop_dev = to_vop_dev(dev_drv);
235 int *cbase = (int *)vop_dev->regs;
236 int *regsbak = (int *)vop_dev->regsbak;
238 char dbg_message[30];
241 spin_lock(&vop_dev->reg_lock);
242 if (likely(vop_dev->clk_on)) {
243 pr_info("vop back up reg:\n");
244 memset(dbg_message, 0, sizeof(dbg_message));
245 memset(buf, 0, sizeof(buf));
246 for (i = 0; i <= (0x200 >> 4); i++) {
247 val = sprintf(dbg_message, "0x%04x: ", i * 16);
248 for (j = 0; j < 4; j++) {
249 val = sprintf(buf, "%08x ",
250 *(regsbak + i * 4 + j));
251 strcat(dbg_message, buf);
253 pr_info("%s\n", dbg_message);
254 memset(dbg_message, 0, sizeof(dbg_message));
255 memset(buf, 0, sizeof(buf));
258 pr_info("vop reg:\n");
259 for (i = 0; i <= (0x200 >> 4); i++) {
260 val = sprintf(dbg_message, "0x%04x: ", i * 16);
261 for (j = 0; j < 4; j++) {
262 sprintf(buf, "%08x ",
263 readl_relaxed(cbase + i * 4 + j));
264 strcat(dbg_message, buf);
266 pr_info("%s\n", dbg_message);
267 memset(dbg_message, 0, sizeof(dbg_message));
268 memset(buf, 0, sizeof(buf));
271 spin_unlock(&vop_dev->reg_lock);
277 static int win##id##_enable(struct vop_device *vop_dev, int en) \
279 spin_lock(&vop_dev->reg_lock); \
280 vop_msk_reg(vop_dev, WIN##id##_CTRL0, V_WIN##id##_EN((u64)en)); \
281 vop_cfg_done(vop_dev); \
282 spin_unlock(&vop_dev->reg_lock); \
290 * enable/disable win directly
292 static int vop_win_direct_en(struct rk_lcdc_driver *drv,
295 struct vop_device *vop_dev = to_vop_dev(drv);
298 win0_enable(vop_dev, en);
299 else if (win_id == 1)
300 win1_enable(vop_dev, en);
302 dev_err(vop_dev->dev, "invalid win number:%d\n", win_id);
306 #define SET_WIN_ADDR(id) \
307 static int set_win##id##_addr(struct vop_device *vop_dev, u32 addr) \
309 spin_lock(&vop_dev->reg_lock); \
310 vop_writel(vop_dev, WIN##id##_YRGB_MST, addr); \
311 vop_msk_reg(vop_dev, WIN##id##_CTRL0, V_WIN##id##_EN(1)); \
312 vop_cfg_done(vop_dev); \
313 spin_unlock(&vop_dev->reg_lock); \
320 static int vop_direct_set_win_addr(struct rk_lcdc_driver *dev_drv,
321 int win_id, u32 addr)
323 struct vop_device *vop_dev = to_vop_dev(dev_drv);
326 set_win0_addr(vop_dev, addr);
328 set_win1_addr(vop_dev, addr);
333 static void vop_read_reg_default_cfg(struct vop_device *vop_dev)
337 struct rk_screen *screen = vop_dev->driver.cur_screen;
338 u32 h_pw_bp = screen->mode.hsync_len + screen->mode.left_margin;
339 u32 V_pw_bp = screen->mode.vsync_len + screen->mode.upper_margin;
341 struct rk_lcdc_win *win0 = vop_dev->driver.win[0];
343 spin_lock(&vop_dev->reg_lock);
344 for (reg = 0; reg < vop_dev->len; reg += 4) {
345 val = vop_readl_backup(vop_dev, reg);
348 win0->area[0].xact = (val & MASK(WIN0_ACT_WIDTH)) + 1;
350 ((val & MASK(WIN0_ACT_HEIGHT)) >> 16) + 1;
353 win0->area[0].xsize = (val & MASK(WIN0_DSP_WIDTH)) + 1;
354 win0->area[0].ysize =
355 ((val & MASK(WIN0_DSP_HEIGHT)) >> 16) + 1;
358 st_x = val & MASK(WIN0_DSP_XST);
359 st_y = (val & MASK(WIN0_DSP_YST)) >> 16;
360 win0->area[0].xpos = st_x - h_pw_bp;
361 win0->area[0].ypos = st_y - V_pw_bp;
364 win0->state = val & MASK(WIN0_EN);
365 win0->area[0].fmt_cfg =
366 (val & MASK(WIN0_DATA_FMT)) >> 1;
367 win0->area[0].format = win0->area[0].fmt_cfg;
370 win0->area[0].y_vir_stride =
371 val & MASK(WIN0_YRGB_VIR_STRIDE);
372 win0->area[0].uv_vir_stride =
373 (val & MASK(WIN0_CBR_VIR_STRIDE)) >> 16;
374 if (win0->area[0].format == ARGB888)
375 win0->area[0].xvir = win0->area[0].y_vir_stride;
376 else if (win0->area[0].format == RGB888)
378 win0->area[0].y_vir_stride * 4 / 3;
379 else if ((win0->area[0].format == RGB565) ||
380 (win0->area[0].format == BGR565))
382 2 * win0->area[0].y_vir_stride;
385 4 * win0->area[0].y_vir_stride;
388 win0->area[0].smem_start = val;
391 win0->area[0].cbr_start = val;
397 spin_unlock(&vop_dev->reg_lock);
400 static int vop_pre_init(struct rk_lcdc_driver *dev_drv)
402 struct vop_device *vop_dev = to_vop_dev(dev_drv);
404 if (vop_dev->pre_init)
407 if (dev_drv->iommu_enabled) {
408 dev_drv->mmu_dev = rk_fb_get_sysmmu_device_by_compatible(
409 dev_drv->mmu_dts_name);
410 if (dev_drv->mmu_dev)
411 rk_fb_platform_set_sysmmu(
412 dev_drv->mmu_dev, dev_drv->dev);
414 dev_err(dev_drv->dev, "fail get rk iommu device\n");
417 if (!support_uboot_display())
418 rk_disp_pwr_enable(dev_drv);
420 vop_clk_enable(vop_dev);
422 /* backup reg config at uboot */
423 vop_read_reg_default_cfg(vop_dev);
425 /* vop io voltage select-->0: 3.3v; 1: 1.8v */
426 if (vop_dev->pwr18 == 1)
427 vop_grf_writel(vop_dev->grf_base, GRF_IO_VSEL,
430 vop_grf_writel(vop_dev->grf_base, GRF_IO_VSEL,
433 vop_msk_reg(vop_dev, SYS_CTRL1, V_SW_AXI_MAX_OUTSTAND_EN(1) |
434 V_SW_AXI_MAX_OUTSTAND_NUM(31));
435 vop_msk_reg(vop_dev, SYS_CTRL2, V_IMD_AUTO_GATING_EN(0));
436 vop_cfg_done(vop_dev);
437 vop_dev->pre_init = true;
442 static void vop_deinit(struct vop_device *vop_dev)
444 struct rk_lcdc_driver *dev_drv = &vop_dev->driver;
446 vop_standby_enable(vop_dev);
447 vop_irq_disable(vop_dev);
448 vop_mmu_disable(dev_drv);
449 vop_clk_disable(vop_dev);
450 clk_unprepare(vop_dev->dclk);
451 clk_unprepare(vop_dev->aclk);
452 clk_unprepare(vop_dev->hclk);
453 pm_runtime_disable(vop_dev->dev);
456 static void __maybe_unused
457 vop_win_csc_mode(struct vop_device *vop_dev, struct rk_lcdc_win *win,
462 spin_lock(&vop_dev->reg_lock);
463 if (likely(vop_dev->clk_on)) {
465 val = V_WIN0_CSC_MODE(csc_mode);
466 vop_msk_reg(vop_dev, WIN0_CTRL0, val);
467 } else if (win->id == 1) {
468 val = V_WIN1_CSC_MODE(csc_mode);
469 vop_msk_reg(vop_dev, WIN1_CTRL0, val);
471 dev_err(vop_dev->dev, "%s win%d unsupport csc mode",
475 spin_unlock(&vop_dev->reg_lock);
478 static int vop_clr_key_cfg(struct rk_lcdc_driver *dev_drv)
480 struct vop_device *vop_dev = to_vop_dev(dev_drv);
481 struct rk_lcdc_win *win;
484 for (i = 0; i < dev_drv->lcdc_win_num; i++) {
485 win = dev_drv->win[i];
488 vop_writel(vop_dev, WIN0_COLOR_KEY, win->color_key_val);
491 vop_writel(vop_dev, WIN1_COLOR_KEY, win->color_key_val);
494 pr_info("%s:un support win num:%d\n",
502 static int vop_alpha_cfg(struct rk_lcdc_driver *dev_drv, int win_id)
504 struct vop_device *vop_dev = to_vop_dev(dev_drv);
505 struct rk_lcdc_win *win = dev_drv->win[win_id];
507 int ppixel_alpha = 0;
508 int alpha_en = win->alpha_en;
513 val = V_WIN0_ALPHA_EN(0);
514 vop_msk_reg(vop_dev, WIN0_ALPHA_CTRL, val);
516 val = V_WIN1_ALPHA_EN(0);
517 vop_msk_reg(vop_dev, WIN1_ALPHA_CTRL, val);
522 ppixel_alpha = ((win->area[0].format == ARGB888) ||
523 (win->area[0].format == ABGR888)) ? 1 : 0;
525 for (i = 0; i < dev_drv->lcdc_win_num; i++) {
526 if (!dev_drv->win[i]->state)
528 if (win->z_order > dev_drv->win[i]->z_order)
533 * The bottom layer not support ppixel_alpha mode.
535 if (i == dev_drv->lcdc_win_num) {
541 val = V_WIN0_ALPHA_EN(alpha_en) |
542 V_WIN0_ALPHA_MODE(ppixel_alpha) |
543 V_WIN0_ALPHA_PRE_MUL(ppixel_alpha) |
544 V_WIN0_ALPHA_SAT_MODE(0);
545 vop_msk_reg(vop_dev, WIN0_ALPHA_CTRL, val);
546 } else if (win_id == 1) {
547 val = V_WIN1_ALPHA_EN(alpha_en) |
548 V_WIN1_ALPHA_MODE(ppixel_alpha) |
549 V_WIN1_ALPHA_PRE_MUL(ppixel_alpha) |
550 V_WIN1_ALPHA_SAT_MODE(0);
551 vop_msk_reg(vop_dev, WIN1_ALPHA_CTRL, val);
553 dev_err(vop_dev->dev, "%s: invalid win id=%d or unsupport\n",
560 static int vop_axi_gather_cfg(struct vop_device *vop_dev,
561 struct rk_lcdc_win *win)
564 u16 yrgb_gather_num = 3;
565 u16 cbcr_gather_num = 1;
567 switch (win->area[0].format) {
591 dev_err(vop_dev->driver.dev, "%s:un supported format[%d]\n",
592 __func__, win->area[0].format);
597 val = V_WIN0_YRGB_AXI_GATHER_EN(1) |
598 V_WIN0_CBR_AXI_GATHER_EN(1) |
599 V_WIN0_YRGB_AXI_GATHER_NUM(yrgb_gather_num) |
600 V_WIN0_CBR_AXI_GATHER_NUM(cbcr_gather_num);
601 vop_msk_reg(vop_dev, WIN0_CTRL1, val);
602 } else if (win->id == 1) {
603 val = V_WIN1_AXI_GATHER_EN(1) |
604 V_WIN1_AXI_GATHER_NUM(yrgb_gather_num);
605 vop_msk_reg(vop_dev, WIN1_CTRL1, val);
610 static int vop_win0_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
612 struct vop_device *vop_dev = to_vop_dev(dev_drv);
613 struct rk_lcdc_win *win = dev_drv->win[win_id];
616 if (win->state == 1) {
617 vop_axi_gather_cfg(vop_dev, win);
618 val = V_WIN0_EN(win->state) |
619 V_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
620 V_WIN0_RB_SWAP(win->area[0].swap_rb) |
621 V_WIN0_UV_SWAP(win->area[0].swap_uv);
622 if (dev_drv->cur_screen->mode.vmode & FB_VMODE_INTERLACED)
623 val |= V_WIN0_INTERLACE_READ(1);
625 val |= V_WIN0_INTERLACE_READ(0);
626 vop_msk_reg(vop_dev, WIN0_CTRL0, val);
628 val = V_WIN0_YRGB_VIR_STRIDE(win->area[0].y_vir_stride) |
629 V_WIN0_CBR_VIR_STRIDE(win->area[0].uv_vir_stride);
630 vop_writel(vop_dev, WIN0_VIR, val);
632 val = V_WIN0_DSP_WIDTH(win->area[0].xsize - 1) |
633 V_WIN0_DSP_HEIGHT(win->area[0].ysize - 1);
634 vop_writel(vop_dev, WIN0_DSP_INFO, val);
636 val = V_WIN0_DSP_XST(win->area[0].dsp_stx) |
637 V_WIN0_DSP_YST(win->area[0].dsp_sty);
638 vop_writel(vop_dev, WIN0_DSP_ST, val);
640 /* only win0 support scale and yuv */
641 val = V_WIN0_ACT_WIDTH(win->area[0].xact - 1) |
642 V_WIN0_ACT_HEIGHT(win->area[0].yact - 1);
643 vop_writel(vop_dev, WIN0_ACT_INFO, val);
645 val = V_WIN0_HS_FACTOR_YRGB(win->scale_yrgb_x) |
646 V_WIN0_VS_FACTOR_YRGB(win->scale_yrgb_y);
647 vop_writel(vop_dev, WIN0_SCL_FACTOR_YRGB, val);
649 val = V_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) |
650 V_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y);
651 vop_writel(vop_dev, WIN0_SCL_FACTOR_CBR, val);
653 if (win->area[0].y_addr > 0)
654 vop_writel(vop_dev, WIN0_YRGB_MST, win->area[0].y_addr);
655 if (win->area[0].uv_addr > 0)
656 vop_writel(vop_dev, WIN0_CBR_MST, win->area[0].uv_addr);
658 vop_alpha_cfg(dev_drv, win_id);
660 val = V_WIN0_EN(win->state);
661 vop_msk_reg(vop_dev, WIN0_CTRL0, val);
667 static int vop_win1_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
669 struct vop_device *vop_dev = to_vop_dev(dev_drv);
670 struct rk_lcdc_win *win = dev_drv->win[win_id];
673 if (win->state == 1) {
674 vop_axi_gather_cfg(vop_dev, win);
675 val = V_WIN1_EN(win->state) |
676 V_WIN1_DATA_FMT(win->area[0].fmt_cfg) |
677 V_WIN1_RB_SWAP(win->area[0].swap_rb);
678 if (dev_drv->cur_screen->mode.vmode & FB_VMODE_INTERLACED)
679 val |= V_WIN1_INTERLACE_READ(1);
680 vop_msk_reg(vop_dev, WIN1_CTRL0, val);
682 val = V_WIN1_VIR_STRIDE(win->area[0].y_vir_stride);
683 vop_writel(vop_dev, WIN1_VIR, val);
685 val = V_WIN1_DSP_WIDTH(win->area[0].xsize - 1) |
686 V_WIN1_DSP_HEIGHT(win->area[0].ysize - 1);
687 vop_writel(vop_dev, WIN1_DSP_INFO, val);
689 val = V_WIN1_DSP_XST(win->area[0].dsp_stx) |
690 V_WIN1_DSP_YST(win->area[0].dsp_sty);
691 vop_writel(vop_dev, WIN1_DSP_ST, val);
693 if (win->area[0].y_addr > 0)
694 vop_writel(vop_dev, WIN1_YRGB_MST, win->area[0].y_addr);
696 vop_alpha_cfg(dev_drv, win_id);
698 val = V_WIN1_EN(win->state);
699 vop_msk_reg(vop_dev, WIN1_CTRL0, val);
705 static int vop_hwc_reg_update(struct rk_lcdc_driver *dev_drv, int win_id)
707 struct vop_device *vop_dev = to_vop_dev(dev_drv);
708 struct rk_lcdc_win *win = dev_drv->win[win_id];
709 unsigned int hwc_size = 0;
712 if (win->state == 1) {
713 vop_axi_gather_cfg(vop_dev, win);
715 if ((win->area[0].xsize == 32) && (win->area[0].ysize == 32))
717 else if ((win->area[0].xsize == 64) &&
718 (win->area[0].ysize == 64))
721 dev_err(vop_dev->dev, "unsupported hwc size[%dx%d]!\n",
722 win->area[0].xsize, win->area[0].ysize);
724 val = V_HWC_EN(1) | V_HWC_SIZE(hwc_size);
725 vop_msk_reg(vop_dev, HWC_CTRL0, val);
727 val = V_HWC_DSP_XST(win->area[0].dsp_stx) |
728 V_HWC_DSP_YST(win->area[0].dsp_sty);
729 vop_msk_reg(vop_dev, HWC_DSP_ST, val);
731 if (win->area[0].y_addr > 0)
732 vop_writel(vop_dev, HWC_MST, win->area[0].y_addr);
734 val = V_HWC_EN(win->state);
735 vop_msk_reg(vop_dev, HWC_CTRL0, val);
741 static int vop_layer_update_regs(struct vop_device *vop_dev,
742 struct rk_lcdc_win *win)
744 struct rk_lcdc_driver *dev_drv = &vop_dev->driver;
746 vop_msk_reg(vop_dev, SYS_CTRL2,
747 V_IMD_VOP_STANDBY_EN(vop_dev->standby));
749 vop_win0_reg_update(dev_drv, win->id);
750 else if (win->id == 1)
751 vop_win1_reg_update(dev_drv, win->id);
752 else if (win->id == 2)
753 vop_hwc_reg_update(dev_drv, win->id);
754 vop_cfg_done(vop_dev);
756 DBG(2, "%s for vop%d\n", __func__, vop_dev->id);
760 static int vop_set_hwc_lut(struct rk_lcdc_driver *dev_drv,
761 int *hwc_lut, int mode)
766 int len = 256 * sizeof(u32);
767 struct vop_device *vop_dev = to_vop_dev(dev_drv);
769 if (!dev_drv->hwc_lut)
770 dev_drv->hwc_lut = devm_kzalloc(vop_dev->dev, len, GFP_KERNEL);
772 spin_lock(&vop_dev->reg_lock);
773 if (likely(vop_dev->clk_on)) {
774 vop_msk_reg(vop_dev, HWC_CTRL0, V_HWC_LUT_EN(0));
775 vop_cfg_done(vop_dev);
777 for (i = 0; i < 256; i++) {
779 dev_drv->hwc_lut[i] = hwc_lut[i];
781 v = dev_drv->hwc_lut[i];
782 c = vop_dev->hwc_lut_addr_base + (i << 2);
783 writel_relaxed(v, c);
785 vop_msk_reg(vop_dev, HWC_CTRL0, V_HWC_LUT_EN(1));
786 vop_cfg_done(vop_dev);
788 spin_unlock(&vop_dev->reg_lock);
793 static int vop_set_lut(struct rk_lcdc_driver *dev_drv, int *dsp_lut)
798 struct vop_device *vop_dev = to_vop_dev(dev_drv);
803 spin_lock(&vop_dev->reg_lock);
804 if (likely(vop_dev->clk_on)) {
805 vop_msk_reg(vop_dev, DSP_CTRL2, V_DSP_LUT_EN(0));
806 vop_cfg_done(vop_dev);
808 for (i = 0; i < 256; i++) {
810 c = vop_dev->dsp_lut_addr_base + (i << 2);
811 writel_relaxed(v, c);
813 vop_msk_reg(vop_dev, DSP_CTRL2, V_DSP_LUT_EN(1));
814 vop_cfg_done(vop_dev);
816 spin_unlock(&vop_dev->reg_lock);
821 static int vop_set_dclk(struct rk_lcdc_driver *dev_drv, int reset_rate)
823 int ret = 0, fps = 0;
824 struct vop_device *vop_dev = to_vop_dev(dev_drv);
825 struct rk_screen *screen = dev_drv->cur_screen;
828 ret = clk_set_rate(vop_dev->dclk, screen->mode.pixclock);
830 dev_err(dev_drv->dev, "set lcdc%d dclk[%d] failed\n",
831 vop_dev->id, screen->mode.pixclock);
833 div_u64(1000000000000llu, clk_get_rate(vop_dev->dclk));
834 vop_dev->driver.pixclock = vop_dev->pixclock;
836 fps = rk_fb_calc_fps(screen, vop_dev->pixclock);
837 screen->ft = 1000 / fps;
838 dev_info(vop_dev->dev, "%s: dclk:%lu>>fps:%d ",
839 vop_dev->driver.name, clk_get_rate(vop_dev->dclk), fps);
843 static int vop_config_timing(struct rk_lcdc_driver *dev_drv)
845 struct vop_device *vop_dev = to_vop_dev(dev_drv);
846 struct rk_screen *screen = dev_drv->cur_screen;
847 u16 hsync_len = screen->mode.hsync_len;
848 u16 left_margin = screen->mode.left_margin;
849 u16 right_margin = screen->mode.right_margin;
850 u16 vsync_len = screen->mode.vsync_len;
851 u16 upper_margin = screen->mode.upper_margin;
852 u16 lower_margin = screen->mode.lower_margin;
853 u16 x_res = screen->mode.xres;
854 u16 y_res = screen->mode.yres;
856 u16 h_total, v_total;
857 u16 vact_end_f1, vact_st_f1, vs_end_f1, vs_st_f1;
859 /* config timing reg valid immediately or after frame start */
860 if (screen->mode.vmode & FB_VMODE_INTERLACED) /* after frame start */
861 vop_msk_reg(vop_dev, SYS_CTRL2, V_IMD_DSP_TIMING_IMD(1));
862 else /* timing reg valid immediately */
863 vop_msk_reg(vop_dev, SYS_CTRL2, V_IMD_DSP_TIMING_IMD(0));
865 h_total = hsync_len + left_margin + x_res + right_margin;
866 v_total = vsync_len + upper_margin + y_res + lower_margin;
868 val = V_DSP_HS_END(hsync_len) | V_DSP_HTOTAL(h_total);
869 vop_msk_reg(vop_dev, DSP_HTOTAL_HS_END, val);
871 val = V_DSP_HACT_END(hsync_len + left_margin + x_res) |
872 V_DSP_HACT_ST(hsync_len + left_margin);
873 vop_msk_reg(vop_dev, DSP_HACT_ST_END, val);
875 if (screen->mode.vmode & FB_VMODE_INTERLACED) {
876 /* First Field Timing */
877 val = V_DSP_VS_END(vsync_len) |
878 V_DSP_VTOTAL(2 * (vsync_len + upper_margin +
879 lower_margin) + y_res + 1);
880 vop_msk_reg(vop_dev, DSP_VTOTAL_VS_END, val);
882 val = V_DSP_VACT_END(vsync_len + upper_margin + y_res / 2) |
883 V_DSP_VACT_ST(vsync_len + upper_margin);
884 vop_msk_reg(vop_dev, DSP_VACT_ST_END, val);
886 /* Second Field Timing */
887 vs_st_f1 = vsync_len + upper_margin + y_res / 2 + lower_margin;
888 vs_end_f1 = 2 * vsync_len + upper_margin + y_res / 2 +
890 val = V_DSP_VS_ST_F1(vs_st_f1) | V_DSP_VS_END_F1(vs_end_f1);
891 vop_msk_reg(vop_dev, DSP_VS_ST_END_F1, val);
893 vact_end_f1 = 2 * (vsync_len + upper_margin) + y_res +
895 vact_st_f1 = 2 * (vsync_len + upper_margin) + y_res / 2 +
897 val = V_DSP_VACT_END_F1(vact_end_f1) |
898 V_DSP_VACT_ST_F1(vact_st_f1);
899 vop_msk_reg(vop_dev, DSP_VACT_ST_END_F1, val);
901 val = V_DSP_LINE_FLAG0_NUM(lower_margin ?
902 vact_end_f1 : vact_end_f1 - 1);
904 val |= V_DSP_LINE_FLAG1_NUM(lower_margin ?
905 vact_end_f1 : vact_end_f1 - 1);
906 vop_msk_reg(vop_dev, LINE_FLAG, val);
908 val = V_DSP_VS_END(vsync_len) | V_DSP_VTOTAL(v_total);
909 vop_msk_reg(vop_dev, DSP_VTOTAL_VS_END, val);
911 val = V_DSP_VACT_END(vsync_len + upper_margin + y_res) |
912 V_DSP_VACT_ST(vsync_len + upper_margin);
913 vop_msk_reg(vop_dev, DSP_VACT_ST_END, val);
915 val = V_DSP_LINE_FLAG0_NUM(vsync_len + upper_margin + y_res) |
916 V_DSP_LINE_FLAG1_NUM(vsync_len + upper_margin + y_res);
917 vop_msk_reg(vop_dev, LINE_FLAG, val);
923 static int vop_config_source(struct rk_lcdc_driver *dev_drv)
925 struct vop_device *vop_dev = to_vop_dev(dev_drv);
926 struct rk_screen *screen = dev_drv->cur_screen;
929 switch (screen->type) {
931 vop_grf_writel(vop_dev->grf_base, GRF_SOC_CON5,
932 V_RGB_VOP_SEL(dev_drv->id));
933 val = V_RGB_DCLK_EN(1) | V_RGB_DCLK_POL(screen->pin_dclk) |
934 V_RGB_HSYNC_POL(screen->pin_hsync) |
935 V_RGB_VSYNC_POL(screen->pin_vsync) |
936 V_RGB_DEN_POL(screen->pin_den);
939 vop_grf_writel(vop_dev->grf_base, GRF_SOC_CON0,
940 V_HDMI_VOP_SEL(dev_drv->id));
941 val = V_HDMI_DCLK_EN(1) | V_HDMI_DCLK_POL(screen->pin_dclk) |
942 V_HDMI_HSYNC_POL(screen->pin_hsync) |
943 V_HDMI_VSYNC_POL(screen->pin_vsync) |
944 V_HDMI_DEN_POL(screen->pin_den);
947 vop_grf_writel(vop_dev->grf_base, GRF_SOC_CON0,
948 V_LVDS_VOP_SEL(dev_drv->id));
949 val = V_LVDS_DCLK_EN(1) | V_LVDS_DCLK_POL(screen->pin_dclk) |
950 V_LVDS_HSYNC_POL(screen->pin_hsync) |
951 V_LVDS_VSYNC_POL(screen->pin_vsync) |
952 V_LVDS_DEN_POL(screen->pin_den);
955 vop_grf_writel(vop_dev->grf_base, GRF_SOC_CON0,
956 V_DSI0_VOP_SEL(dev_drv->id));
957 val = V_MIPI_DCLK_EN(1) | V_MIPI_DCLK_POL(screen->pin_dclk) |
958 V_MIPI_HSYNC_POL(screen->pin_hsync) |
959 V_MIPI_VSYNC_POL(screen->pin_vsync) |
960 V_MIPI_DEN_POL(screen->pin_den);
963 dev_err(vop_dev->dev, "un supported interface[%d]!\n",
968 val |= V_SW_CORE_CLK_SEL(!!screen->pixelrepeat);
969 if (screen->mode.vmode & FB_VMODE_INTERLACED)
970 val |= V_SW_HDMI_CLK_I_SEL(1);
972 val |= V_SW_HDMI_CLK_I_SEL(0);
973 vop_msk_reg(vop_dev, DSP_CTRL0, val);
978 static int vop_config_interface(struct rk_lcdc_driver *dev_drv)
980 struct vop_device *vop_dev = to_vop_dev(dev_drv);
981 struct rk_screen *screen = dev_drv->cur_screen;
984 /* FRC dither down init */
985 if (screen->face != OUT_P888) {
986 vop_writel(vop_dev, FRC_LOWER01_0, 0x12844821);
987 vop_writel(vop_dev, FRC_LOWER01_1, 0x21488412);
988 vop_writel(vop_dev, FRC_LOWER10_0, 0xa55a9696);
989 vop_writel(vop_dev, FRC_LOWER10_1, 0x5aa56969);
990 vop_writel(vop_dev, FRC_LOWER11_0, 0xdeb77deb);
991 vop_writel(vop_dev, FRC_LOWER11_1, 0xed7bb7de);
994 switch (screen->face) {
996 val = V_DSP_OUT_MODE(OUT_P888) | V_DITHER_DOWN(0);
999 val = V_DSP_OUT_MODE(OUT_P565) | V_DITHER_DOWN(1) |
1000 V_DITHER_DOWN_MODE(DITHER_888_565) |
1001 V_DITHER_DOWN_SEL(DITHER_SEL_FRC);
1004 val = V_DSP_OUT_MODE(OUT_P666) | V_DITHER_DOWN(1) |
1005 V_DITHER_DOWN_MODE(DITHER_888_666) |
1006 V_DITHER_DOWN_SEL(DITHER_SEL_FRC);
1009 val = V_DSP_OUT_MODE(OUT_P888) | V_DITHER_DOWN(1) |
1010 V_DITHER_DOWN_MODE(DITHER_888_565) |
1011 V_DITHER_DOWN_SEL(DITHER_SEL_FRC);
1014 val = V_DSP_OUT_MODE(OUT_P888) | V_DITHER_DOWN(1) |
1015 V_DITHER_DOWN_MODE(DITHER_888_666) |
1016 V_DITHER_DOWN_SEL(DITHER_SEL_FRC);
1019 dev_err(vop_dev->dev, "un supported screen face[%d]!\n",
1024 if (screen->mode.vmode & FB_VMODE_INTERLACED)
1025 val |= V_DSP_INTERLACE(1) | V_INTERLACE_FIELD_POL(0);
1027 val |= V_DSP_INTERLACE(0) | V_INTERLACE_FIELD_POL(0);
1029 dev_drv->output_color = screen->color_mode;
1030 if (screen->color_mode == COLOR_RGB)
1031 dev_drv->overlay_mode = VOP_RGB_DOMAIN;
1033 dev_drv->overlay_mode = VOP_YUV_DOMAIN;
1035 val |= V_SW_OVERLAY_MODE(dev_drv->overlay_mode) |
1036 V_DSP_BG_SWAP(screen->swap_gb) |
1037 V_DSP_RB_SWAP(screen->swap_rb) |
1038 V_DSP_RG_SWAP(screen->swap_rg) |
1039 V_DSP_DELTA_SWAP(screen->swap_delta) |
1040 V_DSP_DUMMY_SWAP(screen->swap_dumy) |
1041 V_DSP_BLANK_EN(0) | V_DSP_BLACK_EN(0);
1042 vop_msk_reg(vop_dev, DSP_CTRL2, val);
1047 static void vop_config_background(struct rk_lcdc_driver *dev_drv, int rgb)
1049 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1052 int g = (rgb >> 8) & 0xff;
1053 int r = (rgb >> 16) & 0xff;
1055 val = V_DSP_BG_BLUE(b) | V_DSP_BG_GREEN(g) | V_DSP_BG_RED(r);
1056 vop_msk_reg(vop_dev, DSP_BG, val);
1059 static void vop_bcsh_path_sel(struct rk_lcdc_driver *dev_drv)
1061 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1063 if (dev_drv->overlay_mode == VOP_YUV_DOMAIN) {
1064 if (IS_YUV_COLOR(dev_drv->output_color)) /* bypass */
1065 vop_msk_reg(vop_dev, BCSH_CTRL,
1066 V_SW_BCSH_Y2R_EN(0) | V_SW_BCSH_R2Y_EN(0));
1068 vop_msk_reg(vop_dev, BCSH_CTRL, V_SW_BCSH_Y2R_EN(1) |
1069 V_SW_BCSH_Y2R_CSC_MODE(VOP_Y2R_CSC_MPEG) |
1070 V_SW_BCSH_R2Y_EN(0));
1072 /* overlay_mode=VOP_RGB_DOMAIN */
1073 /* bypass --need check,if bcsh close? */
1074 if (dev_drv->output_color == COLOR_RGB) {
1075 if (dev_drv->bcsh.enable == 1)
1076 vop_msk_reg(vop_dev, BCSH_CTRL,
1077 V_SW_BCSH_R2Y_EN(1) |
1078 V_SW_BCSH_Y2R_EN(1));
1080 vop_msk_reg(vop_dev, BCSH_CTRL,
1081 V_SW_BCSH_R2Y_EN(0) |
1082 V_SW_BCSH_Y2R_EN(0));
1085 vop_msk_reg(vop_dev, BCSH_CTRL,
1086 V_SW_BCSH_R2Y_EN(1) |
1087 V_SW_BCSH_R2Y_CSC_MODE(VOP_Y2R_CSC_MPEG) |
1088 V_SW_BCSH_Y2R_EN(0));
1093 static int vop_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
1094 u16 *yact, int *format, u32 *dsp_addr,
1097 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1100 spin_lock(&vop_dev->reg_lock);
1101 if (likely(vop_dev->clk_on)) {
1102 val = vop_readl(vop_dev, WIN0_ACT_INFO);
1103 *xact = (val & MASK(WIN0_ACT_WIDTH)) + 1;
1104 *yact = ((val & MASK(WIN0_ACT_HEIGHT)) >> 16) + 1;
1106 val = vop_readl(vop_dev, WIN0_CTRL0);
1107 *format = (val & MASK(WIN0_DATA_FMT)) >> 1;
1108 *dsp_addr = vop_readl(vop_dev, WIN0_YRGB_MST);
1110 spin_unlock(&vop_dev->reg_lock);
1115 static int vop_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
1116 int format, u16 xact, u16 yact, u16 xvir,
1119 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1120 int swap = (format == RGB888) ? 1 : 0;
1123 spin_lock(&vop_dev->reg_lock);
1124 if (likely(vop_dev->clk_on)) {
1125 val = V_WIN0_DATA_FMT(format) | V_WIN0_RB_SWAP(swap);
1126 vop_msk_reg(vop_dev, WIN0_CTRL0, val);
1128 vop_msk_reg(vop_dev, WIN0_VIR, V_WIN0_YRGB_VIR_STRIDE(xvir));
1129 vop_writel(vop_dev, WIN0_ACT_INFO, V_WIN0_ACT_WIDTH(xact - 1) |
1130 V_WIN0_ACT_HEIGHT(yact - 1));
1132 vop_writel(vop_dev, WIN0_YRGB_MST, rgb_mst);
1134 vop_cfg_done(vop_dev);
1136 spin_unlock(&vop_dev->reg_lock);
1141 static void vop_reg_restore(struct rk_lcdc_driver *dev_drv)
1143 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1146 spin_lock(&vop_dev->reg_lock);
1148 if (likely(vop_dev->clk_on))
1149 memcpy(vop_dev->regs, vop_dev->regsbak, len);
1151 spin_unlock(&vop_dev->reg_lock);
1153 /* set screen GAMMA lut */
1154 if (dev_drv->cur_screen && dev_drv->cur_screen->dsp_lut)
1155 vop_set_lut(dev_drv, dev_drv->cur_screen->dsp_lut);
1158 vop_set_hwc_lut(dev_drv, dev_drv->hwc_lut, 0);
1161 static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
1163 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1164 struct rk_screen *screen = dev_drv->cur_screen;
1166 /*if (!vop_dev->standby && initscreen && (dev_drv->first_frame != 1))*/
1167 /* flush_kthread_worker(&dev_drv->update_regs_worker);*/
1169 spin_lock(&vop_dev->reg_lock);
1170 if (likely(vop_dev->clk_on)) {
1171 vop_config_interface(dev_drv);
1172 vop_config_source(dev_drv);
1173 vop_config_timing(dev_drv);
1174 if (dev_drv->overlay_mode == VOP_YUV_DOMAIN)
1175 vop_config_background(dev_drv, 0x801080);
1177 vop_config_background(dev_drv, 0x000000);
1179 vop_bcsh_path_sel(dev_drv);
1180 vop_cfg_done(vop_dev);
1182 spin_unlock(&vop_dev->reg_lock);
1184 vop_set_dclk(dev_drv, 1);
1192 * enable or disable layer according to win id
1193 * @open: 1 enable; 0 disable
1195 static void vop_layer_enable(struct vop_device *vop_dev,
1196 unsigned int win_id, bool open)
1198 spin_lock(&vop_dev->reg_lock);
1199 if (likely(vop_dev->clk_on) &&
1200 vop_dev->driver.win[win_id]->state != open) {
1202 if (!vop_dev->atv_layer_cnt) {
1203 dev_info(vop_dev->dev,
1204 "wakeup from standby!\n");
1205 vop_dev->standby = 0;
1207 vop_dev->atv_layer_cnt |= (1 << win_id);
1209 if (vop_dev->atv_layer_cnt & (1 << win_id))
1210 vop_dev->atv_layer_cnt &= ~(1 << win_id);
1212 vop_dev->driver.win[win_id]->state = open;
1214 vop_layer_update_regs(vop_dev,
1215 vop_dev->driver.win[win_id]);
1216 vop_cfg_done(vop_dev);
1218 /* if no layer used,disable lcdc */
1219 if (!vop_dev->atv_layer_cnt) {
1220 dev_info(vop_dev->dev,
1221 "no layer is used,go to standby!\n");
1222 vop_dev->standby = 1;
1225 spin_unlock(&vop_dev->reg_lock);
1228 static int vop_open(struct rk_lcdc_driver *dev_drv, int win_id,
1231 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1233 /* enable clk,when first layer open */
1234 if ((open) && (!vop_dev->atv_layer_cnt)) {
1235 /* rockchip_set_system_status(sys_status); */
1236 vop_pre_init(dev_drv);
1237 vop_clk_enable(vop_dev);
1238 vop_irq_enable(vop_dev);
1240 if (support_uboot_display() && (vop_dev->prop == PRMRY)) {
1241 vop_set_dclk(dev_drv, 0);
1243 vop_load_screen(dev_drv, 1);
1244 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
1245 dev_drv->trsm_ops->enable();
1247 if (dev_drv->bcsh.enable)
1248 vop_set_bcsh(dev_drv, 1);
1250 /* set screen GAMMA lut */
1251 if (dev_drv->cur_screen && dev_drv->cur_screen->dsp_lut)
1252 vop_set_lut(dev_drv, dev_drv->cur_screen->dsp_lut);
1255 if (win_id < ARRAY_SIZE(vop_win))
1256 vop_layer_enable(vop_dev, win_id, open);
1258 dev_err(vop_dev->dev, "invalid win id:%d\n", win_id);
1260 dev_drv->first_frame = 0;
1264 static int vop_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
1266 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1267 struct rk_lcdc_win *win = NULL;
1268 struct rk_screen *screen = dev_drv->cur_screen;
1271 dev_err(dev_drv->dev, "screen is null!\n");
1275 if (win_id >= dev_drv->lcdc_win_num) {
1276 dev_err(dev_drv->dev, "invalid win id:%d!\n", win_id);
1280 win = dev_drv->win[win_id];
1281 win->area[0].y_addr = win->area[0].smem_start + win->area[0].y_offset;
1282 /* only win0 support yuv format */
1284 win->area[0].uv_addr =
1285 win->area[0].cbr_start + win->area[0].c_offset;
1287 win->area[0].uv_addr = 0;
1289 DBG(2, "lcdc[%d]:win[%d]>>:y_addr:0x%x>>uv_addr:0x%x",
1290 vop_dev->id, win->id, win->area[0].y_addr, win->area[0].uv_addr);
1291 DBG(2, ">>y_offset:0x%x>>c_offset=0x%x\n",
1292 win->area[0].y_offset, win->area[0].c_offset);
1296 static int win_0_1_set_par(struct vop_device *vop_dev,
1297 struct rk_screen *screen, struct rk_lcdc_win *win)
1299 char fmt[9] = "NULL";
1301 win->area[0].dsp_stx = win->area[0].xpos + screen->mode.left_margin +
1302 screen->mode.hsync_len;
1303 if (screen->mode.vmode & FB_VMODE_INTERLACED) {
1304 win->area[0].ysize /= 2;
1305 win->area[0].dsp_sty = win->area[0].ypos / 2 +
1306 screen->mode.upper_margin + screen->mode.vsync_len;
1308 win->area[0].dsp_sty = win->area[0].ypos +
1309 screen->mode.upper_margin + screen->mode.vsync_len;
1312 win->scale_yrgb_x = CALSCALE(win->area[0].xact, win->area[0].xsize);
1313 win->scale_yrgb_y = CALSCALE(win->area[0].yact, win->area[0].ysize);
1315 switch (win->area[0].format) {
1317 win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
1318 win->area[0].swap_rb = 0;
1322 win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
1323 win->area[0].swap_rb = 1;
1326 win->area[0].fmt_cfg = VOP_FORMAT_RGB888;
1327 win->area[0].swap_rb = 0;
1330 win->area[0].fmt_cfg = VOP_FORMAT_RGB565;
1331 win->area[0].swap_rb = 0;
1334 win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
1335 win->area[0].swap_rb = 0;
1338 win->area[0].fmt_cfg = VOP_FORMAT_RGB888;
1339 win->area[0].swap_rb = 1;
1342 win->area[0].fmt_cfg = VOP_FORMAT_RGB565;
1343 win->area[0].swap_rb = 1;
1347 win->area[0].fmt_cfg = VOP_FORMAT_YCBCR422;
1348 win->area[0].swap_rb = 0;
1349 win->area[0].swap_uv = 0;
1350 win->scale_cbcr_x = CALSCALE(win->area[0].xact / 2,
1351 win->area[0].xsize);
1352 win->scale_cbcr_y = CALSCALE(win->area[0].yact,
1353 win->area[0].ysize);
1355 dev_err(vop_dev->dev, "%s:win%d unsupport YUV format\n",
1361 win->area[0].fmt_cfg = VOP_FORMAT_YCBCR420;
1362 win->area[0].swap_rb = 0;
1363 win->area[0].swap_uv = 0;
1364 win->scale_cbcr_x = CALSCALE(win->area[0].xact / 2,
1365 win->area[0].xsize);
1366 win->scale_cbcr_y = CALSCALE(win->area[0].yact / 2,
1367 win->area[0].ysize);
1369 dev_err(vop_dev->dev, "%s:win%d unsupport YUV format\n",
1376 win->area[0].fmt_cfg = VOP_FORMAT_YCBCR420;
1377 win->area[0].swap_rb = 0;
1378 win->area[0].swap_uv = 1;
1379 win->scale_cbcr_x = CALSCALE(win->area[0].xact / 2,
1380 win->area[0].xsize);
1381 win->scale_cbcr_y = CALSCALE(win->area[0].yact / 2,
1382 win->area[0].ysize);
1384 dev_err(vop_dev->dev, "%s:win%d unsupport YUV format\n",
1390 win->area[0].fmt_cfg = VOP_FORMAT_YCBCR444;
1391 win->area[0].swap_rb = 0;
1392 win->area[0].swap_uv = 0;
1394 CALSCALE(win->area[0].xact, win->area[0].xsize);
1396 CALSCALE(win->area[0].yact, win->area[0].ysize);
1398 dev_err(vop_dev->dev, "%s:win%d unsupport YUV format\n",
1403 dev_err(vop_dev->dev, "%s:unsupport format[%d]!\n",
1404 __func__, win->area[0].format);
1408 DBG(1, "lcdc[%d]:win[%d]\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d",
1409 vop_dev->id, win->id, get_format_string(win->area[0].format, fmt),
1410 win->area[0].xact, win->area[0].yact, win->area[0].xsize);
1411 DBG(1, ">>ysize:%d>>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n",
1412 win->area[0].ysize, win->area[0].xvir, win->area[0].yvir,
1413 win->area[0].xpos, win->area[0].ypos);
1418 static int hwc_set_par(struct vop_device *vop_dev,
1419 struct rk_screen *screen, struct rk_lcdc_win *win)
1421 win->area[0].dsp_stx = win->area[0].xpos + screen->mode.left_margin +
1422 screen->mode.hsync_len;
1423 win->area[0].dsp_sty = win->area[0].ypos + screen->mode.upper_margin +
1424 screen->mode.vsync_len;
1426 DBG(1, "lcdc[%d]:hwc>>%s\n>>xsize:%d>>ysize:%d>>xpos:%d>>ypos:%d",
1427 vop_dev->id, __func__, win->area[0].xsize, win->area[0].ysize,
1428 win->area[0].xpos, win->area[0].ypos);
1432 static int vop_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
1434 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1435 struct rk_screen *screen = dev_drv->cur_screen;
1438 dev_err(dev_drv->dev, "screen is null!\n");
1444 win_0_1_set_par(vop_dev, screen, dev_drv->win[0]);
1447 win_0_1_set_par(vop_dev, screen, dev_drv->win[1]);
1450 hwc_set_par(vop_dev, screen, dev_drv->win[2]);
1453 dev_err(dev_drv->dev, "%s: unsupported win id:%d\n",
1460 static int vop_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
1461 unsigned long arg, int win_id)
1463 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1465 void __user *argp = (void __user *)arg;
1466 struct color_key_cfg clr_key_cfg;
1469 case RK_FBIOGET_PANEL_SIZE:
1470 panel_size[0] = vop_dev->screen->mode.xres;
1471 panel_size[1] = vop_dev->screen->mode.yres;
1472 if (copy_to_user(argp, panel_size, 8))
1475 case RK_FBIOPUT_COLOR_KEY_CFG:
1476 if (copy_from_user(&clr_key_cfg, argp,
1477 sizeof(struct color_key_cfg)))
1479 vop_clr_key_cfg(dev_drv);
1480 vop_writel(vop_dev, WIN0_COLOR_KEY,
1481 clr_key_cfg.win0_color_key_cfg);
1482 vop_writel(vop_dev, WIN1_COLOR_KEY,
1483 clr_key_cfg.win1_color_key_cfg);
1492 static int vop_get_backlight_device(struct rk_lcdc_driver *dev_drv)
1494 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1495 struct device_node *backlight;
1496 struct property *prop;
1497 u32 *brightness_levels;
1498 u32 length, max, last;
1500 if (vop_dev->backlight)
1502 backlight = of_parse_phandle(vop_dev->dev->of_node, "backlight", 0);
1504 vop_dev->backlight = of_find_backlight_by_node(backlight);
1505 if (!vop_dev->backlight)
1506 dev_info(vop_dev->dev, "No find backlight device\n");
1508 dev_info(vop_dev->dev, "No find backlight device node\n");
1510 prop = of_find_property(backlight, "brightness-levels", &length);
1513 max = length / sizeof(u32);
1515 brightness_levels = kmalloc(256, GFP_KERNEL);
1516 if (brightness_levels)
1519 if (!of_property_read_u32_array(backlight, "brightness-levels",
1520 brightness_levels, max)) {
1521 if (brightness_levels[0] > brightness_levels[last])
1522 dev_drv->cabc_pwm_pol = 1;/*negative*/
1524 dev_drv->cabc_pwm_pol = 0;/*positive*/
1526 dev_info(vop_dev->dev,
1527 "Can not read brightness-levels value\n");
1530 kfree(brightness_levels);
1535 static int vop_backlight_close(struct rk_lcdc_driver *dev_drv, int enable)
1537 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1539 if (dev_drv->suspend_flag)
1542 vop_get_backlight_device(dev_drv);
1545 /* close the backlight */
1546 if (vop_dev->backlight) {
1547 vop_dev->backlight->props.power = FB_BLANK_POWERDOWN;
1548 backlight_update_status(vop_dev->backlight);
1550 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
1551 dev_drv->trsm_ops->disable();
1553 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
1554 dev_drv->trsm_ops->enable();
1556 /* open the backlight */
1557 if (vop_dev->backlight) {
1558 vop_dev->backlight->props.power = FB_BLANK_UNBLANK;
1559 backlight_update_status(vop_dev->backlight);
1566 static int vop_early_suspend(struct rk_lcdc_driver *dev_drv)
1568 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1570 if (dev_drv->suspend_flag)
1573 dev_drv->suspend_flag = 1;
1575 flush_kthread_worker(&dev_drv->update_regs_worker);
1577 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
1578 dev_drv->trsm_ops->disable();
1580 vop_standby_enable(vop_dev);
1581 vop_mmu_disable(dev_drv);
1582 vop_clk_disable(vop_dev);
1583 rk_disp_pwr_disable(dev_drv);
1588 static int vop_early_resume(struct rk_lcdc_driver *dev_drv)
1590 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1592 if (!dev_drv->suspend_flag)
1595 rk_disp_pwr_enable(dev_drv);
1596 vop_clk_enable(vop_dev);
1597 vop_reg_restore(dev_drv);
1598 vop_standby_disable(vop_dev);
1599 vop_mmu_enable(dev_drv);
1600 dev_drv->suspend_flag = 0;
1602 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
1603 dev_drv->trsm_ops->enable();
1608 static int vop_blank(struct rk_lcdc_driver *dev_drv, int win_id, int blank_mode)
1610 switch (blank_mode) {
1611 case FB_BLANK_UNBLANK:
1612 vop_early_resume(dev_drv);
1614 case FB_BLANK_NORMAL:
1615 vop_early_suspend(dev_drv);
1618 vop_early_suspend(dev_drv);
1622 dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
1627 static int vop_get_win_state(struct rk_lcdc_driver *dev_drv,
1628 int win_id, int area_id)
1630 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1631 u32 area_status = 0, state = 0;
1633 spin_lock(&vop_dev->reg_lock);
1634 if (likely(vop_dev->clk_on)) {
1638 vop_read_bit(vop_dev, WIN0_CTRL0, V_WIN0_EN(0));
1642 vop_read_bit(vop_dev, WIN1_CTRL0, V_WIN1_EN(0));
1646 vop_read_bit(vop_dev, HWC_CTRL0, V_HWC_EN(0));
1649 pr_err("%s: win[%d]area[%d],unsupport!!!\n",
1650 __func__, win_id, area_id);
1654 spin_unlock(&vop_dev->reg_lock);
1656 state = (area_status > 0) ? 1 : 0;
1660 static int vop_get_area_num(struct rk_lcdc_driver *dev_drv,
1661 unsigned int *area_support)
1663 area_support[0] = 1;
1664 area_support[1] = 1;
1669 static int vop_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap, bool set)
1671 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1674 spin_lock(&vop_dev->reg_lock);
1675 if (likely(vop_dev->clk_on)) {
1677 vop_msk_reg(vop_dev, DSP_CTRL2, V_DSP_WIN0_TOP(swap));
1681 vop_read_bit(vop_dev, DSP_CTRL2, V_DSP_WIN0_TOP(0));
1686 spin_unlock(&vop_dev->reg_lock);
1691 static char *vop_format_to_string(int format, char *fmt)
1698 strcpy(fmt, "ARGB888");
1701 strcpy(fmt, "RGB888");
1704 strcpy(fmt, "RGB565");
1707 strcpy(fmt, "YCbCr420");
1710 strcpy(fmt, "YCbCr422");
1713 strcpy(fmt, "YCbCr444");
1716 strcpy(fmt, "invalid\n");
1722 static ssize_t vop_get_disp_info(struct rk_lcdc_driver *dev_drv,
1723 char *buf, int win_id)
1725 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1726 struct rk_screen *screen = dev_drv->cur_screen;
1727 u16 hsync_len = screen->mode.hsync_len;
1728 u16 left_margin = screen->mode.left_margin;
1729 u16 vsync_len = screen->mode.vsync_len;
1730 u16 upper_margin = screen->mode.upper_margin;
1731 u32 h_pw_bp = hsync_len + left_margin;
1732 u32 v_pw_bp = vsync_len + upper_margin;
1734 char format_w0[9] = "NULL";
1735 char format_w1[9] = "NULL";
1737 u32 win_ctrl, ovl, vir_info, act_info, dsp_info, dsp_st;
1738 u32 y_factor, uv_factor;
1739 u8 w0_state, w1_state;
1741 u32 w0_vir_y, w0_vir_uv, w0_act_x, w0_act_y, w0_dsp_x, w0_dsp_y;
1742 u32 w0_st_x = h_pw_bp, w0_st_y = v_pw_bp;
1743 u32 w1_vir_y, w1_dsp_x, w1_dsp_y;
1744 u32 w1_st_x = h_pw_bp, w1_st_y = v_pw_bp;
1745 u32 w0_y_h_fac, w0_y_v_fac, w0_uv_h_fac, w0_uv_v_fac;
1750 dclk_freq = screen->mode.pixclock;
1751 /*vop_reg_dump(dev_drv); */
1753 spin_lock(&vop_dev->reg_lock);
1754 if (likely(vop_dev->clk_on)) {
1755 ovl = vop_read_bit(vop_dev, DSP_CTRL2, V_DSP_WIN0_TOP(0));
1757 win_ctrl = vop_readl(vop_dev, WIN0_CTRL0);
1758 w0_state = win_ctrl & MASK(WIN0_EN);
1759 fmt_id = (win_ctrl & MASK(WIN0_DATA_FMT)) >> 1;
1760 vop_format_to_string(fmt_id, format_w0);
1761 vir_info = vop_readl(vop_dev, WIN0_VIR);
1762 act_info = vop_readl(vop_dev, WIN0_ACT_INFO);
1763 dsp_info = vop_readl(vop_dev, WIN0_DSP_INFO);
1764 dsp_st = vop_readl(vop_dev, WIN0_DSP_ST);
1765 y_factor = vop_readl(vop_dev, WIN0_SCL_FACTOR_YRGB);
1766 uv_factor = vop_readl(vop_dev, WIN0_SCL_FACTOR_CBR);
1767 w0_vir_y = vir_info & MASK(WIN0_YRGB_VIR_STRIDE);
1768 w0_vir_uv = (vir_info & MASK(WIN0_CBR_VIR_STRIDE)) >> 16;
1769 w0_act_x = (act_info & MASK(WIN0_ACT_WIDTH)) + 1;
1770 w0_act_y = ((act_info & MASK(WIN0_ACT_HEIGHT)) >> 16) + 1;
1771 w0_dsp_x = (dsp_info & MASK(WIN0_DSP_WIDTH)) + 1;
1772 w0_dsp_y = ((dsp_info & MASK(WIN0_DSP_HEIGHT)) >> 16) + 1;
1774 w0_st_x = dsp_st & MASK(WIN0_DSP_XST);
1775 w0_st_y = (dsp_st & MASK(WIN0_DSP_YST)) >> 16;
1777 w0_y_h_fac = y_factor & MASK(WIN0_HS_FACTOR_YRGB);
1778 w0_y_v_fac = (y_factor & MASK(WIN0_VS_FACTOR_YRGB)) >> 16;
1779 w0_uv_h_fac = uv_factor & MASK(WIN0_HS_FACTOR_CBR);
1780 w0_uv_v_fac = (uv_factor & MASK(WIN0_VS_FACTOR_CBR)) >> 16;
1783 win_ctrl = vop_readl(vop_dev, WIN1_CTRL0);
1784 w1_state = win_ctrl & MASK(WIN1_EN);
1785 fmt_id = (win_ctrl & MASK(WIN1_DATA_FMT)) >> 1;
1786 vop_format_to_string(fmt_id, format_w1);
1787 vir_info = vop_readl(vop_dev, WIN1_VIR);
1788 dsp_info = vop_readl(vop_dev, WIN1_DSP_INFO);
1789 dsp_st = vop_readl(vop_dev, WIN1_DSP_ST);
1790 w1_vir_y = vir_info & MASK(WIN1_VIR_STRIDE);
1791 w1_dsp_x = (dsp_info & MASK(WIN1_DSP_WIDTH)) + 1;
1792 w1_dsp_y = ((dsp_info & MASK(WIN1_DSP_HEIGHT)) >> 16) + 1;
1794 w1_st_x = dsp_st & MASK(WIN1_DSP_XST);
1795 w1_st_y = (dsp_st & MASK(WIN1_DSP_YST)) >> 16;
1798 spin_unlock(&vop_dev->reg_lock);
1801 spin_unlock(&vop_dev->reg_lock);
1803 size += snprintf(dsp_buf, 80,
1804 "win0:\n state:%d, fmt:%7s\n y_vir:%4d, uv_vir:%4d,",
1805 w0_state, format_w0, w0_vir_y, w0_vir_uv);
1806 strcat(buf, dsp_buf);
1807 memset(dsp_buf, 0, sizeof(dsp_buf));
1809 size += snprintf(dsp_buf, 80,
1810 " x_act :%5d, y_act :%5d, dsp_x :%5d, dsp_y :%5d\n",
1811 w0_act_x, w0_act_y, w0_dsp_x, w0_dsp_y);
1812 strcat(buf, dsp_buf);
1813 memset(dsp_buf, 0, sizeof(dsp_buf));
1815 size += snprintf(dsp_buf, 80,
1816 " x_st :%4d, y_st :%4d, y_h_fac:%5d, y_v_fac:%5d, ",
1817 w0_st_x - h_pw_bp, w0_st_y - v_pw_bp, w0_y_h_fac, w0_y_v_fac);
1818 strcat(buf, dsp_buf);
1819 memset(dsp_buf, 0, sizeof(dsp_buf));
1821 size += snprintf(dsp_buf, 80,
1822 "uv_h_fac:%5d, uv_v_fac:%5d\n y_addr:0x%08x, uv_addr:0x%08x\n",
1823 w0_uv_h_fac, w0_uv_v_fac, vop_readl(vop_dev, WIN0_YRGB_MST),
1824 vop_readl(vop_dev, WIN0_CBR_MST));
1825 strcat(buf, dsp_buf);
1826 memset(dsp_buf, 0, sizeof(dsp_buf));
1829 size += snprintf(dsp_buf, 80,
1830 "win1:\n state:%d, fmt:%7s\n y_vir:%4d,",
1831 w1_state, format_w1, w1_vir_y);
1832 strcat(buf, dsp_buf);
1833 memset(dsp_buf, 0, sizeof(dsp_buf));
1835 size += snprintf(dsp_buf, 80,
1836 " dsp_x :%5d, dsp_y :%5d\n",
1837 w1_dsp_x, w1_dsp_y);
1838 strcat(buf, dsp_buf);
1839 memset(dsp_buf, 0, sizeof(dsp_buf));
1841 size += snprintf(dsp_buf, 80,
1842 " x_st :%4d, y_st :%4d, ",
1843 w1_st_x - h_pw_bp, w1_st_y - v_pw_bp);
1844 strcat(buf, dsp_buf);
1845 memset(dsp_buf, 0, sizeof(dsp_buf));
1847 size += snprintf(dsp_buf, 80,
1849 vop_readl(vop_dev, WIN1_YRGB_MST));
1850 strcat(buf, dsp_buf);
1851 memset(dsp_buf, 0, sizeof(dsp_buf));
1854 size += snprintf(dsp_buf, 80,
1855 ovl ? "win0 on the top of win1\n" :
1856 "win1 on the top of win0\n");
1857 strcat(buf, dsp_buf);
1858 memset(dsp_buf, 0, sizeof(dsp_buf));
1863 static int vop_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps, bool set)
1865 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1866 struct rk_screen *screen = dev_drv->cur_screen;
1871 u32 x_total, y_total;
1875 dev_info(dev_drv->dev, "unsupport set fps=0\n");
1878 ft = div_u64(1000000000000llu, fps);
1880 screen->mode.upper_margin + screen->mode.lower_margin +
1881 screen->mode.yres + screen->mode.vsync_len;
1883 screen->mode.left_margin + screen->mode.right_margin +
1884 screen->mode.xres + screen->mode.hsync_len;
1885 dev_drv->pixclock = div_u64(ft, x_total * y_total);
1886 dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
1887 ret = clk_set_rate(vop_dev->dclk, dotclk);
1890 pixclock = div_u64(1000000000000llu, clk_get_rate(vop_dev->dclk));
1891 vop_dev->pixclock = pixclock;
1892 dev_drv->pixclock = vop_dev->pixclock;
1893 fps = rk_fb_calc_fps(screen, pixclock);
1894 screen->ft = 1000 / fps; /*one frame time in ms */
1897 dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
1898 clk_get_rate(vop_dev->dclk), fps);
1903 static int vop_fb_win_remap(struct rk_lcdc_driver *dev_drv, u16 order)
1905 mutex_lock(&dev_drv->fb_win_id_mutex);
1906 if (order == FB_DEFAULT_ORDER)
1907 order = FB0_WIN0_FB1_WIN1_FB2_WIN2_FB3_WIN3_FB4_HWC;
1908 dev_drv->fb4_win_id = order / 10000;
1909 dev_drv->fb3_win_id = (order / 1000) % 10;
1910 dev_drv->fb2_win_id = (order / 100) % 10;
1911 dev_drv->fb1_win_id = (order / 10) % 10;
1912 dev_drv->fb0_win_id = order % 10;
1913 mutex_unlock(&dev_drv->fb_win_id_mutex);
1918 static int vop_get_win_id(struct rk_lcdc_driver *dev_drv, const char *id)
1922 mutex_lock(&dev_drv->fb_win_id_mutex);
1923 if (!strcmp(id, "fb0") || !strcmp(id, "fb5"))
1924 win_id = dev_drv->fb0_win_id;
1925 else if (!strcmp(id, "fb1") || !strcmp(id, "fb6"))
1926 win_id = dev_drv->fb1_win_id;
1927 else if (!strcmp(id, "fb2") || !strcmp(id, "fb7"))
1928 win_id = dev_drv->fb2_win_id;
1929 else if (!strcmp(id, "fb3") || !strcmp(id, "fb8"))
1930 win_id = dev_drv->fb3_win_id;
1931 else if (!strcmp(id, "fb4") || !strcmp(id, "fb9"))
1932 win_id = dev_drv->fb4_win_id;
1933 mutex_unlock(&dev_drv->fb_win_id_mutex);
1938 static int vop_config_done(struct rk_lcdc_driver *dev_drv)
1940 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1942 struct rk_lcdc_win *win = NULL;
1944 spin_lock(&vop_dev->reg_lock);
1945 if (likely(vop_dev->clk_on)) {
1946 for (i = 0; i < dev_drv->lcdc_win_num; i++) {
1947 win = dev_drv->win[i];
1948 vop_layer_update_regs(vop_dev, win);
1950 vop_cfg_done(vop_dev);
1952 spin_unlock(&vop_dev->reg_lock);
1957 static int vop_dpi_open(struct rk_lcdc_driver *dev_drv, bool open)
1959 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1961 spin_lock(&vop_dev->reg_lock);
1962 if (likely(vop_dev->clk_on)) {
1963 vop_msk_reg(vop_dev, SYS_CTRL0, V_DIRECT_PATH_EN(open));
1964 vop_cfg_done(vop_dev);
1966 spin_unlock(&vop_dev->reg_lock);
1971 static int vop_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id)
1973 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1975 spin_lock(&vop_dev->reg_lock);
1976 if (likely(vop_dev->clk_on)) {
1977 vop_msk_reg(vop_dev, SYS_CTRL0,
1978 V_DIRECT_PATH_LAYER_SEL(win_id));
1979 vop_cfg_done(vop_dev);
1981 spin_unlock(&vop_dev->reg_lock);
1985 static int vop_dpi_status(struct rk_lcdc_driver *dev_drv)
1987 struct vop_device *vop_dev = to_vop_dev(dev_drv);
1990 spin_lock(&vop_dev->reg_lock);
1992 if (likely(vop_dev->clk_on))
1993 status = vop_read_bit(vop_dev, SYS_CTRL0, V_DIRECT_PATH_EN(0));
1995 spin_unlock(&vop_dev->reg_lock);
2000 static int vop_set_irq_to_cpu(struct rk_lcdc_driver *dev_drv, int enable)
2002 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2005 enable_irq(vop_dev->irq);
2007 disable_irq(vop_dev->irq);
2011 static int vop_poll_vblank(struct rk_lcdc_driver *dev_drv)
2013 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2017 if (vop_dev->clk_on && (!dev_drv->suspend_flag)) {
2018 int_reg = vop_readl(vop_dev, INTR_STATUS);
2019 if (int_reg & INTR_LINE_FLAG0) {
2020 vop_dev->driver.frame_time.last_framedone_t =
2021 vop_dev->driver.frame_time.framedone_t;
2022 vop_dev->driver.frame_time.framedone_t = cpu_clock(0);
2023 vop_mask_writel(vop_dev, INTR_CLEAR, INTR_LINE_FLAG0,
2025 ret = RK_LF_STATUS_FC;
2027 ret = RK_LF_STATUS_FR;
2030 ret = RK_LF_STATUS_NC;
2036 static int vop_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
2037 unsigned int dsp_addr[][4])
2039 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2041 spin_lock(&vop_dev->reg_lock);
2042 if (likely(vop_dev->clk_on)) {
2043 dsp_addr[0][0] = vop_readl(vop_dev, WIN0_YRGB_MST);
2044 dsp_addr[1][0] = vop_readl(vop_dev, WIN1_YRGB_MST);
2045 dsp_addr[2][0] = vop_readl(vop_dev, HWC_MST);
2047 spin_unlock(&vop_dev->reg_lock);
2053 * sin_hue = sin(a)*256 +0x100;
2054 * cos_hue = cos(a)*256;
2056 * sin_hue = sin(a)*256;
2057 * cos_hue = cos(a)*256;
2059 static int vop_get_bcsh_hue(struct rk_lcdc_driver *dev_drv, bcsh_hue_mode mode)
2061 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2064 spin_lock(&vop_dev->reg_lock);
2065 if (likely(vop_dev->clk_on)) {
2066 val = vop_readl(vop_dev, BCSH_H);
2069 val &= MASK(SIN_HUE);
2073 val &= MASK(COS_HUE);
2081 spin_unlock(&vop_dev->reg_lock);
2086 static int vop_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,
2087 int sin_hue, int cos_hue)
2089 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2092 spin_lock(&vop_dev->reg_lock);
2093 if (likely(vop_dev->clk_on)) {
2095 * config range is [0, 510), typical value is 256
2096 * register range is [0, 255], cos_hue typical value is 128
2097 * sin_hue typical value is 0
2099 val = V_SIN_HUE(sin_hue >> 1) | V_COS_HUE(cos_hue >> 1);
2100 vop_msk_reg(vop_dev, BCSH_H, val);
2101 vop_cfg_done(vop_dev);
2103 spin_unlock(&vop_dev->reg_lock);
2108 static int vop_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
2109 bcsh_bcs_mode mode, int value)
2111 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2114 spin_lock(&vop_dev->reg_lock);
2115 if (likely(vop_dev->clk_on)) {
2119 * user range is [0, 255], typical value is 128
2120 * register range is [-32, 31], typical value is 0
2122 value >>= 2; /* 0-->32-->63 for user, typical is 32 */
2125 else if (value >= 0x20)
2126 value = value - 0x20;
2127 val = V_BRIGHTNESS(value);
2131 * config range is [0, 510), typical value is 256
2132 * register range is [0, 255], typical value is 128
2135 val = V_CONTRAST(value);
2139 * config range is [0, 1015], typical value is 512
2140 * register range is [0, 255], typical value is 128
2143 val = V_SAT_CON(value);
2148 vop_msk_reg(vop_dev, BCSH_BCS, val);
2149 vop_cfg_done(vop_dev);
2151 spin_unlock(&vop_dev->reg_lock);
2156 static int vop_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv, bcsh_bcs_mode mode)
2158 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2161 spin_lock(&vop_dev->reg_lock);
2162 if (likely(vop_dev->clk_on)) {
2163 val = vop_readl(vop_dev, BCSH_BCS);
2166 val &= MASK(BRIGHTNESS);
2174 val &= MASK(CONTRAST);
2179 val &= MASK(SAT_CON);
2187 spin_unlock(&vop_dev->reg_lock);
2191 static int vop_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
2193 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2195 spin_lock(&vop_dev->reg_lock);
2196 if (likely(vop_dev->clk_on)) {
2198 vop_writel(vop_dev, BCSH_BCS,
2199 V_BRIGHTNESS(0x00) | V_CONTRAST(0x80) |
2201 vop_writel(vop_dev, BCSH_H,
2202 V_SIN_HUE(0x00) | V_COS_HUE(0x80));
2203 vop_msk_reg(vop_dev, BCSH_CTRL, V_BCSH_EN(1) |
2204 V_VIDEO_MODE(BCSH_MODE_VIDEO));
2205 dev_drv->bcsh.enable = 1;
2207 vop_msk_reg(vop_dev, BCSH_CTRL, V_BCSH_EN(0));
2208 dev_drv->bcsh.enable = 0;
2210 vop_bcsh_path_sel(dev_drv);
2211 vop_cfg_done(vop_dev);
2213 spin_unlock(&vop_dev->reg_lock);
2218 static int vop_set_bcsh(struct rk_lcdc_driver *dev_drv, bool enable)
2220 if (!enable || !dev_drv->bcsh.enable) {
2221 vop_open_bcsh(dev_drv, false);
2225 if (dev_drv->bcsh.brightness <= 255 ||
2226 dev_drv->bcsh.contrast < 510 ||
2227 dev_drv->bcsh.sat_con <= 1015 ||
2228 (dev_drv->bcsh.sin_hue < 510 && dev_drv->bcsh.cos_hue < 510)) {
2229 vop_open_bcsh(dev_drv, true);
2230 if (dev_drv->bcsh.brightness <= 255)
2231 vop_set_bcsh_bcs(dev_drv, BRIGHTNESS,
2232 dev_drv->bcsh.brightness);
2233 if (dev_drv->bcsh.contrast < 510)
2234 vop_set_bcsh_bcs(dev_drv, CONTRAST,
2235 dev_drv->bcsh.contrast);
2236 if (dev_drv->bcsh.sat_con <= 1015)
2237 vop_set_bcsh_bcs(dev_drv, SAT_CON,
2238 dev_drv->bcsh.sat_con);
2239 if (dev_drv->bcsh.sin_hue < 510 &&
2240 dev_drv->bcsh.cos_hue < 510)
2241 vop_set_bcsh_hue(dev_drv, dev_drv->bcsh.sin_hue,
2242 dev_drv->bcsh.cos_hue);
2248 static int __maybe_unused
2249 vop_dsp_black(struct rk_lcdc_driver *dev_drv, int enable)
2251 struct vop_device *vop_dev = to_vop_dev(dev_drv);
2254 spin_lock(&vop_dev->reg_lock);
2255 if (likely(vop_dev->clk_on)) {
2256 vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_BLACK_EN(1));
2257 vop_cfg_done(vop_dev);
2259 spin_unlock(&vop_dev->reg_lock);
2261 spin_lock(&vop_dev->reg_lock);
2262 if (likely(vop_dev->clk_on)) {
2263 vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_BLACK_EN(0));
2264 vop_cfg_done(vop_dev);
2266 spin_unlock(&vop_dev->reg_lock);
2272 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
2274 .win_direct_en = vop_win_direct_en,
2275 .load_screen = vop_load_screen,
2276 .get_dspbuf_info = vop_get_dspbuf_info,
2277 .post_dspbuf = vop_post_dspbuf,
2278 .set_par = vop_set_par,
2279 .pan_display = vop_pan_display,
2280 .direct_set_addr = vop_direct_set_win_addr,
2283 .suspend = vop_early_suspend,
2284 .resume = vop_early_resume,
2285 .get_win_state = vop_get_win_state,
2286 .area_support_num = vop_get_area_num,
2287 .ovl_mgr = vop_ovl_mgr,
2288 .get_disp_info = vop_get_disp_info,
2289 .fps_mgr = vop_fps_mgr,
2290 .fb_get_win_id = vop_get_win_id,
2291 .fb_win_remap = vop_fb_win_remap,
2292 .poll_vblank = vop_poll_vblank,
2293 .dpi_open = vop_dpi_open,
2294 .dpi_win_sel = vop_dpi_win_sel,
2295 .dpi_status = vop_dpi_status,
2296 .get_dsp_addr = vop_get_dsp_addr,
2297 .set_dsp_bcsh_hue = vop_set_bcsh_hue,
2298 .set_dsp_bcsh_bcs = vop_set_bcsh_bcs,
2299 .get_dsp_bcsh_hue = vop_get_bcsh_hue,
2300 .get_dsp_bcsh_bcs = vop_get_bcsh_bcs,
2301 .open_bcsh = vop_open_bcsh,
2302 .set_dsp_lut = vop_set_lut,
2303 .set_hwc_lut = vop_set_hwc_lut,
2304 .dump_reg = vop_reg_dump,
2305 .cfg_done = vop_config_done,
2306 .set_irq_to_cpu = vop_set_irq_to_cpu,
2307 /*.dsp_black = vop_dsp_black,*/
2308 .backlight_close = vop_backlight_close,
2309 .mmu_en = vop_mmu_enable,
2312 static irqreturn_t vop_isr(int irq, void *dev_id)
2314 struct vop_device *vop_dev = (struct vop_device *)dev_id;
2315 ktime_t timestamp = ktime_get();
2317 unsigned long flags;
2319 spin_lock_irqsave(&vop_dev->irq_lock, flags);
2321 intr_status = vop_readl(vop_dev, INTR_STATUS);
2322 vop_mask_writel(vop_dev, INTR_CLEAR, INTR_MASK, intr_status);
2324 spin_unlock_irqrestore(&vop_dev->irq_lock, flags);
2326 intr_status &= 0xffff; /* ignore raw status at 16~32bit */
2327 /* This is expected for vop iommu irqs, since the irq is shared */
2331 if (intr_status & INTR_FS0) {
2332 timestamp = ktime_get();
2333 vop_dev->driver.vsync_info.timestamp = timestamp;
2334 wake_up_interruptible_all(&vop_dev->driver.vsync_info.wait);
2335 complete(&vop_dev->sync.frmst);
2336 intr_status &= ~INTR_FS0;
2339 /* fs1 interrupt occur only when the address is different */
2340 if (intr_status & INTR_FS1)
2341 intr_status &= ~INTR_FS1;
2343 if (intr_status & INTR_ADDR_SAME)
2344 intr_status &= ~INTR_ADDR_SAME;
2346 if (intr_status & INTR_DSP_HOLD_VALID) {
2347 complete(&vop_dev->sync.stdbyfin);
2348 intr_status &= ~INTR_DSP_HOLD_VALID;
2351 if (intr_status & INTR_LINE_FLAG0)
2352 intr_status &= ~INTR_LINE_FLAG0;
2354 if (intr_status & INTR_LINE_FLAG1)
2355 intr_status &= ~INTR_LINE_FLAG1;
2357 if (intr_status & INTR_BUS_ERROR) {
2358 intr_status &= ~INTR_BUS_ERROR;
2359 dev_warn_ratelimited(vop_dev->dev, "bus error!");
2362 if (intr_status & INTR_WIN0_EMPTY) {
2363 intr_status &= ~INTR_WIN0_EMPTY;
2364 dev_warn_ratelimited(vop_dev->dev, "intr win0 empty!");
2367 if (intr_status & INTR_WIN1_EMPTY) {
2368 intr_status &= ~INTR_WIN1_EMPTY;
2369 dev_warn_ratelimited(vop_dev->dev, "intr win1 empty!");
2372 if (intr_status & INTR_DMA_FINISH)
2373 intr_status &= ~INTR_DMA_FINISH;
2375 if (intr_status & INTR_MMU_STATUS)
2376 intr_status &= ~INTR_MMU_STATUS;
2379 dev_err(vop_dev->dev, "Unknown VOP IRQs: %#02x\n", intr_status);
2384 #if defined(CONFIG_PM)
2385 static int vop_suspend(struct platform_device *pdev, pm_message_t state)
2390 static int vop_resume(struct platform_device *pdev)
2395 #define vop_suspend NULL
2396 #define vop_resume NULL
2399 static int vop_parse_dt(struct vop_device *vop_dev)
2401 struct device_node *np = vop_dev->dev->of_node;
2402 struct rk_lcdc_driver *dev_drv = &vop_dev->driver;
2405 if (of_property_read_u32(np, "rockchip,prop", &val))
2406 vop_dev->prop = PRMRY; /*default set it as primary */
2408 vop_dev->prop = val;
2410 if (of_property_read_u32(np, "rockchip,mirror", &val))
2411 dev_drv->rotate_mode = NO_MIRROR;
2413 dev_drv->rotate_mode = val;
2415 if (of_property_read_u32(np, "rockchip,pwr18", &val))
2416 /*default set it as 3.xv power supply */
2417 vop_dev->pwr18 = false;
2419 vop_dev->pwr18 = (val ? true : false);
2421 if (of_property_read_u32(np, "rockchip,fb-win-map", &val))
2422 dev_drv->fb_win_map = FB_DEFAULT_ORDER;
2424 dev_drv->fb_win_map = val;
2426 if (of_property_read_u32(np, "rockchip,bcsh-en", &val))
2427 dev_drv->bcsh.enable = false;
2429 dev_drv->bcsh.enable = (val ? true : false);
2431 if (of_property_read_u32(np, "rockchip,brightness", &val))
2432 dev_drv->bcsh.brightness = 0xffff;
2434 dev_drv->bcsh.brightness = val;
2436 if (of_property_read_u32(np, "rockchip,contrast", &val))
2437 dev_drv->bcsh.contrast = 0xffff;
2439 dev_drv->bcsh.contrast = val;
2441 if (of_property_read_u32(np, "rockchip,sat-con", &val))
2442 dev_drv->bcsh.sat_con = 0xffff;
2444 dev_drv->bcsh.sat_con = val;
2446 if (of_property_read_u32(np, "rockchip,hue", &val)) {
2447 dev_drv->bcsh.sin_hue = 0xffff;
2448 dev_drv->bcsh.cos_hue = 0xffff;
2450 dev_drv->bcsh.sin_hue = val & 0xff;
2451 dev_drv->bcsh.cos_hue = (val >> 8) & 0xff;
2454 if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
2455 dev_drv->iommu_enabled = 0;
2457 dev_drv->iommu_enabled = val;
2462 static int vop_probe(struct platform_device *pdev)
2464 struct vop_device *vop_dev = NULL;
2465 struct rk_lcdc_driver *dev_drv;
2466 struct device *dev = &pdev->dev;
2467 struct resource *res;
2468 struct device_node *np = pdev->dev.of_node;
2473 * if the primary lcdc has not registered ,the extend
2474 * lcdc register later
2476 of_property_read_u32(np, "rockchip,prop", &prop);
2477 if (prop == EXTEND) {
2478 if (!is_prmry_rk_lcdc_registered())
2479 return -EPROBE_DEFER;
2482 vop_dev = devm_kzalloc(dev, sizeof(struct vop_device), GFP_KERNEL);
2486 platform_set_drvdata(pdev, vop_dev);
2488 vop_parse_dt(vop_dev);
2490 /* enable power domain */
2491 pm_runtime_enable(dev);
2493 vop_dev->hclk = devm_clk_get(vop_dev->dev, "hclk_lcdc");
2494 if (IS_ERR(vop_dev->hclk)) {
2495 dev_err(vop_dev->dev, "failed to get hclk source\n");
2496 return PTR_ERR(vop_dev->hclk);
2499 vop_dev->aclk = devm_clk_get(vop_dev->dev, "aclk_lcdc");
2500 if (IS_ERR(vop_dev->aclk)) {
2501 dev_err(vop_dev->dev, "failed to get aclk source\n");
2502 return PTR_ERR(vop_dev->aclk);
2504 vop_dev->dclk = devm_clk_get(vop_dev->dev, "dclk_lcdc");
2505 if (IS_ERR(vop_dev->dclk)) {
2506 dev_err(vop_dev->dev, "failed to get dclk source\n");
2507 return PTR_ERR(vop_dev->dclk);
2510 clk_prepare(vop_dev->hclk);
2511 clk_prepare(vop_dev->aclk);
2512 clk_prepare(vop_dev->dclk);
2514 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2515 vop_dev->regs = devm_ioremap_resource(dev, res);
2516 if (IS_ERR(vop_dev->regs)) {
2517 ret = PTR_ERR(vop_dev->regs);
2521 vop_dev->reg_phy_base = res->start;
2522 vop_dev->len = resource_size(res);
2523 vop_dev->regsbak = devm_kzalloc(dev, vop_dev->len, GFP_KERNEL);
2524 if (!vop_dev->regsbak) {
2529 vop_dev->hwc_lut_addr_base = (vop_dev->regs + HWC_LUT_ADDR);
2530 vop_dev->dsp_lut_addr_base = (vop_dev->regs + GAMMA_LUT_ADDR);
2531 vop_dev->grf_base = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
2532 if (IS_ERR(vop_dev->grf_base)) {
2533 dev_err(vop_dev->dev, "ERROR!! can't find grf reg property\n");
2534 vop_dev->grf_base = NULL;
2538 dev_set_name(vop_dev->dev, "vop%d", vop_dev->id);
2539 dev_drv = &vop_dev->driver;
2541 dev_drv->prop = prop;
2542 dev_drv->id = vop_dev->id;
2543 dev_drv->ops = &lcdc_drv_ops;
2544 dev_drv->lcdc_win_num = ARRAY_SIZE(vop_win);
2545 dev_drv->reserved_fb = 0;
2546 spin_lock_init(&vop_dev->reg_lock);
2547 spin_lock_init(&vop_dev->irq_lock);
2548 init_completion(&vop_dev->sync.stdbyfin);
2549 init_completion(&vop_dev->sync.frmst);
2550 vop_dev->sync.stdbyfin_to = 50; /* timeout 50 ms */
2551 vop_dev->sync.frmst_to = 50;
2553 vop_dev->irq = platform_get_irq(pdev, 0);
2554 if (vop_dev->irq < 0) {
2555 dev_err(dev, "cannot find IRQ for lcdc%d\n", vop_dev->id);
2560 ret = devm_request_irq(dev, vop_dev->irq, vop_isr,
2562 dev_name(dev), vop_dev);
2564 dev_err(dev, "cannot requeset irq %d - err %d\n",
2569 if (dev_drv->iommu_enabled)
2570 strcpy(dev_drv->mmu_dts_name, VOPL_IOMMU_COMPATIBLE_NAME);
2572 ret = rk_fb_register(dev_drv, vop_win, vop_dev->id);
2574 dev_err(dev, "register fb for failed!\n");
2577 vop_dev->screen = dev_drv->screen0;
2578 dev_info(dev, "lcdc%d probe ok, iommu %s\n",
2579 vop_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled");
2584 clk_unprepare(vop_dev->dclk);
2585 clk_unprepare(vop_dev->aclk);
2586 clk_unprepare(vop_dev->hclk);
2587 pm_runtime_disable(dev);
2592 static int vop_remove(struct platform_device *pdev)
2597 static void vop_shutdown(struct platform_device *pdev)
2599 struct vop_device *vop_dev = platform_get_drvdata(pdev);
2600 struct rk_lcdc_driver *dev_drv = &vop_dev->driver;
2602 dev_drv->suspend_flag = 1;
2604 flush_kthread_worker(&dev_drv->update_regs_worker);
2605 kthread_stop(dev_drv->update_regs_thread);
2607 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
2608 dev_drv->trsm_ops->disable();
2610 vop_deinit(vop_dev);
2611 rk_disp_pwr_disable(dev_drv);
2614 #if defined(CONFIG_OF)
2615 static const struct of_device_id vop_dt_ids[] = {
2616 {.compatible = "rockchip,rk3366-lcdc-lite",},
2621 static struct platform_driver vop_driver = {
2623 .remove = vop_remove,
2625 .name = "rk-vop-lite",
2626 .owner = THIS_MODULE,
2627 .of_match_table = of_match_ptr(vop_dt_ids),
2629 .suspend = vop_suspend,
2630 .resume = vop_resume,
2631 .shutdown = vop_shutdown,
2634 static int __init vop_module_init(void)
2636 return platform_driver_register(&vop_driver);
2639 static void __exit vop_module_exit(void)
2641 platform_driver_unregister(&vop_driver);
2644 fs_initcall(vop_module_init);
2645 module_exit(vop_module_exit);