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