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