Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/msm/dpu: Fall back to a single DSC encoder (1:1:1) on small SoCs

Some SoCs such as SC7280 (used in the Fairphone 5) have only a single
DSC "hard slice" encoder. The current hardcoded use of 2:2:1 topology
(2 LM and 2 DSC for a single interface) make it impossible to use
Display Stream Compression panels with mainline, which is exactly what's
installed on the Fairphone 5.

By loosening the hardcoded `num_dsc = 2` to fall back to `num_dsc =
1` when the catalog only contains one entry, we can trivially support
this phone and unblock further panel enablement on mainline. A few
more supporting changes in this patch ensure hardcoded constants of 2
DSC encoders are replaced to count or read back the actual number of
DSC hardware blocks that are enabled for the given virtual encoder.
Likewise DSC_MODE_SPLIT_PANEL can no longer be unconditionally enabled.

Cc: Luca Weiss <luca.weiss@fairphone.com>
Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Tested-by: Luca Weiss <luca.weiss@fairphone.com>
Reviewed-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Tested-by: Danila Tikhonov <danila@jiaxyga.com>
Patchwork: https://patchwork.freedesktop.org/patch/633318/
Link: https://lore.kernel.org/r/20250122-dpu-111-topology-v2-1-505e95964af9@somainline.org
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

authored by

Marijn Suijten and committed by
Dmitry Baryshkov
b6090ffb 25dc6948

+25 -22
+25 -22
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 622 622 if (dpu_enc->phys_encs[i]) 623 623 intf_count++; 624 624 625 - /* See dpu_encoder_get_topology, we only support 2:2:1 topology */ 626 - if (dpu_enc->dsc) 627 - num_dsc = 2; 625 + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 626 + if (dpu_enc->hw_dsc[i]) 627 + num_dsc++; 628 628 629 629 return (num_dsc > 0) && (num_dsc > intf_count); 630 630 } ··· 686 686 687 687 if (dsc) { 688 688 /* 689 - * In case of Display Stream Compression (DSC), we would use 690 - * 2 DSC encoders, 2 layer mixers and 1 interface 691 - * this is power optimal and can drive up to (including) 4k 692 - * screens 689 + * Use 2 DSC encoders and 2 layer mixers per single interface 690 + * when Display Stream Compression (DSC) is enabled, 691 + * and when enough DSC blocks are available. 692 + * This is power-optimal and can drive up to (including) 4k 693 + * screens. 693 694 */ 694 - topology.num_dsc = 2; 695 - topology.num_lm = 2; 695 + if (dpu_kms->catalog->dsc_count >= 2) { 696 + topology.num_dsc = 2; 697 + topology.num_lm = 2; 698 + } else { 699 + topology.num_dsc = 1; 700 + topology.num_lm = 1; 701 + } 696 702 topology.num_intf = 1; 697 703 } 698 704 ··· 2026 2020 static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc, 2027 2021 struct drm_dsc_config *dsc) 2028 2022 { 2029 - /* coding only for 2LM, 2enc, 1 dsc config */ 2030 2023 struct dpu_encoder_phys *enc_master = dpu_enc->cur_master; 2031 2024 struct dpu_hw_ctl *ctl = enc_master->hw_ctl; 2032 2025 struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; ··· 2035 2030 int dsc_common_mode; 2036 2031 int pic_width; 2037 2032 u32 initial_lines; 2033 + int num_dsc = 0; 2038 2034 int i; 2039 2035 2040 2036 for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { 2041 2037 hw_pp[i] = dpu_enc->hw_pp[i]; 2042 2038 hw_dsc[i] = dpu_enc->hw_dsc[i]; 2043 2039 2044 - if (!hw_pp[i] || !hw_dsc[i]) { 2045 - DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n"); 2046 - return; 2047 - } 2040 + if (!hw_pp[i] || !hw_dsc[i]) 2041 + break; 2042 + 2043 + num_dsc++; 2048 2044 } 2049 2045 2050 - dsc_common_mode = 0; 2051 2046 pic_width = dsc->pic_width; 2052 2047 2053 - dsc_common_mode = DSC_MODE_SPLIT_PANEL; 2048 + dsc_common_mode = 0; 2049 + if (num_dsc > 1) 2050 + dsc_common_mode |= DSC_MODE_SPLIT_PANEL; 2054 2051 if (dpu_encoder_use_dsc_merge(enc_master->parent)) 2055 2052 dsc_common_mode |= DSC_MODE_MULTIPLEX; 2056 2053 if (enc_master->intf_mode == INTF_MODE_VIDEO) ··· 2061 2054 this_frame_slices = pic_width / dsc->slice_width; 2062 2055 intf_ip_w = this_frame_slices * dsc->slice_width; 2063 2056 2064 - /* 2065 - * dsc merge case: when using 2 encoders for the same stream, 2066 - * no. of slices need to be same on both the encoders. 2067 - */ 2068 - enc_ip_w = intf_ip_w / 2; 2057 + enc_ip_w = intf_ip_w / num_dsc; 2069 2058 initial_lines = dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w); 2070 2059 2071 - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) 2060 + for (i = 0; i < num_dsc; i++) 2072 2061 dpu_encoder_dsc_pipe_cfg(ctl, hw_dsc[i], hw_pp[i], 2073 2062 dsc, dsc_common_mode, initial_lines); 2074 2063 }