@@ -2564,18 +2564,128 @@ static int find_optimal_free_pipe_as_secondary_dpp_pipe(
25642564 return free_pipe_idx ;
25652565}
25662566
2567+ static struct pipe_ctx * find_idle_secondary_pipe_check_mpo (
2568+ struct resource_context * res_ctx ,
2569+ const struct resource_pool * pool ,
2570+ const struct pipe_ctx * primary_pipe )
2571+ {
2572+ int i ;
2573+ struct pipe_ctx * secondary_pipe = NULL ;
2574+ struct pipe_ctx * next_odm_mpo_pipe = NULL ;
2575+ int primary_index , preferred_pipe_idx ;
2576+ struct pipe_ctx * old_primary_pipe = NULL ;
2577+
2578+ /*
2579+ * Modified from find_idle_secondary_pipe
2580+ * With windowed MPO and ODM, we want to avoid the case where we want a
2581+ * free pipe for the left side but the free pipe is being used on the
2582+ * right side.
2583+ * Add check on current_state if the primary_pipe is the left side,
2584+ * to check the right side ( primary_pipe->next_odm_pipe ) to see if
2585+ * it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe )
2586+ * - If so, then don't use this pipe
2587+ * EXCEPTION - 3 plane ( 2 MPO plane ) case
2588+ * - in this case, the primary pipe has already gotten a free pipe for the
2589+ * MPO window in the left
2590+ * - when it tries to get a free pipe for the MPO window on the right,
2591+ * it will see that it is already assigned to the right side
2592+ * ( primary_pipe->next_odm_pipe ). But in this case, we want this
2593+ * free pipe, since it will be for the right side. So add an
2594+ * additional condition, that skipping the free pipe on the right only
2595+ * applies if the primary pipe has no bottom pipe currently assigned
2596+ */
2597+ if (primary_pipe ) {
2598+ primary_index = primary_pipe -> pipe_idx ;
2599+ old_primary_pipe = & primary_pipe -> stream -> ctx -> dc -> current_state -> res_ctx .pipe_ctx [primary_index ];
2600+ if ((old_primary_pipe -> next_odm_pipe ) && (old_primary_pipe -> next_odm_pipe -> bottom_pipe )
2601+ && (!primary_pipe -> bottom_pipe ))
2602+ next_odm_mpo_pipe = old_primary_pipe -> next_odm_pipe -> bottom_pipe ;
2603+
2604+ preferred_pipe_idx = (pool -> pipe_count - 1 ) - primary_pipe -> pipe_idx ;
2605+ if ((res_ctx -> pipe_ctx [preferred_pipe_idx ].stream == NULL ) &&
2606+ !(next_odm_mpo_pipe && next_odm_mpo_pipe -> pipe_idx == preferred_pipe_idx )) {
2607+ secondary_pipe = & res_ctx -> pipe_ctx [preferred_pipe_idx ];
2608+ secondary_pipe -> pipe_idx = preferred_pipe_idx ;
2609+ }
2610+ }
2611+
2612+ /*
2613+ * search backwards for the second pipe to keep pipe
2614+ * assignment more consistent
2615+ */
2616+ if (!secondary_pipe )
2617+ for (i = pool -> pipe_count - 1 ; i >= 0 ; i -- ) {
2618+ if ((res_ctx -> pipe_ctx [i ].stream == NULL ) &&
2619+ !(next_odm_mpo_pipe && next_odm_mpo_pipe -> pipe_idx == i )) {
2620+ secondary_pipe = & res_ctx -> pipe_ctx [i ];
2621+ secondary_pipe -> pipe_idx = i ;
2622+ break ;
2623+ }
2624+ }
2625+
2626+ return secondary_pipe ;
2627+ }
2628+
2629+ static struct pipe_ctx * dcn32_acquire_idle_pipe_for_head_pipe_in_layer (
2630+ struct dc_state * state ,
2631+ const struct resource_pool * pool ,
2632+ struct dc_stream_state * stream ,
2633+ const struct pipe_ctx * head_pipe )
2634+ {
2635+ struct resource_context * res_ctx = & state -> res_ctx ;
2636+ struct pipe_ctx * idle_pipe , * pipe ;
2637+ struct resource_context * old_ctx = & stream -> ctx -> dc -> current_state -> res_ctx ;
2638+ int head_index ;
2639+
2640+ if (!head_pipe )
2641+ ASSERT (0 );
2642+
2643+ /*
2644+ * Modified from dcn20_acquire_idle_pipe_for_layer
2645+ * Check if head_pipe in old_context already has bottom_pipe allocated.
2646+ * - If so, check if that pipe is available in the current context.
2647+ * -- If so, reuse pipe from old_context
2648+ */
2649+ head_index = head_pipe -> pipe_idx ;
2650+ pipe = & old_ctx -> pipe_ctx [head_index ];
2651+ if (pipe -> bottom_pipe && res_ctx -> pipe_ctx [pipe -> bottom_pipe -> pipe_idx ].stream == NULL ) {
2652+ idle_pipe = & res_ctx -> pipe_ctx [pipe -> bottom_pipe -> pipe_idx ];
2653+ idle_pipe -> pipe_idx = pipe -> bottom_pipe -> pipe_idx ;
2654+ } else {
2655+ idle_pipe = find_idle_secondary_pipe_check_mpo (res_ctx , pool , head_pipe );
2656+ if (!idle_pipe )
2657+ return NULL ;
2658+ }
2659+
2660+ idle_pipe -> stream = head_pipe -> stream ;
2661+ idle_pipe -> stream_res .tg = head_pipe -> stream_res .tg ;
2662+ idle_pipe -> stream_res .opp = head_pipe -> stream_res .opp ;
2663+
2664+ idle_pipe -> plane_res .hubp = pool -> hubps [idle_pipe -> pipe_idx ];
2665+ idle_pipe -> plane_res .ipp = pool -> ipps [idle_pipe -> pipe_idx ];
2666+ idle_pipe -> plane_res .dpp = pool -> dpps [idle_pipe -> pipe_idx ];
2667+ idle_pipe -> plane_res .mpcc_inst = pool -> dpps [idle_pipe -> pipe_idx ]-> inst ;
2668+
2669+ return idle_pipe ;
2670+ }
2671+
25672672struct pipe_ctx * dcn32_acquire_free_pipe_as_secondary_dpp_pipe (
25682673 const struct dc_state * cur_ctx ,
25692674 struct dc_state * new_ctx ,
25702675 const struct resource_pool * pool ,
25712676 const struct pipe_ctx * opp_head_pipe )
25722677{
2573- int free_pipe_idx =
2574- find_optimal_free_pipe_as_secondary_dpp_pipe (
2575- & cur_ctx -> res_ctx , & new_ctx -> res_ctx ,
2576- pool , opp_head_pipe );
2678+
2679+ int free_pipe_idx ;
25772680 struct pipe_ctx * free_pipe ;
25782681
2682+ if (!opp_head_pipe -> stream -> ctx -> dc -> config .enable_windowed_mpo_odm )
2683+ return dcn32_acquire_idle_pipe_for_head_pipe_in_layer (
2684+ new_ctx , pool , opp_head_pipe -> stream , opp_head_pipe );
2685+
2686+ free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe (
2687+ & cur_ctx -> res_ctx , & new_ctx -> res_ctx ,
2688+ pool , opp_head_pipe );
25792689 if (free_pipe_idx >= 0 ) {
25802690 free_pipe = & new_ctx -> res_ctx .pipe_ctx [free_pipe_idx ];
25812691 free_pipe -> pipe_idx = free_pipe_idx ;
0 commit comments