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 "core_types.h"
28
29 #include "ObjectID.h"
30 #include "atomfirmware.h"
31
32 #include "dc_bios_types.h"
33 #include "include/grph_object_ctrl_defs.h"
34 #include "include/bios_parser_interface.h"
35 #include "include/logger_interface.h"
36
37 #include "command_table2.h"
38
39 #include "bios_parser_helper.h"
40 #include "command_table_helper2.h"
41 #include "bios_parser2.h"
42 #include "bios_parser_types_internal2.h"
43 #include "bios_parser_interface.h"
44
45 #include "bios_parser_common.h"
46
47 #define DC_LOGGER \
48 bp->base.ctx->logger
49
50 #define LAST_RECORD_TYPE 0xff
51 #define SMU9_SYSPLL0_ID 0
52
53 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
54 struct atom_i2c_record *record,
55 struct graphics_object_i2c_info *info);
56
57 static enum bp_result bios_parser_get_firmware_info(
58 struct dc_bios *dcb,
59 struct dc_firmware_info *info);
60
61 static enum bp_result bios_parser_get_encoder_cap_info(
62 struct dc_bios *dcb,
63 struct graphics_object_id object_id,
64 struct bp_encoder_cap_info *info);
65
66 static enum bp_result get_firmware_info_v3_1(
67 struct bios_parser *bp,
68 struct dc_firmware_info *info);
69
70 static enum bp_result get_firmware_info_v3_2(
71 struct bios_parser *bp,
72 struct dc_firmware_info *info);
73
74 static enum bp_result get_firmware_info_v3_4(
75 struct bios_parser *bp,
76 struct dc_firmware_info *info);
77
78 static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
79 struct atom_display_object_path_v2 *object);
80
81 static struct atom_encoder_caps_record *get_encoder_cap_record(
82 struct bios_parser *bp,
83 struct atom_display_object_path_v2 *object);
84
85 #define BIOS_IMAGE_SIZE_OFFSET 2
86 #define BIOS_IMAGE_SIZE_UNIT 512
87
88 #define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)
89
bios_parser2_destruct(struct bios_parser * bp)90 static void bios_parser2_destruct(struct bios_parser *bp)
91 {
92 kfree(bp->base.bios_local_image);
93 kfree(bp->base.integrated_info);
94 }
95
firmware_parser_destroy(struct dc_bios ** dcb)96 static void firmware_parser_destroy(struct dc_bios **dcb)
97 {
98 struct bios_parser *bp = BP_FROM_DCB(*dcb);
99
100 if (!bp) {
101 BREAK_TO_DEBUGGER();
102 return;
103 }
104
105 bios_parser2_destruct(bp);
106
107 kfree(bp);
108 *dcb = NULL;
109 }
110
get_atom_data_table_revision(struct atom_common_table_header * atom_data_tbl,struct atom_data_revision * tbl_revision)111 static void get_atom_data_table_revision(
112 struct atom_common_table_header *atom_data_tbl,
113 struct atom_data_revision *tbl_revision)
114 {
115 if (!tbl_revision)
116 return;
117
118 /* initialize the revision to 0 which is invalid revision */
119 tbl_revision->major = 0;
120 tbl_revision->minor = 0;
121
122 if (!atom_data_tbl)
123 return;
124
125 tbl_revision->major =
126 (uint32_t) atom_data_tbl->format_revision & 0x3f;
127 tbl_revision->minor =
128 (uint32_t) atom_data_tbl->content_revision & 0x3f;
129 }
130
131 /* BIOS oject table displaypath is per connector.
132 * There is extra path not for connector. BIOS fill its encoderid as 0
133 */
bios_parser_get_connectors_number(struct dc_bios * dcb)134 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
135 {
136 struct bios_parser *bp = BP_FROM_DCB(dcb);
137 unsigned int count = 0;
138 unsigned int i;
139
140 switch (bp->object_info_tbl.revision.minor) {
141 default:
142 case 4:
143 for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++)
144 if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)
145 count++;
146
147 break;
148
149 case 5:
150 for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++)
151 if (bp->object_info_tbl.v1_5->display_path[i].encoderobjid != 0)
152 count++;
153
154 break;
155 }
156 return count;
157 }
158
bios_parser_get_connector_id(struct dc_bios * dcb,uint8_t i)159 static struct graphics_object_id bios_parser_get_connector_id(
160 struct dc_bios *dcb,
161 uint8_t i)
162 {
163 struct bios_parser *bp = BP_FROM_DCB(dcb);
164 struct graphics_object_id object_id = dal_graphics_object_id_init(
165 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
166 struct object_info_table *tbl = &bp->object_info_tbl;
167 struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;
168
169 struct display_object_info_table_v1_5 *v1_5 = tbl->v1_5;
170
171 switch (bp->object_info_tbl.revision.minor) {
172 default:
173 case 4:
174 if (v1_4->number_of_path > i) {
175 /* If display_objid is generic object id, the encoderObj
176 * /extencoderobjId should be 0
177 */
178 if (v1_4->display_path[i].encoderobjid != 0 &&
179 v1_4->display_path[i].display_objid != 0)
180 object_id = object_id_from_bios_object_id(
181 v1_4->display_path[i].display_objid);
182 }
183 break;
184
185 case 5:
186 if (v1_5->number_of_path > i) {
187 /* If display_objid is generic object id, the encoderObjId
188 * should be 0
189 */
190 if (v1_5->display_path[i].encoderobjid != 0 &&
191 v1_5->display_path[i].display_objid != 0)
192 object_id = object_id_from_bios_object_id(
193 v1_5->display_path[i].display_objid);
194 }
195 break;
196 }
197 return object_id;
198 }
199
bios_parser_get_src_obj(struct dc_bios * dcb,struct graphics_object_id object_id,uint32_t index,struct graphics_object_id * src_object_id)200 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
201 struct graphics_object_id object_id, uint32_t index,
202 struct graphics_object_id *src_object_id)
203 {
204 struct bios_parser *bp = BP_FROM_DCB(dcb);
205 unsigned int i;
206 enum bp_result bp_result = BP_RESULT_BADINPUT;
207 struct graphics_object_id obj_id = { 0 };
208 struct object_info_table *tbl = &bp->object_info_tbl;
209
210 if (!src_object_id)
211 return bp_result;
212
213 switch (object_id.type) {
214 /* Encoder's Source is GPU. BIOS does not provide GPU, since all
215 * displaypaths point to same GPU (0x1100). Hardcode GPU object type
216 */
217 case OBJECT_TYPE_ENCODER:
218 /* TODO: since num of src must be less than 2.
219 * If found in for loop, should break.
220 * DAL2 implementation may be changed too
221 */
222 switch (bp->object_info_tbl.revision.minor) {
223 default:
224 case 4:
225 for (i = 0; i < tbl->v1_4->number_of_path; i++) {
226 obj_id = object_id_from_bios_object_id(
227 tbl->v1_4->display_path[i].encoderobjid);
228 if (object_id.type == obj_id.type &&
229 object_id.id == obj_id.id &&
230 object_id.enum_id == obj_id.enum_id) {
231 *src_object_id =
232 object_id_from_bios_object_id(
233 0x1100);
234 /* break; */
235 }
236 }
237 bp_result = BP_RESULT_OK;
238 break;
239
240 case 5:
241 for (i = 0; i < tbl->v1_5->number_of_path; i++) {
242 obj_id = object_id_from_bios_object_id(
243 tbl->v1_5->display_path[i].encoderobjid);
244 if (object_id.type == obj_id.type &&
245 object_id.id == obj_id.id &&
246 object_id.enum_id == obj_id.enum_id) {
247 *src_object_id =
248 object_id_from_bios_object_id(
249 0x1100);
250 /* break; */
251 }
252 }
253 bp_result = BP_RESULT_OK;
254 break;
255 }
256 break;
257 case OBJECT_TYPE_CONNECTOR:
258 switch (bp->object_info_tbl.revision.minor) {
259 default:
260 case 4:
261 for (i = 0; i < tbl->v1_4->number_of_path; i++) {
262 obj_id = object_id_from_bios_object_id(
263 tbl->v1_4->display_path[i]
264 .display_objid);
265
266 if (object_id.type == obj_id.type &&
267 object_id.id == obj_id.id &&
268 object_id.enum_id == obj_id.enum_id) {
269 *src_object_id =
270 object_id_from_bios_object_id(
271 tbl->v1_4
272 ->display_path[i]
273 .encoderobjid);
274 /* break; */
275 }
276 }
277 bp_result = BP_RESULT_OK;
278 break;
279 }
280 bp_result = BP_RESULT_OK;
281 break;
282 case 5:
283 for (i = 0; i < tbl->v1_5->number_of_path; i++) {
284 obj_id = object_id_from_bios_object_id(
285 tbl->v1_5->display_path[i].display_objid);
286
287 if (object_id.type == obj_id.type &&
288 object_id.id == obj_id.id &&
289 object_id.enum_id == obj_id.enum_id) {
290 *src_object_id = object_id_from_bios_object_id(
291 tbl->v1_5->display_path[i].encoderobjid);
292 /* break; */
293 }
294 }
295 bp_result = BP_RESULT_OK;
296 break;
297
298 default:
299 bp_result = BP_RESULT_OK;
300 break;
301 }
302
303 return bp_result;
304 }
305
306 /* from graphics_object_id, find display path which includes the object_id */
get_bios_object(struct bios_parser * bp,struct graphics_object_id id)307 static struct atom_display_object_path_v2 *get_bios_object(
308 struct bios_parser *bp,
309 struct graphics_object_id id)
310 {
311 unsigned int i;
312 struct graphics_object_id obj_id = {0};
313
314 switch (id.type) {
315 case OBJECT_TYPE_ENCODER:
316 for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
317 obj_id = object_id_from_bios_object_id(
318 bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
319 if (id.type == obj_id.type && id.id == obj_id.id
320 && id.enum_id == obj_id.enum_id)
321 return &bp->object_info_tbl.v1_4->display_path[i];
322 }
323 fallthrough;
324 case OBJECT_TYPE_CONNECTOR:
325 case OBJECT_TYPE_GENERIC:
326 /* Both Generic and Connector Object ID
327 * will be stored on display_objid
328 */
329 for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
330 obj_id = object_id_from_bios_object_id(
331 bp->object_info_tbl.v1_4->display_path[i].display_objid);
332 if (id.type == obj_id.type && id.id == obj_id.id
333 && id.enum_id == obj_id.enum_id)
334 return &bp->object_info_tbl.v1_4->display_path[i];
335 }
336 fallthrough;
337 default:
338 return NULL;
339 }
340 }
341
342 /* from graphics_object_id, find display path which includes the object_id */
get_bios_object_from_path_v3(struct bios_parser * bp,struct graphics_object_id id)343 static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(struct bios_parser *bp,
344 struct graphics_object_id id)
345 {
346 unsigned int i;
347 struct graphics_object_id obj_id = {0};
348
349 switch (id.type) {
350 case OBJECT_TYPE_ENCODER:
351 for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
352 obj_id = object_id_from_bios_object_id(
353 bp->object_info_tbl.v1_5->display_path[i].encoderobjid);
354 if (id.type == obj_id.type && id.id == obj_id.id
355 && id.enum_id == obj_id.enum_id)
356 return &bp->object_info_tbl.v1_5->display_path[i];
357 }
358 break;
359
360 case OBJECT_TYPE_CONNECTOR:
361 case OBJECT_TYPE_GENERIC:
362 /* Both Generic and Connector Object ID
363 * will be stored on display_objid
364 */
365 for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
366 obj_id = object_id_from_bios_object_id(
367 bp->object_info_tbl.v1_5->display_path[i].display_objid);
368 if (id.type == obj_id.type && id.id == obj_id.id
369 && id.enum_id == obj_id.enum_id)
370 return &bp->object_info_tbl.v1_5->display_path[i];
371 }
372 break;
373
374 default:
375 return NULL;
376 }
377
378 return NULL;
379 }
380
bios_parser_get_i2c_info(struct dc_bios * dcb,struct graphics_object_id id,struct graphics_object_i2c_info * info)381 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
382 struct graphics_object_id id,
383 struct graphics_object_i2c_info *info)
384 {
385 uint32_t offset;
386 struct atom_display_object_path_v2 *object;
387
388 struct atom_display_object_path_v3 *object_path_v3;
389
390 struct atom_common_record_header *header;
391 struct atom_i2c_record *record;
392 struct atom_i2c_record dummy_record = {0};
393 struct bios_parser *bp = BP_FROM_DCB(dcb);
394
395 if (!info)
396 return BP_RESULT_BADINPUT;
397
398 if (id.type == OBJECT_TYPE_GENERIC) {
399 dummy_record.i2c_id = id.id;
400
401 if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)
402 return BP_RESULT_OK;
403 else
404 return BP_RESULT_NORECORD;
405 }
406
407 switch (bp->object_info_tbl.revision.minor) {
408 case 4:
409 default:
410 object = get_bios_object(bp, id);
411
412 if (!object)
413 return BP_RESULT_BADINPUT;
414
415 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
416 break;
417 case 5:
418 object_path_v3 = get_bios_object_from_path_v3(bp, id);
419
420 if (!object_path_v3)
421 return BP_RESULT_BADINPUT;
422
423 offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
424 break;
425 }
426
427 for (;;) {
428 header = GET_IMAGE(struct atom_common_record_header, offset);
429
430 if (!header)
431 return BP_RESULT_BADBIOSTABLE;
432
433 if (header->record_type == LAST_RECORD_TYPE ||
434 !header->record_size)
435 break;
436
437 if (header->record_type == ATOM_I2C_RECORD_TYPE
438 && sizeof(struct atom_i2c_record) <=
439 header->record_size) {
440 /* get the I2C info */
441 record = (struct atom_i2c_record *) header;
442
443 if (get_gpio_i2c_info(bp, record, info) ==
444 BP_RESULT_OK)
445 return BP_RESULT_OK;
446 }
447
448 offset += header->record_size;
449 }
450
451 return BP_RESULT_NORECORD;
452 }
453
get_gpio_i2c_info(struct bios_parser * bp,struct atom_i2c_record * record,struct graphics_object_i2c_info * info)454 static enum bp_result get_gpio_i2c_info(
455 struct bios_parser *bp,
456 struct atom_i2c_record *record,
457 struct graphics_object_i2c_info *info)
458 {
459 struct atom_gpio_pin_lut_v2_1 *header;
460 uint32_t count = 0;
461 unsigned int table_index = 0;
462 bool find_valid = false;
463 struct atom_gpio_pin_assignment *pin;
464
465 if (!info)
466 return BP_RESULT_BADINPUT;
467
468 /* get the GPIO_I2C info */
469 if (!DATA_TABLES(gpio_pin_lut))
470 return BP_RESULT_BADBIOSTABLE;
471
472 header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
473 DATA_TABLES(gpio_pin_lut));
474 if (!header)
475 return BP_RESULT_BADBIOSTABLE;
476
477 if (sizeof(struct atom_common_table_header) +
478 sizeof(struct atom_gpio_pin_assignment) >
479 le16_to_cpu(header->table_header.structuresize))
480 return BP_RESULT_BADBIOSTABLE;
481
482 /* TODO: is version change? */
483 if (header->table_header.content_revision != 1)
484 return BP_RESULT_UNSUPPORTED;
485
486 /* get data count */
487 count = (le16_to_cpu(header->table_header.structuresize)
488 - sizeof(struct atom_common_table_header))
489 / sizeof(struct atom_gpio_pin_assignment);
490
491 pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;
492
493 for (table_index = 0; table_index < count; table_index++) {
494 if (((record->i2c_id & I2C_HW_CAP) == (pin->gpio_id & I2C_HW_CAP)) &&
495 ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) &&
496 ((record->i2c_id & I2C_HW_LANE_MUX) == (pin->gpio_id & I2C_HW_LANE_MUX))) {
497 /* still valid */
498 find_valid = true;
499 break;
500 }
501 pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment));
502 }
503
504 /* If we don't find the entry that we are looking for then
505 * we will return BP_Result_BadBiosTable.
506 */
507 if (find_valid == false)
508 return BP_RESULT_BADBIOSTABLE;
509
510 /* get the GPIO_I2C_INFO */
511 info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
512 info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
513 info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4;
514 info->i2c_slave_address = record->i2c_slave_addr;
515
516 /* TODO: check how to get register offset for en, Y, etc. */
517 info->gpio_info.clk_a_register_index = le16_to_cpu(pin->data_a_reg_index);
518 info->gpio_info.clk_a_shift = pin->gpio_bitshift;
519
520 return BP_RESULT_OK;
521 }
522
get_hpd_record_for_path_v3(struct bios_parser * bp,struct atom_display_object_path_v3 * object)523 static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser *bp,
524 struct atom_display_object_path_v3 *object)
525 {
526 struct atom_common_record_header *header;
527 uint32_t offset;
528
529 if (!object) {
530 BREAK_TO_DEBUGGER(); /* Invalid object */
531 return NULL;
532 }
533
534 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
535
536 for (;;) {
537 header = GET_IMAGE(struct atom_common_record_header, offset);
538
539 if (!header)
540 return NULL;
541
542 if (header->record_type == ATOM_RECORD_END_TYPE ||
543 !header->record_size)
544 break;
545
546 if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
547 && sizeof(struct atom_hpd_int_record) <=
548 header->record_size)
549 return (struct atom_hpd_int_record *) header;
550
551 offset += header->record_size;
552 }
553
554 return NULL;
555 }
556
bios_parser_get_hpd_info(struct dc_bios * dcb,struct graphics_object_id id,struct graphics_object_hpd_info * info)557 static enum bp_result bios_parser_get_hpd_info(
558 struct dc_bios *dcb,
559 struct graphics_object_id id,
560 struct graphics_object_hpd_info *info)
561 {
562 struct bios_parser *bp = BP_FROM_DCB(dcb);
563 struct atom_display_object_path_v2 *object;
564 struct atom_display_object_path_v3 *object_path_v3;
565 struct atom_hpd_int_record *record = NULL;
566
567 if (!info)
568 return BP_RESULT_BADINPUT;
569
570 switch (bp->object_info_tbl.revision.minor) {
571 case 4:
572 default:
573 object = get_bios_object(bp, id);
574
575 if (!object)
576 return BP_RESULT_BADINPUT;
577
578 record = get_hpd_record(bp, object);
579
580 break;
581 case 5:
582 object_path_v3 = get_bios_object_from_path_v3(bp, id);
583
584 if (!object_path_v3)
585 return BP_RESULT_BADINPUT;
586
587 record = get_hpd_record_for_path_v3(bp, object_path_v3);
588 break;
589 }
590
591 if (record != NULL) {
592 info->hpd_int_gpio_uid = record->pin_id;
593 info->hpd_active = record->plugin_pin_state;
594 return BP_RESULT_OK;
595 }
596
597 return BP_RESULT_NORECORD;
598 }
599
get_hpd_record(struct bios_parser * bp,struct atom_display_object_path_v2 * object)600 static struct atom_hpd_int_record *get_hpd_record(
601 struct bios_parser *bp,
602 struct atom_display_object_path_v2 *object)
603 {
604 struct atom_common_record_header *header;
605 uint32_t offset;
606
607 if (!object) {
608 BREAK_TO_DEBUGGER(); /* Invalid object */
609 return NULL;
610 }
611
612 offset = le16_to_cpu(object->disp_recordoffset)
613 + bp->object_info_tbl_offset;
614
615 for (;;) {
616 header = GET_IMAGE(struct atom_common_record_header, offset);
617
618 if (!header)
619 return NULL;
620
621 if (header->record_type == LAST_RECORD_TYPE ||
622 !header->record_size)
623 break;
624
625 if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
626 && sizeof(struct atom_hpd_int_record) <=
627 header->record_size)
628 return (struct atom_hpd_int_record *) header;
629
630 offset += header->record_size;
631 }
632
633 return NULL;
634 }
635
636 /**
637 * bios_parser_get_gpio_pin_info
638 * Get GpioPin information of input gpio id
639 *
640 * @dcb: pointer to the DC BIOS
641 * @gpio_id: GPIO ID
642 * @info: GpioPin information structure
643 * return: Bios parser result code
644 * note:
645 * to get the GPIO PIN INFO, we need:
646 * 1. get the GPIO_ID from other object table, see GetHPDInfo()
647 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records,
648 * to get the registerA offset/mask
649 */
bios_parser_get_gpio_pin_info(struct dc_bios * dcb,uint32_t gpio_id,struct gpio_pin_info * info)650 static enum bp_result bios_parser_get_gpio_pin_info(
651 struct dc_bios *dcb,
652 uint32_t gpio_id,
653 struct gpio_pin_info *info)
654 {
655 struct bios_parser *bp = BP_FROM_DCB(dcb);
656 struct atom_gpio_pin_lut_v2_1 *header;
657 uint32_t count = 0;
658 uint32_t i = 0;
659
660 if (!DATA_TABLES(gpio_pin_lut))
661 return BP_RESULT_BADBIOSTABLE;
662
663 header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
664 DATA_TABLES(gpio_pin_lut));
665 if (!header)
666 return BP_RESULT_BADBIOSTABLE;
667
668 if (sizeof(struct atom_common_table_header) +
669 sizeof(struct atom_gpio_pin_assignment)
670 > le16_to_cpu(header->table_header.structuresize))
671 return BP_RESULT_BADBIOSTABLE;
672
673 if (header->table_header.content_revision != 1)
674 return BP_RESULT_UNSUPPORTED;
675
676 /* Temporary hard code gpio pin info */
677 count = (le16_to_cpu(header->table_header.structuresize)
678 - sizeof(struct atom_common_table_header))
679 / sizeof(struct atom_gpio_pin_assignment);
680 for (i = 0; i < count; ++i) {
681 if (header->gpio_pin[i].gpio_id != gpio_id)
682 continue;
683
684 info->offset =
685 (uint32_t) le16_to_cpu(
686 header->gpio_pin[i].data_a_reg_index);
687 info->offset_y = info->offset + 2;
688 info->offset_en = info->offset + 1;
689 info->offset_mask = info->offset - 1;
690
691 info->mask = (uint32_t) (1 <<
692 header->gpio_pin[i].gpio_bitshift);
693 info->mask_y = info->mask + 2;
694 info->mask_en = info->mask + 1;
695 info->mask_mask = info->mask - 1;
696
697 return BP_RESULT_OK;
698 }
699
700 return BP_RESULT_NORECORD;
701 }
702
device_type_from_device_id(uint16_t device_id)703 static struct device_id device_type_from_device_id(uint16_t device_id)
704 {
705
706 struct device_id result_device_id;
707
708 result_device_id.raw_device_tag = device_id;
709
710 switch (device_id) {
711 case ATOM_DISPLAY_LCD1_SUPPORT:
712 result_device_id.device_type = DEVICE_TYPE_LCD;
713 result_device_id.enum_id = 1;
714 break;
715
716 case ATOM_DISPLAY_LCD2_SUPPORT:
717 result_device_id.device_type = DEVICE_TYPE_LCD;
718 result_device_id.enum_id = 2;
719 break;
720
721 case ATOM_DISPLAY_DFP1_SUPPORT:
722 result_device_id.device_type = DEVICE_TYPE_DFP;
723 result_device_id.enum_id = 1;
724 break;
725
726 case ATOM_DISPLAY_DFP2_SUPPORT:
727 result_device_id.device_type = DEVICE_TYPE_DFP;
728 result_device_id.enum_id = 2;
729 break;
730
731 case ATOM_DISPLAY_DFP3_SUPPORT:
732 result_device_id.device_type = DEVICE_TYPE_DFP;
733 result_device_id.enum_id = 3;
734 break;
735
736 case ATOM_DISPLAY_DFP4_SUPPORT:
737 result_device_id.device_type = DEVICE_TYPE_DFP;
738 result_device_id.enum_id = 4;
739 break;
740
741 case ATOM_DISPLAY_DFP5_SUPPORT:
742 result_device_id.device_type = DEVICE_TYPE_DFP;
743 result_device_id.enum_id = 5;
744 break;
745
746 case ATOM_DISPLAY_DFP6_SUPPORT:
747 result_device_id.device_type = DEVICE_TYPE_DFP;
748 result_device_id.enum_id = 6;
749 break;
750
751 default:
752 BREAK_TO_DEBUGGER(); /* Invalid device Id */
753 result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
754 result_device_id.enum_id = 0;
755 }
756 return result_device_id;
757 }
758
bios_parser_get_device_tag(struct dc_bios * dcb,struct graphics_object_id connector_object_id,uint32_t device_tag_index,struct connector_device_tag_info * info)759 static enum bp_result bios_parser_get_device_tag(
760 struct dc_bios *dcb,
761 struct graphics_object_id connector_object_id,
762 uint32_t device_tag_index,
763 struct connector_device_tag_info *info)
764 {
765 struct bios_parser *bp = BP_FROM_DCB(dcb);
766 struct atom_display_object_path_v2 *object;
767
768 struct atom_display_object_path_v3 *object_path_v3;
769
770
771 if (!info)
772 return BP_RESULT_BADINPUT;
773
774 switch (bp->object_info_tbl.revision.minor) {
775 case 4:
776 default:
777 /* getBiosObject will return MXM object */
778 object = get_bios_object(bp, connector_object_id);
779
780 if (!object) {
781 BREAK_TO_DEBUGGER(); /* Invalid object id */
782 return BP_RESULT_BADINPUT;
783 }
784
785 info->acpi_device = 0; /* BIOS no longer provides this */
786 info->dev_id = device_type_from_device_id(object->device_tag);
787 break;
788 case 5:
789 object_path_v3 = get_bios_object_from_path_v3(bp, connector_object_id);
790
791 if (!object_path_v3) {
792 BREAK_TO_DEBUGGER(); /* Invalid object id */
793 return BP_RESULT_BADINPUT;
794 }
795 info->acpi_device = 0; /* BIOS no longer provides this */
796 info->dev_id = device_type_from_device_id(object_path_v3->device_tag);
797 break;
798 }
799
800 return BP_RESULT_OK;
801 }
802
get_ss_info_v4_1(struct bios_parser * bp,uint32_t id,uint32_t index,struct spread_spectrum_info * ss_info)803 static enum bp_result get_ss_info_v4_1(
804 struct bios_parser *bp,
805 uint32_t id,
806 uint32_t index,
807 struct spread_spectrum_info *ss_info)
808 {
809 enum bp_result result = BP_RESULT_OK;
810 struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
811 struct atom_smu_info_v3_3 *smu_info = NULL;
812
813 if (!ss_info)
814 return BP_RESULT_BADINPUT;
815
816 if (!DATA_TABLES(dce_info))
817 return BP_RESULT_BADBIOSTABLE;
818
819 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,
820 DATA_TABLES(dce_info));
821 if (!disp_cntl_tbl)
822 return BP_RESULT_BADBIOSTABLE;
823
824
825 ss_info->type.STEP_AND_DELAY_INFO = false;
826 ss_info->spread_percentage_divider = 1000;
827 /* BIOS no longer uses target clock. Always enable for now */
828 ss_info->target_clock_range = 0xffffffff;
829
830 switch (id) {
831 case AS_SIGNAL_TYPE_DVI:
832 ss_info->spread_spectrum_percentage =
833 disp_cntl_tbl->dvi_ss_percentage;
834 ss_info->spread_spectrum_range =
835 disp_cntl_tbl->dvi_ss_rate_10hz * 10;
836 if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
837 ss_info->type.CENTER_MODE = true;
838
839 DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
840 break;
841 case AS_SIGNAL_TYPE_HDMI:
842 ss_info->spread_spectrum_percentage =
843 disp_cntl_tbl->hdmi_ss_percentage;
844 ss_info->spread_spectrum_range =
845 disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
846 if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
847 ss_info->type.CENTER_MODE = true;
848
849 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
850 break;
851 /* TODO LVDS not support anymore? */
852 case AS_SIGNAL_TYPE_DISPLAY_PORT:
853 ss_info->spread_spectrum_percentage =
854 disp_cntl_tbl->dp_ss_percentage;
855 ss_info->spread_spectrum_range =
856 disp_cntl_tbl->dp_ss_rate_10hz * 10;
857 if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
858 ss_info->type.CENTER_MODE = true;
859
860 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
861 break;
862 case AS_SIGNAL_TYPE_GPU_PLL:
863 /* atom_firmware: DAL only get data from dce_info table.
864 * if data within smu_info is needed for DAL, VBIOS should
865 * copy it into dce_info
866 */
867 result = BP_RESULT_UNSUPPORTED;
868 break;
869 case AS_SIGNAL_TYPE_XGMI:
870 smu_info = GET_IMAGE(struct atom_smu_info_v3_3,
871 DATA_TABLES(smu_info));
872 if (!smu_info)
873 return BP_RESULT_BADBIOSTABLE;
874 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);
875 ss_info->spread_spectrum_percentage =
876 smu_info->waflclk_ss_percentage;
877 ss_info->spread_spectrum_range =
878 smu_info->gpuclk_ss_rate_10hz * 10;
879 if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
880 ss_info->type.CENTER_MODE = true;
881
882 DC_LOG_BIOS("AS_SIGNAL_TYPE_XGMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
883 break;
884 default:
885 result = BP_RESULT_UNSUPPORTED;
886 }
887
888 return result;
889 }
890
get_ss_info_v4_2(struct bios_parser * bp,uint32_t id,uint32_t index,struct spread_spectrum_info * ss_info)891 static enum bp_result get_ss_info_v4_2(
892 struct bios_parser *bp,
893 uint32_t id,
894 uint32_t index,
895 struct spread_spectrum_info *ss_info)
896 {
897 enum bp_result result = BP_RESULT_OK;
898 struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
899 struct atom_smu_info_v3_1 *smu_info = NULL;
900
901 if (!ss_info)
902 return BP_RESULT_BADINPUT;
903
904 if (!DATA_TABLES(dce_info))
905 return BP_RESULT_BADBIOSTABLE;
906
907 if (!DATA_TABLES(smu_info))
908 return BP_RESULT_BADBIOSTABLE;
909
910 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,
911 DATA_TABLES(dce_info));
912 if (!disp_cntl_tbl)
913 return BP_RESULT_BADBIOSTABLE;
914
915 smu_info = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info));
916 if (!smu_info)
917 return BP_RESULT_BADBIOSTABLE;
918
919 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);
920 ss_info->type.STEP_AND_DELAY_INFO = false;
921 ss_info->spread_percentage_divider = 1000;
922 /* BIOS no longer uses target clock. Always enable for now */
923 ss_info->target_clock_range = 0xffffffff;
924
925 switch (id) {
926 case AS_SIGNAL_TYPE_DVI:
927 ss_info->spread_spectrum_percentage =
928 disp_cntl_tbl->dvi_ss_percentage;
929 ss_info->spread_spectrum_range =
930 disp_cntl_tbl->dvi_ss_rate_10hz * 10;
931 if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
932 ss_info->type.CENTER_MODE = true;
933
934 DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
935 break;
936 case AS_SIGNAL_TYPE_HDMI:
937 ss_info->spread_spectrum_percentage =
938 disp_cntl_tbl->hdmi_ss_percentage;
939 ss_info->spread_spectrum_range =
940 disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
941 if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
942 ss_info->type.CENTER_MODE = true;
943
944 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
945 break;
946 /* TODO LVDS not support anymore? */
947 case AS_SIGNAL_TYPE_DISPLAY_PORT:
948 ss_info->spread_spectrum_percentage =
949 smu_info->gpuclk_ss_percentage;
950 ss_info->spread_spectrum_range =
951 smu_info->gpuclk_ss_rate_10hz * 10;
952 if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
953 ss_info->type.CENTER_MODE = true;
954
955 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
956 break;
957 case AS_SIGNAL_TYPE_GPU_PLL:
958 /* atom_firmware: DAL only get data from dce_info table.
959 * if data within smu_info is needed for DAL, VBIOS should
960 * copy it into dce_info
961 */
962 result = BP_RESULT_UNSUPPORTED;
963 break;
964 default:
965 result = BP_RESULT_UNSUPPORTED;
966 }
967
968 return result;
969 }
970
get_ss_info_v4_5(struct bios_parser * bp,uint32_t id,uint32_t index,struct spread_spectrum_info * ss_info)971 static enum bp_result get_ss_info_v4_5(
972 struct bios_parser *bp,
973 uint32_t id,
974 uint32_t index,
975 struct spread_spectrum_info *ss_info)
976 {
977 enum bp_result result = BP_RESULT_OK;
978 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
979
980 if (!ss_info)
981 return BP_RESULT_BADINPUT;
982
983 if (!DATA_TABLES(dce_info))
984 return BP_RESULT_BADBIOSTABLE;
985
986 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
987 DATA_TABLES(dce_info));
988 if (!disp_cntl_tbl)
989 return BP_RESULT_BADBIOSTABLE;
990
991 ss_info->type.STEP_AND_DELAY_INFO = false;
992 ss_info->spread_percentage_divider = 1000;
993 /* BIOS no longer uses target clock. Always enable for now */
994 ss_info->target_clock_range = 0xffffffff;
995
996 switch (id) {
997 case AS_SIGNAL_TYPE_DVI:
998 ss_info->spread_spectrum_percentage =
999 disp_cntl_tbl->dvi_ss_percentage;
1000 ss_info->spread_spectrum_range =
1001 disp_cntl_tbl->dvi_ss_rate_10hz * 10;
1002 if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1003 ss_info->type.CENTER_MODE = true;
1004
1005 DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1006 break;
1007 case AS_SIGNAL_TYPE_HDMI:
1008 ss_info->spread_spectrum_percentage =
1009 disp_cntl_tbl->hdmi_ss_percentage;
1010 ss_info->spread_spectrum_range =
1011 disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
1012 if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1013 ss_info->type.CENTER_MODE = true;
1014
1015 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1016 break;
1017 case AS_SIGNAL_TYPE_DISPLAY_PORT:
1018 if (bp->base.integrated_info) {
1019 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", bp->base.integrated_info->gpuclk_ss_percentage);
1020 ss_info->spread_spectrum_percentage =
1021 bp->base.integrated_info->gpuclk_ss_percentage;
1022 ss_info->type.CENTER_MODE =
1023 bp->base.integrated_info->gpuclk_ss_type;
1024 } else {
1025 ss_info->spread_spectrum_percentage =
1026 disp_cntl_tbl->dp_ss_percentage;
1027 ss_info->spread_spectrum_range =
1028 disp_cntl_tbl->dp_ss_rate_10hz * 10;
1029 if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1030 ss_info->type.CENTER_MODE = true;
1031 }
1032 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1033 break;
1034 case AS_SIGNAL_TYPE_GPU_PLL:
1035 /* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore.
1036 * SMU Display PLL supposed to be without spread.
1037 * Better place for it would be in atom_display_controller_info_v4_5 table.
1038 */
1039 result = BP_RESULT_UNSUPPORTED;
1040 break;
1041 default:
1042 result = BP_RESULT_UNSUPPORTED;
1043 break;
1044 }
1045
1046 return result;
1047 }
1048
1049 /**
1050 * bios_parser_get_spread_spectrum_info
1051 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
1052 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
1053 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info
1054 * ver 3.1,
1055 * there is only one entry for each signal /ss id. However, there is
1056 * no planning of supporting multiple spread Sprectum entry for EverGreen
1057 * @dcb: pointer to the DC BIOS
1058 * @signal: ASSignalType to be converted to info index
1059 * @index: number of entries that match the converted info index
1060 * @ss_info: sprectrum information structure,
1061 * return: Bios parser result code
1062 */
bios_parser_get_spread_spectrum_info(struct dc_bios * dcb,enum as_signal_type signal,uint32_t index,struct spread_spectrum_info * ss_info)1063 static enum bp_result bios_parser_get_spread_spectrum_info(
1064 struct dc_bios *dcb,
1065 enum as_signal_type signal,
1066 uint32_t index,
1067 struct spread_spectrum_info *ss_info)
1068 {
1069 struct bios_parser *bp = BP_FROM_DCB(dcb);
1070 enum bp_result result = BP_RESULT_UNSUPPORTED;
1071 struct atom_common_table_header *header;
1072 struct atom_data_revision tbl_revision;
1073
1074 if (!ss_info) /* check for bad input */
1075 return BP_RESULT_BADINPUT;
1076
1077 if (!DATA_TABLES(dce_info))
1078 return BP_RESULT_UNSUPPORTED;
1079
1080 header = GET_IMAGE(struct atom_common_table_header,
1081 DATA_TABLES(dce_info));
1082 get_atom_data_table_revision(header, &tbl_revision);
1083
1084 switch (tbl_revision.major) {
1085 case 4:
1086 switch (tbl_revision.minor) {
1087 case 1:
1088 return get_ss_info_v4_1(bp, signal, index, ss_info);
1089 case 2:
1090 case 3:
1091 case 4:
1092 return get_ss_info_v4_2(bp, signal, index, ss_info);
1093 case 5:
1094 return get_ss_info_v4_5(bp, signal, index, ss_info);
1095
1096 default:
1097 ASSERT(0);
1098 break;
1099 }
1100 break;
1101 default:
1102 break;
1103 }
1104 /* there can not be more then one entry for SS Info table */
1105 return result;
1106 }
1107
get_soc_bb_info_v4_4(struct bios_parser * bp,struct bp_soc_bb_info * soc_bb_info)1108 static enum bp_result get_soc_bb_info_v4_4(
1109 struct bios_parser *bp,
1110 struct bp_soc_bb_info *soc_bb_info)
1111 {
1112 enum bp_result result = BP_RESULT_OK;
1113 struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1114
1115 if (!soc_bb_info)
1116 return BP_RESULT_BADINPUT;
1117
1118 if (!DATA_TABLES(dce_info))
1119 return BP_RESULT_BADBIOSTABLE;
1120
1121 if (!DATA_TABLES(smu_info))
1122 return BP_RESULT_BADBIOSTABLE;
1123
1124 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
1125 DATA_TABLES(dce_info));
1126 if (!disp_cntl_tbl)
1127 return BP_RESULT_BADBIOSTABLE;
1128
1129 soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1130 soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1131 soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1132
1133 return result;
1134 }
1135
get_soc_bb_info_v4_5(struct bios_parser * bp,struct bp_soc_bb_info * soc_bb_info)1136 static enum bp_result get_soc_bb_info_v4_5(
1137 struct bios_parser *bp,
1138 struct bp_soc_bb_info *soc_bb_info)
1139 {
1140 enum bp_result result = BP_RESULT_OK;
1141 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1142
1143 if (!soc_bb_info)
1144 return BP_RESULT_BADINPUT;
1145
1146 if (!DATA_TABLES(dce_info))
1147 return BP_RESULT_BADBIOSTABLE;
1148
1149 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
1150 DATA_TABLES(dce_info));
1151 if (!disp_cntl_tbl)
1152 return BP_RESULT_BADBIOSTABLE;
1153
1154 soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1155 soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1156 soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1157
1158 return result;
1159 }
1160
bios_parser_get_soc_bb_info(struct dc_bios * dcb,struct bp_soc_bb_info * soc_bb_info)1161 static enum bp_result bios_parser_get_soc_bb_info(
1162 struct dc_bios *dcb,
1163 struct bp_soc_bb_info *soc_bb_info)
1164 {
1165 struct bios_parser *bp = BP_FROM_DCB(dcb);
1166 enum bp_result result = BP_RESULT_UNSUPPORTED;
1167 struct atom_common_table_header *header;
1168 struct atom_data_revision tbl_revision;
1169
1170 if (!soc_bb_info) /* check for bad input */
1171 return BP_RESULT_BADINPUT;
1172
1173 if (!DATA_TABLES(dce_info))
1174 return BP_RESULT_UNSUPPORTED;
1175
1176 header = GET_IMAGE(struct atom_common_table_header,
1177 DATA_TABLES(dce_info));
1178 get_atom_data_table_revision(header, &tbl_revision);
1179
1180 switch (tbl_revision.major) {
1181 case 4:
1182 switch (tbl_revision.minor) {
1183 case 1:
1184 case 2:
1185 case 3:
1186 break;
1187 case 4:
1188 result = get_soc_bb_info_v4_4(bp, soc_bb_info);
1189 break;
1190 case 5:
1191 result = get_soc_bb_info_v4_5(bp, soc_bb_info);
1192 break;
1193 default:
1194 break;
1195 }
1196 break;
1197 default:
1198 break;
1199 }
1200
1201 return result;
1202 }
1203
get_disp_caps_v4_1(struct bios_parser * bp,uint8_t * dce_caps)1204 static enum bp_result get_disp_caps_v4_1(
1205 struct bios_parser *bp,
1206 uint8_t *dce_caps)
1207 {
1208 enum bp_result result = BP_RESULT_OK;
1209 struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
1210
1211 if (!dce_caps)
1212 return BP_RESULT_BADINPUT;
1213
1214 if (!DATA_TABLES(dce_info))
1215 return BP_RESULT_BADBIOSTABLE;
1216
1217 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,
1218 DATA_TABLES(dce_info));
1219
1220 if (!disp_cntl_tbl)
1221 return BP_RESULT_BADBIOSTABLE;
1222
1223 *dce_caps = disp_cntl_tbl->display_caps;
1224
1225 return result;
1226 }
1227
get_disp_caps_v4_2(struct bios_parser * bp,uint8_t * dce_caps)1228 static enum bp_result get_disp_caps_v4_2(
1229 struct bios_parser *bp,
1230 uint8_t *dce_caps)
1231 {
1232 enum bp_result result = BP_RESULT_OK;
1233 struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
1234
1235 if (!dce_caps)
1236 return BP_RESULT_BADINPUT;
1237
1238 if (!DATA_TABLES(dce_info))
1239 return BP_RESULT_BADBIOSTABLE;
1240
1241 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,
1242 DATA_TABLES(dce_info));
1243
1244 if (!disp_cntl_tbl)
1245 return BP_RESULT_BADBIOSTABLE;
1246
1247 *dce_caps = disp_cntl_tbl->display_caps;
1248
1249 return result;
1250 }
1251
get_disp_caps_v4_3(struct bios_parser * bp,uint8_t * dce_caps)1252 static enum bp_result get_disp_caps_v4_3(
1253 struct bios_parser *bp,
1254 uint8_t *dce_caps)
1255 {
1256 enum bp_result result = BP_RESULT_OK;
1257 struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL;
1258
1259 if (!dce_caps)
1260 return BP_RESULT_BADINPUT;
1261
1262 if (!DATA_TABLES(dce_info))
1263 return BP_RESULT_BADBIOSTABLE;
1264
1265 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3,
1266 DATA_TABLES(dce_info));
1267
1268 if (!disp_cntl_tbl)
1269 return BP_RESULT_BADBIOSTABLE;
1270
1271 *dce_caps = disp_cntl_tbl->display_caps;
1272
1273 return result;
1274 }
1275
get_disp_caps_v4_4(struct bios_parser * bp,uint8_t * dce_caps)1276 static enum bp_result get_disp_caps_v4_4(
1277 struct bios_parser *bp,
1278 uint8_t *dce_caps)
1279 {
1280 enum bp_result result = BP_RESULT_OK;
1281 struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1282
1283 if (!dce_caps)
1284 return BP_RESULT_BADINPUT;
1285
1286 if (!DATA_TABLES(dce_info))
1287 return BP_RESULT_BADBIOSTABLE;
1288
1289 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
1290 DATA_TABLES(dce_info));
1291
1292 if (!disp_cntl_tbl)
1293 return BP_RESULT_BADBIOSTABLE;
1294
1295 *dce_caps = disp_cntl_tbl->display_caps;
1296
1297 return result;
1298 }
1299
get_disp_caps_v4_5(struct bios_parser * bp,uint8_t * dce_caps)1300 static enum bp_result get_disp_caps_v4_5(
1301 struct bios_parser *bp,
1302 uint8_t *dce_caps)
1303 {
1304 enum bp_result result = BP_RESULT_OK;
1305 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1306
1307 if (!dce_caps)
1308 return BP_RESULT_BADINPUT;
1309
1310 if (!DATA_TABLES(dce_info))
1311 return BP_RESULT_BADBIOSTABLE;
1312
1313 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
1314 DATA_TABLES(dce_info));
1315
1316 if (!disp_cntl_tbl)
1317 return BP_RESULT_BADBIOSTABLE;
1318
1319 *dce_caps = disp_cntl_tbl->display_caps;
1320
1321 return result;
1322 }
1323
bios_parser_get_lttpr_interop(struct dc_bios * dcb,uint8_t * dce_caps)1324 static enum bp_result bios_parser_get_lttpr_interop(
1325 struct dc_bios *dcb,
1326 uint8_t *dce_caps)
1327 {
1328 struct bios_parser *bp = BP_FROM_DCB(dcb);
1329 enum bp_result result = BP_RESULT_UNSUPPORTED;
1330 struct atom_common_table_header *header;
1331 struct atom_data_revision tbl_revision;
1332
1333 if (!DATA_TABLES(dce_info))
1334 return BP_RESULT_UNSUPPORTED;
1335
1336 header = GET_IMAGE(struct atom_common_table_header,
1337 DATA_TABLES(dce_info));
1338 get_atom_data_table_revision(header, &tbl_revision);
1339 switch (tbl_revision.major) {
1340 case 4:
1341 switch (tbl_revision.minor) {
1342 case 1:
1343 result = get_disp_caps_v4_1(bp, dce_caps);
1344 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1345 break;
1346 case 2:
1347 result = get_disp_caps_v4_2(bp, dce_caps);
1348 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1349 break;
1350 case 3:
1351 result = get_disp_caps_v4_3(bp, dce_caps);
1352 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1353 break;
1354 case 4:
1355 result = get_disp_caps_v4_4(bp, dce_caps);
1356 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1357 break;
1358 case 5:
1359 result = get_disp_caps_v4_5(bp, dce_caps);
1360 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1361 break;
1362
1363 default:
1364 break;
1365 }
1366 break;
1367 default:
1368 break;
1369 }
1370 DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
1371 return result;
1372 }
1373
bios_parser_get_lttpr_caps(struct dc_bios * dcb,uint8_t * dce_caps)1374 static enum bp_result bios_parser_get_lttpr_caps(
1375 struct dc_bios *dcb,
1376 uint8_t *dce_caps)
1377 {
1378 struct bios_parser *bp = BP_FROM_DCB(dcb);
1379 enum bp_result result = BP_RESULT_UNSUPPORTED;
1380 struct atom_common_table_header *header;
1381 struct atom_data_revision tbl_revision;
1382
1383 if (!DATA_TABLES(dce_info))
1384 return BP_RESULT_UNSUPPORTED;
1385
1386 *dce_caps = 0;
1387 header = GET_IMAGE(struct atom_common_table_header,
1388 DATA_TABLES(dce_info));
1389 get_atom_data_table_revision(header, &tbl_revision);
1390 switch (tbl_revision.major) {
1391 case 4:
1392 switch (tbl_revision.minor) {
1393 case 1:
1394 result = get_disp_caps_v4_1(bp, dce_caps);
1395 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1396 break;
1397 case 2:
1398 result = get_disp_caps_v4_2(bp, dce_caps);
1399 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1400 break;
1401 case 3:
1402 result = get_disp_caps_v4_3(bp, dce_caps);
1403 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1404 break;
1405 case 4:
1406 result = get_disp_caps_v4_4(bp, dce_caps);
1407 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1408 break;
1409 case 5:
1410 result = get_disp_caps_v4_5(bp, dce_caps);
1411 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1412 break;
1413 default:
1414 break;
1415 }
1416 break;
1417 default:
1418 break;
1419 }
1420 DC_LOG_BIOS("DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
1421 if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) {
1422 *dce_caps = 1;
1423 DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled");
1424 }
1425 return result;
1426 }
1427
get_embedded_panel_info_v2_1(struct bios_parser * bp,struct embedded_panel_info * info)1428 static enum bp_result get_embedded_panel_info_v2_1(
1429 struct bios_parser *bp,
1430 struct embedded_panel_info *info)
1431 {
1432 struct lcd_info_v2_1 *lvds;
1433
1434 if (!info)
1435 return BP_RESULT_BADINPUT;
1436
1437 if (!DATA_TABLES(lcd_info))
1438 return BP_RESULT_UNSUPPORTED;
1439
1440 lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));
1441
1442 if (!lvds)
1443 return BP_RESULT_BADBIOSTABLE;
1444
1445 /* TODO: previous vv1_3, should v2_1 */
1446 if (!((lvds->table_header.format_revision == 2)
1447 && (lvds->table_header.content_revision >= 1)))
1448 return BP_RESULT_UNSUPPORTED;
1449
1450 memset(info, 0, sizeof(struct embedded_panel_info));
1451
1452 /* We need to convert from 10KHz units into KHz units */
1453 info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
1454 /* usHActive does not include borders, according to VBIOS team */
1455 info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);
1456 /* usHBlanking_Time includes borders, so we should really be
1457 * subtractingborders duing this translation, but LVDS generally
1458 * doesn't have borders, so we should be okay leaving this as is for
1459 * now. May need to revisit if we ever have LVDS with borders
1460 */
1461 info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);
1462 /* usVActive does not include borders, according to VBIOS team*/
1463 info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);
1464 /* usVBlanking_Time includes borders, so we should really be
1465 * subtracting borders duing this translation, but LVDS generally
1466 * doesn't have borders, so we should be okay leaving this as is for
1467 * now. May need to revisit if we ever have LVDS with borders
1468 */
1469 info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);
1470 info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);
1471 info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);
1472 info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);
1473 info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);
1474 info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
1475 info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
1476
1477 /* not provided by VBIOS */
1478 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
1479
1480 info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
1481 & ATOM_HSYNC_POLARITY);
1482 info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
1483 & ATOM_VSYNC_POLARITY);
1484
1485 /* not provided by VBIOS */
1486 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
1487
1488 info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1489 & ATOM_H_REPLICATIONBY2);
1490 info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1491 & ATOM_V_REPLICATIONBY2);
1492 info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo
1493 & ATOM_COMPOSITESYNC);
1494 info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
1495
1496 /* not provided by VBIOS*/
1497 info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
1498 /* not provided by VBIOS*/
1499 info->ss_id = 0;
1500
1501 info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
1502
1503 return BP_RESULT_OK;
1504 }
1505
bios_parser_get_embedded_panel_info(struct dc_bios * dcb,struct embedded_panel_info * info)1506 static enum bp_result bios_parser_get_embedded_panel_info(
1507 struct dc_bios *dcb,
1508 struct embedded_panel_info *info)
1509 {
1510 struct bios_parser
1511 *bp = BP_FROM_DCB(dcb);
1512 struct atom_common_table_header *header;
1513 struct atom_data_revision tbl_revision;
1514
1515 if (!DATA_TABLES(lcd_info))
1516 return BP_RESULT_FAILURE;
1517
1518 header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));
1519
1520 if (!header)
1521 return BP_RESULT_BADBIOSTABLE;
1522
1523 get_atom_data_table_revision(header, &tbl_revision);
1524
1525 switch (tbl_revision.major) {
1526 case 2:
1527 switch (tbl_revision.minor) {
1528 case 1:
1529 return get_embedded_panel_info_v2_1(bp, info);
1530 default:
1531 break;
1532 }
1533 break;
1534 default:
1535 break;
1536 }
1537
1538 return BP_RESULT_FAILURE;
1539 }
1540
get_support_mask_for_device_id(struct device_id device_id)1541 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
1542 {
1543 enum dal_device_type device_type = device_id.device_type;
1544 uint32_t enum_id = device_id.enum_id;
1545
1546 switch (device_type) {
1547 case DEVICE_TYPE_LCD:
1548 switch (enum_id) {
1549 case 1:
1550 return ATOM_DISPLAY_LCD1_SUPPORT;
1551 default:
1552 break;
1553 }
1554 break;
1555 case DEVICE_TYPE_DFP:
1556 switch (enum_id) {
1557 case 1:
1558 return ATOM_DISPLAY_DFP1_SUPPORT;
1559 case 2:
1560 return ATOM_DISPLAY_DFP2_SUPPORT;
1561 case 3:
1562 return ATOM_DISPLAY_DFP3_SUPPORT;
1563 case 4:
1564 return ATOM_DISPLAY_DFP4_SUPPORT;
1565 case 5:
1566 return ATOM_DISPLAY_DFP5_SUPPORT;
1567 case 6:
1568 return ATOM_DISPLAY_DFP6_SUPPORT;
1569 default:
1570 break;
1571 }
1572 break;
1573 default:
1574 break;
1575 }
1576
1577 /* Unidentified device ID, return empty support mask. */
1578 return 0;
1579 }
1580
bios_parser_is_device_id_supported(struct dc_bios * dcb,struct device_id id)1581 static bool bios_parser_is_device_id_supported(
1582 struct dc_bios *dcb,
1583 struct device_id id)
1584 {
1585 struct bios_parser *bp = BP_FROM_DCB(dcb);
1586
1587 uint32_t mask = get_support_mask_for_device_id(id);
1588
1589 switch (bp->object_info_tbl.revision.minor) {
1590 case 4:
1591 default:
1592 return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & mask) != 0;
1593 break;
1594 case 5:
1595 return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0;
1596 break;
1597 }
1598
1599 return false;
1600 }
1601
bios_parser_get_ss_entry_number(struct dc_bios * dcb,enum as_signal_type signal)1602 static uint32_t bios_parser_get_ss_entry_number(
1603 struct dc_bios *dcb,
1604 enum as_signal_type signal)
1605 {
1606 /* TODO: DAL2 atomfirmware implementation does not need this.
1607 * why DAL3 need this?
1608 */
1609 return 1;
1610 }
1611
bios_parser_transmitter_control(struct dc_bios * dcb,struct bp_transmitter_control * cntl)1612 static enum bp_result bios_parser_transmitter_control(
1613 struct dc_bios *dcb,
1614 struct bp_transmitter_control *cntl)
1615 {
1616 struct bios_parser *bp = BP_FROM_DCB(dcb);
1617
1618 if (!bp->cmd_tbl.transmitter_control)
1619 return BP_RESULT_FAILURE;
1620
1621 return bp->cmd_tbl.transmitter_control(bp, cntl);
1622 }
1623
bios_parser_encoder_control(struct dc_bios * dcb,struct bp_encoder_control * cntl)1624 static enum bp_result bios_parser_encoder_control(
1625 struct dc_bios *dcb,
1626 struct bp_encoder_control *cntl)
1627 {
1628 struct bios_parser *bp = BP_FROM_DCB(dcb);
1629
1630 if (!bp->cmd_tbl.dig_encoder_control)
1631 return BP_RESULT_FAILURE;
1632
1633 return bp->cmd_tbl.dig_encoder_control(bp, cntl);
1634 }
1635
bios_parser_set_pixel_clock(struct dc_bios * dcb,struct bp_pixel_clock_parameters * bp_params)1636 static enum bp_result bios_parser_set_pixel_clock(
1637 struct dc_bios *dcb,
1638 struct bp_pixel_clock_parameters *bp_params)
1639 {
1640 struct bios_parser *bp = BP_FROM_DCB(dcb);
1641
1642 if (!bp->cmd_tbl.set_pixel_clock)
1643 return BP_RESULT_FAILURE;
1644
1645 return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
1646 }
1647
bios_parser_set_dce_clock(struct dc_bios * dcb,struct bp_set_dce_clock_parameters * bp_params)1648 static enum bp_result bios_parser_set_dce_clock(
1649 struct dc_bios *dcb,
1650 struct bp_set_dce_clock_parameters *bp_params)
1651 {
1652 struct bios_parser *bp = BP_FROM_DCB(dcb);
1653
1654 if (!bp->cmd_tbl.set_dce_clock)
1655 return BP_RESULT_FAILURE;
1656
1657 return bp->cmd_tbl.set_dce_clock(bp, bp_params);
1658 }
1659
bios_parser_program_crtc_timing(struct dc_bios * dcb,struct bp_hw_crtc_timing_parameters * bp_params)1660 static enum bp_result bios_parser_program_crtc_timing(
1661 struct dc_bios *dcb,
1662 struct bp_hw_crtc_timing_parameters *bp_params)
1663 {
1664 struct bios_parser *bp = BP_FROM_DCB(dcb);
1665
1666 if (!bp->cmd_tbl.set_crtc_timing)
1667 return BP_RESULT_FAILURE;
1668
1669 return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
1670 }
1671
bios_parser_enable_crtc(struct dc_bios * dcb,enum controller_id id,bool enable)1672 static enum bp_result bios_parser_enable_crtc(
1673 struct dc_bios *dcb,
1674 enum controller_id id,
1675 bool enable)
1676 {
1677 struct bios_parser *bp = BP_FROM_DCB(dcb);
1678
1679 if (!bp->cmd_tbl.enable_crtc)
1680 return BP_RESULT_FAILURE;
1681
1682 return bp->cmd_tbl.enable_crtc(bp, id, enable);
1683 }
1684
bios_parser_enable_disp_power_gating(struct dc_bios * dcb,enum controller_id controller_id,enum bp_pipe_control_action action)1685 static enum bp_result bios_parser_enable_disp_power_gating(
1686 struct dc_bios *dcb,
1687 enum controller_id controller_id,
1688 enum bp_pipe_control_action action)
1689 {
1690 struct bios_parser *bp = BP_FROM_DCB(dcb);
1691
1692 if (!bp->cmd_tbl.enable_disp_power_gating)
1693 return BP_RESULT_FAILURE;
1694
1695 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
1696 action);
1697 }
1698
bios_parser_enable_lvtma_control(struct dc_bios * dcb,uint8_t uc_pwr_on,uint8_t pwrseq_instance,uint8_t bypass_panel_control_wait)1699 static enum bp_result bios_parser_enable_lvtma_control(
1700 struct dc_bios *dcb,
1701 uint8_t uc_pwr_on,
1702 uint8_t pwrseq_instance,
1703 uint8_t bypass_panel_control_wait)
1704 {
1705 struct bios_parser *bp = BP_FROM_DCB(dcb);
1706
1707 if (!bp->cmd_tbl.enable_lvtma_control)
1708 return BP_RESULT_FAILURE;
1709
1710 return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on, pwrseq_instance, bypass_panel_control_wait);
1711 }
1712
bios_parser_is_accelerated_mode(struct dc_bios * dcb)1713 static bool bios_parser_is_accelerated_mode(
1714 struct dc_bios *dcb)
1715 {
1716 return bios_is_accelerated_mode(dcb);
1717 }
1718
1719 /**
1720 * bios_parser_set_scratch_critical_state - update critical state bit
1721 * in VBIOS scratch register
1722 *
1723 * @dcb: pointer to the DC BIO
1724 * @state: set or reset state
1725 */
bios_parser_set_scratch_critical_state(struct dc_bios * dcb,bool state)1726 static void bios_parser_set_scratch_critical_state(
1727 struct dc_bios *dcb,
1728 bool state)
1729 {
1730 bios_set_scratch_critical_state(dcb, state);
1731 }
1732
1733 struct atom_dig_transmitter_info_header_v5_3 {
1734 struct atom_common_table_header table_header;
1735 uint16_t dpphy_hdmi_settings_offset;
1736 uint16_t dpphy_dvi_settings_offset;
1737 uint16_t dpphy_dp_setting_table_offset;
1738 uint16_t uniphy_xbar_settings_v2_table_offset;
1739 uint16_t dpphy_internal_reg_overide_offset;
1740 };
1741
bios_parser_get_firmware_info(struct dc_bios * dcb,struct dc_firmware_info * info)1742 static enum bp_result bios_parser_get_firmware_info(
1743 struct dc_bios *dcb,
1744 struct dc_firmware_info *info)
1745 {
1746 struct bios_parser *bp = BP_FROM_DCB(dcb);
1747 static enum bp_result result = BP_RESULT_BADBIOSTABLE;
1748 struct atom_common_table_header *header;
1749
1750 struct atom_data_revision revision;
1751
1752 if (info && DATA_TABLES(firmwareinfo)) {
1753 header = GET_IMAGE(struct atom_common_table_header,
1754 DATA_TABLES(firmwareinfo));
1755 get_atom_data_table_revision(header, &revision);
1756 switch (revision.major) {
1757 case 3:
1758 switch (revision.minor) {
1759 case 1:
1760 result = get_firmware_info_v3_1(bp, info);
1761 break;
1762 case 2:
1763 case 3:
1764 result = get_firmware_info_v3_2(bp, info);
1765 break;
1766 case 4:
1767 result = get_firmware_info_v3_4(bp, info);
1768 break;
1769 default:
1770 break;
1771 }
1772 break;
1773 default:
1774 break;
1775 }
1776 }
1777
1778 return result;
1779 }
1780
get_firmware_info_v3_1(struct bios_parser * bp,struct dc_firmware_info * info)1781 static enum bp_result get_firmware_info_v3_1(
1782 struct bios_parser *bp,
1783 struct dc_firmware_info *info)
1784 {
1785 struct atom_firmware_info_v3_1 *firmware_info;
1786 struct atom_display_controller_info_v4_1 *dce_info = NULL;
1787
1788 if (!info)
1789 return BP_RESULT_BADINPUT;
1790
1791 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,
1792 DATA_TABLES(firmwareinfo));
1793
1794 dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1795 DATA_TABLES(dce_info));
1796
1797 if (!firmware_info || !dce_info)
1798 return BP_RESULT_BADBIOSTABLE;
1799
1800 memset(info, 0, sizeof(*info));
1801
1802 /* Pixel clock pll information. */
1803 /* We need to convert from 10KHz units into KHz units */
1804 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1805 info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;
1806
1807 /* 27MHz for Vega10: */
1808 info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1809
1810 /* Hardcode frequency if BIOS gives no DCE Ref Clk */
1811 if (info->pll_info.crystal_frequency == 0)
1812 info->pll_info.crystal_frequency = 27000;
1813 /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1814 info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10;
1815 info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1816
1817 /* Get GPU PLL VCO Clock */
1818
1819 if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1820 /* VBIOS gives in 10KHz */
1821 info->smu_gpu_pll_output_freq =
1822 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1823 }
1824
1825 info->oem_i2c_present = false;
1826
1827 return BP_RESULT_OK;
1828 }
1829
get_firmware_info_v3_2(struct bios_parser * bp,struct dc_firmware_info * info)1830 static enum bp_result get_firmware_info_v3_2(
1831 struct bios_parser *bp,
1832 struct dc_firmware_info *info)
1833 {
1834 struct atom_firmware_info_v3_2 *firmware_info;
1835 struct atom_display_controller_info_v4_1 *dce_info = NULL;
1836 struct atom_common_table_header *header;
1837 struct atom_data_revision revision;
1838 struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;
1839 struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;
1840
1841 if (!info)
1842 return BP_RESULT_BADINPUT;
1843
1844 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,
1845 DATA_TABLES(firmwareinfo));
1846
1847 dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1848 DATA_TABLES(dce_info));
1849
1850 if (!firmware_info || !dce_info)
1851 return BP_RESULT_BADBIOSTABLE;
1852
1853 memset(info, 0, sizeof(*info));
1854
1855 header = GET_IMAGE(struct atom_common_table_header,
1856 DATA_TABLES(smu_info));
1857 get_atom_data_table_revision(header, &revision);
1858
1859 if (revision.minor == 2) {
1860 /* Vega12 */
1861 smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
1862 DATA_TABLES(smu_info));
1863 if (!smu_info_v3_2)
1864 return BP_RESULT_BADBIOSTABLE;
1865
1866 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
1867
1868 info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
1869 } else if (revision.minor == 3) {
1870 /* Vega20 */
1871 smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
1872 DATA_TABLES(smu_info));
1873 if (!smu_info_v3_3)
1874 return BP_RESULT_BADBIOSTABLE;
1875
1876 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
1877
1878 info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
1879 }
1880
1881 // We need to convert from 10KHz units into KHz units.
1882 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1883
1884 /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */
1885 info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1886 /* Hardcode frequency if BIOS gives no DCE Ref Clk */
1887 if (info->pll_info.crystal_frequency == 0) {
1888 if (revision.minor == 2)
1889 info->pll_info.crystal_frequency = 27000;
1890 else if (revision.minor == 3)
1891 info->pll_info.crystal_frequency = 100000;
1892 }
1893 /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1894 info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10;
1895 info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1896
1897 /* Get GPU PLL VCO Clock */
1898 if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1899 if (revision.minor == 2)
1900 info->smu_gpu_pll_output_freq =
1901 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1902 else if (revision.minor == 3)
1903 info->smu_gpu_pll_output_freq =
1904 bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
1905 }
1906
1907 if (firmware_info->board_i2c_feature_id == 0x2) {
1908 info->oem_i2c_present = true;
1909 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
1910 } else {
1911 info->oem_i2c_present = false;
1912 }
1913
1914 return BP_RESULT_OK;
1915 }
1916
get_firmware_info_v3_4(struct bios_parser * bp,struct dc_firmware_info * info)1917 static enum bp_result get_firmware_info_v3_4(
1918 struct bios_parser *bp,
1919 struct dc_firmware_info *info)
1920 {
1921 struct atom_firmware_info_v3_4 *firmware_info;
1922 struct atom_common_table_header *header;
1923 struct atom_data_revision revision;
1924 struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
1925 struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
1926
1927 struct atom_smu_info_v3_5 *smu_info_v3_5 = NULL;
1928 struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;
1929 struct atom_smu_info_v4_0 *smu_info_v4_0 = NULL;
1930
1931 if (!info)
1932 return BP_RESULT_BADINPUT;
1933
1934 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
1935 DATA_TABLES(firmwareinfo));
1936
1937 if (!firmware_info)
1938 return BP_RESULT_BADBIOSTABLE;
1939
1940 memset(info, 0, sizeof(*info));
1941
1942 header = GET_IMAGE(struct atom_common_table_header,
1943 DATA_TABLES(dce_info));
1944
1945 get_atom_data_table_revision(header, &revision);
1946
1947 switch (revision.major) {
1948 case 4:
1949 switch (revision.minor) {
1950 case 5:
1951 dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,
1952 DATA_TABLES(dce_info));
1953
1954 if (!dce_info_v4_5)
1955 return BP_RESULT_BADBIOSTABLE;
1956
1957 /* 100MHz expected */
1958 info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;
1959 info->dp_phy_ref_clk = dce_info_v4_5->dpphy_refclk_10khz * 10;
1960 /* 50MHz expected */
1961 info->i2c_engine_ref_clk = dce_info_v4_5->i2c_engine_refclk_10khz * 10;
1962
1963 /* For DCN32/321 Display PLL VCO Frequency from dce_info_v4_5 may not be reliable */
1964 break;
1965
1966 case 4:
1967 dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
1968 DATA_TABLES(dce_info));
1969
1970 if (!dce_info_v4_4)
1971 return BP_RESULT_BADBIOSTABLE;
1972
1973 /* 100MHz expected */
1974 info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
1975 info->dp_phy_ref_clk = dce_info_v4_4->dpphy_refclk_10khz * 10;
1976 /* 50MHz expected */
1977 info->i2c_engine_ref_clk = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
1978
1979 /* Get SMU Display PLL VCO Frequency in KHz*/
1980 info->smu_gpu_pll_output_freq = dce_info_v4_4->dispclk_pll_vco_freq * 10;
1981 break;
1982
1983 default:
1984 /* should not come here, keep as backup, as was before */
1985 dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
1986 DATA_TABLES(dce_info));
1987
1988 if (!dce_info_v4_1)
1989 return BP_RESULT_BADBIOSTABLE;
1990
1991 info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
1992 info->dp_phy_ref_clk = dce_info_v4_1->dpphy_refclk_10khz * 10;
1993 info->i2c_engine_ref_clk = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
1994 break;
1995 }
1996 break;
1997
1998 default:
1999 ASSERT(0);
2000 break;
2001 }
2002
2003 header = GET_IMAGE(struct atom_common_table_header,
2004 DATA_TABLES(smu_info));
2005 get_atom_data_table_revision(header, &revision);
2006
2007 switch (revision.major) {
2008 case 3:
2009 switch (revision.minor) {
2010 case 5:
2011 smu_info_v3_5 = GET_IMAGE(struct atom_smu_info_v3_5,
2012 DATA_TABLES(smu_info));
2013
2014 if (!smu_info_v3_5)
2015 return BP_RESULT_BADBIOSTABLE;
2016 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_5->gpuclk_ss_percentage);
2017 info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10;
2018 break;
2019
2020 default:
2021 break;
2022 }
2023 break;
2024
2025 case 4:
2026 switch (revision.minor) {
2027 case 0:
2028 smu_info_v4_0 = GET_IMAGE(struct atom_smu_info_v4_0,
2029 DATA_TABLES(smu_info));
2030
2031 if (!smu_info_v4_0)
2032 return BP_RESULT_BADBIOSTABLE;
2033
2034 /* For DCN32/321 bootup DCFCLK from smu_info_v4_0 may not be reliable */
2035 break;
2036
2037 default:
2038 break;
2039 }
2040 break;
2041
2042 default:
2043 break;
2044 }
2045
2046 // We need to convert from 10KHz units into KHz units.
2047 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
2048
2049 if (firmware_info->board_i2c_feature_id == 0x2) {
2050 info->oem_i2c_present = true;
2051 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
2052 } else {
2053 info->oem_i2c_present = false;
2054 }
2055
2056 return BP_RESULT_OK;
2057 }
2058
bios_parser_get_encoder_cap_info(struct dc_bios * dcb,struct graphics_object_id object_id,struct bp_encoder_cap_info * info)2059 static enum bp_result bios_parser_get_encoder_cap_info(
2060 struct dc_bios *dcb,
2061 struct graphics_object_id object_id,
2062 struct bp_encoder_cap_info *info)
2063 {
2064 struct bios_parser *bp = BP_FROM_DCB(dcb);
2065 struct atom_display_object_path_v2 *object;
2066 struct atom_encoder_caps_record *record = NULL;
2067
2068 if (!info)
2069 return BP_RESULT_BADINPUT;
2070
2071 #if defined(CONFIG_DRM_AMD_DC_FP)
2072 /* encoder cap record not available in v1_5 */
2073 if (bp->object_info_tbl.revision.minor == 5)
2074 return BP_RESULT_NORECORD;
2075 #endif
2076
2077 object = get_bios_object(bp, object_id);
2078
2079 if (!object)
2080 return BP_RESULT_BADINPUT;
2081
2082 record = get_encoder_cap_record(bp, object);
2083 if (!record)
2084 return BP_RESULT_NORECORD;
2085 DC_LOG_BIOS("record->encodercaps 0x%x for object_id 0x%x", record->encodercaps, object_id.id);
2086
2087 info->DP_HBR2_CAP = (record->encodercaps &
2088 ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
2089 info->DP_HBR2_EN = (record->encodercaps &
2090 ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
2091 info->DP_HBR3_EN = (record->encodercaps &
2092 ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
2093 info->HDMI_6GB_EN = (record->encodercaps &
2094 ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
2095 info->IS_DP2_CAPABLE = (record->encodercaps &
2096 ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
2097 info->DP_UHBR10_EN = (record->encodercaps &
2098 ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
2099 info->DP_UHBR13_5_EN = (record->encodercaps &
2100 ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
2101 info->DP_UHBR20_EN = (record->encodercaps &
2102 ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
2103 info->DP_IS_USB_C = (record->encodercaps &
2104 ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
2105 DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);
2106
2107 return BP_RESULT_OK;
2108 }
2109
2110
get_encoder_cap_record(struct bios_parser * bp,struct atom_display_object_path_v2 * object)2111 static struct atom_encoder_caps_record *get_encoder_cap_record(
2112 struct bios_parser *bp,
2113 struct atom_display_object_path_v2 *object)
2114 {
2115 struct atom_common_record_header *header;
2116 uint32_t offset;
2117
2118 if (!object) {
2119 BREAK_TO_DEBUGGER(); /* Invalid object */
2120 return NULL;
2121 }
2122
2123 offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
2124
2125 for (;;) {
2126 header = GET_IMAGE(struct atom_common_record_header, offset);
2127
2128 if (!header)
2129 return NULL;
2130
2131 offset += header->record_size;
2132
2133 if (header->record_type == LAST_RECORD_TYPE ||
2134 !header->record_size)
2135 break;
2136
2137 if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
2138 continue;
2139
2140 if (sizeof(struct atom_encoder_caps_record) <=
2141 header->record_size)
2142 return (struct atom_encoder_caps_record *)header;
2143 }
2144
2145 return NULL;
2146 }
2147
get_disp_connector_caps_record(struct bios_parser * bp,struct atom_display_object_path_v2 * object)2148 static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
2149 struct bios_parser *bp,
2150 struct atom_display_object_path_v2 *object)
2151 {
2152 struct atom_common_record_header *header;
2153 uint32_t offset;
2154
2155 if (!object) {
2156 BREAK_TO_DEBUGGER(); /* Invalid object */
2157 return NULL;
2158 }
2159
2160 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2161
2162 for (;;) {
2163 header = GET_IMAGE(struct atom_common_record_header, offset);
2164
2165 if (!header)
2166 return NULL;
2167
2168 offset += header->record_size;
2169
2170 if (header->record_type == LAST_RECORD_TYPE ||
2171 !header->record_size)
2172 break;
2173
2174 if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
2175 continue;
2176
2177 if (sizeof(struct atom_disp_connector_caps_record) <=
2178 header->record_size)
2179 return (struct atom_disp_connector_caps_record *)header;
2180 }
2181
2182 return NULL;
2183 }
2184
get_connector_caps_record(struct bios_parser * bp,struct atom_display_object_path_v3 * object)2185 static struct atom_connector_caps_record *get_connector_caps_record(struct bios_parser *bp,
2186 struct atom_display_object_path_v3 *object)
2187 {
2188 struct atom_common_record_header *header;
2189 uint32_t offset;
2190
2191 if (!object) {
2192 BREAK_TO_DEBUGGER(); /* Invalid object */
2193 return NULL;
2194 }
2195
2196 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2197
2198 for (;;) {
2199 header = GET_IMAGE(struct atom_common_record_header, offset);
2200
2201 if (!header)
2202 return NULL;
2203
2204 offset += header->record_size;
2205
2206 if (header->record_type == ATOM_RECORD_END_TYPE ||
2207 !header->record_size)
2208 break;
2209
2210 if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)
2211 continue;
2212
2213 if (sizeof(struct atom_connector_caps_record) <= header->record_size)
2214 return (struct atom_connector_caps_record *)header;
2215 }
2216
2217 return NULL;
2218 }
2219
bios_parser_get_disp_connector_caps_info(struct dc_bios * dcb,struct graphics_object_id object_id,struct bp_disp_connector_caps_info * info)2220 static enum bp_result bios_parser_get_disp_connector_caps_info(
2221 struct dc_bios *dcb,
2222 struct graphics_object_id object_id,
2223 struct bp_disp_connector_caps_info *info)
2224 {
2225 struct bios_parser *bp = BP_FROM_DCB(dcb);
2226 struct atom_display_object_path_v2 *object;
2227
2228 struct atom_display_object_path_v3 *object_path_v3;
2229 struct atom_connector_caps_record *record_path_v3;
2230
2231 struct atom_disp_connector_caps_record *record = NULL;
2232
2233 if (!info)
2234 return BP_RESULT_BADINPUT;
2235
2236 switch (bp->object_info_tbl.revision.minor) {
2237 case 4:
2238 default:
2239 object = get_bios_object(bp, object_id);
2240
2241 if (!object)
2242 return BP_RESULT_BADINPUT;
2243
2244 record = get_disp_connector_caps_record(bp, object);
2245 if (!record)
2246 return BP_RESULT_NORECORD;
2247
2248 info->INTERNAL_DISPLAY =
2249 (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;
2250 info->INTERNAL_DISPLAY_BL =
2251 (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;
2252 break;
2253 case 5:
2254 object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2255
2256 if (!object_path_v3)
2257 return BP_RESULT_BADINPUT;
2258
2259 record_path_v3 = get_connector_caps_record(bp, object_path_v3);
2260 if (!record_path_v3)
2261 return BP_RESULT_NORECORD;
2262
2263 info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
2264 ? 1 : 0;
2265 info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
2266 ? 1 : 0;
2267 break;
2268 }
2269
2270 return BP_RESULT_OK;
2271 }
2272
get_connector_speed_cap_record(struct bios_parser * bp,struct atom_display_object_path_v3 * object)2273 static struct atom_connector_speed_record *get_connector_speed_cap_record(struct bios_parser *bp,
2274 struct atom_display_object_path_v3 *object)
2275 {
2276 struct atom_common_record_header *header;
2277 uint32_t offset;
2278
2279 if (!object) {
2280 BREAK_TO_DEBUGGER(); /* Invalid object */
2281 return NULL;
2282 }
2283
2284 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2285
2286 for (;;) {
2287 header = GET_IMAGE(struct atom_common_record_header, offset);
2288
2289 if (!header)
2290 return NULL;
2291
2292 offset += header->record_size;
2293
2294 if (header->record_type == ATOM_RECORD_END_TYPE ||
2295 !header->record_size)
2296 break;
2297
2298 if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)
2299 continue;
2300
2301 if (sizeof(struct atom_connector_speed_record) <= header->record_size)
2302 return (struct atom_connector_speed_record *)header;
2303 }
2304
2305 return NULL;
2306 }
2307
bios_parser_get_connector_speed_cap_info(struct dc_bios * dcb,struct graphics_object_id object_id,struct bp_connector_speed_cap_info * info)2308 static enum bp_result bios_parser_get_connector_speed_cap_info(
2309 struct dc_bios *dcb,
2310 struct graphics_object_id object_id,
2311 struct bp_connector_speed_cap_info *info)
2312 {
2313 struct bios_parser *bp = BP_FROM_DCB(dcb);
2314 struct atom_display_object_path_v3 *object_path_v3;
2315 //struct atom_connector_speed_record *record = NULL;
2316 struct atom_connector_speed_record *record;
2317
2318 if (!info)
2319 return BP_RESULT_BADINPUT;
2320
2321 object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2322
2323 if (!object_path_v3)
2324 return BP_RESULT_BADINPUT;
2325
2326 record = get_connector_speed_cap_record(bp, object_path_v3);
2327 if (!record)
2328 return BP_RESULT_NORECORD;
2329
2330 info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;
2331 info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;
2332 info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;
2333 info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
2334 info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
2335 info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
2336 return BP_RESULT_OK;
2337 }
2338
get_vram_info_v23(struct bios_parser * bp,struct dc_vram_info * info)2339 static enum bp_result get_vram_info_v23(
2340 struct bios_parser *bp,
2341 struct dc_vram_info *info)
2342 {
2343 struct atom_vram_info_header_v2_3 *info_v23;
2344 static enum bp_result result = BP_RESULT_OK;
2345
2346 info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
2347 DATA_TABLES(vram_info));
2348
2349 if (info_v23 == NULL)
2350 return BP_RESULT_BADBIOSTABLE;
2351
2352 info->num_chans = info_v23->vram_module[0].channel_num;
2353 info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
2354
2355 return result;
2356 }
2357
get_vram_info_v24(struct bios_parser * bp,struct dc_vram_info * info)2358 static enum bp_result get_vram_info_v24(
2359 struct bios_parser *bp,
2360 struct dc_vram_info *info)
2361 {
2362 struct atom_vram_info_header_v2_4 *info_v24;
2363 static enum bp_result result = BP_RESULT_OK;
2364
2365 info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
2366 DATA_TABLES(vram_info));
2367
2368 if (info_v24 == NULL)
2369 return BP_RESULT_BADBIOSTABLE;
2370
2371 info->num_chans = info_v24->vram_module[0].channel_num;
2372 info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
2373
2374 return result;
2375 }
2376
get_vram_info_v25(struct bios_parser * bp,struct dc_vram_info * info)2377 static enum bp_result get_vram_info_v25(
2378 struct bios_parser *bp,
2379 struct dc_vram_info *info)
2380 {
2381 struct atom_vram_info_header_v2_5 *info_v25;
2382 static enum bp_result result = BP_RESULT_OK;
2383
2384 info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
2385 DATA_TABLES(vram_info));
2386
2387 if (info_v25 == NULL)
2388 return BP_RESULT_BADBIOSTABLE;
2389
2390 info->num_chans = info_v25->vram_module[0].channel_num;
2391 info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
2392
2393 return result;
2394 }
2395
get_vram_info_v30(struct bios_parser * bp,struct dc_vram_info * info)2396 static enum bp_result get_vram_info_v30(
2397 struct bios_parser *bp,
2398 struct dc_vram_info *info)
2399 {
2400 struct atom_vram_info_header_v3_0 *info_v30;
2401 enum bp_result result = BP_RESULT_OK;
2402
2403 info_v30 = GET_IMAGE(struct atom_vram_info_header_v3_0,
2404 DATA_TABLES(vram_info));
2405
2406 if (info_v30 == NULL)
2407 return BP_RESULT_BADBIOSTABLE;
2408
2409 info->num_chans = info_v30->channel_num;
2410 info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;
2411
2412 return result;
2413 }
2414
2415
2416 /*
2417 * get_integrated_info_v11
2418 *
2419 * @brief
2420 * Get V8 integrated BIOS information
2421 *
2422 * @param
2423 * bios_parser *bp - [in]BIOS parser handler to get master data table
2424 * integrated_info *info - [out] store and output integrated info
2425 *
2426 * @return
2427 * static enum bp_result - BP_RESULT_OK if information is available,
2428 * BP_RESULT_BADBIOSTABLE otherwise.
2429 */
get_integrated_info_v11(struct bios_parser * bp,struct integrated_info * info)2430 static enum bp_result get_integrated_info_v11(
2431 struct bios_parser *bp,
2432 struct integrated_info *info)
2433 {
2434 struct atom_integrated_system_info_v1_11 *info_v11;
2435 uint32_t i;
2436
2437 info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
2438 DATA_TABLES(integratedsysteminfo));
2439
2440 if (info_v11 == NULL)
2441 return BP_RESULT_BADBIOSTABLE;
2442
2443 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
2444
2445 info->gpu_cap_info =
2446 le32_to_cpu(info_v11->gpucapinfo);
2447 /*
2448 * system_config: Bit[0] = 0 : PCIE power gating disabled
2449 * = 1 : PCIE power gating enabled
2450 * Bit[1] = 0 : DDR-PLL shut down disabled
2451 * = 1 : DDR-PLL shut down enabled
2452 * Bit[2] = 0 : DDR-PLL power down disabled
2453 * = 1 : DDR-PLL power down enabled
2454 */
2455 info->system_config = le32_to_cpu(info_v11->system_config);
2456 info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
2457 info->memory_type = info_v11->memorytype;
2458 info->ma_channel_number = info_v11->umachannelnumber;
2459 info->lvds_ss_percentage =
2460 le16_to_cpu(info_v11->lvds_ss_percentage);
2461 info->dp_ss_control =
2462 le16_to_cpu(info_v11->reserved1);
2463 info->lvds_sspread_rate_in_10hz =
2464 le16_to_cpu(info_v11->lvds_ss_rate_10hz);
2465 info->hdmi_ss_percentage =
2466 le16_to_cpu(info_v11->hdmi_ss_percentage);
2467 info->hdmi_sspread_rate_in_10hz =
2468 le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
2469 info->dvi_ss_percentage =
2470 le16_to_cpu(info_v11->dvi_ss_percentage);
2471 info->dvi_sspread_rate_in_10_hz =
2472 le16_to_cpu(info_v11->dvi_ss_rate_10hz);
2473 info->lvds_misc = info_v11->lvds_misc;
2474 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2475 info->ext_disp_conn_info.gu_id[i] =
2476 info_v11->extdispconninfo.guid[i];
2477 }
2478
2479 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2480 info->ext_disp_conn_info.path[i].device_connector_id =
2481 object_id_from_bios_object_id(
2482 le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
2483
2484 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2485 object_id_from_bios_object_id(
2486 le16_to_cpu(
2487 info_v11->extdispconninfo.path[i].ext_encoder_objid));
2488
2489 info->ext_disp_conn_info.path[i].device_tag =
2490 le16_to_cpu(
2491 info_v11->extdispconninfo.path[i].device_tag);
2492 info->ext_disp_conn_info.path[i].device_acpi_enum =
2493 le16_to_cpu(
2494 info_v11->extdispconninfo.path[i].device_acpi_enum);
2495 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2496 info_v11->extdispconninfo.path[i].auxddclut_index;
2497 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2498 info_v11->extdispconninfo.path[i].hpdlut_index;
2499 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2500 info_v11->extdispconninfo.path[i].channelmapping;
2501 info->ext_disp_conn_info.path[i].caps =
2502 le16_to_cpu(info_v11->extdispconninfo.path[i].caps);
2503 }
2504 info->ext_disp_conn_info.checksum =
2505 info_v11->extdispconninfo.checksum;
2506
2507 info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
2508 info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
2509 for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2510 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2511 info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2512 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2513 info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2514 }
2515 info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
2516 for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2517 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2518 info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2519 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2520 info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2521 }
2522
2523 info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
2524 info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
2525 for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2526 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2527 info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2528 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2529 info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2530 }
2531 info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
2532 for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2533 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2534 info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2535 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2536 info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2537 }
2538
2539 info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
2540 info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
2541 for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2542 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2543 info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2544 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2545 info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2546 }
2547 info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
2548 for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2549 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2550 info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2551 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2552 info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2553 }
2554
2555 info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
2556 info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
2557 for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2558 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2559 info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2560 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2561 info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2562 }
2563 info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
2564 for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2565 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2566 info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2567 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2568 info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2569 }
2570
2571
2572 /** TODO - review **/
2573 #if 0
2574 info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
2575 * 10;
2576 info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
2577 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2578
2579 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2580 /* Convert [10KHz] into [KHz] */
2581 info->disp_clk_voltage[i].max_supported_clk =
2582 le32_to_cpu(info_v11->sDISPCLK_Voltage[i].
2583 ulMaximumSupportedCLK) * 10;
2584 info->disp_clk_voltage[i].voltage_index =
2585 le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex);
2586 }
2587
2588 info->boot_up_req_display_vector =
2589 le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
2590 info->boot_up_nb_voltage =
2591 le16_to_cpu(info_v11->usBootUpNBVoltage);
2592 info->ext_disp_conn_info_offset =
2593 le16_to_cpu(info_v11->usExtDispConnInfoOffset);
2594 info->gmc_restore_reset_time =
2595 le32_to_cpu(info_v11->ulGMCRestoreResetTime);
2596 info->minimum_n_clk =
2597 le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
2598 for (i = 1; i < 4; ++i)
2599 info->minimum_n_clk =
2600 info->minimum_n_clk <
2601 le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
2602 info->minimum_n_clk : le32_to_cpu(
2603 info_v11->ulNbpStateNClkFreq[i]);
2604
2605 info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
2606 info->ddr_dll_power_up_time =
2607 le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
2608 info->ddr_pll_power_up_time =
2609 le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
2610 info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
2611 info->max_lvds_pclk_freq_in_single_link =
2612 le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2613 info->max_lvds_pclk_freq_in_single_link =
2614 le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2615 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2616 info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2617 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2618 info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2619 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2620 info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2621 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2622 info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2623 info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2624 info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2625 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2626 info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2627 info->lvds_off_to_on_delay_in_4ms =
2628 info_v11->ucLVDSOffToOnDelay_in4Ms;
2629 info->lvds_bit_depth_control_val =
2630 le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
2631
2632 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2633 /* Convert [10KHz] into [KHz] */
2634 info->avail_s_clk[i].supported_s_clk =
2635 le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
2636 * 10;
2637 info->avail_s_clk[i].voltage_index =
2638 le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
2639 info->avail_s_clk[i].voltage_id =
2640 le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
2641 }
2642 #endif /* TODO*/
2643
2644 return BP_RESULT_OK;
2645 }
2646
get_integrated_info_v2_1(struct bios_parser * bp,struct integrated_info * info)2647 static enum bp_result get_integrated_info_v2_1(
2648 struct bios_parser *bp,
2649 struct integrated_info *info)
2650 {
2651 struct atom_integrated_system_info_v2_1 *info_v2_1;
2652 uint32_t i;
2653
2654 info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
2655 DATA_TABLES(integratedsysteminfo));
2656
2657 if (info_v2_1 == NULL)
2658 return BP_RESULT_BADBIOSTABLE;
2659
2660 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
2661
2662 info->gpu_cap_info =
2663 le32_to_cpu(info_v2_1->gpucapinfo);
2664 /*
2665 * system_config: Bit[0] = 0 : PCIE power gating disabled
2666 * = 1 : PCIE power gating enabled
2667 * Bit[1] = 0 : DDR-PLL shut down disabled
2668 * = 1 : DDR-PLL shut down enabled
2669 * Bit[2] = 0 : DDR-PLL power down disabled
2670 * = 1 : DDR-PLL power down enabled
2671 */
2672 info->system_config = le32_to_cpu(info_v2_1->system_config);
2673 info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
2674 info->memory_type = info_v2_1->memorytype;
2675 info->ma_channel_number = info_v2_1->umachannelnumber;
2676 info->dp_ss_control =
2677 le16_to_cpu(info_v2_1->reserved1);
2678
2679 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2680 info->ext_disp_conn_info.gu_id[i] =
2681 info_v2_1->extdispconninfo.guid[i];
2682 }
2683
2684 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2685 info->ext_disp_conn_info.path[i].device_connector_id =
2686 object_id_from_bios_object_id(
2687 le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
2688
2689 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2690 object_id_from_bios_object_id(
2691 le16_to_cpu(
2692 info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
2693
2694 info->ext_disp_conn_info.path[i].device_tag =
2695 le16_to_cpu(
2696 info_v2_1->extdispconninfo.path[i].device_tag);
2697 info->ext_disp_conn_info.path[i].device_acpi_enum =
2698 le16_to_cpu(
2699 info_v2_1->extdispconninfo.path[i].device_acpi_enum);
2700 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2701 info_v2_1->extdispconninfo.path[i].auxddclut_index;
2702 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2703 info_v2_1->extdispconninfo.path[i].hpdlut_index;
2704 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2705 info_v2_1->extdispconninfo.path[i].channelmapping;
2706 info->ext_disp_conn_info.path[i].caps =
2707 le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
2708 }
2709
2710 info->ext_disp_conn_info.checksum =
2711 info_v2_1->extdispconninfo.checksum;
2712 info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
2713 info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
2714 for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2715 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2716 info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2717 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2718 info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2719 }
2720 info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
2721 for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2722 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2723 info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2724 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2725 info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2726 }
2727 info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
2728 info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
2729 for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2730 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2731 info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2732 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2733 info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2734 }
2735 info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
2736 for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2737 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2738 info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2739 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2740 info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2741 }
2742 info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
2743 info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
2744 for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2745 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2746 info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2747 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2748 info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2749 }
2750 info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
2751 for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2752 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2753 info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2754 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2755 info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2756 }
2757 info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
2758 info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
2759 for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2760 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2761 info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2762 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2763 info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2764 }
2765 info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
2766 for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2767 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2768 info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2769 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2770 info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2771 }
2772
2773 info->edp1_info.edp_backlight_pwm_hz =
2774 le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
2775 info->edp1_info.edp_ss_percentage =
2776 le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
2777 info->edp1_info.edp_ss_rate_10hz =
2778 le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
2779 info->edp1_info.edp_pwr_on_off_delay =
2780 info_v2_1->edp1_info.edp_pwr_on_off_delay;
2781 info->edp1_info.edp_pwr_on_vary_bl_to_blon =
2782 info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
2783 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
2784 info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
2785 info->edp1_info.edp_panel_bpc =
2786 info_v2_1->edp1_info.edp_panel_bpc;
2787 info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
2788
2789 info->edp2_info.edp_backlight_pwm_hz =
2790 le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
2791 info->edp2_info.edp_ss_percentage =
2792 le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
2793 info->edp2_info.edp_ss_rate_10hz =
2794 le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
2795 info->edp2_info.edp_pwr_on_off_delay =
2796 info_v2_1->edp2_info.edp_pwr_on_off_delay;
2797 info->edp2_info.edp_pwr_on_vary_bl_to_blon =
2798 info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
2799 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
2800 info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
2801 info->edp2_info.edp_panel_bpc =
2802 info_v2_1->edp2_info.edp_panel_bpc;
2803 info->edp2_info.edp_bootup_bl_level =
2804 info_v2_1->edp2_info.edp_bootup_bl_level;
2805
2806 return BP_RESULT_OK;
2807 }
2808
get_integrated_info_v2_2(struct bios_parser * bp,struct integrated_info * info)2809 static enum bp_result get_integrated_info_v2_2(
2810 struct bios_parser *bp,
2811 struct integrated_info *info)
2812 {
2813 struct atom_integrated_system_info_v2_2 *info_v2_2;
2814 uint32_t i;
2815
2816 info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
2817 DATA_TABLES(integratedsysteminfo));
2818
2819 if (info_v2_2 == NULL)
2820 return BP_RESULT_BADBIOSTABLE;
2821
2822 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
2823
2824 info->gpu_cap_info =
2825 le32_to_cpu(info_v2_2->gpucapinfo);
2826 /*
2827 * system_config: Bit[0] = 0 : PCIE power gating disabled
2828 * = 1 : PCIE power gating enabled
2829 * Bit[1] = 0 : DDR-PLL shut down disabled
2830 * = 1 : DDR-PLL shut down enabled
2831 * Bit[2] = 0 : DDR-PLL power down disabled
2832 * = 1 : DDR-PLL power down enabled
2833 */
2834 info->system_config = le32_to_cpu(info_v2_2->system_config);
2835 info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
2836 info->memory_type = info_v2_2->memorytype;
2837 info->ma_channel_number = info_v2_2->umachannelnumber;
2838 info->dp_ss_control =
2839 le16_to_cpu(info_v2_2->reserved1);
2840 info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage;
2841 info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type;
2842
2843 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2844 info->ext_disp_conn_info.gu_id[i] =
2845 info_v2_2->extdispconninfo.guid[i];
2846 }
2847
2848 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2849 info->ext_disp_conn_info.path[i].device_connector_id =
2850 object_id_from_bios_object_id(
2851 le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
2852
2853 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2854 object_id_from_bios_object_id(
2855 le16_to_cpu(
2856 info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
2857
2858 info->ext_disp_conn_info.path[i].device_tag =
2859 le16_to_cpu(
2860 info_v2_2->extdispconninfo.path[i].device_tag);
2861 info->ext_disp_conn_info.path[i].device_acpi_enum =
2862 le16_to_cpu(
2863 info_v2_2->extdispconninfo.path[i].device_acpi_enum);
2864 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2865 info_v2_2->extdispconninfo.path[i].auxddclut_index;
2866 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2867 info_v2_2->extdispconninfo.path[i].hpdlut_index;
2868 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2869 info_v2_2->extdispconninfo.path[i].channelmapping;
2870 info->ext_disp_conn_info.path[i].caps =
2871 le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
2872 }
2873
2874 info->ext_disp_conn_info.checksum =
2875 info_v2_2->extdispconninfo.checksum;
2876 info->ext_disp_conn_info.fixdpvoltageswing =
2877 info_v2_2->extdispconninfo.fixdpvoltageswing;
2878
2879 info->edp1_info.edp_backlight_pwm_hz =
2880 le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
2881 info->edp1_info.edp_ss_percentage =
2882 le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
2883 info->edp1_info.edp_ss_rate_10hz =
2884 le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
2885 info->edp1_info.edp_pwr_on_off_delay =
2886 info_v2_2->edp1_info.edp_pwr_on_off_delay;
2887 info->edp1_info.edp_pwr_on_vary_bl_to_blon =
2888 info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
2889 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
2890 info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
2891 info->edp1_info.edp_panel_bpc =
2892 info_v2_2->edp1_info.edp_panel_bpc;
2893 info->edp1_info.edp_bootup_bl_level =
2894
2895 info->edp2_info.edp_backlight_pwm_hz =
2896 le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
2897 info->edp2_info.edp_ss_percentage =
2898 le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
2899 info->edp2_info.edp_ss_rate_10hz =
2900 le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
2901 info->edp2_info.edp_pwr_on_off_delay =
2902 info_v2_2->edp2_info.edp_pwr_on_off_delay;
2903 info->edp2_info.edp_pwr_on_vary_bl_to_blon =
2904 info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
2905 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
2906 info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
2907 info->edp2_info.edp_panel_bpc =
2908 info_v2_2->edp2_info.edp_panel_bpc;
2909 info->edp2_info.edp_bootup_bl_level =
2910 info_v2_2->edp2_info.edp_bootup_bl_level;
2911
2912 return BP_RESULT_OK;
2913 }
2914
2915 /*
2916 * construct_integrated_info
2917 *
2918 * @brief
2919 * Get integrated BIOS information based on table revision
2920 *
2921 * @param
2922 * bios_parser *bp - [in]BIOS parser handler to get master data table
2923 * integrated_info *info - [out] store and output integrated info
2924 *
2925 * @return
2926 * static enum bp_result - BP_RESULT_OK if information is available,
2927 * BP_RESULT_BADBIOSTABLE otherwise.
2928 */
construct_integrated_info(struct bios_parser * bp,struct integrated_info * info)2929 static enum bp_result construct_integrated_info(
2930 struct bios_parser *bp,
2931 struct integrated_info *info)
2932 {
2933 static enum bp_result result = BP_RESULT_BADBIOSTABLE;
2934
2935 struct atom_common_table_header *header;
2936 struct atom_data_revision revision;
2937
2938 int32_t i;
2939 int32_t j;
2940
2941 if (!info)
2942 return result;
2943
2944 if (info && DATA_TABLES(integratedsysteminfo)) {
2945 header = GET_IMAGE(struct atom_common_table_header,
2946 DATA_TABLES(integratedsysteminfo));
2947
2948 get_atom_data_table_revision(header, &revision);
2949
2950 switch (revision.major) {
2951 case 1:
2952 switch (revision.minor) {
2953 case 11:
2954 case 12:
2955 result = get_integrated_info_v11(bp, info);
2956 break;
2957 default:
2958 return result;
2959 }
2960 break;
2961 case 2:
2962 switch (revision.minor) {
2963 case 1:
2964 result = get_integrated_info_v2_1(bp, info);
2965 break;
2966 case 2:
2967 case 3:
2968 result = get_integrated_info_v2_2(bp, info);
2969 break;
2970 default:
2971 return result;
2972 }
2973 break;
2974 default:
2975 return result;
2976 }
2977 if (result == BP_RESULT_OK) {
2978
2979 DC_LOG_BIOS("edp1:\n"
2980 "\tedp_pwr_on_off_delay = %d\n"
2981 "\tedp_pwr_on_vary_bl_to_blon = %d\n"
2982 "\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
2983 "\tedp_bootup_bl_level = %d\n",
2984 info->edp1_info.edp_pwr_on_off_delay,
2985 info->edp1_info.edp_pwr_on_vary_bl_to_blon,
2986 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff,
2987 info->edp1_info.edp_bootup_bl_level);
2988 DC_LOG_BIOS("edp2:\n"
2989 "\tedp_pwr_on_off_delayv = %d\n"
2990 "\tedp_pwr_on_vary_bl_to_blon = %d\n"
2991 "\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
2992 "\tedp_bootup_bl_level = %d\n",
2993 info->edp2_info.edp_pwr_on_off_delay,
2994 info->edp2_info.edp_pwr_on_vary_bl_to_blon,
2995 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff,
2996 info->edp2_info.edp_bootup_bl_level);
2997 }
2998 }
2999
3000 if (result != BP_RESULT_OK)
3001 return result;
3002 else {
3003 // Log each external path
3004 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
3005 if (info->ext_disp_conn_info.path[i].device_tag != 0)
3006 DC_LOG_BIOS("integrated_info:For EXTERNAL DISPLAY PATH %d --------------\n"
3007 "DEVICE_TAG: 0x%x\n"
3008 "DEVICE_ACPI_ENUM: 0x%x\n"
3009 "DEVICE_CONNECTOR_ID: 0x%x\n"
3010 "EXT_AUX_DDC_LUT_INDEX: %d\n"
3011 "EXT_HPD_PIN_LUT_INDEX: %d\n"
3012 "EXT_ENCODER_OBJ_ID: 0x%x\n"
3013 "Encoder CAPS: 0x%x\n",
3014 i,
3015 info->ext_disp_conn_info.path[i].device_tag,
3016 info->ext_disp_conn_info.path[i].device_acpi_enum,
3017 info->ext_disp_conn_info.path[i].device_connector_id.id,
3018 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index,
3019 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index,
3020 info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
3021 info->ext_disp_conn_info.path[i].caps
3022 );
3023 if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
3024 DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3025 else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
3026 info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
3027 DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3028 }
3029 }
3030 // Log the Checksum and Voltage Swing
3031 DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"
3032 "Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",
3033 info->ext_disp_conn_info.checksum,
3034 info->ext_disp_conn_info.fixdpvoltageswing);
3035 if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {
3036 info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;
3037 DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);
3038 }
3039 }
3040 /* Sort voltage table from low to high*/
3041 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3042 for (j = i; j > 0; --j) {
3043 if (info->disp_clk_voltage[j].max_supported_clk <
3044 info->disp_clk_voltage[j-1].max_supported_clk)
3045 swap(info->disp_clk_voltage[j-1], info->disp_clk_voltage[j]);
3046 }
3047 }
3048
3049 return result;
3050 }
3051
bios_parser_get_vram_info(struct dc_bios * dcb,struct dc_vram_info * info)3052 static enum bp_result bios_parser_get_vram_info(
3053 struct dc_bios *dcb,
3054 struct dc_vram_info *info)
3055 {
3056 struct bios_parser *bp = BP_FROM_DCB(dcb);
3057 static enum bp_result result = BP_RESULT_BADBIOSTABLE;
3058 struct atom_common_table_header *header;
3059 struct atom_data_revision revision;
3060
3061 if (info && DATA_TABLES(vram_info)) {
3062 header = GET_IMAGE(struct atom_common_table_header,
3063 DATA_TABLES(vram_info));
3064
3065 get_atom_data_table_revision(header, &revision);
3066
3067 switch (revision.major) {
3068 case 2:
3069 switch (revision.minor) {
3070 case 3:
3071 result = get_vram_info_v23(bp, info);
3072 break;
3073 case 4:
3074 result = get_vram_info_v24(bp, info);
3075 break;
3076 case 5:
3077 result = get_vram_info_v25(bp, info);
3078 break;
3079 default:
3080 break;
3081 }
3082 break;
3083
3084 case 3:
3085 switch (revision.minor) {
3086 case 0:
3087 result = get_vram_info_v30(bp, info);
3088 break;
3089 default:
3090 break;
3091 }
3092 break;
3093
3094 default:
3095 return result;
3096 }
3097
3098 }
3099 return result;
3100 }
3101
bios_parser_create_integrated_info(struct dc_bios * dcb)3102 static struct integrated_info *bios_parser_create_integrated_info(
3103 struct dc_bios *dcb)
3104 {
3105 struct bios_parser *bp = BP_FROM_DCB(dcb);
3106 struct integrated_info *info;
3107
3108 info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
3109
3110 if (info == NULL) {
3111 ASSERT_CRITICAL(0);
3112 return NULL;
3113 }
3114
3115 if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3116 return info;
3117
3118 kfree(info);
3119
3120 return NULL;
3121 }
3122
update_slot_layout_info(struct dc_bios * dcb,unsigned int i,struct slot_layout_info * slot_layout_info)3123 static enum bp_result update_slot_layout_info(
3124 struct dc_bios *dcb,
3125 unsigned int i,
3126 struct slot_layout_info *slot_layout_info)
3127 {
3128 unsigned int record_offset;
3129 unsigned int j;
3130 struct atom_display_object_path_v2 *object;
3131 struct atom_bracket_layout_record *record;
3132 struct atom_common_record_header *record_header;
3133 static enum bp_result result;
3134 struct bios_parser *bp;
3135 struct object_info_table *tbl;
3136 struct display_object_info_table_v1_4 *v1_4;
3137
3138 record = NULL;
3139 record_header = NULL;
3140 result = BP_RESULT_NORECORD;
3141
3142 bp = BP_FROM_DCB(dcb);
3143 tbl = &bp->object_info_tbl;
3144 v1_4 = tbl->v1_4;
3145
3146 object = &v1_4->display_path[i];
3147 record_offset = (unsigned int)
3148 (object->disp_recordoffset) +
3149 (unsigned int)(bp->object_info_tbl_offset);
3150
3151 for (;;) {
3152
3153 record_header = (struct atom_common_record_header *)
3154 GET_IMAGE(struct atom_common_record_header,
3155 record_offset);
3156 if (record_header == NULL) {
3157 result = BP_RESULT_BADBIOSTABLE;
3158 break;
3159 }
3160
3161 /* the end of the list */
3162 if (record_header->record_type == 0xff ||
3163 record_header->record_size == 0) {
3164 break;
3165 }
3166
3167 if (record_header->record_type ==
3168 ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3169 sizeof(struct atom_bracket_layout_record)
3170 <= record_header->record_size) {
3171 record = (struct atom_bracket_layout_record *)
3172 (record_header);
3173 result = BP_RESULT_OK;
3174 break;
3175 }
3176
3177 record_offset += record_header->record_size;
3178 }
3179
3180 /* return if the record not found */
3181 if (result != BP_RESULT_OK)
3182 return result;
3183
3184 /* get slot sizes */
3185 slot_layout_info->length = record->bracketlen;
3186 slot_layout_info->width = record->bracketwidth;
3187
3188 /* get info for each connector in the slot */
3189 slot_layout_info->num_of_connectors = record->conn_num;
3190 for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3191 slot_layout_info->connectors[j].connector_type =
3192 (enum connector_layout_type)
3193 (record->conn_info[j].connector_type);
3194 switch (record->conn_info[j].connector_type) {
3195 case CONNECTOR_TYPE_DVI_D:
3196 slot_layout_info->connectors[j].connector_type =
3197 CONNECTOR_LAYOUT_TYPE_DVI_D;
3198 slot_layout_info->connectors[j].length =
3199 CONNECTOR_SIZE_DVI;
3200 break;
3201
3202 case CONNECTOR_TYPE_HDMI:
3203 slot_layout_info->connectors[j].connector_type =
3204 CONNECTOR_LAYOUT_TYPE_HDMI;
3205 slot_layout_info->connectors[j].length =
3206 CONNECTOR_SIZE_HDMI;
3207 break;
3208
3209 case CONNECTOR_TYPE_DISPLAY_PORT:
3210 slot_layout_info->connectors[j].connector_type =
3211 CONNECTOR_LAYOUT_TYPE_DP;
3212 slot_layout_info->connectors[j].length =
3213 CONNECTOR_SIZE_DP;
3214 break;
3215
3216 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3217 slot_layout_info->connectors[j].connector_type =
3218 CONNECTOR_LAYOUT_TYPE_MINI_DP;
3219 slot_layout_info->connectors[j].length =
3220 CONNECTOR_SIZE_MINI_DP;
3221 break;
3222
3223 default:
3224 slot_layout_info->connectors[j].connector_type =
3225 CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3226 slot_layout_info->connectors[j].length =
3227 CONNECTOR_SIZE_UNKNOWN;
3228 }
3229
3230 slot_layout_info->connectors[j].position =
3231 record->conn_info[j].position;
3232 slot_layout_info->connectors[j].connector_id =
3233 object_id_from_bios_object_id(
3234 record->conn_info[j].connectorobjid);
3235 }
3236 return result;
3237 }
3238
update_slot_layout_info_v2(struct dc_bios * dcb,unsigned int i,struct slot_layout_info * slot_layout_info)3239 static enum bp_result update_slot_layout_info_v2(
3240 struct dc_bios *dcb,
3241 unsigned int i,
3242 struct slot_layout_info *slot_layout_info)
3243 {
3244 unsigned int record_offset;
3245 struct atom_display_object_path_v3 *object;
3246 struct atom_bracket_layout_record_v2 *record;
3247 struct atom_common_record_header *record_header;
3248 static enum bp_result result;
3249 struct bios_parser *bp;
3250 struct object_info_table *tbl;
3251 struct display_object_info_table_v1_5 *v1_5;
3252 struct graphics_object_id connector_id;
3253
3254 record = NULL;
3255 record_header = NULL;
3256 result = BP_RESULT_NORECORD;
3257
3258 bp = BP_FROM_DCB(dcb);
3259 tbl = &bp->object_info_tbl;
3260 v1_5 = tbl->v1_5;
3261
3262 object = &v1_5->display_path[i];
3263 record_offset = (unsigned int)
3264 (object->disp_recordoffset) +
3265 (unsigned int)(bp->object_info_tbl_offset);
3266
3267 for (;;) {
3268
3269 record_header = (struct atom_common_record_header *)
3270 GET_IMAGE(struct atom_common_record_header,
3271 record_offset);
3272 if (record_header == NULL) {
3273 result = BP_RESULT_BADBIOSTABLE;
3274 break;
3275 }
3276
3277 /* the end of the list */
3278 if (record_header->record_type == ATOM_RECORD_END_TYPE ||
3279 record_header->record_size == 0) {
3280 break;
3281 }
3282
3283 if (record_header->record_type ==
3284 ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&
3285 sizeof(struct atom_bracket_layout_record_v2)
3286 <= record_header->record_size) {
3287 record = (struct atom_bracket_layout_record_v2 *)
3288 (record_header);
3289 result = BP_RESULT_OK;
3290 break;
3291 }
3292
3293 record_offset += record_header->record_size;
3294 }
3295
3296 /* return if the record not found */
3297 if (result != BP_RESULT_OK)
3298 return result;
3299
3300 /* get slot sizes */
3301 connector_id = object_id_from_bios_object_id(object->display_objid);
3302
3303 slot_layout_info->length = record->bracketlen;
3304 slot_layout_info->width = record->bracketwidth;
3305 slot_layout_info->num_of_connectors = v1_5->number_of_path;
3306 slot_layout_info->connectors[i].position = record->conn_num;
3307 slot_layout_info->connectors[i].connector_id = connector_id;
3308
3309 switch (connector_id.id) {
3310 case CONNECTOR_ID_SINGLE_LINK_DVID:
3311 case CONNECTOR_ID_DUAL_LINK_DVID:
3312 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;
3313 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;
3314 break;
3315
3316 case CONNECTOR_ID_HDMI_TYPE_A:
3317 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;
3318 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;
3319 break;
3320
3321 case CONNECTOR_ID_DISPLAY_PORT:
3322 case CONNECTOR_ID_USBC:
3323 if (record->mini_type == MINI_TYPE_NORMAL) {
3324 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;
3325 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;
3326 } else {
3327 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;
3328 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;
3329 }
3330 break;
3331
3332 default:
3333 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3334 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;
3335 }
3336 return result;
3337 }
3338
get_bracket_layout_record(struct dc_bios * dcb,unsigned int bracket_layout_id,struct slot_layout_info * slot_layout_info)3339 static enum bp_result get_bracket_layout_record(
3340 struct dc_bios *dcb,
3341 unsigned int bracket_layout_id,
3342 struct slot_layout_info *slot_layout_info)
3343 {
3344 unsigned int i;
3345 struct bios_parser *bp = BP_FROM_DCB(dcb);
3346 static enum bp_result result;
3347 struct object_info_table *tbl;
3348 struct display_object_info_table_v1_4 *v1_4;
3349 struct display_object_info_table_v1_5 *v1_5;
3350
3351 if (slot_layout_info == NULL) {
3352 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3353 return BP_RESULT_BADINPUT;
3354 }
3355 tbl = &bp->object_info_tbl;
3356 v1_4 = tbl->v1_4;
3357 v1_5 = tbl->v1_5;
3358
3359 result = BP_RESULT_NORECORD;
3360 switch (bp->object_info_tbl.revision.minor) {
3361 case 4:
3362 default:
3363 for (i = 0; i < v1_4->number_of_path; ++i) {
3364 if (bracket_layout_id ==
3365 v1_4->display_path[i].display_objid) {
3366 result = update_slot_layout_info(dcb, i, slot_layout_info);
3367 break;
3368 }
3369 }
3370 break;
3371 case 5:
3372 for (i = 0; i < v1_5->number_of_path; ++i)
3373 result = update_slot_layout_info_v2(dcb, i, slot_layout_info);
3374 break;
3375 }
3376 return result;
3377 }
3378
bios_get_board_layout_info(struct dc_bios * dcb,struct board_layout_info * board_layout_info)3379 static enum bp_result bios_get_board_layout_info(
3380 struct dc_bios *dcb,
3381 struct board_layout_info *board_layout_info)
3382 {
3383 unsigned int i;
3384
3385 struct bios_parser *bp;
3386
3387 static enum bp_result record_result;
3388 unsigned int max_slots;
3389
3390 const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3391 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3392 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3393 0, 0
3394 };
3395
3396
3397 bp = BP_FROM_DCB(dcb);
3398
3399 if (board_layout_info == NULL) {
3400 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3401 return BP_RESULT_BADINPUT;
3402 }
3403
3404 board_layout_info->num_of_slots = 0;
3405 max_slots = MAX_BOARD_SLOTS;
3406
3407 // Assume single slot on v1_5
3408 if (bp->object_info_tbl.revision.minor == 5) {
3409 max_slots = 1;
3410 }
3411
3412 for (i = 0; i < max_slots; ++i) {
3413 record_result = get_bracket_layout_record(dcb,
3414 slot_index_to_vbios_id[i],
3415 &board_layout_info->slots[i]);
3416
3417 if (record_result == BP_RESULT_NORECORD && i > 0)
3418 break; /* no more slots present in bios */
3419 else if (record_result != BP_RESULT_OK)
3420 return record_result; /* fail */
3421
3422 ++board_layout_info->num_of_slots;
3423 }
3424
3425 /* all data is valid */
3426 board_layout_info->is_number_of_slots_valid = 1;
3427 board_layout_info->is_slots_size_valid = 1;
3428 board_layout_info->is_connector_offsets_valid = 1;
3429 board_layout_info->is_connector_lengths_valid = 1;
3430
3431 return BP_RESULT_OK;
3432 }
3433
3434
bios_parser_pack_data_tables(struct dc_bios * dcb,void * dst)3435 static uint16_t bios_parser_pack_data_tables(
3436 struct dc_bios *dcb,
3437 void *dst)
3438 {
3439 // TODO: There is data bytes alignment issue, disable it for now.
3440 return 0;
3441 }
3442
bios_get_golden_table(struct bios_parser * bp,uint32_t rev_major,uint32_t rev_minor,uint16_t * dc_golden_table_ver)3443 static struct atom_dc_golden_table_v1 *bios_get_golden_table(
3444 struct bios_parser *bp,
3445 uint32_t rev_major,
3446 uint32_t rev_minor,
3447 uint16_t *dc_golden_table_ver)
3448 {
3449 struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
3450 uint32_t dc_golden_offset = 0;
3451 *dc_golden_table_ver = 0;
3452
3453 if (!DATA_TABLES(dce_info))
3454 return NULL;
3455
3456 /* ver.4.4 or higher */
3457 switch (rev_major) {
3458 case 4:
3459 switch (rev_minor) {
3460 case 4:
3461 disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
3462 DATA_TABLES(dce_info));
3463 if (!disp_cntl_tbl_4_4)
3464 return NULL;
3465 dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
3466 *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
3467 break;
3468 case 5:
3469 default:
3470 /* For atom_display_controller_info_v4_5 there is no need to get golden table from
3471 * dc_golden_table_offset as all these fields previously in golden table used for AUX
3472 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.
3473 */
3474 break;
3475 }
3476 break;
3477 }
3478
3479 if (!dc_golden_offset)
3480 return NULL;
3481
3482 if (*dc_golden_table_ver != 1)
3483 return NULL;
3484
3485 return GET_IMAGE(struct atom_dc_golden_table_v1,
3486 dc_golden_offset);
3487 }
3488
bios_get_atom_dc_golden_table(struct dc_bios * dcb)3489 static enum bp_result bios_get_atom_dc_golden_table(
3490 struct dc_bios *dcb)
3491 {
3492 struct bios_parser *bp = BP_FROM_DCB(dcb);
3493 enum bp_result result = BP_RESULT_OK;
3494 struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
3495 struct atom_common_table_header *header;
3496 struct atom_data_revision tbl_revision;
3497 uint16_t dc_golden_table_ver = 0;
3498
3499 header = GET_IMAGE(struct atom_common_table_header,
3500 DATA_TABLES(dce_info));
3501 if (!header)
3502 return BP_RESULT_UNSUPPORTED;
3503
3504 get_atom_data_table_revision(header, &tbl_revision);
3505
3506 atom_dc_golden_table = bios_get_golden_table(bp,
3507 tbl_revision.major,
3508 tbl_revision.minor,
3509 &dc_golden_table_ver);
3510
3511 if (!atom_dc_golden_table)
3512 return BP_RESULT_UNSUPPORTED;
3513
3514 dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
3515 dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
3516 dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
3517 dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
3518 dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
3519 dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
3520 dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
3521 dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
3522 dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
3523 dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
3524
3525 return result;
3526 }
3527
3528
3529 static const struct dc_vbios_funcs vbios_funcs = {
3530 .get_connectors_number = bios_parser_get_connectors_number,
3531
3532 .get_connector_id = bios_parser_get_connector_id,
3533
3534 .get_src_obj = bios_parser_get_src_obj,
3535
3536 .get_i2c_info = bios_parser_get_i2c_info,
3537
3538 .get_hpd_info = bios_parser_get_hpd_info,
3539
3540 .get_device_tag = bios_parser_get_device_tag,
3541
3542 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3543
3544 .get_ss_entry_number = bios_parser_get_ss_entry_number,
3545
3546 .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3547
3548 .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3549
3550 .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3551
3552 .is_device_id_supported = bios_parser_is_device_id_supported,
3553
3554 .is_accelerated_mode = bios_parser_is_accelerated_mode,
3555
3556 .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
3557
3558
3559 /* COMMANDS */
3560 .encoder_control = bios_parser_encoder_control,
3561
3562 .transmitter_control = bios_parser_transmitter_control,
3563
3564 .enable_crtc = bios_parser_enable_crtc,
3565
3566 .set_pixel_clock = bios_parser_set_pixel_clock,
3567
3568 .set_dce_clock = bios_parser_set_dce_clock,
3569
3570 .program_crtc_timing = bios_parser_program_crtc_timing,
3571
3572 .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
3573
3574 .bios_parser_destroy = firmware_parser_destroy,
3575
3576 .get_board_layout_info = bios_get_board_layout_info,
3577 /* TODO: use this fn in hw init?*/
3578 .pack_data_tables = bios_parser_pack_data_tables,
3579
3580 .get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
3581
3582 .enable_lvtma_control = bios_parser_enable_lvtma_control,
3583
3584 .get_soc_bb_info = bios_parser_get_soc_bb_info,
3585
3586 .get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
3587
3588 .get_lttpr_caps = bios_parser_get_lttpr_caps,
3589
3590 .get_lttpr_interop = bios_parser_get_lttpr_interop,
3591
3592 .get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
3593 };
3594
bios_parser2_construct(struct bios_parser * bp,struct bp_init_data * init,enum dce_version dce_version)3595 static bool bios_parser2_construct(
3596 struct bios_parser *bp,
3597 struct bp_init_data *init,
3598 enum dce_version dce_version)
3599 {
3600 uint16_t *rom_header_offset = NULL;
3601 struct atom_rom_header_v2_2 *rom_header = NULL;
3602 struct display_object_info_table_v1_4 *object_info_tbl;
3603 struct atom_data_revision tbl_rev = {0};
3604
3605 if (!init)
3606 return false;
3607
3608 if (!init->bios)
3609 return false;
3610
3611 bp->base.funcs = &vbios_funcs;
3612 bp->base.bios = init->bios;
3613 bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
3614
3615 bp->base.ctx = init->ctx;
3616
3617 bp->base.bios_local_image = NULL;
3618
3619 rom_header_offset =
3620 GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
3621
3622 if (!rom_header_offset)
3623 return false;
3624
3625 rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
3626
3627 if (!rom_header)
3628 return false;
3629
3630 get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
3631 if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
3632 return false;
3633
3634 bp->master_data_tbl =
3635 GET_IMAGE(struct atom_master_data_table_v2_1,
3636 rom_header->masterdatatable_offset);
3637
3638 if (!bp->master_data_tbl)
3639 return false;
3640
3641 bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
3642
3643 if (!bp->object_info_tbl_offset)
3644 return false;
3645
3646 object_info_tbl =
3647 GET_IMAGE(struct display_object_info_table_v1_4,
3648 bp->object_info_tbl_offset);
3649
3650 if (!object_info_tbl)
3651 return false;
3652
3653 get_atom_data_table_revision(&object_info_tbl->table_header,
3654 &bp->object_info_tbl.revision);
3655
3656 if (bp->object_info_tbl.revision.major == 1
3657 && bp->object_info_tbl.revision.minor == 4) {
3658 struct display_object_info_table_v1_4 *tbl_v1_4;
3659
3660 tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
3661 bp->object_info_tbl_offset);
3662 if (!tbl_v1_4)
3663 return false;
3664
3665 bp->object_info_tbl.v1_4 = tbl_v1_4;
3666 } else if (bp->object_info_tbl.revision.major == 1
3667 && bp->object_info_tbl.revision.minor == 5) {
3668 struct display_object_info_table_v1_5 *tbl_v1_5;
3669
3670 tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,
3671 bp->object_info_tbl_offset);
3672 if (!tbl_v1_5)
3673 return false;
3674
3675 bp->object_info_tbl.v1_5 = tbl_v1_5;
3676 } else {
3677 ASSERT(0);
3678 return false;
3679 }
3680
3681 dal_firmware_parser_init_cmd_tbl(bp);
3682 dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
3683
3684 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
3685 bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
3686 bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
3687
3688 return true;
3689 }
3690
firmware_parser_create(struct bp_init_data * init,enum dce_version dce_version)3691 struct dc_bios *firmware_parser_create(
3692 struct bp_init_data *init,
3693 enum dce_version dce_version)
3694 {
3695 struct bios_parser *bp;
3696
3697 bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
3698 if (!bp)
3699 return NULL;
3700
3701 if (bios_parser2_construct(bp, init, dce_version))
3702 return &bp->base;
3703
3704 kfree(bp);
3705 return NULL;
3706 }
3707
3708
3709