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 *)¶ms) == 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
bios_cmd_table_para_revision(void * dev,uint32_t index)71 static 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
93 static enum bp_result encoder_control_digx_v1_5(
94 struct bios_parser *bp,
95 struct bp_encoder_control *cntl);
96
97 static enum bp_result encoder_control_fallback(
98 struct bios_parser *bp,
99 struct bp_encoder_control *cntl);
100
init_dig_encoder_control(struct bios_parser * bp)101 static 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
encoder_control_dmcub(struct dc_dmub_srv * dmcub,struct dig_encoder_stream_setup_parameters_v1_5 * dig)117 static 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
encoder_control_digx_v1_5(struct bios_parser * bp,struct bp_encoder_control * cntl)132 static 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, ¶ms);
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
encoder_control_fallback(struct bios_parser * bp,struct bp_encoder_control * cntl)196 static 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
216 static enum bp_result transmitter_control_v1_6(
217 struct bios_parser *bp,
218 struct bp_transmitter_control *cntl);
219
220 static enum bp_result transmitter_control_fallback(
221 struct bios_parser *bp,
222 struct bp_transmitter_control *cntl);
223
init_transmitter_control(struct bios_parser * bp)224 static 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
transmitter_control_dmcub(struct dc_dmub_srv * dmcub,struct dig_transmitter_control_parameters_v1_6 * dig)242 static 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
transmitter_control_v1_6(struct bios_parser * bp,struct bp_transmitter_control * cntl)258 static 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
transmitter_control_fallback(struct bios_parser * bp,struct bp_transmitter_control * cntl)301 static 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
321 static enum bp_result set_pixel_clock_v7(
322 struct bios_parser *bp,
323 struct bp_pixel_clock_parameters *bp_params);
324
325 static enum bp_result set_pixel_clock_fallback(
326 struct bios_parser *bp,
327 struct bp_pixel_clock_parameters *bp_params);
328
init_set_pixel_clock(struct bios_parser * bp)329 static 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
set_pixel_clock_dmcub(struct dc_dmub_srv * dmcub,struct set_pixel_clock_parameter_v1_7 * clk)343 static 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
set_pixel_clock_v7(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)358 static 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
set_pixel_clock_fallback(struct bios_parser * bp,struct bp_pixel_clock_parameters * bp_params)444 static 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
464 static enum bp_result set_crtc_using_dtd_timing_v3(
465 struct bios_parser *bp,
466 struct bp_hw_crtc_timing_parameters *bp_params);
467
init_set_crtc_timing(struct bios_parser * bp)468 static 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
set_crtc_using_dtd_timing_v3(struct bios_parser * bp,struct bp_hw_crtc_timing_parameters * bp_params)485 static 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
587 static enum bp_result enable_crtc_v1(
588 struct bios_parser *bp,
589 enum controller_id controller_id,
590 bool enable);
591
init_enable_crtc(struct bios_parser * bp)592 static 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
enable_crtc_v1(struct bios_parser * bp,enum controller_id controller_id,bool enable)606 static 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
649 static enum bp_result external_encoder_control_v3(
650 struct bios_parser *bp,
651 struct bp_external_encoder_control *cntl);
652
init_external_encoder_control(struct bios_parser * bp)653 static 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
external_encoder_control_v3(struct bios_parser * bp,struct bp_external_encoder_control * cntl)667 static 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
683 static 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
688 static 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
init_enable_disp_power_gating(struct bios_parser * bp)693 static 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
enable_disp_power_gating_dmcub(struct dc_dmub_srv * dmcub,struct enable_disp_power_gating_parameters_v2_1 * pwr)709 static 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
enable_disp_power_gating_v2_1(struct bios_parser * bp,enum controller_id crtc_id,enum bp_pipe_control_action action)724 static 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
enable_disp_power_gating_fallback(struct bios_parser * bp,enum controller_id crtc_id,enum bp_pipe_control_action action)756 static 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
777 static enum bp_result set_dce_clock_v2_1(
778 struct bios_parser *bp,
779 struct bp_set_dce_clock_parameters *bp_params);
780
init_set_dce_clock(struct bios_parser * bp)781 static 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
set_dce_clock_v2_1(struct bios_parser * bp,struct bp_set_dce_clock_parameters * bp_params)795 static 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(¶ms, 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
863 static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id);
864
init_get_smu_clock_info(struct bios_parser * bp)865 static 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
get_smu_clock_info_v3_1(struct bios_parser * bp,uint8_t id)872 static 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
dal_firmware_parser_init_cmd_tbl(struct bios_parser * bp)890 void 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