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