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