]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drm/amd/display: add bw logging for dcn
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dcn10 / dcn10_hw_sequencer.c
1 /*
2 * Copyright 2016 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 #include "dm_services.h"
27 #include "dc.h"
28 #include "core_dc.h"
29 #include "core_types.h"
30 #include "core_status.h"
31 #include "resource.h"
32 #include "dcn10_hw_sequencer.h"
33 #include "dce110/dce110_hw_sequencer.h"
34 #include "dce/dce_hwseq.h"
35 #include "abm.h"
36
37 #include "dcn10/dcn10_transform.h"
38 #include "dcn10/dcn10_mpc.h"
39 #include "dcn10/dcn10_timing_generator.h"
40
41 #include "mem_input.h"
42 #include "timing_generator.h"
43 #include "opp.h"
44 #include "ipp.h"
45
46 #include "dc_bios_types.h"
47
48 #include "raven1/DCN/dcn_1_0_offset.h"
49 #include "raven1/DCN/dcn_1_0_sh_mask.h"
50 #include "vega10/soc15ip.h"
51
52 #include "custom_float.h"
53
54
55 struct dcn10_hwseq_reg_offsets {
56 uint32_t dchubp;
57 uint32_t dpp;
58 uint32_t otg;
59 uint32_t vtg;
60 uint32_t fmt;
61 };
62
63 /* TODO: move to resource */
64 static const struct dcn10_hwseq_reg_offsets reg_offsets[] = {
65 {
66 .dchubp = (mmHUBP0_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL),
67 .dpp = (mmCM0_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL),
68 .otg = (mmOTG0_OTG_CONTROL - mmOTG0_OTG_CONTROL),
69 .vtg = (mmVTG0_CONTROL - mmVTG0_CONTROL),
70 .fmt = (mmFMT0_FMT_BIT_DEPTH_CONTROL -
71 mmFMT0_FMT_BIT_DEPTH_CONTROL),
72 },
73 {
74 .dchubp = (mmHUBP1_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL),
75 .dpp = (mmCM1_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL),
76 .otg = (mmOTG1_OTG_CONTROL - mmOTG0_OTG_CONTROL),
77 .vtg = (mmVTG1_CONTROL - mmVTG0_CONTROL),
78 .fmt = (mmFMT1_FMT_BIT_DEPTH_CONTROL -
79 mmFMT0_FMT_BIT_DEPTH_CONTROL),
80 },
81 {
82 .dchubp = (mmHUBP2_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL),
83 .dpp = (mmCM2_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL),
84 .otg = (mmOTG2_OTG_CONTROL - mmOTG0_OTG_CONTROL),
85 .vtg = (mmVTG2_CONTROL - mmVTG0_CONTROL),
86 .fmt = (mmFMT2_FMT_BIT_DEPTH_CONTROL -
87 mmFMT0_FMT_BIT_DEPTH_CONTROL),
88 },
89 {
90 .dchubp = (mmHUBP3_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL),
91 .dpp = (mmCM3_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL),
92 .otg = (mmOTG3_OTG_CONTROL - mmOTG0_OTG_CONTROL),
93 .vtg = (mmVTG3_CONTROL - mmVTG0_CONTROL),
94 .fmt = (mmFMT3_FMT_BIT_DEPTH_CONTROL -
95 mmFMT0_FMT_BIT_DEPTH_CONTROL),
96 }
97 };
98
99 #define HWSEQ_REG_UPDATE_N(reg_name, n, ...) \
100 generic_reg_update_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__)
101
102 #define HWSEQ_REG_SET_N(reg_name, n, ...) \
103 generic_reg_set_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__)
104
105 #define HWSEQ_REG_UPDATE(reg, field, val) \
106 HWSEQ_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
107
108 #define HWSEQ_REG_UPDATE_2(reg, field1, val1, field2, val2) \
109 HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
110
111 #define HWSEQ_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \
112 HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
113
114
115 #define HWSEQ_REG_SET(reg, field, val) \
116 HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val)
117
118 /* TODO should be moved to OTG */
119 static void lock_otg_master_update(
120 struct dc_context *ctx,
121 uint8_t inst)
122 {
123 uint32_t inst_offset = reg_offsets[inst].otg;
124
125 HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0,
126 OTG_MASTER_UPDATE_LOCK_SEL, inst);
127
128 HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK,
129 OTG_MASTER_UPDATE_LOCK, 1);
130 }
131
132 static bool unlock_master_tg_and_wait(
133 struct dc_context *ctx,
134 uint8_t inst)
135 {
136 uint32_t inst_offset = reg_offsets[inst].otg;
137
138 HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_SYNC_STATUS,
139 VUPDATE_NO_LOCK_EVENT_CLEAR, 1);
140 HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 0);
141
142 if (!wait_reg(ctx, inst_offset, OTG0_OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, 1)) {
143 dm_logger_write(ctx->logger, LOG_ERROR,
144 "wait for VUPDATE_NO_LOCK_EVENT_OCCURRED failed\n");
145 BREAK_TO_DEBUGGER();
146 return false;
147 }
148 return true;
149 }
150
151 /* TODO: should be moved to OTG ? */
152 static void unlock_otg_master(
153 struct dc_context *ctx,
154 uint8_t inst)
155 {
156 uint32_t inst_offset = reg_offsets[inst].otg;
157
158 /* unlock master locker */
159 HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK,
160 OTG_MASTER_UPDATE_LOCK, 0);
161 }
162
163
164 static void wait_no_outstanding_request(
165 struct dc_context *ctx,
166 uint8_t plane_id)
167 {
168 uint32_t inst_offset = reg_offsets[plane_id].dchubp;
169
170 if (!wait_reg(ctx, inst_offset, HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1))
171 BREAK_TO_DEBUGGER();
172 }
173
174 static void disable_clocks(
175 struct dc_context *ctx,
176 uint8_t plane_id)
177 {
178 uint32_t inst_offset = reg_offsets[plane_id].dchubp;
179
180 generic_reg_update_soc15(ctx, inst_offset, HUBP0_HUBP_CLK_CNTL, 1,
181 FD(HUBP0_HUBP_CLK_CNTL__HUBP_CLOCK_ENABLE), 0);
182
183 inst_offset = reg_offsets[plane_id].dpp;
184 generic_reg_update_soc15(ctx, inst_offset, DPP_TOP0_DPP_CONTROL, 1,
185 FD(DPP_TOP0_DPP_CONTROL__DPP_CLOCK_ENABLE), 0);
186 }
187
188 /* TODO: This is one time program during system boot up,
189 * this should be done within BIOS or CAIL
190 */
191 static void dchubp_map_fb_to_mc(struct dc_context *ctx)
192 {
193 /* TODO: do not know where to program
194 * DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
195 */
196 /*
197 * TODO: For real ASIC, FB_OFFSET may be need change to the same value
198 * as FB_BASE. Need re-visit this for real ASIC.
199 */
200 dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_BASE, 0, 0x80);
201 dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_OFFSET, 0, 0);
202 dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_TOP, 0, 0xFF);
203
204 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG0, 7,
205 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_DATA_RESPONSE_STATUS_CLEAR), 0,
206 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_ERROR_CLEAR), 0,
207 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_FLUSH_REQ_CREDIT_EN), 0,
208 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_EN), 0,
209 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_PORT_CONTROL), 1,
210 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_UNIT_ID_BITMASK), 0xd3,
211 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_CREDIT_DISCONNECT_DELAY), 0xc);
212
213
214 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG1, 4,
215 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_IO), 0,
216 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_VC), 6,
217 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_IO), 1,
218 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_VC), 6);
219
220 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_BASE, 1,
221 FD(DCHUBBUB_SDPIF_FB_BASE__SDPIF_FB_BASE), 0x000080);
222
223 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_TOP, 1,
224 FD(DCHUBBUB_SDPIF_FB_TOP__SDPIF_FB_TOP), 0x0000ff);
225
226 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BOT, 1,
227 FD(DCHUBBUB_SDPIF_AGP_BOT__SDPIF_AGP_BOT), 0x0000040);
228
229 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_TOP, 1,
230 FD(DCHUBBUB_SDPIF_AGP_TOP__SDPIF_AGP_TOP), 0x00001ff);
231
232 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BASE, 1,
233 FD(DCHUBBUB_SDPIF_AGP_BASE__SDPIF_AGP_BASE), 0x0000080);
234
235 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_TOP, 1,
236 FD(DCHUBBUB_SDPIF_APER_TOP__SDPIF_APER_TOP), 0x00007ff);
237
238 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_DEF_0, 1,
239 FD(DCHUBBUB_SDPIF_APER_DEF_0__SDPIF_APER_DEF_0), 0xdeadbeef);
240
241 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_0, 2,
242 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_EN_0), 0,
243 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_RELOC_LO_0), 0x90000);
244
245 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_0, 1,
246 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_0__SDPIF_MARC_LENGTH_LO_0), 0x10000);
247
248 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_1, 1,
249 FD(DCHUBBUB_SDPIF_MARC_BASE_LO_1__SDPIF_MARC_BASE_LO_1), 0x10000);
250
251 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_1, 2,
252 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_EN_1), 0,
253 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_RELOC_LO_1), 0xa0000);
254
255 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_1, 1,
256 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_1__SDPIF_MARC_LENGTH_LO_1), 0x10000);
257
258 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_2, 1,
259 FD(DCHUBBUB_SDPIF_MARC_BASE_LO_2__SDPIF_MARC_BASE_LO_2), 0x20000);
260
261 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_2, 2,
262 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_EN_2), 0,
263 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_RELOC_LO_2), 0xb0000);
264
265 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_2, 1,
266 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_2__SDPIF_MARC_LENGTH_LO_2), 0x10000);
267
268 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_3, 1,
269 FD(DCHUBBUB_SDPIF_MARC_BASE_LO_3__SDPIF_MARC_BASE_LO_3), 0x30000);
270
271 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_3, 2,
272 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_EN_3), 0,
273 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_RELOC_LO_3), 0xc0000);
274
275 generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_3, 1,
276 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_3__SDPIF_MARC_LENGTH_LO_3), 0x10000);
277
278 /* TODO: Is DCN_VM_SYSTEM_APERTURE address one time programming?
279 * Are all 4 hubp programmed with the same address?
280 */
281 dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000);
282 dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0);
283 dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000);
284 dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0);
285 dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000);
286 dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0);
287
288 dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000);
289 dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0);
290 dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000);
291 dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0);
292 dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000);
293 dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0);
294
295 dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000);
296 dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0);
297 dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000);
298 dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0);
299 dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000);
300 dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0);
301
302 dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000);
303 dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0);
304 dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000);
305 dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0);
306 dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000);
307 dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0);
308 }
309
310 /* TODO: This is one time program during system boot up,
311 * this should be done within BIOS
312 */
313 static void dchubup_setup_timer(struct dc_context *ctx)
314 {
315 dm_write_reg_soc15(ctx, mmREFCLK_CNTL, 0, 0);
316
317 generic_reg_update_soc15(ctx, 0, DCHUBBUB_GLOBAL_TIMER_CNTL, 1,
318 FD(DCHUBBUB_GLOBAL_TIMER_CNTL__DCHUBBUB_GLOBAL_TIMER_ENABLE), 1);
319 }
320
321 /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
322 * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
323 * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
324 */
325 static void select_vtg(
326 struct dc_context *ctx,
327 uint8_t plane_id,
328 uint8_t inst)
329 {
330 uint32_t inst_offset = reg_offsets[plane_id].dchubp;
331
332 HWSEQ_REG_UPDATE(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, inst);
333 }
334
335 static void enable_dcfclk(
336 struct dc_context *ctx,
337 uint8_t plane_id,
338 uint32_t requested_pix_clk,
339 bool dppclk_div)
340 {
341 uint32_t inst_offset = reg_offsets[plane_id].dchubp;
342
343 HWSEQ_REG_UPDATE(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, 1);
344 }
345
346 static void enable_dppclk(
347 struct dc_context *ctx,
348 uint8_t plane_id,
349 uint32_t requested_pix_clk,
350 bool dppclk_div)
351 {
352 uint32_t inst_offset = reg_offsets[plane_id].dpp;
353
354 dm_logger_write(ctx->logger, LOG_SURFACE,
355 "dppclk_rate_control for pipe %d programed to %d\n",
356 plane_id,
357 dppclk_div);
358
359 /* TODO: find condition for DPP clock to DISPCLK or 1/2 DISPCLK */
360 if (dppclk_div) {
361 /* 1/2 DISPCLK*/
362 HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL,
363 DPPCLK_RATE_CONTROL, 1,
364 DPP_CLOCK_ENABLE, 1);
365 } else {
366 /* DISPCLK */
367 HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL,
368 DPPCLK_RATE_CONTROL, 0,
369 DPP_CLOCK_ENABLE, 1);
370 }
371 }
372
373 static void enable_power_gating_plane(
374 struct dc_context *ctx,
375 bool enable)
376 {
377 uint32_t inst_offset = 0; /* each register only has one instance */
378 bool force_on = 1; /* disable power gating */
379
380 if (enable)
381 force_on = 0;
382
383 /* DCHUBP0/1/2/3 */
384 HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
385 HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
386 HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
387 HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
388
389 /* DPP0/1/2/3 */
390 HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
391 HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
392 HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
393 HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
394 }
395
396 static void dpp_pg_control(
397 struct dc_context *ctx,
398 unsigned int dpp_inst,
399 bool power_on)
400 {
401 uint32_t inst_offset = 0;
402 uint32_t power_gate = power_on ? 0 : 1;
403 uint32_t pwr_status = power_on ? 0 : 2;
404
405 if (ctx->dc->debug.disable_dpp_power_gate)
406 return;
407
408 switch (dpp_inst) {
409 case 0: /* DPP0 */
410 HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG,
411 DOMAIN1_POWER_GATE, power_gate);
412
413 wait_reg(ctx, 0, DOMAIN1_PG_STATUS,
414 DOMAIN1_PGFSM_PWR_STATUS, pwr_status);
415 break;
416 case 1: /* DPP1 */
417 HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG,
418 DOMAIN3_POWER_GATE, power_gate);
419
420 wait_reg(ctx, 0, DOMAIN3_PG_STATUS,
421 DOMAIN3_PGFSM_PWR_STATUS, pwr_status);
422 break;
423 case 2: /* DPP2 */
424 HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG,
425 DOMAIN5_POWER_GATE, power_gate);
426
427 wait_reg(ctx, 0, DOMAIN5_PG_STATUS,
428 DOMAIN5_PGFSM_PWR_STATUS, pwr_status);
429 break;
430 case 3: /* DPP3 */
431 HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG,
432 DOMAIN7_POWER_GATE, power_gate);
433
434 wait_reg(ctx, 0, DOMAIN7_PG_STATUS,
435 DOMAIN7_PGFSM_PWR_STATUS, pwr_status);
436 break;
437 default:
438 BREAK_TO_DEBUGGER();
439 break;
440 }
441 }
442
443 static void hubp_pg_control(
444 struct dc_context *ctx,
445 unsigned int hubp_inst,
446 bool power_on)
447 {
448 uint32_t inst_offset = 0;
449 uint32_t power_gate = power_on ? 0 : 1;
450 uint32_t pwr_status = power_on ? 0 : 2;
451
452 if (ctx->dc->debug.disable_hubp_power_gate)
453 return;
454
455 switch (hubp_inst) {
456 case 0: /* DCHUBP0 */
457 HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG,
458 DOMAIN0_POWER_GATE, power_gate);
459
460 wait_reg(ctx, 0, DOMAIN0_PG_STATUS,
461 DOMAIN0_PGFSM_PWR_STATUS, pwr_status);
462 break;
463 case 1: /* DCHUBP1 */
464 HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG,
465 DOMAIN2_POWER_GATE, power_gate);
466
467 wait_reg(ctx, 0, DOMAIN2_PG_STATUS,
468 DOMAIN2_PGFSM_PWR_STATUS, pwr_status);
469 break;
470 case 2: /* DCHUBP2 */
471 HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG,
472 DOMAIN4_POWER_GATE, power_gate);
473
474 wait_reg(ctx, 0, DOMAIN4_PG_STATUS,
475 DOMAIN4_PGFSM_PWR_STATUS, pwr_status);
476 break;
477 case 3: /* DCHUBP3 */
478 HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG,
479 DOMAIN6_POWER_GATE, power_gate);
480
481 wait_reg(ctx, 0, DOMAIN6_PG_STATUS,
482 DOMAIN6_PGFSM_PWR_STATUS, pwr_status);
483 break;
484 default:
485 BREAK_TO_DEBUGGER();
486 break;
487 }
488 }
489
490 static void power_on_plane(
491 struct dc_context *ctx,
492 uint8_t plane_id,
493 uint8_t inst)
494 {
495 uint32_t inst_offset = 0;
496
497 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
498 IP_REQUEST_EN, 1);
499 dpp_pg_control(ctx, plane_id, true);
500 hubp_pg_control(ctx, plane_id, true);
501 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
502 IP_REQUEST_EN, 0);
503 }
504
505 /* fully check bios enabledisplaypowergating table. dal only need dce init
506 * other power, clock gate register will be handle by dal itself.
507 * further may be put within init_hw
508 */
509 static bool dcn10_enable_display_power_gating(
510 struct core_dc *dc,
511 uint8_t controller_id,
512 struct dc_bios *dcb,
513 enum pipe_gating_control power_gating)
514 {
515 /* TODOFPGA */
516 #if 0
517 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
518 dce110_init_pte(ctx);
519 #endif
520
521 return true;
522 }
523
524 static void bios_golden_init(struct core_dc *dc)
525 {
526 struct dc_bios *bp = dc->ctx->dc_bios;
527 int i;
528
529 /* initialize dcn global */
530 bp->funcs->enable_disp_power_gating(bp,
531 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
532
533 for (i = 0; i < dc->res_pool->pipe_count; i++) {
534 /* initialize dcn per pipe */
535 bp->funcs->enable_disp_power_gating(bp,
536 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
537 }
538 }
539
540 static void init_hw(struct core_dc *dc)
541 {
542 int i;
543 struct dc_bios *bp;
544 struct transform *xfm;
545 struct abm *abm;
546
547 bp = dc->ctx->dc_bios;
548
549 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
550 /* TODO: this will be moved to Diag or BIOS */
551 dchubup_setup_timer(dc->ctx);
552
553 /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface
554 * between dc and kmd
555 */
556 dchubp_map_fb_to_mc(dc->ctx);
557
558 enable_power_gating_plane(dc->ctx, true);
559 return;
560 }
561 /* end of FPGA. Below if real ASIC */
562
563 bios_golden_init(dc);
564
565 for (i = 0; i < dc->res_pool->pipe_count; i++) {
566 xfm = dc->res_pool->transforms[i];
567 xfm->funcs->transform_reset(xfm);
568
569 /* TODOFPGA: may need later */
570 #if 0
571 xfm->funcs->transform_power_up(xfm);
572 dc->hwss.enable_display_pipe_clock_gating(
573 dc->ctx,
574 true);
575 #endif
576 }
577 /* TODOFPGA: light sleep */
578 #if 0
579 dc->hwss.clock_gating_power_up(dc->ctx, false);
580 #endif
581
582 for (i = 0; i < dc->link_count; i++) {
583 /* Power up AND update implementation according to the
584 * required signal (which may be different from the
585 * default signal on connector).
586 */
587 struct core_link *link = dc->links[i];
588
589 link->link_enc->funcs->hw_init(link->link_enc);
590 }
591
592 for (i = 0; i < dc->res_pool->pipe_count; i++) {
593 struct timing_generator *tg =
594 dc->res_pool->timing_generators[i];
595
596 tg->funcs->disable_vga(tg);
597
598 /* Blank controller using driver code instead of
599 * command table.
600 */
601 tg->funcs->set_blank(tg, true);
602 hwss_wait_for_blank_complete(tg);
603 }
604
605 for (i = 0; i < dc->res_pool->audio_count; i++) {
606 struct audio *audio = dc->res_pool->audios[i];
607
608 audio->funcs->hw_init(audio);
609 }
610
611 abm = dc->res_pool->abm;
612 if (abm != NULL) {
613 abm->funcs->init_backlight(abm);
614 abm->funcs->abm_init(abm);
615 }
616
617 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
618 generic_reg_set_soc15(dc->ctx, 0, DIO_MEM_PWR_CTRL, 7,
619 FD(DIO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE), 0,
620 FD(DIO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE), 0,
621 FD(DIO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE), 0,
622 FD(DIO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE), 0,
623 FD(DIO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE), 0,
624 FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0,
625 FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0);
626
627 if (!dc->public.debug.disable_clock_gate) {
628 /* enable all DCN clock gating */
629 generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL, 19,
630 FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE), 0,
631 FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE), 0,
632 FD(DCCG_GATE_DISABLE_CNTL__SOCCLK_GATE_DISABLE), 0,
633 FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE), 0,
634 FD(DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE), 0,
635 FD(DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE), 0,
636 FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE), 0,
637 FD(DCCG_GATE_DISABLE_CNTL__DPPCLK_GATE_DISABLE), 0,
638 FD(DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE), 0,
639 FD(DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE), 0,
640 FD(DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE), 0,
641 FD(DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE), 0,
642 FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE), 0,
643 FD(DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE), 0,
644 FD(DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE), 0,
645 FD(DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE), 0,
646 FD(DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE), 0,
647 FD(DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE), 0,
648 FD(DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE), 0);
649
650 generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL2, 14,
651 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE), 0,
652 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE), 0,
653 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE), 0,
654 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE), 0,
655 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE), 0,
656 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE), 0,
657 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE), 0,
658 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE), 0,
659 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE), 0,
660 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE), 0,
661 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE), 0,
662 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE), 0,
663 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE), 0,
664 FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE), 0);
665
666 generic_reg_update_soc15(dc->ctx, 0, DCFCLK_CNTL, 1,
667 FD(DCFCLK_CNTL__DCFCLK_GATE_DIS), 0);
668 }
669
670 /* This power gating should be one-time program for DAL.
671 * It can only change by registry key
672 * TODO: new task will for this.
673 * if power gating is disable, power_on_plane and power_off_plane
674 * should be skip. Otherwise, hand will be met in power_off_plane
675 */
676 enable_power_gating_plane(dc->ctx, true);
677
678
679 }
680
681 static enum dc_status dcn10_prog_pixclk_crtc_otg(
682 struct pipe_ctx *pipe_ctx,
683 struct validate_context *context,
684 struct core_dc *dc)
685 {
686 struct core_stream *stream = pipe_ctx->stream;
687 enum dc_color_space color_space;
688 struct tg_color black_color = {0};
689 bool enableStereo = stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_NONE ?
690 false:true;
691 bool rightEyePolarity = stream->public.timing.flags.RIGHT_EYE_3D_POLARITY;
692
693
694 /* by upper caller loop, pipe0 is parent pipe and be called first.
695 * back end is set up by for pipe0. Other children pipe share back end
696 * with pipe 0. No program is needed.
697 */
698 if (pipe_ctx->top_pipe != NULL)
699 return DC_OK;
700
701 /* TODO check if timing_changed, disable stream if timing changed */
702
703 /* HW program guide assume display already disable
704 * by unplug sequence. OTG assume stop.
705 */
706 pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, true);
707
708 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
709 pipe_ctx->clock_source,
710 &pipe_ctx->pix_clk_params,
711 &pipe_ctx->pll_settings)) {
712 BREAK_TO_DEBUGGER();
713 return DC_ERROR_UNEXPECTED;
714 }
715 pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
716 pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
717 pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
718 pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
719
720 pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
721
722 pipe_ctx->tg->funcs->program_timing(
723 pipe_ctx->tg,
724 &stream->public.timing,
725 true);
726
727 pipe_ctx->opp->funcs->opp_set_stereo_polarity(
728 pipe_ctx->opp,
729 enableStereo,
730 rightEyePolarity);
731
732 #if 0 /* move to after enable_crtc */
733 /* TODO: OPP FMT, ABM. etc. should be done here. */
734 /* or FPGA now. instance 0 only. TODO: move to opp.c */
735
736 inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt;
737
738 pipe_ctx->opp->funcs->opp_program_fmt(
739 pipe_ctx->opp,
740 &stream->bit_depth_params,
741 &stream->clamping);
742 #endif
743 /* program otg blank color */
744 color_space = stream->public.output_color_space;
745 color_space_to_black_color(dc, color_space, &black_color);
746 pipe_ctx->tg->funcs->set_blank_color(
747 pipe_ctx->tg,
748 &black_color);
749
750 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
751 hwss_wait_for_blank_complete(pipe_ctx->tg);
752
753 /* VTG is within DCHUB command block. DCFCLK is always on */
754 if (false == pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) {
755 BREAK_TO_DEBUGGER();
756 return DC_ERROR_UNEXPECTED;
757 }
758
759 /* TODO program crtc source select for non-virtual signal*/
760 /* TODO program FMT */
761 /* TODO setup link_enc */
762 /* TODO set stream attributes */
763 /* TODO program audio */
764 /* TODO enable stream if timing changed */
765 /* TODO unblank stream if DP */
766
767 return DC_OK;
768 }
769
770 static void reset_back_end_for_pipe(
771 struct core_dc *dc,
772 struct pipe_ctx *pipe_ctx,
773 struct validate_context *context)
774 {
775 int i;
776 struct dc_bios *bp;
777
778 bp = dc->ctx->dc_bios;
779
780 if (pipe_ctx->stream_enc == NULL) {
781 pipe_ctx->stream = NULL;
782 return;
783 }
784
785 /* TODOFPGA break core_link_disable_stream into 2 functions:
786 * disable_stream and disable_link. disable_link will disable PHYPLL
787 * which is used by otg. Move disable_link after disable_crtc
788 */
789 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
790 core_link_disable_stream(pipe_ctx);
791
792 /* by upper caller loop, parent pipe: pipe0, will be reset last.
793 * back end share by all pipes and will be disable only when disable
794 * parent pipe.
795 */
796 if (pipe_ctx->top_pipe == NULL) {
797 pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
798
799 pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, false);
800 }
801
802 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
803 resource_unreference_clock_source(
804 &context->res_ctx, dc->res_pool,
805 &pipe_ctx->clock_source);
806
807 for (i = 0; i < dc->res_pool->pipe_count; i++)
808 if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe_ctx)
809 break;
810
811 if (i == dc->res_pool->pipe_count)
812 return;
813
814 pipe_ctx->stream = NULL;
815 }
816
817 static void reset_front_end_for_pipe(
818 struct core_dc *dc,
819 struct pipe_ctx *pipe_ctx,
820 struct validate_context *context)
821 {
822 struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc);
823 struct mpc_tree_cfg *tree_cfg = NULL;
824
825 if (!pipe_ctx->surface)
826 return;
827
828 lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst);
829
830 /* TODO: build stream pipes group id. For now, use stream otg
831 * id as pipe group id
832 */
833 tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx];
834
835 if (!dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) {
836 dm_logger_write(dc->ctx->logger, LOG_RESOURCE,
837 "%s: failed to find dpp to be removed!\n",
838 __func__);
839 }
840
841 pipe_ctx->top_pipe = NULL;
842 pipe_ctx->bottom_pipe = NULL;
843 pipe_ctx->mpc_idx = -1;
844
845 unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst);
846
847 pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true);
848
849 wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx);
850
851 wait_mpcc_idle(mpc, pipe_ctx->pipe_idx);
852
853 disable_clocks(dc->ctx, pipe_ctx->pipe_idx);
854
855 pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm);
856
857 dm_logger_write(dc->ctx->logger, LOG_DC,
858 "Reset front end for pipe %d\n",
859 pipe_ctx->pipe_idx);
860
861 pipe_ctx->surface = NULL;
862 }
863
864 static void reset_hw_ctx(struct core_dc *dc,
865 struct validate_context *context,
866 void (*reset)(struct core_dc *dc,
867 struct pipe_ctx *pipe_ctx,
868 struct validate_context *context))
869 {
870 int i;
871
872 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
873 struct pipe_ctx *pipe_ctx_old =
874 &dc->current_context->res_ctx.pipe_ctx[i];
875 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
876
877 if (!pipe_ctx_old->stream)
878 continue;
879
880 if (!pipe_ctx->stream ||
881 pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
882 reset(dc, pipe_ctx_old, dc->current_context);
883 }
884 }
885
886 static void reset_hw_ctx_wrap(
887 struct core_dc *dc,
888 struct validate_context *context)
889 {
890 /* Reset Front End*/
891 reset_hw_ctx(dc, context, reset_front_end_for_pipe);
892 /* Reset Back End*/
893 reset_hw_ctx(dc, context, reset_back_end_for_pipe);
894
895 memcpy(context->res_ctx.mpc_tree,
896 dc->current_context->res_ctx.mpc_tree,
897 sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count);
898 }
899
900 static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx,
901 PHYSICAL_ADDRESS_LOC *addr)
902 {
903 struct core_surface *surface = pipe_ctx->surface;
904 bool sec_split = pipe_ctx->top_pipe &&
905 pipe_ctx->top_pipe->surface == pipe_ctx->surface;
906 if (sec_split && surface->public.address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
907 (pipe_ctx->stream->public.timing.timing_3d_format ==
908 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
909 pipe_ctx->stream->public.timing.timing_3d_format ==
910 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
911 *addr = surface->public.address.grph_stereo.left_addr;
912 surface->public.address.grph_stereo.left_addr =\
913 surface->public.address.grph_stereo.right_addr;
914 return true;
915 }
916 return false;
917 }
918
919 static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx)
920 {
921 bool addr_patched = false;
922 PHYSICAL_ADDRESS_LOC addr;
923 struct core_surface *surface = pipe_ctx->surface;
924
925 if (surface == NULL)
926 return;
927 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
928 pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
929 pipe_ctx->mi,
930 &surface->public.address,
931 surface->public.flip_immediate);
932 surface->status.requested_address = surface->public.address;
933 if (addr_patched)
934 pipe_ctx->surface->public.address.grph_stereo.left_addr = addr;
935 }
936
937 static bool dcn10_set_input_transfer_func(
938 struct pipe_ctx *pipe_ctx,
939 const struct core_surface *surface)
940 {
941 struct input_pixel_processor *ipp = pipe_ctx->ipp;
942 const struct core_transfer_func *tf = NULL;
943 bool result = true;
944
945 if (ipp == NULL)
946 return false;
947
948 if (surface->public.in_transfer_func)
949 tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
950
951 if (surface->public.gamma_correction && dce_use_lut(surface))
952 ipp->funcs->ipp_program_input_lut(ipp,
953 surface->public.gamma_correction);
954
955 if (tf == NULL)
956 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
957 else if (tf->public.type == TF_TYPE_PREDEFINED) {
958 switch (tf->public.tf) {
959 case TRANSFER_FUNCTION_SRGB:
960 ipp->funcs->ipp_set_degamma(ipp,
961 IPP_DEGAMMA_MODE_HW_sRGB);
962 break;
963 case TRANSFER_FUNCTION_BT709:
964 ipp->funcs->ipp_set_degamma(ipp,
965 IPP_DEGAMMA_MODE_HW_xvYCC);
966 break;
967 case TRANSFER_FUNCTION_LINEAR:
968 ipp->funcs->ipp_set_degamma(ipp,
969 IPP_DEGAMMA_MODE_BYPASS);
970 break;
971 case TRANSFER_FUNCTION_PQ:
972 result = false;
973 break;
974 default:
975 result = false;
976 break;
977 }
978 } else if (tf->public.type == TF_TYPE_BYPASS) {
979 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
980 } else {
981 /*TF_TYPE_DISTRIBUTED_POINTS*/
982 result = false;
983 }
984
985 return result;
986 }
987 /*modify the method to handle rgb for arr_points*/
988 static bool convert_to_custom_float(
989 struct pwl_result_data *rgb_resulted,
990 struct curve_points *arr_points,
991 uint32_t hw_points_num)
992 {
993 struct custom_float_format fmt;
994
995 struct pwl_result_data *rgb = rgb_resulted;
996
997 uint32_t i = 0;
998
999 fmt.exponenta_bits = 6;
1000 fmt.mantissa_bits = 12;
1001 fmt.sign = false;
1002
1003 if (!convert_to_custom_float_format(
1004 arr_points[0].x,
1005 &fmt,
1006 &arr_points[0].custom_float_x)) {
1007 BREAK_TO_DEBUGGER();
1008 return false;
1009 }
1010
1011 if (!convert_to_custom_float_format(
1012 arr_points[0].offset,
1013 &fmt,
1014 &arr_points[0].custom_float_offset)) {
1015 BREAK_TO_DEBUGGER();
1016 return false;
1017 }
1018
1019 if (!convert_to_custom_float_format(
1020 arr_points[0].slope,
1021 &fmt,
1022 &arr_points[0].custom_float_slope)) {
1023 BREAK_TO_DEBUGGER();
1024 return false;
1025 }
1026
1027 fmt.mantissa_bits = 10;
1028 fmt.sign = false;
1029
1030 if (!convert_to_custom_float_format(
1031 arr_points[1].x,
1032 &fmt,
1033 &arr_points[1].custom_float_x)) {
1034 BREAK_TO_DEBUGGER();
1035 return false;
1036 }
1037
1038 if (!convert_to_custom_float_format(
1039 arr_points[1].y,
1040 &fmt,
1041 &arr_points[1].custom_float_y)) {
1042 BREAK_TO_DEBUGGER();
1043 return false;
1044 }
1045
1046 if (!convert_to_custom_float_format(
1047 arr_points[1].slope,
1048 &fmt,
1049 &arr_points[1].custom_float_slope)) {
1050 BREAK_TO_DEBUGGER();
1051 return false;
1052 }
1053
1054 fmt.mantissa_bits = 12;
1055 fmt.sign = true;
1056
1057 while (i != hw_points_num) {
1058 if (!convert_to_custom_float_format(
1059 rgb->red,
1060 &fmt,
1061 &rgb->red_reg)) {
1062 BREAK_TO_DEBUGGER();
1063 return false;
1064 }
1065
1066 if (!convert_to_custom_float_format(
1067 rgb->green,
1068 &fmt,
1069 &rgb->green_reg)) {
1070 BREAK_TO_DEBUGGER();
1071 return false;
1072 }
1073
1074 if (!convert_to_custom_float_format(
1075 rgb->blue,
1076 &fmt,
1077 &rgb->blue_reg)) {
1078 BREAK_TO_DEBUGGER();
1079 return false;
1080 }
1081
1082 if (!convert_to_custom_float_format(
1083 rgb->delta_red,
1084 &fmt,
1085 &rgb->delta_red_reg)) {
1086 BREAK_TO_DEBUGGER();
1087 return false;
1088 }
1089
1090 if (!convert_to_custom_float_format(
1091 rgb->delta_green,
1092 &fmt,
1093 &rgb->delta_green_reg)) {
1094 BREAK_TO_DEBUGGER();
1095 return false;
1096 }
1097
1098 if (!convert_to_custom_float_format(
1099 rgb->delta_blue,
1100 &fmt,
1101 &rgb->delta_blue_reg)) {
1102 BREAK_TO_DEBUGGER();
1103 return false;
1104 }
1105
1106 ++rgb;
1107 ++i;
1108 }
1109
1110 return true;
1111 }
1112 #define MAX_REGIONS_NUMBER 34
1113 #define MAX_LOW_POINT 25
1114 #define NUMBER_SEGMENTS 32
1115
1116 static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func
1117 *output_tf, struct pwl_params *regamma_params)
1118 {
1119 struct curve_points *arr_points;
1120 struct pwl_result_data *rgb_resulted;
1121 struct pwl_result_data *rgb;
1122 struct pwl_result_data *rgb_plus_1;
1123 struct fixed31_32 y_r;
1124 struct fixed31_32 y_g;
1125 struct fixed31_32 y_b;
1126 struct fixed31_32 y1_min;
1127 struct fixed31_32 y3_max;
1128
1129 int32_t segment_start, segment_end;
1130 int32_t i;
1131 uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
1132
1133 if (output_tf == NULL || regamma_params == NULL ||
1134 output_tf->type == TF_TYPE_BYPASS)
1135 return false;
1136
1137 arr_points = regamma_params->arr_points;
1138 rgb_resulted = regamma_params->rgb_resulted;
1139 hw_points = 0;
1140
1141 memset(regamma_params, 0, sizeof(struct pwl_params));
1142 memset(seg_distr, 0, sizeof(seg_distr));
1143
1144 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
1145 /* 32 segments
1146 * segments are from 2^-25 to 2^7
1147 */
1148 for (i = 0; i < 32 ; i++)
1149 seg_distr[i] = 3;
1150
1151 segment_start = -25;
1152 segment_end = 7;
1153 } else {
1154 /* 10 segments
1155 * segment is from 2^-10 to 2^0
1156 * There are less than 256 points, for optimization
1157 */
1158 seg_distr[0] = 3;
1159 seg_distr[1] = 4;
1160 seg_distr[2] = 4;
1161 seg_distr[3] = 4;
1162 seg_distr[4] = 4;
1163 seg_distr[5] = 4;
1164 seg_distr[6] = 4;
1165 seg_distr[7] = 4;
1166 seg_distr[8] = 5;
1167 seg_distr[9] = 5;
1168
1169 segment_start = -10;
1170 segment_end = 0;
1171 }
1172
1173 for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++)
1174 seg_distr[i] = -1;
1175
1176 for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
1177 if (seg_distr[k] != -1)
1178 hw_points += (1 << seg_distr[k]);
1179 }
1180
1181 j = 0;
1182 for (k = 0; k < (segment_end - segment_start); k++) {
1183 increment = NUMBER_SEGMENTS / (1 << seg_distr[k]);
1184 start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS;
1185 for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) {
1186 if (j == hw_points - 1)
1187 break;
1188 rgb_resulted[j].red = output_tf->tf_pts.red[i];
1189 rgb_resulted[j].green = output_tf->tf_pts.green[i];
1190 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
1191 j++;
1192 }
1193 }
1194
1195 /* last point */
1196 start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS;
1197 rgb_resulted[hw_points - 1].red =
1198 output_tf->tf_pts.red[start_index];
1199 rgb_resulted[hw_points - 1].green =
1200 output_tf->tf_pts.green[start_index];
1201 rgb_resulted[hw_points - 1].blue =
1202 output_tf->tf_pts.blue[start_index];
1203
1204 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
1205 dal_fixed31_32_from_int(segment_start));
1206 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
1207 dal_fixed31_32_from_int(segment_end));
1208 arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
1209 dal_fixed31_32_from_int(segment_end));
1210
1211 y_r = rgb_resulted[0].red;
1212 y_g = rgb_resulted[0].green;
1213 y_b = rgb_resulted[0].blue;
1214
1215 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
1216
1217 arr_points[0].y = y1_min;
1218 arr_points[0].slope = dal_fixed31_32_div(
1219 arr_points[0].y,
1220 arr_points[0].x);
1221 y_r = rgb_resulted[hw_points - 1].red;
1222 y_g = rgb_resulted[hw_points - 1].green;
1223 y_b = rgb_resulted[hw_points - 1].blue;
1224
1225 /* see comment above, m_arrPoints[1].y should be the Y value for the
1226 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
1227 */
1228 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
1229
1230 arr_points[1].y = y3_max;
1231 arr_points[2].y = y3_max;
1232
1233 arr_points[1].slope = dal_fixed31_32_zero;
1234 arr_points[2].slope = dal_fixed31_32_zero;
1235
1236 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
1237 /* for PQ, we want to have a straight line from last HW X point,
1238 * and the slope to be such that we hit 1.0 at 10000 nits.
1239 */
1240 const struct fixed31_32 end_value =
1241 dal_fixed31_32_from_int(125);
1242
1243 arr_points[1].slope = dal_fixed31_32_div(
1244 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
1245 dal_fixed31_32_sub(end_value, arr_points[1].x));
1246 arr_points[2].slope = dal_fixed31_32_div(
1247 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
1248 dal_fixed31_32_sub(end_value, arr_points[1].x));
1249 }
1250
1251 regamma_params->hw_points_num = hw_points;
1252
1253 i = 1;
1254 for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) {
1255 if (seg_distr[k] != -1) {
1256 regamma_params->arr_curve_points[k].segments_num =
1257 seg_distr[k];
1258 regamma_params->arr_curve_points[i].offset =
1259 regamma_params->arr_curve_points[k].
1260 offset + (1 << seg_distr[k]);
1261 }
1262 i++;
1263 }
1264
1265 if (seg_distr[k] != -1)
1266 regamma_params->arr_curve_points[k].segments_num =
1267 seg_distr[k];
1268
1269 rgb = rgb_resulted;
1270 rgb_plus_1 = rgb_resulted + 1;
1271
1272 i = 1;
1273
1274 while (i != hw_points + 1) {
1275 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
1276 rgb_plus_1->red = rgb->red;
1277 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
1278 rgb_plus_1->green = rgb->green;
1279 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
1280 rgb_plus_1->blue = rgb->blue;
1281
1282 rgb->delta_red = dal_fixed31_32_sub(
1283 rgb_plus_1->red,
1284 rgb->red);
1285 rgb->delta_green = dal_fixed31_32_sub(
1286 rgb_plus_1->green,
1287 rgb->green);
1288 rgb->delta_blue = dal_fixed31_32_sub(
1289 rgb_plus_1->blue,
1290 rgb->blue);
1291
1292 ++rgb_plus_1;
1293 ++rgb;
1294 ++i;
1295 }
1296
1297 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
1298
1299 return true;
1300 }
1301
1302 static bool dcn10_set_output_transfer_func(
1303 struct pipe_ctx *pipe_ctx,
1304 const struct core_stream *stream)
1305 {
1306 struct output_pixel_processor *opp = pipe_ctx->opp;
1307
1308 if (opp == NULL)
1309 return false;
1310
1311 opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
1312
1313 if (stream->public.out_transfer_func &&
1314 stream->public.out_transfer_func->type ==
1315 TF_TYPE_PREDEFINED &&
1316 stream->public.out_transfer_func->tf ==
1317 TRANSFER_FUNCTION_SRGB) {
1318 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
1319 } else if (dcn10_translate_regamma_to_hw_format(
1320 stream->public.out_transfer_func, &opp->regamma_params)) {
1321 opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params);
1322 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
1323 } else {
1324 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
1325 }
1326
1327 return true;
1328 }
1329
1330 static void dcn10_pipe_control_lock(
1331 struct core_dc *dc,
1332 struct pipe_ctx *pipe,
1333 bool lock)
1334 {
1335 struct dce_hwseq *hws = hws = dc->hwseq;
1336
1337 /* use TG master update lock to lock everything on the TG
1338 * therefore only top pipe need to lock
1339 */
1340 if (pipe->top_pipe)
1341 return;
1342
1343 if (lock)
1344 dcn10_lock(pipe->tg);
1345 else
1346 dcn10_unlock(pipe->tg);
1347 }
1348
1349 static bool wait_for_reset_trigger_to_occur(
1350 struct dc_context *dc_ctx,
1351 struct timing_generator *tg)
1352 {
1353 bool rc = false;
1354
1355 /* To avoid endless loop we wait at most
1356 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1357 const uint32_t frames_to_wait_on_triggered_reset = 10;
1358 int i;
1359
1360 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1361
1362 if (!tg->funcs->is_counter_moving(tg)) {
1363 DC_ERROR("TG counter is not moving!\n");
1364 break;
1365 }
1366
1367 if (tg->funcs->did_triggered_reset_occur(tg)) {
1368 rc = true;
1369 /* usually occurs at i=1 */
1370 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1371 i);
1372 break;
1373 }
1374
1375 /* Wait for one frame. */
1376 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1377 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1378 }
1379
1380 if (false == rc)
1381 DC_ERROR("GSL: Timeout on reset trigger!\n");
1382
1383 return rc;
1384 }
1385
1386 static void dcn10_enable_timing_synchronization(
1387 struct core_dc *dc,
1388 int group_index,
1389 int group_size,
1390 struct pipe_ctx *grouped_pipes[])
1391 {
1392 struct dc_context *dc_ctx = dc->ctx;
1393 int i;
1394
1395 DC_SYNC_INFO("Setting up OTG reset trigger\n");
1396
1397 for (i = 1; i < group_size; i++)
1398 grouped_pipes[i]->tg->funcs->enable_reset_trigger(
1399 grouped_pipes[i]->tg, grouped_pipes[0]->tg->inst);
1400
1401
1402 DC_SYNC_INFO("Waiting for trigger\n");
1403
1404 /* Need to get only check 1 pipe for having reset as all the others are
1405 * synchronized. Look at last pipe programmed to reset.
1406 */
1407 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->tg);
1408 for (i = 1; i < group_size; i++)
1409 grouped_pipes[i]->tg->funcs->disable_reset_trigger(
1410 grouped_pipes[i]->tg);
1411
1412 DC_SYNC_INFO("Sync complete\n");
1413 }
1414
1415 static void print_rq_dlg_ttu(
1416 struct core_dc *core_dc,
1417 struct pipe_ctx *pipe_ctx)
1418 {
1419 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1420 "\n============== DML TTU Output parameters [%d] ==============\n"
1421 "qos_level_low_wm: %d, \n"
1422 "qos_level_high_wm: %d, \n"
1423 "min_ttu_vblank: %d, \n"
1424 "qos_level_flip: %d, \n"
1425 "refcyc_per_req_delivery_l: %d, \n"
1426 "qos_level_fixed_l: %d, \n"
1427 "qos_ramp_disable_l: %d, \n"
1428 "refcyc_per_req_delivery_pre_l: %d, \n"
1429 "refcyc_per_req_delivery_c: %d, \n"
1430 "qos_level_fixed_c: %d, \n"
1431 "qos_ramp_disable_c: %d, \n"
1432 "refcyc_per_req_delivery_pre_c: %d\n"
1433 "=============================================================\n",
1434 pipe_ctx->pipe_idx,
1435 pipe_ctx->ttu_regs.qos_level_low_wm,
1436 pipe_ctx->ttu_regs.qos_level_high_wm,
1437 pipe_ctx->ttu_regs.min_ttu_vblank,
1438 pipe_ctx->ttu_regs.qos_level_flip,
1439 pipe_ctx->ttu_regs.refcyc_per_req_delivery_l,
1440 pipe_ctx->ttu_regs.qos_level_fixed_l,
1441 pipe_ctx->ttu_regs.qos_ramp_disable_l,
1442 pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l,
1443 pipe_ctx->ttu_regs.refcyc_per_req_delivery_c,
1444 pipe_ctx->ttu_regs.qos_level_fixed_c,
1445 pipe_ctx->ttu_regs.qos_ramp_disable_c,
1446 pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c
1447 );
1448
1449 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1450 "\n============== DML DLG Output parameters [%d] ==============\n"
1451 "refcyc_h_blank_end: %d, \n"
1452 "dlg_vblank_end: %d, \n"
1453 "min_dst_y_next_start: %d, \n"
1454 "refcyc_per_htotal: %d, \n"
1455 "refcyc_x_after_scaler: %d, \n"
1456 "dst_y_after_scaler: %d, \n"
1457 "dst_y_prefetch: %d, \n"
1458 "dst_y_per_vm_vblank: %d, \n"
1459 "dst_y_per_row_vblank: %d, \n"
1460 "ref_freq_to_pix_freq: %d, \n"
1461 "vratio_prefetch: %d, \n"
1462 "refcyc_per_pte_group_vblank_l: %d, \n"
1463 "refcyc_per_meta_chunk_vblank_l: %d, \n"
1464 "dst_y_per_pte_row_nom_l: %d, \n"
1465 "refcyc_per_pte_group_nom_l: %d, \n",
1466 pipe_ctx->pipe_idx,
1467 pipe_ctx->dlg_regs.refcyc_h_blank_end,
1468 pipe_ctx->dlg_regs.dlg_vblank_end,
1469 pipe_ctx->dlg_regs.min_dst_y_next_start,
1470 pipe_ctx->dlg_regs.refcyc_per_htotal,
1471 pipe_ctx->dlg_regs.refcyc_x_after_scaler,
1472 pipe_ctx->dlg_regs.dst_y_after_scaler,
1473 pipe_ctx->dlg_regs.dst_y_prefetch,
1474 pipe_ctx->dlg_regs.dst_y_per_vm_vblank,
1475 pipe_ctx->dlg_regs.dst_y_per_row_vblank,
1476 pipe_ctx->dlg_regs.ref_freq_to_pix_freq,
1477 pipe_ctx->dlg_regs.vratio_prefetch,
1478 pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l,
1479 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l,
1480 pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l,
1481 pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l
1482 );
1483
1484 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1485 "\ndst_y_per_meta_row_nom_l: %d, \n"
1486 "refcyc_per_meta_chunk_nom_l: %d, \n"
1487 "refcyc_per_line_delivery_pre_l: %d, \n"
1488 "refcyc_per_line_delivery_l: %d, \n"
1489 "vratio_prefetch_c: %d, \n"
1490 "refcyc_per_pte_group_vblank_c: %d, \n"
1491 "refcyc_per_meta_chunk_vblank_c: %d, \n"
1492 "dst_y_per_pte_row_nom_c: %d, \n"
1493 "refcyc_per_pte_group_nom_c: %d, \n"
1494 "dst_y_per_meta_row_nom_c: %d, \n"
1495 "refcyc_per_meta_chunk_nom_c: %d, \n"
1496 "refcyc_per_line_delivery_pre_c: %d, \n"
1497 "refcyc_per_line_delivery_c: %d \n"
1498 "========================================================\n",
1499 pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l,
1500 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l,
1501 pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l,
1502 pipe_ctx->dlg_regs.refcyc_per_line_delivery_l,
1503 pipe_ctx->dlg_regs.vratio_prefetch_c,
1504 pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c,
1505 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c,
1506 pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c,
1507 pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c,
1508 pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c,
1509 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c,
1510 pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c,
1511 pipe_ctx->dlg_regs.refcyc_per_line_delivery_c
1512 );
1513
1514 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1515 "\n============== DML RQ Output parameters [%d] ==============\n"
1516 "chunk_size: %d \n"
1517 "min_chunk_size: %d \n"
1518 "meta_chunk_size: %d \n"
1519 "min_meta_chunk_size: %d \n"
1520 "dpte_group_size: %d \n"
1521 "mpte_group_size: %d \n"
1522 "swath_height: %d \n"
1523 "pte_row_height_linear: %d \n"
1524 "========================================================\n",
1525 pipe_ctx->pipe_idx,
1526 pipe_ctx->rq_regs.rq_regs_l.chunk_size,
1527 pipe_ctx->rq_regs.rq_regs_l.min_chunk_size,
1528 pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size,
1529 pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size,
1530 pipe_ctx->rq_regs.rq_regs_l.dpte_group_size,
1531 pipe_ctx->rq_regs.rq_regs_l.mpte_group_size,
1532 pipe_ctx->rq_regs.rq_regs_l.swath_height,
1533 pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear
1534 );
1535 }
1536
1537 static void dcn10_power_on_fe(
1538 struct core_dc *dc,
1539 struct pipe_ctx *pipe_ctx,
1540 struct validate_context *context)
1541 {
1542 struct dc_surface *dc_surface = &pipe_ctx->surface->public;
1543
1544 power_on_plane(dc->ctx,
1545 pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
1546
1547 /* enable DCFCLK current DCHUB */
1548 enable_dcfclk(dc->ctx,
1549 pipe_ctx->pipe_idx,
1550 pipe_ctx->pix_clk_params.requested_pix_clk,
1551 context->bw.dcn.calc_clk.dppclk_div);
1552 dc->current_context->bw.dcn.cur_clk.dppclk_div =
1553 context->bw.dcn.calc_clk.dppclk_div;
1554 context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div;
1555
1556 if (dc_surface) {
1557 dm_logger_write(dc->ctx->logger, LOG_DC,
1558 "Pipe:%d 0x%x: addr hi:0x%x, "
1559 "addr low:0x%x, "
1560 "src: %d, %d, %d,"
1561 " %d; dst: %d, %d, %d, %d;\n",
1562 pipe_ctx->pipe_idx,
1563 dc_surface,
1564 dc_surface->address.grph.addr.high_part,
1565 dc_surface->address.grph.addr.low_part,
1566 dc_surface->src_rect.x,
1567 dc_surface->src_rect.y,
1568 dc_surface->src_rect.width,
1569 dc_surface->src_rect.height,
1570 dc_surface->dst_rect.x,
1571 dc_surface->dst_rect.y,
1572 dc_surface->dst_rect.width,
1573 dc_surface->dst_rect.height);
1574
1575 dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE,
1576 "Pipe %d: width, height, x, y\n"
1577 "viewport:%d, %d, %d, %d\n"
1578 "recout: %d, %d, %d, %d\n",
1579 pipe_ctx->pipe_idx,
1580 pipe_ctx->scl_data.viewport.width,
1581 pipe_ctx->scl_data.viewport.height,
1582 pipe_ctx->scl_data.viewport.x,
1583 pipe_ctx->scl_data.viewport.y,
1584 pipe_ctx->scl_data.recout.width,
1585 pipe_ctx->scl_data.recout.height,
1586 pipe_ctx->scl_data.recout.x,
1587 pipe_ctx->scl_data.recout.y);
1588 print_rq_dlg_ttu(dc, pipe_ctx);
1589 }
1590 }
1591
1592 static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
1593 {
1594 struct xfm_grph_csc_adjustment adjust;
1595 memset(&adjust, 0, sizeof(adjust));
1596 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1597
1598
1599 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1600 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1601 adjust.temperature_matrix[0] =
1602 pipe_ctx->stream->
1603 public.gamut_remap_matrix.matrix[0];
1604 adjust.temperature_matrix[1] =
1605 pipe_ctx->stream->
1606 public.gamut_remap_matrix.matrix[1];
1607 adjust.temperature_matrix[2] =
1608 pipe_ctx->stream->
1609 public.gamut_remap_matrix.matrix[2];
1610 adjust.temperature_matrix[3] =
1611 pipe_ctx->stream->
1612 public.gamut_remap_matrix.matrix[4];
1613 adjust.temperature_matrix[4] =
1614 pipe_ctx->stream->
1615 public.gamut_remap_matrix.matrix[5];
1616 adjust.temperature_matrix[5] =
1617 pipe_ctx->stream->
1618 public.gamut_remap_matrix.matrix[6];
1619 adjust.temperature_matrix[6] =
1620 pipe_ctx->stream->
1621 public.gamut_remap_matrix.matrix[8];
1622 adjust.temperature_matrix[7] =
1623 pipe_ctx->stream->
1624 public.gamut_remap_matrix.matrix[9];
1625 adjust.temperature_matrix[8] =
1626 pipe_ctx->stream->
1627 public.gamut_remap_matrix.matrix[10];
1628 }
1629
1630 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
1631 }
1632
1633 static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1634 {
1635 if (pipe_ctx->surface->public.visible)
1636 return true;
1637 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1638 return true;
1639 return false;
1640 }
1641
1642 static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1643 {
1644 if (pipe_ctx->surface->public.visible)
1645 return true;
1646 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1647 return true;
1648 return false;
1649 }
1650
1651 static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1652 {
1653 if (pipe_ctx->surface->public.visible)
1654 return true;
1655 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1656 return true;
1657 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1658 return true;
1659 return false;
1660 }
1661
1662 static void update_dchubp_dpp(
1663 struct core_dc *dc,
1664 struct pipe_ctx *pipe_ctx,
1665 struct validate_context *context)
1666 {
1667 struct mem_input *mi = pipe_ctx->mi;
1668 struct input_pixel_processor *ipp = pipe_ctx->ipp;
1669 struct core_surface *surface = pipe_ctx->surface;
1670 union plane_size size = surface->public.plane_size;
1671 struct mpc_tree_cfg *tree_cfg = NULL;
1672 struct default_adjustment ocsc = {0};
1673 enum dc_color_space color_space;
1674 struct tg_color black_color = {0};
1675 struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc);
1676 struct pipe_ctx *temp_pipe;
1677 int i;
1678 int tree_pos = 0;
1679 bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe;
1680
1681 /* TODO: proper fix once fpga works */
1682 /* depends on DML calculation, DPP clock value may change dynamically */
1683 enable_dppclk(
1684 dc->ctx,
1685 pipe_ctx->pipe_idx,
1686 pipe_ctx->pix_clk_params.requested_pix_clk,
1687 context->bw.dcn.calc_clk.dppclk_div);
1688 dc->current_context->bw.dcn.cur_clk.dppclk_div =
1689 context->bw.dcn.calc_clk.dppclk_div;
1690 context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div;
1691
1692 select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
1693
1694 update_plane_addr(dc, pipe_ctx);
1695
1696 mi->funcs->mem_input_setup(
1697 mi,
1698 &pipe_ctx->dlg_regs,
1699 &pipe_ctx->ttu_regs,
1700 &pipe_ctx->rq_regs,
1701 &pipe_ctx->pipe_dlg_param);
1702
1703 size.grph.surface_size = pipe_ctx->scl_data.viewport;
1704
1705 if (dc->public.config.gpu_vm_support)
1706 mi->funcs->mem_input_program_pte_vm(
1707 pipe_ctx->mi,
1708 surface->public.format,
1709 &surface->public.tiling_info,
1710 surface->public.rotation);
1711
1712 ipp->funcs->ipp_setup(ipp,
1713 surface->public.format,
1714 1,
1715 IPP_OUTPUT_FORMAT_12_BIT_FIX);
1716
1717 /* mpc TODO un-hardcode object ids
1718 * for pseudo code pipe_move.c :
1719 * add_plane_mpcc(added_plane_inst, mpcc_inst, ...);
1720 * Do we want to cache the tree_cfg?
1721 */
1722
1723 /* TODO: build stream pipes group id. For now, use stream otg
1724 * id as pipe group id
1725 */
1726 pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha;
1727 pipe_ctx->mpc_idx = pipe_ctx->tg->inst;
1728 tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx];
1729 if (tree_cfg->num_pipes == 0) {
1730 tree_cfg->opp_id = pipe_ctx->tg->inst;
1731 for (i = 0; i < MAX_PIPES; i++) {
1732 tree_cfg->dpp[i] = 0xf;
1733 tree_cfg->mpcc[i] = 0xf;
1734 }
1735 }
1736
1737 for (temp_pipe = pipe_ctx->top_pipe;
1738 temp_pipe != NULL; temp_pipe = temp_pipe->top_pipe)
1739 tree_pos++;
1740
1741 tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx;
1742 tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx;
1743 tree_cfg->per_pixel_alpha[tree_pos] = per_pixel_alpha;
1744 tree_cfg->num_pipes = tree_pos + 1;
1745 dcn10_set_mpc_tree(mpc, tree_cfg);
1746
1747 color_space = pipe_ctx->stream->public.output_color_space;
1748 color_space_to_black_color(dc, color_space, &black_color);
1749 dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color);
1750
1751 pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1752 /* scaler configuration */
1753 pipe_ctx->xfm->funcs->transform_set_scaler(
1754 pipe_ctx->xfm, &pipe_ctx->scl_data);
1755
1756 /*gamut remap*/
1757 program_gamut_remap(pipe_ctx);
1758
1759 /*TODO add adjustments parameters*/
1760 ocsc.out_color_space = pipe_ctx->stream->public.output_color_space;
1761 pipe_ctx->opp->funcs->opp_set_csc_default(pipe_ctx->opp, &ocsc);
1762
1763 mi->funcs->mem_input_program_surface_config(
1764 mi,
1765 surface->public.format,
1766 &surface->public.tiling_info,
1767 &size,
1768 surface->public.rotation,
1769 &surface->public.dcc,
1770 surface->public.horizontal_mirror);
1771
1772 mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx));
1773 }
1774
1775 static void program_all_pipe_in_tree(
1776 struct core_dc *dc,
1777 struct pipe_ctx *pipe_ctx,
1778 struct validate_context *context)
1779 {
1780 unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000;
1781
1782 if (pipe_ctx->top_pipe == NULL) {
1783
1784 /* lock otg_master_update to process all pipes associated with
1785 * this OTG. this is done only one time.
1786 */
1787 /* watermark is for all pipes */
1788 pipe_ctx->mi->funcs->program_watermarks(
1789 pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz);
1790 lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst);
1791
1792 pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
1793 pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
1794 pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
1795 pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
1796 pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
1797
1798 pipe_ctx->tg->funcs->program_global_sync(
1799 pipe_ctx->tg);
1800 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx));
1801 }
1802
1803 if (pipe_ctx->surface->public.visible) {
1804 dcn10_power_on_fe(dc, pipe_ctx, context);
1805 update_dchubp_dpp(dc, pipe_ctx, context);
1806 }
1807
1808 if (pipe_ctx->bottom_pipe != NULL)
1809 program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
1810 }
1811
1812 static void dcn10_pplib_apply_display_requirements(
1813 struct core_dc *dc,
1814 struct validate_context *context)
1815 {
1816 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
1817
1818 pp_display_cfg->all_displays_in_sync = false;/*todo*/
1819 pp_display_cfg->nb_pstate_switch_disable = false;
1820 pp_display_cfg->min_engine_clock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
1821 pp_display_cfg->min_memory_clock_khz = context->bw.dcn.cur_clk.fclk_khz;
1822 pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
1823 pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
1824 pp_display_cfg->avail_mclk_switch_time_us =
1825 context->bw.dcn.cur_clk.dram_ccm_us > 0 ? context->bw.dcn.cur_clk.dram_ccm_us : 0;
1826 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us =
1827 context->bw.dcn.cur_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.cur_clk.min_active_dram_ccm_us : 0;
1828 pp_display_cfg->min_dcfclock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
1829 pp_display_cfg->disp_clk_khz = context->bw.dcn.cur_clk.dispclk_khz;
1830 dce110_fill_display_configs(context, pp_display_cfg);
1831
1832 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
1833 struct dm_pp_display_configuration)) != 0)
1834 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
1835
1836 dc->prev_display_config = *pp_display_cfg;
1837 }
1838
1839 static void dcn10_apply_ctx_for_surface(
1840 struct core_dc *dc,
1841 struct core_surface *surface,
1842 struct validate_context *context)
1843 {
1844 int i;
1845
1846 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1847 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1848
1849 if (!pipe_ctx->surface || pipe_ctx->surface != surface)
1850 continue;
1851
1852
1853 /* looking for top pipe to program */
1854 if (!pipe_ctx->top_pipe) {
1855 memcpy(context->res_ctx.mpc_tree,
1856 dc->current_context->res_ctx.mpc_tree,
1857 sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count);
1858
1859 program_all_pipe_in_tree(dc, pipe_ctx, context);
1860 }
1861 }
1862
1863 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1864 "\n============== Watermark parameters ==============\n"
1865 "a.urgent_ns: %d \n"
1866 "a.cstate_enter_plus_exit: %d \n"
1867 "a.cstate_exit: %d \n"
1868 "a.pstate_change: %d \n"
1869 "a.pte_meta_urgent: %d \n"
1870 "b.urgent_ns: %d \n"
1871 "b.cstate_enter_plus_exit: %d \n"
1872 "b.cstate_exit: %d \n"
1873 "b.pstate_change: %d \n"
1874 "b.pte_meta_urgent: %d \n",
1875 context->bw.dcn.watermarks.a.urgent_ns,
1876 context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns,
1877 context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns,
1878 context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns,
1879 context->bw.dcn.watermarks.a.pte_meta_urgent_ns,
1880 context->bw.dcn.watermarks.b.urgent_ns,
1881 context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns,
1882 context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns,
1883 context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns,
1884 context->bw.dcn.watermarks.b.pte_meta_urgent_ns
1885 );
1886 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1887 "\nc.urgent_ns: %d \n"
1888 "c.cstate_enter_plus_exit: %d \n"
1889 "c.cstate_exit: %d \n"
1890 "c.pstate_change: %d \n"
1891 "c.pte_meta_urgent: %d \n"
1892 "d.urgent_ns: %d \n"
1893 "d.cstate_enter_plus_exit: %d \n"
1894 "d.cstate_exit: %d \n"
1895 "d.pstate_change: %d \n"
1896 "d.pte_meta_urgent: %d \n"
1897 "========================================================\n",
1898 context->bw.dcn.watermarks.c.urgent_ns,
1899 context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns,
1900 context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns,
1901 context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns,
1902 context->bw.dcn.watermarks.c.pte_meta_urgent_ns,
1903 context->bw.dcn.watermarks.d.urgent_ns,
1904 context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns,
1905 context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns,
1906 context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns,
1907 context->bw.dcn.watermarks.d.pte_meta_urgent_ns
1908 );
1909
1910 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1911 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1912
1913 if (!pipe_ctx->surface || pipe_ctx->top_pipe)
1914 continue;
1915
1916 /* unlock master update lock */
1917 unlock_otg_master(dc->ctx, pipe_ctx->tg->inst);
1918 }
1919
1920 /* reset unused pipe */
1921 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1922 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1923 struct pipe_ctx *old_pipe_ctx =
1924 &dc->current_context->res_ctx.pipe_ctx[i];
1925
1926 if ((!pipe_ctx->surface && old_pipe_ctx->surface)
1927 || (!pipe_ctx->stream && old_pipe_ctx->stream))
1928 reset_front_end_for_pipe(dc,
1929 old_pipe_ctx, dc->current_context);
1930 }
1931 }
1932
1933 static void dcn10_set_bandwidth(
1934 struct core_dc *dc,
1935 struct validate_context *context,
1936 bool decrease_allowed)
1937 {
1938 struct dm_pp_clock_for_voltage_req clock;
1939
1940 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
1941 return;
1942
1943 if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz
1944 > dc->current_context->bw.dcn.cur_clk.dispclk_khz) {
1945 dc->res_pool->display_clock->funcs->set_clock(
1946 dc->res_pool->display_clock,
1947 context->bw.dcn.calc_clk.dispclk_khz);
1948 dc->current_context->bw.dcn.cur_clk.dispclk_khz =
1949 context->bw.dcn.calc_clk.dispclk_khz;
1950 }
1951 if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz
1952 > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) {
1953 clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
1954 clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz;
1955 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1956 dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1957 context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1958 }
1959 if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz
1960 > dc->current_context->bw.dcn.cur_clk.fclk_khz) {
1961 clock.clk_type = DM_PP_CLOCK_TYPE_FCLK;
1962 clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz;
1963 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1964 dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz;
1965 context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1966 }
1967 if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz
1968 > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) {
1969 dc->current_context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz =
1970 context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
1971 context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz =
1972 context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
1973 }
1974 /* Decrease in freq is increase in period so opposite comparison for dram_ccm */
1975 if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us
1976 < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) {
1977 dc->current_context->bw.dcn.calc_clk.dram_ccm_us =
1978 context->bw.dcn.calc_clk.dram_ccm_us;
1979 context->bw.dcn.cur_clk.dram_ccm_us =
1980 context->bw.dcn.calc_clk.dram_ccm_us;
1981 }
1982 if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us
1983 < dc->current_context->bw.dcn.cur_clk.min_active_dram_ccm_us) {
1984 dc->current_context->bw.dcn.calc_clk.min_active_dram_ccm_us =
1985 context->bw.dcn.calc_clk.min_active_dram_ccm_us;
1986 context->bw.dcn.cur_clk.min_active_dram_ccm_us =
1987 context->bw.dcn.calc_clk.min_active_dram_ccm_us;
1988 }
1989 dcn10_pplib_apply_display_requirements(dc, context);
1990 }
1991
1992 static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
1993 {
1994 struct dc_context *ctx = dc->ctx;
1995 uint32_t inst_offset = 0;
1996
1997 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
1998 IP_REQUEST_EN, 1);
1999 dpp_pg_control(ctx, pipe->pipe_idx, false);
2000 hubp_pg_control(ctx, pipe->pipe_idx, false);
2001 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
2002 IP_REQUEST_EN, 0);
2003
2004 if (pipe->xfm)
2005 pipe->xfm->funcs->transform_reset(pipe->xfm);
2006 memset(&pipe->scl_data, 0, sizeof(pipe->scl_data));
2007 }
2008
2009 static void set_drr(struct pipe_ctx **pipe_ctx,
2010 int num_pipes, int vmin, int vmax)
2011 {
2012 int i = 0;
2013 struct drr_params params = {0};
2014
2015 params.vertical_total_max = vmax;
2016 params.vertical_total_min = vmin;
2017
2018 /* TODO: If multiple pipes are to be supported, you need
2019 * some GSL stuff
2020 */
2021 for (i = 0; i < num_pipes; i++) {
2022 pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, &params);
2023 }
2024 }
2025
2026 static void get_position(struct pipe_ctx **pipe_ctx,
2027 int num_pipes,
2028 struct crtc_position *position)
2029 {
2030 int i = 0;
2031
2032 /* TODO: handle pipes > 1
2033 */
2034 for (i = 0; i < num_pipes; i++)
2035 pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position);
2036 }
2037
2038 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
2039 int num_pipes, const struct dc_static_screen_events *events)
2040 {
2041 unsigned int i;
2042 unsigned int value = 0;
2043
2044 if (events->surface_update)
2045 value |= 0x80;
2046 if (events->cursor_update)
2047 value |= 0x2;
2048
2049 for (i = 0; i < num_pipes; i++)
2050 pipe_ctx[i]->tg->funcs->
2051 set_static_screen_control(pipe_ctx[i]->tg, value);
2052 }
2053
2054 static void set_plane_config(
2055 const struct core_dc *dc,
2056 struct pipe_ctx *pipe_ctx,
2057 struct resource_context *res_ctx)
2058 {
2059 /* TODO */
2060 program_gamut_remap(pipe_ctx);
2061 }
2062
2063 static const struct hw_sequencer_funcs dcn10_funcs = {
2064 .program_gamut_remap = program_gamut_remap,
2065 .init_hw = init_hw,
2066 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2067 .apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
2068 .set_plane_config = set_plane_config,
2069 .update_plane_addr = update_plane_addr,
2070 .update_pending_status = dce110_update_pending_status,
2071 .set_input_transfer_func = dcn10_set_input_transfer_func,
2072 .set_output_transfer_func = dcn10_set_output_transfer_func,
2073 .power_down = dce110_power_down,
2074 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2075 .enable_timing_synchronization = dcn10_enable_timing_synchronization,
2076 .update_info_frame = dce110_update_info_frame,
2077 .enable_stream = dce110_enable_stream,
2078 .disable_stream = dce110_disable_stream,
2079 .unblank_stream = dce110_unblank_stream,
2080 .enable_display_pipe_clock_gating = NULL, /* TODOFPGA */
2081 .enable_display_power_gating = dcn10_enable_display_power_gating,
2082 .power_down_front_end = dcn10_power_down_fe,
2083 .power_on_front_end = dcn10_power_on_fe,
2084 .pipe_control_lock = dcn10_pipe_control_lock,
2085 .set_bandwidth = dcn10_set_bandwidth,
2086 .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
2087 .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg,
2088 .set_drr = set_drr,
2089 .get_position = get_position,
2090 .set_static_screen_control = set_static_screen_control
2091 };
2092
2093
2094 bool dcn10_hw_sequencer_construct(struct core_dc *dc)
2095 {
2096 dc->hwss = dcn10_funcs;
2097 return true;
2098 }
2099