Merge remote-tracking branch 'asoc/topic/pcm5102a' into asoc-next
[linux-2.6-block.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_hw_sequencer.c
CommitLineData
4562236b
HW
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"
4562236b
HW
31#include "dm_helpers.h"
32#include "dce110_hw_sequencer.h"
33#include "dce110_timing_generator.h"
98489c02 34#include "dce/dce_hwseq.h"
87401969 35#include "gpio_service_interface.h"
4562236b 36
3eab7916 37#if defined(CONFIG_DRM_AMD_DC_FBC)
1663ae1c
BL
38#include "dce110_compressor.h"
39#endif
40
4562236b
HW
41#include "bios/bios_parser_helper.h"
42#include "timing_generator.h"
43#include "mem_input.h"
44#include "opp.h"
45#include "ipp.h"
46#include "transform.h"
47#include "stream_encoder.h"
48#include "link_encoder.h"
87401969 49#include "link_hwss.h"
4562236b 50#include "clock_source.h"
5e7773a2 51#include "abm.h"
4562236b 52#include "audio.h"
08b16886 53#include "reg_helper.h"
4562236b
HW
54
55/* include DCE11 register header files */
56#include "dce/dce_11_0_d.h"
57#include "dce/dce_11_0_sh_mask.h"
e266fdf6 58#include "custom_float.h"
4562236b 59
87401969
AJ
60/*
61 * All values are in milliseconds;
62 * For eDP, after power-up/power/down,
63 * 300/500 msec max. delay from LCDVCC to black video generation
64 */
65#define PANEL_POWER_UP_TIMEOUT 300
66#define PANEL_POWER_DOWN_TIMEOUT 500
67#define HPD_CHECK_INTERVAL 10
68
5eefbc40
YHL
69#define CTX \
70 hws->ctx
71#define REG(reg)\
72 hws->regs->reg
73
74#undef FN
75#define FN(reg_name, field_name) \
76 hws->shifts->field_name, hws->masks->field_name
77
4562236b
HW
78struct dce110_hw_seq_reg_offsets {
79 uint32_t crtc;
80};
81
82static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
83{
84 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
85},
86{
87 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
88},
89{
90 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
91},
92{
93 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
94}
95};
96
97#define HW_REG_BLND(reg, id)\
98 (reg + reg_offsets[id].blnd)
99
100#define HW_REG_CRTC(reg, id)\
101 (reg + reg_offsets[id].crtc)
102
103#define MAX_WATERMARK 0xFFFF
104#define SAFE_NBP_MARK 0x7FFF
105
106/*******************************************************************************
107 * Private definitions
108 ******************************************************************************/
109/***************************PIPE_CONTROL***********************************/
110static void dce110_init_pte(struct dc_context *ctx)
111{
112 uint32_t addr;
113 uint32_t value = 0;
114 uint32_t chunk_int = 0;
115 uint32_t chunk_mul = 0;
116
117 addr = mmUNP_DVMM_PTE_CONTROL;
118 value = dm_read_reg(ctx, addr);
119
120 set_reg_field_value(
121 value,
122 0,
123 DVMM_PTE_CONTROL,
124 DVMM_USE_SINGLE_PTE);
125
126 set_reg_field_value(
127 value,
128 1,
129 DVMM_PTE_CONTROL,
130 DVMM_PTE_BUFFER_MODE0);
131
132 set_reg_field_value(
133 value,
134 1,
135 DVMM_PTE_CONTROL,
136 DVMM_PTE_BUFFER_MODE1);
137
138 dm_write_reg(ctx, addr, value);
139
140 addr = mmDVMM_PTE_REQ;
141 value = dm_read_reg(ctx, addr);
142
143 chunk_int = get_reg_field_value(
144 value,
145 DVMM_PTE_REQ,
146 HFLIP_PTEREQ_PER_CHUNK_INT);
147
148 chunk_mul = get_reg_field_value(
149 value,
150 DVMM_PTE_REQ,
151 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
152
153 if (chunk_int != 0x4 || chunk_mul != 0x4) {
154
155 set_reg_field_value(
156 value,
157 255,
158 DVMM_PTE_REQ,
159 MAX_PTEREQ_TO_ISSUE);
160
161 set_reg_field_value(
162 value,
163 4,
164 DVMM_PTE_REQ,
165 HFLIP_PTEREQ_PER_CHUNK_INT);
166
167 set_reg_field_value(
168 value,
169 4,
170 DVMM_PTE_REQ,
171 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
172
173 dm_write_reg(ctx, addr, value);
174 }
175}
176/**************************************************************************/
177
178static void enable_display_pipe_clock_gating(
179 struct dc_context *ctx,
180 bool clock_gating)
181{
182 /*TODO*/
183}
184
185static bool dce110_enable_display_power_gating(
fb3466a4 186 struct dc *dc,
4562236b
HW
187 uint8_t controller_id,
188 struct dc_bios *dcb,
189 enum pipe_gating_control power_gating)
190{
191 enum bp_result bp_result = BP_RESULT_OK;
192 enum bp_pipe_control_action cntl;
193 struct dc_context *ctx = dc->ctx;
194 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
195
196 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
197 return true;
198
199 if (power_gating == PIPE_GATING_CONTROL_INIT)
200 cntl = ASIC_PIPE_INIT;
201 else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
202 cntl = ASIC_PIPE_ENABLE;
203 else
204 cntl = ASIC_PIPE_DISABLE;
205
206 if (controller_id == underlay_idx)
207 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
208
209 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
210
211 bp_result = dcb->funcs->enable_disp_power_gating(
212 dcb, controller_id + 1, cntl);
213
214 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
215 * by default when command table is called
216 *
217 * Bios parser accepts controller_id = 6 as indicative of
218 * underlay pipe in dce110. But we do not support more
219 * than 3.
220 */
221 if (controller_id < CONTROLLER_ID_MAX - 1)
222 dm_write_reg(ctx,
223 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
224 0);
225 }
226
227 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
228 dce110_init_pte(ctx);
229
230 if (bp_result == BP_RESULT_OK)
231 return true;
232 else
233 return false;
234}
235
236static void build_prescale_params(struct ipp_prescale_params *prescale_params,
3be5262e 237 const struct dc_plane_state *plane_state)
4562236b
HW
238{
239 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
240
3be5262e 241 switch (plane_state->format) {
4562236b 242 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
8693049a 243 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
4562236b
HW
244 prescale_params->scale = 0x2020;
245 break;
246 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
247 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
248 prescale_params->scale = 0x2008;
249 break;
250 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
251 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
252 prescale_params->scale = 0x2000;
253 break;
254 default:
255 ASSERT(false);
d7194cf6 256 break;
4562236b
HW
257 }
258}
259
a6114e85
HW
260static bool
261dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
262 const struct dc_plane_state *plane_state)
4562236b 263{
86a66c4e 264 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
7b0c470f 265 const struct dc_transfer_func *tf = NULL;
90e508ba
AK
266 struct ipp_prescale_params prescale_params = { 0 };
267 bool result = true;
268
269 if (ipp == NULL)
270 return false;
271
3be5262e
HW
272 if (plane_state->in_transfer_func)
273 tf = plane_state->in_transfer_func;
90e508ba 274
3be5262e 275 build_prescale_params(&prescale_params, plane_state);
90e508ba
AK
276 ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
277
3be5262e
HW
278 if (plane_state->gamma_correction && dce_use_lut(plane_state))
279 ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction);
d7194cf6 280
90e508ba
AK
281 if (tf == NULL) {
282 /* Default case if no input transfer function specified */
a6114e85 283 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
7b0c470f
LSL
284 } else if (tf->type == TF_TYPE_PREDEFINED) {
285 switch (tf->tf) {
90e508ba 286 case TRANSFER_FUNCTION_SRGB:
a6114e85 287 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
90e508ba
AK
288 break;
289 case TRANSFER_FUNCTION_BT709:
a6114e85 290 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC);
90e508ba
AK
291 break;
292 case TRANSFER_FUNCTION_LINEAR:
a6114e85 293 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
90e508ba
AK
294 break;
295 case TRANSFER_FUNCTION_PQ:
90e508ba
AK
296 default:
297 result = false;
d7194cf6 298 break;
90e508ba 299 }
7b0c470f 300 } else if (tf->type == TF_TYPE_BYPASS) {
70063a59 301 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
90e508ba
AK
302 } else {
303 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
304 result = false;
305 }
306
307 return result;
308}
309
bd1be8e8
HW
310static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted,
311 struct curve_points *arr_points,
312 uint32_t hw_points_num)
fcd2f4bf
AZ
313{
314 struct custom_float_format fmt;
315
316 struct pwl_result_data *rgb = rgb_resulted;
317
318 uint32_t i = 0;
319
320 fmt.exponenta_bits = 6;
321 fmt.mantissa_bits = 12;
322 fmt.sign = true;
323
bd1be8e8
HW
324 if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
325 &arr_points[0].custom_float_x)) {
fcd2f4bf
AZ
326 BREAK_TO_DEBUGGER();
327 return false;
328 }
329
bd1be8e8
HW
330 if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
331 &arr_points[0].custom_float_offset)) {
fcd2f4bf
AZ
332 BREAK_TO_DEBUGGER();
333 return false;
334 }
335
bd1be8e8
HW
336 if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
337 &arr_points[0].custom_float_slope)) {
fcd2f4bf
AZ
338 BREAK_TO_DEBUGGER();
339 return false;
340 }
341
342 fmt.mantissa_bits = 10;
343 fmt.sign = false;
344
bd1be8e8
HW
345 if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
346 &arr_points[1].custom_float_x)) {
fcd2f4bf
AZ
347 BREAK_TO_DEBUGGER();
348 return false;
349 }
350
bd1be8e8
HW
351 if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
352 &arr_points[1].custom_float_y)) {
fcd2f4bf
AZ
353 BREAK_TO_DEBUGGER();
354 return false;
355 }
356
4d06ccd0
HW
357 if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
358 &arr_points[1].custom_float_slope)) {
fcd2f4bf
AZ
359 BREAK_TO_DEBUGGER();
360 return false;
361 }
362
363 fmt.mantissa_bits = 12;
364 fmt.sign = true;
365
366 while (i != hw_points_num) {
bd1be8e8
HW
367 if (!convert_to_custom_float_format(rgb->red, &fmt,
368 &rgb->red_reg)) {
fcd2f4bf
AZ
369 BREAK_TO_DEBUGGER();
370 return false;
371 }
372
bd1be8e8
HW
373 if (!convert_to_custom_float_format(rgb->green, &fmt,
374 &rgb->green_reg)) {
fcd2f4bf
AZ
375 BREAK_TO_DEBUGGER();
376 return false;
377 }
378
bd1be8e8
HW
379 if (!convert_to_custom_float_format(rgb->blue, &fmt,
380 &rgb->blue_reg)) {
fcd2f4bf
AZ
381 BREAK_TO_DEBUGGER();
382 return false;
383 }
384
bd1be8e8
HW
385 if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
386 &rgb->delta_red_reg)) {
fcd2f4bf
AZ
387 BREAK_TO_DEBUGGER();
388 return false;
389 }
390
bd1be8e8
HW
391 if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
392 &rgb->delta_green_reg)) {
fcd2f4bf
AZ
393 BREAK_TO_DEBUGGER();
394 return false;
395 }
396
bd1be8e8
HW
397 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
398 &rgb->delta_blue_reg)) {
fcd2f4bf
AZ
399 BREAK_TO_DEBUGGER();
400 return false;
401 }
402
403 ++rgb;
404 ++i;
405 }
406
407 return true;
408}
409
b310b081
HW
410static bool
411dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
412 struct pwl_params *regamma_params)
fcd2f4bf 413{
23ae4f8e
AZ
414 struct curve_points *arr_points;
415 struct pwl_result_data *rgb_resulted;
416 struct pwl_result_data *rgb;
417 struct pwl_result_data *rgb_plus_1;
fcd2f4bf
AZ
418 struct fixed31_32 y_r;
419 struct fixed31_32 y_g;
420 struct fixed31_32 y_b;
421 struct fixed31_32 y1_min;
422 struct fixed31_32 y3_max;
423
424 int32_t segment_start, segment_end;
23ae4f8e
AZ
425 uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points;
426
b310b081 427 if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
23ae4f8e
AZ
428 return false;
429
430 arr_points = regamma_params->arr_points;
431 rgb_resulted = regamma_params->rgb_resulted;
432 hw_points = 0;
fcd2f4bf
AZ
433
434 memset(regamma_params, 0, sizeof(struct pwl_params));
435
436 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
534db198 437 /* 16 segments
fcd2f4bf
AZ
438 * segments are from 2^-11 to 2^5
439 */
440 segment_start = -11;
441 segment_end = 5;
442
534db198
AZ
443 seg_distr[0] = 2;
444 seg_distr[1] = 2;
445 seg_distr[2] = 2;
446 seg_distr[3] = 2;
447 seg_distr[4] = 2;
448 seg_distr[5] = 2;
449 seg_distr[6] = 3;
450 seg_distr[7] = 4;
451 seg_distr[8] = 4;
452 seg_distr[9] = 4;
453 seg_distr[10] = 4;
454 seg_distr[11] = 5;
455 seg_distr[12] = 5;
456 seg_distr[13] = 5;
457 seg_distr[14] = 5;
458 seg_distr[15] = 5;
459
fcd2f4bf 460 } else {
534db198 461 /* 10 segments
fcd2f4bf
AZ
462 * segment is from 2^-10 to 2^0
463 */
464 segment_start = -10;
465 segment_end = 0;
534db198
AZ
466
467 seg_distr[0] = 3;
468 seg_distr[1] = 4;
469 seg_distr[2] = 4;
470 seg_distr[3] = 4;
471 seg_distr[4] = 4;
472 seg_distr[5] = 4;
473 seg_distr[6] = 4;
474 seg_distr[7] = 4;
475 seg_distr[8] = 5;
476 seg_distr[9] = 5;
477 seg_distr[10] = -1;
478 seg_distr[11] = -1;
479 seg_distr[12] = -1;
480 seg_distr[13] = -1;
481 seg_distr[14] = -1;
482 seg_distr[15] = -1;
483 }
484
485 for (k = 0; k < 16; k++) {
486 if (seg_distr[k] != -1)
487 hw_points += (1 << seg_distr[k]);
fcd2f4bf
AZ
488 }
489
fcd2f4bf 490 j = 0;
534db198
AZ
491 for (k = 0; k < (segment_end - segment_start); k++) {
492 increment = 32 / (1 << seg_distr[k]);
493 start_index = (segment_start + k + 25) * 32;
494 for (i = start_index; i < start_index + 32; i += increment) {
495 if (j == hw_points - 1)
496 break;
497 rgb_resulted[j].red = output_tf->tf_pts.red[i];
498 rgb_resulted[j].green = output_tf->tf_pts.green[i];
499 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
500 j++;
501 }
fcd2f4bf
AZ
502 }
503
534db198
AZ
504 /* last point */
505 start_index = (segment_end + 25) * 32;
b310b081
HW
506 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
507 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
508 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
534db198 509
fcd2f4bf 510 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
b310b081 511 dal_fixed31_32_from_int(segment_start));
fcd2f4bf 512 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
b310b081 513 dal_fixed31_32_from_int(segment_end));
fcd2f4bf
AZ
514
515 y_r = rgb_resulted[0].red;
516 y_g = rgb_resulted[0].green;
517 y_b = rgb_resulted[0].blue;
518
519 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
520
521 arr_points[0].y = y1_min;
b310b081
HW
522 arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y,
523 arr_points[0].x);
fcd2f4bf
AZ
524
525 y_r = rgb_resulted[hw_points - 1].red;
526 y_g = rgb_resulted[hw_points - 1].green;
527 y_b = rgb_resulted[hw_points - 1].blue;
528
529 /* see comment above, m_arrPoints[1].y should be the Y value for the
530 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
531 */
532 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
533
534 arr_points[1].y = y3_max;
fcd2f4bf
AZ
535
536 arr_points[1].slope = dal_fixed31_32_zero;
fcd2f4bf
AZ
537
538 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
539 /* for PQ, we want to have a straight line from last HW X point,
540 * and the slope to be such that we hit 1.0 at 10000 nits.
541 */
b310b081 542 const struct fixed31_32 end_value = dal_fixed31_32_from_int(125);
fcd2f4bf
AZ
543
544 arr_points[1].slope = dal_fixed31_32_div(
b310b081
HW
545 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
546 dal_fixed31_32_sub(end_value, arr_points[1].x));
fcd2f4bf
AZ
547 }
548
549 regamma_params->hw_points_num = hw_points;
550
534db198
AZ
551 i = 1;
552 for (k = 0; k < 16 && i < 16; k++) {
553 if (seg_distr[k] != -1) {
b310b081 554 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
534db198 555 regamma_params->arr_curve_points[i].offset =
b310b081 556 regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
534db198
AZ
557 }
558 i++;
fcd2f4bf
AZ
559 }
560
534db198 561 if (seg_distr[k] != -1)
b310b081 562 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
534db198 563
23ae4f8e
AZ
564 rgb = rgb_resulted;
565 rgb_plus_1 = rgb_resulted + 1;
fcd2f4bf
AZ
566
567 i = 1;
568
569 while (i != hw_points + 1) {
570 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
571 rgb_plus_1->red = rgb->red;
572 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
573 rgb_plus_1->green = rgb->green;
574 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
575 rgb_plus_1->blue = rgb->blue;
576
b310b081
HW
577 rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red);
578 rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green);
579 rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue);
fcd2f4bf
AZ
580
581 ++rgb_plus_1;
582 ++rgb;
583 ++i;
584 }
585
586 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
587
588 return true;
589}
590
a6114e85
HW
591static bool
592dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
593 const struct dc_stream_state *stream)
90e508ba 594{
86a66c4e 595 struct transform *xfm = pipe_ctx->plane_res.xfm;
4562236b 596
7a09f5be
YHL
597 xfm->funcs->opp_power_on_regamma_lut(xfm, true);
598 xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
4562236b 599
4fa086b9 600 if (stream->out_transfer_func &&
efd52204
HW
601 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
602 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
7a09f5be 603 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
efd52204
HW
604 } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func,
605 &xfm->regamma_params)) {
7a09f5be
YHL
606 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
607 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
4562236b 608 } else {
7a09f5be 609 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
4562236b
HW
610 }
611
7a09f5be 612 xfm->funcs->opp_power_on_regamma_lut(xfm, false);
4562236b 613
cc0cb445 614 return true;
4562236b
HW
615}
616
617static enum dc_status bios_parser_crtc_source_select(
618 struct pipe_ctx *pipe_ctx)
619{
620 struct dc_bios *dcb;
621 /* call VBIOS table to set CRTC source for the HW
622 * encoder block
623 * note: video bios clears all FMT setting here. */
624 struct bp_crtc_source_select crtc_source_select = {0};
b73a22d3 625 const struct dc_sink *sink = pipe_ctx->stream->sink;
4562236b 626
8e9c4c8c 627 crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id;
4562236b
HW
628 crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1;
629 /*TODO: Need to un-hardcode color depth, dp_audio and account for
630 * the case where signal and sink signal is different (translator
631 * encoder)*/
632 crtc_source_select.signal = pipe_ctx->stream->signal;
633 crtc_source_select.enable_dp_audio = false;
634 crtc_source_select.sink_signal = pipe_ctx->stream->signal;
1b7441b0
CL
635
636 switch (pipe_ctx->stream->timing.display_color_depth) {
637 case COLOR_DEPTH_666:
638 crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR;
639 break;
640 case COLOR_DEPTH_888:
641 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
642 break;
643 case COLOR_DEPTH_101010:
644 crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR;
645 break;
646 case COLOR_DEPTH_121212:
647 crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR;
648 break;
649 default:
650 BREAK_TO_DEBUGGER();
651 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
652 break;
653 }
4562236b
HW
654
655 dcb = sink->ctx->dc_bios;
656
657 if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
658 dcb,
659 &crtc_source_select)) {
660 return DC_ERROR_UNEXPECTED;
661 }
662
663 return DC_OK;
664}
665
666void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
667{
86e2e1be
HW
668 ASSERT(pipe_ctx->stream);
669
8e9c4c8c 670 if (pipe_ctx->stream_res.stream_enc == NULL)
86e2e1be
HW
671 return; /* this is not root pipe */
672
4562236b 673 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
674 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
675 pipe_ctx->stream_res.stream_enc,
96c50c0d 676 &pipe_ctx->stream_res.encoder_info_frame);
4562236b 677 else if (dc_is_dp_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
678 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
679 pipe_ctx->stream_res.stream_enc,
96c50c0d 680 &pipe_ctx->stream_res.encoder_info_frame);
4562236b
HW
681}
682
683void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
684{
685 enum dc_lane_count lane_count =
d0778ebf 686 pipe_ctx->stream->sink->link->cur_link_settings.lane_count;
4562236b 687
4fa086b9 688 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
d0778ebf 689 struct dc_link *link = pipe_ctx->stream->sink->link;
4562236b 690
db941f24 691
4562236b
HW
692 uint32_t active_total_with_borders;
693 uint32_t early_control = 0;
6b670fa9 694 struct timing_generator *tg = pipe_ctx->stream_res.tg;
4562236b 695
db941f24
EY
696 /* For MST, there are multiply stream go to only one link.
697 * connect DIG back_end to front_end while enable_stream and
698 * disconnect them during disable_stream
699 * BY this, it is logic clean to separate stream and link */
700 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
701 pipe_ctx->stream_res.stream_enc->id, true);
702
703 /* update AVI info frame (HDMI, DP)*/
704 /* TODO: FPGA may change to hwss.update_info_frame */
4562236b 705 dce110_update_info_frame(pipe_ctx);
db941f24 706
4562236b
HW
707 /* enable early control to avoid corruption on DP monitor*/
708 active_total_with_borders =
709 timing->h_addressable
710 + timing->h_border_left
711 + timing->h_border_right;
712
713 if (lane_count != 0)
714 early_control = active_total_with_borders % lane_count;
715
716 if (early_control == 0)
717 early_control = lane_count;
718
719 tg->funcs->set_early_control(tg, early_control);
720
721 /* enable audio only within mode set */
afaacef4 722 if (pipe_ctx->stream_res.audio != NULL) {
4562236b 723 if (dc_is_dp_signal(pipe_ctx->stream->signal))
8e9c4c8c 724 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
4562236b
HW
725 }
726
db941f24
EY
727
728
4562236b
HW
729
730}
731
5eefbc40
YHL
732/*todo: cloned in stream enc, fix*/
733static bool is_panel_backlight_on(struct dce_hwseq *hws)
734{
735 uint32_t value;
736
737 REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
738
739 return value;
740}
741
87401969
AJ
742static bool is_panel_powered_on(struct dce_hwseq *hws)
743{
744 uint32_t value;
745
746 REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
747 return value == 1;
748}
749
5eefbc40 750static enum bp_result link_transmitter_control(
87401969 751 struct dc_bios *bios,
5eefbc40
YHL
752 struct bp_transmitter_control *cntl)
753{
754 enum bp_result result;
5eefbc40 755
87401969 756 result = bios->funcs->transmitter_control(bios, cntl);
5eefbc40
YHL
757
758 return result;
759}
760
87401969
AJ
761/*
762 * @brief
763 * eDP only.
764 */
765void hwss_edp_wait_for_hpd_ready(
069d418f
AJ
766 struct dc_link *link,
767 bool power_up)
87401969 768{
069d418f
AJ
769 struct dc_context *ctx = link->ctx;
770 struct graphics_object_id connector = link->link_enc->connector;
87401969
AJ
771 struct gpio *hpd;
772 bool edp_hpd_high = false;
773 uint32_t time_elapsed = 0;
774 uint32_t timeout = power_up ?
775 PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
776
777 if (dal_graphics_object_id_get_connector_id(connector)
778 != CONNECTOR_ID_EDP) {
779 BREAK_TO_DEBUGGER();
780 return;
781 }
782
783 if (!power_up)
784 /*
785 * From KV, we will not HPD low after turning off VCC -
786 * instead, we will check the SW timer in power_up().
787 */
788 return;
789
790 /*
791 * When we power on/off the eDP panel,
792 * we need to wait until SENSE bit is high/low.
793 */
794
795 /* obtain HPD */
796 /* TODO what to do with this? */
797 hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
798
799 if (!hpd) {
800 BREAK_TO_DEBUGGER();
801 return;
802 }
803
804 dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
805
806 /* wait until timeout or panel detected */
807
808 do {
809 uint32_t detected = 0;
810
811 dal_gpio_get_value(hpd, &detected);
812
813 if (!(detected ^ power_up)) {
814 edp_hpd_high = true;
815 break;
816 }
817
818 msleep(HPD_CHECK_INTERVAL);
819
820 time_elapsed += HPD_CHECK_INTERVAL;
821 } while (time_elapsed < timeout);
822
823 dal_gpio_close(hpd);
824
825 dal_gpio_destroy_irq(&hpd);
826
827 if (false == edp_hpd_high) {
828 dm_logger_write(ctx->logger, LOG_ERROR,
829 "%s: wait timed out!\n", __func__);
830 }
831}
832
833void hwss_edp_power_control(
069d418f
AJ
834 struct dc_link *link,
835 bool power_up)
87401969 836{
069d418f 837 struct dc_context *ctx = link->ctx;
87401969
AJ
838 struct dce_hwseq *hwseq = ctx->dc->hwseq;
839 struct bp_transmitter_control cntl = { 0 };
840 enum bp_result bp_result;
841
842
069d418f 843 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
87401969
AJ
844 != CONNECTOR_ID_EDP) {
845 BREAK_TO_DEBUGGER();
846 return;
847 }
848
849 if (power_up != is_panel_powered_on(hwseq)) {
850 /* Send VBIOS command to prompt eDP panel power */
851
852 dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
853 "%s: Panel Power action: %s\n",
854 __func__, (power_up ? "On":"Off"));
855
856 cntl.action = power_up ?
857 TRANSMITTER_CONTROL_POWER_ON :
858 TRANSMITTER_CONTROL_POWER_OFF;
069d418f
AJ
859 cntl.transmitter = link->link_enc->transmitter;
860 cntl.connector_obj_id = link->link_enc->connector;
87401969
AJ
861 cntl.coherent = false;
862 cntl.lanes_number = LANE_COUNT_FOUR;
069d418f 863 cntl.hpd_sel = link->link_enc->hpd_source;
87401969
AJ
864
865 bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
866
867 if (bp_result != BP_RESULT_OK)
868 dm_logger_write(ctx->logger, LOG_ERROR,
869 "%s: Panel Power bp_result: %d\n",
870 __func__, bp_result);
871 } else {
872 dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
873 "%s: Skipping Panel Power action: %s\n",
874 __func__, (power_up ? "On":"Off"));
875 }
87401969 876}
5eefbc40
YHL
877
878/*todo: cloned in stream enc, fix*/
879/*
880 * @brief
881 * eDP only. Control the backlight of the eDP panel
882 */
87401969 883void hwss_edp_backlight_control(
069d418f
AJ
884 struct dc_link *link,
885 bool enable)
5eefbc40 886{
069d418f
AJ
887 struct dc_context *ctx = link->ctx;
888 struct dce_hwseq *hws = ctx->dc->hwseq;
5eefbc40
YHL
889 struct bp_transmitter_control cntl = { 0 };
890
069d418f 891 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
5eefbc40
YHL
892 != CONNECTOR_ID_EDP) {
893 BREAK_TO_DEBUGGER();
894 return;
895 }
896
897 if (enable && is_panel_backlight_on(hws)) {
898 dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
899 "%s: panel already powered up. Do nothing.\n",
900 __func__);
901 return;
902 }
903
5eefbc40
YHL
904 /* Send VBIOS command to control eDP panel backlight */
905
906 dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
907 "%s: backlight action: %s\n",
908 __func__, (enable ? "On":"Off"));
909
910 cntl.action = enable ?
911 TRANSMITTER_CONTROL_BACKLIGHT_ON :
912 TRANSMITTER_CONTROL_BACKLIGHT_OFF;
87401969 913
5eefbc40
YHL
914 /*cntl.engine_id = ctx->engine;*/
915 cntl.transmitter = link->link_enc->transmitter;
916 cntl.connector_obj_id = link->link_enc->connector;
917 /*todo: unhardcode*/
918 cntl.lanes_number = LANE_COUNT_FOUR;
919 cntl.hpd_sel = link->link_enc->hpd_source;
920
921 /* For eDP, the following delays might need to be considered
922 * after link training completed:
923 * idle period - min. accounts for required BS-Idle pattern,
924 * max. allows for source frame synchronization);
925 * 50 msec max. delay from valid video data from source
926 * to video on dislpay or backlight enable.
927 *
928 * Disable the delay for now.
929 * Enable it in the future if necessary.
930 */
931 /* dc_service_sleep_in_milliseconds(50); */
069d418f 932 link_transmitter_control(ctx->dc_bios, &cntl);
5eefbc40
YHL
933}
934
4176664b 935void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
4562236b 936{
0971c40e 937 struct dc_stream_state *stream = pipe_ctx->stream;
d0778ebf 938 struct dc_link *link = stream->sink->link;
4176664b 939 struct dc *dc = pipe_ctx->stream->ctx->dc;
4562236b 940
2b7c97d6
CL
941 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
942 pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
943 pipe_ctx->stream_res.stream_enc);
944
945 if (dc_is_dp_signal(pipe_ctx->stream->signal))
946 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
947 pipe_ctx->stream_res.stream_enc);
948
949 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
950 pipe_ctx->stream_res.stream_enc, true);
afaacef4
HW
951 if (pipe_ctx->stream_res.audio) {
952 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
4562236b
HW
953
954 if (dc_is_dp_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
955 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
956 pipe_ctx->stream_res.stream_enc);
4562236b 957 else
8e9c4c8c
HW
958 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
959 pipe_ctx->stream_res.stream_enc);
4176664b
CL
960 /*don't free audio if it is from retrain or internal disable stream*/
961 if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) {
962 /*we have to dynamic arbitrate the audio endpoints*/
963 pipe_ctx->stream_res.audio = NULL;
964 /*we free the resource, need reset is_audio_acquired*/
965 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
966 }
4562236b 967
4562236b
HW
968 /* TODO: notify audio driver for if audio modes list changed
969 * add audio mode list change flag */
970 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
971 * stream->stream_engine_id);
972 */
973 }
974
4562236b 975 /* blank at encoder level */
904623ee 976 if (dc_is_dp_signal(pipe_ctx->stream->signal))
8e9c4c8c 977 pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
904623ee 978
4562236b
HW
979 link->link_enc->funcs->connect_dig_be_to_fe(
980 link->link_enc,
8e9c4c8c 981 pipe_ctx->stream_res.stream_enc->id,
4562236b
HW
982 false);
983
984}
985
986void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
987 struct dc_link_settings *link_settings)
988{
989 struct encoder_unblank_param params = { { 0 } };
990
991 /* only 3 items below are used by unblank */
6235b23c 992 params.pixel_clk_khz =
4fa086b9 993 pipe_ctx->stream->timing.pix_clk_khz;
4562236b 994 params.link_settings.link_rate = link_settings->link_rate;
8e9c4c8c 995 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, &params);
4562236b
HW
996}
997
15e17335
CL
998
999void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
1000{
8e9c4c8c
HW
1001 if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL)
1002 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable);
15e17335
CL
1003}
1004
4562236b
HW
1005static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
1006{
1007 switch (crtc_id) {
1008 case CONTROLLER_ID_D0:
1009 return DTO_SOURCE_ID0;
1010 case CONTROLLER_ID_D1:
1011 return DTO_SOURCE_ID1;
1012 case CONTROLLER_ID_D2:
1013 return DTO_SOURCE_ID2;
1014 case CONTROLLER_ID_D3:
1015 return DTO_SOURCE_ID3;
1016 case CONTROLLER_ID_D4:
1017 return DTO_SOURCE_ID4;
1018 case CONTROLLER_ID_D5:
1019 return DTO_SOURCE_ID5;
1020 default:
1021 return DTO_SOURCE_UNKNOWN;
1022 }
1023}
1024
1025static void build_audio_output(
ab8db3e1 1026 struct dc_state *state,
4562236b
HW
1027 const struct pipe_ctx *pipe_ctx,
1028 struct audio_output *audio_output)
1029{
0971c40e 1030 const struct dc_stream_state *stream = pipe_ctx->stream;
8e9c4c8c 1031 audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id;
4562236b
HW
1032
1033 audio_output->signal = pipe_ctx->stream->signal;
1034
1035 /* audio_crtc_info */
1036
1037 audio_output->crtc_info.h_total =
4fa086b9 1038 stream->timing.h_total;
4562236b
HW
1039
1040 /*
1041 * Audio packets are sent during actual CRTC blank physical signal, we
1042 * need to specify actual active signal portion
1043 */
1044 audio_output->crtc_info.h_active =
4fa086b9
LSL
1045 stream->timing.h_addressable
1046 + stream->timing.h_border_left
1047 + stream->timing.h_border_right;
4562236b
HW
1048
1049 audio_output->crtc_info.v_active =
4fa086b9
LSL
1050 stream->timing.v_addressable
1051 + stream->timing.v_border_top
1052 + stream->timing.v_border_bottom;
4562236b
HW
1053
1054 audio_output->crtc_info.pixel_repetition = 1;
1055
1056 audio_output->crtc_info.interlaced =
4fa086b9 1057 stream->timing.flags.INTERLACE;
4562236b
HW
1058
1059 audio_output->crtc_info.refresh_rate =
4fa086b9
LSL
1060 (stream->timing.pix_clk_khz*1000)/
1061 (stream->timing.h_total*stream->timing.v_total);
4562236b
HW
1062
1063 audio_output->crtc_info.color_depth =
4fa086b9 1064 stream->timing.display_color_depth;
4562236b
HW
1065
1066 audio_output->crtc_info.requested_pixel_clock =
10688217 1067 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
4562236b 1068
4562236b 1069 audio_output->crtc_info.calculated_pixel_clock =
10688217 1070 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
4562236b 1071
87b58768
CL
1072/*for HDMI, audio ACR is with deep color ratio factor*/
1073 if (dc_is_hdmi_signal(pipe_ctx->stream->signal) &&
1074 audio_output->crtc_info.requested_pixel_clock ==
4fa086b9 1075 stream->timing.pix_clk_khz) {
10688217 1076 if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
87b58768
CL
1077 audio_output->crtc_info.requested_pixel_clock =
1078 audio_output->crtc_info.requested_pixel_clock/2;
1079 audio_output->crtc_info.calculated_pixel_clock =
10688217 1080 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2;
87b58768 1081
87b58768
CL
1082 }
1083 }
1084
4562236b
HW
1085 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
1086 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1087 audio_output->pll_info.dp_dto_source_clock_in_khz =
ab8db3e1
AG
1088 state->dis_clk->funcs->get_dp_ref_clk_frequency(
1089 state->dis_clk);
4562236b
HW
1090 }
1091
1092 audio_output->pll_info.feed_back_divider =
1093 pipe_ctx->pll_settings.feedback_divider;
1094
1095 audio_output->pll_info.dto_source =
1096 translate_to_dto_source(
1097 pipe_ctx->pipe_idx + 1);
1098
1099 /* TODO hard code to enable for now. Need get from stream */
1100 audio_output->pll_info.ss_enabled = true;
1101
1102 audio_output->pll_info.ss_percentage =
1103 pipe_ctx->pll_settings.ss_percentage;
1104}
1105
1106static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
1107 struct tg_color *color)
1108{
1109 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4;
1110
6702a9ac 1111 switch (pipe_ctx->plane_res.scl_data.format) {
4562236b
HW
1112 case PIXEL_FORMAT_ARGB8888:
1113 /* set boarder color to red */
1114 color->color_r_cr = color_value;
1115 break;
1116
1117 case PIXEL_FORMAT_ARGB2101010:
1118 /* set boarder color to blue */
1119 color->color_b_cb = color_value;
1120 break;
87449a90 1121 case PIXEL_FORMAT_420BPP8:
4562236b
HW
1122 /* set boarder color to green */
1123 color->color_g_y = color_value;
1124 break;
87449a90
AK
1125 case PIXEL_FORMAT_420BPP10:
1126 /* set boarder color to yellow */
1127 color->color_g_y = color_value;
1128 color->color_r_cr = color_value;
1129 break;
4562236b
HW
1130 case PIXEL_FORMAT_FP16:
1131 /* set boarder color to white */
1132 color->color_r_cr = color_value;
1133 color->color_b_cb = color_value;
1134 color->color_g_y = color_value;
1135 break;
1136 default:
1137 break;
1138 }
1139}
1140
fb3466a4 1141static void program_scaler(const struct dc *dc,
4562236b
HW
1142 const struct pipe_ctx *pipe_ctx)
1143{
1144 struct tg_color color = {0};
1145
ff5ef992
AD
1146#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1147 /* TOFPGA */
86a66c4e 1148 if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
ff5ef992
AD
1149 return;
1150#endif
1151
fb3466a4 1152 if (dc->debug.surface_visual_confirm)
4562236b
HW
1153 get_surface_visual_confirm_color(pipe_ctx, &color);
1154 else
1155 color_space_to_black_color(dc,
4fa086b9 1156 pipe_ctx->stream->output_color_space,
4562236b
HW
1157 &color);
1158
86a66c4e
HW
1159 pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
1160 pipe_ctx->plane_res.xfm,
6702a9ac 1161 pipe_ctx->plane_res.scl_data.lb_params.depth,
4562236b
HW
1162 &pipe_ctx->stream->bit_depth_params);
1163
6b670fa9
HW
1164 if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color)
1165 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
1166 pipe_ctx->stream_res.tg,
4562236b
HW
1167 &color);
1168
86a66c4e 1169 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
6702a9ac 1170 &pipe_ctx->plane_res.scl_data);
4562236b
HW
1171}
1172
4b5e7d62 1173static enum dc_status dce110_prog_pixclk_crtc_otg(
4562236b 1174 struct pipe_ctx *pipe_ctx,
608ac7bb 1175 struct dc_state *context,
fb3466a4 1176 struct dc *dc)
4562236b 1177{
0971c40e 1178 struct dc_stream_state *stream = pipe_ctx->stream;
608ac7bb 1179 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
4562236b
HW
1180 pipe_ctx[pipe_ctx->pipe_idx];
1181 struct tg_color black_color = {0};
1182
1183 if (!pipe_ctx_old->stream) {
1184
1185 /* program blank color */
1186 color_space_to_black_color(dc,
4fa086b9 1187 stream->output_color_space, &black_color);
6b670fa9
HW
1188 pipe_ctx->stream_res.tg->funcs->set_blank_color(
1189 pipe_ctx->stream_res.tg,
4562236b 1190 &black_color);
4b5e7d62 1191
4562236b
HW
1192 /*
1193 * Must blank CRTC after disabling power gating and before any
1194 * programming, otherwise CRTC will be hung in bad state
1195 */
6b670fa9 1196 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
4562236b
HW
1197
1198 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
1199 pipe_ctx->clock_source,
10688217 1200 &pipe_ctx->stream_res.pix_clk_params,
4562236b
HW
1201 &pipe_ctx->pll_settings)) {
1202 BREAK_TO_DEBUGGER();
1203 return DC_ERROR_UNEXPECTED;
1204 }
1205
6b670fa9
HW
1206 pipe_ctx->stream_res.tg->funcs->program_timing(
1207 pipe_ctx->stream_res.tg,
4fa086b9 1208 &stream->timing,
4562236b 1209 true);
94267b3d 1210
6b670fa9
HW
1211 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
1212 pipe_ctx->stream_res.tg,
94267b3d 1213 0x182);
4562236b
HW
1214 }
1215
1216 if (!pipe_ctx_old->stream) {
6b670fa9
HW
1217 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(
1218 pipe_ctx->stream_res.tg)) {
4562236b
HW
1219 BREAK_TO_DEBUGGER();
1220 return DC_ERROR_UNEXPECTED;
1221 }
1222 }
1223
94267b3d
ST
1224
1225
4562236b
HW
1226 return DC_OK;
1227}
1228
1229static enum dc_status apply_single_controller_ctx_to_hw(
1230 struct pipe_ctx *pipe_ctx,
608ac7bb 1231 struct dc_state *context,
fb3466a4 1232 struct dc *dc)
4562236b 1233{
0971c40e 1234 struct dc_stream_state *stream = pipe_ctx->stream;
608ac7bb 1235 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
4562236b
HW
1236 pipe_ctx[pipe_ctx->pipe_idx];
1237
1238 /* */
1239 dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc);
1240
181a888f
CL
1241 /* FPGA does not program backend */
1242 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
f0c4d997
CM
1243 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1244 pipe_ctx->stream_res.opp,
1245 COLOR_SPACE_YCBCR601,
1246 stream->timing.display_color_depth,
1247 pipe_ctx->stream->signal);
1248
bf5563ed 1249 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
a6a6cb34 1250 pipe_ctx->stream_res.opp,
4562236b
HW
1251 &stream->bit_depth_params,
1252 &stream->clamping);
4562236b 1253 return DC_OK;
181a888f 1254 }
4562236b
HW
1255 /* TODO: move to stream encoder */
1256 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1257 if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
1258 BREAK_TO_DEBUGGER();
1259 return DC_ERROR_UNEXPECTED;
1260 }
f0c4d997
CM
1261 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1262 pipe_ctx->stream_res.opp,
1263 COLOR_SPACE_YCBCR601,
1264 stream->timing.display_color_depth,
1265 pipe_ctx->stream->signal);
4562236b
HW
1266
1267 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1268 stream->sink->link->link_enc->funcs->setup(
1269 stream->sink->link->link_enc,
1270 pipe_ctx->stream->signal);
1271
ab3c1798 1272 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
8e9c4c8c
HW
1273 pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
1274 pipe_ctx->stream_res.stream_enc,
6b670fa9 1275 pipe_ctx->stream_res.tg->inst,
4fa086b9 1276 stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE);
ab3c1798
VP
1277
1278
603767f9
TC
1279 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1280 pipe_ctx->stream_res.opp,
1281 &stream->bit_depth_params,
1282 &stream->clamping);
1283
4562236b 1284 if (dc_is_dp_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
1285 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
1286 pipe_ctx->stream_res.stream_enc,
4fa086b9
LSL
1287 &stream->timing,
1288 stream->output_color_space);
4562236b
HW
1289
1290 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
1291 pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute(
1292 pipe_ctx->stream_res.stream_enc,
4fa086b9 1293 &stream->timing,
4562236b 1294 stream->phy_pix_clk,
afaacef4 1295 pipe_ctx->stream_res.audio != NULL);
4562236b
HW
1296
1297 if (dc_is_dvi_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
1298 pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute(
1299 pipe_ctx->stream_res.stream_enc,
4fa086b9 1300 &stream->timing,
4562236b
HW
1301 (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
1302 true : false);
1303
15e17335 1304 resource_build_info_frame(pipe_ctx);
3639fa68 1305 dce110_update_info_frame(pipe_ctx);
4562236b 1306 if (!pipe_ctx_old->stream) {
d050f8ed
HW
1307 if (!pipe_ctx->stream->dpms_off)
1308 core_link_enable_stream(context, pipe_ctx);
4562236b
HW
1309 }
1310
6702a9ac 1311 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
4562236b 1312
94267b3d
ST
1313 pipe_ctx->stream->sink->link->psr_enabled = false;
1314
4562236b
HW
1315 return DC_OK;
1316}
1317
1318/******************************************************************************/
1319
fb3466a4 1320static void power_down_encoders(struct dc *dc)
4562236b
HW
1321{
1322 int i;
a0c38eba 1323 enum connector_id connector_id;
68d77dd8 1324 enum signal_type signal = SIGNAL_TYPE_NONE;
b9b171ff
HW
1325
1326 /* do not know BIOS back-front mapping, simply blank all. It will not
1327 * hurt for non-DP
1328 */
1329 for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1330 dc->res_pool->stream_enc[i]->funcs->dp_blank(
1331 dc->res_pool->stream_enc[i]);
1332 }
1333
4562236b 1334 for (i = 0; i < dc->link_count; i++) {
a0c38eba
CL
1335 connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id);
1336 if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
1337 (connector_id == CONNECTOR_ID_EDP)) {
1338
1339 if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
1340 dp_receiver_power_ctrl(dc->links[i], false);
904623ee 1341 if (connector_id == CONNECTOR_ID_EDP)
68d77dd8 1342 signal = SIGNAL_TYPE_EDP;
a0c38eba
CL
1343 }
1344
4562236b 1345 dc->links[i]->link_enc->funcs->disable_output(
069d418f 1346 dc->links[i]->link_enc, signal);
4562236b
HW
1347 }
1348}
1349
fb3466a4 1350static void power_down_controllers(struct dc *dc)
4562236b
HW
1351{
1352 int i;
1353
1354 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1355 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1356 dc->res_pool->timing_generators[i]);
1357 }
1358}
1359
fb3466a4 1360static void power_down_clock_sources(struct dc *dc)
4562236b
HW
1361{
1362 int i;
1363
1364 if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1365 dc->res_pool->dp_clock_source) == false)
1366 dm_error("Failed to power down pll! (dp clk src)\n");
1367
1368 for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1369 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1370 dc->res_pool->clock_sources[i]) == false)
1371 dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1372 }
1373}
1374
fb3466a4 1375static void power_down_all_hw_blocks(struct dc *dc)
4562236b
HW
1376{
1377 power_down_encoders(dc);
1378
1379 power_down_controllers(dc);
1380
1381 power_down_clock_sources(dc);
1663ae1c 1382
3eab7916 1383#if defined(CONFIG_DRM_AMD_DC_FBC)
2f3bfb27
RL
1384 if (dc->fbc_compressor)
1385 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1663ae1c 1386#endif
4562236b
HW
1387}
1388
1389static void disable_vga_and_power_gate_all_controllers(
fb3466a4 1390 struct dc *dc)
4562236b
HW
1391{
1392 int i;
1393 struct timing_generator *tg;
1394 struct dc_context *ctx = dc->ctx;
1395
1396 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1397 tg = dc->res_pool->timing_generators[i];
1398
0a87425a
TC
1399 if (tg->funcs->disable_vga)
1400 tg->funcs->disable_vga(tg);
4562236b
HW
1401
1402 /* Enable CLOCK gating for each pipe BEFORE controller
1403 * powergating. */
1404 enable_display_pipe_clock_gating(ctx,
1405 true);
1406
e6c258cb 1407 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
7f914a62 1408 dc->hwss.disable_plane(dc,
e6c258cb 1409 &dc->current_state->res_ctx.pipe_ctx[i]);
4562236b
HW
1410 }
1411}
1412
1413/**
1414 * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
1415 * 1. Power down all DC HW blocks
1416 * 2. Disable VGA engine on all controllers
1417 * 3. Enable power gating for controller
1418 * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
1419 */
fb3466a4 1420void dce110_enable_accelerated_mode(struct dc *dc)
4562236b
HW
1421{
1422 power_down_all_hw_blocks(dc);
1423
1424 disable_vga_and_power_gate_all_controllers(dc);
1425 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
1426}
1427
4562236b
HW
1428static uint32_t compute_pstate_blackout_duration(
1429 struct bw_fixed blackout_duration,
0971c40e 1430 const struct dc_stream_state *stream)
4562236b
HW
1431{
1432 uint32_t total_dest_line_time_ns;
1433 uint32_t pstate_blackout_duration_ns;
1434
1435 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1436
1437 total_dest_line_time_ns = 1000000UL *
4fa086b9
LSL
1438 stream->timing.h_total /
1439 stream->timing.pix_clk_khz +
4562236b
HW
1440 pstate_blackout_duration_ns;
1441
1442 return total_dest_line_time_ns;
1443}
1444
4562236b 1445void dce110_set_displaymarks(
fb3466a4 1446 const struct dc *dc,
608ac7bb 1447 struct dc_state *context)
4562236b
HW
1448{
1449 uint8_t i, num_pipes;
1450 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1451
1452 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1453 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1454 uint32_t total_dest_line_time_ns;
1455
1456 if (pipe_ctx->stream == NULL)
1457 continue;
1458
1459 total_dest_line_time_ns = compute_pstate_blackout_duration(
77a4ea53 1460 dc->bw_vbios->blackout_duration, pipe_ctx->stream);
86a66c4e
HW
1461 pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks(
1462 pipe_ctx->plane_res.mi,
9037d802
DL
1463 context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1464 context->bw.dce.stutter_exit_wm_ns[num_pipes],
1465 context->bw.dce.urgent_wm_ns[num_pipes],
4562236b
HW
1466 total_dest_line_time_ns);
1467 if (i == underlay_idx) {
1468 num_pipes++;
86a66c4e
HW
1469 pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1470 pipe_ctx->plane_res.mi,
9037d802
DL
1471 context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1472 context->bw.dce.stutter_exit_wm_ns[num_pipes],
1473 context->bw.dce.urgent_wm_ns[num_pipes],
4562236b
HW
1474 total_dest_line_time_ns);
1475 }
1476 num_pipes++;
1477 }
1478}
1479
a2b8659d
TC
1480static void set_safe_displaymarks(
1481 struct resource_context *res_ctx,
1482 const struct resource_pool *pool)
4562236b
HW
1483{
1484 int i;
a2b8659d 1485 int underlay_idx = pool->underlay_pipe_index;
9037d802 1486 struct dce_watermarks max_marks = {
4562236b 1487 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
9037d802 1488 struct dce_watermarks nbp_marks = {
4562236b
HW
1489 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1490
1491 for (i = 0; i < MAX_PIPES; i++) {
8feabd03 1492 if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
4562236b
HW
1493 continue;
1494
86a66c4e
HW
1495 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
1496 res_ctx->pipe_ctx[i].plane_res.mi,
4562236b
HW
1497 nbp_marks,
1498 max_marks,
1499 max_marks,
1500 MAX_WATERMARK);
8feabd03 1501
4562236b 1502 if (i == underlay_idx)
86a66c4e
HW
1503 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1504 res_ctx->pipe_ctx[i].plane_res.mi,
4562236b
HW
1505 nbp_marks,
1506 max_marks,
1507 max_marks,
1508 MAX_WATERMARK);
8feabd03 1509
4562236b
HW
1510 }
1511}
1512
4562236b
HW
1513/*******************************************************************************
1514 * Public functions
1515 ******************************************************************************/
1516
4562236b
HW
1517static void set_drr(struct pipe_ctx **pipe_ctx,
1518 int num_pipes, int vmin, int vmax)
1519{
1520 int i = 0;
1521 struct drr_params params = {0};
1522
1523 params.vertical_total_max = vmax;
1524 params.vertical_total_min = vmin;
1525
1526 /* TODO: If multiple pipes are to be supported, you need
1527 * some GSL stuff
1528 */
1529
1530 for (i = 0; i < num_pipes; i++) {
6b670fa9 1531 pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, &params);
4562236b
HW
1532 }
1533}
1534
72ada5f7
EC
1535static void get_position(struct pipe_ctx **pipe_ctx,
1536 int num_pipes,
1537 struct crtc_position *position)
1538{
1539 int i = 0;
1540
1541 /* TODO: handle pipes > 1
1542 */
1543 for (i = 0; i < num_pipes; i++)
6b670fa9 1544 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
72ada5f7
EC
1545}
1546
4562236b 1547static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
94267b3d 1548 int num_pipes, const struct dc_static_screen_events *events)
4562236b
HW
1549{
1550 unsigned int i;
94267b3d
ST
1551 unsigned int value = 0;
1552
1553 if (events->overlay_update)
1554 value |= 0x100;
1555 if (events->surface_update)
1556 value |= 0x80;
1557 if (events->cursor_update)
1558 value |= 0x2;
4562236b 1559
3eab7916 1560#if defined(CONFIG_DRM_AMD_DC_FBC)
c3aa1d67
BL
1561 value |= 0x84;
1562#endif
1563
4562236b 1564 for (i = 0; i < num_pipes; i++)
6b670fa9
HW
1565 pipe_ctx[i]->stream_res.tg->funcs->
1566 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
4562236b
HW
1567}
1568
1569/* unit: in_khz before mode set, get pixel clock from context. ASIC register
1570 * may not be programmed yet.
1571 * TODO: after mode set, pre_mode_set = false,
1572 * may read PLL register to get pixel clock
1573 */
1574static uint32_t get_max_pixel_clock_for_all_paths(
fb3466a4 1575 struct dc *dc,
608ac7bb 1576 struct dc_state *context,
4562236b
HW
1577 bool pre_mode_set)
1578{
1579 uint32_t max_pix_clk = 0;
1580 int i;
1581
1582 if (!pre_mode_set) {
1583 /* TODO: read ASIC register to get pixel clock */
1584 ASSERT(0);
1585 }
1586
1587 for (i = 0; i < MAX_PIPES; i++) {
1588 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1589
1590 if (pipe_ctx->stream == NULL)
1591 continue;
1592
1593 /* do not check under lay */
1594 if (pipe_ctx->top_pipe)
1595 continue;
1596
10688217 1597 if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk)
4562236b 1598 max_pix_clk =
10688217 1599 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
4562236b
HW
1600 }
1601
1602 if (max_pix_clk == 0)
1603 ASSERT(0);
1604
1605 return max_pix_clk;
1606}
1607
f6baff4d
HW
1608/*
1609 * Find clock state based on clock requested. if clock value is 0, simply
4562236b
HW
1610 * set clock state as requested without finding clock state by clock value
1611 */
f6baff4d 1612
4562236b 1613static void apply_min_clocks(
fb3466a4 1614 struct dc *dc,
608ac7bb 1615 struct dc_state *context,
e9c58bb4 1616 enum dm_pp_clocks_state *clocks_state,
4562236b
HW
1617 bool pre_mode_set)
1618{
1619 struct state_dependent_clocks req_clocks = {0};
4562236b
HW
1620
1621 if (!pre_mode_set) {
1622 /* set clock_state without verification */
ab8db3e1
AG
1623 if (context->dis_clk->funcs->set_min_clocks_state) {
1624 context->dis_clk->funcs->set_min_clocks_state(
1625 context->dis_clk, *clocks_state);
4562236b 1626 return;
5d6d185f 1627 }
4562236b 1628
2c8ad2d5 1629 /* TODO: This is incorrect. Figure out how to fix. */
ab8db3e1
AG
1630 context->dis_clk->funcs->apply_clock_voltage_request(
1631 context->dis_clk,
2c8ad2d5 1632 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
ab8db3e1 1633 context->dis_clk->cur_clocks_value.dispclk_in_khz,
2c8ad2d5
AD
1634 pre_mode_set,
1635 false);
1636
ab8db3e1
AG
1637 context->dis_clk->funcs->apply_clock_voltage_request(
1638 context->dis_clk,
2c8ad2d5 1639 DM_PP_CLOCK_TYPE_PIXELCLK,
ab8db3e1 1640 context->dis_clk->cur_clocks_value.max_pixelclk_in_khz,
2c8ad2d5
AD
1641 pre_mode_set,
1642 false);
1643
ab8db3e1
AG
1644 context->dis_clk->funcs->apply_clock_voltage_request(
1645 context->dis_clk,
2c8ad2d5 1646 DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
ab8db3e1 1647 context->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz,
2c8ad2d5
AD
1648 pre_mode_set,
1649 false);
1650 return;
4562236b
HW
1651 }
1652
1653 /* get the required state based on state dependent clocks:
1654 * display clock and pixel clock
1655 */
9037d802 1656 req_clocks.display_clk_khz = context->bw.dce.dispclk_khz;
4562236b
HW
1657
1658 req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
1659 dc, context, true);
1660
ab8db3e1
AG
1661 if (context->dis_clk->funcs->get_required_clocks_state) {
1662 *clocks_state = context->dis_clk->funcs->get_required_clocks_state(
1663 context->dis_clk, &req_clocks);
1664 context->dis_clk->funcs->set_min_clocks_state(
1665 context->dis_clk, *clocks_state);
4562236b 1666 } else {
ab8db3e1
AG
1667 context->dis_clk->funcs->apply_clock_voltage_request(
1668 context->dis_clk,
2c8ad2d5
AD
1669 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1670 req_clocks.display_clk_khz,
1671 pre_mode_set,
1672 false);
1673
ab8db3e1
AG
1674 context->dis_clk->funcs->apply_clock_voltage_request(
1675 context->dis_clk,
2c8ad2d5
AD
1676 DM_PP_CLOCK_TYPE_PIXELCLK,
1677 req_clocks.pixel_clk_khz,
1678 pre_mode_set,
1679 false);
1680
ab8db3e1
AG
1681 context->dis_clk->funcs->apply_clock_voltage_request(
1682 context->dis_clk,
2c8ad2d5
AD
1683 DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
1684 req_clocks.pixel_clk_khz,
1685 pre_mode_set,
1686 false);
4562236b
HW
1687 }
1688}
1689
3eab7916 1690#if defined(CONFIG_DRM_AMD_DC_FBC)
690b5e39
RL
1691
1692/*
1693 * Check if FBC can be enabled
1694 */
9c6569de 1695static bool should_enable_fbc(struct dc *dc,
0c813535
RL
1696 struct dc_state *context,
1697 uint32_t *pipe_idx)
690b5e39 1698{
0c813535
RL
1699 uint32_t i;
1700 struct pipe_ctx *pipe_ctx = NULL;
1701 struct resource_context *res_ctx = &context->res_ctx;
1702
690b5e39
RL
1703
1704 ASSERT(dc->fbc_compressor);
1705
1706 /* FBC memory should be allocated */
1707 if (!dc->ctx->fbc_gpu_addr)
9c6569de 1708 return false;
690b5e39
RL
1709
1710 /* Only supports single display */
1711 if (context->stream_count != 1)
9c6569de 1712 return false;
690b5e39 1713
0c813535
RL
1714 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1715 if (res_ctx->pipe_ctx[i].stream) {
1716 pipe_ctx = &res_ctx->pipe_ctx[i];
1717 *pipe_idx = i;
1718 break;
1719 }
1720 }
1721
690b5e39
RL
1722 /* Only supports eDP */
1723 if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP)
9c6569de 1724 return false;
690b5e39
RL
1725
1726 /* PSR should not be enabled */
1727 if (pipe_ctx->stream->sink->link->psr_enabled)
9c6569de 1728 return false;
690b5e39 1729
93984bbc
S
1730 /* Nothing to compress */
1731 if (!pipe_ctx->plane_state)
9c6569de 1732 return false;
93984bbc 1733
05230fa9
RL
1734 /* Only for non-linear tiling */
1735 if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
9c6569de 1736 return false;
05230fa9 1737
9c6569de 1738 return true;
690b5e39
RL
1739}
1740
1741/*
1742 * Enable FBC
1743 */
9c6569de
HW
1744static void enable_fbc(struct dc *dc,
1745 struct dc_state *context)
690b5e39 1746{
0c813535
RL
1747 uint32_t pipe_idx = 0;
1748
1749 if (should_enable_fbc(dc, context, &pipe_idx)) {
690b5e39
RL
1750 /* Program GRPH COMPRESSED ADDRESS and PITCH */
1751 struct compr_addr_and_pitch_params params = {0, 0, 0};
1752 struct compressor *compr = dc->fbc_compressor;
0c813535
RL
1753 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1754
690b5e39 1755
9c6569de
HW
1756 params.source_view_width = pipe_ctx->stream->timing.h_addressable;
1757 params.source_view_height = pipe_ctx->stream->timing.v_addressable;
690b5e39
RL
1758
1759 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
1760
1761 compr->funcs->surface_address_and_pitch(compr, &params);
1762 compr->funcs->set_fbc_invalidation_triggers(compr, 1);
1763
1764 compr->funcs->enable_fbc(compr, &params);
1765 }
690b5e39
RL
1766}
1767#endif
1768
4562236b 1769static enum dc_status apply_ctx_to_hw_fpga(
fb3466a4 1770 struct dc *dc,
608ac7bb 1771 struct dc_state *context)
4562236b
HW
1772{
1773 enum dc_status status = DC_ERROR_UNEXPECTED;
1774 int i;
1775
a2b8659d 1776 for (i = 0; i < MAX_PIPES; i++) {
4562236b 1777 struct pipe_ctx *pipe_ctx_old =
608ac7bb 1778 &dc->current_state->res_ctx.pipe_ctx[i];
4562236b
HW
1779 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1780
1781 if (pipe_ctx->stream == NULL)
1782 continue;
1783
1784 if (pipe_ctx->stream == pipe_ctx_old->stream)
1785 continue;
1786
1787 status = apply_single_controller_ctx_to_hw(
1788 pipe_ctx,
1789 context,
1790 dc);
1791
1792 if (status != DC_OK)
1793 return status;
1794 }
1795
1796 return DC_OK;
1797}
1798
54e8695e 1799static void dce110_reset_hw_ctx_wrap(
fb3466a4 1800 struct dc *dc,
608ac7bb 1801 struct dc_state *context)
4562236b
HW
1802{
1803 int i;
1804
1805 /* Reset old context */
1806 /* look up the targets that have been removed since last commit */
a2b8659d 1807 for (i = 0; i < MAX_PIPES; i++) {
4562236b 1808 struct pipe_ctx *pipe_ctx_old =
608ac7bb 1809 &dc->current_state->res_ctx.pipe_ctx[i];
4562236b
HW
1810 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1811
1812 /* Note: We need to disable output if clock sources change,
1813 * since bios does optimization and doesn't apply if changing
1814 * PHY when not already disabled.
1815 */
1816
1817 /* Skip underlay pipe since it will be handled in commit surface*/
1818 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1819 continue;
1820
1821 if (!pipe_ctx->stream ||
54e8695e 1822 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
21e67d4d
HW
1823 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1824
827f11e9
LSL
1825 /* Disable if new stream is null. O/w, if stream is
1826 * disabled already, no need to disable again.
1827 */
1828 if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off)
d050f8ed
HW
1829 core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE);
1830
6b670fa9
HW
1831 pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
1832 if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
54e8695e
DL
1833 dm_error("DC: failed to blank crtc!\n");
1834 BREAK_TO_DEBUGGER();
1835 }
6b670fa9 1836 pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
86a66c4e 1837 pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
608ac7bb 1838 pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
54e8695e 1839
21e67d4d
HW
1840 if (old_clk)
1841 old_clk->funcs->cs_power_down(old_clk);
1842
7f914a62 1843 dc->hwss.disable_plane(dc, pipe_ctx_old);
54e8695e
DL
1844
1845 pipe_ctx_old->stream = NULL;
1846 }
4562236b
HW
1847 }
1848}
1849
cf437593 1850
4562236b 1851enum dc_status dce110_apply_ctx_to_hw(
fb3466a4 1852 struct dc *dc,
608ac7bb 1853 struct dc_state *context)
4562236b
HW
1854{
1855 struct dc_bios *dcb = dc->ctx->dc_bios;
1856 enum dc_status status;
1857 int i;
e9c58bb4 1858 enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID;
4562236b
HW
1859
1860 /* Reset old context */
1861 /* look up the targets that have been removed since last commit */
1862 dc->hwss.reset_hw_ctx_wrap(dc, context);
1863
1864 /* Skip applying if no targets */
ab2541b6 1865 if (context->stream_count <= 0)
4562236b
HW
1866 return DC_OK;
1867
1868 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1869 apply_ctx_to_hw_fpga(dc, context);
1870 return DC_OK;
1871 }
1872
1873 /* Apply new context */
1874 dcb->funcs->set_scratch_critical_state(dcb, true);
1875
1876 /* below is for real asic only */
a2b8659d 1877 for (i = 0; i < dc->res_pool->pipe_count; i++) {
4562236b 1878 struct pipe_ctx *pipe_ctx_old =
608ac7bb 1879 &dc->current_state->res_ctx.pipe_ctx[i];
4562236b
HW
1880 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1881
1882 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1883 continue;
1884
1885 if (pipe_ctx->stream == pipe_ctx_old->stream) {
1886 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
1887 dce_crtc_switch_to_clk_src(dc->hwseq,
1888 pipe_ctx->clock_source, i);
1889 continue;
1890 }
1891
1892 dc->hwss.enable_display_power_gating(
1893 dc, i, dc->ctx->dc_bios,
1894 PIPE_GATING_CONTROL_DISABLE);
1895 }
1896
a2b8659d 1897 set_safe_displaymarks(&context->res_ctx, dc->res_pool);
1663ae1c 1898
3eab7916 1899#if defined(CONFIG_DRM_AMD_DC_FBC)
2f3bfb27
RL
1900 if (dc->fbc_compressor)
1901 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1663ae1c 1902#endif
4562236b
HW
1903 /*TODO: when pplib works*/
1904 apply_min_clocks(dc, context, &clocks_state, true);
1905
ff5ef992 1906#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
3639fa68 1907 if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
c66a54dc 1908 if (context->bw.dcn.calc_clk.fclk_khz
608ac7bb 1909 > dc->current_state->bw.dcn.cur_clk.fclk_khz) {
c66a54dc
DL
1910 struct dm_pp_clock_for_voltage_req clock;
1911
1912 clock.clk_type = DM_PP_CLOCK_TYPE_FCLK;
1913 clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz;
1914 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
608ac7bb 1915 dc->current_state->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
c66a54dc
DL
1916 context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1917 }
1918 if (context->bw.dcn.calc_clk.dcfclk_khz
608ac7bb 1919 > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) {
c66a54dc
DL
1920 struct dm_pp_clock_for_voltage_req clock;
1921
1922 clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
1923 clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz;
1924 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
608ac7bb 1925 dc->current_state->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
c66a54dc
DL
1926 context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1927 }
1928 if (context->bw.dcn.calc_clk.dispclk_khz
608ac7bb 1929 > dc->current_state->bw.dcn.cur_clk.dispclk_khz) {
c66a54dc
DL
1930 dc->res_pool->display_clock->funcs->set_clock(
1931 dc->res_pool->display_clock,
1932 context->bw.dcn.calc_clk.dispclk_khz);
608ac7bb 1933 dc->current_state->bw.dcn.cur_clk.dispclk_khz =
c66a54dc
DL
1934 context->bw.dcn.calc_clk.dispclk_khz;
1935 context->bw.dcn.cur_clk.dispclk_khz =
1936 context->bw.dcn.calc_clk.dispclk_khz;
1937 }
1938 } else
ff5ef992 1939#endif
9037d802 1940 if (context->bw.dce.dispclk_khz
608ac7bb 1941 > dc->current_state->bw.dce.dispclk_khz) {
a2b8659d
TC
1942 dc->res_pool->display_clock->funcs->set_clock(
1943 dc->res_pool->display_clock,
9037d802 1944 context->bw.dce.dispclk_khz * 115 / 100);
1ce71fcd 1945 }
ab8812a3
HW
1946 /* program audio wall clock. use HDMI as clock source if HDMI
1947 * audio active. Otherwise, use DP as clock source
1948 * first, loop to find any HDMI audio, if not, loop find DP audio
1949 */
1950 /* Setup audio rate clock source */
1951 /* Issue:
1952 * Audio lag happened on DP monitor when unplug a HDMI monitor
1953 *
1954 * Cause:
1955 * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
1956 * is set to either dto0 or dto1, audio should work fine.
1957 * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
1958 * set to dto0 will cause audio lag.
1959 *
1960 * Solution:
1961 * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
1962 * find first available pipe with audio, setup audio wall DTO per topology
1963 * instead of per pipe.
1964 */
a2b8659d 1965 for (i = 0; i < dc->res_pool->pipe_count; i++) {
ab8812a3
HW
1966 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1967
1968 if (pipe_ctx->stream == NULL)
1969 continue;
1970
1971 if (pipe_ctx->top_pipe)
1972 continue;
1973
1974 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
1975 continue;
1976
afaacef4 1977 if (pipe_ctx->stream_res.audio != NULL) {
ab8812a3
HW
1978 struct audio_output audio_output;
1979
ab8db3e1 1980 build_audio_output(context, pipe_ctx, &audio_output);
ab8812a3 1981
afaacef4
HW
1982 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
1983 pipe_ctx->stream_res.audio,
ab8812a3
HW
1984 pipe_ctx->stream->signal,
1985 &audio_output.crtc_info,
1986 &audio_output.pll_info);
1987 break;
1988 }
1989 }
1990
1991 /* no HDMI audio is found, try DP audio */
a2b8659d
TC
1992 if (i == dc->res_pool->pipe_count) {
1993 for (i = 0; i < dc->res_pool->pipe_count; i++) {
ab8812a3
HW
1994 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1995
1996 if (pipe_ctx->stream == NULL)
1997 continue;
1998
1999 if (pipe_ctx->top_pipe)
2000 continue;
2001
2002 if (!dc_is_dp_signal(pipe_ctx->stream->signal))
2003 continue;
2004
afaacef4 2005 if (pipe_ctx->stream_res.audio != NULL) {
ab8812a3
HW
2006 struct audio_output audio_output;
2007
ab8db3e1 2008 build_audio_output(context, pipe_ctx, &audio_output);
ab8812a3 2009
afaacef4
HW
2010 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2011 pipe_ctx->stream_res.audio,
ab8812a3
HW
2012 pipe_ctx->stream->signal,
2013 &audio_output.crtc_info,
2014 &audio_output.pll_info);
2015 break;
2016 }
2017 }
2018 }
2019
a2b8659d 2020 for (i = 0; i < dc->res_pool->pipe_count; i++) {
4562236b 2021 struct pipe_ctx *pipe_ctx_old =
608ac7bb 2022 &dc->current_state->res_ctx.pipe_ctx[i];
4562236b
HW
2023 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2024
2025 if (pipe_ctx->stream == NULL)
2026 continue;
2027
2028 if (pipe_ctx->stream == pipe_ctx_old->stream)
2029 continue;
2030
5b92d9d4 2031 if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
313bf4ff
YS
2032 continue;
2033
4562236b
HW
2034 if (pipe_ctx->top_pipe)
2035 continue;
2036
afaacef4 2037 if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) {
ab8812a3 2038
4562236b 2039 struct audio_output audio_output;
4562236b 2040
ab8db3e1 2041 build_audio_output(context, pipe_ctx, &audio_output);
4562236b
HW
2042
2043 if (dc_is_dp_signal(pipe_ctx->stream->signal))
8e9c4c8c
HW
2044 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
2045 pipe_ctx->stream_res.stream_enc,
afaacef4 2046 pipe_ctx->stream_res.audio->inst,
4fa086b9 2047 &pipe_ctx->stream->audio_info);
4562236b 2048 else
8e9c4c8c
HW
2049 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
2050 pipe_ctx->stream_res.stream_enc,
afaacef4 2051 pipe_ctx->stream_res.audio->inst,
4fa086b9 2052 &pipe_ctx->stream->audio_info,
4562236b
HW
2053 &audio_output.crtc_info);
2054
afaacef4
HW
2055 pipe_ctx->stream_res.audio->funcs->az_configure(
2056 pipe_ctx->stream_res.audio,
4562236b
HW
2057 pipe_ctx->stream->signal,
2058 &audio_output.crtc_info,
4fa086b9 2059 &pipe_ctx->stream->audio_info);
4562236b
HW
2060 }
2061
2062 status = apply_single_controller_ctx_to_hw(
2063 pipe_ctx,
2064 context,
2065 dc);
2066
2067 if (DC_OK != status)
2068 return status;
2069 }
2070
6bf52028 2071 /* pplib is notified if disp_num changed */
cf437593 2072 dc->hwss.set_bandwidth(dc, context, true);
4562236b
HW
2073
2074 /* to save power */
2075 apply_min_clocks(dc, context, &clocks_state, false);
2076
2077 dcb->funcs->set_scratch_critical_state(dcb, false);
2078
3eab7916 2079#if defined(CONFIG_DRM_AMD_DC_FBC)
690b5e39
RL
2080 if (dc->fbc_compressor)
2081 enable_fbc(dc, context);
2082
2083#endif
cf437593 2084
4562236b
HW
2085 return DC_OK;
2086}
2087
2088/*******************************************************************************
2089 * Front End programming
2090 ******************************************************************************/
2091static void set_default_colors(struct pipe_ctx *pipe_ctx)
2092{
2093 struct default_adjustment default_adjust = { 0 };
2094
2095 default_adjust.force_hw_default = false;
34996173
HW
2096 default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
2097 default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
4562236b 2098 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
6702a9ac 2099 default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
4562236b
HW
2100
2101 /* display color depth */
2102 default_adjust.color_depth =
4fa086b9 2103 pipe_ctx->stream->timing.display_color_depth;
4562236b
HW
2104
2105 /* Lb color depth */
6702a9ac 2106 default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
4562236b 2107
86a66c4e
HW
2108 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
2109 pipe_ctx->plane_res.xfm, &default_adjust);
4562236b
HW
2110}
2111
b06b7680
LE
2112
2113/*******************************************************************************
2114 * In order to turn on/off specific surface we will program
2115 * Blender + CRTC
2116 *
2117 * In case that we have two surfaces and they have a different visibility
2118 * we can't turn off the CRTC since it will turn off the entire display
2119 *
2120 * |----------------------------------------------- |
2121 * |bottom pipe|curr pipe | | |
2122 * |Surface |Surface | Blender | CRCT |
2123 * |visibility |visibility | Configuration| |
2124 * |------------------------------------------------|
2125 * | off | off | CURRENT_PIPE | blank |
2126 * | off | on | CURRENT_PIPE | unblank |
2127 * | on | off | OTHER_PIPE | unblank |
2128 * | on | on | BLENDING | unblank |
2129 * -------------------------------------------------|
2130 *
2131 ******************************************************************************/
fb3466a4 2132static void program_surface_visibility(const struct dc *dc,
4562236b
HW
2133 struct pipe_ctx *pipe_ctx)
2134{
2135 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
b06b7680 2136 bool blank_target = false;
4562236b
HW
2137
2138 if (pipe_ctx->bottom_pipe) {
b06b7680
LE
2139
2140 /* For now we are supporting only two pipes */
2141 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
2142
3be5262e
HW
2143 if (pipe_ctx->bottom_pipe->plane_state->visible) {
2144 if (pipe_ctx->plane_state->visible)
4562236b
HW
2145 blender_mode = BLND_MODE_BLENDING;
2146 else
2147 blender_mode = BLND_MODE_OTHER_PIPE;
b06b7680 2148
3be5262e 2149 } else if (!pipe_ctx->plane_state->visible)
b06b7680
LE
2150 blank_target = true;
2151
3be5262e 2152 } else if (!pipe_ctx->plane_state->visible)
b06b7680
LE
2153 blank_target = true;
2154
4562236b 2155 dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode);
6b670fa9 2156 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
b06b7680 2157
4562236b
HW
2158}
2159
1bf56e62
ZF
2160static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
2161{
2162 struct xfm_grph_csc_adjustment adjust;
2163 memset(&adjust, 0, sizeof(adjust));
2164 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2165
2166
4fa086b9 2167 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
1bf56e62
ZF
2168 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2169 adjust.temperature_matrix[0] =
2170 pipe_ctx->stream->
4fa086b9 2171 gamut_remap_matrix.matrix[0];
1bf56e62
ZF
2172 adjust.temperature_matrix[1] =
2173 pipe_ctx->stream->
4fa086b9 2174 gamut_remap_matrix.matrix[1];
1bf56e62
ZF
2175 adjust.temperature_matrix[2] =
2176 pipe_ctx->stream->
4fa086b9 2177 gamut_remap_matrix.matrix[2];
1bf56e62
ZF
2178 adjust.temperature_matrix[3] =
2179 pipe_ctx->stream->
4fa086b9 2180 gamut_remap_matrix.matrix[4];
1bf56e62
ZF
2181 adjust.temperature_matrix[4] =
2182 pipe_ctx->stream->
4fa086b9 2183 gamut_remap_matrix.matrix[5];
1bf56e62
ZF
2184 adjust.temperature_matrix[5] =
2185 pipe_ctx->stream->
4fa086b9 2186 gamut_remap_matrix.matrix[6];
1bf56e62
ZF
2187 adjust.temperature_matrix[6] =
2188 pipe_ctx->stream->
4fa086b9 2189 gamut_remap_matrix.matrix[8];
1bf56e62
ZF
2190 adjust.temperature_matrix[7] =
2191 pipe_ctx->stream->
4fa086b9 2192 gamut_remap_matrix.matrix[9];
1bf56e62
ZF
2193 adjust.temperature_matrix[8] =
2194 pipe_ctx->stream->
4fa086b9 2195 gamut_remap_matrix.matrix[10];
1bf56e62
ZF
2196 }
2197
86a66c4e 2198 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
1bf56e62
ZF
2199}
2200
4562236b
HW
2201/**
2202 * TODO REMOVE, USE UPDATE INSTEAD
2203 */
2204static void set_plane_config(
fb3466a4 2205 const struct dc *dc,
4562236b
HW
2206 struct pipe_ctx *pipe_ctx,
2207 struct resource_context *res_ctx)
2208{
86a66c4e 2209 struct mem_input *mi = pipe_ctx->plane_res.mi;
3be5262e 2210 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
4562236b
HW
2211 struct xfm_grph_csc_adjustment adjust;
2212 struct out_csc_color_matrix tbl_entry;
2213 unsigned int i;
2214
2215 memset(&adjust, 0, sizeof(adjust));
2216 memset(&tbl_entry, 0, sizeof(tbl_entry));
2217 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2218
2219 dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
2220
2221 set_default_colors(pipe_ctx);
56ef6ed9 2222 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
4562236b 2223 tbl_entry.color_space =
4fa086b9 2224 pipe_ctx->stream->output_color_space;
4562236b
HW
2225
2226 for (i = 0; i < 12; i++)
2227 tbl_entry.regval[i] =
4fa086b9 2228 pipe_ctx->stream->csc_color_matrix.matrix[i];
4562236b 2229
86a66c4e
HW
2230 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2231 (pipe_ctx->plane_res.xfm, &tbl_entry);
4562236b
HW
2232 }
2233
4fa086b9 2234 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
4562236b
HW
2235 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2236 adjust.temperature_matrix[0] =
2237 pipe_ctx->stream->
4fa086b9 2238 gamut_remap_matrix.matrix[0];
4562236b
HW
2239 adjust.temperature_matrix[1] =
2240 pipe_ctx->stream->
4fa086b9 2241 gamut_remap_matrix.matrix[1];
4562236b
HW
2242 adjust.temperature_matrix[2] =
2243 pipe_ctx->stream->
4fa086b9 2244 gamut_remap_matrix.matrix[2];
4562236b
HW
2245 adjust.temperature_matrix[3] =
2246 pipe_ctx->stream->
4fa086b9 2247 gamut_remap_matrix.matrix[4];
4562236b
HW
2248 adjust.temperature_matrix[4] =
2249 pipe_ctx->stream->
4fa086b9 2250 gamut_remap_matrix.matrix[5];
4562236b
HW
2251 adjust.temperature_matrix[5] =
2252 pipe_ctx->stream->
4fa086b9 2253 gamut_remap_matrix.matrix[6];
4562236b
HW
2254 adjust.temperature_matrix[6] =
2255 pipe_ctx->stream->
4fa086b9 2256 gamut_remap_matrix.matrix[8];
4562236b
HW
2257 adjust.temperature_matrix[7] =
2258 pipe_ctx->stream->
4fa086b9 2259 gamut_remap_matrix.matrix[9];
4562236b
HW
2260 adjust.temperature_matrix[8] =
2261 pipe_ctx->stream->
4fa086b9 2262 gamut_remap_matrix.matrix[10];
4562236b
HW
2263 }
2264
86a66c4e 2265 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
4562236b 2266
6702a9ac 2267 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
4562236b
HW
2268 program_scaler(dc, pipe_ctx);
2269
b06b7680 2270 program_surface_visibility(dc, pipe_ctx);
4562236b
HW
2271
2272 mi->funcs->mem_input_program_surface_config(
2273 mi,
3be5262e
HW
2274 plane_state->format,
2275 &plane_state->tiling_info,
2276 &plane_state->plane_size,
2277 plane_state->rotation,
4562236b 2278 NULL,
4b28b76b
DL
2279 false);
2280 if (mi->funcs->set_blank)
3be5262e 2281 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
4562236b 2282
fb3466a4 2283 if (dc->config.gpu_vm_support)
4562236b 2284 mi->funcs->mem_input_program_pte_vm(
86a66c4e 2285 pipe_ctx->plane_res.mi,
3be5262e
HW
2286 plane_state->format,
2287 &plane_state->tiling_info,
2288 plane_state->rotation);
4562236b
HW
2289}
2290
fb3466a4 2291static void update_plane_addr(const struct dc *dc,
4562236b
HW
2292 struct pipe_ctx *pipe_ctx)
2293{
3be5262e 2294 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
4562236b 2295
3be5262e 2296 if (plane_state == NULL)
4562236b
HW
2297 return;
2298
86a66c4e
HW
2299 pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr(
2300 pipe_ctx->plane_res.mi,
3be5262e
HW
2301 &plane_state->address,
2302 plane_state->flip_immediate);
4562236b 2303
3be5262e 2304 plane_state->status.requested_address = plane_state->address;
4562236b
HW
2305}
2306
2307void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
2308{
3be5262e 2309 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
4562236b 2310
3be5262e 2311 if (plane_state == NULL)
4562236b
HW
2312 return;
2313
3be5262e 2314 plane_state->status.is_flip_pending =
86a66c4e
HW
2315 pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending(
2316 pipe_ctx->plane_res.mi);
4562236b 2317
3be5262e 2318 if (plane_state->status.is_flip_pending && !plane_state->visible)
86a66c4e 2319 pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address;
4562236b 2320
86a66c4e
HW
2321 plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address;
2322 if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
6b670fa9 2323 pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) {
3be5262e 2324 plane_state->status.is_right_eye =\
6b670fa9 2325 !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
7f5c22d1 2326 }
4562236b
HW
2327}
2328
fb3466a4 2329void dce110_power_down(struct dc *dc)
4562236b
HW
2330{
2331 power_down_all_hw_blocks(dc);
2332 disable_vga_and_power_gate_all_controllers(dc);
2333}
2334
2335static bool wait_for_reset_trigger_to_occur(
2336 struct dc_context *dc_ctx,
2337 struct timing_generator *tg)
2338{
2339 bool rc = false;
2340
2341 /* To avoid endless loop we wait at most
2342 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
2343 const uint32_t frames_to_wait_on_triggered_reset = 10;
2344 uint32_t i;
2345
2346 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
2347
2348 if (!tg->funcs->is_counter_moving(tg)) {
2349 DC_ERROR("TG counter is not moving!\n");
2350 break;
2351 }
2352
2353 if (tg->funcs->did_triggered_reset_occur(tg)) {
2354 rc = true;
2355 /* usually occurs at i=1 */
2356 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
2357 i);
2358 break;
2359 }
2360
2361 /* Wait for one frame. */
2362 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
2363 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
2364 }
2365
2366 if (false == rc)
2367 DC_ERROR("GSL: Timeout on reset trigger!\n");
2368
2369 return rc;
2370}
2371
2372/* Enable timing synchronization for a group of Timing Generators. */
2373static void dce110_enable_timing_synchronization(
fb3466a4 2374 struct dc *dc,
4562236b
HW
2375 int group_index,
2376 int group_size,
2377 struct pipe_ctx *grouped_pipes[])
2378{
2379 struct dc_context *dc_ctx = dc->ctx;
2380 struct dcp_gsl_params gsl_params = { 0 };
2381 int i;
2382
2383 DC_SYNC_INFO("GSL: Setting-up...\n");
2384
2385 /* Designate a single TG in the group as a master.
2386 * Since HW doesn't care which one, we always assign
2387 * the 1st one in the group. */
2388 gsl_params.gsl_group = 0;
6b670fa9 2389 gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst;
4562236b
HW
2390
2391 for (i = 0; i < group_size; i++)
6b670fa9
HW
2392 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2393 grouped_pipes[i]->stream_res.tg, &gsl_params);
4562236b
HW
2394
2395 /* Reset slave controllers on master VSync */
2396 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2397
2398 for (i = 1 /* skip the master */; i < group_size; i++)
6b670fa9 2399 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
fa2123db
ML
2400 grouped_pipes[i]->stream_res.tg,
2401 gsl_params.gsl_group);
4562236b
HW
2402
2403 for (i = 1 /* skip the master */; i < group_size; i++) {
2404 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
6b670fa9 2405 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
fa2123db
ML
2406 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2407 grouped_pipes[i]->stream_res.tg);
4562236b
HW
2408 }
2409
4562236b
HW
2410 /* GSL Vblank synchronization is a one time sync mechanism, assumption
2411 * is that the sync'ed displays will not drift out of sync over time*/
2412 DC_SYNC_INFO("GSL: Restoring register states.\n");
2413 for (i = 0; i < group_size; i++)
6b670fa9 2414 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
4562236b
HW
2415
2416 DC_SYNC_INFO("GSL: Set-up complete.\n");
2417}
2418
fa2123db
ML
2419static void dce110_enable_per_frame_crtc_position_reset(
2420 struct dc *dc,
2421 int group_size,
2422 struct pipe_ctx *grouped_pipes[])
2423{
2424 struct dc_context *dc_ctx = dc->ctx;
2425 struct dcp_gsl_params gsl_params = { 0 };
2426 int i;
2427
2428 gsl_params.gsl_group = 0;
2429 gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst;
2430
2431 for (i = 0; i < group_size; i++)
2432 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2433 grouped_pipes[i]->stream_res.tg, &gsl_params);
2434
2435 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2436
2437 for (i = 1; i < group_size; i++)
2438 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2439 grouped_pipes[i]->stream_res.tg,
2440 gsl_params.gsl_master,
2441 &grouped_pipes[i]->stream->triggered_crtc_reset);
2442
2443 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2444 for (i = 1; i < group_size; i++)
2445 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2446
2447 for (i = 0; i < group_size; i++)
2448 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2449
2450}
2451
fb3466a4 2452static void init_hw(struct dc *dc)
4562236b
HW
2453{
2454 int i;
2455 struct dc_bios *bp;
2456 struct transform *xfm;
5e7773a2 2457 struct abm *abm;
4562236b
HW
2458
2459 bp = dc->ctx->dc_bios;
2460 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2461 xfm = dc->res_pool->transforms[i];
2462 xfm->funcs->transform_reset(xfm);
2463
2464 dc->hwss.enable_display_power_gating(
2465 dc, i, bp,
2466 PIPE_GATING_CONTROL_INIT);
2467 dc->hwss.enable_display_power_gating(
2468 dc, i, bp,
2469 PIPE_GATING_CONTROL_DISABLE);
2470 dc->hwss.enable_display_pipe_clock_gating(
2471 dc->ctx,
2472 true);
2473 }
2474
e166ad43 2475 dce_clock_gating_power_up(dc->hwseq, false);
4562236b
HW
2476 /***************************************/
2477
2478 for (i = 0; i < dc->link_count; i++) {
2479 /****************************************/
2480 /* Power up AND update implementation according to the
2481 * required signal (which may be different from the
2482 * default signal on connector). */
d0778ebf 2483 struct dc_link *link = dc->links[i];
069d418f
AJ
2484
2485 if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
2486 dc->hwss.edp_power_control(link, true);
2487
4562236b
HW
2488 link->link_enc->funcs->hw_init(link->link_enc);
2489 }
2490
2491 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2492 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2493
2494 tg->funcs->disable_vga(tg);
2495
2496 /* Blank controller using driver code instead of
2497 * command table. */
2498 tg->funcs->set_blank(tg, true);
4b5e7d62 2499 hwss_wait_for_blank_complete(tg);
4562236b
HW
2500 }
2501
2502 for (i = 0; i < dc->res_pool->audio_count; i++) {
2503 struct audio *audio = dc->res_pool->audios[i];
2504 audio->funcs->hw_init(audio);
2505 }
5e7773a2
AK
2506
2507 abm = dc->res_pool->abm;
6728b30c
AK
2508 if (abm != NULL) {
2509 abm->funcs->init_backlight(abm);
5e7773a2 2510 abm->funcs->abm_init(abm);
6728b30c 2511 }
3eab7916 2512#if defined(CONFIG_DRM_AMD_DC_FBC)
2f3bfb27
RL
2513 if (dc->fbc_compressor)
2514 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
1663ae1c 2515#endif
690b5e39 2516
4562236b
HW
2517}
2518
28f72454 2519void dce110_fill_display_configs(
608ac7bb 2520 const struct dc_state *context,
cf437593
DL
2521 struct dm_pp_display_configuration *pp_display_cfg)
2522{
2523 int j;
2524 int num_cfgs = 0;
2525
2526 for (j = 0; j < context->stream_count; j++) {
2527 int k;
2528
0971c40e 2529 const struct dc_stream_state *stream = context->streams[j];
cf437593
DL
2530 struct dm_pp_single_disp_config *cfg =
2531 &pp_display_cfg->disp_configs[num_cfgs];
2532 const struct pipe_ctx *pipe_ctx = NULL;
2533
2534 for (k = 0; k < MAX_PIPES; k++)
2535 if (stream == context->res_ctx.pipe_ctx[k].stream) {
2536 pipe_ctx = &context->res_ctx.pipe_ctx[k];
2537 break;
2538 }
2539
2540 ASSERT(pipe_ctx != NULL);
2541
631aaa0a
HW
2542 /* only notify active stream */
2543 if (stream->dpms_off)
2544 continue;
2545
cf437593
DL
2546 num_cfgs++;
2547 cfg->signal = pipe_ctx->stream->signal;
2548 cfg->pipe_idx = pipe_ctx->pipe_idx;
4fa086b9
LSL
2549 cfg->src_height = stream->src.height;
2550 cfg->src_width = stream->src.width;
cf437593
DL
2551 cfg->ddi_channel_mapping =
2552 stream->sink->link->ddi_channel_mapping.raw;
2553 cfg->transmitter =
2554 stream->sink->link->link_enc->transmitter;
2555 cfg->link_settings.lane_count =
d0778ebf 2556 stream->sink->link->cur_link_settings.lane_count;
cf437593 2557 cfg->link_settings.link_rate =
d0778ebf 2558 stream->sink->link->cur_link_settings.link_rate;
cf437593 2559 cfg->link_settings.link_spread =
d0778ebf 2560 stream->sink->link->cur_link_settings.link_spread;
cf437593
DL
2561 cfg->sym_clock = stream->phy_pix_clk;
2562 /* Round v_refresh*/
4fa086b9
LSL
2563 cfg->v_refresh = stream->timing.pix_clk_khz * 1000;
2564 cfg->v_refresh /= stream->timing.h_total;
2565 cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)
2566 / stream->timing.v_total;
cf437593
DL
2567 }
2568
2569 pp_display_cfg->display_count = num_cfgs;
2570}
2571
608ac7bb 2572uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
4562236b 2573{
cf437593
DL
2574 uint8_t j;
2575 uint32_t min_vertical_blank_time = -1;
2576
bf5563ed
DA
2577 for (j = 0; j < context->stream_count; j++) {
2578 struct dc_stream_state *stream = context->streams[j];
2579 uint32_t vertical_blank_in_pixels = 0;
2580 uint32_t vertical_blank_time = 0;
cf437593 2581
bf5563ed
DA
2582 vertical_blank_in_pixels = stream->timing.h_total *
2583 (stream->timing.v_total
2584 - stream->timing.v_addressable);
cf437593 2585
bf5563ed
DA
2586 vertical_blank_time = vertical_blank_in_pixels
2587 * 1000 / stream->timing.pix_clk_khz;
cf437593 2588
bf5563ed
DA
2589 if (min_vertical_blank_time > vertical_blank_time)
2590 min_vertical_blank_time = vertical_blank_time;
2591 }
cf437593
DL
2592
2593 return min_vertical_blank_time;
4562236b
HW
2594}
2595
cf437593 2596static int determine_sclk_from_bounding_box(
fb3466a4 2597 const struct dc *dc,
cf437593 2598 int required_sclk)
4562236b
HW
2599{
2600 int i;
2601
cf437593
DL
2602 /*
2603 * Some asics do not give us sclk levels, so we just report the actual
2604 * required sclk
2605 */
2606 if (dc->sclk_lvls.num_levels == 0)
2607 return required_sclk;
4562236b 2608
cf437593
DL
2609 for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
2610 if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
2611 return dc->sclk_lvls.clocks_in_khz[i];
2612 }
2613 /*
2614 * even maximum level could not satisfy requirement, this
2615 * is unexpected at this stage, should have been caught at
2616 * validation time
2617 */
2618 ASSERT(0);
2619 return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
2620}
2621
2622static void pplib_apply_display_requirements(
fb3466a4 2623 struct dc *dc,
608ac7bb 2624 struct dc_state *context)
cf437593
DL
2625{
2626 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2627
2628 pp_display_cfg->all_displays_in_sync =
9037d802 2629 context->bw.dce.all_displays_in_sync;
cf437593 2630 pp_display_cfg->nb_pstate_switch_disable =
9037d802 2631 context->bw.dce.nbp_state_change_enable == false;
cf437593 2632 pp_display_cfg->cpu_cc6_disable =
9037d802 2633 context->bw.dce.cpuc_state_change_enable == false;
cf437593 2634 pp_display_cfg->cpu_pstate_disable =
9037d802 2635 context->bw.dce.cpup_state_change_enable == false;
cf437593 2636 pp_display_cfg->cpu_pstate_separation_time =
9037d802 2637 context->bw.dce.blackout_recovery_time_us;
cf437593 2638
9037d802 2639 pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz
cf437593
DL
2640 / MEMORY_TYPE_MULTIPLIER;
2641
2642 pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
2643 dc,
9037d802 2644 context->bw.dce.sclk_khz);
cf437593
DL
2645
2646 pp_display_cfg->min_engine_clock_deep_sleep_khz
9037d802 2647 = context->bw.dce.sclk_deep_sleep_khz;
cf437593
DL
2648
2649 pp_display_cfg->avail_mclk_switch_time_us =
28f72454 2650 dce110_get_min_vblank_time_us(context);
cf437593
DL
2651 /* TODO: dce11.2*/
2652 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
4562236b 2653
9037d802 2654 pp_display_cfg->disp_clk_khz = context->bw.dce.dispclk_khz;
cf437593 2655
28f72454 2656 dce110_fill_display_configs(context, pp_display_cfg);
cf437593
DL
2657
2658 /* TODO: is this still applicable?*/
2659 if (pp_display_cfg->display_count == 1) {
2660 const struct dc_crtc_timing *timing =
4fa086b9 2661 &context->streams[0]->timing;
cf437593
DL
2662
2663 pp_display_cfg->crtc_index =
2664 pp_display_cfg->disp_configs[0].pipe_idx;
2665 pp_display_cfg->line_time_in_us = timing->h_total * 1000
2666 / timing->pix_clk_khz;
2667 }
2668
2669 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2670 struct dm_pp_display_configuration)) != 0)
2671 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2672
2673 dc->prev_display_config = *pp_display_cfg;
2674}
2675
2676static void dce110_set_bandwidth(
fb3466a4 2677 struct dc *dc,
608ac7bb 2678 struct dc_state *context,
cf437593
DL
2679 bool decrease_allowed)
2680{
2180e7cc 2681 dce110_set_displaymarks(dc, context);
cf437593 2682
608ac7bb 2683 if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) {
a2b8659d
TC
2684 dc->res_pool->display_clock->funcs->set_clock(
2685 dc->res_pool->display_clock,
9037d802 2686 context->bw.dce.dispclk_khz * 115 / 100);
608ac7bb 2687 dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz;
4562236b
HW
2688 }
2689
cf437593 2690 pplib_apply_display_requirements(dc, context);
4562236b
HW
2691}
2692
2693static void dce110_program_front_end_for_pipe(
fb3466a4 2694 struct dc *dc, struct pipe_ctx *pipe_ctx)
4562236b 2695{
86a66c4e 2696 struct mem_input *mi = pipe_ctx->plane_res.mi;
4562236b 2697 struct pipe_ctx *old_pipe = NULL;
3be5262e 2698 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
4562236b
HW
2699 struct xfm_grph_csc_adjustment adjust;
2700 struct out_csc_color_matrix tbl_entry;
a6114e85 2701 struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
4562236b
HW
2702 unsigned int i;
2703
2704 memset(&tbl_entry, 0, sizeof(tbl_entry));
2705
608ac7bb
JZ
2706 if (dc->current_state)
2707 old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
4562236b
HW
2708
2709 memset(&adjust, 0, sizeof(adjust));
2710 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2711
2712 dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
2713
2714 set_default_colors(pipe_ctx);
4fa086b9 2715 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
4562236b
HW
2716 == true) {
2717 tbl_entry.color_space =
4fa086b9 2718 pipe_ctx->stream->output_color_space;
4562236b
HW
2719
2720 for (i = 0; i < 12; i++)
2721 tbl_entry.regval[i] =
4fa086b9 2722 pipe_ctx->stream->csc_color_matrix.matrix[i];
4562236b 2723
86a66c4e
HW
2724 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2725 (pipe_ctx->plane_res.xfm, &tbl_entry);
4562236b
HW
2726 }
2727
4fa086b9 2728 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
4562236b
HW
2729 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2730 adjust.temperature_matrix[0] =
2731 pipe_ctx->stream->
4fa086b9 2732 gamut_remap_matrix.matrix[0];
4562236b
HW
2733 adjust.temperature_matrix[1] =
2734 pipe_ctx->stream->
4fa086b9 2735 gamut_remap_matrix.matrix[1];
4562236b
HW
2736 adjust.temperature_matrix[2] =
2737 pipe_ctx->stream->
4fa086b9 2738 gamut_remap_matrix.matrix[2];
4562236b
HW
2739 adjust.temperature_matrix[3] =
2740 pipe_ctx->stream->
4fa086b9 2741 gamut_remap_matrix.matrix[4];
4562236b
HW
2742 adjust.temperature_matrix[4] =
2743 pipe_ctx->stream->
4fa086b9 2744 gamut_remap_matrix.matrix[5];
4562236b
HW
2745 adjust.temperature_matrix[5] =
2746 pipe_ctx->stream->
4fa086b9 2747 gamut_remap_matrix.matrix[6];
4562236b
HW
2748 adjust.temperature_matrix[6] =
2749 pipe_ctx->stream->
4fa086b9 2750 gamut_remap_matrix.matrix[8];
4562236b
HW
2751 adjust.temperature_matrix[7] =
2752 pipe_ctx->stream->
4fa086b9 2753 gamut_remap_matrix.matrix[9];
4562236b
HW
2754 adjust.temperature_matrix[8] =
2755 pipe_ctx->stream->
4fa086b9 2756 gamut_remap_matrix.matrix[10];
4562236b
HW
2757 }
2758
86a66c4e 2759 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
4562236b 2760
6702a9ac 2761 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
c1473558
AG
2762
2763 program_scaler(dc, pipe_ctx);
4562236b 2764
3eab7916 2765#if defined(CONFIG_DRM_AMD_DC_FBC)
e008b0bc
RL
2766 if (dc->fbc_compressor && old_pipe->stream) {
2767 if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
2768 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2769 else
2770 enable_fbc(dc, dc->current_state);
2771 }
2772#endif
2773
4562236b
HW
2774 mi->funcs->mem_input_program_surface_config(
2775 mi,
3be5262e
HW
2776 plane_state->format,
2777 &plane_state->tiling_info,
2778 &plane_state->plane_size,
2779 plane_state->rotation,
624d7c47 2780 NULL,
4b28b76b
DL
2781 false);
2782 if (mi->funcs->set_blank)
3be5262e 2783 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
4562236b 2784
fb3466a4 2785 if (dc->config.gpu_vm_support)
4562236b 2786 mi->funcs->mem_input_program_pte_vm(
86a66c4e 2787 pipe_ctx->plane_res.mi,
3be5262e
HW
2788 plane_state->format,
2789 &plane_state->tiling_info,
2790 plane_state->rotation);
4562236b 2791
067c878a
YS
2792 /* Moved programming gamma from dc to hwss */
2793 if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) {
a6114e85
HW
2794 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2795 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
067c878a
YS
2796 }
2797
4562236b
HW
2798 dm_logger_write(dc->ctx->logger, LOG_SURFACE,
2799 "Pipe:%d 0x%x: addr hi:0x%x, "
2800 "addr low:0x%x, "
2801 "src: %d, %d, %d,"
2802 " %d; dst: %d, %d, %d, %d;"
2803 "clip: %d, %d, %d, %d\n",
2804 pipe_ctx->pipe_idx,
3be5262e
HW
2805 pipe_ctx->plane_state,
2806 pipe_ctx->plane_state->address.grph.addr.high_part,
2807 pipe_ctx->plane_state->address.grph.addr.low_part,
2808 pipe_ctx->plane_state->src_rect.x,
2809 pipe_ctx->plane_state->src_rect.y,
2810 pipe_ctx->plane_state->src_rect.width,
2811 pipe_ctx->plane_state->src_rect.height,
2812 pipe_ctx->plane_state->dst_rect.x,
2813 pipe_ctx->plane_state->dst_rect.y,
2814 pipe_ctx->plane_state->dst_rect.width,
2815 pipe_ctx->plane_state->dst_rect.height,
2816 pipe_ctx->plane_state->clip_rect.x,
2817 pipe_ctx->plane_state->clip_rect.y,
2818 pipe_ctx->plane_state->clip_rect.width,
2819 pipe_ctx->plane_state->clip_rect.height);
4562236b
HW
2820
2821 dm_logger_write(dc->ctx->logger, LOG_SURFACE,
2822 "Pipe %d: width, height, x, y\n"
2823 "viewport:%d, %d, %d, %d\n"
2824 "recout: %d, %d, %d, %d\n",
2825 pipe_ctx->pipe_idx,
6702a9ac
HW
2826 pipe_ctx->plane_res.scl_data.viewport.width,
2827 pipe_ctx->plane_res.scl_data.viewport.height,
2828 pipe_ctx->plane_res.scl_data.viewport.x,
2829 pipe_ctx->plane_res.scl_data.viewport.y,
2830 pipe_ctx->plane_res.scl_data.recout.width,
2831 pipe_ctx->plane_res.scl_data.recout.height,
2832 pipe_ctx->plane_res.scl_data.recout.x,
2833 pipe_ctx->plane_res.scl_data.recout.y);
4562236b
HW
2834}
2835
4562236b 2836static void dce110_apply_ctx_for_surface(
fb3466a4 2837 struct dc *dc,
3e9ad616
EY
2838 const struct dc_stream_state *stream,
2839 int num_planes,
608ac7bb 2840 struct dc_state *context)
4562236b 2841{
2194e3ae 2842 int i;
4562236b 2843
3e9ad616 2844 if (num_planes == 0)
4562236b
HW
2845 return;
2846
3e9ad616 2847 for (i = 0; i < dc->res_pool->pipe_count; i++) {
3dc780ec
YS
2848 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2849 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2850
2194e3ae 2851 if (stream == pipe_ctx->stream) {
3dc780ec
YS
2852 if (!pipe_ctx->top_pipe &&
2853 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2854 dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
3e9ad616
EY
2855 }
2856 }
2857
a2b8659d 2858 for (i = 0; i < dc->res_pool->pipe_count; i++) {
4562236b
HW
2859 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2860
a2607aef 2861 if (pipe_ctx->stream != stream)
4562236b
HW
2862 continue;
2863
3b21b6d2 2864 /* Need to allocate mem before program front end for Fiji */
ede56984
HW
2865 pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
2866 pipe_ctx->plane_res.mi,
2867 pipe_ctx->stream->timing.h_total,
2868 pipe_ctx->stream->timing.v_total,
2869 pipe_ctx->stream->timing.pix_clk_khz,
2870 context->stream_count);
3b21b6d2 2871
4562236b 2872 dce110_program_front_end_for_pipe(dc, pipe_ctx);
4f804817
YS
2873
2874 dc->hwss.update_plane_addr(dc, pipe_ctx);
2875
b06b7680 2876 program_surface_visibility(dc, pipe_ctx);
4562236b
HW
2877
2878 }
3dc780ec
YS
2879
2880 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2881 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2882 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2883
2884 if ((stream == pipe_ctx->stream) &&
2885 (!pipe_ctx->top_pipe) &&
2886 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2887 dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
2888 }
4562236b
HW
2889}
2890
e6c258cb 2891static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
4562236b 2892{
e6c258cb
YS
2893 int fe_idx = pipe_ctx->pipe_idx;
2894
7950f0f9 2895 /* Do not power down fe when stream is active on dce*/
608ac7bb 2896 if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream)
4562236b
HW
2897 return;
2898
2899 dc->hwss.enable_display_power_gating(
cfe4645e
DL
2900 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2901
2902 dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
2903 dc->res_pool->transforms[fe_idx]);
4562236b
HW
2904}
2905
6be425f3 2906static void dce110_wait_for_mpcc_disconnect(
fb3466a4 2907 struct dc *dc,
6be425f3
EY
2908 struct resource_pool *res_pool,
2909 struct pipe_ctx *pipe_ctx)
b6762f0c
EY
2910{
2911 /* do nothing*/
2912}
2913
bdf9a1a0
YHL
2914static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
2915 enum dc_color_space colorspace,
2916 uint16_t *matrix)
2917{
2918 int i;
2919 struct out_csc_color_matrix tbl_entry;
2920
2921 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2922 == true) {
2923 enum dc_color_space color_space =
2924 pipe_ctx->stream->output_color_space;
2925
2926 //uint16_t matrix[12];
2927 for (i = 0; i < 12; i++)
2928 tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
2929
2930 tbl_entry.color_space = color_space;
2931 //tbl_entry.regval = matrix;
86a66c4e 2932 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry);
bdf9a1a0
YHL
2933 }
2934}
2935
39b485e4
EY
2936void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
2937{
2938 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2939 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
2940 struct mem_input *mi = pipe_ctx->plane_res.mi;
2941 struct dc_cursor_mi_param param = {
2942 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
2943 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
2944 .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
2945 .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
2946 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
2947 };
2948
2949 if (pipe_ctx->plane_state->address.type
2950 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2951 pos_cpy.enable = false;
2952
2953 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2954 pos_cpy.enable = false;
2955
8378fc7e
RL
2956 if (ipp->funcs->ipp_cursor_set_position)
2957 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
2958 if (mi->funcs->set_cursor_position)
2959 mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
39b485e4
EY
2960}
2961
2962void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2963{
2964 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2965
8378fc7e
RL
2966 if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
2967 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
39b485e4
EY
2968 pipe_ctx->plane_res.ipp, attributes);
2969
8378fc7e
RL
2970 if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
2971 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
2972 pipe_ctx->plane_res.mi, attributes);
39b485e4 2973
8378fc7e
RL
2974 if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
2975 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
2976 pipe_ctx->plane_res.xfm, attributes);
39b485e4
EY
2977}
2978
6bf52028 2979static void ready_shared_resources(struct dc *dc, struct dc_state *context) {}
41f97c07
HW
2980
2981static void optimize_shared_resources(struct dc *dc) {}
2982
4562236b 2983static const struct hw_sequencer_funcs dce110_funcs = {
1bf56e62 2984 .program_gamut_remap = program_gamut_remap,
bdf9a1a0 2985 .program_csc_matrix = program_csc_matrix,
4562236b
HW
2986 .init_hw = init_hw,
2987 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
4562236b
HW
2988 .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2989 .set_plane_config = set_plane_config,
2990 .update_plane_addr = update_plane_addr,
2991 .update_pending_status = dce110_update_pending_status,
d7194cf6 2992 .set_input_transfer_func = dce110_set_input_transfer_func,
90e508ba 2993 .set_output_transfer_func = dce110_set_output_transfer_func,
4562236b
HW
2994 .power_down = dce110_power_down,
2995 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2996 .enable_timing_synchronization = dce110_enable_timing_synchronization,
fa2123db 2997 .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset,
4562236b
HW
2998 .update_info_frame = dce110_update_info_frame,
2999 .enable_stream = dce110_enable_stream,
3000 .disable_stream = dce110_disable_stream,
3001 .unblank_stream = dce110_unblank_stream,
3002 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
3003 .enable_display_power_gating = dce110_enable_display_power_gating,
7f914a62 3004 .disable_plane = dce110_power_down_fe,
4562236b 3005 .pipe_control_lock = dce_pipe_control_lock,
4562236b
HW
3006 .set_bandwidth = dce110_set_bandwidth,
3007 .set_drr = set_drr,
72ada5f7 3008 .get_position = get_position,
4562236b 3009 .set_static_screen_control = set_static_screen_control,
54e8695e 3010 .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap,
4b5e7d62 3011 .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
15e17335
CL
3012 .setup_stereo = NULL,
3013 .set_avmute = dce110_set_avmute,
41f97c07
HW
3014 .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
3015 .ready_shared_resources = ready_shared_resources,
3016 .optimize_shared_resources = optimize_shared_resources,
631aaa0a 3017 .pplib_apply_display_requirements = pplib_apply_display_requirements,
87401969
AJ
3018 .edp_backlight_control = hwss_edp_backlight_control,
3019 .edp_power_control = hwss_edp_power_control,
904623ee 3020 .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
39b485e4
EY
3021 .set_cursor_position = dce110_set_cursor_position,
3022 .set_cursor_attribute = dce110_set_cursor_attribute
4562236b
HW
3023};
3024
c13b408b 3025void dce110_hw_sequencer_construct(struct dc *dc)
4562236b
HW
3026{
3027 dc->hwss = dce110_funcs;
4562236b
HW
3028}
3029