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