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