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