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