xref: /openbsd-src/sys/dev/pci/drm/amd/display/dc/bios/command_table.c (revision 1bb76ff151c0aba8e3312a604e4cd2e5195cf4b7)
1fb4d8502Sjsg /*
2fb4d8502Sjsg  * Copyright 2012-15 Advanced Micro Devices, Inc.
3fb4d8502Sjsg  *
4fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
5fb4d8502Sjsg  * copy of this software and associated documentation files (the "Software"),
6fb4d8502Sjsg  * to deal in the Software without restriction, including without limitation
7fb4d8502Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fb4d8502Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
9fb4d8502Sjsg  * Software is furnished to do so, subject to the following conditions:
10fb4d8502Sjsg  *
11fb4d8502Sjsg  * The above copyright notice and this permission notice shall be included in
12fb4d8502Sjsg  * all copies or substantial portions of the Software.
13fb4d8502Sjsg  *
14fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17fb4d8502Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18fb4d8502Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19fb4d8502Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20fb4d8502Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg  *
22fb4d8502Sjsg  * Authors: AMD
23fb4d8502Sjsg  *
24fb4d8502Sjsg  */
25fb4d8502Sjsg 
26fb4d8502Sjsg #include "dm_services.h"
27fb4d8502Sjsg #include "amdgpu.h"
28fb4d8502Sjsg #include "atom.h"
29fb4d8502Sjsg 
30fb4d8502Sjsg #include "include/bios_parser_interface.h"
31fb4d8502Sjsg 
32fb4d8502Sjsg #include "command_table.h"
33fb4d8502Sjsg #include "command_table_helper.h"
34fb4d8502Sjsg #include "bios_parser_helper.h"
35fb4d8502Sjsg #include "bios_parser_types_internal.h"
36fb4d8502Sjsg 
37fb4d8502Sjsg #define EXEC_BIOS_CMD_TABLE(command, params)\
38fb4d8502Sjsg 	(amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
39fb4d8502Sjsg 		GetIndexIntoMasterTable(COMMAND, command), \
40fb4d8502Sjsg 		(uint32_t *)&params) == 0)
41fb4d8502Sjsg 
42fb4d8502Sjsg #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
43fb4d8502Sjsg 	amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
44fb4d8502Sjsg 		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
45fb4d8502Sjsg 
46fb4d8502Sjsg #define BIOS_CMD_TABLE_PARA_REVISION(command)\
47fb4d8502Sjsg 	bios_cmd_table_para_revision(bp->base.ctx->driver_context, \
48fb4d8502Sjsg 		GetIndexIntoMasterTable(COMMAND, command))
49fb4d8502Sjsg 
50fb4d8502Sjsg static void init_dig_encoder_control(struct bios_parser *bp);
51fb4d8502Sjsg static void init_transmitter_control(struct bios_parser *bp);
52fb4d8502Sjsg static void init_set_pixel_clock(struct bios_parser *bp);
53fb4d8502Sjsg static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
54fb4d8502Sjsg static void init_adjust_display_pll(struct bios_parser *bp);
55fb4d8502Sjsg static void init_dac_encoder_control(struct bios_parser *bp);
56fb4d8502Sjsg static void init_dac_output_control(struct bios_parser *bp);
57fb4d8502Sjsg static void init_set_crtc_timing(struct bios_parser *bp);
58fb4d8502Sjsg static void init_enable_crtc(struct bios_parser *bp);
59fb4d8502Sjsg static void init_enable_crtc_mem_req(struct bios_parser *bp);
60fb4d8502Sjsg static void init_external_encoder_control(struct bios_parser *bp);
61fb4d8502Sjsg static void init_enable_disp_power_gating(struct bios_parser *bp);
62fb4d8502Sjsg static void init_program_clock(struct bios_parser *bp);
63fb4d8502Sjsg static void init_set_dce_clock(struct bios_parser *bp);
64fb4d8502Sjsg 
dal_bios_parser_init_cmd_tbl(struct bios_parser * bp)65fb4d8502Sjsg void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
66fb4d8502Sjsg {
67fb4d8502Sjsg 	init_dig_encoder_control(bp);
68fb4d8502Sjsg 	init_transmitter_control(bp);
69fb4d8502Sjsg 	init_set_pixel_clock(bp);
70fb4d8502Sjsg 	init_enable_spread_spectrum_on_ppll(bp);
71fb4d8502Sjsg 	init_adjust_display_pll(bp);
72fb4d8502Sjsg 	init_dac_encoder_control(bp);
73fb4d8502Sjsg 	init_dac_output_control(bp);
74fb4d8502Sjsg 	init_set_crtc_timing(bp);
75fb4d8502Sjsg 	init_enable_crtc(bp);
76fb4d8502Sjsg 	init_enable_crtc_mem_req(bp);
77fb4d8502Sjsg 	init_program_clock(bp);
78fb4d8502Sjsg 	init_external_encoder_control(bp);
79fb4d8502Sjsg 	init_enable_disp_power_gating(bp);
80fb4d8502Sjsg 	init_set_dce_clock(bp);
81fb4d8502Sjsg }
82fb4d8502Sjsg 
bios_cmd_table_para_revision(void * dev,uint32_t index)83fb4d8502Sjsg static uint32_t bios_cmd_table_para_revision(void *dev,
84fb4d8502Sjsg 					     uint32_t index)
85fb4d8502Sjsg {
86fb4d8502Sjsg 	struct amdgpu_device *adev = dev;
87fb4d8502Sjsg 	uint8_t frev, crev;
88fb4d8502Sjsg 
89fb4d8502Sjsg 	if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,
90fb4d8502Sjsg 					index,
91fb4d8502Sjsg 					&frev, &crev))
92fb4d8502Sjsg 		return crev;
93fb4d8502Sjsg 	else
94fb4d8502Sjsg 		return 0;
95fb4d8502Sjsg }
96fb4d8502Sjsg 
97fb4d8502Sjsg /*******************************************************************************
98fb4d8502Sjsg  ********************************************************************************
99fb4d8502Sjsg  **
100fb4d8502Sjsg  **                  D I G E N C O D E R C O N T R O L
101fb4d8502Sjsg  **
102fb4d8502Sjsg  ********************************************************************************
103fb4d8502Sjsg  *******************************************************************************/
104fb4d8502Sjsg static enum bp_result encoder_control_digx_v3(
105fb4d8502Sjsg 	struct bios_parser *bp,
106fb4d8502Sjsg 	struct bp_encoder_control *cntl);
107fb4d8502Sjsg 
108fb4d8502Sjsg static enum bp_result encoder_control_digx_v4(
109fb4d8502Sjsg 	struct bios_parser *bp,
110fb4d8502Sjsg 	struct bp_encoder_control *cntl);
111fb4d8502Sjsg 
112fb4d8502Sjsg static enum bp_result encoder_control_digx_v5(
113fb4d8502Sjsg 	struct bios_parser *bp,
114fb4d8502Sjsg 	struct bp_encoder_control *cntl);
115fb4d8502Sjsg 
116fb4d8502Sjsg static void init_encoder_control_dig_v1(struct bios_parser *bp);
117fb4d8502Sjsg 
init_dig_encoder_control(struct bios_parser * bp)118fb4d8502Sjsg static void init_dig_encoder_control(struct bios_parser *bp)
119fb4d8502Sjsg {
120fb4d8502Sjsg 	uint32_t version =
121fb4d8502Sjsg 		BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
122fb4d8502Sjsg 
123fb4d8502Sjsg 	switch (version) {
124fb4d8502Sjsg 	case 2:
125fb4d8502Sjsg 		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
126fb4d8502Sjsg 		break;
127fb4d8502Sjsg 	case 4:
128fb4d8502Sjsg 		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
129fb4d8502Sjsg 		break;
130fb4d8502Sjsg 
131fb4d8502Sjsg 	case 5:
132fb4d8502Sjsg 		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;
133fb4d8502Sjsg 		break;
134fb4d8502Sjsg 
135fb4d8502Sjsg 	default:
136fb4d8502Sjsg 		init_encoder_control_dig_v1(bp);
137fb4d8502Sjsg 		break;
138fb4d8502Sjsg 	}
139fb4d8502Sjsg }
140fb4d8502Sjsg 
141fb4d8502Sjsg static enum bp_result encoder_control_dig_v1(
142fb4d8502Sjsg 	struct bios_parser *bp,
143fb4d8502Sjsg 	struct bp_encoder_control *cntl);
144fb4d8502Sjsg static enum bp_result encoder_control_dig1_v1(
145fb4d8502Sjsg 	struct bios_parser *bp,
146fb4d8502Sjsg 	struct bp_encoder_control *cntl);
147fb4d8502Sjsg static enum bp_result encoder_control_dig2_v1(
148fb4d8502Sjsg 	struct bios_parser *bp,
149fb4d8502Sjsg 	struct bp_encoder_control *cntl);
150fb4d8502Sjsg 
init_encoder_control_dig_v1(struct bios_parser * bp)151fb4d8502Sjsg static void init_encoder_control_dig_v1(struct bios_parser *bp)
152fb4d8502Sjsg {
153fb4d8502Sjsg 	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
154fb4d8502Sjsg 
155fb4d8502Sjsg 	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
156fb4d8502Sjsg 		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
157fb4d8502Sjsg 	else
158fb4d8502Sjsg 		cmd_tbl->encoder_control_dig1 = NULL;
159fb4d8502Sjsg 
160fb4d8502Sjsg 	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
161fb4d8502Sjsg 		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
162fb4d8502Sjsg 	else
163fb4d8502Sjsg 		cmd_tbl->encoder_control_dig2 = NULL;
164fb4d8502Sjsg 
165fb4d8502Sjsg 	cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
166fb4d8502Sjsg }
167fb4d8502Sjsg 
encoder_control_dig_v1(struct bios_parser * bp,struct bp_encoder_control * cntl)168fb4d8502Sjsg static enum bp_result encoder_control_dig_v1(
169fb4d8502Sjsg 	struct bios_parser *bp,
170fb4d8502Sjsg 	struct bp_encoder_control *cntl)
171fb4d8502Sjsg {
172fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
173fb4d8502Sjsg 	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
174fb4d8502Sjsg 
175fb4d8502Sjsg 	if (cntl != NULL)
176fb4d8502Sjsg 		switch (cntl->engine_id) {
177fb4d8502Sjsg 		case ENGINE_ID_DIGA:
178fb4d8502Sjsg 			if (cmd_tbl->encoder_control_dig1 != NULL)
179fb4d8502Sjsg 				result =
180fb4d8502Sjsg 					cmd_tbl->encoder_control_dig1(bp, cntl);
181fb4d8502Sjsg 			break;
182fb4d8502Sjsg 		case ENGINE_ID_DIGB:
183fb4d8502Sjsg 			if (cmd_tbl->encoder_control_dig2 != NULL)
184fb4d8502Sjsg 				result =
185fb4d8502Sjsg 					cmd_tbl->encoder_control_dig2(bp, cntl);
186fb4d8502Sjsg 			break;
187fb4d8502Sjsg 
188fb4d8502Sjsg 		default:
189fb4d8502Sjsg 			break;
190fb4d8502Sjsg 		}
191fb4d8502Sjsg 
192fb4d8502Sjsg 	return result;
193fb4d8502Sjsg }
194fb4d8502Sjsg 
encoder_control_dig1_v1(struct bios_parser * bp,struct bp_encoder_control * cntl)195fb4d8502Sjsg static enum bp_result encoder_control_dig1_v1(
196fb4d8502Sjsg 	struct bios_parser *bp,
197fb4d8502Sjsg 	struct bp_encoder_control *cntl)
198fb4d8502Sjsg {
199fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
200fb4d8502Sjsg 	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
201fb4d8502Sjsg 
202fb4d8502Sjsg 	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
203fb4d8502Sjsg 
204fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
205fb4d8502Sjsg 		result = BP_RESULT_OK;
206fb4d8502Sjsg 
207fb4d8502Sjsg 	return result;
208fb4d8502Sjsg }
209fb4d8502Sjsg 
encoder_control_dig2_v1(struct bios_parser * bp,struct bp_encoder_control * cntl)210fb4d8502Sjsg static enum bp_result encoder_control_dig2_v1(
211fb4d8502Sjsg 	struct bios_parser *bp,
212fb4d8502Sjsg 	struct bp_encoder_control *cntl)
213fb4d8502Sjsg {
214fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
215fb4d8502Sjsg 	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
216fb4d8502Sjsg 
217fb4d8502Sjsg 	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
218fb4d8502Sjsg 
219fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
220fb4d8502Sjsg 		result = BP_RESULT_OK;
221fb4d8502Sjsg 
222fb4d8502Sjsg 	return result;
223fb4d8502Sjsg }
224fb4d8502Sjsg 
encoder_control_digx_v3(struct bios_parser * bp,struct bp_encoder_control * cntl)225fb4d8502Sjsg static enum bp_result encoder_control_digx_v3(
226fb4d8502Sjsg 	struct bios_parser *bp,
227fb4d8502Sjsg 	struct bp_encoder_control *cntl)
228fb4d8502Sjsg {
229fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
230fb4d8502Sjsg 	DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
231fb4d8502Sjsg 
232fb4d8502Sjsg 	if (LANE_COUNT_FOUR < cntl->lanes_number)
233fb4d8502Sjsg 		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
234fb4d8502Sjsg 	else
235fb4d8502Sjsg 		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
236fb4d8502Sjsg 
237fb4d8502Sjsg 	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
238fb4d8502Sjsg 
239fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units */
240fb4d8502Sjsg 	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
241fb4d8502Sjsg 	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
242fb4d8502Sjsg 	params.ucEncoderMode =
243fb4d8502Sjsg 			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
244fb4d8502Sjsg 					cntl->signal,
245fb4d8502Sjsg 					cntl->enable_dp_audio);
246fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
247fb4d8502Sjsg 
248ad8b1aafSjsg 	switch (cntl->color_depth) {
249ad8b1aafSjsg 	case COLOR_DEPTH_888:
250ad8b1aafSjsg 		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
251ad8b1aafSjsg 		break;
252ad8b1aafSjsg 	case COLOR_DEPTH_101010:
253ad8b1aafSjsg 		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
254ad8b1aafSjsg 		break;
255ad8b1aafSjsg 	case COLOR_DEPTH_121212:
256ad8b1aafSjsg 		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
257ad8b1aafSjsg 		break;
258ad8b1aafSjsg 	case COLOR_DEPTH_161616:
259ad8b1aafSjsg 		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
260ad8b1aafSjsg 		break;
261ad8b1aafSjsg 	default:
262ad8b1aafSjsg 		break;
263ad8b1aafSjsg 	}
264ad8b1aafSjsg 
265fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
266fb4d8502Sjsg 		result = BP_RESULT_OK;
267fb4d8502Sjsg 
268fb4d8502Sjsg 	return result;
269fb4d8502Sjsg }
270fb4d8502Sjsg 
encoder_control_digx_v4(struct bios_parser * bp,struct bp_encoder_control * cntl)271fb4d8502Sjsg static enum bp_result encoder_control_digx_v4(
272fb4d8502Sjsg 	struct bios_parser *bp,
273fb4d8502Sjsg 	struct bp_encoder_control *cntl)
274fb4d8502Sjsg {
275fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
276fb4d8502Sjsg 	DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
277fb4d8502Sjsg 
278fb4d8502Sjsg 	if (LANE_COUNT_FOUR < cntl->lanes_number)
279fb4d8502Sjsg 		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
280fb4d8502Sjsg 	else
281fb4d8502Sjsg 		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
282fb4d8502Sjsg 
283fb4d8502Sjsg 	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
284fb4d8502Sjsg 
285fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units */
286fb4d8502Sjsg 	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
287fb4d8502Sjsg 	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
288fb4d8502Sjsg 	params.ucEncoderMode =
289fb4d8502Sjsg 			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
290fb4d8502Sjsg 					cntl->signal,
291fb4d8502Sjsg 					cntl->enable_dp_audio));
292fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
293fb4d8502Sjsg 
294ad8b1aafSjsg 	switch (cntl->color_depth) {
295ad8b1aafSjsg 	case COLOR_DEPTH_888:
296ad8b1aafSjsg 		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
297ad8b1aafSjsg 		break;
298ad8b1aafSjsg 	case COLOR_DEPTH_101010:
299ad8b1aafSjsg 		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
300ad8b1aafSjsg 		break;
301ad8b1aafSjsg 	case COLOR_DEPTH_121212:
302ad8b1aafSjsg 		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
303ad8b1aafSjsg 		break;
304ad8b1aafSjsg 	case COLOR_DEPTH_161616:
305ad8b1aafSjsg 		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
306ad8b1aafSjsg 		break;
307ad8b1aafSjsg 	default:
308ad8b1aafSjsg 		break;
309ad8b1aafSjsg 	}
310ad8b1aafSjsg 
311fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
312fb4d8502Sjsg 		result = BP_RESULT_OK;
313fb4d8502Sjsg 
314fb4d8502Sjsg 	return result;
315fb4d8502Sjsg }
316fb4d8502Sjsg 
encoder_control_digx_v5(struct bios_parser * bp,struct bp_encoder_control * cntl)317fb4d8502Sjsg static enum bp_result encoder_control_digx_v5(
318fb4d8502Sjsg 	struct bios_parser *bp,
319fb4d8502Sjsg 	struct bp_encoder_control *cntl)
320fb4d8502Sjsg {
321fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
322fb4d8502Sjsg 	ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
323fb4d8502Sjsg 
324fb4d8502Sjsg 	params.ucDigId = (uint8_t)(cntl->engine_id);
325fb4d8502Sjsg 	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
326fb4d8502Sjsg 
327fb4d8502Sjsg 	params.ulPixelClock = cntl->pixel_clock / 10;
328fb4d8502Sjsg 	params.ucDigMode =
329fb4d8502Sjsg 			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
330fb4d8502Sjsg 					cntl->signal,
331fb4d8502Sjsg 					cntl->enable_dp_audio));
332fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
333fb4d8502Sjsg 
334fb4d8502Sjsg 	switch (cntl->color_depth) {
335fb4d8502Sjsg 	case COLOR_DEPTH_888:
336fb4d8502Sjsg 		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
337fb4d8502Sjsg 		break;
338fb4d8502Sjsg 	case COLOR_DEPTH_101010:
339fb4d8502Sjsg 		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
340fb4d8502Sjsg 		break;
341fb4d8502Sjsg 	case COLOR_DEPTH_121212:
342fb4d8502Sjsg 		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
343fb4d8502Sjsg 		break;
344fb4d8502Sjsg 	case COLOR_DEPTH_161616:
345fb4d8502Sjsg 		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
346fb4d8502Sjsg 		break;
347fb4d8502Sjsg 	default:
348fb4d8502Sjsg 		break;
349fb4d8502Sjsg 	}
350fb4d8502Sjsg 
351fb4d8502Sjsg 	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
352fb4d8502Sjsg 		switch (cntl->color_depth) {
353fb4d8502Sjsg 		case COLOR_DEPTH_101010:
354fb4d8502Sjsg 			params.ulPixelClock =
355fb4d8502Sjsg 				(params.ulPixelClock * 30) / 24;
356fb4d8502Sjsg 			break;
357fb4d8502Sjsg 		case COLOR_DEPTH_121212:
358fb4d8502Sjsg 			params.ulPixelClock =
359fb4d8502Sjsg 				(params.ulPixelClock * 36) / 24;
360fb4d8502Sjsg 			break;
361fb4d8502Sjsg 		case COLOR_DEPTH_161616:
362fb4d8502Sjsg 			params.ulPixelClock =
363fb4d8502Sjsg 				(params.ulPixelClock * 48) / 24;
364fb4d8502Sjsg 			break;
365fb4d8502Sjsg 		default:
366fb4d8502Sjsg 			break;
367fb4d8502Sjsg 		}
368fb4d8502Sjsg 
369fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
370fb4d8502Sjsg 		result = BP_RESULT_OK;
371fb4d8502Sjsg 
372fb4d8502Sjsg 	return result;
373fb4d8502Sjsg }
374fb4d8502Sjsg 
375fb4d8502Sjsg /*******************************************************************************
376fb4d8502Sjsg  ********************************************************************************
377fb4d8502Sjsg  **
378fb4d8502Sjsg  **                  TRANSMITTER CONTROL
379fb4d8502Sjsg  **
380fb4d8502Sjsg  ********************************************************************************
381fb4d8502Sjsg  *******************************************************************************/
382fb4d8502Sjsg 
383fb4d8502Sjsg static enum bp_result transmitter_control_v2(
384fb4d8502Sjsg 	struct bios_parser *bp,
385fb4d8502Sjsg 	struct bp_transmitter_control *cntl);
386fb4d8502Sjsg static enum bp_result transmitter_control_v3(
387fb4d8502Sjsg 	struct bios_parser *bp,
388fb4d8502Sjsg 	struct bp_transmitter_control *cntl);
389fb4d8502Sjsg static enum bp_result transmitter_control_v4(
390fb4d8502Sjsg 	struct bios_parser *bp,
391fb4d8502Sjsg 	struct bp_transmitter_control *cntl);
392fb4d8502Sjsg static enum bp_result transmitter_control_v1_5(
393fb4d8502Sjsg 	struct bios_parser *bp,
394fb4d8502Sjsg 	struct bp_transmitter_control *cntl);
395fb4d8502Sjsg static enum bp_result transmitter_control_v1_6(
396fb4d8502Sjsg 	struct bios_parser *bp,
397fb4d8502Sjsg 	struct bp_transmitter_control *cntl);
398fb4d8502Sjsg 
init_transmitter_control(struct bios_parser * bp)399fb4d8502Sjsg static void init_transmitter_control(struct bios_parser *bp)
400fb4d8502Sjsg {
401fb4d8502Sjsg 	uint8_t frev;
402fb4d8502Sjsg 	uint8_t crev;
403fb4d8502Sjsg 
404fb4d8502Sjsg 	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
405fb4d8502Sjsg 			frev, crev) == false)
406fb4d8502Sjsg 		BREAK_TO_DEBUGGER();
407fb4d8502Sjsg 	switch (crev) {
408fb4d8502Sjsg 	case 2:
409fb4d8502Sjsg 		bp->cmd_tbl.transmitter_control = transmitter_control_v2;
410fb4d8502Sjsg 		break;
411fb4d8502Sjsg 	case 3:
412fb4d8502Sjsg 		bp->cmd_tbl.transmitter_control = transmitter_control_v3;
413fb4d8502Sjsg 		break;
414fb4d8502Sjsg 	case 4:
415fb4d8502Sjsg 		bp->cmd_tbl.transmitter_control = transmitter_control_v4;
416fb4d8502Sjsg 		break;
417fb4d8502Sjsg 	case 5:
418fb4d8502Sjsg 		bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
419fb4d8502Sjsg 		break;
420fb4d8502Sjsg 	case 6:
421fb4d8502Sjsg 		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
422fb4d8502Sjsg 		break;
423fb4d8502Sjsg 	default:
424fb4d8502Sjsg 		dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
425fb4d8502Sjsg 		bp->cmd_tbl.transmitter_control = NULL;
426fb4d8502Sjsg 		break;
427fb4d8502Sjsg 	}
428fb4d8502Sjsg }
429fb4d8502Sjsg 
transmitter_control_v2(struct bios_parser * bp,struct bp_transmitter_control * cntl)430fb4d8502Sjsg static enum bp_result transmitter_control_v2(
431fb4d8502Sjsg 	struct bios_parser *bp,
432fb4d8502Sjsg 	struct bp_transmitter_control *cntl)
433fb4d8502Sjsg {
434fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
435fb4d8502Sjsg 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
436fb4d8502Sjsg 	enum connector_id connector_id =
437fb4d8502Sjsg 		dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
438fb4d8502Sjsg 
439fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
440fb4d8502Sjsg 
441fb4d8502Sjsg 	switch (cntl->transmitter) {
442fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_A:
443fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_B:
444fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_C:
445fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_D:
446fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_E:
447fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_F:
448fb4d8502Sjsg 	case TRANSMITTER_TRAVIS_LCD:
449fb4d8502Sjsg 		break;
450fb4d8502Sjsg 	default:
451fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
452fb4d8502Sjsg 	}
453fb4d8502Sjsg 
454fb4d8502Sjsg 	switch (cntl->action) {
455fb4d8502Sjsg 	case TRANSMITTER_CONTROL_INIT:
456fb4d8502Sjsg 		if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
457fb4d8502Sjsg 				(CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
458fb4d8502Sjsg 			/* on INIT this bit should be set according to the
459*1bb76ff1Sjsg 			 * physical connector
460fb4d8502Sjsg 			 * Bit0: dual link connector flag
461fb4d8502Sjsg 			 * =0 connector is single link connector
462fb4d8502Sjsg 			 * =1 connector is dual link connector
463fb4d8502Sjsg 			 */
464fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
465fb4d8502Sjsg 
466fb4d8502Sjsg 		/* connector object id */
467fb4d8502Sjsg 		params.usInitInfo =
468fb4d8502Sjsg 				cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
469fb4d8502Sjsg 		break;
470fb4d8502Sjsg 	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
471*1bb76ff1Sjsg 		/* voltage swing and pre-emphsis */
472fb4d8502Sjsg 		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
473fb4d8502Sjsg 		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
474fb4d8502Sjsg 		break;
475fb4d8502Sjsg 	default:
476fb4d8502Sjsg 		/* if dual-link */
477fb4d8502Sjsg 		if (LANE_COUNT_FOUR < cntl->lanes_number) {
478fb4d8502Sjsg 			/* on ENABLE/DISABLE this bit should be set according to
479fb4d8502Sjsg 			 * actual timing (number of lanes)
480fb4d8502Sjsg 			 * Bit0: dual link connector flag
481fb4d8502Sjsg 			 * =0 connector is single link connector
482fb4d8502Sjsg 			 * =1 connector is dual link connector
483fb4d8502Sjsg 			 */
484fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
485fb4d8502Sjsg 
486fb4d8502Sjsg 			/* link rate, half for dual link
487fb4d8502Sjsg 			 * We need to convert from KHz units into 20KHz units
488fb4d8502Sjsg 			 */
489fb4d8502Sjsg 			params.usPixelClock =
490fb4d8502Sjsg 					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
491fb4d8502Sjsg 		} else
492fb4d8502Sjsg 			/* link rate, half for dual link
493fb4d8502Sjsg 			 * We need to convert from KHz units into 10KHz units
494fb4d8502Sjsg 			 */
495fb4d8502Sjsg 			params.usPixelClock =
496fb4d8502Sjsg 					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
497fb4d8502Sjsg 		break;
498fb4d8502Sjsg 	}
499fb4d8502Sjsg 
500fb4d8502Sjsg 	/* 00 - coherent mode
501fb4d8502Sjsg 	 * 01 - incoherent mode
502fb4d8502Sjsg 	 */
503fb4d8502Sjsg 
504fb4d8502Sjsg 	params.acConfig.fCoherentMode = cntl->coherent;
505fb4d8502Sjsg 
506fb4d8502Sjsg 	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
507fb4d8502Sjsg 			|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
508fb4d8502Sjsg 			|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
509fb4d8502Sjsg 		/* Bit2: Transmitter Link selection
510fb4d8502Sjsg 		 * =0 when bit0=0, single link A/C/E, when bit0=1,
511fb4d8502Sjsg 		 * master link A/C/E
512fb4d8502Sjsg 		 * =1 when bit0=0, single link B/D/F, when bit0=1,
513fb4d8502Sjsg 		 * master link B/D/F
514fb4d8502Sjsg 		 */
515fb4d8502Sjsg 		params.acConfig.ucLinkSel = 1;
516fb4d8502Sjsg 
517fb4d8502Sjsg 	if (ENGINE_ID_DIGB == cntl->engine_id)
518fb4d8502Sjsg 		/* Bit3: Transmitter data source selection
519fb4d8502Sjsg 		 * =0 DIGA is data source.
520fb4d8502Sjsg 		 * =1 DIGB is data source.
521fb4d8502Sjsg 		 * This bit is only useful when ucAction= ATOM_ENABLE
522fb4d8502Sjsg 		 */
523fb4d8502Sjsg 		params.acConfig.ucEncoderSel = 1;
524fb4d8502Sjsg 
525*1bb76ff1Sjsg 	if (CONNECTOR_ID_DISPLAY_PORT == connector_id ||
526*1bb76ff1Sjsg 	    CONNECTOR_ID_USBC == connector_id)
527fb4d8502Sjsg 		/* Bit4: DP connector flag
528fb4d8502Sjsg 		 * =0 connector is none-DP connector
529fb4d8502Sjsg 		 * =1 connector is DP connector
530fb4d8502Sjsg 		 */
531fb4d8502Sjsg 		params.acConfig.fDPConnector = 1;
532fb4d8502Sjsg 
533fb4d8502Sjsg 	/* Bit[7:6]: Transmitter selection
534fb4d8502Sjsg 	 * =0 UNIPHY_ENCODER: UNIPHYA/B
535fb4d8502Sjsg 	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
536fb4d8502Sjsg 	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
537fb4d8502Sjsg 	 * =3 reserved
538fb4d8502Sjsg 	 */
539fb4d8502Sjsg 	params.acConfig.ucTransmitterSel =
540fb4d8502Sjsg 			(uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
541fb4d8502Sjsg 					cntl->transmitter);
542fb4d8502Sjsg 
543fb4d8502Sjsg 	params.ucAction = (uint8_t)cntl->action;
544fb4d8502Sjsg 
545fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
546fb4d8502Sjsg 		result = BP_RESULT_OK;
547fb4d8502Sjsg 
548fb4d8502Sjsg 	return result;
549fb4d8502Sjsg }
550fb4d8502Sjsg 
transmitter_control_v3(struct bios_parser * bp,struct bp_transmitter_control * cntl)551fb4d8502Sjsg static enum bp_result transmitter_control_v3(
552fb4d8502Sjsg 	struct bios_parser *bp,
553fb4d8502Sjsg 	struct bp_transmitter_control *cntl)
554fb4d8502Sjsg {
555fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
556fb4d8502Sjsg 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
557fb4d8502Sjsg 	uint32_t pll_id;
558fb4d8502Sjsg 	enum connector_id conn_id =
559fb4d8502Sjsg 			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
560fb4d8502Sjsg 	const struct command_table_helper *cmd = bp->cmd_helper;
561fb4d8502Sjsg 	bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
562fb4d8502Sjsg 					|| (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
563fb4d8502Sjsg 
564fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
565fb4d8502Sjsg 
566fb4d8502Sjsg 	switch (cntl->transmitter) {
567fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_A:
568fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_B:
569fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_C:
570fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_D:
571fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_E:
572fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_F:
573fb4d8502Sjsg 	case TRANSMITTER_TRAVIS_LCD:
574fb4d8502Sjsg 		break;
575fb4d8502Sjsg 	default:
576fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
577fb4d8502Sjsg 	}
578fb4d8502Sjsg 
579fb4d8502Sjsg 	if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
580fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
581fb4d8502Sjsg 
582fb4d8502Sjsg 	/* fill information based on the action */
583fb4d8502Sjsg 	switch (cntl->action) {
584fb4d8502Sjsg 	case TRANSMITTER_CONTROL_INIT:
585fb4d8502Sjsg 		if (dual_link_conn) {
586fb4d8502Sjsg 			/* on INIT this bit should be set according to the
587fb4d8502Sjsg 			 * phisycal connector
588fb4d8502Sjsg 			 * Bit0: dual link connector flag
589fb4d8502Sjsg 			 * =0 connector is single link connector
590fb4d8502Sjsg 			 * =1 connector is dual link connector
591fb4d8502Sjsg 			 */
592fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
593fb4d8502Sjsg 		}
594fb4d8502Sjsg 
595fb4d8502Sjsg 		/* connector object id */
596fb4d8502Sjsg 		params.usInitInfo =
597fb4d8502Sjsg 				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
598fb4d8502Sjsg 		break;
599fb4d8502Sjsg 	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
600fb4d8502Sjsg 		/* votage swing and pre-emphsis */
601fb4d8502Sjsg 		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
602fb4d8502Sjsg 		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
603fb4d8502Sjsg 		break;
604fb4d8502Sjsg 	default:
605fb4d8502Sjsg 		if (dual_link_conn && cntl->multi_path)
606fb4d8502Sjsg 			/* on ENABLE/DISABLE this bit should be set according to
607fb4d8502Sjsg 			 * actual timing (number of lanes)
608fb4d8502Sjsg 			 * Bit0: dual link connector flag
609fb4d8502Sjsg 			 * =0 connector is single link connector
610fb4d8502Sjsg 			 * =1 connector is dual link connector
611fb4d8502Sjsg 			 */
612fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
613fb4d8502Sjsg 
614fb4d8502Sjsg 		/* if dual-link */
615fb4d8502Sjsg 		if (LANE_COUNT_FOUR < cntl->lanes_number) {
616fb4d8502Sjsg 			/* on ENABLE/DISABLE this bit should be set according to
617fb4d8502Sjsg 			 * actual timing (number of lanes)
618fb4d8502Sjsg 			 * Bit0: dual link connector flag
619fb4d8502Sjsg 			 * =0 connector is single link connector
620fb4d8502Sjsg 			 * =1 connector is dual link connector
621fb4d8502Sjsg 			 */
622fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
623fb4d8502Sjsg 
624fb4d8502Sjsg 			/* link rate, half for dual link
625fb4d8502Sjsg 			 * We need to convert from KHz units into 20KHz units
626fb4d8502Sjsg 			 */
627fb4d8502Sjsg 			params.usPixelClock =
628fb4d8502Sjsg 					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
629fb4d8502Sjsg 		} else {
630fb4d8502Sjsg 			/* link rate, half for dual link
631fb4d8502Sjsg 			 * We need to convert from KHz units into 10KHz units
632fb4d8502Sjsg 			 */
633fb4d8502Sjsg 			params.usPixelClock =
634fb4d8502Sjsg 					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
635fb4d8502Sjsg 		}
636fb4d8502Sjsg 		break;
637fb4d8502Sjsg 	}
638fb4d8502Sjsg 
639fb4d8502Sjsg 	/* 00 - coherent mode
640fb4d8502Sjsg 	 * 01 - incoherent mode
641fb4d8502Sjsg 	 */
642fb4d8502Sjsg 
643fb4d8502Sjsg 	params.acConfig.fCoherentMode = cntl->coherent;
644fb4d8502Sjsg 
645fb4d8502Sjsg 	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
646fb4d8502Sjsg 		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
647fb4d8502Sjsg 		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
648fb4d8502Sjsg 		/* Bit2: Transmitter Link selection
649fb4d8502Sjsg 		 * =0 when bit0=0, single link A/C/E, when bit0=1,
650fb4d8502Sjsg 		 * master link A/C/E
651fb4d8502Sjsg 		 * =1 when bit0=0, single link B/D/F, when bit0=1,
652fb4d8502Sjsg 		 * master link B/D/F
653fb4d8502Sjsg 		 */
654fb4d8502Sjsg 		params.acConfig.ucLinkSel = 1;
655fb4d8502Sjsg 
656fb4d8502Sjsg 	if (ENGINE_ID_DIGB == cntl->engine_id)
657fb4d8502Sjsg 		/* Bit3: Transmitter data source selection
658fb4d8502Sjsg 		 * =0 DIGA is data source.
659fb4d8502Sjsg 		 * =1 DIGB is data source.
660fb4d8502Sjsg 		 * This bit is only useful when ucAction= ATOM_ENABLE
661fb4d8502Sjsg 		 */
662fb4d8502Sjsg 		params.acConfig.ucEncoderSel = 1;
663fb4d8502Sjsg 
664fb4d8502Sjsg 	/* Bit[7:6]: Transmitter selection
665fb4d8502Sjsg 	 * =0 UNIPHY_ENCODER: UNIPHYA/B
666fb4d8502Sjsg 	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
667fb4d8502Sjsg 	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
668fb4d8502Sjsg 	 * =3 reserved
669fb4d8502Sjsg 	 */
670fb4d8502Sjsg 	params.acConfig.ucTransmitterSel =
671fb4d8502Sjsg 			(uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
672fb4d8502Sjsg 
673fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)cntl->lanes_number;
674fb4d8502Sjsg 
675fb4d8502Sjsg 	params.acConfig.ucRefClkSource = (uint8_t)pll_id;
676fb4d8502Sjsg 
677fb4d8502Sjsg 	params.ucAction = (uint8_t)cntl->action;
678fb4d8502Sjsg 
679fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
680fb4d8502Sjsg 		result = BP_RESULT_OK;
681fb4d8502Sjsg 
682fb4d8502Sjsg 	return result;
683fb4d8502Sjsg }
684fb4d8502Sjsg 
transmitter_control_v4(struct bios_parser * bp,struct bp_transmitter_control * cntl)685fb4d8502Sjsg static enum bp_result transmitter_control_v4(
686fb4d8502Sjsg 	struct bios_parser *bp,
687fb4d8502Sjsg 	struct bp_transmitter_control *cntl)
688fb4d8502Sjsg {
689fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
690fb4d8502Sjsg 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
691fb4d8502Sjsg 	uint32_t ref_clk_src_id;
692fb4d8502Sjsg 	enum connector_id conn_id =
693fb4d8502Sjsg 			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
694fb4d8502Sjsg 	const struct command_table_helper *cmd = bp->cmd_helper;
695fb4d8502Sjsg 
696fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
697fb4d8502Sjsg 
698fb4d8502Sjsg 	switch (cntl->transmitter) {
699fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_A:
700fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_B:
701fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_C:
702fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_D:
703fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_E:
704fb4d8502Sjsg 	case TRANSMITTER_UNIPHY_F:
705fb4d8502Sjsg 	case TRANSMITTER_TRAVIS_LCD:
706fb4d8502Sjsg 		break;
707fb4d8502Sjsg 	default:
708fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
709fb4d8502Sjsg 	}
710fb4d8502Sjsg 
711fb4d8502Sjsg 	if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
712fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
713fb4d8502Sjsg 
714fb4d8502Sjsg 	switch (cntl->action) {
715fb4d8502Sjsg 	case TRANSMITTER_CONTROL_INIT:
716fb4d8502Sjsg 	{
717fb4d8502Sjsg 		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
718fb4d8502Sjsg 				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
719fb4d8502Sjsg 			/* on INIT this bit should be set according to the
720fb4d8502Sjsg 			 * phisycal connector
721fb4d8502Sjsg 			 * Bit0: dual link connector flag
722fb4d8502Sjsg 			 * =0 connector is single link connector
723fb4d8502Sjsg 			 * =1 connector is dual link connector
724fb4d8502Sjsg 			 */
725fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
726fb4d8502Sjsg 
727fb4d8502Sjsg 		/* connector object id */
728fb4d8502Sjsg 		params.usInitInfo =
729fb4d8502Sjsg 				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
730fb4d8502Sjsg 	}
731fb4d8502Sjsg 	break;
732fb4d8502Sjsg 	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
733fb4d8502Sjsg 		/* votage swing and pre-emphsis */
734fb4d8502Sjsg 		params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
735fb4d8502Sjsg 		params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
736fb4d8502Sjsg 		break;
737fb4d8502Sjsg 	default:
738fb4d8502Sjsg 		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
739fb4d8502Sjsg 				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
740fb4d8502Sjsg 			/* on ENABLE/DISABLE this bit should be set according to
741fb4d8502Sjsg 			 * actual timing (number of lanes)
742fb4d8502Sjsg 			 * Bit0: dual link connector flag
743fb4d8502Sjsg 			 * =0 connector is single link connector
744fb4d8502Sjsg 			 * =1 connector is dual link connector
745fb4d8502Sjsg 			 */
746fb4d8502Sjsg 			params.acConfig.fDualLinkConnector = 1;
747fb4d8502Sjsg 
748fb4d8502Sjsg 		/* if dual-link */
749fb4d8502Sjsg 		if (LANE_COUNT_FOUR < cntl->lanes_number)
750fb4d8502Sjsg 			/* link rate, half for dual link
751fb4d8502Sjsg 			 * We need to convert from KHz units into 20KHz units
752fb4d8502Sjsg 			 */
753fb4d8502Sjsg 			params.usPixelClock =
754fb4d8502Sjsg 					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
755fb4d8502Sjsg 		else {
756fb4d8502Sjsg 			/* link rate, half for dual link
757fb4d8502Sjsg 			 * We need to convert from KHz units into 10KHz units
758fb4d8502Sjsg 			 */
759fb4d8502Sjsg 			params.usPixelClock =
760fb4d8502Sjsg 					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
761fb4d8502Sjsg 		}
762fb4d8502Sjsg 		break;
763fb4d8502Sjsg 	}
764fb4d8502Sjsg 
765fb4d8502Sjsg 	/* 00 - coherent mode
766fb4d8502Sjsg 	 * 01 - incoherent mode
767fb4d8502Sjsg 	 */
768fb4d8502Sjsg 
769fb4d8502Sjsg 	params.acConfig.fCoherentMode = cntl->coherent;
770fb4d8502Sjsg 
771fb4d8502Sjsg 	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
772fb4d8502Sjsg 		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
773fb4d8502Sjsg 		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
774fb4d8502Sjsg 		/* Bit2: Transmitter Link selection
775fb4d8502Sjsg 		 * =0 when bit0=0, single link A/C/E, when bit0=1,
776fb4d8502Sjsg 		 * master link A/C/E
777fb4d8502Sjsg 		 * =1 when bit0=0, single link B/D/F, when bit0=1,
778fb4d8502Sjsg 		 * master link B/D/F
779fb4d8502Sjsg 		 */
780fb4d8502Sjsg 		params.acConfig.ucLinkSel = 1;
781fb4d8502Sjsg 
782fb4d8502Sjsg 	if (ENGINE_ID_DIGB == cntl->engine_id)
783fb4d8502Sjsg 		/* Bit3: Transmitter data source selection
784fb4d8502Sjsg 		 * =0 DIGA is data source.
785fb4d8502Sjsg 		 * =1 DIGB is data source.
786fb4d8502Sjsg 		 * This bit is only useful when ucAction= ATOM_ENABLE
787fb4d8502Sjsg 		 */
788fb4d8502Sjsg 		params.acConfig.ucEncoderSel = 1;
789fb4d8502Sjsg 
790fb4d8502Sjsg 	/* Bit[7:6]: Transmitter selection
791fb4d8502Sjsg 	 * =0 UNIPHY_ENCODER: UNIPHYA/B
792fb4d8502Sjsg 	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
793fb4d8502Sjsg 	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
794fb4d8502Sjsg 	 * =3 reserved
795fb4d8502Sjsg 	 */
796fb4d8502Sjsg 	params.acConfig.ucTransmitterSel =
797fb4d8502Sjsg 		(uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
798fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
799fb4d8502Sjsg 	params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
800fb4d8502Sjsg 	params.ucAction = (uint8_t)(cntl->action);
801fb4d8502Sjsg 
802fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
803fb4d8502Sjsg 		result = BP_RESULT_OK;
804fb4d8502Sjsg 
805fb4d8502Sjsg 	return result;
806fb4d8502Sjsg }
807fb4d8502Sjsg 
transmitter_control_v1_5(struct bios_parser * bp,struct bp_transmitter_control * cntl)808fb4d8502Sjsg static enum bp_result transmitter_control_v1_5(
809fb4d8502Sjsg 	struct bios_parser *bp,
810fb4d8502Sjsg 	struct bp_transmitter_control *cntl)
811fb4d8502Sjsg {
812fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
813fb4d8502Sjsg 	const struct command_table_helper *cmd = bp->cmd_helper;
814fb4d8502Sjsg 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
815fb4d8502Sjsg 
816fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
817fb4d8502Sjsg 	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
818fb4d8502Sjsg 	params.ucAction = (uint8_t)cntl->action;
819fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)cntl->lanes_number;
820fb4d8502Sjsg 	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
821fb4d8502Sjsg 
822fb4d8502Sjsg 	params.ucDigMode =
823fb4d8502Sjsg 		cmd->signal_type_to_atom_dig_mode(cntl->signal);
824fb4d8502Sjsg 	params.asConfig.ucPhyClkSrcId =
825fb4d8502Sjsg 		cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
826fb4d8502Sjsg 	/* 00 - coherent mode */
827fb4d8502Sjsg 	params.asConfig.ucCoherentMode = cntl->coherent;
828fb4d8502Sjsg 	params.asConfig.ucHPDSel =
829fb4d8502Sjsg 		cmd->hpd_sel_to_atom(cntl->hpd_sel);
830fb4d8502Sjsg 	params.ucDigEncoderSel =
831fb4d8502Sjsg 		cmd->dig_encoder_sel_to_atom(cntl->engine_id);
832fb4d8502Sjsg 	params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
833fb4d8502Sjsg 	params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
834fb4d8502Sjsg 	/*
835fb4d8502Sjsg 	 * In SI/TN case, caller have to set usPixelClock as following:
836fb4d8502Sjsg 	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
837fb4d8502Sjsg 	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
838fb4d8502Sjsg 	 * DVI single link mode: usPixelClock = pixel clock
839fb4d8502Sjsg 	 * DVI dual link mode: usPixelClock = pixel clock
840fb4d8502Sjsg 	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
841fb4d8502Sjsg 	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
842fb4d8502Sjsg 	 * LVDS mode: usPixelClock = pixel clock
843fb4d8502Sjsg 	 */
844fb4d8502Sjsg 	if  (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
845fb4d8502Sjsg 		switch (cntl->color_depth) {
846fb4d8502Sjsg 		case COLOR_DEPTH_101010:
847fb4d8502Sjsg 			params.usSymClock =
848fb4d8502Sjsg 				cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
849fb4d8502Sjsg 			break;
850fb4d8502Sjsg 		case COLOR_DEPTH_121212:
851fb4d8502Sjsg 			params.usSymClock =
852fb4d8502Sjsg 				cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
853fb4d8502Sjsg 			break;
854fb4d8502Sjsg 		case COLOR_DEPTH_161616:
855fb4d8502Sjsg 			params.usSymClock =
856fb4d8502Sjsg 				cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
857fb4d8502Sjsg 			break;
858fb4d8502Sjsg 		default:
859fb4d8502Sjsg 			break;
860fb4d8502Sjsg 		}
861fb4d8502Sjsg 	}
862fb4d8502Sjsg 
863fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
864fb4d8502Sjsg 		result = BP_RESULT_OK;
865fb4d8502Sjsg 
866fb4d8502Sjsg 	return result;
867fb4d8502Sjsg }
868fb4d8502Sjsg 
transmitter_control_v1_6(struct bios_parser * bp,struct bp_transmitter_control * cntl)869fb4d8502Sjsg static enum bp_result transmitter_control_v1_6(
870fb4d8502Sjsg 	struct bios_parser *bp,
871fb4d8502Sjsg 	struct bp_transmitter_control *cntl)
872fb4d8502Sjsg {
873fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
874fb4d8502Sjsg 	const struct command_table_helper *cmd = bp->cmd_helper;
875fb4d8502Sjsg 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
876fb4d8502Sjsg 
877fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
878fb4d8502Sjsg 	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
879fb4d8502Sjsg 	params.ucAction = (uint8_t)cntl->action;
880fb4d8502Sjsg 
881fb4d8502Sjsg 	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
882fb4d8502Sjsg 		params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
883fb4d8502Sjsg 	else
884fb4d8502Sjsg 		params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
885fb4d8502Sjsg 
886fb4d8502Sjsg 	params.ucLaneNum = (uint8_t)cntl->lanes_number;
887fb4d8502Sjsg 	params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
888fb4d8502Sjsg 	params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
889fb4d8502Sjsg 	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
890fb4d8502Sjsg 	params.ulSymClock = cntl->pixel_clock/10;
891fb4d8502Sjsg 
892fb4d8502Sjsg 	/*
893fb4d8502Sjsg 	 * In SI/TN case, caller have to set usPixelClock as following:
894fb4d8502Sjsg 	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
895fb4d8502Sjsg 	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
896fb4d8502Sjsg 	 * DVI single link mode: usPixelClock = pixel clock
897fb4d8502Sjsg 	 * DVI dual link mode: usPixelClock = pixel clock
898fb4d8502Sjsg 	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
899fb4d8502Sjsg 	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
900fb4d8502Sjsg 	 * LVDS mode: usPixelClock = pixel clock
901fb4d8502Sjsg 	 */
902fb4d8502Sjsg 	switch (cntl->signal) {
903fb4d8502Sjsg 	case SIGNAL_TYPE_HDMI_TYPE_A:
904fb4d8502Sjsg 		switch (cntl->color_depth) {
905fb4d8502Sjsg 		case COLOR_DEPTH_101010:
906fb4d8502Sjsg 			params.ulSymClock =
907fb4d8502Sjsg 				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
908fb4d8502Sjsg 			break;
909fb4d8502Sjsg 		case COLOR_DEPTH_121212:
910fb4d8502Sjsg 			params.ulSymClock =
911fb4d8502Sjsg 				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
912fb4d8502Sjsg 			break;
913fb4d8502Sjsg 		case COLOR_DEPTH_161616:
914fb4d8502Sjsg 			params.ulSymClock =
915fb4d8502Sjsg 				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
916fb4d8502Sjsg 			break;
917fb4d8502Sjsg 		default:
918fb4d8502Sjsg 			break;
919fb4d8502Sjsg 		}
920fb4d8502Sjsg 		break;
921fb4d8502Sjsg 		default:
922fb4d8502Sjsg 			break;
923fb4d8502Sjsg 	}
924fb4d8502Sjsg 
925fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
926fb4d8502Sjsg 		result = BP_RESULT_OK;
927fb4d8502Sjsg 	return result;
928fb4d8502Sjsg }
929fb4d8502Sjsg 
930fb4d8502Sjsg /*******************************************************************************
931fb4d8502Sjsg  ********************************************************************************
932fb4d8502Sjsg  **
933fb4d8502Sjsg  **                  SET PIXEL CLOCK
934fb4d8502Sjsg  **
935fb4d8502Sjsg  ********************************************************************************
936fb4d8502Sjsg  *******************************************************************************/
937fb4d8502Sjsg 
938fb4d8502Sjsg static enum bp_result set_pixel_clock_v3(
939fb4d8502Sjsg 	struct bios_parser *bp,
940fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params);
941fb4d8502Sjsg static enum bp_result set_pixel_clock_v5(
942fb4d8502Sjsg 	struct bios_parser *bp,
943fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params);
944fb4d8502Sjsg static enum bp_result set_pixel_clock_v6(
945fb4d8502Sjsg 	struct bios_parser *bp,
946fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params);
947fb4d8502Sjsg static enum bp_result set_pixel_clock_v7(
948fb4d8502Sjsg 	struct bios_parser *bp,
949fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params);
950fb4d8502Sjsg 
init_set_pixel_clock(struct bios_parser * bp)951fb4d8502Sjsg static void init_set_pixel_clock(struct bios_parser *bp)
952fb4d8502Sjsg {
953fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
954fb4d8502Sjsg 	case 3:
955fb4d8502Sjsg 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
956fb4d8502Sjsg 		break;
957fb4d8502Sjsg 	case 5:
958fb4d8502Sjsg 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
959fb4d8502Sjsg 		break;
960fb4d8502Sjsg 	case 6:
961fb4d8502Sjsg 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
962fb4d8502Sjsg 		break;
963fb4d8502Sjsg 	case 7:
964fb4d8502Sjsg 		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
965fb4d8502Sjsg 		break;
966fb4d8502Sjsg 	default:
967fb4d8502Sjsg 		dm_output_to_console("Don't have set_pixel_clock for v%d\n",
968fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
969fb4d8502Sjsg 		bp->cmd_tbl.set_pixel_clock = NULL;
970fb4d8502Sjsg 		break;
971fb4d8502Sjsg 	}
972fb4d8502Sjsg }
973fb4d8502Sjsg 
set_pixel_clock_v3(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)974fb4d8502Sjsg static enum bp_result set_pixel_clock_v3(
975fb4d8502Sjsg 	struct bios_parser *bp,
976fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
977fb4d8502Sjsg {
978fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
979fb4d8502Sjsg 	PIXEL_CLOCK_PARAMETERS_V3 *params;
980fb4d8502Sjsg 	SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
981fb4d8502Sjsg 
982fb4d8502Sjsg 	memset(&allocation, 0, sizeof(allocation));
983fb4d8502Sjsg 
984fb4d8502Sjsg 	if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
985fb4d8502Sjsg 		allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
986fb4d8502Sjsg 	else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
987fb4d8502Sjsg 		allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
988fb4d8502Sjsg 	else
989fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
990fb4d8502Sjsg 
991fb4d8502Sjsg 	allocation.sPCLKInput.usRefDiv =
992fb4d8502Sjsg 			cpu_to_le16((uint16_t)bp_params->reference_divider);
993fb4d8502Sjsg 	allocation.sPCLKInput.usFbDiv =
994fb4d8502Sjsg 			cpu_to_le16((uint16_t)bp_params->feedback_divider);
995fb4d8502Sjsg 	allocation.sPCLKInput.ucFracFbDiv =
996fb4d8502Sjsg 			(uint8_t)bp_params->fractional_feedback_divider;
997fb4d8502Sjsg 	allocation.sPCLKInput.ucPostDiv =
998fb4d8502Sjsg 			(uint8_t)bp_params->pixel_clock_post_divider;
999fb4d8502Sjsg 
1000c349dbc7Sjsg 	/* We need to convert from 100Hz units into 10KHz units */
1001fb4d8502Sjsg 	allocation.sPCLKInput.usPixelClock =
1002c349dbc7Sjsg 			cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1003fb4d8502Sjsg 
1004fb4d8502Sjsg 	params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
1005fb4d8502Sjsg 	params->ucTransmitterId =
1006fb4d8502Sjsg 			bp->cmd_helper->encoder_id_to_atom(
1007fb4d8502Sjsg 					dal_graphics_object_id_get_encoder_id(
1008fb4d8502Sjsg 							bp_params->encoder_object_id));
1009fb4d8502Sjsg 	params->ucEncoderMode =
1010fb4d8502Sjsg 			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
1011fb4d8502Sjsg 					bp_params->signal_type, false));
1012fb4d8502Sjsg 
1013fb4d8502Sjsg 	if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1014fb4d8502Sjsg 		params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1015fb4d8502Sjsg 
1016fb4d8502Sjsg 	if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
1017fb4d8502Sjsg 		params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
1018fb4d8502Sjsg 
1019fb4d8502Sjsg 	if (CONTROLLER_ID_D1 != bp_params->controller_id)
1020fb4d8502Sjsg 		params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
1021fb4d8502Sjsg 
1022fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
1023fb4d8502Sjsg 		result = BP_RESULT_OK;
1024fb4d8502Sjsg 
1025fb4d8502Sjsg 	return result;
1026fb4d8502Sjsg }
1027fb4d8502Sjsg 
1028fb4d8502Sjsg #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
1029fb4d8502Sjsg /* video bios did not define this: */
1030fb4d8502Sjsg typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
1031fb4d8502Sjsg 	PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
1032fb4d8502Sjsg 	/* Caller doesn't need to init this portion */
1033fb4d8502Sjsg 	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1034fb4d8502Sjsg } SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
1035fb4d8502Sjsg #endif
1036fb4d8502Sjsg 
1037fb4d8502Sjsg #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
1038fb4d8502Sjsg /* video bios did not define this: */
1039fb4d8502Sjsg typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
1040fb4d8502Sjsg 	PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
1041fb4d8502Sjsg 	/* Caller doesn't need to init this portion */
1042fb4d8502Sjsg 	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1043fb4d8502Sjsg } SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
1044fb4d8502Sjsg #endif
1045fb4d8502Sjsg 
set_pixel_clock_v5(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)1046fb4d8502Sjsg static enum bp_result set_pixel_clock_v5(
1047fb4d8502Sjsg 	struct bios_parser *bp,
1048fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
1049fb4d8502Sjsg {
1050fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1051fb4d8502Sjsg 	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
1052fb4d8502Sjsg 	uint8_t controller_id;
1053fb4d8502Sjsg 	uint32_t pll_id;
1054fb4d8502Sjsg 
1055fb4d8502Sjsg 	memset(&clk, 0, sizeof(clk));
1056fb4d8502Sjsg 
1057fb4d8502Sjsg 	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1058fb4d8502Sjsg 			&& bp->cmd_helper->controller_id_to_atom(
1059fb4d8502Sjsg 					bp_params->controller_id, &controller_id)) {
1060fb4d8502Sjsg 		clk.sPCLKInput.ucCRTC = controller_id;
1061fb4d8502Sjsg 		clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1062fb4d8502Sjsg 		clk.sPCLKInput.ucRefDiv =
1063fb4d8502Sjsg 				(uint8_t)(bp_params->reference_divider);
1064fb4d8502Sjsg 		clk.sPCLKInput.usFbDiv =
1065fb4d8502Sjsg 				cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1066fb4d8502Sjsg 		clk.sPCLKInput.ulFbDivDecFrac =
1067fb4d8502Sjsg 				cpu_to_le32(bp_params->fractional_feedback_divider);
1068fb4d8502Sjsg 		clk.sPCLKInput.ucPostDiv =
1069fb4d8502Sjsg 				(uint8_t)(bp_params->pixel_clock_post_divider);
1070fb4d8502Sjsg 		clk.sPCLKInput.ucTransmitterID =
1071fb4d8502Sjsg 				bp->cmd_helper->encoder_id_to_atom(
1072fb4d8502Sjsg 						dal_graphics_object_id_get_encoder_id(
1073fb4d8502Sjsg 								bp_params->encoder_object_id));
1074fb4d8502Sjsg 		clk.sPCLKInput.ucEncoderMode =
1075fb4d8502Sjsg 				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1076fb4d8502Sjsg 						bp_params->signal_type, false);
1077fb4d8502Sjsg 
1078c349dbc7Sjsg 		/* We need to convert from 100Hz units into 10KHz units */
1079fb4d8502Sjsg 		clk.sPCLKInput.usPixelClock =
1080c349dbc7Sjsg 				cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1081fb4d8502Sjsg 
1082fb4d8502Sjsg 		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1083fb4d8502Sjsg 			clk.sPCLKInput.ucMiscInfo |=
1084fb4d8502Sjsg 					PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1085fb4d8502Sjsg 
1086fb4d8502Sjsg 		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1087fb4d8502Sjsg 			clk.sPCLKInput.ucMiscInfo |=
1088fb4d8502Sjsg 					PIXEL_CLOCK_MISC_REF_DIV_SRC;
1089fb4d8502Sjsg 
1090fb4d8502Sjsg 		/* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1091fb4d8502Sjsg 		 * =1:30bpp, =2:32bpp
1092fb4d8502Sjsg 		 * driver choose program it itself, i.e. here we program it
1093fb4d8502Sjsg 		 * to 888 by default.
1094fb4d8502Sjsg 		 */
1095ad8b1aafSjsg 		if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1096ad8b1aafSjsg 			switch (bp_params->color_depth) {
1097ad8b1aafSjsg 			case TRANSMITTER_COLOR_DEPTH_30:
1098ad8b1aafSjsg 				/* yes this is correct, the atom define is wrong */
1099ad8b1aafSjsg 				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
1100ad8b1aafSjsg 				break;
1101ad8b1aafSjsg 			case TRANSMITTER_COLOR_DEPTH_36:
1102ad8b1aafSjsg 				/* yes this is correct, the atom define is wrong */
1103ad8b1aafSjsg 				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
1104ad8b1aafSjsg 				break;
1105ad8b1aafSjsg 			default:
1106ad8b1aafSjsg 				break;
1107ad8b1aafSjsg 			}
1108fb4d8502Sjsg 
1109fb4d8502Sjsg 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1110fb4d8502Sjsg 			result = BP_RESULT_OK;
1111fb4d8502Sjsg 	}
1112fb4d8502Sjsg 
1113fb4d8502Sjsg 	return result;
1114fb4d8502Sjsg }
1115fb4d8502Sjsg 
set_pixel_clock_v6(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)1116fb4d8502Sjsg static enum bp_result set_pixel_clock_v6(
1117fb4d8502Sjsg 	struct bios_parser *bp,
1118fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
1119fb4d8502Sjsg {
1120fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1121fb4d8502Sjsg 	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1122fb4d8502Sjsg 	uint8_t controller_id;
1123fb4d8502Sjsg 	uint32_t pll_id;
1124fb4d8502Sjsg 
1125fb4d8502Sjsg 	memset(&clk, 0, sizeof(clk));
1126fb4d8502Sjsg 
1127fb4d8502Sjsg 	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1128fb4d8502Sjsg 			&& bp->cmd_helper->controller_id_to_atom(
1129fb4d8502Sjsg 					bp_params->controller_id, &controller_id)) {
1130fb4d8502Sjsg 		/* Note: VBIOS still wants to use ucCRTC name which is now
1131fb4d8502Sjsg 		 * 1 byte in ULONG
1132fb4d8502Sjsg 		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1133fb4d8502Sjsg 		 *{
1134fb4d8502Sjsg 		 * target the pixel clock to drive the CRTC timing.
1135fb4d8502Sjsg 		 * ULONG ulPixelClock:24;
1136fb4d8502Sjsg 		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1137fb4d8502Sjsg 		 * previous version.
1138fb4d8502Sjsg 		 * ATOM_CRTC1~6, indicate the CRTC controller to
1139fb4d8502Sjsg 		 * ULONG ucCRTC:8;
1140fb4d8502Sjsg 		 * drive the pixel clock. not used for DCPLL case.
1141fb4d8502Sjsg 		 *}CRTC_PIXEL_CLOCK_FREQ;
1142fb4d8502Sjsg 		 *union
1143fb4d8502Sjsg 		 *{
1144fb4d8502Sjsg 		 * pixel clock and CRTC id frequency
1145fb4d8502Sjsg 		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1146fb4d8502Sjsg 		 * ULONG ulDispEngClkFreq; dispclk frequency
1147fb4d8502Sjsg 		 *};
1148fb4d8502Sjsg 		 */
1149fb4d8502Sjsg 		clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1150fb4d8502Sjsg 		clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1151fb4d8502Sjsg 		clk.sPCLKInput.ucRefDiv =
1152fb4d8502Sjsg 				(uint8_t) bp_params->reference_divider;
1153fb4d8502Sjsg 		clk.sPCLKInput.usFbDiv =
1154fb4d8502Sjsg 				cpu_to_le16((uint16_t) bp_params->feedback_divider);
1155fb4d8502Sjsg 		clk.sPCLKInput.ulFbDivDecFrac =
1156fb4d8502Sjsg 				cpu_to_le32(bp_params->fractional_feedback_divider);
1157fb4d8502Sjsg 		clk.sPCLKInput.ucPostDiv =
1158fb4d8502Sjsg 				(uint8_t) bp_params->pixel_clock_post_divider;
1159fb4d8502Sjsg 		clk.sPCLKInput.ucTransmitterID =
1160fb4d8502Sjsg 				bp->cmd_helper->encoder_id_to_atom(
1161fb4d8502Sjsg 						dal_graphics_object_id_get_encoder_id(
1162fb4d8502Sjsg 								bp_params->encoder_object_id));
1163fb4d8502Sjsg 		clk.sPCLKInput.ucEncoderMode =
1164fb4d8502Sjsg 				(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1165fb4d8502Sjsg 						bp_params->signal_type, false);
1166fb4d8502Sjsg 
1167c349dbc7Sjsg 		/* We need to convert from 100 Hz units into 10KHz units */
1168fb4d8502Sjsg 		clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1169c349dbc7Sjsg 				cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
1170fb4d8502Sjsg 
1171fb4d8502Sjsg 		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1172fb4d8502Sjsg 			clk.sPCLKInput.ucMiscInfo |=
1173fb4d8502Sjsg 					PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1174fb4d8502Sjsg 		}
1175fb4d8502Sjsg 
1176fb4d8502Sjsg 		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1177fb4d8502Sjsg 			clk.sPCLKInput.ucMiscInfo |=
1178fb4d8502Sjsg 					PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1179fb4d8502Sjsg 		}
1180fb4d8502Sjsg 
1181fb4d8502Sjsg 		/* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1182fb4d8502Sjsg 		 * 24bpp =1:30bpp, =2:32bpp
1183fb4d8502Sjsg 		 * driver choose program it itself, i.e. here we pass required
1184fb4d8502Sjsg 		 * target rate that includes deep color.
1185fb4d8502Sjsg 		 */
1186ad8b1aafSjsg 		if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1187ad8b1aafSjsg 			switch (bp_params->color_depth) {
1188ad8b1aafSjsg 			case TRANSMITTER_COLOR_DEPTH_30:
1189ad8b1aafSjsg 				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
1190ad8b1aafSjsg 				break;
1191ad8b1aafSjsg 			case TRANSMITTER_COLOR_DEPTH_36:
1192ad8b1aafSjsg 				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
1193ad8b1aafSjsg 				break;
1194ad8b1aafSjsg 			case TRANSMITTER_COLOR_DEPTH_48:
1195ad8b1aafSjsg 				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
1196ad8b1aafSjsg 				break;
1197ad8b1aafSjsg 			default:
1198ad8b1aafSjsg 				break;
1199ad8b1aafSjsg 			}
1200fb4d8502Sjsg 
1201fb4d8502Sjsg 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1202fb4d8502Sjsg 			result = BP_RESULT_OK;
1203fb4d8502Sjsg 	}
1204fb4d8502Sjsg 
1205fb4d8502Sjsg 	return result;
1206fb4d8502Sjsg }
1207fb4d8502Sjsg 
set_pixel_clock_v7(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)1208fb4d8502Sjsg static enum bp_result set_pixel_clock_v7(
1209fb4d8502Sjsg 	struct bios_parser *bp,
1210fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
1211fb4d8502Sjsg {
1212fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1213fb4d8502Sjsg 	PIXEL_CLOCK_PARAMETERS_V7 clk;
1214fb4d8502Sjsg 	uint8_t controller_id;
1215fb4d8502Sjsg 	uint32_t pll_id;
1216fb4d8502Sjsg 
1217fb4d8502Sjsg 	memset(&clk, 0, sizeof(clk));
1218fb4d8502Sjsg 
1219fb4d8502Sjsg 	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1220fb4d8502Sjsg 			&& bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1221fb4d8502Sjsg 		/* Note: VBIOS still wants to use ucCRTC name which is now
1222fb4d8502Sjsg 		 * 1 byte in ULONG
1223fb4d8502Sjsg 		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1224fb4d8502Sjsg 		 *{
1225fb4d8502Sjsg 		 * target the pixel clock to drive the CRTC timing.
1226fb4d8502Sjsg 		 * ULONG ulPixelClock:24;
1227fb4d8502Sjsg 		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1228fb4d8502Sjsg 		 * previous version.
1229fb4d8502Sjsg 		 * ATOM_CRTC1~6, indicate the CRTC controller to
1230fb4d8502Sjsg 		 * ULONG ucCRTC:8;
1231fb4d8502Sjsg 		 * drive the pixel clock. not used for DCPLL case.
1232fb4d8502Sjsg 		 *}CRTC_PIXEL_CLOCK_FREQ;
1233fb4d8502Sjsg 		 *union
1234fb4d8502Sjsg 		 *{
1235fb4d8502Sjsg 		 * pixel clock and CRTC id frequency
1236fb4d8502Sjsg 		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1237fb4d8502Sjsg 		 * ULONG ulDispEngClkFreq; dispclk frequency
1238fb4d8502Sjsg 		 *};
1239fb4d8502Sjsg 		 */
1240fb4d8502Sjsg 		clk.ucCRTC = controller_id;
1241fb4d8502Sjsg 		clk.ucPpll = (uint8_t) pll_id;
1242fb4d8502Sjsg 		clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1243fb4d8502Sjsg 		clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1244fb4d8502Sjsg 
1245c349dbc7Sjsg 		clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
1246fb4d8502Sjsg 
1247fb4d8502Sjsg 		clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1248fb4d8502Sjsg 
1249fb4d8502Sjsg 		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1250fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1251fb4d8502Sjsg 
1252fb4d8502Sjsg 		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1253fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1254fb4d8502Sjsg 
1255fb4d8502Sjsg 		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1256fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1257fb4d8502Sjsg 
1258fb4d8502Sjsg 		if (bp_params->flags.SUPPORT_YUV_420)
1259fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1260fb4d8502Sjsg 
1261fb4d8502Sjsg 		if (bp_params->flags.SET_XTALIN_REF_SRC)
1262fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1263fb4d8502Sjsg 
1264fb4d8502Sjsg 		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1265fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1266fb4d8502Sjsg 
1267fb4d8502Sjsg 		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1268fb4d8502Sjsg 			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1269fb4d8502Sjsg 
1270fb4d8502Sjsg 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1271fb4d8502Sjsg 			result = BP_RESULT_OK;
1272fb4d8502Sjsg 	}
1273fb4d8502Sjsg 	return result;
1274fb4d8502Sjsg }
1275fb4d8502Sjsg 
1276fb4d8502Sjsg /*******************************************************************************
1277fb4d8502Sjsg  ********************************************************************************
1278fb4d8502Sjsg  **
1279fb4d8502Sjsg  **                  ENABLE PIXEL CLOCK SS
1280fb4d8502Sjsg  **
1281fb4d8502Sjsg  ********************************************************************************
1282fb4d8502Sjsg  *******************************************************************************/
1283fb4d8502Sjsg static enum bp_result enable_spread_spectrum_on_ppll_v1(
1284fb4d8502Sjsg 	struct bios_parser *bp,
1285fb4d8502Sjsg 	struct bp_spread_spectrum_parameters *bp_params,
1286fb4d8502Sjsg 	bool enable);
1287fb4d8502Sjsg static enum bp_result enable_spread_spectrum_on_ppll_v2(
1288fb4d8502Sjsg 	struct bios_parser *bp,
1289fb4d8502Sjsg 	struct bp_spread_spectrum_parameters *bp_params,
1290fb4d8502Sjsg 	bool enable);
1291fb4d8502Sjsg static enum bp_result enable_spread_spectrum_on_ppll_v3(
1292fb4d8502Sjsg 	struct bios_parser *bp,
1293fb4d8502Sjsg 	struct bp_spread_spectrum_parameters *bp_params,
1294fb4d8502Sjsg 	bool enable);
1295fb4d8502Sjsg 
init_enable_spread_spectrum_on_ppll(struct bios_parser * bp)1296fb4d8502Sjsg static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1297fb4d8502Sjsg {
1298fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1299fb4d8502Sjsg 	case 1:
1300fb4d8502Sjsg 		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1301fb4d8502Sjsg 				enable_spread_spectrum_on_ppll_v1;
1302fb4d8502Sjsg 		break;
1303fb4d8502Sjsg 	case 2:
1304fb4d8502Sjsg 		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1305fb4d8502Sjsg 				enable_spread_spectrum_on_ppll_v2;
1306fb4d8502Sjsg 		break;
1307fb4d8502Sjsg 	case 3:
1308fb4d8502Sjsg 		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1309fb4d8502Sjsg 				enable_spread_spectrum_on_ppll_v3;
1310fb4d8502Sjsg 		break;
1311fb4d8502Sjsg 	default:
1312fb4d8502Sjsg 		dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1313fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1314fb4d8502Sjsg 		bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1315fb4d8502Sjsg 		break;
1316fb4d8502Sjsg 	}
1317fb4d8502Sjsg }
1318fb4d8502Sjsg 
enable_spread_spectrum_on_ppll_v1(struct bios_parser * bp,struct bp_spread_spectrum_parameters * bp_params,bool enable)1319fb4d8502Sjsg static enum bp_result enable_spread_spectrum_on_ppll_v1(
1320fb4d8502Sjsg 	struct bios_parser *bp,
1321fb4d8502Sjsg 	struct bp_spread_spectrum_parameters *bp_params,
1322fb4d8502Sjsg 	bool enable)
1323fb4d8502Sjsg {
1324fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1325fb4d8502Sjsg 	ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1326fb4d8502Sjsg 
1327fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
1328fb4d8502Sjsg 
1329fb4d8502Sjsg 	if ((enable == true) && (bp_params->percentage > 0))
1330fb4d8502Sjsg 		params.ucEnable = ATOM_ENABLE;
1331fb4d8502Sjsg 	else
1332fb4d8502Sjsg 		params.ucEnable = ATOM_DISABLE;
1333fb4d8502Sjsg 
1334fb4d8502Sjsg 	params.usSpreadSpectrumPercentage =
1335fb4d8502Sjsg 			cpu_to_le16((uint16_t)bp_params->percentage);
1336fb4d8502Sjsg 	params.ucSpreadSpectrumStep =
1337fb4d8502Sjsg 			(uint8_t)bp_params->ver1.step;
1338fb4d8502Sjsg 	params.ucSpreadSpectrumDelay =
1339fb4d8502Sjsg 			(uint8_t)bp_params->ver1.delay;
1340fb4d8502Sjsg 	/* convert back to unit of 10KHz */
1341fb4d8502Sjsg 	params.ucSpreadSpectrumRange =
1342fb4d8502Sjsg 			(uint8_t)(bp_params->ver1.range / 10000);
1343fb4d8502Sjsg 
1344fb4d8502Sjsg 	if (bp_params->flags.EXTERNAL_SS)
1345fb4d8502Sjsg 		params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1346fb4d8502Sjsg 
1347fb4d8502Sjsg 	if (bp_params->flags.CENTER_SPREAD)
1348fb4d8502Sjsg 		params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1349fb4d8502Sjsg 
1350fb4d8502Sjsg 	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1351fb4d8502Sjsg 		params.ucPpll = ATOM_PPLL1;
1352fb4d8502Sjsg 	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1353fb4d8502Sjsg 		params.ucPpll = ATOM_PPLL2;
1354fb4d8502Sjsg 	else
1355fb4d8502Sjsg 		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1356fb4d8502Sjsg 
1357fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1358fb4d8502Sjsg 		result = BP_RESULT_OK;
1359fb4d8502Sjsg 
1360fb4d8502Sjsg 	return result;
1361fb4d8502Sjsg }
1362fb4d8502Sjsg 
enable_spread_spectrum_on_ppll_v2(struct bios_parser * bp,struct bp_spread_spectrum_parameters * bp_params,bool enable)1363fb4d8502Sjsg static enum bp_result enable_spread_spectrum_on_ppll_v2(
1364fb4d8502Sjsg 	struct bios_parser *bp,
1365fb4d8502Sjsg 	struct bp_spread_spectrum_parameters *bp_params,
1366fb4d8502Sjsg 	bool enable)
1367fb4d8502Sjsg {
1368fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1369fb4d8502Sjsg 	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1370fb4d8502Sjsg 
1371fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
1372fb4d8502Sjsg 
1373fb4d8502Sjsg 	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1374fb4d8502Sjsg 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1375fb4d8502Sjsg 	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1376fb4d8502Sjsg 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1377fb4d8502Sjsg 	else
1378fb4d8502Sjsg 		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1379fb4d8502Sjsg 
1380fb4d8502Sjsg 	if ((enable == true) && (bp_params->percentage > 0)) {
1381fb4d8502Sjsg 		params.ucEnable = ATOM_ENABLE;
1382fb4d8502Sjsg 
1383fb4d8502Sjsg 		params.usSpreadSpectrumPercentage =
1384fb4d8502Sjsg 				cpu_to_le16((uint16_t)(bp_params->percentage));
1385fb4d8502Sjsg 		params.usSpreadSpectrumStep =
1386fb4d8502Sjsg 				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1387fb4d8502Sjsg 
1388fb4d8502Sjsg 		if (bp_params->flags.EXTERNAL_SS)
1389fb4d8502Sjsg 			params.ucSpreadSpectrumType |=
1390fb4d8502Sjsg 					ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1391fb4d8502Sjsg 
1392fb4d8502Sjsg 		if (bp_params->flags.CENTER_SPREAD)
1393fb4d8502Sjsg 			params.ucSpreadSpectrumType |=
1394fb4d8502Sjsg 					ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1395fb4d8502Sjsg 
1396fb4d8502Sjsg 		/* Both amounts need to be left shifted first before bit
1397fb4d8502Sjsg 		 * comparison. Otherwise, the result will always be zero here
1398fb4d8502Sjsg 		 */
1399fb4d8502Sjsg 		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1400fb4d8502Sjsg 				((bp_params->ds.feedback_amount <<
1401fb4d8502Sjsg 						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1402fb4d8502Sjsg 						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1403fb4d8502Sjsg 						((bp_params->ds.nfrac_amount <<
1404fb4d8502Sjsg 								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1405fb4d8502Sjsg 								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1406fb4d8502Sjsg 	} else
1407fb4d8502Sjsg 		params.ucEnable = ATOM_DISABLE;
1408fb4d8502Sjsg 
1409fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1410fb4d8502Sjsg 		result = BP_RESULT_OK;
1411fb4d8502Sjsg 
1412fb4d8502Sjsg 	return result;
1413fb4d8502Sjsg }
1414fb4d8502Sjsg 
enable_spread_spectrum_on_ppll_v3(struct bios_parser * bp,struct bp_spread_spectrum_parameters * bp_params,bool enable)1415fb4d8502Sjsg static enum bp_result enable_spread_spectrum_on_ppll_v3(
1416fb4d8502Sjsg 	struct bios_parser *bp,
1417fb4d8502Sjsg 	struct bp_spread_spectrum_parameters *bp_params,
1418fb4d8502Sjsg 	bool enable)
1419fb4d8502Sjsg {
1420fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1421fb4d8502Sjsg 	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1422fb4d8502Sjsg 
1423fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
1424fb4d8502Sjsg 
1425fb4d8502Sjsg 	switch (bp_params->pll_id) {
1426fb4d8502Sjsg 	case CLOCK_SOURCE_ID_PLL0:
1427fb4d8502Sjsg 		/* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1428fb4d8502Sjsg 		 * not for SI display clock.
1429fb4d8502Sjsg 		 */
1430fb4d8502Sjsg 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1431fb4d8502Sjsg 		break;
1432fb4d8502Sjsg 	case CLOCK_SOURCE_ID_PLL1:
1433fb4d8502Sjsg 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1434fb4d8502Sjsg 		break;
1435fb4d8502Sjsg 
1436fb4d8502Sjsg 	case CLOCK_SOURCE_ID_PLL2:
1437fb4d8502Sjsg 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1438fb4d8502Sjsg 		break;
1439fb4d8502Sjsg 
1440fb4d8502Sjsg 	case CLOCK_SOURCE_ID_DCPLL:
1441fb4d8502Sjsg 		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1442fb4d8502Sjsg 		break;
1443fb4d8502Sjsg 
1444fb4d8502Sjsg 	default:
1445fb4d8502Sjsg 		BREAK_TO_DEBUGGER();
1446fb4d8502Sjsg 		/* Unexpected PLL value!! */
1447fb4d8502Sjsg 		return result;
1448fb4d8502Sjsg 	}
1449fb4d8502Sjsg 
1450fb4d8502Sjsg 	if (enable == true) {
1451fb4d8502Sjsg 		params.ucEnable = ATOM_ENABLE;
1452fb4d8502Sjsg 
1453fb4d8502Sjsg 		params.usSpreadSpectrumAmountFrac =
1454fb4d8502Sjsg 				cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1455fb4d8502Sjsg 		params.usSpreadSpectrumStep =
1456fb4d8502Sjsg 				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1457fb4d8502Sjsg 
1458fb4d8502Sjsg 		if (bp_params->flags.EXTERNAL_SS)
1459fb4d8502Sjsg 			params.ucSpreadSpectrumType |=
1460fb4d8502Sjsg 					ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1461fb4d8502Sjsg 		if (bp_params->flags.CENTER_SPREAD)
1462fb4d8502Sjsg 			params.ucSpreadSpectrumType |=
1463fb4d8502Sjsg 					ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1464fb4d8502Sjsg 
1465fb4d8502Sjsg 		/* Both amounts need to be left shifted first before bit
1466fb4d8502Sjsg 		 * comparison. Otherwise, the result will always be zero here
1467fb4d8502Sjsg 		 */
1468fb4d8502Sjsg 		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1469fb4d8502Sjsg 				((bp_params->ds.feedback_amount <<
1470fb4d8502Sjsg 						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1471fb4d8502Sjsg 						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1472fb4d8502Sjsg 						((bp_params->ds.nfrac_amount <<
1473fb4d8502Sjsg 								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1474fb4d8502Sjsg 								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1475fb4d8502Sjsg 	} else
1476fb4d8502Sjsg 		params.ucEnable = ATOM_DISABLE;
1477fb4d8502Sjsg 
1478fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1479fb4d8502Sjsg 		result = BP_RESULT_OK;
1480fb4d8502Sjsg 
1481fb4d8502Sjsg 	return result;
1482fb4d8502Sjsg }
1483fb4d8502Sjsg 
1484fb4d8502Sjsg /*******************************************************************************
1485fb4d8502Sjsg  ********************************************************************************
1486fb4d8502Sjsg  **
1487fb4d8502Sjsg  **                  ADJUST DISPLAY PLL
1488fb4d8502Sjsg  **
1489fb4d8502Sjsg  ********************************************************************************
1490fb4d8502Sjsg  *******************************************************************************/
1491fb4d8502Sjsg 
1492fb4d8502Sjsg static enum bp_result adjust_display_pll_v2(
1493fb4d8502Sjsg 	struct bios_parser *bp,
1494fb4d8502Sjsg 	struct bp_adjust_pixel_clock_parameters *bp_params);
1495fb4d8502Sjsg static enum bp_result adjust_display_pll_v3(
1496fb4d8502Sjsg 	struct bios_parser *bp,
1497fb4d8502Sjsg 	struct bp_adjust_pixel_clock_parameters *bp_params);
1498fb4d8502Sjsg 
init_adjust_display_pll(struct bios_parser * bp)1499fb4d8502Sjsg static void init_adjust_display_pll(struct bios_parser *bp)
1500fb4d8502Sjsg {
1501fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1502fb4d8502Sjsg 	case 2:
1503fb4d8502Sjsg 		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1504fb4d8502Sjsg 		break;
1505fb4d8502Sjsg 	case 3:
1506fb4d8502Sjsg 		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1507fb4d8502Sjsg 		break;
1508fb4d8502Sjsg 	default:
1509fb4d8502Sjsg 		dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1510fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1511fb4d8502Sjsg 		bp->cmd_tbl.adjust_display_pll = NULL;
1512fb4d8502Sjsg 		break;
1513fb4d8502Sjsg 	}
1514fb4d8502Sjsg }
1515fb4d8502Sjsg 
adjust_display_pll_v2(struct bios_parser * bp,struct bp_adjust_pixel_clock_parameters * bp_params)1516fb4d8502Sjsg static enum bp_result adjust_display_pll_v2(
1517fb4d8502Sjsg 	struct bios_parser *bp,
1518fb4d8502Sjsg 	struct bp_adjust_pixel_clock_parameters *bp_params)
1519fb4d8502Sjsg {
1520fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1521fb4d8502Sjsg 	ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1522fb4d8502Sjsg 
1523fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units and then convert
1524fb4d8502Sjsg 	 * output pixel clock back 10KHz-->KHz */
1525fb4d8502Sjsg 	uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1526fb4d8502Sjsg 
1527fb4d8502Sjsg 	params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1528fb4d8502Sjsg 	params.ucTransmitterID =
1529fb4d8502Sjsg 			bp->cmd_helper->encoder_id_to_atom(
1530fb4d8502Sjsg 					dal_graphics_object_id_get_encoder_id(
1531fb4d8502Sjsg 							bp_params->encoder_object_id));
1532fb4d8502Sjsg 	params.ucEncodeMode =
1533fb4d8502Sjsg 			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1534fb4d8502Sjsg 					bp_params->signal_type, false);
15355ca02815Sjsg 
15365ca02815Sjsg 	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
15375ca02815Sjsg 		/* Convert output pixel clock back 10KHz-->KHz: multiply
15385ca02815Sjsg 		 * original pixel clock in KHz by ratio
15395ca02815Sjsg 		 * [output pxlClk/input pxlClk] */
15405ca02815Sjsg 		uint64_t pixel_clk_10_khz_out =
15415ca02815Sjsg 				(uint64_t)le16_to_cpu(params.usPixelClock);
15425ca02815Sjsg 		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
15435ca02815Sjsg 
15445ca02815Sjsg 		if (pixel_clock_10KHz_in != 0) {
15455ca02815Sjsg 			bp_params->adjusted_pixel_clock =
15465ca02815Sjsg 					div_u64(pixel_clk * pixel_clk_10_khz_out,
15475ca02815Sjsg 							pixel_clock_10KHz_in);
15485ca02815Sjsg 		} else {
15495ca02815Sjsg 			bp_params->adjusted_pixel_clock = 0;
15505ca02815Sjsg 			BREAK_TO_DEBUGGER();
15515ca02815Sjsg 		}
15525ca02815Sjsg 
15535ca02815Sjsg 		result = BP_RESULT_OK;
15545ca02815Sjsg 	}
15555ca02815Sjsg 
1556fb4d8502Sjsg 	return result;
1557fb4d8502Sjsg }
1558fb4d8502Sjsg 
adjust_display_pll_v3(struct bios_parser * bp,struct bp_adjust_pixel_clock_parameters * bp_params)1559fb4d8502Sjsg static enum bp_result adjust_display_pll_v3(
1560fb4d8502Sjsg 	struct bios_parser *bp,
1561fb4d8502Sjsg 	struct bp_adjust_pixel_clock_parameters *bp_params)
1562fb4d8502Sjsg {
1563fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1564fb4d8502Sjsg 	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1565fb4d8502Sjsg 	uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1566fb4d8502Sjsg 
1567fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
1568fb4d8502Sjsg 
1569fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units and then convert
1570fb4d8502Sjsg 	 * output pixel clock back 10KHz-->KHz */
1571fb4d8502Sjsg 	params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1572fb4d8502Sjsg 	params.sInput.ucTransmitterID =
1573fb4d8502Sjsg 			bp->cmd_helper->encoder_id_to_atom(
1574fb4d8502Sjsg 					dal_graphics_object_id_get_encoder_id(
1575fb4d8502Sjsg 							bp_params->encoder_object_id));
1576fb4d8502Sjsg 	params.sInput.ucEncodeMode =
1577fb4d8502Sjsg 			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1578fb4d8502Sjsg 					bp_params->signal_type, false);
1579fb4d8502Sjsg 
1580fb4d8502Sjsg 	if (bp_params->ss_enable == true)
1581fb4d8502Sjsg 		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1582fb4d8502Sjsg 
1583fb4d8502Sjsg 	if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1584fb4d8502Sjsg 		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1585fb4d8502Sjsg 
1586fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1587fb4d8502Sjsg 		/* Convert output pixel clock back 10KHz-->KHz: multiply
1588fb4d8502Sjsg 		 * original pixel clock in KHz by ratio
1589fb4d8502Sjsg 		 * [output pxlClk/input pxlClk] */
1590fb4d8502Sjsg 		uint64_t pixel_clk_10_khz_out =
1591fb4d8502Sjsg 				(uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1592fb4d8502Sjsg 		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1593fb4d8502Sjsg 
1594fb4d8502Sjsg 		if (pixel_clk_10_kHz_in != 0) {
1595fb4d8502Sjsg 			bp_params->adjusted_pixel_clock =
1596fb4d8502Sjsg 					div_u64(pixel_clk * pixel_clk_10_khz_out,
1597fb4d8502Sjsg 							pixel_clk_10_kHz_in);
1598fb4d8502Sjsg 		} else {
1599fb4d8502Sjsg 			bp_params->adjusted_pixel_clock = 0;
1600fb4d8502Sjsg 			BREAK_TO_DEBUGGER();
1601fb4d8502Sjsg 		}
1602fb4d8502Sjsg 
1603fb4d8502Sjsg 		bp_params->reference_divider = params.sOutput.ucRefDiv;
1604fb4d8502Sjsg 		bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1605fb4d8502Sjsg 
1606fb4d8502Sjsg 		result = BP_RESULT_OK;
1607fb4d8502Sjsg 	}
1608fb4d8502Sjsg 
1609fb4d8502Sjsg 	return result;
1610fb4d8502Sjsg }
1611fb4d8502Sjsg 
1612fb4d8502Sjsg /*******************************************************************************
1613fb4d8502Sjsg  ********************************************************************************
1614fb4d8502Sjsg  **
1615fb4d8502Sjsg  **                  DAC ENCODER CONTROL
1616fb4d8502Sjsg  **
1617fb4d8502Sjsg  ********************************************************************************
1618fb4d8502Sjsg  *******************************************************************************/
1619fb4d8502Sjsg 
1620fb4d8502Sjsg static enum bp_result dac1_encoder_control_v1(
1621fb4d8502Sjsg 	struct bios_parser *bp,
1622fb4d8502Sjsg 	bool enable,
1623fb4d8502Sjsg 	uint32_t pixel_clock,
1624fb4d8502Sjsg 	uint8_t dac_standard);
1625fb4d8502Sjsg static enum bp_result dac2_encoder_control_v1(
1626fb4d8502Sjsg 	struct bios_parser *bp,
1627fb4d8502Sjsg 	bool enable,
1628fb4d8502Sjsg 	uint32_t pixel_clock,
1629fb4d8502Sjsg 	uint8_t dac_standard);
1630fb4d8502Sjsg 
init_dac_encoder_control(struct bios_parser * bp)1631fb4d8502Sjsg static void init_dac_encoder_control(struct bios_parser *bp)
1632fb4d8502Sjsg {
1633fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1634fb4d8502Sjsg 	case 1:
1635fb4d8502Sjsg 		bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1636fb4d8502Sjsg 		break;
1637fb4d8502Sjsg 	default:
1638fb4d8502Sjsg 		bp->cmd_tbl.dac1_encoder_control = NULL;
1639fb4d8502Sjsg 		break;
1640fb4d8502Sjsg 	}
1641fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1642fb4d8502Sjsg 	case 1:
1643fb4d8502Sjsg 		bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1644fb4d8502Sjsg 		break;
1645fb4d8502Sjsg 	default:
1646fb4d8502Sjsg 		bp->cmd_tbl.dac2_encoder_control = NULL;
1647fb4d8502Sjsg 		break;
1648fb4d8502Sjsg 	}
1649fb4d8502Sjsg }
1650fb4d8502Sjsg 
dac_encoder_control_prepare_params(DAC_ENCODER_CONTROL_PS_ALLOCATION * params,bool enable,uint32_t pixel_clock,uint8_t dac_standard)1651fb4d8502Sjsg static void dac_encoder_control_prepare_params(
1652fb4d8502Sjsg 	DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1653fb4d8502Sjsg 	bool enable,
1654fb4d8502Sjsg 	uint32_t pixel_clock,
1655fb4d8502Sjsg 	uint8_t dac_standard)
1656fb4d8502Sjsg {
1657fb4d8502Sjsg 	params->ucDacStandard = dac_standard;
1658fb4d8502Sjsg 	if (enable)
1659fb4d8502Sjsg 		params->ucAction = ATOM_ENABLE;
1660fb4d8502Sjsg 	else
1661fb4d8502Sjsg 		params->ucAction = ATOM_DISABLE;
1662fb4d8502Sjsg 
1663fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units
1664fb4d8502Sjsg 	 * it looks as if the TvControl do not care about pixel clock
1665fb4d8502Sjsg 	 */
1666fb4d8502Sjsg 	params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1667fb4d8502Sjsg }
1668fb4d8502Sjsg 
dac1_encoder_control_v1(struct bios_parser * bp,bool enable,uint32_t pixel_clock,uint8_t dac_standard)1669fb4d8502Sjsg static enum bp_result dac1_encoder_control_v1(
1670fb4d8502Sjsg 	struct bios_parser *bp,
1671fb4d8502Sjsg 	bool enable,
1672fb4d8502Sjsg 	uint32_t pixel_clock,
1673fb4d8502Sjsg 	uint8_t dac_standard)
1674fb4d8502Sjsg {
1675fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1676fb4d8502Sjsg 	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1677fb4d8502Sjsg 
1678fb4d8502Sjsg 	dac_encoder_control_prepare_params(
1679fb4d8502Sjsg 		&params,
1680fb4d8502Sjsg 		enable,
1681fb4d8502Sjsg 		pixel_clock,
1682fb4d8502Sjsg 		dac_standard);
1683fb4d8502Sjsg 
1684fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1685fb4d8502Sjsg 		result = BP_RESULT_OK;
1686fb4d8502Sjsg 
1687fb4d8502Sjsg 	return result;
1688fb4d8502Sjsg }
1689fb4d8502Sjsg 
dac2_encoder_control_v1(struct bios_parser * bp,bool enable,uint32_t pixel_clock,uint8_t dac_standard)1690fb4d8502Sjsg static enum bp_result dac2_encoder_control_v1(
1691fb4d8502Sjsg 	struct bios_parser *bp,
1692fb4d8502Sjsg 	bool enable,
1693fb4d8502Sjsg 	uint32_t pixel_clock,
1694fb4d8502Sjsg 	uint8_t dac_standard)
1695fb4d8502Sjsg {
1696fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1697fb4d8502Sjsg 	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1698fb4d8502Sjsg 
1699fb4d8502Sjsg 	dac_encoder_control_prepare_params(
1700fb4d8502Sjsg 		&params,
1701fb4d8502Sjsg 		enable,
1702fb4d8502Sjsg 		pixel_clock,
1703fb4d8502Sjsg 		dac_standard);
1704fb4d8502Sjsg 
1705fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1706fb4d8502Sjsg 		result = BP_RESULT_OK;
1707fb4d8502Sjsg 
1708fb4d8502Sjsg 	return result;
1709fb4d8502Sjsg }
1710fb4d8502Sjsg 
1711fb4d8502Sjsg /*******************************************************************************
1712fb4d8502Sjsg  ********************************************************************************
1713fb4d8502Sjsg  **
1714fb4d8502Sjsg  **                  DAC OUTPUT CONTROL
1715fb4d8502Sjsg  **
1716fb4d8502Sjsg  ********************************************************************************
1717fb4d8502Sjsg  *******************************************************************************/
1718fb4d8502Sjsg static enum bp_result dac1_output_control_v1(
1719fb4d8502Sjsg 	struct bios_parser *bp,
1720fb4d8502Sjsg 	bool enable);
1721fb4d8502Sjsg static enum bp_result dac2_output_control_v1(
1722fb4d8502Sjsg 	struct bios_parser *bp,
1723fb4d8502Sjsg 	bool enable);
1724fb4d8502Sjsg 
init_dac_output_control(struct bios_parser * bp)1725fb4d8502Sjsg static void init_dac_output_control(struct bios_parser *bp)
1726fb4d8502Sjsg {
1727fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
1728fb4d8502Sjsg 	case 1:
1729fb4d8502Sjsg 		bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
1730fb4d8502Sjsg 		break;
1731fb4d8502Sjsg 	default:
1732fb4d8502Sjsg 		bp->cmd_tbl.dac1_output_control = NULL;
1733fb4d8502Sjsg 		break;
1734fb4d8502Sjsg 	}
1735fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
1736fb4d8502Sjsg 	case 1:
1737fb4d8502Sjsg 		bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
1738fb4d8502Sjsg 		break;
1739fb4d8502Sjsg 	default:
1740fb4d8502Sjsg 		bp->cmd_tbl.dac2_output_control = NULL;
1741fb4d8502Sjsg 		break;
1742fb4d8502Sjsg 	}
1743fb4d8502Sjsg }
1744fb4d8502Sjsg 
dac1_output_control_v1(struct bios_parser * bp,bool enable)1745fb4d8502Sjsg static enum bp_result dac1_output_control_v1(
1746fb4d8502Sjsg 	struct bios_parser *bp, bool enable)
1747fb4d8502Sjsg {
1748fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1749fb4d8502Sjsg 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1750fb4d8502Sjsg 
1751fb4d8502Sjsg 	if (enable)
1752fb4d8502Sjsg 		params.ucAction = ATOM_ENABLE;
1753fb4d8502Sjsg 	else
1754fb4d8502Sjsg 		params.ucAction = ATOM_DISABLE;
1755fb4d8502Sjsg 
1756fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
1757fb4d8502Sjsg 		result = BP_RESULT_OK;
1758fb4d8502Sjsg 
1759fb4d8502Sjsg 	return result;
1760fb4d8502Sjsg }
1761fb4d8502Sjsg 
dac2_output_control_v1(struct bios_parser * bp,bool enable)1762fb4d8502Sjsg static enum bp_result dac2_output_control_v1(
1763fb4d8502Sjsg 	struct bios_parser *bp, bool enable)
1764fb4d8502Sjsg {
1765fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1766fb4d8502Sjsg 	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1767fb4d8502Sjsg 
1768fb4d8502Sjsg 	if (enable)
1769fb4d8502Sjsg 		params.ucAction = ATOM_ENABLE;
1770fb4d8502Sjsg 	else
1771fb4d8502Sjsg 		params.ucAction = ATOM_DISABLE;
1772fb4d8502Sjsg 
1773fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
1774fb4d8502Sjsg 		result = BP_RESULT_OK;
1775fb4d8502Sjsg 
1776fb4d8502Sjsg 	return result;
1777fb4d8502Sjsg }
1778fb4d8502Sjsg 
1779fb4d8502Sjsg /*******************************************************************************
1780fb4d8502Sjsg  ********************************************************************************
1781fb4d8502Sjsg  **
1782fb4d8502Sjsg  **                  SET CRTC TIMING
1783fb4d8502Sjsg  **
1784fb4d8502Sjsg  ********************************************************************************
1785fb4d8502Sjsg  *******************************************************************************/
1786fb4d8502Sjsg 
1787fb4d8502Sjsg static enum bp_result set_crtc_using_dtd_timing_v3(
1788fb4d8502Sjsg 	struct bios_parser *bp,
1789fb4d8502Sjsg 	struct bp_hw_crtc_timing_parameters *bp_params);
1790fb4d8502Sjsg static enum bp_result set_crtc_timing_v1(
1791fb4d8502Sjsg 	struct bios_parser *bp,
1792fb4d8502Sjsg 	struct bp_hw_crtc_timing_parameters *bp_params);
1793fb4d8502Sjsg 
init_set_crtc_timing(struct bios_parser * bp)1794fb4d8502Sjsg static void init_set_crtc_timing(struct bios_parser *bp)
1795fb4d8502Sjsg {
1796fb4d8502Sjsg 	uint32_t dtd_version =
1797fb4d8502Sjsg 			BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
1798fb4d8502Sjsg 	if (dtd_version > 2)
1799fb4d8502Sjsg 		switch (dtd_version) {
1800fb4d8502Sjsg 		case 3:
1801fb4d8502Sjsg 			bp->cmd_tbl.set_crtc_timing =
1802fb4d8502Sjsg 					set_crtc_using_dtd_timing_v3;
1803fb4d8502Sjsg 			break;
1804fb4d8502Sjsg 		default:
1805fb4d8502Sjsg 			dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
1806fb4d8502Sjsg 				 dtd_version);
1807fb4d8502Sjsg 			bp->cmd_tbl.set_crtc_timing = NULL;
1808fb4d8502Sjsg 			break;
1809fb4d8502Sjsg 		}
1810fb4d8502Sjsg 	else
1811fb4d8502Sjsg 		switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
1812fb4d8502Sjsg 		case 1:
1813fb4d8502Sjsg 			bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
1814fb4d8502Sjsg 			break;
1815fb4d8502Sjsg 		default:
1816fb4d8502Sjsg 			dm_output_to_console("Don't have set_crtc_timing for v%d\n",
1817fb4d8502Sjsg 				 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
1818fb4d8502Sjsg 			bp->cmd_tbl.set_crtc_timing = NULL;
1819fb4d8502Sjsg 			break;
1820fb4d8502Sjsg 		}
1821fb4d8502Sjsg }
1822fb4d8502Sjsg 
set_crtc_timing_v1(struct bios_parser * bp,struct bp_hw_crtc_timing_parameters * bp_params)1823fb4d8502Sjsg static enum bp_result set_crtc_timing_v1(
1824fb4d8502Sjsg 	struct bios_parser *bp,
1825fb4d8502Sjsg 	struct bp_hw_crtc_timing_parameters *bp_params)
1826fb4d8502Sjsg {
1827fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1828fb4d8502Sjsg 	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
1829fb4d8502Sjsg 	uint8_t atom_controller_id;
1830fb4d8502Sjsg 
1831fb4d8502Sjsg 	if (bp->cmd_helper->controller_id_to_atom(
1832fb4d8502Sjsg 			bp_params->controller_id, &atom_controller_id))
1833fb4d8502Sjsg 		params.ucCRTC = atom_controller_id;
1834fb4d8502Sjsg 
1835fb4d8502Sjsg 	params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
1836fb4d8502Sjsg 	params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
1837fb4d8502Sjsg 	params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
1838fb4d8502Sjsg 	params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
1839fb4d8502Sjsg 	params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
1840fb4d8502Sjsg 	params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
1841fb4d8502Sjsg 	params.usV_SyncStart =
1842fb4d8502Sjsg 			cpu_to_le16((uint16_t)(bp_params->v_sync_start));
1843fb4d8502Sjsg 	params.usV_SyncWidth =
1844fb4d8502Sjsg 			cpu_to_le16((uint16_t)(bp_params->v_sync_width));
1845fb4d8502Sjsg 
1846fb4d8502Sjsg 	/* VBIOS does not expect any value except zero into this call, for
1847fb4d8502Sjsg 	 * underscan use another entry ProgramOverscan call but when mode
1848fb4d8502Sjsg 	 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
1849fb4d8502Sjsg 	 * but when same ,but 60 Hz there is corruption
1850fb4d8502Sjsg 	 * DAL1 does not allow the mode 1776x1000@60
1851fb4d8502Sjsg 	 */
1852fb4d8502Sjsg 	params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
1853fb4d8502Sjsg 	params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
1854fb4d8502Sjsg 	params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
1855fb4d8502Sjsg 	params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
1856fb4d8502Sjsg 
1857fb4d8502Sjsg 	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1858fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1859fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1860fb4d8502Sjsg 
1861fb4d8502Sjsg 	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1862fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1863fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1864fb4d8502Sjsg 
1865fb4d8502Sjsg 	if (bp_params->flags.INTERLACE) {
1866fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1867fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1868fb4d8502Sjsg 
1869fb4d8502Sjsg 		/* original DAL code has this condition to apply tis for
1870fb4d8502Sjsg 		 * non-TV/CV only due to complex MV testing for possible
1871fb4d8502Sjsg 		 * impact
1872fb4d8502Sjsg 		 * if (pACParameters->signal != SignalType_YPbPr &&
1873fb4d8502Sjsg 		 *  pACParameters->signal != SignalType_Composite &&
1874fb4d8502Sjsg 		 *  pACParameters->signal != SignalType_SVideo)
1875fb4d8502Sjsg 		 */
1876fb4d8502Sjsg 		/* HW will deduct 0.5 line from 2nd feild.
1877fb4d8502Sjsg 		 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
1878fb4d8502Sjsg 		 * lines for the 2nd feild. we need input as 5 instead
1879fb4d8502Sjsg 		 * of 4, but it is 4 either from Edid data
1880fb4d8502Sjsg 		 * (spec CEA 861) or CEA timing table.
1881fb4d8502Sjsg 		 */
1882fb4d8502Sjsg 		params.usV_SyncStart =
1883fb4d8502Sjsg 				cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
1884fb4d8502Sjsg 	}
1885fb4d8502Sjsg 
1886fb4d8502Sjsg 	if (bp_params->flags.HORZ_COUNT_BY_TWO)
1887fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1888fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1889fb4d8502Sjsg 
1890fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
1891fb4d8502Sjsg 		result = BP_RESULT_OK;
1892fb4d8502Sjsg 
1893fb4d8502Sjsg 	return result;
1894fb4d8502Sjsg }
1895fb4d8502Sjsg 
set_crtc_using_dtd_timing_v3(struct bios_parser * bp,struct bp_hw_crtc_timing_parameters * bp_params)1896fb4d8502Sjsg static enum bp_result set_crtc_using_dtd_timing_v3(
1897fb4d8502Sjsg 	struct bios_parser *bp,
1898fb4d8502Sjsg 	struct bp_hw_crtc_timing_parameters *bp_params)
1899fb4d8502Sjsg {
1900fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
1901fb4d8502Sjsg 	SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
1902fb4d8502Sjsg 	uint8_t atom_controller_id;
1903fb4d8502Sjsg 
1904fb4d8502Sjsg 	if (bp->cmd_helper->controller_id_to_atom(
1905fb4d8502Sjsg 			bp_params->controller_id, &atom_controller_id))
1906fb4d8502Sjsg 		params.ucCRTC = atom_controller_id;
1907fb4d8502Sjsg 
1908fb4d8502Sjsg 	/* bios usH_Size wants h addressable size */
1909fb4d8502Sjsg 	params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
1910fb4d8502Sjsg 	/* bios usH_Blanking_Time wants borders included in blanking */
1911fb4d8502Sjsg 	params.usH_Blanking_Time =
1912fb4d8502Sjsg 			cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
1913fb4d8502Sjsg 	/* bios usV_Size wants v addressable size */
1914fb4d8502Sjsg 	params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
1915fb4d8502Sjsg 	/* bios usV_Blanking_Time wants borders included in blanking */
1916fb4d8502Sjsg 	params.usV_Blanking_Time =
1917fb4d8502Sjsg 			cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
1918fb4d8502Sjsg 	/* bios usHSyncOffset is the offset from the end of h addressable,
1919fb4d8502Sjsg 	 * our horizontalSyncStart is the offset from the beginning
1920fb4d8502Sjsg 	 * of h addressable */
1921fb4d8502Sjsg 	params.usH_SyncOffset =
1922fb4d8502Sjsg 			cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
1923fb4d8502Sjsg 	params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
1924fb4d8502Sjsg 	/* bios usHSyncOffset is the offset from the end of v addressable,
1925fb4d8502Sjsg 	 * our verticalSyncStart is the offset from the beginning of
1926fb4d8502Sjsg 	 * v addressable */
1927fb4d8502Sjsg 	params.usV_SyncOffset =
1928fb4d8502Sjsg 			cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
1929fb4d8502Sjsg 	params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
1930fb4d8502Sjsg 
1931fb4d8502Sjsg 	/* we assume that overscan from original timing does not get bigger
1932fb4d8502Sjsg 	 * than 255
1933fb4d8502Sjsg 	 * we will program all the borders in the Set CRTC Overscan call below
1934fb4d8502Sjsg 	 */
1935fb4d8502Sjsg 
1936fb4d8502Sjsg 	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1937fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1938fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1939fb4d8502Sjsg 
1940fb4d8502Sjsg 	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1941fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1942fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1943fb4d8502Sjsg 
1944fb4d8502Sjsg 	if (bp_params->flags.INTERLACE)	{
1945fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1946fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1947fb4d8502Sjsg 
1948fb4d8502Sjsg 		/* original DAL code has this condition to apply this
1949fb4d8502Sjsg 		 * for non-TV/CV only
1950fb4d8502Sjsg 		 * due to complex MV testing for possible impact
1951fb4d8502Sjsg 		 * if ( pACParameters->signal != SignalType_YPbPr &&
1952fb4d8502Sjsg 		 *  pACParameters->signal != SignalType_Composite &&
1953fb4d8502Sjsg 		 *  pACParameters->signal != SignalType_SVideo)
1954fb4d8502Sjsg 		 */
1955fb4d8502Sjsg 		{
1956fb4d8502Sjsg 			/* HW will deduct 0.5 line from 2nd feild.
1957fb4d8502Sjsg 			 * i.e. for 1080i, it is 2 lines for 1st field,
1958fb4d8502Sjsg 			 * 2.5 lines for the 2nd feild. we need input as 5
1959fb4d8502Sjsg 			 * instead of 4.
1960fb4d8502Sjsg 			 * but it is 4 either from Edid data (spec CEA 861)
1961fb4d8502Sjsg 			 * or CEA timing table.
1962fb4d8502Sjsg 			 */
1963ad8b1aafSjsg 			le16_add_cpu(&params.usV_SyncOffset, 1);
1964fb4d8502Sjsg 		}
1965fb4d8502Sjsg 	}
1966fb4d8502Sjsg 
1967fb4d8502Sjsg 	if (bp_params->flags.HORZ_COUNT_BY_TWO)
1968fb4d8502Sjsg 		params.susModeMiscInfo.usAccess =
1969fb4d8502Sjsg 				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1970fb4d8502Sjsg 
1971fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
1972fb4d8502Sjsg 		result = BP_RESULT_OK;
1973fb4d8502Sjsg 
1974fb4d8502Sjsg 	return result;
1975fb4d8502Sjsg }
1976fb4d8502Sjsg 
1977fb4d8502Sjsg /*******************************************************************************
1978fb4d8502Sjsg  ********************************************************************************
1979fb4d8502Sjsg  **
1980fb4d8502Sjsg  **                  ENABLE CRTC
1981fb4d8502Sjsg  **
1982fb4d8502Sjsg  ********************************************************************************
1983fb4d8502Sjsg  *******************************************************************************/
1984fb4d8502Sjsg 
1985fb4d8502Sjsg static enum bp_result enable_crtc_v1(
1986fb4d8502Sjsg 	struct bios_parser *bp,
1987fb4d8502Sjsg 	enum controller_id controller_id,
1988fb4d8502Sjsg 	bool enable);
1989fb4d8502Sjsg 
init_enable_crtc(struct bios_parser * bp)1990fb4d8502Sjsg static void init_enable_crtc(struct bios_parser *bp)
1991fb4d8502Sjsg {
1992fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
1993fb4d8502Sjsg 	case 1:
1994fb4d8502Sjsg 		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
1995fb4d8502Sjsg 		break;
1996fb4d8502Sjsg 	default:
1997fb4d8502Sjsg 		dm_output_to_console("Don't have enable_crtc for v%d\n",
1998fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
1999fb4d8502Sjsg 		bp->cmd_tbl.enable_crtc = NULL;
2000fb4d8502Sjsg 		break;
2001fb4d8502Sjsg 	}
2002fb4d8502Sjsg }
2003fb4d8502Sjsg 
enable_crtc_v1(struct bios_parser * bp,enum controller_id controller_id,bool enable)2004fb4d8502Sjsg static enum bp_result enable_crtc_v1(
2005fb4d8502Sjsg 	struct bios_parser *bp,
2006fb4d8502Sjsg 	enum controller_id controller_id,
2007fb4d8502Sjsg 	bool enable)
2008fb4d8502Sjsg {
2009fb4d8502Sjsg 	bool result = BP_RESULT_FAILURE;
2010fb4d8502Sjsg 	ENABLE_CRTC_PARAMETERS params = {0};
2011fb4d8502Sjsg 	uint8_t id;
2012fb4d8502Sjsg 
2013fb4d8502Sjsg 	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
2014fb4d8502Sjsg 		params.ucCRTC = id;
2015fb4d8502Sjsg 	else
2016fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2017fb4d8502Sjsg 
2018fb4d8502Sjsg 	if (enable)
2019fb4d8502Sjsg 		params.ucEnable = ATOM_ENABLE;
2020fb4d8502Sjsg 	else
2021fb4d8502Sjsg 		params.ucEnable = ATOM_DISABLE;
2022fb4d8502Sjsg 
2023fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
2024fb4d8502Sjsg 		result = BP_RESULT_OK;
2025fb4d8502Sjsg 
2026fb4d8502Sjsg 	return result;
2027fb4d8502Sjsg }
2028fb4d8502Sjsg 
2029fb4d8502Sjsg /*******************************************************************************
2030fb4d8502Sjsg  ********************************************************************************
2031fb4d8502Sjsg  **
2032fb4d8502Sjsg  **                  ENABLE CRTC MEM REQ
2033fb4d8502Sjsg  **
2034fb4d8502Sjsg  ********************************************************************************
2035fb4d8502Sjsg  *******************************************************************************/
2036fb4d8502Sjsg 
2037fb4d8502Sjsg static enum bp_result enable_crtc_mem_req_v1(
2038fb4d8502Sjsg 	struct bios_parser *bp,
2039fb4d8502Sjsg 	enum controller_id controller_id,
2040fb4d8502Sjsg 	bool enable);
2041fb4d8502Sjsg 
init_enable_crtc_mem_req(struct bios_parser * bp)2042fb4d8502Sjsg static void init_enable_crtc_mem_req(struct bios_parser *bp)
2043fb4d8502Sjsg {
2044fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
2045fb4d8502Sjsg 	case 1:
2046fb4d8502Sjsg 		bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
2047fb4d8502Sjsg 		break;
2048fb4d8502Sjsg 	default:
2049fb4d8502Sjsg 		bp->cmd_tbl.enable_crtc_mem_req = NULL;
2050fb4d8502Sjsg 		break;
2051fb4d8502Sjsg 	}
2052fb4d8502Sjsg }
2053fb4d8502Sjsg 
enable_crtc_mem_req_v1(struct bios_parser * bp,enum controller_id controller_id,bool enable)2054fb4d8502Sjsg static enum bp_result enable_crtc_mem_req_v1(
2055fb4d8502Sjsg 	struct bios_parser *bp,
2056fb4d8502Sjsg 	enum controller_id controller_id,
2057fb4d8502Sjsg 	bool enable)
2058fb4d8502Sjsg {
2059fb4d8502Sjsg 	bool result = BP_RESULT_BADINPUT;
2060fb4d8502Sjsg 	ENABLE_CRTC_PARAMETERS params = {0};
2061fb4d8502Sjsg 	uint8_t id;
2062fb4d8502Sjsg 
2063fb4d8502Sjsg 	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
2064fb4d8502Sjsg 		params.ucCRTC = id;
2065fb4d8502Sjsg 
2066fb4d8502Sjsg 		if (enable)
2067fb4d8502Sjsg 			params.ucEnable = ATOM_ENABLE;
2068fb4d8502Sjsg 		else
2069fb4d8502Sjsg 			params.ucEnable = ATOM_DISABLE;
2070fb4d8502Sjsg 
2071fb4d8502Sjsg 		if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
2072fb4d8502Sjsg 			result = BP_RESULT_OK;
2073fb4d8502Sjsg 		else
2074fb4d8502Sjsg 			result = BP_RESULT_FAILURE;
2075fb4d8502Sjsg 	}
2076fb4d8502Sjsg 
2077fb4d8502Sjsg 	return result;
2078fb4d8502Sjsg }
2079fb4d8502Sjsg 
2080fb4d8502Sjsg /*******************************************************************************
2081fb4d8502Sjsg  ********************************************************************************
2082fb4d8502Sjsg  **
2083fb4d8502Sjsg  **                  DISPLAY PLL
2084fb4d8502Sjsg  **
2085fb4d8502Sjsg  ********************************************************************************
2086fb4d8502Sjsg  *******************************************************************************/
2087fb4d8502Sjsg 
2088fb4d8502Sjsg static enum bp_result program_clock_v5(
2089fb4d8502Sjsg 	struct bios_parser *bp,
2090fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params);
2091fb4d8502Sjsg static enum bp_result program_clock_v6(
2092fb4d8502Sjsg 	struct bios_parser *bp,
2093fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params);
2094fb4d8502Sjsg 
init_program_clock(struct bios_parser * bp)2095fb4d8502Sjsg static void init_program_clock(struct bios_parser *bp)
2096fb4d8502Sjsg {
2097fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2098fb4d8502Sjsg 	case 5:
2099fb4d8502Sjsg 		bp->cmd_tbl.program_clock = program_clock_v5;
2100fb4d8502Sjsg 		break;
2101fb4d8502Sjsg 	case 6:
2102fb4d8502Sjsg 		bp->cmd_tbl.program_clock = program_clock_v6;
2103fb4d8502Sjsg 		break;
2104fb4d8502Sjsg 	default:
2105fb4d8502Sjsg 		dm_output_to_console("Don't have program_clock for v%d\n",
2106fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2107fb4d8502Sjsg 		bp->cmd_tbl.program_clock = NULL;
2108fb4d8502Sjsg 		break;
2109fb4d8502Sjsg 	}
2110fb4d8502Sjsg }
2111fb4d8502Sjsg 
program_clock_v5(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)2112fb4d8502Sjsg static enum bp_result program_clock_v5(
2113fb4d8502Sjsg 	struct bios_parser *bp,
2114fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
2115fb4d8502Sjsg {
2116fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
2117fb4d8502Sjsg 
2118fb4d8502Sjsg 	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2119fb4d8502Sjsg 	uint32_t atom_pll_id;
2120fb4d8502Sjsg 
2121fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
2122fb4d8502Sjsg 	if (!bp->cmd_helper->clock_source_id_to_atom(
2123fb4d8502Sjsg 			bp_params->pll_id, &atom_pll_id)) {
2124*1bb76ff1Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid Input!! */
2125fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2126fb4d8502Sjsg 	}
2127fb4d8502Sjsg 
2128fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units */
2129fb4d8502Sjsg 	params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2130fb4d8502Sjsg 	params.sPCLKInput.usPixelClock =
2131c349dbc7Sjsg 			cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
2132fb4d8502Sjsg 	params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2133fb4d8502Sjsg 
2134fb4d8502Sjsg 	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2135fb4d8502Sjsg 		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2136fb4d8502Sjsg 
2137fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2138fb4d8502Sjsg 		result = BP_RESULT_OK;
2139fb4d8502Sjsg 
2140fb4d8502Sjsg 	return result;
2141fb4d8502Sjsg }
2142fb4d8502Sjsg 
program_clock_v6(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)2143fb4d8502Sjsg static enum bp_result program_clock_v6(
2144fb4d8502Sjsg 	struct bios_parser *bp,
2145fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
2146fb4d8502Sjsg {
2147fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
2148fb4d8502Sjsg 
2149fb4d8502Sjsg 	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2150fb4d8502Sjsg 	uint32_t atom_pll_id;
2151fb4d8502Sjsg 
2152fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
2153fb4d8502Sjsg 
2154fb4d8502Sjsg 	if (!bp->cmd_helper->clock_source_id_to_atom(
2155fb4d8502Sjsg 			bp_params->pll_id, &atom_pll_id)) {
2156fb4d8502Sjsg 		BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2157fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2158fb4d8502Sjsg 	}
2159fb4d8502Sjsg 
2160fb4d8502Sjsg 	/* We need to convert from KHz units into 10KHz units */
2161fb4d8502Sjsg 	params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2162fb4d8502Sjsg 	params.sPCLKInput.ulDispEngClkFreq =
2163c349dbc7Sjsg 			cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
2164fb4d8502Sjsg 
2165fb4d8502Sjsg 	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2166fb4d8502Sjsg 		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2167fb4d8502Sjsg 
2168c349dbc7Sjsg 	if (bp_params->flags.SET_DISPCLK_DFS_BYPASS)
2169c349dbc7Sjsg 		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_DPREFCLK_BYPASS;
2170c349dbc7Sjsg 
2171fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2172fb4d8502Sjsg 		/* True display clock is returned by VBIOS if DFS bypass
2173fb4d8502Sjsg 		 * is enabled. */
2174fb4d8502Sjsg 		bp_params->dfs_bypass_display_clock =
2175fb4d8502Sjsg 				(uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2176fb4d8502Sjsg 		result = BP_RESULT_OK;
2177fb4d8502Sjsg 	}
2178fb4d8502Sjsg 
2179fb4d8502Sjsg 	return result;
2180fb4d8502Sjsg }
2181fb4d8502Sjsg 
2182fb4d8502Sjsg /*******************************************************************************
2183fb4d8502Sjsg  ********************************************************************************
2184fb4d8502Sjsg  **
2185fb4d8502Sjsg  **                  EXTERNAL ENCODER CONTROL
2186fb4d8502Sjsg  **
2187fb4d8502Sjsg  ********************************************************************************
2188fb4d8502Sjsg  *******************************************************************************/
2189fb4d8502Sjsg 
2190fb4d8502Sjsg static enum bp_result external_encoder_control_v3(
2191fb4d8502Sjsg 	struct bios_parser *bp,
2192fb4d8502Sjsg 	struct bp_external_encoder_control *cntl);
2193fb4d8502Sjsg 
init_external_encoder_control(struct bios_parser * bp)2194fb4d8502Sjsg static void init_external_encoder_control(
2195fb4d8502Sjsg 	struct bios_parser *bp)
2196fb4d8502Sjsg {
2197fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2198fb4d8502Sjsg 	case 3:
2199fb4d8502Sjsg 		bp->cmd_tbl.external_encoder_control =
2200fb4d8502Sjsg 				external_encoder_control_v3;
2201fb4d8502Sjsg 		break;
2202fb4d8502Sjsg 	default:
2203fb4d8502Sjsg 		bp->cmd_tbl.external_encoder_control = NULL;
2204fb4d8502Sjsg 		break;
2205fb4d8502Sjsg 	}
2206fb4d8502Sjsg }
2207fb4d8502Sjsg 
external_encoder_control_v3(struct bios_parser * bp,struct bp_external_encoder_control * cntl)2208fb4d8502Sjsg static enum bp_result external_encoder_control_v3(
2209fb4d8502Sjsg 	struct bios_parser *bp,
2210fb4d8502Sjsg 	struct bp_external_encoder_control *cntl)
2211fb4d8502Sjsg {
2212fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
2213fb4d8502Sjsg 
2214fb4d8502Sjsg 	/* we need use _PS_Alloc struct */
2215fb4d8502Sjsg 	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2216fb4d8502Sjsg 	EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2217fb4d8502Sjsg 	struct graphics_object_id encoder;
2218fb4d8502Sjsg 	bool is_input_signal_dp = false;
2219fb4d8502Sjsg 
2220fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
2221fb4d8502Sjsg 
2222fb4d8502Sjsg 	cntl_params = &params.sExtEncoder;
2223fb4d8502Sjsg 
2224fb4d8502Sjsg 	encoder = cntl->encoder_id;
2225fb4d8502Sjsg 
2226fb4d8502Sjsg 	/* check if encoder supports external encoder control table */
2227fb4d8502Sjsg 	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2228fb4d8502Sjsg 	case ENCODER_ID_EXTERNAL_NUTMEG:
2229fb4d8502Sjsg 	case ENCODER_ID_EXTERNAL_TRAVIS:
2230fb4d8502Sjsg 		is_input_signal_dp = true;
2231fb4d8502Sjsg 		break;
2232fb4d8502Sjsg 
2233fb4d8502Sjsg 	default:
2234fb4d8502Sjsg 		BREAK_TO_DEBUGGER();
2235fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2236fb4d8502Sjsg 	}
2237fb4d8502Sjsg 
2238fb4d8502Sjsg 	/* Fill information based on the action
2239fb4d8502Sjsg 	 *
2240fb4d8502Sjsg 	 * Bit[6:4]: indicate external encoder, applied to all functions.
2241fb4d8502Sjsg 	 * =0: external encoder1, mapped to external encoder enum id1
2242fb4d8502Sjsg 	 * =1: external encoder2, mapped to external encoder enum id2
2243fb4d8502Sjsg 	 *
2244fb4d8502Sjsg 	 * enum ObjectEnumId
2245fb4d8502Sjsg 	 * {
2246fb4d8502Sjsg 	 *  EnumId_Unknown = 0,
2247fb4d8502Sjsg 	 *  EnumId_1,
2248fb4d8502Sjsg 	 *  EnumId_2,
2249fb4d8502Sjsg 	 * };
2250fb4d8502Sjsg 	 */
2251fb4d8502Sjsg 	cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2252fb4d8502Sjsg 
2253fb4d8502Sjsg 	switch (cntl->action) {
2254fb4d8502Sjsg 	case EXTERNAL_ENCODER_CONTROL_INIT:
2255fb4d8502Sjsg 		/* output display connector type. Only valid in encoder
2256fb4d8502Sjsg 		 * initialization */
2257fb4d8502Sjsg 		cntl_params->usConnectorId =
2258fb4d8502Sjsg 				cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2259fb4d8502Sjsg 		break;
2260fb4d8502Sjsg 	case EXTERNAL_ENCODER_CONTROL_SETUP:
2261fb4d8502Sjsg 		/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2262fb4d8502Sjsg 		 * 10KHz
2263fb4d8502Sjsg 		 * output display device pixel clock frequency in unit of 10KHz.
2264fb4d8502Sjsg 		 * Only valid in setup and enableoutput
2265fb4d8502Sjsg 		 */
2266fb4d8502Sjsg 		cntl_params->usPixelClock =
2267fb4d8502Sjsg 				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2268fb4d8502Sjsg 		/* Indicate display output signal type drive by external
2269fb4d8502Sjsg 		 * encoder, only valid in setup and enableoutput */
2270fb4d8502Sjsg 		cntl_params->ucEncoderMode =
2271fb4d8502Sjsg 				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2272fb4d8502Sjsg 						cntl->signal, false);
2273fb4d8502Sjsg 
2274fb4d8502Sjsg 		if (is_input_signal_dp) {
2275fb4d8502Sjsg 			/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2276fb4d8502Sjsg 			 * only valid in encoder setup with DP mode. */
2277fb4d8502Sjsg 			if (LINK_RATE_HIGH == cntl->link_rate)
2278fb4d8502Sjsg 				cntl_params->ucConfig |= 1;
2279fb4d8502Sjsg 			/* output color depth Indicate encoder data bpc format
2280fb4d8502Sjsg 			 * in DP mode, only valid in encoder setup in DP mode.
2281fb4d8502Sjsg 			 */
2282fb4d8502Sjsg 			cntl_params->ucBitPerColor =
2283fb4d8502Sjsg 					(uint8_t)(cntl->color_depth);
2284fb4d8502Sjsg 		}
2285fb4d8502Sjsg 		/* Indicate how many lanes used by external encoder, only valid
2286fb4d8502Sjsg 		 * in encoder setup and enableoutput. */
2287fb4d8502Sjsg 		cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2288fb4d8502Sjsg 		break;
2289fb4d8502Sjsg 	case EXTERNAL_ENCODER_CONTROL_ENABLE:
2290fb4d8502Sjsg 		cntl_params->usPixelClock =
2291fb4d8502Sjsg 				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2292fb4d8502Sjsg 		cntl_params->ucEncoderMode =
2293fb4d8502Sjsg 				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2294fb4d8502Sjsg 						cntl->signal, false);
2295fb4d8502Sjsg 		cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2296fb4d8502Sjsg 		break;
2297fb4d8502Sjsg 	default:
2298fb4d8502Sjsg 		break;
2299fb4d8502Sjsg 	}
2300fb4d8502Sjsg 
2301fb4d8502Sjsg 	cntl_params->ucAction = (uint8_t)cntl->action;
2302fb4d8502Sjsg 
2303fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2304fb4d8502Sjsg 		result = BP_RESULT_OK;
2305fb4d8502Sjsg 
2306fb4d8502Sjsg 	return result;
2307fb4d8502Sjsg }
2308fb4d8502Sjsg 
2309fb4d8502Sjsg /*******************************************************************************
2310fb4d8502Sjsg  ********************************************************************************
2311fb4d8502Sjsg  **
2312fb4d8502Sjsg  **                  ENABLE DISPLAY POWER GATING
2313fb4d8502Sjsg  **
2314fb4d8502Sjsg  ********************************************************************************
2315fb4d8502Sjsg  *******************************************************************************/
2316fb4d8502Sjsg 
2317fb4d8502Sjsg static enum bp_result enable_disp_power_gating_v2_1(
2318fb4d8502Sjsg 	struct bios_parser *bp,
2319fb4d8502Sjsg 	enum controller_id crtc_id,
2320fb4d8502Sjsg 	enum bp_pipe_control_action action);
2321fb4d8502Sjsg 
init_enable_disp_power_gating(struct bios_parser * bp)2322fb4d8502Sjsg static void init_enable_disp_power_gating(
2323fb4d8502Sjsg 	struct bios_parser *bp)
2324fb4d8502Sjsg {
2325fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2326fb4d8502Sjsg 	case 1:
2327fb4d8502Sjsg 		bp->cmd_tbl.enable_disp_power_gating =
2328fb4d8502Sjsg 				enable_disp_power_gating_v2_1;
2329fb4d8502Sjsg 		break;
2330fb4d8502Sjsg 	default:
2331fb4d8502Sjsg 		dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2332fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2333fb4d8502Sjsg 		bp->cmd_tbl.enable_disp_power_gating = NULL;
2334fb4d8502Sjsg 		break;
2335fb4d8502Sjsg 	}
2336fb4d8502Sjsg }
2337fb4d8502Sjsg 
enable_disp_power_gating_v2_1(struct bios_parser * bp,enum controller_id crtc_id,enum bp_pipe_control_action action)2338fb4d8502Sjsg static enum bp_result enable_disp_power_gating_v2_1(
2339fb4d8502Sjsg 	struct bios_parser *bp,
2340fb4d8502Sjsg 	enum controller_id crtc_id,
2341fb4d8502Sjsg 	enum bp_pipe_control_action action)
2342fb4d8502Sjsg {
2343fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
2344fb4d8502Sjsg 
2345fb4d8502Sjsg 	ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2346fb4d8502Sjsg 	uint8_t atom_crtc_id;
2347fb4d8502Sjsg 
2348fb4d8502Sjsg 	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2349fb4d8502Sjsg 		params.ucDispPipeId = atom_crtc_id;
2350fb4d8502Sjsg 	else
2351fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2352fb4d8502Sjsg 
2353fb4d8502Sjsg 	params.ucEnable =
2354fb4d8502Sjsg 			bp->cmd_helper->disp_power_gating_action_to_atom(action);
2355fb4d8502Sjsg 
2356fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2357fb4d8502Sjsg 		result = BP_RESULT_OK;
2358fb4d8502Sjsg 
2359fb4d8502Sjsg 	return result;
2360fb4d8502Sjsg }
2361fb4d8502Sjsg 
2362fb4d8502Sjsg /*******************************************************************************
2363fb4d8502Sjsg  ********************************************************************************
2364fb4d8502Sjsg  **
2365fb4d8502Sjsg  **                  SET DCE CLOCK
2366fb4d8502Sjsg  **
2367fb4d8502Sjsg  ********************************************************************************
2368fb4d8502Sjsg  *******************************************************************************/
2369fb4d8502Sjsg static enum bp_result set_dce_clock_v2_1(
2370fb4d8502Sjsg 	struct bios_parser *bp,
2371fb4d8502Sjsg 	struct bp_set_dce_clock_parameters *bp_params);
2372fb4d8502Sjsg 
init_set_dce_clock(struct bios_parser * bp)2373fb4d8502Sjsg static void init_set_dce_clock(struct bios_parser *bp)
2374fb4d8502Sjsg {
2375fb4d8502Sjsg 	switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2376fb4d8502Sjsg 	case 1:
2377fb4d8502Sjsg 		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2378fb4d8502Sjsg 		break;
2379fb4d8502Sjsg 	default:
2380fb4d8502Sjsg 		dm_output_to_console("Don't have set_dce_clock for v%d\n",
2381fb4d8502Sjsg 			 BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2382fb4d8502Sjsg 		bp->cmd_tbl.set_dce_clock = NULL;
2383fb4d8502Sjsg 		break;
2384fb4d8502Sjsg 	}
2385fb4d8502Sjsg }
2386fb4d8502Sjsg 
set_dce_clock_v2_1(struct bios_parser * bp,struct bp_set_dce_clock_parameters * bp_params)2387fb4d8502Sjsg static enum bp_result set_dce_clock_v2_1(
2388fb4d8502Sjsg 	struct bios_parser *bp,
2389fb4d8502Sjsg 	struct bp_set_dce_clock_parameters *bp_params)
2390fb4d8502Sjsg {
2391fb4d8502Sjsg 	enum bp_result result = BP_RESULT_FAILURE;
2392fb4d8502Sjsg 
2393fb4d8502Sjsg 	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2394fb4d8502Sjsg 	uint32_t atom_pll_id;
2395fb4d8502Sjsg 	uint32_t atom_clock_type;
2396fb4d8502Sjsg 	const struct command_table_helper *cmd = bp->cmd_helper;
2397fb4d8502Sjsg 
2398fb4d8502Sjsg 	memset(&params, 0, sizeof(params));
2399fb4d8502Sjsg 
2400fb4d8502Sjsg 	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2401fb4d8502Sjsg 			!cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2402fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2403fb4d8502Sjsg 
2404fb4d8502Sjsg 	params.asParam.ucDCEClkSrc  = atom_pll_id;
2405fb4d8502Sjsg 	params.asParam.ucDCEClkType = atom_clock_type;
2406fb4d8502Sjsg 
2407fb4d8502Sjsg 	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2408fb4d8502Sjsg 		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2409fb4d8502Sjsg 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2410fb4d8502Sjsg 
2411fb4d8502Sjsg 		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2412fb4d8502Sjsg 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2413fb4d8502Sjsg 
2414fb4d8502Sjsg 		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2415fb4d8502Sjsg 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2416fb4d8502Sjsg 
2417fb4d8502Sjsg 		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2418fb4d8502Sjsg 			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2419fb4d8502Sjsg 	}
2420fb4d8502Sjsg 	else
2421fb4d8502Sjsg 		/* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2422fb4d8502Sjsg 		/* We need to convert from KHz units into 10KHz units */
2423fb4d8502Sjsg 		params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2424fb4d8502Sjsg 
2425fb4d8502Sjsg 	if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2426fb4d8502Sjsg 		/* Convert from 10KHz units back to KHz */
2427fb4d8502Sjsg 		bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2428fb4d8502Sjsg 		result = BP_RESULT_OK;
2429fb4d8502Sjsg 	}
2430fb4d8502Sjsg 
2431fb4d8502Sjsg 	return result;
2432fb4d8502Sjsg }
2433