]>
Commit | Line | Data |
---|---|---|
ae79c310 HW |
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 "dm_services.h" | |
27 | ||
28 | #include "ObjectID.h" | |
29 | #include "atomfirmware.h" | |
ae79c310 HW |
30 | |
31 | #include "include/bios_parser_interface.h" | |
32 | ||
33 | #include "command_table2.h" | |
34 | #include "command_table_helper2.h" | |
35 | #include "bios_parser_helper.h" | |
36 | #include "bios_parser_types_internal2.h" | |
37 | ||
38 | #define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\ | |
39 | (((char *)(&((\ | |
40 | struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\ | |
41 | ->FieldName)-(char *)0)/sizeof(uint16_t)) | |
42 | ||
43 | #define EXEC_BIOS_CMD_TABLE(fname, params)\ | |
44 | (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ | |
45 | GET_INDEX_INTO_MASTER_TABLE(command, fname), \ | |
46 | ¶ms) == 0) | |
47 | ||
48 | #define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\ | |
49 | cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ | |
50 | GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev) | |
51 | ||
52 | #define BIOS_CMD_TABLE_PARA_REVISION(fname)\ | |
53 | bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ | |
54 | GET_INDEX_INTO_MASTER_TABLE(command, fname)) | |
55 | ||
56 | static void init_dig_encoder_control(struct bios_parser *bp); | |
57 | static void init_transmitter_control(struct bios_parser *bp); | |
58 | static void init_set_pixel_clock(struct bios_parser *bp); | |
59 | ||
60 | static void init_set_crtc_timing(struct bios_parser *bp); | |
61 | ||
62 | static void init_select_crtc_source(struct bios_parser *bp); | |
63 | static void init_enable_crtc(struct bios_parser *bp); | |
64 | ||
65 | static void init_external_encoder_control(struct bios_parser *bp); | |
66 | static void init_enable_disp_power_gating(struct bios_parser *bp); | |
67 | static void init_set_dce_clock(struct bios_parser *bp); | |
68 | static void init_get_smu_clock_info(struct bios_parser *bp); | |
69 | ||
70 | void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) | |
71 | { | |
72 | init_dig_encoder_control(bp); | |
73 | init_transmitter_control(bp); | |
74 | init_set_pixel_clock(bp); | |
75 | ||
76 | init_set_crtc_timing(bp); | |
77 | ||
78 | init_select_crtc_source(bp); | |
79 | init_enable_crtc(bp); | |
80 | ||
81 | init_external_encoder_control(bp); | |
82 | init_enable_disp_power_gating(bp); | |
83 | init_set_dce_clock(bp); | |
84 | init_get_smu_clock_info(bp); | |
85 | } | |
86 | ||
87 | static uint32_t bios_cmd_table_para_revision(void *cgs_device, | |
88 | uint32_t index) | |
89 | { | |
90 | uint8_t frev, crev; | |
91 | ||
92 | if (cgs_atom_get_cmd_table_revs(cgs_device, | |
93 | index, | |
94 | &frev, &crev) != 0) | |
95 | return 0; | |
96 | return crev; | |
97 | } | |
98 | ||
99 | /****************************************************************************** | |
100 | ****************************************************************************** | |
101 | ** | |
102 | ** D I G E N C O D E R C O N T R O L | |
103 | ** | |
104 | ****************************************************************************** | |
105 | *****************************************************************************/ | |
106 | ||
107 | static enum bp_result encoder_control_digx_v1_5( | |
108 | struct bios_parser *bp, | |
109 | struct bp_encoder_control *cntl); | |
110 | ||
111 | static void init_dig_encoder_control(struct bios_parser *bp) | |
112 | { | |
113 | uint32_t version = | |
114 | BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol); | |
115 | ||
116 | switch (version) { | |
117 | case 5: | |
118 | bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; | |
119 | break; | |
120 | default: | |
121 | bp->cmd_tbl.dig_encoder_control = NULL; | |
122 | break; | |
123 | } | |
124 | } | |
125 | ||
126 | static enum bp_result encoder_control_digx_v1_5( | |
127 | struct bios_parser *bp, | |
128 | struct bp_encoder_control *cntl) | |
129 | { | |
130 | enum bp_result result = BP_RESULT_FAILURE; | |
131 | struct dig_encoder_stream_setup_parameters_v1_5 params = {0}; | |
132 | ||
133 | params.digid = (uint8_t)(cntl->engine_id); | |
134 | params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action); | |
135 | ||
136 | params.pclk_10khz = cntl->pixel_clock / 10; | |
137 | params.digmode = | |
138 | (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( | |
139 | cntl->signal, | |
140 | cntl->enable_dp_audio)); | |
141 | params.lanenum = (uint8_t)(cntl->lanes_number); | |
142 | ||
143 | switch (cntl->color_depth) { | |
144 | case COLOR_DEPTH_888: | |
145 | params.bitpercolor = PANEL_8BIT_PER_COLOR; | |
146 | break; | |
147 | case COLOR_DEPTH_101010: | |
148 | params.bitpercolor = PANEL_10BIT_PER_COLOR; | |
149 | break; | |
150 | case COLOR_DEPTH_121212: | |
151 | params.bitpercolor = PANEL_12BIT_PER_COLOR; | |
152 | break; | |
153 | case COLOR_DEPTH_161616: | |
154 | params.bitpercolor = PANEL_16BIT_PER_COLOR; | |
155 | break; | |
156 | default: | |
157 | break; | |
158 | } | |
159 | ||
160 | if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) | |
161 | switch (cntl->color_depth) { | |
162 | case COLOR_DEPTH_101010: | |
163 | params.pclk_10khz = | |
164 | (params.pclk_10khz * 30) / 24; | |
165 | break; | |
166 | case COLOR_DEPTH_121212: | |
167 | params.pclk_10khz = | |
168 | (params.pclk_10khz * 36) / 24; | |
169 | break; | |
170 | case COLOR_DEPTH_161616: | |
171 | params.pclk_10khz = | |
172 | (params.pclk_10khz * 48) / 24; | |
173 | break; | |
174 | default: | |
175 | break; | |
176 | } | |
177 | ||
178 | if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params)) | |
179 | result = BP_RESULT_OK; | |
180 | ||
181 | return result; | |
182 | } | |
183 | ||
184 | /***************************************************************************** | |
185 | ****************************************************************************** | |
186 | ** | |
187 | ** TRANSMITTER CONTROL | |
188 | ** | |
189 | ****************************************************************************** | |
190 | *****************************************************************************/ | |
191 | ||
192 | static enum bp_result transmitter_control_v1_6( | |
193 | struct bios_parser *bp, | |
194 | struct bp_transmitter_control *cntl); | |
195 | ||
196 | static void init_transmitter_control(struct bios_parser *bp) | |
197 | { | |
198 | uint8_t frev; | |
199 | uint8_t crev; | |
200 | ||
201 | if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) != 0) | |
202 | BREAK_TO_DEBUGGER(); | |
203 | switch (crev) { | |
204 | case 6: | |
205 | bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; | |
206 | break; | |
207 | default: | |
208 | bp->cmd_tbl.transmitter_control = NULL; | |
209 | break; | |
210 | } | |
211 | } | |
212 | ||
213 | static enum bp_result transmitter_control_v1_6( | |
214 | struct bios_parser *bp, | |
215 | struct bp_transmitter_control *cntl) | |
216 | { | |
217 | enum bp_result result = BP_RESULT_FAILURE; | |
218 | const struct command_table_helper *cmd = bp->cmd_helper; | |
219 | struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } }; | |
220 | ||
221 | ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter); | |
222 | ps.param.action = (uint8_t)cntl->action; | |
223 | ||
224 | if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) | |
225 | ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; | |
226 | else | |
227 | ps.param.mode_laneset.digmode = | |
228 | cmd->signal_type_to_atom_dig_mode(cntl->signal); | |
229 | ||
230 | ps.param.lanenum = (uint8_t)cntl->lanes_number; | |
231 | ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); | |
232 | ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); | |
233 | ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id; | |
234 | ps.param.symclk_10khz = cntl->pixel_clock/10; | |
235 | ||
236 | ||
237 | if (cntl->action == TRANSMITTER_CONTROL_ENABLE || | |
238 | cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || | |
239 | cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { | |
7fc6ff77 JL |
240 | dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ |
241 | "%s:ps.param.symclk_10khz = %d\n",\ | |
ae79c310 HW |
242 | __func__, ps.param.symclk_10khz); |
243 | } | |
244 | ||
245 | ||
246 | /*color_depth not used any more, driver has deep color factor in the Phyclk*/ | |
247 | if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps)) | |
248 | result = BP_RESULT_OK; | |
249 | return result; | |
250 | } | |
251 | ||
252 | /****************************************************************************** | |
253 | ****************************************************************************** | |
254 | ** | |
255 | ** SET PIXEL CLOCK | |
256 | ** | |
257 | ****************************************************************************** | |
258 | *****************************************************************************/ | |
259 | ||
260 | static enum bp_result set_pixel_clock_v7( | |
261 | struct bios_parser *bp, | |
262 | struct bp_pixel_clock_parameters *bp_params); | |
263 | ||
264 | static void init_set_pixel_clock(struct bios_parser *bp) | |
265 | { | |
266 | switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) { | |
267 | case 7: | |
268 | bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; | |
269 | break; | |
270 | default: | |
271 | bp->cmd_tbl.set_pixel_clock = NULL; | |
272 | break; | |
273 | } | |
274 | } | |
275 | ||
276 | ||
277 | ||
278 | static enum bp_result set_pixel_clock_v7( | |
279 | struct bios_parser *bp, | |
280 | struct bp_pixel_clock_parameters *bp_params) | |
281 | { | |
282 | enum bp_result result = BP_RESULT_FAILURE; | |
283 | struct set_pixel_clock_parameter_v1_7 clk; | |
284 | uint8_t controller_id; | |
285 | uint32_t pll_id; | |
286 | ||
287 | memset(&clk, 0, sizeof(clk)); | |
288 | ||
289 | if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) | |
290 | && bp->cmd_helper->controller_id_to_atom(bp_params-> | |
291 | controller_id, &controller_id)) { | |
292 | /* Note: VBIOS still wants to use ucCRTC name which is now | |
293 | * 1 byte in ULONG | |
294 | *typedef struct _CRTC_PIXEL_CLOCK_FREQ | |
295 | *{ | |
296 | * target the pixel clock to drive the CRTC timing. | |
297 | * ULONG ulPixelClock:24; | |
298 | * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to | |
299 | * previous version. | |
300 | * ATOM_CRTC1~6, indicate the CRTC controller to | |
301 | * ULONG ucCRTC:8; | |
302 | * drive the pixel clock. not used for DCPLL case. | |
303 | *}CRTC_PIXEL_CLOCK_FREQ; | |
304 | *union | |
305 | *{ | |
306 | * pixel clock and CRTC id frequency | |
307 | * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; | |
308 | * ULONG ulDispEngClkFreq; dispclk frequency | |
309 | *}; | |
310 | */ | |
311 | clk.crtc_id = controller_id; | |
312 | clk.pll_id = (uint8_t) pll_id; | |
313 | clk.encoderobjid = | |
314 | bp->cmd_helper->encoder_id_to_atom( | |
315 | dal_graphics_object_id_get_encoder_id( | |
316 | bp_params->encoder_object_id)); | |
317 | ||
318 | clk.encoder_mode = (uint8_t) bp-> | |
319 | cmd_helper->encoder_mode_bp_to_atom( | |
320 | bp_params->signal_type, false); | |
321 | ||
322 | /* We need to convert from KHz units into 10KHz units */ | |
323 | clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock * | |
324 | 10); | |
325 | ||
326 | clk.deep_color_ratio = | |
327 | (uint8_t) bp->cmd_helper-> | |
328 | transmitter_color_depth_to_atom( | |
329 | bp_params->color_depth); | |
7fc6ff77 JL |
330 | dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ |
331 | "%s:program display clock = %d"\ | |
ae79c310 HW |
332 | "colorDepth = %d\n", __func__,\ |
333 | bp_params->target_pixel_clock, bp_params->color_depth); | |
334 | ||
335 | if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) | |
336 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; | |
337 | ||
338 | if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) | |
339 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; | |
340 | ||
341 | if (bp_params->flags.SUPPORT_YUV_420) | |
342 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; | |
343 | ||
344 | if (bp_params->flags.SET_XTALIN_REF_SRC) | |
345 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; | |
346 | ||
347 | if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) | |
348 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; | |
349 | ||
350 | if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) | |
351 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; | |
352 | ||
353 | if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk)) | |
354 | result = BP_RESULT_OK; | |
355 | } | |
356 | return result; | |
357 | } | |
358 | ||
359 | /****************************************************************************** | |
360 | ****************************************************************************** | |
361 | ** | |
362 | ** SET CRTC TIMING | |
363 | ** | |
364 | ****************************************************************************** | |
365 | *****************************************************************************/ | |
366 | ||
367 | static enum bp_result set_crtc_using_dtd_timing_v3( | |
368 | struct bios_parser *bp, | |
369 | struct bp_hw_crtc_timing_parameters *bp_params); | |
370 | ||
371 | static void init_set_crtc_timing(struct bios_parser *bp) | |
372 | { | |
373 | uint32_t dtd_version = | |
374 | BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); | |
375 | ||
bf5563ed DA |
376 | switch (dtd_version) { |
377 | case 3: | |
378 | bp->cmd_tbl.set_crtc_timing = | |
379 | set_crtc_using_dtd_timing_v3; | |
380 | break; | |
381 | default: | |
382 | bp->cmd_tbl.set_crtc_timing = NULL; | |
383 | break; | |
384 | } | |
ae79c310 HW |
385 | } |
386 | ||
387 | static enum bp_result set_crtc_using_dtd_timing_v3( | |
388 | struct bios_parser *bp, | |
389 | struct bp_hw_crtc_timing_parameters *bp_params) | |
390 | { | |
391 | enum bp_result result = BP_RESULT_FAILURE; | |
392 | struct set_crtc_using_dtd_timing_parameters params = {0}; | |
393 | uint8_t atom_controller_id; | |
394 | ||
395 | if (bp->cmd_helper->controller_id_to_atom( | |
396 | bp_params->controller_id, &atom_controller_id)) | |
397 | params.crtc_id = atom_controller_id; | |
398 | ||
399 | /* bios usH_Size wants h addressable size */ | |
400 | params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable); | |
401 | /* bios usH_Blanking_Time wants borders included in blanking */ | |
402 | params.h_blanking_time = | |
403 | cpu_to_le16((uint16_t)(bp_params->h_total - | |
404 | bp_params->h_addressable)); | |
405 | /* bios usV_Size wants v addressable size */ | |
406 | params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable); | |
407 | /* bios usV_Blanking_Time wants borders included in blanking */ | |
408 | params.v_blanking_time = | |
409 | cpu_to_le16((uint16_t)(bp_params->v_total - | |
410 | bp_params->v_addressable)); | |
411 | /* bios usHSyncOffset is the offset from the end of h addressable, | |
412 | * our horizontalSyncStart is the offset from the beginning | |
413 | * of h addressable | |
414 | */ | |
415 | params.h_syncoffset = | |
416 | cpu_to_le16((uint16_t)(bp_params->h_sync_start - | |
417 | bp_params->h_addressable)); | |
418 | params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); | |
419 | /* bios usHSyncOffset is the offset from the end of v addressable, | |
420 | * our verticalSyncStart is the offset from the beginning of | |
421 | * v addressable | |
422 | */ | |
423 | params.v_syncoffset = | |
424 | cpu_to_le16((uint16_t)(bp_params->v_sync_start - | |
425 | bp_params->v_addressable)); | |
426 | params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); | |
427 | ||
428 | /* we assume that overscan from original timing does not get bigger | |
429 | * than 255 | |
430 | * we will program all the borders in the Set CRTC Overscan call below | |
431 | */ | |
432 | ||
433 | if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0) | |
434 | params.modemiscinfo = | |
435 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | | |
436 | ATOM_HSYNC_POLARITY); | |
437 | ||
438 | if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0) | |
439 | params.modemiscinfo = | |
440 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | | |
441 | ATOM_VSYNC_POLARITY); | |
442 | ||
443 | if (bp_params->flags.INTERLACE) { | |
444 | params.modemiscinfo = | |
445 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | | |
446 | ATOM_INTERLACE); | |
447 | ||
448 | /* original DAL code has this condition to apply this | |
449 | * for non-TV/CV only | |
450 | * due to complex MV testing for possible impact | |
451 | * if ( pACParameters->signal != SignalType_YPbPr && | |
452 | * pACParameters->signal != SignalType_Composite && | |
453 | * pACParameters->signal != SignalType_SVideo) | |
454 | */ | |
455 | { | |
456 | /* HW will deduct 0.5 line from 2nd feild. | |
457 | * i.e. for 1080i, it is 2 lines for 1st field, | |
458 | * 2.5 lines for the 2nd feild. we need input as 5 | |
459 | * instead of 4. | |
460 | * but it is 4 either from Edid data (spec CEA 861) | |
461 | * or CEA timing table. | |
462 | */ | |
463 | params.v_syncoffset = | |
464 | cpu_to_le16(le16_to_cpu(params.v_syncoffset) + | |
465 | 1); | |
466 | ||
467 | } | |
468 | } | |
469 | ||
470 | if (bp_params->flags.HORZ_COUNT_BY_TWO) | |
471 | params.modemiscinfo = | |
472 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | | |
473 | 0x100); /* ATOM_DOUBLE_CLOCK_MODE */ | |
474 | ||
475 | if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params)) | |
476 | result = BP_RESULT_OK; | |
477 | ||
478 | return result; | |
479 | } | |
480 | ||
481 | /****************************************************************************** | |
482 | ****************************************************************************** | |
483 | ** | |
484 | ** SELECT CRTC SOURCE | |
485 | ** | |
486 | ****************************************************************************** | |
487 | *****************************************************************************/ | |
488 | ||
489 | ||
490 | static enum bp_result select_crtc_source_v3( | |
491 | struct bios_parser *bp, | |
492 | struct bp_crtc_source_select *bp_params); | |
493 | ||
494 | static void init_select_crtc_source(struct bios_parser *bp) | |
495 | { | |
496 | switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) { | |
497 | case 3: | |
498 | bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; | |
499 | break; | |
500 | default: | |
501 | bp->cmd_tbl.select_crtc_source = NULL; | |
502 | break; | |
503 | } | |
504 | } | |
505 | ||
506 | ||
507 | static enum bp_result select_crtc_source_v3( | |
508 | struct bios_parser *bp, | |
509 | struct bp_crtc_source_select *bp_params) | |
510 | { | |
511 | bool result = BP_RESULT_FAILURE; | |
512 | struct select_crtc_source_parameters_v2_3 params; | |
513 | uint8_t atom_controller_id; | |
514 | uint32_t atom_engine_id; | |
515 | enum signal_type s = bp_params->signal; | |
516 | ||
517 | memset(¶ms, 0, sizeof(params)); | |
518 | ||
519 | if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, | |
520 | &atom_controller_id)) | |
521 | params.crtc_id = atom_controller_id; | |
522 | else | |
523 | return result; | |
524 | ||
525 | if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, | |
526 | &atom_engine_id)) | |
527 | params.encoder_id = (uint8_t)atom_engine_id; | |
528 | else | |
529 | return result; | |
530 | ||
531 | if (s == SIGNAL_TYPE_EDP || | |
532 | (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal == | |
533 | SIGNAL_TYPE_LVDS)) | |
534 | s = SIGNAL_TYPE_LVDS; | |
535 | ||
536 | params.encode_mode = | |
537 | bp->cmd_helper->encoder_mode_bp_to_atom( | |
538 | s, bp_params->enable_dp_audio); | |
539 | /* Needed for VBIOS Random Spatial Dithering feature */ | |
540 | params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth); | |
541 | ||
542 | if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params)) | |
543 | result = BP_RESULT_OK; | |
544 | ||
545 | return result; | |
546 | } | |
547 | ||
548 | /****************************************************************************** | |
549 | ****************************************************************************** | |
550 | ** | |
551 | ** ENABLE CRTC | |
552 | ** | |
553 | ****************************************************************************** | |
554 | *****************************************************************************/ | |
555 | ||
556 | static enum bp_result enable_crtc_v1( | |
557 | struct bios_parser *bp, | |
558 | enum controller_id controller_id, | |
559 | bool enable); | |
560 | ||
561 | static void init_enable_crtc(struct bios_parser *bp) | |
562 | { | |
563 | switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) { | |
564 | case 1: | |
565 | bp->cmd_tbl.enable_crtc = enable_crtc_v1; | |
566 | break; | |
567 | default: | |
568 | bp->cmd_tbl.enable_crtc = NULL; | |
569 | break; | |
570 | } | |
571 | } | |
572 | ||
573 | static enum bp_result enable_crtc_v1( | |
574 | struct bios_parser *bp, | |
575 | enum controller_id controller_id, | |
576 | bool enable) | |
577 | { | |
578 | bool result = BP_RESULT_FAILURE; | |
579 | struct enable_crtc_parameters params = {0}; | |
580 | uint8_t id; | |
581 | ||
582 | if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) | |
583 | params.crtc_id = id; | |
584 | else | |
585 | return BP_RESULT_BADINPUT; | |
586 | ||
587 | if (enable) | |
588 | params.enable = ATOM_ENABLE; | |
589 | else | |
590 | params.enable = ATOM_DISABLE; | |
591 | ||
592 | if (EXEC_BIOS_CMD_TABLE(enablecrtc, params)) | |
593 | result = BP_RESULT_OK; | |
594 | ||
595 | return result; | |
596 | } | |
597 | ||
598 | /****************************************************************************** | |
599 | ****************************************************************************** | |
600 | ** | |
601 | ** DISPLAY PLL | |
602 | ** | |
603 | ****************************************************************************** | |
604 | *****************************************************************************/ | |
605 | ||
606 | ||
607 | ||
608 | /****************************************************************************** | |
609 | ****************************************************************************** | |
610 | ** | |
611 | ** EXTERNAL ENCODER CONTROL | |
612 | ** | |
613 | ****************************************************************************** | |
614 | *****************************************************************************/ | |
615 | ||
616 | static enum bp_result external_encoder_control_v3( | |
617 | struct bios_parser *bp, | |
618 | struct bp_external_encoder_control *cntl); | |
619 | ||
620 | static void init_external_encoder_control( | |
621 | struct bios_parser *bp) | |
622 | { | |
623 | switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) { | |
624 | case 3: | |
625 | bp->cmd_tbl.external_encoder_control = | |
626 | external_encoder_control_v3; | |
627 | break; | |
628 | default: | |
629 | bp->cmd_tbl.external_encoder_control = NULL; | |
630 | break; | |
631 | } | |
632 | } | |
633 | ||
634 | static enum bp_result external_encoder_control_v3( | |
635 | struct bios_parser *bp, | |
636 | struct bp_external_encoder_control *cntl) | |
637 | { | |
638 | /* TODO */ | |
639 | return BP_RESULT_OK; | |
640 | } | |
641 | ||
642 | /****************************************************************************** | |
643 | ****************************************************************************** | |
644 | ** | |
645 | ** ENABLE DISPLAY POWER GATING | |
646 | ** | |
647 | ****************************************************************************** | |
648 | *****************************************************************************/ | |
649 | ||
650 | static enum bp_result enable_disp_power_gating_v2_1( | |
651 | struct bios_parser *bp, | |
652 | enum controller_id crtc_id, | |
653 | enum bp_pipe_control_action action); | |
654 | ||
655 | static void init_enable_disp_power_gating( | |
656 | struct bios_parser *bp) | |
657 | { | |
658 | switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) { | |
659 | case 1: | |
660 | bp->cmd_tbl.enable_disp_power_gating = | |
661 | enable_disp_power_gating_v2_1; | |
662 | break; | |
663 | default: | |
664 | bp->cmd_tbl.enable_disp_power_gating = NULL; | |
665 | break; | |
666 | } | |
667 | } | |
668 | ||
669 | static enum bp_result enable_disp_power_gating_v2_1( | |
670 | struct bios_parser *bp, | |
671 | enum controller_id crtc_id, | |
672 | enum bp_pipe_control_action action) | |
673 | { | |
674 | enum bp_result result = BP_RESULT_FAILURE; | |
675 | ||
676 | ||
677 | struct enable_disp_power_gating_ps_allocation ps = { { 0 } }; | |
678 | uint8_t atom_crtc_id; | |
679 | ||
680 | if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) | |
681 | ps.param.disp_pipe_id = atom_crtc_id; | |
682 | else | |
683 | return BP_RESULT_BADINPUT; | |
684 | ||
685 | ps.param.enable = | |
686 | bp->cmd_helper->disp_power_gating_action_to_atom(action); | |
687 | ||
688 | if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param)) | |
689 | result = BP_RESULT_OK; | |
690 | ||
691 | return result; | |
692 | } | |
693 | ||
694 | /****************************************************************************** | |
695 | ******************************************************************************* | |
696 | ** | |
697 | ** SET DCE CLOCK | |
698 | ** | |
699 | ******************************************************************************* | |
700 | *******************************************************************************/ | |
701 | ||
702 | static enum bp_result set_dce_clock_v2_1( | |
703 | struct bios_parser *bp, | |
704 | struct bp_set_dce_clock_parameters *bp_params); | |
705 | ||
706 | static void init_set_dce_clock(struct bios_parser *bp) | |
707 | { | |
708 | switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) { | |
709 | case 1: | |
710 | bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; | |
711 | break; | |
712 | default: | |
713 | bp->cmd_tbl.set_dce_clock = NULL; | |
714 | break; | |
715 | } | |
716 | } | |
717 | ||
718 | static enum bp_result set_dce_clock_v2_1( | |
719 | struct bios_parser *bp, | |
720 | struct bp_set_dce_clock_parameters *bp_params) | |
721 | { | |
722 | enum bp_result result = BP_RESULT_FAILURE; | |
723 | ||
724 | struct set_dce_clock_ps_allocation_v2_1 params; | |
725 | uint32_t atom_pll_id; | |
726 | uint32_t atom_clock_type; | |
727 | const struct command_table_helper *cmd = bp->cmd_helper; | |
728 | ||
729 | memset(¶ms, 0, sizeof(params)); | |
730 | ||
731 | if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || | |
732 | !cmd->dc_clock_type_to_atom(bp_params->clock_type, | |
733 | &atom_clock_type)) | |
734 | return BP_RESULT_BADINPUT; | |
735 | ||
736 | params.param.dceclksrc = atom_pll_id; | |
737 | params.param.dceclktype = atom_clock_type; | |
738 | ||
739 | if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { | |
740 | if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) | |
741 | params.param.dceclkflag |= | |
742 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; | |
743 | ||
744 | if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) | |
745 | params.param.dceclkflag |= | |
746 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; | |
747 | ||
748 | if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) | |
749 | params.param.dceclkflag |= | |
750 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; | |
751 | ||
752 | if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) | |
753 | params.param.dceclkflag |= | |
754 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; | |
755 | } else | |
756 | /* only program clock frequency if display clock is used; | |
757 | * VBIOS will program DPREFCLK | |
758 | * We need to convert from KHz units into 10KHz units | |
759 | */ | |
760 | params.param.dceclk_10khz = cpu_to_le32( | |
761 | bp_params->target_clock_frequency / 10); | |
7fc6ff77 JL |
762 | dm_logger_write(bp->base.ctx->logger, LOG_BIOS, |
763 | "%s:target_clock_frequency = %d"\ | |
ae79c310 HW |
764 | "clock_type = %d \n", __func__,\ |
765 | bp_params->target_clock_frequency,\ | |
766 | bp_params->clock_type); | |
767 | ||
768 | if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) { | |
769 | /* Convert from 10KHz units back to KHz */ | |
770 | bp_params->target_clock_frequency = le32_to_cpu( | |
771 | params.param.dceclk_10khz) * 10; | |
772 | result = BP_RESULT_OK; | |
773 | } | |
774 | ||
775 | return result; | |
776 | } | |
777 | ||
778 | ||
779 | /****************************************************************************** | |
780 | ****************************************************************************** | |
781 | ** | |
782 | ** GET SMU CLOCK INFO | |
783 | ** | |
784 | ****************************************************************************** | |
785 | *****************************************************************************/ | |
786 | ||
787 | static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp); | |
788 | ||
789 | static void init_get_smu_clock_info(struct bios_parser *bp) | |
790 | { | |
791 | /* TODO add switch for table vrsion */ | |
792 | bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1; | |
793 | ||
794 | } | |
795 | ||
796 | static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp) | |
797 | { | |
798 | struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0}; | |
799 | struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output; | |
800 | ||
801 | smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ; | |
802 | ||
803 | /* Get Specific Clock */ | |
804 | if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) { | |
805 | memmove(&smu_output, &smu_input, sizeof( | |
806 | struct atom_get_smu_clock_info_parameters_v3_1)); | |
807 | return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz; | |
808 | } | |
809 | ||
810 | return 0; | |
811 | } | |
812 |