2 * Copyright 2012-17 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "reg_helper.h"
30 #include "dcn20_dwb.h"
34 dwbc20->dwbc_regs->reg
40 dwbc20->base.ctx->logger
42 #define FN(reg_name, field_name) \
43 dwbc20->dwbc_shift->field_name, dwbc20->dwbc_mask->field_name
45 enum dwb_outside_pix_strategy
{
46 DWB_OUTSIDE_PIX_STRATEGY_BLACK
= 0,
47 DWB_OUTSIDE_PIX_STRATEGY_EDGE
= 1
50 static bool dwb2_get_caps(struct dwbc
*dwbc
, struct dwb_caps
*caps
)
52 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
54 caps
->adapter_id
= 0; /* we only support 1 adapter currently */
55 caps
->hw_version
= DCN_VERSION_2_0
;
57 memset(&caps
->reserved
, 0, sizeof(caps
->reserved
));
58 memset(&caps
->reserved2
, 0, sizeof(caps
->reserved2
));
59 caps
->sw_version
= dwb_ver_1_0
;
60 caps
->caps
.support_dwb
= true;
61 caps
->caps
.support_ogam
= false;
62 caps
->caps
.support_wbscl
= false;
63 caps
->caps
.support_ocsc
= false;
64 DC_LOG_DWB("%s SUPPORTED! inst = %d", __func__
, dwbc20
->base
.inst
);
67 DC_LOG_DWB("%s NOT SUPPORTED! inst = %d", __func__
, dwbc20
->base
.inst
);
72 void dwb2_config_dwb_cnv(struct dwbc
*dwbc
, struct dc_dwb_params
*params
)
74 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
75 DC_LOG_DWB("%s inst = %d", __func__
, dwbc20
->base
.inst
);
77 /* Set DWB source size */
78 REG_UPDATE_2(CNV_SOURCE_SIZE
, CNV_SOURCE_WIDTH
, params
->cnv_params
.src_width
,
79 CNV_SOURCE_HEIGHT
, params
->cnv_params
.src_height
);
81 /* source size is not equal the source size, then enable cropping. */
82 if (params
->cnv_params
.crop_en
) {
83 REG_UPDATE(CNV_MODE
, CNV_WINDOW_CROP_EN
, 1);
84 REG_UPDATE(CNV_WINDOW_START
, CNV_WINDOW_START_X
, params
->cnv_params
.crop_x
);
85 REG_UPDATE(CNV_WINDOW_START
, CNV_WINDOW_START_Y
, params
->cnv_params
.crop_y
);
86 REG_UPDATE(CNV_WINDOW_SIZE
, CNV_WINDOW_WIDTH
, params
->cnv_params
.crop_width
);
87 REG_UPDATE(CNV_WINDOW_SIZE
, CNV_WINDOW_HEIGHT
, params
->cnv_params
.crop_height
);
89 REG_UPDATE(CNV_MODE
, CNV_WINDOW_CROP_EN
, 0);
92 /* Set CAPTURE_RATE */
93 REG_UPDATE(CNV_MODE
, CNV_FRAME_CAPTURE_RATE
, params
->capture_rate
);
95 /* Set CNV output pixel depth */
96 REG_UPDATE(CNV_MODE
, CNV_OUT_BPC
, params
->cnv_params
.cnv_out_bpc
);
99 static bool dwb2_enable(struct dwbc
*dwbc
, struct dc_dwb_params
*params
)
101 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
103 /* Only chroma scaling (sub-sampling) is supported in DCN2 */
104 if ((params
->cnv_params
.src_width
!= params
->dest_width
) ||
105 (params
->cnv_params
.src_height
!= params
->dest_height
)) {
107 DC_LOG_DWB("%s inst = %d, FAILED!LUMA SCALING NOT SUPPORTED", __func__
, dwbc20
->base
.inst
);
110 DC_LOG_DWB("%s inst = %d, ENABLED", __func__
, dwbc20
->base
.inst
);
112 /* disable power gating */
113 //REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1,
114 // DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1,
115 // WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1);
117 /* Set WB_ENABLE (not double buffered; capture not enabled) */
118 REG_UPDATE(WB_ENABLE
, WB_ENABLE
, 1);
120 /* Set CNV parameters */
121 dwb2_config_dwb_cnv(dwbc
, params
);
123 /* Set scaling parameters */
124 dwb2_set_scaler(dwbc
, params
);
126 /* Enable DWB capture enable (double buffered) */
127 REG_UPDATE(CNV_MODE
, CNV_FRAME_CAPTURE_EN
, DWB_FRAME_CAPTURE_ENABLE
);
130 REG_UPDATE(WB_WARM_UP_MODE_CTL1
, GMC_WARM_UP_ENABLE
, 0);
135 bool dwb2_disable(struct dwbc
*dwbc
)
137 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
138 DC_LOG_DWB("%s inst = %d, Disabled", __func__
, dwbc20
->base
.inst
);
141 REG_UPDATE(CNV_MODE
, CNV_FRAME_CAPTURE_EN
, DWB_FRAME_CAPTURE_DISABLE
);
144 REG_UPDATE(WB_ENABLE
, WB_ENABLE
, 0);
147 REG_UPDATE(WB_SOFT_RESET
, WB_SOFT_RESET
, 1);
148 REG_UPDATE(WB_SOFT_RESET
, WB_SOFT_RESET
, 0);
150 /* enable power gating */
151 //REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0,
152 // DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0,
153 // WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0);
158 static bool dwb2_update(struct dwbc
*dwbc
, struct dc_dwb_params
*params
)
160 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
161 unsigned int pre_locked
;
163 /* Only chroma scaling (sub-sampling) is supported in DCN2 */
164 if ((params
->cnv_params
.src_width
!= params
->dest_width
) ||
165 (params
->cnv_params
.src_height
!= params
->dest_height
)) {
166 DC_LOG_DWB("%s inst = %d, FAILED!LUMA SCALING NOT SUPPORTED", __func__
, dwbc20
->base
.inst
);
169 DC_LOG_DWB("%s inst = %d, scaling", __func__
, dwbc20
->base
.inst
);
172 * Check if the caller has already locked CNV registers.
173 * If so: assume the caller will unlock, so don't touch the lock.
174 * If not: lock them for this update, then unlock after the
175 * update is complete.
177 REG_GET(CNV_UPDATE
, CNV_UPDATE_LOCK
, &pre_locked
);
179 if (pre_locked
== 0) {
180 /* Lock DWB registers */
181 REG_UPDATE(CNV_UPDATE
, CNV_UPDATE_LOCK
, 1);
184 /* Set CNV parameters */
185 dwb2_config_dwb_cnv(dwbc
, params
);
187 /* Set scaling parameters */
188 dwb2_set_scaler(dwbc
, params
);
190 if (pre_locked
== 0) {
191 /* Unlock DWB registers */
192 REG_UPDATE(CNV_UPDATE
, CNV_UPDATE_LOCK
, 0);
198 bool dwb2_is_enabled(struct dwbc
*dwbc
)
200 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
201 unsigned int wb_enabled
= 0;
202 unsigned int cnv_frame_capture_en
= 0;
204 REG_GET(WB_ENABLE
, WB_ENABLE
, &wb_enabled
);
205 REG_GET(CNV_MODE
, CNV_FRAME_CAPTURE_EN
, &cnv_frame_capture_en
);
207 return ((wb_enabled
!= 0) && (cnv_frame_capture_en
!= 0));
210 void dwb2_set_stereo(struct dwbc
*dwbc
,
211 struct dwb_stereo_params
*stereo_params
)
213 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
214 DC_LOG_DWB("%s inst = %d, enabled =%d", __func__
,\
215 dwbc20
->base
.inst
, stereo_params
->stereo_enabled
);
217 if (stereo_params
->stereo_enabled
) {
218 REG_UPDATE(CNV_MODE
, CNV_STEREO_TYPE
, stereo_params
->stereo_type
);
219 REG_UPDATE(CNV_MODE
, CNV_EYE_SELECTION
, stereo_params
->stereo_eye_select
);
220 REG_UPDATE(CNV_MODE
, CNV_STEREO_POLARITY
, stereo_params
->stereo_polarity
);
222 REG_UPDATE(CNV_MODE
, CNV_EYE_SELECTION
, 0);
226 void dwb2_set_new_content(struct dwbc
*dwbc
,
229 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
230 DC_LOG_DWB("%s inst = %d", __func__
, dwbc20
->base
.inst
);
232 REG_UPDATE(CNV_MODE
, CNV_NEW_CONTENT
, is_new_content
);
235 static void dwb2_set_warmup(struct dwbc
*dwbc
,
236 struct dwb_warmup_params
*warmup_params
)
238 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
239 DC_LOG_DWB("%s inst = %d", __func__
, dwbc20
->base
.inst
);
241 REG_UPDATE(WB_WARM_UP_MODE_CTL1
, GMC_WARM_UP_ENABLE
, warmup_params
->warmup_en
);
242 REG_UPDATE(WB_WARM_UP_MODE_CTL1
, WIDTH_WARMUP
, warmup_params
->warmup_width
);
243 REG_UPDATE(WB_WARM_UP_MODE_CTL1
, HEIGHT_WARMUP
, warmup_params
->warmup_height
);
245 REG_UPDATE(WB_WARM_UP_MODE_CTL2
, DATA_VALUE_WARMUP
, warmup_params
->warmup_data
);
246 REG_UPDATE(WB_WARM_UP_MODE_CTL2
, MODE_WARMUP
, warmup_params
->warmup_mode
);
247 REG_UPDATE(WB_WARM_UP_MODE_CTL2
, DATA_DEPTH_WARMUP
, warmup_params
->warmup_depth
);
250 void dwb2_set_scaler(struct dwbc
*dwbc
, struct dc_dwb_params
*params
)
252 struct dcn20_dwbc
*dwbc20
= TO_DCN20_DWBC(dwbc
);
253 DC_LOG_DWB("%s inst = %d", __func__
, dwbc20
->base
.inst
);
255 /* Program scaling mode */
256 REG_UPDATE_2(WBSCL_MODE
, WBSCL_MODE
, params
->out_format
,
257 WBSCL_OUT_BIT_DEPTH
, params
->output_depth
);
259 if (params
->out_format
!= dwb_scaler_mode_bypass444
) {
260 /* Program output size */
261 REG_UPDATE(WBSCL_DEST_SIZE
, WBSCL_DEST_WIDTH
, params
->dest_width
);
262 REG_UPDATE(WBSCL_DEST_SIZE
, WBSCL_DEST_HEIGHT
, params
->dest_height
);
264 /* Program round offsets */
265 REG_UPDATE(WBSCL_ROUND_OFFSET
, WBSCL_ROUND_OFFSET_Y_RGB
, 0x40);
266 REG_UPDATE(WBSCL_ROUND_OFFSET
, WBSCL_ROUND_OFFSET_CBCR
, 0x200);
268 /* Program clamp values */
269 REG_UPDATE(WBSCL_CLAMP_Y_RGB
, WBSCL_CLAMP_UPPER_Y_RGB
, 0x3fe);
270 REG_UPDATE(WBSCL_CLAMP_Y_RGB
, WBSCL_CLAMP_LOWER_Y_RGB
, 0x1);
271 REG_UPDATE(WBSCL_CLAMP_CBCR
, WBSCL_CLAMP_UPPER_CBCR
, 0x3fe);
272 REG_UPDATE(WBSCL_CLAMP_CBCR
, WBSCL_CLAMP_LOWER_CBCR
, 0x1);
274 /* Program outside pixel strategy to use edge pixels */
275 REG_UPDATE(WBSCL_OUTSIDE_PIX_STRATEGY
, WBSCL_OUTSIDE_PIX_STRATEGY
, DWB_OUTSIDE_PIX_STRATEGY_EDGE
);
277 if (params
->cnv_params
.crop_en
) {
278 /* horizontal scale */
279 dwb_program_horz_scalar(dwbc20
, params
->cnv_params
.crop_width
,
281 params
->scaler_taps
);
284 dwb_program_vert_scalar(dwbc20
, params
->cnv_params
.crop_height
,
287 params
->subsample_position
);
289 /* horizontal scale */
290 dwb_program_horz_scalar(dwbc20
, params
->cnv_params
.src_width
,
292 params
->scaler_taps
);
295 dwb_program_vert_scalar(dwbc20
, params
->cnv_params
.src_height
,
298 params
->subsample_position
);
304 const struct dwbc_funcs dcn20_dwbc_funcs
= {
305 .get_caps
= dwb2_get_caps
,
306 .enable
= dwb2_enable
,
307 .disable
= dwb2_disable
,
308 .update
= dwb2_update
,
309 .is_enabled
= dwb2_is_enabled
,
310 .set_stereo
= dwb2_set_stereo
,
311 .set_new_content
= dwb2_set_new_content
,
312 .set_warmup
= dwb2_set_warmup
,
313 .dwb_set_scaler
= dwb2_set_scaler
,
316 void dcn20_dwbc_construct(struct dcn20_dwbc
*dwbc20
,
317 struct dc_context
*ctx
,
318 const struct dcn20_dwbc_registers
*dwbc_regs
,
319 const struct dcn20_dwbc_shift
*dwbc_shift
,
320 const struct dcn20_dwbc_mask
*dwbc_mask
,
323 dwbc20
->base
.ctx
= ctx
;
325 dwbc20
->base
.inst
= inst
;
326 dwbc20
->base
.funcs
= &dcn20_dwbc_funcs
;
328 dwbc20
->dwbc_regs
= dwbc_regs
;
329 dwbc20
->dwbc_shift
= dwbc_shift
;
330 dwbc20
->dwbc_mask
= dwbc_mask
;