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