Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2022 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 // header file of functions being implemented
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  * dcn32_helper_calculate_num_ways_for_subvp: Calculate number of ways needed for SubVP
0034  *
0035  * This function first checks the bytes required per pixel on the SubVP pipe, then calculates
0036  * the total number of pixels required in the SubVP MALL region. These are used to calculate
0037  * the number of cache lines used (then number of ways required) for SubVP MCLK switching.
0038  *
0039  * @param [in] dc: current dc state
0040  * @param [in] context: new dc state
0041  *
0042  * @return: number of ways required for SubVP
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         // Find the phantom pipes
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             /* Get full viewport height from main pipe (required for MBLK calculation) */
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             /* full_vp_width_blk_aligned = FLOOR(vp_x_start + full_vp_width + blk_width - 1, blk_width) -
0087              * FLOOR(vp_x_start, blk_width)
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             /* full_vp_height_blk_aligned = FLOOR(vp_y_start + full_vp_height + blk_height - 1, blk_height) -
0094              * FLOOR(vp_y_start, blk_height)
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             /* mall_alloc_width_blk_aligned_l/c = full_vp_width_blk_aligned_l/c */
0101             mall_alloc_width_blk_aligned = full_vp_width_blk_aligned;
0102 
0103             /* mall_alloc_height_blk_aligned_l/c = CEILING(sub_vp_height_l/c - 1, blk_height_l/c) + blk_height_l/c */
0104             mall_alloc_height_blk_aligned = (pipe->stream->timing.v_addressable - 1 + mblk_height - 1) /
0105                     mblk_height * mblk_height + mblk_height;
0106 
0107             /* full_mblk_width_ub_l/c = mall_alloc_width_blk_aligned_l/c;
0108              * full_mblk_height_ub_l/c = mall_alloc_height_blk_aligned_l/c;
0109              * num_mblk_l/c = (full_mblk_width_ub_l/c / mblk_width_l/c) * (full_mblk_height_ub_l/c / mblk_height_l/c);
0110              * (Should be divisible, but round up if not)
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             // cache lines used is total bytes / cache_line size. Add +2 for worst case alignment
0116             // (MALL is 64-byte aligned)
0117             cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2;
0118 
0119             // For DCC we must cache the meat surface, so double cache lines required
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     /* merge pipes if necessary */
0141     for (i = 0; i < dc->res_pool->pipe_count; i++) {
0142         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
0143 
0144         // For now merge all pipes for SubVP since pipe split case isn't supported yet
0145 
0146         /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */
0147         if (pipe->prev_odm_pipe) {
0148             /*split off odm pipe*/
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; //DCN3_2_DEFAULT_DET_SIZE
0254     }
0255 }