Line data Source code
1 : /*
2 : * Copyright 2022 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 : // header file of functions being implemented
27 : #include "dcn32_resource.h"
28 : #include "dcn20/dcn20_resource.h"
29 : #include "dml/dcn32/display_mode_vba_util_32.h"
30 :
31 : /**
32 : * ********************************************************************************************
33 : * dcn32_helper_calculate_num_ways_for_subvp: Calculate number of ways needed for SubVP
34 : *
35 : * This function first checks the bytes required per pixel on the SubVP pipe, then calculates
36 : * the total number of pixels required in the SubVP MALL region. These are used to calculate
37 : * the number of cache lines used (then number of ways required) for SubVP MCLK switching.
38 : *
39 : * @param [in] dc: current dc state
40 : * @param [in] context: new dc state
41 : *
42 : * @return: number of ways required for SubVP
43 : *
44 : * ********************************************************************************************
45 : */
46 0 : uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_state *context)
47 : {
48 0 : uint32_t num_ways = 0;
49 0 : uint32_t mall_region_pixels = 0;
50 0 : uint32_t bytes_per_pixel = 0;
51 0 : uint32_t cache_lines_used = 0;
52 0 : uint32_t lines_per_way = 0;
53 0 : uint32_t total_cache_lines = 0;
54 0 : uint32_t bytes_in_mall = 0;
55 0 : uint32_t num_mblks = 0;
56 0 : uint32_t cache_lines_per_plane = 0;
57 0 : uint32_t i = 0;
58 :
59 0 : for (i = 0; i < dc->res_pool->pipe_count; i++) {
60 0 : struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
61 :
62 : // Find the phantom pipes
63 0 : if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
64 0 : pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
65 0 : bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4;
66 0 : mall_region_pixels = pipe->plane_state->plane_size.surface_pitch * pipe->stream->timing.v_addressable;
67 :
68 : // For bytes required in MALL, calculate based on number of MBlks required
69 0 : num_mblks = (mall_region_pixels * bytes_per_pixel +
70 0 : DCN3_2_MALL_MBLK_SIZE_BYTES - 1) / DCN3_2_MALL_MBLK_SIZE_BYTES;
71 0 : bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES;
72 : // cache lines used is total bytes / cache_line size. Add +2 for worst case alignment
73 : // (MALL is 64-byte aligned)
74 0 : cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2;
75 :
76 : // For DCC we must cache the meat surface, so double cache lines required
77 0 : if (pipe->plane_state->dcc.enable)
78 0 : cache_lines_per_plane *= 2;
79 0 : cache_lines_used += cache_lines_per_plane;
80 : }
81 : }
82 :
83 0 : total_cache_lines = dc->caps.max_cab_allocation_bytes / dc->caps.cache_line_size;
84 0 : lines_per_way = total_cache_lines / dc->caps.cache_num_ways;
85 0 : num_ways = cache_lines_used / lines_per_way;
86 0 : if (cache_lines_used % lines_per_way > 0)
87 0 : num_ways++;
88 :
89 0 : return num_ways;
90 : }
91 :
92 0 : void dcn32_merge_pipes_for_subvp(struct dc *dc,
93 : struct dc_state *context)
94 : {
95 : uint32_t i;
96 :
97 : /* merge pipes if necessary */
98 0 : for (i = 0; i < dc->res_pool->pipe_count; i++) {
99 0 : struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
100 :
101 : // For now merge all pipes for SubVP since pipe split case isn't supported yet
102 :
103 : /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */
104 0 : if (pipe->prev_odm_pipe) {
105 : /*split off odm pipe*/
106 0 : pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
107 0 : if (pipe->next_odm_pipe)
108 0 : pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
109 :
110 0 : pipe->bottom_pipe = NULL;
111 0 : pipe->next_odm_pipe = NULL;
112 0 : pipe->plane_state = NULL;
113 0 : pipe->stream = NULL;
114 0 : pipe->top_pipe = NULL;
115 0 : pipe->prev_odm_pipe = NULL;
116 0 : if (pipe->stream_res.dsc)
117 0 : dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
118 0 : memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
119 0 : memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
120 0 : } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
121 0 : struct pipe_ctx *top_pipe = pipe->top_pipe;
122 0 : struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
123 :
124 0 : top_pipe->bottom_pipe = bottom_pipe;
125 0 : if (bottom_pipe)
126 0 : bottom_pipe->top_pipe = top_pipe;
127 :
128 0 : pipe->top_pipe = NULL;
129 0 : pipe->bottom_pipe = NULL;
130 0 : pipe->plane_state = NULL;
131 0 : pipe->stream = NULL;
132 0 : memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
133 0 : memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
134 : }
135 : }
136 0 : }
137 :
138 0 : bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc,
139 : struct dc_state *context)
140 : {
141 : uint32_t i;
142 :
143 0 : for (i = 0; i < dc->res_pool->pipe_count; i++) {
144 0 : struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
145 :
146 0 : if (!pipe->stream)
147 : return false;
148 :
149 0 : if (!pipe->plane_state)
150 : return false;
151 : }
152 : return true;
153 : }
154 :
155 0 : bool dcn32_subvp_in_use(struct dc *dc,
156 : struct dc_state *context)
157 : {
158 : uint32_t i;
159 :
160 0 : for (i = 0; i < dc->res_pool->pipe_count; i++) {
161 0 : struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
162 :
163 0 : if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE)
164 : return true;
165 : }
166 : return false;
167 : }
168 :
169 0 : bool dcn32_mpo_in_use(struct dc_state *context)
170 : {
171 : uint32_t i;
172 :
173 0 : for (i = 0; i < context->stream_count; i++) {
174 0 : if (context->stream_status[i].plane_count > 1)
175 : return true;
176 : }
177 : return false;
178 : }
179 :
180 0 : void dcn32_determine_det_override(struct dc_state *context, display_e2e_pipe_params_st *pipes,
181 : bool *is_pipe_split_expected, int pipe_cnt)
182 : {
183 : int i, j, count, stream_segments, pipe_segments[MAX_PIPES];
184 :
185 0 : if (context->stream_count > 0) {
186 0 : stream_segments = 18 / context->stream_count;
187 0 : for (i = 0; i < context->stream_count; i++) {
188 : count = 0;
189 0 : for (j = 0; j < pipe_cnt; j++) {
190 0 : if (context->res_ctx.pipe_ctx[j].stream == context->streams[i]) {
191 0 : count++;
192 0 : if (is_pipe_split_expected[j])
193 0 : count++;
194 : }
195 : }
196 0 : pipe_segments[i] = stream_segments / count;
197 : }
198 :
199 0 : for (i = 0; i < pipe_cnt; i++) {
200 0 : pipes[i].pipe.src.det_size_override = 0;
201 0 : for (j = 0; j < context->stream_count; j++) {
202 0 : if (context->res_ctx.pipe_ctx[i].stream == context->streams[j]) {
203 0 : pipes[i].pipe.src.det_size_override = pipe_segments[j] * DCN3_2_DET_SEG_SIZE;
204 0 : break;
205 : }
206 : }
207 : }
208 : } else {
209 0 : for (i = 0; i < pipe_cnt; i++)
210 0 : pipes[i].pipe.src.det_size_override = 4 * DCN3_2_DET_SEG_SIZE; //DCN3_2_DEFAULT_DET_SIZE
211 : }
212 0 : }
|