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