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