15ca38a18SWenjing Liu /*
25ca38a18SWenjing Liu  * Copyright 2023 Advanced Micro Devices, Inc.
35ca38a18SWenjing Liu  *
45ca38a18SWenjing Liu  * Permission is hereby granted, free of charge, to any person obtaining a
55ca38a18SWenjing Liu  * copy of this software and associated documentation files (the "Software"),
65ca38a18SWenjing Liu  * to deal in the Software without restriction, including without limitation
75ca38a18SWenjing Liu  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85ca38a18SWenjing Liu  * and/or sell copies of the Software, and to permit persons to whom the
95ca38a18SWenjing Liu  * Software is furnished to do so, subject to the following conditions:
105ca38a18SWenjing Liu  *
115ca38a18SWenjing Liu  * The above copyright notice and this permission notice shall be included in
125ca38a18SWenjing Liu  * all copies or substantial portions of the Software.
135ca38a18SWenjing Liu  *
145ca38a18SWenjing Liu  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155ca38a18SWenjing Liu  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165ca38a18SWenjing Liu  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175ca38a18SWenjing Liu  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
185ca38a18SWenjing Liu  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
195ca38a18SWenjing Liu  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
205ca38a18SWenjing Liu  * OTHER DEALINGS IN THE SOFTWARE.
215ca38a18SWenjing Liu  *
225ca38a18SWenjing Liu  * Authors: AMD
235ca38a18SWenjing Liu  *
245ca38a18SWenjing Liu  */
255ca38a18SWenjing Liu 
265ca38a18SWenjing Liu /* FILE POLICY AND INTENDED USAGE:
275ca38a18SWenjing Liu  * This file provides single entrance to link functionality declared in dc
285ca38a18SWenjing Liu  * public headers. The file is intended to be used as a thin translation layer
295ca38a18SWenjing Liu  * that directly calls link internal functions without adding new functional
305ca38a18SWenjing Liu  * behavior.
315ca38a18SWenjing Liu  *
325ca38a18SWenjing Liu  * When exporting a new link related dc function, add function declaration in
335ca38a18SWenjing Liu  * dc.h with detail interface documentation, then add function implementation
345ca38a18SWenjing Liu  * in this file which calls link functions.
355ca38a18SWenjing Liu  */
365ca38a18SWenjing Liu #include "link.h"
37*7ae1dbe6SWenjing Liu #include "dce/dce_i2c.h"
38*7ae1dbe6SWenjing Liu struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
39*7ae1dbe6SWenjing Liu {
40*7ae1dbe6SWenjing Liu 	return dc->links[link_index];
41*7ae1dbe6SWenjing Liu }
42*7ae1dbe6SWenjing Liu 
43*7ae1dbe6SWenjing Liu void dc_get_edp_links(const struct dc *dc,
44*7ae1dbe6SWenjing Liu 		struct dc_link **edp_links,
45*7ae1dbe6SWenjing Liu 		int *edp_num)
46*7ae1dbe6SWenjing Liu {
47*7ae1dbe6SWenjing Liu 	int i;
48*7ae1dbe6SWenjing Liu 
49*7ae1dbe6SWenjing Liu 	*edp_num = 0;
50*7ae1dbe6SWenjing Liu 	for (i = 0; i < dc->link_count; i++) {
51*7ae1dbe6SWenjing Liu 		// report any eDP links, even unconnected DDI's
52*7ae1dbe6SWenjing Liu 		if (!dc->links[i])
53*7ae1dbe6SWenjing Liu 			continue;
54*7ae1dbe6SWenjing Liu 		if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) {
55*7ae1dbe6SWenjing Liu 			edp_links[*edp_num] = dc->links[i];
56*7ae1dbe6SWenjing Liu 			if (++(*edp_num) == MAX_NUM_EDP)
57*7ae1dbe6SWenjing Liu 				return;
58*7ae1dbe6SWenjing Liu 		}
59*7ae1dbe6SWenjing Liu 	}
60*7ae1dbe6SWenjing Liu }
61*7ae1dbe6SWenjing Liu 
62*7ae1dbe6SWenjing Liu bool dc_get_edp_link_panel_inst(const struct dc *dc,
63*7ae1dbe6SWenjing Liu 		const struct dc_link *link,
64*7ae1dbe6SWenjing Liu 		unsigned int *inst_out)
65*7ae1dbe6SWenjing Liu {
66*7ae1dbe6SWenjing Liu 	struct dc_link *edp_links[MAX_NUM_EDP];
67*7ae1dbe6SWenjing Liu 	int edp_num, i;
68*7ae1dbe6SWenjing Liu 
69*7ae1dbe6SWenjing Liu 	*inst_out = 0;
70*7ae1dbe6SWenjing Liu 	if (link->connector_signal != SIGNAL_TYPE_EDP)
71*7ae1dbe6SWenjing Liu 		return false;
72*7ae1dbe6SWenjing Liu 	dc_get_edp_links(dc, edp_links, &edp_num);
73*7ae1dbe6SWenjing Liu 	for (i = 0; i < edp_num; i++) {
74*7ae1dbe6SWenjing Liu 		if (link == edp_links[i])
75*7ae1dbe6SWenjing Liu 			break;
76*7ae1dbe6SWenjing Liu 		(*inst_out)++;
77*7ae1dbe6SWenjing Liu 	}
78*7ae1dbe6SWenjing Liu 	return true;
79*7ae1dbe6SWenjing Liu }
805ca38a18SWenjing Liu 
815ca38a18SWenjing Liu bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
825ca38a18SWenjing Liu {
835ca38a18SWenjing Liu 	return link_detect(link, reason);
845ca38a18SWenjing Liu }
855ca38a18SWenjing Liu 
865ca38a18SWenjing Liu bool dc_link_detect_connection_type(struct dc_link *link,
875ca38a18SWenjing Liu 		enum dc_connection_type *type)
885ca38a18SWenjing Liu {
895ca38a18SWenjing Liu 	return link_detect_connection_type(link, type);
905ca38a18SWenjing Liu }
915ca38a18SWenjing Liu 
925ca38a18SWenjing Liu const struct dc_link_status *dc_link_get_status(const struct dc_link *link)
935ca38a18SWenjing Liu {
945ca38a18SWenjing Liu 	return link_get_status(link);
955ca38a18SWenjing Liu }
965ca38a18SWenjing Liu #ifdef CONFIG_DRM_AMD_DC_HDCP
975ca38a18SWenjing Liu 
985ca38a18SWenjing Liu /* return true if the connected receiver supports the hdcp version */
995ca38a18SWenjing Liu bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal)
1005ca38a18SWenjing Liu {
1015ca38a18SWenjing Liu 	return link_is_hdcp14(link, signal);
1025ca38a18SWenjing Liu }
1035ca38a18SWenjing Liu 
1045ca38a18SWenjing Liu bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal)
1055ca38a18SWenjing Liu {
1065ca38a18SWenjing Liu 	return link_is_hdcp22(link, signal);
1075ca38a18SWenjing Liu }
1085ca38a18SWenjing Liu #endif
1095ca38a18SWenjing Liu 
1105ca38a18SWenjing Liu void dc_link_clear_dprx_states(struct dc_link *link)
1115ca38a18SWenjing Liu {
1125ca38a18SWenjing Liu 	link_clear_dprx_states(link);
1135ca38a18SWenjing Liu }
1145ca38a18SWenjing Liu 
1155ca38a18SWenjing Liu bool dc_link_reset_cur_dp_mst_topology(struct dc_link *link)
1165ca38a18SWenjing Liu {
1175ca38a18SWenjing Liu 	return link_reset_cur_dp_mst_topology(link);
1185ca38a18SWenjing Liu }
1195ca38a18SWenjing Liu 
1205ca38a18SWenjing Liu uint32_t dc_link_bandwidth_kbps(
1215ca38a18SWenjing Liu 	const struct dc_link *link,
1225ca38a18SWenjing Liu 	const struct dc_link_settings *link_settings)
1235ca38a18SWenjing Liu {
1245ca38a18SWenjing Liu 	return dp_link_bandwidth_kbps(link, link_settings);
1255ca38a18SWenjing Liu }
1265ca38a18SWenjing Liu 
1275ca38a18SWenjing Liu uint32_t dc_bandwidth_in_kbps_from_timing(
1285ca38a18SWenjing Liu 	const struct dc_crtc_timing *timing)
1295ca38a18SWenjing Liu {
1305ca38a18SWenjing Liu 	return link_timing_bandwidth_kbps(timing);
1315ca38a18SWenjing Liu }
1325ca38a18SWenjing Liu 
1335ca38a18SWenjing Liu void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map)
1345ca38a18SWenjing Liu {
1355ca38a18SWenjing Liu 	link_get_cur_res_map(dc, map);
1365ca38a18SWenjing Liu }
1375ca38a18SWenjing Liu 
1385ca38a18SWenjing Liu void dc_restore_link_res_map(const struct dc *dc, uint32_t *map)
1395ca38a18SWenjing Liu {
1405ca38a18SWenjing Liu 	link_restore_res_map(dc, map);
1415ca38a18SWenjing Liu }
1425ca38a18SWenjing Liu 
1435ca38a18SWenjing Liu bool dc_link_update_dsc_config(struct pipe_ctx *pipe_ctx)
1445ca38a18SWenjing Liu {
1455ca38a18SWenjing Liu 	return link_update_dsc_config(pipe_ctx);
1465ca38a18SWenjing Liu }
147*7ae1dbe6SWenjing Liu 
148*7ae1dbe6SWenjing Liu bool dc_is_oem_i2c_device_present(
149*7ae1dbe6SWenjing Liu 	struct dc *dc,
150*7ae1dbe6SWenjing Liu 	size_t slave_address)
151*7ae1dbe6SWenjing Liu {
152*7ae1dbe6SWenjing Liu 	if (dc->res_pool->oem_device)
153*7ae1dbe6SWenjing Liu 		return dce_i2c_oem_device_present(
154*7ae1dbe6SWenjing Liu 			dc->res_pool,
155*7ae1dbe6SWenjing Liu 			dc->res_pool->oem_device,
156*7ae1dbe6SWenjing Liu 			slave_address);
157*7ae1dbe6SWenjing Liu 
158*7ae1dbe6SWenjing Liu 	return false;
159*7ae1dbe6SWenjing Liu }
160*7ae1dbe6SWenjing Liu 
161*7ae1dbe6SWenjing Liu bool dc_submit_i2c(
162*7ae1dbe6SWenjing Liu 		struct dc *dc,
163*7ae1dbe6SWenjing Liu 		uint32_t link_index,
164*7ae1dbe6SWenjing Liu 		struct i2c_command *cmd)
165*7ae1dbe6SWenjing Liu {
166*7ae1dbe6SWenjing Liu 
167*7ae1dbe6SWenjing Liu 	struct dc_link *link = dc->links[link_index];
168*7ae1dbe6SWenjing Liu 	struct ddc_service *ddc = link->ddc;
169*7ae1dbe6SWenjing Liu 
170*7ae1dbe6SWenjing Liu 	return dce_i2c_submit_command(
171*7ae1dbe6SWenjing Liu 		dc->res_pool,
172*7ae1dbe6SWenjing Liu 		ddc->ddc_pin,
173*7ae1dbe6SWenjing Liu 		cmd);
174*7ae1dbe6SWenjing Liu }
175*7ae1dbe6SWenjing Liu 
176*7ae1dbe6SWenjing Liu bool dc_submit_i2c_oem(
177*7ae1dbe6SWenjing Liu 		struct dc *dc,
178*7ae1dbe6SWenjing Liu 		struct i2c_command *cmd)
179*7ae1dbe6SWenjing Liu {
180*7ae1dbe6SWenjing Liu 	struct ddc_service *ddc = dc->res_pool->oem_device;
181*7ae1dbe6SWenjing Liu 
182*7ae1dbe6SWenjing Liu 	if (ddc)
183*7ae1dbe6SWenjing Liu 		return dce_i2c_submit_command(
184*7ae1dbe6SWenjing Liu 			dc->res_pool,
185*7ae1dbe6SWenjing Liu 			ddc->ddc_pin,
186*7ae1dbe6SWenjing Liu 			cmd);
187*7ae1dbe6SWenjing Liu 
188*7ae1dbe6SWenjing Liu 	return false;
189*7ae1dbe6SWenjing Liu }
190*7ae1dbe6SWenjing Liu 
191