2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "dm_services.h"
29 #include "core_types.h"
30 #include "core_status.h"
32 #include "hw_sequencer.h"
33 #include "dcn10_hw_sequencer.h"
34 #include "dce110/dce110_hw_sequencer.h"
37 #include "dcn10/dcn10_transform.h"
38 #include "dcn10/dcn10_mpc.h"
39 #include "dcn10/dcn10_timing_generator.h"
41 #include "mem_input.h"
42 #include "timing_generator.h"
46 #include "dc_bios_types.h"
48 #include "raven1/DCN/dcn_1_0_offset.h"
49 #include "raven1/DCN/dcn_1_0_sh_mask.h"
50 #include "vega10/soc15ip.h"
52 #include "custom_float.h"
55 struct dcn10_hwseq_reg_offsets
{
63 /* TODO: move to resource */
64 static const struct dcn10_hwseq_reg_offsets reg_offsets
[] = {
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
),
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
),
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
),
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
),
99 #define HWSEQ_REG_UPDATE_N(reg_name, n, ...) \
100 generic_reg_update_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__)
102 #define HWSEQ_REG_SET_N(reg_name, n, ...) \
103 generic_reg_set_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__)
105 #define HWSEQ_REG_UPDATE(reg, field, val) \
106 HWSEQ_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
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)
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)
115 #define HWSEQ_REG_SET(reg, field, val) \
116 HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val)
118 /* TODO should be moved to OTG */
119 static void lock_otg_master_update(
120 struct dc_context
*ctx
,
123 uint32_t inst_offset
= reg_offsets
[inst
].otg
;
125 HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0
,
126 OTG_MASTER_UPDATE_LOCK_SEL
, inst
);
128 /* unlock master locker */
129 HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK
,
130 OTG_MASTER_UPDATE_LOCK
, 1);
132 /* wait for unlock happens */
133 if (!wait_reg(ctx
, inst_offset
, OTG0_OTG_MASTER_UPDATE_LOCK
, UPDATE_LOCK_STATUS
, 1))
138 static bool unlock_master_tg_and_wait(
139 struct dc_context
*ctx
,
142 uint32_t inst_offset
= reg_offsets
[inst
].otg
;
144 HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_SYNC_STATUS
,
145 VUPDATE_NO_LOCK_EVENT_CLEAR
, 1);
146 HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK
, OTG_MASTER_UPDATE_LOCK
, 0);
148 if (!wait_reg(ctx
, inst_offset
, OTG0_OTG_GLOBAL_SYNC_STATUS
, VUPDATE_NO_LOCK_EVENT_OCCURRED
, 1)) {
149 dm_logger_write(ctx
->logger
, LOG_ERROR
,
150 "wait for VUPDATE_NO_LOCK_EVENT_OCCURRED failed\n");
157 /* TODO: should be moved to OTG ? */
158 static void unlock_otg_master(
159 struct dc_context
*ctx
,
162 uint32_t inst_offset
= reg_offsets
[inst
].otg
;
164 /* unlock master locker */
165 HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK
,
166 OTG_MASTER_UPDATE_LOCK
, 0);
170 static void wait_no_outstanding_request(
171 struct dc_context
*ctx
,
174 uint32_t inst_offset
= reg_offsets
[plane_id
].dchubp
;
176 if (!wait_reg(ctx
, inst_offset
, HUBP0_DCHUBP_CNTL
, HUBP_NO_OUTSTANDING_REQ
, 1))
180 static void disable_clocks(
181 struct dc_context
*ctx
,
184 uint32_t inst_offset
= reg_offsets
[plane_id
].dchubp
;
186 generic_reg_update_soc15(ctx
, inst_offset
, HUBP0_HUBP_CLK_CNTL
, 1,
187 FD(HUBP0_HUBP_CLK_CNTL__HUBP_CLOCK_ENABLE
), 0);
189 inst_offset
= reg_offsets
[plane_id
].dpp
;
190 generic_reg_update_soc15(ctx
, inst_offset
, DPP_TOP0_DPP_CONTROL
, 1,
191 FD(DPP_TOP0_DPP_CONTROL__DPP_CLOCK_ENABLE
), 0);
194 /* TODO: This is one time program during system boot up,
195 * this should be done within BIOS or CAIL
197 static void dchubp_map_fb_to_mc(struct dc_context
*ctx
)
199 /* TODO: do not know where to program
200 * DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
203 * TODO: For real ASIC, FB_OFFSET may be need change to the same value
204 * as FB_BASE. Need re-visit this for real ASIC.
206 dm_write_reg_soc15(ctx
, mmDCHUBBUB_SDPIF_FB_BASE
, 0, 0x80);
207 dm_write_reg_soc15(ctx
, mmDCHUBBUB_SDPIF_FB_OFFSET
, 0, 0);
208 dm_write_reg_soc15(ctx
, mmDCHUBBUB_SDPIF_FB_TOP
, 0, 0xFF);
210 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_CFG0
, 7,
211 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_DATA_RESPONSE_STATUS_CLEAR
), 0,
212 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_ERROR_CLEAR
), 0,
213 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_FLUSH_REQ_CREDIT_EN
), 0,
214 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_EN
), 0,
215 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_PORT_CONTROL
), 1,
216 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_UNIT_ID_BITMASK
), 0xd3,
217 FD(DCHUBBUB_SDPIF_CFG0__SDPIF_CREDIT_DISCONNECT_DELAY
), 0xc);
220 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_CFG1
, 4,
221 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_IO
), 0,
222 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_VC
), 6,
223 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_IO
), 1,
224 FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_VC
), 6);
226 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_FB_BASE
, 1,
227 FD(DCHUBBUB_SDPIF_FB_BASE__SDPIF_FB_BASE
), 0x000080);
229 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_FB_TOP
, 1,
230 FD(DCHUBBUB_SDPIF_FB_TOP__SDPIF_FB_TOP
), 0x0000ff);
232 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_AGP_BOT
, 1,
233 FD(DCHUBBUB_SDPIF_AGP_BOT__SDPIF_AGP_BOT
), 0x0000040);
235 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_AGP_TOP
, 1,
236 FD(DCHUBBUB_SDPIF_AGP_TOP__SDPIF_AGP_TOP
), 0x00001ff);
238 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_AGP_BASE
, 1,
239 FD(DCHUBBUB_SDPIF_AGP_BASE__SDPIF_AGP_BASE
), 0x0000080);
241 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_APER_TOP
, 1,
242 FD(DCHUBBUB_SDPIF_APER_TOP__SDPIF_APER_TOP
), 0x00007ff);
244 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_APER_DEF_0
, 1,
245 FD(DCHUBBUB_SDPIF_APER_DEF_0__SDPIF_APER_DEF_0
), 0xdeadbeef);
247 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_0
, 2,
248 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_EN_0
), 0,
249 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_RELOC_LO_0
), 0x90000);
251 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_0
, 1,
252 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_0__SDPIF_MARC_LENGTH_LO_0
), 0x10000);
254 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_1
, 1,
255 FD(DCHUBBUB_SDPIF_MARC_BASE_LO_1__SDPIF_MARC_BASE_LO_1
), 0x10000);
257 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_1
, 2,
258 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_EN_1
), 0,
259 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_RELOC_LO_1
), 0xa0000);
261 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_1
, 1,
262 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_1__SDPIF_MARC_LENGTH_LO_1
), 0x10000);
264 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_2
, 1,
265 FD(DCHUBBUB_SDPIF_MARC_BASE_LO_2__SDPIF_MARC_BASE_LO_2
), 0x20000);
267 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_2
, 2,
268 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_EN_2
), 0,
269 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_RELOC_LO_2
), 0xb0000);
271 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_2
, 1,
272 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_2__SDPIF_MARC_LENGTH_LO_2
), 0x10000);
274 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_3
, 1,
275 FD(DCHUBBUB_SDPIF_MARC_BASE_LO_3__SDPIF_MARC_BASE_LO_3
), 0x30000);
277 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_3
, 2,
278 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_EN_3
), 0,
279 FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_RELOC_LO_3
), 0xc0000);
281 generic_reg_set_soc15(ctx
, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_3
, 1,
282 FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_3__SDPIF_MARC_LENGTH_LO_3
), 0x10000);
284 /* TODO: Is DCN_VM_SYSTEM_APERTURE address one time programming?
285 * Are all 4 hubp programmed with the same address?
287 dm_write_reg_soc15(ctx
, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
, 0, 0x80000);
288 dm_write_reg_soc15(ctx
, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB
, 0, 0);
289 dm_write_reg_soc15(ctx
, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB
, 0, 0x100000);
290 dm_write_reg_soc15(ctx
, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB
, 0, 0);
291 dm_write_reg_soc15(ctx
, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB
, 0, 0x80000);
292 dm_write_reg_soc15(ctx
, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB
, 0, 0);
294 dm_write_reg_soc15(ctx
, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
, 0, 0x80000);
295 dm_write_reg_soc15(ctx
, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB
, 0, 0);
296 dm_write_reg_soc15(ctx
, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB
, 0, 0x100000);
297 dm_write_reg_soc15(ctx
, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB
, 0, 0);
298 dm_write_reg_soc15(ctx
, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB
, 0, 0x80000);
299 dm_write_reg_soc15(ctx
, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB
, 0, 0);
301 dm_write_reg_soc15(ctx
, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
, 0, 0x80000);
302 dm_write_reg_soc15(ctx
, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB
, 0, 0);
303 dm_write_reg_soc15(ctx
, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB
, 0, 0x100000);
304 dm_write_reg_soc15(ctx
, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB
, 0, 0);
305 dm_write_reg_soc15(ctx
, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB
, 0, 0x80000);
306 dm_write_reg_soc15(ctx
, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB
, 0, 0);
308 dm_write_reg_soc15(ctx
, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB
, 0, 0x80000);
309 dm_write_reg_soc15(ctx
, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB
, 0, 0);
310 dm_write_reg_soc15(ctx
, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB
, 0, 0x100000);
311 dm_write_reg_soc15(ctx
, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB
, 0, 0);
312 dm_write_reg_soc15(ctx
, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB
, 0, 0x80000);
313 dm_write_reg_soc15(ctx
, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB
, 0, 0);
316 /* TODO: This is one time program during system boot up,
317 * this should be done within BIOS
319 static void dchubup_setup_timer(struct dc_context
*ctx
)
321 dm_write_reg_soc15(ctx
, mmREFCLK_CNTL
, 0, 0);
323 generic_reg_update_soc15(ctx
, 0, DCHUBBUB_GLOBAL_TIMER_CNTL
, 1,
324 FD(DCHUBBUB_GLOBAL_TIMER_CNTL__DCHUBBUB_GLOBAL_TIMER_ENABLE
), 1);
327 /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
328 * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
329 * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
331 static void select_vtg(
332 struct dc_context
*ctx
,
336 uint32_t inst_offset
= reg_offsets
[plane_id
].dchubp
;
338 HWSEQ_REG_UPDATE(HUBP0_DCHUBP_CNTL
, HUBP_VTG_SEL
, inst
);
341 static void enable_dcfclk(
342 struct dc_context
*ctx
,
344 uint32_t requested_pix_clk
,
347 uint32_t inst_offset
= reg_offsets
[plane_id
].dchubp
;
349 HWSEQ_REG_UPDATE(HUBP0_HUBP_CLK_CNTL
, HUBP_CLOCK_ENABLE
, 1);
352 static void enable_dppclk(
353 struct dc_context
*ctx
,
355 uint32_t requested_pix_clk
,
358 uint32_t inst_offset
= reg_offsets
[plane_id
].dpp
;
360 dm_logger_write(ctx
->logger
, LOG_SURFACE
,
361 "dppclk_rate_control for pipe %d programed to %d\n",
365 /* TODO: find condition for DPP clock to DISPCLK or 1/2 DISPCLK */
368 HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL
,
369 DPPCLK_RATE_CONTROL
, 1,
370 DPP_CLOCK_ENABLE
, 1);
373 HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL
,
374 DPPCLK_RATE_CONTROL
, 0,
375 DPP_CLOCK_ENABLE
, 1);
379 static void enable_power_gating_plane(
380 struct dc_context
*ctx
,
383 uint32_t inst_offset
= 0; /* each register only has one instance */
384 bool force_on
= 1; /* disable power gating */
390 HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG
, DOMAIN0_POWER_FORCEON
, force_on
);
391 HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG
, DOMAIN2_POWER_FORCEON
, force_on
);
392 HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG
, DOMAIN4_POWER_FORCEON
, force_on
);
393 HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG
, DOMAIN6_POWER_FORCEON
, force_on
);
396 HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG
, DOMAIN1_POWER_FORCEON
, force_on
);
397 HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG
, DOMAIN3_POWER_FORCEON
, force_on
);
398 HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG
, DOMAIN5_POWER_FORCEON
, force_on
);
399 HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG
, DOMAIN7_POWER_FORCEON
, force_on
);
401 if (ctx
->dc
->debug
.disable_clock_gate
) {
402 /* probably better to just write entire register to 0xffff to
403 * ensure all clock gating is disabled
405 HWSEQ_REG_UPDATE_3(DCCG_GATE_DISABLE_CNTL
,
406 DISPCLK_R_DCCG_GATE_DISABLE
, 1,
407 DPREFCLK_R_DCCG_GATE_DISABLE
, 1,
408 REFCLK_R_DIG_GATE_DISABLE
, 1);
409 HWSEQ_REG_UPDATE(DCFCLK_CNTL
,
415 static void dpp_pg_control(
416 struct dc_context
*ctx
,
417 unsigned int dpp_inst
,
420 uint32_t inst_offset
= 0;
421 uint32_t power_gate
= power_on
? 0 : 1;
422 uint32_t pwr_status
= power_on
? 0 : 2;
424 if (ctx
->dc
->debug
.disable_dpp_power_gate
)
429 HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG
,
430 DOMAIN1_POWER_GATE
, power_gate
);
432 wait_reg(ctx
, 0, DOMAIN1_PG_STATUS
,
433 DOMAIN1_PGFSM_PWR_STATUS
, pwr_status
);
436 HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG
,
437 DOMAIN3_POWER_GATE
, power_gate
);
439 wait_reg(ctx
, 0, DOMAIN3_PG_STATUS
,
440 DOMAIN3_PGFSM_PWR_STATUS
, pwr_status
);
443 HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG
,
444 DOMAIN5_POWER_GATE
, power_gate
);
446 wait_reg(ctx
, 0, DOMAIN5_PG_STATUS
,
447 DOMAIN5_PGFSM_PWR_STATUS
, pwr_status
);
450 HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG
,
451 DOMAIN7_POWER_GATE
, power_gate
);
453 wait_reg(ctx
, 0, DOMAIN7_PG_STATUS
,
454 DOMAIN7_PGFSM_PWR_STATUS
, pwr_status
);
462 static void hubp_pg_control(
463 struct dc_context
*ctx
,
464 unsigned int hubp_inst
,
467 uint32_t inst_offset
= 0;
468 uint32_t power_gate
= power_on
? 0 : 1;
469 uint32_t pwr_status
= power_on
? 0 : 2;
471 if (ctx
->dc
->debug
.disable_hubp_power_gate
)
475 case 0: /* DCHUBP0 */
476 HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG
,
477 DOMAIN0_POWER_GATE
, power_gate
);
479 wait_reg(ctx
, 0, DOMAIN0_PG_STATUS
,
480 DOMAIN0_PGFSM_PWR_STATUS
, pwr_status
);
482 case 1: /* DCHUBP1 */
483 HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG
,
484 DOMAIN2_POWER_GATE
, power_gate
);
486 wait_reg(ctx
, 0, DOMAIN2_PG_STATUS
,
487 DOMAIN2_PGFSM_PWR_STATUS
, pwr_status
);
489 case 2: /* DCHUBP2 */
490 HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG
,
491 DOMAIN4_POWER_GATE
, power_gate
);
493 wait_reg(ctx
, 0, DOMAIN4_PG_STATUS
,
494 DOMAIN4_PGFSM_PWR_STATUS
, pwr_status
);
496 case 3: /* DCHUBP3 */
497 HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG
,
498 DOMAIN6_POWER_GATE
, power_gate
);
500 wait_reg(ctx
, 0, DOMAIN6_PG_STATUS
,
501 DOMAIN6_PGFSM_PWR_STATUS
, pwr_status
);
509 static void power_on_plane(
510 struct dc_context
*ctx
,
514 uint32_t inst_offset
= 0;
516 /* disable clock power gating */
518 /* DCCG_GATE_DISABLE_CNTL only has one instance */
519 HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL
,
520 DISPCLK_DCCG_GATE_DISABLE
, 1,
521 DPPCLK_GATE_DISABLE
, 1);
522 /* DCFCLK_CNTL only has one instance */
523 HWSEQ_REG_UPDATE(DCFCLK_CNTL
,
526 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL
,
528 dpp_pg_control(ctx
, plane_id
, true);
529 hubp_pg_control(ctx
, plane_id
, true);
530 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL
,
533 if (ctx
->dc
->debug
.disable_clock_gate
) {
534 HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL
,
535 DISPCLK_DCCG_GATE_DISABLE
, 0);
537 /* DCCG_GATE_DISABLE_CNTL only has one instance. inst_offset = 0 */
538 HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL
,
539 DISPCLK_DCCG_GATE_DISABLE
, 0,
540 DPPCLK_GATE_DISABLE
, 0);
541 /* DCFCLK_CNTL only has one instance. inst_offset = 0 */
542 HWSEQ_REG_UPDATE(DCFCLK_CNTL
,
547 /* fully check bios enabledisplaypowergating table. dal only need dce init
548 * other power, clock gate register will be handle by dal itself.
549 * further may be put within init_hw
551 static bool dcn10_enable_display_power_gating(
553 uint8_t controller_id
,
555 enum pipe_gating_control power_gating
)
559 if (power_gating
!= PIPE_GATING_CONTROL_ENABLE
)
560 dce110_init_pte(ctx
);
566 static void bios_golden_init(struct core_dc
*dc
)
568 struct dc_bios
*bp
= dc
->ctx
->dc_bios
;
571 /* initialize dcn global */
572 bp
->funcs
->enable_disp_power_gating(bp
,
573 CONTROLLER_ID_D0
, ASIC_PIPE_INIT
);
575 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
576 /* initialize dcn per pipe */
577 bp
->funcs
->enable_disp_power_gating(bp
,
578 CONTROLLER_ID_D0
+ i
, ASIC_PIPE_DISABLE
);
582 static void init_hw(struct core_dc
*dc
)
586 struct transform
*xfm
;
589 bp
= dc
->ctx
->dc_bios
;
591 if (IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
)) {
592 /* TODO: this will be moved to Diag or BIOS */
593 dchubup_setup_timer(dc
->ctx
);
595 /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface
598 dchubp_map_fb_to_mc(dc
->ctx
);
600 enable_power_gating_plane(dc
->ctx
, true);
603 /* end of FPGA. Below if real ASIC */
605 bios_golden_init(dc
);
607 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
608 xfm
= dc
->res_pool
->transforms
[i
];
609 xfm
->funcs
->transform_reset(xfm
);
611 /* TODOFPGA: may need later */
613 xfm
->funcs
->transform_power_up(xfm
);
614 dc
->hwss
.enable_display_pipe_clock_gating(
619 /* TODOFPGA: light sleep */
621 dc
->hwss
.clock_gating_power_up(dc
->ctx
, false);
624 for (i
= 0; i
< dc
->link_count
; i
++) {
625 /* Power up AND update implementation according to the
626 * required signal (which may be different from the
627 * default signal on connector).
629 struct core_link
*link
= dc
->links
[i
];
631 link
->link_enc
->funcs
->hw_init(link
->link_enc
);
634 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
635 struct timing_generator
*tg
=
636 dc
->res_pool
->timing_generators
[i
];
638 tg
->funcs
->disable_vga(tg
);
640 /* Blank controller using driver code instead of
643 tg
->funcs
->set_blank(tg
, true);
644 hwss_wait_for_blank_complete(tg
);
647 for (i
= 0; i
< dc
->res_pool
->audio_count
; i
++) {
648 struct audio
*audio
= dc
->res_pool
->audios
[i
];
650 audio
->funcs
->hw_init(audio
);
653 abm
= dc
->res_pool
->abm
;
655 abm
->funcs
->init_backlight(abm
);
656 abm
->funcs
->abm_init(abm
);
659 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
660 generic_reg_set_soc15(dc
->ctx
, 0, DIO_MEM_PWR_CTRL
, 7,
661 FD(DIO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE
), 0,
662 FD(DIO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE
), 0,
663 FD(DIO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE
), 0,
664 FD(DIO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE
), 0,
665 FD(DIO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE
), 0,
666 FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE
), 0,
667 FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE
), 0);
669 /* This power gating should be one-time program for DAL.
670 * It can only change by registry key
671 * TODO: new task will for this.
672 * if power gating is disable, power_on_plane and power_off_plane
673 * should be skip. Otherwise, hand will be met in power_off_plane
676 enable_power_gating_plane(dc
->ctx
, true);
679 static enum dc_status
dcn10_prog_pixclk_crtc_otg(
680 struct pipe_ctx
*pipe_ctx
,
681 struct validate_context
*context
,
684 struct core_stream
*stream
= pipe_ctx
->stream
;
685 enum dc_color_space color_space
;
686 struct tg_color black_color
= {0};
687 bool enableStereo
= stream
->public.timing
.timing_3d_format
== TIMING_3D_FORMAT_NONE
?
689 bool rightEyePolarity
= stream
->public.timing
.flags
.RIGHT_EYE_3D_POLARITY
;
692 /* by upper caller loop, pipe0 is parent pipe and be called first.
693 * back end is set up by for pipe0. Other children pipe share back end
694 * with pipe 0. No program is needed.
696 if (pipe_ctx
->top_pipe
!= NULL
)
699 /* TODO check if timing_changed, disable stream if timing changed */
701 /* HW program guide assume display already disable
702 * by unplug sequence. OTG assume stop.
704 pipe_ctx
->tg
->funcs
->enable_optc_clock(pipe_ctx
->tg
, true);
706 if (false == pipe_ctx
->clock_source
->funcs
->program_pix_clk(
707 pipe_ctx
->clock_source
,
708 &pipe_ctx
->pix_clk_params
,
709 &pipe_ctx
->pll_settings
)) {
711 return DC_ERROR_UNEXPECTED
;
713 pipe_ctx
->tg
->dlg_otg_param
.vready_offset
= pipe_ctx
->pipe_dlg_param
.vready_offset
;
714 pipe_ctx
->tg
->dlg_otg_param
.vstartup_start
= pipe_ctx
->pipe_dlg_param
.vstartup_start
;
715 pipe_ctx
->tg
->dlg_otg_param
.vupdate_offset
= pipe_ctx
->pipe_dlg_param
.vupdate_offset
;
716 pipe_ctx
->tg
->dlg_otg_param
.vupdate_width
= pipe_ctx
->pipe_dlg_param
.vupdate_width
;
718 pipe_ctx
->tg
->dlg_otg_param
.signal
= pipe_ctx
->stream
->signal
;
720 pipe_ctx
->tg
->funcs
->program_timing(
722 &stream
->public.timing
,
725 pipe_ctx
->opp
->funcs
->opp_set_stereo_polarity(
730 #if 0 /* move to after enable_crtc */
731 /* TODO: OPP FMT, ABM. etc. should be done here. */
732 /* or FPGA now. instance 0 only. TODO: move to opp.c */
734 inst_offset
= reg_offsets
[pipe_ctx
->tg
->inst
].fmt
;
736 pipe_ctx
->opp
->funcs
->opp_program_fmt(
738 &stream
->bit_depth_params
,
741 /* program otg blank color */
742 color_space
= stream
->public.output_color_space
;
743 color_space_to_black_color(dc
, color_space
, &black_color
);
744 pipe_ctx
->tg
->funcs
->set_blank_color(
748 pipe_ctx
->tg
->funcs
->set_blank(pipe_ctx
->tg
, true);
749 hwss_wait_for_blank_complete(pipe_ctx
->tg
);
751 /* VTG is within DCHUB command block. DCFCLK is always on */
752 if (false == pipe_ctx
->tg
->funcs
->enable_crtc(pipe_ctx
->tg
)) {
754 return DC_ERROR_UNEXPECTED
;
757 /* TODO program crtc source select for non-virtual signal*/
758 /* TODO program FMT */
759 /* TODO setup link_enc */
760 /* TODO set stream attributes */
761 /* TODO program audio */
762 /* TODO enable stream if timing changed */
763 /* TODO unblank stream if DP */
768 static void reset_back_end_for_pipe(
770 struct pipe_ctx
*pipe_ctx
,
771 struct validate_context
*context
)
776 bp
= dc
->ctx
->dc_bios
;
778 if (pipe_ctx
->stream_enc
== NULL
) {
779 pipe_ctx
->stream
= NULL
;
783 /* TODOFPGA break core_link_disable_stream into 2 functions:
784 * disable_stream and disable_link. disable_link will disable PHYPLL
785 * which is used by otg. Move disable_link after disable_crtc
787 if (!IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
))
788 core_link_disable_stream(pipe_ctx
);
790 /* by upper caller loop, parent pipe: pipe0, will be reset last.
791 * back end share by all pipes and will be disable only when disable
794 if (pipe_ctx
->top_pipe
== NULL
) {
795 pipe_ctx
->tg
->funcs
->disable_crtc(pipe_ctx
->tg
);
797 pipe_ctx
->tg
->funcs
->enable_optc_clock(pipe_ctx
->tg
, false);
800 if (!IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
))
801 resource_unreference_clock_source(
802 &context
->res_ctx
, dc
->res_pool
,
803 &pipe_ctx
->clock_source
);
805 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++)
806 if (&dc
->current_context
->res_ctx
.pipe_ctx
[i
] == pipe_ctx
)
809 if (i
== dc
->res_pool
->pipe_count
)
812 pipe_ctx
->stream
= NULL
;
815 static void reset_front_end_for_pipe(
817 struct pipe_ctx
*pipe_ctx
,
818 struct validate_context
*context
)
820 struct dcn10_mpc
*mpc
= TO_DCN10_MPC(dc
->res_pool
->mpc
);
821 struct mpc_tree_cfg
*tree_cfg
= NULL
;
823 if (!pipe_ctx
->surface
)
826 lock_otg_master_update(dc
->ctx
, pipe_ctx
->tg
->inst
);
828 /* TODO: build stream pipes group id. For now, use stream otg
829 * id as pipe group id
831 tree_cfg
= &context
->res_ctx
.mpc_tree
[pipe_ctx
->mpc_idx
];
833 if (pipe_ctx
->top_pipe
== NULL
)
834 dcn10_delete_mpc_tree(mpc
, tree_cfg
);
836 if (dcn10_remove_dpp(mpc
, tree_cfg
, pipe_ctx
->pipe_idx
))
837 pipe_ctx
->top_pipe
->bottom_pipe
= NULL
;
839 dm_logger_write(dc
->ctx
->logger
, LOG_RESOURCE
,
840 "%s: failed to find dpp to be removed!\n",
845 pipe_ctx
->top_pipe
= NULL
;
846 pipe_ctx
->bottom_pipe
= NULL
;
847 pipe_ctx
->mpc_idx
= -1;
849 unlock_master_tg_and_wait(dc
->ctx
, pipe_ctx
->tg
->inst
);
851 pipe_ctx
->mi
->funcs
->disable_request(pipe_ctx
->mi
);
853 wait_no_outstanding_request(dc
->ctx
, pipe_ctx
->pipe_idx
);
855 wait_mpcc_idle(mpc
, pipe_ctx
->pipe_idx
);
857 disable_clocks(dc
->ctx
, pipe_ctx
->pipe_idx
);
859 pipe_ctx
->xfm
->funcs
->transform_reset(pipe_ctx
->xfm
);
861 dm_logger_write(dc
->ctx
->logger
, LOG_DC
,
862 "Reset front end for pipe %d\n",
865 pipe_ctx
->surface
= NULL
;
868 static void reset_hw_ctx(struct core_dc
*dc
,
869 struct validate_context
*context
,
870 void (*reset
)(struct core_dc
*dc
,
871 struct pipe_ctx
*pipe_ctx
,
872 struct validate_context
*context
))
876 for (i
= dc
->res_pool
->pipe_count
- 1; i
>= 0 ; i
--) {
877 struct pipe_ctx
*pipe_ctx_old
=
878 &dc
->current_context
->res_ctx
.pipe_ctx
[i
];
879 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
881 if (!pipe_ctx_old
->stream
)
884 if (!pipe_ctx
->stream
||
885 pipe_need_reprogram(pipe_ctx_old
, pipe_ctx
))
886 reset(dc
, pipe_ctx_old
, dc
->current_context
);
890 static void reset_hw_ctx_wrap(
892 struct validate_context
*context
)
895 reset_hw_ctx(dc
, context
, reset_front_end_for_pipe
);
897 reset_hw_ctx(dc
, context
, reset_back_end_for_pipe
);
899 memcpy(context
->res_ctx
.mpc_tree
,
900 dc
->current_context
->res_ctx
.mpc_tree
,
901 sizeof(struct mpc_tree_cfg
) * dc
->res_pool
->pipe_count
);
904 static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx
*pipe_ctx
,
905 PHYSICAL_ADDRESS_LOC
*addr
)
907 struct core_surface
*surface
= pipe_ctx
->surface
;
908 bool sec_split
= pipe_ctx
->top_pipe
&&
909 pipe_ctx
->top_pipe
->surface
== pipe_ctx
->surface
;
910 if (sec_split
&& surface
->public.address
.type
== PLN_ADDR_TYPE_GRPH_STEREO
&&
911 (pipe_ctx
->stream
->public.timing
.timing_3d_format
==
912 TIMING_3D_FORMAT_SIDE_BY_SIDE
||
913 pipe_ctx
->stream
->public.timing
.timing_3d_format
==
914 TIMING_3D_FORMAT_TOP_AND_BOTTOM
)) {
915 *addr
= surface
->public.address
.grph_stereo
.left_addr
;
916 surface
->public.address
.grph_stereo
.left_addr
=\
917 surface
->public.address
.grph_stereo
.right_addr
;
923 static void update_plane_addr(const struct core_dc
*dc
, struct pipe_ctx
*pipe_ctx
)
925 bool addr_patched
= false;
926 PHYSICAL_ADDRESS_LOC addr
;
927 struct core_surface
*surface
= pipe_ctx
->surface
;
931 addr_patched
= patch_address_for_sbs_tb_stereo(pipe_ctx
, &addr
);
932 pipe_ctx
->mi
->funcs
->mem_input_program_surface_flip_and_addr(
934 &surface
->public.address
,
935 surface
->public.flip_immediate
);
936 surface
->status
.requested_address
= surface
->public.address
;
938 pipe_ctx
->surface
->public.address
.grph_stereo
.left_addr
= addr
;
941 static bool dcn10_set_input_transfer_func(
942 struct pipe_ctx
*pipe_ctx
,
943 const struct core_surface
*surface
)
945 struct input_pixel_processor
*ipp
= pipe_ctx
->ipp
;
946 const struct core_transfer_func
*tf
= NULL
;
952 if (surface
->public.in_transfer_func
)
953 tf
= DC_TRANSFER_FUNC_TO_CORE(surface
->public.in_transfer_func
);
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
);
963 case TRANSFER_FUNCTION_BT709
:
964 ipp
->funcs
->ipp_set_degamma(ipp
,
965 IPP_DEGAMMA_MODE_HW_xvYCC
);
967 case TRANSFER_FUNCTION_LINEAR
:
968 ipp
->funcs
->ipp_set_degamma(ipp
,
969 IPP_DEGAMMA_MODE_BYPASS
);
971 case TRANSFER_FUNCTION_PQ
:
978 } else if (tf
->public.type
== TF_TYPE_BYPASS
) {
979 ipp
->funcs
->ipp_set_degamma(ipp
, IPP_DEGAMMA_MODE_BYPASS
);
981 /*TF_TYPE_DISTRIBUTED_POINTS*/
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
)
993 struct custom_float_format fmt
;
995 struct pwl_result_data
*rgb
= rgb_resulted
;
999 fmt
.exponenta_bits
= 6;
1000 fmt
.mantissa_bits
= 12;
1003 if (!convert_to_custom_float_format(
1006 &arr_points
[0].custom_float_x
)) {
1007 BREAK_TO_DEBUGGER();
1011 if (!convert_to_custom_float_format(
1012 arr_points
[0].offset
,
1014 &arr_points
[0].custom_float_offset
)) {
1015 BREAK_TO_DEBUGGER();
1019 if (!convert_to_custom_float_format(
1020 arr_points
[0].slope
,
1022 &arr_points
[0].custom_float_slope
)) {
1023 BREAK_TO_DEBUGGER();
1027 fmt
.mantissa_bits
= 10;
1030 if (!convert_to_custom_float_format(
1033 &arr_points
[1].custom_float_x
)) {
1034 BREAK_TO_DEBUGGER();
1038 if (!convert_to_custom_float_format(
1041 &arr_points
[1].custom_float_y
)) {
1042 BREAK_TO_DEBUGGER();
1046 if (!convert_to_custom_float_format(
1047 arr_points
[1].slope
,
1049 &arr_points
[1].custom_float_slope
)) {
1050 BREAK_TO_DEBUGGER();
1054 fmt
.mantissa_bits
= 12;
1057 while (i
!= hw_points_num
) {
1058 if (!convert_to_custom_float_format(
1062 BREAK_TO_DEBUGGER();
1066 if (!convert_to_custom_float_format(
1070 BREAK_TO_DEBUGGER();
1074 if (!convert_to_custom_float_format(
1078 BREAK_TO_DEBUGGER();
1082 if (!convert_to_custom_float_format(
1085 &rgb
->delta_red_reg
)) {
1086 BREAK_TO_DEBUGGER();
1090 if (!convert_to_custom_float_format(
1093 &rgb
->delta_green_reg
)) {
1094 BREAK_TO_DEBUGGER();
1098 if (!convert_to_custom_float_format(
1101 &rgb
->delta_blue_reg
)) {
1102 BREAK_TO_DEBUGGER();
1112 #define MAX_REGIONS_NUMBER 34
1113 #define MAX_LOW_POINT 25
1114 #define NUMBER_SEGMENTS 32
1116 static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func
1117 *output_tf
, struct pwl_params
*regamma_params
)
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
;
1129 int32_t segment_start
, segment_end
;
1131 uint32_t j
, k
, seg_distr
[MAX_REGIONS_NUMBER
], increment
, start_index
, hw_points
;
1133 if (output_tf
== NULL
|| regamma_params
== NULL
||
1134 output_tf
->type
== TF_TYPE_BYPASS
)
1137 arr_points
= regamma_params
->arr_points
;
1138 rgb_resulted
= regamma_params
->rgb_resulted
;
1141 memset(regamma_params
, 0, sizeof(struct pwl_params
));
1142 memset(seg_distr
, 0, sizeof(seg_distr
));
1144 if (output_tf
->tf
== TRANSFER_FUNCTION_PQ
) {
1146 * segments are from 2^-25 to 2^7
1148 for (i
= 0; i
< 32 ; i
++)
1151 segment_start
= -25;
1155 * segment is from 2^-10 to 2^0
1156 * There are less than 256 points, for optimization
1169 segment_start
= -10;
1173 for (i
= segment_end
- segment_start
; i
< MAX_REGIONS_NUMBER
; i
++)
1176 for (k
= 0; k
< MAX_REGIONS_NUMBER
; k
++) {
1177 if (seg_distr
[k
] != -1)
1178 hw_points
+= (1 << seg_distr
[k
]);
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)
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
];
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
];
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
));
1211 y_r
= rgb_resulted
[0].red
;
1212 y_g
= rgb_resulted
[0].green
;
1213 y_b
= rgb_resulted
[0].blue
;
1215 y1_min
= dal_fixed31_32_min(y_r
, dal_fixed31_32_min(y_g
, y_b
));
1217 arr_points
[0].y
= y1_min
;
1218 arr_points
[0].slope
= dal_fixed31_32_div(
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
;
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)
1228 y3_max
= dal_fixed31_32_max(y_r
, dal_fixed31_32_max(y_g
, y_b
));
1230 arr_points
[1].y
= y3_max
;
1231 arr_points
[2].y
= y3_max
;
1233 arr_points
[1].slope
= dal_fixed31_32_zero
;
1234 arr_points
[2].slope
= dal_fixed31_32_zero
;
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.
1240 const struct fixed31_32 end_value
=
1241 dal_fixed31_32_from_int(125);
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
));
1251 regamma_params
->hw_points_num
= hw_points
;
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
=
1258 regamma_params
->arr_curve_points
[i
].offset
=
1259 regamma_params
->arr_curve_points
[k
].
1260 offset
+ (1 << seg_distr
[k
]);
1265 if (seg_distr
[k
] != -1)
1266 regamma_params
->arr_curve_points
[k
].segments_num
=
1270 rgb_plus_1
= rgb_resulted
+ 1;
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
;
1282 rgb
->delta_red
= dal_fixed31_32_sub(
1285 rgb
->delta_green
= dal_fixed31_32_sub(
1288 rgb
->delta_blue
= dal_fixed31_32_sub(
1297 convert_to_custom_float(rgb_resulted
, arr_points
, hw_points
);
1302 static bool dcn10_set_output_transfer_func(
1303 struct pipe_ctx
*pipe_ctx
,
1304 const struct core_surface
*surface
,
1305 const struct core_stream
*stream
)
1307 struct output_pixel_processor
*opp
= pipe_ctx
->opp
;
1309 opp
->regamma_params
.hw_points_num
= GAMMA_HW_POINTS_NUM
;
1311 if (stream
->public.out_transfer_func
&&
1312 stream
->public.out_transfer_func
->type
==
1313 TF_TYPE_PREDEFINED
&&
1314 stream
->public.out_transfer_func
->tf
==
1315 TRANSFER_FUNCTION_SRGB
) {
1316 opp
->funcs
->opp_set_regamma_mode(opp
, OPP_REGAMMA_SRGB
);
1317 } else if (dcn10_translate_regamma_to_hw_format(
1318 stream
->public.out_transfer_func
, &opp
->regamma_params
)) {
1319 opp
->funcs
->opp_program_regamma_pwl(opp
, &opp
->regamma_params
);
1320 opp
->funcs
->opp_set_regamma_mode(opp
, OPP_REGAMMA_USER
);
1322 opp
->funcs
->opp_set_regamma_mode(opp
, OPP_REGAMMA_BYPASS
);
1328 static void dcn10_pipe_control_lock(
1330 struct pipe_ctx
*pipe
,
1333 struct dce_hwseq
*hws
= hws
= dc
->hwseq
;
1335 /* use TG master update lock to lock everything on the TG
1336 * therefore only top pipe need to lock
1342 dcn10_lock(pipe
->tg
);
1344 dcn10_unlock(pipe
->tg
);
1347 static bool wait_for_reset_trigger_to_occur(
1348 struct dc_context
*dc_ctx
,
1349 struct timing_generator
*tg
)
1353 /* To avoid endless loop we wait at most
1354 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1355 const uint32_t frames_to_wait_on_triggered_reset
= 10;
1358 for (i
= 0; i
< frames_to_wait_on_triggered_reset
; i
++) {
1360 if (!tg
->funcs
->is_counter_moving(tg
)) {
1361 DC_ERROR("TG counter is not moving!\n");
1365 if (tg
->funcs
->did_triggered_reset_occur(tg
)) {
1367 /* usually occurs at i=1 */
1368 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1373 /* Wait for one frame. */
1374 tg
->funcs
->wait_for_state(tg
, CRTC_STATE_VACTIVE
);
1375 tg
->funcs
->wait_for_state(tg
, CRTC_STATE_VBLANK
);
1379 DC_ERROR("GSL: Timeout on reset trigger!\n");
1384 static void dcn10_enable_timing_synchronization(
1388 struct pipe_ctx
*grouped_pipes
[])
1390 struct dc_context
*dc_ctx
= dc
->ctx
;
1393 DC_SYNC_INFO("Setting up OTG reset trigger\n");
1395 for (i
= 1; i
< group_size
; i
++)
1396 grouped_pipes
[i
]->tg
->funcs
->enable_reset_trigger(
1397 grouped_pipes
[i
]->tg
, grouped_pipes
[0]->tg
->inst
);
1400 DC_SYNC_INFO("Waiting for trigger\n");
1402 /* Need to get only check 1 pipe for having reset as all the others are
1403 * synchronized. Look at last pipe programmed to reset.
1405 wait_for_reset_trigger_to_occur(dc_ctx
, grouped_pipes
[1]->tg
);
1406 for (i
= 1; i
< group_size
; i
++)
1407 grouped_pipes
[i
]->tg
->funcs
->disable_reset_trigger(
1408 grouped_pipes
[i
]->tg
);
1410 DC_SYNC_INFO("Sync complete\n");
1413 static void dcn10_power_on_fe(
1415 struct pipe_ctx
*pipe_ctx
,
1416 struct validate_context
*context
)
1418 struct dc_surface
*dc_surface
= &pipe_ctx
->surface
->public;
1420 /* power up DCHUP and DPP from pseudo code pipe_move.c */
1421 /*TODO: function: power_on_plane. If already power up, skip
1424 power_on_plane(dc
->ctx
,
1425 pipe_ctx
->pipe_idx
, pipe_ctx
->tg
->inst
);
1427 /* enable DCFCLK current DCHUB */
1428 enable_dcfclk(dc
->ctx
,
1430 pipe_ctx
->pix_clk_params
.requested_pix_clk
,
1431 context
->dppclk_div
);
1434 dm_logger_write(dc
->ctx
->logger
, LOG_DC
,
1435 "Pipe:%d 0x%x: addr hi:0x%x, "
1438 " %d; dst: %d, %d, %d, %d;\n",
1441 dc_surface
->address
.grph
.addr
.high_part
,
1442 dc_surface
->address
.grph
.addr
.low_part
,
1443 dc_surface
->src_rect
.x
,
1444 dc_surface
->src_rect
.y
,
1445 dc_surface
->src_rect
.width
,
1446 dc_surface
->src_rect
.height
,
1447 dc_surface
->dst_rect
.x
,
1448 dc_surface
->dst_rect
.y
,
1449 dc_surface
->dst_rect
.width
,
1450 dc_surface
->dst_rect
.height
);
1452 dm_logger_write(dc
->ctx
->logger
, LOG_HW_SET_MODE
,
1453 "Pipe %d: width, height, x, y\n"
1454 "viewport:%d, %d, %d, %d\n"
1455 "recout: %d, %d, %d, %d\n",
1457 pipe_ctx
->scl_data
.viewport
.width
,
1458 pipe_ctx
->scl_data
.viewport
.height
,
1459 pipe_ctx
->scl_data
.viewport
.x
,
1460 pipe_ctx
->scl_data
.viewport
.y
,
1461 pipe_ctx
->scl_data
.recout
.width
,
1462 pipe_ctx
->scl_data
.recout
.height
,
1463 pipe_ctx
->scl_data
.recout
.x
,
1464 pipe_ctx
->scl_data
.recout
.y
);
1470 static void program_gamut_remap(struct pipe_ctx
*pipe_ctx
)
1472 struct xfm_grph_csc_adjustment adjust
;
1473 memset(&adjust
, 0, sizeof(adjust
));
1474 adjust
.gamut_adjust_type
= GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS
;
1477 if (pipe_ctx
->stream
->public.gamut_remap_matrix
.enable_remap
== true) {
1478 adjust
.gamut_adjust_type
= GRAPHICS_GAMUT_ADJUST_TYPE_SW
;
1479 adjust
.temperature_matrix
[0] =
1481 public.gamut_remap_matrix
.matrix
[0];
1482 adjust
.temperature_matrix
[1] =
1484 public.gamut_remap_matrix
.matrix
[1];
1485 adjust
.temperature_matrix
[2] =
1487 public.gamut_remap_matrix
.matrix
[2];
1488 adjust
.temperature_matrix
[3] =
1490 public.gamut_remap_matrix
.matrix
[4];
1491 adjust
.temperature_matrix
[4] =
1493 public.gamut_remap_matrix
.matrix
[5];
1494 adjust
.temperature_matrix
[5] =
1496 public.gamut_remap_matrix
.matrix
[6];
1497 adjust
.temperature_matrix
[6] =
1499 public.gamut_remap_matrix
.matrix
[8];
1500 adjust
.temperature_matrix
[7] =
1502 public.gamut_remap_matrix
.matrix
[9];
1503 adjust
.temperature_matrix
[8] =
1505 public.gamut_remap_matrix
.matrix
[10];
1508 pipe_ctx
->xfm
->funcs
->transform_set_gamut_remap(pipe_ctx
->xfm
, &adjust
);
1511 static void update_dchubp_dpp(
1513 struct pipe_ctx
*pipe_ctx
,
1514 struct validate_context
*context
)
1516 struct mem_input
*mi
= pipe_ctx
->mi
;
1517 struct input_pixel_processor
*ipp
= pipe_ctx
->ipp
;
1518 struct core_surface
*surface
= pipe_ctx
->surface
;
1519 union plane_size size
= surface
->public.plane_size
;
1520 struct mpc_tree_cfg
*tree_cfg
= NULL
;
1521 struct default_adjustment ocsc
= {0};
1522 enum dc_color_space color_space
;
1523 struct tg_color black_color
= {0};
1524 struct dcn10_mpc
*mpc
= TO_DCN10_MPC(dc
->res_pool
->mpc
);
1526 /* depends on DML calculation, DPP clock value may change dynamically */
1530 pipe_ctx
->pix_clk_params
.requested_pix_clk
,
1531 context
->dppclk_div
);
1533 select_vtg(dc
->ctx
, pipe_ctx
->pipe_idx
, pipe_ctx
->tg
->inst
);
1535 update_plane_addr(dc
, pipe_ctx
);
1537 mi
->funcs
->mem_input_setup(
1539 &pipe_ctx
->dlg_regs
,
1540 &pipe_ctx
->ttu_regs
,
1542 &pipe_ctx
->pipe_dlg_param
);
1544 size
.grph
.surface_size
= pipe_ctx
->scl_data
.viewport
;
1546 if (dc
->public.config
.gpu_vm_support
)
1547 mi
->funcs
->mem_input_program_pte_vm(
1549 surface
->public.format
,
1550 &surface
->public.tiling_info
,
1551 surface
->public.rotation
);
1553 ipp
->funcs
->ipp_setup(ipp
,
1554 surface
->public.format
,
1556 IPP_OUTPUT_FORMAT_12_BIT_FIX
);
1558 /* mpc TODO un-hardcode object ids
1559 * for pseudo code pipe_move.c :
1560 * add_plane_mpcc(added_plane_inst, mpcc_inst, ...);
1561 * Do we want to cache the tree_cfg?
1564 /* TODO: build stream pipes group id. For now, use stream otg
1565 * id as pipe group id
1567 pipe_ctx
->mpc_idx
= pipe_ctx
->tg
->inst
;
1568 tree_cfg
= &context
->res_ctx
.mpc_tree
[pipe_ctx
->mpc_idx
];
1569 /* enable when bottom pipe is present and
1570 * it does not share a surface with current pipe
1572 if (pipe_ctx
->bottom_pipe
&& surface
!= pipe_ctx
->bottom_pipe
->surface
) {
1573 pipe_ctx
->scl_data
.lb_params
.alpha_en
= 1;
1574 tree_cfg
->mode
= TOP_BLND
;
1576 pipe_ctx
->scl_data
.lb_params
.alpha_en
= 0;
1577 tree_cfg
->mode
= TOP_PASSTHRU
;
1579 if (!pipe_ctx
->top_pipe
) {
1580 /* primary pipe, set mpc tree index 0 only */
1581 tree_cfg
->num_pipes
= 1;
1582 tree_cfg
->opp_id
= pipe_ctx
->tg
->inst
;
1583 tree_cfg
->dpp
[0] = pipe_ctx
->pipe_idx
;
1584 tree_cfg
->mpcc
[0] = pipe_ctx
->pipe_idx
;
1585 dcn10_set_mpc_tree(mpc
, tree_cfg
);
1587 /* TODO: add position is hard code to 1 for now
1588 * If more than 2 pipes are supported, calculate position
1590 dcn10_add_dpp(mpc
, tree_cfg
,
1591 pipe_ctx
->pipe_idx
, pipe_ctx
->pipe_idx
, 1);
1594 color_space
= pipe_ctx
->stream
->public.output_color_space
;
1595 color_space_to_black_color(dc
, color_space
, &black_color
);
1596 dcn10_set_mpc_background_color(mpc
, pipe_ctx
->pipe_idx
, &black_color
);
1598 pipe_ctx
->scl_data
.lb_params
.depth
= LB_PIXEL_DEPTH_30BPP
;
1599 /* scaler configuration */
1600 pipe_ctx
->xfm
->funcs
->transform_set_scaler(
1601 pipe_ctx
->xfm
, &pipe_ctx
->scl_data
);
1604 program_gamut_remap(pipe_ctx
);
1606 /*TODO add adjustments parameters*/
1607 ocsc
.out_color_space
= pipe_ctx
->stream
->public.output_color_space
;
1608 pipe_ctx
->opp
->funcs
->opp_set_csc_default(pipe_ctx
->opp
, &ocsc
);
1610 mi
->funcs
->mem_input_program_surface_config(
1612 surface
->public.format
,
1613 &surface
->public.tiling_info
,
1615 surface
->public.rotation
,
1616 &surface
->public.dcc
,
1617 surface
->public.horizontal_mirror
,
1618 surface
->public.visible
);
1620 /* Only support one plane for now. */
1621 pipe_ctx
->tg
->funcs
->set_blank(pipe_ctx
->tg
, !surface
->public.visible
);
1625 static void program_all_pipe_in_tree(
1627 struct pipe_ctx
*pipe_ctx
,
1628 struct validate_context
*context
)
1630 unsigned int ref_clk_mhz
= dc
->res_pool
->ref_clock_inKhz
/1000;
1632 if (pipe_ctx
->surface
->public.visible
|| pipe_ctx
->top_pipe
== NULL
) {
1633 dcn10_power_on_fe(dc
, pipe_ctx
, context
);
1635 /* lock otg_master_update to process all pipes associated with
1636 * this OTG. this is done only one time.
1638 if (pipe_ctx
->top_pipe
== NULL
) {
1639 /* watermark is for all pipes */
1640 pipe_ctx
->mi
->funcs
->program_watermarks(
1641 pipe_ctx
->mi
, &context
->watermarks
, ref_clk_mhz
);
1642 lock_otg_master_update(dc
->ctx
, pipe_ctx
->tg
->inst
);
1644 pipe_ctx
->tg
->dlg_otg_param
.vready_offset
= pipe_ctx
->pipe_dlg_param
.vready_offset
;
1645 pipe_ctx
->tg
->dlg_otg_param
.vstartup_start
= pipe_ctx
->pipe_dlg_param
.vstartup_start
;
1646 pipe_ctx
->tg
->dlg_otg_param
.vupdate_offset
= pipe_ctx
->pipe_dlg_param
.vupdate_offset
;
1647 pipe_ctx
->tg
->dlg_otg_param
.vupdate_width
= pipe_ctx
->pipe_dlg_param
.vupdate_width
;
1648 pipe_ctx
->tg
->dlg_otg_param
.signal
= pipe_ctx
->stream
->signal
;
1649 pipe_ctx
->tg
->funcs
->program_global_sync(
1651 update_dchubp_dpp(dc
, pipe_ctx
, context
);
1654 if (pipe_ctx
->bottom_pipe
!= NULL
)
1655 program_all_pipe_in_tree(dc
, pipe_ctx
->bottom_pipe
, context
);
1658 static void dcn10_pplib_apply_display_requirements(
1660 struct validate_context
*context
)
1662 struct dm_pp_display_configuration
*pp_display_cfg
= &context
->pp_display_cfg
;
1664 pp_display_cfg
->all_displays_in_sync
= false;/*todo*/
1665 pp_display_cfg
->nb_pstate_switch_disable
= false;
1666 pp_display_cfg
->min_engine_clock_khz
= context
->dcfclk_khz
;
1667 pp_display_cfg
->min_memory_clock_khz
= context
->fclk_khz
;
1668 pp_display_cfg
->min_engine_clock_deep_sleep_khz
= context
->dcfclk_deep_sleep_khz
;
1669 pp_display_cfg
->min_dcfc_deep_sleep_clock_khz
= context
->dcfclk_deep_sleep_khz
;
1670 pp_display_cfg
->avail_mclk_switch_time_us
=
1671 context
->dram_ccm_us
> 0 ? context
->dram_ccm_us
: 0;
1672 pp_display_cfg
->avail_mclk_switch_time_in_disp_active_us
=
1673 context
->min_active_dram_ccm_us
> 0 ? context
->min_active_dram_ccm_us
: 0;
1674 pp_display_cfg
->min_dcfclock_khz
= context
->dcfclk_khz
;
1675 pp_display_cfg
->disp_clk_khz
= context
->dispclk_khz
;
1676 dce110_fill_display_configs(context
, pp_display_cfg
);
1678 if (memcmp(&dc
->prev_display_config
, pp_display_cfg
, sizeof(
1679 struct dm_pp_display_configuration
)) != 0)
1680 dm_pp_apply_display_requirements(dc
->ctx
, pp_display_cfg
);
1682 dc
->prev_display_config
= *pp_display_cfg
;
1685 static void dcn10_apply_ctx_for_surface(
1687 struct core_surface
*surface
,
1688 struct validate_context
*context
)
1692 memcpy(context
->res_ctx
.mpc_tree
,
1693 dc
->current_context
->res_ctx
.mpc_tree
,
1694 sizeof(struct mpc_tree_cfg
) * dc
->res_pool
->pipe_count
);
1696 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1697 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
1699 if (!pipe_ctx
->surface
)
1702 /* looking for top pipe to program */
1703 if (!pipe_ctx
->top_pipe
)
1704 program_all_pipe_in_tree(dc
, pipe_ctx
, context
);
1707 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1708 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
1710 if (!pipe_ctx
->surface
|| pipe_ctx
->top_pipe
)
1713 /* unlock master update lock */
1714 unlock_otg_master(dc
->ctx
, pipe_ctx
->tg
->inst
);
1717 /* reset unused pipe */
1718 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1719 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
1720 struct pipe_ctx
*old_pipe_ctx
=
1721 &dc
->current_context
->res_ctx
.pipe_ctx
[i
];
1723 if ((!pipe_ctx
->surface
&& old_pipe_ctx
->surface
)
1724 || (!pipe_ctx
->stream
&& old_pipe_ctx
->stream
))
1725 reset_front_end_for_pipe(dc
,
1726 old_pipe_ctx
, dc
->current_context
);
1730 static void dcn10_set_bandwidth(
1732 struct validate_context
*context
,
1733 bool decrease_allowed
)
1735 struct dm_pp_clock_for_voltage_req clock
;
1737 if (IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
))
1740 if (decrease_allowed
|| context
->dispclk_khz
> dc
->current_context
->dispclk_khz
) {
1741 dc
->res_pool
->display_clock
->funcs
->set_clock(
1742 dc
->res_pool
->display_clock
,
1743 context
->dispclk_khz
);
1744 dc
->current_context
->dispclk_khz
= context
->dispclk_khz
;
1746 if (decrease_allowed
|| context
->dcfclk_khz
> dc
->current_context
->dcfclk_khz
) {
1747 clock
.clk_type
= DM_PP_CLOCK_TYPE_DCFCLK
;
1748 clock
.clocks_in_khz
= context
->dcfclk_khz
;
1749 dm_pp_apply_clock_for_voltage_request(dc
->ctx
, &clock
);
1751 if (decrease_allowed
|| context
->fclk_khz
> dc
->current_context
->fclk_khz
) {
1752 clock
.clk_type
= DM_PP_CLOCK_TYPE_FCLK
;
1753 clock
.clocks_in_khz
= context
->fclk_khz
;
1754 dm_pp_apply_clock_for_voltage_request(dc
->ctx
, &clock
);
1755 dc
->current_context
->fclk_khz
= clock
.clocks_in_khz
;
1757 dcn10_pplib_apply_display_requirements(dc
, context
);
1760 static void dcn10_power_down_fe(struct core_dc
*dc
, struct pipe_ctx
*pipe
)
1762 struct dc_context
*ctx
= dc
->ctx
;
1763 uint32_t inst_offset
= 0;
1765 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL
,
1767 dpp_pg_control(ctx
, pipe
->pipe_idx
, false);
1768 hubp_pg_control(ctx
, pipe
->pipe_idx
, false);
1769 HWSEQ_REG_SET(DC_IP_REQUEST_CNTL
,
1773 pipe
->xfm
->funcs
->transform_reset(pipe
->xfm
);
1774 memset(&pipe
->scl_data
, 0, sizeof(pipe
->scl_data
));
1777 static void set_drr(struct pipe_ctx
**pipe_ctx
,
1778 int num_pipes
, int vmin
, int vmax
)
1781 struct drr_params params
= {0};
1783 params
.vertical_total_max
= vmax
;
1784 params
.vertical_total_min
= vmin
;
1786 /* TODO: If multiple pipes are to be supported, you need
1789 for (i
= 0; i
< num_pipes
; i
++) {
1790 pipe_ctx
[i
]->tg
->funcs
->set_drr(pipe_ctx
[i
]->tg
, ¶ms
);
1794 static void get_position(struct pipe_ctx
**pipe_ctx
,
1796 struct crtc_position
*position
)
1800 /* TODO: handle pipes > 1
1802 for (i
= 0; i
< num_pipes
; i
++)
1803 pipe_ctx
[i
]->tg
->funcs
->get_position(pipe_ctx
[i
]->tg
, position
);
1806 static void set_static_screen_control(struct pipe_ctx
**pipe_ctx
,
1807 int num_pipes
, const struct dc_static_screen_events
*events
)
1810 unsigned int value
= 0;
1812 if (events
->surface_update
)
1814 if (events
->cursor_update
)
1817 for (i
= 0; i
< num_pipes
; i
++)
1818 pipe_ctx
[i
]->tg
->funcs
->
1819 set_static_screen_control(pipe_ctx
[i
]->tg
, value
);
1822 static void set_plane_config(
1823 const struct core_dc
*dc
,
1824 struct pipe_ctx
*pipe_ctx
,
1825 struct resource_context
*res_ctx
)
1828 program_gamut_remap(pipe_ctx
);
1831 static const struct hw_sequencer_funcs dcn10_funcs
= {
1833 .apply_ctx_to_hw
= dce110_apply_ctx_to_hw
,
1834 .apply_ctx_for_surface
= dcn10_apply_ctx_for_surface
,
1835 .set_plane_config
= set_plane_config
,
1836 .update_plane_addr
= update_plane_addr
,
1837 .update_pending_status
= dce110_update_pending_status
,
1838 .set_input_transfer_func
= dcn10_set_input_transfer_func
,
1839 .set_output_transfer_func
= dcn10_set_output_transfer_func
,
1840 .power_down
= dce110_power_down
,
1841 .enable_accelerated_mode
= dce110_enable_accelerated_mode
,
1842 .enable_timing_synchronization
= dcn10_enable_timing_synchronization
,
1843 .update_info_frame
= dce110_update_info_frame
,
1844 .enable_stream
= dce110_enable_stream
,
1845 .disable_stream
= dce110_disable_stream
,
1846 .unblank_stream
= dce110_unblank_stream
,
1847 .enable_display_pipe_clock_gating
= NULL
, /* TODOFPGA */
1848 .enable_display_power_gating
= dcn10_enable_display_power_gating
,
1849 .power_down_front_end
= dcn10_power_down_fe
,
1850 .power_on_front_end
= dcn10_power_on_fe
,
1851 .pipe_control_lock
= dcn10_pipe_control_lock
,
1852 .set_bandwidth
= dcn10_set_bandwidth
,
1853 .reset_hw_ctx_wrap
= reset_hw_ctx_wrap
,
1854 .prog_pixclk_crtc_otg
= dcn10_prog_pixclk_crtc_otg
,
1856 .get_position
= get_position
,
1857 .set_static_screen_control
= set_static_screen_control
1861 bool dcn10_hw_sequencer_construct(struct core_dc
*dc
)
1863 dc
->hwss
= dcn10_funcs
;