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