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