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 ss_info->spread_spectrum_percentage =
1019 disp_cntl_tbl->dp_ss_percentage;
1020 ss_info->spread_spectrum_range =
1021 disp_cntl_tbl->dp_ss_rate_10hz * 10;
1022 if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1023 ss_info->type.CENTER_MODE = true;
1024
1025 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1026 break;
1027 case AS_SIGNAL_TYPE_GPU_PLL:
1028 /* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore.
1029 * SMU Display PLL supposed to be without spread.
1030 * Better place for it would be in atom_display_controller_info_v4_5 table.
1031 */
1032 result = BP_RESULT_UNSUPPORTED;
1033 break;
1034 default:
1035 result = BP_RESULT_UNSUPPORTED;
1036 break;
1037 }
1038
1039 return result;
1040 }
1041
1042 /**
1043 * bios_parser_get_spread_spectrum_info
1044 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
1045 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
1046 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info
1047 * ver 3.1,
1048 * there is only one entry for each signal /ss id. However, there is
1049 * no planning of supporting multiple spread Sprectum entry for EverGreen
1050 * @dcb: pointer to the DC BIOS
1051 * @signal: ASSignalType to be converted to info index
1052 * @index: number of entries that match the converted info index
1053 * @ss_info: sprectrum information structure,
1054 * return: Bios parser result code
1055 */
bios_parser_get_spread_spectrum_info(struct dc_bios * dcb,enum as_signal_type signal,uint32_t index,struct spread_spectrum_info * ss_info)1056 static enum bp_result bios_parser_get_spread_spectrum_info(
1057 struct dc_bios *dcb,
1058 enum as_signal_type signal,
1059 uint32_t index,
1060 struct spread_spectrum_info *ss_info)
1061 {
1062 struct bios_parser *bp = BP_FROM_DCB(dcb);
1063 enum bp_result result = BP_RESULT_UNSUPPORTED;
1064 struct atom_common_table_header *header;
1065 struct atom_data_revision tbl_revision;
1066
1067 if (!ss_info) /* check for bad input */
1068 return BP_RESULT_BADINPUT;
1069
1070 if (!DATA_TABLES(dce_info))
1071 return BP_RESULT_UNSUPPORTED;
1072
1073 header = GET_IMAGE(struct atom_common_table_header,
1074 DATA_TABLES(dce_info));
1075 get_atom_data_table_revision(header, &tbl_revision);
1076
1077 switch (tbl_revision.major) {
1078 case 4:
1079 switch (tbl_revision.minor) {
1080 case 1:
1081 return get_ss_info_v4_1(bp, signal, index, ss_info);
1082 case 2:
1083 case 3:
1084 case 4:
1085 return get_ss_info_v4_2(bp, signal, index, ss_info);
1086 case 5:
1087 return get_ss_info_v4_5(bp, signal, index, ss_info);
1088
1089 default:
1090 ASSERT(0);
1091 break;
1092 }
1093 break;
1094 default:
1095 break;
1096 }
1097 /* there can not be more then one entry for SS Info table */
1098 return result;
1099 }
1100
get_soc_bb_info_v4_4(struct bios_parser * bp,struct bp_soc_bb_info * soc_bb_info)1101 static enum bp_result get_soc_bb_info_v4_4(
1102 struct bios_parser *bp,
1103 struct bp_soc_bb_info *soc_bb_info)
1104 {
1105 enum bp_result result = BP_RESULT_OK;
1106 struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1107
1108 if (!soc_bb_info)
1109 return BP_RESULT_BADINPUT;
1110
1111 if (!DATA_TABLES(dce_info))
1112 return BP_RESULT_BADBIOSTABLE;
1113
1114 if (!DATA_TABLES(smu_info))
1115 return BP_RESULT_BADBIOSTABLE;
1116
1117 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
1118 DATA_TABLES(dce_info));
1119 if (!disp_cntl_tbl)
1120 return BP_RESULT_BADBIOSTABLE;
1121
1122 soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1123 soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1124 soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1125
1126 return result;
1127 }
1128
get_soc_bb_info_v4_5(struct bios_parser * bp,struct bp_soc_bb_info * soc_bb_info)1129 static enum bp_result get_soc_bb_info_v4_5(
1130 struct bios_parser *bp,
1131 struct bp_soc_bb_info *soc_bb_info)
1132 {
1133 enum bp_result result = BP_RESULT_OK;
1134 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1135
1136 if (!soc_bb_info)
1137 return BP_RESULT_BADINPUT;
1138
1139 if (!DATA_TABLES(dce_info))
1140 return BP_RESULT_BADBIOSTABLE;
1141
1142 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
1143 DATA_TABLES(dce_info));
1144 if (!disp_cntl_tbl)
1145 return BP_RESULT_BADBIOSTABLE;
1146
1147 soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1148 soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1149 soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1150
1151 return result;
1152 }
1153
bios_parser_get_soc_bb_info(struct dc_bios * dcb,struct bp_soc_bb_info * soc_bb_info)1154 static enum bp_result bios_parser_get_soc_bb_info(
1155 struct dc_bios *dcb,
1156 struct bp_soc_bb_info *soc_bb_info)
1157 {
1158 struct bios_parser *bp = BP_FROM_DCB(dcb);
1159 enum bp_result result = BP_RESULT_UNSUPPORTED;
1160 struct atom_common_table_header *header;
1161 struct atom_data_revision tbl_revision;
1162
1163 if (!soc_bb_info) /* check for bad input */
1164 return BP_RESULT_BADINPUT;
1165
1166 if (!DATA_TABLES(dce_info))
1167 return BP_RESULT_UNSUPPORTED;
1168
1169 header = GET_IMAGE(struct atom_common_table_header,
1170 DATA_TABLES(dce_info));
1171 get_atom_data_table_revision(header, &tbl_revision);
1172
1173 switch (tbl_revision.major) {
1174 case 4:
1175 switch (tbl_revision.minor) {
1176 case 1:
1177 case 2:
1178 case 3:
1179 break;
1180 case 4:
1181 result = get_soc_bb_info_v4_4(bp, soc_bb_info);
1182 break;
1183 case 5:
1184 result = get_soc_bb_info_v4_5(bp, soc_bb_info);
1185 break;
1186 default:
1187 break;
1188 }
1189 break;
1190 default:
1191 break;
1192 }
1193
1194 return result;
1195 }
1196
get_disp_caps_v4_1(struct bios_parser * bp,uint8_t * dce_caps)1197 static enum bp_result get_disp_caps_v4_1(
1198 struct bios_parser *bp,
1199 uint8_t *dce_caps)
1200 {
1201 enum bp_result result = BP_RESULT_OK;
1202 struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
1203
1204 if (!dce_caps)
1205 return BP_RESULT_BADINPUT;
1206
1207 if (!DATA_TABLES(dce_info))
1208 return BP_RESULT_BADBIOSTABLE;
1209
1210 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,
1211 DATA_TABLES(dce_info));
1212
1213 if (!disp_cntl_tbl)
1214 return BP_RESULT_BADBIOSTABLE;
1215
1216 *dce_caps = disp_cntl_tbl->display_caps;
1217
1218 return result;
1219 }
1220
get_disp_caps_v4_2(struct bios_parser * bp,uint8_t * dce_caps)1221 static enum bp_result get_disp_caps_v4_2(
1222 struct bios_parser *bp,
1223 uint8_t *dce_caps)
1224 {
1225 enum bp_result result = BP_RESULT_OK;
1226 struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
1227
1228 if (!dce_caps)
1229 return BP_RESULT_BADINPUT;
1230
1231 if (!DATA_TABLES(dce_info))
1232 return BP_RESULT_BADBIOSTABLE;
1233
1234 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,
1235 DATA_TABLES(dce_info));
1236
1237 if (!disp_cntl_tbl)
1238 return BP_RESULT_BADBIOSTABLE;
1239
1240 *dce_caps = disp_cntl_tbl->display_caps;
1241
1242 return result;
1243 }
1244
get_disp_caps_v4_3(struct bios_parser * bp,uint8_t * dce_caps)1245 static enum bp_result get_disp_caps_v4_3(
1246 struct bios_parser *bp,
1247 uint8_t *dce_caps)
1248 {
1249 enum bp_result result = BP_RESULT_OK;
1250 struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL;
1251
1252 if (!dce_caps)
1253 return BP_RESULT_BADINPUT;
1254
1255 if (!DATA_TABLES(dce_info))
1256 return BP_RESULT_BADBIOSTABLE;
1257
1258 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3,
1259 DATA_TABLES(dce_info));
1260
1261 if (!disp_cntl_tbl)
1262 return BP_RESULT_BADBIOSTABLE;
1263
1264 *dce_caps = disp_cntl_tbl->display_caps;
1265
1266 return result;
1267 }
1268
get_disp_caps_v4_4(struct bios_parser * bp,uint8_t * dce_caps)1269 static enum bp_result get_disp_caps_v4_4(
1270 struct bios_parser *bp,
1271 uint8_t *dce_caps)
1272 {
1273 enum bp_result result = BP_RESULT_OK;
1274 struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1275
1276 if (!dce_caps)
1277 return BP_RESULT_BADINPUT;
1278
1279 if (!DATA_TABLES(dce_info))
1280 return BP_RESULT_BADBIOSTABLE;
1281
1282 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
1283 DATA_TABLES(dce_info));
1284
1285 if (!disp_cntl_tbl)
1286 return BP_RESULT_BADBIOSTABLE;
1287
1288 *dce_caps = disp_cntl_tbl->display_caps;
1289
1290 return result;
1291 }
1292
get_disp_caps_v4_5(struct bios_parser * bp,uint8_t * dce_caps)1293 static enum bp_result get_disp_caps_v4_5(
1294 struct bios_parser *bp,
1295 uint8_t *dce_caps)
1296 {
1297 enum bp_result result = BP_RESULT_OK;
1298 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1299
1300 if (!dce_caps)
1301 return BP_RESULT_BADINPUT;
1302
1303 if (!DATA_TABLES(dce_info))
1304 return BP_RESULT_BADBIOSTABLE;
1305
1306 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
1307 DATA_TABLES(dce_info));
1308
1309 if (!disp_cntl_tbl)
1310 return BP_RESULT_BADBIOSTABLE;
1311
1312 *dce_caps = disp_cntl_tbl->display_caps;
1313
1314 return result;
1315 }
1316
bios_parser_get_lttpr_interop(struct dc_bios * dcb,uint8_t * dce_caps)1317 static enum bp_result bios_parser_get_lttpr_interop(
1318 struct dc_bios *dcb,
1319 uint8_t *dce_caps)
1320 {
1321 struct bios_parser *bp = BP_FROM_DCB(dcb);
1322 enum bp_result result = BP_RESULT_UNSUPPORTED;
1323 struct atom_common_table_header *header;
1324 struct atom_data_revision tbl_revision;
1325
1326 if (!DATA_TABLES(dce_info))
1327 return BP_RESULT_UNSUPPORTED;
1328
1329 header = GET_IMAGE(struct atom_common_table_header,
1330 DATA_TABLES(dce_info));
1331 get_atom_data_table_revision(header, &tbl_revision);
1332 switch (tbl_revision.major) {
1333 case 4:
1334 switch (tbl_revision.minor) {
1335 case 1:
1336 result = get_disp_caps_v4_1(bp, dce_caps);
1337 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1338 break;
1339 case 2:
1340 result = get_disp_caps_v4_2(bp, dce_caps);
1341 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1342 break;
1343 case 3:
1344 result = get_disp_caps_v4_3(bp, dce_caps);
1345 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1346 break;
1347 case 4:
1348 result = get_disp_caps_v4_4(bp, dce_caps);
1349 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1350 break;
1351 case 5:
1352 result = get_disp_caps_v4_5(bp, dce_caps);
1353 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1354 break;
1355
1356 default:
1357 break;
1358 }
1359 break;
1360 default:
1361 break;
1362 }
1363 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);
1364 return result;
1365 }
1366
bios_parser_get_lttpr_caps(struct dc_bios * dcb,uint8_t * dce_caps)1367 static enum bp_result bios_parser_get_lttpr_caps(
1368 struct dc_bios *dcb,
1369 uint8_t *dce_caps)
1370 {
1371 struct bios_parser *bp = BP_FROM_DCB(dcb);
1372 enum bp_result result = BP_RESULT_UNSUPPORTED;
1373 struct atom_common_table_header *header;
1374 struct atom_data_revision tbl_revision;
1375
1376 if (!DATA_TABLES(dce_info))
1377 return BP_RESULT_UNSUPPORTED;
1378
1379 *dce_caps = 0;
1380 header = GET_IMAGE(struct atom_common_table_header,
1381 DATA_TABLES(dce_info));
1382 get_atom_data_table_revision(header, &tbl_revision);
1383 switch (tbl_revision.major) {
1384 case 4:
1385 switch (tbl_revision.minor) {
1386 case 1:
1387 result = get_disp_caps_v4_1(bp, dce_caps);
1388 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1389 break;
1390 case 2:
1391 result = get_disp_caps_v4_2(bp, dce_caps);
1392 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1393 break;
1394 case 3:
1395 result = get_disp_caps_v4_3(bp, dce_caps);
1396 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1397 break;
1398 case 4:
1399 result = get_disp_caps_v4_4(bp, dce_caps);
1400 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1401 break;
1402 case 5:
1403 result = get_disp_caps_v4_5(bp, dce_caps);
1404 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1405 break;
1406 default:
1407 break;
1408 }
1409 break;
1410 default:
1411 break;
1412 }
1413 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);
1414 if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) {
1415 *dce_caps = 1;
1416 DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled");
1417 }
1418 return result;
1419 }
1420
get_embedded_panel_info_v2_1(struct bios_parser * bp,struct embedded_panel_info * info)1421 static enum bp_result get_embedded_panel_info_v2_1(
1422 struct bios_parser *bp,
1423 struct embedded_panel_info *info)
1424 {
1425 struct lcd_info_v2_1 *lvds;
1426
1427 if (!info)
1428 return BP_RESULT_BADINPUT;
1429
1430 if (!DATA_TABLES(lcd_info))
1431 return BP_RESULT_UNSUPPORTED;
1432
1433 lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));
1434
1435 if (!lvds)
1436 return BP_RESULT_BADBIOSTABLE;
1437
1438 /* TODO: previous vv1_3, should v2_1 */
1439 if (!((lvds->table_header.format_revision == 2)
1440 && (lvds->table_header.content_revision >= 1)))
1441 return BP_RESULT_UNSUPPORTED;
1442
1443 memset(info, 0, sizeof(struct embedded_panel_info));
1444
1445 /* We need to convert from 10KHz units into KHz units */
1446 info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
1447 /* usHActive does not include borders, according to VBIOS team */
1448 info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);
1449 /* usHBlanking_Time includes borders, so we should really be
1450 * subtractingborders duing this translation, but LVDS generally
1451 * doesn't have borders, so we should be okay leaving this as is for
1452 * now. May need to revisit if we ever have LVDS with borders
1453 */
1454 info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);
1455 /* usVActive does not include borders, according to VBIOS team*/
1456 info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);
1457 /* usVBlanking_Time includes borders, so we should really be
1458 * subtracting borders duing this translation, but LVDS generally
1459 * doesn't have borders, so we should be okay leaving this as is for
1460 * now. May need to revisit if we ever have LVDS with borders
1461 */
1462 info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);
1463 info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);
1464 info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);
1465 info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);
1466 info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);
1467 info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
1468 info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
1469
1470 /* not provided by VBIOS */
1471 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
1472
1473 info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
1474 & ATOM_HSYNC_POLARITY);
1475 info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
1476 & ATOM_VSYNC_POLARITY);
1477
1478 /* not provided by VBIOS */
1479 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
1480
1481 info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1482 & ATOM_H_REPLICATIONBY2);
1483 info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1484 & ATOM_V_REPLICATIONBY2);
1485 info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo
1486 & ATOM_COMPOSITESYNC);
1487 info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
1488
1489 /* not provided by VBIOS*/
1490 info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
1491 /* not provided by VBIOS*/
1492 info->ss_id = 0;
1493
1494 info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
1495
1496 return BP_RESULT_OK;
1497 }
1498
bios_parser_get_embedded_panel_info(struct dc_bios * dcb,struct embedded_panel_info * info)1499 static enum bp_result bios_parser_get_embedded_panel_info(
1500 struct dc_bios *dcb,
1501 struct embedded_panel_info *info)
1502 {
1503 struct bios_parser
1504 *bp = BP_FROM_DCB(dcb);
1505 struct atom_common_table_header *header;
1506 struct atom_data_revision tbl_revision;
1507
1508 if (!DATA_TABLES(lcd_info))
1509 return BP_RESULT_FAILURE;
1510
1511 header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));
1512
1513 if (!header)
1514 return BP_RESULT_BADBIOSTABLE;
1515
1516 get_atom_data_table_revision(header, &tbl_revision);
1517
1518 switch (tbl_revision.major) {
1519 case 2:
1520 switch (tbl_revision.minor) {
1521 case 1:
1522 return get_embedded_panel_info_v2_1(bp, info);
1523 default:
1524 break;
1525 }
1526 break;
1527 default:
1528 break;
1529 }
1530
1531 return BP_RESULT_FAILURE;
1532 }
1533
get_support_mask_for_device_id(struct device_id device_id)1534 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
1535 {
1536 enum dal_device_type device_type = device_id.device_type;
1537 uint32_t enum_id = device_id.enum_id;
1538
1539 switch (device_type) {
1540 case DEVICE_TYPE_LCD:
1541 switch (enum_id) {
1542 case 1:
1543 return ATOM_DISPLAY_LCD1_SUPPORT;
1544 default:
1545 break;
1546 }
1547 break;
1548 case DEVICE_TYPE_DFP:
1549 switch (enum_id) {
1550 case 1:
1551 return ATOM_DISPLAY_DFP1_SUPPORT;
1552 case 2:
1553 return ATOM_DISPLAY_DFP2_SUPPORT;
1554 case 3:
1555 return ATOM_DISPLAY_DFP3_SUPPORT;
1556 case 4:
1557 return ATOM_DISPLAY_DFP4_SUPPORT;
1558 case 5:
1559 return ATOM_DISPLAY_DFP5_SUPPORT;
1560 case 6:
1561 return ATOM_DISPLAY_DFP6_SUPPORT;
1562 default:
1563 break;
1564 }
1565 break;
1566 default:
1567 break;
1568 }
1569
1570 /* Unidentified device ID, return empty support mask. */
1571 return 0;
1572 }
1573
bios_parser_is_device_id_supported(struct dc_bios * dcb,struct device_id id)1574 static bool bios_parser_is_device_id_supported(
1575 struct dc_bios *dcb,
1576 struct device_id id)
1577 {
1578 struct bios_parser *bp = BP_FROM_DCB(dcb);
1579
1580 uint32_t mask = get_support_mask_for_device_id(id);
1581
1582 switch (bp->object_info_tbl.revision.minor) {
1583 case 4:
1584 default:
1585 return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & mask) != 0;
1586 break;
1587 case 5:
1588 return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0;
1589 break;
1590 }
1591
1592 return false;
1593 }
1594
bios_parser_get_ss_entry_number(struct dc_bios * dcb,enum as_signal_type signal)1595 static uint32_t bios_parser_get_ss_entry_number(
1596 struct dc_bios *dcb,
1597 enum as_signal_type signal)
1598 {
1599 /* TODO: DAL2 atomfirmware implementation does not need this.
1600 * why DAL3 need this?
1601 */
1602 return 1;
1603 }
1604
bios_parser_transmitter_control(struct dc_bios * dcb,struct bp_transmitter_control * cntl)1605 static enum bp_result bios_parser_transmitter_control(
1606 struct dc_bios *dcb,
1607 struct bp_transmitter_control *cntl)
1608 {
1609 struct bios_parser *bp = BP_FROM_DCB(dcb);
1610
1611 if (!bp->cmd_tbl.transmitter_control)
1612 return BP_RESULT_FAILURE;
1613
1614 return bp->cmd_tbl.transmitter_control(bp, cntl);
1615 }
1616
bios_parser_encoder_control(struct dc_bios * dcb,struct bp_encoder_control * cntl)1617 static enum bp_result bios_parser_encoder_control(
1618 struct dc_bios *dcb,
1619 struct bp_encoder_control *cntl)
1620 {
1621 struct bios_parser *bp = BP_FROM_DCB(dcb);
1622
1623 if (!bp->cmd_tbl.dig_encoder_control)
1624 return BP_RESULT_FAILURE;
1625
1626 return bp->cmd_tbl.dig_encoder_control(bp, cntl);
1627 }
1628
bios_parser_set_pixel_clock(struct dc_bios * dcb,struct bp_pixel_clock_parameters * bp_params)1629 static enum bp_result bios_parser_set_pixel_clock(
1630 struct dc_bios *dcb,
1631 struct bp_pixel_clock_parameters *bp_params)
1632 {
1633 struct bios_parser *bp = BP_FROM_DCB(dcb);
1634
1635 if (!bp->cmd_tbl.set_pixel_clock)
1636 return BP_RESULT_FAILURE;
1637
1638 return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
1639 }
1640
bios_parser_set_dce_clock(struct dc_bios * dcb,struct bp_set_dce_clock_parameters * bp_params)1641 static enum bp_result bios_parser_set_dce_clock(
1642 struct dc_bios *dcb,
1643 struct bp_set_dce_clock_parameters *bp_params)
1644 {
1645 struct bios_parser *bp = BP_FROM_DCB(dcb);
1646
1647 if (!bp->cmd_tbl.set_dce_clock)
1648 return BP_RESULT_FAILURE;
1649
1650 return bp->cmd_tbl.set_dce_clock(bp, bp_params);
1651 }
1652
bios_parser_program_crtc_timing(struct dc_bios * dcb,struct bp_hw_crtc_timing_parameters * bp_params)1653 static enum bp_result bios_parser_program_crtc_timing(
1654 struct dc_bios *dcb,
1655 struct bp_hw_crtc_timing_parameters *bp_params)
1656 {
1657 struct bios_parser *bp = BP_FROM_DCB(dcb);
1658
1659 if (!bp->cmd_tbl.set_crtc_timing)
1660 return BP_RESULT_FAILURE;
1661
1662 return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
1663 }
1664
bios_parser_enable_crtc(struct dc_bios * dcb,enum controller_id id,bool enable)1665 static enum bp_result bios_parser_enable_crtc(
1666 struct dc_bios *dcb,
1667 enum controller_id id,
1668 bool enable)
1669 {
1670 struct bios_parser *bp = BP_FROM_DCB(dcb);
1671
1672 if (!bp->cmd_tbl.enable_crtc)
1673 return BP_RESULT_FAILURE;
1674
1675 return bp->cmd_tbl.enable_crtc(bp, id, enable);
1676 }
1677
bios_parser_enable_disp_power_gating(struct dc_bios * dcb,enum controller_id controller_id,enum bp_pipe_control_action action)1678 static enum bp_result bios_parser_enable_disp_power_gating(
1679 struct dc_bios *dcb,
1680 enum controller_id controller_id,
1681 enum bp_pipe_control_action action)
1682 {
1683 struct bios_parser *bp = BP_FROM_DCB(dcb);
1684
1685 if (!bp->cmd_tbl.enable_disp_power_gating)
1686 return BP_RESULT_FAILURE;
1687
1688 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
1689 action);
1690 }
1691
bios_parser_enable_lvtma_control(struct dc_bios * dcb,uint8_t uc_pwr_on,uint8_t panel_instance,uint8_t bypass_panel_control_wait)1692 static enum bp_result bios_parser_enable_lvtma_control(
1693 struct dc_bios *dcb,
1694 uint8_t uc_pwr_on,
1695 uint8_t panel_instance,
1696 uint8_t bypass_panel_control_wait)
1697 {
1698 struct bios_parser *bp = BP_FROM_DCB(dcb);
1699
1700 if (!bp->cmd_tbl.enable_lvtma_control)
1701 return BP_RESULT_FAILURE;
1702
1703 return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on, panel_instance, bypass_panel_control_wait);
1704 }
1705
bios_parser_is_accelerated_mode(struct dc_bios * dcb)1706 static bool bios_parser_is_accelerated_mode(
1707 struct dc_bios *dcb)
1708 {
1709 return bios_is_accelerated_mode(dcb);
1710 }
1711
1712 /**
1713 * bios_parser_set_scratch_critical_state - update critical state bit
1714 * in VBIOS scratch register
1715 *
1716 * @dcb: pointer to the DC BIO
1717 * @state: set or reset state
1718 */
bios_parser_set_scratch_critical_state(struct dc_bios * dcb,bool state)1719 static void bios_parser_set_scratch_critical_state(
1720 struct dc_bios *dcb,
1721 bool state)
1722 {
1723 bios_set_scratch_critical_state(dcb, state);
1724 }
1725
1726 struct atom_dig_transmitter_info_header_v5_3 {
1727 struct atom_common_table_header table_header;
1728 uint16_t dpphy_hdmi_settings_offset;
1729 uint16_t dpphy_dvi_settings_offset;
1730 uint16_t dpphy_dp_setting_table_offset;
1731 uint16_t uniphy_xbar_settings_v2_table_offset;
1732 uint16_t dpphy_internal_reg_overide_offset;
1733 };
1734
bios_parser_get_firmware_info(struct dc_bios * dcb,struct dc_firmware_info * info)1735 static enum bp_result bios_parser_get_firmware_info(
1736 struct dc_bios *dcb,
1737 struct dc_firmware_info *info)
1738 {
1739 struct bios_parser *bp = BP_FROM_DCB(dcb);
1740 static enum bp_result result = BP_RESULT_BADBIOSTABLE;
1741 struct atom_common_table_header *header;
1742
1743 struct atom_data_revision revision;
1744
1745 if (info && DATA_TABLES(firmwareinfo)) {
1746 header = GET_IMAGE(struct atom_common_table_header,
1747 DATA_TABLES(firmwareinfo));
1748 get_atom_data_table_revision(header, &revision);
1749 switch (revision.major) {
1750 case 3:
1751 switch (revision.minor) {
1752 case 1:
1753 result = get_firmware_info_v3_1(bp, info);
1754 break;
1755 case 2:
1756 case 3:
1757 result = get_firmware_info_v3_2(bp, info);
1758 break;
1759 case 4:
1760 result = get_firmware_info_v3_4(bp, info);
1761 break;
1762 default:
1763 break;
1764 }
1765 break;
1766 default:
1767 break;
1768 }
1769 }
1770
1771 return result;
1772 }
1773
get_firmware_info_v3_1(struct bios_parser * bp,struct dc_firmware_info * info)1774 static enum bp_result get_firmware_info_v3_1(
1775 struct bios_parser *bp,
1776 struct dc_firmware_info *info)
1777 {
1778 struct atom_firmware_info_v3_1 *firmware_info;
1779 struct atom_display_controller_info_v4_1 *dce_info = NULL;
1780
1781 if (!info)
1782 return BP_RESULT_BADINPUT;
1783
1784 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,
1785 DATA_TABLES(firmwareinfo));
1786
1787 dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1788 DATA_TABLES(dce_info));
1789
1790 if (!firmware_info || !dce_info)
1791 return BP_RESULT_BADBIOSTABLE;
1792
1793 memset(info, 0, sizeof(*info));
1794
1795 /* Pixel clock pll information. */
1796 /* We need to convert from 10KHz units into KHz units */
1797 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1798 info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;
1799
1800 /* 27MHz for Vega10: */
1801 info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1802
1803 /* Hardcode frequency if BIOS gives no DCE Ref Clk */
1804 if (info->pll_info.crystal_frequency == 0)
1805 info->pll_info.crystal_frequency = 27000;
1806 /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1807 info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10;
1808 info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1809
1810 /* Get GPU PLL VCO Clock */
1811
1812 if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1813 /* VBIOS gives in 10KHz */
1814 info->smu_gpu_pll_output_freq =
1815 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1816 }
1817
1818 info->oem_i2c_present = false;
1819
1820 return BP_RESULT_OK;
1821 }
1822
get_firmware_info_v3_2(struct bios_parser * bp,struct dc_firmware_info * info)1823 static enum bp_result get_firmware_info_v3_2(
1824 struct bios_parser *bp,
1825 struct dc_firmware_info *info)
1826 {
1827 struct atom_firmware_info_v3_2 *firmware_info;
1828 struct atom_display_controller_info_v4_1 *dce_info = NULL;
1829 struct atom_common_table_header *header;
1830 struct atom_data_revision revision;
1831 struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;
1832 struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;
1833
1834 if (!info)
1835 return BP_RESULT_BADINPUT;
1836
1837 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,
1838 DATA_TABLES(firmwareinfo));
1839
1840 dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1841 DATA_TABLES(dce_info));
1842
1843 if (!firmware_info || !dce_info)
1844 return BP_RESULT_BADBIOSTABLE;
1845
1846 memset(info, 0, sizeof(*info));
1847
1848 header = GET_IMAGE(struct atom_common_table_header,
1849 DATA_TABLES(smu_info));
1850 get_atom_data_table_revision(header, &revision);
1851
1852 if (revision.minor == 2) {
1853 /* Vega12 */
1854 smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
1855 DATA_TABLES(smu_info));
1856 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
1857 if (!smu_info_v3_2)
1858 return BP_RESULT_BADBIOSTABLE;
1859
1860 info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
1861 } else if (revision.minor == 3) {
1862 /* Vega20 */
1863 smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
1864 DATA_TABLES(smu_info));
1865 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
1866 if (!smu_info_v3_3)
1867 return BP_RESULT_BADBIOSTABLE;
1868
1869 info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
1870 }
1871
1872 // We need to convert from 10KHz units into KHz units.
1873 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1874
1875 /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */
1876 info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1877 /* Hardcode frequency if BIOS gives no DCE Ref Clk */
1878 if (info->pll_info.crystal_frequency == 0) {
1879 if (revision.minor == 2)
1880 info->pll_info.crystal_frequency = 27000;
1881 else if (revision.minor == 3)
1882 info->pll_info.crystal_frequency = 100000;
1883 }
1884 /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1885 info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10;
1886 info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1887
1888 /* Get GPU PLL VCO Clock */
1889 if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1890 if (revision.minor == 2)
1891 info->smu_gpu_pll_output_freq =
1892 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1893 else if (revision.minor == 3)
1894 info->smu_gpu_pll_output_freq =
1895 bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
1896 }
1897
1898 if (firmware_info->board_i2c_feature_id == 0x2) {
1899 info->oem_i2c_present = true;
1900 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
1901 } else {
1902 info->oem_i2c_present = false;
1903 }
1904
1905 return BP_RESULT_OK;
1906 }
1907
get_firmware_info_v3_4(struct bios_parser * bp,struct dc_firmware_info * info)1908 static enum bp_result get_firmware_info_v3_4(
1909 struct bios_parser *bp,
1910 struct dc_firmware_info *info)
1911 {
1912 struct atom_firmware_info_v3_4 *firmware_info;
1913 struct atom_common_table_header *header;
1914 struct atom_data_revision revision;
1915 struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
1916 struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
1917
1918 struct atom_smu_info_v3_5 *smu_info_v3_5 = NULL;
1919 struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;
1920 struct atom_smu_info_v4_0 *smu_info_v4_0 = NULL;
1921
1922 if (!info)
1923 return BP_RESULT_BADINPUT;
1924
1925 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
1926 DATA_TABLES(firmwareinfo));
1927
1928 if (!firmware_info)
1929 return BP_RESULT_BADBIOSTABLE;
1930
1931 memset(info, 0, sizeof(*info));
1932
1933 header = GET_IMAGE(struct atom_common_table_header,
1934 DATA_TABLES(dce_info));
1935
1936 get_atom_data_table_revision(header, &revision);
1937
1938 switch (revision.major) {
1939 case 4:
1940 switch (revision.minor) {
1941 case 5:
1942 dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,
1943 DATA_TABLES(dce_info));
1944
1945 if (!dce_info_v4_5)
1946 return BP_RESULT_BADBIOSTABLE;
1947
1948 /* 100MHz expected */
1949 info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;
1950 info->dp_phy_ref_clk = dce_info_v4_5->dpphy_refclk_10khz * 10;
1951 /* 50MHz expected */
1952 info->i2c_engine_ref_clk = dce_info_v4_5->i2c_engine_refclk_10khz * 10;
1953
1954 /* For DCN32/321 Display PLL VCO Frequency from dce_info_v4_5 may not be reliable */
1955 break;
1956
1957 case 4:
1958 dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
1959 DATA_TABLES(dce_info));
1960
1961 if (!dce_info_v4_4)
1962 return BP_RESULT_BADBIOSTABLE;
1963
1964 /* 100MHz expected */
1965 info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
1966 info->dp_phy_ref_clk = dce_info_v4_4->dpphy_refclk_10khz * 10;
1967 /* 50MHz expected */
1968 info->i2c_engine_ref_clk = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
1969
1970 /* Get SMU Display PLL VCO Frequency in KHz*/
1971 info->smu_gpu_pll_output_freq = dce_info_v4_4->dispclk_pll_vco_freq * 10;
1972 break;
1973
1974 default:
1975 /* should not come here, keep as backup, as was before */
1976 dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
1977 DATA_TABLES(dce_info));
1978
1979 if (!dce_info_v4_1)
1980 return BP_RESULT_BADBIOSTABLE;
1981
1982 info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
1983 info->dp_phy_ref_clk = dce_info_v4_1->dpphy_refclk_10khz * 10;
1984 info->i2c_engine_ref_clk = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
1985 break;
1986 }
1987 break;
1988
1989 default:
1990 ASSERT(0);
1991 break;
1992 }
1993
1994 header = GET_IMAGE(struct atom_common_table_header,
1995 DATA_TABLES(smu_info));
1996 get_atom_data_table_revision(header, &revision);
1997
1998 switch (revision.major) {
1999 case 3:
2000 switch (revision.minor) {
2001 case 5:
2002 smu_info_v3_5 = GET_IMAGE(struct atom_smu_info_v3_5,
2003 DATA_TABLES(smu_info));
2004
2005 if (!smu_info_v3_5)
2006 return BP_RESULT_BADBIOSTABLE;
2007 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_5->gpuclk_ss_percentage);
2008 info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10;
2009 break;
2010
2011 default:
2012 break;
2013 }
2014 break;
2015
2016 case 4:
2017 switch (revision.minor) {
2018 case 0:
2019 smu_info_v4_0 = GET_IMAGE(struct atom_smu_info_v4_0,
2020 DATA_TABLES(smu_info));
2021
2022 if (!smu_info_v4_0)
2023 return BP_RESULT_BADBIOSTABLE;
2024
2025 /* For DCN32/321 bootup DCFCLK from smu_info_v4_0 may not be reliable */
2026 break;
2027
2028 default:
2029 break;
2030 }
2031 break;
2032
2033 default:
2034 break;
2035 }
2036
2037 // We need to convert from 10KHz units into KHz units.
2038 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
2039
2040 if (firmware_info->board_i2c_feature_id == 0x2) {
2041 info->oem_i2c_present = true;
2042 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
2043 } else {
2044 info->oem_i2c_present = false;
2045 }
2046
2047 return BP_RESULT_OK;
2048 }
2049
bios_parser_get_encoder_cap_info(struct dc_bios * dcb,struct graphics_object_id object_id,struct bp_encoder_cap_info * info)2050 static enum bp_result bios_parser_get_encoder_cap_info(
2051 struct dc_bios *dcb,
2052 struct graphics_object_id object_id,
2053 struct bp_encoder_cap_info *info)
2054 {
2055 struct bios_parser *bp = BP_FROM_DCB(dcb);
2056 struct atom_display_object_path_v2 *object;
2057 struct atom_encoder_caps_record *record = NULL;
2058
2059 if (!info)
2060 return BP_RESULT_BADINPUT;
2061
2062 #if defined(CONFIG_DRM_AMD_DC_FP)
2063 /* encoder cap record not available in v1_5 */
2064 if (bp->object_info_tbl.revision.minor == 5)
2065 return BP_RESULT_NORECORD;
2066 #endif
2067
2068 object = get_bios_object(bp, object_id);
2069
2070 if (!object)
2071 return BP_RESULT_BADINPUT;
2072
2073 record = get_encoder_cap_record(bp, object);
2074 if (!record)
2075 return BP_RESULT_NORECORD;
2076 DC_LOG_BIOS("record->encodercaps 0x%x for object_id 0x%x", record->encodercaps, object_id.id);
2077
2078 info->DP_HBR2_CAP = (record->encodercaps &
2079 ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
2080 info->DP_HBR2_EN = (record->encodercaps &
2081 ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
2082 info->DP_HBR3_EN = (record->encodercaps &
2083 ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
2084 info->HDMI_6GB_EN = (record->encodercaps &
2085 ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
2086 info->IS_DP2_CAPABLE = (record->encodercaps &
2087 ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
2088 info->DP_UHBR10_EN = (record->encodercaps &
2089 ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
2090 info->DP_UHBR13_5_EN = (record->encodercaps &
2091 ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
2092 info->DP_UHBR20_EN = (record->encodercaps &
2093 ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
2094 info->DP_IS_USB_C = (record->encodercaps &
2095 ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
2096 DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);
2097
2098 return BP_RESULT_OK;
2099 }
2100
2101
get_encoder_cap_record(struct bios_parser * bp,struct atom_display_object_path_v2 * object)2102 static struct atom_encoder_caps_record *get_encoder_cap_record(
2103 struct bios_parser *bp,
2104 struct atom_display_object_path_v2 *object)
2105 {
2106 struct atom_common_record_header *header;
2107 uint32_t offset;
2108
2109 if (!object) {
2110 BREAK_TO_DEBUGGER(); /* Invalid object */
2111 return NULL;
2112 }
2113
2114 offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
2115
2116 for (;;) {
2117 header = GET_IMAGE(struct atom_common_record_header, offset);
2118
2119 if (!header)
2120 return NULL;
2121
2122 offset += header->record_size;
2123
2124 if (header->record_type == LAST_RECORD_TYPE ||
2125 !header->record_size)
2126 break;
2127
2128 if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
2129 continue;
2130
2131 if (sizeof(struct atom_encoder_caps_record) <=
2132 header->record_size)
2133 return (struct atom_encoder_caps_record *)header;
2134 }
2135
2136 return NULL;
2137 }
2138
get_disp_connector_caps_record(struct bios_parser * bp,struct atom_display_object_path_v2 * object)2139 static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
2140 struct bios_parser *bp,
2141 struct atom_display_object_path_v2 *object)
2142 {
2143 struct atom_common_record_header *header;
2144 uint32_t offset;
2145
2146 if (!object) {
2147 BREAK_TO_DEBUGGER(); /* Invalid object */
2148 return NULL;
2149 }
2150
2151 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2152
2153 for (;;) {
2154 header = GET_IMAGE(struct atom_common_record_header, offset);
2155
2156 if (!header)
2157 return NULL;
2158
2159 offset += header->record_size;
2160
2161 if (header->record_type == LAST_RECORD_TYPE ||
2162 !header->record_size)
2163 break;
2164
2165 if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
2166 continue;
2167
2168 if (sizeof(struct atom_disp_connector_caps_record) <=
2169 header->record_size)
2170 return (struct atom_disp_connector_caps_record *)header;
2171 }
2172
2173 return NULL;
2174 }
2175
get_connector_caps_record(struct bios_parser * bp,struct atom_display_object_path_v3 * object)2176 static struct atom_connector_caps_record *get_connector_caps_record(struct bios_parser *bp,
2177 struct atom_display_object_path_v3 *object)
2178 {
2179 struct atom_common_record_header *header;
2180 uint32_t offset;
2181
2182 if (!object) {
2183 BREAK_TO_DEBUGGER(); /* Invalid object */
2184 return NULL;
2185 }
2186
2187 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2188
2189 for (;;) {
2190 header = GET_IMAGE(struct atom_common_record_header, offset);
2191
2192 if (!header)
2193 return NULL;
2194
2195 offset += header->record_size;
2196
2197 if (header->record_type == ATOM_RECORD_END_TYPE ||
2198 !header->record_size)
2199 break;
2200
2201 if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)
2202 continue;
2203
2204 if (sizeof(struct atom_connector_caps_record) <= header->record_size)
2205 return (struct atom_connector_caps_record *)header;
2206 }
2207
2208 return NULL;
2209 }
2210
bios_parser_get_disp_connector_caps_info(struct dc_bios * dcb,struct graphics_object_id object_id,struct bp_disp_connector_caps_info * info)2211 static enum bp_result bios_parser_get_disp_connector_caps_info(
2212 struct dc_bios *dcb,
2213 struct graphics_object_id object_id,
2214 struct bp_disp_connector_caps_info *info)
2215 {
2216 struct bios_parser *bp = BP_FROM_DCB(dcb);
2217 struct atom_display_object_path_v2 *object;
2218
2219 struct atom_display_object_path_v3 *object_path_v3;
2220 struct atom_connector_caps_record *record_path_v3;
2221
2222 struct atom_disp_connector_caps_record *record = NULL;
2223
2224 if (!info)
2225 return BP_RESULT_BADINPUT;
2226
2227 switch (bp->object_info_tbl.revision.minor) {
2228 case 4:
2229 default:
2230 object = get_bios_object(bp, object_id);
2231
2232 if (!object)
2233 return BP_RESULT_BADINPUT;
2234
2235 record = get_disp_connector_caps_record(bp, object);
2236 if (!record)
2237 return BP_RESULT_NORECORD;
2238
2239 info->INTERNAL_DISPLAY =
2240 (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;
2241 info->INTERNAL_DISPLAY_BL =
2242 (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;
2243 break;
2244 case 5:
2245 object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2246
2247 if (!object_path_v3)
2248 return BP_RESULT_BADINPUT;
2249
2250 record_path_v3 = get_connector_caps_record(bp, object_path_v3);
2251 if (!record_path_v3)
2252 return BP_RESULT_NORECORD;
2253
2254 info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
2255 ? 1 : 0;
2256 info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
2257 ? 1 : 0;
2258 break;
2259 }
2260
2261 return BP_RESULT_OK;
2262 }
2263
get_connector_speed_cap_record(struct bios_parser * bp,struct atom_display_object_path_v3 * object)2264 static struct atom_connector_speed_record *get_connector_speed_cap_record(struct bios_parser *bp,
2265 struct atom_display_object_path_v3 *object)
2266 {
2267 struct atom_common_record_header *header;
2268 uint32_t offset;
2269
2270 if (!object) {
2271 BREAK_TO_DEBUGGER(); /* Invalid object */
2272 return NULL;
2273 }
2274
2275 offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2276
2277 for (;;) {
2278 header = GET_IMAGE(struct atom_common_record_header, offset);
2279
2280 if (!header)
2281 return NULL;
2282
2283 offset += header->record_size;
2284
2285 if (header->record_type == ATOM_RECORD_END_TYPE ||
2286 !header->record_size)
2287 break;
2288
2289 if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)
2290 continue;
2291
2292 if (sizeof(struct atom_connector_speed_record) <= header->record_size)
2293 return (struct atom_connector_speed_record *)header;
2294 }
2295
2296 return NULL;
2297 }
2298
bios_parser_get_connector_speed_cap_info(struct dc_bios * dcb,struct graphics_object_id object_id,struct bp_connector_speed_cap_info * info)2299 static enum bp_result bios_parser_get_connector_speed_cap_info(
2300 struct dc_bios *dcb,
2301 struct graphics_object_id object_id,
2302 struct bp_connector_speed_cap_info *info)
2303 {
2304 struct bios_parser *bp = BP_FROM_DCB(dcb);
2305 struct atom_display_object_path_v3 *object_path_v3;
2306 //struct atom_connector_speed_record *record = NULL;
2307 struct atom_connector_speed_record *record;
2308
2309 if (!info)
2310 return BP_RESULT_BADINPUT;
2311
2312 object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2313
2314 if (!object_path_v3)
2315 return BP_RESULT_BADINPUT;
2316
2317 record = get_connector_speed_cap_record(bp, object_path_v3);
2318 if (!record)
2319 return BP_RESULT_NORECORD;
2320
2321 info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;
2322 info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;
2323 info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;
2324 info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
2325 info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
2326 info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
2327 return BP_RESULT_OK;
2328 }
2329
get_vram_info_v23(struct bios_parser * bp,struct dc_vram_info * info)2330 static enum bp_result get_vram_info_v23(
2331 struct bios_parser *bp,
2332 struct dc_vram_info *info)
2333 {
2334 struct atom_vram_info_header_v2_3 *info_v23;
2335 static enum bp_result result = BP_RESULT_OK;
2336
2337 info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
2338 DATA_TABLES(vram_info));
2339
2340 if (info_v23 == NULL)
2341 return BP_RESULT_BADBIOSTABLE;
2342
2343 info->num_chans = info_v23->vram_module[0].channel_num;
2344 info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
2345
2346 return result;
2347 }
2348
get_vram_info_v24(struct bios_parser * bp,struct dc_vram_info * info)2349 static enum bp_result get_vram_info_v24(
2350 struct bios_parser *bp,
2351 struct dc_vram_info *info)
2352 {
2353 struct atom_vram_info_header_v2_4 *info_v24;
2354 static enum bp_result result = BP_RESULT_OK;
2355
2356 info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
2357 DATA_TABLES(vram_info));
2358
2359 if (info_v24 == NULL)
2360 return BP_RESULT_BADBIOSTABLE;
2361
2362 info->num_chans = info_v24->vram_module[0].channel_num;
2363 info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
2364
2365 return result;
2366 }
2367
get_vram_info_v25(struct bios_parser * bp,struct dc_vram_info * info)2368 static enum bp_result get_vram_info_v25(
2369 struct bios_parser *bp,
2370 struct dc_vram_info *info)
2371 {
2372 struct atom_vram_info_header_v2_5 *info_v25;
2373 static enum bp_result result = BP_RESULT_OK;
2374
2375 info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
2376 DATA_TABLES(vram_info));
2377
2378 if (info_v25 == NULL)
2379 return BP_RESULT_BADBIOSTABLE;
2380
2381 info->num_chans = info_v25->vram_module[0].channel_num;
2382 info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
2383
2384 return result;
2385 }
2386
get_vram_info_v30(struct bios_parser * bp,struct dc_vram_info * info)2387 static enum bp_result get_vram_info_v30(
2388 struct bios_parser *bp,
2389 struct dc_vram_info *info)
2390 {
2391 struct atom_vram_info_header_v3_0 *info_v30;
2392 enum bp_result result = BP_RESULT_OK;
2393
2394 info_v30 = GET_IMAGE(struct atom_vram_info_header_v3_0,
2395 DATA_TABLES(vram_info));
2396
2397 if (info_v30 == NULL)
2398 return BP_RESULT_BADBIOSTABLE;
2399
2400 info->num_chans = info_v30->channel_num;
2401 info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;
2402
2403 return result;
2404 }
2405
2406
2407 /*
2408 * get_integrated_info_v11
2409 *
2410 * @brief
2411 * Get V8 integrated BIOS information
2412 *
2413 * @param
2414 * bios_parser *bp - [in]BIOS parser handler to get master data table
2415 * integrated_info *info - [out] store and output integrated info
2416 *
2417 * @return
2418 * static enum bp_result - BP_RESULT_OK if information is available,
2419 * BP_RESULT_BADBIOSTABLE otherwise.
2420 */
get_integrated_info_v11(struct bios_parser * bp,struct integrated_info * info)2421 static enum bp_result get_integrated_info_v11(
2422 struct bios_parser *bp,
2423 struct integrated_info *info)
2424 {
2425 struct atom_integrated_system_info_v1_11 *info_v11;
2426 uint32_t i;
2427
2428 info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
2429 DATA_TABLES(integratedsysteminfo));
2430
2431 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
2432 if (info_v11 == NULL)
2433 return BP_RESULT_BADBIOSTABLE;
2434
2435 info->gpu_cap_info =
2436 le32_to_cpu(info_v11->gpucapinfo);
2437 /*
2438 * system_config: Bit[0] = 0 : PCIE power gating disabled
2439 * = 1 : PCIE power gating enabled
2440 * Bit[1] = 0 : DDR-PLL shut down disabled
2441 * = 1 : DDR-PLL shut down enabled
2442 * Bit[2] = 0 : DDR-PLL power down disabled
2443 * = 1 : DDR-PLL power down enabled
2444 */
2445 info->system_config = le32_to_cpu(info_v11->system_config);
2446 info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
2447 info->memory_type = info_v11->memorytype;
2448 info->ma_channel_number = info_v11->umachannelnumber;
2449 info->lvds_ss_percentage =
2450 le16_to_cpu(info_v11->lvds_ss_percentage);
2451 info->dp_ss_control =
2452 le16_to_cpu(info_v11->reserved1);
2453 info->lvds_sspread_rate_in_10hz =
2454 le16_to_cpu(info_v11->lvds_ss_rate_10hz);
2455 info->hdmi_ss_percentage =
2456 le16_to_cpu(info_v11->hdmi_ss_percentage);
2457 info->hdmi_sspread_rate_in_10hz =
2458 le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
2459 info->dvi_ss_percentage =
2460 le16_to_cpu(info_v11->dvi_ss_percentage);
2461 info->dvi_sspread_rate_in_10_hz =
2462 le16_to_cpu(info_v11->dvi_ss_rate_10hz);
2463 info->lvds_misc = info_v11->lvds_misc;
2464 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2465 info->ext_disp_conn_info.gu_id[i] =
2466 info_v11->extdispconninfo.guid[i];
2467 }
2468
2469 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2470 info->ext_disp_conn_info.path[i].device_connector_id =
2471 object_id_from_bios_object_id(
2472 le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
2473
2474 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2475 object_id_from_bios_object_id(
2476 le16_to_cpu(
2477 info_v11->extdispconninfo.path[i].ext_encoder_objid));
2478
2479 info->ext_disp_conn_info.path[i].device_tag =
2480 le16_to_cpu(
2481 info_v11->extdispconninfo.path[i].device_tag);
2482 info->ext_disp_conn_info.path[i].device_acpi_enum =
2483 le16_to_cpu(
2484 info_v11->extdispconninfo.path[i].device_acpi_enum);
2485 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2486 info_v11->extdispconninfo.path[i].auxddclut_index;
2487 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2488 info_v11->extdispconninfo.path[i].hpdlut_index;
2489 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2490 info_v11->extdispconninfo.path[i].channelmapping;
2491 info->ext_disp_conn_info.path[i].caps =
2492 le16_to_cpu(info_v11->extdispconninfo.path[i].caps);
2493 }
2494 info->ext_disp_conn_info.checksum =
2495 info_v11->extdispconninfo.checksum;
2496
2497 info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
2498 info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
2499 for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2500 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2501 info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2502 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2503 info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2504 }
2505 info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
2506 for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2507 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2508 info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2509 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2510 info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2511 }
2512
2513 info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
2514 info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
2515 for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2516 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2517 info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2518 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2519 info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2520 }
2521 info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
2522 for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2523 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2524 info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2525 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2526 info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2527 }
2528
2529 info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
2530 info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
2531 for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2532 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2533 info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2534 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2535 info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2536 }
2537 info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
2538 for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2539 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2540 info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2541 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2542 info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2543 }
2544
2545 info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
2546 info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
2547 for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2548 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2549 info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2550 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2551 info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2552 }
2553 info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
2554 for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2555 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2556 info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2557 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2558 info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2559 }
2560
2561
2562 /** TODO - review **/
2563 #if 0
2564 info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
2565 * 10;
2566 info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
2567 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2568
2569 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2570 /* Convert [10KHz] into [KHz] */
2571 info->disp_clk_voltage[i].max_supported_clk =
2572 le32_to_cpu(info_v11->sDISPCLK_Voltage[i].
2573 ulMaximumSupportedCLK) * 10;
2574 info->disp_clk_voltage[i].voltage_index =
2575 le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex);
2576 }
2577
2578 info->boot_up_req_display_vector =
2579 le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
2580 info->boot_up_nb_voltage =
2581 le16_to_cpu(info_v11->usBootUpNBVoltage);
2582 info->ext_disp_conn_info_offset =
2583 le16_to_cpu(info_v11->usExtDispConnInfoOffset);
2584 info->gmc_restore_reset_time =
2585 le32_to_cpu(info_v11->ulGMCRestoreResetTime);
2586 info->minimum_n_clk =
2587 le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
2588 for (i = 1; i < 4; ++i)
2589 info->minimum_n_clk =
2590 info->minimum_n_clk <
2591 le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
2592 info->minimum_n_clk : le32_to_cpu(
2593 info_v11->ulNbpStateNClkFreq[i]);
2594
2595 info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
2596 info->ddr_dll_power_up_time =
2597 le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
2598 info->ddr_pll_power_up_time =
2599 le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
2600 info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
2601 info->max_lvds_pclk_freq_in_single_link =
2602 le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2603 info->max_lvds_pclk_freq_in_single_link =
2604 le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2605 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2606 info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2607 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2608 info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2609 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2610 info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2611 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2612 info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2613 info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2614 info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2615 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2616 info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2617 info->lvds_off_to_on_delay_in_4ms =
2618 info_v11->ucLVDSOffToOnDelay_in4Ms;
2619 info->lvds_bit_depth_control_val =
2620 le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
2621
2622 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2623 /* Convert [10KHz] into [KHz] */
2624 info->avail_s_clk[i].supported_s_clk =
2625 le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
2626 * 10;
2627 info->avail_s_clk[i].voltage_index =
2628 le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
2629 info->avail_s_clk[i].voltage_id =
2630 le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
2631 }
2632 #endif /* TODO*/
2633
2634 return BP_RESULT_OK;
2635 }
2636
get_integrated_info_v2_1(struct bios_parser * bp,struct integrated_info * info)2637 static enum bp_result get_integrated_info_v2_1(
2638 struct bios_parser *bp,
2639 struct integrated_info *info)
2640 {
2641 struct atom_integrated_system_info_v2_1 *info_v2_1;
2642 uint32_t i;
2643
2644 info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
2645 DATA_TABLES(integratedsysteminfo));
2646 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
2647
2648 if (info_v2_1 == NULL)
2649 return BP_RESULT_BADBIOSTABLE;
2650
2651 info->gpu_cap_info =
2652 le32_to_cpu(info_v2_1->gpucapinfo);
2653 /*
2654 * system_config: Bit[0] = 0 : PCIE power gating disabled
2655 * = 1 : PCIE power gating enabled
2656 * Bit[1] = 0 : DDR-PLL shut down disabled
2657 * = 1 : DDR-PLL shut down enabled
2658 * Bit[2] = 0 : DDR-PLL power down disabled
2659 * = 1 : DDR-PLL power down enabled
2660 */
2661 info->system_config = le32_to_cpu(info_v2_1->system_config);
2662 info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
2663 info->memory_type = info_v2_1->memorytype;
2664 info->ma_channel_number = info_v2_1->umachannelnumber;
2665 info->dp_ss_control =
2666 le16_to_cpu(info_v2_1->reserved1);
2667
2668 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2669 info->ext_disp_conn_info.gu_id[i] =
2670 info_v2_1->extdispconninfo.guid[i];
2671 }
2672
2673 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2674 info->ext_disp_conn_info.path[i].device_connector_id =
2675 object_id_from_bios_object_id(
2676 le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
2677
2678 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2679 object_id_from_bios_object_id(
2680 le16_to_cpu(
2681 info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
2682
2683 info->ext_disp_conn_info.path[i].device_tag =
2684 le16_to_cpu(
2685 info_v2_1->extdispconninfo.path[i].device_tag);
2686 info->ext_disp_conn_info.path[i].device_acpi_enum =
2687 le16_to_cpu(
2688 info_v2_1->extdispconninfo.path[i].device_acpi_enum);
2689 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2690 info_v2_1->extdispconninfo.path[i].auxddclut_index;
2691 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2692 info_v2_1->extdispconninfo.path[i].hpdlut_index;
2693 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2694 info_v2_1->extdispconninfo.path[i].channelmapping;
2695 info->ext_disp_conn_info.path[i].caps =
2696 le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
2697 }
2698
2699 info->ext_disp_conn_info.checksum =
2700 info_v2_1->extdispconninfo.checksum;
2701 info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
2702 info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
2703 for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2704 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2705 info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2706 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2707 info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2708 }
2709 info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
2710 for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2711 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2712 info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2713 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2714 info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2715 }
2716 info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
2717 info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
2718 for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2719 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2720 info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2721 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2722 info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2723 }
2724 info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
2725 for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2726 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2727 info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2728 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2729 info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2730 }
2731 info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
2732 info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
2733 for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2734 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2735 info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2736 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2737 info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2738 }
2739 info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
2740 for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2741 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2742 info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2743 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2744 info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2745 }
2746 info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
2747 info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
2748 for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2749 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2750 info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2751 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2752 info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2753 }
2754 info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
2755 for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2756 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2757 info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2758 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2759 info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2760 }
2761
2762 info->edp1_info.edp_backlight_pwm_hz =
2763 le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
2764 info->edp1_info.edp_ss_percentage =
2765 le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
2766 info->edp1_info.edp_ss_rate_10hz =
2767 le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
2768 info->edp1_info.edp_pwr_on_off_delay =
2769 info_v2_1->edp1_info.edp_pwr_on_off_delay;
2770 info->edp1_info.edp_pwr_on_vary_bl_to_blon =
2771 info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
2772 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
2773 info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
2774 info->edp1_info.edp_panel_bpc =
2775 info_v2_1->edp1_info.edp_panel_bpc;
2776 info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
2777
2778 info->edp2_info.edp_backlight_pwm_hz =
2779 le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
2780 info->edp2_info.edp_ss_percentage =
2781 le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
2782 info->edp2_info.edp_ss_rate_10hz =
2783 le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
2784 info->edp2_info.edp_pwr_on_off_delay =
2785 info_v2_1->edp2_info.edp_pwr_on_off_delay;
2786 info->edp2_info.edp_pwr_on_vary_bl_to_blon =
2787 info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
2788 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
2789 info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
2790 info->edp2_info.edp_panel_bpc =
2791 info_v2_1->edp2_info.edp_panel_bpc;
2792 info->edp2_info.edp_bootup_bl_level =
2793 info_v2_1->edp2_info.edp_bootup_bl_level;
2794
2795 return BP_RESULT_OK;
2796 }
2797
get_integrated_info_v2_2(struct bios_parser * bp,struct integrated_info * info)2798 static enum bp_result get_integrated_info_v2_2(
2799 struct bios_parser *bp,
2800 struct integrated_info *info)
2801 {
2802 struct atom_integrated_system_info_v2_2 *info_v2_2;
2803 uint32_t i;
2804
2805 info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
2806 DATA_TABLES(integratedsysteminfo));
2807
2808 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
2809
2810 if (info_v2_2 == NULL)
2811 return BP_RESULT_BADBIOSTABLE;
2812
2813 info->gpu_cap_info =
2814 le32_to_cpu(info_v2_2->gpucapinfo);
2815 /*
2816 * system_config: Bit[0] = 0 : PCIE power gating disabled
2817 * = 1 : PCIE power gating enabled
2818 * Bit[1] = 0 : DDR-PLL shut down disabled
2819 * = 1 : DDR-PLL shut down enabled
2820 * Bit[2] = 0 : DDR-PLL power down disabled
2821 * = 1 : DDR-PLL power down enabled
2822 */
2823 info->system_config = le32_to_cpu(info_v2_2->system_config);
2824 info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
2825 info->memory_type = info_v2_2->memorytype;
2826 info->ma_channel_number = info_v2_2->umachannelnumber;
2827 info->dp_ss_control =
2828 le16_to_cpu(info_v2_2->reserved1);
2829
2830 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2831 info->ext_disp_conn_info.gu_id[i] =
2832 info_v2_2->extdispconninfo.guid[i];
2833 }
2834
2835 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2836 info->ext_disp_conn_info.path[i].device_connector_id =
2837 object_id_from_bios_object_id(
2838 le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
2839
2840 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2841 object_id_from_bios_object_id(
2842 le16_to_cpu(
2843 info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
2844
2845 info->ext_disp_conn_info.path[i].device_tag =
2846 le16_to_cpu(
2847 info_v2_2->extdispconninfo.path[i].device_tag);
2848 info->ext_disp_conn_info.path[i].device_acpi_enum =
2849 le16_to_cpu(
2850 info_v2_2->extdispconninfo.path[i].device_acpi_enum);
2851 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2852 info_v2_2->extdispconninfo.path[i].auxddclut_index;
2853 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2854 info_v2_2->extdispconninfo.path[i].hpdlut_index;
2855 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2856 info_v2_2->extdispconninfo.path[i].channelmapping;
2857 info->ext_disp_conn_info.path[i].caps =
2858 le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
2859 }
2860
2861 info->ext_disp_conn_info.checksum =
2862 info_v2_2->extdispconninfo.checksum;
2863 info->ext_disp_conn_info.fixdpvoltageswing =
2864 info_v2_2->extdispconninfo.fixdpvoltageswing;
2865
2866 info->edp1_info.edp_backlight_pwm_hz =
2867 le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
2868 info->edp1_info.edp_ss_percentage =
2869 le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
2870 info->edp1_info.edp_ss_rate_10hz =
2871 le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
2872 info->edp1_info.edp_pwr_on_off_delay =
2873 info_v2_2->edp1_info.edp_pwr_on_off_delay;
2874 info->edp1_info.edp_pwr_on_vary_bl_to_blon =
2875 info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
2876 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
2877 info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
2878 info->edp1_info.edp_panel_bpc =
2879 info_v2_2->edp1_info.edp_panel_bpc;
2880 info->edp1_info.edp_bootup_bl_level =
2881
2882 info->edp2_info.edp_backlight_pwm_hz =
2883 le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
2884 info->edp2_info.edp_ss_percentage =
2885 le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
2886 info->edp2_info.edp_ss_rate_10hz =
2887 le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
2888 info->edp2_info.edp_pwr_on_off_delay =
2889 info_v2_2->edp2_info.edp_pwr_on_off_delay;
2890 info->edp2_info.edp_pwr_on_vary_bl_to_blon =
2891 info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
2892 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
2893 info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
2894 info->edp2_info.edp_panel_bpc =
2895 info_v2_2->edp2_info.edp_panel_bpc;
2896 info->edp2_info.edp_bootup_bl_level =
2897 info_v2_2->edp2_info.edp_bootup_bl_level;
2898
2899 return BP_RESULT_OK;
2900 }
2901
2902 /*
2903 * construct_integrated_info
2904 *
2905 * @brief
2906 * Get integrated BIOS information based on table revision
2907 *
2908 * @param
2909 * bios_parser *bp - [in]BIOS parser handler to get master data table
2910 * integrated_info *info - [out] store and output integrated info
2911 *
2912 * @return
2913 * static enum bp_result - BP_RESULT_OK if information is available,
2914 * BP_RESULT_BADBIOSTABLE otherwise.
2915 */
construct_integrated_info(struct bios_parser * bp,struct integrated_info * info)2916 static enum bp_result construct_integrated_info(
2917 struct bios_parser *bp,
2918 struct integrated_info *info)
2919 {
2920 static enum bp_result result = BP_RESULT_BADBIOSTABLE;
2921
2922 struct atom_common_table_header *header;
2923 struct atom_data_revision revision;
2924
2925 uint32_t i;
2926 uint32_t j;
2927
2928 if (info && DATA_TABLES(integratedsysteminfo)) {
2929 header = GET_IMAGE(struct atom_common_table_header,
2930 DATA_TABLES(integratedsysteminfo));
2931
2932 get_atom_data_table_revision(header, &revision);
2933
2934 switch (revision.major) {
2935 case 1:
2936 switch (revision.minor) {
2937 case 11:
2938 case 12:
2939 result = get_integrated_info_v11(bp, info);
2940 break;
2941 default:
2942 return result;
2943 }
2944 break;
2945 case 2:
2946 switch (revision.minor) {
2947 case 1:
2948 result = get_integrated_info_v2_1(bp, info);
2949 break;
2950 case 2:
2951 result = get_integrated_info_v2_2(bp, info);
2952 break;
2953 default:
2954 return result;
2955 }
2956 break;
2957 default:
2958 return result;
2959 }
2960 if (result == BP_RESULT_OK) {
2961
2962 DC_LOG_BIOS("edp1:\n"
2963 "\tedp_pwr_on_off_delay = %d\n"
2964 "\tedp_pwr_on_vary_bl_to_blon = %d\n"
2965 "\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
2966 "\tedp_bootup_bl_level = %d\n",
2967 info->edp1_info.edp_pwr_on_off_delay,
2968 info->edp1_info.edp_pwr_on_vary_bl_to_blon,
2969 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff,
2970 info->edp1_info.edp_bootup_bl_level);
2971 DC_LOG_BIOS("edp2:\n"
2972 "\tedp_pwr_on_off_delayv = %d\n"
2973 "\tedp_pwr_on_vary_bl_to_blon = %d\n"
2974 "\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
2975 "\tedp_bootup_bl_level = %d\n",
2976 info->edp2_info.edp_pwr_on_off_delay,
2977 info->edp2_info.edp_pwr_on_vary_bl_to_blon,
2978 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff,
2979 info->edp2_info.edp_bootup_bl_level);
2980 }
2981 }
2982
2983 if (result != BP_RESULT_OK)
2984 return result;
2985 else {
2986 // Log each external path
2987 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
2988 if (info->ext_disp_conn_info.path[i].device_tag != 0)
2989 DC_LOG_BIOS("integrated_info:For EXTERNAL DISPLAY PATH %d --------------\n"
2990 "DEVICE_TAG: 0x%x\n"
2991 "DEVICE_ACPI_ENUM: 0x%x\n"
2992 "DEVICE_CONNECTOR_ID: 0x%x\n"
2993 "EXT_AUX_DDC_LUT_INDEX: %d\n"
2994 "EXT_HPD_PIN_LUT_INDEX: %d\n"
2995 "EXT_ENCODER_OBJ_ID: 0x%x\n"
2996 "Encoder CAPS: 0x%x\n",
2997 i,
2998 info->ext_disp_conn_info.path[i].device_tag,
2999 info->ext_disp_conn_info.path[i].device_acpi_enum,
3000 info->ext_disp_conn_info.path[i].device_connector_id.id,
3001 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index,
3002 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index,
3003 info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
3004 info->ext_disp_conn_info.path[i].caps
3005 );
3006 if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
3007 DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3008 else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
3009 info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
3010 DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3011 }
3012 }
3013 // Log the Checksum and Voltage Swing
3014 DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"
3015 "Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",
3016 info->ext_disp_conn_info.checksum,
3017 info->ext_disp_conn_info.fixdpvoltageswing);
3018 if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {
3019 info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;
3020 DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);
3021 }
3022 }
3023 /* Sort voltage table from low to high*/
3024 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3025 for (j = i; j > 0; --j) {
3026 if (info->disp_clk_voltage[j].max_supported_clk <
3027 info->disp_clk_voltage[j-1].max_supported_clk)
3028 swap(info->disp_clk_voltage[j-1], info->disp_clk_voltage[j]);
3029 }
3030 }
3031
3032 return result;
3033 }
3034
bios_parser_get_vram_info(struct dc_bios * dcb,struct dc_vram_info * info)3035 static enum bp_result bios_parser_get_vram_info(
3036 struct dc_bios *dcb,
3037 struct dc_vram_info *info)
3038 {
3039 struct bios_parser *bp = BP_FROM_DCB(dcb);
3040 static enum bp_result result = BP_RESULT_BADBIOSTABLE;
3041 struct atom_common_table_header *header;
3042 struct atom_data_revision revision;
3043
3044 if (info && DATA_TABLES(vram_info)) {
3045 header = GET_IMAGE(struct atom_common_table_header,
3046 DATA_TABLES(vram_info));
3047
3048 get_atom_data_table_revision(header, &revision);
3049
3050 switch (revision.major) {
3051 case 2:
3052 switch (revision.minor) {
3053 case 3:
3054 result = get_vram_info_v23(bp, info);
3055 break;
3056 case 4:
3057 result = get_vram_info_v24(bp, info);
3058 break;
3059 case 5:
3060 result = get_vram_info_v25(bp, info);
3061 break;
3062 default:
3063 break;
3064 }
3065 break;
3066
3067 case 3:
3068 switch (revision.minor) {
3069 case 0:
3070 result = get_vram_info_v30(bp, info);
3071 break;
3072 default:
3073 break;
3074 }
3075 break;
3076
3077 default:
3078 return result;
3079 }
3080
3081 }
3082 return result;
3083 }
3084
bios_parser_create_integrated_info(struct dc_bios * dcb)3085 static struct integrated_info *bios_parser_create_integrated_info(
3086 struct dc_bios *dcb)
3087 {
3088 struct bios_parser *bp = BP_FROM_DCB(dcb);
3089 struct integrated_info *info;
3090
3091 info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
3092
3093 if (info == NULL) {
3094 ASSERT_CRITICAL(0);
3095 return NULL;
3096 }
3097
3098 if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3099 return info;
3100
3101 kfree(info);
3102
3103 return NULL;
3104 }
3105
update_slot_layout_info(struct dc_bios * dcb,unsigned int i,struct slot_layout_info * slot_layout_info)3106 static enum bp_result update_slot_layout_info(
3107 struct dc_bios *dcb,
3108 unsigned int i,
3109 struct slot_layout_info *slot_layout_info)
3110 {
3111 unsigned int record_offset;
3112 unsigned int j;
3113 struct atom_display_object_path_v2 *object;
3114 struct atom_bracket_layout_record *record;
3115 struct atom_common_record_header *record_header;
3116 static enum bp_result result;
3117 struct bios_parser *bp;
3118 struct object_info_table *tbl;
3119 struct display_object_info_table_v1_4 *v1_4;
3120
3121 record = NULL;
3122 record_header = NULL;
3123 result = BP_RESULT_NORECORD;
3124
3125 bp = BP_FROM_DCB(dcb);
3126 tbl = &bp->object_info_tbl;
3127 v1_4 = tbl->v1_4;
3128
3129 object = &v1_4->display_path[i];
3130 record_offset = (unsigned int)
3131 (object->disp_recordoffset) +
3132 (unsigned int)(bp->object_info_tbl_offset);
3133
3134 for (;;) {
3135
3136 record_header = (struct atom_common_record_header *)
3137 GET_IMAGE(struct atom_common_record_header,
3138 record_offset);
3139 if (record_header == NULL) {
3140 result = BP_RESULT_BADBIOSTABLE;
3141 break;
3142 }
3143
3144 /* the end of the list */
3145 if (record_header->record_type == 0xff ||
3146 record_header->record_size == 0) {
3147 break;
3148 }
3149
3150 if (record_header->record_type ==
3151 ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3152 sizeof(struct atom_bracket_layout_record)
3153 <= record_header->record_size) {
3154 record = (struct atom_bracket_layout_record *)
3155 (record_header);
3156 result = BP_RESULT_OK;
3157 break;
3158 }
3159
3160 record_offset += record_header->record_size;
3161 }
3162
3163 /* return if the record not found */
3164 if (result != BP_RESULT_OK)
3165 return result;
3166
3167 /* get slot sizes */
3168 slot_layout_info->length = record->bracketlen;
3169 slot_layout_info->width = record->bracketwidth;
3170
3171 /* get info for each connector in the slot */
3172 slot_layout_info->num_of_connectors = record->conn_num;
3173 for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3174 slot_layout_info->connectors[j].connector_type =
3175 (enum connector_layout_type)
3176 (record->conn_info[j].connector_type);
3177 switch (record->conn_info[j].connector_type) {
3178 case CONNECTOR_TYPE_DVI_D:
3179 slot_layout_info->connectors[j].connector_type =
3180 CONNECTOR_LAYOUT_TYPE_DVI_D;
3181 slot_layout_info->connectors[j].length =
3182 CONNECTOR_SIZE_DVI;
3183 break;
3184
3185 case CONNECTOR_TYPE_HDMI:
3186 slot_layout_info->connectors[j].connector_type =
3187 CONNECTOR_LAYOUT_TYPE_HDMI;
3188 slot_layout_info->connectors[j].length =
3189 CONNECTOR_SIZE_HDMI;
3190 break;
3191
3192 case CONNECTOR_TYPE_DISPLAY_PORT:
3193 slot_layout_info->connectors[j].connector_type =
3194 CONNECTOR_LAYOUT_TYPE_DP;
3195 slot_layout_info->connectors[j].length =
3196 CONNECTOR_SIZE_DP;
3197 break;
3198
3199 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3200 slot_layout_info->connectors[j].connector_type =
3201 CONNECTOR_LAYOUT_TYPE_MINI_DP;
3202 slot_layout_info->connectors[j].length =
3203 CONNECTOR_SIZE_MINI_DP;
3204 break;
3205
3206 default:
3207 slot_layout_info->connectors[j].connector_type =
3208 CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3209 slot_layout_info->connectors[j].length =
3210 CONNECTOR_SIZE_UNKNOWN;
3211 }
3212
3213 slot_layout_info->connectors[j].position =
3214 record->conn_info[j].position;
3215 slot_layout_info->connectors[j].connector_id =
3216 object_id_from_bios_object_id(
3217 record->conn_info[j].connectorobjid);
3218 }
3219 return result;
3220 }
3221
update_slot_layout_info_v2(struct dc_bios * dcb,unsigned int i,struct slot_layout_info * slot_layout_info)3222 static enum bp_result update_slot_layout_info_v2(
3223 struct dc_bios *dcb,
3224 unsigned int i,
3225 struct slot_layout_info *slot_layout_info)
3226 {
3227 unsigned int record_offset;
3228 struct atom_display_object_path_v3 *object;
3229 struct atom_bracket_layout_record_v2 *record;
3230 struct atom_common_record_header *record_header;
3231 static enum bp_result result;
3232 struct bios_parser *bp;
3233 struct object_info_table *tbl;
3234 struct display_object_info_table_v1_5 *v1_5;
3235 struct graphics_object_id connector_id;
3236
3237 record = NULL;
3238 record_header = NULL;
3239 result = BP_RESULT_NORECORD;
3240
3241 bp = BP_FROM_DCB(dcb);
3242 tbl = &bp->object_info_tbl;
3243 v1_5 = tbl->v1_5;
3244
3245 object = &v1_5->display_path[i];
3246 record_offset = (unsigned int)
3247 (object->disp_recordoffset) +
3248 (unsigned int)(bp->object_info_tbl_offset);
3249
3250 for (;;) {
3251
3252 record_header = (struct atom_common_record_header *)
3253 GET_IMAGE(struct atom_common_record_header,
3254 record_offset);
3255 if (record_header == NULL) {
3256 result = BP_RESULT_BADBIOSTABLE;
3257 break;
3258 }
3259
3260 /* the end of the list */
3261 if (record_header->record_type == ATOM_RECORD_END_TYPE ||
3262 record_header->record_size == 0) {
3263 break;
3264 }
3265
3266 if (record_header->record_type ==
3267 ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&
3268 sizeof(struct atom_bracket_layout_record_v2)
3269 <= record_header->record_size) {
3270 record = (struct atom_bracket_layout_record_v2 *)
3271 (record_header);
3272 result = BP_RESULT_OK;
3273 break;
3274 }
3275
3276 record_offset += record_header->record_size;
3277 }
3278
3279 /* return if the record not found */
3280 if (result != BP_RESULT_OK)
3281 return result;
3282
3283 /* get slot sizes */
3284 connector_id = object_id_from_bios_object_id(object->display_objid);
3285
3286 slot_layout_info->length = record->bracketlen;
3287 slot_layout_info->width = record->bracketwidth;
3288 slot_layout_info->num_of_connectors = v1_5->number_of_path;
3289 slot_layout_info->connectors[i].position = record->conn_num;
3290 slot_layout_info->connectors[i].connector_id = connector_id;
3291
3292 switch (connector_id.id) {
3293 case CONNECTOR_ID_SINGLE_LINK_DVID:
3294 case CONNECTOR_ID_DUAL_LINK_DVID:
3295 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;
3296 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;
3297 break;
3298
3299 case CONNECTOR_ID_HDMI_TYPE_A:
3300 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;
3301 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;
3302 break;
3303
3304 case CONNECTOR_ID_DISPLAY_PORT:
3305 case CONNECTOR_ID_USBC:
3306 if (record->mini_type == MINI_TYPE_NORMAL) {
3307 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;
3308 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;
3309 } else {
3310 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;
3311 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;
3312 }
3313 break;
3314
3315 default:
3316 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3317 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;
3318 }
3319 return result;
3320 }
3321
get_bracket_layout_record(struct dc_bios * dcb,unsigned int bracket_layout_id,struct slot_layout_info * slot_layout_info)3322 static enum bp_result get_bracket_layout_record(
3323 struct dc_bios *dcb,
3324 unsigned int bracket_layout_id,
3325 struct slot_layout_info *slot_layout_info)
3326 {
3327 unsigned int i;
3328 struct bios_parser *bp = BP_FROM_DCB(dcb);
3329 static enum bp_result result;
3330 struct object_info_table *tbl;
3331 struct display_object_info_table_v1_4 *v1_4;
3332 struct display_object_info_table_v1_5 *v1_5;
3333
3334 if (slot_layout_info == NULL) {
3335 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3336 return BP_RESULT_BADINPUT;
3337 }
3338 tbl = &bp->object_info_tbl;
3339 v1_4 = tbl->v1_4;
3340 v1_5 = tbl->v1_5;
3341
3342 result = BP_RESULT_NORECORD;
3343 switch (bp->object_info_tbl.revision.minor) {
3344 case 4:
3345 default:
3346 for (i = 0; i < v1_4->number_of_path; ++i) {
3347 if (bracket_layout_id ==
3348 v1_4->display_path[i].display_objid) {
3349 result = update_slot_layout_info(dcb, i, slot_layout_info);
3350 break;
3351 }
3352 }
3353 break;
3354 case 5:
3355 for (i = 0; i < v1_5->number_of_path; ++i)
3356 result = update_slot_layout_info_v2(dcb, i, slot_layout_info);
3357 break;
3358 }
3359 return result;
3360 }
3361
bios_get_board_layout_info(struct dc_bios * dcb,struct board_layout_info * board_layout_info)3362 static enum bp_result bios_get_board_layout_info(
3363 struct dc_bios *dcb,
3364 struct board_layout_info *board_layout_info)
3365 {
3366 unsigned int i;
3367
3368 struct bios_parser *bp;
3369
3370 static enum bp_result record_result;
3371 unsigned int max_slots;
3372
3373 const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3374 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3375 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3376 0, 0
3377 };
3378
3379
3380 bp = BP_FROM_DCB(dcb);
3381
3382 if (board_layout_info == NULL) {
3383 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3384 return BP_RESULT_BADINPUT;
3385 }
3386
3387 board_layout_info->num_of_slots = 0;
3388 max_slots = MAX_BOARD_SLOTS;
3389
3390 // Assume single slot on v1_5
3391 if (bp->object_info_tbl.revision.minor == 5) {
3392 max_slots = 1;
3393 }
3394
3395 for (i = 0; i < max_slots; ++i) {
3396 record_result = get_bracket_layout_record(dcb,
3397 slot_index_to_vbios_id[i],
3398 &board_layout_info->slots[i]);
3399
3400 if (record_result == BP_RESULT_NORECORD && i > 0)
3401 break; /* no more slots present in bios */
3402 else if (record_result != BP_RESULT_OK)
3403 return record_result; /* fail */
3404
3405 ++board_layout_info->num_of_slots;
3406 }
3407
3408 /* all data is valid */
3409 board_layout_info->is_number_of_slots_valid = 1;
3410 board_layout_info->is_slots_size_valid = 1;
3411 board_layout_info->is_connector_offsets_valid = 1;
3412 board_layout_info->is_connector_lengths_valid = 1;
3413
3414 return BP_RESULT_OK;
3415 }
3416
3417
bios_parser_pack_data_tables(struct dc_bios * dcb,void * dst)3418 static uint16_t bios_parser_pack_data_tables(
3419 struct dc_bios *dcb,
3420 void *dst)
3421 {
3422 // TODO: There is data bytes alignment issue, disable it for now.
3423 return 0;
3424 }
3425
bios_get_golden_table(struct bios_parser * bp,uint32_t rev_major,uint32_t rev_minor,uint16_t * dc_golden_table_ver)3426 static struct atom_dc_golden_table_v1 *bios_get_golden_table(
3427 struct bios_parser *bp,
3428 uint32_t rev_major,
3429 uint32_t rev_minor,
3430 uint16_t *dc_golden_table_ver)
3431 {
3432 struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
3433 uint32_t dc_golden_offset = 0;
3434 *dc_golden_table_ver = 0;
3435
3436 if (!DATA_TABLES(dce_info))
3437 return NULL;
3438
3439 /* ver.4.4 or higher */
3440 switch (rev_major) {
3441 case 4:
3442 switch (rev_minor) {
3443 case 4:
3444 disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
3445 DATA_TABLES(dce_info));
3446 if (!disp_cntl_tbl_4_4)
3447 return NULL;
3448 dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
3449 *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
3450 break;
3451 case 5:
3452 default:
3453 /* For atom_display_controller_info_v4_5 there is no need to get golden table from
3454 * dc_golden_table_offset as all these fields previously in golden table used for AUX
3455 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.
3456 */
3457 break;
3458 }
3459 break;
3460 }
3461
3462 if (!dc_golden_offset)
3463 return NULL;
3464
3465 if (*dc_golden_table_ver != 1)
3466 return NULL;
3467
3468 return GET_IMAGE(struct atom_dc_golden_table_v1,
3469 dc_golden_offset);
3470 }
3471
bios_get_atom_dc_golden_table(struct dc_bios * dcb)3472 static enum bp_result bios_get_atom_dc_golden_table(
3473 struct dc_bios *dcb)
3474 {
3475 struct bios_parser *bp = BP_FROM_DCB(dcb);
3476 enum bp_result result = BP_RESULT_OK;
3477 struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
3478 struct atom_common_table_header *header;
3479 struct atom_data_revision tbl_revision;
3480 uint16_t dc_golden_table_ver = 0;
3481
3482 header = GET_IMAGE(struct atom_common_table_header,
3483 DATA_TABLES(dce_info));
3484 if (!header)
3485 return BP_RESULT_UNSUPPORTED;
3486
3487 get_atom_data_table_revision(header, &tbl_revision);
3488
3489 atom_dc_golden_table = bios_get_golden_table(bp,
3490 tbl_revision.major,
3491 tbl_revision.minor,
3492 &dc_golden_table_ver);
3493
3494 if (!atom_dc_golden_table)
3495 return BP_RESULT_UNSUPPORTED;
3496
3497 dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
3498 dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
3499 dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
3500 dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
3501 dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
3502 dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
3503 dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
3504 dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
3505 dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
3506 dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
3507
3508 return result;
3509 }
3510
3511
3512 static const struct dc_vbios_funcs vbios_funcs = {
3513 .get_connectors_number = bios_parser_get_connectors_number,
3514
3515 .get_connector_id = bios_parser_get_connector_id,
3516
3517 .get_src_obj = bios_parser_get_src_obj,
3518
3519 .get_i2c_info = bios_parser_get_i2c_info,
3520
3521 .get_hpd_info = bios_parser_get_hpd_info,
3522
3523 .get_device_tag = bios_parser_get_device_tag,
3524
3525 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3526
3527 .get_ss_entry_number = bios_parser_get_ss_entry_number,
3528
3529 .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3530
3531 .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3532
3533 .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3534
3535 .is_device_id_supported = bios_parser_is_device_id_supported,
3536
3537 .is_accelerated_mode = bios_parser_is_accelerated_mode,
3538
3539 .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
3540
3541
3542 /* COMMANDS */
3543 .encoder_control = bios_parser_encoder_control,
3544
3545 .transmitter_control = bios_parser_transmitter_control,
3546
3547 .enable_crtc = bios_parser_enable_crtc,
3548
3549 .set_pixel_clock = bios_parser_set_pixel_clock,
3550
3551 .set_dce_clock = bios_parser_set_dce_clock,
3552
3553 .program_crtc_timing = bios_parser_program_crtc_timing,
3554
3555 .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
3556
3557 .bios_parser_destroy = firmware_parser_destroy,
3558
3559 .get_board_layout_info = bios_get_board_layout_info,
3560 /* TODO: use this fn in hw init?*/
3561 .pack_data_tables = bios_parser_pack_data_tables,
3562
3563 .get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
3564
3565 .enable_lvtma_control = bios_parser_enable_lvtma_control,
3566
3567 .get_soc_bb_info = bios_parser_get_soc_bb_info,
3568
3569 .get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
3570
3571 .get_lttpr_caps = bios_parser_get_lttpr_caps,
3572
3573 .get_lttpr_interop = bios_parser_get_lttpr_interop,
3574
3575 .get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
3576 };
3577
bios_parser2_construct(struct bios_parser * bp,struct bp_init_data * init,enum dce_version dce_version)3578 static bool bios_parser2_construct(
3579 struct bios_parser *bp,
3580 struct bp_init_data *init,
3581 enum dce_version dce_version)
3582 {
3583 uint16_t *rom_header_offset = NULL;
3584 struct atom_rom_header_v2_2 *rom_header = NULL;
3585 struct display_object_info_table_v1_4 *object_info_tbl;
3586 struct atom_data_revision tbl_rev = {0};
3587
3588 if (!init)
3589 return false;
3590
3591 if (!init->bios)
3592 return false;
3593
3594 bp->base.funcs = &vbios_funcs;
3595 bp->base.bios = init->bios;
3596 bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
3597
3598 bp->base.ctx = init->ctx;
3599
3600 bp->base.bios_local_image = NULL;
3601
3602 rom_header_offset =
3603 GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
3604
3605 if (!rom_header_offset)
3606 return false;
3607
3608 rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
3609
3610 if (!rom_header)
3611 return false;
3612
3613 get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
3614 if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
3615 return false;
3616
3617 bp->master_data_tbl =
3618 GET_IMAGE(struct atom_master_data_table_v2_1,
3619 rom_header->masterdatatable_offset);
3620
3621 if (!bp->master_data_tbl)
3622 return false;
3623
3624 bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
3625
3626 if (!bp->object_info_tbl_offset)
3627 return false;
3628
3629 object_info_tbl =
3630 GET_IMAGE(struct display_object_info_table_v1_4,
3631 bp->object_info_tbl_offset);
3632
3633 if (!object_info_tbl)
3634 return false;
3635
3636 get_atom_data_table_revision(&object_info_tbl->table_header,
3637 &bp->object_info_tbl.revision);
3638
3639 if (bp->object_info_tbl.revision.major == 1
3640 && bp->object_info_tbl.revision.minor == 4) {
3641 struct display_object_info_table_v1_4 *tbl_v1_4;
3642
3643 tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
3644 bp->object_info_tbl_offset);
3645 if (!tbl_v1_4)
3646 return false;
3647
3648 bp->object_info_tbl.v1_4 = tbl_v1_4;
3649 } else if (bp->object_info_tbl.revision.major == 1
3650 && bp->object_info_tbl.revision.minor == 5) {
3651 struct display_object_info_table_v1_5 *tbl_v1_5;
3652
3653 tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,
3654 bp->object_info_tbl_offset);
3655 if (!tbl_v1_5)
3656 return false;
3657
3658 bp->object_info_tbl.v1_5 = tbl_v1_5;
3659 } else {
3660 ASSERT(0);
3661 return false;
3662 }
3663
3664 dal_firmware_parser_init_cmd_tbl(bp);
3665 dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
3666
3667 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
3668 bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
3669 bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
3670
3671 return true;
3672 }
3673
firmware_parser_create(struct bp_init_data * init,enum dce_version dce_version)3674 struct dc_bios *firmware_parser_create(
3675 struct bp_init_data *init,
3676 enum dce_version dce_version)
3677 {
3678 struct bios_parser *bp;
3679
3680 bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
3681 if (!bp)
3682 return NULL;
3683
3684 if (bios_parser2_construct(bp, init, dce_version))
3685 return &bp->base;
3686
3687 kfree(bp);
3688 return NULL;
3689 }
3690
3691
3692