4 * Copyright (C) ROCKCHIP, Inc.
5 * Author:yzq<yzq@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/kernel.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/clk.h>
21 #include <linux/of_device.h>
22 #include <linux/pm_runtime.h>
24 #include <video/of_display_timing.h>
25 #include <drm/rockchip_drm.h>
26 #include <linux/rockchip/cpu.h>
27 #include <linux/rockchip/iomap.h>
28 #include <linux/rk_fb.h>
29 #include <video/display_timing.h>
30 #include <linux/rockchip/cpu.h>
31 #include <linux/rockchip/iomap.h>
32 #include <linux/rockchip/grf.h>
33 #include "rockchip_drm_drv.h"
34 #include "rockchip_drm_fbdev.h"
35 #include "rockchip_drm_crtc.h"
36 #include "rockchip_drm_iommu.h"
39 * FIMD is stand for Fully Interactive Mobile Display and
40 * as a display controller, it transfers contents drawn on memory
41 * to a LCD Panel through Display Interfaces such as RGB or
45 /* position control register for hardware window 0, 2 ~ 4.*/
46 #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16)
47 #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16)
49 * size control register for hardware windows 0 and alpha control register
50 * for hardware windows 1 ~ 4
52 #define VIDOSD_C(win) (VIDOSD_BASE + 0x08 + (win) * 16)
53 /* size control register for hardware windows 1 ~ 2. */
54 #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16)
56 #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8)
57 #define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8)
58 #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4)
60 /* color key control register for hardware window 1 ~ 4. */
61 #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + ((x - 1) * 8))
62 /* color key value register for hardware window 1 ~ 4. */
63 #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8))
65 /* FIMD has totally five hardware windows. */
67 /*****************************************************************************************************/
68 #define SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT 12 /* 4.12*/
69 #define SCALE_FACTOR_BILI_DN_FIXPOINT(x) ((INT32)((x)*(1 << SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT)))
71 #define SCALE_FACTOR_BILI_UP_FIXPOINT_SHIFT 16 /* 0.16*/
73 #define SCALE_FACTOR_AVRG_FIXPOINT_SHIFT 16 /*0.16*/
74 #define SCALE_FACTOR_AVRG_FIXPOINT(x) ((INT32)((x)*(1 << SCALE_FACTOR_AVRG_FIXPOINT_SHIFT)))
76 #define SCALE_FACTOR_BIC_FIXPOINT_SHIFT 16 /* 0.16*/
77 #define SCALE_FACTOR_BIC_FIXPOINT(x) ((INT32)((x)*(1 << SCALE_FACTOR_BIC_FIXPOINT_SHIFT)))
79 #define SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT 12 /*NONE SCALE,vsd_bil*/
80 #define SCALE_FACTOR_VSDBIL_FIXPOINT_SHIFT 12 /*VER SCALE DOWN BIL*/
82 /*****************************************************************************************************/
84 /*#define GET_SCALE_FACTOR_BILI(src, dst) ((((src) - 1) << SCALE_FACTOR_BILI_FIXPOINT_SHIFT) / ((dst) - 1))*/
85 /*#define GET_SCALE_FACTOR_BIC(src, dst) ((((src) - 1) << SCALE_FACTOR_BIC_FIXPOINT_SHIFT) / ((dst) - 1))*/
87 #define GET_SCALE_FACTOR_BILI_DN(src, dst) ((((src)*2 - 3) << (SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT-1)) / ((dst) - 1))
88 #define GET_SCALE_FACTOR_BILI_UP(src, dst) ((((src)*2 - 3) << (SCALE_FACTOR_BILI_UP_FIXPOINT_SHIFT-1)) / ((dst) - 1))
89 #define GET_SCALE_FACTOR_BIC(src, dst) ((((src)*2 - 3) << (SCALE_FACTOR_BIC_FIXPOINT_SHIFT-1)) / ((dst) - 1))
91 #define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev))
93 static struct rk_fb_trsm_ops *trsm_lvds_ops;
94 static struct rk_fb_trsm_ops *trsm_edp_ops;
95 static struct rk_fb_trsm_ops *trsm_mipi_ops;
97 int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
102 case SCREEN_DUAL_LVDS:
109 case SCREEN_DUAL_MIPI:
113 printk(KERN_WARNING "%s:un supported transmitter:%d!\n",
119 struct fimd_driver_data {
120 unsigned int timing_base;
123 static struct fimd_driver_data rockchip4_fimd_driver_data = {
127 static struct fimd_driver_data rockchip5_fimd_driver_data = {
128 .timing_base = 0x20000,
131 struct fimd_win_data {
132 unsigned int offset_x;
133 unsigned int offset_y;
134 unsigned int ovl_width;
135 unsigned int ovl_height;
136 unsigned int fb_width;
137 unsigned int fb_height;
140 unsigned int buf_offsize;
141 unsigned int line_size; /* bytes */
146 struct fimd_context {
147 struct rockchip_drm_subdrv subdrv;
149 struct drm_crtc *crtc;
150 struct clk *pd; //lcdc power domain
151 struct clk *hclk; //lcdc AHP clk
152 struct clk *dclk; //lcdc dclk
153 struct clk *aclk; //lcdc share memory frequency
155 struct fimd_win_data win_data[WINDOWS_NR];
157 unsigned int default_win;
158 unsigned long irq_flags;
164 wait_queue_head_t wait_vsync_queue;
165 atomic_t wait_vsync_event;
168 void *regsbak; //back up reg
169 struct rockchip_drm_panel_info *panel;
170 struct rk_screen *screen;
173 #include "rk3288_drm_fimd.h"
174 static int rk3288_lcdc_get_id(u32 phy_base)
176 if (cpu_is_rk3288()) {
177 if (phy_base == 0xff930000)/*vop big*/
179 else if (phy_base == 0xff940000)/*vop lit*/
184 pr_err("un supported platform \n");
190 static bool fimd_display_is_connected(struct device *dev)
192 DRM_DEBUG_KMS("%s\n", __FILE__);
199 static void *fimd_get_panel(struct device *dev)
201 struct fimd_context *ctx = get_fimd_context(dev);
203 DRM_DEBUG_KMS("%s\n", __FILE__);
208 static int fimd_check_timing(struct device *dev, void *timing)
210 DRM_DEBUG_KMS("%s\n", __FILE__);
217 static int fimd_display_power_on(struct device *dev, int mode)
219 DRM_DEBUG_KMS("%s\n", __FILE__);
226 static struct rockchip_drm_display_ops fimd_display_ops = {
227 .type = ROCKCHIP_DISPLAY_TYPE_LCD,
228 .is_connected = fimd_display_is_connected,
229 .get_panel = fimd_get_panel,
230 .check_timing = fimd_check_timing,
231 .power_on = fimd_display_power_on,
234 static void fimd_dpms(struct device *subdrv_dev, int mode)
236 struct fimd_context *ctx = get_fimd_context(subdrv_dev);
238 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
240 mutex_lock(&ctx->lock);
243 case DRM_MODE_DPMS_ON:
245 * enable fimd hardware only if suspended status.
247 * P.S. fimd_dpms function would be called at booting time so
248 * clk_enable could be called double time.
251 if(trsm_lvds_ops != NULL){
252 printk(KERN_ERR"------>yzq enable lvds\n");
253 trsm_lvds_ops->enable();
256 pm_runtime_get_sync(subdrv_dev);
258 case DRM_MODE_DPMS_STANDBY:
259 case DRM_MODE_DPMS_SUSPEND:
260 case DRM_MODE_DPMS_OFF:
262 pm_runtime_put_sync(subdrv_dev);
265 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
269 mutex_unlock(&ctx->lock);
272 static void fimd_apply(struct device *subdrv_dev)
274 struct fimd_context *ctx = get_fimd_context(subdrv_dev);
275 struct rockchip_drm_manager *mgr = ctx->subdrv.manager;
276 struct rockchip_drm_manager_ops *mgr_ops = mgr->ops;
277 struct rockchip_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
278 struct fimd_win_data *win_data;
281 DRM_DEBUG_KMS("%s\n", __FILE__);
283 for (i = 0; i < WINDOWS_NR; i++) {
284 win_data = &ctx->win_data[i];
285 if (win_data->enabled && (ovl_ops && ovl_ops->commit))
286 ovl_ops->commit(subdrv_dev, i);
289 if (mgr_ops && mgr_ops->commit)
290 mgr_ops->commit(subdrv_dev);
293 static int rk3288_lcdc_alpha_cfg(struct fimd_context *ctx,int win_id)
295 struct alpha_config alpha_config;
296 struct fimd_win_data *win_data;
297 enum alpha_mode alpha_mode;
299 int ppixel_alpha,global_alpha;
300 u32 src_alpha_ctl,dst_alpha_ctl;
303 win_data = &ctx->win_data[win_id];
304 ppixel_alpha = (win_data->bpp==32) ? 1 : 0;
306 alpha_config.src_global_alpha_val = 1;
307 alpha_mode = AB_SRC_OVER;
308 global_alpha = (g_alpha_val == 0) ? 0 : 1;
309 alpha_config.src_global_alpha_val = g_alpha_val;
310 /*printk("%s,alpha_mode=%d,alpha_en=%d,ppixel_a=%d,gla_a=%d\n",
311 __func__,win->alpha_mode,win->alpha_en,ppixel_alpha,global_alpha);*/
316 alpha_config.src_factor_mode=AA_ZERO;
317 alpha_config.dst_factor_mode=AA_ZERO;
320 alpha_config.src_factor_mode=AA_ONE;
321 alpha_config.dst_factor_mode=AA_ZERO;
324 alpha_config.src_factor_mode=AA_ZERO;
325 alpha_config.dst_factor_mode=AA_ONE;
328 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
329 alpha_config.src_factor_mode=AA_ONE;
330 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
333 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
334 alpha_config.src_factor_mode=AA_SRC_INVERSE;
335 alpha_config.dst_factor_mode=AA_ONE;
338 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
339 alpha_config.src_factor_mode=AA_SRC;
340 alpha_config.dst_factor_mode=AA_ZERO;
343 alpha_config.src_factor_mode=AA_ZERO;
344 alpha_config.dst_factor_mode=AA_SRC;
347 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
348 alpha_config.src_factor_mode=AA_SRC_INVERSE;
349 alpha_config.dst_factor_mode=AA_ZERO;
352 alpha_config.src_factor_mode=AA_ZERO;
353 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
356 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
357 alpha_config.src_factor_mode=AA_SRC;
358 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
361 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
362 alpha_config.src_factor_mode=AA_SRC_INVERSE;
363 alpha_config.dst_factor_mode=AA_SRC;
366 alpha_config.src_color_mode=AA_SRC_PRE_MUL;
367 alpha_config.src_factor_mode=AA_SRC_INVERSE;
368 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
370 case AB_SRC_OVER_GLOBAL:
371 alpha_config.src_global_alpha_mode=AA_PER_PIX_GLOBAL;
372 alpha_config.src_color_mode=AA_SRC_NO_PRE_MUL;
373 alpha_config.src_factor_mode=AA_SRC_GLOBAL;
374 alpha_config.dst_factor_mode=AA_SRC_INVERSE;
377 pr_err("alpha mode error\n");
380 if((ppixel_alpha == 1)&&(global_alpha == 1)){
381 alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL;
382 }else if(ppixel_alpha == 1){
383 alpha_config.src_global_alpha_mode = AA_PER_PIX;
384 }else if(global_alpha == 1){
385 alpha_config.src_global_alpha_mode = AA_GLOBAL;
387 pr_err("alpha_en should be 0\n");
389 alpha_config.src_alpha_mode = AA_STRAIGHT;
390 alpha_config.src_alpha_cal_m0 = AA_NO_SAT;
394 src_alpha_ctl = 0x60;
395 dst_alpha_ctl = 0x64;
398 src_alpha_ctl = 0xa0;
399 dst_alpha_ctl = 0xa4;
402 src_alpha_ctl = 0xdc;
403 dst_alpha_ctl = 0xec;
406 src_alpha_ctl = 0x12c;
407 dst_alpha_ctl = 0x13c;
410 mask = m_WIN0_DST_FACTOR_M0;
411 val = v_WIN0_DST_FACTOR_M0(alpha_config.dst_factor_mode);
412 lcdc_msk_reg(ctx, dst_alpha_ctl, mask, val);
413 mask = m_WIN0_SRC_ALPHA_EN | m_WIN0_SRC_COLOR_M0 |
414 m_WIN0_SRC_ALPHA_M0 | m_WIN0_SRC_BLEND_M0 |
415 m_WIN0_SRC_ALPHA_CAL_M0 | m_WIN0_SRC_FACTOR_M0|
416 m_WIN0_SRC_GLOBAL_ALPHA;
417 val = v_WIN0_SRC_ALPHA_EN(1) |
418 v_WIN0_SRC_COLOR_M0(alpha_config.src_color_mode) |
419 v_WIN0_SRC_ALPHA_M0(alpha_config.src_alpha_mode) |
420 v_WIN0_SRC_BLEND_M0(alpha_config.src_global_alpha_mode) |
421 v_WIN0_SRC_ALPHA_CAL_M0(alpha_config.src_alpha_cal_m0) |
422 v_WIN0_SRC_FACTOR_M0(alpha_config.src_factor_mode) |
423 v_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val);
424 lcdc_msk_reg(ctx, src_alpha_ctl, mask, val);
428 static int rk3288_win_0_1_reg_update(struct fimd_context *ctx,int win_id)
430 struct fimd_win_data *win_data;
431 unsigned int mask, val, off;
432 struct rk_screen *screen = ctx->screen;
436 win_data = &ctx->win_data[win_id];
437 switch(win_data->bpp){
448 printk("not support format %d\n",win_data->bpp);
452 xpos = win_data->offset_x + screen->mode.left_margin + screen->mode.hsync_len;
453 ypos = win_data->offset_y + screen->mode.upper_margin + screen->mode.vsync_len;
454 mask = m_WIN0_EN | m_WIN0_DATA_FMT ;
455 val = v_WIN0_EN(1) | v_WIN0_DATA_FMT(fmt_cfg);
456 lcdc_msk_reg(ctx, WIN0_CTRL0+off, mask,val);
458 val = v_WIN0_VIR_STRIDE(win_data->fb_width);
459 lcdc_writel(ctx, WIN0_VIR+off, val);
460 val = v_WIN0_ACT_WIDTH(win_data->fb_width) |
461 v_WIN0_ACT_HEIGHT(win_data->fb_height);
462 lcdc_writel(ctx, WIN0_ACT_INFO+off, val);
464 val = v_WIN0_DSP_WIDTH(win_data->ovl_width) |
465 v_WIN0_DSP_HEIGHT(win_data->ovl_height);
466 lcdc_writel(ctx, WIN0_DSP_INFO+off, val);
468 val = v_WIN0_DSP_XST(xpos) |
469 v_WIN0_DSP_YST(ypos);
470 lcdc_writel(ctx, WIN0_DSP_ST+off, val);
471 lcdc_writel(ctx, WIN0_YRGB_MST+off, win_data->dma_addr );
474 rk3288_lcdc_alpha_cfg(ctx,win_id);
479 static int rk3288_lcdc_post_cfg(struct fimd_context *ctx)
481 struct rk_screen *screen = ctx->screen;
482 u16 x_res = screen->mode.xres;
483 u16 y_res = screen->mode.yres;
486 u16 post_hsd_en,post_vsd_en;
487 u16 post_dsp_hact_st,post_dsp_hact_end;
488 u16 post_dsp_vact_st,post_dsp_vact_end;
489 u16 post_dsp_vact_st_f1,post_dsp_vact_end_f1;
490 u16 post_h_fac,post_v_fac;
492 h_total = screen->mode.hsync_len+screen->mode.left_margin +
493 x_res + screen->mode.right_margin;
494 v_total = screen->mode.vsync_len+screen->mode.upper_margin +
495 y_res + screen->mode.lower_margin;
497 if(screen->post_dsp_stx + screen->post_xsize > x_res){
498 printk(KERN_ERR"post:stx[%d] + xsize[%d] > x_res[%d]\n",
499 screen->post_dsp_stx,screen->post_xsize,x_res);
500 screen->post_dsp_stx = x_res - screen->post_xsize;
502 if(screen->x_mirror == 0){
503 post_dsp_hact_st=screen->post_dsp_stx +
504 screen->mode.hsync_len+screen->mode.left_margin;
505 post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize;
507 post_dsp_hact_end = h_total - screen->mode.right_margin -
508 screen->post_dsp_stx;
509 post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize;
511 if((screen->post_xsize < x_res)&&(screen->post_xsize != 0)){
514 GET_SCALE_FACTOR_BILI_DN(x_res , screen->post_xsize);
521 if(screen->post_dsp_sty + screen->post_ysize > y_res){
522 printk(KERN_ERR "post:sty[%d] + ysize[%d] > y_res[%d]\n",
523 screen->post_dsp_sty,screen->post_ysize,y_res);
524 screen->post_dsp_sty = y_res - screen->post_ysize;
527 if(screen->y_mirror == 0){
528 post_dsp_vact_st = screen->post_dsp_sty +
529 screen->mode.vsync_len+screen->mode.upper_margin;
530 post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
532 post_dsp_vact_end = v_total - screen->mode.lower_margin -
533 - screen->post_dsp_sty;
534 post_dsp_hact_st = post_dsp_vact_end - screen->post_ysize;
536 if((screen->post_ysize < y_res)&&(screen->post_ysize != 0)){
538 post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res, screen->post_ysize);
544 if(screen->interlace == 1){
545 post_dsp_vact_st_f1 = v_total + post_dsp_vact_st;
546 post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
548 post_dsp_vact_st_f1 = 0;
549 post_dsp_vact_end_f1 = 0;
551 printk(KERN_ERR"post:xsize=%d,ysize=%d,xpos=%d,ypos=%d,"
552 "hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n",
553 screen->post_xsize,screen->post_ysize,screen->xpos,screen->ypos,
554 post_hsd_en,post_h_fac,post_vsd_en,post_v_fac);
555 mask = m_DSP_HACT_END_POST | m_DSP_HACT_ST_POST;
556 val = v_DSP_HACT_END_POST(post_dsp_hact_end) |
557 v_DSP_HACT_ST_POST(post_dsp_hact_st);
558 lcdc_msk_reg(ctx, POST_DSP_HACT_INFO, mask, val);
560 mask = m_DSP_VACT_END_POST | m_DSP_VACT_ST_POST;
561 val = v_DSP_VACT_END_POST(post_dsp_vact_end) |
562 v_DSP_VACT_ST_POST(post_dsp_vact_st);
563 lcdc_msk_reg(ctx, POST_DSP_VACT_INFO, mask, val);
565 mask = m_POST_HS_FACTOR_YRGB | m_POST_VS_FACTOR_YRGB;
566 val = v_POST_HS_FACTOR_YRGB(post_h_fac) |
567 v_POST_VS_FACTOR_YRGB(post_v_fac);
568 lcdc_msk_reg(ctx, POST_SCL_FACTOR_YRGB, mask, val);
570 mask = m_DSP_VACT_END_POST_F1 | m_DSP_VACT_ST_POST_F1;
571 val = v_DSP_VACT_END_POST_F1(post_dsp_vact_end_f1) |
572 v_DSP_VACT_ST_POST_F1(post_dsp_vact_st_f1);
573 lcdc_msk_reg(ctx, POST_DSP_VACT_INFO_F1, mask, val);
575 mask = m_POST_HOR_SD_EN | m_POST_VER_SD_EN;
576 val = v_POST_HOR_SD_EN(post_hsd_en) | v_POST_VER_SD_EN(post_vsd_en);
577 lcdc_msk_reg(ctx, POST_SCL_CTRL, mask, val);
580 static void fimd_commit(struct device *dev)
582 struct fimd_context *ctx = get_fimd_context(dev);
583 struct rockchip_drm_panel_info *panel = ctx->panel;
584 struct rk_screen *screen = ctx->screen;
585 u16 hsync_len = screen->mode.hsync_len;
586 u16 left_margin = screen->mode.left_margin;
587 u16 right_margin = screen->mode.right_margin;
588 u16 vsync_len = screen->mode.vsync_len;
589 u16 upper_margin = screen->mode.upper_margin;
590 u16 lower_margin = screen->mode.lower_margin;
591 u16 x_res = screen->mode.xres;
592 u16 y_res = screen->mode.yres;
597 h_total = hsync_len + left_margin + x_res + right_margin;
598 v_total = vsync_len + upper_margin + y_res + lower_margin;
599 screen->post_dsp_stx=0;
600 screen->post_dsp_sty=0;
601 screen->post_xsize =x_res;
602 screen->post_ysize = y_res;
604 printk(KERN_ERR"%s %d\n", __func__,__LINE__);
608 printk(KERN_ERR"%s %d\n", __func__,__LINE__);
612 switch (screen->face) {
615 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
617 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
618 v_DITHER_DOWN_SEL(1);
619 lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
623 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
625 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
626 v_DITHER_DOWN_SEL(1);
627 lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
631 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
633 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0) |
634 v_DITHER_DOWN_SEL(1);
635 lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
639 mask = m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE |
641 val = v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1) |
642 v_DITHER_DOWN_SEL(1);
643 lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
647 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
648 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
649 lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
652 printk("un supported interface!\n");
655 switch(screen->type){
658 case SCREEN_DUAL_LVDS:
660 val = v_RGB_OUT_EN(1);
662 v |= (ctx->lcdc_id << 3);
665 mask = m_HDMI_OUT_EN;
666 val = v_HDMI_OUT_EN(1);
668 v |= (ctx->id << 4);*/
671 mask = m_MIPI_OUT_EN;
672 val = v_MIPI_OUT_EN(1);
673 /*v = (1 << (6+16))||(1 << (9+16));
675 v |= (ctx->id << 9);*/
677 case SCREEN_DUAL_MIPI:
678 mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
679 val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
680 /*v = (1 << (6+16))||(1 << (9+16));
682 v |= (ctx->id << 9);*/
685 face = OUT_RGB_AAA; /*RGB AAA output*/
686 mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
687 val = v_DITHER_DOWN_EN(0) | v_DITHER_UP_EN(0);
688 lcdc_msk_reg(ctx, DSP_CTRL1, mask, val);
690 val = v_EDP_OUT_EN(1);
692 v |= (ctx->id << 5);*/
695 lcdc_msk_reg(ctx, SYS_CTRL, mask, val);
699 lcdc_msk_reg(ctx, SYS_CTRL, mask, val);
700 mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
701 val = v_AXI_OUTSTANDING_MAX_NUM(31) | v_AXI_MAX_OUTSTANDING_EN(1);
702 lcdc_msk_reg(ctx, SYS_CTRL1, mask, val);
704 writel_relaxed(v, RK_GRF_VIRT + RK3288_GRF_SOC_CON6);
705 mask = m_DSP_OUT_MODE | m_DSP_HSYNC_POL | m_DSP_VSYNC_POL |
706 m_DSP_DEN_POL | m_DSP_DCLK_POL | m_DSP_BG_SWAP |
707 m_DSP_RB_SWAP | m_DSP_RG_SWAP | m_DSP_DELTA_SWAP |
708 m_DSP_DUMMY_SWAP | m_DSP_OUT_ZERO | m_DSP_BLANK_EN |
709 m_DSP_BLACK_EN | m_DSP_X_MIR_EN | m_DSP_Y_MIR_EN;
710 val = v_DSP_OUT_MODE(face) | v_DSP_HSYNC_POL(screen->pin_hsync) |
711 v_DSP_VSYNC_POL(screen->pin_vsync) |
712 v_DSP_DEN_POL(screen->pin_den) | v_DSP_DCLK_POL(screen->pin_dclk) |
713 v_DSP_BG_SWAP(screen->swap_gb) | v_DSP_RB_SWAP(screen->swap_rb) |
714 v_DSP_RG_SWAP(screen->swap_rg) |
715 v_DSP_DELTA_SWAP(screen->swap_delta) |
716 v_DSP_DUMMY_SWAP(screen->swap_dumy) | v_DSP_OUT_ZERO(0) |
717 v_DSP_BLANK_EN(0) | v_DSP_BLACK_EN(0) |
718 v_DSP_X_MIR_EN(screen->x_mirror) | v_DSP_Y_MIR_EN(screen->y_mirror);
719 lcdc_msk_reg(ctx, DSP_CTRL0, mask, val);
721 mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
722 val = v_DSP_BG_BLUE(0x3ff) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
723 lcdc_msk_reg(ctx, DSP_BG, mask, val);
725 mask = m_DSP_HS_PW | m_DSP_HTOTAL;
726 val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
727 lcdc_msk_reg(ctx, DSP_HTOTAL_HS_END, mask, val);
729 mask = m_DSP_HACT_END | m_DSP_HACT_ST;
730 val = v_DSP_HACT_END(hsync_len + left_margin + x_res) |
731 v_DSP_HACT_ST(hsync_len + left_margin);
732 lcdc_msk_reg(ctx, DSP_HACT_ST_END, mask, val);
734 mask = m_DSP_VS_PW | m_DSP_VTOTAL;
735 val = v_DSP_VS_PW(vsync_len) | v_DSP_VTOTAL(v_total);
736 lcdc_msk_reg(ctx, DSP_VTOTAL_VS_END, mask, val);
738 mask = m_DSP_VACT_END | m_DSP_VACT_ST;
739 val = v_DSP_VACT_END(vsync_len + upper_margin + y_res) |
740 v_DSP_VACT_ST(vsync_len + upper_margin);
741 lcdc_msk_reg(ctx, DSP_VACT_ST_END, mask, val);
743 rk3288_lcdc_post_cfg(ctx);
747 static int fimd_enable_vblank(struct device *dev)
749 struct fimd_context *ctx = get_fimd_context(dev);
752 DRM_DEBUG_KMS("%s\n", __FILE__);
757 if (!test_and_set_bit(0, &ctx->irq_flags)) {
758 mask = m_FS_INTR_CLR | m_FS_INTR_EN | m_LINE_FLAG_INTR_CLR |
759 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_CLR |
760 m_BUS_ERROR_INTR_EN | m_DSP_LINE_FLAG_NUM;
761 val = v_FS_INTR_CLR(1) | v_FS_INTR_EN(1) | v_LINE_FLAG_INTR_CLR(0) |
762 v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_CLR(0) | v_BUS_ERROR_INTR_EN(0) ;
763 lcdc_msk_reg(ctx, INTR_CTRL0, mask, val);
770 static void fimd_disable_vblank(struct device *dev)
772 struct fimd_context *ctx = get_fimd_context(dev);
775 DRM_DEBUG_KMS("%s\n", __FILE__);
780 if (test_and_clear_bit(0, &ctx->irq_flags)) {
781 mask = m_DSP_HOLD_VALID_INTR_EN | m_FS_INTR_EN |
782 m_LINE_FLAG_INTR_EN | m_BUS_ERROR_INTR_EN;
783 val = v_DSP_HOLD_VALID_INTR_EN(0) | v_FS_INTR_EN(0) |
784 v_LINE_FLAG_INTR_EN(0) | v_BUS_ERROR_INTR_EN(0);
785 lcdc_msk_reg(ctx, INTR_CTRL0, mask, val);
787 mask = m_DSP_HOLD_VALID_INTR_CLR | m_FS_INTR_CLR |
788 m_LINE_FLAG_INTR_CLR | m_LINE_FLAG_INTR_CLR;
789 val = v_DSP_HOLD_VALID_INTR_CLR(0) | v_FS_INTR_CLR(0) |
790 v_LINE_FLAG_INTR_CLR(0) | v_BUS_ERROR_INTR_CLR(0);
791 lcdc_msk_reg(ctx, INTR_CTRL0, mask, val);
793 mask = m_WIN0_EMPTY_INTR_EN | m_WIN1_EMPTY_INTR_EN |
794 m_WIN2_EMPTY_INTR_EN | m_WIN3_EMPTY_INTR_EN |
795 m_HWC_EMPTY_INTR_EN | m_POST_BUF_EMPTY_INTR_EN |
796 m_POST_BUF_EMPTY_INTR_EN;
797 val = v_WIN0_EMPTY_INTR_EN(0) | v_WIN1_EMPTY_INTR_EN(0) |
798 v_WIN2_EMPTY_INTR_EN(0) | v_WIN3_EMPTY_INTR_EN(0) |
799 v_HWC_EMPTY_INTR_EN(0) | v_POST_BUF_EMPTY_INTR_EN(0) |
800 v_PWM_GEN_INTR_EN(0);
801 lcdc_msk_reg(ctx, INTR_CTRL1, mask, val);
803 mask = m_WIN0_EMPTY_INTR_CLR | m_WIN1_EMPTY_INTR_CLR |
804 m_WIN2_EMPTY_INTR_CLR | m_WIN3_EMPTY_INTR_CLR |
805 m_HWC_EMPTY_INTR_CLR | m_POST_BUF_EMPTY_INTR_CLR |
806 m_POST_BUF_EMPTY_INTR_CLR;
807 val = v_WIN0_EMPTY_INTR_CLR(0) | v_WIN1_EMPTY_INTR_CLR(0) |
808 v_WIN2_EMPTY_INTR_CLR(0) | v_WIN3_EMPTY_INTR_CLR(0) |
809 v_HWC_EMPTY_INTR_CLR(0) | v_POST_BUF_EMPTY_INTR_CLR(0) |
810 v_PWM_GEN_INTR_CLR(0);
811 lcdc_msk_reg(ctx, INTR_CTRL1, mask, val);
818 static void fimd_wait_for_vblank(struct device *dev)
820 struct fimd_context *ctx = get_fimd_context(dev);
825 atomic_set(&ctx->wait_vsync_event, 1);
828 * wait for FIMD to signal VSYNC interrupt or return after
829 * timeout which is set to 50ms (refresh rate of 20).
831 if (!wait_event_timeout(ctx->wait_vsync_queue,
832 !atomic_read(&ctx->wait_vsync_event),
834 DRM_DEBUG_KMS("vblank wait timed out.\n");
837 static struct rockchip_drm_manager_ops fimd_manager_ops = {
840 .commit = fimd_commit,
841 .enable_vblank = fimd_enable_vblank,
842 .disable_vblank = fimd_disable_vblank,
843 .wait_for_vblank = fimd_wait_for_vblank,
846 static void fimd_win_mode_set(struct device *dev,
847 struct rockchip_drm_overlay *overlay)
849 struct fimd_context *ctx = get_fimd_context(dev);
850 struct fimd_win_data *win_data;
852 unsigned long offset;
854 DRM_DEBUG_KMS("%s\n", __FILE__);
857 dev_err(dev, "overlay is NULL\n");
862 if (win == DEFAULT_ZPOS)
863 win = ctx->default_win;
865 if (win < 0 || win > WINDOWS_NR)
868 offset = overlay->fb_x * (overlay->bpp >> 3);
869 offset += overlay->fb_y * overlay->pitch;
871 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
873 win_data = &ctx->win_data[win];
875 win_data->offset_x = overlay->crtc_x;
876 win_data->offset_y = overlay->crtc_y;
877 win_data->ovl_width = overlay->crtc_width;
878 win_data->ovl_height = overlay->crtc_height;
879 win_data->fb_width = overlay->fb_width;
880 win_data->fb_height = overlay->fb_height;
881 win_data->dma_addr = overlay->dma_addr[0] + offset;
882 win_data->bpp = overlay->bpp;
883 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
885 win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
887 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
888 win_data->offset_x, win_data->offset_y);
889 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
890 win_data->ovl_width, win_data->ovl_height);
891 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
892 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
893 overlay->fb_width, overlay->crtc_width);
896 static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
898 struct fimd_context *ctx = get_fimd_context(dev);
899 struct fimd_win_data *win_data = &ctx->win_data[win];
903 DRM_DEBUG_KMS("%s\n", __FILE__);
904 switch(win_data->bpp){
915 printk("not support format %d\n",win_data->bpp);
920 printk(KERN_ERR"------>yzq %d SYS_CTRL=%x \n",__LINE__,lcdc_readl(ctx,SYS_CTRL));
921 lcdc_msk_reg(ctx , SYS_CTRL, m_WIN0_FORMAT, v_WIN0_FORMAT(fmt_cfg));
922 printk(KERN_ERR"------>yzq %d SYS_CTRL=%x \n",__LINE__,lcdc_readl(ctx,SYS_CTRL));
926 static void fimd_win_set_colkey(struct device *dev, unsigned int win)
928 // struct fimd_context *ctx = get_fimd_context(dev);
930 DRM_DEBUG_KMS("%s\n", __FILE__);
934 static void fimd_win_commit(struct device *dev, int zpos)
936 struct fimd_context *ctx = get_fimd_context(dev);
937 struct fimd_win_data *win_data;
938 struct rk_screen *screen = ctx->screen;
940 unsigned long val, size;
943 // printk(KERN_ERR"%s %d\n", __func__,__LINE__);
950 // printk(KERN_ERR"%s %d\n", __func__,__LINE__);
951 if (win == DEFAULT_ZPOS)
952 win = ctx->default_win;
954 if (win < 0 || win > WINDOWS_NR)
957 win_data = &ctx->win_data[win];
960 rk3288_win_0_1_reg_update(ctx,0);
963 // printk(KERN_ERR"-->yzq dma_addr=%x buf_offsize=%x win_data->fb_width=%d \nwin_data->fb_height=%d win_data->ovl_height=%d win_data->ovl_width=%d \n win_data->offset_x=%d win_data->offset_y=%d win_data->line_size=%d\n win_data->bpp=%d ",win_data->dma_addr,win_data->buf_offsize,win_data->fb_width,win_data->fb_height,win_data->ovl_height, win_data->ovl_width,win_data->offset_x,win_data->offset_y,win_data->line_size,win_data->bpp);
964 rk3288_win_0_1_reg_update(ctx,1);
967 printk("----->yzq not support now win_id=%d\n",win);
968 // rk3288_win_2_3_reg_update(ctx,2);
971 printk("----->yzq not support now win_id=%d\n",win);
972 // rk3288_win_2_3_reg_update(ctx,3);
975 printk("----->yzq not support now win_id=%d\n",win);
978 // printk("----->yzq now win_id=%d\n",win);
980 //rk3288_lcdc_post_cfg(screen);
981 win_data->enabled = true;
985 static void fimd_win_disable(struct device *dev, int zpos)
987 struct fimd_context *ctx = get_fimd_context(dev);
988 struct fimd_win_data *win_data;
991 DRM_DEBUG_KMS("%s\n", __FILE__);
993 if (win == DEFAULT_ZPOS)
994 win = ctx->default_win;
996 if (win < 0 || win > WINDOWS_NR)
999 win_data = &ctx->win_data[win];
1001 if (ctx->suspended) {
1002 /* do not resume this window*/
1003 win_data->resume = false;
1007 win_data->enabled = false;
1010 static struct rockchip_drm_overlay_ops fimd_overlay_ops = {
1011 .mode_set = fimd_win_mode_set,
1012 .commit = fimd_win_commit,
1013 .disable = fimd_win_disable,
1016 static struct rockchip_drm_manager fimd_manager = {
1018 .ops = &fimd_manager_ops,
1019 .overlay_ops = &fimd_overlay_ops,
1020 .display_ops = &fimd_display_ops,
1023 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
1025 struct fimd_context *ctx = (struct fimd_context *)dev_id;
1026 struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
1027 struct drm_device *drm_dev = subdrv->drm_dev;
1028 struct rockchip_drm_manager *manager = subdrv->manager;
1031 intr0_reg = lcdc_readl(ctx, INTR_CTRL0);
1033 if(intr0_reg & m_FS_INTR_STS){
1034 lcdc_msk_reg(ctx, INTR_CTRL0, m_FS_INTR_CLR,
1039 /* check the crtc is detached already from encoder */
1040 if (manager->pipe < 0)
1043 drm_handle_vblank(drm_dev, manager->pipe);
1044 rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
1046 /* set wait vsync event to zero and wake up queue. */
1047 if (atomic_read(&ctx->wait_vsync_event)) {
1048 atomic_set(&ctx->wait_vsync_event, 0);
1049 DRM_WAKEUP(&ctx->wait_vsync_queue);
1055 static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
1057 DRM_DEBUG_KMS("%s\n", __FILE__);
1060 * enable drm irq mode.
1061 * - with irq_enabled = 1, we can use the vblank feature.
1063 * P.S. note that we wouldn't use drm irq handler but
1064 * just specific driver own one instead because
1065 * drm framework supports only one irq handler.
1067 drm_dev->irq_enabled = 1;
1070 * with vblank_disable_allowed = 1, vblank interrupt will be disabled
1071 * by drm timer once a current process gives up ownership of
1072 * vblank event.(after drm_vblank_put function is called)
1074 drm_dev->vblank_disable_allowed = 1;
1076 /* attach this sub driver to iommu mapping if supported. */
1077 if (is_drm_iommu_supported(drm_dev))
1078 drm_iommu_attach_device(drm_dev, dev);
1083 static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
1085 DRM_DEBUG_KMS("%s\n", __FILE__);
1087 /* detach this sub driver from iommu mapping if supported. */
1088 if (is_drm_iommu_supported(drm_dev))
1089 drm_iommu_detach_device(drm_dev, dev);
1093 static void fimd_clear_win(struct fimd_context *ctx, int win)
1097 DRM_DEBUG_KMS("%s\n", __FILE__);
1101 static int fimd_clock(struct fimd_context *ctx, bool enable)
1103 DRM_DEBUG_KMS("%s\n", __FILE__);
1104 printk(KERN_ERR"---->yzq %s %d \n",__func__,__LINE__);
1110 ret = clk_prepare_enable(ctx->hclk);
1114 ret = clk_prepare_enable(ctx->dclk);
1118 ret = clk_prepare_enable(ctx->aclk);
1125 clk_disable_unprepare(ctx->aclk);
1126 clk_disable_unprepare(ctx->dclk);
1127 clk_disable_unprepare(ctx->hclk);
1134 static void fimd_window_suspend(struct device *dev)
1136 struct fimd_context *ctx = get_fimd_context(dev);
1137 struct fimd_win_data *win_data;
1140 for (i = 0; i < WINDOWS_NR; i++) {
1141 win_data = &ctx->win_data[i];
1142 win_data->resume = win_data->enabled;
1143 fimd_win_disable(dev, i);
1145 fimd_wait_for_vblank(dev);
1148 static void fimd_window_resume(struct device *dev)
1150 struct fimd_context *ctx = get_fimd_context(dev);
1151 struct fimd_win_data *win_data;
1154 for (i = 0; i < WINDOWS_NR; i++) {
1155 win_data = &ctx->win_data[i];
1156 win_data->enabled = win_data->resume;
1157 win_data->resume = false;
1161 static int fimd_activate(struct fimd_context *ctx, bool enable)
1163 struct device *dev = ctx->subdrv.dev;
1167 ret = fimd_clock(ctx, true);
1171 ctx->suspended = false;
1173 /* if vblank was enabled status, enable it again. */
1174 if (test_and_clear_bit(0, &ctx->irq_flags))
1175 fimd_enable_vblank(dev);
1177 fimd_window_resume(dev);
1179 fimd_window_suspend(dev);
1181 fimd_clock(ctx, false);
1182 ctx->suspended = true;
1188 int rk_fb_video_mode_from_timing(const struct display_timing *dt,
1189 struct rk_screen *screen)
1191 screen->mode.pixclock = dt->pixelclock.typ;
1192 screen->mode.left_margin = dt->hback_porch.typ;
1193 screen->mode.right_margin = dt->hfront_porch.typ;
1194 screen->mode.xres = dt->hactive.typ;
1195 screen->mode.hsync_len = dt->hsync_len.typ;
1196 screen->mode.upper_margin = dt->vback_porch.typ;
1197 screen->mode.lower_margin = dt->vfront_porch.typ;
1198 screen->mode.yres = dt->vactive.typ;
1199 screen->mode.vsync_len = dt->vsync_len.typ;
1200 screen->type = SCREEN_LVDS;
1201 screen->lvds_format = LVDS_8BIT_2;
1202 screen->face = OUT_D888_P666;
1204 if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
1205 screen->pin_dclk = 1;
1207 screen->pin_dclk = 0;
1208 if(dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
1209 screen->pin_hsync = 1;
1211 screen->pin_hsync = 0;
1212 if(dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
1213 screen->pin_vsync = 1;
1215 screen->pin_vsync = 0;
1216 if(dt->flags & DISPLAY_FLAGS_DE_HIGH)
1217 screen->pin_den = 1;
1219 screen->pin_den = 0;
1225 int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
1227 struct display_timings *disp_timing;
1228 struct display_timing *dt;
1229 disp_timing = of_get_display_timings(np);
1231 pr_err("parse display timing err\n");
1234 dt = display_timings_get(disp_timing, 0);
1235 rk_fb_video_mode_from_timing(dt, screen);
1236 printk(KERN_ERR "dclk:%d\n"
1250 dt->hback_porch.typ,
1251 dt->hfront_porch.typ,
1254 dt->vback_porch.typ,
1255 dt->vfront_porch.typ,
1264 static int fimd_probe(struct platform_device *pdev)
1266 struct device *dev = &pdev->dev;
1267 struct fimd_context *ctx;
1268 struct rockchip_drm_subdrv *subdrv;
1269 struct rockchip_drm_fimd_pdata *pdata;
1270 struct rockchip_drm_panel_info *panel;
1271 struct device_node *np = pdev->dev.of_node;
1272 struct rk_screen *screen;
1275 struct resource *res;
1280 DRM_DEBUG_KMS("%s\n", __FILE__);
1281 of_property_read_u32(np, "rockchip,prop", &prop);
1282 if (prop == EXTEND) {
1283 printk("---->%s not support lcdc EXTEND now\n",__func__);
1286 if (of_property_read_u32(np, "rockchip,pwr18", &val))
1288 printk("----->%s default set it as 3.xv power supply",__func__);
1292 printk("----->%s lcdc pwr is 1.8, not supply now",__func__);
1294 printk("----->%s lcdc pwr is 3.3v",__func__);
1299 panel = devm_kzalloc(dev, sizeof(struct rockchip_drm_panel_info), GFP_KERNEL);
1300 screen = devm_kzalloc(dev, sizeof(struct rk_screen), GFP_KERNEL);
1301 rk_fb_get_prmry_screen(screen);
1302 memcpy(&panel->timing,&screen->mode,sizeof(struct fb_videomode));
1304 DRM_ERROR("no platform data specified\n");
1308 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1312 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1314 ctx->regs = devm_ioremap_resource(dev, res);
1315 if (IS_ERR(ctx->regs))
1316 return PTR_ERR(ctx->regs);
1317 reg_len = resource_size(res);
1318 ctx->regsbak = devm_kzalloc(dev,reg_len,GFP_KERNEL);
1319 ctx->lcdc_id = rk3288_lcdc_get_id(res->start);
1320 ctx->screen = screen;
1321 ctx->hclk = devm_clk_get(dev, "hclk_lcdc");
1322 ctx->aclk = devm_clk_get(dev, "aclk_lcdc");
1323 ctx->dclk = devm_clk_get(dev, "dclk_lcdc");
1325 ctx->irq = platform_get_irq(pdev, 0);
1327 dev_err(dev, "cannot find IRQ for lcdc%d\n",
1331 ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler,
1332 0, "drm_fimd", ctx);
1334 dev_err(dev, "irq request failed.\n");
1338 ctx->default_win = 0;// pdata->default_win;
1340 DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
1341 atomic_set(&ctx->wait_vsync_event, 0);
1343 subdrv = &ctx->subdrv;
1346 subdrv->manager = &fimd_manager;
1347 subdrv->probe = fimd_subdrv_probe;
1348 subdrv->remove = fimd_subdrv_remove;
1350 mutex_init(&ctx->lock);
1352 platform_set_drvdata(pdev, ctx);
1354 pm_runtime_enable(dev);
1355 pm_runtime_get_sync(dev);
1357 ret = clk_set_rate(ctx->dclk, ctx->screen->mode.pixclock);
1359 printk( "set lcdc%d dclk failed\n", ctx->lcdc_id);
1361 fimd_activate(ctx, true);
1363 if(trsm_lvds_ops != NULL){
1364 printk(KERN_ERR"------>yzq enable lvds\n");
1365 trsm_lvds_ops->enable();
1367 memcpy(ctx->regsbak,ctx->regs,reg_len);
1368 rockchip_drm_subdrv_register(subdrv);
1373 static int fimd_remove(struct platform_device *pdev)
1375 struct device *dev = &pdev->dev;
1376 struct fimd_context *ctx = platform_get_drvdata(pdev);
1378 DRM_DEBUG_KMS("%s\n", __FILE__);
1380 rockchip_drm_subdrv_unregister(&ctx->subdrv);
1385 pm_runtime_set_suspended(dev);
1386 pm_runtime_put_sync(dev);
1389 pm_runtime_disable(dev);
1394 #ifdef CONFIG_PM_SLEEP
1395 static int fimd_suspend(struct device *dev)
1397 struct fimd_context *ctx = get_fimd_context(dev);
1400 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
1401 * called here, an error would be returned by that interface
1402 * because the usage_count of pm runtime is more than 1.
1404 if (!pm_runtime_suspended(dev))
1405 return fimd_activate(ctx, false);
1410 static int fimd_resume(struct device *dev)
1412 struct fimd_context *ctx = get_fimd_context(dev);
1415 * if entered to sleep when lcd panel was on, the usage_count
1416 * of pm runtime would still be 1 so in this case, fimd driver
1417 * should be on directly not drawing on pm runtime interface.
1419 if (!pm_runtime_suspended(dev)) {
1422 ret = fimd_activate(ctx, true);
1427 * in case of dpms on(standby), fimd_apply function will
1428 * be called by encoder's dpms callback to update fimd's
1429 * registers but in case of sleep wakeup, it's not.
1430 * so fimd_apply function should be called at here.
1439 #ifdef CONFIG_PM_RUNTIME
1440 static int fimd_runtime_suspend(struct device *dev)
1442 struct fimd_context *ctx = get_fimd_context(dev);
1444 DRM_DEBUG_KMS("%s\n", __FILE__);
1446 return fimd_activate(ctx, false);
1449 static int fimd_runtime_resume(struct device *dev)
1451 struct fimd_context *ctx = get_fimd_context(dev);
1453 DRM_DEBUG_KMS("%s\n", __FILE__);
1455 return fimd_activate(ctx, true);
1458 #if defined(CONFIG_OF)
1459 static const struct of_device_id rk3288_lcdc_dt_ids[] = {
1460 {.compatible = "rockchip,rk3288-lcdc",},
1465 static const struct dev_pm_ops fimd_pm_ops = {
1466 SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1467 SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1470 struct platform_driver fimd_driver = {
1471 .probe = fimd_probe,
1472 .remove = fimd_remove,
1473 .id_table = rk3288_lcdc_dt_ids,
1475 .name = "rk3288-lcdc",
1476 .owner = THIS_MODULE,
1478 .of_match_table = of_match_ptr(rk3288_lcdc_dt_ids),