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