1/*	$NetBSD: amdgpu_command_table2.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $	*/
2
3/*
4 * Copyright 2012-15 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: amdgpu_command_table2.c,v 1.2 2021/12/18 23:45:00 riastradh Exp $");
30
31#include "dm_services.h"
32
33#include "ObjectID.h"
34
35#include "atomfirmware.h"
36#include "atom.h"
37#include "include/bios_parser_interface.h"
38
39#include "command_table2.h"
40#include "command_table_helper2.h"
41#include "bios_parser_helper.h"
42#include "bios_parser_types_internal2.h"
43#include "amdgpu.h"
44
45#include "dc_dmub_srv.h"
46#include "dc.h"
47
48#define DC_LOGGER \
49	bp->base.ctx->logger
50
51#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\
52	(((char *)(&((\
53		struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\
54		->FieldName)-(char *)0)/sizeof(uint16_t))
55
56#define EXEC_BIOS_CMD_TABLE(fname, params)\
57	(amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
58		GET_INDEX_INTO_MASTER_TABLE(command, fname), \
59		(uint32_t *)&params) == 0)
60
61#define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\
62	amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
63		GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev)
64
65#define BIOS_CMD_TABLE_PARA_REVISION(fname)\
66	bios_cmd_table_para_revision(bp->base.ctx->driver_context, \
67			GET_INDEX_INTO_MASTER_TABLE(command, fname))
68
69
70
71static uint32_t bios_cmd_table_para_revision(void *dev,
72					     uint32_t index)
73{
74	struct amdgpu_device *adev = dev;
75	uint8_t frev, crev;
76
77	if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,
78					index,
79					&frev, &crev))
80		return crev;
81	else
82		return 0;
83}
84
85/******************************************************************************
86 ******************************************************************************
87 **
88 **                  D I G E N C O D E R C O N T R O L
89 **
90 ******************************************************************************
91 *****************************************************************************/
92
93static enum bp_result encoder_control_digx_v1_5(
94	struct bios_parser *bp,
95	struct bp_encoder_control *cntl);
96
97static enum bp_result encoder_control_fallback(
98	struct bios_parser *bp,
99	struct bp_encoder_control *cntl);
100
101static void init_dig_encoder_control(struct bios_parser *bp)
102{
103	uint32_t version =
104		BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol);
105
106	switch (version) {
107	case 5:
108		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5;
109		break;
110	default:
111		dm_output_to_console("Don't have dig_encoder_control for v%d\n", version);
112		bp->cmd_tbl.dig_encoder_control = encoder_control_fallback;
113		break;
114	}
115}
116
117static void encoder_control_dmcub(
118		struct dc_dmub_srv *dmcub,
119		struct dig_encoder_stream_setup_parameters_v1_5 *dig)
120{
121	struct dmub_rb_cmd_digx_encoder_control encoder_control = { 0 };
122
123	encoder_control.header.type = DMUB_CMD__VBIOS;
124	encoder_control.header.sub_type = DMUB_CMD__VBIOS_DIGX_ENCODER_CONTROL;
125	encoder_control.encoder_control.dig.stream_param = *dig;
126
127	dc_dmub_srv_cmd_queue(dmcub, &encoder_control.header);
128	dc_dmub_srv_cmd_execute(dmcub);
129	dc_dmub_srv_wait_idle(dmcub);
130}
131
132static enum bp_result encoder_control_digx_v1_5(
133	struct bios_parser *bp,
134	struct bp_encoder_control *cntl)
135{
136	enum bp_result result = BP_RESULT_FAILURE;
137	struct dig_encoder_stream_setup_parameters_v1_5 params = {0};
138
139	params.digid = (uint8_t)(cntl->engine_id);
140	params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action);
141
142	params.pclk_10khz = cntl->pixel_clock / 10;
143	params.digmode =
144			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
145					cntl->signal,
146					cntl->enable_dp_audio));
147	params.lanenum = (uint8_t)(cntl->lanes_number);
148
149	switch (cntl->color_depth) {
150	case COLOR_DEPTH_888:
151		params.bitpercolor = PANEL_8BIT_PER_COLOR;
152		break;
153	case COLOR_DEPTH_101010:
154		params.bitpercolor = PANEL_10BIT_PER_COLOR;
155		break;
156	case COLOR_DEPTH_121212:
157		params.bitpercolor = PANEL_12BIT_PER_COLOR;
158		break;
159	case COLOR_DEPTH_161616:
160		params.bitpercolor = PANEL_16BIT_PER_COLOR;
161		break;
162	default:
163		break;
164	}
165
166	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
167		switch (cntl->color_depth) {
168		case COLOR_DEPTH_101010:
169			params.pclk_10khz =
170				(params.pclk_10khz * 30) / 24;
171			break;
172		case COLOR_DEPTH_121212:
173			params.pclk_10khz =
174				(params.pclk_10khz * 36) / 24;
175			break;
176		case COLOR_DEPTH_161616:
177			params.pclk_10khz =
178				(params.pclk_10khz * 48) / 24;
179			break;
180		default:
181			break;
182		}
183
184	if (bp->base.ctx->dc->ctx->dmub_srv &&
185	    bp->base.ctx->dc->debug.dmub_command_table) {
186		encoder_control_dmcub(bp->base.ctx->dmub_srv, &params);
187		return BP_RESULT_OK;
188	}
189
190	if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params))
191		result = BP_RESULT_OK;
192
193	return result;
194}
195
196static enum bp_result encoder_control_fallback(
197	struct bios_parser *bp,
198	struct bp_encoder_control *cntl)
199{
200	if (bp->base.ctx->dc->ctx->dmub_srv &&
201	    bp->base.ctx->dc->debug.dmub_command_table) {
202		return encoder_control_digx_v1_5(bp, cntl);
203	}
204
205	return BP_RESULT_FAILURE;
206}
207
208/*****************************************************************************
209 ******************************************************************************
210 **
211 **                  TRANSMITTER CONTROL
212 **
213 ******************************************************************************
214 *****************************************************************************/
215
216static enum bp_result transmitter_control_v1_6(
217	struct bios_parser *bp,
218	struct bp_transmitter_control *cntl);
219
220static enum bp_result transmitter_control_fallback(
221	struct bios_parser *bp,
222	struct bp_transmitter_control *cntl);
223
224static void init_transmitter_control(struct bios_parser *bp)
225{
226	uint8_t frev;
227	uint8_t crev;
228
229	if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) == false)
230		BREAK_TO_DEBUGGER();
231	switch (crev) {
232	case 6:
233		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
234		break;
235	default:
236		dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
237		bp->cmd_tbl.transmitter_control = transmitter_control_fallback;
238		break;
239	}
240}
241
242static void transmitter_control_dmcub(
243		struct dc_dmub_srv *dmcub,
244		struct dig_transmitter_control_parameters_v1_6 *dig)
245{
246	struct dmub_rb_cmd_dig1_transmitter_control transmitter_control;
247
248	transmitter_control.header.type = DMUB_CMD__VBIOS;
249	transmitter_control.header.sub_type =
250		DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL;
251	transmitter_control.transmitter_control.dig = *dig;
252
253	dc_dmub_srv_cmd_queue(dmcub, &transmitter_control.header);
254	dc_dmub_srv_cmd_execute(dmcub);
255	dc_dmub_srv_wait_idle(dmcub);
256}
257
258static enum bp_result transmitter_control_v1_6(
259	struct bios_parser *bp,
260	struct bp_transmitter_control *cntl)
261{
262	enum bp_result result = BP_RESULT_FAILURE;
263	const struct command_table_helper *cmd = bp->cmd_helper;
264	struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } };
265
266	ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter);
267	ps.param.action = (uint8_t)cntl->action;
268
269	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
270		ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings;
271	else
272		ps.param.mode_laneset.digmode =
273				cmd->signal_type_to_atom_dig_mode(cntl->signal);
274
275	ps.param.lanenum = (uint8_t)cntl->lanes_number;
276	ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
277	ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
278	ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id;
279	ps.param.symclk_10khz = cntl->pixel_clock/10;
280
281
282	if (cntl->action == TRANSMITTER_CONTROL_ENABLE ||
283		cntl->action == TRANSMITTER_CONTROL_ACTIAVATE ||
284		cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) {
285		DC_LOG_BIOS("%s:ps.param.symclk_10khz = %d\n",\
286		__func__, ps.param.symclk_10khz);
287	}
288
289	if (bp->base.ctx->dc->ctx->dmub_srv &&
290	    bp->base.ctx->dc->debug.dmub_command_table) {
291		transmitter_control_dmcub(bp->base.ctx->dmub_srv, &ps.param);
292		return BP_RESULT_OK;
293	}
294
295/*color_depth not used any more, driver has deep color factor in the Phyclk*/
296	if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps))
297		result = BP_RESULT_OK;
298	return result;
299}
300
301static enum bp_result transmitter_control_fallback(
302	struct bios_parser *bp,
303	struct bp_transmitter_control *cntl)
304{
305	if (bp->base.ctx->dc->ctx->dmub_srv &&
306	    bp->base.ctx->dc->debug.dmub_command_table) {
307		return transmitter_control_v1_6(bp, cntl);
308	}
309
310	return BP_RESULT_FAILURE;
311}
312
313/******************************************************************************
314 ******************************************************************************
315 **
316 **                  SET PIXEL CLOCK
317 **
318 ******************************************************************************
319 *****************************************************************************/
320
321static enum bp_result set_pixel_clock_v7(
322	struct bios_parser *bp,
323	struct bp_pixel_clock_parameters *bp_params);
324
325static enum bp_result set_pixel_clock_fallback(
326	struct bios_parser *bp,
327	struct bp_pixel_clock_parameters *bp_params);
328
329static void init_set_pixel_clock(struct bios_parser *bp)
330{
331	switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) {
332	case 7:
333		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
334		break;
335	default:
336		dm_output_to_console("Don't have set_pixel_clock for v%d\n",
337			 BIOS_CMD_TABLE_PARA_REVISION(setpixelclock));
338		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback;
339		break;
340	}
341}
342
343static void set_pixel_clock_dmcub(
344		struct dc_dmub_srv *dmcub,
345		struct set_pixel_clock_parameter_v1_7 *clk)
346{
347	struct dmub_rb_cmd_set_pixel_clock pixel_clock = { 0 };
348
349	pixel_clock.header.type = DMUB_CMD__VBIOS;
350	pixel_clock.header.sub_type = DMUB_CMD__VBIOS_SET_PIXEL_CLOCK;
351	pixel_clock.pixel_clock.clk = *clk;
352
353	dc_dmub_srv_cmd_queue(dmcub, &pixel_clock.header);
354	dc_dmub_srv_cmd_execute(dmcub);
355	dc_dmub_srv_wait_idle(dmcub);
356}
357
358static enum bp_result set_pixel_clock_v7(
359	struct bios_parser *bp,
360	struct bp_pixel_clock_parameters *bp_params)
361{
362	enum bp_result result = BP_RESULT_FAILURE;
363	struct set_pixel_clock_parameter_v1_7 clk;
364	uint8_t controller_id;
365	uint32_t pll_id;
366
367	memset(&clk, 0, sizeof(clk));
368
369	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
370			&& bp->cmd_helper->controller_id_to_atom(bp_params->
371					controller_id, &controller_id)) {
372		/* Note: VBIOS still wants to use ucCRTC name which is now
373		 * 1 byte in ULONG
374		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
375		 *{
376		 * target the pixel clock to drive the CRTC timing.
377		 * ULONG ulPixelClock:24;
378		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
379		 * previous version.
380		 * ATOM_CRTC1~6, indicate the CRTC controller to
381		 * ULONG ucCRTC:8;
382		 * drive the pixel clock. not used for DCPLL case.
383		 *}CRTC_PIXEL_CLOCK_FREQ;
384		 *union
385		 *{
386		 * pixel clock and CRTC id frequency
387		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
388		 * ULONG ulDispEngClkFreq; dispclk frequency
389		 *};
390		 */
391		clk.crtc_id = controller_id;
392		clk.pll_id = (uint8_t) pll_id;
393		clk.encoderobjid =
394			bp->cmd_helper->encoder_id_to_atom(
395				dal_graphics_object_id_get_encoder_id(
396					bp_params->encoder_object_id));
397
398		clk.encoder_mode = (uint8_t) bp->
399			cmd_helper->encoder_mode_bp_to_atom(
400				bp_params->signal_type, false);
401
402		clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock_100hz);
403
404		clk.deep_color_ratio =
405			(uint8_t) bp->cmd_helper->
406				transmitter_color_depth_to_atom(
407					bp_params->color_depth);
408
409		DC_LOG_BIOS("%s:program display clock = %d, tg = %d, pll = %d, "\
410				"colorDepth = %d\n", __func__,
411				bp_params->target_pixel_clock_100hz, (int)controller_id,
412				pll_id, bp_params->color_depth);
413
414		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
415			clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
416
417		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
418			clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
419
420		if (bp_params->flags.SUPPORT_YUV_420)
421			clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
422
423		if (bp_params->flags.SET_XTALIN_REF_SRC)
424			clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
425
426		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
427			clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
428
429		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
430			clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
431
432		if (bp->base.ctx->dc->ctx->dmub_srv &&
433		    bp->base.ctx->dc->debug.dmub_command_table) {
434			set_pixel_clock_dmcub(bp->base.ctx->dmub_srv, &clk);
435			return BP_RESULT_OK;
436		}
437
438		if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk))
439			result = BP_RESULT_OK;
440	}
441	return result;
442}
443
444static enum bp_result set_pixel_clock_fallback(
445	struct bios_parser *bp,
446	struct bp_pixel_clock_parameters *bp_params)
447{
448	if (bp->base.ctx->dc->ctx->dmub_srv &&
449	    bp->base.ctx->dc->debug.dmub_command_table) {
450		return set_pixel_clock_v7(bp, bp_params);
451	}
452
453	return BP_RESULT_FAILURE;
454}
455
456/******************************************************************************
457 ******************************************************************************
458 **
459 **                  SET CRTC TIMING
460 **
461 ******************************************************************************
462 *****************************************************************************/
463
464static enum bp_result set_crtc_using_dtd_timing_v3(
465	struct bios_parser *bp,
466	struct bp_hw_crtc_timing_parameters *bp_params);
467
468static void init_set_crtc_timing(struct bios_parser *bp)
469{
470	uint32_t dtd_version =
471			BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming);
472
473	switch (dtd_version) {
474	case 3:
475		bp->cmd_tbl.set_crtc_timing =
476			set_crtc_using_dtd_timing_v3;
477		break;
478	default:
479		dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version);
480		bp->cmd_tbl.set_crtc_timing = NULL;
481		break;
482	}
483}
484
485static enum bp_result set_crtc_using_dtd_timing_v3(
486	struct bios_parser *bp,
487	struct bp_hw_crtc_timing_parameters *bp_params)
488{
489	enum bp_result result = BP_RESULT_FAILURE;
490	struct set_crtc_using_dtd_timing_parameters params = {0};
491	uint8_t atom_controller_id;
492
493	if (bp->cmd_helper->controller_id_to_atom(
494			bp_params->controller_id, &atom_controller_id))
495		params.crtc_id = atom_controller_id;
496
497	/* bios usH_Size wants h addressable size */
498	params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable);
499	/* bios usH_Blanking_Time wants borders included in blanking */
500	params.h_blanking_time =
501			cpu_to_le16((uint16_t)(bp_params->h_total -
502					bp_params->h_addressable));
503	/* bios usV_Size wants v addressable size */
504	params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable);
505	/* bios usV_Blanking_Time wants borders included in blanking */
506	params.v_blanking_time =
507			cpu_to_le16((uint16_t)(bp_params->v_total -
508					bp_params->v_addressable));
509	/* bios usHSyncOffset is the offset from the end of h addressable,
510	 * our horizontalSyncStart is the offset from the beginning
511	 * of h addressable
512	 */
513	params.h_syncoffset =
514			cpu_to_le16((uint16_t)(bp_params->h_sync_start -
515					bp_params->h_addressable));
516	params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
517	/* bios usHSyncOffset is the offset from the end of v addressable,
518	 * our verticalSyncStart is the offset from the beginning of
519	 * v addressable
520	 */
521	params.v_syncoffset =
522			cpu_to_le16((uint16_t)(bp_params->v_sync_start -
523					bp_params->v_addressable));
524	params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
525
526	/* we assume that overscan from original timing does not get bigger
527	 * than 255
528	 * we will program all the borders in the Set CRTC Overscan call below
529	 */
530
531	if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0)
532		params.modemiscinfo =
533				cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
534						ATOM_HSYNC_POLARITY);
535
536	if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0)
537		params.modemiscinfo =
538				cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
539						ATOM_VSYNC_POLARITY);
540
541	if (bp_params->flags.INTERLACE)	{
542		params.modemiscinfo =
543				cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
544						ATOM_INTERLACE);
545
546		/* original DAL code has this condition to apply this
547		 * for non-TV/CV only
548		 * due to complex MV testing for possible impact
549		 * if ( pACParameters->signal != SignalType_YPbPr &&
550		 *  pACParameters->signal != SignalType_Composite &&
551		 *  pACParameters->signal != SignalType_SVideo)
552		 */
553		{
554			/* HW will deduct 0.5 line from 2nd feild.
555			 * i.e. for 1080i, it is 2 lines for 1st field,
556			 * 2.5 lines for the 2nd feild. we need input as 5
557			 * instead of 4.
558			 * but it is 4 either from Edid data (spec CEA 861)
559			 * or CEA timing table.
560			 */
561			params.v_syncoffset =
562				cpu_to_le16(le16_to_cpu(params.v_syncoffset) +
563						1);
564
565		}
566	}
567
568	if (bp_params->flags.HORZ_COUNT_BY_TWO)
569		params.modemiscinfo =
570			cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
571					0x100); /* ATOM_DOUBLE_CLOCK_MODE */
572
573	if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params))
574		result = BP_RESULT_OK;
575
576	return result;
577}
578
579/******************************************************************************
580 ******************************************************************************
581 **
582 **                  ENABLE CRTC
583 **
584 ******************************************************************************
585 *****************************************************************************/
586
587static enum bp_result enable_crtc_v1(
588	struct bios_parser *bp,
589	enum controller_id controller_id,
590	bool enable);
591
592static void init_enable_crtc(struct bios_parser *bp)
593{
594	switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) {
595	case 1:
596		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
597		break;
598	default:
599		dm_output_to_console("Don't have enable_crtc for v%d\n",
600			 BIOS_CMD_TABLE_PARA_REVISION(enablecrtc));
601		bp->cmd_tbl.enable_crtc = NULL;
602		break;
603	}
604}
605
606static enum bp_result enable_crtc_v1(
607	struct bios_parser *bp,
608	enum controller_id controller_id,
609	bool enable)
610{
611	bool result = BP_RESULT_FAILURE;
612	struct enable_crtc_parameters params = {0};
613	uint8_t id;
614
615	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
616		params.crtc_id = id;
617	else
618		return BP_RESULT_BADINPUT;
619
620	if (enable)
621		params.enable = ATOM_ENABLE;
622	else
623		params.enable = ATOM_DISABLE;
624
625	if (EXEC_BIOS_CMD_TABLE(enablecrtc, params))
626		result = BP_RESULT_OK;
627
628	return result;
629}
630
631/******************************************************************************
632 ******************************************************************************
633 **
634 **                  DISPLAY PLL
635 **
636 ******************************************************************************
637 *****************************************************************************/
638
639
640
641/******************************************************************************
642 ******************************************************************************
643 **
644 **                  EXTERNAL ENCODER CONTROL
645 **
646 ******************************************************************************
647 *****************************************************************************/
648
649static enum bp_result external_encoder_control_v3(
650	struct bios_parser *bp,
651	struct bp_external_encoder_control *cntl);
652
653static void init_external_encoder_control(
654	struct bios_parser *bp)
655{
656	switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) {
657	case 3:
658		bp->cmd_tbl.external_encoder_control =
659				external_encoder_control_v3;
660		break;
661	default:
662		bp->cmd_tbl.external_encoder_control = NULL;
663		break;
664	}
665}
666
667static enum bp_result external_encoder_control_v3(
668	struct bios_parser *bp,
669	struct bp_external_encoder_control *cntl)
670{
671	/* TODO */
672	return BP_RESULT_OK;
673}
674
675/******************************************************************************
676 ******************************************************************************
677 **
678 **                  ENABLE DISPLAY POWER GATING
679 **
680 ******************************************************************************
681 *****************************************************************************/
682
683static enum bp_result enable_disp_power_gating_v2_1(
684	struct bios_parser *bp,
685	enum controller_id crtc_id,
686	enum bp_pipe_control_action action);
687
688static enum bp_result enable_disp_power_gating_fallback(
689	struct bios_parser *bp,
690	enum controller_id crtc_id,
691	enum bp_pipe_control_action action);
692
693static void init_enable_disp_power_gating(
694	struct bios_parser *bp)
695{
696	switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) {
697	case 1:
698		bp->cmd_tbl.enable_disp_power_gating =
699				enable_disp_power_gating_v2_1;
700		break;
701	default:
702		dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
703			 BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating));
704		bp->cmd_tbl.enable_disp_power_gating = enable_disp_power_gating_fallback;
705		break;
706	}
707}
708
709static void enable_disp_power_gating_dmcub(
710	struct dc_dmub_srv *dmcub,
711	struct enable_disp_power_gating_parameters_v2_1 *pwr)
712{
713	struct dmub_rb_cmd_enable_disp_power_gating power_gating;
714
715	power_gating.header.type = DMUB_CMD__VBIOS;
716	power_gating.header.sub_type = DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING;
717	power_gating.power_gating.pwr = *pwr;
718
719	dc_dmub_srv_cmd_queue(dmcub, &power_gating.header);
720	dc_dmub_srv_cmd_execute(dmcub);
721	dc_dmub_srv_wait_idle(dmcub);
722}
723
724static enum bp_result enable_disp_power_gating_v2_1(
725	struct bios_parser *bp,
726	enum controller_id crtc_id,
727	enum bp_pipe_control_action action)
728{
729	enum bp_result result = BP_RESULT_FAILURE;
730
731
732	struct enable_disp_power_gating_ps_allocation ps = { { 0 } };
733	uint8_t atom_crtc_id;
734
735	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
736		ps.param.disp_pipe_id = atom_crtc_id;
737	else
738		return BP_RESULT_BADINPUT;
739
740	ps.param.enable =
741		bp->cmd_helper->disp_power_gating_action_to_atom(action);
742
743	if (bp->base.ctx->dc->ctx->dmub_srv &&
744	    bp->base.ctx->dc->debug.dmub_command_table) {
745		enable_disp_power_gating_dmcub(bp->base.ctx->dmub_srv,
746					       &ps.param);
747		return BP_RESULT_OK;
748	}
749
750	if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param))
751		result = BP_RESULT_OK;
752
753	return result;
754}
755
756static enum bp_result enable_disp_power_gating_fallback(
757	struct bios_parser *bp,
758	enum controller_id crtc_id,
759	enum bp_pipe_control_action action)
760{
761	if (bp->base.ctx->dc->ctx->dmub_srv &&
762	    bp->base.ctx->dc->debug.dmub_command_table) {
763		return enable_disp_power_gating_v2_1(bp, crtc_id, action);
764	}
765
766	return BP_RESULT_FAILURE;
767}
768
769/******************************************************************************
770*******************************************************************************
771 **
772 **                  SET DCE CLOCK
773 **
774*******************************************************************************
775*******************************************************************************/
776
777static enum bp_result set_dce_clock_v2_1(
778	struct bios_parser *bp,
779	struct bp_set_dce_clock_parameters *bp_params);
780
781static void init_set_dce_clock(struct bios_parser *bp)
782{
783	switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) {
784	case 1:
785		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
786		break;
787	default:
788		dm_output_to_console("Don't have set_dce_clock for v%d\n",
789			 BIOS_CMD_TABLE_PARA_REVISION(setdceclock));
790		bp->cmd_tbl.set_dce_clock = NULL;
791		break;
792	}
793}
794
795static enum bp_result set_dce_clock_v2_1(
796	struct bios_parser *bp,
797	struct bp_set_dce_clock_parameters *bp_params)
798{
799	enum bp_result result = BP_RESULT_FAILURE;
800
801	struct set_dce_clock_ps_allocation_v2_1 params;
802	uint32_t atom_pll_id;
803	uint32_t atom_clock_type;
804	const struct command_table_helper *cmd = bp->cmd_helper;
805
806	memset(&params, 0, sizeof(params));
807
808	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
809			!cmd->dc_clock_type_to_atom(bp_params->clock_type,
810					&atom_clock_type))
811		return BP_RESULT_BADINPUT;
812
813	params.param.dceclksrc  = atom_pll_id;
814	params.param.dceclktype = atom_clock_type;
815
816	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
817		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
818			params.param.dceclkflag |=
819					DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
820
821		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
822			params.param.dceclkflag |=
823					DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
824
825		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
826			params.param.dceclkflag |=
827					DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
828
829		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
830			params.param.dceclkflag |=
831					DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
832	} else
833		/* only program clock frequency if display clock is used;
834		 * VBIOS will program DPREFCLK
835		 * We need to convert from KHz units into 10KHz units
836		 */
837		params.param.dceclk_10khz = cpu_to_le32(
838				bp_params->target_clock_frequency / 10);
839	DC_LOG_BIOS("%s:target_clock_frequency = %d"\
840			"clock_type = %d \n", __func__,\
841			bp_params->target_clock_frequency,\
842			bp_params->clock_type);
843
844	if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) {
845		/* Convert from 10KHz units back to KHz */
846		bp_params->target_clock_frequency = le32_to_cpu(
847				params.param.dceclk_10khz) * 10;
848		result = BP_RESULT_OK;
849	}
850
851	return result;
852}
853
854
855/******************************************************************************
856 ******************************************************************************
857 **
858 **                  GET SMU CLOCK INFO
859 **
860 ******************************************************************************
861 *****************************************************************************/
862
863static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id);
864
865static void init_get_smu_clock_info(struct bios_parser *bp)
866{
867	/* TODO add switch for table vrsion */
868	bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1;
869
870}
871
872static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id)
873{
874	struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0};
875	struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output;
876
877	smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ;
878	smu_input.syspll_id = id;
879
880	/* Get Specific Clock */
881	if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) {
882		memmove(&smu_output, &smu_input, sizeof(
883			struct atom_get_smu_clock_info_parameters_v3_1));
884		return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz;
885	}
886
887	return 0;
888}
889
890void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)
891{
892	init_dig_encoder_control(bp);
893	init_transmitter_control(bp);
894	init_set_pixel_clock(bp);
895
896	init_set_crtc_timing(bp);
897
898	init_enable_crtc(bp);
899
900	init_external_encoder_control(bp);
901	init_enable_disp_power_gating(bp);
902	init_set_dce_clock(bp);
903	init_get_smu_clock_info(bp);
904
905}
906