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