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