2 * Copyright 2012-15 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_mmhubbub.h"
34 mcif_wb20->mcif_wb_regs->reg
40 #define FN(reg_name, field_name) \
41 mcif_wb20->mcif_wb_shift->field_name, mcif_wb20->mcif_wb_mask->field_name
43 #define MCIF_ADDR(addr) (((unsigned long long)addr & 0xffffffffff) + 0xFE) >> 8
44 #define MCIF_ADDR_HIGH(addr) (unsigned long long)addr >> 40
46 /* wbif programming guide:
47 * 1. set up wbif parameter:
48 * unsigned long long luma_address[4]; //4 frame buffer
49 * unsigned long long chroma_address[4];
50 * unsigned int luma_pitch;
51 * unsigned int chroma_pitch;
52 * unsigned int warmup_pitch=0x10; //256B align, the page size is 4KB when it is 0x10
53 * unsigned int slice_lines; //slice size
54 * unsigned int time_per_pixel; // time per pixel, in ns
55 * unsigned int arbitration_slice; // 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes
56 * unsigned int max_scaled_time; // used for QOS generation
57 * unsigned int swlock=0x0;
58 * unsigned int cli_watermark[4]; //4 group urgent watermark
59 * unsigned int pstate_watermark[4]; //4 group pstate watermark
60 * unsigned int sw_int_en; // Software interrupt enable, frame end and overflow
61 * unsigned int sw_slice_int_en; // slice end interrupt enable
62 * unsigned int sw_overrun_int_en; // overrun error interrupt enable
63 * unsigned int vce_int_en; // VCE interrupt enable, frame end and overflow
64 * unsigned int vce_slice_int_en; // VCE slice end interrupt enable, frame end and overflow
66 * 2. configure wbif register
67 * a. call mmhubbub_config_wbif()
70 * call set_wbif_bufmgr_enable();
72 * 4. wbif_dump_status(), option, for debug purpose
73 * the bufmgr status can show the progress of write back, can be used for debug purpose
76 static void mmhubbub2_config_mcif_buf(struct mcif_wb
*mcif_wb
,
77 struct mcif_buf_params
*params
,
78 unsigned int dest_height
)
80 struct dcn20_mmhubbub
*mcif_wb20
= TO_DCN20_MMHUBBUB(mcif_wb
);
82 /* sw lock buffer0~buffer3, default is 0 */
83 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, params
->swlock
);
85 /* buffer address for packing mode or Luma in planar mode */
86 REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y
, MCIF_WB_BUF_1_ADDR_Y
, MCIF_ADDR(params
->luma_address
[0]));
87 REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH
, MCIF_WB_BUF_1_ADDR_Y_HIGH
, MCIF_ADDR_HIGH(params
->luma_address
[0]));
88 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
89 REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_OFFSET
, MCIF_WB_BUF_1_ADDR_Y_OFFSET
, 0);
91 /* buffer address for Chroma in planar mode (unused in packing mode) */
92 REG_UPDATE(MCIF_WB_BUF_1_ADDR_C
, MCIF_WB_BUF_1_ADDR_C
, MCIF_ADDR(params
->chroma_address
[0]));
93 REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH
, MCIF_WB_BUF_1_ADDR_C_HIGH
, MCIF_ADDR_HIGH(params
->chroma_address
[0]));
94 /* right eye offset for packing mode or Luma in planar mode */
95 REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_OFFSET
, MCIF_WB_BUF_1_ADDR_C_OFFSET
, 0);
97 /* buffer address for packing mode or Luma in planar mode */
98 REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y
, MCIF_WB_BUF_2_ADDR_Y
, MCIF_ADDR(params
->luma_address
[1]));
99 REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH
, MCIF_WB_BUF_2_ADDR_Y_HIGH
, MCIF_ADDR_HIGH(params
->luma_address
[1]));
100 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
101 REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_OFFSET
, MCIF_WB_BUF_2_ADDR_Y_OFFSET
, 0);
103 /* buffer address for Chroma in planar mode (unused in packing mode) */
104 REG_UPDATE(MCIF_WB_BUF_2_ADDR_C
, MCIF_WB_BUF_2_ADDR_C
, MCIF_ADDR(params
->chroma_address
[1]));
105 REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH
, MCIF_WB_BUF_2_ADDR_C_HIGH
, MCIF_ADDR_HIGH(params
->chroma_address
[1]));
106 /* right eye offset for packing mode or Luma in planar mode */
107 REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_OFFSET
, MCIF_WB_BUF_2_ADDR_C_OFFSET
, 0);
109 /* buffer address for packing mode or Luma in planar mode */
110 REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y
, MCIF_WB_BUF_3_ADDR_Y
, MCIF_ADDR(params
->luma_address
[2]));
111 REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH
, MCIF_WB_BUF_3_ADDR_Y_HIGH
, MCIF_ADDR_HIGH(params
->luma_address
[2]));
112 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
113 REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_OFFSET
, MCIF_WB_BUF_3_ADDR_Y_OFFSET
, 0);
115 /* buffer address for Chroma in planar mode (unused in packing mode) */
116 REG_UPDATE(MCIF_WB_BUF_3_ADDR_C
, MCIF_WB_BUF_3_ADDR_C
, MCIF_ADDR(params
->chroma_address
[2]));
117 REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH
, MCIF_WB_BUF_3_ADDR_C_HIGH
, MCIF_ADDR_HIGH(params
->chroma_address
[2]));
118 /* right eye offset for packing mode or Luma in planar mode */
119 REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_OFFSET
, MCIF_WB_BUF_3_ADDR_C_OFFSET
, 0);
121 /* buffer address for packing mode or Luma in planar mode */
122 REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y
, MCIF_WB_BUF_4_ADDR_Y
, MCIF_ADDR(params
->luma_address
[3]));
123 REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH
, MCIF_WB_BUF_4_ADDR_Y_HIGH
, MCIF_ADDR_HIGH(params
->luma_address
[3]));
124 /* right eye sub-buffer address offset for packing mode or Luma in planar mode */
125 REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_OFFSET
, MCIF_WB_BUF_4_ADDR_Y_OFFSET
, 0);
127 /* buffer address for Chroma in planar mode (unused in packing mode) */
128 REG_UPDATE(MCIF_WB_BUF_4_ADDR_C
, MCIF_WB_BUF_4_ADDR_C
, MCIF_ADDR(params
->chroma_address
[3]));
129 REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH
, MCIF_WB_BUF_4_ADDR_C_HIGH
, MCIF_ADDR_HIGH(params
->chroma_address
[3]));
130 /* right eye offset for packing mode or Luma in planar mode */
131 REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_OFFSET
, MCIF_WB_BUF_4_ADDR_C_OFFSET
, 0);
133 /* setup luma & chroma size
134 * should be enough to contain a whole frame Luma data,
135 * the programmed value is frame buffer size [27:8], 256-byte aligned
137 REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE
, MCIF_WB_BUF_LUMA_SIZE
, (params
->luma_pitch
>>8) * dest_height
);
138 REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE
, MCIF_WB_BUF_CHROMA_SIZE
, (params
->chroma_pitch
>>8) * dest_height
);
140 /* enable address fence */
141 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUF_ADDR_FENCE_EN
, 1);
143 /* setup pitch, the programmed value is [15:8], 256B align */
144 REG_UPDATE_2(MCIF_WB_BUF_PITCH
, MCIF_WB_BUF_LUMA_PITCH
, params
->luma_pitch
>> 8,
145 MCIF_WB_BUF_CHROMA_PITCH
, params
->chroma_pitch
>> 8);
147 /* Set pitch for MC cache warm up mode */
148 /* Pitch is 256 bytes aligned. The default pitch is 4K */
149 /* default is 0x10 */
150 REG_UPDATE(MCIF_WB_WARM_UP_CNTL
, MCIF_WB_PITCH_SIZE_WARMUP
, params
->warmup_pitch
);
153 static void mmhubbub2_config_mcif_arb(struct mcif_wb
*mcif_wb
,
154 struct mcif_arb_params
*params
)
156 struct dcn20_mmhubbub
*mcif_wb20
= TO_DCN20_MMHUBBUB(mcif_wb
);
158 /* Programmed by the video driver based on the CRTC timing (for DWB) */
159 REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL
, MCIF_WB_TIME_PER_PIXEL
, params
->time_per_pixel
);
161 /* Programming dwb watermark */
162 /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */
163 /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */
164 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x0);
165 /* urgent_watermarkA */
166 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, params
->cli_watermark
[0]);
167 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x1);
168 /* urgent_watermarkB */
169 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, params
->cli_watermark
[1]);
170 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x2);
171 /* urgent_watermarkC */
172 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, params
->cli_watermark
[2]);
173 REG_UPDATE(MCIF_WB_SCLK_CHANGE
, MCIF_WB_CLI_WATERMARK_MASK
, 0x3);
174 /* urgent_watermarkD */
175 REG_UPDATE(MCIF_WB_WATERMARK
, MCIF_WB_CLI_WATERMARK
, params
->cli_watermark
[3]);
177 /* Programming nb pstate watermark */
178 /* nbp_state_change_watermarkA */
179 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x0);
180 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
,
181 NB_PSTATE_CHANGE_REFRESH_WATERMARK
, params
->pstate_watermark
[0]);
182 /* nbp_state_change_watermarkB */
183 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x1);
184 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
,
185 NB_PSTATE_CHANGE_REFRESH_WATERMARK
, params
->pstate_watermark
[1]);
186 /* nbp_state_change_watermarkC */
187 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x2);
188 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
,
189 NB_PSTATE_CHANGE_REFRESH_WATERMARK
, params
->pstate_watermark
[2]);
190 /* nbp_state_change_watermarkD */
191 REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL
, NB_PSTATE_CHANGE_WATERMARK_MASK
, 0x3);
192 REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK
,
193 NB_PSTATE_CHANGE_REFRESH_WATERMARK
, params
->pstate_watermark
[3]);
195 /* max_scaled_time */
196 REG_UPDATE(MULTI_LEVEL_QOS_CTRL
, MAX_SCALED_TIME_TO_URGENT
, params
->max_scaled_time
);
199 REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL
, MCIF_WB_BUFMGR_SLICE_SIZE
, params
->slice_lines
-1);
201 /* Set arbitration unit for Luma/Chroma */
202 /* arb_unit=2 should be chosen for more efficiency */
203 /* Arbitration size, 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes */
204 REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL
, MCIF_WB_CLIENT_ARBITRATION_SLICE
, params
->arbitration_slice
);
207 void mmhubbub2_config_mcif_irq(struct mcif_wb
*mcif_wb
,
208 struct mcif_irq_params
*params
)
210 struct dcn20_mmhubbub
*mcif_wb20
= TO_DCN20_MMHUBBUB(mcif_wb
);
212 /* Set interrupt mask */
213 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_INT_EN
, params
->sw_int_en
);
214 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_SLICE_INT_EN
, params
->sw_slice_int_en
);
215 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN
, params
->sw_overrun_int_en
);
217 REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL
, MCIF_WB_BUFMGR_VCE_INT_EN
, params
->vce_int_en
);
218 REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL
, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN
, params
->vce_slice_int_en
);
221 void mmhubbub2_enable_mcif(struct mcif_wb
*mcif_wb
)
223 struct dcn20_mmhubbub
*mcif_wb20
= TO_DCN20_MMHUBBUB(mcif_wb
);
226 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_ENABLE
, 1);
229 void mmhubbub2_disable_mcif(struct mcif_wb
*mcif_wb
)
231 struct dcn20_mmhubbub
*mcif_wb20
= TO_DCN20_MMHUBBUB(mcif_wb
);
233 /* disable buffer manager */
234 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_ENABLE
, 0);
237 /* set which group of pstate watermark to use and set wbif watermark change request */
239 static void mmhubbub2_wbif_watermark_change_req(struct mcif_wb *mcif_wb, unsigned int wm_set)
241 struct dcn20_mmhubbub *mcif_wb20 = TO_DCN20_MMHUBBUB(mcif_wb);
244 REG_GET(SMU_WM_CONTROL, MCIF_WB0_WM_CHG_REQ, &change_req);
245 change_req = (change_req == 0) ? 1 : 0;
246 REG_UPDATE(SMU_WM_CONTROL, MCIF_WB0_WM_CHG_SEL, wm_set);
247 REG_UPDATE(SMU_WM_CONTROL, MCIF_WB0_WM_CHG_REQ, change_req);
250 /* Set watermark change interrupt disable bit */
252 static void mmhubbub2_set_wbif_watermark_change_int_disable(struct mcif_wb *mcif_wb, unsigned int ack_int_dis)
254 struct dcn20_mmhubbub *mcif_wb20 = TO_DCN20_MMHUBBUB(mcif_wb);
256 REG_UPDATE(SMU_WM_CONTROL, MCIF_WB0_WM_CHG_ACK_INT_DIS, ack_int_dis);
259 /* Read watermark change interrupt status */
261 unsigned int mmhubbub2_get_wbif_watermark_change_int_status(struct mcif_wb *mcif_wb)
263 struct dcn20_mmhubbub *mcif_wb20 = TO_DCN20_MMHUBBUB(mcif_wb);
266 REG_GET(SMU_WM_CONTROL, MCIF_WB0_WM_CHG_ACK_INT_STATUS, &irq_status);
271 void mcifwb2_dump_frame(struct mcif_wb
*mcif_wb
,
272 struct mcif_buf_params
*mcif_params
,
273 enum dwb_scaler_mode out_format
,
274 unsigned int dest_width
,
275 unsigned int dest_height
,
276 struct mcif_wb_frame_dump_info
*dump_info
,
277 unsigned char *luma_buffer
,
278 unsigned char *chroma_buffer
,
279 unsigned char *dest_luma_buffer
,
280 unsigned char *dest_chroma_buffer
)
282 struct dcn20_mmhubbub
*mcif_wb20
= TO_DCN20_MMHUBBUB(mcif_wb
);
284 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, 0xf);
286 memcpy(dest_luma_buffer
, luma_buffer
, mcif_params
->luma_pitch
* dest_height
);
287 memcpy(dest_chroma_buffer
, chroma_buffer
, mcif_params
->chroma_pitch
* dest_height
/ 2);
289 REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL
, MCIF_WB_BUFMGR_SW_LOCK
, 0x0);
291 dump_info
->format
= out_format
;
292 dump_info
->width
= dest_width
;
293 dump_info
->height
= dest_height
;
294 dump_info
->luma_pitch
= mcif_params
->luma_pitch
;
295 dump_info
->chroma_pitch
= mcif_params
->chroma_pitch
;
296 dump_info
->size
= dest_height
* (mcif_params
->luma_pitch
+ mcif_params
->chroma_pitch
);
299 const struct mcif_wb_funcs dcn20_mmhubbub_funcs
= {
300 .enable_mcif
= mmhubbub2_enable_mcif
,
301 .disable_mcif
= mmhubbub2_disable_mcif
,
302 .config_mcif_buf
= mmhubbub2_config_mcif_buf
,
303 .config_mcif_arb
= mmhubbub2_config_mcif_arb
,
304 .config_mcif_irq
= mmhubbub2_config_mcif_irq
,
305 .dump_frame
= mcifwb2_dump_frame
,
308 void dcn20_mmhubbub_construct(struct dcn20_mmhubbub
*mcif_wb20
,
309 struct dc_context
*ctx
,
310 const struct dcn20_mmhubbub_registers
*mcif_wb_regs
,
311 const struct dcn20_mmhubbub_shift
*mcif_wb_shift
,
312 const struct dcn20_mmhubbub_mask
*mcif_wb_mask
,
315 mcif_wb20
->base
.ctx
= ctx
;
317 mcif_wb20
->base
.inst
= inst
;
318 mcif_wb20
->base
.funcs
= &dcn20_mmhubbub_funcs
;
320 mcif_wb20
->mcif_wb_regs
= mcif_wb_regs
;
321 mcif_wb20
->mcif_wb_shift
= mcif_wb_shift
;
322 mcif_wb20
->mcif_wb_mask
= mcif_wb_mask
;