projects/linux·blob master · refs

2693 lines · 80.0 KiB

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