1/*
2 * Copyright 2023 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/* FILE POLICY AND INTENDED USAGE:
27 * This file owns timing validation against various link limitations. (ex.
28 * link bandwidth, receiver capability or our hardware capability) It also
29 * provides helper functions exposing bandwidth formulas used in validation.
30 */
31#include "link_validation.h"
32#include "protocols/link_dp_capability.h"
33#include "protocols/link_dp_dpia_bw.h"
34#include "resource.h"
35
36#define DC_LOGGER_INIT(logger)
37
38static uint32_t get_tmds_output_pixel_clock_100hz(const struct dc_crtc_timing *timing)
39{
40
41	uint32_t pxl_clk = timing->pix_clk_100hz;
42
43	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
44		pxl_clk /= 2;
45	else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
46		pxl_clk = pxl_clk * 2 / 3;
47
48	if (timing->display_color_depth == COLOR_DEPTH_101010)
49		pxl_clk = pxl_clk * 10 / 8;
50	else if (timing->display_color_depth == COLOR_DEPTH_121212)
51		pxl_clk = pxl_clk * 12 / 8;
52
53	return pxl_clk;
54}
55
56static bool dp_active_dongle_validate_timing(
57		const struct dc_crtc_timing *timing,
58		const struct dpcd_caps *dpcd_caps)
59{
60	const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
61
62	switch (dpcd_caps->dongle_type) {
63	case DISPLAY_DONGLE_DP_VGA_CONVERTER:
64	case DISPLAY_DONGLE_DP_DVI_CONVERTER:
65	case DISPLAY_DONGLE_DP_DVI_DONGLE:
66		if (timing->pixel_encoding == PIXEL_ENCODING_RGB)
67			return true;
68		else
69			return false;
70	default:
71		break;
72	}
73
74	if (dpcd_caps->dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER &&
75			dongle_caps->extendedCapValid == true) {
76		/* Check Pixel Encoding */
77		switch (timing->pixel_encoding) {
78		case PIXEL_ENCODING_RGB:
79		case PIXEL_ENCODING_YCBCR444:
80			break;
81		case PIXEL_ENCODING_YCBCR422:
82			if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through)
83				return false;
84			break;
85		case PIXEL_ENCODING_YCBCR420:
86			if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through)
87				return false;
88			break;
89		default:
90			/* Invalid Pixel Encoding*/
91			return false;
92		}
93
94		switch (timing->display_color_depth) {
95		case COLOR_DEPTH_666:
96		case COLOR_DEPTH_888:
97			/*888 and 666 should always be supported*/
98			break;
99		case COLOR_DEPTH_101010:
100			if (dongle_caps->dp_hdmi_max_bpc < 10)
101				return false;
102			break;
103		case COLOR_DEPTH_121212:
104			if (dongle_caps->dp_hdmi_max_bpc < 12)
105				return false;
106			break;
107		case COLOR_DEPTH_141414:
108		case COLOR_DEPTH_161616:
109		default:
110			/* These color depths are currently not supported */
111			return false;
112		}
113
114		/* Check 3D format */
115		switch (timing->timing_3d_format) {
116		case TIMING_3D_FORMAT_NONE:
117		case TIMING_3D_FORMAT_FRAME_ALTERNATE:
118			/*Only frame alternate 3D is supported on active dongle*/
119			break;
120		default:
121			/*other 3D formats are not supported due to bad infoframe translation */
122			return false;
123		}
124
125		if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter
126			struct dc_crtc_timing outputTiming = *timing;
127
128#if defined(CONFIG_DRM_AMD_DC_FP)
129			if (timing->flags.DSC && !timing->dsc_cfg.is_frl)
130				/* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */
131				outputTiming.flags.DSC = 0;
132#endif
133			if (dc_bandwidth_in_kbps_from_timing(&outputTiming, DC_LINK_ENCODING_HDMI_FRL) >
134					dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps)
135				return false;
136		} else { // DP to HDMI TMDS converter
137			if (get_tmds_output_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
138				return false;
139		}
140	}
141
142	if (dpcd_caps->channel_coding_cap.bits.DP_128b_132b_SUPPORTED == 0 &&
143			dpcd_caps->dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT == 0 &&
144			dongle_caps->dfp_cap_ext.supported) {
145
146		if (dongle_caps->dfp_cap_ext.max_pixel_rate_in_mps < (timing->pix_clk_100hz / 10000))
147			return false;
148
149		if (dongle_caps->dfp_cap_ext.max_video_h_active_width < timing->h_addressable)
150			return false;
151
152		if (dongle_caps->dfp_cap_ext.max_video_v_active_height < timing->v_addressable)
153			return false;
154
155		if (timing->pixel_encoding == PIXEL_ENCODING_RGB) {
156			if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
157				return false;
158			if (timing->display_color_depth == COLOR_DEPTH_666 &&
159					!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_6bpc)
160				return false;
161			else if (timing->display_color_depth == COLOR_DEPTH_888 &&
162					!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_8bpc)
163				return false;
164			else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
165					!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_10bpc)
166				return false;
167			else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
168					!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_12bpc)
169				return false;
170			else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
171					!dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_16bpc)
172				return false;
173		} else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
174			if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
175				return false;
176			if (timing->display_color_depth == COLOR_DEPTH_888 &&
177					!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_8bpc)
178				return false;
179			else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
180					!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_10bpc)
181				return false;
182			else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
183					!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_12bpc)
184				return false;
185			else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
186					!dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_16bpc)
187				return false;
188		} else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
189			if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
190				return false;
191			if (timing->display_color_depth == COLOR_DEPTH_888 &&
192					!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_8bpc)
193				return false;
194			else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
195					!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_10bpc)
196				return false;
197			else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
198					!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_12bpc)
199				return false;
200			else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
201					!dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_16bpc)
202				return false;
203		} else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
204			if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
205				return false;
206			if (timing->display_color_depth == COLOR_DEPTH_888 &&
207					!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_8bpc)
208				return false;
209			else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
210					!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_10bpc)
211				return false;
212			else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
213					!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_12bpc)
214				return false;
215			else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
216					!dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_16bpc)
217				return false;
218		}
219	}
220
221	return true;
222}
223
224uint32_t dp_link_bandwidth_kbps(
225	const struct dc_link *link,
226	const struct dc_link_settings *link_settings)
227{
228	uint32_t total_data_bw_efficiency_x10000 = 0;
229	uint32_t link_rate_per_lane_kbps = 0;
230
231	switch (link_dp_get_encoding_format(link_settings)) {
232	case DP_8b_10b_ENCODING:
233		/* For 8b/10b encoding:
234		 * link rate is defined in the unit of LINK_RATE_REF_FREQ_IN_KHZ per DP byte per lane.
235		 * data bandwidth efficiency is 80% with additional 3% overhead if FEC is supported.
236		 */
237		link_rate_per_lane_kbps = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE;
238		total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000;
239		if (dp_should_enable_fec(link)) {
240			total_data_bw_efficiency_x10000 /= 100;
241			total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100;
242		}
243		break;
244	case DP_128b_132b_ENCODING:
245		/* For 128b/132b encoding:
246		 * link rate is defined in the unit of 10mbps per lane.
247		 * total data bandwidth efficiency is always 96.71%.
248		 */
249		link_rate_per_lane_kbps = link_settings->link_rate * 10000;
250		total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000;
251		break;
252	default:
253		break;
254	}
255
256	/* overall effective link bandwidth = link rate per lane * lane count * total data bandwidth efficiency */
257	return link_rate_per_lane_kbps * link_settings->lane_count / 10000 * total_data_bw_efficiency_x10000;
258}
259
260static bool dp_validate_mode_timing(
261	struct dc_link *link,
262	const struct dc_crtc_timing *timing)
263{
264	uint32_t req_bw;
265	uint32_t max_bw;
266
267	const struct dc_link_settings *link_setting;
268
269	/* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
270	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
271			!link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
272			dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
273		return false;
274
275	/*always DP fail safe mode*/
276	if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
277		timing->h_addressable == (uint32_t) 640 &&
278		timing->v_addressable == (uint32_t) 480)
279		return true;
280
281	link_setting = dp_get_verified_link_cap(link);
282
283	/* TODO: DYNAMIC_VALIDATION needs to be implemented */
284	/*if (flags.DYNAMIC_VALIDATION == 1 &&
285		link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
286		link_setting = &link->verified_link_cap;
287	*/
288
289	req_bw = dc_bandwidth_in_kbps_from_timing(timing, dc_link_get_highest_encoding_format(link));
290	max_bw = dp_link_bandwidth_kbps(link, link_setting);
291
292	if (req_bw <= max_bw) {
293		/* remember the biggest mode here, during
294		 * initial link training (to get
295		 * verified_link_cap), LS sends event about
296		 * cannot train at reported cap to upper
297		 * layer and upper layer will re-enumerate modes.
298		 * this is not necessary if the lower
299		 * verified_link_cap is enough to drive
300		 * all the modes */
301
302		/* TODO: DYNAMIC_VALIDATION needs to be implemented */
303		/* if (flags.DYNAMIC_VALIDATION == 1)
304			dpsst->max_req_bw_for_verified_linkcap = dal_max(
305				dpsst->max_req_bw_for_verified_linkcap, req_bw); */
306		return true;
307	} else
308		return false;
309}
310
311enum dc_status link_validate_mode_timing(
312		const struct dc_stream_state *stream,
313		struct dc_link *link,
314		const struct dc_crtc_timing *timing)
315{
316	uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10;
317	struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
318
319	/* A hack to avoid failing any modes for EDID override feature on
320	 * topology change such as lower quality cable for DP or different dongle
321	 */
322	if (link->remote_sinks[0] && link->remote_sinks[0]->sink_signal == SIGNAL_TYPE_VIRTUAL)
323		return DC_OK;
324
325	/* Passive Dongle */
326	if (max_pix_clk != 0 && get_tmds_output_pixel_clock_100hz(timing) > max_pix_clk)
327		return DC_EXCEED_DONGLE_CAP;
328
329	/* Active Dongle*/
330	if (!dp_active_dongle_validate_timing(timing, dpcd_caps))
331		return DC_EXCEED_DONGLE_CAP;
332
333	switch (stream->signal) {
334	case SIGNAL_TYPE_EDP:
335	case SIGNAL_TYPE_DISPLAY_PORT:
336		if (!dp_validate_mode_timing(
337				link,
338				timing))
339			return DC_NO_DP_LINK_BANDWIDTH;
340		break;
341
342	default:
343		break;
344	}
345
346	return DC_OK;
347}
348
349/*
350 * This function calculates the bandwidth required for the stream timing
351 * and aggregates the stream bandwidth for the respective dpia link
352 *
353 * @stream: pointer to the dc_stream_state struct instance
354 * @num_streams: number of streams to be validated
355 *
356 * return: true if validation is succeeded
357 */
358bool link_validate_dpia_bandwidth(const struct dc_stream_state *stream, const unsigned int num_streams)
359{
360	int bw_needed[MAX_DPIA_NUM] = {0};
361	struct dc_link *dpia_link[MAX_DPIA_NUM] = {0};
362	int num_dpias = 0;
363
364	for (unsigned int i = 0; i < num_streams; ++i) {
365		if (stream[i].signal == SIGNAL_TYPE_DISPLAY_PORT) {
366			/* new dpia sst stream, check whether it exceeds max dpia */
367			if (num_dpias >= MAX_DPIA_NUM)
368				return false;
369
370			dpia_link[num_dpias] = stream[i].link;
371			bw_needed[num_dpias] = dc_bandwidth_in_kbps_from_timing(&stream[i].timing,
372					dc_link_get_highest_encoding_format(dpia_link[num_dpias]));
373			num_dpias++;
374		} else if (stream[i].signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
375			uint8_t j = 0;
376			/* check whether its a known dpia link */
377			for (; j < num_dpias; ++j) {
378				if (dpia_link[j] == stream[i].link)
379					break;
380			}
381
382			if (j == num_dpias) {
383				/* new dpia mst stream, check whether it exceeds max dpia */
384				if (num_dpias >= MAX_DPIA_NUM)
385					return false;
386				else {
387					dpia_link[j] = stream[i].link;
388					num_dpias++;
389				}
390			}
391
392			bw_needed[j] += dc_bandwidth_in_kbps_from_timing(&stream[i].timing,
393				dc_link_get_highest_encoding_format(dpia_link[j]));
394		}
395	}
396
397	/* Include dp overheads */
398	for (uint8_t i = 0; i < num_dpias; ++i) {
399		int dp_overhead = 0;
400
401		dp_overhead = link_dp_dpia_get_dp_overhead_in_dp_tunneling(dpia_link[i]);
402		bw_needed[i] += dp_overhead;
403	}
404
405	return dpia_validate_usb4_bw(dpia_link, bw_needed, num_dpias);
406}
407