2 * Copyright 2015 Freescale Semiconductor, Inc.
4 * Freescale DCU drm device driver
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
12 #include <linux/clk.h>
13 #include <linux/regmap.h>
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_crtc.h>
19 #include <drm/drm_crtc_helper.h>
21 #include "fsl_dcu_drm_crtc.h"
22 #include "fsl_dcu_drm_drv.h"
23 #include "fsl_dcu_drm_plane.h"
25 static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc
*crtc
,
26 struct drm_crtc_state
*old_crtc_state
)
30 static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc
*crtc
,
31 struct drm_crtc_state
*state
)
36 static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc
*crtc
,
37 struct drm_crtc_state
*old_crtc_state
)
41 static void fsl_dcu_drm_disable_crtc(struct drm_crtc
*crtc
)
43 struct drm_device
*dev
= crtc
->dev
;
44 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
47 ret
= regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
48 DCU_MODE_DCU_MODE_MASK
,
49 DCU_MODE_DCU_MODE(DCU_MODE_OFF
));
51 dev_err(fsl_dev
->dev
, "Disable CRTC failed\n");
52 ret
= regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
53 DCU_UPDATE_MODE_READREG
);
55 dev_err(fsl_dev
->dev
, "Enable CRTC failed\n");
58 static void fsl_dcu_drm_crtc_enable(struct drm_crtc
*crtc
)
60 struct drm_device
*dev
= crtc
->dev
;
61 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
64 ret
= regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
65 DCU_MODE_DCU_MODE_MASK
,
66 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL
));
68 dev_err(fsl_dev
->dev
, "Enable CRTC failed\n");
69 ret
= regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
70 DCU_UPDATE_MODE_READREG
);
72 dev_err(fsl_dev
->dev
, "Enable CRTC failed\n");
75 static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc
*crtc
,
76 const struct drm_display_mode
*mode
,
77 struct drm_display_mode
*adjusted_mode
)
82 static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc
*crtc
)
84 struct drm_device
*dev
= crtc
->dev
;
85 struct fsl_dcu_drm_device
*fsl_dev
= dev
->dev_private
;
86 struct drm_display_mode
*mode
= &crtc
->state
->mode
;
87 unsigned int hbp
, hfp
, hsw
, vbp
, vfp
, vsw
, div
, index
;
91 index
= drm_crtc_index(crtc
);
92 dcuclk
= clk_get_rate(fsl_dev
->clk
);
93 div
= dcuclk
/ mode
->clock
/ 1000;
95 /* Configure timings: */
96 hbp
= mode
->htotal
- mode
->hsync_end
;
97 hfp
= mode
->hsync_start
- mode
->hdisplay
;
98 hsw
= mode
->hsync_end
- mode
->hsync_start
;
99 vbp
= mode
->vtotal
- mode
->vsync_end
;
100 vfp
= mode
->vsync_start
- mode
->vdisplay
;
101 vsw
= mode
->vsync_end
- mode
->vsync_start
;
103 ret
= regmap_write(fsl_dev
->regmap
, DCU_HSYN_PARA
,
104 DCU_HSYN_PARA_BP(hbp
) |
105 DCU_HSYN_PARA_PW(hsw
) |
106 DCU_HSYN_PARA_FP(hfp
));
109 ret
= regmap_write(fsl_dev
->regmap
, DCU_VSYN_PARA
,
110 DCU_VSYN_PARA_BP(vbp
) |
111 DCU_VSYN_PARA_PW(vsw
) |
112 DCU_VSYN_PARA_FP(vfp
));
115 ret
= regmap_write(fsl_dev
->regmap
, DCU_DISP_SIZE
,
116 DCU_DISP_SIZE_DELTA_Y(mode
->vdisplay
) |
117 DCU_DISP_SIZE_DELTA_X(mode
->hdisplay
));
120 ret
= regmap_write(fsl_dev
->regmap
, DCU_DIV_RATIO
, div
);
123 ret
= regmap_write(fsl_dev
->regmap
, DCU_SYN_POL
,
124 DCU_SYN_POL_INV_VS_LOW
| DCU_SYN_POL_INV_HS_LOW
);
127 ret
= regmap_write(fsl_dev
->regmap
, DCU_BGND
, DCU_BGND_R(0) |
128 DCU_BGND_G(0) | DCU_BGND_B(0));
131 ret
= regmap_write(fsl_dev
->regmap
, DCU_DCU_MODE
,
132 DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN
);
135 ret
= regmap_write(fsl_dev
->regmap
, DCU_THRESHOLD
,
136 DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL
) |
137 DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL
) |
138 DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL
));
141 ret
= regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
142 DCU_UPDATE_MODE_READREG
);
147 dev_err(dev
->dev
, "set DCU register failed\n");
150 static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs
= {
151 .atomic_begin
= fsl_dcu_drm_crtc_atomic_begin
,
152 .atomic_check
= fsl_dcu_drm_crtc_atomic_check
,
153 .atomic_flush
= fsl_dcu_drm_crtc_atomic_flush
,
154 .disable
= fsl_dcu_drm_disable_crtc
,
155 .enable
= fsl_dcu_drm_crtc_enable
,
156 .mode_fixup
= fsl_dcu_drm_crtc_mode_fixup
,
157 .mode_set_nofb
= fsl_dcu_drm_crtc_mode_set_nofb
,
160 static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs
= {
161 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
162 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
163 .destroy
= drm_crtc_cleanup
,
164 .page_flip
= drm_atomic_helper_page_flip
,
165 .reset
= drm_atomic_helper_crtc_reset
,
166 .set_config
= drm_atomic_helper_set_config
,
169 int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device
*fsl_dev
)
171 struct drm_plane
*primary
;
172 struct drm_crtc
*crtc
= &fsl_dev
->crtc
;
173 unsigned int i
, j
, reg_num
;
176 primary
= fsl_dcu_drm_primary_create_plane(fsl_dev
->drm
);
177 ret
= drm_crtc_init_with_planes(fsl_dev
->drm
, crtc
, primary
, NULL
,
178 &fsl_dcu_drm_crtc_funcs
, NULL
);
182 drm_crtc_helper_add(crtc
, &fsl_dcu_drm_crtc_helper_funcs
);
184 if (!strcmp(fsl_dev
->soc
->name
, "ls1021a"))
185 reg_num
= LS1021A_LAYER_REG_NUM
;
187 reg_num
= VF610_LAYER_REG_NUM
;
188 for (i
= 0; i
<= fsl_dev
->soc
->total_layer
; i
++) {
189 for (j
= 0; j
< reg_num
; j
++) {
190 ret
= regmap_write(fsl_dev
->regmap
,
191 DCU_CTRLDESCLN(i
, j
), 0);
196 ret
= regmap_update_bits(fsl_dev
->regmap
, DCU_DCU_MODE
,
197 DCU_MODE_DCU_MODE_MASK
,
198 DCU_MODE_DCU_MODE(DCU_MODE_OFF
));
201 ret
= regmap_write(fsl_dev
->regmap
, DCU_UPDATE_MODE
,
202 DCU_UPDATE_MODE_READREG
);
208 dev_err(fsl_dev
->dev
, "init DCU register failed\n");