Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
28#include "atom.h"
29
30#include "dc_bios_types.h"
31#include "include/gpio_service_interface.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_table.h"
38#include "bios_parser_helper.h"
39#include "command_table_helper.h"
40#include "bios_parser.h"
41#include "bios_parser_types_internal.h"
42#include "bios_parser_interface.h"
43
44#include "bios_parser_common.h"
45
46#include "dc.h"
47
48#define THREE_PERCENT_OF_10000 300
49
50#define LAST_RECORD_TYPE 0xff
51
52#define DC_LOGGER \
53 bp->base.ctx->logger
54
55#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
56
57static void get_atom_data_table_revision(
58 ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
59 struct atom_data_revision *tbl_revision);
60static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
61 uint16_t **id_list);
62static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
63 struct graphics_object_id id);
64static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
65 ATOM_I2C_RECORD *record,
66 struct graphics_object_i2c_info *info);
67static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
68 ATOM_OBJECT *object);
69static struct device_id device_type_from_device_id(uint16_t device_id);
70static uint32_t signal_to_ss_id(enum as_signal_type signal);
71static uint32_t get_support_mask_for_device_id(struct device_id device_id);
72static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
73 struct bios_parser *bp,
74 ATOM_OBJECT *object);
75
76#define BIOS_IMAGE_SIZE_OFFSET 2
77#define BIOS_IMAGE_SIZE_UNIT 512
78
79/*****************************************************************************/
80static bool bios_parser_construct(
81 struct bios_parser *bp,
82 struct bp_init_data *init,
83 enum dce_version dce_version);
84
85static uint8_t bios_parser_get_connectors_number(
86 struct dc_bios *dcb);
87
88static enum bp_result bios_parser_get_embedded_panel_info(
89 struct dc_bios *dcb,
90 struct embedded_panel_info *info);
91
92/*****************************************************************************/
93
94struct dc_bios *bios_parser_create(
95 struct bp_init_data *init,
96 enum dce_version dce_version)
97{
98 struct bios_parser *bp = NULL;
99
100 bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
101 if (!bp)
102 return NULL;
103
104 if (bios_parser_construct(bp, init, dce_version))
105 return &bp->base;
106
107 kfree(bp);
108 BREAK_TO_DEBUGGER();
109 return NULL;
110}
111
112static void destruct(struct bios_parser *bp)
113{
114 kfree(bp->base.bios_local_image);
115 kfree(bp->base.integrated_info);
116}
117
118static void bios_parser_destroy(struct dc_bios **dcb)
119{
120 struct bios_parser *bp = BP_FROM_DCB(*dcb);
121
122 if (!bp) {
123 BREAK_TO_DEBUGGER();
124 return;
125 }
126
127 destruct(bp);
128
129 kfree(bp);
130 *dcb = NULL;
131}
132
133static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
134{
135 ATOM_OBJECT_TABLE *table;
136
137 uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
138
139 table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
140
141 if (!table)
142 return 0;
143 else
144 return table->ucNumberOfObjects;
145}
146
147static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
148{
149 struct bios_parser *bp = BP_FROM_DCB(dcb);
150
151 return get_number_of_objects(bp,
152 le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
153}
154
155static struct graphics_object_id bios_parser_get_connector_id(
156 struct dc_bios *dcb,
157 uint8_t i)
158{
159 struct bios_parser *bp = BP_FROM_DCB(dcb);
160 struct graphics_object_id object_id = dal_graphics_object_id_init(
161 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
162 uint16_t id;
163
164 uint32_t connector_table_offset = bp->object_info_tbl_offset
165 + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
166
167 ATOM_OBJECT_TABLE *tbl =
168 GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
169
170 if (!tbl) {
171 dm_error("Can't get connector table from atom bios.\n");
172 return object_id;
173 }
174
175 if (tbl->ucNumberOfObjects <= i) {
176 dm_error("Can't find connector id %d in connector table of size %d.\n",
177 i, tbl->ucNumberOfObjects);
178 return object_id;
179 }
180
181 id = le16_to_cpu(tbl->asObjects[i].usObjectID);
182 object_id = object_id_from_bios_object_id(id);
183 return object_id;
184}
185
186static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
187 struct graphics_object_id object_id, uint32_t index,
188 struct graphics_object_id *src_object_id)
189{
190 uint32_t number;
191 uint16_t *id;
192 ATOM_OBJECT *object;
193 struct bios_parser *bp = BP_FROM_DCB(dcb);
194
195 if (!src_object_id)
196 return BP_RESULT_BADINPUT;
197
198 object = get_bios_object(bp, object_id);
199
200 if (!object) {
201 BREAK_TO_DEBUGGER(); /* Invalid object id */
202 return BP_RESULT_BADINPUT;
203 }
204
205 number = get_src_obj_list(bp, object, &id);
206
207 if (number <= index)
208 return BP_RESULT_BADINPUT;
209
210 *src_object_id = object_id_from_bios_object_id(id[index]);
211
212 return BP_RESULT_OK;
213}
214
215static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
216 struct graphics_object_id id,
217 struct graphics_object_i2c_info *info)
218{
219 uint32_t offset;
220 ATOM_OBJECT *object;
221 ATOM_COMMON_RECORD_HEADER *header;
222 ATOM_I2C_RECORD *record;
223 struct bios_parser *bp = BP_FROM_DCB(dcb);
224
225 if (!info)
226 return BP_RESULT_BADINPUT;
227
228 object = get_bios_object(bp, id);
229
230 if (!object)
231 return BP_RESULT_BADINPUT;
232
233 offset = le16_to_cpu(object->usRecordOffset)
234 + bp->object_info_tbl_offset;
235
236 for (;;) {
237 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
238
239 if (!header)
240 return BP_RESULT_BADBIOSTABLE;
241
242 if (LAST_RECORD_TYPE == header->ucRecordType ||
243 !header->ucRecordSize)
244 break;
245
246 if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
247 && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
248 /* get the I2C info */
249 record = (ATOM_I2C_RECORD *) header;
250
251 if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
252 return BP_RESULT_OK;
253 }
254
255 offset += header->ucRecordSize;
256 }
257
258 return BP_RESULT_NORECORD;
259}
260
261static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
262 struct graphics_object_id id,
263 struct graphics_object_hpd_info *info)
264{
265 struct bios_parser *bp = BP_FROM_DCB(dcb);
266 ATOM_OBJECT *object;
267 ATOM_HPD_INT_RECORD *record = NULL;
268
269 if (!info)
270 return BP_RESULT_BADINPUT;
271
272 object = get_bios_object(bp, id);
273
274 if (!object)
275 return BP_RESULT_BADINPUT;
276
277 record = get_hpd_record(bp, object);
278
279 if (record != NULL) {
280 info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
281 info->hpd_active = record->ucPlugged_PinState;
282 return BP_RESULT_OK;
283 }
284
285 return BP_RESULT_NORECORD;
286}
287
288static enum bp_result bios_parser_get_device_tag_record(
289 struct bios_parser *bp,
290 ATOM_OBJECT *object,
291 ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
292{
293 ATOM_COMMON_RECORD_HEADER *header;
294 uint32_t offset;
295
296 offset = le16_to_cpu(object->usRecordOffset)
297 + bp->object_info_tbl_offset;
298
299 for (;;) {
300 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
301
302 if (!header)
303 return BP_RESULT_BADBIOSTABLE;
304
305 offset += header->ucRecordSize;
306
307 if (LAST_RECORD_TYPE == header->ucRecordType ||
308 !header->ucRecordSize)
309 break;
310
311 if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
312 header->ucRecordType)
313 continue;
314
315 if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
316 continue;
317
318 *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
319 return BP_RESULT_OK;
320 }
321
322 return BP_RESULT_NORECORD;
323}
324
325static enum bp_result bios_parser_get_device_tag(
326 struct dc_bios *dcb,
327 struct graphics_object_id connector_object_id,
328 uint32_t device_tag_index,
329 struct connector_device_tag_info *info)
330{
331 struct bios_parser *bp = BP_FROM_DCB(dcb);
332 ATOM_OBJECT *object;
333 ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
334 ATOM_CONNECTOR_DEVICE_TAG *device_tag;
335
336 if (!info)
337 return BP_RESULT_BADINPUT;
338
339 /* getBiosObject will return MXM object */
340 object = get_bios_object(bp, connector_object_id);
341
342 if (!object) {
343 BREAK_TO_DEBUGGER(); /* Invalid object id */
344 return BP_RESULT_BADINPUT;
345 }
346
347 if (bios_parser_get_device_tag_record(bp, object, &record)
348 != BP_RESULT_OK)
349 return BP_RESULT_NORECORD;
350
351 if (device_tag_index >= record->ucNumberOfDevice)
352 return BP_RESULT_NORECORD;
353
354 device_tag = &record->asDeviceTag[device_tag_index];
355
356 info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
357 info->dev_id =
358 device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
359
360 return BP_RESULT_OK;
361}
362
363static enum bp_result get_firmware_info_v1_4(
364 struct bios_parser *bp,
365 struct dc_firmware_info *info);
366static enum bp_result get_firmware_info_v2_1(
367 struct bios_parser *bp,
368 struct dc_firmware_info *info);
369static enum bp_result get_firmware_info_v2_2(
370 struct bios_parser *bp,
371 struct dc_firmware_info *info);
372
373static enum bp_result bios_parser_get_firmware_info(
374 struct dc_bios *dcb,
375 struct dc_firmware_info *info)
376{
377 struct bios_parser *bp = BP_FROM_DCB(dcb);
378 enum bp_result result = BP_RESULT_BADBIOSTABLE;
379 ATOM_COMMON_TABLE_HEADER *header;
380 struct atom_data_revision revision;
381
382 if (info && DATA_TABLES(FirmwareInfo)) {
383 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
384 DATA_TABLES(FirmwareInfo));
385 get_atom_data_table_revision(header, &revision);
386 switch (revision.major) {
387 case 1:
388 switch (revision.minor) {
389 case 4:
390 result = get_firmware_info_v1_4(bp, info);
391 break;
392 default:
393 break;
394 }
395 break;
396
397 case 2:
398 switch (revision.minor) {
399 case 1:
400 result = get_firmware_info_v2_1(bp, info);
401 break;
402 case 2:
403 result = get_firmware_info_v2_2(bp, info);
404 break;
405 default:
406 break;
407 }
408 break;
409 default:
410 break;
411 }
412 }
413
414 return result;
415}
416
417static enum bp_result get_firmware_info_v1_4(
418 struct bios_parser *bp,
419 struct dc_firmware_info *info)
420{
421 ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
422 GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
423 DATA_TABLES(FirmwareInfo));
424
425 if (!info)
426 return BP_RESULT_BADINPUT;
427
428 if (!firmware_info)
429 return BP_RESULT_BADBIOSTABLE;
430
431 memset(info, 0, sizeof(*info));
432
433 /* Pixel clock pll information. We need to convert from 10KHz units into
434 * KHz units */
435 info->pll_info.crystal_frequency =
436 le16_to_cpu(firmware_info->usReferenceClock) * 10;
437 info->pll_info.min_input_pxl_clk_pll_frequency =
438 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
439 info->pll_info.max_input_pxl_clk_pll_frequency =
440 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
441 info->pll_info.min_output_pxl_clk_pll_frequency =
442 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
443 info->pll_info.max_output_pxl_clk_pll_frequency =
444 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
445
446 if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
447 /* Since there is no information on the SS, report conservative
448 * value 3% for bandwidth calculation */
449 /* unit of 0.01% */
450 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
451
452 if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
453 /* Since there is no information on the SS,report conservative
454 * value 3% for bandwidth calculation */
455 /* unit of 0.01% */
456 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
457
458 return BP_RESULT_OK;
459}
460
461static enum bp_result get_ss_info_v3_1(
462 struct bios_parser *bp,
463 uint32_t id,
464 uint32_t index,
465 struct spread_spectrum_info *ss_info);
466
467static enum bp_result get_firmware_info_v2_1(
468 struct bios_parser *bp,
469 struct dc_firmware_info *info)
470{
471 ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
472 GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
473 struct spread_spectrum_info internalSS;
474 uint32_t index;
475
476 if (!info)
477 return BP_RESULT_BADINPUT;
478
479 if (!firmwareInfo)
480 return BP_RESULT_BADBIOSTABLE;
481
482 memset(info, 0, sizeof(*info));
483
484 /* Pixel clock pll information. We need to convert from 10KHz units into
485 * KHz units */
486 info->pll_info.crystal_frequency =
487 le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
488 info->pll_info.min_input_pxl_clk_pll_frequency =
489 le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
490 info->pll_info.max_input_pxl_clk_pll_frequency =
491 le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
492 info->pll_info.min_output_pxl_clk_pll_frequency =
493 le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
494 info->pll_info.max_output_pxl_clk_pll_frequency =
495 le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
496 info->default_display_engine_pll_frequency =
497 le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
498 info->external_clock_source_frequency_for_dp =
499 le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
500 info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
501
502 /* There should be only one entry in the SS info table for Memory Clock
503 */
504 index = 0;
505 if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
506 /* Since there is no information for external SS, report
507 * conservative value 3% for bandwidth calculation */
508 /* unit of 0.01% */
509 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
510 else if (get_ss_info_v3_1(bp,
511 ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
512 if (internalSS.spread_spectrum_percentage) {
513 info->feature.memory_clk_ss_percentage =
514 internalSS.spread_spectrum_percentage;
515 if (internalSS.type.CENTER_MODE) {
516 /* if it is centermode, the exact SS Percentage
517 * will be round up of half of the percentage
518 * reported in the SS table */
519 ++info->feature.memory_clk_ss_percentage;
520 info->feature.memory_clk_ss_percentage /= 2;
521 }
522 }
523 }
524
525 /* There should be only one entry in the SS info table for Engine Clock
526 */
527 index = 1;
528 if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
529 /* Since there is no information for external SS, report
530 * conservative value 3% for bandwidth calculation */
531 /* unit of 0.01% */
532 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
533 else if (get_ss_info_v3_1(bp,
534 ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
535 if (internalSS.spread_spectrum_percentage) {
536 info->feature.engine_clk_ss_percentage =
537 internalSS.spread_spectrum_percentage;
538 if (internalSS.type.CENTER_MODE) {
539 /* if it is centermode, the exact SS Percentage
540 * will be round up of half of the percentage
541 * reported in the SS table */
542 ++info->feature.engine_clk_ss_percentage;
543 info->feature.engine_clk_ss_percentage /= 2;
544 }
545 }
546 }
547
548 return BP_RESULT_OK;
549}
550
551static enum bp_result get_firmware_info_v2_2(
552 struct bios_parser *bp,
553 struct dc_firmware_info *info)
554{
555 ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
556 struct spread_spectrum_info internal_ss;
557 uint32_t index;
558
559 if (!info)
560 return BP_RESULT_BADINPUT;
561
562 firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
563 DATA_TABLES(FirmwareInfo));
564
565 if (!firmware_info)
566 return BP_RESULT_BADBIOSTABLE;
567
568 memset(info, 0, sizeof(*info));
569
570 /* Pixel clock pll information. We need to convert from 10KHz units into
571 * KHz units */
572 info->pll_info.crystal_frequency =
573 le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
574 info->pll_info.min_input_pxl_clk_pll_frequency =
575 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
576 info->pll_info.max_input_pxl_clk_pll_frequency =
577 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
578 info->pll_info.min_output_pxl_clk_pll_frequency =
579 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
580 info->pll_info.max_output_pxl_clk_pll_frequency =
581 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
582 info->default_display_engine_pll_frequency =
583 le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
584 info->external_clock_source_frequency_for_dp =
585 le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
586
587 /* There should be only one entry in the SS info table for Memory Clock
588 */
589 index = 0;
590 if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
591 /* Since there is no information for external SS, report
592 * conservative value 3% for bandwidth calculation */
593 /* unit of 0.01% */
594 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
595 else if (get_ss_info_v3_1(bp,
596 ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
597 if (internal_ss.spread_spectrum_percentage) {
598 info->feature.memory_clk_ss_percentage =
599 internal_ss.spread_spectrum_percentage;
600 if (internal_ss.type.CENTER_MODE) {
601 /* if it is centermode, the exact SS Percentage
602 * will be round up of half of the percentage
603 * reported in the SS table */
604 ++info->feature.memory_clk_ss_percentage;
605 info->feature.memory_clk_ss_percentage /= 2;
606 }
607 }
608 }
609
610 /* There should be only one entry in the SS info table for Engine Clock
611 */
612 index = 1;
613 if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
614 /* Since there is no information for external SS, report
615 * conservative value 3% for bandwidth calculation */
616 /* unit of 0.01% */
617 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
618 else if (get_ss_info_v3_1(bp,
619 ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
620 if (internal_ss.spread_spectrum_percentage) {
621 info->feature.engine_clk_ss_percentage =
622 internal_ss.spread_spectrum_percentage;
623 if (internal_ss.type.CENTER_MODE) {
624 /* if it is centermode, the exact SS Percentage
625 * will be round up of half of the percentage
626 * reported in the SS table */
627 ++info->feature.engine_clk_ss_percentage;
628 info->feature.engine_clk_ss_percentage /= 2;
629 }
630 }
631 }
632
633 /* Remote Display */
634 info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
635
636 /* Is allowed minimum BL level */
637 info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
638 /* Used starting from CI */
639 info->smu_gpu_pll_output_freq =
640 (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
641
642 return BP_RESULT_OK;
643}
644
645static enum bp_result get_ss_info_v3_1(
646 struct bios_parser *bp,
647 uint32_t id,
648 uint32_t index,
649 struct spread_spectrum_info *ss_info)
650{
651 ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
652 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
653 uint32_t table_size;
654 uint32_t i;
655 uint32_t table_index = 0;
656
657 if (!ss_info)
658 return BP_RESULT_BADINPUT;
659
660 if (!DATA_TABLES(ASIC_InternalSS_Info))
661 return BP_RESULT_UNSUPPORTED;
662
663 ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
664 DATA_TABLES(ASIC_InternalSS_Info));
665 table_size =
666 (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
667 - sizeof(ATOM_COMMON_TABLE_HEADER))
668 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
669
670 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
671 &ss_table_header_include->asSpreadSpectrum[0];
672
673 memset(ss_info, 0, sizeof(struct spread_spectrum_info));
674
675 for (i = 0; i < table_size; i++) {
676 if (tbl[i].ucClockIndication != (uint8_t) id)
677 continue;
678
679 if (table_index != index) {
680 table_index++;
681 continue;
682 }
683 /* VBIOS introduced new defines for Version 3, same values as
684 * before, so now use these new ones for Version 3.
685 * Shouldn't affect field VBIOS's V3 as define values are still
686 * same.
687 * #define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01
688 * #define SS_MODE_V3_EXTERNAL_SS_MASK 0x02
689
690 * Old VBIOS defines:
691 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001
692 * #define ATOM_EXTERNAL_SS_MASK 0x00000002
693 */
694
695 if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
696 ss_info->type.EXTERNAL = true;
697
698 if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
699 ss_info->type.CENTER_MODE = true;
700
701 /* Older VBIOS (in field) always provides SS percentage in 0.01%
702 * units set Divider to 100 */
703 ss_info->spread_percentage_divider = 100;
704
705 /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
706 if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
707 & tbl[i].ucSpreadSpectrumMode)
708 ss_info->spread_percentage_divider = 1000;
709
710 ss_info->type.STEP_AND_DELAY_INFO = false;
711 /* convert [10KHz] into [KHz] */
712 ss_info->target_clock_range =
713 le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
714 ss_info->spread_spectrum_percentage =
715 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
716 ss_info->spread_spectrum_range =
717 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
718
719 return BP_RESULT_OK;
720 }
721 return BP_RESULT_NORECORD;
722}
723
724static enum bp_result bios_parser_transmitter_control(
725 struct dc_bios *dcb,
726 struct bp_transmitter_control *cntl)
727{
728 struct bios_parser *bp = BP_FROM_DCB(dcb);
729
730 if (!bp->cmd_tbl.transmitter_control)
731 return BP_RESULT_FAILURE;
732
733 return bp->cmd_tbl.transmitter_control(bp, cntl);
734}
735
736static enum bp_result bios_parser_encoder_control(
737 struct dc_bios *dcb,
738 struct bp_encoder_control *cntl)
739{
740 struct bios_parser *bp = BP_FROM_DCB(dcb);
741
742 if (!bp->cmd_tbl.dig_encoder_control)
743 return BP_RESULT_FAILURE;
744
745 return bp->cmd_tbl.dig_encoder_control(bp, cntl);
746}
747
748static enum bp_result bios_parser_adjust_pixel_clock(
749 struct dc_bios *dcb,
750 struct bp_adjust_pixel_clock_parameters *bp_params)
751{
752 struct bios_parser *bp = BP_FROM_DCB(dcb);
753
754 if (!bp->cmd_tbl.adjust_display_pll)
755 return BP_RESULT_FAILURE;
756
757 return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
758}
759
760static enum bp_result bios_parser_set_pixel_clock(
761 struct dc_bios *dcb,
762 struct bp_pixel_clock_parameters *bp_params)
763{
764 struct bios_parser *bp = BP_FROM_DCB(dcb);
765
766 if (!bp->cmd_tbl.set_pixel_clock)
767 return BP_RESULT_FAILURE;
768
769 return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
770}
771
772static enum bp_result bios_parser_set_dce_clock(
773 struct dc_bios *dcb,
774 struct bp_set_dce_clock_parameters *bp_params)
775{
776 struct bios_parser *bp = BP_FROM_DCB(dcb);
777
778 if (!bp->cmd_tbl.set_dce_clock)
779 return BP_RESULT_FAILURE;
780
781 return bp->cmd_tbl.set_dce_clock(bp, bp_params);
782}
783
784static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
785 struct dc_bios *dcb,
786 struct bp_spread_spectrum_parameters *bp_params,
787 bool enable)
788{
789 struct bios_parser *bp = BP_FROM_DCB(dcb);
790
791 if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
792 return BP_RESULT_FAILURE;
793
794 return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
795 bp, bp_params, enable);
796
797}
798
799static enum bp_result bios_parser_program_crtc_timing(
800 struct dc_bios *dcb,
801 struct bp_hw_crtc_timing_parameters *bp_params)
802{
803 struct bios_parser *bp = BP_FROM_DCB(dcb);
804
805 if (!bp->cmd_tbl.set_crtc_timing)
806 return BP_RESULT_FAILURE;
807
808 return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
809}
810
811static enum bp_result bios_parser_program_display_engine_pll(
812 struct dc_bios *dcb,
813 struct bp_pixel_clock_parameters *bp_params)
814{
815 struct bios_parser *bp = BP_FROM_DCB(dcb);
816
817 if (!bp->cmd_tbl.program_clock)
818 return BP_RESULT_FAILURE;
819
820 return bp->cmd_tbl.program_clock(bp, bp_params);
821
822}
823
824
825static enum bp_result bios_parser_enable_crtc(
826 struct dc_bios *dcb,
827 enum controller_id id,
828 bool enable)
829{
830 struct bios_parser *bp = BP_FROM_DCB(dcb);
831
832 if (!bp->cmd_tbl.enable_crtc)
833 return BP_RESULT_FAILURE;
834
835 return bp->cmd_tbl.enable_crtc(bp, id, enable);
836}
837
838static enum bp_result bios_parser_enable_disp_power_gating(
839 struct dc_bios *dcb,
840 enum controller_id controller_id,
841 enum bp_pipe_control_action action)
842{
843 struct bios_parser *bp = BP_FROM_DCB(dcb);
844
845 if (!bp->cmd_tbl.enable_disp_power_gating)
846 return BP_RESULT_FAILURE;
847
848 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
849 action);
850}
851
852static bool bios_parser_is_device_id_supported(
853 struct dc_bios *dcb,
854 struct device_id id)
855{
856 struct bios_parser *bp = BP_FROM_DCB(dcb);
857
858 uint32_t mask = get_support_mask_for_device_id(id);
859
860 return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
861}
862
863static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
864 ATOM_OBJECT *object)
865{
866 ATOM_COMMON_RECORD_HEADER *header;
867 uint32_t offset;
868
869 if (!object) {
870 BREAK_TO_DEBUGGER(); /* Invalid object */
871 return NULL;
872 }
873
874 offset = le16_to_cpu(object->usRecordOffset)
875 + bp->object_info_tbl_offset;
876
877 for (;;) {
878 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
879
880 if (!header)
881 return NULL;
882
883 if (LAST_RECORD_TYPE == header->ucRecordType ||
884 !header->ucRecordSize)
885 break;
886
887 if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
888 && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
889 return (ATOM_HPD_INT_RECORD *) header;
890
891 offset += header->ucRecordSize;
892 }
893
894 return NULL;
895}
896
897static enum bp_result get_ss_info_from_ss_info_table(
898 struct bios_parser *bp,
899 uint32_t id,
900 struct spread_spectrum_info *ss_info);
901static enum bp_result get_ss_info_from_tbl(
902 struct bios_parser *bp,
903 uint32_t id,
904 struct spread_spectrum_info *ss_info);
905/**
906 * bios_parser_get_spread_spectrum_info
907 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
908 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
909 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
910 * there is only one entry for each signal /ss id. However, there is
911 * no planning of supporting multiple spread Sprectum entry for EverGreen
912 * @param [in] this
913 * @param [in] signal, ASSignalType to be converted to info index
914 * @param [in] index, number of entries that match the converted info index
915 * @param [out] ss_info, sprectrum information structure,
916 * @return Bios parser result code
917 */
918static enum bp_result bios_parser_get_spread_spectrum_info(
919 struct dc_bios *dcb,
920 enum as_signal_type signal,
921 uint32_t index,
922 struct spread_spectrum_info *ss_info)
923{
924 struct bios_parser *bp = BP_FROM_DCB(dcb);
925 enum bp_result result = BP_RESULT_UNSUPPORTED;
926 uint32_t clk_id_ss = 0;
927 ATOM_COMMON_TABLE_HEADER *header;
928 struct atom_data_revision tbl_revision;
929
930 if (!ss_info) /* check for bad input */
931 return BP_RESULT_BADINPUT;
932 /* signal translation */
933 clk_id_ss = signal_to_ss_id(signal);
934
935 if (!DATA_TABLES(ASIC_InternalSS_Info))
936 if (!index)
937 return get_ss_info_from_ss_info_table(bp, clk_id_ss,
938 ss_info);
939
940 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
941 DATA_TABLES(ASIC_InternalSS_Info));
942 get_atom_data_table_revision(header, &tbl_revision);
943
944 switch (tbl_revision.major) {
945 case 2:
946 switch (tbl_revision.minor) {
947 case 1:
948 /* there can not be more then one entry for Internal
949 * SS Info table version 2.1 */
950 if (!index)
951 return get_ss_info_from_tbl(bp, clk_id_ss,
952 ss_info);
953 break;
954 default:
955 break;
956 }
957 break;
958
959 case 3:
960 switch (tbl_revision.minor) {
961 case 1:
962 return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
963 default:
964 break;
965 }
966 break;
967 default:
968 break;
969 }
970 /* there can not be more then one entry for SS Info table */
971 return result;
972}
973
974static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
975 struct bios_parser *bp,
976 uint32_t id,
977 struct spread_spectrum_info *info);
978
979/**
980 * get_ss_info_from_table
981 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
982 * SS_Info table from the VBIOS
983 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or
984 * SS_Info.
985 *
986 * @param this
987 * @param id, spread sprectrum info index
988 * @param pSSinfo, sprectrum information structure,
989 * @return Bios parser result code
990 */
991static enum bp_result get_ss_info_from_tbl(
992 struct bios_parser *bp,
993 uint32_t id,
994 struct spread_spectrum_info *ss_info)
995{
996 if (!ss_info) /* check for bad input, if ss_info is not NULL */
997 return BP_RESULT_BADINPUT;
998 /* for SS_Info table only support DP and LVDS */
999 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1000 return get_ss_info_from_ss_info_table(bp, id, ss_info);
1001 else
1002 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
1003 ss_info);
1004}
1005
1006/**
1007 * get_ss_info_from_internal_ss_info_tbl_V2_1
1008 * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
1009 * from the VBIOS
1010 * There will not be multiple entry for Ver 2.1
1011 *
1012 * @param id, spread sprectrum info index
1013 * @param pSSinfo, sprectrum information structure,
1014 * @return Bios parser result code
1015 */
1016static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1017 struct bios_parser *bp,
1018 uint32_t id,
1019 struct spread_spectrum_info *info)
1020{
1021 enum bp_result result = BP_RESULT_UNSUPPORTED;
1022 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
1023 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1024 uint32_t tbl_size, i;
1025
1026 if (!DATA_TABLES(ASIC_InternalSS_Info))
1027 return result;
1028
1029 header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1030 DATA_TABLES(ASIC_InternalSS_Info));
1031
1032 memset(info, 0, sizeof(struct spread_spectrum_info));
1033
1034 tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
1035 - sizeof(ATOM_COMMON_TABLE_HEADER))
1036 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1037
1038 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1039 &(header->asSpreadSpectrum[0]);
1040 for (i = 0; i < tbl_size; i++) {
1041 result = BP_RESULT_NORECORD;
1042
1043 if (tbl[i].ucClockIndication != (uint8_t)id)
1044 continue;
1045
1046 if (ATOM_EXTERNAL_SS_MASK
1047 & tbl[i].ucSpreadSpectrumMode) {
1048 info->type.EXTERNAL = true;
1049 }
1050 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1051 & tbl[i].ucSpreadSpectrumMode) {
1052 info->type.CENTER_MODE = true;
1053 }
1054 info->type.STEP_AND_DELAY_INFO = false;
1055 /* convert [10KHz] into [KHz] */
1056 info->target_clock_range =
1057 le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
1058 info->spread_spectrum_percentage =
1059 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
1060 info->spread_spectrum_range =
1061 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
1062 result = BP_RESULT_OK;
1063 break;
1064 }
1065
1066 return result;
1067
1068}
1069
1070/**
1071 * get_ss_info_from_ss_info_table
1072 * Get spread sprectrum information from the SS_Info table from the VBIOS
1073 * if the pointer to info is NULL, indicate the caller what to know the number
1074 * of entries that matches the id
1075 * for, the SS_Info table, there should not be more than 1 entry match.
1076 *
1077 * @param [in] id, spread sprectrum id
1078 * @param [out] pSSinfo, sprectrum information structure,
1079 * @return Bios parser result code
1080 */
1081static enum bp_result get_ss_info_from_ss_info_table(
1082 struct bios_parser *bp,
1083 uint32_t id,
1084 struct spread_spectrum_info *ss_info)
1085{
1086 enum bp_result result = BP_RESULT_UNSUPPORTED;
1087 ATOM_SPREAD_SPECTRUM_INFO *tbl;
1088 ATOM_COMMON_TABLE_HEADER *header;
1089 uint32_t table_size;
1090 uint32_t i;
1091 uint32_t id_local = SS_ID_UNKNOWN;
1092 struct atom_data_revision revision;
1093
1094 /* exist of the SS_Info table */
1095 /* check for bad input, pSSinfo can not be NULL */
1096 if (!DATA_TABLES(SS_Info) || !ss_info)
1097 return result;
1098
1099 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
1100 get_atom_data_table_revision(header, &revision);
1101
1102 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
1103
1104 if (1 != revision.major || 2 > revision.minor)
1105 return result;
1106
1107 /* have to convert from Internal_SS format to SS_Info format */
1108 switch (id) {
1109 case ASIC_INTERNAL_SS_ON_DP:
1110 id_local = SS_ID_DP1;
1111 break;
1112 case ASIC_INTERNAL_SS_ON_LVDS:
1113 {
1114 struct embedded_panel_info panel_info;
1115
1116 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1117 == BP_RESULT_OK)
1118 id_local = panel_info.ss_id;
1119 break;
1120 }
1121 default:
1122 break;
1123 }
1124
1125 if (id_local == SS_ID_UNKNOWN)
1126 return result;
1127
1128 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1129 sizeof(ATOM_COMMON_TABLE_HEADER)) /
1130 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1131
1132 for (i = 0; i < table_size; i++) {
1133 if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
1134 continue;
1135
1136 memset(ss_info, 0, sizeof(struct spread_spectrum_info));
1137
1138 if (ATOM_EXTERNAL_SS_MASK &
1139 tbl->asSS_Info[i].ucSpreadSpectrumType)
1140 ss_info->type.EXTERNAL = true;
1141
1142 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
1143 tbl->asSS_Info[i].ucSpreadSpectrumType)
1144 ss_info->type.CENTER_MODE = true;
1145
1146 ss_info->type.STEP_AND_DELAY_INFO = true;
1147 ss_info->spread_spectrum_percentage =
1148 (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
1149 ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
1150 ss_info->step_and_delay_info.delay =
1151 tbl->asSS_Info[i].ucSS_Delay;
1152 ss_info->step_and_delay_info.recommended_ref_div =
1153 tbl->asSS_Info[i].ucRecommendedRef_Div;
1154 ss_info->spread_spectrum_range =
1155 (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
1156
1157 /* there will be only one entry for each display type in SS_info
1158 * table */
1159 result = BP_RESULT_OK;
1160 break;
1161 }
1162
1163 return result;
1164}
1165static enum bp_result get_embedded_panel_info_v1_2(
1166 struct bios_parser *bp,
1167 struct embedded_panel_info *info);
1168static enum bp_result get_embedded_panel_info_v1_3(
1169 struct bios_parser *bp,
1170 struct embedded_panel_info *info);
1171
1172static enum bp_result bios_parser_get_embedded_panel_info(
1173 struct dc_bios *dcb,
1174 struct embedded_panel_info *info)
1175{
1176 struct bios_parser *bp = BP_FROM_DCB(dcb);
1177 ATOM_COMMON_TABLE_HEADER *hdr;
1178
1179 if (!DATA_TABLES(LCD_Info))
1180 return BP_RESULT_FAILURE;
1181
1182 hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
1183
1184 if (!hdr)
1185 return BP_RESULT_BADBIOSTABLE;
1186
1187 switch (hdr->ucTableFormatRevision) {
1188 case 1:
1189 switch (hdr->ucTableContentRevision) {
1190 case 0:
1191 case 1:
1192 case 2:
1193 return get_embedded_panel_info_v1_2(bp, info);
1194 case 3:
1195 return get_embedded_panel_info_v1_3(bp, info);
1196 default:
1197 break;
1198 }
1199 default:
1200 break;
1201 }
1202
1203 return BP_RESULT_FAILURE;
1204}
1205
1206static enum bp_result get_embedded_panel_info_v1_2(
1207 struct bios_parser *bp,
1208 struct embedded_panel_info *info)
1209{
1210 ATOM_LVDS_INFO_V12 *lvds;
1211
1212 if (!info)
1213 return BP_RESULT_BADINPUT;
1214
1215 if (!DATA_TABLES(LVDS_Info))
1216 return BP_RESULT_UNSUPPORTED;
1217
1218 lvds =
1219 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1220
1221 if (!lvds)
1222 return BP_RESULT_BADBIOSTABLE;
1223
1224 if (1 != lvds->sHeader.ucTableFormatRevision
1225 || 2 > lvds->sHeader.ucTableContentRevision)
1226 return BP_RESULT_UNSUPPORTED;
1227
1228 memset(info, 0, sizeof(struct embedded_panel_info));
1229
1230 /* We need to convert from 10KHz units into KHz units*/
1231 info->lcd_timing.pixel_clk =
1232 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1233 /* usHActive does not include borders, according to VBIOS team*/
1234 info->lcd_timing.horizontal_addressable =
1235 le16_to_cpu(lvds->sLCDTiming.usHActive);
1236 /* usHBlanking_Time includes borders, so we should really be subtracting
1237 * borders duing this translation, but LVDS generally*/
1238 /* doesn't have borders, so we should be okay leaving this as is for
1239 * now. May need to revisit if we ever have LVDS with borders*/
1240 info->lcd_timing.horizontal_blanking_time =
1241 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1242 /* usVActive does not include borders, according to VBIOS team*/
1243 info->lcd_timing.vertical_addressable =
1244 le16_to_cpu(lvds->sLCDTiming.usVActive);
1245 /* usVBlanking_Time includes borders, so we should really be subtracting
1246 * borders duing this translation, but LVDS generally*/
1247 /* doesn't have borders, so we should be okay leaving this as is for
1248 * now. May need to revisit if we ever have LVDS with borders*/
1249 info->lcd_timing.vertical_blanking_time =
1250 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1251 info->lcd_timing.horizontal_sync_offset =
1252 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1253 info->lcd_timing.horizontal_sync_width =
1254 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1255 info->lcd_timing.vertical_sync_offset =
1256 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1257 info->lcd_timing.vertical_sync_width =
1258 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1259 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1260 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1261 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1262 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1263 info->lcd_timing.misc_info.H_SYNC_POLARITY =
1264 ~(uint32_t)
1265 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1266 info->lcd_timing.misc_info.V_SYNC_POLARITY =
1267 ~(uint32_t)
1268 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1269 info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1270 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1271 info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1272 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1273 info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1274 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1275 info->lcd_timing.misc_info.COMPOSITE_SYNC =
1276 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1277 info->lcd_timing.misc_info.INTERLACE =
1278 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1279 info->lcd_timing.misc_info.DOUBLE_CLOCK =
1280 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1281 info->ss_id = lvds->ucSS_Id;
1282
1283 {
1284 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1285 /* Get minimum supported refresh rate*/
1286 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1287 info->supported_rr.REFRESH_RATE_30HZ = 1;
1288 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1289 info->supported_rr.REFRESH_RATE_40HZ = 1;
1290 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1291 info->supported_rr.REFRESH_RATE_48HZ = 1;
1292 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1293 info->supported_rr.REFRESH_RATE_50HZ = 1;
1294 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1295 info->supported_rr.REFRESH_RATE_60HZ = 1;
1296 }
1297
1298 /*Drr panel support can be reported by VBIOS*/
1299 if (LCDPANEL_CAP_DRR_SUPPORTED
1300 & lvds->ucLCDPanel_SpecialHandlingCap)
1301 info->drr_enabled = 1;
1302
1303 if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1304 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1305
1306 if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1307 info->lcd_timing.misc_info.RGB888 = true;
1308
1309 info->lcd_timing.misc_info.GREY_LEVEL =
1310 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1311 lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1312
1313 if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1314 info->lcd_timing.misc_info.SPATIAL = true;
1315
1316 if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1317 info->lcd_timing.misc_info.TEMPORAL = true;
1318
1319 if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1320 info->lcd_timing.misc_info.API_ENABLED = true;
1321
1322 return BP_RESULT_OK;
1323}
1324
1325static enum bp_result get_embedded_panel_info_v1_3(
1326 struct bios_parser *bp,
1327 struct embedded_panel_info *info)
1328{
1329 ATOM_LCD_INFO_V13 *lvds;
1330
1331 if (!info)
1332 return BP_RESULT_BADINPUT;
1333
1334 if (!DATA_TABLES(LCD_Info))
1335 return BP_RESULT_UNSUPPORTED;
1336
1337 lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1338
1339 if (!lvds)
1340 return BP_RESULT_BADBIOSTABLE;
1341
1342 if (!((1 == lvds->sHeader.ucTableFormatRevision)
1343 && (3 <= lvds->sHeader.ucTableContentRevision)))
1344 return BP_RESULT_UNSUPPORTED;
1345
1346 memset(info, 0, sizeof(struct embedded_panel_info));
1347
1348 /* We need to convert from 10KHz units into KHz units */
1349 info->lcd_timing.pixel_clk =
1350 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1351 /* usHActive does not include borders, according to VBIOS team */
1352 info->lcd_timing.horizontal_addressable =
1353 le16_to_cpu(lvds->sLCDTiming.usHActive);
1354 /* usHBlanking_Time includes borders, so we should really be subtracting
1355 * borders duing this translation, but LVDS generally*/
1356 /* doesn't have borders, so we should be okay leaving this as is for
1357 * now. May need to revisit if we ever have LVDS with borders*/
1358 info->lcd_timing.horizontal_blanking_time =
1359 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1360 /* usVActive does not include borders, according to VBIOS team*/
1361 info->lcd_timing.vertical_addressable =
1362 le16_to_cpu(lvds->sLCDTiming.usVActive);
1363 /* usVBlanking_Time includes borders, so we should really be subtracting
1364 * borders duing this translation, but LVDS generally*/
1365 /* doesn't have borders, so we should be okay leaving this as is for
1366 * now. May need to revisit if we ever have LVDS with borders*/
1367 info->lcd_timing.vertical_blanking_time =
1368 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1369 info->lcd_timing.horizontal_sync_offset =
1370 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1371 info->lcd_timing.horizontal_sync_width =
1372 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1373 info->lcd_timing.vertical_sync_offset =
1374 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1375 info->lcd_timing.vertical_sync_width =
1376 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1377 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1378 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1379 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1380 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1381 info->lcd_timing.misc_info.H_SYNC_POLARITY =
1382 ~(uint32_t)
1383 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1384 info->lcd_timing.misc_info.V_SYNC_POLARITY =
1385 ~(uint32_t)
1386 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1387 info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1388 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1389 info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1390 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1391 info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1392 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1393 info->lcd_timing.misc_info.COMPOSITE_SYNC =
1394 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1395 info->lcd_timing.misc_info.INTERLACE =
1396 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1397 info->lcd_timing.misc_info.DOUBLE_CLOCK =
1398 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1399 info->ss_id = lvds->ucSS_Id;
1400
1401 /* Drr panel support can be reported by VBIOS*/
1402 if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1403 & lvds->ucLCDPanel_SpecialHandlingCap)
1404 info->drr_enabled = 1;
1405
1406 /* Get supported refresh rate*/
1407 if (info->drr_enabled == 1) {
1408 uint8_t min_rr =
1409 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1410 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1411
1412 if (min_rr != 0) {
1413 if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1414 info->supported_rr.REFRESH_RATE_30HZ = 1;
1415 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1416 info->supported_rr.REFRESH_RATE_40HZ = 1;
1417 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1418 info->supported_rr.REFRESH_RATE_48HZ = 1;
1419 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1420 info->supported_rr.REFRESH_RATE_50HZ = 1;
1421 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1422 info->supported_rr.REFRESH_RATE_60HZ = 1;
1423 } else {
1424 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1425 info->supported_rr.REFRESH_RATE_30HZ = 1;
1426 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1427 info->supported_rr.REFRESH_RATE_40HZ = 1;
1428 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1429 info->supported_rr.REFRESH_RATE_48HZ = 1;
1430 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1431 info->supported_rr.REFRESH_RATE_50HZ = 1;
1432 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1433 info->supported_rr.REFRESH_RATE_60HZ = 1;
1434 }
1435 }
1436
1437 if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1438 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1439
1440 if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1441 info->lcd_timing.misc_info.RGB888 = true;
1442
1443 info->lcd_timing.misc_info.GREY_LEVEL =
1444 (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1445 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1446
1447 return BP_RESULT_OK;
1448}
1449
1450/**
1451 * bios_parser_get_encoder_cap_info
1452 *
1453 * @brief
1454 * Get encoder capability information of input object id
1455 *
1456 * @param object_id, Object id
1457 * @param object_id, encoder cap information structure
1458 *
1459 * @return Bios parser result code
1460 *
1461 */
1462static enum bp_result bios_parser_get_encoder_cap_info(
1463 struct dc_bios *dcb,
1464 struct graphics_object_id object_id,
1465 struct bp_encoder_cap_info *info)
1466{
1467 struct bios_parser *bp = BP_FROM_DCB(dcb);
1468 ATOM_OBJECT *object;
1469 ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1470
1471 if (!info)
1472 return BP_RESULT_BADINPUT;
1473
1474 object = get_bios_object(bp, object_id);
1475
1476 if (!object)
1477 return BP_RESULT_BADINPUT;
1478
1479 record = get_encoder_cap_record(bp, object);
1480 if (!record)
1481 return BP_RESULT_NORECORD;
1482
1483 info->DP_HBR2_EN = record->usHBR2En;
1484 info->DP_HBR3_EN = record->usHBR3En;
1485 info->HDMI_6GB_EN = record->usHDMI6GEn;
1486 return BP_RESULT_OK;
1487}
1488
1489/**
1490 * get_encoder_cap_record
1491 *
1492 * @brief
1493 * Get encoder cap record for the object
1494 *
1495 * @param object, ATOM object
1496 *
1497 * @return atom encoder cap record
1498 *
1499 * @note
1500 * search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1501 */
1502static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1503 struct bios_parser *bp,
1504 ATOM_OBJECT *object)
1505{
1506 ATOM_COMMON_RECORD_HEADER *header;
1507 uint32_t offset;
1508
1509 if (!object) {
1510 BREAK_TO_DEBUGGER(); /* Invalid object */
1511 return NULL;
1512 }
1513
1514 offset = le16_to_cpu(object->usRecordOffset)
1515 + bp->object_info_tbl_offset;
1516
1517 for (;;) {
1518 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1519
1520 if (!header)
1521 return NULL;
1522
1523 offset += header->ucRecordSize;
1524
1525 if (LAST_RECORD_TYPE == header->ucRecordType ||
1526 !header->ucRecordSize)
1527 break;
1528
1529 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1530 continue;
1531
1532 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1533 return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1534 }
1535
1536 return NULL;
1537}
1538
1539static uint32_t get_ss_entry_number(
1540 struct bios_parser *bp,
1541 uint32_t id);
1542static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1543 struct bios_parser *bp,
1544 uint32_t id);
1545static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1546 struct bios_parser *bp,
1547 uint32_t id);
1548static uint32_t get_ss_entry_number_from_ss_info_tbl(
1549 struct bios_parser *bp,
1550 uint32_t id);
1551
1552/**
1553 * BiosParserObject::GetNumberofSpreadSpectrumEntry
1554 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1555 * the VBIOS that match the SSid (to be converted from signal)
1556 *
1557 * @param[in] signal, ASSignalType to be converted to SSid
1558 * @return number of SS Entry that match the signal
1559 */
1560static uint32_t bios_parser_get_ss_entry_number(
1561 struct dc_bios *dcb,
1562 enum as_signal_type signal)
1563{
1564 struct bios_parser *bp = BP_FROM_DCB(dcb);
1565 uint32_t ss_id = 0;
1566 ATOM_COMMON_TABLE_HEADER *header;
1567 struct atom_data_revision revision;
1568
1569 ss_id = signal_to_ss_id(signal);
1570
1571 if (!DATA_TABLES(ASIC_InternalSS_Info))
1572 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1573
1574 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1575 DATA_TABLES(ASIC_InternalSS_Info));
1576 get_atom_data_table_revision(header, &revision);
1577
1578 switch (revision.major) {
1579 case 2:
1580 switch (revision.minor) {
1581 case 1:
1582 return get_ss_entry_number(bp, ss_id);
1583 default:
1584 break;
1585 }
1586 break;
1587 case 3:
1588 switch (revision.minor) {
1589 case 1:
1590 return
1591 get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1592 bp, ss_id);
1593 default:
1594 break;
1595 }
1596 break;
1597 default:
1598 break;
1599 }
1600
1601 return 0;
1602}
1603
1604/**
1605 * get_ss_entry_number_from_ss_info_tbl
1606 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1607 *
1608 * @note There can only be one entry for each id for SS_Info Table
1609 *
1610 * @param [in] id, spread spectrum id
1611 * @return number of SS Entry that match the id
1612 */
1613static uint32_t get_ss_entry_number_from_ss_info_tbl(
1614 struct bios_parser *bp,
1615 uint32_t id)
1616{
1617 ATOM_SPREAD_SPECTRUM_INFO *tbl;
1618 ATOM_COMMON_TABLE_HEADER *header;
1619 uint32_t table_size;
1620 uint32_t i;
1621 uint32_t number = 0;
1622 uint32_t id_local = SS_ID_UNKNOWN;
1623 struct atom_data_revision revision;
1624
1625 /* SS_Info table exist */
1626 if (!DATA_TABLES(SS_Info))
1627 return number;
1628
1629 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1630 DATA_TABLES(SS_Info));
1631 get_atom_data_table_revision(header, &revision);
1632
1633 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
1634 DATA_TABLES(SS_Info));
1635
1636 if (1 != revision.major || 2 > revision.minor)
1637 return number;
1638
1639 /* have to convert from Internal_SS format to SS_Info format */
1640 switch (id) {
1641 case ASIC_INTERNAL_SS_ON_DP:
1642 id_local = SS_ID_DP1;
1643 break;
1644 case ASIC_INTERNAL_SS_ON_LVDS: {
1645 struct embedded_panel_info panel_info;
1646
1647 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1648 == BP_RESULT_OK)
1649 id_local = panel_info.ss_id;
1650 break;
1651 }
1652 default:
1653 break;
1654 }
1655
1656 if (id_local == SS_ID_UNKNOWN)
1657 return number;
1658
1659 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1660 sizeof(ATOM_COMMON_TABLE_HEADER)) /
1661 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1662
1663 for (i = 0; i < table_size; i++)
1664 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
1665 number = 1;
1666 break;
1667 }
1668
1669 return number;
1670}
1671
1672/**
1673 * get_ss_entry_number
1674 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1675 * SS_Info table from the VBIOS
1676 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or
1677 * SS_Info.
1678 *
1679 * @param id, spread sprectrum info index
1680 * @return Bios parser result code
1681 */
1682static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
1683{
1684 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1685 return get_ss_entry_number_from_ss_info_tbl(bp, id);
1686
1687 return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
1688}
1689
1690/**
1691 * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
1692 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
1693 * Ver 2.1 from the VBIOS
1694 * There will not be multiple entry for Ver 2.1
1695 *
1696 * @param id, spread sprectrum info index
1697 * @return number of SS Entry that match the id
1698 */
1699static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1700 struct bios_parser *bp,
1701 uint32_t id)
1702{
1703 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
1704 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1705 uint32_t size;
1706 uint32_t i;
1707
1708 if (!DATA_TABLES(ASIC_InternalSS_Info))
1709 return 0;
1710
1711 header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1712 DATA_TABLES(ASIC_InternalSS_Info));
1713
1714 size = (le16_to_cpu(header_include->sHeader.usStructureSize)
1715 - sizeof(ATOM_COMMON_TABLE_HEADER))
1716 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1717
1718 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1719 &header_include->asSpreadSpectrum[0];
1720 for (i = 0; i < size; i++)
1721 if (tbl[i].ucClockIndication == (uint8_t)id)
1722 return 1;
1723
1724 return 0;
1725}
1726/**
1727 * get_ss_entry_number_from_internal_ss_info_table_V3_1
1728 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
1729 * the VBIOS that matches id
1730 *
1731 * @param[in] id, spread sprectrum id
1732 * @return number of SS Entry that match the id
1733 */
1734static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1735 struct bios_parser *bp,
1736 uint32_t id)
1737{
1738 uint32_t number = 0;
1739 ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
1740 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
1741 uint32_t size;
1742 uint32_t i;
1743
1744 if (!DATA_TABLES(ASIC_InternalSS_Info))
1745 return number;
1746
1747 header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
1748 DATA_TABLES(ASIC_InternalSS_Info));
1749 size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
1750 sizeof(ATOM_COMMON_TABLE_HEADER)) /
1751 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1752
1753 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
1754 &header_include->asSpreadSpectrum[0];
1755
1756 for (i = 0; i < size; i++)
1757 if (tbl[i].ucClockIndication == (uint8_t)id)
1758 number++;
1759
1760 return number;
1761}
1762
1763/**
1764 * bios_parser_get_gpio_pin_info
1765 * Get GpioPin information of input gpio id
1766 *
1767 * @param gpio_id, GPIO ID
1768 * @param info, GpioPin information structure
1769 * @return Bios parser result code
1770 * @note
1771 * to get the GPIO PIN INFO, we need:
1772 * 1. get the GPIO_ID from other object table, see GetHPDInfo()
1773 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
1774 * offset/mask
1775 */
1776static enum bp_result bios_parser_get_gpio_pin_info(
1777 struct dc_bios *dcb,
1778 uint32_t gpio_id,
1779 struct gpio_pin_info *info)
1780{
1781 struct bios_parser *bp = BP_FROM_DCB(dcb);
1782 ATOM_GPIO_PIN_LUT *header;
1783 uint32_t count = 0;
1784 uint32_t i = 0;
1785
1786 if (!DATA_TABLES(GPIO_Pin_LUT))
1787 return BP_RESULT_BADBIOSTABLE;
1788
1789 header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
1790 if (!header)
1791 return BP_RESULT_BADBIOSTABLE;
1792
1793 if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
1794 > le16_to_cpu(header->sHeader.usStructureSize))
1795 return BP_RESULT_BADBIOSTABLE;
1796
1797 if (1 != header->sHeader.ucTableContentRevision)
1798 return BP_RESULT_UNSUPPORTED;
1799
1800 count = (le16_to_cpu(header->sHeader.usStructureSize)
1801 - sizeof(ATOM_COMMON_TABLE_HEADER))
1802 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
1803 for (i = 0; i < count; ++i) {
1804 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
1805 continue;
1806
1807 info->offset =
1808 (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
1809 info->offset_y = info->offset + 2;
1810 info->offset_en = info->offset + 1;
1811 info->offset_mask = info->offset - 1;
1812
1813 info->mask = (uint32_t) (1 <<
1814 header->asGPIO_Pin[i].ucGpioPinBitShift);
1815 info->mask_y = info->mask + 2;
1816 info->mask_en = info->mask + 1;
1817 info->mask_mask = info->mask - 1;
1818
1819 return BP_RESULT_OK;
1820 }
1821
1822 return BP_RESULT_NORECORD;
1823}
1824
1825static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
1826 ATOM_I2C_RECORD *record,
1827 struct graphics_object_i2c_info *info)
1828{
1829 ATOM_GPIO_I2C_INFO *header;
1830 uint32_t count = 0;
1831
1832 if (!info)
1833 return BP_RESULT_BADINPUT;
1834
1835 /* get the GPIO_I2C info */
1836 if (!DATA_TABLES(GPIO_I2C_Info))
1837 return BP_RESULT_BADBIOSTABLE;
1838
1839 header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
1840 if (!header)
1841 return BP_RESULT_BADBIOSTABLE;
1842
1843 if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
1844 > le16_to_cpu(header->sHeader.usStructureSize))
1845 return BP_RESULT_BADBIOSTABLE;
1846
1847 if (1 != header->sHeader.ucTableContentRevision)
1848 return BP_RESULT_UNSUPPORTED;
1849
1850 /* get data count */
1851 count = (le16_to_cpu(header->sHeader.usStructureSize)
1852 - sizeof(ATOM_COMMON_TABLE_HEADER))
1853 / sizeof(ATOM_GPIO_I2C_ASSIGMENT);
1854 if (count < record->sucI2cId.bfI2C_LineMux)
1855 return BP_RESULT_BADBIOSTABLE;
1856
1857 /* get the GPIO_I2C_INFO */
1858 info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
1859 info->i2c_line = record->sucI2cId.bfI2C_LineMux;
1860 info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
1861 info->i2c_slave_address = record->ucI2CAddr;
1862
1863 info->gpio_info.clk_mask_register_index =
1864 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
1865 info->gpio_info.clk_en_register_index =
1866 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
1867 info->gpio_info.clk_y_register_index =
1868 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
1869 info->gpio_info.clk_a_register_index =
1870 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
1871 info->gpio_info.data_mask_register_index =
1872 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
1873 info->gpio_info.data_en_register_index =
1874 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
1875 info->gpio_info.data_y_register_index =
1876 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
1877 info->gpio_info.data_a_register_index =
1878 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
1879
1880 info->gpio_info.clk_mask_shift =
1881 header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
1882 info->gpio_info.clk_en_shift =
1883 header->asGPIO_Info[info->i2c_line].ucClkEnShift;
1884 info->gpio_info.clk_y_shift =
1885 header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
1886 info->gpio_info.clk_a_shift =
1887 header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
1888 info->gpio_info.data_mask_shift =
1889 header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
1890 info->gpio_info.data_en_shift =
1891 header->asGPIO_Info[info->i2c_line].ucDataEnShift;
1892 info->gpio_info.data_y_shift =
1893 header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
1894 info->gpio_info.data_a_shift =
1895 header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
1896
1897 return BP_RESULT_OK;
1898}
1899
1900static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
1901{
1902 bool rc = true;
1903
1904 switch (id.type) {
1905 case OBJECT_TYPE_UNKNOWN:
1906 rc = false;
1907 break;
1908 case OBJECT_TYPE_GPU:
1909 case OBJECT_TYPE_ENGINE:
1910 /* do NOT check for id.id == 0 */
1911 if (id.enum_id == ENUM_ID_UNKNOWN)
1912 rc = false;
1913 break;
1914 default:
1915 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
1916 rc = false;
1917 break;
1918 }
1919
1920 return rc;
1921}
1922
1923static bool dal_graphics_object_id_is_equal(
1924 struct graphics_object_id id1,
1925 struct graphics_object_id id2)
1926{
1927 if (false == dal_graphics_object_id_is_valid(id1)) {
1928 dm_output_to_console(
1929 "%s: Warning: comparing invalid object 'id1'!\n", __func__);
1930 return false;
1931 }
1932
1933 if (false == dal_graphics_object_id_is_valid(id2)) {
1934 dm_output_to_console(
1935 "%s: Warning: comparing invalid object 'id2'!\n", __func__);
1936 return false;
1937 }
1938
1939 if (id1.id == id2.id && id1.enum_id == id2.enum_id
1940 && id1.type == id2.type)
1941 return true;
1942
1943 return false;
1944}
1945
1946static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
1947 struct graphics_object_id id)
1948{
1949 uint32_t offset;
1950 ATOM_OBJECT_TABLE *tbl;
1951 uint32_t i;
1952
1953 switch (id.type) {
1954 case OBJECT_TYPE_ENCODER:
1955 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
1956 break;
1957
1958 case OBJECT_TYPE_CONNECTOR:
1959 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
1960 break;
1961
1962 case OBJECT_TYPE_ROUTER:
1963 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
1964 break;
1965
1966 case OBJECT_TYPE_GENERIC:
1967 if (bp->object_info_tbl.revision.minor < 3)
1968 return NULL;
1969 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
1970 break;
1971
1972 default:
1973 return NULL;
1974 }
1975
1976 offset += bp->object_info_tbl_offset;
1977
1978 tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
1979 if (!tbl)
1980 return NULL;
1981
1982 for (i = 0; i < tbl->ucNumberOfObjects; i++)
1983 if (dal_graphics_object_id_is_equal(id,
1984 object_id_from_bios_object_id(
1985 le16_to_cpu(tbl->asObjects[i].usObjectID))))
1986 return &tbl->asObjects[i];
1987
1988 return NULL;
1989}
1990
1991static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
1992 uint16_t **id_list)
1993{
1994 uint32_t offset;
1995 uint8_t *number;
1996
1997 if (!object) {
1998 BREAK_TO_DEBUGGER(); /* Invalid object id */
1999 return 0;
2000 }
2001
2002 offset = le16_to_cpu(object->usSrcDstTableOffset)
2003 + bp->object_info_tbl_offset;
2004
2005 number = GET_IMAGE(uint8_t, offset);
2006 if (!number)
2007 return 0;
2008
2009 offset += sizeof(uint8_t);
2010 *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2011
2012 if (!*id_list)
2013 return 0;
2014
2015 return *number;
2016}
2017
2018static struct device_id device_type_from_device_id(uint16_t device_id)
2019{
2020
2021 struct device_id result_device_id = {0};
2022
2023 switch (device_id) {
2024 case ATOM_DEVICE_LCD1_SUPPORT:
2025 result_device_id.device_type = DEVICE_TYPE_LCD;
2026 result_device_id.enum_id = 1;
2027 break;
2028
2029 case ATOM_DEVICE_LCD2_SUPPORT:
2030 result_device_id.device_type = DEVICE_TYPE_LCD;
2031 result_device_id.enum_id = 2;
2032 break;
2033
2034 case ATOM_DEVICE_CRT1_SUPPORT:
2035 result_device_id.device_type = DEVICE_TYPE_CRT;
2036 result_device_id.enum_id = 1;
2037 break;
2038
2039 case ATOM_DEVICE_CRT2_SUPPORT:
2040 result_device_id.device_type = DEVICE_TYPE_CRT;
2041 result_device_id.enum_id = 2;
2042 break;
2043
2044 case ATOM_DEVICE_DFP1_SUPPORT:
2045 result_device_id.device_type = DEVICE_TYPE_DFP;
2046 result_device_id.enum_id = 1;
2047 break;
2048
2049 case ATOM_DEVICE_DFP2_SUPPORT:
2050 result_device_id.device_type = DEVICE_TYPE_DFP;
2051 result_device_id.enum_id = 2;
2052 break;
2053
2054 case ATOM_DEVICE_DFP3_SUPPORT:
2055 result_device_id.device_type = DEVICE_TYPE_DFP;
2056 result_device_id.enum_id = 3;
2057 break;
2058
2059 case ATOM_DEVICE_DFP4_SUPPORT:
2060 result_device_id.device_type = DEVICE_TYPE_DFP;
2061 result_device_id.enum_id = 4;
2062 break;
2063
2064 case ATOM_DEVICE_DFP5_SUPPORT:
2065 result_device_id.device_type = DEVICE_TYPE_DFP;
2066 result_device_id.enum_id = 5;
2067 break;
2068
2069 case ATOM_DEVICE_DFP6_SUPPORT:
2070 result_device_id.device_type = DEVICE_TYPE_DFP;
2071 result_device_id.enum_id = 6;
2072 break;
2073
2074 default:
2075 BREAK_TO_DEBUGGER(); /* Invalid device Id */
2076 result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2077 result_device_id.enum_id = 0;
2078 }
2079 return result_device_id;
2080}
2081
2082static void get_atom_data_table_revision(
2083 ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2084 struct atom_data_revision *tbl_revision)
2085{
2086 if (!tbl_revision)
2087 return;
2088
2089 /* initialize the revision to 0 which is invalid revision */
2090 tbl_revision->major = 0;
2091 tbl_revision->minor = 0;
2092
2093 if (!atom_data_tbl)
2094 return;
2095
2096 tbl_revision->major =
2097 (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2098 tbl_revision->minor =
2099 (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2100}
2101
2102static uint32_t signal_to_ss_id(enum as_signal_type signal)
2103{
2104 uint32_t clk_id_ss = 0;
2105
2106 switch (signal) {
2107 case AS_SIGNAL_TYPE_DVI:
2108 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2109 break;
2110 case AS_SIGNAL_TYPE_HDMI:
2111 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2112 break;
2113 case AS_SIGNAL_TYPE_LVDS:
2114 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2115 break;
2116 case AS_SIGNAL_TYPE_DISPLAY_PORT:
2117 clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2118 break;
2119 case AS_SIGNAL_TYPE_GPU_PLL:
2120 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2121 break;
2122 default:
2123 break;
2124 }
2125 return clk_id_ss;
2126}
2127
2128static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2129{
2130 enum dal_device_type device_type = device_id.device_type;
2131 uint32_t enum_id = device_id.enum_id;
2132
2133 switch (device_type) {
2134 case DEVICE_TYPE_LCD:
2135 switch (enum_id) {
2136 case 1:
2137 return ATOM_DEVICE_LCD1_SUPPORT;
2138 case 2:
2139 return ATOM_DEVICE_LCD2_SUPPORT;
2140 default:
2141 break;
2142 }
2143 break;
2144 case DEVICE_TYPE_CRT:
2145 switch (enum_id) {
2146 case 1:
2147 return ATOM_DEVICE_CRT1_SUPPORT;
2148 case 2:
2149 return ATOM_DEVICE_CRT2_SUPPORT;
2150 default:
2151 break;
2152 }
2153 break;
2154 case DEVICE_TYPE_DFP:
2155 switch (enum_id) {
2156 case 1:
2157 return ATOM_DEVICE_DFP1_SUPPORT;
2158 case 2:
2159 return ATOM_DEVICE_DFP2_SUPPORT;
2160 case 3:
2161 return ATOM_DEVICE_DFP3_SUPPORT;
2162 case 4:
2163 return ATOM_DEVICE_DFP4_SUPPORT;
2164 case 5:
2165 return ATOM_DEVICE_DFP5_SUPPORT;
2166 case 6:
2167 return ATOM_DEVICE_DFP6_SUPPORT;
2168 default:
2169 break;
2170 }
2171 break;
2172 case DEVICE_TYPE_CV:
2173 switch (enum_id) {
2174 case 1:
2175 return ATOM_DEVICE_CV_SUPPORT;
2176 default:
2177 break;
2178 }
2179 break;
2180 case DEVICE_TYPE_TV:
2181 switch (enum_id) {
2182 case 1:
2183 return ATOM_DEVICE_TV1_SUPPORT;
2184 default:
2185 break;
2186 }
2187 break;
2188 default:
2189 break;
2190 };
2191
2192 /* Unidentified device ID, return empty support mask. */
2193 return 0;
2194}
2195
2196/**
2197 * bios_parser_set_scratch_critical_state
2198 *
2199 * @brief
2200 * update critical state bit in VBIOS scratch register
2201 *
2202 * @param
2203 * bool - to set or reset state
2204 */
2205static void bios_parser_set_scratch_critical_state(
2206 struct dc_bios *dcb,
2207 bool state)
2208{
2209 bios_set_scratch_critical_state(dcb, state);
2210}
2211
2212/*
2213 * get_integrated_info_v8
2214 *
2215 * @brief
2216 * Get V8 integrated BIOS information
2217 *
2218 * @param
2219 * bios_parser *bp - [in]BIOS parser handler to get master data table
2220 * integrated_info *info - [out] store and output integrated info
2221 *
2222 * @return
2223 * enum bp_result - BP_RESULT_OK if information is available,
2224 * BP_RESULT_BADBIOSTABLE otherwise.
2225 */
2226static enum bp_result get_integrated_info_v8(
2227 struct bios_parser *bp,
2228 struct integrated_info *info)
2229{
2230 ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
2231 uint32_t i;
2232
2233 info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
2234 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2235
2236 if (info_v8 == NULL)
2237 return BP_RESULT_BADBIOSTABLE;
2238 info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
2239 info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
2240 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2241
2242 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2243 /* Convert [10KHz] into [KHz] */
2244 info->disp_clk_voltage[i].max_supported_clk =
2245 le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
2246 ulMaximumSupportedCLK) * 10;
2247 info->disp_clk_voltage[i].voltage_index =
2248 le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
2249 }
2250
2251 info->boot_up_req_display_vector =
2252 le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
2253 info->gpu_cap_info =
2254 le32_to_cpu(info_v8->ulGPUCapInfo);
2255
2256 /*
2257 * system_config: Bit[0] = 0 : PCIE power gating disabled
2258 * = 1 : PCIE power gating enabled
2259 * Bit[1] = 0 : DDR-PLL shut down disabled
2260 * = 1 : DDR-PLL shut down enabled
2261 * Bit[2] = 0 : DDR-PLL power down disabled
2262 * = 1 : DDR-PLL power down enabled
2263 */
2264 info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
2265 info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
2266 info->boot_up_nb_voltage =
2267 le16_to_cpu(info_v8->usBootUpNBVoltage);
2268 info->ext_disp_conn_info_offset =
2269 le16_to_cpu(info_v8->usExtDispConnInfoOffset);
2270 info->memory_type = info_v8->ucMemoryType;
2271 info->ma_channel_number = info_v8->ucUMAChannelNumber;
2272 info->gmc_restore_reset_time =
2273 le32_to_cpu(info_v8->ulGMCRestoreResetTime);
2274
2275 info->minimum_n_clk =
2276 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
2277 for (i = 1; i < 4; ++i)
2278 info->minimum_n_clk =
2279 info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
2280 info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
2281
2282 info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
2283 info->ddr_dll_power_up_time =
2284 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
2285 info->ddr_pll_power_up_time =
2286 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
2287 info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
2288 info->lvds_ss_percentage =
2289 le16_to_cpu(info_v8->usLvdsSSPercentage);
2290 info->lvds_sspread_rate_in_10hz =
2291 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
2292 info->hdmi_ss_percentage =
2293 le16_to_cpu(info_v8->usHDMISSPercentage);
2294 info->hdmi_sspread_rate_in_10hz =
2295 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
2296 info->dvi_ss_percentage =
2297 le16_to_cpu(info_v8->usDVISSPercentage);
2298 info->dvi_sspread_rate_in_10_hz =
2299 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
2300
2301 info->max_lvds_pclk_freq_in_single_link =
2302 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
2303 info->lvds_misc = info_v8->ucLvdsMisc;
2304 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2305 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2306 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2307 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2308 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2309 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2310 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2311 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2312 info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2313 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2314 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2315 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2316 info->lvds_off_to_on_delay_in_4ms =
2317 info_v8->ucLVDSOffToOnDelay_in4Ms;
2318 info->lvds_bit_depth_control_val =
2319 le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
2320
2321 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2322 /* Convert [10KHz] into [KHz] */
2323 info->avail_s_clk[i].supported_s_clk =
2324 le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2325 info->avail_s_clk[i].voltage_index =
2326 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
2327 info->avail_s_clk[i].voltage_id =
2328 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
2329 }
2330
2331 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2332 info->ext_disp_conn_info.gu_id[i] =
2333 info_v8->sExtDispConnInfo.ucGuid[i];
2334 }
2335
2336 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2337 info->ext_disp_conn_info.path[i].device_connector_id =
2338 object_id_from_bios_object_id(
2339 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
2340
2341 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2342 object_id_from_bios_object_id(
2343 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2344
2345 info->ext_disp_conn_info.path[i].device_tag =
2346 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
2347 info->ext_disp_conn_info.path[i].device_acpi_enum =
2348 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2349 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2350 info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2351 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2352 info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2353 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2354 info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
2355 }
2356 info->ext_disp_conn_info.checksum =
2357 info_v8->sExtDispConnInfo.ucChecksum;
2358
2359 return BP_RESULT_OK;
2360}
2361
2362/*
2363 * get_integrated_info_v8
2364 *
2365 * @brief
2366 * Get V8 integrated BIOS information
2367 *
2368 * @param
2369 * bios_parser *bp - [in]BIOS parser handler to get master data table
2370 * integrated_info *info - [out] store and output integrated info
2371 *
2372 * @return
2373 * enum bp_result - BP_RESULT_OK if information is available,
2374 * BP_RESULT_BADBIOSTABLE otherwise.
2375 */
2376static enum bp_result get_integrated_info_v9(
2377 struct bios_parser *bp,
2378 struct integrated_info *info)
2379{
2380 ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
2381 uint32_t i;
2382
2383 info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
2384 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2385
2386 if (!info_v9)
2387 return BP_RESULT_BADBIOSTABLE;
2388
2389 info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
2390 info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
2391 info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
2392
2393 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2394 /* Convert [10KHz] into [KHz] */
2395 info->disp_clk_voltage[i].max_supported_clk =
2396 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
2397 info->disp_clk_voltage[i].voltage_index =
2398 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
2399 }
2400
2401 info->boot_up_req_display_vector =
2402 le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
2403 info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
2404
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_v9->ulSystemConfig);
2414 info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
2415 info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
2416 info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
2417 info->memory_type = info_v9->ucMemoryType;
2418 info->ma_channel_number = info_v9->ucUMAChannelNumber;
2419 info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
2420
2421 info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
2422 for (i = 1; i < 4; ++i)
2423 info->minimum_n_clk =
2424 info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
2425 info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
2426
2427 info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
2428 info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
2429 info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
2430 info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
2431 info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
2432 info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
2433 info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
2434 info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
2435 info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
2436 info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
2437
2438 info->max_lvds_pclk_freq_in_single_link =
2439 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
2440 info->lvds_misc = info_v9->ucLvdsMisc;
2441 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2442 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2443 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2444 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2445 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2446 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2447 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2448 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2449 info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2450 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2451 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2452 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2453 info->lvds_off_to_on_delay_in_4ms =
2454 info_v9->ucLVDSOffToOnDelay_in4Ms;
2455 info->lvds_bit_depth_control_val =
2456 le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
2457
2458 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2459 /* Convert [10KHz] into [KHz] */
2460 info->avail_s_clk[i].supported_s_clk =
2461 le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2462 info->avail_s_clk[i].voltage_index =
2463 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
2464 info->avail_s_clk[i].voltage_id =
2465 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
2466 }
2467
2468 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2469 info->ext_disp_conn_info.gu_id[i] =
2470 info_v9->sExtDispConnInfo.ucGuid[i];
2471 }
2472
2473 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2474 info->ext_disp_conn_info.path[i].device_connector_id =
2475 object_id_from_bios_object_id(
2476 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
2477
2478 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2479 object_id_from_bios_object_id(
2480 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2481
2482 info->ext_disp_conn_info.path[i].device_tag =
2483 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
2484 info->ext_disp_conn_info.path[i].device_acpi_enum =
2485 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2486 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2487 info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2488 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2489 info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2490 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2491 info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
2492 }
2493 info->ext_disp_conn_info.checksum =
2494 info_v9->sExtDispConnInfo.ucChecksum;
2495
2496 return BP_RESULT_OK;
2497}
2498
2499/*
2500 * construct_integrated_info
2501 *
2502 * @brief
2503 * Get integrated BIOS information based on table revision
2504 *
2505 * @param
2506 * bios_parser *bp - [in]BIOS parser handler to get master data table
2507 * integrated_info *info - [out] store and output integrated info
2508 *
2509 * @return
2510 * enum bp_result - BP_RESULT_OK if information is available,
2511 * BP_RESULT_BADBIOSTABLE otherwise.
2512 */
2513static enum bp_result construct_integrated_info(
2514 struct bios_parser *bp,
2515 struct integrated_info *info)
2516{
2517 enum bp_result result = BP_RESULT_BADBIOSTABLE;
2518
2519 ATOM_COMMON_TABLE_HEADER *header;
2520 struct atom_data_revision revision;
2521
2522 if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
2523 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
2524 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2525
2526 get_atom_data_table_revision(header, &revision);
2527
2528 /* Don't need to check major revision as they are all 1 */
2529 switch (revision.minor) {
2530 case 8:
2531 result = get_integrated_info_v8(bp, info);
2532 break;
2533 case 9:
2534 result = get_integrated_info_v9(bp, info);
2535 break;
2536 default:
2537 return result;
2538
2539 }
2540 }
2541
2542 /* Sort voltage table from low to high*/
2543 if (result == BP_RESULT_OK) {
2544 struct clock_voltage_caps temp = {0, 0};
2545 uint32_t i;
2546 uint32_t j;
2547
2548 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2549 for (j = i; j > 0; --j) {
2550 if (
2551 info->disp_clk_voltage[j].max_supported_clk <
2552 info->disp_clk_voltage[j-1].max_supported_clk) {
2553 /* swap j and j - 1*/
2554 temp = info->disp_clk_voltage[j-1];
2555 info->disp_clk_voltage[j-1] =
2556 info->disp_clk_voltage[j];
2557 info->disp_clk_voltage[j] = temp;
2558 }
2559 }
2560 }
2561
2562 }
2563
2564 return result;
2565}
2566
2567static struct integrated_info *bios_parser_create_integrated_info(
2568 struct dc_bios *dcb)
2569{
2570 struct bios_parser *bp = BP_FROM_DCB(dcb);
2571 struct integrated_info *info = NULL;
2572
2573 info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
2574
2575 if (info == NULL) {
2576 ASSERT_CRITICAL(0);
2577 return NULL;
2578 }
2579
2580 if (construct_integrated_info(bp, info) == BP_RESULT_OK)
2581 return info;
2582
2583 kfree(info);
2584
2585 return NULL;
2586}
2587
2588enum bp_result update_slot_layout_info(
2589 struct dc_bios *dcb,
2590 unsigned int i,
2591 struct slot_layout_info *slot_layout_info,
2592 unsigned int record_offset)
2593{
2594 unsigned int j;
2595 struct bios_parser *bp;
2596 ATOM_BRACKET_LAYOUT_RECORD *record;
2597 ATOM_COMMON_RECORD_HEADER *record_header;
2598 enum bp_result result = BP_RESULT_NORECORD;
2599
2600 bp = BP_FROM_DCB(dcb);
2601 record = NULL;
2602 record_header = NULL;
2603
2604 for (;;) {
2605
2606 record_header = (ATOM_COMMON_RECORD_HEADER *)
2607 GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
2608 if (record_header == NULL) {
2609 result = BP_RESULT_BADBIOSTABLE;
2610 break;
2611 }
2612
2613 /* the end of the list */
2614 if (record_header->ucRecordType == 0xff ||
2615 record_header->ucRecordSize == 0) {
2616 break;
2617 }
2618
2619 if (record_header->ucRecordType ==
2620 ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
2621 sizeof(ATOM_BRACKET_LAYOUT_RECORD)
2622 <= record_header->ucRecordSize) {
2623 record = (ATOM_BRACKET_LAYOUT_RECORD *)
2624 (record_header);
2625 result = BP_RESULT_OK;
2626 break;
2627 }
2628
2629 record_offset += record_header->ucRecordSize;
2630 }
2631
2632 /* return if the record not found */
2633 if (result != BP_RESULT_OK)
2634 return result;
2635
2636 /* get slot sizes */
2637 slot_layout_info->length = record->ucLength;
2638 slot_layout_info->width = record->ucWidth;
2639
2640 /* get info for each connector in the slot */
2641 slot_layout_info->num_of_connectors = record->ucConnNum;
2642 for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
2643 slot_layout_info->connectors[j].connector_type =
2644 (enum connector_layout_type)
2645 (record->asConnInfo[j].ucConnectorType);
2646 switch (record->asConnInfo[j].ucConnectorType) {
2647 case CONNECTOR_TYPE_DVI_D:
2648 slot_layout_info->connectors[j].connector_type =
2649 CONNECTOR_LAYOUT_TYPE_DVI_D;
2650 slot_layout_info->connectors[j].length =
2651 CONNECTOR_SIZE_DVI;
2652 break;
2653
2654 case CONNECTOR_TYPE_HDMI:
2655 slot_layout_info->connectors[j].connector_type =
2656 CONNECTOR_LAYOUT_TYPE_HDMI;
2657 slot_layout_info->connectors[j].length =
2658 CONNECTOR_SIZE_HDMI;
2659 break;
2660
2661 case CONNECTOR_TYPE_DISPLAY_PORT:
2662 slot_layout_info->connectors[j].connector_type =
2663 CONNECTOR_LAYOUT_TYPE_DP;
2664 slot_layout_info->connectors[j].length =
2665 CONNECTOR_SIZE_DP;
2666 break;
2667
2668 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
2669 slot_layout_info->connectors[j].connector_type =
2670 CONNECTOR_LAYOUT_TYPE_MINI_DP;
2671 slot_layout_info->connectors[j].length =
2672 CONNECTOR_SIZE_MINI_DP;
2673 break;
2674
2675 default:
2676 slot_layout_info->connectors[j].connector_type =
2677 CONNECTOR_LAYOUT_TYPE_UNKNOWN;
2678 slot_layout_info->connectors[j].length =
2679 CONNECTOR_SIZE_UNKNOWN;
2680 }
2681
2682 slot_layout_info->connectors[j].position =
2683 record->asConnInfo[j].ucPosition;
2684 slot_layout_info->connectors[j].connector_id =
2685 object_id_from_bios_object_id(
2686 record->asConnInfo[j].usConnectorObjectId);
2687 }
2688 return result;
2689}
2690
2691
2692enum bp_result get_bracket_layout_record(
2693 struct dc_bios *dcb,
2694 unsigned int bracket_layout_id,
2695 struct slot_layout_info *slot_layout_info)
2696{
2697 unsigned int i;
2698 unsigned int record_offset;
2699 struct bios_parser *bp;
2700 enum bp_result result;
2701 ATOM_OBJECT *object;
2702 ATOM_OBJECT_TABLE *object_table;
2703 unsigned int genericTableOffset;
2704
2705 bp = BP_FROM_DCB(dcb);
2706 object = NULL;
2707 if (slot_layout_info == NULL) {
2708 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
2709 return BP_RESULT_BADINPUT;
2710 }
2711
2712
2713 genericTableOffset = bp->object_info_tbl_offset +
2714 bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
2715 object_table = (ATOM_OBJECT_TABLE *)
2716 GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset);
2717 if (!object_table)
2718 return BP_RESULT_FAILURE;
2719
2720 result = BP_RESULT_NORECORD;
2721 for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
2722
2723 if (bracket_layout_id ==
2724 object_table->asObjects[i].usObjectID) {
2725
2726 object = &object_table->asObjects[i];
2727 record_offset = object->usRecordOffset +
2728 bp->object_info_tbl_offset;
2729
2730 result = update_slot_layout_info(dcb, i,
2731 slot_layout_info, record_offset);
2732 break;
2733 }
2734 }
2735 return result;
2736}
2737
2738static enum bp_result bios_get_board_layout_info(
2739 struct dc_bios *dcb,
2740 struct board_layout_info *board_layout_info)
2741{
2742 unsigned int i;
2743 struct bios_parser *bp;
2744 enum bp_result record_result;
2745
2746 const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
2747 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
2748 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
2749 0, 0
2750 };
2751
2752 bp = BP_FROM_DCB(dcb);
2753 if (board_layout_info == NULL) {
2754 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
2755 return BP_RESULT_BADINPUT;
2756 }
2757
2758 board_layout_info->num_of_slots = 0;
2759
2760 for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
2761 record_result = get_bracket_layout_record(dcb,
2762 slot_index_to_vbios_id[i],
2763 &board_layout_info->slots[i]);
2764
2765 if (record_result == BP_RESULT_NORECORD && i > 0)
2766 break; /* no more slots present in bios */
2767 else if (record_result != BP_RESULT_OK)
2768 return record_result; /* fail */
2769
2770 ++board_layout_info->num_of_slots;
2771 }
2772
2773 /* all data is valid */
2774 board_layout_info->is_number_of_slots_valid = 1;
2775 board_layout_info->is_slots_size_valid = 1;
2776 board_layout_info->is_connector_offsets_valid = 1;
2777 board_layout_info->is_connector_lengths_valid = 1;
2778
2779 return BP_RESULT_OK;
2780}
2781
2782/******************************************************************************/
2783
2784static const struct dc_vbios_funcs vbios_funcs = {
2785 .get_connectors_number = bios_parser_get_connectors_number,
2786
2787 .get_connector_id = bios_parser_get_connector_id,
2788
2789 .get_src_obj = bios_parser_get_src_obj,
2790
2791 .get_i2c_info = bios_parser_get_i2c_info,
2792
2793 .get_hpd_info = bios_parser_get_hpd_info,
2794
2795 .get_device_tag = bios_parser_get_device_tag,
2796
2797 .get_firmware_info = bios_parser_get_firmware_info,
2798
2799 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
2800
2801 .get_ss_entry_number = bios_parser_get_ss_entry_number,
2802
2803 .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
2804
2805 .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
2806
2807 .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
2808
2809 /* bios scratch register communication */
2810 .is_accelerated_mode = bios_is_accelerated_mode,
2811
2812 .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
2813
2814 .is_device_id_supported = bios_parser_is_device_id_supported,
2815
2816 /* COMMANDS */
2817 .encoder_control = bios_parser_encoder_control,
2818
2819 .transmitter_control = bios_parser_transmitter_control,
2820
2821 .enable_crtc = bios_parser_enable_crtc,
2822
2823 .adjust_pixel_clock = bios_parser_adjust_pixel_clock,
2824
2825 .set_pixel_clock = bios_parser_set_pixel_clock,
2826
2827 .set_dce_clock = bios_parser_set_dce_clock,
2828
2829 .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
2830
2831 .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */
2832
2833 .program_display_engine_pll = bios_parser_program_display_engine_pll,
2834
2835 .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
2836
2837 /* SW init and patch */
2838
2839 .bios_parser_destroy = bios_parser_destroy,
2840
2841 .get_board_layout_info = bios_get_board_layout_info,
2842};
2843
2844static bool bios_parser_construct(
2845 struct bios_parser *bp,
2846 struct bp_init_data *init,
2847 enum dce_version dce_version)
2848{
2849 uint16_t *rom_header_offset = NULL;
2850 ATOM_ROM_HEADER *rom_header = NULL;
2851 ATOM_OBJECT_HEADER *object_info_tbl;
2852 struct atom_data_revision tbl_rev = {0};
2853
2854 if (!init)
2855 return false;
2856
2857 if (!init->bios)
2858 return false;
2859
2860 bp->base.funcs = &vbios_funcs;
2861 bp->base.bios = init->bios;
2862 bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
2863
2864 bp->base.ctx = init->ctx;
2865 bp->base.bios_local_image = NULL;
2866
2867 rom_header_offset =
2868 GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
2869
2870 if (!rom_header_offset)
2871 return false;
2872
2873 rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
2874
2875 if (!rom_header)
2876 return false;
2877
2878 get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
2879 if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
2880 return false;
2881
2882 bp->master_data_tbl =
2883 GET_IMAGE(ATOM_MASTER_DATA_TABLE,
2884 rom_header->usMasterDataTableOffset);
2885
2886 if (!bp->master_data_tbl)
2887 return false;
2888
2889 bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
2890
2891 if (!bp->object_info_tbl_offset)
2892 return false;
2893
2894 object_info_tbl =
2895 GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
2896
2897 if (!object_info_tbl)
2898 return false;
2899
2900 get_atom_data_table_revision(&object_info_tbl->sHeader,
2901 &bp->object_info_tbl.revision);
2902
2903 if (bp->object_info_tbl.revision.major == 1
2904 && bp->object_info_tbl.revision.minor >= 3) {
2905 ATOM_OBJECT_HEADER_V3 *tbl_v3;
2906
2907 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
2908 bp->object_info_tbl_offset);
2909 if (!tbl_v3)
2910 return false;
2911
2912 bp->object_info_tbl.v1_3 = tbl_v3;
2913 } else if (bp->object_info_tbl.revision.major == 1
2914 && bp->object_info_tbl.revision.minor >= 1)
2915 bp->object_info_tbl.v1_1 = object_info_tbl;
2916 else
2917 return false;
2918
2919 dal_bios_parser_init_cmd_tbl(bp);
2920 dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
2921
2922 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
2923
2924 return true;
2925}
2926
2927/******************************************************************************/