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.
26 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
28 #include "reg_helper.h"
31 #include "dcn10_dwb.h"
35 dwbc10->dwbc_regs->reg
41 #define FN(reg_name, field_name) \
42 dwbc10->dwbc_shift->field_name, dwbc10->dwbc_mask->field_name
44 #define TO_DCN10_DWBC(dwbc_base) \
45 container_of(dwbc_base, struct dcn10_dwbc, base)
47 static bool get_caps(struct dwbc
*dwbc
, struct dwb_caps
*caps
)
50 caps
->adapter_id
= 0; /* we only support 1 adapter currently */
51 caps
->hw_version
= DCN_VERSION_1_0
;
53 memset(&caps
->reserved
, 0, sizeof(caps
->reserved
));
54 memset(&caps
->reserved2
, 0, sizeof(caps
->reserved2
));
55 caps
->sw_version
= dwb_ver_1_0
;
56 caps
->caps
.support_dwb
= true;
57 caps
->caps
.support_ogam
= false;
58 caps
->caps
.support_wbscl
= true;
59 caps
->caps
.support_ocsc
= false;
66 static bool enable(struct dwbc
*dwbc
)
68 struct dcn10_dwbc
*dwbc10
= TO_DCN10_DWBC(dwbc
);
71 dwbc
->funcs
->disable(dwbc
);
73 /* disable power gating */
74 REG_UPDATE_5(WB_EC_CONFIG
, DISPCLK_R_WB_GATE_DIS
, 1,
75 DISPCLK_G_WB_GATE_DIS
, 1, DISPCLK_G_WBSCL_GATE_DIS
, 1,
76 WB_LB_LS_DIS
, 1, WB_LUT_LS_DIS
, 1);
78 REG_UPDATE(WB_ENABLE
, WB_ENABLE
, 1);
80 /* lock buffer0~buffer3 */
81 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, 0xf);
83 /* buffer address for packing mode or Luma in planar mode */
84 REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y
, MCIF_WB_BUF_1_ADDR_Y
, (dwbc
->config
.basic_settings
.luma_address
[0] & 0xffffffff));
85 /* REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[0] >> 32)); */
86 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
87 REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_OFFSET
, MCIF_WB_BUF_1_ADDR_Y_OFFSET
, 0);
89 /* buffer address for Chroma in planar mode (unused in packing mode) */
90 REG_UPDATE(MCIF_WB_BUF_1_ADDR_C
, MCIF_WB_BUF_1_ADDR_C
, (dwbc
->config
.basic_settings
.chroma_address
[0] & 0xffffffff));
91 /* REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[0] >> 32)); */
92 /* right eye offset for packing mode or Luma in planar mode */
93 REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_OFFSET
, MCIF_WB_BUF_1_ADDR_C_OFFSET
, 0);
95 /* buffer address for packing mode or Luma in planar mode */
96 REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y
, MCIF_WB_BUF_2_ADDR_Y
, (dwbc
->config
.basic_settings
.luma_address
[1] & 0xffffffff));
97 /* REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[1] >> 32)); */
98 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
99 REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_OFFSET
, MCIF_WB_BUF_2_ADDR_Y_OFFSET
, 0);
101 /* buffer address for Chroma in planar mode (unused in packing mode) */
102 REG_UPDATE(MCIF_WB_BUF_2_ADDR_C
, MCIF_WB_BUF_2_ADDR_C
, (dwbc
->config
.basic_settings
.chroma_address
[1] & 0xffffffff));
103 /* REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[1] >> 32)); */
104 /* right eye offset for packing mode or Luma in planar mode */
105 REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_OFFSET
, MCIF_WB_BUF_2_ADDR_C_OFFSET
, 0);
107 /* buffer address for packing mode or Luma in planar mode */
108 REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y
, MCIF_WB_BUF_3_ADDR_Y
, (dwbc
->config
.basic_settings
.luma_address
[2] & 0xffffffff));
109 /* REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[2] >> 32)); */
110 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
111 REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_OFFSET
, MCIF_WB_BUF_3_ADDR_Y_OFFSET
, 0);
113 /* buffer address for Chroma in planar mode (unused in packing mode) */
114 REG_UPDATE(MCIF_WB_BUF_3_ADDR_C
, MCIF_WB_BUF_3_ADDR_C
, (dwbc
->config
.basic_settings
.chroma_address
[2] & 0xffffffff));
115 /* REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[2] >> 32)); */
116 /* right eye offset for packing mode or Luma in planar mode */
117 REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_OFFSET
, MCIF_WB_BUF_3_ADDR_C_OFFSET
, 0);
119 /* buffer address for packing mode or Luma in planar mode */
120 REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y
, MCIF_WB_BUF_4_ADDR_Y
, (dwbc
->config
.basic_settings
.luma_address
[3] & 0xffffffff));
121 /* REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[3] >> 32)); */
122 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
123 REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_OFFSET
, MCIF_WB_BUF_4_ADDR_Y_OFFSET
, 0);
125 /* buffer address for Chroma in planar mode (unused in packing mode) */
126 REG_UPDATE(MCIF_WB_BUF_4_ADDR_C
, MCIF_WB_BUF_4_ADDR_C
, (dwbc
->config
.basic_settings
.chroma_address
[3] & 0xffffffff));
127 /* REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[3] >> 32)); */
128 /* right eye offset for packing mode or Luma in planar mode */
129 REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_OFFSET
, MCIF_WB_BUF_4_ADDR_C_OFFSET
, 0);
131 /* setup luma & chroma size */
132 REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE
, MCIF_WB_BUF_LUMA_SIZE
, dwbc
->config
.basic_settings
.luma_pitch
* dwbc
->config
.basic_settings
.dest_height
); /* should be enough to contain a whole frame Luma data, same for stereo mode */
133 REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE
, MCIF_WB_BUF_CHROMA_SIZE
, dwbc
->config
.basic_settings
.chroma_pitch
* dwbc
->config
.basic_settings
.dest_height
); /* should be enough to contain a whole frame Luma data, same for stereo mode */
135 /* enable address fence */
136 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUF_ADDR_FENCE_EN
, 1);
139 REG_UPDATE_2(MCIF_WB_BUF_PITCH
, MCIF_WB_BUF_LUMA_PITCH
, dwbc
->config
.basic_settings
.luma_pitch
,
140 MCIF_WB_BUF_CHROMA_PITCH
, dwbc
->config
.basic_settings
.chroma_pitch
);
142 /* Set pitch for MC cache warm up mode */
143 /* Pitch is 256 bytes aligned. The default pitch is 4K */
144 REG_UPDATE(MCIF_WB_WARM_UP_CNTL
, MCIF_WB_PITCH_SIZE_WARMUP
, 0x10); /* default is 0x10 */
146 /* Programmed by the video driver based on the CRTC timing (for DWB) */
147 REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL
, MCIF_WB_TIME_PER_PIXEL
, 0);
149 /* Programming dwb watermark */
150 /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */
151 /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */
152 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x0);
153 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, 0xffff); /* urgent_watermarkA */
154 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x1);
155 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, 0xffff); /* urgent_watermarkB */
156 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x2);
157 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, 0xffff); /* urgent_watermarkC */
158 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x3);
159 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, 0xffff); /* urgent_watermarkD */
161 /* Programming nb pstate watermark */
162 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x0);
163 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
, NB_PSTATE_CHANGE_REFRESH_WATERMARK
, 0xffff); /* nbp_state_change_watermarkA */
164 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x1);
165 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
, NB_PSTATE_CHANGE_REFRESH_WATERMARK
, 0xffff); /* nbp_state_change_watermarkB */
166 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x2);
167 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
, NB_PSTATE_CHANGE_REFRESH_WATERMARK
, 0xffff); /* nbp_state_change_watermarkC */
168 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x3);
169 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
, NB_PSTATE_CHANGE_REFRESH_WATERMARK
, 0xffff); /* nbp_state_change_watermarkD */
171 /* buf_lh_capability = (buffer_size / byte_per_pixel)*time_per_pixel; //client buffer latency hiding capability */
172 /* if (MCIF_WB_CLI_WATERMARK * 2 < buf_lh_capability) //factor '2' can be adjusted if better value is identified during bringup/debug */
173 /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = MCIF_WB_CLI_WATERMARK * 2; */
175 /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = buf_lh_capability; //ensure QoS can be fully mapped to [0:15] region in any scenario */
177 REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL
, MCIF_WB_BUFMGR_SLICE_SIZE
, 31);
179 /* Set arbitration unit for Luma/Chroma */
180 /* arb_unit=2 should be chosen for more efficiency */
181 REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL
, MCIF_WB_CLIENT_ARBITRATION_SLICE
, 2); /* Arbitration size, 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes */
183 /* Program VMID, don't support virtual mode, won't set VMID */
184 /* REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, pVmid); */
186 if (dwbc
->config
.basic_settings
.input_pipe_select
== dwb_pipe0
) {
187 REG_UPDATE(DWB_SOURCE_SELECT
, OPTC_DWB0_SOURCE_SELECT
, dwbc
->config
.basic_settings
.input_src_select
- dwb_src_otg0
);
188 } else if (dwbc
->config
.basic_settings
.input_pipe_select
== dwb_pipe1
) {
189 REG_UPDATE(DWB_SOURCE_SELECT
, OPTC_DWB1_SOURCE_SELECT
, dwbc
->config
.basic_settings
.input_src_select
- dwb_src_otg0
);
192 /* Set interrupt mask */
193 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_INT_EN
, 0); /* Disable interrupt to SW. (the default value is 0.) */
194 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_SLICE_INT_EN
, 0); /* Disable slice complete interrupt to SW.(the default value is 0.) */
195 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN
, 0); /* Disable frame buffer overrun interrupt to SW. (the default value is 0.) */
197 REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL
, MCIF_WB_BUFMGR_VCE_INT_EN
, 1); /* Enable interrupt to VCE */
198 REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL
, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN
, 0); /* Disable slice complete interrupt to VCE. */
200 /* ////////////////// */
202 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_ENABLE
, 1); /* Start working */
204 /* unlock sw lock. */
205 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, 0);
207 dwbc
->status
.enabled
= true;
212 static bool disable(struct dwbc
*dwbc
)
214 struct dcn10_dwbc
*dwbc10
= TO_DCN10_DWBC(dwbc
);
217 REG_UPDATE(CNV_MODE
, CNV_FRAME_CAPTURE_EN
, 0);
220 REG_UPDATE(WB_ENABLE
, WB_ENABLE
, 0);
223 REG_UPDATE(WB_SOFT_RESET
, WB_SOFT_RESET
, 1);
224 REG_UPDATE(WB_SOFT_RESET
, WB_SOFT_RESET
, 0);
226 /* enable power gating */
227 REG_UPDATE_5(WB_EC_CONFIG
, DISPCLK_R_WB_GATE_DIS
, 0,
228 DISPCLK_G_WB_GATE_DIS
, 0, DISPCLK_G_WBSCL_GATE_DIS
, 0,
229 WB_LB_LS_DIS
, 0, WB_LUT_LS_DIS
, 0);
231 /* disable buffer manager */
232 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_ENABLE
, 0);
234 dwbc
->status
.enabled
= false;
239 static bool get_status(struct dwbc
*dwbc
, struct dwb_status
*status
)
242 memcpy(status
, &dwbc
->status
, sizeof(struct dwb_status
));
249 static bool dump_frame(struct dwbc
*dwbc
, struct dwb_frame_info
*frame_info
,
250 unsigned char *luma_buffer
, unsigned char *chroma_buffer
,
251 unsigned char *dest_luma_buffer
, unsigned char *dest_chroma_buffer
)
253 struct dcn10_dwbc
*dwbc10
= TO_DCN10_DWBC(dwbc
);
255 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, 0xf);
257 memcpy(dest_luma_buffer
, luma_buffer
, dwbc
->config
.basic_settings
.luma_pitch
* dwbc
->config
.basic_settings
.dest_height
);
258 memcpy(dest_chroma_buffer
, chroma_buffer
, dwbc
->config
.basic_settings
.chroma_pitch
* dwbc
->config
.basic_settings
.dest_height
/ 2);
260 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, 0x0);
262 frame_info
->format
= dwbc
->config
.advanced_settings
.out_format
;
263 frame_info
->width
= dwbc
->config
.basic_settings
.dest_width
;
264 frame_info
->height
= dwbc
->config
.basic_settings
.dest_height
;
265 frame_info
->luma_pitch
= dwbc
->config
.basic_settings
.luma_pitch
;
266 frame_info
->chroma_pitch
= dwbc
->config
.basic_settings
.chroma_pitch
;
267 frame_info
->size
= dwbc
->config
.basic_settings
.dest_height
* (dwbc
->config
.basic_settings
.luma_pitch
+ dwbc
->config
.basic_settings
.chroma_pitch
);
272 static bool set_basic_settings(struct dwbc
*dwbc
,
273 const struct dwb_basic_settings
*basic_settings
)
275 if (basic_settings
) {
276 memcpy(&dwbc
->config
.basic_settings
, basic_settings
, sizeof(struct dwb_basic_settings
));
283 static bool get_basic_settings(struct dwbc
*dwbc
,
284 struct dwb_basic_settings
*basic_settings
)
286 if (basic_settings
) {
287 memcpy(basic_settings
, &dwbc
->config
.basic_settings
, sizeof(struct dwb_basic_settings
));
294 static bool set_advanced_settings(struct dwbc
*dwbc
,
295 const struct dwb_advanced_settings
*advanced_settings
)
297 if (advanced_settings
) {
298 if (advanced_settings
->uFlag
& sf_output_format
) {
299 dwbc
->config
.advanced_settings
.uFlag
|= sf_output_format
;
300 dwbc
->config
.advanced_settings
.out_format
= advanced_settings
->out_format
;
303 if (advanced_settings
->uFlag
& sf_capture_rate
) {
304 dwbc
->config
.advanced_settings
.uFlag
|= sf_capture_rate
;
305 dwbc
->config
.advanced_settings
.capture_rate
= advanced_settings
->capture_rate
;
314 static bool get_advanced_settings(struct dwbc
*dwbc
,
315 struct dwb_advanced_settings
*advanced_settings
)
317 if (advanced_settings
) {
318 memcpy(advanced_settings
, &dwbc
->config
.advanced_settings
, sizeof(struct dwb_advanced_settings
));
325 static bool reset_advanced_settings(struct dwbc
*dwbc
)
327 dwbc
->config
.advanced_settings
.uFlag
= 0;
328 dwbc
->config
.advanced_settings
.out_format
= dwb_scaler_mode_bypass444
;
329 dwbc
->config
.advanced_settings
.capture_rate
= dwb_capture_rate_0
;
334 const struct dwbc_funcs dcn10_dwbc_funcs
= {
335 .get_caps
= get_caps
,
338 .get_status
= get_status
,
339 .dump_frame
= dump_frame
,
340 .set_basic_settings
= set_basic_settings
,
341 .get_basic_settings
= get_basic_settings
,
342 .set_advanced_settings
= set_advanced_settings
,
343 .get_advanced_settings
= get_advanced_settings
,
344 .reset_advanced_settings
= reset_advanced_settings
,
347 void dcn10_dwbc_construct(struct dcn10_dwbc
*dwbc10
,
348 struct dc_context
*ctx
,
349 const struct dcn10_dwbc_registers
*dwbc_regs
,
350 const struct dcn10_dwbc_shift
*dwbc_shift
,
351 const struct dcn10_dwbc_mask
*dwbc_mask
,
354 dwbc10
->base
.ctx
= ctx
;
356 dwbc10
->base
.inst
= inst
;
357 dwbc10
->base
.funcs
= &dcn10_dwbc_funcs
;
359 dwbc10
->dwbc_regs
= dwbc_regs
;
360 dwbc10
->dwbc_shift
= dwbc_shift
;
361 dwbc10
->dwbc_mask
= dwbc_mask
;