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

drm/i915/dmc: Assert DMC is loaded harder

Currently we have some asserts to make sure the main DMC has been
loaded. Add similar asserts for the pipe DMCs. And we might as well
just check all the mmio registers the firmware has asked us to
initialize. That also covers the hardcoded SSP/HTP registers we were
checking for the main DMC.

TODO: Maybe always configure DMC_EVT_CTL_ENABLE the way the firmware
has it set so that we wouldn't need to special case in the assert?

v2: Also assert in intel_dmc_load_program()

Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250617170759.19552-8-ville.syrjala@linux.intel.com

+48 -18
+2 -2
drivers/gpu/drm/i915/display/intel_display_power_well.c
··· 829 829 830 830 assert_display_rpm_held(display); 831 831 832 - assert_dmc_loaded(display); 832 + assert_main_dmc_loaded(display); 833 833 } 834 834 835 835 void gen9_enable_dc5(struct intel_display *display) ··· 860 860 DC_STATE_EN_UPTO_DC6), 861 861 "DC6 already programmed to be enabled.\n"); 862 862 863 - assert_dmc_loaded(display); 863 + assert_main_dmc_loaded(display); 864 864 } 865 865 866 866 void skl_enable_dc6(struct intel_display *display)
+45 -15
drivers/gpu/drm/i915/display/intel_dmc.c
··· 607 607 dmc_load_mmio(display, dmc_id); 608 608 } 609 609 610 + static void assert_dmc_loaded(struct intel_display *display, 611 + enum intel_dmc_id dmc_id) 612 + { 613 + struct intel_dmc *dmc = display_to_dmc(display); 614 + u32 expected, found; 615 + int i; 616 + 617 + if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id)) 618 + return; 619 + 620 + found = intel_de_read(display, DMC_PROGRAM(dmc->dmc_info[dmc_id].start_mmioaddr, 0)); 621 + expected = dmc->dmc_info[dmc_id].payload[0]; 622 + 623 + drm_WARN(display->drm, found != expected, 624 + "DMC %d program storage start incorrect (expected 0x%x, current 0x%x)\n", 625 + dmc_id, expected, found); 626 + 627 + for (i = 0; i < dmc->dmc_info[dmc_id].mmio_count; i++) { 628 + i915_reg_t reg = dmc->dmc_info[dmc_id].mmioaddr[i]; 629 + 630 + found = intel_de_read(display, reg); 631 + expected = dmc_mmiodata(display, dmc, dmc_id, i); 632 + 633 + /* once set DMC_EVT_CTL_ENABLE can't be cleared :/ */ 634 + if (is_dmc_evt_ctl_reg(display, dmc_id, reg)) { 635 + found &= ~DMC_EVT_CTL_ENABLE; 636 + expected &= ~DMC_EVT_CTL_ENABLE; 637 + } 638 + 639 + drm_WARN(display->drm, found != expected, 640 + "DMC %d mmio[%d]/0x%x incorrect (expected 0x%x, current 0x%x)\n", 641 + dmc_id, i, i915_mmio_reg_offset(reg), expected, found); 642 + } 643 + } 644 + 645 + void assert_main_dmc_loaded(struct intel_display *display) 646 + { 647 + assert_dmc_loaded(display, DMC_FW_MAIN); 648 + } 649 + 610 650 static bool need_pipedmc_load_program(struct intel_display *display) 611 651 { 612 652 /* On TGL/derivatives pipe DMC state is lost when PG1 is disabled */ ··· 710 670 dmc_load_program(display, dmc_id); 711 671 else if (need_pipedmc_load_mmio(display, pipe)) 712 672 dmc_load_mmio(display, dmc_id); 673 + 674 + assert_dmc_loaded(display, dmc_id); 713 675 714 676 if (DISPLAY_VER(display) >= 20) { 715 677 intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display)); ··· 822 780 823 781 pipedmc_clock_gating_wa(display, true); 824 782 825 - for_each_dmc_id(dmc_id) 783 + for_each_dmc_id(dmc_id) { 826 784 dmc_load_program(display, dmc_id); 785 + assert_dmc_loaded(display, dmc_id); 786 + } 827 787 828 788 power_domains->dc_state = 0; 829 789 ··· 854 810 disable_all_event_handlers(display, dmc_id); 855 811 856 812 pipedmc_clock_gating_wa(display, false); 857 - } 858 - 859 - void assert_dmc_loaded(struct intel_display *display) 860 - { 861 - struct intel_dmc *dmc = display_to_dmc(display); 862 - 863 - drm_WARN_ONCE(display->drm, !dmc, "DMC not initialized\n"); 864 - drm_WARN_ONCE(display->drm, dmc && 865 - !intel_de_read(display, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)), 866 - "DMC program storage start is NULL\n"); 867 - drm_WARN_ONCE(display->drm, !intel_de_read(display, DMC_SSP_BASE), 868 - "DMC SSP Base Not fine\n"); 869 - drm_WARN_ONCE(display->drm, !intel_de_read(display, DMC_HTP_SKL), 870 - "DMC HTP Not fine\n"); 871 813 } 872 814 873 815 static bool fw_info_matches_stepping(const struct intel_fw_info *fw_info,
+1 -1
drivers/gpu/drm/i915/display/intel_dmc.h
··· 32 32 void intel_dmc_snapshot_print(const struct intel_dmc_snapshot *snapshot, struct drm_printer *p); 33 33 void intel_dmc_update_dc6_allowed_count(struct intel_display *display, bool start_tracking); 34 34 35 - void assert_dmc_loaded(struct intel_display *display); 35 + void assert_main_dmc_loaded(struct intel_display *display); 36 36 37 37 void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe); 38 38