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