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