@@ -2564,18 +2564,128 @@ static int find_optimal_free_pipe_as_secondary_dpp_pipe(
2564
2564
return free_pipe_idx ;
2565
2565
}
2566
2566
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
+
2567
2672
struct pipe_ctx * dcn32_acquire_free_pipe_as_secondary_dpp_pipe (
2568
2673
const struct dc_state * cur_ctx ,
2569
2674
struct dc_state * new_ctx ,
2570
2675
const struct resource_pool * pool ,
2571
2676
const struct pipe_ctx * opp_head_pipe )
2572
2677
{
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 ;
2577
2680
struct pipe_ctx * free_pipe ;
2578
2681
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 );
2579
2689
if (free_pipe_idx >= 0 ) {
2580
2690
free_pipe = & new_ctx -> res_ctx .pipe_ctx [free_pipe_idx ];
2581
2691
free_pipe -> pipe_idx = free_pipe_idx ;
0 commit comments