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 | |
30 | #include "atomfirmware.h" |
31 | #include "atom.h" |
32 | #include "include/bios_parser_interface.h" |
33 | |
34 | #include "command_table2.h" |
35 | #include "command_table_helper2.h" |
36 | #include "bios_parser_helper.h" |
37 | #include "bios_parser_types_internal2.h" |
38 | #include "amdgpu.h" |
39 | |
40 | #include "dc_dmub_srv.h" |
41 | #include "dc.h" |
42 | |
43 | #define DC_LOGGER \ |
44 | bp->base.ctx->logger |
45 | |
46 | #define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\ |
47 | (offsetof(struct atom_master_list_of_##MasterOrData##_functions_v2_1, FieldName) / sizeof(uint16_t)) |
48 | |
49 | #define EXEC_BIOS_CMD_TABLE(fname, params)\ |
50 | (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \ |
51 | GET_INDEX_INTO_MASTER_TABLE(command, fname), \ |
52 | (uint32_t *)¶ms, sizeof(params)) == 0) |
53 | |
54 | #define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\ |
55 | amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \ |
56 | GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev) |
57 | |
58 | #define BIOS_CMD_TABLE_PARA_REVISION(fname)\ |
59 | bios_cmd_table_para_revision(bp->base.ctx->driver_context, \ |
60 | GET_INDEX_INTO_MASTER_TABLE(command, fname)) |
61 | |
62 | |
63 | |
64 | static uint32_t bios_cmd_table_para_revision(void *dev, |
65 | uint32_t index) |
66 | { |
67 | struct amdgpu_device *adev = dev; |
68 | uint8_t frev, crev; |
69 | |
70 | if (amdgpu_atom_parse_cmd_header(ctx: adev->mode_info.atom_context, |
71 | index, |
72 | frev: &frev, crev: &crev)) |
73 | return crev; |
74 | else |
75 | return 0; |
76 | } |
77 | |
78 | /****************************************************************************** |
79 | ****************************************************************************** |
80 | ** |
81 | ** D I G E N C O D E R C O N T R O L |
82 | ** |
83 | ****************************************************************************** |
84 | *****************************************************************************/ |
85 | |
86 | static enum bp_result encoder_control_digx_v1_5( |
87 | struct bios_parser *bp, |
88 | struct bp_encoder_control *cntl); |
89 | |
90 | static enum bp_result encoder_control_fallback( |
91 | struct bios_parser *bp, |
92 | struct bp_encoder_control *cntl); |
93 | |
94 | static void init_dig_encoder_control(struct bios_parser *bp) |
95 | { |
96 | uint32_t version = |
97 | BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol); |
98 | |
99 | switch (version) { |
100 | case 5: |
101 | bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; |
102 | break; |
103 | default: |
104 | dm_output_to_console("Don't have dig_encoder_control for v%d\n" , version); |
105 | bp->cmd_tbl.dig_encoder_control = encoder_control_fallback; |
106 | break; |
107 | } |
108 | } |
109 | |
110 | static void encoder_control_dmcub( |
111 | struct dc_dmub_srv *dmcub, |
112 | struct dig_encoder_stream_setup_parameters_v1_5 *dig) |
113 | { |
114 | union dmub_rb_cmd cmd; |
115 | |
116 | memset(&cmd, 0, sizeof(cmd)); |
117 | |
118 | cmd.digx_encoder_control.header.type = DMUB_CMD__VBIOS; |
119 | cmd.digx_encoder_control.header.sub_type = |
120 | DMUB_CMD__VBIOS_DIGX_ENCODER_CONTROL; |
121 | cmd.digx_encoder_control.header.payload_bytes = |
122 | sizeof(cmd.digx_encoder_control) - |
123 | sizeof(cmd.digx_encoder_control.header); |
124 | cmd.digx_encoder_control.encoder_control.dig.stream_param = *dig; |
125 | |
126 | dc_wake_and_execute_dmub_cmd(ctx: dmcub->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT); |
127 | } |
128 | |
129 | static enum bp_result encoder_control_digx_v1_5( |
130 | struct bios_parser *bp, |
131 | struct bp_encoder_control *cntl) |
132 | { |
133 | enum bp_result result = BP_RESULT_FAILURE; |
134 | struct dig_encoder_stream_setup_parameters_v1_5 params = {0}; |
135 | |
136 | params.digid = (uint8_t)(cntl->engine_id); |
137 | params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action); |
138 | |
139 | params.pclk_10khz = cntl->pixel_clock / 10; |
140 | params.digmode = |
141 | (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( |
142 | cntl->signal, |
143 | cntl->enable_dp_audio)); |
144 | params.lanenum = (uint8_t)(cntl->lanes_number); |
145 | |
146 | switch (cntl->color_depth) { |
147 | case COLOR_DEPTH_888: |
148 | params.bitpercolor = PANEL_8BIT_PER_COLOR; |
149 | break; |
150 | case COLOR_DEPTH_101010: |
151 | params.bitpercolor = PANEL_10BIT_PER_COLOR; |
152 | break; |
153 | case COLOR_DEPTH_121212: |
154 | params.bitpercolor = PANEL_12BIT_PER_COLOR; |
155 | break; |
156 | case COLOR_DEPTH_161616: |
157 | params.bitpercolor = PANEL_16BIT_PER_COLOR; |
158 | break; |
159 | default: |
160 | break; |
161 | } |
162 | |
163 | if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) |
164 | switch (cntl->color_depth) { |
165 | case COLOR_DEPTH_101010: |
166 | params.pclk_10khz = |
167 | (params.pclk_10khz * 30) / 24; |
168 | break; |
169 | case COLOR_DEPTH_121212: |
170 | params.pclk_10khz = |
171 | (params.pclk_10khz * 36) / 24; |
172 | break; |
173 | case COLOR_DEPTH_161616: |
174 | params.pclk_10khz = |
175 | (params.pclk_10khz * 48) / 24; |
176 | break; |
177 | default: |
178 | break; |
179 | } |
180 | |
181 | if (bp->base.ctx->dc->ctx->dmub_srv && |
182 | bp->base.ctx->dc->debug.dmub_command_table) { |
183 | encoder_control_dmcub(dmcub: bp->base.ctx->dmub_srv, dig: ¶ms); |
184 | return BP_RESULT_OK; |
185 | } |
186 | |
187 | if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params)) |
188 | result = BP_RESULT_OK; |
189 | |
190 | return result; |
191 | } |
192 | |
193 | static enum bp_result encoder_control_fallback( |
194 | struct bios_parser *bp, |
195 | struct bp_encoder_control *cntl) |
196 | { |
197 | if (bp->base.ctx->dc->ctx->dmub_srv && |
198 | bp->base.ctx->dc->debug.dmub_command_table) { |
199 | return encoder_control_digx_v1_5(bp, cntl); |
200 | } |
201 | |
202 | return BP_RESULT_FAILURE; |
203 | } |
204 | |
205 | /***************************************************************************** |
206 | ****************************************************************************** |
207 | ** |
208 | ** TRANSMITTER CONTROL |
209 | ** |
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 | static enum bp_result transmitter_control_v1_7( |
218 | struct bios_parser *bp, |
219 | struct bp_transmitter_control *cntl); |
220 | |
221 | static enum bp_result transmitter_control_fallback( |
222 | struct bios_parser *bp, |
223 | struct bp_transmitter_control *cntl); |
224 | |
225 | static void init_transmitter_control(struct bios_parser *bp) |
226 | { |
227 | uint8_t frev; |
228 | uint8_t crev; |
229 | |
230 | BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev); |
231 | |
232 | switch (crev) { |
233 | case 6: |
234 | bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; |
235 | break; |
236 | case 7: |
237 | bp->cmd_tbl.transmitter_control = transmitter_control_v1_7; |
238 | break; |
239 | default: |
240 | dm_output_to_console("Don't have transmitter_control for v%d\n" , crev); |
241 | bp->cmd_tbl.transmitter_control = transmitter_control_fallback; |
242 | break; |
243 | } |
244 | } |
245 | |
246 | static void transmitter_control_dmcub( |
247 | struct dc_dmub_srv *dmcub, |
248 | struct dig_transmitter_control_parameters_v1_6 *dig) |
249 | { |
250 | union dmub_rb_cmd cmd; |
251 | |
252 | memset(&cmd, 0, sizeof(cmd)); |
253 | |
254 | cmd.dig1_transmitter_control.header.type = DMUB_CMD__VBIOS; |
255 | cmd.dig1_transmitter_control.header.sub_type = |
256 | DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL; |
257 | cmd.dig1_transmitter_control.header.payload_bytes = |
258 | sizeof(cmd.dig1_transmitter_control) - |
259 | sizeof(cmd.dig1_transmitter_control.header); |
260 | cmd.dig1_transmitter_control.transmitter_control.dig = *dig; |
261 | |
262 | dc_wake_and_execute_dmub_cmd(ctx: dmcub->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT); |
263 | } |
264 | |
265 | static enum bp_result transmitter_control_v1_6( |
266 | struct bios_parser *bp, |
267 | struct bp_transmitter_control *cntl) |
268 | { |
269 | enum bp_result result = BP_RESULT_FAILURE; |
270 | const struct command_table_helper *cmd = bp->cmd_helper; |
271 | struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } }; |
272 | |
273 | ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter); |
274 | ps.param.action = (uint8_t)cntl->action; |
275 | |
276 | if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) |
277 | ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; |
278 | else |
279 | ps.param.mode_laneset.digmode = |
280 | cmd->signal_type_to_atom_dig_mode(cntl->signal); |
281 | |
282 | ps.param.lanenum = (uint8_t)cntl->lanes_number; |
283 | ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); |
284 | ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); |
285 | ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id; |
286 | ps.param.symclk_10khz = cntl->pixel_clock/10; |
287 | |
288 | |
289 | if (cntl->action == TRANSMITTER_CONTROL_ENABLE || |
290 | cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || |
291 | cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { |
292 | DC_LOG_BIOS("%s:ps.param.symclk_10khz = %d\n" ,\ |
293 | __func__, ps.param.symclk_10khz); |
294 | } |
295 | |
296 | if (bp->base.ctx->dc->ctx->dmub_srv && |
297 | bp->base.ctx->dc->debug.dmub_command_table) { |
298 | transmitter_control_dmcub(dmcub: bp->base.ctx->dmub_srv, dig: &ps.param); |
299 | return BP_RESULT_OK; |
300 | } |
301 | |
302 | /*color_depth not used any more, driver has deep color factor in the Phyclk*/ |
303 | if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps)) |
304 | result = BP_RESULT_OK; |
305 | return result; |
306 | } |
307 | |
308 | static void transmitter_control_dmcub_v1_7( |
309 | struct dc_dmub_srv *dmcub, |
310 | struct dmub_dig_transmitter_control_data_v1_7 *dig) |
311 | { |
312 | union dmub_rb_cmd cmd; |
313 | |
314 | memset(&cmd, 0, sizeof(cmd)); |
315 | |
316 | cmd.dig1_transmitter_control.header.type = DMUB_CMD__VBIOS; |
317 | cmd.dig1_transmitter_control.header.sub_type = |
318 | DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL; |
319 | cmd.dig1_transmitter_control.header.payload_bytes = |
320 | sizeof(cmd.dig1_transmitter_control) - |
321 | sizeof(cmd.dig1_transmitter_control.header); |
322 | cmd.dig1_transmitter_control.transmitter_control.dig_v1_7 = *dig; |
323 | |
324 | dc_wake_and_execute_dmub_cmd(ctx: dmcub->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT); |
325 | } |
326 | |
327 | static enum bp_result transmitter_control_v1_7( |
328 | struct bios_parser *bp, |
329 | struct bp_transmitter_control *cntl) |
330 | { |
331 | enum bp_result result = BP_RESULT_FAILURE; |
332 | const struct command_table_helper *cmd = bp->cmd_helper; |
333 | struct dmub_dig_transmitter_control_data_v1_7 dig_v1_7 = {0}; |
334 | |
335 | uint8_t hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_0; |
336 | |
337 | if (dc_is_dp_signal(signal: cntl->signal)) |
338 | hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_DP_0; |
339 | |
340 | dig_v1_7.phyid = cmd->phy_id_to_atom(cntl->transmitter); |
341 | dig_v1_7.action = (uint8_t)cntl->action; |
342 | |
343 | if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) |
344 | dig_v1_7.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; |
345 | else |
346 | dig_v1_7.mode_laneset.digmode = |
347 | cmd->signal_type_to_atom_dig_mode(cntl->signal); |
348 | |
349 | dig_v1_7.lanenum = (uint8_t)cntl->lanes_number; |
350 | dig_v1_7.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); |
351 | dig_v1_7.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); |
352 | dig_v1_7.connobj_id = (uint8_t)cntl->connector_obj_id.id; |
353 | dig_v1_7.HPO_instance = hpo_instance; |
354 | dig_v1_7.symclk_units.symclk_10khz = cntl->pixel_clock/10; |
355 | |
356 | if (cntl->action == TRANSMITTER_CONTROL_ENABLE || |
357 | cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || |
358 | cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { |
359 | DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_10khz = %d\n" , |
360 | __func__, dig_v1_7.symclk_units.symclk_10khz); |
361 | } |
362 | |
363 | if (bp->base.ctx->dc->ctx->dmub_srv && |
364 | bp->base.ctx->dc->debug.dmub_command_table) { |
365 | transmitter_control_dmcub_v1_7(dmcub: bp->base.ctx->dmub_srv, dig: &dig_v1_7); |
366 | return BP_RESULT_OK; |
367 | } |
368 | |
369 | /*color_depth not used any more, driver has deep color factor in the Phyclk*/ |
370 | if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, dig_v1_7)) |
371 | result = BP_RESULT_OK; |
372 | return result; |
373 | } |
374 | |
375 | static enum bp_result transmitter_control_fallback( |
376 | struct bios_parser *bp, |
377 | struct bp_transmitter_control *cntl) |
378 | { |
379 | if (bp->base.ctx->dc->ctx->dmub_srv && |
380 | bp->base.ctx->dc->debug.dmub_command_table) { |
381 | return transmitter_control_v1_7(bp, cntl); |
382 | } |
383 | |
384 | return BP_RESULT_FAILURE; |
385 | } |
386 | |
387 | /****************************************************************************** |
388 | ****************************************************************************** |
389 | ** |
390 | ** SET PIXEL CLOCK |
391 | ** |
392 | ****************************************************************************** |
393 | *****************************************************************************/ |
394 | |
395 | static enum bp_result set_pixel_clock_v7( |
396 | struct bios_parser *bp, |
397 | struct bp_pixel_clock_parameters *bp_params); |
398 | |
399 | static enum bp_result set_pixel_clock_fallback( |
400 | struct bios_parser *bp, |
401 | struct bp_pixel_clock_parameters *bp_params); |
402 | |
403 | static void init_set_pixel_clock(struct bios_parser *bp) |
404 | { |
405 | switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) { |
406 | case 7: |
407 | bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; |
408 | break; |
409 | default: |
410 | dm_output_to_console("Don't have set_pixel_clock for v%d\n" , |
411 | BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); |
412 | bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback; |
413 | break; |
414 | } |
415 | } |
416 | |
417 | static void set_pixel_clock_dmcub( |
418 | struct dc_dmub_srv *dmcub, |
419 | struct set_pixel_clock_parameter_v1_7 *clk) |
420 | { |
421 | union dmub_rb_cmd cmd; |
422 | |
423 | memset(&cmd, 0, sizeof(cmd)); |
424 | |
425 | cmd.set_pixel_clock.header.type = DMUB_CMD__VBIOS; |
426 | cmd.set_pixel_clock.header.sub_type = DMUB_CMD__VBIOS_SET_PIXEL_CLOCK; |
427 | cmd.set_pixel_clock.header.payload_bytes = |
428 | sizeof(cmd.set_pixel_clock) - |
429 | sizeof(cmd.set_pixel_clock.header); |
430 | cmd.set_pixel_clock.pixel_clock.clk = *clk; |
431 | |
432 | dc_wake_and_execute_dmub_cmd(ctx: dmcub->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT); |
433 | } |
434 | |
435 | static enum bp_result set_pixel_clock_v7( |
436 | struct bios_parser *bp, |
437 | struct bp_pixel_clock_parameters *bp_params) |
438 | { |
439 | enum bp_result result = BP_RESULT_FAILURE; |
440 | struct set_pixel_clock_parameter_v1_7 clk; |
441 | uint8_t controller_id; |
442 | uint32_t pll_id; |
443 | |
444 | memset(&clk, 0, sizeof(clk)); |
445 | |
446 | if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) |
447 | && bp->cmd_helper->controller_id_to_atom(bp_params-> |
448 | controller_id, &controller_id)) { |
449 | /* Note: VBIOS still wants to use ucCRTC name which is now |
450 | * 1 byte in ULONG |
451 | *typedef struct _CRTC_PIXEL_CLOCK_FREQ |
452 | *{ |
453 | * target the pixel clock to drive the CRTC timing. |
454 | * ULONG ulPixelClock:24; |
455 | * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to |
456 | * previous version. |
457 | * ATOM_CRTC1~6, indicate the CRTC controller to |
458 | * ULONG ucCRTC:8; |
459 | * drive the pixel clock. not used for DCPLL case. |
460 | *}CRTC_PIXEL_CLOCK_FREQ; |
461 | *union |
462 | *{ |
463 | * pixel clock and CRTC id frequency |
464 | * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; |
465 | * ULONG ulDispEngClkFreq; dispclk frequency |
466 | *}; |
467 | */ |
468 | clk.crtc_id = controller_id; |
469 | clk.pll_id = (uint8_t) pll_id; |
470 | clk.encoderobjid = |
471 | bp->cmd_helper->encoder_id_to_atom( |
472 | dal_graphics_object_id_get_encoder_id( |
473 | id: bp_params->encoder_object_id)); |
474 | |
475 | clk.encoder_mode = (uint8_t) bp-> |
476 | cmd_helper->encoder_mode_bp_to_atom( |
477 | bp_params->signal_type, false); |
478 | |
479 | clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock_100hz); |
480 | |
481 | clk.deep_color_ratio = |
482 | (uint8_t) bp->cmd_helper-> |
483 | transmitter_color_depth_to_atom( |
484 | bp_params->color_depth); |
485 | |
486 | DC_LOG_BIOS("%s:program display clock = %d, tg = %d, pll = %d, " \ |
487 | "colorDepth = %d\n" , __func__, |
488 | bp_params->target_pixel_clock_100hz, (int)controller_id, |
489 | pll_id, bp_params->color_depth); |
490 | |
491 | if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) |
492 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; |
493 | |
494 | if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) |
495 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; |
496 | |
497 | if (bp_params->flags.SUPPORT_YUV_420) |
498 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; |
499 | |
500 | if (bp_params->flags.SET_XTALIN_REF_SRC) |
501 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; |
502 | |
503 | if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) |
504 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; |
505 | |
506 | if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) |
507 | clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; |
508 | |
509 | if (bp->base.ctx->dc->ctx->dmub_srv && |
510 | bp->base.ctx->dc->debug.dmub_command_table) { |
511 | set_pixel_clock_dmcub(dmcub: bp->base.ctx->dmub_srv, clk: &clk); |
512 | return BP_RESULT_OK; |
513 | } |
514 | |
515 | if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk)) |
516 | result = BP_RESULT_OK; |
517 | } |
518 | return result; |
519 | } |
520 | |
521 | static enum bp_result set_pixel_clock_fallback( |
522 | struct bios_parser *bp, |
523 | struct bp_pixel_clock_parameters *bp_params) |
524 | { |
525 | if (bp->base.ctx->dc->ctx->dmub_srv && |
526 | bp->base.ctx->dc->debug.dmub_command_table) { |
527 | return set_pixel_clock_v7(bp, bp_params); |
528 | } |
529 | |
530 | return BP_RESULT_FAILURE; |
531 | } |
532 | |
533 | /****************************************************************************** |
534 | ****************************************************************************** |
535 | ** |
536 | ** SET CRTC TIMING |
537 | ** |
538 | ****************************************************************************** |
539 | *****************************************************************************/ |
540 | |
541 | static enum bp_result set_crtc_using_dtd_timing_v3( |
542 | struct bios_parser *bp, |
543 | struct bp_hw_crtc_timing_parameters *bp_params); |
544 | |
545 | static void init_set_crtc_timing(struct bios_parser *bp) |
546 | { |
547 | uint32_t dtd_version = |
548 | BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); |
549 | |
550 | switch (dtd_version) { |
551 | case 3: |
552 | bp->cmd_tbl.set_crtc_timing = |
553 | set_crtc_using_dtd_timing_v3; |
554 | break; |
555 | default: |
556 | dm_output_to_console("Don't have set_crtc_timing for v%d\n" , dtd_version); |
557 | bp->cmd_tbl.set_crtc_timing = NULL; |
558 | break; |
559 | } |
560 | } |
561 | |
562 | static enum bp_result set_crtc_using_dtd_timing_v3( |
563 | struct bios_parser *bp, |
564 | struct bp_hw_crtc_timing_parameters *bp_params) |
565 | { |
566 | enum bp_result result = BP_RESULT_FAILURE; |
567 | struct set_crtc_using_dtd_timing_parameters params = {0}; |
568 | uint8_t atom_controller_id; |
569 | |
570 | if (bp->cmd_helper->controller_id_to_atom( |
571 | bp_params->controller_id, &atom_controller_id)) |
572 | params.crtc_id = atom_controller_id; |
573 | |
574 | /* bios usH_Size wants h addressable size */ |
575 | params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable); |
576 | /* bios usH_Blanking_Time wants borders included in blanking */ |
577 | params.h_blanking_time = |
578 | cpu_to_le16((uint16_t)(bp_params->h_total - |
579 | bp_params->h_addressable)); |
580 | /* bios usV_Size wants v addressable size */ |
581 | params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable); |
582 | /* bios usV_Blanking_Time wants borders included in blanking */ |
583 | params.v_blanking_time = |
584 | cpu_to_le16((uint16_t)(bp_params->v_total - |
585 | bp_params->v_addressable)); |
586 | /* bios usHSyncOffset is the offset from the end of h addressable, |
587 | * our horizontalSyncStart is the offset from the beginning |
588 | * of h addressable |
589 | */ |
590 | params.h_syncoffset = |
591 | cpu_to_le16((uint16_t)(bp_params->h_sync_start - |
592 | bp_params->h_addressable)); |
593 | params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); |
594 | /* bios usHSyncOffset is the offset from the end of v addressable, |
595 | * our verticalSyncStart is the offset from the beginning of |
596 | * v addressable |
597 | */ |
598 | params.v_syncoffset = |
599 | cpu_to_le16((uint16_t)(bp_params->v_sync_start - |
600 | bp_params->v_addressable)); |
601 | params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); |
602 | |
603 | /* we assume that overscan from original timing does not get bigger |
604 | * than 255 |
605 | * we will program all the borders in the Set CRTC Overscan call below |
606 | */ |
607 | |
608 | if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0) |
609 | params.modemiscinfo = |
610 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | |
611 | ATOM_HSYNC_POLARITY); |
612 | |
613 | if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0) |
614 | params.modemiscinfo = |
615 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | |
616 | ATOM_VSYNC_POLARITY); |
617 | |
618 | if (bp_params->flags.INTERLACE) { |
619 | params.modemiscinfo = |
620 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | |
621 | ATOM_INTERLACE); |
622 | |
623 | /* original DAL code has this condition to apply this |
624 | * for non-TV/CV only |
625 | * due to complex MV testing for possible impact |
626 | * if ( pACParameters->signal != SignalType_YPbPr && |
627 | * pACParameters->signal != SignalType_Composite && |
628 | * pACParameters->signal != SignalType_SVideo) |
629 | */ |
630 | { |
631 | /* HW will deduct 0.5 line from 2nd feild. |
632 | * i.e. for 1080i, it is 2 lines for 1st field, |
633 | * 2.5 lines for the 2nd feild. we need input as 5 |
634 | * instead of 4. |
635 | * but it is 4 either from Edid data (spec CEA 861) |
636 | * or CEA timing table. |
637 | */ |
638 | le16_add_cpu(var: ¶ms.v_syncoffset, val: 1); |
639 | } |
640 | } |
641 | |
642 | if (bp_params->flags.HORZ_COUNT_BY_TWO) |
643 | params.modemiscinfo = |
644 | cpu_to_le16(le16_to_cpu(params.modemiscinfo) | |
645 | 0x100); /* ATOM_DOUBLE_CLOCK_MODE */ |
646 | |
647 | if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params)) |
648 | result = BP_RESULT_OK; |
649 | |
650 | return result; |
651 | } |
652 | |
653 | /****************************************************************************** |
654 | ****************************************************************************** |
655 | ** |
656 | ** ENABLE CRTC |
657 | ** |
658 | ****************************************************************************** |
659 | *****************************************************************************/ |
660 | |
661 | static enum bp_result enable_crtc_v1( |
662 | struct bios_parser *bp, |
663 | enum controller_id controller_id, |
664 | bool enable); |
665 | |
666 | static void init_enable_crtc(struct bios_parser *bp) |
667 | { |
668 | switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) { |
669 | case 1: |
670 | bp->cmd_tbl.enable_crtc = enable_crtc_v1; |
671 | break; |
672 | default: |
673 | dm_output_to_console("Don't have enable_crtc for v%d\n" , |
674 | BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); |
675 | bp->cmd_tbl.enable_crtc = NULL; |
676 | break; |
677 | } |
678 | } |
679 | |
680 | static enum bp_result enable_crtc_v1( |
681 | struct bios_parser *bp, |
682 | enum controller_id controller_id, |
683 | bool enable) |
684 | { |
685 | bool result = BP_RESULT_FAILURE; |
686 | struct enable_crtc_parameters params = {0}; |
687 | uint8_t id; |
688 | |
689 | if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) |
690 | params.crtc_id = id; |
691 | else |
692 | return BP_RESULT_BADINPUT; |
693 | |
694 | if (enable) |
695 | params.enable = ATOM_ENABLE; |
696 | else |
697 | params.enable = ATOM_DISABLE; |
698 | |
699 | if (EXEC_BIOS_CMD_TABLE(enablecrtc, params)) |
700 | result = BP_RESULT_OK; |
701 | |
702 | return result; |
703 | } |
704 | |
705 | /****************************************************************************** |
706 | ****************************************************************************** |
707 | ** |
708 | ** DISPLAY PLL |
709 | ** |
710 | ****************************************************************************** |
711 | *****************************************************************************/ |
712 | |
713 | |
714 | |
715 | /****************************************************************************** |
716 | ****************************************************************************** |
717 | ** |
718 | ** EXTERNAL ENCODER CONTROL |
719 | ** |
720 | ****************************************************************************** |
721 | *****************************************************************************/ |
722 | |
723 | static enum bp_result external_encoder_control_v3( |
724 | struct bios_parser *bp, |
725 | struct bp_external_encoder_control *cntl); |
726 | |
727 | static void init_external_encoder_control( |
728 | struct bios_parser *bp) |
729 | { |
730 | switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) { |
731 | case 3: |
732 | bp->cmd_tbl.external_encoder_control = |
733 | external_encoder_control_v3; |
734 | break; |
735 | default: |
736 | bp->cmd_tbl.external_encoder_control = NULL; |
737 | break; |
738 | } |
739 | } |
740 | |
741 | static enum bp_result external_encoder_control_v3( |
742 | struct bios_parser *bp, |
743 | struct bp_external_encoder_control *cntl) |
744 | { |
745 | /* TODO */ |
746 | return BP_RESULT_OK; |
747 | } |
748 | |
749 | /****************************************************************************** |
750 | ****************************************************************************** |
751 | ** |
752 | ** ENABLE DISPLAY POWER GATING |
753 | ** |
754 | ****************************************************************************** |
755 | *****************************************************************************/ |
756 | |
757 | static enum bp_result enable_disp_power_gating_v2_1( |
758 | struct bios_parser *bp, |
759 | enum controller_id crtc_id, |
760 | enum bp_pipe_control_action action); |
761 | |
762 | static enum bp_result enable_disp_power_gating_fallback( |
763 | struct bios_parser *bp, |
764 | enum controller_id crtc_id, |
765 | enum bp_pipe_control_action action); |
766 | |
767 | static void init_enable_disp_power_gating( |
768 | struct bios_parser *bp) |
769 | { |
770 | switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) { |
771 | case 1: |
772 | bp->cmd_tbl.enable_disp_power_gating = |
773 | enable_disp_power_gating_v2_1; |
774 | break; |
775 | default: |
776 | dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n" , |
777 | BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)); |
778 | bp->cmd_tbl.enable_disp_power_gating = enable_disp_power_gating_fallback; |
779 | break; |
780 | } |
781 | } |
782 | |
783 | static void enable_disp_power_gating_dmcub( |
784 | struct dc_dmub_srv *dmcub, |
785 | struct enable_disp_power_gating_parameters_v2_1 *pwr) |
786 | { |
787 | union dmub_rb_cmd cmd; |
788 | |
789 | memset(&cmd, 0, sizeof(cmd)); |
790 | |
791 | cmd.enable_disp_power_gating.header.type = DMUB_CMD__VBIOS; |
792 | cmd.enable_disp_power_gating.header.sub_type = |
793 | DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING; |
794 | cmd.enable_disp_power_gating.header.payload_bytes = |
795 | sizeof(cmd.enable_disp_power_gating) - |
796 | sizeof(cmd.enable_disp_power_gating.header); |
797 | cmd.enable_disp_power_gating.power_gating.pwr = *pwr; |
798 | |
799 | dc_wake_and_execute_dmub_cmd(ctx: dmcub->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT); |
800 | } |
801 | |
802 | static enum bp_result enable_disp_power_gating_v2_1( |
803 | struct bios_parser *bp, |
804 | enum controller_id crtc_id, |
805 | enum bp_pipe_control_action action) |
806 | { |
807 | enum bp_result result = BP_RESULT_FAILURE; |
808 | |
809 | |
810 | struct enable_disp_power_gating_ps_allocation ps = { { 0 } }; |
811 | uint8_t atom_crtc_id; |
812 | |
813 | if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) |
814 | ps.param.disp_pipe_id = atom_crtc_id; |
815 | else |
816 | return BP_RESULT_BADINPUT; |
817 | |
818 | ps.param.enable = |
819 | bp->cmd_helper->disp_power_gating_action_to_atom(action); |
820 | |
821 | if (bp->base.ctx->dc->ctx->dmub_srv && |
822 | bp->base.ctx->dc->debug.dmub_command_table) { |
823 | enable_disp_power_gating_dmcub(dmcub: bp->base.ctx->dmub_srv, |
824 | pwr: &ps.param); |
825 | return BP_RESULT_OK; |
826 | } |
827 | |
828 | if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param)) |
829 | result = BP_RESULT_OK; |
830 | |
831 | return result; |
832 | } |
833 | |
834 | static enum bp_result enable_disp_power_gating_fallback( |
835 | struct bios_parser *bp, |
836 | enum controller_id crtc_id, |
837 | enum bp_pipe_control_action action) |
838 | { |
839 | if (bp->base.ctx->dc->ctx->dmub_srv && |
840 | bp->base.ctx->dc->debug.dmub_command_table) { |
841 | return enable_disp_power_gating_v2_1(bp, crtc_id, action); |
842 | } |
843 | |
844 | return BP_RESULT_FAILURE; |
845 | } |
846 | |
847 | /****************************************************************************** |
848 | ******************************************************************************* |
849 | ** |
850 | ** SET DCE CLOCK |
851 | ** |
852 | ******************************************************************************* |
853 | *******************************************************************************/ |
854 | |
855 | static enum bp_result set_dce_clock_v2_1( |
856 | struct bios_parser *bp, |
857 | struct bp_set_dce_clock_parameters *bp_params); |
858 | |
859 | static void init_set_dce_clock(struct bios_parser *bp) |
860 | { |
861 | switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) { |
862 | case 1: |
863 | bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; |
864 | break; |
865 | default: |
866 | dm_output_to_console("Don't have set_dce_clock for v%d\n" , |
867 | BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); |
868 | bp->cmd_tbl.set_dce_clock = NULL; |
869 | break; |
870 | } |
871 | } |
872 | |
873 | static enum bp_result set_dce_clock_v2_1( |
874 | struct bios_parser *bp, |
875 | struct bp_set_dce_clock_parameters *bp_params) |
876 | { |
877 | enum bp_result result = BP_RESULT_FAILURE; |
878 | |
879 | struct set_dce_clock_ps_allocation_v2_1 params; |
880 | uint32_t atom_pll_id; |
881 | uint32_t atom_clock_type; |
882 | const struct command_table_helper *cmd = bp->cmd_helper; |
883 | |
884 | memset(¶ms, 0, sizeof(params)); |
885 | |
886 | if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || |
887 | !cmd->dc_clock_type_to_atom(bp_params->clock_type, |
888 | &atom_clock_type)) |
889 | return BP_RESULT_BADINPUT; |
890 | |
891 | params.param.dceclksrc = atom_pll_id; |
892 | params.param.dceclktype = atom_clock_type; |
893 | |
894 | if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { |
895 | if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) |
896 | params.param.dceclkflag |= |
897 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; |
898 | |
899 | if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) |
900 | params.param.dceclkflag |= |
901 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; |
902 | |
903 | if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) |
904 | params.param.dceclkflag |= |
905 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; |
906 | |
907 | if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) |
908 | params.param.dceclkflag |= |
909 | DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; |
910 | } else |
911 | /* only program clock frequency if display clock is used; |
912 | * VBIOS will program DPREFCLK |
913 | * We need to convert from KHz units into 10KHz units |
914 | */ |
915 | params.param.dceclk_10khz = cpu_to_le32( |
916 | bp_params->target_clock_frequency / 10); |
917 | DC_LOG_BIOS("%s:target_clock_frequency = %d" \ |
918 | "clock_type = %d \n" , __func__,\ |
919 | bp_params->target_clock_frequency,\ |
920 | bp_params->clock_type); |
921 | |
922 | if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) { |
923 | /* Convert from 10KHz units back to KHz */ |
924 | bp_params->target_clock_frequency = le32_to_cpu( |
925 | params.param.dceclk_10khz) * 10; |
926 | result = BP_RESULT_OK; |
927 | } |
928 | |
929 | return result; |
930 | } |
931 | |
932 | |
933 | /****************************************************************************** |
934 | ****************************************************************************** |
935 | ** |
936 | ** GET SMU CLOCK INFO |
937 | ** |
938 | ****************************************************************************** |
939 | *****************************************************************************/ |
940 | |
941 | static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id); |
942 | |
943 | static void init_get_smu_clock_info(struct bios_parser *bp) |
944 | { |
945 | /* TODO add switch for table vrsion */ |
946 | bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1; |
947 | |
948 | } |
949 | |
950 | static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id) |
951 | { |
952 | struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0}; |
953 | struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output; |
954 | |
955 | smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ; |
956 | smu_input.syspll_id = id; |
957 | |
958 | /* Get Specific Clock */ |
959 | if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) { |
960 | memmove(&smu_output, &smu_input, sizeof( |
961 | struct atom_get_smu_clock_info_parameters_v3_1)); |
962 | return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz; |
963 | } |
964 | |
965 | return 0; |
966 | } |
967 | |
968 | /****************************************************************************** |
969 | ****************************************************************************** |
970 | ** |
971 | ** LVTMA CONTROL |
972 | ** |
973 | ****************************************************************************** |
974 | *****************************************************************************/ |
975 | |
976 | static enum bp_result enable_lvtma_control( |
977 | struct bios_parser *bp, |
978 | uint8_t uc_pwr_on, |
979 | uint8_t pwrseq_instance, |
980 | uint8_t bypass_panel_control_wait); |
981 | |
982 | static void init_enable_lvtma_control(struct bios_parser *bp) |
983 | { |
984 | /* TODO add switch for table vrsion */ |
985 | bp->cmd_tbl.enable_lvtma_control = enable_lvtma_control; |
986 | |
987 | } |
988 | |
989 | static void enable_lvtma_control_dmcub( |
990 | struct dc_dmub_srv *dmcub, |
991 | uint8_t uc_pwr_on, |
992 | uint8_t pwrseq_instance, |
993 | uint8_t bypass_panel_control_wait) |
994 | { |
995 | |
996 | union dmub_rb_cmd cmd; |
997 | |
998 | memset(&cmd, 0, sizeof(cmd)); |
999 | |
1000 | cmd.lvtma_control.header.type = DMUB_CMD__VBIOS; |
1001 | cmd.lvtma_control.header.sub_type = |
1002 | DMUB_CMD__VBIOS_LVTMA_CONTROL; |
1003 | cmd.lvtma_control.data.uc_pwr_action = |
1004 | uc_pwr_on; |
1005 | cmd.lvtma_control.data.pwrseq_inst = |
1006 | pwrseq_instance; |
1007 | cmd.lvtma_control.data.bypass_panel_control_wait = |
1008 | bypass_panel_control_wait; |
1009 | dc_wake_and_execute_dmub_cmd(ctx: dmcub->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT); |
1010 | } |
1011 | |
1012 | static enum bp_result enable_lvtma_control( |
1013 | struct bios_parser *bp, |
1014 | uint8_t uc_pwr_on, |
1015 | uint8_t pwrseq_instance, |
1016 | uint8_t bypass_panel_control_wait) |
1017 | { |
1018 | enum bp_result result = BP_RESULT_FAILURE; |
1019 | |
1020 | if (bp->base.ctx->dc->ctx->dmub_srv && |
1021 | bp->base.ctx->dc->debug.dmub_command_table) { |
1022 | enable_lvtma_control_dmcub(dmcub: bp->base.ctx->dmub_srv, |
1023 | uc_pwr_on, |
1024 | pwrseq_instance, |
1025 | bypass_panel_control_wait); |
1026 | return BP_RESULT_OK; |
1027 | } |
1028 | return result; |
1029 | } |
1030 | |
1031 | void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) |
1032 | { |
1033 | init_dig_encoder_control(bp); |
1034 | init_transmitter_control(bp); |
1035 | init_set_pixel_clock(bp); |
1036 | |
1037 | init_set_crtc_timing(bp); |
1038 | |
1039 | init_enable_crtc(bp); |
1040 | |
1041 | init_external_encoder_control(bp); |
1042 | init_enable_disp_power_gating(bp); |
1043 | init_set_dce_clock(bp); |
1044 | init_get_smu_clock_info(bp); |
1045 | |
1046 | init_enable_lvtma_control(bp); |
1047 | } |
1048 | |