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