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