0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include "dcn32_resource.h"
0028 #include "dcn20/dcn20_resource.h"
0029 #include "dml/dcn32/display_mode_vba_util_32.h"
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_state *context)
0047 {
0048 uint32_t num_ways = 0;
0049 uint32_t bytes_per_pixel = 0;
0050 uint32_t cache_lines_used = 0;
0051 uint32_t lines_per_way = 0;
0052 uint32_t total_cache_lines = 0;
0053 uint32_t bytes_in_mall = 0;
0054 uint32_t num_mblks = 0;
0055 uint32_t cache_lines_per_plane = 0;
0056 uint32_t i = 0, j = 0;
0057 uint32_t mblk_width = 0;
0058 uint32_t mblk_height = 0;
0059 uint32_t full_vp_width_blk_aligned = 0;
0060 uint32_t full_vp_height_blk_aligned = 0;
0061 uint32_t mall_alloc_width_blk_aligned = 0;
0062 uint32_t mall_alloc_height_blk_aligned = 0;
0063 uint32_t full_vp_height = 0;
0064
0065 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0066 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0067
0068
0069 if (pipe->stream && pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe &&
0070 pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
0071 struct pipe_ctx *main_pipe = NULL;
0072
0073
0074 for (j = 0; j < dc->res_pool->pipe_count; j++) {
0075 main_pipe = &context->res_ctx.pipe_ctx[j];
0076 if (main_pipe->stream == pipe->stream->mall_stream_config.paired_stream) {
0077 full_vp_height = main_pipe->plane_res.scl_data.viewport.height;
0078 break;
0079 }
0080 }
0081
0082 bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4;
0083 mblk_width = DCN3_2_MBLK_WIDTH;
0084 mblk_height = bytes_per_pixel == 4 ? DCN3_2_MBLK_HEIGHT_4BPE : DCN3_2_MBLK_HEIGHT_8BPE;
0085
0086
0087
0088
0089 full_vp_width_blk_aligned = ((pipe->plane_res.scl_data.viewport.x +
0090 pipe->plane_res.scl_data.viewport.width + mblk_width - 1) / mblk_width * mblk_width) +
0091 (pipe->plane_res.scl_data.viewport.x / mblk_width * mblk_width);
0092
0093
0094
0095
0096 full_vp_height_blk_aligned = ((pipe->plane_res.scl_data.viewport.y +
0097 full_vp_height + mblk_height - 1) / mblk_height * mblk_height) +
0098 (pipe->plane_res.scl_data.viewport.y / mblk_height * mblk_height);
0099
0100
0101 mall_alloc_width_blk_aligned = full_vp_width_blk_aligned;
0102
0103
0104 mall_alloc_height_blk_aligned = (pipe->stream->timing.v_addressable - 1 + mblk_height - 1) /
0105 mblk_height * mblk_height + mblk_height;
0106
0107
0108
0109
0110
0111
0112 num_mblks = ((mall_alloc_width_blk_aligned + mblk_width - 1) / mblk_width) *
0113 ((mall_alloc_height_blk_aligned + mblk_height - 1) / mblk_height);
0114 bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES;
0115
0116
0117 cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2;
0118
0119
0120 if (pipe->plane_state->dcc.enable)
0121 cache_lines_per_plane *= 2;
0122 cache_lines_used += cache_lines_per_plane;
0123 }
0124 }
0125
0126 total_cache_lines = dc->caps.max_cab_allocation_bytes / dc->caps.cache_line_size;
0127 lines_per_way = total_cache_lines / dc->caps.cache_num_ways;
0128 num_ways = cache_lines_used / lines_per_way;
0129 if (cache_lines_used % lines_per_way > 0)
0130 num_ways++;
0131
0132 return num_ways;
0133 }
0134
0135 void dcn32_merge_pipes_for_subvp(struct dc *dc,
0136 struct dc_state *context)
0137 {
0138 uint32_t i;
0139
0140
0141 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0142 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0143
0144
0145
0146
0147 if (pipe->prev_odm_pipe) {
0148
0149 pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe;
0150 if (pipe->next_odm_pipe)
0151 pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe;
0152
0153 pipe->bottom_pipe = NULL;
0154 pipe->next_odm_pipe = NULL;
0155 pipe->plane_state = NULL;
0156 pipe->stream = NULL;
0157 pipe->top_pipe = NULL;
0158 pipe->prev_odm_pipe = NULL;
0159 if (pipe->stream_res.dsc)
0160 dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc);
0161 memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
0162 memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
0163 } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
0164 struct pipe_ctx *top_pipe = pipe->top_pipe;
0165 struct pipe_ctx *bottom_pipe = pipe->bottom_pipe;
0166
0167 top_pipe->bottom_pipe = bottom_pipe;
0168 if (bottom_pipe)
0169 bottom_pipe->top_pipe = top_pipe;
0170
0171 pipe->top_pipe = NULL;
0172 pipe->bottom_pipe = NULL;
0173 pipe->plane_state = NULL;
0174 pipe->stream = NULL;
0175 memset(&pipe->plane_res, 0, sizeof(pipe->plane_res));
0176 memset(&pipe->stream_res, 0, sizeof(pipe->stream_res));
0177 }
0178 }
0179 }
0180
0181 bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc,
0182 struct dc_state *context)
0183 {
0184 uint32_t i;
0185
0186 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0187 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0188
0189 if (!pipe->stream)
0190 return false;
0191
0192 if (!pipe->plane_state)
0193 return false;
0194 }
0195 return true;
0196 }
0197
0198 bool dcn32_subvp_in_use(struct dc *dc,
0199 struct dc_state *context)
0200 {
0201 uint32_t i;
0202
0203 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0204 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0205
0206 if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE)
0207 return true;
0208 }
0209 return false;
0210 }
0211
0212 bool dcn32_mpo_in_use(struct dc_state *context)
0213 {
0214 uint32_t i;
0215
0216 for (i = 0; i < context->stream_count; i++) {
0217 if (context->stream_status[i].plane_count > 1)
0218 return true;
0219 }
0220 return false;
0221 }
0222
0223 void dcn32_determine_det_override(struct dc_state *context, display_e2e_pipe_params_st *pipes,
0224 bool *is_pipe_split_expected, int pipe_cnt)
0225 {
0226 int i, j, count, stream_segments, pipe_segments[MAX_PIPES];
0227
0228 if (context->stream_count > 0) {
0229 stream_segments = 18 / context->stream_count;
0230 for (i = 0; i < context->stream_count; i++) {
0231 count = 0;
0232 for (j = 0; j < pipe_cnt; j++) {
0233 if (context->res_ctx.pipe_ctx[j].stream == context->streams[i]) {
0234 count++;
0235 if (is_pipe_split_expected[j])
0236 count++;
0237 }
0238 }
0239 pipe_segments[i] = stream_segments / count;
0240 }
0241
0242 for (i = 0; i < pipe_cnt; i++) {
0243 pipes[i].pipe.src.det_size_override = 0;
0244 for (j = 0; j < context->stream_count; j++) {
0245 if (context->res_ctx.pipe_ctx[i].stream == context->streams[j]) {
0246 pipes[i].pipe.src.det_size_override = pipe_segments[j] * DCN3_2_DET_SEG_SIZE;
0247 break;
0248 }
0249 }
0250 }
0251 } else {
0252 for (i = 0; i < pipe_cnt; i++)
0253 pipes[i].pipe.src.det_size_override = 4 * DCN3_2_DET_SEG_SIZE;
0254 }
0255 }