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