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