]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drm/amd/display: rename struct mem_input to hubp for dcn
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dcn10 / dcn10_hw_sequencer.c
CommitLineData
70ccab60
HW
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"
70ccab60 27#include "core_types.h"
70ccab60 28#include "resource.h"
b02c3b05 29#include "custom_float.h"
70ccab60
HW
30#include "dcn10_hw_sequencer.h"
31#include "dce110/dce110_hw_sequencer.h"
5aff86c1 32#include "dce/dce_hwseq.h"
70ccab60 33#include "abm.h"
2248eb6b 34#include "dcn10/dcn10_mem_input.h"
214435ff 35#include "dcn10/dcn10_timing_generator.h"
587cdfe9
VP
36#include "dcn10/dcn10_dpp.h"
37#include "dcn10/dcn10_mpc.h"
70ccab60
HW
38#include "timing_generator.h"
39#include "opp.h"
40#include "ipp.h"
b02c3b05 41#include "mpc.h"
184debdb 42#include "reg_helper.h"
a6def445 43#include "custom_float.h"
70ccab60 44
184debdb
DL
45#define CTX \
46 hws->ctx
47#define REG(reg)\
48 hws->regs->reg
70ccab60 49
184debdb
DL
50#undef FN
51#define FN(reg_name, field_name) \
52 hws->shifts->field_name, hws->masks->field_name
70ccab60 53
fb3466a4 54static void log_mpc_crc(struct dc *dc)
71395011
TC
55{
56 struct dc_context *dc_ctx = dc->ctx;
57 struct dce_hwseq *hws = dc->hwseq;
58
59 if (REG(MPC_CRC_RESULT_GB))
60 DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n",
61 REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR));
62 if (REG(DPP_TOP0_DPP_CRC_VAL_B_A))
63 DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n",
64 REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G));
65}
66
eb4e33b7
TC
67void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle)
68{
69 static const uint32_t ref_clk_mhz = 48;
70 static const unsigned int frac = 10;
71 uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
72
73 DTN_INFO("%d.%d \t ",
74 us_x10 / frac,
75 us_x10 % frac);
76}
77
78#define DTN_INFO_MICRO_SEC(ref_cycle) \
79 print_microsec(dc_ctx, ref_cycle)
80
233dcd20
TC
81struct dcn_hubbub_wm_set {
82 uint32_t wm_set;
83 uint32_t data_urgent;
84 uint32_t pte_meta_urgent;
85 uint32_t sr_enter;
86 uint32_t sr_exit;
87 uint32_t dram_clk_chanage;
88};
89
90struct dcn_hubbub_wm {
91 struct dcn_hubbub_wm_set sets[4];
92};
93
94static void dcn10_hubbub_wm_read_state(struct dce_hwseq *hws,
95 struct dcn_hubbub_wm *wm)
96{
97 struct dcn_hubbub_wm_set *s;
98
99 s = &wm->sets[0];
100 s->wm_set = 0;
101 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
102 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A);
103 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
104 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
105 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
106
107 s = &wm->sets[1];
108 s->wm_set = 1;
109 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B);
110 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B);
111 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);
112 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);
113 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
114
115 s = &wm->sets[2];
116 s->wm_set = 2;
117 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C);
118 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C);
119 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);
120 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);
121 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
122
123 s = &wm->sets[3];
124 s->wm_set = 3;
125 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D);
126 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D);
127 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);
128 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);
129 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
130}
131
fb3466a4 132static void dcn10_log_hubbub_state(struct dc *dc)
233dcd20
TC
133{
134 struct dc_context *dc_ctx = dc->ctx;
135 struct dcn_hubbub_wm wm;
136 int i;
137
138 dcn10_hubbub_wm_read_state(dc->hwseq, &wm);
139
140 DTN_INFO("HUBBUB WM: \t data_urgent \t pte_meta_urgent \t "
141 "sr_enter \t sr_exit \t dram_clk_change \n");
142
143 for (i = 0; i < 4; i++) {
144 struct dcn_hubbub_wm_set *s;
145
146 s = &wm.sets[i];
147 DTN_INFO("WM_Set[%d]:\t ", s->wm_set);
148 DTN_INFO_MICRO_SEC(s->data_urgent);
149 DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
150 DTN_INFO_MICRO_SEC(s->sr_enter);
151 DTN_INFO_MICRO_SEC(s->sr_exit);
152 DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
153 DTN_INFO("\n");
154 }
155
156 DTN_INFO("\n");
157}
158
fb3466a4 159static void dcn10_log_hw_state(struct dc *dc)
71395011
TC
160{
161 struct dc_context *dc_ctx = dc->ctx;
162 struct resource_pool *pool = dc->res_pool;
163 int i;
164
165 DTN_INFO_BEGIN();
166
233dcd20
TC
167 dcn10_log_hubbub_state(dc);
168
eb4e33b7
TC
169 DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t "
170 "rotation \t mirror \t sw_mode \t "
171 "dcc_en \t blank_en \t ttu_dis \t underflow \t "
71395011
TC
172 "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n");
173
174 for (i = 0; i < pool->pipe_count; i++) {
8feabd03 175 struct hubp *hubp = pool->hubps[i];
71395011
TC
176 struct dcn_hubp_state s;
177
8feabd03 178 hubp1_read_state(TO_DCN10_HUBP(hubp), &s);
71395011 179
eb4e33b7
TC
180 DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t "
181 "%xh \t %xh \t %xh \t "
182 "%d \t %d \t %d \t %xh \t",
71395011
TC
183 i,
184 s.pixel_format,
185 s.inuse_addr_hi,
186 s.viewport_width,
187 s.viewport_height,
188 s.rotation_angle,
189 s.h_mirror_en,
190 s.sw_mode,
191 s.dcc_en,
192 s.blank_en,
193 s.ttu_disable,
eb4e33b7
TC
194 s.underflow_status);
195 DTN_INFO_MICRO_SEC(s.min_ttu_vblank);
196 DTN_INFO_MICRO_SEC(s.qos_level_low_wm);
197 DTN_INFO_MICRO_SEC(s.qos_level_high_wm);
198 DTN_INFO("\n");
71395011
TC
199 }
200 DTN_INFO("\n");
201
214435ff
CM
202 DTN_INFO("OTG:\t v_bs \t v_be \t v_ss \t v_se \t vpol \t vmax \t vmin \t "
203 "h_bs \t h_be \t h_ss \t h_se \t hpol \t htot \t vtot \t underflow\n");
204
205 for (i = 0; i < pool->pipe_count; i++) {
206 struct timing_generator *tg = pool->timing_generators[i];
6f54d0b1 207 struct dcn_otg_state s = {0};
214435ff
CM
208
209 tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s);
210
6f54d0b1
LT
211 //only print if OTG master is enabled
212 if ((s.otg_enabled & 1) == 0)
213 continue;
214
214435ff
CM
215 DTN_INFO("[%d]:\t %d \t %d \t %d \t %d \t "
216 "%d \t %d \t %d \t %d \t %d \t %d \t "
217 "%d \t %d \t %d \t %d \t %d \t ",
218 i,
219 s.v_blank_start,
220 s.v_blank_end,
221 s.v_sync_a_start,
222 s.v_sync_a_end,
223 s.v_sync_a_pol,
224 s.v_total_max,
225 s.v_total_min,
226 s.h_blank_start,
227 s.h_blank_end,
228 s.h_sync_a_start,
229 s.h_sync_a_end,
230 s.h_sync_a_pol,
231 s.h_total,
232 s.v_total,
233 s.underflow_occurred_status);
234 DTN_INFO("\n");
235 }
236 DTN_INFO("\n");
237
71395011
TC
238 log_mpc_crc(dc);
239
240 DTN_INFO_END();
241}
2b13d7d3
TC
242
243static void verify_allow_pstate_change_high(
244 struct dce_hwseq *hws)
245{
246 /* pstate latency is ~20us so if we wait over 40us and pstate allow
247 * still not asserted, we are probably stuck and going to hang
ff79cbdc
BL
248 *
249 * TODO: Figure out why it takes ~100us on linux
250 * pstate takes around ~100us on linux. Unknown currently as to
251 * why it takes that long on linux
2b13d7d3 252 */
ff79cbdc
BL
253 static unsigned int pstate_wait_timeout_us = 200;
254 static unsigned int pstate_wait_expected_timeout_us = 40;
2b13d7d3
TC
255 static unsigned int max_sampled_pstate_wait_us; /* data collection */
256 static bool forced_pstate_allow; /* help with revert wa */
08b8ccfb 257 static bool should_log_hw_state; /* prevent hw state log by default */
2b13d7d3
TC
258
259 unsigned int debug_index = 0x7;
260 unsigned int debug_data;
2b13d7d3
TC
261 unsigned int i;
262
263 if (forced_pstate_allow) {
264 /* we hacked to force pstate allow to prevent hang last time
265 * we verify_allow_pstate_change_high. so disable force
266 * here so we can check status
267 */
458e9d03
BL
268 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
269 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
270 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);
2b13d7d3
TC
271 forced_pstate_allow = false;
272 }
273
274 /* description "3-0: Pipe0 cursor0 QOS
275 * 7-4: Pipe1 cursor0 QOS
276 * 11-8: Pipe2 cursor0 QOS
277 * 15-12: Pipe3 cursor0 QOS
278 * 16: Pipe0 Plane0 Allow Pstate Change
279 * 17: Pipe1 Plane0 Allow Pstate Change
280 * 18: Pipe2 Plane0 Allow Pstate Change
281 * 19: Pipe3 Plane0 Allow Pstate Change
282 * 20: Pipe0 Plane1 Allow Pstate Change
283 * 21: Pipe1 Plane1 Allow Pstate Change
284 * 22: Pipe2 Plane1 Allow Pstate Change
285 * 23: Pipe3 Plane1 Allow Pstate Change
286 * 24: Pipe0 cursor0 Allow Pstate Change
287 * 25: Pipe1 cursor0 Allow Pstate Change
288 * 26: Pipe2 cursor0 Allow Pstate Change
289 * 27: Pipe3 cursor0 Allow Pstate Change
290 * 28: WB0 Allow Pstate Change
291 * 29: WB1 Allow Pstate Change
292 * 30: Arbiter's allow_pstate_change
293 * 31: SOC pstate change request
294 */
295
296 REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, debug_index);
297
298 for (i = 0; i < pstate_wait_timeout_us; i++) {
299 debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
300
ff79cbdc
BL
301 if (debug_data & (1 << 30)) {
302
303 if (i > pstate_wait_expected_timeout_us)
304 dm_logger_write(hws->ctx->logger, LOG_WARNING,
305 "pstate took longer than expected ~%dus",
306 i);
2b13d7d3 307
ff79cbdc
BL
308 return;
309 }
2b13d7d3
TC
310 if (max_sampled_pstate_wait_us < i)
311 max_sampled_pstate_wait_us = i;
312
313 udelay(1);
314 }
315
316 /* force pstate allow to prevent system hang
317 * and break to debugger to investigate
318 */
458e9d03
BL
319 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
320 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,
321 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
2b13d7d3 322 forced_pstate_allow = true;
71395011 323
08b8ccfb 324 if (should_log_hw_state) {
fb3466a4 325 dcn10_log_hw_state(hws->ctx->dc);
08b8ccfb 326 }
71395011 327
ff79cbdc
BL
328 dm_logger_write(hws->ctx->logger, LOG_WARNING,
329 "pstate TEST_DEBUG_DATA: 0x%X",
330 debug_data);
2b13d7d3
TC
331 BREAK_TO_DEBUGGER();
332}
333
70ccab60 334static void enable_dppclk(
184debdb 335 struct dce_hwseq *hws,
70ccab60
HW
336 uint8_t plane_id,
337 uint32_t requested_pix_clk,
338 bool dppclk_div)
339{
184debdb 340 dm_logger_write(hws->ctx->logger, LOG_SURFACE,
70ccab60
HW
341 "dppclk_rate_control for pipe %d programed to %d\n",
342 plane_id,
343 dppclk_div);
344
4e5095ca 345 if (hws->shifts->DPPCLK_RATE_CONTROL)
184debdb 346 REG_UPDATE_2(DPP_CONTROL[plane_id],
4e5095ca 347 DPPCLK_RATE_CONTROL, dppclk_div,
70ccab60 348 DPP_CLOCK_ENABLE, 1);
4e5095ca
DL
349 else
350 REG_UPDATE(DPP_CONTROL[plane_id],
70ccab60 351 DPP_CLOCK_ENABLE, 1);
70ccab60
HW
352}
353
354static void enable_power_gating_plane(
184debdb 355 struct dce_hwseq *hws,
70ccab60
HW
356 bool enable)
357{
70ccab60
HW
358 bool force_on = 1; /* disable power gating */
359
360 if (enable)
361 force_on = 0;
362
363 /* DCHUBP0/1/2/3 */
184debdb
DL
364 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
365 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
366 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
367 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
70ccab60
HW
368
369 /* DPP0/1/2/3 */
184debdb
DL
370 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
371 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
372 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
373 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
70ccab60
HW
374}
375
0a87425a
TC
376static void disable_vga(
377 struct dce_hwseq *hws)
378{
379 REG_WRITE(D1VGA_CONTROL, 0);
380 REG_WRITE(D2VGA_CONTROL, 0);
381 REG_WRITE(D3VGA_CONTROL, 0);
382 REG_WRITE(D4VGA_CONTROL, 0);
383}
384
70ccab60 385static void dpp_pg_control(
184debdb 386 struct dce_hwseq *hws,
70ccab60
HW
387 unsigned int dpp_inst,
388 bool power_on)
389{
70ccab60
HW
390 uint32_t power_gate = power_on ? 0 : 1;
391 uint32_t pwr_status = power_on ? 0 : 2;
392
184debdb 393 if (hws->ctx->dc->debug.disable_dpp_power_gate)
70ccab60
HW
394 return;
395
396 switch (dpp_inst) {
397 case 0: /* DPP0 */
184debdb 398 REG_UPDATE(DOMAIN1_PG_CONFIG,
70ccab60
HW
399 DOMAIN1_POWER_GATE, power_gate);
400
184debdb 401 REG_WAIT(DOMAIN1_PG_STATUS,
8a5d8245
TC
402 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
403 1, 1000);
70ccab60
HW
404 break;
405 case 1: /* DPP1 */
184debdb 406 REG_UPDATE(DOMAIN3_PG_CONFIG,
70ccab60
HW
407 DOMAIN3_POWER_GATE, power_gate);
408
184debdb 409 REG_WAIT(DOMAIN3_PG_STATUS,
8a5d8245
TC
410 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
411 1, 1000);
70ccab60
HW
412 break;
413 case 2: /* DPP2 */
184debdb 414 REG_UPDATE(DOMAIN5_PG_CONFIG,
70ccab60
HW
415 DOMAIN5_POWER_GATE, power_gate);
416
184debdb 417 REG_WAIT(DOMAIN5_PG_STATUS,
8a5d8245
TC
418 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
419 1, 1000);
70ccab60
HW
420 break;
421 case 3: /* DPP3 */
184debdb 422 REG_UPDATE(DOMAIN7_PG_CONFIG,
70ccab60
HW
423 DOMAIN7_POWER_GATE, power_gate);
424
184debdb 425 REG_WAIT(DOMAIN7_PG_STATUS,
8a5d8245
TC
426 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
427 1, 1000);
70ccab60
HW
428 break;
429 default:
430 BREAK_TO_DEBUGGER();
431 break;
432 }
433}
434
08b16886
ZF
435static uint32_t convert_and_clamp(
436 uint32_t wm_ns,
437 uint32_t refclk_mhz,
438 uint32_t clamp_value)
439{
440 uint32_t ret_val = 0;
441 ret_val = wm_ns * refclk_mhz;
442 ret_val /= 1000;
443
444 if (ret_val > clamp_value)
445 ret_val = clamp_value;
446
447 return ret_val;
448}
449
450static void program_watermarks(
451 struct dce_hwseq *hws,
452 struct dcn_watermark_set *watermarks,
453 unsigned int refclk_mhz)
454{
455 uint32_t force_en = hws->ctx->dc->debug.disable_stutter ? 1 : 0;
456 /*
457 * Need to clamp to max of the register values (i.e. no wrap)
458 * for dcn1, all wm registers are 21-bit wide
459 */
460 uint32_t prog_wm_value;
461
cbb4d72e
YS
462 REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
463 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0);
464
08b16886
ZF
465 /* Repeat for water mark set A, B, C and D. */
466 /* clock state A */
467 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
468 refclk_mhz, 0x1fffff);
469 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
470
471 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
472 "URGENCY_WATERMARK_A calculated =%d\n"
473 "HW register value = 0x%x\n",
474 watermarks->a.urgent_ns, prog_wm_value);
475
476 prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
477 refclk_mhz, 0x1fffff);
478 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
479 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
480 "PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
481 "HW register value = 0x%x\n",
482 watermarks->a.pte_meta_urgent_ns, prog_wm_value);
483
484
485 prog_wm_value = convert_and_clamp(
486 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
487 refclk_mhz, 0x1fffff);
488
489 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
490 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
491 "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
492 "HW register value = 0x%x\n",
493 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
494
495
496 prog_wm_value = convert_and_clamp(
497 watermarks->a.cstate_pstate.cstate_exit_ns,
498 refclk_mhz, 0x1fffff);
499 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
500 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
501 "SR_EXIT_WATERMARK_A calculated =%d\n"
502 "HW register value = 0x%x\n",
503 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
504
505
506 prog_wm_value = convert_and_clamp(
507 watermarks->a.cstate_pstate.pstate_change_ns,
508 refclk_mhz, 0x1fffff);
509 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
510 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
511 "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
512 "HW register value = 0x%x\n\n",
513 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
514
515
516 /* clock state B */
517 prog_wm_value = convert_and_clamp(
518 watermarks->b.urgent_ns, refclk_mhz, 0x1fffff);
519 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
520 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
521 "URGENCY_WATERMARK_B calculated =%d\n"
522 "HW register value = 0x%x\n",
523 watermarks->b.urgent_ns, prog_wm_value);
524
525
526 prog_wm_value = convert_and_clamp(
527 watermarks->b.pte_meta_urgent_ns,
528 refclk_mhz, 0x1fffff);
529 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
530 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
531 "PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
532 "HW register value = 0x%x\n",
533 watermarks->b.pte_meta_urgent_ns, prog_wm_value);
534
535
536 prog_wm_value = convert_and_clamp(
537 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
538 refclk_mhz, 0x1fffff);
539 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
540 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
541 "SR_ENTER_WATERMARK_B calculated =%d\n"
542 "HW register value = 0x%x\n",
543 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
544
545
546 prog_wm_value = convert_and_clamp(
547 watermarks->b.cstate_pstate.cstate_exit_ns,
548 refclk_mhz, 0x1fffff);
549 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
550 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
551 "SR_EXIT_WATERMARK_B calculated =%d\n"
552 "HW register value = 0x%x\n",
553 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
554
555 prog_wm_value = convert_and_clamp(
556 watermarks->b.cstate_pstate.pstate_change_ns,
557 refclk_mhz, 0x1fffff);
558 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
559 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
560 "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n"
561 "HW register value = 0x%x\n",
562 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
563
564 /* clock state C */
565 prog_wm_value = convert_and_clamp(
566 watermarks->c.urgent_ns, refclk_mhz, 0x1fffff);
567 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
568 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
569 "URGENCY_WATERMARK_C calculated =%d\n"
570 "HW register value = 0x%x\n",
571 watermarks->c.urgent_ns, prog_wm_value);
572
573
574 prog_wm_value = convert_and_clamp(
575 watermarks->c.pte_meta_urgent_ns,
576 refclk_mhz, 0x1fffff);
577 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
578 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
579 "PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
580 "HW register value = 0x%x\n",
581 watermarks->c.pte_meta_urgent_ns, prog_wm_value);
582
583
584 prog_wm_value = convert_and_clamp(
585 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
586 refclk_mhz, 0x1fffff);
587 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
588 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
589 "SR_ENTER_WATERMARK_C calculated =%d\n"
590 "HW register value = 0x%x\n",
591 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
592
593
594 prog_wm_value = convert_and_clamp(
595 watermarks->c.cstate_pstate.cstate_exit_ns,
596 refclk_mhz, 0x1fffff);
597 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
598 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
599 "SR_EXIT_WATERMARK_C calculated =%d\n"
600 "HW register value = 0x%x\n",
601 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
602
603
604 prog_wm_value = convert_and_clamp(
605 watermarks->c.cstate_pstate.pstate_change_ns,
606 refclk_mhz, 0x1fffff);
607 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
608 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
609 "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n"
610 "HW register value = 0x%x\n",
611 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
612
613 /* clock state D */
614 prog_wm_value = convert_and_clamp(
615 watermarks->d.urgent_ns, refclk_mhz, 0x1fffff);
616 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
617 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
618 "URGENCY_WATERMARK_D calculated =%d\n"
619 "HW register value = 0x%x\n",
620 watermarks->d.urgent_ns, prog_wm_value);
621
622 prog_wm_value = convert_and_clamp(
623 watermarks->d.pte_meta_urgent_ns,
624 refclk_mhz, 0x1fffff);
625 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
626 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
627 "PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
628 "HW register value = 0x%x\n",
629 watermarks->d.pte_meta_urgent_ns, prog_wm_value);
630
631
632 prog_wm_value = convert_and_clamp(
633 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
634 refclk_mhz, 0x1fffff);
635 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
636 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
637 "SR_ENTER_WATERMARK_D calculated =%d\n"
638 "HW register value = 0x%x\n",
639 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
640
641
642 prog_wm_value = convert_and_clamp(
643 watermarks->d.cstate_pstate.cstate_exit_ns,
644 refclk_mhz, 0x1fffff);
645 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
646 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
647 "SR_EXIT_WATERMARK_D calculated =%d\n"
648 "HW register value = 0x%x\n",
649 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
650
651
652 prog_wm_value = convert_and_clamp(
653 watermarks->d.cstate_pstate.pstate_change_ns,
654 refclk_mhz, 0x1fffff);
655 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
656 dm_logger_write(hws->ctx->logger, LOG_HW_MARKS,
657 "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
658 "HW register value = 0x%x\n\n",
659 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
660
661 REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
662 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
cbb4d72e 663
08b16886
ZF
664 REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL,
665 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
666 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
667 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68);
668
669 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
670 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
671 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en);
672
673#if 0
674 REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
675 DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1,
676 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
677#endif
678}
679
680
681static void dcn10_update_dchub(
682 struct dce_hwseq *hws,
683 struct dchub_init_data *dh_data)
684{
685 /* TODO: port code from dal2 */
686 switch (dh_data->fb_mode) {
687 case FRAME_BUFFER_MODE_ZFB_ONLY:
688 /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/
689 REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP,
690 SDPIF_FB_TOP, 0);
691
692 REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE,
693 SDPIF_FB_BASE, 0x0FFFF);
694
695 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
696 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
697
698 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
699 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
700
701 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
702 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
703 dh_data->zfb_size_in_byte - 1) >> 22);
704 break;
705 case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL:
706 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
707
708 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
709 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
710
711 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
712 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
713
714 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
715 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
716 dh_data->zfb_size_in_byte - 1) >> 22);
717 break;
718 case FRAME_BUFFER_MODE_LOCAL_ONLY:
719 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
720 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
721 SDPIF_AGP_BASE, 0);
722
723 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
724 SDPIF_AGP_BOT, 0X03FFFF);
725
726 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
727 SDPIF_AGP_TOP, 0);
728 break;
729 default:
730 break;
731 }
732
733 dh_data->dchub_initialzied = true;
734 dh_data->dchub_info_valid = false;
735}
736
70ccab60 737static void hubp_pg_control(
184debdb 738 struct dce_hwseq *hws,
70ccab60
HW
739 unsigned int hubp_inst,
740 bool power_on)
741{
70ccab60
HW
742 uint32_t power_gate = power_on ? 0 : 1;
743 uint32_t pwr_status = power_on ? 0 : 2;
744
184debdb 745 if (hws->ctx->dc->debug.disable_hubp_power_gate)
70ccab60
HW
746 return;
747
748 switch (hubp_inst) {
749 case 0: /* DCHUBP0 */
184debdb 750 REG_UPDATE(DOMAIN0_PG_CONFIG,
70ccab60
HW
751 DOMAIN0_POWER_GATE, power_gate);
752
184debdb 753 REG_WAIT(DOMAIN0_PG_STATUS,
8a5d8245
TC
754 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
755 1, 1000);
70ccab60
HW
756 break;
757 case 1: /* DCHUBP1 */
184debdb 758 REG_UPDATE(DOMAIN2_PG_CONFIG,
70ccab60
HW
759 DOMAIN2_POWER_GATE, power_gate);
760
184debdb 761 REG_WAIT(DOMAIN2_PG_STATUS,
8a5d8245
TC
762 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
763 1, 1000);
70ccab60
HW
764 break;
765 case 2: /* DCHUBP2 */
184debdb 766 REG_UPDATE(DOMAIN4_PG_CONFIG,
70ccab60
HW
767 DOMAIN4_POWER_GATE, power_gate);
768
184debdb 769 REG_WAIT(DOMAIN4_PG_STATUS,
8a5d8245
TC
770 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
771 1, 1000);
70ccab60
HW
772 break;
773 case 3: /* DCHUBP3 */
184debdb 774 REG_UPDATE(DOMAIN6_PG_CONFIG,
70ccab60
HW
775 DOMAIN6_POWER_GATE, power_gate);
776
184debdb 777 REG_WAIT(DOMAIN6_PG_STATUS,
8a5d8245
TC
778 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
779 1, 1000);
70ccab60
HW
780 break;
781 default:
782 BREAK_TO_DEBUGGER();
783 break;
784 }
785}
786
787static void power_on_plane(
184debdb 788 struct dce_hwseq *hws,
cfe4645e 789 int plane_id)
70ccab60 790{
5df921d4
KC
791 if (REG(DC_IP_REQUEST_CNTL)) {
792 REG_SET(DC_IP_REQUEST_CNTL, 0,
793 IP_REQUEST_EN, 1);
794 dpp_pg_control(hws, plane_id, true);
795 hubp_pg_control(hws, plane_id, true);
796 REG_SET(DC_IP_REQUEST_CNTL, 0,
797 IP_REQUEST_EN, 0);
798 dm_logger_write(hws->ctx->logger, LOG_DEBUG,
799 "Un-gated front end for pipe %d\n", plane_id);
800 }
70ccab60
HW
801}
802
41f97c07
HW
803static void undo_DEGVIDCN10_253_wa(struct dc *dc)
804{
805 struct dce_hwseq *hws = dc->hwseq;
8feabd03 806 struct hubp *hubp = dc->res_pool->hubps[0];
c9bb686b
EY
807 int pwr_status = 0;
808
809 REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status);
810 /* Don't need to blank if hubp is power gated*/
811 if (pwr_status == 2)
812 return;
41f97c07 813
8feabd03 814 hubp->funcs->set_blank(hubp, true);
41f97c07
HW
815
816 REG_SET(DC_IP_REQUEST_CNTL, 0,
817 IP_REQUEST_EN, 1);
818
819 hubp_pg_control(hws, 0, false);
820 REG_SET(DC_IP_REQUEST_CNTL, 0,
821 IP_REQUEST_EN, 0);
822}
823
41f97c07
HW
824static void apply_DEGVIDCN10_253_wa(struct dc *dc)
825{
826 struct dce_hwseq *hws = dc->hwseq;
8feabd03 827 struct hubp *hubp = dc->res_pool->hubps[0];
41f97c07 828
6bf52028
HW
829 if (dc->debug.disable_stutter)
830 return;
831
41f97c07
HW
832 REG_SET(DC_IP_REQUEST_CNTL, 0,
833 IP_REQUEST_EN, 1);
834
835 hubp_pg_control(hws, 0, true);
836 REG_SET(DC_IP_REQUEST_CNTL, 0,
837 IP_REQUEST_EN, 0);
838
8feabd03 839 hubp->funcs->set_hubp_blank_en(hubp, false);
41f97c07
HW
840}
841
fb3466a4 842static void bios_golden_init(struct dc *dc)
70ccab60
HW
843{
844 struct dc_bios *bp = dc->ctx->dc_bios;
845 int i;
846
847 /* initialize dcn global */
848 bp->funcs->enable_disp_power_gating(bp,
849 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
850
851 for (i = 0; i < dc->res_pool->pipe_count; i++) {
852 /* initialize dcn per pipe */
853 bp->funcs->enable_disp_power_gating(bp,
854 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
855 }
856}
857
fb3466a4 858static void dcn10_init_hw(struct dc *dc)
70ccab60
HW
859{
860 int i;
b02c3b05 861 struct abm *abm = dc->res_pool->abm;
184debdb 862 struct dce_hwseq *hws = dc->hwseq;
70ccab60 863
70ccab60 864 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
b02c3b05
DL
865 REG_WRITE(REFCLK_CNTL, 0);
866 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
184debdb
DL
867 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
868
fb3466a4 869 if (!dc->debug.disable_clock_gate) {
184debdb
DL
870 /* enable all DCN clock gating */
871 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
872
873 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
70ccab60 874
184debdb
DL
875 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
876 }
877
878 enable_power_gating_plane(dc->hwseq, true);
70ccab60
HW
879 return;
880 }
881 /* end of FPGA. Below if real ASIC */
882
883 bios_golden_init(dc);
884
0a87425a
TC
885 disable_vga(dc->hwseq);
886
70ccab60
HW
887 for (i = 0; i < dc->link_count; i++) {
888 /* Power up AND update implementation according to the
889 * required signal (which may be different from the
890 * default signal on connector).
891 */
d0778ebf 892 struct dc_link *link = dc->links[i];
70ccab60
HW
893
894 link->link_enc->funcs->hw_init(link->link_enc);
895 }
896
897 for (i = 0; i < dc->res_pool->pipe_count; i++) {
b02c3b05
DL
898 struct transform *xfm = dc->res_pool->transforms[i];
899 struct timing_generator *tg = dc->res_pool->timing_generators[i];
f0558542 900
b02c3b05 901 xfm->funcs->transform_reset(xfm);
cc408d72 902 dc->res_pool->mpc->funcs->remove(
7f4a7253
EB
903 dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree),
904 dc->res_pool->opps[i]->inst, i);
70ccab60 905
70ccab60
HW
906 /* Blank controller using driver code instead of
907 * command table.
908 */
909 tg->funcs->set_blank(tg, true);
910 hwss_wait_for_blank_complete(tg);
911 }
912
913 for (i = 0; i < dc->res_pool->audio_count; i++) {
914 struct audio *audio = dc->res_pool->audios[i];
915
916 audio->funcs->hw_init(audio);
917 }
918
70ccab60
HW
919 if (abm != NULL) {
920 abm->funcs->init_backlight(abm);
921 abm->funcs->abm_init(abm);
922 }
923
924 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
184debdb 925 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
70ccab60 926
fb3466a4 927 if (!dc->debug.disable_clock_gate) {
5970f2ae 928 /* enable all DCN clock gating */
184debdb 929 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
5970f2ae 930
184debdb 931 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
5970f2ae 932
184debdb
DL
933 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
934 }
5970f2ae 935
184debdb 936 enable_power_gating_plane(dc->hwseq, true);
70ccab60
HW
937}
938
939static enum dc_status dcn10_prog_pixclk_crtc_otg(
940 struct pipe_ctx *pipe_ctx,
608ac7bb 941 struct dc_state *context,
fb3466a4 942 struct dc *dc)
70ccab60 943{
0971c40e 944 struct dc_stream_state *stream = pipe_ctx->stream;
70ccab60
HW
945 enum dc_color_space color_space;
946 struct tg_color black_color = {0};
4fa086b9 947 bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ?
70ccab60 948 false:true;
4fa086b9 949 bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY;
70ccab60
HW
950
951
952 /* by upper caller loop, pipe0 is parent pipe and be called first.
953 * back end is set up by for pipe0. Other children pipe share back end
954 * with pipe 0. No program is needed.
955 */
956 if (pipe_ctx->top_pipe != NULL)
957 return DC_OK;
958
959 /* TODO check if timing_changed, disable stream if timing changed */
960
961 /* HW program guide assume display already disable
962 * by unplug sequence. OTG assume stop.
963 */
6b670fa9 964 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
70ccab60
HW
965
966 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
967 pipe_ctx->clock_source,
10688217 968 &pipe_ctx->stream_res.pix_clk_params,
70ccab60
HW
969 &pipe_ctx->pll_settings)) {
970 BREAK_TO_DEBUGGER();
971 return DC_ERROR_UNEXPECTED;
972 }
6b670fa9
HW
973 pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
974 pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
975 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
976 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
70ccab60 977
6b670fa9 978 pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
70ccab60 979
6b670fa9
HW
980 pipe_ctx->stream_res.tg->funcs->program_timing(
981 pipe_ctx->stream_res.tg,
4fa086b9 982 &stream->timing,
70ccab60
HW
983 true);
984
a6a6cb34
HW
985 pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity(
986 pipe_ctx->stream_res.opp,
70ccab60
HW
987 enableStereo,
988 rightEyePolarity);
989
990#if 0 /* move to after enable_crtc */
991 /* TODO: OPP FMT, ABM. etc. should be done here. */
992 /* or FPGA now. instance 0 only. TODO: move to opp.c */
993
6b670fa9 994 inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt;
70ccab60 995
a6a6cb34
HW
996 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
997 pipe_ctx->stream_res.opp,
70ccab60
HW
998 &stream->bit_depth_params,
999 &stream->clamping);
1000#endif
1001 /* program otg blank color */
4fa086b9 1002 color_space = stream->output_color_space;
70ccab60 1003 color_space_to_black_color(dc, color_space, &black_color);
6b670fa9
HW
1004 pipe_ctx->stream_res.tg->funcs->set_blank_color(
1005 pipe_ctx->stream_res.tg,
70ccab60
HW
1006 &black_color);
1007
6b670fa9
HW
1008 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
1009 hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
70ccab60
HW
1010
1011 /* VTG is within DCHUB command block. DCFCLK is always on */
6b670fa9 1012 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
70ccab60
HW
1013 BREAK_TO_DEBUGGER();
1014 return DC_ERROR_UNEXPECTED;
1015 }
1016
1017 /* TODO program crtc source select for non-virtual signal*/
1018 /* TODO program FMT */
1019 /* TODO setup link_enc */
1020 /* TODO set stream attributes */
1021 /* TODO program audio */
1022 /* TODO enable stream if timing changed */
1023 /* TODO unblank stream if DP */
1024
1025 return DC_OK;
1026}
1027
1028static void reset_back_end_for_pipe(
fb3466a4 1029 struct dc *dc,
70ccab60 1030 struct pipe_ctx *pipe_ctx,
608ac7bb 1031 struct dc_state *context)
70ccab60
HW
1032{
1033 int i;
70ccab60 1034
8e9c4c8c 1035 if (pipe_ctx->stream_res.stream_enc == NULL) {
70ccab60
HW
1036 pipe_ctx->stream = NULL;
1037 return;
1038 }
1039
d050f8ed
HW
1040 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1041 /* DPMS may already disable */
1042 if (!pipe_ctx->stream->dpms_off)
1043 core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
1044 }
70ccab60
HW
1045
1046 /* by upper caller loop, parent pipe: pipe0, will be reset last.
1047 * back end share by all pipes and will be disable only when disable
1048 * parent pipe.
1049 */
1050 if (pipe_ctx->top_pipe == NULL) {
6b670fa9 1051 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
70ccab60 1052
6b670fa9 1053 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
70ccab60
HW
1054 }
1055
70ccab60 1056 for (i = 0; i < dc->res_pool->pipe_count; i++)
608ac7bb 1057 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
70ccab60
HW
1058 break;
1059
1060 if (i == dc->res_pool->pipe_count)
1061 return;
1062
1063 pipe_ctx->stream = NULL;
39902db0 1064 dm_logger_write(dc->ctx->logger, LOG_DEBUG,
cfe4645e 1065 "Reset back end for pipe %d, tg:%d\n",
6b670fa9 1066 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
70ccab60
HW
1067}
1068
a74b2734 1069/* trigger HW to start disconnect plane from stream on the next vsync */
fb3466a4 1070static void plane_atomic_disconnect(struct dc *dc,
cfe4645e 1071 int fe_idx)
70ccab60 1072{
8feabd03 1073 struct hubp *hubp = dc->res_pool->hubps[fe_idx];
cc408d72
DL
1074 struct mpc *mpc = dc->res_pool->mpc;
1075 int opp_id, z_idx;
1076 int mpcc_id = -1;
1077
1078 /* look at tree rather than mi here to know if we already reset */
1079 for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) {
1080 struct output_pixel_processor *opp = dc->res_pool->opps[opp_id];
a74b2734 1081
cc408d72
DL
1082 for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) {
1083 if (opp->mpc_tree.dpp[z_idx] == fe_idx) {
1084 mpcc_id = opp->mpc_tree.mpcc[z_idx];
1085 break;
1086 }
1087 }
1088 if (mpcc_id != -1)
1089 break;
1090 }
a74b2734 1091 /*Already reset*/
cc408d72 1092 if (opp_id == dc->res_pool->pipe_count)
a74b2734 1093 return;
70ccab60 1094
fb3466a4 1095 if (dc->debug.sanity_checks)
6be425f3 1096 verify_allow_pstate_change_high(dc->hwseq);
8feabd03 1097 hubp->funcs->dcc_control(hubp, false, false);
fb3466a4 1098 if (dc->debug.sanity_checks)
6be425f3
EY
1099 verify_allow_pstate_change_high(dc->hwseq);
1100
7f4a7253
EB
1101 mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree),
1102 dc->res_pool->opps[opp_id]->inst, fe_idx);
d65359d5
TC
1103}
1104
a74b2734
TC
1105/* disable HW used by plane.
1106 * note: cannot disable until disconnect is complete */
fb3466a4 1107static void plane_atomic_disable(struct dc *dc,
d65359d5
TC
1108 int fe_idx)
1109{
1110 struct dce_hwseq *hws = dc->hwseq;
8feabd03 1111 struct hubp *hubp = dc->res_pool->hubps[fe_idx];
cc408d72 1112 struct mpc *mpc = dc->res_pool->mpc;
8feabd03 1113 int opp_id = hubp->opp_id;
d65359d5 1114
e75504b1 1115 if (opp_id == 0xf)
d65359d5
TC
1116 return;
1117
8feabd03
YHL
1118 mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id);
1119 dc->res_pool->opps[hubp->opp_id]->mpcc_disconnect_pending[hubp->mpcc_id] = false;
6be425f3
EY
1120 /*dm_logger_write(dc->ctx->logger, LOG_ERROR,
1121 "[debug_mpo: atomic disable finished on mpcc %d]\n",
1122 fe_idx);*/
189f73e3 1123
8feabd03 1124 hubp->funcs->set_blank(hubp, true);
d65359d5 1125
fb3466a4 1126 if (dc->debug.sanity_checks)
2b13d7d3
TC
1127 verify_allow_pstate_change_high(dc->hwseq);
1128
d21becbe
TC
1129 REG_UPDATE(HUBP_CLK_CNTL[fe_idx],
1130 HUBP_CLOCK_ENABLE, 0);
1131 REG_UPDATE(DPP_CONTROL[fe_idx],
1132 DPP_CLOCK_ENABLE, 0);
71a2f23e 1133
e75504b1
DL
1134 if (dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0)
1135 REG_UPDATE(OPP_PIPE_CONTROL[opp_id],
71a2f23e 1136 OPP_PIPE_CLOCK_EN, 0);
70ccab60 1137
fb3466a4 1138 if (dc->debug.sanity_checks)
2b13d7d3 1139 verify_allow_pstate_change_high(dc->hwseq);
cfe4645e 1140}
70ccab60 1141
6be425f3
EY
1142/*
1143 * kill power to plane hw
a74b2734 1144 * note: cannot power down until plane is disable
6be425f3 1145 */
fb3466a4 1146static void plane_atomic_power_down(struct dc *dc, int fe_idx)
a74b2734 1147{
6be425f3 1148 struct dce_hwseq *hws = dc->hwseq;
cc408d72 1149 struct transform *xfm = dc->res_pool->transforms[fe_idx];
6be425f3 1150
5df921d4
KC
1151 if (REG(DC_IP_REQUEST_CNTL)) {
1152 REG_SET(DC_IP_REQUEST_CNTL, 0,
1153 IP_REQUEST_EN, 1);
1154 dpp_pg_control(hws, fe_idx, false);
1155 hubp_pg_control(hws, fe_idx, false);
1156 xfm->funcs->transform_reset(xfm);
1157 REG_SET(DC_IP_REQUEST_CNTL, 0,
1158 IP_REQUEST_EN, 0);
1159 dm_logger_write(dc->ctx->logger, LOG_DEBUG,
1160 "Power gated front end %d\n", fe_idx);
a74b2734 1161
5df921d4
KC
1162 if (dc->debug.sanity_checks)
1163 verify_allow_pstate_change_high(dc->hwseq);
1164 }
a74b2734 1165}
6be425f3 1166
a74b2734
TC
1167
1168static void reset_front_end(
fb3466a4 1169 struct dc *dc,
a74b2734
TC
1170 int fe_idx)
1171{
1172 struct dce_hwseq *hws = dc->hwseq;
cc408d72 1173 struct timing_generator *tg;
8feabd03 1174 int opp_id = dc->res_pool->hubps[fe_idx]->opp_id;
a74b2734
TC
1175
1176 /*Already reset*/
1177 if (opp_id == 0xf)
1178 return;
1179
cc408d72 1180 tg = dc->res_pool->timing_generators[opp_id];
a74b2734
TC
1181 tg->funcs->lock(tg);
1182
1183 plane_atomic_disconnect(dc, fe_idx);
1184
1185 REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1);
1186 tg->funcs->unlock(tg);
1187
fb3466a4 1188 if (dc->debug.sanity_checks)
cc408d72 1189 verify_allow_pstate_change_high(hws);
a74b2734
TC
1190
1191 if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
1192 REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst],
8a5d8245
TC
1193 VUPDATE_NO_LOCK_EVENT_OCCURRED, 1,
1194 1, 100000);
a74b2734
TC
1195
1196 plane_atomic_disable(dc, fe_idx);
1197
1198 dm_logger_write(dc->ctx->logger, LOG_DC,
1199 "Reset front end %d\n",
1200 fe_idx);
1201}
1202
fb3466a4 1203static void dcn10_power_down_fe(struct dc *dc, int fe_idx)
cfe4645e 1204{
184debdb 1205 struct dce_hwseq *hws = dc->hwseq;
cc408d72 1206 struct transform *xfm = dc->res_pool->transforms[fe_idx];
70ccab60 1207
cfe4645e 1208 reset_front_end(dc, fe_idx);
70ccab60 1209
184debdb 1210 REG_SET(DC_IP_REQUEST_CNTL, 0,
cfe4645e 1211 IP_REQUEST_EN, 1);
184debdb
DL
1212 dpp_pg_control(hws, fe_idx, false);
1213 hubp_pg_control(hws, fe_idx, false);
cc408d72 1214 xfm->funcs->transform_reset(xfm);
184debdb 1215 REG_SET(DC_IP_REQUEST_CNTL, 0,
cfe4645e 1216 IP_REQUEST_EN, 0);
39902db0 1217 dm_logger_write(dc->ctx->logger, LOG_DEBUG,
cfe4645e 1218 "Power gated front end %d\n", fe_idx);
2b13d7d3 1219
fb3466a4 1220 if (dc->debug.sanity_checks)
2b13d7d3 1221 verify_allow_pstate_change_high(dc->hwseq);
70ccab60
HW
1222}
1223
cfe4645e 1224static void reset_hw_ctx_wrap(
fb3466a4 1225 struct dc *dc,
608ac7bb 1226 struct dc_state *context)
70ccab60
HW
1227{
1228 int i;
1229
cfe4645e 1230 /* Reset Front End*/
6be425f3
EY
1231 /* Lock*/
1232 for (i = 0; i < dc->res_pool->pipe_count; i++) {
608ac7bb 1233 struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
6b670fa9 1234 struct timing_generator *tg = cur_pipe_ctx->stream_res.tg;
6be425f3
EY
1235
1236 if (cur_pipe_ctx->stream)
1237 tg->funcs->lock(tg);
1238 }
1239 /* Disconnect*/
1240 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1241 struct pipe_ctx *pipe_ctx_old =
608ac7bb 1242 &dc->current_state->res_ctx.pipe_ctx[i];
6be425f3
EY
1243 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1244
1245 if (!pipe_ctx->stream ||
3be5262e 1246 !pipe_ctx->plane_state ||
6be425f3
EY
1247 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1248
1249 plane_atomic_disconnect(dc, i);
1250 }
1251 }
1252 /* Unlock*/
1253 for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
608ac7bb 1254 struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
6b670fa9 1255 struct timing_generator *tg = cur_pipe_ctx->stream_res.tg;
6be425f3
EY
1256
1257 if (cur_pipe_ctx->stream)
1258 tg->funcs->unlock(tg);
1259 }
1260
1261 /* Disable and Powerdown*/
cfe4645e
DL
1262 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1263 struct pipe_ctx *pipe_ctx_old =
608ac7bb 1264 &dc->current_state->res_ctx.pipe_ctx[i];
cfe4645e
DL
1265 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1266
1267 /*if (!pipe_ctx_old->stream)
1268 continue;*/
1269
3be5262e 1270 if (pipe_ctx->stream && pipe_ctx->plane_state
6be425f3
EY
1271 && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
1272 continue;
1273
1274 plane_atomic_disable(dc, i);
1275
3be5262e 1276 if (!pipe_ctx->stream || !pipe_ctx->plane_state)
6be425f3 1277 plane_atomic_power_down(dc, i);
cfe4645e 1278 }
6be425f3 1279
cfe4645e 1280 /* Reset Back End*/
70ccab60
HW
1281 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1282 struct pipe_ctx *pipe_ctx_old =
608ac7bb 1283 &dc->current_state->res_ctx.pipe_ctx[i];
70ccab60
HW
1284 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1285
1286 if (!pipe_ctx_old->stream)
1287 continue;
1288
56e6ed45
YS
1289 if (pipe_ctx_old->top_pipe)
1290 continue;
1291
70ccab60 1292 if (!pipe_ctx->stream ||
21e67d4d
HW
1293 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1294 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1295
608ac7bb 1296 reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
21e67d4d
HW
1297
1298 if (old_clk)
1299 old_clk->funcs->cs_power_down(old_clk);
1300 }
70ccab60 1301 }
21e67d4d 1302
70ccab60
HW
1303}
1304
cfe4645e
DL
1305static bool patch_address_for_sbs_tb_stereo(
1306 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
70ccab60 1307{
3be5262e 1308 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
70ccab60 1309 bool sec_split = pipe_ctx->top_pipe &&
3be5262e
HW
1310 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1311 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
4fa086b9 1312 (pipe_ctx->stream->timing.timing_3d_format ==
70ccab60 1313 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
4fa086b9 1314 pipe_ctx->stream->timing.timing_3d_format ==
70ccab60 1315 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
3be5262e
HW
1316 *addr = plane_state->address.grph_stereo.left_addr;
1317 plane_state->address.grph_stereo.left_addr =
1318 plane_state->address.grph_stereo.right_addr;
70ccab60 1319 return true;
cdc5e048 1320 } else {
4fa086b9 1321 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
3be5262e
HW
1322 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1323 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1324 plane_state->address.grph_stereo.right_addr =
1325 plane_state->address.grph_stereo.left_addr;
cdc5e048 1326 }
70ccab60
HW
1327 }
1328 return false;
1329}
1330
9d6f264b
YS
1331static void toggle_watermark_change_req(struct dce_hwseq *hws)
1332{
1333 uint32_t watermark_change_req;
1334
1335 REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
1336 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req);
1337
1338 if (watermark_change_req)
1339 watermark_change_req = 0;
1340 else
1341 watermark_change_req = 1;
1342
1343 REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
1344 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req);
1345}
1346
fb3466a4 1347static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
70ccab60
HW
1348{
1349 bool addr_patched = false;
1350 PHYSICAL_ADDRESS_LOC addr;
3be5262e 1351 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
70ccab60 1352
3be5262e 1353 if (plane_state == NULL)
70ccab60
HW
1354 return;
1355 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
8feabd03
YHL
1356 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1357 pipe_ctx->plane_res.hubp,
3be5262e
HW
1358 &plane_state->address,
1359 plane_state->flip_immediate);
1360 plane_state->status.requested_address = plane_state->address;
70ccab60 1361 if (addr_patched)
3be5262e 1362 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
70ccab60
HW
1363}
1364
1365static bool dcn10_set_input_transfer_func(
3be5262e 1366 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
70ccab60 1367{
b3c340fa 1368 struct transform *xfm_base = pipe_ctx->plane_res.xfm;
7b0c470f 1369 const struct dc_transfer_func *tf = NULL;
70ccab60
HW
1370 bool result = true;
1371
b3c340fa 1372 if (xfm_base == NULL)
70ccab60
HW
1373 return false;
1374
3be5262e
HW
1375 if (plane_state->in_transfer_func)
1376 tf = plane_state->in_transfer_func;
70ccab60 1377
3be5262e 1378 if (plane_state->gamma_correction && dce_use_lut(plane_state))
b3c340fa 1379 xfm_base->funcs->ipp_program_input_lut(xfm_base,
3be5262e 1380 plane_state->gamma_correction);
5aff86c1 1381
70ccab60 1382 if (tf == NULL)
b3c340fa 1383 xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS);
7b0c470f
LSL
1384 else if (tf->type == TF_TYPE_PREDEFINED) {
1385 switch (tf->tf) {
70ccab60 1386 case TRANSFER_FUNCTION_SRGB:
b3c340fa 1387 xfm_base->funcs->ipp_set_degamma(xfm_base,
70ccab60
HW
1388 IPP_DEGAMMA_MODE_HW_sRGB);
1389 break;
1390 case TRANSFER_FUNCTION_BT709:
b3c340fa 1391 xfm_base->funcs->ipp_set_degamma(xfm_base,
70ccab60
HW
1392 IPP_DEGAMMA_MODE_HW_xvYCC);
1393 break;
1394 case TRANSFER_FUNCTION_LINEAR:
b3c340fa 1395 xfm_base->funcs->ipp_set_degamma(xfm_base,
70ccab60
HW
1396 IPP_DEGAMMA_MODE_BYPASS);
1397 break;
1398 case TRANSFER_FUNCTION_PQ:
1399 result = false;
1400 break;
1401 default:
1402 result = false;
1403 break;
1404 }
7b0c470f 1405 } else if (tf->type == TF_TYPE_BYPASS) {
b3c340fa 1406 xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS);
70ccab60
HW
1407 } else {
1408 /*TF_TYPE_DISTRIBUTED_POINTS*/
1409 result = false;
1410 }
1411
1412 return result;
1413}
1414/*modify the method to handle rgb for arr_points*/
1415static bool convert_to_custom_float(
1416 struct pwl_result_data *rgb_resulted,
1417 struct curve_points *arr_points,
1418 uint32_t hw_points_num)
1419{
1420 struct custom_float_format fmt;
1421
1422 struct pwl_result_data *rgb = rgb_resulted;
1423
1424 uint32_t i = 0;
1425
1426 fmt.exponenta_bits = 6;
1427 fmt.mantissa_bits = 12;
1428 fmt.sign = false;
1429
1430 if (!convert_to_custom_float_format(
1431 arr_points[0].x,
1432 &fmt,
1433 &arr_points[0].custom_float_x)) {
1434 BREAK_TO_DEBUGGER();
1435 return false;
1436 }
1437
1438 if (!convert_to_custom_float_format(
1439 arr_points[0].offset,
1440 &fmt,
1441 &arr_points[0].custom_float_offset)) {
1442 BREAK_TO_DEBUGGER();
1443 return false;
1444 }
1445
1446 if (!convert_to_custom_float_format(
1447 arr_points[0].slope,
1448 &fmt,
1449 &arr_points[0].custom_float_slope)) {
1450 BREAK_TO_DEBUGGER();
1451 return false;
1452 }
1453
1454 fmt.mantissa_bits = 10;
1455 fmt.sign = false;
1456
1457 if (!convert_to_custom_float_format(
1458 arr_points[1].x,
1459 &fmt,
1460 &arr_points[1].custom_float_x)) {
1461 BREAK_TO_DEBUGGER();
1462 return false;
1463 }
1464
1465 if (!convert_to_custom_float_format(
1466 arr_points[1].y,
1467 &fmt,
1468 &arr_points[1].custom_float_y)) {
1469 BREAK_TO_DEBUGGER();
1470 return false;
1471 }
1472
1473 if (!convert_to_custom_float_format(
1474 arr_points[1].slope,
1475 &fmt,
1476 &arr_points[1].custom_float_slope)) {
1477 BREAK_TO_DEBUGGER();
1478 return false;
1479 }
1480
1481 fmt.mantissa_bits = 12;
1482 fmt.sign = true;
1483
1484 while (i != hw_points_num) {
1485 if (!convert_to_custom_float_format(
1486 rgb->red,
1487 &fmt,
1488 &rgb->red_reg)) {
1489 BREAK_TO_DEBUGGER();
1490 return false;
1491 }
1492
1493 if (!convert_to_custom_float_format(
1494 rgb->green,
1495 &fmt,
1496 &rgb->green_reg)) {
1497 BREAK_TO_DEBUGGER();
1498 return false;
1499 }
1500
1501 if (!convert_to_custom_float_format(
1502 rgb->blue,
1503 &fmt,
1504 &rgb->blue_reg)) {
1505 BREAK_TO_DEBUGGER();
1506 return false;
1507 }
1508
1509 if (!convert_to_custom_float_format(
1510 rgb->delta_red,
1511 &fmt,
1512 &rgb->delta_red_reg)) {
1513 BREAK_TO_DEBUGGER();
1514 return false;
1515 }
1516
1517 if (!convert_to_custom_float_format(
1518 rgb->delta_green,
1519 &fmt,
1520 &rgb->delta_green_reg)) {
1521 BREAK_TO_DEBUGGER();
1522 return false;
1523 }
1524
1525 if (!convert_to_custom_float_format(
1526 rgb->delta_blue,
1527 &fmt,
1528 &rgb->delta_blue_reg)) {
1529 BREAK_TO_DEBUGGER();
1530 return false;
1531 }
1532
1533 ++rgb;
1534 ++i;
1535 }
1536
1537 return true;
1538}
1539#define MAX_REGIONS_NUMBER 34
1540#define MAX_LOW_POINT 25
1541#define NUMBER_SEGMENTS 32
1542
1543static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func
1544 *output_tf, struct pwl_params *regamma_params)
1545{
1546 struct curve_points *arr_points;
1547 struct pwl_result_data *rgb_resulted;
1548 struct pwl_result_data *rgb;
1549 struct pwl_result_data *rgb_plus_1;
1550 struct fixed31_32 y_r;
1551 struct fixed31_32 y_g;
1552 struct fixed31_32 y_b;
1553 struct fixed31_32 y1_min;
1554 struct fixed31_32 y3_max;
1555
1556 int32_t segment_start, segment_end;
1557 int32_t i;
1558 uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
1559
1560 if (output_tf == NULL || regamma_params == NULL ||
1561 output_tf->type == TF_TYPE_BYPASS)
1562 return false;
1563
1564 arr_points = regamma_params->arr_points;
1565 rgb_resulted = regamma_params->rgb_resulted;
1566 hw_points = 0;
1567
1568 memset(regamma_params, 0, sizeof(struct pwl_params));
1569 memset(seg_distr, 0, sizeof(seg_distr));
1570
1571 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
1572 /* 32 segments
1573 * segments are from 2^-25 to 2^7
1574 */
1575 for (i = 0; i < 32 ; i++)
1576 seg_distr[i] = 3;
1577
1578 segment_start = -25;
1579 segment_end = 7;
1580 } else {
1581 /* 10 segments
1582 * segment is from 2^-10 to 2^0
1583 * There are less than 256 points, for optimization
1584 */
1585 seg_distr[0] = 3;
1586 seg_distr[1] = 4;
1587 seg_distr[2] = 4;
1588 seg_distr[3] = 4;
1589 seg_distr[4] = 4;
1590 seg_distr[5] = 4;
1591 seg_distr[6] = 4;
1592 seg_distr[7] = 4;
1593 seg_distr[8] = 5;
1594 seg_distr[9] = 5;
1595
1596 segment_start = -10;
1597 segment_end = 0;
1598 }
1599
1600 for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++)
1601 seg_distr[i] = -1;
1602
1603 for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
1604 if (seg_distr[k] != -1)
1605 hw_points += (1 << seg_distr[k]);
1606 }
1607
1608 j = 0;
1609 for (k = 0; k < (segment_end - segment_start); k++) {
1610 increment = NUMBER_SEGMENTS / (1 << seg_distr[k]);
1611 start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS;
1612 for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) {
1613 if (j == hw_points - 1)
1614 break;
1615 rgb_resulted[j].red = output_tf->tf_pts.red[i];
1616 rgb_resulted[j].green = output_tf->tf_pts.green[i];
1617 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
1618 j++;
1619 }
1620 }
1621
1622 /* last point */
1623 start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS;
1624 rgb_resulted[hw_points - 1].red =
1625 output_tf->tf_pts.red[start_index];
1626 rgb_resulted[hw_points - 1].green =
1627 output_tf->tf_pts.green[start_index];
1628 rgb_resulted[hw_points - 1].blue =
1629 output_tf->tf_pts.blue[start_index];
1630
1631 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
1632 dal_fixed31_32_from_int(segment_start));
1633 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
1634 dal_fixed31_32_from_int(segment_end));
1635 arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
1636 dal_fixed31_32_from_int(segment_end));
1637
1638 y_r = rgb_resulted[0].red;
1639 y_g = rgb_resulted[0].green;
1640 y_b = rgb_resulted[0].blue;
1641
1642 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
1643
1644 arr_points[0].y = y1_min;
1645 arr_points[0].slope = dal_fixed31_32_div(
1646 arr_points[0].y,
1647 arr_points[0].x);
1648 y_r = rgb_resulted[hw_points - 1].red;
1649 y_g = rgb_resulted[hw_points - 1].green;
1650 y_b = rgb_resulted[hw_points - 1].blue;
1651
1652 /* see comment above, m_arrPoints[1].y should be the Y value for the
1653 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
1654 */
1655 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
1656
1657 arr_points[1].y = y3_max;
1658 arr_points[2].y = y3_max;
1659
1660 arr_points[1].slope = dal_fixed31_32_zero;
1661 arr_points[2].slope = dal_fixed31_32_zero;
1662
1663 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
1664 /* for PQ, we want to have a straight line from last HW X point,
1665 * and the slope to be such that we hit 1.0 at 10000 nits.
1666 */
1667 const struct fixed31_32 end_value =
1668 dal_fixed31_32_from_int(125);
1669
1670 arr_points[1].slope = dal_fixed31_32_div(
1671 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
1672 dal_fixed31_32_sub(end_value, arr_points[1].x));
1673 arr_points[2].slope = dal_fixed31_32_div(
1674 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
1675 dal_fixed31_32_sub(end_value, arr_points[1].x));
1676 }
1677
1678 regamma_params->hw_points_num = hw_points;
1679
1680 i = 1;
1681 for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) {
1682 if (seg_distr[k] != -1) {
1683 regamma_params->arr_curve_points[k].segments_num =
1684 seg_distr[k];
1685 regamma_params->arr_curve_points[i].offset =
1686 regamma_params->arr_curve_points[k].
1687 offset + (1 << seg_distr[k]);
1688 }
1689 i++;
1690 }
1691
1692 if (seg_distr[k] != -1)
1693 regamma_params->arr_curve_points[k].segments_num =
1694 seg_distr[k];
1695
1696 rgb = rgb_resulted;
1697 rgb_plus_1 = rgb_resulted + 1;
1698
1699 i = 1;
1700
1701 while (i != hw_points + 1) {
1702 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
1703 rgb_plus_1->red = rgb->red;
1704 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
1705 rgb_plus_1->green = rgb->green;
1706 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
1707 rgb_plus_1->blue = rgb->blue;
1708
1709 rgb->delta_red = dal_fixed31_32_sub(
1710 rgb_plus_1->red,
1711 rgb->red);
1712 rgb->delta_green = dal_fixed31_32_sub(
1713 rgb_plus_1->green,
1714 rgb->green);
1715 rgb->delta_blue = dal_fixed31_32_sub(
1716 rgb_plus_1->blue,
1717 rgb->blue);
1718
1719 ++rgb_plus_1;
1720 ++rgb;
1721 ++i;
1722 }
1723
1724 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
1725
1726 return true;
1727}
1728
1729static bool dcn10_set_output_transfer_func(
1730 struct pipe_ctx *pipe_ctx,
0971c40e 1731 const struct dc_stream_state *stream)
70ccab60 1732{
86a66c4e 1733 struct transform *xfm = pipe_ctx->plane_res.xfm;
70ccab60 1734
c8d7bd8b 1735 if (xfm == NULL)
f46661dd
AZ
1736 return false;
1737
c8d7bd8b 1738 xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
70ccab60 1739
4fa086b9
LSL
1740 if (stream->out_transfer_func &&
1741 stream->out_transfer_func->type ==
70ccab60 1742 TF_TYPE_PREDEFINED &&
4fa086b9 1743 stream->out_transfer_func->tf ==
70ccab60 1744 TRANSFER_FUNCTION_SRGB) {
c8d7bd8b 1745 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
70ccab60 1746 } else if (dcn10_translate_regamma_to_hw_format(
4fa086b9 1747 stream->out_transfer_func, &xfm->regamma_params)) {
c8d7bd8b
YHL
1748 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
1749 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
70ccab60 1750 } else {
c8d7bd8b 1751 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
70ccab60
HW
1752 }
1753
1754 return true;
1755}
1756
1757static void dcn10_pipe_control_lock(
fb3466a4 1758 struct dc *dc,
70ccab60
HW
1759 struct pipe_ctx *pipe,
1760 bool lock)
1761{
8feabd03
YHL
1762 struct hubp *hubp = NULL;
1763 hubp = dc->res_pool->hubps[pipe->pipe_idx];
70ccab60
HW
1764 /* use TG master update lock to lock everything on the TG
1765 * therefore only top pipe need to lock
1766 */
1767 if (pipe->top_pipe)
1768 return;
1769
fb3466a4 1770 if (dc->debug.sanity_checks)
2b13d7d3
TC
1771 verify_allow_pstate_change_high(dc->hwseq);
1772
70ccab60 1773 if (lock)
6b670fa9 1774 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
70ccab60 1775 else
6b670fa9 1776 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
2b13d7d3 1777
fb3466a4 1778 if (dc->debug.sanity_checks)
2b13d7d3 1779 verify_allow_pstate_change_high(dc->hwseq);
70ccab60
HW
1780}
1781
1782static bool wait_for_reset_trigger_to_occur(
1783 struct dc_context *dc_ctx,
1784 struct timing_generator *tg)
1785{
1786 bool rc = false;
1787
1788 /* To avoid endless loop we wait at most
1789 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1790 const uint32_t frames_to_wait_on_triggered_reset = 10;
1791 int i;
1792
1793 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1794
1795 if (!tg->funcs->is_counter_moving(tg)) {
1796 DC_ERROR("TG counter is not moving!\n");
1797 break;
1798 }
1799
1800 if (tg->funcs->did_triggered_reset_occur(tg)) {
1801 rc = true;
1802 /* usually occurs at i=1 */
1803 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1804 i);
1805 break;
1806 }
1807
1808 /* Wait for one frame. */
1809 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1810 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1811 }
1812
1813 if (false == rc)
1814 DC_ERROR("GSL: Timeout on reset trigger!\n");
1815
1816 return rc;
1817}
1818
1819static void dcn10_enable_timing_synchronization(
fb3466a4 1820 struct dc *dc,
70ccab60
HW
1821 int group_index,
1822 int group_size,
1823 struct pipe_ctx *grouped_pipes[])
1824{
1825 struct dc_context *dc_ctx = dc->ctx;
1826 int i;
1827
1828 DC_SYNC_INFO("Setting up OTG reset trigger\n");
1829
1830 for (i = 1; i < group_size; i++)
6b670fa9
HW
1831 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
1832 grouped_pipes[i]->stream_res.tg, grouped_pipes[0]->stream_res.tg->inst);
70ccab60
HW
1833
1834
1835 DC_SYNC_INFO("Waiting for trigger\n");
1836
1837 /* Need to get only check 1 pipe for having reset as all the others are
1838 * synchronized. Look at last pipe programmed to reset.
1839 */
6b670fa9 1840 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
70ccab60 1841 for (i = 1; i < group_size; i++)
6b670fa9
HW
1842 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
1843 grouped_pipes[i]->stream_res.tg);
70ccab60
HW
1844
1845 DC_SYNC_INFO("Sync complete\n");
1846}
1847
c9742685 1848static void print_rq_dlg_ttu(
fb3466a4 1849 struct dc *core_dc,
c9742685
DL
1850 struct pipe_ctx *pipe_ctx)
1851{
1852 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1853 "\n============== DML TTU Output parameters [%d] ==============\n"
1854 "qos_level_low_wm: %d, \n"
1855 "qos_level_high_wm: %d, \n"
1856 "min_ttu_vblank: %d, \n"
1857 "qos_level_flip: %d, \n"
1858 "refcyc_per_req_delivery_l: %d, \n"
1859 "qos_level_fixed_l: %d, \n"
1860 "qos_ramp_disable_l: %d, \n"
1861 "refcyc_per_req_delivery_pre_l: %d, \n"
1862 "refcyc_per_req_delivery_c: %d, \n"
1863 "qos_level_fixed_c: %d, \n"
1864 "qos_ramp_disable_c: %d, \n"
1865 "refcyc_per_req_delivery_pre_c: %d\n"
1866 "=============================================================\n",
1867 pipe_ctx->pipe_idx,
1868 pipe_ctx->ttu_regs.qos_level_low_wm,
1869 pipe_ctx->ttu_regs.qos_level_high_wm,
1870 pipe_ctx->ttu_regs.min_ttu_vblank,
1871 pipe_ctx->ttu_regs.qos_level_flip,
1872 pipe_ctx->ttu_regs.refcyc_per_req_delivery_l,
1873 pipe_ctx->ttu_regs.qos_level_fixed_l,
1874 pipe_ctx->ttu_regs.qos_ramp_disable_l,
1875 pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l,
1876 pipe_ctx->ttu_regs.refcyc_per_req_delivery_c,
1877 pipe_ctx->ttu_regs.qos_level_fixed_c,
1878 pipe_ctx->ttu_regs.qos_ramp_disable_c,
1879 pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c
1880 );
1881
1882 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1883 "\n============== DML DLG Output parameters [%d] ==============\n"
1884 "refcyc_h_blank_end: %d, \n"
1885 "dlg_vblank_end: %d, \n"
1886 "min_dst_y_next_start: %d, \n"
1887 "refcyc_per_htotal: %d, \n"
1888 "refcyc_x_after_scaler: %d, \n"
1889 "dst_y_after_scaler: %d, \n"
1890 "dst_y_prefetch: %d, \n"
1891 "dst_y_per_vm_vblank: %d, \n"
1892 "dst_y_per_row_vblank: %d, \n"
1893 "ref_freq_to_pix_freq: %d, \n"
1894 "vratio_prefetch: %d, \n"
1895 "refcyc_per_pte_group_vblank_l: %d, \n"
1896 "refcyc_per_meta_chunk_vblank_l: %d, \n"
1897 "dst_y_per_pte_row_nom_l: %d, \n"
1898 "refcyc_per_pte_group_nom_l: %d, \n",
1899 pipe_ctx->pipe_idx,
1900 pipe_ctx->dlg_regs.refcyc_h_blank_end,
1901 pipe_ctx->dlg_regs.dlg_vblank_end,
1902 pipe_ctx->dlg_regs.min_dst_y_next_start,
1903 pipe_ctx->dlg_regs.refcyc_per_htotal,
1904 pipe_ctx->dlg_regs.refcyc_x_after_scaler,
1905 pipe_ctx->dlg_regs.dst_y_after_scaler,
1906 pipe_ctx->dlg_regs.dst_y_prefetch,
1907 pipe_ctx->dlg_regs.dst_y_per_vm_vblank,
1908 pipe_ctx->dlg_regs.dst_y_per_row_vblank,
1909 pipe_ctx->dlg_regs.ref_freq_to_pix_freq,
1910 pipe_ctx->dlg_regs.vratio_prefetch,
1911 pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l,
1912 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l,
1913 pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l,
1914 pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l
1915 );
1916
1917 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1918 "\ndst_y_per_meta_row_nom_l: %d, \n"
1919 "refcyc_per_meta_chunk_nom_l: %d, \n"
1920 "refcyc_per_line_delivery_pre_l: %d, \n"
1921 "refcyc_per_line_delivery_l: %d, \n"
1922 "vratio_prefetch_c: %d, \n"
1923 "refcyc_per_pte_group_vblank_c: %d, \n"
1924 "refcyc_per_meta_chunk_vblank_c: %d, \n"
1925 "dst_y_per_pte_row_nom_c: %d, \n"
1926 "refcyc_per_pte_group_nom_c: %d, \n"
1927 "dst_y_per_meta_row_nom_c: %d, \n"
1928 "refcyc_per_meta_chunk_nom_c: %d, \n"
1929 "refcyc_per_line_delivery_pre_c: %d, \n"
1930 "refcyc_per_line_delivery_c: %d \n"
1931 "========================================================\n",
1932 pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l,
1933 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l,
1934 pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l,
1935 pipe_ctx->dlg_regs.refcyc_per_line_delivery_l,
1936 pipe_ctx->dlg_regs.vratio_prefetch_c,
1937 pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c,
1938 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c,
1939 pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c,
1940 pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c,
1941 pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c,
1942 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c,
1943 pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c,
1944 pipe_ctx->dlg_regs.refcyc_per_line_delivery_c
1945 );
1946
1947 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1948 "\n============== DML RQ Output parameters [%d] ==============\n"
1949 "chunk_size: %d \n"
1950 "min_chunk_size: %d \n"
1951 "meta_chunk_size: %d \n"
1952 "min_meta_chunk_size: %d \n"
1953 "dpte_group_size: %d \n"
1954 "mpte_group_size: %d \n"
1955 "swath_height: %d \n"
1956 "pte_row_height_linear: %d \n"
1957 "========================================================\n",
1958 pipe_ctx->pipe_idx,
1959 pipe_ctx->rq_regs.rq_regs_l.chunk_size,
1960 pipe_ctx->rq_regs.rq_regs_l.min_chunk_size,
1961 pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size,
1962 pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size,
1963 pipe_ctx->rq_regs.rq_regs_l.dpte_group_size,
1964 pipe_ctx->rq_regs.rq_regs_l.mpte_group_size,
1965 pipe_ctx->rq_regs.rq_regs_l.swath_height,
1966 pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear
1967 );
1968}
1969
70ccab60 1970static void dcn10_power_on_fe(
fb3466a4 1971 struct dc *dc,
70ccab60 1972 struct pipe_ctx *pipe_ctx,
608ac7bb 1973 struct dc_state *context)
70ccab60 1974{
3be5262e 1975 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
184debdb 1976 struct dce_hwseq *hws = dc->hwseq;
70ccab60 1977
fb3466a4 1978 if (dc->debug.sanity_checks) {
665da60f
CM
1979 verify_allow_pstate_change_high(dc->hwseq);
1980 }
1981
184debdb 1982 power_on_plane(dc->hwseq,
cfe4645e 1983 pipe_ctx->pipe_idx);
70ccab60 1984
c9742685 1985 /* enable DCFCLK current DCHUB */
d21becbe
TC
1986 REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx],
1987 HUBP_CLOCK_ENABLE, 1);
1988
1989 /* make sure OPP_PIPE_CLOCK_EN = 1 */
6b670fa9 1990 REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->stream_res.tg->inst],
d21becbe 1991 OPP_PIPE_CLOCK_EN, 1);
51666631 1992 /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/
c9742685 1993
3be5262e 1994 if (plane_state) {
61a44fc6 1995 dm_logger_write(dc->ctx->logger, LOG_DC,
c9742685
DL
1996 "Pipe:%d 0x%x: addr hi:0x%x, "
1997 "addr low:0x%x, "
1998 "src: %d, %d, %d,"
1999 " %d; dst: %d, %d, %d, %d;\n",
70ccab60 2000 pipe_ctx->pipe_idx,
3be5262e
HW
2001 plane_state,
2002 plane_state->address.grph.addr.high_part,
2003 plane_state->address.grph.addr.low_part,
2004 plane_state->src_rect.x,
2005 plane_state->src_rect.y,
2006 plane_state->src_rect.width,
2007 plane_state->src_rect.height,
2008 plane_state->dst_rect.x,
2009 plane_state->dst_rect.y,
2010 plane_state->dst_rect.width,
2011 plane_state->dst_rect.height);
c9742685 2012
61a44fc6 2013 dm_logger_write(dc->ctx->logger, LOG_DC,
c9742685
DL
2014 "Pipe %d: width, height, x, y\n"
2015 "viewport:%d, %d, %d, %d\n"
2016 "recout: %d, %d, %d, %d\n",
2017 pipe_ctx->pipe_idx,
6702a9ac
HW
2018 pipe_ctx->plane_res.scl_data.viewport.width,
2019 pipe_ctx->plane_res.scl_data.viewport.height,
2020 pipe_ctx->plane_res.scl_data.viewport.x,
2021 pipe_ctx->plane_res.scl_data.viewport.y,
2022 pipe_ctx->plane_res.scl_data.recout.width,
2023 pipe_ctx->plane_res.scl_data.recout.height,
2024 pipe_ctx->plane_res.scl_data.recout.x,
2025 pipe_ctx->plane_res.scl_data.recout.y);
c9742685 2026 print_rq_dlg_ttu(dc, pipe_ctx);
70ccab60 2027 }
665da60f 2028
fb3466a4 2029 if (dc->debug.sanity_checks) {
665da60f
CM
2030 verify_allow_pstate_change_high(dc->hwseq);
2031 }
70ccab60
HW
2032}
2033
2034static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
2035{
2036 struct xfm_grph_csc_adjustment adjust;
2037 memset(&adjust, 0, sizeof(adjust));
2038 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2039
2040
4fa086b9 2041 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
70ccab60
HW
2042 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2043 adjust.temperature_matrix[0] =
2044 pipe_ctx->stream->
4fa086b9 2045 gamut_remap_matrix.matrix[0];
70ccab60
HW
2046 adjust.temperature_matrix[1] =
2047 pipe_ctx->stream->
4fa086b9 2048 gamut_remap_matrix.matrix[1];
70ccab60
HW
2049 adjust.temperature_matrix[2] =
2050 pipe_ctx->stream->
4fa086b9 2051 gamut_remap_matrix.matrix[2];
70ccab60
HW
2052 adjust.temperature_matrix[3] =
2053 pipe_ctx->stream->
4fa086b9 2054 gamut_remap_matrix.matrix[4];
70ccab60
HW
2055 adjust.temperature_matrix[4] =
2056 pipe_ctx->stream->
4fa086b9 2057 gamut_remap_matrix.matrix[5];
70ccab60
HW
2058 adjust.temperature_matrix[5] =
2059 pipe_ctx->stream->
4fa086b9 2060 gamut_remap_matrix.matrix[6];
70ccab60
HW
2061 adjust.temperature_matrix[6] =
2062 pipe_ctx->stream->
4fa086b9 2063 gamut_remap_matrix.matrix[8];
70ccab60
HW
2064 adjust.temperature_matrix[7] =
2065 pipe_ctx->stream->
4fa086b9 2066 gamut_remap_matrix.matrix[9];
70ccab60
HW
2067 adjust.temperature_matrix[8] =
2068 pipe_ctx->stream->
4fa086b9 2069 gamut_remap_matrix.matrix[10];
70ccab60
HW
2070 }
2071
86a66c4e 2072 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
70ccab60
HW
2073}
2074
abe07e80
YHL
2075
2076static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
2077 enum dc_color_space colorspace,
2078 uint16_t *matrix)
2079{
2080 int i;
2081 struct out_csc_color_matrix tbl_entry;
2082
4fa086b9 2083 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
abe07e80
YHL
2084 == true) {
2085 enum dc_color_space color_space =
4fa086b9 2086 pipe_ctx->stream->output_color_space;
abe07e80
YHL
2087
2088 //uint16_t matrix[12];
2089 for (i = 0; i < 12; i++)
4fa086b9 2090 tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
abe07e80
YHL
2091
2092 tbl_entry.color_space = color_space;
2093 //tbl_entry.regval = matrix;
86a66c4e 2094 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry);
abe07e80
YHL
2095 }
2096}
4b28b76b
DL
2097static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
2098{
3be5262e 2099 if (pipe_ctx->plane_state->visible)
4b28b76b
DL
2100 return true;
2101 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
2102 return true;
2103 return false;
2104}
2105
2106static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
2107{
3be5262e 2108 if (pipe_ctx->plane_state->visible)
4b28b76b
DL
2109 return true;
2110 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
2111 return true;
2112 return false;
2113}
2114
2115static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
2116{
3be5262e 2117 if (pipe_ctx->plane_state->visible)
4b28b76b
DL
2118 return true;
2119 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
2120 return true;
2121 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
2122 return true;
2123 return false;
2124}
2125
ad327346
DL
2126static bool is_rgb_cspace(enum dc_color_space output_color_space)
2127{
2128 switch (output_color_space) {
2129 case COLOR_SPACE_SRGB:
2130 case COLOR_SPACE_SRGB_LIMITED:
2131 case COLOR_SPACE_2020_RGB_FULLRANGE:
2132 case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
2133 case COLOR_SPACE_ADOBERGB:
2134 return true;
2135 case COLOR_SPACE_YCBCR601:
2136 case COLOR_SPACE_YCBCR709:
2137 case COLOR_SPACE_YCBCR601_LIMITED:
2138 case COLOR_SPACE_YCBCR709_LIMITED:
2139 case COLOR_SPACE_2020_YCBCR:
2140 return false;
2141 default:
2142 /* Add a case to switch */
2143 BREAK_TO_DEBUGGER();
2144 return false;
2145 }
2146}
2147
87449a90
AK
2148static void dcn10_get_surface_visual_confirm_color(
2149 const struct pipe_ctx *pipe_ctx,
2150 struct tg_color *color)
2151{
2152 uint32_t color_value = MAX_TG_COLOR_VALUE;
2153
6702a9ac 2154 switch (pipe_ctx->plane_res.scl_data.format) {
87449a90
AK
2155 case PIXEL_FORMAT_ARGB8888:
2156 /* set boarder color to red */
2157 color->color_r_cr = color_value;
2158 break;
2159
2160 case PIXEL_FORMAT_ARGB2101010:
2161 /* set boarder color to blue */
2162 color->color_b_cb = color_value;
2163 break;
2164 case PIXEL_FORMAT_420BPP8:
2165 /* set boarder color to green */
2166 color->color_g_y = color_value;
2167 break;
2168 case PIXEL_FORMAT_420BPP10:
2169 /* set boarder color to yellow */
2170 color->color_g_y = color_value;
2171 color->color_r_cr = color_value;
2172 break;
2173 case PIXEL_FORMAT_FP16:
2174 /* set boarder color to white */
2175 color->color_r_cr = color_value;
2176 color->color_b_cb = color_value;
2177 color->color_g_y = color_value;
2178 break;
2179 default:
2180 break;
2181 }
2182}
2183
8feabd03 2184static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
0cb8a881
YHL
2185 struct vm_system_aperture_param *apt,
2186 struct dce_hwseq *hws)
2187{
2188 PHYSICAL_ADDRESS_LOC physical_page_number;
2189 uint32_t logical_addr_low;
2190 uint32_t logical_addr_high;
2191
2192 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
2193 PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part);
2194 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
2195 PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part);
2196
2197 REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
2198 LOGICAL_ADDR, &logical_addr_low);
2199
2200 REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
2201 LOGICAL_ADDR, &logical_addr_high);
2202
2203 apt->sys_default.quad_part = physical_page_number.quad_part << 12;
2204 apt->sys_low.quad_part = (int64_t)logical_addr_low << 18;
2205 apt->sys_high.quad_part = (int64_t)logical_addr_high << 18;
2206}
2207
2208/* Temporary read settings, future will get values from kmd directly */
8feabd03 2209static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
0cb8a881
YHL
2210 struct vm_context0_param *vm0,
2211 struct dce_hwseq *hws)
2212{
2213 PHYSICAL_ADDRESS_LOC fb_base;
2214 PHYSICAL_ADDRESS_LOC fb_offset;
2215 uint32_t fb_base_value;
2216 uint32_t fb_offset_value;
2217
2218 REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
2219 REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
2220
2221 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
2222 PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
2223 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
2224 PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part);
2225
2226 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
2227 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part);
2228 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
2229 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part);
2230
2231 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
2232 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part);
2233 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
2234 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part);
2235
2236 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
2237 PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part);
2238 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
2239 PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part);
2240
2241 /*
2242 * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space.
2243 * Therefore we need to do
2244 * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR
2245 * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE
2246 */
2247 fb_base.quad_part = (uint64_t)fb_base_value << 24;
2248 fb_offset.quad_part = (uint64_t)fb_offset_value << 24;
2249 vm0->pte_base.quad_part += fb_base.quad_part;
2250 vm0->pte_base.quad_part -= fb_offset.quad_part;
2251}
2252
8feabd03 2253static void dcn10_program_pte_vm(struct hubp *hubp,
0cb8a881
YHL
2254 enum surface_pixel_format format,
2255 union dc_tiling_info *tiling_info,
2256 enum dc_rotation_angle rotation,
2257 struct dce_hwseq *hws)
2258{
8feabd03 2259 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
0cb8a881
YHL
2260 struct vm_system_aperture_param apt = { {{ 0 } } };
2261 struct vm_context0_param vm0 = { { { 0 } } };
2262
2263
8feabd03
YHL
2264 mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
2265 mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
0cb8a881 2266
8feabd03
YHL
2267 hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt);
2268 hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0);
0cb8a881
YHL
2269}
2270
70ccab60 2271static void update_dchubp_dpp(
fb3466a4 2272 struct dc *dc,
70ccab60 2273 struct pipe_ctx *pipe_ctx,
608ac7bb 2274 struct dc_state *context)
70ccab60 2275{
184debdb 2276 struct dce_hwseq *hws = dc->hwseq;
8feabd03 2277 struct hubp *hubp = pipe_ctx->plane_res.hubp;
b3c340fa 2278 struct transform *xfm = pipe_ctx->plane_res.xfm;
3be5262e
HW
2279 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2280 union plane_size size = plane_state->plane_size;
cc408d72
DL
2281 struct mpcc_cfg mpcc_cfg = {0};
2282 struct pipe_ctx *top_pipe;
3be5262e 2283 bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
cbfd33fd 2284
ba326a91 2285 /* TODO: proper fix once fpga works */
70ccab60
HW
2286 /* depends on DML calculation, DPP clock value may change dynamically */
2287 enable_dppclk(
184debdb 2288 dc->hwseq,
70ccab60 2289 pipe_ctx->pipe_idx,
10688217 2290 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk,
9037d802 2291 context->bw.dcn.calc_clk.dppclk_div);
608ac7bb 2292 dc->current_state->bw.dcn.cur_clk.dppclk_div =
c66a54dc
DL
2293 context->bw.dcn.calc_clk.dppclk_div;
2294 context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div;
70ccab60 2295
184debdb
DL
2296 /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
2297 * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
2298 * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
2299 */
6b670fa9 2300 REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst);
70ccab60 2301
8feabd03
YHL
2302 hubp->funcs->hubp_setup(
2303 hubp,
70ccab60
HW
2304 &pipe_ctx->dlg_regs,
2305 &pipe_ctx->ttu_regs,
2306 &pipe_ctx->rq_regs,
2307 &pipe_ctx->pipe_dlg_param);
2308
6702a9ac 2309 size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport;
70ccab60 2310
fb3466a4 2311 if (dc->config.gpu_vm_support)
0cb8a881 2312 dcn10_program_pte_vm(
8feabd03 2313 pipe_ctx->plane_res.hubp,
3be5262e
HW
2314 plane_state->format,
2315 &plane_state->tiling_info,
0cb8a881
YHL
2316 plane_state->rotation,
2317 hws
2318 );
70ccab60 2319
b3c340fa 2320 xfm->funcs->ipp_setup(xfm,
3be5262e 2321 plane_state->format,
264efa31 2322 EXPANSION_MODE_ZERO);
70ccab60 2323
8feabd03 2324 mpcc_cfg.dpp_id = hubp->inst;
7f4a7253
EB
2325 mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst;
2326 mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree);
cc408d72
DL
2327 for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe)
2328 mpcc_cfg.z_index++;
fb3466a4 2329 if (dc->debug.surface_visual_confirm)
cc408d72
DL
2330 dcn10_get_surface_visual_confirm_color(
2331 pipe_ctx, &mpcc_cfg.black_color);
f0558542 2332 else
cc408d72
DL
2333 color_space_to_black_color(
2334 dc, pipe_ctx->stream->output_color_space,
2335 &mpcc_cfg.black_color);
f0558542 2336 mpcc_cfg.per_pixel_alpha = per_pixel_alpha;
ad327346
DL
2337 /* DCN1.0 has output CM before MPC which seems to screw with
2338 * pre-multiplied alpha.
2339 */
2340 mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
4fa086b9 2341 pipe_ctx->stream->output_color_space)
ad327346 2342 && per_pixel_alpha;
8feabd03
YHL
2343 hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg);
2344 hubp->opp_id = mpcc_cfg.opp_id;
70ccab60 2345
6702a9ac
HW
2346 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
2347 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
70ccab60 2348 /* scaler configuration */
86a66c4e
HW
2349 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(
2350 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data);
8feabd03 2351 hubp->funcs->mem_program_viewport(hubp,
6702a9ac 2352 &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c);
70ccab60
HW
2353
2354 /*gamut remap*/
2355 program_gamut_remap(pipe_ctx);
2356
69b516c9
S
2357 program_csc_matrix(pipe_ctx,
2358 pipe_ctx->stream->output_color_space,
2359 pipe_ctx->stream->csc_color_matrix.matrix);
70ccab60 2360
8feabd03
YHL
2361 hubp->funcs->hubp_program_surface_config(
2362 hubp,
3be5262e
HW
2363 plane_state->format,
2364 &plane_state->tiling_info,
70ccab60 2365 &size,
3be5262e
HW
2366 plane_state->rotation,
2367 &plane_state->dcc,
2368 plane_state->horizontal_mirror);
70ccab60 2369
50d4cfdc
YS
2370 dc->hwss.update_plane_addr(dc, pipe_ctx);
2371
8eb5def9 2372 if (is_pipe_tree_visible(pipe_ctx))
8feabd03 2373 hubp->funcs->set_blank(hubp, false);
70ccab60
HW
2374}
2375
9d6f264b 2376
70ccab60 2377static void program_all_pipe_in_tree(
fb3466a4 2378 struct dc *dc,
70ccab60 2379 struct pipe_ctx *pipe_ctx,
608ac7bb 2380 struct dc_state *context)
70ccab60
HW
2381{
2382 unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000;
2383
1a2c82a2 2384 if (pipe_ctx->top_pipe == NULL) {
70ccab60
HW
2385
2386 /* lock otg_master_update to process all pipes associated with
2387 * this OTG. this is done only one time.
2388 */
1a2c82a2 2389 /* watermark is for all pipes */
08b16886 2390 program_watermarks(dc->hwseq, &context->bw.dcn.watermarks, ref_clk_mhz);
2b13d7d3 2391
fb3466a4 2392 if (dc->debug.sanity_checks) {
2b13d7d3
TC
2393 /* pstate stuck check after watermark update */
2394 verify_allow_pstate_change_high(dc->hwseq);
2395 }
2396
6b670fa9 2397 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
cbfd33fd 2398
6b670fa9
HW
2399 pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
2400 pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
2401 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
2402 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
2403 pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
cbfd33fd 2404
6b670fa9
HW
2405 pipe_ctx->stream_res.tg->funcs->program_global_sync(
2406 pipe_ctx->stream_res.tg);
2407 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx));
1a2c82a2 2408 }
cbfd33fd 2409
3be5262e 2410 if (pipe_ctx->plane_state != NULL) {
067c878a
YS
2411 struct dc_cursor_position position = { 0 };
2412 struct pipe_ctx *cur_pipe_ctx =
2413 &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2414
1a2c82a2 2415 dcn10_power_on_fe(dc, pipe_ctx, context);
9d6f264b
YS
2416
2417 /* temporary dcn1 wa:
5667ff5c
DA
2418 * watermark update requires toggle after a/b/c/d sets are programmed
2419 * if hubp is pg then wm value doesn't get properaged to hubp
2420 * need to toggle after ungate to ensure wm gets to hubp.
2421 *
2422 * final solution: we need to get SMU to do the toggle as
2423 * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have
2424 * both driver and fw accessing same register
2425 */
9d6f264b
YS
2426 toggle_watermark_change_req(dc->hwseq);
2427
70ccab60 2428 update_dchubp_dpp(dc, pipe_ctx, context);
067c878a
YS
2429
2430 /* TODO: this is a hack w/a for switching from mpo to pipe split */
2431 dc_stream_set_cursor_position(pipe_ctx->stream, &position);
2432
2433 dc_stream_set_cursor_attributes(pipe_ctx->stream,
2434 &pipe_ctx->stream->cursor_attributes);
2435
2436 if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) {
2437 dc->hwss.set_input_transfer_func(
2438 pipe_ctx, pipe_ctx->plane_state);
2439 dc->hwss.set_output_transfer_func(
2440 pipe_ctx, pipe_ctx->stream);
2441 }
70ccab60
HW
2442 }
2443
fb3466a4 2444 if (dc->debug.sanity_checks) {
2b13d7d3
TC
2445 /* pstate stuck check after each pipe is programmed */
2446 verify_allow_pstate_change_high(dc->hwseq);
2447 }
2448
e1b522bf 2449 if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx)
70ccab60
HW
2450 program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
2451}
2452
2453static void dcn10_pplib_apply_display_requirements(
fb3466a4 2454 struct dc *dc,
608ac7bb 2455 struct dc_state *context)
70ccab60
HW
2456{
2457 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2458
2459 pp_display_cfg->all_displays_in_sync = false;/*todo*/
2460 pp_display_cfg->nb_pstate_switch_disable = false;
c66a54dc
DL
2461 pp_display_cfg->min_engine_clock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
2462 pp_display_cfg->min_memory_clock_khz = context->bw.dcn.cur_clk.fclk_khz;
2463 pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
2464 pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
70ccab60 2465 pp_display_cfg->avail_mclk_switch_time_us =
c66a54dc 2466 context->bw.dcn.cur_clk.dram_ccm_us > 0 ? context->bw.dcn.cur_clk.dram_ccm_us : 0;
70ccab60 2467 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us =
c66a54dc
DL
2468 context->bw.dcn.cur_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.cur_clk.min_active_dram_ccm_us : 0;
2469 pp_display_cfg->min_dcfclock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
2470 pp_display_cfg->disp_clk_khz = context->bw.dcn.cur_clk.dispclk_khz;
70ccab60
HW
2471 dce110_fill_display_configs(context, pp_display_cfg);
2472
2473 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2474 struct dm_pp_display_configuration)) != 0)
2475 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2476
2477 dc->prev_display_config = *pp_display_cfg;
2478}
2479
6bf52028
HW
2480static void optimize_shared_resources(struct dc *dc)
2481{
2482 if (dc->current_state->stream_count == 0) {
2483 apply_DEGVIDCN10_253_wa(dc);
2484 /* S0i2 message */
2485 dcn10_pplib_apply_display_requirements(dc, dc->current_state);
2486 }
441ad741
EY
2487
2488 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2489 dcn_bw_notify_pplib_of_wm_ranges(dc);
6bf52028
HW
2490}
2491
2492static void ready_shared_resources(struct dc *dc, struct dc_state *context)
2493{
2494 if (dc->current_state->stream_count == 0 &&
2495 !dc->debug.disable_stutter)
2496 undo_DEGVIDCN10_253_wa(dc);
2497
2498 /* S0i2 message */
2499 if (dc->current_state->stream_count == 0 &&
2500 context->stream_count != 0)
2501 dcn10_pplib_apply_display_requirements(dc, context);
2502}
2503
70ccab60 2504static void dcn10_apply_ctx_for_surface(
fb3466a4 2505 struct dc *dc,
3e9ad616
EY
2506 const struct dc_stream_state *stream,
2507 int num_planes,
608ac7bb 2508 struct dc_state *context)
70ccab60 2509{
7f10f3c2 2510 int i, be_idx;
70ccab60 2511
fb3466a4 2512 if (dc->debug.sanity_checks)
2b13d7d3
TC
2513 verify_allow_pstate_change_high(dc->hwseq);
2514
3e9ad616
EY
2515 be_idx = -1;
2516 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2517 if (stream == context->res_ctx.pipe_ctx[i].stream) {
2518 be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst;
7f10f3c2 2519 break;
3e9ad616
EY
2520 }
2521 }
2522
2523 ASSERT(be_idx != -1);
2524
2525 if (num_planes == 0) {
2526 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
2527 struct pipe_ctx *old_pipe_ctx =
608ac7bb 2528 &dc->current_state->res_ctx.pipe_ctx[i];
3e9ad616 2529
4e772ae5
YS
2530 if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) {
2531 old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true);
3e9ad616 2532 dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx);
4e772ae5 2533 }
3e9ad616
EY
2534 }
2535 return;
2536 }
7f10f3c2 2537
cfe4645e 2538 /* reset unused mpcc */
71a2f23e 2539 for (i = 0; i < dc->res_pool->pipe_count; i++) {
cfe4645e
DL
2540 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2541 struct pipe_ctx *old_pipe_ctx =
608ac7bb 2542 &dc->current_state->res_ctx.pipe_ctx[i];
7f10f3c2 2543
3be5262e 2544 if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state)
7f10f3c2
TC
2545 continue;
2546
4bdbab3e
EY
2547 /*
2548 * Powergate reused pipes that are not powergated
2549 * fairly hacky right now, using opp_id as indicator
2550 */
7f10f3c2 2551
3be5262e 2552 if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
8feabd03 2553 if (pipe_ctx->plane_res.hubp->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) {
4bdbab3e 2554 dcn10_power_down_fe(dc, pipe_ctx->pipe_idx);
aa985070
EY
2555 /*
2556 * power down fe will unlock when calling reset, need
2557 * to lock it back here. Messy, need rework.
2558 */
6b670fa9 2559 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
aa985070 2560 }
4bdbab3e 2561 }
cfe4645e 2562
7f10f3c2 2563
3be5262e 2564 if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state)
cfe4645e 2565 || (!pipe_ctx->stream && old_pipe_ctx->stream)) {
6b670fa9 2566 if (old_pipe_ctx->stream_res.tg->inst != be_idx)
7f10f3c2
TC
2567 continue;
2568
71a2f23e
EY
2569 if (!old_pipe_ctx->top_pipe) {
2570 ASSERT(0);
2571 continue;
2572 }
2573
4bdbab3e 2574 /* reset mpc */
cc408d72
DL
2575 dc->res_pool->mpc->funcs->remove(
2576 dc->res_pool->mpc,
7f4a7253
EB
2577 &(old_pipe_ctx->stream_res.opp->mpc_tree),
2578 old_pipe_ctx->stream_res.opp->inst,
cc408d72 2579 old_pipe_ctx->pipe_idx);
8feabd03 2580 old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.hubp->mpcc_id] = true;
2b13d7d3 2581
6be425f3
EY
2582 /*dm_logger_write(dc->ctx->logger, LOG_ERROR,
2583 "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n",
2584 old_pipe_ctx->mpcc->inst);*/
2585
fb3466a4 2586 if (dc->debug.sanity_checks)
2b13d7d3
TC
2587 verify_allow_pstate_change_high(dc->hwseq);
2588
cfe4645e
DL
2589 old_pipe_ctx->top_pipe = NULL;
2590 old_pipe_ctx->bottom_pipe = NULL;
3be5262e 2591 old_pipe_ctx->plane_state = NULL;
50d4cfdc 2592 old_pipe_ctx->stream = NULL;
cfe4645e
DL
2593
2594 dm_logger_write(dc->ctx->logger, LOG_DC,
2595 "Reset mpcc for pipe %d\n",
2596 old_pipe_ctx->pipe_idx);
2597 }
71a2f23e 2598 }
cfe4645e 2599
70ccab60
HW
2600 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2601 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2602
3e9ad616 2603 if (pipe_ctx->stream != stream)
70ccab60
HW
2604 continue;
2605
2606 /* looking for top pipe to program */
f0558542 2607 if (!pipe_ctx->top_pipe)
70ccab60
HW
2608 program_all_pipe_in_tree(dc, pipe_ctx, context);
2609 }
2610
c9742685
DL
2611 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
2612 "\n============== Watermark parameters ==============\n"
2613 "a.urgent_ns: %d \n"
2614 "a.cstate_enter_plus_exit: %d \n"
2615 "a.cstate_exit: %d \n"
2616 "a.pstate_change: %d \n"
2617 "a.pte_meta_urgent: %d \n"
2618 "b.urgent_ns: %d \n"
2619 "b.cstate_enter_plus_exit: %d \n"
2620 "b.cstate_exit: %d \n"
2621 "b.pstate_change: %d \n"
2622 "b.pte_meta_urgent: %d \n",
2623 context->bw.dcn.watermarks.a.urgent_ns,
2624 context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns,
2625 context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns,
2626 context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns,
2627 context->bw.dcn.watermarks.a.pte_meta_urgent_ns,
2628 context->bw.dcn.watermarks.b.urgent_ns,
2629 context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns,
2630 context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns,
2631 context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns,
2632 context->bw.dcn.watermarks.b.pte_meta_urgent_ns
2633 );
2634 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
2635 "\nc.urgent_ns: %d \n"
2636 "c.cstate_enter_plus_exit: %d \n"
2637 "c.cstate_exit: %d \n"
2638 "c.pstate_change: %d \n"
2639 "c.pte_meta_urgent: %d \n"
2640 "d.urgent_ns: %d \n"
2641 "d.cstate_enter_plus_exit: %d \n"
2642 "d.cstate_exit: %d \n"
2643 "d.pstate_change: %d \n"
2644 "d.pte_meta_urgent: %d \n"
2645 "========================================================\n",
2646 context->bw.dcn.watermarks.c.urgent_ns,
2647 context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns,
2648 context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns,
2649 context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns,
2650 context->bw.dcn.watermarks.c.pte_meta_urgent_ns,
2651 context->bw.dcn.watermarks.d.urgent_ns,
2652 context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns,
2653 context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns,
2654 context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns,
2655 context->bw.dcn.watermarks.d.pte_meta_urgent_ns
2656 );
2b13d7d3 2657
fb3466a4 2658 if (dc->debug.sanity_checks)
2b13d7d3 2659 verify_allow_pstate_change_high(dc->hwseq);
70ccab60
HW
2660}
2661
2662static void dcn10_set_bandwidth(
fb3466a4 2663 struct dc *dc,
608ac7bb 2664 struct dc_state *context,
70ccab60
HW
2665 bool decrease_allowed)
2666{
5f06b3cf
TC
2667 struct pp_smu_display_requirement_rv *smu_req_cur =
2668 &dc->res_pool->pp_smu_req;
2669 struct pp_smu_display_requirement_rv smu_req = *smu_req_cur;
2670 struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
70ccab60 2671
fb3466a4 2672 if (dc->debug.sanity_checks) {
665da60f
CM
2673 verify_allow_pstate_change_high(dc->hwseq);
2674 }
2675
70ccab60
HW
2676 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
2677 return;
2678
c66a54dc 2679 if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz
608ac7bb 2680 > dc->current_state->bw.dcn.cur_clk.dispclk_khz) {
70ccab60
HW
2681 dc->res_pool->display_clock->funcs->set_clock(
2682 dc->res_pool->display_clock,
9037d802 2683 context->bw.dcn.calc_clk.dispclk_khz);
608ac7bb 2684 dc->current_state->bw.dcn.cur_clk.dispclk_khz =
c66a54dc 2685 context->bw.dcn.calc_clk.dispclk_khz;
70ccab60 2686 }
c66a54dc 2687 if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz
608ac7bb 2688 > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) {
5f06b3cf
TC
2689 smu_req.hard_min_dcefclk_khz =
2690 context->bw.dcn.calc_clk.dcfclk_khz;
70ccab60 2691 }
c66a54dc 2692 if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz
608ac7bb 2693 > dc->current_state->bw.dcn.cur_clk.fclk_khz) {
5f06b3cf 2694 smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz;
c66a54dc
DL
2695 }
2696 if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz
608ac7bb
JZ
2697 > dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) {
2698 dc->current_state->bw.dcn.calc_clk.dcfclk_deep_sleep_khz =
c66a54dc
DL
2699 context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
2700 context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz =
2701 context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
2702 }
5f06b3cf
TC
2703
2704 smu_req.display_count = context->stream_count;
2705
2706 if (pp_smu->set_display_requirement)
2707 pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req);
2708
2709 *smu_req_cur = smu_req;
2710
c66a54dc
DL
2711 /* Decrease in freq is increase in period so opposite comparison for dram_ccm */
2712 if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us
608ac7bb
JZ
2713 < dc->current_state->bw.dcn.cur_clk.dram_ccm_us) {
2714 dc->current_state->bw.dcn.calc_clk.dram_ccm_us =
c66a54dc
DL
2715 context->bw.dcn.calc_clk.dram_ccm_us;
2716 context->bw.dcn.cur_clk.dram_ccm_us =
2717 context->bw.dcn.calc_clk.dram_ccm_us;
2718 }
2719 if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us
608ac7bb
JZ
2720 < dc->current_state->bw.dcn.cur_clk.min_active_dram_ccm_us) {
2721 dc->current_state->bw.dcn.calc_clk.min_active_dram_ccm_us =
c66a54dc
DL
2722 context->bw.dcn.calc_clk.min_active_dram_ccm_us;
2723 context->bw.dcn.cur_clk.min_active_dram_ccm_us =
2724 context->bw.dcn.calc_clk.min_active_dram_ccm_us;
70ccab60
HW
2725 }
2726 dcn10_pplib_apply_display_requirements(dc, context);
2b13d7d3 2727
fb3466a4 2728 if (dc->debug.sanity_checks) {
665da60f
CM
2729 verify_allow_pstate_change_high(dc->hwseq);
2730 }
2731
2b13d7d3 2732 /* need to fix this function. not doing the right thing here */
70ccab60
HW
2733}
2734
70ccab60
HW
2735static void set_drr(struct pipe_ctx **pipe_ctx,
2736 int num_pipes, int vmin, int vmax)
2737{
2738 int i = 0;
2739 struct drr_params params = {0};
2740
2741 params.vertical_total_max = vmax;
2742 params.vertical_total_min = vmin;
2743
2744 /* TODO: If multiple pipes are to be supported, you need
2745 * some GSL stuff
2746 */
2747 for (i = 0; i < num_pipes; i++) {
6b670fa9 2748 pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, &params);
70ccab60
HW
2749 }
2750}
2751
2752static void get_position(struct pipe_ctx **pipe_ctx,
2753 int num_pipes,
2754 struct crtc_position *position)
2755{
2756 int i = 0;
2757
2758 /* TODO: handle pipes > 1
2759 */
2760 for (i = 0; i < num_pipes; i++)
6b670fa9 2761 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
70ccab60
HW
2762}
2763
2764static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
2765 int num_pipes, const struct dc_static_screen_events *events)
2766{
2767 unsigned int i;
2768 unsigned int value = 0;
2769
2770 if (events->surface_update)
2771 value |= 0x80;
2772 if (events->cursor_update)
2773 value |= 0x2;
2774
2775 for (i = 0; i < num_pipes; i++)
6b670fa9
HW
2776 pipe_ctx[i]->stream_res.tg->funcs->
2777 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
70ccab60
HW
2778}
2779
2780static void set_plane_config(
fb3466a4 2781 const struct dc *dc,
70ccab60
HW
2782 struct pipe_ctx *pipe_ctx,
2783 struct resource_context *res_ctx)
2784{
2785 /* TODO */
2786 program_gamut_remap(pipe_ctx);
2787}
2788
4fac6da2 2789static void dcn10_config_stereo_parameters(
0971c40e 2790 struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
7f5c22d1 2791{
4fa086b9 2792 enum view_3d_format view_format = stream->view_format;
7f5c22d1 2793 enum dc_timing_3d_format timing_3d_format =\
4fa086b9 2794 stream->timing.timing_3d_format;
7f5c22d1
VP
2795 bool non_stereo_timing = false;
2796
2797 if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
2798 timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
2799 timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
2800 non_stereo_timing = true;
2801
2802 if (non_stereo_timing == false &&
2803 view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
2804
2805 flags->PROGRAM_STEREO = 1;
2806 flags->PROGRAM_POLARITY = 1;
2807 if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
2808 timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
2809 timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
2810 enum display_dongle_type dongle = \
d0778ebf 2811 stream->sink->link->ddc->dongle_type;
7f5c22d1
VP
2812 if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
2813 dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
2814 dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
2815 flags->DISABLE_STEREO_DP_SYNC = 1;
2816 }
2817 flags->RIGHT_EYE_POLARITY =\
4fa086b9 2818 stream->timing.flags.RIGHT_EYE_3D_POLARITY;
7f5c22d1
VP
2819 if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
2820 flags->FRAME_PACKED = 1;
2821 }
2822
2823 return;
2824}
2825
fb3466a4 2826static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
7f5c22d1
VP
2827{
2828 struct crtc_stereo_flags flags = { 0 };
0971c40e 2829 struct dc_stream_state *stream = pipe_ctx->stream;
7f5c22d1
VP
2830
2831 dcn10_config_stereo_parameters(stream, &flags);
2832
a6a6cb34
HW
2833 pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity(
2834 pipe_ctx->stream_res.opp,
7f5c22d1 2835 flags.PROGRAM_STEREO == 1 ? true:false,
4fa086b9 2836 stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false);
7f5c22d1 2837
6b670fa9
HW
2838 pipe_ctx->stream_res.tg->funcs->program_stereo(
2839 pipe_ctx->stream_res.tg,
4fa086b9 2840 &stream->timing,
7f5c22d1
VP
2841 &flags);
2842
7f5c22d1
VP
2843 return;
2844}
2845
6be425f3 2846static void dcn10_wait_for_mpcc_disconnect(
fb3466a4 2847 struct dc *dc,
6be425f3
EY
2848 struct resource_pool *res_pool,
2849 struct pipe_ctx *pipe_ctx)
87480687
EY
2850{
2851 int i;
87480687 2852
fb3466a4 2853 if (dc->debug.sanity_checks) {
665da60f
CM
2854 verify_allow_pstate_change_high(dc->hwseq);
2855 }
2856
a6a6cb34 2857 if (!pipe_ctx->stream_res.opp)
6be425f3
EY
2858 return;
2859
2860 for (i = 0; i < MAX_PIPES; i++) {
a6a6cb34 2861 if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i]) {
cc408d72 2862 res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i);
a6a6cb34 2863 pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i] = false;
8feabd03 2864 res_pool->hubps[i]->funcs->set_blank(res_pool->hubps[i], true);
6be425f3
EY
2865 /*dm_logger_write(dc->ctx->logger, LOG_ERROR,
2866 "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n",
2867 i);*/
87480687
EY
2868 }
2869 }
6be425f3 2870
fb3466a4 2871 if (dc->debug.sanity_checks) {
665da60f
CM
2872 verify_allow_pstate_change_high(dc->hwseq);
2873 }
2874
87480687
EY
2875}
2876
4fac6da2 2877static bool dcn10_dummy_display_power_gating(
fb3466a4 2878 struct dc *dc,
4fac6da2
DL
2879 uint8_t controller_id,
2880 struct dc_bios *dcb,
2b13d7d3
TC
2881 enum pipe_gating_control power_gating)
2882{
2883 return true;
2884}
2885
2886void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
2887{
3be5262e 2888 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
6b670fa9 2889 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2b13d7d3 2890
3be5262e 2891 if (plane_state == NULL)
2b13d7d3
TC
2892 return;
2893
3be5262e 2894 plane_state->status.is_flip_pending =
8feabd03
YHL
2895 pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending(
2896 pipe_ctx->plane_res.hubp);
2b13d7d3 2897
8feabd03
YHL
2898 plane_state->status.current_address = pipe_ctx->plane_res.hubp->current_address;
2899 if (pipe_ctx->plane_res.hubp->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2b13d7d3 2900 tg->funcs->is_stereo_left_eye) {
3be5262e 2901 plane_state->status.is_right_eye =
6b670fa9 2902 !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2b13d7d3
TC
2903 }
2904}
4fac6da2 2905
0cb8a881
YHL
2906
2907
70ccab60 2908static const struct hw_sequencer_funcs dcn10_funcs = {
1bf56e62 2909 .program_gamut_remap = program_gamut_remap,
abe07e80 2910 .program_csc_matrix = program_csc_matrix,
b02c3b05 2911 .init_hw = dcn10_init_hw,
70ccab60
HW
2912 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2913 .apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
2914 .set_plane_config = set_plane_config,
503a7c6f 2915 .update_plane_addr = dcn10_update_plane_addr,
08b16886 2916 .update_dchub = dcn10_update_dchub,
2b13d7d3 2917 .update_pending_status = dcn10_update_pending_status,
70ccab60
HW
2918 .set_input_transfer_func = dcn10_set_input_transfer_func,
2919 .set_output_transfer_func = dcn10_set_output_transfer_func,
2920 .power_down = dce110_power_down,
2921 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2922 .enable_timing_synchronization = dcn10_enable_timing_synchronization,
2923 .update_info_frame = dce110_update_info_frame,
2924 .enable_stream = dce110_enable_stream,
2925 .disable_stream = dce110_disable_stream,
2926 .unblank_stream = dce110_unblank_stream,
4fac6da2 2927 .enable_display_power_gating = dcn10_dummy_display_power_gating,
70ccab60
HW
2928 .power_down_front_end = dcn10_power_down_fe,
2929 .power_on_front_end = dcn10_power_on_fe,
2930 .pipe_control_lock = dcn10_pipe_control_lock,
2931 .set_bandwidth = dcn10_set_bandwidth,
2932 .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
2933 .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg,
2934 .set_drr = set_drr,
2935 .get_position = get_position,
7f5c22d1 2936 .set_static_screen_control = set_static_screen_control,
15e17335
CL
2937 .setup_stereo = dcn10_setup_stereo,
2938 .set_avmute = dce110_set_avmute,
87480687 2939 .log_hw_state = dcn10_log_hw_state,
41f97c07
HW
2940 .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
2941 .ready_shared_resources = ready_shared_resources,
2942 .optimize_shared_resources = optimize_shared_resources,
87401969
AJ
2943 .edp_backlight_control = hwss_edp_backlight_control,
2944 .edp_power_control = hwss_edp_power_control
70ccab60
HW
2945};
2946
2947
fb3466a4 2948void dcn10_hw_sequencer_construct(struct dc *dc)
70ccab60
HW
2949{
2950 dc->hwss = dcn10_funcs;
70ccab60
HW
2951}
2952