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

drm/i915/dp: Add helpers for Compressed BPP and Slice Count for DSC

This patch adds helpers for calculating the maximum compressed BPP
supported with small joiner.
This also adds a helper for calculating the slice count in case
of small joiner.
These are inside intel_dp since they take into account hardware
limitations.

v6:
* Take mode_clock and mode_hdisplay as input arguments
so that this can be called in intel_dp_mode_valid (Manasi)
v5:
* Get the max slice width from DPCD
* Check against Min_Slice_width of 2560 (Anusha)
v4:
* #defines for PPR in slice count helper (Gaurav)
v3:
* Simply logic for bpp (DK)
* Limit the valid slice count by max supported by Sink (Manasi)
v2:
* Change the small joiner RAM buffer constant as bspec changed (Manasi)
* rename it as SMALL_JOINER since we are not enabling
big joiner yet (Anusha)

Cc: Gaurav K Singh <gaurav.k.singh@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Reviewed-by: Anusha Srivatsa <anusha.srivatsa@intel.com>
Reviewed-by: Gaurav K Singh <gaurav.k.singh@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181031001923.31442-5-manasi.d.navare@intel.com

+108
+104
drivers/gpu/drm/i915/intel_dp.c
··· 45 45 46 46 #define DP_DPRX_ESI_LEN 14 47 47 48 + /* DP DSC small joiner has 2 FIFOs each of 640 x 6 bytes */ 49 + #define DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER 61440 50 + 51 + /* DP DSC throughput values used for slice count calculations KPixels/s */ 52 + #define DP_DSC_PEAK_PIXEL_RATE 2720000 53 + #define DP_DSC_MAX_ENC_THROUGHPUT_0 340000 54 + #define DP_DSC_MAX_ENC_THROUGHPUT_1 400000 55 + 56 + /* DP DSC FEC Overhead factor = (100 - 2.4)/100 */ 57 + #define DP_DSC_FEC_OVERHEAD_FACTOR 976 58 + 48 59 /* Compliance test status bits */ 49 60 #define INTEL_DP_RESOLUTION_SHIFT_MASK 0 50 61 #define INTEL_DP_RESOLUTION_PREFERRED (1 << INTEL_DP_RESOLUTION_SHIFT_MASK) ··· 103 92 { 270000, /* m2_int = 27, m2_fraction = 0 */ 104 93 { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, 105 94 }; 95 + 96 + /* Constants for DP DSC configurations */ 97 + static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15}; 98 + 99 + /* With Single pipe configuration, HW is capable of supporting maximum 100 + * of 4 slices per line. 101 + */ 102 + static const u8 valid_dsc_slicecount[] = {1, 2, 4}; 106 103 107 104 /** 108 105 * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH) ··· 4179 4160 return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, 4180 4161 sink_irq_vector, DP_DPRX_ESI_LEN) == 4181 4162 DP_DPRX_ESI_LEN; 4163 + } 4164 + 4165 + u16 intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count, 4166 + int mode_clock, int mode_hdisplay) 4167 + { 4168 + u16 bits_per_pixel, max_bpp_small_joiner_ram; 4169 + int i; 4170 + 4171 + /* 4172 + * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)* 4173 + * (LinkSymbolClock)* 8 * ((100-FECOverhead)/100)*(TimeSlotsPerMTP) 4174 + * FECOverhead = 2.4%, for SST -> TimeSlotsPerMTP is 1, 4175 + * for MST -> TimeSlotsPerMTP has to be calculated 4176 + */ 4177 + bits_per_pixel = (link_clock * lane_count * 8 * 4178 + DP_DSC_FEC_OVERHEAD_FACTOR) / 4179 + mode_clock; 4180 + 4181 + /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ 4182 + max_bpp_small_joiner_ram = DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER / 4183 + mode_hdisplay; 4184 + 4185 + /* 4186 + * Greatest allowed DSC BPP = MIN (output BPP from avaialble Link BW 4187 + * check, output bpp from small joiner RAM check) 4188 + */ 4189 + bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram); 4190 + 4191 + /* Error out if the max bpp is less than smallest allowed valid bpp */ 4192 + if (bits_per_pixel < valid_dsc_bpp[0]) { 4193 + DRM_DEBUG_KMS("Unsupported BPP %d\n", bits_per_pixel); 4194 + return 0; 4195 + } 4196 + 4197 + /* Find the nearest match in the array of known BPPs from VESA */ 4198 + for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { 4199 + if (bits_per_pixel < valid_dsc_bpp[i + 1]) 4200 + break; 4201 + } 4202 + bits_per_pixel = valid_dsc_bpp[i]; 4203 + 4204 + /* 4205 + * Compressed BPP in U6.4 format so multiply by 16, for Gen 11, 4206 + * fractional part is 0 4207 + */ 4208 + return bits_per_pixel << 4; 4209 + } 4210 + 4211 + u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, 4212 + int mode_clock, 4213 + int mode_hdisplay) 4214 + { 4215 + u8 min_slice_count, i; 4216 + int max_slice_width; 4217 + 4218 + if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE) 4219 + min_slice_count = DIV_ROUND_UP(mode_clock, 4220 + DP_DSC_MAX_ENC_THROUGHPUT_0); 4221 + else 4222 + min_slice_count = DIV_ROUND_UP(mode_clock, 4223 + DP_DSC_MAX_ENC_THROUGHPUT_1); 4224 + 4225 + max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd); 4226 + if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) { 4227 + DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink device\n", 4228 + max_slice_width); 4229 + return 0; 4230 + } 4231 + /* Also take into account max slice width */ 4232 + min_slice_count = min_t(uint8_t, min_slice_count, 4233 + DIV_ROUND_UP(mode_hdisplay, 4234 + max_slice_width)); 4235 + 4236 + /* Find the closest match to the valid slice count values */ 4237 + for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) { 4238 + if (valid_dsc_slicecount[i] > 4239 + drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, 4240 + false)) 4241 + break; 4242 + if (min_slice_count <= valid_dsc_slicecount[i]) 4243 + return valid_dsc_slicecount[i]; 4244 + } 4245 + 4246 + DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count); 4247 + return 0; 4182 4248 } 4183 4249 4184 4250 static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
+4
drivers/gpu/drm/i915/intel_drv.h
··· 1836 1836 bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); 1837 1837 bool 1838 1838 intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]); 1839 + uint16_t intel_dp_dsc_get_output_bpp(int link_clock, uint8_t lane_count, 1840 + int mode_clock, int mode_hdisplay); 1841 + uint8_t intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock, 1842 + int mode_hdisplay); 1839 1843 1840 1844 static inline unsigned int intel_dp_unused_lane_mask(int lane_count) 1841 1845 {