| @@ -78,8 +78,8 @@ · 77 unmodified lines |
| 78 | #define DP_DSC_MAX_ENC_THROUGHPUT_0 340000 | 78 | #define DP_DSC_MAX_ENC_THROUGHPUT_0 340000 |
| 79 | #define DP_DSC_MAX_ENC_THROUGHPUT_1 400000 | 79 | #define DP_DSC_MAX_ENC_THROUGHPUT_1 400000 |
| 80 | | 80 | |
| 81 | /* DP DSC FEC Overhead factor = (100 - 2.4)/100 */ | 81 | /* DP DSC FEC Overhead factor = 1/(0.972261) */ |
| 82 | #define DP_DSC_FEC_OVERHEAD_FACTOR 976 | 82 | #define DP_DSC_FEC_OVERHEAD_FACTOR 972261 |
| 83 | | 83 | |
| 84 | /* Compliance test status bits */ | 84 | /* Compliance test status bits */ |
| 85 | #define INTEL_DP_RESOLUTION_SHIFT_MASK 0 | 85 | #define INTEL_DP_RESOLUTION_SHIFT_MASK 0 |
| @@ -494,6 +494,97 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, · 408 unmodified lines |
| 494 | return 0; | 494 | return 0; |
| 495 | } | 495 | } |
| 496 | | 496 | |
| | 497 | u32 intel_dp_mode_to_fec_clock(u32 mode_clock) |
| | 498 | { |
| | 499 | return div_u64(mul_u32_u32(mode_clock, 1000000U), |
| | 500 | DP_DSC_FEC_OVERHEAD_FACTOR); |
| | 501 | } |
| | 502 | |
| | 503 | static u16 intel_dp_dsc_get_output_bpp(u32 link_clock, u32 lane_count, |
| | 504 | u32 mode_clock, u32 mode_hdisplay) |
| | 505 | { |
| | 506 | u32 bits_per_pixel, max_bpp_small_joiner_ram; |
| | 507 | int i; |
| | 508 | |
| | 509 | /* |
| | 510 | * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)* |
| | 511 | * (LinkSymbolClock)* 8 * (TimeSlotsPerMTP) |
| | 512 | * for SST -> TimeSlotsPerMTP is 1, |
| | 513 | * for MST -> TimeSlotsPerMTP has to be calculated |
| | 514 | */ |
| | 515 | bits_per_pixel = (link_clock * lane_count * 8) / |
| | 516 | intel_dp_mode_to_fec_clock(mode_clock); |
| | 517 | DRM_DEBUG_KMS("Max link bpp: %u\n", bits_per_pixel); |
| | 518 | |
| | 519 | /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ |
| | 520 | max_bpp_small_joiner_ram = DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER / mode_hdisplay; |
| | 521 | DRM_DEBUG_KMS("Max small joiner bpp: %u\n", max_bpp_small_joiner_ram); |
| | 522 | |
| | 523 | /* |
| | 524 | * Greatest allowed DSC BPP = MIN (output BPP from available Link BW |
| | 525 | * check, output bpp from small joiner RAM check) |
| | 526 | */ |
| | 527 | bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram); |
| | 528 | |
| | 529 | /* Error out if the max bpp is less than smallest allowed valid bpp */ |
| | 530 | if (bits_per_pixel < valid_dsc_bpp[0]) { |
| | 531 | DRM_DEBUG_KMS("Unsupported BPP %u, min %u\n", |
| | 532 | bits_per_pixel, valid_dsc_bpp[0]); |
| | 533 | return 0; |
| | 534 | } |
| | 535 | |
| | 536 | /* Find the nearest match in the array of known BPPs from VESA */ |
| | 537 | for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { |
| | 538 | if (bits_per_pixel < valid_dsc_bpp[i + 1]) |
| | 539 | break; |
| | 540 | } |
| | 541 | bits_per_pixel = valid_dsc_bpp[i]; |
| | 542 | |
| | 543 | /* |
| | 544 | * Compressed BPP in U6.4 format so multiply by 16, for Gen 11, |
| | 545 | * fractional part is 0 |
| | 546 | */ |
| | 547 | return bits_per_pixel << 4; |
| | 548 | } |
| | 549 | |
| | 550 | static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, |
| | 551 | int mode_clock, int mode_hdisplay) |
| | 552 | { |
| | 553 | u8 min_slice_count, i; |
| | 554 | int max_slice_width; |
| | 555 | |
| | 556 | if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE) |
| | 557 | min_slice_count = DIV_ROUND_UP(mode_clock, |
| | 558 | DP_DSC_MAX_ENC_THROUGHPUT_0); |
| | 559 | else |
| | 560 | min_slice_count = DIV_ROUND_UP(mode_clock, |
| | 561 | DP_DSC_MAX_ENC_THROUGHPUT_1); |
| | 562 | |
| | 563 | max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd); |
| | 564 | if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) { |
| | 565 | DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink device\n", |
| | 566 | max_slice_width); |
| | 567 | return 0; |
| | 568 | } |
| | 569 | /* Also take into account max slice width */ |
| | 570 | min_slice_count = min_t(u8, min_slice_count, |
| | 571 | DIV_ROUND_UP(mode_hdisplay, |
| | 572 | max_slice_width)); |
| | 573 | |
| | 574 | /* Find the closest match to the valid slice count values */ |
| | 575 | for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) { |
| | 576 | if (valid_dsc_slicecount[i] > |
| | 577 | drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, |
| | 578 | false)) |
| | 579 | break; |
| | 580 | if (min_slice_count <= valid_dsc_slicecount[i]) |
| | 581 | return valid_dsc_slicecount[i]; |
| | 582 | } |
| | 583 | |
| | 584 | DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count); |
| | 585 | return 0; |
| | 586 | } |
| | 587 | |
| 497 | static enum drm_mode_status | 588 | static enum drm_mode_status |
| 498 | intel_dp_mode_valid(struct drm_connector *connector, | 589 | intel_dp_mode_valid(struct drm_connector *connector, |
| 499 | struct drm_display_mode *mode) | 590 | struct drm_display_mode *mode) |
| @@ -2226,7 +2317,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, · 1726 unmodified lines |
| 2226 | adjusted_mode->crtc_clock, | 2317 | adjusted_mode->crtc_clock, |
| 2227 | pipe_config->port_clock, | 2318 | pipe_config->port_clock, |
| 2228 | &pipe_config->dp_m_n, | 2319 | &pipe_config->dp_m_n, |
| 2229 | constant_n); | 2320 | constant_n, pipe_config->fec_enable); |
| 2230 | | 2321 | |
| 2231 | if (intel_connector->panel.downclock_mode != NULL && | 2322 | if (intel_connector->panel.downclock_mode != NULL && |
| 2232 | dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { | 2323 | dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { |
| @@ -2236,7 +2327,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, · 3 unmodified lines |
| 2236 | intel_connector->panel.downclock_mode->clock, | 2327 | intel_connector->panel.downclock_mode->clock, |
| 2237 | pipe_config->port_clock, | 2328 | pipe_config->port_clock, |
| 2238 | &pipe_config->dp_m2_n2, | 2329 | &pipe_config->dp_m2_n2, |
| 2239 | constant_n); | 2330 | constant_n, pipe_config->fec_enable); |
| 2240 | } | 2331 | } |
| 2241 | | 2332 | |
| 2242 | if (!HAS_DDI(dev_priv)) | 2333 | if (!HAS_DDI(dev_priv)) |
| @@ -4323,91 +4414,6 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector) · 2080 unmodified lines |
| 4323 | DP_DPRX_ESI_LEN; | 4414 | DP_DPRX_ESI_LEN; |
| 4324 | } | 4415 | } |
| 4325 | | 4416 | |
| 4326 | u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count, | | |
| 4327 | int mode_clock, int mode_hdisplay) | | |
| 4328 | { | | |
| 4329 | u16 bits_per_pixel, max_bpp_small_joiner_ram; | | |
| 4330 | int i; | | |
| 4331 | | | |
| 4332 | /* | | |
| 4333 | * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)* | | |
| 4334 | * (LinkSymbolClock)* 8 * ((100-FECOverhead)/100)*(TimeSlotsPerMTP) | | |
| 4335 | * FECOverhead = 2.4%, for SST -> TimeSlotsPerMTP is 1, | | |
| 4336 | * for MST -> TimeSlotsPerMTP has to be calculated | | |
| 4337 | */ | | |
| 4338 | bits_per_pixel = (link_clock * lane_count * 8 * | | |
| 4339 | DP_DSC_FEC_OVERHEAD_FACTOR) / | | |
| 4340 | mode_clock; | | |
| 4341 | | | |
| 4342 | /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ | | |
| 4343 | max_bpp_small_joiner_ram = DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER / | | |
| 4344 | mode_hdisplay; | | |
| 4345 | | | |
| 4346 | /* | | |
| 4347 | * Greatest allowed DSC BPP = MIN (output BPP from avaialble Link BW | | |
| 4348 | * check, output bpp from small joiner RAM check) | | |
| 4349 | */ | | |
| 4350 | bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram); | | |
| 4351 | | | |
| 4352 | /* Error out if the max bpp is less than smallest allowed valid bpp */ | | |
| 4353 | if (bits_per_pixel < valid_dsc_bpp[0]) { | | |
| 4354 | DRM_DEBUG_KMS("Unsupported BPP %d\n", bits_per_pixel); | | |
| 4355 | return 0; | | |
| 4356 | } | | |
| 4357 | | | |
| 4358 | /* Find the nearest match in the array of known BPPs from VESA */ | | |
| 4359 | for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) { | | |
| 4360 | if (bits_per_pixel < valid_dsc_bpp[i + 1]) | | |
| 4361 | break; | | |
| 4362 | } | | |
| 4363 | bits_per_pixel = valid_dsc_bpp[i]; | | |
| 4364 | | | |
| 4365 | /* | | |
| 4366 | * Compressed BPP in U6.4 format so multiply by 16, for Gen 11, | | |
| 4367 | * fractional part is 0 | | |
| 4368 | */ | | |
| 4369 | return bits_per_pixel << 4; | | |
| 4370 | } | | |
| 4371 | | | |
| 4372 | u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, | | |
| 4373 | int mode_clock, | | |
| 4374 | int mode_hdisplay) | | |
| 4375 | { | | |
| 4376 | u8 min_slice_count, i; | | |
| 4377 | int max_slice_width; | | |
| 4378 | | | |
| 4379 | if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE) | | |
| 4380 | min_slice_count = DIV_ROUND_UP(mode_clock, | | |
| 4381 | DP_DSC_MAX_ENC_THROUGHPUT_0); | | |
| 4382 | else | | |
| 4383 | min_slice_count = DIV_ROUND_UP(mode_clock, | | |
| 4384 | DP_DSC_MAX_ENC_THROUGHPUT_1); | | |
| 4385 | | | |
| 4386 | max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd); | | |
| 4387 | if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) { | | |
| 4388 | DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink device\n", | | |
| 4389 | max_slice_width); | | |
| 4390 | return 0; | | |
| 4391 | } | | |
| 4392 | /* Also take into account max slice width */ | | |
| 4393 | min_slice_count = min_t(u8, min_slice_count, | | |
| 4394 | DIV_ROUND_UP(mode_hdisplay, | | |
| 4395 | max_slice_width)); | | |
| 4396 | | | |
| 4397 | /* Find the closest match to the valid slice count values */ | | |
| 4398 | for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) { | | |
| 4399 | if (valid_dsc_slicecount[i] > | | |
| 4400 | drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, | | |
| 4401 | false)) | | |
| 4402 | break; | | |
| 4403 | if (min_slice_count <= valid_dsc_slicecount[i]) | | |
| 4404 | return valid_dsc_slicecount[i]; | | |
| 4405 | } | | |
| 4406 | | | |
| 4407 | DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count); | | |
| 4408 | return 0; | | |
| 4409 | } | | |
| 4410 | | | |
| 4411 | static void | 4417 | static void |
| 4412 | intel_pixel_encoding_setup_vsc(struct intel_dp *intel_dp, | 4418 | intel_pixel_encoding_setup_vsc(struct intel_dp *intel_dp, |
| 4413 | const struct intel_crtc_state *crtc_state) | 4419 | const struct intel_crtc_state *crtc_state) |