diff options
Diffstat (limited to 'drivers/gpu')
158 files changed, 3138 insertions, 1094 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index f29c1d0ad4c1..458362e4ea01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1079,20 +1079,16 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) * S0ix even though the system is suspending to idle, so return false * in that case. */ - if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) dev_warn_once(adev->dev, "Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n" "To use suspend-to-idle change the sleep mode in BIOS setup.\n"); - return false; - } #if !IS_ENABLED(CONFIG_AMD_PMC) dev_warn_once(adev->dev, "Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n"); - return false; -#else - return true; #endif /* CONFIG_AMD_PMC */ + return true; } #endif /* CONFIG_SUSPEND */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5bee3ff62344..d376faad7696 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4031,7 +4031,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) amdgpu_gart_dummy_page_fini(adev); - amdgpu_device_unmap_mmio(adev); + if (drm_dev_is_unplugged(adev_to_drm(adev))) + amdgpu_device_unmap_mmio(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 7bb12a76631f..1bf31707e4f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2227,6 +2227,8 @@ amdgpu_pci_remove(struct pci_dev *pdev) struct drm_device *dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_to_adev(dev); + drm_dev_unplug(dev); + if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) { pm_runtime_get_sync(dev->dev); pm_runtime_forbid(dev->dev); @@ -2266,8 +2268,6 @@ amdgpu_pci_remove(struct pci_dev *pdev) amdgpu_driver_unload_kms(dev); - drm_dev_unplug(dev); - /* * Flush any in flight DMA operations from device. * Clear the Bus Master Enable bit and then wait on the PCIe Device diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index a8391f269cd0..40929f34447c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -606,12 +606,21 @@ psp_cmd_submit_buf(struct psp_context *psp, int timeout = 20000; bool ras_intr = false; bool skip_unsupport = false; + bool dev_entered; if (psp->adev->no_hw_access) return 0; - if (!drm_dev_enter(adev_to_drm(psp->adev), &idx)) - return 0; + dev_entered = drm_dev_enter(adev_to_drm(psp->adev), &idx); + /* + * We allow sending PSP messages LOAD_ASD and UNLOAD_TA without acquiring + * a lock in drm_dev_enter during driver unload because we must call + * drm_dev_unplug as the beginning of unload driver sequence . It is very + * crucial that userspace can't access device instances anymore. + */ + if (!dev_entered) + WARN_ON(psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_LOAD_ASD && + psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_UNLOAD_TA); memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); @@ -676,7 +685,8 @@ psp_cmd_submit_buf(struct psp_context *psp, } exit: - drm_dev_exit(idx); + if (dev_entered) + drm_dev_exit(idx); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index f39391e03d46..ca5a1d026f5a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -983,11 +983,9 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v if (offset == reg_access_ctrl->grbm_cntl) { /* if the target reg offset is grbm_cntl, write to scratch_reg2 */ writel(v, scratch_reg2); - writel(v, ((void __iomem *)adev->rmmio) + (offset * 4)); } else if (offset == reg_access_ctrl->grbm_idx) { /* if the target reg offset is grbm_idx, write to scratch_reg3 */ writel(v, scratch_reg3); - writel(v, ((void __iomem *)adev->rmmio) + (offset * 4)); } else { /* * SCRATCH_REG0 = read/write value diff --git a/drivers/gpu/drm/amd/amdgpu/df_v1_7.c b/drivers/gpu/drm/amd/amdgpu/df_v1_7.c index b991609f46c1..5dfab80ffff2 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v1_7.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v1_7.c @@ -94,7 +94,7 @@ static void df_v1_7_update_medium_grain_clock_gating(struct amdgpu_device *adev, WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp); } - /* Exit boradcast mode */ + /* Exit broadcast mode */ adev->df.funcs->enable_broadcast_mode(adev, false); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index c621b2ad7ba3..8ad8a0bffcac 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -754,8 +754,8 @@ static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, * zero here */ WARN_ON(simd != 0); - /* type 2 wave data */ - dst[(*no_fields)++] = 2; + /* type 3 wave data */ + dst[(*no_fields)++] = 3; dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_STATUS); dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_LO); dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_HI); diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c index fa42d1907dfa..7c069010ca9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0.c @@ -151,10 +151,11 @@ static void gfxhub_v3_0_init_system_aperture_regs(struct amdgpu_device *adev) { uint64_t value; - /* Disable AGP. */ + /* Program the AGP BAR */ WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0); - WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, 0); - WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BOT, 0x00FFFFFF); + WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); + WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); + /* Program the system aperture low logical page number. */ WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR, diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 5e0018fe7e7d..0a31a341aa43 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -673,6 +673,7 @@ static void gmc_v11_0_vram_gtt_location(struct amdgpu_device *adev, amdgpu_gmc_vram_location(adev, &adev->gmc, base); amdgpu_gmc_gart_location(adev, mc); + amdgpu_gmc_agp_location(adev, mc); /* base offset of vram pages */ if (amdgpu_sriov_vf(adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c index ae9cd1a4cfee..923fc09bc8fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c @@ -177,10 +177,11 @@ static void mmhub_v3_0_init_system_aperture_regs(struct amdgpu_device *adev) * these regs, and they will be programed at host. * so skip programing these regs. */ - /* Disable AGP. */ + /* Program the AGP BAR */ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BASE, 0); - WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, 0); - WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, 0x00FFFFFF); + WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); + WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); + /* Program the system aperture low logical page number. */ WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR, adev->gmc.vram_start >> 18); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c index c30e40e52fb2..51580302ec42 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c @@ -162,10 +162,10 @@ static void mmhub_v3_0_2_init_system_aperture_regs(struct amdgpu_device *adev) uint64_t value; uint32_t tmp; - /* Disable AGP. */ + /* Program the AGP BAR */ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BASE, 0); - WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, 0); - WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, 0x00FFFFFF); + WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); + WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); if (!amdgpu_sriov_vf(adev)) { /* diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c index 15eb3658d70e..09fdcd20cb91 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c @@ -337,7 +337,13 @@ const struct nbio_hdp_flush_reg nbio_v4_3_hdp_flush_reg = { static void nbio_v4_3_init_registers(struct amdgpu_device *adev) { - return; + if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(4, 3, 0)) { + uint32_t data; + + data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2); + data &= ~RCC_DEV0_EPF2_STRAP2__STRAP_NO_SOFT_RESET_DEV0_F2_MASK; + WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2, data); + } } static u32 nbio_v4_3_get_rom_offset(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index e03cf7f766c5..477be4b62bc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -676,7 +676,8 @@ static int soc21_common_early_init(void *handle) AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_REPEATER_FGCG | - AMD_CG_SUPPORT_GFX_MGCG; + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_HDP_SD; adev->pg_flags = AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_JPEG; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e1d63826927a..f26beb0e0e1d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -106,7 +106,6 @@ #include "modules/inc/mod_freesync.h" #include "modules/power/power_helpers.h" -#include "modules/inc/mod_info_packet.h" #define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB); @@ -1186,24 +1185,38 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_ memset(pa_config, 0, sizeof(*pa_config)); - logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; - pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); - - if (adev->apu_flags & AMD_APU_IS_RAVEN2) - /* - * Raven2 has a HW issue that it is unable to use the vram which - * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the - * workaround that increase system aperture high address (add 1) - * to get rid of the VM fault and hardware hang. - */ - logical_addr_high = max((adev->gmc.fb_end >> 18) + 0x1, adev->gmc.agp_end >> 18); - else - logical_addr_high = max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18; - agp_base = 0; agp_bot = adev->gmc.agp_start >> 24; agp_top = adev->gmc.agp_end >> 24; + /* AGP aperture is disabled */ + if (agp_bot == agp_top) { + logical_addr_low = adev->gmc.vram_start >> 18; + if (adev->apu_flags & AMD_APU_IS_RAVEN2) + /* + * Raven2 has a HW issue that it is unable to use the vram which + * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the + * workaround that increase system aperture high address (add 1) + * to get rid of the VM fault and hardware hang. + */ + logical_addr_high = (adev->gmc.fb_end >> 18) + 0x1; + else + logical_addr_high = adev->gmc.vram_end >> 18; + } else { + logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; + if (adev->apu_flags & AMD_APU_IS_RAVEN2) + /* + * Raven2 has a HW issue that it is unable to use the vram which + * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the + * workaround that increase system aperture high address (add 1) + * to get rid of the VM fault and hardware hang. + */ + logical_addr_high = max((adev->gmc.fb_end >> 18) + 0x1, adev->gmc.agp_end >> 18); + else + logical_addr_high = max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18; + } + + pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); page_table_start.high_part = (u32)(adev->gmc.gart_start >> 44) & 0xF; page_table_start.low_part = (u32)(adev->gmc.gart_start >> 12); @@ -1302,10 +1315,28 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work) else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) && dc_link_check_link_loss_status(dc_link, &offload_work->data) && dc_link_dp_allow_hpd_rx_irq(dc_link)) { - dc_link_dp_handle_link_loss(dc_link); + /* offload_work->data is from handle_hpd_rx_irq-> + * schedule_hpd_rx_offload_work.this is defer handle + * for hpd short pulse. upon here, link status may be + * changed, need get latest link status from dpcd + * registers. if link status is good, skip run link + * training again. + */ + union hpd_irq_data irq_data; + + memset(&irq_data, 0, sizeof(irq_data)); + + /* before dc_link_dp_handle_link_loss, allow new link lost handle + * request be added to work queue if link lost at end of dc_link_ + * dp_handle_link_loss + */ spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags); offload_work->offload_wq->is_handling_link_loss = false; spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags); + + if ((dp_read_hpd_rx_irq_data(dc_link, &irq_data) == DC_OK) && + dc_link_check_link_loss_status(dc_link, &irq_data)) + dc_link_dp_handle_link_loss(dc_link); } mutex_unlock(&adev->dm.dc_lock); @@ -1535,10 +1566,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) (adev->apu_flags & AMD_APU_IS_PICASSO)) init_data.flags.gpu_vm_support = true; break; - case IP_VERSION(2, 1, 0): case IP_VERSION(3, 0, 1): - case IP_VERSION(3, 1, 2): - case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 4): case IP_VERSION(3, 1, 6): init_data.flags.gpu_vm_support = true; break; @@ -1623,6 +1652,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ adev->dm.dc->debug.ignore_cable_id = true; + if (adev->dm.dc->caps.dp_hdmi21_pcon_support) + DRM_INFO("DP-HDMI FRL PCON supported\n"); + r = dm_dmub_hw_init(adev); if (r) { DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); @@ -3235,7 +3267,7 @@ static void handle_hpd_rx_irq(void *param) union hpd_irq_data hpd_irq_data; bool link_loss = false; bool has_left_work = false; - int idx = aconnector->base.index; + int idx = dc_link->link_index; struct hpd_rx_irq_offload_work_queue *offload_wq = &adev->dm.hpd_rx_offload_wq[idx]; memset(&hpd_irq_data, 0, sizeof(hpd_irq_data)); @@ -3377,7 +3409,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev) (void *) aconnector); if (adev->dm.hpd_rx_offload_wq) - adev->dm.hpd_rx_offload_wq[connector->index].aconnector = + adev->dm.hpd_rx_offload_wq[dc_link->link_index].aconnector = aconnector; } } @@ -4572,6 +4604,17 @@ static int dm_init_microcode(struct amdgpu_device *adev) static int dm_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_mode_info *mode_info = &adev->mode_info; + struct atom_context *ctx = mode_info->atom_context; + int index = GetIndexIntoMasterTable(DATA, Object_Header); + u16 data_offset; + + /* if there is no object header, skip DM */ + if (!amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { + adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK; + dev_info(adev->dev, "No object header, skipping DM\n"); + return -ENOENT; + } switch (adev->asic_type) { #if defined(CONFIG_DRM_AMD_DC_SI) @@ -6334,7 +6377,6 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc, dc_plane_state->plane_size.surface_size.width = stream->src.width; dc_plane_state->plane_size.chroma_size.height = stream->src.height; dc_plane_state->plane_size.chroma_size.width = stream->src.width; - dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN; dc_plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN; dc_plane_state->rotation = ROTATION_ANGLE_0; @@ -7113,6 +7155,9 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, aconnector->base.dpms = DRM_MODE_DPMS_OFF; aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ aconnector->audio_inst = -1; + aconnector->pack_sdp_v1_3 = false; + aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE; + memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info)); mutex_init(&aconnector->hpd_lock); /* @@ -7603,6 +7648,8 @@ static void update_freesync_state_on_stream( struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc); unsigned long flags; bool pack_sdp_v1_3 = false; + struct amdgpu_dm_connector *aconn; + enum vrr_packet_type packet_type = PACKET_TYPE_VRR; if (!new_stream) return; @@ -7638,11 +7685,27 @@ static void update_freesync_state_on_stream( } } + aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context; + + if (aconn && aconn->as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) { + pack_sdp_v1_3 = aconn->pack_sdp_v1_3; + + if (aconn->vsdb_info.amd_vsdb_version == 1) + packet_type = PACKET_TYPE_FS_V1; + else if (aconn->vsdb_info.amd_vsdb_version == 2) + packet_type = PACKET_TYPE_FS_V2; + else if (aconn->vsdb_info.amd_vsdb_version == 3) + packet_type = PACKET_TYPE_FS_V3; + + mod_build_adaptive_sync_infopacket(new_stream, aconn->as_type, NULL, + &new_stream->adaptive_sync_infopacket); + } + mod_freesync_build_vrr_infopacket( dm->freesync_module, new_stream, &vrr_params, - PACKET_TYPE_VRR, + packet_type, TRANSFER_FUNC_UNKNOWN, &vrr_infopacket, pack_sdp_v1_3); @@ -10311,6 +10374,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_hdmi_vsdb_info vsdb_info = {0}; bool freesync_capable = false; + enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; if (!connector->state) { DRM_ERROR("%s - Connector has no state", __func__); @@ -10403,6 +10467,26 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, } } + as_type = dm_get_adaptive_sync_support_type(amdgpu_dm_connector->dc_link); + + if (as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) { + i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); + if (i >= 0 && vsdb_info.freesync_supported && vsdb_info.amd_vsdb_version > 0) { + + amdgpu_dm_connector->pack_sdp_v1_3 = true; + amdgpu_dm_connector->as_type = as_type; + amdgpu_dm_connector->vsdb_info = vsdb_info; + + amdgpu_dm_connector->min_vfreq = vsdb_info.min_refresh_rate_hz; + amdgpu_dm_connector->max_vfreq = vsdb_info.max_refresh_rate_hz; + if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) + freesync_capable = true; + + connector->display_info.monitor_range.min_vfreq = vsdb_info.min_refresh_rate_hz; + connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz; + } + } + update: if (dm_con_state) dm_con_state->freesync_capable = freesync_capable; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index d89f2eaf9117..ed5cbe9da40c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -59,6 +59,7 @@ #include "irq_types.h" #include "signal_types.h" #include "amdgpu_dm_crc.h" +#include "mod_info_packet.h" struct aux_payload; struct set_config_cmd_payload; enum aux_return_code_type; @@ -577,6 +578,36 @@ enum mst_progress_status { MST_CLEAR_ALLOCATED_PAYLOAD = BIT(3), }; +/** + * struct amdgpu_hdmi_vsdb_info - Keep track of the VSDB info + * + * AMDGPU supports FreeSync over HDMI by using the VSDB section, and this + * struct is useful to keep track of the display-specific information about + * FreeSync. + */ +struct amdgpu_hdmi_vsdb_info { + /** + * @amd_vsdb_version: Vendor Specific Data Block Version, should be + * used to determine which Vendor Specific InfoFrame (VSIF) to send. + */ + unsigned int amd_vsdb_version; + + /** + * @freesync_supported: FreeSync Supported. + */ + bool freesync_supported; + + /** + * @min_refresh_rate_hz: FreeSync Minimum Refresh Rate in Hz. + */ + unsigned int min_refresh_rate_hz; + + /** + * @max_refresh_rate_hz: FreeSync Maximum Refresh Rate in Hz + */ + unsigned int max_refresh_rate_hz; +}; + struct amdgpu_dm_connector { struct drm_connector base; @@ -649,6 +680,11 @@ struct amdgpu_dm_connector { /* Automated testing */ bool timing_changed; struct dc_crtc_timing *timing_requested; + + /* Adaptive Sync */ + bool pack_sdp_v1_3; + enum adaptive_sync_type as_type; + struct amdgpu_hdmi_vsdb_info vsdb_info; }; static inline void amdgpu_dm_set_mst_status(uint8_t *status, @@ -719,37 +755,6 @@ struct dm_connector_state { uint64_t pbn; }; -/** - * struct amdgpu_hdmi_vsdb_info - Keep track of the VSDB info - * - * AMDGPU supports FreeSync over HDMI by using the VSDB section, and this - * struct is useful to keep track of the display-specific information about - * FreeSync. - */ -struct amdgpu_hdmi_vsdb_info { - /** - * @amd_vsdb_version: Vendor Specific Data Block Version, should be - * used to determine which Vendor Specific InfoFrame (VSIF) to send. - */ - unsigned int amd_vsdb_version; - - /** - * @freesync_supported: FreeSync Supported. - */ - bool freesync_supported; - - /** - * @min_refresh_rate_hz: FreeSync Minimum Refresh Rate in Hz. - */ - unsigned int min_refresh_rate_hz; - - /** - * @max_refresh_rate_hz: FreeSync Maximum Refresh Rate in Hz - */ - unsigned int max_refresh_rate_hz; -}; - - #define to_dm_connector_state(x)\ container_of((x), struct dm_connector_state, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 180d3893b68d..70081c58630f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -403,6 +403,7 @@ bool dm_helpers_dp_mst_start_top_mgr( bool boot) { struct amdgpu_dm_connector *aconnector = link->priv; + int ret; if (!aconnector) { DRM_ERROR("Failed to find connector for link!"); @@ -418,7 +419,16 @@ bool dm_helpers_dp_mst_start_top_mgr( DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); - return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0); + ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); + if (ret < 0) { + DRM_ERROR("DM_MST: Failed to set the device into MST mode!"); + return false; + } + + DRM_INFO("DM_MST: DP%x, %d-lane link detected\n", aconnector->mst_mgr.dpcd[0], + aconnector->mst_mgr.dpcd[2] & DP_MAX_LANE_COUNT_MASK); + + return true; } bool dm_helpers_dp_mst_stop_top_mgr( @@ -1133,3 +1143,36 @@ void dm_helpers_dp_mst_update_branch_bandwidth( // TODO } +static bool dm_is_freesync_pcon_whitelist(const uint32_t branch_dev_id) +{ + bool ret_val = false; + + switch (branch_dev_id) { + case DP_BRANCH_DEVICE_ID_0060AD: + ret_val = true; + break; + default: + break; + } + + return ret_val; +} + +enum adaptive_sync_type dm_get_adaptive_sync_support_type(struct dc_link *link) +{ + struct dpcd_caps *dpcd_caps = &link->dpcd_caps; + enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; + + switch (dpcd_caps->dongle_type) { + case DISPLAY_DONGLE_DP_HDMI_CONVERTER: + if (dpcd_caps->adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT == true && + dpcd_caps->allow_invalid_MSA_timing_param == true && + dm_is_freesync_pcon_whitelist(dpcd_caps->branch_dev_id)) + as_type = FREESYNC_TYPE_PCON_IN_WHITELIST; + break; + default: + break; + } + + return as_type; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 0bff2cc20b02..33f53cae939d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -177,6 +177,9 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector) if (dc_link->sink_count) dc_link_remove_remote_sink(dc_link, dc_sink); + DC_LOG_MST("DM_MST: remove remote sink 0x%p, %d remaining\n", + dc_sink, dc_link->sink_count); + dc_sink_release(dc_sink); aconnector->dc_sink = NULL; aconnector->edid = NULL; @@ -308,6 +311,9 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) return 0; } + DC_LOG_MST("DM_MST: add remote sink 0x%p, %d remaining\n", + dc_sink, aconnector->dc_link->sink_count); + dc_sink->priv = aconnector; aconnector->dc_sink = dc_sink; } @@ -341,6 +347,9 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) return 0; } + DC_LOG_MST("DM_MST: add remote sink 0x%p, %d remaining\n", + dc_sink, aconnector->dc_link->sink_count); + dc_sink->priv = aconnector; /* dc_link_add_remote_sink returns a new reference */ aconnector->dc_sink = dc_sink; @@ -458,6 +467,9 @@ dm_dp_mst_detect(struct drm_connector *connector, if (aconnector->dc_link->sink_count) dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink); + DC_LOG_MST("DM_MST: remove remote sink 0x%p, %d remaining\n", + aconnector->dc_link, aconnector->dc_link->sink_count); + dc_sink_release(aconnector->dc_sink); aconnector->dc_sink = NULL; aconnector->edid = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 89df7244b272..f5276bacfa4e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -572,10 +572,11 @@ static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *cl { struct clk_bw_params *bw_params = clk_mgr->base.bw_params; struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; - uint32_t max_pstate = 0, max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0; + uint32_t max_pstate = 0, max_fclk = 0, max_dispclk = 0, max_dppclk = 0; + uint32_t min_pstate = 0, min_fclk = clock_table->DfPstateTable[0].FClk; int i; - /* Find highest valid fclk pstate */ + /* Find highest and lowest valid fclk pstate */ for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) { if (is_valid_clock_value(clock_table->DfPstateTable[i].FClk) && clock_table->DfPstateTable[i].FClk > max_fclk) { @@ -584,6 +585,14 @@ static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *cl } } + for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) { + if (is_valid_clock_value(clock_table->DfPstateTable[i].FClk) && + clock_table->DfPstateTable[i].FClk < min_fclk) { + min_fclk = clock_table->DfPstateTable[i].FClk; + min_pstate = i; + } + } + /* We expect the table to contain at least one valid fclk entry. */ ASSERT(is_valid_clock_value(max_fclk)); @@ -599,15 +608,17 @@ static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *cl /* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */ for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { - uint32_t min_fclk = clock_table->DfPstateTable[0].FClk; + uint32_t max_level_fclk = clock_table->DfPstateTable[0].FClk; + uint32_t max_level_pstate = 0; int j; + /* Look for the maximum supported FCLK for the current voltage. */ for (j = 1; j < clock_table->NumDfPstatesEnabled; j++) { if (is_valid_clock_value(clock_table->DfPstateTable[j].FClk) && - clock_table->DfPstateTable[j].FClk < min_fclk && + clock_table->DfPstateTable[j].FClk > max_level_fclk && clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]) { - min_fclk = clock_table->DfPstateTable[j].FClk; - min_pstate = j; + max_level_fclk = clock_table->DfPstateTable[j].FClk; + max_level_pstate = j; } } @@ -621,15 +632,15 @@ static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *cl bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; /* Now update clocks we do read */ - bw_params->clk_table.entries[i].fclk_mhz = min_fclk; - bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk; - bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[min_pstate].Voltage; + bw_params->clk_table.entries[i].fclk_mhz = max_level_fclk; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_level_pstate].MemClk; + bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[max_level_pstate].Voltage; bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk; bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk; bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio( - clock_table->DfPstateTable[min_pstate].WckRatio); + clock_table->DfPstateTable[max_level_pstate].WckRatio); } /* Make sure to include at least one entry at highest pstate */ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 8c368bcc8e7e..43d1f38b94ce 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -87,16 +87,6 @@ static int dcn315_get_active_display_cnt_wa( return display_count; } -bool should_disable_otg(struct pipe_ctx *pipe) -{ - bool ret = true; - - if (pipe->stream->link->link_enc && pipe->stream->link->link_enc->funcs->is_dig_enabled && - pipe->stream->link->link_enc->funcs->is_dig_enabled(pipe->stream->link->link_enc)) - ret = false; - return ret; -} - static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; @@ -108,16 +98,12 @@ static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state if (pipe->top_pipe || pipe->prev_odm_pipe) continue; if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL || - dc_is_virtual_signal(pipe->stream->signal))) { - - /* This w/a should not trigger when we have a dig active */ - if (should_disable_otg(pipe)) { - if (disable) { - pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); - reset_sync_context_for_pipe(dc, context, i); - } else - pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); - } + dc_is_virtual_signal(pipe->stream->signal))) { + if (disable) { + pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + reset_sync_context_for_pipe(dc, context, i); + } else + pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); } } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 6475664baa8a..1a2ab934b4bd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -46,7 +46,6 @@ #include "dpcd_defs.h" #include "dmcu.h" #include "dsc.h" -#include "opp.h" #include "hw/clk_mgr.h" #include "dce/dmub_psr.h" #include "dmub/dmub_srv.h" diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 42ce45306483..2e23fd8b4e9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.220" +#define DC_VER "3.2.221" #define MAX_SURFACES 3 #define MAX_PLANES 6 diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 848db8676adf..cc3d6fb39364 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -797,6 +797,29 @@ enum dc_timing_3d_format { TIMING_3D_FORMAT_MAX, }; +#define DC_DSC_QP_SET_SIZE 15 +#define DC_DSC_RC_BUF_THRESH_SIZE 14 +struct dc_dsc_rc_params_override { + int32_t rc_model_size; + int32_t rc_buf_thresh[DC_DSC_RC_BUF_THRESH_SIZE]; + int32_t rc_minqp[DC_DSC_QP_SET_SIZE]; + int32_t rc_maxqp[DC_DSC_QP_SET_SIZE]; + int32_t rc_offset[DC_DSC_QP_SET_SIZE]; + + int32_t rc_tgt_offset_hi; + int32_t rc_tgt_offset_lo; + int32_t rc_edge_factor; + int32_t rc_quant_incr_limit0; + int32_t rc_quant_incr_limit1; + + int32_t initial_fullness_offset; + int32_t initial_delay; + + int32_t flatness_min_qp; + int32_t flatness_max_qp; + int32_t flatness_det_thresh; +}; + struct dc_dsc_config { uint32_t num_slices_h; /* Number of DSC slices - horizontal */ uint32_t num_slices_v; /* Number of DSC slices - vertical */ @@ -811,6 +834,7 @@ struct dc_dsc_config { #endif bool is_dp; /* indicate if DSC is applied based on DP's capability */ uint32_t mst_pbn; /* pbn of display on dsc mst hub */ + const struct dc_dsc_rc_params_override *rc_params_ovrd; /* DM owned memory. If not NULL, apply custom dsc rc params */ }; /** diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 1927eacbfa71..64d5d9b28ca6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -433,6 +433,9 @@ void dc_link_dp_handle_link_loss(struct dc_link *link); bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link); bool dc_link_check_link_loss_status(struct dc_link *link, union hpd_irq_data *hpd_irq_dpcd_data); +enum dc_status dp_read_hpd_rx_irq_data( + struct dc_link *link, + union hpd_irq_data *irq_data); struct dc_sink_init_data; struct dc_sink *dc_link_add_remote_sink( @@ -627,4 +630,31 @@ struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); +/* + * USB4 DPIA BW ALLOCATION PUBLIC FUNCTIONS + */ +/* + * Send a request from DP-Tx requesting to allocate BW remotely after + * allocating it locally. This will get processed by CM and a CB function + * will be called. + * + * @link: pointer to the dc_link struct instance + * @req_bw: The requested bw in Kbyte to allocated + * + * return: none + */ +void dc_link_set_usb4_req_bw_req(struct dc_link *link, int req_bw); + +/* + * CB function for when the status of the Req above is complete. We will + * find out the result of allocating on CM and update structs accordingly + * + * @link: pointer to the dc_link struct instance + * @bw: Allocated or Estimated BW depending on the result + * @result: Response type + * + * return: none + */ +void dc_link_get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t result); + #endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bb155734ac93..f735ae5e045f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2899,7 +2899,7 @@ void dcn10_blank_pixel_data( dc->hwss.set_pipe(pipe_ctx); stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level); } - } else if (blank) { + } else { dc->hwss.set_abm_immediate_disable(pipe_ctx); if (stream_res->tg->funcs->set_blank) { stream_res->tg->funcs->wait_for_state(stream_res->tg, CRTC_STATE_VBLANK); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c index c08c01e05dcf..42344aec60d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c @@ -28,6 +28,7 @@ #include "reg_helper.h" #include "dcn20_dsc.h" #include "dsc/dscc_types.h" +#include "dsc/rc_calc.h" static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps); static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals, @@ -344,10 +345,38 @@ static void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_co } } +static void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_override *override) +{ + uint8_t i; + + rc->rc_model_size = override->rc_model_size; + for (i = 0; i < DC_DSC_RC_BUF_THRESH_SIZE; i++) + rc->rc_buf_thresh[i] = override->rc_buf_thresh[i]; + for (i = 0; i < DC_DSC_QP_SET_SIZE; i++) { + rc->qp_min[i] = override->rc_minqp[i]; + rc->qp_max[i] = override->rc_maxqp[i]; + rc->ofs[i] = override->rc_offset[i]; + } + + rc->rc_tgt_offset_hi = override->rc_tgt_offset_hi; + rc->rc_tgt_offset_lo = override->rc_tgt_offset_lo; + rc->rc_edge_factor = override->rc_edge_factor; + rc->rc_quant_incr_limit0 = override->rc_quant_incr_limit0; + rc->rc_quant_incr_limit1 = override->rc_quant_incr_limit1; + + rc->initial_fullness_offset = override->initial_fullness_offset; + rc->initial_xmit_delay = override->initial_delay; + + rc->flatness_min_qp = override->flatness_min_qp; + rc->flatness_max_qp = override->flatness_max_qp; + rc->flatness_det_thresh = override->flatness_det_thresh; +} + static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals, struct dsc_optc_config *dsc_optc_cfg) { struct dsc_parameters dsc_params; + struct rc_params rc; /* Validate input parameters */ ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h); @@ -412,7 +441,12 @@ static bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_ dsc_reg_vals->pps.native_420 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420); dsc_reg_vals->pps.simple_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422); - if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &dsc_params)) { + calc_rc_params(&rc, &dsc_reg_vals->pps); + + if (dsc_cfg->dc_dsc_cfg.rc_params_ovrd) + dsc_override_rc_params(&rc, dsc_cfg->dc_dsc_cfg.rc_params_ovrd); + + if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &rc, &dsc_params)) { dm_output_to_console("%s: DSC config failed\n", __func__); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 916dceecd3de..cb8edb14603a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1777,6 +1777,15 @@ static void dcn20_program_pipe( &pipe_ctx->stream->bit_depth_params, &pipe_ctx->stream->clamping); } + + /* Set ABM pipe after other pipe configurations done */ + if (pipe_ctx->plane_state->visible) { + if (pipe_ctx->stream_res.abm) { + dc->hwss.set_pipe(pipe_ctx); + pipe_ctx->stream_res.abm->funcs->set_abm_level(pipe_ctx->stream_res.abm, + pipe_ctx->stream->abm_level); + } + } } void dcn20_program_front_end_for_ctx( diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 531f405d2554..3af24ef9cb2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -2225,14 +2225,10 @@ enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_stat enum surface_pixel_format surf_pix_format = plane_state->format; unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format); - enum swizzle_mode_values swizzle = DC_SW_LINEAR; - + plane_state->tiling_info.gfx9.swizzle = DC_SW_64KB_S; if (bpp == 64) - swizzle = DC_SW_64KB_D; - else - swizzle = DC_SW_64KB_S; + plane_state->tiling_info.gfx9.swizzle = DC_SW_64KB_D; - plane_state->tiling_info.gfx9.swizzle = swizzle; return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index fbcf0afeae0d..8f9244fe5c86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1393,15 +1393,13 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) static enum dc_status dcn21_patch_unknown_plane_state(struct dc_plane_state *plane_state) { - enum dc_status result = DC_OK; - if (plane_state->ctx->dc->debug.disable_dcc == DCC_ENABLE) { plane_state->dcc.enable = 1; /* align to our worst case block width */ plane_state->dcc.meta_pitch = ((plane_state->src_rect.width + 1023) / 1024) * 1024; } - result = dcn20_patch_unknown_plane_state(plane_state); - return result; + + return dcn20_patch_unknown_plane_state(plane_state); } static const struct resource_funcs dcn21_res_pool_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index f9ea1e86707f..79850a68f62a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -874,8 +874,9 @@ static const struct dc_plane_cap plane_cap = { }, // 6:1 downscaling ratio: 1000/6 = 166.666 + // 4:1 downscaling ratio for ARGB888 to prevent underflow during P010 playback: 1000/4 = 250 .max_downscale_factor = { - .argb8888 = 167, + .argb8888 = 250, .nv12 = 167, .fp16 = 167 }, @@ -1763,7 +1764,7 @@ static bool dcn314_resource_construct( pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; + dc->caps.max_downscale_ratio = 400; dc->caps.i2c_speed_in_khz = 100; dc->caps.i2c_speed_in_khz_hdcp = 100; dc->caps.max_cursor_size = 256; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c index 330d7cbc7398..a02918eaa2c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c @@ -94,7 +94,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, .apply_idle_power_optimizations = dcn32_apply_idle_power_optimizations, - .does_plane_fit_in_mall = dcn30_does_plane_fit_in_mall, + .does_plane_fit_in_mall = NULL, .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .hardware_release = dcn30_hardware_release, diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index fd57e0167737..55f918b44077 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1714,7 +1714,6 @@ static bool dcn321_resource_construct( dc->caps.mall_size_per_mem_channel * 1024 * 1024; dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; - dc->caps.max_cab_allocation_bytes = 33554432; // 32MB = 1024 * 1024 * 32 dc->caps.subvp_fw_processing_delay_us = 15; dc->caps.subvp_drr_max_vblank_margin_us = 40; dc->caps.subvp_prefetch_end_to_mall_start_us = 15; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index c624c768cc3d..7ce9a5b6c33b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -199,6 +199,7 @@ int dm_helpers_dmub_set_config_sync(struct dc_context *ctx, const struct dc_link *link, struct set_config_cmd_payload *payload, enum set_config_status *operation_result); +enum adaptive_sync_type dm_get_adaptive_sync_support_type(struct dc_link *link); enum dc_edid_status dm_helpers_get_sbios_edid(struct dc_link *link, struct dc_edid *edid); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 197df404761a..d3ba65efe1d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -949,7 +949,6 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc int plane_count; int i; unsigned int optimized_min_dst_y_next_start_us; - bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > 1000.0; plane_count = 0; optimized_min_dst_y_next_start_us = 0; @@ -974,6 +973,8 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { struct dc_link *link = context->streams[0]->sink->link; struct dc_stream_status *stream_status = &context->stream_status[0]; + bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > 1000.0; + bool is_pwrseq0 = link->link_index == 0; if (dc_extended_blank_supported(dc)) { for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -986,18 +987,17 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc } } } - /* zstate only supported on PWRSEQ0 and when there's <2 planes*/ - if (link->link_index != 0 || stream_status->plane_count > 1) + + /* Don't support multi-plane configurations */ + if (stream_status->plane_count > 1) return DCN_ZSTATE_SUPPORT_DISALLOW; - if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000) + if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000)) return DCN_ZSTATE_SUPPORT_ALLOW; - else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr) + else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr) return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; else return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW; - } else if (allow_z8) { - return DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY; } else { return DCN_ZSTATE_SUPPORT_DISALLOW; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index 950669f2c10d..cb7c0c878423 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -3183,7 +3183,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } else { v->MIN_DST_Y_NEXT_START[k] = v->VTotal[k] - v->VFrontPorch[k] + v->VTotal[k] - v->VActive[k] - v->VStartup[k]; } - v->MIN_DST_Y_NEXT_START[k] += dml_floor(4.0 * v->TSetup[k] / (double)v->HTotal[k] / v->PixelClock[k], 1.0) / 4.0; + v->MIN_DST_Y_NEXT_START[k] += dml_floor(4.0 * v->TSetup[k] / ((double)v->HTotal[k] / v->PixelClock[k]), 1.0) / 4.0; if (((v->VUpdateOffsetPix[k] + v->VUpdateWidthPix[k] + v->VReadyOffsetPix[k]) / v->HTotal[k]) <= (isInterlaceTiming ? dml_floor((v->VTotal[k] - v->VActive[k] - v->VFrontPorch[k] - v->VStartup[k]) / 2.0, 1.0) : diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 0dc1a03999b6..27b62ef4f62d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1400,7 +1400,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, /* SS PSR On: all active surfaces part of streams not supporting PSR stored in MALL */ context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes; } - } else if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) { + } else { /* SUBVP: phantom surfaces only stored in MALL */ context->bw_ctx.bw.dcn.mall_subvp_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes; } @@ -2126,6 +2126,10 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, */ context->bw_ctx.bw.dcn.watermarks.a = context->bw_ctx.bw.dcn.watermarks.c; context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 0; + /* Calculate FCLK p-state change watermark based on FCLK pstate change latency in case + * UCLK p-state is not supported, to avoid underflow in case FCLK pstate is supported + */ + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; } else { /* Set A: * All clocks min. diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h b/drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h index ad80bde9bc0f..31574940ccc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/dscc_types.h @@ -46,7 +46,10 @@ struct dsc_parameters { uint32_t rc_buffer_model_size; }; -int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params); +struct rc_params; +int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, + const struct rc_params *rc, + struct dsc_parameters *dsc_params); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c index f0aea988fef0..36d6c1646a51 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c @@ -95,19 +95,19 @@ static void copy_rc_to_cfg(struct drm_dsc_config *dsc_cfg, const struct rc_param dsc_cfg->rc_buf_thresh[i] = rc->rc_buf_thresh[i]; } -int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, struct dsc_parameters *dsc_params) +int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, + const struct rc_params *rc, + struct dsc_parameters *dsc_params) { int ret; - struct rc_params rc; struct drm_dsc_config dsc_cfg; unsigned long long tmp; - calc_rc_params(&rc, pps); dsc_params->pps = *pps; - dsc_params->pps.initial_scale_value = 8 * rc.rc_model_size / (rc.rc_model_size - rc.initial_fullness_offset); + dsc_params->pps.initial_scale_value = 8 * rc->rc_model_size / (rc->rc_model_size - rc->initial_fullness_offset); copy_pps_fields(&dsc_cfg, &dsc_params->pps); - copy_rc_to_cfg(&dsc_cfg, &rc); + copy_rc_to_cfg(&dsc_cfg, rc); dsc_cfg.mux_word_size = dsc_params->pps.bits_per_component <= 10 ? 48 : 64; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h index 58eb7b581093..832a6dd2c5fa 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h @@ -45,30 +45,6 @@ enum bw_type { bool set_dptx_usb4_bw_alloc_support(struct dc_link *link); /* - * Send a request from DP-Tx requesting to allocate BW remotely after - * allocating it locally. This will get processed by CM and a CB function - * will be called. - * - * @link: pointer to the dc_link struct instance - * @req_bw: The requested bw in Kbyte to allocated - * - * return: none - */ -void set_usb4_req_bw_req(struct dc_link *link, int req_bw); - -/* - * CB function for when the status of the Req above is complete. We will - * find out the result of allocating on CM and update structs accordingly - * - * @link: pointer to the dc_link struct instance - * @bw: Allocated or Estimated BW depending on the result - * @result: Response type - * - * return: none - */ -void get_usb4_req_bw_resp(struct dc_link *link, uint8_t bw, uint8_t result); - -/* * Return the response_ready flag from dc_link struct * * @link: pointer to the dc_link struct instance diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 4a122925c3ae..92c18bfb98b3 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -532,6 +532,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, if (dmub->hw_funcs.reset) dmub->hw_funcs.reset(dmub); + /* reset the cache of the last wptr as well now that hw is reset */ + dmub->inbox1_last_wptr = 0; + cw0.offset.quad_part = inst_fb->gpu_addr; cw0.region.base = DMUB_CW0_BASE; cw0.region.top = cw0.region.base + inst_fb->size - 1; @@ -649,6 +652,15 @@ enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub) if (dmub->hw_funcs.reset) dmub->hw_funcs.reset(dmub); + /* mailboxes have been reset in hw, so reset the sw state as well */ + dmub->inbox1_last_wptr = 0; + dmub->inbox1_rb.wrpt = 0; + dmub->inbox1_rb.rptr = 0; + dmub->outbox0_rb.wrpt = 0; + dmub->outbox0_rb.rptr = 0; + dmub->outbox1_rb.wrpt = 0; + dmub->outbox1_rb.rptr = 0; + dmub->hw_init = false; return DMUB_STATUS_OK; diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 3610f71891a3..31a12ce79a8e 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -35,6 +35,7 @@ #define DP_BRANCH_DEVICE_ID_00E04C 0x00E04C #define DP_BRANCH_DEVICE_ID_006037 0x006037 #define DP_BRANCH_DEVICE_ID_001CF8 0x001CF8 +#define DP_BRANCH_DEVICE_ID_0060AD 0x0060AD #define DP_BRANCH_HW_REV_10 0x10 #define DP_BRANCH_HW_REV_20 0x20 diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index 91fe039c0c95..66dc9a19aebe 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -44,8 +44,8 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, enum adaptive_sync_type { ADAPTIVE_SYNC_TYPE_NONE = 0, ADAPTIVE_SYNC_TYPE_DP = 1, - ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST = 2, - ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST = 3, + FREESYNC_TYPE_PCON_IN_WHITELIST = 2, + FREESYNC_TYPE_PCON_NOT_IN_WHITELIST = 3, ADAPTIVE_SYNC_TYPE_EDP = 4, }; diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index a8a31d0a7a7f..ec64f19e1786 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -533,11 +533,11 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, if (stream != NULL) mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet); break; - case ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST: + case FREESYNC_TYPE_PCON_IN_WHITELIST: mod_build_adaptive_sync_infopacket_v1(info_packet); break; case ADAPTIVE_SYNC_TYPE_NONE: - case ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST: + case FREESYNC_TYPE_PCON_NOT_IN_WHITELIST: default: break; } diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 76b9ec64ca50..bd060697d982 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2007,14 +2007,16 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ gc_ver == IP_VERSION(10, 3, 0) || gc_ver == IP_VERSION(10, 1, 2) || gc_ver == IP_VERSION(11, 0, 0) || - gc_ver == IP_VERSION(11, 0, 2))) + gc_ver == IP_VERSION(11, 0, 2) || + gc_ver == IP_VERSION(11, 0, 3))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { if (!(gc_ver == IP_VERSION(10, 3, 1) || gc_ver == IP_VERSION(10, 3, 0) || gc_ver == IP_VERSION(10, 1, 2) || gc_ver == IP_VERSION(11, 0, 0) || - gc_ver == IP_VERSION(11, 0, 2))) + gc_ver == IP_VERSION(11, 0, 2) || + gc_ver == IP_VERSION(11, 0, 3))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index ec52830dde24..8bae3fe869cd 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1498,6 +1498,20 @@ static int smu_disable_dpms(struct smu_context *smu) } /* + * For SMU 13.0.4/11, PMFW will handle the features disablement properly + * for gpu reset case. Driver involvement is unnecessary. + */ + if (amdgpu_in_reset(adev)) { + switch (adev->ip_versions[MP1_HWIP][0]) { + case IP_VERSION(13, 0, 4): + case IP_VERSION(13, 0, 11): + return 0; + default: + break; + } + } + + /* * For gpu reset, runpm and hibernation through BACO, * BACO feature has to be kept enabled. */ diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index 53259c12d777..f85654f1b104 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -369,6 +369,7 @@ static int tc358764_probe(struct mipi_dsi_device *dsi) ctx->bridge.funcs = &tc358764_bridge_funcs; ctx->bridge.of_node = dev->of_node; + ctx->bridge.pre_enable_prev_first = true; drm_bridge_add(&ctx->bridge); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 1d2b4fb4bcf8..44ca803237a5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -22,6 +22,7 @@ #include "etnaviv_gem.h" #include "etnaviv_mmu.h" #include "etnaviv_perfmon.h" +#include "common.xml.h" /* * DRM operations: @@ -56,6 +57,11 @@ static int etnaviv_open(struct drm_device *dev, struct drm_file *file) if (!ctx) return -ENOMEM; + ret = xa_alloc_cyclic(&priv->active_contexts, &ctx->id, ctx, + xa_limit_32b, &priv->next_context_id, GFP_KERNEL); + if (ret < 0) + goto out_free; + ctx->mmu = etnaviv_iommu_context_init(priv->mmu_global, priv->cmdbuf_suballoc); if (!ctx->mmu) { @@ -99,6 +105,8 @@ static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file) etnaviv_iommu_context_put(ctx->mmu); + xa_erase(&priv->active_contexts, ctx->id); + kfree(ctx); } @@ -468,7 +476,47 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = { ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW), }; -DEFINE_DRM_GEM_FOPS(fops); +static void etnaviv_fop_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct drm_file *file = f->private_data; + struct drm_device *dev = file->minor->dev; + struct etnaviv_drm_private *priv = dev->dev_private; + struct etnaviv_file_private *ctx = file->driver_priv; + + /* + * For a description of the text output format used here, see + * Documentation/gpu/drm-usage-stats.rst. + */ + seq_printf(m, "drm-driver:\t%s\n", dev->driver->name); + seq_printf(m, "drm-client-id:\t%u\n", ctx->id); + + for (int i = 0; i < ETNA_MAX_PIPES; i++) { + struct etnaviv_gpu *gpu = priv->gpu[i]; + char engine[10] = "UNK"; + int cur = 0; + + if (!gpu) + continue; + + if (gpu->identity.features & chipFeatures_PIPE_2D) + cur = snprintf(engine, sizeof(engine), "2D"); + if (gpu->identity.features & chipFeatures_PIPE_3D) + cur = snprintf(engine + cur, sizeof(engine) - cur, + "%s3D", cur ? "/" : ""); + if (gpu->identity.nn_core_count > 0) + cur = snprintf(engine + cur, sizeof(engine) - cur, + "%sNN", cur ? "/" : ""); + + seq_printf(m, "drm-engine-%s:\t%llu ns\n", engine, + ctx->sched_entity[i].elapsed_ns); + } +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + DRM_GEM_FOPS, + .show_fdinfo = etnaviv_fop_show_fdinfo, +}; static const struct drm_driver etnaviv_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER, @@ -514,6 +562,8 @@ static int etnaviv_bind(struct device *dev) dma_set_max_seg_size(dev, SZ_2G); + xa_init_flags(&priv->active_contexts, XA_FLAGS_ALLOC); + mutex_init(&priv->gem_lock); INIT_LIST_HEAD(&priv->gem_list); priv->num_gpus = 0; @@ -563,6 +613,8 @@ static void etnaviv_unbind(struct device *dev) etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc); + xa_destroy(&priv->active_contexts); + drm->dev_private = NULL; kfree(priv); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index 2bb4c25565dc..b3eb1662e90c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -12,6 +12,7 @@ #include <linux/sizes.h> #include <linux/time64.h> #include <linux/types.h> +#include <linux/xarray.h> #include <drm/drm_drv.h> #include <drm/drm_gem.h> @@ -28,6 +29,7 @@ struct etnaviv_iommu_global; #define ETNAVIV_SOFTPIN_START_ADDRESS SZ_4M /* must be >= SUBALLOC_SIZE */ struct etnaviv_file_private { + int id; struct etnaviv_iommu_context *mmu; struct drm_sched_entity sched_entity[ETNA_MAX_PIPES]; }; @@ -40,6 +42,9 @@ struct etnaviv_drm_private { struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc; struct etnaviv_iommu_global *mmu_global; + struct xarray active_contexts; + u32 next_context_id; + /* list of GEM objects: */ struct mutex gem_lock; struct list_head gem_list; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 1491159d0d20..45403ea38906 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -393,10 +393,11 @@ static void submit_cleanup(struct kref *kref) wake_up_all(&submit->gpu->fence_event); if (submit->out_fence) { - /* first remove from IDR, so fence can not be found anymore */ - mutex_lock(&submit->gpu->fence_lock); - idr_remove(&submit->gpu->fence_idr, submit->out_fence_id); - mutex_unlock(&submit->gpu->fence_lock); + /* + * Remove from user fence array before dropping the reference, + * so fence can not be found in lookup anymore. + */ + xa_erase(&submit->gpu->user_fences, submit->out_fence_id); dma_fence_put(submit->out_fence); } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 51320eeebfcf..de8c9894967c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -773,6 +773,10 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) goto fail; } + if (gpu->identity.nn_core_count > 0) + dev_warn(gpu->dev, "etnaviv has been instantiated on a NPU, " + "for which the UAPI is still experimental\n"); + /* Exclude VG cores with FE2.0 */ if (gpu->identity.features & chipFeatures_PIPE_VG && gpu->identity.features & chipFeatures_FE20) { @@ -957,6 +961,8 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) gpu->identity.vertex_cache_size); seq_printf(m, "\t shader_core_count: %d\n", gpu->identity.shader_core_count); + seq_printf(m, "\t nn_core_count: %d\n", + gpu->identity.nn_core_count); seq_printf(m, "\t pixel_pipes: %d\n", gpu->identity.pixel_pipes); seq_printf(m, "\t vertex_output_buffer_size: %d\n", @@ -1240,7 +1246,7 @@ int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu, * pretends we didn't find a fence in that case. */ rcu_read_lock(); - fence = idr_find(&gpu->fence_idr, id); + fence = xa_load(&gpu->user_fences, id); if (fence) fence = dma_fence_get_rcu(fence); rcu_read_unlock(); @@ -1450,6 +1456,15 @@ static void sync_point_worker(struct work_struct *work) static void dump_mmu_fault(struct etnaviv_gpu *gpu) { + static const char *fault_reasons[] = { + "slave not present", + "page not present", + "write violation", + "out of bounds", + "read security violation", + "write security violation", + }; + u32 status_reg, status; int i; @@ -1462,18 +1477,25 @@ static void dump_mmu_fault(struct etnaviv_gpu *gpu) dev_err_ratelimited(gpu->dev, "MMU fault status 0x%08x\n", status); for (i = 0; i < 4; i++) { + const char *reason = "unknown"; u32 address_reg; + u32 mmu_status; - if (!(status & (VIVS_MMUv2_STATUS_EXCEPTION0__MASK << (i * 4)))) + mmu_status = (status >> (i * 4)) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK; + if (!mmu_status) continue; + if ((mmu_status - 1) < ARRAY_SIZE(fault_reasons)) + reason = fault_reasons[mmu_status - 1]; + if (gpu->sec_mode == ETNA_SEC_NONE) address_reg = VIVS_MMUv2_EXCEPTION_ADDR(i); else address_reg = VIVS_MMUv2_SEC_EXCEPTION_ADDR; - dev_err_ratelimited(gpu->dev, "MMU %d fault addr 0x%08x\n", i, - gpu_read(gpu, address_reg)); + dev_err_ratelimited(gpu->dev, + "MMU %d fault (%s) addr 0x%08x\n", + i, reason, gpu_read(gpu, address_reg)); } } @@ -1629,7 +1651,6 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu) return etnaviv_gpu_clk_disable(gpu); } -#ifdef CONFIG_PM static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu) { int ret; @@ -1645,7 +1666,6 @@ static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu) return 0; } -#endif static int etnaviv_gpu_cooling_get_max_state(struct thermal_cooling_device *cdev, @@ -1713,18 +1733,17 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master, if (ret) goto out_workqueue; -#ifdef CONFIG_PM - ret = pm_runtime_get_sync(gpu->dev); -#else - ret = etnaviv_gpu_clk_enable(gpu); -#endif + if (IS_ENABLED(CONFIG_PM)) + ret = pm_runtime_get_sync(gpu->dev); + else + ret = etnaviv_gpu_clk_enable(gpu); if (ret < 0) goto out_sched; gpu->drm = drm; gpu->fence_context = dma_fence_context_alloc(1); - idr_init(&gpu->fence_idr); + xa_init_flags(&gpu->user_fences, XA_FLAGS_ALLOC); spin_lock_init(&gpu->fence_spinlock); INIT_WORK(&gpu->sync_point_work, sync_point_worker); @@ -1761,12 +1780,12 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master, etnaviv_sched_fini(gpu); -#ifdef CONFIG_PM - pm_runtime_get_sync(gpu->dev); - pm_runtime_put_sync_suspend(gpu->dev); -#else - etnaviv_gpu_hw_suspend(gpu); -#endif + if (IS_ENABLED(CONFIG_PM)) { + pm_runtime_get_sync(gpu->dev); + pm_runtime_put_sync_suspend(gpu->dev); + } else { + etnaviv_gpu_hw_suspend(gpu); + } if (gpu->mmu_context) etnaviv_iommu_context_put(gpu->mmu_context); @@ -1778,7 +1797,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master, } gpu->drm = NULL; - idr_destroy(&gpu->fence_idr); + xa_destroy(&gpu->user_fences); if (IS_ENABLED(CONFIG_DRM_ETNAVIV_THERMAL)) thermal_cooling_device_unregister(gpu->cooling); @@ -1810,7 +1829,7 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev) gpu->dev = &pdev->dev; mutex_init(&gpu->lock); - mutex_init(&gpu->fence_lock); + mutex_init(&gpu->sched_lock); /* Map registers: */ gpu->mmio = devm_platform_ioremap_resource(pdev, 0); @@ -1880,7 +1899,6 @@ static int etnaviv_gpu_platform_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM static int etnaviv_gpu_rpm_suspend(struct device *dev) { struct etnaviv_gpu *gpu = dev_get_drvdata(dev); @@ -1923,18 +1941,16 @@ static int etnaviv_gpu_rpm_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops etnaviv_gpu_pm_ops = { - SET_RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume, - NULL) + RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume, NULL) }; struct platform_driver etnaviv_gpu_driver = { .driver = { .name = "etnaviv-gpu", .owner = THIS_MODULE, - .pm = &etnaviv_gpu_pm_ops, + .pm = pm_ptr(&etnaviv_gpu_pm_ops), .of_match_table = etnaviv_gpu_match, }, .probe = etnaviv_gpu_platform_probe, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index f1204b070fb8..98c6f9c320fc 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -51,6 +51,9 @@ struct etnaviv_chip_identity { /* Number of shader cores. */ u32 shader_core_count; + /* Number of Neural Network cores. */ + u32 nn_core_count; + /* Size of the vertex cache. */ u32 vertex_cache_size; @@ -100,6 +103,7 @@ struct etnaviv_gpu { struct etnaviv_chip_identity identity; enum etnaviv_sec_mode sec_mode; struct workqueue_struct *wq; + struct mutex sched_lock; struct drm_gpu_scheduler sched; bool initialized; bool fe_running; @@ -117,8 +121,8 @@ struct etnaviv_gpu { u32 idle_mask; /* Fencing support */ - struct mutex fence_lock; - struct idr fence_idr; + struct xarray user_fences; + u32 next_user_fence; u32 next_fence; u32 completed_fence; wait_queue_head_t fence_event; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index 57f334e24189..2e63afa6c798 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -16,6 +16,7 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 128, .shader_core_count = 1, + .nn_core_count = 0, .vertex_cache_size = 8, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -47,6 +48,7 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 512, .shader_core_count = 2, + .nn_core_count = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -78,6 +80,7 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 512, .shader_core_count = 2, + .nn_core_count = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -140,6 +143,7 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 1024, .shader_core_count = 4, + .nn_core_count = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 2, @@ -161,6 +165,38 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .minor_features10 = 0x90044250, .minor_features11 = 0x00000024, }, + { + .model = 0x8000, + .revision = 0x7120, + .product_id = 0x45080009, + .customer_id = 0x88, + .eco_id = 0, + .stream_count = 8, + .register_max = 64, + .thread_count = 256, + .shader_core_count = 1, + .nn_core_count = 8, + .vertex_cache_size = 16, + .vertex_output_buffer_size = 1024, + .pixel_pipes = 1, + .instruction_count = 512, + .num_constants = 320, + .buffer_size = 0, + .varyings_count = 16, + .features = 0xe0287cac, + .minor_features0 = 0xc1799eff, + .minor_features1 = 0xfefbfadb, + .minor_features2 = 0xeb9d6fbf, + .minor_features3 = 0xedfffced, + .minor_features4 = 0xd30dafc7, + .minor_features5 = 0x7b5ac333, + .minor_features6 = 0xfc8ee200, + .minor_features7 = 0x03fffa6f, + .minor_features8 = 0x00fe0ef0, + .minor_features9 = 0x0088003c, + .minor_features10 = 0x108048c0, + .minor_features11 = 0x00000010, + }, }; bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index d29f467eee13..1ae87dfd19c4 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -97,24 +97,24 @@ static const struct drm_sched_backend_ops etnaviv_sched_ops = { int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit) { - int ret = 0; + struct etnaviv_gpu *gpu = submit->gpu; + int ret; /* - * Hold the fence lock across the whole operation to avoid jobs being + * Hold the sched lock across the whole operation to avoid jobs being * pushed out of order with regard to their sched fence seqnos as * allocated in drm_sched_job_arm. */ - mutex_lock(&submit->gpu->fence_lock); + mutex_lock(&gpu->sched_lock); drm_sched_job_arm(&submit->sched_job); submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished); - submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr, - submit->out_fence, 0, - INT_MAX, GFP_KERNEL); - if (submit->out_fence_id < 0) { + ret = xa_alloc_cyclic(&gpu->user_fences, &submit->out_fence_id, + submit->out_fence, xa_limit_32b, + &gpu->next_user_fence, GFP_KERNEL); + if (ret < 0) { drm_sched_job_cleanup(&submit->sched_job); - ret = -ENOMEM; goto out_unlock; } @@ -124,7 +124,7 @@ int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit) drm_sched_entity_push_job(&submit->sched_job); out_unlock: - mutex_unlock(&submit->gpu->fence_lock); + mutex_unlock(&gpu->sched_lock); return ret; } diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h index deaaa99fa654..94d5f33b1fd6 100644 --- a/drivers/gpu/drm/etnaviv/state_hi.xml.h +++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h @@ -8,17 +8,17 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng git clone git://0x04.net/rules-ng-ng The rules-ng-ng source files this header was generated from are: -- state.xml ( 26666 bytes, from 2019-12-20 21:20:35) -- common.xml ( 35468 bytes, from 2018-02-10 13:09:26) -- common_3d.xml ( 15058 bytes, from 2019-12-28 20:02:03) -- state_hi.xml ( 30552 bytes, from 2019-12-28 20:02:48) -- copyright.xml ( 1597 bytes, from 2018-02-10 13:09:26) -- state_2d.xml ( 51552 bytes, from 2018-02-10 13:09:26) -- state_3d.xml ( 83098 bytes, from 2019-12-28 20:02:03) -- state_blt.xml ( 14252 bytes, from 2019-10-20 19:59:15) -- state_vg.xml ( 5975 bytes, from 2018-02-10 13:09:26) - -Copyright (C) 2012-2019 by the following authors: +- state.xml ( 27198 bytes, from 2022-04-22 10:35:24) +- common.xml ( 35468 bytes, from 2020-10-28 12:56:03) +- common_3d.xml ( 15058 bytes, from 2020-10-28 12:56:03) +- state_hi.xml ( 34804 bytes, from 2022-12-02 09:06:28) +- copyright.xml ( 1597 bytes, from 2020-10-28 12:56:03) +- state_2d.xml ( 51552 bytes, from 2020-10-28 12:56:03) +- state_3d.xml ( 84445 bytes, from 2022-11-15 15:59:38) +- state_blt.xml ( 14424 bytes, from 2022-11-07 11:18:41) +- state_vg.xml ( 5975 bytes, from 2020-10-28 12:56:03) + +Copyright (C) 2012-2022 by the following authors: - Wladimir J. van der Laan <laanwj@gmail.com> - Christian Gmeiner <christian.gmeiner@gmail.com> - Lucas Stach <l.stach@pengutronix.de> @@ -321,16 +321,16 @@ DEALINGS IN THE SOFTWARE. #define VIVS_MMUv2_CONFIGURATION_ADDRESS(x) (((x) << VIVS_MMUv2_CONFIGURATION_ADDRESS__SHIFT) & VIVS_MMUv2_CONFIGURATION_ADDRESS__MASK) #define VIVS_MMUv2_STATUS 0x00000188 -#define VIVS_MMUv2_STATUS_EXCEPTION0__MASK 0x00000003 +#define VIVS_MMUv2_STATUS_EXCEPTION0__MASK 0x0000000f #define VIVS_MMUv2_STATUS_EXCEPTION0__SHIFT 0 #define VIVS_MMUv2_STATUS_EXCEPTION0(x) (((x) << VIVS_MMUv2_STATUS_EXCEPTION0__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK) -#define VIVS_MMUv2_STATUS_EXCEPTION1__MASK 0x00000030 +#define VIVS_MMUv2_STATUS_EXCEPTION1__MASK 0x000000f0 #define VIVS_MMUv2_STATUS_EXCEPTION1__SHIFT 4 #define VIVS_MMUv2_STATUS_EXCEPTION1(x) (((x) << VIVS_MMUv2_STATUS_EXCEPTION1__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION1__MASK) -#define VIVS_MMUv2_STATUS_EXCEPTION2__MASK 0x00000300 +#define VIVS_MMUv2_STATUS_EXCEPTION2__MASK 0x00000f00 #define VIVS_MMUv2_STATUS_EXCEPTION2__SHIFT 8 #define VIVS_MMUv2_STATUS_EXCEPTION2(x) (((x) << VIVS_MMUv2_STATUS_EXCEPTION2__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION2__MASK) -#define VIVS_MMUv2_STATUS_EXCEPTION3__MASK 0x00003000 +#define VIVS_MMUv2_STATUS_EXCEPTION3__MASK 0x0000f000 #define VIVS_MMUv2_STATUS_EXCEPTION3__SHIFT 12 #define VIVS_MMUv2_STATUS_EXCEPTION3(x) (((x) << VIVS_MMUv2_STATUS_EXCEPTION3__SHIFT) & VIVS_MMUv2_STATUS_EXCEPTION3__MASK) @@ -465,7 +465,13 @@ DEALINGS IN THE SOFTWARE. #define VIVS_MC_PROFILE_CONFIG0 0x00000470 #define VIVS_MC_PROFILE_CONFIG0_FE__MASK 0x000000ff #define VIVS_MC_PROFILE_CONFIG0_FE__SHIFT 0 +#define VIVS_MC_PROFILE_CONFIG0_FE_DRAW_COUNT 0x0000000a +#define VIVS_MC_PROFILE_CONFIG0_FE_OUT_VERTEX_COUNT 0x0000000b +#define VIVS_MC_PROFILE_CONFIG0_FE_CACHE_MISS_COUNT 0x0000000c #define VIVS_MC_PROFILE_CONFIG0_FE_RESET 0x0000000f +#define VIVS_MC_PROFILE_CONFIG0_FE_CACHE_LK_COUNT 0x00000010 +#define VIVS_MC_PROFILE_CONFIG0_FE_STALL_COUNT 0x00000011 +#define VIVS_MC_PROFILE_CONFIG0_FE_PROCESS_COUNT 0x00000012 #define VIVS_MC_PROFILE_CONFIG0_DE__MASK 0x0000ff00 #define VIVS_MC_PROFILE_CONFIG0_DE__SHIFT 8 #define VIVS_MC_PROFILE_CONFIG0_DE_RESET 0x00000f00 @@ -499,11 +505,14 @@ DEALINGS IN THE SOFTWARE. #define VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER 0x00000006 #define VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER 0x00000007 #define VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER 0x00000008 +#define VIVS_MC_PROFILE_CONFIG1_PA_DROPED_PRIM_COUNTER 0x00000009 +#define VIVS_MC_PROFILE_CONFIG1_PA_FRUSTUM_CLIPPED_PRIM_COUNTER 0x0000000a #define VIVS_MC_PROFILE_CONFIG1_PA_RESET 0x0000000f #define VIVS_MC_PROFILE_CONFIG1_SE__MASK 0x0000ff00 #define VIVS_MC_PROFILE_CONFIG1_SE__SHIFT 8 #define VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT 0x00000000 #define VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT 0x00000100 +#define VIVS_MC_PROFILE_CONFIG1_SE_TRIVIAL_REJECTED_LINE_COUNT 0x00000400 #define VIVS_MC_PROFILE_CONFIG1_SE_RESET 0x00000f00 #define VIVS_MC_PROFILE_CONFIG1_RA__MASK 0x00ff0000 #define VIVS_MC_PROFILE_CONFIG1_RA__SHIFT 16 @@ -515,6 +524,8 @@ DEALINGS IN THE SOFTWARE. #define VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER 0x000a0000 #define VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT 0x000b0000 #define VIVS_MC_PROFILE_CONFIG1_RA_RESET 0x000f0000 +#define VIVS_MC_PROFILE_CONFIG1_RA_PIPE_HZ_CACHE_MISS_COUNTER 0x00110000 +#define VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_HZ_CACHE_MISS_COUNTER 0x00120000 #define VIVS_MC_PROFILE_CONFIG1_TX__MASK 0xff000000 #define VIVS_MC_PROFILE_CONFIG1_TX__SHIFT 24 #define VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS 0x00000000 @@ -535,13 +546,48 @@ DEALINGS IN THE SOFTWARE. #define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE 0x00000001 #define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP 0x00000002 #define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE 0x00000003 -#define VIVS_MC_PROFILE_CONFIG2_MC_RESET 0x0000000f +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_SENTOUT_FROM_COLORPIPE 0x00000004 +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_FROM_COLORPIPE 0x00000005 +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_DEPTHPIPE 0x00000007 +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_SENTOUT_FROM_DEPTHPIPE 0x00000008 +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_DEPTHPIPE 0x00000009 +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_SENTOUT_FROM_DEPTHPIPE 0x0000000a +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_FROM_DEPTHPIPE 0x0000000b +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_OTHERS 0x0000000c +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_OTHERS 0x0000000d +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_FROM_OTHERS 0x0000000e +#define VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_FROM_OTHERS 0x0000000f +#define VIVS_MC_PROFILE_CONFIG2_MC_FE_READ_BANDWIDTH 0x00000015 +#define VIVS_MC_PROFILE_CONFIG2_MC_MMU_READ_BANDWIDTH 0x00000016 +#define VIVS_MC_PROFILE_CONFIG2_MC_BLT_READ_BANDWIDTH 0x00000017 +#define VIVS_MC_PROFILE_CONFIG2_MC_SH0_READ_BANDWIDTH 0x00000018 +#define VIVS_MC_PROFILE_CONFIG2_MC_SH1_READ_BANDWIDTH 0x00000019 +#define VIVS_MC_PROFILE_CONFIG2_MC_PE_WRITE_BANDWIDTH 0x0000001a +#define VIVS_MC_PROFILE_CONFIG2_MC_BLT_WRITE_BANDWIDTH 0x0000001b +#define VIVS_MC_PROFILE_CONFIG2_MC_SH0_WRITE_BANDWIDTH 0x0000001c +#define VIVS_MC_PROFILE_CONFIG2_MC_SH1_WRITE_BANDWIDTH 0x0000001d #define VIVS_MC_PROFILE_CONFIG2_HI__MASK 0x0000ff00 #define VIVS_MC_PROFILE_CONFIG2_HI__SHIFT 8 #define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED 0x00000000 #define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED 0x00000100 #define VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED 0x00000200 #define VIVS_MC_PROFILE_CONFIG2_HI_RESET 0x00000f00 +#define VIVS_MC_PROFILE_CONFIG2_L2__MASK 0x00ff0000 +#define VIVS_MC_PROFILE_CONFIG2_L2__SHIFT 16 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_AXI0_READ_REQUEST_COUNT 0x00000000 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_AXI0_WRITE_REQUEST_COUNT 0x00040000 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_AXI1_WRITE_REQUEST_COUNT 0x00050000 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_READ_TRANSACTIONS_REQUEST_BY_AXI0 0x00080000 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_READ_TRANSACTIONS_REQUEST_BY_AXI1 0x00090000 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_WRITE_TRANSACTIONS_REQUEST_BY_AXI0 0x000c0000 +#define VIVS_MC_PROFILE_CONFIG2_L2_TOTAL_WRITE_TRANSACTIONS_REQUEST_BY_AXI1 0x000d0000 +#define VIVS_MC_PROFILE_CONFIG2_L2_RESET 0x000f0000 +#define VIVS_MC_PROFILE_CONFIG2_L2_AXI0_MINMAX_LATENCY 0x00100000 +#define VIVS_MC_PROFILE_CONFIG2_L2_AXI0_TOTAL_LATENCY 0x00110000 +#define VIVS_MC_PROFILE_CONFIG2_L2_AXI0_TOTAL_REQUEST_COUNT 0x00120000 +#define VIVS_MC_PROFILE_CONFIG2_L2_AXI1_MINMAX_LATENCY 0x00130000 +#define VIVS_MC_PROFILE_CONFIG2_L2_AXI1_TOTAL_LATENCY 0x00140000 +#define VIVS_MC_PROFILE_CONFIG2_L2_AXI1_TOTAL_REQUEST_COUNT 0x00150000 #define VIVS_MC_PROFILE_CONFIG2_BLT__MASK 0xff000000 #define VIVS_MC_PROFILE_CONFIG2_BLT__SHIFT 24 #define VIVS_MC_PROFILE_CONFIG2_BLT_UNK0 0x00000000 @@ -566,5 +612,13 @@ DEALINGS IN THE SOFTWARE. #define VIVS_MC_PROFILE_L2_READ 0x00000564 +#define VIVS_MC_MC_LATENCY_RESET 0x00000568 + +#define VIVS_MC_MC_AXI_MAX_MIN_LATENCY 0x0000056c + +#define VIVS_MC_MC_AXI_TOTAL_LATENCY 0x00000570 + +#define VIVS_MC_MC_AXI_SAMPLE_COUNT 0x00000574 + #endif /* STATE_HI_XML */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 320c370cfe24..06d6513ddaae 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1445,7 +1445,8 @@ static int exynos_dsi_attach(struct drm_bridge *bridge, { struct exynos_dsi *dsi = bridge_to_dsi(bridge); - return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, flags); + return drm_bridge_attach(bridge->encoder, dsi->out_bridge, bridge, + flags); } static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { @@ -1491,7 +1492,10 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, drm_bridge_add(&dsi->bridge); - drm_bridge_attach(encoder, &dsi->bridge, NULL, 0); + drm_bridge_attach(encoder, &dsi->bridge, + list_first_entry_or_null(&encoder->bridge_chain, + struct drm_bridge, + chain_node), 0); /* * This is a temporary solution and should be made by more generic way. @@ -1726,6 +1730,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->bridge.funcs = &exynos_dsi_bridge_funcs; dsi->bridge.of_node = dev->of_node; dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; + dsi->bridge.pre_enable_prev_first = true; ret = component_add(dev, &exynos_dsi_component_ops); if (ret) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 454e73a433c8..6d639ca24dfb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1096,16 +1096,15 @@ static struct i915_gem_engines *alloc_engines(unsigned int count) static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx, struct intel_sseu rcs_sseu) { - const struct intel_gt *gt = to_gt(ctx->i915); + const unsigned int max = I915_NUM_ENGINES; struct intel_engine_cs *engine; struct i915_gem_engines *e, *err; - enum intel_engine_id id; - e = alloc_engines(I915_NUM_ENGINES); + e = alloc_engines(max); if (!e) return ERR_PTR(-ENOMEM); - for_each_engine(engine, gt, id) { + for_each_uabi_engine(engine, ctx->i915) { struct intel_context *ce; struct intel_sseu sseu = {}; int ret; @@ -1113,7 +1112,7 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx, if (engine->legacy_idx == INVALID_ENGINE) continue; - GEM_BUG_ON(engine->legacy_idx >= I915_NUM_ENGINES); + GEM_BUG_ON(engine->legacy_idx >= max); GEM_BUG_ON(e->engines[engine->legacy_idx]); ce = intel_context_create(engine); @@ -1861,11 +1860,19 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv, vm = ctx->vm; GEM_BUG_ON(!vm); + /* + * Get a reference for the allocated handle. Once the handle is + * visible in the vm_xa table, userspace could try to close it + * from under our feet, so we need to hold the extra reference + * first. + */ + i915_vm_get(vm); + err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL); - if (err) + if (err) { + i915_vm_put(vm); return err; - - i915_vm_get(vm); + } GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ args->value = id; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index 04bb909acdec..a049ca0b7980 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -305,10 +305,6 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, spin_unlock(&obj->vma.lock); obj->tiling_and_stride = tiling | stride; - i915_gem_object_unlock(obj); - - /* Force the fence to be reacquired for GTT access */ - i915_gem_object_release_mmap_gtt(obj); /* Try to preallocate memory required to save swizzling on put-pages */ if (i915_gem_object_needs_bit17_swizzle(obj)) { @@ -321,6 +317,11 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, obj->bit_17 = NULL; } + i915_gem_object_unlock(obj); + + /* Force the fence to be reacquired for GTT access */ + i915_gem_object_release_mmap_gtt(obj); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index e94365b08f1e..2aa63ec521b8 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -528,7 +528,7 @@ retry: return rq; } -struct i915_request *intel_context_find_active_request(struct intel_context *ce) +struct i915_request *intel_context_get_active_request(struct intel_context *ce) { struct intel_context *parent = intel_context_to_parent(ce); struct i915_request *rq, *active = NULL; @@ -552,6 +552,8 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce) active = rq; } + if (active) + active = i915_request_get_rcu(active); spin_unlock_irqrestore(&parent->guc_state.lock, flags); return active; diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index fb62b7b8cbcd..0a8d553da3f4 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -268,8 +268,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce, struct i915_request *intel_context_create_request(struct intel_context *ce); -struct i915_request * -intel_context_find_active_request(struct intel_context *ce); +struct i915_request *intel_context_get_active_request(struct intel_context *ce); static inline bool intel_context_is_barrier(const struct intel_context *ce) { diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 0e24af5efee9..b58c30ac8ef0 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -250,8 +250,8 @@ void intel_engine_dump_active_requests(struct list_head *requests, ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, ktime_t *now); -struct i915_request * -intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine); +void intel_engine_get_hung_entity(struct intel_engine_cs *engine, + struct intel_context **ce, struct i915_request **rq); u32 intel_engine_context_size(struct intel_gt *gt, u8 class); struct intel_context * diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 922f1bb22dc6..d4e29da74612 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1584,11 +1584,8 @@ static u32 __cs_pending_mi_force_wakes(struct intel_engine_cs *engine) }; u32 val; - if (!_reg[engine->id].reg) { - drm_err(&engine->i915->drm, - "MSG IDLE undefined for engine id %u\n", engine->id); + if (!_reg[engine->id].reg) return 0; - } val = intel_uncore_read(engine->uncore, _reg[engine->id]); @@ -2114,17 +2111,6 @@ static void print_request_ring(struct drm_printer *m, struct i915_request *rq) } } -static unsigned long list_count(struct list_head *list) -{ - struct list_head *pos; - unsigned long count = 0; - - list_for_each(pos, list) - count++; - - return count; -} - static unsigned long read_ul(void *p, size_t x) { return *(unsigned long *)(p + x); @@ -2216,11 +2202,11 @@ void intel_engine_dump_active_requests(struct list_head *requests, } } -static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m) +static void engine_dump_active_requests(struct intel_engine_cs *engine, + struct drm_printer *m) { + struct intel_context *hung_ce = NULL; struct i915_request *hung_rq = NULL; - struct intel_context *ce; - bool guc; /* * No need for an engine->irq_seqno_barrier() before the seqno reads. @@ -2229,27 +2215,22 @@ static void engine_dump_active_requests(struct intel_engine_cs *engine, struct d * But the intention here is just to report an instantaneous snapshot * so that's fine. */ - lockdep_assert_held(&engine->sched_engine->lock); + intel_engine_get_hung_entity(engine, &hung_ce, &hung_rq); drm_printf(m, "\tRequests:\n"); - guc = intel_uc_uses_guc_submission(&engine->gt->uc); - if (guc) { - ce = intel_engine_get_hung_context(engine); - if (ce) - hung_rq = intel_context_find_active_request(ce); - } else { - hung_rq = intel_engine_execlist_find_hung_request(engine); - } - if (hung_rq) engine_dump_request(hung_rq, m, "\t\thung"); + else if (hung_ce) + drm_printf(m, "\t\tGot hung ce but no hung rq!\n"); - if (guc) + if (intel_uc_uses_guc_submission(&engine->gt->uc)) intel_guc_dump_active_requests(engine, hung_rq, m); else - intel_engine_dump_active_requests(&engine->sched_engine->requests, - hung_rq, m); + intel_execlists_dump_active_requests(engine, hung_rq, m); + + if (hung_rq) + i915_request_put(hung_rq); } void intel_engine_dump(struct intel_engine_cs *engine, @@ -2259,7 +2240,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct i915_gpu_error * const error = &engine->i915->gpu_error; struct i915_request *rq; intel_wakeref_t wakeref; - unsigned long flags; ktime_t dummy; if (header) { @@ -2296,13 +2276,8 @@ void intel_engine_dump(struct intel_engine_cs *engine, i915_reset_count(error)); print_properties(engine, m); - spin_lock_irqsave(&engine->sched_engine->lock, flags); engine_dump_active_requests(engine, m); - drm_printf(m, "\tOn hold?: %lu\n", - list_count(&engine->sched_engine->hold)); - spin_unlock_irqrestore(&engine->sched_engine->lock, flags); - drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base); wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm); if (wakeref) { @@ -2348,8 +2323,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings, return siblings[0]->cops->create_virtual(siblings, count, flags); } -struct i915_request * -intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) +static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine) { struct i915_request *request, *active = NULL; @@ -2401,6 +2375,33 @@ intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine) return active; } +void intel_engine_get_hung_entity(struct intel_engine_cs *engine, + struct intel_context **ce, struct i915_request **rq) +{ + unsigned long flags; + + *ce = intel_engine_get_hung_context(engine); + if (*ce) { + intel_engine_clear_hung_context(engine); + + *rq = intel_context_get_active_request(*ce); + return; + } + + /* + * Getting here with GuC enabled means it is a forced error capture + * with no actual hang. So, no need to attempt the execlist search. + */ + if (intel_uc_uses_guc_submission(&engine->gt->uc)) + return; + + spin_lock_irqsave(&engine->sched_engine->lock, flags); + *rq = engine_execlist_find_hung_request(engine); + if (*rq) + *rq = i915_request_get_rcu(*rq); + spin_unlock_irqrestore(&engine->sched_engine->lock, flags); +} + void xehp_enable_ccs_engines(struct intel_engine_cs *engine) { /* diff --git a/drivers/gpu/drm/i915/gt/intel_engine_regs.h b/drivers/gpu/drm/i915/gt/intel_engine_regs.h index ee3efd06ee54..6b9d9f837669 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_regs.h @@ -81,6 +81,7 @@ #define RING_EIR(base) _MMIO((base) + 0xb0) #define RING_EMR(base) _MMIO((base) + 0xb4) #define RING_ESR(base) _MMIO((base) + 0xb8) +#define GEN12_STATE_ACK_DEBUG(base) _MMIO((base) + 0xbc) #define RING_INSTPM(base) _MMIO((base) + 0xc0) #define RING_CMD_CCTL(base) _MMIO((base) + 0xc4) #define ACTHD(base) _MMIO((base) + 0xc8) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 18ffe55282e5..3c573d41d404 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -4150,6 +4150,33 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, spin_unlock_irqrestore(&sched_engine->lock, flags); } +static unsigned long list_count(struct list_head *list) +{ + struct list_head *pos; + unsigned long count = 0; + + list_for_each(pos, list) + count++; + + return count; +} + +void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, + struct i915_request *hung_rq, + struct drm_printer *m) +{ + unsigned long flags; + + spin_lock_irqsave(&engine->sched_engine->lock, flags); + + intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m); + + drm_printf(m, "\tOn hold?: %lu\n", + list_count(&engine->sched_engine->hold)); + + spin_unlock_irqrestore(&engine->sched_engine->lock, flags); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftest_execlists.c" #endif diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.h b/drivers/gpu/drm/i915/gt/intel_execlists_submission.h index a1aa92c983a5..d2c7d45ea062 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.h +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.h @@ -32,6 +32,10 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, int indent), unsigned int max); +void intel_execlists_dump_active_requests(struct intel_engine_cs *engine, + struct i915_request *hung_rq, + struct drm_printer *m); + bool intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 4f5c06d60bcd..7fa18a3b3957 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -407,6 +407,8 @@ #define GEN9_WM_CHICKEN3 _MMIO(0x5588) #define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9) +#define XEHP_CULLBIT1 MCR_REG(0x6100) + #define CHICKEN_RASTER_1 MCR_REG(0x6204) #define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8) @@ -457,10 +459,12 @@ #define HZ_DEPTH_TEST_LE_GE_OPT_DISABLE REG_BIT(13) #define BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE REG_BIT(3) +#define XEHP_CULLBIT2 MCR_REG(0x7030) + #define GEN8_L3CNTLREG _MMIO(0x7034) #define GEN8_ERRDETBCTRL (1 << 9) -#define PSS_MODE2 _MMIO(0x703c) +#define XEHP_PSS_MODE2 MCR_REG(0x703c) #define SCOREBOARD_STALL_FLUSH_CONTROL REG_BIT(5) #define GEN7_SC_INSTDONE _MMIO(0x7100) @@ -1096,16 +1100,19 @@ #define XEHP_MERT_MOD_CTRL MCR_REG(0xcf28) #define RENDER_MOD_CTRL MCR_REG(0xcf2c) #define COMP_MOD_CTRL MCR_REG(0xcf30) -#define VDBX_MOD_CTRL MCR_REG(0xcf34) -#define VEBX_MOD_CTRL MCR_REG(0xcf38) +#define XELPMP_GSC_MOD_CTRL _MMIO(0xcf30) /* media GT only */ +#define XEHP_VDBX_MOD_CTRL MCR_REG(0xcf34) +#define XELPMP_VDBX_MOD_CTRL _MMIO(0xcf34) +#define XEHP_VEBX_MOD_CTRL MCR_REG(0xcf38) +#define XELPMP_VEBX_MOD_CTRL _MMIO(0xcf38) #define FORCE_MISS_FTLB REG_BIT(3) -#define GEN12_GAMSTLB_CTRL _MMIO(0xcf4c) +#define XEHP_GAMSTLB_CTRL MCR_REG(0xcf4c) #define CONTROL_BLOCK_CLKGATE_DIS REG_BIT(12) #define EGRESS_BLOCK_CLKGATE_DIS REG_BIT(11) #define TAG_BLOCK_CLKGATE_DIS REG_BIT(7) -#define GEN12_GAMCNTRL_CTRL _MMIO(0xcf54) +#define XEHP_GAMCNTRL_CTRL MCR_REG(0xcf54) #define INVALIDATION_BROADCAST_MODE_DIS REG_BIT(12) #define GLOBAL_INVALIDATION_MODE REG_BIT(2) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index bbeeb6dde7ae..81a96c52a92b 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1316,16 +1316,16 @@ static u32 * dg2_emit_rcs_hang_wabb(const struct intel_context *ce, u32 *cs) { *cs++ = MI_LOAD_REGISTER_IMM(1); - *cs++ = i915_mmio_reg_offset(GEN12_STATE_ACK_DEBUG); + *cs++ = i915_mmio_reg_offset(GEN12_STATE_ACK_DEBUG(ce->engine->mmio_base)); *cs++ = 0x21; *cs++ = MI_LOAD_REGISTER_REG; *cs++ = i915_mmio_reg_offset(RING_NOPID(ce->engine->mmio_base)); - *cs++ = i915_mmio_reg_offset(GEN12_CULLBIT1); + *cs++ = i915_mmio_reg_offset(XEHP_CULLBIT1); *cs++ = MI_LOAD_REGISTER_REG; *cs++ = i915_mmio_reg_offset(RING_NOPID(ce->engine->mmio_base)); - *cs++ = i915_mmio_reg_offset(GEN12_CULLBIT2); + *cs++ = i915_mmio_reg_offset(XEHP_CULLBIT2); return cs; } diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 6dacd0dc5c2c..3111df350f57 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -30,6 +30,9 @@ * creation to have a "primed golden context", i.e. a context image that * already contains the changes needed to all the registers. * + * Context workarounds should be implemented in the *_ctx_workarounds_init() + * variants respective to the targeted platforms. + * * - Engine workarounds: the list of these WAs is applied whenever the specific * engine is reset. It's also possible that a set of engine classes share a * common power domain and they are reset together. This happens on some @@ -42,15 +45,28 @@ * saves/restores their values before/after the reset takes place. See * ``drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c`` for reference. * + * Workarounds for registers specific to RCS and CCS should be implemented in + * rcs_engine_wa_init() and ccs_engine_wa_init(), respectively; those for + * registers belonging to BCS, VCS or VECS should be implemented in + * xcs_engine_wa_init(). Workarounds for registers not belonging to a specific + * engine's MMIO range but that are part of of the common RCS/CCS reset domain + * should be implemented in general_render_compute_wa_init(). + * * - GT workarounds: the list of these WAs is applied whenever these registers * revert to their default values: on GPU reset, suspend/resume [1]_, etc. * + * GT workarounds should be implemented in the *_gt_workarounds_init() + * variants respective to the targeted platforms. + * * - Register whitelist: some workarounds need to be implemented in userspace, * but need to touch privileged registers. The whitelist in the kernel * instructs the hardware to allow the access to happen. From the kernel side, * this is just a special case of a MMIO workaround (as we write the list of * these to/be-whitelisted registers to some special HW registers). * + * Register whitelisting should be done in the *_whitelist_build() variants + * respective to the targeted platforms. + * * - Workaround batchbuffers: buffers that get executed automatically by the * hardware on every HW context restore. These buffers are created and * programmed in the default context so the hardware always go through those @@ -777,7 +793,7 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine, /* Wa_18018764978:dg2 */ if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_C0, STEP_FOREVER) || IS_DG2_G11(engine->i915) || IS_DG2_G12(engine->i915)) - wa_masked_en(wal, PSS_MODE2, SCOREBOARD_STALL_FLUSH_CONTROL); + wa_mcr_masked_en(wal, XEHP_PSS_MODE2, SCOREBOARD_STALL_FLUSH_CONTROL); /* Wa_15010599737:dg2 */ wa_mcr_masked_en(wal, CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN); @@ -805,7 +821,7 @@ static void mtl_ctx_workarounds_init(struct intel_engine_cs *engine, wa_mcr_masked_en(wal, VFLSKPD, VF_PREFETCH_TLB_DIS); /* Wa_18018764978 */ - wa_masked_en(wal, PSS_MODE2, SCOREBOARD_STALL_FLUSH_CONTROL); + wa_mcr_masked_en(wal, XEHP_PSS_MODE2, SCOREBOARD_STALL_FLUSH_CONTROL); } /* Wa_18019271663 */ @@ -1543,6 +1559,13 @@ xehpsdv_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) /* Wa_14011060649:xehpsdv */ wa_14011060649(gt, wal); + + /* Wa_14012362059:xehpsdv */ + wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB); + + /* Wa_14014368820:xehpsdv */ + wa_mcr_write_or(wal, XEHP_GAMCNTRL_CTRL, + INVALIDATION_BROADCAST_MODE_DIS | GLOBAL_INVALIDATION_MODE); } static void @@ -1583,6 +1606,12 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) DSS_ROUTER_CLKGATE_DIS); } + if (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_B0) || + IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_B0)) { + /* Wa_14012362059:dg2 */ + wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB); + } + if (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_B0)) { /* Wa_14010948348:dg2_g10 */ wa_write_or(wal, UNSLCGCTL9430, MSQDUNIT_CLKGATE_DIS); @@ -1628,6 +1657,12 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) /* Wa_14011028019:dg2_g10 */ wa_mcr_write_or(wal, SSMCGCTL9530, RTFUNIT_CLKGATE_DIS); + + /* Wa_14010680813:dg2_g10 */ + wa_mcr_write_or(wal, XEHP_GAMSTLB_CTRL, + CONTROL_BLOCK_CLKGATE_DIS | + EGRESS_BLOCK_CLKGATE_DIS | + TAG_BLOCK_CLKGATE_DIS); } /* Wa_14014830051:dg2 */ @@ -1642,6 +1677,16 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) /* Wa_14015795083 */ wa_mcr_write_clr(wal, GEN8_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE); + + /* Wa_18018781329 */ + wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, XEHP_VDBX_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, XEHP_VEBX_MOD_CTRL, FORCE_MISS_FTLB); + + /* Wa_1509235366:dg2 */ + wa_mcr_write_or(wal, XEHP_GAMCNTRL_CTRL, + INVALIDATION_BROADCAST_MODE_DIS | GLOBAL_INVALIDATION_MODE); } static void @@ -1651,16 +1696,27 @@ pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) /* Wa_14015795083 */ wa_mcr_write_clr(wal, GEN8_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE); + + /* Wa_18018781329 */ + wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, XEHP_VDBX_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, XEHP_VEBX_MOD_CTRL, FORCE_MISS_FTLB); } static void xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) { - /* Wa_14014830051 */ if (IS_MTL_GRAPHICS_STEP(gt->i915, M, STEP_A0, STEP_B0) || - IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0)) + IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0)) { + /* Wa_14014830051 */ wa_mcr_write_clr(wal, SARB_CHICKEN1, COMP_CKN_IN); + /* Wa_18018781329 */ + wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB); + wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); + } + /* * Unlike older platforms, we no longer setup implicit steering here; * all MCR accesses are explicitly steered. @@ -1671,7 +1727,17 @@ xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) static void xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) { - /* FIXME: Actual workarounds will be added in future patch(es) */ + if (IS_MTL_MEDIA_STEP(gt->i915, STEP_A0, STEP_B0)) { + /* + * Wa_18018781329 + * + * Note that although these registers are MCR on the primary + * GT, the media GT's versions are regular singleton registers. + */ + wa_write_or(wal, XELPMP_GSC_MOD_CTRL, FORCE_MISS_FTLB); + wa_write_or(wal, XELPMP_VDBX_MOD_CTRL, FORCE_MISS_FTLB); + wa_write_or(wal, XELPMP_VEBX_MOD_CTRL, FORCE_MISS_FTLB); + } debug_dump_steering(gt); } @@ -2325,10 +2391,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) /* Wa_1509727124 */ wa_mcr_masked_en(wal, GEN10_SAMPLER_MODE, SC_DISABLE_POWER_OPTIMIZATION_EBB); - - /* Wa_22013037850 */ - wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW, - DISABLE_128B_EVICTION_COMMAND_UDW); } if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_FOREVER) || @@ -2339,12 +2401,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN12_DISABLE_READ_SUPPRESSION); } - if (IS_DG2(i915)) { - /* Wa_1509235366:dg2 */ - wa_write_or(wal, GEN12_GAMCNTRL_CTRL, INVALIDATION_BROADCAST_MODE_DIS | - GLOBAL_INVALIDATION_MODE); - } - if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) { /* Wa_14013392000:dg2_g11 */ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2, GEN12_ENABLE_LARGE_GRF_MODE); @@ -2357,21 +2413,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN12_DISABLE_HDR_PAST_PAYLOAD_HOLD_FIX); } - if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) || - IS_DG2_G11(i915)) { - /* - * Wa_22012826095:dg2 - * Wa_22013059131:dg2 - */ - wa_mcr_write_clr_set(wal, LSC_CHICKEN_BIT_0_UDW, - MAXREQS_PER_BANK, - REG_FIELD_PREP(MAXREQS_PER_BANK, 2)); - - /* Wa_22013059131:dg2 */ - wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0, - FORCE_1_SUB_MESSAGE_PER_FRAGMENT); - } - /* Wa_1308578152:dg2_g10 when first gslice is fused off */ if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) && needs_wa_1308578152(engine)) { @@ -2396,16 +2437,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) */ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN, MDQ_ARBITRATION_MODE | UGM_BACKUP_MODE); - - /* - * Wa_14010918519:dg2_g10 - * - * LSC_CHICKEN_BIT_0 always reads back as 0 is this stepping, - * so ignoring verification. - */ - wa_mcr_add(wal, LSC_CHICKEN_BIT_0_UDW, 0, - FORCE_SLM_FENCE_SCOPE_TO_TILE | FORCE_UGM_FENCE_SCOPE_TO_TILE, - 0, false); } if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0)) { @@ -2429,18 +2460,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) wa_mcr_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7, DG2_DISABLE_ROUND_ENABLE_ALLOW_FOR_SSLA); - if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_A0, STEP_B0)) { - /* Wa_14010680813:dg2_g10 */ - wa_write_or(wal, GEN12_GAMSTLB_CTRL, CONTROL_BLOCK_CLKGATE_DIS | - EGRESS_BLOCK_CLKGATE_DIS | TAG_BLOCK_CLKGATE_DIS); - } - - if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_A0, STEP_B0) || - IS_DG2_GRAPHICS_STEP(engine->i915, G11, STEP_A0, STEP_B0)) { - /* Wa_14012362059:dg2 */ - wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB); - } - if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_B0, STEP_FOREVER) || IS_DG2_G10(i915)) { /* Wa_22014600077:dg2 */ @@ -2992,14 +3011,17 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_A0, STEP_B0) || IS_MTL_GRAPHICS_STEP(i915, P, STEP_A0, STEP_B0) || + IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_FOREVER) || + IS_DG2_G11(i915) || IS_DG2_G12(i915)) { + /* Wa_22013037850 */ + wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW, + DISABLE_128B_EVICTION_COMMAND_UDW); + } + + if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_A0, STEP_B0) || + IS_MTL_GRAPHICS_STEP(i915, P, STEP_A0, STEP_B0) || IS_PONTEVECCHIO(i915) || IS_DG2(i915)) { - /* Wa_18018781329 */ - wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB); - wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); - wa_mcr_write_or(wal, VDBX_MOD_CTRL, FORCE_MISS_FTLB); - wa_mcr_write_or(wal, VEBX_MOD_CTRL, FORCE_MISS_FTLB); - /* Wa_22014226127 */ wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0, DISABLE_D8_D16_COASLESCE); } @@ -3011,6 +3033,33 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li wa_masked_en(wal, VFG_PREEMPTION_CHICKEN, POLYGON_TRIFAN_LINELOOP_DISABLE); } + if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) || + IS_DG2_G11(i915)) { + /* + * Wa_22012826095:dg2 + * Wa_22013059131:dg2 + */ + wa_mcr_write_clr_set(wal, LSC_CHICKEN_BIT_0_UDW, + MAXREQS_PER_BANK, + REG_FIELD_PREP(MAXREQS_PER_BANK, 2)); + + /* Wa_22013059131:dg2 */ + wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0, + FORCE_1_SUB_MESSAGE_PER_FRAGMENT); + } + + if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0)) { + /* + * Wa_14010918519:dg2_g10 + * + * LSC_CHICKEN_BIT_0 always reads back as 0 is this stepping, + * so ignoring verification. + */ + wa_mcr_add(wal, LSC_CHICKEN_BIT_0_UDW, 0, + FORCE_SLM_FENCE_SCOPE_TO_TILE | FORCE_UGM_FENCE_SCOPE_TO_TILE, + 0, false); + } + if (IS_PONTEVECCHIO(i915)) { /* Wa_16016694945 */ wa_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_OVRLSCCC); @@ -3039,13 +3088,6 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li wa_mcr_masked_dis(wal, MLTICTXCTL, TDONRENDER); wa_mcr_write_or(wal, L3SQCREG1_CCS0, FLUSHALLNONCOH); } - - /* Wa_14012362059:xehpsdv */ - wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB); - - /* Wa_14014368820:xehpsdv */ - wa_write_or(wal, GEN12_GAMCNTRL_CTRL, INVALIDATION_BROADCAST_MODE_DIS | - GLOBAL_INVALIDATION_MODE); } if (IS_DG2(i915) || IS_PONTEVECCHIO(i915)) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 1bccc175f9e6..d76508fa3af7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -11,6 +11,7 @@ #include "intel_guc.h" #include "intel_guc_ads.h" #include "intel_guc_capture.h" +#include "intel_guc_print.h" #include "intel_guc_slpc.h" #include "intel_guc_submission.h" #include "i915_drv.h" @@ -94,8 +95,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc) assert_rpm_wakelock_held(>->i915->runtime_pm); spin_lock_irq(gt->irq_lock); - WARN_ON_ONCE(intel_uncore_read(gt->uncore, GEN8_GT_IIR(2)) & - gt->pm_guc_events); + guc_WARN_ON_ONCE(guc, intel_uncore_read(gt->uncore, GEN8_GT_IIR(2)) & + gt->pm_guc_events); gen6_gt_pm_enable_irq(gt, gt->pm_guc_events); spin_unlock_irq(gt->irq_lock); @@ -342,7 +343,7 @@ static void guc_init_params(struct intel_guc *guc) params[GUC_CTL_DEVID] = guc_ctl_devid(guc); for (i = 0; i < GUC_CTL_MAX_DWORDS; i++) - DRM_DEBUG_DRIVER("param[%2d] = %#x\n", i, params[i]); + guc_dbg(guc, "param[%2d] = %#x\n", i, params[i]); } /* @@ -389,7 +390,6 @@ void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p) int intel_guc_init(struct intel_guc *guc) { - struct intel_gt *gt = guc_to_gt(guc); int ret; ret = intel_uc_fw_init(&guc->fw); @@ -451,7 +451,7 @@ err_fw: intel_uc_fw_fini(&guc->fw); out: intel_uc_fw_change_status(&guc->fw, INTEL_UC_FIRMWARE_INIT_FAIL); - i915_probe_error(gt->i915, "failed with %d\n", ret); + guc_probe_error(guc, "failed with %pe\n", ERR_PTR(ret)); return ret; } @@ -480,7 +480,6 @@ void intel_guc_fini(struct intel_guc *guc) int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, u32 *response_buf, u32 response_buf_size) { - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; struct intel_uncore *uncore = guc_to_gt(guc)->uncore; u32 header; int i; @@ -515,7 +514,7 @@ retry: 10, 10, &header); if (unlikely(ret)) { timeout: - drm_err(&i915->drm, "mmio request %#x: no reply %x\n", + guc_err(guc, "mmio request %#x: no reply %x\n", request[0], header); goto out; } @@ -537,7 +536,7 @@ timeout: if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) == GUC_HXG_TYPE_NO_RESPONSE_RETRY) { u32 reason = FIELD_GET(GUC_HXG_RETRY_MSG_0_REASON, header); - drm_dbg(&i915->drm, "mmio request %#x: retrying, reason %u\n", + guc_dbg(guc, "mmio request %#x: retrying, reason %u\n", request[0], reason); goto retry; } @@ -546,7 +545,7 @@ timeout: u32 hint = FIELD_GET(GUC_HXG_FAILURE_MSG_0_HINT, header); u32 error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, header); - drm_err(&i915->drm, "mmio request %#x: failure %x/%u\n", + guc_err(guc, "mmio request %#x: failure %x/%u\n", request[0], error, hint); ret = -ENXIO; goto out; @@ -554,7 +553,7 @@ timeout: if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) != GUC_HXG_TYPE_RESPONSE_SUCCESS) { proto: - drm_err(&i915->drm, "mmio request %#x: unexpected reply %#x\n", + guc_err(guc, "mmio request %#x: unexpected reply %#x\n", request[0], header); ret = -EPROTO; goto out; @@ -597,9 +596,9 @@ int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, msg = payload[0] & guc->msg_enabled_mask; if (msg & INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED) - drm_err(&guc_to_gt(guc)->i915->drm, "Received early GuC crash dump notification!\n"); + guc_err(guc, "Received early crash dump notification!\n"); if (msg & INTEL_GUC_RECV_MSG_EXCEPTION) - drm_err(&guc_to_gt(guc)->i915->drm, "Received early GuC exception notification!\n"); + guc_err(guc, "Received early exception notification!\n"); return 0; } @@ -653,7 +652,8 @@ int intel_guc_suspend(struct intel_guc *guc) */ ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); if (ret) - DRM_ERROR("GuC suspend: RESET_CLIENT action failed with error %d!\n", ret); + guc_err(guc, "suspend: RESET_CLIENT action failed with %pe\n", + ERR_PTR(ret)); } /* Signal that the GuC isn't running. */ @@ -828,12 +828,11 @@ static int __guc_action_self_cfg(struct intel_guc *guc, u16 key, u16 len, u64 va static int __guc_self_cfg(struct intel_guc *guc, u16 key, u16 len, u64 value) { - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; int err = __guc_action_self_cfg(guc, key, len, value); if (unlikely(err)) - i915_probe_error(i915, "Unsuccessful self-config (%pe) key %#hx value %#llx\n", - ERR_PTR(err), key, value); + guc_probe_error(guc, "Unsuccessful self-config (%pe) key %#hx value %#llx\n", + ERR_PTR(err), key, value); return err; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index a7f737c4792e..69ce06faf8cd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -15,6 +15,7 @@ #include "intel_guc_ads.h" #include "intel_guc_capture.h" #include "intel_guc_fwif.h" +#include "intel_guc_print.h" #include "intel_uc.h" #include "i915_drv.h" @@ -427,7 +428,7 @@ static long guc_mmio_reg_state_create(struct intel_guc *guc) guc->ads_regset = temp_set.storage; - drm_dbg(&guc_to_gt(guc)->i915->drm, "Used %zu KB for temporary ADS regset\n", + guc_dbg(guc, "Used %zu KB for temporary ADS regset\n", (temp_set.storage_max * sizeof(struct guc_mmio_reg)) >> 10); return total * sizeof(struct guc_mmio_reg); @@ -621,7 +622,7 @@ static void guc_init_golden_context(struct intel_guc *guc) engine = find_engine_state(gt, engine_class); if (!engine) { - drm_err(>->i915->drm, "No engine state recorded for class %d!\n", + guc_err(guc, "No engine state recorded for class %d!\n", engine_class); ads_blob_write(guc, ads.eng_state_size[guc_class], 0); ads_blob_write(guc, ads.golden_context_lrca[guc_class], 0); @@ -646,7 +647,6 @@ static int guc_capture_prep_lists(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; u32 ads_ggtt, capture_offset, null_ggtt, total_size = 0; struct guc_gt_system_info local_info; struct iosys_map info_map; @@ -751,7 +751,7 @@ engine_instance_list: } if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(total_size)) - drm_warn(&i915->drm, "GuC->ADS->Capture alloc size changed from %d to %d\n", + guc_warn(guc, "ADS capture alloc size changed from %d to %d\n", guc->ads_capture_size, PAGE_ALIGN(total_size)); return PAGE_ALIGN(total_size); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 1c1b85073b4b..fc3b994626a4 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -1506,7 +1506,7 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, if (!ebuf || !ee) return -EINVAL; - cap = ee->capture; + cap = ee->guc_capture; if (!cap || !ee->engine) return -ENODEV; @@ -1576,8 +1576,8 @@ void intel_guc_capture_free_node(struct intel_engine_coredump *ee) if (!ee || !ee->guc_capture_node) return; - guc_capture_add_node_to_cachelist(ee->capture, ee->guc_capture_node); - ee->capture = NULL; + guc_capture_add_node_to_cachelist(ee->guc_capture, ee->guc_capture_node); + ee->guc_capture = NULL; ee->guc_capture_node = NULL; } @@ -1611,7 +1611,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt, (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) { list_del(&n->link); ee->guc_capture_node = n; - ee->capture = guc->capture; + ee->guc_capture = guc->capture; return; } } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 2b22065e87bf..1803a633ed64 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -11,38 +11,23 @@ #include "i915_drv.h" #include "intel_guc_ct.h" -#include "gt/intel_gt.h" +#include "intel_guc_print.h" static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct) { return container_of(ct, struct intel_guc, ct); } -static inline struct intel_gt *ct_to_gt(struct intel_guc_ct *ct) -{ - return guc_to_gt(ct_to_guc(ct)); -} - -static inline struct drm_i915_private *ct_to_i915(struct intel_guc_ct *ct) -{ - return ct_to_gt(ct)->i915; -} - -static inline struct drm_device *ct_to_drm(struct intel_guc_ct *ct) -{ - return &ct_to_i915(ct)->drm; -} - #define CT_ERROR(_ct, _fmt, ...) \ - drm_err(ct_to_drm(_ct), "CT: " _fmt, ##__VA_ARGS__) + guc_err(ct_to_guc(_ct), "CT: " _fmt, ##__VA_ARGS__) #ifdef CONFIG_DRM_I915_DEBUG_GUC #define CT_DEBUG(_ct, _fmt, ...) \ - drm_dbg(ct_to_drm(_ct), "CT: " _fmt, ##__VA_ARGS__) + guc_dbg(ct_to_guc(_ct), "CT: " _fmt, ##__VA_ARGS__) #else #define CT_DEBUG(...) do { } while (0) #endif #define CT_PROBE_ERROR(_ct, _fmt, ...) \ - i915_probe_error(ct_to_i915(ct), "CT: " _fmt, ##__VA_ARGS__) + guc_probe_error(ct_to_guc(ct), "CT: " _fmt, ##__VA_ARGS__) /** * DOC: CTB Blob diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 5b86b2e286e0..3d2249bda368 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -13,6 +13,7 @@ #include "gt/intel_gt_mcr.h" #include "gt/intel_gt_regs.h" #include "intel_guc_fw.h" +#include "intel_guc_print.h" #include "i915_drv.h" static void guc_prepare_xfer(struct intel_gt *gt) @@ -103,8 +104,10 @@ static inline bool guc_ready(struct intel_uncore *uncore, u32 *status) return uk_val == INTEL_GUC_LOAD_STATUS_READY; } -static int guc_wait_ucode(struct intel_uncore *uncore) +static int guc_wait_ucode(struct intel_guc *guc) { + struct intel_gt *gt = guc_to_gt(guc); + struct intel_uncore *uncore = gt->uncore; u32 status; int ret; @@ -127,10 +130,8 @@ static int guc_wait_ucode(struct intel_uncore *uncore) */ ret = wait_for(guc_ready(uncore, &status), 200); if (ret) { - struct drm_device *drm = &uncore->i915->drm; - - drm_info(drm, "GuC load failed: status = 0x%08X\n", status); - drm_info(drm, "GuC load failed: status: Reset = %d, " + guc_info(guc, "load failed: status = 0x%08X\n", status); + guc_info(guc, "load failed: status: Reset = %d, " "BootROM = 0x%02X, UKernel = 0x%02X, " "MIA = 0x%02X, Auth = 0x%02X\n", REG_FIELD_GET(GS_MIA_IN_RESET, status), @@ -140,12 +141,12 @@ static int guc_wait_ucode(struct intel_uncore *uncore) REG_FIELD_GET(GS_AUTH_STATUS_MASK, status)); if ((status & GS_BOOTROM_MASK) == GS_BOOTROM_RSA_FAILED) { - drm_info(drm, "GuC firmware signature verification failed\n"); + guc_info(guc, "firmware signature verification failed\n"); ret = -ENOEXEC; } if (REG_FIELD_GET(GS_UKERNEL_MASK, status) == INTEL_GUC_LOAD_STATUS_EXCEPTION) { - drm_info(drm, "GuC firmware exception. EIP: %#x\n", + guc_info(guc, "firmware exception. EIP: %#x\n", intel_uncore_read(uncore, SOFT_SCRATCH(13))); ret = -ENXIO; } @@ -194,7 +195,7 @@ int intel_guc_fw_upload(struct intel_guc *guc) if (ret) goto out; - ret = guc_wait_ucode(uncore); + ret = guc_wait_ucode(guc); if (ret) goto out; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 68331c538b0a..c3792ddeec80 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -12,6 +12,7 @@ #include "i915_memcpy.h" #include "intel_guc_capture.h" #include "intel_guc_log.h" +#include "intel_guc_print.h" #if defined(CONFIG_DRM_I915_DEBUG_GUC) #define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_2M @@ -39,7 +40,6 @@ struct guc_log_section { static void _guc_log_init_sizes(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; static const struct guc_log_section sections[GUC_LOG_SECTIONS_LIMIT] = { { GUC_LOG_CRASH_MASK >> GUC_LOG_CRASH_SHIFT, @@ -82,12 +82,12 @@ static void _guc_log_init_sizes(struct intel_guc_log *log) } if (!IS_ALIGNED(log->sizes[i].bytes, log->sizes[i].units)) - drm_err(&i915->drm, "Mis-aligned GuC log %s size: 0x%X vs 0x%X!", + guc_err(guc, "Mis-aligned log %s size: 0x%X vs 0x%X!\n", sections[i].name, log->sizes[i].bytes, log->sizes[i].units); log->sizes[i].count = log->sizes[i].bytes / log->sizes[i].units; if (!log->sizes[i].count) { - drm_err(&i915->drm, "Zero GuC log %s size!", sections[i].name); + guc_err(guc, "Zero log %s size!\n", sections[i].name); } else { /* Size is +1 unit */ log->sizes[i].count--; @@ -95,14 +95,14 @@ static void _guc_log_init_sizes(struct intel_guc_log *log) /* Clip to field size */ if (log->sizes[i].count > sections[i].max) { - drm_err(&i915->drm, "GuC log %s size too large: %d vs %d!", + guc_err(guc, "log %s size too large: %d vs %d!\n", sections[i].name, log->sizes[i].count + 1, sections[i].max + 1); log->sizes[i].count = sections[i].max; } } if (log->sizes[GUC_LOG_SECTIONS_CRASH].units != log->sizes[GUC_LOG_SECTIONS_DEBUG].units) { - drm_err(&i915->drm, "Unit mis-match for GuC log crash and debug sections: %d vs %d!", + guc_err(guc, "Unit mismatch for crash and debug sections: %d vs %d!\n", log->sizes[GUC_LOG_SECTIONS_CRASH].units, log->sizes[GUC_LOG_SECTIONS_DEBUG].units); log->sizes[GUC_LOG_SECTIONS_CRASH].units = log->sizes[GUC_LOG_SECTIONS_DEBUG].units; @@ -374,6 +374,7 @@ size_t intel_guc_get_log_buffer_offset(struct intel_guc_log *log, static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { + struct intel_guc *guc = log_to_guc(log); unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; struct guc_log_buffer_state log_buf_state_local; @@ -383,7 +384,7 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) mutex_lock(&log->relay.lock); - if (WARN_ON(!intel_guc_log_relay_created(log))) + if (guc_WARN_ON(guc, !intel_guc_log_relay_created(log))) goto out_unlock; /* Get the pointer to shared GuC log buffer */ @@ -398,7 +399,7 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) * Used rate limited to avoid deluge of messages, logs might be * getting consumed by User at a slow rate. */ - DRM_ERROR_RATELIMITED("no sub-buffer to copy general logs\n"); + guc_err_ratelimited(guc, "no sub-buffer to copy general logs\n"); log->relay.full_count++; goto out_unlock; @@ -451,7 +452,7 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) write_offset = buffer_size; } else if (unlikely((read_offset > buffer_size) || (write_offset > buffer_size))) { - DRM_ERROR("invalid log buffer state\n"); + guc_err(guc, "invalid log buffer state\n"); /* copy whole buffer as offsets are unreliable */ read_offset = 0; write_offset = buffer_size; @@ -547,7 +548,7 @@ static int guc_log_relay_create(struct intel_guc_log *log) subbuf_size, n_subbufs, &relay_callbacks, dev_priv); if (!guc_log_relay_chan) { - DRM_ERROR("Couldn't create relay chan for GuC logging\n"); + guc_err(guc, "Couldn't create relay channel for logging\n"); ret = -ENOMEM; return ret; @@ -596,9 +597,8 @@ static u32 __get_default_log_level(struct intel_guc_log *log) } if (i915->params.guc_log_level > GUC_LOG_LEVEL_MAX) { - DRM_WARN("Incompatible option detected: %s=%d, %s!\n", - "guc_log_level", i915->params.guc_log_level, - "verbosity too high"); + guc_warn(guc, "Log verbosity param out of range: %d > %d!\n", + i915->params.guc_log_level, GUC_LOG_LEVEL_MAX); return (IS_ENABLED(CONFIG_DRM_I915_DEBUG) || IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) ? GUC_LOG_LEVEL_MAX : GUC_LOG_LEVEL_DISABLED; @@ -641,15 +641,15 @@ int intel_guc_log_create(struct intel_guc_log *log) log->buf_addr = vaddr; log->level = __get_default_log_level(log); - DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", - log->level, str_enabled_disabled(log->level), - str_yes_no(GUC_LOG_LEVEL_IS_VERBOSE(log->level)), - GUC_LOG_LEVEL_TO_VERBOSITY(log->level)); + guc_dbg(guc, "guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", + log->level, str_enabled_disabled(log->level), + str_yes_no(GUC_LOG_LEVEL_IS_VERBOSE(log->level)), + GUC_LOG_LEVEL_TO_VERBOSITY(log->level)); return 0; err: - DRM_ERROR("Failed to allocate or map GuC log buffer. %d\n", ret); + guc_err(guc, "Failed to allocate or map log buffer %pe\n", ERR_PTR(ret)); return ret; } @@ -687,7 +687,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) GUC_LOG_LEVEL_IS_ENABLED(level), GUC_LOG_LEVEL_TO_VERBOSITY(level)); if (ret) { - DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret); + guc_dbg(guc, "guc_log_control action failed %pe\n", ERR_PTR(ret)); goto out_unlock; } @@ -905,7 +905,7 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p, map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC); if (IS_ERR(map)) { - DRM_DEBUG("Failed to pin object\n"); + guc_dbg(guc, "Failed to pin log object: %pe\n", map); drm_puts(p, "(log data unaccessible)\n"); free_page((unsigned long)page); return PTR_ERR(map); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_print.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_print.h new file mode 100644 index 000000000000..e75989d4ba06 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_print.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_GUC_PRINT__ +#define __INTEL_GUC_PRINT__ + +#include "gt/intel_gt.h" +#include "gt/intel_gt_print.h" + +#define guc_printk(_guc, _level, _fmt, ...) \ + gt_##_level(guc_to_gt(_guc), "GUC: " _fmt, ##__VA_ARGS__) + +#define guc_err(_guc, _fmt, ...) \ + guc_printk((_guc), err, _fmt, ##__VA_ARGS__) + +#define guc_warn(_guc, _fmt, ...) \ + guc_printk((_guc), warn, _fmt, ##__VA_ARGS__) + +#define guc_notice(_guc, _fmt, ...) \ + guc_printk((_guc), notice, _fmt, ##__VA_ARGS__) + +#define guc_info(_guc, _fmt, ...) \ + guc_printk((_guc), info, _fmt, ##__VA_ARGS__) + +#define guc_dbg(_guc, _fmt, ...) \ + guc_printk((_guc), dbg, _fmt, ##__VA_ARGS__) + +#define guc_err_ratelimited(_guc, _fmt, ...) \ + guc_printk((_guc), err_ratelimited, _fmt, ##__VA_ARGS__) + +#define guc_probe_error(_guc, _fmt, ...) \ + guc_printk((_guc), probe_error, _fmt, ##__VA_ARGS__) + +#define guc_WARN(_guc, _cond, _fmt, ...) \ + gt_WARN(guc_to_gt(_guc), _cond, "GUC: " _fmt, ##__VA_ARGS__) + +#define guc_WARN_ONCE(_guc, _cond, _fmt, ...) \ + gt_WARN_ONCE(guc_to_gt(_guc), _cond, "GUC: " _fmt, ##__VA_ARGS__) + +#define guc_WARN_ON(_guc, _cond) \ + gt_WARN(guc_to_gt(_guc), _cond, "%s(%s)", "guc_WARN_ON", __stringify(_cond)) + +#define guc_WARN_ON_ONCE(_guc, _cond) \ + gt_WARN_ONCE(guc_to_gt(_guc), _cond, "%s(%s)", "guc_WARN_ON_ONCE", __stringify(_cond)) + +#endif /* __INTEL_GUC_PRINT__ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index b436dd7f12e4..53f3ed3244d5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -27,6 +27,7 @@ #include "intel_guc_ads.h" #include "intel_guc_capture.h" +#include "intel_guc_print.h" #include "intel_guc_submission.h" #include "i915_drv.h" @@ -1443,8 +1444,7 @@ static void guc_init_engine_stats(struct intel_guc *guc) int ret = guc_action_enable_usage_stats(guc); if (ret) - drm_err(>->i915->drm, - "Failed to enable usage stats: %d!\n", ret); + guc_err(guc, "Failed to enable usage stats: %pe\n", ERR_PTR(ret)); } } @@ -1702,7 +1702,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st goto next_context; guilty = false; - rq = intel_context_find_active_request(ce); + rq = intel_context_get_active_request(ce); if (!rq) { head = ce->ring->tail; goto out_replay; @@ -1715,6 +1715,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st head = intel_ring_wrap(ce->ring, rq->head); __i915_request_reset(rq, guilty); + i915_request_put(rq); out_replay: guc_reset_state(ce, head, guilty); next_context: @@ -3585,8 +3586,7 @@ static int guc_request_alloc(struct i915_request *rq) intel_context_sched_disable_unpin(ce); else if (intel_context_is_closed(ce)) if (wait_for(context_close_done(ce), 1500)) - drm_warn(&guc_to_gt(guc)->i915->drm, - "timed out waiting on context sched close before realloc\n"); + guc_warn(guc, "timed out waiting on context sched close before realloc\n"); /* * Call pin_guc_id here rather than in the pinning step as with * dma_resv, contexts can be repeatedly pinned / unpinned trashing the @@ -4349,11 +4349,14 @@ static int __guc_action_set_scheduling_policies(struct intel_guc *guc, ret = intel_guc_send(guc, (u32 *)&policy->h2g, __guc_scheduling_policy_action_size(policy)); - if (ret < 0) + if (ret < 0) { + guc_probe_error(guc, "Failed to configure global scheduling policies: %pe!\n", + ERR_PTR(ret)); return ret; + } if (ret != policy->count) { - drm_warn(&guc_to_gt(guc)->i915->drm, "GuC global scheduler policy processed %d of %d KLVs!", + guc_warn(guc, "global scheduler policy processed %d of %d KLVs!", ret, policy->count); if (ret > policy->count) return -EPROTO; @@ -4367,7 +4370,7 @@ static int guc_init_global_schedule_policy(struct intel_guc *guc) struct scheduling_policy policy; struct intel_gt *gt = guc_to_gt(guc); intel_wakeref_t wakeref; - int ret = 0; + int ret; if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 1, 0)) return 0; @@ -4385,10 +4388,6 @@ static int guc_init_global_schedule_policy(struct intel_guc *guc) yield, ARRAY_SIZE(yield)); ret = __guc_action_set_scheduling_policies(guc, &policy); - if (ret) - i915_probe_error(gt->i915, - "Failed to configure global scheduling policies: %pe!\n", - ERR_PTR(ret)); } return ret; @@ -4487,21 +4486,18 @@ g2h_context_lookup(struct intel_guc *guc, u32 ctx_id) struct intel_context *ce; if (unlikely(ctx_id >= GUC_MAX_CONTEXT_ID)) { - drm_err(&guc_to_gt(guc)->i915->drm, - "Invalid ctx_id %u\n", ctx_id); + guc_err(guc, "Invalid ctx_id %u\n", ctx_id); return NULL; } ce = __get_context(guc, ctx_id); if (unlikely(!ce)) { - drm_err(&guc_to_gt(guc)->i915->drm, - "Context is NULL, ctx_id %u\n", ctx_id); + guc_err(guc, "Context is NULL, ctx_id %u\n", ctx_id); return NULL; } if (unlikely(intel_context_is_child(ce))) { - drm_err(&guc_to_gt(guc)->i915->drm, - "Context is child, ctx_id %u\n", ctx_id); + guc_err(guc, "Context is child, ctx_id %u\n", ctx_id); return NULL; } @@ -4516,7 +4512,7 @@ int intel_guc_deregister_done_process_msg(struct intel_guc *guc, u32 ctx_id; if (unlikely(len < 1)) { - drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u\n", len); + guc_err(guc, "Invalid length %u\n", len); return -EPROTO; } ctx_id = msg[0]; @@ -4568,7 +4564,7 @@ int intel_guc_sched_done_process_msg(struct intel_guc *guc, u32 ctx_id; if (unlikely(len < 2)) { - drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u\n", len); + guc_err(guc, "Invalid length %u\n", len); return -EPROTO; } ctx_id = msg[0]; @@ -4580,8 +4576,7 @@ int intel_guc_sched_done_process_msg(struct intel_guc *guc, if (unlikely(context_destroyed(ce) || (!context_pending_enable(ce) && !context_pending_disable(ce)))) { - drm_err(&guc_to_gt(guc)->i915->drm, - "Bad context sched_state 0x%x, ctx_id %u\n", + guc_err(guc, "Bad context sched_state 0x%x, ctx_id %u\n", ce->guc_state.sched_state, ctx_id); return -EPROTO; } @@ -4665,12 +4660,15 @@ static void guc_handle_context_reset(struct intel_guc *guc, { trace_intel_context_reset(ce); + drm_dbg(&guc_to_gt(guc)->i915->drm, "Got GuC reset of 0x%04X, exiting = %d, banned = %d\n", + ce->guc_id.id, test_bit(CONTEXT_EXITING, &ce->flags), + test_bit(CONTEXT_BANNED, &ce->flags)); + if (likely(intel_context_is_schedulable(ce))) { capture_error_state(guc, ce); guc_context_replay(ce); } else { - drm_info(&guc_to_gt(guc)->i915->drm, - "Ignoring context reset notification of exiting context 0x%04X on %s", + guc_info(guc, "Ignoring context reset notification of exiting context 0x%04X on %s", ce->guc_id.id, ce->engine->name); } } @@ -4683,7 +4681,7 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, int ctx_id; if (unlikely(len != 1)) { - drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); + guc_err(guc, "Invalid length %u", len); return -EPROTO; } @@ -4716,13 +4714,13 @@ int intel_guc_error_capture_process_msg(struct intel_guc *guc, u32 status; if (unlikely(len != 1)) { - drm_dbg(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); + guc_dbg(guc, "Invalid length %u", len); return -EPROTO; } status = msg[0] & INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK; if (status == INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE) - drm_warn(&guc_to_gt(guc)->i915->drm, "G2H-Error capture no space"); + guc_warn(guc, "No space for error capture"); intel_guc_capture_process(guc); @@ -4754,24 +4752,36 @@ static void reset_fail_worker_func(struct work_struct *w) guc->submission_state.reset_fail_mask = 0; spin_unlock_irqrestore(&guc->submission_state.lock, flags); - if (likely(reset_fail_mask)) + if (likely(reset_fail_mask)) { + struct intel_engine_cs *engine; + enum intel_engine_id id; + + /* + * GuC is toast at this point - it dead loops after sending the failed + * reset notification. So need to manually determine the guilty context. + * Note that it should be reliable to do this here because the GuC is + * toast and will not be scheduling behind the KMD's back. + */ + for_each_engine_masked(engine, gt, reset_fail_mask, id) + intel_guc_find_hung_context(engine); + intel_gt_handle_error(gt, reset_fail_mask, I915_ERROR_CAPTURE, - "GuC failed to reset engine mask=0x%x\n", + "GuC failed to reset engine mask=0x%x", reset_fail_mask); + } } int intel_guc_engine_failure_process_msg(struct intel_guc *guc, const u32 *msg, u32 len) { struct intel_engine_cs *engine; - struct intel_gt *gt = guc_to_gt(guc); u8 guc_class, instance; u32 reason; unsigned long flags; if (unlikely(len != 3)) { - drm_err(>->i915->drm, "Invalid length %u", len); + guc_err(guc, "Invalid length %u", len); return -EPROTO; } @@ -4781,8 +4791,7 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, engine = intel_guc_lookup_engine(guc, guc_class, instance); if (unlikely(!engine)) { - drm_err(>->i915->drm, - "Invalid engine %d:%d", guc_class, instance); + guc_err(guc, "Invalid engine %d:%d", guc_class, instance); return -EPROTO; } @@ -4790,7 +4799,7 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, * This is an unexpected failure of a hardware feature. So, log a real * error message not just the informational that comes with the reset. */ - drm_err(>->i915->drm, "GuC engine reset request failed on %d:%d (%s) because 0x%08X", + guc_err(guc, "Engine reset failed on %d:%d (%s) because 0x%08X", guc_class, instance, engine->name, reason); spin_lock_irqsave(&guc->submission_state.lock, flags); @@ -4820,6 +4829,8 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) xa_lock_irqsave(&guc->context_lookup, flags); xa_for_each(&guc->context_lookup, index, ce) { + bool found; + if (!kref_get_unless_zero(&ce->ref)) continue; @@ -4836,10 +4847,18 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) goto next; } + found = false; + spin_lock(&ce->guc_state.lock); list_for_each_entry(rq, &ce->guc_state.requests, sched.link) { if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE) continue; + found = true; + break; + } + spin_unlock(&ce->guc_state.lock); + + if (found) { intel_engine_set_hung_context(engine, ce); /* Can only cope with one hang at a time... */ @@ -4847,6 +4866,7 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine) xa_lock(&guc->context_lookup); goto done; } + next: intel_context_put(ce); xa_lock(&guc->context_lookup); @@ -5342,8 +5362,8 @@ guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count, GEM_BUG_ON(!is_power_of_2(sibling->mask)); if (sibling->mask & ve->base.mask) { - DRM_DEBUG("duplicate %s entry in load balancer\n", - sibling->name); + guc_dbg(guc, "duplicate %s entry in load balancer\n", + sibling->name); err = -EINVAL; goto err_put; } @@ -5352,8 +5372,8 @@ guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count, ve->base.logical_mask |= sibling->logical_mask; if (n != 0 && ve->base.class != sibling->class) { - DRM_DEBUG("invalid mixing of engine class, sibling %d, already %d\n", - sibling->class, ve->base.class); + guc_dbg(guc, "invalid mixing of engine class, sibling %d, already %d\n", + sibling->class, ve->base.class); err = -EINVAL; goto err_put; } else if (n == 0) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 9a8a1abf71d7..de7f987cf611 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -6,11 +6,13 @@ #include <linux/string_helpers.h> #include "gt/intel_gt.h" +#include "gt/intel_gt_print.h" #include "gt/intel_reset.h" #include "intel_gsc_fw.h" #include "intel_gsc_uc.h" #include "intel_guc.h" #include "intel_guc_ads.h" +#include "intel_guc_print.h" #include "intel_guc_submission.h" #include "gt/intel_rps.h" #include "intel_uc.h" @@ -67,14 +69,14 @@ static int __intel_uc_reset_hw(struct intel_uc *uc) ret = intel_reset_guc(gt); if (ret) { - DRM_ERROR("Failed to reset GuC, ret = %d\n", ret); + gt_err(gt, "Failed to reset GuC, ret = %d\n", ret); return ret; } guc_status = intel_uncore_read(gt->uncore, GUC_STATUS); - WARN(!(guc_status & GS_MIA_IN_RESET), - "GuC status: 0x%x, MIA core expected to be in reset\n", - guc_status); + gt_WARN(gt, !(guc_status & GS_MIA_IN_RESET), + "GuC status: 0x%x, MIA core expected to be in reset\n", + guc_status); return ret; } @@ -252,15 +254,13 @@ static int guc_enable_communication(struct intel_guc *guc) intel_guc_ct_event_handler(&guc->ct); spin_unlock_irq(gt->irq_lock); - drm_dbg(&i915->drm, "GuC communication enabled\n"); + guc_dbg(guc, "communication enabled\n"); return 0; } static void guc_disable_communication(struct intel_guc *guc) { - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; - /* * Events generated during or after CT disable are logged by guc in * via mmio. Make sure the register is clear before disabling CT since @@ -280,11 +280,12 @@ static void guc_disable_communication(struct intel_guc *guc) */ guc_get_mmio_msg(guc); - drm_dbg(&i915->drm, "GuC communication disabled\n"); + guc_dbg(guc, "communication disabled\n"); } static void __uc_fetch_firmwares(struct intel_uc *uc) { + struct intel_gt *gt = uc_to_gt(uc); int err; GEM_BUG_ON(!intel_uc_wants_guc(uc)); @@ -293,15 +294,13 @@ static void __uc_fetch_firmwares(struct intel_uc *uc) if (err) { /* Make sure we transition out of transient "SELECTED" state */ if (intel_uc_wants_huc(uc)) { - drm_dbg(&uc_to_gt(uc)->i915->drm, - "Failed to fetch GuC: %d disabling HuC\n", err); + gt_dbg(gt, "Failed to fetch GuC fw (%pe) disabling HuC\n", ERR_PTR(err)); intel_uc_fw_change_status(&uc->huc.fw, INTEL_UC_FIRMWARE_ERROR); } if (intel_uc_wants_gsc_uc(uc)) { - drm_dbg(&uc_to_gt(uc)->i915->drm, - "Failed to fetch GuC: %d disabling GSC\n", err); + gt_dbg(gt, "Failed to fetch GuC fw (%pe) disabling GSC\n", ERR_PTR(err)); intel_uc_fw_change_status(&uc->gsc.fw, INTEL_UC_FIRMWARE_ERROR); } @@ -382,7 +381,7 @@ static int uc_init_wopcm(struct intel_uc *uc) int err; if (unlikely(!base || !size)) { - i915_probe_error(gt->i915, "Unsuccessful WOPCM partitioning\n"); + gt_probe_error(gt, "Unsuccessful WOPCM partitioning\n"); return -E2BIG; } @@ -413,13 +412,13 @@ static int uc_init_wopcm(struct intel_uc *uc) return 0; err_out: - i915_probe_error(gt->i915, "Failed to init uC WOPCM registers!\n"); - i915_probe_error(gt->i915, "%s(%#x)=%#x\n", "DMA_GUC_WOPCM_OFFSET", - i915_mmio_reg_offset(DMA_GUC_WOPCM_OFFSET), - intel_uncore_read(uncore, DMA_GUC_WOPCM_OFFSET)); - i915_probe_error(gt->i915, "%s(%#x)=%#x\n", "GUC_WOPCM_SIZE", - i915_mmio_reg_offset(GUC_WOPCM_SIZE), - intel_uncore_read(uncore, GUC_WOPCM_SIZE)); + gt_probe_error(gt, "Failed to init uC WOPCM registers!\n"); + gt_probe_error(gt, "%s(%#x)=%#x\n", "DMA_GUC_WOPCM_OFFSET", + i915_mmio_reg_offset(DMA_GUC_WOPCM_OFFSET), + intel_uncore_read(uncore, DMA_GUC_WOPCM_OFFSET)); + gt_probe_error(gt, "%s(%#x)=%#x\n", "GUC_WOPCM_SIZE", + i915_mmio_reg_offset(GUC_WOPCM_SIZE), + intel_uncore_read(uncore, GUC_WOPCM_SIZE)); return err; } @@ -449,20 +448,19 @@ static int __uc_check_hw(struct intel_uc *uc) return 0; } -static void print_fw_ver(struct intel_uc *uc, struct intel_uc_fw *fw) +static void print_fw_ver(struct intel_gt *gt, struct intel_uc_fw *fw) { - struct drm_i915_private *i915 = uc_to_gt(uc)->i915; - - drm_info(&i915->drm, "%s firmware %s version %u.%u.%u\n", - intel_uc_fw_type_repr(fw->type), fw->file_selected.path, - fw->file_selected.ver.major, - fw->file_selected.ver.minor, - fw->file_selected.ver.patch); + gt_info(gt, "%s firmware %s version %u.%u.%u\n", + intel_uc_fw_type_repr(fw->type), fw->file_selected.path, + fw->file_selected.ver.major, + fw->file_selected.ver.minor, + fw->file_selected.ver.patch); } static int __uc_init_hw(struct intel_uc *uc) { - struct drm_i915_private *i915 = uc_to_gt(uc)->i915; + struct intel_gt *gt = uc_to_gt(uc); + struct drm_i915_private *i915 = gt->i915; struct intel_guc *guc = &uc->guc; struct intel_huc *huc = &uc->huc; int ret, attempts; @@ -470,10 +468,10 @@ static int __uc_init_hw(struct intel_uc *uc) GEM_BUG_ON(!intel_uc_supports_guc(uc)); GEM_BUG_ON(!intel_uc_wants_guc(uc)); - print_fw_ver(uc, &guc->fw); + print_fw_ver(gt, &guc->fw); if (intel_uc_uses_huc(uc)) - print_fw_ver(uc, &huc->fw); + print_fw_ver(gt, &huc->fw); if (!intel_uc_fw_is_loadable(&guc->fw)) { ret = __uc_check_hw(uc) || @@ -514,8 +512,8 @@ static int __uc_init_hw(struct intel_uc *uc) if (ret == 0) break; - DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and " - "retry %d more time(s)\n", ret, attempts); + gt_dbg(gt, "GuC fw load failed (%pe) will reset and retry %d more time(s)\n", + ERR_PTR(ret), attempts); } /* Did we succeded or run out of retries? */ @@ -551,10 +549,10 @@ static int __uc_init_hw(struct intel_uc *uc) intel_gsc_uc_load_start(&uc->gsc); - drm_info(&i915->drm, "GuC submission %s\n", - str_enabled_disabled(intel_uc_uses_guc_submission(uc))); - drm_info(&i915->drm, "GuC SLPC %s\n", - str_enabled_disabled(intel_uc_uses_guc_slpc(uc))); + gt_info(gt, "GuC submission %s\n", + str_enabled_disabled(intel_uc_uses_guc_submission(uc))); + gt_info(gt, "GuC SLPC %s\n", + str_enabled_disabled(intel_uc_uses_guc_slpc(uc))); return 0; @@ -572,12 +570,12 @@ err_out: __uc_sanitize(uc); if (!ret) { - drm_notice(&i915->drm, "GuC is uninitialized\n"); + gt_notice(gt, "GuC is uninitialized\n"); /* We want to run without GuC submission */ return 0; } - i915_probe_error(i915, "GuC initialization failed %d\n", ret); + gt_probe_error(gt, "GuC initialization failed %pe\n", ERR_PTR(ret)); /* We want to keep KMS alive */ return -EIO; @@ -690,7 +688,7 @@ void intel_uc_suspend(struct intel_uc *uc) with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) { err = intel_guc_suspend(guc); if (err) - DRM_DEBUG_DRIVER("Failed to suspend GuC, err=%d", err); + guc_dbg(guc, "Failed to suspend, %pe", ERR_PTR(err)); } } @@ -718,7 +716,7 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication) err = intel_guc_resume(guc); if (err) { - DRM_DEBUG_DRIVER("Failed to resume GuC, err=%d", err); + guc_dbg(guc, "Failed to resume, %pe", ERR_PTR(err)); return err; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 48c838b4ea62..4295306487c7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -696,6 +696,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, (IS_METEORLAKE(__i915) && \ IS_DISPLAY_STEP(__i915, since, until)) +#define IS_MTL_MEDIA_STEP(__i915, since, until) \ + (IS_METEORLAKE(__i915) && \ + IS_MEDIA_STEP(__i915, since, until)) + /* * DG2 hardware steppings are a bit unusual. The hardware design was forked to * create three variants (G10, G11, and G12) which each have distinct diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 9d5d5a397b64..904f21e1380c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1370,14 +1370,14 @@ static void engine_record_execlists(struct intel_engine_coredump *ee) } static bool record_context(struct i915_gem_context_coredump *e, - const struct i915_request *rq) + struct intel_context *ce) { struct i915_gem_context *ctx; struct task_struct *task; bool simulated; rcu_read_lock(); - ctx = rcu_dereference(rq->context->gem_context); + ctx = rcu_dereference(ce->gem_context); if (ctx && !kref_get_unless_zero(&ctx->ref)) ctx = NULL; rcu_read_unlock(); @@ -1396,8 +1396,8 @@ static bool record_context(struct i915_gem_context_coredump *e, e->guilty = atomic_read(&ctx->guilty_count); e->active = atomic_read(&ctx->active_count); - e->total_runtime = intel_context_get_total_runtime_ns(rq->context); - e->avg_runtime = intel_context_get_avg_runtime_ns(rq->context); + e->total_runtime = intel_context_get_total_runtime_ns(ce); + e->avg_runtime = intel_context_get_avg_runtime_ns(ce); simulated = i915_gem_context_no_error_capture(ctx); @@ -1532,15 +1532,37 @@ intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_ return ee; } +static struct intel_engine_capture_vma * +engine_coredump_add_context(struct intel_engine_coredump *ee, + struct intel_context *ce, + gfp_t gfp) +{ + struct intel_engine_capture_vma *vma = NULL; + + ee->simulated |= record_context(&ee->context, ce); + if (ee->simulated) + return NULL; + + /* + * We need to copy these to an anonymous buffer + * as the simplest method to avoid being overwritten + * by userspace. + */ + vma = capture_vma(vma, ce->ring->vma, "ring", gfp); + vma = capture_vma(vma, ce->state, "HW context", gfp); + + return vma; +} + struct intel_engine_capture_vma * intel_engine_coredump_add_request(struct intel_engine_coredump *ee, struct i915_request *rq, gfp_t gfp) { - struct intel_engine_capture_vma *vma = NULL; + struct intel_engine_capture_vma *vma; - ee->simulated |= record_context(&ee->context, rq); - if (ee->simulated) + vma = engine_coredump_add_context(ee, rq->context, gfp); + if (!vma) return NULL; /* @@ -1550,8 +1572,6 @@ intel_engine_coredump_add_request(struct intel_engine_coredump *ee, */ vma = capture_vma_snapshot(vma, rq->batch_res, gfp, "batch"); vma = capture_user(vma, rq, gfp); - vma = capture_vma(vma, rq->ring->vma, "ring", gfp); - vma = capture_vma(vma, rq->context->state, "HW context", gfp); ee->rq_head = rq->head; ee->rq_post = rq->postfix; @@ -1596,54 +1616,36 @@ capture_engine(struct intel_engine_cs *engine, { struct intel_engine_capture_vma *capture = NULL; struct intel_engine_coredump *ee; - struct intel_context *ce; + struct intel_context *ce = NULL; struct i915_request *rq = NULL; - unsigned long flags; ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); if (!ee) return NULL; - ce = intel_engine_get_hung_context(engine); - if (ce) { - intel_engine_clear_hung_context(engine); - rq = intel_context_find_active_request(ce); - if (!rq || !i915_request_started(rq)) - goto no_request_capture; - } else { - /* - * Getting here with GuC enabled means it is a forced error capture - * with no actual hang. So, no need to attempt the execlist search. - */ - if (!intel_uc_uses_guc_submission(&engine->gt->uc)) { - spin_lock_irqsave(&engine->sched_engine->lock, flags); - rq = intel_engine_execlist_find_hung_request(engine); - spin_unlock_irqrestore(&engine->sched_engine->lock, - flags); - } - } - if (rq) - rq = i915_request_get_rcu(rq); + intel_engine_get_hung_entity(engine, &ce, &rq); + if (rq && !i915_request_started(rq)) + drm_info(&engine->gt->i915->drm, "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n", + engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id); - if (!rq) - goto no_request_capture; - - capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); - if (!capture) { + if (rq) { + capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL); i915_request_put(rq); - goto no_request_capture; + } else if (ce) { + capture = engine_coredump_add_context(ee, ce, ATOMIC_MAYFAIL); } - if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) - intel_guc_capture_get_matching_node(engine->gt, ee, ce); - intel_engine_coredump_add_vma(ee, capture, compress); - i915_request_put(rq); + if (capture) { + intel_engine_coredump_add_vma(ee, capture, compress); - return ee; + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + intel_guc_capture_get_matching_node(engine->gt, ee, ce); + } else { + kfree(ee); + ee = NULL; + } -no_request_capture: - kfree(ee); - return NULL; + return ee; } static void diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index efc75cc2ffdb..56027ffbce51 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -94,7 +94,7 @@ struct intel_engine_coredump { struct intel_instdone instdone; /* GuC matched capture-lists info */ - struct intel_guc_state_capture *capture; + struct intel_guc_state_capture *guc_capture; struct __guc_capture_parsed_output *guc_capture_node; struct i915_gem_context_coredump { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bad36a67d873..3b2642397b82 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8114,10 +8114,6 @@ enum skl_power_gate { #define CLKGATE_DIS_MISC _MMIO(0x46534) #define CLKGATE_DIS_MISC_DMASC_GATING_DIS REG_BIT(21) -#define GEN12_CULLBIT1 _MMIO(0x6100) -#define GEN12_CULLBIT2 _MMIO(0x7030) -#define GEN12_STATE_ACK_DEBUG _MMIO(0x20BC) - #define _MTL_CLKGATE_DIS_TRANS_A 0x604E8 #define _MTL_CLKGATE_DIS_TRANS_B 0x614E8 #define MTL_CLKGATE_DIS_TRANS(trans) _MMIO_TRANS2(trans, _MTL_CLKGATE_DIS_TRANS_A) diff --git a/drivers/gpu/drm/i915/selftests/igt_flush_test.c b/drivers/gpu/drm/i915/selftests/igt_flush_test.c index b484e12df417..29110abb4fe0 100644 --- a/drivers/gpu/drm/i915/selftests/igt_flush_test.c +++ b/drivers/gpu/drm/i915/selftests/igt_flush_test.c @@ -14,21 +14,27 @@ int igt_flush_test(struct drm_i915_private *i915) { - struct intel_gt *gt = to_gt(i915); - int ret = intel_gt_is_wedged(gt) ? -EIO : 0; + struct intel_gt *gt; + unsigned int i; + int ret = 0; - cond_resched(); + for_each_gt(gt, i915, i) { + if (intel_gt_is_wedged(gt)) + ret = -EIO; - if (intel_gt_wait_for_idle(gt, HZ * 3) == -ETIME) { - pr_err("%pS timed out, cancelling all further testing.\n", - __builtin_return_address(0)); + cond_resched(); - GEM_TRACE("%pS timed out.\n", - __builtin_return_address(0)); - GEM_TRACE_DUMP(); + if (intel_gt_wait_for_idle(gt, HZ * 3) == -ETIME) { + pr_err("%pS timed out, cancelling all further testing.\n", + __builtin_return_address(0)); - intel_gt_set_wedged(gt); - ret = -EIO; + GEM_TRACE("%pS timed out.\n", + __builtin_return_address(0)); + GEM_TRACE_DUMP(); + + intel_gt_set_wedged(gt); + ret = -EIO; + } } return ret; diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 369e495d0c3e..b451dee64d34 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -7,7 +7,6 @@ config DRM_MEDIATEK depends on HAVE_ARM_SMCCC depends on OF depends on MTK_MMSYS - select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c index cdfa648910b2..b640bc0559e7 100644 --- a/drivers/gpu/drm/mediatek/mtk_cec.c +++ b/drivers/gpu/drm/mediatek/mtk_cec.c @@ -12,6 +12,8 @@ #include <linux/platform_device.h> #include "mtk_cec.h" +#include "mtk_hdmi.h" +#include "mtk_drm_drv.h" #define TR_CONFIG 0x00 #define CLEAR_CEC_IRQ BIT(15) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_aal.c b/drivers/gpu/drm/mediatek/mtk_disp_aal.c index 0f9d7efb61d7..434e8a9ce8ab 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_aal.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_aal.c @@ -14,6 +14,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DISP_AAL_EN 0x0000 #define AAL_EN BIT(0) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c index 3a53ebc4e172..1773379b2439 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c @@ -14,6 +14,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DISP_CCORR_EN 0x0000 #define CCORR_EN BIT(0) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_color.c b/drivers/gpu/drm/mediatek/mtk_disp_color.c index 473f5bb5cbad..cac9206079e7 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_color.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_color.c @@ -14,6 +14,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DISP_COLOR_CFG_MAIN 0x0400 #define DISP_COLOR_START_MT2701 0x0f00 diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c index bbd558a036ec..c844942603f7 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c @@ -14,6 +14,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DISP_GAMMA_EN 0x0000 #define GAMMA_EN BIT(0) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 84daeaffab6a..9d8c986700ee 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -19,6 +19,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DISP_REG_OVL_INTEN 0x0004 #define OVL_FME_CPL_INT BIT(1) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 0ec2e4049e07..a5a0c3bac35d 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -17,6 +17,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DISP_REG_RDMA_INT_ENABLE 0x0000 #define DISP_REG_RDMA_INT_STATUS 0x0004 diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index b4feaabdb6a7..1f94fcc144d3 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -1693,7 +1693,7 @@ static int mtk_dp_training(struct mtk_dp *mtk_dp) break; default: return -EINVAL; - }; + } continue; } diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 4317595a15d1..948a53f1f4b3 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -14,6 +14,7 @@ #include <linux/of_graph.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> +#include <linux/soc/mediatek/mtk-mmsys.h> #include <linux/types.h> #include <video/videomode.h> @@ -29,6 +30,7 @@ #include "mtk_disp_drv.h" #include "mtk_dpi_regs.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" enum mtk_dpi_out_bit_num { MTK_DPI_OUT_BIT_NUM_8BITS, @@ -66,6 +68,7 @@ struct mtk_dpi { struct drm_connector *connector; void __iomem *regs; struct device *dev; + struct device *mmsys_dev; struct clk *engine_clk; struct clk *pixel_clk; struct clk *tvd_clk; @@ -134,6 +137,7 @@ struct mtk_dpi_yc_limit { * @yuv422_en_bit: Enable bit of yuv422. * @csc_enable_bit: Enable bit of CSC. * @pixels_per_iter: Quantity of transferred pixels per iteration. + * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS. */ struct mtk_dpi_conf { unsigned int (*cal_factor)(int clock); @@ -152,6 +156,7 @@ struct mtk_dpi_conf { u32 yuv422_en_bit; u32 csc_enable_bit; u32 pixels_per_iter; + bool edge_cfg_in_mmsys; }; static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) @@ -448,8 +453,12 @@ static void mtk_dpi_dual_edge(struct mtk_dpi *dpi) mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE ? EDGE_SEL : 0, EDGE_SEL); + if (dpi->conf->edge_cfg_in_mmsys) + mtk_mmsys_ddp_dpi_fmt_config(dpi->mmsys_dev, MTK_DPI_RGB888_DDR_CON); } else { mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE, 0); + if (dpi->conf->edge_cfg_in_mmsys) + mtk_mmsys_ddp_dpi_fmt_config(dpi->mmsys_dev, MTK_DPI_RGB888_SDR_CON); } } @@ -777,8 +786,10 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) { struct mtk_dpi *dpi = dev_get_drvdata(dev); struct drm_device *drm_dev = data; + struct mtk_drm_private *priv = drm_dev->dev_private; int ret; + dpi->mmsys_dev = priv->mmsys_dev; ret = drm_simple_encoder_init(drm_dev, &dpi->encoder, DRM_MODE_ENCODER_TMDS); if (ret) { @@ -929,6 +940,24 @@ static const struct mtk_dpi_conf mt8183_conf = { .csc_enable_bit = CSC_ENABLE, }; +static const struct mtk_dpi_conf mt8186_conf = { + .cal_factor = mt8183_calculate_factor, + .reg_h_fre_con = 0xe0, + .max_clock_khz = 150000, + .output_fmts = mt8183_output_fmts, + .num_output_fmts = ARRAY_SIZE(mt8183_output_fmts), + .edge_cfg_in_mmsys = true, + .pixels_per_iter = 1, + .is_ck_de_pol = true, + .swap_input_support = true, + .support_direct_pin = true, + .dimension_mask = HPW_MASK, + .hvsize_mask = HSIZE_MASK, + .channel_swap_shift = CH_SWAP, + .yuv422_en_bit = YUV422_EN, + .csc_enable_bit = CSC_ENABLE, +}; + static const struct mtk_dpi_conf mt8188_dpintf_conf = { .cal_factor = mt8195_dpintf_calculate_factor, .max_clock_khz = 600000, @@ -1093,6 +1122,9 @@ static const struct of_device_id mtk_dpi_of_ids[] = { { .compatible = "mediatek,mt8183-dpi", .data = &mt8183_conf, }, + { .compatible = "mediatek,mt8186-dpi", + .data = &mt8186_conf, + }, { .compatible = "mediatek,mt8188-dp-intf", .data = &mt8188_dpintf_conf, }, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 112615817dcb..5071f1263216 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -945,6 +945,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mtk_crtc->planes = devm_kcalloc(dev, num_comp_planes, sizeof(struct drm_plane), GFP_KERNEL); + if (!mtk_crtc->planes) + return -ENOMEM; for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index cd5b18ef7951..a13b36ac03a1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -20,8 +20,8 @@ #include <drm/drm_fbdev_generic.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem.h> -#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_ioctl.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> @@ -520,6 +520,7 @@ static int mtk_drm_bind(struct device *dev) err_deinit: mtk_drm_kms_deinit(drm); err_free: + private->drm = NULL; drm_dev_put(drm); return ret; } @@ -637,6 +638,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DPI }, { .compatible = "mediatek,mt8183-dpi", .data = (void *)MTK_DPI }, + { .compatible = "mediatek,mt8186-dpi", + .data = (void *)MTK_DPI }, { .compatible = "mediatek,mt8188-dp-intf", .data = (void *)MTK_DP_INTF }, { .compatible = "mediatek,mt8192-dpi", diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 47e96b0289f9..ec0518aa9315 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -16,13 +16,18 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); +static const struct vm_operations_struct vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + static const struct drm_gem_object_funcs mtk_drm_gem_object_funcs = { .free = mtk_drm_gem_free_object, .get_sg_table = mtk_gem_prime_get_sg_table, .vmap = mtk_drm_gem_prime_vmap, .vunmap = mtk_drm_gem_prime_vunmap, .mmap = mtk_drm_gem_object_mmap, - .vm_ops = &drm_gem_dma_vm_ops, + .vm_ops = &vm_ops, }; static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, @@ -164,8 +169,6 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie, mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs); - if (ret) - drm_gem_vm_close(vma); return ret; } @@ -262,6 +265,6 @@ void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, return; vunmap(vaddr); - mtk_gem->kvaddr = 0; + mtk_gem->kvaddr = NULL; kfree(mtk_gem->pages); } diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 3b7d13028fb6..7d5250351193 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -28,6 +28,7 @@ #include "mtk_disp_drv.h" #include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" #define DSI_START 0x00 @@ -721,7 +722,7 @@ static void mtk_dsi_lane_ready(struct mtk_dsi *dsi) mtk_dsi_clk_ulp_mode_leave(dsi); mtk_dsi_lane0_ulp_mode_leave(dsi); mtk_dsi_clk_hs_mode(dsi, 0); - msleep(20); + usleep_range(1000, 3000); /* The reaction time after pulling up the mipi signal for dsi_rx */ } } diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c index 6207eac88550..2fc9214ffa82 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c @@ -19,6 +19,9 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> +#include "mtk_drm_drv.h" +#include "mtk_hdmi.h" + #define SIF1_CLOK (288) #define DDC_DDCMCTL0 (0x0) #define DDCM_ODRAIN BIT(31) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 3c9dfdb0b328..871870ddf7ec 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -23,6 +23,7 @@ config DRM_MSM select SHMEM select TMPFS select QCOM_SCM + select DEVFREQ_GOV_SIMPLE_ONDEMAND select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILE @@ -140,12 +141,12 @@ config DRM_MSM_DSI_10NM_PHY Choose this option if DSI PHY on SDM845 is used on the platform. config DRM_MSM_DSI_7NM_PHY - bool "Enable DSI 7nm PHY driver in MSM DRM" + bool "Enable DSI 7nm/5nm/4nm PHY driver in MSM DRM" depends on DRM_MSM_DSI default y help - Choose this option if DSI PHY on SM8150/SM8250/SC7280 is used on - the platform. + Choose this option if DSI PHY on SM8150/SM8250/SM8350/SM8450/SM8550/SC7280 + is used on the platform. config DRM_MSM_HDMI bool "Enable HDMI support in MSM DRM driver" diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index 6c9a747eb4ad..c67089a7ebc1 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -53,6 +53,8 @@ static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) static bool a2xx_me_init(struct msm_gpu *gpu) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu); struct msm_ringbuffer *ring = gpu->rb[0]; OUT_PKT3(ring, CP_ME_INIT, 18); @@ -84,15 +86,20 @@ static bool a2xx_me_init(struct msm_gpu *gpu) /* NQ and External Memory Swap */ OUT_RING(ring, 0x00000000); /* protected mode error checking (0x1f2 is REG_AXXX_CP_INT_CNTL) */ - OUT_RING(ring, 0x200001f2); + if (a2xx_gpu->protection_disabled) + OUT_RING(ring, 0x00000000); + else + OUT_RING(ring, 0x200001f2); /* Disable header dumping and Header dump address */ OUT_RING(ring, 0x00000000); /* Header dump size */ OUT_RING(ring, 0x00000000); - /* enable protected mode */ - OUT_PKT3(ring, CP_SET_PROTECTED_MODE, 1); - OUT_RING(ring, 1); + if (!a2xx_gpu->protection_disabled) { + /* enable protected mode */ + OUT_PKT3(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 1); + } adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); return a2xx_idle(gpu); @@ -101,6 +108,7 @@ static bool a2xx_me_init(struct msm_gpu *gpu) static int a2xx_hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu); dma_addr_t pt_base, tran_error; uint32_t *ptr, len; int i, ret; @@ -221,6 +229,17 @@ static int a2xx_hw_init(struct msm_gpu *gpu) len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4; DBG("loading PM4 ucode version: %x", ptr[1]); + /* + * New firmware files seem to have GPU and firmware version in this + * word (0x20xxxx for A200, 0x220xxx for A220, 0x225xxx for A225). + * Older firmware files, which lack protection support, have 0 instead. + */ + if (ptr[1] == 0) { + dev_warn(gpu->dev->dev, + "Legacy firmware detected, disabling protection support\n"); + a2xx_gpu->protection_disabled = true; + } + gpu_write(gpu, REG_AXXX_CP_DEBUG, AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE); gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0); diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.h b/drivers/gpu/drm/msm/adreno/a2xx_gpu.h index 02fba2cb8932..161a075f94af 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.h @@ -15,6 +15,7 @@ struct a2xx_gpu { struct adreno_gpu base; bool pm_enabled; + bool protection_disabled; }; #define to_a2xx_gpu(x) container_of(x, struct a2xx_gpu, base) diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h index beea4a7fc1df..a92788019376 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h @@ -241,6 +241,9 @@ enum a6xx_shader_id { A6XX_HLSQ_FRONTEND_META = 97, A6XX_HLSQ_INDIRECT_META = 98, A6XX_HLSQ_BACKEND_META = 99, + A6XX_SP_LB_6_DATA = 112, + A6XX_SP_LB_7_DATA = 113, + A6XX_HLSQ_INST_RAM_1 = 115, }; enum a6xx_debugbus_id { @@ -274,19 +277,32 @@ enum a6xx_debugbus_id { A6XX_DBGBUS_HLSQ_SPTP = 31, A6XX_DBGBUS_RB_0 = 32, A6XX_DBGBUS_RB_1 = 33, + A6XX_DBGBUS_RB_2 = 34, A6XX_DBGBUS_UCHE_WRAPPER = 36, A6XX_DBGBUS_CCU_0 = 40, A6XX_DBGBUS_CCU_1 = 41, + A6XX_DBGBUS_CCU_2 = 42, A6XX_DBGBUS_VFD_0 = 56, A6XX_DBGBUS_VFD_1 = 57, A6XX_DBGBUS_VFD_2 = 58, A6XX_DBGBUS_VFD_3 = 59, + A6XX_DBGBUS_VFD_4 = 60, + A6XX_DBGBUS_VFD_5 = 61, A6XX_DBGBUS_SP_0 = 64, A6XX_DBGBUS_SP_1 = 65, + A6XX_DBGBUS_SP_2 = 66, A6XX_DBGBUS_TPL1_0 = 72, A6XX_DBGBUS_TPL1_1 = 73, A6XX_DBGBUS_TPL1_2 = 74, A6XX_DBGBUS_TPL1_3 = 75, + A6XX_DBGBUS_TPL1_4 = 76, + A6XX_DBGBUS_TPL1_5 = 77, + A6XX_DBGBUS_SPTP_0 = 88, + A6XX_DBGBUS_SPTP_1 = 89, + A6XX_DBGBUS_SPTP_2 = 90, + A6XX_DBGBUS_SPTP_3 = 91, + A6XX_DBGBUS_SPTP_4 = 92, + A6XX_DBGBUS_SPTP_5 = 93, }; enum a6xx_cp_perfcounter_select { @@ -1071,6 +1087,8 @@ enum a6xx_tex_type { #define REG_A6XX_CP_MISC_CNTL 0x00000840 +#define REG_A6XX_CP_CHICKEN_DBG 0x00000841 + #define REG_A6XX_CP_APRIV_CNTL 0x00000844 #define REG_A6XX_CP_ROQ_THRESHOLDS_1 0x000008c1 diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 3be0f2928b57..aae60cbd9164 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -2028,7 +2028,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) * to cause power supply issues: */ if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu)) - gpu->clamp_to_idle = true; + priv->gpu_clamp_to_idle = true; /* Check if there is a GMU phandle and set it up */ node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index a023d5f962dc..b7e217d00a22 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -385,6 +385,9 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu, nr_debugbus_blocks = ARRAY_SIZE(a6xx_debugbus_blocks) + (a6xx_has_gbif(to_adreno_gpu(gpu)) ? 1 : 0); + if (adreno_is_a650_family(to_adreno_gpu(gpu))) + nr_debugbus_blocks += ARRAY_SIZE(a650_debugbus_blocks); + a6xx_state->debugbus = state_kcalloc(a6xx_state, nr_debugbus_blocks, sizeof(*a6xx_state->debugbus)); @@ -411,6 +414,15 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu, a6xx_state->nr_debugbus += 1; } + + + if (adreno_is_a650_family(to_adreno_gpu(gpu))) { + for (i = 0; i < ARRAY_SIZE(a650_debugbus_blocks); i++) + a6xx_get_debugbus_block(gpu, + a6xx_state, + &a650_debugbus_blocks[i], + &a6xx_state->debugbus[i]); + } } /* Dump the VBIF debugbus on applicable targets */ @@ -524,10 +536,21 @@ static void a6xx_get_cluster(struct msm_gpu *gpu, struct a6xx_gpu_state_obj *obj, struct a6xx_crashdumper *dumper) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); u64 *in = dumper->ptr; u64 out = dumper->iova + A6XX_CD_DATA_OFFSET; size_t datasize; int i, regcount = 0; + u32 id = cluster->id; + + /* Skip registers that are not present on older generation */ + if (!adreno_is_a660_family(adreno_gpu) && + cluster->registers == a660_fe_cluster) + return; + + if (adreno_is_a650_family(adreno_gpu) && + cluster->registers == a6xx_ps_cluster) + id = CLUSTER_VPC_PS; /* Some clusters need a selector register to be programmed too */ if (cluster->sel_reg) @@ -537,7 +560,7 @@ static void a6xx_get_cluster(struct msm_gpu *gpu, int j; in += CRASHDUMP_WRITE(in, REG_A6XX_CP_APERTURE_CNTL_CD, - (cluster->id << 8) | (i << 4) | i); + (id << 8) | (i << 4) | i); for (j = 0; j < cluster->count; j += 2) { int count = RANGE(cluster->registers, j); @@ -687,6 +710,11 @@ static void a6xx_get_crashdumper_registers(struct msm_gpu *gpu, u64 out = dumper->iova + A6XX_CD_DATA_OFFSET; int i, regcount = 0; + /* Skip unsupported registers on older generations */ + if (!adreno_is_a660_family(to_adreno_gpu(gpu)) && + (regs->registers == a660_registers)) + return; + /* Some blocks might need to program a selector register first */ if (regs->val0) in += CRASHDUMP_WRITE(in, regs->val0, regs->val1); @@ -721,6 +749,11 @@ static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu, { int i, regcount = 0, index = 0; + /* Skip unsupported registers on older generations */ + if (!adreno_is_a660_family(to_adreno_gpu(gpu)) && + (regs->registers == a660_registers)) + return; + for (i = 0; i < regs->count; i += 2) regcount += RANGE(regs->registers, i); @@ -909,15 +942,24 @@ static void a6xx_get_registers(struct msm_gpu *gpu, dumper); } +static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu) +{ + /* The value at [16:31] is in 4dword units. Convert it to dwords */ + return gpu_read(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2) >> 14; +} + /* Read a block of data from an indexed register pair */ static void a6xx_get_indexed_regs(struct msm_gpu *gpu, struct a6xx_gpu_state *a6xx_state, - const struct a6xx_indexed_registers *indexed, + struct a6xx_indexed_registers *indexed, struct a6xx_gpu_state_obj *obj) { int i; obj->handle = (const void *) indexed; + if (indexed->count_fn) + indexed->count = indexed->count_fn(gpu); + obj->data = state_kcalloc(a6xx_state, indexed->count, sizeof(u32)); if (!obj->data) return; @@ -946,6 +988,21 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu, a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_indexed_reglist[i], &a6xx_state->indexed_regs[i]); + if (adreno_is_a650_family(to_adreno_gpu(gpu))) { + u32 val; + + val = gpu_read(gpu, REG_A6XX_CP_CHICKEN_DBG); + gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, val | 4); + + /* Get the contents of the CP mempool */ + a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_cp_mempool_indexed, + &a6xx_state->indexed_regs[i]); + + gpu_write(gpu, REG_A6XX_CP_CHICKEN_DBG, val); + a6xx_state->nr_indexed_regs = count; + return; + } + /* Set the CP mempool size to 0 to stabilize it while dumping */ mempool_size = gpu_read(gpu, REG_A6XX_CP_MEM_POOL_SIZE); gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 0); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h index 2fb58b7098e4..790f55e24533 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h @@ -36,16 +36,21 @@ static const u32 a6xx_fe_cluster[] = { 0xa00e, 0xa0ef, 0xa0f8, 0xa0f8, }; +static const u32 a660_fe_cluster[] = { + 0x9807, 0x9807, +}; + static const u32 a6xx_pc_vs_cluster[] = { 0x9100, 0x9108, 0x9300, 0x9306, 0x9980, 0x9981, 0x9b00, 0x9b07, }; -#define CLUSTER_FE 0 -#define CLUSTER_SP_VS 1 -#define CLUSTER_PC_VS 2 -#define CLUSTER_GRAS 3 -#define CLUSTER_SP_PS 4 -#define CLUSTER_PS 5 +#define CLUSTER_FE 0 +#define CLUSTER_SP_VS 1 +#define CLUSTER_PC_VS 2 +#define CLUSTER_GRAS 3 +#define CLUSTER_SP_PS 4 +#define CLUSTER_PS 5 +#define CLUSTER_VPC_PS 6 #define CLUSTER(_id, _reg, _sel_reg, _sel_val) \ { .id = _id, .name = #_id,\ @@ -67,6 +72,7 @@ static const struct a6xx_cluster { CLUSTER(CLUSTER_PS, a6xx_ps_cluster, 0, 0), CLUSTER(CLUSTER_FE, a6xx_fe_cluster, 0, 0), CLUSTER(CLUSTER_PC_VS, a6xx_pc_vs_cluster, 0, 0), + CLUSTER(CLUSTER_FE, a660_fe_cluster, 0, 0), }; static const u32 a6xx_sp_vs_hlsq_cluster[] = { @@ -105,7 +111,7 @@ static const u32 a6xx_sp_ps_hlsq_2d_cluster[] = { static const u32 a6xx_sp_ps_sp_cluster[] = { 0xa980, 0xa9a8, 0xa9b0, 0xa9bc, 0xa9d0, 0xa9d3, 0xa9e0, 0xa9f3, - 0xaa00, 0xaa00, 0xaa30, 0xaa31, + 0xaa00, 0xaa00, 0xaa30, 0xaa31, 0xaaf2, 0xaaf2, }; static const u32 a6xx_sp_ps_sp_2d_cluster[] = { @@ -229,6 +235,9 @@ static const struct a6xx_shader_block { SHADER(A6XX_HLSQ_DATAPATH_META, 0x40), SHADER(A6XX_HLSQ_FRONTEND_META, 0x40), SHADER(A6XX_HLSQ_INDIRECT_META, 0x40), + SHADER(A6XX_SP_LB_6_DATA, 0x200), + SHADER(A6XX_SP_LB_7_DATA, 0x200), + SHADER(A6XX_HLSQ_INST_RAM_1, 0x200), }; static const u32 a6xx_rb_rac_registers[] = { @@ -251,7 +260,7 @@ static const u32 a6xx_registers[] = { 0x0540, 0x0555, /* CP */ 0x0800, 0x0808, 0x0810, 0x0813, 0x0820, 0x0821, 0x0823, 0x0824, - 0x0826, 0x0827, 0x0830, 0x0833, 0x0840, 0x0843, 0x084f, 0x086f, + 0x0826, 0x0827, 0x0830, 0x0833, 0x0840, 0x0845, 0x084f, 0x086f, 0x0880, 0x088a, 0x08a0, 0x08ab, 0x08c0, 0x08c4, 0x08d0, 0x08dd, 0x08f0, 0x08f3, 0x0900, 0x0903, 0x0908, 0x0911, 0x0928, 0x093e, 0x0942, 0x094d, 0x0980, 0x0984, 0x098d, 0x0996, 0x0998, 0x099e, @@ -274,6 +283,13 @@ static const u32 a6xx_registers[] = { /* VFD */ 0xa600, 0xa601, 0xa603, 0xa603, 0xa60a, 0xa60a, 0xa610, 0xa617, 0xa630, 0xa630, + /* HLSQ */ + 0xd002, 0xd003, +}; + +static const u32 a660_registers[] = { + /* UCHE */ + 0x0e3c, 0x0e3c, }; #define REGS(_array, _sel_reg, _sel_val) \ @@ -282,6 +298,7 @@ static const u32 a6xx_registers[] = { static const struct a6xx_registers a6xx_reglist[] = { REGS(a6xx_registers, 0, 0), + REGS(a660_registers, 0, 0), REGS(a6xx_rb_rac_registers, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 0), REGS(a6xx_rb_rbp_registers, REG_A6XX_RB_RB_SUB_BLOCK_SEL_CNTL_CD, 9), }; @@ -366,25 +383,28 @@ static const struct a6xx_registers a6xx_gmu_reglist[] = { REGS(a6xx_gmu_gx_registers, 0, 0), }; -static const struct a6xx_indexed_registers { +static u32 a6xx_get_cp_roq_size(struct msm_gpu *gpu); + +static struct a6xx_indexed_registers { const char *name; u32 addr; u32 data; u32 count; + u32 (*count_fn)(struct msm_gpu *gpu); } a6xx_indexed_reglist[] = { { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, - REG_A6XX_CP_SQE_STAT_DATA, 0x33 }, + REG_A6XX_CP_SQE_STAT_DATA, 0x33, NULL }, { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, - REG_A6XX_CP_DRAW_STATE_DATA, 0x100 }, + REG_A6XX_CP_DRAW_STATE_DATA, 0x100, NULL }, { "CP_UCODE_DBG_DATA", REG_A6XX_CP_SQE_UCODE_DBG_ADDR, - REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x6000 }, + REG_A6XX_CP_SQE_UCODE_DBG_DATA, 0x8000, NULL }, { "CP_ROQ", REG_A6XX_CP_ROQ_DBG_ADDR, - REG_A6XX_CP_ROQ_DBG_DATA, 0x400 }, + REG_A6XX_CP_ROQ_DBG_DATA, 0, a6xx_get_cp_roq_size}, }; -static const struct a6xx_indexed_registers a6xx_cp_mempool_indexed = { +static struct a6xx_indexed_registers a6xx_cp_mempool_indexed = { "CP_MEMPOOL", REG_A6XX_CP_MEM_POOL_DBG_ADDR, - REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2060, + REG_A6XX_CP_MEM_POOL_DBG_DATA, 0x2060, NULL, }; #define DEBUGBUS(_id, _count) { .id = _id, .name = #_id, .count = _count } @@ -443,4 +463,20 @@ static const struct a6xx_debugbus_block a6xx_cx_debugbus_blocks[] = { DEBUGBUS(A6XX_DBGBUS_CX, 0x100), }; +static const struct a6xx_debugbus_block a650_debugbus_blocks[] = { + DEBUGBUS(A6XX_DBGBUS_RB_2, 0x100), + DEBUGBUS(A6XX_DBGBUS_CCU_2, 0x100), + DEBUGBUS(A6XX_DBGBUS_VFD_4, 0x100), + DEBUGBUS(A6XX_DBGBUS_VFD_5, 0x100), + DEBUGBUS(A6XX_DBGBUS_SP_2, 0x100), + DEBUGBUS(A6XX_DBGBUS_TPL1_4, 0x100), + DEBUGBUS(A6XX_DBGBUS_TPL1_5, 0x100), + DEBUGBUS(A6XX_DBGBUS_SPTP_0, 0x100), + DEBUGBUS(A6XX_DBGBUS_SPTP_1, 0x100), + DEBUGBUS(A6XX_DBGBUS_SPTP_2, 0x100), + DEBUGBUS(A6XX_DBGBUS_SPTP_3, 0x100), + DEBUGBUS(A6XX_DBGBUS_SPTP_4, 0x100), + DEBUGBUS(A6XX_DBGBUS_SPTP_5, 0x100), +}; + #endif diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 3605f095b2de..817599766329 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -1083,13 +1083,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) { struct msm_gpu *gpu = &adreno_gpu->base; - struct msm_drm_private *priv = gpu->dev->dev_private; + struct msm_drm_private *priv = gpu->dev ? gpu->dev->dev_private : NULL; unsigned int i; for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++) release_firmware(adreno_gpu->fw[i]); - if (pm_runtime_enabled(&priv->gpu_pdev->dev)) + if (priv && pm_runtime_enabled(&priv->gpu_pdev->dev)) pm_runtime_disable(&priv->gpu_pdev->dev); msm_gpu_cleanup(&adreno_gpu->base); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 13ce321283ff..f29a339a3705 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -748,7 +748,7 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) int i; - if (!state->color_mgmt_changed) + if (!state->color_mgmt_changed && !drm_atomic_crtc_needs_modeset(state)) return; for (i = 0; i < cstate->num_mixers; i++) { @@ -968,7 +968,10 @@ static void dpu_crtc_reset(struct drm_crtc *crtc) if (crtc->state) dpu_crtc_destroy_state(crtc, crtc->state); - __drm_atomic_helper_crtc_reset(crtc, &cstate->base); + if (cstate) + __drm_atomic_helper_crtc_reset(crtc, &cstate->base); + else + __drm_atomic_helper_crtc_reset(crtc, NULL); } /** @@ -1150,6 +1153,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state); pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL); + if (!pstates) + return -ENOMEM; if (!crtc_state->enable || !crtc_state->active) { DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n", @@ -1517,16 +1522,12 @@ DEFINE_SHOW_ATTRIBUTE(dpu_crtc_debugfs_state); static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc) { struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); - struct dentry *debugfs_root; - - debugfs_root = debugfs_create_dir(dpu_crtc->name, - crtc->dev->primary->debugfs_root); debugfs_create_file("status", 0400, - debugfs_root, + crtc->debugfs_entry, dpu_crtc, &_dpu_debugfs_status_fops); debugfs_create_file("state", 0600, - debugfs_root, + crtc->debugfs_entry, &dpu_crtc->base, &dpu_crtc_debugfs_state_fops); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 9c6817b5a194..758261e8ac73 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -162,6 +162,7 @@ enum dpu_enc_rc_states { * @vsync_event_work: worker to handle vsync event for autorefresh * @topology: topology of the display * @idle_timeout: idle timeout duration in milliseconds + * @wide_bus_en: wide bus is enabled on this interface * @dsc: drm_dsc_config pointer, for DSC-enabled encoders */ struct dpu_encoder_virt { @@ -340,9 +341,7 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc, phys_enc->intf_idx - INTF_0, phys_enc->wb_idx - WB_0, phys_enc->hw_pp->idx - PINGPONG_0, intr_idx); - if (phys_enc->parent_ops->handle_frame_done) - phys_enc->parent_ops->handle_frame_done( - phys_enc->parent, phys_enc, + dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, DPU_ENCODER_FRAME_EVENT_ERROR); } @@ -579,19 +578,18 @@ static struct msm_display_topology dpu_encoder_get_topology( topology.num_dspp = topology.num_lm; } - topology.num_enc = 0; topology.num_intf = intf_count; if (dpu_enc->dsc) { - /* In case of Display Stream Compression (DSC), we would use - * 2 encoders, 2 layer mixers and 1 interface + /* + * In case of Display Stream Compression (DSC), we would use + * 2 DSC encoders, 2 layer mixers and 1 interface * this is power optimal and can drive up to (including) 4k * screens */ - topology.num_enc = 2; topology.num_dsc = 2; - topology.num_intf = 1; topology.num_lm = 2; + topology.num_intf = 1; } return topology; @@ -1284,7 +1282,7 @@ static enum dpu_wb dpu_encoder_get_wb(const struct dpu_mdss_cfg *catalog, return WB_MAX; } -static void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc, +void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc, struct dpu_encoder_phys *phy_enc) { struct dpu_encoder_virt *dpu_enc = NULL; @@ -1306,7 +1304,7 @@ static void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc, DPU_ATRACE_END("encoder_vblank_callback"); } -static void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc, +void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc, struct dpu_encoder_phys *phy_enc) { if (!phy_enc) @@ -1382,7 +1380,7 @@ void dpu_encoder_register_frame_event_callback(struct drm_encoder *drm_enc, spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags); } -static void dpu_encoder_frame_done_callback( +void dpu_encoder_frame_done_callback( struct drm_encoder *drm_enc, struct dpu_encoder_phys *ready_phys, u32 event) { @@ -1830,6 +1828,9 @@ static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc, if (hw_pp->ops.setup_dsc) hw_pp->ops.setup_dsc(hw_pp); + if (hw_dsc->ops.dsc_bind_pingpong_blk) + hw_dsc->ops.dsc_bind_pingpong_blk(hw_dsc, true, hw_pp->idx); + if (hw_pp->ops.enable_dsc) hw_pp->ops.enable_dsc(hw_pp); } @@ -2233,12 +2234,6 @@ static int dpu_encoder_virt_add_phys_encs( return 0; } -static const struct dpu_encoder_virt_ops dpu_encoder_parent_ops = { - .handle_vblank_virt = dpu_encoder_vblank_callback, - .handle_underrun_virt = dpu_encoder_underrun_callback, - .handle_frame_done = dpu_encoder_frame_done_callback, -}; - static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, struct dpu_kms *dpu_kms, struct msm_display_info *disp_info) @@ -2258,7 +2253,6 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, memset(&phys_params, 0, sizeof(phys_params)); phys_params.dpu_kms = dpu_kms; phys_params.parent = &dpu_enc->base; - phys_params.parent_ops = &dpu_encoder_parent_ops; phys_params.enc_spinlock = &dpu_enc->enc_spinlock; switch (disp_info->intf_type) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index f2af07d87f56..1d434b22180d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -61,25 +61,6 @@ enum dpu_enc_enable_state { struct dpu_encoder_phys; /** - * struct dpu_encoder_virt_ops - Interface the containing virtual encoder - * provides for the physical encoders to use to callback. - * @handle_vblank_virt: Notify virtual encoder of vblank IRQ reception - * Note: This is called from IRQ handler context. - * @handle_underrun_virt: Notify virtual encoder of underrun IRQ reception - * Note: This is called from IRQ handler context. - * @handle_frame_done: Notify virtual encoder that this phys encoder - * completes last request frame. - */ -struct dpu_encoder_virt_ops { - void (*handle_vblank_virt)(struct drm_encoder *, - struct dpu_encoder_phys *phys); - void (*handle_underrun_virt)(struct drm_encoder *, - struct dpu_encoder_phys *phys); - void (*handle_frame_done)(struct drm_encoder *, - struct dpu_encoder_phys *phys, u32 event); -}; - -/** * struct dpu_encoder_phys_ops - Interface the physical encoders provide to * the containing virtual encoder. * @late_register: DRM Call. Add Userspace interfaces, debugfs. @@ -199,7 +180,6 @@ enum dpu_intr_idx { struct dpu_encoder_phys { struct drm_encoder *parent; struct dpu_encoder_phys_ops ops; - const struct dpu_encoder_virt_ops *parent_ops; struct dpu_hw_mdp *hw_mdptop; struct dpu_hw_ctl *hw_ctl; struct dpu_hw_pingpong *hw_pp; @@ -283,7 +263,6 @@ struct dpu_encoder_phys_cmd { struct dpu_enc_phys_init_params { struct dpu_kms *dpu_kms; struct drm_encoder *parent; - const struct dpu_encoder_virt_ops *parent_ops; enum dpu_enc_split_role split_role; enum dpu_intf intf_idx; enum dpu_wb wb_idx; @@ -400,4 +379,30 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc, */ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc); +/** + * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception + * @drm_enc: Pointer to drm encoder structure + * @phys_enc: Pointer to physical encoder + * Note: This is called from IRQ handler context. + */ +void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc, + struct dpu_encoder_phys *phy_enc); + +/** dpu_encoder_underrun_callback - Notify virtual encoder of underrun IRQ reception + * @drm_enc: Pointer to drm encoder structure + * @phys_enc: Pointer to physical encoder + * Note: This is called from IRQ handler context. + */ +void dpu_encoder_underrun_callback(struct drm_encoder *drm_enc, + struct dpu_encoder_phys *phy_enc); + +/** dpu_encoder_frame_done_callback -- Notify virtual encoder that this phys encoder completes last request frame + * @drm_enc: Pointer to drm encoder structure + * @phys_enc: Pointer to physical encoder + * @event: Event to process + */ +void dpu_encoder_frame_done_callback( + struct drm_encoder *drm_enc, + struct dpu_encoder_phys *ready_phys, u32 event); + #endif /* __dpu_encoder_phys_H__ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index ae28b2b93e69..c8f4a62a9536 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -61,6 +61,7 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; intf_cfg.stream_sel = cmd_enc->stream_sel; intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); + intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc); ctl->ops.setup_intf_cfg(ctl, &intf_cfg); /* setup which pp blk will connect to this intf */ @@ -83,9 +84,7 @@ static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) DPU_ATRACE_BEGIN("pp_done_irq"); /* notify all synchronous clients first, then asynchronous clients */ - if (phys_enc->parent_ops->handle_frame_done) - phys_enc->parent_ops->handle_frame_done(phys_enc->parent, - phys_enc, event); + dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, event); spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); @@ -111,9 +110,7 @@ static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx) DPU_ATRACE_BEGIN("rd_ptr_irq"); cmd_enc = to_dpu_encoder_phys_cmd(phys_enc); - if (phys_enc->parent_ops->handle_vblank_virt) - phys_enc->parent_ops->handle_vblank_virt(phys_enc->parent, - phys_enc); + dpu_encoder_vblank_callback(phys_enc->parent, phys_enc); atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0); wake_up_all(&cmd_enc->pending_vblank_wq); @@ -137,9 +134,7 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx) { struct dpu_encoder_phys *phys_enc = arg; - if (phys_enc->parent_ops->handle_underrun_virt) - phys_enc->parent_ops->handle_underrun_virt(phys_enc->parent, - phys_enc); + dpu_encoder_underrun_callback(phys_enc->parent, phys_enc); } static void dpu_encoder_phys_cmd_atomic_mode_set( @@ -202,9 +197,7 @@ static int _dpu_encoder_phys_cmd_handle_ppdone_timeout( /* request a ctl reset before the next kickoff */ phys_enc->enable_state = DPU_ENC_ERR_NEEDS_HW_RESET; - if (phys_enc->parent_ops->handle_frame_done) - phys_enc->parent_ops->handle_frame_done( - drm_enc, phys_enc, frame_event); + dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, frame_event); return -ETIMEDOUT; } @@ -780,7 +773,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init( dpu_encoder_phys_cmd_init_ops(&phys_enc->ops); phys_enc->parent = p->parent; - phys_enc->parent_ops = p->parent_ops; phys_enc->dpu_kms = p->dpu_kms; phys_enc->split_role = p->split_role; phys_enc->intf_mode = INTF_MODE_CMD; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 0f71e8fe7be7..48c48106b16a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -274,6 +274,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine( intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID; intf_cfg.stream_sel = 0; /* Don't care value for video mode */ intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); + intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc); if (phys_enc->hw_pp->merge_3d) intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; @@ -308,9 +309,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) DPU_ATRACE_BEGIN("vblank_irq"); - if (phys_enc->parent_ops->handle_vblank_virt) - phys_enc->parent_ops->handle_vblank_virt(phys_enc->parent, - phys_enc); + dpu_encoder_vblank_callback(phys_enc->parent, phys_enc); atomic_read(&phys_enc->pending_kickoff_cnt); @@ -330,7 +329,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) /* Signal any waiting atomic commit thread */ wake_up_all(&phys_enc->pending_kickoff_wq); - phys_enc->parent_ops->handle_frame_done(phys_enc->parent, phys_enc, + dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, DPU_ENCODER_FRAME_EVENT_DONE); DPU_ATRACE_END("vblank_irq"); @@ -340,9 +339,7 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg, int irq_idx) { struct dpu_encoder_phys *phys_enc = arg; - if (phys_enc->parent_ops->handle_underrun_virt) - phys_enc->parent_ops->handle_underrun_virt(phys_enc->parent, - phys_enc); + dpu_encoder_underrun_callback(phys_enc->parent, phys_enc); } static bool dpu_encoder_phys_vid_needs_single_flush( @@ -700,7 +697,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init( dpu_encoder_phys_vid_init_ops(&phys_enc->ops); phys_enc->parent = p->parent; - phys_enc->parent_ops = p->parent_ops; phys_enc->dpu_kms = p->dpu_kms; phys_enc->split_role = p->split_role; phys_enc->intf_mode = INTF_MODE_VIDEO; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c index 62f6ff6abf41..bac4aa807b4b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c @@ -26,6 +26,7 @@ /** * dpu_encoder_phys_wb_is_master - report wb always as master encoder + * @phys_enc: Pointer to physical encoder */ static bool dpu_encoder_phys_wb_is_master(struct dpu_encoder_phys *phys_enc) { @@ -364,13 +365,9 @@ static void _dpu_encoder_phys_wb_frame_done_helper(void *arg) DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0); - if (phys_enc->parent_ops->handle_frame_done) - phys_enc->parent_ops->handle_frame_done(phys_enc->parent, - phys_enc, event); + dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, event); - if (phys_enc->parent_ops->handle_vblank_virt) - phys_enc->parent_ops->handle_vblank_virt(phys_enc->parent, - phys_enc); + dpu_encoder_vblank_callback(phys_enc->parent, phys_enc); spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags); atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); @@ -440,9 +437,7 @@ static void _dpu_encoder_phys_wb_handle_wbdone_timeout( if (wb_enc->wb_conn) drm_writeback_signal_completion(wb_enc->wb_conn, 0); - if (phys_enc->parent_ops->handle_frame_done) - phys_enc->parent_ops->handle_frame_done( - phys_enc->parent, phys_enc, frame_event); + dpu_encoder_frame_done_callback(phys_enc->parent, phys_enc, frame_event); } /** @@ -722,7 +717,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init( dpu_encoder_phys_wb_init_ops(&phys_enc->ops); phys_enc->parent = p->parent; - phys_enc->parent_ops = p->parent_ops; phys_enc->dpu_kms = p->dpu_kms; phys_enc->split_role = p->split_role; phys_enc->intf_mode = INTF_MODE_WB_LINE; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 2196e205efa5..cf053e8f081e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -56,7 +56,7 @@ #define MIXER_SDM845_MASK \ (BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) -#define MIXER_SC7180_MASK \ +#define MIXER_QCM2290_MASK \ (BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) #define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER) @@ -67,6 +67,9 @@ #define CTL_SC7280_MASK \ (BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_FETCH_ACTIVE) | BIT(DPU_CTL_VM_CFG)) +#define CTL_SM8550_MASK \ + (CTL_SC7280_MASK | BIT(DPU_CTL_HAS_LAYER_EXT4)) + #define MERGE_3D_SM8150_MASK (0) #define DSPP_MSM8998_MASK BIT(DPU_DSPP_PCC) | BIT(DPU_DSPP_GC) @@ -86,7 +89,6 @@ BIT(MDP_INTF1_INTR) | \ BIT(MDP_INTF2_INTR) | \ BIT(MDP_INTF3_INTR) | \ - BIT(MDP_INTF4_INTR) | \ BIT(MDP_AD4_0_INTR) | \ BIT(MDP_AD4_1_INTR)) @@ -112,6 +114,14 @@ BIT(MDP_INTF3_INTR) | \ BIT(MDP_INTF4_INTR)) +#define IRQ_SM8350_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ + BIT(MDP_SSPP_TOP0_INTR2) | \ + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ + BIT(MDP_INTF0_7xxx_INTR) | \ + BIT(MDP_INTF1_7xxx_INTR) | \ + BIT(MDP_INTF2_7xxx_INTR) | \ + BIT(MDP_INTF3_7xxx_INTR)) + #define IRQ_SC8180X_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ BIT(MDP_SSPP_TOP0_INTR2) | \ BIT(MDP_SSPP_TOP0_HIST_INTR) | \ @@ -124,6 +134,27 @@ BIT(MDP_AD4_0_INTR) | \ BIT(MDP_AD4_1_INTR)) +#define IRQ_SC8280XP_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ + BIT(MDP_SSPP_TOP0_INTR2) | \ + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ + BIT(MDP_INTF0_7xxx_INTR) | \ + BIT(MDP_INTF1_7xxx_INTR) | \ + BIT(MDP_INTF2_7xxx_INTR) | \ + BIT(MDP_INTF3_7xxx_INTR) | \ + BIT(MDP_INTF4_7xxx_INTR) | \ + BIT(MDP_INTF5_7xxx_INTR) | \ + BIT(MDP_INTF6_7xxx_INTR) | \ + BIT(MDP_INTF7_7xxx_INTR) | \ + BIT(MDP_INTF8_7xxx_INTR)) + +#define IRQ_SM8450_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ + BIT(MDP_SSPP_TOP0_INTR2) | \ + BIT(MDP_SSPP_TOP0_HIST_INTR) | \ + BIT(MDP_INTF0_7xxx_INTR) | \ + BIT(MDP_INTF1_7xxx_INTR) | \ + BIT(MDP_INTF2_7xxx_INTR) | \ + BIT(MDP_INTF3_7xxx_INTR)) + #define WB_SM8250_MASK (BIT(DPU_WB_LINE_MODE) | \ BIT(DPU_WB_UBWC) | \ BIT(DPU_WB_YUV_CONFIG) | \ @@ -326,7 +357,7 @@ static const struct dpu_caps sm6115_dpu_caps = { .max_mixer_blendstages = 0x4, .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ - .ubwc_version = DPU_HW_UBWC_VER_20, + .ubwc_version = DPU_HW_UBWC_VER_10, .has_dim_layer = true, .has_idle_pc = true, .max_linewidth = 2160, @@ -365,6 +396,20 @@ static const struct dpu_caps sc8180x_dpu_caps = { .max_vdeci_exp = MAX_VERT_DECIMATION, }; +static const struct dpu_caps sc8280xp_dpu_caps = { + .max_mixer_width = 2560, + .max_mixer_blendstages = 11, + .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .ubwc_version = DPU_HW_UBWC_VER_40, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 5120, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + static const struct dpu_caps sm8250_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0xb, @@ -379,6 +424,48 @@ static const struct dpu_caps sm8250_dpu_caps = { .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, }; +static const struct dpu_caps sm8350_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .ubwc_version = DPU_HW_UBWC_VER_40, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 4096, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_caps sm8450_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .qseed_type = DPU_SSPP_SCALER_QSEED4, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .ubwc_version = DPU_HW_UBWC_VER_40, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 5120, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + +static const struct dpu_caps sm8550_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0xb, + .qseed_type = DPU_SSPP_SCALER_QSEED3LITE, + .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */ + .ubwc_version = DPU_HW_UBWC_VER_40, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = 5120, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, +}; + static const struct dpu_caps sc7280_dpu_caps = { .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, .max_mixer_blendstages = 0x7, @@ -459,6 +546,8 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = { .reg_off = 0x2B4, .bit_off = 8}, .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x2C4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_WB2] = { + .reg_off = 0x3B8, .bit_off = 24}, }, }; @@ -466,7 +555,7 @@ static const struct dpu_mdp_cfg sc8180x_mdp[] = { { .name = "top_0", .id = MDP_TOP, .base = 0x0, .len = 0x45C, - .features = 0, + .features = BIT(DPU_MDP_AUDIO_SELECT), .highest_bank_bit = 0x3, .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2AC, .bit_off = 0}, @@ -493,6 +582,7 @@ static const struct dpu_mdp_cfg sm6115_mdp[] = { .base = 0x0, .len = 0x494, .features = 0, .highest_bank_bit = 0x1, + .ubwc_swizzle = 0x7, .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_DMA0] = { @@ -506,6 +596,7 @@ static const struct dpu_mdp_cfg sm8250_mdp[] = { .base = 0x0, .len = 0x494, .features = 0, .highest_bank_bit = 0x3, /* TODO: 2 for LP_DDR4 */ + .ubwc_swizzle = 0x6, .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2AC, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_VIG1] = { @@ -529,11 +620,67 @@ static const struct dpu_mdp_cfg sm8250_mdp[] = { }, }; +static const struct dpu_mdp_cfg sm8350_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x494, + .features = 0, + .highest_bank_bit = 0x3, /* TODO: 2 for LP_DDR4 */ + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2ac, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x2b4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x2bc, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0x2c4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2ac, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x2b4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x2bc, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x2c4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { + .reg_off = 0x2bc, .bit_off = 20}, + }, +}; + +static const struct dpu_mdp_cfg sm8450_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x494, + .features = BIT(DPU_MDP_PERIPH_0_REMOVED), + .highest_bank_bit = 0x3, /* TODO: 2 for LP_DDR4 */ + .ubwc_swizzle = 0x6, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x2AC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x2B4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x2BC, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0x2C4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x2AC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x2B4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x2BC, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x2C4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { + .reg_off = 0x2BC, .bit_off = 20}, + }, +}; + static const struct dpu_mdp_cfg sc7280_mdp[] = { { .name = "top_0", .id = MDP_TOP, .base = 0x0, .len = 0x2014, .highest_bank_bit = 0x1, + .ubwc_swizzle = 0x6, .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2AC, .bit_off = 0}, .clk_ctrls[DPU_CLK_CTRL_DMA0] = { @@ -545,6 +692,57 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = { }, }; +static const struct dpu_mdp_cfg sc8280xp_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0x0, .len = 0x494, + .features = 0, + .highest_bank_bit = 2, + .ubwc_swizzle = 6, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x2bc, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x2c4, .bit_off = 8}, + .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20}, + }, +}; + +static const struct dpu_mdp_cfg sm8550_mdp[] = { + { + .name = "top_0", .id = MDP_TOP, + .base = 0, .len = 0x494, + .features = BIT(DPU_MDP_PERIPH_0_REMOVED), + .highest_bank_bit = 0x3, /* TODO: 2 for LP_DDR4 */ + .ubwc_swizzle = 0x6, + .clk_ctrls[DPU_CLK_CTRL_VIG0] = { + .reg_off = 0x4330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG1] = { + .reg_off = 0x6330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG2] = { + .reg_off = 0x8330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_VIG3] = { + .reg_off = 0xa330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA0] = { + .reg_off = 0x24330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA1] = { + .reg_off = 0x26330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA2] = { + .reg_off = 0x28330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_DMA3] = { + .reg_off = 0x2a330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { + .reg_off = 0x2c330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { + .reg_off = 0x2e330, .bit_off = 0}, + .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { + .reg_off = 0x2bc, .bit_off = 20}, + }, +}; + static const struct dpu_mdp_cfg qcm2290_mdp[] = { { .name = "top_0", .id = MDP_TOP, @@ -648,6 +846,45 @@ static const struct dpu_ctl_cfg sc7180_ctl[] = { }, }; +static const struct dpu_ctl_cfg sc8280xp_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, + { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, + { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, + { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, + { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, + { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + static const struct dpu_ctl_cfg sm8150_ctl[] = { { .name = "ctl_0", .id = CTL_0, @@ -687,6 +924,123 @@ static const struct dpu_ctl_cfg sm8150_ctl[] = { }, }; +static const struct dpu_ctl_cfg sm8350_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x1e8, + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, + { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x1e8, + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, + { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x1e8, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, + { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x1e8, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, + { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x1e8, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, + { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x1e8, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_ctl_cfg sm8450_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x204, + .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY) | BIT(DPU_CTL_FETCH_ACTIVE), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, + { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x204, + .features = BIT(DPU_CTL_SPLIT_DISPLAY) | CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, + { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, + { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, + { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, + { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x204, + .features = CTL_SC7280_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + +static const struct dpu_ctl_cfg sm8550_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x15000, .len = 0x290, + .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, + { + .name = "ctl_1", .id = CTL_1, + .base = 0x16000, .len = 0x290, + .features = CTL_SM8550_MASK | BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, + { + .name = "ctl_2", .id = CTL_2, + .base = 0x17000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, + { + .name = "ctl_3", .id = CTL_3, + .base = 0x18000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, + { + .name = "ctl_4", .id = CTL_4, + .base = 0x19000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, + { + .name = "ctl_5", .id = CTL_5, + .base = 0x1a000, .len = 0x290, + .features = CTL_SM8550_MASK, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23), + }, +}; + static const struct dpu_ctl_cfg sc7280_ctl[] = { { .name = "ctl_0", .id = CTL_0, @@ -915,6 +1269,68 @@ static const struct dpu_sspp_cfg sm8250_sspp[] = { sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), }; +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_0 = + _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_1 = + _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_2 = + _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8450_vig_sblk_3 = + _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); + +static const struct dpu_sspp_cfg sm8450_sspp[] = { + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, + sm8450_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), + SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK, + sm8450_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), + SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK, + sm8450_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), + SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK, + sm8450_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, + sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), + SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), + SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +}; + +static const struct dpu_sspp_sub_blks sm8550_vig_sblk_0 = + _VIG_SBLK("0", 7, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8550_vig_sblk_1 = + _VIG_SBLK("1", 8, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 = + _VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 = + _VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK("12", 5); +static const struct dpu_sspp_sub_blks sd8550_dma_sblk_5 = _DMA_SBLK("13", 6); + +static const struct dpu_sspp_cfg sm8550_sspp[] = { + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, + sm8550_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), + SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK, + sm8550_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), + SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK, + sm8550_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), + SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK, + sm8550_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, + sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), + SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), + SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_SDM845_MASK, + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2), + SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_SDM845_MASK, + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3), + SSPP_BLK("sspp_12", SSPP_DMA4, 0x2c000, DMA_CURSOR_SDM845_MASK, + sm8550_dma_sblk_4, 14, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + SSPP_BLK("sspp_13", SSPP_DMA5, 0x2e000, DMA_CURSOR_SDM845_MASK, + sd8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +}; + static const struct dpu_sspp_cfg sc7280_sspp[] = { SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7280_MASK, sc7280_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), @@ -926,6 +1342,33 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = { sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), }; +static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_0 = + _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_1 = + _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_2 = + _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); +static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_3 = + _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); + +static const struct dpu_sspp_cfg sc8280xp_sspp[] = { + SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, + sc8280xp_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), + SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SM8250_MASK, + sc8280xp_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), + SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SM8250_MASK, + sc8280xp_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), + SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SM8250_MASK, + sc8280xp_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3), + SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK, + sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0), + SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK, + sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1), + SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, + sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), + SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, + sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +}; #define _VIG_SBLK_NOSCALE(num, sdma_pri) \ { \ @@ -1028,12 +1471,23 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = { }; static const struct dpu_lm_cfg sc7180_lm[] = { - LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK, + LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0), - LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK, + LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, &sc7180_lm_sblk, PINGPONG_1, LM_0, 0), }; +/* SC8280XP */ + +static const struct dpu_lm_cfg sc8280xp_lm[] = { + LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_0, LM_1, DSPP_0), + LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_1, LM_0, DSPP_1), + LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_2, LM_3, DSPP_2), + LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_3, LM_2, DSPP_3), + LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_4, LM_5, 0), + LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK, &sdm845_lm_sblk, PINGPONG_5, LM_4, 0), +}; + /* SM8150 */ static const struct dpu_lm_cfg sm8150_lm[] = { @@ -1052,11 +1506,11 @@ static const struct dpu_lm_cfg sm8150_lm[] = { }; static const struct dpu_lm_cfg sc7280_lm[] = { - LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK, + LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, &sc7180_lm_sblk, PINGPONG_0, 0, DSPP_0), - LM_BLK("lm_2", LM_2, 0x46000, MIXER_SC7180_MASK, + LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, &sc7180_lm_sblk, PINGPONG_2, LM_3, 0), - LM_BLK("lm_3", LM_3, 0x47000, MIXER_SC7180_MASK, + LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK, &sc7180_lm_sblk, PINGPONG_3, LM_2, 0), }; @@ -1071,7 +1525,7 @@ static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { }; static const struct dpu_lm_cfg qcm2290_lm[] = { - LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK, + LM_BLK("lm_0", LM_0, 0x44000, MIXER_QCM2290_MASK, &qcm2290_lm_sblk, PINGPONG_0, 0, DSPP_0), }; @@ -1151,6 +1605,16 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = { .len = 0x20, .version = 0x20000}, }; +#define PP_BLK_DIPHER(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \ + {\ + .name = _name, .id = _id, \ + .base = _base, .len = 0, \ + .features = BIT(DPU_PINGPONG_DITHER), \ + .merge_3d = _merge_3d, \ + .sblk = &_sblk, \ + .intr_done = _done, \ + .intr_rdptr = _rdptr, \ + } #define PP_BLK_TE(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \ {\ .name = _name, .id = _id, \ @@ -1192,6 +1656,21 @@ static struct dpu_pingpong_cfg sc7180_pp[] = { PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te, -1, -1), }; +static struct dpu_pingpong_cfg sc8280xp_pp[] = { + PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), -1), + PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), -1), + PP_BLK_TE("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), -1), + PP_BLK_TE("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), -1), + PP_BLK_TE("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), + PP_BLK_TE("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), +}; + static const struct dpu_pingpong_cfg sm8150_pp[] = { PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), @@ -1213,6 +1692,27 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = { -1), }; +static const struct dpu_pingpong_cfg sm8350_pp[] = { + PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), + PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), + PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), + PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), + PP_BLK("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + -1), + PP_BLK("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + -1), +}; + static const struct dpu_pingpong_cfg sc7280_pp[] = { PP_BLK("pingpong_0", PINGPONG_0, 0x59000, 0, sc7280_pp_sblk, -1, -1), PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1), @@ -1226,6 +1726,61 @@ static struct dpu_pingpong_cfg qcm2290_pp[] = { DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), }; +/* FIXME: interrupts */ +static const struct dpu_pingpong_cfg sm8450_pp[] = { + PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), + PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), + PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), + PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), + PP_BLK("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + -1), + PP_BLK("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + -1), + PP_BLK("pingpong_6", PINGPONG_6, 0x65800, MERGE_3D_3, sdm845_pp_sblk, + -1, + -1), + PP_BLK("pingpong_7", PINGPONG_7, 0x65c00, MERGE_3D_3, sdm845_pp_sblk, + -1, + -1), +}; + +static const struct dpu_pingpong_cfg sm8550_pp[] = { + PP_BLK_DIPHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), + -1), + PP_BLK_DIPHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), + -1), + PP_BLK_DIPHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), + -1), + PP_BLK_DIPHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), + -1), + PP_BLK_DIPHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), + -1), + PP_BLK_DIPHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), + -1), + PP_BLK_DIPHER("pingpong_6", PINGPONG_6, 0x66000, MERGE_3D_3, sc7280_pp_sblk, + -1, + -1), + PP_BLK_DIPHER("pingpong_7", PINGPONG_7, 0x66400, MERGE_3D_3, sc7280_pp_sblk, + -1, + -1), +}; + /************************************************************* * MERGE_3D sub blocks config *************************************************************/ @@ -1243,21 +1798,48 @@ static const struct dpu_merge_3d_cfg sm8150_merge_3d[] = { MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x83200), }; +static const struct dpu_merge_3d_cfg sm8350_merge_3d[] = { + MERGE_3D_BLK("merge_3d_0", MERGE_3D_0, 0x4e000), + MERGE_3D_BLK("merge_3d_1", MERGE_3D_1, 0x4f000), + MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000), +}; + +static const struct dpu_merge_3d_cfg sm8450_merge_3d[] = { + MERGE_3D_BLK("merge_3d_0", MERGE_3D_0, 0x4e000), + MERGE_3D_BLK("merge_3d_1", MERGE_3D_1, 0x4f000), + MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000), + MERGE_3D_BLK("merge_3d_3", MERGE_3D_3, 0x65f00), +}; + +static const struct dpu_merge_3d_cfg sm8550_merge_3d[] = { + MERGE_3D_BLK("merge_3d_0", MERGE_3D_0, 0x4e000), + MERGE_3D_BLK("merge_3d_1", MERGE_3D_1, 0x4f000), + MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x50000), + MERGE_3D_BLK("merge_3d_3", MERGE_3D_3, 0x66700), +}; + /************************************************************* * DSC sub blocks config *************************************************************/ -#define DSC_BLK(_name, _id, _base) \ +#define DSC_BLK(_name, _id, _base, _features) \ {\ .name = _name, .id = _id, \ .base = _base, .len = 0x140, \ - .features = 0, \ + .features = _features, \ } static struct dpu_dsc_cfg sdm845_dsc[] = { - DSC_BLK("dsc_0", DSC_0, 0x80000), - DSC_BLK("dsc_1", DSC_1, 0x80400), - DSC_BLK("dsc_2", DSC_2, 0x80800), - DSC_BLK("dsc_3", DSC_3, 0x80c00), + DSC_BLK("dsc_0", DSC_0, 0x80000, 0), + DSC_BLK("dsc_1", DSC_1, 0x80400, 0), + DSC_BLK("dsc_2", DSC_2, 0x80800, 0), + DSC_BLK("dsc_3", DSC_3, 0x80c00, 0), +}; + +static struct dpu_dsc_cfg sm8150_dsc[] = { + DSC_BLK("dsc_0", DSC_0, 0x80000, BIT(DPU_DSC_OUTPUT_CTRL)), + DSC_BLK("dsc_1", DSC_1, 0x80400, BIT(DPU_DSC_OUTPUT_CTRL)), + DSC_BLK("dsc_2", DSC_2, 0x80800, BIT(DPU_DSC_OUTPUT_CTRL)), + DSC_BLK("dsc_3", DSC_3, 0x80c00, BIT(DPU_DSC_OUTPUT_CTRL)), }; /************************************************************* @@ -1307,6 +1889,13 @@ static const struct dpu_intf_cfg sc7280_intf[] = { INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; +static const struct dpu_intf_cfg sm8350_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_1", INTF_1, 0x35000, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x36000, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + INTF_BLK("intf_3", INTF_3, 0x37000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), +}; + static const struct dpu_intf_cfg sc8180x_intf[] = { INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), @@ -1317,11 +1906,39 @@ static const struct dpu_intf_cfg sc8180x_intf[] = { INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; +/* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */ +static const struct dpu_intf_cfg sc8280xp_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_1", INTF_1, 0x35000, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x36000, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + INTF_BLK("intf_3", INTF_3, 0x37000, INTF_NONE, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), + INTF_BLK("intf_4", INTF_4, 0x38000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 20, 21), + INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_3, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), + INTF_BLK("intf_6", INTF_6, 0x3a000, INTF_DP, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 16, 17), + INTF_BLK("intf_7", INTF_7, 0x3b000, INTF_NONE, MSM_DP_CONTROLLER_2, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 18, 19), + INTF_BLK("intf_8", INTF_8, 0x3c000, INTF_NONE, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 12, 13), +}; + static const struct dpu_intf_cfg qcm2290_intf[] = { INTF_BLK("intf_0", INTF_0, 0x00000, INTF_NONE, 0, 0, 0, 0, 0, 0), INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 26, 27), }; +static const struct dpu_intf_cfg sm8450_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_1", INTF_1, 0x35000, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x36000, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + INTF_BLK("intf_3", INTF_3, 0x37000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), +}; + +static const struct dpu_intf_cfg sm8550_intf[] = { + INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + /* TODO TE sub-blocks for intf1 & intf2 */ + INTF_BLK("intf_1", INTF_1, 0x35000, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x36000, INTF_DSI, 1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + INTF_BLK("intf_3", INTF_3, 0x37000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 30, 31), +}; + /************************************************************* * Writeback blocks config *************************************************************/ @@ -1419,6 +2036,14 @@ static const struct dpu_vbif_cfg sdm845_vbif[] = { }, }; +static const struct dpu_reg_dma_cfg sc8280xp_regdma = { + .base = 0x0, + .version = 0x00020000, + .trigger_sel_off = 0x119c, + .xin_id = 7, + .clk_ctrl = DPU_CLK_CTRL_REG_DMA, +}; + static const struct dpu_reg_dma_cfg sdm845_regdma = { .base = 0x0, .version = 0x1, .trigger_sel_off = 0x119c }; @@ -1435,6 +2060,22 @@ static const struct dpu_reg_dma_cfg sm8250_regdma = { .clk_ctrl = DPU_CLK_CTRL_REG_DMA, }; +static const struct dpu_reg_dma_cfg sm8350_regdma = { + .base = 0x400, + .version = 0x00020000, + .trigger_sel_off = 0x119c, + .xin_id = 7, + .clk_ctrl = DPU_CLK_CTRL_REG_DMA, +}; + +static const struct dpu_reg_dma_cfg sm8450_regdma = { + .base = 0x0, + .version = 0x00020000, + .trigger_sel_off = 0x119c, + .xin_id = 7, + .clk_ctrl = DPU_CLK_CTRL_REG_DMA, +}; + /************************************************************* * PERF data config *************************************************************/ @@ -1691,6 +2332,33 @@ static const struct dpu_perf_cfg sc8180x_perf_data = { .min_dram_ib = 800000, .danger_lut_tbl = {0xf, 0xffff, 0x0}, .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + +static const struct dpu_perf_cfg sc8280xp_perf_data = { + .max_bw_low = 13600000, + .max_bw_high = 18200000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .danger_lut_tbl = {0xf, 0xffff, 0x0}, + .qos_lut_tbl = { {.nentry = ARRAY_SIZE(sc8180x_qos_linear), .entries = sc8180x_qos_linear }, @@ -1739,6 +2407,36 @@ static const struct dpu_perf_cfg sm8250_perf_data = { .bw_inefficiency_factor = 120, }; +static const struct dpu_perf_cfg sm8450_perf_data = { + .max_bw_low = 13600000, + .max_bw_high = 18200000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 35, + /* FIXME: lut tables */ + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + static const struct dpu_perf_cfg sc7280_perf_data = { .max_bw_low = 4700000, .max_bw_high = 8800000, @@ -1767,6 +2465,36 @@ static const struct dpu_perf_cfg sc7280_perf_data = { .bw_inefficiency_factor = 120, }; +static const struct dpu_perf_cfg sm8350_perf_data = { + .max_bw_low = 11800000, + .max_bw_high = 15500000, + .min_core_ib = 2500000, + .min_llcc_ib = 0, + .min_dram_ib = 800000, + .min_prefill_lines = 40, + /* FIXME: lut tables */ + .danger_lut_tbl = {0x3ffff, 0x3ffff, 0x0}, + .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, + .qos_lut_tbl = { + {.nentry = ARRAY_SIZE(sc7180_qos_linear), + .entries = sc7180_qos_linear + }, + {.nentry = ARRAY_SIZE(sc7180_qos_macrotile), + .entries = sc7180_qos_macrotile + }, + {.nentry = ARRAY_SIZE(sc7180_qos_nrt), + .entries = sc7180_qos_nrt + }, + /* TODO: macrotile-qseed is different from macrotile */ + }, + .cdp_cfg = { + {.rd_enable = 1, .wr_enable = 1}, + {.rd_enable = 1, .wr_enable = 0} + }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, +}; + static const struct dpu_perf_cfg qcm2290_perf_data = { .max_bw_low = 2700000, .max_bw_high = 2700000, @@ -1899,6 +2627,8 @@ static const struct dpu_mdss_cfg sm8150_dpu_cfg = { .mixer = sm8150_lm, .dspp_count = ARRAY_SIZE(sm8150_dspp), .dspp = sm8150_dspp, + .dsc_count = ARRAY_SIZE(sm8150_dsc), + .dsc = sm8150_dsc, .pingpong_count = ARRAY_SIZE(sm8150_pp), .pingpong = sm8150_pp, .merge_3d_count = ARRAY_SIZE(sm8150_merge_3d), @@ -1937,6 +2667,32 @@ static const struct dpu_mdss_cfg sc8180x_dpu_cfg = { .mdss_irqs = IRQ_SC8180X_MASK, }; +static const struct dpu_mdss_cfg sc8280xp_dpu_cfg = { + .caps = &sc8280xp_dpu_caps, + .mdp_count = ARRAY_SIZE(sc8280xp_mdp), + .mdp = sc8280xp_mdp, + .ctl_count = ARRAY_SIZE(sc8280xp_ctl), + .ctl = sc8280xp_ctl, + .sspp_count = ARRAY_SIZE(sc8280xp_sspp), + .sspp = sc8280xp_sspp, + .mixer_count = ARRAY_SIZE(sc8280xp_lm), + .mixer = sc8280xp_lm, + .dspp_count = ARRAY_SIZE(sm8150_dspp), + .dspp = sm8150_dspp, + .pingpong_count = ARRAY_SIZE(sc8280xp_pp), + .pingpong = sc8280xp_pp, + .merge_3d_count = ARRAY_SIZE(sm8350_merge_3d), + .merge_3d = sm8350_merge_3d, + .intf_count = ARRAY_SIZE(sc8280xp_intf), + .intf = sc8280xp_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .reg_dma_count = 1, + .dma_cfg = &sc8280xp_regdma, + .perf = &sc8280xp_perf_data, + .mdss_irqs = IRQ_SC8280XP_MASK, +}; + static const struct dpu_mdss_cfg sm8250_dpu_cfg = { .caps = &sm8250_dpu_caps, .mdp_count = ARRAY_SIZE(sm8250_mdp), @@ -1949,6 +2705,8 @@ static const struct dpu_mdss_cfg sm8250_dpu_cfg = { .mixer = sm8150_lm, .dspp_count = ARRAY_SIZE(sm8150_dspp), .dspp = sm8150_dspp, + .dsc_count = ARRAY_SIZE(sm8150_dsc), + .dsc = sm8150_dsc, .pingpong_count = ARRAY_SIZE(sm8150_pp), .pingpong = sm8150_pp, .merge_3d_count = ARRAY_SIZE(sm8150_merge_3d), @@ -1965,6 +2723,84 @@ static const struct dpu_mdss_cfg sm8250_dpu_cfg = { .mdss_irqs = IRQ_SM8250_MASK, }; +static const struct dpu_mdss_cfg sm8350_dpu_cfg = { + .caps = &sm8350_dpu_caps, + .mdp_count = ARRAY_SIZE(sm8350_mdp), + .mdp = sm8350_mdp, + .ctl_count = ARRAY_SIZE(sm8350_ctl), + .ctl = sm8350_ctl, + .sspp_count = ARRAY_SIZE(sm8250_sspp), + .sspp = sm8250_sspp, + .mixer_count = ARRAY_SIZE(sm8150_lm), + .mixer = sm8150_lm, + .dspp_count = ARRAY_SIZE(sm8150_dspp), + .dspp = sm8150_dspp, + .pingpong_count = ARRAY_SIZE(sm8350_pp), + .pingpong = sm8350_pp, + .merge_3d_count = ARRAY_SIZE(sm8350_merge_3d), + .merge_3d = sm8350_merge_3d, + .intf_count = ARRAY_SIZE(sm8350_intf), + .intf = sm8350_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .reg_dma_count = 1, + .dma_cfg = &sm8350_regdma, + .perf = &sm8350_perf_data, + .mdss_irqs = IRQ_SM8350_MASK, +}; + +static const struct dpu_mdss_cfg sm8450_dpu_cfg = { + .caps = &sm8450_dpu_caps, + .mdp_count = ARRAY_SIZE(sm8450_mdp), + .mdp = sm8450_mdp, + .ctl_count = ARRAY_SIZE(sm8450_ctl), + .ctl = sm8450_ctl, + .sspp_count = ARRAY_SIZE(sm8450_sspp), + .sspp = sm8450_sspp, + .mixer_count = ARRAY_SIZE(sm8150_lm), + .mixer = sm8150_lm, + .dspp_count = ARRAY_SIZE(sm8150_dspp), + .dspp = sm8150_dspp, + .pingpong_count = ARRAY_SIZE(sm8450_pp), + .pingpong = sm8450_pp, + .merge_3d_count = ARRAY_SIZE(sm8450_merge_3d), + .merge_3d = sm8450_merge_3d, + .intf_count = ARRAY_SIZE(sm8450_intf), + .intf = sm8450_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .reg_dma_count = 1, + .dma_cfg = &sm8450_regdma, + .perf = &sm8450_perf_data, + .mdss_irqs = IRQ_SM8450_MASK, +}; + +static const struct dpu_mdss_cfg sm8550_dpu_cfg = { + .caps = &sm8550_dpu_caps, + .mdp_count = ARRAY_SIZE(sm8550_mdp), + .mdp = sm8550_mdp, + .ctl_count = ARRAY_SIZE(sm8550_ctl), + .ctl = sm8550_ctl, + .sspp_count = ARRAY_SIZE(sm8550_sspp), + .sspp = sm8550_sspp, + .mixer_count = ARRAY_SIZE(sm8150_lm), + .mixer = sm8150_lm, + .dspp_count = ARRAY_SIZE(sm8150_dspp), + .dspp = sm8150_dspp, + .pingpong_count = ARRAY_SIZE(sm8550_pp), + .pingpong = sm8550_pp, + .merge_3d_count = ARRAY_SIZE(sm8550_merge_3d), + .merge_3d = sm8550_merge_3d, + .intf_count = ARRAY_SIZE(sm8550_intf), + .intf = sm8550_intf, + .vbif_count = ARRAY_SIZE(sdm845_vbif), + .vbif = sdm845_vbif, + .reg_dma_count = 1, + .dma_cfg = &sm8450_regdma, + .perf = &sm8450_perf_data, + .mdss_irqs = IRQ_SM8450_MASK, +}; + static const struct dpu_mdss_cfg sc7280_dpu_cfg = { .caps = &sc7280_dpu_caps, .mdp_count = ARRAY_SIZE(sc7280_mdp), @@ -2023,7 +2859,11 @@ static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = { { .hw_rev = DPU_HW_VER_620, .dpu_cfg = &sc7180_dpu_cfg}, { .hw_rev = DPU_HW_VER_630, .dpu_cfg = &sm6115_dpu_cfg}, { .hw_rev = DPU_HW_VER_650, .dpu_cfg = &qcm2290_dpu_cfg}, + { .hw_rev = DPU_HW_VER_700, .dpu_cfg = &sm8350_dpu_cfg}, { .hw_rev = DPU_HW_VER_720, .dpu_cfg = &sc7280_dpu_cfg}, + { .hw_rev = DPU_HW_VER_800, .dpu_cfg = &sc8280xp_dpu_cfg}, + { .hw_rev = DPU_HW_VER_810, .dpu_cfg = &sm8450_dpu_cfg}, + { .hw_rev = DPU_HW_VER_900, .dpu_cfg = &sm8550_dpu_cfg}, }; const struct dpu_mdss_cfg *dpu_hw_catalog_init(u32 hw_rev) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 3b645d5aa9aa..ddab9caebb18 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -46,7 +46,11 @@ #define DPU_HW_VER_620 DPU_HW_VER(6, 2, 0) /* sc7180 v1.0 */ #define DPU_HW_VER_630 DPU_HW_VER(6, 3, 0) /* sm6115|sm4250 */ #define DPU_HW_VER_650 DPU_HW_VER(6, 5, 0) /* qcm2290|sm4125 */ +#define DPU_HW_VER_700 DPU_HW_VER(7, 0, 0) /* sm8350 */ #define DPU_HW_VER_720 DPU_HW_VER(7, 2, 0) /* sc7280 */ +#define DPU_HW_VER_800 DPU_HW_VER(8, 0, 0) /* sc8280xp */ +#define DPU_HW_VER_810 DPU_HW_VER(8, 1, 0) /* sm8450 */ +#define DPU_HW_VER_900 DPU_HW_VER(9, 0, 0) /* sm8550 */ #define IS_MSM8996_TARGET(rev) IS_DPU_MAJOR_MINOR_SAME((rev), DPU_HW_VER_170) #define IS_MSM8998_TARGET(rev) IS_DPU_MAJOR_MINOR_SAME((rev), DPU_HW_VER_300) @@ -83,6 +87,8 @@ enum { * @DPU_MDP_UBWC_1_0, This chipsets supports Universal Bandwidth * compression initial revision * @DPU_MDP_UBWC_1_5, Universal Bandwidth compression version 1.5 + * @DPU_MDP_PERIPH_0_REMOVED Indicates that access to periph top0 block results + * in a failure * @DPU_MDP_MAX Maximum value */ @@ -93,6 +99,7 @@ enum { DPU_MDP_UBWC_1_0, DPU_MDP_UBWC_1_5, DPU_MDP_AUDIO_SELECT, + DPU_MDP_PERIPH_0_REMOVED, DPU_MDP_MAX }; @@ -192,6 +199,7 @@ enum { * @DPU_CTL_SPLIT_DISPLAY: CTL supports video mode split display * @DPU_CTL_FETCH_ACTIVE: Active CTL for fetch HW (SSPPs) * @DPU_CTL_VM_CFG: CTL config to support multiple VMs + * @DPU_CTL_HAS_LAYER_EXT4: CTL has the CTL_LAYER_EXT4 register * @DPU_CTL_MAX */ enum { @@ -199,6 +207,7 @@ enum { DPU_CTL_ACTIVE_CFG, DPU_CTL_FETCH_ACTIVE, DPU_CTL_VM_CFG, + DPU_CTL_HAS_LAYER_EXT4, DPU_CTL_MAX }; @@ -267,6 +276,15 @@ enum { }; /** + * DSC features + * @DPU_DSC_OUTPUT_CTRL Configure which PINGPONG block gets + * the pixel output from this DSC. + */ +enum { + DPU_DSC_OUTPUT_CTRL = 0x1, +}; + +/** * MACRO DPU_HW_BLK_INFO - information of HW blocks inside DPU * @name: string name for debug purposes * @id: enum identifying this block @@ -519,7 +537,6 @@ struct dpu_clk_ctrl_reg { * @base: register base offset to mdss * @features bit mask identifying sub-blocks/features * @highest_bank_bit: UBWC parameter - * @ubwc_static: ubwc static configuration * @ubwc_swizzle: ubwc default swizzle setting * @clk_ctrls clock control register definition */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index a35ecb6676c8..b88a2f3724e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -17,6 +17,8 @@ (0x70 + (((lm) - LM_0) * 0x004)) #define CTL_LAYER_EXT3(lm) \ (0xA0 + (((lm) - LM_0) * 0x004)) +#define CTL_LAYER_EXT4(lm) \ + (0xB8 + (((lm) - LM_0) * 0x004)) #define CTL_TOP 0x014 #define CTL_FLUSH 0x018 #define CTL_START 0x01C @@ -377,12 +379,37 @@ static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx) DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0); } +struct ctl_blend_config { + int idx, shift, ext_shift; +}; + +static const struct ctl_blend_config ctl_blend_config[][2] = { + [SSPP_NONE] = { { -1 }, { -1 } }, + [SSPP_MAX] = { { -1 }, { -1 } }, + [SSPP_VIG0] = { { 0, 0, 0 }, { 3, 0 } }, + [SSPP_VIG1] = { { 0, 3, 2 }, { 3, 4 } }, + [SSPP_VIG2] = { { 0, 6, 4 }, { 3, 8 } }, + [SSPP_VIG3] = { { 0, 26, 6 }, { 3, 12 } }, + [SSPP_RGB0] = { { 0, 9, 8 }, { -1 } }, + [SSPP_RGB1] = { { 0, 12, 10 }, { -1 } }, + [SSPP_RGB2] = { { 0, 15, 12 }, { -1 } }, + [SSPP_RGB3] = { { 0, 29, 14 }, { -1 } }, + [SSPP_DMA0] = { { 0, 18, 16 }, { 2, 8 } }, + [SSPP_DMA1] = { { 0, 21, 18 }, { 2, 12 } }, + [SSPP_DMA2] = { { 2, 0 }, { 2, 16 } }, + [SSPP_DMA3] = { { 2, 4 }, { 2, 20 } }, + [SSPP_DMA4] = { { 4, 0 }, { 4, 8 } }, + [SSPP_DMA5] = { { 4, 4 }, { 4, 12 } }, + [SSPP_CURSOR0] = { { 1, 20 }, { -1 } }, + [SSPP_CURSOR1] = { { 1, 26 }, { -1 } }, +}; + static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx, enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg) { struct dpu_hw_blk_reg_map *c = &ctx->hw; - u32 mixercfg = 0, mixercfg_ext = 0, mix, ext; - u32 mixercfg_ext2 = 0, mixercfg_ext3 = 0; + u32 mix, ext, mix_ext; + u32 mixercfg[5] = { 0 }; int i, j; int stages; int pipes_per_stage; @@ -397,7 +424,7 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx, else pipes_per_stage = 1; - mixercfg = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */ + mixercfg[0] = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */ if (!stage_cfg) goto exit; @@ -406,109 +433,35 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx, /* overflow to ext register if 'i + 1 > 7' */ mix = (i + 1) & 0x7; ext = i >= 7; + mix_ext = (i + 1) & 0xf; for (j = 0 ; j < pipes_per_stage; j++) { enum dpu_sspp_multirect_index rect_index = stage_cfg->multirect_index[i][j]; - - switch (stage_cfg->stage[i][j]) { - case SSPP_VIG0: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext3 |= ((i + 1) & 0xF) << 0; - } else { - mixercfg |= mix << 0; - mixercfg_ext |= ext << 0; - } - break; - case SSPP_VIG1: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext3 |= ((i + 1) & 0xF) << 4; - } else { - mixercfg |= mix << 3; - mixercfg_ext |= ext << 2; - } - break; - case SSPP_VIG2: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext3 |= ((i + 1) & 0xF) << 8; - } else { - mixercfg |= mix << 6; - mixercfg_ext |= ext << 4; - } - break; - case SSPP_VIG3: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext3 |= ((i + 1) & 0xF) << 12; - } else { - mixercfg |= mix << 26; - mixercfg_ext |= ext << 6; - } - break; - case SSPP_RGB0: - mixercfg |= mix << 9; - mixercfg_ext |= ext << 8; - break; - case SSPP_RGB1: - mixercfg |= mix << 12; - mixercfg_ext |= ext << 10; - break; - case SSPP_RGB2: - mixercfg |= mix << 15; - mixercfg_ext |= ext << 12; - break; - case SSPP_RGB3: - mixercfg |= mix << 29; - mixercfg_ext |= ext << 14; - break; - case SSPP_DMA0: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext2 |= ((i + 1) & 0xF) << 8; - } else { - mixercfg |= mix << 18; - mixercfg_ext |= ext << 16; - } - break; - case SSPP_DMA1: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext2 |= ((i + 1) & 0xF) << 12; - } else { - mixercfg |= mix << 21; - mixercfg_ext |= ext << 18; - } - break; - case SSPP_DMA2: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext2 |= ((i + 1) & 0xF) << 16; - } else { - mix |= (i + 1) & 0xF; - mixercfg_ext2 |= mix << 0; - } - break; - case SSPP_DMA3: - if (rect_index == DPU_SSPP_RECT_1) { - mixercfg_ext2 |= ((i + 1) & 0xF) << 20; - } else { - mix |= (i + 1) & 0xF; - mixercfg_ext2 |= mix << 4; - } - break; - case SSPP_CURSOR0: - mixercfg_ext |= ((i + 1) & 0xF) << 20; - break; - case SSPP_CURSOR1: - mixercfg_ext |= ((i + 1) & 0xF) << 26; - break; - default: - break; + enum dpu_sspp pipe = stage_cfg->stage[i][j]; + const struct ctl_blend_config *cfg = + &ctl_blend_config[pipe][rect_index == DPU_SSPP_RECT_1]; + + /* + * CTL_LAYER has 3-bit field (and extra bits in EXT register), + * all EXT registers has 4-bit fields. + */ + if (cfg->idx == 0) { + mixercfg[0] |= mix << cfg->shift; + mixercfg[1] |= ext << cfg->ext_shift; + } else { + mixercfg[cfg->idx] |= mix_ext << cfg->shift; } } } exit: - DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg); - DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext); - DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg_ext2); - DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg_ext3); + DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg[0]); + DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg[1]); + DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg[2]); + DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg[3]); + if ((test_bit(DPU_CTL_HAS_LAYER_EXT4, &ctx->caps->features))) + DPU_REG_WRITE(c, CTL_LAYER_EXT4(lm), mixercfg[4]); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c index 3662df698dae..619926da1441 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c @@ -29,6 +29,8 @@ #define DSC_RANGE_MAX_QP 0x0B0 #define DSC_RANGE_BPG_OFFSET 0x0EC +#define DSC_CTL(m) (0x1800 - 0x3FC * (m - DSC_0)) + static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc) { struct dpu_hw_blk_reg_map *c = &dsc->hw; @@ -150,6 +152,29 @@ static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc, } } +static void dpu_hw_dsc_bind_pingpong_blk( + struct dpu_hw_dsc *hw_dsc, + bool enable, + const enum dpu_pingpong pp) +{ + struct dpu_hw_blk_reg_map *c = &hw_dsc->hw; + int mux_cfg = 0xF; + u32 dsc_ctl_offset; + + dsc_ctl_offset = DSC_CTL(hw_dsc->idx); + + if (enable) + mux_cfg = (pp - PINGPONG_0) & 0x7; + + DRM_DEBUG_KMS("%s dsc:%d %s pp:%d\n", + enable ? "Binding" : "Unbinding", + hw_dsc->idx - DSC_0, + enable ? "to" : "from", + pp - PINGPONG_0); + + DPU_REG_WRITE(c, dsc_ctl_offset, mux_cfg); +} + static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc, const struct dpu_mdss_cfg *m, void __iomem *addr, @@ -174,6 +199,8 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops, ops->dsc_disable = dpu_hw_dsc_disable; ops->dsc_config = dpu_hw_dsc_config; ops->dsc_config_thresh = dpu_hw_dsc_config_thresh; + if (cap & BIT(DPU_DSC_OUTPUT_CTRL)) + ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk; }; struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h index c0b77fe1a696..ae9b5db53d7f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h @@ -42,6 +42,10 @@ struct dpu_hw_dsc_ops { */ void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc, struct drm_dsc_config *dsc); + + void (*dsc_bind_pingpong_blk)(struct dpu_hw_dsc *hw_dsc, + bool enable, + enum dpu_pingpong pp); }; struct dpu_hw_dsc { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index cf1b6d84c18a..53326f25e40e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -35,6 +35,9 @@ #define MDP_INTF_3_OFF_REV_7xxx 0x37000 #define MDP_INTF_4_OFF_REV_7xxx 0x38000 #define MDP_INTF_5_OFF_REV_7xxx 0x39000 +#define MDP_INTF_6_OFF_REV_7xxx 0x3a000 +#define MDP_INTF_7_OFF_REV_7xxx 0x3b000 +#define MDP_INTF_8_OFF_REV_7xxx 0x3c000 /** * struct dpu_intr_reg - array of DPU register sets @@ -139,6 +142,21 @@ static const struct dpu_intr_reg dpu_intr_set[] = { MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN, MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_STATUS }, + [MDP_INTF6_7xxx_INTR] = { + MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_6_OFF_REV_7xxx+INTF_INTR_STATUS + }, + [MDP_INTF7_7xxx_INTR] = { + MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_7_OFF_REV_7xxx+INTF_INTR_STATUS + }, + [MDP_INTF8_7xxx_INTR] = { + MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_8_OFF_REV_7xxx+INTF_INTR_STATUS + }, }; #define DPU_IRQ_REG(irq_idx) (irq_idx / 32) @@ -252,9 +270,9 @@ static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) cache_irq_mask = intr->cache_irq_mask[reg_idx]; if (cache_irq_mask & DPU_IRQ_MASK(irq_idx)) { - dbgstr = "DPU IRQ already set:"; + dbgstr = "already "; } else { - dbgstr = "DPU IRQ enabled:"; + dbgstr = ""; cache_irq_mask |= DPU_IRQ_MASK(irq_idx); /* Cleaning any pending interrupt */ @@ -268,7 +286,7 @@ static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) intr->cache_irq_mask[reg_idx] = cache_irq_mask; } - pr_debug("%s MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", dbgstr, + pr_debug("DPU IRQ %d %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr, DPU_IRQ_MASK(irq_idx), cache_irq_mask); return 0; @@ -301,9 +319,9 @@ static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) cache_irq_mask = intr->cache_irq_mask[reg_idx]; if ((cache_irq_mask & DPU_IRQ_MASK(irq_idx)) == 0) { - dbgstr = "DPU IRQ is already cleared:"; + dbgstr = "already "; } else { - dbgstr = "DPU IRQ mask disable:"; + dbgstr = ""; cache_irq_mask &= ~DPU_IRQ_MASK(irq_idx); /* Disable interrupts based on the new mask */ @@ -317,7 +335,7 @@ static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) intr->cache_irq_mask[reg_idx] = cache_irq_mask; } - pr_debug("%s MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", dbgstr, + pr_debug("DPU IRQ %d %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr, DPU_IRQ_MASK(irq_idx), cache_irq_mask); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index 46443955443c..425465011c80 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -31,6 +31,9 @@ enum dpu_hw_intr_reg { MDP_INTF3_7xxx_INTR, MDP_INTF4_7xxx_INTR, MDP_INTF5_7xxx_INTR, + MDP_INTF6_7xxx_INTR, + MDP_INTF7_7xxx_INTR, + MDP_INTF8_7xxx_INTR, MDP_INTR_MAX, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index d3b0ed0a9c6c..2d9192a6ce00 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -120,6 +120,8 @@ enum dpu_sspp { SSPP_DMA1, SSPP_DMA2, SSPP_DMA3, + SSPP_DMA4, + SSPP_DMA5, SSPP_CURSOR0, SSPP_CURSOR1, SSPP_MAX @@ -195,6 +197,8 @@ enum dpu_pingpong { PINGPONG_3, PINGPONG_4, PINGPONG_5, + PINGPONG_6, + PINGPONG_7, PINGPONG_S0, PINGPONG_MAX }; @@ -203,6 +207,7 @@ enum dpu_merge_3d { MERGE_3D_0 = 1, MERGE_3D_1, MERGE_3D_2, + MERGE_3D_3, MERGE_3D_MAX }; @@ -214,6 +219,8 @@ enum dpu_intf { INTF_4, INTF_5, INTF_6, + INTF_7, + INTF_8, INTF_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index 691c471b08c2..4246ab0b3bee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -310,7 +310,11 @@ static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx, ctx->mdp->highest_bank_bit << 18); switch (ctx->catalog->caps->ubwc_version) { case DPU_HW_UBWC_VER_10: - /* TODO: UBWC v1 case */ + fast_clear = fmt->alpha_enable ? BIT(31) : 0; + DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL, + fast_clear | (ctx->mdp->ubwc_swizzle & 0x1) | + BIT(8) | + (ctx->mdp->highest_bank_bit << 4)); break; case DPU_HW_UBWC_VER_20: fast_clear = fmt->alpha_enable ? BIT(31) : 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index c3110a25a30d..2bb02e17ee52 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -7,40 +7,17 @@ #include "dpu_hw_top.h" #include "dpu_kms.h" -#define SSPP_SPARE 0x28 - #define FLD_SPLIT_DISPLAY_CMD BIT(1) #define FLD_SMART_PANEL_FREE_RUN BIT(2) #define FLD_INTF_1_SW_TRG_MUX BIT(4) #define FLD_INTF_2_SW_TRG_MUX BIT(8) #define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF -#define DANGER_STATUS 0x360 -#define SAFE_STATUS 0x364 - -#define TE_LINE_INTERVAL 0x3F4 - #define TRAFFIC_SHAPER_EN BIT(31) #define TRAFFIC_SHAPER_RD_CLIENT(num) (0x030 + (num * 4)) #define TRAFFIC_SHAPER_WR_CLIENT(num) (0x060 + (num * 4)) #define TRAFFIC_SHAPER_FIXPOINT_FACTOR 4 -#define MDP_WD_TIMER_0_CTL 0x380 -#define MDP_WD_TIMER_0_CTL2 0x384 -#define MDP_WD_TIMER_0_LOAD_VALUE 0x388 -#define MDP_WD_TIMER_1_CTL 0x390 -#define MDP_WD_TIMER_1_CTL2 0x394 -#define MDP_WD_TIMER_1_LOAD_VALUE 0x398 -#define MDP_WD_TIMER_2_CTL 0x420 -#define MDP_WD_TIMER_2_CTL2 0x424 -#define MDP_WD_TIMER_2_LOAD_VALUE 0x428 -#define MDP_WD_TIMER_3_CTL 0x430 -#define MDP_WD_TIMER_3_CTL2 0x434 -#define MDP_WD_TIMER_3_LOAD_VALUE 0x438 -#define MDP_WD_TIMER_4_CTL 0x440 -#define MDP_WD_TIMER_4_CTL2 0x444 -#define MDP_WD_TIMER_4_LOAD_VALUE 0x448 - #define MDP_TICK_COUNT 16 #define XO_CLK_RATE 19200 #define MS_TICKS_IN_SEC 1000 @@ -48,8 +25,6 @@ #define CALCULATE_WD_LOAD_VALUE(fps) \ ((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps))) -#define DCE_SEL 0x450 - static void dpu_hw_setup_split_pipe(struct dpu_hw_mdp *mdp, struct split_pipe_cfg *cfg) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h index c8156ed4b7fb..feb9a729844a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h @@ -16,6 +16,7 @@ #define INTR_CLEAR 0x018 #define INTR2_EN 0x008 #define INTR2_STATUS 0x00c +#define SSPP_SPARE 0x028 #define INTR2_CLEAR 0x02c #define HIST_INTR_EN 0x01c #define HIST_INTR_STATUS 0x020 @@ -28,7 +29,15 @@ #define DSPP_IGC_COLOR0_RAM_LUTN 0x300 #define DSPP_IGC_COLOR1_RAM_LUTN 0x304 #define DSPP_IGC_COLOR2_RAM_LUTN 0x308 +#define DANGER_STATUS 0x360 +#define SAFE_STATUS 0x364 #define HW_EVENTS_CTL 0x37C +#define MDP_WD_TIMER_0_CTL 0x380 +#define MDP_WD_TIMER_0_CTL2 0x384 +#define MDP_WD_TIMER_0_LOAD_VALUE 0x388 +#define MDP_WD_TIMER_1_CTL 0x390 +#define MDP_WD_TIMER_1_CTL2 0x394 +#define MDP_WD_TIMER_1_LOAD_VALUE 0x398 #define CLK_CTRL3 0x3A8 #define CLK_STATUS3 0x3AC #define CLK_CTRL4 0x3B0 @@ -43,6 +52,18 @@ #define HDMI_DP_CORE_SELECT 0x408 #define MDP_OUT_CTL_0 0x410 #define MDP_VSYNC_SEL 0x414 +#define MDP_WD_TIMER_2_CTL 0x420 +#define MDP_WD_TIMER_2_CTL2 0x424 +#define MDP_WD_TIMER_2_LOAD_VALUE 0x428 +#define MDP_WD_TIMER_3_CTL 0x430 +#define MDP_WD_TIMER_3_CTL2 0x434 +#define MDP_WD_TIMER_3_LOAD_VALUE 0x438 +#define MDP_WD_TIMER_4_CTL 0x440 +#define MDP_WD_TIMER_4_CTL2 0x444 +#define MDP_WD_TIMER_4_LOAD_VALUE 0x448 #define DCE_SEL 0x450 +#define MDP_PERIPH_TOP0 MDP_WD_TIMER_0_CTL +#define MDP_PERIPH_TOP0_END CLK_CTRL3 + #endif /*_DPU_HWIO_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index b71199511a52..a683bd9b5a04 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -927,8 +927,20 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k msm_disp_snapshot_add_block(disp_state, cat->wb[i].len, dpu_kms->mmio + cat->wb[i].base, "wb_%d", i); - msm_disp_snapshot_add_block(disp_state, cat->mdp[0].len, - dpu_kms->mmio + cat->mdp[0].base, "top"); + if (cat->mdp[0].features & BIT(DPU_MDP_PERIPH_0_REMOVED)) { + msm_disp_snapshot_add_block(disp_state, MDP_PERIPH_TOP0, + dpu_kms->mmio + cat->mdp[0].base, "top"); + msm_disp_snapshot_add_block(disp_state, cat->mdp[0].len - MDP_PERIPH_TOP0_END, + dpu_kms->mmio + cat->mdp[0].base + MDP_PERIPH_TOP0_END, "top_2"); + } else { + msm_disp_snapshot_add_block(disp_state, cat->mdp[0].len, + dpu_kms->mmio + cat->mdp[0].base, "top"); + } + + /* dump DSC sub-blocks HW regs info */ + for (i = 0; i < cat->dsc_count; i++) + msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, + dpu_kms->mmio + cat->dsc[i].base, "dsc_%d", i); pm_runtime_put_sync(&dpu_kms->pdev->dev); } @@ -1292,9 +1304,13 @@ static const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sc7180-dpu", }, { .compatible = "qcom,sc7280-dpu", }, { .compatible = "qcom,sc8180x-dpu", }, + { .compatible = "qcom,sc8280xp-dpu", }, { .compatible = "qcom,sm6115-dpu", }, { .compatible = "qcom,sm8150-dpu", }, { .compatible = "qcom,sm8250-dpu", }, + { .compatible = "qcom,sm8350-dpu", }, + { .compatible = "qcom,sm8450-dpu", }, + { .compatible = "qcom,sm8550-dpu", }, {} }; MODULE_DEVICE_TABLE(of, dpu_dt_match); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 86719020afe2..bfd5be89e8b8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1126,7 +1126,7 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) struct dpu_plane_state *pstate = to_dpu_plane_state(state); struct drm_crtc *crtc = state->crtc; struct drm_framebuffer *fb = state->fb; - bool is_rt_pipe, update_qos_remap; + bool is_rt_pipe; const struct dpu_format *fmt = to_dpu_format(msm_framebuffer_format(fb)); struct dpu_hw_pipe_cfg pipe_cfg; @@ -1138,6 +1138,9 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) pstate->pending = true; is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT); + pstate->needs_qos_remap |= (is_rt_pipe != pdpu->is_rt_pipe); + pdpu->is_rt_pipe = is_rt_pipe; + _dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL); DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT @@ -1219,14 +1222,8 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) _dpu_plane_set_ot_limit(plane, crtc, &pipe_cfg); } - update_qos_remap = (is_rt_pipe != pdpu->is_rt_pipe) || - pstate->needs_qos_remap; - - if (update_qos_remap) { - if (is_rt_pipe != pdpu->is_rt_pipe) - pdpu->is_rt_pipe = is_rt_pipe; - else if (pstate->needs_qos_remap) - pstate->needs_qos_remap = false; + if (pstate->needs_qos_remap) { + pstate->needs_qos_remap = false; _dpu_plane_set_qos_remap(plane); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 73b3442e7467..396429e63756 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -496,6 +496,11 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm, /* check if DSC required are allocated or not */ for (i = 0; i < num_dsc; i++) { + if (!rm->dsc_blks[i]) { + DPU_ERROR("DSC %d does not exist\n", i); + return -EIO; + } + if (global_state->dsc_to_enc_id[i]) { DPU_ERROR("DSC %d is already allocated\n", i); return -EIO; @@ -543,8 +548,8 @@ static int _dpu_rm_populate_requirements( { reqs->topology = req_topology; - DRM_DEBUG_KMS("num_lm: %d num_enc: %d num_intf: %d\n", - reqs->topology.num_lm, reqs->topology.num_enc, + DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n", + reqs->topology.num_lm, reqs->topology.num_dsc, reqs->topology.num_intf); return 0; @@ -660,6 +665,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, blks_size, enc_id); break; } + if (!hw_blks[i]) { + DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n", + type, enc_id); + break; + } blks[num_blks++] = hw_blks[i]; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c index 088ec990a2f2..2a5a68366582 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c @@ -70,6 +70,8 @@ int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc, int rc = 0; dpu_wb_conn = devm_kzalloc(dev->dev, sizeof(*dpu_wb_conn), GFP_KERNEL); + if (!dpu_wb_conn) + return -ENOMEM; drm_connector_helper_add(&dpu_wb_conn->base.base, &dpu_wb_conn_helper_funcs); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_irq.c index 4d49f3ba6a96..ddcdd5e87853 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_irq.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_irq.c @@ -69,8 +69,7 @@ irqreturn_t mdp4_irq(struct msm_kms *kms) struct mdp_kms *mdp_kms = to_mdp_kms(kms); struct mdp4_kms *mdp4_kms = to_mdp4_kms(mdp_kms); struct drm_device *dev = mdp4_kms->dev; - struct msm_drm_private *priv = dev->dev_private; - unsigned int id; + struct drm_crtc *crtc; uint32_t status, enable; enable = mdp4_read(mdp4_kms, REG_MDP4_INTR_ENABLE); @@ -81,9 +80,9 @@ irqreturn_t mdp4_irq(struct msm_kms *kms) mdp_dispatch_irqs(mdp_kms, status); - for (id = 0; id < priv->num_crtcs; id++) - if (status & mdp4_crtc_vblank(priv->crtcs[id])) - drm_handle_vblank(dev, id); + drm_for_each_crtc(crtc, dev) + if (status & mdp4_crtc_vblank(crtc)) + drm_crtc_handle_vblank(crtc); return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index e86421c69bd1..86036dd4e1e8 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -1139,7 +1139,10 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc) if (crtc->state) mdp5_crtc_destroy_state(crtc, crtc->state); - __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base); + if (mdp5_cstate) + __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base); + else + __drm_atomic_helper_crtc_reset(crtc, NULL); } static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c index 9b4c8d92ff32..43443a435d59 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_irq.c @@ -82,8 +82,7 @@ irqreturn_t mdp5_irq(struct msm_kms *kms) struct mdp_kms *mdp_kms = to_mdp_kms(kms); struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms); struct drm_device *dev = mdp5_kms->dev; - struct msm_drm_private *priv = dev->dev_private; - unsigned int id; + struct drm_crtc *crtc; uint32_t status, enable; enable = mdp5_read(mdp5_kms, REG_MDP5_INTR_EN); @@ -94,9 +93,9 @@ irqreturn_t mdp5_irq(struct msm_kms *kms) mdp_dispatch_irqs(mdp_kms, status); - for (id = 0; id < priv->num_crtcs; id++) - if (status & mdp5_crtc_vblank(priv->crtcs[id])) - drm_handle_vblank(dev, id); + drm_for_each_crtc(crtc, dev) + if (status & mdp5_crtc_vblank(crtc)) + drm_crtc_handle_vblank(crtc); return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c index e75b97127c0d..b73031cd48e4 100644 --- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c +++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c @@ -129,6 +129,9 @@ void msm_disp_snapshot_destroy(struct drm_device *drm_dev) } priv = drm_dev->dev_private; + if (!priv->kms) + return; + kms = priv->kms; if (kms->dump_worker) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 7ff60e5ff325..bde1a7ce442f 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -122,61 +122,64 @@ struct dp_display_private { struct msm_dp_desc { phys_addr_t io_start; + unsigned int id; unsigned int connector_type; bool wide_bus_en; }; -struct msm_dp_config { - const struct msm_dp_desc *descs; - size_t num_descs; -}; - static const struct msm_dp_desc sc7180_dp_descs[] = { - [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, -}; - -static const struct msm_dp_config sc7180_dp_cfg = { - .descs = sc7180_dp_descs, - .num_descs = ARRAY_SIZE(sc7180_dp_descs), + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + {} }; static const struct msm_dp_desc sc7280_dp_descs[] = { - [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, - [MSM_DP_CONTROLLER_1] = { .io_start = 0x0aea0000, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true }, -}; - -static const struct msm_dp_config sc7280_dp_cfg = { - .descs = sc7280_dp_descs, - .num_descs = ARRAY_SIZE(sc7280_dp_descs), + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true }, + {} }; static const struct msm_dp_desc sc8180x_dp_descs[] = { - [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, - [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, - [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP }, + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP }, + {} }; -static const struct msm_dp_config sc8180x_dp_cfg = { - .descs = sc8180x_dp_descs, - .num_descs = ARRAY_SIZE(sc8180x_dp_descs), +static const struct msm_dp_desc sc8280xp_dp_descs[] = { + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x22090000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + { .io_start = 0x220a0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true }, + {} }; -static const struct msm_dp_desc sm8350_dp_descs[] = { - [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, +static const struct msm_dp_desc sc8280xp_edp_descs[] = { + { .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true }, + { .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true }, + { .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true }, + { .io_start = 0x220a0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true }, + {} }; -static const struct msm_dp_config sm8350_dp_cfg = { - .descs = sm8350_dp_descs, - .num_descs = ARRAY_SIZE(sm8350_dp_descs), +static const struct msm_dp_desc sm8350_dp_descs[] = { + { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort }, + {} }; static const struct of_device_id dp_dt_match[] = { - { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg }, - { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_cfg }, - { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_cfg }, - { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg }, - { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg }, - { .compatible = "qcom,sm8350-dp", .data = &sm8350_dp_cfg }, + { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_descs }, + { .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_descs }, + { .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_descs }, + { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_descs }, + { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_descs }, + { .compatible = "qcom,sc8280xp-dp", .data = &sc8280xp_dp_descs }, + { .compatible = "qcom,sc8280xp-edp", .data = &sc8280xp_edp_descs }, + { .compatible = "qcom,sdm845-dp", .data = &sc7180_dp_descs }, + { .compatible = "qcom,sm8350-dp", .data = &sm8350_dp_descs }, {} }; @@ -390,6 +393,10 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) struct edid *edid; dp->panel->max_dp_lanes = dp->parser->max_dp_lanes; + dp->panel->max_dp_link_rate = dp->parser->max_dp_link_rate; + + drm_dbg_dp(dp->drm_dev, "max_lanes=%d max_link_rate=%d\n", + dp->panel->max_dp_lanes, dp->panel->max_dp_link_rate); rc = dp_panel_read_sink_caps(dp->panel, dp->dp_display.connector); if (rc) @@ -607,8 +614,10 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) } /* enable HDP irq_hpd/replug interrupt */ - dp_catalog_hpd_config_intr(dp->catalog, - DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true); + if (dp->dp_display.internal_hpd) + dp_catalog_hpd_config_intr(dp->catalog, + DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, + true); drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n", dp->dp_display.connector_type, state); @@ -648,8 +657,10 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp->dp_display.connector_type, state); /* disable irq_hpd/replug interrupts */ - dp_catalog_hpd_config_intr(dp->catalog, - DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, false); + if (dp->dp_display.internal_hpd) + dp_catalog_hpd_config_intr(dp->catalog, + DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, + false); /* unplugged, no more irq_hpd handle */ dp_del_event(dp, EV_IRQ_HPD_INT); @@ -675,7 +686,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) } /* disable HPD plug interrupts */ - dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, false); + if (dp->dp_display.internal_hpd) + dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, false); /* * We don't need separate work for disconnect as @@ -693,7 +705,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp_display_handle_plugged_change(&dp->dp_display, false); /* enable HDP plug interrupt to prepare for next plugin */ - if (!dp->dp_display.is_edp) + if (dp->dp_display.internal_hpd) dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true); drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n", @@ -1078,8 +1090,8 @@ static void dp_display_config_hpd(struct dp_display_private *dp) dp_display_host_init(dp); dp_catalog_ctrl_hpd_config(dp->catalog); - /* Enable plug and unplug interrupts only for external DisplayPort */ - if (!dp->dp_display.is_edp) + /* Enable plug and unplug interrupts only if requested */ + if (dp->dp_display.internal_hpd) dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | DP_DP_HPD_UNPLUG_INT_MASK, @@ -1262,10 +1274,9 @@ int dp_display_request_irq(struct msm_dp *dp_display) return 0; } -static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pdev, - unsigned int *id) +static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pdev) { - const struct msm_dp_config *cfg = of_device_get_match_data(&pdev->dev); + const struct msm_dp_desc *descs = of_device_get_match_data(&pdev->dev); struct resource *res; int i; @@ -1273,11 +1284,9 @@ static const struct msm_dp_desc *dp_display_get_desc(struct platform_device *pde if (!res) return NULL; - for (i = 0; i < cfg->num_descs; i++) { - if (cfg->descs[i].io_start == res->start) { - *id = i; - return &cfg->descs[i]; - } + for (i = 0; i < descs[i].io_start; i++) { + if (descs[i].io_start == res->start) + return &descs[i]; } dev_err(&pdev->dev, "unknown displayport instance\n"); @@ -1299,12 +1308,13 @@ static int dp_display_probe(struct platform_device *pdev) if (!dp) return -ENOMEM; - desc = dp_display_get_desc(pdev, &dp->id); + desc = dp_display_get_desc(pdev); if (!desc) return -EINVAL; dp->pdev = pdev; dp->name = "drm_dp"; + dp->id = desc->id; dp->dp_display.connector_type = desc->connector_type; dp->wide_bus_en = desc->wide_bus_en; dp->dp_display.is_edp = @@ -1373,8 +1383,7 @@ static int dp_pm_resume(struct device *dev) dp_catalog_ctrl_hpd_config(dp->catalog); - - if (!dp->dp_display.is_edp) + if (dp->dp_display.internal_hpd) dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | DP_DP_HPD_UNPLUG_INT_MASK, @@ -1497,7 +1506,7 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display) dp = container_of(dp_display, struct dp_display_private, dp_display); if (!dp_display->is_edp) - dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100); + dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0); } bool msm_dp_wide_bus_available(const struct msm_dp *dp_display) @@ -1771,3 +1780,41 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge, dp_display->dp_mode.h_active_low = !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC); } + +void dp_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge); + struct msm_dp *dp_display = dp_bridge->dp_display; + + dp_display->internal_hpd = true; +} + +void dp_bridge_hpd_disable(struct drm_bridge *bridge) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge); + struct msm_dp *dp_display = dp_bridge->dp_display; + + dp_display->internal_hpd = false; +} + +void dp_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status) +{ + struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge); + struct msm_dp *dp_display = dp_bridge->dp_display; + struct dp_display_private *dp = container_of(dp_display, struct dp_display_private, dp_display); + + /* Without next_bridge interrupts are handled by the DP core directly */ + if (dp_display->internal_hpd) + return; + + if (!dp->core_initialized) { + drm_dbg_dp(dp->drm_dev, "not initialized\n"); + return; + } + + if (!dp_display->is_connected && status == connector_status_connected) + dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0); + else if (dp_display->is_connected && status == connector_status_disconnected) + dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0); +} diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index dcedf021f7fe..371337d0fae2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -21,6 +21,7 @@ struct msm_dp { bool power_on; unsigned int connector_type; bool is_edp; + bool internal_hpd; hdmi_codec_plugged_cb plugged_cb; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 6db82f9b03af..275370f21115 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -102,6 +102,9 @@ static const struct drm_bridge_funcs dp_bridge_ops = { .get_modes = dp_bridge_get_modes, .detect = dp_bridge_detect, .atomic_check = dp_bridge_atomic_check, + .hpd_enable = dp_bridge_hpd_enable, + .hpd_disable = dp_bridge_hpd_disable, + .hpd_notify = dp_bridge_hpd_notify, }; struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 82035dbb0578..250f7c66201f 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -32,5 +32,9 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge, void dp_bridge_mode_set(struct drm_bridge *drm_bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode); +void dp_bridge_hpd_enable(struct drm_bridge *bridge); +void dp_bridge_hpd_disable(struct drm_bridge *bridge); +void dp_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status); #endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 5149cebc93f6..1800d8963f8a 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -75,12 +75,13 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel) link_info->rate = drm_dp_bw_code_to_link_rate(dpcd[DP_MAX_LINK_RATE]); link_info->num_lanes = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + /* Limit data lanes from data-lanes of endpoint property of dtsi */ if (link_info->num_lanes > dp_panel->max_dp_lanes) link_info->num_lanes = dp_panel->max_dp_lanes; - /* Limit support upto HBR2 until HBR3 support is added */ - if (link_info->rate >= (drm_dp_bw_code_to_link_rate(DP_LINK_BW_5_4))) - link_info->rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_5_4); + /* Limit link rate from link-frequencies of endpoint property of dtsi */ + if (link_info->rate > dp_panel->max_dp_link_rate) + link_info->rate = dp_panel->max_dp_link_rate; drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor); drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate); diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index d861197ac1c8..f04d0210b5cd 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -50,6 +50,7 @@ struct dp_panel { u32 vic; u32 max_dp_lanes; + u32 max_dp_link_rate; u32 max_bw_code; }; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index dcbe893d66d7..7032dcc8842b 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -91,19 +91,53 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) return 0; } +static u32 dp_parser_link_frequencies(struct device_node *of_node) +{ + struct device_node *endpoint; + u64 frequency = 0; + int cnt; + + endpoint = of_graph_get_endpoint_by_regs(of_node, 1, 0); /* port@1 */ + if (!endpoint) + return 0; + + cnt = of_property_count_u64_elems(endpoint, "link-frequencies"); + + if (cnt > 0) + of_property_read_u64_index(endpoint, "link-frequencies", + cnt - 1, &frequency); + of_node_put(endpoint); + + do_div(frequency, + 10 * /* from symbol rate to link rate */ + 1000); /* kbytes */ + + return frequency; +} + static int dp_parser_misc(struct dp_parser *parser) { struct device_node *of_node = parser->pdev->dev.of_node; - int len; - - len = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); - if (len < 0) { - DRM_WARN("Invalid property \"data-lanes\", default max DP lanes = %d\n", - DP_MAX_NUM_DP_LANES); - len = DP_MAX_NUM_DP_LANES; + int cnt; + + /* + * data-lanes is the property of dp_out endpoint + */ + cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES); + if (cnt < 0) { + /* legacy code, data-lanes is the property of mdss_dp node */ + cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); } - parser->max_dp_lanes = len; + if (cnt > 0) + parser->max_dp_lanes = cnt; + else + parser->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */ + + parser->max_dp_link_rate = dp_parser_link_frequencies(of_node); + if (!parser->max_dp_link_rate) + parser->max_dp_link_rate = DP_LINK_RATE_HBR2; + return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index d30ab773db46..1f068626d445 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -15,6 +15,7 @@ #define DP_LABEL "MDSS DP DISPLAY" #define DP_MAX_PIXEL_CLK_KHZ 675000 #define DP_MAX_NUM_DP_LANES 4 +#define DP_LINK_RATE_HBR2 540000 /* kbytes */ enum dp_pm_type { DP_CORE_PM, @@ -119,6 +120,7 @@ struct dp_parser { struct dp_io io; struct dp_display_data disp_data; u32 max_dp_lanes; + u32 max_dp_link_rate; struct drm_bridge *next_bridge; int (*parse)(struct dp_parser *parser); diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 2a96b4fe7839..bd3763a5d723 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -118,6 +118,8 @@ int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host); int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_6g(struct msm_dsi_host *msm_host); void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host); +unsigned long dsi_byte_clk_get_rate(struct mipi_dsi_host *host, bool is_bonded_dsi, + const struct drm_display_mode *mode); int dsi_tx_buf_alloc_6g(struct msm_dsi_host *msm_host, int size); int dsi_tx_buf_alloc_v2(struct msm_dsi_host *msm_host, int size); void *dsi_tx_buf_get_6g(struct msm_dsi_host *msm_host); @@ -139,6 +141,7 @@ struct msm_dsi_phy_shared_timings { u32 clk_post; u32 clk_pre; bool clk_pre_inc_by_2; + bool byte_intf_clk_div_2; }; struct msm_dsi_phy_clk_request { diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index 7e97c239ed48..6d21f0b33411 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -181,6 +181,20 @@ static const struct msm_dsi_config sdm845_dsi_cfg = { .num_dsi = 2, }; +static const struct regulator_bulk_data sm8550_dsi_regulators[] = { + { .supply = "vdda", .init_load_uA = 16800 }, /* 1.2 V */ +}; + +static const struct msm_dsi_config sm8550_dsi_cfg = { + .io_offset = DSI_6G_REG_SHIFT, + .regulator_data = sm8550_dsi_regulators, + .num_regulators = ARRAY_SIZE(sm8550_dsi_regulators), + .bus_clk_names = dsi_sdm845_bus_clk_names, + .num_bus_clks = ARRAY_SIZE(dsi_sdm845_bus_clk_names), + .io_start = { 0xae94000, 0xae96000 }, + .num_dsi = 2, +}; + static const struct regulator_bulk_data sc7180_dsi_regulators[] = { { .supply = "vdda", .init_load_uA = 21800 }, /* 1.2 V */ }; @@ -209,8 +223,8 @@ static const struct msm_dsi_config sc7280_dsi_cfg = { .num_regulators = ARRAY_SIZE(sc7280_dsi_regulators), .bus_clk_names = dsi_sc7280_bus_clk_names, .num_bus_clks = ARRAY_SIZE(dsi_sc7280_bus_clk_names), - .io_start = { 0xae94000 }, - .num_dsi = 1, + .io_start = { 0xae94000, 0xae96000 }, + .num_dsi = 2, }; static const char * const dsi_qcm2290_bus_clk_names[] = { @@ -300,6 +314,10 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = { &sc7180_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_0, &sc7280_dsi_cfg, &msm_dsi_6g_v2_host_ops}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_6_0, + &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, + {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_7_0, + &sm8550_dsi_cfg, &msm_dsi_6g_v2_host_ops}, }; const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor) diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h index 8f04e685a74e..44be4a88aa83 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -25,6 +25,8 @@ #define MSM_DSI_6G_VER_MINOR_V2_4_0 0x20040000 #define MSM_DSI_6G_VER_MINOR_V2_4_1 0x20040001 #define MSM_DSI_6G_VER_MINOR_V2_5_0 0x20050000 +#define MSM_DSI_6G_VER_MINOR_V2_6_0 0x20060000 +#define MSM_DSI_6G_VER_MINOR_V2_7_0 0x20070000 #define MSM_DSI_V2_VER_MINOR_8064 0x0 diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 89aadd3b3202..18fa30e1e858 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -122,6 +122,7 @@ struct msm_dsi_host { struct clk *byte_intf_clk; unsigned long byte_clk_rate; + unsigned long byte_intf_clk_rate; unsigned long pixel_clk_rate; unsigned long esc_clk_rate; @@ -398,7 +399,6 @@ int msm_dsi_runtime_resume(struct device *dev) int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) { - unsigned long byte_intf_rate; int ret; DBG("Set clk rates: pclk=%d, byteclk=%lu", @@ -418,13 +418,7 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) } if (msm_host->byte_intf_clk) { - /* For CPHY, byte_intf_clk is same as byte_clk */ - if (msm_host->cphy_mode) - byte_intf_rate = msm_host->byte_clk_rate; - else - byte_intf_rate = msm_host->byte_clk_rate / 2; - - ret = clk_set_rate(msm_host->byte_intf_clk, byte_intf_rate); + ret = clk_set_rate(msm_host->byte_intf_clk, msm_host->byte_intf_clk_rate); if (ret) { pr_err("%s: Failed to set rate byte intf clk, %d\n", __func__, ret); @@ -570,9 +564,8 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->byte_clk); } -static unsigned long dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bonded_dsi) +static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode, bool is_bonded_dsi) { - struct drm_display_mode *mode = msm_host->mode; unsigned long pclk_rate; pclk_rate = mode->clock * 1000; @@ -589,11 +582,13 @@ static unsigned long dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bo return pclk_rate; } -static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) +unsigned long dsi_byte_clk_get_rate(struct mipi_dsi_host *host, bool is_bonded_dsi, + const struct drm_display_mode *mode) { + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); u8 lanes = msm_host->lanes; u32 bpp = dsi_get_bpp(msm_host->format); - unsigned long pclk_rate = dsi_get_pclk_rate(msm_host, is_bonded_dsi); + unsigned long pclk_rate = dsi_get_pclk_rate(mode, is_bonded_dsi); u64 pclk_bpp = (u64)pclk_rate * bpp; if (lanes == 0) { @@ -607,8 +602,14 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) else do_div(pclk_bpp, (8 * lanes)); - msm_host->pixel_clk_rate = pclk_rate; - msm_host->byte_clk_rate = pclk_bpp; + return pclk_bpp; +} + +static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) +{ + msm_host->pixel_clk_rate = dsi_get_pclk_rate(msm_host->mode, is_bonded_dsi); + msm_host->byte_clk_rate = dsi_byte_clk_get_rate(&msm_host->base, is_bonded_dsi, + msm_host->mode); DBG("pclk=%lu, bclk=%lu", msm_host->pixel_clk_rate, msm_host->byte_clk_rate); @@ -636,7 +637,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi) dsi_calc_pclk(msm_host, is_bonded_dsi); - pclk_bpp = (u64)dsi_get_pclk_rate(msm_host, is_bonded_dsi) * bpp; + pclk_bpp = (u64)dsi_get_pclk_rate(msm_host->mode, is_bonded_dsi) * bpp; do_div(pclk_bpp, 8); msm_host->src_clk_rate = pclk_bpp; @@ -853,11 +854,12 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod */ slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width); - /* If slice_per_pkt is greater than slice_per_intf + /* + * If slice_count is greater than slice_per_intf * then default to 1. This can happen during partial * update. */ - if (slice_per_intf > dsc->slice_count) + if (dsc->slice_count > slice_per_intf) dsc->slice_count = 1; total_bytes_per_intf = dsc->slice_chunk_size * slice_per_intf; @@ -987,7 +989,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) if (!msm_host->dsc) wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1; else - wc = mode->hdisplay / 2 + 1; + wc = msm_host->dsc->slice_chunk_size * msm_host->dsc->slice_count + 1; dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) | @@ -1883,8 +1885,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); if (!msm_host) { - ret = -ENOMEM; - goto fail; + return -ENOMEM; } msm_host->pdev = pdev; @@ -1893,31 +1894,28 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) ret = dsi_host_parse_dt(msm_host); if (ret) { pr_err("%s: failed to parse dt\n", __func__); - goto fail; + return ret; } msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", &msm_host->ctrl_size); if (IS_ERR(msm_host->ctrl_base)) { pr_err("%s: unable to map Dsi ctrl base\n", __func__); - ret = PTR_ERR(msm_host->ctrl_base); - goto fail; + return PTR_ERR(msm_host->ctrl_base); } pm_runtime_enable(&pdev->dev); msm_host->cfg_hnd = dsi_get_config(msm_host); if (!msm_host->cfg_hnd) { - ret = -EINVAL; pr_err("%s: get config failed\n", __func__); - goto fail; + return -EINVAL; } cfg = msm_host->cfg_hnd->cfg; msm_host->id = dsi_host_get_id(msm_host); if (msm_host->id < 0) { - ret = msm_host->id; pr_err("%s: unable to identify DSI host index\n", __func__); - goto fail; + return msm_host->id; } /* fixup base address by io offset */ @@ -1927,19 +1925,18 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) cfg->regulator_data, &msm_host->supplies); if (ret) - goto fail; + return ret; ret = dsi_clk_init(msm_host); if (ret) { pr_err("%s: unable to initialize dsi clks\n", __func__); - goto fail; + return ret; } msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL); if (!msm_host->rx_buf) { - ret = -ENOMEM; pr_err("%s: alloc rx temp buf failed\n", __func__); - goto fail; + return -ENOMEM; } ret = devm_pm_opp_set_clkname(&pdev->dev, "byte"); @@ -1977,15 +1974,15 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) /* setup workqueue */ msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); + if (!msm_host->workqueue) + return -ENOMEM; + INIT_WORK(&msm_host->err_work, dsi_err_worker); msm_dsi->id = msm_host->id; DBG("Dsi Host %d initialized", msm_host->id); return 0; - -fail: - return ret; } void msm_dsi_host_destroy(struct mipi_dsi_host *host) @@ -2391,6 +2388,10 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, goto unlock_ret; } + msm_host->byte_intf_clk_rate = msm_host->byte_clk_rate; + if (phy_shared_timings->byte_intf_clk_div_2) + msm_host->byte_intf_clk_rate /= 2; + msm_dsi_sfpb_config(msm_host, true); ret = regulator_bulk_enable(msm_host->cfg_hnd->cfg->num_regulators, diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 3a1417397283..1bbac72dad35 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -450,6 +450,26 @@ static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge, int id = dsi_mgr_bridge_get_id(bridge); struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct mipi_dsi_host *host = msm_dsi->host; + struct platform_device *pdev = msm_dsi->pdev; + struct dev_pm_opp *opp; + unsigned long byte_clk_rate; + + byte_clk_rate = dsi_byte_clk_get_rate(host, IS_BONDED_DSI(), mode); + + opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &byte_clk_rate); + if (!IS_ERR(opp)) { + dev_pm_opp_put(opp); + } else if (PTR_ERR(opp) == -ERANGE) { + /* + * An empty table is created by devm_pm_opp_set_clkname() even + * if there is none. Thus find_freq_ceil will still return + * -ERANGE in such case. + */ + if (dev_pm_opp_get_opp_count(&pdev->dev) != 0) + return MODE_CLOCK_RANGE; + } else { + return MODE_ERROR; + } return msm_dsi_host_check_dsc(host, mode); } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index ee6051367679..bb09cbe8ff86 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -350,6 +350,8 @@ int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing, timing->shared_timings.clk_pre_inc_by_2 = 0; } + timing->shared_timings.byte_intf_clk_div_2 = true; + timing->ta_go = 3; timing->ta_sure = 0; timing->ta_get = 4; @@ -454,6 +456,8 @@ int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing, tmax = 255; timing->shared_timings.clk_pre = DIV_ROUND_UP((tmax - tmin) * 125, 10000) + tmin; + timing->shared_timings.byte_intf_clk_div_2 = true; + DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d", timing->shared_timings.clk_pre, timing->shared_timings.clk_post, timing->clk_zero, timing->clk_trail, timing->clk_prepare, timing->hs_exit, @@ -569,6 +573,14 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_7nm_8150_cfgs }, { .compatible = "qcom,sc7280-dsi-phy-7nm", .data = &dsi_phy_7nm_7280_cfgs }, + { .compatible = "qcom,sm6375-dsi-phy-7nm", + .data = &dsi_phy_7nm_6375_cfgs }, + { .compatible = "qcom,sm8350-dsi-phy-5nm", + .data = &dsi_phy_5nm_8350_cfgs }, + { .compatible = "qcom,sm8450-dsi-phy-5nm", + .data = &dsi_phy_5nm_8450_cfgs }, + { .compatible = "qcom,sm8550-dsi-phy-4nm", + .data = &dsi_phy_4nm_8550_cfgs }, #endif {} }; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index 1096afedd616..7137a17ae523 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -55,8 +55,12 @@ extern const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_7nm_6375_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs; struct msm_dsi_dphy_timing { u32 clk_zero; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 9e7fa7d88ead..3b1ed02f644d 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -39,8 +39,16 @@ #define VCO_REF_CLK_RATE 19200000 #define FRAC_BITS 18 +/* Hardware is pre V4.1 */ +#define DSI_PHY_7NM_QUIRK_PRE_V4_1 BIT(0) /* Hardware is V4.1 */ -#define DSI_PHY_7NM_QUIRK_V4_1 BIT(0) +#define DSI_PHY_7NM_QUIRK_V4_1 BIT(1) +/* Hardware is V4.2 */ +#define DSI_PHY_7NM_QUIRK_V4_2 BIT(2) +/* Hardware is V4.3 */ +#define DSI_PHY_7NM_QUIRK_V4_3 BIT(3) +/* Hardware is V5.2 */ +#define DSI_PHY_7NM_QUIRK_V5_2 BIT(4) struct dsi_pll_config { bool enable_ssc; @@ -116,16 +124,27 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config dec_multiple = div_u64(pll_freq * multiplier, divider); dec = div_u64_rem(dec_multiple, multiplier, &frac); - if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1)) + if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) config->pll_clock_inverters = 0x28; - else if (pll_freq <= 1000000000ULL) - config->pll_clock_inverters = 0xa0; - else if (pll_freq <= 2500000000ULL) - config->pll_clock_inverters = 0x20; - else if (pll_freq <= 3020000000ULL) - config->pll_clock_inverters = 0x00; - else - config->pll_clock_inverters = 0x40; + else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + if (pll_freq <= 1300000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq <= 2500000000ULL) + config->pll_clock_inverters = 0x20; + else if (pll_freq <= 4000000000ULL) + config->pll_clock_inverters = 0x00; + else + config->pll_clock_inverters = 0x40; + } else { + if (pll_freq <= 1000000000ULL) + config->pll_clock_inverters = 0xa0; + else if (pll_freq <= 2500000000ULL) + config->pll_clock_inverters = 0x20; + else if (pll_freq <= 3020000000ULL) + config->pll_clock_inverters = 0x00; + else + config->pll_clock_inverters = 0x40; + } config->decimal_div_start = dec; config->frac_div_start = frac; @@ -197,16 +216,32 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll) void __iomem *base = pll->phy->pll_base; u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00; - if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { + if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)) if (pll->vco_current_rate >= 3100000000ULL) analog_controls_five_1 = 0x03; + if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { if (pll->vco_current_rate < 1520000000ULL) vco_config_1 = 0x08; else if (pll->vco_current_rate < 2990000000ULL) vco_config_1 = 0x01; } + if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_2) || + (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3)) { + if (pll->vco_current_rate < 1520000000ULL) + vco_config_1 = 0x08; + else if (pll->vco_current_rate >= 2990000000ULL) + vco_config_1 = 0x01; + } + + if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + if (pll->vco_current_rate < 1557000000ULL) + vco_config_1 = 0x08; + else + vco_config_1 = 0x01; + } + dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1, analog_controls_five_1); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1); @@ -231,9 +266,9 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll) dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a); dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_IFILT, - pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1 ? 0x3f : 0x22); + !(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) ? 0x3f : 0x22); - if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { + if (!(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)) { dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22); if (pll->slave) dsi_phy_write(pll->slave->phy->pll_base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22); @@ -788,7 +823,7 @@ static void dsi_phy_hw_v4_0_lane_settings(struct msm_dsi_phy *phy) const u8 *tx_dctrl = tx_dctrl_0; void __iomem *lane_base = phy->lane_base; - if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) + if (!(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)) tx_dctrl = tx_dctrl_1; /* Strength ctrl settings */ @@ -844,6 +879,13 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, if (dsi_phy_hw_v4_0_is_pll_on(phy)) pr_warn("PLL turned on before configuring PHY\n"); + /* Request for REFGEN READY */ + if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + dsi_phy_write(phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10, 0x1); + udelay(500); + } + /* wait for REFGEN READY */ ret = readl_poll_timeout_atomic(base + REG_DSI_7nm_PHY_CMN_PHY_STATUS, status, (status & BIT(0)), @@ -858,23 +900,64 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, /* Alter PHY configurations if data rate less than 1.5GHZ*/ less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000); - if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { + glbl_str_swi_cal_sel_ctrl = 0x00; + if (phy->cphy_mode) { + vreg_ctrl_0 = 0x51; + vreg_ctrl_1 = 0x55; + glbl_hstx_str_ctrl_0 = 0x00; + glbl_pemph_ctrl_0 = 0x11; + lane_ctrl0 = 0x17; + } else { vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52; + vreg_ctrl_1 = 0x5c; + glbl_hstx_str_ctrl_0 = 0x88; + glbl_pemph_ctrl_0 = 0x00; + lane_ctrl0 = 0x1f; + } + + if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { if (phy->cphy_mode) { + vreg_ctrl_0 = 0x45; + vreg_ctrl_1 = 0x45; + glbl_rescode_top_ctrl = 0x00; + glbl_rescode_bot_ctrl = 0x00; + } else { + vreg_ctrl_0 = 0x44; + vreg_ctrl_1 = 0x19; + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3c : 0x03; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x3c; + } + } else if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3)) { + if (phy->cphy_mode) { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x01; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x3b; + } else { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x01; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x39; + } + } else if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_2) { + if (phy->cphy_mode) { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x01; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x3b; + } else { + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3c : 0x00; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x39; + } + } else if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) { + if (phy->cphy_mode) { + glbl_hstx_str_ctrl_0 = 0x88; glbl_rescode_top_ctrl = 0x00; glbl_rescode_bot_ctrl = 0x3c; } else { glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; } - glbl_str_swi_cal_sel_ctrl = 0x00; - glbl_hstx_str_ctrl_0 = 0x88; } else { - vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59; if (phy->cphy_mode) { glbl_str_swi_cal_sel_ctrl = 0x03; glbl_hstx_str_ctrl_0 = 0x66; } else { + vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59; glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; } @@ -882,17 +965,6 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, glbl_rescode_bot_ctrl = 0x3c; } - if (phy->cphy_mode) { - vreg_ctrl_0 = 0x51; - vreg_ctrl_1 = 0x55; - glbl_pemph_ctrl_0 = 0x11; - lane_ctrl0 = 0x17; - } else { - vreg_ctrl_1 = 0x5c; - glbl_pemph_ctrl_0 = 0x00; - lane_ctrl0 = 0x1f; - } - /* de-assert digital and pll power down */ data = BIT(6) | BIT(5); dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data); @@ -904,9 +976,8 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0x00); /* program CMN_CTRL_4 for minor_ver 2 chipsets*/ - data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0); - data = data & (0xf0); - if (data == 0x20) + if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || + (dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20) dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_4, 0x04); /* Configure PHY lane swap (TODO: we need to calculate this) */ @@ -1017,6 +1088,16 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) pr_warn("Turning OFF PHY while PLL is on\n"); dsi_phy_hw_v4_0_config_lpcdrx(phy, false); + + /* Turn off REFGEN Vote */ + if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || + (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10, 0x0); + wmb(); + /* Delay to ensure HW removes vote before PHY shut down */ + udelay(2); + } + data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_CTRL_0); /* disable all lanes */ @@ -1040,6 +1121,14 @@ static const struct regulator_bulk_data dsi_phy_7nm_37750uA_regulators[] = { { .supply = "vdds", .init_load_uA = 37550 }, }; +static const struct regulator_bulk_data dsi_phy_7nm_97800uA_regulators[] = { + { .supply = "vdds", .init_load_uA = 97800 }, +}; + +static const struct regulator_bulk_data dsi_phy_7nm_98400uA_regulators[] = { + { .supply = "vdds", .init_load_uA = 98400 }, +}; + const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { .has_phy_lane = true, .regulator_data = dsi_phy_7nm_36mA_regulators, @@ -1063,6 +1152,26 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { .quirks = DSI_PHY_7NM_QUIRK_V4_1, }; +const struct msm_dsi_phy_cfg dsi_phy_7nm_6375_cfgs = { + .has_phy_lane = true, + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000ULL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0x5e94400 }, + .num_dsi_phy = 1, + .quirks = DSI_PHY_7NM_QUIRK_V4_1, +}; + const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { .has_phy_lane = true, .regulator_data = dsi_phy_7nm_36mA_regulators, @@ -1079,6 +1188,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { .max_pll_rate = 3500000000UL, .io_start = { 0xae94400, 0xae96400 }, .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_PRE_V4_1, }; const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = { @@ -1102,3 +1212,72 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = { .num_dsi_phy = 1, .quirks = DSI_PHY_7NM_QUIRK_V4_1, }; + +const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_37750uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_37750uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae94400, 0xae96400 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V4_2, +}; + +const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_97800uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_97800uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae94400, 0xae96400 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V4_3, +}; + +const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = { + .has_phy_lane = true, + .regulator_data = dsi_phy_7nm_98400uA_regulators, + .num_regulators = ARRAY_SIZE(dsi_phy_7nm_98400uA_regulators), + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .pll_init = dsi_pll_7nm_init, + .save_pll_state = dsi_7nm_pll_save_state, + .restore_pll_state = dsi_7nm_pll_restore_state, + .set_continuous_clock = dsi_7nm_set_continuous_clock, + }, + .min_pll_rate = 600000000UL, +#ifdef CONFIG_64BIT + .max_pll_rate = 5000000000UL, +#else + .max_pll_rate = ULONG_MAX, +#endif + .io_start = { 0xae95000, 0xae97000 }, + .num_dsi_phy = 2, + .quirks = DSI_PHY_7NM_QUIRK_V5_2, +}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index f1f01db699d3..3132105a2a43 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -120,6 +120,10 @@ static int msm_hdmi_init(struct hdmi *hdmi) int ret; hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); + if (!hdmi->workq) { + ret = -ENOMEM; + goto fail; + } hdmi->i2c = msm_hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c index be4b0b67e797..cb35a297afbd 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c @@ -406,14 +406,14 @@ static const struct clk_ops hdmi_pll_ops = { .set_rate = hdmi_pll_set_rate, }; -static const char * const hdmi_pll_parents[] = { - "pxo", +static const struct clk_parent_data hdmi_pll_parents[] = { + { .fw_name = "pxo", .name = "pxo_board" }, }; static struct clk_init_data pll_init = { .name = "hdmi_pll", .ops = &hdmi_pll_ops, - .parent_names = hdmi_pll_parents, + .parent_data = hdmi_pll_parents, .num_parents = ARRAY_SIZE(hdmi_pll_parents), .flags = CLK_IGNORE_UNUSED, }; @@ -422,8 +422,7 @@ int msm_hdmi_pll_8960_init(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct hdmi_pll_8960 *pll; - struct clk *clk; - int i; + int i, ret; /* sanity check: */ for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++) @@ -443,10 +442,16 @@ int msm_hdmi_pll_8960_init(struct platform_device *pdev) pll->pdev = pdev; pll->clk_hw.init = &pll_init; - clk = devm_clk_register(dev, &pll->clk_hw); - if (IS_ERR(clk)) { + ret = devm_clk_hw_register(dev, &pll->clk_hw); + if (ret < 0) { DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return -EINVAL; + return ret; + } + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw); + if (ret) { + DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret); + return ret; } return 0; diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index 95f4374ae21c..d6ecff0ab618 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -305,6 +305,7 @@ void msm_debugfs_init(struct drm_minor *minor) { struct drm_device *dev = minor->dev; struct msm_drm_private *priv = dev->dev_private; + struct dentry *gpu_devfreq; drm_debugfs_create_files(msm_debugfs_list, ARRAY_SIZE(msm_debugfs_list), @@ -325,6 +326,17 @@ void msm_debugfs_init(struct drm_minor *minor) debugfs_create_file("shrink", S_IRWXU, minor->debugfs_root, dev, &shrink_fops); + gpu_devfreq = debugfs_create_dir("devfreq", minor->debugfs_root); + + debugfs_create_bool("idle_clamp",0600, gpu_devfreq, + &priv->gpu_clamp_to_idle); + + debugfs_create_u32("upthreshold",0600, gpu_devfreq, + &priv->gpu_devfreq_config.upthreshold); + + debugfs_create_u32("downdifferential",0600, gpu_devfreq, + &priv->gpu_devfreq_config.downdifferential); + if (priv->kms && priv->kms->funcs->debugfs_init) priv->kms->funcs->debugfs_init(priv->kms, minor); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 45e81eb148a8..aca48c868c14 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -45,9 +45,10 @@ * - 1.7.0 - Add MSM_PARAM_SUSPENDS to access suspend count * - 1.8.0 - Add MSM_BO_CACHED_COHERENT for supported GPUs (a6xx) * - 1.9.0 - Add MSM_SUBMIT_FENCE_SN_IN + * - 1.10.0 - Add MSM_SUBMIT_BO_NO_IMPLICIT */ #define MSM_VERSION_MAJOR 1 -#define MSM_VERSION_MINOR 9 +#define MSM_VERSION_MINOR 10 #define MSM_VERSION_PATCHLEVEL 0 static const struct drm_mode_config_funcs mode_config_funcs = { @@ -149,6 +150,9 @@ static void msm_irq_uninstall(struct drm_device *dev) struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; + if (!priv->kms) + return; + kms->funcs->irq_uninstall(kms); if (kms->irq_requested) free_irq(kms->irq, dev); @@ -266,8 +270,6 @@ static int msm_drm_uninit(struct device *dev) component_unbind_all(dev, ddev); ddev->dev_private = NULL; - drm_dev_put(ddev); - destroy_workqueue(priv->wq); return 0; @@ -418,6 +420,8 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) priv->dev = ddev; priv->wq = alloc_ordered_workqueue("msm", 0); + if (!priv->wq) + return -ENOMEM; INIT_LIST_HEAD(&priv->objects); mutex_init(&priv->obj_lock); @@ -440,12 +444,12 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) ret = msm_init_vram(ddev); if (ret) - return ret; + goto err_drm_dev_put; /* Bind all our sub-components: */ ret = component_bind_all(dev, ddev); if (ret) - return ret; + goto err_drm_dev_put; dma_set_max_seg_size(dev, UINT_MAX); @@ -491,7 +495,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) if (IS_ERR(priv->event_thread[i].worker)) { ret = PTR_ERR(priv->event_thread[i].worker); DRM_DEV_ERROR(dev, "failed to create crtc_event kthread\n"); - ret = PTR_ERR(priv->event_thread[i].worker); + priv->event_thread[i].worker = NULL; goto err_msm_uninit; } @@ -540,6 +544,8 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) err_msm_uninit: msm_drm_uninit(dev); +err_drm_dev_put: + drm_dev_put(ddev); return ret; } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d4e0ef608950..9f0c184b02a0 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/clk.h> #include <linux/cpufreq.h> +#include <linux/devfreq.h> #include <linux/module.h> #include <linux/component.h> #include <linux/platform_device.h> @@ -61,6 +62,7 @@ enum msm_dp_controller { MSM_DP_CONTROLLER_0, MSM_DP_CONTROLLER_1, MSM_DP_CONTROLLER_2, + MSM_DP_CONTROLLER_3, MSM_DP_CONTROLLER_COUNT, }; @@ -82,14 +84,12 @@ enum msm_event_wait { /** * struct msm_display_topology - defines a display topology pipeline * @num_lm: number of layer mixers used - * @num_enc: number of compression encoder blocks used * @num_intf: number of interfaces the panel is mounted on * @num_dspp: number of dspp blocks used * @num_dsc: number of Display Stream Compression (DSC) blocks used */ struct msm_display_topology { u32 num_lm; - u32 num_enc; u32 num_intf; u32 num_dspp; u32 num_dsc; @@ -233,6 +233,14 @@ struct msm_drm_private { */ unsigned int hangcheck_period; + /** gpu_devfreq_config: Devfreq tuning config for the GPU. */ + struct devfreq_simple_ondemand_data gpu_devfreq_config; + + /** + * gpu_clamp_to_idle: Enable clamping to idle freq when inactive + */ + bool gpu_clamp_to_idle; + /** * disable_err_irq: * diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index a47e5837c528..56641408ea74 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -22,7 +22,7 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, return ERR_PTR(-ENOMEM); fctx->dev = dev; - strncpy(fctx->name, name, sizeof(fctx->name)); + strscpy(fctx->name, name, sizeof(fctx->name)); fctx->context = dma_fence_context_alloc(1); fctx->index = index++; fctx->fenceptr = fenceptr; diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 73a2ca122c57..be4bf77103cd 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -209,6 +209,10 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit, goto out; } submit->cmd[i].relocs = kmalloc(sz, GFP_KERNEL); + if (!submit->cmd[i].relocs) { + ret = -ENOMEM; + goto out; + } ret = copy_from_user(submit->cmd[i].relocs, userptr, sz); if (ret) { ret = -EFAULT; @@ -334,9 +338,20 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit) if (ret) return ret; + /* If userspace has determined that explicit fencing is + * used, it can disable implicit sync on the entire + * submit: + */ if (no_implicit) continue; + /* Otherwise userspace can ask for implicit sync to be + * disabled on specific buffers. This is useful for internal + * usermode driver managed buffers, suballocation, etc. + */ + if (submit->bos[i].flags & MSM_SUBMIT_BO_NO_IMPLICIT) + continue; + ret = drm_sched_job_add_implicit_dependencies(&submit->base, obj, write); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 732295e25683..fc1c0d8611a8 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -109,11 +109,15 @@ struct msm_gpu_devfreq { struct mutex lock; /** - * idle_constraint: + * idle_freq: * - * A PM QoS constraint to limit max freq while the GPU is idle. + * Shadow frequency used while the GPU is idle. From the PoV of + * the devfreq governor, we are continuing to sample busyness and + * adjust frequency while the GPU is idle, but we use this shadow + * value as the GPU is actually clamped to minimum frequency while + * it is inactive. */ - struct dev_pm_qos_request idle_freq; + unsigned long idle_freq; /** * boost_constraint: @@ -135,8 +139,6 @@ struct msm_gpu_devfreq { /** idle_time: Time of last transition to idle: */ ktime_t idle_time; - struct devfreq_dev_status average_status; - /** * idle_work: * @@ -275,9 +277,6 @@ struct msm_gpu { struct msm_gpu_state *crashstate; - /* Enable clamping to idle freq when inactive: */ - bool clamp_to_idle; - /* True if the hardware supports expanded apriv (a650 and newer) */ bool hw_apriv; diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 85c443a37e4e..e27dbf12b5e8 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -33,6 +33,16 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp)); + /* + * If the GPU is idle, devfreq is not aware, so just stash + * the new target freq (to use when we return to active) + */ + if (df->idle_freq) { + df->idle_freq = *freq; + dev_pm_opp_put(opp); + return 0; + } + if (gpu->funcs->gpu_set_freq) { mutex_lock(&df->lock); gpu->funcs->gpu_set_freq(gpu, opp, df->suspended); @@ -48,15 +58,26 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, static unsigned long get_freq(struct msm_gpu *gpu) { + struct msm_gpu_devfreq *df = &gpu->devfreq; + + /* + * If the GPU is idle, use the shadow/saved freq to avoid + * confusing devfreq (which is unaware that we are switching + * to lowest freq until the device is active again) + */ + if (df->idle_freq) + return df->idle_freq; + if (gpu->funcs->gpu_get_freq) return gpu->funcs->gpu_get_freq(gpu); return clk_get_rate(gpu->core_clk); } -static void get_raw_dev_status(struct msm_gpu *gpu, +static int msm_devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *status) { + struct msm_gpu *gpu = dev_to_gpu(dev); struct msm_gpu_devfreq *df = &gpu->devfreq; u64 busy_cycles, busy_time; unsigned long sample_rate; @@ -72,7 +93,7 @@ static void get_raw_dev_status(struct msm_gpu *gpu, if (df->suspended) { mutex_unlock(&df->lock); status->busy_time = 0; - return; + return 0; } busy_cycles = gpu->funcs->gpu_busy(gpu, &sample_rate); @@ -87,71 +108,6 @@ static void get_raw_dev_status(struct msm_gpu *gpu, busy_time = ~0LU; status->busy_time = busy_time; -} - -static void update_average_dev_status(struct msm_gpu *gpu, - const struct devfreq_dev_status *raw) -{ - struct msm_gpu_devfreq *df = &gpu->devfreq; - const u32 polling_ms = df->devfreq->profile->polling_ms; - const u32 max_history_ms = polling_ms * 11 / 10; - struct devfreq_dev_status *avg = &df->average_status; - u64 avg_freq; - - /* simple_ondemand governor interacts poorly with gpu->clamp_to_idle. - * When we enforce the constraint on idle, it calls get_dev_status - * which would normally reset the stats. When we remove the - * constraint on active, it calls get_dev_status again where busy_time - * would be 0. - * - * To remedy this, we always return the average load over the past - * polling_ms. - */ - - /* raw is longer than polling_ms or avg has no history */ - if (div_u64(raw->total_time, USEC_PER_MSEC) >= polling_ms || - !avg->total_time) { - *avg = *raw; - return; - } - - /* Truncate the oldest history first. - * - * Because we keep the history with a single devfreq_dev_status, - * rather than a list of devfreq_dev_status, we have to assume freq - * and load are the same over avg->total_time. We can scale down - * avg->busy_time and avg->total_time by the same factor to drop - * history. - */ - if (div_u64(avg->total_time + raw->total_time, USEC_PER_MSEC) >= - max_history_ms) { - const u32 new_total_time = polling_ms * USEC_PER_MSEC - - raw->total_time; - avg->busy_time = div_u64( - mul_u32_u32(avg->busy_time, new_total_time), - avg->total_time); - avg->total_time = new_total_time; - } - - /* compute the average freq over avg->total_time + raw->total_time */ - avg_freq = mul_u32_u32(avg->current_frequency, avg->total_time); - avg_freq += mul_u32_u32(raw->current_frequency, raw->total_time); - do_div(avg_freq, avg->total_time + raw->total_time); - - avg->current_frequency = avg_freq; - avg->busy_time += raw->busy_time; - avg->total_time += raw->total_time; -} - -static int msm_devfreq_get_dev_status(struct device *dev, - struct devfreq_dev_status *status) -{ - struct msm_gpu *gpu = dev_to_gpu(dev); - struct devfreq_dev_status raw; - - get_raw_dev_status(gpu, &raw); - update_average_dev_status(gpu, &raw); - *status = gpu->devfreq.average_status; return 0; } @@ -183,16 +139,23 @@ static bool has_devfreq(struct msm_gpu *gpu) void msm_devfreq_init(struct msm_gpu *gpu) { struct msm_gpu_devfreq *df = &gpu->devfreq; + struct msm_drm_private *priv = gpu->dev->dev_private; /* We need target support to do devfreq */ if (!gpu->funcs->gpu_busy) return; + /* + * Setup default values for simple_ondemand governor tuning. We + * want to throttle up at 50% load for the double-buffer case, + * where due to stalling waiting for vblank we could get stuck + * at (for ex) 30fps at 50% utilization. + */ + priv->gpu_devfreq_config.upthreshold = 50; + priv->gpu_devfreq_config.downdifferential = 10; + mutex_init(&df->lock); - dev_pm_qos_add_request(&gpu->pdev->dev, &df->idle_freq, - DEV_PM_QOS_MAX_FREQUENCY, - PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq, DEV_PM_QOS_MIN_FREQUENCY, 0); @@ -209,11 +172,10 @@ void msm_devfreq_init(struct msm_gpu *gpu) df->devfreq = devm_devfreq_add_device(&gpu->pdev->dev, &msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND, - NULL); + &priv->gpu_devfreq_config); if (IS_ERR(df->devfreq)) { DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n"); - dev_pm_qos_remove_request(&df->idle_freq); dev_pm_qos_remove_request(&df->boost_freq); df->devfreq = NULL; return; @@ -255,7 +217,6 @@ void msm_devfreq_cleanup(struct msm_gpu *gpu) devfreq_cooling_unregister(gpu->cooling); dev_pm_qos_remove_request(&df->boost_freq); - dev_pm_qos_remove_request(&df->idle_freq); } void msm_devfreq_resume(struct msm_gpu *gpu) @@ -328,6 +289,7 @@ void msm_devfreq_active(struct msm_gpu *gpu) { struct msm_gpu_devfreq *df = &gpu->devfreq; unsigned int idle_time; + unsigned long target_freq; if (!has_devfreq(gpu)) return; @@ -337,8 +299,28 @@ void msm_devfreq_active(struct msm_gpu *gpu) */ cancel_idle_work(df); + /* + * Hold devfreq lock to synchronize with get_dev_status()/ + * target() callbacks + */ + mutex_lock(&df->devfreq->lock); + + target_freq = df->idle_freq; + idle_time = ktime_to_ms(ktime_sub(ktime_get(), df->idle_time)); + df->idle_freq = 0; + + /* + * We could have become active again before the idle work had a + * chance to run, in which case the df->idle_freq would have + * still been zero. In this case, no need to change freq. + */ + if (target_freq) + msm_devfreq_target(&gpu->pdev->dev, &target_freq, 0); + + mutex_unlock(&df->devfreq->lock); + /* * If we've been idle for a significant fraction of a polling * interval, then we won't meet the threshold of busyness for @@ -347,9 +329,6 @@ void msm_devfreq_active(struct msm_gpu *gpu) if (idle_time > msm_devfreq_profile.polling_ms) { msm_devfreq_boost(gpu, 2); } - - dev_pm_qos_update_request(&df->idle_freq, - PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); } @@ -358,11 +337,24 @@ static void msm_devfreq_idle_work(struct kthread_work *work) struct msm_gpu_devfreq *df = container_of(work, struct msm_gpu_devfreq, idle_work.work); struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq); + struct msm_drm_private *priv = gpu->dev->dev_private; + unsigned long idle_freq, target_freq = 0; + + /* + * Hold devfreq lock to synchronize with get_dev_status()/ + * target() callbacks + */ + mutex_lock(&df->devfreq->lock); + + idle_freq = get_freq(gpu); + + if (priv->gpu_clamp_to_idle) + msm_devfreq_target(&gpu->pdev->dev, &target_freq, 0); df->idle_time = ktime_get(); + df->idle_freq = idle_freq; - if (gpu->clamp_to_idle) - dev_pm_qos_update_request(&df->idle_freq, 0); + mutex_unlock(&df->devfreq->lock); } void msm_devfreq_idle(struct msm_gpu *gpu) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 2527afef9c19..02646e4bb4cd 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -286,9 +286,21 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) /* UBWC_2_0 */ msm_mdss_setup_ubwc_dec_20(msm_mdss, 0x11f); break; + case DPU_HW_VER_700: + /* TODO: highest_bank_bit = 2 for LP_DDR4 */ + msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1); + break; case DPU_HW_VER_720: msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_3_0, 6, 1, 1, 1); break; + case DPU_HW_VER_800: + msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 2, 1); + break; + case DPU_HW_VER_810: + case DPU_HW_VER_900: + /* TODO: highest_bank_bit = 2 for LP_DDR4 */ + msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1); + break; } return ret; @@ -515,9 +527,13 @@ static const struct of_device_id mdss_dt_match[] = { { .compatible = "qcom,sc7180-mdss" }, { .compatible = "qcom,sc7280-mdss" }, { .compatible = "qcom,sc8180x-mdss" }, + { .compatible = "qcom,sc8280xp-mdss" }, { .compatible = "qcom,sm6115-mdss" }, { .compatible = "qcom,sm8150-mdss" }, { .compatible = "qcom,sm8250-mdss" }, + { .compatible = "qcom,sm8350-mdss" }, + { .compatible = "qcom,sm8450-mdss" }, + { .compatible = "qcom,sm8550-mdss" }, {} }; MODULE_DEVICE_TABLE(of, mdss_dt_match); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c index 439ef3073512..39eef3dce7c9 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -733,6 +733,7 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs, DRM_MODE_CONNECTOR_DSI); + ctx->panel.prepare_prev_first = true; drm_panel_add(&ctx->panel); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c index 9c3e76171759..46d6f4a87bf7 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c @@ -463,6 +463,7 @@ static int s6e63j0x03_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &s6e63j0x03_funcs, DRM_MODE_CONNECTOR_DSI); + ctx->panel.prepare_prev_first = true; ctx->bl_dev = backlight_device_register("s6e63j0x03", dev, ctx, &s6e63j0x03_bl_ops, NULL); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c index ebf4c2d39ea8..c51d07ec1529 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c @@ -1016,6 +1016,7 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &s6e8aa0_drm_funcs, DRM_MODE_CONNECTOR_DSI); + ctx->panel.prepare_prev_first = true; drm_panel_add(&ctx->panel); diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 0e4378420271..4e6ad6e122bc 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -906,6 +906,12 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched) spin_unlock(&sched->job_list_lock); + if (job) { + job->entity->elapsed_ns += ktime_to_ns( + ktime_sub(job->s_fence->finished.timestamp, + job->s_fence->scheduled.timestamp)); + } + return job; } |