Line data Source code
1 : /*
2 : * Copyright 2022 Advanced Micro Devices, Inc.
3 : *
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:
10 : *
11 : * The above copyright notice and this permission notice shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
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.
21 : *
22 : * Authors: AMD
23 : *
24 : */
25 :
26 :
27 : #include "reg_helper.h"
28 : #include "resource.h"
29 : #include "mcif_wb.h"
30 : #include "dcn32_mmhubbub.h"
31 :
32 :
33 : #define REG(reg)\
34 : mcif_wb30->mcif_wb_regs->reg
35 :
36 : #define CTX \
37 : mcif_wb30->base.ctx
38 :
39 : #undef FN
40 : #define FN(reg_name, field_name) \
41 : mcif_wb30->mcif_wb_shift->field_name, mcif_wb30->mcif_wb_mask->field_name
42 :
43 : #define MCIF_ADDR(addr) (((unsigned long long)addr & 0xffffffffff) + 0xFE) >> 8
44 : #define MCIF_ADDR_HIGH(addr) (unsigned long long)addr >> 40
45 :
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: 2048 bytes 1: 4096 bytes 2: 8192 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
65 : *
66 : * 2. configure wbif register
67 : * a. call mmhubbub_config_wbif()
68 : *
69 : * 3. Enable wbif
70 : * call set_wbif_bufmgr_enable();
71 : *
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
74 : */
75 :
76 0 : static void mmhubbub32_warmup_mcif(struct mcif_wb *mcif_wb,
77 : struct mcif_warmup_params *params)
78 : {
79 0 : struct dcn30_mmhubbub *mcif_wb30 = TO_DCN30_MMHUBBUB(mcif_wb);
80 0 : union large_integer start_address_shift = {.quad_part = params->start_address.quad_part >> 5};
81 :
82 : /* Set base address and region size for warmup */
83 0 : REG_SET(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, 0, MMHUBBUB_WARMUP_BASE_ADDR_HIGH, start_address_shift.high_part);
84 0 : REG_SET(MMHUBBUB_WARMUP_BASE_ADDR_LOW, 0, MMHUBBUB_WARMUP_BASE_ADDR_LOW, start_address_shift.low_part);
85 0 : REG_SET(MMHUBBUB_WARMUP_ADDR_REGION, 0, MMHUBBUB_WARMUP_ADDR_REGION, params->region_size >> 5);
86 : // REG_SET(MMHUBBUB_WARMUP_P_VMID, 0, MMHUBBUB_WARMUP_P_VMID, params->p_vmid);
87 :
88 : /* Set address increment and enable warmup */
89 0 : REG_SET_3(MMHUBBUB_WARMUP_CONTROL_STATUS, 0, MMHUBBUB_WARMUP_EN, true,
90 : MMHUBBUB_WARMUP_SW_INT_EN, true,
91 : MMHUBBUB_WARMUP_INC_ADDR, params->address_increment >> 5);
92 :
93 : /* Wait for an interrupt to signal warmup is completed */
94 0 : REG_WAIT(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_STATUS, 1, 20, 100);
95 :
96 : /* Acknowledge interrupt */
97 0 : REG_UPDATE(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_ACK, 1);
98 :
99 : /* Disable warmup */
100 0 : REG_UPDATE(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_EN, false);
101 0 : }
102 :
103 0 : void mmhubbub32_config_mcif_buf(struct mcif_wb *mcif_wb,
104 : struct mcif_buf_params *params,
105 : unsigned int dest_height)
106 : {
107 0 : struct dcn30_mmhubbub *mcif_wb30 = TO_DCN30_MMHUBBUB(mcif_wb);
108 :
109 : /* buffer address for packing mode or Luma in planar mode */
110 0 : REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, MCIF_ADDR(params->luma_address[0]));
111 0 : REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[0]));
112 :
113 : /* buffer address for Chroma in planar mode (unused in packing mode) */
114 0 : REG_UPDATE(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, MCIF_ADDR(params->chroma_address[0]));
115 0 : REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[0]));
116 :
117 : /* buffer address for packing mode or Luma in planar mode */
118 0 : REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, MCIF_ADDR(params->luma_address[1]));
119 0 : REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[1]));
120 :
121 : /* buffer address for Chroma in planar mode (unused in packing mode) */
122 0 : REG_UPDATE(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, MCIF_ADDR(params->chroma_address[1]));
123 0 : REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[1]));
124 :
125 : /* buffer address for packing mode or Luma in planar mode */
126 0 : REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, MCIF_ADDR(params->luma_address[2]));
127 0 : REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[2]));
128 :
129 : /* buffer address for Chroma in planar mode (unused in packing mode) */
130 0 : REG_UPDATE(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, MCIF_ADDR(params->chroma_address[2]));
131 0 : REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[2]));
132 :
133 : /* buffer address for packing mode or Luma in planar mode */
134 0 : REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, MCIF_ADDR(params->luma_address[3]));
135 0 : REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[3]));
136 :
137 : /* buffer address for Chroma in planar mode (unused in packing mode) */
138 0 : REG_UPDATE(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, MCIF_ADDR(params->chroma_address[3]));
139 0 : REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[3]));
140 :
141 : /* setup luma & chroma size
142 : * should be enough to contain a whole frame Luma data,
143 : * the programmed value is frame buffer size [27:8], 256-byte aligned
144 : */
145 0 : REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, (params->luma_pitch>>8) * dest_height);
146 0 : REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, (params->chroma_pitch>>8) * dest_height);
147 :
148 : /* enable address fence */
149 0 : REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, 1);
150 :
151 : /* setup pitch, the programmed value is [15:8], 256B align */
152 0 : REG_UPDATE_2(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, params->luma_pitch >> 8,
153 : MCIF_WB_BUF_CHROMA_PITCH, params->chroma_pitch >> 8);
154 0 : }
155 :
156 0 : static void mmhubbub32_config_mcif_arb(struct mcif_wb *mcif_wb,
157 : struct mcif_arb_params *params)
158 : {
159 0 : struct dcn30_mmhubbub *mcif_wb30 = TO_DCN30_MMHUBBUB(mcif_wb);
160 :
161 : /* Programmed by the video driver based on the CRTC timing (for DWB) */
162 0 : REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, params->time_per_pixel);
163 :
164 : /* Programming dwb watermark */
165 : /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */
166 : /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */
167 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x0);
168 : /* urgent_watermarkA */
169 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[0]);
170 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x1);
171 : /* urgent_watermarkB */
172 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[1]);
173 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x2);
174 : /* urgent_watermarkC */
175 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[2]);
176 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x3);
177 : /* urgent_watermarkD */
178 0 : REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[3]);
179 :
180 : /* Programming nb pstate watermark */
181 : /* nbp_state_change_watermarkA */
182 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x0);
183 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK,
184 : NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[0]);
185 : /* nbp_state_change_watermarkB */
186 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x1);
187 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK,
188 : NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[1]);
189 : /* nbp_state_change_watermarkC */
190 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x2);
191 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK,
192 : NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[2]);
193 : /* nbp_state_change_watermarkD */
194 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x3);
195 0 : REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK,
196 : NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[3]);
197 :
198 : /* dram_speed_change_duration - register removed */
199 : //REG_UPDATE(MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI,
200 : // MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, params->dram_speed_change_duration);
201 :
202 : /* max_scaled_time */
203 0 : REG_UPDATE(MULTI_LEVEL_QOS_CTRL, MAX_SCALED_TIME_TO_URGENT, params->max_scaled_time);
204 :
205 : /* slice_lines */
206 0 : REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, params->slice_lines-1);
207 :
208 : /* Set arbitration unit for Luma/Chroma */
209 : /* arb_unit=2 should be chosen for more efficiency */
210 : /* Arbitration size, 0: 2048 bytes 1: 4096 bytes 2: 8192 Bytes */
211 0 : REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, params->arbitration_slice);
212 0 : }
213 :
214 : const struct mcif_wb_funcs dcn32_mmhubbub_funcs = {
215 : .warmup_mcif = mmhubbub32_warmup_mcif,
216 : .enable_mcif = mmhubbub2_enable_mcif,
217 : .disable_mcif = mmhubbub2_disable_mcif,
218 : .config_mcif_buf = mmhubbub32_config_mcif_buf,
219 : .config_mcif_arb = mmhubbub32_config_mcif_arb,
220 : .config_mcif_irq = mmhubbub2_config_mcif_irq,
221 : .dump_frame = mcifwb2_dump_frame,
222 : };
223 :
224 0 : void dcn32_mmhubbub_construct(struct dcn30_mmhubbub *mcif_wb30,
225 : struct dc_context *ctx,
226 : const struct dcn30_mmhubbub_registers *mcif_wb_regs,
227 : const struct dcn30_mmhubbub_shift *mcif_wb_shift,
228 : const struct dcn30_mmhubbub_mask *mcif_wb_mask,
229 : int inst)
230 : {
231 0 : mcif_wb30->base.ctx = ctx;
232 :
233 0 : mcif_wb30->base.inst = inst;
234 0 : mcif_wb30->base.funcs = &dcn32_mmhubbub_funcs;
235 :
236 0 : mcif_wb30->mcif_wb_regs = mcif_wb_regs;
237 0 : mcif_wb30->mcif_wb_shift = mcif_wb_shift;
238 0 : mcif_wb30->mcif_wb_mask = mcif_wb_mask;
239 0 : }
|