253ff9659b0d1c7c604973b35957a0c8ed74f927
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dml / dcn32 / dcn32_fpu.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2022 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 #include "dcn32_fpu.h"
27
28 // We need this includes for WATERMARKS_* defines
29 #include "clk_mgr/dcn32/dcn32_smu13_driver_if.h"
30
31 void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr)
32 {
33         /* defaults */
34         double pstate_latency_us = clk_mgr->base.ctx->dc->dml.soc.dram_clock_change_latency_us;
35         double fclk_change_latency_us = clk_mgr->base.ctx->dc->dml.soc.fclk_change_latency_us;
36         double sr_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_exit_time_us;
37         double sr_enter_plus_exit_time_us = clk_mgr->base.ctx->dc->dml.soc.sr_enter_plus_exit_time_us;
38         /* For min clocks use as reported by PM FW and report those as min */
39         uint16_t min_uclk_mhz                   = clk_mgr->base.bw_params->clk_table.entries[0].memclk_mhz;
40         uint16_t min_dcfclk_mhz                 = clk_mgr->base.bw_params->clk_table.entries[0].dcfclk_mhz;
41         uint16_t setb_min_uclk_mhz              = min_uclk_mhz;
42         uint16_t dcfclk_mhz_for_the_second_state = clk_mgr->base.ctx->dc->dml.soc.clock_limits[2].dcfclk_mhz;
43
44         dc_assert_fp_enabled();
45
46         /* For Set B ranges use min clocks state 2 when available, and report those to PM FW */
47         if (dcfclk_mhz_for_the_second_state)
48                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = dcfclk_mhz_for_the_second_state;
49         else
50                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = clk_mgr->base.bw_params->clk_table.entries[0].dcfclk_mhz;
51
52         if (clk_mgr->base.bw_params->clk_table.entries[2].memclk_mhz)
53                 setb_min_uclk_mhz = clk_mgr->base.bw_params->clk_table.entries[2].memclk_mhz;
54
55         /* Set A - Normal - default values */
56         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].valid = true;
57         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us;
58         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us = fclk_change_latency_us;
59         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us;
60         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
61         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
62         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;
63         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF;
64         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz;
65         clk_mgr->base.bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF;
66
67         /* Set B - Performance - higher clocks, using DPM[2] DCFCLK and UCLK */
68         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].valid = true;
69         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us;
70         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.fclk_change_latency_us = fclk_change_latency_us;
71         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us;
72         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
73         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE;
74         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF;
75         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = setb_min_uclk_mhz;
76         clk_mgr->base.bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF;
77
78         /* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */
79         /* 'DalDummyClockChangeLatencyNs' registry key option set to 0x7FFFFFFF can be used to disable Set C for dummy p-state */
80         if (clk_mgr->base.ctx->dc->bb_overrides.dummy_clock_change_latency_ns != 0x7FFFFFFF) {
81                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].valid = true;
82                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 38;
83                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.fclk_change_latency_us = fclk_change_latency_us;
84                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us;
85                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us;
86                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE;
87                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;
88                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF;
89                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
90                 clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
91                 clk_mgr->base.bw_params->dummy_pstate_table[0].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[0].memclk_mhz * 16;
92                 clk_mgr->base.bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 38;
93                 clk_mgr->base.bw_params->dummy_pstate_table[1].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[1].memclk_mhz * 16;
94                 clk_mgr->base.bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9;
95                 clk_mgr->base.bw_params->dummy_pstate_table[2].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[2].memclk_mhz * 16;
96                 clk_mgr->base.bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8;
97                 clk_mgr->base.bw_params->dummy_pstate_table[3].dram_speed_mts = clk_mgr->base.bw_params->clk_table.entries[3].memclk_mhz * 16;
98                 clk_mgr->base.bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5;
99         }
100         /* Set D - MALL - SR enter and exit time specific to MALL, TBD after bringup or later phase for now use DRAM values / 2 */
101         /* For MALL DRAM clock change latency is N/A, for watermak calculations use lowest value dummy P state latency */
102         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].valid = true;
103         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = clk_mgr->base.bw_params->dummy_pstate_table[3].dummy_pstate_latency_us;
104         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.fclk_change_latency_us = fclk_change_latency_us;
105         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = sr_exit_time_us / 2; // TBD
106         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us / 2; // TBD
107         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
108         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz;
109         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
110         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
111         clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
112 }
113
114 /**
115  * dcn32_helper_populate_phantom_dlg_params - Get DLG params for phantom pipes
116  * and populate pipe_ctx with those params.
117  *
118  * This function must be called AFTER the phantom pipes are added to context
119  * and run through DML (so that the DLG params for the phantom pipes can be
120  * populated), and BEFORE we program the timing for the phantom pipes.
121  *
122  * @dc: [in] current dc state
123  * @context: [in] new dc state
124  * @pipes: [in] DML pipe params array
125  * @pipe_cnt: [in] DML pipe count
126  */
127 void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
128                                               struct dc_state *context,
129                                               display_e2e_pipe_params_st *pipes,
130                                               int pipe_cnt)
131 {
132         uint32_t i, pipe_idx;
133
134         dc_assert_fp_enabled();
135
136         for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
137                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
138
139                 if (!pipe->stream)
140                         continue;
141
142                 if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
143                         pipes[pipe_idx].pipe.dest.vstartup_start =
144                                 get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
145                         pipes[pipe_idx].pipe.dest.vupdate_offset =
146                                 get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
147                         pipes[pipe_idx].pipe.dest.vupdate_width =
148                                 get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
149                         pipes[pipe_idx].pipe.dest.vready_offset =
150                                 get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
151                         pipe->pipe_dlg_param = pipes[pipe_idx].pipe.dest;
152                 }
153                 pipe_idx++;
154         }
155 }
156