1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
6 #include "dpu_hw_catalog.h"
7 #include "dpu_hw_intf.h"
10 #define INTF_TIMING_ENGINE_EN 0x000
11 #define INTF_CONFIG 0x004
12 #define INTF_HSYNC_CTL 0x008
13 #define INTF_VSYNC_PERIOD_F0 0x00C
14 #define INTF_VSYNC_PERIOD_F1 0x010
15 #define INTF_VSYNC_PULSE_WIDTH_F0 0x014
16 #define INTF_VSYNC_PULSE_WIDTH_F1 0x018
17 #define INTF_DISPLAY_V_START_F0 0x01C
18 #define INTF_DISPLAY_V_START_F1 0x020
19 #define INTF_DISPLAY_V_END_F0 0x024
20 #define INTF_DISPLAY_V_END_F1 0x028
21 #define INTF_ACTIVE_V_START_F0 0x02C
22 #define INTF_ACTIVE_V_START_F1 0x030
23 #define INTF_ACTIVE_V_END_F0 0x034
24 #define INTF_ACTIVE_V_END_F1 0x038
25 #define INTF_DISPLAY_HCTL 0x03C
26 #define INTF_ACTIVE_HCTL 0x040
27 #define INTF_BORDER_COLOR 0x044
28 #define INTF_UNDERFLOW_COLOR 0x048
29 #define INTF_HSYNC_SKEW 0x04C
30 #define INTF_POLARITY_CTL 0x050
31 #define INTF_TEST_CTL 0x054
32 #define INTF_TP_COLOR0 0x058
33 #define INTF_TP_COLOR1 0x05C
34 #define INTF_FRAME_LINE_COUNT_EN 0x0A8
35 #define INTF_FRAME_COUNT 0x0AC
36 #define INTF_LINE_COUNT 0x0B0
38 #define INTF_DEFLICKER_CONFIG 0x0F0
39 #define INTF_DEFLICKER_STRNG_COEFF 0x0F4
40 #define INTF_DEFLICKER_WEAK_COEFF 0x0F8
42 #define INTF_DSI_CMD_MODE_TRIGGER_EN 0x084
43 #define INTF_PANEL_FORMAT 0x090
44 #define INTF_TPG_ENABLE 0x100
45 #define INTF_TPG_MAIN_CONTROL 0x104
46 #define INTF_TPG_VIDEO_CONFIG 0x108
47 #define INTF_TPG_COMPONENT_LIMITS 0x10C
48 #define INTF_TPG_RECTANGLE 0x110
49 #define INTF_TPG_INITIAL_VALUE 0x114
50 #define INTF_TPG_BLK_WHITE_PATTERN_FRAMES 0x118
51 #define INTF_TPG_RGB_MAPPING 0x11C
52 #define INTF_PROG_FETCH_START 0x170
53 #define INTF_PROG_ROT_START 0x174
55 #define INTF_FRAME_LINE_COUNT_EN 0x0A8
56 #define INTF_FRAME_COUNT 0x0AC
57 #define INTF_LINE_COUNT 0x0B0
59 static struct dpu_intf_cfg
*_intf_offset(enum dpu_intf intf
,
60 struct dpu_mdss_cfg
*m
,
62 struct dpu_hw_blk_reg_map
*b
)
66 for (i
= 0; i
< m
->intf_count
; i
++) {
67 if ((intf
== m
->intf
[i
].id
) &&
68 (m
->intf
[i
].type
!= INTF_NONE
)) {
70 b
->blk_off
= m
->intf
[i
].base
;
71 b
->length
= m
->intf
[i
].len
;
72 b
->hwversion
= m
->hwversion
;
73 b
->log_mask
= DPU_DBG_MASK_INTF
;
78 return ERR_PTR(-EINVAL
);
81 static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf
*ctx
,
82 const struct intf_timing_params
*p
,
83 const struct dpu_format
*fmt
)
85 struct dpu_hw_blk_reg_map
*c
= &ctx
->hw
;
86 u32 hsync_period
, vsync_period
;
87 u32 display_v_start
, display_v_end
;
88 u32 hsync_start_x
, hsync_end_x
;
89 u32 active_h_start
, active_h_end
;
90 u32 active_v_start
, active_v_end
;
91 u32 active_hctl
, display_hctl
, hsync_ctl
;
92 u32 polarity_ctl
, den_polarity
, hsync_polarity
, vsync_polarity
;
96 /* read interface_cfg */
97 intf_cfg
= DPU_REG_READ(c
, INTF_CONFIG
);
98 hsync_period
= p
->hsync_pulse_width
+ p
->h_back_porch
+ p
->width
+
100 vsync_period
= p
->vsync_pulse_width
+ p
->v_back_porch
+ p
->height
+
103 display_v_start
= ((p
->vsync_pulse_width
+ p
->v_back_porch
) *
104 hsync_period
) + p
->hsync_skew
;
105 display_v_end
= ((vsync_period
- p
->v_front_porch
) * hsync_period
) +
108 if (ctx
->cap
->type
== INTF_EDP
|| ctx
->cap
->type
== INTF_DP
) {
109 display_v_start
+= p
->hsync_pulse_width
+ p
->h_back_porch
;
110 display_v_end
-= p
->h_front_porch
;
113 hsync_start_x
= p
->h_back_porch
+ p
->hsync_pulse_width
;
114 hsync_end_x
= hsync_period
- p
->h_front_porch
- 1;
116 if (p
->width
!= p
->xres
) {
117 active_h_start
= hsync_start_x
;
118 active_h_end
= active_h_start
+ p
->xres
- 1;
124 if (p
->height
!= p
->yres
) {
125 active_v_start
= display_v_start
;
126 active_v_end
= active_v_start
+ (p
->yres
* hsync_period
) - 1;
133 active_hctl
= (active_h_end
<< 16) | active_h_start
;
134 intf_cfg
|= BIT(29); /* ACTIVE_H_ENABLE */
140 intf_cfg
|= BIT(30); /* ACTIVE_V_ENABLE */
142 hsync_ctl
= (hsync_period
<< 16) | p
->hsync_pulse_width
;
143 display_hctl
= (hsync_end_x
<< 16) | hsync_start_x
;
146 if (ctx
->cap
->type
== INTF_HDMI
) {
147 hsync_polarity
= p
->yres
>= 720 ? 0 : 1;
148 vsync_polarity
= p
->yres
>= 720 ? 0 : 1;
153 polarity_ctl
= (den_polarity
<< 2) | /* DEN Polarity */
154 (vsync_polarity
<< 1) | /* VSYNC Polarity */
155 (hsync_polarity
<< 0); /* HSYNC Polarity */
157 if (!DPU_FORMAT_IS_YUV(fmt
))
158 panel_format
= (fmt
->bits
[C0_G_Y
] |
159 (fmt
->bits
[C1_B_Cb
] << 2) |
160 (fmt
->bits
[C2_R_Cr
] << 4) |
163 /* Interface treats all the pixel data in RGB888 format */
164 panel_format
= (COLOR_8BIT
|
169 DPU_REG_WRITE(c
, INTF_HSYNC_CTL
, hsync_ctl
);
170 DPU_REG_WRITE(c
, INTF_VSYNC_PERIOD_F0
, vsync_period
* hsync_period
);
171 DPU_REG_WRITE(c
, INTF_VSYNC_PULSE_WIDTH_F0
,
172 p
->vsync_pulse_width
* hsync_period
);
173 DPU_REG_WRITE(c
, INTF_DISPLAY_HCTL
, display_hctl
);
174 DPU_REG_WRITE(c
, INTF_DISPLAY_V_START_F0
, display_v_start
);
175 DPU_REG_WRITE(c
, INTF_DISPLAY_V_END_F0
, display_v_end
);
176 DPU_REG_WRITE(c
, INTF_ACTIVE_HCTL
, active_hctl
);
177 DPU_REG_WRITE(c
, INTF_ACTIVE_V_START_F0
, active_v_start
);
178 DPU_REG_WRITE(c
, INTF_ACTIVE_V_END_F0
, active_v_end
);
179 DPU_REG_WRITE(c
, INTF_BORDER_COLOR
, p
->border_clr
);
180 DPU_REG_WRITE(c
, INTF_UNDERFLOW_COLOR
, p
->underflow_clr
);
181 DPU_REG_WRITE(c
, INTF_HSYNC_SKEW
, p
->hsync_skew
);
182 DPU_REG_WRITE(c
, INTF_POLARITY_CTL
, polarity_ctl
);
183 DPU_REG_WRITE(c
, INTF_FRAME_LINE_COUNT_EN
, 0x3);
184 DPU_REG_WRITE(c
, INTF_CONFIG
, intf_cfg
);
185 DPU_REG_WRITE(c
, INTF_PANEL_FORMAT
, panel_format
);
188 static void dpu_hw_intf_enable_timing_engine(
189 struct dpu_hw_intf
*intf
,
192 struct dpu_hw_blk_reg_map
*c
= &intf
->hw
;
193 /* Note: Display interface select is handled in top block hw layer */
194 DPU_REG_WRITE(c
, INTF_TIMING_ENGINE_EN
, enable
!= 0);
197 static void dpu_hw_intf_setup_prg_fetch(
198 struct dpu_hw_intf
*intf
,
199 const struct intf_prog_fetch
*fetch
)
201 struct dpu_hw_blk_reg_map
*c
= &intf
->hw
;
205 * Fetch should always be outside the active lines. If the fetching
206 * is programmed within active region, hardware behavior is unknown.
209 fetch_enable
= DPU_REG_READ(c
, INTF_CONFIG
);
211 fetch_enable
|= BIT(31);
212 DPU_REG_WRITE(c
, INTF_PROG_FETCH_START
,
215 fetch_enable
&= ~BIT(31);
218 DPU_REG_WRITE(c
, INTF_CONFIG
, fetch_enable
);
221 static void dpu_hw_intf_get_status(
222 struct dpu_hw_intf
*intf
,
223 struct intf_status
*s
)
225 struct dpu_hw_blk_reg_map
*c
= &intf
->hw
;
227 s
->is_en
= DPU_REG_READ(c
, INTF_TIMING_ENGINE_EN
);
229 s
->frame_count
= DPU_REG_READ(c
, INTF_FRAME_COUNT
);
230 s
->line_count
= DPU_REG_READ(c
, INTF_LINE_COUNT
);
237 static u32
dpu_hw_intf_get_line_count(struct dpu_hw_intf
*intf
)
239 struct dpu_hw_blk_reg_map
*c
;
246 return DPU_REG_READ(c
, INTF_LINE_COUNT
);
249 static void _setup_intf_ops(struct dpu_hw_intf_ops
*ops
,
252 ops
->setup_timing_gen
= dpu_hw_intf_setup_timing_engine
;
253 ops
->setup_prg_fetch
= dpu_hw_intf_setup_prg_fetch
;
254 ops
->get_status
= dpu_hw_intf_get_status
;
255 ops
->enable_timing
= dpu_hw_intf_enable_timing_engine
;
256 ops
->get_line_count
= dpu_hw_intf_get_line_count
;
259 static struct dpu_hw_blk_ops dpu_hw_ops
;
261 struct dpu_hw_intf
*dpu_hw_intf_init(enum dpu_intf idx
,
263 struct dpu_mdss_cfg
*m
)
265 struct dpu_hw_intf
*c
;
266 struct dpu_intf_cfg
*cfg
;
268 c
= kzalloc(sizeof(*c
), GFP_KERNEL
);
270 return ERR_PTR(-ENOMEM
);
272 cfg
= _intf_offset(idx
, m
, addr
, &c
->hw
);
273 if (IS_ERR_OR_NULL(cfg
)) {
275 pr_err("failed to create dpu_hw_intf %d\n", idx
);
276 return ERR_PTR(-EINVAL
);
285 _setup_intf_ops(&c
->ops
, c
->cap
->features
);
287 dpu_hw_blk_init(&c
->base
, DPU_HW_BLK_INTF
, idx
, &dpu_hw_ops
);
292 void dpu_hw_intf_destroy(struct dpu_hw_intf
*intf
)
295 dpu_hw_blk_destroy(&intf
->base
);