2 * drivers/video/rockchip/lcdc/rk3036_lcdc.c
4 * Copyright (C) 2014 ROCKCHIP, Inc.
5 * Author:zhengyang<zhengyang@rock-chips.com>
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/string.h>
22 #include <linux/slab.h>
23 #include <linux/device.h>
24 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/platform_device.h>
28 #include <linux/clk.h>
29 #include <asm/div64.h>
30 #include <linux/uaccess.h>
31 #include <linux/rockchip/cpu.h>
32 #include <linux/rockchip/iomap.h>
33 #include <linux/rockchip/grf.h>
34 #include <linux/rockchip/common.h>
35 #include <dt-bindings/clock/rk_system_status.h>
36 #if defined(CONFIG_ION_ROCKCHIP)
37 #include <linux/rockchip-iovmm.h>
39 #include "rk3036_lcdc.h"
41 static int dbg_thresd;
42 module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
44 #define DBG(level, x...) do { \
45 if (unlikely(dbg_thresd >= level)) \
46 dev_info(dev_drv->dev, x); \
49 #define grf_writel(offset, v) do { \
50 writel_relaxed(v, RK_GRF_VIRT + offset); \
54 static struct rk_lcdc_win lcdc_win[] = {
72 static irqreturn_t rk3036_lcdc_isr(int irq, void *dev_id)
74 struct lcdc_device *lcdc_dev =
75 (struct lcdc_device *)dev_id;
76 ktime_t timestamp = ktime_get();
77 u32 int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
79 if (int_reg & m_FS_INT_STA) {
80 timestamp = ktime_get();
81 lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
83 /*if (lcdc_dev->driver.wait_fs) {*/
85 spin_lock(&(lcdc_dev->driver.cpl_lock));
86 complete(&(lcdc_dev->driver.frame_done));
87 spin_unlock(&(lcdc_dev->driver.cpl_lock));
89 lcdc_dev->driver.vsync_info.timestamp = timestamp;
90 wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
92 } else if (int_reg & m_LF_INT_STA) {
93 lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
99 static int rk3036_lcdc_clk_enable(struct lcdc_device *lcdc_dev)
101 #ifdef CONFIG_RK_FPGA
102 lcdc_dev->clk_on = 1;
105 if (!lcdc_dev->clk_on) {
106 clk_prepare_enable(lcdc_dev->hclk);
107 clk_prepare_enable(lcdc_dev->dclk);
108 clk_prepare_enable(lcdc_dev->aclk);
109 /* clk_prepare_enable(lcdc_dev->pd);*/
110 spin_lock(&lcdc_dev->reg_lock);
111 lcdc_dev->clk_on = 1;
112 spin_unlock(&lcdc_dev->reg_lock);
118 static int rk3036_lcdc_clk_disable(struct lcdc_device *lcdc_dev)
120 #ifdef CONFIG_RK_FPGA
121 lcdc_dev->clk_on = 0;
124 if (lcdc_dev->clk_on) {
125 spin_lock(&lcdc_dev->reg_lock);
126 lcdc_dev->clk_on = 0;
127 spin_unlock(&lcdc_dev->reg_lock);
129 clk_disable_unprepare(lcdc_dev->dclk);
130 clk_disable_unprepare(lcdc_dev->hclk);
131 clk_disable_unprepare(lcdc_dev->aclk);
132 /* clk_disable_unprepare(lcdc_dev->pd);*/
138 static int rk3036_lcdc_enable_irq(struct rk_lcdc_driver *dev_drv)
141 struct lcdc_device *lcdc_dev = container_of(dev_drv,
142 struct lcdc_device, driver);
143 mask = m_FS_INT_CLEAR | m_FS_INT_EN;
144 val = v_FS_INT_CLEAR(1) | v_FS_INT_EN(1);
145 lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
149 static int rk3036_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
153 spin_lock(&lcdc_dev->reg_lock);
154 if (likely(lcdc_dev->clk_on)) {
155 mask = m_FS_INT_CLEAR | m_FS_INT_EN;
156 val = v_FS_INT_CLEAR(0) | v_FS_INT_EN(0);
157 lcdc_msk_reg(lcdc_dev, INT_STATUS, mask, val);
158 spin_unlock(&lcdc_dev->reg_lock);
160 spin_unlock(&lcdc_dev->reg_lock);
166 static void rk_lcdc_read_reg_defalut_cfg(struct lcdc_device
172 spin_lock(&lcdc_dev->reg_lock);
173 for (reg = 0; reg < 0xdc; reg += 4)
174 value = lcdc_readl(lcdc_dev, reg);
176 spin_unlock(&lcdc_dev->reg_lock);
179 static int rk3036_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev)
183 enum data_format win0_format = lcdc_dev->driver.win[0]->format;
184 enum data_format win1_format = lcdc_dev->driver.win[1]->format;
186 int win0_alpha_en = ((win0_format == ARGB888) ||
187 (win0_format == ABGR888)) ? 1 : 0;
188 int win1_alpha_en = ((win1_format == ARGB888) ||
189 (win1_format == ABGR888)) ? 1 : 0;
190 u32 *_pv = (u32 *)lcdc_dev->regsbak;
192 _pv += (DSP_CTRL0 >> 2);
193 win0_top = ((*_pv) & (m_WIN0_TOP)) >> 8;
194 if (win0_top && (lcdc_dev->atv_layer_cnt >= 2) && (win0_alpha_en)) {
195 mask = m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN |
197 val = v_WIN0_ALPHA_EN(1) | v_WIN1_ALPHA_EN(0) |
198 v_WIN1_PREMUL_SCALE(0);
199 lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
201 mask = m_WIN0_ALPHA_MODE | m_PREMUL_ALPHA_ENABLE |
203 val = v_WIN0_ALPHA_MODE(1) | v_PREMUL_ALPHA_ENABLE(1) |
204 v_ALPHA_MODE_SEL1(0);
205 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
206 } else if ((!win0_top) && (lcdc_dev->atv_layer_cnt >= 2) &&
208 mask = m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN |
210 val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(1) |
211 v_WIN1_PREMUL_SCALE(0);
212 lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
214 mask = m_WIN1_ALPHA_MODE | m_PREMUL_ALPHA_ENABLE |
216 val = v_WIN1_ALPHA_MODE(1) | v_PREMUL_ALPHA_ENABLE(1) |
217 v_ALPHA_MODE_SEL1(0);
218 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
220 mask = m_WIN0_ALPHA_EN | m_WIN1_ALPHA_EN;
221 val = v_WIN0_ALPHA_EN(0) | v_WIN1_ALPHA_EN(0);
222 lcdc_msk_reg(lcdc_dev, ALPHA_CTRL, mask, val);
227 static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
228 struct rk_lcdc_win *win)
232 if (win->state == 1) {
234 mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP;
235 val = v_WIN0_EN(win->state) |
236 v_WIN0_FORMAT(win->fmt_cfg) |
237 v_WIN0_RB_SWAP(win->swap_rb);
238 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
240 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB,
241 v_X_SCL_FACTOR(win->scale_yrgb_x) |
242 v_Y_SCL_FACTOR(win->scale_yrgb_y));
243 lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_CBR,
244 v_X_SCL_FACTOR(win->scale_cbcr_x) |
245 v_Y_SCL_FACTOR(win->scale_cbcr_y));
246 lcdc_msk_reg(lcdc_dev, WIN0_VIR,
247 m_YRGB_VIR | m_CBBR_VIR,
248 v_YRGB_VIR(win->area[0].y_vir_stride) |
249 v_CBBR_VIR(win->area[0].uv_vir_stride));
250 lcdc_writel(lcdc_dev, WIN0_ACT_INFO,
251 v_ACT_WIDTH(win->area[0].xact) |
252 v_ACT_HEIGHT(win->area[0].yact));
253 lcdc_writel(lcdc_dev, WIN0_DSP_ST,
254 v_DSP_STX(win->area[0].dsp_stx) |
255 v_DSP_STY(win->area[0].dsp_sty));
256 lcdc_writel(lcdc_dev, WIN0_DSP_INFO,
257 v_DSP_WIDTH(win->post_cfg.xsize) |
258 v_DSP_HEIGHT(win->post_cfg.ysize));
260 lcdc_writel(lcdc_dev, WIN0_YRGB_MST,
261 win->area[0].y_addr);
262 lcdc_writel(lcdc_dev, WIN0_CBR_MST,
263 win->area[0].uv_addr);
264 } else if (win->id == 1) {
265 mask = m_WIN1_EN | m_WIN1_FORMAT | m_WIN1_RB_SWAP;
266 val = v_WIN1_EN(win->state) |
267 v_WIN1_FORMAT(win->fmt_cfg) |
268 v_WIN1_RB_SWAP(win->swap_rb);
269 lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
271 lcdc_writel(lcdc_dev, WIN1_SCL_FACTOR_YRGB,
272 v_X_SCL_FACTOR(win->scale_yrgb_x) |
273 v_Y_SCL_FACTOR(win->scale_yrgb_y));
275 lcdc_msk_reg(lcdc_dev, WIN1_VIR, m_YRGB_VIR,
276 v_YRGB_VIR(win->area[0].y_vir_stride));
277 lcdc_writel(lcdc_dev, WIN1_ACT_INFO,
278 v_ACT_WIDTH(win->area[0].xact) |
279 v_ACT_HEIGHT(win->area[0].yact));
280 lcdc_writel(lcdc_dev, WIN1_DSP_INFO,
281 v_DSP_WIDTH(win->post_cfg.xsize) |
282 v_DSP_HEIGHT(win->post_cfg.ysize));
283 lcdc_writel(lcdc_dev, WIN1_DSP_ST,
284 v_DSP_STX(win->area[0].dsp_stx) |
285 v_DSP_STY(win->area[0].dsp_sty));
286 lcdc_writel(lcdc_dev, WIN1_MST, win->area[0].y_addr);
287 } /* else if (win->id == 2) {
290 win->area[0].y_addr = 0;
291 win->area[0].uv_addr = 0;
293 lcdc_msk_reg(lcdc_dev,
294 SYS_CTRL, m_WIN0_EN, v_WIN0_EN(0));
295 else if (win->id == 1)
296 lcdc_msk_reg(lcdc_dev,
297 SYS_CTRL, m_WIN1_EN, v_WIN1_EN(0));
298 else if (win->id == 2)
299 lcdc_msk_reg(lcdc_dev,
300 SYS_CTRL, m_HWC_EN, v_HWC_EN(0));
302 rk3036_lcdc_alpha_cfg(lcdc_dev);
305 static void lcdc_layer_enable(struct lcdc_device *lcdc_dev,
306 unsigned int win_id, bool open)
308 spin_lock(&lcdc_dev->reg_lock);
309 if (likely(lcdc_dev->clk_on) &&
310 lcdc_dev->driver.win[win_id]->state != open) {
312 if (!lcdc_dev->atv_layer_cnt) {
313 dev_info(lcdc_dev->dev,
314 "wakeup from standby!\n");
315 lcdc_dev->standby = 0;
317 lcdc_dev->atv_layer_cnt++;
318 } else if ((lcdc_dev->atv_layer_cnt > 0) && (!open)) {
319 lcdc_dev->atv_layer_cnt--;
321 lcdc_dev->driver.win[win_id]->state = open;
323 lcdc_layer_update_regs(lcdc_dev,
324 lcdc_dev->driver.win[win_id]);
325 lcdc_cfg_done(lcdc_dev);
327 /*if no layer used,disable lcdc*/
328 if (!lcdc_dev->atv_layer_cnt) {
329 dev_info(lcdc_dev->dev,
330 "no layer is used, go to standby!\n");
331 lcdc_dev->standby = 1;
334 spin_unlock(&lcdc_dev->reg_lock);
337 static int rk3036_lcdc_reg_update(struct rk_lcdc_driver *dev_drv)
339 struct lcdc_device *lcdc_dev =
340 container_of(dev_drv, struct lcdc_device, driver);
341 struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
342 struct rk_lcdc_win *win1 = lcdc_dev->driver.win[1];
346 spin_lock(&lcdc_dev->reg_lock);
347 if (likely(lcdc_dev->clk_on)) {
348 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
349 v_LCDC_STANDBY(lcdc_dev->standby));
350 lcdc_layer_update_regs(lcdc_dev, win0);
351 lcdc_layer_update_regs(lcdc_dev, win1);
352 rk3036_lcdc_alpha_cfg(lcdc_dev);
353 lcdc_cfg_done(lcdc_dev);
355 spin_unlock(&lcdc_dev->reg_lock);
356 /* if (dev_drv->wait_fs) { */
358 spin_lock_irqsave(&dev_drv->cpl_lock, flags);
359 init_completion(&dev_drv->frame_done);
360 spin_unlock_irqrestore(&dev_drv->cpl_lock, flags);
361 timeout = wait_for_completion_timeout(&dev_drv->frame_done,
363 (dev_drv->cur_screen->ft
365 if (!timeout && (!dev_drv->frame_done.done)) {
366 dev_warn(lcdc_dev->dev,
367 "wait for new frame start time out!\n");
371 DBG(2, "%s for lcdc%d\n", __func__, lcdc_dev->id);
375 static void rk3036_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
377 memcpy((u8 *)lcdc_dev->regs, (u8 *)lcdc_dev->regsbak, 0xdc);
380 static void rk3036_lcdc_mmu_en(struct rk_lcdc_driver *dev_drv)
383 struct lcdc_device *lcdc_dev =
384 container_of(dev_drv, struct lcdc_device, driver);
386 spin_lock(&lcdc_dev->reg_lock);
387 if (likely(lcdc_dev->clk_on)) {
388 mask = m_MMU_EN | m_AXI_MAX_OUTSTANDING_EN |
389 m_AXI_OUTSTANDING_MAX_NUM;
390 val = v_MMU_EN(1) | v_AXI_OUTSTANDING_MAX_NUM(31) |
391 v_AXI_MAX_OUTSTANDING_EN(1);
392 lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
394 spin_unlock(&lcdc_dev->reg_lock);
397 static int rk3036_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
399 #ifdef CONFIG_RK_FPGA
403 struct lcdc_device *lcdc_dev =
404 container_of(dev_drv, struct lcdc_device, driver);
405 struct rk_screen *screen = dev_drv->cur_screen;
407 ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
409 dev_err(dev_drv->dev,
410 "set lcdc%d dclk failed\n", lcdc_dev->id);
412 div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
413 lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
415 fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
416 screen->ft = 1000 / fps;
417 dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
418 lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
422 /********do basic init*********/
423 static int rk3036_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
425 struct lcdc_device *lcdc_dev = container_of(dev_drv,
426 struct lcdc_device, driver);
428 if (lcdc_dev->pre_init)
430 lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
431 lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
432 lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
433 /* lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc"); */
435 if (/*IS_ERR(lcdc_dev->pd) ||*/ (IS_ERR(lcdc_dev->aclk)) ||
436 (IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
437 dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
441 rk_disp_pwr_enable(dev_drv);
442 rk3036_lcdc_clk_enable(lcdc_dev);
444 /*backup reg config at uboot*/
445 rk_lcdc_read_reg_defalut_cfg(lcdc_dev);
446 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_AUTO_GATING_EN,
447 v_AUTO_GATING_EN(0));
448 lcdc_cfg_done(lcdc_dev);
449 if (dev_drv->iommu_enabled)
450 /*disable win0 to workaround iommu pagefault*/
451 lcdc_layer_enable(lcdc_dev, 0, 0);
452 lcdc_dev->pre_init = true;
457 static int rk3036_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
462 struct lcdc_device *lcdc_dev = container_of(dev_drv,
463 struct lcdc_device, driver);
464 struct rk_screen *screen = dev_drv->cur_screen;
465 u16 right_margin = screen->mode.right_margin;
466 u16 left_margin = screen->mode.left_margin;
467 u16 lower_margin = screen->mode.lower_margin;
468 u16 upper_margin = screen->mode.upper_margin;
469 u16 x_res = screen->mode.xres;
470 u16 y_res = screen->mode.yres;
473 spin_lock(&lcdc_dev->reg_lock);
474 if (likely(lcdc_dev->clk_on)) {
475 switch (screen->type) {
477 mask = m_HDMI_DCLK_EN;
478 val = v_HDMI_DCLK_EN(1);
479 if (screen->pixelrepeat) {
480 mask |= m_CORE_CLK_DIV_EN;
481 val |= v_CORE_CLK_DIV_EN(1);
483 mask |= m_CORE_CLK_DIV_EN;
484 val |= v_CORE_CLK_DIV_EN(0);
486 lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
487 mask = (1 << 4) | (1 << 5) | (1 << 6);
488 val = (screen->pin_hsync << 4) |
489 (screen->pin_vsync << 5) |
490 (screen->pin_den << 6);
491 grf_writel(RK3036_GRF_SOC_CON2, (mask << 16) | val);
494 mask = m_TVE_DAC_DCLK_EN;
495 val = v_TVE_DAC_DCLK_EN(1);
496 if (screen->pixelrepeat) {
497 mask |= m_CORE_CLK_DIV_EN;
498 val |= v_CORE_CLK_DIV_EN(1);
500 mask |= m_CORE_CLK_DIV_EN;
501 val |= v_CORE_CLK_DIV_EN(0);
503 lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val);
504 if ((x_res == 720) && (y_res == 576)) {
505 lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
506 m_TVE_MODE, v_TVE_MODE(TV_PAL));
507 } else if ((x_res == 720) && (y_res == 480)) {
508 lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
509 m_TVE_MODE, v_TVE_MODE(TV_NTSC));
511 dev_err(lcdc_dev->dev,
512 "unsupported video timing!\n");
517 dev_err(lcdc_dev->dev, "un supported interface!\n");
521 mask = m_DSP_OUT_FORMAT | m_HSYNC_POL | m_VSYNC_POL |
522 m_DEN_POL | m_DCLK_POL;
523 val = v_DSP_OUT_FORMAT(face) |
524 v_HSYNC_POL(screen->pin_hsync) |
525 v_VSYNC_POL(screen->pin_vsync) |
526 v_DEN_POL(screen->pin_den) |
527 v_DCLK_POL(screen->pin_dclk);
528 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
530 mask = m_BG_COLOR | m_DSP_BG_SWAP | m_DSP_RB_SWAP |
531 m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
532 m_DSP_DUMMY_SWAP | m_BLANK_EN;
534 val = v_BG_COLOR(0x000000) | v_DSP_BG_SWAP(screen->swap_gb) |
535 v_DSP_RB_SWAP(screen->swap_rb) |
536 v_DSP_RG_SWAP(screen->swap_rg) |
537 v_DSP_DELTA_SWAP(screen->swap_delta) |
538 v_DSP_DUMMY_SWAP(screen->swap_dumy) |
541 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, mask, val);
543 v_HSYNC(screen->mode.hsync_len) | v_HORPRD(screen->mode.
548 lcdc_writel(lcdc_dev, DSP_HTOTAL_HS_END, val);
549 val = v_HAEP(screen->mode.hsync_len + left_margin + x_res) |
550 v_HASP(screen->mode.hsync_len + left_margin);
551 lcdc_writel(lcdc_dev, DSP_HACT_ST_END, val);
553 if (screen->mode.vmode == FB_VMODE_INTERLACED) {
554 /*First Field Timing*/
555 lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END,
556 v_VSYNC(screen->mode.vsync_len) |
557 v_VERPRD(2 * (screen->mode.vsync_len +
558 upper_margin + lower_margin)
560 lcdc_writel(lcdc_dev, DSP_VACT_ST_END,
561 v_VAEP(screen->mode.vsync_len +
562 upper_margin + y_res/2) |
563 v_VASP(screen->mode.vsync_len +
565 /*Second Field Timing*/
566 lcdc_writel(lcdc_dev, DSP_VS_ST_END_F1,
567 v_VSYNC_ST_F1(screen->mode.vsync_len +
568 upper_margin + y_res/2 +
570 v_VSYNC_END_F1(2 * screen->mode.vsync_len
571 + upper_margin + y_res/2 +
573 lcdc_writel(lcdc_dev, DSP_VACT_ST_END_F1,
574 v_VAEP(2 * (screen->mode.vsync_len +
575 upper_margin) + y_res +
577 v_VASP(2 * (screen->mode.vsync_len +
578 upper_margin) + y_res/2 +
581 lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
583 m_INTERLACE_DSP_POL |
584 m_WIN1_DIFF_DCLK_EN |
585 m_WIN0_YRGB_DEFLICK_EN |
586 m_WIN0_CBR_DEFLICK_EN,
587 v_INTERLACE_DSP_EN(1) |
588 v_INTERLACE_DSP_POL(0) |
589 v_WIN1_DIFF_DCLK_EN(1) |
590 v_WIN0_YRGB_DEFLICK_EN(1) |
591 v_WIN0_CBR_DEFLICK_EN(1));
593 val = v_VSYNC(screen->mode.vsync_len) |
594 v_VERPRD(screen->mode.vsync_len + upper_margin +
595 y_res + lower_margin);
596 lcdc_writel(lcdc_dev, DSP_VTOTAL_VS_END, val);
598 val = v_VAEP(screen->mode.vsync_len +
599 upper_margin + y_res) |
600 v_VASP(screen->mode.vsync_len +
601 screen->mode.upper_margin);
602 lcdc_writel(lcdc_dev, DSP_VACT_ST_END, val);
604 lcdc_msk_reg(lcdc_dev, DSP_CTRL0,
606 m_WIN1_DIFF_DCLK_EN |
607 m_WIN0_YRGB_DEFLICK_EN |
608 m_WIN0_CBR_DEFLICK_EN,
609 v_INTERLACE_DSP_EN(0) |
610 v_WIN1_DIFF_DCLK_EN(0) |
611 v_WIN0_YRGB_DEFLICK_EN(0) |
612 v_WIN0_CBR_DEFLICK_EN(0));
615 spin_unlock(&lcdc_dev->reg_lock);
617 ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);
619 dev_err(dev_drv->dev,
620 "set lcdc%d dclk failed\n", lcdc_dev->id);
622 div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
623 lcdc_dev->driver.pixclock = lcdc_dev->pixclock;
625 fps = rk_fb_calc_fps(screen, lcdc_dev->pixclock);
626 screen->ft = 1000 / fps;
627 dev_info(lcdc_dev->dev, "%s: dclk:%lu>>fps:%d ",
628 lcdc_dev->driver.name, clk_get_rate(lcdc_dev->dclk), fps);
629 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
630 dev_drv->trsm_ops->enable();
637 static int rk3036_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
640 struct lcdc_device *lcdc_dev = container_of(dev_drv,
641 struct lcdc_device, driver);
643 /*enable clk,when first layer open */
644 if ((open) && (!lcdc_dev->atv_layer_cnt)) {
645 rk3036_lcdc_pre_init(dev_drv);
646 rk3036_lcdc_clk_enable(lcdc_dev);
647 #if defined(CONFIG_ROCKCHIP_IOMMU)
648 if (dev_drv->iommu_enabled) {
649 if (!dev_drv->mmu_dev) {
651 rk_fb_get_sysmmu_device_by_compatible(
652 dev_drv->mmu_dts_name);
653 if (dev_drv->mmu_dev) {
654 rk_fb_platform_set_sysmmu(dev_drv->mmu_dev,
656 rockchip_iovmm_activate(dev_drv->dev);
658 dev_err(dev_drv->dev,
659 "failed to get iommu device\n"
666 rk3036_lcdc_reg_restore(lcdc_dev);
667 if (dev_drv->iommu_enabled)
668 rk3036_lcdc_mmu_en(dev_drv);
669 if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
670 rk3036_lcdc_set_dclk(dev_drv);
671 rk3036_lcdc_enable_irq(dev_drv);
673 rk3036_load_screen(dev_drv, 1);
677 if (win_id < ARRAY_SIZE(lcdc_win))
678 lcdc_layer_enable(lcdc_dev, win_id, open);
680 dev_err(lcdc_dev->dev, "invalid win id:%d\n", win_id);
682 /*when all layer closed,disable clk */
683 if ((!open) && (!lcdc_dev->atv_layer_cnt)) {
684 rk3036_lcdc_disable_irq(lcdc_dev);
685 rk3036_lcdc_reg_update(dev_drv);
686 #if defined(CONFIG_ROCKCHIP_IOMMU)
687 if (dev_drv->iommu_enabled) {
688 if (dev_drv->mmu_dev)
689 rockchip_iovmm_deactivate(dev_drv->dev);
692 rk3036_lcdc_clk_disable(lcdc_dev);
698 static int rk3036_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
700 struct lcdc_device *lcdc_dev =
701 container_of(dev_drv, struct lcdc_device, driver);
702 struct rk_screen *screen = dev_drv->cur_screen;
703 struct rk_lcdc_win *win = NULL;
704 char fmt[9] = "NULL";
707 dev_err(dev_drv->dev, "screen is null!\n");
712 win = dev_drv->win[0];
713 } else if (win_id == 1) {
714 win = dev_drv->win[1];
716 dev_err(dev_drv->dev, "un supported win number:%d\n", win_id);
720 spin_lock(&lcdc_dev->reg_lock);
721 win->post_cfg.xpos = win->area[0].xpos * (dev_drv->overscan.left +
722 dev_drv->overscan.right)/200 + screen->mode.xres *
723 (100 - dev_drv->overscan.left) / 200;
725 win->post_cfg.ypos = win->area[0].ypos * (dev_drv->overscan.top +
726 dev_drv->overscan.bottom)/200 +
728 (100 - dev_drv->overscan.top) / 200;
729 win->post_cfg.xsize = win->area[0].xsize *
730 (dev_drv->overscan.left +
731 dev_drv->overscan.right)/200;
732 win->post_cfg.ysize = win->area[0].ysize *
733 (dev_drv->overscan.top +
734 dev_drv->overscan.bottom)/200;
736 win->area[0].dsp_stx = win->post_cfg.xpos + screen->mode.left_margin +
737 screen->mode.hsync_len;
738 if (screen->mode.vmode == FB_VMODE_INTERLACED) {
739 win->post_cfg.ysize /= 2;
740 win->area[0].dsp_sty = win->post_cfg.ypos/2 +
741 screen->mode.upper_margin +
742 screen->mode.vsync_len;
744 win->area[0].dsp_sty = win->post_cfg.ypos +
745 screen->mode.upper_margin +
746 screen->mode.vsync_len;
748 win->scale_yrgb_x = calscale(win->area[0].xact, win->post_cfg.xsize);
749 win->scale_yrgb_y = calscale(win->area[0].yact, win->post_cfg.ysize);
750 switch (win->format) {
752 win->fmt_cfg = VOP_FORMAT_ARGB888;
756 win->fmt_cfg = VOP_FORMAT_ARGB888;
760 win->fmt_cfg = VOP_FORMAT_ARGB888;
764 win->fmt_cfg = VOP_FORMAT_RGB888;
768 win->fmt_cfg = VOP_FORMAT_RGB565;
773 win->fmt_cfg = VOP_FORMAT_YCBCR444;
774 win->scale_cbcr_x = calscale(win->area[0].xact,
775 win->post_cfg.xsize);
776 win->scale_cbcr_y = calscale(win->area[0].yact,
777 win->post_cfg.ysize);
780 dev_err(lcdc_dev->driver.dev,
781 "%s:un supported format!\n",
787 win->fmt_cfg = VOP_FORMAT_YCBCR422;
788 win->scale_cbcr_x = calscale((win->area[0].xact / 2),
789 win->post_cfg.xsize);
790 win->scale_cbcr_y = calscale(win->area[0].yact,
791 win->post_cfg.ysize);
794 dev_err(lcdc_dev->driver.dev,
795 "%s:un supported format!\n",
801 win->fmt_cfg = VOP_FORMAT_YCBCR420;
802 win->scale_cbcr_x = calscale(win->area[0].xact / 2,
803 win->post_cfg.xsize);
804 win->scale_cbcr_y = calscale(win->area[0].yact / 2,
805 win->post_cfg.ysize);
808 dev_err(lcdc_dev->driver.dev,
809 "%s:un supported format!\n",
814 dev_err(lcdc_dev->driver.dev, "%s:un supported format!\n",
818 spin_unlock(&lcdc_dev->reg_lock);
820 DBG(2, "lcdc%d>>%s\n"
821 ">>format:%s>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d\n"
822 ">>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", lcdc_dev->id,
823 __func__, get_format_string(win->format, fmt),
824 win->area[0].xact, win->area[0].yact, win->post_cfg.xsize,
825 win->post_cfg.ysize, win->area[0].xvir, win->area[0].yvir,
826 win->post_cfg.xpos, win->post_cfg.ypos);
830 static int rk3036_lcdc_pan_display(struct rk_lcdc_driver *dev_drv, int win_id)
832 struct lcdc_device *lcdc_dev = container_of(dev_drv,
833 struct lcdc_device, driver);
834 struct rk_lcdc_win *win = NULL;
835 struct rk_screen *screen = dev_drv->cur_screen;
838 dev_err(dev_drv->dev, "screen is null!\n");
843 win = dev_drv->win[0];
844 } else if (win_id == 1) {
845 win = dev_drv->win[1];
847 dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
851 spin_lock(&lcdc_dev->reg_lock);
852 if (likely(lcdc_dev->clk_on)) {
853 win->area[0].y_addr = win->area[0].smem_start +
854 win->area[0].y_offset;
855 win->area[0].uv_addr = win->area[0].cbr_start +
856 win->area[0].c_offset;
857 if (win->area[0].y_addr)
858 lcdc_layer_update_regs(lcdc_dev, win);
859 /*lcdc_cfg_done(lcdc_dev);*/
861 spin_unlock(&lcdc_dev->reg_lock);
863 DBG(2, "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x>>offset:%d\n",
864 lcdc_dev->id, __func__, win->area[0].y_addr,
865 win->area[0].uv_addr, win->area[0].y_offset);
866 /* this is the first frame of the system,
867 enable frame start interrupt*/
868 if ((dev_drv->first_frame)) {
869 dev_drv->first_frame = 0;
870 rk3036_lcdc_enable_irq(dev_drv);
875 static int rk3036_lcdc_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd,
876 unsigned long arg, int win_id)
878 struct lcdc_device *lcdc_dev = container_of(dev_drv,
879 struct lcdc_device, driver);
881 void __user *argp = (void __user *)arg;
882 struct color_key_cfg clr_key_cfg;
885 case RK_FBIOGET_PANEL_SIZE:
886 panel_size[0] = lcdc_dev->screen->mode.xres;
887 panel_size[1] = lcdc_dev->screen->mode.yres;
888 if (copy_to_user(argp, panel_size, 8))
891 case RK_FBIOPUT_COLOR_KEY_CFG:
892 if (copy_from_user(&clr_key_cfg, argp,
893 sizeof(struct color_key_cfg)))
895 lcdc_writel(lcdc_dev, WIN0_COLOR_KEY,
896 clr_key_cfg.win0_color_key_cfg);
897 lcdc_writel(lcdc_dev, WIN1_COLOR_KEY,
898 clr_key_cfg.win1_color_key_cfg);
907 static int rk3036_lcdc_get_win_id(struct rk_lcdc_driver *dev_drv,
912 mutex_lock(&dev_drv->fb_win_id_mutex);
913 if (!strcmp(id, "fb0"))
914 win_id = dev_drv->fb0_win_id;
915 else if (!strcmp(id, "fb1"))
916 win_id = dev_drv->fb1_win_id;
917 else if (!strcmp(id, "fb2"))
918 win_id = dev_drv->fb2_win_id;
919 mutex_unlock(&dev_drv->fb_win_id_mutex);
924 static int rk3036_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv,
927 return dev_drv->win[win_id]->state;
930 static int rk3036_lcdc_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap,
933 struct lcdc_device *lcdc_dev =
934 container_of(dev_drv, struct lcdc_device, driver);
937 spin_lock(&lcdc_dev->reg_lock);
938 if (lcdc_dev->clk_on) {
940 lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN0_TOP,
944 ovl = lcdc_read_bit(lcdc_dev, DSP_CTRL0, m_WIN0_TOP);
949 spin_unlock(&lcdc_dev->reg_lock);
954 static int rk3036_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
956 struct lcdc_device *lcdc_dev = container_of(dev_drv,
957 struct lcdc_device, driver);
958 if (dev_drv->suspend_flag)
960 dev_drv->suspend_flag = 1;
961 flush_kthread_worker(&dev_drv->update_regs_worker);
963 if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
964 dev_drv->trsm_ops->disable();
965 spin_lock(&lcdc_dev->reg_lock);
966 if (likely(lcdc_dev->clk_on)) {
967 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN,
969 lcdc_msk_reg(lcdc_dev, INT_STATUS, m_FS_INT_CLEAR,
971 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
973 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
975 lcdc_cfg_done(lcdc_dev);
976 if (dev_drv->iommu_enabled) {
977 if (dev_drv->mmu_dev)
978 rockchip_iovmm_deactivate(dev_drv->dev);
980 spin_unlock(&lcdc_dev->reg_lock);
982 spin_unlock(&lcdc_dev->reg_lock);
985 rk3036_lcdc_clk_disable(lcdc_dev);
986 rk_disp_pwr_disable(dev_drv);
990 static int rk3036_lcdc_early_resume(struct rk_lcdc_driver *dev_drv)
992 struct lcdc_device *lcdc_dev =
993 container_of(dev_drv, struct lcdc_device, driver);
995 if (!dev_drv->suspend_flag)
997 rk_disp_pwr_enable(dev_drv);
998 dev_drv->suspend_flag = 0;
1000 if (lcdc_dev->atv_layer_cnt) {
1001 rk3036_lcdc_clk_enable(lcdc_dev);
1002 rk3036_lcdc_reg_restore(lcdc_dev);
1004 spin_lock(&lcdc_dev->reg_lock);
1006 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_OUT_ZERO,
1008 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
1010 lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_BLANK_EN,
1012 lcdc_cfg_done(lcdc_dev);
1013 if (dev_drv->iommu_enabled) {
1014 if (dev_drv->mmu_dev)
1015 rockchip_iovmm_activate(dev_drv->dev);
1017 spin_unlock(&lcdc_dev->reg_lock);
1020 if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
1021 dev_drv->trsm_ops->enable();
1026 static int rk3036_lcdc_blank(struct rk_lcdc_driver *dev_drv,
1027 int win_id, int blank_mode)
1029 switch (blank_mode) {
1030 case FB_BLANK_UNBLANK:
1031 rk3036_lcdc_early_resume(dev_drv);
1033 case FB_BLANK_NORMAL:
1034 rk3036_lcdc_early_suspend(dev_drv);
1037 rk3036_lcdc_early_suspend(dev_drv);
1041 dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode);
1046 static int rk3036_lcdc_cfg_done(struct rk_lcdc_driver *dev_drv)
1048 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1049 struct lcdc_device, driver);
1051 spin_lock(&lcdc_dev->reg_lock);
1052 if (lcdc_dev->clk_on) {
1053 lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_LCDC_STANDBY,
1054 v_LCDC_STANDBY(lcdc_dev->standby));
1055 lcdc_cfg_done(lcdc_dev);
1057 spin_unlock(&lcdc_dev->reg_lock);
1063 sin_hue = sin(a)*256 +0x100;
1064 cos_hue = cos(a)*256;
1066 sin_hue = sin(a)*256;
1067 cos_hue = cos(a)*256;
1069 static int rk3036_lcdc_get_bcsh_hue(struct rk_lcdc_driver *dev_drv,
1072 struct lcdc_device *lcdc_dev =
1073 container_of(dev_drv, struct lcdc_device, driver);
1076 spin_lock(&lcdc_dev->reg_lock);
1077 if (lcdc_dev->clk_on) {
1078 val = lcdc_readl(lcdc_dev, BCSH_H);
1081 val &= m_BCSH_SIN_HUE;
1084 val &= m_BCSH_COS_HUE;
1091 spin_unlock(&lcdc_dev->reg_lock);
1097 static int rk3036_lcdc_set_bcsh_hue(struct rk_lcdc_driver *dev_drv,
1098 int sin_hue, int cos_hue)
1100 struct lcdc_device *lcdc_dev =
1101 container_of(dev_drv, struct lcdc_device, driver);
1104 spin_lock(&lcdc_dev->reg_lock);
1105 if (lcdc_dev->clk_on) {
1106 mask = m_BCSH_SIN_HUE | m_BCSH_COS_HUE;
1107 val = v_BCSH_SIN_HUE(sin_hue) | v_BCSH_COS_HUE(cos_hue);
1108 lcdc_msk_reg(lcdc_dev, BCSH_H, mask, val);
1109 lcdc_cfg_done(lcdc_dev);
1111 spin_unlock(&lcdc_dev->reg_lock);
1116 static int rk3036_lcdc_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
1117 bcsh_bcs_mode mode, int value)
1119 struct lcdc_device *lcdc_dev =
1120 container_of(dev_drv, struct lcdc_device, driver);
1123 spin_lock(&lcdc_dev->reg_lock);
1124 if (lcdc_dev->clk_on) {
1127 /*from 0 to 255,typical is 128*/
1130 else if (value >= 0x20)
1131 value = value - 0x20;
1132 mask = m_BCSH_BRIGHTNESS;
1133 val = v_BCSH_BRIGHTNESS(value);
1136 /*from 0 to 510,typical is 256*/
1137 mask = m_BCSH_CONTRAST;
1138 val = v_BCSH_CONTRAST(value);
1141 /*from 0 to 1015,typical is 256*/
1142 mask = m_BCSH_SAT_CON;
1143 val = v_BCSH_SAT_CON(value);
1148 lcdc_msk_reg(lcdc_dev, BCSH_BCS, mask, val);
1149 lcdc_cfg_done(lcdc_dev);
1151 spin_unlock(&lcdc_dev->reg_lock);
1155 static int rk3036_lcdc_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv,
1158 struct lcdc_device *lcdc_dev =
1159 container_of(dev_drv, struct lcdc_device, driver);
1162 spin_lock(&lcdc_dev->reg_lock);
1163 if (lcdc_dev->clk_on) {
1164 val = lcdc_readl(lcdc_dev, BCSH_BCS);
1167 val &= m_BCSH_BRIGHTNESS;
1170 else if (val == 0x20)
1174 val &= m_BCSH_CONTRAST;
1178 val &= m_BCSH_SAT_CON;
1185 spin_unlock(&lcdc_dev->reg_lock);
1190 static int rk3036_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open)
1192 struct lcdc_device *lcdc_dev =
1193 container_of(dev_drv, struct lcdc_device, driver);
1196 spin_lock(&lcdc_dev->reg_lock);
1197 if (lcdc_dev->clk_on) {
1199 lcdc_writel(lcdc_dev, BCSH_CTRL,
1200 v_BCSH_EN(1) | v_BCSH_OUT_MODE(3));
1201 lcdc_writel(lcdc_dev, BCSH_BCS,
1202 v_BCSH_BRIGHTNESS(0x00) |
1203 v_BCSH_CONTRAST(0x80) |
1204 v_BCSH_SAT_CON(0x80));
1205 lcdc_writel(lcdc_dev, BCSH_H, v_BCSH_COS_HUE(0x80));
1209 lcdc_msk_reg(lcdc_dev, BCSH_CTRL, mask, val);
1211 lcdc_cfg_done(lcdc_dev);
1213 spin_unlock(&lcdc_dev->reg_lock);
1217 static int rk3036_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
1218 struct overscan *overscan)
1222 dev_drv->overscan = *overscan;
1223 for (i = 0; i < dev_drv->lcdc_win_num; i++) {
1224 if (dev_drv->win[i] && dev_drv->win[i]->state) {
1225 rk3036_lcdc_set_par(dev_drv, i);
1226 rk3036_lcdc_pan_display(dev_drv, i);
1229 rk3036_lcdc_cfg_done(dev_drv);
1233 static int rk3036_fb_win_remap(struct rk_lcdc_driver *dev_drv,
1234 enum fb_win_map_order order)
1236 mutex_lock(&dev_drv->fb_win_id_mutex);
1237 if (order == FB_DEFAULT_ORDER)
1238 order = FB0_WIN1_FB1_WIN0_FB2_WIN2;
1239 dev_drv->fb2_win_id = order / 100;
1240 dev_drv->fb1_win_id = (order / 10) % 10;
1241 dev_drv->fb0_win_id = order % 10;
1242 mutex_unlock(&dev_drv->fb_win_id_mutex);
1247 static int rk3036_lcdc_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps,
1250 struct lcdc_device *lcdc_dev =
1251 container_of(dev_drv, struct lcdc_device, driver);
1252 struct rk_screen *screen = dev_drv->cur_screen;
1257 u32 x_total, y_total;
1260 ft = div_u64(1000000000000llu, fps);
1262 screen->mode.upper_margin + screen->mode.lower_margin +
1263 screen->mode.yres + screen->mode.vsync_len;
1265 screen->mode.left_margin + screen->mode.right_margin +
1266 screen->mode.xres + screen->mode.hsync_len;
1267 dev_drv->pixclock = div_u64(ft, x_total * y_total);
1268 dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
1269 ret = clk_set_rate(lcdc_dev->dclk, dotclk);
1272 pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
1273 lcdc_dev->pixclock = pixclock;
1274 dev_drv->pixclock = pixclock;
1275 fps = rk_fb_calc_fps(lcdc_dev->screen, pixclock);
1276 screen->ft = 1000 / fps; /*one frame time in ms */
1279 dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__,
1280 clk_get_rate(lcdc_dev->dclk), fps);
1285 static int rk3036_lcdc_poll_vblank(struct rk_lcdc_driver *dev_drv)
1287 struct lcdc_device *lcdc_dev =
1288 container_of(dev_drv, struct lcdc_device, driver);
1292 if (lcdc_dev->clk_on) {
1293 int_reg = lcdc_readl(lcdc_dev, INT_STATUS);
1294 if (int_reg & m_LF_INT_STA) {
1295 lcdc_msk_reg(lcdc_dev, INT_STATUS, m_LF_INT_CLEAR,
1297 ret = RK_LF_STATUS_FC;
1299 ret = RK_LF_STATUS_FR;
1302 ret = RK_LF_STATUS_NC;
1308 static int rk3036_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv,
1309 unsigned int *dsp_addr)
1311 struct lcdc_device *lcdc_dev =
1312 container_of(dev_drv, struct lcdc_device, driver);
1314 if (lcdc_dev->clk_on) {
1315 dsp_addr[0] = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
1316 dsp_addr[1] = lcdc_readl(lcdc_dev, WIN1_MST);
1321 static ssize_t rk3036_lcdc_get_disp_info(struct rk_lcdc_driver *dev_drv,
1322 char *buf, int win_id)
1324 struct rk_lcdc_win *win = NULL;
1325 char fmt[9] = "NULL";
1328 if (win_id < ARRAY_SIZE(lcdc_win)) {
1329 win = dev_drv->win[win_id];
1331 dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id);
1335 size = snprintf(buf, PAGE_SIZE, "win%d: %s\n", win_id,
1336 get_format_string(win->format, fmt));
1337 size += snprintf(buf + size, PAGE_SIZE - size,
1338 " xact %d yact %d xvir %d yvir %d\n",
1339 win->area[0].xact, win->area[0].yact,
1340 win->area[0].xvir, win->area[0].yvir);
1341 size += snprintf(buf + size, PAGE_SIZE - size,
1342 " xpos %d ypos %d xsize %d ysize %d\n",
1343 win->area[0].xpos, win->area[0].ypos,
1344 win->area[0].xsize, win->area[0].ysize);
1345 size += snprintf(buf + size, PAGE_SIZE - size,
1346 " yaddr 0x%x uvaddr 0x%x\n",
1347 win->area[0].y_addr, win->area[0].uv_addr);
1351 static int rk3036_lcdc_reg_dump(struct rk_lcdc_driver *dev_drv)
1353 struct lcdc_device *lcdc_dev = container_of(dev_drv,
1356 int *cbase = (int *)lcdc_dev->regs;
1357 int *regsbak = (int *)lcdc_dev->regsbak;
1360 dev_info(dev_drv->dev, "back up reg:\n");
1361 for (i = 0; i <= (0xDC >> 4); i++) {
1362 for (j = 0; j < 4; j++)
1363 dev_info(dev_drv->dev, "%08x ",
1364 *(regsbak + i * 4 + j));
1365 dev_info(dev_drv->dev, "\n");
1368 dev_info(dev_drv->dev, "lcdc reg:\n");
1369 for (i = 0; i <= (0xDC >> 4); i++) {
1370 for (j = 0; j < 4; j++)
1371 dev_info(dev_drv->dev, "%08x ",
1372 readl_relaxed(cbase + i * 4 + j));
1373 dev_info(dev_drv->dev, "\n");
1378 static struct rk_lcdc_drv_ops lcdc_drv_ops = {
1379 .open = rk3036_lcdc_open,
1380 .load_screen = rk3036_load_screen,
1381 .set_par = rk3036_lcdc_set_par,
1382 .pan_display = rk3036_lcdc_pan_display,
1383 .blank = rk3036_lcdc_blank,
1384 .ioctl = rk3036_lcdc_ioctl,
1385 .get_win_state = rk3036_lcdc_get_win_state,
1386 .ovl_mgr = rk3036_lcdc_ovl_mgr,
1387 .get_disp_info = rk3036_lcdc_get_disp_info,
1388 .fps_mgr = rk3036_lcdc_fps_mgr,
1389 .fb_get_win_id = rk3036_lcdc_get_win_id,
1390 .fb_win_remap = rk3036_fb_win_remap,
1391 .poll_vblank = rk3036_lcdc_poll_vblank,
1392 .get_dsp_addr = rk3036_lcdc_get_dsp_addr,
1393 .cfg_done = rk3036_lcdc_cfg_done,
1394 .dump_reg = rk3036_lcdc_reg_dump,
1395 .set_dsp_bcsh_hue = rk3036_lcdc_set_bcsh_hue,
1396 .set_dsp_bcsh_bcs = rk3036_lcdc_set_bcsh_bcs,
1397 .get_dsp_bcsh_hue = rk3036_lcdc_get_bcsh_hue,
1398 .get_dsp_bcsh_bcs = rk3036_lcdc_get_bcsh_bcs,
1399 .open_bcsh = rk3036_lcdc_open_bcsh,
1400 .set_overscan = rk3036_lcdc_set_overscan,
1403 static int rk3036_lcdc_parse_dt(struct lcdc_device *lcdc_dev)
1405 #if defined(CONFIG_ROCKCHIP_IOMMU)
1406 struct device_node *np = lcdc_dev->dev->of_node;
1409 if (of_property_read_u32(np, "rockchip,iommu-enabled", &val))
1410 lcdc_dev->driver.iommu_enabled = 0;
1412 lcdc_dev->driver.iommu_enabled = val;
1414 lcdc_dev->driver.iommu_enabled = 0;
1419 static int rk3036_lcdc_probe(struct platform_device *pdev)
1421 struct lcdc_device *lcdc_dev = NULL;
1422 struct rk_lcdc_driver *dev_drv;
1423 struct device *dev = &pdev->dev;
1424 struct resource *res;
1427 lcdc_dev = devm_kzalloc(dev,
1428 sizeof(struct lcdc_device), GFP_KERNEL);
1430 dev_err(&pdev->dev, "rk3036 lcdc device kmalloc fail!");
1433 platform_set_drvdata(pdev, lcdc_dev);
1434 lcdc_dev->dev = dev;
1435 rk3036_lcdc_parse_dt(lcdc_dev);
1437 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1438 lcdc_dev->reg_phy_base = res->start;
1439 lcdc_dev->len = resource_size(res);
1440 lcdc_dev->regs = devm_ioremap_resource(dev, res);
1441 if (IS_ERR(lcdc_dev->regs))
1442 return PTR_ERR(lcdc_dev->regs);
1444 lcdc_dev->regsbak = devm_kzalloc(dev, lcdc_dev->len, GFP_KERNEL);
1445 if (IS_ERR(lcdc_dev->regsbak))
1446 return PTR_ERR(lcdc_dev->regsbak);
1448 dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
1449 dev_drv = &lcdc_dev->driver;
1451 dev_drv->prop = PRMRY;
1452 dev_drv->id = lcdc_dev->id;
1453 dev_drv->ops = &lcdc_drv_ops;
1454 dev_drv->lcdc_win_num = ARRAY_SIZE(lcdc_win);
1455 spin_lock_init(&lcdc_dev->reg_lock);
1457 lcdc_dev->irq = platform_get_irq(pdev, 0);
1458 if (lcdc_dev->irq < 0) {
1459 dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n",
1464 ret = devm_request_irq(dev, lcdc_dev->irq, rk3036_lcdc_isr,
1465 IRQF_DISABLED | IRQF_SHARED,
1466 dev_name(dev), lcdc_dev);
1468 dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n",
1469 lcdc_dev->irq, ret);
1473 if (dev_drv->iommu_enabled)
1474 strcpy(dev_drv->mmu_dts_name, VOP_IOMMU_COMPATIBLE_NAME);
1476 ret = rk_fb_register(dev_drv, lcdc_win, lcdc_dev->id);
1478 dev_err(dev, "register fb for lcdc%d failed!\n", lcdc_dev->id);
1481 lcdc_dev->screen = dev_drv->screen0;
1483 dev_info(dev, "lcdc probe ok, iommu %s\n",
1484 dev_drv->iommu_enabled ? "enabled" : "disabled");
1489 #if defined(CONFIG_PM)
1490 static int rk3036_lcdc_suspend(struct platform_device *pdev,
1496 static int rk3036_lcdc_resume(struct platform_device *pdev)
1501 #define rk3036_lcdc_suspend NULL
1502 #define rk3036_lcdc_resume NULL
1505 static int rk3036_lcdc_remove(struct platform_device *pdev)
1510 static void rk3036_lcdc_shutdown(struct platform_device *pdev)
1514 #if defined(CONFIG_OF)
1515 static const struct of_device_id rk3036_lcdc_dt_ids[] = {
1516 {.compatible = "rockchip,rk3036-lcdc",},
1521 static struct platform_driver rk3036_lcdc_driver = {
1522 .probe = rk3036_lcdc_probe,
1523 .remove = rk3036_lcdc_remove,
1525 .name = "rk3036-lcdc",
1526 .owner = THIS_MODULE,
1527 .of_match_table = of_match_ptr(rk3036_lcdc_dt_ids),
1529 .suspend = rk3036_lcdc_suspend,
1530 .resume = rk3036_lcdc_resume,
1531 .shutdown = rk3036_lcdc_shutdown,
1534 static int __init rk3036_lcdc_module_init(void)
1536 return platform_driver_register(&rk3036_lcdc_driver);
1539 static void __exit rk3036_lcdc_module_exit(void)
1541 platform_driver_unregister(&rk3036_lcdc_driver);
1544 fs_initcall(rk3036_lcdc_module_init);
1545 module_exit(rk3036_lcdc_module_exit);