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 
26 #include "dm_services.h"
27 #include "core_types.h"
28 #include "timing_generator.h"
29 #include "hw_sequencer.h"
30 #include "hw_sequencer_private.h"
31 #include "basics/dc_common.h"
32 
33 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
34 
35 /* used as index in array of black_color_format */
36 enum black_color_format {
37 	BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0,
38 	BLACK_COLOR_FORMAT_RGB_LIMITED,
39 	BLACK_COLOR_FORMAT_YUV_TV,
40 	BLACK_COLOR_FORMAT_YUV_CV,
41 	BLACK_COLOR_FORMAT_YUV_SUPER_AA,
42 	BLACK_COLOR_FORMAT_DEBUG,
43 };
44 
45 enum dc_color_space_type {
46 	COLOR_SPACE_RGB_TYPE,
47 	COLOR_SPACE_RGB_LIMITED_TYPE,
48 	COLOR_SPACE_YCBCR601_TYPE,
49 	COLOR_SPACE_YCBCR709_TYPE,
50 	COLOR_SPACE_YCBCR2020_TYPE,
51 	COLOR_SPACE_YCBCR601_LIMITED_TYPE,
52 	COLOR_SPACE_YCBCR709_LIMITED_TYPE,
53 	COLOR_SPACE_YCBCR709_BLACK_TYPE,
54 };
55 
56 static const struct tg_color black_color_format[] = {
57 	/* BlackColorFormat_RGB_FullRange */
58 	{0, 0, 0},
59 	/* BlackColorFormat_RGB_Limited */
60 	{0x40, 0x40, 0x40},
61 	/* BlackColorFormat_YUV_TV */
62 	{0x200, 0x40, 0x200},
63 	/* BlackColorFormat_YUV_CV */
64 	{0x1f4, 0x40, 0x1f4},
65 	/* BlackColorFormat_YUV_SuperAA */
66 	{0x1a2, 0x20, 0x1a2},
67 	/* visual confirm debug */
68 	{0xff, 0xff, 0},
69 };
70 
71 struct out_csc_color_matrix_type {
72 	enum dc_color_space_type color_space_type;
73 	uint16_t regval[12];
74 };
75 
76 static const struct out_csc_color_matrix_type output_csc_matrix[] = {
77 	{ COLOR_SPACE_RGB_TYPE,
78 		{ 0x2000, 0,      0,      0,
79 		  0,      0x2000, 0,      0,
80 		  0,      0,      0x2000, 0} },
81 	{ COLOR_SPACE_RGB_LIMITED_TYPE,
82 		{ 0x1B67, 0,      0,      0x201,
83 		  0,      0x1B67, 0,      0x201,
84 		  0,      0,      0x1B67, 0x201} },
85 	{ COLOR_SPACE_YCBCR601_TYPE,
86 		{ 0xE04,  0xF444, 0xFDB9, 0x1004,
87 		  0x831,  0x1016, 0x320,  0x201,
88 		  0xFB45, 0xF6B7, 0xE04,  0x1004} },
89 	{ COLOR_SPACE_YCBCR709_TYPE,
90 		{ 0xE04,  0xF345, 0xFEB7, 0x1004,
91 		  0x5D3,  0x1399, 0x1FA,  0x201,
92 		  0xFCCA, 0xF533, 0xE04,  0x1004} },
93 	/* TODO: correct values below */
94 	{ COLOR_SPACE_YCBCR601_LIMITED_TYPE,
95 		{ 0xE00,  0xF447, 0xFDB9, 0x1000,
96 		  0x991,  0x12C9, 0x3A6,  0x200,
97 		  0xFB47, 0xF6B9, 0xE00,  0x1000} },
98 	{ COLOR_SPACE_YCBCR709_LIMITED_TYPE,
99 		{ 0xE00, 0xF349, 0xFEB7, 0x1000,
100 		  0x6CE, 0x16E3, 0x24F,  0x200,
101 		  0xFCCB, 0xF535, 0xE00, 0x1000} },
102 	{ COLOR_SPACE_YCBCR2020_TYPE,
103 		{ 0x1000, 0xF149, 0xFEB7, 0x1004,
104 		  0x0868, 0x15B2, 0x01E6, 0x201,
105 		  0xFB88, 0xF478, 0x1000, 0x1004} },
106 	{ COLOR_SPACE_YCBCR709_BLACK_TYPE,
107 		{ 0x0000, 0x0000, 0x0000, 0x1000,
108 		  0x0000, 0x0000, 0x0000, 0x0200,
109 		  0x0000, 0x0000, 0x0000, 0x1000} },
110 };
111 
112 static bool is_rgb_type(
113 		enum dc_color_space color_space)
114 {
115 	bool ret = false;
116 
117 	if (color_space == COLOR_SPACE_SRGB			||
118 		color_space == COLOR_SPACE_XR_RGB		||
119 		color_space == COLOR_SPACE_MSREF_SCRGB		||
120 		color_space == COLOR_SPACE_2020_RGB_FULLRANGE	||
121 		color_space == COLOR_SPACE_ADOBERGB		||
122 		color_space == COLOR_SPACE_DCIP3	||
123 		color_space == COLOR_SPACE_DOLBYVISION)
124 		ret = true;
125 	return ret;
126 }
127 
128 static bool is_rgb_limited_type(
129 		enum dc_color_space color_space)
130 {
131 	bool ret = false;
132 
133 	if (color_space == COLOR_SPACE_SRGB_LIMITED		||
134 		color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
135 		ret = true;
136 	return ret;
137 }
138 
139 static bool is_ycbcr601_type(
140 		enum dc_color_space color_space)
141 {
142 	bool ret = false;
143 
144 	if (color_space == COLOR_SPACE_YCBCR601	||
145 		color_space == COLOR_SPACE_XV_YCC_601)
146 		ret = true;
147 	return ret;
148 }
149 
150 static bool is_ycbcr601_limited_type(
151 		enum dc_color_space color_space)
152 {
153 	bool ret = false;
154 
155 	if (color_space == COLOR_SPACE_YCBCR601_LIMITED)
156 		ret = true;
157 	return ret;
158 }
159 
160 static bool is_ycbcr709_type(
161 		enum dc_color_space color_space)
162 {
163 	bool ret = false;
164 
165 	if (color_space == COLOR_SPACE_YCBCR709	||
166 		color_space == COLOR_SPACE_XV_YCC_709)
167 		ret = true;
168 	return ret;
169 }
170 
171 static bool is_ycbcr2020_type(
172 	enum dc_color_space color_space)
173 {
174 	bool ret = false;
175 
176 	if (color_space == COLOR_SPACE_2020_YCBCR)
177 		ret = true;
178 	return ret;
179 }
180 
181 static bool is_ycbcr709_limited_type(
182 		enum dc_color_space color_space)
183 {
184 	bool ret = false;
185 
186 	if (color_space == COLOR_SPACE_YCBCR709_LIMITED)
187 		ret = true;
188 	return ret;
189 }
190 static enum dc_color_space_type get_color_space_type(enum dc_color_space color_space)
191 {
192 	enum dc_color_space_type type = COLOR_SPACE_RGB_TYPE;
193 
194 	if (is_rgb_type(color_space))
195 		type = COLOR_SPACE_RGB_TYPE;
196 	else if (is_rgb_limited_type(color_space))
197 		type = COLOR_SPACE_RGB_LIMITED_TYPE;
198 	else if (is_ycbcr601_type(color_space))
199 		type = COLOR_SPACE_YCBCR601_TYPE;
200 	else if (is_ycbcr709_type(color_space))
201 		type = COLOR_SPACE_YCBCR709_TYPE;
202 	else if (is_ycbcr601_limited_type(color_space))
203 		type = COLOR_SPACE_YCBCR601_LIMITED_TYPE;
204 	else if (is_ycbcr709_limited_type(color_space))
205 		type = COLOR_SPACE_YCBCR709_LIMITED_TYPE;
206 	else if (is_ycbcr2020_type(color_space))
207 		type = COLOR_SPACE_YCBCR2020_TYPE;
208 	else if (color_space == COLOR_SPACE_YCBCR709)
209 		type = COLOR_SPACE_YCBCR709_BLACK_TYPE;
210 	else if (color_space == COLOR_SPACE_YCBCR709_BLACK)
211 		type = COLOR_SPACE_YCBCR709_BLACK_TYPE;
212 	return type;
213 }
214 
215 const uint16_t *find_color_matrix(enum dc_color_space color_space,
216 							uint32_t *array_size)
217 {
218 	int i;
219 	enum dc_color_space_type type;
220 	const uint16_t *val = NULL;
221 	int arr_size = NUM_ELEMENTS(output_csc_matrix);
222 
223 	type = get_color_space_type(color_space);
224 	for (i = 0; i < arr_size; i++)
225 		if (output_csc_matrix[i].color_space_type == type) {
226 			val = output_csc_matrix[i].regval;
227 			*array_size = 12;
228 			break;
229 		}
230 
231 	return val;
232 }
233 
234 
235 void color_space_to_black_color(
236 	const struct dc *dc,
237 	enum dc_color_space colorspace,
238 	struct tg_color *black_color)
239 {
240 	switch (colorspace) {
241 	case COLOR_SPACE_YCBCR601:
242 	case COLOR_SPACE_YCBCR709:
243 	case COLOR_SPACE_YCBCR709_BLACK:
244 	case COLOR_SPACE_YCBCR601_LIMITED:
245 	case COLOR_SPACE_YCBCR709_LIMITED:
246 	case COLOR_SPACE_2020_YCBCR:
247 		*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
248 		break;
249 
250 	case COLOR_SPACE_SRGB_LIMITED:
251 		*black_color =
252 			black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED];
253 		break;
254 
255 	/**
256 	 * Remove default and add case for all color space
257 	 * so when we forget to add new color space
258 	 * compiler will give a warning
259 	 */
260 	case COLOR_SPACE_UNKNOWN:
261 	case COLOR_SPACE_SRGB:
262 	case COLOR_SPACE_XR_RGB:
263 	case COLOR_SPACE_MSREF_SCRGB:
264 	case COLOR_SPACE_XV_YCC_709:
265 	case COLOR_SPACE_XV_YCC_601:
266 	case COLOR_SPACE_2020_RGB_FULLRANGE:
267 	case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
268 	case COLOR_SPACE_ADOBERGB:
269 	case COLOR_SPACE_DCIP3:
270 	case COLOR_SPACE_DISPLAYNATIVE:
271 	case COLOR_SPACE_DOLBYVISION:
272 	case COLOR_SPACE_APPCTRL:
273 	case COLOR_SPACE_CUSTOMPOINTS:
274 		/* fefault is sRGB black (full range). */
275 		*black_color =
276 			black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE];
277 		/* default is sRGB black 0. */
278 		break;
279 	}
280 }
281 
282 bool hwss_wait_for_blank_complete(
283 		struct timing_generator *tg)
284 {
285 	int counter;
286 
287 	/* Not applicable if the pipe is not primary, save 300ms of boot time */
288 	if (!tg->funcs->is_blanked)
289 		return true;
290 	for (counter = 0; counter < 100; counter++) {
291 		if (tg->funcs->is_blanked(tg))
292 			break;
293 
294 		msleep(1);
295 	}
296 
297 	if (counter == 100) {
298 		dm_error("DC: failed to blank crtc!\n");
299 		return false;
300 	}
301 
302 	return true;
303 }
304 
305 void get_mpctree_visual_confirm_color(
306 		struct pipe_ctx *pipe_ctx,
307 		struct tg_color *color)
308 {
309 	const struct tg_color pipe_colors[6] = {
310 			{MAX_TG_COLOR_VALUE, 0, 0}, /* red */
311 			{MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE / 4, 0}, /* orange */
312 			{MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE, 0}, /* yellow */
313 			{0, MAX_TG_COLOR_VALUE, 0}, /* green */
314 			{0, 0, MAX_TG_COLOR_VALUE}, /* blue */
315 			{MAX_TG_COLOR_VALUE / 2, 0, MAX_TG_COLOR_VALUE / 2}, /* purple */
316 	};
317 
318 	struct pipe_ctx *top_pipe = pipe_ctx;
319 
320 	while (top_pipe->top_pipe)
321 		top_pipe = top_pipe->top_pipe;
322 
323 	*color = pipe_colors[top_pipe->pipe_idx];
324 }
325 
326 void get_surface_visual_confirm_color(
327 		const struct pipe_ctx *pipe_ctx,
328 		struct tg_color *color)
329 {
330 	uint32_t color_value = MAX_TG_COLOR_VALUE;
331 
332 	switch (pipe_ctx->plane_res.scl_data.format) {
333 	case PIXEL_FORMAT_ARGB8888:
334 		/* set border color to red */
335 		color->color_r_cr = color_value;
336 		if (pipe_ctx->plane_state->layer_index > 0) {
337 			/* set border color to pink */
338 			color->color_b_cb = color_value;
339 			color->color_g_y = color_value * 0.5;
340 		}
341 		break;
342 
343 	case PIXEL_FORMAT_ARGB2101010:
344 		/* set border color to blue */
345 		color->color_b_cb = color_value;
346 		if (pipe_ctx->plane_state->layer_index > 0) {
347 			/* set border color to cyan */
348 			color->color_g_y = color_value;
349 		}
350 		break;
351 	case PIXEL_FORMAT_420BPP8:
352 		/* set border color to green */
353 		color->color_g_y = color_value;
354 		break;
355 	case PIXEL_FORMAT_420BPP10:
356 		/* set border color to yellow */
357 		color->color_g_y = color_value;
358 		color->color_r_cr = color_value;
359 		break;
360 	case PIXEL_FORMAT_FP16:
361 		/* set border color to white */
362 		color->color_r_cr = color_value;
363 		color->color_b_cb = color_value;
364 		color->color_g_y = color_value;
365 		if (pipe_ctx->plane_state->layer_index > 0) {
366 			/* set border color to orange */
367 			color->color_g_y = 0.22 * color_value;
368 			color->color_b_cb = 0;
369 		}
370 		break;
371 	default:
372 		break;
373 	}
374 }
375 
376 void get_hdr_visual_confirm_color(
377 		struct pipe_ctx *pipe_ctx,
378 		struct tg_color *color)
379 {
380 	uint32_t color_value = MAX_TG_COLOR_VALUE;
381 	bool is_sdr = false;
382 
383 	/* Determine the overscan color based on the top-most (desktop) plane's context */
384 	struct pipe_ctx *top_pipe_ctx  = pipe_ctx;
385 
386 	while (top_pipe_ctx->top_pipe != NULL)
387 		top_pipe_ctx = top_pipe_ctx->top_pipe;
388 
389 	switch (top_pipe_ctx->plane_res.scl_data.format) {
390 	case PIXEL_FORMAT_ARGB2101010:
391 		if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
392 			/* HDR10, ARGB2101010 - set border color to red */
393 			color->color_r_cr = color_value;
394 		} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
395 			/* FreeSync 2 ARGB2101010 - set border color to pink */
396 			color->color_r_cr = color_value;
397 			color->color_b_cb = color_value;
398 		} else
399 			is_sdr = true;
400 		break;
401 	case PIXEL_FORMAT_FP16:
402 		if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
403 			/* HDR10, FP16 - set border color to blue */
404 			color->color_b_cb = color_value;
405 		} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
406 			/* FreeSync 2 HDR - set border color to green */
407 			color->color_g_y = color_value;
408 		} else
409 			is_sdr = true;
410 		break;
411 	default:
412 		is_sdr = true;
413 		break;
414 	}
415 
416 	if (is_sdr) {
417 		/* SDR - set border color to Gray */
418 		color->color_r_cr = color_value/2;
419 		color->color_b_cb = color_value/2;
420 		color->color_g_y = color_value/2;
421 	}
422 }
423 
424 void get_subvp_visual_confirm_color(
425 		struct dc *dc,
426 		struct dc_state *context,
427 		struct pipe_ctx *pipe_ctx,
428 		struct tg_color *color)
429 {
430 	uint32_t color_value = MAX_TG_COLOR_VALUE;
431 	bool enable_subvp = false;
432 	int i;
433 
434 	if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !context)
435 		return;
436 
437 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
438 		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
439 
440 		if (pipe->stream && pipe->stream->mall_stream_config.paired_stream &&
441 		    pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
442 			/* SubVP enable - red */
443 			color->color_g_y = 0;
444 			color->color_b_cb = 0;
445 			color->color_r_cr = color_value;
446 			enable_subvp = true;
447 
448 			if (pipe_ctx->stream == pipe->stream)
449 				return;
450 			break;
451 		}
452 	}
453 
454 	if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) {
455 		color->color_r_cr = 0;
456 		if (pipe_ctx->stream->allow_freesync == 1) {
457 			/* SubVP enable and DRR on - green */
458 			color->color_b_cb = 0;
459 			color->color_g_y = color_value;
460 		} else {
461 			/* SubVP enable and No DRR - blue */
462 			color->color_g_y = 0;
463 			color->color_b_cb = color_value;
464 		}
465 	}
466 }
467 
468 void hwss_build_fast_sequence(struct dc *dc,
469 		struct dc_dmub_cmd *dc_dmub_cmd,
470 		unsigned int dmub_cmd_count,
471 		struct block_sequence block_sequence[],
472 		int *num_steps,
473 		struct pipe_ctx *pipe_ctx)
474 {
475 	struct dc_plane_state *plane = pipe_ctx->plane_state;
476 	struct dc_stream_state *stream = pipe_ctx->stream;
477 	struct dce_hwseq *hws = dc->hwseq;
478 	struct pipe_ctx *current_pipe = NULL;
479 	struct pipe_ctx *current_mpc_pipe = NULL;
480 	unsigned int i = 0;
481 
482 	*num_steps = 0; // Initialize to 0
483 
484 	if (!plane || !stream)
485 		return;
486 
487 	if (dc->hwss.subvp_pipe_control_lock_fast) {
488 		block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
489 		block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
490 		block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
491 		block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
492 		(*num_steps)++;
493 	}
494 	if (dc->hwss.pipe_control_lock) {
495 		block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
496 		block_sequence[*num_steps].params.pipe_control_lock_params.lock = true;
497 		block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
498 		block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
499 		(*num_steps)++;
500 	}
501 
502 	for (i = 0; i < dmub_cmd_count; i++) {
503 		block_sequence[*num_steps].params.send_dmcub_cmd_params.ctx = dc->ctx;
504 		block_sequence[*num_steps].params.send_dmcub_cmd_params.cmd = &(dc_dmub_cmd[i].dmub_cmd);
505 		block_sequence[*num_steps].params.send_dmcub_cmd_params.wait_type = dc_dmub_cmd[i].wait_type;
506 		block_sequence[*num_steps].func = DMUB_SEND_DMCUB_CMD;
507 		(*num_steps)++;
508 	}
509 
510 	current_pipe = pipe_ctx;
511 	while (current_pipe) {
512 		current_mpc_pipe = current_pipe;
513 		while (current_mpc_pipe) {
514 			if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state && current_mpc_pipe->plane_state->update_flags.raw) {
515 				block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe;
516 				block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate;
517 				block_sequence[*num_steps].func = HUBP_SET_FLIP_CONTROL_GSL;
518 				(*num_steps)++;
519 			}
520 			if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) {
521 				block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc;
522 				block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe;
523 				block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips;
524 				block_sequence[*num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER;
525 				(*num_steps)++;
526 			}
527 			if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
528 				block_sequence[*num_steps].params.update_plane_addr_params.dc = dc;
529 				block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
530 				block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
531 				(*num_steps)++;
532 			}
533 
534 			if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) {
535 				block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
536 				block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
537 				block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state;
538 				block_sequence[*num_steps].func = DPP_SET_INPUT_TRANSFER_FUNC;
539 				(*num_steps)++;
540 			}
541 
542 			if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) {
543 				block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe;
544 				block_sequence[*num_steps].func = DPP_PROGRAM_GAMUT_REMAP;
545 				(*num_steps)++;
546 			}
547 			if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) {
548 				block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe;
549 				block_sequence[*num_steps].func = DPP_SETUP_DPP;
550 				(*num_steps)++;
551 			}
552 			if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) {
553 				block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe;
554 				block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE;
555 				(*num_steps)++;
556 			}
557 			if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) {
558 				block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc;
559 				block_sequence[*num_steps].params.set_output_transfer_func_params.pipe_ctx = current_mpc_pipe;
560 				block_sequence[*num_steps].params.set_output_transfer_func_params.stream = current_mpc_pipe->stream;
561 				block_sequence[*num_steps].func = DPP_SET_OUTPUT_TRANSFER_FUNC;
562 				(*num_steps)++;
563 			}
564 
565 			if (current_mpc_pipe->stream->update_flags.bits.out_csc) {
566 				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpc = dc->res_pool->mpc;
567 				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.mpcc_id = current_mpc_pipe->plane_res.hubp->inst;
568 				block_sequence[*num_steps].params.power_on_mpc_mem_pwr_params.power_on = true;
569 				block_sequence[*num_steps].func = MPC_POWER_ON_MPC_MEM_PWR;
570 				(*num_steps)++;
571 
572 				if (current_mpc_pipe->stream->csc_color_matrix.enable_adjustment == true) {
573 					block_sequence[*num_steps].params.set_output_csc_params.mpc = dc->res_pool->mpc;
574 					block_sequence[*num_steps].params.set_output_csc_params.opp_id = current_mpc_pipe->stream_res.opp->inst;
575 					block_sequence[*num_steps].params.set_output_csc_params.regval = current_mpc_pipe->stream->csc_color_matrix.matrix;
576 					block_sequence[*num_steps].params.set_output_csc_params.ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
577 					block_sequence[*num_steps].func = MPC_SET_OUTPUT_CSC;
578 					(*num_steps)++;
579 				} else {
580 					block_sequence[*num_steps].params.set_ocsc_default_params.mpc = dc->res_pool->mpc;
581 					block_sequence[*num_steps].params.set_ocsc_default_params.opp_id = current_mpc_pipe->stream_res.opp->inst;
582 					block_sequence[*num_steps].params.set_ocsc_default_params.color_space = current_mpc_pipe->stream->output_color_space;
583 					block_sequence[*num_steps].params.set_ocsc_default_params.ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
584 					block_sequence[*num_steps].func = MPC_SET_OCSC_DEFAULT;
585 					(*num_steps)++;
586 				}
587 			}
588 			current_mpc_pipe = current_mpc_pipe->bottom_pipe;
589 		}
590 		current_pipe = current_pipe->next_odm_pipe;
591 	}
592 
593 	if (dc->hwss.pipe_control_lock) {
594 		block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
595 		block_sequence[*num_steps].params.pipe_control_lock_params.lock = false;
596 		block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
597 		block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
598 		(*num_steps)++;
599 	}
600 	if (dc->hwss.subvp_pipe_control_lock_fast) {
601 		block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
602 		block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
603 		block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
604 		block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
605 		(*num_steps)++;
606 	}
607 
608 	current_pipe = pipe_ctx;
609 	while (current_pipe) {
610 		current_mpc_pipe = current_pipe;
611 
612 		while (current_mpc_pipe) {
613 			if (!current_mpc_pipe->bottom_pipe && !current_mpc_pipe->next_odm_pipe &&
614 					current_mpc_pipe->stream && current_mpc_pipe->plane_state &&
615 					current_mpc_pipe->plane_state->update_flags.bits.addr_update &&
616 					!current_mpc_pipe->plane_state->skip_manual_trigger) {
617 				block_sequence[*num_steps].params.program_manual_trigger_params.pipe_ctx = current_mpc_pipe;
618 				block_sequence[*num_steps].func = OPTC_PROGRAM_MANUAL_TRIGGER;
619 				(*num_steps)++;
620 			}
621 			current_mpc_pipe = current_mpc_pipe->bottom_pipe;
622 		}
623 		current_pipe = current_pipe->next_odm_pipe;
624 	}
625 }
626 
627 void hwss_execute_sequence(struct dc *dc,
628 		struct block_sequence block_sequence[],
629 		int num_steps)
630 {
631 	unsigned int i;
632 	union block_sequence_params *params;
633 	struct dce_hwseq *hws = dc->hwseq;
634 
635 	for (i = 0; i < num_steps; i++) {
636 		params = &(block_sequence[i].params);
637 		switch (block_sequence[i].func) {
638 
639 		case DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST:
640 			dc->hwss.subvp_pipe_control_lock_fast(params);
641 			break;
642 		case OPTC_PIPE_CONTROL_LOCK:
643 			dc->hwss.pipe_control_lock(params->pipe_control_lock_params.dc,
644 					params->pipe_control_lock_params.pipe_ctx,
645 					params->pipe_control_lock_params.lock);
646 			break;
647 		case HUBP_SET_FLIP_CONTROL_GSL:
648 			dc->hwss.set_flip_control_gsl(params->set_flip_control_gsl_params.pipe_ctx,
649 					params->set_flip_control_gsl_params.flip_immediate);
650 			break;
651 		case HUBP_PROGRAM_TRIPLEBUFFER:
652 			dc->hwss.program_triplebuffer(params->program_triplebuffer_params.dc,
653 					params->program_triplebuffer_params.pipe_ctx,
654 					params->program_triplebuffer_params.enableTripleBuffer);
655 			break;
656 		case HUBP_UPDATE_PLANE_ADDR:
657 			dc->hwss.update_plane_addr(params->update_plane_addr_params.dc,
658 					params->update_plane_addr_params.pipe_ctx);
659 			break;
660 		case DPP_SET_INPUT_TRANSFER_FUNC:
661 			hws->funcs.set_input_transfer_func(params->set_input_transfer_func_params.dc,
662 					params->set_input_transfer_func_params.pipe_ctx,
663 					params->set_input_transfer_func_params.plane_state);
664 			break;
665 		case DPP_PROGRAM_GAMUT_REMAP:
666 			dc->hwss.program_gamut_remap(params->program_gamut_remap_params.pipe_ctx);
667 			break;
668 		case DPP_SETUP_DPP:
669 			hwss_setup_dpp(params);
670 			break;
671 		case DPP_PROGRAM_BIAS_AND_SCALE:
672 			hwss_program_bias_and_scale(params);
673 			break;
674 		case OPTC_PROGRAM_MANUAL_TRIGGER:
675 			hwss_program_manual_trigger(params);
676 			break;
677 		case DPP_SET_OUTPUT_TRANSFER_FUNC:
678 			hws->funcs.set_output_transfer_func(params->set_output_transfer_func_params.dc,
679 					params->set_output_transfer_func_params.pipe_ctx,
680 					params->set_output_transfer_func_params.stream);
681 			break;
682 		case MPC_UPDATE_VISUAL_CONFIRM:
683 			dc->hwss.update_visual_confirm_color(params->update_visual_confirm_params.dc,
684 					params->update_visual_confirm_params.pipe_ctx,
685 					params->update_visual_confirm_params.mpcc_id);
686 			break;
687 		case MPC_POWER_ON_MPC_MEM_PWR:
688 			hwss_power_on_mpc_mem_pwr(params);
689 			break;
690 		case MPC_SET_OUTPUT_CSC:
691 			hwss_set_output_csc(params);
692 			break;
693 		case MPC_SET_OCSC_DEFAULT:
694 			hwss_set_ocsc_default(params);
695 			break;
696 		case DMUB_SEND_DMCUB_CMD:
697 			hwss_send_dmcub_cmd(params);
698 			break;
699 		default:
700 			ASSERT(false);
701 			break;
702 		}
703 	}
704 }
705 
706 void hwss_send_dmcub_cmd(union block_sequence_params *params)
707 {
708 	struct dc_context *ctx = params->send_dmcub_cmd_params.ctx;
709 	union dmub_rb_cmd *cmd = params->send_dmcub_cmd_params.cmd;
710 	enum dm_dmub_wait_type wait_type = params->send_dmcub_cmd_params.wait_type;
711 
712 	dm_execute_dmub_cmd(ctx, cmd, wait_type);
713 }
714 
715 void hwss_program_manual_trigger(union block_sequence_params *params)
716 {
717 	struct pipe_ctx *pipe_ctx = params->program_manual_trigger_params.pipe_ctx;
718 
719 	if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
720 		pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
721 }
722 
723 void hwss_setup_dpp(union block_sequence_params *params)
724 {
725 	struct pipe_ctx *pipe_ctx = params->setup_dpp_params.pipe_ctx;
726 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
727 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
728 
729 	if (dpp && dpp->funcs->dpp_setup) {
730 		// program the input csc
731 		dpp->funcs->dpp_setup(dpp,
732 				plane_state->format,
733 				EXPANSION_MODE_ZERO,
734 				plane_state->input_csc_color_matrix,
735 				plane_state->color_space,
736 				NULL);
737 	}
738 }
739 
740 void hwss_program_bias_and_scale(union block_sequence_params *params)
741 {
742 	struct pipe_ctx *pipe_ctx = params->program_bias_and_scale_params.pipe_ctx;
743 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
744 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
745 	struct dc_bias_and_scale bns_params = {0};
746 
747 	//TODO :for CNVC set scale and bias registers if necessary
748 	build_prescale_params(&bns_params, plane_state);
749 	if (dpp->funcs->dpp_program_bias_and_scale)
750 		dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
751 }
752 
753 void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params)
754 {
755 	struct mpc *mpc = params->power_on_mpc_mem_pwr_params.mpc;
756 	int mpcc_id = params->power_on_mpc_mem_pwr_params.mpcc_id;
757 	bool power_on = params->power_on_mpc_mem_pwr_params.power_on;
758 
759 	if (mpc->funcs->power_on_mpc_mem_pwr)
760 		mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, power_on);
761 }
762 
763 void hwss_set_output_csc(union block_sequence_params *params)
764 {
765 	struct mpc *mpc = params->set_output_csc_params.mpc;
766 	int opp_id = params->set_output_csc_params.opp_id;
767 	const uint16_t *matrix = params->set_output_csc_params.regval;
768 	enum mpc_output_csc_mode ocsc_mode = params->set_output_csc_params.ocsc_mode;
769 
770 	if (mpc->funcs->set_output_csc != NULL)
771 		mpc->funcs->set_output_csc(mpc,
772 				opp_id,
773 				matrix,
774 				ocsc_mode);
775 }
776 
777 void hwss_set_ocsc_default(union block_sequence_params *params)
778 {
779 	struct mpc *mpc = params->set_ocsc_default_params.mpc;
780 	int opp_id = params->set_ocsc_default_params.opp_id;
781 	enum dc_color_space colorspace = params->set_ocsc_default_params.color_space;
782 	enum mpc_output_csc_mode ocsc_mode = params->set_ocsc_default_params.ocsc_mode;
783 
784 	if (mpc->funcs->set_ocsc_default != NULL)
785 		mpc->funcs->set_ocsc_default(mpc,
786 				opp_id,
787 				colorspace,
788 				ocsc_mode);
789 }
790 
791 void get_mclk_switch_visual_confirm_color(
792 		struct dc *dc,
793 		struct dc_state *context,
794 		struct pipe_ctx *pipe_ctx,
795 		struct tg_color *color)
796 {
797 	uint32_t color_value = MAX_TG_COLOR_VALUE;
798 	struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
799 
800 	if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context)
801 		return;
802 
803 	if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
804 			dm_dram_clock_change_unsupported) {
805 		/* MCLK switching is supported */
806 		if (!pipe_ctx->has_vactive_margin) {
807 			/* In Vblank - yellow */
808 			color->color_r_cr = color_value;
809 			color->color_g_y = color_value;
810 
811 			if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
812 				/* FPO + Vblank - cyan */
813 				color->color_r_cr = 0;
814 				color->color_g_y  = color_value;
815 				color->color_b_cb = color_value;
816 			}
817 		} else {
818 			/* In Vactive - pink */
819 			color->color_r_cr = color_value;
820 			color->color_b_cb = color_value;
821 		}
822 		/* SubVP */
823 		get_subvp_visual_confirm_color(dc, context, pipe_ctx, color);
824 	}
825 }
826 
827 void get_surface_tile_visual_confirm_color(
828 		struct pipe_ctx *pipe_ctx,
829 		struct tg_color *color)
830 {
831 	uint32_t color_value = MAX_TG_COLOR_VALUE;
832 	/* Determine the overscan color based on the bottom-most plane's context */
833 	struct pipe_ctx *bottom_pipe_ctx  = pipe_ctx;
834 
835 	while (bottom_pipe_ctx->bottom_pipe != NULL)
836 		bottom_pipe_ctx = bottom_pipe_ctx->bottom_pipe;
837 
838 	switch (bottom_pipe_ctx->plane_state->tiling_info.gfx9.swizzle) {
839 	case DC_SW_LINEAR:
840 		/* LINEAR Surface - set border color to red */
841 		color->color_r_cr = color_value;
842 		break;
843 	default:
844 		break;
845 	}
846 }
847