drm/amd/dc: hw_sequencer: fix semicolon.cocci warnings
[linux-2.6-block.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_hw_sequencer.c
1 /*
2  * Copyright 2015 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 #include "dm_services.h"
26 #include "dc.h"
27 #include "dc_bios_types.h"
28 #include "core_types.h"
29 #include "core_status.h"
30 #include "resource.h"
31 #include "hw_sequencer.h"
32 #include "dm_helpers.h"
33 #include "dce110_hw_sequencer.h"
34 #include "dce110_timing_generator.h"
35
36 #include "bios/bios_parser_helper.h"
37 #include "timing_generator.h"
38 #include "mem_input.h"
39 #include "opp.h"
40 #include "ipp.h"
41 #include "transform.h"
42 #include "stream_encoder.h"
43 #include "link_encoder.h"
44 #include "clock_source.h"
45 #include "abm.h"
46 #include "audio.h"
47 #include "dce/dce_hwseq.h"
48
49 /* include DCE11 register header files */
50 #include "dce/dce_11_0_d.h"
51 #include "dce/dce_11_0_sh_mask.h"
52 #include "custom_float.h"
53
54 struct dce110_hw_seq_reg_offsets {
55         uint32_t crtc;
56 };
57
58 static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
59 {
60         .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
61 },
62 {
63         .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
64 },
65 {
66         .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
67 },
68 {
69         .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
70 }
71 };
72
73 #define HW_REG_BLND(reg, id)\
74         (reg + reg_offsets[id].blnd)
75
76 #define HW_REG_CRTC(reg, id)\
77         (reg + reg_offsets[id].crtc)
78
79 #define MAX_WATERMARK 0xFFFF
80 #define SAFE_NBP_MARK 0x7FFF
81
82 /*******************************************************************************
83  * Private definitions
84  ******************************************************************************/
85 /***************************PIPE_CONTROL***********************************/
86 static void dce110_init_pte(struct dc_context *ctx)
87 {
88         uint32_t addr;
89         uint32_t value = 0;
90         uint32_t chunk_int = 0;
91         uint32_t chunk_mul = 0;
92
93         addr = mmUNP_DVMM_PTE_CONTROL;
94         value = dm_read_reg(ctx, addr);
95
96         set_reg_field_value(
97                 value,
98                 0,
99                 DVMM_PTE_CONTROL,
100                 DVMM_USE_SINGLE_PTE);
101
102         set_reg_field_value(
103                 value,
104                 1,
105                 DVMM_PTE_CONTROL,
106                 DVMM_PTE_BUFFER_MODE0);
107
108         set_reg_field_value(
109                 value,
110                 1,
111                 DVMM_PTE_CONTROL,
112                 DVMM_PTE_BUFFER_MODE1);
113
114         dm_write_reg(ctx, addr, value);
115
116         addr = mmDVMM_PTE_REQ;
117         value = dm_read_reg(ctx, addr);
118
119         chunk_int = get_reg_field_value(
120                 value,
121                 DVMM_PTE_REQ,
122                 HFLIP_PTEREQ_PER_CHUNK_INT);
123
124         chunk_mul = get_reg_field_value(
125                 value,
126                 DVMM_PTE_REQ,
127                 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
128
129         if (chunk_int != 0x4 || chunk_mul != 0x4) {
130
131                 set_reg_field_value(
132                         value,
133                         255,
134                         DVMM_PTE_REQ,
135                         MAX_PTEREQ_TO_ISSUE);
136
137                 set_reg_field_value(
138                         value,
139                         4,
140                         DVMM_PTE_REQ,
141                         HFLIP_PTEREQ_PER_CHUNK_INT);
142
143                 set_reg_field_value(
144                         value,
145                         4,
146                         DVMM_PTE_REQ,
147                         HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
148
149                 dm_write_reg(ctx, addr, value);
150         }
151 }
152 /**************************************************************************/
153
154 static void enable_display_pipe_clock_gating(
155         struct dc_context *ctx,
156         bool clock_gating)
157 {
158         /*TODO*/
159 }
160
161 static bool dce110_enable_display_power_gating(
162         struct core_dc *dc,
163         uint8_t controller_id,
164         struct dc_bios *dcb,
165         enum pipe_gating_control power_gating)
166 {
167         enum bp_result bp_result = BP_RESULT_OK;
168         enum bp_pipe_control_action cntl;
169         struct dc_context *ctx = dc->ctx;
170         unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
171
172         if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
173                 return true;
174
175         if (power_gating == PIPE_GATING_CONTROL_INIT)
176                 cntl = ASIC_PIPE_INIT;
177         else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
178                 cntl = ASIC_PIPE_ENABLE;
179         else
180                 cntl = ASIC_PIPE_DISABLE;
181
182         if (controller_id == underlay_idx)
183                 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
184
185         if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
186
187                 bp_result = dcb->funcs->enable_disp_power_gating(
188                                                 dcb, controller_id + 1, cntl);
189
190                 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
191                  * by default when command table is called
192                  *
193                  * Bios parser accepts controller_id = 6 as indicative of
194                  * underlay pipe in dce110. But we do not support more
195                  * than 3.
196                  */
197                 if (controller_id < CONTROLLER_ID_MAX - 1)
198                         dm_write_reg(ctx,
199                                 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
200                                 0);
201         }
202
203         if (power_gating != PIPE_GATING_CONTROL_ENABLE)
204                 dce110_init_pte(ctx);
205
206         if (bp_result == BP_RESULT_OK)
207                 return true;
208         else
209                 return false;
210 }
211
212 static void build_prescale_params(struct ipp_prescale_params *prescale_params,
213                 const struct core_surface *surface)
214 {
215         prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
216
217         switch (surface->public.format) {
218         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
219         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
220                 prescale_params->scale = 0x2020;
221                 break;
222         case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
223         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
224                 prescale_params->scale = 0x2008;
225                 break;
226         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
227         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
228                 prescale_params->scale = 0x2000;
229                 break;
230         default:
231                 ASSERT(false);
232                 break;
233         }
234 }
235
236 static bool dce110_set_input_transfer_func(
237         struct pipe_ctx *pipe_ctx,
238         const struct core_surface *surface)
239 {
240         struct input_pixel_processor *ipp = pipe_ctx->ipp;
241         const struct core_transfer_func *tf = NULL;
242         struct ipp_prescale_params prescale_params = { 0 };
243         bool result = true;
244
245         if (ipp == NULL)
246                 return false;
247
248         if (surface->public.in_transfer_func)
249                 tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
250
251         build_prescale_params(&prescale_params, surface);
252         ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
253
254         if (surface->public.gamma_correction)
255             ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction);
256
257         if (tf == NULL) {
258                 /* Default case if no input transfer function specified */
259                 ipp->funcs->ipp_set_degamma(ipp,
260                                 IPP_DEGAMMA_MODE_HW_sRGB);
261         } else if (tf->public.type == TF_TYPE_PREDEFINED) {
262                 switch (tf->public.tf) {
263                 case TRANSFER_FUNCTION_SRGB:
264                         ipp->funcs->ipp_set_degamma(ipp,
265                                         IPP_DEGAMMA_MODE_HW_sRGB);
266                         break;
267                 case TRANSFER_FUNCTION_BT709:
268                         ipp->funcs->ipp_set_degamma(ipp,
269                                         IPP_DEGAMMA_MODE_HW_xvYCC);
270                         break;
271                 case TRANSFER_FUNCTION_LINEAR:
272                         ipp->funcs->ipp_set_degamma(ipp,
273                                         IPP_DEGAMMA_MODE_BYPASS);
274                         break;
275                 case TRANSFER_FUNCTION_PQ:
276                         result = false;
277                         break;
278                 default:
279                         result = false;
280                         break;
281                 }
282         } else {
283                 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
284                 result = false;
285         }
286
287         return result;
288 }
289
290 static bool convert_to_custom_float(
291                 struct pwl_result_data *rgb_resulted,
292                 struct curve_points *arr_points,
293                 uint32_t hw_points_num)
294 {
295         struct custom_float_format fmt;
296
297         struct pwl_result_data *rgb = rgb_resulted;
298
299         uint32_t i = 0;
300
301         fmt.exponenta_bits = 6;
302         fmt.mantissa_bits = 12;
303         fmt.sign = true;
304
305         if (!convert_to_custom_float_format(
306                 arr_points[0].x,
307                 &fmt,
308                 &arr_points[0].custom_float_x)) {
309                 BREAK_TO_DEBUGGER();
310                 return false;
311         }
312
313         if (!convert_to_custom_float_format(
314                 arr_points[0].offset,
315                 &fmt,
316                 &arr_points[0].custom_float_offset)) {
317                 BREAK_TO_DEBUGGER();
318                 return false;
319         }
320
321         if (!convert_to_custom_float_format(
322                 arr_points[0].slope,
323                 &fmt,
324                 &arr_points[0].custom_float_slope)) {
325                 BREAK_TO_DEBUGGER();
326                 return false;
327         }
328
329         fmt.mantissa_bits = 10;
330         fmt.sign = false;
331
332         if (!convert_to_custom_float_format(
333                 arr_points[1].x,
334                 &fmt,
335                 &arr_points[1].custom_float_x)) {
336                 BREAK_TO_DEBUGGER();
337                 return false;
338         }
339
340         if (!convert_to_custom_float_format(
341                 arr_points[1].y,
342                 &fmt,
343                 &arr_points[1].custom_float_y)) {
344                 BREAK_TO_DEBUGGER();
345                 return false;
346         }
347
348         if (!convert_to_custom_float_format(
349                 arr_points[2].slope,
350                 &fmt,
351                 &arr_points[2].custom_float_slope)) {
352                 BREAK_TO_DEBUGGER();
353                 return false;
354         }
355
356         fmt.mantissa_bits = 12;
357         fmt.sign = true;
358
359         while (i != hw_points_num) {
360                 if (!convert_to_custom_float_format(
361                         rgb->red,
362                         &fmt,
363                         &rgb->red_reg)) {
364                         BREAK_TO_DEBUGGER();
365                         return false;
366                 }
367
368                 if (!convert_to_custom_float_format(
369                         rgb->green,
370                         &fmt,
371                         &rgb->green_reg)) {
372                         BREAK_TO_DEBUGGER();
373                         return false;
374                 }
375
376                 if (!convert_to_custom_float_format(
377                         rgb->blue,
378                         &fmt,
379                         &rgb->blue_reg)) {
380                         BREAK_TO_DEBUGGER();
381                         return false;
382                 }
383
384                 if (!convert_to_custom_float_format(
385                         rgb->delta_red,
386                         &fmt,
387                         &rgb->delta_red_reg)) {
388                         BREAK_TO_DEBUGGER();
389                         return false;
390                 }
391
392                 if (!convert_to_custom_float_format(
393                         rgb->delta_green,
394                         &fmt,
395                         &rgb->delta_green_reg)) {
396                         BREAK_TO_DEBUGGER();
397                         return false;
398                 }
399
400                 if (!convert_to_custom_float_format(
401                         rgb->delta_blue,
402                         &fmt,
403                         &rgb->delta_blue_reg)) {
404                         BREAK_TO_DEBUGGER();
405                         return false;
406                 }
407
408                 ++rgb;
409                 ++i;
410         }
411
412         return true;
413 }
414
415 static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func
416                 *output_tf, struct pwl_params *regamma_params)
417 {
418         struct curve_points *arr_points;
419         struct pwl_result_data *rgb_resulted;
420         struct pwl_result_data *rgb;
421         struct pwl_result_data *rgb_plus_1;
422         struct fixed31_32 y_r;
423         struct fixed31_32 y_g;
424         struct fixed31_32 y_b;
425         struct fixed31_32 y1_min;
426         struct fixed31_32 y3_max;
427
428         int32_t segment_start, segment_end;
429         uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points;
430
431         if (output_tf == NULL || regamma_params == NULL)
432                 return false;
433
434         arr_points = regamma_params->arr_points;
435         rgb_resulted = regamma_params->rgb_resulted;
436         hw_points = 0;
437
438         memset(regamma_params, 0, sizeof(struct pwl_params));
439
440         if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
441                 /* 16 segments
442                  * segments are from 2^-11 to 2^5
443                  */
444                 segment_start = -11;
445                 segment_end = 5;
446
447                 seg_distr[0] = 2;
448                 seg_distr[1] = 2;
449                 seg_distr[2] = 2;
450                 seg_distr[3] = 2;
451                 seg_distr[4] = 2;
452                 seg_distr[5] = 2;
453                 seg_distr[6] = 3;
454                 seg_distr[7] = 4;
455                 seg_distr[8] = 4;
456                 seg_distr[9] = 4;
457                 seg_distr[10] = 4;
458                 seg_distr[11] = 5;
459                 seg_distr[12] = 5;
460                 seg_distr[13] = 5;
461                 seg_distr[14] = 5;
462                 seg_distr[15] = 5;
463
464         } else {
465                 /* 10 segments
466                  * segment is from 2^-10 to 2^0
467                  */
468                 segment_start = -10;
469                 segment_end = 0;
470
471                 seg_distr[0] = 3;
472                 seg_distr[1] = 4;
473                 seg_distr[2] = 4;
474                 seg_distr[3] = 4;
475                 seg_distr[4] = 4;
476                 seg_distr[5] = 4;
477                 seg_distr[6] = 4;
478                 seg_distr[7] = 4;
479                 seg_distr[8] = 5;
480                 seg_distr[9] = 5;
481                 seg_distr[10] = -1;
482                 seg_distr[11] = -1;
483                 seg_distr[12] = -1;
484                 seg_distr[13] = -1;
485                 seg_distr[14] = -1;
486                 seg_distr[15] = -1;
487         }
488
489         for (k = 0; k < 16; k++) {
490                 if (seg_distr[k] != -1)
491                         hw_points += (1 << seg_distr[k]);
492         }
493
494         j = 0;
495         for (k = 0; k < (segment_end - segment_start); k++) {
496                 increment = 32 / (1 << seg_distr[k]);
497                 start_index = (segment_start + k + 25) * 32;
498                 for (i = start_index; i < start_index + 32; i += increment) {
499                         if (j == hw_points - 1)
500                                 break;
501                         rgb_resulted[j].red = output_tf->tf_pts.red[i];
502                         rgb_resulted[j].green = output_tf->tf_pts.green[i];
503                         rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
504                         j++;
505                 }
506         }
507
508         /* last point */
509         start_index = (segment_end + 25) * 32;
510         rgb_resulted[hw_points - 1].red =
511                         output_tf->tf_pts.red[start_index];
512         rgb_resulted[hw_points - 1].green =
513                         output_tf->tf_pts.green[start_index];
514         rgb_resulted[hw_points - 1].blue =
515                         output_tf->tf_pts.blue[start_index];
516
517         arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
518                         dal_fixed31_32_from_int(segment_start));
519         arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
520                         dal_fixed31_32_from_int(segment_end));
521         arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
522                         dal_fixed31_32_from_int(segment_end));
523
524         y_r = rgb_resulted[0].red;
525         y_g = rgb_resulted[0].green;
526         y_b = rgb_resulted[0].blue;
527
528         y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
529
530         arr_points[0].y = y1_min;
531         arr_points[0].slope = dal_fixed31_32_div(
532                                         arr_points[0].y,
533                                         arr_points[0].x);
534
535         y_r = rgb_resulted[hw_points - 1].red;
536         y_g = rgb_resulted[hw_points - 1].green;
537         y_b = rgb_resulted[hw_points - 1].blue;
538
539         /* see comment above, m_arrPoints[1].y should be the Y value for the
540          * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
541          */
542         y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
543
544         arr_points[1].y = y3_max;
545         arr_points[2].y = y3_max;
546
547         arr_points[1].slope = dal_fixed31_32_zero;
548         arr_points[2].slope = dal_fixed31_32_zero;
549
550         if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
551                 /* for PQ, we want to have a straight line from last HW X point,
552                  * and the slope to be such that we hit 1.0 at 10000 nits.
553                  */
554                 const struct fixed31_32 end_value =
555                                 dal_fixed31_32_from_int(125);
556
557                 arr_points[1].slope = dal_fixed31_32_div(
558                         dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
559                         dal_fixed31_32_sub(end_value, arr_points[1].x));
560                 arr_points[2].slope = dal_fixed31_32_div(
561                         dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
562                         dal_fixed31_32_sub(end_value, arr_points[1].x));
563         }
564
565         regamma_params->hw_points_num = hw_points;
566
567         i = 1;
568         for (k = 0; k < 16 && i < 16; k++) {
569                 if (seg_distr[k] != -1) {
570                         regamma_params->arr_curve_points[k].segments_num =
571                                         seg_distr[k];
572                         regamma_params->arr_curve_points[i].offset =
573                                         regamma_params->arr_curve_points[k].
574                                         offset + (1 << seg_distr[k]);
575                 }
576                 i++;
577         }
578
579         if (seg_distr[k] != -1)
580                 regamma_params->arr_curve_points[k].segments_num =
581                                 seg_distr[k];
582
583         rgb = rgb_resulted;
584         rgb_plus_1 = rgb_resulted + 1;
585
586         i = 1;
587
588         while (i != hw_points + 1) {
589                 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
590                         rgb_plus_1->red = rgb->red;
591                 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
592                         rgb_plus_1->green = rgb->green;
593                 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
594                         rgb_plus_1->blue = rgb->blue;
595
596                 rgb->delta_red = dal_fixed31_32_sub(
597                         rgb_plus_1->red,
598                         rgb->red);
599                 rgb->delta_green = dal_fixed31_32_sub(
600                         rgb_plus_1->green,
601                         rgb->green);
602                 rgb->delta_blue = dal_fixed31_32_sub(
603                         rgb_plus_1->blue,
604                         rgb->blue);
605
606                 ++rgb_plus_1;
607                 ++rgb;
608                 ++i;
609         }
610
611         convert_to_custom_float(rgb_resulted, arr_points, hw_points);
612
613         return true;
614 }
615
616 static bool dce110_set_output_transfer_func(
617         struct pipe_ctx *pipe_ctx,
618         const struct core_surface *surface, /* Surface - To be removed */
619         const struct core_stream *stream)
620 {
621         struct output_pixel_processor *opp = pipe_ctx->opp;
622
623         opp->funcs->opp_power_on_regamma_lut(opp, true);
624         opp->regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM;
625
626         if (stream->public.out_transfer_func &&
627                 stream->public.out_transfer_func->type ==
628                         TF_TYPE_PREDEFINED &&
629                 stream->public.out_transfer_func->tf ==
630                         TRANSFER_FUNCTION_SRGB) {
631                 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
632         } else if (dce110_translate_regamma_to_hw_format(
633                                 stream->public.out_transfer_func, opp->regamma_params)) {
634                         opp->funcs->opp_program_regamma_pwl(opp, opp->regamma_params);
635                         opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
636         } else {
637                 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
638         }
639
640         opp->funcs->opp_power_on_regamma_lut(opp, false);
641
642         return true;
643 }
644
645 static enum dc_status bios_parser_crtc_source_select(
646                 struct pipe_ctx *pipe_ctx)
647 {
648         struct dc_bios *dcb;
649         /* call VBIOS table to set CRTC source for the HW
650          * encoder block
651          * note: video bios clears all FMT setting here. */
652         struct bp_crtc_source_select crtc_source_select = {0};
653         const struct core_sink *sink = pipe_ctx->stream->sink;
654
655         crtc_source_select.engine_id = pipe_ctx->stream_enc->id;
656         crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1;
657         /*TODO: Need to un-hardcode color depth, dp_audio and account for
658          * the case where signal and sink signal is different (translator
659          * encoder)*/
660         crtc_source_select.signal = pipe_ctx->stream->signal;
661         crtc_source_select.enable_dp_audio = false;
662         crtc_source_select.sink_signal = pipe_ctx->stream->signal;
663         crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
664
665         dcb = sink->ctx->dc_bios;
666
667         if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
668                 dcb,
669                 &crtc_source_select)) {
670                 return DC_ERROR_UNEXPECTED;
671         }
672
673         return DC_OK;
674 }
675
676 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
677 {
678         ASSERT(pipe_ctx->stream);
679
680         if (pipe_ctx->stream_enc == NULL)
681                 return;  /* this is not root pipe */
682
683         if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
684                 pipe_ctx->stream_enc->funcs->update_hdmi_info_packets(
685                         pipe_ctx->stream_enc,
686                         &pipe_ctx->encoder_info_frame);
687         else if (dc_is_dp_signal(pipe_ctx->stream->signal))
688                 pipe_ctx->stream_enc->funcs->update_dp_info_packets(
689                         pipe_ctx->stream_enc,
690                         &pipe_ctx->encoder_info_frame);
691 }
692
693 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
694 {
695         enum dc_lane_count lane_count =
696                 pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count;
697
698         struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
699         struct core_link *link = pipe_ctx->stream->sink->link;
700
701         /* 1. update AVI info frame (HDMI, DP)
702          * we always need to update info frame
703         */
704         uint32_t active_total_with_borders;
705         uint32_t early_control = 0;
706         struct timing_generator *tg = pipe_ctx->tg;
707
708         /* TODOFPGA may change to hwss.update_info_frame */
709         dce110_update_info_frame(pipe_ctx);
710         /* enable early control to avoid corruption on DP monitor*/
711         active_total_with_borders =
712                         timing->h_addressable
713                                 + timing->h_border_left
714                                 + timing->h_border_right;
715
716         if (lane_count != 0)
717                 early_control = active_total_with_borders % lane_count;
718
719         if (early_control == 0)
720                 early_control = lane_count;
721
722         tg->funcs->set_early_control(tg, early_control);
723
724         /* enable audio only within mode set */
725         if (pipe_ctx->audio != NULL) {
726                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
727                         pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc);
728         }
729
730         /* For MST, there are multiply stream go to only one link.
731          * connect DIG back_end to front_end while enable_stream and
732          * disconnect them during disable_stream
733          * BY this, it is logic clean to separate stream and link */
734          link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
735                         pipe_ctx->stream_enc->id, true);
736
737 }
738
739 void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
740 {
741         struct core_stream *stream = pipe_ctx->stream;
742         struct core_link *link = stream->sink->link;
743
744         if (pipe_ctx->audio) {
745                 pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio);
746
747                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
748                         pipe_ctx->stream_enc->funcs->dp_audio_disable(
749                                         pipe_ctx->stream_enc);
750                 else
751                         pipe_ctx->stream_enc->funcs->hdmi_audio_disable(
752                                         pipe_ctx->stream_enc);
753
754                 pipe_ctx->audio = NULL;
755
756                 /* TODO: notify audio driver for if audio modes list changed
757                  * add audio mode list change flag */
758                 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
759                  * stream->stream_engine_id);
760                  */
761         }
762
763         if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
764                 pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets(
765                         pipe_ctx->stream_enc);
766
767         if (dc_is_dp_signal(pipe_ctx->stream->signal))
768                 pipe_ctx->stream_enc->funcs->stop_dp_info_packets(
769                         pipe_ctx->stream_enc);
770
771         pipe_ctx->stream_enc->funcs->audio_mute_control(
772                         pipe_ctx->stream_enc, true);
773
774
775         /* blank at encoder level */
776         if (dc_is_dp_signal(pipe_ctx->stream->signal))
777                 pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc);
778
779         link->link_enc->funcs->connect_dig_be_to_fe(
780                         link->link_enc,
781                         pipe_ctx->stream_enc->id,
782                         false);
783
784 }
785
786 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
787                 struct dc_link_settings *link_settings)
788 {
789         struct encoder_unblank_param params = { { 0 } };
790
791         /* only 3 items below are used by unblank */
792         params.pixel_clk_khz =
793                 pipe_ctx->stream->public.timing.pix_clk_khz;
794         params.link_settings.link_rate = link_settings->link_rate;
795         pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, &params);
796 }
797
798 static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
799 {
800         switch (crtc_id) {
801         case CONTROLLER_ID_D0:
802                 return DTO_SOURCE_ID0;
803         case CONTROLLER_ID_D1:
804                 return DTO_SOURCE_ID1;
805         case CONTROLLER_ID_D2:
806                 return DTO_SOURCE_ID2;
807         case CONTROLLER_ID_D3:
808                 return DTO_SOURCE_ID3;
809         case CONTROLLER_ID_D4:
810                 return DTO_SOURCE_ID4;
811         case CONTROLLER_ID_D5:
812                 return DTO_SOURCE_ID5;
813         default:
814                 return DTO_SOURCE_UNKNOWN;
815         }
816 }
817
818 static void build_audio_output(
819         const struct pipe_ctx *pipe_ctx,
820         struct audio_output *audio_output)
821 {
822         const struct core_stream *stream = pipe_ctx->stream;
823         audio_output->engine_id = pipe_ctx->stream_enc->id;
824
825         audio_output->signal = pipe_ctx->stream->signal;
826
827         /* audio_crtc_info  */
828
829         audio_output->crtc_info.h_total =
830                 stream->public.timing.h_total;
831
832         /*
833          * Audio packets are sent during actual CRTC blank physical signal, we
834          * need to specify actual active signal portion
835          */
836         audio_output->crtc_info.h_active =
837                         stream->public.timing.h_addressable
838                         + stream->public.timing.h_border_left
839                         + stream->public.timing.h_border_right;
840
841         audio_output->crtc_info.v_active =
842                         stream->public.timing.v_addressable
843                         + stream->public.timing.v_border_top
844                         + stream->public.timing.v_border_bottom;
845
846         audio_output->crtc_info.pixel_repetition = 1;
847
848         audio_output->crtc_info.interlaced =
849                         stream->public.timing.flags.INTERLACE;
850
851         audio_output->crtc_info.refresh_rate =
852                 (stream->public.timing.pix_clk_khz*1000)/
853                 (stream->public.timing.h_total*stream->public.timing.v_total);
854
855         audio_output->crtc_info.color_depth =
856                 stream->public.timing.display_color_depth;
857
858         audio_output->crtc_info.requested_pixel_clock =
859                         pipe_ctx->pix_clk_params.requested_pix_clk;
860
861         /*
862          * TODO - Investigate why calculated pixel clk has to be
863          * requested pixel clk
864          */
865         audio_output->crtc_info.calculated_pixel_clock =
866                         pipe_ctx->pix_clk_params.requested_pix_clk;
867
868         if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
869                         pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
870                 audio_output->pll_info.dp_dto_source_clock_in_khz =
871                                 pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency(
872                                                 pipe_ctx->dis_clk);
873         }
874
875         audio_output->pll_info.feed_back_divider =
876                         pipe_ctx->pll_settings.feedback_divider;
877
878         audio_output->pll_info.dto_source =
879                 translate_to_dto_source(
880                         pipe_ctx->pipe_idx + 1);
881
882         /* TODO hard code to enable for now. Need get from stream */
883         audio_output->pll_info.ss_enabled = true;
884
885         audio_output->pll_info.ss_percentage =
886                         pipe_ctx->pll_settings.ss_percentage;
887 }
888
889 static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
890                 struct tg_color *color)
891 {
892         uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4;
893
894         switch (pipe_ctx->scl_data.format) {
895         case PIXEL_FORMAT_ARGB8888:
896                 /* set boarder color to red */
897                 color->color_r_cr = color_value;
898                 break;
899
900         case PIXEL_FORMAT_ARGB2101010:
901                 /* set boarder color to blue */
902                 color->color_b_cb = color_value;
903                 break;
904         case PIXEL_FORMAT_420BPP12:
905                 /* set boarder color to green */
906                 color->color_g_y = color_value;
907                 break;
908         case PIXEL_FORMAT_FP16:
909                 /* set boarder color to white */
910                 color->color_r_cr = color_value;
911                 color->color_b_cb = color_value;
912                 color->color_g_y = color_value;
913                 break;
914         default:
915                 break;
916         }
917 }
918
919 static void program_scaler(const struct core_dc *dc,
920                 const struct pipe_ctx *pipe_ctx)
921 {
922         struct tg_color color = {0};
923
924         if (dc->public.debug.surface_visual_confirm)
925                 get_surface_visual_confirm_color(pipe_ctx, &color);
926         else
927                 color_space_to_black_color(dc,
928                                 pipe_ctx->stream->public.output_color_space,
929                                 &color);
930
931         pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth(
932                 pipe_ctx->xfm,
933                 pipe_ctx->scl_data.lb_params.depth,
934                 &pipe_ctx->stream->bit_depth_params);
935
936         if (pipe_ctx->tg->funcs->set_overscan_blank_color)
937                 pipe_ctx->tg->funcs->set_overscan_blank_color(
938                                 pipe_ctx->tg,
939                                 &color);
940
941         pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm,
942                 &pipe_ctx->scl_data);
943 }
944
945 static enum dc_status dce110_prog_pixclk_crtc_otg(
946                 struct pipe_ctx *pipe_ctx,
947                 struct validate_context *context,
948                 struct core_dc *dc)
949 {
950         struct core_stream *stream = pipe_ctx->stream;
951         struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
952                         pipe_ctx[pipe_ctx->pipe_idx];
953         struct tg_color black_color = {0};
954
955         if (!pipe_ctx_old->stream) {
956
957                 /* program blank color */
958                 color_space_to_black_color(dc,
959                                 stream->public.output_color_space, &black_color);
960                 pipe_ctx->tg->funcs->set_blank_color(
961                                 pipe_ctx->tg,
962                                 &black_color);
963
964                 /*
965                  * Must blank CRTC after disabling power gating and before any
966                  * programming, otherwise CRTC will be hung in bad state
967                  */
968                 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
969
970                 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
971                                 pipe_ctx->clock_source,
972                                 &pipe_ctx->pix_clk_params,
973                                 &pipe_ctx->pll_settings)) {
974                         BREAK_TO_DEBUGGER();
975                         return DC_ERROR_UNEXPECTED;
976                 }
977
978                 pipe_ctx->tg->funcs->program_timing(
979                                 pipe_ctx->tg,
980                                 &stream->public.timing,
981                                 true);
982         }
983
984         if (!pipe_ctx_old->stream) {
985                 if (false == pipe_ctx->tg->funcs->enable_crtc(
986                                 pipe_ctx->tg)) {
987                         BREAK_TO_DEBUGGER();
988                         return DC_ERROR_UNEXPECTED;
989                 }
990         }
991
992         return DC_OK;
993 }
994
995 static enum dc_status apply_single_controller_ctx_to_hw(
996                 struct pipe_ctx *pipe_ctx,
997                 struct validate_context *context,
998                 struct core_dc *dc)
999 {
1000         struct core_stream *stream = pipe_ctx->stream;
1001         struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
1002                         pipe_ctx[pipe_ctx->pipe_idx];
1003
1004         /*  */
1005         dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc);
1006
1007         pipe_ctx->opp->funcs->opp_set_dyn_expansion(
1008                         pipe_ctx->opp,
1009                         COLOR_SPACE_YCBCR601,
1010                         stream->public.timing.display_color_depth,
1011                         pipe_ctx->stream->signal);
1012
1013         pipe_ctx->opp->funcs->opp_program_fmt(
1014                         pipe_ctx->opp,
1015                         &stream->bit_depth_params,
1016                         &stream->clamping);
1017
1018         /* FPGA does not program backend */
1019         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
1020                 return DC_OK;
1021
1022         /* TODO: move to stream encoder */
1023         if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1024                 if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
1025                         BREAK_TO_DEBUGGER();
1026                         return DC_ERROR_UNEXPECTED;
1027                 }
1028
1029         if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1030                 stream->sink->link->link_enc->funcs->setup(
1031                         stream->sink->link->link_enc,
1032                         pipe_ctx->stream->signal);
1033
1034         if (dc_is_dp_signal(pipe_ctx->stream->signal))
1035                 pipe_ctx->stream_enc->funcs->dp_set_stream_attribute(
1036                         pipe_ctx->stream_enc,
1037                         &stream->public.timing,
1038                         stream->public.output_color_space);
1039
1040         if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
1041                 pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute(
1042                         pipe_ctx->stream_enc,
1043                         &stream->public.timing,
1044                         stream->phy_pix_clk,
1045                         pipe_ctx->audio != NULL);
1046
1047         if (dc_is_dvi_signal(pipe_ctx->stream->signal))
1048                 pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute(
1049                         pipe_ctx->stream_enc,
1050                         &stream->public.timing,
1051                         (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
1052                         true : false);
1053
1054         if (!pipe_ctx_old->stream) {
1055                 core_link_enable_stream(pipe_ctx);
1056
1057         resource_build_info_frame(pipe_ctx);
1058         dce110_update_info_frame(pipe_ctx);
1059                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1060                         dce110_unblank_stream(pipe_ctx,
1061                                 &stream->sink->link->public.cur_link_settings);
1062         }
1063
1064         pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1065         /* program_scaler and allocate_mem_input are not new asic */
1066         if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data,
1067                                 &pipe_ctx->scl_data,
1068                                 sizeof(struct scaler_data)) != 0)
1069                 program_scaler(dc, pipe_ctx);
1070
1071         /* mst support - use total stream count */
1072                 pipe_ctx->mi->funcs->allocate_mem_input(
1073                                         pipe_ctx->mi,
1074                                         stream->public.timing.h_total,
1075                                         stream->public.timing.v_total,
1076                                         stream->public.timing.pix_clk_khz,
1077                                         context->stream_count);
1078
1079         return DC_OK;
1080 }
1081
1082 /******************************************************************************/
1083
1084 static void power_down_encoders(struct core_dc *dc)
1085 {
1086         int i;
1087
1088         for (i = 0; i < dc->link_count; i++) {
1089                 dc->links[i]->link_enc->funcs->disable_output(
1090                                 dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
1091         }
1092 }
1093
1094 static void power_down_controllers(struct core_dc *dc)
1095 {
1096         int i;
1097
1098         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1099                 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1100                                 dc->res_pool->timing_generators[i]);
1101         }
1102 }
1103
1104 static void power_down_clock_sources(struct core_dc *dc)
1105 {
1106         int i;
1107
1108         if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1109                 dc->res_pool->dp_clock_source) == false)
1110                 dm_error("Failed to power down pll! (dp clk src)\n");
1111
1112         for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1113                 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1114                                 dc->res_pool->clock_sources[i]) == false)
1115                         dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1116         }
1117 }
1118
1119 static void power_down_all_hw_blocks(struct core_dc *dc)
1120 {
1121         power_down_encoders(dc);
1122
1123         power_down_controllers(dc);
1124
1125         power_down_clock_sources(dc);
1126 }
1127
1128 static void disable_vga_and_power_gate_all_controllers(
1129                 struct core_dc *dc)
1130 {
1131         int i;
1132         struct timing_generator *tg;
1133         struct dc_context *ctx = dc->ctx;
1134
1135         for (i = 0; i < dc->res_pool->pipe_count; i++) {
1136                 tg = dc->res_pool->timing_generators[i];
1137
1138                 tg->funcs->disable_vga(tg);
1139
1140                 /* Enable CLOCK gating for each pipe BEFORE controller
1141                  * powergating. */
1142                 enable_display_pipe_clock_gating(ctx,
1143                                 true);
1144
1145                 dc->hwss.power_down_front_end(
1146                         dc, &dc->current_context->res_ctx.pipe_ctx[i]);
1147         }
1148 }
1149
1150 /**
1151  * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
1152  *  1. Power down all DC HW blocks
1153  *  2. Disable VGA engine on all controllers
1154  *  3. Enable power gating for controller
1155  *  4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
1156  */
1157 void dce110_enable_accelerated_mode(struct core_dc *dc)
1158 {
1159         power_down_all_hw_blocks(dc);
1160
1161         disable_vga_and_power_gate_all_controllers(dc);
1162         bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
1163 }
1164
1165 static uint32_t compute_pstate_blackout_duration(
1166         struct bw_fixed blackout_duration,
1167         const struct core_stream *stream)
1168 {
1169         uint32_t total_dest_line_time_ns;
1170         uint32_t pstate_blackout_duration_ns;
1171
1172         pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1173
1174         total_dest_line_time_ns = 1000000UL *
1175                 stream->public.timing.h_total /
1176                 stream->public.timing.pix_clk_khz +
1177                 pstate_blackout_duration_ns;
1178
1179         return total_dest_line_time_ns;
1180 }
1181
1182 /* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/
1183 int get_bw_result_idx(
1184                 struct resource_context *res_ctx,
1185                 int pipe_idx)
1186 {
1187         int i, collapsed_idx;
1188
1189         if (res_ctx->pipe_ctx[pipe_idx].top_pipe)
1190                 return 3;
1191
1192         collapsed_idx = 0;
1193         for (i = 0; i < pipe_idx; i++) {
1194                 if (res_ctx->pipe_ctx[i].stream)
1195                         collapsed_idx++;
1196         }
1197
1198         return collapsed_idx;
1199 }
1200
1201 static bool is_watermark_set_a_greater(
1202                 const struct bw_watermarks *set_a,
1203                 const struct bw_watermarks *set_b)
1204 {
1205         if (set_a->a_mark > set_b->a_mark
1206                         || set_a->b_mark > set_b->b_mark
1207                         || set_a->c_mark > set_b->c_mark
1208                         || set_a->d_mark > set_b->d_mark)
1209                 return true;
1210         return false;
1211 }
1212
1213 static bool did_watermarks_increase(
1214                 struct pipe_ctx *pipe_ctx,
1215                 struct validate_context *context,
1216                 struct validate_context *old_context)
1217 {
1218         int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx,
1219                         pipe_ctx->pipe_idx);
1220         int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx,
1221                         pipe_ctx->pipe_idx);
1222         struct pipe_ctx *old_pipe_ctx =  &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
1223
1224         if (!old_pipe_ctx->stream)
1225                 return true;
1226
1227         if (is_watermark_set_a_greater(
1228                         &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx],
1229                         &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx]))
1230                 return true;
1231         if (is_watermark_set_a_greater(
1232                         &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx],
1233                         &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx]))
1234                 return true;
1235         if (is_watermark_set_a_greater(
1236                         &context->bw_results.urgent_wm_ns[collapsed_pipe_idx],
1237                         &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx]))
1238                 return true;
1239
1240         return false;
1241 }
1242
1243 static void program_wm_for_pipe(struct core_dc *dc,
1244                 struct pipe_ctx *pipe_ctx,
1245                 struct validate_context *context)
1246 {
1247         int total_dest_line_time_ns = compute_pstate_blackout_duration(
1248                         dc->bw_vbios.blackout_duration,
1249                         pipe_ctx->stream);
1250         int bw_result_idx = get_bw_result_idx(&context->res_ctx,
1251                                 pipe_ctx->pipe_idx);
1252
1253         pipe_ctx->mi->funcs->mem_input_program_display_marks(
1254                 pipe_ctx->mi,
1255                 context->bw_results.nbp_state_change_wm_ns[bw_result_idx],
1256                 context->bw_results.stutter_exit_wm_ns[bw_result_idx],
1257                 context->bw_results.urgent_wm_ns[bw_result_idx],
1258                 total_dest_line_time_ns);
1259
1260         if (pipe_ctx->top_pipe)
1261                 pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
1262                                 pipe_ctx->mi,
1263                                 context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1],
1264                                 context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1],
1265                                 context->bw_results.urgent_wm_ns[bw_result_idx + 1],
1266                                 total_dest_line_time_ns);
1267 }
1268
1269 void dce110_set_displaymarks(
1270         const struct core_dc *dc,
1271         struct validate_context *context)
1272 {
1273         uint8_t i, num_pipes;
1274         unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1275
1276         for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1277                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1278                 uint32_t total_dest_line_time_ns;
1279
1280                 if (pipe_ctx->stream == NULL)
1281                         continue;
1282
1283                 total_dest_line_time_ns = compute_pstate_blackout_duration(
1284                         dc->bw_vbios.blackout_duration, pipe_ctx->stream);
1285                 pipe_ctx->mi->funcs->mem_input_program_display_marks(
1286                         pipe_ctx->mi,
1287                         context->bw_results.nbp_state_change_wm_ns[num_pipes],
1288                         context->bw_results.stutter_exit_wm_ns[num_pipes],
1289                         context->bw_results.urgent_wm_ns[num_pipes],
1290                         total_dest_line_time_ns);
1291                 if (i == underlay_idx) {
1292                         num_pipes++;
1293                         pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
1294                                 pipe_ctx->mi,
1295                                 context->bw_results.nbp_state_change_wm_ns[num_pipes],
1296                                 context->bw_results.stutter_exit_wm_ns[num_pipes],
1297                                 context->bw_results.urgent_wm_ns[num_pipes],
1298                                 total_dest_line_time_ns);
1299                 }
1300                 num_pipes++;
1301         }
1302 }
1303
1304 static void set_safe_displaymarks(struct resource_context *res_ctx)
1305 {
1306         int i;
1307         int underlay_idx = res_ctx->pool->underlay_pipe_index;
1308         struct bw_watermarks max_marks = {
1309                 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
1310         struct bw_watermarks nbp_marks = {
1311                 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1312
1313         for (i = 0; i < MAX_PIPES; i++) {
1314                 if (res_ctx->pipe_ctx[i].stream == NULL)
1315                         continue;
1316
1317                 res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks(
1318                                 res_ctx->pipe_ctx[i].mi,
1319                                 nbp_marks,
1320                                 max_marks,
1321                                 max_marks,
1322                                 MAX_WATERMARK);
1323                 if (i == underlay_idx)
1324                         res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks(
1325                                 res_ctx->pipe_ctx[i].mi,
1326                                 nbp_marks,
1327                                 max_marks,
1328                                 max_marks,
1329                                 MAX_WATERMARK);
1330         }
1331 }
1332
1333 static void switch_dp_clock_sources(
1334         const struct core_dc *dc,
1335         struct resource_context *res_ctx)
1336 {
1337         uint8_t i;
1338         for (i = 0; i < MAX_PIPES; i++) {
1339                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1340
1341                 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1342                         continue;
1343
1344                 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1345                         struct clock_source *clk_src =
1346                                 resource_find_used_clk_src_for_sharing(
1347                                                 res_ctx, pipe_ctx);
1348
1349                         if (clk_src &&
1350                                 clk_src != pipe_ctx->clock_source) {
1351                                 resource_unreference_clock_source(
1352                                         res_ctx, &pipe_ctx->clock_source);
1353                                 pipe_ctx->clock_source = clk_src;
1354                                 resource_reference_clock_source(res_ctx, clk_src);
1355
1356                                 dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i);
1357                         }
1358                 }
1359         }
1360 }
1361
1362 /*******************************************************************************
1363  * Public functions
1364  ******************************************************************************/
1365
1366 static void reset_single_pipe_hw_ctx(
1367                 const struct core_dc *dc,
1368                 struct pipe_ctx *pipe_ctx,
1369                 struct validate_context *context)
1370 {
1371         core_link_disable_stream(pipe_ctx);
1372         pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
1373         if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) {
1374                 dm_error("DC: failed to blank crtc!\n");
1375                 BREAK_TO_DEBUGGER();
1376         }
1377         pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
1378         pipe_ctx->mi->funcs->free_mem_input(
1379                                 pipe_ctx->mi, context->stream_count);
1380         resource_unreference_clock_source(
1381                         &context->res_ctx, &pipe_ctx->clock_source);
1382
1383         dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx);
1384
1385         pipe_ctx->stream = NULL;
1386 }
1387
1388 static void set_drr(struct pipe_ctx **pipe_ctx,
1389                 int num_pipes, int vmin, int vmax)
1390 {
1391         int i = 0;
1392         struct drr_params params = {0};
1393
1394         params.vertical_total_max = vmax;
1395         params.vertical_total_min = vmin;
1396
1397         /* TODO: If multiple pipes are to be supported, you need
1398          * some GSL stuff
1399          */
1400
1401         for (i = 0; i < num_pipes; i++) {
1402                 pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, &params);
1403         }
1404 }
1405
1406 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1407                 int num_pipes, int value)
1408 {
1409         unsigned int i;
1410
1411         for (i = 0; i < num_pipes; i++)
1412                 pipe_ctx[i]->tg->funcs->
1413                         set_static_screen_control(pipe_ctx[i]->tg, value);
1414 }
1415
1416 /* unit: in_khz before mode set, get pixel clock from context. ASIC register
1417  * may not be programmed yet.
1418  * TODO: after mode set, pre_mode_set = false,
1419  * may read PLL register to get pixel clock
1420  */
1421 static uint32_t get_max_pixel_clock_for_all_paths(
1422         struct core_dc *dc,
1423         struct validate_context *context,
1424         bool pre_mode_set)
1425 {
1426         uint32_t max_pix_clk = 0;
1427         int i;
1428
1429         if (!pre_mode_set) {
1430                 /* TODO: read ASIC register to get pixel clock */
1431                 ASSERT(0);
1432         }
1433
1434         for (i = 0; i < MAX_PIPES; i++) {
1435                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1436
1437                 if (pipe_ctx->stream == NULL)
1438                         continue;
1439
1440                 /* do not check under lay */
1441                 if (pipe_ctx->top_pipe)
1442                         continue;
1443
1444                 if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk)
1445                         max_pix_clk =
1446                                 pipe_ctx->pix_clk_params.requested_pix_clk;
1447         }
1448
1449         if (max_pix_clk == 0)
1450                 ASSERT(0);
1451
1452         return max_pix_clk;
1453 }
1454
1455 /*
1456  * Find clock state based on clock requested. if clock value is 0, simply
1457  * set clock state as requested without finding clock state by clock value
1458  */
1459 static void apply_min_clocks(
1460         struct core_dc *dc,
1461         struct validate_context *context,
1462         enum dm_pp_clocks_state *clocks_state,
1463         bool pre_mode_set)
1464 {
1465         struct state_dependent_clocks req_clocks = {0};
1466         struct pipe_ctx *pipe_ctx;
1467         int i;
1468
1469         for (i = 0; i < MAX_PIPES; i++) {
1470                 pipe_ctx = &context->res_ctx.pipe_ctx[i];
1471                 if (pipe_ctx->dis_clk != NULL)
1472                         break;
1473         }
1474
1475         if (!pre_mode_set) {
1476                 /* set clock_state without verification */
1477                 if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) {
1478                         pipe_ctx->dis_clk->funcs->set_min_clocks_state(
1479                                                 pipe_ctx->dis_clk, *clocks_state);
1480                         return;
1481                 }
1482
1483                 /* TODOFPGA */
1484         }
1485
1486         /* get the required state based on state dependent clocks:
1487          * display clock and pixel clock
1488          */
1489         req_clocks.display_clk_khz = context->dispclk_khz;
1490
1491         req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
1492                         dc, context, true);
1493
1494         if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) {
1495                 *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state(
1496                                 pipe_ctx->dis_clk, &req_clocks);
1497                 pipe_ctx->dis_clk->funcs->set_min_clocks_state(
1498                         pipe_ctx->dis_clk, *clocks_state);
1499         } else {
1500         }
1501 }
1502
1503 static enum dc_status apply_ctx_to_hw_fpga(
1504                 struct core_dc *dc,
1505                 struct validate_context *context)
1506 {
1507         enum dc_status status = DC_ERROR_UNEXPECTED;
1508         int i;
1509
1510         for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1511                 struct pipe_ctx *pipe_ctx_old =
1512                                 &dc->current_context->res_ctx.pipe_ctx[i];
1513                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1514
1515                 if (pipe_ctx->stream == NULL)
1516                         continue;
1517
1518                 if (pipe_ctx->stream == pipe_ctx_old->stream)
1519                         continue;
1520
1521                 status = apply_single_controller_ctx_to_hw(
1522                                 pipe_ctx,
1523                                 context,
1524                                 dc);
1525
1526                 if (status != DC_OK)
1527                         return status;
1528         }
1529
1530         return DC_OK;
1531 }
1532
1533 static void reset_hw_ctx_wrap(
1534                 struct core_dc *dc,
1535                 struct validate_context *context)
1536 {
1537         int i;
1538
1539         /* Reset old context */
1540         /* look up the targets that have been removed since last commit */
1541         for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1542                 struct pipe_ctx *pipe_ctx_old =
1543                         &dc->current_context->res_ctx.pipe_ctx[i];
1544                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1545
1546                 /* Note: We need to disable output if clock sources change,
1547                  * since bios does optimization and doesn't apply if changing
1548                  * PHY when not already disabled.
1549                  */
1550
1551                 /* Skip underlay pipe since it will be handled in commit surface*/
1552                 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1553                         continue;
1554
1555                 if (!pipe_ctx->stream ||
1556                                 pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
1557                         reset_single_pipe_hw_ctx(
1558                                 dc, pipe_ctx_old, dc->current_context);
1559         }
1560 }
1561
1562 /*TODO: const validate_context*/
1563 enum dc_status dce110_apply_ctx_to_hw(
1564                 struct core_dc *dc,
1565                 struct validate_context *context)
1566 {
1567         struct dc_bios *dcb = dc->ctx->dc_bios;
1568         enum dc_status status;
1569         int i;
1570         enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID;
1571
1572         /* Reset old context */
1573         /* look up the targets that have been removed since last commit */
1574         dc->hwss.reset_hw_ctx_wrap(dc, context);
1575
1576         /* Skip applying if no targets */
1577         if (context->stream_count <= 0)
1578                 return DC_OK;
1579
1580         if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1581                 apply_ctx_to_hw_fpga(dc, context);
1582                 return DC_OK;
1583         }
1584
1585         /* Apply new context */
1586         dcb->funcs->set_scratch_critical_state(dcb, true);
1587
1588         /* below is for real asic only */
1589         for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1590                 struct pipe_ctx *pipe_ctx_old =
1591                                         &dc->current_context->res_ctx.pipe_ctx[i];
1592                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1593
1594                 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1595                         continue;
1596
1597                 if (pipe_ctx->stream == pipe_ctx_old->stream) {
1598                         if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
1599                                 dce_crtc_switch_to_clk_src(dc->hwseq,
1600                                                 pipe_ctx->clock_source, i);
1601                         continue;
1602                 }
1603
1604                 dc->hwss.enable_display_power_gating(
1605                                 dc, i, dc->ctx->dc_bios,
1606                                 PIPE_GATING_CONTROL_DISABLE);
1607         }
1608
1609         set_safe_displaymarks(&context->res_ctx);
1610         /*TODO: when pplib works*/
1611         apply_min_clocks(dc, context, &clocks_state, true);
1612
1613         if (context->dispclk_khz
1614                         > dc->current_context->dispclk_khz)
1615                 context->res_ctx.pool->display_clock->funcs->set_clock(
1616                                 context->res_ctx.pool->display_clock,
1617                                 context->dispclk_khz * 115 / 100);
1618
1619         /* program audio wall clock. use HDMI as clock source if HDMI
1620          * audio active. Otherwise, use DP as clock source
1621          * first, loop to find any HDMI audio, if not, loop find DP audio
1622          */
1623         /* Setup audio rate clock source */
1624         /* Issue:
1625         * Audio lag happened on DP monitor when unplug a HDMI monitor
1626         *
1627         * Cause:
1628         * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
1629         * is set to either dto0 or dto1, audio should work fine.
1630         * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
1631         * set to dto0 will cause audio lag.
1632         *
1633         * Solution:
1634         * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
1635         * find first available pipe with audio, setup audio wall DTO per topology
1636         * instead of per pipe.
1637         */
1638         for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1639                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1640
1641                 if (pipe_ctx->stream == NULL)
1642                         continue;
1643
1644                 if (pipe_ctx->top_pipe)
1645                         continue;
1646
1647                 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
1648                         continue;
1649
1650                 if (pipe_ctx->audio != NULL) {
1651                         struct audio_output audio_output;
1652
1653                         build_audio_output(pipe_ctx, &audio_output);
1654
1655                         pipe_ctx->audio->funcs->wall_dto_setup(
1656                                 pipe_ctx->audio,
1657                                 pipe_ctx->stream->signal,
1658                                 &audio_output.crtc_info,
1659                                 &audio_output.pll_info);
1660                         break;
1661                 }
1662         }
1663
1664         /* no HDMI audio is found, try DP audio */
1665         if (i == context->res_ctx.pool->pipe_count) {
1666                 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1667                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1668
1669                         if (pipe_ctx->stream == NULL)
1670                                 continue;
1671
1672                         if (pipe_ctx->top_pipe)
1673                                 continue;
1674
1675                         if (!dc_is_dp_signal(pipe_ctx->stream->signal))
1676                                 continue;
1677
1678                         if (pipe_ctx->audio != NULL) {
1679                                 struct audio_output audio_output;
1680
1681                                 build_audio_output(pipe_ctx, &audio_output);
1682
1683                                 pipe_ctx->audio->funcs->wall_dto_setup(
1684                                         pipe_ctx->audio,
1685                                         pipe_ctx->stream->signal,
1686                                         &audio_output.crtc_info,
1687                                         &audio_output.pll_info);
1688                                 break;
1689                         }
1690                 }
1691         }
1692
1693         for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1694                 struct pipe_ctx *pipe_ctx_old =
1695                                         &dc->current_context->res_ctx.pipe_ctx[i];
1696                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1697
1698                 if (pipe_ctx->stream == NULL)
1699                         continue;
1700
1701                 if (pipe_ctx->stream == pipe_ctx_old->stream)
1702                         continue;
1703
1704                 if (pipe_ctx->top_pipe)
1705                         continue;
1706
1707                 if (context->res_ctx.pipe_ctx[i].audio != NULL) {
1708
1709                         struct audio_output audio_output;
1710
1711                         build_audio_output(pipe_ctx, &audio_output);
1712
1713                         if (dc_is_dp_signal(pipe_ctx->stream->signal))
1714                                 pipe_ctx->stream_enc->funcs->dp_audio_setup(
1715                                                 pipe_ctx->stream_enc,
1716                                                 pipe_ctx->audio->inst,
1717                                                 &pipe_ctx->stream->public.audio_info);
1718                         else
1719                                 pipe_ctx->stream_enc->funcs->hdmi_audio_setup(
1720                                                 pipe_ctx->stream_enc,
1721                                                 pipe_ctx->audio->inst,
1722                                                 &pipe_ctx->stream->public.audio_info,
1723                                                 &audio_output.crtc_info);
1724
1725                         pipe_ctx->audio->funcs->az_configure(
1726                                         pipe_ctx->audio,
1727                                         pipe_ctx->stream->signal,
1728                                         &audio_output.crtc_info,
1729                                         &pipe_ctx->stream->public.audio_info);
1730                 }
1731
1732                 status = apply_single_controller_ctx_to_hw(
1733                                 pipe_ctx,
1734                                 context,
1735                                 dc);
1736
1737                 if (DC_OK != status)
1738                         return status;
1739         }
1740
1741         dc->hwss.set_displaymarks(dc, context);
1742
1743         /* to save power */
1744         apply_min_clocks(dc, context, &clocks_state, false);
1745
1746         dcb->funcs->set_scratch_critical_state(dcb, false);
1747
1748         switch_dp_clock_sources(dc, &context->res_ctx);
1749
1750         return DC_OK;
1751 }
1752
1753 /*******************************************************************************
1754  * Front End programming
1755  ******************************************************************************/
1756 static void set_default_colors(struct pipe_ctx *pipe_ctx)
1757 {
1758         struct default_adjustment default_adjust = { 0 };
1759
1760         default_adjust.force_hw_default = false;
1761         if (pipe_ctx->surface == NULL)
1762                 default_adjust.in_color_space = COLOR_SPACE_SRGB;
1763         else
1764                 default_adjust.in_color_space =
1765                                 pipe_ctx->surface->public.color_space;
1766         if (pipe_ctx->stream == NULL)
1767                 default_adjust.out_color_space = COLOR_SPACE_SRGB;
1768         else
1769                 default_adjust.out_color_space =
1770                                 pipe_ctx->stream->public.output_color_space;
1771         default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
1772         default_adjust.surface_pixel_format = pipe_ctx->scl_data.format;
1773
1774         /* display color depth */
1775         default_adjust.color_depth =
1776                 pipe_ctx->stream->public.timing.display_color_depth;
1777
1778         /* Lb color depth */
1779         default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth;
1780
1781         pipe_ctx->opp->funcs->opp_set_csc_default(
1782                                         pipe_ctx->opp, &default_adjust);
1783 }
1784
1785
1786 /*******************************************************************************
1787  * In order to turn on/off specific surface we will program
1788  * Blender + CRTC
1789  *
1790  * In case that we have two surfaces and they have a different visibility
1791  * we can't turn off the CRTC since it will turn off the entire display
1792  *
1793  * |----------------------------------------------- |
1794  * |bottom pipe|curr pipe  |              |         |
1795  * |Surface    |Surface    | Blender      |  CRCT   |
1796  * |visibility |visibility | Configuration|         |
1797  * |------------------------------------------------|
1798  * |   off     |    off    | CURRENT_PIPE | blank   |
1799  * |   off     |    on     | CURRENT_PIPE | unblank |
1800  * |   on      |    off    | OTHER_PIPE   | unblank |
1801  * |   on      |    on     | BLENDING     | unblank |
1802  * -------------------------------------------------|
1803  *
1804  ******************************************************************************/
1805 static void program_surface_visibility(const struct core_dc *dc,
1806                 struct pipe_ctx *pipe_ctx)
1807 {
1808         enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
1809         bool blank_target = false;
1810
1811         if (pipe_ctx->bottom_pipe) {
1812
1813                 /* For now we are supporting only two pipes */
1814                 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
1815
1816                 if (pipe_ctx->bottom_pipe->surface->public.visible) {
1817                         if (pipe_ctx->surface->public.visible)
1818                                 blender_mode = BLND_MODE_BLENDING;
1819                         else
1820                                 blender_mode = BLND_MODE_OTHER_PIPE;
1821
1822                 } else if (!pipe_ctx->surface->public.visible)
1823                         blank_target = true;
1824
1825         } else if (!pipe_ctx->surface->public.visible)
1826                 blank_target = true;
1827
1828         dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode);
1829         pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, blank_target);
1830
1831 }
1832
1833 /**
1834  * TODO REMOVE, USE UPDATE INSTEAD
1835  */
1836 static void set_plane_config(
1837         const struct core_dc *dc,
1838         struct pipe_ctx *pipe_ctx,
1839         struct resource_context *res_ctx)
1840 {
1841         struct mem_input *mi = pipe_ctx->mi;
1842         struct core_surface *surface = pipe_ctx->surface;
1843         struct xfm_grph_csc_adjustment adjust;
1844         struct out_csc_color_matrix tbl_entry;
1845         unsigned int i;
1846
1847         memset(&adjust, 0, sizeof(adjust));
1848         memset(&tbl_entry, 0, sizeof(tbl_entry));
1849         adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1850
1851         dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
1852
1853         set_default_colors(pipe_ctx);
1854         if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
1855                         == true) {
1856                 tbl_entry.color_space =
1857                         pipe_ctx->stream->public.output_color_space;
1858
1859                 for (i = 0; i < 12; i++)
1860                         tbl_entry.regval[i] =
1861                         pipe_ctx->stream->public.csc_color_matrix.matrix[i];
1862
1863                 pipe_ctx->opp->funcs->opp_set_csc_adjustment
1864                                 (pipe_ctx->opp, &tbl_entry);
1865         }
1866
1867         if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1868                 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1869                 adjust.temperature_matrix[0] =
1870                                 pipe_ctx->stream->
1871                                 public.gamut_remap_matrix.matrix[0];
1872                 adjust.temperature_matrix[1] =
1873                                 pipe_ctx->stream->
1874                                 public.gamut_remap_matrix.matrix[1];
1875                 adjust.temperature_matrix[2] =
1876                                 pipe_ctx->stream->
1877                                 public.gamut_remap_matrix.matrix[2];
1878                 adjust.temperature_matrix[3] =
1879                                 pipe_ctx->stream->
1880                                 public.gamut_remap_matrix.matrix[4];
1881                 adjust.temperature_matrix[4] =
1882                                 pipe_ctx->stream->
1883                                 public.gamut_remap_matrix.matrix[5];
1884                 adjust.temperature_matrix[5] =
1885                                 pipe_ctx->stream->
1886                                 public.gamut_remap_matrix.matrix[6];
1887                 adjust.temperature_matrix[6] =
1888                                 pipe_ctx->stream->
1889                                 public.gamut_remap_matrix.matrix[8];
1890                 adjust.temperature_matrix[7] =
1891                                 pipe_ctx->stream->
1892                                 public.gamut_remap_matrix.matrix[9];
1893                 adjust.temperature_matrix[8] =
1894                                 pipe_ctx->stream->
1895                                 public.gamut_remap_matrix.matrix[10];
1896         }
1897
1898         pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
1899
1900         pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1901         program_scaler(dc, pipe_ctx);
1902
1903         program_surface_visibility(dc, pipe_ctx);
1904
1905         mi->funcs->mem_input_program_surface_config(
1906                         mi,
1907                         surface->public.format,
1908                         &surface->public.tiling_info,
1909                         &surface->public.plane_size,
1910                         surface->public.rotation,
1911                         NULL,
1912                         false,
1913                         pipe_ctx->surface->public.visible);
1914
1915         if (dc->public.config.gpu_vm_support)
1916                 mi->funcs->mem_input_program_pte_vm(
1917                                 pipe_ctx->mi,
1918                                 surface->public.format,
1919                                 &surface->public.tiling_info,
1920                                 surface->public.rotation);
1921 }
1922
1923 static void update_plane_addr(const struct core_dc *dc,
1924                 struct pipe_ctx *pipe_ctx)
1925 {
1926         struct core_surface *surface = pipe_ctx->surface;
1927
1928         if (surface == NULL)
1929                 return;
1930
1931         pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
1932                         pipe_ctx->mi,
1933                         &surface->public.address,
1934                         surface->public.flip_immediate);
1935
1936         surface->status.requested_address = surface->public.address;
1937 }
1938
1939 void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
1940 {
1941         struct core_surface *surface = pipe_ctx->surface;
1942
1943         if (surface == NULL)
1944                 return;
1945
1946         surface->status.is_flip_pending =
1947                         pipe_ctx->mi->funcs->mem_input_is_flip_pending(
1948                                         pipe_ctx->mi);
1949
1950         if (surface->status.is_flip_pending && !surface->public.visible)
1951                 pipe_ctx->mi->current_address = pipe_ctx->mi->request_address;
1952
1953         surface->status.current_address = pipe_ctx->mi->current_address;
1954 }
1955
1956 void dce110_power_down(struct core_dc *dc)
1957 {
1958         power_down_all_hw_blocks(dc);
1959         disable_vga_and_power_gate_all_controllers(dc);
1960 }
1961
1962 static bool wait_for_reset_trigger_to_occur(
1963         struct dc_context *dc_ctx,
1964         struct timing_generator *tg)
1965 {
1966         bool rc = false;
1967
1968         /* To avoid endless loop we wait at most
1969          * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1970         const uint32_t frames_to_wait_on_triggered_reset = 10;
1971         uint32_t i;
1972
1973         for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1974
1975                 if (!tg->funcs->is_counter_moving(tg)) {
1976                         DC_ERROR("TG counter is not moving!\n");
1977                         break;
1978                 }
1979
1980                 if (tg->funcs->did_triggered_reset_occur(tg)) {
1981                         rc = true;
1982                         /* usually occurs at i=1 */
1983                         DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1984                                         i);
1985                         break;
1986                 }
1987
1988                 /* Wait for one frame. */
1989                 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1990                 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1991         }
1992
1993         if (false == rc)
1994                 DC_ERROR("GSL: Timeout on reset trigger!\n");
1995
1996         return rc;
1997 }
1998
1999 /* Enable timing synchronization for a group of Timing Generators. */
2000 static void dce110_enable_timing_synchronization(
2001                 struct core_dc *dc,
2002                 int group_index,
2003                 int group_size,
2004                 struct pipe_ctx *grouped_pipes[])
2005 {
2006         struct dc_context *dc_ctx = dc->ctx;
2007         struct dcp_gsl_params gsl_params = { 0 };
2008         int i;
2009
2010         DC_SYNC_INFO("GSL: Setting-up...\n");
2011
2012         /* Designate a single TG in the group as a master.
2013          * Since HW doesn't care which one, we always assign
2014          * the 1st one in the group. */
2015         gsl_params.gsl_group = 0;
2016         gsl_params.gsl_master = grouped_pipes[0]->tg->inst;
2017
2018         for (i = 0; i < group_size; i++)
2019                 grouped_pipes[i]->tg->funcs->setup_global_swap_lock(
2020                                         grouped_pipes[i]->tg, &gsl_params);
2021
2022         /* Reset slave controllers on master VSync */
2023         DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2024
2025         for (i = 1 /* skip the master */; i < group_size; i++)
2026                 grouped_pipes[i]->tg->funcs->enable_reset_trigger(
2027                                         grouped_pipes[i]->tg, gsl_params.gsl_group);
2028
2029
2030
2031         for (i = 1 /* skip the master */; i < group_size; i++) {
2032                 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2033                 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg);
2034                 /* Regardless of success of the wait above, remove the reset or
2035                  * the driver will start timing out on Display requests. */
2036                 DC_SYNC_INFO("GSL: disabling trigger-reset.\n");
2037                 grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg);
2038         }
2039
2040
2041         /* GSL Vblank synchronization is a one time sync mechanism, assumption
2042          * is that the sync'ed displays will not drift out of sync over time*/
2043         DC_SYNC_INFO("GSL: Restoring register states.\n");
2044         for (i = 0; i < group_size; i++)
2045                 grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg);
2046
2047         DC_SYNC_INFO("GSL: Set-up complete.\n");
2048 }
2049
2050 static void init_hw(struct core_dc *dc)
2051 {
2052         int i;
2053         struct dc_bios *bp;
2054         struct transform *xfm;
2055         struct abm *abm;
2056
2057         bp = dc->ctx->dc_bios;
2058         for (i = 0; i < dc->res_pool->pipe_count; i++) {
2059                 xfm = dc->res_pool->transforms[i];
2060                 xfm->funcs->transform_reset(xfm);
2061
2062                 dc->hwss.enable_display_power_gating(
2063                                 dc, i, bp,
2064                                 PIPE_GATING_CONTROL_INIT);
2065                 dc->hwss.enable_display_power_gating(
2066                                 dc, i, bp,
2067                                 PIPE_GATING_CONTROL_DISABLE);
2068                 dc->hwss.enable_display_pipe_clock_gating(
2069                         dc->ctx,
2070                         true);
2071         }
2072
2073         dce_clock_gating_power_up(dc->hwseq, false);
2074         /***************************************/
2075
2076         for (i = 0; i < dc->link_count; i++) {
2077                 /****************************************/
2078                 /* Power up AND update implementation according to the
2079                  * required signal (which may be different from the
2080                  * default signal on connector). */
2081                 struct core_link *link = dc->links[i];
2082                 link->link_enc->funcs->hw_init(link->link_enc);
2083         }
2084
2085         for (i = 0; i < dc->res_pool->pipe_count; i++) {
2086                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2087
2088                 tg->funcs->disable_vga(tg);
2089
2090                 /* Blank controller using driver code instead of
2091                  * command table. */
2092                 tg->funcs->set_blank(tg, true);
2093                 hwss_wait_for_blank_complete(tg);
2094         }
2095
2096         for (i = 0; i < dc->res_pool->audio_count; i++) {
2097                 struct audio *audio = dc->res_pool->audios[i];
2098                 audio->funcs->hw_init(audio);
2099         }
2100
2101         abm = dc->res_pool->abm;
2102         if (abm != NULL) {
2103                 abm->funcs->init_backlight(abm);
2104                 abm->funcs->abm_init(abm);
2105         }
2106 }
2107
2108 /* TODO: move this to apply_ctx_tohw some how?*/
2109 static void dce110_power_on_pipe_if_needed(
2110                 struct core_dc *dc,
2111                 struct pipe_ctx *pipe_ctx,
2112                 struct validate_context *context)
2113 {
2114         struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2115         struct dc_bios *dcb = dc->ctx->dc_bios;
2116         struct tg_color black_color = {0};
2117
2118         if (!old_pipe_ctx->stream && pipe_ctx->stream) {
2119                 dc->hwss.enable_display_power_gating(
2120                                 dc,
2121                                 pipe_ctx->pipe_idx,
2122                                 dcb, PIPE_GATING_CONTROL_DISABLE);
2123
2124                 /*
2125                  * This is for powering on underlay, so crtc does not
2126                  * need to be enabled
2127                  */
2128
2129                 pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg,
2130                                 &pipe_ctx->stream->public.timing,
2131                                 false);
2132
2133                 pipe_ctx->tg->funcs->enable_advanced_request(
2134                                 pipe_ctx->tg,
2135                                 true,
2136                                 &pipe_ctx->stream->public.timing);
2137
2138                 pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi,
2139                                 pipe_ctx->stream->public.timing.h_total,
2140                                 pipe_ctx->stream->public.timing.v_total,
2141                                 pipe_ctx->stream->public.timing.pix_clk_khz,
2142                                 context->stream_count);
2143
2144                 /* TODO unhardcode*/
2145                 color_space_to_black_color(dc,
2146                                 COLOR_SPACE_YCBCR601, &black_color);
2147                 pipe_ctx->tg->funcs->set_blank_color(
2148                                 pipe_ctx->tg,
2149                                 &black_color);
2150         }
2151 }
2152
2153 static void dce110_increase_watermarks_for_pipe(
2154                 struct core_dc *dc,
2155                 struct pipe_ctx *pipe_ctx,
2156                 struct validate_context *context)
2157 {
2158         if (did_watermarks_increase(pipe_ctx, context, dc->current_context))
2159                 program_wm_for_pipe(dc, pipe_ctx, context);
2160 }
2161
2162 static void dce110_set_bandwidth(struct core_dc *dc)
2163 {
2164         int i;
2165
2166         for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) {
2167                 struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i];
2168
2169                 if (!pipe_ctx->stream)
2170                         continue;
2171
2172                 program_wm_for_pipe(dc, pipe_ctx, dc->current_context);
2173         }
2174
2175         dc->current_context->res_ctx.pool->display_clock->funcs->set_clock(
2176                         dc->current_context->res_ctx.pool->display_clock,
2177                         dc->current_context->dispclk_khz * 115 / 100);
2178 }
2179
2180 static void dce110_program_front_end_for_pipe(
2181                 struct core_dc *dc, struct pipe_ctx *pipe_ctx)
2182 {
2183         struct mem_input *mi = pipe_ctx->mi;
2184         struct pipe_ctx *old_pipe = NULL;
2185         struct core_surface *surface = pipe_ctx->surface;
2186         struct xfm_grph_csc_adjustment adjust;
2187         struct out_csc_color_matrix tbl_entry;
2188         unsigned int i;
2189
2190         memset(&tbl_entry, 0, sizeof(tbl_entry));
2191
2192         if (dc->current_context)
2193                 old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2194
2195         memset(&adjust, 0, sizeof(adjust));
2196         adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2197
2198         dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
2199
2200         set_default_colors(pipe_ctx);
2201         if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
2202                         == true) {
2203                 tbl_entry.color_space =
2204                         pipe_ctx->stream->public.output_color_space;
2205
2206                 for (i = 0; i < 12; i++)
2207                         tbl_entry.regval[i] =
2208                         pipe_ctx->stream->public.csc_color_matrix.matrix[i];
2209
2210                 pipe_ctx->opp->funcs->opp_set_csc_adjustment
2211                                 (pipe_ctx->opp, &tbl_entry);
2212         }
2213
2214         if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
2215                 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2216                 adjust.temperature_matrix[0] =
2217                                 pipe_ctx->stream->
2218                                 public.gamut_remap_matrix.matrix[0];
2219                 adjust.temperature_matrix[1] =
2220                                 pipe_ctx->stream->
2221                                 public.gamut_remap_matrix.matrix[1];
2222                 adjust.temperature_matrix[2] =
2223                                 pipe_ctx->stream->
2224                                 public.gamut_remap_matrix.matrix[2];
2225                 adjust.temperature_matrix[3] =
2226                                 pipe_ctx->stream->
2227                                 public.gamut_remap_matrix.matrix[4];
2228                 adjust.temperature_matrix[4] =
2229                                 pipe_ctx->stream->
2230                                 public.gamut_remap_matrix.matrix[5];
2231                 adjust.temperature_matrix[5] =
2232                                 pipe_ctx->stream->
2233                                 public.gamut_remap_matrix.matrix[6];
2234                 adjust.temperature_matrix[6] =
2235                                 pipe_ctx->stream->
2236                                 public.gamut_remap_matrix.matrix[8];
2237                 adjust.temperature_matrix[7] =
2238                                 pipe_ctx->stream->
2239                                 public.gamut_remap_matrix.matrix[9];
2240                 adjust.temperature_matrix[8] =
2241                                 pipe_ctx->stream->
2242                                 public.gamut_remap_matrix.matrix[10];
2243         }
2244
2245         pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
2246
2247         pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2248         if (old_pipe && memcmp(&old_pipe->scl_data,
2249                                 &pipe_ctx->scl_data,
2250                                 sizeof(struct scaler_data)) != 0)
2251                 program_scaler(dc, pipe_ctx);
2252
2253         mi->funcs->mem_input_program_surface_config(
2254                         mi,
2255                         surface->public.format,
2256                         &surface->public.tiling_info,
2257                         &surface->public.plane_size,
2258                         surface->public.rotation,
2259                         NULL,
2260                         false,
2261                         pipe_ctx->surface->public.visible);
2262
2263         if (dc->public.config.gpu_vm_support)
2264                 mi->funcs->mem_input_program_pte_vm(
2265                                 pipe_ctx->mi,
2266                                 surface->public.format,
2267                                 &surface->public.tiling_info,
2268                                 surface->public.rotation);
2269
2270         dm_logger_write(dc->ctx->logger, LOG_SURFACE,
2271                         "Pipe:%d 0x%x: addr hi:0x%x, "
2272                         "addr low:0x%x, "
2273                         "src: %d, %d, %d,"
2274                         " %d; dst: %d, %d, %d, %d;"
2275                         "clip: %d, %d, %d, %d\n",
2276                         pipe_ctx->pipe_idx,
2277                         pipe_ctx->surface,
2278                         pipe_ctx->surface->public.address.grph.addr.high_part,
2279                         pipe_ctx->surface->public.address.grph.addr.low_part,
2280                         pipe_ctx->surface->public.src_rect.x,
2281                         pipe_ctx->surface->public.src_rect.y,
2282                         pipe_ctx->surface->public.src_rect.width,
2283                         pipe_ctx->surface->public.src_rect.height,
2284                         pipe_ctx->surface->public.dst_rect.x,
2285                         pipe_ctx->surface->public.dst_rect.y,
2286                         pipe_ctx->surface->public.dst_rect.width,
2287                         pipe_ctx->surface->public.dst_rect.height,
2288                         pipe_ctx->surface->public.clip_rect.x,
2289                         pipe_ctx->surface->public.clip_rect.y,
2290                         pipe_ctx->surface->public.clip_rect.width,
2291                         pipe_ctx->surface->public.clip_rect.height);
2292
2293         dm_logger_write(dc->ctx->logger, LOG_SURFACE,
2294                         "Pipe %d: width, height, x, y\n"
2295                         "viewport:%d, %d, %d, %d\n"
2296                         "recout:  %d, %d, %d, %d\n",
2297                         pipe_ctx->pipe_idx,
2298                         pipe_ctx->scl_data.viewport.width,
2299                         pipe_ctx->scl_data.viewport.height,
2300                         pipe_ctx->scl_data.viewport.x,
2301                         pipe_ctx->scl_data.viewport.y,
2302                         pipe_ctx->scl_data.recout.width,
2303                         pipe_ctx->scl_data.recout.height,
2304                         pipe_ctx->scl_data.recout.x,
2305                         pipe_ctx->scl_data.recout.y);
2306 }
2307
2308 static void dce110_prepare_pipe_for_context(
2309                 struct core_dc *dc,
2310                 struct pipe_ctx *pipe_ctx,
2311                 struct validate_context *context)
2312 {
2313         dce110_power_on_pipe_if_needed(dc, pipe_ctx, context);
2314         dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context);
2315 }
2316
2317 static void dce110_apply_ctx_for_surface(
2318                 struct core_dc *dc,
2319                 struct core_surface *surface,
2320                 struct validate_context *context)
2321 {
2322         int i;
2323
2324         /* TODO remove when removing the surface reset workaroud*/
2325         if (!surface)
2326                 return;
2327
2328         for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
2329                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2330
2331                 if (pipe_ctx->surface != surface)
2332                         continue;
2333
2334                 dce110_program_front_end_for_pipe(dc, pipe_ctx);
2335                 program_surface_visibility(dc, pipe_ctx);
2336
2337         }
2338 }
2339
2340 static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
2341 {
2342         int i;
2343
2344         for (i = 0; i < dc->res_pool->pipe_count; i++)
2345                 if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe)
2346                         break;
2347
2348         if (i == dc->res_pool->pipe_count)
2349                 return;
2350
2351         dc->hwss.enable_display_power_gating(
2352                 dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2353         if (pipe->xfm)
2354                 pipe->xfm->funcs->transform_reset(pipe->xfm);
2355         memset(&pipe->scl_data, 0, sizeof(struct scaler_data));
2356 }
2357
2358 static const struct hw_sequencer_funcs dce110_funcs = {
2359         .init_hw = init_hw,
2360         .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2361         .prepare_pipe_for_context = dce110_prepare_pipe_for_context,
2362         .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2363         .set_plane_config = set_plane_config,
2364         .update_plane_addr = update_plane_addr,
2365         .update_pending_status = dce110_update_pending_status,
2366         .set_input_transfer_func = dce110_set_input_transfer_func,
2367         .set_output_transfer_func = dce110_set_output_transfer_func,
2368         .power_down = dce110_power_down,
2369         .enable_accelerated_mode = dce110_enable_accelerated_mode,
2370         .enable_timing_synchronization = dce110_enable_timing_synchronization,
2371         .update_info_frame = dce110_update_info_frame,
2372         .enable_stream = dce110_enable_stream,
2373         .disable_stream = dce110_disable_stream,
2374         .unblank_stream = dce110_unblank_stream,
2375         .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
2376         .enable_display_power_gating = dce110_enable_display_power_gating,
2377         .power_down_front_end = dce110_power_down_fe,
2378         .pipe_control_lock = dce_pipe_control_lock,
2379         .set_displaymarks = dce110_set_displaymarks,
2380         .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe,
2381         .set_bandwidth = dce110_set_bandwidth,
2382         .set_drr = set_drr,
2383         .set_static_screen_control = set_static_screen_control,
2384         .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
2385         .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
2386 };
2387
2388 bool dce110_hw_sequencer_construct(struct core_dc *dc)
2389 {
2390         dc->hwss = dce110_funcs;
2391
2392         return true;
2393 }
2394