c9140b50c34549f12552bd6317ab5c28c11dd604
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / amd / display / dc / dcn32 / dcn32_hwseq.c
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
27 #include "dm_services.h"
28 #include "dm_helpers.h"
29 #include "core_types.h"
30 #include "resource.h"
31 #include "dccg.h"
32 #include "dce/dce_hwseq.h"
33 #include "dcn30/dcn30_cm_common.h"
34 #include "reg_helper.h"
35 #include "abm.h"
36 #include "hubp.h"
37 #include "dchubbub.h"
38 #include "timing_generator.h"
39 #include "opp.h"
40 #include "ipp.h"
41 #include "mpc.h"
42 #include "mcif_wb.h"
43 #include "dc_dmub_srv.h"
44 #include "link_hwss.h"
45 #include "dpcd_defs.h"
46 #include "dcn32_hwseq.h"
47 #include "clk_mgr.h"
48 #include "dsc.h"
49 #include "dcn20/dcn20_optc.h"
50 #include "dce/dmub_hw_lock_mgr.h"
51 #include "dcn32_resource.h"
52 #include "link.h"
53
54 #define DC_LOGGER_INIT(logger)
55
56 #define CTX \
57         hws->ctx
58 #define REG(reg)\
59         hws->regs->reg
60 #define DC_LOGGER \
61                 dc->ctx->logger
62
63
64 #undef FN
65 #define FN(reg_name, field_name) \
66         hws->shifts->field_name, hws->masks->field_name
67
68 void dcn32_dsc_pg_control(
69                 struct dce_hwseq *hws,
70                 unsigned int dsc_inst,
71                 bool power_on)
72 {
73         uint32_t power_gate = power_on ? 0 : 1;
74         uint32_t pwr_status = power_on ? 0 : 2;
75         uint32_t org_ip_request_cntl = 0;
76
77         if (hws->ctx->dc->debug.disable_dsc_power_gate)
78                 return;
79
80         if (!hws->ctx->dc->debug.enable_double_buffered_dsc_pg_support)
81                 return;
82
83         REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
84         if (org_ip_request_cntl == 0)
85                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
86
87         switch (dsc_inst) {
88         case 0: /* DSC0 */
89                 REG_UPDATE(DOMAIN16_PG_CONFIG,
90                                 DOMAIN_POWER_GATE, power_gate);
91
92                 REG_WAIT(DOMAIN16_PG_STATUS,
93                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
94                                 1, 1000);
95                 break;
96         case 1: /* DSC1 */
97                 REG_UPDATE(DOMAIN17_PG_CONFIG,
98                                 DOMAIN_POWER_GATE, power_gate);
99
100                 REG_WAIT(DOMAIN17_PG_STATUS,
101                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
102                                 1, 1000);
103                 break;
104         case 2: /* DSC2 */
105                 REG_UPDATE(DOMAIN18_PG_CONFIG,
106                                 DOMAIN_POWER_GATE, power_gate);
107
108                 REG_WAIT(DOMAIN18_PG_STATUS,
109                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
110                                 1, 1000);
111                 break;
112         case 3: /* DSC3 */
113                 REG_UPDATE(DOMAIN19_PG_CONFIG,
114                                 DOMAIN_POWER_GATE, power_gate);
115
116                 REG_WAIT(DOMAIN19_PG_STATUS,
117                                 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
118                                 1, 1000);
119                 break;
120         default:
121                 BREAK_TO_DEBUGGER();
122                 break;
123         }
124
125         if (org_ip_request_cntl == 0)
126                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
127 }
128
129
130 void dcn32_enable_power_gating_plane(
131         struct dce_hwseq *hws,
132         bool enable)
133 {
134         bool force_on = true; /* disable power gating */
135         uint32_t org_ip_request_cntl = 0;
136
137         if (enable)
138                 force_on = false;
139
140         REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
141         if (org_ip_request_cntl == 0)
142                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
143
144         /* DCHUBP0/1/2/3 */
145         REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
146         REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
147         REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
148         REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
149
150         /* DCS0/1/2/3 */
151         REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
152         REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
153         REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
154         REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
155
156         if (org_ip_request_cntl == 0)
157                 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
158 }
159
160 void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
161 {
162         uint32_t power_gate = power_on ? 0 : 1;
163         uint32_t pwr_status = power_on ? 0 : 2;
164
165         if (hws->ctx->dc->debug.disable_hubp_power_gate)
166                 return;
167
168         if (REG(DOMAIN0_PG_CONFIG) == 0)
169                 return;
170
171         switch (hubp_inst) {
172         case 0:
173                 REG_SET(DOMAIN0_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
174                 REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
175                 break;
176         case 1:
177                 REG_SET(DOMAIN1_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
178                 REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
179                 break;
180         case 2:
181                 REG_SET(DOMAIN2_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
182                 REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
183                 break;
184         case 3:
185                 REG_SET(DOMAIN3_PG_CONFIG, 0, DOMAIN_POWER_GATE, power_gate);
186                 REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
187                 break;
188         default:
189                 BREAK_TO_DEBUGGER();
190                 break;
191         }
192 }
193
194 static bool dcn32_check_no_memory_request_for_cab(struct dc *dc)
195 {
196         int i;
197
198     /* First, check no-memory-request case */
199         for (i = 0; i < dc->current_state->stream_count; i++) {
200                 if ((dc->current_state->stream_status[i].plane_count) &&
201                         (dc->current_state->streams[i]->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED))
202                         /* Fail eligibility on a visible stream */
203                         break;
204         }
205
206         if (i == dc->current_state->stream_count)
207                 return true;
208
209         return false;
210 }
211
212
213 /* This function loops through every surface that needs to be cached in CAB for SS,
214  * and calculates the total number of ways required to store all surfaces (primary,
215  * meta, cursor).
216  */
217 static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *ctx)
218 {
219         int i;
220         uint32_t num_ways = 0;
221         uint32_t mall_ss_size_bytes = 0;
222
223         mall_ss_size_bytes = ctx->bw_ctx.bw.dcn.mall_ss_size_bytes;
224         // TODO add additional logic for PSR active stream exclusion optimization
225         // mall_ss_psr_active_size_bytes = ctx->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes;
226
227         // Include cursor size for CAB allocation
228         for (i = 0; i < dc->res_pool->pipe_count; i++) {
229                 struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[i];
230
231                 if (!pipe->stream || !pipe->plane_state)
232                         continue;
233
234                 mall_ss_size_bytes += dcn32_helper_calculate_mall_bytes_for_cursor(dc, pipe, false);
235         }
236
237         // Convert number of cache lines required to number of ways
238         if (dc->debug.force_mall_ss_num_ways > 0) {
239                 num_ways = dc->debug.force_mall_ss_num_ways;
240         } else {
241                 num_ways = dcn32_helper_mall_bytes_to_ways(dc, mall_ss_size_bytes);
242         }
243
244         return num_ways;
245 }
246
247 bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable)
248 {
249         union dmub_rb_cmd cmd;
250         uint8_t i;
251         uint32_t ways;
252         int j;
253         bool mall_ss_unsupported = false;
254         struct dc_plane_state *plane = NULL;
255
256         if (!dc->ctx->dmub_srv)
257                 return false;
258
259         for (i = 0; i < dc->current_state->stream_count; i++) {
260                 /* MALL SS messaging is not supported with PSR at this time */
261                 if (dc->current_state->streams[i] != NULL &&
262                                 dc->current_state->streams[i]->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED)
263                         return false;
264         }
265
266         if (enable) {
267                 if (dc->current_state) {
268
269                         /* 1. Check no memory request case for CAB.
270                          * If no memory request case, send CAB_ACTION NO_DF_REQ DMUB message
271                          */
272                         if (dcn32_check_no_memory_request_for_cab(dc)) {
273                                 /* Enable no-memory-requests case */
274                                 memset(&cmd, 0, sizeof(cmd));
275                                 cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
276                                 cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ;
277                                 cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
278
279                                 dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
280
281                                 return true;
282                         }
283
284                         /* 2. Check if all surfaces can fit in CAB.
285                          * If surfaces can fit into CAB, send CAB_ACTION_ALLOW DMUB message
286                          * and configure HUBP's to fetch from MALL
287                          */
288                         ways = dcn32_calculate_cab_allocation(dc, dc->current_state);
289
290                         /* MALL not supported with Stereo3D or TMZ surface. If any plane is using stereo,
291                          * or TMZ surface, don't try to enter MALL.
292                          */
293                         for (i = 0; i < dc->current_state->stream_count; i++) {
294                                 for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
295                                         plane = dc->current_state->stream_status[i].plane_states[j];
296
297                                         if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO ||
298                                                         plane->address.tmz_surface) {
299                                                 mall_ss_unsupported = true;
300                                                 break;
301                                         }
302                                 }
303                                 if (mall_ss_unsupported)
304                                         break;
305                         }
306                         if (ways <= dc->caps.cache_num_ways && !mall_ss_unsupported) {
307                                 memset(&cmd, 0, sizeof(cmd));
308                                 cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
309                                 cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB;
310                                 cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header);
311                                 cmd.cab.cab_alloc_ways = (uint8_t)ways;
312
313                                 dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
314
315                                 return true;
316                         }
317
318                 }
319                 return false;
320         }
321
322         /* Disable CAB */
323         memset(&cmd, 0, sizeof(cmd));
324         cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS;
325         cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_IDLE_OPTIMIZATION;
326         cmd.cab.header.payload_bytes =
327                         sizeof(cmd.cab) - sizeof(cmd.cab.header);
328
329         dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
330
331         return true;
332 }
333
334 /* Send DMCUB message with SubVP pipe info
335  * - For each pipe in context, populate payload with required SubVP information
336  *   if the pipe is using SubVP for MCLK switch
337  * - This function must be called while the DMUB HW lock is acquired by driver
338  */
339 void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context)
340 {
341         int i;
342         bool enable_subvp = false;
343
344         if (!dc->ctx || !dc->ctx->dmub_srv)
345                 return;
346
347         for (i = 0; i < dc->res_pool->pipe_count; i++) {
348                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
349
350                 if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.paired_stream &&
351                                 pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) {
352                         // There is at least 1 SubVP pipe, so enable SubVP
353                         enable_subvp = true;
354                         break;
355                 }
356         }
357         dc_dmub_setup_subvp_dmub_command(dc, context, enable_subvp);
358 }
359
360 /* Sub-Viewport DMUB lock needs to be acquired by driver whenever SubVP is active and:
361  * 1. Any full update for any SubVP main pipe
362  * 2. Any immediate flip for any SubVP pipe
363  * 3. Any flip for DRR pipe
364  * 4. If SubVP was previously in use (i.e. in old context)
365  */
366 void dcn32_subvp_pipe_control_lock(struct dc *dc,
367                 struct dc_state *context,
368                 bool lock,
369                 bool should_lock_all_pipes,
370                 struct pipe_ctx *top_pipe_to_program,
371                 bool subvp_prev_use)
372 {
373         unsigned int i = 0;
374         bool subvp_immediate_flip = false;
375         bool subvp_in_use = false;
376         struct pipe_ctx *pipe;
377
378         for (i = 0; i < dc->res_pool->pipe_count; i++) {
379                 pipe = &context->res_ctx.pipe_ctx[i];
380
381                 if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
382                         subvp_in_use = true;
383                         break;
384                 }
385         }
386
387         if (top_pipe_to_program && top_pipe_to_program->stream && top_pipe_to_program->plane_state) {
388                 if (top_pipe_to_program->stream->mall_stream_config.type == SUBVP_MAIN &&
389                                 top_pipe_to_program->plane_state->flip_immediate)
390                         subvp_immediate_flip = true;
391         }
392
393         // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared.
394         if ((subvp_in_use && (should_lock_all_pipes || subvp_immediate_flip)) || (!subvp_in_use && subvp_prev_use)) {
395                 union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
396
397                 if (!lock) {
398                         for (i = 0; i < dc->res_pool->pipe_count; i++) {
399                                 pipe = &context->res_ctx.pipe_ctx[i];
400                                 if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN &&
401                                                 should_lock_all_pipes)
402                                         pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VBLANK);
403                         }
404                 }
405
406                 hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
407                 hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
408                 hw_lock_cmd.bits.lock = lock;
409                 hw_lock_cmd.bits.should_release = !lock;
410                 dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
411         }
412 }
413
414 void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params)
415 {
416         struct dc *dc = params->subvp_pipe_control_lock_fast_params.dc;
417         bool lock = params->subvp_pipe_control_lock_fast_params.lock;
418         struct pipe_ctx *pipe_ctx = params->subvp_pipe_control_lock_fast_params.pipe_ctx;
419         bool subvp_immediate_flip = false;
420
421         if (pipe_ctx && pipe_ctx->stream && pipe_ctx->plane_state) {
422                 if (pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN &&
423                                 pipe_ctx->plane_state->flip_immediate)
424                         subvp_immediate_flip = true;
425         }
426
427         // Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared.
428         if (subvp_immediate_flip) {
429                 union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
430
431                 hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
432                 hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
433                 hw_lock_cmd.bits.lock = lock;
434                 hw_lock_cmd.bits.should_release = !lock;
435                 dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
436         }
437 }
438
439 bool dcn32_set_mpc_shaper_3dlut(
440         struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream)
441 {
442         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
443         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
444         struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
445         bool result = false;
446
447         const struct pwl_params *shaper_lut = NULL;
448         //get the shaper lut params
449         if (stream->func_shaper) {
450                 if (stream->func_shaper->type == TF_TYPE_HWPWL)
451                         shaper_lut = &stream->func_shaper->pwl;
452                 else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
453                         cm_helper_translate_curve_to_hw_format(stream->ctx,
454                                         stream->func_shaper,
455                                         &dpp_base->shaper_params, true);
456                         shaper_lut = &dpp_base->shaper_params;
457                 }
458         }
459
460         if (stream->lut3d_func &&
461                 stream->lut3d_func->state.bits.initialized == 1) {
462
463                 result = mpc->funcs->program_3dlut(mpc,
464                                                                 &stream->lut3d_func->lut_3d,
465                                                                 mpcc_id);
466
467                 result = mpc->funcs->program_shaper(mpc,
468                                                                 shaper_lut,
469                                                                 mpcc_id);
470         }
471
472         return result;
473 }
474
475 bool dcn32_set_mcm_luts(
476         struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
477 {
478         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
479         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
480         struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
481         bool result = true;
482         struct pwl_params *lut_params = NULL;
483
484         // 1D LUT
485         if (plane_state->blend_tf) {
486                 if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
487                         lut_params = &plane_state->blend_tf->pwl;
488                 else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
489                         cm_helper_translate_curve_to_hw_format(plane_state->ctx,
490                                         plane_state->blend_tf,
491                                         &dpp_base->regamma_params, false);
492                         lut_params = &dpp_base->regamma_params;
493                 }
494         }
495         result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
496
497         // Shaper
498         if (plane_state->in_shaper_func) {
499                 if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL)
500                         lut_params = &plane_state->in_shaper_func->pwl;
501                 else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
502                         // TODO: dpp_base replace
503                         ASSERT(false);
504                         cm_helper_translate_curve_to_hw_format(plane_state->ctx,
505                                         plane_state->in_shaper_func,
506                                         &dpp_base->shaper_params, true);
507                         lut_params = &dpp_base->shaper_params;
508                 }
509         }
510
511         result = mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
512
513         // 3D
514         if (plane_state->lut3d_func && plane_state->lut3d_func->state.bits.initialized == 1)
515                 result = mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func->lut_3d, mpcc_id);
516         else
517                 result = mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
518
519         return result;
520 }
521
522 bool dcn32_set_input_transfer_func(struct dc *dc,
523                                 struct pipe_ctx *pipe_ctx,
524                                 const struct dc_plane_state *plane_state)
525 {
526         struct dce_hwseq *hws = dc->hwseq;
527         struct mpc *mpc = dc->res_pool->mpc;
528         struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
529
530         enum dc_transfer_func_predefined tf;
531         bool result = true;
532         struct pwl_params *params = NULL;
533
534         if (mpc == NULL || plane_state == NULL)
535                 return false;
536
537         tf = TRANSFER_FUNCTION_UNITY;
538
539         if (plane_state->in_transfer_func &&
540                 plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED)
541                 tf = plane_state->in_transfer_func->tf;
542
543         dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
544
545         if (plane_state->in_transfer_func) {
546                 if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL)
547                         params = &plane_state->in_transfer_func->pwl;
548                 else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS &&
549                         cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func,
550                                         &dpp_base->degamma_params, false))
551                         params = &dpp_base->degamma_params;
552         }
553
554         dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
555
556         if (pipe_ctx->stream_res.opp &&
557                         pipe_ctx->stream_res.opp->ctx &&
558                         hws->funcs.set_mcm_luts)
559                 result = hws->funcs.set_mcm_luts(pipe_ctx, plane_state);
560
561         return result;
562 }
563
564 bool dcn32_set_output_transfer_func(struct dc *dc,
565                                 struct pipe_ctx *pipe_ctx,
566                                 const struct dc_stream_state *stream)
567 {
568         int mpcc_id = pipe_ctx->plane_res.hubp->inst;
569         struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
570         struct pwl_params *params = NULL;
571         bool ret = false;
572
573         /* program OGAM or 3DLUT only for the top pipe*/
574         if (resource_is_pipe_type(pipe_ctx, OPP_HEAD)) {
575                 /*program shaper and 3dlut in MPC*/
576                 ret = dcn32_set_mpc_shaper_3dlut(pipe_ctx, stream);
577                 if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
578                         if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
579                                 params = &stream->out_transfer_func->pwl;
580                         else if (pipe_ctx->stream->out_transfer_func->type ==
581                                         TF_TYPE_DISTRIBUTED_POINTS &&
582                                         cm3_helper_translate_curve_to_hw_format(
583                                         stream->out_transfer_func,
584                                         &mpc->blender_params, false))
585                                 params = &mpc->blender_params;
586                         /* there are no ROM LUTs in OUTGAM */
587                         if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
588                                 BREAK_TO_DEBUGGER();
589                 }
590         }
591
592         mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
593         return ret;
594 }
595
596 /* Program P-State force value according to if pipe is using SubVP / FPO or not:
597  * 1. Reset P-State force on all pipes first
598  * 2. For each main pipe, force P-State disallow (P-State allow moderated by DMUB)
599  */
600 void dcn32_update_force_pstate(struct dc *dc, struct dc_state *context)
601 {
602         int i;
603
604         /* Unforce p-state for each pipe if it is not FPO or SubVP.
605          * For FPO and SubVP, if it's already forced disallow, leave
606          * it as disallow.
607          */
608         for (i = 0; i < dc->res_pool->pipe_count; i++) {
609                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
610                 struct hubp *hubp = pipe->plane_res.hubp;
611
612                 if (!pipe->stream || !(pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
613                     pipe->stream->fpo_in_use)) {
614                         if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
615                                 hubp->funcs->hubp_update_force_pstate_disallow(hubp, false);
616                 }
617
618                 /* Today only FPO uses cursor P-State force. Only clear cursor P-State force
619                  * if it's not FPO.
620                  */
621                 if (!pipe->stream || !pipe->stream->fpo_in_use) {
622                         if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow)
623                                 hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, false);
624                 }
625         }
626
627         /* Loop through each pipe -- for each subvp main pipe force p-state allow equal to false.
628          */
629         for (i = 0; i < dc->res_pool->pipe_count; i++) {
630                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
631                 struct hubp *hubp = pipe->plane_res.hubp;
632
633                 if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
634                         if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
635                                 hubp->funcs->hubp_update_force_pstate_disallow(hubp, true);
636                 }
637
638                 if (pipe->stream && pipe->stream->fpo_in_use) {
639                         if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
640                                 hubp->funcs->hubp_update_force_pstate_disallow(hubp, true);
641                         /* For now only force cursor p-state disallow for FPO
642                          * Needs to be added for subvp once FW side gets updated
643                          */
644                         if (hubp && hubp->funcs->hubp_update_force_cursor_pstate_disallow)
645                                 hubp->funcs->hubp_update_force_cursor_pstate_disallow(hubp, true);
646                 }
647         }
648 }
649
650 /* Update MALL_SEL register based on if pipe / plane
651  * is a phantom pipe, main pipe, and if using MALL
652  * for SS.
653  */
654 void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context)
655 {
656         int i;
657         unsigned int num_ways = dcn32_calculate_cab_allocation(dc, context);
658         bool cache_cursor = false;
659
660         for (i = 0; i < dc->res_pool->pipe_count; i++) {
661                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
662                 struct hubp *hubp = pipe->plane_res.hubp;
663
664                 if (pipe->stream && pipe->plane_state && hubp && hubp->funcs->hubp_update_mall_sel) {
665                         int cursor_size = hubp->curs_attr.pitch * hubp->curs_attr.height;
666
667                         switch (hubp->curs_attr.color_format) {
668                         case CURSOR_MODE_MONO:
669                                 cursor_size /= 2;
670                                 break;
671                         case CURSOR_MODE_COLOR_1BIT_AND:
672                         case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
673                         case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
674                                 cursor_size *= 4;
675                                 break;
676
677                         case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
678                         case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
679                         default:
680                                 cursor_size *= 8;
681                                 break;
682                         }
683
684                         if (cursor_size > 16384)
685                                 cache_cursor = true;
686
687                         if (pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
688                                         hubp->funcs->hubp_update_mall_sel(hubp, 1, false);
689                         } else {
690                                 // MALL not supported with Stereo3D
691                                 hubp->funcs->hubp_update_mall_sel(hubp,
692                                         num_ways <= dc->caps.cache_num_ways &&
693                                         pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED &&
694                                         pipe->plane_state->address.type !=  PLN_ADDR_TYPE_GRPH_STEREO &&
695                                         !pipe->plane_state->address.tmz_surface ? 2 : 0,
696                                                         cache_cursor);
697                         }
698                 }
699         }
700 }
701
702 /* Program the sub-viewport pipe configuration after the main / phantom pipes
703  * have been programmed in hardware.
704  * 1. Update force P-State for all the main pipes (disallow P-state)
705  * 2. Update MALL_SEL register
706  * 3. Program FORCE_ONE_ROW_FOR_FRAME for main subvp pipes
707  */
708 void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context)
709 {
710         int i;
711         struct dce_hwseq *hws = dc->hwseq;
712
713         // Don't force p-state disallow -- can't block dummy p-state
714
715         // Update MALL_SEL register for each pipe
716         if (hws && hws->funcs.update_mall_sel)
717                 hws->funcs.update_mall_sel(dc, context);
718
719         // Program FORCE_ONE_ROW_FOR_FRAME and CURSOR_REQ_MODE for main subvp pipes
720         for (i = 0; i < dc->res_pool->pipe_count; i++) {
721                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
722                 struct hubp *hubp = pipe->plane_res.hubp;
723
724                 if (pipe->stream && hubp && hubp->funcs->hubp_prepare_subvp_buffering) {
725                         /* TODO - remove setting CURSOR_REQ_MODE to 0 for legacy cases
726                          *      - need to investigate single pipe MPO + SubVP case to
727                          *        see if CURSOR_REQ_MODE will be back to 1 for SubVP
728                          *        when it should be 0 for MPO
729                          */
730                         if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
731                                 hubp->funcs->hubp_prepare_subvp_buffering(hubp, true);
732                         }
733                 }
734         }
735 }
736
737 static void dcn32_initialize_min_clocks(struct dc *dc)
738 {
739         struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk;
740
741         clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ;
742         clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000;
743         clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
744         clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000;
745         clocks->dppclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dppclk_mhz * 1000;
746         clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
747         clocks->fclk_p_state_change_support = true;
748         clocks->p_state_change_support = true;
749         if (dc->debug.disable_boot_optimizations) {
750                 clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
751         } else {
752                 /* Even though DPG_EN = 1 for the connected display, it still requires the
753                  * correct timing so we cannot set DISPCLK to min freq or it could cause
754                  * audio corruption. Read current DISPCLK from DENTIST and request the same
755                  * freq to ensure that the timing is valid and unchanged.
756                  */
757                 clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
758         }
759
760         dc->clk_mgr->funcs->update_clocks(
761                         dc->clk_mgr,
762                         dc->current_state,
763                         true);
764 }
765
766 void dcn32_init_hw(struct dc *dc)
767 {
768         struct abm **abms = dc->res_pool->multiple_abms;
769         struct dce_hwseq *hws = dc->hwseq;
770         struct dc_bios *dcb = dc->ctx->dc_bios;
771         struct resource_pool *res_pool = dc->res_pool;
772         int i;
773         int edp_num;
774         uint32_t backlight = MAX_BACKLIGHT_LEVEL;
775
776         if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
777                 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
778
779         // Initialize the dccg
780         if (res_pool->dccg->funcs->dccg_init)
781                 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
782
783         if (!dcb->funcs->is_accelerated_mode(dcb)) {
784                 hws->funcs.bios_golden_init(dc);
785                 hws->funcs.disable_vga(dc->hwseq);
786         }
787
788         // Set default OPTC memory power states
789         if (dc->debug.enable_mem_low_power.bits.optc) {
790                 // Shutdown when unassigned and light sleep in VBLANK
791                 REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
792         }
793
794         if (dc->debug.enable_mem_low_power.bits.vga) {
795                 // Power down VGA memory
796                 REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
797         }
798
799         if (dc->ctx->dc_bios->fw_info_valid) {
800                 res_pool->ref_clocks.xtalin_clock_inKhz =
801                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
802
803                 if (res_pool->dccg && res_pool->hubbub) {
804                         (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
805                                         dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
806                                         &res_pool->ref_clocks.dccg_ref_clock_inKhz);
807
808                         (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
809                                         res_pool->ref_clocks.dccg_ref_clock_inKhz,
810                                         &res_pool->ref_clocks.dchub_ref_clock_inKhz);
811                 } else {
812                         // Not all ASICs have DCCG sw component
813                         res_pool->ref_clocks.dccg_ref_clock_inKhz =
814                                         res_pool->ref_clocks.xtalin_clock_inKhz;
815                         res_pool->ref_clocks.dchub_ref_clock_inKhz =
816                                         res_pool->ref_clocks.xtalin_clock_inKhz;
817                 }
818         } else
819                 ASSERT_CRITICAL(false);
820
821         for (i = 0; i < dc->link_count; i++) {
822                 /* Power up AND update implementation according to the
823                  * required signal (which may be different from the
824                  * default signal on connector).
825                  */
826                 struct dc_link *link = dc->links[i];
827
828                 link->link_enc->funcs->hw_init(link->link_enc);
829
830                 /* Check for enabled DIG to identify enabled display */
831                 if (link->link_enc->funcs->is_dig_enabled &&
832                         link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
833                         link->link_status.link_active = true;
834                         link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
835                         if (link->link_enc->funcs->fec_is_active &&
836                                         link->link_enc->funcs->fec_is_active(link->link_enc))
837                                 link->fec_state = dc_link_fec_enabled;
838                 }
839         }
840
841         /* enable_power_gating_plane before dsc_pg_control because
842          * FORCEON = 1 with hw default value on bootup, resume from s3
843          */
844         if (hws->funcs.enable_power_gating_plane)
845                 hws->funcs.enable_power_gating_plane(dc->hwseq, true);
846
847         /* we want to turn off all dp displays before doing detection */
848         dc->link_srv->blank_all_dp_displays(dc);
849
850         /* If taking control over from VBIOS, we may want to optimize our first
851          * mode set, so we need to skip powering down pipes until we know which
852          * pipes we want to use.
853          * Otherwise, if taking control is not possible, we need to power
854          * everything down.
855          */
856         if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
857                 /* Disable boot optimizations means power down everything including PHY, DIG,
858                  * and OTG (i.e. the boot is not optimized because we do a full power down).
859                  */
860                 if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations)
861                         dc->hwss.enable_accelerated_mode(dc, dc->current_state);
862                 else
863                         hws->funcs.init_pipes(dc, dc->current_state);
864
865                 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
866                         dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
867                                         !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
868
869                 dcn32_initialize_min_clocks(dc);
870
871                 /* On HW init, allow idle optimizations after pipes have been turned off.
872                  *
873                  * In certain D3 cases (i.e. BOCO / BOMACO) it's possible that hardware state
874                  * is reset (i.e. not in idle at the time hw init is called), but software state
875                  * still has idle_optimizations = true, so we must disable idle optimizations first
876                  * (i.e. set false), then re-enable (set true).
877                  */
878                 dc_allow_idle_optimizations(dc, false);
879                 dc_allow_idle_optimizations(dc, true);
880         }
881
882         /* In headless boot cases, DIG may be turned
883          * on which causes HW/SW discrepancies.
884          * To avoid this, power down hardware on boot
885          * if DIG is turned on and seamless boot not enabled
886          */
887         if (!dc->config.seamless_boot_edp_requested) {
888                 struct dc_link *edp_links[MAX_NUM_EDP];
889                 struct dc_link *edp_link;
890
891                 dc_get_edp_links(dc, edp_links, &edp_num);
892                 if (edp_num) {
893                         for (i = 0; i < edp_num; i++) {
894                                 edp_link = edp_links[i];
895                                 if (edp_link->link_enc->funcs->is_dig_enabled &&
896                                                 edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
897                                                 dc->hwss.edp_backlight_control &&
898                                                 dc->hwss.power_down &&
899                                                 dc->hwss.edp_power_control) {
900                                         dc->hwss.edp_backlight_control(edp_link, false);
901                                         dc->hwss.power_down(dc);
902                                         dc->hwss.edp_power_control(edp_link, false);
903                                 }
904                         }
905                 } else {
906                         for (i = 0; i < dc->link_count; i++) {
907                                 struct dc_link *link = dc->links[i];
908
909                                 if (link->link_enc->funcs->is_dig_enabled &&
910                                                 link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
911                                                 dc->hwss.power_down) {
912                                         dc->hwss.power_down(dc);
913                                         break;
914                                 }
915
916                         }
917                 }
918         }
919
920         for (i = 0; i < res_pool->audio_count; i++) {
921                 struct audio *audio = res_pool->audios[i];
922
923                 audio->funcs->hw_init(audio);
924         }
925
926         for (i = 0; i < dc->link_count; i++) {
927                 struct dc_link *link = dc->links[i];
928
929                 if (link->panel_cntl)
930                         backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
931         }
932
933         for (i = 0; i < dc->res_pool->pipe_count; i++) {
934                 if (abms[i] != NULL && abms[i]->funcs != NULL)
935                         abms[i]->funcs->abm_init(abms[i], backlight);
936         }
937
938         /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
939         REG_WRITE(DIO_MEM_PWR_CTRL, 0);
940
941         if (!dc->debug.disable_clock_gate) {
942                 /* enable all DCN clock gating */
943                 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
944
945                 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
946
947                 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
948         }
949
950         if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
951                 dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
952
953         if (dc->clk_mgr->funcs->notify_wm_ranges)
954                 dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
955
956         if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
957                 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
958
959         if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
960                 dc->res_pool->hubbub->funcs->force_pstate_change_control(
961                                 dc->res_pool->hubbub, false, false);
962
963         if (dc->res_pool->hubbub->funcs->init_crb)
964                 dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
965
966         if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0)
967                 dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, dc->ctx->dc_bios->vram_info.num_chans, dc->config.sdpif_request_limit_words_per_umc);
968
969         // Get DMCUB capabilities
970         if (dc->ctx->dmub_srv) {
971                 dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
972                 dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
973                 dc->caps.dmub_caps.subvp_psr = dc->ctx->dmub_srv->dmub->feature_caps.subvp_psr_support;
974                 dc->caps.dmub_caps.gecc_enable = dc->ctx->dmub_srv->dmub->feature_caps.gecc_enable;
975                 dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
976         }
977 }
978
979 static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
980                 int opp_cnt)
981 {
982         bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
983         int flow_ctrl_cnt;
984
985         if (opp_cnt >= 2)
986                 hblank_halved = true;
987
988         flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
989                         stream->timing.h_border_left -
990                         stream->timing.h_border_right;
991
992         if (hblank_halved)
993                 flow_ctrl_cnt /= 2;
994
995         /* ODM combine 4:1 case */
996         if (opp_cnt == 4)
997                 flow_ctrl_cnt /= 2;
998
999         return flow_ctrl_cnt;
1000 }
1001
1002 static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
1003 {
1004         struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
1005         struct dc_stream_state *stream = pipe_ctx->stream;
1006         struct pipe_ctx *odm_pipe;
1007         int opp_cnt = 1;
1008
1009         ASSERT(dsc);
1010         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1011                 opp_cnt++;
1012
1013         if (enable) {
1014                 struct dsc_config dsc_cfg;
1015                 struct dsc_optc_config dsc_optc_cfg;
1016                 enum optc_dsc_mode optc_dsc_mode;
1017
1018                 /* Enable DSC hw block */
1019                 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
1020                 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
1021                 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
1022                 dsc_cfg.color_depth = stream->timing.display_color_depth;
1023                 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
1024                 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
1025                 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
1026                 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
1027
1028                 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
1029                 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
1030                 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1031                         struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
1032
1033                         ASSERT(odm_dsc);
1034                         odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
1035                         odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
1036                 }
1037                 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
1038                 dsc_cfg.pic_width *= opp_cnt;
1039
1040                 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
1041
1042                 /* Enable DSC in OPTC */
1043                 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
1044                 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
1045                                                         optc_dsc_mode,
1046                                                         dsc_optc_cfg.bytes_per_pixel,
1047                                                         dsc_optc_cfg.slice_width);
1048         } else {
1049                 /* disable DSC in OPTC */
1050                 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
1051                                 pipe_ctx->stream_res.tg,
1052                                 OPTC_DSC_DISABLED, 0, 0);
1053
1054                 /* disable DSC block */
1055                 dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
1056                 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1057                         ASSERT(odm_pipe->stream_res.dsc);
1058                         odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
1059                 }
1060         }
1061 }
1062
1063 /*
1064 * Given any pipe_ctx, return the total ODM combine factor, and optionally return
1065 * the OPPids which are used
1066 * */
1067 static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_instances)
1068 {
1069         unsigned int opp_count = 1;
1070         struct pipe_ctx *odm_pipe;
1071
1072         /* First get to the top pipe */
1073         for (odm_pipe = pipe_ctx; odm_pipe->prev_odm_pipe; odm_pipe = odm_pipe->prev_odm_pipe)
1074                 ;
1075
1076         /* First pipe is always used */
1077         if (opp_instances)
1078                 opp_instances[0] = odm_pipe->stream_res.opp->inst;
1079
1080         /* Find and count odm pipes, if any */
1081         for (odm_pipe = odm_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1082                 if (opp_instances)
1083                         opp_instances[opp_count] = odm_pipe->stream_res.opp->inst;
1084                 opp_count++;
1085         }
1086
1087         return opp_count;
1088 }
1089
1090 void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
1091 {
1092         struct pipe_ctx *odm_pipe;
1093         int opp_cnt = 0;
1094         int opp_inst[MAX_PIPES] = {0};
1095         bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
1096         struct mpc_dwb_flow_control flow_control;
1097         struct mpc *mpc = dc->res_pool->mpc;
1098         int i;
1099
1100         opp_cnt = get_odm_config(pipe_ctx, opp_inst);
1101
1102         if (opp_cnt > 1)
1103                 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
1104                                 pipe_ctx->stream_res.tg,
1105                                 opp_inst, opp_cnt,
1106                                 &pipe_ctx->stream->timing);
1107         else
1108                 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
1109                                 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1110
1111         rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
1112         flow_control.flow_ctrl_mode = 0;
1113         flow_control.flow_ctrl_cnt0 = 0x80;
1114         flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, opp_cnt);
1115         if (mpc->funcs->set_out_rate_control) {
1116                 for (i = 0; i < opp_cnt; ++i) {
1117                         mpc->funcs->set_out_rate_control(
1118                                         mpc, opp_inst[i],
1119                                         true,
1120                                         rate_control_2x_pclk,
1121                                         &flow_control);
1122                 }
1123         }
1124
1125         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1126                 odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
1127                                 odm_pipe->stream_res.opp,
1128                                 true);
1129         }
1130
1131         if (pipe_ctx->stream_res.dsc) {
1132                 struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
1133
1134                 update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC);
1135
1136                 /* Check if no longer using pipe for ODM, then need to disconnect DSC for that pipe */
1137                 if (!pipe_ctx->next_odm_pipe && current_pipe_ctx->next_odm_pipe &&
1138                                 current_pipe_ctx->next_odm_pipe->stream_res.dsc) {
1139                         struct display_stream_compressor *dsc = current_pipe_ctx->next_odm_pipe->stream_res.dsc;
1140                         /* disconnect DSC block from stream */
1141                         dsc->funcs->dsc_disconnect(dsc);
1142                 }
1143         }
1144 }
1145
1146 unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
1147 {
1148         struct dc_stream_state *stream = pipe_ctx->stream;
1149         unsigned int odm_combine_factor = 0;
1150         bool two_pix_per_container = false;
1151
1152         two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
1153         odm_combine_factor = get_odm_config(pipe_ctx, NULL);
1154
1155         if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
1156                 *k1_div = PIXEL_RATE_DIV_BY_1;
1157                 *k2_div = PIXEL_RATE_DIV_BY_1;
1158         } else if (dc_is_hdmi_tmds_signal(stream->signal) || dc_is_dvi_signal(stream->signal)) {
1159                 *k1_div = PIXEL_RATE_DIV_BY_1;
1160                 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
1161                         *k2_div = PIXEL_RATE_DIV_BY_2;
1162                 else
1163                         *k2_div = PIXEL_RATE_DIV_BY_4;
1164         } else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) {
1165                 if (two_pix_per_container) {
1166                         *k1_div = PIXEL_RATE_DIV_BY_1;
1167                         *k2_div = PIXEL_RATE_DIV_BY_2;
1168                 } else {
1169                         *k1_div = PIXEL_RATE_DIV_BY_1;
1170                         *k2_div = PIXEL_RATE_DIV_BY_4;
1171                         if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
1172                                 *k2_div = PIXEL_RATE_DIV_BY_2;
1173                 }
1174         }
1175
1176         if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA))
1177                 ASSERT(false);
1178
1179         return odm_combine_factor;
1180 }
1181
1182 void dcn32_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
1183 {
1184         uint32_t pix_per_cycle = 1;
1185         uint32_t odm_combine_factor = 1;
1186
1187         if (!pipe_ctx || !pipe_ctx->stream || !pipe_ctx->stream_res.stream_enc)
1188                 return;
1189
1190         odm_combine_factor = get_odm_config(pipe_ctx, NULL);
1191         if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1
1192                 || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
1193                 pix_per_cycle = 2;
1194
1195         if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
1196                 pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc,
1197                                 pix_per_cycle);
1198 }
1199
1200 void dcn32_resync_fifo_dccg_dio(struct dce_hwseq *hws, struct dc *dc, struct dc_state *context)
1201 {
1202         unsigned int i;
1203         struct pipe_ctx *pipe = NULL;
1204         bool otg_disabled[MAX_PIPES] = {false};
1205
1206         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1207                 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1208
1209                 if (!resource_is_pipe_type(pipe, OTG_MASTER))
1210                         continue;
1211
1212                 if ((pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))
1213                         && pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
1214                         pipe->stream_res.tg->funcs->disable_crtc(pipe->stream_res.tg);
1215                         reset_sync_context_for_pipe(dc, context, i);
1216                         otg_disabled[i] = true;
1217                 }
1218         }
1219
1220         hws->ctx->dc->res_pool->dccg->funcs->trigger_dio_fifo_resync(hws->ctx->dc->res_pool->dccg);
1221
1222         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1223                 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1224
1225                 if (otg_disabled[i])
1226                         pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
1227         }
1228 }
1229
1230 void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
1231                 struct dc_link_settings *link_settings)
1232 {
1233         struct encoder_unblank_param params = {0};
1234         struct dc_stream_state *stream = pipe_ctx->stream;
1235         struct dc_link *link = stream->link;
1236         struct dce_hwseq *hws = link->dc->hwseq;
1237         struct pipe_ctx *odm_pipe;
1238         uint32_t pix_per_cycle = 1;
1239
1240         params.opp_cnt = 1;
1241         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1242                 params.opp_cnt++;
1243
1244         /* only 3 items below are used by unblank */
1245         params.timing = pipe_ctx->stream->timing;
1246
1247         params.link_settings.link_rate = link_settings->link_rate;
1248
1249         if (link->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
1250                 /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */
1251                 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank(
1252                                 pipe_ctx->stream_res.hpo_dp_stream_enc,
1253                                 pipe_ctx->stream_res.tg->inst);
1254         } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1255                 if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1
1256                         || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
1257                         params.timing.pix_clk_100hz /= 2;
1258                         pix_per_cycle = 2;
1259                 }
1260                 pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
1261                                 pipe_ctx->stream_res.stream_enc, pix_per_cycle > 1);
1262                 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
1263         }
1264
1265         if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP)
1266                 hws->funcs.edp_backlight_control(link, true);
1267 }
1268
1269 bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
1270 {
1271         struct dc *dc = pipe_ctx->stream->ctx->dc;
1272
1273         if (!is_h_timing_divisible_by_2(pipe_ctx->stream))
1274                 return false;
1275
1276         if (dc_is_dp_signal(pipe_ctx->stream->signal) && !dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) &&
1277                 dc->debug.enable_dp_dig_pixel_rate_div_policy)
1278                 return true;
1279         return false;
1280 }
1281
1282 static void apply_symclk_on_tx_off_wa(struct dc_link *link)
1283 {
1284         /* There are use cases where SYMCLK is referenced by OTG. For instance
1285          * for TMDS signal, OTG relies SYMCLK even if TX video output is off.
1286          * However current link interface will power off PHY when disabling link
1287          * output. This will turn off SYMCLK generated by PHY. The workaround is
1288          * to identify such case where SYMCLK is still in use by OTG when we
1289          * power off PHY. When this is detected, we will temporarily power PHY
1290          * back on and move PHY's SYMCLK state to SYMCLK_ON_TX_OFF by calling
1291          * program_pix_clk interface. When OTG is disabled, we will then power
1292          * off PHY by calling disable link output again.
1293          *
1294          * In future dcn generations, we plan to rework transmitter control
1295          * interface so that we could have an option to set SYMCLK ON TX OFF
1296          * state in one step without this workaround
1297          */
1298
1299         struct dc *dc = link->ctx->dc;
1300         struct pipe_ctx *pipe_ctx = NULL;
1301         uint8_t i;
1302
1303         if (link->phy_state.symclk_ref_cnts.otg > 0) {
1304                 for (i = 0; i < MAX_PIPES; i++) {
1305                         pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1306                         if (resource_is_pipe_type(pipe_ctx, OPP_HEAD) && pipe_ctx->stream->link == link) {
1307                                 pipe_ctx->clock_source->funcs->program_pix_clk(
1308                                                 pipe_ctx->clock_source,
1309                                                 &pipe_ctx->stream_res.pix_clk_params,
1310                                                 dc->link_srv->dp_get_encoding_format(
1311                                                                 &pipe_ctx->link_config.dp_link_settings),
1312                                                 &pipe_ctx->pll_settings);
1313                                 link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
1314                                 break;
1315                         }
1316                 }
1317         }
1318 }
1319
1320 void dcn32_disable_link_output(struct dc_link *link,
1321                 const struct link_resource *link_res,
1322                 enum signal_type signal)
1323 {
1324         struct dc *dc = link->ctx->dc;
1325         const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
1326         struct dmcu *dmcu = dc->res_pool->dmcu;
1327
1328         if (signal == SIGNAL_TYPE_EDP &&
1329                         link->dc->hwss.edp_backlight_control)
1330                 link->dc->hwss.edp_backlight_control(link, false);
1331         else if (dmcu != NULL && dmcu->funcs->lock_phy)
1332                 dmcu->funcs->lock_phy(dmcu);
1333
1334         link_hwss->disable_link_output(link, link_res, signal);
1335         link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
1336
1337         if (signal == SIGNAL_TYPE_EDP &&
1338                         link->dc->hwss.edp_backlight_control)
1339                 link->dc->hwss.edp_power_control(link, false);
1340         else if (dmcu != NULL && dmcu->funcs->lock_phy)
1341                 dmcu->funcs->unlock_phy(dmcu);
1342
1343         dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
1344
1345         apply_symclk_on_tx_off_wa(link);
1346 }
1347
1348 /* For SubVP the main pipe can have a viewport position change
1349  * without a full update. In this case we must also update the
1350  * viewport positions for the phantom pipe accordingly.
1351  */
1352 void dcn32_update_phantom_vp_position(struct dc *dc,
1353                 struct dc_state *context,
1354                 struct pipe_ctx *phantom_pipe)
1355 {
1356         uint32_t i;
1357         struct dc_plane_state *phantom_plane = phantom_pipe->plane_state;
1358
1359         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1360                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1361
1362                 if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN &&
1363                                 pipe->stream->mall_stream_config.paired_stream == phantom_pipe->stream) {
1364                         if (pipe->plane_state && pipe->plane_state->update_flags.bits.position_change) {
1365
1366                                 phantom_plane->src_rect.x = pipe->plane_state->src_rect.x;
1367                                 phantom_plane->src_rect.y = pipe->plane_state->src_rect.y;
1368                                 phantom_plane->clip_rect.x = pipe->plane_state->clip_rect.x;
1369                                 phantom_plane->dst_rect.x = pipe->plane_state->dst_rect.x;
1370                                 phantom_plane->dst_rect.y = pipe->plane_state->dst_rect.y;
1371
1372                                 phantom_pipe->plane_state->update_flags.bits.position_change = 1;
1373                                 resource_build_scaling_params(phantom_pipe);
1374                                 return;
1375                         }
1376                 }
1377         }
1378 }
1379
1380 /* Treat the phantom pipe as if it needs to be fully enabled.
1381  * If the pipe was previously in use but not phantom, it would
1382  * have been disabled earlier in the sequence so we need to run
1383  * the full enable sequence.
1384  */
1385 void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe)
1386 {
1387         phantom_pipe->update_flags.raw = 0;
1388         if (phantom_pipe->stream && phantom_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
1389                 if (resource_is_pipe_type(phantom_pipe, DPP_PIPE)) {
1390                         phantom_pipe->update_flags.bits.enable = 1;
1391                         phantom_pipe->update_flags.bits.mpcc = 1;
1392                         phantom_pipe->update_flags.bits.dppclk = 1;
1393                         phantom_pipe->update_flags.bits.hubp_interdependent = 1;
1394                         phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
1395                         phantom_pipe->update_flags.bits.gamut_remap = 1;
1396                         phantom_pipe->update_flags.bits.scaler = 1;
1397                         phantom_pipe->update_flags.bits.viewport = 1;
1398                         phantom_pipe->update_flags.bits.det_size = 1;
1399                         if (resource_is_pipe_type(phantom_pipe, OTG_MASTER)) {
1400                                 phantom_pipe->update_flags.bits.odm = 1;
1401                                 phantom_pipe->update_flags.bits.global_sync = 1;
1402                         }
1403                 }
1404         }
1405 }
1406
1407 bool dcn32_dsc_pg_status(
1408                 struct dce_hwseq *hws,
1409                 unsigned int dsc_inst)
1410 {
1411         uint32_t pwr_status = 0;
1412
1413         switch (dsc_inst) {
1414         case 0: /* DSC0 */
1415                 REG_GET(DOMAIN16_PG_STATUS,
1416                                 DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
1417                 break;
1418         case 1: /* DSC1 */
1419
1420                 REG_GET(DOMAIN17_PG_STATUS,
1421                                 DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
1422                 break;
1423         case 2: /* DSC2 */
1424                 REG_GET(DOMAIN18_PG_STATUS,
1425                                 DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
1426                 break;
1427         case 3: /* DSC3 */
1428                 REG_GET(DOMAIN19_PG_STATUS,
1429                                 DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
1430                 break;
1431         default:
1432                 BREAK_TO_DEBUGGER();
1433                 break;
1434         }
1435
1436         return pwr_status == 0;
1437 }
1438
1439 void dcn32_update_dsc_pg(struct dc *dc,
1440                 struct dc_state *context,
1441                 bool safe_to_disable)
1442 {
1443         struct dce_hwseq *hws = dc->hwseq;
1444         int i;
1445
1446         for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
1447                 struct display_stream_compressor *dsc = dc->res_pool->dscs[i];
1448                 bool is_dsc_ungated = hws->funcs.dsc_pg_status(hws, dsc->inst);
1449
1450                 if (context->res_ctx.is_dsc_acquired[i]) {
1451                         if (!is_dsc_ungated) {
1452                                 hws->funcs.dsc_pg_control(hws, dsc->inst, true);
1453                         }
1454                 } else if (safe_to_disable) {
1455                         if (is_dsc_ungated) {
1456                                 hws->funcs.dsc_pg_control(hws, dsc->inst, false);
1457                         }
1458                 }
1459         }
1460 }
1461
1462 void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context)
1463 {
1464         unsigned int i;
1465
1466         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1467                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1468                 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1469
1470                 /* If an active, non-phantom pipe is being transitioned into a phantom
1471                  * pipe, wait for the double buffer update to complete first before we do
1472                  * ANY phantom pipe programming.
1473                  */
1474                 if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM &&
1475                                 old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
1476                         old_pipe->stream_res.tg->funcs->wait_for_state(
1477                                         old_pipe->stream_res.tg,
1478                                         CRTC_STATE_VBLANK);
1479                         old_pipe->stream_res.tg->funcs->wait_for_state(
1480                                         old_pipe->stream_res.tg,
1481                                         CRTC_STATE_VACTIVE);
1482                 }
1483         }
1484         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1485                 struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
1486
1487                 if (new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
1488                         // If old context or new context has phantom pipes, apply
1489                         // the phantom timings now. We can't change the phantom
1490                         // pipe configuration safely without driver acquiring
1491                         // the DMCUB lock first.
1492                         dc->hwss.apply_ctx_to_hw(dc, context);
1493                         break;
1494                 }
1495         }
1496 }
1497
1498 /* Blank pixel data during initialization */
1499 void dcn32_init_blank(
1500                 struct dc *dc,
1501                 struct timing_generator *tg)
1502 {
1503         struct dce_hwseq *hws = dc->hwseq;
1504         enum dc_color_space color_space;
1505         struct tg_color black_color = {0};
1506         struct output_pixel_processor *opp = NULL;
1507         struct output_pixel_processor *bottom_opp = NULL;
1508         uint32_t num_opps, opp_id_src0, opp_id_src1;
1509         uint32_t otg_active_width, otg_active_height;
1510         uint32_t i;
1511
1512         /* program opp dpg blank color */
1513         color_space = COLOR_SPACE_SRGB;
1514         color_space_to_black_color(dc, color_space, &black_color);
1515
1516         /* get the OTG active size */
1517         tg->funcs->get_otg_active_size(tg,
1518                         &otg_active_width,
1519                         &otg_active_height);
1520
1521         /* get the OPTC source */
1522         tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
1523
1524         if (opp_id_src0 >= dc->res_pool->res_cap->num_opp) {
1525                 ASSERT(false);
1526                 return;
1527         }
1528
1529         for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
1530                 if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src0) {
1531                         opp = dc->res_pool->opps[i];
1532                         break;
1533                 }
1534         }
1535
1536         if (num_opps == 2) {
1537                 otg_active_width = otg_active_width / 2;
1538
1539                 if (opp_id_src1 >= dc->res_pool->res_cap->num_opp) {
1540                         ASSERT(false);
1541                         return;
1542                 }
1543                 for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
1544                         if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src1) {
1545                                 bottom_opp = dc->res_pool->opps[i];
1546                                 break;
1547                         }
1548                 }
1549         }
1550
1551         if (opp && opp->funcs->opp_set_disp_pattern_generator)
1552                 opp->funcs->opp_set_disp_pattern_generator(
1553                                 opp,
1554                                 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
1555                                 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
1556                                 COLOR_DEPTH_UNDEFINED,
1557                                 &black_color,
1558                                 otg_active_width,
1559                                 otg_active_height,
1560                                 0);
1561
1562         if (num_opps == 2) {
1563                 if (bottom_opp && bottom_opp->funcs->opp_set_disp_pattern_generator) {
1564                         bottom_opp->funcs->opp_set_disp_pattern_generator(
1565                                         bottom_opp,
1566                                         CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
1567                                         CONTROLLER_DP_COLOR_SPACE_UDEFINED,
1568                                         COLOR_DEPTH_UNDEFINED,
1569                                         &black_color,
1570                                         otg_active_width,
1571                                         otg_active_height,
1572                                         0);
1573                         hws->funcs.wait_for_blank_complete(bottom_opp);
1574                 }
1575         }
1576
1577         if (opp)
1578                 hws->funcs.wait_for_blank_complete(opp);
1579 }
1580
1581 void dcn32_blank_phantom(struct dc *dc,
1582                 struct timing_generator *tg,
1583                 int width,
1584                 int height)
1585 {
1586         struct dce_hwseq *hws = dc->hwseq;
1587         enum dc_color_space color_space;
1588         struct tg_color black_color = {0};
1589         struct output_pixel_processor *opp = NULL;
1590         uint32_t num_opps, opp_id_src0, opp_id_src1;
1591         uint32_t otg_active_width, otg_active_height;
1592         uint32_t i;
1593
1594         /* program opp dpg blank color */
1595         color_space = COLOR_SPACE_SRGB;
1596         color_space_to_black_color(dc, color_space, &black_color);
1597
1598         otg_active_width = width;
1599         otg_active_height = height;
1600
1601         /* get the OPTC source */
1602         tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
1603         ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp);
1604
1605         for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
1606                 if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src0) {
1607                         opp = dc->res_pool->opps[i];
1608                         break;
1609                 }
1610         }
1611
1612         if (opp && opp->funcs->opp_set_disp_pattern_generator)
1613                 opp->funcs->opp_set_disp_pattern_generator(
1614                                 opp,
1615                                 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
1616                                 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
1617                                 COLOR_DEPTH_UNDEFINED,
1618                                 &black_color,
1619                                 otg_active_width,
1620                                 otg_active_height,
1621                                 0);
1622
1623         if (tg->funcs->is_tg_enabled(tg))
1624                 hws->funcs.wait_for_blank_complete(opp);
1625 }
1626
1627 bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc,
1628                 const struct dc_state *cur_ctx,
1629                 const struct dc_state *new_ctx)
1630 {
1631         int i;
1632         const struct pipe_ctx *cur_pipe, *new_pipe;
1633         bool is_seamless = true;
1634
1635         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1636                 cur_pipe = &cur_ctx->res_ctx.pipe_ctx[i];
1637                 new_pipe = &new_ctx->res_ctx.pipe_ctx[i];
1638
1639                 if (resource_is_pipe_type(cur_pipe, FREE_PIPE) ||
1640                                 resource_is_pipe_type(new_pipe, FREE_PIPE))
1641                         /* adding or removing free pipes is always seamless */
1642                         continue;
1643                 else if (resource_is_pipe_type(cur_pipe, OTG_MASTER)) {
1644                         if (resource_is_pipe_type(new_pipe, OTG_MASTER))
1645                                 if (cur_pipe->stream->stream_id == new_pipe->stream->stream_id)
1646                                 /* OTG master with the same stream is seamless */
1647                                         continue;
1648                 } else if (resource_is_pipe_type(cur_pipe, OPP_HEAD)) {
1649                         if (resource_is_pipe_type(new_pipe, OPP_HEAD)) {
1650                                 if (cur_pipe->stream_res.tg == new_pipe->stream_res.tg)
1651                                         /*
1652                                          * OPP heads sharing the same timing
1653                                          * generator is seamless
1654                                          */
1655                                         continue;
1656                         }
1657                 } else if (resource_is_pipe_type(cur_pipe, DPP_PIPE)) {
1658                         if (resource_is_pipe_type(new_pipe, DPP_PIPE)) {
1659                                 if (cur_pipe->stream_res.opp == new_pipe->stream_res.opp)
1660                                         /*
1661                                          * DPP pipes sharing the same OPP head is
1662                                          * seamless
1663                                          */
1664                                         continue;
1665                         }
1666                 }
1667
1668                 /*
1669                  * This pipe's transition doesn't fall under any seamless
1670                  * conditions
1671                  */
1672                 is_seamless = false;
1673                 break;
1674         }
1675
1676         return is_seamless;
1677 }