1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
4 #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
8 #include "dpu_hw_mdss.h"
9 #include "dpu_hw_util.h"
11 /* using a file static variables for debugfs access */
12 static u32 dpu_hw_util_log_mask
= DPU_DBG_MASK_NONE
;
14 /* DPU_SCALER_QSEED3 */
15 #define QSEED3_HW_VERSION 0x00
16 #define QSEED3_OP_MODE 0x04
17 #define QSEED3_RGB2Y_COEFF 0x08
18 #define QSEED3_PHASE_INIT 0x0C
19 #define QSEED3_PHASE_STEP_Y_H 0x10
20 #define QSEED3_PHASE_STEP_Y_V 0x14
21 #define QSEED3_PHASE_STEP_UV_H 0x18
22 #define QSEED3_PHASE_STEP_UV_V 0x1C
23 #define QSEED3_PRELOAD 0x20
24 #define QSEED3_DE_SHARPEN 0x24
25 #define QSEED3_DE_SHARPEN_CTL 0x28
26 #define QSEED3_DE_SHAPE_CTL 0x2C
27 #define QSEED3_DE_THRESHOLD 0x30
28 #define QSEED3_DE_ADJUST_DATA_0 0x34
29 #define QSEED3_DE_ADJUST_DATA_1 0x38
30 #define QSEED3_DE_ADJUST_DATA_2 0x3C
31 #define QSEED3_SRC_SIZE_Y_RGB_A 0x40
32 #define QSEED3_SRC_SIZE_UV 0x44
33 #define QSEED3_DST_SIZE 0x48
34 #define QSEED3_COEF_LUT_CTRL 0x4C
35 #define QSEED3_COEF_LUT_SWAP_BIT 0
36 #define QSEED3_COEF_LUT_DIR_BIT 1
37 #define QSEED3_COEF_LUT_Y_CIR_BIT 2
38 #define QSEED3_COEF_LUT_UV_CIR_BIT 3
39 #define QSEED3_COEF_LUT_Y_SEP_BIT 4
40 #define QSEED3_COEF_LUT_UV_SEP_BIT 5
41 #define QSEED3_BUFFER_CTRL 0x50
42 #define QSEED3_CLK_CTRL0 0x54
43 #define QSEED3_CLK_CTRL1 0x58
44 #define QSEED3_CLK_STATUS 0x5C
45 #define QSEED3_PHASE_INIT_Y_H 0x90
46 #define QSEED3_PHASE_INIT_Y_V 0x94
47 #define QSEED3_PHASE_INIT_UV_H 0x98
48 #define QSEED3_PHASE_INIT_UV_V 0x9C
49 #define QSEED3_COEF_LUT 0x100
50 #define QSEED3_FILTERS 5
51 #define QSEED3_LUT_REGIONS 4
52 #define QSEED3_CIRCULAR_LUTS 9
53 #define QSEED3_SEPARABLE_LUTS 10
54 #define QSEED3_LUT_SIZE 60
55 #define QSEED3_ENABLE 2
56 #define QSEED3_DIR_LUT_SIZE (200 * sizeof(u32))
57 #define QSEED3_CIR_LUT_SIZE \
58 (QSEED3_LUT_SIZE * QSEED3_CIRCULAR_LUTS * sizeof(u32))
59 #define QSEED3_SEP_LUT_SIZE \
60 (QSEED3_LUT_SIZE * QSEED3_SEPARABLE_LUTS * sizeof(u32))
62 void dpu_reg_write(struct dpu_hw_blk_reg_map
*c
,
67 /* don't need to mutex protect this */
68 if (c
->log_mask
& dpu_hw_util_log_mask
)
69 DPU_DEBUG_DRIVER("[%s:0x%X] <= 0x%X\n",
70 name
, c
->blk_off
+ reg_off
, val
);
71 writel_relaxed(val
, c
->base_off
+ c
->blk_off
+ reg_off
);
74 int dpu_reg_read(struct dpu_hw_blk_reg_map
*c
, u32 reg_off
)
76 return readl_relaxed(c
->base_off
+ c
->blk_off
+ reg_off
);
79 u32
*dpu_hw_util_get_log_mask_ptr(void)
81 return &dpu_hw_util_log_mask
;
84 static void _dpu_hw_setup_scaler3_lut(struct dpu_hw_blk_reg_map
*c
,
85 struct dpu_hw_scaler3_cfg
*scaler3_cfg
, u32 offset
)
89 unsigned long lut_flags
;
90 u32 lut_addr
, lut_offset
, lut_len
;
91 u32
*lut
[QSEED3_FILTERS
] = {NULL
, NULL
, NULL
, NULL
, NULL
};
92 static const uint32_t off_tbl
[QSEED3_FILTERS
][QSEED3_LUT_REGIONS
][2] = {
93 {{18, 0x000}, {12, 0x120}, {12, 0x1E0}, {8, 0x2A0} },
94 {{6, 0x320}, {3, 0x3E0}, {3, 0x440}, {3, 0x4A0} },
95 {{6, 0x500}, {3, 0x5c0}, {3, 0x620}, {3, 0x680} },
96 {{6, 0x380}, {3, 0x410}, {3, 0x470}, {3, 0x4d0} },
97 {{6, 0x560}, {3, 0x5f0}, {3, 0x650}, {3, 0x6b0} },
100 lut_flags
= (unsigned long) scaler3_cfg
->lut_flag
;
101 if (test_bit(QSEED3_COEF_LUT_DIR_BIT
, &lut_flags
) &&
102 (scaler3_cfg
->dir_len
== QSEED3_DIR_LUT_SIZE
)) {
103 lut
[0] = scaler3_cfg
->dir_lut
;
106 if (test_bit(QSEED3_COEF_LUT_Y_CIR_BIT
, &lut_flags
) &&
107 (scaler3_cfg
->y_rgb_cir_lut_idx
< QSEED3_CIRCULAR_LUTS
) &&
108 (scaler3_cfg
->cir_len
== QSEED3_CIR_LUT_SIZE
)) {
109 lut
[1] = scaler3_cfg
->cir_lut
+
110 scaler3_cfg
->y_rgb_cir_lut_idx
* QSEED3_LUT_SIZE
;
113 if (test_bit(QSEED3_COEF_LUT_UV_CIR_BIT
, &lut_flags
) &&
114 (scaler3_cfg
->uv_cir_lut_idx
< QSEED3_CIRCULAR_LUTS
) &&
115 (scaler3_cfg
->cir_len
== QSEED3_CIR_LUT_SIZE
)) {
116 lut
[2] = scaler3_cfg
->cir_lut
+
117 scaler3_cfg
->uv_cir_lut_idx
* QSEED3_LUT_SIZE
;
120 if (test_bit(QSEED3_COEF_LUT_Y_SEP_BIT
, &lut_flags
) &&
121 (scaler3_cfg
->y_rgb_sep_lut_idx
< QSEED3_SEPARABLE_LUTS
) &&
122 (scaler3_cfg
->sep_len
== QSEED3_SEP_LUT_SIZE
)) {
123 lut
[3] = scaler3_cfg
->sep_lut
+
124 scaler3_cfg
->y_rgb_sep_lut_idx
* QSEED3_LUT_SIZE
;
127 if (test_bit(QSEED3_COEF_LUT_UV_SEP_BIT
, &lut_flags
) &&
128 (scaler3_cfg
->uv_sep_lut_idx
< QSEED3_SEPARABLE_LUTS
) &&
129 (scaler3_cfg
->sep_len
== QSEED3_SEP_LUT_SIZE
)) {
130 lut
[4] = scaler3_cfg
->sep_lut
+
131 scaler3_cfg
->uv_sep_lut_idx
* QSEED3_LUT_SIZE
;
136 for (filter
= 0; filter
< QSEED3_FILTERS
; filter
++) {
140 for (i
= 0; i
< QSEED3_LUT_REGIONS
; i
++) {
141 lut_addr
= QSEED3_COEF_LUT
+ offset
142 + off_tbl
[filter
][i
][1];
143 lut_len
= off_tbl
[filter
][i
][0] << 2;
144 for (j
= 0; j
< lut_len
; j
++) {
147 (lut
[filter
])[lut_offset
++]);
154 if (test_bit(QSEED3_COEF_LUT_SWAP_BIT
, &lut_flags
))
155 DPU_REG_WRITE(c
, QSEED3_COEF_LUT_CTRL
+ offset
, BIT(0));
159 static void _dpu_hw_setup_scaler3_de(struct dpu_hw_blk_reg_map
*c
,
160 struct dpu_hw_scaler3_de_cfg
*de_cfg
, u32 offset
)
162 u32 sharp_lvl
, sharp_ctl
, shape_ctl
, de_thr
;
163 u32 adjust_a
, adjust_b
, adjust_c
;
168 sharp_lvl
= (de_cfg
->sharpen_level1
& 0x1FF) |
169 ((de_cfg
->sharpen_level2
& 0x1FF) << 16);
171 sharp_ctl
= ((de_cfg
->limit
& 0xF) << 9) |
172 ((de_cfg
->prec_shift
& 0x7) << 13) |
173 ((de_cfg
->clip
& 0x7) << 16);
175 shape_ctl
= (de_cfg
->thr_quiet
& 0xFF) |
176 ((de_cfg
->thr_dieout
& 0x3FF) << 16);
178 de_thr
= (de_cfg
->thr_low
& 0x3FF) |
179 ((de_cfg
->thr_high
& 0x3FF) << 16);
181 adjust_a
= (de_cfg
->adjust_a
[0] & 0x3FF) |
182 ((de_cfg
->adjust_a
[1] & 0x3FF) << 10) |
183 ((de_cfg
->adjust_a
[2] & 0x3FF) << 20);
185 adjust_b
= (de_cfg
->adjust_b
[0] & 0x3FF) |
186 ((de_cfg
->adjust_b
[1] & 0x3FF) << 10) |
187 ((de_cfg
->adjust_b
[2] & 0x3FF) << 20);
189 adjust_c
= (de_cfg
->adjust_c
[0] & 0x3FF) |
190 ((de_cfg
->adjust_c
[1] & 0x3FF) << 10) |
191 ((de_cfg
->adjust_c
[2] & 0x3FF) << 20);
193 DPU_REG_WRITE(c
, QSEED3_DE_SHARPEN
+ offset
, sharp_lvl
);
194 DPU_REG_WRITE(c
, QSEED3_DE_SHARPEN_CTL
+ offset
, sharp_ctl
);
195 DPU_REG_WRITE(c
, QSEED3_DE_SHAPE_CTL
+ offset
, shape_ctl
);
196 DPU_REG_WRITE(c
, QSEED3_DE_THRESHOLD
+ offset
, de_thr
);
197 DPU_REG_WRITE(c
, QSEED3_DE_ADJUST_DATA_0
+ offset
, adjust_a
);
198 DPU_REG_WRITE(c
, QSEED3_DE_ADJUST_DATA_1
+ offset
, adjust_b
);
199 DPU_REG_WRITE(c
, QSEED3_DE_ADJUST_DATA_2
+ offset
, adjust_c
);
203 void dpu_hw_setup_scaler3(struct dpu_hw_blk_reg_map
*c
,
204 struct dpu_hw_scaler3_cfg
*scaler3_cfg
,
205 u32 scaler_offset
, u32 scaler_version
,
206 const struct dpu_format
*format
)
209 u32 phase_init
, preload
, src_y_rgb
, src_uv
, dst
;
211 if (!scaler3_cfg
->enable
)
215 op_mode
|= (scaler3_cfg
->y_rgb_filter_cfg
& 0x3) << 16;
217 if (format
&& DPU_FORMAT_IS_YUV(format
)) {
219 op_mode
|= (scaler3_cfg
->uv_filter_cfg
& 0x3) << 24;
222 op_mode
|= (scaler3_cfg
->blend_cfg
& 1) << 31;
223 op_mode
|= (scaler3_cfg
->dir_en
) ? BIT(4) : 0;
226 ((scaler3_cfg
->preload_x
[0] & 0x7F) << 0) |
227 ((scaler3_cfg
->preload_y
[0] & 0x7F) << 8) |
228 ((scaler3_cfg
->preload_x
[1] & 0x7F) << 16) |
229 ((scaler3_cfg
->preload_y
[1] & 0x7F) << 24);
231 src_y_rgb
= (scaler3_cfg
->src_width
[0] & 0x1FFFF) |
232 ((scaler3_cfg
->src_height
[0] & 0x1FFFF) << 16);
234 src_uv
= (scaler3_cfg
->src_width
[1] & 0x1FFFF) |
235 ((scaler3_cfg
->src_height
[1] & 0x1FFFF) << 16);
237 dst
= (scaler3_cfg
->dst_width
& 0x1FFFF) |
238 ((scaler3_cfg
->dst_height
& 0x1FFFF) << 16);
240 if (scaler3_cfg
->de
.enable
) {
241 _dpu_hw_setup_scaler3_de(c
, &scaler3_cfg
->de
, scaler_offset
);
245 if (scaler3_cfg
->lut_flag
)
246 _dpu_hw_setup_scaler3_lut(c
, scaler3_cfg
,
249 if (scaler_version
== 0x1002) {
251 ((scaler3_cfg
->init_phase_x
[0] & 0x3F) << 0) |
252 ((scaler3_cfg
->init_phase_y
[0] & 0x3F) << 8) |
253 ((scaler3_cfg
->init_phase_x
[1] & 0x3F) << 16) |
254 ((scaler3_cfg
->init_phase_y
[1] & 0x3F) << 24);
255 DPU_REG_WRITE(c
, QSEED3_PHASE_INIT
+ scaler_offset
, phase_init
);
257 DPU_REG_WRITE(c
, QSEED3_PHASE_INIT_Y_H
+ scaler_offset
,
258 scaler3_cfg
->init_phase_x
[0] & 0x1FFFFF);
259 DPU_REG_WRITE(c
, QSEED3_PHASE_INIT_Y_V
+ scaler_offset
,
260 scaler3_cfg
->init_phase_y
[0] & 0x1FFFFF);
261 DPU_REG_WRITE(c
, QSEED3_PHASE_INIT_UV_H
+ scaler_offset
,
262 scaler3_cfg
->init_phase_x
[1] & 0x1FFFFF);
263 DPU_REG_WRITE(c
, QSEED3_PHASE_INIT_UV_V
+ scaler_offset
,
264 scaler3_cfg
->init_phase_y
[1] & 0x1FFFFF);
267 DPU_REG_WRITE(c
, QSEED3_PHASE_STEP_Y_H
+ scaler_offset
,
268 scaler3_cfg
->phase_step_x
[0] & 0xFFFFFF);
270 DPU_REG_WRITE(c
, QSEED3_PHASE_STEP_Y_V
+ scaler_offset
,
271 scaler3_cfg
->phase_step_y
[0] & 0xFFFFFF);
273 DPU_REG_WRITE(c
, QSEED3_PHASE_STEP_UV_H
+ scaler_offset
,
274 scaler3_cfg
->phase_step_x
[1] & 0xFFFFFF);
276 DPU_REG_WRITE(c
, QSEED3_PHASE_STEP_UV_V
+ scaler_offset
,
277 scaler3_cfg
->phase_step_y
[1] & 0xFFFFFF);
279 DPU_REG_WRITE(c
, QSEED3_PRELOAD
+ scaler_offset
, preload
);
281 DPU_REG_WRITE(c
, QSEED3_SRC_SIZE_Y_RGB_A
+ scaler_offset
, src_y_rgb
);
283 DPU_REG_WRITE(c
, QSEED3_SRC_SIZE_UV
+ scaler_offset
, src_uv
);
285 DPU_REG_WRITE(c
, QSEED3_DST_SIZE
+ scaler_offset
, dst
);
288 if (format
&& !DPU_FORMAT_IS_DX(format
))
291 if (format
&& format
->alpha_enable
) {
293 if (scaler_version
== 0x1002)
294 op_mode
|= (scaler3_cfg
->alpha_filter_cfg
& 0x1) << 30;
296 op_mode
|= (scaler3_cfg
->alpha_filter_cfg
& 0x3) << 29;
299 DPU_REG_WRITE(c
, QSEED3_OP_MODE
+ scaler_offset
, op_mode
);
302 u32
dpu_hw_get_scaler3_ver(struct dpu_hw_blk_reg_map
*c
,
305 return DPU_REG_READ(c
, QSEED3_HW_VERSION
+ scaler_offset
);
308 void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map
*c
,
310 struct dpu_csc_cfg
*data
, bool csc10
)
312 static const u32 matrix_shift
= 7;
313 u32 clamp_shift
= csc10
? 16 : 8;
316 /* matrix coeff - convert S15.16 to S4.9 */
317 val
= ((data
->csc_mv
[0] >> matrix_shift
) & 0x1FFF) |
318 (((data
->csc_mv
[1] >> matrix_shift
) & 0x1FFF) << 16);
319 DPU_REG_WRITE(c
, csc_reg_off
, val
);
320 val
= ((data
->csc_mv
[2] >> matrix_shift
) & 0x1FFF) |
321 (((data
->csc_mv
[3] >> matrix_shift
) & 0x1FFF) << 16);
322 DPU_REG_WRITE(c
, csc_reg_off
+ 0x4, val
);
323 val
= ((data
->csc_mv
[4] >> matrix_shift
) & 0x1FFF) |
324 (((data
->csc_mv
[5] >> matrix_shift
) & 0x1FFF) << 16);
325 DPU_REG_WRITE(c
, csc_reg_off
+ 0x8, val
);
326 val
= ((data
->csc_mv
[6] >> matrix_shift
) & 0x1FFF) |
327 (((data
->csc_mv
[7] >> matrix_shift
) & 0x1FFF) << 16);
328 DPU_REG_WRITE(c
, csc_reg_off
+ 0xc, val
);
329 val
= (data
->csc_mv
[8] >> matrix_shift
) & 0x1FFF;
330 DPU_REG_WRITE(c
, csc_reg_off
+ 0x10, val
);
333 val
= (data
->csc_pre_lv
[0] << clamp_shift
) | data
->csc_pre_lv
[1];
334 DPU_REG_WRITE(c
, csc_reg_off
+ 0x14, val
);
335 val
= (data
->csc_pre_lv
[2] << clamp_shift
) | data
->csc_pre_lv
[3];
336 DPU_REG_WRITE(c
, csc_reg_off
+ 0x18, val
);
337 val
= (data
->csc_pre_lv
[4] << clamp_shift
) | data
->csc_pre_lv
[5];
338 DPU_REG_WRITE(c
, csc_reg_off
+ 0x1c, val
);
341 val
= (data
->csc_post_lv
[0] << clamp_shift
) | data
->csc_post_lv
[1];
342 DPU_REG_WRITE(c
, csc_reg_off
+ 0x20, val
);
343 val
= (data
->csc_post_lv
[2] << clamp_shift
) | data
->csc_post_lv
[3];
344 DPU_REG_WRITE(c
, csc_reg_off
+ 0x24, val
);
345 val
= (data
->csc_post_lv
[4] << clamp_shift
) | data
->csc_post_lv
[5];
346 DPU_REG_WRITE(c
, csc_reg_off
+ 0x28, val
);
349 DPU_REG_WRITE(c
, csc_reg_off
+ 0x2c, data
->csc_pre_bv
[0]);
350 DPU_REG_WRITE(c
, csc_reg_off
+ 0x30, data
->csc_pre_bv
[1]);
351 DPU_REG_WRITE(c
, csc_reg_off
+ 0x34, data
->csc_pre_bv
[2]);
354 DPU_REG_WRITE(c
, csc_reg_off
+ 0x38, data
->csc_post_bv
[0]);
355 DPU_REG_WRITE(c
, csc_reg_off
+ 0x3c, data
->csc_post_bv
[1]);
356 DPU_REG_WRITE(c
, csc_reg_off
+ 0x40, data
->csc_post_bv
[2]);